Merge branch 'master' into disable_titlebar

This commit is contained in:
neuromagus 2024-07-12 21:49:18 +03:00 committed by GitHub
commit f8461bfe6d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
58 changed files with 467 additions and 167 deletions

View file

@ -4,6 +4,7 @@ packages:
- eudev-dev - eudev-dev
- gdk-pixbuf-dev - gdk-pixbuf-dev
- json-c-dev - json-c-dev
- lcms2-dev
- libdisplay-info-dev - libdisplay-info-dev
- libevdev-dev - libevdev-dev
- libinput-dev - libinput-dev
@ -38,9 +39,14 @@ tasks:
cd sway cd sway
ninja -C build ninja -C build
- build-no-xwayland: | - build-no-xwayland: |
cd sway cd wlroots
meson configure build -Dxwayland=disabled meson configure build -Dxwayland=disabled
ninja -C build ninja -C build
sudo ninja -C build install
cd ../sway
meson configure build --clearcache
ninja -C build
- build-static: | - build-static: |
cd sway cd sway
mkdir subprojects mkdir subprojects

View file

@ -3,6 +3,7 @@ packages:
- cairo - cairo
- gdk-pixbuf2 - gdk-pixbuf2
- json-c - json-c
- lcms2
- libdisplay-info - libdisplay-info
- libegl - libegl
- libinput - libinput

View file

@ -8,6 +8,7 @@ packages:
- devel/pkgconf - devel/pkgconf
- graphics/cairo - graphics/cairo
- graphics/gdk-pixbuf2 - graphics/gdk-pixbuf2
- graphics/lcms2
- graphics/wayland - graphics/wayland
- graphics/wayland-protocols - graphics/wayland-protocols
- textproc/scdoc - textproc/scdoc

View file

@ -53,6 +53,8 @@ size_t escape_markup_text(const char *src, char *dest) {
PangoLayout *get_pango_layout(cairo_t *cairo, const PangoFontDescription *desc, PangoLayout *get_pango_layout(cairo_t *cairo, const PangoFontDescription *desc,
const char *text, double scale, bool markup) { const char *text, double scale, bool markup) {
PangoLayout *layout = pango_cairo_create_layout(cairo); PangoLayout *layout = pango_cairo_create_layout(cairo);
pango_context_set_round_glyph_positions(pango_layout_get_context(layout), false);
PangoAttrList *attrs; PangoAttrList *attrs;
if (markup) { if (markup) {
char *buf; char *buf;
@ -104,6 +106,7 @@ void get_text_size(cairo_t *cairo, const PangoFontDescription *desc, int *width,
void get_text_metrics(const PangoFontDescription *description, int *height, int *baseline) { void get_text_metrics(const PangoFontDescription *description, int *height, int *baseline) {
cairo_t *cairo = cairo_create(NULL); cairo_t *cairo = cairo_create(NULL);
PangoContext *pango = pango_cairo_create_context(cairo); PangoContext *pango = pango_cairo_create_context(cairo);
pango_context_set_round_glyph_positions(pango, false);
// When passing NULL as a language, pango uses the current locale. // When passing NULL as a language, pango uses the current locale.
PangoFontMetrics *metrics = pango_context_get_metrics(pango, description, NULL); PangoFontMetrics *metrics = pango_context_get_metrics(pango, description, NULL);

View file

@ -250,6 +250,7 @@ sway_cmd input_cmd_seat;
sway_cmd input_cmd_accel_profile; sway_cmd input_cmd_accel_profile;
sway_cmd input_cmd_calibration_matrix; sway_cmd input_cmd_calibration_matrix;
sway_cmd input_cmd_click_method; sway_cmd input_cmd_click_method;
sway_cmd input_cmd_clickfinger_button_map;
sway_cmd input_cmd_drag; sway_cmd input_cmd_drag;
sway_cmd input_cmd_drag_lock; sway_cmd input_cmd_drag_lock;
sway_cmd input_cmd_dwt; sway_cmd input_cmd_dwt;
@ -284,6 +285,7 @@ sway_cmd input_cmd_xkb_variant;
sway_cmd output_cmd_adaptive_sync; sway_cmd output_cmd_adaptive_sync;
sway_cmd output_cmd_background; sway_cmd output_cmd_background;
sway_cmd output_cmd_color_profile;
sway_cmd output_cmd_disable; sway_cmd output_cmd_disable;
sway_cmd output_cmd_dpms; sway_cmd output_cmd_dpms;
sway_cmd output_cmd_enable; sway_cmd output_cmd_enable;

View file

@ -7,6 +7,7 @@
#include <wlr/interfaces/wlr_switch.h> #include <wlr/interfaces/wlr_switch.h>
#include <wlr/types/wlr_tablet_tool.h> #include <wlr/types/wlr_tablet_tool.h>
#include <wlr/util/box.h> #include <wlr/util/box.h>
#include <wlr/render/color.h>
#include <xkbcommon/xkbcommon.h> #include <xkbcommon/xkbcommon.h>
#include <xf86drmMode.h> #include <xf86drmMode.h>
#include "../include/config.h" #include "../include/config.h"
@ -148,6 +149,7 @@ struct input_config {
int accel_profile; int accel_profile;
struct calibration_matrix calibration_matrix; struct calibration_matrix calibration_matrix;
int click_method; int click_method;
int clickfinger_button_map;
int drag; int drag;
int drag_lock; int drag_lock;
int dwt; int dwt;
@ -285,6 +287,8 @@ struct output_config {
int max_render_time; // In milliseconds int max_render_time; // In milliseconds
int adaptive_sync; int adaptive_sync;
enum render_bit_depth render_bit_depth; enum render_bit_depth render_bit_depth;
bool set_color_transform;
struct wlr_color_transform *color_transform;
char *background; char *background;
char *background_option; char *background_option;

View file

@ -7,6 +7,10 @@
#include "list.h" #include "list.h"
#include "tree/view.h" #include "tree/view.h"
#if WLR_HAS_XWAYLAND
#include "sway/xwayland.h"
#endif
enum criteria_type { enum criteria_type {
CT_COMMAND = 1 << 0, CT_COMMAND = 1 << 0,
CT_ASSIGN_OUTPUT = 1 << 1, CT_ASSIGN_OUTPUT = 1 << 1,
@ -36,7 +40,7 @@ struct criteria {
struct pattern *app_id; struct pattern *app_id;
struct pattern *con_mark; struct pattern *con_mark;
uint32_t con_id; // internal ID uint32_t con_id; // internal ID
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
struct pattern *class; struct pattern *class;
uint32_t id; // X11 window ID uint32_t id; // X11 window ID
struct pattern *instance; struct pattern *instance;

View file

@ -5,10 +5,11 @@
#include <wlr/types/wlr_virtual_keyboard_v1.h> #include <wlr/types/wlr_virtual_keyboard_v1.h>
#include <wlr/types/wlr_virtual_pointer_v1.h> #include <wlr/types/wlr_virtual_pointer_v1.h>
#include <wlr/types/wlr_transient_seat_v1.h> #include <wlr/types/wlr_transient_seat_v1.h>
#include "sway/server.h"
#include "sway/config.h" #include "sway/config.h"
#include "list.h" #include "list.h"
struct sway_server;
struct sway_input_device { struct sway_input_device {
char *identifier; char *identifier;
struct wlr_input_device *wlr_device; struct wlr_input_device *wlr_device;

View file

@ -66,6 +66,8 @@ struct sway_output {
struct wl_signal disable; struct wl_signal disable;
} events; } events;
struct wlr_color_transform *color_transform;
struct timespec last_presentation; struct timespec last_presentation;
uint32_t refresh_nsec; uint32_t refresh_nsec;
int max_render_time; // In milliseconds int max_render_time; // In milliseconds

View file

@ -5,7 +5,7 @@
#include "config.h" #include "config.h"
#include "list.h" #include "list.h"
#include "sway/desktop/idle_inhibit_v1.h" #include "sway/desktop/idle_inhibit_v1.h"
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
#include "sway/xwayland.h" #include "sway/xwayland.h"
#endif #endif
@ -59,7 +59,7 @@ struct sway_server {
struct wlr_tablet_manager_v2 *tablet_v2; struct wlr_tablet_manager_v2 *tablet_v2;
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
struct sway_xwayland xwayland; struct sway_xwayland xwayland;
struct wl_listener xwayland_surface; struct wl_listener xwayland_surface;
struct wl_listener xwayland_ready; struct wl_listener xwayland_ready;
@ -81,6 +81,8 @@ struct sway_server {
struct wlr_pointer_constraints_v1 *pointer_constraints; struct wlr_pointer_constraints_v1 *pointer_constraints;
struct wl_listener pointer_constraint; struct wl_listener pointer_constraint;
struct wlr_xdg_output_manager_v1 *xdg_output_manager_v1;
struct wlr_output_manager_v1 *output_manager_v1; struct wlr_output_manager_v1 *output_manager_v1;
struct wl_listener output_manager_apply; struct wl_listener output_manager_apply;
struct wl_listener output_manager_test; struct wl_listener output_manager_test;
@ -133,6 +135,8 @@ struct sway_server {
// Stores the nodes that have been marked as "dirty" and will be put into // Stores the nodes that have been marked as "dirty" and will be put into
// the pending transaction. // the pending transaction.
list_t *dirty_nodes; list_t *dirty_nodes;
struct wl_event_source *delayed_modeset;
}; };
extern struct sway_server server; extern struct sway_server server;
@ -165,7 +169,7 @@ void sway_session_lock_add_output(struct sway_session_lock *lock,
bool sway_session_lock_has_surface(struct sway_session_lock *lock, bool sway_session_lock_has_surface(struct sway_session_lock *lock,
struct wlr_surface *surface); struct wlr_surface *surface);
void handle_xdg_shell_toplevel(struct wl_listener *listener, void *data); void handle_xdg_shell_toplevel(struct wl_listener *listener, void *data);
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
void handle_xwayland_surface(struct wl_listener *listener, void *data); void handle_xwayland_surface(struct wl_listener *listener, void *data);
#endif #endif
void handle_server_decoration(struct wl_listener *listener, void *data); void handle_server_decoration(struct wl_listener *listener, void *data);

View file

@ -175,8 +175,6 @@ struct sway_container *container_obstructing_fullscreen_container(struct sway_co
bool container_has_ancestor(struct sway_container *container, bool container_has_ancestor(struct sway_container *container,
struct sway_container *ancestor); struct sway_container *ancestor);
void container_update_textures_recursive(struct sway_container *con);
void container_reap_empty(struct sway_container *con); void container_reap_empty(struct sway_container *con);
struct sway_container *container_flatten(struct sway_container *container); struct sway_container *container_flatten(struct sway_container *container);

View file

@ -2,12 +2,12 @@
#define _SWAY_ROOT_H #define _SWAY_ROOT_H
#include <wayland-server-core.h> #include <wayland-server-core.h>
#include <wayland-util.h> #include <wayland-util.h>
#include <wlr/config.h>
#include <wlr/types/wlr_output_layout.h> #include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_scene.h> #include <wlr/types/wlr_scene.h>
#include <wlr/render/wlr_texture.h> #include <wlr/render/wlr_texture.h>
#include "sway/tree/container.h" #include "sway/tree/container.h"
#include "sway/tree/node.h" #include "sway/tree/node.h"
#include "config.h"
#include "list.h" #include "list.h"
extern struct sway_root *root; extern struct sway_root *root;
@ -47,7 +47,7 @@ struct sway_root {
struct wlr_scene_tree *shell_top; struct wlr_scene_tree *shell_top;
struct wlr_scene_tree *fullscreen; struct wlr_scene_tree *fullscreen;
struct wlr_scene_tree *fullscreen_global; struct wlr_scene_tree *fullscreen_global;
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
struct wlr_scene_tree *unmanaged; struct wlr_scene_tree *unmanaged;
#endif #endif
struct wlr_scene_tree *shell_overlay; struct wlr_scene_tree *shell_overlay;

View file

@ -1,10 +1,11 @@
#ifndef _SWAY_VIEW_H #ifndef _SWAY_VIEW_H
#define _SWAY_VIEW_H #define _SWAY_VIEW_H
#include <wayland-server-core.h> #include <wayland-server-core.h>
#include <wlr/config.h>
#include <wlr/types/wlr_compositor.h> #include <wlr/types/wlr_compositor.h>
#include <wlr/types/wlr_scene.h> #include <wlr/types/wlr_scene.h>
#include "sway/config.h" #include "sway/config.h"
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
#include <wlr/xwayland.h> #include <wlr/xwayland.h>
#endif #endif
#include "sway/input/input-manager.h" #include "sway/input/input-manager.h"
@ -15,7 +16,7 @@ struct sway_xdg_decoration;
enum sway_view_type { enum sway_view_type {
SWAY_VIEW_XDG_SHELL, SWAY_VIEW_XDG_SHELL,
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
SWAY_VIEW_XWAYLAND, SWAY_VIEW_XWAYLAND,
#endif #endif
}; };
@ -27,7 +28,7 @@ enum sway_view_prop {
VIEW_PROP_INSTANCE, VIEW_PROP_INSTANCE,
VIEW_PROP_WINDOW_TYPE, VIEW_PROP_WINDOW_TYPE,
VIEW_PROP_WINDOW_ROLE, VIEW_PROP_WINDOW_ROLE,
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
VIEW_PROP_X11_WINDOW_ID, VIEW_PROP_X11_WINDOW_ID,
VIEW_PROP_X11_PARENT_ID, VIEW_PROP_X11_PARENT_ID,
#endif #endif
@ -98,7 +99,7 @@ struct sway_view {
union { union {
struct wlr_xdg_toplevel *wlr_xdg_toplevel; struct wlr_xdg_toplevel *wlr_xdg_toplevel;
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
struct wlr_xwayland_surface *wlr_xwayland_surface; struct wlr_xwayland_surface *wlr_xwayland_surface;
#endif #endif
}; };
@ -127,7 +128,7 @@ struct sway_xdg_shell_view {
struct wl_listener unmap; struct wl_listener unmap;
struct wl_listener destroy; struct wl_listener destroy;
}; };
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
struct sway_xwayland_view { struct sway_xwayland_view {
struct sway_view view; struct sway_view view;
@ -293,7 +294,7 @@ void view_center_and_clip_surface(struct sway_view *view);
struct sway_view *view_from_wlr_xdg_surface( struct sway_view *view_from_wlr_xdg_surface(
struct wlr_xdg_surface *xdg_surface); struct wlr_xdg_surface *xdg_surface);
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
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);
#endif #endif

View file

@ -45,7 +45,7 @@ subproject(
required: false, required: false,
version: wlroots_version, version: wlroots_version,
) )
wlroots = dependency('wlroots', version: wlroots_version) wlroots = dependency('wlroots-0.18', version: wlroots_version, fallback: 'wlroots')
wlroots_features = { wlroots_features = {
'xwayland': false, 'xwayland': false,
'libinput_backend': false, 'libinput_backend': false,
@ -57,10 +57,6 @@ foreach name, _ : wlroots_features
wlroots_features += { name: have } wlroots_features += { name: have }
endforeach endforeach
if get_option('xwayland').enabled() and not wlroots_features['xwayland']
error('Cannot enable Xwayland in sway: wlroots has been built without Xwayland support')
endif
null_dep = dependency('', required: false) null_dep = dependency('', required: false)
jsonc = dependency('json-c', version: '>=0.13') jsonc = dependency('json-c', version: '>=0.13')
@ -68,7 +64,7 @@ pcre2 = dependency('libpcre2-8')
wayland_server = dependency('wayland-server', version: '>=1.21.0') wayland_server = dependency('wayland-server', version: '>=1.21.0')
wayland_client = dependency('wayland-client') wayland_client = dependency('wayland-client')
wayland_cursor = dependency('wayland-cursor') wayland_cursor = dependency('wayland-cursor')
wayland_protos = dependency('wayland-protocols', version: '>=1.24') wayland_protos = dependency('wayland-protocols', version: '>=1.24', default_options: ['tests=false'])
xkbcommon = dependency('xkbcommon', version: '>=1.5.0') xkbcommon = dependency('xkbcommon', version: '>=1.5.0')
cairo = dependency('cairo') cairo = dependency('cairo')
pango = dependency('pango') pango = dependency('pango')
@ -76,17 +72,15 @@ 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')
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.26.0') : null_dep
xcb = dependency('xcb', required: get_option('xwayland')) xcb = wlroots_features['xwayland'] ? dependency('xcb') : null_dep
drm = dependency('libdrm') drm = dependency('libdrm')
libudev = wlroots_features['libinput_backend'] ? dependency('libudev') : null_dep libudev = wlroots_features['libinput_backend'] ? dependency('libudev') : null_dep
math = cc.find_library('m') math = cc.find_library('m')
rt = cc.find_library('rt') rt = cc.find_library('rt')
xcb_icccm = dependency('xcb-icccm', required: get_option('xwayland')) xcb_icccm = wlroots_features['xwayland'] ? dependency('xcb-icccm') : null_dep
threads = dependency('threads') # for pthread_setschedparam threads = dependency('threads') # for pthread_setschedparam
have_xwayland = xcb.found() and xcb_icccm.found() and wlroots_features['xwayland']
if get_option('sd-bus-provider') == 'auto' if get_option('sd-bus-provider') == 'auto'
if not get_option('tray').disabled() if not get_option('tray').disabled()
assert(get_option('auto_features').auto(), 'sd-bus-provider must not be set to auto since auto_features != auto') assert(get_option('auto_features').auto(), 'sd-bus-provider must not be set to auto since auto_features != auto')
@ -110,7 +104,6 @@ have_tray = (not get_option('tray').disabled()) and tray_deps_found
conf_data = configuration_data() conf_data = configuration_data()
conf_data.set10('HAVE_XWAYLAND', have_xwayland)
conf_data.set10('HAVE_GDK_PIXBUF', gdk_pixbuf.found()) conf_data.set10('HAVE_GDK_PIXBUF', gdk_pixbuf.found())
conf_data.set10('HAVE_LIBSYSTEMD', sdbus.found() and sdbus.name() == 'libsystemd') conf_data.set10('HAVE_LIBSYSTEMD', sdbus.found() and sdbus.name() == 'libsystemd')
conf_data.set10('HAVE_LIBELOGIND', sdbus.found() and sdbus.name() == 'libelogind') conf_data.set10('HAVE_LIBELOGIND', sdbus.found() and sdbus.name() == 'libelogind')
@ -271,7 +264,6 @@ endif
subdir('completions') subdir('completions')
summary({ summary({
'xwayland': have_xwayland,
'gdk-pixbuf': gdk_pixbuf.found(), 'gdk-pixbuf': gdk_pixbuf.found(),
'tray': have_tray, 'tray': have_tray,
'man-pages': scdoc.found(), 'man-pages': scdoc.found(),

View file

@ -4,7 +4,6 @@ option('bash-completions', type: 'boolean', value: true, description: 'Install b
option('fish-completions', type: 'boolean', value: true, description: 'Install fish shell completions.') option('fish-completions', type: 'boolean', value: true, description: 'Install fish shell completions.')
option('swaybar', type: 'boolean', value: true, description: 'Enable support for swaybar') option('swaybar', type: 'boolean', value: true, description: 'Enable support for swaybar')
option('swaynag', type: 'boolean', value: true, description: 'Enable support for swaynag') option('swaynag', type: 'boolean', value: true, description: 'Enable support for swaynag')
option('xwayland', type: 'feature', value: 'auto', description: 'Enable support for X11 applications')
option('tray', type: 'feature', value: 'auto', description: 'Enable support for swaybar tray') option('tray', type: 'feature', value: 'auto', description: 'Enable support for swaybar tray')
option('gdk-pixbuf', type: 'feature', value: 'auto', description: 'Enable support for more image formats in swaybar tray') option('gdk-pixbuf', type: 'feature', value: 'auto', description: 'Enable support for more image formats in swaybar tray')
option('man-pages', type: 'feature', value: 'auto', description: 'Generate and install man pages') option('man-pages', type: 'feature', value: 'auto', description: 'Generate and install man pages')

View file

@ -7,10 +7,10 @@ wayland_scanner = find_program(
) )
protocols = [ protocols = [
wl_protocol_dir / 'stable/tablet/tablet-v2.xml',
wl_protocol_dir / 'stable/xdg-shell/xdg-shell.xml', wl_protocol_dir / 'stable/xdg-shell/xdg-shell.xml',
wl_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml', wl_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml',
wl_protocol_dir / 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml', wl_protocol_dir / 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml',
wl_protocol_dir / 'unstable/tablet/tablet-unstable-v2.xml',
wl_protocol_dir / 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml', wl_protocol_dir / 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml',
wl_protocol_dir / 'staging/content-type/content-type-v1.xml', wl_protocol_dir / 'staging/content-type/content-type-v1.xml',
wl_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml', wl_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml',

View file

@ -11,6 +11,7 @@ static const struct cmd_handler input_handlers[] = {
{ "accel_profile", input_cmd_accel_profile }, { "accel_profile", input_cmd_accel_profile },
{ "calibration_matrix", input_cmd_calibration_matrix }, { "calibration_matrix", input_cmd_calibration_matrix },
{ "click_method", input_cmd_click_method }, { "click_method", input_cmd_click_method },
{ "clickfinger_button_map", input_cmd_clickfinger_button_map },
{ "drag", input_cmd_drag }, { "drag", input_cmd_drag },
{ "drag_lock", input_cmd_drag_lock }, { "drag_lock", input_cmd_drag_lock },
{ "dwt", input_cmd_dwt }, { "dwt", input_cmd_dwt },

View file

@ -0,0 +1,27 @@
#include <string.h>
#include <strings.h>
#include "sway/config.h"
#include "sway/commands.h"
#include "sway/input/input-manager.h"
struct cmd_results *input_cmd_clickfinger_button_map(int argc, char **argv) {
struct cmd_results *error = NULL;
if ((error = checkarg(argc, "clickfinger_button_map", 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 (strcasecmp(argv[0], "lrm") == 0) {
ic->clickfinger_button_map = LIBINPUT_CONFIG_CLICKFINGER_MAP_LRM;
} else if (strcasecmp(argv[0], "lmr") == 0) {
ic->clickfinger_button_map = LIBINPUT_CONFIG_CLICKFINGER_MAP_LMR;
} else {
return cmd_results_new(CMD_INVALID,
"Expected 'clickfinger_button_map <lrm|lmr>'");
}
return cmd_results_new(CMD_SUCCESS, NULL);
}

View file

@ -5,6 +5,7 @@
#include "sway/config.h" #include "sway/config.h"
#include "sway/commands.h" #include "sway/commands.h"
#include "sway/input/input-manager.h" #include "sway/input/input-manager.h"
#include "sway/server.h"
#include "log.h" #include "log.h"
#if WLR_HAS_LIBINPUT_BACKEND #if WLR_HAS_LIBINPUT_BACKEND

View file

@ -3,6 +3,7 @@
#include "sway/config.h" #include "sway/config.h"
#include "sway/commands.h" #include "sway/commands.h"
#include "sway/input/input-manager.h" #include "sway/input/input-manager.h"
#include "sway/server.h"
#include "log.h" #include "log.h"
struct xkb_switch_layout_action { struct xkb_switch_layout_action {

View file

@ -11,6 +11,7 @@
#include "sway/input/seat.h" #include "sway/input/seat.h"
#include "sway/ipc-server.h" #include "sway/ipc-server.h"
#include "sway/output.h" #include "sway/output.h"
#include "sway/server.h"
#include "sway/tree/arrange.h" #include "sway/tree/arrange.h"
#include "sway/tree/container.h" #include "sway/tree/container.h"
#include "sway/tree/root.h" #include "sway/tree/root.h"

View file

@ -10,6 +10,7 @@ static const struct cmd_handler output_handlers[] = {
{ "adaptive_sync", output_cmd_adaptive_sync }, { "adaptive_sync", output_cmd_adaptive_sync },
{ "background", output_cmd_background }, { "background", output_cmd_background },
{ "bg", output_cmd_background }, { "bg", output_cmd_background },
{ "color_profile", output_cmd_color_profile },
{ "disable", output_cmd_disable }, { "disable", output_cmd_disable },
{ "dpms", output_cmd_dpms }, { "dpms", output_cmd_dpms },
{ "enable", output_cmd_enable }, { "enable", output_cmd_enable },

View file

@ -0,0 +1,101 @@
#include <fcntl.h>
#include <strings.h>
#include <sys/stat.h>
#include <unistd.h>
#include <wlr/render/color.h>
#include "sway/commands.h"
#include "sway/config.h"
static bool read_file_into_buf(const char *path, void **buf, size_t *size) {
/* Why not use fopen/fread directly? glibc will succesfully open directories,
* not just files, and supports seeking on them. Instead, we directly
* work with file descriptors and use the more consistent open/fstat/read. */
int fd = open(path, O_RDONLY | O_NOCTTY | O_CLOEXEC);
if (fd == -1) {
return false;
}
char *b = NULL;
struct stat info;
if (fstat(fd, &info) == -1) {
goto fail;
}
// only regular files, to avoid issues with e.g. opening pipes
if (!S_ISREG(info.st_mode)) {
goto fail;
}
off_t s = info.st_size;
if (s <= 0) {
goto fail;
}
b = calloc(1, s);
if (!b) {
goto fail;
}
size_t nread = 0;
while (nread < (size_t)s) {
size_t to_read = (size_t)s - nread;
ssize_t r = read(fd, b + nread, to_read);
if ((r == -1 && errno != EINTR) || r == 0) {
goto fail;
}
nread += (size_t)r;
}
close(fd);
*buf = b;
*size = (size_t)s;
return true; // success
fail:
free(b);
close(fd);
return false;
}
struct cmd_results *output_cmd_color_profile(int argc, char **argv) {
if (!config->handler_context.output_config) {
return cmd_results_new(CMD_FAILURE, "Missing output config");
}
if (!argc) {
return cmd_results_new(CMD_INVALID, "Missing color_profile first argument.");
}
if (strcmp(*argv, "srgb") == 0) {
wlr_color_transform_unref(config->handler_context.output_config->color_transform);
config->handler_context.output_config->color_transform = NULL;
config->handler_context.output_config->set_color_transform = true;
config->handler_context.leftovers.argc = argc - 1;
config->handler_context.leftovers.argv = argv + 1;
} else if (strcmp(*argv, "icc") == 0) {
if (argc < 2) {
return cmd_results_new(CMD_INVALID,
"Invalid color profile specification: icc type requires a file");
}
void *data = NULL;
size_t size = 0;
if (!read_file_into_buf(argv[1], &data, &size)) {
return cmd_results_new(CMD_FAILURE,
"Failed to load color profile: could not read ICC file");
}
struct wlr_color_transform *tmp =
wlr_color_transform_init_linear_to_icc(data, size);
if (!tmp) {
free(data);
return cmd_results_new(CMD_FAILURE,
"Failed to load color profile: failed to initialize transform from ICC");
}
free(data);
wlr_color_transform_unref(config->handler_context.output_config->color_transform);
config->handler_context.output_config->color_transform = tmp;
config->handler_context.output_config->set_color_transform = true;
config->handler_context.leftovers.argc = argc - 2;
config->handler_context.leftovers.argv = argv + 2;
} else {
return cmd_results_new(CMD_INVALID,
"Invalid color profile specification: first argument should be icc|srgb");
}
return NULL;
}

View file

@ -5,6 +5,7 @@
#include <wlr/types/wlr_pointer.h> #include <wlr/types/wlr_pointer.h>
#include "sway/commands.h" #include "sway/commands.h"
#include "sway/input/cursor.h" #include "sway/input/cursor.h"
#include "sway/server.h"
static struct cmd_results *press_or_release(struct sway_cursor *cursor, static struct cmd_results *press_or_release(struct sway_cursor *cursor,
char *action, char *button_str); char *action, char *button_str);

View file

@ -4,6 +4,7 @@
#include "sway/config.h" #include "sway/config.h"
#include "sway/input/cursor.h" #include "sway/input/cursor.h"
#include "sway/input/seat.h" #include "sway/input/seat.h"
#include "sway/server.h"
enum operation { enum operation {
OP_ENABLE, OP_ENABLE,

View file

@ -2,6 +2,7 @@
#include "sway/commands.h" #include "sway/commands.h"
#include "sway/input/seat.h" #include "sway/input/seat.h"
#include "sway/input/input-manager.h" #include "sway/input/input-manager.h"
#include "sway/server.h"
#include "util.h" #include "util.h"
static struct cmd_results *handle_action(struct seat_config *sc, static struct cmd_results *handle_action(struct seat_config *sc,

View file

@ -3,6 +3,7 @@
#include "sway/commands.h" #include "sway/commands.h"
#include "sway/config.h" #include "sway/config.h"
#include "sway/input/seat.h" #include "sway/input/seat.h"
#include "sway/server.h"
#include "sway/tree/container.h" #include "sway/tree/container.h"
#include "sway/tree/view.h" #include "sway/tree/view.h"

View file

@ -18,7 +18,7 @@ static bool test_con_id(struct sway_container *container, void *data) {
return container->node.id == *con_id; return container->node.id == *con_id;
} }
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
static bool test_id(struct sway_container *container, void *data) { static bool test_id(struct sway_container *container, void *data) {
xcb_window_t *wid = data; xcb_window_t *wid = data;
return (container->view && container->view->type == SWAY_VIEW_XWAYLAND return (container->view && container->view->type == SWAY_VIEW_XWAYLAND
@ -53,7 +53,7 @@ struct cmd_results *cmd_swap(int argc, char **argv) {
char *value = join_args(argv + 3, argc - 3); char *value = join_args(argv + 3, argc - 3);
if (strcasecmp(argv[2], "id") == 0) { if (strcasecmp(argv[2], "id") == 0) {
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
xcb_window_t id = strtol(value, NULL, 0); xcb_window_t id = strtol(value, NULL, 0);
other = root_find_container(test_id, &id); other = root_find_container(test_id, &id);
#endif #endif

View file

@ -10,7 +10,7 @@ struct cmd_results *cmd_xwayland(int argc, char **argv) {
return error; return error;
} }
#ifdef HAVE_XWAYLAND #ifdef WLR_HAS_XWAYLAND
enum xwayland_mode xwayland; enum xwayland_mode xwayland;
if (strcmp(argv[0], "force") == 0) { if (strcmp(argv[0], "force") == 0) {
xwayland = XWAYLAND_MODE_IMMEDIATE; xwayland = XWAYLAND_MODE_IMMEDIATE;

View file

@ -23,6 +23,7 @@
#include "sway/config.h" #include "sway/config.h"
#include "sway/criteria.h" #include "sway/criteria.h"
#include "sway/desktop/transaction.h" #include "sway/desktop/transaction.h"
#include "sway/server.h"
#include "sway/swaynag.h" #include "sway/swaynag.h"
#include "sway/tree/arrange.h" #include "sway/tree/arrange.h"
#include "sway/tree/root.h" #include "sway/tree/root.h"

View file

@ -12,6 +12,7 @@
#include "sway/config.h" #include "sway/config.h"
#include "sway/input/keyboard.h" #include "sway/input/keyboard.h"
#include "sway/output.h" #include "sway/output.h"
#include "sway/server.h"
#include "config.h" #include "config.h"
#include "list.h" #include "list.h"
#include "log.h" #include "log.h"

View file

@ -3,6 +3,7 @@
#include <float.h> #include <float.h>
#include "sway/config.h" #include "sway/config.h"
#include "sway/input/keyboard.h" #include "sway/input/keyboard.h"
#include "sway/server.h"
#include "log.h" #include "log.h"
struct input_config *new_input_config(const char* identifier) { struct input_config *new_input_config(const char* identifier) {
@ -27,6 +28,7 @@ struct input_config *new_input_config(const char* identifier) {
input->dwtp = INT_MIN; input->dwtp = INT_MIN;
input->send_events = INT_MIN; input->send_events = INT_MIN;
input->click_method = INT_MIN; input->click_method = INT_MIN;
input->clickfinger_button_map = INT_MIN;
input->middle_emulation = INT_MIN; input->middle_emulation = INT_MIN;
input->natural_scroll = INT_MIN; input->natural_scroll = INT_MIN;
input->accel_profile = INT_MIN; input->accel_profile = INT_MIN;
@ -54,6 +56,9 @@ void merge_input_config(struct input_config *dst, struct input_config *src) {
if (src->click_method != INT_MIN) { if (src->click_method != INT_MIN) {
dst->click_method = src->click_method; dst->click_method = src->click_method;
} }
if (src->clickfinger_button_map != INT_MIN) {
dst->clickfinger_button_map = src->clickfinger_button_map;
}
if (src->drag != INT_MIN) { if (src->drag != INT_MIN) {
dst->drag = src->drag; dst->drag = src->drag;
} }

View file

@ -13,6 +13,7 @@
#include "sway/config.h" #include "sway/config.h"
#include "sway/input/cursor.h" #include "sway/input/cursor.h"
#include "sway/output.h" #include "sway/output.h"
#include "sway/server.h"
#include "sway/tree/root.h" #include "sway/tree/root.h"
#include "log.h" #include "log.h"
#include "util.h" #include "util.h"
@ -75,6 +76,8 @@ struct output_config *new_output_config(const char *name) {
oc->max_render_time = -1; oc->max_render_time = -1;
oc->adaptive_sync = -1; oc->adaptive_sync = -1;
oc->render_bit_depth = RENDER_BIT_DEPTH_DEFAULT; oc->render_bit_depth = RENDER_BIT_DEPTH_DEFAULT;
oc->set_color_transform = false;
oc->color_transform = NULL;
oc->power = -1; oc->power = -1;
return oc; return oc;
} }
@ -190,6 +193,14 @@ static void merge_output_config(struct output_config *dst, struct output_config
if (src->render_bit_depth != RENDER_BIT_DEPTH_DEFAULT) { if (src->render_bit_depth != RENDER_BIT_DEPTH_DEFAULT) {
dst->render_bit_depth = src->render_bit_depth; dst->render_bit_depth = src->render_bit_depth;
} }
if (src->set_color_transform) {
if (src->color_transform) {
wlr_color_transform_ref(src->color_transform);
}
wlr_color_transform_unref(dst->color_transform);
dst->set_color_transform = true;
dst->color_transform = src->color_transform;
}
if (src->background) { if (src->background) {
free(dst->background); free(dst->background);
dst->background = strdup(src->background); dst->background = strdup(src->background);
@ -448,7 +459,7 @@ static void queue_output_config(struct output_config *oc,
#endif #endif
} }
if (wlr_output->transform != tr) { if (wlr_output->transform != tr) {
sway_log(SWAY_DEBUG, "Set %s transform to %d", oc->name, tr); sway_log(SWAY_DEBUG, "Set %s transform to %d", wlr_output->name, tr);
wlr_output_state_set_transform(pending, tr); wlr_output_state_set_transform(pending, tr);
} }
@ -556,6 +567,13 @@ static bool finalize_output_config(struct output_config *oc, struct sway_output
output->max_render_time = oc->max_render_time; output->max_render_time = oc->max_render_time;
} }
if (oc && oc->set_color_transform) {
if (oc->color_transform) {
wlr_color_transform_ref(oc->color_transform);
}
wlr_color_transform_unref(output->color_transform);
output->color_transform = oc->color_transform;
}
return true; return true;
} }
@ -703,21 +721,18 @@ static bool search_adaptive_sync(struct search_context *ctx, size_t output_idx)
struct wlr_backend_output_state *backend_state = &ctx->states[output_idx]; struct wlr_backend_output_state *backend_state = &ctx->states[output_idx];
struct wlr_output_state *state = &backend_state->base; struct wlr_output_state *state = &backend_state->base;
if (!backend_state->output->adaptive_sync_supported) {
return search_finish(ctx, output_idx);
}
if (cfg->config && cfg->config->adaptive_sync == 1) { if (cfg->config && cfg->config->adaptive_sync == 1) {
wlr_output_state_set_adaptive_sync_enabled(state, true); wlr_output_state_set_adaptive_sync_enabled(state, true);
if (search_finish(ctx, output_idx)) { if (search_finish(ctx, output_idx)) {
return true; return true;
} }
} }
if (!cfg->config || cfg->config->adaptive_sync != -1) {
wlr_output_state_set_adaptive_sync_enabled(state, false); wlr_output_state_set_adaptive_sync_enabled(state, false);
if (search_finish(ctx, output_idx)) {
return true;
}
}
// If adaptive sync has not been set, or fallback in case we are on a
// backend that cannot disable adaptive sync such as the wayland backend.
state->committed &= ~WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED;
return search_finish(ctx, output_idx); return search_finish(ctx, output_idx);
} }
@ -909,6 +924,7 @@ bool apply_output_configs(struct matched_output_config *configs,
struct wlr_scene_output_state_options opts = { struct wlr_scene_output_state_options opts = {
.swapchain = wlr_output_swapchain_manager_get_swapchain( .swapchain = wlr_output_swapchain_manager_get_swapchain(
&swapchain_mgr, backend_state->output), &swapchain_mgr, backend_state->output),
.color_transform = cfg->output->color_transform,
}; };
struct wlr_scene_output *scene_output = cfg->output->scene_output; struct wlr_scene_output *scene_output = cfg->output->scene_output;
struct wlr_output_state *state = &backend_state->base; struct wlr_output_state *state = &backend_state->base;
@ -996,6 +1012,7 @@ void free_output_config(struct output_config *oc) {
free(oc->name); free(oc->name);
free(oc->background); free(oc->background);
free(oc->background_option); free(oc->background_option);
wlr_color_transform_unref(oc->color_transform);
free(oc); free(oc);
} }

View file

@ -7,6 +7,7 @@
#include "sway/criteria.h" #include "sway/criteria.h"
#include "sway/tree/container.h" #include "sway/tree/container.h"
#include "sway/config.h" #include "sway/config.h"
#include "sway/server.h"
#include "sway/tree/root.h" #include "sway/tree/root.h"
#include "sway/tree/view.h" #include "sway/tree/view.h"
#include "sway/tree/workspace.h" #include "sway/tree/workspace.h"
@ -22,7 +23,7 @@ bool criteria_is_empty(struct criteria *criteria) {
&& !criteria->app_id && !criteria->app_id
&& !criteria->con_mark && !criteria->con_mark
&& !criteria->con_id && !criteria->con_id
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
&& !criteria->class && !criteria->class
&& !criteria->id && !criteria->id
&& !criteria->instance && !criteria->instance
@ -90,7 +91,7 @@ void criteria_destroy(struct criteria *criteria) {
pattern_destroy(criteria->title); pattern_destroy(criteria->title);
pattern_destroy(criteria->shell); pattern_destroy(criteria->shell);
pattern_destroy(criteria->app_id); pattern_destroy(criteria->app_id);
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
pattern_destroy(criteria->class); pattern_destroy(criteria->class);
pattern_destroy(criteria->instance); pattern_destroy(criteria->instance);
pattern_destroy(criteria->window_role); pattern_destroy(criteria->window_role);
@ -110,7 +111,7 @@ static int regex_cmp(const char *item, const pcre2_code *regex) {
return result; return result;
} }
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
static bool view_has_window_type(struct sway_view *view, enum atom_name name) { static bool view_has_window_type(struct sway_view *view, enum atom_name name) {
if (view->type != SWAY_VIEW_XWAYLAND) { if (view->type != SWAY_VIEW_XWAYLAND) {
return false; return false;
@ -251,7 +252,7 @@ static bool criteria_matches_view(struct criteria *criteria,
return false; return false;
} }
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
if (criteria->id) { // X11 window ID if (criteria->id) { // X11 window ID
uint32_t x11_window_id = view_get_x11_window_id(view); uint32_t x11_window_id = view_get_x11_window_id(view);
if (!x11_window_id || x11_window_id != criteria->id) { if (!x11_window_id || x11_window_id != criteria->id) {
@ -428,7 +429,7 @@ list_t *criteria_get_containers(struct criteria *criteria) {
return matches; return matches;
} }
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
static enum atom_name parse_window_type(const char *type) { static enum atom_name parse_window_type(const char *type) {
if (strcasecmp(type, "normal") == 0) { if (strcasecmp(type, "normal") == 0) {
return NET_WM_WINDOW_TYPE_NORMAL; return NET_WM_WINDOW_TYPE_NORMAL;
@ -461,7 +462,7 @@ enum criteria_token {
T_CON_ID, T_CON_ID,
T_CON_MARK, T_CON_MARK,
T_FLOATING, T_FLOATING,
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
T_CLASS, T_CLASS,
T_ID, T_ID,
T_INSTANCE, T_INSTANCE,
@ -487,7 +488,7 @@ static enum criteria_token token_from_name(char *name) {
return T_CON_ID; return T_CON_ID;
} else if (strcmp(name, "con_mark") == 0) { } else if (strcmp(name, "con_mark") == 0) {
return T_CON_MARK; return T_CON_MARK;
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
} else if (strcmp(name, "class") == 0) { } else if (strcmp(name, "class") == 0) {
return T_CLASS; return T_CLASS;
} else if (strcmp(name, "id") == 0) { } else if (strcmp(name, "id") == 0) {
@ -566,7 +567,7 @@ static bool parse_token(struct criteria *criteria, char *name, char *value) {
case T_CON_MARK: case T_CON_MARK:
pattern_create(&criteria->con_mark, value); pattern_create(&criteria->con_mark, value);
break; break;
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
case T_CLASS: case T_CLASS:
pattern_create(&criteria->class, value); pattern_create(&criteria->class, value);
break; break;
@ -674,7 +675,7 @@ struct criteria *criteria_parse(char *raw, char **error_arg) {
++head; ++head;
struct criteria *criteria = calloc(1, sizeof(struct criteria)); struct criteria *criteria = calloc(1, sizeof(struct criteria));
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
criteria->window_type = ATOM_LAST; // default value criteria->window_type = ATOM_LAST; // default value
#endif #endif
char *name = NULL, *value = NULL; char *name = NULL, *value = NULL;

View file

@ -4,6 +4,7 @@
#include "sway/input/seat.h" #include "sway/input/seat.h"
#include "sway/output.h" #include "sway/output.h"
#include "sway/desktop/launcher.h" #include "sway/desktop/launcher.h"
#include "sway/server.h"
#include "sway/tree/node.h" #include "sway/tree/node.h"
#include "sway/tree/container.h" #include "sway/tree/container.h"
#include "sway/tree/workspace.h" #include "sway/tree/workspace.h"

View file

@ -243,13 +243,17 @@ static int output_repaint_timer_handler(void *data) {
output_configure_scene(output, &root->root_scene->tree.node, 1.0f); output_configure_scene(output, &root->root_scene->tree.node, 1.0f);
if (output->gamma_lut_changed) { struct wlr_scene_output_state_options opts = {
struct wlr_output_state pending; .color_transform = output->color_transform,
wlr_output_state_init(&pending); };
if (!wlr_scene_output_build_state(output->scene_output, &pending, NULL)) {
return 0;
}
struct wlr_output_state pending;
wlr_output_state_init(&pending);
if (!wlr_scene_output_build_state(output->scene_output, &pending, &opts)) {
return 0;
}
if (output->gamma_lut_changed) {
output->gamma_lut_changed = false; output->gamma_lut_changed = false;
struct wlr_gamma_control_v1 *gamma_control = struct wlr_gamma_control_v1 *gamma_control =
wlr_gamma_control_manager_v1_get_control( wlr_gamma_control_manager_v1_get_control(
@ -259,17 +263,16 @@ static int output_repaint_timer_handler(void *data) {
return 0; return 0;
} }
if (!wlr_output_commit_state(output->wlr_output, &pending)) { if (!wlr_output_test_state(output->wlr_output, &pending)) {
wlr_gamma_control_v1_send_failed_and_destroy(gamma_control); wlr_gamma_control_v1_send_failed_and_destroy(gamma_control);
wlr_output_state_finish(&pending); wlr_output_state_set_gamma_lut(&pending, 0, NULL, NULL, NULL);
return 0;
} }
wlr_output_state_finish(&pending);
return 0;
} }
wlr_scene_output_commit(output->scene_output, NULL); if (!wlr_output_commit_state(output->wlr_output, &pending)) {
sway_log(SWAY_ERROR, "Page-flip failed on output %s", output->wlr_output->name);
}
wlr_output_state_finish(&pending);
return 0; return 0;
} }
@ -362,6 +365,26 @@ static void update_output_manager_config(struct sway_server *server) {
ipc_event_output(); ipc_event_output();
} }
static int timer_modeset_handle(void *data) {
struct sway_server *server = data;
wl_event_source_remove(server->delayed_modeset);
server->delayed_modeset = NULL;
apply_all_output_configs();
transaction_commit_dirty();
update_output_manager_config(server);
return 0;
}
static void request_modeset(struct sway_server *server) {
if (server->delayed_modeset == NULL) {
server->delayed_modeset = wl_event_loop_add_timer(server->wl_event_loop,
timer_modeset_handle, server);
wl_event_source_timer_update(server->delayed_modeset, 10);
}
}
static void begin_destroy(struct sway_output *output) { static void begin_destroy(struct sway_output *output) {
struct sway_server *server = output->server; struct sway_server *server = output->server;
@ -385,9 +408,7 @@ static void begin_destroy(struct sway_output *output) {
output->wlr_output->data = NULL; output->wlr_output->data = NULL;
output->wlr_output = NULL; output->wlr_output = NULL;
transaction_commit_dirty(); request_modeset(server);
update_output_manager_config(server);
} }
static void handle_destroy(struct wl_listener *listener, void *data) { static void handle_destroy(struct wl_listener *listener, void *data) {
@ -521,11 +542,7 @@ void handle_new_output(struct wl_listener *listener, void *data) {
sway_session_lock_add_output(server->session_lock.lock, output); sway_session_lock_add_output(server->session_lock.lock, output);
} }
apply_all_output_configs(); request_modeset(server);
transaction_commit_dirty();
update_output_manager_config(server);
} }
void handle_output_layout_change(struct wl_listener *listener, void handle_output_layout_change(struct wl_listener *listener,
@ -677,5 +694,5 @@ void handle_output_power_manager_set_mode(struct wl_listener *listener,
break; break;
} }
store_output_config(oc); store_output_config(oc);
apply_all_output_configs(); request_modeset(output->server);
} }

View file

@ -10,6 +10,7 @@
#include "sway/input/cursor.h" #include "sway/input/cursor.h"
#include "sway/input/input-manager.h" #include "sway/input/input-manager.h"
#include "sway/output.h" #include "sway/output.h"
#include "sway/server.h"
#include "sway/tree/container.h" #include "sway/tree/container.h"
#include "sway/tree/node.h" #include "sway/tree/node.h"
#include "sway/tree/view.h" #include "sway/tree/view.h"
@ -313,7 +314,7 @@ static void arrange_children(enum sway_container_layout layout, list_t *children
if (activated) { if (activated) {
arrange_container(child, width, height - title_bar_height, arrange_container(child, width, height - title_bar_height,
false, 0); title_bar_height == 0, 0);
} else { } else {
disable_container(child); disable_container(child);
} }
@ -342,7 +343,7 @@ static void arrange_children(enum sway_container_layout layout, list_t *children
if (activated) { if (activated) {
arrange_container(child, width, height - title_height, arrange_container(child, width, height - title_height,
false, 0); title_bar_height == 0, 0);
} else { } else {
disable_container(child); disable_container(child);
} }
@ -761,7 +762,7 @@ static bool should_configure(struct sway_node *node,
} }
struct sway_container_state *cstate = &node->sway_container->current; struct sway_container_state *cstate = &node->sway_container->current;
struct sway_container_state *istate = &instruction->container_state; struct sway_container_state *istate = &instruction->container_state;
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
// Xwayland views are position-aware and need to be reconfigured // Xwayland views are position-aware and need to be reconfigured
// when their position changes. // when their position changes.
if (node->sway_container->view->type == SWAY_VIEW_XWAYLAND) { if (node->sway_container->view->type == SWAY_VIEW_XWAYLAND) {

View file

@ -289,6 +289,8 @@ static void handle_commit(struct wl_listener *listener, void *data) {
} }
// XXX: https://github.com/swaywm/sway/issues/2176 // XXX: https://github.com/swaywm/sway/issues/2176
wlr_xdg_surface_schedule_configure(xdg_surface); wlr_xdg_surface_schedule_configure(xdg_surface);
wlr_xdg_toplevel_set_wm_capabilities(view->wlr_xdg_toplevel,
XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
// TODO: wlr_xdg_toplevel_set_bounds() // TODO: wlr_xdg_toplevel_set_bounds()
return; return;
} }
@ -575,7 +577,4 @@ void handle_xdg_shell_toplevel(struct wl_listener *listener, void *data) {
wlr_scene_xdg_surface_create(xdg_shell_view->view.content_tree, xdg_toplevel->base); wlr_scene_xdg_surface_create(xdg_shell_view->view.content_tree, xdg_toplevel->base);
xdg_toplevel->base->data = xdg_shell_view; xdg_toplevel->base->data = xdg_shell_view;
wlr_xdg_toplevel_set_wm_capabilities(xdg_toplevel,
XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN);
} }

View file

@ -25,6 +25,7 @@
#include "sway/layers.h" #include "sway/layers.h"
#include "sway/output.h" #include "sway/output.h"
#include "sway/scene_descriptor.h" #include "sway/scene_descriptor.h"
#include "sway/server.h"
#include "sway/tree/container.h" #include "sway/tree/container.h"
#include "sway/tree/root.h" #include "sway/tree/root.h"
#include "sway/tree/view.h" #include "sway/tree/view.h"
@ -107,7 +108,7 @@ struct sway_node *node_at_coords(
return NULL; return NULL;
} }
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
if (scene_descriptor_try_get(current, SWAY_SCENE_DESC_XWAYLAND_UNMANAGED)) { if (scene_descriptor_try_get(current, SWAY_SCENE_DESC_XWAYLAND_UNMANAGED)) {
return NULL; return NULL;
} }

View file

@ -13,6 +13,7 @@
#include "sway/input/seat.h" #include "sway/input/seat.h"
#include "sway/input/cursor.h" #include "sway/input/cursor.h"
#include "sway/ipc-server.h" #include "sway/ipc-server.h"
#include "sway/server.h"
#include "log.h" #include "log.h"
#if WLR_HAS_SESSION #if WLR_HAS_SESSION
@ -508,12 +509,13 @@ static void handle_key_event(struct sway_keyboard *keyboard,
} }
if (event->state == WL_KEYBOARD_KEY_STATE_RELEASED) { if (event->state == WL_KEYBOARD_KEY_STATE_RELEASED) {
// If the pressed event was sent to a client, also send the released // If the pressed event was sent to a client and we have a focused
// surface immediately before this event, also send the released
// event. In particular, don't send the released event to the IM grab. // event. In particular, don't send the released event to the IM grab.
bool pressed_sent = update_shortcut_state( bool pressed_sent = update_shortcut_state(
&keyboard->state_pressed_sent, event->keycode, &keyboard->state_pressed_sent, event->keycode,
event->state, keyinfo.keycode, 0); event->state, keyinfo.keycode, 0);
if (pressed_sent) { if (pressed_sent && seat->wlr_seat->keyboard_state.focused_surface) {
wlr_seat_set_keyboard(wlr_seat, keyboard->wlr); wlr_seat_set_keyboard(wlr_seat, keyboard->wlr);
wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec, wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec,
event->keycode, event->state); event->keycode, event->state);
@ -959,16 +961,8 @@ cleanup:
free(sway_group); free(sway_group);
} }
void sway_keyboard_configure(struct sway_keyboard *keyboard) { static void sway_keyboard_set_layout(struct sway_keyboard *keyboard,
struct input_config *input_config = struct input_config *input_config) {
input_device_get_config(keyboard->seat_device->input_device);
if (!sway_assert(!wlr_keyboard_group_from_wlr_keyboard(keyboard->wlr),
"sway_keyboard_configure should not be called with a "
"keyboard group's keyboard")) {
return;
}
struct xkb_keymap *keymap = sway_keyboard_compile_keymap(input_config, NULL); struct xkb_keymap *keymap = sway_keyboard_compile_keymap(input_config, NULL);
if (!keymap) { if (!keymap) {
sway_log(SWAY_ERROR, "Failed to compile keymap. Attempting defaults"); sway_log(SWAY_ERROR, "Failed to compile keymap. Attempting defaults");
@ -984,31 +978,13 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) {
!wlr_keyboard_keymaps_match(keyboard->keymap, keymap) : true; !wlr_keyboard_keymaps_match(keyboard->keymap, keymap) : true;
bool effective_layout_changed = keyboard->effective_layout != 0; bool effective_layout_changed = keyboard->effective_layout != 0;
int repeat_rate = 25; if (keymap_changed || config->reloading) {
if (input_config && input_config->repeat_rate != INT_MIN) {
repeat_rate = input_config->repeat_rate;
}
int repeat_delay = 600;
if (input_config && input_config->repeat_delay != INT_MIN) {
repeat_delay = input_config->repeat_delay;
}
bool repeat_info_changed = keyboard->repeat_rate != repeat_rate ||
keyboard->repeat_delay != repeat_delay;
if (keymap_changed || repeat_info_changed || config->reloading) {
xkb_keymap_unref(keyboard->keymap); xkb_keymap_unref(keyboard->keymap);
keyboard->keymap = keymap; keyboard->keymap = keymap;
keyboard->effective_layout = 0; keyboard->effective_layout = 0;
keyboard->repeat_rate = repeat_rate;
keyboard->repeat_delay = repeat_delay;
sway_keyboard_group_remove_invalid(keyboard); sway_keyboard_group_remove_invalid(keyboard);
wlr_keyboard_set_keymap(keyboard->wlr, keyboard->keymap); wlr_keyboard_set_keymap(keyboard->wlr, keyboard->keymap);
wlr_keyboard_set_repeat_info(keyboard->wlr,
keyboard->repeat_rate, keyboard->repeat_delay);
if (!keyboard->wlr->group) { if (!keyboard->wlr->group) {
sway_keyboard_group_add(keyboard); sway_keyboard_group_add(keyboard);
} }
@ -1059,6 +1035,49 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) {
wlr_seat_set_keyboard(seat, keyboard->wlr); wlr_seat_set_keyboard(seat, keyboard->wlr);
} }
if (keymap_changed) {
ipc_event_input("xkb_keymap",
keyboard->seat_device->input_device);
} else if (effective_layout_changed) {
ipc_event_input("xkb_layout",
keyboard->seat_device->input_device);
}
}
void sway_keyboard_configure(struct sway_keyboard *keyboard) {
struct input_config *input_config =
input_device_get_config(keyboard->seat_device->input_device);
if (!sway_assert(!wlr_keyboard_group_from_wlr_keyboard(keyboard->wlr),
"sway_keyboard_configure should not be called with a "
"keyboard group's keyboard")) {
return;
}
int repeat_rate = 25;
if (input_config && input_config->repeat_rate != INT_MIN) {
repeat_rate = input_config->repeat_rate;
}
int repeat_delay = 600;
if (input_config && input_config->repeat_delay != INT_MIN) {
repeat_delay = input_config->repeat_delay;
}
bool repeat_info_changed = keyboard->repeat_rate != repeat_rate ||
keyboard->repeat_delay != repeat_delay;
if (repeat_info_changed || config->reloading) {
keyboard->repeat_rate = repeat_rate;
keyboard->repeat_delay = repeat_delay;
wlr_keyboard_set_repeat_info(keyboard->wlr,
keyboard->repeat_rate, keyboard->repeat_delay);
}
if (!keyboard->seat_device->input_device->is_virtual) {
sway_keyboard_set_layout(keyboard, input_config);
}
wl_list_remove(&keyboard->keyboard_key.link); wl_list_remove(&keyboard->keyboard_key.link);
wl_signal_add(&keyboard->wlr->events.key, &keyboard->keyboard_key); wl_signal_add(&keyboard->wlr->events.key, &keyboard->keyboard_key);
keyboard->keyboard_key.notify = handle_keyboard_key; keyboard->keyboard_key.notify = handle_keyboard_key;
@ -1068,13 +1087,6 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) {
&keyboard->keyboard_modifiers); &keyboard->keyboard_modifiers);
keyboard->keyboard_modifiers.notify = handle_keyboard_modifiers; keyboard->keyboard_modifiers.notify = handle_keyboard_modifiers;
if (keymap_changed) {
ipc_event_input("xkb_keymap",
keyboard->seat_device->input_device);
} else if (effective_layout_changed) {
ipc_event_input("xkb_layout",
keyboard->seat_device->input_device);
}
} }
void sway_keyboard_destroy(struct sway_keyboard *keyboard) { void sway_keyboard_destroy(struct sway_keyboard *keyboard) {

View file

@ -132,6 +132,16 @@ static bool set_click_method(struct libinput_device *device,
return true; return true;
} }
static bool set_clickfinger_button_map(struct libinput_device *device,
enum libinput_config_clickfinger_button_map map) {
if (libinput_device_config_click_get_clickfinger_button_map(device) == map) {
return false;
}
sway_log(SWAY_DEBUG, "clickfinger_set_button_map(%d)", map);
log_status(libinput_device_config_click_set_clickfinger_button_map(device, map));
return true;
}
static bool set_middle_emulation(struct libinput_device *dev, static bool set_middle_emulation(struct libinput_device *dev,
enum libinput_config_middle_emulation_state mid) { enum libinput_config_middle_emulation_state mid) {
if (!libinput_device_config_middle_emulation_is_available(dev) || if (!libinput_device_config_middle_emulation_is_available(dev) ||
@ -281,6 +291,9 @@ bool sway_input_configure_libinput_device(struct sway_input_device *input_device
if (ic->click_method != INT_MIN) { if (ic->click_method != INT_MIN) {
changed |= set_click_method(device, ic->click_method); changed |= set_click_method(device, ic->click_method);
} }
if (ic->clickfinger_button_map != INT_MIN) {
changed |= set_clickfinger_button_map(device, ic->clickfinger_button_map);
}
if (ic->middle_emulation != INT_MIN) { if (ic->middle_emulation != INT_MIN) {
changed |= set_middle_emulation(device, ic->middle_emulation); changed |= set_middle_emulation(device, ic->middle_emulation);
} }
@ -356,6 +369,8 @@ void sway_input_reset_libinput_device(struct sway_input_device *input_device) {
libinput_device_config_left_handed_get_default(device)); libinput_device_config_left_handed_get_default(device));
changed |= set_click_method(device, changed |= set_click_method(device,
libinput_device_config_click_get_default_method(device)); libinput_device_config_click_get_default_method(device));
changed |= set_clickfinger_button_map(device,
libinput_device_config_click_get_default_clickfinger_button_map(device));
changed |= set_middle_emulation(device, changed |= set_middle_emulation(device,
libinput_device_config_middle_emulation_get_default_enabled(device)); libinput_device_config_middle_emulation_get_default_enabled(device));
changed |= set_scroll_method(device, changed |= set_scroll_method(device,

View file

@ -190,7 +190,7 @@ static void seat_send_focus(struct sway_node *node, struct sway_seat *seat) {
node->sway_container->view : NULL; node->sway_container->view : NULL;
if (view && seat_is_input_allowed(seat, view->surface)) { if (view && seat_is_input_allowed(seat, view->surface)) {
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
if (view->type == SWAY_VIEW_XWAYLAND) { if (view->type == SWAY_VIEW_XWAYLAND) {
struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland; struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland;
wlr_xwayland_set_seat(xwayland, seat->wlr_seat); wlr_xwayland_set_seat(xwayland, seat->wlr_seat);
@ -802,11 +802,10 @@ static void seat_configure_keyboard(struct sway_seat *seat,
return; return;
} }
// force notify reenter to pick up the new configuration. This reuses // Notify reenter to pick up the new configuration. This reuses
// the current focused surface to avoid breaking input grabs. // the current focused surface to avoid breaking input grabs.
struct wlr_surface *surface = seat->wlr_seat->keyboard_state.focused_surface; struct wlr_surface *surface = seat->wlr_seat->keyboard_state.focused_surface;
if (surface) { if (surface) {
wlr_seat_keyboard_notify_clear_focus(seat->wlr_seat);
seat_keyboard_notify_enter(seat, surface); seat_keyboard_notify_enter(seat, surface);
} }
} }
@ -1002,7 +1001,7 @@ void seat_configure_xcursor(struct sway_seat *seat) {
setenv("XCURSOR_THEME", cursor_theme, 1); setenv("XCURSOR_THEME", cursor_theme, 1);
} }
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
if (server.xwayland.wlr_xwayland && (!server.xwayland.xcursor_manager || if (server.xwayland.wlr_xwayland && (!server.xwayland.xcursor_manager ||
!xcursor_manager_is_named(server.xwayland.xcursor_manager, !xcursor_manager_is_named(server.xwayland.xcursor_manager,
cursor_theme) || cursor_theme) ||

View file

@ -11,11 +11,12 @@
#include "sway/input/tablet.h" #include "sway/input/tablet.h"
#include "sway/layers.h" #include "sway/layers.h"
#include "sway/output.h" #include "sway/output.h"
#include "sway/server.h"
#include "sway/scene_descriptor.h" #include "sway/scene_descriptor.h"
#include "sway/tree/view.h" #include "sway/tree/view.h"
#include "sway/tree/workspace.h" #include "sway/tree/workspace.h"
#include "log.h" #include "log.h"
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
#include "sway/xwayland.h" #include "sway/xwayland.h"
#endif #endif
@ -234,7 +235,7 @@ static void handle_tablet_tool_tip(struct sway_seat *seat,
node->sway_container : NULL; node->sway_container : NULL;
struct wlr_layer_surface_v1 *layer; struct wlr_layer_surface_v1 *layer;
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
struct wlr_xwayland_surface *xsurface; struct wlr_xwayland_surface *xsurface;
#endif #endif
if ((layer = wlr_layer_surface_v1_try_from_wlr_surface(surface)) && if ((layer = wlr_layer_surface_v1_try_from_wlr_surface(surface)) &&
@ -268,7 +269,7 @@ static void handle_tablet_tool_tip(struct sway_seat *seat,
seat_set_focus_container(seat, cont); seat_set_focus_container(seat, cont);
seatop_begin_down(seat, node->sway_container, sx, sy); seatop_begin_down(seat, node->sway_container, sx, sy);
} }
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
// Handle tapping on an xwayland unmanaged view // Handle tapping on an xwayland unmanaged view
else if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(surface)) && else if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(surface)) &&
xsurface->override_redirect && xsurface->override_redirect &&
@ -514,7 +515,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
return; return;
} }
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
// Handle clicking on xwayland unmanaged view // Handle clicking on xwayland unmanaged view
struct wlr_xwayland_surface *xsurface; struct wlr_xwayland_surface *xsurface;
if (surface && if (surface &&

View file

@ -1,5 +1,6 @@
#include "sway/config.h" #include "sway/config.h"
#include "sway/input/switch.h" #include "sway/input/switch.h"
#include "sway/server.h"
#include "log.h" #include "log.h"
struct sway_switch *sway_switch_create(struct sway_seat *seat, struct sway_switch *sway_switch_create(struct sway_seat *seat,

View file

@ -7,6 +7,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/server.h"
#if WLR_HAS_LIBINPUT_BACKEND #if WLR_HAS_LIBINPUT_BACKEND
#include <wlr/backend/libinput.h> #include <wlr/backend/libinput.h>

View file

@ -9,6 +9,8 @@
#include "sway/input/text_input.h" #include "sway/input/text_input.h"
#include "sway/input/text_input_popup.h" #include "sway/input/text_input_popup.h"
#include "sway/layers.h" #include "sway/layers.h"
#include "sway/server.h"
static void input_popup_update(struct sway_input_popup *popup); static void input_popup_update(struct sway_input_popup *popup);
static struct sway_text_input *relay_get_focusable_text_input( static struct sway_text_input *relay_get_focusable_text_input(
@ -66,11 +68,13 @@ static void handle_im_keyboard_grab_destroy(struct wl_listener *listener, void *
struct sway_input_method_relay *relay = wl_container_of(listener, relay, struct sway_input_method_relay *relay = wl_container_of(listener, relay,
input_method_keyboard_grab_destroy); input_method_keyboard_grab_destroy);
struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data; struct wlr_input_method_keyboard_grab_v2 *keyboard_grab = data;
struct wlr_seat *wlr_seat = keyboard_grab->input_method->seat;
wl_list_remove(&relay->input_method_keyboard_grab_destroy.link); wl_list_remove(&relay->input_method_keyboard_grab_destroy.link);
if (keyboard_grab->keyboard) { if (keyboard_grab->keyboard) {
// send modifier state to original client // send modifier state to original client
wlr_seat_keyboard_notify_modifiers(keyboard_grab->input_method->seat, wlr_seat_set_keyboard(wlr_seat, keyboard_grab->keyboard);
wlr_seat_keyboard_notify_modifiers(wlr_seat,
&keyboard_grab->keyboard->modifiers); &keyboard_grab->keyboard->modifiers);
} }
} }

View file

@ -11,6 +11,7 @@
#include "log.h" #include "log.h"
#include "sway/config.h" #include "sway/config.h"
#include "sway/ipc-json.h" #include "sway/ipc-json.h"
#include "sway/server.h"
#include "sway/tree/container.h" #include "sway/tree/container.h"
#include "sway/tree/view.h" #include "sway/tree/view.h"
#include "sway/tree/workspace.h" #include "sway/tree/workspace.h"
@ -154,7 +155,7 @@ static json_object *ipc_json_output_mode_description(
return mode_object; return mode_object;
} }
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
static const char *ipc_json_xwindow_type_description(struct sway_view *view) { static const char *ipc_json_xwindow_type_description(struct sway_view *view) {
struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface; struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface;
struct sway_xwayland *xwayland = &server.xwayland; struct sway_xwayland *xwayland = &server.xwayland;
@ -577,9 +578,10 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object
bool visible = view_is_visible(c->view); bool visible = view_is_visible(c->view);
json_object_object_add(object, "visible", json_object_new_boolean(visible)); json_object_object_add(object, "visible", json_object_new_boolean(visible));
bool has_titlebar = c->title_bar.tree->node.enabled;
struct wlr_box window_box = { struct wlr_box window_box = {
c->pending.content_x - c->pending.x, c->pending.content_x - c->pending.x,
(c->current.border == B_PIXEL) ? c->pending.content_y - c->pending.y : 0, has_titlebar ? 0 : c->pending.content_y - c->pending.y,
c->pending.content_width, c->pending.content_width,
c->pending.content_height c->pending.content_height
}; };
@ -633,7 +635,7 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object
json_object_new_string(ipc_json_content_type_description(content_type))); json_object_new_string(ipc_json_content_type_description(content_type)));
} }
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
if (c->view->type == SWAY_VIEW_XWAYLAND) { if (c->view->type == SWAY_VIEW_XWAYLAND) {
json_object_object_add(object, "window", json_object_object_add(object, "window",
json_object_new_int(view_get_x11_window_id(c->view))); json_object_new_int(view_get_x11_window_id(c->view)));
@ -990,6 +992,18 @@ static json_object *describe_libinput_device(struct libinput_device *device) {
} }
json_object_object_add(object, "click_method", json_object_object_add(object, "click_method",
json_object_new_string(click_method)); json_object_new_string(click_method));
const char *button_map = "unknown";
switch (libinput_device_config_click_get_clickfinger_button_map(device)) {
case LIBINPUT_CONFIG_CLICKFINGER_MAP_LRM:
button_map = "lrm";
break;
case LIBINPUT_CONFIG_CLICKFINGER_MAP_LMR:
button_map = "lmr";
break;
}
json_object_object_add(object, "clickfinger_button_map",
json_object_new_string(button_map));
} }
if (libinput_device_config_middle_emulation_is_available(device)) { if (libinput_device_config_middle_emulation_is_available(device)) {

View file

@ -155,6 +155,7 @@ sway_sources = files(
'commands/input/accel_profile.c', 'commands/input/accel_profile.c',
'commands/input/calibration_matrix.c', 'commands/input/calibration_matrix.c',
'commands/input/click_method.c', 'commands/input/click_method.c',
'commands/input/clickfinger_button_map.c',
'commands/input/drag.c', 'commands/input/drag.c',
'commands/input/drag_lock.c', 'commands/input/drag_lock.c',
'commands/input/dwt.c', 'commands/input/dwt.c',
@ -203,6 +204,7 @@ sway_sources = files(
'commands/output/toggle.c', 'commands/output/toggle.c',
'commands/output/transform.c', 'commands/output/transform.c',
'commands/output/unplug.c', 'commands/output/unplug.c',
'commands/output/color_profile.c',
'tree/arrange.c', 'tree/arrange.c',
'tree/container.c', 'tree/container.c',
@ -232,7 +234,7 @@ sway_deps = [
xcb_icccm, xcb_icccm,
] ]
if have_xwayland if wlroots_features['xwayland']
sway_sources += 'desktop/xwayland.c' sway_sources += 'desktop/xwayland.c'
endif endif

View file

@ -56,7 +56,7 @@
#include "sway/input/cursor.h" #include "sway/input/cursor.h"
#include "sway/tree/root.h" #include "sway/tree/root.h"
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
#include <wlr/xwayland/shell.h> #include <wlr/xwayland/shell.h>
#include "sway/xwayland.h" #include "sway/xwayland.h"
#endif #endif
@ -113,12 +113,13 @@ static bool is_privileged(const struct wl_global *global) {
global == server.input->keyboard_shortcuts_inhibit->global || global == server.input->keyboard_shortcuts_inhibit->global ||
global == server.input->virtual_keyboard->global || global == server.input->virtual_keyboard->global ||
global == server.input->virtual_pointer->global || global == server.input->virtual_pointer->global ||
global == server.input->transient_seat_manager->global; global == server.input->transient_seat_manager->global ||
global == server.xdg_output_manager_v1->global;
} }
static bool filter_global(const struct wl_client *client, static bool filter_global(const struct wl_client *client,
const struct wl_global *global, void *data) { const struct wl_global *global, void *data) {
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland; struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland;
if (xwayland && global == xwayland->shell_v1->global) { if (xwayland && global == xwayland->shell_v1->global) {
return xwayland->server != NULL && client == xwayland->server->client; return xwayland->server != NULL && client == xwayland->server->client;
@ -275,7 +276,8 @@ bool server_init(struct sway_server *server) {
wl_signal_add(&root->output_layout->events.change, wl_signal_add(&root->output_layout->events.change,
&server->output_layout_change); &server->output_layout_change);
wlr_xdg_output_manager_v1_create(server->wl_display, root->output_layout); server->xdg_output_manager_v1 =
wlr_xdg_output_manager_v1_create(server->wl_display, root->output_layout);
server->idle_notifier_v1 = wlr_idle_notifier_v1_create(server->wl_display); server->idle_notifier_v1 = wlr_idle_notifier_v1_create(server->wl_display);
sway_idle_inhibit_manager_v1_init(); sway_idle_inhibit_manager_v1_init();
@ -437,7 +439,7 @@ bool server_init(struct sway_server *server) {
void server_fini(struct sway_server *server) { void server_fini(struct sway_server *server) {
// TODO: free sway-specific resources // TODO: free sway-specific resources
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
wlr_xwayland_destroy(server->xwayland.wlr_xwayland); wlr_xwayland_destroy(server->xwayland.wlr_xwayland);
#endif #endif
wl_display_destroy_clients(server->wl_display); wl_display_destroy_clients(server->wl_display);
@ -447,7 +449,7 @@ void server_fini(struct sway_server *server) {
} }
bool server_start(struct sway_server *server) { bool server_start(struct sway_server *server) {
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
if (config->xwayland != XWAYLAND_MODE_DISABLED) { if (config->xwayland != XWAYLAND_MODE_DISABLED) {
sway_log(SWAY_DEBUG, "Initializing Xwayland (lazy=%d)", sway_log(SWAY_DEBUG, "Initializing Xwayland (lazy=%d)",
config->xwayland == XWAYLAND_MODE_LAZY); config->xwayland == XWAYLAND_MODE_LAZY);

View file

@ -143,6 +143,12 @@ The following commands may only be used in the configuration file.
*input* <identifier> click_method none|button_areas|clickfinger *input* <identifier> click_method none|button_areas|clickfinger
Changes the click method for the specified device. Changes the click method for the specified device.
*input* <identifier> clickfinger_button_map lrm|lmr
Specifies which button mapping to use for clickfinger. _lrm_ treats 1 finger as
left click, 2 fingers as right click, and 3 fingers as middle click. _lmr_
treats 1 finger as left click, 2 fingers as middle click, and 3 fingers as
right click.
*input* <identifier> drag enabled|disabled *input* <identifier> drag enabled|disabled
Enables or disables tap-and-drag for specified input device. Enables or disables tap-and-drag for specified input device.

View file

@ -1168,7 +1168,7 @@ following properties will be included for devices that support them:
: Whether tap to click is enabled. It can be _enabled_ or _disabled_ : Whether tap to click is enabled. It can be _enabled_ or _disabled_
|- tap_button_map |- tap_button_map
: string : string
: The finger to button mapping in use. It can be _lmr_ or _lrm_ : The finger to button mapping in use for tapping. It can be _lmr_ or _lrm_
|- tap_drag |- tap_drag
: string : string
: Whether tap-and-drag is enabled. It can be _enabled_ or _disabled_ : Whether tap-and-drag is enabled. It can be _enabled_ or _disabled_
@ -1190,6 +1190,9 @@ following properties will be included for devices that support them:
|- click_method |- click_method
: string : string
: The click method in use. It can be _none_, _button_areas_, or _clickfinger_ : The click method in use. It can be _none_, _button_areas_, or _clickfinger_
|- click_button_map
: string
: The finger to button mapping in use for clickfinger. It can be _lmr_ or _lrm_
|- middle_emulation |- middle_emulation
: string : string
: Whether middle emulation is enabled. It can be _enabled_ or _disabled_ : Whether middle emulation is enabled. It can be _enabled_ or _disabled_

View file

@ -178,6 +178,18 @@ must be separated by one space. For example:
updated to work with different bit depths. This command is experimental, updated to work with different bit depths. This command is experimental,
and may be removed or changed in the future. and may be removed or changed in the future.
*output* <name> color_profile srgb|[icc <file>]
Sets the color profile for an output. The default is _srgb_. <file> should be a
path to a display ICC profile.
Not all renderers support this feature; currently it only works with the
the Vulkan renderer. Even where supported, the application of the color
profile may be inaccurate.
This command is experimental, and may be removed or changed in the future. It
may have no effect or produce unexpected output when used together with future
HDR support features.
# SEE ALSO # SEE ALSO
*sway*(5) *sway-input*(5) *sway*(5) *sway-input*(5)

View file

@ -294,6 +294,9 @@ void sway_text_node_set_text(struct sway_text_node *node, char *text) {
void sway_text_node_set_max_width(struct sway_text_node *node, int max_width) { void sway_text_node_set_max_width(struct sway_text_node *node, int max_width) {
struct text_buffer *buffer = wl_container_of(node, buffer, props); struct text_buffer *buffer = wl_container_of(node, buffer, props);
if (max_width == buffer->props.max_width) {
return;
}
buffer->props.max_width = max_width; buffer->props.max_width = max_width;
wlr_scene_buffer_set_dest_size(buffer->buffer_node, wlr_scene_buffer_set_dest_size(buffer->buffer_node,
get_text_width(&buffer->props), buffer->props.height); get_text_width(&buffer->props), buffer->props.height);
@ -303,6 +306,9 @@ void sway_text_node_set_max_width(struct sway_text_node *node, int max_width) {
void sway_text_node_set_background(struct sway_text_node *node, float background[4]) { void sway_text_node_set_background(struct sway_text_node *node, float background[4]) {
struct text_buffer *buffer = wl_container_of(node, buffer, props); struct text_buffer *buffer = wl_container_of(node, buffer, props);
if (memcmp(&node->background, background, sizeof(*background) * 4) == 0) {
return;
}
memcpy(&node->background, background, sizeof(*background) * 4); memcpy(&node->background, background, sizeof(*background) * 4);
render_backing_buffer(buffer); render_backing_buffer(buffer);
} }

View file

@ -279,6 +279,7 @@ void output_destroy(struct sway_output *output) {
list_free(output->workspaces); list_free(output->workspaces);
list_free(output->current.workspaces); list_free(output->current.workspaces);
wl_event_source_remove(output->repaint_timer); wl_event_source_remove(output->repaint_timer);
wlr_color_transform_unref(output->color_transform);
free(output); free(output);
} }

View file

@ -53,7 +53,7 @@ struct sway_root *root_create(struct wl_display *wl_display) {
root->layers.shell_top = alloc_scene_tree(root->layer_tree, &failed); root->layers.shell_top = alloc_scene_tree(root->layer_tree, &failed);
root->layers.fullscreen = alloc_scene_tree(root->layer_tree, &failed); root->layers.fullscreen = alloc_scene_tree(root->layer_tree, &failed);
root->layers.fullscreen_global = alloc_scene_tree(root->layer_tree, &failed); root->layers.fullscreen_global = alloc_scene_tree(root->layer_tree, &failed);
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
root->layers.unmanaged = alloc_scene_tree(root->layer_tree, &failed); root->layers.unmanaged = alloc_scene_tree(root->layer_tree, &failed);
#endif #endif
root->layers.shell_overlay = alloc_scene_tree(root->layer_tree, &failed); root->layers.shell_overlay = alloc_scene_tree(root->layer_tree, &failed);

View file

@ -1,16 +1,17 @@
#include <stdlib.h> #include <stdlib.h>
#include <strings.h> #include <strings.h>
#include <wayland-server-core.h> #include <wayland-server-core.h>
#include <wlr/config.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_ext_foreign_toplevel_list_v1.h> #include <wlr/types/wlr_ext_foreign_toplevel_list_v1.h>
#include <wlr/types/wlr_foreign_toplevel_management_v1.h> #include <wlr/types/wlr_foreign_toplevel_management_v1.h>
#include <wlr/types/wlr_fractional_scale_v1.h>
#include <wlr/types/wlr_output_layout.h> #include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_server_decoration.h> #include <wlr/types/wlr_server_decoration.h>
#include <wlr/types/wlr_subcompositor.h> #include <wlr/types/wlr_subcompositor.h>
#include <wlr/types/wlr_xdg_decoration_v1.h> #include <wlr/types/wlr_xdg_decoration_v1.h>
#include "config.h" #if WLR_HAS_XWAYLAND
#if HAVE_XWAYLAND
#include <wlr/xwayland.h> #include <wlr/xwayland.h>
#endif #endif
#include "list.h" #include "list.h"
@ -126,7 +127,7 @@ const char *view_get_instance(struct sway_view *view) {
} }
return NULL; return NULL;
} }
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
uint32_t view_get_x11_window_id(struct sway_view *view) { uint32_t view_get_x11_window_id(struct sway_view *view) {
if (view->impl->get_int_prop) { if (view->impl->get_int_prop) {
return view->impl->get_int_prop(view, VIEW_PROP_X11_WINDOW_ID); return view->impl->get_int_prop(view, VIEW_PROP_X11_WINDOW_ID);
@ -159,7 +160,7 @@ const char *view_get_shell(struct sway_view *view) {
switch(view->type) { switch(view->type) {
case SWAY_VIEW_XDG_SHELL: case SWAY_VIEW_XDG_SHELL:
return "xdg_shell"; return "xdg_shell";
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
case SWAY_VIEW_XWAYLAND: case SWAY_VIEW_XWAYLAND:
return "xwayland"; return "xwayland";
#endif #endif
@ -173,9 +174,9 @@ void view_get_constraints(struct sway_view *view, double *min_width,
view->impl->get_constraints(view, view->impl->get_constraints(view,
min_width, max_width, min_height, max_height); min_width, max_width, min_height, max_height);
} else { } else {
*min_width = DBL_MIN; *min_width = 1;
*max_width = DBL_MAX; *max_width = DBL_MAX;
*min_height = DBL_MIN; *min_height = 1;
*max_height = DBL_MAX; *max_height = DBL_MAX;
} }
} }
@ -365,8 +366,8 @@ void view_autoconfigure(struct sway_view *view) {
con->pending.content_x = x; con->pending.content_x = x;
con->pending.content_y = y; con->pending.content_y = y;
con->pending.content_width = width; con->pending.content_width = fmax(width, 1);
con->pending.content_height = height; con->pending.content_height = fmax(height, 1);
} }
void view_set_activated(struct sway_view *view, bool activated) { void view_set_activated(struct sway_view *view, bool activated) {
@ -499,7 +500,7 @@ void view_execute_criteria(struct sway_view *view) {
static void view_populate_pid(struct sway_view *view) { static void view_populate_pid(struct sway_view *view) {
pid_t pid; pid_t pid;
switch (view->type) { switch (view->type) {
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
case SWAY_VIEW_XWAYLAND:; case SWAY_VIEW_XWAYLAND:;
struct wlr_xwayland_surface *surf = struct wlr_xwayland_surface *surf =
wlr_xwayland_surface_try_from_wlr_surface(view->surface); wlr_xwayland_surface_try_from_wlr_surface(view->surface);
@ -741,6 +742,14 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface,
ws = select_workspace(view); ws = select_workspace(view);
} }
if (ws && ws->output) {
// Once the output is determined, we can notify the client early about
// scale to reduce startup jitter.
float scale = ws->output->wlr_output->scale;
wlr_fractional_scale_v1_notify_scale(wlr_surface, scale);
wlr_surface_set_preferred_buffer_scale(wlr_surface, ceil(scale));
}
struct sway_seat *seat = input_manager_current_seat(); struct sway_seat *seat = input_manager_current_seat();
struct sway_node *node = struct sway_node *node =
seat_get_focus_inactive(seat, ws ? &ws->node : &root->node); seat_get_focus_inactive(seat, ws ? &ws->node : &root->node);
@ -838,7 +847,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface,
bool set_focus = should_focus(view); bool set_focus = should_focus(view);
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
struct wlr_xwayland_surface *xsurface; struct wlr_xwayland_surface *xsurface;
if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(wlr_surface))) { if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(wlr_surface))) {
set_focus &= wlr_xwayland_icccm_input_model(xsurface) != set_focus &= wlr_xwayland_icccm_input_model(xsurface) !=
@ -927,11 +936,14 @@ void view_update_size(struct sway_view *view) {
void view_center_and_clip_surface(struct sway_view *view) { void view_center_and_clip_surface(struct sway_view *view) {
struct sway_container *con = view->container; struct sway_container *con = view->container;
bool clip_to_geometry = true;
if (container_is_floating(con)) { if (container_is_floating(con)) {
// We always center the current coordinates rather than the next, as the // We always center the current coordinates rather than the next, as the
// geometry immediately affects the currently active rendering. // geometry immediately affects the currently active rendering.
int x = (int) fmax(0, (con->current.content_width - view->geometry.width) / 2); int x = (int) fmax(0, (con->current.content_width - view->geometry.width) / 2);
int y = (int) fmax(0, (con->current.content_height - view->geometry.height) / 2); int y = (int) fmax(0, (con->current.content_height - view->geometry.height) / 2);
clip_to_geometry = !view->using_csd;
wlr_scene_node_set_position(&view->content_tree->node, x, y); wlr_scene_node_set_position(&view->content_tree->node, x, y);
} else { } else {
@ -940,12 +952,16 @@ void view_center_and_clip_surface(struct sway_view *view) {
// only make sure to clip the content if there is content to clip // only make sure to clip the content if there is content to clip
if (!wl_list_empty(&con->view->content_tree->children)) { if (!wl_list_empty(&con->view->content_tree->children)) {
wlr_scene_subsurface_tree_set_clip(&con->view->content_tree->node, &(struct wlr_box){ struct wlr_box clip = {0};
.x = con->view->geometry.x, if (clip_to_geometry) {
.y = con->view->geometry.y, clip = (struct wlr_box){
.width = con->current.content_width, .x = con->view->geometry.x,
.height = con->current.content_height, .y = con->view->geometry.y,
}); .width = con->current.content_width,
.height = con->current.content_height,
};
}
wlr_scene_subsurface_tree_set_clip(&con->view->content_tree->node, &clip);
} }
} }
@ -954,7 +970,7 @@ struct sway_view *view_from_wlr_surface(struct wlr_surface *wlr_surface) {
if ((xdg_surface = wlr_xdg_surface_try_from_wlr_surface(wlr_surface))) { if ((xdg_surface = wlr_xdg_surface_try_from_wlr_surface(wlr_surface))) {
return view_from_wlr_xdg_surface(xdg_surface); return view_from_wlr_xdg_surface(xdg_surface);
} }
#if HAVE_XWAYLAND #if WLR_HAS_XWAYLAND
struct wlr_xwayland_surface *xsurface; struct wlr_xwayland_surface *xsurface;
if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(wlr_surface))) { if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(wlr_surface))) {
return view_from_wlr_xwayland_surface(xsurface); return view_from_wlr_xwayland_surface(xsurface);
@ -1178,7 +1194,7 @@ void view_set_urgent(struct sway_view *view, bool enable) {
ipc_event_window(view->container, "urgent"); ipc_event_window(view->container, "urgent");
if (!container_is_scratchpad_hidden(view->container)) { if (!container_is_scratchpad_hidden_or_child(view->container)) {
workspace_detect_urgent(view->container->pending.workspace); workspace_detect_urgent(view->container->pending.workspace);
} }
} }

View file

@ -10,6 +10,7 @@
#include "sway/input/seat.h" #include "sway/input/seat.h"
#include "sway/ipc-server.h" #include "sway/ipc-server.h"
#include "sway/output.h" #include "sway/output.h"
#include "sway/server.h"
#include "sway/tree/arrange.h" #include "sway/tree/arrange.h"
#include "sway/tree/container.h" #include "sway/tree/container.h"
#include "sway/tree/node.h" #include "sway/tree/node.h"
@ -707,6 +708,11 @@ void workspace_for_each_container(struct sway_workspace *ws,
struct sway_container *workspace_find_container(struct sway_workspace *ws, struct sway_container *workspace_find_container(struct sway_workspace *ws,
bool (*test)(struct sway_container *con, void *data), void *data) { bool (*test)(struct sway_container *con, void *data), void *data) {
struct sway_container *result = NULL; struct sway_container *result = NULL;
if (ws == NULL){
sway_log(SWAY_ERROR, "Cannot find container with no workspace.");
return NULL;
}
// Tiling // Tiling
for (int i = 0; i < ws->tiling->length; ++i) { for (int i = 0; i < ws->tiling->length; ++i) {
struct sway_container *child = ws->tiling->items[i]; struct sway_container *child = ws->tiling->items[i];

View file

@ -38,14 +38,14 @@ void xdg_activation_v1_handle_request_activate(struct wl_listener *listener,
} }
// This is an activation request. If this context is internal we have ctx->seat. // This is an activation request. If this context is internal we have ctx->seat.
struct sway_seat *seat = ctx->seat; if (ctx->seat) {
if (!seat) { view_request_activate(view, ctx->seat);
// Otherwise, use the seat indicated by the launcher client in set_serial return;
seat = ctx->token->seat ? ctx->token->seat->data : NULL;
} }
if (seat && ctx->had_focused_surface) { // Otherwise, activate if passed from another focused client
view_request_activate(view, seat); if (ctx->token->seat && ctx->had_focused_surface) {
view_request_activate(view, ctx->token->seat->data);
} else { } else {
// The token is valid, but cannot be used to activate a window // The token is valid, but cannot be used to activate a window
view_request_urgent(view); view_request_urgent(view);