Merge branch 'swaywm:master' into drag_mode

This commit is contained in:
hmpthcs 2023-06-30 22:20:13 -04:00 committed by GitHub
commit d4405b7349
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
41 changed files with 734 additions and 472 deletions

View file

@ -267,6 +267,7 @@ sway_cmd input_cmd_scroll_factor;
sway_cmd input_cmd_repeat_delay; sway_cmd input_cmd_repeat_delay;
sway_cmd input_cmd_repeat_rate; sway_cmd input_cmd_repeat_rate;
sway_cmd input_cmd_scroll_button; sway_cmd input_cmd_scroll_button;
sway_cmd input_cmd_scroll_button_lock;
sway_cmd input_cmd_scroll_method; sway_cmd input_cmd_scroll_method;
sway_cmd input_cmd_tap; sway_cmd input_cmd_tap;
sway_cmd input_cmd_tap_button_map; sway_cmd input_cmd_tap_button_map;

View file

@ -161,6 +161,7 @@ struct input_config {
int repeat_delay; int repeat_delay;
int repeat_rate; int repeat_rate;
int scroll_button; int scroll_button;
int scroll_button_lock;
int scroll_method; int scroll_method;
int send_events; int send_events;
int tap; int tap;

View file

@ -2,7 +2,6 @@
#define _SWAY_DESKTOP_IDLE_INHIBIT_V1_H #define _SWAY_DESKTOP_IDLE_INHIBIT_V1_H
#include <wlr/types/wlr_idle_inhibit_v1.h> #include <wlr/types/wlr_idle_inhibit_v1.h>
#include <wlr/types/wlr_idle.h> #include <wlr/types/wlr_idle.h>
#include "sway/server.h"
enum sway_idle_inhibit_mode { enum sway_idle_inhibit_mode {
INHIBIT_IDLE_APPLICATION, // Application set inhibitor (when visible) INHIBIT_IDLE_APPLICATION, // Application set inhibitor (when visible)
@ -16,12 +15,9 @@ struct sway_idle_inhibit_manager_v1 {
struct wlr_idle_inhibit_manager_v1 *wlr_manager; struct wlr_idle_inhibit_manager_v1 *wlr_manager;
struct wl_listener new_idle_inhibitor_v1; struct wl_listener new_idle_inhibitor_v1;
struct wl_list inhibitors; struct wl_list inhibitors;
struct wlr_idle *idle;
}; };
struct sway_idle_inhibitor_v1 { struct sway_idle_inhibitor_v1 {
struct sway_idle_inhibit_manager_v1 *manager;
struct wlr_idle_inhibitor_v1 *wlr_inhibitor; struct wlr_idle_inhibitor_v1 *wlr_inhibitor;
struct sway_view *view; struct sway_view *view;
enum sway_idle_inhibit_mode mode; enum sway_idle_inhibit_mode mode;
@ -33,8 +29,7 @@ struct sway_idle_inhibitor_v1 {
bool sway_idle_inhibit_v1_is_active( bool sway_idle_inhibit_v1_is_active(
struct sway_idle_inhibitor_v1 *inhibitor); struct sway_idle_inhibitor_v1 *inhibitor);
void sway_idle_inhibit_v1_check_active( void sway_idle_inhibit_v1_check_active(void);
struct sway_idle_inhibit_manager_v1 *manager);
void sway_idle_inhibit_v1_user_inhibitor_register(struct sway_view *view, void sway_idle_inhibit_v1_user_inhibitor_register(struct sway_view *view,
enum sway_idle_inhibit_mode mode); enum sway_idle_inhibit_mode mode);
@ -48,6 +43,6 @@ struct sway_idle_inhibitor_v1 *sway_idle_inhibit_v1_application_inhibitor_for_vi
void sway_idle_inhibit_v1_user_inhibitor_destroy( void sway_idle_inhibit_v1_user_inhibitor_destroy(
struct sway_idle_inhibitor_v1 *inhibitor); struct sway_idle_inhibitor_v1 *inhibitor);
struct sway_idle_inhibit_manager_v1 *sway_idle_inhibit_manager_v1_create( bool sway_idle_inhibit_manager_v1_init(void);
struct wl_display *wl_display, struct wlr_idle *idle);
#endif #endif

View file

@ -35,7 +35,6 @@ struct sway_cursor {
pixman_region32_t confine; // invalid if active_constraint == NULL pixman_region32_t confine; // invalid if active_constraint == NULL
bool active_confine_requires_warp; bool active_confine_requires_warp;
struct wlr_pointer_gestures_v1 *pointer_gestures;
struct wl_listener hold_begin; struct wl_listener hold_begin;
struct wl_listener hold_end; struct wl_listener hold_end;
struct wl_listener pinch_begin; struct wl_listener pinch_begin;
@ -53,6 +52,7 @@ struct sway_cursor {
struct wl_listener touch_down; struct wl_listener touch_down;
struct wl_listener touch_up; struct wl_listener touch_up;
struct wl_listener touch_cancel;
struct wl_listener touch_motion; struct wl_listener touch_motion;
struct wl_listener touch_frame; struct wl_listener touch_frame;
bool simulating_pointer_from_touch; bool simulating_pointer_from_touch;

View file

@ -25,6 +25,7 @@ struct sway_input_manager {
struct wlr_keyboard_shortcuts_inhibit_manager_v1 *keyboard_shortcuts_inhibit; struct wlr_keyboard_shortcuts_inhibit_manager_v1 *keyboard_shortcuts_inhibit;
struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard; struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard;
struct wlr_virtual_pointer_manager_v1 *virtual_pointer; struct wlr_virtual_pointer_manager_v1 *virtual_pointer;
struct wlr_pointer_gestures_v1 *pointer_gestures;
struct wl_listener new_input; struct wl_listener new_input;
struct wl_listener inhibit_activate; struct wl_listener inhibit_activate;

View file

@ -12,6 +12,7 @@
#include "sway/input/text_input.h" #include "sway/input/text_input.h"
struct sway_seat; struct sway_seat;
struct render_context;
struct sway_seatop_impl { struct sway_seatop_impl {
void (*button)(struct sway_seat *seat, uint32_t time_msec, void (*button)(struct sway_seat *seat, uint32_t time_msec,
@ -43,14 +44,15 @@ struct sway_seatop_impl {
struct wlr_touch_up_event *event); struct wlr_touch_up_event *event);
void (*touch_down)(struct sway_seat *seat, void (*touch_down)(struct sway_seat *seat,
struct wlr_touch_down_event *event, double lx, double ly); struct wlr_touch_down_event *event, double lx, double ly);
void (*touch_cancel)(struct sway_seat *seat,
struct wlr_touch_cancel_event *event);
void (*tablet_tool_motion)(struct sway_seat *seat, void (*tablet_tool_motion)(struct sway_seat *seat,
struct sway_tablet_tool *tool, uint32_t time_msec); struct sway_tablet_tool *tool, uint32_t time_msec);
void (*tablet_tool_tip)(struct sway_seat *seat, struct sway_tablet_tool *tool, void (*tablet_tool_tip)(struct sway_seat *seat, struct sway_tablet_tool *tool,
uint32_t time_msec, enum wlr_tablet_tool_tip_state state); uint32_t time_msec, enum wlr_tablet_tool_tip_state state);
void (*end)(struct sway_seat *seat); void (*end)(struct sway_seat *seat);
void (*unref)(struct sway_seat *seat, struct sway_container *con); void (*unref)(struct sway_seat *seat, struct sway_container *con);
void (*render)(struct sway_seat *seat, struct sway_output *output, void (*render)(struct sway_seat *seat, struct render_context *ctx);
const pixman_region32_t *damage);
bool allow_set_cursor; bool allow_set_cursor;
}; };
@ -102,8 +104,9 @@ struct sway_seat {
struct sway_workspace *workspace; struct sway_workspace *workspace;
char *prev_workspace_name; // for workspace back_and_forth char *prev_workspace_name; // for workspace back_and_forth
// If the focused layer is set, views cannot receive keyboard focus
struct wlr_layer_surface_v1 *focused_layer; struct wlr_layer_surface_v1 *focused_layer;
// If the exclusive layer is set, views cannot receive keyboard focus
bool has_exclusive_layer;
// If exclusive_client is set, no other clients will receive input events // If exclusive_client is set, no other clients will receive input events
struct wl_client *exclusive_client; struct wl_client *exclusive_client;
@ -338,6 +341,9 @@ void seatop_touch_up(struct sway_seat *seat,
void seatop_touch_down(struct sway_seat *seat, void seatop_touch_down(struct sway_seat *seat,
struct wlr_touch_down_event *event, double lx, double ly); struct wlr_touch_down_event *event, double lx, double ly);
void seatop_touch_cancel(struct sway_seat *seat,
struct wlr_touch_cancel_event *event);
void seatop_rebase(struct sway_seat *seat, uint32_t time_msec); void seatop_rebase(struct sway_seat *seat, uint32_t time_msec);
/** /**
@ -356,8 +362,7 @@ void seatop_unref(struct sway_seat *seat, struct sway_container *con);
* Instructs a seatop to render anything that it needs to render * Instructs a seatop to render anything that it needs to render
* (eg. dropzone for move-tiling) * (eg. dropzone for move-tiling)
*/ */
void seatop_render(struct sway_seat *seat, struct sway_output *output, void seatop_render(struct sway_seat *seat, struct render_context *ctx);
const pixman_region32_t *damage);
bool seatop_allows_set_cursor(struct sway_seat *seat); bool seatop_allows_set_cursor(struct sway_seat *seat);

View file

@ -55,6 +55,10 @@ struct sway_layer_subsurface {
}; };
struct sway_output; struct sway_output;
struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface(
struct wlr_surface *surface);
void arrange_layers(struct sway_output *output); void arrange_layers(struct sway_output *output);
struct sway_layer_surface *layer_from_wlr_layer_surface_v1( struct sway_layer_surface *layer_from_wlr_layer_surface_v1(

View file

@ -57,6 +57,7 @@ struct sway_output {
uint32_t refresh_nsec; uint32_t refresh_nsec;
int max_render_time; // In milliseconds int max_render_time; // In milliseconds
struct wl_event_source *repaint_timer; struct wl_event_source *repaint_timer;
bool gamma_lut_changed;
}; };
struct sway_output_non_desktop { struct sway_output_non_desktop {
@ -65,6 +66,14 @@ struct sway_output_non_desktop {
struct wl_listener destroy; struct wl_listener destroy;
}; };
struct render_context {
struct sway_output *output;
struct wlr_renderer *renderer;
const pixman_region32_t *output_damage;
struct wlr_render_pass *pass;
};
struct sway_output *output_create(struct wlr_output *wlr_output); struct sway_output *output_create(struct wlr_output *wlr_output);
void output_destroy(struct sway_output *output); void output_destroy(struct sway_output *output);
@ -115,7 +124,7 @@ bool output_has_opaque_overlay_layer_surface(struct sway_output *output);
struct sway_workspace *output_get_active_workspace(struct sway_output *output); struct sway_workspace *output_get_active_workspace(struct sway_output *output);
void output_render(struct sway_output *output, pixman_region32_t *damage); void output_render(struct render_context *ctx);
void output_surface_for_each_surface(struct sway_output *output, void output_surface_for_each_surface(struct sway_output *output,
struct wlr_surface *surface, double ox, double oy, struct wlr_surface *surface, double ox, double oy,
@ -168,8 +177,7 @@ void output_get_box(struct sway_output *output, struct wlr_box *box);
enum sway_container_layout output_get_default_layout( enum sway_container_layout output_get_default_layout(
struct sway_output *output); struct sway_output *output);
void render_rect(struct sway_output *output, void render_rect(struct render_context *ctx, const struct wlr_box *_box,
const pixman_region32_t *output_damage, const struct wlr_box *_box,
float color[static 4]); float color[static 4]);
void premultiply_alpha(float color[4], float opacity); void premultiply_alpha(float color[4], float opacity);
@ -180,6 +188,8 @@ enum wlr_direction opposite_direction(enum wlr_direction d);
void handle_output_layout_change(struct wl_listener *listener, void *data); void handle_output_layout_change(struct wl_listener *listener, void *data);
void handle_gamma_control_set_gamma(struct wl_listener *listener, void *data);
void handle_output_manager_apply(struct wl_listener *listener, void *data); void handle_output_manager_apply(struct wl_listener *listener, void *data);
void handle_output_manager_test(struct wl_listener *listener, void *data); void handle_output_manager_test(struct wl_listener *listener, void *data);

View file

@ -21,6 +21,7 @@
#include <wlr/types/wlr_xdg_shell.h> #include <wlr/types/wlr_xdg_shell.h>
#include "config.h" #include "config.h"
#include "list.h" #include "list.h"
#include "sway/desktop/idle_inhibit_v1.h"
#if HAVE_XWAYLAND #if HAVE_XWAYLAND
#include "sway/xwayland.h" #include "sway/xwayland.h"
#endif #endif
@ -53,7 +54,7 @@ struct sway_server {
struct wlr_idle *idle; struct wlr_idle *idle;
struct wlr_idle_notifier_v1 *idle_notifier_v1; struct wlr_idle_notifier_v1 *idle_notifier_v1;
struct sway_idle_inhibit_manager_v1 *idle_inhibit_manager_v1; struct sway_idle_inhibit_manager_v1 idle_inhibit_manager_v1;
struct wlr_layer_shell_v1 *layer_shell; struct wlr_layer_shell_v1 *layer_shell;
struct wl_listener layer_shell_surface; struct wl_listener layer_shell_surface;
@ -91,6 +92,9 @@ struct sway_server {
struct wl_listener output_manager_apply; struct wl_listener output_manager_apply;
struct wl_listener output_manager_test; struct wl_listener output_manager_test;
struct wlr_gamma_control_manager_v1 *gamma_control_manager_v1;
struct wl_listener gamma_control_set_gamma;
struct { struct {
bool locked; bool locked;
struct wlr_session_lock_manager_v1 *manager; struct wlr_session_lock_manager_v1 *manager;

View file

@ -160,6 +160,8 @@ struct sway_xwayland_view {
struct wl_listener set_window_type; struct wl_listener set_window_type;
struct wl_listener set_hints; struct wl_listener set_hints;
struct wl_listener set_decorations; struct wl_listener set_decorations;
struct wl_listener associate;
struct wl_listener dissociate;
struct wl_listener map; struct wl_listener map;
struct wl_listener unmap; struct wl_listener unmap;
struct wl_listener destroy; struct wl_listener destroy;
@ -177,6 +179,8 @@ struct sway_xwayland_unmanaged {
struct wl_listener request_fullscreen; struct wl_listener request_fullscreen;
struct wl_listener commit; struct wl_listener commit;
struct wl_listener set_geometry; struct wl_listener set_geometry;
struct wl_listener associate;
struct wl_listener dissociate;
struct wl_listener map; struct wl_listener map;
struct wl_listener unmap; struct wl_listener unmap;
struct wl_listener destroy; struct wl_listener destroy;

View file

@ -48,7 +48,6 @@ wlroots = dependency('wlroots', version: wlroots_version)
wlroots_features = { wlroots_features = {
'xwayland': false, 'xwayland': false,
'libinput_backend': false, 'libinput_backend': false,
'gles2_renderer': false,
'session': false, 'session': false,
} }
foreach name, _ : wlroots_features foreach name, _ : wlroots_features
@ -75,7 +74,6 @@ pango = dependency('pango')
pangocairo = dependency('pangocairo') pangocairo = dependency('pangocairo')
gdk_pixbuf = dependency('gdk-pixbuf-2.0', required: get_option('gdk-pixbuf')) gdk_pixbuf = dependency('gdk-pixbuf-2.0', required: get_option('gdk-pixbuf'))
pixman = dependency('pixman-1') pixman = dependency('pixman-1')
glesv2 = wlroots_features['gles2_renderer'] ? dependency('glesv2') : null_dep
libevdev = dependency('libevdev') libevdev = dependency('libevdev')
libinput = wlroots_features['libinput_backend'] ? dependency('libinput', version: '>=1.21.0') : null_dep libinput = wlroots_features['libinput_backend'] ? dependency('libinput', version: '>=1.21.0') : null_dep
xcb = dependency('xcb', required: get_option('xwayland')) xcb = dependency('xcb', required: get_option('xwayland'))

View file

@ -41,7 +41,7 @@ struct cmd_results *cmd_inhibit_idle(int argc, char **argv) {
sway_idle_inhibit_v1_user_inhibitor_destroy(inhibitor); sway_idle_inhibit_v1_user_inhibitor_destroy(inhibitor);
} else { } else {
inhibitor->mode = mode; inhibitor->mode = mode;
sway_idle_inhibit_v1_check_active(server.idle_inhibit_manager_v1); sway_idle_inhibit_v1_check_active();
} }
} else if (!clear) { } else if (!clear) {
sway_idle_inhibit_v1_user_inhibitor_register(con->view, mode); sway_idle_inhibit_v1_user_inhibitor_register(con->view, mode);

View file

@ -27,6 +27,7 @@ static const struct cmd_handler input_handlers[] = {
{ "repeat_rate", input_cmd_repeat_rate }, { "repeat_rate", input_cmd_repeat_rate },
{ "rotation_angle", input_cmd_rotation_angle }, { "rotation_angle", input_cmd_rotation_angle },
{ "scroll_button", input_cmd_scroll_button }, { "scroll_button", input_cmd_scroll_button },
{ "scroll_button_lock", input_cmd_scroll_button_lock },
{ "scroll_factor", input_cmd_scroll_factor }, { "scroll_factor", input_cmd_scroll_factor },
{ "scroll_method", input_cmd_scroll_method }, { "scroll_method", input_cmd_scroll_method },
{ "tap", input_cmd_tap }, { "tap", input_cmd_tap },

View file

@ -0,0 +1,26 @@
#include <libinput.h>
#include <string.h>
#include <strings.h>
#include "sway/config.h"
#include "sway/commands.h"
#include "sway/input/input-manager.h"
#include "util.h"
struct cmd_results *input_cmd_scroll_button_lock(int argc, char **argv) {
struct cmd_results *error = NULL;
if ((error = checkarg(argc, "scroll_button_lock", EXPECTED_AT_LEAST, 1))) {
return error;
}
struct input_config *ic = config->handler_context.input_config;
if (!ic) {
return cmd_results_new(CMD_FAILURE, "No input device defined.");
}
if (parse_boolean(argv[0], true)) {
ic->scroll_button_lock = LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_ENABLED;
} else {
ic->scroll_button_lock = LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED;
}
return cmd_results_new(CMD_SUCCESS, NULL);
}

View file

@ -35,6 +35,7 @@ struct input_config *new_input_config(const char* identifier) {
input->pointer_accel = FLT_MIN; input->pointer_accel = FLT_MIN;
input->scroll_factor = FLT_MIN; input->scroll_factor = FLT_MIN;
input->scroll_button = INT_MIN; input->scroll_button = INT_MIN;
input->scroll_button_lock = INT_MIN;
input->scroll_method = INT_MIN; input->scroll_method = INT_MIN;
input->left_handed = INT_MIN; input->left_handed = INT_MIN;
input->repeat_delay = INT_MIN; input->repeat_delay = INT_MIN;
@ -96,6 +97,9 @@ void merge_input_config(struct input_config *dst, struct input_config *src) {
if (src->scroll_button != INT_MIN) { if (src->scroll_button != INT_MIN) {
dst->scroll_button = src->scroll_button; dst->scroll_button = src->scroll_button;
} }
if (src->scroll_button_lock != INT_MIN) {
dst->scroll_button_lock = src->scroll_button_lock;
}
if (src->send_events != INT_MIN) { if (src->send_events != INT_MIN) {
dst->send_events = src->send_events; dst->send_events = src->send_events;
} }

View file

@ -12,7 +12,7 @@
static void destroy_inhibitor(struct sway_idle_inhibitor_v1 *inhibitor) { static void destroy_inhibitor(struct sway_idle_inhibitor_v1 *inhibitor) {
wl_list_remove(&inhibitor->link); wl_list_remove(&inhibitor->link);
wl_list_remove(&inhibitor->destroy.link); wl_list_remove(&inhibitor->destroy.link);
sway_idle_inhibit_v1_check_active(inhibitor->manager); sway_idle_inhibit_v1_check_active();
free(inhibitor); free(inhibitor);
} }
@ -35,7 +35,6 @@ void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data) {
return; return;
} }
inhibitor->manager = manager;
inhibitor->mode = INHIBIT_IDLE_APPLICATION; inhibitor->mode = INHIBIT_IDLE_APPLICATION;
inhibitor->wlr_inhibitor = wlr_inhibitor; inhibitor->wlr_inhibitor = wlr_inhibitor;
wl_list_insert(&manager->inhibitors, &inhibitor->link); wl_list_insert(&manager->inhibitors, &inhibitor->link);
@ -43,33 +42,34 @@ void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data) {
inhibitor->destroy.notify = handle_destroy; inhibitor->destroy.notify = handle_destroy;
wl_signal_add(&wlr_inhibitor->events.destroy, &inhibitor->destroy); wl_signal_add(&wlr_inhibitor->events.destroy, &inhibitor->destroy);
sway_idle_inhibit_v1_check_active(manager); sway_idle_inhibit_v1_check_active();
} }
void sway_idle_inhibit_v1_user_inhibitor_register(struct sway_view *view, void sway_idle_inhibit_v1_user_inhibitor_register(struct sway_view *view,
enum sway_idle_inhibit_mode mode) { enum sway_idle_inhibit_mode mode) {
struct sway_idle_inhibit_manager_v1 *manager = &server.idle_inhibit_manager_v1;
struct sway_idle_inhibitor_v1 *inhibitor = struct sway_idle_inhibitor_v1 *inhibitor =
calloc(1, sizeof(struct sway_idle_inhibitor_v1)); calloc(1, sizeof(struct sway_idle_inhibitor_v1));
if (!inhibitor) { if (!inhibitor) {
return; return;
} }
inhibitor->manager = server.idle_inhibit_manager_v1;
inhibitor->mode = mode; inhibitor->mode = mode;
inhibitor->view = view; inhibitor->view = view;
wl_list_insert(&inhibitor->manager->inhibitors, &inhibitor->link); wl_list_insert(&manager->inhibitors, &inhibitor->link);
inhibitor->destroy.notify = handle_destroy; inhibitor->destroy.notify = handle_destroy;
wl_signal_add(&view->events.unmap, &inhibitor->destroy); wl_signal_add(&view->events.unmap, &inhibitor->destroy);
sway_idle_inhibit_v1_check_active(inhibitor->manager); sway_idle_inhibit_v1_check_active();
} }
struct sway_idle_inhibitor_v1 *sway_idle_inhibit_v1_user_inhibitor_for_view( struct sway_idle_inhibitor_v1 *sway_idle_inhibit_v1_user_inhibitor_for_view(
struct sway_view *view) { struct sway_view *view) {
struct sway_idle_inhibit_manager_v1 *manager = &server.idle_inhibit_manager_v1;
struct sway_idle_inhibitor_v1 *inhibitor; struct sway_idle_inhibitor_v1 *inhibitor;
wl_list_for_each(inhibitor, &server.idle_inhibit_manager_v1->inhibitors, wl_list_for_each(inhibitor, &manager->inhibitors, link) {
link) {
if (inhibitor->mode != INHIBIT_IDLE_APPLICATION && if (inhibitor->mode != INHIBIT_IDLE_APPLICATION &&
inhibitor->view == view) { inhibitor->view == view) {
return inhibitor; return inhibitor;
@ -80,9 +80,9 @@ struct sway_idle_inhibitor_v1 *sway_idle_inhibit_v1_user_inhibitor_for_view(
struct sway_idle_inhibitor_v1 *sway_idle_inhibit_v1_application_inhibitor_for_view( struct sway_idle_inhibitor_v1 *sway_idle_inhibit_v1_application_inhibitor_for_view(
struct sway_view *view) { struct sway_view *view) {
struct sway_idle_inhibit_manager_v1 *manager = &server.idle_inhibit_manager_v1;
struct sway_idle_inhibitor_v1 *inhibitor; struct sway_idle_inhibitor_v1 *inhibitor;
wl_list_for_each(inhibitor, &server.idle_inhibit_manager_v1->inhibitors, wl_list_for_each(inhibitor, &manager->inhibitors, link) {
link) {
if (inhibitor->mode == INHIBIT_IDLE_APPLICATION && if (inhibitor->mode == INHIBIT_IDLE_APPLICATION &&
view_from_wlr_surface(inhibitor->wlr_inhibitor->surface) == view) { view_from_wlr_surface(inhibitor->wlr_inhibitor->surface) == view) {
return inhibitor; return inhibitor;
@ -131,8 +131,8 @@ bool sway_idle_inhibit_v1_is_active(struct sway_idle_inhibitor_v1 *inhibitor) {
return false; return false;
} }
void sway_idle_inhibit_v1_check_active( void sway_idle_inhibit_v1_check_active(void) {
struct sway_idle_inhibit_manager_v1 *manager) { struct sway_idle_inhibit_manager_v1 *manager = &server.idle_inhibit_manager_v1;
struct sway_idle_inhibitor_v1 *inhibitor; struct sway_idle_inhibitor_v1 *inhibitor;
bool inhibited = false; bool inhibited = false;
wl_list_for_each(inhibitor, &manager->inhibitors, link) { wl_list_for_each(inhibitor, &manager->inhibitors, link) {
@ -140,28 +140,22 @@ void sway_idle_inhibit_v1_check_active(
break; break;
} }
} }
wlr_idle_set_enabled(manager->idle, NULL, !inhibited); wlr_idle_set_enabled(server.idle, NULL, !inhibited);
wlr_idle_notifier_v1_set_inhibited(server.idle_notifier_v1, inhibited); wlr_idle_notifier_v1_set_inhibited(server.idle_notifier_v1, inhibited);
} }
struct sway_idle_inhibit_manager_v1 *sway_idle_inhibit_manager_v1_create( bool sway_idle_inhibit_manager_v1_init(void) {
struct wl_display *wl_display, struct wlr_idle *idle) { struct sway_idle_inhibit_manager_v1 *manager = &server.idle_inhibit_manager_v1;
struct sway_idle_inhibit_manager_v1 *manager =
calloc(1, sizeof(struct sway_idle_inhibit_manager_v1)); manager->wlr_manager = wlr_idle_inhibit_v1_create(server.wl_display);
if (!manager) { if (!manager->wlr_manager) {
return NULL; return false;
} }
manager->wlr_manager = wlr_idle_inhibit_v1_create(wl_display);
if (!manager->wlr_manager) {
free(manager);
return NULL;
}
manager->idle = idle;
wl_signal_add(&manager->wlr_manager->events.new_inhibitor, wl_signal_add(&manager->wlr_manager->events.new_inhibitor,
&manager->new_idle_inhibitor_v1); &manager->new_idle_inhibitor_v1);
manager->new_idle_inhibitor_v1.notify = handle_idle_inhibitor_v1; manager->new_idle_inhibitor_v1.notify = handle_idle_inhibitor_v1;
wl_list_init(&manager->inhibitors); wl_list_init(&manager->inhibitors);
return manager; return true;
} }

View file

@ -17,6 +17,39 @@
#include "sway/tree/arrange.h" #include "sway/tree/arrange.h"
#include "sway/tree/workspace.h" #include "sway/tree/workspace.h"
struct wlr_layer_surface_v1 *toplevel_layer_surface_from_surface(
struct wlr_surface *surface) {
struct wlr_layer_surface_v1 *layer;
do {
if (!surface) {
return NULL;
}
// Topmost layer surface
if ((layer = wlr_layer_surface_v1_try_from_wlr_surface(surface))) {
return layer;
}
// Layer subsurface
if (wlr_subsurface_try_from_wlr_surface(surface)) {
surface = wlr_surface_get_root_surface(surface);
continue;
}
// Layer surface popup
struct wlr_xdg_surface * xdg_popup = NULL;
if ((xdg_popup = wlr_xdg_surface_try_from_wlr_surface(surface)) &&
xdg_popup->role == WLR_XDG_SURFACE_ROLE_POPUP) {
if (!xdg_popup->popup->parent) {
return NULL;
}
surface = wlr_surface_get_root_surface(xdg_popup->popup->parent);
continue;
}
// Return early if the surface is not a layer/xdg_popup/sub surface
return NULL;
} while (true);
}
static void apply_exclusive(struct wlr_box *usable_area, static void apply_exclusive(struct wlr_box *usable_area,
uint32_t anchor, int32_t exclusive, uint32_t anchor, int32_t exclusive,
int32_t margin_top, int32_t margin_right, int32_t margin_top, int32_t margin_right,
@ -218,8 +251,9 @@ void arrange_layers(struct sway_output *output) {
for (size_t i = 0; i < nlayers; ++i) { for (size_t i = 0; i < nlayers; ++i) {
wl_list_for_each_reverse(layer, wl_list_for_each_reverse(layer,
&output->layers[layers_above_shell[i]], link) { &output->layers[layers_above_shell[i]], link) {
if (layer->layer_surface->current.keyboard_interactive && if (layer->layer_surface->current.keyboard_interactive
layer->layer_surface->mapped) { == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE &&
layer->layer_surface->surface->mapped) {
topmost = layer; topmost = layer;
break; break;
} }
@ -231,10 +265,12 @@ void arrange_layers(struct sway_output *output) {
struct sway_seat *seat; struct sway_seat *seat;
wl_list_for_each(seat, &server.input->seats, link) { wl_list_for_each(seat, &server.input->seats, link) {
seat->has_exclusive_layer = false;
if (topmost != NULL) { if (topmost != NULL) {
seat_set_focus_layer(seat, topmost->layer_surface); seat_set_focus_layer(seat, topmost->layer_surface);
} else if (seat->focused_layer && } else if (seat->focused_layer &&
!seat->focused_layer->current.keyboard_interactive) { seat->focused_layer->current.keyboard_interactive
!= ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE) {
seat_set_focus_layer(seat, NULL); seat_set_focus_layer(seat, NULL);
} }
} }
@ -253,7 +289,7 @@ static struct sway_layer_surface *find_mapped_layer_by_client(
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], link) { &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], link) {
struct wl_resource *resource = lsurface->layer_surface->resource; struct wl_resource *resource = lsurface->layer_surface->resource;
if (wl_resource_get_client(resource) == client if (wl_resource_get_client(resource) == client
&& lsurface->layer_surface->mapped) { && lsurface->layer_surface->surface->mapped) {
return lsurface; return lsurface;
} }
} }
@ -293,8 +329,8 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) {
bool layer_changed = false; bool layer_changed = false;
if (layer_surface->current.committed != 0 if (layer_surface->current.committed != 0
|| layer->mapped != layer_surface->mapped) { || layer->mapped != layer_surface->surface->mapped) {
layer->mapped = layer_surface->mapped; layer->mapped = layer_surface->surface->mapped;
layer_changed = layer->layer != layer_surface->current.layer; layer_changed = layer->layer != layer_surface->current.layer;
if (layer_changed) { if (layer_changed) {
wl_list_remove(&layer->link); wl_list_remove(&layer->link);
@ -312,6 +348,8 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) {
bool extent_changed = bool extent_changed =
memcmp(&old_extent, &layer->extent, sizeof(struct wlr_box)) != 0; memcmp(&old_extent, &layer->extent, sizeof(struct wlr_box)) != 0;
if (extent_changed || layer_changed) { if (extent_changed || layer_changed) {
old_extent.x += output->lx;
old_extent.y += output->ly;
output_damage_box(output, &old_extent); output_damage_box(output, &old_extent);
output_damage_surface(output, layer->geo.x, layer->geo.y, output_damage_surface(output, layer->geo.x, layer->geo.y,
layer_surface->surface, true); layer_surface->surface, true);
@ -347,7 +385,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
wl_container_of(listener, sway_layer, destroy); wl_container_of(listener, sway_layer, destroy);
sway_log(SWAY_DEBUG, "Layer surface destroyed (%s)", sway_log(SWAY_DEBUG, "Layer surface destroyed (%s)",
sway_layer->layer_surface->namespace); sway_layer->layer_surface->namespace);
if (sway_layer->layer_surface->mapped) { if (sway_layer->layer_surface->surface->mapped) {
unmap(sway_layer); unmap(sway_layer);
} }
@ -452,9 +490,9 @@ static struct sway_layer_subsurface *create_subsurface(
wl_list_insert(&layer_surface->subsurfaces, &subsurface->link); wl_list_insert(&layer_surface->subsurfaces, &subsurface->link);
subsurface->map.notify = subsurface_handle_map; subsurface->map.notify = subsurface_handle_map;
wl_signal_add(&wlr_subsurface->events.map, &subsurface->map); wl_signal_add(&wlr_subsurface->surface->events.map, &subsurface->map);
subsurface->unmap.notify = subsurface_handle_unmap; subsurface->unmap.notify = subsurface_handle_unmap;
wl_signal_add(&wlr_subsurface->events.unmap, &subsurface->unmap); wl_signal_add(&wlr_subsurface->surface->events.unmap, &subsurface->unmap);
subsurface->destroy.notify = subsurface_handle_destroy; subsurface->destroy.notify = subsurface_handle_destroy;
wl_signal_add(&wlr_subsurface->events.destroy, &subsurface->destroy); wl_signal_add(&wlr_subsurface->events.destroy, &subsurface->destroy);
subsurface->commit.notify = subsurface_handle_commit; subsurface->commit.notify = subsurface_handle_commit;
@ -569,9 +607,9 @@ static struct sway_layer_popup *create_popup(struct wlr_xdg_popup *wlr_popup,
popup->parent_layer = parent; popup->parent_layer = parent;
popup->map.notify = popup_handle_map; popup->map.notify = popup_handle_map;
wl_signal_add(&wlr_popup->base->events.map, &popup->map); wl_signal_add(&wlr_popup->base->surface->events.map, &popup->map);
popup->unmap.notify = popup_handle_unmap; popup->unmap.notify = popup_handle_unmap;
wl_signal_add(&wlr_popup->base->events.unmap, &popup->unmap); wl_signal_add(&wlr_popup->base->surface->events.unmap, &popup->unmap);
popup->destroy.notify = popup_handle_destroy; popup->destroy.notify = popup_handle_destroy;
wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy); wl_signal_add(&wlr_popup->base->events.destroy, &popup->destroy);
popup->commit.notify = popup_handle_commit; popup->commit.notify = popup_handle_commit;
@ -659,9 +697,9 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
sway_layer->destroy.notify = handle_destroy; sway_layer->destroy.notify = handle_destroy;
wl_signal_add(&layer_surface->events.destroy, &sway_layer->destroy); wl_signal_add(&layer_surface->events.destroy, &sway_layer->destroy);
sway_layer->map.notify = handle_map; sway_layer->map.notify = handle_map;
wl_signal_add(&layer_surface->events.map, &sway_layer->map); wl_signal_add(&layer_surface->surface->events.map, &sway_layer->map);
sway_layer->unmap.notify = handle_unmap; sway_layer->unmap.notify = handle_unmap;
wl_signal_add(&layer_surface->events.unmap, &sway_layer->unmap); wl_signal_add(&layer_surface->surface->events.unmap, &sway_layer->unmap);
sway_layer->new_popup.notify = handle_new_popup; sway_layer->new_popup.notify = handle_new_popup;
wl_signal_add(&layer_surface->events.new_popup, &sway_layer->new_popup); wl_signal_add(&layer_surface->events.new_popup, &sway_layer->new_popup);
sway_layer->new_subsurface.notify = handle_new_subsurface; sway_layer->new_subsurface.notify = handle_new_subsurface;

View file

@ -6,8 +6,10 @@
#include <wayland-server-core.h> #include <wayland-server-core.h>
#include <wlr/config.h> #include <wlr/config.h>
#include <wlr/backend/headless.h> #include <wlr/backend/headless.h>
#include <wlr/render/swapchain.h>
#include <wlr/render/wlr_renderer.h> #include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_buffer.h> #include <wlr/types/wlr_buffer.h>
#include <wlr/types/wlr_gamma_control_v1.h>
#include <wlr/types/wlr_matrix.h> #include <wlr/types/wlr_matrix.h>
#include <wlr/types/wlr_output_layout.h> #include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_output.h> #include <wlr/types/wlr_output.h>
@ -264,7 +266,7 @@ void output_drag_icons_for_each_surface(struct sway_output *output,
double ox = drag_icon->x - output->lx; double ox = drag_icon->x - output->lx;
double oy = drag_icon->y - output->ly; double oy = drag_icon->y - output->ly;
if (drag_icon->wlr_drag_icon->mapped) { if (drag_icon->wlr_drag_icon->surface->mapped) {
output_surface_for_each_surface(output, output_surface_for_each_surface(output,
drag_icon->wlr_drag_icon->surface, ox, oy, drag_icon->wlr_drag_icon->surface, ox, oy,
iterator, user_data); iterator, user_data);
@ -294,7 +296,7 @@ static void output_for_each_surface(struct sway_output *output,
if (lock_surface->output != output->wlr_output) { if (lock_surface->output != output->wlr_output) {
continue; continue;
} }
if (!lock_surface->mapped) { if (!lock_surface->surface->mapped) {
continue; continue;
} }
@ -456,7 +458,7 @@ static void count_surface_iterator(struct sway_output *output,
} }
static bool scan_out_fullscreen_view(struct sway_output *output, static bool scan_out_fullscreen_view(struct sway_output *output,
struct sway_view *view) { struct wlr_output_state *pending, struct sway_view *view) {
struct wlr_output *wlr_output = output->wlr_output; struct wlr_output *wlr_output = output->wlr_output;
struct sway_workspace *workspace = output->current.active_workspace; struct sway_workspace *workspace = output->current.active_workspace;
if (!sway_assert(workspace, "Expected an active workspace")) { if (!sway_assert(workspace, "Expected an active workspace")) {
@ -522,15 +524,16 @@ static bool scan_out_fullscreen_view(struct sway_output *output,
return false; return false;
} }
wlr_output_attach_buffer(wlr_output, &surface->buffer->base); wlr_output_state_set_buffer(pending, &surface->buffer->base);
if (!wlr_output_test(wlr_output)) {
if (!wlr_output_test_state(wlr_output, pending)) {
return false; return false;
} }
wlr_presentation_surface_sampled_on_output(server.presentation, surface, wlr_presentation_surface_sampled_on_output(server.presentation, surface,
wlr_output); wlr_output);
return wlr_output_commit(wlr_output); return wlr_output_commit_state(wlr_output, pending);
} }
static void get_frame_damage(struct sway_output *output, static void get_frame_damage(struct sway_output *output,
@ -563,6 +566,7 @@ static int output_repaint_timer_handler(void *data) {
wlr_output->frame_pending = false; wlr_output->frame_pending = false;
if (!wlr_output->needs_frame && if (!wlr_output->needs_frame &&
!output->gamma_lut_changed &&
!pixman_region32_not_empty(&output->damage_ring.current)) { !pixman_region32_not_empty(&output->damage_ring.current)) {
return 0; return 0;
} }
@ -577,16 +581,31 @@ static int output_repaint_timer_handler(void *data) {
fullscreen_con = workspace->current.fullscreen; fullscreen_con = workspace->current.fullscreen;
} }
pixman_region32_t frame_damage; struct wlr_output_state pending = {0};
get_frame_damage(output, &frame_damage);
wlr_output_set_damage(wlr_output, &frame_damage); if (output->gamma_lut_changed) {
pixman_region32_fini(&frame_damage); output->gamma_lut_changed = false;
struct wlr_gamma_control_v1 *gamma_control =
wlr_gamma_control_manager_v1_get_control(
server.gamma_control_manager_v1, wlr_output);
if (!wlr_gamma_control_v1_apply(gamma_control, &pending)) {
goto out;
}
if (!wlr_output_test_state(wlr_output, &pending)) {
wlr_output_state_finish(&pending);
pending = (struct wlr_output_state){0};
wlr_gamma_control_v1_send_failed_and_destroy(gamma_control);
}
}
pending.committed |= WLR_OUTPUT_STATE_DAMAGE;
get_frame_damage(output, &pending.damage);
if (fullscreen_con && fullscreen_con->view && !debug.noscanout) { if (fullscreen_con && fullscreen_con->view && !debug.noscanout) {
// Try to scan-out the fullscreen view // Try to scan-out the fullscreen view
static bool last_scanned_out = false; static bool last_scanned_out = false;
bool scanned_out = bool scanned_out =
scan_out_fullscreen_view(output, fullscreen_con->view); scan_out_fullscreen_view(output, &pending, fullscreen_con->view);
if (scanned_out && !last_scanned_out) { if (scanned_out && !last_scanned_out) {
sway_log(SWAY_DEBUG, "Scanning out fullscreen view on %s", sway_log(SWAY_DEBUG, "Scanning out fullscreen view on %s",
@ -600,33 +619,68 @@ static int output_repaint_timer_handler(void *data) {
last_scanned_out = scanned_out; last_scanned_out = scanned_out;
if (scanned_out) { if (scanned_out) {
return 0; goto out;
} }
} }
if (!wlr_output_configure_primary_swapchain(wlr_output, &pending, &wlr_output->swapchain)) {
goto out;
}
int buffer_age; int buffer_age;
if (!wlr_output_attach_render(output->wlr_output, &buffer_age)) { struct wlr_buffer *buffer = wlr_swapchain_acquire(wlr_output->swapchain, &buffer_age);
return 0; if (buffer == NULL) {
goto out;
}
struct wlr_render_pass *render_pass = wlr_renderer_begin_buffer_pass(
wlr_output->renderer, buffer, NULL);
if (render_pass == NULL) {
wlr_buffer_unlock(buffer);
goto out;
} }
pixman_region32_t damage; pixman_region32_t damage;
pixman_region32_init(&damage); pixman_region32_init(&damage);
wlr_damage_ring_get_buffer_damage(&output->damage_ring, buffer_age, &damage); wlr_damage_ring_get_buffer_damage(&output->damage_ring, buffer_age, &damage);
if (debug.damage == DAMAGE_RERENDER) {
int width, height;
wlr_output_transformed_resolution(wlr_output, &width, &height);
pixman_region32_union_rect(&damage, &damage, 0, 0, width, height);
}
struct render_context ctx = {
.output_damage = &damage,
.renderer = wlr_output->renderer,
.output = output,
.pass = render_pass,
};
struct timespec now; struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now); clock_gettime(CLOCK_MONOTONIC, &now);
output_render(output, &damage); output_render(&ctx);
pixman_region32_fini(&damage); pixman_region32_fini(&damage);
if (!wlr_output_commit(wlr_output)) { if (!wlr_render_pass_submit(render_pass)) {
return 0; wlr_buffer_unlock(buffer);
goto out;
}
wlr_output_state_set_buffer(&pending, buffer);
wlr_buffer_unlock(buffer);
if (!wlr_output_commit_state(wlr_output, &pending)) {
goto out;
} }
wlr_damage_ring_rotate(&output->damage_ring); wlr_damage_ring_rotate(&output->damage_ring);
output->last_frame = now; output->last_frame = now;
out:
wlr_output_state_finish(&pending);
return 0; return 0;
} }
@ -1042,6 +1096,21 @@ void handle_output_layout_change(struct wl_listener *listener,
update_output_manager_config(server); update_output_manager_config(server);
} }
void handle_gamma_control_set_gamma(struct wl_listener *listener, void *data) {
struct sway_server *server =
wl_container_of(listener, server, gamma_control_set_gamma);
const struct wlr_gamma_control_manager_v1_set_gamma_event *event = data;
struct sway_output *output = event->output->data;
if(!output) {
return;
}
output->gamma_lut_changed = true;
wlr_output_schedule_frame(output->wlr_output);
}
static void output_manager_apply(struct sway_server *server, static void output_manager_apply(struct sway_server *server,
struct wlr_output_configuration_v1 *config, bool test_only) { struct wlr_output_configuration_v1 *config, bool test_only) {
// TODO: perform atomic tests on the whole backend atomically // TODO: perform atomic tests on the whole backend atomically

File diff suppressed because it is too large Load diff

View file

@ -344,7 +344,7 @@ static void transaction_progress(void) {
server.queued_transaction = NULL; server.queued_transaction = NULL;
if (!server.pending_transaction) { if (!server.pending_transaction) {
sway_idle_inhibit_v1_check_active(server.idle_inhibit_manager_v1); sway_idle_inhibit_v1_check_active();
return; return;
} }

View file

@ -104,8 +104,8 @@ static struct sway_xdg_popup *popup_create(
wl_signal_add(&xdg_surface->events.destroy, &popup->destroy); wl_signal_add(&xdg_surface->events.destroy, &popup->destroy);
popup->destroy.notify = popup_handle_destroy; popup->destroy.notify = popup_handle_destroy;
wl_signal_add(&xdg_surface->events.map, &popup->child.surface_map); wl_signal_add(&xdg_surface->surface->events.map, &popup->child.surface_map);
wl_signal_add(&xdg_surface->events.unmap, &popup->child.surface_unmap); wl_signal_add(&xdg_surface->surface->events.unmap, &popup->child.surface_unmap);
popup_unconstrain(popup); popup_unconstrain(popup);
@ -344,7 +344,7 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data)
struct wlr_xdg_toplevel *toplevel = xdg_shell_view->view.wlr_xdg_toplevel; struct wlr_xdg_toplevel *toplevel = xdg_shell_view->view.wlr_xdg_toplevel;
struct sway_view *view = &xdg_shell_view->view; struct sway_view *view = &xdg_shell_view->view;
if (!toplevel->base->mapped) { if (!toplevel->base->surface->mapped) {
return; return;
} }
@ -529,10 +529,10 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data) {
xdg_shell_view->view.wlr_xdg_toplevel = xdg_surface->toplevel; xdg_shell_view->view.wlr_xdg_toplevel = xdg_surface->toplevel;
xdg_shell_view->map.notify = handle_map; xdg_shell_view->map.notify = handle_map;
wl_signal_add(&xdg_surface->events.map, &xdg_shell_view->map); wl_signal_add(&xdg_surface->surface->events.map, &xdg_shell_view->map);
xdg_shell_view->unmap.notify = handle_unmap; xdg_shell_view->unmap.notify = handle_unmap;
wl_signal_add(&xdg_surface->events.unmap, &xdg_shell_view->unmap); wl_signal_add(&xdg_surface->surface->events.unmap, &xdg_shell_view->unmap);
xdg_shell_view->destroy.notify = handle_destroy; xdg_shell_view->destroy.notify = handle_destroy;
wl_signal_add(&xdg_surface->events.destroy, &xdg_shell_view->destroy); wl_signal_add(&xdg_surface->events.destroy, &xdg_shell_view->destroy);

View file

@ -125,8 +125,10 @@ static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) {
} }
static void unmanaged_handle_request_activate(struct wl_listener *listener, void *data) { static void unmanaged_handle_request_activate(struct wl_listener *listener, void *data) {
struct wlr_xwayland_surface *xsurface = data; struct sway_xwayland_unmanaged *surface =
if (!xsurface->mapped) { wl_container_of(listener, surface, request_activate);
struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface;
if (xsurface->surface == NULL || !xsurface->surface->mapped) {
return; return;
} }
struct sway_seat *seat = input_manager_current_seat(); struct sway_seat *seat = input_manager_current_seat();
@ -138,12 +140,29 @@ static void unmanaged_handle_request_activate(struct wl_listener *listener, void
seat_set_focus_surface(seat, xsurface->surface, false); seat_set_focus_surface(seat, xsurface->surface, false);
} }
static void unmanaged_handle_associate(struct wl_listener *listener, void *data) {
struct sway_xwayland_unmanaged *surface =
wl_container_of(listener, surface, associate);
struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface;
wl_signal_add(&xsurface->surface->events.map, &surface->map);
surface->map.notify = unmanaged_handle_map;
wl_signal_add(&xsurface->surface->events.unmap, &surface->unmap);
surface->unmap.notify = unmanaged_handle_unmap;
}
static void unmanaged_handle_dissociate(struct wl_listener *listener, void *data) {
struct sway_xwayland_unmanaged *surface =
wl_container_of(listener, surface, dissociate);
wl_list_remove(&surface->map.link);
wl_list_remove(&surface->unmap.link);
}
static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) { static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) {
struct sway_xwayland_unmanaged *surface = struct sway_xwayland_unmanaged *surface =
wl_container_of(listener, surface, destroy); wl_container_of(listener, surface, destroy);
wl_list_remove(&surface->request_configure.link); wl_list_remove(&surface->request_configure.link);
wl_list_remove(&surface->map.link); wl_list_remove(&surface->associate.link);
wl_list_remove(&surface->unmap.link); wl_list_remove(&surface->dissociate.link);
wl_list_remove(&surface->destroy.link); wl_list_remove(&surface->destroy.link);
wl_list_remove(&surface->override_redirect.link); wl_list_remove(&surface->override_redirect.link);
wl_list_remove(&surface->request_activate.link); wl_list_remove(&surface->request_activate.link);
@ -159,7 +178,7 @@ static void unmanaged_handle_override_redirect(struct wl_listener *listener, voi
wl_container_of(listener, surface, override_redirect); wl_container_of(listener, surface, override_redirect);
struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface;
bool mapped = xsurface->mapped; bool mapped = xsurface->surface != NULL && xsurface->surface->mapped;
if (mapped) { if (mapped) {
unmanaged_handle_unmap(&surface->unmap, NULL); unmanaged_handle_unmap(&surface->unmap, NULL);
} }
@ -186,10 +205,10 @@ static struct sway_xwayland_unmanaged *create_unmanaged(
wl_signal_add(&xsurface->events.request_configure, wl_signal_add(&xsurface->events.request_configure,
&surface->request_configure); &surface->request_configure);
surface->request_configure.notify = unmanaged_handle_request_configure; surface->request_configure.notify = unmanaged_handle_request_configure;
wl_signal_add(&xsurface->events.map, &surface->map); wl_signal_add(&xsurface->events.associate, &surface->associate);
surface->map.notify = unmanaged_handle_map; surface->associate.notify = unmanaged_handle_associate;
wl_signal_add(&xsurface->events.unmap, &surface->unmap); wl_signal_add(&xsurface->events.dissociate, &surface->dissociate);
surface->unmap.notify = unmanaged_handle_unmap; surface->dissociate.notify = unmanaged_handle_dissociate;
wl_signal_add(&xsurface->events.destroy, &surface->destroy); wl_signal_add(&xsurface->events.destroy, &surface->destroy);
surface->destroy.notify = unmanaged_handle_destroy; surface->destroy.notify = unmanaged_handle_destroy;
wl_signal_add(&xsurface->events.set_override_redirect, &surface->override_redirect); wl_signal_add(&xsurface->events.set_override_redirect, &surface->override_redirect);
@ -472,8 +491,8 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
wl_list_remove(&xwayland_view->set_window_type.link); wl_list_remove(&xwayland_view->set_window_type.link);
wl_list_remove(&xwayland_view->set_hints.link); wl_list_remove(&xwayland_view->set_hints.link);
wl_list_remove(&xwayland_view->set_decorations.link); wl_list_remove(&xwayland_view->set_decorations.link);
wl_list_remove(&xwayland_view->map.link); wl_list_remove(&xwayland_view->associate.link);
wl_list_remove(&xwayland_view->unmap.link); wl_list_remove(&xwayland_view->dissociate.link);
wl_list_remove(&xwayland_view->override_redirect.link); wl_list_remove(&xwayland_view->override_redirect.link);
view_begin_destroy(&xwayland_view->view); view_begin_destroy(&xwayland_view->view);
} }
@ -495,8 +514,8 @@ static void handle_unmap(struct wl_listener *listener, void *data) {
static void handle_map(struct wl_listener *listener, void *data) { static void handle_map(struct wl_listener *listener, void *data) {
struct sway_xwayland_view *xwayland_view = struct sway_xwayland_view *xwayland_view =
wl_container_of(listener, xwayland_view, map); wl_container_of(listener, xwayland_view, map);
struct wlr_xwayland_surface *xsurface = data;
struct sway_view *view = &xwayland_view->view; struct sway_view *view = &xwayland_view->view;
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
view->natural_width = xsurface->width; view->natural_width = xsurface->width;
view->natural_height = xsurface->height; view->natural_height = xsurface->height;
@ -515,10 +534,10 @@ static void handle_map(struct wl_listener *listener, void *data) {
static void handle_override_redirect(struct wl_listener *listener, void *data) { static void handle_override_redirect(struct wl_listener *listener, void *data) {
struct sway_xwayland_view *xwayland_view = struct sway_xwayland_view *xwayland_view =
wl_container_of(listener, xwayland_view, override_redirect); wl_container_of(listener, xwayland_view, override_redirect);
struct wlr_xwayland_surface *xsurface = data;
struct sway_view *view = &xwayland_view->view; struct sway_view *view = &xwayland_view->view;
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
bool mapped = xsurface->mapped; bool mapped = xsurface->surface != NULL && xsurface->surface->mapped;
if (mapped) { if (mapped) {
handle_unmap(&xwayland_view->unmap, NULL); handle_unmap(&xwayland_view->unmap, NULL);
} }
@ -537,7 +556,7 @@ static void handle_request_configure(struct wl_listener *listener, void *data) {
struct wlr_xwayland_surface_configure_event *ev = data; struct wlr_xwayland_surface_configure_event *ev = data;
struct sway_view *view = &xwayland_view->view; struct sway_view *view = &xwayland_view->view;
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
if (!xsurface->mapped) { if (xsurface->surface == NULL || !xsurface->surface->mapped) {
wlr_xwayland_surface_configure(xsurface, ev->x, ev->y, wlr_xwayland_surface_configure(xsurface, ev->x, ev->y,
ev->width, ev->height); ev->width, ev->height);
return; return;
@ -566,7 +585,7 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data)
wl_container_of(listener, xwayland_view, request_fullscreen); wl_container_of(listener, xwayland_view, request_fullscreen);
struct sway_view *view = &xwayland_view->view; struct sway_view *view = &xwayland_view->view;
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
if (!xsurface->mapped) { if (xsurface->surface == NULL || !xsurface->surface->mapped) {
return; return;
} }
container_set_fullscreen(view->container, xsurface->fullscreen); container_set_fullscreen(view->container, xsurface->fullscreen);
@ -580,7 +599,7 @@ static void handle_request_minimize(struct wl_listener *listener, void *data) {
wl_container_of(listener, xwayland_view, request_minimize); wl_container_of(listener, xwayland_view, request_minimize);
struct sway_view *view = &xwayland_view->view; struct sway_view *view = &xwayland_view->view;
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
if (!xsurface->mapped) { if (xsurface->surface == NULL || !xsurface->surface->mapped) {
return; return;
} }
@ -595,7 +614,7 @@ static void handle_request_move(struct wl_listener *listener, void *data) {
wl_container_of(listener, xwayland_view, request_move); wl_container_of(listener, xwayland_view, request_move);
struct sway_view *view = &xwayland_view->view; struct sway_view *view = &xwayland_view->view;
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
if (!xsurface->mapped) { if (xsurface->surface == NULL || !xsurface->surface->mapped) {
return; return;
} }
if (!container_is_floating(view->container) || if (!container_is_floating(view->container) ||
@ -611,7 +630,7 @@ static void handle_request_resize(struct wl_listener *listener, void *data) {
wl_container_of(listener, xwayland_view, request_resize); wl_container_of(listener, xwayland_view, request_resize);
struct sway_view *view = &xwayland_view->view; struct sway_view *view = &xwayland_view->view;
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
if (!xsurface->mapped) { if (xsurface->surface == NULL || !xsurface->surface->mapped) {
return; return;
} }
if (!container_is_floating(view->container)) { if (!container_is_floating(view->container)) {
@ -627,7 +646,7 @@ static void handle_request_activate(struct wl_listener *listener, void *data) {
wl_container_of(listener, xwayland_view, request_activate); wl_container_of(listener, xwayland_view, request_activate);
struct sway_view *view = &xwayland_view->view; struct sway_view *view = &xwayland_view->view;
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
if (!xsurface->mapped) { if (xsurface->surface == NULL || !xsurface->surface->mapped) {
return; return;
} }
view_request_activate(view, NULL); view_request_activate(view, NULL);
@ -640,7 +659,7 @@ static void handle_set_title(struct wl_listener *listener, void *data) {
wl_container_of(listener, xwayland_view, set_title); wl_container_of(listener, xwayland_view, set_title);
struct sway_view *view = &xwayland_view->view; struct sway_view *view = &xwayland_view->view;
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
if (!xsurface->mapped) { if (xsurface->surface == NULL || !xsurface->surface->mapped) {
return; return;
} }
view_update_title(view, false); view_update_title(view, false);
@ -652,7 +671,7 @@ static void handle_set_class(struct wl_listener *listener, void *data) {
wl_container_of(listener, xwayland_view, set_class); wl_container_of(listener, xwayland_view, set_class);
struct sway_view *view = &xwayland_view->view; struct sway_view *view = &xwayland_view->view;
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
if (!xsurface->mapped) { if (xsurface->surface == NULL || !xsurface->surface->mapped) {
return; return;
} }
view_execute_criteria(view); view_execute_criteria(view);
@ -663,7 +682,7 @@ static void handle_set_role(struct wl_listener *listener, void *data) {
wl_container_of(listener, xwayland_view, set_role); wl_container_of(listener, xwayland_view, set_role);
struct sway_view *view = &xwayland_view->view; struct sway_view *view = &xwayland_view->view;
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
if (!xsurface->mapped) { if (xsurface->surface == NULL || !xsurface->surface->mapped) {
return; return;
} }
view_execute_criteria(view); view_execute_criteria(view);
@ -699,7 +718,7 @@ static void handle_set_window_type(struct wl_listener *listener, void *data) {
wl_container_of(listener, xwayland_view, set_window_type); wl_container_of(listener, xwayland_view, set_window_type);
struct sway_view *view = &xwayland_view->view; struct sway_view *view = &xwayland_view->view;
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
if (!xsurface->mapped) { if (xsurface->surface == NULL || !xsurface->surface->mapped) {
return; return;
} }
view_execute_criteria(view); view_execute_criteria(view);
@ -710,7 +729,7 @@ static void handle_set_hints(struct wl_listener *listener, void *data) {
wl_container_of(listener, xwayland_view, set_hints); wl_container_of(listener, xwayland_view, set_hints);
struct sway_view *view = &xwayland_view->view; struct sway_view *view = &xwayland_view->view;
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
if (!xsurface->mapped) { if (xsurface->surface == NULL || !xsurface->surface->mapped) {
return; return;
} }
const bool hints_urgency = xcb_icccm_wm_hints_get_urgency(xsurface->hints); const bool hints_urgency = xcb_icccm_wm_hints_get_urgency(xsurface->hints);
@ -725,6 +744,24 @@ static void handle_set_hints(struct wl_listener *listener, void *data) {
} }
} }
static void handle_associate(struct wl_listener *listener, void *data) {
struct sway_xwayland_view *xwayland_view =
wl_container_of(listener, xwayland_view, associate);
struct wlr_xwayland_surface *xsurface =
xwayland_view->view.wlr_xwayland_surface;
wl_signal_add(&xsurface->surface->events.unmap, &xwayland_view->unmap);
xwayland_view->unmap.notify = handle_unmap;
wl_signal_add(&xsurface->surface->events.map, &xwayland_view->map);
xwayland_view->map.notify = handle_map;
}
static void handle_dissociate(struct wl_listener *listener, void *data) {
struct sway_xwayland_view *xwayland_view =
wl_container_of(listener, xwayland_view, dissociate);
wl_list_remove(&xwayland_view->map.link);
wl_list_remove(&xwayland_view->unmap.link);
}
struct sway_view *view_from_wlr_xwayland_surface( struct sway_view *view_from_wlr_xwayland_surface(
struct wlr_xwayland_surface *xsurface) { struct wlr_xwayland_surface *xsurface) {
return xsurface->data; return xsurface->data;
@ -794,11 +831,11 @@ struct sway_xwayland_view *create_xwayland_view(struct wlr_xwayland_surface *xsu
&xwayland_view->set_decorations); &xwayland_view->set_decorations);
xwayland_view->set_decorations.notify = handle_set_decorations; xwayland_view->set_decorations.notify = handle_set_decorations;
wl_signal_add(&xsurface->events.unmap, &xwayland_view->unmap); wl_signal_add(&xsurface->events.associate, &xwayland_view->associate);
xwayland_view->unmap.notify = handle_unmap; xwayland_view->associate.notify = handle_associate;
wl_signal_add(&xsurface->events.map, &xwayland_view->map); wl_signal_add(&xsurface->events.dissociate, &xwayland_view->dissociate);
xwayland_view->map.notify = handle_map; xwayland_view->dissociate.notify = handle_dissociate;
wl_signal_add(&xsurface->events.set_override_redirect, wl_signal_add(&xsurface->events.set_override_redirect,
&xwayland_view->override_redirect); &xwayland_view->override_redirect);

View file

@ -236,7 +236,7 @@ void cursor_update_image(struct sway_cursor *cursor,
// Try a node's resize edge // Try a node's resize edge
enum wlr_edges edge = find_resize_edge(node->sway_container, NULL, cursor); enum wlr_edges edge = find_resize_edge(node->sway_container, NULL, cursor);
if (edge == WLR_EDGE_NONE) { if (edge == WLR_EDGE_NONE) {
cursor_set_image(cursor, "left_ptr", NULL); cursor_set_image(cursor, "default", NULL);
} else if (container_is_floating(node->sway_container)) { } else if (container_is_floating(node->sway_container)) {
cursor_set_image(cursor, wlr_xcursor_get_resize_name(edge), NULL); cursor_set_image(cursor, wlr_xcursor_get_resize_name(edge), NULL);
} else { } else {
@ -247,12 +247,12 @@ void cursor_update_image(struct sway_cursor *cursor,
} }
} }
} else { } else {
cursor_set_image(cursor, "left_ptr", NULL); cursor_set_image(cursor, "default", NULL);
} }
} }
static void cursor_hide(struct sway_cursor *cursor) { static void cursor_hide(struct sway_cursor *cursor) {
wlr_cursor_set_image(cursor->cursor, NULL, 0, 0, 0, 0, 0, 0); wlr_cursor_unset_image(cursor->cursor);
cursor->hidden = true; cursor->hidden = true;
wlr_seat_pointer_notify_clear_focus(cursor->seat->wlr_seat); wlr_seat_pointer_notify_clear_focus(cursor->seat->wlr_seat);
} }
@ -509,6 +509,24 @@ static void handle_touch_up(struct wl_listener *listener, void *data) {
} }
} }
static void handle_touch_cancel(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_cancel);
struct wlr_touch_cancel_event *event = data;
cursor_handle_activity_from_device(cursor, &event->touch->base);
struct sway_seat *seat = cursor->seat;
if (cursor->simulating_pointer_from_touch) {
if (cursor->pointer_touch_id == cursor->seat->touch_id) {
cursor->pointer_touch_up = true;
dispatch_cursor_button(cursor, &event->touch->base,
event->time_msec, BTN_LEFT, WLR_BUTTON_RELEASED);
}
} else {
seatop_touch_cancel(seat, event);
}
}
static void handle_touch_motion(struct wl_listener *listener, void *data) { static void handle_touch_motion(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = struct sway_cursor *cursor =
wl_container_of(listener, cursor, touch_motion); wl_container_of(listener, cursor, touch_motion);
@ -1050,10 +1068,9 @@ void cursor_set_image(struct sway_cursor *cursor, const char *image,
} }
if (!image) { if (!image) {
wlr_cursor_set_image(cursor->cursor, NULL, 0, 0, 0, 0, 0, 0); wlr_cursor_unset_image(cursor->cursor);
} else if (!current_image || strcmp(current_image, image) != 0) { } else if (!current_image || strcmp(current_image, image) != 0) {
wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager, image, wlr_cursor_set_xcursor(cursor->cursor, cursor->xcursor_manager, image);
cursor->cursor);
} }
} }
@ -1100,6 +1117,7 @@ void sway_cursor_destroy(struct sway_cursor *cursor) {
wl_list_remove(&cursor->frame.link); wl_list_remove(&cursor->frame.link);
wl_list_remove(&cursor->touch_down.link); wl_list_remove(&cursor->touch_down.link);
wl_list_remove(&cursor->touch_up.link); wl_list_remove(&cursor->touch_up.link);
wl_list_remove(&cursor->touch_cancel.link);
wl_list_remove(&cursor->touch_motion.link); wl_list_remove(&cursor->touch_motion.link);
wl_list_remove(&cursor->touch_frame.link); wl_list_remove(&cursor->touch_frame.link);
wl_list_remove(&cursor->tool_axis.link); wl_list_remove(&cursor->tool_axis.link);
@ -1136,9 +1154,6 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) {
wl_list_init(&cursor->image_surface_destroy.link); wl_list_init(&cursor->image_surface_destroy.link);
cursor->image_surface_destroy.notify = handle_image_surface_destroy; cursor->image_surface_destroy.notify = handle_image_surface_destroy;
// gesture events
cursor->pointer_gestures = wlr_pointer_gestures_v1_create(server.wl_display);
wl_signal_add(&wlr_cursor->events.hold_begin, &cursor->hold_begin); wl_signal_add(&wlr_cursor->events.hold_begin, &cursor->hold_begin);
cursor->hold_begin.notify = handle_pointer_hold_begin; cursor->hold_begin.notify = handle_pointer_hold_begin;
wl_signal_add(&wlr_cursor->events.hold_end, &cursor->hold_end); wl_signal_add(&wlr_cursor->events.hold_end, &cursor->hold_end);
@ -1181,6 +1196,9 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) {
wl_signal_add(&wlr_cursor->events.touch_up, &cursor->touch_up); wl_signal_add(&wlr_cursor->events.touch_up, &cursor->touch_up);
cursor->touch_up.notify = handle_touch_up; cursor->touch_up.notify = handle_touch_up;
wl_signal_add(&wlr_cursor->events.touch_cancel, &cursor->touch_cancel);
cursor->touch_cancel.notify = handle_touch_cancel;
wl_signal_add(&wlr_cursor->events.touch_motion, wl_signal_add(&wlr_cursor->events.touch_motion,
&cursor->touch_motion); &cursor->touch_motion);
cursor->touch_motion.notify = handle_touch_motion; cursor->touch_motion.notify = handle_touch_motion;

View file

@ -495,6 +495,8 @@ struct sway_input_manager *input_manager_create(struct sway_server *server) {
wl_signal_add(&input->keyboard_shortcuts_inhibit->events.new_inhibitor, wl_signal_add(&input->keyboard_shortcuts_inhibit->events.new_inhibitor,
&input->keyboard_shortcuts_inhibit_new_inhibitor); &input->keyboard_shortcuts_inhibit_new_inhibitor);
input->pointer_gestures = wlr_pointer_gestures_v1_create(server->wl_display);
return input; return input;
} }
@ -532,6 +534,18 @@ static void retranslate_keysyms(struct input_config *input_config) {
return; return;
} }
} }
for (int i = 0; i < config->input_type_configs->length; ++i) {
struct input_config *ic = config->input_type_configs->items[i];
if (ic->xkb_layout || ic->xkb_file) {
// this is the first config with xkb_layout or xkb_file
if (ic->identifier == input_config->identifier) {
translate_keysyms(ic);
}
return;
}
}
} }
static void input_manager_configure_input( static void input_manager_configure_input(

View file

@ -166,6 +166,18 @@ static bool set_scroll_button(struct libinput_device *dev, uint32_t button) {
return true; return true;
} }
static bool set_scroll_button_lock(struct libinput_device *dev,
enum libinput_config_scroll_button_lock_state lock) {
uint32_t scroll = libinput_device_config_scroll_get_methods(dev);
if ((scroll & ~LIBINPUT_CONFIG_SCROLL_NO_SCROLL) == 0 ||
libinput_device_config_scroll_get_button_lock(dev) == lock) {
return false;
}
sway_log(SWAY_DEBUG, "scroll_set_button_lock(%" PRIu32 ")", lock);
log_status(libinput_device_config_scroll_set_button_lock(dev, lock));
return true;
}
static bool set_dwt(struct libinput_device *device, bool dwt) { static bool set_dwt(struct libinput_device *device, bool dwt) {
if (!libinput_device_config_dwt_is_available(device) || if (!libinput_device_config_dwt_is_available(device) ||
libinput_device_config_dwt_get_enabled(device) == dwt) { libinput_device_config_dwt_get_enabled(device) == dwt) {
@ -276,6 +288,9 @@ bool sway_input_configure_libinput_device(struct sway_input_device *input_device
if (ic->scroll_button != INT_MIN) { if (ic->scroll_button != INT_MIN) {
changed |= set_scroll_button(device, ic->scroll_button); changed |= set_scroll_button(device, ic->scroll_button);
} }
if (ic->scroll_button_lock != INT_MIN) {
changed |= set_scroll_button_lock(device, ic->scroll_button_lock);
}
if (ic->dwt != INT_MIN) { if (ic->dwt != INT_MIN) {
changed |= set_dwt(device, ic->dwt); changed |= set_dwt(device, ic->dwt);
} }

View file

@ -367,7 +367,7 @@ static void handle_new_node(struct wl_listener *listener, void *data) {
} }
static void drag_icon_damage_whole(struct sway_drag_icon *icon) { static void drag_icon_damage_whole(struct sway_drag_icon *icon) {
if (!icon->wlr_drag_icon->mapped) { if (!icon->wlr_drag_icon->surface->mapped) {
return; return;
} }
desktop_damage_surface(icon->wlr_drag_icon->surface, icon->x, icon->y, true); desktop_damage_surface(icon->wlr_drag_icon->surface, icon->x, icon->y, true);
@ -511,9 +511,9 @@ static void handle_start_drag(struct wl_listener *listener, void *data) {
icon->surface_commit.notify = drag_icon_handle_surface_commit; icon->surface_commit.notify = drag_icon_handle_surface_commit;
wl_signal_add(&wlr_drag_icon->surface->events.commit, &icon->surface_commit); wl_signal_add(&wlr_drag_icon->surface->events.commit, &icon->surface_commit);
icon->unmap.notify = drag_icon_handle_unmap; icon->unmap.notify = drag_icon_handle_unmap;
wl_signal_add(&wlr_drag_icon->events.unmap, &icon->unmap); wl_signal_add(&wlr_drag_icon->surface->events.unmap, &icon->unmap);
icon->map.notify = drag_icon_handle_map; icon->map.notify = drag_icon_handle_map;
wl_signal_add(&wlr_drag_icon->events.map, &icon->map); wl_signal_add(&wlr_drag_icon->surface->events.map, &icon->map);
icon->destroy.notify = drag_icon_handle_destroy; icon->destroy.notify = drag_icon_handle_destroy;
wl_signal_add(&wlr_drag_icon->events.destroy, &icon->destroy); wl_signal_add(&wlr_drag_icon->events.destroy, &icon->destroy);
@ -671,7 +671,7 @@ static void seat_update_capabilities(struct sway_seat *seat) {
} else { } else {
wlr_seat_set_capabilities(seat->wlr_seat, caps); wlr_seat_set_capabilities(seat->wlr_seat, caps);
if ((previous_caps & WL_SEAT_CAPABILITY_POINTER) == 0) { if ((previous_caps & WL_SEAT_CAPABILITY_POINTER) == 0) {
cursor_set_image(seat->cursor, "left_ptr", NULL); cursor_set_image(seat->cursor, "default", NULL);
} }
} }
} }
@ -1039,7 +1039,7 @@ void seat_configure_xcursor(struct sway_seat *seat) {
wlr_xcursor_manager_load(server.xwayland.xcursor_manager, 1); wlr_xcursor_manager_load(server.xwayland.xcursor_manager, 1);
struct wlr_xcursor *xcursor = wlr_xcursor_manager_get_xcursor( struct wlr_xcursor *xcursor = wlr_xcursor_manager_get_xcursor(
server.xwayland.xcursor_manager, "left_ptr", 1); server.xwayland.xcursor_manager, "default", 1);
if (xcursor != NULL) { if (xcursor != NULL) {
struct wlr_xcursor_image *image = xcursor->images[0]; struct wlr_xcursor_image *image = xcursor->images[0];
wlr_xwayland_set_cursor( wlr_xwayland_set_cursor(
@ -1082,7 +1082,7 @@ void seat_configure_xcursor(struct sway_seat *seat) {
// Reset the cursor so that we apply it to outputs that just appeared // Reset the cursor so that we apply it to outputs that just appeared
cursor_set_image(seat->cursor, NULL, NULL); cursor_set_image(seat->cursor, NULL, NULL);
cursor_set_image(seat->cursor, "left_ptr", NULL); cursor_set_image(seat->cursor, "default", NULL);
wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x, wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x,
seat->cursor->cursor->y); seat->cursor->cursor->y);
} }
@ -1295,11 +1295,15 @@ static void seat_set_workspace_focus(struct sway_seat *seat, struct sway_node *n
} }
void seat_set_focus(struct sway_seat *seat, struct sway_node *node) { void seat_set_focus(struct sway_seat *seat, struct sway_node *node) {
if (seat->focused_layer) { // Prevents the layer from losing focus if it has keyboard exclusivity
if (seat->has_exclusive_layer) {
struct wlr_layer_surface_v1 *layer = seat->focused_layer; struct wlr_layer_surface_v1 *layer = seat->focused_layer;
seat_set_focus_layer(seat, NULL); seat_set_focus_layer(seat, NULL);
seat_set_workspace_focus(seat, node); seat_set_workspace_focus(seat, node);
seat_set_focus_layer(seat, layer); seat_set_focus_layer(seat, layer);
} else if (seat->focused_layer) {
seat_set_focus_layer(seat, NULL);
seat_set_workspace_focus(seat, node);
} else { } else {
seat_set_workspace_focus(seat, node); seat_set_workspace_focus(seat, node);
} }
@ -1347,14 +1351,20 @@ void seat_set_focus_layer(struct sway_seat *seat,
seat_set_focus(seat, previous); seat_set_focus(seat, previous);
} }
return; return;
} else if (!layer || seat->focused_layer == layer) { } else if (!layer) {
return; return;
} }
assert(layer->mapped); assert(layer->surface->mapped);
seat_set_focus_surface(seat, layer->surface, true); if (layer->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP &&
if (layer->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) { layer->current.keyboard_interactive
seat->focused_layer = layer; == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE) {
seat->has_exclusive_layer = true;
} }
if (seat->focused_layer == layer) {
return;
}
seat_set_focus_surface(seat, layer->surface, true);
seat->focused_layer = layer;
} }
void seat_set_exclusive_client(struct sway_seat *seat, void seat_set_exclusive_client(struct sway_seat *seat,
@ -1638,6 +1648,12 @@ void seatop_touch_down(struct sway_seat *seat, struct wlr_touch_down_event *even
} }
} }
void seatop_touch_cancel(struct sway_seat *seat, struct wlr_touch_cancel_event *event) {
if (seat->seatop_impl->touch_cancel) {
seat->seatop_impl->touch_cancel(seat, event);
}
}
void seatop_tablet_tool_tip(struct sway_seat *seat, void seatop_tablet_tool_tip(struct sway_seat *seat,
struct sway_tablet_tool *tool, uint32_t time_msec, struct sway_tablet_tool *tool, uint32_t time_msec,
enum wlr_tablet_tool_tip_state state) { enum wlr_tablet_tool_tip_state state) {
@ -1726,10 +1742,9 @@ void seatop_end(struct sway_seat *seat) {
seat->seatop_impl = NULL; seat->seatop_impl = NULL;
} }
void seatop_render(struct sway_seat *seat, struct sway_output *output, void seatop_render(struct sway_seat *seat, struct render_context *ctx) {
const pixman_region32_t *damage) {
if (seat->seatop_impl->render) { if (seat->seatop_impl->render) {
seat->seatop_impl->render(seat, output, damage); seat->seatop_impl->render(seat, ctx);
} }
} }

View file

@ -2,6 +2,7 @@
#include <float.h> #include <float.h>
#include <libevdev/libevdev.h> #include <libevdev/libevdev.h>
#include <wlr/types/wlr_cursor.h> #include <wlr/types/wlr_cursor.h>
#include <wlr/types/wlr_subcompositor.h>
#include <wlr/types/wlr_tablet_v2.h> #include <wlr/types/wlr_tablet_v2.h>
#include <wlr/types/wlr_xcursor_manager.h> #include <wlr/types/wlr_xcursor_manager.h>
#include "gesture.h" #include "gesture.h"
@ -9,6 +10,7 @@
#include "sway/input/cursor.h" #include "sway/input/cursor.h"
#include "sway/input/seat.h" #include "sway/input/seat.h"
#include "sway/input/tablet.h" #include "sway/input/tablet.h"
#include "sway/layers.h"
#include "sway/output.h" #include "sway/output.h"
#include "sway/tree/view.h" #include "sway/tree/view.h"
#include "sway/tree/workspace.h" #include "sway/tree/workspace.h"
@ -365,10 +367,9 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
return; return;
} }
// Handle clicking a layer surface // Handle clicking a layer surface and its popups/subsurfaces
struct wlr_layer_surface_v1 *layer; struct wlr_layer_surface_v1 *layer = NULL;
if (surface && if ((layer = toplevel_layer_surface_from_surface(surface))) {
(layer = wlr_layer_surface_v1_try_from_wlr_surface(surface))) {
if (layer->current.keyboard_interactive) { if (layer->current.keyboard_interactive) {
seat_set_focus_layer(seat, layer); seat_set_focus_layer(seat, layer);
transaction_commit_dirty(); transaction_commit_dirty();
@ -545,6 +546,21 @@ static void check_focus_follows_mouse(struct sway_seat *seat,
if (wlr_output == NULL) { if (wlr_output == NULL) {
return; return;
} }
struct wlr_surface *surface = NULL;
double sx, sy;
node_at_coords(seat, seat->cursor->cursor->x, seat->cursor->cursor->y,
&surface, &sx, &sy);
// Focus topmost layer surface
struct wlr_layer_surface_v1 *layer = NULL;
if ((layer = toplevel_layer_surface_from_surface(surface)) &&
layer->current.keyboard_interactive) {
seat_set_focus_layer(seat, layer);
transaction_commit_dirty();
return;
}
struct sway_output *hovered_output = wlr_output->data; struct sway_output *hovered_output = wlr_output->data;
if (focus && hovered_output != node_get_output(focus)) { if (focus && hovered_output != node_get_output(focus)) {
struct sway_workspace *ws = output_get_active_workspace(hovered_output); struct sway_workspace *ws = output_get_active_workspace(hovered_output);
@ -934,7 +950,7 @@ static void handle_hold_begin(struct sway_seat *seat,
// ... otherwise forward to client // ... otherwise forward to client
struct sway_cursor *cursor = seat->cursor; struct sway_cursor *cursor = seat->cursor;
wlr_pointer_gestures_v1_send_hold_begin( wlr_pointer_gestures_v1_send_hold_begin(
cursor->pointer_gestures, cursor->seat->wlr_seat, server.input->pointer_gestures, cursor->seat->wlr_seat,
event->time_msec, event->fingers); event->time_msec, event->fingers);
} }
} }
@ -946,7 +962,7 @@ static void handle_hold_end(struct sway_seat *seat,
if (!gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_HOLD)) { if (!gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_HOLD)) {
struct sway_cursor *cursor = seat->cursor; struct sway_cursor *cursor = seat->cursor;
wlr_pointer_gestures_v1_send_hold_end( wlr_pointer_gestures_v1_send_hold_end(
cursor->pointer_gestures, cursor->seat->wlr_seat, server.input->pointer_gestures, cursor->seat->wlr_seat,
event->time_msec, event->cancelled); event->time_msec, event->cancelled);
return; return;
} }
@ -979,7 +995,7 @@ static void handle_pinch_begin(struct sway_seat *seat,
// ... otherwise forward to client // ... otherwise forward to client
struct sway_cursor *cursor = seat->cursor; struct sway_cursor *cursor = seat->cursor;
wlr_pointer_gestures_v1_send_pinch_begin( wlr_pointer_gestures_v1_send_pinch_begin(
cursor->pointer_gestures, cursor->seat->wlr_seat, server.input->pointer_gestures, cursor->seat->wlr_seat,
event->time_msec, event->fingers); event->time_msec, event->fingers);
} }
} }
@ -995,7 +1011,7 @@ static void handle_pinch_update(struct sway_seat *seat,
// ... otherwise forward to client // ... otherwise forward to client
struct sway_cursor *cursor = seat->cursor; struct sway_cursor *cursor = seat->cursor;
wlr_pointer_gestures_v1_send_pinch_update( wlr_pointer_gestures_v1_send_pinch_update(
cursor->pointer_gestures, server.input->pointer_gestures,
cursor->seat->wlr_seat, cursor->seat->wlr_seat,
event->time_msec, event->dx, event->dy, event->time_msec, event->dx, event->dy,
event->scale, event->rotation); event->scale, event->rotation);
@ -1009,7 +1025,7 @@ static void handle_pinch_end(struct sway_seat *seat,
if (!gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_PINCH)) { if (!gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_PINCH)) {
struct sway_cursor *cursor = seat->cursor; struct sway_cursor *cursor = seat->cursor;
wlr_pointer_gestures_v1_send_pinch_end( wlr_pointer_gestures_v1_send_pinch_end(
cursor->pointer_gestures, cursor->seat->wlr_seat, server.input->pointer_gestures, cursor->seat->wlr_seat,
event->time_msec, event->cancelled); event->time_msec, event->cancelled);
return; return;
} }
@ -1042,7 +1058,7 @@ static void handle_swipe_begin(struct sway_seat *seat,
// ... otherwise forward to client // ... otherwise forward to client
struct sway_cursor *cursor = seat->cursor; struct sway_cursor *cursor = seat->cursor;
wlr_pointer_gestures_v1_send_swipe_begin( wlr_pointer_gestures_v1_send_swipe_begin(
cursor->pointer_gestures, cursor->seat->wlr_seat, server.input->pointer_gestures, cursor->seat->wlr_seat,
event->time_msec, event->fingers); event->time_msec, event->fingers);
} }
} }
@ -1059,7 +1075,7 @@ static void handle_swipe_update(struct sway_seat *seat,
// ... otherwise forward to client // ... otherwise forward to client
struct sway_cursor *cursor = seat->cursor; struct sway_cursor *cursor = seat->cursor;
wlr_pointer_gestures_v1_send_swipe_update( wlr_pointer_gestures_v1_send_swipe_update(
cursor->pointer_gestures, cursor->seat->wlr_seat, server.input->pointer_gestures, cursor->seat->wlr_seat,
event->time_msec, event->dx, event->dy); event->time_msec, event->dx, event->dy);
} }
} }
@ -1070,7 +1086,7 @@ static void handle_swipe_end(struct sway_seat *seat,
struct seatop_default_event *seatop = seat->seatop_data; struct seatop_default_event *seatop = seat->seatop_data;
if (!gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_SWIPE)) { if (!gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_SWIPE)) {
struct sway_cursor *cursor = seat->cursor; struct sway_cursor *cursor = seat->cursor;
wlr_pointer_gestures_v1_send_swipe_end(cursor->pointer_gestures, wlr_pointer_gestures_v1_send_swipe_end(server.input->pointer_gestures,
cursor->seat->wlr_seat, event->time_msec, event->cancelled); cursor->seat->wlr_seat, event->time_msec, event->cancelled);
return; return;
} }

View file

@ -64,11 +64,11 @@ static void handle_touch_up(struct sway_seat *seat,
} }
} }
wlr_seat_touch_notify_up(seat->wlr_seat, event->time_msec, event->touch_id);
if (wl_list_empty(&e->point_events)) { if (wl_list_empty(&e->point_events)) {
seatop_begin_default(seat); seatop_begin_default(seat);
} }
wlr_seat_touch_notify_up(seat->wlr_seat, event->time_msec, event->touch_id);
} }
static void handle_touch_down(struct sway_seat *seat, static void handle_touch_down(struct sway_seat *seat,
@ -104,6 +104,28 @@ static void handle_touch_down(struct sway_seat *seat,
} }
} }
static void handle_touch_cancel(struct sway_seat *seat,
struct wlr_touch_cancel_event *event) {
struct seatop_down_event *e = seat->seatop_data;
struct seatop_touch_point_event *point_event, *tmp;
wl_list_for_each_safe(point_event, tmp, &e->point_events, link) {
if (point_event->touch_id == event->touch_id) {
wl_list_remove(&point_event->link);
free(point_event);
break;
}
}
if (e->surface) {
wlr_seat_touch_notify_cancel(seat->wlr_seat, e->surface);
}
if (wl_list_empty(&e->point_events)) {
seatop_begin_default(seat);
}
}
static void handle_pointer_axis(struct sway_seat *seat, static void handle_pointer_axis(struct sway_seat *seat,
struct wlr_pointer_axis_event *event) { struct wlr_pointer_axis_event *event) {
struct sway_input_device *input_device = struct sway_input_device *input_device =
@ -189,6 +211,7 @@ static const struct sway_seatop_impl seatop_impl = {
.touch_motion = handle_touch_motion, .touch_motion = handle_touch_motion,
.touch_up = handle_touch_up, .touch_up = handle_touch_up,
.touch_down = handle_touch_down, .touch_down = handle_touch_down,
.touch_cancel = handle_touch_cancel,
.unref = handle_unref, .unref = handle_unref,
.end = handle_end, .end = handle_end,
.allow_set_cursor = true, .allow_set_cursor = true,

View file

@ -31,21 +31,20 @@ struct seatop_move_tiling_event {
bool insert_after_target; bool insert_after_target;
}; };
static void handle_render(struct sway_seat *seat, static void handle_render(struct sway_seat *seat, struct render_context *ctx) {
struct sway_output *output, const pixman_region32_t *damage) {
struct seatop_move_tiling_event *e = seat->seatop_data; struct seatop_move_tiling_event *e = seat->seatop_data;
if (!e->threshold_reached) { if (!e->threshold_reached) {
return; return;
} }
if (e->target_node && node_get_output(e->target_node) == output) { if (e->target_node && node_get_output(e->target_node) == ctx->output) {
float color[4]; float color[4];
memcpy(&color, config->border_colors.focused.indicator, memcpy(&color, config->border_colors.focused.indicator,
sizeof(float) * 4); sizeof(float) * 4);
premultiply_alpha(color, 0.5); premultiply_alpha(color, 0.5);
struct wlr_box box; struct wlr_box box;
memcpy(&box, &e->drop_box, sizeof(struct wlr_box)); memcpy(&box, &e->drop_box, sizeof(struct wlr_box));
scale_box(&box, output->wlr_output->scale); scale_box(&box, ctx->output->wlr_output->scale);
render_rect(output, damage, &box, color); render_rect(ctx, &box, color);
} }
} }

View file

@ -1019,6 +1019,17 @@ static json_object *describe_libinput_device(struct libinput_device *device) {
uint32_t button = libinput_device_config_scroll_get_button(device); uint32_t button = libinput_device_config_scroll_get_button(device);
json_object_object_add(object, "scroll_button", json_object_object_add(object, "scroll_button",
json_object_new_int(button)); json_object_new_int(button));
const char *lock = "unknown";
switch (libinput_device_config_scroll_get_button_lock(device)) {
case LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_ENABLED:
lock = "enabled";
break;
case LIBINPUT_CONFIG_SCROLL_BUTTON_LOCK_DISABLED:
lock = "disabled";
break;
}
json_object_object_add(object, "scroll_button_lock",
json_object_new_string(lock));
} }
} }

View file

@ -60,7 +60,7 @@ static void destroy_lock_surface(struct sway_session_lock_surface *surf) {
struct wlr_session_lock_surface_v1 *other; struct wlr_session_lock_surface_v1 *other;
wl_list_for_each(other, &server.session_lock.lock->surfaces, link) { wl_list_for_each(other, &server.session_lock.lock->surfaces, link) {
if (other != surf->lock_surface && other->mapped) { if (other != surf->lock_surface && other->surface->mapped) {
next_focus = other->surface; next_focus = other->surface;
break; break;
} }
@ -104,7 +104,7 @@ static void handle_new_surface(struct wl_listener *listener, void *data) {
surf->surface = lock_surface->surface; surf->surface = lock_surface->surface;
surf->output = output; surf->output = output;
surf->map.notify = handle_surface_map; surf->map.notify = handle_surface_map;
wl_signal_add(&lock_surface->events.map, &surf->map); wl_signal_add(&lock_surface->surface->events.map, &surf->map);
surf->destroy.notify = handle_surface_destroy; surf->destroy.notify = handle_surface_destroy;
wl_signal_add(&lock_surface->events.destroy, &surf->destroy); wl_signal_add(&lock_surface->events.destroy, &surf->destroy);
surf->surface_commit.notify = handle_surface_commit; surf->surface_commit.notify = handle_surface_commit;

View file

@ -172,6 +172,7 @@ sway_sources = files(
'commands/input/repeat_delay.c', 'commands/input/repeat_delay.c',
'commands/input/repeat_rate.c', 'commands/input/repeat_rate.c',
'commands/input/scroll_button.c', 'commands/input/scroll_button.c',
'commands/input/scroll_button_lock.c',
'commands/input/scroll_factor.c', 'commands/input/scroll_factor.c',
'commands/input/scroll_method.c', 'commands/input/scroll_method.c',
'commands/input/tap.c', 'commands/input/tap.c',
@ -223,7 +224,6 @@ sway_deps = [
math, math,
pango, pango,
pcre2, pcre2,
glesv2,
pixman, pixman,
threads, threads,
wayland_server, wayland_server,

View file

@ -55,7 +55,7 @@
#endif #endif
#define SWAY_XDG_SHELL_VERSION 2 #define SWAY_XDG_SHELL_VERSION 2
#define SWAY_LAYER_SHELL_VERSION 3 #define SWAY_LAYER_SHELL_VERSION 4
#if WLR_HAS_DRM_BACKEND #if WLR_HAS_DRM_BACKEND
static void handle_drm_lease_request(struct wl_listener *listener, void *data) { static void handle_drm_lease_request(struct wl_listener *listener, void *data) {
@ -114,7 +114,11 @@ bool server_init(struct sway_server *server) {
server->data_device_manager = server->data_device_manager =
wlr_data_device_manager_create(server->wl_display); wlr_data_device_manager_create(server->wl_display);
server->gamma_control_manager_v1 =
wlr_gamma_control_manager_v1_create(server->wl_display); wlr_gamma_control_manager_v1_create(server->wl_display);
server->gamma_control_set_gamma.notify = handle_gamma_control_set_gamma;
wl_signal_add(&server->gamma_control_manager_v1->events.set_gamma,
&server->gamma_control_set_gamma);
server->new_output.notify = handle_new_output; server->new_output.notify = handle_new_output;
wl_signal_add(&server->backend->events.new_output, &server->new_output); wl_signal_add(&server->backend->events.new_output, &server->new_output);
@ -126,8 +130,7 @@ bool server_init(struct sway_server *server) {
server->idle = wlr_idle_create(server->wl_display); server->idle = wlr_idle_create(server->wl_display);
server->idle_notifier_v1 = wlr_idle_notifier_v1_create(server->wl_display); server->idle_notifier_v1 = wlr_idle_notifier_v1_create(server->wl_display);
server->idle_inhibit_manager_v1 = sway_idle_inhibit_manager_v1_init();
sway_idle_inhibit_manager_v1_create(server->wl_display, server->idle);
server->layer_shell = wlr_layer_shell_v1_create(server->wl_display, server->layer_shell = wlr_layer_shell_v1_create(server->wl_display,
SWAY_LAYER_SHELL_VERSION); SWAY_LAYER_SHELL_VERSION);

View file

@ -185,6 +185,9 @@ The following commands may only be used in the configuration file.
debug-events*, or as a x11 mouse button (button[1-3,8,9]). If set to debug-events*, or as a x11 mouse button (button[1-3,8,9]). If set to
_disable_, it disables the scroll_method on_button_down. _disable_, it disables the scroll_method on_button_down.
*input* <identifier> scroll_button_lock enabled|disabled
Enables or disables scroll button lock for specified input device.
*input* <identifier> scroll_factor <floating point value> *input* <identifier> scroll_factor <floating point value>
Changes the scroll factor for the specified input device. Scroll speed will Changes the scroll factor for the specified input device. Scroll speed will
be scaled by the given value, which must be non-negative. be scaled by the given value, which must be non-negative.

View file

@ -1195,6 +1195,9 @@ following properties will be included for devices that support them:
: int : int
: The scroll button to use when _scroll_method_ is _on_button_down_. This : The scroll button to use when _scroll_method_ is _on_button_down_. This
will be given as an input event code will be given as an input event code
|- scroll_button_lock
: string
: Whether scroll button lock is enabled. It can be _enabled_ or _disabled_
|- dwt |- dwt
: string : string
: Whether disable-while-typing is enabled. It can be _enabled_ or _disabled_ : Whether disable-while-typing is enabled. It can be _enabled_ or _disabled_

View file

@ -389,8 +389,8 @@ runtime.
for_window <criteria> move container to output <output> for_window <criteria> move container to output <output>
*bindsym* [--whole-window] [--border] [--exclude-titlebar] [--release] [--locked] \ *bindsym* [--whole-window] [--border] [--exclude-titlebar] [--release] [--locked] \
[--to-code] [--input-device=<device>] [--no-warn] [--no-repeat] [Group<1-4>+]<key combo> \ [--to-code] [--input-device=<device>] [--no-warn] [--no-repeat] [--inhibited] \
<command> [Group<1-4>+]<key combo> <command>
Binds _key combo_ to execute the sway command _command_ when pressed. You Binds _key combo_ to execute the sway command _command_ when pressed. You
may use XKB key names here (*wev*(1) is a good tool for discovering these). may use XKB key names here (*wev*(1) is a good tool for discovering these).
With the flag _--release_, the command is executed when the key combo is With the flag _--release_, the command is executed when the key combo is
@ -454,7 +454,8 @@ runtime.
``` ```
*bindcode* [--whole-window] [--border] [--exclude-titlebar] [--release] \ *bindcode* [--whole-window] [--border] [--exclude-titlebar] [--release] \
[--locked] [--input-device=<device>] [--no-warn] [Group<1-4>+]<code> <command> [--locked] [--input-device=<device>] [--no-warn] [--no-repeat] [--inhibited] \
[Group<1-4>+]<code> <command>
is also available for binding with key/button codes instead of key/button names. is also available for binding with key/button codes instead of key/button names.
*bindswitch* [--locked] [--no-warn] [--reload] <switch>:<state> <command> *bindswitch* [--locked] [--no-warn] [--reload] <switch>:<state> <command>

View file

@ -17,7 +17,7 @@ void xdg_activation_v1_handle_request_activate(struct wl_listener *listener,
return; return;
} }
if (!xdg_surface->mapped) { if (!xdg_surface->surface->mapped) {
// This is a startup notification. If we are tracking it, the data // This is a startup notification. If we are tracking it, the data
// field is a launcher_ctx. // field is a launcher_ctx.
struct launcher_ctx *ctx = event->token->data; struct launcher_ctx *ctx = event->token->data;

View file

@ -82,7 +82,7 @@ void update_cursor(struct swaybar_seat *seat) {
pointer->cursor_theme = wl_cursor_theme_load( pointer->cursor_theme = wl_cursor_theme_load(
cursor_theme, cursor_size * scale, seat->bar->shm); cursor_theme, cursor_size * scale, seat->bar->shm);
struct wl_cursor *cursor; struct wl_cursor *cursor;
cursor = wl_cursor_theme_get_cursor(pointer->cursor_theme, "left_ptr"); cursor = wl_cursor_theme_get_cursor(pointer->cursor_theme, "default");
pointer->cursor_image = cursor->images[0]; pointer->cursor_image = cursor->images[0];
wl_surface_set_buffer_scale(pointer->cursor_surface, scale); wl_surface_set_buffer_scale(pointer->cursor_surface, scale);
wl_surface_attach(pointer->cursor_surface, wl_surface_attach(pointer->cursor_surface,
@ -207,7 +207,7 @@ static void workspace_next(struct swaybar *bar, struct swaybar_output *output,
} }
} }
if (new) { if (new && new != active) {
ipc_send_workspace_command(bar, new->name); ipc_send_workspace_command(bar, new->name);
// Since we're asking Sway to switch to 'new', it should become visible. // Since we're asking Sway to switch to 'new', it should become visible.

View file

@ -426,12 +426,9 @@ bool ipc_initialize(struct swaybar *bar) {
} }
free(res); free(res);
struct swaybar_config *config = bar->config; char *subscribe =
char subscribe[128]; // suitably large buffer "[ \"barconfig_update\", \"bar_state_update\", \"mode\", \"workspace\" ]";
len = snprintf(subscribe, 128, len = strlen(subscribe);
"[ \"barconfig_update\" , \"bar_state_update\" %s %s ]",
config->binding_mode_indicator ? ", \"mode\"" : "",
config->workspace_buttons ? ", \"workspace\"" : "");
free(ipc_single_command(bar->ipc_event_socketfd, free(ipc_single_command(bar->ipc_event_socketfd,
IPC_SUBSCRIBE, subscribe, &len)); IPC_SUBSCRIBE, subscribe, &len));
return true; return true;

View file

@ -106,7 +106,7 @@ static int register_host(sd_bus_message *msg, void *data, sd_bus_error *error) {
sway_log(SWAY_DEBUG, "Registering Status Notifier Host '%s'", service); sway_log(SWAY_DEBUG, "Registering Status Notifier Host '%s'", service);
list_add(watcher->hosts, strdup(service)); list_add(watcher->hosts, strdup(service));
sd_bus_emit_signal(watcher->bus, obj_path, watcher->interface, sd_bus_emit_signal(watcher->bus, obj_path, watcher->interface,
"StatusNotifierHostRegistered", "s", service); "StatusNotifierHostRegistered", "");
} else { } else {
sway_log(SWAY_DEBUG, "Status Notifier Host '%s' already registered", service); sway_log(SWAY_DEBUG, "Status Notifier Host '%s' already registered", service);
} }

View file

@ -154,7 +154,7 @@ static void update_cursor(struct swaynag_seat *seat) {
pointer->cursor_theme = wl_cursor_theme_load( pointer->cursor_theme = wl_cursor_theme_load(
cursor_theme, cursor_size * swaynag->scale, swaynag->shm); cursor_theme, cursor_size * swaynag->scale, swaynag->shm);
struct wl_cursor *cursor = struct wl_cursor *cursor =
wl_cursor_theme_get_cursor(pointer->cursor_theme, "left_ptr"); wl_cursor_theme_get_cursor(pointer->cursor_theme, "default");
pointer->cursor_image = cursor->images[0]; pointer->cursor_image = cursor->images[0];
wl_surface_set_buffer_scale(pointer->cursor_surface, wl_surface_set_buffer_scale(pointer->cursor_surface,
swaynag->scale); swaynag->scale);