]> git.mdlowis.com Git - proto/labwc.git/commitdiff
src/view.c: Convert SnapToEdge to use view_apply_xxx_geometry framework
authorConsolatis <35009135+Consolatis@users.noreply.github.com>
Fri, 1 Jul 2022 00:07:40 +0000 (02:07 +0200)
committerJohan Malm <johanmalm@users.noreply.github.com>
Sat, 2 Jul 2022 11:43:23 +0000 (12:43 +0100)
include/labwc.h
src/interactive.c
src/view.c

index be6a629dacfa5773c6ac93b8b842edf97d3e2473..7fc0e0a532ff23e9fc1459752ecc25f988a7e37b 100644 (file)
@@ -306,6 +306,7 @@ struct view {
        bool been_mapped;
        bool minimized;
        bool maximized;
+       uint32_t tiled;  /* private, enum view_edge in src/view.c */
        struct wlr_output *fullscreen;
 
        /* geometry of the wlr_surface contained within the view */
index 8ade121ada3f4c3a83cb8cb6dfbea051c34262aa..c7dab3dc900bd7c7f4819517bb311b48132fe090 100644 (file)
@@ -40,6 +40,7 @@ interactive_begin(struct view *view, enum input_mode mode, uint32_t edges)
                        return;
                }
        }
+       view->tiled = 0;
 
        /*
         * This function sets up an interactive move or resize operation, where
index e82dd6d387df74e1ecb30f8c5ed080fcebd1742d..8c3938fbdeadb8e142010a4bce32e5a8db3dcb00 100644 (file)
 
 #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
 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
 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);
 }
 
-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
 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
 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;
        }
 
-       struct wlr_box dst = view_get_edge_snap_box(view, output, edge);
-
-       if (view->x == dst.x && view->y == dst.y && view->w == dst.width
-                       && view->h == dst.height) {
-               /* Move over to the next screen if this is already snapped. */
-               struct wlr_box usable =
-                       output_usable_area_in_layout_coords(output);
+       if (view->tiled == edge) {
+               /* We are already tiled for this edge and thus should switch outputs */
+               struct wlr_output *new_output = NULL;
+               struct wlr_output *current_output = output->wlr_output;
+               struct wlr_output_layout *layout = view->server->output_layout;
                switch (edge) {
                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;
                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;
                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;
                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;
                default:
                        break;
                }
-
-               struct wlr_output *new_wlr_output = wlr_output_layout_output_at(
-                       view->server->output_layout, dst.x, dst.y);
-               struct output *new_output =
-                       output_from_wlr_output(view->server, new_wlr_output);
-
-               if (new_output == output || !new_output
-                               || edge == VIEW_EDGE_CENTER) {
+               if (new_output && new_output != current_output) {
+                       /* Move to next output */
+                       edge = view_edge_invert(edge);
+                       output = output_from_wlr_output(view->server, new_output);
+               } else {
+                       /* No more output to move to */
                        return;
                }
-
-               dst = view_get_edge_snap_box(view, new_output,
-                       view_edge_invert(edge));
        }
 
-       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);
-       }
+       /* TODO: store old geometry if !maximized && !fullscreen && !tiled */
+       view->tiled = edge;
+       view_apply_tiled_geometry(view, output);
 }
 
 const char *