summaryrefslogtreecommitdiff
path: root/settings-dialogs
diff options
context:
space:
mode:
authorViktor Odintsev <zakhams@gmail.com>2017-06-28 22:57:26 +0300
committerViktor Odintsev <ninetls@xfce.org>2017-06-28 22:57:26 +0300
commit473ef8458b4e31711cbf2f7675d6bf0bbba52df5 (patch)
treee14748523e44b2d2df8b6683106ce8ca257f19a4 /settings-dialogs
parent4c101f9b807fbd5e1067ca7254740a4ef1744e68 (diff)
downloadxfwm4-473ef8458b4e31711cbf2f7675d6bf0bbba52df5.tar.gz
Implement RangeDebouncer
This object allows to easily listen GtkRange value when drag was finished. This was allowed in GTK2 with "update-policy" attribute set to "discontinuous" which was removed in GTK3.
Diffstat (limited to 'settings-dialogs')
-rw-r--r--settings-dialogs/Makefile.am4
-rw-r--r--settings-dialogs/range-debouncer.c232
-rw-r--r--settings-dialogs/range-debouncer.h44
-rw-r--r--settings-dialogs/tweaks-settings.c11
-rw-r--r--settings-dialogs/xfwm4-settings.c9
5 files changed, 291 insertions, 9 deletions
diff --git a/settings-dialogs/Makefile.am b/settings-dialogs/Makefile.am
index 4d96f2c3e..f477c605d 100644
--- a/settings-dialogs/Makefile.am
+++ b/settings-dialogs/Makefile.am
@@ -36,6 +36,8 @@ xfwm4_settings_SOURCES = \
xfwm4-settings.c \
xfwm4-settings.h \
xfwm4-dialog_ui.h \
+ range-debouncer.c \
+ range-debouncer.h \
common.c \
common.h
@@ -61,6 +63,8 @@ xfwm4_settings_LDADD = \
xfwm4_tweaks_settings_SOURCES = \
tweaks-settings.c \
xfwm4-tweaks-dialog_ui.h \
+ range-debouncer.c \
+ range-debouncer.h \
common.c \
common.h
diff --git a/settings-dialogs/range-debouncer.c b/settings-dialogs/range-debouncer.c
new file mode 100644
index 000000000..571670bb1
--- /dev/null
+++ b/settings-dialogs/range-debouncer.c
@@ -0,0 +1,232 @@
+/* vi:set sw=2 sts=2 ts=2 et ai tw=100: */
+/*-
+ * Copyright (c) 2017 Viktor Odintsev <zakhams@gmail.com>
+ *
+ * This program 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 program 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 program; if not, write to the Free Software
+ * Foundation, Inc., Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include "range-debouncer.h"
+
+
+
+struct _RangeDebouncerClass
+{
+ GObjectClass __parent__;
+};
+
+struct _RangeDebouncer
+{
+ GObject __parent__;
+
+ GtkRange *range;
+ gboolean pressed : 1;
+
+ gulong signal1;
+ gulong signal2;
+ gulong signal3;
+};
+
+enum
+{
+ PROP_0,
+ PROP_VALUE,
+ N_PROPERTIES,
+};
+
+static void range_debouncer_finalize (GObject *object);
+static void range_debouncer_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void range_debouncer_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+
+static void range_debouncer_weak_notify (RangeDebouncer *range_debouncer);
+
+static void range_debouncer_value_changed (RangeDebouncer *range_debouncer);
+static gboolean range_debouncer_button_pressed (RangeDebouncer *range_debouncer);
+static gboolean range_debouncer_button_released (RangeDebouncer *range_debouncer);
+
+G_DEFINE_TYPE (RangeDebouncer, range_debouncer, G_TYPE_OBJECT)
+
+
+
+static void
+range_debouncer_class_init (RangeDebouncerClass *klass)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = range_debouncer_finalize;
+ gobject_class->get_property = range_debouncer_get_property;
+ gobject_class->set_property = range_debouncer_set_property;
+
+ g_object_class_install_property (gobject_class, PROP_VALUE,
+ g_param_spec_double ("value", NULL, NULL,
+ -G_MAXDOUBLE, G_MAXDOUBLE, 0,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+}
+
+
+
+static void
+range_debouncer_init (RangeDebouncer *range_debouncer)
+{
+ range_debouncer->range = NULL;
+ range_debouncer->pressed = FALSE;
+
+ range_debouncer->signal1 = 0;
+ range_debouncer->signal2 = 0;
+ range_debouncer->signal3 = 0;
+}
+
+
+
+RangeDebouncer *
+range_debouncer_bind (GtkRange *range)
+{
+ RangeDebouncer *range_debouncer;
+
+ g_return_val_if_fail (GTK_IS_RANGE (range), NULL);
+
+ range_debouncer = g_object_new (TYPE_RANGE_DEBOUNCER, NULL);
+ range_debouncer->range = range;
+
+ /* RangeDebouncer will be destroyed with GtkRange */
+ g_object_weak_ref (G_OBJECT (range), (GWeakNotify)range_debouncer_weak_notify, range_debouncer);
+
+ range_debouncer->signal1 =
+ g_signal_connect_swapped (range, "value-changed",
+ G_CALLBACK (range_debouncer_value_changed), range_debouncer);
+ range_debouncer->signal2 =
+ g_signal_connect_swapped (range, "button-press-event",
+ G_CALLBACK (range_debouncer_button_pressed), range_debouncer);
+ range_debouncer->signal3 =
+ g_signal_connect_swapped (range, "button-release-event",
+ G_CALLBACK (range_debouncer_button_released), range_debouncer);
+
+ return range_debouncer;
+}
+
+
+
+static void
+range_debouncer_finalize (GObject *object)
+{
+ RangeDebouncer *range_debouncer = RANGE_DEBOUNCER (object);
+
+ if (G_UNLIKELY (range_debouncer->range != NULL))
+ {
+ g_signal_handler_disconnect(range_debouncer->range, range_debouncer->signal1);
+ g_signal_handler_disconnect(range_debouncer->range, range_debouncer->signal2);
+ g_signal_handler_disconnect(range_debouncer->range, range_debouncer->signal3);
+ }
+
+ G_OBJECT_CLASS (range_debouncer_parent_class)->finalize (object);
+}
+
+
+
+static void
+range_debouncer_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ RangeDebouncer *range_debouncer = RANGE_DEBOUNCER (object);
+
+ switch (prop_id)
+ {
+ case PROP_VALUE:
+ if (G_LIKELY (range_debouncer->range != NULL))
+ g_value_set_double (value, gtk_range_get_value (range_debouncer->range));
+ else
+ g_value_set_double (value, 0);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+
+static void
+range_debouncer_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ RangeDebouncer *range_debouncer = RANGE_DEBOUNCER (object);
+ gdouble val_double;
+
+ switch (prop_id)
+ {
+ case PROP_VALUE:
+ val_double = g_value_get_double (value);
+ if (G_LIKELY (range_debouncer->range != NULL) &&
+ gtk_range_get_value (range_debouncer->range) != val_double)
+ {
+ gtk_range_set_value (range_debouncer->range, val_double);
+ g_object_notify (object, "value");
+ }
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+
+static void
+range_debouncer_weak_notify (RangeDebouncer *range_debouncer)
+{
+ range_debouncer->range = NULL;
+ g_object_unref (range_debouncer);
+}
+
+
+
+static void
+range_debouncer_value_changed (RangeDebouncer *range_debouncer)
+{
+ if (!range_debouncer->pressed)
+ g_object_notify (G_OBJECT (range_debouncer), "value");
+}
+
+
+
+static gboolean
+range_debouncer_button_pressed (RangeDebouncer *range_debouncer)
+{
+ range_debouncer->pressed = TRUE;
+ return FALSE;
+}
+
+
+
+static gboolean
+range_debouncer_button_released (RangeDebouncer *range_debouncer)
+{
+ range_debouncer->pressed = FALSE;
+ g_object_notify (G_OBJECT (range_debouncer), "value");
+ return FALSE;
+}
diff --git a/settings-dialogs/range-debouncer.h b/settings-dialogs/range-debouncer.h
new file mode 100644
index 000000000..4db04b4c2
--- /dev/null
+++ b/settings-dialogs/range-debouncer.h
@@ -0,0 +1,44 @@
+/* vi:set sw=2 sts=2 ts=2 et ai tw=100: */
+/*-
+ * Copyright (c) 2017 Viktor Odintsev <zakhams@gmail.com>
+ *
+ * This program 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 program 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 program; if not, write to the Free Software
+ * Foundation, Inc., Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifndef __RANGE_DEBOUNCER_H__
+#define __RANGE_DEBOUNCER_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+typedef struct _RangeDebouncerClass RangeDebouncerClass;
+typedef struct _RangeDebouncer RangeDebouncer;
+
+#define TYPE_RANGE_DEBOUNCER (range_debouncer_get_type ())
+#define RANGE_DEBOUNCER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_RANGE_DEBOUNCER, RangeDebouncer))
+#define RANGE_DEBOUNCER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_RANGE_DEBOUNCER, RangeDebouncerClass))
+#define IS_RANGE_DEBOUNCER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_RANGE_DEBOUNCER))
+#define IS_RANGE_DEBOUNCER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_RANGE_DEBOUNCER))
+#define RANGE_DEBOUNCER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_RANGE_DEBOUNCER, RangeDebouncerClass))
+
+GType range_debouncer_get_type (void) G_GNUC_CONST;
+
+RangeDebouncer * range_debouncer_bind (GtkRange *range);
+
+G_END_DECLS
+
+#endif /* __RANGE_DEBOUNCER_H__ */
diff --git a/settings-dialogs/tweaks-settings.c b/settings-dialogs/tweaks-settings.c
index d3b45c5dd..1ed110941 100644
--- a/settings-dialogs/tweaks-settings.c
+++ b/settings-dialogs/tweaks-settings.c
@@ -44,6 +44,7 @@
#include <xfconf/xfconf.h>
#include "xfwm4-tweaks-dialog_ui.h"
+#include "range-debouncer.h"
#include "common.h"
static Window opt_socket_id = 0;
@@ -420,23 +421,23 @@ wm_tweaks_dialog_configure_widgets (GtkBuilder *builder)
xfconf_g_property_bind (xfwm4_channel,
"/general/frame_opacity",
G_TYPE_INT,
- (GObject *) gtk_range_get_adjustment (GTK_RANGE (frame_opacity_scale)), "value");
+ (GObject *) range_debouncer_bind (GTK_RANGE (frame_opacity_scale)), "value");
xfconf_g_property_bind (xfwm4_channel,
"/general/resize_opacity",
G_TYPE_INT,
- (GObject *) gtk_range_get_adjustment (GTK_RANGE (resize_opacity_scale)), "value");
+ (GObject *) range_debouncer_bind (GTK_RANGE (resize_opacity_scale)), "value");
xfconf_g_property_bind (xfwm4_channel,
"/general/move_opacity",
G_TYPE_INT,
- (GObject *) gtk_range_get_adjustment (GTK_RANGE (move_opacity_scale)), "value");
+ (GObject *) range_debouncer_bind (GTK_RANGE (move_opacity_scale)), "value");
xfconf_g_property_bind (xfwm4_channel,
"/general/inactive_opacity",
G_TYPE_INT,
- (GObject *) gtk_range_get_adjustment (GTK_RANGE (inactive_opacity_scale)), "value");
+ (GObject *) range_debouncer_bind (GTK_RANGE (inactive_opacity_scale)), "value");
xfconf_g_property_bind (xfwm4_channel,
"/general/popup_opacity",
G_TYPE_INT,
- (GObject *) gtk_range_get_adjustment (GTK_RANGE (popup_opacity_scale)), "value");
+ (GObject *) range_debouncer_bind (GTK_RANGE (popup_opacity_scale)), "value");
vbox = GTK_WIDGET (gtk_builder_get_object (builder, "main-vbox"));
gtk_widget_show_all (vbox);
diff --git a/settings-dialogs/xfwm4-settings.c b/settings-dialogs/xfwm4-settings.c
index 45daa35c1..094b3044b 100644
--- a/settings-dialogs/xfwm4-settings.c
+++ b/settings-dialogs/xfwm4-settings.c
@@ -48,6 +48,7 @@
#include "xfwm4-dialog_ui.h"
#include "xfwm4-settings.h"
+#include "range-debouncer.h"
#include "common.h"
@@ -561,9 +562,9 @@ xfwm_settings_constructed (GObject *object)
/* Focus tab */
xfconf_g_property_bind (settings->priv->wm_channel, "/general/focus_delay", G_TYPE_INT,
- gtk_range_get_adjustment (GTK_RANGE (focus_delay_scale)), "value");
+ range_debouncer_bind (GTK_RANGE (focus_delay_scale)), "value");
xfconf_g_property_bind (settings->priv->wm_channel, "/general/raise_delay", G_TYPE_INT,
- gtk_range_get_adjustment (GTK_RANGE (focus_raise_delay_scale)), "value");
+ range_debouncer_bind (GTK_RANGE (focus_raise_delay_scale)), "value");
xfconf_g_property_bind (settings->priv->wm_channel, "/general/raise_on_click", G_TYPE_BOOLEAN,
raise_on_click_check, "active");
xfconf_g_property_bind (settings->priv->wm_channel, "/general/raise_on_focus", G_TYPE_BOOLEAN,
@@ -630,9 +631,9 @@ xfwm_settings_constructed (GObject *object)
/* Advanced tab */
xfconf_g_property_bind (settings->priv->wm_channel, "/general/snap_width", G_TYPE_INT,
- gtk_range_get_adjustment (GTK_RANGE (snap_width_scale)), "value");
+ range_debouncer_bind (GTK_RANGE (snap_width_scale)), "value");
xfconf_g_property_bind (settings->priv->wm_channel, "/general/wrap_resistance", G_TYPE_INT,
- gtk_range_get_adjustment (GTK_RANGE (wrap_resistance_scale)), "value");
+ range_debouncer_bind (GTK_RANGE (wrap_resistance_scale)), "value");
xfconf_g_property_bind (settings->priv->wm_channel, "/general/box_move", G_TYPE_BOOLEAN,
box_move_check, "active");
xfconf_g_property_bind (settings->priv->wm_channel, "/general/box_resize", G_TYPE_BOOLEAN,