Merge lp:~smspillaz/compiz-core/compiz-core.lim into lp:compiz-core
- compiz-core.lim
- Merge into 0.9.7
Status: | Superseded |
---|---|
Proposed branch: | lp:~smspillaz/compiz-core/compiz-core.lim |
Merge into: | lp:compiz-core |
Diff against target: |
1432 lines (+1077/-11) 16 files modified
gtk/window-decorator/CMakeLists.txt (+6/-0) gtk/window-decorator/decorator.c (+32/-6) gtk/window-decorator/events.c (+115/-3) gtk/window-decorator/gtk-window-decorator.c (+56/-0) gtk/window-decorator/gtk-window-decorator.h (+8/-1) gtk/window-decorator/local-menus/CMakeLists.txt (+60/-0) gtk/window-decorator/local-menus/src/local-menus.c (+423/-0) gtk/window-decorator/local-menus/src/local-menus.h (+120/-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 (+54/-0) gtk/window-decorator/wnck.c (+5/-1) |
To merge this branch: | bzr merge lp:~smspillaz/compiz-core/compiz-core.lim |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Marco Trevisan (Treviño) | Needs Fixing | ||
Daniel van Vugt | Approve | ||
Alan Griffiths | Abstain | ||
Sam Spilsbury | Pending | ||
Review via email: mp+94641@code.launchpad.net |
This proposal supersedes a proposal from 2012-02-22.
This proposal has been superseded by a proposal from 2012-02-28.
Commit message
Description of the change
Adds support for Ubuntu's "locally integrated menu bars" into gtk-window-
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal | # |
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
> 8 +#define GWD_SHOW_LOCAL_MENU (WNCK_WINDOW_
>
> 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_
>
Its C
>
> 296 button_
> 297
> 298 - for (i = 3; i < MAX_BUTTONS_
> 299 + for (i = 4; i < MAX_BUTTONS_
> 300 button_
> 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
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
Please resubmit for target branch lp:compiz-core (0.9.7)
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal | # |
Looks better
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
(More work needed to adopt to trevino;s changes)
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
Fails to build ifndef META_HAS_
[ 0%] Building C object gtk/window-
/home/dan/
/home/dan/
cc1: all warnings being treated as errors
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');
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;
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).
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
Yep, done
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_
[ 5%] Building CXX object gtk/window-
/home/dan/
/home/dan/
/home/dan/
/home/dan/
make[2]: *** [gtk/window-
make[1]: *** [gtk/window-
make: *** [all] Error 2
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
Tests needed to be disabled on META_HAS_
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
Test cases fail (crash). Maybe they need to be disabled if local menus are disabled...
The following tests FAILED:
1 - gtk_window_
2 - gtk_window_
Errors while running CTest
make: *** [test] Error 8
-----
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff709bb70 in ?? () from /usr/lib/
(gdb) bt
#0 0x00007ffff709bb70 in ?? () from /usr/lib/
#1 0x00007ffff709e2f5 in ?? () from /usr/lib/
#2 0x00007ffff6dc29f0 in g_object_unref ()
from /usr/lib/
#3 0x000000000042ef7d in void testing:
#4 0x000000000042751f in testing:
#5 0x000000000042763d in testing:
#6 0x0000000000427787 in testing:
#7 0x0000000000427a17 in testing:
#8 0x000000000042eafd in bool testing:
#9 0x0000000000426c0b in testing:
#10 0x0000000000413145 in main ()
-----
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff709bb70 in ?? () from /usr/lib/
(gdb) bt
#0 0x00007ffff709bb70 in ?? () from /usr/lib/
#1 0x00007ffff709e2f5 in ?? () from /usr/lib/
#2 0x00007ffff6dc29f0 in g_object_unref ()
from /usr/lib/
#3 0x000000000042ef7d in void testing:
#4 0x000000000042751f in testing:
#5 0x000000000042763d in testing:
#6 0x0000000000427787 in testing:
#7 0x0000000000427a17 in testing:
#8 0x000000000042eafd in bool testing:
#9 0x0000000000426c0b in testing:
#10 0x0000000000413145 in main ()
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
Huh, that's weird. I've disabled META_HAS_
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
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
Confirmed all unit tests now pass and no obvious bugs in manual testing.
I still think we need to be tidier with the CMake syntax as I've mentioned before...
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
Yes, one day I'm going to introduce a bunch of functions to the CMake which reduce the verbosity.
Daniel - if you want to test this for realz, you can use the following:
lp:~smspillaz/metacity/metacity.lim
lp:~3v1n0/unity/lim-panel
lp:~indicator-applet-developers/indicator-appmenu/local-menus-single-menu
lp:~smspillaz/light-themes/light-themes.limv4
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal | # |
Looks OK, Builds OK, automated tests run. (With no META_HAS_
Marco Trevisan (Treviño) (3v1n0) wrote : Posted in a previous version of this proposal | # |
I've tested it, to be even better, maybe you could also sync the title geometries once you opened/closed the menu, but that can be optional.
One thing you need to fix is the double-click over the title, that currently doesn't work as expected.
Look at the logic I've used in PanelTitlebarGr
Then I guess we need to define with design better one case: if a window is unfocused, and the user presses over the title / icon, should we just focus it or also open the menu? Currently we do both, but I'm not sure this is the best choice.
Marco Trevisan (Treviño) (3v1n0) wrote : Posted in a previous version of this proposal | # |
Ah, don't care about syncing geometries. You don't need that and could cause problems to the panel... :)
Marco Trevisan (Treviño) (3v1n0) wrote : Posted in a previous version of this proposal | # |
Ah, one more thing. Please check if the window you're decorating has the "_UBUNTU_
Marco Trevisan (Treviño) (3v1n0) wrote : Posted in a previous version of this proposal | # |
Ah, I forgot... The decorator is still missing to react to the com.canonical.
Sam Spilsbury (smspillaz) wrote : Posted in a previous version of this proposal | # |
OK, I'll take care of these two things too. Thanks.
Alan Griffiths (alan-griffiths) wrote : | # |
No obvious errors
Daniel van Vugt (vanvugt) wrote : | # |
Confirmed again all unit tests now pass and no obvious bugs in manual testing.
Though, like Alan, I have not reviewed the theoretical correctness of the code in detail.
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
Mostly it works, well.
By the way, I've tested the support for the EntryActivateRe
This is the stacktrace I have: http://
Actually you should just ignore that signal if no decorated window is in focus.
Sam Spilsbury (smspillaz) wrote : | # |
Ack.
- 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
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-25 05:11: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-25 05:11: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-25 05:11: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,75 @@ |
176 | } |
177 | |
178 | void |
179 | +on_local_menu_hidden (gpointer user_data) |
180 | +{ |
181 | + Window xid = GPOINTER_TO_INT (user_data); |
182 | + WnckWindow *win = wnck_window_get (xid); |
183 | + decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); |
184 | + |
185 | + d->button_states[BUTTON_WINDOW_MENU] &= ~PRESSED_EVENT_WINDOW; |
186 | + |
187 | + queue_decor_draw (d); |
188 | +} |
189 | + |
190 | +void |
191 | +window_menu_button_event (WnckWindow *win, |
192 | + decor_event *gtkwd_event, |
193 | + decor_event_type gtkwd_type) |
194 | +{ |
195 | + decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); |
196 | + guint state = d->button_states[BUTTON_WINDOW_MENU]; |
197 | + |
198 | + common_button_event (win, gtkwd_event, gtkwd_type, |
199 | + BUTTON_WINDOW_MENU, 1, _("Window Menu")); |
200 | + |
201 | + switch (gtkwd_type) { |
202 | + case GButtonPress: |
203 | + if (gtkwd_event->button == 1) |
204 | + { |
205 | + if (d->button_states[BUTTON_WINDOW_MENU] & BUTTON_EVENT_ACTION_STATE) |
206 | + { |
207 | + delayed_move_info *info = g_new0 (delayed_move_info, 1); |
208 | + |
209 | + info->button = gtkwd_event->button; |
210 | + info->time = gtkwd_event->time; |
211 | + info->win = win; |
212 | + info->x_root = gtkwd_event->x_root; |
213 | + info->y_root = gtkwd_event->y_root; |
214 | + |
215 | + gwd_prepare_show_local_menu ((start_move_window_cb) move_resize_window_on_timeout, (gpointer) info); |
216 | + } |
217 | + } |
218 | + break; |
219 | + case GButtonRelease: |
220 | + if (gtkwd_event->button == 1) |
221 | + if (state) |
222 | + { |
223 | + int win_x, win_y; |
224 | + int box_x = d->button_windows[BUTTON_WINDOW_MENU].pos.x1; |
225 | + |
226 | + wnck_window_get_geometry (win, &win_x, &win_y, NULL, NULL); |
227 | + |
228 | + int x = win_x + box_x; |
229 | + int y = win_y + d->context->extents.top; |
230 | + |
231 | + gwd_show_local_menu (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), |
232 | + wnck_window_get_xid (win), |
233 | + x, y, |
234 | + box_x, |
235 | + d->context->extents.top, |
236 | + gtkwd_event->button, |
237 | + gtkwd_event->time, |
238 | + (show_window_menu_hidden_cb) on_local_menu_hidden, |
239 | + GINT_TO_POINTER (wnck_window_get_xid (d->win))); |
240 | + } |
241 | + break; |
242 | + default: |
243 | + break; |
244 | + } |
245 | +} |
246 | + |
247 | +void |
248 | handle_title_button_event (WnckWindow *win, |
249 | int action, |
250 | decor_event *gtkwd_event) |
251 | @@ -485,7 +583,17 @@ |
252 | |
253 | restack_window (win, Above); |
254 | |
255 | - move_resize_window (win, WM_MOVERESIZE_MOVE, gtkwd_event); |
256 | + delayed_move_info *info = g_new0 (delayed_move_info, 1); |
257 | + |
258 | + info->x_root = gtkwd_event->x_root; |
259 | + info->y_root = gtkwd_event->y_root; |
260 | + info->button = gtkwd_event->button; |
261 | + info->time = gtkwd_event->time; |
262 | + info->win = win; |
263 | + |
264 | + move_resize_window_on_timeout ((gpointer) info); |
265 | + |
266 | + g_free (info); |
267 | } |
268 | } |
269 | else if (gtkwd_event->button == 2) |
270 | @@ -1031,6 +1139,10 @@ |
271 | if (get_window_prop (xevent->xproperty.window, select_window_atom, &select)) |
272 | update_switcher_window (xevent->xproperty.window, select); |
273 | } |
274 | + else if (xevent->xproperty.atom == ubuntu_appmenu_unique_name_atom) |
275 | + { |
276 | + local_menu_cache_reload_xwindow (gdk_x11_display_get_xdisplay (gdkdisplay), xevent->xproperty.window); |
277 | + } |
278 | break; |
279 | case DestroyNotify: |
280 | g_hash_table_remove (frame_table, |
281 | |
282 | === modified file 'gtk/window-decorator/gtk-window-decorator.c' |
283 | --- gtk/window-decorator/gtk-window-decorator.c 2011-10-13 12:22:14 +0000 |
284 | +++ gtk/window-decorator/gtk-window-decorator.c 2012-02-25 05:11:17 +0000 |
285 | @@ -24,6 +24,7 @@ |
286 | */ |
287 | |
288 | #include "gtk-window-decorator.h" |
289 | +#include "local-menus.h" |
290 | |
291 | gboolean minimal = FALSE; |
292 | |
293 | @@ -48,6 +49,7 @@ |
294 | Atom toolkit_action_atom; |
295 | Atom toolkit_action_window_menu_atom; |
296 | Atom toolkit_action_force_quit_dialog_atom; |
297 | +Atom ubuntu_appmenu_unique_name_atom; |
298 | |
299 | Atom net_wm_state_atom; |
300 | Atom net_wm_state_modal_atom; |
301 | @@ -128,6 +130,35 @@ |
302 | "normal", "modal_dialog", "dialog", "menu", "utility" |
303 | }; |
304 | |
305 | +Box * |
306 | +get_active_window_local_menu_rectangle (gpointer user_data, int *dx, int *dy, int *top_height, Window *xid) |
307 | +{ |
308 | + WnckScreen *screen = (WnckScreen *) user_data; |
309 | + WnckWindow *window = wnck_screen_get_active_window (screen); |
310 | + int width, height; |
311 | + decor_t *d = g_object_get_data (G_OBJECT (window), "decor"); |
312 | + |
313 | + wnck_window_get_geometry (window, dx, dy, &width, &height); |
314 | + |
315 | + *top_height = d->context->extents.top; |
316 | + |
317 | + *xid = wnck_window_get_xid (window); |
318 | + |
319 | + Box *rect = &d->button_windows[BUTTON_WINDOW_MENU].pos; |
320 | + |
321 | + return rect; |
322 | +} |
323 | + |
324 | +void |
325 | +on_local_menu_window_menu_updated (gpointer user_data) |
326 | +{ |
327 | + Window xid = GPOINTER_TO_INT (user_data); |
328 | + WnckWindow *window = wnck_window_get (xid); |
329 | + decor_t *d = g_object_get_data (G_OBJECT (window), "decor"); |
330 | + |
331 | + queue_decor_draw (d); |
332 | +} |
333 | + |
334 | int |
335 | main (int argc, char *argv[]) |
336 | { |
337 | @@ -304,6 +335,7 @@ |
338 | |
339 | net_wm_state_atom = XInternAtom (xdisplay,"_NET_WM_STATE", 0); |
340 | net_wm_state_modal_atom = XInternAtom (xdisplay, "_NET_WM_STATE_MODAL", 0); |
341 | + ubuntu_appmenu_unique_name_atom = XInternAtom (xdisplay, "_UBUNTU_APPMENU_UNIQUE_NAME", 0); |
342 | |
343 | status = decor_acquire_dm_session (xdisplay, |
344 | gdk_screen_get_number (gdkscreen), |
345 | @@ -448,8 +480,32 @@ |
346 | |
347 | update_default_decorations (gdkscreen); |
348 | |
349 | +#ifdef META_HAS_LOCAL_MENUS |
350 | + GDBusConnection *conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); |
351 | + local_menu_entry_activated_request_funcs funcs = |
352 | + { |
353 | + get_active_window_local_menu_rectangle, |
354 | + on_local_menu_window_menu_updated |
355 | + }; |
356 | + |
357 | + if (conn) |
358 | + { |
359 | + global_lim_listener = g_dbus_proxy_new_sync (conn, 0, NULL, "com.canonical.Unity.Panel.Service", |
360 | + "/com/canonical/Unity/Panel/Service", |
361 | + "com.canonical.Unity.Panel.Service", |
362 | + NULL, NULL); |
363 | + |
364 | + g_signal_connect (G_OBJECT (global_lim_listener), "g-signal", G_CALLBACK (local_menu_entry_activated_request), (gpointer) &funcs); |
365 | + } |
366 | +#endif |
367 | gtk_main (); |
368 | +#ifdef META_HAS_LOCAL_MENUS |
369 | + if (global_lim_listener) |
370 | + g_object_unref (global_lim_listener); |
371 | |
372 | + if (conn) |
373 | + g_object_unref (conn); |
374 | +#endif |
375 | win = windows = wnck_screen_get_windows (screen); |
376 | |
377 | while (win != NULL) |
378 | |
379 | === modified file 'gtk/window-decorator/gtk-window-decorator.h' |
380 | --- gtk/window-decorator/gtk-window-decorator.h 2011-10-13 12:22:14 +0000 |
381 | +++ gtk/window-decorator/gtk-window-decorator.h 2012-02-25 05:11:17 +0000 |
382 | @@ -306,6 +306,7 @@ |
383 | extern Atom toolkit_action_force_quit_dialog_atom; |
384 | extern Atom net_wm_state_atom; |
385 | extern Atom net_wm_state_modal_atom; |
386 | +extern Atom ubuntu_appmenu_unique_name_atom; |
387 | |
388 | extern Time dm_sn_timestamp; |
389 | |
390 | @@ -328,7 +329,8 @@ |
391 | #define BUTTON_UNSHADE 7 |
392 | #define BUTTON_UNABOVE 8 |
393 | #define BUTTON_UNSTICK 9 |
394 | -#define BUTTON_NUM 10 |
395 | +#define BUTTON_WINDOW_MENU 10 |
396 | +#define BUTTON_NUM 11 |
397 | |
398 | struct _pos { |
399 | int x, y, w, h; |
400 | @@ -1013,6 +1015,11 @@ |
401 | decor_event_type gtkwd_type); |
402 | |
403 | void |
404 | +window_menu_button_event (WnckWindow *win, |
405 | + decor_event *gtkwd_event, |
406 | + decor_event_type gtkwd_type); |
407 | + |
408 | +void |
409 | handle_title_button_event (WnckWindow *win, |
410 | int action, |
411 | decor_event *gtkwd_event); |
412 | |
413 | === added directory 'gtk/window-decorator/local-menus' |
414 | === added file 'gtk/window-decorator/local-menus/CMakeLists.txt' |
415 | --- gtk/window-decorator/local-menus/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
416 | +++ gtk/window-decorator/local-menus/CMakeLists.txt 2012-02-25 05:11:17 +0000 |
417 | @@ -0,0 +1,60 @@ |
418 | +pkg_check_modules( |
419 | + LOCAL_MENUS |
420 | + REQUIRED |
421 | + glib-2.0 gio-2.0 libwnck-1.0 gtk+-2.0>=2.18.0 |
422 | +) |
423 | + |
424 | +INCLUDE_DIRECTORIES( |
425 | + ${CMAKE_CURRENT_SOURCE_DIR}/include |
426 | + ${CMAKE_CURRENT_SOURCE_DIR}/src |
427 | + |
428 | + ${compiz_SOURCE_DIR}/gtk/window-decorator |
429 | + |
430 | + ${Boost_INCLUDE_DIRS} |
431 | + |
432 | + ${LOCAL_MENUS_INCLUDE_DIRS} |
433 | + ${METACITY_INCLUDE_DIRS} |
434 | +) |
435 | + |
436 | +LINK_DIRECTORIES (${LOCAL_MENUS_LIBRARY_DIRS}) |
437 | + |
438 | +SET( |
439 | + PUBLIC_HEADERS |
440 | +) |
441 | + |
442 | +SET( |
443 | + PRIVATE_HEADERS |
444 | + ${CMAKE_CURRENT_SOURCE_DIR}/src/local-menus.h |
445 | +) |
446 | + |
447 | +SET( |
448 | + SRCS |
449 | + ${CMAKE_CURRENT_SOURCE_DIR}/src/local-menus.c |
450 | +) |
451 | + |
452 | +ADD_LIBRARY( |
453 | + gtk_window_decorator_local_menus STATIC |
454 | + |
455 | + ${SRCS} |
456 | + |
457 | + ${PUBLIC_HEADERS} |
458 | + ${PRIVATE_HEADERS} |
459 | +) |
460 | + |
461 | +IF (COMPIZ_BUILD_TESTING) |
462 | +ADD_SUBDIRECTORY( ${CMAKE_CURRENT_SOURCE_DIR}/tests ) |
463 | +ENDIF (COMPIZ_BUILD_TESTING) |
464 | + |
465 | +SET_TARGET_PROPERTIES( |
466 | + gtk_window_decorator_local_menus PROPERTIES |
467 | + PUBLIC_HEADER "${PUBLIC_HEADERS}" |
468 | +) |
469 | + |
470 | +install (FILES ${PUBLIC_HEADERS} DESTINATION ${COMPIZ_CORE_INCLUDE_DIR}) |
471 | + |
472 | +TARGET_LINK_LIBRARIES( |
473 | + gtk_window_decorator_local_menus |
474 | + |
475 | + ${LOCAL_MENUS_LIBRARIES} |
476 | +) |
477 | + |
478 | |
479 | === added directory 'gtk/window-decorator/local-menus/include' |
480 | === added directory 'gtk/window-decorator/local-menus/src' |
481 | === added file 'gtk/window-decorator/local-menus/src/local-menus.c' |
482 | --- gtk/window-decorator/local-menus/src/local-menus.c 1970-01-01 00:00:00 +0000 |
483 | +++ gtk/window-decorator/local-menus/src/local-menus.c 2012-02-25 05:11:17 +0000 |
484 | @@ -0,0 +1,423 @@ |
485 | +/* |
486 | + * Copyright © 2006 Novell, Inc. |
487 | + * |
488 | + * This library is free software; you can redistribute it and/or |
489 | + * modify it under the terms of the GNU Lesser General Public |
490 | + * License as published by the Free Software Foundation; either |
491 | + * version 2 of the License, or (at your option) any later version. |
492 | + * |
493 | + * This library is distributed in the hope that it will be useful, |
494 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
495 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
496 | + * Lesser General Public License for more details. |
497 | + * |
498 | + * You should have received a copy of the GNU Lesser General Public |
499 | + * License along with this library; if not, write to the |
500 | + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
501 | + * Boston, MA 02111-1307, USA. |
502 | + * |
503 | + * Author: David Reveman <davidr@novell.com> |
504 | + * |
505 | + * 2D Mode: Copyright © 2010 Sam Spilsbury <smspillaz@gmail.com> |
506 | + * Frames Management: Copright © 2011 Canonical Ltd. |
507 | + * Authored By: Sam Spilsbury <sam.spilsbury@canonical.com> |
508 | + */ |
509 | + |
510 | +#include <string.h> |
511 | +#include "local-menus.h" |
512 | +#include <gdk/gdk.h> |
513 | +#include <gdk/gdkx.h> |
514 | + |
515 | +#define GLOBAL 0 |
516 | +#define LOCAL 1 |
517 | + |
518 | +#define ALLOWED 2 |
519 | +#define NOT_ALLOWED 1 |
520 | + |
521 | +gint menu_mode = GLOBAL; |
522 | + |
523 | +GDBusProxy *global_lim_listener; |
524 | + |
525 | + |
526 | +#ifdef META_HAS_LOCAL_MENUS |
527 | +static void |
528 | +gwd_menu_mode_changed (GSettings *settings, |
529 | + gchar *key, |
530 | + gpointer user_data) |
531 | +{ |
532 | + menu_mode = g_settings_get_enum (settings, "menu-mode"); |
533 | +} |
534 | +#endif |
535 | + |
536 | +active_local_menu *active_menu; |
537 | +pending_local_menu *pending_menu; |
538 | + |
539 | +GHashTable *get_windows_with_menus_table () |
540 | +{ |
541 | + static GHashTable *windows_with_menus = NULL; |
542 | + |
543 | + if (!windows_with_menus) |
544 | + windows_with_menus = g_hash_table_new (NULL, NULL); |
545 | + |
546 | + return windows_with_menus; |
547 | +} |
548 | + |
549 | +static gboolean read_xprop_for_window (Display *dpy, Window xid) |
550 | +{ |
551 | + Atom ubuntu_appmenu_unique_name = XInternAtom (dpy, "_UBUNTU_APPMENU_UNIQUE_NAME", FALSE); |
552 | + Atom utf8_string = XInternAtom (dpy, "UTF8_STRING", FALSE); |
553 | + Atom actual; |
554 | + int fmt; |
555 | + unsigned long nitems, nleft; |
556 | + unsigned char *prop; |
557 | + XGetWindowProperty (dpy, xid, ubuntu_appmenu_unique_name, |
558 | + 0L, 16L, FALSE, utf8_string, &actual, &fmt, &nitems, &nleft, &prop); |
559 | + |
560 | + if (actual == utf8_string && fmt == 8 && nitems > 1) |
561 | + { |
562 | + g_hash_table_replace (get_windows_with_menus_table (), GINT_TO_POINTER (xid), GINT_TO_POINTER (ALLOWED)); |
563 | + return TRUE; |
564 | + } |
565 | + else |
566 | + { |
567 | + g_hash_table_replace (get_windows_with_menus_table (), GINT_TO_POINTER (xid), GINT_TO_POINTER (NOT_ALLOWED)); |
568 | + return FALSE; |
569 | + } |
570 | +} |
571 | + |
572 | +gboolean |
573 | +local_menu_allowed_on_window (Display *dpy, Window xid) |
574 | +{ |
575 | + gpointer local_menu_allowed_found = g_hash_table_lookup (get_windows_with_menus_table (), GINT_TO_POINTER (xid)); |
576 | + |
577 | + if (local_menu_allowed_found) |
578 | + { |
579 | + return GPOINTER_TO_INT (local_menu_allowed_found) == ALLOWED; |
580 | + } |
581 | + else if (dpy && xid) |
582 | + { |
583 | + return read_xprop_for_window (dpy, xid); |
584 | + } |
585 | + |
586 | + return FALSE; |
587 | +} |
588 | + |
589 | +gboolean |
590 | +gwd_window_should_have_local_menu (WnckWindow *win) |
591 | +{ |
592 | +#ifdef META_HAS_LOCAL_MENUS |
593 | + const gchar * const *schemas = g_settings_list_schemas (); |
594 | + static GSettings *lim_settings = NULL; |
595 | + while (*schemas != NULL && !lim_settings) |
596 | + { |
597 | + if (g_str_equal (*schemas, "com.canonical.indicator.appmenu")) |
598 | + { |
599 | + lim_settings = g_settings_new ("com.canonical.indicator.appmenu"); |
600 | + menu_mode = g_settings_get_enum (lim_settings, "menu-mode"); |
601 | + g_signal_connect (lim_settings, "changed::menu-mode", G_CALLBACK (gwd_menu_mode_changed), NULL); |
602 | + break; |
603 | + } |
604 | + ++schemas; |
605 | + } |
606 | + |
607 | + if (lim_settings && win) |
608 | + return menu_mode == LOCAL && local_menu_allowed_on_window (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), wnck_window_get_xid (win)); |
609 | +#endif |
610 | + |
611 | + return FALSE; |
612 | +} |
613 | + |
614 | +gchar * |
615 | +gwd_get_entry_id_from_sync_variant (GVariant *args) |
616 | +{ |
617 | + /* We need to get the indicator data once we've called show */ |
618 | + |
619 | + GVariantIter* iter = NULL; |
620 | + gchar* name_hint = NULL; |
621 | + gchar* indicator_id = NULL; |
622 | + gchar* entry_id = NULL; |
623 | + gchar* label = NULL; |
624 | + gboolean label_sensitive = FALSE; |
625 | + gboolean label_visible = FALSE; |
626 | + guint32 image_type = 0; |
627 | + gchar* image_data = NULL; |
628 | + gboolean image_sensitive = FALSE; |
629 | + gboolean image_visible = FALSE; |
630 | + gint32 priority = -1; |
631 | + |
632 | + g_variant_get (args, "(a(ssssbbusbbi))", &iter); |
633 | + while (g_variant_iter_loop (iter, "(ssssbbusbbi)", |
634 | + &indicator_id, |
635 | + &entry_id, |
636 | + &name_hint, |
637 | + &label, |
638 | + &label_sensitive, |
639 | + &label_visible, |
640 | + &image_type, |
641 | + &image_data, |
642 | + &image_sensitive, |
643 | + &image_visible, |
644 | + &priority)) |
645 | + { |
646 | + g_variant_unref (args); |
647 | + return g_strdup (entry_id); |
648 | + } |
649 | + |
650 | + g_variant_unref (args); |
651 | + g_assert_not_reached (); |
652 | + return NULL; |
653 | +} |
654 | +#ifdef META_HAS_LOCAL_MENUS |
655 | +static void |
656 | +on_local_menu_activated (GDBusProxy *proxy, |
657 | + gchar *sender_name, |
658 | + gchar *signal_name, |
659 | + GVariant *parameters, |
660 | + gpointer user_data) |
661 | +{ |
662 | + |
663 | + if (g_strcmp0 (signal_name, "EntryActivated") == 0) |
664 | + { |
665 | + show_local_menu_data *d = (show_local_menu_data *) user_data; |
666 | + gchar *entry_id = NULL; |
667 | + gint x_out, y_out; |
668 | + guint width, height; |
669 | + |
670 | + g_variant_get (parameters, "(s(iiuu))", &entry_id, &x_out, &y_out, &width, &height, NULL); |
671 | + |
672 | + if (!d->local_menu_entry_id) |
673 | + { |
674 | + GError *error = NULL; |
675 | + GVariant *params = g_variant_new ("(s)", "libappmenu.so", NULL); |
676 | + GVariant *args = g_dbus_proxy_call_sync (proxy, "SyncOne", params, 0, 500, NULL, &error); |
677 | + |
678 | + g_assert_no_error (error); |
679 | + d->local_menu_entry_id = gwd_get_entry_id_from_sync_variant (args); |
680 | + } |
681 | + |
682 | + if (g_strcmp0 (entry_id, d->local_menu_entry_id) == 0) |
683 | + { |
684 | + d->rect->x = x_out - d->dx; |
685 | + d->rect->y = y_out - d->dy; |
686 | + d->rect->width = width; |
687 | + d->rect->height = height; |
688 | + (*d->cb) (d->user_data); |
689 | + } |
690 | + else if (g_strcmp0 (entry_id, "") == 0) |
691 | + { |
692 | + memset (d->rect, 0, sizeof (GdkRectangle)); |
693 | + (*d->cb) (d->user_data); |
694 | + |
695 | + g_signal_handlers_disconnect_by_func (proxy, on_local_menu_activated, d); |
696 | + |
697 | + if (active_menu) |
698 | + { |
699 | + g_free (active_menu); |
700 | + active_menu = NULL; |
701 | + } |
702 | + |
703 | + g_free (d->local_menu_entry_id); |
704 | + g_free (d); |
705 | + } |
706 | + } |
707 | + |
708 | +} |
709 | +#endif |
710 | +gboolean |
711 | +gwd_move_window_instead (gpointer user_data) |
712 | +{ |
713 | + (*pending_menu->cb) (pending_menu->user_data); |
714 | + g_free (pending_menu->user_data); |
715 | + g_free (pending_menu); |
716 | + pending_menu = NULL; |
717 | + return FALSE; |
718 | +} |
719 | + |
720 | +void |
721 | +gwd_prepare_show_local_menu (start_move_window_cb start_move_window, |
722 | + gpointer user_data_start_move_window) |
723 | +{ |
724 | + if (pending_menu) |
725 | + { |
726 | + g_source_remove (pending_menu->move_timeout_id); |
727 | + g_free (pending_menu->user_data); |
728 | + g_free (pending_menu); |
729 | + pending_menu = NULL; |
730 | + } |
731 | + |
732 | + pending_menu = g_new0 (pending_local_menu, 1); |
733 | + pending_menu->cb = start_move_window; |
734 | + pending_menu->user_data = user_data_start_move_window; |
735 | + pending_menu->move_timeout_id = g_timeout_add (120, gwd_move_window_instead, pending_menu); |
736 | +} |
737 | + |
738 | +#ifdef META_HAS_LOCAL_MENUS |
739 | +void |
740 | +local_menu_entry_activated_request (GDBusProxy *proxy, |
741 | + gchar *sender_name, |
742 | + gchar *signal_name, |
743 | + GVariant *parameters, |
744 | + gpointer user_data) |
745 | +{ |
746 | + if (g_strcmp0 (signal_name, "EntryActivateRequest") == 0) |
747 | + { |
748 | + gchar *activated_entry_id; |
749 | + gchar *local_menu_entry_id; |
750 | + local_menu_entry_activated_request_funcs *funcs = (local_menu_entry_activated_request_funcs *) user_data; |
751 | + |
752 | + g_variant_get (parameters, "(s)", &activated_entry_id, NULL); |
753 | + |
754 | + GError *error = NULL; |
755 | + GVariant *params = g_variant_new ("(s)", "libappmenu.so", NULL); |
756 | + GVariant *args = g_dbus_proxy_call_sync (proxy, "SyncOne", params, 0, 500, NULL, &error); |
757 | + |
758 | + g_assert_no_error (error); |
759 | + local_menu_entry_id = gwd_get_entry_id_from_sync_variant (args); |
760 | + |
761 | + if (g_strcmp0 (activated_entry_id, local_menu_entry_id) == 0) |
762 | + { |
763 | + WnckScreen *screen = wnck_screen_get_for_root (gdk_x11_get_default_root_xwindow ()); |
764 | + int dx, dy, top_height; |
765 | + Window xid; |
766 | + |
767 | + if (screen) |
768 | + { |
769 | + Box *rect = (*funcs->active_window_local_menu_rect_callback) ((gpointer) screen, &dx, &dy, &top_height, &xid); |
770 | + |
771 | + if (rect) |
772 | + { |
773 | + int x = rect->x1; |
774 | + int y = top_height; |
775 | + |
776 | + gwd_show_local_menu (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), |
777 | + xid, x + dx, y + dy, x, y, 0, 0, |
778 | + funcs->show_window_menu_hidden_callback, GINT_TO_POINTER (xid)); |
779 | + } |
780 | + } |
781 | + } |
782 | + } |
783 | +} |
784 | +#endif |
785 | + |
786 | +gboolean |
787 | +gwd_show_local_menu (Display *xdisplay, |
788 | + Window frame_xwindow, |
789 | + int x, |
790 | + int y, |
791 | + int x_win, |
792 | + int y_win, |
793 | + int button, |
794 | + guint32 timestamp, |
795 | + show_window_menu_hidden_cb cb, |
796 | + gpointer user_data_show_window_menu) |
797 | +{ |
798 | + if (pending_menu) |
799 | + { |
800 | + g_source_remove (pending_menu->move_timeout_id); |
801 | + g_free (pending_menu->user_data); |
802 | + g_free (pending_menu); |
803 | + pending_menu = NULL; |
804 | + } |
805 | + |
806 | +#ifdef META_HAS_LOCAL_MENUS |
807 | + |
808 | + |
809 | + XUngrabPointer (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), CurrentTime); |
810 | + XUngrabKeyboard (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), CurrentTime); |
811 | + XSync (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), FALSE); |
812 | + |
813 | + GDBusProxy *proxy = global_lim_listener; |
814 | + |
815 | + if (proxy) |
816 | + { |
817 | + GVariant *message = g_variant_new ("(uiiu)", frame_xwindow, x, y, time); |
818 | + GError *error = NULL; |
819 | + g_dbus_proxy_call_sync (proxy, "ShowAppMenu", message, 0, 500, NULL, &error); |
820 | + if (error) |
821 | + { |
822 | + g_print ("error calling ShowAppMenu: %s\n", error->message); |
823 | + return FALSE; |
824 | + } |
825 | + |
826 | + show_local_menu_data *data = g_new0 (show_local_menu_data, 1); |
827 | + |
828 | + if (active_menu) |
829 | + g_free (active_menu); |
830 | + |
831 | + active_menu = g_new0 (active_local_menu, 1); |
832 | + |
833 | + data->cb = cb; |
834 | + data->user_data = user_data_show_window_menu; |
835 | + data->rect = &active_menu->rect; |
836 | + data->dx = x - x_win; |
837 | + data->dy = y - y_win; |
838 | + data->local_menu_entry_id = NULL; |
839 | + |
840 | + g_signal_connect (proxy, "g-signal", G_CALLBACK (on_local_menu_activated), data); |
841 | + |
842 | + return TRUE; |
843 | + } |
844 | +#endif |
845 | + return FALSE; |
846 | +} |
847 | + |
848 | +void |
849 | +force_local_menus_on (WnckWindow *win, |
850 | + MetaButtonLayout *button_layout) |
851 | +{ |
852 | +#ifdef META_HAS_LOCAL_MENUS |
853 | + if (gwd_window_should_have_local_menu (win)) |
854 | + { |
855 | + if (button_layout->left_buttons[0] != META_BUTTON_FUNCTION_LAST) |
856 | + { |
857 | + unsigned int i = 0; |
858 | + for (; i < MAX_BUTTONS_PER_CORNER; i++) |
859 | + { |
860 | + if (button_layout->left_buttons[i] == META_BUTTON_FUNCTION_WINDOW_MENU) |
861 | + break; |
862 | + else if (button_layout->left_buttons[i] == META_BUTTON_FUNCTION_LAST) |
863 | + { |
864 | + if ((i + 1) < MAX_BUTTONS_PER_CORNER) |
865 | + { |
866 | + button_layout->left_buttons[i + 1] = META_BUTTON_FUNCTION_LAST; |
867 | + button_layout->left_buttons[i] = META_BUTTON_FUNCTION_WINDOW_MENU; |
868 | + break; |
869 | + } |
870 | + } |
871 | + } |
872 | + } |
873 | + if (button_layout->right_buttons[0] != META_BUTTON_FUNCTION_LAST) |
874 | + { |
875 | + unsigned int i = 0; |
876 | + for (; i < MAX_BUTTONS_PER_CORNER; i++) |
877 | + { |
878 | + if (button_layout->right_buttons[i] == META_BUTTON_FUNCTION_WINDOW_MENU) |
879 | + break; |
880 | + else if (button_layout->right_buttons[i] == META_BUTTON_FUNCTION_LAST) |
881 | + { |
882 | + if ((i + 1) < MAX_BUTTONS_PER_CORNER) |
883 | + { |
884 | + button_layout->right_buttons[i + 1] = META_BUTTON_FUNCTION_LAST; |
885 | + button_layout->right_buttons[i] = META_BUTTON_FUNCTION_WINDOW_MENU; |
886 | + break; |
887 | + } |
888 | + } |
889 | + } |
890 | + } |
891 | + } |
892 | +#endif |
893 | +} |
894 | + |
895 | +void |
896 | +local_menu_cache_notify_window_destroyed (Window xid) |
897 | +{ |
898 | + g_hash_table_remove (get_windows_with_menus_table (), GINT_TO_POINTER (xid)); |
899 | +} |
900 | + |
901 | +void |
902 | +local_menu_cache_reload_xwindow (Display *dpy, Window xid) |
903 | +{ |
904 | + read_xprop_for_window (dpy, xid); |
905 | +} |
906 | + |
907 | + |
908 | |
909 | === added file 'gtk/window-decorator/local-menus/src/local-menus.h' |
910 | --- gtk/window-decorator/local-menus/src/local-menus.h 1970-01-01 00:00:00 +0000 |
911 | +++ gtk/window-decorator/local-menus/src/local-menus.h 2012-02-25 05:11:17 +0000 |
912 | @@ -0,0 +1,120 @@ |
913 | +/* |
914 | + * Copyright © 2006 Novell, Inc. |
915 | + * |
916 | + * This library is free software; you can redistribute it and/or |
917 | + * modify it under the terms of the GNU Lesser General Public |
918 | + * License as published by the Free Software Foundation; either |
919 | + * version 2 of the License, or (at your option) any later version. |
920 | + * |
921 | + * This library is distributed in the hope that it will be useful, |
922 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
923 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
924 | + * Lesser General Public License for more details. |
925 | + * |
926 | + * You should have received a copy of the GNU Lesser General Public |
927 | + * License along with this library; if not, write to the |
928 | + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
929 | + * Boston, MA 02111-1307, USA. |
930 | + * |
931 | + * Author: David Reveman <davidr@novell.com> |
932 | + * |
933 | + * 2D Mode: Copyright © 2010 Sam Spilsbury <smspillaz@gmail.com> |
934 | + * Frames Management: Copright © 2011 Canonical Ltd. |
935 | + * Authored By: Sam Spilsbury <sam.spilsbury@canonical.com> |
936 | + */ |
937 | + |
938 | +#ifdef __cplusplus |
939 | +extern "C" |
940 | +{ |
941 | +#endif |
942 | + |
943 | +#include <glib.h> |
944 | +#include <gio/gio.h> |
945 | +#ifndef WNCK_I_KNOW_THIS_IS_UNSTABLE |
946 | +#define WNCK_I_KNOW_THIS_IS_UNSTABLE |
947 | +#endif |
948 | +#include <libwnck/libwnck.h> |
949 | +#include <libwnck/window-action-menu.h> |
950 | +#include <metacity-private/theme.h> |
951 | +#include <X11/Xregion.h> |
952 | + |
953 | + |
954 | +typedef void (*show_window_menu_hidden_cb) (gpointer); |
955 | +typedef void (*start_move_window_cb) (gpointer); |
956 | +typedef Box * (*get_active_window_local_menu_rect_cb) (gpointer, int *, int *, int *, Window *); |
957 | + |
958 | +typedef struct _pending_local_menu |
959 | +{ |
960 | + gint move_timeout_id; |
961 | + gpointer user_data; |
962 | + start_move_window_cb cb; |
963 | +} pending_local_menu; |
964 | + |
965 | +typedef struct _active_local_menu |
966 | +{ |
967 | + GdkRectangle rect; |
968 | +} active_local_menu; |
969 | + |
970 | +extern active_local_menu *active_menu; |
971 | +extern GDBusProxy *global_lim_listener; |
972 | + |
973 | +typedef struct _show_local_menu_data |
974 | +{ |
975 | + show_window_menu_hidden_cb cb; |
976 | + gpointer user_data; |
977 | + GdkRectangle *rect; |
978 | + gint dx; |
979 | + gint dy; |
980 | + gchar *local_menu_entry_id; |
981 | +} show_local_menu_data; |
982 | + |
983 | +typedef struct _local_menu_entry_activated_request_funcs |
984 | +{ |
985 | + get_active_window_local_menu_rect_cb active_window_local_menu_rect_callback; |
986 | + show_window_menu_hidden_cb show_window_menu_hidden_callback; |
987 | +} local_menu_entry_activated_request_funcs; |
988 | + |
989 | +gboolean |
990 | +gwd_window_should_have_local_menu (WnckWindow *win); |
991 | + |
992 | +void |
993 | +force_local_menus_on (WnckWindow *win, |
994 | + MetaButtonLayout *layout); |
995 | + |
996 | +/* Button Down */ |
997 | +void |
998 | +gwd_prepare_show_local_menu (start_move_window_cb start_move_window, |
999 | + gpointer user_data_start_move_window); |
1000 | + |
1001 | +/* Button Up */ |
1002 | +gboolean |
1003 | +gwd_show_local_menu (Display *xdisplay, |
1004 | + Window frame_xwindow, |
1005 | + int x, |
1006 | + int y, |
1007 | + int x_win, |
1008 | + int y_win, |
1009 | + int button, |
1010 | + guint32 timestamp, |
1011 | + show_window_menu_hidden_cb cb, |
1012 | + gpointer user_data_show_window_menu); |
1013 | + |
1014 | +void |
1015 | +local_menu_cache_notify_window_destroyed (Window xid); |
1016 | + |
1017 | +void |
1018 | +local_menu_cache_reload_xwindow (Display *xdisplay, Window xid); |
1019 | + |
1020 | +gboolean |
1021 | +local_menu_allowed_on_window (Display *dpy, Window xid); |
1022 | + |
1023 | +void |
1024 | +local_menu_entry_activated_request (GDBusProxy *proxy, |
1025 | + gchar *sender_name, |
1026 | + gchar *signal_name, |
1027 | + GVariant *parameters, |
1028 | + gpointer user_data); |
1029 | + |
1030 | +#ifdef __cplusplus |
1031 | +} |
1032 | +#endif |
1033 | |
1034 | === added directory 'gtk/window-decorator/local-menus/tests' |
1035 | === added file 'gtk/window-decorator/local-menus/tests/CMakeLists.txt' |
1036 | --- gtk/window-decorator/local-menus/tests/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
1037 | +++ gtk/window-decorator/local-menus/tests/CMakeLists.txt 2012-02-25 05:11:17 +0000 |
1038 | @@ -0,0 +1,3 @@ |
1039 | +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) |
1040 | +add_subdirectory (check_local_menu_on_off) |
1041 | +add_subdirectory (force_local_menu_on) |
1042 | |
1043 | === added directory 'gtk/window-decorator/local-menus/tests/check_local_menu_on_off' |
1044 | === added file 'gtk/window-decorator/local-menus/tests/check_local_menu_on_off/CMakeLists.txt' |
1045 | --- gtk/window-decorator/local-menus/tests/check_local_menu_on_off/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
1046 | +++ gtk/window-decorator/local-menus/tests/check_local_menu_on_off/CMakeLists.txt 2012-02-25 05:11:17 +0000 |
1047 | @@ -0,0 +1,21 @@ |
1048 | +include_directories (${CMAKE_CURRENT_SOURCE_DIR} |
1049 | + ${compiz_SOURCE_DIR}/gtk/window-decorator/local-menus/tests |
1050 | + ${compiz_SOURCE_DIR}/gtk/window-decorator |
1051 | + ${compiz_SOURCE_DIR}/gtk/window-decorator/local-menus/src) |
1052 | + |
1053 | +add_executable( |
1054 | + gtk_window_decorator_check_local_menu_on_off_test |
1055 | + |
1056 | + ${CMAKE_CURRENT_SOURCE_DIR}/test-local-menu-on-off.cpp |
1057 | +) |
1058 | + |
1059 | +target_link_libraries( |
1060 | + gtk_window_decorator_check_local_menu_on_off_test |
1061 | + |
1062 | + gtk_window_decorator_local_menus |
1063 | + |
1064 | + ${GTEST_BOTH_LIBRARIES} |
1065 | + ${CMAKE_THREAD_LIBS_INIT} # Link in pthread. |
1066 | +) |
1067 | + |
1068 | +add_test (gtk_window_decorator_local_menus_on_off gtk_window_decorator_check_local_menu_on_off_test) |
1069 | |
1070 | === added directory 'gtk/window-decorator/local-menus/tests/check_local_menu_on_off/check_local_menu_on_off' |
1071 | === added directory 'gtk/window-decorator/local-menus/tests/check_local_menu_on_off/check_local_menu_on_off/CMakeFiles' |
1072 | === added file 'gtk/window-decorator/local-menus/tests/check_local_menu_on_off/test-local-menu-on-off.cpp' |
1073 | --- gtk/window-decorator/local-menus/tests/check_local_menu_on_off/test-local-menu-on-off.cpp 1970-01-01 00:00:00 +0000 |
1074 | +++ gtk/window-decorator/local-menus/tests/check_local_menu_on_off/test-local-menu-on-off.cpp 2012-02-25 05:11:17 +0000 |
1075 | @@ -0,0 +1,27 @@ |
1076 | +#include "test-local-menu.h" |
1077 | + |
1078 | +#define GLOBAL 0 |
1079 | +#define LOCAL 1 |
1080 | +#ifdef META_HAS_LOCAL_MENUS |
1081 | + |
1082 | +TEST_F (GtkWindowDecoratorTestLocalMenu, TestOn) |
1083 | +{ |
1084 | + g_settings_set_enum (getSettings (), "menu-mode", LOCAL); |
1085 | + gboolean result = gwd_window_should_have_local_menu (getWindow ()); |
1086 | + |
1087 | + EXPECT_TRUE (result); |
1088 | +} |
1089 | + |
1090 | +TEST_F (GtkWindowDecoratorTestLocalMenu, TestOff) |
1091 | +{ |
1092 | + g_settings_set_enum (getSettings (), "menu-mode", GLOBAL); |
1093 | + gboolean result = gwd_window_should_have_local_menu (getWindow ()); |
1094 | + |
1095 | + EXPECT_FALSE (result); |
1096 | +} |
1097 | +#else |
1098 | +TEST_F (GtkWindowDecoratorTestLocalMenu, NoMenus) |
1099 | +{ |
1100 | + ASSERT_TRUE (true) << "Local menus tests not enabled because META_HAS_LOCAL_MENUS is off"; |
1101 | +} |
1102 | +#endif |
1103 | |
1104 | === added directory 'gtk/window-decorator/local-menus/tests/force_local_menu_on' |
1105 | === added file 'gtk/window-decorator/local-menus/tests/force_local_menu_on/CMakeLists.txt' |
1106 | --- gtk/window-decorator/local-menus/tests/force_local_menu_on/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
1107 | +++ gtk/window-decorator/local-menus/tests/force_local_menu_on/CMakeLists.txt 2012-02-25 05:11:17 +0000 |
1108 | @@ -0,0 +1,21 @@ |
1109 | +include_directories (${CMAKE_CURRENT_SOURCE_DIR} |
1110 | + ${compiz_SOURCE_DIR}/gtk/window-decorator/local-menus/tests |
1111 | + ${compiz_SOURCE_DIR}/gtk/window-decorator |
1112 | + ${compiz_SOURCE_DIR}/gtk/window-decorator/local-menus/src) |
1113 | + |
1114 | +add_executable( |
1115 | + gtk_window_decorator_force_local_menu_on_test |
1116 | + |
1117 | + ${CMAKE_CURRENT_SOURCE_DIR}/test-force-local-menu-on.cpp |
1118 | +) |
1119 | + |
1120 | +target_link_libraries( |
1121 | + gtk_window_decorator_force_local_menu_on_test |
1122 | + |
1123 | + gtk_window_decorator_local_menus |
1124 | + |
1125 | + ${GTEST_BOTH_LIBRARIES} |
1126 | + ${CMAKE_THREAD_LIBS_INIT} # Link in pthread. |
1127 | +) |
1128 | + |
1129 | +add_test (gtk_window_decorator_force_local_menu_on gtk_window_decorator_force_local_menu_on_test) |
1130 | |
1131 | === added file 'gtk/window-decorator/local-menus/tests/force_local_menu_on/test-force-local-menu-on.cpp' |
1132 | --- gtk/window-decorator/local-menus/tests/force_local_menu_on/test-force-local-menu-on.cpp 1970-01-01 00:00:00 +0000 |
1133 | +++ gtk/window-decorator/local-menus/tests/force_local_menu_on/test-force-local-menu-on.cpp 2012-02-25 05:11:17 +0000 |
1134 | @@ -0,0 +1,77 @@ |
1135 | +#include "test-local-menu.h" |
1136 | +#include <cstring> |
1137 | + |
1138 | +#define GLOBAL 0 |
1139 | +#define LOCAL 1 |
1140 | +#ifdef META_HAS_LOCAL_MENUS |
1141 | + |
1142 | +namespace |
1143 | +{ |
1144 | + void initializeMetaButtonLayout (MetaButtonLayout *layout) |
1145 | + { |
1146 | + memset (layout, 0, sizeof (MetaButtonLayout)); |
1147 | + |
1148 | + unsigned int i; |
1149 | + |
1150 | + for (i = 0; i < MAX_BUTTONS_PER_CORNER; i++) |
1151 | + { |
1152 | + layout->right_buttons[i] = META_BUTTON_FUNCTION_LAST; |
1153 | + layout->left_buttons[i] = META_BUTTON_FUNCTION_LAST; |
1154 | + } |
1155 | + } |
1156 | +} |
1157 | + |
1158 | +class GtkWindowDecoratorTestLocalMenuLayout : |
1159 | + public GtkWindowDecoratorTestLocalMenu |
1160 | +{ |
1161 | + public: |
1162 | + |
1163 | + MetaButtonLayout * getLayout () { return &mLayout; } |
1164 | + |
1165 | + virtual void SetUp () |
1166 | + { |
1167 | + GtkWindowDecoratorTestLocalMenu::SetUp (); |
1168 | + ::initializeMetaButtonLayout (&mLayout); |
1169 | + g_settings_set_enum (getSettings (), "menu-mode", LOCAL); |
1170 | + } |
1171 | + |
1172 | + private: |
1173 | + |
1174 | + MetaButtonLayout mLayout; |
1175 | +}; |
1176 | + |
1177 | +TEST_F (GtkWindowDecoratorTestLocalMenuLayout, TestForceNoButtonsSet) |
1178 | +{ |
1179 | + force_local_menus_on (getWindow (), getLayout ()); |
1180 | + |
1181 | + EXPECT_EQ (getLayout ()->right_buttons[0], META_BUTTON_FUNCTION_LAST); |
1182 | + EXPECT_EQ (getLayout ()->left_buttons[0], META_BUTTON_FUNCTION_LAST); |
1183 | +} |
1184 | + |
1185 | +TEST_F (GtkWindowDecoratorTestLocalMenuLayout, TestForceNoCloseButtonSet) |
1186 | +{ |
1187 | + getLayout ()->right_buttons[0] = META_BUTTON_FUNCTION_CLOSE; |
1188 | + |
1189 | + force_local_menus_on (getWindow (), getLayout ()); |
1190 | + |
1191 | + EXPECT_EQ (getLayout ()->right_buttons[1], META_BUTTON_FUNCTION_WINDOW_MENU); |
1192 | + EXPECT_EQ (getLayout ()->left_buttons[0], META_BUTTON_FUNCTION_LAST); |
1193 | +} |
1194 | + |
1195 | +TEST_F (GtkWindowDecoratorTestLocalMenuLayout, TestForceNoCloseMinimizeMaximizeButtonSet) |
1196 | +{ |
1197 | + getLayout ()->left_buttons[0] = META_BUTTON_FUNCTION_CLOSE; |
1198 | + getLayout ()->left_buttons[1] = META_BUTTON_FUNCTION_CLOSE; |
1199 | + getLayout ()->left_buttons[2] = META_BUTTON_FUNCTION_CLOSE; |
1200 | + |
1201 | + force_local_menus_on (getWindow (), getLayout ()); |
1202 | + |
1203 | + EXPECT_EQ (getLayout ()->right_buttons[0], META_BUTTON_FUNCTION_LAST); |
1204 | + EXPECT_EQ (getLayout ()->left_buttons[3], META_BUTTON_FUNCTION_WINDOW_MENU); |
1205 | +} |
1206 | +#else |
1207 | +TEST_F (GtkWindowDecoratorTestLocalMenu, NoMenus) |
1208 | +{ |
1209 | + ASSERT_TRUE (true) << "Local menus tests not enabled because META_HAS_LOCAL_MENUS is off"; |
1210 | +} |
1211 | +#endif |
1212 | |
1213 | === added directory 'gtk/window-decorator/local-menus/tests/show_hide_menu' |
1214 | === added file 'gtk/window-decorator/local-menus/tests/test-local-menu.h' |
1215 | --- gtk/window-decorator/local-menus/tests/test-local-menu.h 1970-01-01 00:00:00 +0000 |
1216 | +++ gtk/window-decorator/local-menus/tests/test-local-menu.h 2012-02-25 05:11:17 +0000 |
1217 | @@ -0,0 +1,49 @@ |
1218 | +#include <gtest/gtest.h> |
1219 | +#include <gmock/gmock.h> |
1220 | +#include "local-menus.h" |
1221 | +#include <X11/Xlib.h> |
1222 | +#include <gio/gio.h> |
1223 | + |
1224 | +class GtkWindowDecoratorTestLocalMenu : |
1225 | + public ::testing::Test |
1226 | +{ |
1227 | + public: |
1228 | + |
1229 | +#ifdef META_HAS_LOCAL_MENUS |
1230 | + WnckWindow * getWindow () { return mWindow; } |
1231 | + GSettings * getSettings () { return mSettings; } |
1232 | + virtual void SetUp () |
1233 | + { |
1234 | + gtk_init (NULL, NULL); |
1235 | + |
1236 | + mXDisplay = XOpenDisplay (NULL); |
1237 | + mXWindow = XCreateSimpleWindow (mXDisplay, DefaultRootWindow (mXDisplay), 0, 0, 100, 100, 0, 0, 0); |
1238 | + |
1239 | + XMapRaised (mXDisplay, mXWindow); |
1240 | + |
1241 | + XFlush (mXDisplay); |
1242 | + |
1243 | + while (g_main_context_iteration (g_main_context_default (), FALSE)); |
1244 | + |
1245 | + mWindow = wnck_window_get (mXWindow); |
1246 | + |
1247 | + g_setenv("GSETTINGS_BACKEND", "memory", true); |
1248 | + mSettings = g_settings_new ("com.canonical.indicator.appmenu"); |
1249 | + } |
1250 | + |
1251 | + virtual void TearDown () |
1252 | + { |
1253 | + XDestroyWindow (mXDisplay, mXWindow); |
1254 | + XCloseDisplay (mXDisplay); |
1255 | + |
1256 | + g_object_unref (mSettings); |
1257 | + } |
1258 | +#endif |
1259 | + |
1260 | + private: |
1261 | + |
1262 | + WnckWindow *mWindow; |
1263 | + Window mXWindow; |
1264 | + Display *mXDisplay; |
1265 | + GSettings *mSettings; |
1266 | +}; |
1267 | |
1268 | === modified file 'gtk/window-decorator/metacity.c' |
1269 | --- gtk/window-decorator/metacity.c 2012-02-16 06:51:37 +0000 |
1270 | +++ gtk/window-decorator/metacity.c 2012-02-25 05:11:17 +0000 |
1271 | @@ -24,6 +24,7 @@ |
1272 | */ |
1273 | |
1274 | #include "gtk-window-decorator.h" |
1275 | +#include "local-menus.h" |
1276 | |
1277 | #ifdef USE_METACITY |
1278 | |
1279 | @@ -488,6 +489,8 @@ |
1280 | button_layout->right_buttons[i] = META_BUTTON_FUNCTION_LAST; |
1281 | } |
1282 | |
1283 | + force_local_menus_on (d->win, button_layout); |
1284 | + |
1285 | *flags = 0; |
1286 | |
1287 | if (d->actions & WNCK_WINDOW_ACTION_CLOSE) |
1288 | @@ -538,6 +541,12 @@ |
1289 | *flags |= (MetaFrameFlags ) META_FRAME_ABOVE; |
1290 | #endif |
1291 | |
1292 | +#ifdef META_HAS_LOCAL_MENUS |
1293 | + if (d->win && |
1294 | + local_menu_allowed_on_window (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), wnck_window_get_xid (d->win))) |
1295 | + *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_WINDOW_MENU; |
1296 | +#endif |
1297 | + |
1298 | meta_theme_get_frame_borders (theme, |
1299 | frame_type, |
1300 | d->frame->text_height, |
1301 | @@ -558,6 +567,15 @@ |
1302 | else |
1303 | clip->height = d->border_layout.left.y2 - d->border_layout.left.y1; |
1304 | |
1305 | + memset (fgeom, 0, sizeof (MetaFrameGeometry)); |
1306 | + |
1307 | +#ifdef META_HAS_LOCAL_MENUS |
1308 | + |
1309 | + if (d->layout) |
1310 | + fgeom->text_layout = g_object_ref (d->layout); |
1311 | + |
1312 | +#endif |
1313 | + |
1314 | meta_theme_calc_geometry (theme, |
1315 | frame_type, |
1316 | d->frame->text_height, |
1317 | @@ -567,6 +585,15 @@ |
1318 | button_layout, |
1319 | fgeom); |
1320 | |
1321 | +#ifdef META_HAS_LOCAL_MENUS |
1322 | + |
1323 | + if (d->layout) |
1324 | + g_object_unref (fgeom->text_layout); |
1325 | + |
1326 | + fgeom->text_layout = NULL; |
1327 | + |
1328 | +#endif |
1329 | + |
1330 | clip->width += left_width + right_width; |
1331 | clip->height += top_height + bottom_height; |
1332 | } |
1333 | @@ -601,6 +628,11 @@ |
1334 | GdkColor bg_color; |
1335 | double bg_alpha; |
1336 | |
1337 | + memset (&button_layout, 0, sizeof (MetaButtonLayout)); |
1338 | + |
1339 | + for (i = 0; i < MAX_BUTTONS_PER_CORNER; i++) |
1340 | + button_layout.left_buttons[i] = button_layout.right_buttons[i] = META_BUTTON_FUNCTION_LAST; |
1341 | + |
1342 | if (!d->pixmap || !d->picture) |
1343 | return; |
1344 | |
1345 | @@ -675,6 +707,9 @@ |
1346 | |
1347 | size = MAX (fgeom.top_height, fgeom.bottom_height); |
1348 | |
1349 | + if (active_menu) |
1350 | + g_object_set_data (G_OBJECT (style_window), "local_menu_rect", &active_menu->rect); |
1351 | + |
1352 | if (rect.width && size) |
1353 | { |
1354 | XRenderPictFormat *format; |
1355 | @@ -899,6 +934,9 @@ |
1356 | XRenderFreePicture (xdisplay, src); |
1357 | } |
1358 | |
1359 | + if (active_menu) |
1360 | + g_object_set_data (G_OBJECT (style_window), "local_menu_rect", NULL); |
1361 | + |
1362 | copy_to_front_buffer (d); |
1363 | |
1364 | if (d->frame_window) |
1365 | @@ -1078,6 +1116,15 @@ |
1366 | break; |
1367 | #endif |
1368 | |
1369 | +#ifdef META_HAS_LOCAL_MENUS |
1370 | + case BUTTON_WINDOW_MENU: |
1371 | + if (!meta_button_present (&button_layout, META_BUTTON_FUNCTION_WINDOW_MENU)) |
1372 | + return FALSE; |
1373 | + |
1374 | + space = &fgeom.window_menu_rect; |
1375 | + break; |
1376 | +#endif |
1377 | + |
1378 | default: |
1379 | return FALSE; |
1380 | } |
1381 | @@ -1266,6 +1313,8 @@ |
1382 | MetaTheme *theme; |
1383 | GdkRectangle clip; |
1384 | |
1385 | + memset (&fgeom, 0, sizeof (MetaFrameGeometry)); |
1386 | + |
1387 | theme = meta_theme_get_current (); |
1388 | |
1389 | meta_get_decoration_geometry (d, theme, &flags, &fgeom, &button_layout, |
1390 | @@ -1490,6 +1539,11 @@ |
1391 | return META_BUTTON_FUNCTION_UNSTICK; |
1392 | #endif |
1393 | |
1394 | +#ifdef META_HAS_LOCAL_MENUS |
1395 | + else if (strcmp (str, "window_menu") == 0) |
1396 | + return META_BUTTON_FUNCTION_WINDOW_MENU; |
1397 | +#endif |
1398 | + |
1399 | else |
1400 | return META_BUTTON_FUNCTION_LAST; |
1401 | } |
1402 | |
1403 | === modified file 'gtk/window-decorator/wnck.c' |
1404 | --- gtk/window-decorator/wnck.c 2012-02-10 10:23:27 +0000 |
1405 | +++ gtk/window-decorator/wnck.c 2012-02-25 05:11:17 +0000 |
1406 | @@ -24,6 +24,7 @@ |
1407 | */ |
1408 | |
1409 | #include "gtk-window-decorator.h" |
1410 | +#include "local-menus.h" |
1411 | |
1412 | const gchar * |
1413 | get_frame_type (WnckWindow *win) |
1414 | @@ -738,7 +739,8 @@ |
1415 | stick_button_event, |
1416 | unshade_button_event, |
1417 | unabove_button_event, |
1418 | - unstick_button_event |
1419 | + unstick_button_event, |
1420 | + window_menu_button_event |
1421 | }; |
1422 | |
1423 | d = calloc (1, sizeof (decor_t)); |
1424 | @@ -784,6 +786,8 @@ |
1425 | window_closed (WnckScreen *screen, |
1426 | WnckWindow *win) |
1427 | { |
1428 | + local_menu_cache_notify_window_destroyed (wnck_window_get_xid (win)); |
1429 | + |
1430 | decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); |
1431 | |
1432 | if (d) |
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; PER_CORNER; i++) PER_CORNER; i++) layout- >right_ buttons[ i] = META_BUTTON_ FUNCTION_ LAST;
297
298 - for (i = 3; i < MAX_BUTTONS_
299 + for (i = 4; i < MAX_BUTTONS_
300 button_
301 }
I'm not sure what the magic number "3"->"4" is. But we now seem to miss 3 entirely. Is that correct?