diff --git a/include/labwc.h b/include/labwc.h index ebc66987..c86deccd 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -112,6 +112,13 @@ struct view_impl { void (*unmap)(struct view *view); }; +struct border { + int top; + int right; + int bottom; + int left; +}; + struct view { struct server *server; enum view_type type; @@ -127,7 +134,19 @@ struct view { bool mapped; bool been_mapped; bool minimized; + + /* geometry of the wlr_surface contained within the view */ int x, y, w, h; + + /* + * margin refers to the space between the extremities of the view and + * wlr_surface - typically made up of decoration. + * For xdg-shell views, the margin is typically negative. + */ + struct border margin; + + int xdg_grab_offset; + bool show_server_side_deco; struct wl_listener map; @@ -168,8 +187,6 @@ void xwayland_surface_new(struct wl_listener *listener, void *data); void xwayland_unmanaged_create(struct server *server, struct wlr_xwayland_surface *xsurface); -void view_init_position(struct view *view); - /** * view_get_surface_geometry - geometry relative to view * @view: toplevel containing the surface to process @@ -181,7 +198,6 @@ struct wlr_box view_geometry(struct view *view); void view_resize(struct view *view, struct wlr_box geo); void view_minimize(struct view *view); void view_unminimize(struct view *view); -bool view_hasfocus(struct view *view); void desktop_focus_view(struct view *view); @@ -218,7 +234,7 @@ void keyboard_new(struct server *server, struct wlr_input_device *device); void output_frame(struct wl_listener *listener, void *data); void output_new(struct wl_listener *listener, void *data); -struct wlr_box deco_max_extents(struct view *view); +struct border 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); diff --git a/src/cursor.c b/src/cursor.c index efcada27..faa75e10 100644 --- a/src/cursor.c +++ b/src/cursor.c @@ -30,7 +30,9 @@ static void process_cursor_resize(struct server *server, uint32_t time) double dy = server->cursor->y - server->grab_y; struct view *view = server->grabbed_view; - struct wlr_box new_view_geo = view_geometry(view); + struct wlr_box new_view_geo = { + .x = view->x, .y = view->y, .width = view->w, .height = view->h + }; if (server->resize_edges & WLR_EDGE_TOP) { new_view_geo.y = server->grab_box.y + dy; @@ -53,6 +55,8 @@ static void process_cursor_resize(struct server *server, uint32_t time) view->y = new_view_geo.y; /* Resize */ + new_view_geo.width -= 2 * view->xdg_grab_offset; + new_view_geo.height -= 2 * view->xdg_grab_offset; view_resize(view, new_view_geo); } @@ -74,8 +78,8 @@ static void process_cursor_motion(struct server *server, uint32_t time) struct wlr_surface *surface = NULL; int view_area; struct view *view = desktop_view_at(server, server->cursor->x, - server->cursor->y, &surface, &sx, &sy, - &view_area); + 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 @@ -83,6 +87,8 @@ static void process_cursor_motion(struct server *server, uint32_t time) wlr_xcursor_manager_set_cursor_image( server->cursor_mgr, XCURSOR_DEFAULT, server->cursor); } + + /* TODO: Could we use wlr_xcursor_get_resize_name() here?? */ switch (view_area) { case LAB_DECO_PART_TITLE: wlr_xcursor_manager_set_cursor_image( @@ -189,8 +195,8 @@ void cursor_button(struct wl_listener *listener, void *data) struct wlr_surface *surface; int view_area; struct view *view = desktop_view_at(server, server->cursor->x, - server->cursor->y, &surface, &sx, &sy, - &view_area); + server->cursor->y, &surface, &sx, + &sy, &view_area); if (event->state == WLR_BUTTON_RELEASED) { /* Exit interactive move/resize mode. */ server->cursor_mode = LAB_CURSOR_PASSTHROUGH; diff --git a/src/deco.c b/src/deco.c index 1366b226..4b365c16 100644 --- a/src/deco.c +++ b/src/deco.c @@ -10,17 +10,17 @@ #include "common/bug-on.h" #include "common/log.h" -#define BORDER_WIDTH (1) +#define BORDER_WIDTH (2) -struct wlr_box deco_max_extents(struct view *view) +struct border deco_max_extents(struct view *view) { - struct wlr_box box = { - .x = view->x - BORDER_WIDTH, - .y = view->y - rc.title_height - BORDER_WIDTH, - .width = view->w + 2 * BORDER_WIDTH, - .height = view->h + rc.title_height + 2 * BORDER_WIDTH, + struct border border = { + .top = rc.title_height + BORDER_WIDTH, + .bottom = BORDER_WIDTH, + .left = BORDER_WIDTH, + .right = BORDER_WIDTH, }; - return box; + return border; } struct wlr_box deco_box(struct view *view, enum deco_part deco_part) diff --git a/src/desktop.c b/src/desktop.c index 19e8e5d6..268e8951 100644 --- a/src/desktop.c +++ b/src/desktop.c @@ -153,11 +153,8 @@ static bool _view_at(struct view *view, double lx, double ly, view->xdg_surface, view_sx, view_sy, &_sx, &_sy); break; case LAB_XWAYLAND_VIEW: - if (!view->xwayland_surface->surface) - return false; - _surface = - wlr_surface_surface_at(view->xwayland_surface->surface, - view_sx, view_sy, &_sx, &_sy); + _surface = wlr_surface_surface_at(view->surface, view_sx, + view_sy, &_sx, &_sy); break; } diff --git a/src/interactive.c b/src/interactive.c index c702e4c9..bad7690f 100644 --- a/src/interactive.c +++ b/src/interactive.c @@ -14,6 +14,9 @@ void interactive_begin(struct view *view, enum cursor_mode mode, uint32_t edges) /* Remember view and cursor positions at start of move/resize */ server->grab_x = server->cursor->x; server->grab_y = server->cursor->y; - server->grab_box = view_geometry(view); + struct wlr_box box = { + .x = view->x, .y = view->y, .width = view->w, .height = view->h + }; + memcpy(&server->grab_box, &box, sizeof(struct wlr_box)); server->resize_edges = edges; } diff --git a/src/output.c b/src/output.c index 44cf15e1..3cd37f84 100644 --- a/src/output.c +++ b/src/output.c @@ -53,14 +53,10 @@ static void render_cycle_box(struct output *output) } return; render_it: - if ((view->type == LAB_XWAYLAND_VIEW) || !rc.client_side_decorations) { - box = deco_max_extents(view); - } else { - box.x = view->x; - box.y = view->y; - box.width = view->w; - box.height = view->h; - } + box.x = view->x - view->margin.left; + box.y = view->y - view->margin.top; + box.width = view->w + view->margin.left + view->margin.right; + box.height = view->h + view->margin.top + view->margin.bottom; struct draw_data dd = { .renderer = view->server->renderer, .transform_matrix = output->wlr_output->transform_matrix, diff --git a/src/view.c b/src/view.c index d47a07b3..ee7a4dce 100644 --- a/src/view.c +++ b/src/view.c @@ -1,70 +1,13 @@ #include "labwc.h" #include "common/bug-on.h" -void view_init_position(struct view *view) -{ - /* If surface already has a 'desired' position, don't touch it */ - if (view->x || view->y) - return; - - /* Do not touch xwayland surfaces like menus and apps like dmenu */ - if (view->type == LAB_XWAYLAND_VIEW && !view->show_server_side_deco) - return; - - struct wlr_box box; - if (view->type == LAB_XDG_SHELL_VIEW && !view->show_server_side_deco) - /* - * We're here either because rc.xml says yes to CSD or - * because the XDG shell won't allow CSD to be turned off - */ - wlr_xdg_surface_get_geometry(view->xdg_surface, &box); - else - box = deco_max_extents(view); - view->x -= box.x; - view->y -= box.y; - if (view->type != LAB_XWAYLAND_VIEW) - return; - wlr_xwayland_surface_configure(view->xwayland_surface, view->x, view->y, - view->xwayland_surface->width, - view->xwayland_surface->height); -} - -struct wlr_box view_get_surface_geometry(struct view *view) -{ - struct wlr_box box = { 0 }; - switch (view->type) { - case LAB_XDG_SHELL_VIEW: - wlr_xdg_surface_get_geometry(view->xdg_surface, &box); - break; - case LAB_XWAYLAND_VIEW: - box.width = view->w; - box.height = view->h; - break; - } - return box; -} - -/* Get geometry relative to screen */ -struct wlr_box view_geometry(struct view *view) -{ - struct wlr_box b = view_get_surface_geometry(view); - /* Add XDG view invisible border if it exists */ - b.width += 2 * b.x; - b.height += 2 * b.y; - /* Make co-ordinates relative to screen */ - b.x = view->x; - b.y = view->y; - return b; -} - void view_resize(struct view *view, struct wlr_box geo) { - struct wlr_box border = view_get_surface_geometry(view); struct wlr_box box = { .x = view->x, .y = view->y, - .width = geo.width - 2 * border.x, - .height = geo.height - 2 * border.y, + .width = geo.width, + .height = geo.height, }; view->impl->configure(view, box); } diff --git a/src/xdg.c b/src/xdg.c index df9c71d9..595613de 100644 --- a/src/xdg.c +++ b/src/xdg.c @@ -129,18 +129,41 @@ static void xdg_toplevel_view_close(struct view *view) wlr_xdg_toplevel_send_close(view->xdg_surface); } +static struct border xdg_shell_border(struct view *view) +{ + struct wlr_box box; + wlr_xdg_surface_get_geometry(view->xdg_surface, &box); + struct border border = { + .top = -box.y, + .bottom = -box.y, + .left = -box.x, + .right = -box.x, + }; + return border; +} + static void xdg_toplevel_view_map(struct view *view) { view->mapped = true; view->surface = view->xdg_surface->surface; if (!view->been_mapped) { view->show_server_side_deco = has_ssd(view); - view_init_position(view); + if (view->show_server_side_deco) { + view->margin = deco_max_extents(view); + } else { + view->margin = xdg_shell_border(view); + view->xdg_grab_offset = -view->margin.left; + } + /* align to edge of screen */ + view->x += view->margin.left; + view->y += view->margin.top; } view->been_mapped = true; + wl_signal_add(&view->xdg_surface->surface->events.commit, &view->commit); view->commit.notify = handle_commit; + desktop_focus_view(view); } diff --git a/src/xwayland.c b/src/xwayland.c index ae10e26d..c40976b4 100644 --- a/src/xwayland.c +++ b/src/xwayland.c @@ -55,12 +55,10 @@ static void _close(struct view *view) wlr_xwayland_surface_close(view->xwayland_surface); } -static bool want_ssd(struct view *view) +static bool want_deco(struct view *view) { - if (view->xwayland_surface->decorations != - WLR_XWAYLAND_SURFACE_DECORATIONS_ALL) - return false; - return true; + return view->xwayland_surface->decorations == + WLR_XWAYLAND_SURFACE_DECORATIONS_ALL; } static void map(struct view *view) @@ -68,12 +66,20 @@ static void map(struct view *view) view->mapped = true; view->x = view->xwayland_surface->x; view->y = view->xwayland_surface->y; + view->w = view->xwayland_surface->width; + view->h = view->xwayland_surface->height; view->surface = view->xwayland_surface->surface; - if (!view->been_mapped) { - view->show_server_side_deco = want_ssd(view); - view_init_position(view); - } - view->been_mapped = true; + view->show_server_side_deco = want_deco(view); + + view->margin = deco_max_extents(view); + + /* ensure we're inside screen */ + view->x += view->margin.left; + view->y += view->margin.top; + struct wlr_box box = { + .x = view->x, .y = view->y, .width = view->w, .height = view->h + }; + view->impl->configure(view, box); /* Add commit here, as xwayland map/unmap can change the wlr_surface */ wl_signal_add(&view->xwayland_surface->surface->events.commit,