mirror of
https://github.com/labwc/labwc.git
synced 2025-11-04 13:30:07 -05:00
src/view.c: Convert SnapToEdge to use view_apply_xxx_geometry framework
This commit is contained in:
parent
992089e901
commit
3a4b55886d
3 changed files with 128 additions and 104 deletions
|
|
@ -306,6 +306,7 @@ struct view {
|
||||||
bool been_mapped;
|
bool been_mapped;
|
||||||
bool minimized;
|
bool minimized;
|
||||||
bool maximized;
|
bool maximized;
|
||||||
|
uint32_t tiled; /* private, enum view_edge in src/view.c */
|
||||||
struct wlr_output *fullscreen;
|
struct wlr_output *fullscreen;
|
||||||
|
|
||||||
/* geometry of the wlr_surface contained within the view */
|
/* geometry of the wlr_surface contained within the view */
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ interactive_begin(struct view *view, enum input_mode mode, uint32_t edges)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
view->tiled = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function sets up an interactive move or resize operation, where
|
* This function sets up an interactive move or resize operation, where
|
||||||
|
|
|
||||||
230
src/view.c
230
src/view.c
|
|
@ -10,6 +10,89 @@
|
||||||
|
|
||||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All view_apply_xxx_geometry() functions must *not* modify
|
||||||
|
* any state besides repositioning or resizing the view.
|
||||||
|
*
|
||||||
|
* They may be called repeatably during output layout changes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum view_edge {
|
||||||
|
VIEW_EDGE_INVALID = 0,
|
||||||
|
|
||||||
|
VIEW_EDGE_LEFT,
|
||||||
|
VIEW_EDGE_RIGHT,
|
||||||
|
VIEW_EDGE_UP,
|
||||||
|
VIEW_EDGE_DOWN,
|
||||||
|
VIEW_EDGE_CENTER,
|
||||||
|
};
|
||||||
|
|
||||||
|
static enum view_edge
|
||||||
|
view_edge_invert(enum view_edge edge)
|
||||||
|
{
|
||||||
|
switch (edge) {
|
||||||
|
case VIEW_EDGE_LEFT:
|
||||||
|
return VIEW_EDGE_RIGHT;
|
||||||
|
case VIEW_EDGE_RIGHT:
|
||||||
|
return VIEW_EDGE_LEFT;
|
||||||
|
case VIEW_EDGE_UP:
|
||||||
|
return VIEW_EDGE_DOWN;
|
||||||
|
case VIEW_EDGE_DOWN:
|
||||||
|
return VIEW_EDGE_UP;
|
||||||
|
case VIEW_EDGE_CENTER:
|
||||||
|
case VIEW_EDGE_INVALID:
|
||||||
|
default:
|
||||||
|
return VIEW_EDGE_INVALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct wlr_box
|
||||||
|
view_get_edge_snap_box(struct view *view, struct output *output,
|
||||||
|
enum view_edge edge)
|
||||||
|
{
|
||||||
|
struct wlr_box usable = output_usable_area_in_layout_coords(output);
|
||||||
|
if (usable.height == output->wlr_output->height
|
||||||
|
&& output->wlr_output->scale != 1) {
|
||||||
|
usable.height /= output->wlr_output->scale;
|
||||||
|
}
|
||||||
|
if (usable.width == output->wlr_output->width
|
||||||
|
&& output->wlr_output->scale != 1) {
|
||||||
|
usable.width /= output->wlr_output->scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
int x_offset = edge == VIEW_EDGE_RIGHT
|
||||||
|
? (usable.width + rc.gap) / 2 : rc.gap;
|
||||||
|
int y_offset = edge == VIEW_EDGE_DOWN
|
||||||
|
? (usable.height + rc.gap) / 2 : rc.gap;
|
||||||
|
|
||||||
|
int base_width, base_height;
|
||||||
|
switch (edge) {
|
||||||
|
case VIEW_EDGE_LEFT:
|
||||||
|
case VIEW_EDGE_RIGHT:
|
||||||
|
base_width = (usable.width - 3 * rc.gap) / 2;
|
||||||
|
base_height = usable.height - 2 * rc.gap;
|
||||||
|
break;
|
||||||
|
case VIEW_EDGE_UP:
|
||||||
|
case VIEW_EDGE_DOWN:
|
||||||
|
base_width = usable.width - 2 * rc.gap;
|
||||||
|
base_height = (usable.height - 3 * rc.gap) / 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
case VIEW_EDGE_CENTER:
|
||||||
|
base_width = usable.width - 2 * rc.gap;
|
||||||
|
base_height = usable.height - 2 * rc.gap;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
struct wlr_box dst = {
|
||||||
|
.x = x_offset + usable.x + view->margin.left,
|
||||||
|
.y = y_offset + usable.y + view->margin.top,
|
||||||
|
.width = base_width - view->margin.left - view->margin.right,
|
||||||
|
.height = base_height - view->margin.top - view->margin.bottom,
|
||||||
|
};
|
||||||
|
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
view_set_activated(struct view *view, bool activated)
|
view_set_activated(struct view *view, bool activated)
|
||||||
{
|
{
|
||||||
|
|
@ -185,6 +268,27 @@ view_center(struct view *view)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
view_apply_tiled_geometry(struct view *view, struct output *output)
|
||||||
|
{
|
||||||
|
assert(view->tiled);
|
||||||
|
if (!output) {
|
||||||
|
output = view_output(view);
|
||||||
|
}
|
||||||
|
if (!output) {
|
||||||
|
wlr_log(WLR_ERROR, "Can't tile: no output");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_box dst = view_get_edge_snap_box(view, output, view->tiled);
|
||||||
|
if (view->w == dst.width && view->h == dst.height) {
|
||||||
|
/* move horizontally/vertically without changing size */
|
||||||
|
view_move(view, dst.x, dst.y);
|
||||||
|
} else {
|
||||||
|
view_move_resize(view, dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
view_apply_fullscreen_geometry(struct view *view, struct wlr_output *wlr_output)
|
view_apply_fullscreen_geometry(struct view *view, struct wlr_output *wlr_output)
|
||||||
{
|
{
|
||||||
|
|
@ -515,35 +619,6 @@ view_move_to_edge(struct view *view, const char *direction)
|
||||||
view_move(view, x, y);
|
view_move(view, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum view_edge {
|
|
||||||
VIEW_EDGE_INVALID,
|
|
||||||
|
|
||||||
VIEW_EDGE_LEFT,
|
|
||||||
VIEW_EDGE_RIGHT,
|
|
||||||
VIEW_EDGE_UP,
|
|
||||||
VIEW_EDGE_DOWN,
|
|
||||||
VIEW_EDGE_CENTER,
|
|
||||||
};
|
|
||||||
|
|
||||||
static enum view_edge
|
|
||||||
view_edge_invert(enum view_edge edge)
|
|
||||||
{
|
|
||||||
switch (edge) {
|
|
||||||
case VIEW_EDGE_LEFT:
|
|
||||||
return VIEW_EDGE_RIGHT;
|
|
||||||
case VIEW_EDGE_RIGHT:
|
|
||||||
return VIEW_EDGE_LEFT;
|
|
||||||
case VIEW_EDGE_UP:
|
|
||||||
return VIEW_EDGE_DOWN;
|
|
||||||
case VIEW_EDGE_DOWN:
|
|
||||||
return VIEW_EDGE_UP;
|
|
||||||
case VIEW_EDGE_CENTER:
|
|
||||||
case VIEW_EDGE_INVALID:
|
|
||||||
default:
|
|
||||||
return VIEW_EDGE_INVALID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum view_edge
|
static enum view_edge
|
||||||
view_edge_parse(const char *direction)
|
view_edge_parse(const char *direction)
|
||||||
{
|
{
|
||||||
|
|
@ -565,53 +640,6 @@ view_edge_parse(const char *direction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wlr_box
|
|
||||||
view_get_edge_snap_box(struct view *view, struct output *output,
|
|
||||||
enum view_edge edge)
|
|
||||||
{
|
|
||||||
struct wlr_box usable = output_usable_area_in_layout_coords(output);
|
|
||||||
if (usable.height == output->wlr_output->height
|
|
||||||
&& output->wlr_output->scale != 1) {
|
|
||||||
usable.height /= output->wlr_output->scale;
|
|
||||||
}
|
|
||||||
if (usable.width == output->wlr_output->width
|
|
||||||
&& output->wlr_output->scale != 1) {
|
|
||||||
usable.width /= output->wlr_output->scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
int x_offset = edge == VIEW_EDGE_RIGHT
|
|
||||||
? (usable.width + rc.gap) / 2 : rc.gap;
|
|
||||||
int y_offset = edge == VIEW_EDGE_DOWN
|
|
||||||
? (usable.height + rc.gap) / 2 : rc.gap;
|
|
||||||
|
|
||||||
int base_width, base_height;
|
|
||||||
switch (edge) {
|
|
||||||
case VIEW_EDGE_LEFT:
|
|
||||||
case VIEW_EDGE_RIGHT:
|
|
||||||
base_width = (usable.width - 3 * rc.gap) / 2;
|
|
||||||
base_height = usable.height - 2 * rc.gap;
|
|
||||||
break;
|
|
||||||
case VIEW_EDGE_UP:
|
|
||||||
case VIEW_EDGE_DOWN:
|
|
||||||
base_width = usable.width - 2 * rc.gap;
|
|
||||||
base_height = (usable.height - 3 * rc.gap) / 2;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
case VIEW_EDGE_CENTER:
|
|
||||||
base_width = usable.width - 2 * rc.gap;
|
|
||||||
base_height = usable.height - 2 * rc.gap;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
struct wlr_box dst = {
|
|
||||||
.x = x_offset + usable.x + view->margin.left,
|
|
||||||
.y = y_offset + usable.y + view->margin.top,
|
|
||||||
.width = base_width - view->margin.left - view->margin.right,
|
|
||||||
.height = base_height - view->margin.top - view->margin.bottom,
|
|
||||||
};
|
|
||||||
|
|
||||||
return dst;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
view_snap_to_edge(struct view *view, const char *direction)
|
view_snap_to_edge(struct view *view, const char *direction)
|
||||||
{
|
{
|
||||||
|
|
@ -630,50 +658,44 @@ view_snap_to_edge(struct view *view, const char *direction)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_box dst = view_get_edge_snap_box(view, output, edge);
|
if (view->tiled == edge) {
|
||||||
|
/* We are already tiled for this edge and thus should switch outputs */
|
||||||
if (view->x == dst.x && view->y == dst.y && view->w == dst.width
|
struct wlr_output *new_output = NULL;
|
||||||
&& view->h == dst.height) {
|
struct wlr_output *current_output = output->wlr_output;
|
||||||
/* Move over to the next screen if this is already snapped. */
|
struct wlr_output_layout *layout = view->server->output_layout;
|
||||||
struct wlr_box usable =
|
|
||||||
output_usable_area_in_layout_coords(output);
|
|
||||||
switch (edge) {
|
switch (edge) {
|
||||||
case VIEW_EDGE_LEFT:
|
case VIEW_EDGE_LEFT:
|
||||||
dst.x -= (usable.width / 2) + 1;
|
new_output = wlr_output_layout_adjacent_output(
|
||||||
|
layout, WLR_DIRECTION_LEFT, current_output, 1, 0);
|
||||||
break;
|
break;
|
||||||
case VIEW_EDGE_RIGHT:
|
case VIEW_EDGE_RIGHT:
|
||||||
dst.x += (usable.width / 2) + 1;
|
new_output = wlr_output_layout_adjacent_output(
|
||||||
|
layout, WLR_DIRECTION_RIGHT, current_output, 1, 0);
|
||||||
break;
|
break;
|
||||||
case VIEW_EDGE_UP:
|
case VIEW_EDGE_UP:
|
||||||
dst.y -= (usable.height / 2) + 1;
|
new_output = wlr_output_layout_adjacent_output(
|
||||||
|
layout, WLR_DIRECTION_UP, current_output, 0, 1);
|
||||||
break;
|
break;
|
||||||
case VIEW_EDGE_DOWN:
|
case VIEW_EDGE_DOWN:
|
||||||
dst.y += (usable.height / 2) + 1;
|
new_output = wlr_output_layout_adjacent_output(
|
||||||
|
layout, WLR_DIRECTION_DOWN, current_output, 0, 1);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (new_output && new_output != current_output) {
|
||||||
struct wlr_output *new_wlr_output = wlr_output_layout_output_at(
|
/* Move to next output */
|
||||||
view->server->output_layout, dst.x, dst.y);
|
edge = view_edge_invert(edge);
|
||||||
struct output *new_output =
|
output = output_from_wlr_output(view->server, new_output);
|
||||||
output_from_wlr_output(view->server, new_wlr_output);
|
} else {
|
||||||
|
/* No more output to move to */
|
||||||
if (new_output == output || !new_output
|
|
||||||
|| edge == VIEW_EDGE_CENTER) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dst = view_get_edge_snap_box(view, new_output,
|
|
||||||
view_edge_invert(edge));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (view->w == dst.width && view->h == dst.height) {
|
/* TODO: store old geometry if !maximized && !fullscreen && !tiled */
|
||||||
/* move horizontally/vertically without changing size */
|
view->tiled = edge;
|
||||||
view_move(view, dst.x, dst.y);
|
view_apply_tiled_geometry(view, output);
|
||||||
} else {
|
|
||||||
view_move_resize(view, dst);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue