Merge lp:~robertcarr/ido/offscreen-scale into lp:ido/0.3

Proposed by Robert Carr
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
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.

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...

To post a comment you must log in.
Revision history for this message
Robert Carr (robertcarr) wrote :
Revision history for this message
Robert Carr (robertcarr) wrote :
Revision history for this message
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?

review: Needs Information
Revision history for this message
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_CLASS_MENU instead the "menu".
3) Use always Gtk+ rendering functions, if possible. Instead of getting the background color and painting with cairo, use gtk_render_background () with the proper style context created, with the right state flags set in. The theming engine will now be in charge of doing the right rendering, you'll only need to care about writing the right style context. Unity's panel and indicators, for example, give to Gtk+ a cairo context, ask Gtk+ to render, then use this cairo context (now rendered) where they want.

lp:~robertcarr/ido/offscreen-scale updated
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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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

Subscribers

People subscribed via source and target branches