summaryrefslogtreecommitdiff
path: root/gtk
diff options
context:
space:
mode:
authorCarlos Garnacho <carlos@imendio.com>2008-03-03 21:15:21 +0000
committerFederico Mena Quintero <federico@src.gnome.org>2008-03-03 21:15:21 +0000
commit761749c26b9c300da5a5db08837af0e73b857624 (patch)
tree29375d93f6d028547d1c8c1fc9c7e1b7cbdd374e /gtk
parent845a4632d9c9bb909b4dc05e0a98123d6b4abd66 (diff)
downloadgtk+-761749c26b9c300da5a5db08837af0e73b857624.tar.gz
bgo417389 - Scrollwheel for GtkPathBar
2008-03-03 Carlos Garnacho <carlos@imendio.com> Fix http://bugzilla.gnome.org/show_bug.cgi?id=417389 - Make the scrollwheel work in GtkPathBar. * gtk/gtkpathbar.h (struct _GtkPathBar): New field event_window. * gtk/gtkpathbar.c (gtk_path_bar_realize): New function. Create an input-only window, event_window, which we'll use to capture scroll events. (gtk_path_bar_map): Show the event_window under the rest of the windows, so it will be a catch-all for unhandled events. Signed-off-by: Federico Mena Quintero <federico@gnu.org> svn path=/trunk/; revision=19699
Diffstat (limited to 'gtk')
-rw-r--r--gtk/gtkpathbar.c128
-rw-r--r--gtk/gtkpathbar.h2
2 files changed, 115 insertions, 15 deletions
diff --git a/gtk/gtkpathbar.c b/gtk/gtkpathbar.c
index 0594251305..d396cc895c 100644
--- a/gtk/gtkpathbar.c
+++ b/gtk/gtkpathbar.c
@@ -80,9 +80,12 @@ G_DEFINE_TYPE (GtkPathBar, gtk_path_bar, GTK_TYPE_CONTAINER)
static void gtk_path_bar_finalize (GObject *object);
static void gtk_path_bar_dispose (GObject *object);
+static void gtk_path_bar_realize (GtkWidget *widget);
+static void gtk_path_bar_unrealize (GtkWidget *widget);
static void gtk_path_bar_size_request (GtkWidget *widget,
GtkRequisition *requisition);
-static void gtk_path_bar_unmap (GtkWidget *widget);
+static void gtk_path_bar_map (GtkWidget *widget);
+static void gtk_path_bar_unmap (GtkWidget *widget);
static void gtk_path_bar_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
static void gtk_path_bar_add (GtkContainer *container,
@@ -93,10 +96,10 @@ static void gtk_path_bar_forall (GtkContainer *container,
gboolean include_internals,
GtkCallback callback,
gpointer callback_data);
-static void gtk_path_bar_scroll_up (GtkWidget *button,
- GtkPathBar *path_bar);
-static void gtk_path_bar_scroll_down (GtkWidget *button,
- GtkPathBar *path_bar);
+static gboolean gtk_path_bar_scroll (GtkWidget *widget,
+ GdkEventScroll *event);
+static void gtk_path_bar_scroll_up (GtkPathBar *path_bar);
+static void gtk_path_bar_scroll_down (GtkPathBar *path_bar);
static void gtk_path_bar_stop_scrolling (GtkPathBar *path_bar);
static gboolean gtk_path_bar_slider_up_defocus (GtkWidget *widget,
GdkEventButton *event,
@@ -175,8 +178,8 @@ gtk_path_bar_init (GtkPathBar *path_bar)
path_bar->down_slider_button = get_slider_button (path_bar, GTK_ARROW_RIGHT);
path_bar->icon_size = FALLBACK_ICON_SIZE;
- g_signal_connect (path_bar->up_slider_button, "clicked", G_CALLBACK (gtk_path_bar_scroll_up), path_bar);
- g_signal_connect (path_bar->down_slider_button, "clicked", G_CALLBACK (gtk_path_bar_scroll_down), path_bar);
+ g_signal_connect_swapped (path_bar->up_slider_button, "clicked", G_CALLBACK (gtk_path_bar_scroll_up), path_bar);
+ g_signal_connect_swapped (path_bar->down_slider_button, "clicked", G_CALLBACK (gtk_path_bar_scroll_down), path_bar);
g_signal_connect (path_bar->up_slider_button, "focus_out_event", G_CALLBACK (gtk_path_bar_slider_up_defocus), path_bar);
g_signal_connect (path_bar->down_slider_button, "focus_out_event", G_CALLBACK (gtk_path_bar_slider_down_defocus), path_bar);
@@ -204,12 +207,16 @@ gtk_path_bar_class_init (GtkPathBarClass *path_bar_class)
gobject_class->dispose = gtk_path_bar_dispose;
widget_class->size_request = gtk_path_bar_size_request;
+ widget_class->realize = gtk_path_bar_realize;
+ widget_class->unrealize = gtk_path_bar_unrealize;
+ widget_class->map = gtk_path_bar_map;
widget_class->unmap = gtk_path_bar_unmap;
widget_class->size_allocate = gtk_path_bar_size_allocate;
widget_class->style_set = gtk_path_bar_style_set;
widget_class->screen_changed = gtk_path_bar_screen_changed;
widget_class->grab_notify = gtk_path_bar_grab_notify;
widget_class->state_changed = gtk_path_bar_state_changed;
+ widget_class->scroll_event = gtk_path_bar_scroll;
container_class->add = gtk_path_bar_add;
container_class->forall = gtk_path_bar_forall;
@@ -363,13 +370,66 @@ gtk_path_bar_update_slider_buttons (GtkPathBar *path_bar)
}
static void
+gtk_path_bar_map (GtkWidget *widget)
+{
+ gdk_window_show (GTK_PATH_BAR (widget)->event_window);
+
+ GTK_WIDGET_CLASS (gtk_path_bar_parent_class)->map (widget);
+}
+
+static void
gtk_path_bar_unmap (GtkWidget *widget)
{
gtk_path_bar_stop_scrolling (GTK_PATH_BAR (widget));
+ gdk_window_hide (GTK_PATH_BAR (widget)->event_window);
GTK_WIDGET_CLASS (gtk_path_bar_parent_class)->unmap (widget);
}
+static void
+gtk_path_bar_realize (GtkWidget *widget)
+{
+ GtkPathBar *path_bar;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+ path_bar = GTK_PATH_BAR (widget);
+ widget->window = gtk_widget_get_parent_window (widget);
+ g_object_ref (widget->window);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.wclass = GDK_INPUT_ONLY;
+ attributes.event_mask = gtk_widget_get_events (widget);
+ attributes.event_mask |= GDK_SCROLL_MASK;
+ attributes_mask = GDK_WA_X | GDK_WA_Y;
+
+ path_bar->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
+ &attributes, attributes_mask);
+ gdk_window_set_user_data (path_bar->event_window, widget);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+}
+
+static void
+gtk_path_bar_unrealize (GtkWidget *widget)
+{
+ GtkPathBar *path_bar;
+
+ path_bar = GTK_PATH_BAR (widget);
+
+ gdk_window_set_user_data (path_bar->event_window, NULL);
+ gdk_window_destroy (path_bar->event_window);
+ path_bar->event_window = NULL;
+
+ (* GTK_WIDGET_CLASS (gtk_path_bar_parent_class)->unrealize) (widget);
+}
+
/* This is a tad complicated
*/
static void
@@ -390,6 +450,11 @@ gtk_path_bar_size_allocate (GtkWidget *widget,
widget->allocation = *allocation;
+ if (GTK_WIDGET_REALIZED (widget))
+ gdk_window_move_resize (path_bar->event_window,
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+
/* No path is set; we don't have to allocate anything. */
if (path_bar->button_list == NULL)
return;
@@ -594,6 +659,25 @@ gtk_path_bar_screen_changed (GtkWidget *widget,
gtk_path_bar_check_icon_theme (GTK_PATH_BAR (widget));
}
+static gboolean
+gtk_path_bar_scroll (GtkWidget *widget,
+ GdkEventScroll *event)
+{
+ switch (event->direction)
+ {
+ case GDK_SCROLL_RIGHT:
+ case GDK_SCROLL_DOWN:
+ gtk_path_bar_scroll_down (GTK_PATH_BAR (widget));
+ break;
+ case GDK_SCROLL_LEFT:
+ case GDK_SCROLL_UP:
+ gtk_path_bar_scroll_up (GTK_PATH_BAR (widget));
+ break;
+ }
+
+ return TRUE;
+}
+
static void
gtk_path_bar_add (GtkContainer *container,
GtkWidget *widget)
@@ -679,7 +763,7 @@ gtk_path_bar_forall (GtkContainer *container,
}
static void
-gtk_path_bar_scroll_down (GtkWidget *button, GtkPathBar *path_bar)
+gtk_path_bar_scroll_down (GtkPathBar *path_bar)
{
GList *list;
GList *down_button = NULL;
@@ -695,11 +779,17 @@ gtk_path_bar_scroll_down (GtkWidget *button, GtkPathBar *path_bar)
return;
}
+ if (gtk_widget_get_child_visible (BUTTON_DATA (path_bar->button_list->data)->button))
+ {
+ /* Return if the last button is already visible */
+ return;
+ }
+
gtk_widget_queue_resize (GTK_WIDGET (path_bar));
border_width = GTK_CONTAINER (path_bar)->border_width;
direction = gtk_widget_get_direction (GTK_WIDGET (path_bar));
-
+
/* We find the button at the 'down' end that we have to make
* visible */
for (list = path_bar->button_list; list; list = list->next)
@@ -745,7 +835,7 @@ gtk_path_bar_scroll_down (GtkWidget *button, GtkPathBar *path_bar)
}
static void
-gtk_path_bar_scroll_up (GtkWidget *button, GtkPathBar *path_bar)
+gtk_path_bar_scroll_up (GtkPathBar *path_bar)
{
GList *list;
@@ -755,9 +845,17 @@ gtk_path_bar_scroll_up (GtkWidget *button, GtkPathBar *path_bar)
return;
}
+ list = g_list_last (path_bar->button_list);
+
+ if (gtk_widget_get_child_visible (BUTTON_DATA (list->data)->button))
+ {
+ /* Return if the first button is already visible */
+ return;
+ }
+
gtk_widget_queue_resize (GTK_WIDGET (path_bar));
- for (list = g_list_last (path_bar->button_list); list; list = list->prev)
+ for ( ; list; list = list->prev)
{
if (list->prev && gtk_widget_get_child_visible (BUTTON_DATA (list->prev->data)->button))
{
@@ -777,9 +875,9 @@ gtk_path_bar_scroll_timeout (GtkPathBar *path_bar)
if (path_bar->timer)
{
if (path_bar->scrolling_up)
- gtk_path_bar_scroll_up (path_bar->up_slider_button, path_bar);
+ gtk_path_bar_scroll_up (path_bar);
else if (path_bar->scrolling_down)
- gtk_path_bar_scroll_down (path_bar->down_slider_button, path_bar);
+ gtk_path_bar_scroll_down (path_bar);
if (path_bar->need_timer)
{
@@ -882,13 +980,13 @@ gtk_path_bar_slider_button_press (GtkWidget *widget,
{
path_bar->scrolling_down = FALSE;
path_bar->scrolling_up = TRUE;
- gtk_path_bar_scroll_up (path_bar->up_slider_button, path_bar);
+ gtk_path_bar_scroll_up (path_bar);
}
else if (widget == path_bar->down_slider_button)
{
path_bar->scrolling_up = FALSE;
path_bar->scrolling_down = TRUE;
- gtk_path_bar_scroll_down (path_bar->down_slider_button, path_bar);
+ gtk_path_bar_scroll_down (path_bar);
}
if (!path_bar->timer)
diff --git a/gtk/gtkpathbar.h b/gtk/gtkpathbar.h
index 3d32bbaad8..aa56ff81ca 100644
--- a/gtk/gtkpathbar.h
+++ b/gtk/gtkpathbar.h
@@ -51,6 +51,8 @@ struct _GtkPathBar
GdkPixbuf *home_icon;
GdkPixbuf *desktop_icon;
+ GdkWindow *event_window;
+
GList *button_list;
GList *first_scrolled_button;
GList *fake_root;