ayatana-ido-0.10.1/AUTHORS0000644000000000000000000000235414471671403011731 0ustar Allan LeSage Allan LeSage Charles Kerr CI Train Bot Cody Russell David Barth Devendranath Thadi Didier Roche Jami Kettunen Jan Palus Jason Conti Javier Jardón Jeremy Bicha Karl Lattimer karl-qdh Ken VanDine Lars Uebernickel Lars Uebernickel Marco Trevisan (Treviño) Marco Trevisan (Treviño) Mathieu Trudel-Lapierre Michael Terry Michal Hruby Mike Gabriel Rico Tzschichholz Robert Ancell Robert Carr Robert Tari Sebastien Bacher Sylvain POULAIN Ted Gould Till Maas ayatana-ido-0.10.1/AUTHORS.Canonical0000644000000000000000000000004714471671403013614 0ustar Cody Russell ayatana-ido-0.10.1/.build.yml0000644000000000000000000000617414471671403012565 0ustar ########################################################## # THE FOLLOWING LINES IS USED BY docker-build ########################################################## requires: archlinux: - clang - gcc - git - startup-notification - which - cmake - cmake-extras - glib2 - gobject-introspection - gtk3 - gtk-doc - vala - lcov - gcovr debian: # Useful URL: https://salsa.debian.org/debian-ayatana-team/ayatana-ido - clang - clang-tools - cppcheck - git - cmake - cmake-extras - gobject-introspection - gtk-doc-tools - libgirepository1.0-dev - libglib2.0-dev - libgtest-dev - libgtk-3-dev - libx11-dev - libxi-dev - valac - lcov - gcovr - xauth - xvfb ubuntu: - clang - clang-tools - cppcheck - git - cmake - cmake-extras - gobject-introspection - gtk-doc-tools - libgirepository1.0-dev - libglib2.0-dev - libgtest-dev - libgtk-3-dev - libx11-dev - libxi-dev - valac - lcov - gcovr - xauth - xvfb variables: - 'CHECKERS=" -enable-checker deadcode.DeadStores -enable-checker alpha.deadcode.UnreachableCode -enable-checker alpha.core.CastSize -enable-checker alpha.core.CastToStruct -enable-checker alpha.core.IdenticalExpr -enable-checker alpha.core.SizeofPtr -enable-checker alpha.security.ArrayBoundV2 -enable-checker alpha.security.MallocOverflow -enable-checker alpha.security.ReturnPtrRange -enable-checker alpha.unix.SimpleStream -enable-checker alpha.unix.cstring.BufferOverlap -enable-checker alpha.unix.cstring.NotNullTerminated -enable-checker alpha.unix.cstring.OutOfBounds -enable-checker alpha.core.FixedAddr -enable-checker security.insecureAPI.strcpy"' build_scripts: - if [ ${DISTRO_NAME} == "debian" ];then - cppcheck --enable=warning,style,performance,portability,information,missingInclude . - fi - - if [ -e ./CMakeLists.txt ]; then - if [ ${DISTRO_NAME} == "debian" ] || [ ${DISTRO_NAME} == "ubuntu" ]; then - scan-build $CHECKERS cmake . -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_VERBOSE_MAKEFILE=ON -DENABLE_WERROR=ON -DENABLE_TESTS=ON - else - scan-build $CHECKERS cmake . -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_VERBOSE_MAKEFILE=ON -DENABLE_WERROR=ON - fi - else - exit 1 - fi - - if [ $CPU_COUNT -gt 1 ]; then - if [ ${DISTRO_NAME} == "debian" ];then - scan-build $CHECKERS --keep-cc --use-cc=clang --use-c++=clang++ -o html-report make -j $CPU_COUNT - make clean - fi - scan-build $CHECKERS --keep-cc -o html-report make -j $CPU_COUNT - else - if [ ${DISTRO_NAME} == "debian" ];then - scan-build $CHECKERS --keep-cc --use-cc=clang --use-c++=clang++ -o html-report make - make clean - fi - scan-build $CHECKERS --keep-cc -o html-report make - fi - XVFB_RUN="$(which xvfb-run || true)" - if [ ${DISTRO_NAME} == "debian" ] || [ ${DISTRO_NAME} == "ubuntu" ];then - if [ -e ./CMakeLists.txt ]; then - ${XVFB_RUN} make test - fi - fi ayatana-ido-0.10.1/ChangeLog0000644000000000000000000021752214471671403012440 0ustar 2023-08-24 Mike Gabriel * release 0.10.1 (HEAD -> main, tag: 0.10.1) * COPYING: Symlink to COPYING.GPL-3, the licensed used by the majority of code files. (c9bfd1b5) * Rename COPYING to COPYING.GPL-3 and use Debian's version of it. (cc276098) * COPYING files: Ship a copy of LGPL-2(+) and LGPL-3. Some code files in this project use either of those licenses. (b040a375) * COPYING.LGPL.2.1: Rename to COPYING.LGPL-2.1 (and use layout from Debian's LGPL-2.1 license file shipped in /usr/share/common-licenses/). (20d65627) * Merge branch 'tyll-executable_so' (39277de1) 2023-08-24 Till Maas * cmake: Install library as library (610ddb96) 2023-08-07 Mike Gabriel * Merge branch 'tari01-pr/no-hardcoded-icon-sizes' (b1998c6a) 2023-08-05 Robert Tari * Do not hardcode icon sizes (e487b162) * Fix possible memory leaks (ebb915b5) * src/idoalarmmenuitem.c: Do not free non memory-allocated variable (579cad6e) * src/idoplaybackmenuitem.c: Drop unused variable (c2bade07) * src/idoplaybackmenuitem.c: Fix undefined variable (be68b43c) 2023-06-09 Mike Gabriel * d/libayatana-ido3-0.4-0.symbols: Update symbols. (09c5052d) * d/changelog: amend revision (5263257c) * release 0.10.0 (75f61898) (tag: 0.10.0) 2023-05-05 Mike Gabriel * Merge branch 'tari01-pr/level-item' (e74e767a) 2023-04-04 Robert Tari * Add level menu item (876a9fa2) * CMakeLists.txt: Add threads fix for old CMake (fc636cea) 2023-05-05 Mike Gabriel * Merge branch 'tari01-pr/progress-item-rewrite' (c730328e) 2023-03-03 Robert Tari * src/idoprogressmenuitem.c: Rewrite to use icon, progress property and activation (1b164cf8) 2023-02-26 Mike Gabriel * Revert "cmake: Enable building tests by default" (f19a5f47) * debian/libayatana-ido3-0.4-0.symbols: Update symbols. (109100e2) * release 0.9.3 (10b05bdb) (tag: 0.9.3) * Merge branch 'JamiKettunen-modern-gtest' (62ec1cda) 2023-02-26 Jami Kettunen * cmake: Enable building tests by default (889c006f) * tests: Fix building against modern GTest (f692439d) 2022-09-05 Mike Gabriel * Merge branch 'tari01-pr/secondary-text-and-count' (4e047789) 2022-09-04 Robert Tari * src/idobasicmenuitem.c: Set secondary text and count with lozenge from menu model (7aa6323b) 2022-06-27 Mike Gabriel * .travis.yml: Add CI builds for Ubuntu 22.04. (10fde125) 2022-06-03 Mike Gabriel * release 0.9.2 (69ba03b9) (tag: 0.9.2) 2022-03-24 Mike Gabriel * Merge branch 'ricotz-main' (e56a633c) 2022-03-15 Rico Tzschichholz * vala: The name of the vapi should match the pkg-config name (2e1c0409) 2022-02-28 Mike Gabriel * Merge branch 'jpalus-link-libm' (d87cc103) 2022-02-19 Jan Palus * src/CMakeLists.txt: link libm for expf, pow and sinf (62f510e2) 2022-02-17 Mike Gabriel * release 0.9.1 (9e8a410f) (tag: 0.9.1) 2022-02-08 Robert Tari * .travis.yml: Run CI builds on Travis CI's Ubuntu focal base system + disable ppc64el builds (9c8dd710) 2022-01-27 Mike Gabriel * Merge branch 'tari01-pr/cleanup-compile-flags' (854485a8) 2022-01-14 Robert Tari * .build.yml: Drop extra compilation flags and build with -Werror (aaf337b8) * Clean up compilation flags (b6278e24) 2021-11-12 Mike Gabriel * Merge branch 'sunweaver-pr/ppc64le-alive-again' (b340930c) 2021-11-10 Mike Gabriel * .travis.yml: Re-enable ppc64le builds on Travis CI again. (f07e4bd2) * Merge branch 'tari01-pr/drop-scale-margin' (abcf34b1) 2021-11-05 Robert Tari * src/idoscalemenuitem.c: Drop hard-coded end-margin for the Scale Display Object (696edc3e) 2021-11-02 Mike Gabriel * release 0.9.0 (72d04c90) (tag: 0.9.0) * debian/control: ayatana-ido (esp. the shared library) breaks older ayatana-indicators-* versions that use IDOs. (929370bb) * debian/control: Drop B-D: mate-common. (ab857b2f) * debian/control: Bump Standards-Version: to 4.6.0. No changes needed. (1350ad88) 2021-10-26 Mike Gabriel * .build.yml: Drop autogen.sh support; Run unit tests in build_scripts: target. (9205e10e) * Revert ".build.yml: Drop autogen.sh support; Run unit tests in build_scripts: target." (e128c176) 2021-10-25 Mike Gabriel * .build.yml: Drop autogen.sh support; Run unit tests in build_scripts: target. (bde36171) 2021-10-20 Robert Tari * .travis.yml: Temporarily disable ppc64le builds (cb6e7423) 2021-10-18 Mike Gabriel * Merge branch 'tari01-pr/use-consistent-ido-names' (b26af470) 2021-09-20 Robert Tari * Use consistent Ayatana IDO names (caec51f5) * Merge branch 'pr/fix-unit-test-failure-on-ubuntu-20-04' (f0f879c6) * Fix unit test failure on Ubuntu 20.04 (24ee3d02) * Fix copyright headers (2c6a2669) 2021-09-02 Robert Tari * Fix Travis status image (2600470f) * Merge branch 'sunweaver-pr/ubuntu-CI-builds-run-unittests' (d08fc80c) 2021-08-28 Mike Gabriel * .travis.yml: Use Ayatana Indicators project's dev-scripts repo. (f16cedf9) 2021-09-02 Robert Tari * Merge branch 'sunweaver-pr/use-ayatana-indicators-dev-scripts' (f30a2b96) 2021-08-29 Mike Gabriel * .build.yml: Also run unit tests during CI builds against Ubuntu. (e4ce9964) 2021-08-28 Mike Gabriel * .travis.yml: Use Ayatana Indicators project's dev-scripts repo. (5b2b0168) 2021-08-10 Mike Gabriel * CMakeLists.txt: Add empty line below 'Options' comment. (8b37e2d5) * Merge branch 'tari01-pr/no-pie-only-in-tests' (0cff15b5) 2021-08-10 Robert Tari * Use -no-pie build flags for test only (95d2a880) 2021-08-10 Mike Gabriel * Merge branch 'tari01-pr/add-enable-werror-option' (b4927b12) 2021-08-09 Robert Tari * Add ENABLE_WERROR option (c68353a5) 2021-06-09 Mike Gabriel * Merge branch 'tari01-pr/cmake-install-full' (879e27ea) 2021-06-08 Robert Tari * src/CMakeLists.txt: Add missing target link libraries (48818026) 2021-06-09 Mike Gabriel * Merge branch 'tari01-pr/add-missing-target-libs' (473c7063) 2021-06-08 Robert Tari * data/libayatana-ido3-0.4.pc.in: Use CMAKE_INSTALL_FULL_*DIR locations (e2a30acb) * src/CMakeLists.txt: Add missing target link libraries (0dd15ce5) * Merge branch 'sunweaver-pr/conditional-build-of-GIR-and-VAPI' (54f11749) 2021-06-07 Mike Gabriel * src/CMakeLists.txt: Wrap GIR and VAPI related build instructions into if-clauses (that check, if INTROSPECTION_FOUND and VAPI_FOUND). (7f9c75d8) * Merge branch 'tari01-pr/relative-install-dirs' (f754c6a2) 2021-06-07 Robert Tari * Use CMAKE_INSTALL_FULL_*DIR variables for installation (10c3401d) 2021-06-07 Mike Gabriel * Merge branch 'tari01-pr/add-glib-2.0-to-pkgconfig' (215fbe41) 2021-06-04 Robert Tari * data/libayatana-ido3-0.4.pc.in: Add glib-2.0 dependency (91cb0ab4) 2021-06-07 Mike Gabriel * Merge branch 'tari01-pr/add-project-description' (942bdd59) 2021-06-01 Robert Tari * README.md: Add project description (30aa3c2b) 2021-05-25 Mike Gabriel * Merge branch 'tari01-pr/update-docs' (e11bf6e8) 2021-05-17 Robert Tari * Add documentation files (5dae59b3) * Merge branch 'trism/fix-removable-a11y' (e6a410de) 2021-05-04 Mike Gabriel * CMakeLists.txt: Move coverage report generation macro into basefolder's CMakeLists.txt file. (41d83490) 2021-05-11 Mike Gabriel * debian/control: Adjust versioned B-D on cmake (3.13 as stated in CMakeLists.txt). (287c8fc4) 2021-05-12 Robert Tari * Merge branch 'sunweaver-pr/fix-coverage-report' (8d2c0128) 2021-05-11 Mike Gabriel * debian/control: Adjust versioned B-D on cmake (3.13 as stated in CMakeLists.txt). (4dedcedf) 2021-05-03 Robert Tari * src/idolocationmenuitem.c: Fix deprecated g_time_zone_new warning. (ef73e1d3) 2021-05-04 Mike Gabriel * .travis.yml: Don't try running autotools based CI build. (80df555d) 2021-05-11 Mike Gabriel * debian/control: Adjust versioned B-D on cmake (3.13 as stated in CMakeLists.txt). (c158381d) 2021-05-09 Jason Conti * src/idoremovablemenuitem.c: replace grid with box to fix a11y (d6d68760) 2021-05-04 Mike Gabriel * Merge branch 'tari01-pr/fix-deprecation-warning' (9f2f8e9f) 2021-05-03 Robert Tari * src/idolocationmenuitem.c: Fix deprecated g_time_zone_new warning. (4f34f7b8) 2021-05-04 Mike Gabriel * .travis.yml: Don't try running autotools based CI build. (5663ffb1) * CMakeLists.txt: Move coverage report generation macro into basefolder's CMakeLists.txt file. (81db2957) 2021-05-03 Mike Gabriel * debian/libayatana-ido3-0.4-0.symbols: Add symbol 'ido_basic_menu_item_set_pixbuf' (coming with 0.8.3). (ccd08348) 2021-04-27 Mike Gabriel * .travis.yml: Temporarily disable ubuntu:rolling while the new distro version being bootstrapped by Canonical. (9c92d427) * Merge branch 'tari01-pr/add-appointment-icon' (12c8fa46) 2021-03-24 Robert Tari * Add us to the copyright headers (241bd377) * src/basicmenuitem.c: Add GdkPixbuf source support for the icon (386eaabc) * src/basicmenuitem.h: Add the ido_basic_menu_item_set_pixbuf function (aa242a51) * src/idoappointmentmenuitem.c: Contruct the basic menu item using the pixbuf property (f95ddece) * Whitespace fix (1158fdc8) 2021-04-21 Mike Gabriel * Merge branch 'tari01-pr/switch-to-cmake' (fcf633bd) 2021-04-21 Robert Tari * CMakeLists.txt: Drop duplicate status messages (3adf9ec3) * CMakeLists.txt: Fix typo (c75d5b57) 2021-04-20 Mike Gabriel * debian/: Adjust to build system switch-over to CMake. (6b4eb421) 2021-02-03 Robert Tari * src/idotimestampmenuitem.c: Whitespace fixes in copyright header. (d62ba3a0) * Drop local config.h includes. (2ebe5c8e) 2021-02-05 Robert Tari * Remove automake-related files (715feb6c) 2021-04-21 Mike Gabriel * tests/CMakeLists.txt: Unit tests may only run and build if shared library target has been built. (9ec937ca) * tests/CMakeLists.txt: Build unit tests with --no-pie CXXFLAG. (fd3931e5) 2021-04-20 Mike Gabriel * tests/: Port to using GMock cmake package from cmake-extras. (db3414f6) * example/CMakeLists.txt: The example/ folder requires the library to have been built. Fix parallel build issue with -DDISABLED_TESTS=OFF option. (42a5485d) * CMakeLists.txt: Drop duplicate ENABLE_COVERAGE_REPORT() macro call. (65f7c219) * CMakeLists.txt: Leave finding gtest.pc to GMock cmake module. (38e4b901) * CMakeLists.txt: Tolerate older versions of GLib-2.0 and GoogleTest. Support building on Debian 10. (bbe29018) * CMakeLists.txt: Let's tolerate CMake minimum version 3.13 (to support building against Debian 10). (f308bf10) 2021-04-21 Mike Gabriel * {tests/,}CMakeLists.txt: Add ENABLE_COVERAGE build option. (05732031) 2021-04-20 Mike Gabriel * CMakeLists.txt: Don't use variable name MAINTAINER_MODE (it is misleading), use ENABLE_TESTS and ENABLE_COVERAGE as options instead. (ab041b77) * src/CMakeLists.txt: Actively set --library-path for g-ir-scanner. (94e20a89) 2021-02-05 Robert Tari * Add CMakeLists.txt files. (9f96225d) 2021-04-20 Mike Gabriel * CMake: Add required .cmake includes (FindGObjectIntrospection, FindVala). (b74d4016) 2021-02-05 Robert Tari * Add data/libayatana-ido3-0.4.pc.in (e34245c3) 2021-04-21 Mike Gabriel * .build.yml: On Debian, actively enable unit tests when building with CMake. (34e808d3) * .build.yml: Don't fail on which's non-zero exit-code. (d5f56cd5) * .build.yml: Run unit tests in xvfb-run environment (if xvfb-run is $PATH). (656b45e6) * .build.yml: Test target with CMake is 'test', with autotools it is 'check'. (f1eeeb95) 2021-04-20 Mike Gabriel * .build.yml: No such Makefile target distcheck with CMake builds. (bde5cc1d) * .build.yml: Don't run cmake in Clang mode. Breaks GCC builds later on. (2502b951) * .travis.yml: Also run Travis CI builds against current Debian stable. (51c1bd8a) * .travis.yml: pip3-install wheel. Should resolve "error: invalid command 'bdist_wheel'" during installation of PyGithub. (9fe49e4d) * .build.yml: Drop echo statement. (5dc3ba64) * .build.yml: Don't confuse docker-build with unneeded colons (confuses YAML parser). (2a313fd8) * .build.yml: Re-add clang for archlinux and ubuntu (needed for scan-build command). (6973640c) * .build.yml: Add build requirements: gcovr, lcov. (7a84804f) * .build.yml: Additionall pull in cmake related packages. (75c827df) * .build.yml: Drop not-required build requirements. (5d258485) * .build.yml: Add CMake support. (cdf83990) * .build.yml: Drop fedora build target. (d622a631) * Travis-CI: temporarily disable archlinux:latest CI builds. (e3021e92) * Travis-CI: Also build against Ubuntu 20.04 (for Ubuntu Touch's sake). (3b3c77d5) * .build.yml: Try installing pacman to work-around missing /var/lib/pacman directory. (746f6cfb) * Travis-CI: Simplify CI scripts, drop fedora remnants, no gen-index script needed. (020f5baa) * .travis.yml: Drop deploy: section. (58448311) * TRAVIS: Disable Fedora CI builds for now (and thus, cppcheck). (96c2ddba) 2021-01-25 Mike Gabriel * release 0.8.2 (e4bf36c6) (tag: 0.8.2) * debian/*: Update from official Debian packaging. (9f276a06) 2020-12-22 Robert Tari * Merge branch 'sunweaver-pr/travis-builds-against-fedora' (f51b230f) 2020-12-22 Mike Gabriel * Travis: Enable CI builds against Fedora. (46dc10a1) * Merge branch 'dthadi3-ppc64le' (bcc5cc52) 2020-12-10 Devendranath Thadi * Travis-ci: archlinux docker image not available on power (3255a97e) * Travis-ci: added support for ppc64le (e5a710f7) 2020-12-03 Mike Gabriel * .build.yml: Add 'which' build-requirement (needed by autogen.sh / mate-common) when building against Archlinux. (9aa47501) * Travis: First attempt at CI building against Archlinux. (8acd8f71) * debian/libayatana-ido3-0.4-0.symbols: Update for new symbols related to idoRemovableMenuItem. (af27d395) 2020-12-03 Robert Tari * Merge branch 'sunweaver-pr/fix-make-distcheck' (295c154b) 2020-11-30 Mike Gabriel * AUTHORS: Add Robert Tari to authors. (afdf4623) 2020-12-03 Robert Tari * Merge branch 'sunweaver-pr/update-authors' (6e5bb51a) 2020-12-02 Mike Gabriel * TRAVIS: Add .build.yml (missing in previous commit). (5df78c79) * TRAVIS: first attempt of doing CI builds in docker images. (1803b017) 2020-12-03 Mike Gabriel * NEWS: Add file (compiled out of Git history). (3ca4c37e) * Makefile.am: Add --disable-silent-rules option to DISTCHECK_CONFIGURE_FLAGS. (2a83a928) * src/Makefile.am: Move 'sources_c =' variable definition further up. (9057543f) * src/Makefile.am: Split out all *.c files from libayatana_ido_0_4_la_SOURCES into sources_c variable. (385c7976) * src/Makefile.am: Various TAB'bing fixes / beautifications. (d5fb21d8) * src/Makefile.am: Merge old 'INCLUDES =' and 'AM_CPPFLAGS =' values (and beautify the TAB'bing). (5307fc84) * src/libayatana-ido.h: Include internal APIs from the local directory (i.e. the same dir where libayatana-ido.h is located). (bd87193c) * configure.ac: Comment out CHECK_XORG_GTEST. Not available in a functional state, currently. (0a5a670d) * Makefile.am: Re-add DISTCHECK_CONFIGURE_FLAGS to disable GTK doc build during 'make distcheck'. (9f5734c8) 2020-12-02 Mike Gabriel * TRAVIS: Add .build.yml (missing in previous commit). (f2e01767) * TRAVIS: first attempt of doing CI builds in docker images. (8323793f) 2020-11-30 Mike Gabriel * AUTHORS: Add Robert Tari to authors. (36c39de3) 2020-12-01 Mike Gabriel * .travis.yml: Correctly set MATRIX_EVAL for 'GCC 10.x / Ubuntu bionic'. (6f86a8c6) * .travis.yml: Add test-build against GCC 10.x. (1cbc0bc9) * .travis.yml: Name Ubuntu version in CI job names. (67324d2f) * .travis.yml: Disable 'Clang 3.9 / xenial' CI build (GLib2.0 too old in Ubuntu xenial). (521d2bd0) * .travis.yml: Disable 'GCC 5.4 / xenial' CI build (GLib2.0 too old in Ubuntu xenial).. (9478a52e) * .travis.yml: Add 'script:' section. Our test target is 'check', not 'test'. Also enable more verbose builds. (242e6706) * .travis.yml: Run autogen.sh before configuring/building. (aff72d87) 2020-11-30 Mike Gabriel * Initial .travis.yml configuration. (da6f59b5) * Merge branch 'tari01-pr/show-removable-button' (7fb66ef5) 2020-11-26 Robert Tari * idoremovablemenuitem.c: Show button by default (e7d62172) 2020-11-30 Mike Gabriel * Merge branch 'tari01-pr/ido-removable' (fbf7f2e5) 2020-11-24 Robert Tari * Add a new menu item type: IDO Removable (02f9598a) 2020-11-09 Mike Gabriel * release 0.8.1 (d3bcb7d2) (tag: 0.8.1) 2020-10-21 Mike Gabriel * Merge branch 'tari01-pr/switch-initial-state' (2267a403) 2020-09-25 Robert Tari * idoswitchmenuitem.c: Fix setting the initial state for the switch (336b92c4) 2020-10-21 Mike Gabriel * Merge branch 'tari01-pr/basic-markup' (b0dfd127) 2020-09-25 Robert Tari * Add sanity-check in ido_switch_menu_item_activate (13e3334d) 2020-09-16 Robert Tari * idoswitchmenuitem.c: Pass the switch activation state in the action signal (eaa7ce5d) * Whitespace fix (f96d98c7) 2020-09-17 Robert Tari * idobasicmenuitem.c: Add optional markup to the basic menu item (009998bd) 2020-09-27 Mike Gabriel * Merge branch 'tari01-pr/switch-state-fix' (bbcbd080) 2020-09-25 Robert Tari * Add sanity-check in ido_switch_menu_item_activate (d3184630) 2020-09-16 Robert Tari * idoswitchmenuitem.c: Pass the switch activation state in the action signal (6a4bf3d4) * Whitespace fix (7ed68c15) 2020-08-14 Mike Gabriel * release 0.8.0 (d580f61c) (tag: 0.8.0) 2020-08-13 Robert Tari * Merge branch 'sunweaver-pr/ayatanamenuitemfactory-make-public-api' Attributes GH PR #13: https://github.com/AyatanaIndicators/ayatana-ido/pull/13 (11e687d9) 2020-08-13 Mike Gabriel * src/Makefile.am: Export ayatanamenuitemfactory.h as part of the public API, needed by indicator-ng.c in libayatana-indicator. (d61bb9fd) 2020-08-11 Robert Tari * Merge branch 'sunweaver-pr/replace-x-canonical-attributes' Attributes GH PR #11: https://github.com/AyatanaIndicators/ayatana-ido/pull/11 (34aa56fb) * Merge branch 'pr/replace-x-canonical-attributes' of https://github.com/sunweaver/ayatana-ido into sunweaver-pr/replace-x-canonical-attributes (b3686dc2) 2020-08-11 Mike Gabriel * Replace x-canonical attributes solely used by Ayatana Indicators. (974147df) 2020-08-11 Robert Tari * Replace x-canonical attributes (9e209733) 2020-08-10 Mike Gabriel * Merge branch 'tari01-master' (4e2ff263) 2020-08-07 Robert Tari * Drop IDO Message Dialog (2ce8e4a7) 2020-07-31 Robert Tari * Merge pull request #8 from tari01/master (f062e196) * Centre playback menu item spinner/Pad application menu item label (b65bc505) 2020-07-28 Robert Tari * Merge pull request #7 from tari01/master (b18ced14) * Centre volume control/Stretch calendar horizontally (f937570c) 2020-07-24 Mike Gabriel * release 0.5.0 (fac3c960) (tag: 0.5.0) * src/idomessagedialog.c: Mark G_GNUC_{BEGIN,END}_IGNORE_DEPRECATIONS wrapping around gtk_dialog_get_action_area() with a FIXME. (ef4ea9d0) * Merge branch 'tari01-master' (669fb5e0) 2020-07-24 Robert Tari * Updated colour getter for playback control (40a8f045) * Some refactoring to avoid warnings (c0bddf13) 2020-07-23 Mike Gabriel * Merge branch 'tari01-master' (f8f87bdc) 2020-07-23 Robert Tari * Remove ayatana-private.h (9384761a) 2020-07-07 Mike Gabriel * src/Makefile.am: Don't choke with FTBFS on every future deprecation warning. Drop -Werror from CPPFLAGS. (9e2cc8f1) * Merge branch 'kikislater-patch-1' (e29ccbb7) 2020-07-07 Sylvain POULAIN * gtk_widget_get_state is deprecated (033c9f49) 2019-12-04 Mike Gabriel * release 0.4.90 (f9466bb0) (tag: 0.4.90) * Port from Glib's g_object_newv to g_object_new_with_properties. (15453452) 2019-12-03 Mike Gabriel * Avoid deprecated g_type_class_add_private. (0ab4079b) 2018-08-13 Mike Gabriel * release 0.4.4 (3fded466) (tag: 0.4.4) * libayatana-ido3.pc.in: Fix Name: field in .pc file. (87e08a67) * Revert "libayatana-ido3.pc.in: Unversion name of .pc pkg-config file (plus fix Name: field in .pc file)." (c4357fbb) * release 0.4.3 (b98a821b) (tag: 0.4.3) * debian/control: Rename -dev pkg (drop SO version from name). (455e1136) * libayatana-ido3.pc.in: Unversion name of .pc pkg-config file (plus fix Name: field in .pc file). (b88e8e92) * debian/libayatana-ido3-0.4-dev.install: Unversion name of .pc pkg-config file. (e1b6e693) * debian/gir1.2-ayatanaido3-0.4.install: Renamed from gir1.2-ayatana-ido3-0.4.install. (b3497fb3) * debian/gir1.2-ayatanaido3-0.4.install: Renamed from gir1.2-ayatana-ido3-0.4.install. (177a6942) * debian/control: typo fix (missing colon in Replaces: field). (c3c95ec7) 2018-07-16 Mike Gabriel * autogen.sh: Fix PKG_NAME (ido -> ayatana-ido). (34aabe72) 2017-12-04 Mike Gabriel * debian/*: Adopt packaging changes from official Debian package. (57c67c96) * debian/copyright: Package has moved on Github (ArcticaProject -> AyatanaIndicators). (d78483e8) * debian/control: Package has moved on Github (ArcticaProject -> AyatanaIndicators). (c1b56c62) * debian/changelog: Bump upsteam version to a development version. (100892aa) * release 0.4.2 (5a10cb59) (tag: 0.4.2) * tests/Makefile.am: Fix static lib name (libido -> libayatana-ido). (511562ee) * debian/control: Bump Standards-Version: to 4.1.1. No changes needed. (bb3f64f4) * libayatana-ido3.pc.in: Fix pkg-config name (libido -> libayatana-ido). (3fcfc52c) 2017-10-26 Mike Gabriel * Makefile.am: Drop distcheck features. (f87b4295) 2017-10-22 Mike Gabriel * debian/changelog: Fix source project name in most recent changelog stanza. (35eeb7e7) 2017-09-15 Mike Gabriel * release 0.4.1 (75bbddb3) (tag: 0.4.1) 2017-06-23 Mike Gabriel * debian/control: Add versioned B-D: dpkg-dev (>= 1.16.1.1) (1202ada6) * debian/upstream: Add upstream signing keys. (d54247b4) * debian/watch: Add file. (cf2fe656) * debian/patches: Add README for patches folder. (9ade6cd9) * debian/rules: Add get-orig-source rule. (c17595f7) * debian/rules: Enable all hardening flags. (b7ac3e9d) * debian/control: Don't duplicate Section: for shared library package. (9c9bd9db) * debian/control: Bump Standards-Version: to 3.9.8. No changes needed. (eb4383f4) * debian/copyright: Adopt minor changes from official Debian package. (4f7b60c9) 2017-05-22 Mike Gabriel * configure.ac: Let AC_CONFIG_SRCDIR point to src/libayatana-ido.h. (03ae4390) * src/libido.h: Drop empty file (artifact of fork). (e835f22a) * debian/copyright: Adopt from official Debian package. (33c6c134) * release 0.4.0 (2c5700f7) (tag: 0.4.0) * configure.ac: Update shared library name, bug tracker URL, homepage URL. (fda91d47) * Build system: Drop remnants of GTK-2+ support. (39d0d9fb) * debian/{control,gir1.2-ayatana-ido3-0.4.install}: Turn into Multi-Arch: same package. (fec55f9d) * debian/control: Update SYNOPSIS and LONG_DESCRIPTION fields. (81e64871) * autogen.sh: Drop references to deprecated shell variables. (6b027abf) * Drop .bzr-builddeb/default.conf. We are on Git. (5ff2bc11) 2017-05-16 Mike Gabriel * One step back... Mimick Canonical's API. Use their namespace for item attributes. (4daacc47) * Move NEWS file from Canonical out of the way. (7956f5b7) 2017-05-15 Marco Trevisan (Treviño) * IdoCalendarMenuItem: disconnect from parent signals on item destruction (LP: #1506427) (61e95ac5) 2017-05-15 Mike Gabriel * build system: Switch to mate-common. (89f8b570) 2015-11-16 Mike Gabriel * Use x-ayatanaindicator-* instead of x-canonical-*. (4a435758) * Makefile.am (fcf7848c) 2015-11-11 Mike Gabriel * Drop .bzrignore file. (656e57dc) 2015-11-06 Mike Gabriel * libayatana-ido fork: Fix include paths for public header files. (ffebacae) * Adapt pkconfig .pc files to library name changes. (8acfbb70) * debian/rules: Drop override_dh_auto_test rule. Tests are disabled in tests/Makefile.am at the moment, anyway. (3790a17d) * make: Improve distclean ruleset. (17de78b1) * Re-add forgotten files after fork: libayatana-ido.pc.in, libayatana-ido3.pc.in. (00872537) * Fork ayatana-ido from Ubuntu's ido shared library. (76d15095) 2015-10-02 CI Train Bot * Releasing 13.10.0+15.10.20151002-0ubuntu1 (d1b09d9f) 2015-10-02 Lars Uebernickel * idosourcemenuitem: change misplaced g_return_val_if_fail() Approved by: Sebastien Bacher, PS Jenkins bot (771ce0c2) * idosourcemenuitem: change misplaced g_return_val_if_fail() (fd3ea181) 2015-07-28 CI Train Bot * Releasing 13.10.0+15.10.20150728-0ubuntu1 (f007376c) 2015-07-28 Marco Trevisan (Treviño) * IdoCalendarMenuItem: add crash guard on ido_calendar_menu_item_key_press (03583381) 2015-07-22 Marco Trevisan (Treviño) * IdoCalendarMenuItem: add crash guard on ido_calendar_menu_item_key_press (ac4bbf0c) 2015-03-19 CI Train Bot * Releasing 13.10.0+15.04.20150319-0ubuntu1 (6f2f647e) 2015-03-19 Lars Uebernickel * idoscalemenuitem: fix scale hover state Approved by: Sebastien Bacher, PS Jenkins bot, Simon Steinbeiß (4c578ba7) 2015-03-10 Lars Uebernickel * idoscalemenuitem: set focus flag on scale (3bef6a19) * idoscalemenuitem: translate motion event coordinates (07a30270) 2015-01-30 CI Train Bot * Releasing 13.10.0+15.04.20150130-0ubuntu1 (fced82c1) 2015-01-30 Lars Uebernickel * idoplaybackmenuitem: don't set the spinner class (34458940) * idoplaybackmenuitem: don't set the spinner class (1f922e5a) 2015-01-22 CI Train Bot * Releasing 13.10.0+15.04.20150122-0ubuntu1 (467b70e3) 2015-01-22 Lars Uebernickel * idoscalemenuitem: fix slider event forwarding Approved by: Iain Lane, PS Jenkins bot (9f8609c1) 2015-01-21 Lars Uebernickel * idoscalemenuitem: remove extraneous line (22e14c51) * idoscalemenuitem: only forward button events that are inside the scale (3ae1abba) * idoscalemenuitem: don't translate event coordinates (b42893f3) 2014-11-03 CI bot * Releasing 13.10.0+15.04.20141103-0ubuntu1 (d69f78b0) 2014-11-03 Ted Gould * Update tags for newer GObject Introsepction Scanner and disable xorg-gtest tests Fixes: 1382020 Approved by: PS Jenkins bot (2d4009b5) * Filter out symbols in the library (c3c628dc) * Comment out xorg-gtest tests (fae005ab) 2014-10-16 Ted Gould * Add lcov version 1.11 (e9522b40) * Update tags for newer GObject Introsepction Scanner (5c4cf2d5) 2014-04-23 CI bot * Releasing 13.10.0+14.04.20140423-0ubuntu1 (01ce8c36) 2014-04-23 Lars Uebernickel * Make long track infos better readable (bc444da6) * idoplaybackmenuitem: don't introduce even more magic numbers (82c094a5) * idoplaybackmenuitem: center the controls horizontally (8844b191) * idomediaplayermenuitem: don't hardcode width (3c5e4d8c) * idomediaplayermenuitem: use small font for track info labels (560f9332) 2014-04-07 CI bot * Releasing 13.10.0+14.04.20140407-0ubuntu1 (c734bb89) 2014-04-07 Lars Uebernickel * idobasicmenuitem: update icon when the theme changes (c3fc9b1c) 2014-04-04 Lars Uebernickel * idobasicmenuitem: don't export update_image() (220d43ca) * idobasicmenuitem: update icon when the theme changes (b7ec0fe2) 2014-03-28 CI bot * Releasing 13.10.0+14.04.20140328-0ubuntu1 (1c842fe4) * Update symbols (06270039) 2014-03-28 Lars Uebernickel * idoplaybackmenuitem: propagate events in the menu keyrelease handler (d973b784) * expose idobasicmenuitem, a normal menu item that supports non-square icons (6e90a5c3) * Highlight back/forward buttons when hovering them with the pointer (34b23e22) * idobasicmenuitem: check return value of gtk_icon_info_get_filename() for NULL (8269c14b) 2014-03-27 Lars Uebernickel * idobasicmenuitem: add symbol for _new_from_model() (ab158b1d) * idobasicmenuitem: support non-square icons (d1403ebc) * Expose IdoBasicMenuItem as com.canonical.indicator.basic (b5fe1d71) 2014-03-26 Lars Uebernickel * idobasicmenuitem: put progress menu item into its own file (7614e880) * idoplaybackmenuitem: propagate events in the menu keyrelease handler (0ddb4920) 2014-03-25 Lars Uebernickel * Highlight back/forward buttons when hovering them with the pointer (02c9ed65) * idoplaybackmenuitem: put action names into array keyed by buttons (a877446d) 2014-03-24 CI bot * Releasing 13.10.0+14.04.20140324-0ubuntu1 (e14ab5db) 2014-03-24 Lars Uebernickel * idoplaybackmenuitem: set active flag when player is launching (f5921039) * idoplaybackmenuitem: set active flag when player is launching (5a777027) * idoplaybackmenuitem: don't add .menu css class on the menu item (ab0798e7) 2014-03-21 CI bot * Releasing 13.10.0+14.04.20140321-0ubuntu1 (bfd8fefa) 2014-03-21 Lars Uebernickel * idoapplicationmenuitem: request correct size for empty icons (96d791b3) 2014-03-20 Lars Uebernickel * idoapplicationmenuitem: request correct size for empty icons (69e211f0) 2014-03-13 CI bot * Releasing 13.10.0+14.04.20140313-0ubuntu1 (5cdbd5d4) 2014-03-13 Lars Uebernickel * idoscalemenuitem: use the scale's actual size allocation for events Fixes: 1069762 (60495e0e) 2014-03-12 Lars Uebernickel * Put some space between scale and min/max buttons (40079a79) * Remove toggle-size-allocate handler (3c6efc9d) * idoscalemenuitem: use the scale's actual size allocation for events (b500b83b) 2014-02-13 CI bot * Releasing 13.10.0+14.04.20140213-0ubuntu1 (a52c1a6c) 2014-02-13 Sebastien Bacher * Update the Standards-Version (4a24fe6d) * Update the Standards-Version (a1b73d7d) 2014-01-07 Ken VanDine * Sync changes uploaded to the archive back to trunk . (8f62a0c1) * Build with -Wno-error=deprecated-declarations. (3ebe5c10) 2013-12-19 Ted Gould * Allow gcov 1.10 (b4754082) * No error for deprecations (77d4d122) 2013-12-18 Ted Gould * Allow gcov 1.10 (abf7494e) * No error for deprecations (ba3a0149) 2013-11-28 Lars Uebernickel * IdoScaleMenuItem: intercept left and right keys. Fixes: https://bugs.launchpad.net/bugs/1242550. (e3f4d1d2) * IdoScaleMenuItem: allow changing value with left/right and +/- keys (8035c973) 2013-11-27 Automatic PS uploader * Releasing 13.10.0+14.04.20131127-0ubuntu1 (revision 162 from lp:ido). (d0714b78) * Releasing 13.10.0+14.04.20131127-0ubuntu1, based on r162 (a5b1e91a) 2013-11-27 Lars Uebernickel * idoactionhelper: remove potentially stray idle source when finalizing. (b4f0d45f) * idoactionhelper: remove potentially stray idle source when finalizing (ee400c2a) 2013-11-26 Automatic PS uploader * Releasing 13.10.0+14.04.20131126-0ubuntu1 (revision 160 from lp:ido). (74a2e436) * Releasing 13.10.0+14.04.20131126-0ubuntu1, based on r160 (b4af2fc0) 2013-11-26 Lars Uebernickel * ido_calendar_menu_item_new_from_model: initialize local variables with NULL (04c85ff3) * ido_calendar_menu_item_new_from_model: initialize local variables with NULL (8d768203) 2013-11-06 Automatic PS uploader * Releasing 13.10.0+14.04.20131106-0ubuntu1 (revision 158 from lp:ido). (d1cdca8e) * Releasing 13.10.0+14.04.20131106-0ubuntu1, based on r158 (9bb7ffcd) 2013-11-06 Lars Uebernickel * ido_user_menu_item: remove superfluous unref (48b2262e) * ido_user_menu_item: remove superfluous unref (bb2f459b) 2013-11-05 Automatic PS uploader * Releasing 13.10.0+14.04.20131105.1-0ubuntu1 (revision 156 from lp:ido). (0a01da42) * Releasing 13.10.0+14.04.20131105.1-0ubuntu1, based on r156 (3f79da93) * Update symbols (447b26e4) 2013-10-31 Lars Uebernickel * idoscalemenuitem: disconnect signal from parent (e1fa7c7d) * idoscalemenuitem: disconnect signal from parent (10c52b70) 2013-10-28 Lars Uebernickel * IdoUserMenuItem: only allow file icons as avatars (28427a3e) * ido_user_menu_item_set_icon_from_file_icon: don't initialize width and height (6485128d) * ido_user_menu_item_set_icon_from_file_icon: free file (a2e6b66a) 2013-10-27 Lars Uebernickel * Don't export ido_user_menu_item_set_icon_from_file_icon() (0e079e89) 2013-10-26 Lars Uebernickel * IdoUserMenuItem: only allow file icons as avatars (dc577baa) 2013-10-24 Lars Uebernickel * Also allow using + and - keys to change the slider (cd88b8ae) 2013-10-22 Lars Uebernickel * Make IdoSwitchMenuItem accessible from gtk_menu_new_from_model. (596e38b6) * Unref serialized_icon (bccb3fbe) * Don't call gtk_image_clear() on a NULL widget (180ab330) * debian: add new ido symbols (f5c03fb9) * examples: use new IdoSwitchMenuItem API (d910f415) * Make IdoSwitchMenuItem accessible from gtk_menu_new_from_model (898a2216) * IdoSwitchMenuItem: deprecate get_content_area and add set_{label,icon} (8a99eded) 2013-10-21 Lars Uebernickel * IdoScaleMenuItem: intercept left and right keys (8fe2bdf7) 2013-10-11 Automatic PS uploader * Releasing 13.10.0+13.10.20131011-0ubuntu1 (revision 152 from lp:ido). (6e849d59) * Releasing 13.10.0+13.10.20131011-0ubuntu1, based on r152 (845d114e) 2013-10-10 Lars Uebernickel * idoscalemenuitem: request a minimum width of 200px. (302d2445) * idoscalemenuitem: request a minimum width of 200px (30289d8c) 2013-09-30 Lars Uebernickel * idousermenuitem: center avatar and adjust spacing. (ebffc6d3) 2013-09-30 Automatic PS uploader * Releasing 13.10.0+13.10.20130930-0ubuntu1 (revision 149 from lp:ido). (5c5055d3) 2013-09-30 Lars Uebernickel * idousermenuitem: center user avatars and adjust spacing (a5ee7a61) 2013-09-30 Automatic PS uploader * Releasing 13.10.0+13.10.20130930-0ubuntu1, based on r149 (9db63ea5) 2013-09-25 Lars Uebernickel * idoscalemenuitem: don't update the action state when the action state changes (8a9333d1) * idoscalemenuitem: don't update the action state when the action state changes (ed88015d) 2013-09-20 Automatic PS uploader * Releasing 13.10.0+13.10.20130920-0ubuntu1 (revision 147 from lp:ido). (4bc9bfd8) * Releasing 13.10.0+13.10.20130920-0ubuntu1, based on r147 (93686c5e) 2013-09-16 Lars Uebernickel * Reverse slider movement when scrolling by default. Fixes: https://bugs.launchpad.net/bugs/1225330. (d6cd5121) 2013-09-15 Lars Uebernickel * Revert slider movement when scrolling by default (a947c803) 2013-08-14 Automatic PS uploader * Releasing 13.10.0+13.10.20130814-0ubuntu1 (revision 145 from lp:ido). (e95f3161) * Releasing 13.10.0+13.10.20130814-0ubuntu1, based on r145 (8e3c2c4c) * Update symbols (4c88448b) 2013-08-13 Lars Uebernickel * Add widgets for messaging menu. (05443b6b) 2013-08-13 Ted Gould * Library functions taking GVariant params need to ref_sink() and unref() always. (reason #24 to not like GVariant) (bb86413d) * Adding new symbols (f19d539f) 2013-08-13 Lars Uebernickel * Add IdoSourceMenuItem (be7301a1) * Add IdoApplicationMenuItem (8b1bba62) 2013-07-31 Automatic PS uploader * Releasing 13.10.0+13.10.20130731-0ubuntu1 (revision 143 from lp:ido). (242477ce) * Releasing 13.10.0+13.10.20130731-0ubuntu1, based on r143 (c835e939) * Update symbols (a79b4554) 2013-07-30 Charles Kerr * Support x-canonical-type: "com.canonical.indicator.progress" and "com.canonical.indicator.alarm". (86b63cfd) 2013-07-25 Charles Kerr * sync two removed API functions: ido_location_menu_item_set_format, ido_location_menu_item_set_name (ad7dd275) * implement IdoLocationMenuItem as a subclass of IdoTimeStampMenuItem (5761e8d1) * add support for com.canonical.indicator.alarm menuitems. (1b716667) * implement IdoAppointmentMenuItem as a specialization of IdoTimeStampMenuItem (c823c870) * add IdoTimeStampMenuItem, a base class for appointments, locations, and alarms (89784377) * subclass IdoAppointmentMenuItem from IdoBasicMenuItem (3565dadf) * add a 6px margin between the icon and primary text iff the icon is visible (b4cc30dc) * subclass IdoLocationMenuItem from IdoBasicMenuItem (124564dd) * add make the type macro for IdoBasicMenuItem follow the standard naming scheme (8a9b4b89) 2013-07-24 Charles Kerr * don't hardcode making com.canonical.indicator.progress insensitiv. its sensitivity should follow its action's sensitivity. (2ef49dc4) * add public API symbols to debian/ (69f5f2cb) * add a menuitem that renders com.canonical.indicator.progress as laid out in https://wiki.ubuntu.com/Power#Phone (79875b4b) 2013-07-03 Automatic PS uploader * Releasing 13.10.0+13.10.20130703.1-0ubuntu1 to ubuntu. (f3e64f72) * Releasing 13.10.0+13.10.20130703.1-0ubuntu1, based on r141 (e7bf3599) 2013-07-03 Ted Gould * Fix broken comments for the introspection scanner. (f40fb902) 2013-07-02 Ted Gould * Fixing some small introspection errors (fd29ab9e) 2013-07-02 Charles Kerr * fix IdoLocationMenuItem label alignment issue reported by ted. (829c2c24) * revert the UBUNTU_MENUPROXY line since will's reverting the gtk menu proxy to support it as before (644fe6e5) * add test cases of IdoLocationMenuItem to the 'menus' example app (3eb15969) * in idolocationmenuitem, fix slight alignment issue in the city label (8c347eb6) 2013-07-02 Automatic PS uploader * Releasing 13.10.0+13.10.20130702-0ubuntu1 to ubuntu. (20247ad5) * Releasing 13.10.0+13.10.20130702-0ubuntu1, based on r138 (4f768672) 2013-07-01 Charles Kerr * Test to see if a user's avatar is loadable before we use it. (43222b36) * in ido_user_menu_item_set_icon(), remove a g_warning iff icon is NULL (14e5eeb2) * don't load the icon twice (059926df) * if a user's avatar icon file doesn't exist or isn't readable, fall back to the default avatar (e31ab7b9) 2013-06-28 Automatic PS uploader * Releasing 13.10.0+13.10.20130628-0ubuntu1 to ubuntu. (5c6e7618) * Releasing 13.10.0+13.10.20130628-0ubuntu1, based on r136 (c0080ba3) * Update symbols (9d1a1d79) 2013-06-27 Charles Kerr * one-liner fix to a copy-paste error in GuestMenuItem's handling of online/active guests. (fbabe330) * fix a copy-paste bug in the last commit's GuestMenuItem code (549a1b5c) 2013-06-24 Charles Kerr * Adds support for the guest menuitem. (49b6a152) 2013-06-23 Charles Kerr * oops, that @replaceme should have been 0replaceme... (db32e752) * in debian/libido3-0.1-0.symbols, add the new symbols (90116502) * silence console warnings when a NULL filename is passed into ido_user_menu_item_set_icon_from_filename() (1f0bfc0a) * add ido_guest_menu_item_new_for_model() (8008ec3c) * add an 'icon' property to idousermenuitem (61ce7276) 2013-06-20 Lars Uebernickel * Add IdoMediaPlayerMenuItem and IdoPlaybackMenuItem. (8f8d487e) 2013-06-19 Lars Uebernickel * ido_playback_menu_item_parent_key_press_event: be more explicit (e88a842c) * idoplaybackmenuitem: remove redundant 'else' (80a024e4) * idoplaybackmenuitem: warn before crashing in g_str_equal (5aca3b41) * ido_playback_menu_item_get_button_at_pos: add ascii blueprint (e2de4823) * ido_media_player_menu_item_state_changed: declare constant variables as const (5d9faae9) * idomediaplayermenuitem: allow non-local album art (ba02d52c) * idomediaplayermenuitem: make album art size a #define (52a73fd6) * debian: add new symbols (810627ec) * idoplaybackmenuitem.c: mark internal functions as static (bf730496) * Merge trunk (9bf880d9) 2013-06-19 Automatic PS uploader * Releasing 13.10.0daily13.06.19-0ubuntu1 to ubuntu. (e84fd152) * Releasing 13.10.0daily13.06.19-0ubuntu1, based on r132 (a2aa0cb5) * Update symbols (f9589a7b) 2013-06-17 Lars Uebernickel * IdoPlaybackMenuItem: listen to state changes of the 'play' action (bfb0755c) 2013-06-17 Charles Kerr * Better handling of IdoMenuItem construction from GMenuItems, better public API documentation. (72653592) 2013-06-17 Lars Uebernickel * Add IdoPlaybackMenuItem (01d0c0b1) 2013-06-17 Charles Kerr * copyediting: fix copy/paste errors in the documentation (0aa36d9c) * in IdoAppointmentMenuItem's update_timestamp_label(), clear the label text if either the time or format properties are unset (32915975) * add documentation for the public API calls (03485394) * when building location and appointment menuitems from a GMenu, grab all the parameters and then pass them to object_new() as a block to avoid them getting set twice -- once with the constructor's default values, and then once afterwards (9205983a) * in idoappointmentmenuitem.c, fix startup issue arising from updating the timestamp label when the strftime format string hasn't been initialized yet. (6de8e038) 2013-06-15 Charles Kerr * adds the ido widgets needed for indicator-datetime. (83e47356) * in debian/libido3-0.1-0.symbols, that should be '0replaceme'... (53ee722f) 2013-06-14 Charles Kerr * add the new calendar, appointment, location symbols to debian/ (1a47ea12) * fix time_t issue in idocalendarmenuitem's gmenu code (2e5b7f36) * bump version from 13.10.0 to 13.10.1 (5d6dce19) * in idolocationmenuitem, assume seconds are shown in the timestamp when the time format string includes '%s', '%S', '%T', '%X', or '%c' (2e2f7e3d) * add ted's name to idoappointmentmenuitem.c for create_color_icon_pixbuf() (5988e06c) * remove g_message that leaked into last commit (914258f0) * add calendar, location, and appointment menuitems to the IDO factory (17c7bd1f) * add ido_calendar_menu_item_new_from_model() (93735362) * add location menuitem (88522dcd) * add appointment menuitem (3db9d6ff) 2013-06-12 Lars Uebernickel * Add IdoMediaPlayerMenuItem (ef70e33d) 2013-06-08 Jeremy Bicha * Depend on valac instead of valac-0.16 for easier transitions Have libido3-0.1-dev depend on gir1.2-ido3-0.1 Drop unnecessary gir build-depends. (76101320) 2013-06-07 Jeremy Bicha * Depend on valac instead of valac-0.16 for easier transitions Have libido3-0.1-dev depend on gir1.2-ido3-0.1 Drop unnecessary gir build-depends (f265a165) 2013-06-07 Lars Uebernickel * Add support for creating scale menu items from a menu model. (c80dc60d) * Merge trunk (62ed83ce) * idoscalemenuitem: look "{min,max}-icon" on the GMenuItem (8db174af) 2013-06-07 Automatic PS uploader * Releasing 13.10.0daily13.06.07-0ubuntu1 to ubuntu. (b36e57dd) * Releasing 13.10.0daily13.06.07-0ubuntu1, based on r127 (c9dba5ad) * Update symbols (5dc44195) 2013-05-31 Lars Uebernickel * debian: add new symbols (c23cdfcb) * Add support for creating scale menu items from a menu model (26d057cb) * Add ido_action_helper_change_state (03dc54fb) * idoscalemenuitem: make the scale expand and fill in the menu item (cb6475e5) 2013-05-31 Charles Kerr * Put a framework in place to move custom menu items from the indicator packages into ido. It depends on a vendor-patch to gtk (see bug #1183505), because gtk+ does not yet have an API for inserting arbitrary menu items into menus created with gtk_menu_new_from_model(). (e5d21874) 2013-05-31 Lars Uebernickel * debian: add new symbols (18f2ca9e) * Bump glib and gtk dependencies (52b6ef7b) * ido_user_menu_item_new_from_model: fix docstring (3578bb3a) 2013-05-27 Lars Uebernickel * Move crate_user_menu_item into idousermenuitem.c (e863f12e) * IdoActionHelper: document signals and properties (07f79077) * debian/changelog: bump version (d4474897) 2013-05-24 Lars Uebernickel * GtkMenuItemFactory -> UbuntuMenuItemFactory (2c0fa18b) 2013-05-23 Lars Uebernickel * Bumb version to 13.10 (725c0ade) * Create IdoUserMenuItems for indicator.user-menu-item (424d5f42) 2013-05-22 Lars Uebernickel * Merge IdoUserMenuItem branch (18569334) * Add IdoActionHelper (12a5f155) * Add IdoMenuItemFactory (3f3aa147) 2013-03-27 Charles Kerr * rename idousermenuitem's "icon" property as "icon-filename" for a little more clarity. (e9c82c39) 2013-03-26 Charles Kerr * in ido_user_menu_item_primitive_draw_cb_gtk_3(), remove deprecated use of gtk_widget_get_style(), gtk_widget_get_state() (0430322c) * add idousermenuitem to the examples (49c57fdc) * add properties to IdoUserMenuItem and remove its dependencies on DbusmenuMenuitem (259c7ad0) * rename user-widget.[ch] to idousermenuitem.[ch]. Not building yet, next step is to decouple from dbusmenu. (2d8eac6a) * add user-widget.[ch] from indicator-session's trunk (bf3b14f5) 2013-03-01 Automatic PS uploader * Releasing 12.10.3daily13.03.01-0ubuntu1 to ubuntu. (27f3661c) * Releasing 12.10.3daily13.03.01-0ubuntu1, based on r125 (34b7cb32) 2013-02-27 Mathieu Trudel-Lapierre * Fix linking against X11 and Xi which xorg-gtest now seems to require. I'll fix xorg-gtest directly too (in progress), but this is to avoid blocking builds and daily release. Fixes: https://bugs.launchpad.net/bugs/1126353. (3f9644c5) * Explicitly link against X11 and Xi while xorg-gtest doesn't. (3fae0abe) 2013-02-06 Mathieu Trudel-Lapierre * Fix building against gtest/xorg-gtest. Fixes: https://bugs.launchpad.net/bugs/1112775. (f294976a) * Guard against CID:12651, division by zero of FPS value due to its use for timing timeline updates. (f81bc0d3) * Shut up coverity about CID:12650. (d9aa6f03) 2013-02-05 Mathieu Trudel-Lapierre * Avoid FTBFS due to conflicting paths to gtest source, or because the relevant gtest files aren't found -- always use the xorg-gtest gtest source, and adjust path accordingly. (fe1d7264) 2013-01-11 Automatic PS uploader * Releasing 12.10.3daily13.01.11-0ubuntu1 to ubuntu. (22a384d7) * Releasing 12.10.3daily13.01.11-0ubuntu1, based on r122 (5b7d7353) 2013-01-04 Robert Ancell * Add introspection and vala support. Fixes: https://bugs.launchpad.net/bugs/582985. (2db941fb) 2012-12-18 Allan LeSage * Testing with cyphermox--removing the special Xvfb auto_test override appears to resolve flaky tests under Jenkins. (b7c4bed2) 2012-12-17 Allan LeSage * Update changelog. (d5a5d411) * Remove Xvfb from debian/control. (6c956308) * Remove auto_test override. (0219eb9a) 2012-12-15 Robert Ancell * Update packing for introspection/vapi (bdb90268) * Add introspection dependencies (8830da32) 2012-12-14 Robert Ancell * Add introspection and Vala support to IDO (6c9a6684) 2012-12-05 Mathieu Trudel-Lapierre * Run tests through xfvb-run. (21040fca) * - Add xvfb to Build-Depends. - Override dh_auto_test to run them through xvfb-run. (57be74b7) 2012-11-26 Didier Roche * Bootstrapping ido. (7fc48c2b) * add bootstrap comment (638bd117) 2012-11-26 Mathieu Trudel-Lapierre * Inline packaging. (2d8dd253) * Reactivate tests, they don't fail. (7dc37ec5) * Drop the override for dh_makeshlibs. (cc01061b) 2012-11-19 Mathieu Trudel-Lapierre * Temporarily disable tests via overriding dh_auto_test; they fail to properly start X in a schroot. (a06895c0) * Add Vcs-Bzr, Vcs-Browser fields with a notice to uploaders. (64322799) * - Reorganize Build-Depends: move libxorg-gtest-dev up to be consistent with other indicator stack packages. - List libgtest-dev explicitly in Build-Depends. (10bad323) * Add gnome-common to Build-Depends. (1e30ac26) * Override dh_autoreconf to call autogen.sh and not run configure... (dfaa0f4b) * debian/rules: - Add and export DPKG_GENSYMBOLS_CHECK_LEVEL instead of passing -c4 to dh_makeshlibs. (634fa1b4) * debian/control: - Update to match style with other indicator stack packages: use trailing commas at the end of dependency lists. (e1ee7820) * Specify that bzr-builddeb should use split mode to build the package (3432ef30) * Manually import debian/ from ido 12.10.2-0ubuntu1. (804ec33e) 2012-11-08 Charles Kerr * one-liner to add 'check-news' to our AM_INIT_AUTOMAKE invocation (ae5b229f) 2012-11-06 Charles Kerr * add tests for ido_entry_menu_item_get_entry, bringing package line coverage up to 55.5% (8b984ae8) * add tests for IdoCalendarMenuItems's mark/unmark/clear days, bringing package line coverage up to 55.2% (38965ac9) * add tests for IdoScaleMenuItem, bringing package line coverage to 54% (07d422b4) * add more coverage for idocalendar. total package's line coverage is up to 50% now (33683f31) * add tests for idomessagedialog (0b831239) * add missing G_BEGIN_DECLS call (12437e91) * add IdoSwitchMenuItem test (9d88f5c1) * extract-method: TestMenuItems::PutInMenu() (d2c974f3) 2012-09-20 Charles Kerr * 12.10.2 (3e84f25e) * the calendar widget shouldn't eat the ESC key.. Fixes: https://bugs.launchpad.net/bugs/964005. Approved by Lars Uebernickel, jenkins. (b98fedd4) 2012-09-19 Charles Kerr * the calendar widget shouldn't eat the ESC key. (20fe9d4c) 2012-08-27 Lars Uebernickel * 12.10.1 (63717ffc) * Merge lp:~larsu/ido/remove-slider-hack-953757 (bfdc8422) 2012-08-22 Charles Kerr * merge lp:~charlesk/ido/nogtk2 to remove gtk2 support from the configure script and the source (2481b74f) * remove the gtk2 conditional compiles for IdoMessageDialog (73302803) * remove the gtk2 conditional compiles for IdoCalendarMenuItem (2c688719) * remove the gtk2 conditional compiles for IdoEntryMenuItem (821b008d) * sync with lp:ido (fc8fad25) 2012-08-21 Charles Kerr * merge lp:~ken-vandine/ido/link-libm to AC_CHECK_LIBM to get -lm now that gtk doesn't include that in it's .pc file (8f279d3f) * merge lp:~charlesk/ido/switch to add GtkSwitchMenuItem (a0631d30) * bump to 12.10.0 (d4f4fa39) * revert the event delegation for now, it's not necessary for FF (402fffb5) * when the mouse is over the GtkSwitch widget, the menuitem should delegate the mouse down and motion events to it. (fbd76f40) * use gtk_menu_shell_deactivate() rather than gtk_menu_popdown(); the latter handles the issue of the menu title being painted as if the menu were still open (fb4b3068) * ...and if we're not clearing that in dispose(), then we don't need dispose() anymore (791d0042) * don't keep the GBinding pointer around, it'll be destroyed automatically when the menuitem's destroyed (c0af3f55) * comment tweaks (0f1f31d9) * make the glib 2.32 requirement explicit in configure.ac (e99fb9fa) * add IdoSwitchMenuItem (992e7468) 2012-07-24 Ken VanDine * Use AC_CHECK_LIBM to get -lm now that gtk doesn't include that in it's .pc file (cfbf3b9d) 2012-05-07 Charles Kerr * require gtk3 (84a63033) * remove unused function ido_range_grab_notify() (78c634c4) 2012-04-26 Charles Kerr * merge lp:~ted/ido/gtest to add the gtest framework and a few tests to make sure our menu items can be created and realized. (2a3f56b5) 2012-04-25 Ted Gould * Bring in xorg-gtest to get an X11 wrapper (46367686) * Build a scale menu item as well (62a010af) * Adding in the entry menuitem as well. (d02dfec2) * Putting in the BEGIN_DECLS for the C++ folks (e112516e) * Now we can realize the menu item to make sure it doesn't mess that up (072a5ab6) * Now we're allocating a calendar (7db7f0e7) * Adding in a dummy test and the dependencies to build it (274e4778) * No gtk-doc.m4 needed (68dedd8b) * We've now got a test directory! (4f9a30d2) * Adding in Google test build utilities (8bba0b8f) * Attaching bug (d6d8e2e1) 2012-04-12 Charles Kerr * merge lp:~allanlesage/ido/TDD to add targets to autotools build for code-coverage reporting. For more information, see this blog post: http://qualityhour.wordpress.com/2012/01/29/test-coverage-tutorial-for-cc-autotools-projects/ . (ceb09d1a) 2012-03-27 Allan LeSage * Added gcov coverage tooling. (0597fa88) 2012-03-21 Ted Gould * 0.3.4 (a4ad20e5) (tag: 0.3.4) 2012-03-16 Lars Uebernickel * ido-range: chain up constructed() to base class (0d4d88db) * Remove slider mouse button hack (dde83216) 2012-03-14 Charles Kerr * fix regression that broke mousewheel operations on the idoscale (6a6e63c0) * fix regression that broke mousewheel operations on the idoscale (196217d7) 2012-03-13 Charles Kerr * 0.3.3 (6db7ec8d) (tag: 0.3.3) * merge lp:~charlesk/ido/lp-898611 to fix lp bug #898611 (99152011) 2012-03-12 Charles Kerr * alter mouse button 2 clicks to behave like mouse button 2 clicks for lp bug #898611. (8722b2b1) * Merge lp:~charlesk/indicator-sound/lp-921065 into lp:indicator-sound to add "primary-clicked" and "secondary-clicked" events for lp bug #921065 (9b02ced3) * Merge lp:~charlesk/ido/lp-906050 into lp:ido to resolve the following LP tickets: (728b3d1f) 2012-03-10 Charles Kerr * add primary-clicked and secondary-clicked signals for lp bug #921065 (db0c18cb) 2012-03-09 Charles Kerr * tweak: fix some indentation damage in the header file (dfbd1c2f) * remove idooffscreenproxy (8497b8ef) * small code cleanup in update_packing() (942c6ccd) * Fix LP Bug #906050 by removing idoscalemenuitem's offscreen proxy. (ab9e35ac) * don't override widget_class.state_changed in idoscalemenuitem ... that was preventing the prelight state from ever showing up there. (c96a9ad4) 2012-03-09 Ted Gould * 0.3.2 (5b65ff3b) (tag: 0.3.2) 2012-02-09 Ken VanDine * add style class "menubar" to the offscreen proxy, this fixes the white background drawn in the sound menu menu with the current gtk3/light-themes (LP: #925700) (eec3ce5b) 2012-02-08 Ken VanDine * add style class "menubar" to the offscreen proxy, this fixes the white background drawn in the sound menu with the current gtk3/light-themes (LP: #925700) (a6f5ba8a) 2012-01-12 Ken VanDine * Patch from ~covox (LP: #867649) (4471ef23) 2011-12-14 Ken VanDine * removed deprecations from gtk3 and fixed sizing issues with idemessagedialog (LP: #888392) (97ead211) * removed deprecations from gtk3 and fixed sizing issues with idemessagedialog (LP: #888392) (9b717e50) 2011-10-13 Ted Gould * 0.3.1 (50b234a4) (tag: 0.3.1) 2011-10-12 Ted Gould * Fixes for ARM (8a442cf1) 2011-10-06 Ken VanDine * one more fix for armel FTBFS (28c45e5c) 2011-10-05 Ken VanDine * Fixed FTBFS on armel (LP: #866039) (fcda3837) 2011-10-03 Michal Hruby * Merge lp:~mhr3/ido/bug-865122 (93b180bd) * Get rid of unnecessary check (565816b6) * And we need to include config.h (81e42543) * Use the grab-notify workaround only when using Gtk3 (ae22267a) * Fix bug #865122 (4dd0ca96) 2011-09-28 Ted Gould * 0.3.0 (8a32a254) (tag: 0.3.0) 2011-09-20 Ted Gould * 0.2.93 (49d7db70) (tag: 0.2.93) 2011-09-16 Ted Gould * Ignoring m4 (db192710) * Update Autotools and remove Shave (90cb6637) * Fix the calendar item (08a590ac) * Freeing the new event (3abfadde) * Attaching bug (6e4d5b14) * Putting the new code as GTK3 only (d903b298) * Removing a bunch of debug messages (f5be40f0) * Use get_origin instead of position and uncomment out our adjustments (94ce65a5) * Use the root position in the event instead of finding it (8d56d16e) * Clean up some debug and such (8ca02b8e) 2011-09-15 Ted Gould * Reformating (f2699633) * A check point (f4c7db4e) 2011-09-13 Ted Gould * 0.2.92 (1415b10d) (tag: 0.2.92) * Ignoring some junk! (3c967456) * Putting the offscreen proxy in EXTRA_DIST if we're building GTK2 version (24f2228a) * Making the proxy GTK3 only (6b7751a8) 2011-09-13 Robert Carr * Only use the offscreen proxy stuff in GTK3 (074baff8) 2011-09-13 Ted Gould * Increasing the number of warnings (41f3702d) 2011-09-08 Ted Gould * 0.2.91 (9a47c76a) (tag: 0.2.91) 2011-09-08 Robert Carr * Merge lp:~robertcarr/ido/offscreen-scale (af912b97) 2011-09-06 Robert Carr * Ok I take it back we don't care about border. use custom css to set border-width and radius (a2ddfbb6) * Don't leak style context... (01dd00e0) * Use GtkBorder in drawing background (0d4a3db7) * Use gtk_render_background (7bc5c973) 2011-09-02 Robert Carr * Whoops copyright headers (2f38eb39) * Implement an IdoOffscreenProxy object to work around GtkRange/Scale needing grabs, change IdoScaleMenuItem to make use of this. Fixes lp: #804009 (8de6cb90) 2011-08-03 Javier Jardón * configure.ac: Update autotools config a bit (c9394c71) * build: Use upstream silent rules instead shave (66af8460) 2011-06-21 Ted Gould * 0.2.90 (0b3ce25c) (tag: 0.2.90) * Commenting out boiler plate code that is causing a warning (5ae054d2) * Making sure the menu example doesn't use a menu proxy (ea37afc6) * Avoid duplicate events (f3a7a217) * Updating to GTK3 (e1c47927) 2011-06-20 Michael Terry * use const not G_CONST_RETURN (d61ddbef) 2011-06-01 Michael Terry * drop deprecated use of event_window (cd59e86e) * adjustments aren't widgets (db8bf6c5) * fix build errors with gtk2 (da4d22c3) * fix various unused-variable warnings; not directly related to gtk3 work, but helps focus on actual problems (ab8fccf9) * some further automake magic for dual versioning (d9ec4cfe) * allow building either gtk2 or gtk3 versions; some deprecation cleanups (5ddcf6b5) 2011-05-27 Ken VanDine * porting to gtk3, WIP (3e67ec3d) 2011-05-12 Karl Lattimer * fixed multiple signal issue which caused calendar jumps bug #768956 (b80a8199) 2011-03-16 Ted Gould * 0.2.2 (33ab93de) (tag: 0.2.2) 2011-03-16 David Barth * add signals for select/activate and a set date function - merge of karl-qdh branch (add9d713) 2011-03-15 karl-qdh * Bug in closure (d163ba56) 2011-03-14 Ted Gould * Be able to set active date and signal when it changes (9b651a12) 2011-03-06 karl-qdh * minor fixes (3a78f4ca) * Merge with trunk (aac51739) * Added new API to the calendar menu item so we can change the selected day/date. Also added new signals for selecting days and selecting with double click. In indicator-datetime these signals will be connected to either launching evolution (double), or invoking a re-building of the appointments menu (single) from the selected day forward. (368393bf) 2011-03-02 Ted Gould * Adding back lost API (a38ef762) 2011-02-28 David Barth * integrating Karl & mterry's API for exposing calendar display options (8264fbe2) 2011-02-25 Michael Terry * compile fix (40048835) 2011-02-25 karl-qdh * Added return if fails to public api (acbbf01f) * Gmf. (ae4456bf) * Merging with trunk (6b313f16) * Added missing getter for calendar display options (a7e9eed7) 2011-02-24 Ken VanDine * Added ido_calendar_menu_item_get_calendar back to prevent a ABI break (acebf0d2) 2011-02-24 Cody Russell * Fixed missing semicolon. Also the code formatting was all messed up so I fixed that because I'm kind of a code formatting nazi. Sie müssen Antretenbzr diff (3072fd17) * Bump version (0ade4861) 2011-02-23 Ted Gould * Adding API to the calendar menu item (461b1687) 2011-02-23 karl-qdh * Added get_date, pretty critical function (b6f75c17) * Removed useless marshal include (3acb7aa0) * Fixed building of api changes (f18b9b84) 2011-02-22 karl-qdh * Removed get_calendar, we don't want it and it's unnecessary to do this (841bcef7) 2011-02-21 karl-qdh * Added month change signal too, slight cleanup of tabs (f0138998) * Added additional API for marking days and setting options (99b479df) 2011-01-18 Cody Russell * Remove IdoGestureManager (5b3b2fe2) * Fix linker problems in Natty. (603f3279) * Add GTK_LIBS to the example programs' LDADD (9f822793) 2010-10-07 Cody Russell * Listen to GtkMenuItem's 'toggle-size-allocate' signal to get the toggle size instead of using the GSEAL'd GtkMenuItem::toggle_size value. (ecaf8c79) 2010-09-24 Cody Russell * Cleanup, and update to latest geis API. (193b5061) 2010-09-14 Cody Russell * Merge geis updates. (9aa08ce6) * Remove gtk-doc.make (0a8cdd08) * Fix properties. (8b95b135) * GEIS updates. (846ae96e) 2010-09-13 Cody Russell * Merge fix for bug #635370 (f3ca63f0) 2010-09-10 Cody Russell * When we grab focus, it seemed to also select all the text. (308c3076) 2010-09-09 Cody Russell * Bump version to 0.2.0. (8a939cf2) * Bump version to 0.1.12 (553318dd) * Pull in gtk-doc.make from trunk. (37df02c9) 2010-09-09 David Barth * replace gtk-doc.make with the packaging version to avoid a merge conflict (435b5823) 2010-09-08 David Barth * fix distcheck; thanks to seb128 (228cbdae) 2010-08-19 David Barth * don't export export menus over dbus, that won't work... (6e46e3be) 2010-08-15 Cody Russell * Feel up your widgets. (e90ec22f) 2010-08-03 Cody Russell * Fix for armel build. Patch by David Sugar. (f3893ee5) 2010-07-29 Cody Russell * bleh (b35ee3e7) * Bump version. (ee58467e) 2010-07-27 Cody Russell * Need to update the last progress. (f5a80f5b) 2010-07-22 Cody Russell * Bump version (95536449) * ido_timeline_set_progress() (47fbcc20) 2010-07-20 Cody Russell * Calendar keyboard navigation. (91975606) * Fix something. (8ae5a81a) * Small cleanups (12736cbd) 2010-07-19 Cody Russell * Calendar (29475f33) 2010-07-15 Cody Russell * Force IdoRange to style itself by name rather than by class. Otherwise they all have the style used by the last one created. (272dafa2) * Fix for distcheck (32093b51) * Bump version to 0.1.9 (cea3e8ff) * Merge scale-size branch. (663fb983) * Different range size styles. (b3dc66c6) 2010-07-14 Cody Russell * Fix compile for ARM (7aed15f7) 2010-07-13 Cody Russell * Merge in range branch. (dfa54555) * Add IdoRange, and modify IdoScaleMenuItem to use it. (01d2367c) 2010-07-08 Cody Russell * Bump version (09a64549) * Fix IdoMessageDialog to compile with deprecated gtk+ for Meerkat. (03c0ea45) * Fix license (e937255e) * Fixes for dist (6218c6d7) * Bump version to 0.1.7. (23318a5d) * Merge up with trunk. (b3f43507) * Start the morph on focus-in-event rather than button-press-event. (5fa7b66f) 2010-07-07 Cody Russell * Send button-press and button-release events to the entry. Also grab focus at the first key-press. (44058898) 2010-07-02 Cody Russell * Set focus-on-map to FALSE. (717cf40f) 2010-06-08 Cody Russell * Bump version to 0.1.6 (fab639ce) 2010-05-12 Cody Russell * IdoMessageDialog - a morphing message dialog. (a544da2c) 2010-05-10 Cody Russell * Fake out the grab stuff by setting GTK_HAS_GRAB on the scale widget before forwarding the event. (ac894c8f) * Try to remove offscreen fu (9f850501) 2010-04-14 Cody Russell * reverse-scroll-events property only affects GDK_SCROLL_UP and GDK_SCROLL_DOWN (dd709add) 2010-03-24 David Barth * release 0.1.5 - Don't return TRUE if keyval is GDK_Return. - Bump gtk+ requirement to 2.19.7 - Don't capture up/down keys. Compile fixes for latest gtk+. - Button press event fixes. (172006ca) (tag: 0.1.5) 2010-03-18 Cody Russell * Don't return TRUE if keyval is GDK_Return. (9a3de4a3) 2010-03-16 Cody Russell * Bump gtk+ requirement to 2.19.7 (e27e482b) * Don't capture up/down keys. Compile fixes for latest gtk+. (e965ac4c) 2010-03-15 Cody Russell * Don't capture up/down keys. Compile fixes for latest gtk+. (d6a2f217) 2010-03-11 Cody Russell * Button press event fixes. (7561ce13) 2010-03-11 David Barth * release 0.1.4 (cb28301c) (tag: 0.1.4) 2010-03-10 Cody Russell * Button press event fixes. (0dfd8e6f) 2010-03-09 Cody Russell * Don't forward the event to the entry if the user hit the Esc key. (3865303f) * Fix for grab/release signals. If you grab the slider and then release it while the mouse is outside the menu, it was not emitting the released signal. (de771b0e) 2010-03-08 Cody Russell * Fix keyboard navigation issues in the entry widget, fixes bug #533284. (a46e53c8) * Merge trunk (e2caba6c) * Return TRUE after forwarding the event to priv->entry (ae62dc79) 2010-03-05 Cody Russell * Add grab/release signals (6c7fcbe1) 2010-03-04 Ken VanDine * bump version to 0.1.3 (af984182) 2010-03-04 Cody Russell * Make 'ido-offscreen-scale' the name of the GtkOffscreenWindow, not the GtkScale. (2cffa858) (tag: 0.1.3) * Name the offscreen scale 'ido-offscreen-scale' (08e010a3) 2010-02-18 David Barth * bump version to 0.1.2 (3acbbdb5) (tag: 0.1.2) 2010-02-13 Cody Russell * Support reversing scroll events (fc660fc4) 2010-02-11 Cody Russell * merge in secondary_padding branch from ken-vandine (ad50ecd5) 2010-02-11 Ken VanDine * fixed build failure where secondary_padding wasn't initialized (1841df08) * bump version to 0.1.1 (cf57f227) (tag: 0.1.1) 2010-02-09 Cody Russell * Merge initial-slider-value branch (6ac36fef) * Merge scale-icons branch (484a47ca) * Add support for initial value to ido_scale_menu_item_new_with_range() (a8435258) * Upper/lower clamping on icon click (e8c2d569) 2010-02-06 Cody Russell * Add support for primary/secondary icons. (bd5faca6) 2010-02-05 Cody Russell * Fix build for ARM architecture (d03f3860) * Test ARM fix (518846a9) * merge scale-spacing-fixes branch (e892ebea) 2010-02-04 Cody Russell * Scale spacing fixes (50ae8efb) * Fix distcheck (1595f645) (tag: 0.1.0) * Merge license change branch (c650b69c) * Merge fix-header-install branch (5d5a08d3) * Merge spacing-fixes branch (d9fc8cf4) * Fix headers to install (faf10d17) * Remove stuff (a5aad4e7) * Copyright/license fu (8b8228c8) * Spacing fixes (9f3461cc) 2010-02-02 Cody Russell * Fix header installs (6b60795c) * Merge entry menuitem (140b9857) 2010-02-01 Cody Russell * Entry menu items (0dc1eba6) * Merge offscreen scale branch (c9b34c90) * Unref the pixbuf (0372535b) 2010-01-25 Cody Russell * Merge get-scale branch (c4a23ad2) * Autogen changes (0696acf9) * Add ido_scale_menu_item_get_scale() function (902d58de) 2010-01-20 Cody Russell * Use GtkOffscreenWindow to manage rendering of the scale. (51029c20) 2010-01-19 Cody Russell * IDO initial commit, scale menuitem (ebb7b05f) ayatana-ido-0.10.1/cmake/COPYING-CMAKE-SCRIPTS0000644000000000000000000000245714471671403014743 0ustar Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ayatana-ido-0.10.1/cmake/FindGObjectIntrospection.cmake0000644000000000000000000000376514471671403017651 0ustar # - try to find gobject-introspection # # Once done this will define # # INTROSPECTION_FOUND - system has gobject-introspection # INTROSPECTION_SCANNER - the gobject-introspection scanner, g-ir-scanner # INTROSPECTION_COMPILER - the gobject-introspection compiler, g-ir-compiler # INTROSPECTION_GENERATE - the gobject-introspection generate, g-ir-generate # INTROSPECTION_GIRDIR # INTROSPECTION_TYPELIBDIR # INTROSPECTION_CFLAGS # INTROSPECTION_LIBS # # Copyright (C) 2010, Pino Toscano, # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. macro(_GIR_GET_PKGCONFIG_VAR _outvar _varname) execute_process( COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=${_varname} gobject-introspection-1.0 OUTPUT_VARIABLE _result RESULT_VARIABLE _null ) if (_null) else() string(REGEX REPLACE "[\r\n]" " " _result "${_result}") string(REGEX REPLACE " +$" "" _result "${_result}") separate_arguments(_result) set(${_outvar} ${_result} CACHE INTERNAL "") endif() endmacro(_GIR_GET_PKGCONFIG_VAR) find_package(PkgConfig) if(PKG_CONFIG_FOUND) if(PACKAGE_FIND_VERSION_COUNT GREATER 0) set(_gir_version_cmp ">=${PACKAGE_FIND_VERSION}") endif() pkg_check_modules(_pc_gir gobject-introspection-1.0${_gir_version_cmp}) if(_pc_gir_FOUND) set(INTROSPECTION_FOUND TRUE) _gir_get_pkgconfig_var(INTROSPECTION_SCANNER "g_ir_scanner") _gir_get_pkgconfig_var(INTROSPECTION_COMPILER "g_ir_compiler") _gir_get_pkgconfig_var(INTROSPECTION_GENERATE "g_ir_generate") _gir_get_pkgconfig_var(INTROSPECTION_GIRDIR "girdir") _gir_get_pkgconfig_var(INTROSPECTION_TYPELIBDIR "typelibdir") set(INTROSPECTION_CFLAGS "${_pc_gir_CFLAGS}") set(INTROSPECTION_LIBS "${_pc_gir_LIBS}") endif() endif() mark_as_advanced( INTROSPECTION_SCANNER INTROSPECTION_COMPILER INTROSPECTION_GENERATE INTROSPECTION_GIRDIR INTROSPECTION_TYPELIBDIR INTROSPECTION_CFLAGS INTROSPECTION_LIBS ) ayatana-ido-0.10.1/cmake/FindVala.cmake0000644000000000000000000000442214471671403014425 0ustar # - Find Vala # This module looks for valac. # This module defines the following values: # VALA_FOUND # VALA_COMPILER # VALA_VERSION # VAPI_GEN # VAPI_GEN_VERSION #============================================================================= # Copyright Přemysl Janouch 2011 # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY # OF SUCH DAMAGE. #============================================================================= find_program (VALA_COMPILER "valac") if (VALA_COMPILER) execute_process (COMMAND ${VALA_COMPILER} --version OUTPUT_VARIABLE VALA_VERSION) string (REGEX MATCH "[.0-9]+" VALA_VERSION "${VALA_VERSION}") endif (VALA_COMPILER) find_program (VAPI_GEN "vapigen") if (VAPI_GEN) execute_process (COMMAND ${VAPI_GEN} --version OUTPUT_VARIABLE VAPI_GEN_VERSION) string (REGEX MATCH "[.0-9]+" VAPI_GEN_VERSION "${VAPI_GEN_VERSION}") endif (VAPI_GEN) include (FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS (Vala REQUIRED_VARS VALA_COMPILER VERSION_VAR VALA_VERSION) mark_as_advanced (VALA_COMPILER VALA_VERSION VAPI_GEN) ayatana-ido-0.10.1/CMakeLists.txt0000644000000000000000000000366214471671403013424 0ustar cmake_minimum_required(VERSION 3.13) project(ayatana-ido C CXX) set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake" "${CMAKE_MODULE_PATH}") if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) SET(CMAKE_INSTALL_PREFIX "/usr" CACHE PATH "..." FORCE) endif(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) # Options option(ENABLE_TESTS "Enable all tests and checks" OFF) option(ENABLE_COVERAGE "Enable coverage reports (includes enabling all tests and checks)" OFF) option(ENABLE_WERROR "Treat all build warnings as errors" OFF) if(ENABLE_COVERAGE) set(ENABLE_TESTS ON) set(CMAKE_BUILD_TYPE "Coverage") else() set(CMAKE_BUILD_TYPE "Release") endif() if(ENABLE_COVERAGE) set(ENABLE_TESTS ON) set(CMAKE_BUILD_TYPE "Coverage") else() set(CMAKE_BUILD_TYPE "Release") endif() if(ENABLE_WERROR) add_definitions("-Werror") endif() if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") add_definitions("-Weverything") else() add_definitions("-Wall") endif() # Thread fix for old CMake set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") # Check for prerequisites set(DEPS glib-2.0>=2.58 gtk+-3.0>=3.24) find_package (PkgConfig REQUIRED) pkg_check_modules(PROJECT_DEPS REQUIRED ${DEPS}) # Set global variables include(GNUInstallDirs) set(PROJECT_VERSION "0.10.1") # Make everything add_subdirectory(src) add_subdirectory(data) if (ENABLE_TESTS) include(CTest) enable_testing() add_subdirectory(example) add_subdirectory(tests) # coverage if (ENABLE_COVERAGE) find_package(CoverageReport) ENABLE_COVERAGE_REPORT( TARGETS "ayatana-ido3-0.4" TESTS "gtest-menuitems" FILTER /usr/include ${CMAKE_BINARY_DIR}/* ) endif() endif() # Display config info message(STATUS "Install prefix: ${CMAKE_INSTALL_PREFIX}") message(STATUS "Unit tests: ${ENABLE_TESTS}") message(STATUS "Build with -Werror: ${ENABLE_WERROR}") ayatana-ido-0.10.1/COPYING.GPL-30000644000000000000000000010451514471671403012477 0ustar GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . ayatana-ido-0.10.1/COPYING.LGPL-20000644000000000000000000006144514471671403012616 0ustar GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Library General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ayatana-ido-0.10.1/COPYING.LGPL-2.10000644000000000000000000006364214471671403012756 0ustar GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ayatana-ido-0.10.1/COPYING.LGPL-30000644000000000000000000001674414471671403012621 0ustar GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. ayatana-ido-0.10.1/data/CMakeLists.txt0000644000000000000000000000042714471671403014331 0ustar # libayatana-ido3-0.4.pc configure_file("${CMAKE_CURRENT_SOURCE_DIR}/libayatana-ido3-0.4.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/libayatana-ido3-0.4.pc" @ONLY) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libayatana-ido3-0.4.pc" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig/") ayatana-ido-0.10.1/data/libayatana-ido3-0.4.pc.in0000644000000000000000000000052014471671403015754 0ustar prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=${prefix} libdir=@CMAKE_INSTALL_FULL_LIBDIR@ includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ Name: libayatana-ido3 Description: Ayatana Indicator Display Objects Version: @PROJECT_VERSION@ Libs: -L${libdir} -layatana-ido3-0.4 Cflags: -I${includedir}/libayatana-ido3-0.4 Requires: gtk+-3.0 glib-2.0 ayatana-ido-0.10.1/example/CMakeLists.txt0000644000000000000000000000051114471671403015045 0ustar # menus add_executable("menus" menus.c) target_include_directories("menus" PUBLIC ${PROJECT_DEPS_INCLUDE_DIRS}) target_link_libraries("menus" ${PROJECT_DEPS_LIBRARIES} "-L${CMAKE_BINARY_DIR}/src" -layatana-ido3-0.4) target_include_directories("menus" PUBLIC "${CMAKE_SOURCE_DIR}/src") add_dependencies("menus" ayatana-ido3-0.4) ayatana-ido-0.10.1/example/menus.c0000644000000000000000000001400614471671403013604 0ustar #include #include "idoscalemenuitem.h" #include "idocalendarmenuitem.h" #include "idoentrymenuitem.h" #include "idolocationmenuitem.h" #include "idoswitchmenuitem.h" #include "idousermenuitem.h" #include "idoremovablemenuitem.h" #include "idolevelmenuitem.h" static void slider_grabbed (GtkWidget *widget, gpointer user_data) { g_print ("grabbed\n"); } static void slider_released (GtkWidget *widget, gpointer user_data) { g_print ("released\n"); } int main (int argc, char *argv[]) { guint i; GtkWidget *window; GtkWidget *vbox; GtkWidget *menu; GtkWidget *menuitem; GtkWidget *root; GtkWidget *menubar; GtkWidget *image; const struct { const char * username; const char * icon_filename; gboolean is_logged_in; gboolean is_active; } users[] = { { "Guest", NULL, FALSE, FALSE }, { "Bobby Fischer", "/usr/share/pixmaps/faces/chess.jpg", FALSE, FALSE }, { "Linus Torvalds", "/usr/share/pixmaps/faces/penguin.jpg", TRUE, FALSE }, { "Mark Shuttleworth", "/usr/share/pixmaps/faces/astronaut.jpg", TRUE, TRUE } }; const struct { const char * name; const char * timezone; const char * format; } locations[] = { { "Oklahoma City", "America/Chicago", "%I:%M %p" }, { "Magdeburg", "Europe/Berlin", "%T" }, { "Kuntzig", "Europe/Paris", "%a %H:%M" } }; g_unsetenv ("UBUNTU_MENUPROXY"); gtk_init (&argc, &argv); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_title (GTK_WINDOW (window), "Menus"); gtk_widget_set_size_request (window, 300, 200); g_signal_connect (window, "delete-event", G_CALLBACK (gtk_main_quit), NULL); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_container_add (GTK_CONTAINER (window), vbox); menubar = gtk_menu_bar_new (); gtk_box_pack_start (GTK_BOX (vbox), menubar, FALSE, FALSE, 0); menu = gtk_menu_new (); root = gtk_menu_item_new_with_label ("File"); gtk_menu_item_set_submenu (GTK_MENU_ITEM (root), menu); menuitem = gtk_menu_item_new_with_label ("New"); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); menuitem = gtk_menu_item_new_with_label ("Open"); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); /* Scale */ menuitem = ido_scale_menu_item_new_with_range ("Volume", IDO_RANGE_STYLE_DEFAULT, 65, 0, 100, 1); ido_scale_menu_item_set_style (IDO_SCALE_MENU_ITEM (menuitem), IDO_SCALE_MENU_ITEM_STYLE_IMAGE); image = ido_scale_menu_item_get_primary_image (IDO_SCALE_MENU_ITEM (menuitem)); gtk_image_set_from_icon_name (GTK_IMAGE (image), "document-new", GTK_ICON_SIZE_MENU); image = ido_scale_menu_item_get_secondary_image (IDO_SCALE_MENU_ITEM (menuitem)); gtk_image_set_from_icon_name (GTK_IMAGE (image), "document-open", GTK_ICON_SIZE_MENU); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); g_signal_connect (menuitem, "slider-grabbed", G_CALLBACK (slider_grabbed), NULL); g_signal_connect (menuitem, "slider-released", G_CALLBACK (slider_released), NULL); /* Entry */ menuitem = ido_entry_menu_item_new (); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); /* Switch */ menuitem = ido_switch_menu_item_new (); ido_switch_menu_item_set_label (IDO_SWITCH_MENU_ITEM (menuitem), "This is a switch."); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); /* Calendar */ gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_separator_menu_item_new ()); menuitem = ido_calendar_menu_item_new (); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); /* Users */ gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_separator_menu_item_new ()); for (i=0; iremovable menu item\nIt has a link\nAnd some small text"); idoRemovableMenuItemUseMarkup(IDO_REMOVABLE_MENU_ITEM(menuitem), TRUE); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); gtk_menu_shell_append (GTK_MENU_SHELL (menu), gtk_separator_menu_item_new ()); /* Level */ menuitem = ido_level_menu_item_new(); idoLevelMenuItemSetText (IDO_LEVEL_MENU_ITEM (menuitem), "Some battery level"); GIcon *pIcon = g_themed_icon_new_with_default_fallbacks ("battery"); idoLevelMenuItemSetIcon (IDO_LEVEL_MENU_ITEM (menuitem), pIcon); idoLevelMenuItemSetLevel (IDO_LEVEL_MENU_ITEM (menuitem), 50); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); /* Add the menubar */ gtk_menu_shell_append (GTK_MENU_SHELL (menubar), root); gtk_widget_show_all (window); gtk_main (); return 0; } ayatana-ido-0.10.1/INSTALL.md0000644000000000000000000000140514471671403012305 0ustar # Build and installation instructions ## Compile-time build dependencies - cmake (>= 3.13) - cmake-extras - glib-2.0 (>= 2.36) - gobject-introspection - gtk-doc - vala (>= 0.16) - gtk+-3.0 (>= 3.24) - gtest (>= 1.6.0) - gmock - gcovr (>= 2.4) - lcov (>= 1.9) ## For end-users and packagers ``` cd ayatana-ido-X.Y.Z mkdir build cd build cmake .. make sudo make install ``` ## For testers - unit tests only ``` cd ayatana-ido-X.Y.Z mkdir build cd build cmake .. -DENABLE_TESTS=ON make make test ``` ## For testers - both unit tests and code coverage ``` cd ayatana-ido-X.Y.Z mkdir build cd build cmake .. -DENABLE_COVERAGE=ON make make test make coverage-html ``` **The install prefix defaults to `/usr`, change it with `-DCMAKE_INSTALL_PREFIX=/some/path`** ayatana-ido-0.10.1/NEWS0000644000000000000000000001026114471671403011354 0ustar Overview of changes in ayatana-ido 0.10.1 - src/idoalarmmenuitem.c: Do not free non memory-allocated variable - Fix possible memory leaks. - Do not hardcode icon sizes. - cmake: Install library as library. - Update/add COPYING files, ship COPYING files for all licensed used. Overview of changes in ayatana-ido 0.10.0 - Add level menu item. - CMakeLists.txt: Add threads fix for old CMake. - src/idoprogressmenuitem.c: Rewrite to use icon, progress property and activation. - Revert "cmake: Enable building tests by default". Overview of changes in ayatana-ido 0.9.3 - cmake: Enable building tests by default. - tests: Fix building against modern GTest. - src/idobasicmenuitem.c: Set secondary text and count with lozenge from menu model. Overview of changes in ayatana-ido 0.9.2 - src/CMakeLists.txt: link libm for expf, pow and sinf. - vala: The name of the vapi should match the pkg-config name. Overview of changes in ayatana-ido 0.9.1 - Clean up compilation flags. - src/idoscalemenuitem.c: Drop hard-coded end-margin for the Scale Display Object. Overview of changes in ayatana-ido 0.9.0 - Port to CMake. - Add better documentation. - data/libayatana-ido3-0.4.pc.in: Add glib-2.0 dependency. - src/idoappointmentmenuitem.c: Construct the basic menu item using the pixbuf property. - src/basicmenuitem.c: Add GdkPixbuf source support for the icon. - src/idoremovablemenuitem.c: Replace grid with box to fix a11y. - src/idolocationmenuitem.c: Fix deprecated g_time_zone_new warning. - Fix a unit test failure on Ubuntu 20.04. - Use consistent Ayatana IDO names. This version of Ayatana IDO breaks NG system indicators before 0.9.x. Overview of changes in ayatana-ido 0.8.2 - Add Travis support (CI builds). - Update AUTHORS file. - Add new NEWS file. - Add a new menu item type: IDO Removable. Overview of changes in ayatana-ido 0.8.1 - idoswitchmenuitem.c: Fix setting the initial state for the switch. - idoswitchmenuitem.c: Pass the switch activation state in the action signal. - idobasicmenuitem.c: Add optional markup to the basic menu item. Overview of changes in ayatana-ido 0.8.0 - src/Makefile.am: Export ayatanamenuitemfactory.h as part of the public API, needed by indicator-ng.c in libayatana-indicator. - Replace x-canonical attributes solely used by Ayatana Indicators. - Drop IDO Message Dialog. - Centre playback menu item spinner/Pad application menu item label. - Centre volume control/Stretch calendar horizontally. Overview of changes in ayatana-ido 0.5.0 - src/idomessagedialog.c: Mark G_GNUC_{BEGIN,END}_IGNORE_DEPRECATIONS wrapping around gtk_dialog_get_action_area() with a FIXME. - Updated colour getter for playback control. - Some refactoring to avoid warnings. - Remove ayatana-private.h. - src/Makefile.am: Don't choke with FTBFS on every future deprecation warning. Drop -Werror from CPPFLAGS. - gtk_widget_get_state is deprecated. Overview of changes in ayatana-ido 0.4.90 - Port from Glib's g_object_newv to g_object_new_with_properties. - Avoid deprecated g_type_class_add_private. Overview of changes in ayatana-ido 0.4.4 - libayatana-ido3.pc.in: Fix Name: field in .pc file. - Revert "libayatana-ido3.pc.in: Unversion name of .pc pkg-config file (plus fix Name: field in .pc file). Overview of changes in ayatana-ido 0.4.3 - libayatana-ido3.pc.in: Unversion name of .pc pkg-config file (plus fix Name: field in .pc file). - autogen.sh: Fix PKG_NAME (ido -> ayatana-ido). Overview of changes in ayatana-ido 0.4.2 - tests/Makefile.am: Fix static lib name (libido -> libayatana-ido). - libayatana-ido3.pc.in: Fix pkg-config name (libido -> libayatana-ido). - Makefile.am: Drop distcheck features. Overview of changes in ayatana-ido 0.4.1 - configure.ac: Let AC_CONFIG_SRCDIR point to src/libayatana-ido.h. - src/libido.h: Drop empty file (artifact of fork). Overview of changes in ayatana-ido 0.4.1 - Build system: Drop remnants of GTK-2+ support. - IdoCalendarMenuItem: disconnect from parent signals on item destruction (LP: #1506427) - build system: Switch to mate-common. - Fork ayatana-ido from Ubuntu's ido shared library. ayatana-ido-0.10.1/NEWS.Canonical0000644000000000000000000000026514471671403013245 0ustar 12.10.2: * fix escape key behavior in calendar menuitem (LP: #953757) 12.10.1: * remove gtk2 support * remove slider hack (lp #953757) 12.10.0: * new widget IdoSwitchMenuItem ayatana-ido-0.10.1/README.md0000644000000000000000000000422114471671403012133 0ustar # ayatana-ido - Ayatana Indicator Display Objects [![Build Status](https://api.travis-ci.com/AyatanaIndicators/ayatana-ido.svg)](https://travis-ci.com/github/AyatanaIndicators/ayatana-ido) ## About Ayatana Indicators The Ayatana Indicators project is the continuation of Application Indicators and System Indicators, two technologies developed by Canonical Ltd. for the Unity7 desktop. Application Indicators are a GTK implementation of the StatusNotifierItem Specification (SNI) that was originally submitted to freedesktop.org by KDE. System Indicators are an extensions to the Application Indicators idea. System Indicators allow for far more widgets to be displayed in the indicator's menu. The Ayatana Indicators project is the new upstream for application indicators, system indicators and associated projects with a focus on making Ayatana Indicators a desktop agnostic technology. On GNU/Linux, Ayatana Indicators are currently available for desktop envinronments like MATE (used by default in [Ubuntu MATE](https://ubuntu-mate.com)), XFCE (used by default in [Xubuntu](https://bluesabre.org/2021/02/25/xubuntu-21-04-progress-update/), LXDE, and the Budgie Desktop. The Lomiri Operating Environment (UI of the Ubuntu Touch OS, formerly known as Unity8) uses Ayatana Indicators for rendering its notification area and the [UBports](https://ubports.com) project is a core contributor to the Ayatana Indicators project. For further info, please visit: https://ayatana-indicators.org ## About this Software Component Ayatana IDO provides custom GTK menu widgets for Ayatana System Indicators. Below is a list of currently available menu item types: - Basic menu item - Scale menu item - Entry menu item - Source menu item - Location menu item - Switch menu item - Alarm menu item - Media player menu item - Switch menu item - Application menu item - Playback menu item - Timestamp menu item - Appointment menu item - Progress menu item - User menu item - Calendar menu item - Removable menu item ## License and Copyright See COPYING and AUTHORS file in this project. ## Building and Testing For instructions on building and running built-in tests, see the INSTALL.md file. ayatana-ido-0.10.1/src/ayatanamenuitemfactory.c0000644000000000000000000000444514471671403016371 0ustar /* * Copyright 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * Lars Uebernickel */ #include "ayatanamenuitemfactory.h" G_DEFINE_INTERFACE_WITH_CODE (AyatanaMenuItemFactory, ayatana_menu_item_factory, G_TYPE_OBJECT, GIOExtensionPoint *ep = g_io_extension_point_register (AYATANA_MENU_ITEM_FACTORY_EXTENSION_POINT_NAME); g_io_extension_point_set_required_type (ep, g_define_type_id);) /* * ayatana_menu_item_factory_get_all: * * Returns a static list of all registered factories. */ GList * ayatana_menu_item_factory_get_all (void) { static GList *factories = NULL; if (factories == NULL) { GIOExtensionPoint *ep; GList *it; g_type_ensure (AYATANA_TYPE_MENU_ITEM_FACTORY); ep = g_io_extension_point_lookup (AYATANA_MENU_ITEM_FACTORY_EXTENSION_POINT_NAME); for (it = g_io_extension_point_get_extensions (ep); it != NULL; it = it->next) { GIOExtension *ext = it->data; AyatanaMenuItemFactory *factory; factory = g_object_new (g_io_extension_get_type (ext), NULL); factories = g_list_prepend (factories, factory); } factories = g_list_reverse (factories); } return factories; } static void ayatana_menu_item_factory_default_init (AyatanaMenuItemFactoryInterface *iface) { } GtkMenuItem * ayatana_menu_item_factory_create_menu_item (AyatanaMenuItemFactory *factory, const gchar *type, GMenuItem *menuitem, GActionGroup *actions) { return AYATANA_MENU_ITEM_FACTORY_GET_IFACE (factory)->create_menu_item (factory, type, menuitem, actions); } ayatana-ido-0.10.1/src/ayatanamenuitemfactory.h0000644000000000000000000000501714471671403016372 0ustar /* * Copyright 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * Lars Uebernickel */ #ifndef __AYATANA_MENU_ITEM_FACTORY_H__ #define __AYATANA_MENU_ITEM_FACTORY_H__ #include G_BEGIN_DECLS #define AYATANA_TYPE_MENU_ITEM_FACTORY (ayatana_menu_item_factory_get_type ()) #define AYATANA_MENU_ITEM_FACTORY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), AYATANA_TYPE_MENU_ITEM_FACTORY, AyatanaMenuItemFactory)) #define AYATANA_IS_MENU_ITEM_FACTORY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), AYATANA_TYPE_MENU_ITEM_FACTORY)) #define AYATANA_MENU_ITEM_FACTORY_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), AYATANA_TYPE_MENU_ITEM_FACTORY, AyatanaMenuItemFactoryInterface)) #define AYATANA_MENU_ITEM_FACTORY_EXTENSION_POINT_NAME "ayatana-menu-item-factory" typedef struct _AyatanaMenuItemFactoryInterface AyatanaMenuItemFactoryInterface; typedef struct _AyatanaMenuItemFactory AyatanaMenuItemFactory; struct _AyatanaMenuItemFactoryInterface { GTypeInterface iface; GtkMenuItem * (*create_menu_item) (AyatanaMenuItemFactory *factory, const gchar *type, GMenuItem *menuitem, GActionGroup *actions); }; GDK_AVAILABLE_IN_3_10 GList * ayatana_menu_item_factory_get_all (void); GDK_AVAILABLE_IN_3_10 GType ayatana_menu_item_factory_get_type (void); GDK_AVAILABLE_IN_3_10 GtkMenuItem * ayatana_menu_item_factory_create_menu_item (AyatanaMenuItemFactory *factory, const gchar *type, GMenuItem *menuitem, GActionGroup *actions); G_END_DECLS #endif ayatana-ido-0.10.1/src/CMakeLists.txt0000644000000000000000000001422114471671403014204 0ustar # ayatanamenuitemfactory.h # idocalendarmenuitem.h # idoentrymenuitem.h # idorange.h # idoscalemenuitem.h # idoswitchmenuitem.h # idotimeline.h # libayatana-ido.h install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/ayatanamenuitemfactory.h" DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/libayatana-ido3-0.4/libayatana-ido") install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/idocalendarmenuitem.h" DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/libayatana-ido3-0.4/libayatana-ido") install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/idoentrymenuitem.h" DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/libayatana-ido3-0.4/libayatana-ido") install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/idorange.h" DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/libayatana-ido3-0.4/libayatana-ido") install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/idoscalemenuitem.h" DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/libayatana-ido3-0.4/libayatana-ido") install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/idoswitchmenuitem.h" DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/libayatana-ido3-0.4/libayatana-ido") install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/idotimeline.h" DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/libayatana-ido3-0.4/libayatana-ido") install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/libayatana-ido.h" DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/libayatana-ido3-0.4/libayatana-ido") set(HEADERS idorange.h idoappointmentmenuitem.h idousermenuitem.h idoalarmmenuitem.h idotimestampmenuitem.h idoplaybackmenuitem.h idoremovablemenuitem.h ayatanamenuitemfactory.h idobasicmenuitem.h idoapplicationmenuitem.h idotimeline.h idosourcemenuitem.h idoactionhelper.h idocalendarmenuitem.h idolocationmenuitem.h idoprogressmenuitem.h libayatana-ido.h idomediaplayermenuitem.h idoswitchmenuitem.h idoscalemenuitem.h idodetaillabel.h idoentrymenuitem.h idolevelmenuitem.h ) set(SOURCES idotimestampmenuitem.c idodetaillabel.c libayatana-ido.c idomenuitemfactory.c idoactionhelper.c idoapplicationmenuitem.c idoplaybackmenuitem.c idomediaplayermenuitem.c idocalendarmenuitem.c ayatanamenuitemfactory.c idoprogressmenuitem.c idolocationmenuitem.c idoscalemenuitem.c idoentrymenuitem.c idoalarmmenuitem.c idorange.c idoappointmentmenuitem.c idoswitchmenuitem.c idoremovablemenuitem.c idobasicmenuitem.c idousermenuitem.c idosourcemenuitem.c idotimeline.c idolevelmenuitem.c ${CMAKE_CURRENT_BINARY_DIR}/idotypebuiltins.c ) # idotypebuiltins.h find_program(GLIB_MKENUMS glib-mkenums) add_custom_command( OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/idotypebuiltins.h" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMAND ${GLIB_MKENUMS} --template idotypebuiltins.h.template ${HEADERS} --output="${CMAKE_CURRENT_BINARY_DIR}/idotypebuiltins.h" ) # idotypebuiltins.c add_custom_command( OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/idotypebuiltins.c" DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/idotypebuiltins.h" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMAND ${GLIB_MKENUMS} --template idotypebuiltins.c.template ${HEADERS} --output="${CMAKE_CURRENT_BINARY_DIR}/idotypebuiltins.c" ) # ayatana-ido3-0.4.so add_library("ayatana-ido3-0.4" SHARED ${SOURCES}) set_target_properties("ayatana-ido3-0.4" PROPERTIES VERSION 0.0.0 SOVERSION 0) target_link_libraries("ayatana-ido3-0.4" ${PROJECT_DEPS_LIBRARIES} m) target_include_directories("ayatana-ido3-0.4" PUBLIC ${PROJECT_DEPS_INCLUDE_DIRS}) target_include_directories("ayatana-ido3-0.4" PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) target_include_directories("ayatana-ido3-0.4" PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_compile_definitions("ayatana-ido3-0.4" PUBLIC G_LOG_DOMAIN="IDO") install(TARGETS "ayatana-ido3-0.4" LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}") # AyatanaIdo3-0.4.gir find_package(GObjectIntrospection REQUIRED QUIET) if (INTROSPECTION_FOUND) set(HEADERS idocalendarmenuitem.h idoentrymenuitem.h idorange.h idoscalemenuitem.h idoswitchmenuitem.h idotimeline.h ) add_custom_command( OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/AyatanaIdo3-0.4.gir" DEPENDS "ayatana-ido3-0.4" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMAND ${INTROSPECTION_SCANNER} ${SOURCES} ${HEADERS} --symbol-prefix=ido --identifier-prefix=Ido --namespace=AyatanaIdo3 --nsversion=0.4 --quiet --pkg=gtk+-3.0 --warn-all --include=Gtk-3.0 --c-include="libayatana-ido/libayatana-ido.h" --library="ayatana-ido3-0.4" --library-path=${CMAKE_CURRENT_BINARY_DIR} --output "${CMAKE_CURRENT_BINARY_DIR}/AyatanaIdo3-0.4.gir" ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/AyatanaIdo3-0.4.gir" DESTINATION "${CMAKE_INSTALL_FULL_DATADIR}/gir-1.0") # AyatanaIdo3-0.4.typelib add_custom_command( OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/AyatanaIdo3-0.4.typelib" DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/AyatanaIdo3-0.4.gir" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${INTROSPECTION_COMPILER} --includedir=${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/AyatanaIdo3-0.4.gir -o "${CMAKE_CURRENT_BINARY_DIR}/AyatanaIdo3-0.4.typelib" ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/AyatanaIdo3-0.4.typelib" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/girepository-1.0") # libayatana-ido3-0.4.vapi find_package(Vala REQUIRED QUIET) if (VALA_FOUND) add_custom_command( OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/libayatana-ido3-0.4.vapi" DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/AyatanaIdo3-0.4.typelib" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMAND ${VAPI_GEN} --library=libayatana-ido3-0.4 --pkg gtk+-3.0 AyatanaIdo3-0.4.gir ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libayatana-ido3-0.4.vapi" DESTINATION "${CMAKE_INSTALL_FULL_DATADIR}/vala/vapi") add_custom_target("src" ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/libayatana-ido3-0.4.vapi") endif () endif () ayatana-ido-0.10.1/src/idoactionhelper.c0000644000000000000000000003374214471671403014772 0ustar /* * Copyright 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * Lars Uebernickel */ #include "idoactionhelper.h" typedef GObjectClass IdoActionHelperClass; struct _IdoActionHelper { GObject parent; GtkWidget *widget; GActionGroup *actions; gchar *action_name; GVariant *action_target; guint idle_source_id; }; G_DEFINE_TYPE (IdoActionHelper, ido_action_helper, G_TYPE_OBJECT) enum { PROP_0, PROP_WIDGET, PROP_ACTION_GROUP, PROP_ACTION_NAME, PROP_ACTION_TARGET, NUM_PROPERTIES }; enum { ACTION_STATE_CHANGED, NUM_SIGNALS }; static GParamSpec *properties[NUM_PROPERTIES]; static guint signals[NUM_SIGNALS]; static void ido_action_helper_action_added (GActionGroup *actions, const gchar *action_name, gpointer user_data) { IdoActionHelper *helper = user_data; gboolean enabled; GVariant *state; if (!g_str_equal (action_name, helper->action_name)) return; if (g_action_group_query_action (actions, action_name, &enabled, NULL, NULL, NULL, &state)) { gtk_widget_set_sensitive (helper->widget, enabled); if (state) { g_signal_emit (helper, signals[ACTION_STATE_CHANGED], 0, state); g_variant_unref (state); } } else { gtk_widget_set_sensitive (helper->widget, FALSE); } } static void ido_action_helper_action_removed (GActionGroup *action_group, gchar *action_name, gpointer user_data) { IdoActionHelper *helper = user_data; if (g_str_equal (action_name, helper->action_name)) gtk_widget_set_sensitive (helper->widget, FALSE); } static void ido_action_helper_action_enabled_changed (GActionGroup *action_group, gchar *action_name, gboolean enabled, gpointer user_data) { IdoActionHelper *helper = user_data; if (g_str_equal (action_name, helper->action_name)) gtk_widget_set_sensitive (helper->widget, enabled); } static void ido_action_helper_action_state_changed (GActionGroup *action_group, gchar *action_name, GVariant *value, gpointer user_data) { IdoActionHelper *helper = user_data; if (g_str_equal (action_name, helper->action_name)) g_signal_emit (helper, signals[ACTION_STATE_CHANGED], 0, value); } static gboolean call_action_added (gpointer user_data) { IdoActionHelper *helper = user_data; ido_action_helper_action_added (helper->actions, helper->action_name, helper); helper->idle_source_id = 0; return G_SOURCE_REMOVE; } static void ido_action_helper_constructed (GObject *object) { IdoActionHelper *helper = IDO_ACTION_HELPER (object); g_signal_connect (helper->actions, "action-added", G_CALLBACK (ido_action_helper_action_added), helper); g_signal_connect (helper->actions, "action-removed", G_CALLBACK (ido_action_helper_action_removed), helper); g_signal_connect (helper->actions, "action-enabled-changed", G_CALLBACK (ido_action_helper_action_enabled_changed), helper); g_signal_connect (helper->actions, "action-state-changed", G_CALLBACK (ido_action_helper_action_state_changed), helper); if (g_action_group_has_action (helper->actions, helper->action_name)) { /* call action_added in an idle, so that we don't fire the * state-changed signal during construction (nobody could have * connected by then). */ helper->idle_source_id = g_idle_add (call_action_added, helper); } G_OBJECT_CLASS (ido_action_helper_parent_class)->constructed (object); } static void ido_action_helper_get_property (GObject *object, guint id, GValue *value, GParamSpec *pspec) { IdoActionHelper *helper = IDO_ACTION_HELPER (object); switch (id) { case PROP_WIDGET: g_value_set_object (value, helper->widget); break; case PROP_ACTION_GROUP: g_value_set_object (value, helper->actions); break; case PROP_ACTION_NAME: g_value_set_string (value, helper->action_name); break; case PROP_ACTION_TARGET: g_value_set_variant (value, helper->action_target); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, id, pspec); } } static void ido_action_helper_set_property (GObject *object, guint id, const GValue *value, GParamSpec *pspec) { IdoActionHelper *helper = IDO_ACTION_HELPER (object); switch (id) { case PROP_WIDGET: /* construct-only */ helper->widget = g_value_dup_object (value); break; case PROP_ACTION_GROUP: /* construct-only */ helper->actions = g_value_dup_object (value); break; case PROP_ACTION_NAME: /* construct-only */ helper->action_name = g_value_dup_string (value); break; case PROP_ACTION_TARGET: /* construct-only */ helper->action_target = g_value_dup_variant (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, id, pspec); } } static void ido_action_helper_finalize (GObject *object) { IdoActionHelper *helper = IDO_ACTION_HELPER (object); if (helper->idle_source_id) g_source_remove (helper->idle_source_id); g_object_unref (helper->widget); g_signal_handlers_disconnect_by_data (helper->actions, helper); g_object_unref (helper->actions); g_free (helper->action_name); if (helper->action_target) g_variant_unref (helper->action_target); G_OBJECT_CLASS (ido_action_helper_parent_class)->finalize (object); } static void ido_action_helper_class_init (IdoActionHelperClass *class) { GObjectClass *object_class = G_OBJECT_CLASS (class); object_class->constructed = ido_action_helper_constructed; object_class->get_property = ido_action_helper_get_property; object_class->set_property = ido_action_helper_set_property; object_class->finalize = ido_action_helper_finalize; /** * IdoActionHelper::action-state-changed: * @helper: the #IdoActionHelper watching the action * @state: the new state of the action * * Emitted when the widget must be updated from the action's state, * which happens every time the action appears in the group and when * the action changes its state. */ signals[ACTION_STATE_CHANGED] = g_signal_new ("action-state-changed", IDO_TYPE_ACTION_HELPER, G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__VARIANT, G_TYPE_NONE, 1, G_TYPE_VARIANT); /** * IdoActionHelper:widget: * * The widget that is associated with this action helper. The action * helper updates the widget's "sensitive" property to reflect whether * the action #IdoActionHelper:action-name exists in * #IdoActionHelper:action-group. */ properties[PROP_WIDGET] = g_param_spec_object ("widget", "", "", GTK_TYPE_WIDGET, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); /** * IdoActionHelper:action-group: * * The action group that eventually contains the action that * #IdoActionHelper:widget should be bound to. */ properties[PROP_ACTION_GROUP] = g_param_spec_object ("action-group", "", "", G_TYPE_ACTION_GROUP, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); /** * IdoActionHelper:action-name: * * The name of the action in #IdoActionHelper:action-group that * should be bound to #IdoActionHelper:widget */ properties[PROP_ACTION_NAME] = g_param_spec_string ("action-name", "", "", NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); /** * IdoActionHelper:action-target: * * The target of #IdoActionHelper:widget. ido_action_helper_activate() * passes the target as parameter when activating the action. * * The handler of #IdoActionHelper:action-state-changed is responsible * for comparing this target with the action's state and updating the * #IdoActionHelper:widget appropriately. */ properties[PROP_ACTION_TARGET] = g_param_spec_variant ("action-target", "", "", G_VARIANT_TYPE_ANY, NULL, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, NUM_PROPERTIES, properties); } static void ido_action_helper_init (IdoActionHelper *helper) { } /** * ido_action_helper_new: * @widget: a #GtkWidget * @action_group: a #GActionGroup * @action_name: the name of an action in @action_group * @target: the target of the action * * Creates a new #IdoActionHelper. This helper ties @widget to an action * (and a target), and performs some common tasks: * * @widget will be set to insensitive whenever @action_group does not * contain an action with the name @action_name, or the action with that * name is disabled. * * Also, the helper emits the "action-state-changed" signal whenever the * widget must be updated from the action's state. This includes once * when the action was added, and every time the action changes its * state. * * Returns: (transfer full): a new #IdoActionHelper */ IdoActionHelper * ido_action_helper_new (GtkWidget *widget, GActionGroup *action_group, const gchar *action_name, GVariant *target) { g_return_val_if_fail (widget != NULL, NULL); g_return_val_if_fail (action_group != NULL, NULL); g_return_val_if_fail (action_name != NULL, NULL); return g_object_new (IDO_TYPE_ACTION_HELPER, "widget", widget, "action-group", action_group, "action-name", action_name, "action-target", target, NULL); } /** * ido_action_helper_get_widget: * @helper: an #IdoActionHelper * * Returns: (transfer none): the #GtkWidget associated with @helper */ GtkWidget * ido_action_helper_get_widget (IdoActionHelper *helper) { g_return_val_if_fail (IDO_IS_ACTION_HELPER (helper), NULL); return helper->widget; } /** * ido_action_helper_get_action_target: * @helper: an #IdoActionHelper * * Returns: (transfer none): the action target that was set in * ido_action_helper_new() as a #GVariant */ GVariant * ido_action_helper_get_action_target (IdoActionHelper *helper) { g_return_val_if_fail (IDO_IS_ACTION_HELPER (helper), NULL); return helper->action_target; } /** * ido_action_helper_activate: * @helper: an #IdoActionHelper * * Activates the action that is associated with this helper. */ void ido_action_helper_activate (IdoActionHelper *helper) { g_return_if_fail (IDO_IS_ACTION_HELPER (helper)); if (helper->actions && helper->action_name) g_action_group_activate_action (helper->actions, helper->action_name, helper->action_target); } /** * ido_action_helper_activate_with_parameter: * @helper: an #IdoActionHelper * @parameter: a #GVariant containing the parameter * * Activates the action that is associated with this helper passing * @parameter instead the "target" associated with the menu item this * helper is bound to. */ void ido_action_helper_activate_with_parameter (IdoActionHelper *helper, GVariant *parameter) { g_return_if_fail (IDO_IS_ACTION_HELPER (helper)); g_return_if_fail (parameter != NULL); g_variant_ref_sink (parameter); if (helper->actions && helper->action_name) g_action_group_activate_action (helper->actions, helper->action_name, parameter); g_variant_unref (parameter); } /** * ido_action_helper_change_action_state: * @helper: an #IdoActionHelper * @state: the proposed new state of the action * * Requests changing the state of the action that is associated with * @helper to @state. * * If @state is floating, it is consumed. */ void ido_action_helper_change_action_state (IdoActionHelper *helper, GVariant *state) { g_return_if_fail (IDO_IS_ACTION_HELPER (helper)); g_return_if_fail (state != NULL); g_variant_ref_sink (state); if (helper->actions && helper->action_name) g_action_group_change_action_state (helper->actions, helper->action_name, state); g_variant_unref (state); } ayatana-ido-0.10.1/src/idoactionhelper.h0000644000000000000000000000407614471671403014775 0ustar /* * Copyright 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * Lars Uebernickel */ #ifndef __IDO_ACTION_HELPER_H__ #define __IDO_ACTION_HELPER_H__ #include #define IDO_TYPE_ACTION_HELPER (ido_action_helper_get_type ()) #define IDO_ACTION_HELPER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), IDO_TYPE_ACTION_HELPER, IdoActionHelper)) #define IDO_IS_ACTION_HELPER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), IDO_TYPE_ACTION_HELPER)) typedef struct _IdoActionHelper IdoActionHelper; GType ido_menu_item_get_type (void); IdoActionHelper * ido_action_helper_new (GtkWidget *widget, GActionGroup *action_group, const gchar *action_name, GVariant *target); GtkWidget * ido_action_helper_get_widget (IdoActionHelper *helper); GVariant * ido_action_helper_get_action_target (IdoActionHelper *helper); void ido_action_helper_activate (IdoActionHelper *helper); void ido_action_helper_activate_with_parameter (IdoActionHelper *helper, GVariant *parameter); void ido_action_helper_change_action_state (IdoActionHelper *helper, GVariant *state); #endif ayatana-ido-0.10.1/src/idoalarmmenuitem.c0000644000000000000000000000711414471671403015147 0ustar /* * Copyright 2013 Canonical Ltd. * Copyright 2021-2023 Robert Tari * * Authors: * Charles Kerr * Ted Gould * Robert Tari * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include #include "idoactionhelper.h" #include "idotimestampmenuitem.h" /** * ido_alarm_menu_item_new_from_model: * @menu_item: the corresponding menuitem * @actions: action group to tell when this GtkMenuItem is activated * * Creates a new IdoTimeStampMenuItem with properties initialized * appropriately for a org.ayatana.indicator.alarm * * If the menuitem's 'action' attribute is set, trigger that action * in @actions when this IdoAppointmentMenuItem is activated. */ GtkMenuItem * ido_alarm_menu_item_new_from_model (GMenuItem * menu_item, GActionGroup * actions) { guint i; guint n; gint64 i64; gchar * str; const gchar * names[4] = {0}; GValue * values; const guint n_max = 4; IdoBasicMenuItem * ido_menu_item; /* create the ido_menu_item */ n = 0; values = g_new0(GValue, n_max); if (g_menu_item_get_attribute (menu_item, G_MENU_ATTRIBUTE_LABEL, "s", &str)) { names[n] = "text"; g_value_init (&values[n], G_TYPE_STRING); g_value_take_string (&values[n], str); n++; } if (TRUE) { names[n] = "icon"; g_value_init (&values[n], G_TYPE_OBJECT); g_value_take_object (&values[n], g_themed_icon_new_with_default_fallbacks ("alarm-symbolic")); n++; } if (g_menu_item_get_attribute (menu_item, "x-ayatana-time-format", "s", &str)) { names[n] = "format"; g_value_init (&values[n], G_TYPE_STRING); g_value_take_string (&values[n], str); n++; } if (g_menu_item_get_attribute (menu_item, "x-ayatana-time", "x", &i64)) { names[n] = "date-time"; g_value_init (&values[n], G_TYPE_DATE_TIME); g_value_take_boxed (&values[n], g_date_time_new_from_unix_local (i64)); n++; } g_assert (n <= G_N_ELEMENTS (names)); g_assert (n <= n_max); ido_menu_item = IDO_BASIC_MENU_ITEM(g_object_new_with_properties (IDO_TYPE_TIME_STAMP_MENU_ITEM, n, names, values)); for (i=0; i * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #ifndef __IDO_ALARM_MENU_ITEM_H__ #define __IDO_ALARM_MENU_ITEM_H__ #include G_BEGIN_DECLS GtkMenuItem * ido_alarm_menu_item_new_from_model (GMenuItem * menuitem, GActionGroup * actions); G_END_DECLS #endif ayatana-ido-0.10.1/src/idoapplicationmenuitem.c0000644000000000000000000001351214471671403016355 0ustar /* * Copyright 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * Lars Uebernickel */ #include "idoapplicationmenuitem.h" #include "idoactionhelper.h" typedef GtkMenuItemClass IdoApplicationMenuItemClass; struct _IdoApplicationMenuItem { GtkMenuItem parent; gboolean is_running; GtkWidget *icon; GtkWidget *label; }; G_DEFINE_TYPE (IdoApplicationMenuItem, ido_application_menu_item, GTK_TYPE_MENU_ITEM); static void ido_application_menu_item_constructed (GObject *object) { IdoApplicationMenuItem *item = IDO_APPLICATION_MENU_ITEM (object); GtkWidget *grid; gint icon_height; gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, NULL, &icon_height); item->icon = g_object_ref (gtk_image_new ()); gtk_image_set_pixel_size (GTK_IMAGE (item->icon), icon_height); gtk_widget_set_margin_end(item->icon, 6); item->label = g_object_ref (gtk_label_new ("")); grid = gtk_grid_new (); gtk_grid_attach (GTK_GRID (grid), item->icon, 0, 0, 1, 1); gtk_grid_attach (GTK_GRID (grid), item->label, 1, 0, 1, 1); gtk_container_add (GTK_CONTAINER (object), grid); gtk_widget_show_all (grid); G_OBJECT_CLASS (ido_application_menu_item_parent_class)->constructed (object); } static void ido_application_menu_item_dispose (GObject *object) { IdoApplicationMenuItem *self = IDO_APPLICATION_MENU_ITEM (object); g_clear_object (&self->icon); g_clear_object (&self->label); G_OBJECT_CLASS (ido_application_menu_item_parent_class)->dispose (object); } static gboolean ido_application_menu_item_draw (GtkWidget *widget, cairo_t *cr) { IdoApplicationMenuItem *item = IDO_APPLICATION_MENU_ITEM (widget); GTK_WIDGET_CLASS (ido_application_menu_item_parent_class)->draw (widget, cr); if (item->is_running) { const int arrow_width = 5; const double half_arrow_height = 4.5; GtkAllocation alloc; GdkRGBA color; double center; gtk_widget_get_allocation (widget, &alloc); gtk_style_context_get_color (gtk_widget_get_style_context (widget), gtk_widget_get_state_flags (widget), &color); gdk_cairo_set_source_rgba (cr, &color); center = alloc.height / 2 + 0.5; cairo_move_to (cr, 0, center - half_arrow_height); cairo_line_to (cr, 0, center + half_arrow_height); cairo_line_to (cr, arrow_width, center); cairo_close_path (cr); cairo_fill (cr); } return FALSE; } void ido_application_menu_item_class_init (IdoApplicationMenuItemClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->constructed = ido_application_menu_item_constructed; object_class->dispose = ido_application_menu_item_dispose; widget_class->draw = ido_application_menu_item_draw; } static void ido_application_menu_item_init (IdoApplicationMenuItem *self) { } static void ido_application_menu_item_set_label (IdoApplicationMenuItem *item, const gchar *label) { gtk_label_set_label (GTK_LABEL (item->label), label); } static void ido_application_menu_item_set_icon (IdoApplicationMenuItem *item, GIcon *icon) { gtk_image_set_from_gicon (GTK_IMAGE (item->icon), icon, GTK_ICON_SIZE_MENU); } static void ido_application_menu_item_state_changed (IdoActionHelper *helper, GVariant *state, gpointer user_data) { IdoApplicationMenuItem *item = user_data; item->is_running = g_variant_get_boolean (state); gtk_widget_queue_draw (GTK_WIDGET (item)); } GtkMenuItem * ido_application_menu_item_new_from_model (GMenuItem *menuitem, GActionGroup *actions) { GtkMenuItem *item; gchar *label; GVariant *serialized_icon; gchar *action; item = g_object_new (IDO_TYPE_APPLICATION_MENU_ITEM, NULL); gtk_widget_set_margin_end(IDO_APPLICATION_MENU_ITEM(item)->label, 16); if (g_menu_item_get_attribute (menuitem, "label", "s", &label)) { ido_application_menu_item_set_label (IDO_APPLICATION_MENU_ITEM (item), label); g_free (label); } serialized_icon = g_menu_item_get_attribute_value (menuitem, "icon", NULL); if (serialized_icon) { GIcon *icon; icon = g_icon_deserialize (serialized_icon); if (icon) { ido_application_menu_item_set_icon (IDO_APPLICATION_MENU_ITEM (item), icon); g_object_unref (icon); } g_variant_unref (serialized_icon); } if (g_menu_item_get_attribute (menuitem, "action", "s", &action)) { IdoActionHelper *helper; helper = ido_action_helper_new (GTK_WIDGET (item), actions, action, NULL); g_signal_connect (helper, "action-state-changed", G_CALLBACK (ido_application_menu_item_state_changed), item); g_signal_connect_object (item, "activate", G_CALLBACK (ido_action_helper_activate), helper, G_CONNECT_SWAPPED); g_signal_connect_swapped (item, "destroy", G_CALLBACK (g_object_unref), helper); g_free (action); } return item; } ayatana-ido-0.10.1/src/idoapplicationmenuitem.h0000644000000000000000000000277114471671403016367 0ustar /* * Copyright 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * Lars Uebernickel */ #ifndef __IDO_APPLICATION_MENU_ITEM_H__ #define __IDO_APPLICATION_MENU_ITEM_H__ #include #define IDO_TYPE_APPLICATION_MENU_ITEM (ido_application_menu_item_get_type ()) #define IDO_APPLICATION_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), IDO_TYPE_APPLICATION_MENU_ITEM, IdoApplicationMenuItem)) #define IS_IDO_APPLICATION_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IDO_TYPE_APPLICATION_MENU_ITEM)) typedef struct _IdoApplicationMenuItem IdoApplicationMenuItem; GType ido_application_menu_item_get_type (void); GtkMenuItem * ido_application_menu_item_new_from_model (GMenuItem *item, GActionGroup *actions); #endif ayatana-ido-0.10.1/src/idoappointmentmenuitem.c0000644000000000000000000001133014471671403016404 0ustar /* * Copyright 2013 Canonical Ltd. * Copyright 2021-2023 Robert Tari * * Authors: * Charles Kerr * Ted Gould * Robert Tari * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include #include "idoactionhelper.h" #include "idotimestampmenuitem.h" /* create a menu-sized pixbuf filled with specified color */ static GdkPixbuf * create_color_icon_pixbuf (const char * color_spec) { static int width = -1; static int height = -1; GdkPixbuf * pixbuf = NULL; if (width == -1) { gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, &height); width = CLAMP (width, 10, 30); height = CLAMP (height, 10, 30); } if (color_spec && *color_spec) { cairo_surface_t * surface; cairo_t * cr; GdkRGBA rgba; surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); cr = cairo_create (surface); if (gdk_rgba_parse (&rgba, color_spec)) gdk_cairo_set_source_rgba (cr, &rgba); cairo_paint (cr); cairo_set_source_rgba (cr, 0, 0, 0, 0.5); cairo_set_line_width (cr, 1); cairo_rectangle (cr, 0.5, 0.5, width-1, height-1); cairo_stroke (cr); pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0, width, height); cairo_destroy (cr); cairo_surface_destroy (surface); } return pixbuf; } /** * ido_appointment_menu_item_new_from_model: * @menu_item: the corresponding menuitem * @actions: action group to tell when this GtkMenuItem is activated * * Creates a new IdoTimeStampMenuItem with properties initialized * appropriately for a org.ayatana.indicator.alarm * * If the menuitem's 'action' attribute is set, trigger that action * in @actions when this IdoAppointmentMenuItem is activated. */ GtkMenuItem * ido_appointment_menu_item_new_from_model (GMenuItem * menu_item, GActionGroup * actions) { guint i; guint n; gint64 i64; gchar * str; IdoBasicMenuItem * ido_menu_item; const gchar * names[4] = {0}; GValue * values; const guint n_max = 4; /* create the ido_menu_item */ n = 0; values = g_new0(GValue, n_max); if (g_menu_item_get_attribute (menu_item, G_MENU_ATTRIBUTE_LABEL, "s", &str)) { names[n] = "text"; g_value_init (&values[n], G_TYPE_STRING); g_value_take_string (&values[n], str); n++; } if (g_menu_item_get_attribute (menu_item, "x-ayatana-color", "s", &str)) { names[n] = "pixbuf"; g_value_init (&values[n], G_TYPE_OBJECT); g_value_take_object (&values[n], create_color_icon_pixbuf (str)); g_free(str); n++; } if (g_menu_item_get_attribute (menu_item, "x-ayatana-time-format", "s", &str)) { names[n] = "format"; g_value_init (&values[n], G_TYPE_STRING); g_value_take_string (&values[n], str); n++; } if (g_menu_item_get_attribute (menu_item, "x-ayatana-time", "x", &i64)) { names[n] = "date-time"; g_value_init (&values[n], G_TYPE_DATE_TIME); g_value_take_boxed (&values[n], g_date_time_new_from_unix_local (i64)); n++; } g_assert (n <= G_N_ELEMENTS (names)); g_assert (n <= n_max); ido_menu_item = IDO_BASIC_MENU_ITEM(g_object_new_with_properties (IDO_TYPE_TIME_STAMP_MENU_ITEM, n, names, values)); for (i=0; i * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #ifndef __IDO_APPOINTMENT_MENU_ITEM_H__ #define __IDO_APPOINTMENT_MENU_ITEM_H__ #include G_BEGIN_DECLS GtkMenuItem * ido_appointment_menu_item_new_from_model (GMenuItem * menuitem, GActionGroup * actions); G_END_DECLS #endif ayatana-ido-0.10.1/src/idobasicmenuitem.c0000644000000000000000000003234114471671403015134 0ustar /* * Copyright 2013 Canonical Ltd. * Copyright 2021-2023 Robert Tari * * Authors: * Charles Kerr * Robert Tari * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include #include "idodetaillabel.h" #include "idoactionhelper.h" #include "idobasicmenuitem.h" enum { PROP_0, PROP_ICON, PROP_PIXBUF, PROP_TEXT, PROP_SECONDARY_TEXT, PROP_LAST }; static GParamSpec *properties[PROP_LAST]; typedef struct { GIcon * icon; GdkPixbuf *pPixbuf; char * text; char * secondary_text; GtkWidget * image; GtkWidget * label; GtkWidget * secondary_label; } IdoBasicMenuItemPrivate; G_DEFINE_TYPE_WITH_PRIVATE (IdoBasicMenuItem, ido_basic_menu_item, GTK_TYPE_MENU_ITEM); /*** **** GObject Virtual Functions ***/ static void my_get_property (GObject * o, guint property_id, GValue * value, GParamSpec * pspec) { IdoBasicMenuItem * self = IDO_BASIC_MENU_ITEM (o); IdoBasicMenuItemPrivate * p = ido_basic_menu_item_get_instance_private(self); switch (property_id) { case PROP_ICON: g_value_set_object (value, p->icon); break; case PROP_PIXBUF: g_value_set_object(value, p->pPixbuf); break; case PROP_TEXT: g_value_set_string (value, p->text); break; case PROP_SECONDARY_TEXT: g_value_set_string (value, p->secondary_text); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec); break; } } static void my_set_property (GObject * o, guint property_id, const GValue * value, GParamSpec * pspec) { IdoBasicMenuItem * self = IDO_BASIC_MENU_ITEM (o); switch (property_id) { case PROP_ICON: ido_basic_menu_item_set_icon (self, g_value_get_object (value)); break; case PROP_PIXBUF: ido_basic_menu_item_set_pixbuf(self, g_value_get_object(value)); break; case PROP_TEXT: ido_basic_menu_item_set_text (self, g_value_get_string (value)); break; case PROP_SECONDARY_TEXT: ido_basic_menu_item_set_secondary_text (self, g_value_get_string (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec); break; } } static void my_dispose (GObject * object) { IdoBasicMenuItem * self = IDO_BASIC_MENU_ITEM (object); IdoBasicMenuItemPrivate *p = ido_basic_menu_item_get_instance_private(self); g_clear_object (&p->icon); g_clear_object (&p->pPixbuf); g_clear_object (&p->secondary_label); G_OBJECT_CLASS (ido_basic_menu_item_parent_class)->dispose (object); } static void my_finalize (GObject * object) { IdoBasicMenuItem * self = IDO_BASIC_MENU_ITEM (object); IdoBasicMenuItemPrivate *p = ido_basic_menu_item_get_instance_private(self); g_free (p->text); g_free (p->secondary_text); G_OBJECT_CLASS (ido_basic_menu_item_parent_class)->finalize (object); } static void ido_basic_menu_item_update_image (IdoBasicMenuItem *self) { IdoBasicMenuItemPrivate *p = ido_basic_menu_item_get_instance_private(self); gtk_image_clear (GTK_IMAGE (p->image)); if (p->icon == NULL && p->pPixbuf == NULL) { gtk_widget_set_visible (p->image, FALSE); } else { if (p->pPixbuf) { gtk_image_set_from_pixbuf(GTK_IMAGE(p->image), p->pPixbuf); gtk_widget_set_visible(p->image, TRUE); } else if (p->icon) { gtk_image_set_from_gicon (GTK_IMAGE (p->image), p->icon, GTK_ICON_SIZE_MENU); gtk_widget_set_visible (p->image, TRUE); } } } static void ido_basic_menu_item_style_updated (GtkWidget *widget) { GTK_WIDGET_CLASS (ido_basic_menu_item_parent_class)->style_updated (widget); ido_basic_menu_item_update_image (IDO_BASIC_MENU_ITEM (widget)); gtk_widget_queue_draw (widget); } /*** **** Instantiation ***/ static void ido_basic_menu_item_class_init (IdoBasicMenuItemClass *klass) { GParamFlags prop_flags; GObjectClass * gobject_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); gobject_class->get_property = my_get_property; gobject_class->set_property = my_set_property; gobject_class->dispose = my_dispose; gobject_class->finalize = my_finalize; widget_class->style_updated = ido_basic_menu_item_style_updated; prop_flags = G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS; properties[PROP_ICON] = g_param_spec_object ("icon", "Icon", "The menuitem's GIcon", G_TYPE_OBJECT, prop_flags); properties[PROP_PIXBUF] = g_param_spec_object ("pixbuf", "Pixbuf", "The menuitem's GdkPixbuf", G_TYPE_OBJECT, prop_flags); properties[PROP_TEXT] = g_param_spec_string ("text", "Text", "The menuitem's text", "", prop_flags); properties[PROP_SECONDARY_TEXT] = g_param_spec_string ("secondary-text", "Secondary Text", "The menuitem's secondary text", "", prop_flags); g_object_class_install_properties (gobject_class, PROP_LAST, properties); } static void ido_basic_menu_item_init (IdoBasicMenuItem *self) { GtkWidget * w; GtkGrid * grid; IdoBasicMenuItemPrivate *p = ido_basic_menu_item_get_instance_private(self); p->image = gtk_image_new (); gtk_widget_set_halign(p->image, GTK_ALIGN_START); gtk_widget_set_valign(p->image, GTK_ALIGN_START); p->label = gtk_label_new (""); gtk_widget_set_halign(p->label, GTK_ALIGN_START); gtk_widget_set_valign(p->label, GTK_ALIGN_CENTER); p->secondary_label = g_object_ref (ido_detail_label_new ("")); gtk_widget_set_halign(p->secondary_label, GTK_ALIGN_END); gtk_widget_set_valign(p->secondary_label, GTK_ALIGN_CENTER); gtk_style_context_add_class (gtk_widget_get_style_context (p->secondary_label), "accelerator"); w = gtk_grid_new (); grid = GTK_GRID (w); gtk_grid_attach (grid, p->image, 0, 0, 1, 1); gtk_grid_attach (grid, p->label, 1, 0, 1, 1); gtk_grid_attach (grid, p->secondary_label, 2, 0, 1, 1); g_object_set (p->image, "halign", GTK_ALIGN_START, "hexpand", FALSE, "valign", GTK_ALIGN_CENTER, "margin-right", 6, NULL); g_object_set (p->label, "halign", GTK_ALIGN_START, "hexpand", TRUE, "margin-right", 6, "valign", GTK_ALIGN_CENTER, NULL); g_object_set (p->secondary_label, "halign", GTK_ALIGN_END, "hexpand", FALSE, "valign", GTK_ALIGN_CENTER, NULL); gtk_widget_show (w); gtk_container_add (GTK_CONTAINER (self), w); } /*** **** Public API ***/ /* create a new IdoBasicMenuItem */ GtkWidget * ido_basic_menu_item_new (void) { return GTK_WIDGET (g_object_new (IDO_TYPE_BASIC_MENU_ITEM, NULL)); } void ido_basic_menu_item_set_icon (IdoBasicMenuItem * self, GIcon * icon) { IdoBasicMenuItemPrivate *p = ido_basic_menu_item_get_instance_private(self); if (p->icon != icon) { if (p->icon) g_object_unref (p->icon); p->icon = icon ? g_object_ref (icon) : NULL; ido_basic_menu_item_update_image (self); } } void ido_basic_menu_item_set_pixbuf(IdoBasicMenuItem *self, GdkPixbuf *pPixbuf) { IdoBasicMenuItemPrivate *pPrivate = ido_basic_menu_item_get_instance_private(self); if (pPrivate->pPixbuf != pPixbuf) { if (pPrivate->pPixbuf) { g_object_unref(pPrivate->pPixbuf); } pPrivate->pPixbuf = pPixbuf ? g_object_ref(pPixbuf) : NULL; ido_basic_menu_item_update_image(self); } } void ido_basic_menu_item_set_icon_from_file (IdoBasicMenuItem * self, const char * filename) { GFile * file = filename ? g_file_new_for_path (filename) : NULL; GIcon * icon = file ? g_file_icon_new (file) : NULL; ido_basic_menu_item_set_icon (self, icon); g_clear_object (&icon); g_clear_object (&file); } void ido_basic_menu_item_set_text (IdoBasicMenuItem * self, const char * text) { IdoBasicMenuItemPrivate *p = ido_basic_menu_item_get_instance_private(self); if (g_strcmp0 (p->text, text)) { g_free (p->text); p->text = g_strdup (text); g_object_set (G_OBJECT(p->label), "label", p->text, "visible", (gboolean)(p->text && *p->text), NULL); } } void ido_basic_menu_item_set_secondary_text (IdoBasicMenuItem * self, const char * secondary_text) { IdoBasicMenuItemPrivate *p = ido_basic_menu_item_get_instance_private(self); if (g_strcmp0 (p->secondary_text, secondary_text)) { g_free (p->secondary_text); p->secondary_text = g_strdup (secondary_text); ido_detail_label_set_text (IDO_DETAIL_LABEL (p->secondary_label), p->secondary_text); gtk_widget_set_visible (p->secondary_label, (gboolean)(p->secondary_text && *p->secondary_text)); } } void ido_basic_menu_item_set_secondary_count (IdoBasicMenuItem *self, gint nCount) { IdoBasicMenuItemPrivate *pPrivate = ido_basic_menu_item_get_instance_private (self); gchar *sSecondaryText = g_strdup_printf("%i", nCount); if (g_strcmp0 (pPrivate->secondary_text, sSecondaryText)) { g_free (pPrivate->secondary_text); pPrivate->secondary_text = g_strdup (sSecondaryText); ido_detail_label_set_count (IDO_DETAIL_LABEL (pPrivate->secondary_label), nCount); gtk_widget_set_visible (pPrivate->secondary_label, (gboolean)(pPrivate->secondary_text && *pPrivate->secondary_text)); } g_free (sSecondaryText); } static void ido_basic_menu_item_activate (GtkMenuItem *item, gpointer user_data) { IdoActionHelper *helper = user_data; ido_action_helper_activate (helper); } GtkMenuItem * ido_basic_menu_item_new_from_model (GMenuItem * menu_item, GActionGroup * actions) { GtkWidget *item; gchar *label; gchar *action; GVariant *serialized_icon; item = ido_basic_menu_item_new (); IdoBasicMenuItemPrivate *p = ido_basic_menu_item_get_instance_private(IDO_BASIC_MENU_ITEM(item)); gboolean use_markup = FALSE; g_menu_item_get_attribute(menu_item, "x-ayatana-use-markup", "b", &use_markup); g_object_set(p->label, "use-markup", use_markup, NULL); g_object_set(p->secondary_label, "use-markup", use_markup, NULL); if (g_menu_item_get_attribute (menu_item, "label", "s", &label)) { ido_basic_menu_item_set_text (IDO_BASIC_MENU_ITEM (item), label); g_free (label); } gchar *sSecondaryText; if (g_menu_item_get_attribute (menu_item, "x-ayatana-secondary-text", "s", &sSecondaryText)) { ido_basic_menu_item_set_secondary_text (IDO_BASIC_MENU_ITEM (item), sSecondaryText); g_free (sSecondaryText); } guint nSecondaryCount; if (g_menu_item_get_attribute (menu_item, "x-ayatana-secondary-count", "i", &nSecondaryCount)) { ido_basic_menu_item_set_secondary_count (IDO_BASIC_MENU_ITEM (item), nSecondaryCount); } serialized_icon = g_menu_item_get_attribute_value (menu_item, "icon", NULL); if (serialized_icon) { GIcon *icon; icon = g_icon_deserialize (serialized_icon); ido_basic_menu_item_set_icon (IDO_BASIC_MENU_ITEM (item), icon); g_object_unref (icon); g_variant_unref (serialized_icon); } if (g_menu_item_get_attribute (menu_item, "action", "s", &action)) { IdoActionHelper *helper; GVariant *target; target = g_menu_item_get_attribute_value (menu_item, "target", NULL); helper = ido_action_helper_new (item, actions, action, target); g_signal_connect_object (item, "activate", G_CALLBACK (ido_basic_menu_item_activate), helper, 0); g_signal_connect_swapped (item, "destroy", G_CALLBACK (g_object_unref), helper); if (target) g_variant_unref (target); g_free (action); } return GTK_MENU_ITEM (item); } ayatana-ido-0.10.1/src/idobasicmenuitem.h0000644000000000000000000000502214471671403015135 0ustar /** * Copyright 2013 Canonical Ltd. * Copyright 2021 Robert Tari * * Authors: * Charles Kerr * Robert Tari * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #ifndef __IDO_BASIC_MENU_ITEM_H__ #define __IDO_BASIC_MENU_ITEM_H__ #include G_BEGIN_DECLS #define IDO_TYPE_BASIC_MENU_ITEM (ido_basic_menu_item_get_type ()) #define IDO_BASIC_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), IDO_TYPE_BASIC_MENU_ITEM, IdoBasicMenuItem)) #define IDO_IS_BASIC_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IDO_TYPE_BASIC_MENU_ITEM)) typedef struct _IdoBasicMenuItem IdoBasicMenuItem; typedef struct _IdoBasicMenuItemClass IdoBasicMenuItemClass; struct _IdoBasicMenuItemClass { GtkMenuItemClass parent_class; }; /** * A simple menuitem that includes a right-justified secondary text. */ struct _IdoBasicMenuItem { /*< private >*/ GtkMenuItem parent; }; GType ido_basic_menu_item_get_type (void) G_GNUC_CONST; GtkWidget * ido_basic_menu_item_new (void); void ido_basic_menu_item_set_icon (IdoBasicMenuItem * self, GIcon * icon); void ido_basic_menu_item_set_pixbuf (IdoBasicMenuItem * self, GdkPixbuf * pPixbuf); void ido_basic_menu_item_set_icon_from_file (IdoBasicMenuItem * self, const char * filename); void ido_basic_menu_item_set_text (IdoBasicMenuItem * self, const char * text); void ido_basic_menu_item_set_secondary_text (IdoBasicMenuItem * self, const char * text); GtkMenuItem * ido_basic_menu_item_new_from_model (GMenuItem * menuitem, GActionGroup * actions); G_END_DECLS #endif ayatana-ido-0.10.1/src/idocalendarmenuitem.c0000644000000000000000000005657414471671403015642 0ustar /* * Copyright 2010 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of either or both of the following licenses: * * 1) the GNU Lesser General Public License version 3, as published by the * Free Software Foundation; and/or * 2) the GNU Lesser General Public License version 2.1, as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License version 3 and version 2.1 along with this program. If not, see * * * Authors: * Cody Russell */ #include #include "idoactionhelper.h" #include "idocalendarmenuitem.h" static void ido_calendar_menu_item_finalize (GObject *item); static void ido_calendar_menu_item_select (GtkMenuItem *item); static void ido_calendar_menu_item_deselect (GtkMenuItem *item); static gboolean ido_calendar_menu_item_button_release (GtkWidget *widget, GdkEventButton *event); static gboolean ido_calendar_menu_item_button_press (GtkWidget *widget, GdkEventButton *event); static gboolean ido_calendar_menu_item_key_press (GtkWidget *widget, GdkEventKey *event, gpointer data); static void ido_calendar_menu_item_send_focus_change (GtkWidget *widget, gboolean in); static void calendar_realized_cb (GtkWidget *widget, IdoCalendarMenuItem *item); static void calendar_move_focus_cb (GtkWidget *widget, GtkDirectionType direction, IdoCalendarMenuItem *item); static void calendar_month_changed_cb (GtkWidget *widget, gpointer user_data); static void calendar_day_selected_double_click_cb (GtkWidget *widget, gpointer user_data); static void calendar_day_selected_cb (GtkWidget *widget, gpointer user_data); typedef struct { GtkWidget *box; GtkWidget *calendar; GtkWidget *parent; gboolean selected; } IdoCalendarMenuItemPrivate; G_DEFINE_TYPE_WITH_PRIVATE (IdoCalendarMenuItem, ido_calendar_menu_item, GTK_TYPE_MENU_ITEM) static void ido_calendar_menu_item_class_init (IdoCalendarMenuItemClass *klass) { GObjectClass *gobject_class; GtkWidgetClass *widget_class; GtkMenuItemClass *menu_item_class; gobject_class = G_OBJECT_CLASS (klass); widget_class = GTK_WIDGET_CLASS (klass); menu_item_class = GTK_MENU_ITEM_CLASS (klass); gobject_class->finalize = ido_calendar_menu_item_finalize; widget_class->button_release_event = ido_calendar_menu_item_button_release; widget_class->button_press_event = ido_calendar_menu_item_button_press; menu_item_class->select = ido_calendar_menu_item_select; menu_item_class->deselect = ido_calendar_menu_item_deselect; menu_item_class->hide_on_activate = TRUE; g_signal_new("month-changed", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); g_signal_new("day-selected", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); g_signal_new("day-selected-double-click", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } static void ido_calendar_menu_item_init (IdoCalendarMenuItem *item) { IdoCalendarMenuItemPrivate *priv = ido_calendar_menu_item_get_instance_private(item); /* Will be disposed automatically */ priv->calendar = g_object_new (gtk_calendar_get_type (), NULL); g_object_add_weak_pointer (G_OBJECT (priv->calendar), (gpointer*) &priv->calendar); g_signal_connect (priv->calendar, "realize", G_CALLBACK (calendar_realized_cb), item); g_signal_connect (priv->calendar, "move-focus", G_CALLBACK (calendar_move_focus_cb), item); priv->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); gtk_box_pack_start (GTK_BOX (priv->box), priv->calendar, TRUE, TRUE, 0); gtk_container_add (GTK_CONTAINER (item), priv->box); gtk_widget_show_all (priv->box); } static void ido_calendar_menu_item_finalize (GObject *object) { IdoCalendarMenuItem *item = IDO_CALENDAR_MENU_ITEM (object); IdoCalendarMenuItemPrivate *priv = ido_calendar_menu_item_get_instance_private(item); if (G_IS_OBJECT (priv->calendar)) { g_object_remove_weak_pointer (G_OBJECT (priv->calendar), (gpointer*) &priv->calendar); g_signal_handlers_disconnect_by_data (priv->calendar, item); } if (G_IS_OBJECT (priv->parent)) { g_object_remove_weak_pointer (G_OBJECT (priv->parent), (gpointer*) &priv->parent); g_signal_handlers_disconnect_by_data (priv->parent, item); } G_OBJECT_CLASS (ido_calendar_menu_item_parent_class)->finalize (object); } static void ido_calendar_menu_item_send_focus_change (GtkWidget *widget, gboolean in) { GdkEvent *event = gdk_event_new (GDK_FOCUS_CHANGE); g_object_ref (widget); if (in) gtk_widget_grab_focus (widget); event->focus_change.type = GDK_FOCUS_CHANGE; event->focus_change.window = g_object_ref (gtk_widget_get_window (widget)); event->focus_change.in = in; gtk_widget_event (widget, event); g_object_notify (G_OBJECT (widget), "has-focus"); g_object_unref (widget); gdk_event_free (event); } static gboolean ido_calendar_menu_item_key_press (GtkWidget *widget, GdkEventKey *event, gpointer data) { IdoCalendarMenuItem *menuitem = IDO_CALENDAR_MENU_ITEM (data); IdoCalendarMenuItemPrivate *priv = ido_calendar_menu_item_get_instance_private(menuitem); g_return_val_if_fail (IDO_IS_CALENDAR_MENU_ITEM (menuitem), FALSE); if (priv->selected) { GtkWidget *calendar = priv->calendar; gtk_widget_event (calendar, ((GdkEvent *)(void*)(event))); if (gtk_widget_get_window (calendar) != NULL) { gdk_window_raise (gtk_widget_get_window (calendar)); } if (!gtk_widget_has_focus (calendar)) { gtk_widget_grab_focus (calendar); } return (event->keyval != GDK_KEY_Return) && (event->keyval != GDK_KEY_Escape); } return FALSE; } static gboolean ido_calendar_menu_item_button_press (GtkWidget *widget, GdkEventButton *event) { IdoCalendarMenuItem *menuitem = IDO_CALENDAR_MENU_ITEM (widget); IdoCalendarMenuItemPrivate *priv = ido_calendar_menu_item_get_instance_private(menuitem); GtkWidget *calendar = priv->calendar; if (event->button == 1) { if (gtk_widget_get_window (calendar) != NULL) { gdk_window_raise (gtk_widget_get_window (calendar)); } if (!gtk_widget_has_focus (calendar)) { gtk_widget_grab_focus (calendar); } GdkEvent * newevent = gdk_event_copy((GdkEvent *)(event)); GList * children = gdk_window_get_children(gtk_widget_get_window(calendar)); GList * child; gint root_x = event->x_root; gint root_y = event->y_root; for (child = children; child != NULL; child = g_list_next(child)) { gint newx, newy; gint winx, winy; GdkWindow * newwindow = (GdkWindow*)child->data; ((GdkEventButton *)newevent)->window = newwindow; gdk_window_get_origin(newwindow, &winx, &winy); newx = root_x - winx; newy = root_y - winy; if (newx >= 0 && newy >= 0 && newx < gdk_window_get_width(newwindow) && newy < gdk_window_get_height(newwindow)) { ((GdkEventButton *)newevent)->x = newx; ((GdkEventButton *)newevent)->y = newy; GTK_WIDGET_GET_CLASS(calendar)->button_press_event(GTK_WIDGET(calendar), (GdkEventButton*)newevent); } } ((GdkEventButton *)newevent)->window = event->window; gdk_event_free(newevent); return TRUE; } return FALSE; } static gboolean ido_calendar_menu_item_button_release (GtkWidget *widget, GdkEventButton *event) { IdoCalendarMenuItem *menuitem = IDO_CALENDAR_MENU_ITEM (widget); IdoCalendarMenuItemPrivate *priv = ido_calendar_menu_item_get_instance_private(menuitem); GtkWidget *calendar = priv->calendar; GTK_WIDGET_GET_CLASS(calendar)->button_release_event(GTK_WIDGET(calendar), event); return TRUE; } static void ido_calendar_menu_item_select (GtkMenuItem *item) { IdoCalendarMenuItem *menuitem = IDO_CALENDAR_MENU_ITEM (item); IdoCalendarMenuItemPrivate *priv = ido_calendar_menu_item_get_instance_private(menuitem); priv->selected = TRUE; ido_calendar_menu_item_send_focus_change (GTK_WIDGET (priv->calendar), TRUE); } static void ido_calendar_menu_item_deselect (GtkMenuItem *item) { IdoCalendarMenuItem *menuitem = IDO_CALENDAR_MENU_ITEM (item); IdoCalendarMenuItemPrivate *priv = ido_calendar_menu_item_get_instance_private(menuitem); priv->selected = FALSE; ido_calendar_menu_item_send_focus_change (GTK_WIDGET (priv->calendar), FALSE); } static void calendar_realized_cb (GtkWidget *widget, IdoCalendarMenuItem *item) { if (gtk_widget_get_window (widget) != NULL) { gdk_window_raise (gtk_widget_get_window (widget)); } IdoCalendarMenuItemPrivate *priv = ido_calendar_menu_item_get_instance_private(item); priv->parent = gtk_widget_get_parent (GTK_WIDGET (item)); g_object_add_weak_pointer (G_OBJECT (priv->parent), (gpointer*) &priv->parent); g_signal_connect (priv->parent, "key-press-event", G_CALLBACK (ido_calendar_menu_item_key_press), item); g_signal_connect (priv->calendar, "month-changed", G_CALLBACK (calendar_month_changed_cb), item); g_signal_connect (priv->calendar, "day-selected", G_CALLBACK (calendar_day_selected_cb), item); g_signal_connect (priv->calendar, "day-selected-double-click", G_CALLBACK (calendar_day_selected_double_click_cb), item); ido_calendar_menu_item_send_focus_change (widget, TRUE); } static void calendar_move_focus_cb (GtkWidget *widget, GtkDirectionType direction, IdoCalendarMenuItem *item) { IdoCalendarMenuItem *menuitem = IDO_CALENDAR_MENU_ITEM (widget); IdoCalendarMenuItemPrivate *priv = ido_calendar_menu_item_get_instance_private(menuitem); ido_calendar_menu_item_send_focus_change (GTK_WIDGET (priv->calendar), FALSE); g_signal_emit_by_name (item, "move-focus", GTK_DIR_TAB_FORWARD); } static void calendar_month_changed_cb (GtkWidget *widget, gpointer user_data) { IdoCalendarMenuItem *item = (IdoCalendarMenuItem *)user_data; g_signal_emit_by_name (item, "month-changed", NULL); } static void calendar_day_selected_cb (GtkWidget *widget, gpointer user_data) { IdoCalendarMenuItem *item = (IdoCalendarMenuItem *)user_data; g_signal_emit_by_name (item, "day-selected", NULL); } static void calendar_day_selected_double_click_cb (GtkWidget *widget, gpointer user_data) { IdoCalendarMenuItem *item = (IdoCalendarMenuItem *)user_data; guint day, month, year; gtk_calendar_get_date (GTK_CALENDAR (widget), &year, &month, &day); g_signal_emit_by_name (item, "day-selected-double-click", NULL); } /** * ido_calendar_menu_item_new: * * Creates a new #IdoCalendarMenuItem * * Return Value: a new #IdoCalendarMenuItem. **/ GtkWidget * ido_calendar_menu_item_new (void) { return g_object_new (IDO_TYPE_CALENDAR_MENU_ITEM, NULL); } /** * ido_calendar_menu_item_get_calendar: * @menuitem: A #IdoCalendarMenuItem * * Returns the calendar associated with this menu item. * * Return Value: (transfer none): The #GtkCalendar used in this item. */ GtkWidget * ido_calendar_menu_item_get_calendar (IdoCalendarMenuItem *menuitem) { g_return_val_if_fail (IDO_IS_CALENDAR_MENU_ITEM (menuitem), NULL); IdoCalendarMenuItemPrivate *priv = ido_calendar_menu_item_get_instance_private(menuitem); return priv->calendar; } /** * ido_calendar_menu_item_mark_day: * @menuitem: A #IdoCalendarMenuItem * @day: the day number to unmark between 1 and 31. * * Places a visual marker on a particular day. * * Return Value: #TRUE */ gboolean ido_calendar_menu_item_mark_day (IdoCalendarMenuItem *menuitem, guint day) { g_return_val_if_fail(IDO_IS_CALENDAR_MENU_ITEM(menuitem), FALSE); IdoCalendarMenuItemPrivate *priv = ido_calendar_menu_item_get_instance_private(menuitem); gtk_calendar_mark_day(GTK_CALENDAR (priv->calendar), day); return TRUE; } /** * ido_calendar_menu_item_unmark_day: * @menuitem: A #IdoCalendarMenuItem * @day: the day number to unmark between 1 and 31. * * Removes the visual marker from a particular day. * * Return Value: #TRUE */ gboolean ido_calendar_menu_item_unmark_day (IdoCalendarMenuItem *menuitem, guint day) { g_return_val_if_fail(IDO_IS_CALENDAR_MENU_ITEM(menuitem), FALSE); IdoCalendarMenuItemPrivate *priv = ido_calendar_menu_item_get_instance_private(menuitem); gtk_calendar_unmark_day(GTK_CALENDAR (priv->calendar), day); return TRUE; } /** * ido_calendar_menu_item_clear_marks: * @menuitem: A #IdoCalendarMenuItem * * Remove all visual markers. */ void ido_calendar_menu_item_clear_marks (IdoCalendarMenuItem *menuitem) { g_return_if_fail(IDO_IS_CALENDAR_MENU_ITEM(menuitem)); IdoCalendarMenuItemPrivate *priv = ido_calendar_menu_item_get_instance_private(menuitem); gtk_calendar_clear_marks(GTK_CALENDAR (priv->calendar)); } /** * ido_calendar_menu_item_set_display_options: * @menuitem: A #IdoCalendarMenuItem * @flags: the display options to set * * Set the display options for the calendar. */ void ido_calendar_menu_item_set_display_options (IdoCalendarMenuItem *menuitem, GtkCalendarDisplayOptions flags) { g_return_if_fail(IDO_IS_CALENDAR_MENU_ITEM(menuitem)); IdoCalendarMenuItemPrivate *priv = ido_calendar_menu_item_get_instance_private(menuitem); gtk_calendar_set_display_options (GTK_CALENDAR (priv->calendar), flags); } /** * ido_calendar_menu_item_get_display_options: * @menuitem: A #IdoCalendarMenuItem * * Get the display options for the calendar. * * Return Value: the display options in use */ GtkCalendarDisplayOptions ido_calendar_menu_item_get_display_options (IdoCalendarMenuItem *menuitem) { g_return_val_if_fail(IDO_IS_CALENDAR_MENU_ITEM(menuitem), 0); IdoCalendarMenuItemPrivate *priv = ido_calendar_menu_item_get_instance_private(menuitem); return gtk_calendar_get_display_options (GTK_CALENDAR (priv->calendar)); } /** * ido_calendar_menu_item_get_date: * @menuitem: A #IdoCalendarMenuItem * @year: (out) (allow-none): location to store the year as a decimal number (e.g. 2011), or #NULL. * @month: (out) (allow-none): location to store the month number (between 0 and 11), or #NULL. * @day: (out) (allow-none): location to store the day number (between 1 and 31), or #NULL. * * Gets the selected date. */ void ido_calendar_menu_item_get_date (IdoCalendarMenuItem *menuitem, guint *year, guint *month, guint *day) { g_return_if_fail(IDO_IS_CALENDAR_MENU_ITEM(menuitem)); IdoCalendarMenuItemPrivate *priv = ido_calendar_menu_item_get_instance_private(menuitem); gtk_calendar_get_date (GTK_CALENDAR (priv->calendar), year, month, day); } /** * ido_calendar_menu_item_set_date: * @menuitem: A #IdoCalendarMenuItem * @year: the year to show (e.g. 2011). * @month: a month number (between 0 and 11). * @day: The day number (between 1 and 31). * * Set the date shown on the calendar. * * Return Value: #TRUE */ gboolean ido_calendar_menu_item_set_date (IdoCalendarMenuItem *menuitem, guint year, guint month, guint day) { guint old_y, old_m, old_d; g_return_val_if_fail (IDO_IS_CALENDAR_MENU_ITEM(menuitem), FALSE); IdoCalendarMenuItemPrivate *priv = ido_calendar_menu_item_get_instance_private(menuitem); ido_calendar_menu_item_get_date (menuitem, &old_y, &old_m, &old_d); if ((old_y != year) || (old_m != month)) gtk_calendar_select_month (GTK_CALENDAR (priv->calendar), month, year); if (old_d != day) gtk_calendar_select_day (GTK_CALENDAR (priv->calendar), day); return TRUE; } /*** **** **** **** ***/ static void activate_current_day (IdoCalendarMenuItem * ido_calendar, const char * action_name_key) { GObject * o; const char * action_name; GActionGroup * action_group; o = G_OBJECT (ido_calendar); action_name = g_object_get_data (o, action_name_key); action_group = g_object_get_data (o, "ido-action-group"); if (action_group && action_name) { guint y, m, d; GDateTime * date_time; GVariant * target; ido_calendar_menu_item_get_date (ido_calendar, &y, &m, &d); m++; date_time = g_date_time_new_local (y, m, d, 9, 0, 0); target = g_variant_new_int64 (g_date_time_to_unix (date_time)); g_action_group_activate_action (action_group, action_name, target); g_date_time_unref (date_time); } } static void on_day_selected (IdoCalendarMenuItem * ido_calendar) { activate_current_day (ido_calendar, "ido-selection-action-name"); } static void on_day_double_clicked (IdoCalendarMenuItem * ido_calendar) { activate_current_day (ido_calendar, "ido-activation-action-name"); } static void on_action_state_changed (IdoActionHelper * helper, GVariant * state, gpointer unused G_GNUC_UNUSED) { GVariant * v; const char * key; IdoCalendarMenuItem * ido_calendar; ido_calendar = IDO_CALENDAR_MENU_ITEM (ido_action_helper_get_widget (helper)); g_return_if_fail (ido_calendar != NULL); g_return_if_fail (g_variant_is_of_type (state, G_VARIANT_TYPE_DICTIONARY)); /* an int64 representing a time_t indicating which year and month should be visible in the calendar and which day should be given the cursor. */ key = "calendar-day"; if ((v = g_variant_lookup_value (state, key, G_VARIANT_TYPE_INT64))) { int y, m, d; time_t t; GDateTime * date_time; t = g_variant_get_int64 (v); date_time = g_date_time_new_from_unix_local (t); g_date_time_get_ymd (date_time, &y, &m, &d); m--; /* adjust month from GDateTime (1 based) to GtkCalendar (0 based) */ ido_calendar_menu_item_set_date (ido_calendar, y, m, d); g_date_time_unref (date_time); g_variant_unref (v); } /* a boolean value of whether or not to show the week numbers */ key = "show-week-numbers"; if ((v = g_variant_lookup_value (state, key, G_VARIANT_TYPE_BOOLEAN))) { const GtkCalendarDisplayOptions old_flags = ido_calendar_menu_item_get_display_options (ido_calendar); GtkCalendarDisplayOptions new_flags = old_flags; if (g_variant_get_boolean (v)) new_flags |= GTK_CALENDAR_SHOW_WEEK_NUMBERS; else new_flags &= ~GTK_CALENDAR_SHOW_WEEK_NUMBERS; if (new_flags != old_flags) ido_calendar_menu_item_set_display_options (ido_calendar, new_flags); g_variant_unref (v); } /* an array of int32 day-of-months denoting days that have appointments */ key = "appointment-days"; ido_calendar_menu_item_clear_marks (ido_calendar); if ((v = g_variant_lookup_value (state, key, G_VARIANT_TYPE("ai")))) { gint32 day; GVariantIter iter; g_variant_iter_init (&iter, v); while (g_variant_iter_next (&iter, "i", &day)) ido_calendar_menu_item_mark_day (ido_calendar, day); g_variant_unref (v); } } GtkMenuItem * ido_calendar_menu_item_new_from_model (GMenuItem * menu_item, GActionGroup * actions) { GObject * o; GtkWidget * calendar; IdoCalendarMenuItem * ido_calendar; gchar * selection_action_name = NULL; gchar * activation_action_name = NULL; /* get the select & activate action names */ g_menu_item_get_attribute (menu_item, "action", "s", &selection_action_name); g_menu_item_get_attribute (menu_item, "activation-action", "s", &activation_action_name); /* remember the action group & action names so that we can poke them when user selects and double-clicks */ ido_calendar = IDO_CALENDAR_MENU_ITEM (ido_calendar_menu_item_new ()); o = G_OBJECT (ido_calendar); g_object_set_data_full (o, "ido-action-group", g_object_ref(actions), g_object_unref); g_object_set_data_full (o, "ido-selection-action-name", selection_action_name, g_free); g_object_set_data_full (o, "ido-activation-action-name", activation_action_name, g_free); calendar = ido_calendar_menu_item_get_calendar (ido_calendar); g_signal_connect_swapped (calendar, "day-selected", G_CALLBACK(on_day_selected), ido_calendar); g_signal_connect_swapped (calendar, "day-selected-double-click", G_CALLBACK(on_day_double_clicked), ido_calendar); /* Use an IdoActionHelper for state updates. Since we have two separate actions for selection & activation, we'll do the activation & targets logic here in ido-calendar */ if (selection_action_name != NULL) { IdoActionHelper * helper; helper = ido_action_helper_new (GTK_WIDGET(ido_calendar), actions, selection_action_name, NULL); g_signal_connect (helper, "action-state-changed", G_CALLBACK (on_action_state_changed), NULL); g_signal_connect_swapped (ido_calendar, "destroy", G_CALLBACK (g_object_unref), helper); } return GTK_MENU_ITEM (ido_calendar); } ayatana-ido-0.10.1/src/idocalendarmenuitem.h0000644000000000000000000000700714471671403015632 0ustar /* * Copyright 2010 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of either or both of the following licenses: * * 1) the GNU Lesser General Public License version 3, as published by the * Free Software Foundation; and/or * 2) the GNU Lesser General Public License version 2.1, as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License version 3 and version 2.1 along with this program. If not, see * * * Authors: * Cody Russell */ #ifndef __IDO_CALENDAR_MENU_ITEM_H__ #define __IDO_CALENDAR_MENU_ITEM_H__ #include G_BEGIN_DECLS #define IDO_TYPE_CALENDAR_MENU_ITEM (ido_calendar_menu_item_get_type ()) #define IDO_CALENDAR_MENU_ITEM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), IDO_TYPE_CALENDAR_MENU_ITEM, IdoCalendarMenuItem)) #define IDO_CALENDAR_MENU_ITEM_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), IDO_TYPE_CALENDAR_MENU_ITEM, IdoCalendarMenuItemClass)) #define IDO_IS_CALENDAR_MENU_ITEM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), IDO_TYPE_CALENDAR_MENU_ITEM)) #define IDO_IS_CALENDAR_MENU_ITEM_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), IDO_TYPE_CALENDAR_MENU_ITEM)) #define IDO_CALENDAR_MENU_ITEM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), IDO_TYPE_CALENDAR_MENU_ITEM, IdoCalendarMenuItemClass)) typedef struct _IdoCalendarMenuItem IdoCalendarMenuItem; typedef struct _IdoCalendarMenuItemClass IdoCalendarMenuItemClass; struct _IdoCalendarMenuItem { GtkMenuItem parent_instance; }; struct _IdoCalendarMenuItemClass { GtkMenuItemClass parent_class; }; GType ido_calendar_menu_item_get_type (void) G_GNUC_CONST; GtkWidget *ido_calendar_menu_item_new (void); GtkWidget *ido_calendar_menu_item_get_calendar (IdoCalendarMenuItem *menuitem); gboolean ido_calendar_menu_item_mark_day (IdoCalendarMenuItem *menuitem, guint day); gboolean ido_calendar_menu_item_unmark_day (IdoCalendarMenuItem *menuitem, guint day); void ido_calendar_menu_item_clear_marks (IdoCalendarMenuItem *menuitem); void ido_calendar_menu_item_set_display_options (IdoCalendarMenuItem *menuitem, GtkCalendarDisplayOptions flags); GtkCalendarDisplayOptions ido_calendar_menu_item_get_display_options (IdoCalendarMenuItem *menuitem); void ido_calendar_menu_item_get_date (IdoCalendarMenuItem *menuitem, guint *year, guint *month, guint *day); gboolean ido_calendar_menu_item_set_date (IdoCalendarMenuItem *menuitem, guint year, guint month, guint day); GtkMenuItem * ido_calendar_menu_item_new_from_model (GMenuItem * menuitem, GActionGroup * actions); G_END_DECLS #endif /* __IDO_CALENDAR_MENU_ITEM_H__ */ ayatana-ido-0.10.1/src/idodetaillabel.c0000644000000000000000000002626014471671403014554 0ustar /* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * Lars Uebernickel */ #include "idodetaillabel.h" #include typedef struct { gchar *text; PangoLayout *layout; gboolean draw_lozenge; } IdoDetailLabelPrivate; enum { PROP_0, PROP_TEXT, NUM_PROPERTIES }; static GParamSpec *properties[NUM_PROPERTIES]; G_DEFINE_TYPE_WITH_PRIVATE (IdoDetailLabel, ido_detail_label, GTK_TYPE_WIDGET) static void ido_detail_label_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { IdoDetailLabel *self = IDO_DETAIL_LABEL (object); IdoDetailLabelPrivate *priv = ido_detail_label_get_instance_private(self); switch (property_id) { case PROP_TEXT: g_value_set_string (value, priv->text); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void ido_detail_label_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { IdoDetailLabel *self = IDO_DETAIL_LABEL (object); switch (property_id) { case PROP_TEXT: ido_detail_label_set_text (self, g_value_get_string (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void ido_detail_label_finalize (GObject *object) { IdoDetailLabelPrivate *priv = ido_detail_label_get_instance_private(IDO_DETAIL_LABEL (object)); g_free (priv->text); G_OBJECT_CLASS (ido_detail_label_parent_class)->finalize (object); } static void ido_detail_label_dispose (GObject *object) { IdoDetailLabelPrivate *priv = ido_detail_label_get_instance_private(IDO_DETAIL_LABEL (object)); g_clear_object (&priv->layout); G_OBJECT_CLASS (ido_detail_label_parent_class)->dispose (object); } static void ido_detail_label_ensure_layout (IdoDetailLabel *label) { IdoDetailLabelPrivate *priv = ido_detail_label_get_instance_private(label); if (priv->layout == NULL) { priv->layout = gtk_widget_create_pango_layout (GTK_WIDGET (label), priv->text); pango_layout_set_alignment (priv->layout, PANGO_ALIGN_CENTER); pango_layout_set_ellipsize (priv->layout, PANGO_ELLIPSIZE_END); pango_layout_set_height (priv->layout, -1); // TODO update layout on "style-updated" and "direction-changed" } } static void cairo_lozenge (cairo_t *cr, double x, double y, double w, double h, double radius) { double x1 = x + w - radius; double x2 = x + radius; double y1 = y + radius; double y2 = y + h - radius; cairo_move_to (cr, x + radius, y); cairo_arc (cr, x1, y1, radius, G_PI * 1.5, G_PI * 2); cairo_arc (cr, x1, y2, radius, 0, G_PI * 0.5); cairo_arc (cr, x2, y2, radius, G_PI * 0.5, G_PI); cairo_arc (cr, x2, y1, radius, G_PI, G_PI * 1.5); } static PangoFontMetrics * gtk_widget_get_font_metrics (GtkWidget *widget, PangoContext *context) { PangoFontDescription *font; PangoFontMetrics *metrics; gtk_style_context_get (gtk_widget_get_style_context (widget), gtk_widget_get_state_flags (widget), "font", &font, NULL); metrics = pango_context_get_metrics (context, font, pango_context_get_language (context)); pango_font_description_free (font); return metrics; } static gint ido_detail_label_get_minimum_text_width (IdoDetailLabel *label) { IdoDetailLabelPrivate *priv = ido_detail_label_get_instance_private(label); PangoContext *context; PangoFontMetrics *metrics; gint char_width; gint w; context = pango_layout_get_context (priv->layout); metrics = gtk_widget_get_font_metrics (GTK_WIDGET (label), context); char_width = pango_font_metrics_get_approximate_digit_width (metrics); w = 2 * char_width / PANGO_SCALE; pango_font_metrics_unref (metrics); return w; } static gboolean ido_detail_label_draw (GtkWidget *widget, cairo_t *cr) { IdoDetailLabel *label = IDO_DETAIL_LABEL (widget); IdoDetailLabelPrivate *priv = ido_detail_label_get_instance_private(label); PangoRectangle extents; GtkAllocation allocation; double x, w, h, radius; GdkRGBA color; if (!priv->text || !*priv->text) return TRUE; gtk_widget_get_allocation (widget, &allocation); ido_detail_label_ensure_layout (IDO_DETAIL_LABEL (widget)); pango_layout_get_extents (priv->layout, NULL, &extents); pango_extents_to_pixels (&extents, NULL); h = MIN (allocation.height, extents.height); radius = floor (h / 2.0); w = MAX (ido_detail_label_get_minimum_text_width (label), extents.width) + 2.0 * radius; x = allocation.width - w; pango_layout_set_width (priv->layout, (allocation.width - 2 * radius) * PANGO_SCALE); pango_layout_get_extents (priv->layout, NULL, &extents); pango_extents_to_pixels (&extents, NULL); gtk_style_context_get_color (gtk_widget_get_style_context (widget), gtk_widget_get_state_flags (widget), &color); gdk_cairo_set_source_rgba (cr, &color); cairo_set_line_width (cr, 1.0); cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD); if (priv->draw_lozenge) cairo_lozenge (cr, x, 0.0, w, h, radius); cairo_move_to (cr, x + radius, (allocation.height - extents.height) / 2.0); pango_cairo_layout_path (cr, priv->layout); cairo_fill (cr); return TRUE; } static void ido_detail_label_get_preferred_width (GtkWidget *widget, gint *minimum, gint *natural) { IdoDetailLabelPrivate *priv = ido_detail_label_get_instance_private(IDO_DETAIL_LABEL (widget)); PangoRectangle extents; double radius; ido_detail_label_ensure_layout (IDO_DETAIL_LABEL (widget)); pango_layout_get_extents (priv->layout, NULL, &extents); pango_extents_to_pixels (&extents, NULL); radius = floor (extents.height / 2.0); *minimum = ido_detail_label_get_minimum_text_width (IDO_DETAIL_LABEL (widget)) + 2.0 * radius; *natural = MAX (*minimum, extents.width + 2.0 * radius); } static void ido_detail_label_get_preferred_height (GtkWidget *widget, gint *minimum, gint *natural) { IdoDetailLabelPrivate *priv = ido_detail_label_get_instance_private(IDO_DETAIL_LABEL (widget)); PangoContext *context; PangoFontMetrics *metrics; PangoRectangle extents; ido_detail_label_ensure_layout (IDO_DETAIL_LABEL (widget)); pango_layout_get_extents (priv->layout, NULL, &extents); pango_extents_to_pixels (&extents, NULL); context = pango_layout_get_context (priv->layout); metrics = gtk_widget_get_font_metrics (widget, context); *minimum = *natural = (pango_font_metrics_get_ascent (metrics) + pango_font_metrics_get_descent (metrics)) / PANGO_SCALE; pango_font_metrics_unref (metrics); } static void ido_detail_label_class_init (IdoDetailLabelClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->get_property = ido_detail_label_get_property; object_class->set_property = ido_detail_label_set_property; object_class->finalize = ido_detail_label_finalize; object_class->dispose = ido_detail_label_dispose; widget_class->draw = ido_detail_label_draw; widget_class->get_preferred_width = ido_detail_label_get_preferred_width; widget_class->get_preferred_height = ido_detail_label_get_preferred_height; properties[PROP_TEXT] = g_param_spec_string ("text", "Text", "The text of the label", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, NUM_PROPERTIES, properties); } static void ido_detail_label_init (IdoDetailLabel *self) { gtk_widget_set_has_window (GTK_WIDGET (self), FALSE); } GtkWidget * ido_detail_label_new (const gchar *label) { return g_object_new (IDO_TYPE_DETAIL_LABEL, "text", label, NULL); } const gchar * ido_detail_label_get_text (IdoDetailLabel *label) { g_return_val_if_fail (IDO_IS_DETAIL_LABEL (label), NULL); IdoDetailLabelPrivate *priv = ido_detail_label_get_instance_private(label); return priv->text; } /* collapse_whitespace: * @str: the source string * * Collapses all occurences of consecutive whitespace charactes in @str * into a single space. * * Returns: (transfer full): a newly-allocated string */ static gchar * collapse_whitespace (const gchar *str) { GString *result; gboolean in_space = FALSE; if (str == NULL) return NULL; result = g_string_new (""); while (*str) { gunichar c = g_utf8_get_char_validated (str, -1); if (c == (gunichar) -1) break; if (!g_unichar_isspace (c)) { g_string_append_unichar (result, c); in_space = FALSE; } else if (!in_space) { g_string_append_c (result, ' '); in_space = TRUE; } str = g_utf8_next_char (str); } return g_string_free (result, FALSE); } static void ido_detail_label_set_text_impl (IdoDetailLabel *label, const gchar *text, gboolean draw_lozenge) { IdoDetailLabelPrivate *priv = ido_detail_label_get_instance_private(label); g_clear_object (&priv->layout); g_free (priv->text); priv->text = g_strdup (text); priv->draw_lozenge = draw_lozenge; g_object_notify_by_pspec (G_OBJECT (label), properties[PROP_TEXT]); gtk_widget_queue_resize (GTK_WIDGET (label)); } void ido_detail_label_set_text (IdoDetailLabel *label, const gchar *text) { gchar *str; g_return_if_fail (IDO_IS_DETAIL_LABEL (label)); str = collapse_whitespace (text); ido_detail_label_set_text_impl (label, str, FALSE); g_free (str); } void ido_detail_label_set_count (IdoDetailLabel *label, gint count) { gchar *text; g_return_if_fail (IDO_IS_DETAIL_LABEL (label)); text = g_strdup_printf ("%d", count); ido_detail_label_set_text_impl (label, text, TRUE); g_free (text); } ayatana-ido-0.10.1/src/idodetaillabel.h0000644000000000000000000000412214471671403014552 0ustar /* * Copyright 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * Lars Uebernickel */ #ifndef __IDO_DETAIL_LABEL_H__ #define __IDO_DETAIL_LABEL_H__ #include #define IDO_TYPE_DETAIL_LABEL (ido_detail_label_get_type()) #define IDO_DETAIL_LABEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), IDO_TYPE_DETAIL_LABEL, IdoDetailLabel)) #define IDO_DETAIL_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), IDO_TYPE_DETAIL_LABEL, IdoDetailLabelClass)) #define IDO_IS_DETAIL_LABEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IDO_TYPE_DETAIL_LABEL)) #define IDO_IS_DETAIL_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), IDO_TYPE_DETAIL_LABEL)) #define IDO_DETAIL_LABEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), IDO_TYPE_DETAIL_LABEL, IdoDetailLabelClass)) typedef struct _IdoDetailLabel IdoDetailLabel; typedef struct _IdoDetailLabelClass IdoDetailLabelClass; struct _IdoDetailLabel { GtkWidget parent; }; struct _IdoDetailLabelClass { GtkWidgetClass parent_class; }; GType ido_detail_label_get_type (void) G_GNUC_CONST; GtkWidget * ido_detail_label_new (const gchar *str); const gchar * ido_detail_label_get_text (IdoDetailLabel *label); void ido_detail_label_set_text (IdoDetailLabel *label, const gchar *text); void ido_detail_label_set_count (IdoDetailLabel *label, gint count); #endif ayatana-ido-0.10.1/src/idoentrymenuitem.c0000644000000000000000000002203614471671403015214 0ustar /* * Copyright 2010 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of either or both of the following licenses: * * 1) the GNU Lesser General Public License version 3, as published by the * Free Software Foundation; and/or * 2) the GNU Lesser General Public License version 2.1, as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License version 3 and version 2.1 along with this program. If not, see * * * Authors: * Cody Russell */ #include #include "idoentrymenuitem.h" static void ido_entry_menu_item_finalize (GObject *item); static void ido_entry_menu_item_select (GtkMenuItem *item); static void ido_entry_menu_item_deselect (GtkMenuItem *item); static gboolean ido_entry_menu_item_button_release (GtkWidget *widget, GdkEventButton *event); static gboolean ido_entry_menu_item_key_press (GtkWidget *widget, GdkEventKey *event, gpointer data); static gboolean ido_entry_menu_item_button_press (GtkWidget *widget, GdkEventButton *event); static void ido_entry_menu_item_send_focus_change (GtkWidget *widget, gboolean in); static void entry_realized_cb (GtkWidget *widget, IdoEntryMenuItem *item); static void entry_move_focus_cb (GtkWidget *widget, GtkDirectionType direction, IdoEntryMenuItem *item); typedef struct { GtkWidget *box; GtkWidget *entry; gboolean selected; } IdoEntryMenuItemPrivate; G_DEFINE_TYPE_WITH_PRIVATE (IdoEntryMenuItem, ido_entry_menu_item, GTK_TYPE_MENU_ITEM) static void ido_entry_menu_item_class_init (IdoEntryMenuItemClass *klass) { GObjectClass *gobject_class; GtkWidgetClass *widget_class; GtkMenuItemClass *menu_item_class; gobject_class = G_OBJECT_CLASS (klass); widget_class = GTK_WIDGET_CLASS (klass); menu_item_class = GTK_MENU_ITEM_CLASS (klass); gobject_class->finalize = ido_entry_menu_item_finalize; widget_class->button_release_event = ido_entry_menu_item_button_release; widget_class->button_press_event = ido_entry_menu_item_button_press; menu_item_class->select = ido_entry_menu_item_select; menu_item_class->deselect = ido_entry_menu_item_deselect; menu_item_class->hide_on_activate = TRUE; } static void ido_entry_menu_item_init (IdoEntryMenuItem *item) { IdoEntryMenuItemPrivate *priv; GtkBorder border; border.left = 4; border.right = 4; border.top = 2; border.bottom = 2; priv = ido_entry_menu_item_get_instance_private(item); priv->entry = g_object_new (gtk_entry_get_type (), "inner-border", &border, NULL); g_signal_connect (priv->entry, "realize", G_CALLBACK (entry_realized_cb), item); g_signal_connect (priv->entry, "move-focus", G_CALLBACK (entry_move_focus_cb), item); priv->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); gtk_box_pack_start (GTK_BOX (priv->box), priv->entry, FALSE, FALSE, 0); gtk_container_add (GTK_CONTAINER (item), priv->box); gtk_widget_show_all (priv->box); } static gboolean is_key_press_valid (IdoEntryMenuItem *item, gint key) { switch (key) { case GDK_KEY_Escape: case GDK_KEY_Up: case GDK_KEY_Down: case GDK_KEY_KP_Up: case GDK_KEY_KP_Down: return FALSE; default: return TRUE; } } static gboolean ido_entry_menu_item_key_press (GtkWidget *widget, GdkEventKey *event, gpointer data) { IdoEntryMenuItem *menuitem = IDO_ENTRY_MENU_ITEM(data); IdoEntryMenuItemPrivate *priv = ido_entry_menu_item_get_instance_private(menuitem); if (priv->selected && is_key_press_valid (menuitem, event->keyval)) { GtkWidget *entry = priv->entry; gtk_widget_event (entry, ((GdkEvent *)(void*)(event))); /* We've handled the event, but if the key was GDK_KEY_Return * we still want to forward the event up to the menu shell * to ensure that the menuitem receives the activate signal. */ return event->keyval != GDK_KEY_Return; } return FALSE; } static void ido_entry_menu_item_send_focus_change (GtkWidget *widget, gboolean in) { GdkEvent *event = gdk_event_new (GDK_FOCUS_CHANGE); g_object_ref (widget); event->focus_change.type = GDK_FOCUS_CHANGE; event->focus_change.window = g_object_ref (gtk_widget_get_window (widget)); event->focus_change.in = in; gtk_widget_event (widget, event); g_object_notify (G_OBJECT (widget), "has-focus"); g_object_unref (widget); gdk_event_free (event); } static gboolean ido_entry_menu_item_button_press (GtkWidget *widget, GdkEventButton *event) { IdoEntryMenuItem *menuitem = IDO_ENTRY_MENU_ITEM(widget); IdoEntryMenuItemPrivate *priv = ido_entry_menu_item_get_instance_private(menuitem); GtkWidget *entry = priv->entry; if (event->button == 1) { if (gtk_widget_get_window (entry) != NULL) { gdk_window_raise (gtk_widget_get_window (entry)); } if (!gtk_widget_has_focus (entry)) { gtk_widget_grab_focus (entry); } gtk_widget_event (entry, ((GdkEvent *)(void*)(event))); return TRUE; } return FALSE; } static gboolean ido_entry_menu_item_button_release (GtkWidget *widget, GdkEventButton *event) { IdoEntryMenuItem *menuitem = IDO_ENTRY_MENU_ITEM(widget); IdoEntryMenuItemPrivate *priv = ido_entry_menu_item_get_instance_private(menuitem); GtkWidget *entry = priv->entry; gtk_widget_event (entry, ((GdkEvent *)(void*)(event))); return TRUE; } static void ido_entry_menu_item_select (GtkMenuItem *item) { IdoEntryMenuItem *menuitem = IDO_ENTRY_MENU_ITEM(item); IdoEntryMenuItemPrivate *priv = ido_entry_menu_item_get_instance_private(menuitem); priv->selected = TRUE; ido_entry_menu_item_send_focus_change (GTK_WIDGET (priv->entry), TRUE); } static void ido_entry_menu_item_deselect (GtkMenuItem *item) { IdoEntryMenuItem *menuitem = IDO_ENTRY_MENU_ITEM(item); IdoEntryMenuItemPrivate *priv = ido_entry_menu_item_get_instance_private(menuitem); priv->selected = FALSE; ido_entry_menu_item_send_focus_change (GTK_WIDGET (priv->entry), FALSE); } static void entry_realized_cb (GtkWidget *widget, IdoEntryMenuItem *item) { if (gtk_widget_get_window (widget) != NULL) { gdk_window_raise (gtk_widget_get_window (widget)); } g_signal_connect (gtk_widget_get_parent (GTK_WIDGET (item)), "key-press-event", G_CALLBACK (ido_entry_menu_item_key_press), item); ido_entry_menu_item_send_focus_change (widget, TRUE); } static void entry_move_focus_cb (GtkWidget *widget, GtkDirectionType direction, IdoEntryMenuItem *item) { IdoEntryMenuItemPrivate *priv = ido_entry_menu_item_get_instance_private(item); ido_entry_menu_item_send_focus_change (GTK_WIDGET (priv->entry), FALSE); g_signal_emit_by_name (item, "move-focus", GTK_DIR_TAB_FORWARD); } /** * ido_entry_menu_item_new: * * Creates a new #IdoEntryMenuItem. * * Return Value: the newly created #IdoEntryMenuItem. */ GtkWidget * ido_entry_menu_item_new (void) { return g_object_new (IDO_TYPE_ENTRY_MENU_ITEM, NULL); } /** * ido_entry_menu_item_get_entry: * @menuitem: The #IdoEntryMenuItem. * * Get the #GtkEntry used in this menu item. * * Return Value: (transfer none): The #GtkEntry inside this menu item. */ GtkWidget * ido_entry_menu_item_get_entry (IdoEntryMenuItem *menuitem) { g_return_val_if_fail (IDO_IS_ENTRY_MENU_ITEM (menuitem), NULL); IdoEntryMenuItemPrivate *priv = ido_entry_menu_item_get_instance_private(menuitem); return priv->entry; } static void ido_entry_menu_item_finalize (GObject *gobject) { /* no-op */ } ayatana-ido-0.10.1/src/idoentrymenuitem.h0000644000000000000000000000423714471671403015224 0ustar /* * Copyright 2010 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of either or both of the following licenses: * * 1) the GNU Lesser General Public License version 3, as published by the * Free Software Foundation; and/or * 2) the GNU Lesser General Public License version 2.1, as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License version 3 and version 2.1 along with this program. If not, see * * * Authors: * Cody Russell */ #ifndef __IDO_ENTRY_MENU_ITEM_H__ #define __IDO_ENTRY_MENU_ITEM_H__ #include G_BEGIN_DECLS #define IDO_TYPE_ENTRY_MENU_ITEM (ido_entry_menu_item_get_type ()) #define IDO_ENTRY_MENU_ITEM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), IDO_TYPE_ENTRY_MENU_ITEM, IdoEntryMenuItem)) #define IDO_ENTRY_MENU_ITEM_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), IDO_TYPE_ENTRY_MENU_ITEM, IdoEntryMenuItemClass)) #define IDO_IS_ENTRY_MENU_ITEM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), IDO_TYPE_ENTRY_MENU_ITEM)) #define IDO_IS_ENTRY_MENU_ITEM_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), IDO_TYPE_ENTRY_MENU_ITEM)) #define IDO_ENTRY_MENU_ITEM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), IDO_TYPE_ENTRY_MENU_ITEM, IdoEntryMenuItemClass)) typedef struct _IdoEntryMenuItem IdoEntryMenuItem; typedef struct _IdoEntryMenuItemClass IdoEntryMenuItemClass; struct _IdoEntryMenuItem { GtkMenuItem parent_instance; }; struct _IdoEntryMenuItemClass { GtkMenuItemClass parent_class; }; GType ido_entry_menu_item_get_type (void) G_GNUC_CONST; GtkWidget *ido_entry_menu_item_new (void); GtkWidget *ido_entry_menu_item_get_entry (IdoEntryMenuItem *menuitem); G_END_DECLS #endif /* __IDO_ENTRY_MENU_ITEM_H__ */ ayatana-ido-0.10.1/src/idolevelmenuitem.c0000644000000000000000000002214614471671403015164 0ustar /* * Copyright 2023 Robert Tari * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Robert Tari */ #include "idolevelmenuitem.h" #include "idoactionhelper.h" enum { PROP_0, PROP_ICON, PROP_TEXT, PROP_LEVEL, PROP_LAST }; static GParamSpec *lProperties[PROP_LAST]; typedef struct { GIcon *pIcon; gchar *sText; GtkWidget *pLabel; GtkWidget *pImage; GtkWidget *pLevelBar; IdoActionHelper *pHelper; } IdoLevelMenuItemPrivate; static GParamSpec *lProperties[PROP_LAST]; G_DEFINE_TYPE_WITH_PRIVATE (IdoLevelMenuItem, ido_level_menu_item, GTK_TYPE_MENU_ITEM) static void onGetProperty (GObject *pObject, guint nProperty, GValue *pValue, GParamSpec *pParamSpec) { IdoLevelMenuItem *self = IDO_LEVEL_MENU_ITEM (pObject); IdoLevelMenuItemPrivate *pPrivate = ido_level_menu_item_get_instance_private (self); switch (nProperty) { case PROP_ICON: { g_value_set_object (pValue, pPrivate->pIcon); break; } case PROP_TEXT: { g_value_set_string (pValue, pPrivate->sText); break; } case PROP_LEVEL: { guint16 nLevel = (guint16) gtk_level_bar_get_value (GTK_LEVEL_BAR (pPrivate->pLevelBar)); g_value_set_uint (pValue, (guint16) nLevel); break; } default: { G_OBJECT_WARN_INVALID_PROPERTY_ID (pObject, nProperty, pParamSpec); break; } } } static void onSetProperty (GObject *pObject, guint nProperty, const GValue *pValue, GParamSpec *pParamSpec) { IdoLevelMenuItem *self = IDO_LEVEL_MENU_ITEM(pObject); switch (nProperty) { case PROP_ICON: { idoLevelMenuItemSetIcon (self, g_value_get_object (pValue)); break; } case PROP_TEXT: { idoLevelMenuItemSetText (self, g_value_get_string (pValue)); break; } case PROP_LEVEL: { idoLevelMenuItemSetLevel (self, g_value_get_uint (pValue)); break; } default: { G_OBJECT_WARN_INVALID_PROPERTY_ID (pObject, nProperty, pParamSpec); break; } } } static void onDispose (GObject *pObject) { IdoLevelMenuItem *self = IDO_LEVEL_MENU_ITEM (pObject); IdoLevelMenuItemPrivate *pPrivate = ido_level_menu_item_get_instance_private (self); g_clear_object (&pPrivate->pIcon); G_OBJECT_CLASS (ido_level_menu_item_parent_class)->dispose(pObject); } static void onFinalize(GObject *pObject) { IdoLevelMenuItem *self = IDO_LEVEL_MENU_ITEM (pObject); IdoLevelMenuItemPrivate *pPrivate = ido_level_menu_item_get_instance_private (self); g_free (pPrivate->sText); G_OBJECT_CLASS (ido_level_menu_item_parent_class)->finalize (pObject); } static void idoLevelMenuItemStyleUpdateImage (IdoLevelMenuItem *self) { IdoLevelMenuItemPrivate *pPrivate = ido_level_menu_item_get_instance_private (self); gtk_image_clear (GTK_IMAGE (pPrivate->pImage)); if (pPrivate->pIcon == NULL) { gtk_widget_set_visible (pPrivate->pImage, FALSE); } else { gtk_image_set_from_gicon (GTK_IMAGE (pPrivate->pImage), pPrivate->pIcon, GTK_ICON_SIZE_MENU); gtk_widget_set_visible (pPrivate->pImage, TRUE); } } static void onStyleUpdated (GtkWidget *pWidget) { GTK_WIDGET_CLASS (ido_level_menu_item_parent_class)->style_updated (pWidget); idoLevelMenuItemStyleUpdateImage (IDO_LEVEL_MENU_ITEM (pWidget)); gtk_widget_queue_draw (pWidget); } static void onActivate (GtkMenuItem *item, gpointer pData) { IdoActionHelper *pHelper = pData; ido_action_helper_activate (pHelper); } static void ido_level_menu_item_class_init (IdoLevelMenuItemClass *klass) { GObjectClass *pObject = G_OBJECT_CLASS (klass); GtkWidgetClass *pWidget = GTK_WIDGET_CLASS (klass); pObject->get_property = onGetProperty; pObject->set_property = onSetProperty; pObject->dispose = onDispose; pObject->finalize = onFinalize; pWidget->style_updated = onStyleUpdated; GParamFlags nParamFlags = G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS; lProperties[PROP_ICON] = g_param_spec_object ("icon", "Icon", "The menuitem's GIcon", G_TYPE_OBJECT, nParamFlags); lProperties[PROP_TEXT] = g_param_spec_string ("text", "Text", "The menuitem's text", "", nParamFlags); lProperties[PROP_LEVEL] = g_param_spec_uint ("level", "Level", "The menuitem's level bar value", 0, 100, 0, nParamFlags); g_object_class_install_properties(pObject, PROP_LAST, lProperties); } static void ido_level_menu_item_init (IdoLevelMenuItem *self) { IdoLevelMenuItemPrivate *pPrivate = ido_level_menu_item_get_instance_private (self); pPrivate->pHelper = NULL; pPrivate->pImage = gtk_image_new(); pPrivate->pLabel = gtk_label_new(""); pPrivate->pLevelBar = gtk_level_bar_new_for_interval (0.0, 100.0); gtk_level_bar_add_offset_value (GTK_LEVEL_BAR (pPrivate->pLevelBar), GTK_LEVEL_BAR_OFFSET_LOW, 20.0); gtk_level_bar_add_offset_value (GTK_LEVEL_BAR (pPrivate->pLevelBar), GTK_LEVEL_BAR_OFFSET_HIGH, 90.0); gtk_level_bar_add_offset_value (GTK_LEVEL_BAR (pPrivate->pLevelBar), GTK_LEVEL_BAR_OFFSET_FULL, 100.0); GtkWidget *pGrid = gtk_grid_new (); gtk_grid_attach (GTK_GRID (pGrid), pPrivate->pImage, 0, 0, 1, 2); gtk_grid_attach (GTK_GRID (pGrid), pPrivate->pLabel, 1, 0, 1, 1); gtk_grid_attach (GTK_GRID (pGrid), pPrivate->pLevelBar, 1, 1, 1, 1); g_object_set (pPrivate->pImage, "halign", GTK_ALIGN_START, "hexpand", FALSE, "valign", GTK_ALIGN_START, "margin-right", 6, NULL); g_object_set (pPrivate->pLabel, "halign", GTK_ALIGN_START, "hexpand", TRUE, "valign", GTK_ALIGN_CENTER, NULL); gtk_widget_show_all (pGrid); gtk_container_add (GTK_CONTAINER(self), pGrid); } GtkWidget* ido_level_menu_item_new () { return GTK_WIDGET (g_object_new (IDO_TYPE_LEVEL_MENU_ITEM, NULL)); } void idoLevelMenuItemSetIcon (IdoLevelMenuItem *self, GIcon *pIcon) { IdoLevelMenuItemPrivate *pPrivate = ido_level_menu_item_get_instance_private (self); if (pPrivate->pIcon != pIcon) { if (pPrivate->pIcon) { g_object_unref (pPrivate->pIcon); } pPrivate->pIcon = pIcon ? g_object_ref (pIcon) : NULL; idoLevelMenuItemStyleUpdateImage (self); } } void idoLevelMenuItemSetText (IdoLevelMenuItem *self, const char *sText) { IdoLevelMenuItemPrivate *pPrivate = ido_level_menu_item_get_instance_private (self); if (g_strcmp0(pPrivate->sText, sText)) { g_free (pPrivate->sText); pPrivate->sText = g_strdup (sText); g_object_set (G_OBJECT (pPrivate->pLabel), "label", pPrivate->sText, "visible", (gboolean)(pPrivate->sText && *pPrivate->sText), NULL); } } void idoLevelMenuItemSetLevel (IdoLevelMenuItem *self, guint16 nLevel) { IdoLevelMenuItemPrivate *pPrivate = ido_level_menu_item_get_instance_private (self); gtk_level_bar_set_value (GTK_LEVEL_BAR (pPrivate->pLevelBar), (gdouble)nLevel); } GtkMenuItem* ido_level_menu_item_new_from_model (GMenuItem *pMenuItem, GActionGroup *pActionGroup) { GtkWidget *pItem = ido_level_menu_item_new (); IdoLevelMenuItemPrivate *pPrivate = ido_level_menu_item_get_instance_private (IDO_LEVEL_MENU_ITEM (pItem)); gchar *sLabel; if (g_menu_item_get_attribute (pMenuItem, "label", "s", &sLabel)) { idoLevelMenuItemSetText (IDO_LEVEL_MENU_ITEM (pItem), sLabel); g_free (sLabel); } GVariant *sIcon = g_menu_item_get_attribute_value (pMenuItem, "icon", NULL); if (sIcon) { GIcon *pIcon = g_icon_deserialize (sIcon); idoLevelMenuItemSetIcon (IDO_LEVEL_MENU_ITEM (pItem), pIcon); g_object_unref (pIcon); g_variant_unref (sIcon); } guint16 nProgress = 0; if (g_menu_item_get_attribute (pMenuItem, "x-ayatana-level", "q", &nProgress)) { idoLevelMenuItemSetLevel (IDO_LEVEL_MENU_ITEM (pItem), nProgress); } gchar *sAction; if (g_menu_item_get_attribute (pMenuItem, "action", "s", &sAction)) { GVariant *sTarget = g_menu_item_get_attribute_value (pMenuItem, "target", NULL); pPrivate->pHelper = ido_action_helper_new (pItem, pActionGroup, sAction, sTarget); g_signal_connect_object (pItem, "activate", G_CALLBACK (onActivate), pPrivate->pHelper, 0); g_signal_connect_swapped (pItem, "destroy", G_CALLBACK (g_object_unref), pPrivate->pHelper); if (sTarget) { g_variant_unref (sTarget); } g_free (sAction); } return GTK_MENU_ITEM (pItem); } ayatana-ido-0.10.1/src/idolevelmenuitem.h0000644000000000000000000000332414471671403015166 0ustar /* * Copyright 2023 Robert Tari * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Robert Tari */ #ifndef __IDO_LEVEL_MENU_ITEM_H__ #define __IDO_LEVEL_MENU_ITEM_H__ #include G_BEGIN_DECLS #define IDO_TYPE_LEVEL_MENU_ITEM (ido_level_menu_item_get_type ()) #define IDO_LEVEL_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), IDO_TYPE_LEVEL_MENU_ITEM, IdoLevelMenuItem)) #define IDO_IS_LEVEL_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IDO_TYPE_LEVEL_MENU_ITEM)) typedef struct _IdoLevelMenuItem IdoLevelMenuItem; typedef struct _IdoLevelMenuItemClass IdoLevelMenuItemClass; struct _IdoLevelMenuItemClass { GtkMenuItemClass parent_class; }; struct _IdoLevelMenuItem { GtkMenuItem parent; }; GType ido_level_menu_item_get_type (void) G_GNUC_CONST; GtkWidget* ido_level_menu_item_new (); GtkMenuItem* ido_level_menu_item_new_from_model (GMenuItem *pMenuItem, GActionGroup *pActionGroup); void idoLevelMenuItemSetIcon (IdoLevelMenuItem *self, GIcon *pIcon); void idoLevelMenuItemSetText (IdoLevelMenuItem *self, const char *sText); void idoLevelMenuItemSetLevel (IdoLevelMenuItem *self, guint16 nLevel); G_END_DECLS #endif ayatana-ido-0.10.1/src/idolocationmenuitem.c0000644000000000000000000002345714471671403015673 0ustar /* * Copyright 2013 Canonical Ltd. * Copyright 2023 Robert Tari * * Authors: * Charles Kerr * Robert Tari * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include /* strstr() */ #include #include "idoactionhelper.h" #include "idolocationmenuitem.h" enum { PROP_0, PROP_TIMEZONE, PROP_LAST }; static GParamSpec *properties[PROP_LAST]; typedef struct { char * timezone; guint timestamp_timer; } IdoLocationMenuItemPrivate; G_DEFINE_TYPE_WITH_PRIVATE (IdoLocationMenuItem, ido_location_menu_item, IDO_TYPE_TIME_STAMP_MENU_ITEM); /*** **** Timestamp Label ***/ static void update_timestamp (IdoLocationMenuItem * self) { GTimeZone * tz; GDateTime * date_time; IdoLocationMenuItemPrivate * priv = ido_location_menu_item_get_instance_private(self); #if GLIB_CHECK_VERSION(2, 68, 0) tz = g_time_zone_new_identifier (priv->timezone); #else tz = g_time_zone_new (priv->timezone); #endif if (tz == NULL) tz = g_time_zone_new_local (); date_time = g_date_time_new_now (tz); ido_time_stamp_menu_item_set_date_time (IDO_TIME_STAMP_MENU_ITEM(self), date_time); g_date_time_unref (date_time); g_time_zone_unref (tz); } static void stop_timestamp_timer (IdoLocationMenuItem * self) { IdoLocationMenuItemPrivate * p = ido_location_menu_item_get_instance_private(self); if (p->timestamp_timer != 0) { g_source_remove (p->timestamp_timer); p->timestamp_timer = 0; } } static void restart_timestamp_timer (IdoLocationMenuItem * self); static gboolean on_timestamp_timer (gpointer gself) { IdoLocationMenuItem * self = IDO_LOCATION_MENU_ITEM (gself); update_timestamp (self); restart_timestamp_timer (self); return G_SOURCE_REMOVE; } static guint calculate_seconds_until_next_minute (void) { guint seconds; GTimeSpan diff; GDateTime * now; GDateTime * next; GDateTime * start_of_next; now = g_date_time_new_now_local (); next = g_date_time_add_minutes (now, 1); start_of_next = g_date_time_new_local (g_date_time_get_year (next), g_date_time_get_month (next), g_date_time_get_day_of_month (next), g_date_time_get_hour (next), g_date_time_get_minute (next), 1); diff = g_date_time_difference (start_of_next, now); seconds = (diff + (G_TIME_SPAN_SECOND - 1)) / G_TIME_SPAN_SECOND; /* cleanup */ g_date_time_unref (start_of_next); g_date_time_unref (next); g_date_time_unref (now); return seconds; } static void restart_timestamp_timer (IdoLocationMenuItem * self) { const char * fmt = ido_time_stamp_menu_item_get_format (IDO_TIME_STAMP_MENU_ITEM (self)); gboolean timestamp_shows_seconds; int interval_sec; IdoLocationMenuItemPrivate * priv = ido_location_menu_item_get_instance_private(self); stop_timestamp_timer (self); timestamp_shows_seconds = fmt && (strstr(fmt,"%s") || strstr(fmt,"%S") || strstr(fmt,"%T") || strstr(fmt,"%X") || strstr(fmt,"%c")); if (timestamp_shows_seconds) interval_sec = 1; else interval_sec = calculate_seconds_until_next_minute(); priv->timestamp_timer = g_timeout_add_seconds (interval_sec, on_timestamp_timer, self); } /*** **** GObject Virtual Functions ***/ static void my_get_property (GObject * o, guint property_id, GValue * value, GParamSpec * pspec) { IdoLocationMenuItem * self = IDO_LOCATION_MENU_ITEM (o); IdoLocationMenuItemPrivate * p = ido_location_menu_item_get_instance_private(self); switch (property_id) { case PROP_TIMEZONE: g_value_set_string (value, p->timezone); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec); break; } } static void my_set_property (GObject * o, guint property_id, const GValue * value, GParamSpec * pspec) { IdoLocationMenuItem * self = IDO_LOCATION_MENU_ITEM (o); switch (property_id) { case PROP_TIMEZONE: ido_location_menu_item_set_timezone (self, g_value_get_string (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec); break; } } static void my_dispose (GObject * object) { stop_timestamp_timer (IDO_LOCATION_MENU_ITEM (object)); G_OBJECT_CLASS (ido_location_menu_item_parent_class)->dispose (object); } static void my_finalize (GObject * object) { IdoLocationMenuItem * self = IDO_LOCATION_MENU_ITEM (object); IdoLocationMenuItemPrivate * priv = ido_location_menu_item_get_instance_private(self); g_free (priv->timezone); G_OBJECT_CLASS (ido_location_menu_item_parent_class)->finalize (object); } /*** **** Instantiation ***/ static void ido_location_menu_item_class_init (IdoLocationMenuItemClass *klass) { GObjectClass * gobject_class = G_OBJECT_CLASS (klass); gobject_class->get_property = my_get_property; gobject_class->set_property = my_set_property; gobject_class->dispose = my_dispose; gobject_class->finalize = my_finalize; properties[PROP_TIMEZONE] = g_param_spec_string ( "timezone", "timezone identifier", "string used to identify a timezone; eg, 'America/Chicago'", NULL, G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (gobject_class, PROP_LAST, properties); } static void ido_location_menu_item_init (IdoLocationMenuItem *self) { /* Update the timer whenever the format string changes because it determines whether we update once per second or per minute */ g_signal_connect (self, "notify::format", G_CALLBACK(restart_timestamp_timer), NULL); } /*** **** Public API ***/ /* create a new IdoLocationMenuItemType */ GtkWidget * ido_location_menu_item_new (void) { return GTK_WIDGET (g_object_new (IDO_LOCATION_MENU_ITEM_TYPE, NULL)); } /** * ido_location_menu_item_set_timezone: * @timezone: timezone identifier (eg: "America/Chicago") * * Set this location's timezone. This will be used to show the location's * current time in menuitem's right-justified secondary label. */ void ido_location_menu_item_set_timezone (IdoLocationMenuItem * self, const char * timezone) { IdoLocationMenuItemPrivate * p; g_return_if_fail (IDO_IS_LOCATION_MENU_ITEM (self)); p = ido_location_menu_item_get_instance_private(self); g_free (p->timezone); p->timezone = g_strdup (timezone); update_timestamp (self); } /** * ido_location_menu_item_new_from_model: * @menu_item: the corresponding menuitem * @actions: action group to tell when this GtkMenuItem is activated * * Creates a new IdoLocationMenuItem with properties initialized from * the menuitem's attributes. * * If the menuitem's 'action' attribute is set, trigger that action * in @actions when this IdoLocationMenuItem is activated. */ GtkMenuItem * ido_location_menu_item_new_from_model (GMenuItem * menu_item, GActionGroup * actions) { guint i; guint n; gchar * str; IdoLocationMenuItem * ido_location; const gchar * names[3]; GValue * values; const guint n_max = 3; /* create the ido_location */ n = 0; values = g_new0(GValue, n_max); if (g_menu_item_get_attribute (menu_item, "label", "s", &str)) { names[n] = "text"; g_value_init (&values[n], G_TYPE_STRING); g_value_take_string (&values[n], str); n++; } if (g_menu_item_get_attribute (menu_item, "x-ayatana-timezone", "s", &str)) { names[n] = "timezone"; g_value_init (&values[n], G_TYPE_STRING); g_value_take_string (&values[n], str); n++; } if (g_menu_item_get_attribute (menu_item, "x-ayatana-time-format", "s", &str)) { names[n] = "format"; g_value_init (&values[n], G_TYPE_STRING); g_value_take_string (&values[n], str); n++; } g_assert (n <= G_N_ELEMENTS (names)); g_assert (n <= n_max); ido_location = IDO_LOCATION_MENU_ITEM(g_object_new_with_properties (IDO_LOCATION_MENU_ITEM_TYPE, n, names, values)); for (i=0; i * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #ifndef __IDO_LOCATION_MENU_ITEM_H__ #define __IDO_LOCATION_MENU_ITEM_H__ #include #include "idotimestampmenuitem.h" G_BEGIN_DECLS #define IDO_LOCATION_MENU_ITEM_TYPE (ido_location_menu_item_get_type ()) #define IDO_LOCATION_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), IDO_LOCATION_MENU_ITEM_TYPE, IdoLocationMenuItem)) #define IDO_IS_LOCATION_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IDO_LOCATION_MENU_ITEM_TYPE)) typedef struct _IdoLocationMenuItem IdoLocationMenuItem; typedef struct _IdoLocationMenuItemClass IdoLocationMenuItemClass; struct _IdoLocationMenuItemClass { IdoTimeStampMenuItemClass parent_class; }; /** * A menuitem that indicates a location. * * It contains a primary label giving the location's name and a * right-aligned secondary label showing the location's current time */ struct _IdoLocationMenuItem { /*< private >*/ IdoTimeStampMenuItem parent; }; GType ido_location_menu_item_get_type (void) G_GNUC_CONST; GtkWidget * ido_location_menu_item_new (void); GtkMenuItem * ido_location_menu_item_new_from_model (GMenuItem * menuitem, GActionGroup * actions); void ido_location_menu_item_set_timezone (IdoLocationMenuItem * menuitem, const char * timezone); void ido_location_menu_item_set_format (IdoLocationMenuItem * menuitem, const char * strftime_fmt); G_END_DECLS #endif ayatana-ido-0.10.1/src/idomediaplayermenuitem.c0000644000000000000000000003014514471671403016347 0ustar /* * Copyright 2013 Canonical Ltd. * Copyright 2023 Robert Tari * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * Conor Curran * Mirco Müller * Lars Uebernickel * Robert Tari */ #include "idomediaplayermenuitem.h" #include "idoactionhelper.h" #define ALBUM_ART_SIZE 60 typedef GtkMenuItemClass IdoMediaPlayerMenuItemClass; struct _IdoMediaPlayerMenuItem { GtkMenuItem parent; GCancellable *cancellable; GtkWidget* player_label; GtkWidget* player_icon; GtkWidget* metadata_widget; GtkWidget* album_art; GtkWidget* artist_label; GtkWidget* piece_label; GtkWidget* container_label; gboolean running; }; G_DEFINE_TYPE (IdoMediaPlayerMenuItem, ido_media_player_menu_item, GTK_TYPE_MENU_ITEM); static void ido_media_player_menu_item_dispose (GObject *object) { IdoMediaPlayerMenuItem *self = IDO_MEDIA_PLAYER_MENU_ITEM (object); if (self->cancellable) { g_cancellable_cancel (self->cancellable); g_clear_object (&self->cancellable); } G_OBJECT_CLASS (ido_media_player_menu_item_parent_class)->dispose (object); } static gboolean ido_media_player_menu_item_draw (GtkWidget *widget, cairo_t *cr) { IdoMediaPlayerMenuItem *self = IDO_MEDIA_PLAYER_MENU_ITEM (widget); GTK_WIDGET_CLASS (ido_media_player_menu_item_parent_class)->draw (widget, cr); /* draw a triangle next to the application name if the app is running */ if (self->running) { const int arrow_width = 5; const int half_arrow_height = 4; GdkRGBA color; GtkAllocation allocation; GtkAllocation label_allocation; int x; int y; gtk_style_context_get_color (gtk_widget_get_style_context (widget), gtk_widget_get_state_flags (widget), &color); gtk_widget_get_allocation (widget, &allocation); gtk_widget_get_allocation (self->player_label, &label_allocation); x = allocation.x; y = label_allocation.y - allocation.y + label_allocation.height / 2; cairo_move_to (cr, x, y - half_arrow_height); cairo_line_to (cr, x, y + half_arrow_height); cairo_line_to (cr, x + arrow_width, y); cairo_close_path (cr); gdk_cairo_set_source_rgba (cr, &color); cairo_fill (cr); } return FALSE; } static void ido_media_player_menu_item_class_init (IdoMediaPlayerMenuItemClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); object_class->dispose = ido_media_player_menu_item_dispose; widget_class->draw = ido_media_player_menu_item_draw; } static GtkWidget * track_info_label_new () { GtkWidget *label; label = gtk_label_new (NULL); gtk_label_set_width_chars (GTK_LABEL (label), 25); gtk_label_set_max_width_chars (GTK_LABEL (label), 25); gtk_widget_set_halign(label, GTK_ALIGN_START); gtk_widget_set_valign(label, GTK_ALIGN_CENTER); gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_MIDDLE); return label; } static void ido_media_player_menu_item_init (IdoMediaPlayerMenuItem *self) { GtkWidget *grid; self->cancellable = g_cancellable_new (); self->player_icon = gtk_image_new(); gtk_widget_set_margin_end(self->player_icon, 6); gtk_widget_set_halign (self->player_icon, GTK_ALIGN_START); self->player_label = gtk_label_new (NULL); gtk_widget_set_halign (self->player_label, GTK_ALIGN_START); gtk_widget_set_hexpand (self->player_label, TRUE); self->album_art = gtk_image_new(); gtk_widget_set_size_request (self->album_art, ALBUM_ART_SIZE, ALBUM_ART_SIZE); gtk_widget_set_margin_end(self->album_art, 8); self->artist_label = track_info_label_new (); self->piece_label = track_info_label_new (); self->container_label = track_info_label_new (); gtk_widget_set_vexpand (self->container_label, TRUE); gtk_widget_set_valign (self->container_label, GTK_ALIGN_START); self->metadata_widget = gtk_grid_new (); gtk_grid_attach (GTK_GRID (self->metadata_widget), self->album_art, 0, 0, 1, 4); gtk_grid_attach (GTK_GRID (self->metadata_widget), self->piece_label, 1, 0, 1, 1); gtk_grid_attach (GTK_GRID (self->metadata_widget), self->artist_label, 1, 1, 1, 1); gtk_grid_attach (GTK_GRID (self->metadata_widget), self->container_label, 1, 2, 1, 1); grid = gtk_grid_new (); gtk_grid_set_row_spacing (GTK_GRID (grid), 8); gtk_grid_attach (GTK_GRID (grid), self->player_icon, 0, 0, 1, 1); gtk_grid_attach (GTK_GRID (grid), self->player_label, 1, 0, 1, 1); gtk_grid_attach (GTK_GRID (grid), self->metadata_widget, 0, 1, 2, 1); gtk_container_add (GTK_CONTAINER (self), grid); gtk_widget_show_all (grid); /* hide metadata by defalut (player is not running) */ gtk_widget_hide (self->metadata_widget); } static void ido_media_player_menu_item_set_player_name (IdoMediaPlayerMenuItem *self, const gchar *name) { g_return_if_fail (IDO_IS_MEDIA_PLAYER_MENU_ITEM (self)); gtk_label_set_label (GTK_LABEL (self->player_label), name); } static void ido_media_player_menu_item_set_player_icon (IdoMediaPlayerMenuItem *self, GIcon *icon) { g_return_if_fail (IDO_IS_MEDIA_PLAYER_MENU_ITEM (self)); gtk_image_set_from_gicon (GTK_IMAGE (self->player_icon), icon, GTK_ICON_SIZE_MENU); } static void ido_media_player_menu_item_set_is_running (IdoMediaPlayerMenuItem *self, gboolean running) { g_return_if_fail (IDO_IS_MEDIA_PLAYER_MENU_ITEM (self)); if (self->running != running) { self->running = running; gtk_widget_queue_draw (GTK_WIDGET (self)); } } static void album_art_received (GObject *object, GAsyncResult *result, gpointer user_data) { IdoMediaPlayerMenuItem *self = user_data; GdkPixbuf *pixbuf; GError *error = NULL; pixbuf = gdk_pixbuf_new_from_stream_finish (result, &error); if (pixbuf == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("unable to fetch album art: %s", error->message); g_error_free (error); return; } gtk_image_set_from_pixbuf (GTK_IMAGE (self->album_art), pixbuf); g_object_unref (pixbuf); } static void album_art_file_opened (GObject *object, GAsyncResult *result, gpointer user_data) { IdoMediaPlayerMenuItem *self = user_data; GFileInputStream *input; GError *error = NULL; input = g_file_read_finish (G_FILE (object), result, &error); if (input == NULL) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning ("unable to fetch album art: %s", error->message); g_error_free (error); return; } gdk_pixbuf_new_from_stream_at_scale_async (G_INPUT_STREAM (input), ALBUM_ART_SIZE, ALBUM_ART_SIZE, TRUE, self->cancellable, album_art_received, self); g_object_unref (input); } static void ido_media_player_menu_item_set_album_art (IdoMediaPlayerMenuItem *self, const gchar *url) { GFile *file; g_return_if_fail (IDO_IS_MEDIA_PLAYER_MENU_ITEM (self)); gtk_image_clear (GTK_IMAGE (self->album_art)); if (url == NULL) return; file = g_file_new_for_uri (url); g_file_read_async (file, G_PRIORITY_DEFAULT, self->cancellable, album_art_file_opened, self); g_object_unref (file); } static void gtk_label_set_markup_printf_escaped (GtkLabel *label, const gchar *format, ...) { va_list args; gchar *str; va_start (args, format); str = g_markup_vprintf_escaped (format, args); gtk_label_set_markup (label, str); va_end (args); g_free (str); } static void ido_media_player_menu_item_set_metadata (IdoMediaPlayerMenuItem *self, const gchar *title, const gchar *artist, const gchar *album, const gchar *art_url) { g_return_if_fail (IDO_IS_MEDIA_PLAYER_MENU_ITEM (self)); /* hide if there's no metadata */ if (title == NULL || *title == '\0') { gtk_label_set_label (GTK_LABEL (self->piece_label), NULL); gtk_label_set_label (GTK_LABEL (self->artist_label), NULL); gtk_label_set_label (GTK_LABEL (self->container_label), NULL); ido_media_player_menu_item_set_album_art (self, NULL); gtk_widget_hide (self->metadata_widget); } else { gtk_label_set_markup_printf_escaped (GTK_LABEL (self->piece_label), "%s", title); gtk_label_set_markup_printf_escaped (GTK_LABEL (self->artist_label), "%s", artist); gtk_label_set_markup_printf_escaped (GTK_LABEL (self->container_label), "%s", album); ido_media_player_menu_item_set_album_art (self, art_url); gtk_widget_show (self->metadata_widget); } } static void ido_media_player_menu_item_state_changed (IdoActionHelper *helper, GVariant *state, gpointer user_data) { IdoMediaPlayerMenuItem *widget; gboolean running = FALSE; const gchar *title = NULL; const gchar *artist = NULL; const gchar *album = NULL; const gchar *art_url = NULL; g_variant_lookup (state, "running", "b", &running); g_variant_lookup (state, "title", "&s", &title); g_variant_lookup (state, "artist", "&s", &artist); g_variant_lookup (state, "album", "&s", &album); g_variant_lookup (state, "art-url", "&s", &art_url); widget = IDO_MEDIA_PLAYER_MENU_ITEM (ido_action_helper_get_widget (helper)); ido_media_player_menu_item_set_is_running (widget, running); ido_media_player_menu_item_set_metadata (widget, title, artist, album, art_url); } GtkMenuItem * ido_media_player_menu_item_new_from_model (GMenuItem *menuitem, GActionGroup *actions) { GtkMenuItem *widget; gchar *label; gchar *action; GVariant *v; widget = g_object_new (IDO_TYPE_MEDIA_PLAYER_MENU_ITEM, NULL); if (g_menu_item_get_attribute (menuitem, "label", "s", &label)) { ido_media_player_menu_item_set_player_name (IDO_MEDIA_PLAYER_MENU_ITEM (widget), label); g_free (label); } if ((v = g_menu_item_get_attribute_value (menuitem, "icon", NULL))) { GIcon *icon; icon = g_icon_deserialize (v); if (icon) { ido_media_player_menu_item_set_player_icon (IDO_MEDIA_PLAYER_MENU_ITEM (widget), icon); g_object_unref (icon); } g_variant_unref (v); } if (g_menu_item_get_attribute (menuitem, "action", "s", &action)) { IdoActionHelper *helper; helper = ido_action_helper_new (GTK_WIDGET (widget), actions, action, NULL); g_signal_connect (helper, "action-state-changed", G_CALLBACK (ido_media_player_menu_item_state_changed), NULL); g_signal_connect_object (widget, "activate", G_CALLBACK (ido_action_helper_activate), helper, G_CONNECT_SWAPPED); g_signal_connect_swapped (widget, "destroy", G_CALLBACK (g_object_unref), helper); g_free (action); } return widget; } ayatana-ido-0.10.1/src/idomediaplayermenuitem.h0000644000000000000000000000313414471671403016352 0ustar /* * Copyright 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * Conor Curran * Mirco Müller * Lars Uebernickel */ #ifndef __IDO_MEDIA_PLAYER_MENU_ITEM_H__ #define __IDO_MEDIA_PLAYER_MENU_ITEM_H__ #include G_BEGIN_DECLS #define IDO_TYPE_MEDIA_PLAYER_MENU_ITEM (ido_media_player_menu_item_get_type ()) #define IDO_MEDIA_PLAYER_MENU_ITEM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), IDO_TYPE_MEDIA_PLAYER_MENU_ITEM, IdoMediaPlayerMenuItem)) #define IDO_IS_MEDIA_PLAYER_MENU_ITEM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), IDO_TYPE_MEDIA_PLAYER_MENU_ITEM)) typedef struct _IdoMediaPlayerMenuItem IdoMediaPlayerMenuItem; GType ido_media_player_menu_item_get_type (void); GtkMenuItem * ido_media_player_menu_item_new_from_model (GMenuItem *menuitem, GActionGroup *actions); G_END_DECLS #endif ayatana-ido-0.10.1/src/idomenuitemfactory.c0000644000000000000000000001170714471671403015525 0ustar /* * Copyright 2013 Canonical Ltd. * Copyright 2023 Robert Tari * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * Lars Uebernickel * Robert Tari */ #include #include "ayatanamenuitemfactory.h" #include "idoalarmmenuitem.h" #include "idoappointmentmenuitem.h" #include "idobasicmenuitem.h" #include "idocalendarmenuitem.h" #include "idolocationmenuitem.h" #include "idoscalemenuitem.h" #include "idousermenuitem.h" #include "idomediaplayermenuitem.h" #include "idoplaybackmenuitem.h" #include "idoapplicationmenuitem.h" #include "idosourcemenuitem.h" #include "idoswitchmenuitem.h" #include "idoprogressmenuitem.h" #include "idoremovablemenuitem.h" #include "idolevelmenuitem.h" #define IDO_TYPE_MENU_ITEM_FACTORY (ido_menu_item_factory_get_type ()) #define IDO_MENU_ITEM_FACTORY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), IDO_TYPE_MENU_ITEM_FACTORY, IdoMenuItemFactory)) #define IDO_IS_MENU_ITEM_FACTORY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), IDO_TYPE_MENU_ITEM_FACTORY)) typedef GObject IdoMenuItemFactory; typedef GObjectClass IdoMenuItemFactoryClass; GType ido_menu_item_factory_get_type (void); static void ido_menu_item_factory_interface_init (AyatanaMenuItemFactoryInterface *iface); G_DEFINE_TYPE_WITH_CODE (IdoMenuItemFactory, ido_menu_item_factory, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (AYATANA_TYPE_MENU_ITEM_FACTORY, ido_menu_item_factory_interface_init) g_io_extension_point_implement (AYATANA_MENU_ITEM_FACTORY_EXTENSION_POINT_NAME, g_define_type_id, "ido", 0);) static GtkMenuItem * ido_menu_item_factory_create_menu_item (AyatanaMenuItemFactory *factory, const gchar *type, GMenuItem *menuitem, GActionGroup *actions) { GtkMenuItem *item = NULL; if (g_str_equal (type, "org.ayatana.indicator.user-menu-item")) item = ido_user_menu_item_new_from_model (menuitem, actions); if (g_str_equal (type, "org.ayatana.indicator.guest-menu-item")) item = ido_guest_menu_item_new_from_model (menuitem, actions); else if (g_str_equal (type, "org.ayatana.indicator.calendar")) item = ido_calendar_menu_item_new_from_model (menuitem, actions); else if (g_str_equal (type, "org.ayatana.indicator.location")) item = ido_location_menu_item_new_from_model (menuitem, actions); else if (g_str_equal (type, "org.ayatana.indicator.appointment")) item = ido_appointment_menu_item_new_from_model (menuitem, actions); else if (g_str_equal (type, "org.ayatana.indicator.alarm")) item = ido_alarm_menu_item_new_from_model (menuitem, actions); else if (g_str_equal (type, "org.ayatana.indicator.basic")) item = ido_basic_menu_item_new_from_model (menuitem, actions); else if (g_str_equal (type, "org.ayatana.indicator.progress")) item = ido_progress_menu_item_new_from_model (menuitem, actions); else if (g_str_equal (type, "org.ayatana.indicator.slider")) item = ido_scale_menu_item_new_from_model (menuitem, actions); else if (g_str_equal (type, "org.ayatana.indicator.media-player")) item = ido_media_player_menu_item_new_from_model (menuitem, actions); else if (g_str_equal (type, "org.ayatana.indicator.playback-item")) item = ido_playback_menu_item_new_from_model (menuitem, actions); else if (g_str_equal (type, "org.ayatana.indicator.application")) item = ido_application_menu_item_new_from_model (menuitem, actions); else if (g_str_equal (type, "org.ayatana.indicator.messages.source")) item = ido_source_menu_item_new_from_menu_model (menuitem, actions); else if (g_str_equal (type, "org.ayatana.indicator.switch")) item = ido_switch_menu_item_new_from_menu_model (menuitem, actions); else if (g_str_equal (type, "org.ayatana.indicator.removable")) item = ido_removable_menu_item_new_from_model (menuitem, actions); else if (g_str_equal (type, "org.ayatana.indicator.level")) item = ido_level_menu_item_new_from_model (menuitem, actions); return item; } static void ido_menu_item_factory_class_init (IdoMenuItemFactoryClass *class) { } static void ido_menu_item_factory_interface_init (AyatanaMenuItemFactoryInterface *iface) { iface->create_menu_item = ido_menu_item_factory_create_menu_item; } static void ido_menu_item_factory_init (IdoMenuItemFactory *factory) { } ayatana-ido-0.10.1/src/idoplaybackmenuitem.c0000644000000000000000000013717314471671403015652 0ustar /* * Copyright 2013 Canonical Ltd. * Copyright 2023 Robert Tari * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * Conor Curran * Mirco Müller * Andrea Cimitan * Lars Uebernickel * Robert Tari */ #include "idoplaybackmenuitem.h" #include #include #define RECT_WIDTH 130.0f #define Y 7.0f #define INNER_RADIUS 12.5 #define MIDDLE_RADIUS 13.0f #define OUTER_RADIUS 14.5f #define CIRCLE_RADIUS 21.0f #define PREV_WIDTH 25.0f #define PREV_HEIGHT 17.0f #define NEXT_WIDTH 25.0f //PREV_WIDTH #define NEXT_HEIGHT 17.0f //PREV_HEIGHT #define TRI_WIDTH 11.0f #define TRI_HEIGHT 13.0f #define TRI_OFFSET 6.0f #define PREV_X -2.0f #define PREV_Y 13.0f #define NEXT_X 76.0f //prev_y #define NEXT_Y 13.0f //prev_y #define PAUSE_WIDTH 21.0f #define PAUSE_HEIGHT 27.0f #define BAR_WIDTH 4.5f #define BAR_HEIGHT 24.0f #define BAR_OFFSET 10.0f #define PAUSE_X 41.0f #define PAUSE_Y 7.0f #define PLAY_WIDTH 28.0f #define PLAY_HEIGHT 29.0f #define PLAY_PADDING 5.0f #define INNER_START_SHADE 0.98 #define INNER_END_SHADE 0.98 #define MIDDLE_START_SHADE 1.0 #define MIDDLE_END_SHADE 1.0 #define OUTER_START_SHADE 0.75 #define OUTER_END_SHADE 1.3 #define SHADOW_BUTTON_SHADE 0.8 #define OUTER_PLAY_START_SHADE 0.7 #define OUTER_PLAY_END_SHADE 1.38 #define BUTTON_START_SHADE 1.1 #define BUTTON_END_SHADE 0.9 #define BUTTON_SHADOW_SHADE 0.8 #define INNER_COMPRESSED_START_SHADE 1.0 #define INNER_COMPRESSED_END_SHADE 1.0 typedef enum { STATE_PAUSED, STATE_PLAYING, STATE_LAUNCHING } State; typedef enum { BUTTON_NONE, BUTTON_PREVIOUS, BUTTON_PLAYPAUSE, BUTTON_NEXT, N_BUTTONS } Button; typedef GtkMenuItemClass IdoPlaybackMenuItemClass; struct _IdoPlaybackMenuItem { GtkMenuItem parent; State current_state; Button cur_pushed_button; Button cur_hover_button; gboolean has_focus; gboolean keyboard_activated; /* TRUE if the current button was activated with a key */ GActionGroup *action_group; gchar *button_actions[N_BUTTONS]; }; G_DEFINE_TYPE (IdoPlaybackMenuItem, ido_playback_menu_item, GTK_TYPE_MENU_ITEM); static gboolean ido_playback_menu_item_draw (GtkWidget* button, cairo_t *cr); static void ido_playback_menu_item_dispose (GObject *object) { IdoPlaybackMenuItem *item = IDO_PLAYBACK_MENU_ITEM (object); if (item->action_group) { g_signal_handlers_disconnect_by_data (item->action_group, item); g_clear_object (&item->action_group); } G_OBJECT_CLASS (ido_playback_menu_item_parent_class)->dispose (object); } static void ido_playback_menu_item_finalize (GObject *object) { IdoPlaybackMenuItem *item = IDO_PLAYBACK_MENU_ITEM (object); gint i; for (i = 0; i < N_BUTTONS; i++) g_free (item->button_actions[i]); G_OBJECT_CLASS (ido_playback_menu_item_parent_class)->finalize (object); } static Button ido_playback_menu_item_get_button_at_pos (GtkWidget *item, gint x, gint y) { GtkAllocation alloc; gint left; /* 0 44 86 130 * 5 +------+ * 12 +-----+ +-----+ * |prev play next| * 40 +-----+ +-----+ * 47 +------+ */ gtk_widget_get_allocation (item, &alloc); left = alloc.x + (alloc.width - RECT_WIDTH) / 2; if (x > left && x < left + 44 && y > 12 && y < 40) return BUTTON_PREVIOUS; if (x > left + 44 && x < left + 86 && y > 5 && y < 47) return BUTTON_PLAYPAUSE; if (x > left + 86 && x < left + 130 && y > 12 && y < 40) return BUTTON_NEXT; return BUTTON_NONE; } static gboolean ido_playback_menu_item_parent_key_press_event (GtkWidget *widget, GdkEventKey *event, gpointer user_data) { IdoPlaybackMenuItem *self = user_data; /* only listen to events when the playback menu item is selected */ if (!self->has_focus) return FALSE; switch (event->keyval) { case GDK_KEY_Left: self->cur_pushed_button = BUTTON_PREVIOUS; break; case GDK_KEY_Right: self->cur_pushed_button = BUTTON_NEXT; break; case GDK_KEY_space: if (self->cur_hover_button != BUTTON_NONE) self->cur_pushed_button = self->cur_hover_button; else self->cur_pushed_button = BUTTON_PLAYPAUSE; break; default: self->cur_pushed_button = BUTTON_NONE; } if (self->cur_pushed_button != BUTTON_NONE) { const gchar *action = self->button_actions[self->cur_pushed_button]; if (self->action_group && action) g_action_group_activate_action (self->action_group, action, NULL); self->keyboard_activated = TRUE; gtk_widget_queue_draw (widget); return TRUE; } return FALSE; } static gboolean ido_playback_menu_item_parent_key_release_event (GtkWidget *widget, GdkEventKey *event, gpointer user_data) { IdoPlaybackMenuItem *self = user_data; switch (event->keyval) { case GDK_KEY_Left: case GDK_KEY_Right: case GDK_KEY_space: self->cur_pushed_button = BUTTON_NONE; self->keyboard_activated = FALSE; gtk_widget_queue_draw (widget); break; } return FALSE; } static void ido_playback_menu_item_parent_set (GtkWidget *widget, GtkWidget *old_parent) { GtkWidget *parent; /* Menus don't pass key events to their children. This works around * that by listening to key events on the parent widget. */ if (old_parent) { g_signal_handlers_disconnect_by_func (old_parent, ido_playback_menu_item_parent_key_press_event, widget); g_signal_handlers_disconnect_by_func (old_parent, ido_playback_menu_item_parent_key_release_event, widget); } parent = gtk_widget_get_parent (widget); if (parent) { g_signal_connect (parent, "key-press-event", G_CALLBACK (ido_playback_menu_item_parent_key_press_event), widget); g_signal_connect (parent, "key-release-event", G_CALLBACK (ido_playback_menu_item_parent_key_release_event), widget); } } static void ido_playback_menu_item_select (GtkMenuItem *item) { IdoPlaybackMenuItem *self = IDO_PLAYBACK_MENU_ITEM (item); self->has_focus = TRUE; GTK_MENU_ITEM_CLASS (ido_playback_menu_item_parent_class)->select (item); } static void ido_playback_menu_item_deselect (GtkMenuItem *item) { IdoPlaybackMenuItem *self = IDO_PLAYBACK_MENU_ITEM (item); self->has_focus = FALSE; GTK_MENU_ITEM_CLASS (ido_playback_menu_item_parent_class)->deselect (item); } static gboolean ido_playback_menu_item_button_press_event (GtkWidget *menuitem, GdkEventButton *event) { IdoPlaybackMenuItem *item = IDO_PLAYBACK_MENU_ITEM (menuitem); item->cur_pushed_button = ido_playback_menu_item_get_button_at_pos (menuitem, event->x, event->y); gtk_widget_queue_draw (menuitem); return TRUE; } static gboolean ido_playback_menu_item_button_release_event (GtkWidget *menuitem, GdkEventButton *event) { IdoPlaybackMenuItem *item = IDO_PLAYBACK_MENU_ITEM (menuitem); const gchar *action = item->button_actions[item->cur_pushed_button]; if (item->action_group && action) g_action_group_activate_action (item->action_group, action, NULL); item->cur_pushed_button = BUTTON_NONE; gtk_widget_queue_draw (menuitem); return TRUE; } static gboolean ido_playback_menu_item_motion_notify_event (GtkWidget *menuitem, GdkEventMotion *event) { IdoPlaybackMenuItem *item = IDO_PLAYBACK_MENU_ITEM (menuitem); item->cur_hover_button = ido_playback_menu_item_get_button_at_pos (menuitem, event->x, event->y); gtk_widget_queue_draw (menuitem); return TRUE; } static gboolean ido_playback_menu_item_leave_notify_event (GtkWidget *menuitem, GdkEventCrossing *event) { IdoPlaybackMenuItem *item = IDO_PLAYBACK_MENU_ITEM (menuitem); item->cur_pushed_button = BUTTON_NONE; item->cur_hover_button = BUTTON_NONE; gtk_widget_queue_draw (GTK_WIDGET(menuitem)); return TRUE; } static void ido_playback_menu_item_class_init (IdoPlaybackMenuItemClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GtkMenuItemClass *menuitem_class = GTK_MENU_ITEM_CLASS (klass); gobject_class->dispose = ido_playback_menu_item_dispose; gobject_class->finalize = ido_playback_menu_item_finalize; widget_class->button_press_event = ido_playback_menu_item_button_press_event; widget_class->button_release_event = ido_playback_menu_item_button_release_event; widget_class->motion_notify_event = ido_playback_menu_item_motion_notify_event; widget_class->leave_notify_event = ido_playback_menu_item_leave_notify_event; widget_class->parent_set = ido_playback_menu_item_parent_set; widget_class->draw = ido_playback_menu_item_draw; menuitem_class->select = ido_playback_menu_item_select; menuitem_class->deselect = ido_playback_menu_item_deselect; } static void ido_playback_menu_item_init (IdoPlaybackMenuItem *self) { gtk_widget_set_size_request (GTK_WIDGET (self), 200, 43); } static void ido_playback_menu_item_set_state (IdoPlaybackMenuItem *self, State state) { self->current_state = state; if (self->current_state == STATE_LAUNCHING) gtk_widget_set_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_ACTIVE, FALSE); else gtk_widget_unset_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_ACTIVE); gtk_widget_queue_draw (GTK_WIDGET (self)); } static void ido_playback_menu_item_set_state_from_string (IdoPlaybackMenuItem *self, const gchar *state) { g_return_if_fail (state != NULL); if (g_str_equal (state, "Playing")) ido_playback_menu_item_set_state (self, STATE_PLAYING); else if (g_str_equal (state, "Launching")) ido_playback_menu_item_set_state (self, STATE_LAUNCHING); else /* "Paused" and fallback */ ido_playback_menu_item_set_state (self, STATE_PAUSED); } static void ido_playback_menu_item_action_added (GActionGroup *action_group, const gchar *action_name, gpointer user_data) { IdoPlaybackMenuItem *self = user_data; const gchar *action; action = self->button_actions[BUTTON_PLAYPAUSE]; if (action && g_str_equal (action_name, action)) { GVariant *state; state = g_action_group_get_action_state (action_group, action); if (g_variant_is_of_type (state, G_VARIANT_TYPE_STRING)) ido_playback_menu_item_set_state_from_string (self, g_variant_get_string (state, NULL)); g_variant_unref (state); } } static void ido_playback_menu_item_action_removed (GActionGroup *action_group, const gchar *action_name, gpointer user_data) { IdoPlaybackMenuItem *self = user_data; const gchar *action; action = self->button_actions[BUTTON_PLAYPAUSE]; if (action && g_str_equal (action_name, action)) ido_playback_menu_item_set_state (self, STATE_PAUSED); } static void ido_playback_menu_item_action_state_changed (GActionGroup *action_group, const gchar *action_name, GVariant *value, gpointer user_data) { IdoPlaybackMenuItem *self = user_data; const gchar *action; g_return_if_fail (action_name != NULL); action = self->button_actions[BUTTON_PLAYPAUSE]; if (action && g_str_equal (action_name, action)) { if (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)) ido_playback_menu_item_set_state_from_string (self, g_variant_get_string (value, NULL)); } } GtkMenuItem * ido_playback_menu_item_new_from_model (GMenuItem *item, GActionGroup *actions) { IdoPlaybackMenuItem *widget; gchar *play_action; widget = g_object_new (IDO_TYPE_PLAYBACK_MENU_ITEM, NULL); widget->action_group = g_object_ref (actions); g_signal_connect (actions, "action-state-changed", G_CALLBACK (ido_playback_menu_item_action_state_changed), widget); g_signal_connect (actions, "action-added", G_CALLBACK (ido_playback_menu_item_action_added), widget); g_signal_connect (actions, "action-removed", G_CALLBACK (ido_playback_menu_item_action_removed), widget); g_menu_item_get_attribute (item, "x-ayatana-play-action", "s", &widget->button_actions[BUTTON_PLAYPAUSE]); g_menu_item_get_attribute (item, "x-ayatana-next-action", "s", &widget->button_actions[BUTTON_NEXT]); g_menu_item_get_attribute (item, "x-ayatana-previous-action", "s", &widget->button_actions[BUTTON_PREVIOUS]); play_action = widget->button_actions[BUTTON_PLAYPAUSE]; if (play_action && g_action_group_has_action (actions, play_action)) ido_playback_menu_item_action_added (actions, play_action, widget); return GTK_MENU_ITEM (widget); } /* * Drawing */ static void draw_gradient (cairo_t* cr, double x, double y, double w, double r, double* rgba_start, double* rgba_end) { cairo_pattern_t* pattern = NULL; cairo_move_to (cr, x, y); cairo_line_to (cr, x + w - 2.0f * r, y); cairo_arc (cr, x + w - 2.0f * r, y + r, r, -90.0f * G_PI / 180.0f, 90.0f * G_PI / 180.0f); cairo_line_to (cr, x, y + 2.0f * r); cairo_arc (cr, x, y + r, r, 90.0f * G_PI / 180.0f, 270.0f * G_PI / 180.0f); cairo_close_path (cr); pattern = cairo_pattern_create_linear (x, y, x, y + 2.0f * r); cairo_pattern_add_color_stop_rgba (pattern, 0.0f, rgba_start[0], rgba_start[1], rgba_start[2], rgba_start[3]); cairo_pattern_add_color_stop_rgba (pattern, 1.0f, rgba_end[0], rgba_end[1], rgba_end[2], rgba_end[3]); cairo_set_source (cr, pattern); cairo_fill (cr); cairo_pattern_destroy (pattern); } static void draw_circle (cairo_t* cr, double x, double y, double r, double* rgba_start, double* rgba_end) { cairo_pattern_t* pattern = NULL; cairo_move_to (cr, x, y); cairo_arc (cr, x + r, y + r, r, 0.0f * G_PI / 180.0f, 360.0f * G_PI / 180.0f); pattern = cairo_pattern_create_linear (x, y, x, y + 2.0f * r); cairo_pattern_add_color_stop_rgba (pattern, 0.0f, rgba_start[0], rgba_start[1], rgba_start[2], rgba_start[3]); cairo_pattern_add_color_stop_rgba (pattern, 1.0f, rgba_end[0], rgba_end[1], rgba_end[2], rgba_end[3]); cairo_set_source (cr, pattern); cairo_fill (cr); cairo_pattern_destroy (pattern); } static void _setup (cairo_t** cr, cairo_surface_t** surf, gint width, gint height) { if (!cr || !surf) return; *surf = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); *cr = cairo_create (*surf); cairo_scale (*cr, 1.0f, 1.0f); cairo_set_operator (*cr, CAIRO_OPERATOR_CLEAR); cairo_paint (*cr); cairo_set_operator (*cr, CAIRO_OPERATOR_OVER); } static void _mask_prev (cairo_t* cr, double x, double y, double tri_width, double tri_height, double tri_offset) { if (!cr) return; cairo_move_to (cr, x, y + tri_height / 2.0f); cairo_line_to (cr, x + tri_width, y); cairo_line_to (cr, x + tri_width, y + tri_height); x += tri_offset; cairo_move_to (cr, x, y + tri_height / 2.0f); cairo_line_to (cr, x + tri_width, y); cairo_line_to (cr, x + tri_width, y + tri_height); x -= tri_offset; cairo_rectangle (cr, x, y, 2.5f, tri_height); cairo_close_path (cr); } static void _mask_next (cairo_t* cr, double x, double y, double tri_width, double tri_height, double tri_offset) { if (!cr) return; cairo_move_to (cr, x, y); cairo_line_to (cr, x + tri_width, y + tri_height / 2.0f); cairo_line_to (cr, x, y + tri_height); x += tri_offset; cairo_move_to (cr, x, y); cairo_line_to (cr, x + tri_width, y + tri_height / 2.0f); cairo_line_to (cr, x, y + tri_height); x -= tri_offset; x += 2.0f * tri_width - tri_offset - 1.0f; cairo_rectangle (cr, x, y, 2.5f, tri_height); cairo_close_path (cr); } static void _mask_pause (cairo_t* cr, double x, double y, double bar_width, double bar_height, double bar_offset) { if (!cr) return; cairo_set_line_width (cr, bar_width); cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); x += bar_width; y += bar_width; cairo_move_to (cr, x, y); cairo_line_to (cr, x, y + bar_height); cairo_move_to (cr, x + bar_offset, y); cairo_line_to (cr, x + bar_offset, y + bar_height); } static void _mask_play (cairo_t* cr, double x, double y, double tri_width, double tri_height) { if (!cr) return; cairo_move_to (cr, x, y); cairo_line_to (cr, x + tri_width, y + tri_height / 2.0f); cairo_line_to (cr, x, y + tri_height); cairo_close_path (cr); } static void _fill (cairo_t* cr, double x_start, double y_start, double x_end, double y_end, double* rgba_start, double* rgba_end, gboolean stroke) { cairo_pattern_t* pattern = NULL; if (!cr || !rgba_start || !rgba_end) return; pattern = cairo_pattern_create_linear (x_start, y_start, x_end, y_end); cairo_pattern_add_color_stop_rgba (pattern, 0.0f, rgba_start[0], rgba_start[1], rgba_start[2], rgba_start[3]); cairo_pattern_add_color_stop_rgba (pattern, 1.0f, rgba_end[0], rgba_end[1], rgba_end[2], rgba_end[3]); cairo_set_source (cr, pattern); if (stroke) cairo_stroke (cr); else cairo_fill (cr); cairo_pattern_destroy (pattern); } static void _finalize (cairo_t* cr, cairo_t** cr_surf, cairo_surface_t** surf, double x, double y) { if (!cr || !cr_surf || !surf) return; cairo_set_source_surface (cr, *surf, x, y); cairo_paint (cr); cairo_surface_destroy (*surf); cairo_destroy (*cr_surf); } static void _finalize_repaint (cairo_t* cr, cairo_t** cr_surf, cairo_surface_t** surf, double x, double y, int repaints) { if (!cr || !cr_surf || !surf) return; while (repaints > 0) { cairo_set_source_surface (cr, *surf, x, y); cairo_paint (cr); repaints--; } cairo_surface_destroy (*surf); cairo_destroy (*cr_surf); } static void _color_rgb_to_hls (gdouble *r, gdouble *g, gdouble *b) { gdouble min; gdouble max; gdouble red; gdouble green; gdouble blue; gdouble h = 0; gdouble l; gdouble s; gdouble delta; red = *r; green = *g; blue = *b; if (red > green) { if (red > blue) max = red; else max = blue; if (green < blue) min = green; else min = blue; } else { if (green > blue) max = green; else max = blue; if (red < blue) min = red; else min = blue; } l = (max+min)/2; if (fabs (max-min) < 0.0001) { h = 0; s = 0; } else { if (l <= 0.5) s = (max-min)/(max+min); else s = (max-min)/(2-max-min); delta = (max -min) != 0 ? (max -min) : 1; if(delta == 0) delta = 1; if (red == max) h = (green-blue)/delta; else if (green == max) h = 2+(blue-red)/delta; else if (blue == max) h = 4+(red-green)/delta; h *= 60; if (h < 0.0) h += 360; } *r = h; *g = l; *b = s; } static void _color_hls_to_rgb (gdouble *h, gdouble *l, gdouble *s) { gdouble hue; gdouble lightness; gdouble saturation; gdouble m1, m2; gdouble r, g, b; lightness = *l; saturation = *s; if (lightness <= 0.5) m2 = lightness*(1+saturation); else m2 = lightness+saturation-lightness*saturation; m1 = 2*lightness-m2; if (saturation == 0) { *h = lightness; *l = lightness; *s = lightness; } else { hue = *h+120; while (hue > 360) hue -= 360; while (hue < 0) hue += 360; if (hue < 60) r = m1+(m2-m1)*hue/60; else if (hue < 180) r = m2; else if (hue < 240) r = m1+(m2-m1)*(240-hue)/60; else r = m1; hue = *h; while (hue > 360) hue -= 360; while (hue < 0) hue += 360; if (hue < 60) g = m1+(m2-m1)*hue/60; else if (hue < 180) g = m2; else if (hue < 240) g = m1+(m2-m1)*(240-hue)/60; else g = m1; hue = *h-120; while (hue > 360) hue -= 360; while (hue < 0) hue += 360; if (hue < 60) b = m1+(m2-m1)*hue/60; else if (hue < 180) b = m2; else if (hue < 240) b = m1+(m2-m1)*(240-hue)/60; else b = m1; *h = r; *l = g; *s = b; } } static void _color_shade(const GdkRGBA *a, float k, GdkRGBA *b) { double red; double green; double blue; red = a->red; green = a->green; blue = a->blue; if (k == 1.0) { b->red = red; b->green = green; b->blue = blue; return; } _color_rgb_to_hls (&red, &green, &blue); green *= k; if (green > 1.0) green = 1.0; else if (green < 0.0) green = 0.0; blue *= k; if (blue > 1.0) blue = 1.0; else if (blue < 0.0) blue = 0.0; _color_hls_to_rgb (&red, &green, &blue); b->red = red; b->green = green; b->blue = blue; } static inline void _blurinner (guchar* pixel, gint* zR, gint* zG, gint* zB, gint* zA, gint alpha, gint aprec, gint zprec) { gint R; gint G; gint B; guchar A; R = *pixel; G = *(pixel + 1); B = *(pixel + 2); A = *(pixel + 3); *zR += (alpha * ((R << zprec) - *zR)) >> aprec; *zG += (alpha * ((G << zprec) - *zG)) >> aprec; *zB += (alpha * ((B << zprec) - *zB)) >> aprec; *zA += (alpha * ((A << zprec) - *zA)) >> aprec; *pixel = *zR >> zprec; *(pixel + 1) = *zG >> zprec; *(pixel + 2) = *zB >> zprec; *(pixel + 3) = *zA >> zprec; } static inline void _blurrow (guchar* pixels, gint width, gint height, gint channels, gint line, gint alpha, gint aprec, gint zprec) { gint zR; gint zG; gint zB; gint zA; gint index; guchar* scanline; scanline = &(pixels[line * width * channels]); zR = *scanline << zprec; zG = *(scanline + 1) << zprec; zB = *(scanline + 2) << zprec; zA = *(scanline + 3) << zprec; for (index = 0; index < width; index ++) _blurinner (&scanline[index * channels], &zR, &zG, &zB, &zA, alpha, aprec, zprec); for (index = width - 2; index >= 0; index--) _blurinner (&scanline[index * channels], &zR, &zG, &zB, &zA, alpha, aprec, zprec); } static inline void _blurcol (guchar* pixels, gint width, gint height, gint channels, gint x, gint alpha, gint aprec, gint zprec) { gint zR; gint zG; gint zB; gint zA; gint index; guchar* ptr; ptr = pixels; ptr += x * channels; zR = *((guchar*) ptr ) << zprec; zG = *((guchar*) ptr + 1) << zprec; zB = *((guchar*) ptr + 2) << zprec; zA = *((guchar*) ptr + 3) << zprec; for (index = width; index < (height - 1) * width; index += width) _blurinner ((guchar*) &ptr[index * channels], &zR, &zG, &zB, &zA, alpha, aprec, zprec); for (index = (height - 2) * width; index >= 0; index -= width) _blurinner ((guchar*) &ptr[index * channels], &zR, &zG, &zB, &zA, alpha, aprec, zprec); } static void _expblur (guchar* pixels, gint width, gint height, gint channels, gint radius, gint aprec, gint zprec) { gint alpha; gint row = 0; gint col = 0; if (radius < 1) return; // calculate the alpha such that 90% of // the kernel is within the radius. // (Kernel extends to infinity) alpha = (gint) ((1 << aprec) * (1.0f - expf (-2.3f / (radius + 1.f)))); for (; row < height; row++) _blurrow (pixels, width, height, channels, row, alpha, aprec, zprec); for(; col < width; col++) _blurcol (pixels, width, height, channels, col, alpha, aprec, zprec); return; } static void _surface_blur (cairo_surface_t* surface, guint radius) { guchar* pixels; guint width; guint height; cairo_format_t format; // before we mess with the surface execute any pending drawing cairo_surface_flush (surface); pixels = cairo_image_surface_get_data (surface); width = cairo_image_surface_get_width (surface); height = cairo_image_surface_get_height (surface); format = cairo_image_surface_get_format (surface); switch (format) { case CAIRO_FORMAT_ARGB32: _expblur (pixels, width, height, 4, radius, 16, 7); break; case CAIRO_FORMAT_RGB24: _expblur (pixels, width, height, 3, radius, 16, 7); break; case CAIRO_FORMAT_A8: _expblur (pixels, width, height, 1, radius, 16, 7); break; default : // do nothing break; } // inform cairo we altered the surfaces contents cairo_surface_mark_dirty (surface); } static void get_colour(GtkStyleContext *pStyleContext, GtkStateFlags nState, const gchar *sColour, GdkRGBA *pRGBA) { GdkRGBA *pRGBATmp; gtk_style_context_get(pStyleContext, nState, sColour, &pRGBATmp, NULL); *pRGBA = *pRGBATmp; gdk_rgba_free(pRGBATmp); } static gboolean ido_playback_menu_item_draw (GtkWidget* button, cairo_t *cr) { IdoPlaybackMenuItem *item = IDO_PLAYBACK_MENU_ITEM (button); GtkAllocation alloc; gint X; gint abs_pause_x; gint abs_prev_x; gint abs_next_x; g_return_val_if_fail(IDO_IS_PLAYBACK_MENU_ITEM (button), FALSE); g_return_val_if_fail(cr != NULL, FALSE); cairo_surface_t* surf = NULL; cairo_t* cr_surf = NULL; GtkStyleContext *pStyleContext; GdkRGBA bg_color, fg_color, bg_selected, bg_prelight; GdkRGBA color_middle[2], color_middle_prelight[2], color_outer[2], color_outer_prelight[2], color_play_outer[2], color_play_outer_prelight[2], color_button[4], color_button_shadow, color_inner[2], color_inner_compressed[2]; pStyleContext = gtk_widget_get_style_context(gtk_widget_get_parent(button)); // Some buggy themes don't define a fallback "background-color" - let's make this a button, then. gtk_style_context_add_class(pStyleContext, GTK_STYLE_CLASS_BUTTON); get_colour(pStyleContext, GTK_STATE_FLAG_NORMAL, GTK_STYLE_PROPERTY_BACKGROUND_COLOR, &bg_color); get_colour(pStyleContext, GTK_STATE_FLAG_PRELIGHT, GTK_STYLE_PROPERTY_BACKGROUND_COLOR, &bg_prelight); get_colour(pStyleContext, GTK_STATE_FLAG_SELECTED, GTK_STYLE_PROPERTY_BACKGROUND_COLOR, &bg_selected); get_colour(pStyleContext, GTK_STATE_FLAG_NORMAL, GTK_STYLE_PROPERTY_COLOR, &fg_color); _color_shade (&bg_color, MIDDLE_START_SHADE, &color_middle[0]); _color_shade (&bg_color, MIDDLE_END_SHADE, &color_middle[1]); _color_shade (&bg_prelight, MIDDLE_START_SHADE, &color_middle_prelight[0]); _color_shade (&bg_prelight, MIDDLE_END_SHADE, &color_middle_prelight[1]); _color_shade (&bg_color, OUTER_START_SHADE, &color_outer[0]); _color_shade (&bg_color, OUTER_END_SHADE, &color_outer[1]); _color_shade (&bg_prelight, OUTER_START_SHADE, &color_outer_prelight[0]); _color_shade (&bg_prelight, OUTER_END_SHADE, &color_outer_prelight[1]); _color_shade (&bg_color, OUTER_PLAY_START_SHADE, &color_play_outer[0]); _color_shade (&bg_color, OUTER_PLAY_END_SHADE, &color_play_outer[1]); _color_shade (&bg_prelight, OUTER_PLAY_START_SHADE, &color_play_outer_prelight[0]); _color_shade (&bg_prelight, OUTER_PLAY_END_SHADE, &color_play_outer_prelight[1]); _color_shade (&bg_color, INNER_START_SHADE, &color_inner[0]); _color_shade (&bg_color, INNER_END_SHADE, &color_inner[1]); _color_shade (&fg_color, BUTTON_START_SHADE, &color_button[0]); _color_shade (&fg_color, BUTTON_END_SHADE, &color_button[1]); _color_shade (&bg_color, BUTTON_SHADOW_SHADE, &color_button[2]); _color_shade (&bg_color, SHADOW_BUTTON_SHADE, &color_button_shadow); _color_shade (&bg_selected, 1.0, &color_button[3]); _color_shade (&bg_color, INNER_COMPRESSED_START_SHADE, &color_inner_compressed[0]); _color_shade (&bg_color, INNER_COMPRESSED_END_SHADE, &color_inner_compressed[1]); double MIDDLE_END[] = {color_middle[0].red, color_middle[0].green, color_middle[0].blue, 1.0f}; double MIDDLE_START[] = {color_middle[1].red, color_middle[1].green, color_middle[1].blue, 1.0f}; double MIDDLE_END_PRELIGHT[] = {color_middle_prelight[0].red, color_middle_prelight[0].green, color_middle_prelight[0].blue, 1.0f}; double MIDDLE_START_PRELIGHT[] = {color_middle_prelight[1].red, color_middle_prelight[1].green, color_middle_prelight[1].blue, 1.0f}; double OUTER_END[] = {color_outer[0].red, color_outer[0].green, color_outer[0].blue, 1.0f}; double OUTER_START[] = {color_outer[1].red, color_outer[1].green, color_outer[1].blue, 1.0f}; double OUTER_END_PRELIGHT[] = {color_outer_prelight[0].red, color_outer_prelight[0].green, color_outer_prelight[0].blue, 1.0f}; double OUTER_START_PRELIGHT[] = {color_outer_prelight[1].red, color_outer_prelight[1].green, color_outer_prelight[1].blue, 1.0f}; double SHADOW_BUTTON[] = {color_button_shadow.red, color_button_shadow.green, color_button_shadow.blue, 0.3f}; double OUTER_PLAY_END[] = {color_play_outer[0].red, color_play_outer[0].green, color_play_outer[0].blue, 1.0f}; double OUTER_PLAY_START[] = {color_play_outer[1].red, color_play_outer[1].green, color_play_outer[1].blue, 1.0f}; double OUTER_PLAY_END_PRELIGHT[] = {color_play_outer_prelight[0].red, color_play_outer_prelight[0].green, color_play_outer_prelight[0].blue, 1.0f}; double OUTER_PLAY_START_PRELIGHT[] = {color_play_outer_prelight[1].red, color_play_outer_prelight[1].green, color_play_outer_prelight[1].blue, 1.0f}; double BUTTON_END[] = {color_button[0].red, color_button[0].green, color_button[0].blue, 1.0f}; double BUTTON_START[] = {color_button[1].red, color_button[1].green, color_button[1].blue, 1.0f}; double BUTTON_SHADOW[] = {color_button[2].red, color_button[2].green, color_button[2].blue, 0.75f}; double BUTTON_SHADOW_FOCUS[] = {color_button[3].red, color_button[3].green, color_button[3].blue, 1.0f}; double INNER_COMPRESSED_END[] = {color_inner_compressed[1].red, color_inner_compressed[1].green, color_inner_compressed[1].blue, 1.0f}; double INNER_COMPRESSED_START[] = {color_inner_compressed[0].red, color_inner_compressed[0].green, color_inner_compressed[0].blue, 1.0f}; gtk_widget_get_allocation (button, &alloc); X = alloc.x + (alloc.width - RECT_WIDTH) / 2 + OUTER_RADIUS; abs_pause_x = X + PAUSE_X; abs_prev_x = X + PREV_X; abs_next_x = X + NEXT_X; draw_gradient (cr, X, Y, RECT_WIDTH, OUTER_RADIUS, OUTER_START, OUTER_END); draw_gradient (cr, X, Y + 1, RECT_WIDTH - 2, MIDDLE_RADIUS, MIDDLE_START, MIDDLE_END); draw_gradient (cr, X, Y + 2, RECT_WIDTH - 4, MIDDLE_RADIUS, MIDDLE_START, MIDDLE_END); if(item->cur_pushed_button == BUTTON_PREVIOUS) { draw_gradient (cr, X, Y, RECT_WIDTH/2, OUTER_RADIUS, OUTER_END, OUTER_START); draw_gradient (cr, X, Y + 1, RECT_WIDTH/2, MIDDLE_RADIUS, INNER_COMPRESSED_START, INNER_COMPRESSED_END); draw_gradient (cr, X, Y + 2, RECT_WIDTH/2, MIDDLE_RADIUS, INNER_COMPRESSED_START, INNER_COMPRESSED_END); } else if(item->cur_pushed_button == BUTTON_NEXT) { draw_gradient (cr, RECT_WIDTH / 2 + X, Y, RECT_WIDTH/2, OUTER_RADIUS, OUTER_END, OUTER_START); draw_gradient (cr, RECT_WIDTH / 2 + X, Y + 1, (RECT_WIDTH - 4.5)/2, MIDDLE_RADIUS, INNER_COMPRESSED_START, INNER_COMPRESSED_END); draw_gradient (cr, RECT_WIDTH / 2 + X, Y + 2, (RECT_WIDTH - 7)/2, MIDDLE_RADIUS, INNER_COMPRESSED_START, INNER_COMPRESSED_END); } else if (item->cur_hover_button == BUTTON_PREVIOUS) { draw_gradient (cr, X, Y, RECT_WIDTH/2, OUTER_RADIUS, OUTER_START_PRELIGHT, OUTER_END_PRELIGHT); draw_gradient (cr, X, Y + 1, RECT_WIDTH/2, MIDDLE_RADIUS, MIDDLE_START_PRELIGHT, MIDDLE_END_PRELIGHT); draw_gradient (cr, X, Y + 2, RECT_WIDTH/2, MIDDLE_RADIUS, MIDDLE_START_PRELIGHT, MIDDLE_END_PRELIGHT); } else if (item->cur_hover_button == BUTTON_NEXT) { draw_gradient (cr, RECT_WIDTH / 2 + X, Y, RECT_WIDTH/2, OUTER_RADIUS, OUTER_START_PRELIGHT, OUTER_END_PRELIGHT); draw_gradient (cr, RECT_WIDTH / 2 + X, Y + 1, (RECT_WIDTH - 4.5)/2, MIDDLE_RADIUS, MIDDLE_START_PRELIGHT, MIDDLE_END_PRELIGHT); draw_gradient (cr, RECT_WIDTH / 2 + X, Y + 2, (RECT_WIDTH - 7)/2, MIDDLE_RADIUS, MIDDLE_START_PRELIGHT, MIDDLE_END_PRELIGHT); } // play/pause shadow if(item->cur_pushed_button != BUTTON_PLAYPAUSE) { cairo_save (cr); cairo_rectangle (cr, X, Y, RECT_WIDTH, MIDDLE_RADIUS*2); cairo_clip (cr); draw_circle (cr, X + RECT_WIDTH / 2.0f - 2.0f * OUTER_RADIUS - 5.5f - 1.0f, Y - ((CIRCLE_RADIUS - OUTER_RADIUS)) - 1.0f, CIRCLE_RADIUS + 1.0f, SHADOW_BUTTON, SHADOW_BUTTON); cairo_restore (cr); } // play/pause button if(item->cur_pushed_button == BUTTON_PLAYPAUSE) { draw_circle (cr, X + RECT_WIDTH / 2.0f - 2.0f * OUTER_RADIUS - 5.5f, Y - ((CIRCLE_RADIUS - OUTER_RADIUS)) , CIRCLE_RADIUS, OUTER_PLAY_END, OUTER_PLAY_START); draw_circle (cr, X + RECT_WIDTH / 2.0f - 2.0f * OUTER_RADIUS - 5.5f + 1.25f, Y - ((CIRCLE_RADIUS - OUTER_RADIUS)) + 1.25f, CIRCLE_RADIUS - 1.25, INNER_COMPRESSED_START, INNER_COMPRESSED_END); } else if (item->cur_hover_button == BUTTON_PLAYPAUSE) { /* this subtle offset is to fix alpha borders, should be removed once this draw routine will be refactored */ draw_circle (cr, X + RECT_WIDTH / 2.0f - 2.0f * OUTER_RADIUS - 5.5f + 0.1, Y - ((CIRCLE_RADIUS - OUTER_RADIUS)) + 0.1, CIRCLE_RADIUS - 0.1, OUTER_PLAY_START_PRELIGHT, OUTER_PLAY_END_PRELIGHT); draw_circle (cr, X + RECT_WIDTH / 2.0f - 2.0f * OUTER_RADIUS - 5.5f + 1.25f, Y - ((CIRCLE_RADIUS - OUTER_RADIUS)) + 1.25f, CIRCLE_RADIUS - 1.25, MIDDLE_START_PRELIGHT, MIDDLE_END_PRELIGHT); } else { draw_circle (cr, X + RECT_WIDTH / 2.0f - 2.0f * OUTER_RADIUS - 5.5f, Y - ((CIRCLE_RADIUS - OUTER_RADIUS)), CIRCLE_RADIUS, OUTER_PLAY_START, OUTER_PLAY_END); draw_circle (cr, X + RECT_WIDTH / 2.0f - 2.0f * OUTER_RADIUS - 5.5f + 1.25f, Y - ((CIRCLE_RADIUS - OUTER_RADIUS)) + 1.25f, CIRCLE_RADIUS - 1.25, MIDDLE_START, MIDDLE_END); } // draw previous-button drop-shadow if ((item->cur_pushed_button == BUTTON_PREVIOUS && item->keyboard_activated) || item->cur_hover_button == BUTTON_PREVIOUS) { _setup (&cr_surf, &surf, PREV_WIDTH+6, PREV_HEIGHT+6); _mask_prev (cr_surf, (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, (PREV_HEIGHT - TRI_HEIGHT) / 2.0f, TRI_WIDTH, TRI_HEIGHT, TRI_OFFSET); _fill (cr_surf, (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, (PREV_HEIGHT - TRI_HEIGHT) / 2.0f, (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, (double) TRI_HEIGHT, BUTTON_SHADOW_FOCUS, BUTTON_SHADOW_FOCUS, FALSE); _surface_blur (surf, 3); _finalize_repaint (cr, &cr_surf, &surf, abs_prev_x, PREV_Y + 0.5f, 3); } else { _setup (&cr_surf, &surf, PREV_WIDTH, PREV_HEIGHT); _mask_prev (cr_surf, (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, (PREV_HEIGHT - TRI_HEIGHT) / 2.0f, TRI_WIDTH, TRI_HEIGHT, TRI_OFFSET); _fill (cr_surf, (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, (PREV_HEIGHT - TRI_HEIGHT) / 2.0f, (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, (double) TRI_HEIGHT, BUTTON_SHADOW, BUTTON_SHADOW, FALSE); _surface_blur (surf, 1); _finalize (cr, &cr_surf, &surf, abs_prev_x, PREV_Y + 1.0f); } // draw previous-button _setup (&cr_surf, &surf, PREV_WIDTH, PREV_HEIGHT); _mask_prev (cr_surf, (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, (PREV_HEIGHT - TRI_HEIGHT) / 2.0f, TRI_WIDTH, TRI_HEIGHT, TRI_OFFSET); _fill (cr_surf, (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, (PREV_HEIGHT - TRI_HEIGHT) / 2.0f, (PREV_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, (double) TRI_HEIGHT, BUTTON_START, BUTTON_END, FALSE); _finalize (cr, &cr_surf, &surf, abs_prev_x, PREV_Y); // draw next-button drop-shadow if ((item->cur_pushed_button == BUTTON_NEXT && item->keyboard_activated) || item->cur_hover_button == BUTTON_NEXT) { _setup (&cr_surf, &surf, NEXT_WIDTH+6, NEXT_HEIGHT+6); _mask_next (cr_surf, (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, (NEXT_HEIGHT - TRI_HEIGHT) / 2.0f, TRI_WIDTH, TRI_HEIGHT, TRI_OFFSET); _fill (cr_surf, (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, (NEXT_HEIGHT - TRI_HEIGHT) / 2.0f, (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, (double) TRI_HEIGHT, BUTTON_SHADOW_FOCUS, BUTTON_SHADOW_FOCUS, FALSE); _surface_blur (surf, 3); _finalize_repaint (cr, &cr_surf, &surf, abs_next_x, NEXT_Y + 0.5f, 3); } else { _setup (&cr_surf, &surf, NEXT_WIDTH, NEXT_HEIGHT); _mask_next (cr_surf, (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, (NEXT_HEIGHT - TRI_HEIGHT) / 2.0f, TRI_WIDTH, TRI_HEIGHT, TRI_OFFSET); _fill (cr_surf, (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, (NEXT_HEIGHT - TRI_HEIGHT) / 2.0f, (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, (double) TRI_HEIGHT, BUTTON_SHADOW, BUTTON_SHADOW, FALSE); _surface_blur (surf, 1); _finalize (cr, &cr_surf, &surf, abs_next_x, NEXT_Y + 1.0f); } // draw next-button _setup (&cr_surf, &surf, NEXT_WIDTH, NEXT_HEIGHT); _mask_next (cr_surf, (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, (NEXT_HEIGHT - TRI_HEIGHT) / 2.0f, TRI_WIDTH, TRI_HEIGHT, TRI_OFFSET); _fill (cr_surf, (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, (NEXT_HEIGHT - TRI_HEIGHT) / 2.0f, (NEXT_WIDTH - (2.0f * TRI_WIDTH - TRI_OFFSET)) / 2.0f, (double) TRI_HEIGHT, BUTTON_START, BUTTON_END, FALSE); _finalize (cr, &cr_surf, &surf, abs_next_x, NEXT_Y); // draw pause-button drop-shadow if (item->current_state == STATE_PLAYING) { if (item->has_focus && (item->cur_hover_button == BUTTON_NONE || item->cur_hover_button == BUTTON_PLAYPAUSE) && (item->cur_pushed_button == BUTTON_NONE || item->cur_pushed_button == BUTTON_PLAYPAUSE)) { _setup (&cr_surf, &surf, PAUSE_WIDTH+6, PAUSE_HEIGHT+6); _mask_pause (cr_surf, (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, (PAUSE_HEIGHT - BAR_HEIGHT) / 2.0f, BAR_WIDTH, BAR_HEIGHT - 2.0f * BAR_WIDTH, BAR_OFFSET); _fill (cr_surf, (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, (PAUSE_HEIGHT - BAR_HEIGHT) / 2.0f, (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, (double) BAR_HEIGHT, BUTTON_SHADOW_FOCUS, BUTTON_SHADOW_FOCUS, TRUE); _surface_blur (surf, 3); _finalize_repaint (cr, &cr_surf, &surf, abs_pause_x, PAUSE_Y + 0.5f, 3); } else { _setup (&cr_surf, &surf, PAUSE_WIDTH, PAUSE_HEIGHT); _mask_pause (cr_surf, (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, (PAUSE_HEIGHT - BAR_HEIGHT) / 2.0f, BAR_WIDTH, BAR_HEIGHT - 2.0f * BAR_WIDTH, BAR_OFFSET); _fill (cr_surf, (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, (PAUSE_HEIGHT - BAR_HEIGHT) / 2.0f, (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, (double) BAR_HEIGHT, BUTTON_SHADOW, BUTTON_SHADOW, TRUE); _surface_blur (surf, 1); _finalize (cr, &cr_surf, &surf, abs_pause_x, PAUSE_Y + 1.0f); } // draw pause-button _setup (&cr_surf, &surf, PAUSE_WIDTH, PAUSE_HEIGHT); _mask_pause (cr_surf, (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, (PAUSE_HEIGHT - BAR_HEIGHT) / 2.0f, BAR_WIDTH, BAR_HEIGHT - 2.0f * BAR_WIDTH, BAR_OFFSET); _fill (cr_surf, (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, (PAUSE_HEIGHT - BAR_HEIGHT) / 2.0f, (PAUSE_WIDTH - (2.0f * BAR_WIDTH + BAR_OFFSET)) / 2.0f, (double) BAR_HEIGHT, BUTTON_START, BUTTON_END, TRUE); _finalize (cr, &cr_surf, &surf, abs_pause_x, PAUSE_Y); } else if (item->current_state == STATE_PAUSED) { if (item->has_focus && (item->cur_hover_button == BUTTON_NONE || item->cur_hover_button == BUTTON_PLAYPAUSE) && (item->cur_pushed_button == BUTTON_NONE || item->cur_pushed_button == BUTTON_PLAYPAUSE)) { _setup (&cr_surf, &surf, PLAY_WIDTH+6, PLAY_HEIGHT+6); _mask_play (cr_surf, PLAY_PADDING, PLAY_PADDING, PLAY_WIDTH - (2*PLAY_PADDING), PLAY_HEIGHT - (2*PLAY_PADDING)); _fill (cr_surf, PLAY_PADDING, PLAY_PADDING, PLAY_WIDTH - (2*PLAY_PADDING), PLAY_HEIGHT - (2*PLAY_PADDING), BUTTON_SHADOW_FOCUS, BUTTON_SHADOW_FOCUS, FALSE); _surface_blur (surf, 3); _finalize_repaint (cr, &cr_surf, &surf, abs_pause_x-0.5f, PAUSE_Y + 0.5f, 3); } else { _setup (&cr_surf, &surf, PLAY_WIDTH, PLAY_HEIGHT); _mask_play (cr_surf, PLAY_PADDING, PLAY_PADDING, PLAY_WIDTH - (2*PLAY_PADDING), PLAY_HEIGHT - (2*PLAY_PADDING)); _fill (cr_surf, PLAY_PADDING, PLAY_PADDING, PLAY_WIDTH - (2*PLAY_PADDING), PLAY_HEIGHT - (2*PLAY_PADDING), BUTTON_SHADOW, BUTTON_SHADOW, FALSE); _surface_blur (surf, 1); _finalize (cr, &cr_surf, &surf, abs_pause_x-0.75f, PAUSE_Y + 1.0f); } // draw play-button _setup (&cr_surf, &surf, PLAY_WIDTH, PLAY_HEIGHT); cairo_set_line_width (cr, 10.5); cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND); _mask_play (cr_surf, PLAY_PADDING, PLAY_PADDING, PLAY_WIDTH - (2*PLAY_PADDING), PLAY_HEIGHT - (2*PLAY_PADDING)); _fill (cr_surf, PLAY_PADDING, PLAY_PADDING, PLAY_WIDTH - (2*PLAY_PADDING), PLAY_HEIGHT - (2*PLAY_PADDING), BUTTON_START, BUTTON_END, FALSE); _finalize (cr, &cr_surf, &surf, abs_pause_x-0.5f, PAUSE_Y); } else if (item->current_state == STATE_LAUNCHING) { gtk_render_activity (gtk_widget_get_style_context (button), cr, (alloc.width / 2) - 15, (alloc.height / 2) - 15, 30, 30); } return FALSE; } ayatana-ido-0.10.1/src/idoplaybackmenuitem.h0000644000000000000000000000275714471671403015656 0ustar /* * Copyright 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * Conor Curran * Lars Uebernickel */ #ifndef __IDO_PLAYBACK_MENU_ITEM_H__ #define __IDO_PLAYBACK_MENU_ITEM_H__ #include #define IDO_TYPE_PLAYBACK_MENU_ITEM (ido_playback_menu_item_get_type ()) #define IDO_PLAYBACK_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), IDO_TYPE_PLAYBACK_MENU_ITEM, IdoPlaybackMenuItem)) #define IDO_IS_PLAYBACK_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IDO_TYPE_PLAYBACK_MENU_ITEM)) typedef struct _IdoPlaybackMenuItem IdoPlaybackMenuItem; GType ido_playback_menu_item_get_type (void); GtkMenuItem * ido_playback_menu_item_new_from_model (GMenuItem *item, GActionGroup *actions); #endif ayatana-ido-0.10.1/src/idoprogressmenuitem.c0000644000000000000000000000611114471671403015713 0ustar /* * Copyright 2023 Robert Tari * * Authors: * Robert Tari * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include "idoprogressmenuitem.h" #include "idobasicmenuitem.h" #include "idoactionhelper.h" static void onActivate (GtkMenuItem *item, gpointer pData) { IdoActionHelper *pHelper = pData; ido_action_helper_activate (pHelper); } /** * ido_progress_menu_item_new_from_model: * @pMenuItem: the corresponding menuitem * @pActionGroup: action group to tell when this GtkMenuItem is activated * * Creates a new progress menuitem with properties initialized from * the menuitem's attributes. * * If the menuitem's 'action' attribute is set, trigger that action * in @pActionGroup when this IdoProgressMenuItem is activated. */ GtkMenuItem *ido_progress_menu_item_new_from_model (GMenuItem *pMenuItem, GActionGroup *pActionGroup) { IdoBasicMenuItem *pBasicMenuItem = NULL; gchar *sLabel = NULL; if (g_menu_item_get_attribute (pMenuItem, "label", "s", &sLabel)) { pBasicMenuItem = IDO_BASIC_MENU_ITEM (g_object_new (IDO_TYPE_BASIC_MENU_ITEM, "text", sLabel, NULL)); g_free (sLabel); GVariant *pIconVariant = g_menu_item_get_attribute_value (pMenuItem, "icon", NULL); if (pIconVariant) { GIcon *pIcon = g_icon_deserialize (pIconVariant); ido_basic_menu_item_set_icon (pBasicMenuItem, pIcon); g_object_unref (pIcon); g_variant_unref (pIconVariant); } guint16 nProgress = 0; if (g_menu_item_get_attribute (pMenuItem, "x-ayatana-progress", "q", &nProgress)) { gchar *sProgress = g_strdup_printf ("%"G_GUINT16_FORMAT"%%", nProgress); ido_basic_menu_item_set_secondary_text (pBasicMenuItem, sProgress); g_free (sProgress); } gchar *sAction = NULL; if (g_menu_item_get_attribute (pMenuItem, "action", "s", &sAction)) { GVariant *pTarget = g_menu_item_get_attribute_value (pMenuItem, "target", NULL); IdoActionHelper *pHelper = ido_action_helper_new (GTK_WIDGET (pBasicMenuItem), pActionGroup, sAction, pTarget); g_signal_connect_object (pBasicMenuItem, "activate", G_CALLBACK (onActivate), pHelper, 0); g_signal_connect_swapped (pBasicMenuItem, "destroy", G_CALLBACK (g_object_unref), pHelper); if (pTarget) { g_variant_unref (pTarget); } g_free (sAction); } } return GTK_MENU_ITEM (pBasicMenuItem); } ayatana-ido-0.10.1/src/idoprogressmenuitem.h0000644000000000000000000000172514471671403015726 0ustar /** * Copyright 2013 Canonical Ltd. * * Authors: * Charles Kerr * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #ifndef __IDO_PROGRESS_MENU_ITEM_H__ #define __IDO_PROGRESS_MENU_ITEM_H__ #include GtkMenuItem * ido_progress_menu_item_new_from_model (GMenuItem * menuitem, GActionGroup * actions); #endif ayatana-ido-0.10.1/src/idorange.c0000644000000000000000000001403114471671403013377 0ustar /* * Copyright 2010 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of either or both of the following licenses: * * 1) the GNU Lesser General Public License version 3, as published by the * Free Software Foundation; and/or * 2) the GNU Lesser General Public License version 2.1, as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License version 3 and version 2.1 along with this program. If not, see * * * Authors: * Cody Russell */ #include "idorange.h" #include "idotypebuiltins.h" typedef struct { IdoRangeStyle style; } IdoRangePrivate; static void ido_range_constructed (GObject *object); static void ido_range_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static void ido_range_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); G_DEFINE_TYPE_WITH_PRIVATE (IdoRange, ido_range, GTK_TYPE_SCALE) enum { PROP_0, PROP_STYLE }; static void ido_range_class_init (IdoRangeClass *class) { GObjectClass *gobject_class = G_OBJECT_CLASS (class); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); gobject_class->constructed = ido_range_constructed; gobject_class->set_property = ido_range_set_property; gobject_class->get_property = ido_range_get_property; g_object_class_install_property (gobject_class, PROP_STYLE, g_param_spec_enum ("range-style", "Range style", "The style of the range", IDO_TYPE_RANGE_STYLE, IDO_RANGE_STYLE_SMALL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); gtk_widget_class_install_style_property (widget_class, g_param_spec_int ("knob-width", "The knob width", "The knob width", G_MININT, G_MAXINT, 8, G_PARAM_READABLE)); gtk_widget_class_install_style_property (widget_class, g_param_spec_int ("knob-height", "The knob height", "The knob height", G_MININT, G_MAXINT, 8, G_PARAM_READABLE)); } static void ido_range_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { IdoRange *range = IDO_RANGE (object); IdoRangePrivate *priv = ido_range_get_instance_private (range); switch (prop_id) { case PROP_STYLE: g_value_set_enum (value, priv->style); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void ido_range_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { IdoRange *range = IDO_RANGE (object); IdoRangePrivate *priv = ido_range_get_instance_private (range); switch (prop_id) { case PROP_STYLE: priv->style = g_value_get_enum (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void ido_range_constructed (GObject *object) { IdoRange *range = IDO_RANGE (object); IdoRangeStyle style; char buf[1024]; g_object_get (range, "range-style", &style, NULL); g_snprintf (buf, sizeof (buf), "idorange-%p", range); gtk_widget_set_name (GTK_WIDGET (range), buf); if (style == IDO_RANGE_STYLE_SMALL) { gint width, height; gtk_widget_style_get (GTK_WIDGET (range), "knob-width", &width, "knob-height", &height, NULL); } gtk_range_set_slider_size_fixed (GTK_RANGE (range), TRUE); G_OBJECT_CLASS (ido_range_parent_class)->constructed (object); } static void ido_range_init (IdoRange *range) { /* no-op */ } /** * ido_range_new: * @adj: A #GtkAdjustment providing the range values * @style: The range style * * Creates a new #IdoRange widget. * * Return Value: A new #IdoRange **/ GtkWidget * ido_range_new (GObject *adj, IdoRangeStyle style) { g_return_val_if_fail (GTK_IS_ADJUSTMENT (adj), NULL); return g_object_new (IDO_TYPE_RANGE, "orientation", GTK_ORIENTATION_HORIZONTAL, "adjustment", adj, "range-style", style, NULL); } ayatana-ido-0.10.1/src/idorange.h0000644000000000000000000000422314471671403013406 0ustar /* * Copyright (C) 2010 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of either or both of the following licenses: * * 1) the GNU Lesser General Public License version 3, as published by the * Free Software Foundation; and/or * 2) the GNU Lesser General Public License version 2.1, as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License version 3 and version 2.1 along with this program. If not, see * * * Authors: * Cody Russell */ #ifndef __IDO_RANGE_H__ #define __IDO_RANGE_H__ #include G_BEGIN_DECLS #define IDO_TYPE_RANGE (ido_range_get_type ()) #define IDO_RANGE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), IDO_TYPE_RANGE, IdoRange)) #define IDO_RANGE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), IDO_TYPE_RANGE, IdoRangeClass)) #define IDO_IS_RANGE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), IDO_TYPE_RANGE)) #define IDO_IS_RANGE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), IDO_TYPE_RANGE)) #define IDO_RANGE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), IDO_TYPE_RANGE, IdoRangeClass)) typedef enum { IDO_RANGE_STYLE_DEFAULT, IDO_RANGE_STYLE_SMALL } IdoRangeStyle; typedef struct _IdoRange IdoRange; typedef struct _IdoRangeClass IdoRangeClass; struct _IdoRange { GtkScale parent_instance; }; struct _IdoRangeClass { GtkScaleClass parent_class; /* Padding for future expansion */ void (*_ido_reserved1) (void); void (*_ido_reserved2) (void); void (*_ido_reserved3) (void); void (*_ido_reserved4) (void); }; GType ido_range_get_type (void) G_GNUC_CONST; GtkWidget* ido_range_new (GObject *adj, IdoRangeStyle style); G_END_DECLS #endif /* __IDO_RANGE_H__ */ ayatana-ido-0.10.1/src/idoremovablemenuitem.c0000644000000000000000000003662314471671403016036 0ustar /* * Copyright 2013 Canonical Ltd. * Copyright 2023 Robert Tari * * Authors: * Charles Kerr * Robert Tari * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include #include "idoactionhelper.h" #include "idoremovablemenuitem.h" enum { PROP_0, PROP_ICON, PROP_TEXT, PROP_LAST }; static GParamSpec *lProperties[PROP_LAST]; typedef struct { GIcon *pIcon; char *sText; GtkWidget *pImage; GtkWidget *pLabel; GtkWidget *pButton; gboolean bClosePressed; IdoActionHelper *pHelper; } IdoRemovableMenuItemPrivate; G_DEFINE_TYPE_WITH_PRIVATE(IdoRemovableMenuItem, ido_removable_menu_item, GTK_TYPE_MENU_ITEM); static void onGetProperty(GObject *pObject, guint nProperty, GValue *pValue, GParamSpec *pParamSpec) { IdoRemovableMenuItem *self = IDO_REMOVABLE_MENU_ITEM(pObject); IdoRemovableMenuItemPrivate *pPrivate = ido_removable_menu_item_get_instance_private(self); switch (nProperty) { case PROP_ICON: { g_value_set_object(pValue, pPrivate->pIcon); break; } case PROP_TEXT: { g_value_set_string(pValue, pPrivate->sText); break; } default: { G_OBJECT_WARN_INVALID_PROPERTY_ID(pObject, nProperty, pParamSpec); break; } } } static void onSetProperty(GObject *pObject, guint nProperty, const GValue *pValue, GParamSpec *pParamSpec) { IdoRemovableMenuItem *self = IDO_REMOVABLE_MENU_ITEM(pObject); switch (nProperty) { case PROP_ICON: { idoRemovableMenuItemSetIcon(self, g_value_get_object(pValue)); break; } case PROP_TEXT: { idoRemovableMenuItemSetText(self, g_value_get_string(pValue)); break; } default: { G_OBJECT_WARN_INVALID_PROPERTY_ID(pObject, nProperty, pParamSpec); break; } } } static void onDispose(GObject *pObject) { IdoRemovableMenuItem *self = IDO_REMOVABLE_MENU_ITEM(pObject); IdoRemovableMenuItemPrivate *pPrivate = ido_removable_menu_item_get_instance_private(self); g_clear_object (&pPrivate->pIcon); G_OBJECT_CLASS(ido_removable_menu_item_parent_class)->dispose(pObject); } static void onFinalize(GObject * pObject) { IdoRemovableMenuItem *self = IDO_REMOVABLE_MENU_ITEM(pObject); IdoRemovableMenuItemPrivate *pPrivate = ido_removable_menu_item_get_instance_private(self); g_free(pPrivate->sText); G_OBJECT_CLASS (ido_removable_menu_item_parent_class)->finalize(pObject); } static void idoRemovableMenuItemStyleUpdateImage(IdoRemovableMenuItem *self) { IdoRemovableMenuItemPrivate *pPrivate = ido_removable_menu_item_get_instance_private(self); gtk_image_clear(GTK_IMAGE(pPrivate->pImage)); if (pPrivate->pIcon == NULL) { gtk_widget_set_visible(pPrivate->pImage, FALSE); } else { gtk_image_set_from_gicon (GTK_IMAGE (pPrivate->pImage), pPrivate->pIcon, GTK_ICON_SIZE_MENU); gtk_widget_set_visible (pPrivate->pImage, TRUE); } } static void onStyleUpdated(GtkWidget *pWidget) { GTK_WIDGET_CLASS(ido_removable_menu_item_parent_class)->style_updated(pWidget); idoRemovableMenuItemStyleUpdateImage(IDO_REMOVABLE_MENU_ITEM(pWidget)); gtk_widget_queue_draw(pWidget); } static gboolean idoRemovableMenuItemIsWidget(GtkWidget *pWidget, GdkEventButton *pEventButton) { if (gtk_widget_get_window(pWidget) == NULL) { return FALSE; } GtkAllocation cAllocation; gtk_widget_get_allocation(pWidget, &cAllocation); GdkWindow *window = gtk_widget_get_window(pWidget); int nXWin, nYWin; gdk_window_get_origin(window, &nXWin, &nYWin); int nXMin = cAllocation.x; int nXMax = cAllocation.x + cAllocation.width; int nYMin = cAllocation.y; int nYMax = cAllocation.y + cAllocation.height; int nX = pEventButton->x_root - nXWin; int nY = pEventButton->y_root - nYWin; return nX >= nXMin && nX <= nXMax && nY >= nYMin && nY <= nYMax; } static gboolean onButtonPress(GtkWidget *pWidget, GdkEventButton *pEventButton) { g_return_val_if_fail(IDO_IS_REMOVABLE_MENU_ITEM(pWidget), FALSE); IdoRemovableMenuItem *self = IDO_REMOVABLE_MENU_ITEM(pWidget); IdoRemovableMenuItemPrivate *pPrivate = ido_removable_menu_item_get_instance_private(self); if (pEventButton->button == GDK_BUTTON_PRIMARY) { if (idoRemovableMenuItemIsWidget(pPrivate->pLabel, pEventButton)) { gtk_widget_event(pPrivate->pLabel, (GdkEvent *)pEventButton); } else if (idoRemovableMenuItemIsWidget(pPrivate->pButton, pEventButton)) { gtk_widget_set_state_flags(pPrivate->pButton, GTK_STATE_FLAG_PRELIGHT | GTK_STATE_FLAG_FOCUSED | GTK_STATE_FLAG_ACTIVE, TRUE); pPrivate->bClosePressed = TRUE; } } return TRUE; } static gboolean onButtonRelease(GtkWidget *pWidget, GdkEventButton *pEventButton) { g_return_val_if_fail(IDO_IS_REMOVABLE_MENU_ITEM(pWidget), FALSE); IdoRemovableMenuItem *self = IDO_REMOVABLE_MENU_ITEM(pWidget); IdoRemovableMenuItemPrivate *pPrivate = ido_removable_menu_item_get_instance_private(self); if (pEventButton->button == GDK_BUTTON_PRIMARY) { if (idoRemovableMenuItemIsWidget(pPrivate->pButton, pEventButton)) { if (pPrivate->bClosePressed) { GtkWidget *pParent = gtk_widget_get_parent(GTK_WIDGET(self)); GList *lMenuItems = gtk_container_get_children(GTK_CONTAINER(pParent)); guint nRemovables = 0; for(GList *pElem = lMenuItems; pElem; pElem = pElem->next) { if (IDO_IS_REMOVABLE_MENU_ITEM(pElem->data)) { nRemovables++; } } g_list_free(lMenuItems); if (pPrivate->pHelper) { ido_action_helper_activate(pPrivate->pHelper); } else { gtk_container_remove(GTK_CONTAINER(pParent), GTK_WIDGET(self)); } if (GTK_IS_MENU_SHELL(pParent) && nRemovables == 1) { gtk_menu_shell_deactivate(GTK_MENU_SHELL(pParent)); } } } else if (idoRemovableMenuItemIsWidget(pPrivate->pLabel, pEventButton)) { gtk_widget_event(pPrivate->pLabel, (GdkEvent *)pEventButton); } } gtk_widget_set_state_flags(pPrivate->pButton, GTK_STATE_FLAG_NORMAL, TRUE); pPrivate->bClosePressed = FALSE; return TRUE; } static gboolean onMotionNotify(GtkWidget *pMenuItem, GdkEventMotion *pEventMotion) { g_return_val_if_fail(IDO_IS_REMOVABLE_MENU_ITEM(pMenuItem), FALSE); IdoRemovableMenuItem *self = IDO_REMOVABLE_MENU_ITEM(pMenuItem); IdoRemovableMenuItemPrivate *pPrivate = ido_removable_menu_item_get_instance_private(self); GtkAllocation cAllocationSelf; gtk_widget_get_allocation(GTK_WIDGET(self), &cAllocationSelf); GtkWidget *pWidget; if (idoRemovableMenuItemIsWidget(pPrivate->pButton, (GdkEventButton*)pEventMotion)) { pWidget = pPrivate->pButton; if (!pPrivate->bClosePressed) { gtk_widget_set_state_flags(pPrivate->pButton, GTK_STATE_FLAG_FOCUSED, TRUE); } else { gtk_widget_set_state_flags(pPrivate->pButton, GTK_STATE_FLAG_PRELIGHT | GTK_STATE_FLAG_FOCUSED | GTK_STATE_FLAG_ACTIVE, TRUE); } } else { pWidget = pPrivate->pLabel; gtk_widget_set_state_flags(pPrivate->pButton, GTK_STATE_FLAG_NORMAL, TRUE); } GtkAllocation cAllocationLabel; gtk_widget_get_allocation(pWidget, &cAllocationLabel); GdkEventMotion *pEventMotionNew = (GdkEventMotion *)gdk_event_copy((GdkEvent *)pEventMotion); pEventMotionNew->x = pEventMotion->x - (cAllocationLabel.x - cAllocationSelf.x); pEventMotionNew->y = pEventMotion->y - (cAllocationLabel.y - cAllocationSelf.y); gtk_widget_event(pWidget, (GdkEvent *)pEventMotionNew); gdk_event_free((GdkEvent *)pEventMotionNew); return FALSE; } static gboolean onLeaveNotify(GtkWidget *pWidget, GdkEventCrossing *pEventCrossing) { g_return_val_if_fail(IDO_IS_REMOVABLE_MENU_ITEM(pWidget), FALSE); IdoRemovableMenuItem *self = IDO_REMOVABLE_MENU_ITEM(pWidget); IdoRemovableMenuItemPrivate *pPrivate = ido_removable_menu_item_get_instance_private(self); gtk_widget_event(pPrivate->pLabel, (GdkEvent *)pEventCrossing); return FALSE; } static void ido_removable_menu_item_class_init(IdoRemovableMenuItemClass *klass) { GObjectClass *pObject = G_OBJECT_CLASS(klass); GtkWidgetClass *pWidget = GTK_WIDGET_CLASS(klass); GtkMenuItemClass *pMenuItem = GTK_MENU_ITEM_CLASS(klass); pObject->get_property = onGetProperty; pObject->set_property = onSetProperty; pObject->dispose = onDispose; pObject->finalize = onFinalize; pWidget->style_updated = onStyleUpdated; pWidget->leave_notify_event = onLeaveNotify; pWidget->motion_notify_event = onMotionNotify; pWidget->button_press_event = onButtonPress; pWidget->button_release_event = onButtonRelease; pMenuItem->select = NULL; GParamFlags nParamFlags = G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS; lProperties[PROP_ICON] = g_param_spec_object("icon", "Icon", "The menuitem's GIcon", G_TYPE_OBJECT, nParamFlags); lProperties[PROP_TEXT] = g_param_spec_string ("text", "Text", "The menuitem's text", "", nParamFlags); g_object_class_install_properties(pObject, PROP_LAST, lProperties); } static gboolean onActivateLink(GtkLabel *pLabel, gchar *sUri, gpointer pUserData) { g_return_val_if_fail(IDO_IS_REMOVABLE_MENU_ITEM(pUserData), FALSE); IdoRemovableMenuItem *self = IDO_REMOVABLE_MENU_ITEM(pUserData); GError *pError = NULL; if (!gtk_show_uri_on_window(NULL, sUri, gtk_get_current_event_time(), &pError)) { g_warning("Unable to show '%s': %s", sUri, pError->message); g_error_free(pError); } GtkWidget *pParent = gtk_widget_get_parent(GTK_WIDGET(self)); if (GTK_IS_MENU_SHELL(pParent)) { gtk_menu_shell_deactivate(GTK_MENU_SHELL(pParent)); } return TRUE; } static void ido_removable_menu_item_init(IdoRemovableMenuItem *self) { IdoRemovableMenuItemPrivate *pPrivate = ido_removable_menu_item_get_instance_private(self); pPrivate->bClosePressed = FALSE; pPrivate->pHelper = NULL; pPrivate->pImage = gtk_image_new(); gtk_widget_set_halign(pPrivate->pImage, GTK_ALIGN_START); gtk_widget_set_valign(pPrivate->pImage, GTK_ALIGN_START); pPrivate->pLabel = gtk_label_new(""); gtk_widget_set_halign(pPrivate->pLabel, GTK_ALIGN_START); gtk_widget_set_valign(pPrivate->pLabel, GTK_ALIGN_CENTER); pPrivate->pButton = gtk_button_new(); gtk_button_set_label(GTK_BUTTON(pPrivate->pButton), "X"); gtk_widget_set_halign(pPrivate->pButton, GTK_ALIGN_CENTER); gtk_widget_set_valign(pPrivate->pButton, GTK_ALIGN_CENTER); gtk_widget_show(pPrivate->pButton); GtkWidget *pBox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); gtk_box_pack_start(GTK_BOX(pBox), pPrivate->pImage, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(pBox), pPrivate->pLabel, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(pBox), pPrivate->pButton, FALSE, FALSE, 0); g_object_set(pPrivate->pImage, "halign", GTK_ALIGN_START, "hexpand", FALSE, "valign", GTK_ALIGN_CENTER, "margin-right", 6, NULL); g_object_set(pPrivate->pLabel, "halign", GTK_ALIGN_START, "hexpand", TRUE, "margin-right", 6, "valign", GTK_ALIGN_CENTER, NULL); gtk_widget_show(pBox); gtk_container_add(GTK_CONTAINER(self), pBox); g_signal_connect(pPrivate->pLabel, "activate-link", G_CALLBACK(onActivateLink), self); } GtkWidget *ido_removable_menu_item_new (void) { return GTK_WIDGET(g_object_new(IDO_TYPE_REMOVABLE_MENU_ITEM, NULL)); } void idoRemovableMenuItemSetIcon(IdoRemovableMenuItem *self, GIcon *pIcon) { IdoRemovableMenuItemPrivate *pPrivate = ido_removable_menu_item_get_instance_private(self); if (pPrivate->pIcon != pIcon) { if (pPrivate->pIcon) { g_object_unref(pPrivate->pIcon); } pPrivate->pIcon = pIcon ? g_object_ref(pIcon) : NULL; idoRemovableMenuItemStyleUpdateImage(self); } } void idoRemovableMenuItemSetIconFromFile(IdoRemovableMenuItem *self, const char *sFilename) { GFile *pFile = sFilename ? g_file_new_for_path(sFilename) : NULL; GIcon *pIcon = pFile ? g_file_icon_new(pFile) : NULL; idoRemovableMenuItemSetIcon(self, pIcon); g_clear_object(&pIcon); g_clear_object(&pFile); } void idoRemovableMenuItemSetText(IdoRemovableMenuItem *self, const char *sText) { IdoRemovableMenuItemPrivate *pPrivate = ido_removable_menu_item_get_instance_private(self); if (g_strcmp0(pPrivate->sText, sText)) { g_free(pPrivate->sText); pPrivate->sText = g_strdup(sText); g_object_set (G_OBJECT(pPrivate->pLabel), "label", pPrivate->sText, "visible", (gboolean)(pPrivate->sText && *pPrivate->sText), NULL); } } GtkMenuItem *ido_removable_menu_item_new_from_model(GMenuItem *pMenuItem, GActionGroup *pActionGroup) { GtkWidget *pItem = ido_removable_menu_item_new(); IdoRemovableMenuItemPrivate *pPrivate = ido_removable_menu_item_get_instance_private(IDO_REMOVABLE_MENU_ITEM(pItem)); gboolean bUseMarkup = FALSE; g_menu_item_get_attribute(pMenuItem, "x-ayatana-use-markup", "b", &bUseMarkup); idoRemovableMenuItemUseMarkup(IDO_REMOVABLE_MENU_ITEM(pItem), bUseMarkup); gchar *sLabel; if (g_menu_item_get_attribute(pMenuItem, "label", "s", &sLabel)) { idoRemovableMenuItemSetText(IDO_REMOVABLE_MENU_ITEM(pItem), sLabel); g_free(sLabel); } GVariant *sIcon = g_menu_item_get_attribute_value(pMenuItem, "icon", NULL); if (sIcon) { GIcon *pIcon = g_icon_deserialize(sIcon); idoRemovableMenuItemSetIcon(IDO_REMOVABLE_MENU_ITEM(pItem), pIcon); g_object_unref(pIcon); g_variant_unref(sIcon); } gchar *sAction; if (g_menu_item_get_attribute(pMenuItem, "action", "s", &sAction)) { GVariant *sTarget = g_menu_item_get_attribute_value(pMenuItem, "target", NULL); pPrivate->pHelper = ido_action_helper_new(pItem, pActionGroup, sAction, sTarget); g_signal_connect_swapped(pItem, "destroy", G_CALLBACK (g_object_unref), pPrivate->pHelper); if (sTarget) { g_variant_unref(sTarget); } g_free(sAction); } return GTK_MENU_ITEM(pItem); } void idoRemovableMenuItemUseMarkup(IdoRemovableMenuItem *self, gboolean bUse) { IdoRemovableMenuItemPrivate *pPrivate = ido_removable_menu_item_get_instance_private(IDO_REMOVABLE_MENU_ITEM(self)); g_object_set(pPrivate->pLabel, "use-markup", bUse, NULL); } ayatana-ido-0.10.1/src/idoremovablemenuitem.h0000644000000000000000000000232314471671403016031 0ustar #ifndef __IDO_REMOVABLE_MENU_ITEM_H__ #define __IDO_REMOVABLE_MENU_ITEM_H__ #include G_BEGIN_DECLS #define IDO_TYPE_REMOVABLE_MENU_ITEM (ido_removable_menu_item_get_type()) #define IDO_REMOVABLE_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), IDO_TYPE_REMOVABLE_MENU_ITEM, IdoRemovableMenuItem)) #define IDO_IS_REMOVABLE_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), IDO_TYPE_REMOVABLE_MENU_ITEM)) typedef struct _IdoRemovableMenuItem IdoRemovableMenuItem; typedef struct _IdoRemovableMenuItemClass IdoRemovableMenuItemClass; struct _IdoRemovableMenuItemClass { GtkMenuItemClass parent_class; }; struct _IdoRemovableMenuItem { GtkMenuItem parent; }; GType ido_removable_menu_item_get_type()G_GNUC_CONST; GtkWidget * ido_removable_menu_item_new(); void idoRemovableMenuItemSetIcon(IdoRemovableMenuItem *self, GIcon *pIcon); void idoRemovableMenuItemSetIconFromFile(IdoRemovableMenuItem *self, const char *sFilename); void idoRemovableMenuItemSetText(IdoRemovableMenuItem *self, const char *sText); void idoRemovableMenuItemUseMarkup(IdoRemovableMenuItem *self, gboolean bUse); GtkMenuItem* ido_removable_menu_item_new_from_model(GMenuItem *pMenuItem, GActionGroup *pActionGroup); G_END_DECLS #endif ayatana-ido-0.10.1/src/idoscalemenuitem.c0000644000000000000000000011121314471671403015136 0ustar /* * Copyright 2010 Canonical, Ltd. * Copyright 2021 Robert Tari * * This program is free software: you can redistribute it and/or modify it * under the terms of either or both of the following licenses: * * 1) the GNU Lesser General Public License version 3, as published by the * Free Software Foundation; and/or * 2) the GNU Lesser General Public License version 2.1, as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License version 3 and version 2.1 along with this program. If not, see * * * Authors: * Cody Russell * Robert Tari */ #include #include "idorange.h" #include "idoscalemenuitem.h" #include "idotypebuiltins.h" #include "idoactionhelper.h" static void ido_scale_menu_item_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static void ido_scale_menu_item_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); static gboolean ido_scale_menu_item_parent_key_press_event (GtkWidget *widget, GdkEventKey *event, gpointer user_data); static void ido_scale_menu_item_select (GtkMenuItem *item); static void ido_scale_menu_item_deselect (GtkMenuItem *item); static gboolean ido_scale_menu_item_button_press_event (GtkWidget *menuitem, GdkEventButton *event); static gboolean ido_scale_menu_item_button_release_event (GtkWidget *menuitem, GdkEventButton *event); static gboolean ido_scale_menu_item_motion_notify_event (GtkWidget *menuitem, GdkEventMotion *event); static void ido_scale_menu_item_primary_image_notify (GtkImage *image, GParamSpec *pspec, IdoScaleMenuItem *item); static void ido_scale_menu_item_secondary_image_notify (GtkImage *image, GParamSpec *pspec, IdoScaleMenuItem *item); static void ido_scale_menu_item_parent_set (GtkWidget *item, GtkWidget *previous_parent); static void update_packing (IdoScaleMenuItem *self, IdoScaleMenuItemStyle style); static void default_primary_clicked_handler (IdoScaleMenuItem *self); static void default_secondary_clicked_handler (IdoScaleMenuItem *self); typedef struct { GtkWidget *scale; GtkAdjustment *adjustment; GtkWidget *primary_image; GtkWidget *secondary_image; GtkWidget *primary_label; GtkWidget *secondary_label; GtkWidget *hbox; gboolean reverse_scroll; gboolean grabbed; IdoScaleMenuItemStyle style; IdoRangeStyle range_style; gboolean ignore_value_changed; gboolean has_focus; } IdoScaleMenuItemPrivate; enum { SLIDER_GRABBED, SLIDER_RELEASED, PRIMARY_CLICKED, SECONDARY_CLICKED, VALUE_CHANGED, LAST_SIGNAL }; enum { PROP_0, PROP_ADJUSTMENT, PROP_REVERSE_SCROLL_EVENTS, PROP_STYLE, PROP_RANGE_STYLE }; static guint signals[LAST_SIGNAL] = { 0 }; G_DEFINE_TYPE_WITH_PRIVATE (IdoScaleMenuItem, ido_scale_menu_item, GTK_TYPE_MENU_ITEM) static gboolean ido_scale_menu_item_scroll_event (GtkWidget *menuitem, GdkEventScroll *event) { IdoScaleMenuItem *item = IDO_SCALE_MENU_ITEM (menuitem); IdoScaleMenuItemPrivate *priv = ido_scale_menu_item_get_instance_private (item); GtkWidget *scale = priv->scale; if (priv->reverse_scroll) { switch (event->direction) { case GDK_SCROLL_UP: event->direction = GDK_SCROLL_DOWN; break; case GDK_SCROLL_DOWN: event->direction = GDK_SCROLL_UP; break; default: break; } } gtk_widget_event (scale, ((GdkEvent *)(void*)(event))); return TRUE; } static void ido_scale_menu_item_scale_value_changed (GtkRange *range, gpointer user_data) { IdoScaleMenuItem *self = user_data; IdoScaleMenuItemPrivate *priv = ido_scale_menu_item_get_instance_private (self); /* The signal is not sent when it was set through * ido_scale_menu_item_set_value(). */ if (!priv->ignore_value_changed) g_signal_emit (self, signals[VALUE_CHANGED], 0, gtk_range_get_value (range)); } static void ido_scale_menu_item_constructed (GObject *object) { IdoScaleMenuItem *self = IDO_SCALE_MENU_ITEM (object); IdoScaleMenuItemPrivate *priv = ido_scale_menu_item_get_instance_private (self); GObject *adj = G_OBJECT (gtk_adjustment_new (0.0, 0.0, 100.0, 1.0, 10.0, 0.0)); IdoRangeStyle range_style; GtkWidget *hbox; priv->adjustment = NULL; g_object_get (self, "range-style", &range_style, NULL); priv->scale = ido_range_new (adj, range_style); g_signal_connect (priv->scale, "value-changed", G_CALLBACK (ido_scale_menu_item_scale_value_changed), self); g_object_ref (priv->scale); gtk_scale_set_draw_value (GTK_SCALE (priv->scale), FALSE); hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); priv->primary_image = gtk_image_new (); g_signal_connect (priv->primary_image, "notify", G_CALLBACK (ido_scale_menu_item_primary_image_notify), self); priv->secondary_image = gtk_image_new (); g_signal_connect (priv->secondary_image, "notify", G_CALLBACK (ido_scale_menu_item_secondary_image_notify), self); priv->primary_label = gtk_label_new (""); priv->secondary_label = gtk_label_new (""); priv->hbox = hbox; update_packing (self, priv->style); gtk_container_add (GTK_CONTAINER (self), hbox); gtk_widget_add_events (GTK_WIDGET(self), GDK_SCROLL_MASK); } static void ido_scale_menu_item_class_init (IdoScaleMenuItemClass *item_class) { GObjectClass *gobject_class = G_OBJECT_CLASS (item_class); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (item_class); GtkMenuItemClass *menuitem_class = GTK_MENU_ITEM_CLASS (item_class); item_class->primary_clicked = default_primary_clicked_handler; item_class->secondary_clicked = default_secondary_clicked_handler; menuitem_class->select = ido_scale_menu_item_select; menuitem_class->deselect = ido_scale_menu_item_deselect; widget_class->button_press_event = ido_scale_menu_item_button_press_event; widget_class->button_release_event = ido_scale_menu_item_button_release_event; widget_class->motion_notify_event = ido_scale_menu_item_motion_notify_event; widget_class->scroll_event = ido_scale_menu_item_scroll_event; widget_class->parent_set = ido_scale_menu_item_parent_set; gobject_class->constructed = ido_scale_menu_item_constructed; gobject_class->set_property = ido_scale_menu_item_set_property; gobject_class->get_property = ido_scale_menu_item_get_property; g_object_class_install_property (gobject_class, PROP_STYLE, g_param_spec_enum ("accessory-style", "Style of primary/secondary widgets", "The style of the primary/secondary widgets", IDO_TYPE_SCALE_MENU_ITEM_STYLE, IDO_SCALE_MENU_ITEM_STYLE_NONE, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, PROP_RANGE_STYLE, g_param_spec_enum ("range-style", "Range style", "Style of the range", IDO_TYPE_RANGE_STYLE, IDO_RANGE_STYLE_DEFAULT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property (gobject_class, PROP_ADJUSTMENT, g_param_spec_object ("adjustment", "Adjustment", "The adjustment containing the scale value", GTK_TYPE_ADJUSTMENT, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, PROP_REVERSE_SCROLL_EVENTS, g_param_spec_boolean ("reverse-scroll-events", "Reverse scroll events", "Reverses how up/down scroll events are interpreted", TRUE, G_PARAM_READWRITE)); /** * IdoScaleMenuItem::slider-grabbed: * @menuitem: The #IdoScaleMenuItem emitting the signal. * * The ::slider-grabbed signal is emitted when the pointer selects the slider. */ signals[SLIDER_GRABBED] = g_signal_new ("slider-grabbed", G_OBJECT_CLASS_TYPE (gobject_class), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * IdoScaleMenuItem::slider-released: * @menuitem: The #IdoScaleMenuItem emitting the signal. * * The ::slider-released signal is emitted when the pointer releases the slider. */ signals[SLIDER_RELEASED] = g_signal_new ("slider-released", G_OBJECT_CLASS_TYPE (gobject_class), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * IdoScaleMenuItem::primary-clicked: * @menuitem: The #IdoScaleMenuItem emitting the signal. * * The ::primary-clicked signal is emitted when the pointer clicks the primary label. */ signals[PRIMARY_CLICKED] = g_signal_new ("primary-clicked", G_TYPE_FROM_CLASS (item_class), G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, G_STRUCT_OFFSET (IdoScaleMenuItemClass, primary_clicked), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, /* return type */ 0 /* n_params */); /** * IdoScaleMenuItem::secondary-clicked: * @menuitem: The #IdoScaleMenuItem emitting the signal. * * The ::secondary-clicked signal is emitted when the pointer clicks the secondary label. */ signals[SECONDARY_CLICKED] = g_signal_new ("secondary-clicked", G_TYPE_FROM_CLASS (item_class), G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, G_STRUCT_OFFSET (IdoScaleMenuItemClass, secondary_clicked), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, /* return type */ 0 /* n_params */); /** * IdoScaleMenuItem::value-changed: * @menuitem: the #IdoScaleMenuItem for which the value changed * @value: the new value * * Emitted whenever the value of the contained scale changes because * of user input. */ signals[VALUE_CHANGED] = g_signal_new ("value-changed", IDO_TYPE_SCALE_MENU_ITEM, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__DOUBLE, G_TYPE_NONE, 1, G_TYPE_DOUBLE); } static void update_packing (IdoScaleMenuItem *self, IdoScaleMenuItemStyle style) { IdoScaleMenuItemPrivate *priv = ido_scale_menu_item_get_instance_private (self); GtkBox * box = GTK_BOX (priv->hbox); GtkContainer *container = GTK_CONTAINER (priv->hbox); /* remove the old layout */ GList * children = gtk_container_get_children (container); GList * l; for (l=children; l!=NULL; l=l->next) gtk_container_remove (container, l->data); g_list_free (children); /* add the new layout */ switch (style) { case IDO_SCALE_MENU_ITEM_STYLE_IMAGE: gtk_box_pack_start (box, priv->primary_image, FALSE, FALSE, 0); gtk_box_pack_start (box, priv->scale, TRUE, TRUE, 0); gtk_box_pack_start (box, priv->secondary_image, FALSE, FALSE, 0); break; case IDO_SCALE_MENU_ITEM_STYLE_LABEL: gtk_box_pack_start (box, priv->primary_label, FALSE, FALSE, 0); gtk_box_pack_start (box, priv->scale, TRUE, TRUE, 0); gtk_box_pack_start (box, priv->secondary_label, FALSE, FALSE, 0); break; default: gtk_box_pack_start (box, priv->scale, TRUE, TRUE, 0); break; } gtk_widget_show_all (priv->hbox); } static void ido_scale_menu_item_init (IdoScaleMenuItem *self) { IdoScaleMenuItemPrivate *priv = ido_scale_menu_item_get_instance_private (self); priv->reverse_scroll = TRUE; gtk_widget_set_size_request (GTK_WIDGET (self), 200, -1); } static void ido_scale_menu_item_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { IdoScaleMenuItem *menu_item = IDO_SCALE_MENU_ITEM (object); IdoScaleMenuItemPrivate *priv = ido_scale_menu_item_get_instance_private (menu_item); switch (prop_id) { case PROP_ADJUSTMENT: gtk_range_set_adjustment (GTK_RANGE (priv->scale), g_value_get_object (value)); break; case PROP_REVERSE_SCROLL_EVENTS: priv->reverse_scroll = g_value_get_boolean (value); break; case PROP_STYLE: ido_scale_menu_item_set_style (menu_item, g_value_get_enum (value)); break; case PROP_RANGE_STYLE: priv->range_style = g_value_get_enum (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void ido_scale_menu_item_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { IdoScaleMenuItem *menu_item = IDO_SCALE_MENU_ITEM (object); IdoScaleMenuItemPrivate *priv = ido_scale_menu_item_get_instance_private (menu_item); GtkAdjustment *adjustment; switch (prop_id) { case PROP_ADJUSTMENT: adjustment = gtk_range_get_adjustment (GTK_RANGE (priv->scale)); g_value_set_object (value, adjustment); break; case PROP_REVERSE_SCROLL_EVENTS: g_value_set_boolean (value, priv->reverse_scroll); break; case PROP_RANGE_STYLE: g_value_set_enum (value, priv->range_style); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static gboolean ido_scale_menu_item_parent_key_press_event (GtkWidget *widget, GdkEventKey *event, gpointer user_data) { IdoScaleMenuItem *menu_item = IDO_SCALE_MENU_ITEM (user_data); IdoScaleMenuItemPrivate *priv = ido_scale_menu_item_get_instance_private (menu_item); /* only listen to events when the playback menu item is selected */ if (!priv->has_focus) return FALSE; switch (event->keyval) { case GDK_KEY_Left: case GDK_KEY_minus: case GDK_KEY_KP_Subtract: GTK_RANGE_GET_CLASS (priv->scale)->move_slider (GTK_RANGE (priv->scale), GTK_SCROLL_STEP_LEFT); return TRUE; case GDK_KEY_Right: case GDK_KEY_plus: case GDK_KEY_KP_Add: GTK_RANGE_GET_CLASS (priv->scale)->move_slider (GTK_RANGE (priv->scale), GTK_SCROLL_STEP_RIGHT); return TRUE; } return FALSE; } static void ido_scale_menu_item_select (GtkMenuItem *item) { IdoScaleMenuItem *menu_item = IDO_SCALE_MENU_ITEM (item); IdoScaleMenuItemPrivate *priv = ido_scale_menu_item_get_instance_private (menu_item); priv->has_focus = TRUE; gtk_widget_set_state_flags (priv->scale, GTK_STATE_FLAG_FOCUSED, FALSE); GTK_MENU_ITEM_CLASS (ido_scale_menu_item_parent_class)->select (item); } static void ido_scale_menu_item_deselect (GtkMenuItem *item) { IdoScaleMenuItem *menu_item = IDO_SCALE_MENU_ITEM (item); IdoScaleMenuItemPrivate *priv = ido_scale_menu_item_get_instance_private (menu_item); priv->has_focus = FALSE; gtk_widget_unset_state_flags (priv->scale, GTK_STATE_FLAG_FOCUSED); GTK_MENU_ITEM_CLASS (ido_scale_menu_item_parent_class)->deselect (item); } static gboolean ido_scale_menu_item_button_press_event (GtkWidget *menuitem, GdkEventButton *event) { IdoScaleMenuItem *item = IDO_SCALE_MENU_ITEM (menuitem); IdoScaleMenuItemPrivate *priv = ido_scale_menu_item_get_instance_private (item); GtkAllocation alloc; gint x, y; gtk_widget_get_allocation (priv->scale, &alloc); gtk_widget_translate_coordinates (menuitem, priv->scale, event->x, event->y, &x, &y); if (x > 0 && x < alloc.width && y > 0 && y < alloc.height) gtk_widget_event (priv->scale, (GdkEvent *) event); if (!priv->grabbed) { priv->grabbed = TRUE; g_signal_emit (menuitem, signals[SLIDER_GRABBED], 0); } return TRUE; } static gboolean ido_scale_menu_item_button_release_event (GtkWidget *menuitem, GdkEventButton *event) { IdoScaleMenuItem *item = IDO_SCALE_MENU_ITEM (menuitem); IdoScaleMenuItemPrivate *priv = ido_scale_menu_item_get_instance_private (item); GtkWidget *scale = priv->scale; GtkAllocation alloc; gint x, y; gtk_widget_get_allocation (priv->scale, &alloc); gtk_widget_translate_coordinates (menuitem, priv->scale, event->x, event->y, &x, &y); /* if user clicked to the left of the scale... */ if (x < 0) { if (gtk_widget_get_direction (menuitem) == GTK_TEXT_DIR_LTR) { ido_scale_menu_item_primary_clicked (item); } else { ido_scale_menu_item_secondary_clicked (item); } } /* if user clicked to the right of the scale... */ else if (x > alloc.width) { if (gtk_widget_get_direction (menuitem) == GTK_TEXT_DIR_LTR) { ido_scale_menu_item_secondary_clicked (item); } else { ido_scale_menu_item_primary_clicked (item); } } /* user clicked on the scale... */ else if (x > 0 && x < alloc.width && y > 0 && y < alloc.height) { gtk_widget_event (scale, (GdkEvent*) event); } if (priv->grabbed) { priv->grabbed = FALSE; g_signal_emit (menuitem, signals[SLIDER_RELEASED], 0); } return TRUE; } static gboolean ido_scale_menu_item_motion_notify_event (GtkWidget *menuitem, GdkEventMotion *event) { IdoScaleMenuItem *menu_item = IDO_SCALE_MENU_ITEM (menuitem); IdoScaleMenuItemPrivate *priv = ido_scale_menu_item_get_instance_private (menu_item); GtkAllocation alloc; gint x, y; gtk_widget_get_allocation (priv->scale, &alloc); gtk_widget_translate_coordinates (menuitem, priv->scale, event->x, event->y, &x, &y); /* don't translate coordinates when the scale has the "grab" - * GtkRange expects coords relative to its event window in that case */ if (!priv->grabbed) { event->x = x; event->y = y; } if (priv->grabbed || (x > 0 && x < alloc.width && y > 0 && y < alloc.height)) gtk_widget_event (priv->scale, (GdkEvent *) event); return TRUE; } static void menu_hidden (GtkWidget *menu, IdoScaleMenuItem *scale) { IdoScaleMenuItemPrivate *priv = ido_scale_menu_item_get_instance_private (scale); if (priv->grabbed) { priv->grabbed = FALSE; g_signal_emit (scale, signals[SLIDER_RELEASED], 0); } } static void ido_scale_menu_item_parent_set (GtkWidget *item, GtkWidget *previous_parent) { GtkWidget *parent; if (previous_parent) { g_signal_handlers_disconnect_by_func (previous_parent, menu_hidden, item); g_signal_handlers_disconnect_by_func (previous_parent, ido_scale_menu_item_parent_key_press_event, item); } parent = gtk_widget_get_parent (item); if (parent) { g_signal_connect (parent, "hide", G_CALLBACK (menu_hidden), item); /* Menus don't pass key events to their children. This works around * that by listening to key events on the parent widget. */ g_signal_connect (parent, "key-press-event", G_CALLBACK (ido_scale_menu_item_parent_key_press_event), item); } } static void ido_scale_menu_item_primary_image_notify (GtkImage *image, GParamSpec *pspec, IdoScaleMenuItem *item) { if (gtk_image_get_storage_type (image) == GTK_IMAGE_EMPTY) gtk_widget_hide (GTK_WIDGET (image)); else gtk_widget_show (GTK_WIDGET (image)); } static void ido_scale_menu_item_secondary_image_notify (GtkImage *image, GParamSpec *pspec, IdoScaleMenuItem *item) { if (gtk_image_get_storage_type (image) == GTK_IMAGE_EMPTY) gtk_widget_hide (GTK_WIDGET (image)); else gtk_widget_show (GTK_WIDGET (image)); } /** * ido_scale_menu_item_new: * @label: the text of the new menu item. * @size: The size style of the range. * @adjustment: A #GtkAdjustment describing the slider value. * * Creates a new #IdoScaleMenuItem with an empty label. * * Return Value: a new #IdoScaleMenuItem. **/ GtkWidget* ido_scale_menu_item_new (const gchar *label, IdoRangeStyle range_style, GtkAdjustment *adjustment) { return g_object_new (IDO_TYPE_SCALE_MENU_ITEM, "adjustment", adjustment, "range-style", range_style, NULL); } /** * ido_scale_menu_item_new_with_label: * @label: the text of the menu item. * @size: The size style of the range. * @min: The minimum value of the slider. * @max: The maximum value of the slider. * @step: The step increment of the slider. * * Creates a new #IdoScaleMenuItem containing a label. * * Return Value: a new #IdoScaleMenuItem. **/ GtkWidget* ido_scale_menu_item_new_with_range (const gchar *label, IdoRangeStyle range_style, gdouble value, gdouble min, gdouble max, gdouble step) { GObject *adjustment = G_OBJECT (gtk_adjustment_new (value, min, max, step, 10 * step, 0)); return GTK_WIDGET (g_object_new (IDO_TYPE_SCALE_MENU_ITEM, "label", label, "range-style", range_style, "adjustment", adjustment, NULL)); } /** * ido_scale_menu_item_get_scale: * @menuitem: The #IdoScaleMenuItem * * Retrieves the scale widget. * * Return Value: (transfer none): The #IdoRange in this item **/ GtkWidget* ido_scale_menu_item_get_scale (IdoScaleMenuItem *menuitem) { IdoScaleMenuItemPrivate *priv; g_return_val_if_fail (IDO_IS_SCALE_MENU_ITEM (menuitem), NULL); priv = ido_scale_menu_item_get_instance_private (menuitem); return priv->scale; } /** * ido_scale_menu_item_get_style: * @menuitem: The #IdoScaleMenuItem * * Retrieves the type of widgets being used for the primary and * secondary widget slots. This could be images, labels, or nothing. * * Return Value: A #IdoScaleMenuItemStyle enum describing the style. **/ IdoScaleMenuItemStyle ido_scale_menu_item_get_style (IdoScaleMenuItem *menuitem) { IdoScaleMenuItemPrivate *priv; g_return_val_if_fail (IDO_IS_SCALE_MENU_ITEM (menuitem), IDO_SCALE_MENU_ITEM_STYLE_NONE); priv = ido_scale_menu_item_get_instance_private (menuitem); return priv->style; } /** * ido_scale_menu_item_set_style: * @menuitem: The #IdoScaleMenuItem * @style: Set the style use for the primary and secondary widget slots. * * Sets the type of widgets being used for the primary and * secondary widget slots. This could be images, labels, or nothing. **/ void ido_scale_menu_item_set_style (IdoScaleMenuItem *menuitem, IdoScaleMenuItemStyle style) { IdoScaleMenuItemPrivate *priv; g_return_if_fail (IDO_IS_SCALE_MENU_ITEM (menuitem)); priv = ido_scale_menu_item_get_instance_private (menuitem); priv->style = style; update_packing (menuitem, style); } /** * ido_scale_menu_item_get_primary_image: * @menuitem: The #IdoScaleMenuItem * * Retrieves a pointer to the image widget used in the primary slot. * Whether this is visible depends upon the return value from * ido_scale_menu_item_get_style(). * * Return Value: (transfer none): A #GtkWidget pointer for the primary image. **/ GtkWidget * ido_scale_menu_item_get_primary_image (IdoScaleMenuItem *menuitem) { IdoScaleMenuItemPrivate *priv; g_return_val_if_fail (IDO_IS_SCALE_MENU_ITEM (menuitem), NULL); priv = ido_scale_menu_item_get_instance_private (menuitem); return priv->primary_image; } /** * ido_scale_menu_item_get_secondary_image: * @menuitem: The #IdoScaleMenuItem * * Retrieves a pointer to the image widget used in the secondary slot. * Whether this is visible depends upon the return value from * ido_scale_menu_item_get_style(). * * Return Value: (transfer none): A #GtkWidget pointer for the secondary image. **/ GtkWidget * ido_scale_menu_item_get_secondary_image (IdoScaleMenuItem *menuitem) { IdoScaleMenuItemPrivate *priv; g_return_val_if_fail (IDO_IS_SCALE_MENU_ITEM (menuitem), NULL); priv = ido_scale_menu_item_get_instance_private (menuitem); return priv->secondary_image; } /** * ido_scale_menu_item_set_icons: * @item: a #IdoScaleMenuItem * @primary-icon: (allow-none): the primary icon, or %NULL * @secondary-icon: (allow-none): the secondary icon, %NULL * * Sets the icons of @item to @primary_icon and @secondary_icon. * Pass %NULL for either of them to unset the icon. */ static void ido_scale_menu_item_set_icons (IdoScaleMenuItem *item, GIcon *primary_icon, GIcon *secondary_icon) { GtkWidget *primary; GtkWidget *secondary; primary = ido_scale_menu_item_get_primary_image (item); secondary = ido_scale_menu_item_get_secondary_image (item); if (primary_icon) gtk_image_set_from_gicon (GTK_IMAGE (primary), primary_icon, GTK_ICON_SIZE_MENU); else gtk_image_clear (GTK_IMAGE (primary)); if (secondary_icon) gtk_image_set_from_gicon (GTK_IMAGE (secondary), secondary_icon, GTK_ICON_SIZE_MENU); else gtk_image_clear (GTK_IMAGE (secondary)); } /** * ido_scale_menu_item_get_primary_label: * @menuitem: The #IdoScaleMenuItem * * Retrieves a string of the text for the primary label widget. * Whether this is visible depends upon the return value from * ido_scale_menu_item_get_style(). * * Return Value: The label text. **/ const gchar* ido_scale_menu_item_get_primary_label (IdoScaleMenuItem *menuitem) { IdoScaleMenuItemPrivate *priv; g_return_val_if_fail (IDO_IS_SCALE_MENU_ITEM (menuitem), NULL); priv = ido_scale_menu_item_get_instance_private (menuitem); return gtk_label_get_text (GTK_LABEL (priv->primary_label)); } /** * ido_scale_menu_item_get_secondary_label: * @menuitem: The #IdoScaleMenuItem * * Retrieves a string of the text for the secondary label widget. * Whether this is visible depends upon the return value from * ido_scale_menu_item_get_style(). * * Return Value: The label text. **/ const gchar* ido_scale_menu_item_get_secondary_label (IdoScaleMenuItem *menuitem) { IdoScaleMenuItemPrivate *priv; g_return_val_if_fail (IDO_IS_SCALE_MENU_ITEM (menuitem), NULL); priv = ido_scale_menu_item_get_instance_private (menuitem); return gtk_label_get_text (GTK_LABEL (priv->secondary_label)); } /** * ido_scale_menu_item_set_primary_label: * @menuitem: The #IdoScaleMenuItem * @label: The label text * * Sets the text for the label widget in the primary slot. This * widget will only be visibile if the return value of * ido_scale_menu_item_get_style() is set to %IDO_SCALE_MENU_ITEM_STYLE_LABEL. **/ void ido_scale_menu_item_set_primary_label (IdoScaleMenuItem *menuitem, const gchar *label) { IdoScaleMenuItemPrivate *priv; g_return_if_fail (IDO_IS_SCALE_MENU_ITEM (menuitem)); priv = ido_scale_menu_item_get_instance_private (menuitem); if (priv->primary_label) { gtk_label_set_text (GTK_LABEL (priv->primary_label), label); } } /** * ido_scale_menu_item_set_secondary_label: * @menuitem: The #IdoScaleMenuItem * @label: The label text * * Sets the text for the label widget in the secondary slot. This * widget will only be visibile if the return value of * ido_scale_menu_item_get_style() is set to %IDO_SCALE_MENU_ITEM_STYLE_LABEL. **/ void ido_scale_menu_item_set_secondary_label (IdoScaleMenuItem *menuitem, const gchar *label) { IdoScaleMenuItemPrivate *priv; g_return_if_fail (IDO_IS_SCALE_MENU_ITEM (menuitem)); priv = ido_scale_menu_item_get_instance_private (menuitem); if (priv->secondary_label) { gtk_label_set_text (GTK_LABEL (priv->secondary_label), label); } } /** * ido_scale_menu_item_primary_clicked: * @menuitem: the #IdoScaleMenuItem * * Emits the "primary-clicked" signal. * * The default handler for this signal lowers the scale's * adjustment to its lower bound. */ void ido_scale_menu_item_primary_clicked (IdoScaleMenuItem * menuitem) { g_signal_emit (menuitem, signals[PRIMARY_CLICKED], 0); } static void default_primary_clicked_handler (IdoScaleMenuItem * item) { g_debug ("%s: setting scale to lower bound", G_STRFUNC); IdoScaleMenuItemPrivate * priv = ido_scale_menu_item_get_instance_private (item); GtkAdjustment *adj = gtk_range_get_adjustment (GTK_RANGE (priv->scale)); gtk_adjustment_set_value (adj, gtk_adjustment_get_lower (adj)); } /** * ido_scale_menu_item_secondary_clicked: * @menuitem: the #IdoScaleMenuItem * * Emits the "secondary-clicked" signal. * * The default handler for this signal raises the scale's * adjustment to its upper bound. */ void ido_scale_menu_item_secondary_clicked (IdoScaleMenuItem * menuitem) { g_signal_emit (menuitem, signals[SECONDARY_CLICKED], 0); } static void default_secondary_clicked_handler (IdoScaleMenuItem * item) { g_debug ("%s: setting scale to upper bound", G_STRFUNC); IdoScaleMenuItemPrivate * priv = ido_scale_menu_item_get_instance_private (item); GtkAdjustment *adj = gtk_range_get_adjustment (GTK_RANGE (priv->scale)); gtk_adjustment_set_value (adj, gtk_adjustment_get_upper (adj)); } /* ido_scale_menu_item_set_value: * * Sets the value of the scale inside @item to @value, without emitting * "value-changed". */ static void ido_scale_menu_item_set_value (IdoScaleMenuItem *item, gdouble value) { IdoScaleMenuItemPrivate *priv = ido_scale_menu_item_get_instance_private (item); /* set ignore_value_changed to signify to the scale menu item that it * should not emit its own value-changed signal, as that should only * be emitted when the value is changed by the user. */ priv->ignore_value_changed = TRUE; gtk_range_set_value (GTK_RANGE (priv->scale), value); priv->ignore_value_changed = FALSE; } /** * ido_scale_menu_item_state_changed: * * Updates a IdoScaleMenuItem from @state. State must be a double which * contains the current value of the slider. */ static void ido_scale_menu_item_state_changed (IdoActionHelper *helper, GVariant *state, gpointer user_data) { GtkWidget *menuitem; menuitem = ido_action_helper_get_widget (helper); ido_scale_menu_item_set_value (IDO_SCALE_MENU_ITEM (menuitem), g_variant_get_double (state)); } static void ido_scale_menu_item_value_changed (GtkScale *scale, gdouble value, gpointer user_data) { IdoActionHelper *helper = user_data; ido_action_helper_change_action_state (helper, g_variant_new_double (value)); } static GIcon * menu_item_get_icon (GMenuItem *menuitem, const gchar *attribute) { GVariant *value; value = g_menu_item_get_attribute_value (menuitem, attribute, NULL); return value ? g_icon_deserialize (value) : NULL; } /** * ido_scale_menu_item_new_from_model: * * Creates a new #IdoScaleMenuItem. If @menuitem contains an action, it * will be bound to that action in @actions. * * Returns: (transfer full): a new #IdoScaleMenuItem */ GtkMenuItem * ido_scale_menu_item_new_from_model (GMenuItem *menuitem, GActionGroup *actions) { GtkWidget *item; gchar *action; gdouble min = 0.0; gdouble max = 100.0; gdouble step = 1.0; GIcon *min_icon; GIcon *max_icon; g_menu_item_get_attribute (menuitem, "min-value", "d", &min); g_menu_item_get_attribute (menuitem, "max-value", "d", &max); g_menu_item_get_attribute (menuitem, "step", "d", &step); item = ido_scale_menu_item_new_with_range ("Volume", IDO_RANGE_STYLE_DEFAULT, 0.0, min, max, step); ido_scale_menu_item_set_style (IDO_SCALE_MENU_ITEM (item), IDO_SCALE_MENU_ITEM_STYLE_IMAGE); if (g_menu_item_get_attribute (menuitem, "action", "s", &action)) { IdoActionHelper *helper; helper = ido_action_helper_new (item, actions, action, NULL); g_signal_connect (helper, "action-state-changed", G_CALLBACK (ido_scale_menu_item_state_changed), NULL); g_signal_connect (item, "value-changed", G_CALLBACK (ido_scale_menu_item_value_changed), helper); g_signal_connect_swapped (item, "destroy", G_CALLBACK (g_object_unref), helper); g_free (action); } min_icon = menu_item_get_icon (menuitem, "min-icon"); max_icon = menu_item_get_icon (menuitem, "max-icon"); ido_scale_menu_item_set_icons (IDO_SCALE_MENU_ITEM (item), min_icon, max_icon); if (min_icon) g_object_unref (min_icon); if (max_icon) g_object_unref (max_icon); return GTK_MENU_ITEM (item); } #define __IDO_SCALE_MENU_ITEM_C__ ayatana-ido-0.10.1/src/idoscalemenuitem.h0000644000000000000000000001102414471671403015142 0ustar /* * Copyright 2010 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of either or both of the following licenses: * * 1) the GNU Lesser General Public License version 3, as published by the * Free Software Foundation; and/or * 2) the GNU Lesser General Public License version 2.1, as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License version 3 and version 2.1 along with this program. If not, see * * * Authors: * Cody Russell */ #ifndef __IDO_SCALE_MENU_ITEM_H__ #define __IDO_SCALE_MENU_ITEM_H__ #include #include "idorange.h" G_BEGIN_DECLS #define IDO_TYPE_SCALE_MENU_ITEM (ido_scale_menu_item_get_type ()) #define IDO_SCALE_MENU_ITEM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), IDO_TYPE_SCALE_MENU_ITEM, IdoScaleMenuItem)) #define IDO_SCALE_MENU_ITEM_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), IDO_TYPE_SCALE_MENU_ITEM, IdoScaleMenuItemClass)) #define IDO_IS_SCALE_MENU_ITEM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), IDO_TYPE_SCALE_MENU_ITEM)) #define IDO_IS_SCALE_MENU_ITEM_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), IDO_TYPE_SCALE_MENU_ITEM)) #define IDO_SCALE_MENU_ITEM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), IDO_TYPE_SCALE_MENU_ITEM, IdoScaleMenuItemClass)) typedef enum { IDO_SCALE_MENU_ITEM_STYLE_NONE, IDO_SCALE_MENU_ITEM_STYLE_IMAGE, IDO_SCALE_MENU_ITEM_STYLE_LABEL } IdoScaleMenuItemStyle; typedef struct _IdoScaleMenuItem IdoScaleMenuItem; typedef struct _IdoScaleMenuItemClass IdoScaleMenuItemClass; struct _IdoScaleMenuItem { GtkMenuItem parent_instance; }; struct _IdoScaleMenuItemClass { GtkMenuItemClass parent_class; /* signal default handlers */ void (*primary_clicked)(IdoScaleMenuItem * menuitem); void (*secondary_clicked)(IdoScaleMenuItem * menuitem); }; GType ido_scale_menu_item_get_type (void) G_GNUC_CONST; GtkWidget *ido_scale_menu_item_new (const gchar *label, IdoRangeStyle size, GtkAdjustment *adjustment); GtkWidget *ido_scale_menu_item_new_with_range (const gchar *label, IdoRangeStyle size, gdouble value, gdouble min, gdouble max, gdouble step); GtkWidget *ido_scale_menu_item_get_scale (IdoScaleMenuItem *menuitem); IdoScaleMenuItemStyle ido_scale_menu_item_get_style (IdoScaleMenuItem *menuitem); void ido_scale_menu_item_set_style (IdoScaleMenuItem *menuitem, IdoScaleMenuItemStyle style); GtkWidget *ido_scale_menu_item_get_primary_image (IdoScaleMenuItem *menuitem); GtkWidget *ido_scale_menu_item_get_secondary_image (IdoScaleMenuItem *menuitem); const gchar *ido_scale_menu_item_get_primary_label (IdoScaleMenuItem *menuitem); void ido_scale_menu_item_set_primary_label (IdoScaleMenuItem *menuitem, const gchar *label); const gchar *ido_scale_menu_item_get_secondary_label (IdoScaleMenuItem *menuitem); void ido_scale_menu_item_set_secondary_label (IdoScaleMenuItem *menuitem, const gchar *label); void ido_scale_menu_item_primary_clicked (IdoScaleMenuItem *menuitem); void ido_scale_menu_item_secondary_clicked (IdoScaleMenuItem *menuitem); GtkMenuItem * ido_scale_menu_item_new_from_model (GMenuItem *menuitem, GActionGroup *actions); G_END_DECLS #endif /* __IDO_SCALE_MENU_ITEM_H__ */ ayatana-ido-0.10.1/src/idosourcemenuitem.c0000644000000000000000000001651214471671403015355 0ustar /* * Copyright 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * Lars Uebernickel */ #include "idosourcemenuitem.h" #include #include "idodetaillabel.h" #include "idoactionhelper.h" typedef GtkMenuItemClass IdoSourceMenuItemClass; struct _IdoSourceMenuItem { GtkMenuItem parent; GtkWidget *icon; GtkWidget *label; GtkWidget *detail; gint64 time; guint timer_id; }; G_DEFINE_TYPE (IdoSourceMenuItem, ido_source_menu_item, GTK_TYPE_MENU_ITEM); static void ido_source_menu_item_constructed (GObject *object) { IdoSourceMenuItem *item = IDO_SOURCE_MENU_ITEM (object); GtkWidget *grid; gint icon_width; gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &icon_width, NULL); item->icon = g_object_ref (gtk_image_new ()); gtk_widget_set_margin_start(item->icon, icon_width); gtk_widget_set_margin_end(item->icon, 6); item->label = g_object_ref (gtk_label_new ("")); gtk_label_set_max_width_chars (GTK_LABEL (item->label), 40); gtk_label_set_ellipsize (GTK_LABEL (item->label), PANGO_ELLIPSIZE_END); gtk_widget_set_halign(item->label, GTK_ALIGN_START); gtk_widget_set_valign(item->label, GTK_ALIGN_CENTER); item->detail = g_object_ref (ido_detail_label_new ("")); gtk_widget_set_halign (item->detail, GTK_ALIGN_END); gtk_widget_set_hexpand (item->detail, TRUE); gtk_style_context_add_class (gtk_widget_get_style_context (item->detail), "accelerator"); grid = gtk_grid_new (); gtk_grid_attach (GTK_GRID (grid), item->icon, 0, 0, 1, 1); gtk_grid_attach (GTK_GRID (grid), item->label, 1, 0, 1, 1); gtk_grid_attach (GTK_GRID (grid), item->detail, 2, 0, 1, 1); gtk_container_add (GTK_CONTAINER (object), grid); gtk_widget_show_all (grid); G_OBJECT_CLASS (ido_source_menu_item_parent_class)->constructed (object); } static gchar * ido_source_menu_item_time_span_string (gint64 timestamp) { gchar *str; gint64 span; gint hours; gint minutes; span = MAX (g_get_real_time () - timestamp, 0) / G_USEC_PER_SEC; hours = span / 3600; minutes = (span / 60) % 60; if (hours == 0) { /* TRANSLATORS: number of minutes that have passed */ str = g_strdup_printf (ngettext ("%d min", "%d min", minutes), minutes); } else { /* TRANSLATORS: number of hours that have passed */ str = g_strdup_printf (ngettext ("%d h", "%d h", hours), hours); } return str; } static void ido_source_menu_item_set_detail_time (IdoSourceMenuItem *self, gint64 time) { gchar *str; self->time = time; str = ido_source_menu_item_time_span_string (self->time); ido_detail_label_set_text (IDO_DETAIL_LABEL (self->detail), str); g_free (str); } static gboolean ido_source_menu_item_update_time (gpointer data) { IdoSourceMenuItem *self = data; ido_source_menu_item_set_detail_time (self, self->time); return TRUE; } static void ido_source_menu_item_dispose (GObject *object) { IdoSourceMenuItem *self = IDO_SOURCE_MENU_ITEM (object); if (self->timer_id != 0) { g_source_remove (self->timer_id); self->timer_id = 0; } g_clear_object (&self->icon); g_clear_object (&self->label); g_clear_object (&self->detail); G_OBJECT_CLASS (ido_source_menu_item_parent_class)->dispose (object); } static void ido_source_menu_item_class_init (IdoSourceMenuItemClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->constructed = ido_source_menu_item_constructed; object_class->dispose = ido_source_menu_item_dispose; } static void ido_source_menu_item_init (IdoSourceMenuItem *self) { } static void ido_source_menu_item_set_label (IdoSourceMenuItem *item, const gchar *label) { gtk_label_set_label (GTK_LABEL (item->label), label ? label : ""); } static void ido_source_menu_item_set_icon (IdoSourceMenuItem *item, GIcon *icon) { if (icon) gtk_image_set_from_gicon (GTK_IMAGE (item->icon), icon, GTK_ICON_SIZE_MENU); else gtk_image_clear (GTK_IMAGE (item->icon)); } static void ido_source_menu_item_activate (GtkMenuItem *item, gpointer user_data) { IdoActionHelper *helper = user_data; /* The parameter signifies whether this source was activated (TRUE) or * dismissed (FALSE). Since there's no UI to dismiss a gtkmenuitem, * this always passes TRUE. */ ido_action_helper_activate_with_parameter (helper, g_variant_new_boolean (TRUE)); } static void ido_source_menu_item_state_changed (IdoActionHelper *helper, GVariant *state, gpointer user_data) { IdoSourceMenuItem *item = user_data; guint32 count; gint64 time; const gchar *str; if (item->timer_id != 0) { g_source_remove (item->timer_id); item->timer_id = 0; } g_return_if_fail (g_variant_is_of_type (state, G_VARIANT_TYPE ("(uxsb)"))); g_variant_get (state, "(ux&sb)", &count, &time, &str, NULL); if (count != 0) ido_detail_label_set_count (IDO_DETAIL_LABEL (item->detail), count); else if (time != 0) { ido_source_menu_item_set_detail_time (item, time); item->timer_id = g_timeout_add_seconds (59, ido_source_menu_item_update_time, item); } else if (str != NULL && *str) ido_detail_label_set_text (IDO_DETAIL_LABEL (item->detail), str); } GtkMenuItem * ido_source_menu_item_new_from_menu_model (GMenuItem *menuitem, GActionGroup *actions) { GtkMenuItem *item; GVariant *serialized_icon; GIcon *icon = NULL; gchar *label; gchar *action = NULL; item = g_object_new (IDO_TYPE_SOURCE_MENU_ITEM, NULL); if (g_menu_item_get_attribute (menuitem, "label", "s", &label)) { ido_source_menu_item_set_label (IDO_SOURCE_MENU_ITEM (item), label); g_free (label); } serialized_icon = g_menu_item_get_attribute_value (menuitem, "icon", NULL); if (serialized_icon) { icon = g_icon_deserialize (serialized_icon); g_variant_unref (serialized_icon); } ido_source_menu_item_set_icon (IDO_SOURCE_MENU_ITEM (item), icon); if (g_menu_item_get_attribute (menuitem, "action", "s", &action)) { IdoActionHelper *helper; helper = ido_action_helper_new (GTK_WIDGET (item), actions, action, NULL); g_signal_connect (helper, "action-state-changed", G_CALLBACK (ido_source_menu_item_state_changed), item); g_signal_connect_object (item, "activate", G_CALLBACK (ido_source_menu_item_activate), helper, 0); g_signal_connect_swapped (item, "destroy", G_CALLBACK (g_object_unref), helper); g_free (action); } if (icon) g_object_unref (icon); return item; } ayatana-ido-0.10.1/src/idosourcemenuitem.h0000644000000000000000000000265014471671403015360 0ustar /* * Copyright 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * Lars Uebernickel */ #ifndef __IDO_SOURCE_MENU_ITEM_H__ #define __IDO_SOURCE_MENU_ITEM_H__ #include #define IDO_TYPE_SOURCE_MENU_ITEM (ido_source_menu_item_get_type ()) #define IDO_SOURCE_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), IDO_TYPE_SOURCE_MENU_ITEM, IdoSourceMenuItem)) #define IDO_IS_SOURCE_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IDO_TYPE_SOURCE_MENU_ITEM)) typedef struct _IdoSourceMenuItem IdoSourceMenuItem; GType ido_source_menu_item_get_type (void); GtkMenuItem * ido_source_menu_item_new_from_menu_model (GMenuItem *menuitem, GActionGroup *actions); #endif ayatana-ido-0.10.1/src/idoswitchmenuitem.c0000644000000000000000000002020214471671403015345 0ustar /* * A GtkCheckMenuItem that uses a GtkSwitch to show its 'active' property * * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Charles Kerr */ #include "idoswitchmenuitem.h" #include "idoactionhelper.h" static void ido_switch_menu_finalize (GObject * item); static gboolean ido_switch_menu_button_release_event (GtkWidget * widget, GdkEventButton * event); typedef struct { GtkWidget * box; GtkWidget * content_area; GtkWidget * label; GtkWidget * image; GtkWidget * switch_w; } IdoSwitchMenuItemPrivate; /*** **** Life Cycle ***/ G_DEFINE_TYPE_WITH_PRIVATE (IdoSwitchMenuItem, ido_switch_menu_item, GTK_TYPE_CHECK_MENU_ITEM) static void ido_switch_menu_item_class_init (IdoSwitchMenuItemClass *klass) { GObjectClass * gobject_class; GtkWidgetClass * widget_class; GtkCheckMenuItemClass * check_class; gobject_class = G_OBJECT_CLASS (klass); gobject_class->finalize = ido_switch_menu_finalize; widget_class = GTK_WIDGET_CLASS (klass); widget_class->button_release_event = ido_switch_menu_button_release_event; check_class = GTK_CHECK_MENU_ITEM_CLASS (klass); check_class->draw_indicator = NULL; } static void ido_switch_menu_item_init (IdoSwitchMenuItem *item) { IdoSwitchMenuItemPrivate *priv = ido_switch_menu_item_get_instance_private(item); priv->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); priv->content_area = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); priv->switch_w = gtk_switch_new (); gtk_box_pack_start (GTK_BOX (priv->box), priv->content_area, TRUE, TRUE, 0); gtk_box_pack_end (GTK_BOX (priv->box), priv->switch_w, FALSE, FALSE, 0); gtk_container_add (GTK_CONTAINER (item), priv->box); gtk_widget_show_all (priv->box); g_object_bind_property (item, "active", priv->switch_w, "active", G_BINDING_SYNC_CREATE); } /*** **** Don't popdown the menu immediately after clicking on a switch... **** wait a moment so the user can see the GtkSwitch be toggled. ***/ static gboolean popdown_later_cb (gpointer widget) { GtkWidget * parent = gtk_widget_get_parent (widget); if (GTK_IS_MENU (parent)) { gtk_menu_shell_deactivate (GTK_MENU_SHELL(parent)); } g_object_unref (widget); return FALSE; /* only call this cb once */ } static gboolean ido_switch_menu_button_release_event (GtkWidget * widget, GdkEventButton * event) { gtk_menu_item_activate (GTK_MENU_ITEM(widget)); g_timeout_add (500, popdown_later_cb, g_object_ref(widget)); return TRUE; /* stop the event so that it doesn't trigger popdown() */ } /** * ido_switch_menu_item_new: * * Creates a new #IdoSwitchMenuItem * * Return Value: a new #IdoSwitchMenuItem. **/ GtkWidget * ido_switch_menu_item_new (void) { return g_object_new (IDO_TYPE_SWITCH_MENU_ITEM, NULL); } /** * ido_switch_menu_item_get_content_area: * @item: The #IdoSwitchMenuItem. * * Get the #GtkContainer to add additional widgets into. * * This function is dperecated. * * Return Value: (transfer none): The #GtkContainer to add additional widgets into. **/ GtkContainer * ido_switch_menu_item_get_content_area (IdoSwitchMenuItem * item) { static gboolean warned = FALSE; g_return_val_if_fail (IDO_IS_SWITCH_MENU_ITEM(item), NULL); IdoSwitchMenuItemPrivate *priv = ido_switch_menu_item_get_instance_private(item); if (!warned) { g_warning ("%s is deprecated. Please don't use it, especially if you're using" "ido_switch_menu_set_{label,icon}()", G_STRFUNC); warned = TRUE; } return GTK_CONTAINER (priv->content_area); } /** * ido_switch_menu_item_set_label: * @item: a #IdoSwitchMenuItem. * @label: a string to set as the label of @item * * Set the label of @item to @label. **/ void ido_switch_menu_item_set_label (IdoSwitchMenuItem *item, const gchar *label) { IdoSwitchMenuItemPrivate *priv; g_return_if_fail (IDO_IS_SWITCH_MENU_ITEM (item)); g_return_if_fail (label != NULL); priv = ido_switch_menu_item_get_instance_private(item); if (priv->label == NULL) { priv->label = gtk_label_new (NULL); gtk_widget_set_halign (priv->label, GTK_ALIGN_START); gtk_widget_show (priv->label); gtk_box_pack_end (GTK_BOX (priv->content_area), priv->label, TRUE, TRUE, 0); } gtk_label_set_text (GTK_LABEL (priv->label), label); } /** * ido_switch_menu_item_set_icon: * @item: a #IdoSwitchMenuItem. * @icon: (allow-none): a #GIcon * * Set the icon of @item to @icon. **/ void ido_switch_menu_item_set_icon (IdoSwitchMenuItem *item, GIcon *icon) { IdoSwitchMenuItemPrivate *priv; g_return_if_fail (IDO_IS_SWITCH_MENU_ITEM (item)); g_return_if_fail (icon == NULL || G_IS_ICON (icon)); priv = ido_switch_menu_item_get_instance_private(item); if (icon) { if (priv->image == NULL) { priv->image = gtk_image_new (); gtk_widget_show (priv->image); gtk_box_pack_start (GTK_BOX (priv->content_area), priv->image, FALSE, FALSE, 0); } gtk_image_set_from_gicon (GTK_IMAGE (priv->image), icon, GTK_ICON_SIZE_MENU); } else if (priv->image) { gtk_image_clear (GTK_IMAGE (priv->image)); } } static void ido_source_menu_item_state_changed (IdoActionHelper *helper, GVariant *state, gpointer user_data) { IdoSwitchMenuItem *item = IDO_SWITCH_MENU_ITEM (user_data); if (g_variant_is_of_type (state, G_VARIANT_TYPE_BOOLEAN)) gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), g_variant_get_boolean (state)); } static void ido_switch_menu_item_activate(IdoSwitchMenuItem *self, gpointer user_data) { g_return_if_fail(IDO_IS_SWITCH_MENU_ITEM(self)); IdoActionHelper *helper = user_data; IdoSwitchMenuItemPrivate *priv = ido_switch_menu_item_get_instance_private(self); gboolean active = gtk_switch_get_active(GTK_SWITCH(priv->switch_w)); ido_action_helper_activate_with_parameter(helper, g_variant_new_boolean(active)); } GtkMenuItem * ido_switch_menu_item_new_from_menu_model (GMenuItem *menuitem, GActionGroup *actions) { GtkMenuItem *item; gchar *label; GVariant *serialized_icon; gchar *action = NULL; item = g_object_new (IDO_TYPE_SWITCH_MENU_ITEM, NULL); if (g_menu_item_get_attribute (menuitem, "label", "s", &label)) { ido_switch_menu_item_set_label (IDO_SWITCH_MENU_ITEM (item), label); g_free (label); } serialized_icon = g_menu_item_get_attribute_value (menuitem, "icon", NULL); if (serialized_icon) { GIcon *icon; icon = g_icon_deserialize (serialized_icon); if (icon) { ido_switch_menu_item_set_icon (IDO_SWITCH_MENU_ITEM (item), icon); g_object_unref (icon); } g_variant_unref (serialized_icon); } if (g_menu_item_get_attribute (menuitem, "action", "s", &action)) { IdoActionHelper *helper; helper = ido_action_helper_new (GTK_WIDGET (item), actions, action, NULL); g_signal_connect (helper, "action-state-changed", G_CALLBACK (ido_source_menu_item_state_changed), item); g_signal_connect(item, "activate", G_CALLBACK(ido_switch_menu_item_activate), helper); g_signal_connect_swapped (item, "destroy", G_CALLBACK (g_object_unref), helper); g_free (action); } return item; } static void ido_switch_menu_finalize (GObject * item) { /* no-op */ } ayatana-ido-0.10.1/src/idoswitchmenuitem.h0000644000000000000000000000501214471671403015354 0ustar /* * A GtkCheckMenuItem that uses a GtkSwitch to show its 'active' property. * * Copyright © 2012 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Author: Charles Kerr */ #ifndef __IDO_SWITCH_MENU_ITEM_H__ #define __IDO_SWITCH_MENU_ITEM_H__ #include G_BEGIN_DECLS #define IDO_TYPE_SWITCH_MENU_ITEM (ido_switch_menu_item_get_type ()) #define IDO_SWITCH_MENU_ITEM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), IDO_TYPE_SWITCH_MENU_ITEM, IdoSwitchMenuItem)) #define IDO_SWITCH_MENU_ITEM_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), IDO_TYPE_SWITCH_MENU_ITEM, IdoSwitchMenuItemClass)) #define IDO_IS_SWITCH_MENU_ITEM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), IDO_TYPE_SWITCH_MENU_ITEM)) #define IDO_IS_SWITCH_MENU_ITEM_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), IDO_TYPE_SWITCH_MENU_ITEM)) #define IDO_SWITCH_MENU_ITEM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), IDO_TYPE_SWITCH_MENU_ITEM, IdoSwitchMenuItemClass)) typedef struct _IdoSwitchMenuItem IdoSwitchMenuItem; typedef struct _IdoSwitchMenuItemClass IdoSwitchMenuItemClass; struct _IdoSwitchMenuItem { GtkCheckMenuItem parent_instance; }; struct _IdoSwitchMenuItemClass { GtkCheckMenuItemClass parent_class; }; GType ido_switch_menu_item_get_type (void) G_GNUC_CONST; GtkWidget *ido_switch_menu_item_new (void); GtkContainer *ido_switch_menu_item_get_content_area (IdoSwitchMenuItem * item); GtkMenuItem * ido_switch_menu_item_new_from_menu_model (GMenuItem *menuitem, GActionGroup *actions); void ido_switch_menu_item_set_label (IdoSwitchMenuItem *item, const gchar *label); void ido_switch_menu_item_set_icon (IdoSwitchMenuItem *item, GIcon *icon); G_END_DECLS #endif /* __IDO_SWITCH_MENU_ITEM_H__ */ ayatana-ido-0.10.1/src/idotimeline.c0000644000000000000000000004715414471671403014125 0ustar /* -*- Mode: C; c-file-style: "gnu"; tab-width: 8 -*- */ /* gtktimeline.c * * Copyright (C) 2007 Carlos Garnacho * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #include "idotimeline.h" #include "idotypebuiltins.h" #include #include #define MSECS_PER_SEC 1000 #define FRAME_INTERVAL(nframes) (MSECS_PER_SEC / nframes) #define DEFAULT_FPS 30 typedef struct { guint duration; guint fps; guint source_id; GTimer *timer; gdouble progress; gdouble last_progress; GdkScreen *screen; guint animations_enabled : 1; guint loop : 1; guint direction : 1; } IdoTimelinePrivate; enum { PROP_0, PROP_FPS, PROP_DURATION, PROP_LOOP, PROP_DIRECTION, PROP_SCREEN }; enum { STARTED, PAUSED, FINISHED, FRAME, LAST_SIGNAL }; static guint signals [LAST_SIGNAL] = { 0, }; static void ido_timeline_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static void ido_timeline_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); static void ido_timeline_finalize (GObject *object); G_DEFINE_TYPE_WITH_PRIVATE (IdoTimeline, ido_timeline, G_TYPE_OBJECT) static void ido_timeline_class_init (IdoTimelineClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->set_property = ido_timeline_set_property; object_class->get_property = ido_timeline_get_property; object_class->finalize = ido_timeline_finalize; g_object_class_install_property (object_class, PROP_FPS, g_param_spec_uint ("fps", "FPS", "Frames per second for the timeline", 1, G_MAXUINT, DEFAULT_FPS, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_DURATION, g_param_spec_uint ("duration", "Animation Duration", "Animation Duration", 0, G_MAXUINT, 0, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_LOOP, g_param_spec_boolean ("loop", "Loop", "Whether the timeline loops or not", FALSE, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_DIRECTION, g_param_spec_enum ("direction", "Direction", "Whether the timeline moves forward or backward in time", IDO_TYPE_TIMELINE_DIRECTION, IDO_TIMELINE_DIRECTION_FORWARD, G_PARAM_READWRITE)); g_object_class_install_property (object_class, PROP_SCREEN, g_param_spec_object ("screen", "Screen", "Screen to get the settings from", GDK_TYPE_SCREEN, G_PARAM_READWRITE)); /** * IdoTimeline::started: * @timeline: The #IdoTimeline emitting the signal. * * The ::started signal is emitted when the timeline starts. */ signals[STARTED] = g_signal_new ("started", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (IdoTimelineClass, started), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * IdoTimeline::paused: * @timeline: The #IdoTimeline emitting the signal. * * The ::paused signal is emitted when the timeline pauses. */ signals[PAUSED] = g_signal_new ("paused", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (IdoTimelineClass, paused), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * IdoTimeline::finished: * @timeline: The #IdoTimeline emitting the signal. * * The ::paused signal is emitted when the timeline finishes. */ signals[FINISHED] = g_signal_new ("finished", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (IdoTimelineClass, finished), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * IdoTimeline::frame: * @timeline: The #IdoTimeline emitting the signal. * @progress: The progress position for this frame from 0.0 (start) to 1.0 (end). * * The ::frame signal is emitted when a frame should be drawn. */ signals[FRAME] = g_signal_new ("frame", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (IdoTimelineClass, frame), NULL, NULL, g_cclosure_marshal_VOID__DOUBLE, G_TYPE_NONE, 1, G_TYPE_DOUBLE); } static void ido_timeline_init (IdoTimeline *timeline) { IdoTimelinePrivate *priv = ido_timeline_get_instance_private (timeline); priv->fps = DEFAULT_FPS; priv->duration = 0.0; priv->direction = IDO_TIMELINE_DIRECTION_FORWARD; priv->screen = gdk_screen_get_default (); priv->last_progress = 0; } static void ido_timeline_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { IdoTimeline *timeline; timeline = IDO_TIMELINE (object); switch (prop_id) { case PROP_FPS: ido_timeline_set_fps (timeline, g_value_get_uint (value)); break; case PROP_DURATION: ido_timeline_set_duration (timeline, g_value_get_uint (value)); break; case PROP_LOOP: ido_timeline_set_loop (timeline, g_value_get_boolean (value)); break; case PROP_DIRECTION: ido_timeline_set_direction (timeline, g_value_get_enum (value)); break; case PROP_SCREEN: ido_timeline_set_screen (timeline, (GdkScreen*)g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void ido_timeline_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { IdoTimeline *timeline = IDO_TIMELINE (object); IdoTimelinePrivate *priv = ido_timeline_get_instance_private (timeline); switch (prop_id) { case PROP_FPS: g_value_set_uint (value, priv->fps); break; case PROP_DURATION: g_value_set_uint (value, priv->duration); break; case PROP_LOOP: g_value_set_boolean (value, priv->loop); break; case PROP_DIRECTION: g_value_set_enum (value, priv->direction); break; case PROP_SCREEN: g_value_set_object (value, priv->screen); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } static void ido_timeline_finalize (GObject *object) { IdoTimeline *timeline = IDO_TIMELINE (object); IdoTimelinePrivate *priv = ido_timeline_get_instance_private (timeline); if (priv->source_id) { g_source_remove (priv->source_id); priv->source_id = 0; } if (priv->timer) g_timer_destroy (priv->timer); G_OBJECT_CLASS (ido_timeline_parent_class)->finalize (object); } static gboolean ido_timeline_run_frame (IdoTimeline *timeline) { gdouble delta_progress, progress; guint elapsed_time; IdoTimelinePrivate *priv = ido_timeline_get_instance_private (timeline); elapsed_time = (guint) (g_timer_elapsed (priv->timer, NULL) * 1000); g_timer_start (priv->timer); if (priv->animations_enabled) { delta_progress = (gdouble) elapsed_time / priv->duration; progress = priv->last_progress; if (priv->direction == IDO_TIMELINE_DIRECTION_BACKWARD) progress -= delta_progress; else progress += delta_progress; priv->last_progress = progress; progress = CLAMP (progress, 0., 1.); } else progress = (priv->direction == IDO_TIMELINE_DIRECTION_FORWARD) ? 1.0 : 0.0; priv->progress = progress; g_signal_emit (timeline, signals [FRAME], 0, progress); if ((priv->direction == IDO_TIMELINE_DIRECTION_FORWARD && progress == 1.0) || (priv->direction == IDO_TIMELINE_DIRECTION_BACKWARD && progress == 0.0)) { if (!priv->loop) { if (priv->source_id) { g_source_remove (priv->source_id); priv->source_id = 0; } g_timer_stop (priv->timer); g_signal_emit (timeline, signals [FINISHED], 0); return FALSE; } else ido_timeline_rewind (timeline); } return TRUE; } /** * ido_timeline_new: * @duration: duration in milliseconds for the timeline * * Creates a new #IdoTimeline with the specified number of frames. * * Return Value: the newly created #IdoTimeline **/ IdoTimeline * ido_timeline_new (guint duration) { return g_object_new (IDO_TYPE_TIMELINE, "duration", duration, NULL); } /** * ido_timeline_new_for_screen: * @duration: duration in milliseconds for the timeline * @screen: Screen to start on. * * Creates a new #IdoTimeline with the specified number of frames on the given screen. * * Return Value: the newly created #IdoTimeline **/ IdoTimeline * ido_timeline_new_for_screen (guint duration, GdkScreen *screen) { return g_object_new (IDO_TYPE_TIMELINE, "duration", duration, "screen", screen, NULL); } /** * ido_timeline_start: * @timeline: A #IdoTimeline * * Runs the timeline from the current frame. **/ void ido_timeline_start (IdoTimeline *timeline) { IdoTimelinePrivate *priv; gboolean enable_animations = FALSE; g_return_if_fail (IDO_IS_TIMELINE (timeline)); priv = ido_timeline_get_instance_private (timeline); if (!priv->source_id) { if (priv->timer) g_timer_continue (priv->timer); else priv->timer = g_timer_new (); /* sanity check; CID: 12651 */ priv->fps = priv->fps > 0 ? priv->fps : DEFAULT_FPS; if (priv->screen) { #if 0 GtkSettings *settings = gtk_settings_get_for_screen (priv->screen); g_object_get (settings, "ido-enable-animations", &enable_animations, NULL); #else // XXX enable_animations = TRUE; #endif } priv->animations_enabled = (enable_animations == TRUE); g_signal_emit (timeline, signals [STARTED], 0); if (enable_animations) priv->source_id = gdk_threads_add_timeout (FRAME_INTERVAL (priv->fps), (GSourceFunc) ido_timeline_run_frame, timeline); else priv->source_id = gdk_threads_add_idle ((GSourceFunc) ido_timeline_run_frame, timeline); } } /** * ido_timeline_pause: * @timeline: A #IdoTimeline * * Pauses the timeline. **/ void ido_timeline_pause (IdoTimeline *timeline) { IdoTimelinePrivate *priv; g_return_if_fail (IDO_IS_TIMELINE (timeline)); priv = ido_timeline_get_instance_private (timeline); if (priv->source_id) { g_timer_stop (priv->timer); g_source_remove (priv->source_id); priv->source_id = 0; g_signal_emit (timeline, signals [PAUSED], 0); } } /** * ido_timeline_rewind: * @timeline: A #IdoTimeline * * Rewinds the timeline. **/ void ido_timeline_rewind (IdoTimeline *timeline) { IdoTimelinePrivate *priv; g_return_if_fail (IDO_IS_TIMELINE (timeline)); priv = ido_timeline_get_instance_private (timeline); if (ido_timeline_get_direction(timeline) != IDO_TIMELINE_DIRECTION_FORWARD) priv->progress = priv->last_progress = 1.; else priv->progress = priv->last_progress = 0.; /* reset timer */ if (priv->timer) { g_timer_start (priv->timer); if (!priv->source_id) g_timer_stop (priv->timer); } } /** * ido_timeline_is_running: * @timeline: A #IdoTimeline * * Returns whether the timeline is running or not. * * Return Value: %TRUE if the timeline is running **/ gboolean ido_timeline_is_running (IdoTimeline *timeline) { IdoTimelinePrivate *priv; g_return_val_if_fail (IDO_IS_TIMELINE (timeline), FALSE); priv = ido_timeline_get_instance_private (timeline); return (priv->source_id != 0); } /** * ido_timeline_get_fps: * @timeline: A #IdoTimeline * * Returns the number of frames per second. * * Return Value: frames per second **/ guint ido_timeline_get_fps (IdoTimeline *timeline) { IdoTimelinePrivate *priv; g_return_val_if_fail (IDO_IS_TIMELINE (timeline), 1); priv = ido_timeline_get_instance_private (timeline); return priv->fps; } /** * ido_timeline_set_fps: * @timeline: A #IdoTimeline * @fps: frames per second * * Sets the number of frames per second that * the timeline will play. **/ void ido_timeline_set_fps (IdoTimeline *timeline, guint fps) { IdoTimelinePrivate *priv; g_return_if_fail (IDO_IS_TIMELINE (timeline)); g_return_if_fail (fps > 0); priv = ido_timeline_get_instance_private (timeline); /* Coverity CID: 12650/12651: guard against division by 0. */ priv->fps = fps > 0 ? fps : priv->fps; if (ido_timeline_is_running (timeline)) { g_source_remove (priv->source_id); priv->source_id = gdk_threads_add_timeout (FRAME_INTERVAL (priv->fps), (GSourceFunc) ido_timeline_run_frame, timeline); } g_object_notify (G_OBJECT (timeline), "fps"); } /** * ido_timeline_get_loop: * @timeline: A #IdoTimeline * * Returns whether the timeline loops to the * beginning when it has reached the end. * * Return Value: %TRUE if the timeline loops **/ gboolean ido_timeline_get_loop (IdoTimeline *timeline) { IdoTimelinePrivate *priv; g_return_val_if_fail (IDO_IS_TIMELINE (timeline), FALSE); priv = ido_timeline_get_instance_private (timeline); return priv->loop; } /** * ido_timeline_set_loop: * @timeline: A #IdoTimeline * @loop: %TRUE to make the timeline loop * * Sets whether the timeline loops to the beginning * when it has reached the end. **/ void ido_timeline_set_loop (IdoTimeline *timeline, gboolean loop) { IdoTimelinePrivate *priv; g_return_if_fail (IDO_IS_TIMELINE (timeline)); priv = ido_timeline_get_instance_private (timeline); if (loop != priv->loop) { priv->loop = loop; g_object_notify (G_OBJECT (timeline), "loop"); } } /** * ido_timeline_set_duration: * @timeline: A #IdoTimeline * @duration: Duration in milliseconds. * * Set the animation duration. */ void ido_timeline_set_duration (IdoTimeline *timeline, guint duration) { IdoTimelinePrivate *priv; g_return_if_fail (IDO_IS_TIMELINE (timeline)); priv = ido_timeline_get_instance_private (timeline); if (duration != priv->duration) { priv->duration = duration; g_object_notify (G_OBJECT (timeline), "duration"); } } /** * ido_timeline_get_duration: * @timeline: A #IdoTimeline * * Set the animation duration. * * Return Value: Duration in milliseconds. */ guint ido_timeline_get_duration (IdoTimeline *timeline) { IdoTimelinePrivate *priv; g_return_val_if_fail (IDO_IS_TIMELINE (timeline), 0); priv = ido_timeline_get_instance_private (timeline); return priv->duration; } /** * ido_timeline_set_direction: * @timeline: A #IdoTimeline * @direction: direction * * Sets the direction of the timeline. **/ void ido_timeline_set_direction (IdoTimeline *timeline, IdoTimelineDirection direction) { IdoTimelinePrivate *priv; g_return_if_fail (IDO_IS_TIMELINE (timeline)); priv = ido_timeline_get_instance_private (timeline); if (direction != priv->direction) { priv->direction = direction; g_object_notify (G_OBJECT (timeline), "direction"); } } /** * ido_timeline_get_direction: * @timeline: A #IdoTimeline * * Returns the direction of the timeline. * * Return Value: direction **/ IdoTimelineDirection ido_timeline_get_direction (IdoTimeline *timeline) { IdoTimelinePrivate *priv; g_return_val_if_fail (IDO_IS_TIMELINE (timeline), IDO_TIMELINE_DIRECTION_FORWARD); priv = ido_timeline_get_instance_private (timeline); return priv->direction; } /** * ido_timeline_set_screen: * @timeline: A #IdoTimeline * @screen: A #GdkScreen to use * * Set the screen the timeline is running on. */ void ido_timeline_set_screen (IdoTimeline *timeline, GdkScreen *screen) { IdoTimelinePrivate *priv; g_return_if_fail (IDO_IS_TIMELINE (timeline)); g_return_if_fail (GDK_IS_SCREEN (screen)); priv = ido_timeline_get_instance_private (timeline); if (priv->screen) g_object_unref (priv->screen); priv->screen = g_object_ref (screen); g_object_notify (G_OBJECT (timeline), "screen"); } /** * ido_timeline_get_screen: * @timeline: A #IdoTimeline * * Get the screen this timeline is running on. * * Return Value: (transfer none): The #GdkScreen this timeline is running on. */ GdkScreen * ido_timeline_get_screen (IdoTimeline *timeline) { IdoTimelinePrivate *priv; g_return_val_if_fail (IDO_IS_TIMELINE (timeline), NULL); priv = ido_timeline_get_instance_private (timeline); return priv->screen; } /** * ido_timeline_get_progress: * @timeline: A #IdoTimeline * * Get the progress on the timeline. * * Return Value: The progress from 0.0 (start) to 1.0 (end) */ gdouble ido_timeline_get_progress (IdoTimeline *timeline) { IdoTimelinePrivate *priv; g_return_val_if_fail (IDO_IS_TIMELINE (timeline), 0.); priv = ido_timeline_get_instance_private (timeline); return priv->progress; } /** * ido_timeline_set_progress: * @timeline: A #IdoTimeline * @progress: The progress from 0.0 (start) to 1.0 (end) * * Set the progress on the timeline. */ void ido_timeline_set_progress (IdoTimeline *timeline, gdouble progress) { IdoTimelinePrivate *priv; g_return_if_fail (IDO_IS_TIMELINE (timeline)); priv = ido_timeline_get_instance_private (timeline); if (priv->source_id) { g_timer_stop (priv->timer); g_source_remove (priv->source_id); priv->source_id = 0; } priv->progress = priv->last_progress = progress; ido_timeline_start (timeline); } /** * ido_timeline_calculate_progress: * @linear_progress: The progress from 0.0 (start) to 1.0 (end) * @progress_type: The progress transform to apply * * Transform a linear progress position using the given transform. * * Return Value: the progress position using the provided transform. */ gdouble ido_timeline_calculate_progress (gdouble linear_progress, IdoTimelineProgressType progress_type) { gdouble progress; progress = linear_progress; switch (progress_type) { case IDO_TIMELINE_PROGRESS_LINEAR: break; case IDO_TIMELINE_PROGRESS_SINUSOIDAL: progress = sinf ((progress * G_PI) / 2); break; case IDO_TIMELINE_PROGRESS_EXPONENTIAL: progress *= progress; break; case IDO_TIMELINE_PROGRESS_EASE_IN_EASE_OUT: { progress *= 2; if (progress < 1) progress = pow (progress, 3) / 2; else progress = (pow (progress - 2, 3) + 2) / 2; } } return progress; } ayatana-ido-0.10.1/src/idotimeline.h0000644000000000000000000001163714471671403014127 0ustar /* * Copyright (C) 2007 Carlos Garnacho * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #ifndef __IDO_TIMELINE_H__ #define __IDO_TIMELINE_H__ #include #include #include G_BEGIN_DECLS #define IDO_TYPE_TIMELINE (ido_timeline_get_type ()) #define IDO_TIMELINE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), IDO_TYPE_TIMELINE, IdoTimeline)) #define IDO_TIMELINE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), IDO_TYPE_TIMELINE, IdoTimelineClass)) #define IDO_IS_TIMELINE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), IDO_TYPE_TIMELINE)) #define IDO_IS_TIMELINE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), IDO_TYPE_TIMELINE)) #define IDO_TIMELINE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), IDO_TYPE_TIMELINE, IdoTimelineClass)) typedef struct IdoTimeline IdoTimeline; typedef struct IdoTimelineClass IdoTimelineClass; typedef enum { IDO_TIMELINE_DIRECTION_FORWARD, IDO_TIMELINE_DIRECTION_BACKWARD } IdoTimelineDirection; typedef enum { IDO_TIMELINE_PROGRESS_LINEAR, IDO_TIMELINE_PROGRESS_SINUSOIDAL, IDO_TIMELINE_PROGRESS_EXPONENTIAL, IDO_TIMELINE_PROGRESS_EASE_IN_EASE_OUT } IdoTimelineProgressType; struct IdoTimeline { GObject parent_instance; }; struct IdoTimelineClass { GObjectClass parent_class; void (* started) (IdoTimeline *timeline); void (* finished) (IdoTimeline *timeline); void (* paused) (IdoTimeline *timeline); void (* frame) (IdoTimeline *timeline, gdouble progress); void (* __ido_reserved1) (void); void (* __ido_reserved2) (void); void (* __ido_reserved3) (void); void (* __ido_reserved4) (void); }; GType ido_timeline_get_type (void) G_GNUC_CONST; IdoTimeline *ido_timeline_new (guint duration); IdoTimeline *ido_timeline_new_for_screen (guint duration, GdkScreen *screen); void ido_timeline_start (IdoTimeline *timeline); void ido_timeline_pause (IdoTimeline *timeline); void ido_timeline_rewind (IdoTimeline *timeline); gboolean ido_timeline_is_running (IdoTimeline *timeline); guint ido_timeline_get_fps (IdoTimeline *timeline); void ido_timeline_set_fps (IdoTimeline *timeline, guint fps); gboolean ido_timeline_get_loop (IdoTimeline *timeline); void ido_timeline_set_loop (IdoTimeline *timeline, gboolean loop); guint ido_timeline_get_duration (IdoTimeline *timeline); void ido_timeline_set_duration (IdoTimeline *timeline, guint duration); GdkScreen *ido_timeline_get_screen (IdoTimeline *timeline); void ido_timeline_set_screen (IdoTimeline *timeline, GdkScreen *screen); IdoTimelineDirection ido_timeline_get_direction (IdoTimeline *timeline); void ido_timeline_set_direction (IdoTimeline *timeline, IdoTimelineDirection direction); gdouble ido_timeline_get_progress (IdoTimeline *timeline); void ido_timeline_set_progress (IdoTimeline *timeline, gdouble progress); gdouble ido_timeline_calculate_progress (gdouble linear_progress, IdoTimelineProgressType progress_type); G_END_DECLS #endif /* __IDO_TIMELINE_H__ */ ayatana-ido-0.10.1/src/idotimestampmenuitem.c0000644000000000000000000001443114471671403016056 0ustar /* * Copyright 2013 Canonical Ltd. * * Authors: * Charles Kerr * Ted Gould * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include /* strstr() */ #include #include "idoactionhelper.h" #include "idotimestampmenuitem.h" enum { PROP_0, PROP_FORMAT, PROP_DATE_TIME, PROP_LAST }; static GParamSpec *properties[PROP_LAST]; typedef struct { char * format; GDateTime * date_time; } IdoTimeStampMenuItemPrivate; G_DEFINE_TYPE_WITH_PRIVATE (IdoTimeStampMenuItem, ido_time_stamp_menu_item, IDO_TYPE_BASIC_MENU_ITEM); /*** **** GObject Virtual Functions ***/ static void my_get_property (GObject * o, guint property_id, GValue * v, GParamSpec * pspec) { IdoTimeStampMenuItem * self = IDO_TIME_STAMP_MENU_ITEM (o); IdoTimeStampMenuItemPrivate * priv = ido_time_stamp_menu_item_get_instance_private(self); switch (property_id) { case PROP_FORMAT: g_value_set_string (v, priv->format); break; case PROP_DATE_TIME: g_value_set_boxed (v, priv->date_time); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec); break; } } static void my_set_property (GObject * o, guint property_id, const GValue * v, GParamSpec * pspec) { IdoTimeStampMenuItem * self = IDO_TIME_STAMP_MENU_ITEM (o); switch (property_id) { case PROP_FORMAT: ido_time_stamp_menu_item_set_format (self, g_value_get_string (v)); break; case PROP_DATE_TIME: ido_time_stamp_menu_item_set_date_time (self, g_value_get_boxed (v)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec); break; } } static void my_dispose (GObject * object) { IdoTimeStampMenuItem * self = IDO_TIME_STAMP_MENU_ITEM (object); IdoTimeStampMenuItemPrivate * priv = ido_time_stamp_menu_item_get_instance_private(self); g_clear_pointer (&priv->date_time, g_date_time_unref); G_OBJECT_CLASS (ido_time_stamp_menu_item_parent_class)->dispose (object); } static void my_finalize (GObject * object) { IdoTimeStampMenuItem * self = IDO_TIME_STAMP_MENU_ITEM (object); IdoTimeStampMenuItemPrivate * priv = ido_time_stamp_menu_item_get_instance_private(self); g_free (priv->format); G_OBJECT_CLASS (ido_time_stamp_menu_item_parent_class)->finalize (object); } /*** **** Instantiation ***/ static void ido_time_stamp_menu_item_class_init (IdoTimeStampMenuItemClass *klass) { GParamFlags prop_flags; GObjectClass * gobject_class = G_OBJECT_CLASS (klass); gobject_class->get_property = my_get_property; gobject_class->set_property = my_set_property; gobject_class->dispose = my_dispose; gobject_class->finalize = my_finalize; prop_flags = G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS; properties[PROP_FORMAT] = g_param_spec_string ( "format", "strftime format", "strftime-style format string for the timestamp", "%F %T", prop_flags); properties[PROP_DATE_TIME] = g_param_spec_boxed ( "date-time", "Date-Time", "GDateTime specifying the time to render", G_TYPE_DATE_TIME, prop_flags); g_object_class_install_properties (gobject_class, PROP_LAST, properties); } static void ido_time_stamp_menu_item_init (IdoTimeStampMenuItem *self) { /* no-op */ } static void update_timestamp_label (IdoTimeStampMenuItem * self) { char * str; IdoTimeStampMenuItemPrivate * priv = ido_time_stamp_menu_item_get_instance_private(self); if (priv->date_time && priv->format) str = g_date_time_format (priv->date_time, priv->format); else str = NULL; ido_basic_menu_item_set_secondary_text (IDO_BASIC_MENU_ITEM (self), str); g_free (str); } /*** **** Public API ***/ /* create a new IdoTimeStampMenuItem */ GtkWidget * ido_time_stamp_menu_item_new (void) { return GTK_WIDGET (g_object_new (IDO_TYPE_TIME_STAMP_MENU_ITEM, NULL)); } /** * ido_time_stamp_menu_item_set_time: * @time: the time to be rendered in the appointment's timestamp label. * * Set the time that will be displayed in the menuitem's * right-justified timestamp label */ void ido_time_stamp_menu_item_set_date_time (IdoTimeStampMenuItem * self, GDateTime * date_time) { IdoTimeStampMenuItemPrivate * priv; g_return_if_fail (IDO_IS_TIME_STAMP_MENU_ITEM (self)); priv = ido_time_stamp_menu_item_get_instance_private(self); g_clear_pointer (&priv->date_time, g_date_time_unref); if (date_time != NULL) priv->date_time = g_date_time_ref (date_time); update_timestamp_label (self); } /** * ido_time_stamp_menu_item_set_format: * @format: the format string used when showing the appointment's time * * Set the format string for rendering the appointment's time * in its right-justified secondary label. * * See strfrtime(3) for more information on the format string. */ void ido_time_stamp_menu_item_set_format (IdoTimeStampMenuItem * self, const char * strftime_fmt) { IdoTimeStampMenuItemPrivate * priv; g_return_if_fail (IDO_IS_TIME_STAMP_MENU_ITEM (self)); priv = ido_time_stamp_menu_item_get_instance_private(self); g_free (priv->format); priv->format = g_strdup (strftime_fmt); update_timestamp_label (self); } const gchar * ido_time_stamp_menu_item_get_format (IdoTimeStampMenuItem * self) { IdoTimeStampMenuItemPrivate * priv; g_return_val_if_fail (IDO_IS_TIME_STAMP_MENU_ITEM (self), NULL); priv = ido_time_stamp_menu_item_get_instance_private(self); return priv->format; } ayatana-ido-0.10.1/src/idotimestampmenuitem.h0000644000000000000000000000443414471671403016065 0ustar /** * Copyright 2013 Canonical Ltd. * * Authors: * Charles Kerr * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #ifndef __IDO_TIME_STAMP_MENU_ITEM_H__ #define __IDO_TIME_STAMP_MENU_ITEM_H__ #include #include "idobasicmenuitem.h" G_BEGIN_DECLS #define IDO_TYPE_TIME_STAMP_MENU_ITEM (ido_time_stamp_menu_item_get_type ()) #define IDO_TIME_STAMP_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), IDO_TYPE_TIME_STAMP_MENU_ITEM, IdoTimeStampMenuItem)) #define IDO_IS_TIME_STAMP_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IDO_TYPE_TIME_STAMP_MENU_ITEM)) typedef struct _IdoTimeStampMenuItem IdoTimeStampMenuItem; typedef struct _IdoTimeStampMenuItemClass IdoTimeStampMenuItemClass; struct _IdoTimeStampMenuItemClass { IdoBasicMenuItemClass parent_class; }; /** * A menuitem that contains a left-aligned optional icon and label * and a right-aligned secondary label showing the specified time * in the specified format. * * Used by IdoLocationMenuItem, IdoAppointmentMenuItem, and IdoAlarmMenuItem. */ struct _IdoTimeStampMenuItem { /*< private >*/ IdoBasicMenuItem parent; }; GType ido_time_stamp_menu_item_get_type (void) G_GNUC_CONST; GtkWidget * ido_time_stamp_menu_item_new (void); void ido_time_stamp_menu_item_set_date_time (IdoTimeStampMenuItem * menuitem, GDateTime * date_time); void ido_time_stamp_menu_item_set_format (IdoTimeStampMenuItem * menuitem, const char * strftime_fmt); const char * ido_time_stamp_menu_item_get_format (IdoTimeStampMenuItem * menuitem); G_END_DECLS #endif ayatana-ido-0.10.1/src/idotypebuiltins.c.template0000644000000000000000000000135614471671403016656 0ustar /*** BEGIN file-header ***/ #include "idotypebuiltins.h" /*** END file-header ***/ /*** BEGIN file-production ***/ /* enumerations from "@filename@" */ #include "@filename@" /*** END file-production ***/ /*** BEGIN value-header ***/ GType @enum_name@_get_type(void) { static GType enum_type_id = 0; if (G_UNLIKELY (!enum_type_id)) { static const G@Type@Value values[] = { /*** END value-header ***/ /*** BEGIN value-production ***/ { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, /*** END value-production ***/ /*** BEGIN value-tail ***/ { 0, NULL, NULL } }; enum_type_id = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); } return enum_type_id; } /*** END value-tail ***/ ayatana-ido-0.10.1/src/idotypebuiltins.h.template0000644000000000000000000000100214471671403016647 0ustar /*** BEGIN file-header ***/ #ifndef __IDO_ENUM_TYPES_H__ #define __IDO_ENUM_TYPES_H__ #include G_BEGIN_DECLS /*** END file-header ***/ /*** BEGIN file-production ***/ /* enumerations from "@filename@" */ /*** END file-production ***/ /*** BEGIN file-tail ***/ G_END_DECLS #endif /* !__IDO_ENUM_TYPES_H__ */ /*** END file-tail ***/ /*** BEGIN value-header ***/ GType @enum_name@_get_type (void) G_GNUC_CONST; #define IDO_TYPE_@ENUMSHORT@ (@enum_name@_get_type()) /*** END value-header ***/ ayatana-ido-0.10.1/src/idousermenuitem.c0000644000000000000000000004135414471671403015035 0ustar /* Copyright 2011 Canonical Ltd. Copyright 2023 Robert Tari Authors: Conor Curran Mirco Müller Charles Kerr Robert Tari This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include "idousermenuitem.h" #include "idoactionhelper.h" #define FALLBACK_ICON_NAME "avatar-default" enum { PROP_0, PROP_LABEL, PROP_ICON, PROP_IS_LOGGED_IN, PROP_IS_CURRENT_USER, PROP_LAST }; static GParamSpec *properties[PROP_LAST]; typedef struct { GtkWidget* user_image; GtkWidget* user_name; GtkWidget* container; GtkWidget* tick_icon; gboolean is_logged_in; gboolean is_current_user; gchar * label; GIcon * icon; } IdoUserMenuItemPrivate; G_DEFINE_TYPE_WITH_PRIVATE (IdoUserMenuItem, ido_user_menu_item, GTK_TYPE_MENU_ITEM); /* Prototypes */ static gboolean ido_user_menu_item_primitive_draw_cb_gtk_3 (GtkWidget * image, cairo_t * cr, gpointer gself); /*** **** GObject virtual functions ***/ static void my_get_property (GObject * o, guint property_id, GValue * value, GParamSpec * pspec) { IdoUserMenuItem * self = IDO_USER_MENU_ITEM (o); IdoUserMenuItemPrivate * priv = ido_user_menu_item_get_instance_private(self); switch (property_id) { case PROP_LABEL: g_value_set_string (value, priv->label); break; case PROP_ICON: g_value_set_object (value, priv->icon); break; case PROP_IS_LOGGED_IN: g_value_set_boolean (value, priv->is_logged_in); break; case PROP_IS_CURRENT_USER: g_value_set_boolean (value, priv->is_current_user); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec); break; } } static void my_set_property (GObject * o, guint property_id, const GValue * value, GParamSpec * pspec) { IdoUserMenuItem * self = IDO_USER_MENU_ITEM (o); IdoUserMenuItemPrivate * priv = ido_user_menu_item_get_instance_private(self); switch (property_id) { case PROP_LABEL: ido_user_menu_item_set_label (self, g_value_get_string (value)); break; case PROP_ICON: ido_user_menu_item_set_icon (self, g_value_get_object (value)); break; case PROP_IS_LOGGED_IN: ido_user_menu_item_set_logged_in (self, g_value_get_boolean (value)); break; case PROP_IS_CURRENT_USER: priv->is_current_user = g_value_get_boolean (value); gtk_widget_queue_draw (GTK_WIDGET(self)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec); break; } } static void my_dispose (GObject *object) { IdoUserMenuItem * self = IDO_USER_MENU_ITEM (object); IdoUserMenuItemPrivate * priv = ido_user_menu_item_get_instance_private(self); g_clear_object (&priv->icon); G_OBJECT_CLASS (ido_user_menu_item_parent_class)->dispose (object); } static void my_finalize (GObject *object) { IdoUserMenuItem * self = IDO_USER_MENU_ITEM (object); IdoUserMenuItemPrivate * priv = ido_user_menu_item_get_instance_private(self); g_free (priv->label); G_OBJECT_CLASS (ido_user_menu_item_parent_class)->finalize (object); } static void ido_user_menu_item_class_init (IdoUserMenuItemClass *klass) { GParamFlags prop_flags; GObjectClass * gobject_class = G_OBJECT_CLASS (klass); gobject_class->get_property = my_get_property; gobject_class->set_property = my_set_property; gobject_class->dispose = my_dispose; gobject_class->finalize = my_finalize; prop_flags = G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS; properties[PROP_LABEL] = g_param_spec_string ("label", "The user's name", "The name to display", "J. Random User", prop_flags); properties[PROP_ICON] = g_param_spec_object ("icon", "Icon", "The user's GIcon", G_TYPE_OBJECT, prop_flags); properties[PROP_IS_LOGGED_IN] = g_param_spec_boolean ("is-logged-in", "is logged in", "is user logged in?", FALSE, prop_flags); properties[PROP_IS_CURRENT_USER] = g_param_spec_boolean ("is-current-user", "is current user", "is user current?", FALSE, prop_flags); g_object_class_install_properties (gobject_class, PROP_LAST, properties); } static void ido_user_menu_item_init (IdoUserMenuItem *self) { IdoUserMenuItemPrivate * priv = ido_user_menu_item_get_instance_private(self); // Create the UI elements. priv->user_image = gtk_image_new (); gtk_image_set_from_icon_name (GTK_IMAGE (priv->user_image), FALLBACK_ICON_NAME, GTK_ICON_SIZE_MENU); priv->user_name = gtk_label_new (NULL); priv->container = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); priv->tick_icon = gtk_image_new_from_icon_name ("account-logged-in", GTK_ICON_SIZE_MENU); gtk_widget_set_halign(priv->tick_icon, GTK_ALIGN_END); gtk_widget_set_valign(priv->tick_icon, GTK_ALIGN_CENTER); // Pack it together gtk_box_pack_start (GTK_BOX (priv->container), priv->user_image, FALSE, TRUE, 0); gtk_box_pack_start (GTK_BOX (priv->container), priv->user_name, FALSE, FALSE, 3); gtk_box_pack_end (GTK_BOX(priv->container), priv->tick_icon, FALSE, FALSE, 5); gtk_widget_show_all (priv->container); gtk_container_add (GTK_CONTAINER (self), priv->container); gtk_widget_show_all (priv->tick_icon); gtk_widget_set_no_show_all (priv->tick_icon, TRUE); gtk_widget_hide (priv->tick_icon); // Fetch the drawing context. g_signal_connect_after (GTK_WIDGET(self), "draw", G_CALLBACK(ido_user_menu_item_primitive_draw_cb_gtk_3), GTK_WIDGET(self)); } /*****************************************************************/ static gboolean ido_user_menu_item_primitive_draw_cb_gtk_3 (GtkWidget * widget, cairo_t * cr, gpointer user_data) { IdoUserMenuItemPrivate * priv; g_return_val_if_fail(IS_IDO_USER_MENU_ITEM(user_data), FALSE); priv = ido_user_menu_item_get_instance_private(IDO_USER_MENU_ITEM(user_data)); /* Draw dot only when user is the current user. */ if (priv->is_current_user) { GtkStyleContext * style_context; GtkStateFlags state_flags; GdkRGBA color; gdouble x, y; /* get the foreground color */ style_context = gtk_widget_get_style_context (widget); state_flags = gtk_widget_get_state_flags (widget); gtk_style_context_get_color (style_context, state_flags, &color); GtkAllocation allocation; gtk_widget_get_allocation (widget, &allocation); x = allocation.x + 13; y = allocation.height / 2; cairo_arc (cr, x, y, 3.0, 0.0, 2 * G_PI); gdk_cairo_set_source_rgba (cr, &color); cairo_fill (cr); } return FALSE; } /*** **** Avatar ***/ static gboolean ido_user_menu_item_set_icon_from_file_icon (IdoUserMenuItem *self, GFileIcon *icon) { GFile *file; gchar *path; gint width; gint height; GdkPixbuf *pixbuf; IdoUserMenuItemPrivate * priv = ido_user_menu_item_get_instance_private(self); file = g_file_icon_get_file (G_FILE_ICON (icon)); path = g_file_get_path (file); /* width and height will always be set by this function */ gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height); pixbuf = gdk_pixbuf_new_from_file_at_scale (path, width, height, TRUE, NULL); g_free (path); if (pixbuf) { gtk_image_set_from_pixbuf (GTK_IMAGE (priv->user_image), pixbuf); g_object_unref (pixbuf); return TRUE; } return FALSE; } /*** **** PUBLIC API ***/ void ido_user_menu_item_set_icon (IdoUserMenuItem * self, GIcon * icon) { IdoUserMenuItemPrivate * priv = ido_user_menu_item_get_instance_private(self); if (priv->icon == icon) return; g_clear_object (&priv->icon); if (icon) priv->icon = g_object_ref (icon); /* Avatars are always loaded from disk. Show the fallback when no icon * is set, the icon is not a file icon, or the file could not be * found. */ if (icon == NULL || !G_IS_FILE_ICON (icon) || !ido_user_menu_item_set_icon_from_file_icon (self, G_FILE_ICON (icon))) { gtk_image_set_from_icon_name (GTK_IMAGE (priv->user_image), FALLBACK_ICON_NAME, GTK_ICON_SIZE_MENU); } } void ido_user_menu_item_set_icon_from_file (IdoUserMenuItem * self, const char * filename) { GFile * file = filename ? g_file_new_for_path (filename) : NULL; GIcon * icon = file ? g_file_icon_new (file) : NULL; ido_user_menu_item_set_icon (self, icon); g_clear_object (&icon); g_clear_object (&file); } void ido_user_menu_item_set_logged_in (IdoUserMenuItem * self, gboolean is_logged_in) { IdoUserMenuItemPrivate * priv = ido_user_menu_item_get_instance_private(self); gtk_widget_set_visible (priv->tick_icon, is_logged_in); } void ido_user_menu_item_set_current_user (IdoUserMenuItem * self, gboolean is_current_user) { IdoUserMenuItemPrivate * priv = ido_user_menu_item_get_instance_private(self); priv->is_current_user = is_current_user; gtk_widget_queue_draw (GTK_WIDGET (self)); } void ido_user_menu_item_set_label (IdoUserMenuItem * self, const char * label) { IdoUserMenuItemPrivate * priv = ido_user_menu_item_get_instance_private(self); gtk_label_set_label (GTK_LABEL(priv->user_name), label); } GtkWidget* ido_user_menu_item_new (void) { return GTK_WIDGET (g_object_new (IDO_USER_MENU_ITEM_TYPE, NULL)); } /*** **** ***/ /* * This is a helper function for creating user menuitems for both * "org.ayatana.indicator.user-menu-item" and "org.ayatana.indicator.guest-menu-item", * since they only differ in how they use their action's state. */ static GtkMenuItem * user_menu_item_new_from_model (GMenuItem * menuitem, GActionGroup * actions, GCallback state_changed_callback) { guint i; guint n; IdoUserMenuItem * ido_user; gchar * str; gchar * action; GVariant * v; const gchar * names [2]; GValue * values; const guint n_max = 2; /* create the ido_user */ n = 0; values = g_new0(GValue, n_max); if (g_menu_item_get_attribute (menuitem, G_MENU_ATTRIBUTE_LABEL, "s", &str)) { names[n] = "label"; g_value_init (&values[n], G_TYPE_STRING); g_value_take_string (&values[n], str); n++; } if ((v = g_menu_item_get_attribute_value (menuitem, G_MENU_ATTRIBUTE_ICON, NULL))) { names[n] = "icon"; GIcon * icon = g_icon_deserialize (v); g_value_init (&values[n], G_TYPE_OBJECT); g_value_take_object (&values[n], icon); g_variant_unref (v); n++; } g_assert (n <= G_N_ELEMENTS (names)); g_assert (n <= n_max); ido_user = IDO_USER_MENU_ITEM(g_object_new_with_properties (IDO_USER_MENU_ITEM_TYPE, n, names, values)); for (i=0; i This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef __IDO_USER_MENU_ITEM_H__ #define __IDO_USER_MENU_ITEM_H__ #include G_BEGIN_DECLS #define IDO_USER_MENU_ITEM_TYPE (ido_user_menu_item_get_type ()) #define IDO_USER_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), IDO_USER_MENU_ITEM_TYPE, IdoUserMenuItem)) #define IDO_USER_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), IDO_USER_MENU_ITEM_TYPE, IdoUserMenuItemClass)) #define IS_IDO_USER_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IDO_USER_MENU_ITEM_TYPE)) #define IS_IDO_USER_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), IDO_USER_MENU_ITEM_TYPE)) #define IDO_USER_MENU_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), IDO_USER_MENU_ITEM_TYPE, IdoUserMenuItemClass)) typedef struct _IdoUserMenuItem IdoUserMenuItem; typedef struct _IdoUserMenuItemClass IdoUserMenuItemClass; /* property keys */ #define IDO_USER_MENU_ITEM_PROP_LABEL "label" #define IDO_USER_MENU_ITEM_PROP_ICON_FILENAME "icon-filename" #define IDO_USER_MENU_ITEM_PROP_IS_LOGGED_IN "is-logged-in" #define IDO_USER_MENU_ITEM_PROP_IS_CURRENT_USER "is-current-user" struct _IdoUserMenuItemClass { GtkMenuItemClass parent_class; }; struct _IdoUserMenuItem { /*< private >*/ GtkMenuItem parent; }; GType ido_user_menu_item_get_type (void) G_GNUC_CONST; GtkWidget* ido_user_menu_item_new(void); void ido_user_menu_item_set_icon (IdoUserMenuItem * self, GIcon * icon); void ido_user_menu_item_set_icon_from_file (IdoUserMenuItem * self, const char * filename); void ido_user_menu_item_set_logged_in (IdoUserMenuItem * self, gboolean is_logged_in); void ido_user_menu_item_set_current_user (IdoUserMenuItem * self, gboolean is_current_user); void ido_user_menu_item_set_label (IdoUserMenuItem * self, const char * label); GtkMenuItem * ido_user_menu_item_new_from_model (GMenuItem *menuitem, GActionGroup *actions); GtkMenuItem * ido_guest_menu_item_new_from_model (GMenuItem *menuitem, GActionGroup *actions); G_END_DECLS #endif ayatana-ido-0.10.1/src/libayatana-ido.c0000644000000000000000000000213014471671403014462 0ustar /* * Copyright 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . * * Authors: * Lars Uebernickel */ #include /** * ido_init: * * Initializes ido. It has to be called after gtk_init(), but before any * other calls into ido are made. */ void ido_init (void) { GType ido_menu_item_factory_get_type (void); /* make sure this extension point is registered so that gtk calls it * when finding custom menu items */ g_type_ensure (ido_menu_item_factory_get_type ()); } ayatana-ido-0.10.1/src/libayatana-ido.h0000644000000000000000000000215014471671403014471 0ustar /* * Copyright 2010 Canonical, Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of either or both of the following licenses: * * 1) the GNU Lesser General Public License version 3, as published by the * Free Software Foundation; and/or * 2) the GNU Lesser General Public License version 2.1, as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranties of * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR * PURPOSE. See the applicable version of the GNU Lesser General Public * License for more details. * * You should have received a copy of both the GNU Lesser General Public * License version 3 and version 2.1 along with this program. If not, see * * * Authors: * Cody Russell */ #ifndef __IDO__ #define __IDO__ #include "idocalendarmenuitem.h" #include "idoscalemenuitem.h" #include "idoentrymenuitem.h" void ido_init (void); #endif /* __IDO__ */ ayatana-ido-0.10.1/tests/CMakeLists.txt0000644000000000000000000000077714471671403014572 0ustar find_package(GTest REQUIRED) # gtest-menuitems include_directories( ${CMAKE_SOURCE_DIR}/src ${PROJECT_DEPS_INCLUDE_DIRS} ) add_executable("gtest-menuitems" gtest-menuitems.cpp) target_link_options("gtest-menuitems" PRIVATE -no-pie) target_link_libraries("gtest-menuitems" ayatana-ido3-0.4 ${PROJECT_DEPS_LIBRARIES} ${GTEST_LIBRARIES} ${GTEST_BOTH_LIBRARIES} ${GMOCK_LIBRARIES} ) add_test("gtest-menuitems" "gtest-menuitems") add_dependencies("gtest-menuitems" ayatana-ido3-0.4) ayatana-ido-0.10.1/tests/gtest-menuitems.cpp0000644000000000000000000000451614471671403015663 0ustar #include #include #include "idocalendarmenuitem.h" #include "idoentrymenuitem.h" #include "idoscalemenuitem.h" class TestMenuitems : public ::testing::Test { public: TestMenuitems() { gint argc = 0; gchar * argv[] = {NULL}; gtk_init(&argc, (gchar ***)&argv); return; } }; TEST_F(TestMenuitems, BuildCalendar) { GtkWidget * cal = ido_calendar_menu_item_new(); EXPECT_TRUE(cal != NULL); EXPECT_TRUE(IDO_IS_CALENDAR_MENU_ITEM(cal)); EXPECT_TRUE(GTK_IS_MENU_ITEM(cal)); GtkWidget * menu = gtk_menu_new(); gtk_widget_show(menu); gtk_menu_shell_append(GTK_MENU_SHELL(menu), cal); gtk_widget_show(cal); gtk_widget_realize(cal); EXPECT_TRUE(gtk_widget_get_realized(cal)); g_object_ref_sink(menu); g_object_unref(menu); return; } TEST_F(TestMenuitems, BuildEntry) { GtkWidget * entry = ido_entry_menu_item_new(); EXPECT_TRUE(entry != NULL); EXPECT_TRUE(IDO_IS_ENTRY_MENU_ITEM(entry)); EXPECT_TRUE(GTK_IS_MENU_ITEM(entry)); GtkWidget * menu = gtk_menu_new(); gtk_widget_show(menu); gtk_menu_shell_append(GTK_MENU_SHELL(menu), entry); gtk_widget_show(entry); gtk_widget_realize(entry); EXPECT_TRUE(gtk_widget_get_realized(entry)); g_object_ref_sink(menu); g_object_unref(menu); return; } TEST_F(TestMenuitems, BuildScaleDefault) { GtkWidget * scale = ido_scale_menu_item_new("Label", IDO_RANGE_STYLE_DEFAULT, gtk_adjustment_new(0.5, 0.0, 1.0, 0.01, 0.1, 0.1)); EXPECT_TRUE(scale != NULL); EXPECT_TRUE(IDO_IS_SCALE_MENU_ITEM(scale)); EXPECT_TRUE(GTK_IS_MENU_ITEM(scale)); GtkWidget * menu = gtk_menu_new(); gtk_widget_show(menu); gtk_menu_shell_append(GTK_MENU_SHELL(menu), scale); gtk_widget_show(scale); gtk_widget_realize(scale); EXPECT_TRUE(gtk_widget_get_realized(scale)); g_object_ref_sink(menu); g_object_unref(menu); return; } TEST_F(TestMenuitems, BuildScaleSmall) { GtkWidget * scale = ido_scale_menu_item_new("Label", IDO_RANGE_STYLE_SMALL, gtk_adjustment_new(0.5, 0.0, 1.0, 0.01, 0.1, 0.1)); EXPECT_TRUE(scale != NULL); EXPECT_TRUE(IDO_IS_SCALE_MENU_ITEM(scale)); EXPECT_TRUE(GTK_IS_MENU_ITEM(scale)); GtkWidget * menu = gtk_menu_new(); gtk_widget_show(menu); gtk_menu_shell_append(GTK_MENU_SHELL(menu), scale); gtk_widget_show(scale); gtk_widget_realize(scale); EXPECT_TRUE(gtk_widget_get_realized(scale)); g_object_ref_sink(menu); g_object_unref(menu); return; } ayatana-ido-0.10.1/.travis.yml0000644000000000000000000000174014471671403012770 0ustar # vim: set ts=2 sts=2 sw=2 expandtab : dist: focal language: shell os: linux arch: - amd64 # - ppc64le services: - docker addons: apt: packages: - python3-pip - python3-setuptools before_install: # let's use the MATE project's docker build script... - curl -Ls -o docker-build https://github.com/AyatanaIndicators/ayatana-dev-scripts/raw/main/travis/docker-build - chmod +x docker-build install: - pip3 install wheel - pip3 install PyGithub - ./docker-build --name ${DISTRO} --config .build.yml --install script: - ./docker-build --name ${DISTRO} --verbose --config .build.yml --build scripts env: # temp disable of archlinux builds, see https://gitlab.archlinux.org/archlinux/archlinux-docker/-/issues/56 # - DISTRO="archlinux:latest" - DISTRO="debian:testing" - DISTRO="debian:stable" # - DISTRO="ubuntu:rolling" - DISTRO="ubuntu:jammy" - DISTRO="ubuntu:focal" jobs: exclude: - env: DISTRO="archlinux:latest" arch: ppc64le