mirror of
https://github.com/labwc/labwc.git
synced 2026-02-05 04:06:33 -05: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',
|
||||
'debug.c',
|
||||
'desktop.c',
|
||||
'desktop-state.c',
|
||||
'dnd.c',
|
||||
'edges.c',
|
||||
'idle.c',
|
||||
|
|
|
|||
13
src/output.c
13
src/output.c
|
|
@ -26,6 +26,7 @@
|
|||
#include "common/mem.h"
|
||||
#include "common/scene-helpers.h"
|
||||
#include "config/rcxml.h"
|
||||
#include "desktop-state.h"
|
||||
#include "labwc.h"
|
||||
#include "layers.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);
|
||||
|
||||
/*
|
||||
* 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)) {
|
||||
wlr_output_configuration_v1_send_succeeded(config);
|
||||
} else {
|
||||
|
|
@ -803,6 +812,10 @@ handle_output_manager_apply(struct wl_listener *listener, void *data)
|
|||
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 */
|
||||
cursor_update_focus(server);
|
||||
cursor_update_image(&server->seat);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue