mirror of
https://github.com/labwc/labwc.git
synced 2026-04-10 08:21:07 -04:00
Merge branch 'master' into master
This commit is contained in:
commit
6003c62c1f
20 changed files with 446 additions and 249 deletions
|
|
@ -2,19 +2,23 @@
|
|||
#ifndef __LABWC_ACTION_H
|
||||
#define __LABWC_ACTION_H
|
||||
|
||||
struct server;
|
||||
struct view;
|
||||
struct server;
|
||||
struct wl_list;
|
||||
|
||||
struct action {
|
||||
uint32_t type;
|
||||
char *arg;
|
||||
struct wl_list link;
|
||||
struct wl_list link; /* struct keybinding.actions,
|
||||
* struct mousebinding.actions,
|
||||
* struct menuitem.actions */
|
||||
|
||||
uint32_t type; /* enum action_type */
|
||||
struct wl_list args; /* struct action_arg.link */
|
||||
};
|
||||
|
||||
struct action *action_create(const char *action_name);
|
||||
void action_list_free(struct wl_list *action_list);
|
||||
|
||||
void action_arg_add_str(struct action *action, char *key, const char *value);
|
||||
void actions_run(struct view *activator, struct server *server,
|
||||
struct wl_list *actions, uint32_t resize_edges);
|
||||
void action_list_free(struct wl_list *action_list);
|
||||
|
||||
#endif
|
||||
#endif /* __LABWC_ACTION_H */
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ struct keybind {
|
|||
uint32_t modifiers;
|
||||
xkb_keysym_t *keysyms;
|
||||
size_t keysyms_len;
|
||||
struct wl_list actions;
|
||||
struct wl_list link;
|
||||
struct wl_list actions; /* struct action.link */
|
||||
struct wl_list link; /* struct rcxml.keybinds */
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -26,9 +26,9 @@ struct mousebind {
|
|||
|
||||
/* ex: doubleclick, press, drag */
|
||||
enum mouse_event mouse_event;
|
||||
struct wl_list actions;
|
||||
struct wl_list actions; /* struct action.link */
|
||||
|
||||
struct wl_list link; /* rcxml::mousebinds */
|
||||
struct wl_list link; /* struct rcxml.mousebinds */
|
||||
bool pressed_in_context; /* used in click events */
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -37,11 +37,11 @@ struct rcxml {
|
|||
/* keyboard */
|
||||
int repeat_rate;
|
||||
int repeat_delay;
|
||||
struct wl_list keybinds;
|
||||
struct wl_list keybinds; /* struct keybind.link */
|
||||
|
||||
/* mouse */
|
||||
long doubleclick_time; /* in ms */
|
||||
struct wl_list mousebinds;
|
||||
long doubleclick_time; /* in ms */
|
||||
struct wl_list mousebinds; /* struct mousebind.link */
|
||||
|
||||
/* libinput */
|
||||
struct wl_list libinput_categories;
|
||||
|
|
|
|||
|
|
@ -306,13 +306,14 @@ struct view {
|
|||
bool been_mapped;
|
||||
bool minimized;
|
||||
bool maximized;
|
||||
uint32_t tiled; /* private, enum view_edge in src/view.c */
|
||||
struct wlr_output *fullscreen;
|
||||
|
||||
/* geometry of the wlr_surface contained within the view */
|
||||
int x, y, w, h;
|
||||
|
||||
/* geometry before maximize */
|
||||
struct wlr_box unmaximized_geometry;
|
||||
/* user defined geometry before maximize / tiling / fullscreen */
|
||||
struct wlr_box natural_geometry;
|
||||
|
||||
/*
|
||||
* margin refers to the space between the extremities of the
|
||||
|
|
@ -364,6 +365,7 @@ struct view {
|
|||
struct xwayland_unmanaged {
|
||||
struct server *server;
|
||||
struct wlr_xwayland_surface *xwayland_surface;
|
||||
struct wlr_scene_node *node;
|
||||
struct wl_list link;
|
||||
int lx, ly;
|
||||
|
||||
|
|
@ -460,6 +462,7 @@ void foreign_toplevel_handle_create(struct view *view);
|
|||
void desktop_move_to_front(struct view *view);
|
||||
void desktop_move_to_back(struct view *view);
|
||||
void desktop_focus_and_activate_view(struct seat *seat, struct view *view);
|
||||
void desktop_arrange_all_views(struct server *server);
|
||||
|
||||
enum lab_cycle_dir {
|
||||
LAB_CYCLE_DIR_NONE,
|
||||
|
|
|
|||
24
include/private/action.h
Normal file
24
include/private/action.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
#ifndef __LABWC_PRIVATE_ACTION_H
|
||||
#define __LABWC_PRIVATE_ACTION_H
|
||||
|
||||
/* Don't include ourself as search path starts at current directory */
|
||||
#include "../action.h"
|
||||
|
||||
enum action_arg_type {
|
||||
LAB_ACTION_ARG_STR = 0,
|
||||
};
|
||||
|
||||
struct action_arg {
|
||||
struct wl_list link; /* struct action.args */
|
||||
|
||||
const char *key; /* May be NULL if there is just one arg */
|
||||
enum action_arg_type type;
|
||||
};
|
||||
|
||||
struct action_arg_str {
|
||||
struct action_arg base;
|
||||
char *value;
|
||||
};
|
||||
|
||||
#endif /* __LABWC_PRIVATE_ACTION_H */
|
||||
|
|
@ -134,8 +134,10 @@ struct ssd_hover_state {
|
|||
|
||||
/* Public SSD API */
|
||||
void ssd_create(struct view *view);
|
||||
|
||||
void ssd_hide(struct view *view);
|
||||
void ssd_set_active(struct view *view, bool activated);
|
||||
|
||||
void ssd_update_title(struct view *view);
|
||||
void ssd_update_geometry(struct view *view);
|
||||
void ssd_reload(struct view *view);
|
||||
|
|
|
|||
117
src/action.c
117
src/action.c
|
|
@ -1,6 +1,8 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#include <assert.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <wlr/util/log.h>
|
||||
|
|
@ -9,8 +11,8 @@
|
|||
#include "debug.h"
|
||||
#include "labwc.h"
|
||||
#include "menu/menu.h"
|
||||
#include "private/action.h"
|
||||
#include "ssd.h"
|
||||
#include "action.h"
|
||||
#include "workspaces.h"
|
||||
|
||||
enum action_type {
|
||||
|
|
@ -64,6 +66,24 @@ const char *action_names[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static char *
|
||||
action_str_from_arg(struct action_arg *arg)
|
||||
{
|
||||
assert(arg->type == LAB_ACTION_ARG_STR);
|
||||
return ((struct action_arg_str *)arg)->value;
|
||||
}
|
||||
|
||||
static struct action_arg *
|
||||
action_get_first_arg(struct action *action)
|
||||
{
|
||||
struct action_arg *arg;
|
||||
struct wl_list *item = action->args.next;
|
||||
if (item == &action->args) {
|
||||
return NULL;
|
||||
}
|
||||
return wl_container_of(item, arg, link);
|
||||
}
|
||||
|
||||
static enum action_type
|
||||
action_type_from_str(const char *action_name)
|
||||
{
|
||||
|
|
@ -85,15 +105,26 @@ action_create(const char *action_name)
|
|||
}
|
||||
struct action *action = calloc(1, sizeof(struct action));
|
||||
action->type = action_type_from_str(action_name);
|
||||
wl_list_init(&action->args);
|
||||
return action;
|
||||
}
|
||||
|
||||
void action_list_free(struct wl_list *action_list)
|
||||
{
|
||||
struct action_arg *arg, *arg_tmp;
|
||||
struct action *action, *action_tmp;
|
||||
/* Free actions */
|
||||
wl_list_for_each_safe(action, action_tmp, action_list, link) {
|
||||
wl_list_remove(&action->link);
|
||||
zfree(action->arg);
|
||||
/* Free args */
|
||||
wl_list_for_each_safe(arg, arg_tmp, &action->args, link) {
|
||||
wl_list_remove(&arg->link);
|
||||
zfree(arg->key);
|
||||
if (arg->type == LAB_ACTION_ARG_STR) {
|
||||
free(action_str_from_arg(arg));
|
||||
}
|
||||
zfree(arg);
|
||||
}
|
||||
zfree(action);
|
||||
}
|
||||
}
|
||||
|
|
@ -151,9 +182,13 @@ actions_run(struct view *activator, struct server *server,
|
|||
|
||||
struct view *view;
|
||||
struct action *action;
|
||||
struct action_arg *arg;
|
||||
wl_list_for_each(action, actions, link) {
|
||||
wlr_log(WLR_DEBUG, "Handling action %s (%u) with arg %s",
|
||||
action_names[action->type], action->type, action->arg);
|
||||
wlr_log(WLR_DEBUG, "Handling action %s (%u)",
|
||||
action_names[action->type], action->type);
|
||||
|
||||
/* Get arg now so we don't have to repeat every time we only need one */
|
||||
arg = action_get_first_arg(action);
|
||||
|
||||
/*
|
||||
* Refetch view because it may have been changed due to the
|
||||
|
|
@ -171,28 +206,30 @@ actions_run(struct view *activator, struct server *server,
|
|||
debug_dump_scene(server);
|
||||
break;
|
||||
case ACTION_TYPE_EXECUTE:
|
||||
{
|
||||
struct buf cmd;
|
||||
buf_init(&cmd);
|
||||
buf_add(&cmd, action->arg);
|
||||
buf_expand_shell_variables(&cmd);
|
||||
spawn_async_no_shell(cmd.buf);
|
||||
free(cmd.buf);
|
||||
if (!arg) {
|
||||
wlr_log(WLR_ERROR, "Missing argument for Execute");
|
||||
break;
|
||||
}
|
||||
struct buf cmd;
|
||||
buf_init(&cmd);
|
||||
buf_add(&cmd, action_str_from_arg(arg));
|
||||
buf_expand_shell_variables(&cmd);
|
||||
spawn_async_no_shell(cmd.buf);
|
||||
free(cmd.buf);
|
||||
break;
|
||||
case ACTION_TYPE_EXIT:
|
||||
wl_display_terminate(server->wl_display);
|
||||
break;
|
||||
case ACTION_TYPE_MOVE_TO_EDGE:
|
||||
if (action->arg) {
|
||||
view_move_to_edge(view, action->arg);
|
||||
if (arg) {
|
||||
view_move_to_edge(view, action_str_from_arg(arg));
|
||||
} else {
|
||||
wlr_log(WLR_ERROR, "Missing argument for MoveToEdge");
|
||||
}
|
||||
break;
|
||||
case ACTION_TYPE_SNAP_TO_EDGE:
|
||||
if (action->arg) {
|
||||
view_snap_to_edge(view, action->arg);
|
||||
if (arg) {
|
||||
view_snap_to_edge(view, action_str_from_arg(arg));
|
||||
} else {
|
||||
wlr_log(WLR_ERROR, "Missing argument for SnapToEdge");
|
||||
}
|
||||
|
|
@ -211,7 +248,11 @@ actions_run(struct view *activator, struct server *server,
|
|||
kill(getpid(), SIGHUP);
|
||||
break;
|
||||
case ACTION_TYPE_SHOW_MENU:
|
||||
show_menu(server, view, action->arg);
|
||||
if (arg) {
|
||||
show_menu(server, view, action_str_from_arg(arg));
|
||||
} else {
|
||||
wlr_log(WLR_ERROR, "Missing argument for ShowMenu");
|
||||
}
|
||||
break;
|
||||
case ACTION_TYPE_TOGGLE_MAXIMIZE:
|
||||
if (view) {
|
||||
|
|
@ -263,27 +304,33 @@ actions_run(struct view *activator, struct server *server,
|
|||
}
|
||||
break;
|
||||
case ACTION_TYPE_GO_TO_DESKTOP:
|
||||
{
|
||||
struct workspace *target;
|
||||
target = workspaces_find(server->workspace_current, action->arg);
|
||||
if (target) {
|
||||
workspaces_switch_to(target);
|
||||
}
|
||||
if (!arg) {
|
||||
wlr_log(WLR_ERROR, "Missing argument for GoToDesktop");
|
||||
break;
|
||||
}
|
||||
struct workspace *target;
|
||||
char *target_name = action_str_from_arg(arg);
|
||||
target = workspaces_find(server->workspace_current, target_name);
|
||||
if (target) {
|
||||
workspaces_switch_to(target);
|
||||
}
|
||||
break;
|
||||
case ACTION_TYPE_SEND_TO_DESKTOP:
|
||||
if (!arg) {
|
||||
wlr_log(WLR_ERROR, "Missing argument for SendToDesktop");
|
||||
break;
|
||||
}
|
||||
if (view) {
|
||||
struct workspace *target;
|
||||
target = workspaces_find(view->workspace, action->arg);
|
||||
char *target_name = action_str_from_arg(arg);
|
||||
target = workspaces_find(view->workspace, target_name);
|
||||
if (target) {
|
||||
workspaces_send_to(view, target);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ACTION_TYPE_NONE:
|
||||
wlr_log(WLR_ERROR,
|
||||
"Not executing unknown action with arg %s",
|
||||
action->arg);
|
||||
wlr_log(WLR_ERROR, "Not executing unknown action");
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
|
|
@ -292,9 +339,21 @@ actions_run(struct view *activator, struct server *server,
|
|||
* adding a new action without installing a handler here.
|
||||
*/
|
||||
wlr_log(WLR_ERROR,
|
||||
"Not executing invalid action (%u) with arg %s"
|
||||
" This is a BUG. Please report.",
|
||||
action->type, action->arg);
|
||||
"Not executing invalid action (%u)"
|
||||
" This is a BUG. Please report.", action->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
action_arg_add_str(struct action *action, char *key, const char *value)
|
||||
{
|
||||
assert(value && "Tried to add NULL action string argument");
|
||||
struct action_arg_str *arg = calloc(1, sizeof(*arg));
|
||||
arg->base.type = LAB_ACTION_ARG_STR;
|
||||
if (key) {
|
||||
arg->base.key = strdup(key);
|
||||
}
|
||||
arg->value = strdup(value);
|
||||
wl_list_insert(action->args.prev, &arg->base.link);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,21 +71,18 @@ fill_keybind(char *nodename, char *content)
|
|||
} else if (!current_keybind_action) {
|
||||
wlr_log(WLR_ERROR, "expect <action name=\"\"> element first. "
|
||||
"nodename: '%s' content: '%s'", nodename, content);
|
||||
} else if (current_keybind_action->arg) {
|
||||
wlr_log(WLR_ERROR, "Action argument already set: %s",
|
||||
current_keybind_action->arg);
|
||||
} else if (!strcmp(nodename, "command.action")) {
|
||||
/* Execute */
|
||||
current_keybind_action->arg = strdup(content);
|
||||
action_arg_add_str(current_keybind_action, NULL, content);
|
||||
} else if (!strcmp(nodename, "direction.action")) {
|
||||
/* MoveToEdge, SnapToEdge */
|
||||
current_keybind_action->arg = strdup(content);
|
||||
action_arg_add_str(current_keybind_action, NULL, content);
|
||||
} else if (!strcmp(nodename, "menu.action")) {
|
||||
/* ShowMenu */
|
||||
current_keybind_action->arg = strdup(content);
|
||||
action_arg_add_str(current_keybind_action, NULL, content);
|
||||
} else if (!strcmp(nodename, "to.action")) {
|
||||
/* GoToDesktop, SendToDesktop */
|
||||
current_keybind_action->arg = strdup(content);
|
||||
action_arg_add_str(current_keybind_action, NULL, content);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -134,15 +131,12 @@ fill_mousebind(char *nodename, char *content)
|
|||
} else if (!current_mousebind_action) {
|
||||
wlr_log(WLR_ERROR, "expect <action name=\"\"> element first. "
|
||||
"nodename: '%s' content: '%s'", nodename, content);
|
||||
} else if (current_mousebind_action->arg) {
|
||||
wlr_log(WLR_ERROR, "Action argument already set: %s",
|
||||
current_mousebind_action->arg);
|
||||
} else if (!strcmp(nodename, "command.action")) {
|
||||
current_mousebind_action->arg = strdup(content);
|
||||
action_arg_add_str(current_mousebind_action, NULL, content);
|
||||
} else if (!strcmp(nodename, "direction.action")) {
|
||||
current_mousebind_action->arg = strdup(content);
|
||||
action_arg_add_str(current_mousebind_action, NULL, content);
|
||||
} else if (!strcmp(nodename, "menu.action")) {
|
||||
current_mousebind_action->arg = strdup(content);
|
||||
action_arg_add_str(current_mousebind_action, NULL, content);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -544,7 +538,7 @@ load_default_key_bindings(void)
|
|||
wl_list_insert(k->actions.prev, &action->link);
|
||||
|
||||
if (key_combos[i].command) {
|
||||
action->arg = strdup(key_combos[i].command);
|
||||
action_arg_add_str(action, NULL, key_combos[i].command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -604,7 +598,7 @@ load_default_mouse_bindings(void)
|
|||
wl_list_insert(m->actions.prev, &action->link);
|
||||
|
||||
if (mouse_combos[i].command) {
|
||||
action->arg = strdup(mouse_combos[i].command);
|
||||
action_arg_add_str(action, NULL, mouse_combos[i].command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,6 +99,16 @@ deactivate_all_views(struct server *server)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
desktop_arrange_all_views(struct server *server)
|
||||
{
|
||||
/* Adjust window positions/sizes */
|
||||
struct view *view;
|
||||
wl_list_for_each(view, &server->views, link) {
|
||||
view_adjust_for_layout_change(view);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
desktop_focus_and_activate_view(struct seat *seat, struct view *view)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -17,30 +17,51 @@ max_move_scale(double pos_cursor, double pos_current,
|
|||
void
|
||||
interactive_begin(struct view *view, enum input_mode mode, uint32_t edges)
|
||||
{
|
||||
if (view->maximized) {
|
||||
if (mode == LAB_INPUT_STATE_MOVE && view->fullscreen) {
|
||||
/**
|
||||
* We don't allow moving fullscreen windows.
|
||||
*
|
||||
* If you think there is a good reason to allow it
|
||||
* feel free to open an issue explaining your use-case.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
if (mode == LAB_INPUT_STATE_RESIZE
|
||||
&& (view->fullscreen || view->maximized)) {
|
||||
/* We don't allow resizing while in maximized or fullscreen state */
|
||||
return;
|
||||
}
|
||||
if (view->maximized || view->tiled) {
|
||||
if (mode == LAB_INPUT_STATE_MOVE) {
|
||||
/* Exit maximized or tiled mode */
|
||||
int new_x = max_move_scale(view->server->seat.cursor->x,
|
||||
view->x, view->w, view->unmaximized_geometry.width);
|
||||
view->x, view->w, view->natural_geometry.width);
|
||||
int new_y = max_move_scale(view->server->seat.cursor->y,
|
||||
view->y, view->h, view->unmaximized_geometry.height);
|
||||
view->unmaximized_geometry.x = new_x;
|
||||
view->unmaximized_geometry.y = new_y;
|
||||
view_maximize(view, false);
|
||||
/*
|
||||
* view_maximize() indirectly calls view->impl->configure
|
||||
* which is async but we are using the current values in
|
||||
* server->grab_box. We pretend the configure already
|
||||
* happened by setting them manually.
|
||||
view->y, view->h, view->natural_geometry.height);
|
||||
view->natural_geometry.x = new_x;
|
||||
view->natural_geometry.y = new_y;
|
||||
if (view->maximized) {
|
||||
view_maximize(view, false);
|
||||
}
|
||||
if (view->tiled) {
|
||||
view_move_resize(view, view->natural_geometry);
|
||||
}
|
||||
/**
|
||||
* view_maximize() / view_move_resize() indirectly calls
|
||||
* view->impl->configure which is async but we are using
|
||||
* the current values in server->grab_box. We pretend the
|
||||
* configure already happened by setting them manually.
|
||||
*/
|
||||
view->x = new_x;
|
||||
view->y = new_y;
|
||||
view->w = view->unmaximized_geometry.width;
|
||||
view->h = view->unmaximized_geometry.height;
|
||||
} else {
|
||||
return;
|
||||
view->w = view->natural_geometry.width;
|
||||
view->h = view->natural_geometry.height;
|
||||
}
|
||||
}
|
||||
|
||||
/* Moving or resizing always resets tiled state */
|
||||
view->tiled = 0;
|
||||
|
||||
/*
|
||||
* This function sets up an interactive move or resize operation, where
|
||||
* the compositor stops propagating pointer events to clients and
|
||||
|
|
@ -101,9 +122,9 @@ interactive_end(struct view *view)
|
|||
* When unmaximizing later on restore
|
||||
* original position
|
||||
*/
|
||||
view->unmaximized_geometry.x =
|
||||
view->natural_geometry.x =
|
||||
view->server->grab_box.x;
|
||||
view->unmaximized_geometry.y =
|
||||
view->natural_geometry.y =
|
||||
view->server->grab_box.y;
|
||||
} else {
|
||||
view_snap_to_edge(view, "up");
|
||||
|
|
|
|||
32
src/layers.c
32
src/layers.c
|
|
@ -25,6 +25,7 @@ layers_arrange(struct output *output)
|
|||
wlr_output_effective_resolution(output->wlr_output,
|
||||
&full_area.width, &full_area.height);
|
||||
struct wlr_box usable_area = full_area;
|
||||
struct wlr_box old_usable_area = output->usable_area;
|
||||
|
||||
struct server *server = output->server;
|
||||
struct wlr_scene_output *scene_output =
|
||||
|
|
@ -37,11 +38,29 @@ layers_arrange(struct output *output)
|
|||
int nr_layers = sizeof(output->layers) / sizeof(output->layers[0]);
|
||||
for (int i = 0; i < nr_layers; i++) {
|
||||
struct lab_layer_surface *lab_layer_surface;
|
||||
|
||||
/*
|
||||
* First we go over the list of surfaces that have
|
||||
* exclusive_zone set (e.g. statusbars) because we have to
|
||||
* determine the usable area before processing regular layouts.
|
||||
*/
|
||||
wl_list_for_each(lab_layer_surface, &output->layers[i], link) {
|
||||
struct wlr_scene_layer_surface_v1 *scene_layer_surface =
|
||||
lab_layer_surface->scene_layer_surface;
|
||||
wlr_scene_layer_surface_v1_configure(
|
||||
scene_layer_surface, &full_area, &usable_area);
|
||||
if (scene_layer_surface->layer_surface->current.exclusive_zone) {
|
||||
wlr_scene_layer_surface_v1_configure(
|
||||
scene_layer_surface, &full_area, &usable_area);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we process regular layouts */
|
||||
wl_list_for_each(lab_layer_surface, &output->layers[i], link) {
|
||||
struct wlr_scene_layer_surface_v1 *scene_layer_surface =
|
||||
lab_layer_surface->scene_layer_surface;
|
||||
if (!scene_layer_surface->layer_surface->current.exclusive_zone) {
|
||||
wlr_scene_layer_surface_v1_configure(
|
||||
scene_layer_surface, &full_area, &usable_area);
|
||||
}
|
||||
}
|
||||
|
||||
wlr_scene_node_set_position(&output->layer_tree[i]->node,
|
||||
|
|
@ -80,7 +99,12 @@ layers_arrange(struct output *output)
|
|||
!seat->focused_layer->current.keyboard_interactive) {
|
||||
seat_set_focus_layer(seat, NULL);
|
||||
}
|
||||
/* FIXME: should we call a desktop_arrange_all_views() here? */
|
||||
|
||||
/* Finally re-arrange all views based on usable_area */
|
||||
if (old_usable_area.width != output->usable_area.width
|
||||
|| old_usable_area.height != output->usable_area.height) {
|
||||
desktop_arrange_all_views(server);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -350,7 +374,7 @@ new_layer_surface_notify(struct wl_listener *listener, void *data)
|
|||
return;
|
||||
}
|
||||
|
||||
wl_list_insert(&output->layers[layer_surface->pending.layer],
|
||||
wl_list_insert(output->layers[layer_surface->pending.layer].prev,
|
||||
&surface->link);
|
||||
/*
|
||||
* Temporarily set the layer's current state to pending so that
|
||||
|
|
|
|||
|
|
@ -238,16 +238,16 @@ fill_item(char *nodename, char *content)
|
|||
wlr_log(WLR_ERROR, "expect <action name=\"\"> element first. "
|
||||
"nodename: '%s' content: '%s'", nodename, content);
|
||||
} else if (!strcmp(nodename, "command.action")) {
|
||||
current_item_action->arg = strdup(content);
|
||||
action_arg_add_str(current_item_action, NULL, content);
|
||||
} else if (!strcmp(nodename, "execute.action")) {
|
||||
/*
|
||||
* <action name="Execute"><execute>foo</execute></action>
|
||||
* is deprecated, but we support it anyway for backward
|
||||
* compatibility with old openbox-menu generators
|
||||
*/
|
||||
current_item_action->arg = strdup(content);
|
||||
action_arg_add_str(current_item_action, NULL, content);
|
||||
} else if (!strcmp(nodename, "to.action")) {
|
||||
current_item_action->arg = strdup(content);
|
||||
action_arg_add_str(current_item_action, NULL, content);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -209,10 +209,7 @@ static void
|
|||
output_update_for_layout_change(struct server *server)
|
||||
{
|
||||
/* Adjust window positions/sizes */
|
||||
struct view *view;
|
||||
wl_list_for_each(view, &server->views, link) {
|
||||
view_adjust_for_layout_change(view);
|
||||
}
|
||||
desktop_arrange_all_views(server);
|
||||
|
||||
/*
|
||||
* "Move" each wlr_output_cursor (in per-output coordinates) to
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ reload_config_and_theme(void)
|
|||
if (!view->mapped || !view->ssd.enabled) {
|
||||
continue;
|
||||
}
|
||||
view->margin = ssd_thickness(view);
|
||||
ssd_reload(view);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,10 @@
|
|||
struct border
|
||||
ssd_thickness(struct view *view)
|
||||
{
|
||||
if (!view->ssd.enabled) {
|
||||
struct border border = { 0 };
|
||||
return border;
|
||||
}
|
||||
struct theme *theme = view->server->theme;
|
||||
struct border border = {
|
||||
.top = theme->title_height + theme->border_width,
|
||||
|
|
@ -159,6 +163,7 @@ ssd_create(struct view *view)
|
|||
ssd_extents_create(view);
|
||||
ssd_border_create(view);
|
||||
ssd_titlebar_create(view);
|
||||
view->margin = ssd_thickness(view);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -171,10 +176,12 @@ ssd_update_geometry(struct view *view)
|
|||
if (!view->ssd.enabled) {
|
||||
if (view->ssd.tree->node.enabled) {
|
||||
wlr_scene_node_set_enabled(&view->ssd.tree->node, false);
|
||||
view->margin = ssd_thickness(view);
|
||||
}
|
||||
return;
|
||||
} else if (!view->ssd.tree->node.enabled) {
|
||||
wlr_scene_node_set_enabled(&view->ssd.tree->node, true);
|
||||
view->margin = ssd_thickness(view);
|
||||
}
|
||||
|
||||
int width = view->w;
|
||||
|
|
@ -198,15 +205,6 @@ ssd_update_geometry(struct view *view)
|
|||
view->ssd.state.y = view->y;
|
||||
}
|
||||
|
||||
void
|
||||
ssd_hide(struct view *view)
|
||||
{
|
||||
if (!view->ssd.tree) {
|
||||
return;
|
||||
}
|
||||
wlr_scene_node_set_enabled(&view->ssd.tree->node, false);
|
||||
}
|
||||
|
||||
void ssd_reload(struct view *view)
|
||||
{
|
||||
if (!view->ssd.tree) {
|
||||
|
|
|
|||
331
src/view.c
331
src/view.c
|
|
@ -8,8 +8,93 @@
|
|||
#include "menu/menu.h"
|
||||
#include "workspaces.h"
|
||||
|
||||
#define LAB_FALLBACK_WIDTH 640
|
||||
#define LAB_FALLBACK_HEIGHT 480
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
/**
|
||||
* All view_apply_xxx_geometry() functions must *not* modify
|
||||
* any state besides repositioning or resizing the view.
|
||||
*
|
||||
* They may be called repeatably during output layout changes.
|
||||
*/
|
||||
|
||||
enum view_edge {
|
||||
VIEW_EDGE_INVALID = 0,
|
||||
|
||||
VIEW_EDGE_LEFT,
|
||||
VIEW_EDGE_RIGHT,
|
||||
VIEW_EDGE_UP,
|
||||
VIEW_EDGE_DOWN,
|
||||
VIEW_EDGE_CENTER,
|
||||
};
|
||||
|
||||
static enum view_edge
|
||||
view_edge_invert(enum view_edge edge)
|
||||
{
|
||||
switch (edge) {
|
||||
case VIEW_EDGE_LEFT:
|
||||
return VIEW_EDGE_RIGHT;
|
||||
case VIEW_EDGE_RIGHT:
|
||||
return VIEW_EDGE_LEFT;
|
||||
case VIEW_EDGE_UP:
|
||||
return VIEW_EDGE_DOWN;
|
||||
case VIEW_EDGE_DOWN:
|
||||
return VIEW_EDGE_UP;
|
||||
case VIEW_EDGE_CENTER:
|
||||
case VIEW_EDGE_INVALID:
|
||||
default:
|
||||
return VIEW_EDGE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
static struct wlr_box
|
||||
view_get_edge_snap_box(struct view *view, struct output *output,
|
||||
enum view_edge edge)
|
||||
{
|
||||
struct wlr_box usable = output_usable_area_in_layout_coords(output);
|
||||
if (usable.height == output->wlr_output->height
|
||||
&& output->wlr_output->scale != 1) {
|
||||
usable.height /= output->wlr_output->scale;
|
||||
}
|
||||
if (usable.width == output->wlr_output->width
|
||||
&& output->wlr_output->scale != 1) {
|
||||
usable.width /= output->wlr_output->scale;
|
||||
}
|
||||
|
||||
int x_offset = edge == VIEW_EDGE_RIGHT
|
||||
? (usable.width + rc.gap) / 2 : rc.gap;
|
||||
int y_offset = edge == VIEW_EDGE_DOWN
|
||||
? (usable.height + rc.gap) / 2 : rc.gap;
|
||||
|
||||
int base_width, base_height;
|
||||
switch (edge) {
|
||||
case VIEW_EDGE_LEFT:
|
||||
case VIEW_EDGE_RIGHT:
|
||||
base_width = (usable.width - 3 * rc.gap) / 2;
|
||||
base_height = usable.height - 2 * rc.gap;
|
||||
break;
|
||||
case VIEW_EDGE_UP:
|
||||
case VIEW_EDGE_DOWN:
|
||||
base_width = usable.width - 2 * rc.gap;
|
||||
base_height = (usable.height - 3 * rc.gap) / 2;
|
||||
break;
|
||||
default:
|
||||
case VIEW_EDGE_CENTER:
|
||||
base_width = usable.width - 2 * rc.gap;
|
||||
base_height = usable.height - 2 * rc.gap;
|
||||
break;
|
||||
}
|
||||
struct wlr_box dst = {
|
||||
.x = x_offset + usable.x + view->margin.left,
|
||||
.y = y_offset + usable.y + view->margin.top,
|
||||
.width = base_width - view->margin.left - view->margin.right,
|
||||
.height = base_height - view->margin.top - view->margin.bottom,
|
||||
};
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
void
|
||||
view_set_activated(struct view *view, bool activated)
|
||||
{
|
||||
|
|
@ -176,6 +261,38 @@ view_compute_centered_position(struct view *view, int w, int h, int *x, int *y)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
set_fallback_geometry(struct view *view)
|
||||
{
|
||||
view->natural_geometry.width = LAB_FALLBACK_WIDTH;
|
||||
view->natural_geometry.height = LAB_FALLBACK_HEIGHT;
|
||||
view_compute_centered_position(view,
|
||||
view->natural_geometry.width,
|
||||
view->natural_geometry.height,
|
||||
&view->natural_geometry.x,
|
||||
&view->natural_geometry.y);
|
||||
}
|
||||
#undef LAB_FALLBACK_WIDTH
|
||||
#undef LAB_FALLBACK_HEIGHT
|
||||
|
||||
static void
|
||||
view_store_natural_geometry(struct view *view)
|
||||
{
|
||||
/**
|
||||
* If an application was started maximized or fullscreened, its
|
||||
* natural_geometry width/height may still be zero in which case we set
|
||||
* some fallback values. This is the case with foot and Qt applications.
|
||||
*/
|
||||
if (!view->w || !view->h) {
|
||||
set_fallback_geometry(view);
|
||||
} else {
|
||||
view->natural_geometry.x = view->x;
|
||||
view->natural_geometry.y = view->y;
|
||||
view->natural_geometry.width = view->w;
|
||||
view->natural_geometry.height = view->h;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
view_center(struct view *view)
|
||||
{
|
||||
|
|
@ -185,6 +302,27 @@ view_center(struct view *view)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
view_apply_tiled_geometry(struct view *view, struct output *output)
|
||||
{
|
||||
assert(view->tiled);
|
||||
if (!output) {
|
||||
output = view_output(view);
|
||||
}
|
||||
if (!output) {
|
||||
wlr_log(WLR_ERROR, "Can't tile: no output");
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_box dst = view_get_edge_snap_box(view, output, view->tiled);
|
||||
if (view->w == dst.width && view->h == dst.height) {
|
||||
/* move horizontally/vertically without changing size */
|
||||
view_move(view, dst.x, dst.y);
|
||||
} else {
|
||||
view_move_resize(view, dst);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
view_apply_fullscreen_geometry(struct view *view, struct wlr_output *wlr_output)
|
||||
{
|
||||
|
|
@ -234,41 +372,17 @@ view_apply_maximized_geometry(struct view *view)
|
|||
view_move_resize(view, box);
|
||||
}
|
||||
|
||||
#define LAB_FALLBACK_WIDTH (640)
|
||||
#define LAB_FALLBACK_HEIGHT (480)
|
||||
|
||||
static void
|
||||
set_fallback_geometry(struct view *view)
|
||||
{
|
||||
view->unmaximized_geometry.width = LAB_FALLBACK_WIDTH;
|
||||
view->unmaximized_geometry.height = LAB_FALLBACK_HEIGHT;
|
||||
view_compute_centered_position(view,
|
||||
view->unmaximized_geometry.width,
|
||||
view->unmaximized_geometry.height,
|
||||
&view->unmaximized_geometry.x,
|
||||
&view->unmaximized_geometry.y);
|
||||
}
|
||||
|
||||
static void
|
||||
view_apply_unmaximized_geometry(struct view *view)
|
||||
{
|
||||
/*
|
||||
* If an application was started maximized, its unmaximized_geometry
|
||||
* width/height may still be zero in which case we set some fallback
|
||||
* values. This is the case with foot and Qt applications.
|
||||
*/
|
||||
if (wlr_box_empty(&view->unmaximized_geometry)) {
|
||||
set_fallback_geometry(view);
|
||||
}
|
||||
|
||||
struct wlr_output_layout *layout = view->server->output_layout;
|
||||
if (wlr_output_layout_intersects(layout, NULL,
|
||||
&view->unmaximized_geometry)) {
|
||||
&view->natural_geometry)) {
|
||||
/* restore to original geometry */
|
||||
view_move_resize(view, view->unmaximized_geometry);
|
||||
view_move_resize(view, view->natural_geometry);
|
||||
} else {
|
||||
/* reposition if original geometry is offscreen */
|
||||
struct wlr_box box = view->unmaximized_geometry;
|
||||
struct wlr_box box = view->natural_geometry;
|
||||
if (view_compute_centered_position(view, box.width, box.height,
|
||||
&box.x, &box.y)) {
|
||||
view_move_resize(view, box);
|
||||
|
|
@ -294,16 +408,18 @@ view_maximize(struct view *view, bool maximize)
|
|||
}
|
||||
if (maximize) {
|
||||
interactive_end(view);
|
||||
view->unmaximized_geometry.x = view->x;
|
||||
view->unmaximized_geometry.y = view->y;
|
||||
view->unmaximized_geometry.width = view->w;
|
||||
view->unmaximized_geometry.height = view->h;
|
||||
|
||||
if (!view->tiled) {
|
||||
view_store_natural_geometry(view);
|
||||
}
|
||||
view_apply_maximized_geometry(view);
|
||||
view->maximized = true;
|
||||
} else {
|
||||
/* unmaximize */
|
||||
view_apply_unmaximized_geometry(view);
|
||||
if (view->tiled) {
|
||||
view_apply_tiled_geometry(view, NULL);
|
||||
} else {
|
||||
view_apply_unmaximized_geometry(view);
|
||||
}
|
||||
view->maximized = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -322,6 +438,8 @@ view_toggle_decorations(struct view *view)
|
|||
ssd_update_geometry(view);
|
||||
if (view->maximized) {
|
||||
view_apply_maximized_geometry(view);
|
||||
} else if (view->tiled) {
|
||||
view_apply_tiled_geometry(view, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -353,6 +471,8 @@ view_set_decorations(struct view *view, bool decorations)
|
|||
ssd_update_geometry(view);
|
||||
if (view->maximized) {
|
||||
view_apply_maximized_geometry(view);
|
||||
} else if (view->tiled) {
|
||||
view_apply_tiled_geometry(view, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -381,11 +501,8 @@ view_set_fullscreen(struct view *view, bool fullscreen,
|
|||
wlr_output = view_wlr_output(view);
|
||||
}
|
||||
if (fullscreen) {
|
||||
if (!view->maximized) {
|
||||
view->unmaximized_geometry.x = view->x;
|
||||
view->unmaximized_geometry.y = view->y;
|
||||
view->unmaximized_geometry.width = view->w;
|
||||
view->unmaximized_geometry.height = view->h;
|
||||
if (!view->maximized && !view->tiled) {
|
||||
view_store_natural_geometry(view);
|
||||
}
|
||||
view->fullscreen = wlr_output;
|
||||
view_apply_fullscreen_geometry(view, view->fullscreen);
|
||||
|
|
@ -393,6 +510,8 @@ view_set_fullscreen(struct view *view, bool fullscreen,
|
|||
/* restore to normal */
|
||||
if (view->maximized) {
|
||||
view_apply_maximized_geometry(view);
|
||||
} else if (view->tiled) {
|
||||
view_apply_tiled_geometry(view, NULL);
|
||||
} else {
|
||||
view_apply_unmaximized_geometry(view);
|
||||
}
|
||||
|
|
@ -421,6 +540,9 @@ view_adjust_for_layout_change(struct view *view)
|
|||
} else if (view->maximized) {
|
||||
/* recompute maximized geometry */
|
||||
view_apply_maximized_geometry(view);
|
||||
} else if (view->tiled) {
|
||||
/* recompute tiled geometry */
|
||||
view_apply_tiled_geometry(view, NULL);
|
||||
} else {
|
||||
/* reposition view if it's offscreen */
|
||||
struct wlr_box box = { view->x, view->y, view->w, view->h };
|
||||
|
|
@ -515,35 +637,6 @@ view_move_to_edge(struct view *view, const char *direction)
|
|||
view_move(view, x, y);
|
||||
}
|
||||
|
||||
enum view_edge {
|
||||
VIEW_EDGE_INVALID,
|
||||
|
||||
VIEW_EDGE_LEFT,
|
||||
VIEW_EDGE_RIGHT,
|
||||
VIEW_EDGE_UP,
|
||||
VIEW_EDGE_DOWN,
|
||||
VIEW_EDGE_CENTER,
|
||||
};
|
||||
|
||||
static enum view_edge
|
||||
view_edge_invert(enum view_edge edge)
|
||||
{
|
||||
switch (edge) {
|
||||
case VIEW_EDGE_LEFT:
|
||||
return VIEW_EDGE_RIGHT;
|
||||
case VIEW_EDGE_RIGHT:
|
||||
return VIEW_EDGE_LEFT;
|
||||
case VIEW_EDGE_UP:
|
||||
return VIEW_EDGE_DOWN;
|
||||
case VIEW_EDGE_DOWN:
|
||||
return VIEW_EDGE_UP;
|
||||
case VIEW_EDGE_CENTER:
|
||||
case VIEW_EDGE_INVALID:
|
||||
default:
|
||||
return VIEW_EDGE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
static enum view_edge
|
||||
view_edge_parse(const char *direction)
|
||||
{
|
||||
|
|
@ -565,53 +658,6 @@ view_edge_parse(const char *direction)
|
|||
}
|
||||
}
|
||||
|
||||
static struct wlr_box
|
||||
view_get_edge_snap_box(struct view *view, struct output *output,
|
||||
enum view_edge edge)
|
||||
{
|
||||
struct wlr_box usable = output_usable_area_in_layout_coords(output);
|
||||
if (usable.height == output->wlr_output->height
|
||||
&& output->wlr_output->scale != 1) {
|
||||
usable.height /= output->wlr_output->scale;
|
||||
}
|
||||
if (usable.width == output->wlr_output->width
|
||||
&& output->wlr_output->scale != 1) {
|
||||
usable.width /= output->wlr_output->scale;
|
||||
}
|
||||
|
||||
int x_offset = edge == VIEW_EDGE_RIGHT
|
||||
? (usable.width + rc.gap) / 2 : rc.gap;
|
||||
int y_offset = edge == VIEW_EDGE_DOWN
|
||||
? (usable.height + rc.gap) / 2 : rc.gap;
|
||||
|
||||
int base_width, base_height;
|
||||
switch (edge) {
|
||||
case VIEW_EDGE_LEFT:
|
||||
case VIEW_EDGE_RIGHT:
|
||||
base_width = (usable.width - 3 * rc.gap) / 2;
|
||||
base_height = usable.height - 2 * rc.gap;
|
||||
break;
|
||||
case VIEW_EDGE_UP:
|
||||
case VIEW_EDGE_DOWN:
|
||||
base_width = usable.width - 2 * rc.gap;
|
||||
base_height = (usable.height - 3 * rc.gap) / 2;
|
||||
break;
|
||||
default:
|
||||
case VIEW_EDGE_CENTER:
|
||||
base_width = usable.width - 2 * rc.gap;
|
||||
base_height = usable.height - 2 * rc.gap;
|
||||
break;
|
||||
}
|
||||
struct wlr_box dst = {
|
||||
.x = x_offset + usable.x + view->margin.left,
|
||||
.y = y_offset + usable.y + view->margin.top,
|
||||
.width = base_width - view->margin.left - view->margin.right,
|
||||
.height = base_height - view->margin.top - view->margin.bottom,
|
||||
};
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
void
|
||||
view_snap_to_edge(struct view *view, const char *direction)
|
||||
{
|
||||
|
|
@ -619,6 +665,9 @@ view_snap_to_edge(struct view *view, const char *direction)
|
|||
wlr_log(WLR_ERROR, "no view");
|
||||
return;
|
||||
}
|
||||
if (view->fullscreen) {
|
||||
return;
|
||||
}
|
||||
struct output *output = view_output(view);
|
||||
if (!output) {
|
||||
wlr_log(WLR_ERROR, "no output");
|
||||
|
|
@ -630,50 +679,50 @@ view_snap_to_edge(struct view *view, const char *direction)
|
|||
return;
|
||||
}
|
||||
|
||||
struct wlr_box dst = view_get_edge_snap_box(view, output, edge);
|
||||
|
||||
if (view->x == dst.x && view->y == dst.y && view->w == dst.width
|
||||
&& view->h == dst.height) {
|
||||
/* Move over to the next screen if this is already snapped. */
|
||||
struct wlr_box usable =
|
||||
output_usable_area_in_layout_coords(output);
|
||||
if (view->tiled == edge) {
|
||||
/* We are already tiled for this edge and thus should switch outputs */
|
||||
struct wlr_output *new_output = NULL;
|
||||
struct wlr_output *current_output = output->wlr_output;
|
||||
struct wlr_output_layout *layout = view->server->output_layout;
|
||||
switch (edge) {
|
||||
case VIEW_EDGE_LEFT:
|
||||
dst.x -= (usable.width / 2) + 1;
|
||||
new_output = wlr_output_layout_adjacent_output(
|
||||
layout, WLR_DIRECTION_LEFT, current_output, 1, 0);
|
||||
break;
|
||||
case VIEW_EDGE_RIGHT:
|
||||
dst.x += (usable.width / 2) + 1;
|
||||
new_output = wlr_output_layout_adjacent_output(
|
||||
layout, WLR_DIRECTION_RIGHT, current_output, 1, 0);
|
||||
break;
|
||||
case VIEW_EDGE_UP:
|
||||
dst.y -= (usable.height / 2) + 1;
|
||||
new_output = wlr_output_layout_adjacent_output(
|
||||
layout, WLR_DIRECTION_UP, current_output, 0, 1);
|
||||
break;
|
||||
case VIEW_EDGE_DOWN:
|
||||
dst.y += (usable.height / 2) + 1;
|
||||
new_output = wlr_output_layout_adjacent_output(
|
||||
layout, WLR_DIRECTION_DOWN, current_output, 0, 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
struct wlr_output *new_wlr_output = wlr_output_layout_output_at(
|
||||
view->server->output_layout, dst.x, dst.y);
|
||||
struct output *new_output =
|
||||
output_from_wlr_output(view->server, new_wlr_output);
|
||||
|
||||
if (new_output == output || !new_output
|
||||
|| edge == VIEW_EDGE_CENTER) {
|
||||
if (new_output && new_output != current_output) {
|
||||
/* Move to next output */
|
||||
edge = view_edge_invert(edge);
|
||||
output = output_from_wlr_output(view->server, new_output);
|
||||
} else {
|
||||
/* No more output to move to */
|
||||
return;
|
||||
}
|
||||
|
||||
dst = view_get_edge_snap_box(view, new_output,
|
||||
view_edge_invert(edge));
|
||||
}
|
||||
|
||||
if (view->w == dst.width && view->h == dst.height) {
|
||||
/* move horizontally/vertically without changing size */
|
||||
view_move(view, dst.x, dst.y);
|
||||
} else {
|
||||
view_move_resize(view, dst);
|
||||
if (view->maximized) {
|
||||
/* Unmaximize + keep using existing natural_geometry */
|
||||
view_maximize(view, false);
|
||||
} else if (!view->tiled) {
|
||||
/* store current geometry as new natural_geometry */
|
||||
view_store_natural_geometry(view);
|
||||
}
|
||||
view->tiled = edge;
|
||||
view_apply_tiled_geometry(view, output);
|
||||
}
|
||||
|
||||
const char *
|
||||
|
|
|
|||
|
|
@ -298,7 +298,6 @@ xdg_toplevel_view_map(struct view *view)
|
|||
|
||||
view->ssd.enabled = has_ssd(view);
|
||||
if (view->ssd.enabled) {
|
||||
view->margin = ssd_thickness(view);
|
||||
ssd_create(view);
|
||||
}
|
||||
|
||||
|
|
@ -311,7 +310,6 @@ xdg_toplevel_view_map(struct view *view)
|
|||
}
|
||||
|
||||
view_discover_output(view);
|
||||
|
||||
view->been_mapped = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ unmanaged_handle_commit(struct wl_listener *listener, void *data)
|
|||
struct wlr_xwayland_surface *xsurface = unmanaged->xwayland_surface;
|
||||
unmanaged->lx = xsurface->x;
|
||||
unmanaged->ly = xsurface->y;
|
||||
wlr_scene_node_set_position(unmanaged->node,
|
||||
unmanaged->lx, unmanaged->ly);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -33,6 +35,8 @@ unmanaged_handle_set_geometry(struct wl_listener *listener, void *data)
|
|||
wlr_log(WLR_DEBUG, "xwayland-unmanaged surface has moved");
|
||||
unmanaged->lx = xsurface->x;
|
||||
unmanaged->ly = xsurface->y;
|
||||
wlr_scene_node_set_position(unmanaged->node,
|
||||
unmanaged->lx, unmanaged->ly);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -59,10 +63,11 @@ unmanaged_handle_map(struct wl_listener *listener, void *data)
|
|||
}
|
||||
|
||||
/* node will be destroyed automatically once surface is destroyed */
|
||||
struct wlr_scene_node *node = &wlr_scene_surface_create(
|
||||
unmanaged->node = &wlr_scene_surface_create(
|
||||
unmanaged->server->unmanaged_tree,
|
||||
xsurface->surface)->buffer->node;
|
||||
wlr_scene_node_set_position(node, unmanaged->lx, unmanaged->ly);
|
||||
wlr_scene_node_set_position(unmanaged->node,
|
||||
unmanaged->lx, unmanaged->ly);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -144,6 +144,14 @@ handle_request_configure(struct wl_listener *listener, void *data)
|
|||
int height = event->height;
|
||||
view_adjust_size(view, &width, &height);
|
||||
|
||||
view->pending_move_resize.update_x = event->x != view->x;
|
||||
view->pending_move_resize.update_y = event->y != view->y;
|
||||
view->pending_move_resize.x = event->x;
|
||||
view->pending_move_resize.y = event->y;
|
||||
view->pending_move_resize.width = width;
|
||||
view->pending_move_resize.height = height;
|
||||
|
||||
wlr_scene_node_set_position(&view->scene_tree->node, event->x, event->y);
|
||||
wlr_xwayland_surface_configure(view->xwayland_surface,
|
||||
event->x, event->y, width, height);
|
||||
}
|
||||
|
|
@ -216,6 +224,13 @@ move(struct view *view, double x, double y)
|
|||
{
|
||||
view->x = x;
|
||||
view->y = y;
|
||||
|
||||
/* override any previous pending move */
|
||||
view->pending_move_resize.update_x = false;
|
||||
view->pending_move_resize.update_y = false;
|
||||
view->pending_move_resize.x = x;
|
||||
view->pending_move_resize.y = y;
|
||||
|
||||
struct wlr_xwayland_surface *s = view->xwayland_surface;
|
||||
wlr_xwayland_surface_configure(s, (int16_t)x, (int16_t)y,
|
||||
(uint16_t)s->width, (uint16_t)s->height);
|
||||
|
|
@ -329,7 +344,7 @@ map(struct view *view)
|
|||
if (!view->been_mapped) {
|
||||
view->ssd.enabled = want_deco(view);
|
||||
if (view->ssd.enabled) {
|
||||
view->margin = ssd_thickness(view);
|
||||
ssd_create(view);
|
||||
}
|
||||
|
||||
if (!view->maximized && !view->fullscreen) {
|
||||
|
|
@ -341,11 +356,6 @@ map(struct view *view)
|
|||
}
|
||||
|
||||
view_discover_output(view);
|
||||
|
||||
if (view->ssd.enabled) {
|
||||
/* Create ssd after view_disover_output() had been called */
|
||||
ssd_create(view);
|
||||
}
|
||||
view->been_mapped = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue