~sil2100/compiz-core/fglrx_decor_fix

« back to all changes in this revision

Viewing changes to gtk/window-decorator/local-menus/src/local-menus.c

  • Committer: Daniel van Vugt
  • Date: 2012-03-30 07:31:56 UTC
  • mfrom: (3076.1.1 revert-lim)
  • Revision ID: daniel.van.vugt@canonical.com-20120330073156-zkf1b676o3m2vur2
Revert locally integrated menus support because it is not being used and
is apparently causing a regression (LP: #962085)

This reverts LP: #931245 and LP: #682788. It is a pure revert of
lp:compiz-core r3036.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright © 2006 Novell, Inc.
3
 
 *
4
 
 * This library is free software; you can redistribute it and/or
5
 
 * modify it under the terms of the GNU Lesser General Public
6
 
 * License as published by the Free Software Foundation; either
7
 
 * version 2 of the License, or (at your option) any later version.
8
 
 *
9
 
 * This library is distributed in the hope that it will be useful,
10
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 
 * Lesser General Public License for more details.
13
 
 *
14
 
 * You should have received a copy of the GNU Lesser General Public
15
 
 * License along with this library; if not, write to the
16
 
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17
 
 * Boston, MA 02111-1307, USA.
18
 
 *
19
 
 * Author: David Reveman <davidr@novell.com>
20
 
 *
21
 
 * 2D Mode: Copyright © 2010 Sam Spilsbury <smspillaz@gmail.com>
22
 
 * Frames Management: Copright © 2011 Canonical Ltd.
23
 
 *        Authored By: Sam Spilsbury <sam.spilsbury@canonical.com>
24
 
 */
25
 
 
26
 
#include <string.h>
27
 
#include "local-menus.h"
28
 
#include <gdk/gdk.h>
29
 
#include <gdk/gdkx.h>
30
 
#include <stdlib.h>
31
 
 
32
 
#define GLOBAL 0
33
 
#define LOCAL 1
34
 
 
35
 
#define ALLOWED 2
36
 
#define NOT_ALLOWED 1
37
 
 
38
 
gint menu_mode = GLOBAL;
39
 
 
40
 
GDBusProxy *global_lim_listener;
41
 
 
42
 
 
43
 
#ifdef META_HAS_LOCAL_MENUS
44
 
static void
45
 
gwd_menu_mode_changed (GSettings *settings,
46
 
                       gchar     *key,
47
 
                       gpointer  user_data)
48
 
{
49
 
    menu_mode = g_settings_get_enum (settings, "menu-mode");
50
 
}
51
 
#endif
52
 
 
53
 
active_local_menu *active_menu;
54
 
pending_local_menu *pending_menu;
55
 
 
56
 
GHashTable *get_windows_with_menus_table ()
57
 
{
58
 
   static GHashTable *windows_with_menus = NULL;
59
 
 
60
 
   if (!windows_with_menus)
61
 
     windows_with_menus = g_hash_table_new (NULL, NULL);
62
 
 
63
 
   return windows_with_menus;
64
 
}
65
 
 
66
 
static gboolean read_xprop_for_window (Display *dpy, Window xid)
67
 
{
68
 
  Atom ubuntu_appmenu_unique_name = XInternAtom (dpy, "_UBUNTU_APPMENU_UNIQUE_NAME", FALSE);
69
 
  Atom utf8_string = XInternAtom (dpy, "UTF8_STRING", FALSE);
70
 
  Atom actual;
71
 
  int  fmt;
72
 
  unsigned long nitems, nleft;
73
 
  unsigned char *prop;
74
 
  XGetWindowProperty (dpy, xid, ubuntu_appmenu_unique_name,
75
 
                      0L, 16L, FALSE, utf8_string, &actual, &fmt, &nitems, &nleft, &prop);
76
 
 
77
 
  if (actual == utf8_string && fmt == 8 && nitems > 1)
78
 
  {
79
 
    g_hash_table_replace (get_windows_with_menus_table (), GINT_TO_POINTER (xid), GINT_TO_POINTER (ALLOWED));
80
 
    return TRUE;
81
 
  }
82
 
  else
83
 
  {
84
 
    g_hash_table_replace (get_windows_with_menus_table (), GINT_TO_POINTER (xid), GINT_TO_POINTER (NOT_ALLOWED));
85
 
    return FALSE;
86
 
  }
87
 
}
88
 
 
89
 
gboolean
90
 
local_menu_allowed_on_window (Display *dpy, Window xid)
91
 
{
92
 
  gpointer local_menu_allowed_found = g_hash_table_lookup (get_windows_with_menus_table (), GINT_TO_POINTER (xid));
93
 
 
94
 
  if (local_menu_allowed_found)
95
 
    {
96
 
      return GPOINTER_TO_INT (local_menu_allowed_found) == ALLOWED;
97
 
    }
98
 
  else if (dpy && xid)
99
 
    {
100
 
      return read_xprop_for_window (dpy, xid);
101
 
    }
102
 
 
103
 
  return FALSE;
104
 
}
105
 
 
106
 
gboolean
107
 
gwd_window_should_have_local_menu (Window win)
108
 
{
109
 
#ifdef META_HAS_LOCAL_MENUS
110
 
    const gchar * const *schemas = g_settings_list_schemas ();
111
 
    static GSettings *lim_settings = NULL;
112
 
    while (*schemas != NULL && !lim_settings)
113
 
    {
114
 
        if (g_str_equal (*schemas, "com.canonical.indicator.appmenu"))
115
 
        {
116
 
            lim_settings = g_settings_new ("com.canonical.indicator.appmenu");
117
 
            menu_mode = g_settings_get_enum (lim_settings, "menu-mode");
118
 
            g_signal_connect (lim_settings, "changed::menu-mode", G_CALLBACK (gwd_menu_mode_changed), NULL);
119
 
            break;
120
 
        }
121
 
        ++schemas;
122
 
    }
123
 
 
124
 
    if (lim_settings && win)
125
 
        return menu_mode == LOCAL && local_menu_allowed_on_window (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), win);
126
 
#endif
127
 
 
128
 
    return FALSE;
129
 
}
130
 
 
131
 
gchar *
132
 
gwd_get_entry_id_from_sync_variant (GVariant *args)
133
 
{
134
 
    /* We need to get the indicator data once we've called show */
135
 
 
136
 
    GVariantIter* iter            = NULL;
137
 
    gchar*        name_hint       = NULL;
138
 
    gchar*        indicator_id    = NULL;
139
 
    gchar*        entry_id        = NULL;
140
 
    gchar*        label           = NULL;
141
 
    gboolean      label_sensitive = FALSE;
142
 
    gboolean      label_visible   = FALSE;
143
 
    guint32       image_type      = 0;
144
 
    gchar*        image_data      = NULL;
145
 
    gboolean      image_sensitive = FALSE;
146
 
    gboolean      image_visible   = FALSE;
147
 
    gint32        priority        = -1;
148
 
 
149
 
    g_variant_get (args, "(a(ssssbbusbbi))", &iter);
150
 
    while (g_variant_iter_loop (iter, "(ssssbbusbbi)",
151
 
                            &indicator_id,
152
 
                            &entry_id,
153
 
                            &name_hint,
154
 
                            &label,
155
 
                            &label_sensitive,
156
 
                            &label_visible,
157
 
                            &image_type,
158
 
                            &image_data,
159
 
                            &image_sensitive,
160
 
                            &image_visible,
161
 
                            &priority))
162
 
    {
163
 
        g_variant_unref (args);
164
 
        return g_strdup (entry_id);
165
 
    }
166
 
 
167
 
    g_variant_unref (args);
168
 
    g_assert_not_reached ();
169
 
    return NULL;
170
 
}
171
 
#ifdef META_HAS_LOCAL_MENUS
172
 
static void
173
 
on_local_menu_activated (GDBusProxy *proxy,
174
 
                         gchar      *sender_name,
175
 
                         gchar      *signal_name,
176
 
                         GVariant   *parameters,
177
 
                         gpointer   user_data)
178
 
{
179
 
 
180
 
    if (g_strcmp0 (signal_name, "EntryActivated") == 0)
181
 
    {
182
 
        show_local_menu_data *d = (show_local_menu_data *) user_data;
183
 
        gchar *entry_id = NULL;
184
 
        gint            x_out, y_out;
185
 
        guint           width, height;
186
 
 
187
 
        g_variant_get (parameters, "(s(iiuu))", &entry_id, &x_out, &y_out, &width, &height, NULL);
188
 
 
189
 
        if (!d->local_menu_entry_id)
190
 
        {
191
 
            GError   *error = NULL;
192
 
            GVariant *params = g_variant_new ("(s)", "libappmenu.so", NULL);
193
 
            GVariant *args = g_dbus_proxy_call_sync (proxy, "SyncOne", params, 0, 500, NULL, &error);
194
 
 
195
 
            g_assert_no_error (error);
196
 
            d->local_menu_entry_id = gwd_get_entry_id_from_sync_variant (args);
197
 
        }
198
 
 
199
 
        if (g_strcmp0 (entry_id, d->local_menu_entry_id) == 0)
200
 
        {
201
 
            d->rect->x = x_out - d->dx;
202
 
            d->rect->y = y_out - d->dy;
203
 
            d->rect->width = width;
204
 
            d->rect->height = height;
205
 
            (*d->cb) (d->user_data);
206
 
        }
207
 
        else if (g_strcmp0 (entry_id, "") == 0)
208
 
        {
209
 
            memset (d->rect, 0, sizeof (GdkRectangle));
210
 
            (*d->cb) (d->user_data);
211
 
 
212
 
            g_signal_handlers_disconnect_by_func (proxy, on_local_menu_activated, d);
213
 
 
214
 
            if (active_menu)
215
 
            {
216
 
                g_free (active_menu);
217
 
                active_menu = NULL;
218
 
            }
219
 
 
220
 
            g_free (d->local_menu_entry_id);
221
 
            g_free (d);
222
 
        }
223
 
    }
224
 
 
225
 
}
226
 
#endif
227
 
gboolean
228
 
gwd_move_window_instead (gpointer user_data)
229
 
{
230
 
    (*pending_menu->cb) (pending_menu->user_data);
231
 
    g_source_remove (pending_menu->move_timeout_id);
232
 
    g_free (pending_menu->user_data);
233
 
    g_free (pending_menu);
234
 
    pending_menu = NULL;
235
 
    return FALSE;
236
 
}
237
 
 
238
 
void
239
 
local_menu_process_motion(gint x_root, gint y_root)
240
 
{
241
 
    if (!pending_menu)
242
 
        return;
243
 
 
244
 
    if (abs (pending_menu->x_root - x_root) > 4 &&
245
 
        abs (pending_menu->y_root - y_root) > 4)
246
 
        gwd_move_window_instead (pending_menu);
247
 
}
248
 
 
249
 
void
250
 
gwd_prepare_show_local_menu (start_move_window_cb start_move_window,
251
 
                             gpointer user_data_start_move_window,
252
 
                             gint     x_root,
253
 
                             gint     y_root)
254
 
{
255
 
    if (pending_menu)
256
 
    {
257
 
        g_source_remove (pending_menu->move_timeout_id);
258
 
        g_free (pending_menu->user_data);
259
 
        g_free (pending_menu);
260
 
        pending_menu = NULL;
261
 
    }
262
 
 
263
 
    pending_menu = g_new0 (pending_local_menu, 1);
264
 
    pending_menu->cb = start_move_window;
265
 
    pending_menu->user_data = user_data_start_move_window;
266
 
    pending_menu->move_timeout_id = g_timeout_add (150, gwd_move_window_instead, pending_menu);
267
 
}
268
 
 
269
 
#ifdef META_HAS_LOCAL_MENUS
270
 
void
271
 
local_menu_entry_activated_request (GDBusProxy *proxy,
272
 
                                    gchar      *sender_name,
273
 
                                    gchar      *signal_name,
274
 
                                    GVariant   *parameters,
275
 
                                    gpointer   user_data)
276
 
{
277
 
  if (g_strcmp0 (signal_name, "EntryActivateRequest") == 0)
278
 
    {
279
 
      gchar *activated_entry_id;
280
 
      gchar *local_menu_entry_id;
281
 
      local_menu_entry_activated_request_funcs *funcs = (local_menu_entry_activated_request_funcs *) user_data;
282
 
 
283
 
      g_variant_get (parameters, "(s)", &activated_entry_id, NULL);
284
 
 
285
 
      GError   *error = NULL;
286
 
      GVariant *params = g_variant_new ("(s)", "libappmenu.so", NULL);
287
 
      GVariant *args = g_dbus_proxy_call_sync (proxy, "SyncOne", params, 0, 500, NULL, &error);
288
 
 
289
 
      g_assert_no_error (error);
290
 
      local_menu_entry_id = gwd_get_entry_id_from_sync_variant (args);
291
 
 
292
 
      if (g_strcmp0 (activated_entry_id, local_menu_entry_id) == 0)
293
 
        {
294
 
          WnckScreen *screen = wnck_screen_get_for_root (gdk_x11_get_default_root_xwindow ());
295
 
          int dx, dy, top_height;
296
 
          Window xid;
297
 
 
298
 
          if (screen)
299
 
            {
300
 
              Box *rect = (*funcs->active_window_local_menu_rect_callback) ((gpointer) screen, &dx, &dy, &top_height, &xid);
301
 
 
302
 
              if (rect)
303
 
                {
304
 
                  int x = rect->x1;
305
 
                  int y = top_height;
306
 
 
307
 
                  gwd_show_local_menu (gdk_x11_display_get_xdisplay (gdk_display_get_default ()),
308
 
                                           xid, x + dx, y + dy, x, y, 0, 0,
309
 
                                           funcs->show_window_menu_hidden_callback, GINT_TO_POINTER (xid));
310
 
                }
311
 
            }
312
 
        }
313
 
    }
314
 
}
315
 
#endif
316
 
 
317
 
gboolean
318
 
gwd_show_local_menu (Display *xdisplay,
319
 
                     Window  frame_xwindow,
320
 
                     int      x,
321
 
                     int      y,
322
 
                     int      x_win,
323
 
                     int      y_win,
324
 
                     int      button,
325
 
                     guint32  timestamp,
326
 
                     show_window_menu_hidden_cb cb,
327
 
                     gpointer user_data_show_window_menu)
328
 
{
329
 
    if (pending_menu)
330
 
    {
331
 
        g_source_remove (pending_menu->move_timeout_id);
332
 
        g_free (pending_menu->user_data);
333
 
        g_free (pending_menu);
334
 
        pending_menu = NULL;
335
 
    }
336
 
 
337
 
#ifdef META_HAS_LOCAL_MENUS
338
 
 
339
 
 
340
 
    XUngrabPointer (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), CurrentTime);
341
 
    XUngrabKeyboard (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), CurrentTime);
342
 
    XSync (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), FALSE);
343
 
 
344
 
    GDBusProxy *proxy = global_lim_listener;
345
 
 
346
 
    if (proxy)
347
 
    {
348
 
        GVariant *message = g_variant_new ("(uiiu)", frame_xwindow, x, y, time);
349
 
        GError   *error = NULL;
350
 
        g_dbus_proxy_call_sync (proxy, "ShowAppMenu", message, 0, 500, NULL, &error);
351
 
        if (error)
352
 
        {
353
 
            g_print ("error calling ShowAppMenu: %s\n", error->message);
354
 
            return FALSE;
355
 
        }
356
 
 
357
 
        show_local_menu_data *data = g_new0 (show_local_menu_data, 1);
358
 
 
359
 
        if (active_menu)
360
 
            g_free (active_menu);
361
 
 
362
 
        active_menu = g_new0 (active_local_menu, 1);
363
 
 
364
 
        data->cb = cb;
365
 
        data->user_data = user_data_show_window_menu;
366
 
        data->rect = &active_menu->rect;
367
 
        data->dx = x - x_win;
368
 
        data->dy = y - y_win;
369
 
        data->local_menu_entry_id = NULL;  
370
 
 
371
 
        g_signal_connect (proxy, "g-signal", G_CALLBACK (on_local_menu_activated), data);
372
 
 
373
 
        return TRUE;
374
 
    }
375
 
#endif
376
 
    return FALSE;
377
 
}
378
 
 
379
 
void
380
 
force_local_menus_on (Window           win,
381
 
                      MetaButtonLayout *button_layout)
382
 
{
383
 
#ifdef META_HAS_LOCAL_MENUS
384
 
    if (gwd_window_should_have_local_menu (win))
385
 
    {
386
 
        if (button_layout->left_buttons[0] != META_BUTTON_FUNCTION_LAST)
387
 
        {
388
 
            unsigned int i = 0;
389
 
            for (; i < MAX_BUTTONS_PER_CORNER; i++)
390
 
            {
391
 
                if (button_layout->left_buttons[i] == META_BUTTON_FUNCTION_WINDOW_MENU)
392
 
                    break;
393
 
                else if (button_layout->left_buttons[i] == META_BUTTON_FUNCTION_LAST)
394
 
                {
395
 
                    if ((i + 1) < MAX_BUTTONS_PER_CORNER)
396
 
                    {
397
 
                        button_layout->left_buttons[i + 1] = META_BUTTON_FUNCTION_LAST;
398
 
                        button_layout->left_buttons[i] = META_BUTTON_FUNCTION_WINDOW_MENU;
399
 
                        break;
400
 
                    }
401
 
                }
402
 
            }
403
 
        }
404
 
        if (button_layout->right_buttons[0] != META_BUTTON_FUNCTION_LAST)
405
 
        {
406
 
            unsigned int i = 0;
407
 
            for (; i < MAX_BUTTONS_PER_CORNER; i++)
408
 
            {
409
 
                if (button_layout->right_buttons[i] == META_BUTTON_FUNCTION_WINDOW_MENU)
410
 
                    break;
411
 
                else if (button_layout->right_buttons[i] == META_BUTTON_FUNCTION_LAST)
412
 
                {
413
 
                    if ((i + 1) < MAX_BUTTONS_PER_CORNER)
414
 
                    {
415
 
                        button_layout->right_buttons[i + 1] = META_BUTTON_FUNCTION_LAST;
416
 
                        button_layout->right_buttons[i] = META_BUTTON_FUNCTION_WINDOW_MENU;
417
 
                        break;
418
 
                    }
419
 
                }
420
 
            }
421
 
        }
422
 
    }
423
 
#endif
424
 
}
425
 
 
426
 
void
427
 
local_menu_cache_notify_window_destroyed (Window xid)
428
 
{
429
 
  g_hash_table_remove (get_windows_with_menus_table (), GINT_TO_POINTER (xid));
430
 
}
431
 
 
432
 
void
433
 
local_menu_cache_reload_xwindow (Display *dpy, Window xid)
434
 
{
435
 
  read_xprop_for_window (dpy, xid);
436
 
}
437
 
 
438