Merge lp:~smspillaz/compiz-core/compiz-core.lim into lp:compiz-core
- compiz-core.lim
- Merge into 0.9.7
Status: | Merged |
---|---|
Merged at revision: | 3036 |
Proposed branch: | lp:~smspillaz/compiz-core/compiz-core.lim |
Merge into: | lp:compiz-core |
Diff against target: |
1601 lines (+1218/-11) 16 files modified
gtk/window-decorator/CMakeLists.txt (+6/-0) gtk/window-decorator/decorator.c (+32/-6) gtk/window-decorator/events.c (+117/-3) gtk/window-decorator/gtk-window-decorator.c (+59/-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 (+438/-0) gtk/window-decorator/local-menus/src/local-menus.h (+125/-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 (+47/-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 (+89/-0) gtk/window-decorator/local-menus/tests/test-local-menu.h (+106/-0) gtk/window-decorator/metacity.c (+54/-0) gtk/window-decorator/wnck.c (+32/-1) |
To merge this branch: | bzr merge lp:~smspillaz/compiz-core/compiz-core.lim |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Daniel van Vugt | Approve | ||
Alan Griffiths | Approve | ||
Marco Trevisan (Treviño) | Approve | ||
Sam Spilsbury | Pending | ||
Review via email: mp+94891@code.launchpad.net |
This proposal supersedes a proposal from 2012-02-25.
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 : Posted in a previous version of this proposal | # |
No obvious errors
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal | # |
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 : Posted in a previous version of this proposal | # |
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 : Posted in a previous version of this proposal | # |
Ack.
Marco Trevisan (Treviño) (3v1n0) wrote : | # |
Crash fixed, it looks good to me now.
Unfortunately not all the apps yet supports the _UBUNTU_
Marco Trevisan (Treviño) (3v1n0) : | # |
- 3003. By Sam Spilsbury
-
Tell us if we have them
Alan Griffiths (alan-griffiths) : | # |
- 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.
Daniel van Vugt (vanvugt) wrote : | # |
No obvious problems or regressions. And Valgrind is happy.
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-03-02 02:56:17 +0000 | |||
4 | @@ -4,7 +4,10 @@ | |||
5 | 4 | set (CMAKE_INSTALL_RPATH ${libdir}) | 4 | set (CMAKE_INSTALL_RPATH ${libdir}) |
6 | 5 | endif (COMPIZ_BUILD_WITH_RPATH) | 5 | endif (COMPIZ_BUILD_WITH_RPATH) |
7 | 6 | 6 | ||
8 | 7 | add_subdirectory (local-menus) | ||
9 | 8 | |||
10 | 7 | include_directories ( | 9 | include_directories ( |
11 | 10 | ${CMAKE_CURRENT_SOURCE_DIR}/local-menus/src | ||
12 | 8 | ${compiz_SOURCE_DIR}/include | 11 | ${compiz_SOURCE_DIR}/include |
13 | 9 | ${CMAKE_BINARY_DIR}/gtk | 12 | ${CMAKE_BINARY_DIR}/gtk |
14 | 10 | ${GTK_WINDOW_DECORATOR_INCLUDE_DIRS} | 13 | ${GTK_WINDOW_DECORATOR_INCLUDE_DIRS} |
15 | @@ -63,6 +66,9 @@ | |||
16 | 63 | target_link_libraries ( | 66 | target_link_libraries ( |
17 | 64 | gtk-window-decorator | 67 | gtk-window-decorator |
18 | 65 | decoration | 68 | decoration |
19 | 69 | |||
20 | 70 | gtk_window_decorator_local_menus | ||
21 | 71 | |||
22 | 66 | ${GTK_WINDOW_DECORATOR_LIBRARIES} | 72 | ${GTK_WINDOW_DECORATOR_LIBRARIES} |
23 | 67 | ${GCONF_LIBRARIES} | 73 | ${GCONF_LIBRARIES} |
24 | 68 | ${DBUS_GLIB_LIBRARIES} | 74 | ${DBUS_GLIB_LIBRARIES} |
25 | 69 | 75 | ||
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-03-02 02:56:17 +0000 | |||
29 | @@ -24,6 +24,7 @@ | |||
30 | 24 | */ | 24 | */ |
31 | 25 | 25 | ||
32 | 26 | #include "gtk-window-decorator.h" | 26 | #include "gtk-window-decorator.h" |
33 | 27 | #include "local-menus.h" | ||
34 | 27 | 28 | ||
35 | 28 | decor_frame_t * | 29 | decor_frame_t * |
36 | 29 | create_normal_frame (const gchar *type) | 30 | create_normal_frame (const gchar *type) |
37 | @@ -230,12 +231,16 @@ | |||
38 | 230 | void | 231 | void |
39 | 231 | update_event_windows (WnckWindow *win) | 232 | update_event_windows (WnckWindow *win) |
40 | 232 | { | 233 | { |
41 | 234 | #define GWD_SHOW_LOCAL_MENU (WNCK_WINDOW_ACTION_BELOW << 1) | ||
42 | 233 | Display *xdisplay; | 235 | Display *xdisplay; |
43 | 234 | decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); | 236 | decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); |
44 | 235 | gint x0, y0, width, height, x, y, w, h; | 237 | gint x0, y0, width, height, x, y, w, h; |
45 | 236 | gint i, j, k, l; | 238 | gint i, j, k, l; |
46 | 237 | gint actions = d->actions; | 239 | gint actions = d->actions; |
47 | 238 | 240 | ||
48 | 241 | if (gwd_window_should_have_local_menu (win ? wnck_window_get_xid (win) : 0)) | ||
49 | 242 | actions |= GWD_SHOW_LOCAL_MENU; | ||
50 | 243 | |||
51 | 239 | xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); | 244 | xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()); |
52 | 240 | 245 | ||
53 | 241 | /* Get the geometry of the client */ | 246 | /* Get the geometry of the client */ |
54 | @@ -298,11 +303,19 @@ | |||
55 | 298 | XMapWindow (xdisplay, d->event_windows[i][j].window); | 303 | XMapWindow (xdisplay, d->event_windows[i][j].window); |
56 | 299 | XMoveResizeWindow (xdisplay, d->event_windows[i][j].window, | 304 | XMoveResizeWindow (xdisplay, d->event_windows[i][j].window, |
57 | 300 | x, y, w, h); | 305 | x, y, w, h); |
58 | 306 | |||
59 | 307 | BoxPtr box = &d->event_windows[i][j].pos; | ||
60 | 308 | box->x1 = x; | ||
61 | 309 | box->x2 = x + w; | ||
62 | 310 | box->y1 = y; | ||
63 | 311 | box->y2 = y + h; | ||
64 | 301 | } | 312 | } |
65 | 302 | /* No parent and no geometry - unmap all event windows */ | 313 | /* No parent and no geometry - unmap all event windows */ |
66 | 303 | else if (!d->frame_window) | 314 | else if (!d->frame_window) |
67 | 304 | { | 315 | { |
68 | 305 | XUnmapWindow (xdisplay, d->event_windows[i][j].window); | 316 | XUnmapWindow (xdisplay, d->event_windows[i][j].window); |
69 | 317 | |||
70 | 318 | memset (&d->event_windows[i][j].pos, 0, sizeof (Box)); | ||
71 | 306 | } | 319 | } |
72 | 307 | } | 320 | } |
73 | 308 | } | 321 | } |
74 | @@ -326,12 +339,18 @@ | |||
75 | 326 | WNCK_WINDOW_ACTION_STICK, | 339 | WNCK_WINDOW_ACTION_STICK, |
76 | 327 | WNCK_WINDOW_ACTION_UNSHADE, | 340 | WNCK_WINDOW_ACTION_UNSHADE, |
77 | 328 | WNCK_WINDOW_ACTION_ABOVE, | 341 | WNCK_WINDOW_ACTION_ABOVE, |
84 | 329 | WNCK_WINDOW_ACTION_UNSTICK | 342 | WNCK_WINDOW_ACTION_UNSTICK, |
85 | 330 | #else | 343 | #else |
86 | 331 | 0, | 344 | 0, |
87 | 332 | 0, | 345 | 0, |
88 | 333 | 0, | 346 | 0, |
89 | 334 | 0, | 347 | 0, |
90 | 348 | 0, | ||
91 | 349 | #endif | ||
92 | 350 | |||
93 | 351 | #ifdef META_HAS_LOCAL_MENUS | ||
94 | 352 | GWD_SHOW_LOCAL_MENU | ||
95 | 353 | #else | ||
96 | 335 | 0 | 354 | 0 |
97 | 336 | #endif | 355 | #endif |
98 | 337 | 356 | ||
99 | @@ -371,10 +390,17 @@ | |||
100 | 371 | Window win = d->button_windows[i].window; | 390 | Window win = d->button_windows[i].window; |
101 | 372 | XMapWindow (xdisplay, win); | 391 | XMapWindow (xdisplay, win); |
102 | 373 | XMoveResizeWindow (xdisplay, win, x, y, w, h); | 392 | XMoveResizeWindow (xdisplay, win, x, y, w, h); |
103 | 393 | |||
104 | 394 | BoxPtr box = &d->button_windows[i].pos; | ||
105 | 395 | box->x1 = x; | ||
106 | 396 | box->x2 = x + w; | ||
107 | 397 | box->y1 = y; | ||
108 | 398 | box->y2 = y + h; | ||
109 | 374 | } | 399 | } |
110 | 375 | else if (!d->frame_window) | 400 | else if (!d->frame_window) |
111 | 376 | { | 401 | { |
112 | 377 | XUnmapWindow (xdisplay, d->button_windows[i].window); | 402 | XUnmapWindow (xdisplay, d->button_windows[i].window); |
113 | 403 | memset (&d->button_windows[i].pos, 0, sizeof (Box)); | ||
114 | 378 | } | 404 | } |
115 | 379 | } | 405 | } |
116 | 380 | 406 | ||
117 | 381 | 407 | ||
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-03-02 02:56:17 +0000 | |||
121 | @@ -24,6 +24,16 @@ | |||
122 | 24 | */ | 24 | */ |
123 | 25 | 25 | ||
124 | 26 | #include "gtk-window-decorator.h" | 26 | #include "gtk-window-decorator.h" |
125 | 27 | #include "local-menus.h" | ||
126 | 28 | |||
127 | 29 | typedef struct _delayed_move_info | ||
128 | 30 | { | ||
129 | 31 | WnckWindow *win; | ||
130 | 32 | int x_root; | ||
131 | 33 | int y_root; | ||
132 | 34 | unsigned int button; | ||
133 | 35 | unsigned int time; | ||
134 | 36 | } delayed_move_info; | ||
135 | 27 | 37 | ||
136 | 28 | void | 38 | void |
137 | 29 | move_resize_window (WnckWindow *win, | 39 | move_resize_window (WnckWindow *win, |
138 | @@ -65,8 +75,9 @@ | |||
139 | 65 | ev.xclient.data.l[3] = gtkwd_event->button; | 75 | ev.xclient.data.l[3] = gtkwd_event->button; |
140 | 66 | ev.xclient.data.l[4] = 1; | 76 | ev.xclient.data.l[4] = 1; |
141 | 67 | 77 | ||
144 | 68 | XUngrabPointer (xdisplay, gtkwd_event->time); | 78 | XAllowEvents (xdisplay, AsyncKeyboard | AsyncPointer, CurrentTime); |
145 | 69 | XUngrabKeyboard (xdisplay, gtkwd_event->time); | 79 | XUngrabPointer (xdisplay, CurrentTime); |
146 | 80 | XUngrabKeyboard (xdisplay, CurrentTime); | ||
147 | 70 | 81 | ||
148 | 71 | XSendEvent (xdisplay, xroot, FALSE, | 82 | XSendEvent (xdisplay, xroot, FALSE, |
149 | 72 | SubstructureRedirectMask | SubstructureNotifyMask, | 83 | SubstructureRedirectMask | SubstructureNotifyMask, |
150 | @@ -75,6 +86,24 @@ | |||
151 | 75 | XSync (xdisplay, FALSE); | 86 | XSync (xdisplay, FALSE); |
152 | 76 | } | 87 | } |
153 | 77 | 88 | ||
154 | 89 | static gboolean | ||
155 | 90 | move_resize_window_on_timeout (gpointer user_data) | ||
156 | 91 | { | ||
157 | 92 | delayed_move_info *info = (delayed_move_info *) user_data; | ||
158 | 93 | |||
159 | 94 | decor_event event; | ||
160 | 95 | event.x = 0; | ||
161 | 96 | event.y = 0; | ||
162 | 97 | event.x_root = info->x_root; | ||
163 | 98 | event.y_root = info->y_root; | ||
164 | 99 | event.button = info->button; | ||
165 | 100 | event.window = wnck_window_get_xid (info->win); | ||
166 | 101 | |||
167 | 102 | move_resize_window (info->win, WM_MOVERESIZE_MOVE, &event); | ||
168 | 103 | |||
169 | 104 | return FALSE; | ||
170 | 105 | } | ||
171 | 106 | |||
172 | 78 | void | 107 | void |
173 | 79 | common_button_event (WnckWindow *win, | 108 | common_button_event (WnckWindow *win, |
174 | 80 | decor_event *gtkwd_event, | 109 | decor_event *gtkwd_event, |
175 | @@ -380,6 +409,75 @@ | |||
176 | 380 | } | 409 | } |
177 | 381 | 410 | ||
178 | 382 | void | 411 | void |
179 | 412 | on_local_menu_hidden (gpointer user_data) | ||
180 | 413 | { | ||
181 | 414 | Window xid = GPOINTER_TO_INT (user_data); | ||
182 | 415 | WnckWindow *win = wnck_window_get (xid); | ||
183 | 416 | decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); | ||
184 | 417 | |||
185 | 418 | d->button_states[BUTTON_WINDOW_MENU] &= ~PRESSED_EVENT_WINDOW; | ||
186 | 419 | |||
187 | 420 | queue_decor_draw (d); | ||
188 | 421 | } | ||
189 | 422 | |||
190 | 423 | void | ||
191 | 424 | window_menu_button_event (WnckWindow *win, | ||
192 | 425 | decor_event *gtkwd_event, | ||
193 | 426 | decor_event_type gtkwd_type) | ||
194 | 427 | { | ||
195 | 428 | decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); | ||
196 | 429 | guint state = d->button_states[BUTTON_WINDOW_MENU]; | ||
197 | 430 | |||
198 | 431 | common_button_event (win, gtkwd_event, gtkwd_type, | ||
199 | 432 | BUTTON_WINDOW_MENU, 1, _("Window Menu")); | ||
200 | 433 | |||
201 | 434 | switch (gtkwd_type) { | ||
202 | 435 | case GButtonPress: | ||
203 | 436 | if (gtkwd_event->button == 1) | ||
204 | 437 | { | ||
205 | 438 | if (d->button_states[BUTTON_WINDOW_MENU] & BUTTON_EVENT_ACTION_STATE) | ||
206 | 439 | { | ||
207 | 440 | delayed_move_info *info = g_new0 (delayed_move_info, 1); | ||
208 | 441 | |||
209 | 442 | info->button = gtkwd_event->button; | ||
210 | 443 | info->time = gtkwd_event->time; | ||
211 | 444 | info->win = win; | ||
212 | 445 | info->x_root = gtkwd_event->x_root; | ||
213 | 446 | info->y_root = gtkwd_event->y_root; | ||
214 | 447 | |||
215 | 448 | gwd_prepare_show_local_menu ((start_move_window_cb) move_resize_window_on_timeout, (gpointer) info, info->x_root, info->y_root); | ||
216 | 449 | } | ||
217 | 450 | } | ||
218 | 451 | break; | ||
219 | 452 | case GButtonRelease: | ||
220 | 453 | if (gtkwd_event->button == 1) | ||
221 | 454 | if (state) | ||
222 | 455 | { | ||
223 | 456 | int win_x, win_y; | ||
224 | 457 | int box_x = d->button_windows[BUTTON_WINDOW_MENU].pos.x1; | ||
225 | 458 | |||
226 | 459 | wnck_window_get_geometry (win, &win_x, &win_y, NULL, NULL); | ||
227 | 460 | |||
228 | 461 | int x = win_x + box_x; | ||
229 | 462 | int y = win_y + d->context->extents.top; | ||
230 | 463 | |||
231 | 464 | gwd_show_local_menu (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), | ||
232 | 465 | wnck_window_get_xid (win), | ||
233 | 466 | x, y, | ||
234 | 467 | box_x, | ||
235 | 468 | d->context->extents.top, | ||
236 | 469 | gtkwd_event->button, | ||
237 | 470 | gtkwd_event->time, | ||
238 | 471 | (show_window_menu_hidden_cb) on_local_menu_hidden, | ||
239 | 472 | GINT_TO_POINTER (wnck_window_get_xid (d->win))); | ||
240 | 473 | } | ||
241 | 474 | break; | ||
242 | 475 | default: | ||
243 | 476 | break; | ||
244 | 477 | } | ||
245 | 478 | } | ||
246 | 479 | |||
247 | 480 | void | ||
248 | 383 | handle_title_button_event (WnckWindow *win, | 481 | handle_title_button_event (WnckWindow *win, |
249 | 384 | int action, | 482 | int action, |
250 | 385 | decor_event *gtkwd_event) | 483 | decor_event *gtkwd_event) |
251 | @@ -485,7 +583,17 @@ | |||
252 | 485 | 583 | ||
253 | 486 | restack_window (win, Above); | 584 | restack_window (win, Above); |
254 | 487 | 585 | ||
256 | 488 | move_resize_window (win, WM_MOVERESIZE_MOVE, gtkwd_event); | 586 | delayed_move_info *info = g_new0 (delayed_move_info, 1); |
257 | 587 | |||
258 | 588 | info->x_root = gtkwd_event->x_root; | ||
259 | 589 | info->y_root = gtkwd_event->y_root; | ||
260 | 590 | info->button = gtkwd_event->button; | ||
261 | 591 | info->time = gtkwd_event->time; | ||
262 | 592 | info->win = win; | ||
263 | 593 | |||
264 | 594 | move_resize_window_on_timeout ((gpointer) info); | ||
265 | 595 | |||
266 | 596 | g_free (info); | ||
267 | 489 | } | 597 | } |
268 | 490 | } | 598 | } |
269 | 491 | else if (gtkwd_event->button == 2) | 599 | else if (gtkwd_event->button == 2) |
270 | @@ -918,6 +1026,7 @@ | |||
271 | 918 | xid = (gulong) | 1026 | xid = (gulong) |
272 | 919 | g_hash_table_lookup (frame_table, | 1027 | g_hash_table_lookup (frame_table, |
273 | 920 | GINT_TO_POINTER (xevent->xbutton.window)); | 1028 | GINT_TO_POINTER (xevent->xbutton.window)); |
274 | 1029 | XAllowEvents (gdk_x11_display_get_xdisplay (gdkdisplay), AsyncPointer, CurrentTime); | ||
275 | 921 | break; | 1030 | break; |
276 | 922 | case EnterNotify: | 1031 | case EnterNotify: |
277 | 923 | case LeaveNotify: | 1032 | case LeaveNotify: |
278 | @@ -929,6 +1038,7 @@ | |||
279 | 929 | xid = (gulong) | 1038 | xid = (gulong) |
280 | 930 | g_hash_table_lookup (frame_table, | 1039 | g_hash_table_lookup (frame_table, |
281 | 931 | GINT_TO_POINTER (xevent->xmotion.window)); | 1040 | GINT_TO_POINTER (xevent->xmotion.window)); |
282 | 1041 | local_menu_process_motion (xevent->xmotion.x_root, xevent->xmotion.y_root); | ||
283 | 932 | break; | 1042 | break; |
284 | 933 | case PropertyNotify: | 1043 | case PropertyNotify: |
285 | 934 | if (xevent->xproperty.atom == frame_input_window_atom) | 1044 | if (xevent->xproperty.atom == frame_input_window_atom) |
286 | @@ -1031,6 +1141,10 @@ | |||
287 | 1031 | if (get_window_prop (xevent->xproperty.window, select_window_atom, &select)) | 1141 | if (get_window_prop (xevent->xproperty.window, select_window_atom, &select)) |
288 | 1032 | update_switcher_window (xevent->xproperty.window, select); | 1142 | update_switcher_window (xevent->xproperty.window, select); |
289 | 1033 | } | 1143 | } |
290 | 1144 | else if (xevent->xproperty.atom == ubuntu_appmenu_unique_name_atom) | ||
291 | 1145 | { | ||
292 | 1146 | local_menu_cache_reload_xwindow (gdk_x11_display_get_xdisplay (gdkdisplay), xevent->xproperty.window); | ||
293 | 1147 | } | ||
294 | 1034 | break; | 1148 | break; |
295 | 1035 | case DestroyNotify: | 1149 | case DestroyNotify: |
296 | 1036 | g_hash_table_remove (frame_table, | 1150 | g_hash_table_remove (frame_table, |
297 | 1037 | 1151 | ||
298 | === modified file 'gtk/window-decorator/gtk-window-decorator.c' | |||
299 | --- gtk/window-decorator/gtk-window-decorator.c 2011-10-13 12:22:14 +0000 | |||
300 | +++ gtk/window-decorator/gtk-window-decorator.c 2012-03-02 02:56:17 +0000 | |||
301 | @@ -24,6 +24,7 @@ | |||
302 | 24 | */ | 24 | */ |
303 | 25 | 25 | ||
304 | 26 | #include "gtk-window-decorator.h" | 26 | #include "gtk-window-decorator.h" |
305 | 27 | #include "local-menus.h" | ||
306 | 27 | 28 | ||
307 | 28 | gboolean minimal = FALSE; | 29 | gboolean minimal = FALSE; |
308 | 29 | 30 | ||
309 | @@ -48,6 +49,7 @@ | |||
310 | 48 | Atom toolkit_action_atom; | 49 | Atom toolkit_action_atom; |
311 | 49 | Atom toolkit_action_window_menu_atom; | 50 | Atom toolkit_action_window_menu_atom; |
312 | 50 | Atom toolkit_action_force_quit_dialog_atom; | 51 | Atom toolkit_action_force_quit_dialog_atom; |
313 | 52 | Atom ubuntu_appmenu_unique_name_atom; | ||
314 | 51 | 53 | ||
315 | 52 | Atom net_wm_state_atom; | 54 | Atom net_wm_state_atom; |
316 | 53 | Atom net_wm_state_modal_atom; | 55 | Atom net_wm_state_modal_atom; |
317 | @@ -128,6 +130,38 @@ | |||
318 | 128 | "normal", "modal_dialog", "dialog", "menu", "utility" | 130 | "normal", "modal_dialog", "dialog", "menu", "utility" |
319 | 129 | }; | 131 | }; |
320 | 130 | 132 | ||
321 | 133 | Box * | ||
322 | 134 | get_active_window_local_menu_rectangle (gpointer user_data, int *dx, int *dy, int *top_height, Window *xid) | ||
323 | 135 | { | ||
324 | 136 | WnckScreen *screen = (WnckScreen *) user_data; | ||
325 | 137 | WnckWindow *window = wnck_screen_get_active_window (screen); | ||
326 | 138 | int width, height; | ||
327 | 139 | decor_t *d = g_object_get_data (G_OBJECT (window), "decor"); | ||
328 | 140 | |||
329 | 141 | if (!d->decorated) | ||
330 | 142 | return NULL; | ||
331 | 143 | |||
332 | 144 | wnck_window_get_geometry (window, dx, dy, &width, &height); | ||
333 | 145 | |||
334 | 146 | *top_height = d->context->extents.top; | ||
335 | 147 | |||
336 | 148 | *xid = wnck_window_get_xid (window); | ||
337 | 149 | |||
338 | 150 | Box *rect = &d->button_windows[BUTTON_WINDOW_MENU].pos; | ||
339 | 151 | |||
340 | 152 | return rect; | ||
341 | 153 | } | ||
342 | 154 | |||
343 | 155 | void | ||
344 | 156 | on_local_menu_window_menu_updated (gpointer user_data) | ||
345 | 157 | { | ||
346 | 158 | Window xid = GPOINTER_TO_INT (user_data); | ||
347 | 159 | WnckWindow *window = wnck_window_get (xid); | ||
348 | 160 | decor_t *d = g_object_get_data (G_OBJECT (window), "decor"); | ||
349 | 161 | |||
350 | 162 | queue_decor_draw (d); | ||
351 | 163 | } | ||
352 | 164 | |||
353 | 131 | int | 165 | int |
354 | 132 | main (int argc, char *argv[]) | 166 | main (int argc, char *argv[]) |
355 | 133 | { | 167 | { |
356 | @@ -304,6 +338,7 @@ | |||
357 | 304 | 338 | ||
358 | 305 | net_wm_state_atom = XInternAtom (xdisplay,"_NET_WM_STATE", 0); | 339 | net_wm_state_atom = XInternAtom (xdisplay,"_NET_WM_STATE", 0); |
359 | 306 | net_wm_state_modal_atom = XInternAtom (xdisplay, "_NET_WM_STATE_MODAL", 0); | 340 | net_wm_state_modal_atom = XInternAtom (xdisplay, "_NET_WM_STATE_MODAL", 0); |
360 | 341 | ubuntu_appmenu_unique_name_atom = XInternAtom (xdisplay, "_UBUNTU_APPMENU_UNIQUE_NAME", 0); | ||
361 | 307 | 342 | ||
362 | 308 | status = decor_acquire_dm_session (xdisplay, | 343 | status = decor_acquire_dm_session (xdisplay, |
363 | 309 | gdk_screen_get_number (gdkscreen), | 344 | gdk_screen_get_number (gdkscreen), |
364 | @@ -448,8 +483,32 @@ | |||
365 | 448 | 483 | ||
366 | 449 | update_default_decorations (gdkscreen); | 484 | update_default_decorations (gdkscreen); |
367 | 450 | 485 | ||
368 | 486 | #ifdef META_HAS_LOCAL_MENUS | ||
369 | 487 | GDBusConnection *conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); | ||
370 | 488 | local_menu_entry_activated_request_funcs funcs = | ||
371 | 489 | { | ||
372 | 490 | get_active_window_local_menu_rectangle, | ||
373 | 491 | on_local_menu_window_menu_updated | ||
374 | 492 | }; | ||
375 | 493 | |||
376 | 494 | if (conn) | ||
377 | 495 | { | ||
378 | 496 | global_lim_listener = g_dbus_proxy_new_sync (conn, 0, NULL, "com.canonical.Unity.Panel.Service", | ||
379 | 497 | "/com/canonical/Unity/Panel/Service", | ||
380 | 498 | "com.canonical.Unity.Panel.Service", | ||
381 | 499 | NULL, NULL); | ||
382 | 500 | |||
383 | 501 | g_signal_connect (G_OBJECT (global_lim_listener), "g-signal", G_CALLBACK (local_menu_entry_activated_request), (gpointer) &funcs); | ||
384 | 502 | } | ||
385 | 503 | #endif | ||
386 | 451 | gtk_main (); | 504 | gtk_main (); |
387 | 505 | #ifdef META_HAS_LOCAL_MENUS | ||
388 | 506 | if (global_lim_listener) | ||
389 | 507 | g_object_unref (global_lim_listener); | ||
390 | 452 | 508 | ||
391 | 509 | if (conn) | ||
392 | 510 | g_object_unref (conn); | ||
393 | 511 | #endif | ||
394 | 453 | win = windows = wnck_screen_get_windows (screen); | 512 | win = windows = wnck_screen_get_windows (screen); |
395 | 454 | 513 | ||
396 | 455 | while (win != NULL) | 514 | while (win != NULL) |
397 | 456 | 515 | ||
398 | === modified file 'gtk/window-decorator/gtk-window-decorator.h' | |||
399 | --- gtk/window-decorator/gtk-window-decorator.h 2011-10-13 12:22:14 +0000 | |||
400 | +++ gtk/window-decorator/gtk-window-decorator.h 2012-03-02 02:56:17 +0000 | |||
401 | @@ -306,6 +306,7 @@ | |||
402 | 306 | extern Atom toolkit_action_force_quit_dialog_atom; | 306 | extern Atom toolkit_action_force_quit_dialog_atom; |
403 | 307 | extern Atom net_wm_state_atom; | 307 | extern Atom net_wm_state_atom; |
404 | 308 | extern Atom net_wm_state_modal_atom; | 308 | extern Atom net_wm_state_modal_atom; |
405 | 309 | extern Atom ubuntu_appmenu_unique_name_atom; | ||
406 | 309 | 310 | ||
407 | 310 | extern Time dm_sn_timestamp; | 311 | extern Time dm_sn_timestamp; |
408 | 311 | 312 | ||
409 | @@ -328,7 +329,8 @@ | |||
410 | 328 | #define BUTTON_UNSHADE 7 | 329 | #define BUTTON_UNSHADE 7 |
411 | 329 | #define BUTTON_UNABOVE 8 | 330 | #define BUTTON_UNABOVE 8 |
412 | 330 | #define BUTTON_UNSTICK 9 | 331 | #define BUTTON_UNSTICK 9 |
414 | 331 | #define BUTTON_NUM 10 | 332 | #define BUTTON_WINDOW_MENU 10 |
415 | 333 | #define BUTTON_NUM 11 | ||
416 | 332 | 334 | ||
417 | 333 | struct _pos { | 335 | struct _pos { |
418 | 334 | int x, y, w, h; | 336 | int x, y, w, h; |
419 | @@ -1013,6 +1015,11 @@ | |||
420 | 1013 | decor_event_type gtkwd_type); | 1015 | decor_event_type gtkwd_type); |
421 | 1014 | 1016 | ||
422 | 1015 | void | 1017 | void |
423 | 1018 | window_menu_button_event (WnckWindow *win, | ||
424 | 1019 | decor_event *gtkwd_event, | ||
425 | 1020 | decor_event_type gtkwd_type); | ||
426 | 1021 | |||
427 | 1022 | void | ||
428 | 1016 | handle_title_button_event (WnckWindow *win, | 1023 | handle_title_button_event (WnckWindow *win, |
429 | 1017 | int action, | 1024 | int action, |
430 | 1018 | decor_event *gtkwd_event); | 1025 | decor_event *gtkwd_event); |
431 | 1019 | 1026 | ||
432 | === added directory 'gtk/window-decorator/local-menus' | |||
433 | === added file 'gtk/window-decorator/local-menus/CMakeLists.txt' | |||
434 | --- gtk/window-decorator/local-menus/CMakeLists.txt 1970-01-01 00:00:00 +0000 | |||
435 | +++ gtk/window-decorator/local-menus/CMakeLists.txt 2012-03-02 02:56:17 +0000 | |||
436 | @@ -0,0 +1,60 @@ | |||
437 | 1 | pkg_check_modules( | ||
438 | 2 | LOCAL_MENUS | ||
439 | 3 | REQUIRED | ||
440 | 4 | glib-2.0 gio-2.0 libwnck-1.0 gtk+-2.0>=2.18.0 | ||
441 | 5 | ) | ||
442 | 6 | |||
443 | 7 | INCLUDE_DIRECTORIES( | ||
444 | 8 | ${CMAKE_CURRENT_SOURCE_DIR}/include | ||
445 | 9 | ${CMAKE_CURRENT_SOURCE_DIR}/src | ||
446 | 10 | |||
447 | 11 | ${compiz_SOURCE_DIR}/gtk/window-decorator | ||
448 | 12 | |||
449 | 13 | ${Boost_INCLUDE_DIRS} | ||
450 | 14 | |||
451 | 15 | ${LOCAL_MENUS_INCLUDE_DIRS} | ||
452 | 16 | ${METACITY_INCLUDE_DIRS} | ||
453 | 17 | ) | ||
454 | 18 | |||
455 | 19 | LINK_DIRECTORIES (${LOCAL_MENUS_LIBRARY_DIRS}) | ||
456 | 20 | |||
457 | 21 | SET( | ||
458 | 22 | PUBLIC_HEADERS | ||
459 | 23 | ) | ||
460 | 24 | |||
461 | 25 | SET( | ||
462 | 26 | PRIVATE_HEADERS | ||
463 | 27 | ${CMAKE_CURRENT_SOURCE_DIR}/src/local-menus.h | ||
464 | 28 | ) | ||
465 | 29 | |||
466 | 30 | SET( | ||
467 | 31 | SRCS | ||
468 | 32 | ${CMAKE_CURRENT_SOURCE_DIR}/src/local-menus.c | ||
469 | 33 | ) | ||
470 | 34 | |||
471 | 35 | ADD_LIBRARY( | ||
472 | 36 | gtk_window_decorator_local_menus STATIC | ||
473 | 37 | |||
474 | 38 | ${SRCS} | ||
475 | 39 | |||
476 | 40 | ${PUBLIC_HEADERS} | ||
477 | 41 | ${PRIVATE_HEADERS} | ||
478 | 42 | ) | ||
479 | 43 | |||
480 | 44 | IF (COMPIZ_BUILD_TESTING) | ||
481 | 45 | ADD_SUBDIRECTORY( ${CMAKE_CURRENT_SOURCE_DIR}/tests ) | ||
482 | 46 | ENDIF (COMPIZ_BUILD_TESTING) | ||
483 | 47 | |||
484 | 48 | SET_TARGET_PROPERTIES( | ||
485 | 49 | gtk_window_decorator_local_menus PROPERTIES | ||
486 | 50 | PUBLIC_HEADER "${PUBLIC_HEADERS}" | ||
487 | 51 | ) | ||
488 | 52 | |||
489 | 53 | install (FILES ${PUBLIC_HEADERS} DESTINATION ${COMPIZ_CORE_INCLUDE_DIR}) | ||
490 | 54 | |||
491 | 55 | TARGET_LINK_LIBRARIES( | ||
492 | 56 | gtk_window_decorator_local_menus | ||
493 | 57 | |||
494 | 58 | ${LOCAL_MENUS_LIBRARIES} | ||
495 | 59 | ) | ||
496 | 60 | |||
497 | 0 | 61 | ||
498 | === added directory 'gtk/window-decorator/local-menus/include' | |||
499 | === added directory 'gtk/window-decorator/local-menus/src' | |||
500 | === added file 'gtk/window-decorator/local-menus/src/local-menus.c' | |||
501 | --- gtk/window-decorator/local-menus/src/local-menus.c 1970-01-01 00:00:00 +0000 | |||
502 | +++ gtk/window-decorator/local-menus/src/local-menus.c 2012-03-02 02:56:17 +0000 | |||
503 | @@ -0,0 +1,438 @@ | |||
504 | 1 | /* | ||
505 | 2 | * Copyright © 2006 Novell, Inc. | ||
506 | 3 | * | ||
507 | 4 | * This library is free software; you can redistribute it and/or | ||
508 | 5 | * modify it under the terms of the GNU Lesser General Public | ||
509 | 6 | * License as published by the Free Software Foundation; either | ||
510 | 7 | * version 2 of the License, or (at your option) any later version. | ||
511 | 8 | * | ||
512 | 9 | * This library is distributed in the hope that it will be useful, | ||
513 | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
514 | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
515 | 12 | * Lesser General Public License for more details. | ||
516 | 13 | * | ||
517 | 14 | * You should have received a copy of the GNU Lesser General Public | ||
518 | 15 | * License along with this library; if not, write to the | ||
519 | 16 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
520 | 17 | * Boston, MA 02111-1307, USA. | ||
521 | 18 | * | ||
522 | 19 | * Author: David Reveman <davidr@novell.com> | ||
523 | 20 | * | ||
524 | 21 | * 2D Mode: Copyright © 2010 Sam Spilsbury <smspillaz@gmail.com> | ||
525 | 22 | * Frames Management: Copright © 2011 Canonical Ltd. | ||
526 | 23 | * Authored By: Sam Spilsbury <sam.spilsbury@canonical.com> | ||
527 | 24 | */ | ||
528 | 25 | |||
529 | 26 | #include <string.h> | ||
530 | 27 | #include "local-menus.h" | ||
531 | 28 | #include <gdk/gdk.h> | ||
532 | 29 | #include <gdk/gdkx.h> | ||
533 | 30 | #include <stdlib.h> | ||
534 | 31 | |||
535 | 32 | #define GLOBAL 0 | ||
536 | 33 | #define LOCAL 1 | ||
537 | 34 | |||
538 | 35 | #define ALLOWED 2 | ||
539 | 36 | #define NOT_ALLOWED 1 | ||
540 | 37 | |||
541 | 38 | gint menu_mode = GLOBAL; | ||
542 | 39 | |||
543 | 40 | GDBusProxy *global_lim_listener; | ||
544 | 41 | |||
545 | 42 | |||
546 | 43 | #ifdef META_HAS_LOCAL_MENUS | ||
547 | 44 | static void | ||
548 | 45 | gwd_menu_mode_changed (GSettings *settings, | ||
549 | 46 | gchar *key, | ||
550 | 47 | gpointer user_data) | ||
551 | 48 | { | ||
552 | 49 | menu_mode = g_settings_get_enum (settings, "menu-mode"); | ||
553 | 50 | } | ||
554 | 51 | #endif | ||
555 | 52 | |||
556 | 53 | active_local_menu *active_menu; | ||
557 | 54 | pending_local_menu *pending_menu; | ||
558 | 55 | |||
559 | 56 | GHashTable *get_windows_with_menus_table () | ||
560 | 57 | { | ||
561 | 58 | static GHashTable *windows_with_menus = NULL; | ||
562 | 59 | |||
563 | 60 | if (!windows_with_menus) | ||
564 | 61 | windows_with_menus = g_hash_table_new (NULL, NULL); | ||
565 | 62 | |||
566 | 63 | return windows_with_menus; | ||
567 | 64 | } | ||
568 | 65 | |||
569 | 66 | static gboolean read_xprop_for_window (Display *dpy, Window xid) | ||
570 | 67 | { | ||
571 | 68 | Atom ubuntu_appmenu_unique_name = XInternAtom (dpy, "_UBUNTU_APPMENU_UNIQUE_NAME", FALSE); | ||
572 | 69 | Atom utf8_string = XInternAtom (dpy, "UTF8_STRING", FALSE); | ||
573 | 70 | Atom actual; | ||
574 | 71 | int fmt; | ||
575 | 72 | unsigned long nitems, nleft; | ||
576 | 73 | unsigned char *prop; | ||
577 | 74 | XGetWindowProperty (dpy, xid, ubuntu_appmenu_unique_name, | ||
578 | 75 | 0L, 16L, FALSE, utf8_string, &actual, &fmt, &nitems, &nleft, &prop); | ||
579 | 76 | |||
580 | 77 | if (actual == utf8_string && fmt == 8 && nitems > 1) | ||
581 | 78 | { | ||
582 | 79 | g_hash_table_replace (get_windows_with_menus_table (), GINT_TO_POINTER (xid), GINT_TO_POINTER (ALLOWED)); | ||
583 | 80 | return TRUE; | ||
584 | 81 | } | ||
585 | 82 | else | ||
586 | 83 | { | ||
587 | 84 | g_hash_table_replace (get_windows_with_menus_table (), GINT_TO_POINTER (xid), GINT_TO_POINTER (NOT_ALLOWED)); | ||
588 | 85 | return FALSE; | ||
589 | 86 | } | ||
590 | 87 | } | ||
591 | 88 | |||
592 | 89 | gboolean | ||
593 | 90 | local_menu_allowed_on_window (Display *dpy, Window xid) | ||
594 | 91 | { | ||
595 | 92 | gpointer local_menu_allowed_found = g_hash_table_lookup (get_windows_with_menus_table (), GINT_TO_POINTER (xid)); | ||
596 | 93 | |||
597 | 94 | if (local_menu_allowed_found) | ||
598 | 95 | { | ||
599 | 96 | return GPOINTER_TO_INT (local_menu_allowed_found) == ALLOWED; | ||
600 | 97 | } | ||
601 | 98 | else if (dpy && xid) | ||
602 | 99 | { | ||
603 | 100 | return read_xprop_for_window (dpy, xid); | ||
604 | 101 | } | ||
605 | 102 | |||
606 | 103 | return FALSE; | ||
607 | 104 | } | ||
608 | 105 | |||
609 | 106 | gboolean | ||
610 | 107 | gwd_window_should_have_local_menu (Window win) | ||
611 | 108 | { | ||
612 | 109 | #ifdef META_HAS_LOCAL_MENUS | ||
613 | 110 | const gchar * const *schemas = g_settings_list_schemas (); | ||
614 | 111 | static GSettings *lim_settings = NULL; | ||
615 | 112 | while (*schemas != NULL && !lim_settings) | ||
616 | 113 | { | ||
617 | 114 | if (g_str_equal (*schemas, "com.canonical.indicator.appmenu")) | ||
618 | 115 | { | ||
619 | 116 | lim_settings = g_settings_new ("com.canonical.indicator.appmenu"); | ||
620 | 117 | menu_mode = g_settings_get_enum (lim_settings, "menu-mode"); | ||
621 | 118 | g_signal_connect (lim_settings, "changed::menu-mode", G_CALLBACK (gwd_menu_mode_changed), NULL); | ||
622 | 119 | break; | ||
623 | 120 | } | ||
624 | 121 | ++schemas; | ||
625 | 122 | } | ||
626 | 123 | |||
627 | 124 | if (lim_settings && win) | ||
628 | 125 | return menu_mode == LOCAL && local_menu_allowed_on_window (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), win); | ||
629 | 126 | #endif | ||
630 | 127 | |||
631 | 128 | return FALSE; | ||
632 | 129 | } | ||
633 | 130 | |||
634 | 131 | gchar * | ||
635 | 132 | gwd_get_entry_id_from_sync_variant (GVariant *args) | ||
636 | 133 | { | ||
637 | 134 | /* We need to get the indicator data once we've called show */ | ||
638 | 135 | |||
639 | 136 | GVariantIter* iter = NULL; | ||
640 | 137 | gchar* name_hint = NULL; | ||
641 | 138 | gchar* indicator_id = NULL; | ||
642 | 139 | gchar* entry_id = NULL; | ||
643 | 140 | gchar* label = NULL; | ||
644 | 141 | gboolean label_sensitive = FALSE; | ||
645 | 142 | gboolean label_visible = FALSE; | ||
646 | 143 | guint32 image_type = 0; | ||
647 | 144 | gchar* image_data = NULL; | ||
648 | 145 | gboolean image_sensitive = FALSE; | ||
649 | 146 | gboolean image_visible = FALSE; | ||
650 | 147 | gint32 priority = -1; | ||
651 | 148 | |||
652 | 149 | g_variant_get (args, "(a(ssssbbusbbi))", &iter); | ||
653 | 150 | while (g_variant_iter_loop (iter, "(ssssbbusbbi)", | ||
654 | 151 | &indicator_id, | ||
655 | 152 | &entry_id, | ||
656 | 153 | &name_hint, | ||
657 | 154 | &label, | ||
658 | 155 | &label_sensitive, | ||
659 | 156 | &label_visible, | ||
660 | 157 | &image_type, | ||
661 | 158 | &image_data, | ||
662 | 159 | &image_sensitive, | ||
663 | 160 | &image_visible, | ||
664 | 161 | &priority)) | ||
665 | 162 | { | ||
666 | 163 | g_variant_unref (args); | ||
667 | 164 | return g_strdup (entry_id); | ||
668 | 165 | } | ||
669 | 166 | |||
670 | 167 | g_variant_unref (args); | ||
671 | 168 | g_assert_not_reached (); | ||
672 | 169 | return NULL; | ||
673 | 170 | } | ||
674 | 171 | #ifdef META_HAS_LOCAL_MENUS | ||
675 | 172 | static void | ||
676 | 173 | on_local_menu_activated (GDBusProxy *proxy, | ||
677 | 174 | gchar *sender_name, | ||
678 | 175 | gchar *signal_name, | ||
679 | 176 | GVariant *parameters, | ||
680 | 177 | gpointer user_data) | ||
681 | 178 | { | ||
682 | 179 | |||
683 | 180 | if (g_strcmp0 (signal_name, "EntryActivated") == 0) | ||
684 | 181 | { | ||
685 | 182 | show_local_menu_data *d = (show_local_menu_data *) user_data; | ||
686 | 183 | gchar *entry_id = NULL; | ||
687 | 184 | gint x_out, y_out; | ||
688 | 185 | guint width, height; | ||
689 | 186 | |||
690 | 187 | g_variant_get (parameters, "(s(iiuu))", &entry_id, &x_out, &y_out, &width, &height, NULL); | ||
691 | 188 | |||
692 | 189 | if (!d->local_menu_entry_id) | ||
693 | 190 | { | ||
694 | 191 | GError *error = NULL; | ||
695 | 192 | GVariant *params = g_variant_new ("(s)", "libappmenu.so", NULL); | ||
696 | 193 | GVariant *args = g_dbus_proxy_call_sync (proxy, "SyncOne", params, 0, 500, NULL, &error); | ||
697 | 194 | |||
698 | 195 | g_assert_no_error (error); | ||
699 | 196 | d->local_menu_entry_id = gwd_get_entry_id_from_sync_variant (args); | ||
700 | 197 | } | ||
701 | 198 | |||
702 | 199 | if (g_strcmp0 (entry_id, d->local_menu_entry_id) == 0) | ||
703 | 200 | { | ||
704 | 201 | d->rect->x = x_out - d->dx; | ||
705 | 202 | d->rect->y = y_out - d->dy; | ||
706 | 203 | d->rect->width = width; | ||
707 | 204 | d->rect->height = height; | ||
708 | 205 | (*d->cb) (d->user_data); | ||
709 | 206 | } | ||
710 | 207 | else if (g_strcmp0 (entry_id, "") == 0) | ||
711 | 208 | { | ||
712 | 209 | memset (d->rect, 0, sizeof (GdkRectangle)); | ||
713 | 210 | (*d->cb) (d->user_data); | ||
714 | 211 | |||
715 | 212 | g_signal_handlers_disconnect_by_func (proxy, on_local_menu_activated, d); | ||
716 | 213 | |||
717 | 214 | if (active_menu) | ||
718 | 215 | { | ||
719 | 216 | g_free (active_menu); | ||
720 | 217 | active_menu = NULL; | ||
721 | 218 | } | ||
722 | 219 | |||
723 | 220 | g_free (d->local_menu_entry_id); | ||
724 | 221 | g_free (d); | ||
725 | 222 | } | ||
726 | 223 | } | ||
727 | 224 | |||
728 | 225 | } | ||
729 | 226 | #endif | ||
730 | 227 | gboolean | ||
731 | 228 | gwd_move_window_instead (gpointer user_data) | ||
732 | 229 | { | ||
733 | 230 | (*pending_menu->cb) (pending_menu->user_data); | ||
734 | 231 | g_source_remove (pending_menu->move_timeout_id); | ||
735 | 232 | g_free (pending_menu->user_data); | ||
736 | 233 | g_free (pending_menu); | ||
737 | 234 | pending_menu = NULL; | ||
738 | 235 | return FALSE; | ||
739 | 236 | } | ||
740 | 237 | |||
741 | 238 | void | ||
742 | 239 | local_menu_process_motion(gint x_root, gint y_root) | ||
743 | 240 | { | ||
744 | 241 | if (!pending_menu) | ||
745 | 242 | return; | ||
746 | 243 | |||
747 | 244 | if (abs (pending_menu->x_root - x_root) > 4 && | ||
748 | 245 | abs (pending_menu->y_root - y_root) > 4) | ||
749 | 246 | gwd_move_window_instead (pending_menu); | ||
750 | 247 | } | ||
751 | 248 | |||
752 | 249 | void | ||
753 | 250 | gwd_prepare_show_local_menu (start_move_window_cb start_move_window, | ||
754 | 251 | gpointer user_data_start_move_window, | ||
755 | 252 | gint x_root, | ||
756 | 253 | gint y_root) | ||
757 | 254 | { | ||
758 | 255 | if (pending_menu) | ||
759 | 256 | { | ||
760 | 257 | g_source_remove (pending_menu->move_timeout_id); | ||
761 | 258 | g_free (pending_menu->user_data); | ||
762 | 259 | g_free (pending_menu); | ||
763 | 260 | pending_menu = NULL; | ||
764 | 261 | } | ||
765 | 262 | |||
766 | 263 | pending_menu = g_new0 (pending_local_menu, 1); | ||
767 | 264 | pending_menu->cb = start_move_window; | ||
768 | 265 | pending_menu->user_data = user_data_start_move_window; | ||
769 | 266 | pending_menu->move_timeout_id = g_timeout_add (150, gwd_move_window_instead, pending_menu); | ||
770 | 267 | } | ||
771 | 268 | |||
772 | 269 | #ifdef META_HAS_LOCAL_MENUS | ||
773 | 270 | void | ||
774 | 271 | local_menu_entry_activated_request (GDBusProxy *proxy, | ||
775 | 272 | gchar *sender_name, | ||
776 | 273 | gchar *signal_name, | ||
777 | 274 | GVariant *parameters, | ||
778 | 275 | gpointer user_data) | ||
779 | 276 | { | ||
780 | 277 | if (g_strcmp0 (signal_name, "EntryActivateRequest") == 0) | ||
781 | 278 | { | ||
782 | 279 | gchar *activated_entry_id; | ||
783 | 280 | gchar *local_menu_entry_id; | ||
784 | 281 | local_menu_entry_activated_request_funcs *funcs = (local_menu_entry_activated_request_funcs *) user_data; | ||
785 | 282 | |||
786 | 283 | g_variant_get (parameters, "(s)", &activated_entry_id, NULL); | ||
787 | 284 | |||
788 | 285 | GError *error = NULL; | ||
789 | 286 | GVariant *params = g_variant_new ("(s)", "libappmenu.so", NULL); | ||
790 | 287 | GVariant *args = g_dbus_proxy_call_sync (proxy, "SyncOne", params, 0, 500, NULL, &error); | ||
791 | 288 | |||
792 | 289 | g_assert_no_error (error); | ||
793 | 290 | local_menu_entry_id = gwd_get_entry_id_from_sync_variant (args); | ||
794 | 291 | |||
795 | 292 | if (g_strcmp0 (activated_entry_id, local_menu_entry_id) == 0) | ||
796 | 293 | { | ||
797 | 294 | WnckScreen *screen = wnck_screen_get_for_root (gdk_x11_get_default_root_xwindow ()); | ||
798 | 295 | int dx, dy, top_height; | ||
799 | 296 | Window xid; | ||
800 | 297 | |||
801 | 298 | if (screen) | ||
802 | 299 | { | ||
803 | 300 | Box *rect = (*funcs->active_window_local_menu_rect_callback) ((gpointer) screen, &dx, &dy, &top_height, &xid); | ||
804 | 301 | |||
805 | 302 | if (rect) | ||
806 | 303 | { | ||
807 | 304 | int x = rect->x1; | ||
808 | 305 | int y = top_height; | ||
809 | 306 | |||
810 | 307 | gwd_show_local_menu (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), | ||
811 | 308 | xid, x + dx, y + dy, x, y, 0, 0, | ||
812 | 309 | funcs->show_window_menu_hidden_callback, GINT_TO_POINTER (xid)); | ||
813 | 310 | } | ||
814 | 311 | } | ||
815 | 312 | } | ||
816 | 313 | } | ||
817 | 314 | } | ||
818 | 315 | #endif | ||
819 | 316 | |||
820 | 317 | gboolean | ||
821 | 318 | gwd_show_local_menu (Display *xdisplay, | ||
822 | 319 | Window frame_xwindow, | ||
823 | 320 | int x, | ||
824 | 321 | int y, | ||
825 | 322 | int x_win, | ||
826 | 323 | int y_win, | ||
827 | 324 | int button, | ||
828 | 325 | guint32 timestamp, | ||
829 | 326 | show_window_menu_hidden_cb cb, | ||
830 | 327 | gpointer user_data_show_window_menu) | ||
831 | 328 | { | ||
832 | 329 | if (pending_menu) | ||
833 | 330 | { | ||
834 | 331 | g_source_remove (pending_menu->move_timeout_id); | ||
835 | 332 | g_free (pending_menu->user_data); | ||
836 | 333 | g_free (pending_menu); | ||
837 | 334 | pending_menu = NULL; | ||
838 | 335 | } | ||
839 | 336 | |||
840 | 337 | #ifdef META_HAS_LOCAL_MENUS | ||
841 | 338 | |||
842 | 339 | |||
843 | 340 | XUngrabPointer (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), CurrentTime); | ||
844 | 341 | XUngrabKeyboard (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), CurrentTime); | ||
845 | 342 | XSync (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), FALSE); | ||
846 | 343 | |||
847 | 344 | GDBusProxy *proxy = global_lim_listener; | ||
848 | 345 | |||
849 | 346 | if (proxy) | ||
850 | 347 | { | ||
851 | 348 | GVariant *message = g_variant_new ("(uiiu)", frame_xwindow, x, y, time); | ||
852 | 349 | GError *error = NULL; | ||
853 | 350 | g_dbus_proxy_call_sync (proxy, "ShowAppMenu", message, 0, 500, NULL, &error); | ||
854 | 351 | if (error) | ||
855 | 352 | { | ||
856 | 353 | g_print ("error calling ShowAppMenu: %s\n", error->message); | ||
857 | 354 | return FALSE; | ||
858 | 355 | } | ||
859 | 356 | |||
860 | 357 | show_local_menu_data *data = g_new0 (show_local_menu_data, 1); | ||
861 | 358 | |||
862 | 359 | if (active_menu) | ||
863 | 360 | g_free (active_menu); | ||
864 | 361 | |||
865 | 362 | active_menu = g_new0 (active_local_menu, 1); | ||
866 | 363 | |||
867 | 364 | data->cb = cb; | ||
868 | 365 | data->user_data = user_data_show_window_menu; | ||
869 | 366 | data->rect = &active_menu->rect; | ||
870 | 367 | data->dx = x - x_win; | ||
871 | 368 | data->dy = y - y_win; | ||
872 | 369 | data->local_menu_entry_id = NULL; | ||
873 | 370 | |||
874 | 371 | g_signal_connect (proxy, "g-signal", G_CALLBACK (on_local_menu_activated), data); | ||
875 | 372 | |||
876 | 373 | return TRUE; | ||
877 | 374 | } | ||
878 | 375 | #endif | ||
879 | 376 | return FALSE; | ||
880 | 377 | } | ||
881 | 378 | |||
882 | 379 | void | ||
883 | 380 | force_local_menus_on (Window win, | ||
884 | 381 | MetaButtonLayout *button_layout) | ||
885 | 382 | { | ||
886 | 383 | #ifdef META_HAS_LOCAL_MENUS | ||
887 | 384 | if (gwd_window_should_have_local_menu (win)) | ||
888 | 385 | { | ||
889 | 386 | if (button_layout->left_buttons[0] != META_BUTTON_FUNCTION_LAST) | ||
890 | 387 | { | ||
891 | 388 | unsigned int i = 0; | ||
892 | 389 | for (; i < MAX_BUTTONS_PER_CORNER; i++) | ||
893 | 390 | { | ||
894 | 391 | if (button_layout->left_buttons[i] == META_BUTTON_FUNCTION_WINDOW_MENU) | ||
895 | 392 | break; | ||
896 | 393 | else if (button_layout->left_buttons[i] == META_BUTTON_FUNCTION_LAST) | ||
897 | 394 | { | ||
898 | 395 | if ((i + 1) < MAX_BUTTONS_PER_CORNER) | ||
899 | 396 | { | ||
900 | 397 | button_layout->left_buttons[i + 1] = META_BUTTON_FUNCTION_LAST; | ||
901 | 398 | button_layout->left_buttons[i] = META_BUTTON_FUNCTION_WINDOW_MENU; | ||
902 | 399 | break; | ||
903 | 400 | } | ||
904 | 401 | } | ||
905 | 402 | } | ||
906 | 403 | } | ||
907 | 404 | if (button_layout->right_buttons[0] != META_BUTTON_FUNCTION_LAST) | ||
908 | 405 | { | ||
909 | 406 | unsigned int i = 0; | ||
910 | 407 | for (; i < MAX_BUTTONS_PER_CORNER; i++) | ||
911 | 408 | { | ||
912 | 409 | if (button_layout->right_buttons[i] == META_BUTTON_FUNCTION_WINDOW_MENU) | ||
913 | 410 | break; | ||
914 | 411 | else if (button_layout->right_buttons[i] == META_BUTTON_FUNCTION_LAST) | ||
915 | 412 | { | ||
916 | 413 | if ((i + 1) < MAX_BUTTONS_PER_CORNER) | ||
917 | 414 | { | ||
918 | 415 | button_layout->right_buttons[i + 1] = META_BUTTON_FUNCTION_LAST; | ||
919 | 416 | button_layout->right_buttons[i] = META_BUTTON_FUNCTION_WINDOW_MENU; | ||
920 | 417 | break; | ||
921 | 418 | } | ||
922 | 419 | } | ||
923 | 420 | } | ||
924 | 421 | } | ||
925 | 422 | } | ||
926 | 423 | #endif | ||
927 | 424 | } | ||
928 | 425 | |||
929 | 426 | void | ||
930 | 427 | local_menu_cache_notify_window_destroyed (Window xid) | ||
931 | 428 | { | ||
932 | 429 | g_hash_table_remove (get_windows_with_menus_table (), GINT_TO_POINTER (xid)); | ||
933 | 430 | } | ||
934 | 431 | |||
935 | 432 | void | ||
936 | 433 | local_menu_cache_reload_xwindow (Display *dpy, Window xid) | ||
937 | 434 | { | ||
938 | 435 | read_xprop_for_window (dpy, xid); | ||
939 | 436 | } | ||
940 | 437 | |||
941 | 438 | |||
942 | 0 | 439 | ||
943 | === added file 'gtk/window-decorator/local-menus/src/local-menus.h' | |||
944 | --- gtk/window-decorator/local-menus/src/local-menus.h 1970-01-01 00:00:00 +0000 | |||
945 | +++ gtk/window-decorator/local-menus/src/local-menus.h 2012-03-02 02:56:17 +0000 | |||
946 | @@ -0,0 +1,125 @@ | |||
947 | 1 | /* | ||
948 | 2 | * Copyright © 2006 Novell, Inc. | ||
949 | 3 | * | ||
950 | 4 | * This library is free software; you can redistribute it and/or | ||
951 | 5 | * modify it under the terms of the GNU Lesser General Public | ||
952 | 6 | * License as published by the Free Software Foundation; either | ||
953 | 7 | * version 2 of the License, or (at your option) any later version. | ||
954 | 8 | * | ||
955 | 9 | * This library is distributed in the hope that it will be useful, | ||
956 | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
957 | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
958 | 12 | * Lesser General Public License for more details. | ||
959 | 13 | * | ||
960 | 14 | * You should have received a copy of the GNU Lesser General Public | ||
961 | 15 | * License along with this library; if not, write to the | ||
962 | 16 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
963 | 17 | * Boston, MA 02111-1307, USA. | ||
964 | 18 | * | ||
965 | 19 | * Author: David Reveman <davidr@novell.com> | ||
966 | 20 | * | ||
967 | 21 | * 2D Mode: Copyright © 2010 Sam Spilsbury <smspillaz@gmail.com> | ||
968 | 22 | * Frames Management: Copright © 2011 Canonical Ltd. | ||
969 | 23 | * Authored By: Sam Spilsbury <sam.spilsbury@canonical.com> | ||
970 | 24 | */ | ||
971 | 25 | |||
972 | 26 | #ifdef __cplusplus | ||
973 | 27 | extern "C" | ||
974 | 28 | { | ||
975 | 29 | #endif | ||
976 | 30 | |||
977 | 31 | #include <glib.h> | ||
978 | 32 | #include <gio/gio.h> | ||
979 | 33 | #ifndef WNCK_I_KNOW_THIS_IS_UNSTABLE | ||
980 | 34 | #define WNCK_I_KNOW_THIS_IS_UNSTABLE | ||
981 | 35 | #endif | ||
982 | 36 | #include <libwnck/libwnck.h> | ||
983 | 37 | #include <libwnck/window-action-menu.h> | ||
984 | 38 | #include <metacity-private/theme.h> | ||
985 | 39 | #include <X11/Xregion.h> | ||
986 | 40 | |||
987 | 41 | |||
988 | 42 | typedef void (*show_window_menu_hidden_cb) (gpointer); | ||
989 | 43 | typedef void (*start_move_window_cb) (gpointer); | ||
990 | 44 | typedef Box * (*get_active_window_local_menu_rect_cb) (gpointer, int *, int *, int *, Window *); | ||
991 | 45 | |||
992 | 46 | typedef struct _pending_local_menu | ||
993 | 47 | { | ||
994 | 48 | gint move_timeout_id; | ||
995 | 49 | gpointer user_data; | ||
996 | 50 | start_move_window_cb cb; | ||
997 | 51 | gint x_root; | ||
998 | 52 | gint y_root; | ||
999 | 53 | } pending_local_menu; | ||
1000 | 54 | |||
1001 | 55 | typedef struct _active_local_menu | ||
1002 | 56 | { | ||
1003 | 57 | GdkRectangle rect; | ||
1004 | 58 | } active_local_menu; | ||
1005 | 59 | |||
1006 | 60 | extern active_local_menu *active_menu; | ||
1007 | 61 | extern GDBusProxy *global_lim_listener; | ||
1008 | 62 | |||
1009 | 63 | typedef struct _show_local_menu_data | ||
1010 | 64 | { | ||
1011 | 65 | show_window_menu_hidden_cb cb; | ||
1012 | 66 | gpointer user_data; | ||
1013 | 67 | GdkRectangle *rect; | ||
1014 | 68 | gint dx; | ||
1015 | 69 | gint dy; | ||
1016 | 70 | gchar *local_menu_entry_id; | ||
1017 | 71 | } show_local_menu_data; | ||
1018 | 72 | |||
1019 | 73 | typedef struct _local_menu_entry_activated_request_funcs | ||
1020 | 74 | { | ||
1021 | 75 | get_active_window_local_menu_rect_cb active_window_local_menu_rect_callback; | ||
1022 | 76 | show_window_menu_hidden_cb show_window_menu_hidden_callback; | ||
1023 | 77 | } local_menu_entry_activated_request_funcs; | ||
1024 | 78 | |||
1025 | 79 | gboolean | ||
1026 | 80 | gwd_window_should_have_local_menu (Window win); | ||
1027 | 81 | |||
1028 | 82 | void | ||
1029 | 83 | force_local_menus_on (Window win, | ||
1030 | 84 | MetaButtonLayout *layout); | ||
1031 | 85 | |||
1032 | 86 | /* Button Down */ | ||
1033 | 87 | void | ||
1034 | 88 | gwd_prepare_show_local_menu (start_move_window_cb start_move_window, | ||
1035 | 89 | gpointer user_data_start_move_window, gint x_root, gint y_root); | ||
1036 | 90 | |||
1037 | 91 | /* Button Up */ | ||
1038 | 92 | gboolean | ||
1039 | 93 | gwd_show_local_menu (Display *xdisplay, | ||
1040 | 94 | Window frame_xwindow, | ||
1041 | 95 | int x, | ||
1042 | 96 | int y, | ||
1043 | 97 | int x_win, | ||
1044 | 98 | int y_win, | ||
1045 | 99 | int button, | ||
1046 | 100 | guint32 timestamp, | ||
1047 | 101 | show_window_menu_hidden_cb cb, | ||
1048 | 102 | gpointer user_data_show_window_menu); | ||
1049 | 103 | |||
1050 | 104 | void | ||
1051 | 105 | local_menu_cache_notify_window_destroyed (Window xid); | ||
1052 | 106 | |||
1053 | 107 | void | ||
1054 | 108 | local_menu_cache_reload_xwindow (Display *xdisplay, Window xid); | ||
1055 | 109 | |||
1056 | 110 | gboolean | ||
1057 | 111 | local_menu_allowed_on_window (Display *dpy, Window xid); | ||
1058 | 112 | |||
1059 | 113 | void | ||
1060 | 114 | local_menu_entry_activated_request (GDBusProxy *proxy, | ||
1061 | 115 | gchar *sender_name, | ||
1062 | 116 | gchar *signal_name, | ||
1063 | 117 | GVariant *parameters, | ||
1064 | 118 | gpointer user_data); | ||
1065 | 119 | |||
1066 | 120 | void | ||
1067 | 121 | local_menu_process_motion (gint x_root, gint y_root); | ||
1068 | 122 | |||
1069 | 123 | #ifdef __cplusplus | ||
1070 | 124 | } | ||
1071 | 125 | #endif | ||
1072 | 0 | 126 | ||
1073 | === added directory 'gtk/window-decorator/local-menus/tests' | |||
1074 | === added file 'gtk/window-decorator/local-menus/tests/CMakeLists.txt' | |||
1075 | --- gtk/window-decorator/local-menus/tests/CMakeLists.txt 1970-01-01 00:00:00 +0000 | |||
1076 | +++ gtk/window-decorator/local-menus/tests/CMakeLists.txt 2012-03-02 02:56:17 +0000 | |||
1077 | @@ -0,0 +1,3 @@ | |||
1078 | 1 | include_directories (${CMAKE_CURRENT_SOURCE_DIR}) | ||
1079 | 2 | add_subdirectory (check_local_menu_on_off) | ||
1080 | 3 | add_subdirectory (force_local_menu_on) | ||
1081 | 0 | 4 | ||
1082 | === added directory 'gtk/window-decorator/local-menus/tests/check_local_menu_on_off' | |||
1083 | === added file 'gtk/window-decorator/local-menus/tests/check_local_menu_on_off/CMakeLists.txt' | |||
1084 | --- gtk/window-decorator/local-menus/tests/check_local_menu_on_off/CMakeLists.txt 1970-01-01 00:00:00 +0000 | |||
1085 | +++ gtk/window-decorator/local-menus/tests/check_local_menu_on_off/CMakeLists.txt 2012-03-02 02:56:17 +0000 | |||
1086 | @@ -0,0 +1,21 @@ | |||
1087 | 1 | include_directories (${CMAKE_CURRENT_SOURCE_DIR} | ||
1088 | 2 | ${compiz_SOURCE_DIR}/gtk/window-decorator/local-menus/tests | ||
1089 | 3 | ${compiz_SOURCE_DIR}/gtk/window-decorator | ||
1090 | 4 | ${compiz_SOURCE_DIR}/gtk/window-decorator/local-menus/src) | ||
1091 | 5 | |||
1092 | 6 | add_executable( | ||
1093 | 7 | gtk_window_decorator_check_local_menu_on_off_test | ||
1094 | 8 | |||
1095 | 9 | ${CMAKE_CURRENT_SOURCE_DIR}/test-local-menu-on-off.cpp | ||
1096 | 10 | ) | ||
1097 | 11 | |||
1098 | 12 | target_link_libraries( | ||
1099 | 13 | gtk_window_decorator_check_local_menu_on_off_test | ||
1100 | 14 | |||
1101 | 15 | gtk_window_decorator_local_menus | ||
1102 | 16 | |||
1103 | 17 | ${GTEST_BOTH_LIBRARIES} | ||
1104 | 18 | ${CMAKE_THREAD_LIBS_INIT} # Link in pthread. | ||
1105 | 19 | ) | ||
1106 | 20 | |||
1107 | 21 | add_test (gtk_window_decorator_local_menus_on_off gtk_window_decorator_check_local_menu_on_off_test) | ||
1108 | 0 | 22 | ||
1109 | === added directory 'gtk/window-decorator/local-menus/tests/check_local_menu_on_off/check_local_menu_on_off' | |||
1110 | === added directory 'gtk/window-decorator/local-menus/tests/check_local_menu_on_off/check_local_menu_on_off/CMakeFiles' | |||
1111 | === added file 'gtk/window-decorator/local-menus/tests/check_local_menu_on_off/test-local-menu-on-off.cpp' | |||
1112 | --- gtk/window-decorator/local-menus/tests/check_local_menu_on_off/test-local-menu-on-off.cpp 1970-01-01 00:00:00 +0000 | |||
1113 | +++ gtk/window-decorator/local-menus/tests/check_local_menu_on_off/test-local-menu-on-off.cpp 2012-03-02 02:56:17 +0000 | |||
1114 | @@ -0,0 +1,47 @@ | |||
1115 | 1 | #include "test-local-menu.h" | ||
1116 | 2 | #include <string.h> | ||
1117 | 3 | #include <gdk/gdkx.h> | ||
1118 | 4 | |||
1119 | 5 | #define GLOBAL 0 | ||
1120 | 6 | #define LOCAL 1 | ||
1121 | 7 | #ifdef META_HAS_LOCAL_MENUS | ||
1122 | 8 | |||
1123 | 9 | TEST_F (GtkWindowDecoratorTestLocalMenu, TestOnNoProp) | ||
1124 | 10 | { | ||
1125 | 11 | g_settings_set_enum (getSettings (), "menu-mode", LOCAL); | ||
1126 | 12 | gboolean result = gwd_window_should_have_local_menu (getWindow ()); | ||
1127 | 13 | |||
1128 | 14 | EXPECT_FALSE (result); | ||
1129 | 15 | } | ||
1130 | 16 | |||
1131 | 17 | TEST_F (GtkWindowDecoratorTestLocalMenu, TestOnWithProp) | ||
1132 | 18 | { | ||
1133 | 19 | g_settings_set_enum (getSettings (), "menu-mode", LOCAL); | ||
1134 | 20 | |||
1135 | 21 | Window xid = getWindow (); | ||
1136 | 22 | Atom ubuntu_appmenu_unique_name = XInternAtom (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), "_UBUNTU_APPMENU_UNIQUE_NAME", FALSE); | ||
1137 | 23 | Atom utf8_string = XInternAtom (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), "UTF8_STRING", FALSE); | ||
1138 | 24 | const char data[] = ":abcd1234"; | ||
1139 | 25 | |||
1140 | 26 | XChangeProperty (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), xid, ubuntu_appmenu_unique_name, utf8_string, 8, PropModeReplace, (const unsigned char *) data, strlen (data)); | ||
1141 | 27 | |||
1142 | 28 | gdk_display_sync (gdk_display_get_default ()); | ||
1143 | 29 | |||
1144 | 30 | gboolean result = gwd_window_should_have_local_menu (getWindow ()); | ||
1145 | 31 | |||
1146 | 32 | EXPECT_TRUE (result); | ||
1147 | 33 | } | ||
1148 | 34 | |||
1149 | 35 | TEST_F (GtkWindowDecoratorTestLocalMenu, TestOff) | ||
1150 | 36 | { | ||
1151 | 37 | g_settings_set_enum (getSettings (), "menu-mode", GLOBAL); | ||
1152 | 38 | gboolean result = gwd_window_should_have_local_menu (getWindow ()); | ||
1153 | 39 | |||
1154 | 40 | EXPECT_FALSE (result); | ||
1155 | 41 | } | ||
1156 | 42 | #else | ||
1157 | 43 | TEST_F (GtkWindowDecoratorTestLocalMenu, NoMenus) | ||
1158 | 44 | { | ||
1159 | 45 | ASSERT_TRUE (true) << "Local menus tests not enabled because META_HAS_LOCAL_MENUS is off"; | ||
1160 | 46 | } | ||
1161 | 47 | #endif | ||
1162 | 0 | 48 | ||
1163 | === added directory 'gtk/window-decorator/local-menus/tests/force_local_menu_on' | |||
1164 | === added file 'gtk/window-decorator/local-menus/tests/force_local_menu_on/CMakeLists.txt' | |||
1165 | --- gtk/window-decorator/local-menus/tests/force_local_menu_on/CMakeLists.txt 1970-01-01 00:00:00 +0000 | |||
1166 | +++ gtk/window-decorator/local-menus/tests/force_local_menu_on/CMakeLists.txt 2012-03-02 02:56:17 +0000 | |||
1167 | @@ -0,0 +1,21 @@ | |||
1168 | 1 | include_directories (${CMAKE_CURRENT_SOURCE_DIR} | ||
1169 | 2 | ${compiz_SOURCE_DIR}/gtk/window-decorator/local-menus/tests | ||
1170 | 3 | ${compiz_SOURCE_DIR}/gtk/window-decorator | ||
1171 | 4 | ${compiz_SOURCE_DIR}/gtk/window-decorator/local-menus/src) | ||
1172 | 5 | |||
1173 | 6 | add_executable( | ||
1174 | 7 | gtk_window_decorator_force_local_menu_on_test | ||
1175 | 8 | |||
1176 | 9 | ${CMAKE_CURRENT_SOURCE_DIR}/test-force-local-menu-on.cpp | ||
1177 | 10 | ) | ||
1178 | 11 | |||
1179 | 12 | target_link_libraries( | ||
1180 | 13 | gtk_window_decorator_force_local_menu_on_test | ||
1181 | 14 | |||
1182 | 15 | gtk_window_decorator_local_menus | ||
1183 | 16 | |||
1184 | 17 | ${GTEST_BOTH_LIBRARIES} | ||
1185 | 18 | ${CMAKE_THREAD_LIBS_INIT} # Link in pthread. | ||
1186 | 19 | ) | ||
1187 | 20 | |||
1188 | 21 | add_test (gtk_window_decorator_force_local_menu_on gtk_window_decorator_force_local_menu_on_test) | ||
1189 | 0 | 22 | ||
1190 | === added file 'gtk/window-decorator/local-menus/tests/force_local_menu_on/test-force-local-menu-on.cpp' | |||
1191 | --- gtk/window-decorator/local-menus/tests/force_local_menu_on/test-force-local-menu-on.cpp 1970-01-01 00:00:00 +0000 | |||
1192 | +++ gtk/window-decorator/local-menus/tests/force_local_menu_on/test-force-local-menu-on.cpp 2012-03-02 02:56:17 +0000 | |||
1193 | @@ -0,0 +1,89 @@ | |||
1194 | 1 | #include "test-local-menu.h" | ||
1195 | 2 | #include <cstring> | ||
1196 | 3 | #include <gdk/gdkx.h> | ||
1197 | 4 | |||
1198 | 5 | #define GLOBAL 0 | ||
1199 | 6 | #define LOCAL 1 | ||
1200 | 7 | #ifdef META_HAS_LOCAL_MENUS | ||
1201 | 8 | |||
1202 | 9 | namespace | ||
1203 | 10 | { | ||
1204 | 11 | void initializeMetaButtonLayout (MetaButtonLayout *layout) | ||
1205 | 12 | { | ||
1206 | 13 | memset (layout, 0, sizeof (MetaButtonLayout)); | ||
1207 | 14 | |||
1208 | 15 | unsigned int i; | ||
1209 | 16 | |||
1210 | 17 | for (i = 0; i < MAX_BUTTONS_PER_CORNER; i++) | ||
1211 | 18 | { | ||
1212 | 19 | layout->right_buttons[i] = META_BUTTON_FUNCTION_LAST; | ||
1213 | 20 | layout->left_buttons[i] = META_BUTTON_FUNCTION_LAST; | ||
1214 | 21 | } | ||
1215 | 22 | } | ||
1216 | 23 | } | ||
1217 | 24 | |||
1218 | 25 | class GtkWindowDecoratorTestLocalMenuLayout : | ||
1219 | 26 | public GtkWindowDecoratorTestLocalMenu | ||
1220 | 27 | { | ||
1221 | 28 | public: | ||
1222 | 29 | |||
1223 | 30 | MetaButtonLayout * getLayout () { return &mLayout; } | ||
1224 | 31 | |||
1225 | 32 | virtual void SetUp () | ||
1226 | 33 | { | ||
1227 | 34 | GtkWindowDecoratorTestLocalMenu::SetUp (); | ||
1228 | 35 | ::initializeMetaButtonLayout (&mLayout); | ||
1229 | 36 | g_settings_set_enum (getSettings (), "menu-mode", LOCAL); | ||
1230 | 37 | |||
1231 | 38 | Window xid = getWindow (); | ||
1232 | 39 | Atom ubuntu_appmenu_unique_name = XInternAtom (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), "_UBUNTU_APPMENU_UNIQUE_NAME", FALSE); | ||
1233 | 40 | Atom utf8_string = XInternAtom (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), "UTF8_STRING", FALSE); | ||
1234 | 41 | const char data[] = ":abcd1234"; | ||
1235 | 42 | |||
1236 | 43 | XChangeProperty (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), xid, ubuntu_appmenu_unique_name, utf8_string, 8, PropModeReplace, (const unsigned char *) data, strlen (data)); | ||
1237 | 44 | |||
1238 | 45 | gdk_display_sync (gdk_display_get_default ()); | ||
1239 | 46 | |||
1240 | 47 | ASSERT_TRUE (gwd_window_should_have_local_menu (getWindow ())); | ||
1241 | 48 | } | ||
1242 | 49 | |||
1243 | 50 | private: | ||
1244 | 51 | |||
1245 | 52 | MetaButtonLayout mLayout; | ||
1246 | 53 | }; | ||
1247 | 54 | |||
1248 | 55 | TEST_F (GtkWindowDecoratorTestLocalMenuLayout, TestForceNoButtonsSet) | ||
1249 | 56 | { | ||
1250 | 57 | force_local_menus_on (getWindow (), getLayout ()); | ||
1251 | 58 | |||
1252 | 59 | EXPECT_EQ (getLayout ()->right_buttons[0], META_BUTTON_FUNCTION_LAST); | ||
1253 | 60 | EXPECT_EQ (getLayout ()->left_buttons[0], META_BUTTON_FUNCTION_LAST); | ||
1254 | 61 | } | ||
1255 | 62 | |||
1256 | 63 | TEST_F (GtkWindowDecoratorTestLocalMenuLayout, TestForceNoCloseButtonSet) | ||
1257 | 64 | { | ||
1258 | 65 | getLayout ()->right_buttons[0] = META_BUTTON_FUNCTION_CLOSE; | ||
1259 | 66 | |||
1260 | 67 | force_local_menus_on (getWindow (), getLayout ()); | ||
1261 | 68 | |||
1262 | 69 | EXPECT_EQ (getLayout ()->right_buttons[1], META_BUTTON_FUNCTION_WINDOW_MENU); | ||
1263 | 70 | EXPECT_EQ (getLayout ()->left_buttons[0], META_BUTTON_FUNCTION_LAST); | ||
1264 | 71 | } | ||
1265 | 72 | |||
1266 | 73 | TEST_F (GtkWindowDecoratorTestLocalMenuLayout, TestForceNoCloseMinimizeMaximizeButtonSet) | ||
1267 | 74 | { | ||
1268 | 75 | getLayout ()->left_buttons[0] = META_BUTTON_FUNCTION_CLOSE; | ||
1269 | 76 | getLayout ()->left_buttons[1] = META_BUTTON_FUNCTION_CLOSE; | ||
1270 | 77 | getLayout ()->left_buttons[2] = META_BUTTON_FUNCTION_CLOSE; | ||
1271 | 78 | |||
1272 | 79 | force_local_menus_on (getWindow (), getLayout ()); | ||
1273 | 80 | |||
1274 | 81 | EXPECT_EQ (getLayout ()->right_buttons[0], META_BUTTON_FUNCTION_LAST); | ||
1275 | 82 | EXPECT_EQ (getLayout ()->left_buttons[3], META_BUTTON_FUNCTION_WINDOW_MENU); | ||
1276 | 83 | } | ||
1277 | 84 | #else | ||
1278 | 85 | TEST_F (GtkWindowDecoratorTestLocalMenu, NoMenus) | ||
1279 | 86 | { | ||
1280 | 87 | ASSERT_TRUE (true) << "Local menus tests not enabled because META_HAS_LOCAL_MENUS is off"; | ||
1281 | 88 | } | ||
1282 | 89 | #endif | ||
1283 | 0 | 90 | ||
1284 | === added directory 'gtk/window-decorator/local-menus/tests/show_hide_menu' | |||
1285 | === added file 'gtk/window-decorator/local-menus/tests/test-local-menu.h' | |||
1286 | --- gtk/window-decorator/local-menus/tests/test-local-menu.h 1970-01-01 00:00:00 +0000 | |||
1287 | +++ gtk/window-decorator/local-menus/tests/test-local-menu.h 2012-03-02 02:56:17 +0000 | |||
1288 | @@ -0,0 +1,106 @@ | |||
1289 | 1 | #include <gtest/gtest.h> | ||
1290 | 2 | #include <gmock/gmock.h> | ||
1291 | 3 | #include "local-menus.h" | ||
1292 | 4 | #include <X11/Xlib.h> | ||
1293 | 5 | #include <gio/gio.h> | ||
1294 | 6 | #include <sys/poll.h> | ||
1295 | 7 | #include <X11/Xatom.h> | ||
1296 | 8 | |||
1297 | 9 | class GtkWindowDecoratorTestLocalMenu : | ||
1298 | 10 | public ::testing::Test | ||
1299 | 11 | { | ||
1300 | 12 | public: | ||
1301 | 13 | |||
1302 | 14 | #ifdef META_HAS_LOCAL_MENUS | ||
1303 | 15 | Window getWindow () { return mXWindow; } | ||
1304 | 16 | GSettings * getSettings () { return mSettings; } | ||
1305 | 17 | virtual void SetUp () | ||
1306 | 18 | { | ||
1307 | 19 | gtk_init (NULL, NULL); | ||
1308 | 20 | |||
1309 | 21 | mXDisplay = XOpenDisplay (NULL); | ||
1310 | 22 | |||
1311 | 23 | XSelectInput (mXDisplay, DefaultRootWindow (mXDisplay), PropertyChangeMask); | ||
1312 | 24 | |||
1313 | 25 | mXWindow = XCreateSimpleWindow (mXDisplay, DefaultRootWindow (mXDisplay), 0, 0, 100, 100, 0, 0, 0); | ||
1314 | 26 | |||
1315 | 27 | Atom net_client_list = XInternAtom (mXDisplay, "_NET_CLIENT_LIST", FALSE); | ||
1316 | 28 | |||
1317 | 29 | XMapRaised (mXDisplay, mXWindow); | ||
1318 | 30 | |||
1319 | 31 | XFlush (mXDisplay); | ||
1320 | 32 | |||
1321 | 33 | /* Wait for _NET_CLIENT_LIST to be updated with this window */ | ||
1322 | 34 | while (1) | ||
1323 | 35 | { | ||
1324 | 36 | struct pollfd pfd; | ||
1325 | 37 | |||
1326 | 38 | pfd.events = POLLIN; | ||
1327 | 39 | pfd.revents = 0; | ||
1328 | 40 | pfd.fd = ConnectionNumber (mXDisplay); | ||
1329 | 41 | |||
1330 | 42 | XEvent event; | ||
1331 | 43 | |||
1332 | 44 | poll (&pfd, 1, -1); | ||
1333 | 45 | |||
1334 | 46 | XNextEvent (mXDisplay, &event); | ||
1335 | 47 | |||
1336 | 48 | gboolean foundWindow = FALSE; | ||
1337 | 49 | |||
1338 | 50 | switch (event.type) | ||
1339 | 51 | { | ||
1340 | 52 | case PropertyNotify: | ||
1341 | 53 | { | ||
1342 | 54 | if (event.xproperty.atom == net_client_list) | ||
1343 | 55 | { | ||
1344 | 56 | Atom type; | ||
1345 | 57 | int fmt; | ||
1346 | 58 | unsigned long nitems, nleft; | ||
1347 | 59 | unsigned char *prop; | ||
1348 | 60 | |||
1349 | 61 | XGetWindowProperty (mXDisplay, event.xproperty.window, net_client_list, | ||
1350 | 62 | 0L, 128L, FALSE, XA_WINDOW, &type, &fmt, &nitems, &nleft, &prop); | ||
1351 | 63 | |||
1352 | 64 | if (fmt == 32 && type == XA_WINDOW && nitems && !nleft) | ||
1353 | 65 | { | ||
1354 | 66 | Window *windows = (Window *) prop; | ||
1355 | 67 | |||
1356 | 68 | while (nitems--) | ||
1357 | 69 | { | ||
1358 | 70 | if (*(windows++) == mXWindow) | ||
1359 | 71 | foundWindow = TRUE; | ||
1360 | 72 | } | ||
1361 | 73 | } | ||
1362 | 74 | |||
1363 | 75 | XFree (prop); | ||
1364 | 76 | } | ||
1365 | 77 | |||
1366 | 78 | break; | ||
1367 | 79 | } | ||
1368 | 80 | default: | ||
1369 | 81 | break; | ||
1370 | 82 | } | ||
1371 | 83 | |||
1372 | 84 | if (foundWindow) | ||
1373 | 85 | break; | ||
1374 | 86 | } | ||
1375 | 87 | |||
1376 | 88 | g_setenv("GSETTINGS_BACKEND", "memory", true); | ||
1377 | 89 | mSettings = g_settings_new ("com.canonical.indicator.appmenu"); | ||
1378 | 90 | } | ||
1379 | 91 | |||
1380 | 92 | virtual void TearDown () | ||
1381 | 93 | { | ||
1382 | 94 | XDestroyWindow (mXDisplay, mXWindow); | ||
1383 | 95 | XCloseDisplay (mXDisplay); | ||
1384 | 96 | |||
1385 | 97 | g_object_unref (mSettings); | ||
1386 | 98 | } | ||
1387 | 99 | #endif | ||
1388 | 100 | |||
1389 | 101 | private: | ||
1390 | 102 | |||
1391 | 103 | Window mXWindow; | ||
1392 | 104 | Display *mXDisplay; | ||
1393 | 105 | GSettings *mSettings; | ||
1394 | 106 | }; | ||
1395 | 0 | 107 | ||
1396 | === modified file 'gtk/window-decorator/metacity.c' | |||
1397 | --- gtk/window-decorator/metacity.c 2012-02-16 06:51:37 +0000 | |||
1398 | +++ gtk/window-decorator/metacity.c 2012-03-02 02:56:17 +0000 | |||
1399 | @@ -24,6 +24,7 @@ | |||
1400 | 24 | */ | 24 | */ |
1401 | 25 | 25 | ||
1402 | 26 | #include "gtk-window-decorator.h" | 26 | #include "gtk-window-decorator.h" |
1403 | 27 | #include "local-menus.h" | ||
1404 | 27 | 28 | ||
1405 | 28 | #ifdef USE_METACITY | 29 | #ifdef USE_METACITY |
1406 | 29 | 30 | ||
1407 | @@ -488,6 +489,8 @@ | |||
1408 | 488 | button_layout->right_buttons[i] = META_BUTTON_FUNCTION_LAST; | 489 | button_layout->right_buttons[i] = META_BUTTON_FUNCTION_LAST; |
1409 | 489 | } | 490 | } |
1410 | 490 | 491 | ||
1411 | 492 | force_local_menus_on (d->win ? wnck_window_get_xid (d->win) : 0, button_layout); | ||
1412 | 493 | |||
1413 | 491 | *flags = 0; | 494 | *flags = 0; |
1414 | 492 | 495 | ||
1415 | 493 | if (d->actions & WNCK_WINDOW_ACTION_CLOSE) | 496 | if (d->actions & WNCK_WINDOW_ACTION_CLOSE) |
1416 | @@ -538,6 +541,12 @@ | |||
1417 | 538 | *flags |= (MetaFrameFlags ) META_FRAME_ABOVE; | 541 | *flags |= (MetaFrameFlags ) META_FRAME_ABOVE; |
1418 | 539 | #endif | 542 | #endif |
1419 | 540 | 543 | ||
1420 | 544 | #ifdef META_HAS_LOCAL_MENUS | ||
1421 | 545 | if (d->win && | ||
1422 | 546 | local_menu_allowed_on_window (gdk_x11_display_get_xdisplay (gdk_display_get_default ()), wnck_window_get_xid (d->win))) | ||
1423 | 547 | *flags |= (MetaFrameFlags ) META_FRAME_ALLOWS_WINDOW_MENU; | ||
1424 | 548 | #endif | ||
1425 | 549 | |||
1426 | 541 | meta_theme_get_frame_borders (theme, | 550 | meta_theme_get_frame_borders (theme, |
1427 | 542 | frame_type, | 551 | frame_type, |
1428 | 543 | d->frame->text_height, | 552 | d->frame->text_height, |
1429 | @@ -558,6 +567,15 @@ | |||
1430 | 558 | else | 567 | else |
1431 | 559 | clip->height = d->border_layout.left.y2 - d->border_layout.left.y1; | 568 | clip->height = d->border_layout.left.y2 - d->border_layout.left.y1; |
1432 | 560 | 569 | ||
1433 | 570 | memset (fgeom, 0, sizeof (MetaFrameGeometry)); | ||
1434 | 571 | |||
1435 | 572 | #ifdef META_HAS_LOCAL_MENUS | ||
1436 | 573 | |||
1437 | 574 | if (d->layout) | ||
1438 | 575 | fgeom->text_layout = g_object_ref (d->layout); | ||
1439 | 576 | |||
1440 | 577 | #endif | ||
1441 | 578 | |||
1442 | 561 | meta_theme_calc_geometry (theme, | 579 | meta_theme_calc_geometry (theme, |
1443 | 562 | frame_type, | 580 | frame_type, |
1444 | 563 | d->frame->text_height, | 581 | d->frame->text_height, |
1445 | @@ -567,6 +585,15 @@ | |||
1446 | 567 | button_layout, | 585 | button_layout, |
1447 | 568 | fgeom); | 586 | fgeom); |
1448 | 569 | 587 | ||
1449 | 588 | #ifdef META_HAS_LOCAL_MENUS | ||
1450 | 589 | |||
1451 | 590 | if (d->layout) | ||
1452 | 591 | g_object_unref (fgeom->text_layout); | ||
1453 | 592 | |||
1454 | 593 | fgeom->text_layout = NULL; | ||
1455 | 594 | |||
1456 | 595 | #endif | ||
1457 | 596 | |||
1458 | 570 | clip->width += left_width + right_width; | 597 | clip->width += left_width + right_width; |
1459 | 571 | clip->height += top_height + bottom_height; | 598 | clip->height += top_height + bottom_height; |
1460 | 572 | } | 599 | } |
1461 | @@ -601,6 +628,11 @@ | |||
1462 | 601 | GdkColor bg_color; | 628 | GdkColor bg_color; |
1463 | 602 | double bg_alpha; | 629 | double bg_alpha; |
1464 | 603 | 630 | ||
1465 | 631 | memset (&button_layout, 0, sizeof (MetaButtonLayout)); | ||
1466 | 632 | |||
1467 | 633 | for (i = 0; i < MAX_BUTTONS_PER_CORNER; i++) | ||
1468 | 634 | button_layout.left_buttons[i] = button_layout.right_buttons[i] = META_BUTTON_FUNCTION_LAST; | ||
1469 | 635 | |||
1470 | 604 | if (!d->pixmap || !d->picture) | 636 | if (!d->pixmap || !d->picture) |
1471 | 605 | return; | 637 | return; |
1472 | 606 | 638 | ||
1473 | @@ -675,6 +707,9 @@ | |||
1474 | 675 | 707 | ||
1475 | 676 | size = MAX (fgeom.top_height, fgeom.bottom_height); | 708 | size = MAX (fgeom.top_height, fgeom.bottom_height); |
1476 | 677 | 709 | ||
1477 | 710 | if (active_menu) | ||
1478 | 711 | g_object_set_data (G_OBJECT (style_window), "local_menu_rect", &active_menu->rect); | ||
1479 | 712 | |||
1480 | 678 | if (rect.width && size) | 713 | if (rect.width && size) |
1481 | 679 | { | 714 | { |
1482 | 680 | XRenderPictFormat *format; | 715 | XRenderPictFormat *format; |
1483 | @@ -899,6 +934,9 @@ | |||
1484 | 899 | XRenderFreePicture (xdisplay, src); | 934 | XRenderFreePicture (xdisplay, src); |
1485 | 900 | } | 935 | } |
1486 | 901 | 936 | ||
1487 | 937 | if (active_menu) | ||
1488 | 938 | g_object_set_data (G_OBJECT (style_window), "local_menu_rect", NULL); | ||
1489 | 939 | |||
1490 | 902 | copy_to_front_buffer (d); | 940 | copy_to_front_buffer (d); |
1491 | 903 | 941 | ||
1492 | 904 | if (d->frame_window) | 942 | if (d->frame_window) |
1493 | @@ -1078,6 +1116,15 @@ | |||
1494 | 1078 | break; | 1116 | break; |
1495 | 1079 | #endif | 1117 | #endif |
1496 | 1080 | 1118 | ||
1497 | 1119 | #ifdef META_HAS_LOCAL_MENUS | ||
1498 | 1120 | case BUTTON_WINDOW_MENU: | ||
1499 | 1121 | if (!meta_button_present (&button_layout, META_BUTTON_FUNCTION_WINDOW_MENU)) | ||
1500 | 1122 | return FALSE; | ||
1501 | 1123 | |||
1502 | 1124 | space = &fgeom.window_menu_rect; | ||
1503 | 1125 | break; | ||
1504 | 1126 | #endif | ||
1505 | 1127 | |||
1506 | 1081 | default: | 1128 | default: |
1507 | 1082 | return FALSE; | 1129 | return FALSE; |
1508 | 1083 | } | 1130 | } |
1509 | @@ -1266,6 +1313,8 @@ | |||
1510 | 1266 | MetaTheme *theme; | 1313 | MetaTheme *theme; |
1511 | 1267 | GdkRectangle clip; | 1314 | GdkRectangle clip; |
1512 | 1268 | 1315 | ||
1513 | 1316 | memset (&fgeom, 0, sizeof (MetaFrameGeometry)); | ||
1514 | 1317 | |||
1515 | 1269 | theme = meta_theme_get_current (); | 1318 | theme = meta_theme_get_current (); |
1516 | 1270 | 1319 | ||
1517 | 1271 | meta_get_decoration_geometry (d, theme, &flags, &fgeom, &button_layout, | 1320 | meta_get_decoration_geometry (d, theme, &flags, &fgeom, &button_layout, |
1518 | @@ -1490,6 +1539,11 @@ | |||
1519 | 1490 | return META_BUTTON_FUNCTION_UNSTICK; | 1539 | return META_BUTTON_FUNCTION_UNSTICK; |
1520 | 1491 | #endif | 1540 | #endif |
1521 | 1492 | 1541 | ||
1522 | 1542 | #ifdef META_HAS_LOCAL_MENUS | ||
1523 | 1543 | else if (strcmp (str, "window_menu") == 0) | ||
1524 | 1544 | return META_BUTTON_FUNCTION_WINDOW_MENU; | ||
1525 | 1545 | #endif | ||
1526 | 1546 | |||
1527 | 1493 | else | 1547 | else |
1528 | 1494 | return META_BUTTON_FUNCTION_LAST; | 1548 | return META_BUTTON_FUNCTION_LAST; |
1529 | 1495 | } | 1549 | } |
1530 | 1496 | 1550 | ||
1531 | === modified file 'gtk/window-decorator/wnck.c' | |||
1532 | --- gtk/window-decorator/wnck.c 2012-02-10 10:23:27 +0000 | |||
1533 | +++ gtk/window-decorator/wnck.c 2012-03-02 02:56:17 +0000 | |||
1534 | @@ -24,6 +24,7 @@ | |||
1535 | 24 | */ | 24 | */ |
1536 | 25 | 25 | ||
1537 | 26 | #include "gtk-window-decorator.h" | 26 | #include "gtk-window-decorator.h" |
1538 | 27 | #include "local-menus.h" | ||
1539 | 27 | 28 | ||
1540 | 28 | const gchar * | 29 | const gchar * |
1541 | 29 | get_frame_type (WnckWindow *win) | 30 | get_frame_type (WnckWindow *win) |
1542 | @@ -375,6 +376,19 @@ | |||
1543 | 375 | if (cursor[i][j].cursor) | 376 | if (cursor[i][j].cursor) |
1544 | 376 | XDefineCursor (xdisplay, d->event_windows[i][j].window, | 377 | XDefineCursor (xdisplay, d->event_windows[i][j].window, |
1545 | 377 | cursor[i][j].cursor); | 378 | cursor[i][j].cursor); |
1546 | 379 | |||
1547 | 380 | XGrabButton (xdisplay, | ||
1548 | 381 | Button1Mask, | ||
1549 | 382 | AnyModifier, | ||
1550 | 383 | d->event_windows[i][j].window, | ||
1551 | 384 | FALSE, | ||
1552 | 385 | ButtonPressMask | | ||
1553 | 386 | ButtonReleaseMask | | ||
1554 | 387 | PointerMotionMask, | ||
1555 | 388 | GrabModeAsync, | ||
1556 | 389 | GrabModeAsync, | ||
1557 | 390 | None, | ||
1558 | 391 | None); | ||
1559 | 378 | } | 392 | } |
1560 | 379 | } | 393 | } |
1561 | 380 | 394 | ||
1562 | @@ -389,6 +403,20 @@ | |||
1563 | 389 | CopyFromParent, CopyFromParent, CopyFromParent, | 403 | CopyFromParent, CopyFromParent, CopyFromParent, |
1564 | 390 | CWOverrideRedirect | CWEventMask, &attr); | 404 | CWOverrideRedirect | CWEventMask, &attr); |
1565 | 391 | 405 | ||
1566 | 406 | |||
1567 | 407 | XGrabButton (xdisplay, | ||
1568 | 408 | Button1Mask, | ||
1569 | 409 | AnyModifier, | ||
1570 | 410 | d->button_windows[i].window, | ||
1571 | 411 | FALSE, | ||
1572 | 412 | ButtonPressMask | | ||
1573 | 413 | ButtonReleaseMask | | ||
1574 | 414 | PointerMotionMask, | ||
1575 | 415 | GrabModeAsync, | ||
1576 | 416 | GrabModeAsync, | ||
1577 | 417 | None, | ||
1578 | 418 | None); | ||
1579 | 419 | |||
1580 | 392 | d->button_states[i] = 0; | 420 | d->button_states[i] = 0; |
1581 | 393 | } | 421 | } |
1582 | 394 | } | 422 | } |
1583 | @@ -738,7 +766,8 @@ | |||
1584 | 738 | stick_button_event, | 766 | stick_button_event, |
1585 | 739 | unshade_button_event, | 767 | unshade_button_event, |
1586 | 740 | unabove_button_event, | 768 | unabove_button_event, |
1588 | 741 | unstick_button_event | 769 | unstick_button_event, |
1589 | 770 | window_menu_button_event | ||
1590 | 742 | }; | 771 | }; |
1591 | 743 | 772 | ||
1592 | 744 | d = calloc (1, sizeof (decor_t)); | 773 | d = calloc (1, sizeof (decor_t)); |
1593 | @@ -784,6 +813,8 @@ | |||
1594 | 784 | window_closed (WnckScreen *screen, | 813 | window_closed (WnckScreen *screen, |
1595 | 785 | WnckWindow *win) | 814 | WnckWindow *win) |
1596 | 786 | { | 815 | { |
1597 | 816 | local_menu_cache_notify_window_destroyed (wnck_window_get_xid (win)); | ||
1598 | 817 | |||
1599 | 787 | decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); | 818 | decor_t *d = g_object_get_data (G_OBJECT (win), "decor"); |
1600 | 788 | 819 | ||
1601 | 789 | if (d) | 820 | 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?