]> git.mdlowis.com Git - proto/labwc.git/commitdiff
Support xwayland window title bar dragging
authorJohan Malm <jgm323@gmail.com>
Mon, 4 May 2020 21:21:30 +0000 (22:21 +0100)
committerJohan Malm <jgm323@gmail.com>
Mon, 4 May 2020 21:21:30 +0000 (22:21 +0100)
Makefile
README.md
deco.c [new file with mode: 0644]
labwc.h
output.c
server.c
view.c

index 2ab76353733248f478fc30c50d98fb0026f006fc..cbb31be64ec35b2e373c57e50b1a9b97714f0013 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -13,9 +13,11 @@ ASAN_FLAGS = -O0 -fsanitize=address -fno-common -fno-omit-frame-pointer -rdynami
 WP = `pkg-config --variable=pkgdatadir wayland-protocols`
 WS = `pkg-config --variable=wayland_scanner wayland-scanner`
 
+OBJS = main.o xdg.o view.o xwl.o server.o output.o dbg.o deco.o
+
 all: labwc
 
-labwc: xdg-shell-protocol.o main.o xdg.o view.o xwl.o server.o output.o dbg.o
+labwc: xdg-shell-protocol.o $(OBJS)
        $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
 
 xdg-shell-protocol.h:
index edbbd8710c079e17fc9fdc34bac333d43b8a56f2..b0940f0630417111f25e01b7b39770e319ebecba 100644 (file)
--- a/README.md
+++ b/README.md
@@ -2,8 +2,6 @@
 
 labwc is a wayland compositor based on wlroots
 
-[https://imgur.com/rb2hJh3](https://imgur.com/rb2hJh3)
-
 ## Dependencies
 
 - wlroots
@@ -15,7 +13,6 @@ labwc is a wayland compositor based on wlroots
 Alt+Escape  Exit labwc
 Alt+F2      Cycle between windows
 Alt+F3      Launch dmenu
-Alt+F6      Move window
 Alt+F12     Print all views (helpful if run from X11)
 ```
 
@@ -47,7 +44,7 @@ In terms of size comparison of these two giants, it's worth reflecting on the si
 
 [sway](https://github.com/swaywm/sway) - 37k LOC
 
-[rootston](https://github.com/swaywm/wlroots/tree/master/rootston) - 7k LOC
+[rootston]() - 7k LOC
 
 [openbox](https://github.com/danakj/openbox) - 53k LOC
 
diff --git a/deco.c b/deco.c
new file mode 100644 (file)
index 0000000..cf89f8d
--- /dev/null
+++ b/deco.c
@@ -0,0 +1,39 @@
+#include "labwc.h"
+
+struct wlr_box deco_max_extents(struct view *view)
+{
+       struct wlr_box box = {
+               .x = view->x - XWL_WINDOW_BORDER,
+               .y = view->y - XWL_TITLEBAR_HEIGHT - XWL_WINDOW_BORDER,
+               .width = view->surface->current.width + 2 * XWL_WINDOW_BORDER,
+               .height = view->surface->current.height + XWL_TITLEBAR_HEIGHT +
+                         2 * XWL_WINDOW_BORDER,
+       };
+       return box;
+}
+
+struct wlr_box deco_box(struct view *view, enum deco_part deco_part)
+{
+       struct wlr_box box = { .x = 0, .y = 0, .width = 0, .height = 0 };
+       if (!view)
+               return;
+       switch (deco_part) {
+       case LAB_DECO_PART_TOP:
+               box.x = view->x - XWL_WINDOW_BORDER;
+               box.y = view->y - XWL_TITLEBAR_HEIGHT - XWL_WINDOW_BORDER;
+               box.width = view->surface->current.width + 2 * XWL_WINDOW_BORDER;
+               box.height = XWL_TITLEBAR_HEIGHT + XWL_WINDOW_BORDER;
+               break;
+       }
+       return box;
+}
+
+enum deco_part deco_at(struct view *view, double lx, double ly)
+{
+       struct wlr_box box;
+       box = deco_box(view, LAB_DECO_PART_TOP);
+       if (wlr_box_contains_point(&box, lx, ly))
+               return LAB_DECO_PART_TOP;
+       return LAB_DECO_NONE;
+}
+
diff --git a/labwc.h b/labwc.h
index c610e9d7ba0d72f07f7e359f1d586e0aefa3fd9d..b333819f8311f6b02e668011168a823fd64754aa 100644 (file)
--- a/labwc.h
+++ b/labwc.h
@@ -33,7 +33,6 @@
 #define XWL_TITLEBAR_HEIGHT (10)
 #define XWL_WINDOW_BORDER (3)
 
-/* For brevity's sake, struct members are annotated where they are used. */
 enum cursor_mode {
        TINYWL_CURSOR_PASSTHROUGH,
        TINYWL_CURSOR_MOVE,
@@ -84,6 +83,11 @@ struct output {
 
 enum view_type { LAB_XDG_SHELL_VIEW, LAB_XWAYLAND_VIEW };
 
+enum deco_part {
+       LAB_DECO_NONE,
+       LAB_DECO_PART_TOP
+};
+
 struct view {
        enum view_type type;
        struct wl_list link;
@@ -131,6 +135,7 @@ void xwl_surface_destroy(struct wl_listener *listener, void *data);
 void xwl_surface_configure(struct wl_listener *listener, void *data);
 void xwl_surface_new(struct wl_listener *listener, void *data);
 
+bool view_want_deco(struct view *view);
 void view_focus_last_toplevel(struct server *server);
 void focus_view(struct view *view, struct wlr_surface *surface);
 void view_focus_next_toplevel(struct server *server);
@@ -139,7 +144,7 @@ void begin_interactive(struct view *view, enum cursor_mode mode,
 bool is_toplevel(struct view *view);
 struct view *desktop_view_at(struct server *server, double lx, double ly,
                             struct wlr_surface **surface, double *sx,
-                            double *sy);
+                            double *sy, int *view_area);
 
 /* TODO: try to refactor to remove from header file */
 struct view *first_toplevel(struct server *server);
@@ -157,4 +162,8 @@ void output_frame(struct wl_listener *listener, void *data);
 
 void dbg_show_views(struct server *server);
 
+struct wlr_box deco_max_extents(struct view *view);
+struct wlr_box deco_box(struct view *view, enum deco_part deco_part);
+enum deco_part deco_at(struct view *view, double lx, double ly);
+
 #endif /* LABWC_H */
index 773763c6f230b3cce5df7611b6af73a576fed920..34172e03e428d429e2b9ab8b2b186f9cc3b0f393 100644 (file)
--- a/output.c
+++ b/output.c
@@ -1,9 +1,5 @@
 #include "labwc.h"
 
-/*
- * Used to move all of the data necessary to render a surface from the
- * top-level frame handler to the per-surface render function.
- */
 struct render_data {
        struct wlr_output *output;
        struct wlr_renderer *renderer;
@@ -13,32 +9,19 @@ struct render_data {
 
 static void render_decorations(struct wlr_output *output, struct view *view)
 {
-       if (!view->surface)
-               return;
-       if (view->type != LAB_XWAYLAND_VIEW)
-               return;
-       if (!is_toplevel(view))
-               return;
-       if (view->xwayland_surface->override_redirect)
-               return;
-       if (view->xwayland_surface->decorations !=
-           WLR_XWAYLAND_SURFACE_DECORATIONS_ALL)
+       if (!view_want_deco(view))
                return;
 
-       struct wlr_box box = {
-               .x = view->x - XWL_WINDOW_BORDER,
-               .y = view->y - XWL_TITLEBAR_HEIGHT - XWL_WINDOW_BORDER,
-               .width = view->surface->current.width + 2 * XWL_WINDOW_BORDER,
-               .height = view->surface->current.height + XWL_TITLEBAR_HEIGHT +
-                         2 * XWL_WINDOW_BORDER,
-       };
-
+       struct wlr_box box = deco_max_extents(view);
        float matrix[9];
        wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL, 0,
                               output->transform_matrix);
-
        float color[] = { 0.2, 0.2, 0.7, 0.9 };
        wlr_render_quad_with_matrix(view->server->renderer, color, matrix);
+
+       box = deco_box(view, LAB_DECO_PART_TOP);
+       float color2[] = { 0.7, 0.2, 0.2, 0.9 };
+       wlr_render_rect(view->server->renderer, &box, color2, output->transform_matrix);
 }
 
 static void render_surface(struct wlr_surface *surface, int sx, int sy,
index 7eb01a39eb893187567769b99ef95322e5c77e51..bccce7bc17675ac9033b9f4119c8286fa04ae2fb 100644 (file)
--- a/server.c
+++ b/server.c
@@ -252,9 +252,10 @@ static void process_cursor_motion(struct server *server, uint32_t time)
        double sx, sy;
        struct wlr_seat *seat = server->seat;
        struct wlr_surface *surface = NULL;
+       int view_area;
        struct view *view = desktop_view_at(server, server->cursor->x,
                                            server->cursor->y, &surface, &sx,
-                                           &sy);
+                                           &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
@@ -262,6 +263,12 @@ static void process_cursor_motion(struct server *server, uint32_t time)
                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;
+       }
        if (surface) {
                bool focus_changed = seat->pointer_state.focused_surface !=
                                     surface;
@@ -332,9 +339,10 @@ void server_cursor_button(struct wl_listener *listener, void *data)
                                       event->button, event->state);
        double sx, sy;
        struct wlr_surface *surface;
+       int view_area;
        struct view *view = desktop_view_at(server, server->cursor->x,
                                            server->cursor->y, &surface, &sx,
-                                           &sy);
+                                           &sy, &view_area);
        if (event->state == WLR_BUTTON_RELEASED) {
                /* If you released any buttons, we exit interactive move/resize
                 * mode. */
@@ -342,6 +350,11 @@ void server_cursor_button(struct wl_listener *listener, void *data)
        } else {
                /* Focus that client if the button was _pressed_ */
                focus_view(view, surface);
+               switch (view_area) {
+               case LAB_DECO_PART_TOP:
+                       begin_interactive(view, TINYWL_CURSOR_MOVE, 0);
+                       break;
+               }
        }
 }
 
diff --git a/view.c b/view.c
index 46b508110a9144d5c95b57b26c5da69daa125651..90dd12e948d991e59d8d4ab34af60198703788ad 100644 (file)
--- a/view.c
+++ b/view.c
@@ -1,5 +1,21 @@
 #include "labwc.h"
 
+bool view_want_deco(struct view *view)
+{
+       if (!view->surface)
+               return false;
+       if (view->type != LAB_XWAYLAND_VIEW)
+               return false;
+       if (!is_toplevel(view))
+               return false;
+       if (view->xwayland_surface->override_redirect)
+               return false;
+       if (view->xwayland_surface->decorations !=
+           WLR_XWAYLAND_SURFACE_DECORATIONS_ALL)
+               return false;
+       return true;
+}
+
 static struct view *last_toplevel(struct server *server)
 {
        struct view *view;
@@ -127,10 +143,6 @@ void begin_interactive(struct view *view, enum cursor_mode mode, uint32_t edges)
        struct server *server = view->server;
        struct wlr_surface *focused_surface =
                server->seat->pointer_state.focused_surface;
-       if (view->surface != focused_surface) {
-               /* Deny move/resize requests from unfocused clients. */
-               return;
-       }
        server->grabbed_view = view;
        server->cursor_mode = mode;
 
@@ -216,7 +228,7 @@ static bool view_at(struct view *view, double lx, double ly,
                break;
        }
 
-       if (_surface != NULL) {
+       if (_surface) {
                *sx = _sx;
                *sy = _sy;
                *surface = _surface;
@@ -227,16 +239,28 @@ static bool view_at(struct view *view, double lx, double ly,
 
 struct view *desktop_view_at(struct server *server, double lx, double ly,
                             struct wlr_surface **surface, double *sx,
-                            double *sy)
+                            double *sy, int *view_area)
 {
-       /* This iterates over all of our surfaces and attempts to find one under
-        * the cursor. This relies on server->views being ordered from
-        * top-to-bottom. */
+       /*
+        * This iterates over all of our surfaces and attempts to find one under
+        * the cursor. It relies on server->views being ordered from
+        * top-to-bottom.
+        */
+       struct wlr_box border_box = {
+               .x = 0, .y = 0,
+               .width = 0, .height = 0,
+       };
        struct view *view;
        wl_list_for_each (view, &server->views, link) {
-               if (view_at(view, lx, ly, surface, sx, sy)) {
+               if (view_at(view, lx, ly, surface, sx, sy))
+                       return view;
+               if (!view_want_deco(view))
+                       continue;
+               if (deco_at(view, lx, ly) == LAB_DECO_PART_TOP) {
+                       *view_area = LAB_DECO_PART_TOP;
                        return view;
                }
        }
        return NULL;
 }
+