#ifndef __LABWC_SSD_INTERNAL_H
#define __LABWC_SSD_INTERNAL_H
+#include <wlr/util/box.h>
#include "ssd.h"
#define FOR_EACH(tmp, ...) \
* don't update things we don't have to.
*/
struct {
- int x;
- int y;
- int width;
- int height;
+ struct wlr_box geometry;
struct ssd_state_title {
char *text;
struct ssd_state_title_width active;
} title;
} state;
- /* An invisble area around the view which allows resizing */
+ /* An invisible area around the view which allows resizing */
struct ssd_sub_tree extents;
/* The top of the view, containing buttons, title, .. */
struct wlr_output *fullscreen;
- /* geometry of the wlr_surface contained within the view */
- int x, y, w, h;
-
- /* user defined geometry before maximize / tiling / fullscreen */
+ /*
+ * Geometry of the wlr_surface contained within the view, as
+ * currently displayed. Should be kept in sync with the
+ * scene-graph at all times.
+ */
+ struct wlr_box current;
+ /*
+ * Expected geometry after any pending move/resize requests
+ * have been processed. Should match current geometry when no
+ * move/resize requests are pending.
+ */
+ struct wlr_box pending;
+ /*
+ * Saved geometry which will be restored when the view returns
+ * to normal/floating state after being maximized/fullscreen/
+ * tiled. Values are undefined/out-of-date when the view is not
+ * maximized/fullscreen/tiled.
+ */
struct wlr_box natural_geometry;
- struct view_pending_move_resize {
- int x, y;
- uint32_t width, height;
- uint32_t configure_serial;
- } pending_move_resize;
+ /* used by xdg-shell views */
+ uint32_t pending_configure_serial;
struct ssd *ssd;
int x, y;
if (force_menu_top_left) {
- x = view->x;
- y = view->y;
+ x = view->current.x;
+ y = view->current.y;
} else {
x = server->seat.cursor->x;
y = server->seat.cursor->y;
double dy = server->seat.cursor->y - server->grab_y;
struct view *view = server->grabbed_view;
- struct wlr_box new_view_geo = {
- .x = view->x, .y = view->y, .width = view->w, .height = view->h
- };
+ struct wlr_box new_view_geo = view->current;
if (server->resize_edges & WLR_EDGE_TOP) {
new_view_geo.height = server->grab_box.height - dy;
int lx, ly;
if (view) {
- lx = view->x;
- ly = view->y;
+ lx = view->current.x;
+ ly = view->current.y;
} else if (node && wlr_surface_is_layer_surface(surface)) {
wlr_scene_node_coords(node, &lx, &ly);
#if HAVE_XWAYLAND
{
uint32_t resize_edges = ssd_resize_edges(ctx->type);
if (ctx->view && !resize_edges) {
+ struct wlr_box box = ctx->view->current;
resize_edges |=
- (int)cursor->x < ctx->view->x + ctx->view->w / 2 ?
+ (int)cursor->x < box.x + box.width / 2 ?
WLR_EDGE_LEFT : WLR_EDGE_RIGHT;
resize_edges |=
- (int)cursor->y < ctx->view->y + ctx->view->h / 2 ?
+ (int)cursor->y < box.y + box.height / 2 ?
WLR_EDGE_TOP : WLR_EDGE_BOTTOM;
}
return resize_edges;
{
assert(view->toplevel.handle);
- struct wlr_box view_geo = { view->x, view->y, view->w, view->h };
+ struct wlr_box view_geo = view->current;
struct wlr_output_layout *layout = view->server->output_layout;
struct output *output;
*/
struct server *server = view->server;
struct seat *seat = &server->seat;
- struct wlr_box geometry = {
- .x = view->x,
- .y = view->y,
- .width = view->w,
- .height = view->h
- };
+ struct wlr_box geometry = view->current;
switch (mode) {
case LAB_INPUT_STATE_MOVE:
* to keep it (in the snap-to-maximize case).
*/
geometry = view->natural_geometry;
- geometry.x = max_move_scale(seat->cursor->x, view->x,
- view->w, geometry.width);
- geometry.y = max_move_scale(seat->cursor->y, view->y,
- view->h, geometry.height);
+ geometry.x = max_move_scale(seat->cursor->x,
+ view->current.x, view->current.width,
+ geometry.width);
+ geometry.y = max_move_scale(seat->cursor->y,
+ view->current.y, view->current.height,
+ geometry.height);
view_restore_to(view, geometry);
} else {
/* Store natural geometry at start of move */
{
struct server *server = view->server;
struct wlr_box mgeom, intersection;
- struct wlr_box vgeom = {.x = view->x, .y = view->y, .width = view->w,
- .height = view->h};
- struct wlr_box tgeom = {.x = *x, .y = *y, .width = view->w,
- .height = view->h};
+ struct wlr_box vgeom = view->current;
+ struct wlr_box tgeom = {.x = *x, .y = *y, .width = vgeom.width,
+ .height = vgeom.height};
struct output *output;
struct border border = ssd_get_margin(view->ssd);
struct edges view_edges; /* The edges of the current view */
struct edges other_edges; /* The edges of the monitor/other view */
struct edges flags = { 0 };
- view_edges.left = view->x - border.left + 1;
- view_edges.top = view->y - border.top + 1;
- view_edges.right = view->x + view->w + border.right;
- view_edges.bottom = view->y + view->h + border.bottom;
+ view_edges.left = vgeom.x - border.left + 1;
+ view_edges.top = vgeom.y - border.top + 1;
+ view_edges.right = vgeom.x + vgeom.width + border.right;
+ view_edges.bottom = vgeom.y + vgeom.height + border.bottom;
target_edges.left = *x - border.left;
target_edges.top = *y - border.top;
- target_edges.right = *x + view->w + border.right;
- target_edges.bottom = *y + view->h + border.bottom;
+ target_edges.right = *x + vgeom.width + border.right;
+ target_edges.bottom = *y + vgeom.height + border.bottom;
if (!rc.screen_edge_strength) {
return;
if (flags.left == 1) {
*x = other_edges.left + border.left;
} else if (flags.right == 1) {
- *x = other_edges.right - view->w - border.right;
+ *x = other_edges.right - vgeom.width - border.right;
}
if (flags.top == 1) {
*y = other_edges.top + border.top;
} else if (flags.bottom == 1) {
- *y = other_edges.bottom - view->h - border.bottom;
+ *y = other_edges.bottom - vgeom.height - border.bottom;
}
/* reset the flags */
struct server *server = view->server;
struct output *output;
struct wlr_box mgeom, intersection;
- struct wlr_box vgeom = {.x = view->x, .y = view->y, .width = view->w,
- .height = view->h};
- struct wlr_box tgeom = {.x = new_view_geo->x, .y = new_view_geo->y,
- .width = new_view_geo->width, .height = new_view_geo->height};
+ struct wlr_box vgeom = view->current;
+ struct wlr_box tgeom = *new_view_geo;
struct border border = ssd_get_margin(view->ssd);
struct edges view_edges; /* The edges of the current view */
struct edges target_edges; /* The desired edges */
struct edges other_edges; /* The edges of the monitor/other view */
struct edges flags = { 0 };
- view_edges.left = view->x - border.left;
- view_edges.top = view->y - border.top;
- view_edges.right = view->x + view->w + border.right;
- view_edges.bottom = view->y + view->h + border.bottom;
+ view_edges.left = vgeom.x - border.left;
+ view_edges.top = vgeom.y - border.top;
+ view_edges.right = vgeom.x + vgeom.width + border.right;
+ view_edges.bottom = vgeom.y + vgeom.height + border.bottom;
target_edges.left = new_view_geo->x - border.left;
target_edges.top = new_view_geo->y - border.top;
if (flags.left == 1) {
new_view_geo->x = other_edges.left
+ border.left;
- new_view_geo->width = view->w;
+ new_view_geo->width = vgeom.width;
}
} else if (server->resize_edges & WLR_EDGE_RIGHT) {
if (flags.right == 1) {
if (server->resize_edges & WLR_EDGE_TOP) {
if (flags.top == 1) {
new_view_geo->y = other_edges.top + border.top;
- new_view_geo->height = view->h;
+ new_view_geo->height = vgeom.height;
}
} else if (server->resize_edges & WLR_EDGE_BOTTOM) {
if (flags.bottom == 1) {
assert(view);
struct border border = ssd_thickness(view);
return (struct wlr_box){
- .x = view->x - border.left,
- .y = view->y - border.top,
- .width = view->w + border.left + border.right,
- .height = view->h + border.top + border.bottom,
+ .x = view->current.x - border.left,
+ .y = view->current.y - border.top,
+ .width = view->current.width + border.left + border.right,
+ .height = view->current.height + border.top + border.bottom,
};
}
ssd_titlebar_create(ssd);
ssd->margin = ssd_thickness(view);
ssd_set_active(ssd, active);
-
- ssd->state.width = view->w;
- ssd->state.height = view->h;
- ssd->state.x = view->x;
- ssd->state.y = view->y;
+ ssd->state.geometry = view->current;
return ssd;
}
return;
}
- struct view *view = ssd->view;
- if (view->w == ssd->state.width && view->h == ssd->state.height) {
- if (view->x != ssd->state.x || view->y != ssd->state.y) {
+ struct wlr_box cached = ssd->state.geometry;
+ struct wlr_box current = ssd->view->current;
+ if (current.width == cached.width && current.height == cached.height) {
+ if (current.x != cached.x || current.y != cached.y) {
/* Dynamically resize extents based on position and usable_area */
ssd_extents_update(ssd);
- ssd->state.x = view->x;
- ssd->state.y = view->y;
+ ssd->state.geometry = current;
}
return;
}
ssd_extents_update(ssd);
ssd_border_update(ssd);
ssd_titlebar_update(ssd);
-
- ssd->state.width = view->w;
- ssd->state.height = view->h;
- ssd->state.x = view->x;
- ssd->state.y = view->y;
+ ssd->state.geometry = current;
}
void
{
struct view *view = ssd->view;
struct theme *theme = view->server->theme;
- int width = view->w;
- int height = view->h;
+ int width = view->current.width;
+ int height = view->current.height;
int full_width = width + 2 * theme->border_width;
float *color;
struct view *view = ssd->view;
struct theme *theme = view->server->theme;
- int width = view->w;
- int height = view->h;
+ int width = view->current.width;
+ int height = view->current.height;
int full_width = width + 2 * theme->border_width;
struct ssd_part *part;
struct theme *theme = view->server->theme;
- int width = view->w;
- int height = view->h;
+ int width = view->current.width;
+ int height = view->current.height;
int full_height = height + theme->border_width * 2 + theme->title_height;
int full_width = width + 2 * theme->border_width;
int extended_area = SSD_EXTENDED_AREA;
{
struct view *view = ssd->view;
struct theme *theme = view->server->theme;
- int width = view->w;
+ int width = view->current.width;
float *color;
struct wlr_scene_tree *parent;
ssd_titlebar_update(struct ssd *ssd)
{
struct view *view = ssd->view;
- int width = view->w;
- if (width == ssd->state.width) {
+ int width = view->current.width;
+ if (width == ssd->state.geometry.width) {
return;
}
struct theme *theme = view->server->theme;
{
struct view *view = ssd->view;
struct theme *theme = view->server->theme;
- int width = view->w;
+ int width = view->current.width;
int title_bg_width = width - SSD_BUTTON_WIDTH * SSD_BUTTON_COUNT;
int x, y;
struct ssd_part *part;
struct ssd_sub_tree *subtree;
struct ssd_state_title_width *dstate;
- int title_bg_width = view->w - SSD_BUTTON_WIDTH * SSD_BUTTON_COUNT;
+ int title_bg_width = view->current.width
+ - SSD_BUTTON_WIDTH * SSD_BUTTON_COUNT;
FOR_EACH_STATE(ssd, subtree) {
if (subtree == &ssd->titlebar.active) {
view_moved(struct view *view)
{
assert(view);
- wlr_scene_node_set_position(&view->scene_tree->node, view->x, view->y);
+ wlr_scene_node_set_position(&view->scene_tree->node,
+ view->current.x, view->current.y);
view_discover_output(view);
ssd_update_geometry(view->ssd);
cursor_update_focus(view->server);
double closest_x, closest_y;
struct wlr_output *wlr_output = NULL;
wlr_output_layout_closest_point(view->server->output_layout, wlr_output,
- view->x + view->w / 2, view->y + view->h / 2, &closest_x,
- &closest_y);
+ view->current.x + view->current.width / 2,
+ view->current.y + view->current.height / 2,
+ &closest_x, &closest_y);
wlr_output = wlr_output_layout_output_at(view->server->output_layout,
closest_x, closest_y);
return wlr_output;
* natural_geometry width/height may still be zero in which case we set
* some fallback values. This is the case with foot and Qt applications.
*/
- if (!view->w || !view->h) {
+ if (wlr_box_empty(&view->current)) {
set_fallback_geometry(view);
} else {
- view->natural_geometry.x = view->x;
- view->natural_geometry.y = view->y;
- view->natural_geometry.width = view->w;
- view->natural_geometry.height = view->h;
+ view->natural_geometry = view->current;
}
}
{
assert(view);
int x, y;
- if (view_compute_centered_position(view, view->w, view->h, &x, &y)) {
+ if (view_compute_centered_position(view, view->current.width,
+ view->current.height, &x, &y)) {
view_move(view, x, y);
}
}
geo.width -= margin.left + margin.right;
geo.height -= margin.top + margin.bottom;
- if (view->w == geo.width && view->h == geo.height) {
+ if (view->current.width == geo.width
+ && view->current.height == geo.height) {
/* move horizontally/vertically without changing size */
view_move(view, geo.x, geo.y);
} else {
}
struct wlr_box dst = view_get_edge_snap_box(view, output, view->tiled);
- if (view->w == dst.width && view->h == dst.height) {
+ if (view->current.width == dst.width
+ && view->current.height == dst.height) {
/* move horizontally/vertically without changing size */
view_move(view, dst.x, dst.y);
} else {
}
} else if (!view_apply_special_geometry(view)) {
/* reposition view if it's offscreen */
- struct wlr_box box = { view->x, view->y, view->w, view->h };
- if (!wlr_output_layout_intersects(layout, NULL, &box)) {
+ if (!wlr_output_layout_intersects(layout, NULL,
+ &view->current)) {
view_center(view);
}
}
int x = 0, y = 0;
if (!strcasecmp(direction, "left")) {
x = usable.x + margin.left + rc.gap;
- y = view->y;
+ y = view->current.y;
} else if (!strcasecmp(direction, "up")) {
- x = view->x;
+ x = view->current.x;
y = usable.y + margin.top + rc.gap;
} else if (!strcasecmp(direction, "right")) {
- x = usable.x + usable.width - view->w - margin.right
- - rc.gap;
- y = view->y;
+ x = usable.x + usable.width - view->current.width
+ - margin.right - rc.gap;
+ y = view->current.y;
} else if (!strcasecmp(direction, "down")) {
- x = view->x;
- y = usable.y + usable.height - view->h - margin.bottom
- - rc.gap;
+ x = view->current.x;
+ y = usable.y + usable.height - view->current.height
+ - margin.bottom - rc.gap;
} else {
wlr_log(WLR_ERROR, "invalid edge");
return;
struct wlr_box *popup_box = &popup->current.geometry;
struct wlr_output_layout *output_layout = server->output_layout;
struct wlr_output *wlr_output = wlr_output_layout_output_at(
- output_layout, view->x + popup_box->x, view->y + popup_box->y);
+ output_layout, view->current.x + popup_box->x,
+ view->current.y + popup_box->y);
struct wlr_box output_box;
wlr_output_layout_get_box(output_layout, wlr_output, &output_box);
struct wlr_box output_toplevel_box = {
- .x = output_box.x - view->x,
- .y = output_box.y - view->y,
+ .x = output_box.x - view->current.x,
+ .y = output_box.y - view->current.y,
.width = output_box.width,
.height = output_box.height,
};
struct wlr_box size;
wlr_xdg_surface_get_geometry(xdg_surface, &size);
+ struct wlr_box *current = &view->current;
+ struct wlr_box *pending = &view->pending;
bool update_required = false;
- if (view->w != size.width || view->h != size.height) {
+ if (current->width != size.width || current->height != size.height) {
update_required = true;
- view->w = size.width;
- view->h = size.height;
+ current->width = size.width;
+ current->height = size.height;
}
- uint32_t serial = view->pending_move_resize.configure_serial;
+ uint32_t serial = view->pending_configure_serial;
if (serial > 0 && serial >= xdg_surface->current.configure_serial) {
- if (view->x != view->pending_move_resize.x) {
+ if (current->x != pending->x) {
update_required = true;
- view->x = view->pending_move_resize.x +
- view->pending_move_resize.width - size.width;
+ current->x = pending->x + pending->width - size.width;
}
- if (view->y != view->pending_move_resize.y) {
+ if (current->y != pending->y) {
update_required = true;
- view->y = view->pending_move_resize.y +
- view->pending_move_resize.height - size.height;
+ current->y = pending->y + pending->height - size.height;
}
if (serial == xdg_surface->current.configure_serial) {
- view->pending_move_resize.configure_serial = 0;
+ view->pending_configure_serial = 0;
}
}
if (update_required) {
xdg_toplevel_view_configure(struct view *view, struct wlr_box geo)
{
view_adjust_size(view, &geo.width, &geo.height);
-
- view->pending_move_resize.x = geo.x;
- view->pending_move_resize.y = geo.y;
- view->pending_move_resize.width = geo.width;
- view->pending_move_resize.height = geo.height;
+ view->pending = geo;
struct wlr_xdg_toplevel *xdg_toplevel = xdg_toplevel_from_view(view);
uint32_t serial = wlr_xdg_toplevel_set_size(xdg_toplevel,
(uint32_t)geo.width, (uint32_t)geo.height);
if (serial > 0) {
- view->pending_move_resize.configure_serial = serial;
- } else if (view->pending_move_resize.configure_serial == 0) {
- view->x = geo.x;
- view->y = geo.y;
+ view->pending_configure_serial = serial;
+ } else if (view->pending_configure_serial == 0) {
+ view->current.x = geo.x;
+ view->current.y = geo.y;
view_moved(view);
}
}
static void
xdg_toplevel_view_move(struct view *view, int x, int y)
{
- view->x = x;
- view->y = y;
+ view->current.x = x;
+ view->current.y = y;
/* override any previous pending move */
- view->pending_move_resize.x = x;
- view->pending_move_resize.y = y;
+ view->pending.x = x;
+ view->pending.y = y;
view_moved(view);
}
if (!parent_xdg_toplevel) {
struct wlr_box box =
output_usable_area_from_cursor_coords(view->server);
- view->x = box.x;
- view->y = box.y;
+ view->current.x = box.x;
+ view->current.y = box.y;
/* Center the view without touching its w and h fields. This means we
* can't simply set w/h and call view_center(). w and h fields should
struct view *parent = lookup_view_by_xdg_toplevel(
view->server, parent_xdg_toplevel);
assert(parent);
- int center_x = parent->x + parent->w / 2;
- int center_y = parent->y + parent->h / 2;
- view->x = center_x - xdg_surface->current.geometry.width / 2;
- view->y = center_y - xdg_surface->current.geometry.height / 2;
+ int center_x = parent->current.x + parent->current.width / 2;
+ int center_y = parent->current.y + parent->current.height / 2;
+ view->current.x = center_x
+ - xdg_surface->current.geometry.width / 2;
+ view->current.y = center_y
+ - xdg_surface->current.geometry.height / 2;
}
struct border margin = ssd_get_margin(view->ssd);
- view->x += margin.left;
- view->y += margin.top;
+ view->current.x += margin.left;
+ view->current.y += margin.top;
}
static const char *
static void
ensure_initial_geometry(struct view *view)
{
- if (!view->w || !view->h) {
+ if (wlr_box_empty(&view->current)) {
struct wlr_xwayland_surface *xwayland_surface =
xwayland_surface_from_view(view);
- view->x = xwayland_surface->x;
- view->y = xwayland_surface->y;
- view->w = xwayland_surface->width;
- view->h = xwayland_surface->height;
+ view->current.x = xwayland_surface->x;
+ view->current.y = xwayland_surface->y;
+ view->current.width = xwayland_surface->width;
+ view->current.height = xwayland_surface->height;
/*
* If there is no pending move/resize yet, then set
* current values (used in map()).
*/
- struct view_pending_move_resize *pending =
- &view->pending_move_resize;
- if (!pending->width || !pending->height) {
- pending->x = view->x;
- pending->y = view->y;
- pending->width = view->w;
- pending->height = view->h;
+ if (wlr_box_empty(&view->pending)) {
+ view->pending = view->current;
}
}
}
/* Must receive commit signal before accessing surface->current* */
struct wlr_surface_state *state = &view->surface->current;
- struct view_pending_move_resize *pending = &view->pending_move_resize;
+ struct wlr_box *current = &view->current;
+ struct wlr_box *pending = &view->pending;
- if (view->w == state->width && view->h == state->height) {
+ if (current->width == state->width && current->height == state->height) {
return;
}
- view->w = state->width;
- view->h = state->height;
+ current->width = state->width;
+ current->height = state->height;
- if (view->x != pending->x) {
+ if (current->x != pending->x) {
/* Adjust x for queued up configure events */
- view->x = pending->x + pending->width - view->w;
+ current->x = pending->x + pending->width - current->width;
}
- if (view->y != pending->y) {
+ if (current->y != pending->y) {
/* Adjust y for queued up configure events */
- view->y = pending->y + pending->height - view->h;
+ current->y = pending->y + pending->height - current->height;
}
view_moved(view);
}
static void
configure(struct view *view, struct wlr_box geo)
{
- view->pending_move_resize.x = geo.x;
- view->pending_move_resize.y = geo.y;
- view->pending_move_resize.width = geo.width;
- view->pending_move_resize.height = geo.height;
-
+ view->pending = geo;
wlr_xwayland_surface_configure(xwayland_surface_from_view(view),
geo.x, geo.y, geo.width, geo.height);
/* If not resizing, process the move immediately */
- if (view->w == geo.width && view->h == geo.height) {
- view->x = geo.x;
- view->y = geo.y;
+ if (view->current.width == geo.width
+ && view->current.height == geo.height) {
+ view->current.x = geo.x;
+ view->current.y = geo.y;
view_moved(view);
}
}
static void
move(struct view *view, int x, int y)
{
- view->x = x;
- view->y = y;
+ view->current.x = x;
+ view->current.y = y;
/* override any previous pending move */
- view->pending_move_resize.x = x;
- view->pending_move_resize.y = y;
+ view->pending.x = x;
+ view->pending.y = y;
struct wlr_xwayland_surface *s = xwayland_surface_from_view(view);
wlr_xwayland_surface_configure(s, (int16_t)x, (int16_t)y,
} else {
struct wlr_box box =
output_usable_area_from_cursor_coords(view->server);
- view->x = box.x;
- view->y = box.y;
+ view->current.x = box.x;
+ view->current.y = box.y;
view_center(view);
}
}
{
struct wlr_box deco = ssd_max_extents(view);
if (deco.x < 0) {
- view->x -= deco.x;
+ view->current.x -= deco.x;
}
if (deco.y < 0) {
- view->y -= deco.y;
+ view->current.y -= deco.y;
}
- struct wlr_box box = {
- .x = view->x, .y = view->y, .width = view->w, .height = view->h
- };
- view->impl->configure(view, box);
+ view->impl->configure(view, view->current);
}
static void
* the final intended position/size rather than waiting
* for handle_commit().
*/
- view->x = view->pending_move_resize.x;
- view->y = view->pending_move_resize.y;
- view->w = view->pending_move_resize.width;
- view->h = view->pending_move_resize.height;
+ view->current = view->pending;
view_moved(view);
view->been_mapped = true;
}