aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Eric Janouch <p@janouch.name>2022-07-17 07:15:19 +0200
committerPřemysl Eric Janouch <p@janouch.name>2022-07-17 07:16:41 +0200
commit4efda5347ca1fd06e1edc95b6e5269ba1b10a6bf (patch)
treeeae873bf049c16750293cceceed75b09a9501670
parent23429d9631ed8b94007fa9af49d7ae83c47e419e (diff)
downloadfiv-4efda5347ca1fd06e1edc95b6e5269ba1b10a6bf.tar.gz
fiv-4efda5347ca1fd06e1edc95b6e5269ba1b10a6bf.tar.xz
fiv-4efda5347ca1fd06e1edc95b6e5269ba1b10a6bf.zip
Let FivView take care of its drag gesture
Making the GtkScrolledWindow's scrollbars draggable again.
-rw-r--r--fiv-view.c83
-rw-r--r--fiv.c73
2 files changed, 79 insertions, 77 deletions
diff --git a/fiv-view.c b/fiv-view.c
index 25494b0..1fa4880 100644
--- a/fiv-view.c
+++ b/fiv-view.c
@@ -68,6 +68,7 @@ struct _FivView {
bool enhance : 1; ///< Try to enhance picture data
bool scale_to_fit : 1; ///< Image no larger than the allocation
double scale; ///< Scaling factor
+ double drag_start[2]; ///< Adjustment values for drag origin
cairo_surface_t *enhance_swap; ///< Quick swap in/out
FivIoProfile screen_cms_profile; ///< Target colour profile for widget
@@ -489,8 +490,7 @@ fiv_view_realize(GtkWidget *widget)
// than what we get automatically.
.visual = gtk_widget_get_visual(widget),
- // Pointer motion/release enables attaching GtkGestureDrag to
- // the parent GtkScrolledWindow, having it work with the mouse.
+ // Pointer motion/release enables GtkGestureDrag.
.event_mask = gtk_widget_get_events(widget) | GDK_KEY_PRESS_MASK |
GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
GDK_POINTER_MOTION_MASK,
@@ -621,13 +621,12 @@ fiv_view_draw(GtkWidget *widget, cairo_t *cr)
static gboolean
fiv_view_button_press_event(GtkWidget *widget, GdkEventButton *event)
{
+ // XXX: Return value?
GTK_WIDGET_CLASS(fiv_view_parent_class)->button_press_event(widget, event);
if (event->button == GDK_BUTTON_PRIMARY &&
gtk_widget_get_focus_on_click(widget))
gtk_widget_grab_focus(widget);
-
- // TODO(p): Use for left button scroll drag, which may rather be a gesture.
return FALSE;
}
@@ -830,6 +829,63 @@ fiv_view_unmap(GtkWidget *widget)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static void
+on_drag_begin(GtkGestureDrag *drag, G_GNUC_UNUSED gdouble start_x,
+ G_GNUC_UNUSED gdouble start_y, gpointer user_data)
+{
+ GtkGesture *gesture = GTK_GESTURE(drag);
+ GdkEventSequence *sequence = gtk_gesture_get_last_updated_sequence(gesture);
+ GdkModifierType state = 0;
+ gdk_event_get_state(gtk_gesture_get_last_event(gesture, sequence), &state);
+ if (state & gtk_accelerator_get_default_mod_mask()) {
+ gtk_gesture_set_state(gesture, GTK_EVENT_SEQUENCE_DENIED);
+ return;
+ }
+
+ // Since we set this up as a pointer-only gesture, there is only the NULL
+ // sequence, so gtk_gesture_set_sequence_state() is completely unneeded.
+ gtk_gesture_set_state(gesture, GTK_EVENT_SEQUENCE_CLAIMED);
+
+ GdkWindow *window = gtk_widget_get_window(
+ gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(drag)));
+ GdkCursor *cursor =
+ gdk_cursor_new_from_name(gdk_window_get_display(window), "grabbing");
+ gdk_window_set_cursor(window, cursor);
+ g_object_unref(cursor);
+
+ FivView *self = FIV_VIEW(user_data);
+ self->drag_start[0] = self->hadjustment ?
+ gtk_adjustment_get_value(self->hadjustment) : 0;
+ self->drag_start[1] = self->vadjustment ?
+ gtk_adjustment_get_value(self->vadjustment) : 0;
+}
+
+static void
+on_drag_update(G_GNUC_UNUSED GtkGestureDrag *drag, gdouble offset_x,
+ gdouble offset_y, gpointer user_data)
+{
+ FivView *self = FIV_VIEW(user_data);
+ if (self->hadjustment) {
+ gtk_adjustment_set_value(
+ self->hadjustment, self->drag_start[0] - offset_x);
+ }
+ if (self->vadjustment) {
+ gtk_adjustment_set_value(
+ self->vadjustment, self->drag_start[1] - offset_y);
+ }
+}
+
+static void
+on_drag_end(GtkGestureDrag *drag, G_GNUC_UNUSED gdouble start_x,
+ G_GNUC_UNUSED gdouble start_y, G_GNUC_UNUSED gpointer user_data)
+{
+ GdkWindow *window = gtk_widget_get_window(
+ gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(drag)));
+ gdk_window_set_cursor(window, NULL);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+static void
show_error_dialog(GtkWindow *parent, GError *error)
{
GtkWidget *dialog = gtk_message_dialog_new(parent, GTK_DIALOG_MODAL,
@@ -1275,6 +1331,25 @@ fiv_view_init(FivView *self)
self->filter = true;
self->checkerboard = false;
self->scale = 1.0;
+
+ GtkGesture *drag = gtk_gesture_drag_new(GTK_WIDGET(self));
+ g_object_set_data_full(
+ G_OBJECT(self), "fiv-view-drag-gesture", drag, g_object_unref);
+ gtk_event_controller_set_propagation_phase(
+ GTK_EVENT_CONTROLLER(drag), GTK_PHASE_BUBBLE);
+
+ // GtkScrolledWindow's internal GtkGestureDrag is set to only look for
+ // touch events (and its "event_controllers" are perfectly private,
+ // so we can't change this), hopefully this is mutually exclusive with that.
+ // Though note that the GdkWindow doesn't register for touch events now.
+ gtk_gesture_single_set_exclusive(GTK_GESTURE_SINGLE(drag), TRUE);
+
+ g_signal_connect(drag, "drag-begin",
+ G_CALLBACK(on_drag_begin), self);
+ g_signal_connect(drag, "drag-update",
+ G_CALLBACK(on_drag_update), self);
+ g_signal_connect(drag, "drag-end",
+ G_CALLBACK(on_drag_end), self);
}
// --- Public interface --------------------------------------------------------
diff --git a/fiv.c b/fiv.c
index af59a72..dccc85f 100644
--- a/fiv.c
+++ b/fiv.c
@@ -1323,61 +1323,6 @@ on_button_press_browser_paned(
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-static void
-on_view_scroller_drag_begin(GtkGestureDrag *self, G_GNUC_UNUSED gdouble start_x,
- G_GNUC_UNUSED gdouble start_y, gpointer user_data)
-{
- GtkGesture *gesture = GTK_GESTURE(self);
- GdkEventSequence *sequence = gtk_gesture_get_last_updated_sequence(gesture);
- GdkModifierType state = 0;
- gdk_event_get_state(gtk_gesture_get_last_event(gesture, sequence), &state);
- if (state & gtk_accelerator_get_default_mod_mask()) {
- gtk_gesture_set_state(gesture, GTK_EVENT_SEQUENCE_DENIED);
- return;
- }
-
- // Since we set this up as a pointer-only gesture, there is only the NULL
- // sequence, so gtk_gesture_set_sequence_state() is completely unneeded.
- gtk_gesture_set_state(gesture, GTK_EVENT_SEQUENCE_CLAIMED);
-
- GdkWindow *window = gtk_widget_get_window(
- gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(self)));
- GdkCursor *cursor =
- gdk_cursor_new_from_name(gdk_window_get_display(window), "grabbing");
- gdk_window_set_cursor(window, cursor);
- g_object_unref(cursor);
-
- double *init = user_data;
- GtkScrolledWindow *sw = GTK_SCROLLED_WINDOW(
- gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(self)));
- init[0] = gtk_adjustment_get_value(gtk_scrolled_window_get_hadjustment(sw));
- init[1] = gtk_adjustment_get_value(gtk_scrolled_window_get_vadjustment(sw));
-}
-
-static void
-on_view_scroller_drag(GtkGestureDrag *self, gdouble offset_x, gdouble offset_y,
- gpointer user_data)
-{
- const double *init = user_data;
- GtkScrolledWindow *sw = GTK_SCROLLED_WINDOW(
- gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(self)));
- gtk_adjustment_set_value(
- gtk_scrolled_window_get_hadjustment(sw), init[0] - offset_x);
- gtk_adjustment_set_value(
- gtk_scrolled_window_get_vadjustment(sw), init[1] - offset_y);
-}
-
-static void
-on_view_scroller_drag_end(GtkGestureDrag *self, G_GNUC_UNUSED gdouble start_x,
- G_GNUC_UNUSED gdouble start_y, G_GNUC_UNUSED gpointer user_data)
-{
- GdkWindow *window = gtk_widget_get_window(
- gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(self)));
- gdk_window_set_cursor(window, NULL);
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
static GtkWidget *
make_toolbar_button(const char *symbolic, const char *tooltip)
{
@@ -1948,24 +1893,6 @@ main(int argc, char *argv[])
G_CALLBACK(on_view_drag_data_received), NULL);
gtk_container_add(GTK_CONTAINER(view_scroller), g.view);
- GtkGesture *drag = gtk_gesture_drag_new(view_scroller);
- gtk_event_controller_set_propagation_phase(
- GTK_EVENT_CONTROLLER(drag), GTK_PHASE_CAPTURE);
-
- // GtkScrolledWindow's internal GtkGestureDrag is set to only look for
- // touch events (and its "event_controllers" are perfectly private,
- // so we can't change this), hopefully this is mutually exclusive with that.
- // Though note that the GdkWindow doesn't register for touch events now.
- gtk_gesture_single_set_exclusive(GTK_GESTURE_SINGLE(drag), TRUE);
-
- double init_drag_values[2] = {};
- g_signal_connect(drag, "drag-begin",
- G_CALLBACK(on_view_scroller_drag_begin), init_drag_values);
- g_signal_connect(drag, "drag-update",
- G_CALLBACK(on_view_scroller_drag), init_drag_values);
- g_signal_connect(drag, "drag-end",
- G_CALLBACK(on_view_scroller_drag_end), init_drag_values);
-
// We need to hide it together with the separator.
g.view_toolbar = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_box_pack_start(GTK_BOX(g.view_toolbar),