Commit 5ec56d2e authored by Matthias Clasen's avatar Matthias Clasen

Port the overlayscroll example

Make the overlayscroll example use the overlay scrolling that is
now built into GtkScrolledWindow, instead of the manual prototype.
parent 47ce0111
......@@ -18,233 +18,6 @@
#include <gtk/gtk.h>
#include <string.h>
typedef struct {
GtkWidget *sw;
GtkWidget *rv;
gint64 last_scroll_time;
gboolean over;
gboolean dragging;
gboolean autodetect;
gboolean touch_mode;
} IndicatorData;
IndicatorData *
get_indicator_data (GtkWidget *sb)
{
IndicatorData *data;
data = (IndicatorData *) g_object_get_data (G_OBJECT (sb), "indicator-data");
if (!data)
{
data = g_new0 (IndicatorData, 1);
g_object_set_data_full (G_OBJECT (sb), "indicator-data", data, g_free);
}
return data;
}
static gboolean
conceil_scrollbar (gpointer data)
{
GtkWidget *sb = data;
IndicatorData *id = get_indicator_data (sb);
if (g_get_monotonic_time () - id->last_scroll_time >= 1000000 &&
id->touch_mode &&
!id->over &&
!id->dragging)
{
if (gtk_revealer_get_reveal_child (GTK_REVEALER (id->rv)))
gtk_revealer_set_reveal_child (GTK_REVEALER (id->rv), FALSE);
}
return G_SOURCE_CONTINUE;
}
static void
value_changed (GtkAdjustment *adj, GtkWidget *sb)
{
IndicatorData *id = get_indicator_data (sb);
if (id->touch_mode &&
!gtk_revealer_get_reveal_child (GTK_REVEALER (id->rv)))
gtk_revealer_set_reveal_child (GTK_REVEALER (id->rv), TRUE);
id->last_scroll_time = g_get_monotonic_time ();
}
static gboolean
enter_notify (GtkWidget *sb, GdkEventCrossing *event)
{
GtkStyleContext *context = gtk_widget_get_style_context (sb);
IndicatorData *id = get_indicator_data (sb);
gtk_style_context_add_class (context, "locked");
gtk_widget_queue_resize (sb);
id->over = TRUE;
return G_SOURCE_CONTINUE;
}
static gboolean
leave_notify (GtkWidget *sb, GdkEventCrossing *event)
{
GtkStyleContext *context = gtk_widget_get_style_context (sb);
IndicatorData *id = get_indicator_data (sb);
gtk_style_context_remove_class (context, "locked");
gtk_widget_queue_resize (sb);
id->over = FALSE;
return G_SOURCE_CONTINUE;
}
static void
style_changed (GtkStyleContext *context, GtkWidget *sb)
{
IndicatorData *id = get_indicator_data (sb);
if (gtk_style_context_has_class (context, "dragging"))
id->dragging = TRUE;
else
id->dragging = FALSE;
}
static const gchar *
input_source (GdkInputSource source)
{
switch (source)
{
case GDK_SOURCE_MOUSE: return "mouse";
case GDK_SOURCE_PEN: return "pen";
case GDK_SOURCE_ERASER: return "eraser";
case GDK_SOURCE_CURSOR: return "cursor";
case GDK_SOURCE_KEYBOARD: return "keyboard";
case GDK_SOURCE_TOUCHSCREEN: return "touchscreen";
case GDK_SOURCE_TOUCHPAD: return "touchpad";
default: return "unknown";
}
}
static void
list_devices (GdkDeviceManager *dm)
{
GList *devices, *l;
GList *slaves, *s;
GdkDevice *device;
devices = gdk_device_manager_list_devices (dm, GDK_DEVICE_TYPE_MASTER);
for (l = devices; l; l = l->next)
{
device = l->data;
g_print ("%s%s\n",
gdk_device_get_name (device),
gdk_device_get_has_cursor (device) ? ", has cursor" : "");
slaves = gdk_device_list_slave_devices (device);
for (s = slaves; s; s = s->next)
{
device = s->data;
g_print (" ↳ %s, %s\n",
gdk_device_get_name (device),
input_source (gdk_device_get_source (device)));
}
g_list_free (slaves);
}
g_list_free (devices);
}
static gboolean
has_mouse (GdkDeviceManager *dm)
{
GdkDevice *cp;
GList *slaves, *s;
GdkDevice *device;
gboolean found;
found = FALSE;
cp = gdk_device_manager_get_client_pointer (dm);
slaves = gdk_device_list_slave_devices (cp);
for (s = slaves; s; s = s->next)
{
device = s->data;
if (gdk_device_get_source (device) != GDK_SOURCE_MOUSE)
continue;
if (strstr (gdk_device_get_name (device), "XTEST"))
continue;
if (strstr (gdk_device_get_name (device), "TrackPoint"))
continue;
if (g_object_get_data (G_OBJECT (device), "removed"))
continue;
found = TRUE;
break;
}
g_list_free (slaves);
return found;
}
static void
update_touch_mode (IndicatorData *id, gboolean touch_mode)
{
id->touch_mode = touch_mode;
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (id->sw),
GTK_POLICY_NEVER,
id->touch_mode ? GTK_POLICY_EXTERNAL : GTK_POLICY_AUTOMATIC);
g_print ("touch mode now %s\n", id->touch_mode ? "ON" : "OFF");
}
static void
device_added (GdkDeviceManager *dm, GdkDevice *device, IndicatorData *id)
{
if (id->autodetect)
update_touch_mode (id, !has_mouse (dm));
}
static void
device_removed (GdkDeviceManager *dm, GdkDevice *device, IndicatorData *id)
{
if (id->autodetect)
{
/* We need to work around the fact that ::device-removed is emitted
* before the device is removed from the list.
*/
g_object_set_data (G_OBJECT (device), "removed", GINT_TO_POINTER (1));
update_touch_mode (id, !has_mouse (dm));
}
}
static void
mode_changed (GtkComboBox *combo, IndicatorData *id)
{
GdkDeviceManager *dm;
gint active = gtk_combo_box_get_active (combo);
dm = gdk_display_get_device_manager (gdk_display_get_default ());
if (active == 0)
{
id->autodetect = TRUE;
update_touch_mode (id, !has_mouse (dm));
}
else if (active == 1)
{
id->autodetect = FALSE;
update_touch_mode (id, FALSE);
}
else
{
id->autodetect = FALSE;
update_touch_mode (id, TRUE);
}
}
static gchar *
get_content (void)
{
......@@ -258,21 +31,13 @@ get_content (void)
return g_string_free (s, FALSE);
}
static const gchar data[] =
".scrollbar.overlay-indicator.dragging,"
".scrollbar.overlay-indicator.locked {"
" -GtkRange-slider-width: 15;"
"}"
".scrollbar.overlay-indicator.dragging.trough,"
".scrollbar.overlay-indicator.locked.trough {"
" background-color: alpha(black,0.1);"
"}"
".scrollbar.overlay-indicator {"
" -GtkRange-slider-width: 10;"
"}"
".scrollbar.overlay-indicator.trough {"
" background-color: transparent;"
"}";
static void
mode_changed (GtkComboBox *combo, GtkScrolledWindow *sw)
{
gint active = gtk_combo_box_get_active (combo);
gtk_scrolled_window_set_overlay_scrolling (sw, active == 1);
}
int
main (int argc, char *argv[])
......@@ -282,24 +47,12 @@ main (int argc, char *argv[])
GtkWidget *box;
GtkWidget *sw;
GtkWidget *tv;
GtkWidget *ov;
GtkWidget *rv;
GtkWidget *sb;
GtkWidget *sb2;
GtkWidget *combo;
GtkAdjustment *adj;
GtkCssProvider *provider;
IndicatorData *id;
GdkDeviceManager *dm;
gtk_init (&argc, &argv);
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_data (provider, data, -1, NULL);
gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW (window), 640, 480);
g_signal_connect (window, "delete-event", G_CALLBACK (gtk_main_quit), NULL);
......@@ -307,15 +60,12 @@ main (int argc, char *argv[])
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 20);
gtk_container_add (GTK_CONTAINER (window), box);
ov = gtk_overlay_new ();
gtk_box_pack_start (GTK_BOX (box), ov, TRUE, TRUE, 0);
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_NEVER,
GTK_POLICY_EXTERNAL);
GTK_POLICY_AUTOMATIC);
gtk_container_add (GTK_CONTAINER (ov), sw);
gtk_box_pack_start (GTK_BOX (box), sw, TRUE, TRUE, 0);
content = get_content ();
......@@ -328,34 +78,12 @@ main (int argc, char *argv[])
adj = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (tv));
sb = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL, adj);
rv = gtk_revealer_new ();
gtk_revealer_set_transition_type (GTK_REVEALER (rv), GTK_REVEALER_TRANSITION_TYPE_CROSSFADE);
gtk_revealer_set_transition_duration (GTK_REVEALER (rv), 750);
gtk_container_add (GTK_CONTAINER (rv), sb);
gtk_overlay_add_overlay (GTK_OVERLAY (ov), rv);
gtk_widget_set_halign (rv, GTK_ALIGN_END);
gtk_widget_set_valign (rv, GTK_ALIGN_FILL);
id = get_indicator_data (sb);
id->sw = sw;
id->rv = rv;
gtk_style_context_add_class (gtk_widget_get_style_context (sb), "overlay-indicator");
g_signal_connect (sb, "enter-notify-event", G_CALLBACK (enter_notify), NULL);
g_signal_connect (sb, "leave-notify-event", G_CALLBACK (leave_notify), NULL);
g_signal_connect (gtk_widget_get_style_context (sb), "changed", G_CALLBACK (style_changed), sb);
g_signal_connect (adj, "value-changed", G_CALLBACK (value_changed), sb);
g_timeout_add (500, conceil_scrollbar, sb);
combo = gtk_combo_box_text_new ();
gtk_widget_set_valign (combo, GTK_ALIGN_START);
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "Autodetect");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "Mouse mode");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "Touch mode");
g_signal_connect (combo, "changed", G_CALLBACK (mode_changed), id);
gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "Traditional");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "Overlay");
g_signal_connect (combo, "changed", G_CALLBACK (mode_changed), sw);
gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 1);
gtk_container_add (GTK_CONTAINER (box), combo);
......@@ -364,12 +92,6 @@ main (int argc, char *argv[])
gtk_widget_show_all (window);
dm = gdk_display_get_device_manager (gdk_display_get_default ());
list_devices (dm);
g_signal_connect (dm, "device-added", G_CALLBACK (device_added), id);
g_signal_connect (dm, "device-removed", G_CALLBACK (device_removed), id);
gtk_main ();
return 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment