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: 1167 lines (+888/-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 (+27/-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 (+77/-0)
gtk/window-decorator/local-menus/tests/test-local-menu.h (+49/-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+94091@code.launchpad.net

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

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 : Posted in a previous version of this proposal

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
Revision history for this message
Sam Spilsbury (smspillaz) wrote :

Tests needed to be disabled on META_HAS_LOCAL_MENUS, thanks for catching that.

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

Test cases fail (crash). Maybe they need to be disabled if local menus are disabled...

The following tests FAILED:
   1 - gtk_window_decorator_local_menus_on_off (SEGFAULT)
   2 - gtk_window_decorator_force_local_menu_on (SEGFAULT)
Errors while running CTest
make: *** [test] Error 8

-----

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff709bb70 in ?? () from /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0
(gdb) bt
#0 0x00007ffff709bb70 in ?? () from /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0
#1 0x00007ffff709e2f5 in ?? () from /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0
#2 0x00007ffff6dc29f0 in g_object_unref ()
   from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#3 0x000000000042ef7d in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) ()
#4 0x000000000042751f in testing::Test::Run() ()
#5 0x000000000042763d in testing::TestInfo::Run() ()
#6 0x0000000000427787 in testing::TestCase::Run() ()
#7 0x0000000000427a17 in testing::internal::UnitTestImpl::RunAllTests() ()
#8 0x000000000042eafd in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) ()
#9 0x0000000000426c0b in testing::UnitTest::Run() ()
#10 0x0000000000413145 in main ()

-----

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff709bb70 in ?? () from /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0
(gdb) bt
#0 0x00007ffff709bb70 in ?? () from /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0
#1 0x00007ffff709e2f5 in ?? () from /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0
#2 0x00007ffff6dc29f0 in g_object_unref ()
   from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#3 0x000000000042ef7d in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) ()
#4 0x000000000042751f in testing::Test::Run() ()
#5 0x000000000042763d in testing::TestInfo::Run() ()
#6 0x0000000000427787 in testing::TestCase::Run() ()
#7 0x0000000000427a17 in testing::internal::UnitTestImpl::RunAllTests() ()
#8 0x000000000042eafd in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) ()
#9 0x0000000000426c0b in testing::UnitTest::Run() ()
#10 0x0000000000413145 in main ()

review: Needs Fixing
Revision history for this message
Sam Spilsbury (smspillaz) wrote :

Huh, that's weird. I've disabled META_HAS_LOCAL_MENUS here, and make sure to link to the system libmetacity-private and the tests are still passing for me.

Can you post the output of the individual tests before it reaches the point where they crash? Or do they just crash without outputting anything ?

(Could be something to do with the SetUp () function, so I'll give that a try

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-22 08:43:17 +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-22 08:43:17 +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-22 08:43:17 +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-22 08:43:17 +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-22 08:43:17 +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-22 08:43:17 +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-22 08:43:17 +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-22 08:43:17 +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-22 08:43:17 +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-22 08:43:17 +0000
840@@ -0,0 +1,27 @@
841+#include "test-local-menu.h"
842+
843+#define GLOBAL 0
844+#define LOCAL 1
845+#ifdef META_HAS_LOCAL_MENUS
846+
847+TEST_F (GtkWindowDecoratorTestLocalMenu, TestOn)
848+{
849+ g_settings_set_enum (getSettings (), "menu-mode", LOCAL);
850+ gboolean result = gwd_window_should_have_local_menu (getWindow ());
851+
852+ EXPECT_TRUE (result);
853+}
854+
855+TEST_F (GtkWindowDecoratorTestLocalMenu, TestOff)
856+{
857+ g_settings_set_enum (getSettings (), "menu-mode", GLOBAL);
858+ gboolean result = gwd_window_should_have_local_menu (getWindow ());
859+
860+ EXPECT_FALSE (result);
861+}
862+#else
863+TEST_F (GtkWindowDecoratorTestLocalMenu, NoMenus)
864+{
865+ ASSERT_TRUE (true) << "Local menus tests not enabled because META_HAS_LOCAL_MENUS is off";
866+}
867+#endif
868
869=== added directory 'gtk/window-decorator/local-menus/tests/force_local_menu_on'
870=== added file 'gtk/window-decorator/local-menus/tests/force_local_menu_on/CMakeLists.txt'
871--- gtk/window-decorator/local-menus/tests/force_local_menu_on/CMakeLists.txt 1970-01-01 00:00:00 +0000
872+++ gtk/window-decorator/local-menus/tests/force_local_menu_on/CMakeLists.txt 2012-02-22 08:43:17 +0000
873@@ -0,0 +1,21 @@
874+include_directories (${CMAKE_CURRENT_SOURCE_DIR}
875+ ${compiz_SOURCE_DIR}/gtk/window-decorator/local-menus/tests
876+ ${compiz_SOURCE_DIR}/gtk/window-decorator
877+ ${compiz_SOURCE_DIR}/gtk/window-decorator/local-menus/src)
878+
879+add_executable(
880+ gtk_window_decorator_force_local_menu_on_test
881+
882+ ${CMAKE_CURRENT_SOURCE_DIR}/test-force-local-menu-on.cpp
883+)
884+
885+target_link_libraries(
886+ gtk_window_decorator_force_local_menu_on_test
887+
888+ gtk_window_decorator_local_menus
889+
890+ ${GTEST_BOTH_LIBRARIES}
891+ ${CMAKE_THREAD_LIBS_INIT} # Link in pthread.
892+)
893+
894+add_test (gtk_window_decorator_force_local_menu_on gtk_window_decorator_force_local_menu_on_test)
895
896=== added file 'gtk/window-decorator/local-menus/tests/force_local_menu_on/test-force-local-menu-on.cpp'
897--- gtk/window-decorator/local-menus/tests/force_local_menu_on/test-force-local-menu-on.cpp 1970-01-01 00:00:00 +0000
898+++ gtk/window-decorator/local-menus/tests/force_local_menu_on/test-force-local-menu-on.cpp 2012-02-22 08:43:17 +0000
899@@ -0,0 +1,77 @@
900+#include "test-local-menu.h"
901+#include <cstring>
902+
903+#define GLOBAL 0
904+#define LOCAL 1
905+#ifdef META_HAS_LOCAL_MENUS
906+
907+namespace
908+{
909+ void initializeMetaButtonLayout (MetaButtonLayout *layout)
910+ {
911+ memset (layout, 0, sizeof (MetaButtonLayout));
912+
913+ unsigned int i;
914+
915+ for (i = 0; i < MAX_BUTTONS_PER_CORNER; i++)
916+ {
917+ layout->right_buttons[i] = META_BUTTON_FUNCTION_LAST;
918+ layout->left_buttons[i] = META_BUTTON_FUNCTION_LAST;
919+ }
920+ }
921+}
922+
923+class GtkWindowDecoratorTestLocalMenuLayout :
924+ public GtkWindowDecoratorTestLocalMenu
925+{
926+ public:
927+
928+ MetaButtonLayout * getLayout () { return &mLayout; }
929+
930+ virtual void SetUp ()
931+ {
932+ GtkWindowDecoratorTestLocalMenu::SetUp ();
933+ ::initializeMetaButtonLayout (&mLayout);
934+ g_settings_set_enum (getSettings (), "menu-mode", LOCAL);
935+ }
936+
937+ private:
938+
939+ MetaButtonLayout mLayout;
940+};
941+
942+TEST_F (GtkWindowDecoratorTestLocalMenuLayout, TestForceNoButtonsSet)
943+{
944+ force_local_menus_on (getWindow (), getLayout ());
945+
946+ EXPECT_EQ (getLayout ()->right_buttons[0], META_BUTTON_FUNCTION_LAST);
947+ EXPECT_EQ (getLayout ()->left_buttons[0], META_BUTTON_FUNCTION_LAST);
948+}
949+
950+TEST_F (GtkWindowDecoratorTestLocalMenuLayout, TestForceNoCloseButtonSet)
951+{
952+ getLayout ()->right_buttons[0] = META_BUTTON_FUNCTION_CLOSE;
953+
954+ force_local_menus_on (getWindow (), getLayout ());
955+
956+ EXPECT_EQ (getLayout ()->right_buttons[1], META_BUTTON_FUNCTION_WINDOW_MENU);
957+ EXPECT_EQ (getLayout ()->left_buttons[0], META_BUTTON_FUNCTION_LAST);
958+}
959+
960+TEST_F (GtkWindowDecoratorTestLocalMenuLayout, TestForceNoCloseMinimizeMaximizeButtonSet)
961+{
962+ getLayout ()->left_buttons[0] = META_BUTTON_FUNCTION_CLOSE;
963+ getLayout ()->left_buttons[1] = META_BUTTON_FUNCTION_CLOSE;
964+ getLayout ()->left_buttons[2] = META_BUTTON_FUNCTION_CLOSE;
965+
966+ force_local_menus_on (getWindow (), getLayout ());
967+
968+ EXPECT_EQ (getLayout ()->right_buttons[0], META_BUTTON_FUNCTION_LAST);
969+ EXPECT_EQ (getLayout ()->left_buttons[3], META_BUTTON_FUNCTION_WINDOW_MENU);
970+}
971+#else
972+TEST_F (GtkWindowDecoratorTestLocalMenu, NoMenus)
973+{
974+ ASSERT_TRUE (true) << "Local menus tests not enabled because META_HAS_LOCAL_MENUS is off";
975+}
976+#endif
977
978=== added directory 'gtk/window-decorator/local-menus/tests/show_hide_menu'
979=== added file 'gtk/window-decorator/local-menus/tests/test-local-menu.h'
980--- gtk/window-decorator/local-menus/tests/test-local-menu.h 1970-01-01 00:00:00 +0000
981+++ gtk/window-decorator/local-menus/tests/test-local-menu.h 2012-02-22 08:43:17 +0000
982@@ -0,0 +1,49 @@
983+#include <gtest/gtest.h>
984+#include <gmock/gmock.h>
985+#include "local-menus.h"
986+#include <X11/Xlib.h>
987+#include <gio/gio.h>
988+
989+class GtkWindowDecoratorTestLocalMenu :
990+ public ::testing::Test
991+{
992+ public:
993+
994+#ifdef META_HAS_LOCAL_MENUS
995+ WnckWindow * getWindow () { return mWindow; }
996+ GSettings * getSettings () { return mSettings; }
997+ virtual void SetUp ()
998+ {
999+ gtk_init (NULL, NULL);
1000+
1001+ mXDisplay = XOpenDisplay (NULL);
1002+ mXWindow = XCreateSimpleWindow (mXDisplay, DefaultRootWindow (mXDisplay), 0, 0, 100, 100, 0, 0, 0);
1003+
1004+ XMapRaised (mXDisplay, mXWindow);
1005+
1006+ XFlush (mXDisplay);
1007+
1008+ while (g_main_context_iteration (g_main_context_default (), FALSE));
1009+
1010+ mWindow = wnck_window_get (mXWindow);
1011+
1012+ g_setenv("GSETTINGS_BACKEND", "memory", true);
1013+ mSettings = g_settings_new ("com.canonical.indicator.appmenu");
1014+ }
1015+
1016+ virtual void TearDown ()
1017+ {
1018+ XDestroyWindow (mXDisplay, mXWindow);
1019+ XCloseDisplay (mXDisplay);
1020+
1021+ g_object_unref (mSettings);
1022+ }
1023+#endif
1024+
1025+ private:
1026+
1027+ WnckWindow *mWindow;
1028+ Window mXWindow;
1029+ Display *mXDisplay;
1030+ GSettings *mSettings;
1031+};
1032
1033=== modified file 'gtk/window-decorator/metacity.c'
1034--- gtk/window-decorator/metacity.c 2012-02-16 06:51:37 +0000
1035+++ gtk/window-decorator/metacity.c 2012-02-22 08:43:17 +0000
1036@@ -24,6 +24,7 @@
1037 */
1038
1039 #include "gtk-window-decorator.h"
1040+#include "local-menus.h"
1041
1042 #ifdef USE_METACITY
1043
1044@@ -488,6 +489,8 @@
1045 button_layout->right_buttons[i] = META_BUTTON_FUNCTION_LAST;
1046 }
1047
1048+ force_local_menus_on (d->win, button_layout);
1049+
1050 *flags = 0;
1051
1052 if (d->actions & WNCK_WINDOW_ACTION_CLOSE)
1053@@ -558,6 +561,15 @@
1054 else
1055 clip->height = d->border_layout.left.y2 - d->border_layout.left.y1;
1056
1057+ memset (fgeom, 0, sizeof (MetaFrameGeometry));
1058+
1059+#ifdef META_HAS_LOCAL_MENUS
1060+
1061+ if (d->layout)
1062+ fgeom->text_layout = g_object_ref (d->layout);
1063+
1064+#endif
1065+
1066 meta_theme_calc_geometry (theme,
1067 frame_type,
1068 d->frame->text_height,
1069@@ -567,6 +579,15 @@
1070 button_layout,
1071 fgeom);
1072
1073+#ifdef META_HAS_LOCAL_MENUS
1074+
1075+ if (d->layout)
1076+ g_object_unref (fgeom->text_layout);
1077+
1078+ fgeom->text_layout = NULL;
1079+
1080+#endif
1081+
1082 clip->width += left_width + right_width;
1083 clip->height += top_height + bottom_height;
1084 }
1085@@ -601,6 +622,11 @@
1086 GdkColor bg_color;
1087 double bg_alpha;
1088
1089+ memset (&button_layout, 0, sizeof (MetaButtonLayout));
1090+
1091+ for (i = 0; i < MAX_BUTTONS_PER_CORNER; i++)
1092+ button_layout.left_buttons[i] = button_layout.right_buttons[i] = META_BUTTON_FUNCTION_LAST;
1093+
1094 if (!d->pixmap || !d->picture)
1095 return;
1096
1097@@ -675,6 +701,9 @@
1098
1099 size = MAX (fgeom.top_height, fgeom.bottom_height);
1100
1101+ if (active_menu)
1102+ g_object_set_data (G_OBJECT (style_window), "local_menu_rect", &active_menu->rect);
1103+
1104 if (rect.width && size)
1105 {
1106 XRenderPictFormat *format;
1107@@ -899,6 +928,9 @@
1108 XRenderFreePicture (xdisplay, src);
1109 }
1110
1111+ if (active_menu)
1112+ g_object_set_data (G_OBJECT (style_window), "local_menu_rect", NULL);
1113+
1114 copy_to_front_buffer (d);
1115
1116 if (d->frame_window)
1117@@ -1078,6 +1110,15 @@
1118 break;
1119 #endif
1120
1121+#ifdef META_HAS_LOCAL_MENUS
1122+ case BUTTON_WINDOW_MENU:
1123+ if (!meta_button_present (&button_layout, META_BUTTON_FUNCTION_WINDOW_MENU))
1124+ return FALSE;
1125+
1126+ space = &fgeom.window_menu_rect;
1127+ break;
1128+#endif
1129+
1130 default:
1131 return FALSE;
1132 }
1133@@ -1266,6 +1307,8 @@
1134 MetaTheme *theme;
1135 GdkRectangle clip;
1136
1137+ memset (&fgeom, 0, sizeof (MetaFrameGeometry));
1138+
1139 theme = meta_theme_get_current ();
1140
1141 meta_get_decoration_geometry (d, theme, &flags, &fgeom, &button_layout,
1142@@ -1490,6 +1533,11 @@
1143 return META_BUTTON_FUNCTION_UNSTICK;
1144 #endif
1145
1146+#ifdef META_HAS_LOCAL_MENUS
1147+ else if (strcmp (str, "window_menu") == 0)
1148+ return META_BUTTON_FUNCTION_WINDOW_MENU;
1149+#endif
1150+
1151 else
1152 return META_BUTTON_FUNCTION_LAST;
1153 }
1154
1155=== modified file 'gtk/window-decorator/wnck.c'
1156--- gtk/window-decorator/wnck.c 2012-02-10 10:23:27 +0000
1157+++ gtk/window-decorator/wnck.c 2012-02-22 08:43:17 +0000
1158@@ -738,7 +738,8 @@
1159 stick_button_event,
1160 unshade_button_event,
1161 unabove_button_event,
1162- unstick_button_event
1163+ unstick_button_event,
1164+ window_menu_button_event
1165 };
1166
1167 d = calloc (1, sizeof (decor_t));

Subscribers

People subscribed via source and target branches