]> git.mdlowis.com Git - proto/labwc.git/commitdiff
Add cursor.c
authorJohan Malm <jgm323@gmail.com>
Fri, 29 May 2020 20:36:12 +0000 (21:36 +0100)
committerJohan Malm <jgm323@gmail.com>
Fri, 29 May 2020 20:36:12 +0000 (21:36 +0100)
src/cursor.c [new file with mode: 0644]
src/interactive.c
src/meson.build
src/server.c

diff --git a/src/cursor.c b/src/cursor.c
new file mode 100644 (file)
index 0000000..b0b29d4
--- /dev/null
@@ -0,0 +1,227 @@
+#include "labwc.h"
+
+static void process_cursor_move(struct server *server, uint32_t time)
+{
+       /* Move the grabbed view to the new position. */
+       double dx = server->cursor->x - server->grab_x;
+       double dy = server->cursor->y - server->grab_y;
+       server->grabbed_view->x = server->grab_box.x + dx;
+       server->grabbed_view->y = server->grab_box.y + dy;
+
+       if (server->grabbed_view->type != LAB_XWAYLAND_VIEW)
+               return;
+
+       struct view *view = server->grabbed_view;
+       wlr_xwayland_surface_configure(view->xwayland_surface, view->x, view->y,
+                                      view->xwayland_surface->width,
+                                      view->xwayland_surface->height);
+}
+
+#define MIN_VIEW_WIDTH (100)
+#define MIN_VIEW_HEIGHT (60)
+
+static void process_cursor_resize(struct server *server, uint32_t time)
+{
+       /*
+        * TODO: Wait for the client to prepare a buffer at the new size, then
+        * commit any movement that was prepared.
+        */
+       double dx = server->cursor->x - server->grab_x;
+       double dy = server->cursor->y - server->grab_y;
+
+       struct view *view = server->grabbed_view;
+       struct wlr_box new_view_geo = view_geometry(view);
+
+       if (server->resize_edges & WLR_EDGE_TOP) {
+               new_view_geo.y = server->grab_box.y + dy;
+               new_view_geo.height = server->grab_box.height - dy;
+       } else if (server->resize_edges & WLR_EDGE_BOTTOM) {
+               new_view_geo.height = server->grab_box.height + dy;
+       }
+       if (server->resize_edges & WLR_EDGE_LEFT) {
+               new_view_geo.x = server->grab_box.x + dx;
+               new_view_geo.width = server->grab_box.width - dx;
+       } else if (server->resize_edges & WLR_EDGE_RIGHT) {
+               new_view_geo.width = server->grab_box.width + dx;
+       }
+       if ((new_view_geo.height < MIN_VIEW_HEIGHT) ||
+           (new_view_geo.width < MIN_VIEW_WIDTH))
+               return;
+
+       /* Move */
+       view->x = new_view_geo.x;
+       view->y = new_view_geo.y;
+
+       /* Resize */
+       view_resize(view, new_view_geo);
+}
+
+static void process_cursor_motion(struct server *server, uint32_t time)
+{
+       /* If the mode is non-passthrough, delegate to those functions. */
+       if (server->cursor_mode == TINYWL_CURSOR_MOVE) {
+               process_cursor_move(server, time);
+               return;
+       } else if (server->cursor_mode == TINYWL_CURSOR_RESIZE) {
+               process_cursor_resize(server, time);
+               return;
+       }
+
+       /* Otherwise, find the view under the pointer and send the event along.
+        */
+       double sx, sy;
+       struct wlr_seat *seat = server->seat;
+       struct wlr_surface *surface = NULL;
+       int view_area;
+       struct view *view = view_at(server, server->cursor->x,
+                                   server->cursor->y, &surface, &sx, &sy,
+                                   &view_area);
+       if (!view) {
+               /* If there's no view under the cursor, set the cursor image to
+                * a default. This is what makes the cursor image appear when
+                * you move it around the screen, not over any views. */
+               wlr_xcursor_manager_set_cursor_image(
+                       server->cursor_mgr, "left_ptr", server->cursor);
+       }
+       switch (view_area) {
+       case LAB_DECO_PART_TOP:
+               wlr_xcursor_manager_set_cursor_image(
+                       server->cursor_mgr, "left_ptr", server->cursor);
+               break;
+       case LAB_DECO_PART_LEFT:
+               wlr_xcursor_manager_set_cursor_image(
+                       server->cursor_mgr, "left_side", server->cursor);
+               break;
+       }
+       if (surface) {
+               bool focus_changed = seat->pointer_state.focused_surface !=
+                                    surface;
+               /*
+                * "Enter" the surface if necessary. This lets the client know
+                * that the cursor has entered one of its surfaces.
+                *
+                * Note that this gives the surface "pointer focus", which is
+                * distinct from keyboard focus. You get pointer focus by moving
+                * the pointer over a window.
+                */
+               wlr_seat_pointer_notify_enter(seat, surface, sx, sy);
+               if (!focus_changed) {
+                       /* The enter event contains coordinates, so we only need
+                        * to notify on motion if the focus did not change. */
+                       wlr_seat_pointer_notify_motion(seat, time, sx, sy);
+               }
+       } else {
+               /* Clear pointer focus so future button events and such are not
+                * sent to the last client to have the cursor over it. */
+               wlr_seat_pointer_clear_focus(seat);
+       }
+}
+
+void server_cursor_motion(struct wl_listener *listener, void *data)
+{
+       /*
+        * This event is forwarded by the cursor when a pointer emits a
+        * _relative_ pointer motion event (i.e. a delta)
+        */
+       struct server *server =
+               wl_container_of(listener, server, cursor_motion);
+       struct wlr_event_pointer_motion *event = data;
+
+       /*
+        * The cursor doesn't move unless we tell it to. The cursor
+        * automatically handles constraining the motion to the output layout,
+        * as well as any special configuration applied for the specific input
+        * device which generated the event. You can pass NULL for the device
+        * if you want to move the cursor around without any input.
+        */
+       wlr_cursor_move(server->cursor, event->device, event->delta_x,
+                       event->delta_y);
+       process_cursor_motion(server, event->time_msec);
+}
+
+void server_cursor_motion_absolute(struct wl_listener *listener, void *data)
+{
+       /*
+        * This event is forwarded by the cursor when a pointer emits an
+        * _absolute_ motion event, from 0..1 on each axis. This happens, for
+        * example, when wlroots is running under a Wayland window rather than
+        * KMS+DRM, and you move the mouse over the window. You could enter the
+        * window from any edge, so we have to warp the mouse there. There is
+        * also some hardware which emits these events.
+        */
+       struct server *server =
+               wl_container_of(listener, server, cursor_motion_absolute);
+       struct wlr_event_pointer_motion_absolute *event = data;
+       wlr_cursor_warp_absolute(server->cursor, event->device, event->x,
+                                event->y);
+       process_cursor_motion(server, event->time_msec);
+}
+
+void server_cursor_button(struct wl_listener *listener, void *data)
+{
+       /*
+        * This event is forwarded by the cursor when a pointer emits a button
+        * event.
+        */
+       struct server *server =
+               wl_container_of(listener, server, cursor_button);
+       struct wlr_event_pointer_button *event = data;
+
+       /*
+        * Notify the client with pointer focus that a button press has
+        * occurred.
+        */
+       wlr_seat_pointer_notify_button(server->seat, event->time_msec,
+                                      event->button, event->state);
+       double sx, sy;
+       struct wlr_surface *surface;
+       int view_area;
+       struct view *view = view_at(server, server->cursor->x,
+                                   server->cursor->y, &surface, &sx, &sy,
+                                   &view_area);
+       if (event->state == WLR_BUTTON_RELEASED) {
+               /* Exit interactive move/resize mode. */
+               server->cursor_mode = TINYWL_CURSOR_PASSTHROUGH;
+       } else {
+               /* Focus that client if the button was _pressed_ */
+               view_focus(view);
+               switch (view_area) {
+               case LAB_DECO_PART_TOP:
+                       interactive_begin(view, TINYWL_CURSOR_MOVE, 0);
+                       break;
+               case LAB_DECO_PART_LEFT:
+                       interactive_begin(view, TINYWL_CURSOR_RESIZE,
+                                         WLR_EDGE_LEFT);
+                       break;
+               }
+       }
+}
+
+void server_cursor_axis(struct wl_listener *listener, void *data)
+{
+       /*
+        * This event is forwarded by the cursor when a pointer emits an axis
+        * event, for example when you move the scroll wheel.
+        */
+       struct server *server = wl_container_of(listener, server, cursor_axis);
+       struct wlr_event_pointer_axis *event = data;
+
+       /* Notify the client with pointer focus of the axis event. */
+       wlr_seat_pointer_notify_axis(server->seat, event->time_msec,
+                                    event->orientation, event->delta,
+                                    event->delta_discrete, event->source);
+}
+
+void server_cursor_frame(struct wl_listener *listener, void *data)
+{
+       /*
+        * This event is forwarded by the cursor when a pointer emits an frame
+        * event. Frame events are sent after regular pointer events to group
+        * multiple events together. For instance, two axis events may happen
+        * at the same time, in which case a frame event won't be sent in
+        * between.
+        */
+       struct server *server = wl_container_of(listener, server, cursor_frame);
+       /* Notify the client with pointer focus of the frame event. */
+       wlr_seat_pointer_notify_frame(server->seat);
+}
index 7022ead9f95f2d45941faf52b066617c042edf60..c702e4c92c5621e54fb8ca2a282a5e98d22815b9 100644 (file)
@@ -17,4 +17,3 @@ void interactive_begin(struct view *view, enum cursor_mode mode, uint32_t edges)
        server->grab_box = view_geometry(view);
        server->resize_edges = edges;
 }
-
index 1f1aa33a69d4c0b6add631038efa790af3bbcb5a..fcbce31d878c31e8a0c7b5db7b12fe1e585bb578 100644 (file)
@@ -1,4 +1,5 @@
 labwc_sources = files(
+  'cursor.c',
   'deco.c',
   'interactive.c',
   'main.c',
index 69a2f490a54b5001c071ad04577858938bcd8d50..be047f44ca18ac63de2b222ea7cf8ad2df8263cb 100644 (file)
@@ -1,8 +1,5 @@
 #include "labwc.h"
 
-#define MIN_VIEW_WIDTH (100)
-#define MIN_VIEW_HEIGHT (60)
-
 static void keyboard_handle_modifiers(struct wl_listener *listener, void *data)
 {
        /*
@@ -212,213 +209,6 @@ void seat_request_set_selection(struct wl_listener *listener, void *data)
        wlr_seat_set_selection(server->seat, event->source, event->serial);
 }
 
-static void process_cursor_move(struct server *server, uint32_t time)
-{
-       /* Move the grabbed view to the new position. */
-       double dx = server->cursor->x - server->grab_x;
-       double dy = server->cursor->y - server->grab_y;
-       server->grabbed_view->x = server->grab_box.x + dx;
-       server->grabbed_view->y = server->grab_box.y + dy;
-
-       if (server->grabbed_view->type != LAB_XWAYLAND_VIEW)
-               return;
-
-       struct view *view = server->grabbed_view;
-       wlr_xwayland_surface_configure(view->xwayland_surface, view->x, view->y,
-                                      view->xwayland_surface->width,
-                                      view->xwayland_surface->height);
-}
-
-static void process_cursor_resize(struct server *server, uint32_t time)
-{
-       /*
-        * TODO: Wait for the client to prepare a buffer at the new size, then
-        * commit any movement that was prepared.
-        */
-       double dx = server->cursor->x - server->grab_x;
-       double dy = server->cursor->y - server->grab_y;
-
-       struct view *view = server->grabbed_view;
-       struct wlr_box new_view_geo = view_geometry(view);
-
-       if (server->resize_edges & WLR_EDGE_TOP) {
-               new_view_geo.y = server->grab_box.y + dy;
-               new_view_geo.height = server->grab_box.height - dy;
-       } else if (server->resize_edges & WLR_EDGE_BOTTOM) {
-               new_view_geo.height = server->grab_box.height + dy;
-       }
-       if (server->resize_edges & WLR_EDGE_LEFT) {
-               new_view_geo.x = server->grab_box.x + dx;
-               new_view_geo.width = server->grab_box.width - dx;
-       } else if (server->resize_edges & WLR_EDGE_RIGHT) {
-               new_view_geo.width = server->grab_box.width + dx;
-       }
-       if ((new_view_geo.height < MIN_VIEW_HEIGHT) ||
-           (new_view_geo.width < MIN_VIEW_WIDTH))
-               return;
-
-       /* Move */
-       view->x = new_view_geo.x;
-       view->y = new_view_geo.y;
-
-       /* Resize */
-       view_resize(view, new_view_geo);
-}
-
-static void process_cursor_motion(struct server *server, uint32_t time)
-{
-       /* If the mode is non-passthrough, delegate to those functions. */
-       if (server->cursor_mode == TINYWL_CURSOR_MOVE) {
-               process_cursor_move(server, time);
-               return;
-       } else if (server->cursor_mode == TINYWL_CURSOR_RESIZE) {
-               process_cursor_resize(server, time);
-               return;
-       }
-
-       /* Otherwise, find the view under the pointer and send the event along.
-        */
-       double sx, sy;
-       struct wlr_seat *seat = server->seat;
-       struct wlr_surface *surface = NULL;
-       int view_area;
-       struct view *view = view_at(server, server->cursor->x,
-                                   server->cursor->y, &surface, &sx, &sy,
-                                   &view_area);
-       if (!view) {
-               /* If there's no view under the cursor, set the cursor image to
-                * a default. This is what makes the cursor image appear when
-                * you move it around the screen, not over any views. */
-               wlr_xcursor_manager_set_cursor_image(
-                       server->cursor_mgr, "left_ptr", server->cursor);
-       }
-       switch (view_area) {
-       case LAB_DECO_PART_TOP:
-               wlr_xcursor_manager_set_cursor_image(
-                       server->cursor_mgr, "left_ptr", server->cursor);
-               break;
-       case LAB_DECO_PART_LEFT:
-               wlr_xcursor_manager_set_cursor_image(
-                       server->cursor_mgr, "left_side", server->cursor);
-               break;
-       }
-       if (surface) {
-               bool focus_changed = seat->pointer_state.focused_surface !=
-                                    surface;
-               /*
-                * "Enter" the surface if necessary. This lets the client know
-                * that the cursor has entered one of its surfaces.
-                *
-                * Note that this gives the surface "pointer focus", which is
-                * distinct from keyboard focus. You get pointer focus by moving
-                * the pointer over a window.
-                */
-               wlr_seat_pointer_notify_enter(seat, surface, sx, sy);
-               if (!focus_changed) {
-                       /* The enter event contains coordinates, so we only need
-                        * to notify on motion if the focus did not change. */
-                       wlr_seat_pointer_notify_motion(seat, time, sx, sy);
-               }
-       } else {
-               /* Clear pointer focus so future button events and such are not
-                * sent to the last client to have the cursor over it. */
-               wlr_seat_pointer_clear_focus(seat);
-       }
-}
-
-void server_cursor_motion(struct wl_listener *listener, void *data)
-{
-       /* This event is forwarded by the cursor when a pointer emits a
-        * _relative_ pointer motion event (i.e. a delta) */
-       struct server *server =
-               wl_container_of(listener, server, cursor_motion);
-       struct wlr_event_pointer_motion *event = data;
-       /* The cursor doesn't move unless we tell it to. The cursor
-        * automatically handles constraining the motion to the output layout,
-        * as well as any special configuration applied for the specific input
-        * device which generated the event. You can pass NULL for the device if
-        * you want to move the cursor around without any input. */
-       wlr_cursor_move(server->cursor, event->device, event->delta_x,
-                       event->delta_y);
-       process_cursor_motion(server, event->time_msec);
-}
-
-void server_cursor_motion_absolute(struct wl_listener *listener, void *data)
-{
-       /* This event is forwarded by the cursor when a pointer emits an
-        * _absolute_ motion event, from 0..1 on each axis. This happens, for
-        * example, when wlroots is running under a Wayland window rather than
-        * KMS+DRM, and you move the mouse over the window. You could enter the
-        * window from any edge, so we have to warp the mouse there. There is
-        * also some hardware which emits these events. */
-       struct server *server =
-               wl_container_of(listener, server, cursor_motion_absolute);
-       struct wlr_event_pointer_motion_absolute *event = data;
-       wlr_cursor_warp_absolute(server->cursor, event->device, event->x,
-                                event->y);
-       process_cursor_motion(server, event->time_msec);
-}
-
-void server_cursor_button(struct wl_listener *listener, void *data)
-{
-       /* This event is forwarded by the cursor when a pointer emits a button
-        * event. */
-       struct server *server =
-               wl_container_of(listener, server, cursor_button);
-       struct wlr_event_pointer_button *event = data;
-       /* Notify the client with pointer focus that a button press has occurred
-        */
-       wlr_seat_pointer_notify_button(server->seat, event->time_msec,
-                                      event->button, event->state);
-       double sx, sy;
-       struct wlr_surface *surface;
-       int view_area;
-       struct view *view = view_at(server, server->cursor->x,
-                                   server->cursor->y, &surface, &sx, &sy,
-                                   &view_area);
-       if (event->state == WLR_BUTTON_RELEASED) {
-               /* If you released any buttons, we exit interactive move/resize
-                * mode. */
-               server->cursor_mode = TINYWL_CURSOR_PASSTHROUGH;
-       } else {
-               /* Focus that client if the button was _pressed_ */
-               view_focus(view);
-               switch (view_area) {
-               case LAB_DECO_PART_TOP:
-                       interactive_begin(view, TINYWL_CURSOR_MOVE, 0);
-                       break;
-               case LAB_DECO_PART_LEFT:
-                       interactive_begin(view, TINYWL_CURSOR_RESIZE,
-                                         WLR_EDGE_LEFT);
-                       break;
-               }
-       }
-}
-
-void server_cursor_axis(struct wl_listener *listener, void *data)
-{
-       /* This event is forwarded by the cursor when a pointer emits an axis
-        * event, for example when you move the scroll wheel. */
-       struct server *server = wl_container_of(listener, server, cursor_axis);
-       struct wlr_event_pointer_axis *event = data;
-       /* Notify the client with pointer focus of the axis event. */
-       wlr_seat_pointer_notify_axis(server->seat, event->time_msec,
-                                    event->orientation, event->delta,
-                                    event->delta_discrete, event->source);
-}
-
-void server_cursor_frame(struct wl_listener *listener, void *data)
-{
-       /* This event is forwarded by the cursor when a pointer emits an frame
-        * event. Frame events are sent after regular pointer events to group
-        * multiple events together. For instance, two axis events may happen at
-        * the
-        * same time, in which case a frame event won't be sent in between. */
-       struct server *server = wl_container_of(listener, server, cursor_frame);
-       /* Notify the client with pointer focus of the frame event. */
-       wlr_seat_pointer_notify_frame(server->seat);
-}
-
 void server_new_output(struct wl_listener *listener, void *data)
 {
        /* This event is rasied by the backend when a new output (aka a display