source: trunk/third/gnome-panel/gnome-panel/global-keys.c @ 18631

Revision 18631, 9.8 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18630, which included commits to RCS files with non-trunk default branches.
Line 
1#include <config.h>
2
3#include <X11/keysym.h>
4#include <gdk/gdkx.h>
5#include <gdk/gdk.h>
6
7#include <libgnome/libgnome.h>
8
9#include "global-keys.h"
10
11#include "applet.h"
12#include "foobar-widget.h"
13#include "gnome-run.h"
14#include "panel.h"
15#include "menu.h"
16#include "panel-util.h"
17#include "egg-screen-exec.h"
18#include "eggaccelerators.h"
19
20extern GlobalConfig global_config;
21extern GSList *panels;
22
23#define N_BITS 32 /*all modifier masks fit into it */
24
25typedef struct {
26        guint mods;
27        guint key;
28} ModAndKey;
29typedef void (*BitsCallback) (guint value, ModAndKey *mod_and_key);
30
31static guint
32get_ignored_mods (void)
33{
34  guint ignored_mods;
35
36  ignored_mods = 0;
37  egg_keymap_resolve_virtual_modifiers (gdk_keymap_get_default (),
38                                        EGG_VIRTUAL_NUM_LOCK_MASK |
39                                        EGG_VIRTUAL_SCROLL_LOCK_MASK,
40                                        &ignored_mods);
41
42  return ignored_mods;
43}
44
45static void
46all_combinations (guint mask_to_traverse,
47                  BitsCallback callback,
48                  ModAndKey *mod_and_key)
49{
50        int indexes[N_BITS];/*indexes of bits we need to flip*/
51        int i, bit, bits_set_cnt;
52        int uppervalue;
53
54        bit = 0;
55        for (i = 0; i < N_BITS; i++) {
56                if (mask_to_traverse & (1<<i))
57                        indexes[bit++]=i;
58        }
59
60        bits_set_cnt = bit;
61
62        uppervalue = 1<<bits_set_cnt;
63        for (i = 0; i < uppervalue; i++) {
64                int j, result = 0;
65
66                for (j = 0; j < bits_set_cnt; j++) {
67                        if (i & (1<<j))
68                                result |= (1<<indexes[j]);
69                }
70                callback (result, mod_and_key);
71        }
72}
73
74static void
75do_grab_key (guint mod, ModAndKey* data)
76{
77        XGrabKey (GDK_DISPLAY(), data->key, (mod | data->mods),
78                  GDK_ROOT_WINDOW(), True, GrabModeAsync, GrabModeAsync);
79}
80
81static void
82grab_key (guint mod, guint key)
83{
84        ModAndKey data;
85        guint ignored_mods;
86        int other_mods;
87
88        ignored_mods = get_ignored_mods ();
89       
90        other_mods = ignored_mods & ~mod;
91   
92        data.mods = mod;
93        data.key = key;
94   
95        all_combinations (other_mods, do_grab_key, &data);
96}
97
98static void
99do_ungrab_key (guint mod, ModAndKey* data)
100{
101        XUngrabKey(GDK_DISPLAY(), data->key, (mod | data->mods),
102                   GDK_ROOT_WINDOW());
103}
104
105static void
106ungrab_key (guint mod,guint key)
107{
108        ModAndKey data;
109        guint ignored_mods;
110        int other_mods;
111
112        /* FIXME this is broken as the modifiers may have changed
113         * between the grab and the ungrab.
114         */
115        ignored_mods = get_ignored_mods ();
116       
117        other_mods = ignored_mods & ~mod;
118   
119        data.mods = mod;
120        data.key = key;
121   
122        all_combinations(other_mods, do_ungrab_key, &data);
123}
124
125void
126panel_global_keys_setup (void)
127{
128        static guint lastkey_menu = 0;
129        static guint laststate_menu = 0;
130        static guint lastkey_run = 0;
131        static guint laststate_run = 0;
132        static guint lastkey_screenshot = 0;
133        static guint laststate_screenshot = 0;
134        static guint lastkey_window_screenshot = 0;
135        static guint laststate_window_screenshot = 0;
136
137        /* FIXME: the if trees are horrible, this shoul dbe cleaned up with
138         * lists or something */
139
140        gdk_error_trap_push();
141        if (lastkey_menu != 0) {
142                ungrab_key (laststate_menu, lastkey_menu);
143        }
144        if (lastkey_run != 0 &&
145            (lastkey_menu != lastkey_run ||
146             laststate_menu != laststate_run)) {
147                ungrab_key (laststate_run, lastkey_run);
148        }
149        if (lastkey_run != 0 &&
150            (lastkey_menu != lastkey_screenshot ||
151             laststate_menu != laststate_screenshot) &&
152            (lastkey_run != lastkey_screenshot ||
153             laststate_run != laststate_screenshot)) {
154                ungrab_key (laststate_screenshot, lastkey_screenshot);
155        }
156        if (lastkey_run != 0 &&
157            (lastkey_menu != lastkey_window_screenshot ||
158             laststate_menu != laststate_window_screenshot) &&
159            (lastkey_run != lastkey_window_screenshot ||
160             laststate_run != laststate_window_screenshot) &&
161            (lastkey_screenshot != lastkey_window_screenshot ||
162             laststate_screenshot != laststate_window_screenshot)) {
163                ungrab_key (laststate_window_screenshot,
164                            lastkey_window_screenshot);
165        }
166       
167        if (global_config.keys_enabled &&
168            global_config.menu_key.keysym) {
169                lastkey_menu = XKeysymToKeycode(GDK_DISPLAY(),
170                                                global_config.menu_key.keysym);
171                laststate_menu = global_config.menu_key.state;
172                if (lastkey_menu != 0)
173                        grab_key (laststate_menu, lastkey_menu);
174        } else {
175                lastkey_menu = 0;
176        }
177
178        if (global_config.keys_enabled &&
179            global_config.run_key.keysym) {
180                lastkey_run = XKeysymToKeycode (GDK_DISPLAY (),
181                                                global_config.run_key.keysym);
182                laststate_run = global_config.run_key.state;
183                if (lastkey_run != 0 &&
184                    (lastkey_menu != lastkey_run ||
185                     laststate_menu != laststate_run))
186                        grab_key (laststate_run, lastkey_run);
187        } else {
188                lastkey_run = 0;
189        }
190
191        if (global_config.keys_enabled &&
192            global_config.screenshot_key.keysym) {
193                lastkey_screenshot = XKeysymToKeycode
194                        (GDK_DISPLAY (), global_config.screenshot_key.keysym);
195                laststate_screenshot = global_config.screenshot_key.state;
196                if (lastkey_screenshot != 0 &&
197                    (lastkey_menu != lastkey_screenshot ||
198                     laststate_menu != laststate_screenshot) &&
199                    (lastkey_run != lastkey_screenshot ||
200                     laststate_run != laststate_screenshot))
201                        grab_key (laststate_screenshot, lastkey_screenshot);
202        } else {
203                lastkey_screenshot = 0;
204        }
205
206        if (global_config.keys_enabled &&
207            global_config.window_screenshot_key.keysym) {
208                lastkey_window_screenshot = XKeysymToKeycode
209                        (GDK_DISPLAY (), global_config.window_screenshot_key.keysym);
210                laststate_window_screenshot = global_config.window_screenshot_key.state;
211                if (lastkey_window_screenshot != 0 &&
212                    (lastkey_menu != lastkey_window_screenshot ||
213                     laststate_menu != laststate_window_screenshot) &&
214                    (lastkey_run != lastkey_window_screenshot ||
215                     laststate_run != laststate_window_screenshot) &&
216                    (lastkey_screenshot != lastkey_window_screenshot ||
217                     laststate_screenshot != laststate_window_screenshot))
218                        grab_key (laststate_window_screenshot,
219                                  lastkey_window_screenshot);
220        } else {
221                lastkey_window_screenshot = 0;
222        }
223
224        gdk_flush ();
225        gdk_error_trap_pop();
226}
227
228static gboolean
229check_for_grabs (void)
230{
231        if (gdk_pointer_grab (gdk_get_default_root_window (), FALSE,
232                              0, NULL, NULL, GDK_CURRENT_TIME)
233            != GrabSuccess) {
234                return TRUE;
235        } else {
236                gdk_pointer_ungrab (GDK_CURRENT_TIME);
237                return FALSE;
238        }
239}
240
241GdkFilterReturn
242panel_global_keys_filter (GdkXEvent *gdk_xevent,
243                          GdkEvent  *event,
244                          GdkScreen *screen)
245{
246        XEvent *xevent = (XEvent *)gdk_xevent;
247        guint keycode, state;
248        guint menu_keycode, menu_state;
249        guint run_keycode, run_state;
250        guint screenshot_keycode, screenshot_state;
251        guint window_screenshot_keycode, window_screenshot_state;
252        guint ignored_mods;
253
254        g_return_val_if_fail (GDK_IS_SCREEN (screen), GDK_FILTER_CONTINUE);
255       
256        if(xevent->type != KeyPress)
257                return GDK_FILTER_CONTINUE;
258
259        ignored_mods = get_ignored_mods ();
260       
261        keycode = xevent->xkey.keycode;
262        state = xevent->xkey.state;
263
264        menu_keycode = XKeysymToKeycode (GDK_DISPLAY (),
265                                         global_config.menu_key.keysym);
266        menu_state = global_config.menu_key.state;
267
268        run_keycode = XKeysymToKeycode (GDK_DISPLAY (),
269                                        global_config.run_key.keysym);
270        run_state = global_config.run_key.state;
271
272        screenshot_keycode = XKeysymToKeycode (GDK_DISPLAY (),
273                                               global_config.screenshot_key.keysym);
274        screenshot_state = global_config.screenshot_key.state;
275
276        window_screenshot_keycode =
277                XKeysymToKeycode (GDK_DISPLAY (),
278                                  global_config.window_screenshot_key.keysym);
279        window_screenshot_state = global_config.window_screenshot_key.state;
280
281        if (keycode == menu_keycode &&
282            (state & (~ignored_mods)) == menu_state) {
283                PanelWidget *panel_widget;
284                GtkWidget   *panel;
285                GtkWidget   *menu;
286
287                /* check if anybody else has a grab */
288                if (check_for_grabs ())
289                        return GDK_FILTER_CONTINUE;
290
291                panel_widget = panels->data;
292                menu = create_panel_root_menu (panel_widget);
293                panel = panel_widget->panel_parent;
294
295                if (BASEP_IS_WIDGET (panel)) {
296                        BASEP_WIDGET (panel)->autohide_inhibit = TRUE;
297                        basep_widget_autohide (BASEP_WIDGET (panel));
298                }
299
300                gtk_menu_set_screen (GTK_MENU (menu), screen);
301                gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
302                                NULL, NULL, 0, GDK_CURRENT_TIME);
303                return GDK_FILTER_REMOVE;
304        } else if (keycode == run_keycode &&
305                   (state & (~ignored_mods)) == run_state) {
306                /* check if anybody else has a grab */
307                if (check_for_grabs ()) {
308                        return GDK_FILTER_CONTINUE;
309                }
310
311                show_run_dialog (screen);
312                return GDK_FILTER_REMOVE;
313        } else if (keycode == screenshot_keycode &&
314                   (state & (~ignored_mods)) == screenshot_state) {
315                char *argv [2];
316                char *proggie;
317
318                /* check if anybody else has a grab */
319                if (check_for_grabs ()) {
320                        return GDK_FILTER_CONTINUE;
321                }
322
323                proggie = g_find_program_in_path  ("gnome-panel-screenshot");
324                if (proggie == NULL) {
325                        panel_error_dialog (
326                                screen,
327                                "cannot_find_ss_program",
328                                _("Can't find the screenshot program"));
329                        return GDK_FILTER_REMOVE;
330                }
331                argv[0] = proggie;
332                argv[1] = NULL;
333
334                if (egg_screen_execute_async (screen, g_get_home_dir (), 1, argv) < 0)
335                        panel_error_dialog (screen,
336                                            "cannot_exec_ss_program",
337                                            _("Can't execute the screenshot program"));
338
339                g_free (proggie);
340
341                return GDK_FILTER_REMOVE;
342        } else if (keycode == window_screenshot_keycode &&
343                   (state & (~ignored_mods)) == window_screenshot_state) {
344                char *argv [3];
345                char *proggie;
346
347                /* check if anybody else has a grab */
348                if (check_for_grabs ()) {
349                        return GDK_FILTER_CONTINUE;
350                }
351
352                proggie = g_find_program_in_path  ("gnome-panel-screenshot");
353                if (proggie == NULL) {
354                        panel_error_dialog (
355                                screen,
356                                "cannot_find_ss_program",
357                                _("Can't find the screenshot program"));
358                        return GDK_FILTER_REMOVE;
359                }
360                argv[0] = proggie;
361                argv[1] = "--window";
362                argv[2] = NULL;
363
364                if (egg_screen_execute_async (screen, g_get_home_dir (), 2, argv) < 0)
365                        panel_error_dialog (screen,
366                                            "cannot_exec_ss_program",
367                                            _("Can't execute the screenshot program"));
368
369                g_free (proggie);
370
371                return GDK_FILTER_REMOVE;
372        }
373
374        return GDK_FILTER_CONTINUE;
375}
Note: See TracBrowser for help on using the repository browser.