rebase: Sway 1.11 (#431)
Co-authored-by: Erik Reider <35975961+ErikReider@users.noreply.github.com>
This commit is contained in:
parent
1710f7ddff
commit
f47f35c52c
86 changed files with 1026 additions and 711 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -7,8 +7,6 @@ test/
|
||||||
build/
|
build/
|
||||||
build-*/
|
build-*/
|
||||||
.cache/
|
.cache/
|
||||||
!build-scripts
|
|
||||||
!build-scripts/*
|
|
||||||
.lvimrc
|
.lvimrc
|
||||||
config-debug
|
config-debug
|
||||||
wayland-*-protocol.*
|
wayland-*-protocol.*
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
<img src="assets/swayfx_logo.svg" width="256" alt="swayfx logo">
|
<img src="assets/swayfx_logo.svg" width="256" alt="swayfx logo">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Sway is an incredible window manager, and certainly one of the most well established wayland window managers. However, it is restricted to only include the functionality that existed in i3. This fork ditches the simple wlr_renderer, and replaces it with our fx_renderer, capable of rendering with fancy GLES2 effects. This, along with a couple of minor changes, expands sway's featureset to include the following:
|
Sway is an incredible window manager, and certainly one of the most well established wayland window managers. However, it is restricted to only include the functionality that existed in i3. This fork ditches the simple wlr_renderer, and replaces it with our fx_renderer, capable of rendering with fancy GLES2 effects. This, along with a couple of minor changes, expands sway's featureset to include the following:
|
||||||
|
|
||||||
|
|
|
@ -360,3 +360,8 @@ char *format_str(const char *fmt, ...) {
|
||||||
va_end(args);
|
va_end(args);
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool has_prefix(const char *str, const char *prefix) {
|
||||||
|
return strncmp(str, prefix, strlen(prefix)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,14 +46,18 @@ output * bg @datadir@/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png fill
|
||||||
#
|
#
|
||||||
# Example configuration:
|
# Example configuration:
|
||||||
#
|
#
|
||||||
# input "2:14:SynPS/2_Synaptics_TouchPad" {
|
# input type:touchpad {
|
||||||
# dwt enabled
|
# dwt enabled
|
||||||
# tap enabled
|
# tap enabled
|
||||||
# natural_scroll enabled
|
# natural_scroll enabled
|
||||||
# middle_emulation enabled
|
# middle_emulation enabled
|
||||||
# }
|
# }
|
||||||
#
|
#
|
||||||
# You can get the names of your inputs by running: swaymsg -t get_inputs
|
# input type:keyboard {
|
||||||
|
# xkb_layout "eu"
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# You can also configure each device individually.
|
||||||
# Read `man 5 sway-input` for more information about this section.
|
# Read `man 5 sway-input` for more information about this section.
|
||||||
|
|
||||||
### Key bindings
|
### Key bindings
|
||||||
|
|
12
flake.lock
generated
12
flake.lock
generated
|
@ -2,11 +2,11 @@
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1740019556,
|
"lastModified": 1750605355,
|
||||||
"narHash": "sha256-vn285HxnnlHLWnv59Og7muqECNMS33mWLM14soFIv2g=",
|
"narHash": "sha256-xT8cPLTxlktxI9vSdoBlAVK7dXgd8IK59j7ZwzkkhnI=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "dad564433178067be1fbdfcce23b546254b6d641",
|
"rev": "3078b9a9e75f1790e6d6ef9955fdc6a2d1740cc6",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -29,11 +29,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1739733667,
|
"lastModified": 1749449355,
|
||||||
"narHash": "sha256-BLIADMQwPJUtl6hFBhh5/xyYwLFDnNQz0RtgWO/Ua8s=",
|
"narHash": "sha256-GMMmxM/z7KKEs5PXB0TJFMg7qcwqbQ3/nI2906sZbxM=",
|
||||||
"owner": "wlrfx",
|
"owner": "wlrfx",
|
||||||
"repo": "scenefx",
|
"repo": "scenefx",
|
||||||
"rev": "87c0e8b6d5c86557a800445e8e4c322f387fe19c",
|
"rev": "b92dcb43bcf0da17ba8bfbdd7385dce75383628c",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
10
flake.nix
10
flake.nix
|
@ -25,10 +25,10 @@
|
||||||
version = "0.4.0-git";
|
version = "0.4.0-git";
|
||||||
src = pkgs.lib.cleanSource ./.;
|
src = pkgs.lib.cleanSource ./.;
|
||||||
nativeBuildInputs = old.nativeBuildInputs ++ [ pkgs.cmake ];
|
nativeBuildInputs = old.nativeBuildInputs ++ [ pkgs.cmake ];
|
||||||
# Add wlroots_0_18 here
|
# Add wlroots_0_19 here
|
||||||
buildInputs = old.buildInputs ++ [
|
buildInputs = old.buildInputs ++ [
|
||||||
pkgs.scenefx
|
pkgs.scenefx
|
||||||
pkgs.wlroots_0_18 # <-- Added this line
|
pkgs.wlroots_0_19 # <-- Added this line
|
||||||
];
|
];
|
||||||
providedSessions = [ pkgs.swayfx-unwrapped.meta.mainProgram ];
|
providedSessions = [ pkgs.swayfx-unwrapped.meta.mainProgram ];
|
||||||
patches = []; ## Consider if you need patches from the original derivation
|
patches = []; ## Consider if you need patches from the original derivation
|
||||||
|
@ -77,13 +77,13 @@
|
||||||
# Adding wlroots and scenefx explicitly here is fine, but they are also included via inputsFrom
|
# Adding wlroots and scenefx explicitly here is fine, but they are also included via inputsFrom
|
||||||
inputsFrom = [
|
inputsFrom = [
|
||||||
self.packages.${pkgs.system}.swayfx-unwrapped
|
self.packages.${pkgs.system}.swayfx-unwrapped
|
||||||
# pkgs.wlroots_0_18 # Included via swayfx-unwrapped buildInputs now
|
# pkgs.wlroots_0_19 # Included via swayfx-unwrapped buildInputs now
|
||||||
# pkgs.scenefx # Included via swayfx-unwrapped buildInputs now
|
# pkgs.scenefx # Included via swayfx-unwrapped buildInputs now
|
||||||
];
|
];
|
||||||
# You still might want wlroots/scenefx here if you need tools/headers directly in the shell
|
# You still might want wlroots/scenefx here if you need tools/headers directly in the shell
|
||||||
# outside of what swayfx uses.
|
# outside of what swayfx uses.
|
||||||
buildInputs = [
|
buildInputs = [
|
||||||
pkgs.wlroots_0_18
|
pkgs.wlroots_0_19
|
||||||
pkgs.scenefx
|
pkgs.scenefx
|
||||||
];
|
];
|
||||||
packages = with pkgs; [
|
packages = with pkgs; [
|
||||||
|
@ -96,7 +96,7 @@
|
||||||
echo "Copying wlroots and scenefx sources to ./subprojects for dev environment..."
|
echo "Copying wlroots and scenefx sources to ./subprojects for dev environment..."
|
||||||
mkdir -p "$PWD/subprojects" && cd "$PWD/subprojects"
|
mkdir -p "$PWD/subprojects" && cd "$PWD/subprojects"
|
||||||
rm -rf wlroots scenefx # Clean previous copies if they exist
|
rm -rf wlroots scenefx # Clean previous copies if they exist
|
||||||
cp -R --no-preserve=mode,ownership ${pkgs.wlroots_0_18.src} wlroots
|
cp -R --no-preserve=mode,ownership ${pkgs.wlroots_0_19.src} wlroots
|
||||||
cp -R --no-preserve=mode,ownership ${pkgs.scenefx.src} scenefx
|
cp -R --no-preserve=mode,ownership ${pkgs.scenefx.src} scenefx
|
||||||
echo "Done copying sources."
|
echo "Done copying sources."
|
||||||
cd "$OLDPWD"
|
cd "$OLDPWD"
|
||||||
|
|
|
@ -40,4 +40,6 @@ bool expand_path(char **path);
|
||||||
char *vformat_str(const char *fmt, va_list args) _SWAY_ATTRIB_PRINTF(1, 0);
|
char *vformat_str(const char *fmt, va_list args) _SWAY_ATTRIB_PRINTF(1, 0);
|
||||||
char *format_str(const char *fmt, ...) _SWAY_ATTRIB_PRINTF(1, 2);
|
char *format_str(const char *fmt, ...) _SWAY_ATTRIB_PRINTF(1, 2);
|
||||||
|
|
||||||
|
bool has_prefix(const char *str, const char *prefix);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#ifndef _SWAY_CONFIG_H
|
#ifndef _SWAY_CONFIG_H
|
||||||
#define _SWAY_CONFIG_H
|
#define _SWAY_CONFIG_H
|
||||||
#include <libinput.h>
|
#include <libinput.h>
|
||||||
#include <scenefx/types/fx/blur_data.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
|
@ -53,6 +53,9 @@ struct criteria {
|
||||||
char urgent; // 'l' for latest or 'o' for oldest
|
char urgent; // 'l' for latest or 'o' for oldest
|
||||||
struct pattern *workspace;
|
struct pattern *workspace;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
struct pattern *sandbox_engine;
|
||||||
|
struct pattern *sandbox_app_id;
|
||||||
|
struct pattern *sandbox_instance_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool criteria_is_empty(struct criteria *criteria);
|
bool criteria_is_empty(struct criteria *criteria);
|
||||||
|
|
|
@ -13,6 +13,7 @@ enum sway_idle_inhibit_mode {
|
||||||
struct sway_idle_inhibit_manager_v1 {
|
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_listener manager_destroy;
|
||||||
struct wl_list inhibitors;
|
struct wl_list inhibitors;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,8 @@ struct sway_input_manager {
|
||||||
|
|
||||||
struct sway_input_manager *input_manager_create(struct sway_server *server);
|
struct sway_input_manager *input_manager_create(struct sway_server *server);
|
||||||
|
|
||||||
|
void input_manager_finish(struct sway_input_manager *input);
|
||||||
|
|
||||||
bool input_manager_has_focus(struct sway_node *node);
|
bool input_manager_has_focus(struct sway_node *node);
|
||||||
|
|
||||||
void input_manager_set_focus(struct sway_node *node);
|
void input_manager_set_focus(struct sway_node *node);
|
||||||
|
|
|
@ -25,8 +25,10 @@ struct sway_input_method_relay {
|
||||||
struct wlr_input_method_v2 *input_method; // doesn't have to be present
|
struct wlr_input_method_v2 *input_method; // doesn't have to be present
|
||||||
|
|
||||||
struct wl_listener text_input_new;
|
struct wl_listener text_input_new;
|
||||||
|
struct wl_listener text_input_manager_destroy;
|
||||||
|
|
||||||
struct wl_listener input_method_new;
|
struct wl_listener input_method_new;
|
||||||
|
struct wl_listener input_method_manager_destroy;
|
||||||
struct wl_listener input_method_commit;
|
struct wl_listener input_method_commit;
|
||||||
struct wl_listener input_method_new_popup_surface;
|
struct wl_listener input_method_new_popup_surface;
|
||||||
struct wl_listener input_method_grab_keyboard;
|
struct wl_listener input_method_grab_keyboard;
|
||||||
|
|
|
@ -59,7 +59,6 @@ struct sway_output {
|
||||||
|
|
||||||
struct wl_listener layout_destroy;
|
struct wl_listener layout_destroy;
|
||||||
struct wl_listener destroy;
|
struct wl_listener destroy;
|
||||||
struct wl_listener commit;
|
|
||||||
struct wl_listener present;
|
struct wl_listener present;
|
||||||
struct wl_listener frame;
|
struct wl_listener frame;
|
||||||
struct wl_listener request_state;
|
struct wl_listener request_state;
|
||||||
|
@ -74,7 +73,6 @@ 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;
|
|
||||||
bool allow_tearing;
|
bool allow_tearing;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -95,6 +93,10 @@ struct sway_output *output_from_wlr_output(struct wlr_output *output);
|
||||||
struct sway_output *output_get_in_direction(struct sway_output *reference,
|
struct sway_output *output_get_in_direction(struct sway_output *reference,
|
||||||
enum wlr_direction direction);
|
enum wlr_direction direction);
|
||||||
|
|
||||||
|
void output_configure_scene(struct sway_output *output,
|
||||||
|
struct wlr_scene_node *node, float opacity, int corner_radius,
|
||||||
|
bool blur_enabled, bool has_titlebar, struct sway_container *closest_con);
|
||||||
|
|
||||||
void output_add_workspace(struct sway_output *output,
|
void output_add_workspace(struct sway_output *output,
|
||||||
struct sway_workspace *workspace);
|
struct sway_workspace *workspace);
|
||||||
|
|
||||||
|
@ -138,9 +140,6 @@ enum sway_container_layout output_get_default_layout(
|
||||||
|
|
||||||
enum wlr_direction opposite_direction(enum wlr_direction d);
|
enum wlr_direction opposite_direction(enum wlr_direction d);
|
||||||
|
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
@ -27,7 +27,7 @@ struct sway_session_lock {
|
||||||
struct sway_server {
|
struct sway_server {
|
||||||
struct wl_display *wl_display;
|
struct wl_display *wl_display;
|
||||||
struct wl_event_loop *wl_event_loop;
|
struct wl_event_loop *wl_event_loop;
|
||||||
const char *socket;
|
char *socket;
|
||||||
|
|
||||||
struct wlr_backend *backend;
|
struct wlr_backend *backend;
|
||||||
struct wlr_session *session;
|
struct wlr_session *session;
|
||||||
|
@ -46,6 +46,7 @@ struct sway_server {
|
||||||
|
|
||||||
struct wl_listener new_output;
|
struct wl_listener new_output;
|
||||||
struct wl_listener renderer_lost;
|
struct wl_listener renderer_lost;
|
||||||
|
struct wl_event_source *recreating_renderer;
|
||||||
|
|
||||||
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;
|
||||||
|
@ -104,8 +105,10 @@ struct sway_server {
|
||||||
struct wlr_ext_foreign_toplevel_list_v1 *foreign_toplevel_list;
|
struct wlr_ext_foreign_toplevel_list_v1 *foreign_toplevel_list;
|
||||||
struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_manager;
|
struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_manager;
|
||||||
struct wlr_content_type_manager_v1 *content_type_manager_v1;
|
struct wlr_content_type_manager_v1 *content_type_manager_v1;
|
||||||
struct wlr_data_control_manager_v1 *data_control_manager_v1;
|
struct wlr_data_control_manager_v1 *wlr_data_control_manager_v1;
|
||||||
|
struct wlr_ext_data_control_manager_v1 *ext_data_control_manager_v1;
|
||||||
struct wlr_screencopy_manager_v1 *screencopy_manager_v1;
|
struct wlr_screencopy_manager_v1 *screencopy_manager_v1;
|
||||||
|
struct wlr_ext_image_copy_capture_manager_v1 *ext_image_copy_capture_manager_v1;
|
||||||
struct wlr_export_dmabuf_manager_v1 *export_dmabuf_manager_v1;
|
struct wlr_export_dmabuf_manager_v1 *export_dmabuf_manager_v1;
|
||||||
struct wlr_security_context_manager_v1 *security_context_manager_v1;
|
struct wlr_security_context_manager_v1 *security_context_manager_v1;
|
||||||
|
|
||||||
|
@ -148,20 +151,19 @@ struct sway_debug {
|
||||||
bool noatomic; // Ignore atomic layout updates
|
bool noatomic; // Ignore atomic layout updates
|
||||||
bool txn_timings; // Log verbose messages about transactions
|
bool txn_timings; // Log verbose messages about transactions
|
||||||
bool txn_wait; // Always wait for the timeout before applying
|
bool txn_wait; // Always wait for the timeout before applying
|
||||||
bool legacy_wl_drm; // Enable the legacy wl_drm interface
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct sway_debug debug;
|
extern struct sway_debug debug;
|
||||||
|
|
||||||
extern bool allow_unsupported_gpu;
|
extern bool allow_unsupported_gpu;
|
||||||
|
|
||||||
|
void sway_terminate(int exit_code);
|
||||||
|
|
||||||
bool server_init(struct sway_server *server);
|
bool server_init(struct sway_server *server);
|
||||||
void server_fini(struct sway_server *server);
|
void server_fini(struct sway_server *server);
|
||||||
bool server_start(struct sway_server *server);
|
bool server_start(struct sway_server *server);
|
||||||
void server_run(struct sway_server *server);
|
void server_run(struct sway_server *server);
|
||||||
|
|
||||||
void restore_nofile_limit(void);
|
|
||||||
|
|
||||||
void handle_new_output(struct wl_listener *listener, void *data);
|
void handle_new_output(struct wl_listener *listener, void *data);
|
||||||
|
|
||||||
void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data);
|
void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data);
|
||||||
|
|
|
@ -98,6 +98,7 @@ struct sway_container {
|
||||||
|
|
||||||
struct wl_listener output_enter;
|
struct wl_listener output_enter;
|
||||||
struct wl_listener output_leave;
|
struct wl_listener output_leave;
|
||||||
|
struct wl_listener output_handler_destroy;
|
||||||
|
|
||||||
struct sway_container_state current;
|
struct sway_container_state current;
|
||||||
struct sway_container_state pending;
|
struct sway_container_state pending;
|
||||||
|
|
|
@ -223,6 +223,12 @@ const char *view_get_window_role(struct sway_view *view);
|
||||||
|
|
||||||
uint32_t view_get_window_type(struct sway_view *view);
|
uint32_t view_get_window_type(struct sway_view *view);
|
||||||
|
|
||||||
|
const char *view_get_sandbox_engine(struct sway_view *view);
|
||||||
|
|
||||||
|
const char *view_get_sandbox_app_id(struct sway_view *view);
|
||||||
|
|
||||||
|
const char *view_get_sandbox_instance_id(struct sway_view *view);
|
||||||
|
|
||||||
const char *view_get_shell(struct sway_view *view);
|
const char *view_get_shell(struct sway_view *view);
|
||||||
|
|
||||||
void view_get_constraints(struct sway_view *view, double *min_width,
|
void view_get_constraints(struct sway_view *view, double *min_width,
|
||||||
|
|
|
@ -96,7 +96,7 @@ void workspace_output_add_priority(struct sway_workspace *workspace,
|
||||||
struct sway_output *output);
|
struct sway_output *output);
|
||||||
|
|
||||||
struct sway_output *workspace_output_get_highest_available(
|
struct sway_output *workspace_output_get_highest_available(
|
||||||
struct sway_workspace *ws, struct sway_output *exclude);
|
struct sway_workspace *ws);
|
||||||
|
|
||||||
void workspace_detect_urgent(struct sway_workspace *workspace);
|
void workspace_detect_urgent(struct sway_workspace *workspace);
|
||||||
|
|
||||||
|
|
33
meson.build
33
meson.build
|
@ -3,7 +3,7 @@ project(
|
||||||
'c',
|
'c',
|
||||||
version: '0.5.1',
|
version: '0.5.1',
|
||||||
license: 'MIT',
|
license: 'MIT',
|
||||||
meson_version: '>=0.60.0',
|
meson_version: '>=1.3',
|
||||||
default_options: [
|
default_options: [
|
||||||
'c_std=c11',
|
'c_std=c11',
|
||||||
'warning_level=2',
|
'warning_level=2',
|
||||||
|
@ -47,14 +47,14 @@ subproject(
|
||||||
scenefx = dependency('scenefx-0.3', fallback: 'scenefx')
|
scenefx = dependency('scenefx-0.3', fallback: 'scenefx')
|
||||||
|
|
||||||
# Execute the wlroots subproject, if any
|
# Execute the wlroots subproject, if any
|
||||||
wlroots_version = ['>=0.18.0', '<0.19.0']
|
wlroots_version = ['>=0.19.0', '<0.20.0']
|
||||||
subproject(
|
subproject(
|
||||||
'wlroots',
|
'wlroots',
|
||||||
default_options: ['examples=false'],
|
default_options: ['examples=false'],
|
||||||
required: false,
|
required: false,
|
||||||
version: wlroots_version,
|
version: wlroots_version,
|
||||||
)
|
)
|
||||||
wlroots = dependency('wlroots-0.18', version: wlroots_version, fallback: 'wlroots')
|
wlroots = dependency('wlroots-0.19', version: wlroots_version, fallback: 'wlroots')
|
||||||
wlroots_features = {
|
wlroots_features = {
|
||||||
'xwayland': false,
|
'xwayland': false,
|
||||||
'libinput_backend': false,
|
'libinput_backend': false,
|
||||||
|
@ -88,7 +88,7 @@ libudev = wlroots_features['libinput_backend'] ? dependency('libudev') : null_de
|
||||||
math = cc.find_library('m')
|
math = cc.find_library('m')
|
||||||
rt = cc.find_library('rt')
|
rt = cc.find_library('rt')
|
||||||
xcb_icccm = wlroots_features['xwayland'] ? dependency('xcb-icccm') : null_dep
|
xcb_icccm = wlroots_features['xwayland'] ? dependency('xcb-icccm') : null_dep
|
||||||
threads = dependency('threads') # for pthread_setschedparam
|
threads = dependency('threads') # for pthread_setschedparam and pthread_atfork
|
||||||
|
|
||||||
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()
|
||||||
|
@ -181,31 +181,10 @@ add_project_arguments('-DSWAY_VERSION=@0@'.format(version), language: 'c')
|
||||||
add_project_arguments('-DSWAY_ORIGINAL_VERSION="@0@"'.format(original_version), language: 'c')
|
add_project_arguments('-DSWAY_ORIGINAL_VERSION="@0@"'.format(original_version), language: 'c')
|
||||||
add_project_arguments('-DSCENEFX_VERSION="@0@"'.format(scenefx.version()), language: 'c')
|
add_project_arguments('-DSCENEFX_VERSION="@0@"'.format(scenefx.version()), language: 'c')
|
||||||
|
|
||||||
# Compute the relative path used by compiler invocations.
|
fs = import('fs')
|
||||||
source_root = meson.current_source_dir().split('/')
|
|
||||||
build_root = meson.global_build_root().split('/')
|
|
||||||
relative_dir_parts = []
|
|
||||||
i = 0
|
|
||||||
in_prefix = true
|
|
||||||
foreach p : build_root
|
|
||||||
if i >= source_root.length() or not in_prefix or p != source_root[i]
|
|
||||||
in_prefix = false
|
|
||||||
relative_dir_parts += '..'
|
|
||||||
endif
|
|
||||||
i += 1
|
|
||||||
endforeach
|
|
||||||
i = 0
|
|
||||||
in_prefix = true
|
|
||||||
foreach p : source_root
|
|
||||||
if i >= build_root.length() or not in_prefix or build_root[i] != p
|
|
||||||
in_prefix = false
|
|
||||||
relative_dir_parts += p
|
|
||||||
endif
|
|
||||||
i += 1
|
|
||||||
endforeach
|
|
||||||
relative_dir = join_paths(relative_dir_parts) + '/'
|
|
||||||
|
|
||||||
# Strip relative path prefixes from the code if possible, otherwise hide them.
|
# Strip relative path prefixes from the code if possible, otherwise hide them.
|
||||||
|
relative_dir = fs.relative_to(meson.current_source_dir(), meson.global_build_root()) + '/'
|
||||||
if cc.has_argument('-fmacro-prefix-map=/prefix/to/hide=')
|
if cc.has_argument('-fmacro-prefix-map=/prefix/to/hide=')
|
||||||
add_project_arguments(
|
add_project_arguments(
|
||||||
'-fmacro-prefix-map=@0@='.format(relative_dir),
|
'-fmacro-prefix-map=@0@='.format(relative_dir),
|
||||||
|
|
|
@ -9,12 +9,15 @@ wayland_scanner = find_program(
|
||||||
protocols = [
|
protocols = [
|
||||||
wl_protocol_dir / 'stable/tablet/tablet-v2.xml',
|
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/pointer-constraints/pointer-constraints-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',
|
||||||
|
wl_protocol_dir / 'staging/ext-foreign-toplevel-list/ext-foreign-toplevel-list-v1.xml',
|
||||||
|
wl_protocol_dir / 'staging/ext-image-capture-source/ext-image-capture-source-v1.xml',
|
||||||
|
wl_protocol_dir / 'staging/ext-image-copy-capture/ext-image-copy-capture-v1.xml',
|
||||||
wl_protocol_dir / 'staging/tearing-control/tearing-control-v1.xml',
|
wl_protocol_dir / 'staging/tearing-control/tearing-control-v1.xml',
|
||||||
|
wl_protocol_dir / 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml',
|
||||||
|
wl_protocol_dir / 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml',
|
||||||
|
wl_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml',
|
||||||
'wlr-layer-shell-unstable-v1.xml',
|
'wlr-layer-shell-unstable-v1.xml',
|
||||||
'idle.xml',
|
'idle.xml',
|
||||||
'wlr-output-power-management-unstable-v1.xml',
|
'wlr-output-power-management-unstable-v1.xml',
|
||||||
|
|
|
@ -3,3 +3,4 @@ Name=Sway
|
||||||
Comment=An i3-compatible Wayland compositor
|
Comment=An i3-compatible Wayland compositor
|
||||||
Exec=sway
|
Exec=sway
|
||||||
Type=Application
|
Type=Application
|
||||||
|
DesktopNames=sway;wlroots;swayfx
|
||||||
|
|
|
@ -23,7 +23,7 @@ struct cmd_results *cmd_assign(int argc, char **argv) {
|
||||||
|
|
||||||
--argc; ++argv;
|
--argc; ++argv;
|
||||||
|
|
||||||
if (strncmp(*argv, "→", strlen("→")) == 0) {
|
if (has_prefix(*argv, "→")) {
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
free(criteria);
|
free(criteria);
|
||||||
return cmd_results_new(CMD_INVALID, "Missing workspace");
|
return cmd_results_new(CMD_INVALID, "Missing workspace");
|
||||||
|
|
|
@ -11,7 +11,7 @@ struct cmd_results *bar_cmd_font(int argc, char **argv) {
|
||||||
char *font = join_args(argv, argc);
|
char *font = join_args(argv, argc);
|
||||||
free(config->current_bar->font);
|
free(config->current_bar->font);
|
||||||
|
|
||||||
if (strncmp(font, "pango:", 6) == 0) {
|
if (has_prefix(font, "pango:")) {
|
||||||
if (config->current_bar->pango_markup == PANGO_MARKUP_DEFAULT) {
|
if (config->current_bar->pango_markup == PANGO_MARKUP_DEFAULT) {
|
||||||
config->current_bar->pango_markup = true;
|
config->current_bar->pango_markup = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -367,8 +367,7 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv,
|
||||||
}
|
}
|
||||||
} else if (strcmp("--exclude-titlebar", argv[0]) == 0) {
|
} else if (strcmp("--exclude-titlebar", argv[0]) == 0) {
|
||||||
exclude_titlebar = true;
|
exclude_titlebar = true;
|
||||||
} else if (strncmp("--input-device=", argv[0],
|
} else if (has_prefix(argv[0], "--input-device=")) {
|
||||||
strlen("--input-device=")) == 0) {
|
|
||||||
free(binding->input);
|
free(binding->input);
|
||||||
binding->input = strdup(argv[0] + strlen("--input-device="));
|
binding->input = strdup(argv[0] + strlen("--input-device="));
|
||||||
strip_quotes(binding->input);
|
strip_quotes(binding->input);
|
||||||
|
@ -399,7 +398,7 @@ static struct cmd_results *cmd_bindsym_or_bindcode(int argc, char **argv,
|
||||||
list_t *split = split_string(argv[0], "+");
|
list_t *split = split_string(argv[0], "+");
|
||||||
for (int i = 0; i < split->length; ++i) {
|
for (int i = 0; i < split->length; ++i) {
|
||||||
// Check for group
|
// Check for group
|
||||||
if (strncmp(split->items[i], "Group", strlen("Group")) == 0) {
|
if (has_prefix(split->items[i], "Group")) {
|
||||||
if (binding->group != XKB_LAYOUT_INVALID) {
|
if (binding->group != XKB_LAYOUT_INVALID) {
|
||||||
free_sway_binding(binding);
|
free_sway_binding(binding);
|
||||||
list_free_items_and_destroy(split);
|
list_free_items_and_destroy(split);
|
||||||
|
|
|
@ -13,10 +13,7 @@ struct cmd_results *cmd_blur_brightness(int argc, char **argv) {
|
||||||
return cmd_results_new(CMD_FAILURE, "Invalid brightness specified");
|
return cmd_results_new(CMD_FAILURE, "Invalid brightness specified");
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_scene *root_scene = root->root_scene;
|
wlr_scene_set_blur_brightness(root->root_scene, value);
|
||||||
struct blur_data blur_data = root_scene->blur_data;
|
|
||||||
blur_data.brightness = value;
|
|
||||||
wlr_scene_set_blur_data(root_scene, blur_data);
|
|
||||||
|
|
||||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,7 @@ struct cmd_results *cmd_blur_contrast(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_scene *root_scene = root->root_scene;
|
struct wlr_scene *root_scene = root->root_scene;
|
||||||
struct blur_data blur_data = root_scene->blur_data;
|
wlr_scene_set_blur_contrast(root_scene, value);
|
||||||
blur_data.contrast = value;
|
|
||||||
wlr_scene_set_blur_data(root_scene, blur_data);
|
|
||||||
|
|
||||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
#include "scenefx/render/fx_renderer/fx_effect_framebuffers.h"
|
|
||||||
#include "sway/commands.h"
|
#include "sway/commands.h"
|
||||||
#include "sway/config.h"
|
|
||||||
#include "sway/output.h"
|
|
||||||
|
|
||||||
struct cmd_results *cmd_blur_noise(int argc, char **argv) {
|
struct cmd_results *cmd_blur_noise(int argc, char **argv) {
|
||||||
struct cmd_results *error = NULL;
|
struct cmd_results *error = NULL;
|
||||||
|
@ -16,9 +13,7 @@ struct cmd_results *cmd_blur_noise(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_scene *root_scene = root->root_scene;
|
struct wlr_scene *root_scene = root->root_scene;
|
||||||
struct blur_data blur_data = root_scene->blur_data;
|
wlr_scene_set_blur_noise(root_scene, value);
|
||||||
blur_data.noise = value;
|
|
||||||
wlr_scene_set_blur_data(root_scene, blur_data);
|
|
||||||
|
|
||||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,7 @@ struct cmd_results *cmd_blur_passes(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_scene *root_scene = root->root_scene;
|
struct wlr_scene *root_scene = root->root_scene;
|
||||||
struct blur_data blur_data = root_scene->blur_data;
|
wlr_scene_set_blur_num_passes(root_scene, value);
|
||||||
blur_data.num_passes = value;
|
|
||||||
wlr_scene_set_blur_data(root_scene, blur_data);
|
|
||||||
|
|
||||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,7 @@ struct cmd_results *cmd_blur_radius(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_scene *root_scene = root->root_scene;
|
struct wlr_scene *root_scene = root->root_scene;
|
||||||
struct blur_data blur_data = root_scene->blur_data;
|
wlr_scene_set_blur_radius(root_scene, value);
|
||||||
blur_data.radius = value;
|
|
||||||
wlr_scene_set_blur_data(root_scene, blur_data);
|
|
||||||
|
|
||||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,7 @@ struct cmd_results *cmd_blur_saturation(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_scene *root_scene = root->root_scene;
|
struct wlr_scene *root_scene = root->root_scene;
|
||||||
struct blur_data blur_data = root_scene->blur_data;
|
wlr_scene_set_blur_brightness(root_scene, value);
|
||||||
blur_data.saturation = value;
|
|
||||||
wlr_scene_set_blur_data(root_scene, blur_data);
|
|
||||||
|
|
||||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,10 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <signal.h>
|
|
||||||
#include "sway/commands.h"
|
#include "sway/commands.h"
|
||||||
#include "sway/config.h"
|
#include "sway/config.h"
|
||||||
#include "sway/server.h"
|
|
||||||
#include "sway/desktop/launcher.h"
|
#include "sway/desktop/launcher.h"
|
||||||
#include "sway/tree/container.h"
|
|
||||||
#include "sway/tree/root.h"
|
|
||||||
#include "sway/tree/workspace.h"
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "stringop.h"
|
#include "stringop.h"
|
||||||
|
|
||||||
|
@ -25,16 +19,6 @@ struct cmd_results *cmd_exec_validate(int argc, char **argv) {
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void export_xdga_token(struct launcher_ctx *ctx) {
|
|
||||||
const char *token = launcher_ctx_get_token_name(ctx);
|
|
||||||
setenv("XDG_ACTIVATION_TOKEN", token, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void export_startup_id(struct launcher_ctx *ctx) {
|
|
||||||
const char *token = launcher_ctx_get_token_name(ctx);
|
|
||||||
setenv("DESKTOP_STARTUP_ID", token, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct cmd_results *cmd_exec_process(int argc, char **argv) {
|
struct cmd_results *cmd_exec_process(int argc, char **argv) {
|
||||||
struct cmd_results *error = NULL;
|
struct cmd_results *error = NULL;
|
||||||
char *cmd = NULL;
|
char *cmd = NULL;
|
||||||
|
@ -56,67 +40,36 @@ struct cmd_results *cmd_exec_process(int argc, char **argv) {
|
||||||
|
|
||||||
sway_log(SWAY_DEBUG, "Executing %s", cmd);
|
sway_log(SWAY_DEBUG, "Executing %s", cmd);
|
||||||
|
|
||||||
int fd[2];
|
|
||||||
if (pipe(fd) != 0) {
|
|
||||||
sway_log(SWAY_ERROR, "Unable to create pipe for fork");
|
|
||||||
}
|
|
||||||
|
|
||||||
pid_t pid, child;
|
|
||||||
struct launcher_ctx *ctx = launcher_ctx_create_internal();
|
struct launcher_ctx *ctx = launcher_ctx_create_internal();
|
||||||
|
|
||||||
// Fork process
|
// Fork process
|
||||||
if ((pid = fork()) == 0) {
|
pid_t child = fork();
|
||||||
// Fork child process again
|
if (child == 0) {
|
||||||
restore_nofile_limit();
|
|
||||||
setsid();
|
setsid();
|
||||||
sigset_t set;
|
if (ctx) {
|
||||||
sigemptyset(&set);
|
const char *token = launcher_ctx_get_token_name(ctx);
|
||||||
sigprocmask(SIG_SETMASK, &set, NULL);
|
setenv("XDG_ACTIVATION_TOKEN", token, 1);
|
||||||
signal(SIGPIPE, SIG_DFL);
|
if (!no_startup_id) {
|
||||||
close(fd[0]);
|
setenv("DESKTOP_STARTUP_ID", token, 1);
|
||||||
if ((child = fork()) == 0) {
|
|
||||||
close(fd[1]);
|
|
||||||
if (ctx) {
|
|
||||||
export_xdga_token(ctx);
|
|
||||||
}
|
}
|
||||||
if (ctx && !no_startup_id) {
|
|
||||||
export_startup_id(ctx);
|
|
||||||
}
|
|
||||||
execlp("sh", "sh", "-c", cmd, (void *)NULL);
|
|
||||||
sway_log_errno(SWAY_ERROR, "execlp failed");
|
|
||||||
_exit(1);
|
|
||||||
}
|
}
|
||||||
ssize_t s = 0;
|
|
||||||
while ((size_t)s < sizeof(pid_t)) {
|
execlp("sh", "sh", "-c", cmd, (void*)NULL);
|
||||||
s += write(fd[1], ((uint8_t *)&child) + s, sizeof(pid_t) - s);
|
sway_log_errno(SWAY_ERROR, "execve failed");
|
||||||
}
|
|
||||||
close(fd[1]);
|
|
||||||
_exit(0); // Close child process
|
_exit(0); // Close child process
|
||||||
} else if (pid < 0) {
|
} else if (child < 0) {
|
||||||
|
launcher_ctx_destroy(ctx);
|
||||||
free(cmd);
|
free(cmd);
|
||||||
close(fd[0]);
|
|
||||||
close(fd[1]);
|
|
||||||
return cmd_results_new(CMD_FAILURE, "fork() failed");
|
return cmd_results_new(CMD_FAILURE, "fork() failed");
|
||||||
}
|
}
|
||||||
free(cmd);
|
|
||||||
close(fd[1]); // close write
|
sway_log(SWAY_DEBUG, "Child process created with pid %d", child);
|
||||||
ssize_t s = 0;
|
if (ctx != NULL) {
|
||||||
while ((size_t)s < sizeof(pid_t)) {
|
sway_log(SWAY_DEBUG, "Recording workspace for process %d", child);
|
||||||
s += read(fd[0], ((uint8_t *)&child) + s, sizeof(pid_t) - s);
|
ctx->pid = child;
|
||||||
}
|
|
||||||
close(fd[0]);
|
|
||||||
// cleanup child process
|
|
||||||
waitpid(pid, NULL, 0);
|
|
||||||
if (child > 0) {
|
|
||||||
sway_log(SWAY_DEBUG, "Child process created with pid %d", child);
|
|
||||||
if (ctx != NULL) {
|
|
||||||
sway_log(SWAY_DEBUG, "Recording workspace for process %d", child);
|
|
||||||
ctx->pid = child;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
launcher_ctx_destroy(ctx);
|
|
||||||
return cmd_results_new(CMD_FAILURE, "Second fork() failed");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(cmd);
|
||||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "sway/commands.h"
|
#include "sway/commands.h"
|
||||||
#include "sway/config.h"
|
#include "sway/config.h"
|
||||||
|
#include "sway/server.h"
|
||||||
void sway_terminate(int exit_code);
|
|
||||||
|
|
||||||
struct cmd_results *cmd_exit(int argc, char **argv) {
|
struct cmd_results *cmd_exit(int argc, char **argv) {
|
||||||
struct cmd_results *error = NULL;
|
struct cmd_results *error = NULL;
|
||||||
|
|
|
@ -13,9 +13,9 @@ struct cmd_results *cmd_font(int argc, char **argv) {
|
||||||
char *font = join_args(argv, argc);
|
char *font = join_args(argv, argc);
|
||||||
free(config->font);
|
free(config->font);
|
||||||
|
|
||||||
if (strncmp(font, "pango:", 6) == 0) {
|
if (has_prefix(font, "pango:")) {
|
||||||
config->pango_markup = true;
|
config->pango_markup = true;
|
||||||
config->font = strdup(font + 6);
|
config->font = strdup(font + strlen("pango:"));
|
||||||
free(font);
|
free(font);
|
||||||
} else {
|
} else {
|
||||||
config->pango_markup = false;
|
config->pango_markup = false;
|
||||||
|
|
|
@ -121,8 +121,7 @@ static struct cmd_results *cmd_bind_or_unbind_gesture(int argc, char **argv, boo
|
||||||
binding->flags |= BINDING_EXACT;
|
binding->flags |= BINDING_EXACT;
|
||||||
} else if (strcmp("--no-warn", argv[0]) == 0) {
|
} else if (strcmp("--no-warn", argv[0]) == 0) {
|
||||||
warn = false;
|
warn = false;
|
||||||
} else if (strncmp("--input-device=", argv[0],
|
} else if (has_prefix(argv[0], "--input-device=")) {
|
||||||
strlen("--input-device=")) == 0) {
|
|
||||||
free(binding->input);
|
free(binding->input);
|
||||||
binding->input = strdup(argv[0] + strlen("--input-device="));
|
binding->input = strdup(argv[0] + strlen("--input-device="));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -3,12 +3,12 @@
|
||||||
|
|
||||||
struct cmd_results *cmd_include(int argc, char **argv) {
|
struct cmd_results *cmd_include(int argc, char **argv) {
|
||||||
struct cmd_results *error = NULL;
|
struct cmd_results *error = NULL;
|
||||||
if ((error = checkarg(argc, "include", EXPECTED_EQUAL_TO, 1))) {
|
if ((error = checkarg(argc, "include", EXPECTED_AT_LEAST, 1))) {
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
char *files = join_args(argv, argc);
|
||||||
// We don't care if the included config(s) fails to load.
|
// We don't care if the included config(s) fails to load.
|
||||||
load_include_configs(argv[0], config, &config->swaynag_config_errors);
|
load_include_configs(files, config, &config->swaynag_config_errors);
|
||||||
|
|
||||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,11 @@ struct cmd_results *input_cmd_drag_lock(int argc, char **argv) {
|
||||||
return cmd_results_new(CMD_FAILURE, "No input device defined.");
|
return cmd_results_new(CMD_FAILURE, "No input device defined.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if HAVE_LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY
|
||||||
|
if (strcmp(argv[0], "enabled_sticky") == 0) {
|
||||||
|
ic->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
if (parse_boolean(argv[0], true)) {
|
if (parse_boolean(argv[0], true)) {
|
||||||
ic->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_ENABLED;
|
ic->drag_lock = LIBINPUT_CONFIG_DRAG_LOCK_ENABLED;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -86,7 +86,7 @@ static void toggle_select_send_events_for_device(struct input_config *ic,
|
||||||
static void toggle_send_events(int argc, char **argv) {
|
static void toggle_send_events(int argc, char **argv) {
|
||||||
struct input_config *ic = config->handler_context.input_config;
|
struct input_config *ic = config->handler_context.input_config;
|
||||||
bool wildcard = strcmp(ic->identifier, "*") == 0;
|
bool wildcard = strcmp(ic->identifier, "*") == 0;
|
||||||
const char *type = strncmp(ic->identifier, "type:", strlen("type:")) == 0
|
const char *type = has_prefix(ic->identifier, "type:")
|
||||||
? ic->identifier + strlen("type:") : NULL;
|
? ic->identifier + strlen("type:") : NULL;
|
||||||
struct sway_input_device *device = NULL;
|
struct sway_input_device *device = NULL;
|
||||||
wl_list_for_each(device, &server.input->devices, link) {
|
wl_list_for_each(device, &server.input->devices, link) {
|
||||||
|
@ -146,8 +146,7 @@ struct cmd_results *input_cmd_events(int argc, char **argv) {
|
||||||
|
|
||||||
toggle_send_events(argc - 1, argv + 1);
|
toggle_send_events(argc - 1, argv + 1);
|
||||||
|
|
||||||
if (strcmp(ic->identifier, "*") == 0 ||
|
if (strcmp(ic->identifier, "*") == 0 || has_prefix(ic->identifier, "type:")) {
|
||||||
strncmp(ic->identifier, "type:", strlen("type:")) == 0) {
|
|
||||||
// Update the device input configs and then reset the type/wildcard
|
// Update the device input configs and then reset the type/wildcard
|
||||||
// config send events mode so that is does not override the device
|
// config send events mode so that is does not override the device
|
||||||
// ones. The device ones will be applied when attempting to apply
|
// ones. The device ones will be applied when attempting to apply
|
||||||
|
|
|
@ -23,7 +23,7 @@ struct cmd_results *cmd_mark(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool add = false, toggle = false;
|
bool add = false, toggle = false;
|
||||||
while (argc > 0 && strncmp(*argv, "--", 2) == 0) {
|
while (argc > 0 && has_prefix(*argv, "--")) {
|
||||||
if (strcmp(*argv, "--add") == 0) {
|
if (strcmp(*argv, "--add") == 0) {
|
||||||
add = true;
|
add = true;
|
||||||
} else if (strcmp(*argv, "--replace") == 0) {
|
} else if (strcmp(*argv, "--replace") == 0) {
|
||||||
|
|
|
@ -222,6 +222,7 @@ static void container_move_to_workspace(struct sway_container *container,
|
||||||
container_detach(container);
|
container_detach(container);
|
||||||
if (workspace_is_empty(workspace) && container->pending.children) {
|
if (workspace_is_empty(workspace) && container->pending.children) {
|
||||||
workspace_unwrap_children(workspace, container);
|
workspace_unwrap_children(workspace, container);
|
||||||
|
container_reap_empty(container);
|
||||||
} else {
|
} else {
|
||||||
container->pending.width = container->pending.height = 0;
|
container->pending.width = container->pending.height = 0;
|
||||||
container->width_fraction = container->height_fraction = 0;
|
container->width_fraction = container->height_fraction = 0;
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
#include "sway/commands.h"
|
#include "sway/commands.h"
|
||||||
#include "sway/tree/view.h"
|
#include "sway/tree/container.h"
|
||||||
|
#include "sway/output.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
struct cmd_results *cmd_opacity(int argc, char **argv) {
|
struct cmd_results *cmd_opacity(int argc, char **argv) {
|
||||||
|
@ -37,6 +38,8 @@ struct cmd_results *cmd_opacity(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
con->alpha = val;
|
con->alpha = val;
|
||||||
|
output_configure_scene(NULL, &con->scene_tree->node,
|
||||||
|
1.0f, 0, false, false, NULL);
|
||||||
container_update(con);
|
container_update(con);
|
||||||
|
|
||||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||||
|
|
|
@ -3,10 +3,8 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
|
||||||
#include "sway/commands.h"
|
#include "sway/commands.h"
|
||||||
#include "sway/config.h"
|
#include "sway/config.h"
|
||||||
#include "sway/swaynag.h"
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "stringop.h"
|
#include "stringop.h"
|
||||||
|
|
||||||
|
@ -42,14 +40,14 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct output_config *output = config->handler_context.output_config;
|
struct output_config *output = config->handler_context.output_config;
|
||||||
|
char *src = NULL;
|
||||||
if (strcasecmp(argv[1], "solid_color") == 0) {
|
if (strcasecmp(argv[1], "solid_color") == 0) {
|
||||||
if (!validate_color(argv[0])) {
|
if (!validate_color(argv[0])) {
|
||||||
return cmd_results_new(CMD_INVALID,
|
return cmd_results_new(CMD_INVALID,
|
||||||
"Colors should be of the form #RRGGBB");
|
"Colors should be of the form #RRGGBB");
|
||||||
}
|
}
|
||||||
output->background = strdup(argv[0]);
|
if (!(output->background = strdup(argv[0]))) goto cleanup;
|
||||||
output->background_option = strdup("solid_color");
|
if (!(output->background_option = strdup("solid_color"))) goto cleanup;
|
||||||
output->background_fallback = NULL;
|
output->background_fallback = NULL;
|
||||||
argc -= 2; argv += 2;
|
argc -= 2; argv += 2;
|
||||||
} else {
|
} else {
|
||||||
|
@ -77,37 +75,25 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
|
||||||
return cmd_results_new(CMD_INVALID, "Missing background file");
|
return cmd_results_new(CMD_INVALID, "Missing background file");
|
||||||
}
|
}
|
||||||
|
|
||||||
char *src = join_args(argv, j);
|
if (!(src = join_args(argv, j))) goto cleanup;
|
||||||
if (!expand_path(&src)) {
|
if (!expand_path(&src)) {
|
||||||
struct cmd_results *cmd_res = cmd_results_new(CMD_INVALID,
|
struct cmd_results *cmd_res = cmd_results_new(CMD_INVALID,
|
||||||
"Invalid syntax (%s)", src);
|
"Invalid syntax (%s)", src);
|
||||||
free(src);
|
free(src);
|
||||||
return cmd_res;
|
return cmd_res;
|
||||||
}
|
}
|
||||||
if (!src) {
|
|
||||||
sway_log(SWAY_ERROR, "Failed to allocate expanded path");
|
|
||||||
return cmd_results_new(CMD_FAILURE, "Unable to allocate resource");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config->reading && *src != '/') {
|
if (config->reading && *src != '/') {
|
||||||
// src file is inside configuration dir
|
// src file is inside configuration dir
|
||||||
|
|
||||||
char *conf = strdup(config->current_config_path);
|
char *conf = strdup(config->current_config_path);
|
||||||
if (!conf) {
|
if (!conf) goto cleanup;
|
||||||
sway_log(SWAY_ERROR, "Failed to duplicate string");
|
|
||||||
free(src);
|
|
||||||
return cmd_results_new(CMD_FAILURE,
|
|
||||||
"Unable to allocate resources");
|
|
||||||
}
|
|
||||||
|
|
||||||
char *conf_path = dirname(conf);
|
char *conf_path = dirname(conf);
|
||||||
char *real_src = malloc(strlen(conf_path) + strlen(src) + 2);
|
char *real_src = malloc(strlen(conf_path) + strlen(src) + 2);
|
||||||
if (!real_src) {
|
if (!real_src) {
|
||||||
free(src);
|
|
||||||
free(conf);
|
free(conf);
|
||||||
sway_log(SWAY_ERROR, "Unable to allocate memory");
|
goto cleanup;
|
||||||
return cmd_results_new(CMD_FAILURE,
|
|
||||||
"Unable to allocate resources");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(real_src, strlen(conf_path) + strlen(src) + 2, "%s/%s", conf_path, src);
|
snprintf(real_src, strlen(conf_path) + strlen(src) + 2, "%s/%s", conf_path, src);
|
||||||
|
@ -117,40 +103,48 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool can_access = access(src, F_OK) != -1;
|
bool can_access = access(src, F_OK) != -1;
|
||||||
|
argc -= j + 1; argv += j + 1;
|
||||||
|
free(output->background_option);
|
||||||
|
free(output->background_fallback);
|
||||||
|
free(output->background);
|
||||||
|
output->background = output->background_option = output->background_fallback = NULL;
|
||||||
|
char *fallback = NULL;
|
||||||
|
|
||||||
|
if (argc && *argv[0] == '#') {
|
||||||
|
if (validate_color(argv[0])) {
|
||||||
|
if (!(fallback = strdup(argv[0]))) goto cleanup;
|
||||||
|
output->background_fallback = fallback;
|
||||||
|
} else {
|
||||||
|
sway_log(SWAY_ERROR, "fallback '%s' should be of the form #RRGGBB", argv[0]);
|
||||||
|
config_add_swaynag_warning("fallback '%s' should be of the form #RRGGBB\n", argv[0]);
|
||||||
|
}
|
||||||
|
argc--; argv++;
|
||||||
|
}
|
||||||
|
|
||||||
if (!can_access) {
|
if (!can_access) {
|
||||||
sway_log_errno(SWAY_ERROR, "Unable to access background file '%s'",
|
if (!fallback) {
|
||||||
src);
|
sway_log(SWAY_ERROR, "Unable to access background file '%s' "
|
||||||
config_add_swaynag_warning("Unable to access background file '%s'",
|
"and no valid fallback provided", src);
|
||||||
src);
|
struct cmd_results *res = cmd_results_new(CMD_FAILURE, "Unable to access "
|
||||||
struct cmd_results *result = cmd_results_new(CMD_FAILURE,
|
"background file '%s' and no valid fallback provided", src);
|
||||||
"unable to access background file '%s'", src);
|
free(src);
|
||||||
free(src);
|
return res;
|
||||||
return result;
|
}
|
||||||
|
sway_log(SWAY_DEBUG, "Cannot access file '%s', using fallback '%s'", src, fallback);
|
||||||
|
output->background = fallback;
|
||||||
|
if (!(output->background_option = strdup("solid_color"))) goto cleanup;
|
||||||
|
output->background_fallback = NULL;
|
||||||
} else {
|
} else {
|
||||||
output->background = src;
|
output->background = src;
|
||||||
output->background_option = strdup(mode);
|
if (!(output->background_option = strdup(mode))) goto cleanup;
|
||||||
}
|
|
||||||
argc -= j + 1; argv += j + 1;
|
|
||||||
|
|
||||||
output->background_fallback = NULL;
|
|
||||||
if (argc && *argv[0] == '#') {
|
|
||||||
if (!validate_color(argv[0])) {
|
|
||||||
return cmd_results_new(CMD_INVALID,
|
|
||||||
"fallback color should be of the form #RRGGBB");
|
|
||||||
}
|
|
||||||
|
|
||||||
output->background_fallback = strdup(argv[0]);
|
|
||||||
argc--; argv++;
|
|
||||||
|
|
||||||
if (!can_access) {
|
|
||||||
output->background = output->background_fallback;
|
|
||||||
output->background_option = strdup("solid_color");
|
|
||||||
output->background_fallback = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
config->handler_context.leftovers.argc = argc;
|
config->handler_context.leftovers.argc = argc;
|
||||||
config->handler_context.leftovers.argv = argv;
|
config->handler_context.leftovers.argv = argv;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
free(src);
|
||||||
|
sway_log(SWAY_ERROR, "Failed to allocate resources");
|
||||||
|
return cmd_results_new(CMD_FAILURE, "Unable to allocate resources");
|
||||||
}
|
}
|
||||||
|
|
|
@ -457,7 +457,7 @@ static struct cmd_results *cmd_resize_set(int argc, char **argv) {
|
||||||
if (argc > num_consumed_args) {
|
if (argc > num_consumed_args) {
|
||||||
return cmd_results_new(CMD_INVALID, "%s", usage);
|
return cmd_results_new(CMD_INVALID, "%s", usage);
|
||||||
}
|
}
|
||||||
if (width.unit == MOVEMENT_UNIT_INVALID) {
|
if (height.unit == MOVEMENT_UNIT_INVALID) {
|
||||||
return cmd_results_new(CMD_INVALID, "%s", usage);
|
return cmd_results_new(CMD_INVALID, "%s", usage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,10 +118,10 @@ struct cmd_results *cmd_scratchpad(int argc, char **argv) {
|
||||||
|
|
||||||
// If using criteria, this command is executed for every container which
|
// If using criteria, this command is executed for every container which
|
||||||
// matches the criteria. If this container isn't in the scratchpad,
|
// matches the criteria. If this container isn't in the scratchpad,
|
||||||
// we'll just silently return a success. The same is true if the
|
// we'll return an error. The same is true if the
|
||||||
// overridden node is not a container.
|
// overridden node is not a container.
|
||||||
if (!con || !con->scratchpad) {
|
if (!con || !con->scratchpad) {
|
||||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
return cmd_results_new(CMD_INVALID, "Container is not in scratchpad.");
|
||||||
}
|
}
|
||||||
scratchpad_toggle_container(con);
|
scratchpad_toggle_container(con);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -586,28 +586,12 @@ bool load_main_config(const char *file, bool is_active, bool validating) {
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool load_include_config(const char *path, const char *parent_dir,
|
static bool load_include_config(const char *path, struct sway_config *config,
|
||||||
struct sway_config *config, struct swaynag_instance *swaynag) {
|
struct swaynag_instance *swaynag) {
|
||||||
// save parent config
|
// save parent config
|
||||||
const char *parent_config = config->current_config_path;
|
const char *parent_config = config->current_config_path;
|
||||||
|
|
||||||
char *full_path;
|
char *real_path = realpath(path, NULL);
|
||||||
int len = strlen(path);
|
|
||||||
if (len >= 1 && path[0] != '/') {
|
|
||||||
len = len + strlen(parent_dir) + 2;
|
|
||||||
full_path = malloc(len * sizeof(char));
|
|
||||||
if (!full_path) {
|
|
||||||
sway_log(SWAY_ERROR,
|
|
||||||
"Unable to allocate full path to included config");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
snprintf(full_path, len, "%s/%s", parent_dir, path);
|
|
||||||
} else {
|
|
||||||
full_path = strdup(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *real_path = realpath(full_path, NULL);
|
|
||||||
free(full_path);
|
|
||||||
|
|
||||||
if (real_path == NULL) {
|
if (real_path == NULL) {
|
||||||
sway_log(SWAY_DEBUG, "%s not found.", path);
|
sway_log(SWAY_DEBUG, "%s not found.", path);
|
||||||
|
@ -659,7 +643,7 @@ void load_include_configs(const char *path, struct sway_config *config,
|
||||||
char **w = p.we_wordv;
|
char **w = p.we_wordv;
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < p.we_wordc; ++i) {
|
for (i = 0; i < p.we_wordc; ++i) {
|
||||||
load_include_config(w[i], parent_dir, config, swaynag);
|
load_include_config(w[i], config, swaynag);
|
||||||
}
|
}
|
||||||
wordfree(&p);
|
wordfree(&p);
|
||||||
}
|
}
|
||||||
|
@ -959,8 +943,8 @@ char *do_var_replacement(char *str) {
|
||||||
// Find matching variable
|
// Find matching variable
|
||||||
for (i = 0; i < config->symbols->length; ++i) {
|
for (i = 0; i < config->symbols->length; ++i) {
|
||||||
struct sway_variable *var = config->symbols->items[i];
|
struct sway_variable *var = config->symbols->items[i];
|
||||||
int vnlen = strlen(var->name);
|
if (has_prefix(find, var->name)) {
|
||||||
if (strncmp(find, var->name, vnlen) == 0) {
|
int vnlen = strlen(var->name);
|
||||||
int vvlen = strlen(var->value);
|
int vvlen = strlen(var->value);
|
||||||
char *newstr = malloc(strlen(str) - vnlen + vvlen + 1);
|
char *newstr = malloc(strlen(str) - vnlen + vvlen + 1);
|
||||||
if (!newstr) {
|
if (!newstr) {
|
||||||
|
|
|
@ -213,36 +213,21 @@ static void invoke_swaybar(struct bar_config *bar) {
|
||||||
sway_log(SWAY_ERROR, "Failed to create fork for swaybar");
|
sway_log(SWAY_ERROR, "Failed to create fork for swaybar");
|
||||||
return;
|
return;
|
||||||
} else if (pid == 0) {
|
} else if (pid == 0) {
|
||||||
// Remove the SIGUSR1 handler that wlroots adds for xwayland
|
if (!sway_set_cloexec(sockets[1], false)) {
|
||||||
sigset_t set;
|
|
||||||
sigemptyset(&set);
|
|
||||||
sigprocmask(SIG_SETMASK, &set, NULL);
|
|
||||||
signal(SIGPIPE, SIG_DFL);
|
|
||||||
|
|
||||||
restore_nofile_limit();
|
|
||||||
|
|
||||||
pid = fork();
|
|
||||||
if (pid < 0) {
|
|
||||||
sway_log_errno(SWAY_ERROR, "fork failed");
|
|
||||||
_exit(EXIT_FAILURE);
|
|
||||||
} else if (pid == 0) {
|
|
||||||
if (!sway_set_cloexec(sockets[1], false)) {
|
|
||||||
_exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
char wayland_socket_str[16];
|
|
||||||
snprintf(wayland_socket_str, sizeof(wayland_socket_str),
|
|
||||||
"%d", sockets[1]);
|
|
||||||
setenv("WAYLAND_SOCKET", wayland_socket_str, true);
|
|
||||||
|
|
||||||
// run custom swaybar
|
|
||||||
char *const cmd[] = {
|
|
||||||
bar->swaybar_command ? bar->swaybar_command : "swaybar",
|
|
||||||
"-b", bar->id, NULL};
|
|
||||||
execvp(cmd[0], cmd);
|
|
||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
_exit(EXIT_SUCCESS);
|
|
||||||
|
char wayland_socket_str[16];
|
||||||
|
snprintf(wayland_socket_str, sizeof(wayland_socket_str),
|
||||||
|
"%d", sockets[1]);
|
||||||
|
setenv("WAYLAND_SOCKET", wayland_socket_str, true);
|
||||||
|
|
||||||
|
// run custom swaybar
|
||||||
|
char *const cmd[] = {
|
||||||
|
bar->swaybar_command ? bar->swaybar_command : "swaybar",
|
||||||
|
"-b", bar->id, NULL};
|
||||||
|
execvp(cmd[0], cmd);
|
||||||
|
_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (close(sockets[1]) != 0) {
|
if (close(sockets[1]) != 0) {
|
||||||
|
@ -250,11 +235,6 @@ static void invoke_swaybar(struct bar_config *bar) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (waitpid(pid, NULL, 0) < 0) {
|
|
||||||
sway_log_errno(SWAY_ERROR, "waitpid failed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sway_log(SWAY_DEBUG, "Spawned swaybar %s", bar->id);
|
sway_log(SWAY_DEBUG, "Spawned swaybar %s", bar->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -300,7 +300,7 @@ struct input_config *store_input_config(struct input_config *ic,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool type = strncmp(ic->identifier, "type:", strlen("type:")) == 0;
|
bool type = has_prefix(ic->identifier, "type:");
|
||||||
if (type && error && !validate_type_on_existing(ic, error)) {
|
if (type && error && !validate_type_on_existing(ic, error)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ struct output_config *new_output_config(const char *name) {
|
||||||
oc->refresh_rate = -1;
|
oc->refresh_rate = -1;
|
||||||
oc->custom_mode = -1;
|
oc->custom_mode = -1;
|
||||||
oc->drm_mode.type = -1;
|
oc->drm_mode.type = -1;
|
||||||
oc->x = oc->y = -1;
|
oc->x = oc->y = INT_MAX;
|
||||||
oc->scale = -1;
|
oc->scale = -1;
|
||||||
oc->scale_filter = SCALE_FILTER_DEFAULT;
|
oc->scale_filter = SCALE_FILTER_DEFAULT;
|
||||||
oc->transform = -1;
|
oc->transform = -1;
|
||||||
|
@ -93,11 +93,11 @@ static void supersede_output_config(struct output_config *dst, struct output_con
|
||||||
if (src->height != -1) {
|
if (src->height != -1) {
|
||||||
dst->height = -1;
|
dst->height = -1;
|
||||||
}
|
}
|
||||||
if (src->x != -1) {
|
if (src->x != INT_MAX) {
|
||||||
dst->x = -1;
|
dst->x = INT_MAX;
|
||||||
}
|
}
|
||||||
if (src->y != -1) {
|
if (src->y != INT_MAX) {
|
||||||
dst->y = -1;
|
dst->y = INT_MAX;
|
||||||
}
|
}
|
||||||
if (src->scale != -1) {
|
if (src->scale != -1) {
|
||||||
dst->scale = -1;
|
dst->scale = -1;
|
||||||
|
@ -129,6 +129,13 @@ static void supersede_output_config(struct output_config *dst, struct output_con
|
||||||
if (src->render_bit_depth != RENDER_BIT_DEPTH_DEFAULT) {
|
if (src->render_bit_depth != RENDER_BIT_DEPTH_DEFAULT) {
|
||||||
dst->render_bit_depth = RENDER_BIT_DEPTH_DEFAULT;
|
dst->render_bit_depth = RENDER_BIT_DEPTH_DEFAULT;
|
||||||
}
|
}
|
||||||
|
if (src->set_color_transform) {
|
||||||
|
if (dst->color_transform) {
|
||||||
|
wlr_color_transform_unref(dst->color_transform);
|
||||||
|
dst->color_transform = NULL;
|
||||||
|
}
|
||||||
|
dst->set_color_transform = false;
|
||||||
|
}
|
||||||
if (src->background) {
|
if (src->background) {
|
||||||
free(dst->background);
|
free(dst->background);
|
||||||
dst->background = NULL;
|
dst->background = NULL;
|
||||||
|
@ -144,6 +151,9 @@ static void supersede_output_config(struct output_config *dst, struct output_con
|
||||||
if (src->power != -1) {
|
if (src->power != -1) {
|
||||||
dst->power = -1;
|
dst->power = -1;
|
||||||
}
|
}
|
||||||
|
if (src->allow_tearing != -1) {
|
||||||
|
dst->allow_tearing = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// merge_output_config sets all fields in dst that were set in src
|
// merge_output_config sets all fields in dst that were set in src
|
||||||
|
@ -157,10 +167,10 @@ static void merge_output_config(struct output_config *dst, struct output_config
|
||||||
if (src->height != -1) {
|
if (src->height != -1) {
|
||||||
dst->height = src->height;
|
dst->height = src->height;
|
||||||
}
|
}
|
||||||
if (src->x != -1) {
|
if (src->x != INT_MAX) {
|
||||||
dst->x = src->x;
|
dst->x = src->x;
|
||||||
}
|
}
|
||||||
if (src->y != -1) {
|
if (src->y != INT_MAX) {
|
||||||
dst->y = src->y;
|
dst->y = src->y;
|
||||||
}
|
}
|
||||||
if (src->scale != -1) {
|
if (src->scale != -1) {
|
||||||
|
@ -527,7 +537,7 @@ static bool finalize_output_config(struct output_config *oc, struct sway_output
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find position for it
|
// Find position for it
|
||||||
if (oc && (oc->x != -1 || oc->y != -1)) {
|
if (oc && oc->x != INT_MAX && oc->y != INT_MAX) {
|
||||||
sway_log(SWAY_DEBUG, "Set %s position to %d, %d", oc->name, oc->x, oc->y);
|
sway_log(SWAY_DEBUG, "Set %s position to %d, %d", oc->name, oc->x, oc->y);
|
||||||
wlr_output_layout_add(root->output_layout, wlr_output, oc->x, oc->y);
|
wlr_output_layout_add(root->output_layout, wlr_output, oc->x, oc->y);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1060,42 +1070,27 @@ static bool _spawn_swaybg(char **command) {
|
||||||
sway_log_errno(SWAY_ERROR, "fork failed");
|
sway_log_errno(SWAY_ERROR, "fork failed");
|
||||||
return false;
|
return false;
|
||||||
} else if (pid == 0) {
|
} else if (pid == 0) {
|
||||||
restore_nofile_limit();
|
if (!sway_set_cloexec(sockets[1], false)) {
|
||||||
|
|
||||||
pid = fork();
|
|
||||||
if (pid < 0) {
|
|
||||||
sway_log_errno(SWAY_ERROR, "fork failed");
|
|
||||||
_exit(EXIT_FAILURE);
|
|
||||||
} else if (pid == 0) {
|
|
||||||
if (!sway_set_cloexec(sockets[1], false)) {
|
|
||||||
_exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
char wayland_socket_str[16];
|
|
||||||
snprintf(wayland_socket_str, sizeof(wayland_socket_str),
|
|
||||||
"%d", sockets[1]);
|
|
||||||
setenv("WAYLAND_SOCKET", wayland_socket_str, true);
|
|
||||||
|
|
||||||
execvp(command[0], command);
|
|
||||||
sway_log_errno(SWAY_ERROR, "failed to execute '%s' "
|
|
||||||
"(background configuration probably not applied)",
|
|
||||||
command[0]);
|
|
||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
_exit(EXIT_SUCCESS);
|
|
||||||
|
char wayland_socket_str[16];
|
||||||
|
snprintf(wayland_socket_str, sizeof(wayland_socket_str),
|
||||||
|
"%d", sockets[1]);
|
||||||
|
setenv("WAYLAND_SOCKET", wayland_socket_str, true);
|
||||||
|
|
||||||
|
execvp(command[0], command);
|
||||||
|
sway_log_errno(SWAY_ERROR, "failed to execute '%s' "
|
||||||
|
"(background configuration probably not applied)",
|
||||||
|
command[0]);
|
||||||
|
_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (close(sockets[1]) != 0) {
|
if (close(sockets[1]) != 0) {
|
||||||
sway_log_errno(SWAY_ERROR, "close failed");
|
sway_log_errno(SWAY_ERROR, "close failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int fork_status = 0;
|
return true;
|
||||||
if (waitpid(pid, &fork_status, 0) < 0) {
|
|
||||||
sway_log_errno(SWAY_ERROR, "waitpid failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return WIFEXITED(fork_status) && WEXITSTATUS(fork_status) == EXIT_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool spawn_swaybg(void) {
|
bool spawn_swaybg(void) {
|
||||||
|
|
|
@ -34,7 +34,10 @@ bool criteria_is_empty(struct criteria *criteria) {
|
||||||
&& !criteria->tiling
|
&& !criteria->tiling
|
||||||
&& !criteria->urgent
|
&& !criteria->urgent
|
||||||
&& !criteria->workspace
|
&& !criteria->workspace
|
||||||
&& !criteria->pid;
|
&& !criteria->pid
|
||||||
|
&& !criteria->sandbox_engine
|
||||||
|
&& !criteria->sandbox_app_id
|
||||||
|
&& !criteria->sandbox_instance_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The error pointer is used for parsing functions, and saves having to pass it
|
// The error pointer is used for parsing functions, and saves having to pass it
|
||||||
|
@ -98,6 +101,9 @@ void criteria_destroy(struct criteria *criteria) {
|
||||||
#endif
|
#endif
|
||||||
pattern_destroy(criteria->con_mark);
|
pattern_destroy(criteria->con_mark);
|
||||||
pattern_destroy(criteria->workspace);
|
pattern_destroy(criteria->workspace);
|
||||||
|
pattern_destroy(criteria->sandbox_engine);
|
||||||
|
pattern_destroy(criteria->sandbox_app_id);
|
||||||
|
pattern_destroy(criteria->sandbox_instance_id);
|
||||||
free(criteria->target);
|
free(criteria->target);
|
||||||
free(criteria->cmdlist);
|
free(criteria->cmdlist);
|
||||||
free(criteria->raw);
|
free(criteria->raw);
|
||||||
|
@ -248,6 +254,66 @@ static bool criteria_matches_view(struct criteria *criteria,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (criteria->sandbox_engine) {
|
||||||
|
const char *sandbox_engine = view_get_sandbox_engine(view);
|
||||||
|
if (!sandbox_engine) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (criteria->sandbox_engine->match_type) {
|
||||||
|
case PATTERN_FOCUSED:
|
||||||
|
if (focused && lenient_strcmp(sandbox_engine, view_get_sandbox_engine(focused))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PATTERN_PCRE2:
|
||||||
|
if (regex_cmp(sandbox_engine, criteria->sandbox_engine->regex) < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (criteria->sandbox_app_id) {
|
||||||
|
const char *sandbox_app_id = view_get_sandbox_app_id(view);
|
||||||
|
if (!sandbox_app_id) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (criteria->sandbox_app_id->match_type) {
|
||||||
|
case PATTERN_FOCUSED:
|
||||||
|
if (focused && lenient_strcmp(sandbox_app_id, view_get_sandbox_app_id(focused))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PATTERN_PCRE2:
|
||||||
|
if (regex_cmp(sandbox_app_id, criteria->sandbox_app_id->regex) < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (criteria->sandbox_instance_id) {
|
||||||
|
const char *sandbox_instance_id = view_get_sandbox_instance_id(view);
|
||||||
|
if (!sandbox_instance_id) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (criteria->sandbox_instance_id->match_type) {
|
||||||
|
case PATTERN_FOCUSED:
|
||||||
|
if (focused && lenient_strcmp(sandbox_instance_id, view_get_sandbox_instance_id(focused))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PATTERN_PCRE2:
|
||||||
|
if (regex_cmp(sandbox_instance_id, criteria->sandbox_instance_id->regex) < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!criteria_matches_container(criteria, view->container)) {
|
if (!criteria_matches_container(criteria, view->container)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -475,6 +541,9 @@ enum criteria_token {
|
||||||
T_URGENT,
|
T_URGENT,
|
||||||
T_WORKSPACE,
|
T_WORKSPACE,
|
||||||
T_PID,
|
T_PID,
|
||||||
|
T_SANDBOX_ENGINE,
|
||||||
|
T_SANDBOX_APP_ID,
|
||||||
|
T_SANDBOX_INSTANCE_ID,
|
||||||
|
|
||||||
T_INVALID,
|
T_INVALID,
|
||||||
};
|
};
|
||||||
|
@ -514,6 +583,12 @@ static enum criteria_token token_from_name(char *name) {
|
||||||
return T_FLOATING;
|
return T_FLOATING;
|
||||||
} else if (strcmp(name, "pid") == 0) {
|
} else if (strcmp(name, "pid") == 0) {
|
||||||
return T_PID;
|
return T_PID;
|
||||||
|
} else if (strcmp(name, "sandbox_engine") == 0) {
|
||||||
|
return T_SANDBOX_ENGINE;
|
||||||
|
} else if (strcmp(name, "sandbox_app_id") == 0) {
|
||||||
|
return T_SANDBOX_APP_ID;
|
||||||
|
} else if (strcmp(name, "sandbox_instance_id") == 0) {
|
||||||
|
return T_SANDBOX_INSTANCE_ID;
|
||||||
}
|
}
|
||||||
return T_INVALID;
|
return T_INVALID;
|
||||||
}
|
}
|
||||||
|
@ -555,8 +630,7 @@ static bool parse_token(struct criteria *criteria, char *name, char *value) {
|
||||||
if (strcmp(value, "__focused__") == 0) {
|
if (strcmp(value, "__focused__") == 0) {
|
||||||
struct sway_seat *seat = input_manager_current_seat();
|
struct sway_seat *seat = input_manager_current_seat();
|
||||||
struct sway_container *focus = seat_get_focused_container(seat);
|
struct sway_container *focus = seat_get_focused_container(seat);
|
||||||
struct sway_view *view = focus ? focus->view : NULL;
|
criteria->con_id = focus ? focus->node.id : 0;
|
||||||
criteria->con_id = view ? view->container->node.id : 0;
|
|
||||||
} else {
|
} else {
|
||||||
criteria->con_id = strtoul(value, &endptr, 10);
|
criteria->con_id = strtoul(value, &endptr, 10);
|
||||||
if (*endptr != 0) {
|
if (*endptr != 0) {
|
||||||
|
@ -617,6 +691,15 @@ static bool parse_token(struct criteria *criteria, char *name, char *value) {
|
||||||
error = strdup("The value for 'pid' should be numeric");
|
error = strdup("The value for 'pid' should be numeric");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case T_SANDBOX_ENGINE:
|
||||||
|
pattern_create(&criteria->sandbox_engine, value);
|
||||||
|
break;
|
||||||
|
case T_SANDBOX_APP_ID:
|
||||||
|
pattern_create(&criteria->sandbox_app_id, value);
|
||||||
|
break;
|
||||||
|
case T_SANDBOX_INSTANCE_ID:
|
||||||
|
pattern_create(&criteria->sandbox_instance_id, value);
|
||||||
|
break;
|
||||||
case T_INVALID:
|
case T_INVALID:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <wlr/types/wlr_idle_notify_v1.h>
|
#include <wlr/types/wlr_idle_notify_v1.h>
|
||||||
|
#include <wlr/types/wlr_session_lock_v1.h>
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "sway/desktop/idle_inhibit_v1.h"
|
#include "sway/desktop/idle_inhibit_v1.h"
|
||||||
#include "sway/input/seat.h"
|
#include "sway/input/seat.h"
|
||||||
|
@ -44,6 +45,14 @@ void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data) {
|
||||||
sway_idle_inhibit_v1_check_active();
|
sway_idle_inhibit_v1_check_active();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handle_manager_destroy(struct wl_listener *listener, void *data) {
|
||||||
|
struct sway_idle_inhibit_manager_v1 *manager =
|
||||||
|
wl_container_of(listener, manager, manager_destroy);
|
||||||
|
|
||||||
|
wl_list_remove(&manager->manager_destroy.link);
|
||||||
|
wl_list_remove(&manager->new_idle_inhibitor_v1.link);
|
||||||
|
}
|
||||||
|
|
||||||
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_inhibit_manager_v1 *manager = &server.idle_inhibit_manager_v1;
|
||||||
|
@ -103,11 +112,34 @@ void sway_idle_inhibit_v1_user_inhibitor_destroy(
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sway_idle_inhibit_v1_is_active(struct sway_idle_inhibitor_v1 *inhibitor) {
|
bool sway_idle_inhibit_v1_is_active(struct sway_idle_inhibitor_v1 *inhibitor) {
|
||||||
|
if (server.session_lock.lock) {
|
||||||
|
// A session lock is active. In this case, only application inhibitors
|
||||||
|
// on the session lock surface can have any effect.
|
||||||
|
if (inhibitor->mode != INHIBIT_IDLE_APPLICATION) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
struct wlr_surface *wlr_surface = inhibitor->wlr_inhibitor->surface;
|
||||||
|
if (!wlr_session_lock_surface_v1_try_from_wlr_surface(wlr_surface)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return wlr_surface->mapped;
|
||||||
|
}
|
||||||
|
|
||||||
switch (inhibitor->mode) {
|
switch (inhibitor->mode) {
|
||||||
case INHIBIT_IDLE_APPLICATION:;
|
case INHIBIT_IDLE_APPLICATION:;
|
||||||
// If there is no view associated with the inhibitor, assume visible
|
struct wlr_surface *wlr_surface = inhibitor->wlr_inhibitor->surface;
|
||||||
struct sway_view *view = view_from_wlr_surface(inhibitor->wlr_inhibitor->surface);
|
struct wlr_layer_surface_v1 *layer_surface =
|
||||||
return !view || !view->container || view_is_visible(view);
|
wlr_layer_surface_v1_try_from_wlr_surface(wlr_surface);
|
||||||
|
if (layer_surface) {
|
||||||
|
// Layer surfaces can be occluded but are always on screen after
|
||||||
|
// they have been mapped.
|
||||||
|
return layer_surface->output && layer_surface->output->enabled &&
|
||||||
|
wlr_surface->mapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is no view associated with the inhibitor, assume invisible
|
||||||
|
struct sway_view *view = view_from_wlr_surface(wlr_surface);
|
||||||
|
return view && view->container && view_is_visible(view);
|
||||||
case INHIBIT_IDLE_FOCUS:;
|
case INHIBIT_IDLE_FOCUS:;
|
||||||
struct sway_seat *seat = NULL;
|
struct sway_seat *seat = NULL;
|
||||||
wl_list_for_each(seat, &server.input->seats, link) {
|
wl_list_for_each(seat, &server.input->seats, link) {
|
||||||
|
@ -153,6 +185,9 @@ bool sway_idle_inhibit_manager_v1_init(void) {
|
||||||
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_signal_add(&manager->wlr_manager->events.destroy,
|
||||||
|
&manager->manager_destroy);
|
||||||
|
manager->manager_destroy.notify = handle_manager_destroy;
|
||||||
wl_list_init(&manager->inhibitors);
|
wl_list_init(&manager->inhibitors);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -286,7 +286,7 @@ static void handle_output_destroy(struct wl_listener *listener, void *data) {
|
||||||
wl_container_of(listener, layer, output_destroy);
|
wl_container_of(listener, layer, output_destroy);
|
||||||
|
|
||||||
layer->output = NULL;
|
layer->output = NULL;
|
||||||
wlr_scene_node_destroy(&layer->scene->tree->node);
|
wlr_layer_surface_v1_destroy(layer->layer_surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_node_destroy(struct wl_listener *listener, void *data) {
|
static void handle_node_destroy(struct wl_listener *listener, void *data) {
|
||||||
|
@ -311,8 +311,7 @@ static void handle_node_destroy(struct wl_listener *listener, void *data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_layer_surface_v1 *wlr_layer_surface = layer->layer_surface;
|
struct wlr_layer_surface_v1 *wlr_layer_surface = layer->layer_surface;
|
||||||
if (wlr_layer_surface->current.layer ==
|
if (wlr_layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND ||
|
||||||
ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND ||
|
|
||||||
wlr_layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM) {
|
wlr_layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM) {
|
||||||
if (layer->output) {
|
if (layer->output) {
|
||||||
wlr_scene_optimized_blur_mark_dirty(layer->output->layers.blur_layer);
|
wlr_scene_optimized_blur_mark_dirty(layer->output->layers.blur_layer);
|
||||||
|
@ -343,9 +342,6 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) {
|
||||||
wl_container_of(listener, surface, surface_commit);
|
wl_container_of(listener, surface, surface_commit);
|
||||||
|
|
||||||
struct wlr_layer_surface_v1 *layer_surface = surface->layer_surface;
|
struct wlr_layer_surface_v1 *layer_surface = surface->layer_surface;
|
||||||
if (!layer_surface->initialized) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rerender the optimized blur on change
|
// Rerender the optimized blur on change
|
||||||
struct wlr_layer_surface_v1 *wlr_layer_surface = surface->layer_surface;
|
struct wlr_layer_surface_v1 *wlr_layer_surface = surface->layer_surface;
|
||||||
|
@ -358,7 +354,7 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t committed = layer_surface->current.committed;
|
uint32_t committed = layer_surface->current.committed;
|
||||||
if (committed & WLR_LAYER_SURFACE_V1_STATE_LAYER) {
|
if (layer_surface->initialized && committed & WLR_LAYER_SURFACE_V1_STATE_LAYER) {
|
||||||
enum zwlr_layer_shell_v1_layer layer_type = layer_surface->current.layer;
|
enum zwlr_layer_shell_v1_layer layer_type = layer_surface->current.layer;
|
||||||
struct wlr_scene_tree *output_layer = sway_layer_get_scene(
|
struct wlr_scene_tree *output_layer = sway_layer_get_scene(
|
||||||
surface->output, layer_type);
|
surface->output, layer_type);
|
||||||
|
@ -367,7 +363,6 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) {
|
||||||
|
|
||||||
if (layer_surface->initial_commit || committed || layer_surface->surface->mapped != surface->mapped) {
|
if (layer_surface->initial_commit || committed || layer_surface->surface->mapped != surface->mapped) {
|
||||||
surface->mapped = layer_surface->surface->mapped;
|
surface->mapped = layer_surface->surface->mapped;
|
||||||
layer_parse_criteria(surface);
|
|
||||||
arrange_layers(surface->output);
|
arrange_layers(surface->output);
|
||||||
transaction_commit_dirty();
|
transaction_commit_dirty();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,18 +6,18 @@
|
||||||
#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/swapchain.h>
|
||||||
|
#include <wlr/render/wlr_renderer.h>
|
||||||
#include <wlr/types/wlr_buffer.h>
|
#include <wlr/types/wlr_buffer.h>
|
||||||
#include <wlr/types/wlr_alpha_modifier_v1.h>
|
#include <wlr/types/wlr_alpha_modifier_v1.h>
|
||||||
#include <wlr/types/wlr_gamma_control_v1.h>
|
#include <wlr/types/wlr_gamma_control_v1.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_management_v1.h>
|
#include <wlr/types/wlr_output_management_v1.h>
|
||||||
#include <wlr/types/wlr_output_power_management_v1.h>
|
#include <wlr/types/wlr_output_power_management_v1.h>
|
||||||
#include <wlr/types/wlr_output.h>
|
#include <wlr/types/wlr_output.h>
|
||||||
#include <wlr/types/wlr_presentation_time.h>
|
#include <wlr/types/wlr_presentation_time.h>
|
||||||
#include <wlr/types/wlr_compositor.h>
|
#include <wlr/types/wlr_compositor.h>
|
||||||
#include <wlr/types/wlr_xdg_shell.h>
|
|
||||||
#include <wlr/types/wlr_subcompositor.h>
|
#include <wlr/types/wlr_subcompositor.h>
|
||||||
|
#include <wlr/types/wlr_xdg_shell.h>
|
||||||
#include <wlr/util/region.h>
|
#include <wlr/util/region.h>
|
||||||
#include <wlr/util/transform.h>
|
#include <wlr/util/transform.h>
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
@ -38,6 +38,10 @@
|
||||||
#include "sway/tree/view.h"
|
#include "sway/tree/view.h"
|
||||||
#include "sway/tree/workspace.h"
|
#include "sway/tree/workspace.h"
|
||||||
|
|
||||||
|
#if WLR_HAS_XWAYLAND
|
||||||
|
#include "sway/xwayland.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if WLR_HAS_DRM_BACKEND
|
#if WLR_HAS_DRM_BACKEND
|
||||||
#include <wlr/backend/drm.h>
|
#include <wlr/backend/drm.h>
|
||||||
#include <wlr/types/wlr_drm_lease_v1.h>
|
#include <wlr/types/wlr_drm_lease_v1.h>
|
||||||
|
@ -190,8 +194,8 @@ static enum wlr_scale_filter_mode get_scale_filter(struct sway_output *output,
|
||||||
struct wlr_scene_buffer *buffer) {
|
struct wlr_scene_buffer *buffer) {
|
||||||
// if we are scaling down, we should always choose linear
|
// if we are scaling down, we should always choose linear
|
||||||
if (buffer->dst_width > 0 && buffer->dst_height > 0 && (
|
if (buffer->dst_width > 0 && buffer->dst_height > 0 && (
|
||||||
buffer->dst_width < buffer->buffer_width ||
|
buffer->dst_width < buffer->WLR_PRIVATE.buffer_width ||
|
||||||
buffer->dst_height < buffer->buffer_height)) {
|
buffer->dst_height < buffer->WLR_PRIVATE.buffer_height)) {
|
||||||
return WLR_SCALE_FILTER_BILINEAR;
|
return WLR_SCALE_FILTER_BILINEAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,7 +209,7 @@ static enum wlr_scale_filter_mode get_scale_filter(struct sway_output *output,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void output_configure_scene(struct sway_output *output, struct wlr_scene_node *node, float opacity,
|
void output_configure_scene(struct sway_output *output, struct wlr_scene_node *node, float opacity,
|
||||||
int corner_radius, bool blur_enabled, bool has_titlebar, struct sway_container *closest_con) {
|
int corner_radius, bool blur_enabled, bool has_titlebar, struct sway_container *closest_con) {
|
||||||
if (!node->enabled) {
|
if (!node->enabled) {
|
||||||
return;
|
return;
|
||||||
|
@ -238,18 +242,24 @@ static void output_configure_scene(struct sway_output *output, struct wlr_scene_
|
||||||
// hack: don't call the scene setter because that will damage all outputs
|
// hack: don't call the scene setter because that will damage all outputs
|
||||||
// We don't want to damage outputs that aren't our current output that
|
// We don't want to damage outputs that aren't our current output that
|
||||||
// we're configuring
|
// we're configuring
|
||||||
buffer->filter_mode = get_scale_filter(output, buffer);
|
if (output) {
|
||||||
|
buffer->filter_mode = get_scale_filter(output, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
wlr_scene_buffer_set_opacity(buffer, opacity);
|
wlr_scene_buffer_set_opacity(buffer, opacity);
|
||||||
|
|
||||||
if (!surface || !surface->surface) {
|
if (!surface || !surface->surface) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Other buffers should set their own effects manually, like the
|
// Other buffers should set their own effects manually, like the
|
||||||
// text buffer and saved views
|
// text buffer and saved views
|
||||||
struct wlr_layer_surface_v1 *layer_surface = NULL;
|
struct wlr_layer_surface_v1 *layer_surface = NULL;
|
||||||
if (wlr_xdg_surface_try_from_wlr_surface(surface->surface)
|
if (wlr_xdg_surface_try_from_wlr_surface(surface->surface)
|
||||||
|| wlr_xwayland_surface_try_from_wlr_surface(surface->surface)) {
|
#if WLR_HAS_XWAYLAND
|
||||||
|
|| wlr_xwayland_surface_try_from_wlr_surface(surface->surface)
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
wlr_scene_buffer_set_corner_radius(buffer,
|
wlr_scene_buffer_set_corner_radius(buffer,
|
||||||
container_has_corner_radius(closest_con) ? corner_radius : 0,
|
container_has_corner_radius(closest_con) ? corner_radius : 0,
|
||||||
has_titlebar ? CORNER_LOCATION_BOTTOM : CORNER_LOCATION_ALL);
|
has_titlebar ? CORNER_LOCATION_BOTTOM : CORNER_LOCATION_ALL);
|
||||||
|
@ -303,9 +313,10 @@ static int output_repaint_timer_handler(void *data) {
|
||||||
struct sway_output *output = data;
|
struct sway_output *output = data;
|
||||||
|
|
||||||
output->wlr_output->frame_pending = false;
|
output->wlr_output->frame_pending = false;
|
||||||
if (!output->enabled) {
|
if (!output->wlr_output->enabled) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
output_configure_scene(output, &root->root_scene->tree.node, 1.0f,
|
output_configure_scene(output, &root->root_scene->tree.node, 1.0f,
|
||||||
0, false, false, NULL);
|
0, false, false, NULL);
|
||||||
|
|
||||||
|
@ -313,10 +324,8 @@ static int output_repaint_timer_handler(void *data) {
|
||||||
.color_transform = output->color_transform,
|
.color_transform = output->color_transform,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlr_output *wlr_output = output->wlr_output;
|
|
||||||
struct wlr_scene_output *scene_output = output->scene_output;
|
struct wlr_scene_output *scene_output = output->scene_output;
|
||||||
if (!wlr_output->needs_frame && !output->gamma_lut_changed &&
|
if (!wlr_scene_output_needs_frame(scene_output)) {
|
||||||
!pixman_region32_not_empty(&scene_output->pending_commit_damage)) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,22 +336,6 @@ static int output_repaint_timer_handler(void *data) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output->gamma_lut_changed) {
|
|
||||||
output->gamma_lut_changed = false;
|
|
||||||
struct wlr_gamma_control_v1 *gamma_control =
|
|
||||||
wlr_gamma_control_manager_v1_get_control(
|
|
||||||
server.gamma_control_manager_v1, output->wlr_output);
|
|
||||||
if (!wlr_gamma_control_v1_apply(gamma_control, &pending)) {
|
|
||||||
wlr_output_state_finish(&pending);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!wlr_output_test_state(output->wlr_output, &pending)) {
|
|
||||||
wlr_gamma_control_v1_send_failed_and_destroy(gamma_control);
|
|
||||||
wlr_output_state_set_gamma_lut(&pending, 0, NULL, NULL, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (output_can_tear(output)) {
|
if (output_can_tear(output)) {
|
||||||
pending.tearing_page_flip = true;
|
pending.tearing_page_flip = true;
|
||||||
|
|
||||||
|
@ -479,23 +472,24 @@ void force_modeset(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void begin_destroy(struct sway_output *output) {
|
static void begin_destroy(struct sway_output *output) {
|
||||||
if (output->enabled) {
|
|
||||||
output_disable(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
output_begin_destroy(output);
|
|
||||||
|
|
||||||
wl_list_remove(&output->link);
|
|
||||||
|
|
||||||
wl_list_remove(&output->layout_destroy.link);
|
wl_list_remove(&output->layout_destroy.link);
|
||||||
wl_list_remove(&output->destroy.link);
|
wl_list_remove(&output->destroy.link);
|
||||||
wl_list_remove(&output->commit.link);
|
|
||||||
wl_list_remove(&output->present.link);
|
wl_list_remove(&output->present.link);
|
||||||
wl_list_remove(&output->frame.link);
|
wl_list_remove(&output->frame.link);
|
||||||
wl_list_remove(&output->request_state.link);
|
wl_list_remove(&output->request_state.link);
|
||||||
|
|
||||||
|
// Remove the scene_output first to ensure that the scene does not emit
|
||||||
|
// events for this output.
|
||||||
wlr_scene_output_destroy(output->scene_output);
|
wlr_scene_output_destroy(output->scene_output);
|
||||||
output->scene_output = NULL;
|
output->scene_output = NULL;
|
||||||
|
|
||||||
|
if (output->enabled) {
|
||||||
|
output_disable(output);
|
||||||
|
}
|
||||||
|
output_begin_destroy(output);
|
||||||
|
wl_list_remove(&output->link);
|
||||||
|
|
||||||
output->wlr_output->data = NULL;
|
output->wlr_output->data = NULL;
|
||||||
output->wlr_output = NULL;
|
output->wlr_output = NULL;
|
||||||
|
|
||||||
|
@ -515,20 +509,6 @@ static void handle_layout_destroy(struct wl_listener *listener, void *data) {
|
||||||
begin_destroy(output);
|
begin_destroy(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_commit(struct wl_listener *listener, void *data) {
|
|
||||||
struct sway_output *output = wl_container_of(listener, output, commit);
|
|
||||||
struct wlr_output_event_commit *event = data;
|
|
||||||
|
|
||||||
if (!output->enabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next time the output is enabled, try to re-apply the gamma LUT
|
|
||||||
if ((event->state->committed & WLR_OUTPUT_STATE_ENABLED) && !output->wlr_output->enabled) {
|
|
||||||
output->gamma_lut_changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_present(struct wl_listener *listener, void *data) {
|
static void handle_present(struct wl_listener *listener, void *data) {
|
||||||
struct sway_output *output = wl_container_of(listener, output, present);
|
struct sway_output *output = wl_container_of(listener, output, present);
|
||||||
struct wlr_output_event_present *output_event = data;
|
struct wlr_output_event_present *output_event = data;
|
||||||
|
@ -537,7 +517,7 @@ static void handle_present(struct wl_listener *listener, void *data) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
output->last_presentation = *output_event->when;
|
output->last_presentation = output_event->when;
|
||||||
output->refresh_nsec = output_event->refresh;
|
output->refresh_nsec = output_event->refresh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -646,8 +626,6 @@ void handle_new_output(struct wl_listener *listener, void *data) {
|
||||||
output->layout_destroy.notify = handle_layout_destroy;
|
output->layout_destroy.notify = handle_layout_destroy;
|
||||||
wl_signal_add(&wlr_output->events.destroy, &output->destroy);
|
wl_signal_add(&wlr_output->events.destroy, &output->destroy);
|
||||||
output->destroy.notify = handle_destroy;
|
output->destroy.notify = handle_destroy;
|
||||||
wl_signal_add(&wlr_output->events.commit, &output->commit);
|
|
||||||
output->commit.notify = handle_commit;
|
|
||||||
wl_signal_add(&wlr_output->events.present, &output->present);
|
wl_signal_add(&wlr_output->events.present, &output->present);
|
||||||
output->present.notify = handle_present;
|
output->present.notify = handle_present;
|
||||||
wl_signal_add(&wlr_output->events.frame, &output->frame);
|
wl_signal_add(&wlr_output->events.frame, &output->frame);
|
||||||
|
@ -665,21 +643,6 @@ void handle_new_output(struct wl_listener *listener, void *data) {
|
||||||
request_modeset();
|
request_modeset();
|
||||||
}
|
}
|
||||||
|
|
||||||
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 struct output_config *output_config_for_config_head(
|
static struct output_config *output_config_for_config_head(
|
||||||
struct wlr_output_configuration_head_v1 *config_head) {
|
struct wlr_output_configuration_head_v1 *config_head) {
|
||||||
struct output_config *oc = new_output_config(config_head->state.output->name);
|
struct output_config *oc = new_output_config(config_head->state.output->name);
|
||||||
|
|
|
@ -312,12 +312,13 @@ static void arrange_children(enum sway_container_layout layout, list_t *children
|
||||||
next_title_offset - title_offset, title_bar_height);
|
next_title_offset - title_offset, title_bar_height);
|
||||||
wlr_scene_node_set_enabled(&child->border.tree->node, activated);
|
wlr_scene_node_set_enabled(&child->border.tree->node, activated);
|
||||||
wlr_scene_node_set_enabled(&child->shadow->node, false);
|
wlr_scene_node_set_enabled(&child->shadow->node, false);
|
||||||
|
wlr_scene_node_set_enabled(&child->scene_tree->node, true);
|
||||||
wlr_scene_node_set_position(&child->scene_tree->node, 0, title_bar_height);
|
wlr_scene_node_set_position(&child->scene_tree->node, 0, title_bar_height);
|
||||||
wlr_scene_node_reparent(&child->scene_tree->node, content);
|
wlr_scene_node_reparent(&child->scene_tree->node, content);
|
||||||
|
|
||||||
if (activated) {
|
int net_height = height - title_bar_height;
|
||||||
arrange_container(child, width, height - title_bar_height,
|
if (activated && width > 0 && net_height > 0) {
|
||||||
title_bar_height == 0, 0);
|
arrange_container(child, width, net_height, title_bar_height == 0, 0);
|
||||||
} else {
|
} else {
|
||||||
disable_container(child);
|
disable_container(child);
|
||||||
}
|
}
|
||||||
|
@ -342,12 +343,13 @@ static void arrange_children(enum sway_container_layout layout, list_t *children
|
||||||
arrange_title_bar(child, 0, y - title_height, width, title_bar_height);
|
arrange_title_bar(child, 0, y - title_height, width, title_bar_height);
|
||||||
wlr_scene_node_set_enabled(&child->border.tree->node, activated);
|
wlr_scene_node_set_enabled(&child->border.tree->node, activated);
|
||||||
wlr_scene_node_set_enabled(&child->shadow->node, false);
|
wlr_scene_node_set_enabled(&child->shadow->node, false);
|
||||||
|
wlr_scene_node_set_enabled(&child->scene_tree->node, true);
|
||||||
wlr_scene_node_set_position(&child->scene_tree->node, 0, title_height);
|
wlr_scene_node_set_position(&child->scene_tree->node, 0, title_height);
|
||||||
wlr_scene_node_reparent(&child->scene_tree->node, content);
|
wlr_scene_node_reparent(&child->scene_tree->node, content);
|
||||||
|
|
||||||
if (activated) {
|
int net_height = height - title_height;
|
||||||
arrange_container(child, width, height - title_height,
|
if (activated && width > 0 && net_height > 0) {
|
||||||
title_bar_height == 0, 0);
|
arrange_container(child, width, net_height, title_bar_height == 0, 0);
|
||||||
} else {
|
} else {
|
||||||
disable_container(child);
|
disable_container(child);
|
||||||
}
|
}
|
||||||
|
@ -365,8 +367,12 @@ static void arrange_children(enum sway_container_layout layout, list_t *children
|
||||||
container_has_shadow(child) && child->view);
|
container_has_shadow(child) && child->view);
|
||||||
wlr_scene_node_set_position(&child->scene_tree->node, 0, off);
|
wlr_scene_node_set_position(&child->scene_tree->node, 0, off);
|
||||||
wlr_scene_node_reparent(&child->scene_tree->node, content);
|
wlr_scene_node_reparent(&child->scene_tree->node, content);
|
||||||
arrange_container(child, width, cheight, true, gaps);
|
if (width > 0 && cheight > 0) {
|
||||||
off += cheight + gaps;
|
arrange_container(child, width, cheight, true, gaps);
|
||||||
|
off += cheight + gaps;
|
||||||
|
} else {
|
||||||
|
disable_container(child);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (layout == L_HORIZ) {
|
} else if (layout == L_HORIZ) {
|
||||||
int off = 0;
|
int off = 0;
|
||||||
|
@ -379,8 +385,12 @@ static void arrange_children(enum sway_container_layout layout, list_t *children
|
||||||
container_has_shadow(child) && child->view);
|
container_has_shadow(child) && child->view);
|
||||||
wlr_scene_node_set_position(&child->scene_tree->node, off, 0);
|
wlr_scene_node_set_position(&child->scene_tree->node, off, 0);
|
||||||
wlr_scene_node_reparent(&child->scene_tree->node, content);
|
wlr_scene_node_reparent(&child->scene_tree->node, content);
|
||||||
arrange_container(child, cwidth, height, true, gaps);
|
if (cwidth > 0 && height > 0) {
|
||||||
off += cwidth + gaps;
|
arrange_container(child, cwidth, height, true, gaps);
|
||||||
|
off += cwidth + gaps;
|
||||||
|
} else {
|
||||||
|
disable_container(child);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sway_assert(false, "unreachable");
|
sway_assert(false, "unreachable");
|
||||||
|
@ -543,7 +553,8 @@ static void arrange_container(struct sway_container *con,
|
||||||
// make sure to reparent, it's possible that the client just came out of
|
// make sure to reparent, it's possible that the client just came out of
|
||||||
// fullscreen mode where the parent of the surface is not the container
|
// fullscreen mode where the parent of the surface is not the container
|
||||||
wlr_scene_node_reparent(&con->view->scene_tree->node, con->content_tree);
|
wlr_scene_node_reparent(&con->view->scene_tree->node, con->content_tree);
|
||||||
wlr_scene_node_set_position(&con->view->scene_tree->node, border_left, border_top);
|
wlr_scene_node_set_position(&con->view->scene_tree->node,
|
||||||
|
border_left, border_top);
|
||||||
} else {
|
} else {
|
||||||
// make sure to disable the title bar if the parent is not managing it
|
// make sure to disable the title bar if the parent is not managing it
|
||||||
if (title_bar) {
|
if (title_bar) {
|
||||||
|
@ -627,6 +638,7 @@ static void arrange_workspace_floating(struct sway_workspace *ws) {
|
||||||
floater->current.x, floater->current.y);
|
floater->current.x, floater->current.y);
|
||||||
wlr_scene_node_set_enabled(&floater->scene_tree->node, true);
|
wlr_scene_node_set_enabled(&floater->scene_tree->node, true);
|
||||||
wlr_scene_node_set_enabled(&floater->shadow->node, container_has_shadow(floater) && floater->view);
|
wlr_scene_node_set_enabled(&floater->shadow->node, container_has_shadow(floater) && floater->view);
|
||||||
|
wlr_scene_node_set_enabled(&floater->border.tree->node, true);
|
||||||
|
|
||||||
arrange_container(floater, floater->current.width, floater->current.height,
|
arrange_container(floater, floater->current.width, floater->current.height,
|
||||||
true, ws->gaps_inner);
|
true, ws->gaps_inner);
|
||||||
|
@ -679,16 +691,17 @@ static void arrange_output(struct sway_output *output, int width, int height) {
|
||||||
wlr_scene_node_set_enabled(&child->layers.tiling->node, !fs);
|
wlr_scene_node_set_enabled(&child->layers.tiling->node, !fs);
|
||||||
wlr_scene_node_set_enabled(&child->layers.fullscreen->node, fs);
|
wlr_scene_node_set_enabled(&child->layers.fullscreen->node, fs);
|
||||||
|
|
||||||
arrange_workspace_floating(child);
|
|
||||||
|
|
||||||
wlr_scene_node_set_enabled(&output->layers.shell_background->node, !fs);
|
wlr_scene_node_set_enabled(&output->layers.shell_background->node, !fs);
|
||||||
wlr_scene_node_set_enabled(&output->layers.shell_bottom->node, !fs);
|
wlr_scene_node_set_enabled(&output->layers.shell_bottom->node, !fs);
|
||||||
wlr_scene_node_set_enabled(&output->layers.blur_layer->node, !fs);
|
wlr_scene_node_set_enabled(&output->layers.blur_layer->node, !fs);
|
||||||
wlr_scene_node_set_enabled(&output->layers.fullscreen->node, fs);
|
wlr_scene_node_set_enabled(&output->layers.fullscreen->node, fs);
|
||||||
|
|
||||||
if (fs) {
|
if (fs) {
|
||||||
|
disable_workspace(child);
|
||||||
|
|
||||||
wlr_scene_rect_set_size(output->fullscreen_background, width, height);
|
wlr_scene_rect_set_size(output->fullscreen_background, width, height);
|
||||||
|
|
||||||
|
arrange_workspace_floating(child);
|
||||||
arrange_fullscreen(child->layers.fullscreen, fs, child,
|
arrange_fullscreen(child->layers.fullscreen, fs, child,
|
||||||
width, height);
|
width, height);
|
||||||
} else {
|
} else {
|
||||||
|
@ -701,6 +714,7 @@ static void arrange_output(struct sway_output *output, int width, int height) {
|
||||||
arrange_workspace_tiling(child,
|
arrange_workspace_tiling(child,
|
||||||
area->width - gaps->left - gaps->right,
|
area->width - gaps->left - gaps->right,
|
||||||
area->height - gaps->top - gaps->bottom);
|
area->height - gaps->top - gaps->bottom);
|
||||||
|
arrange_workspace_floating(child);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
wlr_scene_node_set_enabled(&child->layers.tiling->node, false);
|
wlr_scene_node_set_enabled(&child->layers.tiling->node, false);
|
||||||
|
@ -757,6 +771,15 @@ static void arrange_root(struct sway_root *root) {
|
||||||
struct sway_output *output = root->outputs->items[i];
|
struct sway_output *output = root->outputs->items[i];
|
||||||
struct sway_workspace *ws = output->current.active_workspace;
|
struct sway_workspace *ws = output->current.active_workspace;
|
||||||
|
|
||||||
|
wlr_scene_output_set_position(output->scene_output, output->lx, output->ly);
|
||||||
|
|
||||||
|
// disable all workspaces to get to a known state
|
||||||
|
for (int j = 0; j < output->current.workspaces->length; j++) {
|
||||||
|
struct sway_workspace *workspace = output->current.workspaces->items[j];
|
||||||
|
disable_workspace(workspace);
|
||||||
|
}
|
||||||
|
|
||||||
|
// arrange the active workspace
|
||||||
if (ws) {
|
if (ws) {
|
||||||
arrange_workspace_floating(ws);
|
arrange_workspace_floating(ws);
|
||||||
}
|
}
|
||||||
|
|
|
@ -299,18 +299,17 @@ static void handle_commit(struct wl_listener *listener, void *data) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_box new_geo;
|
struct wlr_box *new_geo = &xdg_surface->geometry;
|
||||||
wlr_xdg_surface_get_geometry(xdg_surface, &new_geo);
|
bool new_size = new_geo->width != view->geometry.width ||
|
||||||
bool new_size = new_geo.width != view->geometry.width ||
|
new_geo->height != view->geometry.height ||
|
||||||
new_geo.height != view->geometry.height ||
|
new_geo->x != view->geometry.x ||
|
||||||
new_geo.x != view->geometry.x ||
|
new_geo->y != view->geometry.y;
|
||||||
new_geo.y != view->geometry.y;
|
|
||||||
|
|
||||||
if (new_size) {
|
if (new_size) {
|
||||||
// The client changed its surface size in this commit. For floating
|
// The client changed its surface size in this commit. For floating
|
||||||
// containers, we resize the container to match. For tiling containers,
|
// containers, we resize the container to match. For tiling containers,
|
||||||
// we only recenter the surface.
|
// we only recenter the surface.
|
||||||
memcpy(&view->geometry, &new_geo, sizeof(struct wlr_box));
|
memcpy(&view->geometry, new_geo, sizeof(struct wlr_box));
|
||||||
if (container_is_floating(view->container)) {
|
if (container_is_floating(view->container)) {
|
||||||
view_update_size(view);
|
view_update_size(view);
|
||||||
// Only set the toplevel size the current container actually has a size.
|
// Only set the toplevel size the current container actually has a size.
|
||||||
|
@ -483,12 +482,8 @@ static void handle_map(struct wl_listener *listener, void *data) {
|
||||||
struct sway_view *view = &xdg_shell_view->view;
|
struct sway_view *view = &xdg_shell_view->view;
|
||||||
struct wlr_xdg_toplevel *toplevel = view->wlr_xdg_toplevel;
|
struct wlr_xdg_toplevel *toplevel = view->wlr_xdg_toplevel;
|
||||||
|
|
||||||
view->natural_width = toplevel->base->current.geometry.width;
|
view->natural_width = toplevel->base->geometry.width;
|
||||||
view->natural_height = toplevel->base->current.geometry.height;
|
view->natural_height = toplevel->base->geometry.height;
|
||||||
if (!view->natural_width && !view->natural_height) {
|
|
||||||
view->natural_width = toplevel->base->surface->current.width;
|
|
||||||
view->natural_height = toplevel->base->surface->current.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool csd = false;
|
bool csd = false;
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ static void unmanaged_handle_map(struct wl_listener *listener, void *data) {
|
||||||
surface->set_geometry.notify = unmanaged_handle_set_geometry;
|
surface->set_geometry.notify = unmanaged_handle_set_geometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wlr_xwayland_or_surface_wants_focus(xsurface)) {
|
if (wlr_xwayland_surface_override_redirect_wants_focus(xsurface)) {
|
||||||
struct sway_seat *seat = input_manager_current_seat();
|
struct sway_seat *seat = input_manager_current_seat();
|
||||||
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);
|
||||||
|
@ -96,7 +96,7 @@ static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) {
|
||||||
// This simply returns focus to the parent surface if there's one available.
|
// This simply returns focus to the parent surface if there's one available.
|
||||||
// This seems to handle JetBrains issues.
|
// This seems to handle JetBrains issues.
|
||||||
if (xsurface->parent && xsurface->parent->surface
|
if (xsurface->parent && xsurface->parent->surface
|
||||||
&& wlr_xwayland_or_surface_wants_focus(xsurface->parent)) {
|
&& wlr_xwayland_surface_override_redirect_wants_focus(xsurface->parent)) {
|
||||||
seat_set_focus_surface(seat, xsurface->parent->surface, false);
|
seat_set_focus_surface(seat, xsurface->parent->surface, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -289,9 +289,6 @@ static void set_activated(struct sway_view *view, bool activated) {
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_xwayland_surface_activate(surface, activated);
|
wlr_xwayland_surface_activate(surface, activated);
|
||||||
if (activated) {
|
|
||||||
wlr_xwayland_surface_restack(surface, NULL, XCB_STACK_MODE_ABOVE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_tiled(struct sway_view *view, bool tiled) {
|
static void set_tiled(struct sway_view *view, bool tiled) {
|
||||||
|
@ -299,7 +296,7 @@ static void set_tiled(struct sway_view *view, bool tiled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface;
|
struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface;
|
||||||
wlr_xwayland_surface_set_maximized(surface, tiled);
|
wlr_xwayland_surface_set_maximized(surface, tiled, tiled);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_fullscreen(struct sway_view *view, bool fullscreen) {
|
static void set_fullscreen(struct sway_view *view, bool fullscreen) {
|
||||||
|
|
|
@ -578,7 +578,7 @@ static void handle_tablet_tool_position(struct sway_cursor *cursor,
|
||||||
// tablet events until the drag is released, even if we are now over a
|
// tablet events until the drag is released, even if we are now over a
|
||||||
// non-tablet surface.
|
// non-tablet surface.
|
||||||
if (!cursor->simulating_pointer_from_tool_tip &&
|
if (!cursor->simulating_pointer_from_tool_tip &&
|
||||||
((surface && wlr_surface_accepts_tablet_v2(tablet->tablet_v2, surface)) ||
|
((surface && wlr_surface_accepts_tablet_v2(surface, tablet->tablet_v2)) ||
|
||||||
wlr_tablet_tool_v2_has_implicit_grab(tool->tablet_v2_tool))) {
|
wlr_tablet_tool_v2_has_implicit_grab(tool->tablet_v2_tool))) {
|
||||||
seatop_tablet_tool_motion(seat, tool, time_msec);
|
seatop_tablet_tool_motion(seat, tool, time_msec);
|
||||||
} else {
|
} else {
|
||||||
|
@ -664,7 +664,7 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) {
|
||||||
dispatch_cursor_button(cursor, &event->tablet->base, event->time_msec,
|
dispatch_cursor_button(cursor, &event->tablet->base, event->time_msec,
|
||||||
BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED);
|
BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED);
|
||||||
wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
|
wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
|
||||||
} else if (!surface || !wlr_surface_accepts_tablet_v2(tablet_v2, surface)) {
|
} else if (!surface || !wlr_surface_accepts_tablet_v2(surface, tablet_v2)) {
|
||||||
// If we started holding the tool tip down on a surface that accepts
|
// If we started holding the tool tip down on a surface that accepts
|
||||||
// tablet v2, we should notify that surface if it gets released over a
|
// tablet v2, we should notify that surface if it gets released over a
|
||||||
// surface that doesn't support v2.
|
// surface that doesn't support v2.
|
||||||
|
@ -749,7 +749,7 @@ static void handle_tool_button(struct wl_listener *listener, void *data) {
|
||||||
bool mod_pressed = modifiers & config->floating_mod;
|
bool mod_pressed = modifiers & config->floating_mod;
|
||||||
|
|
||||||
bool surface_supports_tablet_events =
|
bool surface_supports_tablet_events =
|
||||||
surface && wlr_surface_accepts_tablet_v2(tablet_v2, surface);
|
surface && wlr_surface_accepts_tablet_v2(surface, tablet_v2);
|
||||||
|
|
||||||
// Simulate pointer when:
|
// Simulate pointer when:
|
||||||
// 1. The modifier key is pressed, OR
|
// 1. The modifier key is pressed, OR
|
||||||
|
@ -1047,6 +1047,7 @@ void sway_cursor_destroy(struct sway_cursor *cursor) {
|
||||||
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);
|
||||||
wl_list_remove(&cursor->tool_tip.link);
|
wl_list_remove(&cursor->tool_tip.link);
|
||||||
|
wl_list_remove(&cursor->tool_proximity.link);
|
||||||
wl_list_remove(&cursor->tool_button.link);
|
wl_list_remove(&cursor->tool_button.link);
|
||||||
wl_list_remove(&cursor->request_set_cursor.link);
|
wl_list_remove(&cursor->request_set_cursor.link);
|
||||||
|
|
||||||
|
@ -1212,7 +1213,7 @@ uint32_t get_mouse_bindsym(const char *name, char **error) {
|
||||||
SWAY_SCROLL_UP, SWAY_SCROLL_DOWN, SWAY_SCROLL_LEFT,
|
SWAY_SCROLL_UP, SWAY_SCROLL_DOWN, SWAY_SCROLL_LEFT,
|
||||||
SWAY_SCROLL_RIGHT, BTN_SIDE, BTN_EXTRA};
|
SWAY_SCROLL_RIGHT, BTN_SIDE, BTN_EXTRA};
|
||||||
return buttons[number - 1];
|
return buttons[number - 1];
|
||||||
} else if (strncmp(name, "BTN_", strlen("BTN_")) == 0) {
|
} else if (has_prefix(name, "BTN_")) {
|
||||||
// Get event code from name
|
// Get event code from name
|
||||||
int code = libevdev_event_code_from_name(EV_KEY, name);
|
int code = libevdev_event_code_from_name(EV_KEY, name);
|
||||||
if (code == -1) {
|
if (code == -1) {
|
||||||
|
@ -1237,7 +1238,7 @@ uint32_t get_mouse_bindcode(const char *name, char **error) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
const char *event = libevdev_event_code_get_name(EV_KEY, code);
|
const char *event = libevdev_event_code_get_name(EV_KEY, code);
|
||||||
if (!event || strncmp(event, "BTN_", strlen("BTN_")) != 0) {
|
if (!event || !has_prefix(event, "BTN_")) {
|
||||||
*error = format_str("Event code %d (%s) is not a button",
|
*error = format_str("Event code %d (%s) is not a button",
|
||||||
code, event ? event : "(null)");
|
code, event ? event : "(null)");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -493,6 +493,14 @@ struct sway_input_manager *input_manager_create(struct sway_server *server) {
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void input_manager_finish(struct sway_input_manager *input) {
|
||||||
|
wl_list_remove(&input->new_input.link);
|
||||||
|
wl_list_remove(&input->virtual_keyboard_new.link);
|
||||||
|
wl_list_remove(&input->virtual_pointer_new.link);
|
||||||
|
wl_list_remove(&input->keyboard_shortcuts_inhibit_new_inhibitor.link);
|
||||||
|
wl_list_remove(&input->transient_seat_create.link);
|
||||||
|
}
|
||||||
|
|
||||||
bool input_manager_has_focus(struct sway_node *node) {
|
bool input_manager_has_focus(struct sway_node *node) {
|
||||||
struct sway_seat *seat = NULL;
|
struct sway_seat *seat = NULL;
|
||||||
wl_list_for_each(seat, &server.input->seats, link) {
|
wl_list_for_each(seat, &server.input->seats, link) {
|
||||||
|
@ -577,7 +585,7 @@ void input_manager_configure_all_input_mappings(void) {
|
||||||
void input_manager_apply_input_config(struct input_config *input_config) {
|
void input_manager_apply_input_config(struct input_config *input_config) {
|
||||||
struct sway_input_device *input_device = NULL;
|
struct sway_input_device *input_device = NULL;
|
||||||
bool wildcard = strcmp(input_config->identifier, "*") == 0;
|
bool wildcard = strcmp(input_config->identifier, "*") == 0;
|
||||||
bool type_wildcard = strncmp(input_config->identifier, "type:", 5) == 0;
|
bool type_wildcard = has_prefix(input_config->identifier, "type:");
|
||||||
wl_list_for_each(input_device, &server.input->devices, link) {
|
wl_list_for_each(input_device, &server.input->devices, link) {
|
||||||
bool type_matches = type_wildcard &&
|
bool type_matches = type_wildcard &&
|
||||||
strcmp(input_device_get_type(input_device), input_config->identifier + 5) == 0;
|
strcmp(input_device_get_type(input_device), input_config->identifier + 5) == 0;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <wlr/config.h>
|
#include <wlr/config.h>
|
||||||
#include <wlr/backend/multi.h>
|
#include <wlr/backend/multi.h>
|
||||||
#include <wlr/interfaces/wlr_keyboard.h>
|
#include <wlr/interfaces/wlr_keyboard.h>
|
||||||
|
#include <wlr/types/wlr_cursor.h>
|
||||||
#include <wlr/types/wlr_keyboard.h>
|
#include <wlr/types/wlr_keyboard.h>
|
||||||
#include <wlr/types/wlr_keyboard_group.h>
|
#include <wlr/types/wlr_keyboard_group.h>
|
||||||
#include <xkbcommon/xkbcommon-names.h>
|
#include <xkbcommon/xkbcommon-names.h>
|
||||||
|
@ -267,6 +268,7 @@ static bool keyboard_execute_compositor_binding(struct sway_keyboard *keyboard,
|
||||||
const xkb_keysym_t *pressed_keysyms, uint32_t modifiers, size_t keysyms_len) {
|
const xkb_keysym_t *pressed_keysyms, uint32_t modifiers, size_t keysyms_len) {
|
||||||
for (size_t i = 0; i < keysyms_len; ++i) {
|
for (size_t i = 0; i < keysyms_len; ++i) {
|
||||||
xkb_keysym_t keysym = pressed_keysyms[i];
|
xkb_keysym_t keysym = pressed_keysyms[i];
|
||||||
|
|
||||||
if (keysym >= XKB_KEY_XF86Switch_VT_1 &&
|
if (keysym >= XKB_KEY_XF86Switch_VT_1 &&
|
||||||
keysym <= XKB_KEY_XF86Switch_VT_12) {
|
keysym <= XKB_KEY_XF86Switch_VT_12) {
|
||||||
#if WLR_HAS_SESSION
|
#if WLR_HAS_SESSION
|
||||||
|
@ -282,6 +284,36 @@ static bool keyboard_execute_compositor_binding(struct sway_keyboard *keyboard,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool keyboard_execute_pointer_keysyms(struct sway_keyboard *keyboard,
|
||||||
|
uint32_t time, const xkb_keysym_t *pressed_keysyms, size_t keysyms_len,
|
||||||
|
enum wl_keyboard_key_state state) {
|
||||||
|
struct sway_cursor *cursor = keyboard->seat_device->sway_seat->cursor;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < keysyms_len; ++i) {
|
||||||
|
xkb_keysym_t keysym = pressed_keysyms[i];
|
||||||
|
|
||||||
|
uint32_t button = wlr_keyboard_keysym_to_pointer_button(keysym);
|
||||||
|
if (button != 0) {
|
||||||
|
dispatch_cursor_button(cursor, &keyboard->wlr->base, time, button,
|
||||||
|
(enum wl_pointer_button_state)state);
|
||||||
|
wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dx, dy;
|
||||||
|
wlr_keyboard_keysym_to_pointer_motion(keysym, &dx, &dy);
|
||||||
|
if (state == WL_KEYBOARD_KEY_STATE_PRESSED && (dx != 0 || dy != 0)) {
|
||||||
|
dx *= 10;
|
||||||
|
dy *= 10;
|
||||||
|
pointer_motion(cursor, time, &keyboard->wlr->base, dx, dy, dx, dy);
|
||||||
|
wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get keysyms and modifiers from the keyboard as xkb sees them.
|
* Get keysyms and modifiers from the keyboard as xkb sees them.
|
||||||
*
|
*
|
||||||
|
@ -507,6 +539,11 @@ static void handle_key_event(struct sway_keyboard *keyboard,
|
||||||
keyboard, keyinfo.raw_keysyms, keyinfo.raw_modifiers,
|
keyboard, keyinfo.raw_keysyms, keyinfo.raw_modifiers,
|
||||||
keyinfo.raw_keysyms_len);
|
keyinfo.raw_keysyms_len);
|
||||||
}
|
}
|
||||||
|
if (!handled) {
|
||||||
|
handled = keyboard_execute_pointer_keysyms(keyboard, event->time_msec,
|
||||||
|
keyinfo.translated_keysyms, keyinfo.translated_keysyms_len,
|
||||||
|
event->state);
|
||||||
|
}
|
||||||
|
|
||||||
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 and we have a focused
|
// If the pressed event was sent to a client and we have a focused
|
||||||
|
|
|
@ -272,6 +272,10 @@ bool sway_input_configure_libinput_device(struct sway_input_device *input_device
|
||||||
}
|
}
|
||||||
if (ic->drag_lock != INT_MIN) {
|
if (ic->drag_lock != INT_MIN) {
|
||||||
changed |= set_tap_drag_lock(device, ic->drag_lock);
|
changed |= set_tap_drag_lock(device, ic->drag_lock);
|
||||||
|
} else {
|
||||||
|
#if HAVE_LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY
|
||||||
|
changed |= set_tap_drag_lock(device, LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if (ic->pointer_accel != FLT_MIN) {
|
if (ic->pointer_accel != FLT_MIN) {
|
||||||
changed |= set_accel_speed(device, ic->pointer_accel);
|
changed |= set_accel_speed(device, ic->pointer_accel);
|
||||||
|
@ -354,8 +358,12 @@ void sway_input_reset_libinput_device(struct sway_input_device *input_device) {
|
||||||
libinput_device_config_tap_get_default_button_map(device));
|
libinput_device_config_tap_get_default_button_map(device));
|
||||||
changed |= set_tap_drag(device,
|
changed |= set_tap_drag(device,
|
||||||
libinput_device_config_tap_get_default_drag_enabled(device));
|
libinput_device_config_tap_get_default_drag_enabled(device));
|
||||||
|
#if HAVE_LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY
|
||||||
|
changed |= set_tap_drag_lock(device, LIBINPUT_CONFIG_DRAG_LOCK_ENABLED_STICKY);
|
||||||
|
#else
|
||||||
changed |= set_tap_drag_lock(device,
|
changed |= set_tap_drag_lock(device,
|
||||||
libinput_device_config_tap_get_default_drag_lock_enabled(device));
|
libinput_device_config_tap_get_default_drag_lock_enabled(device));
|
||||||
|
#endif
|
||||||
changed |= set_accel_speed(device,
|
changed |= set_accel_speed(device,
|
||||||
libinput_device_config_accel_get_default_speed(device));
|
libinput_device_config_accel_get_default_speed(device));
|
||||||
changed |= set_rotation_angle(device,
|
changed |= set_rotation_angle(device,
|
||||||
|
@ -391,6 +399,19 @@ void sway_input_reset_libinput_device(struct sway_input_device *input_device) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool sway_udev_device_is_builtin(struct udev_device *udev_device) {
|
||||||
|
const char *id_path = udev_device_get_property_value(udev_device, "ID_PATH");
|
||||||
|
if (!id_path) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_prefix(id_path, "platform-")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return has_prefix(id_path, "pci-") && strstr(id_path, "-platform-");
|
||||||
|
}
|
||||||
|
|
||||||
bool sway_libinput_device_is_builtin(struct sway_input_device *sway_device) {
|
bool sway_libinput_device_is_builtin(struct sway_input_device *sway_device) {
|
||||||
if (!wlr_input_device_is_libinput(sway_device->wlr_device)) {
|
if (!wlr_input_device_is_libinput(sway_device->wlr_device)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -404,18 +425,7 @@ bool sway_libinput_device_is_builtin(struct sway_input_device *sway_device) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *id_path = udev_device_get_property_value(udev_device, "ID_PATH");
|
bool is_builtin = sway_udev_device_is_builtin(udev_device);
|
||||||
if (!id_path) {
|
udev_device_unref(udev_device);
|
||||||
return false;
|
return is_builtin;
|
||||||
}
|
|
||||||
|
|
||||||
const char prefix_platform[] = "platform-";
|
|
||||||
if (strncmp(id_path, prefix_platform, strlen(prefix_platform)) == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char prefix_pci[] = "pci-";
|
|
||||||
const char infix_platform[] = "-platform-";
|
|
||||||
return (strncmp(id_path, prefix_pci, strlen(prefix_pci)) == 0) &&
|
|
||||||
strstr(id_path, infix_platform);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -647,10 +647,6 @@ static void seat_reset_input_config(struct sway_seat *seat,
|
||||||
sway_device->input_device->wlr_device, NULL);
|
sway_device->input_device->wlr_device, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool has_prefix(const char *str, const char *prefix) {
|
|
||||||
return strncmp(str, prefix, strlen(prefix)) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the name of the built-in output, if any. Returns NULL if there isn't
|
* Get the name of the built-in output, if any. Returns NULL if there isn't
|
||||||
* exactly one built-in output.
|
* exactly one built-in output.
|
||||||
|
|
|
@ -273,7 +273,7 @@ static void handle_tablet_tool_tip(struct sway_seat *seat,
|
||||||
// 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 &&
|
||||||
wlr_xwayland_or_surface_wants_focus(xsurface)) {
|
wlr_xwayland_surface_override_redirect_wants_focus(xsurface)) {
|
||||||
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);
|
||||||
seat_set_focus_surface(seat, xsurface->surface, false);
|
seat_set_focus_surface(seat, xsurface->surface, false);
|
||||||
|
@ -355,6 +355,13 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
|
||||||
struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat);
|
struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat);
|
||||||
uint32_t modifiers = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
|
uint32_t modifiers = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
|
||||||
|
|
||||||
|
bool mod_pressed = modifiers & config->floating_mod;
|
||||||
|
uint32_t mod_move_btn = config->floating_mod_inverse ? BTN_RIGHT : BTN_LEFT;
|
||||||
|
uint32_t mod_resize_btn = config->floating_mod_inverse ? BTN_LEFT : BTN_RIGHT;
|
||||||
|
bool mod_move_btn_pressed = mod_pressed && button == mod_move_btn;
|
||||||
|
bool mod_resize_btn_pressed = mod_pressed && button == mod_resize_btn;
|
||||||
|
bool titlebar_left_btn_pressed = on_titlebar && button == BTN_LEFT;
|
||||||
|
|
||||||
// Handle mouse bindings
|
// Handle mouse bindings
|
||||||
if (trigger_pointer_button_binding(seat, device, button, state, modifiers,
|
if (trigger_pointer_button_binding(seat, device, button, state, modifiers,
|
||||||
on_titlebar, on_border, on_contents, on_workspace)) {
|
on_titlebar, on_border, on_contents, on_workspace)) {
|
||||||
|
@ -403,33 +410,28 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle tiling resize via mod
|
// Handle tiling resize via mod
|
||||||
bool mod_pressed = modifiers & config->floating_mod;
|
if (cont && !is_floating_or_child && mod_pressed && mod_resize_btn_pressed &&
|
||||||
if (cont && !is_floating_or_child && mod_pressed &&
|
|
||||||
state == WL_POINTER_BUTTON_STATE_PRESSED) {
|
state == WL_POINTER_BUTTON_STATE_PRESSED) {
|
||||||
uint32_t btn_resize = config->floating_mod_inverse ?
|
edge = 0;
|
||||||
BTN_LEFT : BTN_RIGHT;
|
edge |= cursor->cursor->x > cont->pending.x + cont->pending.width / 2 ?
|
||||||
if (button == btn_resize) {
|
WLR_EDGE_RIGHT : WLR_EDGE_LEFT;
|
||||||
edge = 0;
|
edge |= cursor->cursor->y > cont->pending.y + cont->pending.height / 2 ?
|
||||||
edge |= cursor->cursor->x > cont->pending.x + cont->pending.width / 2 ?
|
WLR_EDGE_BOTTOM : WLR_EDGE_TOP;
|
||||||
WLR_EDGE_RIGHT : WLR_EDGE_LEFT;
|
|
||||||
edge |= cursor->cursor->y > cont->pending.y + cont->pending.height / 2 ?
|
|
||||||
WLR_EDGE_BOTTOM : WLR_EDGE_TOP;
|
|
||||||
|
|
||||||
const char *image = NULL;
|
const char *image = NULL;
|
||||||
if (edge == (WLR_EDGE_LEFT | WLR_EDGE_TOP)) {
|
if (edge == (WLR_EDGE_LEFT | WLR_EDGE_TOP)) {
|
||||||
image = "nw-resize";
|
image = "nw-resize";
|
||||||
} else if (edge == (WLR_EDGE_TOP | WLR_EDGE_RIGHT)) {
|
} else if (edge == (WLR_EDGE_TOP | WLR_EDGE_RIGHT)) {
|
||||||
image = "ne-resize";
|
image = "ne-resize";
|
||||||
} else if (edge == (WLR_EDGE_RIGHT | WLR_EDGE_BOTTOM)) {
|
} else if (edge == (WLR_EDGE_RIGHT | WLR_EDGE_BOTTOM)) {
|
||||||
image = "se-resize";
|
image = "se-resize";
|
||||||
} else if (edge == (WLR_EDGE_BOTTOM | WLR_EDGE_LEFT)) {
|
} else if (edge == (WLR_EDGE_BOTTOM | WLR_EDGE_LEFT)) {
|
||||||
image = "sw-resize";
|
image = "sw-resize";
|
||||||
}
|
|
||||||
cursor_set_image(seat->cursor, image, NULL);
|
|
||||||
seat_set_focus_container(seat, cont);
|
|
||||||
seatop_begin_resize_tiling(seat, cont, edge);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
cursor_set_image(seat->cursor, image, NULL);
|
||||||
|
seat_set_focus_container(seat, cont);
|
||||||
|
seatop_begin_resize_tiling(seat, cont, edge);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle changing focus when clicking on a container
|
// Handle changing focus when clicking on a container
|
||||||
|
@ -454,12 +456,10 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
|
||||||
|
|
||||||
// Handle beginning floating move
|
// Handle beginning floating move
|
||||||
if (cont && is_floating_or_child && !is_fullscreen_or_child &&
|
if (cont && is_floating_or_child && !is_fullscreen_or_child &&
|
||||||
state == WL_POINTER_BUTTON_STATE_PRESSED) {
|
state == WL_POINTER_BUTTON_STATE_PRESSED &&
|
||||||
uint32_t btn_move = config->floating_mod_inverse ? BTN_RIGHT : BTN_LEFT;
|
(mod_move_btn_pressed || titlebar_left_btn_pressed)) {
|
||||||
if (button == btn_move && (mod_pressed || on_titlebar)) {
|
seatop_begin_move_floating(seat, container_toplevel_ancestor(cont));
|
||||||
seatop_begin_move_floating(seat, container_toplevel_ancestor(cont));
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle beginning floating resize
|
// Handle beginning floating resize
|
||||||
|
@ -473,9 +473,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Via mod+click
|
// Via mod+click
|
||||||
uint32_t btn_resize = config->floating_mod_inverse ?
|
if (mod_resize_btn_pressed) {
|
||||||
BTN_LEFT : BTN_RIGHT;
|
|
||||||
if (mod_pressed && button == btn_resize) {
|
|
||||||
struct sway_container *floater = container_toplevel_ancestor(cont);
|
struct sway_container *floater = container_toplevel_ancestor(cont);
|
||||||
edge = 0;
|
edge = 0;
|
||||||
edge |= cursor->cursor->x > floater->pending.x + floater->pending.width / 2 ?
|
edge |= cursor->cursor->x > floater->pending.x + floater->pending.width / 2 ?
|
||||||
|
@ -489,18 +487,15 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle moving a tiling container
|
// Handle moving a tiling container
|
||||||
if (config->tiling_drag && (mod_pressed || on_titlebar) &&
|
if (config->tiling_drag && (mod_move_btn_pressed || titlebar_left_btn_pressed) &&
|
||||||
state == WL_POINTER_BUTTON_STATE_PRESSED && !is_floating_or_child &&
|
state == WL_POINTER_BUTTON_STATE_PRESSED && !is_floating_or_child &&
|
||||||
cont && cont->pending.fullscreen_mode == FULLSCREEN_NONE &&
|
cont && cont->pending.fullscreen_mode == FULLSCREEN_NONE) {
|
||||||
button == (config->floating_mod_inverse ? BTN_RIGHT : BTN_LEFT)) {
|
|
||||||
|
|
||||||
// If moving a container by its title bar, use a threshold for the drag
|
// If moving a container by its title bar, use a threshold for the drag
|
||||||
if (!mod_pressed && config->tiling_drag_threshold > 0) {
|
if (!mod_pressed && config->tiling_drag_threshold > 0) {
|
||||||
seatop_begin_move_tiling_threshold(seat, cont);
|
seatop_begin_move_tiling_threshold(seat, cont);
|
||||||
} else {
|
} else {
|
||||||
seatop_begin_move_tiling(seat, cont);
|
seatop_begin_move_tiling(seat, cont);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -523,7 +518,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
|
||||||
if (surface &&
|
if (surface &&
|
||||||
(xsurface = wlr_xwayland_surface_try_from_wlr_surface(surface)) &&
|
(xsurface = wlr_xwayland_surface_try_from_wlr_surface(surface)) &&
|
||||||
xsurface->override_redirect &&
|
xsurface->override_redirect &&
|
||||||
wlr_xwayland_or_surface_wants_focus(xsurface)) {
|
wlr_xwayland_surface_override_redirect_wants_focus(xsurface)) {
|
||||||
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);
|
||||||
seat_set_focus_surface(seat, xsurface->surface, false);
|
seat_set_focus_surface(seat, xsurface->surface, false);
|
||||||
|
@ -669,7 +664,7 @@ static void handle_touch_down(struct sway_seat *seat,
|
||||||
double sx, sy;
|
double sx, sy;
|
||||||
node_at_coords(seat, seat->touch_x, seat->touch_y, &surface, &sx, &sy);
|
node_at_coords(seat, seat->touch_x, seat->touch_y, &surface, &sx, &sy);
|
||||||
|
|
||||||
if (surface && wlr_surface_accepts_touch(wlr_seat, surface)) {
|
if (surface && wlr_surface_accepts_touch(surface, wlr_seat)) {
|
||||||
if (seat_is_input_allowed(seat, surface)) {
|
if (seat_is_input_allowed(seat, surface)) {
|
||||||
cursor->simulating_pointer_from_touch = false;
|
cursor->simulating_pointer_from_touch = false;
|
||||||
seatop_begin_touch_down(seat, surface, event, sx, sy, lx, ly);
|
seatop_begin_touch_down(seat, surface, event, sx, sy, lx, ly);
|
||||||
|
|
|
@ -100,6 +100,7 @@ static void handle_touch_down(struct sway_seat *seat,
|
||||||
|
|
||||||
if (focused_node) {
|
if (focused_node) {
|
||||||
seat_set_focus(seat, focused_node);
|
seat_set_focus(seat, focused_node);
|
||||||
|
transaction_commit_dirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -363,7 +363,7 @@ void sway_tablet_pad_set_focus(struct sway_tablet_pad *tablet_pad,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (surface == NULL ||
|
if (surface == NULL ||
|
||||||
!wlr_surface_accepts_tablet_v2(tablet_pad->tablet->tablet_v2, surface)) {
|
!wlr_surface_accepts_tablet_v2(surface, tablet_pad->tablet->tablet_v2)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#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"
|
#include "sway/server.h"
|
||||||
|
#include <wlr/types/wlr_session_lock_v1.h>
|
||||||
|
|
||||||
static struct sway_text_input *relay_get_focusable_text_input(
|
static struct sway_text_input *relay_get_focusable_text_input(
|
||||||
struct sway_input_method_relay *relay) {
|
struct sway_input_method_relay *relay) {
|
||||||
|
@ -385,6 +386,8 @@ static void input_popup_set_focus(struct sway_input_popup *popup,
|
||||||
|
|
||||||
struct wlr_layer_surface_v1 *layer_surface =
|
struct wlr_layer_surface_v1 *layer_surface =
|
||||||
wlr_layer_surface_v1_try_from_wlr_surface(surface);
|
wlr_layer_surface_v1_try_from_wlr_surface(surface);
|
||||||
|
struct wlr_session_lock_surface_v1 *lock_surface =
|
||||||
|
wlr_session_lock_surface_v1_try_from_wlr_surface(surface);
|
||||||
|
|
||||||
struct wlr_scene_tree *relative_parent;
|
struct wlr_scene_tree *relative_parent;
|
||||||
if (layer_surface) {
|
if (layer_surface) {
|
||||||
|
@ -404,8 +407,30 @@ static void input_popup_set_focus(struct sway_input_popup *popup,
|
||||||
// surface. Layer surfaces get destroyed as part of the output being
|
// surface. Layer surfaces get destroyed as part of the output being
|
||||||
// destroyed, thus also trickling down to popups.
|
// destroyed, thus also trickling down to popups.
|
||||||
popup->fixed_output = layer->layer_surface->output;
|
popup->fixed_output = layer->layer_surface->output;
|
||||||
|
} else if (lock_surface) {
|
||||||
|
wl_signal_add(&lock_surface->surface->events.unmap,
|
||||||
|
&popup->focused_surface_unmap);
|
||||||
|
|
||||||
|
struct sway_layer_surface *lock = lock_surface->data;
|
||||||
|
if (lock == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
relative_parent = lock->scene->tree;
|
||||||
|
popup->desc.view = NULL;
|
||||||
|
|
||||||
|
// we don't need to add an event here to NULL out this field because
|
||||||
|
// this field will only be initialized if the popup is part of a layer
|
||||||
|
// surface. Layer surfaces get destroyed as part of the output being
|
||||||
|
// destroyed, thus also trickling down to popups.
|
||||||
|
popup->fixed_output = lock->layer_surface->output;
|
||||||
} else {
|
} else {
|
||||||
struct sway_view *view = view_from_wlr_surface(surface);
|
struct sway_view *view = view_from_wlr_surface(surface);
|
||||||
|
// In the future there may be other shells been added, so we also need to check here.
|
||||||
|
if (view == NULL) {
|
||||||
|
sway_log(SWAY_DEBUG, "Unsupported IME focus surface");
|
||||||
|
return;
|
||||||
|
}
|
||||||
wl_signal_add(&view->events.unmap, &popup->focused_surface_unmap);
|
wl_signal_add(&view->events.unmap, &popup->focused_surface_unmap);
|
||||||
relative_parent = view->scene_tree;
|
relative_parent = view->scene_tree;
|
||||||
popup->desc.view = view;
|
popup->desc.view = view;
|
||||||
|
@ -572,6 +597,34 @@ static void relay_handle_input_method(struct wl_listener *listener,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sway_input_method_relay_finish_text_input(struct sway_input_method_relay *relay) {
|
||||||
|
wl_list_remove(&relay->text_input_new.link);
|
||||||
|
wl_list_remove(&relay->text_input_manager_destroy.link);
|
||||||
|
wl_list_init(&relay->text_input_new.link);
|
||||||
|
wl_list_init(&relay->text_input_manager_destroy.link);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void relay_handle_text_input_manager_destroy(struct wl_listener *listener, void *data) {
|
||||||
|
struct sway_input_method_relay *relay = wl_container_of(listener, relay,
|
||||||
|
text_input_manager_destroy);
|
||||||
|
|
||||||
|
sway_input_method_relay_finish_text_input(relay);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sway_input_method_relay_finish_input_method(struct sway_input_method_relay *relay) {
|
||||||
|
wl_list_remove(&relay->input_method_new.link);
|
||||||
|
wl_list_remove(&relay->input_method_manager_destroy.link);
|
||||||
|
wl_list_init(&relay->input_method_new.link);
|
||||||
|
wl_list_init(&relay->input_method_manager_destroy.link);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void relay_handle_input_method_manager_destroy(struct wl_listener *listener, void *data) {
|
||||||
|
struct sway_input_method_relay *relay = wl_container_of(listener, relay,
|
||||||
|
input_method_manager_destroy);
|
||||||
|
|
||||||
|
sway_input_method_relay_finish_input_method(relay);
|
||||||
|
}
|
||||||
|
|
||||||
void sway_input_method_relay_init(struct sway_seat *seat,
|
void sway_input_method_relay_init(struct sway_seat *seat,
|
||||||
struct sway_input_method_relay *relay) {
|
struct sway_input_method_relay *relay) {
|
||||||
relay->seat = seat;
|
relay->seat = seat;
|
||||||
|
@ -581,16 +634,22 @@ void sway_input_method_relay_init(struct sway_seat *seat,
|
||||||
relay->text_input_new.notify = relay_handle_text_input;
|
relay->text_input_new.notify = relay_handle_text_input;
|
||||||
wl_signal_add(&server.text_input->events.text_input,
|
wl_signal_add(&server.text_input->events.text_input,
|
||||||
&relay->text_input_new);
|
&relay->text_input_new);
|
||||||
|
relay->text_input_manager_destroy.notify = relay_handle_text_input_manager_destroy;
|
||||||
|
wl_signal_add(&server.text_input->events.destroy,
|
||||||
|
&relay->text_input_manager_destroy);
|
||||||
|
|
||||||
relay->input_method_new.notify = relay_handle_input_method;
|
relay->input_method_new.notify = relay_handle_input_method;
|
||||||
wl_signal_add(
|
wl_signal_add(
|
||||||
&server.input_method->events.input_method,
|
&server.input_method->events.input_method,
|
||||||
&relay->input_method_new);
|
&relay->input_method_new);
|
||||||
|
relay->input_method_manager_destroy.notify = relay_handle_input_method_manager_destroy;
|
||||||
|
wl_signal_add(&server.input_method->events.destroy,
|
||||||
|
&relay->input_method_manager_destroy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sway_input_method_relay_finish(struct sway_input_method_relay *relay) {
|
void sway_input_method_relay_finish(struct sway_input_method_relay *relay) {
|
||||||
wl_list_remove(&relay->input_method_new.link);
|
sway_input_method_relay_finish_text_input(relay);
|
||||||
wl_list_remove(&relay->text_input_new.link);
|
sway_input_method_relay_finish_input_method(relay);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sway_input_method_relay_set_focus(struct sway_input_method_relay *relay,
|
void sway_input_method_relay_set_focus(struct sway_input_method_relay *relay,
|
||||||
|
|
|
@ -6,13 +6,13 @@
|
||||||
#include <wlr/config.h>
|
#include <wlr/config.h>
|
||||||
#include <wlr/types/wlr_content_type_v1.h>
|
#include <wlr/types/wlr_content_type_v1.h>
|
||||||
#include <wlr/types/wlr_output.h>
|
#include <wlr/types/wlr_output.h>
|
||||||
|
#include <wlr/types/wlr_ext_foreign_toplevel_list_v1.h>
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "json_object.h"
|
#include "json_object.h"
|
||||||
#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/layers.h"
|
|
||||||
#include "sway/scene_descriptor.h"
|
#include "sway/scene_descriptor.h"
|
||||||
#include "sway/server.h"
|
#include "sway/server.h"
|
||||||
#include "sway/tree/container.h"
|
#include "sway/tree/container.h"
|
||||||
|
@ -23,6 +23,7 @@
|
||||||
#include "sway/input/input-manager.h"
|
#include "sway/input/input-manager.h"
|
||||||
#include "sway/input/cursor.h"
|
#include "sway/input/cursor.h"
|
||||||
#include "sway/input/seat.h"
|
#include "sway/input/seat.h"
|
||||||
|
#include "sway/layers.h"
|
||||||
#include "wlr-layer-shell-unstable-v1-protocol.h"
|
#include "wlr-layer-shell-unstable-v1-protocol.h"
|
||||||
#include "sway/desktop/idle_inhibit_v1.h"
|
#include "sway/desktop/idle_inhibit_v1.h"
|
||||||
|
|
||||||
|
@ -659,6 +660,10 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object
|
||||||
json_object_object_add(object, "app_id",
|
json_object_object_add(object, "app_id",
|
||||||
app_id ? json_object_new_string(app_id) : NULL);
|
app_id ? json_object_new_string(app_id) : NULL);
|
||||||
|
|
||||||
|
json_object_object_add(object, "foreign_toplevel_identifier",
|
||||||
|
c->view->ext_foreign_toplevel ?
|
||||||
|
json_object_new_string(c->view->ext_foreign_toplevel->identifier) : NULL);
|
||||||
|
|
||||||
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));
|
||||||
|
|
||||||
|
@ -684,6 +689,18 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object
|
||||||
json_object_object_add(object, "inhibit_idle",
|
json_object_object_add(object, "inhibit_idle",
|
||||||
json_object_new_boolean(view_inhibit_idle(c->view)));
|
json_object_new_boolean(view_inhibit_idle(c->view)));
|
||||||
|
|
||||||
|
const char *sandbox_engine = view_get_sandbox_engine(c->view);
|
||||||
|
json_object_object_add(object, "sandbox_engine",
|
||||||
|
sandbox_engine ? json_object_new_string(sandbox_engine) : NULL);
|
||||||
|
|
||||||
|
const char *sandbox_app_id = view_get_sandbox_app_id(c->view);
|
||||||
|
json_object_object_add(object, "sandbox_app_id",
|
||||||
|
sandbox_app_id ? json_object_new_string(sandbox_app_id) : NULL);
|
||||||
|
|
||||||
|
const char *sandbox_instance_id = view_get_sandbox_instance_id(c->view);
|
||||||
|
json_object_object_add(object, "sandbox_instance_id",
|
||||||
|
sandbox_instance_id ? json_object_new_string(sandbox_instance_id) : NULL);
|
||||||
|
|
||||||
json_object *idle_inhibitors = json_object_new_object();
|
json_object *idle_inhibitors = json_object_new_object();
|
||||||
|
|
||||||
struct sway_idle_inhibitor_v1 *user_inhibitor =
|
struct sway_idle_inhibitor_v1 *user_inhibitor =
|
||||||
|
|
|
@ -234,6 +234,9 @@ static void handle_unlock(struct wl_listener *listener, void *data) {
|
||||||
struct sway_output *output = root->outputs->items[i];
|
struct sway_output *output = root->outputs->items[i];
|
||||||
arrange_layers(output);
|
arrange_layers(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Views are now visible, so check if we need to activate inhibition again.
|
||||||
|
sway_idle_inhibit_v1_check_active();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_abandon(struct wl_listener *listener, void *data) {
|
static void handle_abandon(struct wl_listener *listener, void *data) {
|
||||||
|
@ -297,6 +300,10 @@ static void handle_session_lock(struct wl_listener *listener, void *data) {
|
||||||
|
|
||||||
wlr_session_lock_v1_send_locked(lock);
|
wlr_session_lock_v1_send_locked(lock);
|
||||||
server.session_lock.lock = sway_lock;
|
server.session_lock.lock = sway_lock;
|
||||||
|
|
||||||
|
// The lock screen covers everything, so check if any active inhibition got
|
||||||
|
// deactivated due to lost visibility.
|
||||||
|
sway_idle_inhibit_v1_check_active();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_session_lock_destroy(struct wl_listener *listener, void *data) {
|
static void handle_session_lock_destroy(struct wl_listener *listener, void *data) {
|
||||||
|
|
69
sway/main.c
69
sway/main.c
|
@ -1,5 +1,6 @@
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <pango/pangocairo.h>
|
#include <pango/pangocairo.h>
|
||||||
|
#include <pthread.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -44,10 +45,6 @@ void sway_terminate(int exit_code) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sig_handler(int signal) {
|
|
||||||
sway_terminate(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void run_as_ipc_client(char *command, char *socket_path) {
|
void run_as_ipc_client(char *command, char *socket_path) {
|
||||||
int socketfd = ipc_open_socket(socket_path);
|
int socketfd = ipc_open_socket(socket_path);
|
||||||
uint32_t len = strlen(command);
|
uint32_t len = strlen(command);
|
||||||
|
@ -125,6 +122,16 @@ static bool detect_suid(void) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void restore_nofile_limit(void) {
|
||||||
|
if (original_nofile_rlimit.rlim_cur == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (setrlimit(RLIMIT_NOFILE, &original_nofile_rlimit) != 0) {
|
||||||
|
sway_log_errno(SWAY_ERROR, "Failed to restore max open files limit: "
|
||||||
|
"setrlimit(NOFILE) failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void increase_nofile_limit(void) {
|
static void increase_nofile_limit(void) {
|
||||||
if (getrlimit(RLIMIT_NOFILE, &original_nofile_rlimit) != 0) {
|
if (getrlimit(RLIMIT_NOFILE, &original_nofile_rlimit) != 0) {
|
||||||
sway_log_errno(SWAY_ERROR, "Failed to bump max open files limit: "
|
sway_log_errno(SWAY_ERROR, "Failed to bump max open files limit: "
|
||||||
|
@ -139,17 +146,38 @@ static void increase_nofile_limit(void) {
|
||||||
"setrlimit(NOFILE) failed");
|
"setrlimit(NOFILE) failed");
|
||||||
sway_log(SWAY_INFO, "Running with %d max open files",
|
sway_log(SWAY_INFO, "Running with %d max open files",
|
||||||
(int)original_nofile_rlimit.rlim_cur);
|
(int)original_nofile_rlimit.rlim_cur);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void restore_nofile_limit(void) {
|
|
||||||
if (original_nofile_rlimit.rlim_cur == 0) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (setrlimit(RLIMIT_NOFILE, &original_nofile_rlimit) != 0) {
|
|
||||||
sway_log_errno(SWAY_ERROR, "Failed to restore max open files limit: "
|
pthread_atfork(NULL, NULL, restore_nofile_limit);
|
||||||
"setrlimit(NOFILE) failed");
|
}
|
||||||
}
|
|
||||||
|
static int term_signal(int signal, void *data) {
|
||||||
|
sway_terminate(EXIT_SUCCESS);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void restore_signals(void) {
|
||||||
|
sigset_t set;
|
||||||
|
sigemptyset(&set);
|
||||||
|
sigprocmask(SIG_SETMASK, &set, NULL);
|
||||||
|
|
||||||
|
struct sigaction sa_dfl = { .sa_handler = SIG_DFL };
|
||||||
|
sigaction(SIGCHLD, &sa_dfl, NULL);
|
||||||
|
sigaction(SIGPIPE, &sa_dfl, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init_signals(void) {
|
||||||
|
wl_event_loop_add_signal(server.wl_event_loop, SIGTERM, term_signal, NULL);
|
||||||
|
wl_event_loop_add_signal(server.wl_event_loop, SIGINT, term_signal, NULL);
|
||||||
|
|
||||||
|
struct sigaction sa_ign = { .sa_handler = SIG_IGN };
|
||||||
|
// avoid need to reap children
|
||||||
|
sigaction(SIGCHLD, &sa_ign, NULL);
|
||||||
|
// prevent ipc write errors from crashing sway
|
||||||
|
sigaction(SIGPIPE, &sa_ign, NULL);
|
||||||
|
|
||||||
|
pthread_atfork(NULL, NULL, restore_signals);
|
||||||
}
|
}
|
||||||
|
|
||||||
void enable_debug_flag(const char *flag) {
|
void enable_debug_flag(const char *flag) {
|
||||||
|
@ -159,10 +187,8 @@ void enable_debug_flag(const char *flag) {
|
||||||
debug.txn_wait = true;
|
debug.txn_wait = true;
|
||||||
} else if (strcmp(flag, "txn-timings") == 0) {
|
} else if (strcmp(flag, "txn-timings") == 0) {
|
||||||
debug.txn_timings = true;
|
debug.txn_timings = true;
|
||||||
} else if (strncmp(flag, "txn-timeout=", 12) == 0) {
|
} else if (has_prefix(flag, "txn-timeout=")) {
|
||||||
server.txn_timeout_ms = atoi(&flag[12]);
|
server.txn_timeout_ms = atoi(&flag[strlen("txn-timeout=")]);
|
||||||
} else if (strcmp(flag, "legacy-wl-drm") == 0) {
|
|
||||||
debug.legacy_wl_drm = true;
|
|
||||||
} else {
|
} else {
|
||||||
sway_log(SWAY_ERROR, "Unknown debug flag: %s", flag);
|
sway_log(SWAY_ERROR, "Unknown debug flag: %s", flag);
|
||||||
}
|
}
|
||||||
|
@ -323,13 +349,6 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
increase_nofile_limit();
|
increase_nofile_limit();
|
||||||
|
|
||||||
// handle SIGTERM signals
|
|
||||||
signal(SIGTERM, sig_handler);
|
|
||||||
signal(SIGINT, sig_handler);
|
|
||||||
|
|
||||||
// prevent ipc from crashing sway
|
|
||||||
signal(SIGPIPE, SIG_IGN);
|
|
||||||
|
|
||||||
sway_log(SWAY_INFO, "Starting swayfx version " SWAY_VERSION
|
sway_log(SWAY_INFO, "Starting swayfx version " SWAY_VERSION
|
||||||
" (based on sway version " SWAY_ORIGINAL_VERSION ")");
|
" (based on sway version " SWAY_ORIGINAL_VERSION ")");
|
||||||
|
|
||||||
|
@ -337,6 +356,8 @@ int main(int argc, char **argv) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init_signals();
|
||||||
|
|
||||||
if (server.linux_dmabuf_v1) {
|
if (server.linux_dmabuf_v1) {
|
||||||
wlr_scene_set_linux_dmabuf_v1(root->root_scene, server.linux_dmabuf_v1);
|
wlr_scene_set_linux_dmabuf_v1(root->root_scene, server.linux_dmabuf_v1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,16 +14,19 @@
|
||||||
#include <wlr/types/wlr_content_type_v1.h>
|
#include <wlr/types/wlr_content_type_v1.h>
|
||||||
#include <wlr/types/wlr_cursor_shape_v1.h>
|
#include <wlr/types/wlr_cursor_shape_v1.h>
|
||||||
#include <wlr/types/wlr_data_control_v1.h>
|
#include <wlr/types/wlr_data_control_v1.h>
|
||||||
|
#include <wlr/types/wlr_ext_data_control_v1.h>
|
||||||
#include <wlr/types/wlr_data_device.h>
|
#include <wlr/types/wlr_data_device.h>
|
||||||
#include <wlr/types/wlr_drm.h>
|
|
||||||
#include <wlr/types/wlr_export_dmabuf_v1.h>
|
#include <wlr/types/wlr_export_dmabuf_v1.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_ext_image_capture_source_v1.h>
|
||||||
|
#include <wlr/types/wlr_ext_image_copy_capture_v1.h>
|
||||||
#include <wlr/types/wlr_fractional_scale_v1.h>
|
#include <wlr/types/wlr_fractional_scale_v1.h>
|
||||||
#include <wlr/types/wlr_gamma_control_v1.h>
|
#include <wlr/types/wlr_gamma_control_v1.h>
|
||||||
#include <wlr/types/wlr_idle_notify_v1.h>
|
#include <wlr/types/wlr_idle_notify_v1.h>
|
||||||
#include <wlr/types/wlr_layer_shell_v1.h>
|
#include <wlr/types/wlr_layer_shell_v1.h>
|
||||||
#include <wlr/types/wlr_linux_dmabuf_v1.h>
|
#include <wlr/types/wlr_linux_dmabuf_v1.h>
|
||||||
|
#include <wlr/types/wlr_linux_drm_syncobj_v1.h>
|
||||||
#include <wlr/types/wlr_output_management_v1.h>
|
#include <wlr/types/wlr_output_management_v1.h>
|
||||||
#include <wlr/types/wlr_output_power_management_v1.h>
|
#include <wlr/types/wlr_output_power_management_v1.h>
|
||||||
#include <wlr/types/wlr_pointer_constraints_v1.h>
|
#include <wlr/types/wlr_pointer_constraints_v1.h>
|
||||||
|
@ -69,6 +72,7 @@
|
||||||
#define SWAY_XDG_SHELL_VERSION 5
|
#define SWAY_XDG_SHELL_VERSION 5
|
||||||
#define SWAY_LAYER_SHELL_VERSION 4
|
#define SWAY_LAYER_SHELL_VERSION 4
|
||||||
#define SWAY_FOREIGN_TOPLEVEL_LIST_VERSION 1
|
#define SWAY_FOREIGN_TOPLEVEL_LIST_VERSION 1
|
||||||
|
#define SWAY_PRESENTATION_VERSION 2
|
||||||
|
|
||||||
bool allow_unsupported_gpu = false;
|
bool allow_unsupported_gpu = false;
|
||||||
|
|
||||||
|
@ -104,8 +108,10 @@ static bool is_privileged(const struct wl_global *global) {
|
||||||
global == server.input_method->global ||
|
global == server.input_method->global ||
|
||||||
global == server.foreign_toplevel_list->global ||
|
global == server.foreign_toplevel_list->global ||
|
||||||
global == server.foreign_toplevel_manager->global ||
|
global == server.foreign_toplevel_manager->global ||
|
||||||
global == server.data_control_manager_v1->global ||
|
global == server.wlr_data_control_manager_v1->global ||
|
||||||
|
global == server.ext_data_control_manager_v1->global ||
|
||||||
global == server.screencopy_manager_v1->global ||
|
global == server.screencopy_manager_v1->global ||
|
||||||
|
global == server.ext_image_copy_capture_manager_v1->global ||
|
||||||
global == server.export_dmabuf_manager_v1->global ||
|
global == server.export_dmabuf_manager_v1->global ||
|
||||||
global == server.security_context_manager_v1->global ||
|
global == server.security_context_manager_v1->global ||
|
||||||
global == server.gamma_control_manager_v1->global ||
|
global == server.gamma_control_manager_v1->global ||
|
||||||
|
@ -175,11 +181,11 @@ static void detect_proprietary(struct wlr_backend *backend, void *data) {
|
||||||
drmFreeVersion(version);
|
drmFreeVersion(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_renderer_lost(struct wl_listener *listener, void *data) {
|
static void do_renderer_recreate(void *data) {
|
||||||
struct sway_server *server = wl_container_of(listener, server, renderer_lost);
|
struct sway_server *server = data;
|
||||||
|
server->recreating_renderer = NULL;
|
||||||
|
|
||||||
sway_log(SWAY_INFO, "Re-creating renderer after GPU reset");
|
sway_log(SWAY_INFO, "Re-creating renderer after GPU reset");
|
||||||
|
|
||||||
struct wlr_renderer *renderer = fx_renderer_create(server->backend);
|
struct wlr_renderer *renderer = fx_renderer_create(server->backend);
|
||||||
if (renderer == NULL) {
|
if (renderer == NULL) {
|
||||||
sway_log(SWAY_ERROR, "Unable to create renderer");
|
sway_log(SWAY_ERROR, "Unable to create renderer");
|
||||||
|
@ -214,12 +220,25 @@ static void handle_renderer_lost(struct wl_listener *listener, void *data) {
|
||||||
wlr_renderer_destroy(old_renderer);
|
wlr_renderer_destroy(old_renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void handle_renderer_lost(struct wl_listener *listener, void *data) {
|
||||||
|
struct sway_server *server = wl_container_of(listener, server, renderer_lost);
|
||||||
|
|
||||||
|
if (server->recreating_renderer != NULL) {
|
||||||
|
sway_log(SWAY_DEBUG, "Re-creation of renderer already scheduled");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sway_log(SWAY_INFO, "Scheduling re-creation of renderer after GPU reset");
|
||||||
|
server->recreating_renderer = wl_event_loop_add_idle(server->wl_event_loop, do_renderer_recreate, server);
|
||||||
|
}
|
||||||
|
|
||||||
bool server_init(struct sway_server *server) {
|
bool server_init(struct sway_server *server) {
|
||||||
sway_log(SWAY_DEBUG, "Initializing Wayland server");
|
sway_log(SWAY_DEBUG, "Initializing Wayland server");
|
||||||
server->wl_display = wl_display_create();
|
server->wl_display = wl_display_create();
|
||||||
server->wl_event_loop = wl_display_get_event_loop(server->wl_display);
|
server->wl_event_loop = wl_display_get_event_loop(server->wl_display);
|
||||||
|
|
||||||
wl_display_set_global_filter(server->wl_display, filter_global, NULL);
|
wl_display_set_global_filter(server->wl_display, filter_global, NULL);
|
||||||
|
wl_display_set_default_max_buffer_size(server->wl_display, 1024 * 1024);
|
||||||
|
|
||||||
root = root_create(server->wl_display);
|
root = root_create(server->wl_display);
|
||||||
|
|
||||||
|
@ -245,9 +264,12 @@ bool server_init(struct sway_server *server) {
|
||||||
if (wlr_renderer_get_texture_formats(server->renderer, WLR_BUFFER_CAP_DMABUF) != NULL) {
|
if (wlr_renderer_get_texture_formats(server->renderer, WLR_BUFFER_CAP_DMABUF) != NULL) {
|
||||||
server->linux_dmabuf_v1 = wlr_linux_dmabuf_v1_create_with_renderer(
|
server->linux_dmabuf_v1 = wlr_linux_dmabuf_v1_create_with_renderer(
|
||||||
server->wl_display, 4, server->renderer);
|
server->wl_display, 4, server->renderer);
|
||||||
if (debug.legacy_wl_drm) {
|
}
|
||||||
wlr_drm_create(server->wl_display, server->renderer);
|
if (wlr_renderer_get_drm_fd(server->renderer) >= 0 &&
|
||||||
}
|
server->renderer->features.timeline &&
|
||||||
|
server->backend->features.timeline) {
|
||||||
|
wlr_linux_drm_syncobj_manager_v1_create(server->wl_display, 1,
|
||||||
|
wlr_renderer_get_drm_fd(server->renderer));
|
||||||
}
|
}
|
||||||
|
|
||||||
server->allocator = wlr_allocator_autocreate(server->backend,
|
server->allocator = wlr_allocator_autocreate(server->backend,
|
||||||
|
@ -267,9 +289,8 @@ bool server_init(struct sway_server *server) {
|
||||||
|
|
||||||
server->gamma_control_manager_v1 =
|
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;
|
wlr_scene_set_gamma_control_manager_v1(root->root_scene,
|
||||||
wl_signal_add(&server->gamma_control_manager_v1->events.set_gamma,
|
server->gamma_control_manager_v1);
|
||||||
&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);
|
||||||
|
@ -321,7 +342,7 @@ bool server_init(struct sway_server *server) {
|
||||||
wl_signal_add(&server->pointer_constraints->events.new_constraint,
|
wl_signal_add(&server->pointer_constraints->events.new_constraint,
|
||||||
&server->pointer_constraint);
|
&server->pointer_constraint);
|
||||||
|
|
||||||
wlr_presentation_create(server->wl_display, server->backend);
|
wlr_presentation_create(server->wl_display, server->backend, SWAY_PRESENTATION_VERSION);
|
||||||
wlr_alpha_modifier_v1_create(server->wl_display);
|
wlr_alpha_modifier_v1_create(server->wl_display);
|
||||||
|
|
||||||
server->output_manager_v1 =
|
server->output_manager_v1 =
|
||||||
|
@ -363,7 +384,10 @@ bool server_init(struct sway_server *server) {
|
||||||
|
|
||||||
server->export_dmabuf_manager_v1 = wlr_export_dmabuf_manager_v1_create(server->wl_display);
|
server->export_dmabuf_manager_v1 = wlr_export_dmabuf_manager_v1_create(server->wl_display);
|
||||||
server->screencopy_manager_v1 = wlr_screencopy_manager_v1_create(server->wl_display);
|
server->screencopy_manager_v1 = wlr_screencopy_manager_v1_create(server->wl_display);
|
||||||
server->data_control_manager_v1 = wlr_data_control_manager_v1_create(server->wl_display);
|
server->ext_image_copy_capture_manager_v1 = wlr_ext_image_copy_capture_manager_v1_create(server->wl_display, 1);
|
||||||
|
wlr_ext_output_image_capture_source_manager_v1_create(server->wl_display, 1);
|
||||||
|
server->wlr_data_control_manager_v1 = wlr_data_control_manager_v1_create(server->wl_display);
|
||||||
|
server->ext_data_control_manager_v1 = wlr_ext_data_control_manager_v1_create(server->wl_display, 1);
|
||||||
server->security_context_manager_v1 = wlr_security_context_manager_v1_create(server->wl_display);
|
server->security_context_manager_v1 = wlr_security_context_manager_v1_create(server->wl_display);
|
||||||
wlr_viewporter_create(server->wl_display);
|
wlr_viewporter_create(server->wl_display);
|
||||||
wlr_single_pixel_buffer_manager_v1_create(server->wl_display);
|
wlr_single_pixel_buffer_manager_v1_create(server->wl_display);
|
||||||
|
@ -444,14 +468,41 @@ bool server_init(struct sway_server *server) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void server_fini(struct sway_server *server) {
|
void server_fini(struct sway_server *server) {
|
||||||
|
// remove listeners
|
||||||
|
wl_list_remove(&server->renderer_lost.link);
|
||||||
|
wl_list_remove(&server->new_output.link);
|
||||||
|
wl_list_remove(&server->layer_shell_surface.link);
|
||||||
|
wl_list_remove(&server->xdg_shell_toplevel.link);
|
||||||
|
wl_list_remove(&server->server_decoration.link);
|
||||||
|
wl_list_remove(&server->xdg_decoration.link);
|
||||||
|
wl_list_remove(&server->pointer_constraint.link);
|
||||||
|
wl_list_remove(&server->output_manager_apply.link);
|
||||||
|
wl_list_remove(&server->output_manager_test.link);
|
||||||
|
wl_list_remove(&server->output_power_manager_set_mode.link);
|
||||||
|
#if WLR_HAS_DRM_BACKEND
|
||||||
|
if (server->drm_lease_manager) {
|
||||||
|
wl_list_remove(&server->drm_lease_request.link);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
wl_list_remove(&server->tearing_control_new_object.link);
|
||||||
|
wl_list_remove(&server->xdg_activation_v1_request_activate.link);
|
||||||
|
wl_list_remove(&server->xdg_activation_v1_new_token.link);
|
||||||
|
wl_list_remove(&server->request_set_cursor_shape.link);
|
||||||
|
input_manager_finish(server->input);
|
||||||
|
|
||||||
// TODO: free sway-specific resources
|
// TODO: free sway-specific resources
|
||||||
#if WLR_HAS_XWAYLAND
|
#if WLR_HAS_XWAYLAND
|
||||||
wlr_xwayland_destroy(server->xwayland.wlr_xwayland);
|
if (server->xwayland.wlr_xwayland != NULL) {
|
||||||
|
wl_list_remove(&server->xwayland_surface.link);
|
||||||
|
wl_list_remove(&server->xwayland_ready.link);
|
||||||
|
wlr_xwayland_destroy(server->xwayland.wlr_xwayland);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
wl_display_destroy_clients(server->wl_display);
|
wl_display_destroy_clients(server->wl_display);
|
||||||
wlr_backend_destroy(server->backend);
|
wlr_backend_destroy(server->backend);
|
||||||
wl_display_destroy(server->wl_display);
|
wl_display_destroy(server->wl_display);
|
||||||
list_free(server->dirty_nodes);
|
list_free(server->dirty_nodes);
|
||||||
|
free(server->socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool server_start(struct sway_server *server) {
|
bool server_start(struct sway_server *server) {
|
||||||
|
|
|
@ -143,6 +143,12 @@ runtime.
|
||||||
|
|
||||||
This setting also applies to the current binding mode indicator.
|
This setting also applies to the current binding mode indicator.
|
||||||
|
|
||||||
|
The following commands may only be used at runtime.
|
||||||
|
|
||||||
|
*mode* toggle [<bar_id>]
|
||||||
|
Toggles the current mode between _hide_ and _dock_. Any other mode
|
||||||
|
is treated as _hide_.
|
||||||
|
|
||||||
## TRAY
|
## TRAY
|
||||||
|
|
||||||
Swaybar provides a system tray where third-party applications may place icons.
|
Swaybar provides a system tray where third-party applications may place icons.
|
||||||
|
|
|
@ -152,8 +152,9 @@ The following commands may only be used in the configuration file.
|
||||||
*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.
|
||||||
|
|
||||||
*input* <identifier> drag_lock enabled|disabled
|
*input* <identifier> drag_lock enabled|disabled|enabled_sticky
|
||||||
Enables or disables drag lock for specified input device.
|
Enables or disables drag lock for specified input device. The default is
|
||||||
|
_enabled_sticky_.
|
||||||
|
|
||||||
*input* <identifier> dwt enabled|disabled
|
*input* <identifier> dwt enabled|disabled
|
||||||
Enables or disables disable-while-typing for the specified input device.
|
Enables or disables disable-while-typing for the specified input device.
|
||||||
|
|
|
@ -138,7 +138,7 @@ has the following properties:
|
||||||
: Whether the workspace is currently focused by the default seat (_seat0_)
|
: Whether the workspace is currently focused by the default seat (_seat0_)
|
||||||
|- urgent
|
|- urgent
|
||||||
: boolean
|
: boolean
|
||||||
: Whether a view on the workspace has the urgent flag set
|
: Whether a window on the workspace has the urgent flag set
|
||||||
|- rect
|
|- rect
|
||||||
: object
|
: object
|
||||||
: The bounds of the workspace. It consists of _x_, _y_, _width_, and _height_
|
: The bounds of the workspace. It consists of _x_, _y_, _width_, and _height_
|
||||||
|
@ -405,7 +405,7 @@ node and will have the following properties:
|
||||||
that can be used as an aid in submitting reproduction steps for bug reports
|
that can be used as an aid in submitting reproduction steps for bug reports
|
||||||
|- fullscreen_mode
|
|- fullscreen_mode
|
||||||
: integer
|
: integer
|
||||||
: (Only containers and views) The fullscreen mode of the node. 0 means none, 1 means
|
: (Only containers and windows) The fullscreen mode of the node. 0 means none, 1 means
|
||||||
full workspace, and 2 means global fullscreen
|
full workspace, and 2 means global fullscreen
|
||||||
|- floating
|
|- floating
|
||||||
: string
|
: string
|
||||||
|
@ -415,32 +415,45 @@ node and will have the following properties:
|
||||||
: Whether the window is in the scratchpad. Can be either "none" or "fresh"
|
: Whether the window is in the scratchpad. Can be either "none" or "fresh"
|
||||||
|- app_id
|
|- app_id
|
||||||
: string
|
: string
|
||||||
: (Only views) For an xdg-shell view, the name of the application, if set.
|
: (Only windows) For an xdg-shell window, the name of the application, if set.
|
||||||
Otherwise, _null_
|
Otherwise, _null_
|
||||||
|- pid
|
|- pid
|
||||||
: integer
|
: integer
|
||||||
: (Only views) The PID of the application that owns the view
|
: (Only windows) The PID of the application that owns the window
|
||||||
|
|- foreign_toplevel_identifier
|
||||||
|
: string
|
||||||
|
: (Only windows) The ext-foreign-toplevel-list-v1 toplevel identifier of this node.
|
||||||
|- visible
|
|- visible
|
||||||
: boolean
|
: boolean
|
||||||
: (Only views) Whether the node is visible
|
: (Only windows) Whether the node is visible
|
||||||
|- shell
|
|- shell
|
||||||
: string
|
: string
|
||||||
: (Only views) The shell of the view, such as _xdg\_shell_ or _xwayland_
|
: (Only windows) The shell of the window, such as _xdg\_shell_ or _xwayland_
|
||||||
|- inhibit_idle
|
|- inhibit_idle
|
||||||
: boolean
|
: boolean
|
||||||
: (Only views) Whether the view is inhibiting the idle state
|
: (Only windows) Whether the window is inhibiting the idle state
|
||||||
|- idle_inhibitors
|
|- idle_inhibitors
|
||||||
: object
|
: object
|
||||||
: (Only views) An object containing the state of the _application_ and _user_ idle inhibitors.
|
: (Only windows) An object containing the state of the _application_ and _user_ idle inhibitors.
|
||||||
_application_ can be _enabled_ or _none_.
|
_application_ can be _enabled_ or _none_.
|
||||||
_user_ can be _focus_, _fullscreen_, _open_, _visible_ or _none_.
|
_user_ can be _focus_, _fullscreen_, _open_, _visible_ or _none_.
|
||||||
|
|- sandbox_engine
|
||||||
|
: string
|
||||||
|
: (Only windows) The associated sandbox engine (or _null_)
|
||||||
|
|- sandbox_app_id
|
||||||
|
: string
|
||||||
|
: (Only windows) The app ID provided by the associated sandbox engine (or _null_)
|
||||||
|
|- sandbox_instance_id
|
||||||
|
: string
|
||||||
|
: (Only windows) The instance ID provided by the associated sandbox engine (or
|
||||||
|
_null_)
|
||||||
|- window
|
|- window
|
||||||
: integer
|
: integer
|
||||||
: (Only xwayland views) The X11 window ID for the xwayland view
|
: (Only xwayland windows) The X11 window ID for the xwayland window
|
||||||
|- window_properties
|
|- window_properties
|
||||||
: object
|
: object
|
||||||
: (Only xwayland views) An object containing the _title_, _class_, _instance_,
|
: (Only xwayland windows) An object containing the _title_, _class_, _instance_,
|
||||||
_window\_role_, _window\_type_, and _transient\_for_ for the view
|
_window\_role_, _window\_type_, and _transient\_for_ for the window
|
||||||
|
|
||||||
|
|
||||||
*Example Reply:*
|
*Example Reply:*
|
||||||
|
@ -945,13 +958,13 @@ containing the _#RRGGBBAA_ representation of the color:
|
||||||
that are not visible
|
that are not visible
|
||||||
|- urgent_workspace_text
|
|- urgent_workspace_text
|
||||||
: The color to use for the text of the workspace buttons for workspaces that
|
: The color to use for the text of the workspace buttons for workspaces that
|
||||||
contain an urgent view
|
contain an urgent window
|
||||||
|- urgent_workspace_bg
|
|- urgent_workspace_bg
|
||||||
: The color to use for the background of the workspace buttons for workspaces
|
: The color to use for the background of the workspace buttons for workspaces
|
||||||
that contain an urgent view
|
that contain an urgent window
|
||||||
|- urgent_workspace_border
|
|- urgent_workspace_border
|
||||||
: The color to use for the border of the workspace buttons for workspaces that
|
: The color to use for the border of the workspace buttons for workspaces that
|
||||||
contain an urgent view
|
contain an urgent window
|
||||||
|- binding_mode_text
|
|- binding_mode_text
|
||||||
: The color to use for the text of the binding mode indicator
|
: The color to use for the text of the binding mode indicator
|
||||||
|- binding_mode_bg
|
|- binding_mode_bg
|
||||||
|
@ -1205,7 +1218,8 @@ following properties will be included for devices that support them:
|
||||||
: Whether tap-and-drag is enabled. It can be _enabled_ or _disabled_
|
: Whether tap-and-drag is enabled. It can be _enabled_ or _disabled_
|
||||||
|- tap_drag_lock
|
|- tap_drag_lock
|
||||||
: string
|
: string
|
||||||
: Whether drag-lock is enabled. It can be _enabled_ or _disabled_
|
: Whether drag-lock is enabled. It can be _enabled_, _disabled_ or
|
||||||
|
_enabled_sticky_
|
||||||
|- accel_speed
|
|- accel_speed
|
||||||
: double
|
: double
|
||||||
: The pointer-acceleration in use
|
: The pointer-acceleration in use
|
||||||
|
@ -1497,7 +1511,7 @@ available:
|
||||||
: Sent whenever the binding mode changes
|
: Sent whenever the binding mode changes
|
||||||
|- 0x80000003
|
|- 0x80000003
|
||||||
: window
|
: window
|
||||||
: Sent whenever an event involving a view occurs such as being reparented,
|
: Sent whenever an event involving a window occurs such as being reparented,
|
||||||
focused, or closed
|
focused, or closed
|
||||||
|- 0x80000004
|
|- 0x80000004
|
||||||
: barconfig_update
|
: barconfig_update
|
||||||
|
@ -1553,8 +1567,8 @@ The following change types are currently available:
|
||||||
|- rename
|
|- rename
|
||||||
: The workspace was renamed
|
: The workspace was renamed
|
||||||
|- urgent
|
|- urgent
|
||||||
: A view on the workspace has had their urgency hint set or all urgency hints
|
: A window on the workspace has had their urgency hint set or all urgency hints
|
||||||
for views on the workspace have been cleared
|
for windows on the workspace have been cleared
|
||||||
|- reload
|
|- reload
|
||||||
: The configuration file has been reloaded
|
: The configuration file has been reloaded
|
||||||
|
|
||||||
|
@ -1652,7 +1666,7 @@ with the following properties:
|
||||||
|
|
||||||
## 0x80000003. WINDOW
|
## 0x80000003. WINDOW
|
||||||
|
|
||||||
Sent whenever a change involving a view occurs. The event consists of a single
|
Sent whenever a change involving a window occurs. The event consists of a single
|
||||||
object with the following properties:
|
object with the following properties:
|
||||||
|
|
||||||
[- *PROPERTY*
|
[- *PROPERTY*
|
||||||
|
@ -1663,30 +1677,30 @@ object with the following properties:
|
||||||
:[ The type of change that occurred. See below for more information
|
:[ The type of change that occurred. See below for more information
|
||||||
|- container
|
|- container
|
||||||
: object
|
: object
|
||||||
: An object representing the view effected
|
: An object representing the window effected
|
||||||
|
|
||||||
|
|
||||||
The following change types are currently available:
|
The following change types are currently available:
|
||||||
[- *TYPE*
|
[- *TYPE*
|
||||||
:- *DESCRIPTION*
|
:- *DESCRIPTION*
|
||||||
|- new
|
|- new
|
||||||
:[ The view was created
|
:[ The window was created
|
||||||
|- close
|
|- close
|
||||||
: The view was closed
|
: The window was closed
|
||||||
|- focus
|
|- focus
|
||||||
: The view was focused
|
: The window was focused
|
||||||
|- title
|
|- title
|
||||||
: The view's title has changed
|
: The window's title has changed
|
||||||
|- fullscreen_mode
|
|- fullscreen_mode
|
||||||
: The view's fullscreen mode has changed
|
: The window's fullscreen mode has changed
|
||||||
|- move
|
|- move
|
||||||
: The view has been reparented in the tree
|
: The window has been reparented in the tree
|
||||||
|- floating
|
|- floating
|
||||||
: The view has become floating or is no longer floating
|
: The window has become floating or is no longer floating
|
||||||
|- urgent
|
|- urgent
|
||||||
: The view's urgency hint has changed status
|
: The window's urgency hint has changed status
|
||||||
|- mark
|
|- mark
|
||||||
: A mark has been added or removed from the view
|
: A mark has been added or removed from the window
|
||||||
|
|
||||||
|
|
||||||
*Example Event:*
|
*Example Event:*
|
||||||
|
|
131
sway/sway.5.scd
131
sway/sway.5.scd
|
@ -66,8 +66,8 @@ The following commands may only be used in the configuration file.
|
||||||
*default_orientation* horizontal|vertical|auto
|
*default_orientation* horizontal|vertical|auto
|
||||||
Sets the default container layout for tiled containers.
|
Sets the default container layout for tiled containers.
|
||||||
|
|
||||||
*include* <path>
|
*include* <paths...>
|
||||||
Includes another file from _path_. _path_ can be either a full path or a
|
Include files from _paths_. _paths_ can include either a full path or a
|
||||||
path relative to the parent config, and expands shell syntax (see
|
path relative to the parent config, and expands shell syntax (see
|
||||||
*wordexp*(3) for details). The same include file can only be included once;
|
*wordexp*(3) for details). The same include file can only be included once;
|
||||||
subsequent attempts will be ignored.
|
subsequent attempts will be ignored.
|
||||||
|
@ -121,7 +121,7 @@ They are expected to be used with *bindsym* or at runtime through *swaymsg*(1).
|
||||||
Exit sway and end your Wayland session.
|
Exit sway and end your Wayland session.
|
||||||
|
|
||||||
*floating* enable|disable|toggle
|
*floating* enable|disable|toggle
|
||||||
Make focused view floating, non-floating, or the opposite of what it is now.
|
Make focused window floating, non-floating, or the opposite of what it is now.
|
||||||
|
|
||||||
<criteria> *focus*
|
<criteria> *focus*
|
||||||
Moves focus to the container that matches the specified criteria.
|
Moves focus to the container that matches the specified criteria.
|
||||||
|
@ -156,9 +156,9 @@ They are expected to be used with *bindsym* or at runtime through *swaymsg*(1).
|
||||||
Moves focus between the floating and tiled layers.
|
Moves focus between the floating and tiled layers.
|
||||||
|
|
||||||
*fullscreen* [enable|disable|toggle] [global]
|
*fullscreen* [enable|disable|toggle] [global]
|
||||||
Makes focused view fullscreen, non-fullscreen, or the opposite of what it
|
Makes focused window fullscreen, non-fullscreen, or the opposite of what it
|
||||||
is now. If no argument is given, it does the same as _toggle_. If _global_
|
is now. If no argument is given, it does the same as _toggle_. If _global_
|
||||||
is specified, the view will be fullscreen across all outputs.
|
is specified, the window will be fullscreen across all outputs.
|
||||||
|
|
||||||
*gaps* inner|outer|horizontal|vertical|top|right|bottom|left all|current
|
*gaps* inner|outer|horizontal|vertical|top|right|bottom|left all|current
|
||||||
set|plus|minus|toggle <amount>
|
set|plus|minus|toggle <amount>
|
||||||
|
@ -168,16 +168,16 @@ set|plus|minus|toggle <amount>
|
||||||
_vertical_.
|
_vertical_.
|
||||||
|
|
||||||
*inhibit_idle* focus|fullscreen|open|none|visible
|
*inhibit_idle* focus|fullscreen|open|none|visible
|
||||||
Set/unset an idle inhibitor for the view. _focus_ will inhibit idle when
|
Set/unset an idle inhibitor for the window. _focus_ will inhibit idle when
|
||||||
the view is focused by any seat. _fullscreen_ will inhibit idle when the
|
the window is focused by any seat. _fullscreen_ will inhibit idle when the
|
||||||
view is fullscreen (or a descendant of a fullscreen container) and is
|
view is fullscreen (or a descendant of a fullscreen container) and is
|
||||||
visible. _open_ will inhibit idle until the view is closed (or the
|
visible. _open_ will inhibit idle until the window is closed (or the
|
||||||
inhibitor is unset/changed). _visible_ will inhibit idle when the view is
|
inhibitor is unset/changed). _visible_ will inhibit idle when the window is
|
||||||
visible on any output. _none_ will remove any existing idle inhibitor for
|
visible on any output. _none_ will remove any existing idle inhibitor for
|
||||||
the view.
|
the window.
|
||||||
|
|
||||||
This can also be used with criteria to set an idle inhibitor for any
|
This can also be used with criteria to set an idle inhibitor for any
|
||||||
existing view or with _for_window_ to set idle inhibitors for future views.
|
existing window or with _for_window_ to set idle inhibitors for future windows.
|
||||||
|
|
||||||
*layout* default|splith|splitv|stacking|tabbed
|
*layout* default|splith|splitv|stacking|tabbed
|
||||||
Sets the layout mode of the focused container.
|
Sets the layout mode of the focused container.
|
||||||
|
@ -335,12 +335,12 @@ set|plus|minus|toggle <amount>
|
||||||
|
|
||||||
*shortcuts_inhibitor* enable|disable
|
*shortcuts_inhibitor* enable|disable
|
||||||
Enables or disables the ability of clients to inhibit keyboard
|
Enables or disables the ability of clients to inhibit keyboard
|
||||||
shortcuts for a view. This is primarily useful for virtualization and
|
shortcuts for a window. This is primarily useful for virtualization and
|
||||||
remote desktop software. It affects either the currently focused view
|
remote desktop software. It affects either the currently focused window
|
||||||
or a set of views selected by criteria. Subcommand _disable_
|
or a set of windows selected by criteria. Subcommand _disable_
|
||||||
additionally deactivates any active inhibitors for the given view(s).
|
additionally deactivates any active inhibitors for the given window(s).
|
||||||
Criteria are particularly useful with the *for_window* command to
|
Criteria are particularly useful with the *for_window* command to
|
||||||
configure a class of views differently from the per-seat defaults
|
configure a class of windows differently from the per-seat defaults
|
||||||
established by the *seat* subcommand of the same name. See
|
established by the *seat* subcommand of the same name. See
|
||||||
*sway-input*(5) for more ways to affect inhibitors.
|
*sway-input*(5) for more ways to affect inhibitors.
|
||||||
|
|
||||||
|
@ -368,7 +368,7 @@ set|plus|minus|toggle <amount>
|
||||||
Swaps the position, geometry, and fullscreen status of two containers. The
|
Swaps the position, geometry, and fullscreen status of two containers. The
|
||||||
first container can be selected either by criteria or focus. The second
|
first container can be selected either by criteria or focus. The second
|
||||||
container can be selected by _id_, _con_id_, or _mark_. _id_ can only be
|
container can be selected by _id_, _con_id_, or _mark_. _id_ can only be
|
||||||
used with xwayland views. If the first container has focus, it will retain
|
used with xwayland windows. If the first container has focus, it will retain
|
||||||
focus unless it is moved to a different workspace or the second container
|
focus unless it is moved to a different workspace or the second container
|
||||||
becomes fullscreen on the same workspace as the first container. In either
|
becomes fullscreen on the same workspace as the first container. In either
|
||||||
of those cases, the second container will gain focus.
|
of those cases, the second container will gain focus.
|
||||||
|
@ -376,12 +376,29 @@ set|plus|minus|toggle <amount>
|
||||||
*title_format* <format>
|
*title_format* <format>
|
||||||
Sets the format of window titles. The following placeholders may be used:
|
Sets the format of window titles. The following placeholders may be used:
|
||||||
|
|
||||||
%title - The title supplied by the window ++
|
*%title*
|
||||||
%app_id - The wayland app ID (applicable to wayland windows only) ++
|
The title supplied by the window
|
||||||
%class - The X11 classname (applicable to xwayland windows only) ++
|
|
||||||
%instance - The X11 instance (applicable to xwayland windows only) ++
|
*%app_id*
|
||||||
%shell - The protocol the window is using (typically xwayland or
|
The wayland app ID (applicable to wayland windows only)
|
||||||
xdg_shell)
|
|
||||||
|
*%class*
|
||||||
|
The X11 classname (applicable to xwayland windows only)
|
||||||
|
|
||||||
|
*%instance*
|
||||||
|
The X11 instance (applicable to xwayland windows only)
|
||||||
|
|
||||||
|
*%shell*
|
||||||
|
The protocol the window is using (typically xwayland or xdg_shell)
|
||||||
|
|
||||||
|
*%sandbox_engine*
|
||||||
|
The associated sandbox engine
|
||||||
|
|
||||||
|
*%sandbox_app_id*
|
||||||
|
The app ID provided by the associated sandbox engine
|
||||||
|
|
||||||
|
*%sandbox_instance_id*
|
||||||
|
The instance ID provided by the associated sandbox engine
|
||||||
|
|
||||||
This command is typically used with *for_window* criteria. For example:
|
This command is typically used with *for_window* criteria. For example:
|
||||||
|
|
||||||
|
@ -396,14 +413,14 @@ The following commands may be used either in the configuration file or at
|
||||||
runtime.
|
runtime.
|
||||||
|
|
||||||
*assign* <criteria> [→] [workspace] [number] <workspace>
|
*assign* <criteria> [→] [workspace] [number] <workspace>
|
||||||
Assigns views matching _criteria_ (see *CRITERIA* for details) to
|
Assigns windows matching _criteria_ (see *CRITERIA* for details) to
|
||||||
_workspace_. The → (U+2192) is optional and cosmetic. This command is
|
_workspace_. The → (U+2192) is optional and cosmetic. This command is
|
||||||
equivalent to:
|
equivalent to:
|
||||||
|
|
||||||
for_window <criteria> move container to workspace <workspace>
|
for_window <criteria> move container to workspace <workspace>
|
||||||
|
|
||||||
*assign* <criteria> [→] output left|right|up|down|<name>
|
*assign* <criteria> [→] output left|right|up|down|<name>
|
||||||
Assigns views matching _criteria_ (see *CRITERIA* for details) to the
|
Assigns windows matching _criteria_ (see *CRITERIA* for details) to the
|
||||||
specified output. The → (U+2192) is optional and cosmetic. This command is
|
specified output. The → (U+2192) is optional and cosmetic. This command is
|
||||||
equivalent to:
|
equivalent to:
|
||||||
|
|
||||||
|
@ -586,10 +603,10 @@ runtime.
|
||||||
The window that has focus.
|
The window that has focus.
|
||||||
|
|
||||||
*client.focused_inactive*
|
*client.focused_inactive*
|
||||||
The most recently focused view within a container which is not focused.
|
The most recently focused window within a container which is not focused.
|
||||||
|
|
||||||
*client.focused_tab_title*
|
*client.focused_tab_title*
|
||||||
A view that has focused descendant container.
|
A window that has focused descendant container.
|
||||||
Tab or stack container title that is the parent of the focused container
|
Tab or stack container title that is the parent of the focused container
|
||||||
but is not directly focused. Defaults to focused_inactive if not
|
but is not directly focused. Defaults to focused_inactive if not
|
||||||
specified and does not use the indicator and child_border colors.
|
specified and does not use the indicator and child_border colors.
|
||||||
|
@ -598,10 +615,10 @@ runtime.
|
||||||
Ignored (present for i3 compatibility).
|
Ignored (present for i3 compatibility).
|
||||||
|
|
||||||
*client.unfocused*
|
*client.unfocused*
|
||||||
A view that does not have focus.
|
A window that does not have focus.
|
||||||
|
|
||||||
*client.urgent*
|
*client.urgent*
|
||||||
A view with an urgency hint. *Note*: Native Wayland windows do not
|
A window with an urgency hint. *Note*: Native Wayland windows do not
|
||||||
support urgency. Urgency only works for Xwayland windows.
|
support urgency. Urgency only works for Xwayland windows.
|
||||||
|
|
||||||
The meaning of each color is:
|
The meaning of each color is:
|
||||||
|
@ -616,12 +633,12 @@ runtime.
|
||||||
The text color of the title bar.
|
The text color of the title bar.
|
||||||
|
|
||||||
_indicator_
|
_indicator_
|
||||||
The color used to indicate where a new view will open. In a tiled
|
The color used to indicate where a new window will open. In a tiled
|
||||||
container, this would paint the right border of the current view if a
|
container, this would paint the right border of the current window if a
|
||||||
new view would be opened to the right.
|
new window would be opened to the right.
|
||||||
|
|
||||||
_child_border_
|
_child_border_
|
||||||
The border around the view itself.
|
The border around the window itself.
|
||||||
|
|
||||||
The default colors are:
|
The default colors are:
|
||||||
|
|
||||||
|
@ -865,7 +882,7 @@ The default colors are:
|
||||||
|
|
||||||
*gaps* inner|outer|horizontal|vertical|top|right|bottom|left <amount>
|
*gaps* inner|outer|horizontal|vertical|top|right|bottom|left <amount>
|
||||||
Sets default _amount_ pixels of _inner_ or _outer_ gap, where the inner
|
Sets default _amount_ pixels of _inner_ or _outer_ gap, where the inner
|
||||||
affects spacing around each view and outer affects the spacing around each
|
affects spacing around each window and outer affects the spacing around each
|
||||||
workspace. Outer gaps are in addition to inner gaps. To reduce or remove
|
workspace. Outer gaps are in addition to inner gaps. To reduce or remove
|
||||||
outer gaps, outer gaps can be set to a negative value. _outer_ gaps can
|
outer gaps, outer gaps can be set to a negative value. _outer_ gaps can
|
||||||
also be specified per side with _top_, _right_, _bottom_, and _left_ or
|
also be specified per side with _top_, _right_, _bottom_, and _left_ or
|
||||||
|
@ -937,9 +954,9 @@ The default colors are:
|
||||||
A list of output names may be obtained via *swaymsg -t get_outputs*.
|
A list of output names may be obtained via *swaymsg -t get_outputs*.
|
||||||
|
|
||||||
*popup_during_fullscreen* smart|ignore|leave_fullscreen
|
*popup_during_fullscreen* smart|ignore|leave_fullscreen
|
||||||
Determines what to do when a fullscreen view opens a dialog.
|
Determines what to do when a fullscreen window opens a dialog.
|
||||||
If _smart_ (the default), the dialog will be displayed. If _ignore_, the
|
If _smart_ (the default), the dialog will be displayed. If _ignore_, the
|
||||||
dialog will not be rendered. If _leave_fullscreen_, the view will exit
|
dialog will not be rendered. If _leave_fullscreen_, the window will exit
|
||||||
fullscreen mode and the dialog will be rendered.
|
fullscreen mode and the dialog will be rendered.
|
||||||
|
|
||||||
*primary_selection* enabled|disabled
|
*primary_selection* enabled|disabled
|
||||||
|
@ -1065,18 +1082,18 @@ The default colors are:
|
||||||
A criteria is a string in the form of, for example:
|
A criteria is a string in the form of, for example:
|
||||||
|
|
||||||
```
|
```
|
||||||
[class="[Rr]egex.*" title="some title"]
|
[app_id="some-application" title="[Rr]egex.*"]
|
||||||
```
|
```
|
||||||
|
|
||||||
The string contains one or more (space separated) attribute/value pairs. They
|
The string contains one or more (space separated) attribute/value pairs. They
|
||||||
are used by some commands to choose which views to execute actions on. All
|
are used by some commands to choose which windows to execute actions on. All
|
||||||
attributes must match for the criteria to match. Criteria is retained across
|
attributes must match for the criteria to match. Criteria is retained across
|
||||||
commands separated by a *,*, but will be reset (and allow for new criteria, if
|
commands separated by a *,*, but will be reset (and allow for new criteria, if
|
||||||
desired) for commands separated by a *;*.
|
desired) for commands separated by a *;*.
|
||||||
|
|
||||||
Criteria may be used with either the *for_window* or *assign* commands to
|
Criteria may be used with either the *for_window* or *assign* commands to
|
||||||
specify operations to perform on new views. A criteria may also be used to
|
specify operations to perform on new windows. A criteria may also be used to
|
||||||
perform specific commands (ones that normally act upon one window) on all views
|
perform specific commands (ones that normally act upon one window) on all windows
|
||||||
that match that criteria. For example:
|
that match that criteria. For example:
|
||||||
|
|
||||||
Focus on a window with the mark "IRC":
|
Focus on a window with the mark "IRC":
|
||||||
|
@ -1085,10 +1102,19 @@ Focus on a window with the mark "IRC":
|
||||||
[con_mark="IRC"] focus
|
[con_mark="IRC"] focus
|
||||||
```
|
```
|
||||||
|
|
||||||
Kill all windows with the title "Emacs":
|
Kill all windows where the title contains "Emacs":
|
||||||
|
|
||||||
```
|
```
|
||||||
[class="Emacs"] kill
|
[title="Emacs"] kill
|
||||||
|
```
|
||||||
|
|
||||||
|
Several attributes allow regular expressions. These use Perl-compatible regular
|
||||||
|
expressions (PCRE2), which are documented in *pcre2pattern*(3) and summarized in
|
||||||
|
*pcre2syntax*(3). For example, this moves all windows with titles ending in
|
||||||
|
"sway" or "Sway" to workspace 1:
|
||||||
|
|
||||||
|
```
|
||||||
|
[title="[Ss]way$"] move workspace 1
|
||||||
```
|
```
|
||||||
|
|
||||||
You may like to use swaymsg -t get_tree for finding the values of these
|
You may like to use swaymsg -t get_tree for finding the values of these
|
||||||
|
@ -1164,10 +1190,27 @@ The following attributes may be matched with:
|
||||||
applications and requires XWayland.
|
applications and requires XWayland.
|
||||||
|
|
||||||
*workspace*
|
*workspace*
|
||||||
Compare against the workspace name for this view. Can be a regular
|
Compare against the workspace name for this window. Can be a regular
|
||||||
expression. If the value is \_\_focused\_\_, then all the views on the
|
expression. If the value is \_\_focused\_\_, then all the windows on the
|
||||||
currently focused workspace matches.
|
currently focused workspace matches.
|
||||||
|
|
||||||
|
*sandbox_engine*
|
||||||
|
Compare against the associated sandbox engine. Can be a regular expression.
|
||||||
|
If the value is \_\_focused\_\_, then the sandbox engine must be the same as
|
||||||
|
that of the currently focused window.
|
||||||
|
|
||||||
|
*sandbox_app_id*
|
||||||
|
Compare against the app ID provided by the associated sandbox engine. Can be
|
||||||
|
a regular expression. If the value is \_\_focused\_\_, then the sandbox app
|
||||||
|
ID must be the same as that of the currently focused window.
|
||||||
|
|
||||||
|
*sandbox_instance_id*
|
||||||
|
Compare against the instance ID provided by the associated sandbox engine.
|
||||||
|
Can be a regular expression. If the value is \_\_focused\_\_, then the
|
||||||
|
sandbox instance ID must be the same as that of the currently focused
|
||||||
|
window.
|
||||||
|
|
||||||
# SEE ALSO
|
# SEE ALSO
|
||||||
|
|
||||||
*sway*(1) *sway-input*(5) *sway-output*(5) *sway-bar*(5) *sway-ipc*(7)
|
*sway*(1) *sway-input*(5) *sway-output*(5) *sway-bar*(5) *sway-ipc*(7)
|
||||||
|
*pcre2pattern*(3) *pcre2syntax*(3)
|
||||||
|
|
|
@ -64,18 +64,6 @@ static int get_text_width(struct sway_text_node *props) {
|
||||||
return MAX(width, 0);
|
return MAX(width, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_source_box(struct text_buffer *buffer) {
|
|
||||||
struct sway_text_node *props = &buffer->props;
|
|
||||||
struct wlr_fbox source_box = {
|
|
||||||
.x = 0,
|
|
||||||
.y = 0,
|
|
||||||
.width = ceil(get_text_width(props) * buffer->scale),
|
|
||||||
.height = ceil(props->height * buffer->scale),
|
|
||||||
};
|
|
||||||
|
|
||||||
wlr_scene_buffer_set_source_box(buffer->buffer_node, &source_box);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void render_backing_buffer(struct text_buffer *buffer) {
|
static void render_backing_buffer(struct text_buffer *buffer) {
|
||||||
if (!buffer->visible) {
|
if (!buffer->visible) {
|
||||||
return;
|
return;
|
||||||
|
@ -87,7 +75,7 @@ static void render_backing_buffer(struct text_buffer *buffer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
float scale = buffer->scale;
|
float scale = buffer->scale;
|
||||||
int width = ceil(buffer->props.width * scale);
|
int width = ceil(get_text_width(&buffer->props) * scale);
|
||||||
int height = ceil(buffer->props.height * scale);
|
int height = ceil(buffer->props.height * scale);
|
||||||
float *color = (float *)&buffer->props.color;
|
float *color = (float *)&buffer->props.color;
|
||||||
float *background = (float *)&buffer->props.background;
|
float *background = (float *)&buffer->props.background;
|
||||||
|
@ -147,13 +135,12 @@ static void render_backing_buffer(struct text_buffer *buffer) {
|
||||||
|
|
||||||
wlr_scene_buffer_set_buffer(buffer->buffer_node, &cairo_buffer->base);
|
wlr_scene_buffer_set_buffer(buffer->buffer_node, &cairo_buffer->base);
|
||||||
wlr_buffer_drop(&cairo_buffer->base);
|
wlr_buffer_drop(&cairo_buffer->base);
|
||||||
update_source_box(buffer);
|
|
||||||
|
|
||||||
pixman_region32_t opaque;
|
pixman_region32_t opaque;
|
||||||
pixman_region32_init(&opaque);
|
pixman_region32_init(&opaque);
|
||||||
if (background[3] == 1) {
|
if (background[3] == 1) {
|
||||||
pixman_region32_union_rect(&opaque, &opaque, 0, 0,
|
pixman_region32_union_rect(&opaque, &opaque, 0, 0,
|
||||||
buffer->props.width, buffer->props.height);
|
get_text_width(&buffer->props), buffer->props.height);
|
||||||
}
|
}
|
||||||
wlr_scene_buffer_set_opaque_region(buffer->buffer_node, &opaque);
|
wlr_scene_buffer_set_opaque_region(buffer->buffer_node, &opaque);
|
||||||
pixman_region32_fini(&opaque);
|
pixman_region32_fini(&opaque);
|
||||||
|
@ -300,7 +287,6 @@ void sway_text_node_set_max_width(struct sway_text_node *node, int max_width) {
|
||||||
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);
|
||||||
update_source_box(buffer);
|
|
||||||
render_backing_buffer(buffer);
|
render_backing_buffer(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,36 +63,27 @@ bool swaynag_spawn(const char *swaynag_command,
|
||||||
sway_log(SWAY_ERROR, "Failed to create fork for swaynag");
|
sway_log(SWAY_ERROR, "Failed to create fork for swaynag");
|
||||||
goto failed;
|
goto failed;
|
||||||
} else if (pid == 0) {
|
} else if (pid == 0) {
|
||||||
restore_nofile_limit();
|
if (!sway_set_cloexec(sockets[1], false)) {
|
||||||
|
|
||||||
pid = fork();
|
|
||||||
if (pid < 0) {
|
|
||||||
sway_log_errno(SWAY_ERROR, "fork failed");
|
|
||||||
_exit(EXIT_FAILURE);
|
|
||||||
} else if (pid == 0) {
|
|
||||||
if (!sway_set_cloexec(sockets[1], false)) {
|
|
||||||
_exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (swaynag->detailed) {
|
|
||||||
close(swaynag->fd[1]);
|
|
||||||
dup2(swaynag->fd[0], STDIN_FILENO);
|
|
||||||
close(swaynag->fd[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
char wayland_socket_str[16];
|
|
||||||
snprintf(wayland_socket_str, sizeof(wayland_socket_str),
|
|
||||||
"%d", sockets[1]);
|
|
||||||
setenv("WAYLAND_SOCKET", wayland_socket_str, true);
|
|
||||||
|
|
||||||
size_t length = strlen(swaynag_command) + strlen(swaynag->args) + 2;
|
|
||||||
char *cmd = malloc(length);
|
|
||||||
snprintf(cmd, length, "%s %s", swaynag_command, swaynag->args);
|
|
||||||
execlp("sh", "sh", "-c", cmd, NULL);
|
|
||||||
sway_log_errno(SWAY_ERROR, "execlp failed");
|
|
||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
_exit(EXIT_SUCCESS);
|
|
||||||
|
if (swaynag->detailed) {
|
||||||
|
close(swaynag->fd[1]);
|
||||||
|
dup2(swaynag->fd[0], STDIN_FILENO);
|
||||||
|
close(swaynag->fd[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
char wayland_socket_str[16];
|
||||||
|
snprintf(wayland_socket_str, sizeof(wayland_socket_str),
|
||||||
|
"%d", sockets[1]);
|
||||||
|
setenv("WAYLAND_SOCKET", wayland_socket_str, true);
|
||||||
|
|
||||||
|
size_t length = strlen(swaynag_command) + strlen(swaynag->args) + 2;
|
||||||
|
char *cmd = malloc(length);
|
||||||
|
snprintf(cmd, length, "%s %s", swaynag_command, swaynag->args);
|
||||||
|
execlp("sh", "sh", "-c", cmd, NULL);
|
||||||
|
sway_log_errno(SWAY_ERROR, "execlp failed");
|
||||||
|
_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (swaynag->detailed) {
|
if (swaynag->detailed) {
|
||||||
|
@ -107,11 +98,6 @@ bool swaynag_spawn(const char *swaynag_command,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (waitpid(pid, NULL, 0) < 0) {
|
|
||||||
sway_log_errno(SWAY_ERROR, "waitpid failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
failed:
|
failed:
|
||||||
|
@ -161,4 +147,3 @@ void swaynag_show(struct swaynag_instance *swaynag) {
|
||||||
close(swaynag->fd[1]);
|
close(swaynag->fd[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ static void apply_horiz_layout(list_t *children, struct wlr_box *parent) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate each height fraction
|
// Calculate each width fraction
|
||||||
double total_width_fraction = 0;
|
double total_width_fraction = 0;
|
||||||
for (int i = 0; i < children->length; ++i) {
|
for (int i = 0; i < children->length; ++i) {
|
||||||
struct sway_container *child = children->items[i];
|
struct sway_container *child = children->items[i];
|
||||||
|
@ -82,12 +82,18 @@ static void apply_horiz_layout(list_t *children, struct wlr_box *parent) {
|
||||||
child->pending.y = parent->y;
|
child->pending.y = parent->y;
|
||||||
child->pending.width = round(child->width_fraction * child_total_width);
|
child->pending.width = round(child->width_fraction * child_total_width);
|
||||||
child->pending.height = parent->height;
|
child->pending.height = parent->height;
|
||||||
child_x += child->pending.width + inner_gap;
|
|
||||||
|
|
||||||
// Make last child use remaining width of parent
|
// Make last child use remaining width of parent
|
||||||
if (i == children->length - 1) {
|
if (i == children->length - 1) {
|
||||||
child->pending.width = parent->x + parent->width - child->pending.x;
|
child->pending.width = parent->x + parent->width - child->pending.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Arbitrary lower bound for window size
|
||||||
|
if (child->pending.width < 10 || child->pending.height < 10) {
|
||||||
|
child->pending.width = 0;
|
||||||
|
child->pending.height = 0;
|
||||||
|
}
|
||||||
|
child_x += child->pending.width + inner_gap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,12 +167,18 @@ static void apply_vert_layout(list_t *children, struct wlr_box *parent) {
|
||||||
child->pending.y = child_y;
|
child->pending.y = child_y;
|
||||||
child->pending.width = parent->width;
|
child->pending.width = parent->width;
|
||||||
child->pending.height = round(child->height_fraction * child_total_height);
|
child->pending.height = round(child->height_fraction * child_total_height);
|
||||||
child_y += child->pending.height + inner_gap;
|
|
||||||
|
|
||||||
// Make last child use remaining height of parent
|
// Make last child use remaining height of parent
|
||||||
if (i == children->length - 1) {
|
if (i == children->length - 1) {
|
||||||
child->pending.height = parent->y + parent->height - child->pending.y;
|
child->pending.height = parent->y + parent->height - child->pending.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Arbitrary lower bound for window size
|
||||||
|
if (child->pending.width < 10 || child->pending.height < 10) {
|
||||||
|
child->pending.width = 0;
|
||||||
|
child->pending.height = 0;
|
||||||
|
}
|
||||||
|
child_y += child->pending.height + inner_gap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#include "sway/tree/container.h"
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <drm_fourcc.h>
|
#include <drm_fourcc.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -8,9 +7,8 @@
|
||||||
#include <wlr/types/wlr_linux_dmabuf_v1.h>
|
#include <wlr/types/wlr_linux_dmabuf_v1.h>
|
||||||
#include <wlr/types/wlr_output_layout.h>
|
#include <wlr/types/wlr_output_layout.h>
|
||||||
#include <wlr/types/wlr_subcompositor.h>
|
#include <wlr/types/wlr_subcompositor.h>
|
||||||
#include <wlr/util/box.h>
|
|
||||||
#include "linux-dmabuf-unstable-v1-protocol.h"
|
|
||||||
#include "scenefx/types/fx/corner_location.h"
|
#include "scenefx/types/fx/corner_location.h"
|
||||||
|
#include "linux-dmabuf-unstable-v1-protocol.h"
|
||||||
#include "sway/config.h"
|
#include "sway/config.h"
|
||||||
#include "sway/desktop/transaction.h"
|
#include "sway/desktop/transaction.h"
|
||||||
#include "sway/input/input-manager.h"
|
#include "sway/input/input-manager.h"
|
||||||
|
@ -53,6 +51,14 @@ static void handle_output_leave(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void handle_destroy(
|
||||||
|
struct wl_listener *listener, void *data) {
|
||||||
|
struct sway_container *con = wl_container_of(
|
||||||
|
listener, con, output_handler_destroy);
|
||||||
|
|
||||||
|
container_begin_destroy(con);
|
||||||
|
}
|
||||||
|
|
||||||
static bool handle_point_accepts_input(
|
static bool handle_point_accepts_input(
|
||||||
struct wlr_scene_buffer *buffer, double *x, double *y) {
|
struct wlr_scene_buffer *buffer, double *x, double *y) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -136,6 +142,9 @@ struct sway_container *container_create(struct sway_view *view) {
|
||||||
c->output_leave.notify = handle_output_leave;
|
c->output_leave.notify = handle_output_leave;
|
||||||
wl_signal_add(&c->output_handler->events.output_leave,
|
wl_signal_add(&c->output_handler->events.output_leave,
|
||||||
&c->output_leave);
|
&c->output_leave);
|
||||||
|
c->output_handler_destroy.notify = handle_destroy;
|
||||||
|
wl_signal_add(&c->output_handler->node.events.destroy,
|
||||||
|
&c->output_handler_destroy);
|
||||||
c->output_handler->point_accepts_input = handle_point_accepts_input;
|
c->output_handler->point_accepts_input = handle_point_accepts_input;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -578,6 +587,12 @@ void container_begin_destroy(struct sway_container *con) {
|
||||||
if (con->pending.parent || con->pending.workspace) {
|
if (con->pending.parent || con->pending.workspace) {
|
||||||
container_detach(con);
|
container_detach(con);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (con->view && con->view->container == con) {
|
||||||
|
wl_list_remove(&con->output_enter.link);
|
||||||
|
wl_list_remove(&con->output_leave.link);
|
||||||
|
wl_list_remove(&con->output_handler_destroy.link);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void container_reap_empty(struct sway_container *con) {
|
void container_reap_empty(struct sway_container *con) {
|
||||||
|
@ -722,26 +737,35 @@ size_t parse_title_format(struct sway_container *container, char *buffer) {
|
||||||
len += next - format;
|
len += next - format;
|
||||||
format = next;
|
format = next;
|
||||||
|
|
||||||
if (strncmp(next, "%title", 6) == 0) {
|
if (has_prefix(next, "%title")) {
|
||||||
if (container->view) {
|
if (container->view) {
|
||||||
len += append_prop(buffer, view_get_title(container->view));
|
len += append_prop(buffer, view_get_title(container->view));
|
||||||
} else {
|
} else {
|
||||||
len += container_build_representation(container->pending.layout, container->pending.children, buffer);
|
len += container_build_representation(container->pending.layout, container->pending.children, buffer);
|
||||||
}
|
}
|
||||||
format += 6;
|
format += strlen("%title");
|
||||||
} else if (container->view) {
|
} else if (container->view) {
|
||||||
if (strncmp(next, "%app_id", 7) == 0) {
|
if (has_prefix(next, "%app_id")) {
|
||||||
len += append_prop(buffer, view_get_app_id(container->view));
|
len += append_prop(buffer, view_get_app_id(container->view));
|
||||||
format += 7;
|
format += strlen("%app_id");
|
||||||
} else if (strncmp(next, "%class", 6) == 0) {
|
} else if (has_prefix(next, "%class")) {
|
||||||
len += append_prop(buffer, view_get_class(container->view));
|
len += append_prop(buffer, view_get_class(container->view));
|
||||||
format += 6;
|
format += strlen("%class");
|
||||||
} else if (strncmp(next, "%instance", 9) == 0) {
|
} else if (has_prefix(next, "%instance")) {
|
||||||
len += append_prop(buffer, view_get_instance(container->view));
|
len += append_prop(buffer, view_get_instance(container->view));
|
||||||
format += 9;
|
format += strlen("%instance");
|
||||||
} else if (strncmp(next, "%shell", 6) == 0) {
|
} else if (has_prefix(next, "%shell")) {
|
||||||
len += append_prop(buffer, view_get_shell(container->view));
|
len += append_prop(buffer, view_get_shell(container->view));
|
||||||
format += 6;
|
format += strlen("%shell");
|
||||||
|
} else if (has_prefix(next, "%sandbox_engine")) {
|
||||||
|
len += append_prop(buffer, view_get_sandbox_engine(container->view));
|
||||||
|
format += strlen("%sandbox_engine");
|
||||||
|
} else if (has_prefix(next, "%sandbox_app_id")) {
|
||||||
|
len += append_prop(buffer, view_get_sandbox_app_id(container->view));
|
||||||
|
format += strlen("%sandbox_app_id");
|
||||||
|
} else if (has_prefix(next, "%sandbox_instance_id")) {
|
||||||
|
len += append_prop(buffer, view_get_sandbox_instance_id(container->view));
|
||||||
|
format += strlen("%sandbox_instance_id");
|
||||||
} else {
|
} else {
|
||||||
lenient_strcat(buffer, "%");
|
lenient_strcat(buffer, "%");
|
||||||
++format;
|
++format;
|
||||||
|
@ -804,7 +828,7 @@ size_t container_build_representation(enum sway_container_layout layout,
|
||||||
len += strlen(identifier);
|
len += strlen(identifier);
|
||||||
lenient_strcat(buffer, identifier);
|
lenient_strcat(buffer, identifier);
|
||||||
} else {
|
} else {
|
||||||
len += 6;
|
len += strlen("(null)");
|
||||||
lenient_strcat(buffer, "(null)");
|
lenient_strcat(buffer, "(null)");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1968,3 +1992,4 @@ bool container_has_corner_radius(struct sway_container *con) {
|
||||||
!(config->smart_corner_radius && con->current.workspace->current_gaps.top == 0)) &&
|
!(config->smart_corner_radius && con->current.workspace->current_gaps.top == 0)) &&
|
||||||
con->corner_radius;
|
con->corner_radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -205,3 +205,4 @@ struct wlr_scene_shadow *alloc_scene_shadow(struct wlr_scene_tree *parent,
|
||||||
|
|
||||||
return shadow;
|
return shadow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ static void restore_workspaces(struct sway_output *output) {
|
||||||
for (int j = 0; j < other->workspaces->length; j++) {
|
for (int j = 0; j < other->workspaces->length; j++) {
|
||||||
struct sway_workspace *ws = other->workspaces->items[j];
|
struct sway_workspace *ws = other->workspaces->items[j];
|
||||||
struct sway_output *highest =
|
struct sway_output *highest =
|
||||||
workspace_output_get_highest_available(ws, NULL);
|
workspace_output_get_highest_available(ws);
|
||||||
if (highest == output) {
|
if (highest == output) {
|
||||||
workspace_detach(ws);
|
workspace_detach(ws);
|
||||||
output_add_workspace(output, ws);
|
output_add_workspace(output, ws);
|
||||||
|
@ -208,11 +208,8 @@ static void output_evacuate(struct sway_output *output) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
struct sway_output *fallback_output = NULL;
|
struct sway_output *fallback_output = NULL;
|
||||||
if (root->outputs->length > 1) {
|
if (root->outputs->length > 0) {
|
||||||
fallback_output = root->outputs->items[0];
|
fallback_output = root->outputs->items[0];
|
||||||
if (fallback_output == output) {
|
|
||||||
fallback_output = root->outputs->items[1];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (output->workspaces->length) {
|
while (output->workspaces->length) {
|
||||||
|
@ -221,7 +218,7 @@ static void output_evacuate(struct sway_output *output) {
|
||||||
workspace_detach(workspace);
|
workspace_detach(workspace);
|
||||||
|
|
||||||
struct sway_output *new_output =
|
struct sway_output *new_output =
|
||||||
workspace_output_get_highest_available(workspace, output);
|
workspace_output_get_highest_available(workspace);
|
||||||
if (!new_output) {
|
if (!new_output) {
|
||||||
new_output = fallback_output;
|
new_output = fallback_output;
|
||||||
}
|
}
|
||||||
|
@ -292,11 +289,13 @@ void output_disable(struct sway_output *output) {
|
||||||
sway_log(SWAY_DEBUG, "Disabling output '%s'", output->wlr_output->name);
|
sway_log(SWAY_DEBUG, "Disabling output '%s'", output->wlr_output->name);
|
||||||
wl_signal_emit_mutable(&output->events.disable, output);
|
wl_signal_emit_mutable(&output->events.disable, output);
|
||||||
|
|
||||||
output_evacuate(output);
|
// Remove the output now to avoid interacting with it during e.g.,
|
||||||
|
// transactions, as the output might be physically removed with the scene
|
||||||
|
// output destroyed.
|
||||||
list_del(root->outputs, index);
|
list_del(root->outputs, index);
|
||||||
|
|
||||||
output->enabled = false;
|
output->enabled = false;
|
||||||
|
|
||||||
|
output_evacuate(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
void output_begin_destroy(struct sway_output *output) {
|
void output_begin_destroy(struct sway_output *output) {
|
||||||
|
|
|
@ -228,6 +228,8 @@ void root_scratchpad_show(struct sway_container *con) {
|
||||||
if (old_ws) {
|
if (old_ws) {
|
||||||
workspace_consider_destroy(old_ws);
|
workspace_consider_destroy(old_ws);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
container_raise_floating(con);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void disable_fullscreen(struct sway_container *con, void *data) {
|
static void disable_fullscreen(struct sway_container *con, void *data) {
|
||||||
|
|
|
@ -8,9 +8,11 @@
|
||||||
#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_fractional_scale_v1.h>
|
||||||
#include <wlr/types/wlr_output_layout.h>
|
#include <wlr/types/wlr_output_layout.h>
|
||||||
|
#include <wlr/types/wlr_security_context_v1.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 <wlr/types/wlr_session_lock_v1.h>
|
||||||
#if WLR_HAS_XWAYLAND
|
#if WLR_HAS_XWAYLAND
|
||||||
#include <wlr/xwayland.h>
|
#include <wlr/xwayland.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -154,6 +156,34 @@ uint32_t view_get_window_type(struct sway_view *view) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct wlr_security_context_v1_state *security_context_from_view(
|
||||||
|
struct sway_view *view) {
|
||||||
|
const struct wl_client *client =
|
||||||
|
wl_resource_get_client(view->surface->resource);
|
||||||
|
const struct wlr_security_context_v1_state *security_context =
|
||||||
|
wlr_security_context_manager_v1_lookup_client(
|
||||||
|
server.security_context_manager_v1, client);
|
||||||
|
return security_context;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *view_get_sandbox_engine(struct sway_view *view) {
|
||||||
|
const struct wlr_security_context_v1_state *security_context =
|
||||||
|
security_context_from_view(view);
|
||||||
|
return security_context ? security_context->sandbox_engine : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *view_get_sandbox_app_id(struct sway_view *view) {
|
||||||
|
const struct wlr_security_context_v1_state *security_context =
|
||||||
|
security_context_from_view(view);
|
||||||
|
return security_context ? security_context->app_id : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *view_get_sandbox_instance_id(struct sway_view *view) {
|
||||||
|
const struct wlr_security_context_v1_state *security_context =
|
||||||
|
security_context_from_view(view);
|
||||||
|
return security_context ? security_context->instance_id : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
const char *view_get_shell(struct sway_view *view) {
|
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:
|
||||||
|
@ -188,6 +218,10 @@ uint32_t view_configure(struct sway_view *view, double lx, double ly, int width,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool view_inhibit_idle(struct sway_view *view) {
|
bool view_inhibit_idle(struct sway_view *view) {
|
||||||
|
if (server.session_lock.lock) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
struct sway_idle_inhibitor_v1 *user_inhibitor =
|
struct sway_idle_inhibitor_v1 *user_inhibitor =
|
||||||
sway_idle_inhibit_v1_user_inhibitor_for_view(view);
|
sway_idle_inhibit_v1_user_inhibitor_for_view(view);
|
||||||
|
|
||||||
|
@ -483,10 +517,12 @@ void view_execute_criteria(struct sway_view *view) {
|
||||||
sway_log(SWAY_DEBUG, "for_window '%s' matches view %p, cmd: '%s'",
|
sway_log(SWAY_DEBUG, "for_window '%s' matches view %p, cmd: '%s'",
|
||||||
criteria->raw, view, criteria->cmdlist);
|
criteria->raw, view, criteria->cmdlist);
|
||||||
list_add(view->executed_criteria, criteria);
|
list_add(view->executed_criteria, criteria);
|
||||||
list_t *res_list = execute_command(
|
list_t *res_list = execute_command(criteria->cmdlist, NULL, view->container);
|
||||||
criteria->cmdlist, NULL, view->container);
|
|
||||||
while (res_list->length) {
|
while (res_list->length) {
|
||||||
struct cmd_results *res = res_list->items[0];
|
struct cmd_results *res = res_list->items[0];
|
||||||
|
if (res->status != CMD_SUCCESS) {
|
||||||
|
sway_log(SWAY_ERROR, "for_window '%s' failed: %s", criteria->raw, res->error);
|
||||||
|
}
|
||||||
free_cmd_results(res);
|
free_cmd_results(res);
|
||||||
list_del(res_list, 0);
|
list_del(res_list, 0);
|
||||||
}
|
}
|
||||||
|
@ -879,7 +915,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface,
|
||||||
#if WLR_HAS_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_surface_icccm_input_model(xsurface) !=
|
||||||
WLR_ICCCM_INPUT_MODEL_NONE;
|
WLR_ICCCM_INPUT_MODEL_NONE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1015,6 +1051,9 @@ struct sway_view *view_from_wlr_surface(struct wlr_surface *wlr_surface) {
|
||||||
if (wlr_layer_surface_v1_try_from_wlr_surface(wlr_surface) != NULL) {
|
if (wlr_layer_surface_v1_try_from_wlr_surface(wlr_surface) != NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (wlr_session_lock_surface_v1_try_from_wlr_surface(wlr_surface) != NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
const char *role = wlr_surface->role ? wlr_surface->role->name : NULL;
|
const char *role = wlr_surface->role ? wlr_surface->role->name : NULL;
|
||||||
sway_log(SWAY_DEBUG, "Surface of unknown type (role %s): %p",
|
sway_log(SWAY_DEBUG, "Surface of unknown type (role %s): %p",
|
||||||
|
|
|
@ -246,7 +246,7 @@ static void workspace_name_from_binding(const struct sway_binding * binding,
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the command is workspace number <name>, isolate the name
|
// If the command is workspace number <name>, isolate the name
|
||||||
if (strncmp(_target, "number ", strlen("number ")) == 0) {
|
if (has_prefix(_target, "number ")) {
|
||||||
size_t length = strlen(_target) - strlen("number ") + 1;
|
size_t length = strlen(_target) - strlen("number ") + 1;
|
||||||
char *temp = malloc(length);
|
char *temp = malloc(length);
|
||||||
strncpy(temp, _target + strlen("number "), length - 1);
|
strncpy(temp, _target + strlen("number "), length - 1);
|
||||||
|
@ -659,13 +659,9 @@ void workspace_output_add_priority(struct sway_workspace *workspace,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sway_output *workspace_output_get_highest_available(
|
struct sway_output *workspace_output_get_highest_available(
|
||||||
struct sway_workspace *ws, struct sway_output *exclude) {
|
struct sway_workspace *ws) {
|
||||||
for (int i = 0; i < ws->output_priority->length; i++) {
|
for (int i = 0; i < ws->output_priority->length; i++) {
|
||||||
const char *name = ws->output_priority->items[i];
|
const char *name = ws->output_priority->items[i];
|
||||||
if (exclude && output_match_name_or_id(exclude, name)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sway_output *output = output_by_name_or_id(name);
|
struct sway_output *output = output_by_name_or_id(name);
|
||||||
if (output) {
|
if (output) {
|
||||||
return output;
|
return output;
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "loop.h"
|
#include "loop.h"
|
||||||
|
#include "stringop.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
void ipc_send_workspace_command(struct swaybar *bar, const char *ws) {
|
void ipc_send_workspace_command(struct swaybar *bar, const char *ws) {
|
||||||
|
@ -45,8 +46,8 @@ void ipc_send_workspace_command(struct swaybar *bar, const char *ws) {
|
||||||
|
|
||||||
char *parse_font(const char *font) {
|
char *parse_font(const char *font) {
|
||||||
char *new_font = NULL;
|
char *new_font = NULL;
|
||||||
if (strncmp("pango:", font, 6) == 0) {
|
if (has_prefix(font, "pango:")) {
|
||||||
font += 6;
|
font += strlen("pango:");
|
||||||
}
|
}
|
||||||
new_font = strdup(font);
|
new_font = strdup(font);
|
||||||
return new_font;
|
return new_font;
|
||||||
|
|
|
@ -93,8 +93,9 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
free(socket_path);
|
free(socket_path);
|
||||||
|
|
||||||
signal(SIGINT, sig_handler);
|
struct sigaction sa = { .sa_handler = sig_handler };
|
||||||
signal(SIGTERM, sig_handler);
|
sigaction(SIGINT, &sa, NULL);
|
||||||
|
sigaction(SIGTERM, &sa, NULL);
|
||||||
|
|
||||||
swaybar.running = true;
|
swaybar.running = true;
|
||||||
bar_run(&swaybar);
|
bar_run(&swaybar);
|
||||||
|
|
|
@ -293,11 +293,11 @@ static uint32_t render_status_block(struct render_context *ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
double offset = 0;
|
double offset = 0;
|
||||||
if (strncmp(block->align, "left", 4) == 0) {
|
if (has_prefix(block->align, "left")) {
|
||||||
offset = x_pos;
|
offset = x_pos;
|
||||||
} else if (strncmp(block->align, "right", 5) == 0) {
|
} else if (has_prefix(block->align, "right")) {
|
||||||
offset = x_pos + width - text_width;
|
offset = x_pos + width - text_width;
|
||||||
} else if (strncmp(block->align, "center", 6) == 0) {
|
} else if (has_prefix(block->align, "center")) {
|
||||||
offset = x_pos + (width - text_width) / 2;
|
offset = x_pos + (width - text_width) / 2;
|
||||||
}
|
}
|
||||||
double text_y = height / 2.0 - text_height / 2.0;
|
double text_y = height / 2.0 - text_height / 2.0;
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "cairo_util.h"
|
#include "cairo_util.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "stringop.h"
|
||||||
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
|
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
|
||||||
|
|
||||||
// TODO menu
|
// TODO menu
|
||||||
|
@ -161,7 +162,7 @@ static int get_property_callback(sd_bus_message *msg, void *data,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(prop, "Status") == 0 || (sni->status && (sni->status[0] == 'N' ?
|
if (strcmp(prop, "Status") == 0 || (sni->status && (sni->status[0] == 'N' ?
|
||||||
prop[0] == 'A' : strncmp(prop, "Icon", 4) == 0))) {
|
prop[0] == 'A' : has_prefix(prop, "Icon")))) {
|
||||||
set_sni_dirty(sni);
|
set_sni_dirty(sni);
|
||||||
}
|
}
|
||||||
cleanup:
|
cleanup:
|
||||||
|
@ -364,7 +365,7 @@ static void handle_click(struct swaybar_sni *sni, int x, int y,
|
||||||
method = "ContextMenu";
|
method = "ContextMenu";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp(method, "Scroll", strlen("Scroll")) == 0) {
|
if (has_prefix(method, "Scroll")) {
|
||||||
char dir = method[strlen("Scroll")];
|
char dir = method[strlen("Scroll")];
|
||||||
char *orientation = (dir == 'U' || dir == 'D') ? "vertical" : "horizontal";
|
char *orientation = (dir == 'U' || dir == 'D') ? "vertical" : "horizontal";
|
||||||
int sign = (dir == 'U' || dir == 'L') ? -1 : 1;
|
int sign = (dir == 'U' || dir == 'L') ? -1 : 1;
|
||||||
|
|
|
@ -31,9 +31,9 @@ static int handle_lost_service(sd_bus_message *msg,
|
||||||
struct swaybar_watcher *watcher = data;
|
struct swaybar_watcher *watcher = data;
|
||||||
for (int idx = 0; idx < watcher->items->length; ++idx) {
|
for (int idx = 0; idx < watcher->items->length; ++idx) {
|
||||||
char *id = watcher->items->items[idx];
|
char *id = watcher->items->items[idx];
|
||||||
int cmp_res = using_standard_protocol(watcher) ?
|
bool cmp_res = using_standard_protocol(watcher) ?
|
||||||
cmp_id(id, service) : strncmp(id, service, strlen(service));
|
cmp_id(id, service) == 0 : has_prefix(id, service);
|
||||||
if (cmp_res == 0) {
|
if (cmp_res) {
|
||||||
sway_log(SWAY_DEBUG, "Unregistering Status Notifier Item '%s'", id);
|
sway_log(SWAY_DEBUG, "Unregistering Status Notifier Item '%s'", id);
|
||||||
list_del(watcher->items, idx--);
|
list_del(watcher->items, idx--);
|
||||||
sd_bus_emit_signal(watcher->bus, obj_path, watcher->interface,
|
sd_bus_emit_signal(watcher->bus, obj_path, watcher->interface,
|
||||||
|
|
|
@ -16,10 +16,6 @@
|
||||||
#include "ipc-client.h"
|
#include "ipc-client.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
void sway_terminate(int exit_code) {
|
|
||||||
exit(exit_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool success_object(json_object *result) {
|
static bool success_object(json_object *result) {
|
||||||
json_object *success;
|
json_object *success;
|
||||||
|
|
||||||
|
@ -99,7 +95,7 @@ static const char *pretty_type_name(const char *name) {
|
||||||
const char *b;
|
const char *b;
|
||||||
} type_names[] = {
|
} type_names[] = {
|
||||||
{ "keyboard", "Keyboard" },
|
{ "keyboard", "Keyboard" },
|
||||||
{ "pointer", "Mouse" },
|
{ "pointer", "Pointer" },
|
||||||
{ "touchpad", "Touchpad" },
|
{ "touchpad", "Touchpad" },
|
||||||
{ "tablet_pad", "Tablet pad" },
|
{ "tablet_pad", "Tablet pad" },
|
||||||
{ "tablet_tool", "Tablet tool" },
|
{ "tablet_tool", "Tablet tool" },
|
||||||
|
@ -330,6 +326,10 @@ static void pretty_print_tree(json_object *obj, int indent) {
|
||||||
const char *instance = json_object_get_string(json_object_object_get(window_props_obj, "instance"));
|
const char *instance = json_object_get_string(json_object_object_get(window_props_obj, "instance"));
|
||||||
const char *class = json_object_get_string(json_object_object_get(window_props_obj, "class"));
|
const char *class = json_object_get_string(json_object_object_get(window_props_obj, "class"));
|
||||||
int x11_id = json_object_get_int(json_object_object_get(obj, "window"));
|
int x11_id = json_object_get_int(json_object_object_get(obj, "window"));
|
||||||
|
const char *foreign_toplevel_id = json_object_get_string(json_object_object_get(obj, "foreign_toplevel_identifier"));
|
||||||
|
const char *sandbox_engine = json_object_get_string(json_object_object_get(obj, "sandbox_engine"));
|
||||||
|
const char *sandbox_app_id = json_object_get_string(json_object_object_get(obj, "sandbox_app_id"));
|
||||||
|
const char *sandbox_instance_id = json_object_get_string(json_object_object_get(obj, "sandbox_instance_id"));
|
||||||
|
|
||||||
printf(" (%s, pid: %d", shell, pid);
|
printf(" (%s, pid: %d", shell, pid);
|
||||||
if (app_id != NULL) {
|
if (app_id != NULL) {
|
||||||
|
@ -344,6 +344,18 @@ static void pretty_print_tree(json_object *obj, int indent) {
|
||||||
if (x11_id != 0) {
|
if (x11_id != 0) {
|
||||||
printf(", X11 window: 0x%X", x11_id);
|
printf(", X11 window: 0x%X", x11_id);
|
||||||
}
|
}
|
||||||
|
if (foreign_toplevel_id != NULL) {
|
||||||
|
printf(", foreign_toplevel_id: \"%s\"", foreign_toplevel_id);
|
||||||
|
}
|
||||||
|
if (sandbox_engine != NULL) {
|
||||||
|
printf(", sandbox_engine: \"%s\"", sandbox_engine);
|
||||||
|
}
|
||||||
|
if (sandbox_app_id != NULL) {
|
||||||
|
printf(", sandbox_app_id: \"%s\"", sandbox_app_id);
|
||||||
|
}
|
||||||
|
if (sandbox_instance_id != NULL) {
|
||||||
|
printf(", sandbox_instance_id: \"%s\"", sandbox_instance_id);
|
||||||
|
}
|
||||||
printf(")");
|
printf(")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,11 +13,6 @@ void sig_handler(int signal) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sway_terminate(int code) {
|
|
||||||
swaynag_destroy(&swaynag);
|
|
||||||
exit(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
int status = EXIT_SUCCESS;
|
int status = EXIT_SUCCESS;
|
||||||
|
|
||||||
|
@ -107,7 +102,8 @@ int main(int argc, char **argv) {
|
||||||
sway_log(SWAY_DEBUG, "\t[%s] `%s`", button->text, button->action);
|
sway_log(SWAY_DEBUG, "\t[%s] `%s`", button->text, button->action);
|
||||||
}
|
}
|
||||||
|
|
||||||
signal(SIGTERM, sig_handler);
|
struct sigaction sa = { .sa_handler = sig_handler };
|
||||||
|
sigaction(SIGTERM, &sa, NULL);
|
||||||
|
|
||||||
swaynag_setup(&swaynag);
|
swaynag_setup(&swaynag);
|
||||||
swaynag_run(&swaynag);
|
swaynag_run(&swaynag);
|
||||||
|
|
Loading…
Add table
Reference in a new issue