mirror of
https://github.com/labwc/labwc.git
synced 2026-03-11 05:33:49 -04:00
parent
8ced055cb9
commit
e4dca57c96
4 changed files with 150 additions and 0 deletions
31
include/desktop-state.h
Normal file
31
include/desktop-state.h
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
#ifndef LABWC_DESKTOP_STATE_H
|
||||||
|
#define LABWC_DESKTOP_STATE_H
|
||||||
|
#include <wayland-util.h>
|
||||||
|
|
||||||
|
struct server;
|
||||||
|
struct output;
|
||||||
|
|
||||||
|
struct desktop_output {
|
||||||
|
struct output *output;
|
||||||
|
double scale;
|
||||||
|
struct wl_array views;
|
||||||
|
struct wl_list link;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Helpers to remember windows and scales for each output */
|
||||||
|
void desktop_state_create(struct server *server, struct wl_list *desktop_outputs);
|
||||||
|
void desktop_state_destroy(struct wl_list *desktop_outputs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* desktop_state_adjust_on_output_scale_change() - adjust views on scale change
|
||||||
|
* @server: server
|
||||||
|
* @desktop_outputs: object list containing scale and array of views
|
||||||
|
*
|
||||||
|
* Put windows back on the pre-scale-change output and also adjust position/size
|
||||||
|
* to fit the usable area.
|
||||||
|
*/
|
||||||
|
void desktop_state_adjust_on_output_scale_change(struct server *server,
|
||||||
|
struct wl_list *desktop_outputs);
|
||||||
|
|
||||||
|
#endif /* LABWC_DESKTOP_STATE_H */
|
||||||
105
src/desktop-state.c
Normal file
105
src/desktop-state.c
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
#define _POSIX_C_SOURCE 200809L
|
||||||
|
#include "desktop-state.h"
|
||||||
|
#include <assert.h>
|
||||||
|
#include <wlr/types/wlr_output.h>
|
||||||
|
#include <wlr/util/log.h>
|
||||||
|
#include "common/array.h"
|
||||||
|
#include "common/border.h"
|
||||||
|
#include "common/mem.h"
|
||||||
|
#include "labwc.h"
|
||||||
|
#include "output.h"
|
||||||
|
#include "ssd.h"
|
||||||
|
#include "view.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
desktop_state_create(struct server *server, struct wl_list *desktop_outputs)
|
||||||
|
{
|
||||||
|
struct output *output;
|
||||||
|
wl_list_for_each(output, &server->outputs, link) {
|
||||||
|
struct desktop_output *desktop_output = znew(*desktop_output);
|
||||||
|
desktop_output->output = output;
|
||||||
|
desktop_output->scale = output->wlr_output->scale;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* On output scale change, windows can move from one output to
|
||||||
|
* another, so we have to remember where they were.
|
||||||
|
*/
|
||||||
|
struct view *view;
|
||||||
|
wl_array_init(&desktop_output->views);
|
||||||
|
wl_list_for_each(view, &server->views, link) {
|
||||||
|
if (view->output == output) {
|
||||||
|
array_add(&desktop_output->views, view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_list_insert(desktop_outputs, &desktop_output->link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void desktop_state_destroy(struct wl_list *desktop_outputs)
|
||||||
|
{
|
||||||
|
struct desktop_output *desktop_output, *next;
|
||||||
|
wl_list_for_each_safe(desktop_output, next, desktop_outputs, link) {
|
||||||
|
wl_list_remove(&desktop_output->link);
|
||||||
|
wl_array_release(&desktop_output->views);
|
||||||
|
zfree(desktop_output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
get_scale(double *scale, struct output *output, struct wl_list *desktop_outputs)
|
||||||
|
{
|
||||||
|
struct desktop_output *desktop_output;
|
||||||
|
wl_list_for_each(desktop_output, desktop_outputs, link) {
|
||||||
|
if (desktop_output->output == output) {
|
||||||
|
*scale = desktop_output->scale;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(false && "output list mismatch");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fit_window_within_usable_area(struct view *view)
|
||||||
|
{
|
||||||
|
struct wlr_box usable = output_usable_area_in_layout_coords(view->output);
|
||||||
|
struct border margin = ssd_get_margin(view->ssd);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is quite a simple approach.
|
||||||
|
*
|
||||||
|
* We prioritise keeping windows big because with a scale increase, it
|
||||||
|
* is likely that users will want that. As such, we first move the
|
||||||
|
* window to the top/left corner and then shrink it to the usable area
|
||||||
|
* if needed.
|
||||||
|
*/
|
||||||
|
view_move(view, usable.x + margin.left, usable.y + margin.top);
|
||||||
|
view_constrain_size_to_that_of_usable_area(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
desktop_state_adjust_on_output_scale_change(struct server *server,
|
||||||
|
struct wl_list *desktop_outputs)
|
||||||
|
{
|
||||||
|
struct desktop_output *desktop_output;
|
||||||
|
wl_list_for_each(desktop_output, desktop_outputs, link) {
|
||||||
|
struct view **view;
|
||||||
|
wl_array_for_each(view, &desktop_output->views) {
|
||||||
|
struct output *output = desktop_output->output;
|
||||||
|
double old_scale = 0.0;
|
||||||
|
if (!get_scale(&old_scale, output, desktop_outputs)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* Put window back on the pre-scale-change output */
|
||||||
|
if ((*view)->output != output) {
|
||||||
|
view_set_output(*view, output);
|
||||||
|
}
|
||||||
|
/* Adjust window position and size */
|
||||||
|
if (old_scale != (*view)->output->wlr_output->scale) {
|
||||||
|
fit_window_within_usable_area(*view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,7 @@ labwc_sources = files(
|
||||||
'buffer.c',
|
'buffer.c',
|
||||||
'debug.c',
|
'debug.c',
|
||||||
'desktop.c',
|
'desktop.c',
|
||||||
|
'desktop-state.c',
|
||||||
'dnd.c',
|
'dnd.c',
|
||||||
'edges.c',
|
'edges.c',
|
||||||
'idle.c',
|
'idle.c',
|
||||||
|
|
|
||||||
13
src/output.c
13
src/output.c
|
|
@ -26,6 +26,7 @@
|
||||||
#include "common/mem.h"
|
#include "common/mem.h"
|
||||||
#include "common/scene-helpers.h"
|
#include "common/scene-helpers.h"
|
||||||
#include "config/rcxml.h"
|
#include "config/rcxml.h"
|
||||||
|
#include "desktop-state.h"
|
||||||
#include "labwc.h"
|
#include "labwc.h"
|
||||||
#include "layers.h"
|
#include "layers.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
|
|
@ -791,6 +792,14 @@ handle_output_manager_apply(struct wl_listener *listener, void *data)
|
||||||
|
|
||||||
bool config_is_good = verify_output_config_v1(config);
|
bool config_is_good = verify_output_config_v1(config);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save old desktop state, specifically windows and scales for each
|
||||||
|
* output, so that window positions and sizes can be adjusted later.
|
||||||
|
*/
|
||||||
|
struct wl_list desktop_outputs;
|
||||||
|
wl_list_init(&desktop_outputs);
|
||||||
|
desktop_state_create(server, &desktop_outputs);
|
||||||
|
|
||||||
if (config_is_good && output_config_apply(server, config)) {
|
if (config_is_good && output_config_apply(server, config)) {
|
||||||
wlr_output_configuration_v1_send_succeeded(config);
|
wlr_output_configuration_v1_send_succeeded(config);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -803,6 +812,10 @@ handle_output_manager_apply(struct wl_listener *listener, void *data)
|
||||||
output->wlr_output->scale);
|
output->wlr_output->scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Adjust windows if output scale(s) changed */
|
||||||
|
desktop_state_adjust_on_output_scale_change(server, &desktop_outputs);
|
||||||
|
desktop_state_destroy(&desktop_outputs);
|
||||||
|
|
||||||
/* Re-set cursor image in case scale changed */
|
/* Re-set cursor image in case scale changed */
|
||||||
cursor_update_focus(server);
|
cursor_update_focus(server);
|
||||||
cursor_update_image(&server->seat);
|
cursor_update_image(&server->seat);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue