Let FivView take care of its drag gesture
Making the GtkScrolledWindow's scrollbars draggable again.
This commit is contained in:
parent
23429d9631
commit
4efda5347c
83
fiv-view.c
83
fiv-view.c
|
@ -68,6 +68,7 @@ struct _FivView {
|
||||||
bool enhance : 1; ///< Try to enhance picture data
|
bool enhance : 1; ///< Try to enhance picture data
|
||||||
bool scale_to_fit : 1; ///< Image no larger than the allocation
|
bool scale_to_fit : 1; ///< Image no larger than the allocation
|
||||||
double scale; ///< Scaling factor
|
double scale; ///< Scaling factor
|
||||||
|
double drag_start[2]; ///< Adjustment values for drag origin
|
||||||
|
|
||||||
cairo_surface_t *enhance_swap; ///< Quick swap in/out
|
cairo_surface_t *enhance_swap; ///< Quick swap in/out
|
||||||
FivIoProfile screen_cms_profile; ///< Target colour profile for widget
|
FivIoProfile screen_cms_profile; ///< Target colour profile for widget
|
||||||
|
@ -489,8 +490,7 @@ fiv_view_realize(GtkWidget *widget)
|
||||||
// than what we get automatically.
|
// than what we get automatically.
|
||||||
.visual = gtk_widget_get_visual(widget),
|
.visual = gtk_widget_get_visual(widget),
|
||||||
|
|
||||||
// Pointer motion/release enables attaching GtkGestureDrag to
|
// Pointer motion/release enables GtkGestureDrag.
|
||||||
// the parent GtkScrolledWindow, having it work with the mouse.
|
|
||||||
.event_mask = gtk_widget_get_events(widget) | GDK_KEY_PRESS_MASK |
|
.event_mask = gtk_widget_get_events(widget) | GDK_KEY_PRESS_MASK |
|
||||||
GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
|
GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
|
||||||
GDK_POINTER_MOTION_MASK,
|
GDK_POINTER_MOTION_MASK,
|
||||||
|
@ -621,13 +621,12 @@ fiv_view_draw(GtkWidget *widget, cairo_t *cr)
|
||||||
static gboolean
|
static gboolean
|
||||||
fiv_view_button_press_event(GtkWidget *widget, GdkEventButton *event)
|
fiv_view_button_press_event(GtkWidget *widget, GdkEventButton *event)
|
||||||
{
|
{
|
||||||
|
// XXX: Return value?
|
||||||
GTK_WIDGET_CLASS(fiv_view_parent_class)->button_press_event(widget, event);
|
GTK_WIDGET_CLASS(fiv_view_parent_class)->button_press_event(widget, event);
|
||||||
|
|
||||||
if (event->button == GDK_BUTTON_PRIMARY &&
|
if (event->button == GDK_BUTTON_PRIMARY &&
|
||||||
gtk_widget_get_focus_on_click(widget))
|
gtk_widget_get_focus_on_click(widget))
|
||||||
gtk_widget_grab_focus(widget);
|
gtk_widget_grab_focus(widget);
|
||||||
|
|
||||||
// TODO(p): Use for left button scroll drag, which may rather be a gesture.
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -829,6 +828,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
|
static void
|
||||||
show_error_dialog(GtkWindow *parent, GError *error)
|
show_error_dialog(GtkWindow *parent, GError *error)
|
||||||
{
|
{
|
||||||
|
@ -1275,6 +1331,25 @@ fiv_view_init(FivView *self)
|
||||||
self->filter = true;
|
self->filter = true;
|
||||||
self->checkerboard = false;
|
self->checkerboard = false;
|
||||||
self->scale = 1.0;
|
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 --------------------------------------------------------
|
// --- Public interface --------------------------------------------------------
|
||||||
|
|
73
fiv.c
73
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 *
|
static GtkWidget *
|
||||||
make_toolbar_button(const char *symbolic, const char *tooltip)
|
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);
|
G_CALLBACK(on_view_drag_data_received), NULL);
|
||||||
gtk_container_add(GTK_CONTAINER(view_scroller), g.view);
|
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.
|
// We need to hide it together with the separator.
|
||||||
g.view_toolbar = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
g.view_toolbar = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
||||||
gtk_box_pack_start(GTK_BOX(g.view_toolbar),
|
gtk_box_pack_start(GTK_BOX(g.view_toolbar),
|
||||||
|
|
Loading…
Reference in New Issue