diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 15 | ||||
-rw-r--r-- | src/idooffscreenproxy.c | 515 | ||||
-rw-r--r-- | src/idooffscreenproxy.h | 62 | ||||
-rw-r--r-- | src/idoscalemenuitem.c | 261 | ||||
-rw-r--r-- | src/idoscalemenuitem.h | 10 |
5 files changed, 136 insertions, 727 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 16936d7..b849bf5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -28,13 +28,6 @@ EXTRA_DIST = \ idotypebuiltins.c.template -if USE_GTK3 -sources_h += idooffscreenproxy.h -else -EXTRA_DIST += idooffscreenproxy.h \ - idooffscreenproxy.c -endif - idotypebuiltins.h: stamp-idotypebuiltins.h stamp-idotypebuiltins.h: $(sources_h) @@ -76,10 +69,6 @@ libido_0_1_la_SOURCES = \ idoscalemenuitem.c \ idotimeline.c -if USE_GTK3 -libido_0_1_la_SOURCES += idooffscreenproxy.c -endif - libido3_0_1_la_SOURCES = $(libido_0_1_la_SOURCES) libidoincludedir=$(includedir)/libido$(VER)-0.1/libido @@ -93,10 +82,6 @@ libidoinclude_HEADERS = \ idotimeline.h \ libido.h -if USE_GTK3 -libidoinclude_HEADERS += idooffscreenproxy.h -endif - libido_0_1_la_LIBADD = $(GTK_LIBS) libido_0_1_la_LDFLAGS = \ $(GTK_LT_LDFLAGS) \ diff --git a/src/idooffscreenproxy.c b/src/idooffscreenproxy.c deleted file mode 100644 index e6aea84..0000000 --- a/src/idooffscreenproxy.c +++ /dev/null @@ -1,515 +0,0 @@ -/* - * Copyright 2011 Canonical, Ltd. - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of either or both of the following licenses: - * - * 1) the GNU Lesser General Public License version 3, as published by the - * Free Software Foundation; and/or - * 2) the GNU Lesser General Public License version 2.1, as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the applicable version of the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of both the GNU Lesser General Public - * License version 3 and version 2.1 along with this program. If not, see - * <http://www.gnu.org/licenses/> - * - * Authors: - * Robert Carr <racarr@canonical.com> - */ - -#include <gtk/gtk.h> -#include "idooffscreenproxy.h" - -struct _IdoOffscreenProxyPrivate -{ - GtkWidget *child; - - GdkWindow *offscreen_window; -}; - -static void ido_offscreen_proxy_realize (GtkWidget *widget); -static void ido_offscreen_proxy_unrealize (GtkWidget *widget); -static void ido_offscreen_proxy_get_preferred_width (GtkWidget *widget, - gint *minimum, - gint *natural); -static void ido_offscreen_proxy_get_preferred_height (GtkWidget *widget, - gint *minimum, - gint *natural); - -static void ido_offscreen_proxy_size_allocate (GtkWidget *widget, - GtkAllocation *allocation); -static gboolean ido_offscreen_proxy_damage (GtkWidget *widget, - GdkEventExpose *event); -static gboolean ido_offscreen_proxy_draw (GtkWidget *widget, - cairo_t *cr); -static void ido_offscreen_proxy_add (GtkContainer *container, - GtkWidget *child); -static void ido_offscreen_proxy_remove (GtkContainer *container, - GtkWidget *widget); -static void ido_offscreen_proxy_forall (GtkContainer *container, - gboolean include_internals, - GtkCallback callback, - gpointer callback_data); -static GType ido_offscreen_proxy_child_type (GtkContainer *container); - -static cairo_surface_t * ido_offscreen_proxy_create_alpha_image_surface (GdkWindow *offscreen, gint width, gint height); - - - -G_DEFINE_TYPE (IdoOffscreenProxy, ido_offscreen_proxy, GTK_TYPE_CONTAINER); - -#define IDO_OFFSCREEN_PROXY_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), IDO_TYPE_OFFSCREEN_PROXY, IdoOffscreenProxyPrivate)) - -static void -ido_offscreen_proxy_class_init (IdoOffscreenProxyClass *klass) -{ - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); - GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass); - - g_type_class_add_private (klass, sizeof (IdoOffscreenProxyPrivate)); - - widget_class->realize = ido_offscreen_proxy_realize; - widget_class->unrealize = ido_offscreen_proxy_unrealize; - widget_class->get_preferred_width = ido_offscreen_proxy_get_preferred_width; - widget_class->get_preferred_height = ido_offscreen_proxy_get_preferred_height; - widget_class->size_allocate = ido_offscreen_proxy_size_allocate; - widget_class->draw = ido_offscreen_proxy_draw; - - g_signal_override_class_closure (g_signal_lookup ("damage-event", GTK_TYPE_WIDGET), - IDO_TYPE_OFFSCREEN_PROXY, - g_cclosure_new (G_CALLBACK (ido_offscreen_proxy_damage), - NULL, NULL)); - - container_class->add = ido_offscreen_proxy_add; - container_class->remove = ido_offscreen_proxy_remove; - container_class->forall = ido_offscreen_proxy_forall; - container_class->child_type = ido_offscreen_proxy_child_type; - -} - -static void -ido_offscreen_proxy_init (IdoOffscreenProxy *proxy) -{ - proxy->priv = IDO_OFFSCREEN_PROXY_GET_PRIVATE (proxy); - - gtk_widget_set_has_window (GTK_WIDGET (proxy), TRUE); - - gtk_widget_set_events (GTK_WIDGET(proxy), gtk_widget_get_events (GTK_WIDGET(proxy)) - | GDK_EXPOSURE_MASK - | GDK_POINTER_MOTION_MASK - | GDK_BUTTON_PRESS_MASK - | GDK_BUTTON_RELEASE_MASK - | GDK_SCROLL_MASK - | GDK_ENTER_NOTIFY_MASK - | GDK_LEAVE_NOTIFY_MASK); - - gtk_container_set_border_width (GTK_CONTAINER (proxy), 0); -} - -GtkWidget * -ido_offscreen_proxy_new (void) -{ - return g_object_new (IDO_TYPE_OFFSCREEN_PROXY, NULL); -} - -static GdkWindow * -pick_offscreen_child (GdkWindow *offscreen_window, - double widget_x, double widget_y, - IdoOffscreenProxy *proxy) -{ - GtkAllocation child_area; - - if (proxy->priv->child && gtk_widget_get_visible (proxy->priv->child)) - { - gtk_widget_get_allocation (proxy->priv->child, &child_area); - - // if (widget_x >= 0 && widget_x < child_area.width && - // widget_y >= 0 && widget_y < child_area.height) - //return proxy->priv->offscreen_window; - return proxy->priv->offscreen_window; - } - - return NULL; -} - -static void -offscreen_to_parent (GdkWindow *offscreen_window, - double offscreen_x, - double offscreen_y, - double *parent_x, - double *parent_y, - gpointer user_data) -{ - *parent_x = offscreen_x; - *parent_y = offscreen_y; -} - -static void -offscreen_from_parent (GdkWindow *window, - double parent_x, - double parent_y, - double *offscreen_x, - double *offscreen_y, - gpointer user_data) -{ - *offscreen_x = parent_x; - *offscreen_y = parent_y; -} - -static cairo_surface_t * -ido_offscreen_proxy_create_alpha_image_surface (GdkWindow *offscreen, gint width, gint height) -{ - return cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); -} - -static void -proxy_add_css (GtkStyleContext *sc) -{ - GtkCssProvider *provider = gtk_css_provider_new(); - const gchar *proxy_css = ".menu.ido-offscreen { \nborder-width: 0;\nborder-radius:0; \n}\n"; - - gtk_css_provider_load_from_data (provider, proxy_css, -1, NULL); - - gtk_style_context_add_provider (sc, GTK_STYLE_PROVIDER (provider), - GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); - -} - -static void -ido_offscreen_proxy_realize (GtkWidget *widget) -{ - IdoOffscreenProxy *proxy = IDO_OFFSCREEN_PROXY (widget); - GtkAllocation allocation, child_area; - GtkStyleContext *context; - GdkWindow *window; - GdkWindowAttr attributes; - gint attributes_mask; - // GtkRequisition child_requisition; - - gtk_widget_set_realized (widget, TRUE); - - gtk_widget_get_allocation (widget, &allocation); - - attributes.x = allocation.x; - attributes.y = allocation.y; - attributes.width = allocation.width; - attributes.height = allocation.height; - - attributes.window_type = GDK_WINDOW_CHILD; - attributes.event_mask = gtk_widget_get_events (widget) - | GDK_EXPOSURE_MASK - | GDK_POINTER_MOTION_MASK - | GDK_BUTTON_PRESS_MASK - | GDK_BUTTON_RELEASE_MASK - | GDK_SCROLL_MASK - | GDK_ENTER_NOTIFY_MASK - | GDK_LEAVE_NOTIFY_MASK; - attributes.visual = gdk_screen_get_rgba_visual (gdk_screen_get_default ());//gtk_widget_get_visual (widget); - if (!attributes.visual) - { - attributes.visual = gdk_screen_get_system_visual (gdk_screen_get_default ()); - } - attributes.wclass = GDK_INPUT_OUTPUT; - - attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL; - - window = gdk_window_new (gtk_widget_get_parent_window (widget), - &attributes, attributes_mask); - - gtk_widget_set_window (widget, window); - gdk_window_set_user_data (window, widget); - - g_signal_connect (window, "pick-embedded-child", - G_CALLBACK (pick_offscreen_child), proxy); - - attributes.window_type = GDK_WINDOW_OFFSCREEN; - attributes.x = attributes.y = 0; - - if (proxy->priv->child && gtk_widget_get_visible (proxy->priv->child)) - { - gtk_widget_get_allocation (proxy->priv->child, &child_area); - attributes.width = child_area.width; - attributes.height = child_area.height; - } - - proxy->priv->offscreen_window = gdk_window_new (gtk_widget_get_root_window (widget), - &attributes, attributes_mask); - gdk_window_set_user_data (proxy->priv->offscreen_window, widget); - - if (proxy->priv->child) - gtk_widget_set_parent_window (proxy->priv->child, proxy->priv->offscreen_window); - - gdk_offscreen_window_set_embedder (proxy->priv->offscreen_window, - window); - - g_signal_connect(proxy->priv->offscreen_window, "create-surface", - G_CALLBACK (ido_offscreen_proxy_create_alpha_image_surface), - proxy); - g_signal_connect (proxy->priv->offscreen_window, "to-embedder", - G_CALLBACK (offscreen_to_parent), NULL); - g_signal_connect (proxy->priv->offscreen_window, "from-embedder", - G_CALLBACK (offscreen_from_parent), NULL); - - context = gtk_widget_get_style_context (widget); - gtk_style_context_add_class (context, GTK_STYLE_CLASS_MENUITEM); - gtk_style_context_set_background (context, window); - gtk_style_context_set_background (context, proxy->priv->offscreen_window); - gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP | GTK_JUNCTION_BOTTOM | GTK_JUNCTION_LEFT | GTK_JUNCTION_RIGHT); - - gtk_widget_set_name (widget, "IdoOffscreenProxy"); - gtk_widget_path_iter_set_name (gtk_widget_get_path (widget), -1, "IdoOffscreenProxy"); - - gdk_window_show (proxy->priv->offscreen_window); -} - -static void -ido_offscreen_proxy_unrealize (GtkWidget *widget) -{ - IdoOffscreenProxy *proxy = IDO_OFFSCREEN_PROXY (widget); - - gdk_window_set_user_data (proxy->priv->offscreen_window, NULL); - gdk_window_destroy (proxy->priv->offscreen_window); - proxy->priv->offscreen_window = NULL; - - GTK_WIDGET_CLASS (ido_offscreen_proxy_parent_class)->unrealize (widget); -} - -static GType -ido_offscreen_proxy_child_type (GtkContainer *container) -{ - IdoOffscreenProxy *proxy = IDO_OFFSCREEN_PROXY (container); - - if (proxy->priv->child) - return G_TYPE_NONE; - - return GTK_TYPE_WIDGET; -} - -static void -ido_offscreen_proxy_add (GtkContainer *container, - GtkWidget *child) -{ - IdoOffscreenProxy *proxy = IDO_OFFSCREEN_PROXY (container); - - if (!proxy->priv->child) - { - gtk_widget_set_parent_window (child, proxy->priv->offscreen_window); - gtk_widget_set_parent (child, GTK_WIDGET (proxy)); - proxy->priv->child = child; - } - else - { - g_warning ("IdoOffscreenProxy can only have a single child\n"); - } -} - -static void -ido_offscreen_proxy_remove (GtkContainer *container, - GtkWidget *widget) -{ - IdoOffscreenProxy *proxy = IDO_OFFSCREEN_PROXY (container); - gboolean was_visible; - - was_visible = gtk_widget_get_visible (widget); - - if (proxy->priv->child == widget) - { - gtk_widget_unparent (widget); - proxy->priv->child = NULL; - - if (was_visible && gtk_widget_get_visible (GTK_WIDGET (container))) - gtk_widget_queue_resize (GTK_WIDGET (container)); - } -} - -static void -ido_offscreen_proxy_forall (GtkContainer *container, - gboolean include_internals, - GtkCallback callback, - gpointer callback_data) -{ - IdoOffscreenProxy *proxy = IDO_OFFSCREEN_PROXY (container); - - g_return_if_fail (callback != NULL); - - if (proxy->priv->child) - (*callback) (proxy->priv->child, callback_data); -} - -static void -ido_offscreen_proxy_size_request (GtkWidget *widget, - GtkRequisition *requisition) -{ - IdoOffscreenProxy *proxy = IDO_OFFSCREEN_PROXY (widget); - int w, h; - - w = 0; - h = 0; - - if (proxy->priv->child && gtk_widget_get_visible (proxy->priv->child)) - { - GtkRequisition child_requisition; - - gtk_widget_get_preferred_size (proxy->priv->child, - &child_requisition, NULL); - w = child_requisition.width; - h = child_requisition.height; - } - - requisition->width = w; - requisition->height = h; - -} - -static void -ido_offscreen_proxy_get_preferred_width (GtkWidget *widget, - gint *minimum, - gint *natural) -{ - GtkRequisition requisition; - - ido_offscreen_proxy_size_request (widget, &requisition); - - *minimum = *natural = requisition.width; -} - -static void -ido_offscreen_proxy_get_preferred_height (GtkWidget *widget, - gint *minimum, - gint *natural) -{ - GtkRequisition requisition; - - ido_offscreen_proxy_size_request (widget, &requisition); - - *minimum = *natural = requisition.height; - -} - -static void -ido_offscreen_proxy_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - IdoOffscreenProxy *proxy; - - proxy = IDO_OFFSCREEN_PROXY (widget); - - gtk_widget_set_allocation (widget, allocation); - - if (gtk_widget_get_realized (widget)) - { - gdk_window_move_resize (gtk_widget_get_window (widget), - allocation->x, - allocation->y, - allocation->width, - allocation->height); - } - - if (proxy->priv->child && gtk_widget_get_visible (proxy->priv->child)) - { - GtkRequisition child_requisition; - GtkAllocation child_allocation; - - gtk_widget_get_preferred_size (proxy->priv->child, - &child_requisition, NULL); - - child_allocation.x = child_requisition.width; - child_allocation.y = child_requisition.height; - child_allocation.width = allocation->width; - child_allocation.height = allocation->height; - - if (gtk_widget_get_realized (widget)) - gdk_window_move_resize (proxy->priv->offscreen_window, - child_allocation.x, - child_allocation.y, - child_allocation.width+4, - child_allocation.height); - - child_allocation.x = child_allocation.y = 0; - gtk_widget_size_allocate (proxy->priv->child, &child_allocation); - } -} - - -static gboolean -ido_offscreen_proxy_damage (GtkWidget *widget, - GdkEventExpose *event) -{ - gdk_window_invalidate_rect (gtk_widget_get_window (widget), - NULL, FALSE); - return TRUE; -} - -static GtkStyleContext * -get_menu_style_context () -{ - GtkStyleContext *sc; - GtkWidgetPath *path; - - path = gtk_widget_path_new (); - gtk_widget_path_append_type (path, GTK_TYPE_MENU); - - sc = gtk_style_context_new(); - - proxy_add_css (sc); - - gtk_style_context_set_path (sc, path); - gtk_style_context_add_class (sc, GTK_STYLE_CLASS_MENU); - gtk_style_context_add_class (sc, "ido-offscreen"); - - - - gtk_widget_path_free (path); - - return sc; -} - -static gboolean -ido_offscreen_proxy_draw (GtkWidget *widget, - cairo_t *cr) -{ - IdoOffscreenProxy *proxy = IDO_OFFSCREEN_PROXY (widget); - GdkWindow *window; - GtkStyleContext *sc; - - window = gtk_widget_get_window (widget); - - sc = get_menu_style_context(); - - gtk_style_context_add_class (sc, "menubar"); - - gtk_render_background (sc, cr, - 0, 0, - gdk_window_get_width (window), - gdk_window_get_height (window)); - - g_object_unref (sc); - - if (gtk_cairo_should_draw_window (cr, window)) - { - cairo_surface_t *surface; - - if (proxy->priv->child && gtk_widget_get_visible (proxy->priv->child)) - { - surface = gdk_offscreen_window_get_surface (proxy->priv->offscreen_window); - - cairo_set_source_surface (cr, surface, 0, 0); - cairo_paint (cr); - } - } - else if (gtk_cairo_should_draw_window (cr, proxy->priv->offscreen_window)) - { - if (proxy->priv->child) - gtk_container_propagate_draw (GTK_CONTAINER (widget), - proxy->priv->child, - cr); - } - - return TRUE; -} diff --git a/src/idooffscreenproxy.h b/src/idooffscreenproxy.h deleted file mode 100644 index 3071eab..0000000 --- a/src/idooffscreenproxy.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2011 Canonical, Ltd. - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of either or both of the following licenses: - * - * 1) the GNU Lesser General Public License version 3, as published by the - * Free Software Foundation; and/or - * 2) the GNU Lesser General Public License version 2.1, as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the applicable version of the GNU Lesser General Public - * License for more details. - * - * You should have received a copy of both the GNU Lesser General Public - * License version 3 and version 2.1 along with this program. If not, see - * <http://www.gnu.org/licenses/> - * - * Authors: - * Robert Carr <racarr@canonical.com> - */ - -#ifndef __IDO_OFFSCREEN_PROXY_H__ -#define __IDO_OFFSCREEN_PROXy_H__ - -#include <gdk/gdk.h> -#include <gtk/gtk.h> - -G_BEGIN_DECLS - -#define IDO_TYPE_OFFSCREEN_PROXY (ido_offscreen_proxy_get_type ()) -#define IDO_OFFSCREEN_PROXY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), IDO_TYPE_OFFSCREEN_PROXY, IdoOffscreenProxy)) -#define IDO_OFFSCREEN_PROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), IDO_TYPE_OFFSCREEN_PROXY, IdoOffscreenProxyClass)) -#define IDO_IS_OFFSCREEN_PROXY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IDO_TYPE_OFFSCREEN_PROXY)) -#define IDO_IS_OFFSCREEN_PROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), IDO_TYPE_OFFSCREEN_PROXY)) -#define IDO_OFFSCREEN_PROXY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), IDO_TYPE_OFFSCREEN_PROXY, IdoOffscreenProxyClass)) - -typedef struct _IdoOffscreenProxy IdoOffscreenProxy; -typedef struct _IdoOffscreenProxyClass IdoOffscreenProxyClass; -typedef struct _IdoOffscreenProxyPrivate IdoOffscreenProxyPrivate; - -struct _IdoOffscreenProxyClass -{ - GtkBinClass parent_class; -}; - -struct _IdoOffscreenProxy -{ - GtkContainer container; - - IdoOffscreenProxyPrivate *priv; -}; - -GType ido_offscreen_proxy_get_type (void) G_GNUC_CONST; -GtkWidget *ido_offscreen_proxy_new (void); - -G_END_DECLS - -#endif diff --git a/src/idoscalemenuitem.c b/src/idoscalemenuitem.c index f973f52..4b60b8b 100644 --- a/src/idoscalemenuitem.c +++ b/src/idoscalemenuitem.c @@ -31,10 +31,6 @@ #include "idoscalemenuitem.h" #include "idotypebuiltins.h" -#ifdef USE_GTK3 -#include "idooffscreenproxy.h" -#endif - static void ido_scale_menu_item_set_property (GObject *object, guint prop_id, const GValue *value, @@ -59,16 +55,12 @@ static void ido_scale_menu_item_notify (IdoScaleMenuItem GParamSpec *pspec, gpointer user_data); static void update_packing (IdoScaleMenuItem *self, - IdoScaleMenuItemStyle style, - IdoScaleMenuItemStyle old_style); + IdoScaleMenuItemStyle style); +static void default_primary_clicked_handler (IdoScaleMenuItem *self); +static void default_secondary_clicked_handler (IdoScaleMenuItem *self); struct _IdoScaleMenuItemPrivate { GtkWidget *scale; - -#ifdef USE_GTK3 - GtkWidget *proxy; -#endif - GtkAdjustment *adjustment; GtkWidget *primary_image; GtkWidget *secondary_image; @@ -88,6 +80,8 @@ struct _IdoScaleMenuItemPrivate { enum { SLIDER_GRABBED, SLIDER_RELEASED, + PRIMARY_CLICKED, + SECONDARY_CLICKED, LAST_SIGNAL }; @@ -105,13 +99,6 @@ G_DEFINE_TYPE (IdoScaleMenuItem, ido_scale_menu_item, GTK_TYPE_MENU_ITEM) #define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), IDO_TYPE_SCALE_MENU_ITEM, IdoScaleMenuItemPrivate)) -static void -ido_scale_menu_item_state_changed (GtkWidget *widget, - GtkStateType previous_state) -{ - gtk_widget_set_state (widget, GTK_STATE_NORMAL); -} - static gboolean ido_scale_menu_item_scroll_event (GtkWidget *menuitem, GdkEventScroll *event) @@ -230,6 +217,21 @@ ido_scale_menu_item_toggle_size_allocate (IdoScaleMenuItem *item, priv->toggle_size = toggle_size; } +static gboolean +on_scale_button_press_or_release_event (GtkWidget * widget G_GNUC_UNUSED, + GdkEventButton * event, + gpointer unused G_GNUC_UNUSED) +{ + /* HACK: we want the behaviour you get with the middle button, so we + * mangle the event. clicking with other buttons moves the slider in + * step increments, clicking with the middle button moves the slider to + * the location of the click. */ + if (event->button == 1) + event->button = 2; + + return FALSE; +} + static void ido_scale_menu_item_constructed (GObject *object) { @@ -248,15 +250,12 @@ ido_scale_menu_item_constructed (GObject *object) priv->scale = ido_range_new (adj, range_style); g_object_ref (priv->scale); gtk_scale_set_draw_value (GTK_SCALE (priv->scale), FALSE); - -#ifdef USE_GTK3 - gtk_widget_set_can_focus (priv->scale, FALSE); - - priv->proxy = ido_offscreen_proxy_new (); - g_object_ref (priv->proxy); - gtk_container_add (GTK_CONTAINER (priv->proxy), priv->scale); -#endif + g_signal_connect (G_OBJECT (priv->scale), "button-press-event", + G_CALLBACK (on_scale_button_press_or_release_event), NULL); + g_signal_connect (G_OBJECT (priv->scale), "button-release-event", + G_CALLBACK (on_scale_button_press_or_release_event), NULL); + #ifdef USE_GTK3 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); #else @@ -278,7 +277,7 @@ ido_scale_menu_item_constructed (GObject *object) priv->hbox = hbox; - update_packing (self, priv->style, priv->style); + update_packing (self, priv->style); g_signal_connect (self, "toggle-size-allocate", G_CALLBACK (ido_scale_menu_item_toggle_size_allocate), @@ -289,6 +288,8 @@ ido_scale_menu_item_constructed (GObject *object) NULL); gtk_container_add (GTK_CONTAINER (self), hbox); + + gtk_widget_add_events (GTK_WIDGET(self), GDK_SCROLL_MASK); } static void @@ -297,11 +298,13 @@ ido_scale_menu_item_class_init (IdoScaleMenuItemClass *item_class) GObjectClass *gobject_class = G_OBJECT_CLASS (item_class); GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (item_class); + item_class->primary_clicked = default_primary_clicked_handler; + item_class->secondary_clicked = default_secondary_clicked_handler; + widget_class->button_press_event = ido_scale_menu_item_button_press_event; widget_class->button_release_event = ido_scale_menu_item_button_release_event; widget_class->motion_notify_event = ido_scale_menu_item_motion_notify_event; widget_class->scroll_event = ido_scale_menu_item_scroll_event; - widget_class->state_changed = ido_scale_menu_item_state_changed; widget_class->size_allocate = ido_scale_menu_item_size_allocate; gobject_class->constructed = ido_scale_menu_item_constructed; @@ -358,95 +361,58 @@ ido_scale_menu_item_class_init (IdoScaleMenuItemClass *item_class) g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + signals[PRIMARY_CLICKED] = g_signal_new ("primary-clicked", + G_TYPE_FROM_CLASS (item_class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, + G_STRUCT_OFFSET (IdoScaleMenuItemClass, primary_clicked), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, /* return type */ + 0 /* n_params */); + + signals[SECONDARY_CLICKED] = g_signal_new ("secondary-clicked", + G_TYPE_FROM_CLASS (item_class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, + G_STRUCT_OFFSET (IdoScaleMenuItemClass, secondary_clicked), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, /* return type */ + 0 /* n_params */); + g_type_class_add_private (item_class, sizeof (IdoScaleMenuItemPrivate)); } static void -update_packing (IdoScaleMenuItem *self, IdoScaleMenuItemStyle style, IdoScaleMenuItemStyle old_style) +update_packing (IdoScaleMenuItem *self, IdoScaleMenuItemStyle style) { IdoScaleMenuItemPrivate *priv = GET_PRIVATE (self); + GtkBox * box = GTK_BOX (priv->hbox); GtkContainer *container = GTK_CONTAINER (priv->hbox); - if (style != old_style) - { - switch (old_style) - { - case IDO_SCALE_MENU_ITEM_STYLE_NONE: -#ifdef USE_GTK3 - gtk_container_remove (container, priv->proxy); -#else - gtk_container_remove (container, priv->scale); -#endif - break; - - case IDO_SCALE_MENU_ITEM_STYLE_IMAGE: - gtk_container_remove (container, priv->primary_image); - gtk_container_remove (container, priv->secondary_image); -#ifdef USE_GTK3 - gtk_container_remove (container, priv->proxy); -#else - gtk_container_remove (container, priv->scale); -#endif - break; - - case IDO_SCALE_MENU_ITEM_STYLE_LABEL: - gtk_container_remove (container, priv->primary_label); - gtk_container_remove (container, priv->secondary_label); -#ifdef USE_GTK3 - gtk_container_remove (container, priv->proxy); -#else - gtk_container_remove (container, priv->scale); -#endif - break; - - default: -#ifdef USE_GTK3 - gtk_container_remove (container, priv->proxy); -#else - gtk_container_remove (container, priv->scale); -#endif - break; - } - } + /* remove the old layout */ + GList * children = gtk_container_get_children (container); + GList * l; + for (l=children; l!=NULL; l=l->next) + gtk_container_remove (container, l->data); + g_list_free (children); + /* add the new layout */ switch (style) { - case IDO_SCALE_MENU_ITEM_STYLE_NONE: -#ifdef USE_GTK3 - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->proxy, FALSE, FALSE, 0); -#else - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->scale, FALSE, FALSE, 0); -#endif - break; - case IDO_SCALE_MENU_ITEM_STYLE_IMAGE: - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->primary_image, FALSE, FALSE, 0); - -#ifdef USE_GTK3 - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->proxy, FALSE, FALSE, 0); -#else - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->scale, FALSE, FALSE, 0); -#endif - - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->secondary_image, FALSE, FALSE, 0); + gtk_box_pack_start (box, priv->primary_image, FALSE, FALSE, 0); + gtk_box_pack_start (box, priv->scale, FALSE, FALSE, 0); + gtk_box_pack_start (box, priv->secondary_image, FALSE, FALSE, 0); break; case IDO_SCALE_MENU_ITEM_STYLE_LABEL: - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->primary_label, FALSE, FALSE, 0); -#ifdef USE_GTK3 - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->proxy, FALSE, FALSE, 0); -#else - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->scale, FALSE, FALSE, 0); -#endif - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->secondary_label, FALSE, FALSE, 0); + gtk_box_pack_start (box, priv->primary_label, FALSE, FALSE, 0); + gtk_box_pack_start (box, priv->scale, FALSE, FALSE, 0); + gtk_box_pack_start (box, priv->secondary_label, FALSE, FALSE, 0); break; default: -#ifdef USE_GTK3 - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->proxy, FALSE, FALSE, 0); -#else - gtk_box_pack_start (GTK_BOX (priv->hbox), priv->scale, FALSE, FALSE, 0); -#endif + gtk_box_pack_start (box, priv->scale, FALSE, FALSE, 0); break; } @@ -579,64 +545,50 @@ static gboolean ido_scale_menu_item_button_release_event (GtkWidget *menuitem, GdkEventButton *event) { + IdoScaleMenuItem *item = IDO_SCALE_MENU_ITEM (menuitem); IdoScaleMenuItemPrivate *priv = GET_PRIVATE (menuitem); GtkWidget *scale = priv->scale; gdouble x; + /* if user clicked to the left of the scale... */ if (event->x > priv->child_allocation.x && event->x < priv->child_allocation.x + priv->left_padding) { - GtkAdjustment *adj = gtk_range_get_adjustment (GTK_RANGE (priv->scale)); - if (gtk_widget_get_direction (menuitem) == GTK_TEXT_DIR_LTR) { - gtk_adjustment_set_value (adj, gtk_adjustment_get_lower (adj)); + ido_scale_menu_item_primary_clicked (item); } else { - gtk_adjustment_set_value (adj, gtk_adjustment_get_upper (adj)); + ido_scale_menu_item_secondary_clicked (item); } - - if (priv->grabbed) - { - priv->grabbed = FALSE; - g_signal_emit (menuitem, signals[SLIDER_RELEASED], 0); - } - - return TRUE; } - if (event->x < priv->child_allocation.x + priv->child_allocation.width + priv->right_padding + priv->left_padding && + /* if user clicked to the right of the scale... */ + else if (event->x < priv->child_allocation.x + priv->child_allocation.width + priv->right_padding + priv->left_padding && event->x > priv->child_allocation.x + priv->child_allocation.width + priv->left_padding) { - GtkAdjustment *adj = gtk_range_get_adjustment (GTK_RANGE (priv->scale)); - if (gtk_widget_get_direction (menuitem) == GTK_TEXT_DIR_LTR) { - gtk_adjustment_set_value (adj, gtk_adjustment_get_upper (adj)); + ido_scale_menu_item_secondary_clicked (item); } else { - gtk_adjustment_set_value (adj, gtk_adjustment_get_lower (adj)); + ido_scale_menu_item_primary_clicked (item); } - - if (priv->grabbed) - { - priv->grabbed = FALSE; - g_signal_emit (menuitem, signals[SLIDER_RELEASED], 0); - } - - return TRUE; } - translate_event_coordinates (menuitem, event->x, &x); - event->x = x; + /* user clicked on the scale... */ + else + { + translate_event_coordinates (menuitem, event->x, &x); + event->x = x; - translate_event_coordinates (menuitem, event->x_root, &x); - event->x_root= x; + translate_event_coordinates (menuitem, event->x_root, &x); + event->x_root= x; - gtk_widget_event (scale, - ((GdkEvent *)(void*)(event))); + gtk_widget_event (scale, (GdkEvent*)event); + } if (priv->grabbed) { @@ -812,16 +764,14 @@ ido_scale_menu_item_set_style (IdoScaleMenuItem *menuitem, IdoScaleMenuItemStyle style) { IdoScaleMenuItemPrivate *priv; - IdoScaleMenuItemStyle old_style; g_return_if_fail (IDO_IS_SCALE_MENU_ITEM (menuitem)); priv = GET_PRIVATE (menuitem); - old_style = priv->style; priv->style = style; - update_packing (menuitem, style, old_style); + update_packing (menuitem, style); } /** @@ -958,5 +908,50 @@ ido_scale_menu_item_set_secondary_label (IdoScaleMenuItem *menuitem, } } +/** + * ido_scale_menu_item_primary_clicked: + * @menuitem: the #IdoScaleMenuItem + * + * Emits the "primary-clicked" signal. + * + * The default handler for this signal lowers the scale's + * adjustment to its lower bound. + */ +void +ido_scale_menu_item_primary_clicked (IdoScaleMenuItem * item) +{ + g_signal_emit (item, signals[PRIMARY_CLICKED], 0); +} +static void +default_primary_clicked_handler (IdoScaleMenuItem * item) +{ + g_debug ("%s: setting scale to lower bound", G_STRFUNC); + IdoScaleMenuItemPrivate * priv = GET_PRIVATE (item); + GtkAdjustment *adj = gtk_range_get_adjustment (GTK_RANGE (priv->scale)); + gtk_adjustment_set_value (adj, gtk_adjustment_get_lower (adj)); +} + +/** + * ido_scale_menu_item_primary_clicked: + * @menuitem: the #IdoScaleMenuItem + * + * Emits the "primary-clicked" signal. + * + * The default handler for this signal raises the scale's + * adjustment to its upper bound. + */ +void +ido_scale_menu_item_secondary_clicked (IdoScaleMenuItem * item) +{ + g_signal_emit (item, signals[SECONDARY_CLICKED], 0); +} +static void +default_secondary_clicked_handler (IdoScaleMenuItem * item) +{ + g_debug ("%s: setting scale to upper bound", G_STRFUNC); + IdoScaleMenuItemPrivate * priv = GET_PRIVATE (item); + GtkAdjustment *adj = gtk_range_get_adjustment (GTK_RANGE (priv->scale)); + gtk_adjustment_set_value (adj, gtk_adjustment_get_upper (adj)); +} #define __IDO_SCALE_MENU_ITEM_C__ diff --git a/src/idoscalemenuitem.h b/src/idoscalemenuitem.h index 5afafd3..81a3474 100644 --- a/src/idoscalemenuitem.h +++ b/src/idoscalemenuitem.h @@ -59,6 +59,10 @@ struct _IdoScaleMenuItem struct _IdoScaleMenuItemClass { GtkMenuItemClass parent_class; + + /* signal default handlers */ + void (*primary_clicked)(IdoScaleMenuItem * self); + void (*secondary_clicked)(IdoScaleMenuItem * self); }; @@ -79,12 +83,14 @@ void ido_scale_menu_item_set_style (IdoScaleMenuItem IdoScaleMenuItemStyle style); GtkWidget *ido_scale_menu_item_get_primary_image (IdoScaleMenuItem *menuitem); GtkWidget *ido_scale_menu_item_get_secondary_image (IdoScaleMenuItem *menuitem); -const gchar *ido_scale_menu_item_get_primary_label (IdoScaleMenuItem *menuitem); -const gchar *ido_scale_menu_item_get_secondary_label (IdoScaleMenuItem *menuitem); +const gchar *ido_scale_menu_item_get_primary_label (IdoScaleMenuItem *menuitem); void ido_scale_menu_item_set_primary_label (IdoScaleMenuItem *menuitem, const gchar *label); +const gchar *ido_scale_menu_item_get_secondary_label (IdoScaleMenuItem *menuitem); void ido_scale_menu_item_set_secondary_label (IdoScaleMenuItem *menuitem, const gchar *label); +void ido_scale_menu_item_primary_clicked (IdoScaleMenuItem *menuitem); +void ido_scale_menu_item_secondary_clicked (IdoScaleMenuItem *menuitem); G_END_DECLS |