]> git.mdlowis.com Git - proto/labwc.git/commitdiff
SnapToRegion: Allow for live config updates
authorConsolatis <35009135+Consolatis@users.noreply.github.com>
Sun, 1 Jan 2023 17:12:20 +0000 (18:12 +0100)
committerConsolatis <35009135+Consolatis@users.noreply.github.com>
Wed, 11 Jan 2023 17:52:24 +0000 (18:52 +0100)
include/labwc.h
include/regions.h
include/view.h
src/interactive.c
src/output.c
src/regions.c
src/server.c
src/view.c

index 596bb0d71f261304aea649518fa5df5dd004d459..6a68514eb0007e030b0c398a37fc2d5060d6b02e 100644 (file)
@@ -315,7 +315,6 @@ struct output {
        struct wlr_box usable_area;
 
        struct wl_list regions;  /* struct region.link */
-       struct wlr_box regions_usable_area;
 
        struct lab_data_buffer *osd_buffer;
 
index 87806123831769c6f333bc7fc619bebd076c1232..e77cd3f0da068843363b3af17d2b4dd4a918ec33 100644 (file)
@@ -33,12 +33,43 @@ struct region_overlay {
 /* Can be used as a cheap check to detect if there are any regions configured */
 bool regions_available(void);
 
-void regions_update(struct output *output);
+/**
+ * regions_reconfigure*() - re-initializes all regions from struct rc.
+ *
+ * - all views are evacuated from the given output (or all of them)
+ * - all output local regions are destroyed
+ * - new output local regions are created from struct rc
+ * - the region geometry is re-calculated
+ */
+void regions_reconfigure(struct server *server);
+void regions_reconfigure_output(struct output *output);
+
+/* re-calculate the geometry based on usable area */
+void regions_update_geometry(struct output *output);
+
+/**
+ * Mark all views which are currently region-tiled to the given output as
+ * evacuated. This means that the view->tiled_region pointer is reset to
+ * NULL but view->tiled_region_evacuate is set to a copy of the region name.
+ *
+ * The next time desktop_arrange_all_views() causes a call to
+ * view_apply_region_geometry() it will try to find a new output and then
+ * search for a region with the same name. If found, view->tiled_region will
+ * be set to the new region and view->tiled_region_evacuate will be free'd.
+ *
+ * If no region with the old name is found (e.g. the user deleted or renamed
+ * the region in rc.xml and caused a Reconfigure) the view will be reset to
+ * non-tiled state and view->tiled_region_evacuate will be free'd.
+ */
 void regions_evacuate_output(struct output *output);
+
+/* Free all regions in given wl_list pointer */
 void regions_destroy(struct seat *seat, struct wl_list *regions);
 
+/* Get output local region from cursor or name, may be NULL */
 struct region *regions_from_cursor(struct server *server);
 struct region *regions_from_name(const char *region_name, struct output *output);
+
 void regions_show_overlay(struct view *view, struct seat *seat, struct region *region);
 void regions_hide_overlay(struct seat *seat);
 
index c04885cc92d8d7b8b78371ecb49052ecde6d6a14..8cf3859f7b25a616885e3b63517608229eac6541 100644 (file)
@@ -51,7 +51,7 @@ struct view {
        bool maximized;
        uint32_t tiled;  /* private, enum view_edge in src/view.c */
 
-       /* Pointer to an output owned struct region, may be NULL or already free'd */
+       /* Pointer to an output owned struct region, may be NULL */
        struct region *tiled_region;
        /* Set to region->name when tiled_region is free'd by a destroying output */
        char *tiled_region_evacuate;
@@ -132,6 +132,7 @@ void view_toggle_maximize(struct view *view);
 void view_toggle_decorations(struct view *view);
 void view_toggle_always_on_top(struct view *view);
 bool view_is_always_on_top(struct view *view);
+bool view_is_tiled(struct view *view);
 void view_move_to_workspace(struct view *view, struct workspace *workspace);
 void view_set_decorations(struct view *view, bool decorations);
 void view_toggle_fullscreen(struct view *view);
index f1007441f00d9d473195dd467fe587b17cecf38b..83731d52a8843b84e7172a6185ec6fd34f955bda 100644 (file)
@@ -45,7 +45,7 @@ interactive_begin(struct view *view, enum input_mode mode, uint32_t edges)
                         */
                        return;
                }
-               if (view->maximized || view->tiled || view->tiled_region) {
+               if (view->maximized || view_is_tiled(view)) {
                        /*
                         * Un-maximize and restore natural width/height.
                         * Don't reset tiled state yet since we may want
index fa258ba9f05bc5dc1b2aaaf138fa6bdedacc4fc8..991a165337e1a92f3efc93b4fd49a02794118c66 100644 (file)
@@ -212,6 +212,9 @@ new_output_notify(struct wl_listener *listener, void *data)
        output->scene_output = wlr_scene_get_scene_output(server->scene, wlr_output);
        assert(output->scene_output);
 
+       /* Create regions from config */
+       regions_reconfigure_output(output);
+
        server->pending_output_layout_change--;
        do_output_layout_change(server);
 }
@@ -452,7 +455,7 @@ void
 output_update_usable_area(struct output *output)
 {
        if (update_usable_area(output)) {
-               regions_update(output);
+               regions_update_geometry(output);
                desktop_arrange_all_views(output->server);
        }
 }
@@ -466,9 +469,9 @@ output_update_all_usable_areas(struct server *server, bool layout_changed)
        wl_list_for_each(output, &server->outputs, link) {
                if (update_usable_area(output)) {
                        usable_area_changed = true;
-                       regions_update(output);
+                       regions_update_geometry(output);
                } else if (layout_changed) {
-                       regions_update(output);
+                       regions_update_geometry(output);
                }
        }
        if (usable_area_changed || layout_changed) {
index 727a78c30a216c69c8c5b3268e5002b26c713b02..7ca2d9d234547d3e520b784944ac9e99cdf45cb2 100644 (file)
@@ -149,29 +149,51 @@ regions_hide_overlay(struct seat *seat)
 }
 
 void
-regions_update(struct output *output)
+regions_reconfigure_output(struct output *output)
 {
        assert(output);
 
-       struct region *region;
-       struct wlr_box usable = output_usable_area_in_layout_coords(output);
+       /* Evacuate views and destroy current regions */
+       if (!wl_list_empty(&output->regions)) {
+               regions_evacuate_output(output);
+               regions_destroy(&output->server->seat, &output->regions);
+       }
 
-       /* Initialize regions */
-       if (wl_list_empty(&output->regions)) {
-               wl_list_for_each(region, &rc.regions, link) {
-                       struct region *region_new = znew(*region_new);
-                       /* Create a copy */
-                       region_new->name = xstrdup(region->name);
-                       region_new->percentage = region->percentage;
-                       wl_list_append(&output->regions, &region_new->link);
-               }
+       /* Initialize regions from config */
+       struct region *region;
+       wl_list_for_each(region, &rc.regions, link) {
+               struct region *region_new = znew(*region_new);
+               /* Create a copy */
+               region_new->name = xstrdup(region->name);
+               region_new->percentage = region->percentage;
+               wl_list_append(&output->regions, &region_new->link);
        }
 
-       if (wlr_box_equal(&output->regions_usable_area, &usable)) {
-               /* Nothing changed */
-               return;
+       /* Update region geometries */
+       regions_update_geometry(output);
+}
+
+void
+regions_reconfigure(struct server *server)
+{
+       struct output *output;
+
+       /* Evacuate views and initialize regions from config */
+       wl_list_for_each(output, &server->outputs, link) {
+               regions_reconfigure_output(output);
        }
-       output->regions_usable_area = usable;
+
+       /* Tries to match the evacuated views to the new regions */
+       desktop_arrange_all_views(server);
+}
+
+void
+regions_update_geometry(struct output *output)
+{
+       assert(output);
+
+       struct region *region;
+       struct wlr_box usable = output_usable_area_in_layout_coords(output);
 
        /* Update regions */
        struct wlr_box *perc, *geo;
@@ -201,6 +223,8 @@ regions_evacuate_output(struct output *output)
                                        view->tiled_region_evacuate =
                                                xstrdup(region->name);
                                }
+                               /* Prevent carrying around a dangling pointer */
+                               view->tiled_region = NULL;
                                break;
                        }
                }
index e36c2880a8e735d1bdc05320a3d75d10bb1ec397..d8a816dfc6f60871f723a5685ec51d42fe390840 100644 (file)
@@ -20,6 +20,7 @@
 #include "labwc.h"
 #include "layers.h"
 #include "menu/menu.h"
+#include "regions.h"
 #include "theme.h"
 #include "view.h"
 #include "workspaces.h"
@@ -49,6 +50,7 @@ reload_config_and_theme(void)
 
        menu_reconfigure(g_server);
        seat_reconfigure(g_server);
+       regions_reconfigure(g_server);
 }
 
 static int
index 0208ec5888b02a79aa76f1daa0efdf7a896e477a..0e620b2a6b474303f4da1ad4f243971d9af5cffc 100644 (file)
@@ -295,7 +295,7 @@ void
 view_store_natural_geometry(struct view *view)
 {
        assert(view);
-       if (view->maximized || view->tiled || view->tiled_region) {
+       if (view->maximized || view_is_tiled(view)) {
                /* Do not overwrite the stored geometry with special cases */
                return;
        }
@@ -347,7 +347,7 @@ static void
 view_apply_region_geometry(struct view *view)
 {
        assert(view);
-       assert(view->tiled_region);
+       assert(view->tiled_region || view->tiled_region_evacuate);
 
        if (view->tiled_region_evacuate) {
                /* View was evacuated from a destroying output */
@@ -357,7 +357,7 @@ view_apply_region_geometry(struct view *view)
                        return;
                }
 
-               /* Get new output local region */
+               /* Get new output local region, may be NULL */
                view->tiled_region = regions_from_name(
                        view->tiled_region_evacuate, output);
 
@@ -500,7 +500,7 @@ view_apply_special_geometry(struct view *view)
                view_apply_maximized_geometry(view);
        } else if (view->tiled) {
                view_apply_tiled_geometry(view, NULL);
-       } else if (view->tiled_region) {
+       } else if (view->tiled_region || view->tiled_region_evacuate) {
                view_apply_region_geometry(view);
        } else {
                return false;
@@ -538,6 +538,15 @@ view_restore_to(struct view *view, struct wlr_box geometry)
        view_move_resize(view, geometry);
 }
 
+bool
+view_is_tiled(struct view *view)
+{
+       if (!view) {
+               return false;
+       }
+       return view->tiled || view->tiled_region || view->tiled_region_evacuate;
+}
+
 /* Reset tiled state of view without changing geometry */
 void
 view_set_untiled(struct view *view)
@@ -545,6 +554,7 @@ view_set_untiled(struct view *view)
        assert(view);
        view->tiled = VIEW_EDGE_INVALID;
        view->tiled_region = NULL;
+       zfree(view->tiled_region_evacuate);
 }
 
 void