Merge lp:~robertcarr/ido/offscreen-scale into lp:ido/0.3
- offscreen-scale
- Merge into trunk
Status: | Superseded |
---|---|
Proposed branch: | lp:~robertcarr/ido/offscreen-scale |
Merge into: | lp:ido/0.3 |
Diff against target: |
716 lines (+584/-14) 4 files modified
src/Makefile.am (+5/-2) src/idooffscreenproxy.c (+497/-0) src/idooffscreenproxy.h (+62/-0) src/idoscalemenuitem.c (+20/-12) |
To merge this branch: | bzr merge lp:~robertcarr/ido/offscreen-scale |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ted Gould (community) | Needs Information | ||
Review via email: mp+73872@code.launchpad.net |
This proposal has been superseded by a proposal from 2011-09-06.
Commit message
Description of the change
Implement an IdoOffscreenProxy object to render a widget which is actually displayed offscreen. This works around the issue with GtkRange/Scale needing grabs and fixes LP:#804009. Might also be useful for making calendar, etc work...
Robert Carr (robertcarr) wrote : | # |
Robert Carr (robertcarr) wrote : | # |
The GTK merge was fail. I think this is correct: https:/
Ted Gould (ted) wrote : | # |
I'm not going to be able to set up the GTK stuff and get that working in a reasonable fashion, but it seems just from reading the code that there might be an issue with the style contexts. It seems that as the proxy goes down it needs to pass the style context information on through to the off screen widget so that it gets rendered correctly (active, panel, etc.) all come from the widget path which is simplified. Also, I'm unsure about getting a background color with a singular state instead of grabbing the state from the menu item itself.
I guess the question is: does the theme draw correctly with this patch?
Andrea Cimitan (cimi) wrote : | # |
Some notes:
1) When you create your style context, be always sure to add both the right widget path and the correct classes, if you only need GtkMenu that's fine.
2) Please use the Gtk+ constants for the classes, GTK_STYLE_
3) Use always Gtk+ rendering functions, if possible. Instead of getting the background color and painting with cairo, use gtk_render_
- 85. By Robert Carr
-
Use gtk_render_
background - 86. By Robert Carr
-
Use GtkBorder in drawing background
- 87. By Robert Carr
-
Don't leak style context...
- 88. By Robert Carr
-
Ok I take it back we don't care about border. use custom css to set border-width and radius
Unmerged revisions
Preview Diff
1 | === modified file 'src/Makefile.am' |
2 | --- src/Makefile.am 2011-06-01 19:24:28 +0000 |
3 | +++ src/Makefile.am 2011-09-02 18:57:28 +0000 |
4 | @@ -18,9 +18,10 @@ |
5 | idoentrymenuitem.h \ |
6 | idomessagedialog.h \ |
7 | idorange.h \ |
8 | + idooffscreenproxy.h \ |
9 | idoscalemenuitem.h \ |
10 | idotimeline.h \ |
11 | - libido.h |
12 | + libido.h |
13 | |
14 | EXTRA_DIST = \ |
15 | ido.list \ |
16 | @@ -62,7 +63,8 @@ |
17 | idomessagedialog.c \ |
18 | idorange.c \ |
19 | idoscalemenuitem.c \ |
20 | - idotimeline.c |
21 | + idotimeline.c \ |
22 | + idooffscreenproxy.c |
23 | libido3_0_1_la_SOURCES = $(libido_0_1_la_SOURCES) |
24 | |
25 | libidoincludedir=$(includedir)/libido$(VER)-0.1/libido |
26 | @@ -74,6 +76,7 @@ |
27 | idorange.h \ |
28 | idoscalemenuitem.h \ |
29 | idotimeline.h \ |
30 | + idooffscreenproxy.h \ |
31 | libido.h |
32 | |
33 | libido_0_1_la_LIBADD = $(GTK_LIBS) |
34 | |
35 | === added file 'src/idooffscreenproxy.c' |
36 | --- src/idooffscreenproxy.c 1970-01-01 00:00:00 +0000 |
37 | +++ src/idooffscreenproxy.c 2011-09-02 18:57:28 +0000 |
38 | @@ -0,0 +1,497 @@ |
39 | +/* |
40 | + * Copyright 2011 Canonical, Ltd. |
41 | + * |
42 | + * This program is free software: you can redistribute it and/or modify it |
43 | + * under the terms of either or both of the following licenses: |
44 | + * |
45 | + * 1) the GNU Lesser General Public License version 3, as published by the |
46 | + * Free Software Foundation; and/or |
47 | + * 2) the GNU Lesser General Public License version 2.1, as published by |
48 | + * the Free Software Foundation. |
49 | + * |
50 | + * This program is distributed in the hope that it will be useful, but |
51 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
52 | + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR |
53 | + * PURPOSE. See the applicable version of the GNU Lesser General Public |
54 | + * License for more details. |
55 | + * |
56 | + * You should have received a copy of both the GNU Lesser General Public |
57 | + * License version 3 and version 2.1 along with this program. If not, see |
58 | + * <http://www.gnu.org/licenses/> |
59 | + * |
60 | + * Authors: |
61 | + * Robert Carr <racarr@canonical.com> |
62 | + */ |
63 | + |
64 | +#include <gtk/gtk.h> |
65 | +#include "idooffscreenproxy.h" |
66 | + |
67 | +struct _IdoOffscreenProxyPrivate |
68 | +{ |
69 | + GtkWidget *child; |
70 | + |
71 | + GdkWindow *offscreen_window; |
72 | +}; |
73 | + |
74 | +static void ido_offscreen_proxy_realize (GtkWidget *widget); |
75 | +static void ido_offscreen_proxy_unrealize (GtkWidget *widget); |
76 | +static void ido_offscreen_proxy_get_preferred_width (GtkWidget *widget, |
77 | + gint *minimum, |
78 | + gint *natural); |
79 | +static void ido_offscreen_proxy_get_preferred_height (GtkWidget *widget, |
80 | + gint *minimum, |
81 | + gint *natural); |
82 | + |
83 | +static void ido_offscreen_proxy_size_allocate (GtkWidget *widget, |
84 | + GtkAllocation *allocation); |
85 | +static gboolean ido_offscreen_proxy_damage (GtkWidget *widget, |
86 | + GdkEventExpose *event); |
87 | +static gboolean ido_offscreen_proxy_draw (GtkWidget *widget, |
88 | + cairo_t *cr); |
89 | +static void ido_offscreen_proxy_add (GtkContainer *container, |
90 | + GtkWidget *child); |
91 | +static void ido_offscreen_proxy_remove (GtkContainer *container, |
92 | + GtkWidget *widget); |
93 | +static void ido_offscreen_proxy_forall (GtkContainer *container, |
94 | + gboolean include_internals, |
95 | + GtkCallback callback, |
96 | + gpointer callback_data); |
97 | +static GType ido_offscreen_proxy_child_type (GtkContainer *container); |
98 | + |
99 | +static cairo_surface_t * ido_offscreen_proxy_create_alpha_image_surface (GdkWindow *offscreen, gint width, gint height); |
100 | + |
101 | + |
102 | + |
103 | +G_DEFINE_TYPE (IdoOffscreenProxy, ido_offscreen_proxy, GTK_TYPE_CONTAINER); |
104 | + |
105 | +#define IDO_OFFSCREEN_PROXY_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), IDO_TYPE_OFFSCREEN_PROXY, IdoOffscreenProxyPrivate)) |
106 | + |
107 | +static void |
108 | +ido_offscreen_proxy_class_init (IdoOffscreenProxyClass *klass) |
109 | +{ |
110 | + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); |
111 | + GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass); |
112 | + |
113 | + g_type_class_add_private (klass, sizeof (IdoOffscreenProxyPrivate)); |
114 | + |
115 | + widget_class->realize = ido_offscreen_proxy_realize; |
116 | + widget_class->unrealize = ido_offscreen_proxy_unrealize; |
117 | + widget_class->get_preferred_width = ido_offscreen_proxy_get_preferred_width; |
118 | + widget_class->get_preferred_height = ido_offscreen_proxy_get_preferred_height; |
119 | + widget_class->size_allocate = ido_offscreen_proxy_size_allocate; |
120 | + widget_class->draw = ido_offscreen_proxy_draw; |
121 | + |
122 | + g_signal_override_class_closure (g_signal_lookup ("damage-event", GTK_TYPE_WIDGET), |
123 | + IDO_TYPE_OFFSCREEN_PROXY, |
124 | + g_cclosure_new (G_CALLBACK (ido_offscreen_proxy_damage), |
125 | + NULL, NULL)); |
126 | + |
127 | + container_class->add = ido_offscreen_proxy_add; |
128 | + container_class->remove = ido_offscreen_proxy_remove; |
129 | + container_class->forall = ido_offscreen_proxy_forall; |
130 | + container_class->child_type = ido_offscreen_proxy_child_type; |
131 | + |
132 | +} |
133 | + |
134 | +static void |
135 | +ido_offscreen_proxy_init (IdoOffscreenProxy *proxy) |
136 | +{ |
137 | + proxy->priv = IDO_OFFSCREEN_PROXY_GET_PRIVATE (proxy); |
138 | + |
139 | + gtk_widget_set_has_window (GTK_WIDGET (proxy), TRUE); |
140 | + |
141 | + gtk_widget_set_events (GTK_WIDGET(proxy), gtk_widget_get_events (GTK_WIDGET(proxy)) |
142 | + | GDK_EXPOSURE_MASK |
143 | + | GDK_POINTER_MOTION_MASK |
144 | + | GDK_BUTTON_PRESS_MASK |
145 | + | GDK_BUTTON_RELEASE_MASK |
146 | + | GDK_SCROLL_MASK |
147 | + | GDK_ENTER_NOTIFY_MASK |
148 | + | GDK_LEAVE_NOTIFY_MASK); |
149 | +} |
150 | + |
151 | +GtkWidget * |
152 | +ido_offscreen_proxy_new (void) |
153 | +{ |
154 | + return g_object_new (IDO_TYPE_OFFSCREEN_PROXY, NULL); |
155 | +} |
156 | + |
157 | +static GdkWindow * |
158 | +pick_offscreen_child (GdkWindow *offscreen_window, |
159 | + double widget_x, double widget_y, |
160 | + IdoOffscreenProxy *proxy) |
161 | +{ |
162 | + GtkAllocation child_area; |
163 | + |
164 | + if (proxy->priv->child && gtk_widget_get_visible (proxy->priv->child)) |
165 | + { |
166 | + gtk_widget_get_allocation (proxy->priv->child, &child_area); |
167 | + |
168 | + // if (widget_x >= 0 && widget_x < child_area.width && |
169 | + // widget_y >= 0 && widget_y < child_area.height) |
170 | + //return proxy->priv->offscreen_window; |
171 | + exit(0); |
172 | + return proxy->priv->offscreen_window; |
173 | + } |
174 | + |
175 | + return NULL; |
176 | +} |
177 | + |
178 | +static void |
179 | +offscreen_to_parent (GdkWindow *offscreen_window, |
180 | + double offscreen_x, |
181 | + double offscreen_y, |
182 | + double *parent_x, |
183 | + double *parent_y, |
184 | + gpointer user_data) |
185 | +{ |
186 | + *parent_x = offscreen_x; |
187 | + *parent_y = offscreen_y; |
188 | +} |
189 | + |
190 | +static void |
191 | +offscreen_from_parent (GdkWindow *window, |
192 | + double parent_x, |
193 | + double parent_y, |
194 | + double *offscreen_x, |
195 | + double *offscreen_y, |
196 | + gpointer user_data) |
197 | +{ |
198 | + *offscreen_x = parent_x; |
199 | + *offscreen_y = parent_y; |
200 | +} |
201 | + |
202 | +static cairo_surface_t * |
203 | +ido_offscreen_proxy_create_alpha_image_surface (GdkWindow *offscreen, gint width, gint height) |
204 | +{ |
205 | + return cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); |
206 | +} |
207 | + |
208 | +static void |
209 | +ido_offscreen_proxy_realize (GtkWidget *widget) |
210 | +{ |
211 | + IdoOffscreenProxy *proxy = IDO_OFFSCREEN_PROXY (widget); |
212 | + GtkAllocation allocation, child_area; |
213 | + GtkStyleContext *context; |
214 | + GdkWindow *window; |
215 | + GdkWindowAttr attributes; |
216 | + gint attributes_mask; |
217 | + // GtkRequisition child_requisition; |
218 | + |
219 | + gtk_widget_set_realized (widget, TRUE); |
220 | + |
221 | + gtk_widget_get_allocation (widget, &allocation); |
222 | + |
223 | + attributes.x = allocation.x; |
224 | + attributes.y = allocation.y; |
225 | + attributes.width = allocation.width; |
226 | + attributes.height = allocation.height; |
227 | + |
228 | + attributes.window_type = GDK_WINDOW_CHILD; |
229 | + attributes.event_mask = gtk_widget_get_events (widget) |
230 | + | GDK_EXPOSURE_MASK |
231 | + | GDK_POINTER_MOTION_MASK |
232 | + | GDK_BUTTON_PRESS_MASK |
233 | + | GDK_BUTTON_RELEASE_MASK |
234 | + | GDK_SCROLL_MASK |
235 | + | GDK_ENTER_NOTIFY_MASK |
236 | + | GDK_LEAVE_NOTIFY_MASK; |
237 | + attributes.visual = gdk_screen_get_rgba_visual (gdk_screen_get_default ());//gtk_widget_get_visual (widget); |
238 | + attributes.wclass = GDK_INPUT_OUTPUT; |
239 | + |
240 | + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL; |
241 | + |
242 | + window = gdk_window_new (gtk_widget_get_parent_window (widget), |
243 | + &attributes, attributes_mask); |
244 | + |
245 | + gtk_widget_set_window (widget, window); |
246 | + gdk_window_set_user_data (window, widget); |
247 | + |
248 | + g_signal_connect (window, "pick-embedded-child", |
249 | + G_CALLBACK (pick_offscreen_child), proxy); |
250 | + |
251 | + attributes.window_type = GDK_WINDOW_OFFSCREEN; |
252 | + attributes.x = attributes.y = 0; |
253 | + |
254 | + if (proxy->priv->child && gtk_widget_get_visible (proxy->priv->child)) |
255 | + { |
256 | + gtk_widget_get_allocation (proxy->priv->child, &child_area); |
257 | + attributes.width = child_area.width; |
258 | + attributes.height = child_area.height; |
259 | + } |
260 | + |
261 | + proxy->priv->offscreen_window = gdk_window_new (gtk_widget_get_root_window (widget), |
262 | + &attributes, attributes_mask); |
263 | + gdk_window_set_user_data (proxy->priv->offscreen_window, widget); |
264 | + |
265 | + if (proxy->priv->child) |
266 | + gtk_widget_set_parent_window (proxy->priv->child, proxy->priv->offscreen_window); |
267 | + |
268 | + gdk_offscreen_window_set_embedder (proxy->priv->offscreen_window, |
269 | + window); |
270 | + |
271 | + g_signal_connect(proxy->priv->offscreen_window, "create-surface", |
272 | + G_CALLBACK (ido_offscreen_proxy_create_alpha_image_surface), |
273 | + proxy); |
274 | + g_signal_connect (proxy->priv->offscreen_window, "to-embedder", |
275 | + G_CALLBACK (offscreen_to_parent), NULL); |
276 | + g_signal_connect (proxy->priv->offscreen_window, "from-embedder", |
277 | + G_CALLBACK (offscreen_from_parent), NULL); |
278 | + |
279 | + context = gtk_widget_get_style_context (widget); |
280 | + gtk_style_context_add_class (context, GTK_STYLE_CLASS_MENUITEM); |
281 | + gtk_style_context_set_background (context, window); |
282 | + gtk_style_context_set_background (context, proxy->priv->offscreen_window); |
283 | + |
284 | + gdk_window_show (proxy->priv->offscreen_window); |
285 | +} |
286 | + |
287 | +static void |
288 | +ido_offscreen_proxy_unrealize (GtkWidget *widget) |
289 | +{ |
290 | + IdoOffscreenProxy *proxy = IDO_OFFSCREEN_PROXY (widget); |
291 | + |
292 | + gdk_window_set_user_data (proxy->priv->offscreen_window, NULL); |
293 | + gdk_window_destroy (proxy->priv->offscreen_window); |
294 | + proxy->priv->offscreen_window = NULL; |
295 | + |
296 | + GTK_WIDGET_CLASS (ido_offscreen_proxy_parent_class)->unrealize (widget); |
297 | +} |
298 | + |
299 | +static GType |
300 | +ido_offscreen_proxy_child_type (GtkContainer *container) |
301 | +{ |
302 | + IdoOffscreenProxy *proxy = IDO_OFFSCREEN_PROXY (container); |
303 | + |
304 | + if (proxy->priv->child) |
305 | + return G_TYPE_NONE; |
306 | + |
307 | + return GTK_TYPE_WIDGET; |
308 | +} |
309 | + |
310 | +static void |
311 | +ido_offscreen_proxy_add (GtkContainer *container, |
312 | + GtkWidget *child) |
313 | +{ |
314 | + IdoOffscreenProxy *proxy = IDO_OFFSCREEN_PROXY (container); |
315 | + |
316 | + if (!proxy->priv->child) |
317 | + { |
318 | + gtk_widget_set_parent_window (child, proxy->priv->offscreen_window); |
319 | + gtk_widget_set_parent (child, GTK_WIDGET (proxy)); |
320 | + proxy->priv->child = child; |
321 | + } |
322 | + else |
323 | + { |
324 | + g_warning ("IdoOffscreenProxy can only have a single child\n"); |
325 | + } |
326 | +} |
327 | + |
328 | +static void |
329 | +ido_offscreen_proxy_remove (GtkContainer *container, |
330 | + GtkWidget *widget) |
331 | +{ |
332 | + IdoOffscreenProxy *proxy = IDO_OFFSCREEN_PROXY (container); |
333 | + gboolean was_visible; |
334 | + |
335 | + was_visible = gtk_widget_get_visible (widget); |
336 | + |
337 | + if (proxy->priv->child == widget) |
338 | + { |
339 | + gtk_widget_unparent (widget); |
340 | + proxy->priv->child = NULL; |
341 | + |
342 | + if (was_visible && gtk_widget_get_visible (GTK_WIDGET (container))) |
343 | + gtk_widget_queue_resize (GTK_WIDGET (container)); |
344 | + } |
345 | +} |
346 | + |
347 | +static void |
348 | +ido_offscreen_proxy_forall (GtkContainer *container, |
349 | + gboolean include_internals, |
350 | + GtkCallback callback, |
351 | + gpointer callback_data) |
352 | +{ |
353 | + IdoOffscreenProxy *proxy = IDO_OFFSCREEN_PROXY (container); |
354 | + |
355 | + g_return_if_fail (callback != NULL); |
356 | + |
357 | + if (proxy->priv->child) |
358 | + (*callback) (proxy->priv->child, callback_data); |
359 | +} |
360 | + |
361 | +static void |
362 | +ido_offscreen_proxy_size_request (GtkWidget *widget, |
363 | + GtkRequisition *requisition) |
364 | +{ |
365 | + IdoOffscreenProxy *proxy = IDO_OFFSCREEN_PROXY (widget); |
366 | + int w, h; |
367 | + |
368 | + w = 0; |
369 | + h = 0; |
370 | + |
371 | + if (proxy->priv->child && gtk_widget_get_visible (proxy->priv->child)) |
372 | + { |
373 | + GtkRequisition child_requisition; |
374 | + |
375 | + gtk_widget_get_preferred_size (proxy->priv->child, |
376 | + &child_requisition, NULL); |
377 | + w = child_requisition.width; |
378 | + h = child_requisition.height; |
379 | + } |
380 | + |
381 | + requisition->width = w; |
382 | + requisition->height = h; |
383 | + |
384 | +} |
385 | + |
386 | +static void |
387 | +ido_offscreen_proxy_get_preferred_width (GtkWidget *widget, |
388 | + gint *minimum, |
389 | + gint *natural) |
390 | +{ |
391 | + GtkRequisition requisition; |
392 | + |
393 | + ido_offscreen_proxy_size_request (widget, &requisition); |
394 | + |
395 | + *minimum = *natural = requisition.width; |
396 | +} |
397 | + |
398 | +static void |
399 | +ido_offscreen_proxy_get_preferred_height (GtkWidget *widget, |
400 | + gint *minimum, |
401 | + gint *natural) |
402 | +{ |
403 | + GtkRequisition requisition; |
404 | + |
405 | + ido_offscreen_proxy_size_request (widget, &requisition); |
406 | + |
407 | + *minimum = *natural = requisition.height; |
408 | + |
409 | +} |
410 | + |
411 | +static void |
412 | +ido_offscreen_proxy_size_allocate (GtkWidget *widget, |
413 | + GtkAllocation *allocation) |
414 | +{ |
415 | + IdoOffscreenProxy *proxy; |
416 | + |
417 | + proxy = IDO_OFFSCREEN_PROXY (widget); |
418 | + |
419 | + gtk_widget_set_allocation (widget, allocation); |
420 | + |
421 | + if (gtk_widget_get_realized (widget)) |
422 | + { |
423 | + gdk_window_move_resize (gtk_widget_get_window (widget), |
424 | + allocation->x, |
425 | + allocation->y, |
426 | + allocation->width, |
427 | + allocation->height); |
428 | + } |
429 | + |
430 | + if (proxy->priv->child && gtk_widget_get_visible (proxy->priv->child)) |
431 | + { |
432 | + GtkRequisition child_requisition; |
433 | + GtkAllocation child_allocation; |
434 | + |
435 | + gtk_widget_get_preferred_size (proxy->priv->child, |
436 | + &child_requisition, NULL); |
437 | + |
438 | + child_allocation.x = child_requisition.width; |
439 | + child_allocation.y = child_requisition.height; |
440 | + child_allocation.width = allocation->width; |
441 | + child_allocation.height = allocation->height; |
442 | + |
443 | + if (gtk_widget_get_realized (widget)) |
444 | + gdk_window_move_resize (proxy->priv->offscreen_window, |
445 | + child_allocation.x, |
446 | + child_allocation.y, |
447 | + child_allocation.width+4, |
448 | + child_allocation.height); |
449 | + |
450 | + child_allocation.x = child_allocation.y = 0; |
451 | + gtk_widget_size_allocate (proxy->priv->child, &child_allocation); |
452 | + } |
453 | +} |
454 | + |
455 | + |
456 | +static gboolean |
457 | +ido_offscreen_proxy_damage (GtkWidget *widget, |
458 | + GdkEventExpose *event) |
459 | +{ |
460 | + gdk_window_invalidate_rect (gtk_widget_get_window (widget), |
461 | + NULL, FALSE); |
462 | + return TRUE; |
463 | +} |
464 | + |
465 | +static void |
466 | +get_background_color (GdkRGBA *color) |
467 | +{ |
468 | + GtkStyleContext *sc; |
469 | + GtkWidgetPath *path; |
470 | + |
471 | + path = gtk_widget_path_new (); |
472 | + gtk_widget_path_append_type (path, GTK_TYPE_MENU); |
473 | + |
474 | + sc = gtk_style_context_new(); |
475 | + |
476 | + gtk_style_context_set_path (sc, path); |
477 | + gtk_style_context_add_class (sc, "menu"); |
478 | + gtk_style_context_get_background_color (sc, GTK_STATE_FLAG_ACTIVE, color); |
479 | + |
480 | + |
481 | + gtk_widget_path_free (path); |
482 | + g_object_unref (sc); |
483 | +} |
484 | + |
485 | +static gboolean |
486 | +ido_offscreen_proxy_draw (GtkWidget *widget, |
487 | + cairo_t *cr) |
488 | +{ |
489 | + IdoOffscreenProxy *proxy = IDO_OFFSCREEN_PROXY (widget); |
490 | + GdkWindow *window; |
491 | + GdkRGBA bg_color; |
492 | + |
493 | + window = gtk_widget_get_window (widget); |
494 | + |
495 | + get_background_color (&bg_color); |
496 | + |
497 | + if (gtk_cairo_should_draw_window (cr, window)) |
498 | + { |
499 | + cairo_surface_t *surface; |
500 | + |
501 | + if (proxy->priv->child && gtk_widget_get_visible (proxy->priv->child)) |
502 | + { |
503 | + surface = gdk_offscreen_window_get_surface (proxy->priv->offscreen_window); |
504 | + |
505 | + cairo_set_source_rgba(cr, bg_color.red, bg_color.green, |
506 | + bg_color.blue, 1); |
507 | + cairo_paint(cr); |
508 | + |
509 | + cairo_set_source_surface (cr, surface, 0, 0); |
510 | + cairo_paint (cr); |
511 | + } |
512 | + } |
513 | + else if (gtk_cairo_should_draw_window (cr, proxy->priv->offscreen_window)) |
514 | + { |
515 | + cairo_save (cr); |
516 | + cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); |
517 | + cairo_paint(cr); |
518 | + cairo_restore (cr); |
519 | + |
520 | + // gtk_render_background (gtk_widget_get_style_context (widget), cr, |
521 | + // 0, 0, |
522 | + // gdk_window_get_width (proxy->priv->offscreen_window), |
523 | + // gdk_window_get_height (proxy->priv->offscreen_window)); |
524 | + |
525 | + |
526 | + |
527 | + |
528 | + if (proxy->priv->child) |
529 | + gtk_container_propagate_draw (GTK_CONTAINER (widget), |
530 | + proxy->priv->child, |
531 | + cr); |
532 | + } |
533 | + |
534 | + return TRUE; |
535 | +} |
536 | |
537 | === added file 'src/idooffscreenproxy.h' |
538 | --- src/idooffscreenproxy.h 1970-01-01 00:00:00 +0000 |
539 | +++ src/idooffscreenproxy.h 2011-09-02 18:57:28 +0000 |
540 | @@ -0,0 +1,62 @@ |
541 | +/* |
542 | + * Copyright 2011 Canonical, Ltd. |
543 | + * |
544 | + * This program is free software: you can redistribute it and/or modify it |
545 | + * under the terms of either or both of the following licenses: |
546 | + * |
547 | + * 1) the GNU Lesser General Public License version 3, as published by the |
548 | + * Free Software Foundation; and/or |
549 | + * 2) the GNU Lesser General Public License version 2.1, as published by |
550 | + * the Free Software Foundation. |
551 | + * |
552 | + * This program is distributed in the hope that it will be useful, but |
553 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
554 | + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR |
555 | + * PURPOSE. See the applicable version of the GNU Lesser General Public |
556 | + * License for more details. |
557 | + * |
558 | + * You should have received a copy of both the GNU Lesser General Public |
559 | + * License version 3 and version 2.1 along with this program. If not, see |
560 | + * <http://www.gnu.org/licenses/> |
561 | + * |
562 | + * Authors: |
563 | + * Robert Carr <racarr@canonical.com> |
564 | + */ |
565 | + |
566 | +#ifndef __IDO_OFFSCREEN_PROXY_H__ |
567 | +#define __IDO_OFFSCREEN_PROXy_H__ |
568 | + |
569 | +#include <gdk/gdk.h> |
570 | +#include <gtk/gtk.h> |
571 | + |
572 | +G_BEGIN_DECLS |
573 | + |
574 | +#define IDO_TYPE_OFFSCREEN_PROXY (ido_offscreen_proxy_get_type ()) |
575 | +#define IDO_OFFSCREEN_PROXY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), IDO_TYPE_OFFSCREEN_PROXY, IdoOffscreenProxy)) |
576 | +#define IDO_OFFSCREEN_PROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), IDO_TYPE_OFFSCREEN_PROXY, IdoOffscreenProxyClass)) |
577 | +#define IDO_IS_OFFSCREEN_PROXY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IDO_TYPE_OFFSCREEN_PROXY)) |
578 | +#define IDO_IS_OFFSCREEN_PROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), IDO_TYPE_OFFSCREEN_PROXY)) |
579 | +#define IDO_OFFSCREEN_PROXY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), IDO_TYPE_OFFSCREEN_PROXY, IdoOffscreenProxyClass)) |
580 | + |
581 | +typedef struct _IdoOffscreenProxy IdoOffscreenProxy; |
582 | +typedef struct _IdoOffscreenProxyClass IdoOffscreenProxyClass; |
583 | +typedef struct _IdoOffscreenProxyPrivate IdoOffscreenProxyPrivate; |
584 | + |
585 | +struct _IdoOffscreenProxyClass |
586 | +{ |
587 | + GtkBinClass parent_class; |
588 | +}; |
589 | + |
590 | +struct _IdoOffscreenProxy |
591 | +{ |
592 | + GtkContainer container; |
593 | + |
594 | + IdoOffscreenProxyPrivate *priv; |
595 | +}; |
596 | + |
597 | +GType ido_offscreen_proxy_get_type (void) G_GNUC_CONST; |
598 | +GtkWidget *ido_offscreen_proxy_new (void); |
599 | + |
600 | +G_END_DECLS |
601 | + |
602 | +#endif |
603 | |
604 | === modified file 'src/idoscalemenuitem.c' |
605 | --- src/idoscalemenuitem.c 2011-06-20 13:34:43 +0000 |
606 | +++ src/idoscalemenuitem.c 2011-09-02 18:57:28 +0000 |
607 | @@ -26,6 +26,7 @@ |
608 | #include <gtk/gtk.h> |
609 | #include "idorange.h" |
610 | #include "idoscalemenuitem.h" |
611 | +#include "idooffscreenproxy.h" |
612 | #include "idotypebuiltins.h" |
613 | |
614 | static void ido_scale_menu_item_set_property (GObject *object, |
615 | @@ -57,6 +58,7 @@ |
616 | |
617 | struct _IdoScaleMenuItemPrivate { |
618 | GtkWidget *scale; |
619 | + GtkWidget *proxy; |
620 | GtkAdjustment *adjustment; |
621 | GtkWidget *primary_image; |
622 | GtkWidget *secondary_image; |
623 | @@ -226,6 +228,12 @@ |
624 | priv->scale = ido_range_new (adj, range_style); |
625 | g_object_ref (priv->scale); |
626 | gtk_scale_set_draw_value (GTK_SCALE (priv->scale), FALSE); |
627 | + |
628 | + gtk_widget_set_can_focus (priv->scale, FALSE); |
629 | + |
630 | + priv->proxy = ido_offscreen_proxy_new (); |
631 | + g_object_ref (priv->proxy); |
632 | + gtk_container_add (GTK_CONTAINER (priv->proxy), priv->scale); |
633 | |
634 | hbox = gtk_hbox_new (FALSE, 0); |
635 | |
636 | @@ -338,23 +346,23 @@ |
637 | switch (old_style) |
638 | { |
639 | case IDO_SCALE_MENU_ITEM_STYLE_NONE: |
640 | - gtk_container_remove (container, priv->scale); |
641 | + gtk_container_remove (container, priv->proxy); |
642 | break; |
643 | |
644 | case IDO_SCALE_MENU_ITEM_STYLE_IMAGE: |
645 | gtk_container_remove (container, priv->primary_image); |
646 | gtk_container_remove (container, priv->secondary_image); |
647 | - gtk_container_remove (container, priv->scale); |
648 | + gtk_container_remove (container, priv->proxy); |
649 | break; |
650 | |
651 | case IDO_SCALE_MENU_ITEM_STYLE_LABEL: |
652 | gtk_container_remove (container, priv->primary_label); |
653 | gtk_container_remove (container, priv->secondary_label); |
654 | - gtk_container_remove (container, priv->scale); |
655 | + gtk_container_remove (container, priv->proxy); |
656 | break; |
657 | |
658 | default: |
659 | - gtk_container_remove (container, priv->scale); |
660 | + gtk_container_remove (container, priv->proxy); |
661 | break; |
662 | } |
663 | } |
664 | @@ -362,23 +370,23 @@ |
665 | switch (style) |
666 | { |
667 | case IDO_SCALE_MENU_ITEM_STYLE_NONE: |
668 | - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->scale, FALSE, FALSE, 0); |
669 | + gtk_box_pack_start (GTK_BOX (priv->hbox), priv->proxy, FALSE, FALSE, 0); |
670 | break; |
671 | |
672 | case IDO_SCALE_MENU_ITEM_STYLE_IMAGE: |
673 | gtk_box_pack_start (GTK_BOX (priv->hbox), priv->primary_image, FALSE, FALSE, 0); |
674 | - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->scale, FALSE, FALSE, 0); |
675 | + gtk_box_pack_start (GTK_BOX (priv->hbox), priv->proxy, FALSE, FALSE, 0); |
676 | gtk_box_pack_start (GTK_BOX (priv->hbox), priv->secondary_image, FALSE, FALSE, 0); |
677 | break; |
678 | |
679 | case IDO_SCALE_MENU_ITEM_STYLE_LABEL: |
680 | gtk_box_pack_start (GTK_BOX (priv->hbox), priv->primary_label, FALSE, FALSE, 0); |
681 | - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->scale, FALSE, FALSE, 0); |
682 | + gtk_box_pack_start (GTK_BOX (priv->hbox), priv->proxy, FALSE, FALSE, 0); |
683 | gtk_box_pack_start (GTK_BOX (priv->hbox), priv->secondary_label, FALSE, FALSE, 0); |
684 | break; |
685 | |
686 | default: |
687 | - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->scale, FALSE, FALSE, 0); |
688 | + gtk_box_pack_start (GTK_BOX (priv->hbox), priv->proxy, FALSE, FALSE, 0); |
689 | break; |
690 | } |
691 | |
692 | @@ -480,12 +488,12 @@ |
693 | translate_event_coordinates (menuitem, event->x_root, &x); |
694 | event->x_root = x; |
695 | |
696 | - ubuntu_gtk_widget_set_has_grab (scale, TRUE); |
697 | + // ubuntu_gtk_widget_set_has_grab (scale, TRUE); |
698 | |
699 | - gtk_widget_event (scale, |
700 | + gtk_widget_event (priv->scale, |
701 | ((GdkEvent *)(void*)(event))); |
702 | |
703 | - ubuntu_gtk_widget_set_has_grab (scale, FALSE); |
704 | + // ubuntu_gtk_widget_set_has_grab (scale, FALSE); |
705 | |
706 | if (!priv->grabbed) |
707 | { |
708 | @@ -493,7 +501,7 @@ |
709 | g_signal_emit (menuitem, signals[SLIDER_GRABBED], 0); |
710 | } |
711 | |
712 | - return TRUE; |
713 | + return FALSE; |
714 | } |
715 | |
716 | static gboolean |
This working depends on: https:/ /code.launchpad .net/~robertcar r/gtk/fix- offscreen- grabs/+ merge/73870