Commit 6e30f6eb authored by Alberts Muktupāvels's avatar Alberts Muktupāvels

Revert "remove old libpanel-applet documentation"

This reverts commit cdd562fb.
parent d2057776
......@@ -5,6 +5,7 @@ SUBDIRS = \
modules \
gnome-panel \
libpanel-applet \
doc \
docs \
help \
data \
......@@ -268,6 +268,10 @@ AC_CONFIG_FILES([
SUBDIRS = reference
panel-session-handling.txt \
-include $(top_srcdir)/
The _GNOME_PANEL_ACTION is a simple mechanism whereby an
application window invoke one of a number of simple
actions which will be handled by the GNOME panel. This
protocol is intended to be used by window managers who
provide keybindings for these actions.
To invoke an action the application sends the following
ClientMessage to the root window of the screen on which
the keybinding was activated:
type = ClientMessage
window = the root window
message_type = _GNOME_PANEL_ACTION
format = 32
data.l[0] = action
data.l[1] = timestamp
Possible action atoms are:
Unsupported actions are ignored by the panel.
This note describes areas where implementation of keynav for panels was
- PanelWidget and objects on the panel such as launchers and applets need to
be focusable
Both the PanelWidget and objects on the panel need to be focusable in order
to invoke the context menu using only the keyboard. In the normal course of
things, GTK+ does not support a widget and its children be focusable.
Instead of requiring the PanelWidget be focusable we have introduced a key
binding Ctrl+F10 which pops up the panel's context menu. So a PanelWidget
is focusable only when it does not have any children. There is, therefore,
no need for the key binding Ctrl+Tab to move the focus to the PanelWidget from
an applet or a launcher.
The function panel_widget_real_focus is PanelWidget's default signal
handler for focus signal. This function is called when either PanelWidget
or a child has focus and Tab or arrow keys are used to move focus. If the
PanelWidget has focus and the PanelWidget has children the GTK_CAN_FOCUS flag
is unset so that a child can receive focus.
- An applet with a tooltip receives focus
If an applet has a tooltip, the applet will receive focus so that the tooltip
can be displayed, even if the applet contains focusable widgets. The
focusable widgets in the applet can be traversed using the arrow keys.
- Tab should move focus from within an applet to the next object on the panel
This is implemented by defining an action signal "move_focus_out_of_applet"
on PanelApplet and binding Tab and Shift+Tab to this action.
When focus is in an applet the event is passed to the focus widget then its
children until a toplevel is reached unless the event is handled. This is
done in gtk_window_key_press_event(). The original implemementation for
"move_focus_out_of_applet" had the action signal defined on PanelAppletFrame
but as a GtkSocket always reports a key press event as being handled when
the GtkPlug is in a different process, the event has not passed to the
The implementation for "moving_focus_out_of_applet" sets a flag
moving_focus_out so that the function panel_applet_focus() which is
PanelApplet's default signal handler for focus signal will not attempt to
move the focus within the applet if this flag is set.
- Implementing key bindings
If focus is in an applet which is in another process, the GtkSocket will
report the key stroke as having been handled. This means that key bindings
will not be activated. The workaround for this is to handle those key
strokes in panel_event() a signal handler for the event signal in panel.c.
However, we only want to handle some keybindings, for example we do not want
to handle Shift+F10, which displays the context menu, and Ctrl+F1, which
displays the tooltip, but we do want to handle Ctrl+F10 which displays the
panel's context menu.
- Focus indication
We need a mechanism that will make visible which panel has focus. We also
need to do this without impacting current behaviour.
We set the state of a PanelWidget to GTK_STATE_SELECTED whan focus is in a
PanelWidget. We provide a default panel rc file gnome-panelrc, which is
installed in $(datadir). This rc file sets the default default color for
SELECTED for any widget which is a descended from a PanelWidget or
PanelApplet to be the same as the NORMAL colour.
If there is a requirement to make panel focus indication visible, the
following lines added to ~/.gtkrc-2.0 will make a selected panel prelight
style "prelight-selected"
fg[SELECTED] = { 0, 0, 0 }
bg[SELECTED] = { 0xea60, 0xea60, 0xea60 }
widget_class "*PanelWidget*" style "prelight-selected"
widget_class "*PanelApplet*" style "prelight-selected"
Panel session/configuration handling
(Please read the session-management docs in porting-docs before
reading this)
Panel global configuration
All the panel configuration options that are not per panel are stored
in GConf in the /apps/panel/global folder. There is a schema for it,
and sysadms can override the defaults by changing the defaults in the
default database.
It will look like this
Panel Profiles
All the per-panel setup is stored in named profiles. Initially the
"Default" profile is created for you, and if you never create a new
profile everything seems to the user just like profiles don't exist.
The profiles contain all the per-panel settings and the per-applet
Each profile stores it's configuration in GConf in a separate prefix,
like this:
When a new profile is created it's content is copied from a default
profile choosen depending on the screen size. The defaults are stored
in /apps/panel/default-profiles, like this:
These are delivered in a serialized fashion in gnome-core, and the (to
be written by hp) gconf deserialization app is used to install
them at make install/package install time. Then the sysadmin can
change these as he sees fit. I can imagine a "make current profile be
default" button somewhere.
[ This is a area where opinions differ.
The active profile can typically be changed by the user any time
using a popdown menu or suchlike. (Just imagine selecting a new
profile and all the panels will go swooosh and pop up in their
new places with different applets and stuff.)
The name of the active profile is always the same as the current
gsm named session.
Per-Session Data
NOTE: This section only applies to alex version aboce. In _vicious_
version, there would be no real per-session data, just the session name.
The only per-session data saved by the panel is which profile it
uses. In general per-session data should only be trivial things that
the user won't be mad when(if?) he loses. According to hp's
session-management docs in the porting-docs:
This can all be kind of a pain, so apps are encouraged to
save all their state as part of the command they pass to the
session manager, and avoid saving persistent files. That is, it's
easier and more robust to have a command line option
--with-window-count=3 than it is to store the window count in GConf under
and provide a discard command to clear that key.
It seems unnecessary to store the panel per session data in GConf, so
we would just store the command line saved to the session manager as
"--profile=Laptop" (replace laptop by name of active profile). This
way we won't have problems cleaning up GConf either.
Per-Panel configuration
The panel profile data would looks something like this:
/33214/ ...
/apps/panel/profile/Laptop/applets/43234/applet_type (oaf id?)
/prefs/ <- This is where the applet itself
stores it's per-instance prefs.
/56378/ ...
This means that the panel profile configuration data is a list
of panels with unique ids, that has per panel settings, and a list of
applets with unique ids (applets may move between panels, and need to
keep their prefs, so they are not in the panel subfolder).
Each applet folder also have a "prefs" folder
(e.g. /apps/panel/profile/Laptop/applets/43234/prefs/) which is used by the
applet to store it's per instance data.
Applet Prefs
An applet has two sorts of preferences, per-instance and global. The
per-instace perferences are options that may be different for each
instance of the applet (such as number of rows in the pager), while
the global preferences are preferences that are shared by all running
applets of that type (and even non-running ones in different
profiles). Examples of global preferences may be tooltip timeouts, or
in deskguide the number of windows in a class before grouping starts.
It is important that the preferences ui for the applet separates the
global and the per-instance settings in some way, so users do not get
totally confused about what is applied to all instances and what is not.
Global applet preferences are managed entierly by the applet, and is
normally stored in GConf in a key such as:
Global settings have normal GConf behaviour, and the applet should
install a schema for them.
Per-instance preferences are private to the applet. You should write
schemas for them for good measure, but currently GConf doesn't handle
dynamic keys well, so they will not be installed. In the future this
will be fixed though. The keys are private anyway, so not having
schemas does not matter that much, since other apps should not modify
them (and can't find them since they are dynamic and prefixed with
strange id's).
When the panel instantiates an applet (first time or not) it will give
the applet a GConf prefix (see above) for it to read and write it's
per-instance configuration from. Since there is no way currently to
have schemas for these dynamic prefixes there won't be any default
values for the applet settings. Thus we have to hardcode the settings
in the applet.
So the way to read prefs changes slightly. You have to try reading,
and if there is no data in gconf, use the default value. The way to
use this is to call gconf_client_get(), which return NULL if the value
is unset and has no default (this means it will automagically work
whenever we implement dynamic prefix schemas).
We should probably wrap the gconf calls in some utility functions like
applet_gconf_get_int_with_default (SomeAppletType *applet,
const gchar* key,
gint default,
GError** err)
GError* error = NULL;
GConfValue* val;
GConfClient *client = panel_gconf_get_client ();
gchar *full_key;
g_return_val_if_fail(err == NULL || *err == NULL, 0);
full_key = applet_get_full_key (applet, key);
val = get(client, full_key, TRUE, NULL, NULL, &error);
g_free (full_key);
if (val != NULL)
gint retval = def;
g_assert(error == NULL);
if (check_type(key, val, GCONF_VALUE_INT, &error))
retval = gconf_value_get_int(val);
handle_error(client, error, err);
return retval;
return default;
And the applet would use this like this
#define TOOLTIP_TIMEOUT_DEFAULT 100 /* msec */
timeout = applet_gconf_get_int_with_default ("tooltip_timeout", TOOLTIP_TIMEOUT_DEFAULT, NULL);
It is important that we have actual defines for the defaults, so as to
not repeat the problems we had previously, with different defaults in
different places.
Session Manager interaction
[NOTE: Only applies to alex version, _vicious_ one doesn't even need this ]
The panels responds to the SaveYourself request, but does not need to
propagate this request to the applets, since the applet settings are
stored per-instance-in-a-profile, and not in a session. This makes
things robust (won't lose applet setup), and easier to understand for
the user.
The only thing the panel needs to do on SaveSetup is to pass the
command line containing the active profile "--profile=Laptop" to the
session manager. There are no GConf cleanup needed, or no session id
thrown about at all.
Full example GConf tree
/apps/panel/profile/Default/applets/62568/prefs/ ...
/apps/panel/profile/Default/applets/43355/prefs/ ...
/apps/panel/profile/Coding/ ...
/apps/panel/profile/Gaming/ ..
/apps/panel/default-profiles/small/ (panels and applets)
/apps/panel/default-profiles/medium/ (panels and applets)
/apps/panel/default-profiles/large/ (panels and applets)
* Things which need discussion
+ New toplevel behaviour
+ Toplevel keybindings
+ Configuration
+ GConf usage
New toplevel behaviour
There are some mildly controversial changes in the panel
behaviour with the new toplevel widget.
1) Autohiding hides into the corner of the screen. This change
was recommended by the usability team based on the fact the
unhiding the panel isn't any harder - you just throw the
mouse into the corner of the screen - but it makes
operations near the edge of the screen a lot less error
prone - previously you had to be careful not to go near the
hidden panel.
2) GTK+ stock arrows on the hide buttons. I went for these
instead of using the previous pixmaps because it makes
theming easier and the default stock arrows are actually a
lot clearer, IMHO.
3) Grab handle on floating panels with no hide buttons.
Discussed before - previously there was no way to access
the panel context menu on a floating panel. I'd imagine
some people will cry "ugly", but I haven't seen a better
suggestion yet.
4) Hiding a floating panel using the hide buttons makes the
panel hide to the edge of the screen rather than just
resizing into a button. Originally the reason I did this
was temporary - currently the panel animations only allow
moving the panel, not resizing it - but I've come to prefer
the behaviour.
5) Floating panels now snap to the edge, corner and center (at
the edge) of the screen. I think this makes sense, but
maybe the snap region at 20 pixels is too big.
6) You can rotate a floating panel with the mouse by holding
down Ctrl when moving it with the mouse.
7) You can resize the panel by clicking on the edge and
dragging. Note, that you can change the width (height for
vertical panels) of floating panels. The idea is that
floating panels are "packed". I think this is a sensible
I think that's about it. I'd encourage people to check out the
"new-toplevel" branch (don't install it, just run it from the source
dir - it doesn't recognise your preferences) and experiment with the
behaviour before commenting.
Panel toplevel keybindings
The new toplevel widget currently binds some of metacity's
window keybindings to similar functions on the panel.
+ activate_window_menu: popup the panel context menu. Same
thing as Ctrl-F10.
+ toggle_maximized: toggle between expanded/un-expanded.
+ maximize: expand the panel.
+ unmaximize: un-expand the panel.
+ toggle_shaded: toggle the panel between hidden/un-hidden. If
you have autohide enabled this does autohiding type
behaviour, otherwise its does hiding in a similar way to
doing it with the hide buttons.
+ begin_move:
+ begin_resize: move/resize the panel in similar ways to the
way you can move/resize windows using the keyboard with
So there's a few questions about this:
1) Does it make sense to overload the window keybindings with
similar functions on panels. It may lead to user confusion,
but I think it will just make learning the panel bindings
easier and also free us of the burden of coming up with new
key sequences for these operations.
2) Are the activate_window_menu and toggle_shaded bindings
similar enough to popping up the context menu and hiding
the panel similar enough to warrant the overloading. I
think the others definetly make sense.
3) Are there any other operations which would benefit from
keybindings like this. They don't neccessarily need to have
equivalent ones in metacity.
4) We're tying ourselves closely here to metacity. Maybe we
should only do this if metacity is running (this is what
the keybindings dialog does).
To test this out with the "new-toplevel" branch you need the
attached patch for metacity.
GConf Usage
We made a litany of mistakes when we did the porting from
gnome-config to GConf for 2.0:
1) We use schemas for the default setup in a very dubious way.
As a side effect it is extremely awkward to change the
default panel setup.
2) We came up with the idea of panel "profiles" but never
exposed it in the interface and didn't add the ability to
switch between profiles.
3) Panel doesn't respond to GConf notifications
4) Using huge long internal identifiers for for panels and
applets which makes it very hard to grok the panel's
gconf tree.
5) Various little mistakes like storing a bitfield as an ints
6) Not all changes are written to gconf immediately, there's
still some weird remenants that I don't fully understand of
saving configuration on receipt of SaveYourself and various
global timeouts for saving all the panel configuration.
7) Saving the configuration to GConf on startup even though
nothing has changed.
So, clearly 3, 4, 5, 6, and 7 are pretty obvious things to
fix. Some of them will take a fair bit of work to fix, but there's no
arguments on what the behaviour should be.
(1) is pretty tough to figure out what should be done.
Currently the panel does the following:
+ Installs a set of "schemas" into /schemas/apps/panel/default-profiles
which really is just the default configuration tree. e.g. we
install schemas like:
when clearly we should have a single schema:
which is then applied to the keys:
The default specified in the schema should just be the
default size when you create a new panel and so we need a
seperate place to get the information that "the default
panel setup should have a 32 pixel wide panel on the top and
a 24 pixel wide panel on the bottom".
The most sensible solution to this is that the default panel
setup should get installed into the defaults database. This
could be done in a number of ways:
* Use a gconftool script which would write the default setup
to the defaults database. It would look something like:
export GCONF_CONFIG_SOURCE='xml:readwrite:/usr/etc/gconf/gconf.xml.defaults'
gconftool-2 --direct
-s /apps/panel/profiles/default/panels/00001/size -t int 32
gconftool-2 --direct
-s /apps/panel/profiles/default/panels/00002/size -t int 24
* Come up with a homegrown file format for describing a the
default panel setup and write a simple program for parsing
it and installing it into the defaults database. It might
look something like:
<toplevel id="top_menu_panel">
<name>Top Menu Panel</name>
<background type="plain"/>
<applet iid="">
<object type="">
* Come up with a new GConf file format which
--makefile-install-rule would handle just like the .schemas
file. This file format would effectively be a gconf script
<value type="int" key="/apps/panel/profiles/default/panels/0001/size">24</value>
<value type="int" key="/apps/panel/profiles/default/panels/0002/size">32</value>
Because of profiles and needing to be able to use the default
setup on newly available screens, the default setup needs to always be
available, so we would actually need to be able to install these
defaults in somewhere like
so that we can copy it everytime we start a new profile or
find that we've logged into a machine with a screen with no panels
configured for it.
(2) is something else which needs to be decided upon. The
original idea behind them was for session management. You could have a
different panel setups for different purposes. I've just read over
gnome-panel/doc/panel-session-handling.txt and reminded myself of what
this was all about.
Alex wanted something similar to gnome-terminal AFAIK, you
could switch between profiles at runtime, create new profiles etc. If
you save your session, the current profile you are using is saved so
you use this profile every time you log in to that session.
George wanted to have the current profile to be decided by the
current session name - you basically have a profile for each session.
Thinking about it, I prefer George's approach (even though I'd
completely forgotten about it).
Alternatively, we could forget the whole idea of session
management with the panel. All your configuration is global and is the
same for all sessions.
libpanel-applet \
-include $(top_srcdir)/
# The name of the module, e.g. 'glib'.
DOC_MODULE = libpanel-applet
# Uncomment for versioned docs and specify the version of the module, e.g. '2'.
# The top-level XML file.
# Directories containing the source code.
# gtk-doc will search all .c and .h files beneath these paths
# for inline comments documenting functions and macros.
# e.g. DOC_SOURCE_DIR=$(top_srcdir)/gtk $(top_srcdir)/gdk
DOC_SOURCE_DIR = $(top_srcdir)/libpanel-applet
# Extra options to pass to gtkdoc-scangobj. Normally not needed.
# Extra options to supply to gtkdoc-scan.
# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
SCAN_OPTIONS = --rebuild-types
# Extra options to supply to gtkdoc-mkdb
# e.g. MKDB_OPTIONS=--xml-mode --output-format=xml
MKDB_OPTIONS = --xml-mode --output-format=xml
# Extra options to supply to gtkdoc-mkhtml
# Extra options to supply to gtkdoc-fixref. Normally not needed.
# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
# 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)/libpanel-applet/*.h
CFILE_GLOB = $(top_srcdir)/libpanel-applet/*.c
# Extra header to include when scanning, which are not under DOC_SOURCE_DIR
# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h
# Header files or dirs to ignore when scanning. Use base file/dir names
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code
panel-applet-bindings.h \
panel-applet-enums.h \
panel-applet-factory.h \
panel-applet-private.h \
# Images to copy into HTML directory.
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
add_to_panel.png \
# Extra files that are included by $(DOC_MAIN_SGML_FILE).
# e.g. content_files=running.xml building.xml changes-2.0.xml
content_files =
# Files where gtk-doc abbrevations (#GtkWidget) are expanded
# e.g. expand_content_files=running.xml
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. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
-I$(top_srcdir)/libpanel-applet \
-I$(top_builddir)/libpanel-applet \
$(top_builddir)/libpanel-applet/ \
# This includes the standard gtk-doc make rules, copied by gtkdocize.
include $(top_srcdir)/gtk-doc.make
# Comment this out if you want 'make check' to test you doc status
# and run some sanity checks
SRCDIR=$(abs_srcdir) BUILDDIR=$(abs_builddir)
-include $(top_srcdir)/
This diff is collapsed.
<TITLE>Panel Applet</TITLE>