]> git.mdlowis.com Git - proto/labwc.git/commitdiff
config: support <margin top="" bottom="" left="" right="" output="" />
authorJohan Malm <jgm323@gmail.com>
Tue, 6 Jun 2023 18:52:57 +0000 (19:52 +0100)
committerJohan Malm <johanmalm@users.noreply.github.com>
Mon, 26 Jun 2023 05:04:07 +0000 (06:04 +0100)
docs/labwc-config.5.scd
docs/rc.xml.all
include/config/rcxml.h
src/config/rcxml.c
src/layers.c

index 0c447fc2ec5a2c56d7d92790bba14e758ea6431c..e3bfe5c2746aa15054d5cbe7cdb1b7c3333e00f1 100644 (file)
@@ -239,6 +239,12 @@ Therefore, where multiple objects of the same kind are required (for example
 *<theme><font place=""><weight>*
        Font weight (normal or bold). Default is normal.
 
+## MARGIN
+
+*<margin top="" bottom="" left="" right="" output="" />*
+       Specify the number of pixels to reserve at the edges of an output.
+       New, maximized and tiled windows will not be placed in these areas.
+
 ## KEYBOARD
 
 *<keyboard><keybind key="">*
index aff736aa9401f63bb2c87748b0d01dfd6800e392..20f92a3143e2aaa519089c25d3f26af471e2dad6 100644 (file)
     </names>
   </desktops>
 
+  <!--
+    # <margin> can be used to reserve space where new/maximized/tiled
+    # windows will not be placed. Clients using layer-shell protocol reserve
+    # space automatically, so <margin> is only intended for other, specialist
+    # cases.
+    #
+    # If output is left empty, the margin will be applied to all outputs.
+
+    <margin top="" bottom="" left="" right="" output="" />
+  -->
+
   <!-- Percent based regions based on output usable area, % char is required -->
   <!--
     <regions>
index d7ae5eb8323a2a4f67c277cbb588293f37e65397..88a2ee0f94446b694a183350227fab3161fd656f 100644 (file)
@@ -6,6 +6,7 @@
 #include <stdio.h>
 #include <wayland-server-core.h>
 
+#include "common/border.h"
 #include "common/buf.h"
 #include "common/font.h"
 #include "config/libinput.h"
@@ -18,6 +19,12 @@ enum window_switcher_field_content {
        LAB_FIELD_TITLE,
 };
 
+struct usable_area_override {
+       struct border margin;
+       char *output;
+       struct wl_list link; /* struct rcxml.usable_area_overrides */
+};
+
 struct window_switcher_field {
        enum window_switcher_field_content content;
        int width;
@@ -47,6 +54,9 @@ struct rcxml {
        /* Pointer to current theme */
        struct theme *theme;
 
+       /* <margin top="" bottom="" left="" right="" output="" /> */
+       struct wl_list usable_area_overrides;
+
        /* keyboard */
        int repeat_rate;
        int repeat_delay;
index 2073ebf5f4e5e608313349f1c3d5c984ea8fc278..633b26bd6bac80645d8dec86d40caffe6a343dbd 100644 (file)
 #include "workspaces.h"
 
 static bool in_regions;
+static bool in_usable_area_override;
 static bool in_keybind;
 static bool in_mousebind;
 static bool in_libinput_category;
 static bool in_window_switcher_field;
 static bool in_window_rules;
 
+static struct usable_area_override *current_usable_area_override;
 static struct keybind *current_keybind;
 static struct mousebind *current_mousebind;
 static struct libinput_category *current_libinput_category;
@@ -60,6 +62,36 @@ enum font_place {
 static void load_default_key_bindings(void);
 static void load_default_mouse_bindings(void);
 
+static void
+fill_usable_area_override(char *nodename, char *content)
+{
+       if (!strcasecmp(nodename, "margin")) {
+               current_usable_area_override = znew(*current_usable_area_override);
+               wl_list_append(&rc.usable_area_overrides, &current_usable_area_override->link);
+               return;
+       }
+       string_truncate_at_pattern(nodename, ".margin");
+       if (!content) {
+               /* nop */
+       } else if (!current_usable_area_override) {
+               wlr_log(WLR_ERROR, "no usable-area-override object");
+       } else if (!strcmp(nodename, "output")) {
+               free(current_usable_area_override->output);
+               current_usable_area_override->output = xstrdup(content);
+       } else if (!strcmp(nodename, "left")) {
+               current_usable_area_override->margin.left = atoi(content);
+       } else if (!strcmp(nodename, "right")) {
+               current_usable_area_override->margin.right = atoi(content);
+       } else if (!strcmp(nodename, "top")) {
+               current_usable_area_override->margin.top = atoi(content);
+       } else if (!strcmp(nodename, "bottom")) {
+               current_usable_area_override->margin.bottom = atoi(content);
+       } else {
+               wlr_log(WLR_ERROR, "Unexpected data usable-area-override parser: %s=\"%s\"",
+                       nodename, content);
+       }
+}
+
 /* Does a boolean-parse but also allows 'default' */
 static void
 set_property(const char *str, enum property *variable)
@@ -478,6 +510,9 @@ entry(xmlNode *node, char *nodename, char *content)
                printf("%s: %s\n", nodename, content);
        }
 
+       if (in_usable_area_override) {
+               fill_usable_area_override(nodename, content);
+       }
        if (in_keybind) {
                fill_keybind(nodename, content);
        }
@@ -564,6 +599,7 @@ entry(xmlNode *node, char *nodename, char *content)
        } else if (!strcasecmp(nodename, "name.context.mouse")) {
                current_mouse_context = content;
                current_mousebind = NULL;
+
        } else if (!strcasecmp(nodename, "repeatRate.keyboard")) {
                rc.repeat_rate = atoi(content);
        } else if (!strcasecmp(nodename, "repeatDelay.keyboard")) {
@@ -656,6 +692,12 @@ xml_tree_walk(xmlNode *node)
                if (!strcasecmp((char *)n->name, "comment")) {
                        continue;
                }
+               if (!strcasecmp((char *)n->name, "margin")) {
+                       in_usable_area_override = true;
+                       traverse(n);
+                       in_usable_area_override = false;
+                       continue;
+               }
                if (!strcasecmp((char *)n->name, "keybind")) {
                        in_keybind = true;
                        traverse(n);
@@ -724,6 +766,7 @@ rcxml_init(void)
        static bool has_run;
 
        if (!has_run) {
+               wl_list_init(&rc.usable_area_overrides);
                wl_list_init(&rc.keybinds);
                wl_list_init(&rc.mousebinds);
                wl_list_init(&rc.libinput_categories);
@@ -1185,6 +1228,13 @@ rcxml_finish(void)
        zfree(rc.font_osd.name);
        zfree(rc.theme_name);
 
+       struct usable_area_override *area, *area_tmp;
+       wl_list_for_each_safe(area, area_tmp, &rc.usable_area_overrides, link) {
+               wl_list_remove(&area->link);
+               zfree(area->output);
+               zfree(area);
+       }
+
        struct keybind *k, *k_tmp;
        wl_list_for_each_safe(k, k_tmp, &rc.keybinds, link) {
                wl_list_remove(&k->link);
@@ -1228,6 +1278,7 @@ rcxml_finish(void)
        }
 
        /* Reset state vars for starting fresh when Reload is triggered */
+       current_usable_area_override = NULL;
        current_keybind = NULL;
        current_mousebind = NULL;
        current_libinput_category = NULL;
index bd0b0e17db2597dd26cba04f143e063634639a11..2d750f22b840d79a5f9c67712c65c21890510a2f 100644 (file)
 #include <stdbool.h>
 #include <stdlib.h>
 #include <string.h>
+#include <strings.h>
 #include <wayland-server.h>
 #include <wlr/types/wlr_layer_shell_v1.h>
 #include <wlr/util/log.h>
 #include "common/list.h"
 #include "common/mem.h"
+#include "config/rcxml.h"
 #include "layers.h"
 #include "labwc.h"
 #include "node.h"
 
+static void
+apply_override(struct output *output, struct wlr_box *usable_area)
+{
+       struct usable_area_override *override;
+       wl_list_for_each(override, &rc.usable_area_overrides, link) {
+               if (override->output && strcasecmp(override->output, output->wlr_output->name)) {
+                       continue;
+               }
+               usable_area->x += override->margin.left;
+               usable_area->y += override->margin.top;
+               usable_area->width -= override->margin.left + override->margin.right;
+               usable_area->height -= override->margin.top + override->margin.bottom;
+       }
+}
+
 static void
 arrange_one_layer(struct output *output, const struct wlr_box *full_area,
                struct wlr_box *usable_area, struct wlr_scene_tree *tree,
@@ -49,6 +66,8 @@ layers_arrange(struct output *output)
                &full_area.width, &full_area.height);
        struct wlr_box usable_area = full_area;
 
+       apply_override(output, &usable_area);
+
        struct server *server = output->server;
        struct wlr_scene_output *scene_output =
                wlr_scene_get_scene_output(server->scene, output->wlr_output);