diff --git a/README.md b/README.md index 1b05b32c..92887736 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Aiming to become a light-weight openbox alternative for Wayland ## Dependencies -- wlroots +- wlroots (>=0.10.0) - wayland-protocols ## Background diff --git a/labwc.h b/labwc.h index b333819f..fa977b1f 100644 --- a/labwc.h +++ b/labwc.h @@ -66,7 +66,7 @@ struct server { enum cursor_mode cursor_mode; struct view *grabbed_view; double grab_x, grab_y; - int grab_width, grab_height; + struct wlr_box grab_box; uint32_t resize_edges; struct wlr_output_layout *output_layout; diff --git a/server.c b/server.c index 295c3ece..1e80ae2e 100644 --- a/server.c +++ b/server.c @@ -202,38 +202,44 @@ static void process_cursor_resize(struct server *server, uint32_t time) * view on one or two axes, but can also move the view if you resize * from the top or left edges (or top-left corner). * - * Note that I took some shortcuts here. In a more fleshed-out - * compositor, you'd wait for the client to prepare a buffer at the new - * size, then commit any movement that was prepared. + * TODO: Wait for the client to prepare a buffer at the new size, then + * commit any movement that was prepared. */ struct view *view = server->grabbed_view; - double dx = server->cursor->x - server->grab_x; - double dy = server->cursor->y - server->grab_y; - double x = view->x; - double y = view->y; - int width = server->grab_width; - int height = server->grab_height; + double border_x = server->cursor->x - server->grab_x; + double border_y = server->cursor->y - server->grab_y; + int new_left = server->grab_box.x; + int new_right = server->grab_box.x + server->grab_box.width; + int new_top = server->grab_box.y; + int new_bottom = server->grab_box.y + server->grab_box.height; + if (server->resize_edges & WLR_EDGE_TOP) { - y = server->grab_y + dy; - height -= dy; - if (height < 1) { - y += height; - } + new_top = border_y; + if (new_top >= new_bottom) + new_top = new_bottom - 1; } else if (server->resize_edges & WLR_EDGE_BOTTOM) { - height += dy; + new_bottom = border_y; + if (new_bottom <= new_top) + new_bottom = new_top + 1; } if (server->resize_edges & WLR_EDGE_LEFT) { - x = server->grab_x + dx; - width -= dx; - if (width < 1) { - x += width; - } + new_left = border_x; + if (new_left >= new_right) + new_left = new_right - 1; } else if (server->resize_edges & WLR_EDGE_RIGHT) { - width += dx; + new_right = border_x; + if (new_right <= new_left) + new_right = new_left + 1; } - view->x = x; - view->y = y; - wlr_xdg_toplevel_set_size(view->xdg_surface, width, height); + + struct wlr_box geo_box; + wlr_xdg_surface_get_geometry(view->xdg_surface, &geo_box); + view->x = new_left - geo_box.x; + view->y = new_top - geo_box.y; + + int new_width = new_right - new_left; + int new_height = new_bottom - new_top; + wlr_xdg_toplevel_set_size(view->xdg_surface, new_width, new_height); } static void process_cursor_motion(struct server *server, uint32_t time) diff --git a/view.c b/view.c index 90dd12e9..f67251f3 100644 --- a/view.c +++ b/view.c @@ -141,34 +141,36 @@ void begin_interactive(struct view *view, enum cursor_mode mode, uint32_t edges) * the compositor stops propegating pointer events to clients and * instead consumes them itself, to move or resize windows. */ struct server *server = view->server; - struct wlr_surface *focused_surface = - server->seat->pointer_state.focused_surface; server->grabbed_view = view; server->cursor_mode = mode; - struct wlr_box geo_box; - switch (view->type) { - case LAB_XDG_SHELL_VIEW: - wlr_xdg_surface_get_geometry(view->xdg_surface, &geo_box); - break; - case LAB_XWAYLAND_VIEW: - geo_box.x = view->xwayland_surface->x; - geo_box.y = view->xwayland_surface->y; - geo_box.width = view->xwayland_surface->width; - geo_box.height = view->xwayland_surface->height; - break; - } - if (mode == TINYWL_CURSOR_MOVE) { server->grab_x = server->cursor->x - view->x; server->grab_y = server->cursor->y - view->y; } else { - server->grab_x = server->cursor->x + geo_box.x; - server->grab_y = server->cursor->y + geo_box.y; + + struct wlr_box geo_box; + switch (view->type) { + case LAB_XDG_SHELL_VIEW: + wlr_xdg_surface_get_geometry(view->xdg_surface, &geo_box); + break; + case LAB_XWAYLAND_VIEW: + geo_box.x = view->xwayland_surface->x; + geo_box.y = view->xwayland_surface->y; + geo_box.width = view->xwayland_surface->width; + geo_box.height = view->xwayland_surface->height; + break; + } + + double border_x = (view->x + geo_box.x) + ((edges & WLR_EDGE_RIGHT) ? geo_box.width : 0); + double border_y = (view->y + geo_box.y) + ((edges & WLR_EDGE_BOTTOM) ? geo_box.height : 0); + server->grab_x = server->cursor->x - border_x; + server->grab_y = server->cursor->y - border_y; + server->grab_box = geo_box; + server->grab_box.x += view->x; + server->grab_box.y += view->y; + server->resize_edges = edges; } - server->grab_width = geo_box.width; - server->grab_height = geo_box.height; - server->resize_edges = edges; } bool is_toplevel(struct view *view) @@ -246,10 +248,6 @@ struct view *desktop_view_at(struct server *server, double lx, double ly, * 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))