From 6f37a56d81060f6ed6fd3078c193571e9ae32f37 Mon Sep 17 00:00:00 2001 From: Matt Birkholz Date: Sun, 27 Nov 2016 11:41:34 -0700 Subject: [PATCH] gtk: GtkPanedView and GtkScrolledView for 3.20.9 (Ubuntu 16.10). --- src/gtk/Makefile.am | 1 + src/gtk/README | 3 +- src/gtk/configure.ac | 2 + src/gtk/gtkpanedview-3.20.9.c | 61 ++++++ src/gtk/gtkscrolledview-3.18.9.c | 8 - src/gtk/gtkscrolledview-3.20.9.c | 343 +++++++++++++++++++++++++++++++ 6 files changed, 409 insertions(+), 9 deletions(-) create mode 100644 src/gtk/gtkpanedview-3.20.9.c create mode 100644 src/gtk/gtkscrolledview-3.20.9.c diff --git a/src/gtk/Makefile.am b/src/gtk/Makefile.am index dddb147d8..1632ca935 100644 --- a/src/gtk/Makefile.am +++ b/src/gtk/Makefile.am @@ -146,6 +146,7 @@ EXTRA_DIST += gtkpanedview-3.10.8.c gtkscrolledview-3.10.8.c EXTRA_DIST += gtkpanedview-3.14.13.c gtkscrolledview-3.14.13.c EXTRA_DIST += gtkpanedview-3.16.7.c gtkscrolledview-3.16.7.c EXTRA_DIST += gtkpanedview-3.18.9.c gtkscrolledview-3.18.9.c +EXTRA_DIST += gtkpanedview-3.20.9.c gtkscrolledview-3.20.9.c EXTRA_DIST += conses.png hello.scm test-gport-performance.scm EXTRA_DIST += debian diff --git a/src/gtk/README b/src/gtk/README index 564326880..b7f199b53 100644 --- a/src/gtk/README +++ b/src/gtk/README @@ -13,12 +13,13 @@ require access to private members of their supertypes, so they need a struct declaration matching the private declaration in the toolkit. The trick: Select an implementation of the special widgets that is -compatible with your system's toolkit. Four are provided and +compatible with your system's toolkit. Five are provided and correspond to recent Ubuntu releases. If your system is using a matching or "close enough" version of the toolkit, you will get a treat. Ubuntu Gtk+ + 16.10 3.20.9 16.04lts 3.18.9 15.10 3.16.7 15.04 3.14.13 diff --git a/src/gtk/configure.ac b/src/gtk/configure.ac index f5ce85f4a..05e7585e1 100644 --- a/src/gtk/configure.ac +++ b/src/gtk/configure.ac @@ -74,6 +74,8 @@ AC_ARG_WITH([gtk-version], if test "${with_gtk_version}" != guess; then GTK_VERSION=$with_gtk_version +elif pkg-config --exists 'gtk+-3.0 >= 3.20.9' 2>/dev/null; then + GTK_VERSION=3.20.9 elif pkg-config --exists 'gtk+-3.0 >= 3.18.9' 2>/dev/null; then GTK_VERSION=3.18.9 elif pkg-config --exists 'gtk+-3.0 >= 3.16.7' 2>/dev/null; then diff --git a/src/gtk/gtkpanedview-3.20.9.c b/src/gtk/gtkpanedview-3.20.9.c new file mode 100644 index 000000000..0f9d49588 --- /dev/null +++ b/src/gtk/gtkpanedview-3.20.9.c @@ -0,0 +1,61 @@ +/* -*-C-*- + +Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, + 2016 Matthew Birkholz + +This file is part of a gtk plugin for MIT/GNU Scheme. + +This plugin is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +This plugin is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this plugin; if not, write to the Free Software Foundation, +Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +/* A specialized GtkPaned. See documentation of . */ + +/* The v3.20.9 of GtkPaned seems to do the right thing with + GtkScrolledViews, so this version of GtkPanedView is not actually + specialized. */ + +#include "gtkpanedview.h" + +G_DEFINE_TYPE (GtkPanedView, gtk_paned_view, + GTK_TYPE_PANED) + +static void +gtk_paned_view_class_init (GtkPanedViewClass *class) +{ + GtkWidgetClass *widget_class = (GtkWidgetClass*) class; +} + +static void +gtk_paned_view_init (GtkPanedView *paned_view) +{ + g_assert (GTK_PANED (paned_view) ->priv != NULL); +} + +/** + * gtk_paned_view_new: + * @orientation: GTK_ORIENTATION_VERTICAL or GTK_ORIENTATION_HORIZONTAL. + * + * Creates a new paned view. + * + * Returns: a new paned view. + */ +GtkWidget* +gtk_paned_view_new (GtkOrientation orientation) +{ + return (g_object_new (GTK_TYPE_PANED_VIEW, + "orientation", orientation, + NULL)); +} diff --git a/src/gtk/gtkscrolledview-3.18.9.c b/src/gtk/gtkscrolledview-3.18.9.c index 3c6e04de3..012e133cf 100644 --- a/src/gtk/gtkscrolledview-3.18.9.c +++ b/src/gtk/gtkscrolledview-3.18.9.c @@ -99,7 +99,6 @@ gtk_scrolled_view_new (GtkAdjustment *hadjustment, gtkscrolledwindow.c v3.18.9 unless otherwise noted. struct Indicator - struct ScrollHistoryElem struct _GtkScrolledWindowPrivate static gint _gtk_scrolled_window_get_scrollbar_spacing () static void gtk_scrolled_window_get_preferred_size () PATCHED @@ -126,13 +125,6 @@ typedef struct guint over_timeout_id; } Indicator; -typedef struct -{ - gdouble dx; - gdouble dy; - guint32 evtime; -} ScrollHistoryElem; - struct _GtkScrolledWindowPrivate { GtkWidget *hscrollbar; diff --git a/src/gtk/gtkscrolledview-3.20.9.c b/src/gtk/gtkscrolledview-3.20.9.c new file mode 100644 index 000000000..b6aafb452 --- /dev/null +++ b/src/gtk/gtkscrolledview-3.20.9.c @@ -0,0 +1,343 @@ +/* -*-C-*- + +Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, + 2016 Matthew Birkholz + +This file is part of a gtk plugin for MIT/GNU Scheme. + +This plugin is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2 of the License, or (at your +option) any later version. + +This plugin is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this plugin; if not, write to the Free Software Foundation, +Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +/* A specialized GtkScrolledWindow. See documentation of + . */ + +#include "gtkscrolledview.h" + +static void gtk_scrolled_window_get_preferred_width (GtkWidget *widget, + gint *minimum_size, + gint *natural_size); +static void gtk_scrolled_window_get_preferred_height (GtkWidget *widget, + gint *minimum_size, + gint *natural_size); +static void gtk_scrolled_window_get_preferred_height_for_width (GtkWidget *layout, + gint width, + gint *minimum_height, + gint *natural_height); +static void gtk_scrolled_window_get_preferred_width_for_height (GtkWidget *layout, + gint width, + gint *minimum_height, + gint *natural_height); + +G_DEFINE_TYPE (GtkScrolledView, gtk_scrolled_view, + GTK_TYPE_SCROLLED_WINDOW) + +static void +gtk_scrolled_view_class_init (GtkScrolledViewClass *class) +{ + GtkWidgetClass *widget_class = (GtkWidgetClass*) class; + + widget_class->get_preferred_width = gtk_scrolled_window_get_preferred_width; + widget_class->get_preferred_height = gtk_scrolled_window_get_preferred_height; + widget_class->get_preferred_height_for_width = gtk_scrolled_window_get_preferred_height_for_width; + widget_class->get_preferred_width_for_height = gtk_scrolled_window_get_preferred_width_for_height; +} + +static void +gtk_scrolled_view_init (GtkScrolledView *scrolled_view) +{ + g_assert (GTK_SCROLLED_WINDOW (scrolled_view) ->priv != NULL); +} + +/** + * gtk_scrolled_view_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_scrolled_view_new (GtkAdjustment *hadjustment, + GtkAdjustment *vadjustment) +{ + GtkWidget *scrolled_view; + + if (hadjustment) + g_return_val_if_fail (GTK_IS_ADJUSTMENT (hadjustment), NULL); + + if (vadjustment) + g_return_val_if_fail (GTK_IS_ADJUSTMENT (vadjustment), NULL); + + scrolled_view = g_object_new (GTK_TYPE_SCROLLED_VIEW, + "hadjustment", hadjustment, + "vadjustment", vadjustment, + NULL); + + return scrolled_view; +} + +/* The following definitions were copied unchanged from + gtkscrolledwindow.c v3.18.9 unless otherwise noted. The geometry + protocol methods in v3.20.9 now use private gadget functions, but + the v3.18.9 code is still correct, so it is used instead. This + presumably means limited CSS styling for GtkScrolledView (until the + gadget functions are no longer private). + + struct Indicator v3.20.9 + struct _GtkScrolledWindowPrivate v3.20.9 + static gint _gtk_scrolled_window_get_scrollbar_spacing () + static void gtk_scrolled_window_get_preferred_size () PATCHED + static void gtk_scrolled_window_get_preferred_width () + static void gtk_scrolled_window_get_preferred_height () + static void gtk_scrolled_window_get_preferred_height_for_width () + static void gtk_scrolled_window_get_preferred_width_for_height () +*/ + +typedef struct +{ + GtkWidget *scrollbar; + GdkWindow *window; + gboolean over; /* either mouse over, or while dragging */ + gint64 last_scroll_time; + guint conceil_timer; + + gdouble current_pos; + gdouble source_pos; + gdouble target_pos; + gint64 start_time; + gint64 end_time; + guint tick_id; + guint over_timeout_id; +} Indicator; + +typedef long GtkCssGadget; +typedef long GtkCssNode; + +struct _GtkScrolledWindowPrivate +{ + GtkWidget *hscrollbar; + GtkWidget *vscrollbar; + + GtkCssGadget *gadget; + GtkCssNode *overshoot_node[4]; + GtkCssNode *undershoot_node[4]; + + Indicator hindicator; + Indicator vindicator; + + GtkCornerType window_placement; + guint16 shadow_type; + + guint hscrollbar_policy : 2; + guint vscrollbar_policy : 2; + guint hscrollbar_visible : 1; + guint vscrollbar_visible : 1; + guint focus_out : 1; /* used by ::move-focus-out implementation */ + guint overlay_scrolling : 1; + guint use_indicators : 1; + + gint min_content_width; + gint min_content_height; + + guint scroll_events_overshoot_id; + + /* Kinetic scrolling */ + GtkGesture *long_press_gesture; + GtkGesture *swipe_gesture; + + GArray *scroll_history; + GdkDevice *scroll_device; + + /* These two gestures are mutually exclusive */ + GtkGesture *drag_gesture; + GtkGesture *pan_gesture; + + gdouble drag_start_x; + gdouble drag_start_y; + + GdkDevice *drag_device; + guint kinetic_scrolling : 1; + guint capture_button_press : 1; + guint in_drag : 1; + + guint deceleration_id; + + gdouble x_velocity; + gdouble y_velocity; + + gdouble unclamped_hadj_value; + gdouble unclamped_vadj_value; +}; + +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); + + 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_scrolled_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); + GtkWidget *child; + gint min_size, nat_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, &min_size, &nat_size); + if (priv->min_content_width >= 0) + min_size = MAX (min_size, priv->min_content_width); + } + else /* GTK_ORIENTATION_VERTICAL */ + { + gtk_widget_get_preferred_height (child, &min_size, &nat_size); + if (priv->min_content_height >= 0) + min_size = MAX (min_size, priv->min_content_height); + } + } + + if (!priv->use_indicators) + { + if (orientation == GTK_ORIENTATION_HORIZONTAL) + { + if (priv->vscrollbar_policy != GTK_POLICY_NEVER) + { + gint min_width, nat_width; + gint scrollbar_spacing = _gtk_scrolled_window_get_scrollbar_spacing (scrolled_window); + gtk_widget_get_preferred_width (priv->vscrollbar, &min_width, &nat_width); + min_size += MAX (0, scrollbar_spacing + min_width); + nat_size += MAX (0, scrollbar_spacing + nat_width); + } + if (priv->hscrollbar_policy != GTK_POLICY_NEVER) + { + gint min_width, nat_width; + gtk_widget_get_preferred_width (priv->hscrollbar, &min_width, &nat_width); + min_size = MAX (min_size, min_width); + nat_size = MAX (nat_size, nat_width); + } + } + else /* orientation == GTK_ORIENTATION_VERTICAL */ + { + if (priv->hscrollbar_policy != GTK_POLICY_NEVER) + { + gint min_height, nat_height; + gint scrollbar_spacing = _gtk_scrolled_window_get_scrollbar_spacing (scrolled_window); + gtk_widget_get_preferred_height (priv->hscrollbar, &min_height, &nat_height); + min_size += MAX (0, scrollbar_spacing + min_height); + nat_size += MAX (0, scrollbar_spacing + nat_height); + } + if (priv->vscrollbar_policy != GTK_POLICY_NEVER) + { + gint min_height, nat_height; + gtk_widget_get_preferred_height (priv->vscrollbar, &min_height, &nat_height); + min_size = MAX (min_size, min_height); + nat_size = MAX (nat_size, nat_height); + } + } + } + + 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_style_context_get_state (context); + + gtk_style_context_get_padding (context, state, &padding); + gtk_style_context_get_border (context, state, &border); + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + { + min_size += padding.left + padding.right + border.left + border.right; + nat_size += padding.left + padding.right + border.left + border.right; + } + else + { + min_size += padding.top + padding.bottom + border.top + border.bottom; + nat_size += padding.top + padding.bottom + border.top + border.bottom; + } + } + + *minimum_size = min_size; + *natural_size = nat_size; +} + +static void +gtk_scrolled_window_get_preferred_width (GtkWidget *widget, + gint *minimum_size, + gint *natural_size) +{ + gtk_scrolled_window_get_preferred_size (widget, GTK_ORIENTATION_HORIZONTAL, minimum_size, natural_size); +} + +static void +gtk_scrolled_window_get_preferred_height (GtkWidget *widget, + gint *minimum_size, + gint *natural_size) +{ + gtk_scrolled_window_get_preferred_size (widget, GTK_ORIENTATION_VERTICAL, minimum_size, natural_size); +} + +static void +gtk_scrolled_window_get_preferred_height_for_width (GtkWidget *widget, + gint width, + gint *minimum_height, + gint *natural_height) +{ + GTK_WIDGET_GET_CLASS (widget)->get_preferred_height (widget, minimum_height, natural_height); +} + +static void +gtk_scrolled_window_get_preferred_width_for_height (GtkWidget *widget, + gint height, + gint *minimum_width, + gint *natural_width) +{ + GTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget, minimum_width, natural_width); +} -- 2.25.1