|
|
@@ -3,6 +3,7 @@
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
#include <getopt.h>
|
|
|
|
#include <getopt.h>
|
|
|
|
#include <libinput.h>
|
|
|
|
#include <libinput.h>
|
|
|
|
|
|
|
|
#include <limits.h>
|
|
|
|
#include <linux/input-event-codes.h>
|
|
|
|
#include <linux/input-event-codes.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <signal.h>
|
|
|
@@ -15,6 +16,7 @@
|
|
|
|
#include <wlr/backend.h>
|
|
|
|
#include <wlr/backend.h>
|
|
|
|
#include <wlr/backend/libinput.h>
|
|
|
|
#include <wlr/backend/libinput.h>
|
|
|
|
#include <wlr/render/allocator.h>
|
|
|
|
#include <wlr/render/allocator.h>
|
|
|
|
|
|
|
|
#include <wlr/render/swapchain.h>
|
|
|
|
#include <wlr/render/wlr_renderer.h>
|
|
|
|
#include <wlr/render/wlr_renderer.h>
|
|
|
|
#include <wlr/types/wlr_alpha_modifier_v1.h>
|
|
|
|
#include <wlr/types/wlr_alpha_modifier_v1.h>
|
|
|
|
#include <wlr/types/wlr_compositor.h>
|
|
|
|
#include <wlr/types/wlr_compositor.h>
|
|
|
@@ -27,6 +29,7 @@
|
|
|
|
#include <wlr/types/wlr_ext_data_control_v1.h>
|
|
|
|
#include <wlr/types/wlr_ext_data_control_v1.h>
|
|
|
|
#include <wlr/types/wlr_ext_image_capture_source_v1.h>
|
|
|
|
#include <wlr/types/wlr_ext_image_capture_source_v1.h>
|
|
|
|
#include <wlr/types/wlr_ext_image_copy_capture_v1.h>
|
|
|
|
#include <wlr/types/wlr_ext_image_copy_capture_v1.h>
|
|
|
|
|
|
|
|
#include <wlr/types/wlr_ext_foreign_toplevel_list_v1.h>
|
|
|
|
#include <wlr/types/wlr_fractional_scale_v1.h>
|
|
|
|
#include <wlr/types/wlr_fractional_scale_v1.h>
|
|
|
|
#include <wlr/types/wlr_gamma_control_v1.h>
|
|
|
|
#include <wlr/types/wlr_gamma_control_v1.h>
|
|
|
|
#include <wlr/types/wlr_idle_inhibit_v1.h>
|
|
|
|
#include <wlr/types/wlr_idle_inhibit_v1.h>
|
|
|
@@ -41,6 +44,7 @@
|
|
|
|
#include <wlr/types/wlr_output_layout.h>
|
|
|
|
#include <wlr/types/wlr_output_layout.h>
|
|
|
|
#include <wlr/types/wlr_output_management_v1.h>
|
|
|
|
#include <wlr/types/wlr_output_management_v1.h>
|
|
|
|
#include <wlr/types/wlr_output_power_management_v1.h>
|
|
|
|
#include <wlr/types/wlr_output_power_management_v1.h>
|
|
|
|
|
|
|
|
#include <wlr/types/wlr_output_swapchain_manager.h>
|
|
|
|
#include <wlr/types/wlr_pointer.h>
|
|
|
|
#include <wlr/types/wlr_pointer.h>
|
|
|
|
#include <wlr/types/wlr_pointer_constraints_v1.h>
|
|
|
|
#include <wlr/types/wlr_pointer_constraints_v1.h>
|
|
|
|
#include <wlr/types/wlr_presentation_time.h>
|
|
|
|
#include <wlr/types/wlr_presentation_time.h>
|
|
|
@@ -84,7 +88,9 @@
|
|
|
|
/* enums */
|
|
|
|
/* enums */
|
|
|
|
enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */
|
|
|
|
enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */
|
|
|
|
enum { XDGShell, LayerShell, X11 }; /* client types */
|
|
|
|
enum { XDGShell, LayerShell, X11 }; /* client types */
|
|
|
|
enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrOverlay, LyrIMPopup, LyrBlock, NUM_LAYERS }; /* scene layers */
|
|
|
|
enum { LyrBg, LyrBottom, LyrTile, LyrFloat, LyrTop, LyrFS, LyrUnmanaged, LyrOverlay,
|
|
|
|
|
|
|
|
LyrIMPopup, LyrBlock, NUM_LAYERS }; /* scene layers */
|
|
|
|
|
|
|
|
enum { AxisUp, AxisRight, AxisDown, AxisLeft };
|
|
|
|
|
|
|
|
|
|
|
|
typedef union {
|
|
|
|
typedef union {
|
|
|
|
int i;
|
|
|
|
int i;
|
|
|
@@ -93,6 +99,13 @@ typedef union {
|
|
|
|
const void *v;
|
|
|
|
const void *v;
|
|
|
|
} Arg;
|
|
|
|
} Arg;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
|
|
|
unsigned int mod;
|
|
|
|
|
|
|
|
unsigned int dir;
|
|
|
|
|
|
|
|
void (*func)(const Arg *);
|
|
|
|
|
|
|
|
const Arg arg;
|
|
|
|
|
|
|
|
} Axis;
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
typedef struct {
|
|
|
|
unsigned int mod;
|
|
|
|
unsigned int mod;
|
|
|
|
unsigned int button;
|
|
|
|
unsigned int button;
|
|
|
@@ -119,6 +132,13 @@ typedef struct {
|
|
|
|
struct wlr_xwayland_surface *xwayland;
|
|
|
|
struct wlr_xwayland_surface *xwayland;
|
|
|
|
} surface;
|
|
|
|
} surface;
|
|
|
|
struct wlr_xdg_toplevel_decoration_v1 *decoration;
|
|
|
|
struct wlr_xdg_toplevel_decoration_v1 *decoration;
|
|
|
|
|
|
|
|
struct wlr_ext_foreign_toplevel_handle_v1 *foreign_toplevel_handle;
|
|
|
|
|
|
|
|
struct wlr_scene *image_capture_scene;
|
|
|
|
|
|
|
|
struct wlr_ext_image_capture_source_v1 *image_capture_source;
|
|
|
|
|
|
|
|
union {
|
|
|
|
|
|
|
|
struct wlr_scene_tree *image_capture_tree;
|
|
|
|
|
|
|
|
struct wlr_scene_surface *image_capture_scene_surface;
|
|
|
|
|
|
|
|
} capture;
|
|
|
|
struct wl_listener commit;
|
|
|
|
struct wl_listener commit;
|
|
|
|
struct wl_listener map;
|
|
|
|
struct wl_listener map;
|
|
|
|
struct wl_listener maximize;
|
|
|
|
struct wl_listener maximize;
|
|
|
@@ -133,12 +153,12 @@ typedef struct {
|
|
|
|
struct wl_listener associate;
|
|
|
|
struct wl_listener associate;
|
|
|
|
struct wl_listener dissociate;
|
|
|
|
struct wl_listener dissociate;
|
|
|
|
struct wl_listener configure;
|
|
|
|
struct wl_listener configure;
|
|
|
|
|
|
|
|
struct wl_listener set_geometry;
|
|
|
|
struct wl_listener set_hints;
|
|
|
|
struct wl_listener set_hints;
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
unsigned int bw;
|
|
|
|
unsigned int bw;
|
|
|
|
uint32_t tags;
|
|
|
|
uint32_t tags;
|
|
|
|
int isfloating, isurgent, isfullscreen;
|
|
|
|
int isfloating, isurgent, isfullscreen;
|
|
|
|
uint32_t resize; /* configure serial of a pending resize */
|
|
|
|
|
|
|
|
} Client;
|
|
|
|
} Client;
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
typedef struct {
|
|
|
@@ -152,9 +172,8 @@ typedef struct {
|
|
|
|
struct wlr_keyboard_group *wlr_group;
|
|
|
|
struct wlr_keyboard_group *wlr_group;
|
|
|
|
struct wlr_keyboard *virtual_keyboard;
|
|
|
|
struct wlr_keyboard *virtual_keyboard;
|
|
|
|
|
|
|
|
|
|
|
|
int nsyms;
|
|
|
|
xkb_keysym_t keysyms[2];
|
|
|
|
const xkb_keysym_t *keysyms; /* invalid if nsyms == 0 */
|
|
|
|
uint32_t mods;
|
|
|
|
uint32_t mods; /* invalid if nsyms == 0 */
|
|
|
|
|
|
|
|
struct wl_event_source *key_repeat_source;
|
|
|
|
struct wl_event_source *key_repeat_source;
|
|
|
|
|
|
|
|
|
|
|
|
struct wl_listener modifiers;
|
|
|
|
struct wl_listener modifiers;
|
|
|
@@ -249,6 +268,7 @@ static void arrangelayer(Monitor *m, struct wl_list *list,
|
|
|
|
static void arrangelayers(Monitor *m);
|
|
|
|
static void arrangelayers(Monitor *m);
|
|
|
|
static void axisnotify(struct wl_listener *listener, void *data);
|
|
|
|
static void axisnotify(struct wl_listener *listener, void *data);
|
|
|
|
static void buttonpress(struct wl_listener *listener, void *data);
|
|
|
|
static void buttonpress(struct wl_listener *listener, void *data);
|
|
|
|
|
|
|
|
static void capturerequest(struct wl_listener *listener, void *data);
|
|
|
|
static void chvt(const Arg *arg);
|
|
|
|
static void chvt(const Arg *arg);
|
|
|
|
static void checkidleinhibitor(struct wlr_surface *exclude);
|
|
|
|
static void checkidleinhibitor(struct wlr_surface *exclude);
|
|
|
|
static void cleanup(void);
|
|
|
|
static void cleanup(void);
|
|
|
@@ -309,7 +329,7 @@ static void moveresize(const Arg *arg);
|
|
|
|
static void outputmgrapply(struct wl_listener *listener, void *data);
|
|
|
|
static void outputmgrapply(struct wl_listener *listener, void *data);
|
|
|
|
static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test);
|
|
|
|
static void outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test);
|
|
|
|
static void outputmgrtest(struct wl_listener *listener, void *data);
|
|
|
|
static void outputmgrtest(struct wl_listener *listener, void *data);
|
|
|
|
static void pointerfocus(Client *c, struct wlr_surface *surface,
|
|
|
|
static void pointerfocus(Client *c, LayerSurface* l, struct wlr_surface *surface,
|
|
|
|
double sx, double sy, uint32_t time);
|
|
|
|
double sx, double sy, uint32_t time);
|
|
|
|
static void printstatus(void);
|
|
|
|
static void printstatus(void);
|
|
|
|
static void powermgrsetmode(struct wl_listener *listener, void *data);
|
|
|
|
static void powermgrsetmode(struct wl_listener *listener, void *data);
|
|
|
@@ -357,6 +377,7 @@ static void zoom(const Arg *arg);
|
|
|
|
static pid_t child_pid = -1;
|
|
|
|
static pid_t child_pid = -1;
|
|
|
|
static int locked;
|
|
|
|
static int locked;
|
|
|
|
static void *exclusive_focus;
|
|
|
|
static void *exclusive_focus;
|
|
|
|
|
|
|
|
static Client *focused_client;
|
|
|
|
static struct wl_display *dpy;
|
|
|
|
static struct wl_display *dpy;
|
|
|
|
static struct wl_event_loop *event_loop;
|
|
|
|
static struct wl_event_loop *event_loop;
|
|
|
|
static struct wlr_backend *backend;
|
|
|
|
static struct wlr_backend *backend;
|
|
|
@@ -383,6 +404,8 @@ static struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard_mgr;
|
|
|
|
static struct wlr_virtual_pointer_manager_v1 *virtual_pointer_mgr;
|
|
|
|
static struct wlr_virtual_pointer_manager_v1 *virtual_pointer_mgr;
|
|
|
|
static struct wlr_cursor_shape_manager_v1 *cursor_shape_mgr;
|
|
|
|
static struct wlr_cursor_shape_manager_v1 *cursor_shape_mgr;
|
|
|
|
static struct wlr_output_power_manager_v1 *power_mgr;
|
|
|
|
static struct wlr_output_power_manager_v1 *power_mgr;
|
|
|
|
|
|
|
|
static struct wlr_ext_foreign_toplevel_list_v1 *foreign_toplevel_list;
|
|
|
|
|
|
|
|
static struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1 *ext_foreign_toplevel_image_capture_source_manager_v1;
|
|
|
|
|
|
|
|
|
|
|
|
static struct wlr_pointer_constraints_v1 *pointer_constraints;
|
|
|
|
static struct wlr_pointer_constraints_v1 *pointer_constraints;
|
|
|
|
static struct wlr_relative_pointer_manager_v1 *relative_pointer_mgr;
|
|
|
|
static struct wlr_relative_pointer_manager_v1 *relative_pointer_mgr;
|
|
|
@@ -437,6 +460,7 @@ static struct wl_listener request_set_cursor_shape = {.notify = setcursorshape};
|
|
|
|
static struct wl_listener request_start_drag = {.notify = requeststartdrag};
|
|
|
|
static struct wl_listener request_start_drag = {.notify = requeststartdrag};
|
|
|
|
static struct wl_listener start_drag = {.notify = startdrag};
|
|
|
|
static struct wl_listener start_drag = {.notify = startdrag};
|
|
|
|
static struct wl_listener new_session_lock = {.notify = locksession};
|
|
|
|
static struct wl_listener new_session_lock = {.notify = locksession};
|
|
|
|
|
|
|
|
static struct wl_listener new_foreign_toplevel_capture_request = {.notify = capturerequest};
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef XWAYLAND
|
|
|
|
#ifdef XWAYLAND
|
|
|
|
static void activatex11(struct wl_listener *listener, void *data);
|
|
|
|
static void activatex11(struct wl_listener *listener, void *data);
|
|
|
@@ -444,6 +468,7 @@ static void associatex11(struct wl_listener *listener, void *data);
|
|
|
|
static void configurex11(struct wl_listener *listener, void *data);
|
|
|
|
static void configurex11(struct wl_listener *listener, void *data);
|
|
|
|
static void createnotifyx11(struct wl_listener *listener, void *data);
|
|
|
|
static void createnotifyx11(struct wl_listener *listener, void *data);
|
|
|
|
static void dissociatex11(struct wl_listener *listener, void *data);
|
|
|
|
static void dissociatex11(struct wl_listener *listener, void *data);
|
|
|
|
|
|
|
|
static void setgeometryx11(struct wl_listener *listener, void *data);
|
|
|
|
static void sethints(struct wl_listener *listener, void *data);
|
|
|
|
static void sethints(struct wl_listener *listener, void *data);
|
|
|
|
static void xwaylandready(struct wl_listener *listener, void *data);
|
|
|
|
static void xwaylandready(struct wl_listener *listener, void *data);
|
|
|
|
static struct wl_listener new_xwayland_surface = {.notify = createnotifyx11};
|
|
|
|
static struct wl_listener new_xwayland_surface = {.notify = createnotifyx11};
|
|
|
@@ -463,10 +488,23 @@ static struct wlr_xwayland *xwayland;
|
|
|
|
void
|
|
|
|
void
|
|
|
|
applybounds(Client *c, struct wlr_box *bbox)
|
|
|
|
applybounds(Client *c, struct wlr_box *bbox)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
/* set minimum possible */
|
|
|
|
/* set minimum client size to 1 */
|
|
|
|
c->geom.width = MAX(1 + 2 * (int)c->bw, c->geom.width);
|
|
|
|
c->geom.width = MAX(1 + 2 * (int)c->bw, c->geom.width);
|
|
|
|
c->geom.height = MAX(1 + 2 * (int)c->bw, c->geom.height);
|
|
|
|
c->geom.height = MAX(1 + 2 * (int)c->bw, c->geom.height);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!c->isfullscreen) {
|
|
|
|
|
|
|
|
struct wlr_box min = {0}, max = {0};
|
|
|
|
|
|
|
|
client_get_size_hints(c, &max, &min);
|
|
|
|
|
|
|
|
c->geom.width = MAX(min.width + 2 * (int)c->bw, c->geom.width);
|
|
|
|
|
|
|
|
c->geom.height = MAX(min.height + 2 * (int)c->bw, c->geom.height);
|
|
|
|
|
|
|
|
/* Some clients set their max size to INT_MAX, which does not violate the
|
|
|
|
|
|
|
|
* protocol but it's unnecesary, as they can set their max size to zero. */
|
|
|
|
|
|
|
|
if (max.width > 0 && 2 * (int)c->bw <= INT_MAX - max.width) /* Checks for overflow */
|
|
|
|
|
|
|
|
c->geom.width = MIN(max.width + 2 * (int)c->bw, c->geom.width);
|
|
|
|
|
|
|
|
if (max.height > 0 && 2 * (int)c->bw <= INT_MAX - max.height) /* Checks for overflow */
|
|
|
|
|
|
|
|
c->geom.height = MIN(max.height + 2 * (int)c->bw, c->geom.height);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (c->geom.x >= bbox->x + bbox->width)
|
|
|
|
if (c->geom.x >= bbox->x + bbox->width)
|
|
|
|
c->geom.x = bbox->x + bbox->width - c->geom.width;
|
|
|
|
c->geom.x = bbox->x + bbox->width - c->geom.width;
|
|
|
|
if (c->geom.y >= bbox->y + bbox->height)
|
|
|
|
if (c->geom.y >= bbox->y + bbox->height)
|
|
|
@@ -518,7 +556,9 @@ arrange(Monitor *m)
|
|
|
|
wl_list_for_each(c, &clients, link) {
|
|
|
|
wl_list_for_each(c, &clients, link) {
|
|
|
|
if (c->mon == m) {
|
|
|
|
if (c->mon == m) {
|
|
|
|
wlr_scene_node_set_enabled(&c->scene->node, VISIBLEON(c, m));
|
|
|
|
wlr_scene_node_set_enabled(&c->scene->node, VISIBLEON(c, m));
|
|
|
|
client_set_suspended(c, !VISIBLEON(c, m));
|
|
|
|
client_set_suspended(c, !VISIBLEON(c, m)
|
|
|
|
|
|
|
|
&& (!c->image_capture_source
|
|
|
|
|
|
|
|
|| wl_list_empty(&c->image_capture_source->resources)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@@ -593,10 +633,13 @@ arrangelayers(Monitor *m)
|
|
|
|
for (i = 3; i >= 0; i--)
|
|
|
|
for (i = 3; i >= 0; i--)
|
|
|
|
arrangelayer(m, &m->layers[i], &usable_area, 0);
|
|
|
|
arrangelayer(m, &m->layers[i], &usable_area, 0);
|
|
|
|
|
|
|
|
|
|
|
|
/* Find topmost keyboard interactive layer, if such a layer exists */
|
|
|
|
/* Find topmost keyboard interactive layer that has indicated it wants
|
|
|
|
|
|
|
|
* exclusive access to the keyboard, if such a layer exists */
|
|
|
|
for (i = 0; i < (int)LENGTH(layers_above_shell); i++) {
|
|
|
|
for (i = 0; i < (int)LENGTH(layers_above_shell); i++) {
|
|
|
|
wl_list_for_each_reverse(l, &m->layers[layers_above_shell[i]], link) {
|
|
|
|
wl_list_for_each_reverse(l, &m->layers[layers_above_shell[i]], link) {
|
|
|
|
if (locked || !l->layer_surface->current.keyboard_interactive || !l->mapped)
|
|
|
|
if (locked ||
|
|
|
|
|
|
|
|
l->layer_surface->current.keyboard_interactive != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE ||
|
|
|
|
|
|
|
|
!l->mapped)
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
/* Deactivate the focused client. */
|
|
|
|
/* Deactivate the focused client. */
|
|
|
|
focusclient(NULL, 0);
|
|
|
|
focusclient(NULL, 0);
|
|
|
@@ -613,9 +656,26 @@ axisnotify(struct wl_listener *listener, void *data)
|
|
|
|
/* This event is forwarded by the cursor when a pointer emits an axis event,
|
|
|
|
/* This event is forwarded by the cursor when a pointer emits an axis event,
|
|
|
|
* for example when you move the scroll wheel. */
|
|
|
|
* for example when you move the scroll wheel. */
|
|
|
|
struct wlr_pointer_axis_event *event = data;
|
|
|
|
struct wlr_pointer_axis_event *event = data;
|
|
|
|
|
|
|
|
const Axis *a;
|
|
|
|
|
|
|
|
unsigned int adir;
|
|
|
|
|
|
|
|
struct wlr_keyboard *keyboard;
|
|
|
|
|
|
|
|
uint32_t mods;
|
|
|
|
|
|
|
|
|
|
|
|
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
|
|
|
|
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
|
|
|
|
/* TODO: allow usage of scroll wheel for mousebindings, it can be implemented
|
|
|
|
|
|
|
|
* by checking the event's orientation and the delta of the event */
|
|
|
|
if (event->orientation == WL_POINTER_AXIS_VERTICAL_SCROLL)
|
|
|
|
|
|
|
|
adir = event->delta > 0 ? AxisDown : AxisUp;
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
adir = event->delta > 0 ? AxisRight : AxisLeft;
|
|
|
|
|
|
|
|
keyboard = wlr_seat_get_keyboard(seat);
|
|
|
|
|
|
|
|
mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
|
|
|
|
|
|
|
|
for (a = axes; a < END(axes); a++) {
|
|
|
|
|
|
|
|
if (CLEANMASK(mods) == CLEANMASK(a->mod) && adir == a->dir && a->func) {
|
|
|
|
|
|
|
|
a->func(&a->arg);
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Notify the client with pointer focus of the axis event. */
|
|
|
|
/* Notify the client with pointer focus of the axis event. */
|
|
|
|
wlr_seat_pointer_notify_axis(seat,
|
|
|
|
wlr_seat_pointer_notify_axis(seat,
|
|
|
|
event->time_msec, event->orientation, event->delta,
|
|
|
|
event->time_msec, event->orientation, event->delta,
|
|
|
@@ -628,7 +688,8 @@ buttonpress(struct wl_listener *listener, void *data)
|
|
|
|
struct wlr_pointer_button_event *event = data;
|
|
|
|
struct wlr_pointer_button_event *event = data;
|
|
|
|
struct wlr_keyboard *keyboard;
|
|
|
|
struct wlr_keyboard *keyboard;
|
|
|
|
uint32_t mods;
|
|
|
|
uint32_t mods;
|
|
|
|
Client *c;
|
|
|
|
Client *c = NULL;
|
|
|
|
|
|
|
|
LayerSurface *l = NULL;
|
|
|
|
const Button *b;
|
|
|
|
const Button *b;
|
|
|
|
|
|
|
|
|
|
|
|
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
|
|
|
|
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
|
|
|
@@ -640,10 +701,15 @@ buttonpress(struct wl_listener *listener, void *data)
|
|
|
|
if (locked)
|
|
|
|
if (locked)
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
/* Change focus if the button was _pressed_ over a client */
|
|
|
|
/* Change focus if the button was _pressed_ over a client
|
|
|
|
xytonode(cursor->x, cursor->y, NULL, &c, NULL, NULL, NULL);
|
|
|
|
or a layer surface with on-demand keyboard interactivity */
|
|
|
|
if (c && (!client_is_unmanaged(c) || client_wants_focus(c)))
|
|
|
|
xytonode(cursor->x, cursor->y, NULL, &c, &l, NULL, NULL);
|
|
|
|
|
|
|
|
if (c && (!client_is_unmanaged(c) || client_wants_focus(c))) {
|
|
|
|
focusclient(c, 1);
|
|
|
|
focusclient(c, 1);
|
|
|
|
|
|
|
|
} else if (l && l->layer_surface->current.keyboard_interactive) {
|
|
|
|
|
|
|
|
focusclient(NULL, 0);
|
|
|
|
|
|
|
|
client_notify_enter(l->layer_surface->surface, wlr_seat_get_keyboard(seat));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
keyboard = wlr_seat_get_keyboard(seat);
|
|
|
|
keyboard = wlr_seat_get_keyboard(seat);
|
|
|
|
mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
|
|
|
|
mods = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
|
|
|
@@ -657,10 +723,11 @@ buttonpress(struct wl_listener *listener, void *data)
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case WL_POINTER_BUTTON_STATE_RELEASED:
|
|
|
|
case WL_POINTER_BUTTON_STATE_RELEASED:
|
|
|
|
/* If you released any buttons, we exit interactive move/resize mode. */
|
|
|
|
/* If you released any buttons, we exit interactive move/resize mode. */
|
|
|
|
/* TODO: should reset to the pointer focus's current setcursor */
|
|
|
|
|
|
|
|
if (!locked && cursor_mode != CurNormal && cursor_mode != CurPressed) {
|
|
|
|
if (!locked && cursor_mode != CurNormal && cursor_mode != CurPressed) {
|
|
|
|
wlr_cursor_set_xcursor(cursor, cursor_mgr, "default");
|
|
|
|
|
|
|
|
cursor_mode = CurNormal;
|
|
|
|
cursor_mode = CurNormal;
|
|
|
|
|
|
|
|
/* Update the cursor */
|
|
|
|
|
|
|
|
wlr_seat_pointer_clear_focus(seat);
|
|
|
|
|
|
|
|
motionnotify(0, NULL, 0, 0, 0, 0);
|
|
|
|
/* Drop the window off on its new monitor */
|
|
|
|
/* Drop the window off on its new monitor */
|
|
|
|
selmon = xytomon(cursor->x, cursor->y);
|
|
|
|
selmon = xytomon(cursor->x, cursor->y);
|
|
|
|
setmon(grabc, selmon, 0);
|
|
|
|
setmon(grabc, selmon, 0);
|
|
|
@@ -676,6 +743,25 @@ buttonpress(struct wl_listener *listener, void *data)
|
|
|
|
event->time_msec, event->button, event->state);
|
|
|
|
event->time_msec, event->button, event->state);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
|
|
capturerequest(struct wl_listener *listener, void *data)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request *request = data;
|
|
|
|
|
|
|
|
Client *view = request->toplevel_handle->data;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!view->image_capture_source) {
|
|
|
|
|
|
|
|
view->image_capture_source = wlr_ext_image_capture_source_v1_create_with_scene_node(
|
|
|
|
|
|
|
|
&view->image_capture_scene->tree.node, event_loop, alloc, drw);
|
|
|
|
|
|
|
|
if (!view->image_capture_source)
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request_accept(
|
|
|
|
|
|
|
|
request, view->image_capture_source);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
client_set_suspended(view, 0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
void
|
|
|
|
chvt(const Arg *arg)
|
|
|
|
chvt(const Arg *arg)
|
|
|
|
{
|
|
|
|
{
|
|
|
@@ -718,6 +804,7 @@ cleanup(void)
|
|
|
|
destroykeyboardgroup(&kb_group->destroy, NULL);
|
|
|
|
destroykeyboardgroup(&kb_group->destroy, NULL);
|
|
|
|
|
|
|
|
|
|
|
|
input_method_relay_finish(input_method_relay);
|
|
|
|
input_method_relay_finish(input_method_relay);
|
|
|
|
|
|
|
|
input_method_relay = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
/* If it's not destroyed manually, it will cause a use-after-free of wlr_seat.
|
|
|
|
/* If it's not destroyed manually, it will cause a use-after-free of wlr_seat.
|
|
|
|
* Destroy it until it's fixed on the wlroots side */
|
|
|
|
* Destroy it until it's fixed on the wlroots side */
|
|
|
@@ -788,6 +875,7 @@ cleanuplisteners(void)
|
|
|
|
wl_list_remove(&request_start_drag.link);
|
|
|
|
wl_list_remove(&request_start_drag.link);
|
|
|
|
wl_list_remove(&start_drag.link);
|
|
|
|
wl_list_remove(&start_drag.link);
|
|
|
|
wl_list_remove(&new_session_lock.link);
|
|
|
|
wl_list_remove(&new_session_lock.link);
|
|
|
|
|
|
|
|
wl_list_remove(&new_foreign_toplevel_capture_request.link);
|
|
|
|
#ifdef XWAYLAND
|
|
|
|
#ifdef XWAYLAND
|
|
|
|
wl_list_remove(&new_xwayland_surface.link);
|
|
|
|
wl_list_remove(&new_xwayland_surface.link);
|
|
|
|
wl_list_remove(&xwayland_ready.link);
|
|
|
|
wl_list_remove(&xwayland_ready.link);
|
|
|
@@ -843,6 +931,11 @@ commitlayersurfacenotify(struct wl_listener *listener, void *data)
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (layer_surface == exclusive_focus
|
|
|
|
|
|
|
|
&& layer_surface->current.keyboard_interactive !=
|
|
|
|
|
|
|
|
ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE)
|
|
|
|
|
|
|
|
exclusive_focus = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
if (layer_surface->current.committed == 0 && l->mapped == layer_surface->surface->mapped)
|
|
|
|
if (layer_surface->current.committed == 0 && l->mapped == layer_surface->surface->mapped)
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
l->mapped = layer_surface->surface->mapped;
|
|
|
|
l->mapped = layer_surface->surface->mapped;
|
|
|
@@ -881,14 +974,13 @@ commitnotify(struct wl_listener *listener, void *data)
|
|
|
|
if (c->decoration)
|
|
|
|
if (c->decoration)
|
|
|
|
requestdecorationmode(&c->set_decoration_mode, c->decoration);
|
|
|
|
requestdecorationmode(&c->set_decoration_mode, c->decoration);
|
|
|
|
wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, 0, 0);
|
|
|
|
wlr_xdg_toplevel_set_size(c->surface.xdg->toplevel, 0, 0);
|
|
|
|
|
|
|
|
if (!c->isfloating)
|
|
|
|
|
|
|
|
client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT |
|
|
|
|
|
|
|
|
WLR_EDGE_RIGHT);
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
resize(c, c->geom, (c->isfloating && !c->isfullscreen));
|
|
|
|
resize(c, c->geom, (c->isfloating && !c->isfullscreen));
|
|
|
|
|
|
|
|
|
|
|
|
/* mark a pending resize as completed */
|
|
|
|
|
|
|
|
if (c->resize && c->resize <= c->surface.xdg->current.configure_serial)
|
|
|
|
|
|
|
|
c->resize = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
void
|
|
|
@@ -1345,6 +1437,7 @@ destroynotify(struct wl_listener *listener, void *data)
|
|
|
|
wl_list_remove(&c->associate.link);
|
|
|
|
wl_list_remove(&c->associate.link);
|
|
|
|
wl_list_remove(&c->configure.link);
|
|
|
|
wl_list_remove(&c->configure.link);
|
|
|
|
wl_list_remove(&c->dissociate.link);
|
|
|
|
wl_list_remove(&c->dissociate.link);
|
|
|
|
|
|
|
|
wl_list_remove(&c->set_geometry.link);
|
|
|
|
wl_list_remove(&c->set_hints.link);
|
|
|
|
wl_list_remove(&c->set_hints.link);
|
|
|
|
} else
|
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
@@ -1404,7 +1497,8 @@ dirtomon(enum wlr_direction dir)
|
|
|
|
dir, selmon->wlr_output, selmon->m.x, selmon->m.y)))
|
|
|
|
dir, selmon->wlr_output, selmon->m.x, selmon->m.y)))
|
|
|
|
return next->data;
|
|
|
|
return next->data;
|
|
|
|
if ((next = wlr_output_layout_farthest_output(output_layout,
|
|
|
|
if ((next = wlr_output_layout_farthest_output(output_layout,
|
|
|
|
dir ^ (WLR_DIRECTION_LEFT|WLR_DIRECTION_RIGHT),
|
|
|
|
dir ^ (WLR_DIRECTION_LEFT | WLR_DIRECTION_RIGHT |
|
|
|
|
|
|
|
|
WLR_DIRECTION_UP | WLR_DIRECTION_DOWN),
|
|
|
|
selmon->wlr_output, selmon->m.x, selmon->m.y)))
|
|
|
|
selmon->wlr_output, selmon->m.x, selmon->m.y)))
|
|
|
|
return next->data;
|
|
|
|
return next->data;
|
|
|
|
return selmon;
|
|
|
|
return selmon;
|
|
|
@@ -1434,6 +1528,9 @@ focusclient(Client *c, int lift)
|
|
|
|
wlr_xdg_popup_destroy(popup);
|
|
|
|
wlr_xdg_popup_destroy(popup);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (old_c && old_c == exclusive_focus && client_wants_focus(old_c))
|
|
|
|
|
|
|
|
exclusive_focus = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
/* Put the new client atop the focus stack and select its monitor */
|
|
|
|
/* Put the new client atop the focus stack and select its monitor */
|
|
|
|
if (c && !client_is_unmanaged(c)) {
|
|
|
|
if (c && !client_is_unmanaged(c)) {
|
|
|
|
wl_list_remove(&c->flink);
|
|
|
|
wl_list_remove(&c->flink);
|
|
|
@@ -1447,24 +1544,23 @@ focusclient(Client *c, int lift)
|
|
|
|
client_set_border_color(c, focuscolor);
|
|
|
|
client_set_border_color(c, focuscolor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Deactivate old client if focus is changing */
|
|
|
|
/* If an overlay is focused, don't focus or activate the client,
|
|
|
|
if (old && (!c || client_surface(c) != old)) {
|
|
|
|
* but only update its position in fstack to render its border with focuscolor
|
|
|
|
/* If an overlay is focused, don't focus or activate the client,
|
|
|
|
* and focus it after the overlay is closed. */
|
|
|
|
* but only update its position in fstack to render its border with focuscolor
|
|
|
|
if (old && (!c || client_surface(c) != old)
|
|
|
|
* and focus it after the overlay is closed. */
|
|
|
|
&& old_client_type == LayerShell && wlr_scene_node_coords(
|
|
|
|
if (old_client_type == LayerShell && wlr_scene_node_coords(
|
|
|
|
&old_l->scene->node, &unused_lx, &unused_ly)
|
|
|
|
&old_l->scene->node, &unused_lx, &unused_ly)
|
|
|
|
&& old_l->layer_surface->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP
|
|
|
|
&& old_l->layer_surface->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) {
|
|
|
|
&& old_l->layer_surface->current.keyboard_interactive == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE)
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
} else if (old_c && old_c == exclusive_focus && client_wants_focus(old_c)) {
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Don't deactivate old client if the new one wants focus, as this causes issues with winecfg
|
|
|
|
|
|
|
|
* and probably other clients */
|
|
|
|
|
|
|
|
} else if (old_c && !client_is_unmanaged(old_c) && (!c || !client_wants_focus(c))) {
|
|
|
|
|
|
|
|
client_set_border_color(old_c, bordercolor);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
client_activate_surface(old, 0);
|
|
|
|
if (focused_client && focused_client != c && !(c && client_is_unmanaged(c))) {
|
|
|
|
}
|
|
|
|
struct wlr_surface *s = client_surface(focused_client);
|
|
|
|
|
|
|
|
if (c)
|
|
|
|
|
|
|
|
client_set_border_color(focused_client, bordercolor);
|
|
|
|
|
|
|
|
if (s && s->mapped)
|
|
|
|
|
|
|
|
client_activate_surface(s, 0);
|
|
|
|
|
|
|
|
focused_client = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
printstatus();
|
|
|
|
printstatus();
|
|
|
|
|
|
|
|
|
|
|
@@ -1485,6 +1581,9 @@ focusclient(Client *c, int lift)
|
|
|
|
|
|
|
|
|
|
|
|
/* Activate the new client */
|
|
|
|
/* Activate the new client */
|
|
|
|
client_activate_surface(client_surface(c), 1);
|
|
|
|
client_activate_surface(client_surface(c), 1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!client_is_unmanaged(c))
|
|
|
|
|
|
|
|
focused_client = c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
void
|
|
|
@@ -1629,11 +1728,8 @@ keybinding(uint32_t mods, xkb_keysym_t sym)
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
const Key *k;
|
|
|
|
const Key *k;
|
|
|
|
for (k = keys; k < END(keys); k++) {
|
|
|
|
for (k = keys; k < END(keys); k++) {
|
|
|
|
if (CLEANMASK(mods) == CLEANMASK(k->mod)
|
|
|
|
if (CLEANMASK(mods) == CLEANMASK(k->mod) && sym == k->keysym && k->func)
|
|
|
|
&& xkb_keysym_to_lower(sym) == xkb_keysym_to_lower(k->keysym)
|
|
|
|
|
|
|
|
&& k->func) {
|
|
|
|
|
|
|
|
return k;
|
|
|
|
return k;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
@@ -1641,46 +1737,44 @@ keybinding(uint32_t mods, xkb_keysym_t sym)
|
|
|
|
void
|
|
|
|
void
|
|
|
|
keypress(struct wl_listener *listener, void *data)
|
|
|
|
keypress(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* This event is raised when a key is pressed or released. */
|
|
|
|
/* This event is raised when a key is pressed or released. */
|
|
|
|
KeyboardGroup *group = wl_container_of(listener, group, key);
|
|
|
|
KeyboardGroup *group = wl_container_of(listener, group, key);
|
|
|
|
struct wlr_keyboard_key_event *event = data;
|
|
|
|
struct wlr_keyboard_key_event *event = data;
|
|
|
|
|
|
|
|
|
|
|
|
/* Translate libinput keycode -> xkbcommon */
|
|
|
|
/* Translate libinput keycode -> xkbcommon */
|
|
|
|
uint32_t keycode = event->keycode + 8;
|
|
|
|
uint32_t keycode = event->keycode + 8;
|
|
|
|
/* Get a list of keysyms based on the keymap for this keyboard */
|
|
|
|
struct wlr_keyboard *kb = &group->wlr_group->keyboard;
|
|
|
|
const xkb_keysym_t *syms;
|
|
|
|
xkb_layout_index_t layout = xkb_state_key_get_layout(kb->xkb_state, keycode);
|
|
|
|
int nsyms = xkb_state_key_get_syms(
|
|
|
|
|
|
|
|
group->wlr_group->keyboard.xkb_state, keycode, &syms);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int handled = 0;
|
|
|
|
int handled = 0;
|
|
|
|
uint32_t mods = wlr_keyboard_get_modifiers(&group->wlr_group->keyboard);
|
|
|
|
|
|
|
|
|
|
|
|
// Get the keysyms for level 0 (normal) and level 1 (shifted)
|
|
|
|
|
|
|
|
// Only one keysym for each level:
|
|
|
|
|
|
|
|
// multiple keysyms per keycode don't really exist in the real world
|
|
|
|
|
|
|
|
for (int i = 0; i < 2; i++)
|
|
|
|
|
|
|
|
group->keysyms[i] = keymap_get_one_sym_by_level(kb->keymap, keycode, layout, i);
|
|
|
|
|
|
|
|
group->mods = wlr_keyboard_get_modifiers(&group->wlr_group->keyboard);
|
|
|
|
|
|
|
|
|
|
|
|
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
|
|
|
|
wlr_idle_notifier_v1_notify_activity(idle_notifier, seat);
|
|
|
|
|
|
|
|
|
|
|
|
/* On _press_ if there is no active screen locker,
|
|
|
|
/* On _press_ if there is no active screen locker,
|
|
|
|
* attempt to process a compositor keybinding. */
|
|
|
|
* attempt to process a compositor keybinding. */
|
|
|
|
if (!locked && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
|
|
|
if (!locked && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
|
|
|
for (i = 0; i < nsyms; i++) {
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
|
|
const Key *key = keybinding(mods, syms[i]);
|
|
|
|
const Key *key = keybinding(group->mods, group->keysyms[i]);
|
|
|
|
if (key) {
|
|
|
|
if (key) {
|
|
|
|
consumed[event->keycode] = 1;
|
|
|
|
consumed[event->keycode] = 1;
|
|
|
|
key->func(&key->arg);
|
|
|
|
key->func(&key->arg);
|
|
|
|
handled = 1;
|
|
|
|
handled = 1;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (handled && group->wlr_group->keyboard.repeat_info.delay > 0) {
|
|
|
|
if (handled && group->wlr_group->keyboard.repeat_info.delay > 0)
|
|
|
|
group->mods = mods;
|
|
|
|
|
|
|
|
group->keysyms = syms;
|
|
|
|
|
|
|
|
group->nsyms = nsyms;
|
|
|
|
|
|
|
|
wl_event_source_timer_update(group->key_repeat_source,
|
|
|
|
wl_event_source_timer_update(group->key_repeat_source,
|
|
|
|
group->wlr_group->keyboard.repeat_info.delay);
|
|
|
|
group->wlr_group->keyboard.repeat_info.delay);
|
|
|
|
} else {
|
|
|
|
else
|
|
|
|
group->nsyms = 0;
|
|
|
|
|
|
|
|
wl_event_source_timer_update(group->key_repeat_source, 0);
|
|
|
|
wl_event_source_timer_update(group->key_repeat_source, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (handled || input_method_keyboard_grab_forward_key(group, event))
|
|
|
|
if (handled || input_method_keyboard_grab_forward_key(group, event))
|
|
|
|
return;
|
|
|
|
return;
|
|
|
@@ -1716,17 +1810,18 @@ int
|
|
|
|
keyrepeat(void *data)
|
|
|
|
keyrepeat(void *data)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
KeyboardGroup *group = data;
|
|
|
|
KeyboardGroup *group = data;
|
|
|
|
int i;
|
|
|
|
if (group->wlr_group->keyboard.repeat_info.rate <= 0)
|
|
|
|
if (!group->nsyms || group->wlr_group->keyboard.repeat_info.rate <= 0)
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
|
|
wl_event_source_timer_update(group->key_repeat_source,
|
|
|
|
wl_event_source_timer_update(group->key_repeat_source,
|
|
|
|
1000 / group->wlr_group->keyboard.repeat_info.rate);
|
|
|
|
1000 / group->wlr_group->keyboard.repeat_info.rate);
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < group->nsyms; i++) {
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
|
|
const Key *key = keybinding(group->mods, group->keysyms[i]);
|
|
|
|
const Key *key = keybinding(group->mods, group->keysyms[i]);
|
|
|
|
if (key)
|
|
|
|
if (key) {
|
|
|
|
key->func(&key->arg);
|
|
|
|
key->func(&key->arg);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
@@ -1773,6 +1868,11 @@ mapnotify(struct wl_listener *listener, void *data)
|
|
|
|
Monitor *m;
|
|
|
|
Monitor *m;
|
|
|
|
int i;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct wlr_ext_foreign_toplevel_handle_v1_state foreign_toplevel_state = {
|
|
|
|
|
|
|
|
.app_id = client_get_appid(c),
|
|
|
|
|
|
|
|
.title = client_get_title(c),
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/* Create scene tree for this client and its border */
|
|
|
|
/* Create scene tree for this client and its border */
|
|
|
|
c->scene = client_surface(c)->data = wlr_scene_tree_create(layers[LyrTile]);
|
|
|
|
c->scene = client_surface(c)->data = wlr_scene_tree_create(layers[LyrTile]);
|
|
|
|
/* Enabled later by a call to arrange() */
|
|
|
|
/* Enabled later by a call to arrange() */
|
|
|
@@ -1787,9 +1887,8 @@ mapnotify(struct wl_listener *listener, void *data)
|
|
|
|
/* Handle unmanaged clients first so we can return prior create borders */
|
|
|
|
/* Handle unmanaged clients first so we can return prior create borders */
|
|
|
|
if (client_is_unmanaged(c)) {
|
|
|
|
if (client_is_unmanaged(c)) {
|
|
|
|
/* Unmanaged clients always are floating */
|
|
|
|
/* Unmanaged clients always are floating */
|
|
|
|
wlr_scene_node_reparent(&c->scene->node, layers[LyrFloat]);
|
|
|
|
wlr_scene_node_reparent(&c->scene->node, layers[LyrUnmanaged]);
|
|
|
|
wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y);
|
|
|
|
wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y);
|
|
|
|
client_set_size(c, c->geom.width, c->geom.height);
|
|
|
|
|
|
|
|
if (client_wants_focus(c)) {
|
|
|
|
if (client_wants_focus(c)) {
|
|
|
|
focusclient(c, 1);
|
|
|
|
focusclient(c, 1);
|
|
|
|
exclusive_focus = c;
|
|
|
|
exclusive_focus = c;
|
|
|
@@ -1804,7 +1903,6 @@ mapnotify(struct wl_listener *listener, void *data)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Initialize client geometry with room for border */
|
|
|
|
/* Initialize client geometry with room for border */
|
|
|
|
client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
|
|
|
|
|
|
|
|
c->geom.width += 2 * c->bw;
|
|
|
|
c->geom.width += 2 * c->bw;
|
|
|
|
c->geom.height += 2 * c->bw;
|
|
|
|
c->geom.height += 2 * c->bw;
|
|
|
|
|
|
|
|
|
|
|
@@ -1812,6 +1910,18 @@ mapnotify(struct wl_listener *listener, void *data)
|
|
|
|
wl_list_insert(&clients, &c->link);
|
|
|
|
wl_list_insert(&clients, &c->link);
|
|
|
|
wl_list_insert(&fstack, &c->flink);
|
|
|
|
wl_list_insert(&fstack, &c->flink);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
c->foreign_toplevel_handle = wlr_ext_foreign_toplevel_handle_v1_create(
|
|
|
|
|
|
|
|
foreign_toplevel_list, &foreign_toplevel_state);
|
|
|
|
|
|
|
|
c->foreign_toplevel_handle->data = c;
|
|
|
|
|
|
|
|
c->image_capture_scene = wlr_scene_create();
|
|
|
|
|
|
|
|
if (c->type == XDGShell)
|
|
|
|
|
|
|
|
c->capture.image_capture_tree = wlr_scene_xdg_surface_create(&c->image_capture_scene->tree, c->surface.xdg);
|
|
|
|
|
|
|
|
#ifdef XWAYLAND
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
c->capture.image_capture_scene_surface = wlr_scene_surface_create(&c->image_capture_scene->tree, c->surface.xwayland->surface);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Set initial monitor, tags, floating status, and focus:
|
|
|
|
/* Set initial monitor, tags, floating status, and focus:
|
|
|
|
* we always consider floating, clients that have parent and thus
|
|
|
|
* we always consider floating, clients that have parent and thus
|
|
|
|
* we set the same tags and monitor as its parent.
|
|
|
|
* we set the same tags and monitor as its parent.
|
|
|
@@ -1892,22 +2002,23 @@ void
|
|
|
|
motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double dy,
|
|
|
|
motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double dy,
|
|
|
|
double dx_unaccel, double dy_unaccel)
|
|
|
|
double dx_unaccel, double dy_unaccel)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
int nx, ny;
|
|
|
|
double sx = 0, sy = 0, sx_confined, sy_confined;
|
|
|
|
double sx = 0, sy = 0, sx_confined, sy_confined;
|
|
|
|
Client *c = NULL, *w = NULL;
|
|
|
|
Client *c = NULL, *w = NULL;
|
|
|
|
LayerSurface *l = NULL;
|
|
|
|
LayerSurface *l = NULL, *focusedl = NULL;
|
|
|
|
struct wlr_surface *surface = NULL;
|
|
|
|
struct wlr_surface *surface = NULL;
|
|
|
|
struct wlr_pointer_constraint_v1 *constraint;
|
|
|
|
struct wlr_pointer_constraint_v1 *constraint;
|
|
|
|
|
|
|
|
|
|
|
|
/* Find the client under the pointer and send the event along. */
|
|
|
|
/* Find the client under the pointer and send the event along. */
|
|
|
|
xytonode(cursor->x, cursor->y, &surface, &c, NULL, &sx, &sy);
|
|
|
|
xytonode(cursor->x, cursor->y, &surface, &c, &l, &sx, &sy);
|
|
|
|
|
|
|
|
|
|
|
|
if (cursor_mode == CurPressed && !seat->drag
|
|
|
|
if (cursor_mode == CurPressed && !seat->drag
|
|
|
|
&& surface != seat->pointer_state.focused_surface
|
|
|
|
&& surface != seat->pointer_state.focused_surface
|
|
|
|
&& toplevel_from_wlr_surface(seat->pointer_state.focused_surface, &w, &l) >= 0) {
|
|
|
|
&& toplevel_from_wlr_surface(seat->pointer_state.focused_surface, &w, &focusedl) >= 0) {
|
|
|
|
c = w;
|
|
|
|
c = w;
|
|
|
|
surface = seat->pointer_state.focused_surface;
|
|
|
|
surface = seat->pointer_state.focused_surface;
|
|
|
|
sx = cursor->x - (l ? l->scene->node.x : w->geom.x);
|
|
|
|
sx = cursor->x - (focusedl ? focusedl->scene->node.x : w->geom.x);
|
|
|
|
sy = cursor->y - (l ? l->scene->node.y : w->geom.y);
|
|
|
|
sy = cursor->y - (focusedl ? focusedl->scene->node.y : w->geom.y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* time is 0 in internal calls meant to restore pointer focus. */
|
|
|
|
/* time is 0 in internal calls meant to restore pointer focus. */
|
|
|
@@ -1949,7 +2060,17 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d
|
|
|
|
/* If we are currently grabbing the mouse, handle and return */
|
|
|
|
/* If we are currently grabbing the mouse, handle and return */
|
|
|
|
if (cursor_mode == CurMove) {
|
|
|
|
if (cursor_mode == CurMove) {
|
|
|
|
/* Move the grabbed client to the new position. */
|
|
|
|
/* Move the grabbed client to the new position. */
|
|
|
|
resize(grabc, (struct wlr_box){.x = (int)round(cursor->x) - grabcx, .y = (int)round(cursor->y) - grabcy,
|
|
|
|
nx = (int)round(cursor->x) - grabcx;
|
|
|
|
|
|
|
|
ny = (int)round(cursor->y) - grabcy;
|
|
|
|
|
|
|
|
if (abs(selmon->w.x - nx) < (int)snap)
|
|
|
|
|
|
|
|
nx = selmon->w.x;
|
|
|
|
|
|
|
|
else if (abs((selmon->w.x + selmon->w.width) - (nx + grabc->geom.width)) < (int)snap)
|
|
|
|
|
|
|
|
nx = selmon->w.x + selmon->w.width - grabc->geom.width;
|
|
|
|
|
|
|
|
if (abs(selmon->w.y - ny) < (int)snap)
|
|
|
|
|
|
|
|
ny = selmon->w.y;
|
|
|
|
|
|
|
|
else if (abs((selmon->w.y + selmon->w.height) - (ny + grabc->geom.height)) < (int)snap)
|
|
|
|
|
|
|
|
ny = selmon->w.y + selmon->w.height - grabc->geom.height;
|
|
|
|
|
|
|
|
resize(grabc, (struct wlr_box){.x = nx, .y = ny,
|
|
|
|
.width = grabc->geom.width, .height = grabc->geom.height}, 1);
|
|
|
|
.width = grabc->geom.width, .height = grabc->geom.height}, 1);
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
} else if (cursor_mode == CurResize) {
|
|
|
|
} else if (cursor_mode == CurResize) {
|
|
|
@@ -1964,7 +2085,7 @@ motionnotify(uint32_t time, struct wlr_input_device *device, double dx, double d
|
|
|
|
if (!surface && !seat->drag)
|
|
|
|
if (!surface && !seat->drag)
|
|
|
|
wlr_cursor_set_xcursor(cursor, cursor_mgr, "default");
|
|
|
|
wlr_cursor_set_xcursor(cursor, cursor_mgr, "default");
|
|
|
|
|
|
|
|
|
|
|
|
pointerfocus(c, surface, sx, sy, time);
|
|
|
|
pointerfocus(c, l, surface, sx, sy, time);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
void
|
|
|
@@ -2027,49 +2148,61 @@ outputmgrapplyortest(struct wlr_output_configuration_v1 *config, int test)
|
|
|
|
* output_layout.change event, not here.
|
|
|
|
* output_layout.change event, not here.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
struct wlr_output_configuration_head_v1 *config_head;
|
|
|
|
struct wlr_output_configuration_head_v1 *config_head;
|
|
|
|
int ok = 1;
|
|
|
|
size_t states_len, i;
|
|
|
|
|
|
|
|
struct wlr_output_swapchain_manager swapchain_manager;
|
|
|
|
|
|
|
|
struct wlr_backend_output_state *states =
|
|
|
|
|
|
|
|
wlr_output_configuration_v1_build_state(config, &states_len);
|
|
|
|
|
|
|
|
int ok = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!states) {
|
|
|
|
|
|
|
|
wlr_output_configuration_v1_send_failed(config);
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
wlr_output_swapchain_manager_init(&swapchain_manager, backend);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ok = wlr_output_swapchain_manager_prepare(&swapchain_manager, states, states_len);
|
|
|
|
|
|
|
|
if (!ok || test)
|
|
|
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < states_len; i++) {
|
|
|
|
|
|
|
|
struct wlr_swapchain *swapchain = wlr_output_swapchain_manager_get_swapchain(
|
|
|
|
|
|
|
|
&swapchain_manager, states[i].output);
|
|
|
|
|
|
|
|
if (swapchain && !states[i].output->enabled)
|
|
|
|
|
|
|
|
wlr_output_state_set_buffer(&states[i].base, wlr_swapchain_acquire(swapchain));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!(ok = wlr_backend_commit(backend, states, states_len)))
|
|
|
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
wlr_output_swapchain_manager_apply(&swapchain_manager);
|
|
|
|
|
|
|
|
|
|
|
|
wl_list_for_each(config_head, &config->heads, link) {
|
|
|
|
wl_list_for_each(config_head, &config->heads, link) {
|
|
|
|
struct wlr_output *wlr_output = config_head->state.output;
|
|
|
|
struct wlr_output *wlr_output = config_head->state.output;
|
|
|
|
Monitor *m = wlr_output->data;
|
|
|
|
Monitor *m = wlr_output->data;
|
|
|
|
struct wlr_output_state state;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Ensure displays previously disabled by wlr-output-power-management-v1
|
|
|
|
/* Ensure displays previously disabled by wlr-output-power-management-v1
|
|
|
|
* are properly handled*/
|
|
|
|
* are properly handled*/
|
|
|
|
m->asleep = 0;
|
|
|
|
m->asleep = 0;
|
|
|
|
|
|
|
|
|
|
|
|
wlr_output_state_init(&state);
|
|
|
|
|
|
|
|
wlr_output_state_set_enabled(&state, config_head->state.enabled);
|
|
|
|
|
|
|
|
if (!config_head->state.enabled)
|
|
|
|
|
|
|
|
goto apply_or_test;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (config_head->state.mode)
|
|
|
|
|
|
|
|
wlr_output_state_set_mode(&state, config_head->state.mode);
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
wlr_output_state_set_custom_mode(&state,
|
|
|
|
|
|
|
|
config_head->state.custom_mode.width,
|
|
|
|
|
|
|
|
config_head->state.custom_mode.height,
|
|
|
|
|
|
|
|
config_head->state.custom_mode.refresh);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
wlr_output_state_set_transform(&state, config_head->state.transform);
|
|
|
|
|
|
|
|
wlr_output_state_set_scale(&state, config_head->state.scale);
|
|
|
|
|
|
|
|
wlr_output_state_set_adaptive_sync_enabled(&state,
|
|
|
|
|
|
|
|
config_head->state.adaptive_sync_enabled);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
apply_or_test:
|
|
|
|
|
|
|
|
ok &= test ? wlr_output_test_state(wlr_output, &state)
|
|
|
|
|
|
|
|
: wlr_output_commit_state(wlr_output, &state);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Don't move monitors if position wouldn't change. This avoids
|
|
|
|
/* Don't move monitors if position wouldn't change. This avoids
|
|
|
|
* wlroots marking the output as manually configured.
|
|
|
|
* wlroots marking the output as manually configured.
|
|
|
|
* wlr_output_layout_add does not like disabled outputs */
|
|
|
|
* wlr_output_layout_add does not like disabled outputs */
|
|
|
|
if (!test && wlr_output->enabled && (m->m.x != config_head->state.x || m->m.y != config_head->state.y))
|
|
|
|
if (config_head->state.enabled
|
|
|
|
|
|
|
|
&& (m->m.x != config_head->state.x || m->m.y != config_head->state.y
|
|
|
|
|
|
|
|
|| !wlr_output_layout_get(output_layout, wlr_output))) {
|
|
|
|
wlr_output_layout_add(output_layout, wlr_output,
|
|
|
|
wlr_output_layout_add(output_layout, wlr_output,
|
|
|
|
config_head->state.x, config_head->state.y);
|
|
|
|
config_head->state.x, config_head->state.y);
|
|
|
|
|
|
|
|
}
|
|
|
|
wlr_output_state_finish(&state);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
|
|
|
wlr_output_swapchain_manager_finish(&swapchain_manager);
|
|
|
|
|
|
|
|
for (i = 0; i < states_len; i++)
|
|
|
|
|
|
|
|
wlr_output_state_finish(&states[i].base);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
free(states);
|
|
|
|
|
|
|
|
|
|
|
|
if (ok)
|
|
|
|
if (ok)
|
|
|
|
wlr_output_configuration_v1_send_succeeded(config);
|
|
|
|
wlr_output_configuration_v1_send_succeeded(config);
|
|
|
|
else
|
|
|
|
else
|
|
|
@@ -2088,14 +2221,19 @@ outputmgrtest(struct wl_listener *listener, void *data)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
void
|
|
|
|
pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy,
|
|
|
|
pointerfocus(Client *c, LayerSurface *l, struct wlr_surface *surface, double sx, double sy,
|
|
|
|
uint32_t time)
|
|
|
|
uint32_t time)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct timespec now;
|
|
|
|
struct timespec now;
|
|
|
|
|
|
|
|
|
|
|
|
if (surface != seat->pointer_state.focused_surface &&
|
|
|
|
if (surface != seat->pointer_state.focused_surface && sloppyfocus && time) {
|
|
|
|
sloppyfocus && time && c && !client_is_unmanaged(c))
|
|
|
|
if (c && (!client_is_unmanaged(c) || client_wants_focus(c))) {
|
|
|
|
focusclient(c, 0);
|
|
|
|
focusclient(c, 0);
|
|
|
|
|
|
|
|
} else if (l && l->layer_surface->current.keyboard_interactive) {
|
|
|
|
|
|
|
|
focusclient(NULL, 0);
|
|
|
|
|
|
|
|
client_notify_enter(l->layer_surface->surface, wlr_seat_get_keyboard(seat));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* If surface is NULL, clear pointer focus */
|
|
|
|
/* If surface is NULL, clear pointer focus */
|
|
|
|
if (!surface) {
|
|
|
|
if (!surface) {
|
|
|
@@ -2249,9 +2387,7 @@ resize(Client *c, struct wlr_box geo, int interact)
|
|
|
|
wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw);
|
|
|
|
wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw);
|
|
|
|
wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw);
|
|
|
|
wlr_scene_node_set_position(&c->border[3]->node, c->geom.width - c->bw, c->bw);
|
|
|
|
|
|
|
|
|
|
|
|
/* this is a no-op if size hasn't changed */
|
|
|
|
client_set_size(c, c->geom.width - 2 * c->bw, c->geom.height - 2 * c->bw);
|
|
|
|
c->resize = client_set_size(c, c->geom.width - 2 * c->bw,
|
|
|
|
|
|
|
|
c->geom.height - 2 * c->bw);
|
|
|
|
|
|
|
|
client_get_clip(c, &clip);
|
|
|
|
client_get_clip(c, &clip);
|
|
|
|
wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip);
|
|
|
|
wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip);
|
|
|
|
}
|
|
|
|
}
|
|
|
@@ -2583,7 +2719,7 @@ setup(void)
|
|
|
|
wl_signal_add(&xdg_shell->events.new_toplevel, &new_xdg_toplevel);
|
|
|
|
wl_signal_add(&xdg_shell->events.new_toplevel, &new_xdg_toplevel);
|
|
|
|
wl_signal_add(&xdg_shell->events.new_popup, &new_xdg_popup);
|
|
|
|
wl_signal_add(&xdg_shell->events.new_popup, &new_xdg_popup);
|
|
|
|
|
|
|
|
|
|
|
|
layer_shell = wlr_layer_shell_v1_create(dpy, 3);
|
|
|
|
layer_shell = wlr_layer_shell_v1_create(dpy, 4);
|
|
|
|
wl_signal_add(&layer_shell->events.new_surface, &new_layer_surface);
|
|
|
|
wl_signal_add(&layer_shell->events.new_surface, &new_layer_surface);
|
|
|
|
|
|
|
|
|
|
|
|
idle_notifier = wlr_idle_notifier_v1_create(dpy);
|
|
|
|
idle_notifier = wlr_idle_notifier_v1_create(dpy);
|
|
|
@@ -2597,6 +2733,12 @@ setup(void)
|
|
|
|
(float [4]){0.1f, 0.1f, 0.1f, 1.0f});
|
|
|
|
(float [4]){0.1f, 0.1f, 0.1f, 1.0f});
|
|
|
|
wlr_scene_node_set_enabled(&locked_bg->node, 0);
|
|
|
|
wlr_scene_node_set_enabled(&locked_bg->node, 0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreign_toplevel_list = wlr_ext_foreign_toplevel_list_v1_create(dpy,1);
|
|
|
|
|
|
|
|
ext_foreign_toplevel_image_capture_source_manager_v1 =
|
|
|
|
|
|
|
|
wlr_ext_foreign_toplevel_image_capture_source_manager_v1_create(dpy, 1);
|
|
|
|
|
|
|
|
wl_signal_add(&ext_foreign_toplevel_image_capture_source_manager_v1->events.new_request,
|
|
|
|
|
|
|
|
&new_foreign_toplevel_capture_request);
|
|
|
|
|
|
|
|
|
|
|
|
/* Use decoration protocols to negotiate server-side decorations */
|
|
|
|
/* Use decoration protocols to negotiate server-side decorations */
|
|
|
|
wlr_server_decoration_manager_set_default_mode(
|
|
|
|
wlr_server_decoration_manager_set_default_mode(
|
|
|
|
wlr_server_decoration_manager_create(dpy),
|
|
|
|
wlr_server_decoration_manager_create(dpy),
|
|
|
@@ -2672,7 +2814,6 @@ setup(void)
|
|
|
|
|
|
|
|
|
|
|
|
input_method_manager = wlr_input_method_manager_v2_create(dpy);
|
|
|
|
input_method_manager = wlr_input_method_manager_v2_create(dpy);
|
|
|
|
text_input_manager = wlr_text_input_manager_v3_create(dpy);
|
|
|
|
text_input_manager = wlr_text_input_manager_v3_create(dpy);
|
|
|
|
input_method_relay = ecalloc(1, sizeof(*input_method_relay));
|
|
|
|
|
|
|
|
input_method_relay = input_method_relay_create();
|
|
|
|
input_method_relay = input_method_relay_create();
|
|
|
|
|
|
|
|
|
|
|
|
/* Make sure XWayland clients don't connect to the parent X server,
|
|
|
|
/* Make sure XWayland clients don't connect to the parent X server,
|
|
|
@@ -2848,6 +2989,8 @@ unmapnotify(struct wl_listener *listener, void *data)
|
|
|
|
cursor_mode = CurNormal;
|
|
|
|
cursor_mode = CurNormal;
|
|
|
|
grabc = NULL;
|
|
|
|
grabc = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (c == focused_client)
|
|
|
|
|
|
|
|
focused_client = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
if (client_is_unmanaged(c)) {
|
|
|
|
if (client_is_unmanaged(c)) {
|
|
|
|
if (c == exclusive_focus) {
|
|
|
|
if (c == exclusive_focus) {
|
|
|
@@ -2860,6 +3003,20 @@ unmapnotify(struct wl_listener *listener, void *data)
|
|
|
|
wl_list_remove(&c->flink);
|
|
|
|
wl_list_remove(&c->flink);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (c->foreign_toplevel_handle) {
|
|
|
|
|
|
|
|
wlr_ext_foreign_toplevel_handle_v1_destroy(c->foreign_toplevel_handle);
|
|
|
|
|
|
|
|
c->foreign_toplevel_handle = NULL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef XWAYLAND
|
|
|
|
|
|
|
|
if (c->type != XDGShell && c->capture.image_capture_scene_surface) {
|
|
|
|
|
|
|
|
wlr_scene_node_destroy(&c->capture.image_capture_scene_surface->buffer->node);
|
|
|
|
|
|
|
|
c->capture.image_capture_scene_surface = NULL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
wlr_scene_node_destroy(&c->image_capture_scene->tree.node);
|
|
|
|
|
|
|
|
c->image_capture_scene = NULL;
|
|
|
|
|
|
|
|
c->image_capture_source = NULL;
|
|
|
|
wlr_scene_node_destroy(&c->scene->node);
|
|
|
|
wlr_scene_node_destroy(&c->scene->node);
|
|
|
|
client_surface(c)->data = NULL;
|
|
|
|
client_surface(c)->data = NULL;
|
|
|
|
printstatus();
|
|
|
|
printstatus();
|
|
|
@@ -2981,6 +3138,15 @@ updatetitle(struct wl_listener *listener, void *data)
|
|
|
|
Client *c = wl_container_of(listener, c, set_title);
|
|
|
|
Client *c = wl_container_of(listener, c, set_title);
|
|
|
|
if (c == focustop(c->mon))
|
|
|
|
if (c == focustop(c->mon))
|
|
|
|
printstatus();
|
|
|
|
printstatus();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (c->foreign_toplevel_handle) {
|
|
|
|
|
|
|
|
struct wlr_ext_foreign_toplevel_handle_v1_state foreign_toplevel_state = {
|
|
|
|
|
|
|
|
.app_id = client_get_appid(c),
|
|
|
|
|
|
|
|
.title = client_get_title(c),
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
wlr_ext_foreign_toplevel_handle_v1_update_state(c->foreign_toplevel_handle,
|
|
|
|
|
|
|
|
&foreign_toplevel_state);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
void
|
|
|
@@ -3025,6 +3191,7 @@ virtualkeyboard(struct wl_listener *listener, void *data)
|
|
|
|
|
|
|
|
|
|
|
|
/* Add the new keyboard to the group */
|
|
|
|
/* Add the new keyboard to the group */
|
|
|
|
wlr_keyboard_group_add_keyboard(group->wlr_group, &kb->keyboard);
|
|
|
|
wlr_keyboard_group_add_keyboard(group->wlr_group, &kb->keyboard);
|
|
|
|
|
|
|
|
wlr_seat_set_capabilities(seat, seat->capabilities | WL_SEAT_CAPABILITY_KEYBOARD);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
void
|
|
|
@@ -3036,6 +3203,7 @@ virtualpointer(struct wl_listener *listener, void *data)
|
|
|
|
wlr_cursor_attach_input_device(cursor, device);
|
|
|
|
wlr_cursor_attach_input_device(cursor, device);
|
|
|
|
if (event->suggested_output)
|
|
|
|
if (event->suggested_output)
|
|
|
|
wlr_cursor_map_input_to_output(cursor, device, event->suggested_output);
|
|
|
|
wlr_cursor_map_input_to_output(cursor, device, event->suggested_output);
|
|
|
|
|
|
|
|
wlr_seat_set_capabilities(seat, seat->capabilities | WL_SEAT_CAPABILITY_POINTER);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Monitor *
|
|
|
|
Monitor *
|
|
|
@@ -3049,10 +3217,8 @@ void
|
|
|
|
xytonode(double x, double y, struct wlr_surface **psurface,
|
|
|
|
xytonode(double x, double y, struct wlr_surface **psurface,
|
|
|
|
Client **pc, LayerSurface **pl, double *nx, double *ny)
|
|
|
|
Client **pc, LayerSurface **pl, double *nx, double *ny)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct wlr_scene_node *node, *pnode;
|
|
|
|
struct wlr_scene_node *node;
|
|
|
|
struct wlr_surface *surface = NULL;
|
|
|
|
struct wlr_surface *surface = NULL;
|
|
|
|
Client *c = NULL;
|
|
|
|
|
|
|
|
LayerSurface *l = NULL;
|
|
|
|
|
|
|
|
int layer;
|
|
|
|
int layer;
|
|
|
|
|
|
|
|
|
|
|
|
for (layer = NUM_LAYERS - 1; !surface && layer >= 0; layer--) {
|
|
|
|
for (layer = NUM_LAYERS - 1; !surface && layer >= 0; layer--) {
|
|
|
@@ -3063,18 +3229,10 @@ xytonode(double x, double y, struct wlr_surface **psurface,
|
|
|
|
if (node->type == WLR_SCENE_NODE_BUFFER)
|
|
|
|
if (node->type == WLR_SCENE_NODE_BUFFER)
|
|
|
|
surface = wlr_scene_surface_try_from_buffer(
|
|
|
|
surface = wlr_scene_surface_try_from_buffer(
|
|
|
|
wlr_scene_buffer_from_node(node))->surface;
|
|
|
|
wlr_scene_buffer_from_node(node))->surface;
|
|
|
|
/* Walk the tree to find a node that knows the client */
|
|
|
|
|
|
|
|
for (pnode = node; pnode && !c; pnode = &pnode->parent->node)
|
|
|
|
|
|
|
|
c = pnode->data;
|
|
|
|
|
|
|
|
if (c && c->type == LayerShell) {
|
|
|
|
|
|
|
|
c = NULL;
|
|
|
|
|
|
|
|
l = pnode->data;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (psurface) *psurface = surface;
|
|
|
|
if (psurface) *psurface = surface;
|
|
|
|
if (pc) *pc = c;
|
|
|
|
toplevel_from_wlr_surface(surface, pc, pl);
|
|
|
|
if (pl) *pl = l;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
void
|
|
|
@@ -3135,13 +3293,8 @@ configurex11(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Client *c = wl_container_of(listener, c, configure);
|
|
|
|
Client *c = wl_container_of(listener, c, configure);
|
|
|
|
struct wlr_xwayland_surface_configure_event *event = data;
|
|
|
|
struct wlr_xwayland_surface_configure_event *event = data;
|
|
|
|
if (!client_surface(c) || !client_surface(c)->mapped) {
|
|
|
|
if (!client_surface(c) || !client_surface(c)->mapped
|
|
|
|
wlr_xwayland_surface_configure(c->surface.xwayland,
|
|
|
|
|| client_is_unmanaged(c)) {
|
|
|
|
event->x, event->y, event->width, event->height);
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (client_is_unmanaged(c)) {
|
|
|
|
|
|
|
|
wlr_scene_node_set_position(&c->scene->node, event->x, event->y);
|
|
|
|
|
|
|
|
wlr_xwayland_surface_configure(c->surface.xwayland,
|
|
|
|
wlr_xwayland_surface_configure(c->surface.xwayland,
|
|
|
|
event->x, event->y, event->width, event->height);
|
|
|
|
event->x, event->y, event->width, event->height);
|
|
|
|
return;
|
|
|
|
return;
|
|
|
@@ -3174,6 +3327,7 @@ createnotifyx11(struct wl_listener *listener, void *data)
|
|
|
|
LISTEN(&xsurface->events.request_activate, &c->activate, activatex11);
|
|
|
|
LISTEN(&xsurface->events.request_activate, &c->activate, activatex11);
|
|
|
|
LISTEN(&xsurface->events.request_configure, &c->configure, configurex11);
|
|
|
|
LISTEN(&xsurface->events.request_configure, &c->configure, configurex11);
|
|
|
|
LISTEN(&xsurface->events.request_fullscreen, &c->fullscreen, fullscreennotify);
|
|
|
|
LISTEN(&xsurface->events.request_fullscreen, &c->fullscreen, fullscreennotify);
|
|
|
|
|
|
|
|
LISTEN(&xsurface->events.set_geometry, &c->set_geometry, setgeometryx11);
|
|
|
|
LISTEN(&xsurface->events.set_hints, &c->set_hints, sethints);
|
|
|
|
LISTEN(&xsurface->events.set_hints, &c->set_hints, sethints);
|
|
|
|
LISTEN(&xsurface->events.set_title, &c->set_title, updatetitle);
|
|
|
|
LISTEN(&xsurface->events.set_title, &c->set_title, updatetitle);
|
|
|
|
}
|
|
|
|
}
|
|
|
@@ -3186,6 +3340,19 @@ dissociatex11(struct wl_listener *listener, void *data)
|
|
|
|
wl_list_remove(&c->unmap.link);
|
|
|
|
wl_list_remove(&c->unmap.link);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
|
|
setgeometryx11(struct wl_listener *listener, void *data)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
Client *c = wl_container_of(listener, c, set_geometry);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!client_is_unmanaged(c) || !client_surface(c)
|
|
|
|
|
|
|
|
|| !client_surface(c)->mapped)
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
client_get_geometry(c, &c->geom);
|
|
|
|
|
|
|
|
wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
void
|
|
|
|
sethints(struct wl_listener *listener, void *data)
|
|
|
|
sethints(struct wl_listener *listener, void *data)
|
|
|
|
{
|
|
|
|
{
|
|
|
|