SnapToRegion: Evacuate tiled views from destroying outputs

This commit is contained in:
Consolatis 2022-07-07 19:05:54 +02:00
parent 25cea94a32
commit 4edd67de17
5 changed files with 56 additions and 0 deletions

View file

@ -28,6 +28,7 @@ bool regions_available(void);
void regions_init(struct server *server, struct seat *seat); void regions_init(struct server *server, struct seat *seat);
void regions_update(struct output *output); void regions_update(struct output *output);
void regions_evacuate_output(struct output *output);
void regions_destroy(struct wl_list *regions); void regions_destroy(struct wl_list *regions);
struct region *regions_from_cursor(struct server *server); struct region *regions_from_cursor(struct server *server);

View file

@ -50,7 +50,12 @@ struct view {
bool minimized; bool minimized;
bool maximized; bool maximized;
uint32_t tiled; /* private, enum view_edge in src/view.c */ 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 */
struct region *tiled_region; struct region *tiled_region;
/* Set to region->name when tiled_region is free'd by a destroying output */
char *tiled_region_evacuate;
struct wlr_output *fullscreen; struct wlr_output *fullscreen;
/* geometry of the wlr_surface contained within the view */ /* geometry of the wlr_surface contained within the view */

View file

@ -41,6 +41,7 @@ static void
output_destroy_notify(struct wl_listener *listener, void *data) output_destroy_notify(struct wl_listener *listener, void *data)
{ {
struct output *output = wl_container_of(listener, output, destroy); struct output *output = wl_container_of(listener, output, destroy);
regions_evacuate_output(output);
regions_destroy(&output->regions); regions_destroy(&output->regions);
wl_list_remove(&output->link); wl_list_remove(&output->link);
wl_list_remove(&output->frame.link); wl_list_remove(&output->frame.link);
@ -307,6 +308,7 @@ output_config_apply(struct server *server,
} }
if (need_to_remove) { if (need_to_remove) {
regions_evacuate_output(output);
wlr_output_layout_remove(server->output_layout, o); wlr_output_layout_remove(server->output_layout, o);
output->scene_output = NULL; output->scene_output = NULL;
} }

View file

@ -156,6 +156,26 @@ regions_update(struct output *output)
} }
} }
void
regions_evacuate_output(struct output *output)
{
assert(output);
struct view *view;
struct region *region;
wl_list_for_each(view, &output->server->views, link) {
wl_list_for_each(region, &output->regions, link) {
if (view->tiled_region == region) {
if (!view->tiled_region_evacuate) {
view->tiled_region_evacuate =
xstrdup(region->name);
}
break;
}
}
}
}
void void
regions_destroy(struct wl_list *regions) regions_destroy(struct wl_list *regions)
{ {

View file

@ -2,6 +2,7 @@
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <strings.h> #include <strings.h>
#include "common/mem.h"
#include "common/scene-helpers.h" #include "common/scene-helpers.h"
#include "labwc.h" #include "labwc.h"
#include "menu/menu.h" #include "menu/menu.h"
@ -348,6 +349,29 @@ view_apply_region_geometry(struct view *view)
assert(view); assert(view);
assert(view->tiled_region); assert(view->tiled_region);
if (view->tiled_region_evacuate) {
/* View was evacuated from a destroying output */
struct output *output = view_output(view);
if (!output) {
wlr_log(WLR_INFO, "apply region geometry failed: no more ouputs");
return;
}
/* Get new output local region */
view->tiled_region = regions_from_name(
view->tiled_region_evacuate, output);
/* Get rid of the evacuate instruction */
zfree(view->tiled_region_evacuate);
if (!view->tiled_region) {
/* Existing region name doesn't exist in rc.xml anymore */
view_set_untiled(view);
view_apply_natural_geometry(view);
return;
}
}
/* Create a copy of the original region geometry */ /* Create a copy of the original region geometry */
struct wlr_box geo = view->tiled_region->geo; struct wlr_box geo = view->tiled_region->geo;
@ -980,6 +1004,10 @@ view_destroy(struct view *view)
seat_reset_pressed(&server->seat); seat_reset_pressed(&server->seat);
} }
if (view->tiled_region_evacuate) {
zfree(view->tiled_region_evacuate);
}
osd_on_view_destroy(view); osd_on_view_destroy(view);
undecorate(view); undecorate(view);