]> git.mdlowis.com Git - proto/labwc.git/commitdiff
input: expose general cursor motion and button functions
authorJens Peters <jp7677@gmail.com>
Sat, 20 Apr 2024 09:33:04 +0000 (11:33 +0200)
committerConsolatis <35009135+Consolatis@users.noreply.github.com>
Mon, 27 May 2024 20:40:50 +0000 (22:40 +0200)
Separate the general logic from the pointer notifications
to allow reuse of those function for other (e.g. tablet)
input sources.

include/input/cursor.h
src/input/cursor.c

index 94c9df4751e616934b77c799051820b51ec22816..24f7326d53afc6c9a97a03c2dfeb65491c407f1b 100644 (file)
@@ -118,6 +118,32 @@ void cursor_update_focus(struct server *server);
  */
 void cursor_update_image(struct seat *seat);
 
+/**
+ * Processes cursor motion. The return value indicates if a client
+ * should be notified. Parameters sx, sy holds the surface coordinates
+ * in that case.
+ */
+bool cursor_process_motion(struct server *server, uint32_t time, double *sx, double *sy);
+
+/**
+ * Processes cursor button press. The return value indicates if a client
+ * should be notified.
+ */
+bool cursor_process_button_press(struct seat *seat, uint32_t button, uint32_t time_msec);
+
+/**
+ * Processes cursor button release. The return value indicates if the client
+ * should be notified. Should be followed by cursor_finish_button_release()
+ * after notifying a client.
+ */
+bool cursor_process_button_release(struct seat *seat, uint32_t button, uint32_t time_msec);
+
+/**
+ * Finishes cursor button release. The return value indicates if an interactive
+ * move/resize had been finished. Should be called after notifying a client.
+ */
+bool cursor_finish_button_release(struct seat *seat);
+
 void cursor_init(struct seat *seat);
 void cursor_reload(struct seat *seat);
 void cursor_emulate_move_absolute(struct seat *seat,
index 596ea386ee0f65194204d0119439d550a1760222..dfd13038a482c8d983f525ea157ef114a0003feb 100644 (file)
@@ -354,8 +354,9 @@ update_pressed_surface(struct seat *seat, struct cursor_context *ctx)
        return false;
 }
 
-static void
-process_cursor_motion_out_of_surface(struct server *server, uint32_t time)
+static bool
+process_cursor_motion_out_of_surface(struct server *server,
+               double *sx, double *sy)
 {
        struct view *view = server->seat.pressed.view;
        struct wlr_scene_node *node = server->seat.pressed.node;
@@ -374,28 +375,29 @@ process_cursor_motion_out_of_surface(struct server *server, uint32_t time)
 #endif
        } else {
                wlr_log(WLR_ERROR, "Can't detect surface for out-of-surface movement");
-               return;
+               return false;
        }
 
-       double sx = server->seat.cursor->x - lx;
-       double sy = server->seat.cursor->y - ly;
+       *sx = server->seat.cursor->x - lx;
+       *sy = server->seat.cursor->y - ly;
        /* Take into account invisible xdg-shell CSD borders */
        if (view && view->type == LAB_XDG_SHELL_VIEW) {
                struct wlr_box geo;
                wlr_xdg_surface_get_geometry(xdg_surface_from_view(view), &geo);
-               sx += geo.x;
-               sy += geo.y;
+               *sx += geo.x;
+               *sy += geo.y;
        }
 
-       wlr_seat_pointer_notify_motion(server->seat.seat, time, sx, sy);
+       return true;
 }
 
 /*
- * Common logic shared by cursor_update_focus() and process_cursor_motion()
+ * Common logic shared by cursor_update_focus(), process_cursor_motion()
+ * and cursor_axis()
  */
-static void
+static bool
 cursor_update_common(struct server *server, struct cursor_context *ctx,
-               uint32_t time_msec, bool cursor_has_moved)
+               uint32_t time_msec, bool cursor_has_moved, double *sx, double *sy)
 {
        struct seat *seat = &server->seat;
        struct wlr_seat *wlr_seat = seat->seat;
@@ -407,7 +409,7 @@ cursor_update_common(struct server *server, struct cursor_context *ctx,
                 * Prevent updating focus/cursor image during
                 * interactive move/resize
                 */
-               return;
+               return false;
        }
 
        /* TODO: verify drag_icon logic */
@@ -422,9 +424,9 @@ cursor_update_common(struct server *server, struct cursor_context *ctx,
                         * we can keep scrolling or selecting text even
                         * if the cursor moves outside of the surface.
                         */
-                       process_cursor_motion_out_of_surface(server, time_msec);
+                       return process_cursor_motion_out_of_surface(server, sx, sy);
                }
-               return;
+               return false;
        }
 
        if (ctx->surface && !input_inhibit_blocks_surface(seat,
@@ -457,8 +459,9 @@ cursor_update_common(struct server *server, struct cursor_context *ctx,
                        seat->server_cursor = LAB_CURSOR_CLIENT;
                }
                if (cursor_has_moved) {
-                       wlr_seat_pointer_notify_motion(wlr_seat, time_msec,
-                               ctx->sx, ctx->sy);
+                       *sx = ctx->sx;
+                       *sy = ctx->sy;
+                       return true;
                }
        } else {
                /*
@@ -477,6 +480,7 @@ cursor_update_common(struct server *server, struct cursor_context *ctx,
                        cursor_set(seat, cursor);
                }
        }
+       return false;
 }
 
 uint32_t
@@ -495,16 +499,16 @@ cursor_get_resize_edges(struct wlr_cursor *cursor, struct cursor_context *ctx)
        return resize_edges;
 }
 
-static void
-process_cursor_motion(struct server *server, uint32_t time)
+bool
+cursor_process_motion(struct server *server, uint32_t time, double *sx, double *sy)
 {
        /* If the mode is non-passthrough, delegate to those functions. */
        if (server->input_mode == LAB_INPUT_STATE_MOVE) {
                process_cursor_move(server, time);
-               return;
+               return false;
        } else if (server->input_mode == LAB_INPUT_STATE_RESIZE) {
                process_cursor_resize(server, time);
-               return;
+               return false;
        }
 
        /* Otherwise, find view under the pointer and send the event along */
@@ -514,7 +518,7 @@ process_cursor_motion(struct server *server, uint32_t time)
        if (ctx.type == LAB_SSD_MENU) {
                menu_process_cursor_motion(ctx.node);
                cursor_set(&server->seat, LAB_CURSOR_DEFAULT);
-               return;
+               return false;
        }
 
        if (seat->drag.active) {
@@ -543,7 +547,8 @@ process_cursor_motion(struct server *server, uint32_t time)
                }
        }
 
-       cursor_update_common(server, &ctx, time, /*cursor_has_moved*/ true);
+       return cursor_update_common(server, &ctx, time,
+               /* cursor_has_moved */ true, sx, sy);
 }
 
 static uint32_t
@@ -569,8 +574,9 @@ _cursor_update_focus(struct server *server)
                        ctx.surface, rc.raise_on_focus);
        }
 
+       double sx, sy;
        cursor_update_common(server, &ctx, msec(&now),
-               /*cursor_has_moved*/ false);
+               /*cursor_has_moved*/ false, &sx, &sy);
 }
 
 void
@@ -738,7 +744,11 @@ preprocess_cursor_motion(struct seat *seat, struct wlr_pointer *pointer,
         * without any input.
         */
        wlr_cursor_move(seat->cursor, &pointer->base, dx, dy);
-       process_cursor_motion(seat->server, time_msec);
+       double sx, sy;
+       bool notify = cursor_process_motion(seat->server, time_msec, &sx, &sy);
+       if (notify) {
+               wlr_seat_pointer_notify_motion(seat->seat, time_msec, sx, sy);
+       }
 }
 
 static void
@@ -947,9 +957,8 @@ handle_press_mousebinding(struct server *server, struct cursor_context *ctx,
 
 static uint32_t press_msec;
 
-static void
-cursor_button_press(struct seat *seat, uint32_t button,
-               enum wlr_button_state button_state, uint32_t time_msec)
+bool
+cursor_process_button_press(struct seat *seat, uint32_t button, uint32_t time_msec)
 {
        struct server *server = seat->server;
        struct cursor_context ctx = get_cursor_context(server);
@@ -972,7 +981,7 @@ cursor_button_press(struct seat *seat, uint32_t button,
                 * so subsequent release always closes menu or selects menu item.
                 */
                press_msec = 0;
-               return;
+               return false;
        }
 
        /*
@@ -1012,7 +1021,7 @@ cursor_button_press(struct seat *seat, uint32_t button,
                 * Note: This does not work for XWayland clients
                 */
                wlr_seat_pointer_end_grab(seat->seat);
-               return;
+               return false;
        }
 
        /* Bindings to the Frame context swallow mouse events if activated */
@@ -1021,14 +1030,15 @@ cursor_button_press(struct seat *seat, uint32_t button,
 
        if (ctx.surface && !consumed_by_frame_context) {
                /* Notify client with pointer focus of button press */
-               wlr_seat_pointer_notify_button(seat->seat, time_msec,
-                       button, button_state);
+               return true;
        }
+
+       return false;
 }
 
-static void
-cursor_button_release(struct seat *seat, uint32_t button,
-               enum wlr_button_state button_state, uint32_t time_msec)
+bool
+cursor_process_button_release(struct seat *seat, uint32_t button,
+               uint32_t time_msec)
 {
        struct server *server = seat->server;
        struct cursor_context ctx = get_cursor_context(server);
@@ -1043,24 +1053,20 @@ cursor_button_release(struct seat *seat, uint32_t button,
                                menu_call_selected_actions(server);
                        } else {
                                menu_close_root(server);
+                               double sx, sy;
                                cursor_update_common(server, &ctx, time_msec,
-                                       /*cursor_has_moved*/ false);
+                                       /*cursor_has_moved*/ false, &sx, &sy);
                        }
                }
-               return;
+               return false;
        }
 
        if (server->input_mode != LAB_INPUT_STATE_PASSTHROUGH) {
                if (pressed_surface) {
                        /* Ensure CSD clients see the release event */
-                       wlr_seat_pointer_notify_button(seat->seat, time_msec,
-                               button, button_state);
+                       return true;
                }
-
-               /* Exit interactive move/resize mode */
-               interactive_finish(server->grabbed_view);
-
-               return;
+               return false;
        }
 
        if (pressed_surface && ctx.surface != pressed_surface) {
@@ -1068,9 +1074,7 @@ cursor_button_release(struct seat *seat, uint32_t button,
                 * Button released but originally pressed over a different surface.
                 * Just send the release event to the still focused surface.
                 */
-               wlr_seat_pointer_notify_button(seat->seat, time_msec,
-                       button, button_state);
-               return;
+               return true;
        }
 
        /* Bindings to the Frame context swallow mouse events if activated */
@@ -1079,9 +1083,25 @@ cursor_button_release(struct seat *seat, uint32_t button,
 
        if (!consumed_by_frame_context) {
                /* Notify client with pointer focus of button release */
-               wlr_seat_pointer_notify_button(seat->seat, time_msec,
-                       button, button_state);
+               return true;
+       }
+
+       return false;
+}
+
+bool
+cursor_finish_button_release(struct seat *seat)
+{
+       struct server *server = seat->server;
+
+       if (server->input_mode == LAB_INPUT_STATE_MOVE
+                       || server->input_mode == LAB_INPUT_STATE_RESIZE) {
+               /* Exit interactive move/resize mode */
+               interactive_finish(server->grabbed_view);
+               return true;
        }
+
+       return false;
 }
 
 static void
@@ -1095,12 +1115,24 @@ cursor_button(struct wl_listener *listener, void *data)
        struct wlr_pointer_button_event *event = data;
        idle_manager_notify_activity(seat->seat);
 
+       bool notify;
        switch (event->state) {
        case WLR_BUTTON_PRESSED:
-               cursor_button_press(seat, event->button, event->state, event->time_msec);
+               notify = cursor_process_button_press(seat, event->button,
+                       event->time_msec);
+               if (notify) {
+                       wlr_seat_pointer_notify_button(seat->seat, event->time_msec,
+                               event->button, event->state);
+               }
                break;
        case WLR_BUTTON_RELEASED:
-               cursor_button_release(seat, event->button, event->state, event->time_msec);
+               notify = cursor_process_button_release(seat, event->button,
+                       event->time_msec);
+               if (notify) {
+                       wlr_seat_pointer_notify_button(seat->seat, event->time_msec,
+                               event->button, event->state);
+               }
+               cursor_finish_button_release(seat);
                break;
        }
 }
@@ -1129,7 +1161,11 @@ cursor_emulate_move_absolute(struct seat *seat, struct wlr_input_device *device,
                dx, dy, dx, dy);
 
        wlr_cursor_move(seat->cursor, device, dx, dy);
-       process_cursor_motion(seat->server, time_msec);
+       double sx, sy;
+       bool notify = cursor_process_motion(seat->server, time_msec, &sx, &sy);
+       if (notify) {
+               wlr_seat_pointer_notify_motion(seat->seat, time_msec, sx, sy);
+       }
        wlr_seat_pointer_notify_frame(seat->seat);
 }
 
@@ -1139,12 +1175,20 @@ cursor_emulate_button(struct seat *seat, uint32_t button,
 {
        idle_manager_notify_activity(seat->seat);
 
+       bool notify;
        switch (state) {
        case WLR_BUTTON_PRESSED:
-               cursor_button_press(seat, button, state, time_msec);
+               notify = cursor_process_button_press(seat, button, time_msec);
+               if (notify) {
+                       wlr_seat_pointer_notify_button(seat->seat, time_msec, button, state);
+               }
                break;
        case WLR_BUTTON_RELEASED:
-               cursor_button_release(seat, button, state, time_msec);
+               notify = cursor_process_button_release(seat, button, time_msec);
+               if (notify) {
+                       wlr_seat_pointer_notify_button(seat->seat, time_msec, button, state);
+               }
+               cursor_finish_button_release(seat);
                break;
        }
 }
@@ -1245,7 +1289,9 @@ cursor_axis(struct wl_listener *listener, void *data)
 
        if (ctx.surface && !handled) {
                /* Make sure we are sending the events to the surface under the cursor */
-               cursor_update_common(server, &ctx, event->time_msec, false);
+               double sx, sy;
+               cursor_update_common(server, &ctx, event->time_msec,
+                       /*cursor_has_moved*/ false, &sx, &sy);
 
                /* Notify the client with pointer focus of the axis event. */
                wlr_seat_pointer_notify_axis(seat->seat, event->time_msec,