]> git.mdlowis.com Git - proto/labwc.git/commitdiff
xdg: add snapping.notifyClient option to control tiling events
authorAndrew J. Hesford <ajh@sideband.org>
Tue, 23 Jan 2024 03:11:53 +0000 (22:11 -0500)
committerAndrew J. Hesford <ajh@sideband.org>
Tue, 30 Jan 2024 12:30:07 +0000 (07:30 -0500)
docs/labwc-config.5.scd
docs/rc.xml.all
include/config/rcxml.h
include/view.h
src/config/rcxml.c
src/view.c
src/xdg.c

index 1e0a553ec83f4480b9de717eee3e56776e8dd2d6..1375181386108654b759f0deef011571b9d10ea7 100644 (file)
@@ -236,16 +236,44 @@ this is for compatibility with Openbox.
 
 ## WINDOW SNAPPING
 
-The following two options relate to triggering window actions when moving
-windows using the mouse.
+Windows may be "snapped" to an edge or user-defined region of an output when
+activated with SnapToEdge actions or, optionally, by dragging windows to the
+edges of an output. Edge snapping causes a window to occupy half of its output,
+extending outward from the snapped edge.
 
 *<snapping><range>*
-       The distance in pixels from the edge of an output for window Move
-       operations to trigger SnapToEdge. A range of 0 disables window snapping.
-       Default is 1.
+       If an interactive move ends with the cursor a maximum distance *range*,
+       (in pixels) from the edge of an output, the move will trigger a
+       SnapToEdge action for that edge. A *range* of 0 disables snapping via
+       interactive moves. Default is 1.
 
 *<snapping><topMaximize>* [yes|no]
-       Maximize window if Move operation ends on the top edge. Default is yes.
+       If *yes*, an interactive move that snaps a window to the top edge will
+       maximize the window. If *no*, snapping will behave as it does with other
+       edges, causing the window to occupy the top half of an output. Default
+       is yes.
+
+*<snapping><notifyClient>* [always|region|edge|never]
+       Snapping windows can trigger corresponding tiling events for native
+       Wayland clients. Clients may use these events to alter their rendering
+       based on knowledge that some edges of the view are confined to edges of
+       a snapping region or output. For example, rounded corners may become
+       square when tiled, or media players may letter-box or pillar-box video
+       rather than imposing rigid aspect ratios on windows that will violate
+       the constraints of window snapping.
+
+       - When *always* is specified, any window that is snapped to either an
+         output edge or a user-defined region will receive a tiling event.
+
+       - When *region* is specified, only windows snapped to a user-defined
+         region will receive an event.
+
+       - When *edge* is specified, only windows snapped to an output edge will
+         receive an event.
+
+       - When *never* is specified, tiling events will never be triggered.
+
+       The default is "always".
 
 ## REGIONS
 
index 7f59a1d35244b0e2684bc86098975791d5ce155d..423bcb749d020193c081eb98a0369907e48382dd 100644 (file)
     <raiseOnFocus>no</raiseOnFocus>
   </focus>
 
-  <!-- Set range to 0 to disable window snapping completely -->
   <snapping>
+    <!-- Set range to 0 to disable window snapping completely -->
     <range>1</range>
     <topMaximize>yes</topMaximize>
+    <notifyClient>always</notifyClient>
   </snapping>
 
   <!--
index 76094c99c370ad8472b24c21cb3766b5166e16a6..8e41700082314f45dff92d840ec2de5eefcd9cd8 100644 (file)
@@ -35,6 +35,14 @@ enum adaptive_sync_mode {
        LAB_ADAPTIVE_SYNC_FULLSCREEN,
 };
 
+enum tiling_events_mode {
+       LAB_TILING_EVENTS_NEVER = 0,
+       LAB_TILING_EVENTS_REGION = 1 << 0,
+       LAB_TILING_EVENTS_EDGE = 1 << 1,
+       LAB_TILING_EVENTS_ALWAYS =
+               (LAB_TILING_EVENTS_REGION | LAB_TILING_EVENTS_EDGE),
+};
+
 struct usable_area_override {
        struct border margin;
        char *output;
@@ -114,6 +122,7 @@ struct rcxml {
        /* window snapping */
        int snap_edge_range;
        bool snap_top_maximize;
+       enum tiling_events_mode snap_tiling_events_mode;
 
        enum resize_indicator_mode resize_indicator;
 
index a568945c5639798bc2ba1ad692dfcb0ae930458a..887a199a507470abc29bcfe3e960cb43939f133c 100644 (file)
@@ -94,7 +94,7 @@ struct view_impl {
        void (*map)(struct view *view);
        void (*set_activated)(struct view *view, bool activated);
        void (*set_fullscreen)(struct view *view, bool fullscreen);
-       void (*set_tiled)(struct view *view);
+       void (*notify_tiled)(struct view *view);
        /*
         * client_request is true if the client unmapped its own
         * surface; false if we are just minimizing the view. The two
index 9dd97ecb5dd741e3d31508726744f37c87f55c8c..768579d55d3cb3267ea14716c793cde1b70b5186 100644 (file)
@@ -835,6 +835,18 @@ entry(xmlNode *node, char *nodename, char *content)
                rc.snap_edge_range = atoi(content);
        } else if (!strcasecmp(nodename, "topMaximize.snapping")) {
                set_bool(content, &rc.snap_top_maximize);
+       } else if (!strcasecmp(nodename, "notifyClient.snapping")) {
+               if (!strcasecmp(content, "always")) {
+                       rc.snap_tiling_events_mode = LAB_TILING_EVENTS_ALWAYS;
+               } else if (!strcasecmp(content, "region")) {
+                       rc.snap_tiling_events_mode = LAB_TILING_EVENTS_REGION;
+               } else if (!strcasecmp(content, "edge")) {
+                       rc.snap_tiling_events_mode = LAB_TILING_EVENTS_EDGE;
+               } else if (!strcasecmp(content, "never")) {
+                       rc.snap_tiling_events_mode = LAB_TILING_EVENTS_NEVER;
+               } else {
+                       wlr_log(WLR_ERROR, "ignoring invalid value for notifyClient");
+               }
 
        /* <windowSwitcher show="" preview="" outlines="" /> */
        } else if (!strcasecmp(nodename, "show.windowSwitcher")) {
@@ -1092,6 +1104,7 @@ rcxml_init(void)
 
        rc.snap_edge_range = 1;
        rc.snap_top_maximize = true;
+       rc.snap_tiling_events_mode = LAB_TILING_EVENTS_ALWAYS;
 
        rc.window_switcher.show = true;
        rc.window_switcher.preview = true;
index 143798044567edb727299652e933be7cd23a2c95..180ae189d342ba2f17bbddcae6ba3b53211f1bf1 100644 (file)
@@ -1043,6 +1043,15 @@ view_is_floating(struct view *view)
                || view_is_tiled(view));
 }
 
+static void
+view_notify_tiled(struct view *view)
+{
+       assert(view);
+       if (view->impl->notify_tiled) {
+               view->impl->notify_tiled(view);
+       }
+}
+
 /* Reset tiled state of view without changing geometry */
 void
 view_set_untiled(struct view *view)
@@ -1051,10 +1060,7 @@ view_set_untiled(struct view *view)
        view->tiled = VIEW_EDGE_INVALID;
        view->tiled_region = NULL;
        zfree(view->tiled_region_evacuate);
-
-       if (view->impl->set_tiled) {
-               view->impl->set_tiled(view);
-       }
+       view_notify_tiled(view);
 }
 
 void
@@ -1775,11 +1781,7 @@ view_snap_to_edge(struct view *view, enum view_edge edge,
        view_set_untiled(view);
        view_set_output(view, output);
        view->tiled = edge;
-
-       if (view->impl->set_tiled) {
-               view->impl->set_tiled(view);
-       }
-
+       view_notify_tiled(view);
        view_apply_tiled_geometry(view);
 }
 
@@ -1813,11 +1815,7 @@ view_snap_to_region(struct view *view, struct region *region,
        }
        view_set_untiled(view);
        view->tiled_region = region;
-
-       if (view->impl->set_tiled) {
-               view->impl->set_tiled(view);
-       }
-
+       view_notify_tiled(view);
        view_apply_region_geometry(view);
 }
 
index c338ad83b5349c6f6ee04035f5a2f3d93ea463be..dc9acc91c89fcfb1a15f72ddfdd98d270b29d97f 100644 (file)
--- a/src/xdg.c
+++ b/src/xdg.c
@@ -424,32 +424,42 @@ xdg_toplevel_view_set_fullscreen(struct view *view, bool fullscreen)
 }
 
 static void
-xdg_toplevel_view_set_tiled(struct view *view)
+xdg_toplevel_view_notify_tiled(struct view *view)
 {
-       enum wlr_edges edge;
+       /* Take no action if xdg-shell tiling is disabled */
+       if (rc.snap_tiling_events_mode == LAB_TILING_EVENTS_NEVER) {
+               return;
+       }
+
+       enum wlr_edges edge = WLR_EDGE_NONE;
+
+       bool want_edge = rc.snap_tiling_events_mode & LAB_TILING_EVENTS_EDGE;
+       bool want_region = rc.snap_tiling_events_mode & LAB_TILING_EVENTS_REGION;
 
        /*
         * Edge-snapped view are considered tiled on the snapped edge and those
         * perpendicular to it.
         */
-       switch (view->tiled) {
-       case VIEW_EDGE_LEFT:
-               edge = WLR_EDGE_LEFT | WLR_EDGE_TOP | WLR_EDGE_BOTTOM;
-               break;
-       case VIEW_EDGE_RIGHT:
-               edge = WLR_EDGE_RIGHT | WLR_EDGE_TOP | WLR_EDGE_BOTTOM;
-               break;
-       case VIEW_EDGE_UP:
-               edge = WLR_EDGE_TOP | WLR_EDGE_LEFT | WLR_EDGE_RIGHT;
-               break;
-       case VIEW_EDGE_DOWN:
-               edge = WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT;
-               break;
-       default:
-               edge = WLR_EDGE_NONE;
+       if (want_edge) {
+               switch (view->tiled) {
+               case VIEW_EDGE_LEFT:
+                       edge = WLR_EDGE_LEFT | WLR_EDGE_TOP | WLR_EDGE_BOTTOM;
+                       break;
+               case VIEW_EDGE_RIGHT:
+                       edge = WLR_EDGE_RIGHT | WLR_EDGE_TOP | WLR_EDGE_BOTTOM;
+                       break;
+               case VIEW_EDGE_UP:
+                       edge = WLR_EDGE_TOP | WLR_EDGE_LEFT | WLR_EDGE_RIGHT;
+                       break;
+               case VIEW_EDGE_DOWN:
+                       edge = WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT;
+                       break;
+               default:
+                       edge = WLR_EDGE_NONE;
+               }
        }
 
-       if (view->tiled_region) {
+       if (want_region && view->tiled_region) {
                /* Region-snapped views are considered tiled on all edges */
                edge = WLR_EDGE_LEFT | WLR_EDGE_RIGHT |
                        WLR_EDGE_TOP | WLR_EDGE_BOTTOM;
@@ -629,7 +639,7 @@ static const struct view_impl xdg_toplevel_view_impl = {
        .map = xdg_toplevel_view_map,
        .set_activated = xdg_toplevel_view_set_activated,
        .set_fullscreen = xdg_toplevel_view_set_fullscreen,
-       .set_tiled = xdg_toplevel_view_set_tiled,
+       .notify_tiled = xdg_toplevel_view_notify_tiled,
        .unmap = xdg_toplevel_view_unmap,
        .maximize = xdg_toplevel_view_maximize,
        .minimize = xdg_toplevel_view_minimize,