Merge lp:~smspillaz/compiz-core/compiz-core.lim into lp:compiz-core

Proposed by Sam Spilsbury
Status: Superseded
Proposed branch: lp:~smspillaz/compiz-core/compiz-core.lim
Merge into: lp:compiz-core
Diff against target: 1152 lines (+873/-11)
15 files modified
gtk/window-decorator/CMakeLists.txt (+6/-0)
gtk/window-decorator/decorator.c (+32/-6)
gtk/window-decorator/events.c (+109/-3)
gtk/window-decorator/gtk-window-decorator.h (+7/-1)
gtk/window-decorator/local-menus/CMakeLists.txt (+60/-0)
gtk/window-decorator/local-menus/src/local-menus.c (+331/-0)
gtk/window-decorator/local-menus/src/local-menus.h (+95/-0)
gtk/window-decorator/local-menus/tests/CMakeLists.txt (+3/-0)
gtk/window-decorator/local-menus/tests/check_local_menu_on_off/CMakeLists.txt (+21/-0)
gtk/window-decorator/local-menus/tests/check_local_menu_on_off/test-local-menu-on-off.cpp (+20/-0)
gtk/window-decorator/local-menus/tests/force_local_menu_on/CMakeLists.txt (+21/-0)
gtk/window-decorator/local-menus/tests/force_local_menu_on/test-force-local-menu-on.cpp (+70/-0)
gtk/window-decorator/local-menus/tests/test-local-menu.h (+48/-0)
gtk/window-decorator/metacity.c (+48/-0)
gtk/window-decorator/wnck.c (+2/-1)
To merge this branch: bzr merge lp:~smspillaz/compiz-core/compiz-core.lim
Reviewer Review Type Date Requested Status
Daniel van Vugt Needs Fixing
Alan Griffiths Pending
Review via email: mp+93949@code.launchpad.net

This proposal supersedes a proposal from 2012-02-06.

This proposal has been superseded by a proposal from 2012-02-22.

Description of the change

Adds support for Ubuntu's "locally integrated menu bars" into gtk-window-decorator.

No tests as of yet, but I'll try and write some for

showing/hiding
forcing them on/off
positions etc

soonish.

To post a comment you must log in.
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

8 +#define GWD_SHOW_LOCAL_MENU (WNCK_WINDOW_ACTION_BELOW << 1)

No plausible reason for using a macro. In C++ constants (enum or unsigned int) are better as they respect scope rules. Also, should this be inside "#ifdef META_HAS_LOCAL_MENUS" conditional?

296 button_layout->right_buttons[2] = META_BUTTON_FUNCTION_CLOSE;
297
298 - for (i = 3; i < MAX_BUTTONS_PER_CORNER; i++)
299 + for (i = 4; i < MAX_BUTTONS_PER_CORNER; i++)
300 button_layout->right_buttons[i] = META_BUTTON_FUNCTION_LAST;
301 }

I'm not sure what the magic number "3"->"4" is. But we now seem to miss 3 entirely. Is that correct?

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

> 8 +#define GWD_SHOW_LOCAL_MENU (WNCK_WINDOW_ACTION_BELOW << 1)
>
> No plausible reason for using a macro. In C++ constants (enum or unsigned
> int) are better as they respect scope rules. Also, should this be inside
> "#ifdef META_HAS_LOCAL_MENUS" conditional?
>

Its C

>
> 296 button_layout->right_buttons[2] = META_BUTTON_FUNCTION_CLOSE;
> 297
> 298 - for (i = 3; i < MAX_BUTTONS_PER_CORNER; i++)
> 299 + for (i = 4; i < MAX_BUTTONS_PER_CORNER; i++)
> 300 button_layout->right_buttons[i] = META_BUTTON_FUNCTION_LAST;
> 301 }
>
> I'm not sure what the magic number "3"->"4" is. But we now seem to miss 3
> entirely. Is that correct?

Its for initializing the array, though maybe thats wrong. Good find let me check

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Please resubmit for target branch lp:compiz-core (0.9.7)

review: Needs Resubmitting
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

Looks better

review: Approve
Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

(More work needed to adopt to trevino;s changes)

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Fails to build ifndef META_HAS_LOCAL_MENUS

[ 0%] Building C object gtk/window-decorator/local-menus/CMakeFiles/gtk_window_decorator_local_menus.dir/src/local-menus.c.o
/home/dan/bzr/compiz-core/lim/gtk/window-decorator/local-menus/src/local-menus.c:36:1: error: ‘gwd_menu_mode_changed’ defined but not used [-Werror=unused-function]
/home/dan/bzr/compiz-core/lim/gtk/window-decorator/local-menus/src/local-menus.c:72:1: error: ‘on_local_menu_activated’ defined but not used [-Werror=unused-function]
cc1: all warnings being treated as errors

review: Needs Fixing
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote : Posted in a previous version of this proposal

+ gboolean empty = g_strcmp0 (entry_id, "") == 0;

You can do the same with:
gboolean empty = (!entry_id || entry_id[0] == '\0');

Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

If we're trying to be cryptic...

   gboolean empty = g_strcmp0 (entry_id, "") == 0;

can be written:

   gboolean empty = !entry_id || !*entry_id;

Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote : Posted in a previous version of this proposal

Ah, Sam remember to update the "EntryActivated" signal against the new signature s(iiuu).

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal

Yep, done

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Fails to build for a whole new reason now :(

Scanning dependencies of target gtk_window_decorator_force_local_menu_on_test
[ 5%] Building CXX object gtk/window-decorator/local-menus/tests/force_local_menu_on/CMakeFiles/gtk_window_decorator_force_local_menu_on_test.dir/test-force-local-menu-on.cpp.o
/home/dan/bzr/compiz-core/lim/gtk/window-decorator/local-menus/tests/force_local_menu_on/test-force-local-menu-on.cpp: In member function ‘virtual void GtkWindowDecoratorTestLocalMenuLayout_TestForceNoCloseButtonSet_Test::TestBody()’:
/home/dan/bzr/compiz-core/lim/gtk/window-decorator/local-menus/tests/force_local_menu_on/test-force-local-menu-on.cpp:56:5: error: ‘META_BUTTON_FUNCTION_WINDOW_MENU’ was not declared in this scope
/home/dan/bzr/compiz-core/lim/gtk/window-decorator/local-menus/tests/force_local_menu_on/test-force-local-menu-on.cpp: In member function ‘virtual void GtkWindowDecoratorTestLocalMenuLayout_TestForceNoCloseMinimizeMaximizeButtonSet_Test::TestBody()’:
/home/dan/bzr/compiz-core/lim/gtk/window-decorator/local-menus/tests/force_local_menu_on/test-force-local-menu-on.cpp:69:5: error: ‘META_BUTTON_FUNCTION_WINDOW_MENU’ was not declared in this scope
make[2]: *** [gtk/window-decorator/local-menus/tests/force_local_menu_on/CMakeFiles/gtk_window_decorator_force_local_menu_on_test.dir/test-force-local-menu-on.cpp.o] Error 1
make[1]: *** [gtk/window-decorator/local-menus/tests/force_local_menu_on/CMakeFiles/gtk_window_decorator_force_local_menu_on_test.dir/all] Error 2
make: *** [all] Error 2

review: Needs Fixing
2996. By Sam Spilsbury

Also ifdef the local menus tests

2997. By Sam Spilsbury

Don't run global setup or teardown functions if no local menus

2998. By Sam Spilsbury

Merge lp:compiz-core and allow alt-accelerator to open menus as well as reading the xprop
to determine if local menus are applicable

2999. By Sam Spilsbury

Fix memory error and menu button not showing

3000. By Sam Spilsbury

Fix placement of menus on alt-accelerator, remove debug messages

3001. By Sam Spilsbury

Fix build failure without META_HAS_LOCAL_MENUS

3002. By Sam Spilsbury

Fix a crash when trying to show the window menu on a non decorated window

3003. By Sam Spilsbury

Tell us if we have them

3004. By Sam Spilsbury

Merged lp:compiz-core

3005. By Sam Spilsbury

We also need to test the property too

3006. By Sam Spilsbury

Grab buttons too so that we can process motion events on the titlebar and
move the window instead.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'gtk/window-decorator/CMakeLists.txt'
2--- gtk/window-decorator/CMakeLists.txt 2011-02-16 17:39:56 +0000
3+++ gtk/window-decorator/CMakeLists.txt 2012-02-21 10:38:22 +0000
4@@ -4,7 +4,10 @@
5 set (CMAKE_INSTALL_RPATH ${libdir})
6 endif (COMPIZ_BUILD_WITH_RPATH)
7
8+ add_subdirectory (local-menus)
9+
10 include_directories (
11+ ${CMAKE_CURRENT_SOURCE_DIR}/local-menus/src
12 ${compiz_SOURCE_DIR}/include
13 ${CMAKE_BINARY_DIR}/gtk
14 ${GTK_WINDOW_DECORATOR_INCLUDE_DIRS}
15@@ -63,6 +66,9 @@
16 target_link_libraries (
17 gtk-window-decorator
18 decoration
19+
20+ gtk_window_decorator_local_menus
21+
22 ${GTK_WINDOW_DECORATOR_LIBRARIES}
23 ${GCONF_LIBRARIES}
24 ${DBUS_GLIB_LIBRARIES}
25
26=== modified file 'gtk/window-decorator/decorator.c'
27--- gtk/window-decorator/decorator.c 2012-02-20 07:42:20 +0000
28+++ gtk/window-decorator/decorator.c 2012-02-21 10:38:22 +0000
29@@ -24,6 +24,7 @@
30 */
31
32 #include "gtk-window-decorator.h"
33+#include "local-menus.h"
34
35 decor_frame_t *
36 create_normal_frame (const gchar *type)
37@@ -230,12 +231,16 @@
38 void
39 update_event_windows (WnckWindow *win)
40 {
41+#define GWD_SHOW_LOCAL_MENU (WNCK_WINDOW_ACTION_BELOW << 1)
42 Display *xdisplay;
43 decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
44 gint x0, y0, width, height, x, y, w, h;
45 gint i, j, k, l;
46 gint actions = d->actions;
47
48+ if (gwd_window_should_have_local_menu (win))
49+ actions |= GWD_SHOW_LOCAL_MENU;
50+
51 xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
52
53 /* Get the geometry of the client */
54@@ -298,11 +303,19 @@
55 XMapWindow (xdisplay, d->event_windows[i][j].window);
56 XMoveResizeWindow (xdisplay, d->event_windows[i][j].window,
57 x, y, w, h);
58+
59+ BoxPtr box = &d->event_windows[i][j].pos;
60+ box->x1 = x;
61+ box->x2 = x + w;
62+ box->y1 = y;
63+ box->y2 = y + h;
64 }
65 /* No parent and no geometry - unmap all event windows */
66 else if (!d->frame_window)
67 {
68 XUnmapWindow (xdisplay, d->event_windows[i][j].window);
69+
70+ memset (&d->event_windows[i][j].pos, 0, sizeof (Box));
71 }
72 }
73 }
74@@ -326,12 +339,18 @@
75 WNCK_WINDOW_ACTION_STICK,
76 WNCK_WINDOW_ACTION_UNSHADE,
77 WNCK_WINDOW_ACTION_ABOVE,
78- WNCK_WINDOW_ACTION_UNSTICK
79-#else
80- 0,
81- 0,
82- 0,
83- 0,
84+ WNCK_WINDOW_ACTION_UNSTICK,
85+#else
86+ 0,
87+ 0,
88+ 0,
89+ 0,
90+ 0,
91+#endif
92+
93+#ifdef META_HAS_LOCAL_MENUS
94+ GWD_SHOW_LOCAL_MENU
95+#else
96 0
97 #endif
98
99@@ -371,10 +390,17 @@
100 Window win = d->button_windows[i].window;
101 XMapWindow (xdisplay, win);
102 XMoveResizeWindow (xdisplay, win, x, y, w, h);
103+
104+ BoxPtr box = &d->button_windows[i].pos;
105+ box->x1 = x;
106+ box->x2 = x + w;
107+ box->y1 = y;
108+ box->y2 = y + h;
109 }
110 else if (!d->frame_window)
111 {
112 XUnmapWindow (xdisplay, d->button_windows[i].window);
113+ memset (&d->button_windows[i].pos, 0, sizeof (Box));
114 }
115 }
116
117
118=== modified file 'gtk/window-decorator/events.c'
119--- gtk/window-decorator/events.c 2012-02-20 07:46:35 +0000
120+++ gtk/window-decorator/events.c 2012-02-21 10:38:22 +0000
121@@ -24,6 +24,16 @@
122 */
123
124 #include "gtk-window-decorator.h"
125+#include "local-menus.h"
126+
127+typedef struct _delayed_move_info
128+{
129+ WnckWindow *win;
130+ int x_root;
131+ int y_root;
132+ unsigned int button;
133+ unsigned int time;
134+} delayed_move_info;
135
136 void
137 move_resize_window (WnckWindow *win,
138@@ -65,8 +75,9 @@
139 ev.xclient.data.l[3] = gtkwd_event->button;
140 ev.xclient.data.l[4] = 1;
141
142- XUngrabPointer (xdisplay, gtkwd_event->time);
143- XUngrabKeyboard (xdisplay, gtkwd_event->time);
144+ XAllowEvents (xdisplay, AsyncKeyboard | AsyncPointer, CurrentTime);
145+ XUngrabPointer (xdisplay, CurrentTime);
146+ XUngrabKeyboard (xdisplay, CurrentTime);
147
148 XSendEvent (xdisplay, xroot, FALSE,
149 SubstructureRedirectMask | SubstructureNotifyMask,
150@@ -75,6 +86,24 @@
151 XSync (xdisplay, FALSE);
152 }
153
154+static gboolean
155+move_resize_window_on_timeout (gpointer user_data)
156+{
157+ delayed_move_info *info = (delayed_move_info *) user_data;
158+
159+ decor_event event;
160+ event.x = 0;
161+ event.y = 0;
162+ event.x_root = info->x_root;
163+ event.y_root = info->y_root;
164+ event.button = info->button;
165+ event.window = wnck_window_get_xid (info->win);
166+
167+ move_resize_window (info->win, WM_MOVERESIZE_MOVE, &event);
168+
169+ return FALSE;
170+}
171+
172 void
173 common_button_event (WnckWindow *win,
174 decor_event *gtkwd_event,
175@@ -380,6 +409,73 @@
176 }
177
178 void
179+on_local_menu_hidden (gpointer user_data)
180+{
181+ decor_t *d = (decor_t *) user_data;
182+
183+ d->button_states[BUTTON_WINDOW_MENU] &= ~PRESSED_EVENT_WINDOW;
184+
185+ queue_decor_draw (d);
186+}
187+
188+void
189+window_menu_button_event (WnckWindow *win,
190+ decor_event *gtkwd_event,
191+ decor_event_type gtkwd_type)
192+{
193+ decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
194+ guint state = d->button_states[BUTTON_WINDOW_MENU];
195+
196+ common_button_event (win, gtkwd_event, gtkwd_type,
197+ BUTTON_WINDOW_MENU, 1, _("Window Menu"));
198+
199+ switch (gtkwd_type) {
200+ case GButtonPress:
201+ if (gtkwd_event->button == 1)
202+ {
203+ if (d->button_states[BUTTON_WINDOW_MENU] & BUTTON_EVENT_ACTION_STATE)
204+ {
205+ delayed_move_info *info = g_new0 (delayed_move_info, 1);
206+
207+ info->button = gtkwd_event->button;
208+ info->time = gtkwd_event->time;
209+ info->win = win;
210+ info->x_root = gtkwd_event->x_root;
211+ info->y_root = gtkwd_event->y_root;
212+
213+ gwd_prepare_show_local_menu ((start_move_window_cb) move_resize_window_on_timeout, (gpointer) info);
214+ }
215+ }
216+ break;
217+ case GButtonRelease:
218+ if (gtkwd_event->button == 1)
219+ if (state)
220+ {
221+ int win_x, win_y;
222+ int box_x = d->button_windows[BUTTON_WINDOW_MENU].pos.x1;
223+
224+ wnck_window_get_geometry (win, &win_x, &win_y, NULL, NULL);
225+
226+ int x = win_x + box_x;
227+ int y = win_y + d->context->extents.top;
228+
229+ gwd_show_local_menu (gdk_x11_display_get_xdisplay (gdk_display_get_default ()),
230+ wnck_window_get_xid (win),
231+ x, y,
232+ box_x,
233+ d->context->extents.top,
234+ gtkwd_event->button,
235+ gtkwd_event->time,
236+ (show_window_menu_hidden_cb) on_local_menu_hidden,
237+ (gpointer) d);
238+ }
239+ break;
240+ default:
241+ break;
242+ }
243+}
244+
245+void
246 handle_title_button_event (WnckWindow *win,
247 int action,
248 decor_event *gtkwd_event)
249@@ -485,7 +581,17 @@
250
251 restack_window (win, Above);
252
253- move_resize_window (win, WM_MOVERESIZE_MOVE, gtkwd_event);
254+ delayed_move_info *info = g_new0 (delayed_move_info, 1);
255+
256+ info->x_root = gtkwd_event->x_root;
257+ info->y_root = gtkwd_event->y_root;
258+ info->button = gtkwd_event->button;
259+ info->time = gtkwd_event->time;
260+ info->win = win;
261+
262+ move_resize_window_on_timeout ((gpointer) info);
263+
264+ g_free (info);
265 }
266 }
267 else if (gtkwd_event->button == 2)
268
269=== modified file 'gtk/window-decorator/gtk-window-decorator.h'
270--- gtk/window-decorator/gtk-window-decorator.h 2011-10-13 12:22:14 +0000
271+++ gtk/window-decorator/gtk-window-decorator.h 2012-02-21 10:38:22 +0000
272@@ -328,7 +328,8 @@
273 #define BUTTON_UNSHADE 7
274 #define BUTTON_UNABOVE 8
275 #define BUTTON_UNSTICK 9
276-#define BUTTON_NUM 10
277+#define BUTTON_WINDOW_MENU 10
278+#define BUTTON_NUM 11
279
280 struct _pos {
281 int x, y, w, h;
282@@ -1013,6 +1014,11 @@
283 decor_event_type gtkwd_type);
284
285 void
286+window_menu_button_event (WnckWindow *win,
287+ decor_event *gtkwd_event,
288+ decor_event_type gtkwd_type);
289+
290+void
291 handle_title_button_event (WnckWindow *win,
292 int action,
293 decor_event *gtkwd_event);
294
295=== added directory 'gtk/window-decorator/local-menus'
296=== added file 'gtk/window-decorator/local-menus/CMakeLists.txt'
297--- gtk/window-decorator/local-menus/CMakeLists.txt 1970-01-01 00:00:00 +0000
298+++ gtk/window-decorator/local-menus/CMakeLists.txt 2012-02-21 10:38:22 +0000
299@@ -0,0 +1,60 @@
300+pkg_check_modules(
301+ LOCAL_MENUS
302+ REQUIRED
303+ glib-2.0 gio-2.0 libwnck-1.0 gtk+-2.0>=2.18.0
304+)
305+
306+INCLUDE_DIRECTORIES(
307+ ${CMAKE_CURRENT_SOURCE_DIR}/include
308+ ${CMAKE_CURRENT_SOURCE_DIR}/src
309+
310+ ${compiz_SOURCE_DIR}/gtk/window-decorator
311+
312+ ${Boost_INCLUDE_DIRS}
313+
314+ ${LOCAL_MENUS_INCLUDE_DIRS}
315+ ${METACITY_INCLUDE_DIRS}
316+)
317+
318+LINK_DIRECTORIES (${LOCAL_MENUS_LIBRARY_DIRS})
319+
320+SET(
321+ PUBLIC_HEADERS
322+)
323+
324+SET(
325+ PRIVATE_HEADERS
326+ ${CMAKE_CURRENT_SOURCE_DIR}/src/local-menus.h
327+)
328+
329+SET(
330+ SRCS
331+ ${CMAKE_CURRENT_SOURCE_DIR}/src/local-menus.c
332+)
333+
334+ADD_LIBRARY(
335+ gtk_window_decorator_local_menus STATIC
336+
337+ ${SRCS}
338+
339+ ${PUBLIC_HEADERS}
340+ ${PRIVATE_HEADERS}
341+)
342+
343+IF (COMPIZ_BUILD_TESTING)
344+ADD_SUBDIRECTORY( ${CMAKE_CURRENT_SOURCE_DIR}/tests )
345+ENDIF (COMPIZ_BUILD_TESTING)
346+
347+SET_TARGET_PROPERTIES(
348+ gtk_window_decorator_local_menus PROPERTIES
349+ PUBLIC_HEADER "${PUBLIC_HEADERS}"
350+)
351+
352+install (FILES ${PUBLIC_HEADERS} DESTINATION ${COMPIZ_CORE_INCLUDE_DIR})
353+
354+TARGET_LINK_LIBRARIES(
355+ gtk_window_decorator_local_menus
356+
357+ ${LOCAL_MENUS_LIBRARIES}
358+)
359+
360
361=== added directory 'gtk/window-decorator/local-menus/include'
362=== added directory 'gtk/window-decorator/local-menus/src'
363=== added file 'gtk/window-decorator/local-menus/src/local-menus.c'
364--- gtk/window-decorator/local-menus/src/local-menus.c 1970-01-01 00:00:00 +0000
365+++ gtk/window-decorator/local-menus/src/local-menus.c 2012-02-21 10:38:22 +0000
366@@ -0,0 +1,331 @@
367+/*
368+ * Copyright © 2006 Novell, Inc.
369+ *
370+ * This library is free software; you can redistribute it and/or
371+ * modify it under the terms of the GNU Lesser General Public
372+ * License as published by the Free Software Foundation; either
373+ * version 2 of the License, or (at your option) any later version.
374+ *
375+ * This library is distributed in the hope that it will be useful,
376+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
377+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
378+ * Lesser General Public License for more details.
379+ *
380+ * You should have received a copy of the GNU Lesser General Public
381+ * License along with this library; if not, write to the
382+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
383+ * Boston, MA 02111-1307, USA.
384+ *
385+ * Author: David Reveman <davidr@novell.com>
386+ *
387+ * 2D Mode: Copyright © 2010 Sam Spilsbury <smspillaz@gmail.com>
388+ * Frames Management: Copright © 2011 Canonical Ltd.
389+ * Authored By: Sam Spilsbury <sam.spilsbury@canonical.com>
390+ */
391+
392+#include <string.h>
393+#include "local-menus.h"
394+#include <gdk/gdk.h>
395+#include <gdk/gdkx.h>
396+
397+#define GLOBAL 0
398+#define LOCAL 1
399+
400+gint menu_mode = GLOBAL;
401+
402+#ifdef META_HAS_LOCAL_MENUS
403+static void
404+gwd_menu_mode_changed (GSettings *settings,
405+ gchar *key,
406+ gpointer user_data)
407+{
408+ menu_mode = g_settings_get_enum (settings, "menu-mode");
409+}
410+#endif
411+
412+active_local_menu *active_menu;
413+pending_local_menu *pending_menu;
414+
415+gboolean
416+gwd_window_should_have_local_menu (WnckWindow *win)
417+{
418+#ifdef META_HAS_LOCAL_MENUS
419+ const gchar * const *schemas = g_settings_list_schemas ();
420+ static GSettings *lim_settings = NULL;
421+ while (*schemas != NULL && !lim_settings)
422+ {
423+ if (g_str_equal (*schemas, "com.canonical.indicator.appmenu"))
424+ {
425+ lim_settings = g_settings_new ("com.canonical.indicator.appmenu");
426+ menu_mode = g_settings_get_enum (lim_settings, "menu-mode");
427+ g_signal_connect (lim_settings, "changed::menu-mode", G_CALLBACK (gwd_menu_mode_changed), NULL);
428+ break;
429+ }
430+ ++schemas;
431+ }
432+
433+ if (lim_settings)
434+ return menu_mode == LOCAL;
435+#endif
436+
437+ return FALSE;
438+}
439+
440+gchar *
441+gwd_get_entry_id_from_sync_variant (GVariant *args)
442+{
443+ /* We need to get the indicator data once we've called show */
444+
445+ GVariantIter* iter = NULL;
446+ gchar* name_hint = NULL;
447+ gchar* indicator_id = NULL;
448+ gchar* entry_id = NULL;
449+ gchar* label = NULL;
450+ gboolean label_sensitive = FALSE;
451+ gboolean label_visible = FALSE;
452+ guint32 image_type = 0;
453+ gchar* image_data = NULL;
454+ gboolean image_sensitive = FALSE;
455+ gboolean image_visible = FALSE;
456+ gint32 priority = -1;
457+
458+ g_variant_get (args, "(a(ssssbbusbbi))", &iter);
459+ while (g_variant_iter_loop (iter, "(ssssbbusbbi)",
460+ &indicator_id,
461+ &entry_id,
462+ &name_hint,
463+ &label,
464+ &label_sensitive,
465+ &label_visible,
466+ &image_type,
467+ &image_data,
468+ &image_sensitive,
469+ &image_visible,
470+ &priority))
471+ {
472+ g_variant_unref (args);
473+ return g_strdup (entry_id);
474+ }
475+
476+ g_variant_unref (args);
477+ g_assert_not_reached ();
478+ return NULL;
479+}
480+#ifdef META_HAS_LOCAL_MENUS
481+static void
482+on_local_menu_activated (GDBusProxy *proxy,
483+ gchar *sender_name,
484+ gchar *signal_name,
485+ GVariant *parameters,
486+ gpointer user_data)
487+{
488+
489+ if (g_strcmp0 (signal_name, "EntryActivated") == 0)
490+ {
491+ show_local_menu_data *d = (show_local_menu_data *) user_data;
492+ gchar *entry_id = NULL;
493+ gint x_out, y_out;
494+ guint width, height;
495+
496+ g_variant_get (parameters, "(s(iiuu))", &entry_id, &x_out, &y_out, &width, &height, NULL);
497+
498+ if (!d->local_menu_entry_id)
499+ {
500+ GError *error = NULL;
501+ GVariant *params = g_variant_new ("(s)", "libappmenu.so", NULL);
502+ GVariant *args = g_dbus_proxy_call_sync (proxy, "SyncOne", params, 0, 500, NULL, &error);
503+
504+ g_assert_no_error (error);
505+ d->local_menu_entry_id = gwd_get_entry_id_from_sync_variant (args);
506+ }
507+
508+ if (g_strcmp0 (entry_id, d->local_menu_entry_id) == 0)
509+ {
510+ d->rect->x = x_out - d->dx;
511+ d->rect->y = y_out - d->dy;
512+ d->rect->width = width;
513+ d->rect->height = height;
514+ }
515+ else if (g_strcmp0 (entry_id, "") == 0)
516+ {
517+ memset (d->rect, 0, sizeof (GdkRectangle));
518+ (*d->cb) (d->user_data);
519+
520+ g_signal_handlers_disconnect_by_func (d->proxy, on_local_menu_activated, d);
521+
522+ g_object_unref (d->proxy);
523+ g_object_unref (d->conn);
524+
525+ if (active_menu)
526+ {
527+ g_free (active_menu);
528+ active_menu = NULL;
529+ }
530+
531+ g_free (d->local_menu_entry_id);
532+ g_free (d);
533+ }
534+ }
535+
536+}
537+#endif
538+gboolean
539+gwd_move_window_instead (gpointer user_data)
540+{
541+ (*pending_menu->cb) (pending_menu->user_data);
542+ g_free (pending_menu->user_data);
543+ g_free (pending_menu);
544+ pending_menu = NULL;
545+ return FALSE;
546+}
547+
548+void
549+gwd_prepare_show_local_menu (start_move_window_cb start_move_window,
550+ gpointer user_data_start_move_window)
551+{
552+ if (pending_menu)
553+ {
554+ g_source_remove (pending_menu->move_timeout_id);
555+ g_free (pending_menu->user_data);
556+ g_free (pending_menu);
557+ pending_menu = NULL;
558+ }
559+
560+ pending_menu = g_new0 (pending_local_menu, 1);
561+ pending_menu->cb = start_move_window;
562+ pending_menu->user_data = user_data_start_move_window;
563+ pending_menu->move_timeout_id = g_timeout_add (120, gwd_move_window_instead, pending_menu);
564+}
565+
566+void
567+gwd_show_local_menu (Display *xdisplay,
568+ Window frame_xwindow,
569+ int x,
570+ int y,
571+ int x_win,
572+ int y_win,
573+ int button,
574+ guint32 timestamp,
575+ show_window_menu_hidden_cb cb,
576+ gpointer user_data_show_window_menu)
577+{
578+ if (pending_menu)
579+ {
580+ g_source_remove (pending_menu->move_timeout_id);
581+ g_free (pending_menu->user_data);
582+ g_free (pending_menu);
583+ pending_menu = NULL;
584+ }
585+
586+#ifdef META_HAS_LOCAL_MENUS
587+ GError *error = NULL;
588+ GDBusConnection *conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
589+
590+
591+ XUngrabPointer (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), CurrentTime);
592+ XUngrabKeyboard (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), CurrentTime);
593+ XSync (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), FALSE);
594+
595+ if (!conn)
596+ {
597+ g_print ("error getting connection: %s\n", error->message);
598+ return;
599+ }
600+
601+ GDBusProxy *proxy = g_dbus_proxy_new_sync (conn, 0, NULL, "com.canonical.Unity.Panel.Service",
602+ "/com/canonical/Unity/Panel/Service",
603+ "com.canonical.Unity.Panel.Service",
604+ NULL, &error);
605+
606+ if (proxy)
607+ {
608+ GVariant *message = g_variant_new ("(uiiu)", frame_xwindow, x, y, time);
609+ g_dbus_proxy_call_sync (proxy, "ShowAppMenu", message, 0, 500, NULL, &error);
610+ if (error)
611+ {
612+ g_print ("error calling ShowAppMenu: %s\n", error->message);
613+ g_object_unref (proxy);
614+ g_object_unref (conn);
615+ return;
616+ }
617+
618+ show_local_menu_data *data = g_new0 (show_local_menu_data, 1);
619+
620+ if (active_menu)
621+ g_free (active_menu);
622+
623+ active_menu = g_new0 (active_local_menu, 1);
624+
625+ data->conn = g_object_ref (conn);
626+ data->proxy = g_object_ref (proxy);
627+ data->cb = cb;
628+ data->user_data = user_data_show_window_menu;
629+ data->rect = &active_menu->rect;
630+ data->dx = x - x_win;
631+ data->dy = y - y_win;
632+ data->local_menu_entry_id = NULL;
633+
634+ g_signal_connect (proxy, "g-signal", G_CALLBACK (on_local_menu_activated), data);
635+
636+ g_object_unref (conn);
637+ g_object_unref (proxy);
638+
639+ return;
640+ }
641+ else
642+ {
643+ g_print ("error getting proxy: %s\n", error->message);
644+ }
645+
646+ g_object_unref (conn);
647+#endif
648+}
649+
650+void
651+force_local_menus_on (WnckWindow *win,
652+ MetaButtonLayout *button_layout)
653+{
654+#ifdef META_HAS_LOCAL_MENUS
655+ if (gwd_window_should_have_local_menu (win))
656+ {
657+ if (button_layout->left_buttons[0] != META_BUTTON_FUNCTION_LAST)
658+ {
659+ unsigned int i = 0;
660+ for (; i < MAX_BUTTONS_PER_CORNER; i++)
661+ {
662+ if (button_layout->left_buttons[i] == META_BUTTON_FUNCTION_WINDOW_MENU)
663+ break;
664+ else if (button_layout->left_buttons[i] == META_BUTTON_FUNCTION_LAST)
665+ {
666+ if ((i + 1) < MAX_BUTTONS_PER_CORNER)
667+ {
668+ button_layout->left_buttons[i + 1] = META_BUTTON_FUNCTION_LAST;
669+ button_layout->left_buttons[i] = META_BUTTON_FUNCTION_WINDOW_MENU;
670+ break;
671+ }
672+ }
673+ }
674+ }
675+ if (button_layout->right_buttons[0] != META_BUTTON_FUNCTION_LAST)
676+ {
677+ unsigned int i = 0;
678+ for (; i < MAX_BUTTONS_PER_CORNER; i++)
679+ {
680+ if (button_layout->right_buttons[i] == META_BUTTON_FUNCTION_WINDOW_MENU)
681+ break;
682+ else if (button_layout->right_buttons[i] == META_BUTTON_FUNCTION_LAST)
683+ {
684+ if ((i + 1) < MAX_BUTTONS_PER_CORNER)
685+ {
686+ button_layout->right_buttons[i + 1] = META_BUTTON_FUNCTION_LAST;
687+ button_layout->right_buttons[i] = META_BUTTON_FUNCTION_WINDOW_MENU;
688+ break;
689+ }
690+ }
691+ }
692+ }
693+ }
694+#endif
695+}
696+
697+
698
699=== added file 'gtk/window-decorator/local-menus/src/local-menus.h'
700--- gtk/window-decorator/local-menus/src/local-menus.h 1970-01-01 00:00:00 +0000
701+++ gtk/window-decorator/local-menus/src/local-menus.h 2012-02-21 10:38:22 +0000
702@@ -0,0 +1,95 @@
703+/*
704+ * Copyright © 2006 Novell, Inc.
705+ *
706+ * This library is free software; you can redistribute it and/or
707+ * modify it under the terms of the GNU Lesser General Public
708+ * License as published by the Free Software Foundation; either
709+ * version 2 of the License, or (at your option) any later version.
710+ *
711+ * This library is distributed in the hope that it will be useful,
712+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
713+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
714+ * Lesser General Public License for more details.
715+ *
716+ * You should have received a copy of the GNU Lesser General Public
717+ * License along with this library; if not, write to the
718+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
719+ * Boston, MA 02111-1307, USA.
720+ *
721+ * Author: David Reveman <davidr@novell.com>
722+ *
723+ * 2D Mode: Copyright © 2010 Sam Spilsbury <smspillaz@gmail.com>
724+ * Frames Management: Copright © 2011 Canonical Ltd.
725+ * Authored By: Sam Spilsbury <sam.spilsbury@canonical.com>
726+ */
727+
728+#ifdef __cplusplus
729+extern "C"
730+{
731+#endif
732+
733+#include <glib.h>
734+#include <gio/gio.h>
735+#ifndef WNCK_I_KNOW_THIS_IS_UNSTABLE
736+#define WNCK_I_KNOW_THIS_IS_UNSTABLE
737+#endif
738+#include <libwnck/libwnck.h>
739+#include <libwnck/window-action-menu.h>
740+#include <metacity-private/theme.h>
741+
742+typedef void (*show_window_menu_hidden_cb) (gpointer);
743+typedef void (*start_move_window_cb) (gpointer);
744+
745+typedef struct _pending_local_menu
746+{
747+ gint move_timeout_id;
748+ gpointer user_data;
749+ start_move_window_cb cb;
750+} pending_local_menu;
751+
752+typedef struct _active_local_menu
753+{
754+ GdkRectangle rect;
755+} active_local_menu;
756+
757+extern active_local_menu *active_menu;
758+
759+typedef struct _show_local_menu_data
760+{
761+ GDBusConnection *conn;
762+ GDBusProxy *proxy;
763+ show_window_menu_hidden_cb cb;
764+ gpointer user_data;
765+ GdkRectangle *rect;
766+ gint dx;
767+ gint dy;
768+ gchar *local_menu_entry_id;
769+} show_local_menu_data;
770+
771+gboolean
772+gwd_window_should_have_local_menu (WnckWindow *win);
773+
774+void
775+force_local_menus_on (WnckWindow *win,
776+ MetaButtonLayout *layout);
777+
778+/* Button Down */
779+void
780+gwd_prepare_show_local_menu (start_move_window_cb start_move_window,
781+ gpointer user_data_start_move_window);
782+
783+/* Button Up */
784+void
785+gwd_show_local_menu (Display *xdisplay,
786+ Window frame_xwindow,
787+ int x,
788+ int y,
789+ int x_win,
790+ int y_win,
791+ int button,
792+ guint32 timestamp,
793+ show_window_menu_hidden_cb cb,
794+ gpointer user_data_show_window_menu);
795+#ifdef __cplusplus
796+}
797+#endif
798
799=== added directory 'gtk/window-decorator/local-menus/tests'
800=== added file 'gtk/window-decorator/local-menus/tests/CMakeLists.txt'
801--- gtk/window-decorator/local-menus/tests/CMakeLists.txt 1970-01-01 00:00:00 +0000
802+++ gtk/window-decorator/local-menus/tests/CMakeLists.txt 2012-02-21 10:38:22 +0000
803@@ -0,0 +1,3 @@
804+include_directories (${CMAKE_CURRENT_SOURCE_DIR})
805+add_subdirectory (check_local_menu_on_off)
806+add_subdirectory (force_local_menu_on)
807
808=== added directory 'gtk/window-decorator/local-menus/tests/check_local_menu_on_off'
809=== added file 'gtk/window-decorator/local-menus/tests/check_local_menu_on_off/CMakeLists.txt'
810--- gtk/window-decorator/local-menus/tests/check_local_menu_on_off/CMakeLists.txt 1970-01-01 00:00:00 +0000
811+++ gtk/window-decorator/local-menus/tests/check_local_menu_on_off/CMakeLists.txt 2012-02-21 10:38:22 +0000
812@@ -0,0 +1,21 @@
813+include_directories (${CMAKE_CURRENT_SOURCE_DIR}
814+ ${compiz_SOURCE_DIR}/gtk/window-decorator/local-menus/tests
815+ ${compiz_SOURCE_DIR}/gtk/window-decorator
816+ ${compiz_SOURCE_DIR}/gtk/window-decorator/local-menus/src)
817+
818+add_executable(
819+ gtk_window_decorator_check_local_menu_on_off_test
820+
821+ ${CMAKE_CURRENT_SOURCE_DIR}/test-local-menu-on-off.cpp
822+)
823+
824+target_link_libraries(
825+ gtk_window_decorator_check_local_menu_on_off_test
826+
827+ gtk_window_decorator_local_menus
828+
829+ ${GTEST_BOTH_LIBRARIES}
830+ ${CMAKE_THREAD_LIBS_INIT} # Link in pthread.
831+)
832+
833+add_test (gtk_window_decorator_local_menus_on_off gtk_window_decorator_check_local_menu_on_off_test)
834
835=== added directory 'gtk/window-decorator/local-menus/tests/check_local_menu_on_off/check_local_menu_on_off'
836=== added directory 'gtk/window-decorator/local-menus/tests/check_local_menu_on_off/check_local_menu_on_off/CMakeFiles'
837=== added file 'gtk/window-decorator/local-menus/tests/check_local_menu_on_off/test-local-menu-on-off.cpp'
838--- gtk/window-decorator/local-menus/tests/check_local_menu_on_off/test-local-menu-on-off.cpp 1970-01-01 00:00:00 +0000
839+++ gtk/window-decorator/local-menus/tests/check_local_menu_on_off/test-local-menu-on-off.cpp 2012-02-21 10:38:22 +0000
840@@ -0,0 +1,20 @@
841+#include "test-local-menu.h"
842+
843+#define GLOBAL 0
844+#define LOCAL 1
845+
846+TEST_F (GtkWindowDecoratorTestLocalMenu, TestOn)
847+{
848+ g_settings_set_enum (getSettings (), "menu-mode", LOCAL);
849+ gboolean result = gwd_window_should_have_local_menu (getWindow ());
850+
851+ EXPECT_TRUE (result);
852+}
853+
854+TEST_F (GtkWindowDecoratorTestLocalMenu, TestOff)
855+{
856+ g_settings_set_enum (getSettings (), "menu-mode", GLOBAL);
857+ gboolean result = gwd_window_should_have_local_menu (getWindow ());
858+
859+ EXPECT_FALSE (result);
860+}
861
862=== added directory 'gtk/window-decorator/local-menus/tests/force_local_menu_on'
863=== added file 'gtk/window-decorator/local-menus/tests/force_local_menu_on/CMakeLists.txt'
864--- gtk/window-decorator/local-menus/tests/force_local_menu_on/CMakeLists.txt 1970-01-01 00:00:00 +0000
865+++ gtk/window-decorator/local-menus/tests/force_local_menu_on/CMakeLists.txt 2012-02-21 10:38:22 +0000
866@@ -0,0 +1,21 @@
867+include_directories (${CMAKE_CURRENT_SOURCE_DIR}
868+ ${compiz_SOURCE_DIR}/gtk/window-decorator/local-menus/tests
869+ ${compiz_SOURCE_DIR}/gtk/window-decorator
870+ ${compiz_SOURCE_DIR}/gtk/window-decorator/local-menus/src)
871+
872+add_executable(
873+ gtk_window_decorator_force_local_menu_on_test
874+
875+ ${CMAKE_CURRENT_SOURCE_DIR}/test-force-local-menu-on.cpp
876+)
877+
878+target_link_libraries(
879+ gtk_window_decorator_force_local_menu_on_test
880+
881+ gtk_window_decorator_local_menus
882+
883+ ${GTEST_BOTH_LIBRARIES}
884+ ${CMAKE_THREAD_LIBS_INIT} # Link in pthread.
885+)
886+
887+add_test (gtk_window_decorator_force_local_menu_on gtk_window_decorator_force_local_menu_on_test)
888
889=== added file 'gtk/window-decorator/local-menus/tests/force_local_menu_on/test-force-local-menu-on.cpp'
890--- gtk/window-decorator/local-menus/tests/force_local_menu_on/test-force-local-menu-on.cpp 1970-01-01 00:00:00 +0000
891+++ gtk/window-decorator/local-menus/tests/force_local_menu_on/test-force-local-menu-on.cpp 2012-02-21 10:38:22 +0000
892@@ -0,0 +1,70 @@
893+#include "test-local-menu.h"
894+#include <cstring>
895+
896+#define GLOBAL 0
897+#define LOCAL 1
898+
899+namespace
900+{
901+ void initializeMetaButtonLayout (MetaButtonLayout *layout)
902+ {
903+ memset (layout, 0, sizeof (MetaButtonLayout));
904+
905+ unsigned int i;
906+
907+ for (i = 0; i < MAX_BUTTONS_PER_CORNER; i++)
908+ {
909+ layout->right_buttons[i] = META_BUTTON_FUNCTION_LAST;
910+ layout->left_buttons[i] = META_BUTTON_FUNCTION_LAST;
911+ }
912+ }
913+}
914+
915+class GtkWindowDecoratorTestLocalMenuLayout :
916+ public GtkWindowDecoratorTestLocalMenu
917+{
918+ public:
919+
920+ MetaButtonLayout * getLayout () { return &mLayout; }
921+
922+ virtual void SetUp ()
923+ {
924+ GtkWindowDecoratorTestLocalMenu::SetUp ();
925+ ::initializeMetaButtonLayout (&mLayout);
926+ g_settings_set_enum (getSettings (), "menu-mode", LOCAL);
927+ }
928+
929+ private:
930+
931+ MetaButtonLayout mLayout;
932+};
933+
934+TEST_F (GtkWindowDecoratorTestLocalMenuLayout, TestForceNoButtonsSet)
935+{
936+ force_local_menus_on (getWindow (), getLayout ());
937+
938+ EXPECT_EQ (getLayout ()->right_buttons[0], META_BUTTON_FUNCTION_LAST);
939+ EXPECT_EQ (getLayout ()->left_buttons[0], META_BUTTON_FUNCTION_LAST);
940+}
941+
942+TEST_F (GtkWindowDecoratorTestLocalMenuLayout, TestForceNoCloseButtonSet)
943+{
944+ getLayout ()->right_buttons[0] = META_BUTTON_FUNCTION_CLOSE;
945+
946+ force_local_menus_on (getWindow (), getLayout ());
947+
948+ EXPECT_EQ (getLayout ()->right_buttons[1], META_BUTTON_FUNCTION_WINDOW_MENU);
949+ EXPECT_EQ (getLayout ()->left_buttons[0], META_BUTTON_FUNCTION_LAST);
950+}
951+
952+TEST_F (GtkWindowDecoratorTestLocalMenuLayout, TestForceNoCloseMinimizeMaximizeButtonSet)
953+{
954+ getLayout ()->left_buttons[0] = META_BUTTON_FUNCTION_CLOSE;
955+ getLayout ()->left_buttons[1] = META_BUTTON_FUNCTION_CLOSE;
956+ getLayout ()->left_buttons[2] = META_BUTTON_FUNCTION_CLOSE;
957+
958+ force_local_menus_on (getWindow (), getLayout ());
959+
960+ EXPECT_EQ (getLayout ()->right_buttons[0], META_BUTTON_FUNCTION_LAST);
961+ EXPECT_EQ (getLayout ()->left_buttons[3], META_BUTTON_FUNCTION_WINDOW_MENU);
962+}
963
964=== added directory 'gtk/window-decorator/local-menus/tests/show_hide_menu'
965=== added file 'gtk/window-decorator/local-menus/tests/test-local-menu.h'
966--- gtk/window-decorator/local-menus/tests/test-local-menu.h 1970-01-01 00:00:00 +0000
967+++ gtk/window-decorator/local-menus/tests/test-local-menu.h 2012-02-21 10:38:22 +0000
968@@ -0,0 +1,48 @@
969+#include <gtest/gtest.h>
970+#include <gmock/gmock.h>
971+#include "local-menus.h"
972+#include <X11/Xlib.h>
973+#include <gio/gio.h>
974+
975+class GtkWindowDecoratorTestLocalMenu :
976+ public ::testing::Test
977+{
978+ public:
979+
980+ WnckWindow * getWindow () { return mWindow; }
981+ GSettings * getSettings () { return mSettings; }
982+
983+ virtual void SetUp ()
984+ {
985+ gtk_init (NULL, NULL);
986+
987+ mXDisplay = XOpenDisplay (NULL);
988+ mXWindow = XCreateSimpleWindow (mXDisplay, DefaultRootWindow (mXDisplay), 0, 0, 100, 100, 0, 0, 0);
989+
990+ XMapRaised (mXDisplay, mXWindow);
991+
992+ XFlush (mXDisplay);
993+
994+ while (g_main_context_iteration (g_main_context_default (), FALSE));
995+
996+ mWindow = wnck_window_get (mXWindow);
997+
998+ g_setenv("GSETTINGS_BACKEND", "memory", true);
999+ mSettings = g_settings_new ("com.canonical.indicator.appmenu");
1000+ }
1001+
1002+ virtual void TearDown ()
1003+ {
1004+ XDestroyWindow (mXDisplay, mXWindow);
1005+ XCloseDisplay (mXDisplay);
1006+
1007+ g_object_unref (mSettings);
1008+ }
1009+
1010+ private:
1011+
1012+ WnckWindow *mWindow;
1013+ Window mXWindow;
1014+ Display *mXDisplay;
1015+ GSettings *mSettings;
1016+};
1017
1018=== modified file 'gtk/window-decorator/metacity.c'
1019--- gtk/window-decorator/metacity.c 2012-02-16 06:51:37 +0000
1020+++ gtk/window-decorator/metacity.c 2012-02-21 10:38:22 +0000
1021@@ -24,6 +24,7 @@
1022 */
1023
1024 #include "gtk-window-decorator.h"
1025+#include "local-menus.h"
1026
1027 #ifdef USE_METACITY
1028
1029@@ -488,6 +489,8 @@
1030 button_layout->right_buttons[i] = META_BUTTON_FUNCTION_LAST;
1031 }
1032
1033+ force_local_menus_on (d->win, button_layout);
1034+
1035 *flags = 0;
1036
1037 if (d->actions & WNCK_WINDOW_ACTION_CLOSE)
1038@@ -558,6 +561,15 @@
1039 else
1040 clip->height = d->border_layout.left.y2 - d->border_layout.left.y1;
1041
1042+ memset (fgeom, 0, sizeof (MetaFrameGeometry));
1043+
1044+#ifdef META_HAS_LOCAL_MENUS
1045+
1046+ if (d->layout)
1047+ fgeom->text_layout = g_object_ref (d->layout);
1048+
1049+#endif
1050+
1051 meta_theme_calc_geometry (theme,
1052 frame_type,
1053 d->frame->text_height,
1054@@ -567,6 +579,15 @@
1055 button_layout,
1056 fgeom);
1057
1058+#ifdef META_HAS_LOCAL_MENUS
1059+
1060+ if (d->layout)
1061+ g_object_unref (fgeom->text_layout);
1062+
1063+ fgeom->text_layout = NULL;
1064+
1065+#endif
1066+
1067 clip->width += left_width + right_width;
1068 clip->height += top_height + bottom_height;
1069 }
1070@@ -601,6 +622,11 @@
1071 GdkColor bg_color;
1072 double bg_alpha;
1073
1074+ memset (&button_layout, 0, sizeof (MetaButtonLayout));
1075+
1076+ for (i = 0; i < MAX_BUTTONS_PER_CORNER; i++)
1077+ button_layout.left_buttons[i] = button_layout.right_buttons[i] = META_BUTTON_FUNCTION_LAST;
1078+
1079 if (!d->pixmap || !d->picture)
1080 return;
1081
1082@@ -675,6 +701,9 @@
1083
1084 size = MAX (fgeom.top_height, fgeom.bottom_height);
1085
1086+ if (active_menu)
1087+ g_object_set_data (G_OBJECT (style_window), "local_menu_rect", &active_menu->rect);
1088+
1089 if (rect.width && size)
1090 {
1091 XRenderPictFormat *format;
1092@@ -899,6 +928,9 @@
1093 XRenderFreePicture (xdisplay, src);
1094 }
1095
1096+ if (active_menu)
1097+ g_object_set_data (G_OBJECT (style_window), "local_menu_rect", NULL);
1098+
1099 copy_to_front_buffer (d);
1100
1101 if (d->frame_window)
1102@@ -1078,6 +1110,15 @@
1103 break;
1104 #endif
1105
1106+#ifdef META_HAS_LOCAL_MENUS
1107+ case BUTTON_WINDOW_MENU:
1108+ if (!meta_button_present (&button_layout, META_BUTTON_FUNCTION_WINDOW_MENU))
1109+ return FALSE;
1110+
1111+ space = &fgeom.window_menu_rect;
1112+ break;
1113+#endif
1114+
1115 default:
1116 return FALSE;
1117 }
1118@@ -1266,6 +1307,8 @@
1119 MetaTheme *theme;
1120 GdkRectangle clip;
1121
1122+ memset (&fgeom, 0, sizeof (MetaFrameGeometry));
1123+
1124 theme = meta_theme_get_current ();
1125
1126 meta_get_decoration_geometry (d, theme, &flags, &fgeom, &button_layout,
1127@@ -1490,6 +1533,11 @@
1128 return META_BUTTON_FUNCTION_UNSTICK;
1129 #endif
1130
1131+#ifdef META_HAS_LOCAL_MENUS
1132+ else if (strcmp (str, "window_menu") == 0)
1133+ return META_BUTTON_FUNCTION_WINDOW_MENU;
1134+#endif
1135+
1136 else
1137 return META_BUTTON_FUNCTION_LAST;
1138 }
1139
1140=== modified file 'gtk/window-decorator/wnck.c'
1141--- gtk/window-decorator/wnck.c 2012-02-10 10:23:27 +0000
1142+++ gtk/window-decorator/wnck.c 2012-02-21 10:38:22 +0000
1143@@ -738,7 +738,8 @@
1144 stick_button_event,
1145 unshade_button_event,
1146 unabove_button_event,
1147- unstick_button_event
1148+ unstick_button_event,
1149+ window_menu_button_event
1150 };
1151
1152 d = calloc (1, sizeof (decor_t));

Subscribers

People subscribed via source and target branches