diff options
48 files changed, 6862 insertions, 190 deletions
@@ -64,7 +64,127 @@ tests/test-glib-proxy-client tests/test-glib-proxy-server tests/test-glib-proxy-proxy tests/test-glib-proxy -libdbusmenu-glib/DbusmenuGlib-0.2.gir -libdbusmenu-glib/DbusmenuGlib-0.2.typelib +libdbusmenu-glib/Dbusmenu-Glib-0.2.gir +libdbusmenu-glib/Dbusmenu-Glib-0.2.typelib +libdbusmenu-glib/Dbusmenu-Glib-0.2.vapi libdbusmenu-gtk/DbusmenuGtk-0.2.gir +libdbusmenu-gtk/DbusmenuGtk-0.2.tmp.gir libdbusmenu-gtk/DbusmenuGtk-0.2.typelib +libdbusmenu-gtk/DbusmenuGtk-0.2.vapi +tests/test-gtk-objects +tests/test-gtk-objects-test +tests/test-gtk-objects.xml +tests/test-gtk-shortcut +tests/test-gtk-shortcut-client +tests/test-gtk-shortcut-server +tests/test-glib-submenu +tests/test-glib-submenu-client +tests/test-glib-submenu-server +docs/libdbusmenu-glib/reference/html-build.stamp +docs/libdbusmenu-glib/reference/html.stamp +docs/libdbusmenu-glib/reference/libdbusmenu-glib-decl-list.txt +docs/libdbusmenu-glib/reference/libdbusmenu-glib-decl-list.txt.bak +docs/libdbusmenu-glib/reference/libdbusmenu-glib-decl.txt +docs/libdbusmenu-glib/reference/libdbusmenu-glib-decl.txt.bak +docs/libdbusmenu-glib/reference/libdbusmenu-glib-overrides.txt +docs/libdbusmenu-glib/reference/libdbusmenu-glib-undeclared.txt +docs/libdbusmenu-glib/reference/libdbusmenu-glib-undocumented.txt +docs/libdbusmenu-glib/reference/libdbusmenu-glib-unused.txt +docs/libdbusmenu-glib/reference/libdbusmenu-glib.args +docs/libdbusmenu-glib/reference/libdbusmenu-glib.hierarchy +docs/libdbusmenu-glib/reference/libdbusmenu-glib.interfaces +docs/libdbusmenu-glib/reference/libdbusmenu-glib.prerequisites +docs/libdbusmenu-glib/reference/libdbusmenu-glib.signals +docs/libdbusmenu-glib/reference/scan-build.stamp +docs/libdbusmenu-glib/reference/sgml-build.stamp +docs/libdbusmenu-glib/reference/sgml.stamp +docs/libdbusmenu-glib/reference/tmpl-build.stamp +docs/libdbusmenu-glib/reference/tmpl.stamp +docs/libdbusmenu-glib/reference/version.xml +docs/libdbusmenu-glib/reference/xml +docs/libdbusmenu-glib/reference/html/annotation-glossary.html +docs/libdbusmenu-glib/reference/html/api-index-full.html +docs/libdbusmenu-glib/reference/html/ch01.html +docs/libdbusmenu-glib/reference/html/home.png +docs/libdbusmenu-glib/reference/html/index.html +docs/libdbusmenu-glib/reference/html/index.sgml +docs/libdbusmenu-glib/reference/html/left.png +docs/libdbusmenu-glib/reference/html/libdbusmenu-glib-DbusmenuClient.html +docs/libdbusmenu-glib/reference/html/libdbusmenu-glib-DbusmenuClientMenuitem.html +docs/libdbusmenu-glib/reference/html/libdbusmenu-glib-DbusmenuMenuitem.html +docs/libdbusmenu-glib/reference/html/libdbusmenu-glib-DbusmenuMenuitemProxy.html +docs/libdbusmenu-glib/reference/html/libdbusmenu-glib-DbusmenuServer.html +docs/libdbusmenu-glib/reference/html/libdbusmenu-glib.devhelp +docs/libdbusmenu-glib/reference/html/libdbusmenu-glib.devhelp2 +docs/libdbusmenu-glib/reference/html/object-tree.html +docs/libdbusmenu-glib/reference/html/right.png +docs/libdbusmenu-glib/reference/html/style.css +docs/libdbusmenu-glib/reference/html/up.png +docs/libdbusmenu-glib/reference/tmpl/client-menuitem.sgml +docs/libdbusmenu-glib/reference/tmpl/client-menuitem.sgml.bak +docs/libdbusmenu-glib/reference/tmpl/client.sgml +docs/libdbusmenu-glib/reference/tmpl/client.sgml.bak +docs/libdbusmenu-glib/reference/tmpl/libdbusmenu-glib-unused.sgml +docs/libdbusmenu-glib/reference/tmpl/menuitem-proxy.sgml +docs/libdbusmenu-glib/reference/tmpl/menuitem-proxy.sgml.bak +docs/libdbusmenu-glib/reference/tmpl/menuitem.sgml +docs/libdbusmenu-glib/reference/tmpl/menuitem.sgml.bak +docs/libdbusmenu-glib/reference/tmpl/server.sgml +docs/libdbusmenu-glib/reference/tmpl/server.sgml.bak +docs/libdbusmenu-gtk/reference/html-build.stamp +docs/libdbusmenu-gtk/reference/html.stamp +docs/libdbusmenu-gtk/reference/libdbusmenu-gtk-decl-list.txt +docs/libdbusmenu-gtk/reference/libdbusmenu-gtk-decl-list.txt.bak +docs/libdbusmenu-gtk/reference/libdbusmenu-gtk-decl.txt +docs/libdbusmenu-gtk/reference/libdbusmenu-gtk-decl.txt.bak +docs/libdbusmenu-gtk/reference/libdbusmenu-gtk-overrides.txt +docs/libdbusmenu-gtk/reference/libdbusmenu-gtk-sections.txt +docs/libdbusmenu-gtk/reference/libdbusmenu-gtk-undeclared.txt +docs/libdbusmenu-gtk/reference/libdbusmenu-gtk-undocumented.txt +docs/libdbusmenu-gtk/reference/libdbusmenu-gtk-unused.txt +docs/libdbusmenu-gtk/reference/libdbusmenu-gtk.args +docs/libdbusmenu-gtk/reference/libdbusmenu-gtk.hierarchy +docs/libdbusmenu-gtk/reference/libdbusmenu-gtk.interfaces +docs/libdbusmenu-gtk/reference/libdbusmenu-gtk.prerequisites +docs/libdbusmenu-gtk/reference/libdbusmenu-gtk.signals +docs/libdbusmenu-gtk/reference/libdbusmenu-gtk.types +docs/libdbusmenu-gtk/reference/scan-build.stamp +docs/libdbusmenu-gtk/reference/sgml-build.stamp +docs/libdbusmenu-gtk/reference/sgml.stamp +docs/libdbusmenu-gtk/reference/tmpl-build.stamp +docs/libdbusmenu-gtk/reference/tmpl.stamp +docs/libdbusmenu-gtk/reference/version.xml +docs/libdbusmenu-gtk/reference/xml +docs/libdbusmenu-gtk/reference/html/Genericmenuitem.html +docs/libdbusmenu-gtk/reference/html/api-index-full.html +docs/libdbusmenu-gtk/reference/html/ch01.html +docs/libdbusmenu-gtk/reference/html/home.png +docs/libdbusmenu-gtk/reference/html/index.html +docs/libdbusmenu-gtk/reference/html/index.sgml +docs/libdbusmenu-gtk/reference/html/left.png +docs/libdbusmenu-gtk/reference/html/libdbusmenu-gtk-DbusmenuGtkClient.html +docs/libdbusmenu-gtk/reference/html/libdbusmenu-gtk-DbusmenuGtkMenu.html +docs/libdbusmenu-gtk/reference/html/libdbusmenu-gtk-menuitem.html +docs/libdbusmenu-gtk/reference/html/libdbusmenu-gtk.devhelp +docs/libdbusmenu-gtk/reference/html/libdbusmenu-gtk.devhelp2 +docs/libdbusmenu-gtk/reference/html/object-tree.html +docs/libdbusmenu-gtk/reference/html/right.png +docs/libdbusmenu-gtk/reference/html/style.css +docs/libdbusmenu-gtk/reference/html/up.png +docs/libdbusmenu-gtk/reference/tmpl/client.sgml +docs/libdbusmenu-gtk/reference/tmpl/client.sgml.bak +docs/libdbusmenu-gtk/reference/tmpl/genericmenuitem.sgml +docs/libdbusmenu-gtk/reference/tmpl/genericmenuitem.sgml.bak +docs/libdbusmenu-gtk/reference/tmpl/libdbusmenu-gtk-unused.sgml +docs/libdbusmenu-gtk/reference/tmpl/menu.sgml +docs/libdbusmenu-gtk/reference/tmpl/menu.sgml.bak +docs/libdbusmenu-gtk/reference/tmpl/menuitem.sgml +docs/libdbusmenu-gtk/reference/tmpl/menuitem.sgml.bak +gtk-doc.make +m4/gtk-doc.m4 +tests/dbusmenu-jsonloader.pc +tests/libdbusmenu-jsonloader.la +tests/libdbusmenu_jsonloader_la-json-loader.lo +tests/test-json-server +tests/test-json-client +tests/test-json @@ -2,10 +2,12 @@ Installation Instructions ************************* Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, -2006, 2007, 2008 Free Software Foundation, Inc. +2006, 2007, 2008, 2009 Free Software Foundation, Inc. - This file is free documentation; the Free Software Foundation gives -unlimited permission to copy, distribute and modify it. + Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved. This file is offered as-is, +without warranty of any kind. Basic Installation ================== @@ -13,7 +15,11 @@ Basic Installation Briefly, the shell commands `./configure; make; make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for -instructions specific to this package. +instructions specific to this package. Some packages provide this +`INSTALL' file but do not implement all of the features documented +below. The lack of an optional feature in a given package is not +necessarily a bug. More recommendations for GNU packages can be found +in *note Makefile Conventions: (standards)Makefile Conventions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses @@ -42,7 +48,7 @@ may remove or edit it. you want to change it or regenerate `configure' using a newer version of `autoconf'. -The simplest way to compile this package is: + The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. @@ -53,12 +59,22 @@ The simplest way to compile this package is: 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with - the package. + the package, generally using the just-built uninstalled binaries. 4. Type `make install' to install the programs and any data files and - documentation. - - 5. You can remove the program binaries and object files from the + documentation. When installing into a prefix owned by root, it is + recommended that the package be configured and built as a regular + user, and only the `make install' phase executed with root + privileges. + + 5. Optionally, type `make installcheck' to repeat any self-tests, but + this time using the binaries in their final installed location. + This target does not install anything. Running this target as a + regular user, particularly if the prior `make install' required + root privileges, verifies that the installation completed + correctly. + + 6. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is @@ -67,8 +83,15 @@ The simplest way to compile this package is: all sorts of other programs in order to regenerate files that came with the distribution. - 6. Often, you can also type `make uninstall' to remove the installed - files again. + 7. Often, you can also type `make uninstall' to remove the installed + files again. In practice, not all packages have tested that + uninstallation works correctly, even though it is required by the + GNU Coding Standards. + + 8. Some packages, particularly those that use Automake, provide `make + distcheck', which can by used by developers to test that all other + targets like `make install' and `make uninstall' work correctly. + This target is generally not run by end users. Compilers and Options ===================== @@ -93,7 +116,8 @@ same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the -source code in the directory that `configure' is in and in `..'. +source code in the directory that `configure' is in and in `..'. This +is known as a "VPATH" build. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have @@ -120,7 +144,8 @@ Installation Names By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving -`configure' the option `--prefix=PREFIX'. +`configure' the option `--prefix=PREFIX', where PREFIX must be an +absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you @@ -131,15 +156,46 @@ Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories -you can set and what kinds of files go in them. +you can set and what kinds of files go in them. In general, the +default for these options is expressed in terms of `${prefix}', so that +specifying just `--prefix' will affect all of the other directory +specifications that were not explicitly provided. + + The most portable way to affect installation locations is to pass the +correct locations to `configure'; however, many packages provide one or +both of the following shortcuts of passing variable assignments to the +`make install' command line to change installation locations without +having to reconfigure or recompile. + + The first method involves providing an override variable for each +affected directory. For example, `make install +prefix=/alternate/directory' will choose an alternate location for all +directory configuration variables that were expressed in terms of +`${prefix}'. Any directories that were specified during `configure', +but not in terms of `${prefix}', must each be overridden at install +time for the entire installation to be relocated. The approach of +makefile variable overrides for each directory variable is required by +the GNU Coding Standards, and ideally causes no recompilation. +However, some platforms have known limitations with the semantics of +shared libraries that end up requiring recompilation when using this +method, particularly noticeable in packages that use GNU Libtool. + + The second method involves providing the `DESTDIR' variable. For +example, `make install DESTDIR=/alternate/directory' will prepend +`/alternate/directory' before all installation names. The approach of +`DESTDIR' overrides is not required by the GNU Coding Standards, and +does not work on platforms that have drive letters. On the other hand, +it does better at avoiding recompilation issues, and works well even +when some directory options were not specified in terms of `${prefix}' +at `configure' time. + +Optional Features +================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. -Optional Features -================= - Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE @@ -152,6 +208,13 @@ find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. + Some packages offer the ability to configure how verbose the +execution of `make' will be. For these packages, running `./configure +--enable-silent-rules' sets the default to minimal output, which can be +overridden with `make V=1'; while running `./configure +--disable-silent-rules' sets the default to verbose, which can be +overridden with `make V=0'. + Particular systems ================== @@ -159,7 +222,7 @@ Particular systems CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: - ./configure CC="cc -Ae" + ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. @@ -174,6 +237,16 @@ and if that doesn't work, try ./configure CC="cc -nodtk" + On Solaris, don't put `/usr/ucb' early in your `PATH'. This +directory contains several dysfunctional programs; working variants of +these programs are available in `/usr/bin'. So, if you need `/usr/ucb' +in your `PATH', put it _after_ `/usr/bin'. + + On Haiku, software installed for all users goes in `/boot/common', +not `/usr/local'. It is recommended to use the following options: + + ./configure --prefix=/boot/common + Specifying the System Type ========================== @@ -189,7 +262,8 @@ type, such as `sun4', or a canonical name which has the form: where SYSTEM can have one of these forms: - OS KERNEL-OS + OS + KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't @@ -277,7 +351,7 @@ operates. `configure' can determine that directory automatically. `--prefix=DIR' - Use DIR as the installation prefix. *Note Installation Names:: + Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. diff --git a/Makefile.am b/Makefile.am index 658f946..3853d2a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,7 +8,7 @@ SUBDIRS = \ libdbusmenu-gtk \ tools \ tests \ + docs \ po -DISTCHECK_CONFIGURE_FLAGS = --enable-introspection - +DISTCHECK_CONFIGURE_FLAGS = --enable-introspection --enable-gtk-doc @@ -9,4 +9,4 @@ which gnome-autogen.sh || { USE_GNOME2_MACROS=1 \ USE_COMMON_DOC_BUILD=yes \ -. gnome-autogen.sh +gnome-autogen.sh --enable-gtk-doc $@ diff --git a/configure.ac b/configure.ac index 2e95d55..93aa557 100644 --- a/configure.ac +++ b/configure.ac @@ -1,11 +1,11 @@ -AC_INIT(libdbusmenu, 0.2.9, ted@canonical.com) +AC_INIT(libdbusmenu, 0.3.6, ted@canonical.com) AC_COPYRIGHT([Copyright 2009,2010 Canonical]) AC_PREREQ(2.62) AM_CONFIG_HEADER(config.h) -AM_INIT_AUTOMAKE(libdbusmenu, 0.2.9, [-Wno-portability]) +AM_INIT_AUTOMAKE(libdbusmenu, 0.3.6, [-Wno-portability]) AM_MAINTAINER_MODE @@ -22,6 +22,13 @@ AC_CONFIG_MACRO_DIR([m4]) m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) ########################### +# GTK Doc +########################### + +GTK_DOC_CHECK([1.4]) +GNOME_DOC_INIT + +########################### # Dependencies - GLib ########################### @@ -67,8 +74,10 @@ AC_SUBST(DBUSMENUDUMPER_LIBS) ########################### JSON_GLIB_REQUIRED_VERSION=0.6.0 +GIO_UNIX_REQUIRED_VERSION=2.24 -PKG_CHECK_MODULES(DBUSMENUTESTS, json-glib-1.0 >= $JSON_GLIB_REQUIRED_VERSION) +PKG_CHECK_MODULES(DBUSMENUTESTS, json-glib-1.0 >= $JSON_GLIB_REQUIRED_VERSION + gio-unix-2.0 >= $GIO_UNIX_REQUIRED_VERSION) AC_SUBST(DBUSMENUTESTS_CFLAGS) AC_SUBST(DBUSMENUTESTS_LIBS) @@ -90,7 +99,7 @@ AC_PATH_PROG([VALA_API_GEN], [vapigen]) ########################### LIBDBUSMENU_CURRENT=1 -LIBDBUSMENU_REVISION=6 +LIBDBUSMENU_REVISION=11 LIBDBUSMENU_AGE=0 AC_SUBST(LIBDBUSMENU_CURRENT) @@ -131,6 +140,14 @@ libdbusmenu-gtk/dbusmenu-gtk.pc tools/Makefile tools/testapp/Makefile tests/Makefile +tests/dbusmenu-jsonloader.pc +docs/Makefile +docs/libdbusmenu-glib/Makefile +docs/libdbusmenu-glib/reference/Makefile +docs/libdbusmenu-glib/reference/version.xml +docs/libdbusmenu-gtk/Makefile +docs/libdbusmenu-gtk/reference/Makefile +docs/libdbusmenu-gtk/reference/version.xml ]) ########################### diff --git a/docs/Makefile.am b/docs/Makefile.am new file mode 100644 index 0000000..87ffe5f --- /dev/null +++ b/docs/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = libdbusmenu-glib libdbusmenu-gtk diff --git a/docs/libdbusmenu-glib/Makefile.am b/docs/libdbusmenu-glib/Makefile.am new file mode 100644 index 0000000..f3ddc22 --- /dev/null +++ b/docs/libdbusmenu-glib/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = reference diff --git a/docs/libdbusmenu-glib/reference/Makefile.am b/docs/libdbusmenu-glib/reference/Makefile.am new file mode 100644 index 0000000..e8a3610 --- /dev/null +++ b/docs/libdbusmenu-glib/reference/Makefile.am @@ -0,0 +1,92 @@ +## Process this file with automake to produce Makefile.in + +# We require automake 1.6 at least. +AUTOMAKE_OPTIONS = 1.6 + +# This is a blank Makefile.am for using gtk-doc. +# Copy this to your project's API docs directory and modify the variables to +# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples +# of using the various options. + +# The name of the module, e.g. 'glib'. +DOC_MODULE=libdbusmenu-glib + +# The top-level SGML file. You can change this if you want to. +DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml + +# The directory containing the source code. Relative to $(srcdir). +# gtk-doc will search all .c & .h files beneath here for inline comments +# documenting the functions and macros. +# e.g. DOC_SOURCE_DIR=../../../gtk +DOC_SOURCE_DIR=../../../libdbusmenu-glib + +# Extra options to pass to gtkdoc-scangobj. Not normally needed. +SCANGOBJ_OPTIONS=--nogtkinit --type-init-func="g_type_init()" + +# Extra options to supply to gtkdoc-scan. +# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" +SCAN_OPTIONS= + +# Extra options to supply to gtkdoc-mkdb. +# e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml +MKDB_OPTIONS=--sgml-mode --output-format=xml + +# Extra options to supply to gtkdoc-mktmpl +# e.g. MKTMPL_OPTIONS=--only-section-tmpl +MKTMPL_OPTIONS= + +# Extra options to supply to gtkdoc-fixref. Not normally needed. +# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html +FIXXREF_OPTIONS= + +# Used for dependencies. The docs will be rebuilt if any of these change. +# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h +# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c +HFILE_GLOB=$(top_srcdir)/libdbusmenu-glib/*.h +CFILE_GLOB=$(top_srcdir)/libdbusmenu-glib/*.c + +# Header files to ignore when scanning. +# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h +IGNORE_HFILES= \ + menuitem-marshal.h \ + server-marshal.h \ + menuitem-private.h \ + dbusmenu-client.h \ + dbusmenu-server.h + +# Images to copy into HTML directory. +# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png +HTML_IMAGES= + +# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). +# e.g. content_files=running.sgml building.sgml changes-2.0.sgml +content_files=version.xml + +# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded +# These files must be listed here *and* in content_files +# e.g. expand_content_files=running.sgml +expand_content_files= + +# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. +# Only needed if you are using gtkdoc-scangobj to dynamically query widget +# signals and properties. +# e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) +# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) +INCLUDES=-I$(top_srcdir) $(DBUSMENUGLIB_CFLAGS) $(DBUSMENUGTK_CFLAGS) +GTKDOC_LIBS=$(top_builddir)/libdbusmenu-glib/libdbusmenu-glib.la + +# This includes the standard gtk-doc make rules, copied by gtkdocize. +include $(top_srcdir)/gtk-doc.local.make + +# Other files to distribute +# e.g. EXTRA_DIST += version.xml.in +EXTRA_DIST += version.xml.in + +# Files not to distribute +# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types +# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt +#DISTCLEANFILES += + +# Comment this out if you want your docs-status tested during 'make check' +#TESTS = $(GTKDOC_CHECK) + diff --git a/docs/libdbusmenu-glib/reference/libdbusmenu-glib-docs.sgml b/docs/libdbusmenu-glib/reference/libdbusmenu-glib-docs.sgml new file mode 100644 index 0000000..ecc25a3 --- /dev/null +++ b/docs/libdbusmenu-glib/reference/libdbusmenu-glib-docs.sgml @@ -0,0 +1,33 @@ +<?xml version="1.0"?> +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" + "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" +[ + <!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'"> +]> +<book id="index"> + <bookinfo> + <title>libdbusmenu-glib Reference Manual</title> + </bookinfo> + + <chapter> + <title>API</title> + <xi:include href="xml/server.xml"/> + <xi:include href="xml/menuitem-proxy.xml"/> + <xi:include href="xml/menuitem.xml"/> + <xi:include href="xml/client.xml"/> + <xi:include href="xml/client-menuitem.xml"/> + <xi:include href="xml/dbusmenu-client.xml"/> + <xi:include href="xml/dbusmenu-server.xml"/> + + </chapter> + <chapter id="object-tree"> + <title>Object Hierarchy</title> + <xi:include href="xml/tree_index.sgml"/> + </chapter> + <index id="api-index-full"> + <title>API Index</title> + <xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include> + </index> + + <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include> +</book> diff --git a/docs/libdbusmenu-glib/reference/libdbusmenu-glib-sections.txt b/docs/libdbusmenu-glib/reference/libdbusmenu-glib-sections.txt new file mode 100644 index 0000000..0186049 --- /dev/null +++ b/docs/libdbusmenu-glib/reference/libdbusmenu-glib-sections.txt @@ -0,0 +1,157 @@ +<SECTION> +<FILE>client</FILE> +<TITLE>DbusmenuClient</TITLE> +DBUSMENU_CLIENT_SIGNAL_LAYOUT_UPDATED +DBUSMENU_CLIENT_SIGNAL_ROOT_CHANGED +DBUSMENU_CLIENT_SIGNAL_NEW_MENUITEM +DBUSMENU_CLIENT_PROP_DBUS_NAME +DBUSMENU_CLIENT_PROP_DBUS_OBJECT +DBUSMENU_CLIENT_TYPES_DEFAULT +DBUSMENU_CLIENT_TYPES_SEPARATOR +DBUSMENU_CLIENT_TYPES_IMAGE +DbusmenuClient +DbusmenuClientClass +DbusmenuClientTypeHandler +dbusmenu_client_new +dbusmenu_client_get_root +dbusmenu_client_add_type_handler +dbusmenu_client_send_event +dbusmenu_client_send_about_to_show +<SUBSECTION Standard> +DBUSMENU_CLIENT +DBUSMENU_IS_CLIENT +DBUSMENU_TYPE_CLIENT +dbusmenu_client_get_type +DBUSMENU_CLIENT_CLASS +DBUSMENU_IS_CLIENT_CLASS +DBUSMENU_CLIENT_GET_CLASS +</SECTION> + +<SECTION> +<FILE>menuitem</FILE> +<TITLE>DbusmenuMenuitem</TITLE> +DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED +DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED +DBUSMENU_MENUITEM_SIGNAL_CHILD_ADDED +DBUSMENU_MENUITEM_SIGNAL_CHILD_REMOVED +DBUSMENU_MENUITEM_SIGNAL_CHILD_MOVED +DBUSMENU_MENUITEM_SIGNAL_REALIZED +DBUSMENU_MENUITEM_SIGNAL_REALIZED_ID +DBUSMENU_MENUITEM_PROP_TYPE +DBUSMENU_MENUITEM_PROP_VISIBLE +DBUSMENU_MENUITEM_PROP_ENABLED +DBUSMENU_MENUITEM_PROP_LABEL +DBUSMENU_MENUITEM_PROP_ICON_NAME +DBUSMENU_MENUITEM_PROP_ICON_DATA +DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE +DBUSMENU_MENUITEM_PROP_TOGGLE_STATE +DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY +DBUSMENU_MENUITEM_TOGGLE_CHECK +DBUSMENU_MENUITEM_TOGGLE_RADIO +DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED +DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED +DBUSMENU_MENUITEM_TOGGLE_STATE_UNKNOWN +DBUSMENU_MENUITEM_ICON_NAME_BLANK +DBUSMENU_MENUITEM_CHILD_DISPLAY_SUBMENU +DbusmenuMenuitem +dbusmenu_menuitem_about_to_show_cb +dbusmenu_menuitem_buildxml_slot_t +DbusmenuMenuitemClass +dbusmenu_menuitem_new +dbusmenu_menuitem_new_with_id +dbusmenu_menuitem_get_id +dbusmenu_menuitem_get_children +dbusmenu_menuitem_take_children +dbusmenu_menuitem_get_position +dbusmenu_menuitem_get_position_realized +dbusmenu_menuitem_child_append +dbusmenu_menuitem_child_prepend +dbusmenu_menuitem_child_delete +dbusmenu_menuitem_child_add_position +dbusmenu_menuitem_child_reorder +dbusmenu_menuitem_child_find +dbusmenu_menuitem_find_id +dbusmenu_menuitem_property_set +dbusmenu_menuitem_property_set_value +dbusmenu_menuitem_property_set_bool +dbusmenu_menuitem_property_set_int +dbusmenu_menuitem_property_get +dbusmenu_menuitem_property_get_value +dbusmenu_menuitem_property_get_bool +dbusmenu_menuitem_property_get_int +dbusmenu_menuitem_property_exist +dbusmenu_menuitem_properties_list +dbusmenu_menuitem_properties_copy +dbusmenu_menuitem_property_remove +dbusmenu_menuitem_set_root +dbusmenu_menuitem_get_root +dbusmenu_menuitem_foreach +dbusmenu_menuitem_handle_event +dbusmenu_menuitem_send_about_to_show +<SUBSECTION Standard> +DBUSMENU_MENUITEM +DBUSMENU_IS_MENUITEM +DBUSMENU_TYPE_MENUITEM +dbusmenu_menuitem_get_type +DBUSMENU_MENUITEM_CLASS +DBUSMENU_IS_MENUITEM_CLASS +DBUSMENU_MENUITEM_GET_CLASS +</SECTION> + +<SECTION> +<FILE>server</FILE> +<TITLE>DbusmenuServer</TITLE> +DBUSMENU_SERVER_SIGNAL_ID_PROP_UPDATE +DBUSMENU_SERVER_SIGNAL_ID_UPDATE +DBUSMENU_SERVER_SIGNAL_LAYOUT_UPDATED +DBUSMENU_SERVER_SIGNAL_LAYOUT_UPDATE +DBUSMENU_SERVER_PROP_DBUS_OBJECT +DBUSMENU_SERVER_PROP_ROOT_NODE +DBUSMENU_SERVER_PROP_VERSION +DbusmenuServer +DbusmenuServerClass +dbusmenu_server_new +dbusmenu_server_set_root +<SUBSECTION Standard> +DBUSMENU_SERVER +DBUSMENU_IS_SERVER +DBUSMENU_TYPE_SERVER +dbusmenu_server_get_type +DBUSMENU_SERVER_CLASS +DBUSMENU_IS_SERVER_CLASS +DBUSMENU_SERVER_GET_CLASS +</SECTION> + +<SECTION> +<FILE>client-menuitem</FILE> +<TITLE>DbusmenuClientMenuitem</TITLE> +DBUSMENU_CLIENT_MENUITEM_TYPE +DbusmenuClientMenuitem +DbusmenuClientMenuitemClass +dbusmenu_client_menuitem_new +<SUBSECTION Standard> +DBUSMENU_CLIENT_MENUITEM +DBUSMENU_IS_CLIENT_MENUITEM +dbusmenu_client_menuitem_get_type +DBUSMENU_CLIENT_MENUITEM_CLASS +DBUSMENU_IS_CLIENT_MENUITEM_CLASS +DBUSMENU_CLIENT_MENUITEM_GET_CLASS +</SECTION> + +<SECTION> +<FILE>menuitem-proxy</FILE> +<TITLE>DbusmenuMenuitemProxy</TITLE> +DbusmenuMenuitemProxy +DbusmenuMenuitemProxyClass +dbusmenu_menuitem_proxy_new +dbusmenu_menuitem_proxy_get_wrapped +<SUBSECTION Standard> +DBUSMENU_MENUITEM_PROXY +DBUSMENU_IS_MENUITEM_PROXY +DBUSMENU_TYPE_MENUITEM_PROXY +dbusmenu_menuitem_proxy_get_type +DBUSMENU_MENUITEM_PROXY_CLASS +DBUSMENU_IS_MENUITEM_PROXY_CLASS +DBUSMENU_MENUITEM_PROXY_GET_CLASS +</SECTION> + diff --git a/docs/libdbusmenu-glib/reference/tmpl/dummy.sgml b/docs/libdbusmenu-glib/reference/tmpl/dummy.sgml new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/docs/libdbusmenu-glib/reference/tmpl/dummy.sgml diff --git a/docs/libdbusmenu-glib/reference/version.xml.in b/docs/libdbusmenu-glib/reference/version.xml.in new file mode 100644 index 0000000..d78bda9 --- /dev/null +++ b/docs/libdbusmenu-glib/reference/version.xml.in @@ -0,0 +1 @@ +@VERSION@ diff --git a/docs/libdbusmenu-gtk/Makefile.am b/docs/libdbusmenu-gtk/Makefile.am new file mode 100644 index 0000000..f3ddc22 --- /dev/null +++ b/docs/libdbusmenu-gtk/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = reference diff --git a/docs/libdbusmenu-gtk/reference/Makefile.am b/docs/libdbusmenu-gtk/reference/Makefile.am new file mode 100644 index 0000000..ec1bd28 --- /dev/null +++ b/docs/libdbusmenu-gtk/reference/Makefile.am @@ -0,0 +1,87 @@ +## Process this file with automake to produce Makefile.in + +# We require automake 1.6 at least. +AUTOMAKE_OPTIONS = 1.6 + +# This is a blank Makefile.am for using gtk-doc. +# Copy this to your project's API docs directory and modify the variables to +# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples +# of using the various options. + +# The name of the module, e.g. 'glib'. +DOC_MODULE=libdbusmenu-gtk + +# The top-level SGML file. You can change this if you want to. +DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml + +# The directory containing the source code. Relative to $(srcdir). +# gtk-doc will search all .c & .h files beneath here for inline comments +# documenting the functions and macros. +# e.g. DOC_SOURCE_DIR=../../../gtk +DOC_SOURCE_DIR=../../../libdbusmenu-gtk + +# Extra options to pass to gtkdoc-scangobj. Not normally needed. +SCANGOBJ_OPTIONS=--nogtkinit --type-init-func="g_type_init()" + +# Extra options to supply to gtkdoc-scan. +# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" +SCAN_OPTIONS= + +# Extra options to supply to gtkdoc-mkdb. +# e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml +MKDB_OPTIONS=--sgml-mode --output-format=xml + +# Extra options to supply to gtkdoc-mktmpl +# e.g. MKTMPL_OPTIONS=--only-section-tmpl +MKTMPL_OPTIONS= + +# Extra options to supply to gtkdoc-fixref. Not normally needed. +# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html +FIXXREF_OPTIONS= + +# Used for dependencies. The docs will be rebuilt if any of these change. +# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h +# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c +HFILE_GLOB=$(top_srcdir)/libdbusmenu-gtk/*.h +CFILE_GLOB=$(top_srcdir)/libdbusmenu-gtk/*.c + +# Header files to ignore when scanning. +# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h +IGNORE_HFILES= + +# Images to copy into HTML directory. +# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png +HTML_IMAGES= + +# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). +# e.g. content_files=running.sgml building.sgml changes-2.0.sgml +content_files=version.xml + +# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded +# These files must be listed here *and* in content_files +# e.g. expand_content_files=running.sgml +expand_content_files= + +# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. +# Only needed if you are using gtkdoc-scangobj to dynamically query widget +# signals and properties. +# e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) +# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) +INCLUDES=-I$(top_srcdir) $(DBUSMENUGLIB_CFLAGS) $(DBUSMENUGTK_CFLAGS) +GTKDOC_LIBS=$(top_builddir)/libdbusmenu-gtk/libdbusmenu-gtk.la + +# This includes the standard gtk-doc make rules, copied by gtkdocize. +include $(top_srcdir)/gtk-doc.local.make + +# Other files to distribute +# e.g. EXTRA_DIST += version.xml.in +EXTRA_DIST += version.xml.in + +# Files not to distribute +# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types +# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt +#DISTCLEANFILES += + +# Comment this out if you want your docs-status tested during 'make check' +#TESTS = $(GTKDOC_CHECK) + diff --git a/docs/libdbusmenu-gtk/reference/libdbusmenu-gtk-docs.sgml b/docs/libdbusmenu-gtk/reference/libdbusmenu-gtk-docs.sgml new file mode 100644 index 0000000..ae9ab07 --- /dev/null +++ b/docs/libdbusmenu-gtk/reference/libdbusmenu-gtk-docs.sgml @@ -0,0 +1,30 @@ +<?xml version="1.0"?> +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" + "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" +[ + <!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'"> +]> +<book id="index"> + <bookinfo> + <title>libdbusmenu-gtk Reference Manual</title> + </bookinfo> + + <chapter> + <title>API</title> + <xi:include href="xml/menu.xml"/> + <xi:include href="xml/client.xml"/> + <xi:include href="xml/genericmenuitem.xml"/> + <xi:include href="xml/menuitem.xml"/> + + </chapter> + <chapter id="object-tree"> + <title>Object Hierarchy</title> + <xi:include href="xml/tree_index.sgml"/> + </chapter> + <index id="api-index-full"> + <title>API Index</title> + <xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include> + </index> + + <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include> +</book> diff --git a/docs/libdbusmenu-gtk/reference/tmpl/dummy.sgml b/docs/libdbusmenu-gtk/reference/tmpl/dummy.sgml new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/docs/libdbusmenu-gtk/reference/tmpl/dummy.sgml diff --git a/docs/libdbusmenu-gtk/reference/version.xml.in b/docs/libdbusmenu-gtk/reference/version.xml.in new file mode 100644 index 0000000..d78bda9 --- /dev/null +++ b/docs/libdbusmenu-gtk/reference/version.xml.in @@ -0,0 +1 @@ +@VERSION@ diff --git a/gtk-doc.local.make b/gtk-doc.local.make new file mode 100644 index 0000000..3dcda60 --- /dev/null +++ b/gtk-doc.local.make @@ -0,0 +1,194 @@ +# -*- mode: makefile -*- + +#################################### +# Everything below here is generic # +#################################### + +if GTK_DOC_USE_LIBTOOL +GTKDOC_CC = $(LIBTOOL) --mode=compile $(CC) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +GTKDOC_LD = $(LIBTOOL) --mode=link $(CC) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) +GTKDOC_RUN = $(LIBTOOL) --mode=execute +else +GTKDOC_CC = $(CC) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +GTKDOC_LD = $(CC) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) +GTKDOC_RUN = sh -c +endif + +# We set GPATH here; this gives us semantics for GNU make +# which are more like other make's VPATH, when it comes to +# whether a source that is a target of one rule is then +# searched for in VPATH/GPATH. +# +GPATH = $(srcdir) + +TARGET_DIR=$(HTML_DIR)/$(DOC_MODULE) + +EXTRA_DIST = \ + $(content_files) \ + $(HTML_IMAGES) \ + $(DOC_MAIN_SGML_FILE) + +DOC_STAMPS=scan-build.stamp tmpl-build.stamp sgml-build.stamp html-build.stamp \ + $(srcdir)/tmpl.stamp $(srcdir)/sgml.stamp $(srcdir)/html.stamp + +SCANOBJ_FILES = \ + $(DOC_MODULE).args \ + $(DOC_MODULE).hierarchy \ + $(DOC_MODULE).interfaces \ + $(DOC_MODULE).prerequisites \ + $(DOC_MODULE).signals + +REPORT_FILES = \ + $(DOC_MODULE)-undocumented.txt \ + $(DOC_MODULE)-undeclared.txt \ + $(DOC_MODULE)-unused.txt + +CLEANFILES = $(SCANOBJ_FILES) $(REPORT_FILES) $(DOC_STAMPS) + +if ENABLE_GTK_DOC +all-local: html-build.stamp +else +all-local: +endif + +docs: html-build.stamp + +$(REPORT_FILES): sgml-build.stamp + +#### scan #### + +scan-build.stamp: $(HFILE_GLOB) $(CFILE_GLOB) + @echo 'gtk-doc: Scanning header files' + @-chmod -R u+w $(srcdir) + cd $(srcdir) && \ + gtkdoc-scan --module=$(DOC_MODULE) --source-dir=$(DOC_SOURCE_DIR) --ignore-headers="$(IGNORE_HFILES)" $(SCAN_OPTIONS) $(EXTRA_HFILES) + if grep -l '^..*$$' $(srcdir)/$(DOC_MODULE).types > /dev/null 2>&1 ; then \ + CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" RUN="$(GTKDOC_RUN)" CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS)" LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" gtkdoc-scangobj $(SCANGOBJ_OPTIONS) --module=$(DOC_MODULE) --output-dir=$(srcdir) ; \ + else \ + cd $(srcdir) ; \ + for i in $(SCANOBJ_FILES) ; do \ + test -f $$i || touch $$i ; \ + done \ + fi + touch scan-build.stamp + +$(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt: scan-build.stamp + @true + +#### templates #### + +tmpl-build.stamp: $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt + @echo 'gtk-doc: Rebuilding template files' + @-chmod -R u+w $(srcdir) + cd $(srcdir) && gtkdoc-mktmpl --module=$(DOC_MODULE) $(MKTMPL_OPTIONS) + touch tmpl-build.stamp + +tmpl.stamp: tmpl-build.stamp + @true + +tmpl/*.sgml: + @true + + +#### xml #### + +sgml-build.stamp: tmpl.stamp $(HFILE_GLOB) $(CFILE_GLOB) $(DOC_MODULE)-sections.txt $(srcdir)/tmpl/*.sgml $(expand_content_files) + @echo 'gtk-doc: Building XML' + @-chmod -R u+w $(srcdir) + cd $(srcdir) && \ + gtkdoc-mkdb --module=$(DOC_MODULE) --source-dir=$(DOC_SOURCE_DIR) --output-format=xml --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) $(MKDB_OPTIONS) + touch sgml-build.stamp + +sgml.stamp: sgml-build.stamp + @true + +#### html #### + +html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) + @echo 'gtk-doc: Building HTML' + @-chmod -R u+w $(srcdir) + rm -rf $(srcdir)/html + mkdir $(srcdir)/html + mkhtml_options=""; \ + gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-path"; \ + if test "$(?)" = "0"; then \ + mkhtml_options=--path="$(srcdir)"; \ + fi + cd $(srcdir)/html && gtkdoc-mkhtml $(mkhtml_options) $(MKHTML_OPTIONS) $(DOC_MODULE) ../$(DOC_MAIN_SGML_FILE) + test "x$(HTML_IMAGES)" = "x" || ( cd $(srcdir) && cp $(HTML_IMAGES) html ) + @echo 'gtk-doc: Fixing cross-references' + cd $(srcdir) && gtkdoc-fixxref --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS) + touch html-build.stamp + +############## + +clean-local: + rm -f *~ *.bak + rm -rf .libs + +distclean-local: + cd $(srcdir) && \ + rm -rf xml $(REPORT_FILES) \ + $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt + +maintainer-clean-local: clean + cd $(srcdir) && rm -rf xml html + +install-data-local: + installfiles=`echo $(srcdir)/html/*`; \ + if test "$$installfiles" = '$(srcdir)/html/*'; \ + then echo '-- Nothing to install' ; \ + else \ + if test -n "$(DOC_MODULE_VERSION)"; then \ + installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \ + else \ + installdir="$(DESTDIR)$(TARGET_DIR)"; \ + fi; \ + $(mkinstalldirs) $${installdir} ; \ + for i in $$installfiles; do \ + echo '-- Installing '$$i ; \ + $(INSTALL_DATA) $$i $${installdir}; \ + done; \ + if test -n "$(DOC_MODULE_VERSION)"; then \ + mv -f $${installdir}/$(DOC_MODULE).devhelp2 \ + $${installdir}/$(DOC_MODULE)-$(DOC_MODULE_VERSION).devhelp2; \ + mv -f $${installdir}/$(DOC_MODULE).devhelp \ + $${installdir}/$(DOC_MODULE)-$(DOC_MODULE_VERSION).devhelp; \ + fi; \ + ! which gtkdoc-rebase >/dev/null 2>&1 || \ + gtkdoc-rebase --relative --dest-dir=$(DESTDIR) --html-dir=$${installdir} ; \ + fi + +uninstall-local: + if test -n "$(DOC_MODULE_VERSION)"; then \ + installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \ + else \ + installdir="$(DESTDIR)$(TARGET_DIR)"; \ + fi; \ + rm -rf $${installdir} + +# +# Require gtk-doc when making dist +# +if ENABLE_GTK_DOC +dist-check-gtkdoc: +else +dist-check-gtkdoc: + @echo "*** gtk-doc must be installed and enabled in order to make dist" + @false +endif + +dist-hook: dist-check-gtkdoc dist-hook-local + mkdir $(distdir)/tmpl + mkdir $(distdir)/xml + mkdir $(distdir)/html + -cp $(srcdir)/tmpl/*.sgml $(distdir)/tmpl + -cp $(srcdir)/xml/*.xml $(distdir)/xml + -cp $(srcdir)/html/* $(distdir)/html + -cp $(srcdir)/$(DOC_MODULE).types $(distdir)/ + -cp $(srcdir)/$(DOC_MODULE)-sections.txt $(distdir)/ + cd $(distdir) && rm -f $(DISTCLEANFILES) + ! which gtkdoc-rebase >/dev/null 2>&1 || \ + gtkdoc-rebase --online --relative --html-dir=$(distdir)/html + +.PHONY : dist-hook-local docs diff --git a/libdbusmenu-glib/Makefile.am b/libdbusmenu-glib/Makefile.am index c1aff41..3df1513 100644 --- a/libdbusmenu-glib/Makefile.am +++ b/libdbusmenu-glib/Makefile.am @@ -99,21 +99,25 @@ menuitem-marshal.c: $(srcdir)/menuitem-marshal.list -include $(INTROSPECTION_MAKEFILE) INTROSPECTION_GIRS = -INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir) +INTROSPECTION_SCANNER_ARGS = \ + --add-include-path=$(srcdir) \ + $(addprefix --c-include=libdbusmenu-glib/, $(introspection_sources)) INTROSPECTION_COMPILER_ARGS = --includedir=$(builddir) if HAVE_INTROSPECTION introspection_sources = $(libdbusmenu_glibinclude_HEADERS) -DbusmenuGlib-0.2.gir: libdbusmenu-glib.la -DbusmenuGlib_0_2_gir_INCLUDES = \ +Dbusmenu_Glib-0.2.gir: libdbusmenu-glib.la +Dbusmenu_Glib_0_2_gir_INCLUDES = \ GObject-2.0 -DbusmenuGlib_0_2_gir_CFLAGS = $(DBUSMENUGLIB_CFLAGS) -DbusmenuGlib_0_2_gir_LIBS = libdbusmenu-glib.la -DbusmenuGlib_0_2_gir_FILES = $(addprefix $(srcdir)/, $(introspection_sources)) +Dbusmenu_Glib_0_2_gir_CFLAGS = $(DBUSMENUGLIB_CFLAGS) +Dbusmenu_Glib_0_2_gir_LIBS = libdbusmenu-glib.la +Dbusmenu_Glib_0_2_gir_FILES = $(addprefix $(srcdir)/, $(introspection_sources)) +Dbusmenu_Glib_0_2_gir_NAMESPACE = Dbusmenu +Dbusmenu_Glib_0_2_gir_VERSION = Glib-0.2 -INTROSPECTION_GIRS += DbusmenuGlib-0.2.gir +INTROSPECTION_GIRS += Dbusmenu-Glib-0.2.gir girdir = $(datadir)/gir-1.0 gir_DATA = $(INTROSPECTION_GIRS) @@ -132,10 +136,10 @@ endif if HAVE_INTROSPECTION vapidir = $(datadir)/vala/vapi -vapi_DATA = DbusmenuGlib-0.2.vapi +vapi_DATA = Dbusmenu-Glib-0.2.vapi -DbusmenuGlib-0.2.vapi: DbusmenuGlib-0.2.gir - $(VALA_API_GEN) --library=DbusmenuGlib-0.2 $< +Dbusmenu-Glib-0.2.vapi: Dbusmenu-Glib-0.2.gir + $(VALA_API_GEN) --library=Dbusmenu-Glib-0.2 $< CLEANFILES += $(vapi_DATA) diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index d2ba541..2e985d6 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -30,6 +30,8 @@ License version 3 and version 2.1 along with this program. If not, see #include "config.h" #endif +#include <dbus/dbus-glib-bindings.h> + #include <libxml/parser.h> #include <libxml/tree.h> @@ -397,6 +399,25 @@ dbus_owner_change (DBusGProxy * proxy, const gchar * name, const gchar * prev, c return build_proxies(client); } +/* This is the response to see if the name has an owner. If + it does, then we should build the proxies here. Race condition + check. */ +static void +name_owner_check (DBusGProxy *proxy, gboolean has_owner, GError *error, gpointer userdata) +{ + if (error != NULL) { + return; + } + + if (!has_owner) { + return; + } + + DbusmenuClient * client = DBUSMENU_CLIENT(userdata); + build_proxies(client); + return; +} + /* This function builds the DBus proxy which will look out for the service coming up. */ static void @@ -426,6 +447,13 @@ build_dbus_proxy (DbusmenuClient * client) dbus_g_proxy_connect_signal(priv->dbusproxy, "NameOwnerChanged", G_CALLBACK(dbus_owner_change), client, NULL); + /* Now let's check to make sure we're not in some race + condition case. */ + org_freedesktop_DBus_name_has_owner_async(priv->dbusproxy, + priv->dbus_name, + name_owner_check, + client); + return; } @@ -533,6 +561,12 @@ build_proxies (DbusmenuClient * client) static gint parse_node_get_id (xmlNodePtr node) { + if (node == NULL) { + return -1; + } + if (node->type != XML_ELEMENT_NODE) { + return -1; + } if (g_strcmp0((gchar *)node->name, "menu") != 0) { /* This kills some nodes early */ g_warning("XML Node is not 'menu' it is '%s'", node->name); @@ -682,6 +716,17 @@ menuitem_call_cb (DBusGProxy * proxy, GError * error, gpointer userdata) void dbusmenu_client_send_event (DbusmenuClient * client, gint id, const gchar * name, const GValue * value, guint timestamp) { + g_return_if_fail(DBUSMENU_IS_CLIENT(client)); + g_return_if_fail(id >= 0); + g_return_if_fail(name != NULL); + + if (value == NULL) { + GValue internalval = {0}; + g_value_init(&internalval, G_TYPE_INT); + g_value_set_int(&internalval, 0); + value = &internalval; + } + DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client); org_ayatana_dbusmenu_event_async (priv->menuproxy, id, name, value, timestamp, menuitem_call_cb, GINT_TO_POINTER(id)); return; @@ -855,6 +900,10 @@ parse_layout (DbusmenuClient * client, const gchar * layout) xmlNodePtr root = xmlDocGetRootElement(xmldoc); + if (root == NULL) { + g_warning("Unable to get root node of menu XML"); + } + DbusmenuMenuitem * oldroot = priv->root; priv->root = parse_layout_xml(client, root, priv->root, NULL, priv->menuproxy); diff --git a/libdbusmenu-glib/dbus-menu.xml b/libdbusmenu-glib/dbus-menu.xml index 7937049..53b67de 100644 --- a/libdbusmenu-glib/dbus-menu.xml +++ b/libdbusmenu-glib/dbus-menu.xml @@ -29,12 +29,18 @@ License version 3 and version 2.1 along with this program. If not, see <http://www.gnu.org/licenses/> --> <node name="/" xmlns:dox="http://www.ayatana.org/dbus/dox.dtd"> + <dox:d><![CDATA[ + @mainpage + + The goal of DBusMenu is to expose menus on DBus. + + Main interface is documented here: @ref org::ayatana::dbusmenu + ]]></dox:d> <interface name="org.ayatana.dbusmenu"> <dox:d><![CDATA[ - The goal of this DBus interface is to be able to pass menu items - through DBus. + A DBus interface to expose menus on DBus. - Items are represented with a unique numeric id and a dictionary of + Menu items are represented with a unique numeric id and a dictionary of properties. To reduce the amount of DBus traffic, a property should only be returned @@ -100,6 +106,20 @@ License version 3 and version 2.1 along with this program. If not, see <td>Empty</td> </tr> <tr> + <td>shortcut</td> + <td>array of arrays of strings</td> + <td>The shortcut of the item. Each array represents the key press + in the list of keypresses. Each list of strings contains a list of + modifiers and then the key that is used. The modifier strings + allowed are: "Control", "Alt", "Shift" and "Super". + + - A simple shortcut like Ctrl+S is represented as: + [["Control", "S"]] + - A complex shortcut like Ctrl+Q, Alt+X is represented as: + [["Control", "Q"], ["Alt", "X"]]</td> + <td>Empty</td> + </tr> + <tr> <td>toggle-type</td> <td>string</td> <td> diff --git a/libdbusmenu-glib/menuitem.c b/libdbusmenu-glib/menuitem.c index 6a3c4bc..623539c 100644 --- a/libdbusmenu-glib/menuitem.c +++ b/libdbusmenu-glib/menuitem.c @@ -517,6 +517,9 @@ dbusmenu_menuitem_take_children (DbusmenuMenuitem * mi) GList * children = priv->children; priv->children = NULL; g_list_foreach(children, take_children_signal, mi); + + dbusmenu_menuitem_property_remove(mi, DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY); + return children; } @@ -622,6 +625,10 @@ dbusmenu_menuitem_child_append (DbusmenuMenuitem * mi, DbusmenuMenuitem * child) DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi); g_return_val_if_fail(g_list_find(priv->children, child) == NULL, FALSE); + if (priv->children == NULL && !dbusmenu_menuitem_property_exist(mi, DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY)) { + dbusmenu_menuitem_property_set(mi, DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY, DBUSMENU_MENUITEM_CHILD_DISPLAY_SUBMENU); + } + priv->children = g_list_append(priv->children, child); #ifdef MASSIVEDEBUGGING g_debug("Menuitem %d (%s) signalling child added %d (%s) at %d", ID(mi), LABEL(mi), ID(child), LABEL(child), g_list_length(priv->children) - 1); @@ -650,6 +657,10 @@ dbusmenu_menuitem_child_prepend (DbusmenuMenuitem * mi, DbusmenuMenuitem * child DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi); g_return_val_if_fail(g_list_find(priv->children, child) == NULL, FALSE); + if (priv->children == NULL && !dbusmenu_menuitem_property_exist(mi, DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY)) { + dbusmenu_menuitem_property_set(mi, DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY, DBUSMENU_MENUITEM_CHILD_DISPLAY_SUBMENU); + } + priv->children = g_list_prepend(priv->children, child); #ifdef MASSIVEDEBUGGING g_debug("Menuitem %d (%s) signalling child added %d (%s) at %d", ID(mi), LABEL(mi), ID(child), LABEL(child), 0); @@ -683,6 +694,11 @@ dbusmenu_menuitem_child_delete (DbusmenuMenuitem * mi, DbusmenuMenuitem * child) #endif g_signal_emit(G_OBJECT(mi), signals[CHILD_REMOVED], 0, child, TRUE); g_object_unref(G_OBJECT(child)); + + if (priv->children == NULL) { + dbusmenu_menuitem_property_remove(mi, DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY); + } + return TRUE; } @@ -707,6 +723,10 @@ dbusmenu_menuitem_child_add_position (DbusmenuMenuitem * mi, DbusmenuMenuitem * DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi); g_return_val_if_fail(g_list_find(priv->children, child) == NULL, FALSE); + if (priv->children == NULL && !dbusmenu_menuitem_property_exist(mi, DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY)) { + dbusmenu_menuitem_property_set(mi, DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY, DBUSMENU_MENUITEM_CHILD_DISPLAY_SUBMENU); + } + priv->children = g_list_insert(priv->children, child, position); #ifdef MASSIVEDEBUGGING g_debug("Menuitem %d (%s) signalling child added %d (%s) at %d", ID(mi), LABEL(mi), ID(child), LABEL(child), position); @@ -1199,7 +1219,7 @@ dbusmenu_menuitem_get_root (DbusmenuMenuitem * mi) /** dbusmenu_menuitem_buildxml: @mi: #DbusmenuMenuitem to represent in XML - @array: A list of string that will be turned into an XML file + @array: (element-type utf8): A list of string that will be turned into an XML file This function will add strings to the array @array. It will put at least one entry if this menu item has no children. If it has @@ -1247,7 +1267,7 @@ foreach_helper (gpointer data, gpointer user_data) dbusmenu_menuitem_foreach: @mi: The #DbusmenItem to start from @func: Function to call on every node in the tree - @data: User data to pass to the function + @data: (closure): User data to pass to the function This calls the function @func on this menu item and all of the children of this item. And their children. And @@ -1305,7 +1325,7 @@ dbusmenu_menuitem_handle_event (DbusmenuMenuitem * mi, const gchar * name, const dbusmenu_menuitem_send_about_to_show: @mi: The #DbusmenuMenuitem to send the signal on. @cb: Callback to call when the call has returned. - @cb_data: Data to pass to the callback. + @cb_data: (closure): Data to pass to the callback. This function is used to send the even that the submenu of this item is about to be shown. Callers to this event diff --git a/libdbusmenu-glib/menuitem.h b/libdbusmenu-glib/menuitem.h index e5b5ae2..e17d851 100644 --- a/libdbusmenu-glib/menuitem.h +++ b/libdbusmenu-glib/menuitem.h @@ -58,6 +58,8 @@ G_BEGIN_DECLS #define DBUSMENU_MENUITEM_PROP_ICON_DATA "icon-data" #define DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE "toggle-type" #define DBUSMENU_MENUITEM_PROP_TOGGLE_STATE "toggle-state" +#define DBUSMENU_MENUITEM_PROP_SHORTCUT "shortcut" +#define DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY "children-display" #define DBUSMENU_MENUITEM_TOGGLE_CHECK "checkmark" #define DBUSMENU_MENUITEM_TOGGLE_RADIO "radio" @@ -68,16 +70,23 @@ G_BEGIN_DECLS #define DBUSMENU_MENUITEM_ICON_NAME_BLANK "blank-icon" +#define DBUSMENU_MENUITEM_SHORTCUT_CONTROL "Control" +#define DBUSMENU_MENUITEM_SHORTCUT_ALT "Alt" +#define DBUSMENU_MENUITEM_SHORTCUT_SHIFT "Shift" +#define DBUSMENU_MENUITEM_SHORTCUT_SUPER "Super" + +#define DBUSMENU_MENUITEM_CHILD_DISPLAY_SUBMENU "submenu" + /** - DbusmenuMenuitem: - - This is the #GObject based object that represents a menu - item. It gets created the same on both the client and - the server side and libdbusmenu-glib does the work of making - this object model appear on both sides of DBus. Simple - really, though through updates and people coming on and off - the bus it can lead to lots of fun complex scenarios. -*/ + * DbusmenuMenuitem: + * + * This is the #GObject based object that represents a menu + * item. It gets created the same on both the client and + * the server side and libdbusmenu-glib does the work of making + * this object model appear on both sides of DBus. Simple + * really, though through updates and people coming on and off + * the bus it can lead to lots of fun complex scenarios. + */ typedef struct _DbusmenuMenuitem DbusmenuMenuitem; struct _DbusmenuMenuitem { @@ -85,36 +94,41 @@ struct _DbusmenuMenuitem }; /** - dbusmenu_menuitem_about_to_show_cb: - @mi Menu item that should be shown - @user_data Extra user data sent with the function - - Callback prototype for a callback that is called when the - menu should be shown. -*/ + * dbusmenu_menuitem_about_to_show_cb: + * @mi: Menu item that should be shown + * @user_data: (closure): Extra user data sent with the function + * + * Callback prototype for a callback that is called when the + * menu should be shown. + */ typedef void (*dbusmenu_menuitem_about_to_show_cb) (DbusmenuMenuitem * mi, gpointer user_data); +/** + * dbusmenu_menuitem_buildxml_slot_t: + * @mi: (in): Menu item that should be built from + * @stringarray: (inout) (transfer none) (array) (element-type utf8): An array of strings that can be combined into an XML file. + * + * This is the function that is called to represent this menu item + * as an XML fragment. Should call it's own children. + */ +typedef void (*dbusmenu_menuitem_buildxml_slot_t) (DbusmenuMenuitem * mi, GPtrArray* stringarray); /** - DbusmenuMenuitemClass: - @property_changed: Slot for #DbusmenuMenuitem::property-changed. - @item_activated: Slot for #DbusmenuMenuitem::item-activated. - @child_added: Slot for #DbusmenuMenuitem::child-added. - @child_removed: Slot for #DbusmenuMenuitem::child-removed. - @child_moved: Slot for #DbusmenuMenuitem::child-moved. - @realized: Slot for #DbusmenuMenuitem::realized. - @buildxml: Virtual function that appends the strings required - to represent this menu item in the menu XML file. - @handle_event: This function is to override how events are handled - by subclasses. Look at #dbusmenu_menuitem_handle_event for - lots of good information. - @send_about_to_show: Virtual function that notifies server that the - client is about to show a menu. - @reserved1: Reserved for future use. - @reserved2: Reserved for future use. - @reserved3: Reserved for future use. - @reserved4: Reserved for future use. -*/ + * DbusmenuMenuitemClass: + * @property_changed: Slot for #DbusmenuMenuitem::property-changed. + * @item_activated: Slot for #DbusmenuMenuitem::item-activated. + * @child_added: Slot for #DbusmenuMenuitem::child-added. + * @child_removed: Slot for #DbusmenuMenuitem::child-removed. + * @child_moved: Slot for #DbusmenuMenuitem::child-moved. + * @realized: Slot for #DbusmenuMenuitem::realized. + * @buildxml: Virtual function that appends the strings required to represent this menu item in the menu XML file. + * @handle_event: This function is to override how events are handled by subclasses. Look at #dbusmenu_menuitem_handle_event for lots of good information. + * @send_about_to_show: Virtual function that notifies server that the client is about to show a menu. + * @reserved1: Reserved for future use. + * @reserved2: Reserved for future use. + * @reserved3: Reserved for future use. + * @reserved4: Reserved for future use. + */ typedef struct _DbusmenuMenuitemClass DbusmenuMenuitemClass; struct _DbusmenuMenuitemClass { @@ -129,7 +143,7 @@ struct _DbusmenuMenuitemClass void (*realized) (void); /* Virtual functions */ - void (*buildxml) (GPtrArray * stringarray); + dbusmenu_menuitem_buildxml_slot_t buildxml; void (*handle_event) (DbusmenuMenuitem * mi, const gchar * name, const GValue * value, guint timestamp); void (*send_about_to_show) (DbusmenuMenuitem * mi, dbusmenu_menuitem_about_to_show_cb cb, gpointer cb_data); @@ -179,23 +193,23 @@ void dbusmenu_menuitem_handle_event (DbusmenuMenuitem * mi, const gchar * name, void dbusmenu_menuitem_send_about_to_show (DbusmenuMenuitem * mi, dbusmenu_menuitem_about_to_show_cb cb, gpointer cb_data); /** - SECTION:menuitem - @short_description: A lowlevel represenation of a menuitem - @stability: Unstable - @include: libdbusmenu-glib/menuitem.h - - A #DbusmenuMenuitem is the lowest level of represenation of a - single item in a menu. It gets created on the server side - and copied over to the client side where it gets rendered. As - the server starts to change it, and grow it, and do all kinds - of fun stuff that information is transfered over DBus and the - client updates it's understanding of the object model. - - Most people using either the client or the server should be - able to deal mostly with #DbusmenuMenuitem objects. These - are simple, but then they can be attached to more complex - objects and handled appropriately. -*/ + * SECTION:menuitem + * @short_description: A lowlevel represenation of a menuitem + * @stability: Unstable + * @include: libdbusmenu-glib/menuitem.h + * + * A #DbusmenuMenuitem is the lowest level of represenation of a + * single item in a menu. It gets created on the server side + * and copied over to the client side where it gets rendered. As + * the server starts to change it, and grow it, and do all kinds + * of fun stuff that information is transfered over DBus and the + * client updates it's understanding of the object model. + * + * Most people using either the client or the server should be + * able to deal mostly with #DbusmenuMenuitem objects. These + * are simple, but then they can be attached to more complex + * objects and handled appropriately. + */ G_END_DECLS diff --git a/libdbusmenu-glib/server.c b/libdbusmenu-glib/server.c index 02c9c57..13c2843 100644 --- a/libdbusmenu-glib/server.c +++ b/libdbusmenu-glib/server.c @@ -146,8 +146,8 @@ dbusmenu_server_class_init (DbusmenuServerClass *class) G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(DbusmenuServerClass, id_update), NULL, NULL, - g_cclosure_marshal_VOID__UINT, - G_TYPE_NONE, 1, G_TYPE_UINT); + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); /** DbusmenuServer::layout-updated: @arg0: The #DbusmenuServer emitting the signal. @@ -225,15 +225,22 @@ static void set_property (GObject * obj, guint id, const GValue * value, GParamSpec * pspec) { DbusmenuServerPrivate * priv = DBUSMENU_SERVER_GET_PRIVATE(obj); + GError * error = NULL; switch (id) { case PROP_DBUS_OBJECT: g_return_if_fail(priv->dbusobject == NULL); priv->dbusobject = g_value_dup_string(value); - DBusGConnection * connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); - dbus_g_connection_register_g_object(connection, - priv->dbusobject, - obj); + DBusGConnection * connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error); + + if (connection == NULL || error != NULL) { + g_warning("Unable to get session bus: %s", error == NULL ? "No message" : error->message); + if (error != NULL) { g_error_free(error); } + } else { + dbus_g_connection_register_g_object(connection, + priv->dbusobject, + obj); + } break; case PROP_ROOT_NODE: if (priv->root != NULL) { diff --git a/libdbusmenu-gtk/Makefile.am b/libdbusmenu-gtk/Makefile.am index 9cc557c..2be63b7 100644 --- a/libdbusmenu-gtk/Makefile.am +++ b/libdbusmenu-gtk/Makefile.am @@ -45,7 +45,10 @@ pkgconfigdir = $(libdir)/pkgconfig -include $(INTROSPECTION_MAKEFILE) INTROSPECTION_GIRS = -INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir) --add-include-path=$(top_builddir)/libdbusmenu-glib +INTROSPECTION_SCANNER_ARGS = \ + --add-include-path=$(srcdir) \ + --add-include-path=$(top_builddir)/libdbusmenu-glib \ + $(addprefix --c-include=libdbusmenu-gtk/, $(introspection_sources)) INTROSPECTION_COMPILER_ARGS = --includedir=$(builddir) --includedir=$(top_builddir)/libdbusmenu-glib if HAVE_INTROSPECTION @@ -56,7 +59,7 @@ DbusmenuGtk-0.2.gir: libdbusmenu-gtk.la DbusmenuGtk_0_2_gir_INCLUDES = \ GObject-2.0 \ Gtk-2.0 \ - DbusmenuGlib-0.2 + Dbusmenu-Glib-0.2 DbusmenuGtk_0_2_gir_CFLAGS = $(DBUSMENUGTK_CFLAGS) -I$(top_srcdir) DbusmenuGtk_0_2_gir_LIBS = libdbusmenu-gtk.la DbusmenuGtk_0_2_gir_FILES = $(addprefix $(srcdir)/, $(introspection_sources)) @@ -87,7 +90,7 @@ DbusmenuGtk-0.2.vapi: DbusmenuGtk-0.2.tmp.gir Makefile.am --pkg gdk-pixbuf-2.0 \ --pkg gtk+-2.0 \ --pkg atk \ - --pkg DbusmenuGlib-0.2 \ + --pkg Dbusmenu-Glib-0.2 \ --vapidir=$(top_builddir)/libdbusmenu-glib \ $< diff --git a/libdbusmenu-gtk/client.c b/libdbusmenu-gtk/client.c index b13af6a..b406697 100644 --- a/libdbusmenu-gtk/client.c +++ b/libdbusmenu-gtk/client.c @@ -36,6 +36,15 @@ License version 3 and version 2.1 along with this program. If not, see #include "menuitem.h" #include "genericmenuitem.h" +/* Private */ +typedef struct _DbusmenuGtkClientPrivate DbusmenuGtkClientPrivate; +struct _DbusmenuGtkClientPrivate { + GtkAccelGroup * agroup; +}; + +#define DBUSMENU_GTKCLIENT_GET_PRIVATE(o) \ +(G_TYPE_INSTANCE_GET_PRIVATE ((o), DBUSMENU_GTKCLIENT_TYPE, DbusmenuGtkClientPrivate)) + /* Prototypes */ static void dbusmenu_gtkclient_class_init (DbusmenuGtkClientClass *klass); static void dbusmenu_gtkclient_init (DbusmenuGtkClient *self); @@ -62,6 +71,8 @@ dbusmenu_gtkclient_class_init (DbusmenuGtkClientClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); + g_type_class_add_private (klass, sizeof (DbusmenuGtkClientPrivate)); + object_class->dispose = dbusmenu_gtkclient_dispose; object_class->finalize = dbusmenu_gtkclient_finalize; @@ -73,6 +84,10 @@ dbusmenu_gtkclient_class_init (DbusmenuGtkClientClass *klass) static void dbusmenu_gtkclient_init (DbusmenuGtkClient *self) { + DbusmenuGtkClientPrivate * priv = DBUSMENU_GTKCLIENT_GET_PRIVATE(self); + + priv->agroup = NULL; + dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(self), DBUSMENU_CLIENT_TYPES_DEFAULT, new_item_normal); dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(self), DBUSMENU_CLIENT_TYPES_SEPARATOR, new_item_seperator); @@ -85,6 +100,12 @@ dbusmenu_gtkclient_init (DbusmenuGtkClient *self) static void dbusmenu_gtkclient_dispose (GObject *object) { + DbusmenuGtkClientPrivate * priv = DBUSMENU_GTKCLIENT_GET_PRIVATE(object); + + if (priv->agroup != NULL) { + g_object_unref(priv->agroup); + priv->agroup = NULL; + } G_OBJECT_CLASS (dbusmenu_gtkclient_parent_class)->dispose (object); return; @@ -99,6 +120,155 @@ dbusmenu_gtkclient_finalize (GObject *object) return; } +/* Structure for passing data to swap_agroup */ +typedef struct _swap_agroup_t swap_agroup_t; +struct _swap_agroup_t { + DbusmenuGtkClient * client; + GtkAccelGroup * old_agroup; + GtkAccelGroup * new_agroup; +}; + +/* Looks at the old version of the accelerator group and + the new one and makes the state proper. */ +static gboolean +do_swap_agroup (DbusmenuMenuitem * mi, gpointer userdata) { + swap_agroup_t * data = (swap_agroup_t *)userdata; + + /* If we don't have a shortcut we don't care */ + if (!dbusmenu_menuitem_property_exist(mi, DBUSMENU_MENUITEM_PROP_SHORTCUT)) { + return FALSE; + } + + guint key = 0; + GdkModifierType modifiers = 0; + + dbusmenu_menuitem_property_get_shortcut(mi, &key, &modifiers); + + if (key == 0) { + return FALSE; + } + + #ifdef MASSIVEDEBUGGING + g_debug("Setting shortcut on '%s': %d %X", dbusmenu_menuitem_property_get(mi, DBUSMENU_MENUITEM_PROP_LABEL), key, modifiers); + #endif + + GtkMenuItem * gmi = dbusmenu_gtkclient_menuitem_get(data->client, mi); + if (gmi == NULL) { + return FALSE; + } + + const gchar * accel_path = gtk_menu_item_get_accel_path(gmi); + + if (accel_path != NULL) { + gtk_accel_map_change_entry(accel_path, key, modifiers, TRUE /* replace */); + } else { + gchar * accel_path = g_strdup_printf("<Appmenus>/Generated/%X/%d", GPOINTER_TO_UINT(data->client), dbusmenu_menuitem_get_id(mi)); + + gtk_accel_map_add_entry(accel_path, key, modifiers); + gtk_widget_set_accel_path(GTK_WIDGET(gmi), accel_path, data->new_agroup); + g_free(accel_path); + } + + GtkMenu * submenu = dbusmenu_gtkclient_menuitem_get_submenu(data->client, mi); + if (submenu != NULL) { + gtk_menu_set_accel_group(submenu, data->new_agroup); + } + + return TRUE; +} + +static void +swap_agroup (DbusmenuMenuitem *mi, gpointer userdata) { + do_swap_agroup (mi, userdata); + + return; /* See what I did here, Ted? :) */ +} + +/* Refresh the shortcut for an entry */ +static void +refresh_shortcut (DbusmenuGtkClient * client, DbusmenuMenuitem * mi) +{ + g_return_if_fail(DBUSMENU_IS_GTKCLIENT(client)); + g_return_if_fail(DBUSMENU_IS_MENUITEM(mi)); + + DbusmenuGtkClientPrivate * priv = DBUSMENU_GTKCLIENT_GET_PRIVATE(client); + + swap_agroup_t data; + data.client = client; + data.old_agroup = priv->agroup; + data.new_agroup = priv->agroup; + + if (do_swap_agroup(mi, &data)) { + guint key = 0; + GdkModifierType mod = 0; + GtkMenuItem *gmi = dbusmenu_gtkclient_menuitem_get (client, mi); + + dbusmenu_menuitem_property_get_shortcut (mi, &key, &mod); + + if (key != 0) { + gtk_widget_add_accelerator (GTK_WIDGET (gmi), "activate", priv->agroup, key, mod, GTK_ACCEL_VISIBLE); + } + } + + return; +} + + +/** + dbusmenu_gtkclient_set_accel_group: + @client: To set the group on + @agroup: The new acceleration group + + Sets the acceleration group for the menu items with accelerators + on this client. +*/ +void +dbusmenu_gtkclient_set_accel_group (DbusmenuGtkClient * client, GtkAccelGroup * agroup) +{ + g_return_if_fail(DBUSMENU_IS_GTKCLIENT(client)); + g_return_if_fail(GTK_IS_ACCEL_GROUP(agroup)); + + DbusmenuGtkClientPrivate * priv = DBUSMENU_GTKCLIENT_GET_PRIVATE(client); + + DbusmenuMenuitem * root = dbusmenu_client_get_root(DBUSMENU_CLIENT(client)); + if (root != NULL) { + swap_agroup_t data; + data.client = client; + data.old_agroup = priv->agroup; + data.new_agroup = agroup; + + dbusmenu_menuitem_foreach(root, swap_agroup, &data); + } + + if (priv->agroup != NULL) { + g_object_unref(priv->agroup); + priv->agroup = NULL; + } + + priv->agroup = agroup; + + return; +} + +/** + dbusmenu_gtkclient_get_accel_group: + @client: Client to query for an accelerator group + + Gets the accel group for this client. + + Return value: Either a valid group or #NULL on error or + none set. +*/ +GtkAccelGroup * +dbusmenu_gtkclient_get_accel_group (DbusmenuGtkClient * client) +{ + g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), NULL); + + DbusmenuGtkClientPrivate * priv = DBUSMENU_GTKCLIENT_GET_PRIVATE(client); + + return priv->agroup; +} + /* Internal Functions */ static const gchar * data_menuitem = "dbusmenugtk-data-gtkmenuitem"; @@ -225,6 +395,17 @@ menu_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, GValue * value, GtkMen return; } +/* Special handler for the shortcut changing as we need to have the + client for that one to get the accel group. */ +static void +menu_shortcut_change_cb (DbusmenuMenuitem * mi, gchar * prop, GValue * value, DbusmenuGtkClient * client) +{ + if (!g_strcmp0(prop, DBUSMENU_MENUITEM_PROP_SHORTCUT)) { + refresh_shortcut(client, mi); + } + return; +} + /* Call back that happens when the DbusmenuMenuitem is destroyed. We're making sure to clean up everything else down the pipe. */ @@ -291,6 +472,7 @@ dbusmenu_gtkclient_newitem_base (DbusmenuGtkClient * client, DbusmenuMenuitem * /* DbusmenuMenuitem signals */ g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(menu_prop_change_cb), gmi); + g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(menu_shortcut_change_cb), client); g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_CHILD_REMOVED, G_CALLBACK(delete_child), client); g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_CHILD_MOVED, G_CALLBACK(move_child), client); @@ -305,6 +487,7 @@ dbusmenu_gtkclient_newitem_base (DbusmenuGtkClient * client, DbusmenuMenuitem * process_sensitive(item, gmi, dbusmenu_menuitem_property_get_value(item, DBUSMENU_MENUITEM_PROP_ENABLED)); process_toggle_type(item, gmi, dbusmenu_menuitem_property_get_value(item, DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE)); process_toggle_state(item, gmi, dbusmenu_menuitem_property_get_value(item, DBUSMENU_MENUITEM_PROP_TOGGLE_STATE)); + refresh_shortcut(client, item); /* Oh, we're a child, let's deal with that */ if (parent != NULL) { @@ -322,6 +505,7 @@ new_child (DbusmenuMenuitem * mi, DbusmenuMenuitem * child, guint position, Dbus #endif if (dbusmenu_menuitem_get_root(mi)) { return; } + if (g_strcmp0(dbusmenu_menuitem_property_get(mi, DBUSMENU_MENUITEM_PROP_TYPE), DBUSMENU_CLIENT_TYPES_SEPARATOR) == 0) { return; } gpointer ann_menu = g_object_get_data(G_OBJECT(mi), data_menu); GtkMenu * menu = GTK_MENU(ann_menu); @@ -423,6 +607,29 @@ dbusmenu_gtkclient_menuitem_get (DbusmenuGtkClient * client, DbusmenuMenuitem * return GTK_MENU_ITEM(data); } +/** + dbusmenu_gtkclient_menuitem_get_submenu: + @client: A #DbusmenuGtkClient with the item in it. + @item: #DbusmenuMenuitem to get associated #GtkMenu on. + + This grabs the submenu associated with the menuitem. + + Return value: The #GtkMenu if there is one. +*/ +GtkMenu * +dbusmenu_gtkclient_menuitem_get_submenu (DbusmenuGtkClient * client, DbusmenuMenuitem * item) +{ + g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), NULL); + g_return_val_if_fail(DBUSMENU_IS_MENUITEM(item), NULL); + + gpointer data = g_object_get_data(G_OBJECT(item), data_menu); + if (data == NULL) { + return NULL; + } + + return GTK_MENU(data); +} + /* The base type handler that builds a plain ol' GtkMenuItem to represent, well, the GtkMenuItem */ static gboolean diff --git a/libdbusmenu-gtk/client.h b/libdbusmenu-gtk/client.h index 4cfbdcf..a7c96ee 100644 --- a/libdbusmenu-gtk/client.h +++ b/libdbusmenu-gtk/client.h @@ -77,6 +77,10 @@ struct _DbusmenuGtkClient { GType dbusmenu_gtkclient_get_type (void); DbusmenuGtkClient * dbusmenu_gtkclient_new (gchar * dbus_name, gchar * dbus_object); GtkMenuItem * dbusmenu_gtkclient_menuitem_get (DbusmenuGtkClient * client, DbusmenuMenuitem * item); +GtkMenu * dbusmenu_gtkclient_menuitem_get_submenu (DbusmenuGtkClient * client, DbusmenuMenuitem * item); + +void dbusmenu_gtkclient_set_accel_group (DbusmenuGtkClient * client, GtkAccelGroup * agroup); +GtkAccelGroup * dbusmenu_gtkclient_get_accel_group (DbusmenuGtkClient * client); void dbusmenu_gtkclient_newitem_base (DbusmenuGtkClient * client, DbusmenuMenuitem * item, GtkMenuItem * gmi, DbusmenuMenuitem * parent); diff --git a/libdbusmenu-gtk/genericmenuitem.c b/libdbusmenu-gtk/genericmenuitem.c index 8f40d93..30b072f 100644 --- a/libdbusmenu-gtk/genericmenuitem.c +++ b/libdbusmenu-gtk/genericmenuitem.c @@ -158,6 +158,8 @@ get_hpadding (GtkWidget * widget) static void set_label (GtkMenuItem * menu_item, const gchar * label) { + if (label == NULL) return; + GtkWidget * child = gtk_bin_get_child(GTK_BIN(menu_item)); GtkLabel * labelw = NULL; gboolean suppress_update = FALSE; @@ -191,9 +193,10 @@ set_label (GtkMenuItem * menu_item, const gchar * label) update the one that we already have. */ if (labelw == NULL) { /* Build it */ - labelw = GTK_LABEL(gtk_label_new(label)); + labelw = GTK_LABEL(gtk_accel_label_new(label)); gtk_label_set_use_underline(GTK_LABEL(labelw), TRUE); gtk_misc_set_alignment(GTK_MISC(labelw), 0.0, 0.5); + gtk_accel_label_set_accel_widget(GTK_ACCEL_LABEL(labelw), GTK_WIDGET(menu_item)); gtk_widget_show(GTK_WIDGET(labelw)); /* Check to see if it needs to be in the bin for this diff --git a/libdbusmenu-gtk/menuitem.c b/libdbusmenu-gtk/menuitem.c index 23ff311..5846aa7 100644 --- a/libdbusmenu-gtk/menuitem.c +++ b/libdbusmenu-gtk/menuitem.c @@ -27,6 +27,9 @@ License version 3 and version 2.1 along with this program. If not, see */ #include "menuitem.h" +#include <gdk/gdk.h> +#include <gtk/gtk.h> +#include <dbus/dbus-gtype-specialized.h> /** dbusmenu_menuitem_property_set_image: @@ -128,3 +131,248 @@ dbusmenu_menuitem_property_get_image (DbusmenuMenuitem * menuitem, const gchar * return icon; } +/** + dbusmenu_menuitem_property_set_shortcut_string: + @menuitem: The #DbusmenuMenuitem to set the shortcut on + @shortcut: String describing the shortcut + + This function takes a GTK shortcut string as defined in + #gtk_accelerator_parse and turns that into the information + required to send it over DBusmenu. + + Return value: Whether it was successful at setting the property. +*/ +gboolean +dbusmenu_menuitem_property_set_shortcut_string (DbusmenuMenuitem * menuitem, const gchar * shortcut) +{ + g_return_val_if_fail(DBUSMENU_IS_MENUITEM(menuitem), FALSE); + g_return_val_if_fail(shortcut != NULL, FALSE); + + guint key = 0; + GdkModifierType modifier = 0; + + gtk_accelerator_parse(shortcut, &key, &modifier); + + if (key == 0) { + g_warning("Unable to parse shortcut string '%s'", shortcut); + return FALSE; + } + + return dbusmenu_menuitem_property_set_shortcut(menuitem, key, modifier); +} + +/** + dbusmenu_menuitem_property_set_shortcut: + @menuitem: The #DbusmenuMenuitem to set the shortcut on + @key: The keycode of the key to send + @modifier: A bitmask of modifiers used to activate the item + + Takes the modifer described by @key and @modifier and places that into + the format sending across Dbus for shortcuts. + + Return value: Whether it was successful at setting the property. +*/ +gboolean +dbusmenu_menuitem_property_set_shortcut (DbusmenuMenuitem * menuitem, guint key, GdkModifierType modifier) +{ + g_return_val_if_fail(DBUSMENU_IS_MENUITEM(menuitem), FALSE); + g_return_val_if_fail(gtk_accelerator_valid(key, modifier), FALSE); + + GArray * array = g_array_sized_new(TRUE, TRUE, sizeof(gchar *), 4); /* Four seems like the max we'd need, plus it's still small */ + + const gchar * control_val = DBUSMENU_MENUITEM_SHORTCUT_CONTROL; + const gchar * alt_val = DBUSMENU_MENUITEM_SHORTCUT_ALT; + const gchar * shift_val = DBUSMENU_MENUITEM_SHORTCUT_SHIFT; + const gchar * super_val = DBUSMENU_MENUITEM_SHORTCUT_SUPER; + + if (modifier & GDK_CONTROL_MASK) { + g_array_append_val(array, control_val); + } + if (modifier & GDK_MOD1_MASK) { + g_array_append_val(array, alt_val); + } + if (modifier & GDK_SHIFT_MASK) { + g_array_append_val(array, shift_val); + } + if (modifier & GDK_SUPER_MASK) { + g_array_append_val(array, super_val); + } + + const gchar * keyname = gdk_keyval_name(key); + g_array_append_val(array, keyname); + + GType type = dbus_g_type_get_collection("GPtrArray", G_TYPE_STRV); + GPtrArray * wrapper = (GPtrArray *)dbus_g_type_specialized_construct(type); + + GValue value = {0,}; + g_value_init(&value, type); + g_value_take_boxed(&value, wrapper); + + DBusGTypeSpecializedAppendContext ctx; + dbus_g_type_specialized_init_append(&value, &ctx); + + GValue strval = {0,}; + g_value_init(&strval, G_TYPE_STRV); + g_value_take_boxed(&strval, array->data); + g_array_free(array, FALSE); + + dbus_g_type_specialized_collection_append(&ctx, &strval); + dbus_g_type_specialized_collection_end_append(&ctx); + + dbusmenu_menuitem_property_set_value(menuitem, DBUSMENU_MENUITEM_PROP_SHORTCUT, &value); + + return TRUE; +} + +/* Look at the closures in an accel group and find + the one that matches the one we've been passed */ +static gboolean +find_closure (GtkAccelKey * key, GClosure * closure, gpointer user_data) +{ + return closure == user_data; +} + +/** + dbusmenu_menuitem_property_set_shortcut_menuitem: + @menuitem: The #DbusmenuMenuitem to set the shortcut on + @gmi: A menu item to steal the shortcut off of + + Takes the shortcut that is installed on a menu item and calls + #dbusmenu_menuitem_property_set_shortcut with it. It also sets + up listeners to watch it change. + + Return value: Whether it was successful at setting the property. +*/ +gboolean +dbusmenu_menuitem_property_set_shortcut_menuitem (DbusmenuMenuitem * menuitem, const GtkMenuItem * gmi) +{ + g_return_val_if_fail(DBUSMENU_IS_MENUITEM(menuitem), FALSE); + g_return_val_if_fail(GTK_IS_MENU_ITEM(gmi), FALSE); + + GClosure * closure = NULL; + GtkWidget *label = GTK_BIN (gmi)->child; + + if (GTK_IS_ACCEL_LABEL (label)) + { + g_object_get (label, + "accel-closure", &closure, + NULL); + } + + if (closure == NULL) + return FALSE; + + GtkAccelGroup * group = gtk_accel_group_from_accel_closure(closure); + + /* Apparently this is more common than I thought. */ + if (group == NULL) { + return FALSE; + } + + GtkAccelKey * key = gtk_accel_group_find(group, find_closure, closure); + /* Again, not much we can do except complain loudly. */ + g_return_val_if_fail(key != NULL, FALSE); + + if (!gtk_accelerator_valid (key->accel_key, key->accel_mods)) + return FALSE; + + return dbusmenu_menuitem_property_set_shortcut(menuitem, key->accel_key, key->accel_mods); +} + +/* A set of typed data for the interator */ +typedef struct _iter_data_t iter_data_t; +struct _iter_data_t { + guint * key; + GdkModifierType * modifier; +}; + +/* Goes through the wrapper items. In reality we only support one + so it checks to see if a key is set first. But, we could possibly, + support more in the future. */ +static void +_wrapper_iterator (const GValue * value, gpointer user_data) +{ + iter_data_t * iter_data = (iter_data_t *)user_data; + + if (*iter_data->key != 0) { + g_warning("Shortcut is more than one entry. Which we don't currently support. Taking the first."); + return; + } + + if (!G_VALUE_HOLDS(value, G_TYPE_STRV)) { + g_warning("Unexpected shortcut structure. Value array is: %s", G_VALUE_TYPE_NAME(value)); + return; + } + + gchar ** stringarray = (gchar **)g_value_get_boxed(value); + if (stringarray == NULL) { + return; + } + + const gchar * last_string = NULL; + int i; + + for (i = 0; stringarray[i] != NULL; i++) { + last_string = stringarray[i]; + + if (g_strcmp0(last_string, DBUSMENU_MENUITEM_SHORTCUT_CONTROL) == 0) { + *iter_data->modifier |= GDK_CONTROL_MASK; + continue; + } + if (g_strcmp0(last_string, DBUSMENU_MENUITEM_SHORTCUT_ALT) == 0) { + *iter_data->modifier |= GDK_MOD1_MASK; + continue; + } + if (g_strcmp0(last_string, DBUSMENU_MENUITEM_SHORTCUT_SHIFT) == 0) { + *iter_data->modifier |= GDK_SHIFT_MASK; + continue; + } + if (g_strcmp0(last_string, DBUSMENU_MENUITEM_SHORTCUT_SUPER) == 0) { + *iter_data->modifier |= GDK_SUPER_MASK; + continue; + } + } + + if (last_string != NULL) { + GdkModifierType tempmod; + gtk_accelerator_parse(last_string, iter_data->key, &tempmod); + } + + return; +} + +/** + dbusmenu_menuitem_property_get_shortcut: + @menuitem: The #DbusmenuMenuitem to get the shortcut off + @key: Location to put the key value + @modifier: Location to put the modifier mask + + This function gets a GTK shortcut as a key and a mask + for use to set the accelerators. +*/ +void +dbusmenu_menuitem_property_get_shortcut (DbusmenuMenuitem * menuitem, guint * key, GdkModifierType * modifier) +{ + *key = 0; + *modifier = 0; + + g_return_if_fail(DBUSMENU_IS_MENUITEM(menuitem)); + + const GValue * wrapper = dbusmenu_menuitem_property_get_value(menuitem, DBUSMENU_MENUITEM_PROP_SHORTCUT); + if (wrapper == NULL) { + return; + } + if (!dbus_g_type_is_collection(G_VALUE_TYPE(wrapper))) { + g_warning("Unexpected shortcut structure. Wrapper is: %s", G_VALUE_TYPE_NAME(wrapper)); + return; + } + + iter_data_t iter_data; + iter_data.key = key; + iter_data.modifier = modifier; + + dbus_g_type_collection_value_iterate(wrapper, _wrapper_iterator, &iter_data); + + return; +} + diff --git a/libdbusmenu-gtk/menuitem.h b/libdbusmenu-gtk/menuitem.h index ff458de..6960f76 100644 --- a/libdbusmenu-gtk/menuitem.h +++ b/libdbusmenu-gtk/menuitem.h @@ -32,8 +32,15 @@ License version 3 and version 2.1 along with this program. If not, see #include <glib.h> #include <gdk-pixbuf/gdk-pixbuf.h> #include <libdbusmenu-glib/menuitem.h> +#include <gdk/gdk.h> +#include <gtk/gtk.h> gboolean dbusmenu_menuitem_property_set_image (DbusmenuMenuitem * menuitem, const gchar * property, const GdkPixbuf * data); GdkPixbuf * dbusmenu_menuitem_property_get_image (DbusmenuMenuitem * menuitem, const gchar * property); +gboolean dbusmenu_menuitem_property_set_shortcut (DbusmenuMenuitem * menuitem, guint key, GdkModifierType modifier); +gboolean dbusmenu_menuitem_property_set_shortcut_string (DbusmenuMenuitem * menuitem, const gchar * shortcut); +gboolean dbusmenu_menuitem_property_set_shortcut_menuitem (DbusmenuMenuitem * menuitem, const GtkMenuItem * gmi); +void dbusmenu_menuitem_property_get_shortcut (DbusmenuMenuitem * menuitem, guint * key, GdkModifierType * modifiers); + #endif diff --git a/tests/Makefile.am b/tests/Makefile.am index cfa1399..63857a2 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,13 +1,19 @@ DBUS_RUNNER=dbus-test-runner +CLEANFILES= + TESTS = \ test-glib-objects-test \ test-glib-layout \ test-glib-properties \ test-glib-proxy \ test-glib-simple-items \ + test-glib-submenu \ + test-json \ + test-gtk-objects-test \ test-gtk-label \ + test-gtk-shortcut \ test-gtk-reorder check_PROGRAMS = \ @@ -20,14 +26,58 @@ check_PROGRAMS = \ test-glib-proxy-client \ test-glib-proxy-server \ test-glib-proxy-proxy \ + test-gtk-objects \ + test-glib-submenu-client \ + test-glib-submenu-server \ test-gtk-label-client \ test-gtk-label-server \ + test-gtk-shortcut-client \ + test-gtk-shortcut-server \ test-glib-simple-items \ - test-gtk-reorder-server + test-gtk-reorder-server \ + test-json-client \ + test-json-server XVFB_RUN=". $(srcdir)/run-xvfb.sh" ###################### +# JSON Loader lib +###################### + +lib_LTLIBRARIES = libdbusmenu-jsonloader.la + +libdbusmenu_jsonloaderincludedir=$(includedir)/libdbusmenu-0.1/libdbusmenu-jsonloader/ + +libdbusmenu_jsonloaderinclude_HEADERS = \ + json-loader.h + +libdbusmenu_jsonloader_la_SOURCES = \ + json-loader.h \ + json-loader.c + +libdbusmenu_jsonloader_la_LDFLAGS = \ + -version-info $(LIBDBUSMENU_CURRENT):$(LIBDBUSMENU_REVISION):$(LIBDBUSMENU_AGE) \ + -no-undefined \ + -export-symbols-regex "^[^_].*" + +libdbusmenu_jsonloader_la_CFLAGS = \ + $(DBUSMENUGLIB_CFLAGS) \ + $(DBUSMENUTESTS_CFLAGS) \ + -I $(srcdir)/.. \ + -Wall \ + -Werror \ + -DG_DISABLE_DEPRECATED \ + -DG_LOG_DOMAIN="\"LIBDBUSMENU-JSONLOADER\"" + +libdbusmenu_jsonloader_la_LIBADD = \ + ../libdbusmenu-glib/libdbusmenu-glib.la \ + $(DBUSMENUGLIB_LIBS) \ + $(DBUSMENUTESTS_LIBS) + +pkgconfig_DATA = dbusmenu-jsonloader.pc +pkgconfigdir = $(libdir)/pkgconfig + +###################### # Test GLib server ###################### @@ -75,6 +125,79 @@ test_glib_layout_client_LDADD = \ ../libdbusmenu-glib/libdbusmenu-glib.la \ $(DBUSMENUGLIB_LIBS) +###################### +# Test JSON +###################### + +test-json: test-json-client test-json-server Makefile.am + @echo "#!/bin/bash" > $@ + @echo $(XVFB_RUN) >> $@ + @echo $(DBUS_RUNNER) --task ./test-json-client --task-name Client --parameter $(top_builddir)/tools/dbusmenu-dumper --parameter test-json-01.output.json --ignore-return --task ./test-json-server --task-name Server --parameter $(srcdir)/test-json-01.json --ignore-return >> $@ + @echo diff $(srcdir)/test-json-01.json test-json-01.output.json \> /dev/null >> $@ + @chmod +x $@ + +CLEANFILES += test-json-01.output.json + +test_json_server_SOURCES = \ + test-json-server.c + +test_json_server_CFLAGS = \ + -I $(srcdir)/.. \ + -I $(srcdir) \ + $(DBUSMENUGLIB_CFLAGS) \ + $(DBUSMENUTESTS_CFLAGS) \ + -Wall -Werror + +test_json_server_LDADD = \ + ../libdbusmenu-glib/libdbusmenu-glib.la \ + libdbusmenu-jsonloader.la \ + $(DBUSMENUTESTS_LIBS) \ + $(DBUSMENUGLIB_LIBS) + +test_json_client_SOURCES = \ + test-json-client.c + +test_json_client_CFLAGS = \ + -I $(srcdir)/.. \ + $(DBUSMENUGLIB_CFLAGS) -Wall -Werror + +test_json_client_LDADD = \ + ../libdbusmenu-glib/libdbusmenu-glib.la \ + $(DBUSMENUTESTS_LIBS) \ + $(DBUSMENUGLIB_LIBS) + +###################### +# Test Glib Submenu +###################### + +test-glib-submenu: test-glib-submenu-client test-glib-submenu-server Makefile.am + @echo "#!/bin/bash" > $@ + @echo $(DBUS_RUNNER) --task ./test-glib-submenu-client --task-name Client --task ./test-glib-submenu-server --task-name Server --ignore-return >> $@ + @chmod +x $@ + +test_glib_submenu_server_SOURCES = \ + test-glib-submenu.h \ + test-glib-submenu-server.c + +test_glib_submenu_server_CFLAGS = \ + -I $(srcdir)/.. \ + $(DBUSMENUGLIB_CFLAGS) -Wall -Werror + +test_glib_submenu_server_LDADD = \ + ../libdbusmenu-glib/libdbusmenu-glib.la \ + $(DBUSMENUGLIB_LIBS) + +test_glib_submenu_client_SOURCES = \ + test-glib-submenu.h \ + test-glib-submenu-client.c + +test_glib_submenu_client_CFLAGS = \ + -I $(srcdir)/.. \ + $(DBUSMENUGLIB_CFLAGS) -Wall -Werror + +test_glib_submenu_client_LDADD = \ + ../libdbusmenu-glib/libdbusmenu-glib.la \ + $(DBUSMENUGLIB_LIBS) ###################### # Test Glib Object @@ -84,7 +207,7 @@ OBJECT_XML_REPORT = test-glib-objects.xml test-glib-objects-test: test-glib-objects Makefile.am @echo "#!/bin/bash" > $@ - @echo $(DBUS_RUNNER) --task gtester --parameter --verbose --parameter -k --parameter -o --parameter $(OBJECT_XML_REPORT) --parameter ./test-glib-objects >> $@ + @echo $(DBUS_RUNNER) --task gtester --task-name test --parameter --verbose --parameter -k --parameter -o --parameter $(OBJECT_XML_REPORT) --parameter ./test-glib-objects >> $@ @chmod +x $@ test_glib_objects_SOURCES = \ @@ -196,6 +319,34 @@ test_glib_simple_items_LDADD = \ ../libdbusmenu-glib/libdbusmenu-glib.la \ $(DBUSMENUGLIB_LIBS) +###################### +# Test GTK Object +###################### + +GTK_OBJECT_XML_REPORT = test-gtk-objects.xml + +test-gtk-objects-test: test-gtk-objects Makefile.am + @echo "#!/bin/bash" > $@ + @echo $(XVFB_RUN) >> $@ + @echo $(DBUS_RUNNER) --task gtester --task-name test --parameter --verbose --parameter -k --parameter -o --parameter $(GTK_OBJECT_XML_REPORT) --parameter ./test-gtk-objects >> $@ + @chmod +x $@ + +test_gtk_objects_SOURCES = \ + test-gtk-objects.c + +test_gtk_objects_CFLAGS = \ + -I $(srcdir)/.. \ + $(DBUSMENUGLIB_CFLAGS) \ + $(DBUSMENUGTK_CFLAGS) \ + -DSRCDIR="\"$(srcdir)\"" \ + -Wall -Werror + +test_gtk_objects_LDADD = \ + ../libdbusmenu-glib/libdbusmenu-glib.la \ + ../libdbusmenu-gtk/libdbusmenu-gtk.la \ + $(DBUSMENUGLIB_LIBS) \ + $(DBUSMENUGTK_LIBS) + ######################### # Test GTK Label ######################### @@ -218,6 +369,7 @@ test_gtk_label_server_CFLAGS = \ test_gtk_label_server_LDADD = \ ../libdbusmenu-glib/libdbusmenu-glib.la \ ../libdbusmenu-gtk/libdbusmenu-gtk.la \ + libdbusmenu-jsonloader.la \ $(DBUSMENUGTK_LIBS) \ $(DBUSMENUTESTS_LIBS) @@ -237,6 +389,46 @@ test_gtk_label_client_LDADD = \ $(DBUSMENUTESTS_LIBS) ######################### +# Test GTK Shortcut +######################### + +test-gtk-shortcut: test-gtk-shortcut-client test-gtk-shortcut-server Makefile.am + @echo "#!/bin/bash" > $@ + @echo $(XVFB_RUN) >> $@ + @echo $(DBUS_RUNNER) --task ./test-gtk-shortcut-client --task-name Client --task ./test-gtk-shortcut-server --task-name Server --ignore-return >> $@ + @chmod +x $@ + +test_gtk_shortcut_server_SOURCES = \ + test-gtk-shortcut-server.c + +test_gtk_shortcut_server_CFLAGS = \ + -I $(srcdir)/.. \ + $(DBUSMENUGTK_CFLAGS) \ + $(DBUSMENUTESTS_CFLAGS) \ + $(DBUSMENUGLIB_CFLAGS) -Wall -Werror + +test_gtk_shortcut_server_LDADD = \ + ../libdbusmenu-glib/libdbusmenu-glib.la \ + ../libdbusmenu-gtk/libdbusmenu-gtk.la \ + $(DBUSMENUGTK_LIBS) \ + $(DBUSMENUTESTS_LIBS) + +test_gtk_shortcut_client_SOURCES = \ + test-gtk-shortcut-client.c + +test_gtk_shortcut_client_CFLAGS = \ + -I $(srcdir)/.. \ + $(DBUSMENUGTK_CFLAGS) \ + $(DBUSMENUTESTS_CFLAGS) \ + $(DBUSMENUGLIB_CFLAGS) -Wall -Werror + +test_gtk_shortcut_client_LDADD = \ + ../libdbusmenu-glib/libdbusmenu-glib.la \ + ../libdbusmenu-gtk/libdbusmenu-gtk.la \ + $(DBUSMENUGTK_LIBS) \ + $(DBUSMENUTESTS_LIBS) + +######################### # Test GTK Reorder ######################### @@ -294,6 +486,7 @@ EXTRA_DIST = \ $(examples_DATA) \ run-xvfb.sh \ $(json_DATA) \ + test-gtk-objects.jpg \ dbusmenu-gtk/dbusMenuTest \ dbusmenu-gtk/mago_tests/dbusmenu.xml \ dbusmenu-gtk/mago_tests/dbusmenu.py \ @@ -312,9 +505,10 @@ EXTRA_DIST = \ dbusmenu-gtk/mago_tests/data/several_submenus_recursive.json \ dbusmenu-gtk/mago_tests/data/several_submenus_utf8.json \ dbusmenu-gtk/mago_tests/data/static.json \ - dbusmenu-gtk/mago_tests/data/test-gtk-label.json + dbusmenu-gtk/mago_tests/data/test-gtk-label.json \ + test-json-01.json -CLEANFILES = \ +CLEANFILES += \ dbusmenu-gtk/mago_tests/dbusmenu.pyc distclean-local: @@ -322,5 +516,6 @@ distclean-local: DISTCLEANFILES = \ $(TESTS) \ - $(OBJECT_XML_REPORT) + $(OBJECT_XML_REPORT) \ + $(GTK_OBJECT_XML_REPORT) diff --git a/tests/dbusmenu-jsonloader.pc.in b/tests/dbusmenu-jsonloader.pc.in new file mode 100644 index 0000000..d042132 --- /dev/null +++ b/tests/dbusmenu-jsonloader.pc.in @@ -0,0 +1,14 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +bindir=@bindir@ +includedir=@includedir@ + +Cflags: -I${includedir}/libdbusmenu-0.1 +Requires: dbus-glib-1,dbusmenu-glib,json-glib-1.0 +Libs: -L${libdir} -ldbusmenu-jsonloader + +Name: libdbusmenu-jsonloader +Description: A small library to load JSON descriptions of menus. Mostly for testing. +Version: @VERSION@ + diff --git a/tests/json-loader.c b/tests/json-loader.c new file mode 100644 index 0000000..aad4295 --- /dev/null +++ b/tests/json-loader.c @@ -0,0 +1,220 @@ +/* +A loader to turn JSON into dbusmenu menuitems + +Copyright 2010 Canonical Ltd. + +Authors: + Ted Gould <ted@canonical.com> + +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 <http://www.gnu.org/licenses/>. +*/ + +#include "json-loader.h" +#include <dbus/dbus-gtype-specialized.h> + +static GValue * +node2value (JsonNode * node) +{ + if (node == NULL) { + return NULL; + } + + GValue * value = g_new0(GValue, 1); + + if (JSON_NODE_TYPE(node) == JSON_NODE_VALUE) { + json_node_get_value(node, value); + return value; + } + + if (JSON_NODE_TYPE(node) == JSON_NODE_ARRAY) { + JsonArray * array = json_node_get_array(node); + JsonNode * first = json_array_get_element(array, 0); + + if (JSON_NODE_TYPE(first) == JSON_NODE_VALUE) { + GValue subvalue = {0}; + json_node_get_value(first, &subvalue); + + if (G_VALUE_TYPE(&subvalue) == G_TYPE_STRING) { + GArray * garray = g_array_sized_new(TRUE, TRUE, sizeof(gchar *), json_array_get_length(array)); + g_value_init(value, G_TYPE_STRV); + g_value_take_boxed(value, garray->data); + + int i; + for (i = 0; i < json_array_get_length(array); i++) { + const gchar * str = json_node_get_string(json_array_get_element(array, i)); + gchar * dupstr = g_strdup(str); + g_array_append_val(garray, dupstr); + } + + g_array_free(garray, FALSE); + } else { + GValueArray * varray = g_value_array_new(json_array_get_length(array)); + g_value_init(value, G_TYPE_VALUE_ARRAY); + g_value_take_boxed(value, varray); + + g_value_array_append(varray, &subvalue); + g_value_unset(&subvalue); + + int i; + for (i = 1; i < json_array_get_length(array); i++) { + json_node_get_value(first, &subvalue); + g_value_array_append(varray, &subvalue); + g_value_unset(&subvalue); + } + } + + } else { + GValue * subvalue = node2value(first); + GType type = dbus_g_type_get_collection("GPtrArray", G_VALUE_TYPE(subvalue)); + gpointer * wrapper = dbus_g_type_specialized_construct(type); + + g_value_init(value, type); + g_value_take_boxed(value, wrapper); + + DBusGTypeSpecializedAppendContext ctx; + dbus_g_type_specialized_init_append(value, &ctx); + + dbus_g_type_specialized_collection_append(&ctx, subvalue); + int i; + for (i = 1; i < json_array_get_length(array); i++) { + GValue * subvalue = node2value(node); + dbus_g_type_specialized_collection_append(&ctx, subvalue); + } + + dbus_g_type_specialized_collection_end_append(&ctx); + } + } + + if (JSON_NODE_TYPE(node) == JSON_NODE_OBJECT) { + JsonObject * obj = json_node_get_object(node); + + GType type = dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE); + GHashTable * hash = (GHashTable *)dbus_g_type_specialized_construct(type); + + g_value_init(value, type); + g_value_take_boxed(value, hash); + + DBusGTypeSpecializedAppendContext ctx; + dbus_g_type_specialized_init_append(value, &ctx); + + GList * members = NULL; + for (members = json_object_get_members(obj); members != NULL; members = g_list_next(members)) { + const gchar * member = members->data; + + JsonNode * lnode = json_object_get_member(obj, member); + GValue * value = node2value(lnode); + + if (value != NULL) { + GValue name = {0}; + g_value_init(&name, G_TYPE_STRING); + g_value_set_static_string(&name, member); + + dbus_g_type_specialized_map_append(&ctx, &name, value); + + g_value_unset(&name); + g_value_unset(value); + g_free(value); + } + } + } + + return value; +} + +static void +set_props (DbusmenuMenuitem * mi, JsonObject * node) +{ + if (node == NULL) return; + + GList * members = NULL; + for (members = json_object_get_members(node); members != NULL; members = g_list_next(members)) { + const gchar * member = members->data; + + if (!g_strcmp0(member, "id")) { continue; } + if (!g_strcmp0(member, "submenu")) { continue; } + + JsonNode * lnode = json_object_get_member(node, member); + GValue * value = node2value(lnode); + + if (value != NULL) { + dbusmenu_menuitem_property_set_value(mi, member, value); + g_value_unset(value); + g_free(value); + } + } + + return; +} + +DbusmenuMenuitem * +dbusmenu_json_build_from_node (const JsonNode * cnode) +{ + JsonNode * node = (JsonNode *)cnode; /* To match the jsonglib API :( */ + + if (node == NULL) return NULL; + if (JSON_NODE_TYPE(node) != JSON_NODE_OBJECT) return NULL; + + JsonObject * layout = json_node_get_object(node); + + DbusmenuMenuitem * local = NULL; + if (json_object_has_member(layout, "id")) { + JsonNode * node = json_object_get_member(layout, "id"); + g_return_val_if_fail(JSON_NODE_TYPE(node) == JSON_NODE_VALUE, NULL); + local = dbusmenu_menuitem_new_with_id(json_node_get_int(node)); + } else { + local = dbusmenu_menuitem_new(); + } + + set_props(local, layout); + + if (json_object_has_member(layout, "submenu")) { + JsonNode * node = json_object_get_member(layout, "submenu"); + g_return_val_if_fail(JSON_NODE_TYPE(node) == JSON_NODE_ARRAY, local); + JsonArray * array = json_node_get_array(node); + guint count; + for (count = 0; count < json_array_get_length(array); count++) { + DbusmenuMenuitem * child = dbusmenu_json_build_from_node(json_array_get_element(array, count)); + if (child != NULL) { + dbusmenu_menuitem_child_append(local, child); + } + } + } + + /* g_debug("Layout to menu return: 0x%X", (unsigned int)local); */ + return local; +} + +DbusmenuMenuitem * +dbusmenu_json_build_from_file (const gchar * filename) +{ + JsonParser * parser = json_parser_new(); + + GError * error = NULL; + if (!json_parser_load_from_file(parser, filename, &error)) { + g_warning("Failed parsing file %s because: %s", filename, error->message); + g_error_free(error); + return NULL; + } + + JsonNode * root_node = json_parser_get_root(parser); + if (JSON_NODE_TYPE(root_node) != JSON_NODE_OBJECT) { + g_warning("Root node is not an object, fail. It's an: %s", json_node_type_name(root_node)); + return NULL; + } + + DbusmenuMenuitem * mi = dbusmenu_json_build_from_node(root_node); + + g_object_unref(parser); + + return mi; +} diff --git a/tests/json-loader.h b/tests/json-loader.h new file mode 100644 index 0000000..666bb6e --- /dev/null +++ b/tests/json-loader.h @@ -0,0 +1,31 @@ +/* +A loader to turn JSON into dbusmenu menuitems + +Copyright 2010 Canonical Ltd. + +Authors: + Ted Gould <ted@canonical.com> + +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 <http://www.gnu.org/licenses/>. +*/ + +#ifndef __DBUSMENU_JSON_LOADER_H__ +#define __DBUSMENU_JSON_LOADER_H__ + +#include <libdbusmenu-glib/menuitem.h> +#include <json-glib/json-glib.h> + +DbusmenuMenuitem * dbusmenu_json_build_from_node (const JsonNode * node); +DbusmenuMenuitem * dbusmenu_json_build_from_file (const gchar * filename); + +#endif /* __DBUSMENU_JSON_LOADER_H__ */ diff --git a/tests/run-xvfb.sh b/tests/run-xvfb.sh index 3622dbf..3aa05c1 100644 --- a/tests/run-xvfb.sh +++ b/tests/run-xvfb.sh @@ -1,4 +1,4 @@ -if [ "$DISPLAY" == "" ]; then +if [ "x$DISPLAY" == "x" ]; then Xvfb -ac -noreset -screen 0 800x600x16 -help 2>/dev/null 1>&2 XID=`for id in 101 102 103 104 105 106 107 197 199 211 223 227 293 307 308 309 310 311 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 4703 4721 4723 4729 4733 4751 9973 9974 9975 9976 9977 9978 9979 9980 9981 9982 9983 9984 9985 9986 9987 9988 9989 9990 9991 9992 9993 9994 9995 9996 9997 9998 9999 ; do test -e /tmp/.X$id-lock || { echo $id; exit 0; }; done; exit 1` { Xvfb -ac -noreset -screen 0 800x600x16 :$XID -screen 0 800x600x16 -nolisten tcp -auth /dev/null >/dev/null 2>&1 & trap "kill -15 $! " 0 HUP INT QUIT TRAP USR1 PIPE TERM ; } || { echo "Gtk+Tests:ERROR: Failed to start Xvfb environment for X11 target tests."; exit 1; } diff --git a/tests/test-glib-submenu-client.c b/tests/test-glib-submenu-client.c new file mode 100644 index 0000000..57762cd --- /dev/null +++ b/tests/test-glib-submenu-client.c @@ -0,0 +1,119 @@ +/* +A test for libdbusmenu to ensure its quality. + +Copyright 2009 Canonical Ltd. + +Authors: + Ted Gould <ted@canonical.com> + +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 <http://www.gnu.org/licenses/>. +*/ + +#include <glib.h> + +#include <libdbusmenu-glib/client.h> +#include <libdbusmenu-glib/menuitem.h> + +#include "test-glib-submenu.h" + +static guint layouton = 0; +static GMainLoop * mainloop = NULL; +static gboolean passed = TRUE; + +static void +realization (DbusmenuMenuitem * mi) +{ + const gchar * value; + gboolean original = passed; + + value = dbusmenu_menuitem_property_get(mi, DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY); + + if (layouton % 2 == 0) { + if (value == NULL) { + passed = FALSE; + } + } else { + if (value != NULL) { + passed = FALSE; + } + } + + if (original != passed) { + g_debug("Oops, this is where we failed"); + } + + return; +} + +static void +layout_updated (DbusmenuClient * client, gpointer data) +{ + g_debug("Layout Updated"); + + DbusmenuMenuitem * menuroot = dbusmenu_client_get_root(client); + if (menuroot == NULL) { + g_debug("Root is NULL?"); + return; + } + + GList * children = dbusmenu_menuitem_get_children(menuroot); + if (children == NULL) { + g_debug("No Children on root -- fail"); + passed = FALSE; + } else { + for (; children != NULL; children = g_list_next(children)) { + g_signal_connect(G_OBJECT(children->data), DBUSMENU_MENUITEM_SIGNAL_REALIZED, G_CALLBACK(realization), NULL); + } + } + + layouton++; + + if (layouts[layouton].id == -1) { + g_main_loop_quit(mainloop); + } + + return; +} + +static gboolean +timer_func (gpointer data) +{ + g_debug("Death timer. Oops. Got to: %d", layouton); + passed = FALSE; + g_main_loop_quit(mainloop); + return FALSE; +} + +int +main (int argc, char ** argv) +{ + g_type_init(); + + DbusmenuClient * client = dbusmenu_client_new("org.dbusmenu.test", "/org/test"); + g_signal_connect(G_OBJECT(client), DBUSMENU_CLIENT_SIGNAL_LAYOUT_UPDATED, G_CALLBACK(layout_updated), NULL); + + g_timeout_add_seconds(10, timer_func, client); + + mainloop = g_main_loop_new(NULL, FALSE); + g_main_loop_run(mainloop); + + g_object_unref(G_OBJECT(client)); + + if (passed) { + g_debug("Quiting"); + return 0; + } else { + g_debug("Quiting as we're a failure"); + return 1; + } +} diff --git a/tests/test-glib-submenu-server.c b/tests/test-glib-submenu-server.c new file mode 100644 index 0000000..68f7004 --- /dev/null +++ b/tests/test-glib-submenu-server.c @@ -0,0 +1,109 @@ +/* +A test for libdbusmenu to ensure its quality. + +Copyright 2009 Canonical Ltd. + +Authors: + Ted Gould <ted@canonical.com> + +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 <http://www.gnu.org/licenses/>. +*/ + +#include <glib.h> + +#include <dbus/dbus.h> +#include <dbus/dbus-glib.h> +#include <dbus/dbus-glib-lowlevel.h> +#include <dbus/dbus-glib-bindings.h> + +#include <libdbusmenu-glib/server.h> +#include <libdbusmenu-glib/menuitem.h> + +#include "test-glib-submenu.h" + + +static DbusmenuMenuitem * +layout2menuitem (layout_t * layout) +{ + if (layout == NULL || layout->id == 0) return NULL; + + DbusmenuMenuitem * local = dbusmenu_menuitem_new_with_id(layout->id); + + if (layout->submenu != NULL) { + guint count; + for (count = 0; layout->submenu[count].id != -1; count++) { + DbusmenuMenuitem * child = layout2menuitem(&layout->submenu[count]); + if (child != NULL) { + dbusmenu_menuitem_child_append(local, child); + } + } + } + + /* g_debug("Layout to menu return: 0x%X", (unsigned int)local); */ + return local; +} + +static guint layouton = 0; +static DbusmenuServer * server = NULL; +static GMainLoop * mainloop = NULL; + +static gboolean +timer_func (gpointer data) +{ + if (layouts[layouton].id == -1) { + g_main_loop_quit(mainloop); + return FALSE; + } + g_debug("Updating to Layout %d", layouton); + + dbusmenu_server_set_root(server, layout2menuitem(&layouts[layouton])); + layouton++; + + return TRUE; +} + +int +main (int argc, char ** argv) +{ + GError * error = NULL; + + g_type_init(); + + DBusGConnection * connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); + g_debug("DBus ID: %s", dbus_connection_get_server_id(dbus_g_connection_get_connection(dbus_g_bus_get(DBUS_BUS_SESSION, NULL)))); + + DBusGProxy * bus_proxy = dbus_g_proxy_new_for_name(connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); + guint nameret = 0; + + if (!org_freedesktop_DBus_request_name(bus_proxy, "org.dbusmenu.test", 0, &nameret, &error)) { + g_error("Unable to call to request name"); + return 1; + } + + if (nameret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { + g_error("Unable to get name"); + return 1; + } + + server = dbusmenu_server_new("/org/test"); + + timer_func(NULL); + g_timeout_add(2500, timer_func, NULL); + + mainloop = g_main_loop_new(NULL, FALSE); + g_main_loop_run(mainloop); + + g_debug("Quiting"); + + return 0; +} diff --git a/tests/test-glib-submenu.h b/tests/test-glib-submenu.h new file mode 100644 index 0000000..f585d1b --- /dev/null +++ b/tests/test-glib-submenu.h @@ -0,0 +1,54 @@ +/* +A test for libdbusmenu to ensure its quality. + +Copyright 2009 Canonical Ltd. + +Authors: + Ted Gould <ted@canonical.com> + +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 <http://www.gnu.org/licenses/>. +*/ + +typedef struct _layout_t layout_t; +struct _layout_t { + gint id; + layout_t * submenu; +}; + +layout_t submenu_l2[] = { + {id: 6, submenu: NULL}, + {id: 7, submenu: NULL}, + {id: 8, submenu: NULL}, + {id: -1, submenu: NULL} +}; + +layout_t submenu[] = { + {id: 2, submenu: submenu_l2}, + {id: 3, submenu: submenu_l2}, + {id: -1, submenu: NULL} +}; + +layout_t no_submenu[] = { + {id: 4, submenu: NULL}, + {id: 5, submenu: NULL}, + {id: -1, submenu: NULL} +}; + +layout_t layouts[] = { + {id: 1, submenu: no_submenu}, + {id: 1, submenu: submenu}, + {id: 1, submenu: no_submenu}, + {id: 1, submenu: submenu}, + {id: -1, submenu: NULL} +}; + diff --git a/tests/test-gtk-label-server.c b/tests/test-gtk-label-server.c index 32d7a43..32572fc 100644 --- a/tests/test-gtk-label-server.c +++ b/tests/test-gtk-label-server.c @@ -30,74 +30,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include <libdbusmenu-glib/server.h> #include <json-glib/json-glib.h> - -static void -menuitem_click(DbusmenuMenuitem * mi, guint32 time, gpointer user_data) -{ - g_debug("Clicked on: %d @ %d", dbusmenu_menuitem_get_id(mi), time); - return; -} - -static void -set_props (DbusmenuMenuitem * mi, JsonObject * node) -{ - if (node == NULL) return; - - GList * members = NULL; - for (members = json_object_get_members(node); members != NULL; members = g_list_next(members)) { - const gchar * member = members->data; - - if (!g_strcmp0(member, "id")) { continue; } - if (!g_strcmp0(member, "submenu")) { continue; } - - JsonNode * lnode = json_object_get_member(node, member); - if (JSON_NODE_TYPE(lnode) != JSON_NODE_VALUE) { continue; } - - GValue value = {0}; - json_node_get_value(lnode, &value); - dbusmenu_menuitem_property_set_value(mi, member, &value); - g_value_unset(&value); - } - - return; -} - -static DbusmenuMenuitem * -layout2menuitem (JsonNode * inlayout) -{ - if (inlayout == NULL) return NULL; - if (JSON_NODE_TYPE(inlayout) != JSON_NODE_OBJECT) return NULL; - - JsonObject * layout = json_node_get_object(inlayout); - - DbusmenuMenuitem * local = NULL; - if (json_object_has_member(layout, "id")) { - JsonNode * node = json_object_get_member(layout, "id"); - g_return_val_if_fail(JSON_NODE_TYPE(node) == JSON_NODE_VALUE, NULL); - local = dbusmenu_menuitem_new_with_id(json_node_get_int(node)); - } else { - local = dbusmenu_menuitem_new(); - } - g_signal_connect(G_OBJECT(local), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(menuitem_click), NULL); - - set_props(local, layout); - - if (json_object_has_member(layout, "submenu")) { - JsonNode * node = json_object_get_member(layout, "submenu"); - g_return_val_if_fail(JSON_NODE_TYPE(node) == JSON_NODE_ARRAY, local); - JsonArray * array = json_node_get_array(node); - guint count; - for (count = 0; count < json_array_get_length(array); count++) { - DbusmenuMenuitem * child = layout2menuitem(json_array_get_element(array, count)); - if (child != NULL) { - dbusmenu_menuitem_child_append(local, child); - } - } - } - - /* g_debug("Layout to menu return: 0x%X", (unsigned int)local); */ - return local; -} +#include "json-loader.h" static JsonArray * root_array = NULL; static guint layouton = 0; @@ -114,7 +47,7 @@ timer_func (gpointer data) } g_debug("Updating to Layout %d", layouton); - dbusmenu_server_set_root(server, layout2menuitem(json_array_get_element(root_array, layouton))); + dbusmenu_server_set_root(server, dbusmenu_json_build_from_node(json_array_get_element(root_array, layouton))); layouton++; return TRUE; diff --git a/tests/test-gtk-objects.c b/tests/test-gtk-objects.c new file mode 100644 index 0000000..726f404 --- /dev/null +++ b/tests/test-gtk-objects.c @@ -0,0 +1,145 @@ +/* +Testing for the various objects just by themselves. + +Copyright 2010 Canonical Ltd. + +Authors: + Ted Gould <ted@canonical.com> + +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 <http://www.gnu.org/licenses/>. +*/ + +#include <libdbusmenu-glib/menuitem.h> +#include <libdbusmenu-gtk/menuitem.h> +#include <gdk/gdkkeysyms.h> + +#define TEST_IMAGE SRCDIR "/" "test-gtk-objects.jpg" + +/* Building the basic menu item, make sure we didn't break + any core GObject stuff */ +static void +test_object_menuitem (void) +{ + /* Build a menu item */ + DbusmenuMenuitem * item = dbusmenu_menuitem_new(); + + /* Test to make sure it's a happy object */ + g_assert(item != NULL); + g_assert(G_IS_OBJECT(item)); + g_assert(DBUSMENU_IS_MENUITEM(item)); + + /* Set up a check to make sure it gets destroyed on unref */ + g_object_add_weak_pointer(G_OBJECT(item), (gpointer *)&item); + g_object_unref(item); + + /* Did it go away? */ + g_assert(item == NULL); + + return; +} + +/* Setting and getting a pixbuf */ +static void +test_object_prop_pixbuf (void) +{ + const gchar * prop_name = "image-test"; + + /* Build a menu item */ + DbusmenuMenuitem * item = dbusmenu_menuitem_new(); + + /* Test to make sure it's a happy object */ + g_assert(item != NULL); + g_assert(G_IS_OBJECT(item)); + g_assert(DBUSMENU_IS_MENUITEM(item)); + + /* Load our image */ + GdkPixbuf * pixbuf = gdk_pixbuf_new_from_file(TEST_IMAGE, NULL); + g_assert(pixbuf != NULL); + + /* Set the property */ + gboolean success = dbusmenu_menuitem_property_set_image(item, prop_name, pixbuf); + g_assert(success); + g_object_unref(pixbuf); + + /* Check to see if it's set */ + const GValue * val = dbusmenu_menuitem_property_get_value(item, prop_name); + g_assert(val != NULL); + + /* Get the pixbuf back! */ + GdkPixbuf * newpixbuf = dbusmenu_menuitem_property_get_image(item, prop_name); + g_assert(newpixbuf != NULL); + g_object_unref(newpixbuf); + + g_object_unref(item); + + return; +} + +/* Setting and getting a shortcut */ +static void +test_object_prop_shortcut (void) +{ + /* Build a menu item */ + DbusmenuMenuitem * item = dbusmenu_menuitem_new(); + + /* Test to make sure it's a happy object */ + g_assert(item != NULL); + g_assert(G_IS_OBJECT(item)); + g_assert(DBUSMENU_IS_MENUITEM(item)); + + guint key = GDK_c; + GdkModifierType modifier = GDK_CONTROL_MASK; + + /* Set a shortcut */ + gboolean success = dbusmenu_menuitem_property_set_shortcut(item, key, modifier); + g_assert(success); + + /* Check for value */ + const GValue * val = dbusmenu_menuitem_property_get_value(item, DBUSMENU_MENUITEM_PROP_SHORTCUT); + g_assert(val != NULL); + + /* Check to see if we love it */ + guint newkey = 0; + GdkModifierType newmodifier = 0; + dbusmenu_menuitem_property_get_shortcut(item, &newkey, &newmodifier); + + g_assert(key == newkey); + g_assert(newmodifier == modifier); + + g_object_unref(item); + + return; +} + +/* Build the test suite */ +static void +test_gtk_objects_suite (void) +{ + g_test_add_func ("/dbusmenu/gtk/objects/menuitem/base", test_object_menuitem); + g_test_add_func ("/dbusmenu/gtk/objects/menuitem/prop_pixbuf", test_object_prop_pixbuf); + g_test_add_func ("/dbusmenu/gtk/objects/menuitem/prop_shortcut", test_object_prop_shortcut); + return; +} + +gint +main (gint argc, gchar * argv[]) +{ + gtk_init(&argc, &argv); + + g_test_init(&argc, &argv, NULL); + + /* Test suites */ + test_gtk_objects_suite(); + + return g_test_run (); +} diff --git a/tests/test-gtk-objects.jpg b/tests/test-gtk-objects.jpg Binary files differnew file mode 100644 index 0000000..478704e --- /dev/null +++ b/tests/test-gtk-objects.jpg diff --git a/tests/test-gtk-shortcut-client.c b/tests/test-gtk-shortcut-client.c new file mode 100644 index 0000000..003885c --- /dev/null +++ b/tests/test-gtk-shortcut-client.c @@ -0,0 +1,76 @@ +/* +A test for libdbusmenu to ensure its quality. + +Copyright 2009 Canonical Ltd. + +Authors: + Ted Gould <ted@canonical.com> + +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 <http://www.gnu.org/licenses/>. +*/ + +#include <gtk/gtk.h> +#include <libdbusmenu-gtk/menu.h> +#include <libdbusmenu-gtk/client.h> + +static GMainLoop * mainloop = NULL; +static gboolean passed = TRUE; +static guint death_timer = 0; + +static gboolean +timer_func (gpointer data) +{ + passed = TRUE; + g_main_loop_quit(mainloop); + return FALSE; +} + +int +main (int argc, char ** argv) +{ + gtk_init(&argc, &argv); + + g_debug("Building Window"); + GtkWidget * window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + GtkWidget * menubar = gtk_menu_bar_new(); + GtkWidget * menuitem = gtk_menu_item_new_with_label("Test"); + + DbusmenuGtkMenu * dmenu = dbusmenu_gtkmenu_new ("glib.label.test", "/org/test"); + DbusmenuGtkClient * dclient = dbusmenu_gtkmenu_get_client(dmenu); + + GtkAccelGroup * agroup = gtk_accel_group_new(); + dbusmenu_gtkclient_set_accel_group(dclient, agroup); + + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), GTK_WIDGET(dmenu)); + gtk_widget_show(menuitem); + gtk_menu_bar_append(menubar, menuitem); + gtk_widget_show(menubar); + gtk_container_add(GTK_CONTAINER(window), menubar); + gtk_window_set_title(GTK_WINDOW(window), "libdbusmenu-gtk test"); + gtk_window_add_accel_group(GTK_WINDOW(window), agroup); + gtk_widget_show(window); + + death_timer = g_timeout_add_seconds(10, timer_func, window); + + g_debug("Entering Mainloop"); + mainloop = g_main_loop_new(NULL, FALSE); + g_main_loop_run(mainloop); + + if (passed) { + g_debug("Quiting"); + return 0; + } else { + g_debug("Quiting as we're a failure"); + return 1; + } +} diff --git a/tests/test-gtk-shortcut-server.c b/tests/test-gtk-shortcut-server.c new file mode 100644 index 0000000..3b703a1 --- /dev/null +++ b/tests/test-gtk-shortcut-server.c @@ -0,0 +1,99 @@ +/* +A test for libdbusmenu to ensure its quality. + +Copyright 2009 Canonical Ltd. + +Authors: + Ted Gould <ted@canonical.com> + +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 <http://www.gnu.org/licenses/>. +*/ + +#include <glib.h> +#include <gdk/gdkkeysyms.h> + +#include <dbus/dbus.h> +#include <dbus/dbus-glib.h> +#include <dbus/dbus-glib-lowlevel.h> +#include <dbus/dbus-glib-bindings.h> + +#include <libdbusmenu-glib/menuitem.h> +#include <libdbusmenu-glib/server.h> +#include <libdbusmenu-gtk/menuitem.h> + +GMainLoop * mainloop = NULL; +DbusmenuServer * server = NULL; + +gboolean +timer_func (gpointer userdata) +{ + g_main_loop_quit(mainloop); + return FALSE; +} + +void +build_menu (void) +{ + DbusmenuMenuitem * item; + + DbusmenuMenuitem * root = dbusmenu_menuitem_new(); + + item = dbusmenu_menuitem_new(); + dbusmenu_menuitem_property_set(item, DBUSMENU_MENUITEM_PROP_LABEL, "Control-L"); + dbusmenu_menuitem_property_set_shortcut(item, GDK_l, GDK_CONTROL_MASK); + dbusmenu_menuitem_child_append(root, item); + g_object_unref(item); + + + dbusmenu_server_set_root(server, root); + g_object_unref(root); + + return; +} + +int +main (int argc, char ** argv) +{ + GError * error = NULL; + + g_type_init(); + + DBusGConnection * connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); + g_debug("DBus ID: %s", dbus_connection_get_server_id(dbus_g_connection_get_connection(dbus_g_bus_get(DBUS_BUS_SESSION, NULL)))); + + DBusGProxy * bus_proxy = dbus_g_proxy_new_for_name(connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); + guint nameret = 0; + + if (!org_freedesktop_DBus_request_name(bus_proxy, "glib.label.test", 0, &nameret, &error)) { + g_error("Unable to call to request name"); + return 1; + } + + if (nameret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { + g_error("Unable to get name"); + return 1; + } + + server = dbusmenu_server_new("/org/test"); + build_menu(); + + g_timeout_add_seconds(10, timer_func, NULL); + + mainloop = g_main_loop_new(NULL, FALSE); + g_main_loop_run(mainloop); + + g_debug("Quiting"); + + return 0; +} + diff --git a/tests/test-json-01.json b/tests/test-json-01.json new file mode 100644 index 0000000..88e1cbf --- /dev/null +++ b/tests/test-json-01.json @@ -0,0 +1,4023 @@ +{ + "id": 0, + "children-display": "submenu", + "submenu": [ + { + "id": 5, + "enabled": true, + "label": "File", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 6, + "shortcut": [["Control", "q"]], + "enabled": true, + "label": "Quit", + "visible": true + }, + { + "id": 7, + "shortcut": [["Control", "Shift", "w"]], + "enabled": true, + "label": "Close all", + "visible": true + }, + { + "id": 8, + "shortcut": [["Control", "w"]], + "enabled": true, + "label": "Close", + "visible": true + }, + { + "id": 9, + "type": "separator" + }, + { + "id": 10, + "enabled": true, + "label": "Send by Email...", + "visible": true + }, + { + "id": 11, + "shortcut": [["Control", "p"]], + "enabled": true, + "label": "Print...", + "visible": true + }, + { + "id": 12, + "enabled": true, + "label": "Page Setup", + "visible": true + }, + { + "id": 13, + "type": "separator" + }, + { + "id": 14, + "enabled": true, + "label": "Revert", + "visible": true + }, + { + "id": 15, + "enabled": true, + "label": "Save as Template...", + "visible": true + }, + { + "id": 16, + "enabled": true, + "label": "Save a Copy...", + "visible": true + }, + { + "id": 17, + "shortcut": [["Control", "Shift", "s"]], + "enabled": true, + "label": "Save As...", + "visible": true + }, + { + "id": 18, + "shortcut": [["Control", "s"]], + "enabled": true, + "label": "Save", + "visible": true + }, + { + "id": 19, + "type": "separator" + }, + { + "id": 20, + "enabled": true, + "label": "Open Recent", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 21, + "enabled": true, + "label": "Document History", + "visible": true + }, + { + "id": 22, + "type": "separator" + }, + { + "id": 23, + "shortcut": [["Control", "2"]], + "enabled": true, + "label": "giggity.jpg", + "visible": true + }, + { + "id": 24, + "shortcut": [["Control", "1"]], + "enabled": true, + "label": "Icon Height.svg", + "visible": true + } + ] + }, + { + "id": 25, + "enabled": true, + "label": "Open Location...", + "visible": true + }, + { + "id": 26, + "shortcut": [["Control", "Alt", "o"]], + "enabled": true, + "label": "Open as Layers...", + "visible": true + }, + { + "id": 27, + "shortcut": [["Control", "o"]], + "enabled": true, + "label": "Open...", + "visible": true + }, + { + "id": 28, + "enabled": true, + "label": "Create", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 29, + "enabled": true, + "label": "Web Page Themes", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 30, + "enabled": true, + "label": "Classic.Gimp.Org", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 31, + "enabled": true, + "label": "Tube Sub-Sub-Button Label...", + "visible": true + }, + { + "id": 32, + "enabled": true, + "label": "Tube Sub-Button Label...", + "visible": true + }, + { + "id": 33, + "enabled": true, + "label": "Tube Button Label...", + "visible": true + }, + { + "id": 34, + "enabled": true, + "label": "Small Header...", + "visible": true + }, + { + "id": 35, + "enabled": true, + "label": "General Tube Labels...", + "visible": true + }, + { + "id": 36, + "enabled": true, + "label": "Big Header...", + "visible": true + } + ] + }, + { + "id": 37, + "enabled": true, + "label": "Beveled Pattern", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 38, + "enabled": true, + "label": "Hrule...", + "visible": true + }, + { + "id": 39, + "enabled": true, + "label": "Heading...", + "visible": true + }, + { + "id": 40, + "enabled": true, + "label": "Button...", + "visible": true + }, + { + "id": 41, + "enabled": true, + "label": "Bullet...", + "visible": true + }, + { + "id": 42, + "enabled": true, + "label": "Arrow...", + "visible": true + } + ] + }, + { + "id": 43, + "enabled": true, + "label": "Alien Glow", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 44, + "enabled": true, + "label": "Hrule...", + "visible": true + }, + { + "id": 45, + "enabled": true, + "label": "Button...", + "visible": true + }, + { + "id": 46, + "enabled": true, + "label": "Bullet...", + "visible": true + }, + { + "id": 47, + "enabled": true, + "label": "Arrow...", + "visible": true + } + ] + } + ] + }, + { + "id": 48, + "enabled": true, + "label": "Patterns", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 49, + "enabled": true, + "label": "Truchet...", + "visible": true + }, + { + "id": 50, + "enabled": true, + "label": "Swirly...", + "visible": true + }, + { + "id": 51, + "enabled": true, + "label": "Swirl-Tile...", + "visible": true + }, + { + "id": 52, + "enabled": true, + "label": "Render Map...", + "visible": true + }, + { + "id": 53, + "enabled": true, + "label": "Land...", + "visible": true + }, + { + "id": 54, + "enabled": true, + "label": "Flatland...", + "visible": true + }, + { + "id": 55, + "enabled": true, + "label": "Camouflage...", + "visible": true + }, + { + "id": 56, + "enabled": true, + "label": "3D Truchet...", + "visible": true + } + ] + }, + { + "id": 57, + "enabled": true, + "label": "Logos", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 58, + "enabled": true, + "label": "Web Title Header...", + "visible": true + }, + { + "id": 59, + "enabled": true, + "label": "Textured...", + "visible": true + }, + { + "id": 60, + "enabled": true, + "label": "Text Circle...", + "visible": true + }, + { + "id": 61, + "enabled": true, + "label": "Starscape...", + "visible": true + }, + { + "id": 62, + "enabled": true, + "label": "Speed Text...", + "visible": true + }, + { + "id": 63, + "enabled": true, + "label": "SOTA Chrome...", + "visible": true + }, + { + "id": 64, + "enabled": true, + "label": "Particle Trace...", + "visible": true + }, + { + "id": 65, + "enabled": true, + "label": "Newsprint Text...", + "visible": true + }, + { + "id": 66, + "enabled": true, + "label": "Neon...", + "visible": true + }, + { + "id": 67, + "enabled": true, + "label": "Imigre-26...", + "visible": true + }, + { + "id": 68, + "enabled": true, + "label": "Gradient Bevel...", + "visible": true + }, + { + "id": 69, + "enabled": true, + "label": "Glowing Hot...", + "visible": true + }, + { + "id": 70, + "enabled": true, + "label": "Glossy...", + "visible": true + }, + { + "id": 71, + "enabled": true, + "label": "Frosty...", + "visible": true + }, + { + "id": 72, + "enabled": true, + "label": "Crystal...", + "visible": true + }, + { + "id": 73, + "enabled": true, + "label": "Cool Metal...", + "visible": true + }, + { + "id": 74, + "enabled": true, + "label": "Comic Book...", + "visible": true + }, + { + "id": 75, + "enabled": true, + "label": "Chrome...", + "visible": true + }, + { + "id": 76, + "enabled": true, + "label": "Chip Away...", + "visible": true + }, + { + "id": 77, + "enabled": true, + "label": "Chalk...", + "visible": true + }, + { + "id": 78, + "enabled": true, + "label": "Carved...", + "visible": true + }, + { + "id": 79, + "enabled": true, + "label": "Bovination...", + "visible": true + }, + { + "id": 80, + "enabled": true, + "label": "Blended...", + "visible": true + }, + { + "id": 81, + "enabled": true, + "label": "Basic I...", + "visible": true + }, + { + "id": 82, + "enabled": true, + "label": "Basic II...", + "visible": true + }, + { + "id": 83, + "enabled": true, + "label": "Alien Neon...", + "visible": true + }, + { + "id": 84, + "enabled": true, + "label": "Alien Glow...", + "visible": true + }, + { + "id": 85, + "enabled": true, + "label": "3D Outline...", + "visible": true + } + ] + }, + { + "id": 86, + "enabled": true, + "label": "Buttons", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 87, + "enabled": true, + "label": "Simple Beveled Button...", + "visible": true + }, + { + "id": 88, + "enabled": true, + "label": "Round Button...", + "visible": true + } + ] + }, + { + "id": 89, + "type": "separator" + }, + { + "id": 90, + "enabled": true, + "label": "xscanimage", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 91, + "enabled": false, + "label": "Device dialog...", + "visible": true + } + ] + }, + { + "id": 92, + "enabled": true, + "label": "Screenshot...", + "visible": true + }, + { + "id": 93, + "shortcut": [["Control", "Shift", "v"]], + "enabled": true, + "label": "From Clipboard", + "visible": true + } + ] + }, + { + "id": 94, + "shortcut": [["Control", "n"]], + "enabled": true, + "label": "New...", + "visible": true + } + ] + }, + { + "id": 95, + "enabled": true, + "label": "Edit", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 96, + "enabled": true, + "label": "Units", + "visible": true + }, + { + "id": 97, + "enabled": true, + "label": "Modules", + "visible": true + }, + { + "id": 98, + "enabled": true, + "label": "Keyboard Shortcuts", + "visible": true + }, + { + "id": 99, + "enabled": true, + "label": "Preferences", + "visible": true + }, + { + "id": 100, + "type": "separator" + }, + { + "id": 101, + "enabled": false, + "label": "Stroke Path...", + "visible": true + }, + { + "id": 102, + "enabled": false, + "label": "Stroke Selection...", + "visible": true + }, + { + "id": 103, + "shortcut": [["Control", "semicolon"]], + "enabled": true, + "label": "Fill with Pattern", + "visible": true + }, + { + "id": 104, + "shortcut": [["Control", "period"]], + "enabled": true, + "label": "Fill with BG Color", + "visible": true + }, + { + "id": 105, + "shortcut": [["Control", "comma"]], + "enabled": true, + "label": "Fill with FG Color", + "visible": true + }, + { + "id": 106, + "shortcut": [["Delete"]], + "enabled": true, + "label": "Clear", + "visible": true + }, + { + "id": 107, + "type": "separator" + }, + { + "id": 108, + "enabled": true, + "label": "Buffer", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 109, + "enabled": true, + "label": "Paste Named...", + "visible": true + }, + { + "id": 110, + "enabled": true, + "label": "Copy Visible Named...", + "visible": true + }, + { + "id": 111, + "enabled": true, + "label": "Copy Named...", + "visible": true + }, + { + "id": 112, + "enabled": true, + "label": "Cut Named...", + "visible": true + } + ] + }, + { + "id": 113, + "enabled": true, + "label": "Paste as", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 114, + "enabled": true, + "label": "New Pattern...", + "visible": true + }, + { + "id": 115, + "enabled": true, + "label": "New Brush...", + "visible": true + }, + { + "id": 116, + "enabled": true, + "label": "New Layer", + "visible": true + }, + { + "id": 117, + "shortcut": [["Control", "Shift", "v"]], + "enabled": true, + "label": "New Image", + "visible": true + } + ] + }, + { + "id": 118, + "enabled": true, + "label": "Paste Into", + "visible": true + }, + { + "id": 119, + "shortcut": [["Control", "v"]], + "enabled": true, + "label": "Paste", + "visible": true + }, + { + "id": 120, + "shortcut": [["Control", "Shift", "c"]], + "enabled": true, + "label": "Copy Visible", + "visible": true + }, + { + "id": 121, + "shortcut": [["Control", "c"]], + "enabled": true, + "label": "Copy", + "visible": true + }, + { + "id": 122, + "shortcut": [["Control", "x"]], + "enabled": true, + "label": "Cut", + "visible": true + }, + { + "id": 123, + "type": "separator" + }, + { + "id": 124, + "enabled": true, + "label": "Undo History", + "visible": true + }, + { + "id": 3, + "enabled": false, + "label": "_Fade...", + "visible": true + }, + { + "id": 2, + "shortcut": [["Control", "y"]], + "enabled": false, + "label": "_Redo", + "visible": true + }, + { + "id": 1, + "shortcut": [["Control", "z"]], + "enabled": false, + "label": "_Undo", + "visible": true + } + ] + }, + { + "id": 125, + "enabled": true, + "label": "Select", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 126, + "enabled": false, + "label": "To Path", + "visible": true + }, + { + "id": 127, + "enabled": true, + "label": "Save to Channel", + "visible": true + }, + { + "id": 128, + "shortcut": [["Shift", "q"]], + "enabled": true, + "toggle-state": 0, + "label": "Toggle Quick Mask", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 129, + "type": "separator" + }, + { + "id": 130, + "enabled": true, + "label": "Distort...", + "visible": true + }, + { + "id": 131, + "enabled": false, + "label": "Border...", + "visible": true + }, + { + "id": 132, + "enabled": false, + "label": "Grow...", + "visible": true + }, + { + "id": 133, + "enabled": false, + "label": "Shrink...", + "visible": true + }, + { + "id": 134, + "enabled": false, + "label": "Sharpen", + "visible": true + }, + { + "id": 135, + "enabled": false, + "label": "Feather...", + "visible": true + }, + { + "id": 136, + "type": "separator" + }, + { + "id": 137, + "enabled": true, + "label": "Selection Editor", + "visible": true + }, + { + "id": 138, + "shortcut": [["Shift", "v"]], + "enabled": false, + "label": "From Path", + "visible": true + }, + { + "id": 139, + "shortcut": [["Shift", "o"]], + "enabled": true, + "label": "By Color", + "visible": true + }, + { + "id": 140, + "shortcut": [["Control", "Shift", "l"]], + "enabled": false, + "label": "Float", + "visible": true + }, + { + "id": 141, + "shortcut": [["Control", "i"]], + "enabled": true, + "label": "Invert", + "visible": true + }, + { + "id": 142, + "shortcut": [["Control", "Shift", "a"]], + "enabled": false, + "label": "None", + "visible": true + }, + { + "id": 143, + "shortcut": [["Control", "a"]], + "enabled": true, + "label": "All", + "visible": true + } + ] + }, + { + "id": 144, + "enabled": true, + "label": "View", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 145, + "enabled": true, + "toggle-state": 1, + "label": "Show Statusbar", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 146, + "enabled": true, + "toggle-state": 0, + "label": "Show Scrollbars", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 147, + "shortcut": [["Control", "Shift", "r"]], + "enabled": true, + "toggle-state": 0, + "label": "Show Rulers", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 148, + "enabled": true, + "toggle-state": 1, + "label": "Show Menubar", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 149, + "enabled": true, + "label": "Padding Color", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 150, + "enabled": true, + "label": "As in Preferences", + "visible": true + }, + { + "id": 151, + "type": "separator" + }, + { + "id": 152, + "enabled": true, + "label": "Select Custom Color...", + "visible": true + }, + { + "id": 153, + "enabled": true, + "label": "Dark Check Color", + "visible": true + }, + { + "id": 154, + "enabled": true, + "label": "Light Check Color", + "visible": true + }, + { + "id": 155, + "enabled": true, + "label": "From Theme", + "visible": true + } + ] + }, + { + "id": 156, + "type": "separator" + }, + { + "id": 157, + "enabled": true, + "toggle-state": 0, + "label": "Snap to Active Path", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 158, + "enabled": true, + "toggle-state": 0, + "label": "Snap to Canvas Edges", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 159, + "enabled": true, + "toggle-state": 0, + "label": "Snap to Grid", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 160, + "enabled": true, + "toggle-state": 1, + "label": "Snap to Guides", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 161, + "type": "separator" + }, + { + "id": 162, + "enabled": true, + "toggle-state": 0, + "label": "Show Sample Points", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 163, + "enabled": true, + "toggle-state": 0, + "label": "Show Grid", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 164, + "shortcut": [["Control", "Shift", "t"]], + "enabled": true, + "toggle-state": 0, + "label": "Show Guides", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 165, + "enabled": true, + "toggle-state": 0, + "label": "Show Layer Boundary", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 166, + "shortcut": [["Control", "t"]], + "enabled": true, + "toggle-state": 0, + "label": "Show Selection", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 167, + "type": "separator" + }, + { + "id": 168, + "enabled": true, + "label": "Display Filters...", + "visible": true + }, + { + "id": 169, + "enabled": true, + "label": "Navigation Window", + "visible": true + }, + { + "id": 170, + "type": "separator" + }, + { + "id": 171, + "enabled": true, + "shortcut": [["F11"]], + "toggle-state": 0, + "label": "Fullscreen", + "toggle-type": "checkmark", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 172, + "enabled": true, + "label": "Open Display...", + "visible": true + } + ] + }, + { + "id": 173, + "shortcut": [["Control", "e"]], + "enabled": true, + "label": "Shrink Wrap", + "visible": true + }, + { + "id": 174, + "type": "separator" + }, + { + "id": 175, + "enabled": true, + "label": "_Zoom (67%)", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 176, + "enabled": true, + "toggle-state": 0, + "label": "Othe_r (67%)...", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 177, + "type": "separator" + }, + { + "id": 178, + "enabled": true, + "toggle-state": 0, + "label": "1:16 (6.25%)", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 179, + "enabled": true, + "toggle-state": 0, + "label": "1:8 (12.5%)", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 180, + "enabled": true, + "toggle-state": 0, + "label": "1:4 (25%)", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 181, + "enabled": true, + "toggle-state": 0, + "label": "1:2 (50%)", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 182, + "shortcut": [["1"]], + "enabled": true, + "toggle-state": 1, + "label": "1:1 (100%)", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 183, + "enabled": true, + "toggle-state": 0, + "label": "2:1 (200%)", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 184, + "enabled": true, + "toggle-state": 0, + "label": "4:1 (400%)", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 185, + "enabled": true, + "toggle-state": 0, + "label": "8:1 (800%)", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 186, + "enabled": true, + "toggle-state": 0, + "label": "16:1 (1600%)", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 187, + "type": "separator" + }, + { + "id": 188, + "enabled": true, + "label": "Fill Window", + "visible": true + }, + { + "id": 189, + "shortcut": [["Control", "Shift", "e"]], + "enabled": true, + "label": "Fit Image in Window", + "visible": true + }, + { + "id": 190, + "shortcut": [["plus"]], + "enabled": true, + "label": "Zoom In", + "visible": true + }, + { + "id": 191, + "shortcut": [["minus"]], + "enabled": true, + "label": "Zoom Out", + "visible": true + }, + { + "id": 4, + "shortcut": [["grave"]], + "enabled": true, + "label": "Re_vert Zoom (67%)", + "visible": true + } + ] + }, + { + "id": 192, + "enabled": true, + "toggle-state": 1, + "label": "Dot for Dot", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 193, + "enabled": true, + "label": "New View", + "visible": true + } + ] + }, + { + "id": 194, + "enabled": true, + "label": "Image", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 195, + "shortcut": [["Alt", "Return"]], + "enabled": true, + "label": "Image Properties", + "visible": true + }, + { + "id": 196, + "enabled": true, + "label": "Configure Grid...", + "visible": true + }, + { + "id": 197, + "enabled": true, + "label": "Guides", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 198, + "enabled": true, + "label": "Remove all Guides", + "visible": true + }, + { + "id": 199, + "enabled": true, + "label": "New Guides from Selection", + "visible": true + }, + { + "id": 200, + "enabled": true, + "label": "New Guide...", + "visible": true + }, + { + "id": 201, + "enabled": true, + "label": "New Guide (by Percent)...", + "visible": true + } + ] + }, + { + "id": 202, + "type": "separator" + }, + { + "id": 203, + "enabled": true, + "label": "Align Visible Layers...", + "visible": true + }, + { + "id": 204, + "enabled": true, + "label": "Flatten Image", + "visible": true + }, + { + "id": 205, + "shortcut": [["Control", "m"]], + "enabled": true, + "label": "Merge Visible Layers...", + "visible": true + }, + { + "id": 206, + "type": "separator" + }, + { + "id": 207, + "enabled": true, + "label": "Zealous Crop", + "visible": true + }, + { + "id": 208, + "enabled": true, + "label": "Autocrop Image", + "visible": true + }, + { + "id": 209, + "enabled": false, + "label": "Crop to Selection", + "visible": true + }, + { + "id": 210, + "type": "separator" + }, + { + "id": 211, + "enabled": true, + "label": "Scale Image...", + "visible": true + }, + { + "id": 212, + "enabled": true, + "label": "Print Size...", + "visible": true + }, + { + "id": 213, + "enabled": false, + "label": "Fit Canvas to Selection", + "visible": true + }, + { + "id": 214, + "enabled": true, + "label": "Fit Canvas to Layers", + "visible": true + }, + { + "id": 215, + "enabled": true, + "label": "Canvas Size...", + "visible": true + }, + { + "id": 216, + "type": "separator" + }, + { + "id": 217, + "enabled": true, + "label": "Transform", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 218, + "enabled": true, + "label": "Guillotine", + "visible": true + }, + { + "id": 219, + "type": "separator" + }, + { + "id": 220, + "enabled": true, + "label": "Rotate 180\302\260", + "visible": true + }, + { + "id": 221, + "enabled": true, + "label": "Rotate 90\302\260 counter-clockwise", + "visible": true + }, + { + "id": 222, + "enabled": true, + "label": "Rotate 90\302\260 clockwise", + "visible": true + }, + { + "id": 223, + "type": "separator" + }, + { + "id": 224, + "enabled": true, + "label": "Flip Vertically", + "visible": true + }, + { + "id": 225, + "enabled": true, + "label": "Flip Horizontally", + "visible": true + } + ] + }, + { + "id": 226, + "enabled": true, + "label": "Mode", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 227, + "enabled": true, + "label": "Convert to Color Profile...", + "visible": true + }, + { + "id": 228, + "enabled": true, + "label": "Assign Color Profile...", + "visible": true + }, + { + "id": 229, + "type": "separator" + }, + { + "id": 230, + "enabled": true, + "toggle-state": 0, + "label": "Indexed...", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 231, + "enabled": true, + "toggle-state": 0, + "label": "Grayscale", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 232, + "enabled": true, + "toggle-state": 1, + "label": "RGB", + "toggle-type": "checkmark", + "visible": true + } + ] + }, + { + "id": 233, + "shortcut": [["Control", "d"]], + "enabled": true, + "label": "Duplicate", + "visible": true + } + ] + }, + { + "id": 234, + "enabled": true, + "label": "Layer", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 235, + "enabled": true, + "label": "Autocrop Layer", + "visible": true + }, + { + "id": 236, + "enabled": false, + "label": "Crop to Selection", + "visible": true + }, + { + "id": 237, + "enabled": true, + "label": "Scale Layer...", + "visible": true + }, + { + "id": 238, + "enabled": true, + "label": "Layer to Image Size", + "visible": true + }, + { + "id": 239, + "enabled": true, + "label": "Layer Boundary Size...", + "visible": true + }, + { + "id": 240, + "type": "separator" + }, + { + "id": 241, + "enabled": true, + "label": "Transform", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 242, + "shortcut": [["Control", "Shift", "o"]], + "enabled": true, + "label": "Offset...", + "visible": true + }, + { + "id": 243, + "type": "separator" + }, + { + "id": 244, + "enabled": true, + "label": "Arbitrary Rotation...", + "visible": true + }, + { + "id": 245, + "enabled": true, + "label": "Rotate 180\302\260", + "visible": true + }, + { + "id": 246, + "enabled": true, + "label": "Rotate 90\302\260 counter-clockwise", + "visible": true + }, + { + "id": 247, + "enabled": true, + "label": "Rotate 90\302\260 clockwise", + "visible": true + }, + { + "id": 248, + "type": "separator" + }, + { + "id": 249, + "enabled": true, + "label": "Flip Vertically", + "visible": true + }, + { + "id": 250, + "enabled": true, + "label": "Flip Horizontally", + "visible": true + } + ] + }, + { + "id": 251, + "enabled": true, + "label": "Transparency", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 252, + "enabled": true, + "label": "Intersect with Selection", + "visible": true + }, + { + "id": 253, + "enabled": true, + "label": "Subtract from Selection", + "visible": true + }, + { + "id": 254, + "enabled": true, + "label": "Add to Selection", + "visible": true + }, + { + "id": 255, + "enabled": true, + "label": "Alpha to Selection", + "visible": true + }, + { + "id": 256, + "type": "separator" + }, + { + "id": 257, + "enabled": true, + "label": "Threshold Alpha...", + "visible": true + }, + { + "id": 258, + "enabled": true, + "label": "Semi-Flatten", + "visible": true + }, + { + "id": 259, + "enabled": true, + "label": "Color to Alpha...", + "visible": true + }, + { + "id": 260, + "enabled": true, + "label": "Remove Alpha Channel", + "visible": true + }, + { + "id": 261, + "enabled": false, + "label": "Add Alpha Channel", + "visible": true + } + ] + }, + { + "id": 262, + "enabled": true, + "label": "Mask", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 263, + "enabled": false, + "label": "Intersect with Selection", + "visible": true + }, + { + "id": 264, + "enabled": false, + "label": "Subtract from Selection", + "visible": true + }, + { + "id": 265, + "enabled": false, + "label": "Add to Selection", + "visible": true + }, + { + "id": 266, + "enabled": false, + "label": "Mask to Selection", + "visible": true + }, + { + "id": 267, + "type": "separator" + }, + { + "id": 268, + "enabled": false, + "toggle-state": 0, + "label": "Disable Layer Mask", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 269, + "enabled": false, + "toggle-state": 0, + "label": "Edit Layer Mask", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 270, + "enabled": false, + "toggle-state": 0, + "label": "Show Layer Mask", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 271, + "type": "separator" + }, + { + "id": 272, + "enabled": false, + "label": "Delete Layer Mask", + "visible": true + }, + { + "id": 273, + "enabled": false, + "label": "Apply Layer Mask", + "visible": true + }, + { + "id": 274, + "enabled": true, + "label": "Add Layer Mask...", + "visible": true + } + ] + }, + { + "id": 275, + "enabled": true, + "label": "Stack", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 276, + "enabled": true, + "label": "Reverse Layer Order", + "visible": true + }, + { + "id": 277, + "type": "separator" + }, + { + "id": 278, + "enabled": false, + "label": "Layer to Bottom", + "visible": true + }, + { + "id": 279, + "enabled": false, + "label": "Layer to Top", + "visible": true + }, + { + "id": 280, + "enabled": false, + "label": "Lower Layer", + "visible": true + }, + { + "id": 281, + "enabled": false, + "label": "Raise Layer", + "visible": true + }, + { + "id": 282, + "type": "separator" + }, + { + "id": 283, + "shortcut": [["End"]], + "enabled": false, + "label": "Select Bottom Layer", + "visible": true + }, + { + "id": 284, + "shortcut": [["Home"]], + "enabled": false, + "label": "Select Top Layer", + "visible": true + }, + { + "id": 285, + "shortcut": [["Page_Down"]], + "enabled": false, + "label": "Select Next Layer", + "visible": true + }, + { + "id": 286, + "shortcut": [["Page_Up"]], + "enabled": false, + "label": "Select Previous Layer", + "visible": true + } + ] + }, + { + "id": 287, + "type": "separator", + "children-display": "submenu", + "submenu": [ + { + "id": 288, + "enabled": false, + "label": "Empty", + "visible": true + } + ] + }, + { + "id": 289, + "enabled": true, + "label": "Delete Layer", + "visible": true + }, + { + "id": 290, + "enabled": false, + "label": "Merge Down", + "visible": true + }, + { + "id": 291, + "shortcut": [["Control", "h"]], + "enabled": false, + "label": "Anchor Layer", + "visible": true + }, + { + "id": 292, + "shortcut": [["Control", "Shift", "d"]], + "enabled": true, + "label": "Duplicate Layer", + "visible": true + }, + { + "id": 293, + "enabled": true, + "label": "New from Visible", + "visible": true + }, + { + "id": 294, + "shortcut": [["Control", "Shift", "n"]], + "enabled": true, + "label": "New Layer...", + "visible": true + } + ] + }, + { + "id": 295, + "enabled": true, + "label": "Colors", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 296, + "enabled": true, + "label": "Retinex...", + "visible": true + }, + { + "id": 297, + "enabled": true, + "label": "Maximum RGB...", + "visible": true + }, + { + "id": 298, + "enabled": false, + "label": "Hot...", + "visible": true + }, + { + "id": 299, + "enabled": true, + "label": "Filter Pack...", + "visible": true + }, + { + "id": 300, + "enabled": true, + "label": "Color to Alpha...", + "visible": true + }, + { + "id": 301, + "enabled": true, + "label": "Colorify...", + "visible": true + }, + { + "id": 302, + "type": "separator" + }, + { + "id": 303, + "enabled": true, + "label": "Info", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 304, + "enabled": true, + "label": "Smooth Palette...", + "visible": true + }, + { + "id": 305, + "enabled": true, + "label": "Colorcube Analysis...", + "visible": true + }, + { + "id": 306, + "enabled": true, + "label": "Border Average...", + "visible": true + }, + { + "id": 307, + "enabled": true, + "label": "Histogram", + "visible": true + } + ] + }, + { + "id": 308, + "enabled": true, + "label": "Map", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 309, + "enabled": true, + "label": "Sample Colorize...", + "visible": true + }, + { + "id": 310, + "enabled": true, + "label": "Rotate Colors...", + "visible": true + }, + { + "id": 311, + "enabled": true, + "label": "Palette Map", + "visible": true + }, + { + "id": 312, + "enabled": true, + "label": "Gradient Map", + "visible": true + }, + { + "id": 313, + "enabled": true, + "label": "Color Exchange...", + "visible": true + }, + { + "id": 314, + "enabled": true, + "label": "Alien Map...", + "visible": true + }, + { + "id": 315, + "type": "separator" + }, + { + "id": 316, + "enabled": false, + "label": "Set Colormap...", + "visible": true + }, + { + "id": 317, + "enabled": false, + "label": "Rearrange Colormap...", + "visible": true + } + ] + }, + { + "id": 318, + "enabled": true, + "label": "Components", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 319, + "enabled": false, + "label": "Recompose", + "visible": true + }, + { + "id": 320, + "enabled": true, + "label": "Decompose...", + "visible": true + }, + { + "id": 321, + "enabled": false, + "label": "Compose...", + "visible": true + }, + { + "id": 322, + "enabled": true, + "label": "Channel Mixer...", + "visible": true + } + ] + }, + { + "id": 323, + "enabled": true, + "label": "Auto", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 324, + "enabled": true, + "label": "Stretch HSV", + "visible": true + }, + { + "id": 325, + "enabled": true, + "label": "Stretch Contrast", + "visible": true + }, + { + "id": 326, + "enabled": true, + "label": "Normalize", + "visible": true + }, + { + "id": 327, + "enabled": true, + "label": "Color Enhance", + "visible": true + }, + { + "id": 328, + "enabled": true, + "label": "White Balance", + "visible": true + }, + { + "id": 329, + "enabled": true, + "label": "Equalize", + "visible": true + } + ] + }, + { + "id": 330, + "type": "separator" + }, + { + "id": 331, + "enabled": true, + "toggle-state": 0, + "label": "Use GEGL", + "toggle-type": "checkmark", + "visible": true + }, + { + "id": 332, + "type": "separator" + }, + { + "id": 333, + "enabled": true, + "label": "Value Invert", + "visible": true + }, + { + "id": 334, + "enabled": true, + "label": "Invert", + "visible": true + }, + { + "id": 335, + "type": "separator" + }, + { + "id": 336, + "enabled": true, + "label": "Desaturate...", + "visible": true + }, + { + "id": 337, + "enabled": true, + "label": "Posterize...", + "visible": true + }, + { + "id": 338, + "enabled": true, + "label": "Curves...", + "visible": true + }, + { + "id": 339, + "enabled": true, + "label": "Levels...", + "visible": true + }, + { + "id": 340, + "enabled": true, + "label": "Threshold...", + "visible": true + }, + { + "id": 341, + "enabled": true, + "label": "Brightness-Contrast...", + "visible": true + }, + { + "id": 342, + "enabled": true, + "label": "Colorize...", + "visible": true + }, + { + "id": 343, + "enabled": true, + "label": "Hue-Saturation...", + "visible": true + }, + { + "id": 344, + "enabled": true, + "label": "Color Balance...", + "visible": true + } + ] + }, + { + "id": 345, + "enabled": true, + "label": "Tools", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 346, + "shortcut": [["x"]], + "enabled": true, + "label": "Swap Colors", + "visible": true + }, + { + "id": 347, + "shortcut": [["d"]], + "enabled": true, + "label": "Default Colors", + "visible": true + }, + { + "id": 348, + "shortcut": [["Control", "b"]], + "enabled": true, + "label": "Toolbox", + "visible": true + }, + { + "id": 349, + "type": "separator" + }, + { + "id": 350, + "enabled": true, + "label": "GEGL Operation...", + "visible": true + }, + { + "id": 351, + "shortcut": [["t"]], + "enabled": true, + "label": "Text", + "visible": true + }, + { + "id": 352, + "shortcut": [["Shift", "m"]], + "enabled": true, + "label": "Measure", + "visible": true + }, + { + "id": 353, + "shortcut": [["z"]], + "enabled": true, + "label": "Zoom", + "visible": true + }, + { + "id": 354, + "shortcut": [["o"]], + "enabled": true, + "label": "Color Picker", + "visible": true + }, + { + "id": 355, + "shortcut": [["b"]], + "enabled": true, + "label": "Paths", + "visible": true + }, + { + "id": 356, + "enabled": true, + "label": "Color Tools", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 357, + "enabled": true, + "label": "Desaturate...", + "visible": true + }, + { + "id": 358, + "enabled": true, + "label": "Posterize...", + "visible": true + }, + { + "id": 359, + "enabled": true, + "label": "Curves...", + "visible": true + }, + { + "id": 360, + "enabled": true, + "label": "Levels...", + "visible": true + }, + { + "id": 361, + "enabled": true, + "label": "Threshold...", + "visible": true + }, + { + "id": 362, + "enabled": true, + "label": "Brightness-Contrast...", + "visible": true + }, + { + "id": 363, + "enabled": true, + "label": "Colorize...", + "visible": true + }, + { + "id": 364, + "enabled": true, + "label": "Hue-Saturation...", + "visible": true + }, + { + "id": 365, + "enabled": true, + "label": "Color Balance...", + "visible": true + } + ] + }, + { + "id": 366, + "enabled": true, + "label": "Transform Tools", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 367, + "shortcut": [["Shift", "f"]], + "enabled": true, + "label": "Flip", + "visible": true + }, + { + "id": 368, + "shortcut": [["Shift", "p"]], + "enabled": true, + "label": "Perspective", + "visible": true + }, + { + "id": 369, + "shortcut": [["Shift", "s"]], + "enabled": true, + "label": "Shear", + "visible": true + }, + { + "id": 370, + "shortcut": [["Shift", "t"]], + "enabled": true, + "label": "Scale", + "visible": true + }, + { + "id": 371, + "shortcut": [["Shift", "r"]], + "enabled": true, + "label": "Rotate", + "visible": true + }, + { + "id": 372, + "shortcut": [["Shift", "c"]], + "enabled": true, + "label": "Crop", + "visible": true + }, + { + "id": 373, + "shortcut": [["m"]], + "enabled": true, + "label": "Move", + "visible": true + }, + { + "id": 374, + "shortcut": [["q"]], + "enabled": true, + "label": "Align", + "visible": true + } + ] + }, + { + "id": 375, + "enabled": true, + "label": "Paint Tools", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 376, + "shortcut": [["Shift", "d"]], + "enabled": true, + "label": "Dodge / Burn", + "visible": true + }, + { + "id": 377, + "shortcut": [["s"]], + "enabled": true, + "label": "Smudge", + "visible": true + }, + { + "id": 378, + "shortcut": [["Shift", "u"]], + "enabled": true, + "label": "Blur / Sharpen", + "visible": true + }, + { + "id": 379, + "enabled": true, + "label": "Perspective Clone", + "visible": true + }, + { + "id": 380, + "shortcut": [["h"]], + "enabled": true, + "label": "Heal", + "visible": true + }, + { + "id": 381, + "shortcut": [["c"]], + "enabled": true, + "label": "Clone", + "visible": true + }, + { + "id": 382, + "shortcut": [["k"]], + "enabled": true, + "label": "Ink", + "visible": true + }, + { + "id": 383, + "shortcut": [["a"]], + "enabled": true, + "label": "Airbrush", + "visible": true + }, + { + "id": 384, + "shortcut": [["Shift", "e"]], + "enabled": true, + "label": "Eraser", + "visible": true + }, + { + "id": 385, + "shortcut": [["p"]], + "enabled": true, + "label": "Paintbrush", + "visible": true + }, + { + "id": 386, + "shortcut": [["n"]], + "enabled": true, + "label": "Pencil", + "visible": true + }, + { + "id": 387, + "shortcut": [["l"]], + "enabled": true, + "label": "Blend", + "visible": true + }, + { + "id": 388, + "shortcut": [["Shift", "b"]], + "enabled": true, + "label": "Bucket Fill", + "visible": true + } + ] + }, + { + "id": 389, + "enabled": true, + "label": "Selection Tools", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 390, + "shortcut": [["i"]], + "enabled": true, + "label": "Intelligent Scissors", + "visible": true + }, + { + "id": 391, + "shortcut": [["Shift", "o"]], + "enabled": true, + "label": "By Color Select", + "visible": true + }, + { + "id": 392, + "shortcut": [["u"]], + "enabled": true, + "label": "Fuzzy Select", + "visible": true + }, + { + "id": 393, + "enabled": true, + "label": "Foreground Select", + "visible": true + }, + { + "id": 394, + "shortcut": [["f"]], + "enabled": true, + "label": "Free Select", + "visible": true + }, + { + "id": 395, + "shortcut": [["e"]], + "enabled": true, + "label": "Ellipse Select", + "visible": true + }, + { + "id": 396, + "shortcut": [["r"]], + "enabled": true, + "label": "Rectangle Select", + "visible": true + } + ] + } + ] + }, + { + "id": 397, + "enabled": true, + "label": "Filters", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 398, + "enabled": true, + "label": "Script-Fu", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 399, + "enabled": true, + "label": "Start Server...", + "visible": true + }, + { + "id": 400, + "enabled": true, + "label": "Refresh Scripts", + "visible": true + }, + { + "id": 401, + "enabled": true, + "label": "Console", + "visible": true + } + ] + }, + { + "id": 402, + "enabled": true, + "label": "Python-Fu", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 403, + "enabled": true, + "label": "Console", + "visible": true + } + ] + }, + { + "id": 404, + "type": "separator" + }, + { + "id": 405, + "enabled": true, + "label": "Alpha to Logo", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 406, + "enabled": true, + "label": "Textured...", + "visible": true + }, + { + "id": 407, + "enabled": true, + "label": "Particle Trace...", + "visible": true + }, + { + "id": 408, + "enabled": true, + "label": "Neon...", + "visible": true + }, + { + "id": 409, + "enabled": true, + "label": "Gradient Bevel...", + "visible": true + }, + { + "id": 410, + "enabled": true, + "label": "Glowing Hot...", + "visible": true + }, + { + "id": 411, + "enabled": true, + "label": "Glossy...", + "visible": true + }, + { + "id": 412, + "enabled": true, + "label": "Frosty...", + "visible": true + }, + { + "id": 413, + "enabled": true, + "label": "Cool Metal...", + "visible": true + }, + { + "id": 414, + "enabled": true, + "label": "Comic Book...", + "visible": true + }, + { + "id": 415, + "enabled": true, + "label": "Chrome...", + "visible": true + }, + { + "id": 416, + "enabled": true, + "label": "Chip Away...", + "visible": true + }, + { + "id": 417, + "enabled": true, + "label": "Chalk...", + "visible": true + }, + { + "id": 418, + "enabled": true, + "label": "Bovination...", + "visible": true + }, + { + "id": 419, + "enabled": true, + "label": "Blended...", + "visible": true + }, + { + "id": 420, + "enabled": true, + "label": "Basic I...", + "visible": true + }, + { + "id": 421, + "enabled": true, + "label": "Basic II...", + "visible": true + }, + { + "id": 422, + "enabled": true, + "label": "Alien Neon...", + "visible": true + }, + { + "id": 423, + "enabled": true, + "label": "Alien Glow...", + "visible": true + }, + { + "id": 424, + "enabled": true, + "label": "3D Outline...", + "visible": true + } + ] + }, + { + "id": 425, + "type": "separator" + }, + { + "id": 426, + "enabled": true, + "label": "Animation", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 427, + "enabled": true, + "label": "Unoptimize", + "visible": true + }, + { + "id": 428, + "enabled": true, + "label": "Playback...", + "visible": true + }, + { + "id": 429, + "enabled": true, + "label": "Optimize (for GIF)", + "visible": true + }, + { + "id": 430, + "enabled": true, + "label": "Optimize (Difference)", + "visible": true + }, + { + "id": 431, + "type": "separator" + }, + { + "id": 432, + "enabled": true, + "label": "Waves...", + "visible": true + }, + { + "id": 433, + "enabled": true, + "label": "Spinning Globe...", + "visible": true + }, + { + "id": 434, + "enabled": true, + "label": "Rippling...", + "visible": true + }, + { + "id": 435, + "enabled": true, + "label": "Burn-In...", + "visible": true + }, + { + "id": 436, + "enabled": true, + "label": "Blend...", + "visible": true + } + ] + }, + { + "id": 437, + "enabled": true, + "label": "Web", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 438, + "enabled": true, + "label": "Slice...", + "visible": true + }, + { + "id": 439, + "enabled": true, + "label": "Semi-Flatten", + "visible": true + }, + { + "id": 440, + "enabled": true, + "label": "Image Map...", + "visible": true + } + ] + }, + { + "id": 441, + "enabled": true, + "label": "Render", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 442, + "enabled": true, + "label": "Spyrogimp...", + "visible": true + }, + { + "id": 443, + "enabled": true, + "label": "Sphere Designer...", + "visible": true + }, + { + "id": 444, + "enabled": true, + "label": "Line Nova...", + "visible": true + }, + { + "id": 445, + "enabled": true, + "label": "Lava...", + "visible": true + }, + { + "id": 446, + "enabled": true, + "label": "Gfig...", + "visible": true + }, + { + "id": 447, + "enabled": true, + "label": "Fractal Explorer...", + "visible": true + }, + { + "id": 448, + "enabled": true, + "label": "Circuit...", + "visible": true + }, + { + "id": 449, + "type": "separator" + }, + { + "id": 450, + "enabled": true, + "label": "Pattern", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 451, + "enabled": true, + "label": "Sinus...", + "visible": true + }, + { + "id": 452, + "enabled": true, + "label": "Qbist...", + "visible": true + }, + { + "id": 453, + "enabled": true, + "label": "Maze...", + "visible": true + }, + { + "id": 454, + "enabled": true, + "label": "Jigsaw...", + "visible": true + }, + { + "id": 455, + "enabled": true, + "label": "Grid...", + "visible": true + }, + { + "id": 456, + "enabled": true, + "label": "Diffraction Patterns...", + "visible": true + }, + { + "id": 457, + "enabled": true, + "label": "CML Explorer...", + "visible": true + }, + { + "id": 458, + "enabled": true, + "label": "Checkerboard...", + "visible": true + } + ] + }, + { + "id": 459, + "enabled": true, + "label": "Nature", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 460, + "enabled": true, + "label": "IFS Fractal...", + "visible": true + }, + { + "id": 461, + "enabled": true, + "label": "Flame...", + "visible": true + } + ] + }, + { + "id": 462, + "enabled": true, + "label": "Clouds", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 463, + "enabled": true, + "label": "Solid Noise...", + "visible": true + }, + { + "id": 464, + "enabled": true, + "label": "Plasma...", + "visible": true + }, + { + "id": 465, + "enabled": true, + "label": "Fog...", + "visible": true + }, + { + "id": 466, + "enabled": true, + "label": "Difference Clouds...", + "visible": true + } + ] + } + ] + }, + { + "id": 467, + "enabled": true, + "label": "Map", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 468, + "enabled": true, + "label": "Warp...", + "visible": true + }, + { + "id": 469, + "enabled": true, + "label": "Tile...", + "visible": true + }, + { + "id": 470, + "enabled": true, + "label": "Small Tiles...", + "visible": true + }, + { + "id": 471, + "enabled": true, + "label": "Paper Tile...", + "visible": true + }, + { + "id": 472, + "enabled": true, + "label": "Map Object...", + "visible": true + }, + { + "id": 473, + "enabled": true, + "label": "Make Seamless", + "visible": true + }, + { + "id": 474, + "enabled": true, + "label": "Illusion...", + "visible": true + }, + { + "id": 475, + "enabled": true, + "label": "Fractal Trace...", + "visible": true + }, + { + "id": 476, + "enabled": true, + "label": "Displace...", + "visible": true + }, + { + "id": 477, + "enabled": true, + "label": "Bump Map...", + "visible": true + } + ] + }, + { + "id": 478, + "enabled": true, + "label": "Decor", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 479, + "enabled": false, + "label": "Stencil Chrome...", + "visible": true + }, + { + "id": 480, + "enabled": false, + "label": "Stencil Carve...", + "visible": true + }, + { + "id": 481, + "enabled": false, + "label": "Slide...", + "visible": true + }, + { + "id": 482, + "enabled": false, + "label": "Round Corners...", + "visible": true + }, + { + "id": 483, + "enabled": true, + "label": "Old Photo...", + "visible": true + }, + { + "id": 484, + "enabled": true, + "label": "Fuzzy Border...", + "visible": true + }, + { + "id": 485, + "enabled": true, + "label": "Coffee Stain...", + "visible": true + }, + { + "id": 486, + "enabled": true, + "label": "Add Border...", + "visible": true + }, + { + "id": 487, + "enabled": true, + "label": "Add Bevel...", + "visible": true + } + ] + }, + { + "id": 488, + "enabled": true, + "label": "Artistic", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 489, + "enabled": true, + "label": "Weave...", + "visible": true + }, + { + "id": 490, + "enabled": true, + "label": "Van Gogh (LIC)...", + "visible": true + }, + { + "id": 491, + "enabled": true, + "label": "Softglow...", + "visible": true + }, + { + "id": 492, + "enabled": true, + "label": "Predator...", + "visible": true + }, + { + "id": 493, + "enabled": true, + "label": "Photocopy...", + "visible": true + }, + { + "id": 494, + "enabled": true, + "label": "Oilify...", + "visible": true + }, + { + "id": 495, + "enabled": true, + "label": "GIMPressionist...", + "visible": true + }, + { + "id": 496, + "enabled": true, + "label": "Cubism...", + "visible": true + }, + { + "id": 497, + "enabled": true, + "label": "Clothify...", + "visible": true + }, + { + "id": 498, + "enabled": true, + "label": "Cartoon...", + "visible": true + }, + { + "id": 499, + "enabled": true, + "label": "Apply Canvas...", + "visible": true + } + ] + }, + { + "id": 500, + "enabled": true, + "label": "Combine", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 501, + "enabled": true, + "label": "Filmstrip...", + "visible": true + }, + { + "id": 502, + "enabled": true, + "label": "Depth Merge...", + "visible": true + } + ] + }, + { + "id": 503, + "enabled": true, + "label": "Generic", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 504, + "enabled": true, + "label": "Erode", + "visible": true + }, + { + "id": 505, + "enabled": true, + "label": "Dilate", + "visible": true + }, + { + "id": 506, + "enabled": true, + "label": "Convolution Matrix...", + "visible": true + } + ] + }, + { + "id": 507, + "enabled": true, + "label": "Edge-Detect", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 508, + "enabled": true, + "label": "Sobel...", + "visible": true + }, + { + "id": 509, + "enabled": true, + "label": "Neon...", + "visible": true + }, + { + "id": 510, + "enabled": true, + "label": "Laplace", + "visible": true + }, + { + "id": 511, + "enabled": true, + "label": "Edge...", + "visible": true + }, + { + "id": 512, + "enabled": true, + "label": "Difference of Gaussians...", + "visible": true + } + ] + }, + { + "id": 513, + "enabled": true, + "label": "Noise", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 514, + "enabled": true, + "label": "Spread...", + "visible": true + }, + { + "id": 515, + "enabled": true, + "label": "Slur...", + "visible": true + }, + { + "id": 516, + "enabled": true, + "label": "RGB Noise...", + "visible": true + }, + { + "id": 517, + "enabled": true, + "label": "Pick...", + "visible": true + }, + { + "id": 518, + "enabled": true, + "label": "Hurl...", + "visible": true + }, + { + "id": 519, + "enabled": true, + "label": "HSV Noise...", + "visible": true + } + ] + }, + { + "id": 520, + "enabled": true, + "label": "Light and Shadow", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 521, + "enabled": true, + "label": "Glass Tile...", + "visible": true + }, + { + "id": 522, + "enabled": true, + "label": "Apply Lens...", + "visible": true + }, + { + "id": 523, + "type": "separator" + }, + { + "id": 524, + "enabled": true, + "label": "Xach-Effect...", + "visible": true + }, + { + "id": 525, + "enabled": true, + "label": "Perspective...", + "visible": true + }, + { + "id": 526, + "enabled": true, + "label": "Drop Shadow...", + "visible": true + }, + { + "id": 527, + "type": "separator" + }, + { + "id": 528, + "enabled": true, + "label": "Supernova...", + "visible": true + }, + { + "id": 529, + "enabled": true, + "label": "Sparkle...", + "visible": true + }, + { + "id": 530, + "enabled": true, + "label": "Lighting Effects...", + "visible": true + }, + { + "id": 531, + "enabled": true, + "label": "Lens Flare...", + "visible": true + }, + { + "id": 532, + "enabled": true, + "label": "Gradient Flare...", + "visible": true + } + ] + }, + { + "id": 533, + "enabled": true, + "label": "Distorts", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 534, + "enabled": true, + "label": "Wind...", + "visible": true + }, + { + "id": 535, + "enabled": true, + "label": "Whirl and Pinch...", + "visible": true + }, + { + "id": 536, + "enabled": true, + "label": "Waves...", + "visible": true + }, + { + "id": 537, + "enabled": true, + "label": "Video...", + "visible": true + }, + { + "id": 538, + "enabled": true, + "label": "Value Propagate...", + "visible": true + }, + { + "id": 539, + "enabled": true, + "label": "Shift...", + "visible": true + }, + { + "id": 540, + "enabled": true, + "label": "Ripple...", + "visible": true + }, + { + "id": 541, + "enabled": true, + "label": "Polar Coordinates...", + "visible": true + }, + { + "id": 542, + "enabled": true, + "label": "Pagecurl...", + "visible": true + }, + { + "id": 543, + "enabled": true, + "label": "Newsprint...", + "visible": true + }, + { + "id": 544, + "enabled": true, + "label": "Mosaic...", + "visible": true + }, + { + "id": 545, + "enabled": true, + "label": "Lens Distortion...", + "visible": true + }, + { + "id": 546, + "enabled": true, + "label": "IWarp...", + "visible": true + }, + { + "id": 547, + "enabled": true, + "label": "Erase Every Other Row...", + "visible": true + }, + { + "id": 548, + "enabled": true, + "label": "Engrave...", + "visible": true + }, + { + "id": 549, + "enabled": true, + "label": "Emboss...", + "visible": true + }, + { + "id": 550, + "enabled": true, + "label": "Curve Bend...", + "visible": true + }, + { + "id": 551, + "enabled": true, + "label": "Blinds...", + "visible": true + } + ] + }, + { + "id": 552, + "enabled": true, + "label": "Enhance", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 553, + "enabled": true, + "label": "Unsharp Mask...", + "visible": true + }, + { + "id": 554, + "enabled": true, + "label": "Sharpen...", + "visible": true + }, + { + "id": 555, + "enabled": true, + "label": "Red Eye Removal...", + "visible": true + }, + { + "id": 556, + "enabled": false, + "label": "NL Filter...", + "visible": true + }, + { + "id": 557, + "enabled": true, + "label": "Destripe...", + "visible": true + }, + { + "id": 558, + "enabled": true, + "label": "Despeckle...", + "visible": true + }, + { + "id": 559, + "enabled": true, + "label": "Deinterlace...", + "visible": true + }, + { + "id": 560, + "enabled": true, + "label": "Antialias", + "visible": true + } + ] + }, + { + "id": 561, + "enabled": true, + "label": "Blur", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 562, + "enabled": true, + "label": "Tileable Blur...", + "visible": true + }, + { + "id": 563, + "enabled": true, + "label": "Selective Gaussian Blur...", + "visible": true + }, + { + "id": 564, + "enabled": true, + "label": "Pixelize...", + "visible": true + }, + { + "id": 565, + "enabled": true, + "label": "Motion Blur...", + "visible": true + }, + { + "id": 566, + "enabled": true, + "label": "Gaussian Blur...", + "visible": true + }, + { + "id": 567, + "enabled": true, + "label": "Blur", + "visible": true + } + ] + }, + { + "id": 568, + "type": "separator" + }, + { + "id": 569, + "enabled": true, + "label": "Reset all Filters", + "visible": true + }, + { + "id": 570, + "shortcut": [["Control", "Shift", "f"]], + "enabled": false, + "label": "Re-Show Last", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 571, + "enabled": false, + "label": "Empty", + "visible": true + } + ] + }, + { + "id": 572, + "shortcut": [["Control", "f"]], + "enabled": false, + "label": "Repeat Last", + "visible": true + } + ] + }, + { + "id": 573, + "enabled": true, + "label": "Windows", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 574, + "shortcut": [["Control", "b"]], + "enabled": true, + "label": "Toolbox", + "visible": true + }, + { + "id": 575, + "type": "separator" + }, + { + "id": 576, + "enabled": true, + "label": "Dockable Dialogs", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 577, + "enabled": true, + "label": "Error Console", + "visible": true + }, + { + "id": 578, + "enabled": true, + "label": "Tools", + "visible": true + }, + { + "id": 579, + "enabled": true, + "label": "Templates", + "visible": true + }, + { + "id": 580, + "enabled": true, + "label": "Document History", + "visible": true + }, + { + "id": 581, + "enabled": true, + "label": "Images", + "visible": true + }, + { + "id": 582, + "type": "separator" + }, + { + "id": 583, + "enabled": true, + "label": "Buffers", + "visible": true + }, + { + "id": 584, + "enabled": true, + "label": "Fonts", + "visible": true + }, + { + "id": 585, + "enabled": true, + "label": "Palettes", + "visible": true + }, + { + "id": 586, + "shortcut": [["Control", "g"]], + "enabled": true, + "label": "Gradients", + "visible": true + }, + { + "id": 587, + "shortcut": [["Control", "Shift", "p"]], + "enabled": true, + "label": "Patterns", + "visible": true + }, + { + "id": 588, + "shortcut": [["Control", "Shift", "b"]], + "enabled": true, + "label": "Brushes", + "visible": true + }, + { + "id": 589, + "enabled": true, + "label": "Colors", + "visible": true + }, + { + "id": 590, + "type": "separator" + }, + { + "id": 591, + "enabled": true, + "label": "Sample Points", + "visible": true + }, + { + "id": 592, + "enabled": true, + "label": "Pointer", + "visible": true + }, + { + "id": 593, + "enabled": true, + "label": "Undo History", + "visible": true + }, + { + "id": 594, + "enabled": true, + "label": "Navigation", + "visible": true + }, + { + "id": 595, + "enabled": true, + "label": "Selection Editor", + "visible": true + }, + { + "id": 596, + "enabled": true, + "label": "Histogram", + "visible": true + }, + { + "id": 597, + "enabled": true, + "label": "Colormap", + "visible": true + }, + { + "id": 598, + "enabled": true, + "label": "Paths", + "visible": true + }, + { + "id": 599, + "enabled": true, + "label": "Channels", + "visible": true + }, + { + "id": 600, + "shortcut": [["Control", "l"]], + "enabled": true, + "label": "Layers", + "visible": true + }, + { + "id": 601, + "type": "separator" + }, + { + "id": 602, + "enabled": true, + "label": "Device Status", + "visible": true + }, + { + "id": 603, + "enabled": true, + "label": "Tool Options", + "visible": true + } + ] + }, + { + "id": 604, + "enabled": true, + "label": "Recently Closed Docks", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 605, + "enabled": false, + "label": "Empty", + "visible": true + } + ] + } + ] + }, + { + "id": 606, + "enabled": true, + "label": "Help", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 607, + "enabled": true, + "label": "User Manual", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 608, + "enabled": true, + "label": "Working with Digital Camera Photos", + "visible": true + }, + { + "id": 609, + "enabled": true, + "label": "Using Paths", + "visible": true + }, + { + "id": 610, + "enabled": true, + "label": "Preparing your Images for the Web", + "visible": true + }, + { + "id": 611, + "enabled": true, + "label": "How to Use Dialogs", + "visible": true + }, + { + "id": 612, + "enabled": true, + "label": "Drawing Simple Objects", + "visible": true + }, + { + "id": 613, + "enabled": true, + "label": "Create, Open and Save Files", + "visible": true + }, + { + "id": 614, + "enabled": true, + "label": "Basic Concepts", + "visible": true + } + ] + }, + { + "id": 615, + "enabled": true, + "label": "GIMP Online", + "children-display": "submenu", + "visible": true, + "submenu": [ + { + "id": 616, + "enabled": true, + "label": "User Manual Web Site", + "visible": true + }, + { + "id": 617, + "enabled": true, + "label": "Plug-in Registry", + "visible": true + }, + { + "id": 618, + "enabled": true, + "label": "Main Web Site", + "visible": true + }, + { + "id": 619, + "enabled": true, + "label": "Developer Web Site", + "visible": true + } + ] + }, + { + "id": 620, + "type": "separator" + }, + { + "id": 621, + "enabled": true, + "label": "Procedure Browser", + "visible": true + }, + { + "id": 622, + "enabled": true, + "label": "Plug-In Browser", + "visible": true + }, + { + "id": 623, + "type": "separator" + }, + { + "id": 624, + "enabled": true, + "label": "About", + "visible": true + }, + { + "id": 625, + "enabled": true, + "label": "Tip of the Day", + "visible": true + }, + { + "id": 626, + "shortcut": [["Shift", "F1"]], + "enabled": true, + "label": "Context Help", + "visible": true + }, + { + "id": 627, + "shortcut": [["F1"]], + "enabled": true, + "label": "Help", + "visible": true + } + ] + } + ] +} diff --git a/tests/test-json-client.c b/tests/test-json-client.c new file mode 100644 index 0000000..f9da55e --- /dev/null +++ b/tests/test-json-client.c @@ -0,0 +1,75 @@ +/* +Test to check the json-loader and dbusmenu-dumper + +Copyright 2010 Canonical Ltd. + +Authors: + Ted Gould <ted@canonical.com> + +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 <http://www.gnu.org/licenses/>. +*/ + +#include <glib.h> +#include <gio/gio.h> +#include <dbus/dbus-glib.h> +#include <dbus/dbus-glib-bindings.h> +#include <dbus/dbus-glib-lowlevel.h> + +GMainLoop * mainloop = NULL; + +int +main (int argc, char ** argv) +{ + g_type_init(); + g_debug("Wait for friends"); + + GError * error = NULL; + DBusGConnection * session_bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error); + if (error != NULL) { + g_error("Unable to get session bus: %s", error->message); + return 1; + } + + DBusGProxy * bus_proxy = dbus_g_proxy_new_for_name(session_bus, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); + + gboolean has_owner = FALSE; + gint owner_count = 0; + while (!has_owner && owner_count < 10000) { + org_freedesktop_DBus_name_has_owner(bus_proxy, "org.dbusmenu.test", &has_owner, NULL); + owner_count++; + } + + if (owner_count == 10000) { + g_error("Unable to get name owner after 10000 tries"); + return 1; + } + + g_usleep(500000); + + g_debug("Initing"); + + gchar * command = g_strdup_printf("%s --dbus-name=org.dbusmenu.test --dbus-object=/org/test", argv[1]); + g_debug("Executing: %s", command); + + gchar * output; + g_spawn_command_line_sync(command, &output, NULL, NULL, NULL); + + GFile * ofile = g_file_new_for_commandline_arg(argv[2]); + if (ofile != NULL) { + g_file_replace_contents(ofile, output, g_utf8_strlen(output, -1), NULL, FALSE, 0, NULL, NULL, NULL); + } + + g_debug("Exiting"); + + return 0; +} diff --git a/tests/test-json-server.c b/tests/test-json-server.c new file mode 100644 index 0000000..fe9507a --- /dev/null +++ b/tests/test-json-server.c @@ -0,0 +1,81 @@ +/* +Test to check the json-loader and dbusmenu-dumper + +Copyright 2010 Canonical Ltd. + +Authors: + Ted Gould <ted@canonical.com> + +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 <http://www.gnu.org/licenses/>. +*/ + +#include <glib.h> + +#include <dbus/dbus.h> +#include <dbus/dbus-glib.h> +#include <dbus/dbus-glib-lowlevel.h> +#include <dbus/dbus-glib-bindings.h> + +#include <libdbusmenu-glib/server.h> +#include <libdbusmenu-glib/menuitem.h> + +#include "json-loader.h" + +static GMainLoop * mainloop = NULL; + +static gboolean +timer_func (gpointer data) +{ + g_main_loop_quit(mainloop); + return FALSE; +} + +int +main (int argc, char ** argv) +{ + GError * error = NULL; + + g_type_init(); + + DBusGConnection * connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); + g_debug("DBus ID: %s", dbus_connection_get_server_id(dbus_g_connection_get_connection(dbus_g_bus_get(DBUS_BUS_SESSION, NULL)))); + + DBusGProxy * bus_proxy = dbus_g_proxy_new_for_name(connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); + guint nameret = 0; + + if (!org_freedesktop_DBus_request_name(bus_proxy, "org.dbusmenu.test", 0, &nameret, &error)) { + g_error("Unable to call to request name"); + return 1; + } + + if (nameret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { + g_error("Unable to get name"); + return 1; + } + + DbusmenuServer * server = dbusmenu_server_new("/org/test"); + + DbusmenuMenuitem * root = dbusmenu_json_build_from_file(argv[1]); + g_return_val_if_fail(root!=NULL, 1); + + dbusmenu_server_set_root(server, root); + + g_timeout_add(10000, timer_func, NULL); + + mainloop = g_main_loop_new(NULL, FALSE); + g_main_loop_run(mainloop); + + g_debug("Quiting"); + + return 0; +} diff --git a/tools/Makefile.am b/tools/Makefile.am index ab7a598..48993f1 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -10,11 +10,14 @@ dbusmenu_dumper_SOURCES = \ dbusmenu_dumper_CFLAGS = \ -I $(srcdir)/.. \ - $(DBUSMENUGLIB_CFLAGS) $(DBUSMENUDUMPER_CFLAGS) -Wall -Werror + $(DBUSMENUGLIB_CFLAGS) \ + $(DBUSMENUDUMPER_CFLAGS) \ + -Wall -Werror dbusmenu_dumper_LDADD = \ ../libdbusmenu-glib/libdbusmenu-glib.la \ - $(DBUSMENUGLIB_LIBS) $(DBUSMENUDUMPER_LIBS) + $(DBUSMENUGLIB_LIBS) \ + $(DBUSMENUDUMPER_LIBS) doc_DATA = README.dbusmenu-bench diff --git a/tools/dbusmenu-dumper.c b/tools/dbusmenu-dumper.c index 82ca5c1..40ab1e1 100644 --- a/tools/dbusmenu-dumper.c +++ b/tools/dbusmenu-dumper.c @@ -30,10 +30,111 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include <libdbusmenu-glib/client.h> #include <libdbusmenu-glib/menuitem.h> +#include <dbus/dbus-gtype-specialized.h> #include <X11/Xlib.h> static GMainLoop * mainloop = NULL; +static gchar * value2string (const GValue * value, int depth); + +static gchar * +strv_dumper(const GValue * value) +{ + gchar ** strv = (gchar **)g_value_get_boxed(value); + + gchar * joined = g_strjoinv("\", \"", strv); + gchar * retval = g_strdup_printf("[\"%s\"]", joined); + g_free(joined); + return retval; +} + +typedef struct _collection_iterator_t collection_iterator_t; +struct _collection_iterator_t { + gchar * space; + GPtrArray * array; + gboolean first; + int depth; +}; + +static void +collection_iterate (const GValue * value, gpointer user_data) +{ + collection_iterator_t * iter = (collection_iterator_t *)user_data; + + gchar * str = value2string(value, iter->depth); + gchar * retval = NULL; + + if (iter->first) { + iter->first = FALSE; + retval = g_strdup_printf("\n%s%s", iter->space, str); + } else { + retval = g_strdup_printf(",\n%s%s", iter->space, str); + } + + g_ptr_array_add(iter->array, retval); + g_free(str); + + return; +} + +static gchar * +collection_dumper (const GValue * value, int depth) +{ + gchar * space = g_strnfill(depth, ' '); + GPtrArray * array = g_ptr_array_new_with_free_func(g_free); + + g_ptr_array_add(array, g_strdup("[")); + + collection_iterator_t iter; + iter.space = space; + iter.array = array; + iter.first = TRUE; + iter.depth = depth + 2; + + dbus_g_type_collection_value_iterate(value, collection_iterate, &iter); + + g_ptr_array_add(array, g_strdup_printf("\n%s]", space)); + + g_free(space); + + gchar * retstr = NULL; + if (array->len == 3) { + retstr = g_strdup_printf("[%s]", ((gchar *)array->pdata[1]) + depth + 1/*for newline*/); + } else { + retstr = g_strjoinv(NULL, (gchar **)array->pdata); + } + + g_ptr_array_free(array, TRUE); + + return retstr; +} + +static gchar * +value2string (const GValue * value, int depth) +{ + gchar * str = NULL; + + if (value == NULL) { + return g_strdup("(null)"); + } + + if (dbus_g_type_is_collection(G_VALUE_TYPE(value))) { + str = collection_dumper(value, depth); + } else if (G_VALUE_TYPE(value) == G_TYPE_STRV) { + str = strv_dumper(value); + } else if (G_VALUE_TYPE(value) == G_TYPE_BOOLEAN) { + if (g_value_get_boolean(value)) { + str = g_strdup("true"); + } else { + str = g_strdup("false"); + } + } else { + str = g_strdup_value_contents(value); + } + + return str; +} + static void print_menuitem (DbusmenuMenuitem * item, int depth) { @@ -43,11 +144,10 @@ print_menuitem (DbusmenuMenuitem * item, int depth) GList * properties = dbusmenu_menuitem_properties_list(item); GList * property; for (property = properties; property != NULL; property = g_list_next(property)) { - GValue value = {0}; - g_value_init(&value, G_TYPE_STRING); - g_value_transform(dbusmenu_menuitem_property_get_value(item, (gchar *)property->data), &value); - g_print(",\n%s\"%s\": \"%s\"", space, (gchar *)property->data, g_value_get_string(&value)); - g_value_unset(&value); + const GValue * value = dbusmenu_menuitem_property_get_value(item, (gchar *)property->data); + gchar * str = value2string(value, depth + g_utf8_strlen((gchar *)property->data, -1) + 2 /*quotes*/ + 2 /*: */); + g_print(",\n%s\"%s\": %s", space, (gchar *)property->data, str); + g_free(str); } g_list_free(properties); |