From: Matt Birkholz Date: Tue, 14 Aug 2012 04:39:48 +0000 (-0700) Subject: gtk: Replaced GtkScrolledWindow with GtkScrollingWindow. X-Git-Tag: mit-scheme-pucked-9.2.12~562 X-Git-Url: https://birchwood-abbey.net/git?a=commitdiff_plain;h=b68993c01933a854d781c0e72910242ed34b9435;p=mit-scheme.git gtk: Replaced GtkScrolledWindow with GtkScrollingWindow. Define GtkScrollingWindow as a subclass of GtkScrolledWindow that specializes (overrides) the geometry protocol, while inheriting kinetic scrolling and other goodies(?). --- diff --git a/src/gtk/Makefile-fragment b/src/gtk/Makefile-fragment index 4c3dc3dbb..f0a80d50d 100644 --- a/src/gtk/Makefile-fragment +++ b/src/gtk/Makefile-fragment @@ -59,11 +59,17 @@ install: | ../microcode/scheme --library ../lib --batch-mode` = "c"; \ then $(MAKE) install-liarc-bundle; fi -gtk-shim.so: gtk-shim.o scmwidget.o gtkio.o $(SHIM_LOADER) - $(LINK_SHIM) gtk-shim.o scmwidget.o gtkio.o \ +gtk-shim.so: gtk-shim.o gtkscrollingwindow.o scmwidget.o gtkio.o $(SHIM_LOADER) + $(LINK_SHIM) gtk-shim.o gtkscrollingwindow.o scmwidget.o gtkio.o \ `pkg-config --libs gtk+-3.0 gthread-2.0` $(SHIM_LIBS) -scmwidget.o: scmwidget.c +gtkscrollingwindow.o: gtkscrollingwindow.c gtkscrollingwindow.h + $(COMPILE_SHIM) `pkg-config --cflags gtk+-3.0` -c gtkscrollingwindow.c + +gtkscrollingwindow.c: gtkscrollingwindow.c.stay + cp -p gtkscrollingwindow.c.stay gtkscrollingwindow.c + +scmwidget.o: scmwidget.c scmwidget.h $(COMPILE_SHIM) `pkg-config --cflags gtk+-3.0` -c scmwidget.c scmwidget.c: scmwidget.c.stay diff --git a/src/gtk/gtk-shim.h b/src/gtk/gtk-shim.h index 3949d085b..0fcb62276 100644 --- a/src/gtk/gtk-shim.h +++ b/src/gtk/gtk-shim.h @@ -30,6 +30,7 @@ USA. #include #include "scmwidget.h" +#include "gtkscrollingwindow.h" typedef unsigned int uint; extern gboolean start_gtk (int *argc, char ***argv); diff --git a/src/gtk/gtk-widget.scm b/src/gtk/gtk-widget.scm index 7d5de4199..e6603c402 100644 --- a/src/gtk/gtk-widget.scm +++ b/src/gtk/gtk-widget.scm @@ -623,7 +623,7 @@ USA. (define (gtk-scrolled-window-new) (let* ((window (make-gtk-scrolled-window)) (alien (gobject-alien window))) - (C-call "gtk_scrolled_window_new" alien 0 0) + (C-call "gtk_scrolling_window_new" alien 0 0) (error-if-null alien "Could not create:" window) (C-call "g_object_ref_sink" alien alien) (set-gtk-widget-destroy-callback! window) diff --git a/src/gtk/gtk.cdecl b/src/gtk/gtk.cdecl index 6375ee94b..1f56dfc83 100644 --- a/src/gtk/gtk.cdecl +++ b/src/gtk/gtk.cdecl @@ -99,6 +99,11 @@ USA. ;;; miscellaneous +(extern (* GtkWidget) ;gtkscrollingwindow.h + gtk_scrolling_window_new + (hadjustment (* GtkAdjustment)) + (vadjustment (* GtkAdjustment))) + (extern void g_free ;glib-2.8.6/glib/gmem.h (mem gpointer)) diff --git a/src/gtk/gtkscrollingwindow.c.stay b/src/gtk/gtkscrollingwindow.c.stay new file mode 100644 index 000000000..38efa8ba0 --- /dev/null +++ b/src/gtk/gtkscrollingwindow.c.stay @@ -0,0 +1,336 @@ +#include "gtkscrollingwindow.h" + +/** + * SECTION:gtkscrollingwindow + * @Short_description: Adds scrollbars to its child widget + * @Title: GtkScrollingWindow + * @See_also: #GtkScrollable, #GtkViewport, #GtkAdjustment + * + * #GtkScrollingWindow is a #GtkBin subclass: it's a container that + * accepts a single child widget (a GtkScrollable) and adds an + * optional beveled frame and scrollbars. + * + * The position of the scrollbars is controlled by the scroll + * adjustments. See #GtkAdjustment for the fields in an adjustment. + * + * #GtkScrollingWindow is a #GtkScrolledWindow subclass that overrides + * the geometry protocol to work as follows: + * + * A scrolled window (GtkScrolledWindow) is about squeezing an overly + * large widget into a small space and allowing the user to scroll it. + * It ignores the natural size of the problem widget, expecting a + * gtk_widget_set_size_request to override (squeeze) it. + * + * A scrolling window (GtkScrollingWindow) is about sticking + * scrollbars on a viewport -- a GtkScrollable. Its natural size is + * the natural size of the viewport, scrollbars and frame (with + * spacing). Using gtk_widget_set_size_request interferes with the + * natural sizing (esp. shrinking of expandable viewports). + */ + +struct _GtkScrolledWindowPrivate +{ + GtkWidget *hscrollbar; + GtkWidget *vscrollbar; + + GtkCornerType real_window_placement; + guint16 shadow_type; + + guint window_placement_set : 1; + guint hscrollbar_policy : 2; + guint vscrollbar_policy : 2; + guint hscrollbar_visible : 1; + guint vscrollbar_visible : 1; + guint window_placement : 2; + guint focus_out : 1; /* Flag used by ::move-focus-out implementation */ + + gint min_content_width; + gint min_content_height; + + /* Kinetic scrolling */ + GdkEvent *button_press_event; + GdkWindow *overshoot_window; + GdkDevice *drag_device; + guint kinetic_scrolling : 1; + guint capture_button_press : 1; + guint in_drag : 1; + guint last_button_event_valid : 1; + + guint release_timeout_id; + guint deceleration_id; + + gdouble last_button_event_x_root; + gdouble last_button_event_y_root; + + gdouble last_motion_event_x_root; + gdouble last_motion_event_y_root; + guint32 last_motion_event_time; + + gdouble x_velocity; + gdouble y_velocity; + + gdouble unclamped_hadj_value; + gdouble unclamped_vadj_value; +}; + +static void +gtk_scrolled_window_update_real_placement (GtkScrolledWindow *scrolled_window) +{ + GtkScrolledWindowPrivate *priv = scrolled_window->priv; + GtkSettings *settings; + + settings = gtk_widget_get_settings (GTK_WIDGET (scrolled_window)); + + if (priv->window_placement_set || settings == NULL) + priv->real_window_placement = priv->window_placement; + else + g_object_get (settings, + "gtk-scrolled-window-placement", + &priv->real_window_placement, + NULL); +} + +static void +gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window) +{ + GtkScrolledWindowPrivate *priv; + + scrolled_window->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (scrolled_window, + GTK_TYPE_SCROLLED_WINDOW, + GtkScrolledWindowPrivate); + + gtk_widget_set_has_window (GTK_WIDGET (scrolled_window), FALSE); + gtk_widget_set_can_focus (GTK_WIDGET (scrolled_window), TRUE); + + priv->hscrollbar = NULL; + priv->vscrollbar = NULL; + priv->hscrollbar_policy = GTK_POLICY_AUTOMATIC; + priv->vscrollbar_policy = GTK_POLICY_AUTOMATIC; + priv->hscrollbar_visible = FALSE; + priv->vscrollbar_visible = FALSE; + priv->focus_out = FALSE; + priv->window_placement = GTK_CORNER_TOP_LEFT; + gtk_scrolled_window_update_real_placement (scrolled_window); + priv->min_content_width = -1; + priv->min_content_height = -1; + + gtk_scrolled_window_set_kinetic_scrolling (scrolled_window, TRUE); + gtk_scrolled_window_set_capture_button_press (scrolled_window, TRUE); +} + +static void gtk_scrolling_window_get_preferred_width (GtkWidget *widget, + gint *minimum_size, + gint *natural_size); +static void gtk_scrolling_window_get_preferred_height (GtkWidget *widget, + gint *minimum_size, + gint *natural_size); +static void gtk_scrolling_window_get_preferred_height_for_width (GtkWidget *layout, + gint width, + gint *minimum_height, + gint *natural_height); +static void gtk_scrolling_window_get_preferred_width_for_height (GtkWidget *layout, + gint width, + gint *minimum_height, + gint *natural_height); + +G_DEFINE_TYPE (GtkScrollingWindow, gtk_scrolling_window, + GTK_TYPE_SCROLLED_WINDOW) + +static void +gtk_scrolling_window_class_init (GtkScrollingWindowClass *class) +{ + GtkWidgetClass *widget_class = (GtkWidgetClass*) class; + + widget_class->get_preferred_width = gtk_scrolling_window_get_preferred_width; + widget_class->get_preferred_height = gtk_scrolling_window_get_preferred_height; + widget_class->get_preferred_height_for_width = gtk_scrolling_window_get_preferred_height_for_width; + widget_class->get_preferred_width_for_height = gtk_scrolling_window_get_preferred_width_for_height; +} + +static void +gtk_scrolling_window_init (GtkScrollingWindow *scrolling_window) +{ + gtk_scrolled_window_init (GTK_SCROLLED_WINDOW (scrolling_window)); +} + +/** + * gtk_scrolling_window_new: + * @hadjustment: (allow-none): horizontal adjustment + * @vadjustment: (allow-none): vertical adjustment + * + * Creates a new scrolling window. + * + * The two arguments are the scrolling window's adjustments; these will be + * shared with the scrollbars and the child widget to keep the bars in sync + * with the child. Usually you want to pass %NULL for the adjustments, which + * will cause the scrolling window to create them for you. + * + * Returns: a new scrolling window + */ +GtkWidget* +gtk_scrolling_window_new (GtkAdjustment *hadjustment, + GtkAdjustment *vadjustment) +{ + GtkWidget *scrolling_window; + + if (hadjustment) + g_return_val_if_fail (GTK_IS_ADJUSTMENT (hadjustment), NULL); + + if (vadjustment) + g_return_val_if_fail (GTK_IS_ADJUSTMENT (vadjustment), NULL); + + scrolling_window = g_object_new (GTK_TYPE_SCROLLING_WINDOW, + "hadjustment", hadjustment, + "vadjustment", vadjustment, + NULL); + + return scrolling_window; +} + +extern gboolean ubuntu_overlay_scrollbar_get_enabled (void); + +static gint +gtk_scrolled_window_get_scrollbar_spacing (GtkScrolledWindow *scrolled_window) +{ + GtkScrolledWindowClass *class; + + g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window), 0); + + if (ubuntu_overlay_scrollbar_get_enabled ()) + return 0; + + class = GTK_SCROLLED_WINDOW_GET_CLASS (scrolled_window); + + if (class->scrollbar_spacing >= 0) + return class->scrollbar_spacing; + else + { + gint scrollbar_spacing; + + gtk_widget_style_get (GTK_WIDGET (scrolled_window), + "scrollbar-spacing", &scrollbar_spacing, + NULL); + + return scrollbar_spacing; + } +} + +static void +gtk_scrolling_window_get_preferred_size (GtkWidget *widget, + GtkOrientation orientation, + gint *minimum_size, + gint *natural_size) +{ + GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget); + GtkScrolledWindowPrivate *priv = scrolled_window->priv; + GtkBin *bin = GTK_BIN (scrolled_window); + gint minimum; + gint natural; + GtkWidget *child; + + /* Init to child size. */ + child = gtk_bin_get_child (bin); + if (child && gtk_widget_get_visible (child)) + { + if (orientation == GTK_ORIENTATION_HORIZONTAL) + gtk_widget_get_preferred_width (child, &minimum, &natural); + else + gtk_widget_get_preferred_height (child, &minimum, &natural); + } + + /* Add min_content_width/height. */ + { + gint min_content_size = (orientation == GTK_ORIENTATION_HORIZONTAL + ? priv->min_content_width + : priv->min_content_height); + if (min_content_size >= 0) + { + minimum = MAX (minimum, min_content_size); + natural = MAX (natural, min_content_size); + } + } + + /* Add scrollbar size. */ + if (priv->vscrollbar_policy != GTK_POLICY_NEVER) + { + gint min, nat; + gint space = gtk_scrolled_window_get_scrollbar_spacing (scrolled_window); + if (orientation == GTK_ORIENTATION_VERTICAL) + gtk_widget_get_preferred_height (priv->hscrollbar, &min, &nat); + else + gtk_widget_get_preferred_width (priv->vscrollbar, &min, &nat); + minimum += space + min; + natural += space + nat; + } + + /* Add shadow size. */ + if (priv->shadow_type != GTK_SHADOW_NONE) + { + GtkStyleContext *context; + GtkStateFlags state; + GtkBorder padding, border; + + context = gtk_widget_get_style_context (GTK_WIDGET (widget)); + state = gtk_widget_get_state_flags (GTK_WIDGET (widget)); + + gtk_style_context_save (context); + gtk_style_context_add_class (context, GTK_STYLE_CLASS_FRAME); + gtk_style_context_get_padding (context, state, &padding); + gtk_style_context_get_border (context, state, &border); + gtk_style_context_restore (context); + + if (orientation == GTK_ORIENTATION_VERTICAL) + { + minimum += padding.top + padding.bottom + border.top + border.bottom; + natural += padding.top + padding.bottom + border.top + border.bottom; + } + else + { + minimum += padding.left + padding.right + border.left + border.right; + natural += padding.left + padding.right + border.left + border.right; + } + } + + if (minimum_size) + *minimum_size = minimum; + if (natural_size) + *natural_size = natural; +} + +static void +gtk_scrolling_window_get_preferred_width (GtkWidget *widget, + gint *minimum_size, + gint *natural_size) +{ + gtk_scrolling_window_get_preferred_size (widget, GTK_ORIENTATION_HORIZONTAL, minimum_size, natural_size); +} + +static void +gtk_scrolling_window_get_preferred_height (GtkWidget *widget, + gint *minimum_size, + gint *natural_size) +{ + gtk_scrolling_window_get_preferred_size (widget, GTK_ORIENTATION_VERTICAL, minimum_size, natural_size); +} + +static void +gtk_scrolling_window_get_preferred_height_for_width (GtkWidget *widget, + gint width, + gint *minimum_height, + gint *natural_height) +{ + g_return_if_fail (GTK_IS_WIDGET (widget)); + + GTK_WIDGET_GET_CLASS (widget)->get_preferred_height (widget, minimum_height, natural_height); +} + +static void +gtk_scrolling_window_get_preferred_width_for_height (GtkWidget *widget, + gint height, + gint *minimum_width, + gint *natural_width) +{ + g_return_if_fail (GTK_IS_WIDGET (widget)); + + GTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget, minimum_width, natural_width); +} diff --git a/src/gtk/gtkscrollingwindow.h b/src/gtk/gtkscrollingwindow.h new file mode 100644 index 000000000..72fce3eac --- /dev/null +++ b/src/gtk/gtkscrollingwindow.h @@ -0,0 +1,27 @@ +#include + +#define GTK_TYPE_SCROLLING_WINDOW (gtk_scrolling_window_get_type ()) +#define GTK_SCROLLING_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SCROLLING_WINDOW, GtkScrollingWindow)) +#define GTK_SCROLLING_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_SCROLLING_WINDOW, GtkScrollingWindowClass)) +#define GTK_IS_SCROLLING_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SCROLLING_WINDOW)) +#define GTK_IS_SCROLLING_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SCROLLING_WINDOW)) +#define GTK_SCROLLING_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_SCROLLING_WINDOW, GtkScrollingWindowClass)) + + +typedef struct _GtkScrollingWindow GtkScrollingWindow; +typedef struct _GtkScrollingWindowClass GtkScrollingWindowClass; + +struct _GtkScrollingWindow +{ + GtkScrolledWindow scrolled; +}; + +struct _GtkScrollingWindowClass +{ + GtkScrolledWindowClass parent_class; +}; + + +GType gtk_scrolling_window_get_type (void) G_GNUC_CONST; +GtkWidget* gtk_scrolling_window_new (GtkAdjustment *hadjustment, + GtkAdjustment *vadjustment);