From 67f3422a4c4839dedd551a37b5142dc477661e55 Mon Sep 17 00:00:00 2001 From: Diederik ter Rahe Date: Thu, 1 Aug 2024 09:21:17 -0400 Subject: [PATCH] convert bauhaus and iop graphs to gtkgestures prep for gtk4 --- src/bauhaus/bauhaus.c | 121 ++++++++++++++++--------------- src/develop/imageop.c | 64 +++++++++-------- src/dtgtk/thumbnail.c | 102 +++++++++++--------------- src/gui/gtk.c | 31 ++++++++ src/gui/gtk.h | 24 +++++++ src/iop/atrous.c | 101 ++++++++++++-------------- src/iop/basecurve.c | 89 ++++++++++++----------- src/iop/colorchecker.c | 65 +++++++++-------- src/iop/colorcorrection.c | 62 ++++++++-------- src/iop/colorequal.c | 79 ++++++++------------ src/iop/colorzones.c | 118 +++++++++++++++--------------- src/iop/denoiseprofile.c | 71 ++++++++---------- src/iop/filmicrgb.c | 72 ++++++++----------- src/iop/levels.c | 109 +++++++++++++++------------- src/iop/lowlight.c | 69 +++++++++--------- src/iop/monochrome.c | 104 +++++++++++++-------------- src/iop/rawdenoise.c | 64 ++++++++--------- src/iop/rgbcurve.c | 148 ++++++++++++++++++-------------------- src/iop/rgblevels.c | 111 +++++++++++++--------------- src/iop/tonecurve.c | 109 ++++++++++++++-------------- src/iop/toneequal.c | 107 +++++++++++---------------- src/iop/zonesystem.c | 87 +++++++++++----------- 22 files changed, 931 insertions(+), 976 deletions(-) diff --git a/src/bauhaus/bauhaus.c b/src/bauhaus/bauhaus.c index a398d2bfc597..6c873414b1f3 100644 --- a/src/bauhaus/bauhaus.c +++ b/src/bauhaus/bauhaus.c @@ -69,9 +69,9 @@ static gboolean _popup_key_press(GtkWidget *widget, GdkEventKey *event, gpointer static gboolean _widget_draw(GtkWidget *widget, cairo_t *crf); static gboolean _widget_scroll(GtkWidget *widget, GdkEventScroll *event); static gboolean _widget_key_press(GtkWidget *widget, GdkEventKey *event); -static gboolean _widget_button_press(GtkWidget *widget, GdkEventButton *event); -static gboolean _widget_button_release(GtkWidget *widget, GdkEventButton *event); -static gboolean _widget_motion_notify(GtkWidget *widget, GdkEventMotion *event); +static void _widget_button_press(GtkGestureSingle*, int, double, double, GtkWidget*); +static void _widget_button_release(GtkGestureSingle*, int, double, double, GtkWidget*); +static void _widget_motion(GtkEventControllerMotion*, double, double, GtkWidget*); static void _widget_get_preferred_width(GtkWidget *widget, gint *minimum_size, gint *natural_size); @@ -642,10 +642,30 @@ static void _window_show(GtkWidget *w, gpointer user_data) gtk_grab_add(GTK_WIDGET(user_data)); } +static void _widget_leave(GtkEventControllerMotion *controller, + GtkWidget *widget) +{ + if(controller == NULL) + // gtk_widget_set_state_flags triggers resize&draw avalanche + // instead add GTK_STATE_FLAG_PRELIGHT in _widget_draw + darktable.bauhaus->hovered = widget; + else + darktable.bauhaus->hovered = NULL; + + gtk_widget_queue_draw(widget); +} + +static void _widget_enter(GtkEventControllerMotion *controller, + double x, + double y, + GtkWidget *widget) +{ + _widget_leave(NULL, widget); +} + static void dt_bh_init(DtBauhausWidget *w) { w->field = NULL; - w->section = NULL; // no quad icon and no toggle button: @@ -655,30 +675,18 @@ static void dt_bh_init(DtBauhausWidget *w) w->show_quad = TRUE; w->show_label = TRUE; - gtk_widget_add_events(GTK_WIDGET(w), GDK_POINTER_MOTION_MASK - | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK - | GDK_FOCUS_CHANGE_MASK + if(darktable.control->accel_initialising) return; + + gtk_widget_add_events(GTK_WIDGET(w), GDK_FOCUS_CHANGE_MASK | darktable.gui->scroll_mask); + dt_gui_connect_click_all(w, _widget_button_press, _widget_button_release, w); + dt_gui_connect_motion(w, _widget_motion, _widget_enter, _widget_leave, w); + gtk_widget_set_can_focus(GTK_WIDGET(w), TRUE); dt_gui_add_class(GTK_WIDGET(w), "dt_bauhaus"); } -static gboolean _widget_enter_leave(GtkWidget *widget, GdkEventCrossing *event) -{ - if(event->type == GDK_ENTER_NOTIFY) - // gtk_widget_set_state_flags triggers resize&draw avalanche - // instead add GTK_STATE_FLAG_PRELIGHT in _widget_draw - darktable.bauhaus->hovered = widget; - else - darktable.bauhaus->hovered = NULL; - - gtk_widget_queue_draw(widget); - - return FALSE; -} - static void _widget_finalize(GObject *widget) { dt_bauhaus_widget_t *w = DT_BAUHAUS_WIDGET(widget); @@ -716,13 +724,8 @@ static void dt_bh_class_init(DtBauhausWidgetClass *class) widget_class->draw = _widget_draw; widget_class->scroll_event = _widget_scroll; widget_class->key_press_event = _widget_key_press; - widget_class->button_press_event = _widget_button_press; - widget_class->button_release_event = _widget_button_release; - widget_class->motion_notify_event = _widget_motion_notify; widget_class->get_preferred_width = _widget_get_preferred_width; widget_class->get_preferred_height = _widget_get_preferred_height; - widget_class->enter_notify_event = _widget_enter_leave; - widget_class->leave_notify_event = _widget_enter_leave; G_OBJECT_CLASS(class)->finalize = _widget_finalize; } @@ -3378,8 +3381,11 @@ static gboolean _popup_key_press(GtkWidget *widget, return TRUE; } -static gboolean _widget_button_press(GtkWidget *widget, - GdkEventButton *event) +static void _widget_button_press(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + GtkWidget *widget) { dt_bauhaus_widget_t *w = (dt_bauhaus_widget_t *)widget; _request_focus(w); @@ -3389,33 +3395,34 @@ static gboolean _widget_button_press(GtkWidget *widget, gtk_widget_get_allocation(widget, &allocation); const int w3 = allocation.width - w->margin.left - w->padding.left - w->margin.right - w->padding.right; - const double ex = event->x - w->margin.left - w->padding.left; - const double ey = event->y - w->margin.top - w->padding.top; + const double ex = x - w->margin.left - w->padding.left; + const double ey = y - w->margin.top - w->padding.top; + guint button = gtk_gesture_single_get_current_button(gesture); if(w->quad_paint - && event->x > allocation.width - _widget_get_quad_width(w) + && x > allocation.width - _widget_get_quad_width(w) - w->margin.right - w->padding.right) { dt_bauhaus_widget_press_quad(widget); } - else if(event->button == 1 - && event->type == GDK_2BUTTON_PRESS) + else if(button == 1 && n_press == 2) { - if(!(dt_modifier_is(event->state, GDK_CONTROL_MASK) && w->field + if(!(dt_modifier_eq(gesture, GDK_CONTROL_MASK) && w->field && dt_gui_presets_autoapply_for_module((dt_iop_module_t *)w->module, widget))) dt_bauhaus_widget_reset(widget); // reset to default. // never called for combo, as we popup the other window under your cursor before. // (except in weird corner cases where the popup is under the -1st entry _popup_hide(); } - else if(event->button == 3 || w->type == DT_BAUHAUS_COMBOBOX) + else if(button == 3 || w->type == DT_BAUHAUS_COMBOBOX) { + GdkEventMotion *event = (GdkEventMotion *)gtk_get_current_event(); // TODO cleanup darktable.bauhaus->opentime = event->time; - darktable.bauhaus->mouse_x = event->x; - darktable.bauhaus->mouse_y = event->y; + darktable.bauhaus->mouse_x = x; + darktable.bauhaus->mouse_y = y; _popup_show(widget); } - else if(event->button == 2) + else if(button == 2) { _slider_zoom_range(w, 0); // reset zoom range to soft min/max _slider_zoom_toast(w); @@ -3424,7 +3431,7 @@ static gboolean _widget_button_press(GtkWidget *widget, { dt_bauhaus_slider_data_t *d = &w->data.slider; d->is_dragging = -1; - if(!dt_modifier_is(event->state, 0)) + if(!dt_modifier_eq(gesture, 0)) darktable.bauhaus->mouse_x = ex; else if(ey > darktable.bauhaus->line_height / 2.0f) { @@ -3433,36 +3440,36 @@ static gboolean _widget_button_press(GtkWidget *widget, darktable.bauhaus->mouse_x = NAN; } - else - return FALSE; } - return TRUE; + dt_gui_claim(gesture); } -static gboolean _widget_button_release(GtkWidget *widget, - GdkEventButton *event) +static void _widget_button_release(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + GtkWidget *widget) { dt_bauhaus_widget_t *w = (dt_bauhaus_widget_t *)widget; dt_bauhaus_widget_release_quad(widget); - if(w->type != DT_BAUHAUS_SLIDER) return FALSE; + if(w->type != DT_BAUHAUS_SLIDER) return; dt_bauhaus_slider_data_t *d = &w->data.slider; - if(event->button == 1 && d->is_dragging) + if(gtk_gesture_single_get_current_button(gesture) == 1 && d->is_dragging) { d->is_dragging = 0; if(d->timeout_handle) g_source_remove(d->timeout_handle); d->timeout_handle = 0; _slider_set_normalized(w, d->pos); - - return TRUE; } - return FALSE; } -static gboolean _widget_motion_notify(GtkWidget *widget, - GdkEventMotion *event) +static void _widget_motion(GtkEventControllerMotion *controller, + double x, + double y, + GtkWidget *widget) { dt_bauhaus_widget_t *w = (dt_bauhaus_widget_t *)widget; dt_bauhaus_slider_data_t *d = &w->data.slider; @@ -3471,21 +3478,21 @@ static gboolean _widget_motion_notify(GtkWidget *widget, gtk_widget_get_allocation(widget, &allocation); const int w3 = allocation.width - w->margin.left - w->padding.left - w->margin.right - w->padding.right; - const double ex = event->x - w->margin.left - w->padding.left; + const double ex = x - w->margin.left - w->padding.left; if(w->type == DT_BAUHAUS_COMBOBOX) { darktable.control->element = - event->x <= allocation.width - _widget_get_quad_width(w) || !w->quad_paint + x <= allocation.width - _widget_get_quad_width(w) || !w->quad_paint ? DT_ACTION_ELEMENT_SELECTION : DT_ACTION_ELEMENT_BUTTON; } - else if(d->is_dragging && event->state & GDK_BUTTON1_MASK) + else if(d->is_dragging) { const float r = _slider_right_pos((float)w3, w); if(dt_isnan(darktable.bauhaus->mouse_x)) { - if(dt_modifier_is(event->state, 0)) + if(dt_modifier_eq(controller, 0)) _slider_set_normalized(w, (ex / w3) / r); else darktable.bauhaus->mouse_x = ex; @@ -3495,6 +3502,7 @@ static gboolean _widget_motion_notify(GtkWidget *widget, const float scaled_step = w3 * r * dt_bauhaus_slider_get_step(widget) / (d->max - d->min); const float steps = floorf((ex - darktable.bauhaus->mouse_x) / scaled_step); + GdkEventMotion *event = (GdkEventMotion *)gtk_get_current_event(); // TODO cleanup _slider_add_step(widget, copysignf(1, d->factor) * steps, event->state, FALSE); darktable.bauhaus->mouse_x += steps * scaled_step; @@ -3513,7 +3521,6 @@ static gboolean _widget_motion_notify(GtkWidget *widget, w->quad_paint ? DT_ACTION_ELEMENT_BUTTON : DT_ACTION_ELEMENT_VALUE; gtk_widget_queue_draw(widget); - return TRUE; } void dt_bauhaus_vimkey_exec(const char *input) diff --git a/src/develop/imageop.c b/src/develop/imageop.c index ec6fb581abf1..e79b4ed4bab0 100644 --- a/src/develop/imageop.c +++ b/src/develop/imageop.c @@ -2404,52 +2404,57 @@ void dt_iop_gui_update_expanded(dt_iop_module_t *module) dtgtk_expander_set_expanded(DTGTK_EXPANDER(module->expander), expanded); } -static gboolean _iop_plugin_body_button_press(GtkWidget *w, - GdkEventButton *e, - gpointer user_data) +static void _iop_plugin_body_button_press(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *module) { - dt_iop_module_t *module = (dt_iop_module_t *)user_data; - if(e->button == 1) + guint button = gtk_gesture_single_get_current_button(gesture); + if(button == 1) { dt_iop_request_focus(module); - return TRUE; + dt_gui_claim(gesture); + return; } - else if(e->button == 3) + else if(button == 3) { _presets_popup_callback(NULL, NULL, module); - return TRUE; + dt_gui_claim(gesture); + return; } - return FALSE; } -static gboolean _iop_plugin_header_button_press(GtkWidget *w, - GdkEventButton *e, - gpointer user_data) +static void _iop_plugin_header_button_press(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *module) { - if(e->type == GDK_2BUTTON_PRESS || e->type == GDK_3BUTTON_PRESS) return TRUE; + if(n_press > 1) return; - dt_iop_module_t *module = (dt_iop_module_t *)user_data; - - if(e->button == 1) + guint button = gtk_gesture_single_get_current_button(gesture); + if(button == 1) { - if(dt_modifier_is(e->state, GDK_SHIFT_MASK | GDK_CONTROL_MASK)) + if(dt_modifier_eq(gesture, GDK_SHIFT_MASK | GDK_CONTROL_MASK)) { GtkBox *container = dt_ui_get_container(darktable.gui->ui, DT_UI_CONTAINER_PANEL_RIGHT_CENTER); - g_object_set_data(G_OBJECT(container), "source_data", user_data); - return FALSE; + g_object_set_data(G_OBJECT(container), "source_data", module); + return; } - else if(dt_modifier_is(e->state, GDK_CONTROL_MASK)) + else if(dt_modifier_eq(gesture, GDK_CONTROL_MASK)) { dt_iop_gui_rename_module(module); - return TRUE; + dt_gui_claim(gesture); + return; } else { const gboolean collapse_others = !dt_conf_get_bool("darkroom/ui/single_module") - != (!dt_modifier_is(e->state, GDK_SHIFT_MASK)); + != (!dt_modifier_eq(gesture, GDK_SHIFT_MASK)); dt_iop_gui_set_expanded(module, !module->expanded, collapse_others); @@ -2459,16 +2464,17 @@ static gboolean _iop_plugin_header_button_press(GtkWidget *w, //used to take focus away from module search text input box when module selected gtk_widget_grab_focus(dt_ui_center(darktable.gui->ui)); - return TRUE; + dt_gui_claim(gesture); + return; } } - else if(e->button == 3) + else if(button == 3) { _presets_popup_callback(NULL, NULL, module); - return TRUE; + dt_gui_claim(gesture); + return; } - return FALSE; } static void _header_size_callback(GtkWidget *widget, @@ -2909,8 +2915,7 @@ void dt_iop_gui_set_expander(dt_iop_module_t *module) module->header = header; /* setup the header box */ - g_signal_connect(G_OBJECT(header_evb), "button-press-event", - G_CALLBACK(_iop_plugin_header_button_press), module); + dt_gui_connect_click_all(header_evb, _iop_plugin_header_button_press, NULL, module); gtk_widget_add_events(header_evb, GDK_POINTER_MOTION_MASK); g_signal_connect(G_OBJECT(header_evb), "enter-notify-event", G_CALLBACK(_header_motion_notify_show_callback), module); @@ -2918,8 +2923,7 @@ void dt_iop_gui_set_expander(dt_iop_module_t *module) G_CALLBACK(_header_motion_notify_hide_callback), module); /* connect mouse button callbacks for focus and presets */ - g_signal_connect(G_OBJECT(body_evb), "button-press-event", - G_CALLBACK(_iop_plugin_body_button_press), module); + dt_gui_connect_click_all(body_evb, _iop_plugin_body_button_press, NULL, module); gtk_widget_add_events(body_evb, GDK_POINTER_MOTION_MASK); g_signal_connect(G_OBJECT(body_evb), "enter-notify-event", G_CALLBACK(_header_motion_notify_show_callback), module); diff --git a/src/dtgtk/thumbnail.c b/src/dtgtk/thumbnail.c index c5824f425e76..a1a669851ebb 100644 --- a/src/dtgtk/thumbnail.c +++ b/src/dtgtk/thumbnail.c @@ -926,43 +926,41 @@ static void _thumbs_show_overlays(dt_thumbnail_t *thumb) } } -static gboolean _event_main_motion(GtkWidget *widget, - GdkEventMotion *event, - gpointer user_data) +static void _event_main_motion(GtkEventControllerMotion *controller, + double x, + double y, + dt_thumbnail_t *thumb) { - if(!user_data) return TRUE; - dt_thumbnail_t *thumb = (dt_thumbnail_t *)user_data; + if(!thumb) return; // first, we hide the block overlays after a delay if the mouse hasn't move _thumbs_show_overlays(thumb); if(!thumb->mouse_over && !thumb->disable_mouseover) dt_control_set_mouse_over_id(thumb->imgid); - return FALSE; } -static gboolean _event_main_press(GtkWidget *widget, - GdkEventButton *event, - gpointer user_data) +static void _event_main_press(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_thumbnail_t *thumb) { - dt_thumbnail_t *thumb = (dt_thumbnail_t *)user_data; - if(event->button == 1 - && ((event->type == GDK_2BUTTON_PRESS && !thumb->single_click) - || (event->type == GDK_BUTTON_PRESS - && dt_modifier_is(event->state, 0) && thumb->single_click))) + if((n_press == 2 && !thumb->single_click) + || (n_press == 1 + && dt_modifier_eq(gesture, 0) && thumb->single_click)) { dt_control_set_mouse_over_id(thumb->imgid); // to ensure we haven't lost imgid during double-click } - return FALSE; } -static gboolean _event_main_release(GtkWidget *widget, - GdkEventButton *event, - gpointer user_data) +static void _event_main_release(GtkGesture *gesture, + int n_press, + double x, + double y, + dt_thumbnail_t *thumb) { - dt_thumbnail_t *thumb = (dt_thumbnail_t *)user_data; - - if(event->button == 1 - && !thumb->moved + GdkEventButton *event = (GdkEventButton *)gtk_gesture_get_last_event(gesture, NULL); + if(!thumb->moved && thumb->sel_mode != DT_THUMBNAIL_SEL_MODE_DISABLED) { if(dt_modifier_is(event->state, 0) @@ -976,7 +974,6 @@ static gboolean _event_main_release(GtkWidget *widget, else if(dt_modifier_is(event->state, GDK_SHIFT_MASK)) dt_selection_select_range(darktable.selection, thumb->imgid); } - return FALSE; } static gboolean _event_rating_press(GtkWidget *widget, @@ -1255,20 +1252,24 @@ static gboolean _event_box_enter_leave(GtkWidget *widget, return FALSE; } -static gboolean _event_image_enter_leave(GtkWidget *widget, - GdkEventCrossing *event, - gpointer user_data) +static void _event_image_leave(GtkEventControllerMotion *controller, + dt_thumbnail_t *thumb) { - dt_thumbnail_t *thumb = (dt_thumbnail_t *)user_data; - // we ensure that the image has mouse over - if(!thumb->mouse_over && event->type == GDK_ENTER_NOTIFY + if(!thumb->mouse_over && controller == NULL && !thumb->disable_mouseover) dt_control_set_mouse_over_id(thumb->imgid); _set_flag(thumb->w_image_box, GTK_STATE_FLAG_PRELIGHT, - (event->type == GDK_ENTER_NOTIFY)); - return FALSE; + (controller == NULL)); +} + +static void _event_image_enter(GtkEventControllerMotion *controller, + double x, + double y, + dt_thumbnail_t *thumb) +{ + _event_image_leave(NULL, thumb); } static gboolean _event_btn_enter_leave(GtkWidget *widget, @@ -1339,13 +1340,12 @@ static gboolean _event_star_leave(GtkWidget *widget, return TRUE; } -static gboolean _event_main_leave(GtkWidget *widget, - GdkEventCrossing *event, - gpointer user_data) +static void _event_main_leave(GtkEventControllerMotion *controller, + gpointer user_data) { + GdkEventCrossing *event = (GdkEventCrossing *)gtk_get_current_event(); // if we leave for ancestor, that means we leave for blank thumbtable area if(event->detail == GDK_NOTIFY_ANCESTOR) dt_control_set_mouse_over_id(NO_IMGID); - return FALSE; } // we only want to specify that the mouse is hovereing the thumbnail @@ -1356,7 +1356,7 @@ static gboolean _event_main_drag_motion(GtkWidget *widget, const guint time, gpointer user_data) { - _event_main_motion(widget, NULL, user_data); + _event_main_motion(NULL, .0f, .0f, user_data); return TRUE; } @@ -1401,10 +1401,7 @@ GtkWidget *dt_thumbnail_create_widget(dt_thumbnail_t *thumb, g_signal_connect(G_OBJECT(thumb->w_main), "drag-motion", G_CALLBACK(_event_main_drag_motion), thumb); - g_signal_connect(G_OBJECT(thumb->w_main), "button-press-event", - G_CALLBACK(_event_main_press), thumb); - g_signal_connect(G_OBJECT(thumb->w_main), "button-release-event", - G_CALLBACK(_event_main_release), thumb); + dt_gui_connect_click(thumb->w_main, _event_main_press, _event_main_release, thumb); g_object_set_data(G_OBJECT(thumb->w_main), "thumb", thumb); DT_DEBUG_CONTROL_SIGNAL_CONNECT(darktable.signals, DT_SIGNAL_ACTIVE_IMAGES_CHANGE, @@ -1423,16 +1420,9 @@ GtkWidget *dt_thumbnail_create_widget(dt_thumbnail_t *thumb, // the background thumb->w_back = gtk_event_box_new(); - gtk_widget_set_events(thumb->w_back, - GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_STRUCTURE_MASK - | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK - | GDK_POINTER_MOTION_MASK); + gtk_widget_set_events(thumb->w_back, GDK_STRUCTURE_MASK); // TODO: Needed? gtk_widget_set_name(thumb->w_back, "thumb-back"); - g_signal_connect(G_OBJECT(thumb->w_back), "motion-notify-event", - G_CALLBACK(_event_main_motion), thumb); - g_signal_connect(G_OBJECT(thumb->w_back), "leave-notify-event", - G_CALLBACK(_event_main_leave), thumb); + dt_gui_connect_motion(thumb->w_back, _event_main_motion, NULL, _event_main_leave, thumb); gtk_widget_show(thumb->w_back); gtk_container_add(GTK_CONTAINER(thumb->w_main), thumb->w_back); @@ -1462,12 +1452,7 @@ GtkWidget *dt_thumbnail_create_widget(dt_thumbnail_t *thumb, | GDK_STRUCTURE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK); - g_signal_connect(G_OBJECT(evt_image), "motion-notify-event", - G_CALLBACK(_event_main_motion), thumb); - g_signal_connect(G_OBJECT(evt_image), "enter-notify-event", - G_CALLBACK(_event_image_enter_leave), thumb); - g_signal_connect(G_OBJECT(evt_image), "leave-notify-event", - G_CALLBACK(_event_image_enter_leave), thumb); + dt_gui_connect_motion(evt_image, _event_main_motion, _event_image_enter, _event_image_leave, thumb); gtk_widget_show(evt_image); gtk_overlay_add_overlay(GTK_OVERLAY(thumb->w_image_box), evt_image); thumb->w_image = gtk_drawing_area_new(); @@ -1481,12 +1466,7 @@ GtkWidget *dt_thumbnail_create_widget(dt_thumbnail_t *thumb, | GDK_POINTER_MOTION_MASK); g_signal_connect(G_OBJECT(thumb->w_image), "draw", G_CALLBACK(_event_image_draw), thumb); - g_signal_connect(G_OBJECT(thumb->w_image), "motion-notify-event", - G_CALLBACK(_event_main_motion), thumb); - g_signal_connect(G_OBJECT(thumb->w_image), "enter-notify-event", - G_CALLBACK(_event_image_enter_leave), thumb); - g_signal_connect(G_OBJECT(thumb->w_image), "leave-notify-event", - G_CALLBACK(_event_image_enter_leave), thumb); + dt_gui_connect_motion(thumb->w_image, _event_main_motion, _event_image_enter, _event_image_leave, thumb); g_signal_connect(G_OBJECT(thumb->w_image), "style-updated", G_CALLBACK(_event_image_style_updated), thumb); gtk_widget_show(thumb->w_image); diff --git a/src/gui/gtk.c b/src/gui/gtk.c index 6808a1c41201..2ebca19807ce 100644 --- a/src/gui/gtk.c +++ b/src/gui/gtk.c @@ -4161,6 +4161,37 @@ gboolean dt_gui_long_click(const int second, return second - first > delay; } +GtkGestureSingle *(dt_gui_connect_click)(GtkWidget *widget, + GCallback pressed, + GCallback released, + gpointer data) +{ + GtkGesture *gesture = gtk_gesture_multi_press_new(widget); + g_object_weak_ref(G_OBJECT (widget), (GWeakNotify) g_object_unref, gesture); + + if(pressed) g_signal_connect(gesture, "pressed", pressed, data); + if(released) g_signal_connect(gesture, "released", released, data); + + return (GtkGestureSingle *)gesture; +} + +GtkEventController *(dt_gui_connect_motion)(GtkWidget *widget, + GCallback motion, + GCallback enter, + GCallback leave, + gpointer data) +{ + GtkEventController *controller = gtk_event_controller_motion_new(widget); + g_object_weak_ref(G_OBJECT (widget), (GWeakNotify) g_object_unref, controller); + + if(motion) g_signal_connect(controller, "motion", motion, data); + if(enter) g_signal_connect(controller, "enter", enter, data); + if(leave) g_signal_connect(controller, "leave", leave, data); + + return controller; +} + + // clang-format off // modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py // vim: shiftwidth=2 expandtab tabstop=2 cindent diff --git a/src/gui/gtk.h b/src/gui/gtk.h index 08b9179f5d4d..76526d26f6e6 100644 --- a/src/gui/gtk.h +++ b/src/gui/gtk.h @@ -524,6 +524,30 @@ void dt_gui_hide_collapsible_section(dt_gui_collapsible_section_t *cs); gboolean dt_gui_long_click(const int second, const int first); +GtkGestureSingle *(dt_gui_connect_click)(GtkWidget *widget, + GCallback pressed, + GCallback released, + gpointer data); +#define dt_gui_connect_click(widget, pressed, released, data) \ + dt_gui_connect_click(GTK_WIDGET(widget), G_CALLBACK(pressed), G_CALLBACK(released), (data)) +#define dt_gui_connect_click_all(widget, pressed, released, data) \ + gtk_gesture_single_set_button(dt_gui_connect_click(widget, pressed, released, data), 0) + +#define dt_gui_claim(gesture) \ + gtk_gesture_set_state(GTK_GESTURE(gesture), GTK_EVENT_SEQUENCE_CLAIMED) + +GtkEventController *(dt_gui_connect_motion)(GtkWidget *widget, + GCallback motion, + GCallback enter, + GCallback leave, + gpointer data); +#define dt_gui_connect_motion(widget, motion, enter, leave, data) \ + dt_gui_connect_motion(GTK_WIDGET(widget), G_CALLBACK(motion), G_CALLBACK(enter), G_CALLBACK(leave), (data)) + +// in gtk4 use gtk_event_controller_get_current_event_state(GTK_EVENT_CONTROLLER(controller)); +#define dt_modifier_eq(controller, mask)\ + dt_modifier_is(dt_key_modifier_state(), mask) + #ifdef __cplusplus } // extern "C" #endif /* __cplusplus */ diff --git a/src/iop/atrous.c b/src/iop/atrous.c index 6910ede9423b..b10b275da838 100644 --- a/src/iop/atrous.c +++ b/src/iop/atrous.c @@ -1076,17 +1076,23 @@ void gui_update(struct dt_iop_module_t *self) // gui stuff: -static gboolean area_enter_leave_notify(GtkWidget *widget, - GdkEventCrossing *event, - dt_iop_module_t *self) +static void _atrous_leave(GtkEventControllerMotion *controller, + dt_iop_module_t *self) { dt_iop_atrous_gui_data_t *g = self->gui_data; - g->in_curve = event->type == GDK_ENTER_NOTIFY; + g->in_curve = controller == NULL; if(!g->dragging) g->x_move = -1; - gtk_widget_queue_draw(widget); - return FALSE; + gtk_widget_queue_draw(GTK_WIDGET(g->area)); +} + +static void _atrous_enter(GtkEventControllerMotion *controller, + double x, + double y, + dt_iop_module_t *self) +{ + _atrous_leave(NULL, self); } // fills in new parameters based on mouse position (in 0,1) @@ -1423,19 +1429,21 @@ static gboolean area_draw(GtkWidget *widget, return FALSE; } -static gboolean area_motion_notify(GtkWidget *widget, - GdkEventMotion *event, - dt_iop_module_t *self) +static void _atrous_motion(GtkEventControllerMotion *controller, + double x, + double y, + dt_iop_module_t *self) { dt_iop_atrous_gui_data_t *g = self->gui_data; dt_iop_atrous_params_t *p = self->params; + const int inset = INSET; GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); + gtk_widget_get_allocation(GTK_WIDGET(g->area), &allocation); const int height = allocation.height - 2 * inset - DT_RESIZE_HANDLE_SIZE; const int width = allocation.width - 2 * inset; - if(!g->dragging) g->mouse_x = CLAMP(event->x - inset, 0, width) / (float)width; - g->mouse_y = 1.0 - CLAMP(event->y - inset, 0, height) / (float)height; + if(!g->dragging) g->mouse_x = CLAMP(x - inset, 0, width) / (float)width; + g->mouse_y = 1.0 - CLAMP(y - inset, 0, height) / (float)height; darktable.control->element = 0; @@ -1449,7 +1457,7 @@ static gboolean area_motion_notify(GtkWidget *widget, *p = g->drag_params; if(g->x_move >= 0) { - const float mx = CLAMP(event->x - inset, 0, width) / (float)width; + const float mx = CLAMP(x - inset, 0, width) / (float)width; if(g->x_move > 0 && g->x_move < BANDS - 1) { const float minx = p->x[g->channel][g->x_move - 1] + 0.001f; @@ -1461,10 +1469,9 @@ static gboolean area_motion_notify(GtkWidget *widget, { get_params(p, g->channel2, g->mouse_x, g->mouse_y + g->mouse_pick, g->mouse_radius); } - gtk_widget_queue_draw(widget); - dt_dev_add_history_item_target(darktable.develop, self, TRUE, widget + g->channel); + dt_dev_add_history_item_target(darktable.develop, self, TRUE, g->area + g->channel); } - else if(event->y > height) + else if(y > height) { // move x-positions g->x_move = 0; @@ -1479,8 +1486,6 @@ static gboolean area_motion_notify(GtkWidget *widget, } } darktable.control->element = g->x_move + 1; - - gtk_widget_queue_draw(widget); } else { @@ -1501,61 +1506,57 @@ static gboolean area_motion_notify(GtkWidget *widget, } // don't move x-positions: g->x_move = -1; - gtk_widget_queue_draw(widget); } - return TRUE; + gtk_widget_queue_draw(GTK_WIDGET(g->area)); } -static gboolean area_button_press(GtkWidget *widget, - GdkEventButton *event, - dt_iop_module_t *self) +static void _atrous_button_press(GtkGesture *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self) { - if(event->button == 1 && event->type == GDK_2BUTTON_PRESS) + dt_iop_atrous_gui_data_t *g = self->gui_data; + if(n_press == 2) { // reset current curve dt_iop_atrous_params_t *p = self->params; const dt_iop_atrous_params_t *const d = self->default_params; - dt_iop_atrous_gui_data_t *g = self->gui_data; reset_mix(self); for(int k = 0; k < BANDS; k++) { p->x[g->channel2][k] = d->x[g->channel2][k]; p->y[g->channel2][k] = d->y[g->channel2][k]; } - dt_dev_add_history_item_target(darktable.develop, self, TRUE, widget + g->channel2); + dt_dev_add_history_item_target(darktable.develop, self, TRUE, g->area + g->channel2); } - else if(event->button == 1) + else { // set active point - dt_iop_atrous_gui_data_t *g = self->gui_data; reset_mix(self); const int inset = INSET; GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); + gtk_widget_get_allocation(GTK_WIDGET(g->area), &allocation); const int height = allocation.height - 2 * inset - DT_RESIZE_HANDLE_SIZE; const int width = allocation.width - 2 * inset; g->mouse_pick = dt_draw_curve_calc_value(g->minmax_curve, - CLAMP(event->x - inset, 0, width) / (float)width); - g->mouse_pick -= 1.0 - CLAMP(event->y - inset, 0, height) / (float)height; + CLAMP(x - inset, 0, width) / (float)width); + g->mouse_pick -= 1.0 - CLAMP(y - inset, 0, height) / (float)height; g->dragging = 1; - return TRUE; + dt_gui_claim(gesture); } - return FALSE; } -static gboolean area_button_release(GtkWidget *widget, - GdkEventButton *event, - dt_iop_module_t *self) +static void _atrous_button_release(GtkGesture *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self) { - if(event->button == 1) - { - dt_iop_atrous_gui_data_t *g = self->gui_data; - g->dragging = 0; - reset_mix(self); - return TRUE; - } - return FALSE; + dt_iop_atrous_gui_data_t *g = self->gui_data; + g->dragging = 0; + reset_mix(self); } static gboolean area_scrolled(GtkWidget *widget, @@ -1809,16 +1810,8 @@ void gui_init(struct dt_iop_module_t *self) dt_action_define_iop(self, NULL, N_("graph"), GTK_WIDGET(g->area), &_action_def_equalizer); g_signal_connect(G_OBJECT(g->area), "draw", G_CALLBACK(area_draw), self); - g_signal_connect(G_OBJECT(g->area), "button-press-event", - G_CALLBACK(area_button_press), self); - g_signal_connect(G_OBJECT(g->area), "button-release-event", - G_CALLBACK(area_button_release), self); - g_signal_connect(G_OBJECT(g->area), "motion-notify-event", - G_CALLBACK(area_motion_notify), self); - g_signal_connect(G_OBJECT(g->area), "leave-notify-event", - G_CALLBACK(area_enter_leave_notify), self); - g_signal_connect(G_OBJECT(g->area), "enter-notify-event", - G_CALLBACK(area_enter_leave_notify), self); + dt_gui_connect_click(g->area, _atrous_button_press, _atrous_button_release, self); + dt_gui_connect_motion(g->area, _atrous_motion, _atrous_enter, _atrous_leave, self); g_signal_connect(G_OBJECT(g->area), "scroll-event", G_CALLBACK(area_scrolled), self); diff --git a/src/iop/basecurve.c b/src/iop/basecurve.c index 1c3dae2aba23..b86733c89992 100644 --- a/src/iop/basecurve.c +++ b/src/iop/basecurve.c @@ -1583,15 +1583,14 @@ void cleanup_global(dt_iop_module_so_t *module) module->data = NULL; } -static gboolean dt_iop_basecurve_leave_notify(GtkWidget *widget, - GdkEventCrossing *event, - dt_iop_module_t *self) +static void _basecurve_leave(GtkEventControllerMotion *controller, + dt_iop_module_t *self) { dt_iop_basecurve_gui_data_t *g = self->gui_data; + GdkEventCrossing *event = (GdkEventCrossing *)gtk_get_current_event(); if(!(event->state & GDK_BUTTON1_MASK)) g->selected = -1; - gtk_widget_queue_draw(widget); - return FALSE; + gtk_widget_queue_draw(GTK_WIDGET(g->area)); } static float to_log(const float x, const float base) @@ -1828,9 +1827,10 @@ static gboolean _move_point_internal(dt_iop_module_t *self, float dy, const guint state); -static gboolean dt_iop_basecurve_motion_notify(GtkWidget *widget, - GdkEventMotion *event, - dt_iop_module_t *self) +static void _basecurve_motion(GtkEventControllerMotion *controller, + double x, + double y, + dt_iop_module_t *self) { dt_iop_basecurve_gui_data_t *g = self->gui_data; dt_iop_basecurve_params_t *p = self->params; @@ -1839,18 +1839,19 @@ static gboolean dt_iop_basecurve_motion_notify(GtkWidget *widget, dt_iop_basecurve_node_t *basecurve = p->basecurve[ch]; GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); + gtk_widget_get_allocation(GTK_WIDGET(g->area), &allocation); const int inset = DT_GUI_CURVE_EDITOR_INSET; int height = allocation.height - 2 * inset, width = allocation.width - 2 * inset; const double old_m_x = g->mouse_x; const double old_m_y = g->mouse_y; - g->mouse_x = event->x - inset; - g->mouse_y = event->y - inset; + g->mouse_x = x - inset; + g->mouse_y = y - inset; const float mx = CLAMP(g->mouse_x, 0, width) / (float)width; const float my = 1.0f - CLAMP(g->mouse_y, 0, height) / (float)height; const float linx = to_lin(mx, g->loglogscale), liny = to_lin(my, g->loglogscale); + GdkEventMotion *event = (GdkEventMotion *)gtk_get_current_event(); if(event->state & GDK_BUTTON1_MASK) { // got a vertex selected: @@ -1865,13 +1866,14 @@ static gboolean dt_iop_basecurve_motion_notify(GtkWidget *widget, const float dy = to_lin(1 - g->mouse_y / height - translate_mouse_y, g->loglogscale) - to_lin(1 - old_m_y / height - translate_mouse_y, g->loglogscale); - return _move_point_internal(self, widget, dx, dy, event->state); + _move_point_internal(self, GTK_WIDGET(g->area), dx, dy, event->state); + return; } else if(nodes < MAXNODES && g->selected >= -1) { // no vertex was close, create a new one! g->selected = _add_node(basecurve, &p->basecurve_nodes[ch], linx, liny); - dt_dev_add_history_item_target(darktable.develop, self, TRUE, widget); + dt_dev_add_history_item_target(darktable.develop, self, TRUE, g->area); } } else @@ -1893,14 +1895,15 @@ static gboolean dt_iop_basecurve_motion_notify(GtkWidget *widget, } g->selected = nearest; } - if(g->selected >= 0) gtk_widget_grab_focus(widget); - gtk_widget_queue_draw(widget); - return TRUE; + if(g->selected >= 0) gtk_widget_grab_focus(GTK_WIDGET(g->area)); + gtk_widget_queue_draw(GTK_WIDGET(g->area)); } -static gboolean dt_iop_basecurve_button_press(GtkWidget *widget, - GdkEventButton *event, - dt_iop_module_t *self) +static void _basecurve_button_press(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self) { dt_iop_basecurve_params_t *p = self->params; const dt_iop_basecurve_params_t *const d = self->default_params; @@ -1910,18 +1913,19 @@ static gboolean dt_iop_basecurve_button_press(GtkWidget *widget, int nodes = p->basecurve_nodes[ch]; dt_iop_basecurve_node_t *basecurve = p->basecurve[ch]; - if(event->button == 1) + guint button = gtk_gesture_single_get_current_button(gesture); + if(button == 1) { - if(event->type == GDK_BUTTON_PRESS && dt_modifier_is(event->state, GDK_CONTROL_MASK) + if(n_press == 1 && dt_modifier_eq(gesture, GDK_CONTROL_MASK) && nodes < MAXNODES && g->selected == -1) { // if we are not on a node -> add a new node at the current x of the pointer and y of the curve at that x const int inset = DT_GUI_CURVE_EDITOR_INSET; GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); + gtk_widget_get_allocation(GTK_WIDGET(g->area), &allocation); int width = allocation.width - 2 * inset; - g->mouse_x = event->x - inset; - g->mouse_y = event->y - inset; + g->mouse_x = x - inset; + g->mouse_y = y - inset; const float mx = CLAMP(g->mouse_x, 0, width) / (float)width; const float linx = to_lin(mx, g->loglogscale); @@ -1948,12 +1952,12 @@ static gboolean dt_iop_basecurve_button_press(GtkWidget *widget, (selected < nodes && basecurve[selected].x - linx <= 0.025))) { // evaluate the curve at the current x position - const float y = dt_draw_curve_calc_value(g->minmax_curve, linx); + const float calc_y = dt_draw_curve_calc_value(g->minmax_curve, linx); - if(y >= 0.0 && y <= 1.0) // never add something outside the viewport, you couldn't change it afterwards + if(calc_y >= 0.0 && calc_y <= 1.0) // never add something outside the viewport, you couldn't change it afterwards { // create a new node - selected = _add_node(basecurve, &p->basecurve_nodes[ch], linx, y); + selected = _add_node(basecurve, &p->basecurve_nodes[ch], linx, calc_y); // maybe set the new one as being selected float min = .04f; @@ -1961,17 +1965,18 @@ static gboolean dt_iop_basecurve_button_press(GtkWidget *widget, for(int k = 0; k < nodes; k++) { float other_y = to_log(basecurve[k].y, g->loglogscale); - float dist = (y - other_y) * (y - other_y); + float dist = (calc_y - other_y) * (calc_y - other_y); if(dist < min) g->selected = selected; } - dt_dev_add_history_item_target(darktable.develop, self, TRUE, widget); + dt_dev_add_history_item_target(darktable.develop, self, TRUE, g->area); gtk_widget_queue_draw(GTK_WIDGET(g->area)); } } - return TRUE; + dt_gui_claim(gesture); + return; } - else if(event->type == GDK_2BUTTON_PRESS) + else if(n_press == 2) { // reset current curve p->basecurve_nodes[ch] = d->basecurve_nodes[ch]; @@ -1982,20 +1987,23 @@ static gboolean dt_iop_basecurve_button_press(GtkWidget *widget, p->basecurve[ch][k].y = d->basecurve[ch][k].y; } g->selected = -2; // avoid motion notify re-inserting immediately. - dt_dev_add_history_item_target(darktable.develop, self, TRUE, widget); + dt_dev_add_history_item_target(darktable.develop, self, TRUE, g->area); gtk_widget_queue_draw(GTK_WIDGET(g->area)); - return TRUE; + dt_gui_claim(gesture); + return; } } - else if(event->button == 3 && g->selected >= 0) + else if(button == 3 && g->selected >= 0) { + dt_gui_claim(gesture); + if(g->selected == 0 || g->selected == nodes - 1) { float reset_value = g->selected == 0 ? 0 : 1; basecurve[g->selected].y = basecurve[g->selected].x = reset_value; gtk_widget_queue_draw(GTK_WIDGET(g->area)); - dt_dev_add_history_item_target(darktable.develop, self, TRUE, widget); - return TRUE; + dt_dev_add_history_item_target(darktable.develop, self, TRUE, g->area); + return; } for(int k = g->selected; k < nodes - 1; k++) @@ -2007,10 +2015,8 @@ static gboolean dt_iop_basecurve_button_press(GtkWidget *widget, g->selected = -2; // avoid re-insertion of that point immediately after this p->basecurve_nodes[ch]--; gtk_widget_queue_draw(GTK_WIDGET(g->area)); - dt_dev_add_history_item_target(darktable.develop, self, TRUE, widget); - return TRUE; + dt_dev_add_history_item_target(darktable.develop, self, TRUE, g->area); } - return FALSE; } static gboolean _move_point_internal(dt_iop_module_t *self, @@ -2181,9 +2187,8 @@ void gui_init(struct dt_iop_module_t *self) | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); gtk_widget_set_can_focus(GTK_WIDGET(g->area), TRUE); g_signal_connect(G_OBJECT(g->area), "draw", G_CALLBACK(dt_iop_basecurve_draw), self); - g_signal_connect(G_OBJECT(g->area), "button-press-event", G_CALLBACK(dt_iop_basecurve_button_press), self); - g_signal_connect(G_OBJECT(g->area), "motion-notify-event", G_CALLBACK(dt_iop_basecurve_motion_notify), self); - g_signal_connect(G_OBJECT(g->area), "leave-notify-event", G_CALLBACK(dt_iop_basecurve_leave_notify), self); + dt_gui_connect_click_all(g->area, _basecurve_button_press, NULL, self); + dt_gui_connect_motion(g->area, _basecurve_motion, NULL, _basecurve_leave, self); g_signal_connect(G_OBJECT(g->area), "scroll-event", G_CALLBACK(_scrolled), self); g_signal_connect(G_OBJECT(g->area), "key-press-event", G_CALLBACK(dt_iop_basecurve_key_press), self); } diff --git a/src/iop/colorchecker.c b/src/iop/colorchecker.c index 090aed27de58..ffe23d21dc27 100644 --- a/src/iop/colorchecker.c +++ b/src/iop/colorchecker.c @@ -1215,22 +1215,22 @@ static gboolean checker_draw(GtkWidget *widget, return TRUE; } -static gboolean checker_motion_notify( - GtkWidget *widget, - GdkEventMotion *event, - dt_iop_module_t *self) +static void _colorchecker_motion(GtkEventControllerMotion *controller, + double x, + double y, + dt_iop_module_t *self) { // highlight? dt_iop_colorchecker_params_t *p = self->params; dt_iop_colorchecker_gui_data_t *g = self->gui_data; GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); + gtk_widget_get_allocation(GTK_WIDGET(g->area), &allocation); const int width = allocation.width; const int height = allocation.height; - const float mouse_x = CLAMP(event->x, 0, width); - const float mouse_y = CLAMP(event->y, 0, height); + const float mouse_x = CLAMP(x, 0, width); + const float mouse_y = CLAMP(y, 0, height); int cells_x = 6, cells_y = 4; if(p->num_patches > 24) { @@ -1240,7 +1240,7 @@ static gboolean checker_motion_notify( const float mx = mouse_x * cells_x / (float)width; const float my = mouse_y * cells_y / (float)height; const int patch = (int)mx + cells_x * (int)my; - if(patch < 0 || patch >= p->num_patches) return FALSE; + if(patch < 0 || patch >= p->num_patches) return; char tooltip[1024]; snprintf(tooltip, sizeof(tooltip), _("(%2.2f %2.2f %2.2f)\n" @@ -1251,21 +1251,22 @@ static gboolean checker_motion_notify( "shift+click while color picking to replace patch"), p->source_L[patch], p->source_a[patch], p->source_b[patch]); gtk_widget_set_tooltip_text(g->area, tooltip); - return TRUE; } -static gboolean checker_button_press( - GtkWidget *widget, GdkEventButton *event, - dt_iop_module_t *self) +static void _colorchecker_button_press(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self) { dt_iop_colorchecker_params_t *p = self->params; dt_iop_colorchecker_gui_data_t *g = self->gui_data; GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); + gtk_widget_get_allocation(GTK_WIDGET(g->area), &allocation); int width = allocation.width, height = allocation.height; - const float mouse_x = CLAMP(event->x, 0, width); - const float mouse_y = CLAMP(event->y, 0, height); + const float mouse_x = CLAMP(x, 0, width); + const float mouse_y = CLAMP(y, 0, height); int cells_x = 6, cells_y = 4; if(p->num_patches > 24) { @@ -1275,9 +1276,10 @@ static gboolean checker_button_press( const float mx = mouse_x * cells_x / (float)width; const float my = mouse_y * cells_y / (float)height; int patch = (int)mx + cells_x*(int)my; - if(event->button == 1 && event->type == GDK_2BUTTON_PRESS) + guint button = gtk_gesture_single_get_current_button(gesture); + if(button == 1 && n_press == 2) { // reset on double click - if(patch < 0 || patch >= p->num_patches) return FALSE; + if(patch < 0 || patch >= p->num_patches) return; p->target_L[patch] = p->source_L[patch]; p->target_a[patch] = p->source_a[patch]; p->target_b[patch] = p->source_b[patch]; @@ -1286,12 +1288,13 @@ static gboolean checker_button_press( _colorchecker_update_sliders(self); --darktable.gui->reset; gtk_widget_queue_draw(g->area); - return TRUE; + dt_gui_claim(gesture); + return; } - else if(event->button == 3 && (patch < p->num_patches)) + else if(button == 3 && (patch < p->num_patches)) { // right click: delete patch, move others up - if(patch < 0 || patch >= p->num_patches) return FALSE; + if(patch < 0 || patch >= p->num_patches) return; memmove(p->target_L+patch, p->target_L+patch+1, sizeof(float)*(p->num_patches-1-patch)); memmove(p->target_a+patch, p->target_a+patch+1, @@ -1311,10 +1314,11 @@ static gboolean checker_button_press( _colorchecker_update_sliders(self); --darktable.gui->reset; gtk_widget_queue_draw(g->area); - return TRUE; + dt_gui_claim(gesture); + return; } - else if((event->button == 1) && - dt_modifier_is(event->state, GDK_SHIFT_MASK) && + else if((button == 1) && + dt_modifier_eq(gesture, GDK_SHIFT_MASK) && (self->request_color_pick == DT_REQUEST_COLORPICK_MODULE)) { // shift-left while colour picking: replace source colour @@ -1355,11 +1359,12 @@ static gboolean checker_button_press( g->patch = g->drawn_patch = patch; gtk_widget_queue_draw(g->area); } - return TRUE; + dt_gui_claim(gesture); + return; } if(patch >= p->num_patches) patch = p->num_patches-1; dt_bauhaus_combobox_set(g->combobox_patch, patch); - return FALSE; + return; } void gui_init(struct dt_iop_module_t *self) @@ -1373,16 +1378,10 @@ void gui_init(struct dt_iop_module_t *self) g->area = dtgtk_drawing_area_new_with_aspect_ratio(4.0/6.0); gtk_box_pack_start(GTK_BOX(self->widget), g->area, TRUE, TRUE, 0); - gtk_widget_add_events(GTK_WIDGET(g->area), - GDK_POINTER_MOTION_MASK - | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_LEAVE_NOTIFY_MASK); g_signal_connect(G_OBJECT(g->area), "draw", G_CALLBACK(checker_draw), self); - g_signal_connect(G_OBJECT(g->area), "button-press-event", - G_CALLBACK(checker_button_press), self); - g_signal_connect(G_OBJECT(g->area), "motion-notify-event", - G_CALLBACK(checker_motion_notify), self); + dt_gui_connect_click_all(g->area, _colorchecker_button_press, NULL, self); + dt_gui_connect_motion(g->area, _colorchecker_motion, NULL, NULL, self); g->patch = 0; g->drawn_patch = -1; diff --git a/src/iop/colorcorrection.c b/src/iop/colorcorrection.c index 466fa51aadb3..e56196a77cec 100644 --- a/src/iop/colorcorrection.c +++ b/src/iop/colorcorrection.c @@ -223,12 +223,17 @@ void gui_update(struct dt_iop_module_t *self) static gboolean dt_iop_colorcorrection_draw(GtkWidget *widget, cairo_t *cr, dt_iop_module_t *self); -static gboolean dt_iop_colorcorrection_motion_notify(GtkWidget *widget, GdkEventMotion *event, - dt_iop_module_t *self); -static gboolean dt_iop_colorcorrection_button_press(GtkWidget *widget, GdkEventButton *event, - dt_iop_module_t *self); -static gboolean dt_iop_colorcorrection_leave_notify(GtkWidget *widget, GdkEventCrossing *event, - dt_iop_module_t *self); +static void _colorcorrection_button_press(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self); +static void _colorcorrection_motion(GtkEventControllerMotion *controller, + double x, + double y, + dt_iop_module_t *self); +static void _colorcorrection_leave(GtkEventControllerMotion *controller, + dt_iop_module_t *self); static gboolean dt_iop_colorcorrection_scrolled(GtkWidget *widget, GdkEventScroll *event, dt_iop_module_t *self); static gboolean dt_iop_colorcorrection_key_press(GtkWidget *widget, GdkEventKey *event, @@ -250,17 +255,11 @@ void gui_init(struct dt_iop_module_t *self) "bright means highlights, dark means shadows. " "use mouse wheel to change saturation.")); - gtk_widget_add_events(GTK_WIDGET(g->area), GDK_POINTER_MOTION_MASK | darktable.gui->scroll_mask - | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); + gtk_widget_add_events(GTK_WIDGET(g->area), darktable.gui->scroll_mask); gtk_widget_set_can_focus(GTK_WIDGET(g->area), TRUE); g_signal_connect(G_OBJECT(g->area), "draw", G_CALLBACK(dt_iop_colorcorrection_draw), self); - g_signal_connect(G_OBJECT(g->area), "button-press-event", G_CALLBACK(dt_iop_colorcorrection_button_press), - self); - g_signal_connect(G_OBJECT(g->area), "motion-notify-event", G_CALLBACK(dt_iop_colorcorrection_motion_notify), - self); - g_signal_connect(G_OBJECT(g->area), "leave-notify-event", G_CALLBACK(dt_iop_colorcorrection_leave_notify), - self); + dt_gui_connect_click(g->area, _colorcorrection_button_press, NULL, self); + dt_gui_connect_motion(g->area, _colorcorrection_motion, NULL, _colorcorrection_leave, self); g_signal_connect(G_OBJECT(g->area), "scroll-event", G_CALLBACK(dt_iop_colorcorrection_scrolled), self); g_signal_connect(G_OBJECT(g->area), "key-press-event", G_CALLBACK(dt_iop_colorcorrection_key_press), self); @@ -355,19 +354,22 @@ static gboolean dt_iop_colorcorrection_draw(GtkWidget *widget, cairo_t *crf, dt_ return TRUE; } -static gboolean dt_iop_colorcorrection_motion_notify(GtkWidget *widget, GdkEventMotion *event, - dt_iop_module_t *self) +static void _colorcorrection_motion(GtkEventControllerMotion *controller, + double x, + double y, + dt_iop_module_t *self) { dt_iop_colorcorrection_gui_data_t *g = self->gui_data; dt_iop_colorcorrection_params_t *p = self->params; const int inset = DT_COLORCORRECTION_INSET; GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); + gtk_widget_get_allocation(GTK_WIDGET(g->area), &allocation); int width = allocation.width - 2 * inset, height = allocation.height - 2 * inset; - const float mouse_x = CLAMP(event->x - inset, 0, width); - const float mouse_y = CLAMP(height - 1 - event->y + inset, 0, height); + const float mouse_x = CLAMP(x - inset, 0, width); + const float mouse_y = CLAMP(height - 1 - y + inset, 0, height); const float ma = (2.0 * mouse_x - width) * DT_COLORCORRECTION_MAX / (float)width; const float mb = (2.0 * mouse_y - height) * DT_COLORCORRECTION_MAX / (float)height; + GdkEventMotion *event = (GdkEventMotion *)gtk_get_current_event(); if(event->state & GDK_BUTTON1_MASK) { if(g->selected == 1) @@ -394,15 +396,18 @@ static gboolean dt_iop_colorcorrection_motion_notify(GtkWidget *widget, GdkEvent else if(disthi < thrs * thrs && disthi <= distlo) g->selected = 2; } - if(g->selected > 0) gtk_widget_grab_focus(widget); + if(g->selected > 0) gtk_widget_grab_focus(GTK_WIDGET(g->area)); gtk_widget_queue_draw(GTK_WIDGET(g->area)); - return TRUE; } -static gboolean dt_iop_colorcorrection_button_press(GtkWidget *widget, GdkEventButton *event, - dt_iop_module_t *self) +static void _colorcorrection_button_press(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self) { - if(event->button == 1 && event->type == GDK_2BUTTON_PRESS) + dt_gui_claim(gesture); + if(n_press == 2) { // double click resets: dt_iop_colorcorrection_gui_data_t *g = self->gui_data; @@ -424,17 +429,14 @@ static gboolean dt_iop_colorcorrection_button_press(GtkWidget *widget, GdkEventB dt_dev_add_history_item(darktable.develop, self, TRUE); } } - return TRUE; } - return FALSE; } -static gboolean dt_iop_colorcorrection_leave_notify(GtkWidget *widget, GdkEventCrossing *event, - dt_iop_module_t *self) +static void _colorcorrection_leave(GtkEventControllerMotion *controller, + dt_iop_module_t *self) { dt_iop_colorcorrection_gui_data_t *g = self->gui_data; gtk_widget_queue_draw(GTK_WIDGET(g->area)); - return TRUE; } static gboolean dt_iop_colorcorrection_scrolled(GtkWidget *widget, GdkEventScroll *event, dt_iop_module_t *self) diff --git a/src/iop/colorequal.c b/src/iop/colorequal.c index fa32d826e5c0..91d01f5eb2ce 100644 --- a/src/iop/colorequal.c +++ b/src/iop/colorequal.c @@ -2236,76 +2236,68 @@ static gboolean _area_scrolled_callback(GtkWidget *widget, return gtk_widget_event(w, (GdkEvent*)event); } -static gboolean _area_motion_notify_callback(GtkWidget *widget, - GdkEventMotion *event, - dt_iop_module_t *self) +static void _colorequal_motion(GtkEventControllerMotion *controller, + double x, + double y, + dt_iop_module_t *self) { dt_iop_colorequal_gui_data_t *g = self->gui_data; if(g->dragging && g->on_node) - _area_set_pos(g, event->y); + _area_set_pos(g, y); else { // look if close to a node const float epsilon = DT_PIXEL_APPLY_DPI(10.0); const int oldsel = g->selected; const int oldon = g->on_node; - g->selected = (int)(((float)event->x - g->points[0][0]) + g->selected = (int)(((float)x - g->points[0][0]) / (g->points[1][0] - g->points[0][0]) + 0.5f) % NODES; - g->on_node = fabsf(g->points[g->selected][1] - (float)event->y) < epsilon; + g->on_node = fabsf(g->points[g->selected][1] - (float)y) < epsilon; darktable.control->element = g->selected; if(oldsel != g->selected || oldon != g->on_node) gtk_widget_queue_draw(GTK_WIDGET(g->area)); } - - return TRUE; } -static gboolean _area_button_press_callback(GtkWidget *widget, - GdkEventButton *event, - dt_iop_module_t *self) +static void _colorequal_button_press(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self) { dt_iop_colorequal_gui_data_t *g = self->gui_data; - if(event->button == 2 - || (event->button == 1 // Ctrl+Click alias for macOS - && dt_modifier_is(event->state, GDK_CONTROL_MASK))) + guint button = gtk_gesture_single_get_current_button(gesture); + if(button == 2 + || (button == 1 // Ctrl+Click alias for macOS + && dt_modifier_eq(gesture, GDK_CONTROL_MASK))) { dt_conf_set_bool("plugins/darkroom/colorequal/show_sliders", gtk_notebook_get_n_pages(g->notebook) != 4); gui_update(self); } - else if(event->button == 1) + else if(button == 1) { - if(event->type == GDK_2BUTTON_PRESS) - { + dt_gui_claim(gesture); + if(n_press == 2) _area_reset_nodes(g); - return TRUE; - } else - { g->dragging = TRUE; - } } - else - return gtk_widget_event(_get_slider(g, g->selected), (GdkEvent*)event); - - return FALSE; + // TODO + // else + // return gtk_widget_event(_get_slider(g, g->selected), (GdkEvent*)event); } -static gboolean _area_button_release_callback(GtkWidget *widget, - GdkEventButton *event, - dt_iop_module_t *self) +static void _colorequal_button_release(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self) { dt_iop_colorequal_gui_data_t *g = self->gui_data; - - if(event->button == 1) - { - g->dragging = FALSE; - return TRUE; - } - - return FALSE; + g->dragging = FALSE; } static gboolean _area_size_callback(GtkWidget *widget, @@ -2514,19 +2506,10 @@ void gui_init(struct dt_iop_module_t *self) dt_action_define_iop(self, NULL, N_("graph"), GTK_WIDGET(g->area), &_action_def_coloreq); gtk_widget_set_tooltip_text(GTK_WIDGET(g->area), _("double-click to reset the curve\nmiddle click to toggle sliders visibility\nalt+scroll to change page")); gtk_widget_set_can_focus(GTK_WIDGET(g->area), TRUE); - gtk_widget_add_events(GTK_WIDGET(g->area), - GDK_BUTTON_PRESS_MASK - | GDK_POINTER_MOTION_MASK - | GDK_BUTTON_RELEASE_MASK - | GDK_SCROLL_MASK - | GDK_SMOOTH_SCROLL_MASK); + gtk_widget_add_events(GTK_WIDGET(g->area), darktable.gui->scroll_mask); g_signal_connect(G_OBJECT(g->area), "draw", G_CALLBACK(_iop_colorequalizer_draw), self); - g_signal_connect(G_OBJECT(g->area), "button-press-event", - G_CALLBACK(_area_button_press_callback), self); - g_signal_connect(G_OBJECT(g->area), "button-release-event", - G_CALLBACK(_area_button_release_callback), self); - g_signal_connect(G_OBJECT(g->area), "motion-notify-event", - G_CALLBACK(_area_motion_notify_callback), self); + dt_gui_connect_click_all(g->area, _colorequal_button_press, _colorequal_button_release, self); + dt_gui_connect_motion(g->area, _colorequal_motion, NULL, NULL, self); g_signal_connect(G_OBJECT(g->area), "scroll-event", G_CALLBACK(_area_scrolled_callback), self); g_signal_connect(G_OBJECT(g->area), "size_allocate", diff --git a/src/iop/colorzones.c b/src/iop/colorzones.c index edffbadae6a8..2ac04da6102a 100644 --- a/src/iop/colorzones.c +++ b/src/iop/colorzones.c @@ -1922,15 +1922,18 @@ static gboolean _area_scrolled_callback(GtkWidget *widget, return TRUE; } -static gboolean _area_motion_notify_callback(GtkWidget *widget, - GdkEventMotion *event, - dt_iop_module_t *self) +static void _colorzones_motion(GtkEventControllerMotion *controller, + double x, + double y, + dt_iop_module_t *self) { dt_iop_colorzones_gui_data_t *g = self->gui_data; dt_iop_colorzones_params_t *p = self->params; const int inset = DT_IOP_COLORZONES_INSET; + GdkEventMotion *event = (GdkEventMotion *)gtk_get_current_event(); + GtkWidget *widget = gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(controller)); GtkAllocation allocation; gtk_widget_get_allocation(widget, &allocation); @@ -1943,8 +1946,8 @@ static gboolean _area_motion_notify_callback(GtkWidget *widget, const float mx = g->mouse_x; const float my = g->mouse_y; - g->mouse_x = CLAMP(event->x - inset, 0, width) / (float)width; - g->mouse_y = 1.0 - CLAMP(event->y - inset, 0, height) / (float)height; + g->mouse_x = CLAMP(x - inset, 0, width) / (float)width; + g->mouse_y = 1.0 - CLAMP(y - inset, 0, height) / (float)height; if(event->state & GDK_BUTTON1_MASK) { @@ -1956,7 +1959,7 @@ static gboolean _area_motion_notify_callback(GtkWidget *widget, gtk_widget_queue_draw(GTK_WIDGET(g->area)); } - return TRUE; + return; } const int ch = g->channel; @@ -1966,8 +1969,8 @@ static gboolean _area_motion_notify_callback(GtkWidget *widget, const double old_m_x = g->mouse_x; const double old_m_y = fabs(g->mouse_y); - g->mouse_x = CLAMP(event->x - inset, 0, width) / (float)width; - g->mouse_y = 1.0 - CLAMP(event->y - inset, 0, height) / (float)height; + g->mouse_x = CLAMP(x - inset, 0, width) / (float)width; + g->mouse_y = 1.0 - CLAMP(y - inset, 0, height) / (float)height; darktable.control->element = (int)(8.0 * @@ -2006,7 +2009,8 @@ static gboolean _area_motion_notify_callback(GtkWidget *widget, g->zoom_factor, g->offset_y); dt_iop_color_picker_reset(self, TRUE); - return _move_point_internal(self, widget, g->selected, dx, dy, event->state); + _move_point_internal(self, widget, g->selected, dx, dy, event->state); + return; } } @@ -2022,7 +2026,7 @@ static gboolean _area_motion_notify_callback(GtkWidget *widget, dt_dev_add_history_item_target(darktable.develop, self, TRUE, widget + ch); } } - else if(event->y > height) + else if(y > height) { g->x_move = 0; const int bands = p->curve_num_nodes[g->channel]; @@ -2088,33 +2092,37 @@ static gboolean _area_motion_notify_callback(GtkWidget *widget, } gtk_widget_queue_draw(widget); - return TRUE; + return; } -static gboolean _area_button_press_callback(GtkWidget *widget, - GdkEventButton *event, - dt_iop_module_t *self) +static void _colorzones_button_press(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self) { dt_iop_colorzones_gui_data_t *g = self->gui_data; dt_iop_colorzones_params_t *p = self->params; const dt_iop_colorzones_params_t *const d = self->default_params; - if(darktable.develop->darkroom_skip_mouse_events) return TRUE; + if(darktable.develop->darkroom_skip_mouse_events) return; int ch = g->channel; int nodes = p->curve_num_nodes[ch]; dt_iop_colorzones_node_t *curve = p->curve[ch]; - if(event->button == 1) + GtkWidget *widget = gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(gesture)); + guint button = gtk_gesture_single_get_current_button(gesture); + if(button == 1) { - if(g->edit_by_area && event->type != GDK_2BUTTON_PRESS - && !dt_modifier_is(event->state, GDK_CONTROL_MASK)) + if(g->edit_by_area && n_press != 2 + && !dt_modifier_eq(gesture, GDK_CONTROL_MASK)) { g->dragging = 1; - return TRUE; + return; } - else if(event->type == GDK_BUTTON_PRESS - && dt_modifier_is(event->state, GDK_CONTROL_MASK) + else if(n_press == 1 + && dt_modifier_eq(gesture, GDK_CONTROL_MASK) && nodes < DT_IOP_COLORZONES_MAXNODES && (g->selected == -1 || g->edit_by_area)) { @@ -2126,8 +2134,8 @@ static gboolean _area_button_press_callback(GtkWidget *widget, const int height = allocation.height - 2 * inset; const int width = allocation.width - 2 * inset; - g->mouse_x = CLAMP(event->x - inset, 0, width) / (float)width; - g->mouse_y = 1.0 - CLAMP(event->y - inset, 0, height) / (float)height; + g->mouse_x = CLAMP(x - inset, 0, width) / (float)width; + g->mouse_y = 1.0 - CLAMP(y - inset, 0, height) / (float)height; const float mx = _mouse_to_curve(g->mouse_x, g->zoom_factor, g->offset_x); @@ -2149,14 +2157,14 @@ static gboolean _area_button_press_callback(GtkWidget *widget, if(selected == -1) selected = nodes; // evaluate the curve at the current x position - const float y = dt_draw_curve_calc_value(g->minmax_curve[ch], mx); + const float calc_y = dt_draw_curve_calc_value(g->minmax_curve[ch], mx); - if(y >= 0.0f && y <= 1.0f) // never add something outside the - // viewport, you couldn't change it - // afterwards + if(calc_y >= 0.0f && calc_y <= 1.0f) // never add something outside the + // viewport, you couldn't change it + // afterwards { // create a new node - selected = _add_node(curve, &p->curve_num_nodes[ch], mx, y); + selected = _add_node(curve, &p->curve_num_nodes[ch], mx, calc_y); // maybe set the new one as being selected const float min = .04f * .04f; // comparing against square @@ -2164,7 +2172,7 @@ static gboolean _area_button_press_callback(GtkWidget *widget, for(int k = 0; k < nodes; k++) { const float other_y = _curve_to_mouse(curve[k].y, g->zoom_factor, g->offset_y); - const float dist = (y - other_y) * (y - other_y); + const float dist = (calc_y - other_y) * (calc_y - other_y); if(dist < min) g->selected = selected; } @@ -2173,9 +2181,9 @@ static gboolean _area_button_press_callback(GtkWidget *widget, gtk_widget_queue_draw(GTK_WIDGET(g->area)); } - return TRUE; + return; } - else if(event->type == GDK_2BUTTON_PRESS) + else if(n_press == 2) { // reset current curve p->curve_num_nodes[ch] = d->curve_num_nodes[ch]; @@ -2191,11 +2199,12 @@ static gboolean _area_button_press_callback(GtkWidget *widget, dt_dev_add_history_item_target(darktable.develop, self, TRUE, widget + ch); gtk_widget_queue_draw(GTK_WIDGET(g->area)); - return TRUE; + return; } } - else if(event->button == 3 && g->selected >= 0) + else if(button == 3 && g->selected >= 0) { + dt_gui_claim(gesture); if((g->selected == 0 || g->selected == nodes - 1) && p->splines_version == DT_IOP_COLORZONES_SPLINES_V1) { @@ -2216,48 +2225,43 @@ static gboolean _area_button_press_callback(GtkWidget *widget, dt_iop_color_picker_reset(self, TRUE); gtk_widget_queue_draw(GTK_WIDGET(g->area)); dt_dev_add_history_item_target(darktable.develop, self, TRUE, widget + ch); - return TRUE; + return; } // right click deletes the node, ctrl+right click reset the node to y-zero _delete_node(self, curve, &p->curve_num_nodes[ch], - g->selected, dt_modifier_is(event->state, GDK_CONTROL_MASK)); + g->selected, dt_modifier_eq(gesture, GDK_CONTROL_MASK)); g->selected = -2; // avoid re-insertion of that point immediately after this - - return TRUE; } - - return FALSE; } -static gboolean _area_button_release_callback(GtkWidget *widget, - GdkEventButton *event, - dt_iop_module_t *self) +static void _colorzones_button_release(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self) { - if(darktable.develop->darkroom_skip_mouse_events) return TRUE; + if(darktable.develop->darkroom_skip_mouse_events) return; - if(event->button == 1) + if(gtk_gesture_single_get_current_button(gesture) == 1) { dt_iop_colorzones_gui_data_t *g = self->gui_data; g->dragging = 0; - return TRUE; } - return FALSE; } -static gboolean _area_leave_notify_callback(GtkWidget *widget, - GdkEventCrossing *event, - dt_iop_module_t *self) +static void _colorzones_leave(GtkEventControllerMotion *controller, + dt_iop_module_t *self) { - if(darktable.develop->darkroom_skip_mouse_events) return TRUE; + if(darktable.develop->darkroom_skip_mouse_events) return; dt_iop_colorzones_gui_data_t *g = self->gui_data; // for fluxbox g->mouse_y = -fabs(g->mouse_y); + GdkEventCrossing *event = (GdkEventCrossing *)gtk_get_current_event(); if(!(event->state & GDK_BUTTON1_MASK)) g->selected = -1; - gtk_widget_queue_draw(widget); - return TRUE; + gtk_widget_queue_draw(GTK_WIDGET(g->area)); } static gboolean _area_key_press_callback(GtkWidget *widget, @@ -2722,14 +2726,8 @@ void gui_init(struct dt_iop_module_t *self) gtk_widget_set_can_focus(GTK_WIDGET(g->area), TRUE); g_signal_connect(G_OBJECT(g->area), "draw", G_CALLBACK(_area_draw_callback), self); - g_signal_connect(G_OBJECT(g->area), "button-press-event", - G_CALLBACK(_area_button_press_callback), self); - g_signal_connect(G_OBJECT(g->area), "button-release-event", - G_CALLBACK(_area_button_release_callback), self); - g_signal_connect(G_OBJECT(g->area), "motion-notify-event", - G_CALLBACK(_area_motion_notify_callback), self); - g_signal_connect(G_OBJECT(g->area), "leave-notify-event", - G_CALLBACK(_area_leave_notify_callback), self); + dt_gui_connect_click(g->area, _colorzones_button_press, _colorzones_button_release, self); + dt_gui_connect_motion(g->area, _colorzones_motion, NULL, _colorzones_leave, self); g_signal_connect(G_OBJECT(g->area), "scroll-event", G_CALLBACK(_area_scrolled_callback), self); g_signal_connect(G_OBJECT(g->area), "key-press-event", diff --git a/src/iop/denoiseprofile.c b/src/iop/denoiseprofile.c index 32ab6a5cec84..08b6a04002ef 100644 --- a/src/iop/denoiseprofile.c +++ b/src/iop/denoiseprofile.c @@ -3508,18 +3508,19 @@ static gboolean denoiseprofile_draw(GtkWidget *widget, return FALSE; } -static gboolean denoiseprofile_motion_notify(GtkWidget *widget, - GdkEventMotion *event, - dt_iop_module_t *self) +static void _denoiseprofile_motion(GtkEventControllerMotion *controller, + double x, + double y, + dt_iop_module_t *self) { dt_iop_denoiseprofile_gui_data_t *g = self->gui_data; dt_iop_denoiseprofile_params_t *p = self->params; const int inset = DT_IOP_DENOISE_PROFILE_INSET; GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); + gtk_widget_get_allocation(GTK_WIDGET(g->area), &allocation); int height = allocation.height - 2 * inset, width = allocation.width - 2 * inset; - if(!g->dragging) g->mouse_x = CLAMP(event->x - inset, 0, width) / (float)width; - g->mouse_y = 1.0 - CLAMP(event->y - inset, 0, height) / (float)height; + if(!g->dragging) g->mouse_x = CLAMP(x - inset, 0, width) / (float)width; + g->mouse_y = 1.0 - CLAMP(y - inset, 0, height) / (float)height; if(g->dragging) { *p = g->drag_params; @@ -3535,17 +3536,18 @@ static gboolean denoiseprofile_motion_notify(GtkWidget *widget, { g->x_move = -1; } - gtk_widget_queue_draw(widget); - return TRUE; + gtk_widget_queue_draw(GTK_WIDGET(g->area)); } -static gboolean denoiseprofile_button_press(GtkWidget *widget, - GdkEventButton *event, - dt_iop_module_t *self) +static void _denoiseprofile_button_press(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self) { dt_iop_denoiseprofile_gui_data_t *g = self->gui_data; const int ch = g->channel; - if(event->button == 1 && event->type == GDK_2BUTTON_PRESS) + if(n_press == 2) { // reset current curve dt_iop_denoiseprofile_params_t *p = self->params; @@ -3559,44 +3561,37 @@ static gboolean denoiseprofile_button_press(GtkWidget *widget, dt_dev_add_history_item(darktable.develop, self, TRUE); gtk_widget_queue_draw(GTK_WIDGET(g->area)); } - else if(event->button == 1) + else { g->drag_params = *(dt_iop_denoiseprofile_params_t *)self->params; const int inset = DT_IOP_DENOISE_PROFILE_INSET; GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); + gtk_widget_get_allocation(GTK_WIDGET(g->area), &allocation); int height = allocation.height - 2 * inset, width = allocation.width - 2 * inset; g->mouse_pick = dt_draw_curve_calc_value(g->transition_curve, - CLAMP(event->x - inset, 0, width) / (float)width); - g->mouse_pick -= 1.0 - CLAMP(event->y - inset, 0, height) / (float)height; + CLAMP(x - inset, 0, width) / (float)width); + g->mouse_pick -= 1.0 - CLAMP(y - inset, 0, height) / (float)height; g->dragging = 1; - return TRUE; } - return FALSE; } -static gboolean denoiseprofile_button_release(GtkWidget *widget, - GdkEventButton *event, - dt_iop_module_t *self) +static void _denoiseprofile_button_release(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self) { - if(event->button == 1) - { - dt_iop_denoiseprofile_gui_data_t *g = self->gui_data; - g->dragging = 0; - return TRUE; - } - return FALSE; + dt_iop_denoiseprofile_gui_data_t *g = self->gui_data; + g->dragging = 0; } -static gboolean denoiseprofile_leave_notify(GtkWidget *widget, - GdkEventCrossing *event, - dt_iop_module_t *self) +static void _denoiseprofile_leave(GtkEventControllerMotion *controller, + dt_iop_module_t *self) { dt_iop_denoiseprofile_gui_data_t *g = self->gui_data; if(!g->dragging) g->mouse_y = -1.0; - gtk_widget_queue_draw(widget); - return TRUE; + gtk_widget_queue_draw(GTK_WIDGET(g->area)); } static gboolean denoiseprofile_scrolled(GtkWidget *widget, @@ -3702,14 +3697,8 @@ void gui_init(dt_iop_module_t *self) dt_action_define_iop(self, NULL, N_("graph"), GTK_WIDGET(g->area), NULL); g_signal_connect(G_OBJECT(g->area), "draw", G_CALLBACK(denoiseprofile_draw), self); - g_signal_connect(G_OBJECT(g->area), "button-press-event", - G_CALLBACK(denoiseprofile_button_press), self); - g_signal_connect(G_OBJECT(g->area), "button-release-event", - G_CALLBACK(denoiseprofile_button_release), self); - g_signal_connect(G_OBJECT(g->area), "motion-notify-event", - G_CALLBACK(denoiseprofile_motion_notify), self); - g_signal_connect(G_OBJECT(g->area), "leave-notify-event", - G_CALLBACK(denoiseprofile_leave_notify), self); + dt_gui_connect_click(g->area, _denoiseprofile_button_press, _denoiseprofile_button_release, self); + dt_gui_connect_motion(g->area, _denoiseprofile_motion, NULL, _denoiseprofile_leave, self); g_signal_connect(G_OBJECT(g->area), "scroll-event", G_CALLBACK(denoiseprofile_scrolled), self); gtk_box_pack_start(GTK_BOX(g->box_wavelets), GTK_WIDGET(g->area), FALSE, FALSE, 0); diff --git a/src/iop/filmicrgb.c b/src/iop/filmicrgb.c index f13f6382758d..0a8604457342 100644 --- a/src/iop/filmicrgb.c +++ b/src/iop/filmicrgb.c @@ -4180,9 +4180,13 @@ static gboolean dt_iop_tonecurve_draw(GtkWidget *widget, cairo_t *crf, dt_iop_mo return FALSE; } -static gboolean area_button_press(GtkWidget *widget, GdkEventButton *event, dt_iop_module_t *self) +static void _filmicrgb_button_press(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self) { - if(darktable.gui->reset) return TRUE; + if(darktable.gui->reset) return; dt_iop_filmicrgb_gui_data_t *g = self->gui_data; @@ -4190,8 +4194,8 @@ static gboolean area_button_press(GtkWidget *widget, GdkEventButton *event, dt_i if(g->active_button != DT_FILMIC_GUI_BUTTON_LAST) { - - if(event->button == 1 && event->type == GDK_2BUTTON_PRESS) + guint button = gtk_gesture_single_get_current_button(gesture); + if(button == 1 && n_press == 2) { // double click resets view if(g->active_button == DT_FILMIC_GUI_BUTTON_TYPE) @@ -4199,14 +4203,9 @@ static gboolean area_button_press(GtkWidget *widget, GdkEventButton *event, dt_i g->gui_mode = DT_FILMIC_GUI_LOOK; gtk_widget_queue_draw(GTK_WIDGET(g->area)); dt_conf_set_int("plugins/darkroom/filmicrgb/graph_view", g->gui_mode); - return TRUE; - } - else - { - return FALSE; } } - else if(event->button == 1) + else if(button == 1) { // simple left click cycles through modes in positive direction if(g->active_button == DT_FILMIC_GUI_BUTTON_TYPE) @@ -4219,24 +4218,17 @@ static gboolean area_button_press(GtkWidget *widget, GdkEventButton *event, dt_i gtk_widget_queue_draw(GTK_WIDGET(g->area)); dt_conf_set_int("plugins/darkroom/filmicrgb/graph_view", g->gui_mode); - return TRUE; } else if(g->active_button == DT_FILMIC_GUI_BUTTON_LABELS) { g->gui_show_labels = !g->gui_show_labels; gtk_widget_queue_draw(GTK_WIDGET(g->area)); dt_conf_set_int("plugins/darkroom/filmicrgb/graph_show_labels", g->gui_show_labels); - return TRUE; - } - else - { - // we should never get there since (g->active_button != DT_FILMIC_GUI_BUTTON_LAST) - // and any other case has been processed above. - return FALSE; } } - else if(event->button == 3) + else if(button == 3) { + dt_gui_claim(gesture); // simple right click cycles through modes in negative direction if(g->active_button == DT_FILMIC_GUI_BUTTON_TYPE) { @@ -4247,44 +4239,44 @@ static gboolean area_button_press(GtkWidget *widget, GdkEventButton *event, dt_i gtk_widget_queue_draw(GTK_WIDGET(g->area)); dt_conf_set_int("plugins/darkroom/filmicrgb/graph_view", g->gui_mode); - return TRUE; } else if(g->active_button == DT_FILMIC_GUI_BUTTON_LABELS) { g->gui_show_labels = !g->gui_show_labels; gtk_widget_queue_draw(GTK_WIDGET(g->area)); dt_conf_set_int("plugins/darkroom/filmicrgb/graph_show_labels", g->gui_show_labels); - return TRUE; - } - else - { - return FALSE; } } } - - return FALSE; } -static gboolean area_enter_leave_notify(GtkWidget *widget, GdkEventCrossing *event, dt_iop_module_t *self) +static void _filmicrgb_leave(GtkEventControllerMotion *controller, + dt_iop_module_t *self) { dt_iop_filmicrgb_gui_data_t *g = self->gui_data; - g->gui_hover = event->type == GDK_ENTER_NOTIFY; + g->gui_hover = controller == NULL; gtk_widget_queue_draw(GTK_WIDGET(g->area)); - return FALSE; } -static gboolean area_motion_notify(GtkWidget *widget, GdkEventMotion *event, dt_iop_module_t *self) +static void _filmicrgb_enter(GtkEventControllerMotion *controller, + double x, + double y, + dt_iop_module_t *self) +{ + _filmicrgb_leave(NULL, self); +} + +static void _filmicrgb_motion(GtkEventControllerMotion *controller, + double x, + double y, + dt_iop_module_t *self) { - if(darktable.gui->reset) return 1; + if(darktable.gui->reset) return; dt_iop_filmicrgb_gui_data_t *g = self->gui_data; - if(!g->gui_sizes_inited) return FALSE; + if(!g->gui_sizes_inited) return; // get in-widget coordinates - const float y = event->y; - const float x = event->x; - if(x > 0. && x < g->allocation.width && y > 0. && y < g->allocation.height) g->gui_hover = TRUE; gint save_active_button = g->active_button; @@ -4337,13 +4329,11 @@ static gboolean area_motion_notify(GtkWidget *widget, GdkEventMotion *event, dt_ } if(save_active_button != g->active_button) gtk_widget_queue_draw(GTK_WIDGET(g->area)); - return TRUE; } else { g->active_button = DT_FILMIC_GUI_BUTTON_LAST; if(save_active_button != g->active_button) (GTK_WIDGET(g->area)); - return FALSE; } } @@ -4365,10 +4355,8 @@ void gui_init(dt_iop_module_t *self) gtk_widget_set_can_focus(GTK_WIDGET(g->area), TRUE); g_signal_connect(G_OBJECT(g->area), "draw", G_CALLBACK(dt_iop_tonecurve_draw), self); - g_signal_connect(G_OBJECT(g->area), "button-press-event", G_CALLBACK(area_button_press), self); - g_signal_connect(G_OBJECT(g->area), "leave-notify-event", G_CALLBACK(area_enter_leave_notify), self); - g_signal_connect(G_OBJECT(g->area), "enter-notify-event", G_CALLBACK(area_enter_leave_notify), self); - g_signal_connect(G_OBJECT(g->area), "motion-notify-event", G_CALLBACK(area_motion_notify), self); + dt_gui_connect_click_all(g->area, _filmicrgb_button_press, NULL, self); + dt_gui_connect_motion(g->area, _filmicrgb_motion, _filmicrgb_enter, _filmicrgb_leave, self); // Init GTK notebook static struct dt_action_def_t notebook_def = { }; diff --git a/src/iop/levels.c b/src/iop/levels.c index e254fa34958a..4ef31aa8dcb4 100644 --- a/src/iop/levels.c +++ b/src/iop/levels.c @@ -49,10 +49,22 @@ DT_MODULE_INTROSPECTION(2, dt_iop_levels_params_t) static gboolean dt_iop_levels_area_draw(GtkWidget *widget, cairo_t *crf, dt_iop_module_t *self); -static gboolean dt_iop_levels_motion_notify(GtkWidget *widget, GdkEventMotion *event, dt_iop_module_t *self); -static gboolean dt_iop_levels_button_press(GtkWidget *widget, GdkEventButton *event, dt_iop_module_t *self); -static gboolean dt_iop_levels_button_release(GtkWidget *widget, GdkEventButton *event, dt_iop_module_t *self); -static gboolean dt_iop_levels_leave_notify(GtkWidget *widget, GdkEventCrossing *event, dt_iop_module_t *self); +static void _levels_button_press(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self); +static void _levels_button_release(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self); +static void _levels_motion(GtkEventControllerMotion *controller, + double x, + double y, + dt_iop_module_t *self); +static void _levels_leave(GtkEventControllerMotion *controller, + dt_iop_module_t *self); static gboolean dt_iop_levels_scroll(GtkWidget *widget, GdkEventScroll *event, dt_iop_module_t *self); static void dt_iop_levels_autoadjust_callback(GtkRange *range, dt_iop_module_t *self); //static void dt_iop_levels_mode_callback(GtkWidget *combo, gpointer user_data); @@ -643,10 +655,8 @@ void gui_init(dt_iop_module_t *self) dt_action_define_iop(self, NULL, N_("levels"), GTK_WIDGET(g->area), NULL); g_signal_connect(G_OBJECT(g->area), "draw", G_CALLBACK(dt_iop_levels_area_draw), self); - g_signal_connect(G_OBJECT(g->area), "button-press-event", G_CALLBACK(dt_iop_levels_button_press), self); - g_signal_connect(G_OBJECT(g->area), "button-release-event", G_CALLBACK(dt_iop_levels_button_release), self); - g_signal_connect(G_OBJECT(g->area), "motion-notify-event", G_CALLBACK(dt_iop_levels_motion_notify), self); - g_signal_connect(G_OBJECT(g->area), "leave-notify-event", G_CALLBACK(dt_iop_levels_leave_notify), self); + dt_gui_connect_click(g->area, _levels_button_press, _levels_button_release, self); + dt_gui_connect_motion(g->area, _levels_motion, NULL, _levels_leave, self); g_signal_connect(G_OBJECT(g->area), "scroll-event", G_CALLBACK(dt_iop_levels_scroll), self); GtkWidget *box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); @@ -707,12 +717,12 @@ void gui_cleanup(dt_iop_module_t *self) IOP_GUI_FREE; } -static gboolean dt_iop_levels_leave_notify(GtkWidget *widget, GdkEventCrossing *event, dt_iop_module_t *self) +static void _levels_leave(GtkEventControllerMotion *controller, + dt_iop_module_t *self) { dt_iop_levels_gui_data_t *g = self->gui_data; g->mouse_x = g->mouse_y = -1.0; - gtk_widget_queue_draw(widget); - return TRUE; + gtk_widget_queue_draw(GTK_WIDGET(g->area)); } static gboolean dt_iop_levels_area_draw(GtkWidget *widget, cairo_t *crf, dt_iop_module_t *self) @@ -873,26 +883,29 @@ static void dt_iop_levels_move_handle(dt_iop_module_t *self, int handle_move, fl g->last_picked_color = -1; } -static gboolean dt_iop_levels_motion_notify(GtkWidget *widget, GdkEventMotion *event, dt_iop_module_t *self) +static void _levels_motion(GtkEventControllerMotion *controller, + double x, + double y, + dt_iop_module_t *self) { dt_iop_levels_gui_data_t *g = self->gui_data; dt_iop_levels_params_t *p = self->params; const int inset = DT_GUI_CURVE_EDITOR_INSET; GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); + gtk_widget_get_allocation(GTK_WIDGET(g->area), &allocation); int height = allocation.height - 2 * inset - DT_RESIZE_HANDLE_SIZE, width = allocation.width - 2 * inset; if(!g->dragging) { - g->mouse_x = CLAMP(event->x - inset, 0, width); + g->mouse_x = CLAMP(x - inset, 0, width); g->drag_start_percentage = (p->levels[1] - p->levels[0]) / (p->levels[2] - p->levels[0]); } - g->mouse_y = CLAMP(event->y - inset, 0, height); + g->mouse_y = CLAMP(y - inset, 0, height); if(g->dragging) { if(g->handle_move >= 0 && g->handle_move < 3) { - const float mx = (CLAMP(event->x - inset, 0, width)) / (float)width; + const float mx = (CLAMP(x - inset, 0, width)) / (float)width; dt_iop_levels_move_handle(self, g->handle_move, mx, p->levels, g->drag_start_percentage); } @@ -901,7 +914,7 @@ static gboolean dt_iop_levels_motion_notify(GtkWidget *widget, GdkEventMotion *e else { g->handle_move = 0; - const float mx = CLAMP(event->x - inset, 0, width) / (float)width; + const float mx = CLAMP(x - inset, 0, width) / (float)width; float dist = fabsf(p->levels[0] - mx); for(int k = 1; k < 3; k++) { @@ -913,49 +926,45 @@ static gboolean dt_iop_levels_motion_notify(GtkWidget *widget, GdkEventMotion *e } } } - gtk_widget_queue_draw(widget); - - return TRUE; + gtk_widget_queue_draw(GTK_WIDGET(g->area)); } -static gboolean dt_iop_levels_button_press(GtkWidget *widget, GdkEventButton *event, dt_iop_module_t *self) +static void _levels_button_press(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self) { // set active point - if(event->button == 1) - { - if(darktable.develop->gui_module != self) dt_iop_request_focus(self); + if(darktable.develop->gui_module != self) dt_iop_request_focus(self); - if(event->type == GDK_2BUTTON_PRESS) - { - // Reset - dt_iop_levels_gui_data_t *g = self->gui_data; - memcpy(self->params, self->default_params, self->params_size); + if(n_press == 2) + { + // Reset + dt_iop_levels_gui_data_t *g = self->gui_data; + memcpy(self->params, self->default_params, self->params_size); - // Needed in case the user scrolls or drags immediately after a reset, - // as drag_start_percentage is only updated when the mouse is moved. - g->drag_start_percentage = 0.5; - dt_dev_add_history_item(darktable.develop, self, TRUE); - gtk_widget_queue_draw(GTK_WIDGET(g->area)); - } - else - { - dt_iop_levels_gui_data_t *g = self->gui_data; - g->dragging = 1; - } - return TRUE; + // Needed in case the user scrolls or drags immediately after a reset, + // as drag_start_percentage is only updated when the mouse is moved. + g->drag_start_percentage = 0.5; + dt_dev_add_history_item(darktable.develop, self, TRUE); + gtk_widget_queue_draw(GTK_WIDGET(g->area)); } - return FALSE; -} - -static gboolean dt_iop_levels_button_release(GtkWidget *widget, GdkEventButton *event, dt_iop_module_t *self) -{ - if(event->button == 1) + else { dt_iop_levels_gui_data_t *g = self->gui_data; - g->dragging = 0; - return TRUE; + g->dragging = 1; } - return FALSE; +} + +static void _levels_button_release(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self) +{ + dt_iop_levels_gui_data_t *g = self->gui_data; + g->dragging = 0; } static gboolean dt_iop_levels_scroll(GtkWidget *widget, GdkEventScroll *event, dt_iop_module_t *self) diff --git a/src/iop/lowlight.c b/src/iop/lowlight.c index d857c18175b0..b86f3b57b8e8 100644 --- a/src/iop/lowlight.c +++ b/src/iop/lowlight.c @@ -667,22 +667,25 @@ static gboolean lowlight_draw(GtkWidget *widget, cairo_t *crf, dt_iop_module_t * return FALSE; } -static gboolean lowlight_motion_notify(GtkWidget *widget, GdkEventMotion *event, dt_iop_module_t *self) +static void _lowlight_motion(GtkEventControllerMotion *controller, + double x, + double y, + dt_iop_module_t *self) { dt_iop_lowlight_gui_data_t *g = self->gui_data; dt_iop_lowlight_params_t *p = self->params; const int inset = DT_IOP_LOWLIGHT_INSET; GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); + gtk_widget_get_allocation(GTK_WIDGET(g->area), &allocation); int height = allocation.height - 2 * inset - DT_RESIZE_HANDLE_SIZE, width = allocation.width - 2 * inset; - if(!g->dragging) g->mouse_x = CLAMP(event->x - inset, 0, width) / (float)width; - g->mouse_y = 1.0 - CLAMP(event->y - inset, 0, height) / (float)height; + if(!g->dragging) g->mouse_x = CLAMP(x - inset, 0, width) / (float)width; + g->mouse_y = 1.0 - CLAMP(y - inset, 0, height) / (float)height; if(g->dragging) { *p = g->drag_params; if(g->x_move >= 0) { - const float mx = CLAMP(event->x - inset, 0, width) / (float)width; + const float mx = CLAMP(x - inset, 0, width) / (float)width; if(g->x_move > 0 && g->x_move < DT_IOP_LOWLIGHT_BANDS - 1) { const float minx = p->transition_x[g->x_move - 1] + 0.001f; @@ -694,10 +697,9 @@ static gboolean lowlight_motion_notify(GtkWidget *widget, GdkEventMotion *event, { dt_iop_lowlight_get_params(p, g->mouse_x, g->mouse_y + g->mouse_pick, g->mouse_radius); } - gtk_widget_queue_draw(widget); - dt_dev_add_history_item_target(darktable.develop, self, TRUE, widget); + dt_dev_add_history_item_target(darktable.develop, self, TRUE, g->area); } - else if(event->y > height) + else if(y > height) { g->x_move = 0; float dist = fabs(p->transition_x[0] - g->mouse_x); @@ -710,20 +712,22 @@ static gboolean lowlight_motion_notify(GtkWidget *widget, GdkEventMotion *event, dist = d2; } } - gtk_widget_queue_draw(widget); } else { g->x_move = -1; - gtk_widget_queue_draw(widget); } - return TRUE; + gtk_widget_queue_draw(GTK_WIDGET(g->area)); } -static gboolean lowlight_button_press(GtkWidget *widget, GdkEventButton *event, dt_iop_module_t *self) +static void _lowlight_button_press(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self) { dt_iop_lowlight_gui_data_t *g = self->gui_data; - if(event->button == 1 && event->type == GDK_2BUTTON_PRESS) + if(n_press == 2) { // reset current curve dt_iop_lowlight_params_t *p = self->params; @@ -733,42 +737,39 @@ static gboolean lowlight_button_press(GtkWidget *widget, GdkEventButton *event, p->transition_x[k] = d->transition_x[k]; p->transition_y[k] = d->transition_y[k]; } - dt_dev_add_history_item_target(darktable.develop, self, TRUE, widget); + dt_dev_add_history_item_target(darktable.develop, self, TRUE, g->area); gtk_widget_queue_draw(GTK_WIDGET(g->area)); } - else if(event->button == 1) + else { g->drag_params = *(dt_iop_lowlight_params_t *)self->params; const int inset = DT_IOP_LOWLIGHT_INSET; GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); + gtk_widget_get_allocation(GTK_WIDGET(g->area), &allocation); int height = allocation.height - 2 * inset - DT_RESIZE_HANDLE_SIZE, width = allocation.width - 2 * inset; g->mouse_pick - = dt_draw_curve_calc_value(g->transition_curve, CLAMP(event->x - inset, 0, width) / (float)width); - g->mouse_pick -= 1.0 - CLAMP(event->y - inset, 0, height) / (float)height; + = dt_draw_curve_calc_value(g->transition_curve, CLAMP(x - inset, 0, width) / (float)width); + g->mouse_pick -= 1.0 - CLAMP(y - inset, 0, height) / (float)height; g->dragging = 1; - return TRUE; } - return FALSE; } -static gboolean lowlight_button_release(GtkWidget *widget, GdkEventButton *event, dt_iop_module_t *self) +static void _lowlight_button_release(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self) { - if(event->button == 1) - { - dt_iop_lowlight_gui_data_t *g = self->gui_data; - g->dragging = 0; - return TRUE; - } - return FALSE; + dt_iop_lowlight_gui_data_t *g = self->gui_data; + g->dragging = 0; } -static gboolean lowlight_leave_notify(GtkWidget *widget, GdkEventCrossing *event, dt_iop_module_t *self) +static void _lowlight_leave(GtkEventControllerMotion *controller, + dt_iop_module_t *self) { dt_iop_lowlight_gui_data_t *g = self->gui_data; if(!g->dragging) g->mouse_y = -1.0; - gtk_widget_queue_draw(widget); - return TRUE; + gtk_widget_queue_draw(GTK_WIDGET(g->area)); } static gboolean lowlight_scrolled(GtkWidget *widget, GdkEventScroll *event, dt_iop_module_t *self) @@ -814,10 +815,8 @@ void gui_init(struct dt_iop_module_t *self) gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(g->area), FALSE, FALSE, 0); g_signal_connect(G_OBJECT(g->area), "draw", G_CALLBACK(lowlight_draw), self); - g_signal_connect(G_OBJECT(g->area), "button-press-event", G_CALLBACK(lowlight_button_press), self); - g_signal_connect(G_OBJECT(g->area), "button-release-event", G_CALLBACK(lowlight_button_release), self); - g_signal_connect(G_OBJECT(g->area), "motion-notify-event", G_CALLBACK(lowlight_motion_notify), self); - g_signal_connect(G_OBJECT(g->area), "leave-notify-event", G_CALLBACK(lowlight_leave_notify), self); + dt_gui_connect_click(g->area, _lowlight_button_press, _lowlight_button_release, self); + dt_gui_connect_motion(g->area, _lowlight_motion, NULL, _lowlight_leave, self); g_signal_connect(G_OBJECT(g->area), "scroll-event", G_CALLBACK(lowlight_scrolled), self); g->scale_blueness = dt_bauhaus_slider_from_params(self, "blueness"); diff --git a/src/iop/monochrome.c b/src/iop/monochrome.c index e22a9a548389..5675ffbb79f9 100644 --- a/src/iop/monochrome.c +++ b/src/iop/monochrome.c @@ -452,7 +452,10 @@ void color_picker_apply(dt_iop_module_t *self, GtkWidget *picker, dt_dev_pixelpi dt_control_queue_redraw_widget(self->widget); } -static gboolean _monochrome_motion_notify(GtkWidget *widget, GdkEventMotion *event, dt_iop_module_t *self) +static void _monochrome_motion(GtkEventControllerMotion *controller, + double x, + double y, + dt_iop_module_t *self) { dt_iop_monochrome_gui_data_t *g = self->gui_data; dt_iop_monochrome_params_t *p = self->params; @@ -461,73 +464,68 @@ static gboolean _monochrome_motion_notify(GtkWidget *widget, GdkEventMotion *eve const float old_a = p->a, old_b = p->b; const int inset = DT_COLORCORRECTION_INSET; GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); + gtk_widget_get_allocation(GTK_WIDGET(g->area), &allocation); int width = allocation.width - 2 * inset, height = allocation.height - 2 * inset; - const float mouse_x = CLAMP(event->x - inset, 0, width); - const float mouse_y = CLAMP(height - 1 - event->y + inset, 0, height); + const float mouse_x = CLAMP(x - inset, 0, width); + const float mouse_y = CLAMP(height - 1 - y + inset, 0, height); p->a = PANEL_WIDTH * (mouse_x - width * 0.5f) / (float)width; p->b = PANEL_WIDTH * (mouse_y - height * 0.5f) / (float)height; if(old_a != p->a || old_b != p->b) dt_dev_add_history_item(darktable.develop, self, TRUE); gtk_widget_queue_draw(GTK_WIDGET(g->area)); } - return TRUE; } -static gboolean _monochrome_button_press(GtkWidget *widget, GdkEventButton *event, dt_iop_module_t *self) +static void _monochrome_button_press(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self) { - if(event->button == 1) + dt_iop_monochrome_gui_data_t *g = self->gui_data; + dt_iop_monochrome_params_t *p = self->params; + dt_iop_color_picker_reset(self, TRUE); + if(n_press == 2) { - dt_iop_monochrome_gui_data_t *g = self->gui_data; - dt_iop_monochrome_params_t *p = self->params; - dt_iop_color_picker_reset(self, TRUE); - if(event->type == GDK_2BUTTON_PRESS) - { - // reset - const dt_iop_monochrome_params_t *const p0 = self->default_params; - p->a = p0->a; - p->b = p0->b; - p->size = p0->size; - } - else - { - const int inset = DT_COLORCORRECTION_INSET; - GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); - int width = allocation.width - 2 * inset, height = allocation.height - 2 * inset; - const float mouse_x = CLAMP(event->x - inset, 0, width); - const float mouse_y = CLAMP(height - 1 - event->y + inset, 0, height); - p->a = PANEL_WIDTH * (mouse_x - width * 0.5f) / (float)width; - p->b = PANEL_WIDTH * (mouse_y - height * 0.5f) / (float)height; - g->dragging = 1; - g_object_set(G_OBJECT(widget), "has-tooltip", FALSE, (gchar *)0); - } - gtk_widget_queue_draw(GTK_WIDGET(g->area)); - return TRUE; + // reset + const dt_iop_monochrome_params_t *const p0 = self->default_params; + p->a = p0->a; + p->b = p0->b; + p->size = p0->size; } - return FALSE; + else + { + const int inset = DT_COLORCORRECTION_INSET; + GtkAllocation allocation; + gtk_widget_get_allocation(GTK_WIDGET(g->area), &allocation); + int width = allocation.width - 2 * inset, height = allocation.height - 2 * inset; + const float mouse_x = CLAMP(x - inset, 0, width); + const float mouse_y = CLAMP(height - 1 - y + inset, 0, height); + p->a = PANEL_WIDTH * (mouse_x - width * 0.5f) / (float)width; + p->b = PANEL_WIDTH * (mouse_y - height * 0.5f) / (float)height; + g->dragging = 1; + } + gtk_widget_queue_draw(GTK_WIDGET(g->area)); } -static gboolean _monochrome_button_release(GtkWidget *widget, GdkEventButton *event, dt_iop_module_t *self) +static void _monochrome_button_release(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self) { - if(event->button == 1) - { - dt_iop_monochrome_gui_data_t *g = self->gui_data; - dt_iop_color_picker_reset(self, TRUE); - g->dragging = 0; - dt_dev_add_history_item(darktable.develop, self, TRUE); - g_object_set(G_OBJECT(widget), "has-tooltip", TRUE, (gchar *)0); - return TRUE; - } - return FALSE; + dt_iop_monochrome_gui_data_t *g = self->gui_data; + dt_iop_color_picker_reset(self, TRUE); + g->dragging = 0; + dt_dev_add_history_item(darktable.develop, self, TRUE); } -static gboolean _monochrome_leave_notify(GtkWidget *widget, GdkEventCrossing *event, dt_iop_module_t *self) +static void _monochrome_leave(GtkEventControllerMotion *controller, + dt_iop_module_t *self) { dt_iop_monochrome_gui_data_t *g = self->gui_data; g->dragging = 0; gtk_widget_queue_draw(GTK_WIDGET(g->area)); - return TRUE; } static gboolean _monochrome_scrolled(GtkWidget *widget, GdkEventScroll *event, dt_iop_module_t *self) @@ -563,16 +561,10 @@ void gui_init(struct dt_iop_module_t *self) gtk_widget_set_tooltip_text(GTK_WIDGET(g->area), _("drag and scroll mouse wheel to adjust the virtual color filter")); dt_action_define_iop(self, NULL, N_("grid"), GTK_WIDGET(g->area), NULL); - gtk_widget_add_events(GTK_WIDGET(g->area), GDK_POINTER_MOTION_MASK - | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_LEAVE_NOTIFY_MASK | darktable.gui->scroll_mask); + gtk_widget_add_events(GTK_WIDGET(g->area), darktable.gui->scroll_mask); g_signal_connect(G_OBJECT(g->area), "draw", G_CALLBACK(_monochrome_draw), self); - g_signal_connect(G_OBJECT(g->area), "button-press-event", G_CALLBACK(_monochrome_button_press), self); - g_signal_connect(G_OBJECT(g->area), "button-release-event", G_CALLBACK(_monochrome_button_release), - self); - g_signal_connect(G_OBJECT(g->area), "motion-notify-event", G_CALLBACK(_monochrome_motion_notify), - self); - g_signal_connect(G_OBJECT(g->area), "leave-notify-event", G_CALLBACK(_monochrome_leave_notify), self); + dt_gui_connect_click(g->area, _monochrome_button_press, _monochrome_button_release, self); + dt_gui_connect_motion(g->area, _monochrome_motion, NULL, _monochrome_leave, self); g_signal_connect(G_OBJECT(g->area), "scroll-event", G_CALLBACK(_monochrome_scrolled), self); g->highlights diff --git a/src/iop/rawdenoise.c b/src/iop/rawdenoise.c index 15239eeda549..93fb0fd6376c 100644 --- a/src/iop/rawdenoise.c +++ b/src/iop/rawdenoise.c @@ -766,16 +766,19 @@ static gboolean rawdenoise_draw(GtkWidget *widget, cairo_t *crf, dt_iop_module_t return FALSE; } -static gboolean rawdenoise_motion_notify(GtkWidget *widget, GdkEventMotion *event, dt_iop_module_t *self) +static void _rawdenoise_motion(GtkEventControllerMotion *controller, + double x, + double y, + dt_iop_module_t *self) { dt_iop_rawdenoise_gui_data_t *g = self->gui_data; dt_iop_rawdenoise_params_t *p = self->params; const int inset = DT_IOP_RAWDENOISE_INSET; GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); + gtk_widget_get_allocation(GTK_WIDGET(g->area), &allocation); int height = allocation.height - 2 * inset, width = allocation.width - 2 * inset; - if(!g->dragging) g->mouse_x = CLAMP(event->x - inset, 0, width) / (float)width; - g->mouse_y = 1.0 - CLAMP(event->y - inset, 0, height) / (float)height; + if(!g->dragging) g->mouse_x = CLAMP(x - inset, 0, width) / (float)width; + g->mouse_y = 1.0 - CLAMP(y - inset, 0, height) / (float)height; if(g->dragging) { *p = g->drag_params; @@ -783,22 +786,24 @@ static gboolean rawdenoise_motion_notify(GtkWidget *widget, GdkEventMotion *even { dt_iop_rawdenoise_get_params(p, g->channel, g->mouse_x, g->mouse_y + g->mouse_pick, g->mouse_radius); } - gtk_widget_queue_draw(widget); - dt_dev_add_history_item_target(darktable.develop, self, TRUE, widget + g->channel); + dt_dev_add_history_item_target(darktable.develop, self, TRUE, g->area + g->channel); } else { g->x_move = -1; - gtk_widget_queue_draw(widget); } - return TRUE; + gtk_widget_queue_draw(GTK_WIDGET(g->area)); } -static gboolean rawdenoise_button_press(GtkWidget *widget, GdkEventButton *event, dt_iop_module_t *self) +static void _rawdenoise_button_press(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self) { dt_iop_rawdenoise_gui_data_t *g = self->gui_data; const int ch = g->channel; - if(event->button == 1 && event->type == GDK_2BUTTON_PRESS) + if(n_press == 2) { // reset current curve dt_iop_rawdenoise_params_t *p = self->params; @@ -808,42 +813,39 @@ static gboolean rawdenoise_button_press(GtkWidget *widget, GdkEventButton *event p->x[ch][k] = d->x[ch][k]; p->y[ch][k] = d->y[ch][k]; } - dt_dev_add_history_item_target(darktable.develop, self, TRUE, widget + ch); + dt_dev_add_history_item_target(darktable.develop, self, TRUE, g->area + ch); gtk_widget_queue_draw(GTK_WIDGET(g->area)); } - else if(event->button == 1) + else { g->drag_params = *(dt_iop_rawdenoise_params_t *)self->params; const int inset = DT_IOP_RAWDENOISE_INSET; GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); + gtk_widget_get_allocation(GTK_WIDGET(g->area), &allocation); int height = allocation.height - 2 * inset, width = allocation.width - 2 * inset; g->mouse_pick - = dt_draw_curve_calc_value(g->transition_curve, CLAMP(event->x - inset, 0, width) / (float)width); - g->mouse_pick -= 1.0 - CLAMP(event->y - inset, 0, height) / (float)height; + = dt_draw_curve_calc_value(g->transition_curve, CLAMP(x - inset, 0, width) / (float)width); + g->mouse_pick -= 1.0 - CLAMP(y - inset, 0, height) / (float)height; g->dragging = 1; - return TRUE; } - return FALSE; } -static gboolean rawdenoise_button_release(GtkWidget *widget, GdkEventButton *event, dt_iop_module_t *self) +static void _rawdenoise_button_release(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self) { - if(event->button == 1) - { - dt_iop_rawdenoise_gui_data_t *g = self->gui_data; - g->dragging = 0; - return TRUE; - } - return FALSE; + dt_iop_rawdenoise_gui_data_t *g = self->gui_data; + g->dragging = 0; } -static gboolean rawdenoise_leave_notify(GtkWidget *widget, GdkEventCrossing *event, dt_iop_module_t *self) +static void _rawdenoise_leave(GtkEventControllerMotion *controller, + dt_iop_module_t *self) { dt_iop_rawdenoise_gui_data_t *g = self->gui_data; if(!g->dragging) g->mouse_y = -1.0; - gtk_widget_queue_draw(widget); - return TRUE; + gtk_widget_queue_draw(GTK_WIDGET(g->area)); } static gboolean rawdenoise_scrolled(GtkWidget *widget, GdkEventScroll *event, dt_iop_module_t *self) @@ -916,10 +918,8 @@ void gui_init(dt_iop_module_t *self) gtk_box_pack_start(GTK_BOX(box_raw), GTK_WIDGET(g->area), FALSE, FALSE, 0); g_signal_connect(G_OBJECT(g->area), "draw", G_CALLBACK(rawdenoise_draw), self); - g_signal_connect(G_OBJECT(g->area), "button-press-event", G_CALLBACK(rawdenoise_button_press), self); - g_signal_connect(G_OBJECT(g->area), "button-release-event", G_CALLBACK(rawdenoise_button_release), self); - g_signal_connect(G_OBJECT(g->area), "motion-notify-event", G_CALLBACK(rawdenoise_motion_notify), self); - g_signal_connect(G_OBJECT(g->area), "leave-notify-event", G_CALLBACK(rawdenoise_leave_notify), self); + dt_gui_connect_click(g->area, _rawdenoise_button_press, _rawdenoise_button_release, self); + dt_gui_connect_motion(g->area, _rawdenoise_motion, NULL, _rawdenoise_leave, self); g_signal_connect(G_OBJECT(g->area), "scroll-event", G_CALLBACK(rawdenoise_scrolled), self); g->threshold = dt_bauhaus_slider_from_params(self, "threshold"); diff --git a/src/iop/rgbcurve.c b/src/iop/rgbcurve.c index 28f934b5d359..7253a1ec0854 100644 --- a/src/iop/rgbcurve.c +++ b/src/iop/rgbcurve.c @@ -749,16 +749,15 @@ static gboolean _area_key_press_callback(GtkWidget *widget, #undef RGBCURVE_DEFAULT_STEP -static gboolean _area_leave_notify_callback(GtkWidget *widget, - GdkEventCrossing *event, - dt_iop_module_t *self) +static void _rgbcurve_leave(GtkEventControllerMotion *controller, + dt_iop_module_t *self) { dt_iop_rgbcurve_gui_data_t *g = self->gui_data; + GdkEventCrossing *event = (GdkEventCrossing *)gtk_get_current_event(); if(!(event->state & GDK_BUTTON1_MASK)) g->selected = -1; - gtk_widget_queue_draw(widget); - return FALSE; + gtk_widget_queue_draw(GTK_WIDGET(g->area)); } static gboolean _area_draw_callback(GtkWidget *widget, @@ -1171,28 +1170,29 @@ static gboolean _area_draw_callback(GtkWidget *widget, return TRUE; } -static gboolean _area_motion_notify_callback(GtkWidget *widget, - GdkEventMotion *event, - dt_iop_module_t *self) +static void _rgbcurve_motion(GtkEventControllerMotion *controller, + double x, + double y, + dt_iop_module_t *self) { dt_iop_rgbcurve_gui_data_t *g = self->gui_data; dt_iop_rgbcurve_params_t *p = self->params; const int inset = DT_GUI_CURVE_EDITOR_INSET; + GtkAllocation allocation; + gtk_widget_get_allocation(GTK_WIDGET(g->area), &allocation); + const int height = allocation.height - 2 * inset; + const int width = allocation.width - 2 * inset; + GdkEventMotion *event = (GdkEventMotion *)gtk_get_current_event(); // drag the draw area if(darktable.develop->darkroom_skip_mouse_events) { - GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); - const int height = allocation.height - 2 * inset; - const int width = allocation.width - 2 * inset; - const float mx = g->mouse_x; const float my = g->mouse_y; - g->mouse_x = CLAMP(event->x - inset, 0, width) / (float)width; - g->mouse_y = 1.0 - CLAMP(event->y - inset, 0, height) / (float)height; + g->mouse_x = CLAMP(x - inset, 0, width) / (float)width; + g->mouse_y = 1.0 - CLAMP(y - inset, 0, height) / (float)height; if(event->state & GDK_BUTTON1_MASK) { @@ -1204,7 +1204,7 @@ static gboolean _area_motion_notify_callback(GtkWidget *widget, gtk_widget_queue_draw(GTK_WIDGET(g->area)); } - return TRUE; + return; } const int ch = g->channel; @@ -1216,15 +1216,11 @@ static gboolean _area_motion_notify_callback(GtkWidget *widget, && g->channel != DT_IOP_RGBCURVE_R) goto finally; - GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); - const int height = allocation.height - 2 * inset, width = allocation.width - 2 * inset; - const double old_m_x = g->mouse_x; const double old_m_y = g->mouse_y; - g->mouse_x = CLAMP(event->x - inset, 0, width) / (float)width; - g->mouse_y = 1.0 - CLAMP(event->y - inset, 0, height) / (float)height; + g->mouse_x = CLAMP(x - inset, 0, width) / (float)width; + g->mouse_y = 1.0 - CLAMP(y - inset, 0, height) / (float)height; const float mx = g->mouse_x; const float my = g->mouse_y; @@ -1255,14 +1251,15 @@ static gboolean _area_motion_notify_callback(GtkWidget *widget, g->zoom_factor, g->offset_y); dt_iop_color_picker_reset(self, TRUE); - return _move_point_internal(self, widget, dx, dy, event->state); + _move_point_internal(self, GTK_WIDGET(g->area), dx, dy, event->state); + return; } else if(nodes < DT_IOP_RGBCURVE_MAXNODES && g->selected >= -1) { dt_iop_color_picker_reset(self, TRUE); // no vertex was close, create a new one! g->selected = _add_node(curve_nodes, &p->curve_num_nodes[ch], linx, liny); - dt_dev_add_history_item_target(darktable.develop, self, TRUE, widget + ch); + dt_dev_add_history_item_target(darktable.develop, self, TRUE, g->area + ch); } } else @@ -1289,43 +1286,45 @@ static gboolean _area_motion_notify_callback(GtkWidget *widget, g->selected = nearest; } finally: - if(g->selected >= 0) gtk_widget_grab_focus(widget); - gtk_widget_queue_draw(widget); - return TRUE; + if(g->selected >= 0) gtk_widget_grab_focus(GTK_WIDGET(g->area)); + gtk_widget_queue_draw(GTK_WIDGET(g->area)); } -static gboolean _area_button_press_callback(GtkWidget *widget, - GdkEventButton *event, - dt_iop_module_t *self) +static void _rgbcurve_button_press(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self) { dt_iop_rgbcurve_params_t *p = self->params; const dt_iop_rgbcurve_params_t *const d = self->default_params; dt_iop_rgbcurve_gui_data_t *g = self->gui_data; - if(darktable.develop->darkroom_skip_mouse_events) - return TRUE; + if(darktable.develop->darkroom_skip_mouse_events) return; const int ch = g->channel; const int autoscale = p->curve_autoscale; const int nodes = p->curve_num_nodes[ch]; dt_iop_rgbcurve_node_t *curve_nodes = p->curve_nodes[ch]; - if(event->button == 1) + guint button = gtk_gesture_single_get_current_button(gesture); + if(button == 1) { - if(event->type == GDK_BUTTON_PRESS - && dt_modifier_is(event->state, GDK_CONTROL_MASK) + dt_gui_claim(gesture); + if(n_press == 1 + && dt_modifier_eq(gesture, GDK_CONTROL_MASK) && nodes < DT_IOP_RGBCURVE_MAXNODES && g->selected == -1) { // if we are not on a node -> add a new node at the current x of // the pointer and y of the curve at that x const int inset = DT_GUI_CURVE_EDITOR_INSET; GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); + gtk_widget_get_allocation(GTK_WIDGET(g->area), &allocation); const int width = allocation.width - 2 * inset; const int height = allocation.height - 2 * inset; - g->mouse_x = CLAMP(event->x - inset, 0, width) / (float)width; - g->mouse_y = 1.0 - CLAMP(event->y - inset, 0, height) / (float)height; + g->mouse_x = CLAMP(x - inset, 0, width) / (float)width; + g->mouse_y = 1.0 - CLAMP(y - inset, 0, height) / (float)height; const float mx = g->mouse_x; const float linx = _mouse_to_curve(mx, g->zoom_factor, g->offset_x); @@ -1348,34 +1347,32 @@ static gboolean _area_button_press_callback(GtkWidget *widget, } if(selected == -1) selected = nodes; - // evaluate the curve at the current x position - const float y = dt_draw_curve_calc_value(g->minmax_curve[ch], linx); + // evaluate the curve at the current x position + const float calc_y = dt_draw_curve_calc_value(g->minmax_curve[ch], linx); - if(y >= 0.0f && y <= 1.0f) // never add something outside the - // viewport, you couldn't change it - // afterwards - { - // create a new node - selected = _add_node(curve_nodes, &p->curve_num_nodes[ch], linx, y); - - // maybe set the new one as being selected - const float min = .04f * .04f; // comparing against square - for(int k = 0; k < nodes; k++) - { - const float other_y = - _curve_to_mouse(curve_nodes[k].y, g->zoom_factor, g->offset_y); - const float dist = (y - other_y) * (y - other_y); - if(dist < min) g->selected = selected; - } + if(calc_y >= 0.0f && calc_y <= 1.0f) // never add something outside the + // viewport, you couldn't change it + // afterwards + { + // create a new node + selected = _add_node(curve_nodes, &p->curve_num_nodes[ch], linx, calc_y); - dt_iop_color_picker_reset(self, TRUE); - dt_dev_add_history_item_target(darktable.develop, self, TRUE, widget + ch); - gtk_widget_queue_draw(GTK_WIDGET(g->area)); + // maybe set the new one as being selected + const float min = .04f * .04f; // comparing against square + for(int k = 0; k < nodes; k++) + { + const float other_y = + _curve_to_mouse(curve_nodes[k].y, g->zoom_factor, g->offset_y); + const float dist = (calc_y - other_y) * (calc_y - other_y); + if(dist < min) g->selected = selected; } - return TRUE; + dt_iop_color_picker_reset(self, TRUE); + dt_dev_add_history_item_target(darktable.develop, self, TRUE, g->area + ch); + gtk_widget_queue_draw(GTK_WIDGET(g->area)); + } } - else if(event->type == GDK_2BUTTON_PRESS) + else if(n_press == 2) { // reset current curve // if autoscale is on: allow only reset of L curve @@ -1391,7 +1388,7 @@ static gboolean _area_button_press_callback(GtkWidget *widget, g->selected = -2; // avoid motion notify re-inserting immediately. dt_bauhaus_combobox_set(g->interpolator, p->curve_type[DT_IOP_RGBCURVE_R]); dt_iop_color_picker_reset(self, TRUE); - dt_dev_add_history_item_target(darktable.develop, self, TRUE, widget + ch); + dt_dev_add_history_item_target(darktable.develop, self, TRUE, g->area + ch); gtk_widget_queue_draw(GTK_WIDGET(g->area)); } else @@ -1402,23 +1399,23 @@ static gboolean _area_button_press_callback(GtkWidget *widget, g->selected = -2; // avoid motion notify re-inserting immediately. dt_bauhaus_combobox_set(g->autoscale, 1); dt_iop_color_picker_reset(self, TRUE); - dt_dev_add_history_item_target(darktable.develop, self, TRUE, widget + ch); + dt_dev_add_history_item_target(darktable.develop, self, TRUE, g->area + ch); gtk_widget_queue_draw(GTK_WIDGET(g->area)); } } - return TRUE; } } - else if(event->button == 3 && g->selected >= 0) + else if(button == 3 && g->selected >= 0) { + dt_gui_claim(gesture); if(g->selected == 0 || g->selected == nodes - 1) { const float reset_value = g->selected == 0 ? 0.f : 1.f; curve_nodes[g->selected].y = curve_nodes[g->selected].x = reset_value; dt_iop_color_picker_reset(self, TRUE); - dt_dev_add_history_item_target(darktable.develop, self, TRUE, widget + ch); + dt_dev_add_history_item_target(darktable.develop, self, TRUE, g->area + ch); gtk_widget_queue_draw(GTK_WIDGET(g->area)); - return TRUE; + return; } for(int k = g->selected; k < nodes - 1; k++) @@ -1430,11 +1427,9 @@ static gboolean _area_button_press_callback(GtkWidget *widget, g->selected = -2; // avoid re-insertion of that point immediately after this p->curve_num_nodes[ch]--; dt_iop_color_picker_reset(self, TRUE); - dt_dev_add_history_item_target(darktable.develop, self, TRUE, widget + ch); + dt_dev_add_history_item_target(darktable.develop, self, TRUE, g->area + ch); gtk_widget_queue_draw(GTK_WIDGET(g->area)); - return TRUE; } - return FALSE; } void gui_reset(struct dt_iop_module_t *self) @@ -1542,19 +1537,12 @@ void gui_init(struct dt_iop_module_t *self) // gtk_widget_set_tooltip_text(GTK_WIDGET(g->area), _("double click // to reset curve")); - gtk_widget_add_events(GTK_WIDGET(g->area), - GDK_POINTER_MOTION_MASK | darktable.gui->scroll_mask - | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); + gtk_widget_add_events(GTK_WIDGET(g->area), darktable.gui->scroll_mask); gtk_widget_set_can_focus(GTK_WIDGET(g->area), TRUE); g_signal_connect(G_OBJECT(g->area), "draw", G_CALLBACK(_area_draw_callback), self); - g_signal_connect(G_OBJECT(g->area), "button-press-event", - G_CALLBACK(_area_button_press_callback), self); - g_signal_connect(G_OBJECT(g->area), "motion-notify-event", - G_CALLBACK(_area_motion_notify_callback), self); - g_signal_connect(G_OBJECT(g->area), "leave-notify-event", - G_CALLBACK(_area_leave_notify_callback), self); + dt_gui_connect_click_all(g->area, _rgbcurve_button_press, NULL, self); + dt_gui_connect_motion(g->area, _rgbcurve_motion, NULL, _rgbcurve_leave, self); g_signal_connect(G_OBJECT(g->area), "scroll-event", G_CALLBACK(_area_scrolled_callback), self); g_signal_connect(G_OBJECT(g->area), "key-press-event", diff --git a/src/iop/rgblevels.c b/src/iop/rgblevels.c index c920c5c5efd5..6dfd4887e906 100644 --- a/src/iop/rgblevels.c +++ b/src/iop/rgblevels.c @@ -363,14 +363,12 @@ void gui_post_expose(dt_iop_module_t *self, cairo_stroke(cr); } -static gboolean _area_leave_notify_callback(GtkWidget *widget, - GdkEventCrossing *event, - dt_iop_module_t *self) +static void _rgblevels_leave(GtkEventControllerMotion *controller, + dt_iop_module_t *self) { dt_iop_rgblevels_gui_data_t *g = self->gui_data; g->mouse_x = g->mouse_y = -1.0; - gtk_widget_queue_draw(widget); - return TRUE; + gtk_widget_queue_draw(GTK_WIDGET(g->area)); } static gboolean _area_draw_callback(GtkWidget *widget, @@ -553,28 +551,29 @@ static void _rgblevels_move_handle(dt_iop_module_t *self, gtk_widget_queue_draw(GTK_WIDGET(g->area)); } -static gboolean _area_motion_notify_callback(GtkWidget *widget, - GdkEventMotion *event, - dt_iop_module_t *self) +static void _rgblevels_motion(GtkEventControllerMotion *controller, + double x, + double y, + dt_iop_module_t *self) { dt_iop_rgblevels_gui_data_t *g = self->gui_data; dt_iop_rgblevels_params_t *p = self->params; const int inset = DT_GUI_CURVE_EDITOR_INSET; GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); + gtk_widget_get_allocation(GTK_WIDGET(g->area), &allocation); int height = allocation.height - 2 * inset - DT_RESIZE_HANDLE_SIZE, width = allocation.width - 2 * inset; if(!g->dragging) { - g->mouse_x = CLAMP(event->x - inset, 0, width); + g->mouse_x = CLAMP(x - inset, 0, width); g->drag_start_percentage = (p->levels[g->channel][1] - p->levels[g->channel][0]) / (p->levels[g->channel][2] - p->levels[g->channel][0]); } - g->mouse_y = CLAMP(event->y - inset, 0, height); + g->mouse_y = CLAMP(y - inset, 0, height); if(g->dragging) { if(g->handle_move >= 0 && g->handle_move < 3) { - const float mx = (CLAMP(event->x - inset, 0, width)) / (float)width; + const float mx = (CLAMP(x - inset, 0, width)) / (float)width; _rgblevels_move_handle(self, g->handle_move, mx, p->levels[g->channel], g->drag_start_percentage); } @@ -582,7 +581,7 @@ static gboolean _area_motion_notify_callback(GtkWidget *widget, else { g->handle_move = 0; - const float mx = CLAMP(event->x - inset, 0, width) / (float)width; + const float mx = CLAMP(x - inset, 0, width) / (float)width; float dist = fabsf(p->levels[g->channel][0] - mx); for(int k = 1; k < 3; k++) { @@ -596,62 +595,54 @@ static gboolean _area_motion_notify_callback(GtkWidget *widget, darktable.control->element = g->handle_move; - gtk_widget_queue_draw(widget); + gtk_widget_queue_draw(GTK_WIDGET(g->area)); } - - return TRUE; } -static gboolean _area_button_press_callback(GtkWidget *widget, - GdkEventButton *event, - dt_iop_module_t *self) +static void _rgblevels_button_press(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self) { // set active point - if(event->button == 1) - { - if(darktable.develop->gui_module != self) dt_iop_request_focus(self); + if(darktable.develop->gui_module != self) dt_iop_request_focus(self); - if(event->type == GDK_2BUTTON_PRESS) - { - _turn_selregion_picker_off(self); + if(n_press == 2) + { + _turn_selregion_picker_off(self); - // Reset - dt_iop_rgblevels_gui_data_t *g = self->gui_data; - dt_iop_rgblevels_params_t *p = self->params; - const dt_iop_rgblevels_params_t *const default_params = self->default_params; + // Reset + dt_iop_rgblevels_gui_data_t *g = self->gui_data; + dt_iop_rgblevels_params_t *p = self->params; + const dt_iop_rgblevels_params_t *const default_params = self->default_params; - for(int i = 0; i < 3; i++) - p->levels[g->channel][i] = default_params->levels[g->channel][i]; + for(int i = 0; i < 3; i++) + p->levels[g->channel][i] = default_params->levels[g->channel][i]; - // Needed in case the user scrolls or drags immediately after a reset, - // as drag_start_percentage is only updated when the mouse is moved. - g->drag_start_percentage = 0.5; - dt_dev_add_history_item(darktable.develop, self, TRUE); - gtk_widget_queue_draw(GTK_WIDGET(g->area)); - } - else - { - _turn_selregion_picker_off(self); + // Needed in case the user scrolls or drags immediately after a reset, + // as drag_start_percentage is only updated when the mouse is moved. + g->drag_start_percentage = 0.5; + dt_dev_add_history_item(darktable.develop, self, TRUE); + gtk_widget_queue_draw(GTK_WIDGET(g->area)); + } + else + { + _turn_selregion_picker_off(self); - dt_iop_rgblevels_gui_data_t *g = self->gui_data; - g->dragging = 1; - } - return TRUE; + dt_iop_rgblevels_gui_data_t *g = self->gui_data; + g->dragging = 1; } - return FALSE; } -static gboolean _area_button_release_callback(GtkWidget *widget, - GdkEventButton *event, - dt_iop_module_t *self) +static void _rgblevels_button_release(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self) { - if(event->button == 1) - { - dt_iop_rgblevels_gui_data_t *g = self->gui_data; - g->dragging = 0; - return TRUE; - } - return FALSE; + dt_iop_rgblevels_gui_data_t *g = self->gui_data; + g->dragging = 0; } static gboolean _area_scroll_callback(GtkWidget *widget, @@ -1061,14 +1052,8 @@ void gui_init(dt_iop_module_t *self) "operates on L channel.")); g_signal_connect(G_OBJECT(g->area), "draw", G_CALLBACK(_area_draw_callback), self); - g_signal_connect(G_OBJECT(g->area), "button-press-event", - G_CALLBACK(_area_button_press_callback), self); - g_signal_connect(G_OBJECT(g->area), "button-release-event", - G_CALLBACK(_area_button_release_callback), self); - g_signal_connect(G_OBJECT(g->area), "motion-notify-event", - G_CALLBACK(_area_motion_notify_callback), self); - g_signal_connect(G_OBJECT(g->area), "leave-notify-event", - G_CALLBACK(_area_leave_notify_callback), self); + dt_gui_connect_click(g->area, _rgblevels_button_press, _rgblevels_button_release, self); + dt_gui_connect_motion(g->area, _rgblevels_motion, NULL, _rgblevels_leave, self); g_signal_connect(G_OBJECT(g->area), "scroll-event", G_CALLBACK(_area_scroll_callback), self); diff --git a/src/iop/tonecurve.c b/src/iop/tonecurve.c index 6cf07090049a..eab8ba84d429 100644 --- a/src/iop/tonecurve.c +++ b/src/iop/tonecurve.c @@ -53,15 +53,17 @@ DT_MODULE_INTROSPECTION(5, dt_iop_tonecurve_params_t) static gboolean dt_iop_tonecurve_draw(GtkWidget *widget, cairo_t *crf, dt_iop_module_t *self); -static gboolean dt_iop_tonecurve_motion_notify(GtkWidget *widget, - GdkEventMotion *event, - dt_iop_module_t *self); -static gboolean dt_iop_tonecurve_button_press(GtkWidget *widget, - GdkEventButton *event, - dt_iop_module_t *self); -static gboolean dt_iop_tonecurve_leave_notify(GtkWidget *widget, - GdkEventCrossing *event, - dt_iop_module_t *self); +static void _tonecurve_button_press(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self); +static void _tonecurve_motion(GtkEventControllerMotion *controller, + double x, + double y, + dt_iop_module_t *self); +static void _tonecurve_leave(GtkEventControllerMotion *controller, + dt_iop_module_t *self); static gboolean dt_iop_tonecurve_key_press(GtkWidget *widget, GdkEventKey *event, dt_iop_module_t *self); @@ -1294,17 +1296,11 @@ void gui_init(struct dt_iop_module_t *self) // FIXME: that tooltip goes in the way of the numbers when you hover a node to get a reading //gtk_widget_set_tooltip_text(GTK_WIDGET(g->area), _("double click to reset curve")); - gtk_widget_add_events(GTK_WIDGET(g->area), GDK_POINTER_MOTION_MASK | darktable.gui->scroll_mask - | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); + gtk_widget_add_events(GTK_WIDGET(g->area), darktable.gui->scroll_mask); gtk_widget_set_can_focus(GTK_WIDGET(g->area), TRUE); g_signal_connect(G_OBJECT(g->area), "draw", G_CALLBACK(dt_iop_tonecurve_draw), self); - g_signal_connect(G_OBJECT(g->area), "button-press-event", - G_CALLBACK(dt_iop_tonecurve_button_press), self); - g_signal_connect(G_OBJECT(g->area), "motion-notify-event", - G_CALLBACK(dt_iop_tonecurve_motion_notify), self); - g_signal_connect(G_OBJECT(g->area), "leave-notify-event", - G_CALLBACK(dt_iop_tonecurve_leave_notify), self); + dt_gui_connect_click_all(g->area, _tonecurve_button_press, NULL, self); + dt_gui_connect_motion(g->area, _tonecurve_motion, NULL, _tonecurve_leave, self); g_signal_connect(G_OBJECT(g->area), "scroll-event", G_CALLBACK(_scrolled), self); g_signal_connect(G_OBJECT(g->area), "key-press-event", @@ -1357,15 +1353,14 @@ void gui_cleanup(struct dt_iop_module_t *self) IOP_GUI_FREE; } -static gboolean dt_iop_tonecurve_leave_notify(GtkWidget *widget, - GdkEventCrossing *event, - dt_iop_module_t *self) +static void _tonecurve_leave(GtkEventControllerMotion *controller, + dt_iop_module_t *self) { dt_iop_tonecurve_gui_data_t *g = self->gui_data; + GdkEventMotion *event = (GdkEventMotion *)gtk_get_current_event(); if(!(event->state & GDK_BUTTON1_MASK)) g->selected = -1; - gtk_widget_queue_draw(widget); - return FALSE; + gtk_widget_queue_draw(GTK_WIDGET(g->area)); } static void picker_scale(const float *in, float *out) @@ -1765,12 +1760,14 @@ static inline int _add_node(dt_iop_tonecurve_node_t *tonecurve, return selected; } -static gboolean dt_iop_tonecurve_motion_notify(GtkWidget *widget, - GdkEventMotion *event, - dt_iop_module_t *self) +static void _tonecurve_motion(GtkEventControllerMotion *controller, + double x, + double y, + dt_iop_module_t *self) { dt_iop_tonecurve_gui_data_t *g = self->gui_data; dt_iop_tonecurve_params_t *p = self->params; + GtkWidget *widget = GTK_WIDGET(g->area); int ch = g->channel; int nodes = p->tonecurve_nodes[ch]; @@ -1786,14 +1783,15 @@ static gboolean dt_iop_tonecurve_motion_notify(GtkWidget *widget, int height = allocation.height - 2 * inset, width = allocation.width - 2 * inset; double old_m_x = g->mouse_x; double old_m_y = g->mouse_y; - g->mouse_x = event->x - inset; - g->mouse_y = event->y - inset; + g->mouse_x = x - inset; + g->mouse_y = y - inset; const float mx = CLAMP(g->mouse_x, 0, width) / width; const float my = 1.0f - CLAMP(g->mouse_y, 0, height) / height; const float linx = to_lin(mx, g->loglogscale, ch, g->semilog, 0), liny = to_lin(my, g->loglogscale, ch, g->semilog, 1); + GdkEventMotion *event = (GdkEventMotion *)gtk_get_current_event(); if(event->state & GDK_BUTTON1_MASK) { // got a vertex selected: @@ -1808,7 +1806,8 @@ static gboolean dt_iop_tonecurve_motion_notify(GtkWidget *widget, - to_lin(old_m_x / width - translate_mouse_x, g->loglogscale, ch, g->semilog, 0); const float dy = to_lin(1 - g->mouse_y / height - translate_mouse_y, g->loglogscale, ch, g->semilog, 1) - to_lin(1 - old_m_y / height - translate_mouse_y, g->loglogscale, ch, g->semilog, 1); - return _move_point_internal(self, widget, dx, dy, event->state); + _move_point_internal(self, widget, dx, dy, event->state); + return; } else if(nodes < DT_IOP_TONECURVE_MAXNODES && g->selected >= -1) { @@ -1839,12 +1838,13 @@ static gboolean dt_iop_tonecurve_motion_notify(GtkWidget *widget, finally: if(g->selected >= 0) gtk_widget_grab_focus(widget); gtk_widget_queue_draw(widget); - return TRUE; } -static gboolean dt_iop_tonecurve_button_press(GtkWidget *widget, - GdkEventButton *event, - dt_iop_module_t *self) +static void _tonecurve_button_press(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self) { dt_iop_tonecurve_params_t *p = self->params; const dt_iop_tonecurve_params_t *const d = self->default_params; @@ -1855,10 +1855,12 @@ static gboolean dt_iop_tonecurve_button_press(GtkWidget *widget, int nodes = p->tonecurve_nodes[ch]; dt_iop_tonecurve_node_t *tonecurve = p->tonecurve[ch]; - if(event->button == 1) + guint button = gtk_gesture_single_get_current_button(gesture); + if(button == 1) { - if(event->type == GDK_BUTTON_PRESS - && dt_modifier_is(event->state, GDK_CONTROL_MASK) + dt_gui_claim(gesture); + if(n_press == 1 + && dt_modifier_eq(event->state, GDK_CONTROL_MASK) && nodes < DT_IOP_TONECURVE_MAXNODES && g->selected == -1) { @@ -1866,10 +1868,10 @@ static gboolean dt_iop_tonecurve_button_press(GtkWidget *widget, // the pointer and y of the curve at that x const int inset = DT_GUI_CURVE_EDITOR_INSET; GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); + gtk_widget_get_allocation(GTK_WIDGET(g->area), &allocation); int width = allocation.width - 2 * inset; - g->mouse_x = event->x - inset; - g->mouse_y = event->y - inset; + g->mouse_x = x - inset; + g->mouse_y = y - inset; const float mx = CLAMP(g->mouse_x, 0, width) / (float)width; const float linx = to_lin(mx, g->loglogscale, ch, g->semilog, 0); @@ -1896,12 +1898,12 @@ static gboolean dt_iop_tonecurve_button_press(GtkWidget *widget, (selected < nodes && tonecurve[selected].x - linx <= 0.025))) { // evaluate the curve at the current x position - const float y = dt_draw_curve_calc_value(g->minmax_curve[ch], linx); + const float calc_y = dt_draw_curve_calc_value(g->minmax_curve[ch], linx); - if(y >= 0.0 && y <= 1.0) // never add something outside the viewport, you couldn't change it afterwards + if(calc_y >= 0.0 && calc_y <= 1.0) // never add something outside the viewport, you couldn't change it afterwards { // create a new node - selected = _add_node(tonecurve, &p->tonecurve_nodes[ch], linx, y); + selected = _add_node(tonecurve, &p->tonecurve_nodes[ch], linx, calc_y); // maybe set the new one as being selected float min = .04f; @@ -1909,17 +1911,16 @@ static gboolean dt_iop_tonecurve_button_press(GtkWidget *widget, for(int k = 0; k < nodes; k++) { float other_y = to_log(tonecurve[k].y, g->loglogscale, ch, g->semilog, 1); - float dist = (y - other_y) * (y - other_y); + float dist = (calc_y - other_y) * (calc_y - other_y); if(dist < min) g->selected = selected; } - dt_dev_add_history_item_target(darktable.develop, self, TRUE, widget + ch); + dt_dev_add_history_item_target(darktable.develop, self, TRUE, g->area + ch); gtk_widget_queue_draw(GTK_WIDGET(g->area)); } } - return TRUE; } - else if(event->type == GDK_2BUTTON_PRESS) + else if(n_press == 2) { // reset current curve // if autoscale_ab is on: allow only reset of L curve @@ -1934,7 +1935,7 @@ static gboolean dt_iop_tonecurve_button_press(GtkWidget *widget, } g->selected = -2; // avoid motion notify re-inserting immediately. dt_bauhaus_combobox_set(g->interpolator, p->tonecurve_type[ch_L]); - dt_dev_add_history_item_target(darktable.develop, self, TRUE, widget + ch); + dt_dev_add_history_item_target(darktable.develop, self, TRUE, g->area + ch); gtk_widget_queue_draw(GTK_WIDGET(g->area)); } else @@ -1944,22 +1945,22 @@ static gboolean dt_iop_tonecurve_button_press(GtkWidget *widget, p->tonecurve_autoscale_ab = DT_S_SCALE_MANUAL; g->selected = -2; // avoid motion notify re-inserting immediately. dt_bauhaus_combobox_set(g->autoscale_ab, 1); - dt_dev_add_history_item_target(darktable.develop, self, TRUE, widget + ch); + dt_dev_add_history_item_target(darktable.develop, self, TRUE, g->area + ch); gtk_widget_queue_draw(GTK_WIDGET(g->area)); } } - return TRUE; } } - else if(event->button == 3 && g->selected >= 0) + else if(button == 3 && g->selected >= 0) { + dt_gui_claim(gesture); if(g->selected == 0 || g->selected == nodes - 1) { float reset_value = g->selected == 0 ? 0 : 1; tonecurve[g->selected].y = tonecurve[g->selected].x = reset_value; gtk_widget_queue_draw(GTK_WIDGET(g->area)); - dt_dev_add_history_item_target(darktable.develop, self, TRUE, widget + ch); - return TRUE; + dt_dev_add_history_item_target(darktable.develop, self, TRUE, g->area + ch); + return; } for(int k = g->selected; k < nodes - 1; k++) @@ -1971,10 +1972,8 @@ static gboolean dt_iop_tonecurve_button_press(GtkWidget *widget, g->selected = -2; // avoid re-insertion of that point immediately after this p->tonecurve_nodes[ch]--; gtk_widget_queue_draw(GTK_WIDGET(g->area)); - dt_dev_add_history_item_target(darktable.develop, self, TRUE, widget + ch); - return TRUE; + dt_dev_add_history_item_target(darktable.develop, self, TRUE, g->area + ch); } - return FALSE; } // clang-format off diff --git a/src/iop/toneequal.c b/src/iop/toneequal.c index 4f925c07a9af..06287b6934bd 100644 --- a/src/iop/toneequal.c +++ b/src/iop/toneequal.c @@ -3024,13 +3024,13 @@ static gboolean dt_iop_toneequalizer_bar_draw(GtkWidget *widget, return TRUE; } - -static gboolean area_enter_leave_notify(GtkWidget *widget, - GdkEventCrossing *event, - dt_iop_module_t *self) +static void _toneequal_enter(GtkEventControllerMotion *controller, + double x, + double y, + dt_iop_module_t *self) { - if(darktable.gui->reset) return TRUE; - if(!self->enabled) return FALSE; + if(darktable.gui->reset) return; + if(!self->enabled) return; dt_iop_toneequalizer_gui_data_t *g = self->gui_data; @@ -3044,8 +3044,8 @@ static gboolean area_enter_leave_notify(GtkWidget *widget, dt_dev_add_history_item(darktable.develop, self, FALSE); } dt_iop_gui_enter_critical_section(self); - g->area_x = (event->x - g->inset); - g->area_y = (event->y - g->inset); + g->area_x = (x - g->inset); + g->area_y = (y - g->inset); g->area_dragging = FALSE; g->area_active_node = -1; g->area_cursor_valid = (g->area_x > 0.0f @@ -3055,23 +3055,21 @@ static gboolean area_enter_leave_notify(GtkWidget *widget, dt_iop_gui_leave_critical_section(self); gtk_widget_queue_draw(GTK_WIDGET(g->area)); - return FALSE; } - -static gboolean area_button_press(GtkWidget *widget, - GdkEventButton *event, - dt_iop_module_t *self) +static void _toneequal_button_press(GtkGesture *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self) { - - if(darktable.gui->reset) return TRUE; + if(darktable.gui->reset) return; dt_iop_toneequalizer_gui_data_t *g = self->gui_data; dt_iop_request_focus(self); - if(event->button == 1 - && event->type == GDK_2BUTTON_PRESS) + if(n_press == 2) { dt_iop_toneequalizer_params_t *p = self->params; const dt_iop_toneequalizer_params_t *const d = self->default_params; @@ -3093,9 +3091,8 @@ static gboolean area_button_press(GtkWidget *widget, // Redraw graph gtk_widget_queue_draw(GTK_WIDGET(g->area)); dt_dev_add_history_item(darktable.develop, self, TRUE); - return TRUE; } - else if(event->button == 1) + else { if(self->enabled) { @@ -3106,22 +3103,19 @@ static gboolean area_button_press(GtkWidget *widget, { dt_dev_add_history_item(darktable.develop, self, TRUE); } - return TRUE; } // Unlock the colour picker so we can display our own custom cursor dt_iop_color_picker_reset(self, TRUE); - - return FALSE; } - -static gboolean area_motion_notify(GtkWidget *widget, - GdkEventMotion *event, - dt_iop_module_t *self) +static void _toneequal_motion(GtkEventControllerMotion *controller, + double x, + double y, + dt_iop_module_t *self) { - if(darktable.gui->reset) return TRUE; - if(!self->enabled) return FALSE; + if(darktable.gui->reset) return; + if(!self->enabled) return; dt_iop_toneequalizer_gui_data_t *g = self->gui_data; dt_iop_toneequalizer_params_t *p = self->params; @@ -3131,7 +3125,7 @@ static gboolean area_motion_notify(GtkWidget *widget, // vertical distance travelled since button_pressed event dt_iop_gui_enter_critical_section(self); // graph spans over 4 EV - const float offset = (-event->y + g->area_y) / g->graph_height * 4.0f; + const float offset = (-y + g->area_y) / g->graph_height * 4.0f; const float cursor_exposure = g->area_x / g->graph_width * 8.0f - 8.0f; // Get the desired correction on exposure channels @@ -3141,8 +3135,8 @@ static gboolean area_motion_notify(GtkWidget *widget, } dt_iop_gui_enter_critical_section(self); - g->area_x = (event->x - g->inset); - g->area_y = event->y; + g->area_x = (x - g->inset); + g->area_y = y; g->area_cursor_valid = (g->area_x > 0.0f && g->area_x < g->graph_width && g->area_y > 0.0f @@ -3166,13 +3160,14 @@ static gboolean area_motion_notify(GtkWidget *widget, dt_iop_gui_leave_critical_section(self); gtk_widget_queue_draw(GTK_WIDGET(g->area)); - return TRUE; } -static gboolean area_button_release(GtkWidget *widget, - GdkEventButton *event, - dt_iop_module_t *self) +static gboolean _toneequal_button_release(GtkGesture *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self) { if(darktable.gui->reset) return TRUE; if(!self->enabled) return FALSE; @@ -3182,25 +3177,20 @@ static gboolean area_button_release(GtkWidget *widget, // Give focus to module dt_iop_request_focus(self); - if(event->button == 1) - { - dt_iop_toneequalizer_params_t *p = self->params; - - if(g->area_dragging) - { - // Update GUI with new params - update_exposure_sliders(g, p); + dt_iop_toneequalizer_params_t *p = self->params; - dt_dev_add_history_item(darktable.develop, self, FALSE); + if(g->area_dragging) + { + // Update GUI with new params + update_exposure_sliders(g, p); - dt_iop_gui_enter_critical_section(self); - g->area_dragging= 0; - dt_iop_gui_leave_critical_section(self); + dt_dev_add_history_item(darktable.develop, self, FALSE); - return TRUE; - } + dt_iop_gui_enter_critical_section(self); + g->area_dragging= 0; + dt_iop_gui_leave_critical_section(self); } - return FALSE; + return TRUE; } static gboolean area_scroll(GtkWidget *widget, @@ -3371,22 +3361,11 @@ void gui_init(struct dt_iop_module_t *self) gtk_widget_set_name(GTK_WIDGET(wrapper), "toneeqgraph"); dt_action_define_iop(self, NULL, N_("graph"), GTK_WIDGET(wrapper), NULL); gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(wrapper), TRUE, TRUE, 0); - gtk_widget_add_events(GTK_WIDGET(g->area), - GDK_POINTER_MOTION_MASK | darktable.gui->scroll_mask - | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); + gtk_widget_add_events(GTK_WIDGET(g->area), darktable.gui->scroll_mask); gtk_widget_set_can_focus(GTK_WIDGET(g->area), TRUE); g_signal_connect(G_OBJECT(g->area), "draw", G_CALLBACK(area_draw), self); - g_signal_connect(G_OBJECT(g->area), "button-press-event", - G_CALLBACK(area_button_press), self); - g_signal_connect(G_OBJECT(g->area), "button-release-event", - G_CALLBACK(area_button_release), self); - g_signal_connect(G_OBJECT(g->area), "leave-notify-event", - G_CALLBACK(area_enter_leave_notify), self); - g_signal_connect(G_OBJECT(g->area), "enter-notify-event", - G_CALLBACK(area_enter_leave_notify), self); - g_signal_connect(G_OBJECT(g->area), "motion-notify-event", - G_CALLBACK(area_motion_notify), self); + dt_gui_connect_click(g->area, _toneequal_button_press, _toneequal_button_release, self); + dt_gui_connect_motion(g->area, _toneequal_motion, _toneequal_enter, NULL, self); g_signal_connect(G_OBJECT(g->area), "scroll-event", G_CALLBACK(area_scroll), self); gtk_widget_set_tooltip_text(GTK_WIDGET(g->area), _("double-click to reset the curve")); diff --git a/src/iop/zonesystem.c b/src/iop/zonesystem.c index 70e4b01c794b..4b01425a738b 100644 --- a/src/iop/zonesystem.c +++ b/src/iop/zonesystem.c @@ -404,14 +404,22 @@ static gboolean dt_iop_zonesystem_preview_draw(GtkWidget *widget, cairo_t *crf, dt_iop_module_t *self); static gboolean dt_iop_zonesystem_bar_draw(GtkWidget *widget, cairo_t *crf, dt_iop_module_t *self); -static gboolean dt_iop_zonesystem_bar_motion_notify(GtkWidget *widget, GdkEventMotion *event, - dt_iop_module_t *self); -static gboolean dt_iop_zonesystem_bar_leave_notify(GtkWidget *widget, GdkEventCrossing *event, - dt_iop_module_t *self); -static gboolean dt_iop_zonesystem_bar_button_press(GtkWidget *widget, GdkEventButton *event, - dt_iop_module_t *self); -static gboolean dt_iop_zonesystem_bar_button_release(GtkWidget *widget, GdkEventButton *event, - dt_iop_module_t *self); +static void _zonesystem_button_press(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self); +static void _zonesystem_button_release(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self); +static void _zonesystem_motion(GtkEventControllerMotion *controller, + double x, + double y, + dt_iop_module_t *self); +static void _zonesystem_leave(GtkEventControllerMotion *controller, + dt_iop_module_t *self); static gboolean dt_iop_zonesystem_bar_scrolled(GtkWidget *widget, GdkEventScroll *event, dt_iop_module_t *self); @@ -453,9 +461,6 @@ void gui_init(struct dt_iop_module_t *self) g->preview = dtgtk_drawing_area_new_with_height(0); g_signal_connect(G_OBJECT(g->preview), "size-allocate", G_CALLBACK(size_allocate_callback), self); g_signal_connect(G_OBJECT(g->preview), "draw", G_CALLBACK(dt_iop_zonesystem_preview_draw), self); - gtk_widget_add_events(GTK_WIDGET(g->preview), GDK_POINTER_MOTION_MASK - | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_LEAVE_NOTIFY_MASK); /* create the zonesystem bar widget */ g->zones = gtk_drawing_area_new(); @@ -463,18 +468,10 @@ void gui_init(struct dt_iop_module_t *self) "left-click on a border to create a marker\n" "right-click on a marker to delete it")); g_signal_connect(G_OBJECT(g->zones), "draw", G_CALLBACK(dt_iop_zonesystem_bar_draw), self); - g_signal_connect(G_OBJECT(g->zones), "motion-notify-event", G_CALLBACK(dt_iop_zonesystem_bar_motion_notify), - self); - g_signal_connect(G_OBJECT(g->zones), "leave-notify-event", G_CALLBACK(dt_iop_zonesystem_bar_leave_notify), - self); - g_signal_connect(G_OBJECT(g->zones), "button-press-event", G_CALLBACK(dt_iop_zonesystem_bar_button_press), - self); - g_signal_connect(G_OBJECT(g->zones), "button-release-event", - G_CALLBACK(dt_iop_zonesystem_bar_button_release), self); + dt_gui_connect_click_all(g->zones, _zonesystem_button_press, _zonesystem_button_release, self); + dt_gui_connect_motion(g->zones, _zonesystem_motion, NULL, _zonesystem_leave, self); g_signal_connect(G_OBJECT(g->zones), "scroll-event", G_CALLBACK(dt_iop_zonesystem_bar_scrolled), self); - gtk_widget_add_events(GTK_WIDGET(g->zones), GDK_POINTER_MOTION_MASK - | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_LEAVE_NOTIFY_MASK | darktable.gui->scroll_mask); + gtk_widget_add_events(GTK_WIDGET(g->zones), darktable.gui->scroll_mask); gtk_widget_set_size_request(g->zones, -1, DT_PIXEL_APPLY_DPI(40)); gtk_box_pack_start(GTK_BOX(self->widget), g->preview, TRUE, TRUE, 0); @@ -599,14 +596,17 @@ static gboolean dt_iop_zonesystem_bar_draw(GtkWidget *widget, cairo_t *crf, dt_i return TRUE; } -static gboolean dt_iop_zonesystem_bar_button_press(GtkWidget *widget, GdkEventButton *event, - dt_iop_module_t *self) +static void _zonesystem_button_press(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self) { dt_iop_zonesystem_params_t *p = self->params; dt_iop_zonesystem_gui_data_t *g = self->gui_data; const int inset = DT_ZONESYSTEM_INSET; GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); + gtk_widget_get_allocation(g->zones, &allocation); int width = allocation.width - 2 * inset; /*, height = allocation.height - 2*inset;*/ /* calculate zonemap */ @@ -618,8 +618,8 @@ static gboolean dt_iop_zonesystem_bar_button_press(GtkWidget *widget, GdkEventBu float zw = zonemap[k + 1] - zonemap[k]; if((g->mouse_x / width) > zonemap[k] + (zw / 2)) k++; - - if(event->button == 1) + guint button = gtk_gesture_single_get_current_button(gesture); + if(button == 1) { if(p->zone[k] == -1) { @@ -629,25 +629,26 @@ static gboolean dt_iop_zonesystem_bar_button_press(GtkWidget *widget, GdkEventBu g->is_dragging = TRUE; g->current_zone = k; } - else if(event->button == 3) + else if(button == 3) { /* clear the controlpoint */ p->zone[k] = -1; dt_dev_add_history_item(darktable.develop, self, TRUE); } - - return TRUE; } -static gboolean dt_iop_zonesystem_bar_button_release(GtkWidget *widget, GdkEventButton *event, - dt_iop_module_t *self) +static void _zonesystem_button_release(GtkGestureSingle *gesture, + int n_press, + double x, + double y, + dt_iop_module_t *self) { dt_iop_zonesystem_gui_data_t *g = self->gui_data; - if(event->button == 1) + guint button = gtk_gesture_single_get_current_button(gesture); + if(button == 1) { g->is_dragging = FALSE; } - return TRUE; } static gboolean dt_iop_zonesystem_bar_scrolled(GtkWidget *widget, GdkEventScroll *event, dt_iop_module_t *self) @@ -669,23 +670,24 @@ static gboolean dt_iop_zonesystem_bar_scrolled(GtkWidget *widget, GdkEventScroll return TRUE; } -static gboolean dt_iop_zonesystem_bar_leave_notify(GtkWidget *widget, GdkEventCrossing *event, - dt_iop_module_t *self) +static void _zonesystem_leave(GtkEventControllerMotion *controller, + dt_iop_module_t *self) { dt_iop_zonesystem_gui_data_t *g = self->gui_data; g->hilite_zone = FALSE; gtk_widget_queue_draw(g->preview); - return TRUE; } -static gboolean dt_iop_zonesystem_bar_motion_notify(GtkWidget *widget, GdkEventMotion *event, - dt_iop_module_t *self) +static void _zonesystem_motion(GtkEventControllerMotion *controller, + double x, + double y, + dt_iop_module_t *self) { dt_iop_zonesystem_params_t *p = self->params; dt_iop_zonesystem_gui_data_t *g = self->gui_data; const int inset = DT_ZONESYSTEM_INSET; GtkAllocation allocation; - gtk_widget_get_allocation(widget, &allocation); + gtk_widget_get_allocation(g->zones, &allocation); int width = allocation.width - 2 * inset, height = allocation.height - 2 * inset; /* calculate zonemap */ @@ -693,8 +695,8 @@ static gboolean dt_iop_zonesystem_bar_motion_notify(GtkWidget *widget, GdkEventM _iop_zonesystem_calculate_zonemap(p, zonemap); /* record mouse position within control */ - g->mouse_x = CLAMP(event->x - inset, 0, width); - g->mouse_y = CLAMP(height - 1 - event->y + inset, 0, height); + g->mouse_x = CLAMP(x - inset, 0, width); + g->mouse_y = CLAMP(height - 1 - y + inset, 0, height); if(g->is_dragging) { @@ -731,7 +733,6 @@ static gboolean dt_iop_zonesystem_bar_motion_notify(GtkWidget *widget, GdkEventM gtk_widget_queue_draw(self->widget); gtk_widget_queue_draw(g->preview); - return TRUE; }