WM <--> panel protocol



Hi Havoc,
	For a while now we've been talking about moving the panel's global
keybindings out of the panel and into the window manager in an effort to
rid us of one more point of keybindings clashes.

	I've hacked up a simple ClientMessage based protocol and implemented it
for metacity. Attached is the gnome-panel and metacity patches and a
short spec.

	Thoughts, comments etc. welcome.

Good Luck,
Mark.
_GNOME_DOCK_ACTION Protocol

  The _GNOME_DOCK_ACTION WM_PROTOCOL is a simple mechanism
  whereby the window manager may invoke one of a number of
  actions on a DOCK type toplevel window (as advertised by
  the _NET_WM_WINDOW_TYPE hint).

   type = ClientMessage
   window = the DOCK window
   message_type = WM_PROTOCOLS
   format = 32
   data.l[0] = _GNOME_DOCK_ACTION
   data.l[1] = timestamp
   data.l[2] = action

  A DOCK window willing to participate in this protocol
  SHOULD list _GNOME_DOCK_ACTION in the WM_PROTOCOLS
  property of the window.

  On receipt of this message the client MAY invoke an
  action as indicated by the message. Unsupported actions
  may safely be ingored.

  Possible action atoms are:

    _GNOME_DOCK_ACTION_MAIN_MENU, ATOM
    _GNOME_DOCK_ACTION_RUN_DIALOG, ATOM
    _GNOME_DOCK_ACTION_SCREENSHOT, ATOM
    _GNOME_DOCK_ACTION_WINDOW_SCREENSHOT, ATOM
Index: delete.c
===================================================================
RCS file: /cvs/gnome/metacity/src/delete.c,v
retrieving revision 1.5
diff -u -p -r1.5 delete.c
--- delete.c	8 Dec 2002 19:17:17 -0000	1.5
+++ delete.c	10 Feb 2003 04:54:51 -0000
@@ -360,7 +360,8 @@ meta_window_delete (MetaWindow  *window,
                   window->desc);
       meta_window_send_icccm_message (window,
                                       window->display->atom_wm_delete_window,
-                                      timestamp);
+                                      timestamp,
+                                      NULL);
     }
   else
     {
Index: display.c
===================================================================
RCS file: /cvs/gnome/metacity/src/display.c,v
retrieving revision 1.177
diff -u -p -r1.177 display.c
--- display.c	28 Jan 2003 15:07:43 -0000	1.177
+++ display.c	10 Feb 2003 04:55:00 -0000
@@ -266,7 +266,12 @@ meta_display_open (const char *name)
     "_NET_STARTUP_ID",
     "_METACITY_TOGGLE_VERBOSE",
     "_METACITY_UPDATE_COUNTER",
-    "SYNC_COUNTER"
+    "SYNC_COUNTER",
+    "_GNOME_DOCK_ACTION",
+    "_GNOME_DOCK_ACTION_MAIN_MENU",
+    "_GNOME_DOCK_ACTION_RUN_DIALOG",
+    "_GNOME_DOCK_ACTION_SCREENSHOT",
+    "_GNOME_DOCK_ACTION_WINDOW_SCREENSHOT"
   };
   Atom atoms[G_N_ELEMENTS(atom_names)];
   
@@ -406,6 +411,11 @@ meta_display_open (const char *name)
   display->atom_metacity_toggle_verbose = atoms[78];
   display->atom_metacity_update_counter = atoms[79];
   display->atom_sync_counter = atoms[80];
+  display->atom_gnome_dock_action = atoms[81];
+  display->atom_gnome_dock_action_main_menu = atoms[82];
+  display->atom_gnome_dock_action_run_dialog = atoms[83];
+  display->atom_gnome_dock_action_screenshot = atoms[84];
+  display->atom_gnome_dock_action_window_screenshot = atoms[85];
   
   display->prop_hooks = NULL;
   meta_display_init_window_prop_hooks (display);
@@ -3279,11 +3289,13 @@ meta_display_ping_window (MetaDisplay   
 {
   MetaPingData *ping_data;
 
+#if 0
   if (timestamp == CurrentTime)
     {
       meta_warning ("Tried to ping a window with CurrentTime! Not allowed.\n");
       return;
     }
+#endif
 
   if (!window->net_wm_ping)
     {
@@ -3311,7 +3323,8 @@ meta_display_ping_window (MetaDisplay   
               timestamp, window->desc);
   meta_window_send_icccm_message (window,
 				  display->atom_net_wm_ping,
-				  timestamp);
+				  timestamp,
+                                  NULL);
 }
 
 /* process the pong from our ping */
Index: display.h
===================================================================
RCS file: /cvs/gnome/metacity/src/display.h,v
retrieving revision 1.98
diff -u -p -r1.98 display.h
--- display.h	28 Jan 2003 15:07:43 -0000	1.98
+++ display.h	10 Feb 2003 04:55:02 -0000
@@ -169,6 +169,11 @@ struct _MetaDisplay
   Atom atom_metacity_toggle_verbose;
   Atom atom_metacity_update_counter;
   Atom atom_sync_counter;
+  Atom atom_gnome_dock_action;
+  Atom atom_gnome_dock_action_main_menu;
+  Atom atom_gnome_dock_action_run_dialog;
+  Atom atom_gnome_dock_action_screenshot;
+  Atom atom_gnome_dock_action_window_screenshot;
   
   /* This is the actual window from focus events,
    * not the one we last set
Index: keybindings.c
===================================================================
RCS file: /cvs/gnome/metacity/src/keybindings.c,v
retrieving revision 1.76
diff -u -p -r1.76 keybindings.c
--- keybindings.c	21 Jan 2003 22:40:25 -0000	1.76
+++ keybindings.c	10 Feb 2003 04:55:07 -0000
@@ -79,6 +79,11 @@ static void handle_toggle_desktop     (M
                                        MetaWindow     *window,
                                        XEvent         *event,
                                        MetaKeyBinding *binding);
+static void handle_panel_keybinding   (MetaDisplay    *display,
+                                       MetaScreen     *screen,
+                                       MetaWindow     *window,
+                                       XEvent         *event,
+                                       MetaKeyBinding *binding);
 static void handle_toggle_maximize    (MetaDisplay    *display,
                                        MetaScreen     *screen,
                                        MetaWindow     *window,
@@ -265,6 +270,14 @@ static const MetaKeyHandler screen_handl
     GINT_TO_POINTER (META_TAB_LIST_DOCKS) },  
   { META_KEYBINDING_SHOW_DESKTOP, handle_toggle_desktop,
     NULL },
+  { META_KEYBINDING_PANEL_MAIN_MENU, handle_panel_keybinding,
+    GINT_TO_POINTER (META_KEYBINDING_ACTION_PANEL_MAIN_MENU) },
+  { META_KEYBINDING_PANEL_RUN_DIALOG, handle_panel_keybinding,
+    GINT_TO_POINTER (META_KEYBINDING_ACTION_PANEL_RUN_DIALOG) },
+  { META_KEYBINDING_PANEL_SCREENSHOT, handle_panel_keybinding,
+    GINT_TO_POINTER (META_KEYBINDING_ACTION_PANEL_SCREENSHOT) },
+  { META_KEYBINDING_PANEL_WINDOW_SCREENSHOT, handle_panel_keybinding,
+    GINT_TO_POINTER (META_KEYBINDING_ACTION_PANEL_WINDOW_SCREENSHOT) },
   { META_KEYBINDING_COMMAND_1, handle_run_command,
     GINT_TO_POINTER (0) },
   { META_KEYBINDING_COMMAND_2, handle_run_command,
@@ -1017,6 +1030,14 @@ meta_window_grab_keys (MetaWindow  *wind
 {
   if (window->all_keys_grabbed)
     return;
+
+  if (window->type == META_WINDOW_DOCK)
+    {
+      if (window->keys_grabbed)
+        ungrab_all_keys (window->display, window->xwindow);
+      window->keys_grabbed = FALSE;
+      return;
+    }
   
   if (window->keys_grabbed)
     {
@@ -2514,6 +2535,68 @@ handle_toggle_desktop (MetaDisplay    *d
     meta_screen_unshow_desktop (screen);
   else
     meta_screen_show_desktop (screen);
+}
+
+static void
+handle_panel_keybinding (MetaDisplay    *display,
+                         MetaScreen     *screen,
+                         MetaWindow     *window,
+                         XEvent         *event,
+                         MetaKeyBinding *binding)
+{
+  MetaKeyBindingAction action;
+  Atom action_atom;
+  MetaWindow *dock_window;
+  GList *windows, *tmp;
+  long message_data[3] = {0, 0, 0};
+  
+  action = GPOINTER_TO_INT (binding->handler->data);
+
+  action_atom = None;
+  switch (action)
+    {
+    case META_KEYBINDING_ACTION_PANEL_MAIN_MENU:
+      action_atom = display->atom_gnome_dock_action_main_menu;
+      break;
+    case META_KEYBINDING_ACTION_PANEL_RUN_DIALOG:
+      action_atom = display->atom_gnome_dock_action_run_dialog;
+      break;
+    case META_KEYBINDING_ACTION_PANEL_SCREENSHOT:
+      action_atom = display->atom_gnome_dock_action_screenshot;
+      break;
+    case META_KEYBINDING_ACTION_PANEL_WINDOW_SCREENSHOT:
+      action_atom = display->atom_gnome_dock_action_window_screenshot;
+      break;
+    default:
+      return;
+    }
+
+  windows = meta_stack_list_windows (screen->stack, NULL);
+
+  dock_window = NULL;
+  tmp = windows;
+  while (tmp)
+    {
+      MetaWindow *window = tmp->data;
+
+      if (window->screen == screen &&
+          window->type == META_WINDOW_DOCK &&
+          window->gnome_dock_action)
+        {
+          dock_window = window;
+          break;
+        }
+
+      tmp = tmp->next;
+    }
+
+  message_data [0] = action_atom;
+
+  if (dock_window)
+    meta_window_send_icccm_message (dock_window,
+                                    display->atom_gnome_dock_action,
+                                    event->xkey.time,
+                                    message_data);
 }
 
 static void
Index: metacity.schemas.in
===================================================================
RCS file: /cvs/gnome/metacity/src/metacity.schemas.in,v
retrieving revision 1.26
diff -u -p -r1.26 metacity.schemas.in
--- metacity.schemas.in	31 Jan 2003 03:57:01 -0000	1.26
+++ metacity.schemas.in	10 Feb 2003 04:55:11 -0000
@@ -1600,6 +1600,100 @@ you set
     </schema>
 
     <schema>
+      <key>/schemas/apps/metacity/global_keybindings/panel_main_menu</key>
+      <applyto>/apps/metacity/global_keybindings/panel_main_menu</applyto>
+      <owner>metacity</owner>
+      <type>string</type>
+      <default>&lt;Alt&gt;F1</default>
+      <locale name="C">
+         <short>Show the panel menu</short>
+         <long>
+          The keybinding which shows the panel's main menu.
+
+          The format looks like "&lt;Control&gt;a" or
+          "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+          The parser is fairly liberal and allows lower or upper case,
+          and also abbreviations such as "&lt;Ctl&gt;" and
+          "&lt;Ctrl&gt;". If you set the option to the special string
+          "disabled", then there will be no keybinding for this
+          action.
+         </long>
+      </locale>
+    </schema>
+
+    <schema>
+      <key>/schemas/apps/metacity/global_keybindings/panel_run_dialog</key>
+      <applyto>/apps/metacity/global_keybindings/panel_run_dialog</applyto>
+      <owner>metacity</owner>
+      <type>string</type>
+      <default>&lt;Alt&gt;F2</default>
+      <locale name="C">
+         <short>Show the panel run dialog</short>
+         <long>
+          The keybinding which display's the panel's "Run Program" dialog
+          box.
+
+          The format looks like "&lt;Control&gt;a" or
+          "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+          The parser is fairly liberal and allows lower or upper case,
+          and also abbreviations such as "&lt;Ctl&gt;" and
+          "&lt;Ctrl&gt;". If you set the option to the special string
+          "disabled", then there will be no keybinding for this
+          action.
+         </long>
+      </locale>
+    </schema>
+
+    <schema>
+      <key>/schemas/apps/metacity/global_keybindings/panel_screenshot</key>
+      <applyto>/apps/metacity/global_keybindings/panel_screenshot</applyto>
+      <owner>metacity</owner>
+      <type>string</type>
+      <default>Print</default>
+      <locale name="C">
+         <short>Take a screenshot</short>
+         <long>
+          The keybinding which invokes the panel's screenshot utility.
+
+          The format looks like "&lt;Control&gt;a" or
+          "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+          The parser is fairly liberal and allows lower or upper case,
+          and also abbreviations such as "&lt;Ctl&gt;" and
+          "&lt;Ctrl&gt;". If you set the option to the special string
+          "disabled", then there will be no keybinding for this
+          action.
+         </long>
+      </locale>
+    </schema>
+
+    <schema>
+      <key>/schemas/apps/metacity/global_keybindings/panel_window_screenshot</key>
+      <applyto>/apps/metacity/global_keybindings/panel_window_screenshot</applyto>
+      <owner>metacity</owner>
+      <type>string</type>
+      <default>&lt;Alt&gt;Print</default>
+      <locale name="C">
+         <short>Take a screenshot of a window</short>
+         <long>
+          The keybinding which invokes the panel's screenshot utility
+          to take a screenshot of a window.
+
+          The format looks like "&lt;Control&gt;a" or
+          "&lt;Shift&gt;&lt;Alt&gt;F1.
+
+          The parser is fairly liberal and allows lower or upper case,
+          and also abbreviations such as "&lt;Ctl&gt;" and
+          "&lt;Ctrl&gt;". If you set the option to the special string
+          "disabled", then there will be no keybinding for this
+          action.
+         </long>
+      </locale>
+    </schema>
+
+    <schema>
       <key>/schemas/apps/metacity/global_keybindings/run_command</key>
       <applyto>/apps/metacity/global_keybindings/run_command_1</applyto>
       <applyto>/apps/metacity/global_keybindings/run_command_2</applyto>
Index: prefs.c
===================================================================
RCS file: /cvs/gnome/metacity/src/prefs.c,v
retrieving revision 1.40
diff -u -p -r1.40 prefs.c
--- prefs.c	28 Jan 2003 15:07:43 -0000	1.40
+++ prefs.c	10 Feb 2003 04:55:15 -0000
@@ -1363,6 +1363,10 @@ static MetaKeyPref screen_bindings[] = {
   { META_KEYBINDING_CYCLE_PANELS, 0, 0 },
   { META_KEYBINDING_CYCLE_PANELS_BACKWARD, 0, 0 },
   { META_KEYBINDING_SHOW_DESKTOP, 0, 0 },
+  { META_KEYBINDING_PANEL_MAIN_MENU, 0, 0 },
+  { META_KEYBINDING_PANEL_RUN_DIALOG, 0, 0 },
+  { META_KEYBINDING_PANEL_SCREENSHOT, 0, 0 },
+  { META_KEYBINDING_PANEL_WINDOW_SCREENSHOT, 0, 0 },
   { META_KEYBINDING_COMMAND_1, 0, 0 },
   { META_KEYBINDING_COMMAND_2, 0, 0 },
   { META_KEYBINDING_COMMAND_3, 0, 0 },
Index: prefs.h
===================================================================
RCS file: /cvs/gnome/metacity/src/prefs.h,v
retrieving revision 1.29
diff -u -p -r1.29 prefs.h
--- prefs.h	28 Jan 2003 15:07:43 -0000	1.29
+++ prefs.h	10 Feb 2003 04:55:15 -0000
@@ -109,6 +109,10 @@ void        meta_prefs_change_workspace_
 #define META_KEYBINDING_CYCLE_PANELS             "cycle_panels"
 #define META_KEYBINDING_CYCLE_PANELS_BACKWARD    "cycle_panels_backward"
 #define META_KEYBINDING_SHOW_DESKTOP             "show_desktop"
+#define META_KEYBINDING_PANEL_MAIN_MENU          "panel_main_menu"
+#define META_KEYBINDING_PANEL_RUN_DIALOG         "panel_run_dialog"
+#define META_KEYBINDING_PANEL_SCREENSHOT         "panel_screenshot"
+#define META_KEYBINDING_PANEL_WINDOW_SCREENSHOT  "panel_window_screenshot"
 #define META_KEYBINDING_COMMAND_1                "run_command_1"
 #define META_KEYBINDING_COMMAND_2                "run_command_2"
 #define META_KEYBINDING_COMMAND_3                "run_command_3"
@@ -204,6 +208,10 @@ typedef enum _MetaKeyBindingAction
   META_KEYBINDING_ACTION_CYCLE_PANELS,
   META_KEYBINDING_ACTION_CYCLE_PANELS_BACKWARD,
   META_KEYBINDING_ACTION_SHOW_DESKTOP,
+  META_KEYBINDING_ACTION_PANEL_MAIN_MENU,
+  META_KEYBINDING_ACTION_PANEL_RUN_DIALOG,
+  META_KEYBINDING_ACTION_PANEL_SCREENSHOT,
+  META_KEYBINDING_ACTION_PANEL_WINDOW_SCREENSHOT,
   META_KEYBINDING_ACTION_COMMAND_1,
   META_KEYBINDING_ACTION_COMMAND_2,
   META_KEYBINDING_ACTION_COMMAND_3,
Index: window.c
===================================================================
RCS file: /cvs/gnome/metacity/src/window.c,v
retrieving revision 1.264
diff -u -p -r1.264 window.c
--- window.c	25 Jan 2003 16:58:43 -0000	1.264
+++ window.c	10 Feb 2003 04:55:42 -0000
@@ -3103,7 +3103,8 @@ meta_window_focus (MetaWindow  *window,
                       window->desc);
           meta_window_send_icccm_message (window,
                                           window->display->atom_wm_take_focus,
-                                          timestamp);
+                                          timestamp,
+                                          NULL);
           window->display->expected_focus_window = window;
         }
       
@@ -3267,7 +3268,8 @@ meta_window_lower (MetaWindow  *window)
 void
 meta_window_send_icccm_message (MetaWindow *window,
                                 Atom        atom,
-                                Time        timestamp)
+                                Time        timestamp,
+                                long        extra_data[3])
 {
   /* This comment and code are from twm, copyright
    * Open Group, Evans & Sutherland, etc.
@@ -3294,6 +3296,13 @@ meta_window_send_icccm_message (MetaWind
     ev.data.l[0] = atom;
     ev.data.l[1] = timestamp;
 
+    if (extra_data != NULL)
+      {
+        ev.data.l[2] = extra_data [0];
+        ev.data.l[3] = extra_data [1];
+        ev.data.l[4] = extra_data [2];
+      }
+
     meta_error_trap_push (window->display);
     XSendEvent (window->display->xdisplay,
                 window->xwindow, False, 0, (XEvent*) &ev);
@@ -4491,6 +4500,7 @@ update_protocols (MetaWindow *window)
   window->take_focus = FALSE;
   window->delete_window = FALSE;
   window->net_wm_ping = FALSE;
+  window->gnome_dock_action = FALSE;
   
   meta_error_trap_push (window->display);  
   
@@ -4508,6 +4518,8 @@ update_protocols (MetaWindow *window)
             window->delete_window = TRUE;
           else if (protocols[i] == window->display->atom_net_wm_ping)
             window->net_wm_ping = TRUE;
+          else if (protocols[i] == window->display->atom_gnome_dock_action)
+            window->gnome_dock_action = TRUE;
           ++i;
         }
 
@@ -5366,6 +5378,8 @@ recalc_window_type (MetaWindow *window)
       
       /* update stacking constraints */
       meta_window_update_layer (window);
+
+      meta_window_grab_keys (window);
     }
 }
 
Index: window.h
===================================================================
RCS file: /cvs/gnome/metacity/src/window.h,v
retrieving revision 1.82
diff -u -p -r1.82 window.h
--- window.h	5 Jan 2003 07:51:02 -0000	1.82
+++ window.h	10 Feb 2003 04:55:44 -0000
@@ -131,6 +131,7 @@ struct _MetaWindow
   guint take_focus : 1;
   guint delete_window : 1;
   guint net_wm_ping : 1;
+  guint gnome_dock_action : 1;
   /* Globally active / No input */
   guint input : 1;
   
@@ -379,7 +380,8 @@ void        meta_window_update_unfocused
 /* Sends a client message */
 void meta_window_send_icccm_message (MetaWindow *window,
                                      Atom        atom,
-                                     Time        timestamp);
+                                     Time        timestamp,
+                                     long        extra_data[3]);
 
 
 gboolean meta_window_configure_request (MetaWindow *window,
Index: Makefile.am
===================================================================
RCS file: /cvs/gnome/gnome-panel/gnome-panel/Makefile.am,v
retrieving revision 1.307
diff -u -p -r1.307 Makefile.am
--- Makefile.am	12 Jan 2003 04:08:46 -0000	1.307
+++ Makefile.am	10 Feb 2003 05:01:08 -0000
@@ -119,7 +119,6 @@ panel_sources =			\
 	panel-config-global.c  	\
 	panel-util.c		\
 	panel-gconf.c		\
-	global-keys.c		\
 	panel-config.c  	\
 	distribution.c		\
 	gnome-run.c  		\
@@ -139,6 +138,7 @@ panel_sources =			\
 	panel-menu-bar.c        \
 	panel-recent.c		\
 	panel-gdk-pixbuf-extensions.c \
+	panel-dock-actions.c	\
 	$(EGG_RECENT_FILES_C)	\
 	$(NULL)
 
@@ -163,7 +163,6 @@ panel_headers =			\
 	applet.h         	\
 	drawer.h  		\
 	panel-util.h		\
-	global-keys.h		\
 	panel-config.h		\
 	panel-config-global.h  	\
 	panel-gconf.h		\
@@ -184,6 +183,7 @@ panel_headers =			\
 	panel-menu-bar.h        \
 	panel-recent.h		\
 	panel-gdk-pixbuf-extensions.h \
+	panel-dock-actions.h	\
 	$(EGG_RECENT_FILES_H)	\
 	$(NULL)
 
Index: basep-widget.c
===================================================================
RCS file: /cvs/gnome/gnome-panel/gnome-panel/basep-widget.c,v
retrieving revision 1.193
diff -u -p -r1.193 basep-widget.c
--- basep-widget.c	12 Jan 2003 04:08:46 -0000	1.193
+++ basep-widget.c	10 Feb 2003 05:01:17 -0000
@@ -28,6 +28,7 @@
 #include "panel-typebuiltins.h"
 #include "panel-gconf.h"
 #include "panel-stock-icons.h"
+#include "panel-dock-actions.h"
 
 extern GSList *panel_list;
 
@@ -1488,6 +1489,8 @@ basep_widget_update_winhints (BasePWidge
 
 	xstuff_set_wmspec_dock_hints (w->window,
 				      (basep->mode == BASEP_AUTO_HIDE));
+
+	panel_dock_actions_set_window_hint (w->window);
 
 	/* FIXME: non-compliance should be tested! */
 
Index: global-keys.c
===================================================================
RCS file: global-keys.c
diff -N global-keys.c
--- global-keys.c	21 Jan 2003 08:45:37 -0000	1.38
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,371 +0,0 @@
-#include <config.h>
-
-#include <X11/keysym.h>
-#include <gdk/gdkx.h>
-#include <gdk/gdk.h>
-
-#include <libgnome/libgnome.h>
-
-#include "global-keys.h"
-
-#include "applet.h"
-#include "gnome-run.h"
-#include "panel.h"
-#include "menu.h"
-#include "panel-util.h"
-#include "egg-screen-exec.h"
-#include "eggaccelerators.h"
-#include "xstuff.h"
-
-extern GlobalConfig global_config;
-extern GSList *panels;
-
-#define N_BITS 32 /*all modifier masks fit into it */
-
-typedef struct {
-	guint mods;
-	guint key;
-} ModAndKey;
-typedef void (*BitsCallback) (guint value, ModAndKey *mod_and_key);
-
-static guint
-get_ignored_mods (void)
-{
-  guint ignored_mods;
-
-  ignored_mods = 0;
-  egg_keymap_resolve_virtual_modifiers (gdk_keymap_get_default (),
-                                        EGG_VIRTUAL_NUM_LOCK_MASK |
-                                        EGG_VIRTUAL_SCROLL_LOCK_MASK,
-                                        &ignored_mods);
-
-  return ignored_mods;
-}
-
-static void
-all_combinations (guint mask_to_traverse,
-		  BitsCallback callback,
-		  ModAndKey *mod_and_key)
-{
-	int indexes[N_BITS];/*indexes of bits we need to flip*/
-	int i, bit, bits_set_cnt;
-	int uppervalue;
-
-	bit = 0;
-	for (i = 0; i < N_BITS; i++) {
-		if (mask_to_traverse & (1<<i))
-			indexes[bit++]=i;
-	}
-
-	bits_set_cnt = bit;
-
-	uppervalue = 1<<bits_set_cnt;
-	for (i = 0; i < uppervalue; i++) {
-		int j, result = 0;
-
-		for (j = 0; j < bits_set_cnt; j++) {
-			if (i & (1<<j))
-				result |= (1<<indexes[j]);
-		}
-		callback (result, mod_and_key);
-	}
-}
-
-static void
-do_grab_key (guint mod, ModAndKey* data)
-{
-	xstuff_grab_key_on_all_screens (data->key, (mod | data->mods), TRUE);
-}
-
-static void
-grab_key (guint mod, guint key)
-{
-	ModAndKey data;
-        guint ignored_mods;
-        int other_mods;
-
-        ignored_mods = get_ignored_mods ();
-        
-        other_mods = ignored_mods & ~mod;
-    
-	data.mods = mod;
-        data.key = key;
-    
-	all_combinations (other_mods, do_grab_key, &data);
-}
-
-static void
-do_ungrab_key (guint mod, ModAndKey* data)
-{
-	xstuff_grab_key_on_all_screens (data->key, (mod | data->mods), FALSE);
-}
-
-static void 
-ungrab_key (guint mod,guint key)
-{
-	ModAndKey data;
-        guint ignored_mods;
-        int other_mods;
-
-        /* FIXME this is broken as the modifiers may have changed
-         * between the grab and the ungrab.
-         */
-        ignored_mods = get_ignored_mods ();
-        
-        other_mods = ignored_mods & ~mod;
-    
-	data.mods = mod;
-	data.key = key;
-    
-	all_combinations(other_mods, do_ungrab_key, &data);
-}
-
-void
-panel_global_keys_setup (void)
-{
-	static guint lastkey_menu = 0;
-	static guint laststate_menu = 0;
-	static guint lastkey_run = 0;
-	static guint laststate_run = 0;
-	static guint lastkey_screenshot = 0;
-	static guint laststate_screenshot = 0;
-	static guint lastkey_window_screenshot = 0;
-	static guint laststate_window_screenshot = 0;
-
-	/* FIXME: the if trees are horrible, this shoul dbe cleaned up with
-	 * lists or something */
-
-	gdk_error_trap_push();
-	if (lastkey_menu != 0) {
-		ungrab_key (laststate_menu, lastkey_menu);
-	}
-	if (lastkey_run != 0 &&
-	    (lastkey_menu != lastkey_run ||
-	     laststate_menu != laststate_run)) {
-		ungrab_key (laststate_run, lastkey_run);
-	}
-	if (lastkey_run != 0 &&
-	    (lastkey_menu != lastkey_screenshot ||
-	     laststate_menu != laststate_screenshot) &&
-	    (lastkey_run != lastkey_screenshot ||
-	     laststate_run != laststate_screenshot)) {
-		ungrab_key (laststate_screenshot, lastkey_screenshot);
-	}
-	if (lastkey_run != 0 &&
-	    (lastkey_menu != lastkey_window_screenshot ||
-	     laststate_menu != laststate_window_screenshot) &&
-	    (lastkey_run != lastkey_window_screenshot ||
-	     laststate_run != laststate_window_screenshot) &&
-	    (lastkey_screenshot != lastkey_window_screenshot ||
-	     laststate_screenshot != laststate_window_screenshot)) {
-		ungrab_key (laststate_window_screenshot,
-			    lastkey_window_screenshot);
-	}
-	
-	if (global_config.keys_enabled && 
-	    global_config.menu_key.keysym) {
-		lastkey_menu = XKeysymToKeycode(GDK_DISPLAY(),
-						global_config.menu_key.keysym);
-		laststate_menu = global_config.menu_key.state;
-		if (lastkey_menu != 0)
-			grab_key (laststate_menu, lastkey_menu);
-	} else {
-		lastkey_menu = 0;
-	}
-
-	if (global_config.keys_enabled && 
-	    global_config.run_key.keysym) {
-		lastkey_run = XKeysymToKeycode (GDK_DISPLAY (),
-						global_config.run_key.keysym);
-		laststate_run = global_config.run_key.state;
-		if (lastkey_run != 0 &&
-		    (lastkey_menu != lastkey_run ||
-		     laststate_menu != laststate_run))
-			grab_key (laststate_run, lastkey_run);
-	} else {
-		lastkey_run = 0;
-	}
-
-	if (global_config.keys_enabled && 
-	    global_config.screenshot_key.keysym) {
-		lastkey_screenshot = XKeysymToKeycode
-			(GDK_DISPLAY (), global_config.screenshot_key.keysym);
-		laststate_screenshot = global_config.screenshot_key.state;
-		if (lastkey_screenshot != 0 &&
-		    (lastkey_menu != lastkey_screenshot ||
-		     laststate_menu != laststate_screenshot) &&
-		    (lastkey_run != lastkey_screenshot ||
-		     laststate_run != laststate_screenshot))
-			grab_key (laststate_screenshot, lastkey_screenshot);
-	} else {
-		lastkey_screenshot = 0;
-	}
-
-	if (global_config.keys_enabled && 
-	    global_config.window_screenshot_key.keysym) {
-		lastkey_window_screenshot = XKeysymToKeycode
-			(GDK_DISPLAY (), global_config.window_screenshot_key.keysym);
-		laststate_window_screenshot = global_config.window_screenshot_key.state;
-		if (lastkey_window_screenshot != 0 &&
-		    (lastkey_menu != lastkey_window_screenshot ||
-		     laststate_menu != laststate_window_screenshot) &&
-		    (lastkey_run != lastkey_window_screenshot ||
-		     laststate_run != laststate_window_screenshot) &&
-		    (lastkey_screenshot != lastkey_window_screenshot ||
-		     laststate_screenshot != laststate_window_screenshot))
-			grab_key (laststate_window_screenshot,
-				  lastkey_window_screenshot);
-	} else {
-		lastkey_window_screenshot = 0;
-	}
-
-	gdk_flush ();
-	gdk_error_trap_pop();
-}
-
-static gboolean
-check_for_grabs (void)
-{
-	if (gdk_pointer_grab (gdk_get_default_root_window (), FALSE, 
-			      0, NULL, NULL, GDK_CURRENT_TIME)
-	    != GrabSuccess) {
-		return TRUE;
-	} else {
-		gdk_pointer_ungrab (GDK_CURRENT_TIME);
-		return FALSE;
-	}
-}
-
-GdkFilterReturn
-panel_global_keys_filter (GdkXEvent *gdk_xevent,
-			  GdkEvent  *event,
-			  GdkScreen *screen)
-{
-	XEvent *xevent = (XEvent *)gdk_xevent;
-	guint keycode, state;
-	guint menu_keycode, menu_state;
-	guint run_keycode, run_state;
-	guint screenshot_keycode, screenshot_state;
-	guint window_screenshot_keycode, window_screenshot_state;
-        guint ignored_mods;
-
-	g_return_val_if_fail (GDK_IS_SCREEN (screen), GDK_FILTER_CONTINUE);
-        
-	if(xevent->type != KeyPress)
-		return GDK_FILTER_CONTINUE;
-
-        ignored_mods = get_ignored_mods ();
-        
-	keycode = xevent->xkey.keycode;
-	state = xevent->xkey.state;
-
-	menu_keycode = XKeysymToKeycode (GDK_DISPLAY (),
-					 global_config.menu_key.keysym);
-	menu_state = global_config.menu_key.state;
-
-	run_keycode = XKeysymToKeycode (GDK_DISPLAY (),
-					global_config.run_key.keysym);
-	run_state = global_config.run_key.state;
-
-	screenshot_keycode = XKeysymToKeycode (GDK_DISPLAY (),
-					       global_config.screenshot_key.keysym);
-	screenshot_state = global_config.screenshot_key.state;
-
-	window_screenshot_keycode =
-		XKeysymToKeycode (GDK_DISPLAY (),
-				  global_config.window_screenshot_key.keysym);
-	window_screenshot_state = global_config.window_screenshot_key.state;
-
-	if (keycode == menu_keycode &&
-	    (state & (~ignored_mods)) == menu_state) {
-		PanelWidget *panel_widget;
-		GtkWidget   *panel;
-		GtkWidget   *menu;
-
-		/* check if anybody else has a grab */
-		if (check_for_grabs ())
-			return GDK_FILTER_CONTINUE;
-
-		panel_widget = panels->data;
-		menu = create_panel_root_menu (panel_widget);
-		panel = panel_widget->panel_parent;
-
-		BASEP_WIDGET (panel)->autohide_inhibit = TRUE;
-		basep_widget_autohide (BASEP_WIDGET (panel));
-
-		gtk_menu_set_screen (GTK_MENU (menu), screen);
-		gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
-				NULL, NULL, 0, GDK_CURRENT_TIME);
-		return GDK_FILTER_REMOVE;
-	} else if (keycode == run_keycode &&
-		   (state & (~ignored_mods)) == run_state) {
-		/* check if anybody else has a grab */
-		if (check_for_grabs ()) {
-			return GDK_FILTER_CONTINUE;
-		}
-
-		show_run_dialog (screen);
-		return GDK_FILTER_REMOVE;
-	} else if (keycode == screenshot_keycode &&
-		   (state & (~ignored_mods)) == screenshot_state) {
-		char *argv [2];
-		char *proggie;
-
-		/* check if anybody else has a grab */
-		if (check_for_grabs ()) {
-			return GDK_FILTER_CONTINUE;
-		}
-
-		proggie = g_find_program_in_path  ("gnome-panel-screenshot");
-		if (proggie == NULL) {
-			panel_error_dialog (
-				screen,
-				"cannot_find_ss_program",
-				_("Can't find the screenshot program"));
-			return GDK_FILTER_REMOVE;
-		}
-		argv[0] = proggie;
-		argv[1] = NULL;
-
-		if (egg_screen_execute_async (screen, g_get_home_dir (), 1, argv) < 0)
-			panel_error_dialog (screen,
-					    "cannot_exec_ss_program",
-					    _("Can't execute the screenshot program"));
-
-		g_free (proggie);
-
-		return GDK_FILTER_REMOVE;
-	} else if (keycode == window_screenshot_keycode &&
-		   (state & (~ignored_mods)) == window_screenshot_state) {
-		char *argv [3];
-		char *proggie;
-
-		/* check if anybody else has a grab */
-		if (check_for_grabs ()) {
-			return GDK_FILTER_CONTINUE;
-		}
-
-		proggie = g_find_program_in_path  ("gnome-panel-screenshot");
-		if (proggie == NULL) {
-			panel_error_dialog (
-				screen,
-				"cannot_find_ss_program",
-				_("Can't find the screenshot program"));
-			return GDK_FILTER_REMOVE;
-		}
-		argv[0] = proggie;
-		argv[1] = "--window";
-		argv[2] = NULL;
-
-		if (egg_screen_execute_async (screen, g_get_home_dir (), 2, argv) < 0)
-			panel_error_dialog (screen,
-					    "cannot_exec_ss_program",
-					    _("Can't execute the screenshot program"));
-
-		g_free (proggie);
-
-		return GDK_FILTER_REMOVE;
-	}
-
-	return GDK_FILTER_CONTINUE;
-}
Index: global-keys.h
===================================================================
RCS file: global-keys.h
diff -N global-keys.h
--- global-keys.h	6 Oct 2002 22:52:37 -0000	1.5
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,16 +0,0 @@
-#ifndef GLOBAL_KEYS_H
-#define GLOBAL_KEYS_H 1    
-
-/* WTF are these doing here */
-/*#define XK_LEFT_WIN 115
-#define XK_RIGHT_WIN 116
-#define XK_RIGHT_MENU 117*/
-
-#include <gdk/gdktypes.h>
-
-void		panel_global_keys_setup	 (void);
-GdkFilterReturn	panel_global_keys_filter (GdkXEvent *gdk_xevent,
-					  GdkEvent  *event,
-				          GdkScreen *screen);
-
-#endif
Index: main.c
===================================================================
RCS file: /cvs/gnome/gnome-panel/gnome-panel/main.c,v
retrieving revision 1.330
diff -u -p -r1.330 main.c
--- main.c	10 Jan 2003 01:19:51 -0000	1.330
+++ main.c	10 Feb 2003 05:01:17 -0000
@@ -30,7 +30,7 @@
 #include "session.h"
 #include "xstuff.h"
 #include "panel-stock-icons.h"
-#include "global-keys.h"
+#include "panel-dock-actions.h"
 
 extern int config_sync_timeout;
 
@@ -191,7 +191,7 @@ main(int argc, char **argv)
 
 	panel_tooltips = gtk_tooltips_new ();
 
-	xstuff_init ((GdkFilterFunc) panel_global_keys_filter);
+	panel_dock_actions_init ();
 	multiscreen_init ();
 	panel_init_stock_icons_and_items ();
 
Index: panel-dock-actions.c
===================================================================
RCS file: panel-dock-actions.c
diff -N panel-dock-actions.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ panel-dock-actions.c	10 Feb 2003 05:01:33 -0000
@@ -0,0 +1,206 @@
+/*
+ * panel-dock-actions.h: _GNOME_DOCK_ACTIONS protocol impl.
+ *
+ * Copyright (C) 2003 Sun Microsystems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Authors:
+ *	Mark McLoughlin <mark skynet ie>
+ */
+
+#include <config.h>
+
+#include "panel-dock-actions.h"
+
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <X11/Xlib.h>
+#include <libgnome/gnome-i18n.h>
+
+#include "gnome-run.h"
+#include "menu.h"
+#include "basep-widget.h"
+#include "panel-util.h"
+#include "egg-screen-exec.h"
+
+static Atom atom_wm_protocols                        = None;
+static Atom atom_gnome_dock_action                   = None;
+static Atom atom_gnome_dock_action_main_menu         = None;
+static Atom atom_gnome_dock_action_run_dialog        = None;
+static Atom atom_gnome_dock_action_screenshot        = None;
+static Atom atom_gnome_dock_action_window_screenshot = None;
+
+extern GSList *panels;
+
+void
+panel_dock_actions_set_window_hint (GdkWindow *window)
+{
+	Window  xwindow;
+	Status  status;
+	Atom   *existing_protocols = NULL;
+	Atom   *new_protocols;
+	int     n_atoms;
+	int     i;
+
+	g_return_if_fail (atom_gnome_dock_action != None);
+
+	xwindow = gdk_x11_drawable_get_xid (window);
+
+	gdk_error_trap_push ();
+	status = XGetWMProtocols (gdk_display, xwindow,
+				  &existing_protocols, &n_atoms);
+	if (gdk_error_trap_pop ())
+		return;
+
+	if (!status || !n_atoms)
+		n_atoms = 1;
+	else
+		n_atoms++;
+
+	new_protocols = g_new (Atom, n_atoms);
+	new_protocols [0] = atom_gnome_dock_action;
+
+	for (i = 1; i < n_atoms; i++)
+		new_protocols [i] = existing_protocols [i + 1];
+
+	if (existing_protocols)
+		XFree (existing_protocols);
+
+	gdk_error_trap_push ();
+	status = XSetWMProtocols (gdk_display, xwindow, new_protocols, n_atoms);
+	gdk_error_trap_pop ();
+
+	g_free (new_protocols);
+}
+
+static void
+panel_dock_actions_main_menu (GdkScreen *screen)
+{
+	PanelWidget *panel_widget;
+	GtkWidget   *panel;
+	GtkWidget   *menu;
+
+	panel_widget = panels->data;
+	menu = create_panel_root_menu (panel_widget);
+	panel = panel_widget->panel_parent;
+
+	BASEP_WIDGET (panel)->autohide_inhibit = TRUE;
+	basep_widget_autohide (BASEP_WIDGET (panel));
+
+	gtk_menu_set_screen (GTK_MENU (menu), screen);
+	gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 0, GDK_CURRENT_TIME);
+}
+
+static void
+panel_dock_actions_run_dialog (GdkScreen *screen)
+{
+	show_run_dialog (screen);
+}
+
+static void
+panel_dock_actions_screenshot (GdkScreen *screen,
+			       gboolean   window_only)
+{
+	char *argv [3];
+	char *proggie;
+
+	proggie = g_find_program_in_path  ("gnome-panel-screenshot");
+	if (!proggie) {
+		panel_error_dialog (screen,
+				    "cannot_find_ss_program",
+				    _("Can't find the screenshot program"));
+		return;
+	}
+
+	argv [0] = proggie;
+	argv [1] = window_only ? "--window" : NULL;
+	argv [2] = NULL;
+
+	if (egg_screen_execute_async (screen, g_get_home_dir (), 2, argv) < 0)
+		panel_error_dialog (screen,
+				    "cannot_exec_ss_program",
+				    _("Can't execute the screenshot program"));
+
+	g_free (proggie);
+}
+
+static GdkFilterReturn
+panel_dock_actions_filter (GdkXEvent *gdk_xevent,
+			   GdkEvent  *event,
+			   gpointer   data)
+{
+	GdkScreen *screen;
+	GdkWindow *window;
+	XEvent    *xevent = (XEvent *) gdk_xevent;
+
+	if (xevent->type != ClientMessage)
+		return GDK_FILTER_CONTINUE;
+
+	if (xevent->xclient.message_type != atom_wm_protocols)
+		return GDK_FILTER_CONTINUE;
+
+	if (xevent->xclient.data.l [0] != atom_gnome_dock_action)
+		return GDK_FILTER_CONTINUE;
+
+	window = gdk_window_lookup_for_display (
+			gdk_display_get_default (), xevent->xclient.window);
+	if (!window)
+		return GDK_FILTER_CONTINUE;
+
+	screen = gdk_drawable_get_screen (window);
+
+	if (xevent->xclient.data.l [2] == atom_gnome_dock_action_main_menu)
+		panel_dock_actions_main_menu (screen);
+	else if (xevent->xclient.data.l [2] == atom_gnome_dock_action_run_dialog)
+		panel_dock_actions_run_dialog (screen);
+	else if (xevent->xclient.data.l [2] == atom_gnome_dock_action_screenshot)
+		panel_dock_actions_screenshot (screen, FALSE);
+	else if (xevent->xclient.data.l [2] == atom_gnome_dock_action_window_screenshot)
+		panel_dock_actions_screenshot (screen, TRUE);
+	else
+		return GDK_FILTER_CONTINUE;
+
+	return GDK_FILTER_REMOVE;
+}
+
+void
+panel_dock_actions_init (void)
+{
+	GdkDisplay *display;
+	GdkAtom     gdk_atom_wm_protocols;
+
+	display = gdk_display_get_default ();
+
+	gdk_atom_wm_protocols =
+		gdk_atom_intern ("WM_PROTOCOLS", FALSE);
+
+	atom_wm_protocols =
+		XInternAtom (gdk_display, "WM_PROTOCOLS", TRUE);
+	atom_gnome_dock_action =
+		XInternAtom (gdk_display, "_GNOME_DOCK_ACTION", FALSE);
+	atom_gnome_dock_action_main_menu =
+		XInternAtom (gdk_display, "_GNOME_DOCK_ACTION_MAIN_MENU", FALSE);
+	atom_gnome_dock_action_run_dialog =
+		XInternAtom (gdk_display, "_GNOME_DOCK_ACTION_RUN_DIALOG", FALSE);
+	atom_gnome_dock_action_screenshot =
+		XInternAtom (gdk_display, "_GNOME_DOCK_ACTION_SCREENSHOT", FALSE);
+	atom_gnome_dock_action_window_screenshot =
+		XInternAtom (gdk_display, "_GNOME_DOCK_ACTION_WINDOW_SCREENSHOT", FALSE);
+
+	gdk_display_add_client_message_filter (
+		display, gdk_atom_wm_protocols, panel_dock_actions_filter, NULL);
+}
Index: panel-dock-actions.h
===================================================================
RCS file: panel-dock-actions.h
diff -N panel-dock-actions.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ panel-dock-actions.h	10 Feb 2003 05:01:33 -0000
@@ -0,0 +1,38 @@
+/*
+ * panel-dock-actions.h: _GNOME_DOCK_ACTIONS protocol impl.
+ *
+ * Copyright (C) 2003 Sun Microsystems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Authors:
+ *	Mark McLoughlin <mark skynet ie>
+ */
+
+#ifndef __PANEL_DOCK_ACTIONS_H__
+#define __PANEL_DOCK_ACTIONS_H__
+
+#include <glib/gmacros.h>
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+void panel_dock_actions_init            (void);
+void panel_dock_actions_set_window_hint (GdkWindow *window);
+
+G_END_DECLS
+
+#endif /* __PANEL_DOCK_ACTIONS_H__ */
Index: panel.c
===================================================================
RCS file: /cvs/gnome/gnome-panel/gnome-panel/panel.c,v
retrieving revision 1.502
diff -u -p -r1.502 panel.c
--- panel.c	31 Jan 2003 04:03:50 -0000	1.502
+++ panel.c	10 Feb 2003 05:01:44 -0000
@@ -2002,10 +2002,7 @@ panel_apply_global_config (void)
 
 		basep_update_frame (BASEP_WIDGET (pd->panel));
 	}
-
-	panel_global_keys_setup ();
 }
-
 
 static GtkWidget *
 panel_load_edge_panel_from_gconf (const char          *profile,
Index: xstuff.c
===================================================================
RCS file: /cvs/gnome/gnome-panel/gnome-panel/xstuff.c,v
retrieving revision 1.61
diff -u -p -r1.61 xstuff.c
--- xstuff.c	21 Jan 2003 08:45:37 -0000	1.61
+++ xstuff.c	10 Feb 2003 05:01:45 -0000
@@ -312,26 +312,6 @@ xstuff_delete_property (GdkWindow *windo
 			 panel_atom_get (name));
 }
 
-void
-xstuff_init (GdkFilterFunc keys_filter)
-{
-	GdkDisplay *display;
-	int         screens, i;
-
-	display = gdk_display_get_default ();
-	screens = gdk_display_get_n_screens (display);
-
-	for (i = 0; i < screens; i++) {
-		GdkScreen *screen;
-		GdkWindow *root_window;
-
-		screen = gdk_display_get_screen (display, i);
-		root_window = gdk_screen_get_root_window (screen);
-
-		gdk_window_add_filter (root_window, keys_filter, screen);
-	}
-}
-
 /* Zoom animation */
 #define MINIATURIZE_ANIMATION_FRAMES_Z   1
 #define MINIATURIZE_ANIMATION_STEPS_Z    6
Index: xstuff.h
===================================================================
RCS file: /cvs/gnome/gnome-panel/gnome-panel/xstuff.h,v
retrieving revision 1.27
diff -u -p -r1.27 xstuff.h
--- xstuff.h	21 Jan 2003 08:45:37 -0000	1.27
+++ xstuff.h	10 Feb 2003 05:01:46 -0000
@@ -4,7 +4,6 @@
 #include <gdk/gdk.h>
 #include <gtk/gtkwidget.h>
 
-void xstuff_init			(GdkFilterFunc keys_filter);
 void xstuff_delete_property		(GdkWindow *window,
 					 const char *name);
 gboolean xstuff_is_compliant_wm		(void);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]