From 69e85305f2d455c8943514edde215ce69791076a Mon Sep 17 00:00:00 2001 From: Kristian Rietveld Date: Sun, 2 Sep 2012 21:21:51 +0200 Subject: [PATCH 20/68] Introduce a background window The background window covers the part left uncovered by the overshoot window. Two background windows are used to be able to cover an "L shape" that appears when is scrolled in the horizontal and vertical direction at the same time. These background windows are used to capture events, such as scroll events. In the future, it could also be used to draw a specific background pattern/gradient (if the window is configured as INPUT/OUTPUT window). --- gtk/gtkscrolledwindow.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/gtk/gtkscrolledwindow.c b/gtk/gtkscrolledwindow.c index 02745b1..9d0d87a 100644 --- a/gtk/gtkscrolledwindow.c +++ b/gtk/gtkscrolledwindow.c @@ -95,6 +95,8 @@ typedef struct { /* Kinetic scrolling */ GdkEvent *button_press_event; GdkWindow *overshoot_window; + GdkWindow *vbackground_window; + GdkWindow *hbackground_window; guint pointer_grabbed : 1; guint kinetic_scrolling : 1; guint capture_button_press : 1; @@ -1481,6 +1483,8 @@ gtk_scrolled_window_expose (GtkWidget *widget, vscrollbar_window = gtk_widget_get_window (scrolled_window->vscrollbar); if (event->window == priv->overshoot_window || + event->window == priv->vbackground_window || + event->window == priv->hbackground_window || event->window == hscrollbar_window || event->window == vscrollbar_window) GTK_WIDGET_CLASS (gtk_scrolled_window_parent_class)->expose_event (widget, event); @@ -1871,6 +1875,7 @@ _gtk_scrolled_window_allocate_overshoot_window (GtkScrolledWindow *scrolled_wind _gtk_scrolled_window_get_overshoot (scrolled_window, &overshoot_x, &overshoot_y); + /* Overshoot window */ window_allocation = relative_allocation; window_allocation.x += allocation.x; window_allocation.y += allocation.y; @@ -1887,6 +1892,46 @@ _gtk_scrolled_window_allocate_overshoot_window (GtkScrolledWindow *scrolled_wind gdk_window_move_resize (priv->overshoot_window, window_allocation.x, window_allocation.y, window_allocation.width, window_allocation.height); + + /* Vertical background window */ + window_allocation = relative_allocation; + window_allocation.x += allocation.x; + window_allocation.y += allocation.y; + + if (ABS (overshoot_x) > 0) + { + window_allocation.width = ABS (overshoot_x); + if (overshoot_x > 0) + window_allocation.x += relative_allocation.width - overshoot_x; + + gdk_window_move_resize (priv->vbackground_window, + window_allocation.x, window_allocation.y, + window_allocation.width, + window_allocation.height); + gdk_window_show (priv->vbackground_window); + } + else + gdk_window_hide (priv->vbackground_window); + + /* Horizontal background window */ + window_allocation = relative_allocation; + window_allocation.x += allocation.x; + window_allocation.y += allocation.y; + + if (ABS (overshoot_y) > 0) + { + window_allocation.height = ABS (overshoot_y); + if (overshoot_y > 0) + window_allocation.y += relative_allocation.height - overshoot_y; + + gdk_window_move_resize (priv->hbackground_window, + window_allocation.x, window_allocation.y, + window_allocation.width, + window_allocation.height); + gdk_window_show (priv->hbackground_window); + } + else + gdk_window_hide (priv->hbackground_window); } static void @@ -3259,6 +3304,7 @@ gtk_scrolled_window_realize (GtkWidget *widget) gtk_widget_get_allocation (widget, &allocation); gtk_scrolled_window_relative_allocation (widget, &relative_allocation); + /* Overshoot window */ attributes.window_type = GDK_WINDOW_CHILD; attributes.x = allocation.x + relative_allocation.x; attributes.y = allocation.y + relative_allocation.y; @@ -3277,6 +3323,45 @@ gtk_scrolled_window_realize (GtkWidget *widget) gdk_window_set_user_data (priv->overshoot_window, widget); + /* Vertical background window */ + attributes.window_type = GDK_WINDOW_CHILD; + attributes.x = allocation.x + relative_allocation.x; + attributes.y = allocation.y + relative_allocation.y; + attributes.width = 0; + attributes.height = 0; + attributes.wclass = GDK_INPUT_ONLY; + attributes.visual = gtk_widget_get_visual (widget); + attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | + GDK_BUTTON_MOTION_MASK | GDK_SCROLL_MASK; + + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL; + + priv->vbackground_window = + gdk_window_new (gtk_widget_get_parent_window (widget), + &attributes, attributes_mask); + + gdk_window_set_user_data (priv->vbackground_window, widget); + + /* Horizontal background window */ + attributes.window_type = GDK_WINDOW_CHILD; + attributes.x = allocation.x + relative_allocation.x; + attributes.y = allocation.y + relative_allocation.y; + attributes.width = 0; + attributes.height = 0; + attributes.wclass = GDK_INPUT_ONLY; + attributes.visual = gtk_widget_get_visual (widget); + attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | + GDK_BUTTON_MOTION_MASK | GDK_SCROLL_MASK; + + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL; + + priv->hbackground_window = + gdk_window_new (gtk_widget_get_parent_window (widget), + &attributes, attributes_mask); + + gdk_window_set_user_data (priv->hbackground_window, widget); + + child_widget = gtk_bin_get_child (GTK_BIN (widget)); if (child_widget) @@ -3296,6 +3381,14 @@ gtk_scrolled_window_unrealize (GtkWidget *widget) gdk_window_destroy (priv->overshoot_window); priv->overshoot_window = NULL; + gdk_window_set_user_data (priv->vbackground_window, NULL); + gdk_window_destroy (priv->vbackground_window); + priv->vbackground_window = NULL; + + gdk_window_set_user_data (priv->hbackground_window, NULL); + gdk_window_destroy (priv->hbackground_window); + priv->hbackground_window = NULL; + gtk_widget_set_realized (widget, FALSE); GTK_WIDGET_CLASS (gtk_scrolled_window_parent_class)->unrealize (widget); @@ -3308,6 +3401,15 @@ gtk_scrolled_window_map (GtkWidget *widget) GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window); gdk_window_show (priv->overshoot_window); + if (gdk_window_get_width (priv->vbackground_window) > 1) + gdk_window_show (priv->vbackground_window); + else + gdk_window_hide (priv->vbackground_window); + + if (gdk_window_get_height (priv->hbackground_window) > 1) + gdk_window_show (priv->hbackground_window); + else + gdk_window_hide (priv->hbackground_window); GTK_WIDGET_CLASS (gtk_scrolled_window_parent_class)->map (widget); } @@ -3319,6 +3421,8 @@ gtk_scrolled_window_unmap (GtkWidget *widget) GtkScrolledWindowPrivate *priv = GTK_SCROLLED_WINDOW_GET_PRIVATE (scrolled_window); gdk_window_hide (priv->overshoot_window); + gdk_window_hide (priv->vbackground_window); + gdk_window_hide (priv->hbackground_window); GTK_WIDGET_CLASS (gtk_scrolled_window_parent_class)->unmap (widget); } -- 1.7.10.2 (Apple Git-33)