struct wlr_box usable_area;
struct wl_list regions; /* struct region.link */
- struct wlr_box regions_usable_area;
struct lab_data_buffer *osd_buffer;
/* 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);
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;
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);
*/
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
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);
}
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);
}
}
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) {
}
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, ®ion_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, ®ion_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;
view->tiled_region_evacuate =
xstrdup(region->name);
}
+ /* Prevent carrying around a dangling pointer */
+ view->tiled_region = NULL;
break;
}
}
#include "labwc.h"
#include "layers.h"
#include "menu/menu.h"
+#include "regions.h"
#include "theme.h"
#include "view.h"
#include "workspaces.h"
menu_reconfigure(g_server);
seat_reconfigure(g_server);
+ regions_reconfigure(g_server);
}
static int
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;
}
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 */
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);
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;
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)
assert(view);
view->tiled = VIEW_EDGE_INVALID;
view->tiled_region = NULL;
+ zfree(view->tiled_region_evacuate);
}
void