From: Johan Malm Date: Mon, 4 May 2020 21:21:30 +0000 (+0100) Subject: Support xwayland window title bar dragging X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=83c3492c87a87a6a99c604991e7c7ead3695f202;p=proto%2Flabwc.git Support xwayland window title bar dragging --- diff --git a/Makefile b/Makefile index 2ab76353..cbb31be6 100644 --- 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: diff --git a/README.md b/README.md index edbbd871..b0940f06 100644 --- 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 index 00000000..cf89f8d9 --- /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 c610e9d7..b333819f 100644 --- 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 */ diff --git a/output.c b/output.c index 773763c6..34172e03 100644 --- 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, diff --git a/server.c b/server.c index 7eb01a39..bccce7bc 100644 --- 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 46b50811..90dd12e9 100644 --- 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; } +