void (*unmap)(struct view *view);
};
+struct border {
+ int top;
+ int right;
+ int bottom;
+ int left;
+};
+
struct view {
struct server *server;
enum view_type type;
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;
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
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);
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);
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;
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);
}
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
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(
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;
#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)
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;
}
/* 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;
}
}
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,
#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);
}
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);
}
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)
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,