This commit is contained in:
Emil Engberg 2023-12-19 16:55:22 +01:00
commit eb2dbe26f1
38 changed files with 349 additions and 469 deletions

View File

@ -2,13 +2,13 @@
Sway ist ein [i3](https://i3wm.org/)-kompatibler [Wayland](http://wayland.freedesktop.org/)-Compositor. Lies die [FAQ](https://github.com/swaywm/sway/wiki). Tritt dem [IRC Channel](https://web.libera.chat/gamja/?channels=#sway) bei (#sway on irc.libera.chat; Englisch). Sway ist ein [i3](https://i3wm.org/)-kompatibler [Wayland](http://wayland.freedesktop.org/)-Compositor. Lies die [FAQ](https://github.com/swaywm/sway/wiki). Tritt dem [IRC Channel](https://web.libera.chat/gamja/?channels=#sway) bei (#sway on irc.libera.chat; Englisch).
## Signaturen ## Signaturen
Jedes Release wird mit dem PGP-Schlüssel [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) signiert und auf GitHub veröffentlicht. Jedes Release wird mit dem PGP-Schlüssel [E88F5E48](https://keys.openpgp.org/search?q=34FF9526CFEF0E97A340E2E40FDE7BE0E88F5E48) signiert und [auf GitHub](https://github.com/swaywm/sway/releases) veröffentlicht.
## Installation ## Installation
### Mit der Paketverwaltung
Sway kann in vielen Distributionen direkt durch die Paketverwaltung installiert werden. Das Paket sollte "sway" heißen. Falls es kein solches Paket gibt, kannst du im [Wiki](https://github.com/swaywm/sway/wiki/Unsupported-packages) (englisch) nach mehr Informationen bezüglich deiner Distribution suchen.
Falls du sway für deine eigene Distribution als Paket bereitstellen möchtest, solltest du die Entwickler per IRC oder E-Mail (sir@cmpwn.com) kontaktieren. ### Über die Paketverwaltung
Sway kann in vielen Distributionen direkt durch die Paketverwaltung installiert werden. Versuche einfach das Packet "sway" zu installieren.
### Quellcode selbst kompilieren ### Quellcode selbst kompilieren
@ -23,8 +23,8 @@ sway benötigt die folgenden Pakete:
* pango * pango
* cairo * cairo
* gdk-pixbuf2 (Optional, wird für das Benachrichtigungsfeld (System Tray) benötigt) * gdk-pixbuf2 (Optional, wird für das Benachrichtigungsfeld (System Tray) benötigt)
* [scdoc](https://git.sr.ht/~sircmpwn/scdoc)\* (Optional, wird für die Dokumentation (Man Pages) benötigt) * [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (Optional, wird für die Dokumentation (Man Pages) benötigt)\*
* git\* * git (Optional: Versionsinfo)\*
_\*Werden nur während des Kompilierens benötigt_ _\*Werden nur während des Kompilierens benötigt_

View File

@ -1,7 +1,6 @@
lib_sway_common = static_library( lib_sway_common = static_library(
'sway-common', 'sway-common',
files( files(
'background-image.c',
'cairo.c', 'cairo.c',
'gesture.c', 'gesture.c',
'ipc-client.c', 'ipc-client.c',
@ -14,7 +13,6 @@ lib_sway_common = static_library(
), ),
dependencies: [ dependencies: [
cairo, cairo,
gdk_pixbuf,
pango, pango,
pangocairo, pangocairo,
wayland_client.partial_dependency(compile_args: true) wayland_client.partial_dependency(compile_args: true)

View File

@ -205,7 +205,7 @@ bar {
# When the status_command prints a new line to stdout, swaybar updates. # When the status_command prints a new line to stdout, swaybar updates.
# The default just shows the current date and time. # The default just shows the current date and time.
status_command while date +'%Y-%m-%d %I:%M:%S %p'; do sleep 1; done status_command while date +'%Y-%m-%d %X'; do sleep 1; done
colors { colors {
statusline #ffffff statusline #ffffff

View File

@ -1,20 +0,0 @@
#ifndef _SWAY_BACKGROUND_IMAGE_H
#define _SWAY_BACKGROUND_IMAGE_H
#include "cairo_util.h"
enum background_mode {
BACKGROUND_MODE_STRETCH,
BACKGROUND_MODE_FILL,
BACKGROUND_MODE_FIT,
BACKGROUND_MODE_CENTER,
BACKGROUND_MODE_TILE,
BACKGROUND_MODE_SOLID_COLOR,
BACKGROUND_MODE_INVALID,
};
enum background_mode parse_background_mode(const char *mode);
cairo_surface_t *load_background_image(const char *path);
void render_background_image(cairo_t *cairo, cairo_surface_t *image,
enum background_mode mode, int buffer_width, int buffer_height);
#endif

View File

@ -1,7 +1,6 @@
#ifndef _SWAY_INPUT_INPUT_MANAGER_H #ifndef _SWAY_INPUT_INPUT_MANAGER_H
#define _SWAY_INPUT_INPUT_MANAGER_H #define _SWAY_INPUT_INPUT_MANAGER_H
#include <libinput.h> #include <libinput.h>
#include <wlr/types/wlr_input_inhibitor.h>
#include <wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h> #include <wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h>
#include <wlr/types/wlr_virtual_keyboard_v1.h> #include <wlr/types/wlr_virtual_keyboard_v1.h>
#include <wlr/types/wlr_virtual_pointer_v1.h> #include <wlr/types/wlr_virtual_pointer_v1.h>
@ -21,7 +20,6 @@ struct sway_input_manager {
struct wl_list devices; struct wl_list devices;
struct wl_list seats; struct wl_list seats;
struct wlr_input_inhibit_manager *inhibit;
struct wlr_keyboard_shortcuts_inhibit_manager_v1 *keyboard_shortcuts_inhibit; struct wlr_keyboard_shortcuts_inhibit_manager_v1 *keyboard_shortcuts_inhibit;
struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard; struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard;
struct wlr_virtual_pointer_manager_v1 *virtual_pointer; struct wlr_virtual_pointer_manager_v1 *virtual_pointer;

View File

@ -108,9 +108,6 @@ struct sway_seat {
// If the exclusive layer is set, views cannot receive keyboard focus // If the exclusive layer is set, views cannot receive keyboard focus
bool has_exclusive_layer; bool has_exclusive_layer;
// If exclusive_client is set, no other clients will receive input events
struct wl_client *exclusive_client;
// Last touch point // Last touch point
int32_t touch_id; int32_t touch_id;
double touch_x, touch_y; double touch_x, touch_y;
@ -201,8 +198,7 @@ void seat_set_focus_surface(struct sway_seat *seat,
void seat_set_focus_layer(struct sway_seat *seat, void seat_set_focus_layer(struct sway_seat *seat,
struct wlr_layer_surface_v1 *layer); struct wlr_layer_surface_v1 *layer);
void seat_set_exclusive_client(struct sway_seat *seat, void seat_unfocus_unless_client(struct sway_seat *seat, struct wl_client *client);
struct wl_client *client);
struct sway_node *seat_get_focus(struct sway_seat *seat); struct sway_node *seat_get_focus(struct sway_seat *seat);

View File

@ -39,6 +39,7 @@ struct sway_output {
struct sway_output_state current; struct sway_output_state current;
struct wl_listener layout_destroy;
struct wl_listener destroy; struct wl_listener destroy;
struct wl_listener commit; struct wl_listener commit;
struct wl_listener present; struct wl_listener present;

View File

@ -59,7 +59,7 @@ struct sway_server {
struct wl_listener layer_shell_surface; struct wl_listener layer_shell_surface;
struct wlr_xdg_shell *xdg_shell; struct wlr_xdg_shell *xdg_shell;
struct wl_listener xdg_shell_surface; struct wl_listener xdg_shell_toplevel;
struct wlr_tablet_manager_v2 *tablet_v2; struct wlr_tablet_manager_v2 *tablet_v2;
@ -114,6 +114,10 @@ struct sway_server {
struct wlr_text_input_manager_v3 *text_input; struct wlr_text_input_manager_v3 *text_input;
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_screencopy_manager_v1 *screencopy_manager_v1;
struct wlr_export_dmabuf_manager_v1 *export_dmabuf_manager_v1;
struct wlr_security_context_manager_v1 *security_context_manager_v1;
struct wlr_xdg_activation_v1 *xdg_activation_v1; struct wlr_xdg_activation_v1 *xdg_activation_v1;
struct wl_listener xdg_activation_v1_request_activate; struct wl_listener xdg_activation_v1_request_activate;
@ -159,6 +163,8 @@ struct sway_debug {
extern struct sway_debug debug; extern struct sway_debug debug;
extern bool allow_unsupported_gpu;
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);
@ -172,7 +178,7 @@ 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);
void handle_layer_shell_surface(struct wl_listener *listener, void *data); void handle_layer_shell_surface(struct wl_listener *listener, void *data);
void sway_session_lock_init(void); void sway_session_lock_init(void);
void handle_xdg_shell_surface(struct wl_listener *listener, void *data); void handle_xdg_shell_toplevel(struct wl_listener *listener, void *data);
#if HAVE_XWAYLAND #if HAVE_XWAYLAND
void handle_xwayland_surface(struct wl_listener *listener, void *data); void handle_xwayland_surface(struct wl_listener *listener, void *data);
#endif #endif

View File

@ -41,7 +41,7 @@ struct sway_root {
} events; } events;
}; };
struct sway_root *root_create(void); struct sway_root *root_create(struct wl_display *display);
void root_destroy(struct sway_root *root); void root_destroy(struct sway_root *root);

View File

@ -226,6 +226,7 @@ struct sway_xdg_popup {
struct wlr_xdg_popup *wlr_xdg_popup; struct wlr_xdg_popup *wlr_xdg_popup;
struct wl_listener surface_commit;
struct wl_listener new_popup; struct wl_listener new_popup;
struct wl_listener destroy; struct wl_listener destroy;
}; };

View File

@ -16,4 +16,6 @@ struct sway_xdg_decoration {
struct sway_xdg_decoration *xdg_decoration_from_surface( struct sway_xdg_decoration *xdg_decoration_from_surface(
struct wlr_surface *surface); struct wlr_surface *surface);
void set_xdg_decoration_mode(struct sway_xdg_decoration *deco);
#endif #endif

7
include/swaybar/image.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef _SWAYBAR_IMAGE_H
#define _SWAYBAR_IMAGE_H
#include <cairo.h>
cairo_surface_t *load_image(const char *path);
#endif

View File

@ -37,7 +37,7 @@ if is_freebsd
endif endif
# Execute the wlroots subproject, if any # Execute the wlroots subproject, if any
wlroots_version = ['>=0.17.0', '<0.18.0'] wlroots_version = ['>=0.18.0', '<0.19.0']
subproject( subproject(
'wlroots', 'wlroots',
default_options: ['examples=false'], default_options: ['examples=false'],
@ -77,8 +77,7 @@ pixman = dependency('pixman-1')
libevdev = dependency('libevdev') libevdev = dependency('libevdev')
libinput = wlroots_features['libinput_backend'] ? dependency('libinput', version: '>=1.21.0') : null_dep libinput = wlroots_features['libinput_backend'] ? dependency('libinput', version: '>=1.21.0') : null_dep
xcb = dependency('xcb', required: get_option('xwayland')) xcb = dependency('xcb', required: get_option('xwayland'))
drm_full = dependency('libdrm') # only needed for drm_fourcc.h drm = dependency('libdrm')
drm = drm_full.partial_dependency(compile_args: true, includes: true)
libudev = wlroots_features['libinput_backend'] ? dependency('libudev') : null_dep libudev = wlroots_features['libinput_backend'] ? dependency('libudev') : null_dep
math = cc.find_library('m') math = cc.find_library('m')
rt = cc.find_library('rt') rt = cc.find_library('rt')

View File

@ -16,7 +16,6 @@ protocols = [
wl_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml', wl_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml',
'wlr-layer-shell-unstable-v1.xml', 'wlr-layer-shell-unstable-v1.xml',
'idle.xml', 'idle.xml',
'wlr-input-inhibitor-unstable-v1.xml',
'wlr-output-power-management-unstable-v1.xml', 'wlr-output-power-management-unstable-v1.xml',
] ]

View File

@ -1,67 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<protocol name="wlr_input_inhibit_unstable_v1">
<copyright>
Copyright © 2018 Drew DeVault
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
without fee, provided that the above copyright notice appear in
all copies and that both that copyright notice and this permission
notice appear in supporting documentation, and that the name of
the copyright holders not be used in advertising or publicity
pertaining to distribution of the software without specific,
written prior permission. The copyright holders make no
representations about the suitability of this software for any
purpose. It is provided "as is" without express or implied
warranty.
THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
THIS SOFTWARE.
</copyright>
<interface name="zwlr_input_inhibit_manager_v1" version="1">
<description summary="inhibits input events to other clients">
Clients can use this interface to prevent input events from being sent to
any surfaces but its own, which is useful for example in lock screen
software. It is assumed that access to this interface will be locked down
to whitelisted clients by the compositor.
</description>
<request name="get_inhibitor">
<description summary="inhibit input to other clients">
Activates the input inhibitor. As long as the inhibitor is active, the
compositor will not send input events to other clients.
</description>
<arg name="id" type="new_id" interface="zwlr_input_inhibitor_v1"/>
</request>
<enum name="error">
<entry name="already_inhibited" value="0" summary="an input inhibitor is already in use on the compositor"/>
</enum>
</interface>
<interface name="zwlr_input_inhibitor_v1" version="1">
<description summary="inhibits input to other clients">
While this resource exists, input to clients other than the owner of the
inhibitor resource will not receive input events. The client that owns
this resource will receive all input events normally. The compositor will
also disable all of its own input processing (such as keyboard shortcuts)
while the inhibitor is active.
The compositor may continue to send input events to selected clients,
such as an on-screen keyboard (via the input-method protocol).
</description>
<request name="destroy" type="destructor">
<description summary="destroy the input inhibitor object">
Destroy the inhibitor and allow other clients to receive input.
</description>
</request>
</interface>
</protocol>

View File

@ -123,7 +123,10 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
src); src);
config_add_swaynag_warning("Unable to access background file '%s'", config_add_swaynag_warning("Unable to access background file '%s'",
src); src);
struct cmd_results *result = cmd_results_new(CMD_FAILURE,
"unable to access background file '%s'", src);
free(src); free(src);
return result;
} else { } else {
output->background = src; output->background = src;
output->background_option = strdup(mode); output->background_option = strdup(mode);

View File

@ -1,4 +1,5 @@
#include <string.h> #include <string.h>
#include <wlr/util/transform.h>
#include "sway/commands.h" #include "sway/commands.h"
#include "sway/config.h" #include "sway/config.h"
#include "log.h" #include "log.h"

View File

@ -975,7 +975,7 @@ char *do_var_replacement(char *str) {
int offset = find - str; int offset = find - str;
strncpy(newptr, str, offset); strncpy(newptr, str, offset);
newptr += offset; newptr += offset;
strncpy(newptr, var->value, vvlen); memcpy(newptr, var->value, vvlen);
newptr += vvlen; newptr += vvlen;
strcpy(newptr, find + vnlen); strcpy(newptr, find + vnlen);
free(str); free(str);

View File

@ -305,9 +305,8 @@ static void handle_output_destroy(struct wl_listener *listener, void *data) {
struct sway_seat *seat = input_manager_get_default_seat(); struct sway_seat *seat = input_manager_get_default_seat();
struct wl_client *client = struct wl_client *client =
wl_resource_get_client(sway_layer->layer_surface->resource); wl_resource_get_client(sway_layer->layer_surface->resource);
bool set_focus = seat->exclusive_client == client;
if (set_focus) { if (!server.session_lock.locked) {
struct sway_layer_surface *layer = struct sway_layer_surface *layer =
find_mapped_layer_by_client(client, sway_layer->layer_surface->output); find_mapped_layer_by_client(client, sway_layer->layer_surface->output);
if (layer) { if (layer) {
@ -542,36 +541,6 @@ static void popup_damage(struct sway_layer_popup *layer_popup, bool whole) {
output_damage_surface(output, ox, oy, surface, whole); output_damage_surface(output, ox, oy, surface, whole);
} }
static void popup_handle_map(struct wl_listener *listener, void *data) {
struct sway_layer_popup *popup = wl_container_of(listener, popup, map);
struct sway_layer_surface *layer = popup_get_layer(popup);
struct wlr_output *wlr_output = layer->layer_surface->output;
sway_assert(wlr_output, "wlr_layer_surface_v1 has null output");
surface_enter_output(popup->wlr_popup->base->surface, wlr_output->data);
popup_damage(popup, true);
}
static void popup_handle_unmap(struct wl_listener *listener, void *data) {
struct sway_layer_popup *popup = wl_container_of(listener, popup, unmap);
popup_damage(popup, true);
}
static void popup_handle_commit(struct wl_listener *listener, void *data) {
struct sway_layer_popup *popup = wl_container_of(listener, popup, commit);
popup_damage(popup, false);
}
static void popup_handle_destroy(struct wl_listener *listener, void *data) {
struct sway_layer_popup *popup =
wl_container_of(listener, popup, destroy);
wl_list_remove(&popup->map.link);
wl_list_remove(&popup->unmap.link);
wl_list_remove(&popup->destroy.link);
wl_list_remove(&popup->commit.link);
free(popup);
}
static void popup_unconstrain(struct sway_layer_popup *popup) { static void popup_unconstrain(struct sway_layer_popup *popup) {
struct sway_layer_surface *layer = popup_get_layer(popup); struct sway_layer_surface *layer = popup_get_layer(popup);
struct wlr_xdg_popup *wlr_popup = popup->wlr_popup; struct wlr_xdg_popup *wlr_popup = popup->wlr_popup;
@ -592,6 +561,39 @@ static void popup_unconstrain(struct sway_layer_popup *popup) {
wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box); wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box);
} }
static void popup_handle_map(struct wl_listener *listener, void *data) {
struct sway_layer_popup *popup = wl_container_of(listener, popup, map);
struct sway_layer_surface *layer = popup_get_layer(popup);
struct wlr_output *wlr_output = layer->layer_surface->output;
sway_assert(wlr_output, "wlr_layer_surface_v1 has null output");
surface_enter_output(popup->wlr_popup->base->surface, wlr_output->data);
popup_damage(popup, true);
}
static void popup_handle_unmap(struct wl_listener *listener, void *data) {
struct sway_layer_popup *popup = wl_container_of(listener, popup, unmap);
popup_damage(popup, true);
}
static void popup_handle_commit(struct wl_listener *listener, void *data) {
struct sway_layer_popup *popup = wl_container_of(listener, popup, commit);
if (popup->wlr_popup->base->initial_commit) {
popup_unconstrain(popup);
}
popup_damage(popup, false);
}
static void popup_handle_destroy(struct wl_listener *listener, void *data) {
struct sway_layer_popup *popup =
wl_container_of(listener, popup, destroy);
wl_list_remove(&popup->map.link);
wl_list_remove(&popup->unmap.link);
wl_list_remove(&popup->destroy.link);
wl_list_remove(&popup->commit.link);
free(popup);
}
static void popup_handle_new_popup(struct wl_listener *listener, void *data); static void popup_handle_new_popup(struct wl_listener *listener, void *data);
static struct sway_layer_popup *create_popup(struct wlr_xdg_popup *wlr_popup, static struct sway_layer_popup *create_popup(struct wlr_xdg_popup *wlr_popup,
@ -617,8 +619,6 @@ static struct sway_layer_popup *create_popup(struct wlr_xdg_popup *wlr_popup,
popup->new_popup.notify = popup_handle_new_popup; popup->new_popup.notify = popup_handle_new_popup;
wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup); wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup);
popup_unconstrain(popup);
return popup; return popup;
} }

View File

@ -16,6 +16,7 @@
#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/util/region.h> #include <wlr/util/region.h>
#include <wlr/util/transform.h>
#include "config.h" #include "config.h"
#include "log.h" #include "log.h"
#include "sway/config.h" #include "sway/config.h"
@ -891,8 +892,7 @@ static void update_output_manager_config(struct sway_server *server) {
ipc_event_output(); ipc_event_output();
} }
static void handle_destroy(struct wl_listener *listener, void *data) { static void begin_destroy(struct sway_output *output) {
struct sway_output *output = wl_container_of(listener, output, destroy);
struct sway_server *server = output->server; struct sway_server *server = output->server;
if (output->enabled) { if (output->enabled) {
@ -903,6 +903,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
wl_list_remove(&output->link); wl_list_remove(&output->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->commit.link);
wl_list_remove(&output->present.link); wl_list_remove(&output->present.link);
@ -921,6 +922,16 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
update_output_manager_config(server); update_output_manager_config(server);
} }
static void handle_destroy(struct wl_listener *listener, void *data) {
struct sway_output *output = wl_container_of(listener, output, destroy);
begin_destroy(output);
}
static void handle_layout_destroy(struct wl_listener *listener, void *data) {
struct sway_output *output = wl_container_of(listener, output, layout_destroy);
begin_destroy(output);
}
static void update_textures(struct sway_container *con, void *data) { static void update_textures(struct sway_container *con, void *data) {
container_update_title_textures(con); container_update_title_textures(con);
container_update_marks_textures(con); container_update_marks_textures(con);
@ -964,6 +975,11 @@ static void handle_commit(struct wl_listener *listener, void *data) {
wlr_damage_ring_set_bounds(&output->damage_ring, width, height); wlr_damage_ring_set_bounds(&output->damage_ring, width, height);
wlr_output_schedule_frame(output->wlr_output); wlr_output_schedule_frame(output->wlr_output);
} }
// 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) {
@ -1030,6 +1046,8 @@ void handle_new_output(struct wl_listener *listener, void *data) {
output->server = server; output->server = server;
wlr_damage_ring_init(&output->damage_ring); wlr_damage_ring_init(&output->damage_ring);
wl_signal_add(&root->output_layout->events.destroy, &output->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); wl_signal_add(&wlr_output->events.commit, &output->commit);

View File

@ -13,6 +13,7 @@
#include <wlr/types/wlr_output.h> #include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_compositor.h> #include <wlr/types/wlr_compositor.h>
#include <wlr/util/region.h> #include <wlr/util/region.h>
#include <wlr/util/transform.h>
#include "log.h" #include "log.h"
#include "config.h" #include "config.h"
#include "sway/config.h" #include "sway/config.h"

View File

@ -38,6 +38,7 @@ static void popup_destroy(struct sway_view_child *child) {
return; return;
} }
struct sway_xdg_popup *popup = (struct sway_xdg_popup *)child; struct sway_xdg_popup *popup = (struct sway_xdg_popup *)child;
wl_list_remove(&popup->surface_commit.link);
wl_list_remove(&popup->new_popup.link); wl_list_remove(&popup->new_popup.link);
wl_list_remove(&popup->destroy.link); wl_list_remove(&popup->destroy.link);
free(popup); free(popup);
@ -51,18 +52,6 @@ static const struct sway_view_child_impl popup_impl = {
static struct sway_xdg_popup *popup_create( static struct sway_xdg_popup *popup_create(
struct wlr_xdg_popup *wlr_popup, struct sway_view *view); struct wlr_xdg_popup *wlr_popup, struct sway_view *view);
static void popup_handle_new_popup(struct wl_listener *listener, void *data) {
struct sway_xdg_popup *popup =
wl_container_of(listener, popup, new_popup);
struct wlr_xdg_popup *wlr_popup = data;
popup_create(wlr_popup, popup->child.view);
}
static void popup_handle_destroy(struct wl_listener *listener, void *data) {
struct sway_xdg_popup *popup = wl_container_of(listener, popup, destroy);
view_child_destroy(&popup->child);
}
static void popup_unconstrain(struct sway_xdg_popup *popup) { static void popup_unconstrain(struct sway_xdg_popup *popup) {
struct sway_view *view = popup->child.view; struct sway_view *view = popup->child.view;
struct wlr_xdg_popup *wlr_popup = popup->wlr_xdg_popup; struct wlr_xdg_popup *wlr_popup = popup->wlr_xdg_popup;
@ -87,6 +76,25 @@ static void popup_unconstrain(struct sway_xdg_popup *popup) {
wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box); wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box);
} }
static void popup_handle_surface_commit(struct wl_listener *listener, void *data) {
struct sway_xdg_popup *popup = wl_container_of(listener, popup, surface_commit);
if (popup->wlr_xdg_popup->base->initial_commit) {
popup_unconstrain(popup);
}
}
static void popup_handle_new_popup(struct wl_listener *listener, void *data) {
struct sway_xdg_popup *popup =
wl_container_of(listener, popup, new_popup);
struct wlr_xdg_popup *wlr_popup = data;
popup_create(wlr_popup, popup->child.view);
}
static void popup_handle_destroy(struct wl_listener *listener, void *data) {
struct sway_xdg_popup *popup = wl_container_of(listener, popup, destroy);
view_child_destroy(&popup->child);
}
static struct sway_xdg_popup *popup_create( static struct sway_xdg_popup *popup_create(
struct wlr_xdg_popup *wlr_popup, struct sway_view *view) { struct wlr_xdg_popup *wlr_popup, struct sway_view *view) {
struct wlr_xdg_surface *xdg_surface = wlr_popup->base; struct wlr_xdg_surface *xdg_surface = wlr_popup->base;
@ -97,22 +105,21 @@ static struct sway_xdg_popup *popup_create(
return NULL; return NULL;
} }
view_child_init(&popup->child, &popup_impl, view, xdg_surface->surface); view_child_init(&popup->child, &popup_impl, view, xdg_surface->surface);
popup->wlr_xdg_popup = xdg_surface->popup; popup->wlr_xdg_popup = wlr_popup;
wl_signal_add(&xdg_surface->surface->events.commit, &popup->surface_commit);
popup->surface_commit.notify = popup_handle_surface_commit;
wl_signal_add(&xdg_surface->events.new_popup, &popup->new_popup); wl_signal_add(&xdg_surface->events.new_popup, &popup->new_popup);
popup->new_popup.notify = popup_handle_new_popup; popup->new_popup.notify = popup_handle_new_popup;
wl_signal_add(&xdg_surface->events.destroy, &popup->destroy); wl_signal_add(&wlr_popup->events.destroy, &popup->destroy);
popup->destroy.notify = popup_handle_destroy; popup->destroy.notify = popup_handle_destroy;
wl_signal_add(&xdg_surface->surface->events.map, &popup->child.surface_map); wl_signal_add(&xdg_surface->surface->events.map, &popup->child.surface_map);
wl_signal_add(&xdg_surface->surface->events.unmap, &popup->child.surface_unmap); wl_signal_add(&xdg_surface->surface->events.unmap, &popup->child.surface_unmap);
popup_unconstrain(popup);
return popup; return popup;
} }
static struct sway_xdg_shell_view *xdg_shell_view_from_view( static struct sway_xdg_shell_view *xdg_shell_view_from_view(
struct sway_view *view) { struct sway_view *view) {
if (!sway_assert(view->type == SWAY_VIEW_XDG_SHELL, if (!sway_assert(view->type == SWAY_VIEW_XDG_SHELL,
@ -286,6 +293,19 @@ static void handle_commit(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_surface *xdg_surface = view->wlr_xdg_toplevel->base; struct wlr_xdg_surface *xdg_surface = view->wlr_xdg_toplevel->base;
if (xdg_surface->initial_commit) {
if (view->xdg_decoration != NULL) {
set_xdg_decoration_mode(view->xdg_decoration);
}
// XXX: https://github.com/swaywm/sway/issues/2176
wlr_xdg_surface_schedule_configure(xdg_surface);
return;
}
if (!xdg_surface->surface->mapped) {
return;
}
struct wlr_box new_geo; struct wlr_box new_geo;
wlr_xdg_surface_get_geometry(xdg_surface, &new_geo); 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 ||
@ -421,7 +441,6 @@ static void handle_unmap(struct wl_listener *listener, void *data) {
view_unmap(view); view_unmap(view);
wl_list_remove(&xdg_shell_view->commit.link);
wl_list_remove(&xdg_shell_view->new_popup.link); wl_list_remove(&xdg_shell_view->new_popup.link);
wl_list_remove(&xdg_shell_view->request_maximize.link); wl_list_remove(&xdg_shell_view->request_maximize.link);
wl_list_remove(&xdg_shell_view->request_fullscreen.link); wl_list_remove(&xdg_shell_view->request_fullscreen.link);
@ -464,10 +483,6 @@ static void handle_map(struct wl_listener *listener, void *data) {
transaction_commit_dirty(); transaction_commit_dirty();
xdg_shell_view->commit.notify = handle_commit;
wl_signal_add(&toplevel->base->surface->events.commit,
&xdg_shell_view->commit);
xdg_shell_view->new_popup.notify = handle_new_popup; xdg_shell_view->new_popup.notify = handle_new_popup;
wl_signal_add(&toplevel->base->events.new_popup, wl_signal_add(&toplevel->base->events.new_popup,
&xdg_shell_view->new_popup); &xdg_shell_view->new_popup);
@ -507,6 +522,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
wl_list_remove(&xdg_shell_view->destroy.link); wl_list_remove(&xdg_shell_view->destroy.link);
wl_list_remove(&xdg_shell_view->map.link); wl_list_remove(&xdg_shell_view->map.link);
wl_list_remove(&xdg_shell_view->unmap.link); wl_list_remove(&xdg_shell_view->unmap.link);
wl_list_remove(&xdg_shell_view->commit.link);
view->wlr_xdg_toplevel = NULL; view->wlr_xdg_toplevel = NULL;
if (view->xdg_decoration) { if (view->xdg_decoration) {
view->xdg_decoration->view = NULL; view->xdg_decoration->view = NULL;
@ -519,17 +535,12 @@ struct sway_view *view_from_wlr_xdg_surface(
return xdg_surface->data; return xdg_surface->data;
} }
void handle_xdg_shell_surface(struct wl_listener *listener, void *data) { void handle_xdg_shell_toplevel(struct wl_listener *listener, void *data) {
struct wlr_xdg_surface *xdg_surface = data; struct wlr_xdg_toplevel *xdg_toplevel = data;
if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) {
sway_log(SWAY_DEBUG, "New xdg_shell popup");
return;
}
sway_log(SWAY_DEBUG, "New xdg_shell toplevel title='%s' app_id='%s'", sway_log(SWAY_DEBUG, "New xdg_shell toplevel title='%s' app_id='%s'",
xdg_surface->toplevel->title, xdg_surface->toplevel->app_id); xdg_toplevel->title, xdg_toplevel->app_id);
wlr_xdg_surface_ping(xdg_surface); wlr_xdg_surface_ping(xdg_toplevel->base);
struct sway_xdg_shell_view *xdg_shell_view = struct sway_xdg_shell_view *xdg_shell_view =
calloc(1, sizeof(struct sway_xdg_shell_view)); calloc(1, sizeof(struct sway_xdg_shell_view));
@ -538,16 +549,20 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data) {
} }
view_init(&xdg_shell_view->view, SWAY_VIEW_XDG_SHELL, &view_impl); view_init(&xdg_shell_view->view, SWAY_VIEW_XDG_SHELL, &view_impl);
xdg_shell_view->view.wlr_xdg_toplevel = xdg_surface->toplevel; xdg_shell_view->view.wlr_xdg_toplevel = xdg_toplevel;
xdg_shell_view->map.notify = handle_map; xdg_shell_view->map.notify = handle_map;
wl_signal_add(&xdg_surface->surface->events.map, &xdg_shell_view->map); wl_signal_add(&xdg_toplevel->base->surface->events.map, &xdg_shell_view->map);
xdg_shell_view->unmap.notify = handle_unmap; xdg_shell_view->unmap.notify = handle_unmap;
wl_signal_add(&xdg_surface->surface->events.unmap, &xdg_shell_view->unmap); wl_signal_add(&xdg_toplevel->base->surface->events.unmap, &xdg_shell_view->unmap);
xdg_shell_view->commit.notify = handle_commit;
wl_signal_add(&xdg_toplevel->base->surface->events.commit,
&xdg_shell_view->commit);
xdg_shell_view->destroy.notify = handle_destroy; xdg_shell_view->destroy.notify = handle_destroy;
wl_signal_add(&xdg_surface->events.destroy, &xdg_shell_view->destroy); wl_signal_add(&xdg_toplevel->events.destroy, &xdg_shell_view->destroy);
xdg_surface->data = xdg_shell_view; xdg_toplevel->base->data = xdg_shell_view;
} }

View File

@ -170,6 +170,7 @@ static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) {
} }
static void handle_map(struct wl_listener *listener, void *data); static void handle_map(struct wl_listener *listener, void *data);
static void handle_associate(struct wl_listener *listener, void *data);
struct sway_xwayland_view *create_xwayland_view(struct wlr_xwayland_surface *xsurface); struct sway_xwayland_view *create_xwayland_view(struct wlr_xwayland_surface *xsurface);
@ -178,14 +179,22 @@ static void unmanaged_handle_override_redirect(struct wl_listener *listener, voi
wl_container_of(listener, surface, override_redirect); wl_container_of(listener, surface, override_redirect);
struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface; struct wlr_xwayland_surface *xsurface = surface->wlr_xwayland_surface;
bool mapped = xsurface->surface != NULL && xsurface->surface->mapped; bool associated = xsurface->surface != NULL;
bool mapped = associated && xsurface->surface->mapped;
if (mapped) { if (mapped) {
unmanaged_handle_unmap(&surface->unmap, NULL); unmanaged_handle_unmap(&surface->unmap, NULL);
} }
if (associated) {
unmanaged_handle_dissociate(&surface->dissociate, NULL);
}
unmanaged_handle_destroy(&surface->destroy, NULL); unmanaged_handle_destroy(&surface->destroy, NULL);
xsurface->data = NULL; xsurface->data = NULL;
struct sway_xwayland_view *xwayland_view = create_xwayland_view(xsurface); struct sway_xwayland_view *xwayland_view = create_xwayland_view(xsurface);
if (associated) {
handle_associate(&xwayland_view->associate, NULL);
}
if (mapped) { if (mapped) {
handle_map(&xwayland_view->map, xsurface); handle_map(&xwayland_view->map, xsurface);
} }
@ -531,20 +540,30 @@ static void handle_map(struct wl_listener *listener, void *data) {
transaction_commit_dirty(); transaction_commit_dirty();
} }
static void handle_dissociate(struct wl_listener *listener, void *data);
static void handle_override_redirect(struct wl_listener *listener, void *data) { static void handle_override_redirect(struct wl_listener *listener, void *data) {
struct sway_xwayland_view *xwayland_view = struct sway_xwayland_view *xwayland_view =
wl_container_of(listener, xwayland_view, override_redirect); wl_container_of(listener, xwayland_view, override_redirect);
struct sway_view *view = &xwayland_view->view; struct sway_view *view = &xwayland_view->view;
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
bool mapped = xsurface->surface != NULL && xsurface->surface->mapped; bool associated = xsurface->surface != NULL;
bool mapped = associated && xsurface->surface->mapped;
if (mapped) { if (mapped) {
handle_unmap(&xwayland_view->unmap, NULL); handle_unmap(&xwayland_view->unmap, NULL);
} }
if (associated) {
handle_dissociate(&xwayland_view->dissociate, NULL);
}
handle_destroy(&xwayland_view->destroy, view); handle_destroy(&xwayland_view->destroy, view);
xsurface->data = NULL; xsurface->data = NULL;
struct sway_xwayland_unmanaged *unmanaged = create_unmanaged(xsurface); struct sway_xwayland_unmanaged *unmanaged = create_unmanaged(xsurface);
if (associated) {
unmanaged_handle_associate(&unmanaged->associate, NULL);
}
if (mapped) { if (mapped) {
unmanaged_handle_map(&unmanaged->map, xsurface); unmanaged_handle_map(&unmanaged->map, xsurface);
} }

View File

@ -6,7 +6,6 @@
#include <wlr/config.h> #include <wlr/config.h>
#include <wlr/types/wlr_cursor.h> #include <wlr/types/wlr_cursor.h>
#include <wlr/types/wlr_keyboard_group.h> #include <wlr/types/wlr_keyboard_group.h>
#include <wlr/types/wlr_input_inhibitor.h>
#include <wlr/types/wlr_virtual_keyboard_v1.h> #include <wlr/types/wlr_virtual_keyboard_v1.h>
#include <wlr/types/wlr_virtual_pointer_v1.h> #include <wlr/types/wlr_virtual_pointer_v1.h>
#include "sway/config.h" #include "sway/config.h"
@ -284,34 +283,6 @@ static void handle_new_input(struct wl_listener *listener, void *data) {
} }
} }
static void handle_inhibit_activate(struct wl_listener *listener, void *data) {
struct sway_input_manager *input_manager = wl_container_of(
listener, input_manager, inhibit_activate);
struct sway_seat *seat;
wl_list_for_each(seat, &input_manager->seats, link) {
seat_set_exclusive_client(seat, input_manager->inhibit->active_client);
}
}
static void handle_inhibit_deactivate(struct wl_listener *listener, void *data) {
struct sway_input_manager *input_manager = wl_container_of(
listener, input_manager, inhibit_deactivate);
struct sway_seat *seat;
if (server.session_lock.locked) {
// Don't deactivate the grab of a screenlocker
return;
}
wl_list_for_each(seat, &input_manager->seats, link) {
seat_set_exclusive_client(seat, NULL);
struct sway_node *previous = seat_get_focus(seat);
if (previous) {
// Hack to get seat to re-focus the return value of get_focus
seat_set_focus(seat, NULL);
seat_set_focus(seat, previous);
}
}
}
static void handle_keyboard_shortcuts_inhibitor_destroy( static void handle_keyboard_shortcuts_inhibitor_destroy(
struct wl_listener *listener, void *data) { struct wl_listener *listener, void *data) {
struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor = struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor =
@ -480,14 +451,6 @@ struct sway_input_manager *input_manager_create(struct sway_server *server) {
&input->virtual_pointer_new); &input->virtual_pointer_new);
input->virtual_pointer_new.notify = handle_virtual_pointer; input->virtual_pointer_new.notify = handle_virtual_pointer;
input->inhibit = wlr_input_inhibit_manager_create(server->wl_display);
input->inhibit_activate.notify = handle_inhibit_activate;
wl_signal_add(&input->inhibit->events.activate,
&input->inhibit_activate);
input->inhibit_deactivate.notify = handle_inhibit_deactivate;
wl_signal_add(&input->inhibit->events.deactivate,
&input->inhibit_deactivate);
input->keyboard_shortcuts_inhibit = input->keyboard_shortcuts_inhibit =
wlr_keyboard_shortcuts_inhibit_v1_create(server->wl_display); wlr_keyboard_shortcuts_inhibit_v1_create(server->wl_display);
input->keyboard_shortcuts_inhibit_new_inhibitor.notify = input->keyboard_shortcuts_inhibit_new_inhibitor.notify =

View File

@ -405,8 +405,7 @@ static void handle_key_event(struct sway_keyboard *keyboard,
char *device_identifier = input_device_get_identifier(wlr_device); char *device_identifier = input_device_get_identifier(wlr_device);
bool exact_identifier = keyboard->wlr->group != NULL; bool exact_identifier = keyboard->wlr->group != NULL;
seat_idle_notify_activity(seat, IDLE_SOURCE_KEYBOARD); seat_idle_notify_activity(seat, IDLE_SOURCE_KEYBOARD);
bool input_inhibited = seat->exclusive_client != NULL || bool locked = server.session_lock.locked;
server.session_lock.locked;
struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor = struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor =
keyboard_shortcuts_inhibitor_get_for_focused_surface(seat); keyboard_shortcuts_inhibitor_get_for_focused_surface(seat);
bool shortcuts_inhibited = sway_inhibitor && sway_inhibitor->inhibitor->active; bool shortcuts_inhibited = sway_inhibitor && sway_inhibitor->inhibitor->active;
@ -424,17 +423,17 @@ static void handle_key_event(struct sway_keyboard *keyboard,
struct sway_binding *binding_released = NULL; struct sway_binding *binding_released = NULL;
get_active_binding(&keyboard->state_keycodes, get_active_binding(&keyboard->state_keycodes,
config->current_mode->keycode_bindings, &binding_released, config->current_mode->keycode_bindings, &binding_released,
keyinfo.code_modifiers, true, input_inhibited, keyinfo.code_modifiers, true, locked,
shortcuts_inhibited, device_identifier, shortcuts_inhibited, device_identifier,
exact_identifier, keyboard->effective_layout); exact_identifier, keyboard->effective_layout);
get_active_binding(&keyboard->state_keysyms_raw, get_active_binding(&keyboard->state_keysyms_raw,
config->current_mode->keysym_bindings, &binding_released, config->current_mode->keysym_bindings, &binding_released,
keyinfo.raw_modifiers, true, input_inhibited, keyinfo.raw_modifiers, true, locked,
shortcuts_inhibited, device_identifier, shortcuts_inhibited, device_identifier,
exact_identifier, keyboard->effective_layout); exact_identifier, keyboard->effective_layout);
get_active_binding(&keyboard->state_keysyms_translated, get_active_binding(&keyboard->state_keysyms_translated,
config->current_mode->keysym_bindings, &binding_released, config->current_mode->keysym_bindings, &binding_released,
keyinfo.translated_modifiers, true, input_inhibited, keyinfo.translated_modifiers, true, locked,
shortcuts_inhibited, device_identifier, shortcuts_inhibited, device_identifier,
exact_identifier, keyboard->effective_layout); exact_identifier, keyboard->effective_layout);
@ -456,17 +455,17 @@ static void handle_key_event(struct sway_keyboard *keyboard,
if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
get_active_binding(&keyboard->state_keycodes, get_active_binding(&keyboard->state_keycodes,
config->current_mode->keycode_bindings, &binding, config->current_mode->keycode_bindings, &binding,
keyinfo.code_modifiers, false, input_inhibited, keyinfo.code_modifiers, false, locked,
shortcuts_inhibited, device_identifier, shortcuts_inhibited, device_identifier,
exact_identifier, keyboard->effective_layout); exact_identifier, keyboard->effective_layout);
get_active_binding(&keyboard->state_keysyms_raw, get_active_binding(&keyboard->state_keysyms_raw,
config->current_mode->keysym_bindings, &binding, config->current_mode->keysym_bindings, &binding,
keyinfo.raw_modifiers, false, input_inhibited, keyinfo.raw_modifiers, false, locked,
shortcuts_inhibited, device_identifier, shortcuts_inhibited, device_identifier,
exact_identifier, keyboard->effective_layout); exact_identifier, keyboard->effective_layout);
get_active_binding(&keyboard->state_keysyms_translated, get_active_binding(&keyboard->state_keysyms_translated,
config->current_mode->keysym_bindings, &binding, config->current_mode->keysym_bindings, &binding,
keyinfo.translated_modifiers, false, input_inhibited, keyinfo.translated_modifiers, false, locked,
shortcuts_inhibited, device_identifier, shortcuts_inhibited, device_identifier,
exact_identifier, keyboard->effective_layout); exact_identifier, keyboard->effective_layout);
} }

View File

@ -803,9 +803,7 @@ static void seat_apply_input_mapping(struct sway_seat *seat,
static void seat_configure_pointer(struct sway_seat *seat, static void seat_configure_pointer(struct sway_seat *seat,
struct sway_seat_device *sway_device) { struct sway_seat_device *sway_device) {
if ((seat->wlr_seat->capabilities & WL_SEAT_CAPABILITY_POINTER) == 0) { seat_configure_xcursor(seat);
seat_configure_xcursor(seat);
}
wlr_cursor_attach_input_device(seat->cursor->cursor, wlr_cursor_attach_input_device(seat->cursor->cursor,
sway_device->input_device->wlr_device); sway_device->input_device->wlr_device);
wl_event_source_timer_update( wl_event_source_timer_update(
@ -1069,44 +1067,44 @@ void seat_configure_xcursor(struct sway_seat *seat) {
sway_log(SWAY_ERROR, sway_log(SWAY_ERROR,
"Cannot create XCursor manager for theme '%s'", cursor_theme); "Cannot create XCursor manager for theme '%s'", cursor_theme);
} }
}
for (int i = 0; i < root->outputs->length; ++i) {
struct sway_output *sway_output = root->outputs->items[i]; for (int i = 0; i < root->outputs->length; ++i) {
struct wlr_output *output = sway_output->wlr_output; struct sway_output *sway_output = root->outputs->items[i];
bool result = struct wlr_output *output = sway_output->wlr_output;
wlr_xcursor_manager_load(seat->cursor->xcursor_manager, bool result =
output->scale); wlr_xcursor_manager_load(seat->cursor->xcursor_manager,
if (!result) { output->scale);
sway_log(SWAY_ERROR, if (!result) {
"Cannot load xcursor theme for output '%s' with scale %f", sway_log(SWAY_ERROR,
output->name, output->scale); "Cannot load xcursor theme for output '%s' with scale %f",
output->name, output->scale);
}
} }
}
// Reset the cursor so that we apply it to outputs that just appeared // Reset the cursor so that we apply it to outputs that just appeared
cursor_set_image(seat->cursor, NULL, NULL); cursor_set_image(seat->cursor, NULL, NULL);
cursor_set_image(seat->cursor, "default", NULL); cursor_set_image(seat->cursor, "default", NULL);
wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x, wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x,
seat->cursor->cursor->y); seat->cursor->cursor->y);
}
} }
bool seat_is_input_allowed(struct sway_seat *seat, bool seat_is_input_allowed(struct sway_seat *seat,
struct wlr_surface *surface) { struct wlr_surface *surface) {
if (server.session_lock.locked) { if (!server.session_lock.locked) {
if (server.session_lock.lock == NULL) { return true;
return false; }
} if (server.session_lock.lock == NULL) {
struct wlr_session_lock_surface_v1 *lock_surf;
wl_list_for_each(lock_surf, &server.session_lock.lock->surfaces, link) {
if (lock_surf->surface == surface) {
return true;
}
}
return false; return false;
} }
struct wl_client *client = wl_resource_get_client(surface->resource); struct wlr_session_lock_surface_v1 *lock_surf;
return seat->exclusive_client == client || seat->exclusive_client == NULL; wl_list_for_each(lock_surf, &server.session_lock.lock->surfaces, link) {
if (lock_surf->surface == surface) {
return true;
}
}
return false;
} }
static void send_unfocus(struct sway_container *con, void *data) { static void send_unfocus(struct sway_container *con, void *data) {
@ -1371,18 +1369,7 @@ void seat_set_focus_layer(struct sway_seat *seat,
seat->focused_layer = layer; seat->focused_layer = layer;
} }
void seat_set_exclusive_client(struct sway_seat *seat, void seat_unfocus_unless_client(struct sway_seat *seat, struct wl_client *client) {
struct wl_client *client) {
if (!client) {
seat->exclusive_client = client;
// Triggers a refocus of the topmost surface layer if necessary
// TODO: Make layer surface focus per-output based on cursor position
for (int i = 0; i < root->outputs->length; ++i) {
struct sway_output *output = root->outputs->items[i];
arrange_layers(output);
}
return;
}
if (seat->focused_layer) { if (seat->focused_layer) {
if (wl_resource_get_client(seat->focused_layer->resource) != client) { if (wl_resource_get_client(seat->focused_layer->resource) != client) {
seat_set_focus_layer(seat, NULL); seat_set_focus_layer(seat, NULL);
@ -1409,7 +1396,6 @@ void seat_set_exclusive_client(struct sway_seat *seat,
now.tv_nsec / 1000, point->touch_id); now.tv_nsec / 1000, point->touch_id);
} }
} }
seat->exclusive_client = client;
} }
struct sway_node *seat_get_focus_inactive(struct sway_seat *seat, struct sway_node *seat_get_focus_inactive(struct sway_seat *seat,

View File

@ -33,9 +33,8 @@ static bool sway_switch_trigger_test(enum sway_switch_trigger trigger,
} }
static void execute_binding(struct sway_switch *sway_switch) { static void execute_binding(struct sway_switch *sway_switch) {
struct sway_seat* seat = sway_switch->seat_device->sway_seat; struct sway_seat *seat = sway_switch->seat_device->sway_seat;
bool input_inhibited = seat->exclusive_client != NULL || bool locked = server.session_lock.locked;
server.session_lock.locked;
list_t *bindings = config->current_mode->switch_bindings; list_t *bindings = config->current_mode->switch_bindings;
struct sway_switch_binding *matched_binding = NULL; struct sway_switch_binding *matched_binding = NULL;
@ -52,13 +51,13 @@ static void execute_binding(struct sway_switch *sway_switch) {
continue; continue;
} }
bool binding_locked = binding->flags & BINDING_LOCKED; bool binding_locked = binding->flags & BINDING_LOCKED;
if (!binding_locked && input_inhibited) { if (!binding_locked && locked) {
continue; continue;
} }
matched_binding = binding; matched_binding = binding;
if (binding_locked == input_inhibited) { if (binding_locked == locked) {
break; break;
} }
} }

View File

@ -58,9 +58,7 @@ void sway_configure_tablet(struct sway_tablet *tablet) {
tablet->seat_device->input_device->wlr_device; tablet->seat_device->input_device->wlr_device;
struct sway_seat *seat = tablet->seat_device->sway_seat; struct sway_seat *seat = tablet->seat_device->sway_seat;
if ((seat->wlr_seat->capabilities & WL_SEAT_CAPABILITY_POINTER) == 0) { seat_configure_xcursor(seat);
seat_configure_xcursor(seat);
}
if (!tablet->tablet_v2) { if (!tablet->tablet_v2) {
tablet->tablet_v2 = tablet->tablet_v2 =

View File

@ -4,6 +4,7 @@
#include "sway/input/cursor.h" #include "sway/input/cursor.h"
#include "sway/input/keyboard.h" #include "sway/input/keyboard.h"
#include "sway/input/seat.h" #include "sway/input/seat.h"
#include "sway/layers.h"
#include "sway/output.h" #include "sway/output.h"
#include "sway/server.h" #include "sway/server.h"
#include "sway/surface.h" #include "sway/surface.h"
@ -129,7 +130,6 @@ static void handle_unlock(struct wl_listener *listener, void *data) {
struct sway_seat *seat; struct sway_seat *seat;
wl_list_for_each(seat, &server.input->seats, link) { wl_list_for_each(seat, &server.input->seats, link) {
seat_set_exclusive_client(seat, NULL);
// copied from seat_set_focus_layer -- deduplicate? // copied from seat_set_focus_layer -- deduplicate?
struct sway_node *previous = seat_get_focus_inactive(seat, &root->node); struct sway_node *previous = seat_get_focus_inactive(seat, &root->node);
if (previous) { if (previous) {
@ -139,6 +139,13 @@ static void handle_unlock(struct wl_listener *listener, void *data) {
} }
} }
// Triggers a refocus of the topmost surface layer if necessary
// TODO: Make layer surface focus per-output based on cursor position
for (int i = 0; i < root->outputs->length; ++i) {
struct sway_output *output = root->outputs->items[i];
arrange_layers(output);
}
// redraw everything // redraw everything
for (int i = 0; i < root->outputs->length; ++i) { for (int i = 0; i < root->outputs->length; ++i) {
struct sway_output *output = root->outputs->items[i]; struct sway_output *output = root->outputs->items[i];
@ -155,11 +162,6 @@ static void handle_abandon(struct wl_listener *listener, void *data) {
wl_list_remove(&server.session_lock.lock_unlock.link); wl_list_remove(&server.session_lock.lock_unlock.link);
wl_list_remove(&server.session_lock.lock_destroy.link); wl_list_remove(&server.session_lock.lock_destroy.link);
struct sway_seat *seat;
wl_list_for_each(seat, &server.input->seats, link) {
seat->exclusive_client = NULL;
}
// redraw everything // redraw everything
for (int i = 0; i < root->outputs->length; ++i) { for (int i = 0; i < root->outputs->length; ++i) {
struct sway_output *output = root->outputs->items[i]; struct sway_output *output = root->outputs->items[i];
@ -182,7 +184,7 @@ static void handle_session_lock(struct wl_listener *listener, void *data) {
struct sway_seat *seat; struct sway_seat *seat;
wl_list_for_each(seat, &server.input->seats, link) { wl_list_for_each(seat, &server.input->seats, link) {
seat_set_exclusive_client(seat, client); seat_unfocus_unless_client(seat, client);
} }
wl_signal_add(&lock->events.new_surface, &server.session_lock.lock_new_surface); wl_signal_add(&lock->events.new_surface, &server.session_lock.lock_new_surface);

View File

@ -49,44 +49,6 @@ void sig_handler(int signal) {
sway_terminate(EXIT_SUCCESS); sway_terminate(EXIT_SUCCESS);
} }
void detect_proprietary(int allow_unsupported_gpu) {
FILE *f = fopen("/proc/modules", "r");
if (!f) {
return;
}
char *line = NULL;
size_t line_size = 0;
while (getline(&line, &line_size, f) != -1) {
if (strncmp(line, "nvidia ", 7) == 0) {
if (allow_unsupported_gpu) {
sway_log(SWAY_ERROR,
"!!! Proprietary Nvidia drivers are in use !!!");
} else {
sway_log(SWAY_ERROR,
"Proprietary Nvidia drivers are NOT supported. "
"Use Nouveau. To launch sway anyway, launch with "
"--unsupported-gpu and DO NOT report issues.");
exit(EXIT_FAILURE);
}
break;
}
if (strstr(line, "fglrx")) {
if (allow_unsupported_gpu) {
sway_log(SWAY_ERROR,
"!!! Proprietary AMD drivers are in use !!!");
} else {
sway_log(SWAY_ERROR, "Proprietary AMD drivers do NOT support "
"Wayland. Use radeon. To try anyway, launch sway with "
"--unsupported-gpu and DO NOT report issues.");
exit(EXIT_FAILURE);
}
break;
}
}
free(line);
fclose(f);
}
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);
@ -255,7 +217,7 @@ static const char usage[] =
"\n"; "\n";
int main(int argc, char **argv) { int main(int argc, char **argv) {
static bool verbose = false, debug = false, validate = false, allow_unsupported_gpu = false; static bool verbose = false, debug = false, validate = false;
char *config_path = NULL; char *config_path = NULL;
@ -363,7 +325,6 @@ int main(int argc, char **argv) {
return 0; return 0;
} }
detect_proprietary(allow_unsupported_gpu);
increase_nofile_limit(); increase_nofile_limit();
// handle SIGTERM signals // handle SIGTERM signals
@ -375,8 +336,6 @@ int main(int argc, char **argv) {
sway_log(SWAY_INFO, "Starting sway version " SWAY_VERSION); sway_log(SWAY_INFO, "Starting sway version " SWAY_VERSION);
root = root_create();
if (!server_init(&server)) { if (!server_init(&server)) {
return 1; return 1;
} }

View File

@ -24,8 +24,9 @@
#include <wlr/types/wlr_primary_selection_v1.h> #include <wlr/types/wlr_primary_selection_v1.h>
#include <wlr/types/wlr_relative_pointer_v1.h> #include <wlr/types/wlr_relative_pointer_v1.h>
#include <wlr/types/wlr_screencopy_v1.h> #include <wlr/types/wlr_screencopy_v1.h>
#include <wlr/types/wlr_single_pixel_buffer_v1.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_single_pixel_buffer_v1.h>
#include <wlr/types/wlr_subcompositor.h> #include <wlr/types/wlr_subcompositor.h>
#include <wlr/types/wlr_tablet_v2.h> #include <wlr/types/wlr_tablet_v2.h>
#include <wlr/types/wlr_viewporter.h> #include <wlr/types/wlr_viewporter.h>
@ -36,6 +37,7 @@
#include <wlr/types/wlr_xdg_foreign_v1.h> #include <wlr/types/wlr_xdg_foreign_v1.h>
#include <wlr/types/wlr_xdg_foreign_v2.h> #include <wlr/types/wlr_xdg_foreign_v2.h>
#include <wlr/types/wlr_xdg_output_v1.h> #include <wlr/types/wlr_xdg_output_v1.h>
#include <xf86drm.h>
#include "config.h" #include "config.h"
#include "list.h" #include "list.h"
#include "log.h" #include "log.h"
@ -59,6 +61,8 @@
#define SWAY_XDG_SHELL_VERSION 2 #define SWAY_XDG_SHELL_VERSION 2
#define SWAY_LAYER_SHELL_VERSION 4 #define SWAY_LAYER_SHELL_VERSION 4
bool allow_unsupported_gpu = false;
#if WLR_HAS_DRM_BACKEND #if WLR_HAS_DRM_BACKEND
static void handle_drm_lease_request(struct wl_listener *listener, void *data) { static void handle_drm_lease_request(struct wl_listener *listener, void *data) {
/* We only offer non-desktop outputs, but in the future we might want to do /* We only offer non-desktop outputs, but in the future we might want to do
@ -73,6 +77,24 @@ static void handle_drm_lease_request(struct wl_listener *listener, void *data) {
} }
#endif #endif
static bool is_privileged(const struct wl_global *global) {
return
global == server.output_manager_v1->global ||
global == server.output_power_manager_v1->global ||
global == server.input_method->global ||
global == server.foreign_toplevel_manager->global ||
global == server.data_control_manager_v1->global ||
global == server.screencopy_manager_v1->global ||
global == server.export_dmabuf_manager_v1->global ||
global == server.security_context_manager_v1->global ||
global == server.gamma_control_manager_v1->global ||
global == server.layer_shell->global ||
global == server.session_lock.manager->global ||
global == server.input->keyboard_shortcuts_inhibit->global ||
global == server.input->virtual_keyboard->global ||
global == server.input->virtual_pointer->global;
}
static bool filter_global(const struct wl_client *client, static bool filter_global(const struct wl_client *client,
const struct wl_global *global, void *data) { const struct wl_global *global, void *data) {
#if HAVE_XWAYLAND #if HAVE_XWAYLAND
@ -82,9 +104,54 @@ static bool filter_global(const struct wl_client *client,
} }
#endif #endif
// Restrict usage of privileged protocols to unsandboxed clients
// TODO: add a way for users to configure an allow-list
const struct wlr_security_context_v1_state *security_context =
wlr_security_context_manager_v1_lookup_client(
server.security_context_manager_v1, (struct wl_client *)client);
if (is_privileged(global)) {
return security_context == NULL;
}
return true; return true;
} }
static void detect_proprietary(struct wlr_backend *backend, void *data) {
int drm_fd = wlr_backend_get_drm_fd(backend);
if (drm_fd < 0) {
return;
}
drmVersion *version = drmGetVersion(drm_fd);
if (version == NULL) {
sway_log(SWAY_ERROR, "drmGetVersion() failed");
return;
}
bool is_unsupported = false;
if (strcmp(version->name, "nvidia-drm") == 0) {
is_unsupported = true;
sway_log(SWAY_ERROR, "!!! Proprietary Nvidia drivers are in use !!!");
if (!allow_unsupported_gpu) {
sway_log(SWAY_ERROR, "Use Nouveau instead");
}
}
if (strcmp(version->name, "evdi") == 0) {
is_unsupported = true;
sway_log(SWAY_ERROR, "!!! Proprietary DisplayLink drivers are in use !!!");
}
if (!allow_unsupported_gpu && is_unsupported) {
sway_log(SWAY_ERROR,
"Proprietary drivers are NOT supported. To launch sway anyway, "
"launch with --unsupported-gpu and DO NOT report issues.");
exit(EXIT_FAILURE);
}
drmFreeVersion(version);
}
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();
@ -92,12 +159,16 @@ bool server_init(struct sway_server *server) {
wl_display_set_global_filter(server->wl_display, filter_global, NULL); wl_display_set_global_filter(server->wl_display, filter_global, NULL);
root = root_create(server->wl_display);
server->backend = wlr_backend_autocreate(server->wl_display, &server->session); server->backend = wlr_backend_autocreate(server->wl_display, &server->session);
if (!server->backend) { if (!server->backend) {
sway_log(SWAY_ERROR, "Unable to create backend"); sway_log(SWAY_ERROR, "Unable to create backend");
return false; return false;
} }
wlr_multi_for_each_backend(server->backend, detect_proprietary, NULL);
server->renderer = wlr_renderer_autocreate(server->backend); server->renderer = wlr_renderer_autocreate(server->backend);
if (!server->renderer) { if (!server->renderer) {
sway_log(SWAY_ERROR, "Failed to create renderer"); sway_log(SWAY_ERROR, "Failed to create renderer");
@ -155,9 +226,9 @@ bool server_init(struct sway_server *server) {
server->xdg_shell = wlr_xdg_shell_create(server->wl_display, server->xdg_shell = wlr_xdg_shell_create(server->wl_display,
SWAY_XDG_SHELL_VERSION); SWAY_XDG_SHELL_VERSION);
wl_signal_add(&server->xdg_shell->events.new_surface, wl_signal_add(&server->xdg_shell->events.new_toplevel,
&server->xdg_shell_surface); &server->xdg_shell_toplevel);
server->xdg_shell_surface.notify = handle_xdg_shell_surface; server->xdg_shell_toplevel.notify = handle_xdg_shell_toplevel;
server->tablet_v2 = wlr_tablet_v2_create(server->wl_display); server->tablet_v2 = wlr_tablet_v2_create(server->wl_display);
@ -226,9 +297,10 @@ bool server_init(struct sway_server *server) {
} }
#endif #endif
wlr_export_dmabuf_manager_v1_create(server->wl_display); server->export_dmabuf_manager_v1 = wlr_export_dmabuf_manager_v1_create(server->wl_display);
wlr_screencopy_manager_v1_create(server->wl_display); server->screencopy_manager_v1 = wlr_screencopy_manager_v1_create(server->wl_display);
wlr_data_control_manager_v1_create(server->wl_display); server->data_control_manager_v1 = wlr_data_control_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);
server->content_type_manager_v1 = server->content_type_manager_v1 =

View File

@ -649,7 +649,8 @@ The default colors are:
*default_border* normal|none|pixel [<n>] *default_border* normal|none|pixel [<n>]
Set default border style for new tiled windows. Set default border style for new tiled windows. Config reload won't affect
existing windows, only newly created ones after the reload.
*default_floating_border* normal|none|pixel [<n>] *default_floating_border* normal|none|pixel [<n>]
Set default border style for new floating windows. This only applies to Set default border style for new floating windows. This only applies to

View File

@ -3,6 +3,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <wlr/types/wlr_output_layout.h> #include <wlr/types/wlr_output_layout.h>
#include <wlr/util/transform.h>
#include "sway/desktop/transaction.h" #include "sway/desktop/transaction.h"
#include "sway/input/seat.h" #include "sway/input/seat.h"
#include "sway/ipc-server.h" #include "sway/ipc-server.h"
@ -23,14 +24,14 @@ static void output_layout_handle_change(struct wl_listener *listener,
transaction_commit_dirty(); transaction_commit_dirty();
} }
struct sway_root *root_create(void) { struct sway_root *root_create(struct wl_display *wl_display) {
struct sway_root *root = calloc(1, sizeof(struct sway_root)); struct sway_root *root = calloc(1, sizeof(struct sway_root));
if (!root) { if (!root) {
sway_log(SWAY_ERROR, "Unable to allocate sway_root"); sway_log(SWAY_ERROR, "Unable to allocate sway_root");
return NULL; return NULL;
} }
node_init(&root->node, N_ROOT, root); node_init(&root->node, N_ROOT, root);
root->output_layout = wlr_output_layout_create(); root->output_layout = wlr_output_layout_create(wl_display);
wl_list_init(&root->all_outputs); wl_list_init(&root->all_outputs);
#if HAVE_XWAYLAND #if HAVE_XWAYLAND
wl_list_init(&root->xwayland_unmanaged); wl_list_init(&root->xwayland_unmanaged);
@ -52,7 +53,6 @@ void root_destroy(struct sway_root *root) {
list_free(root->scratchpad); list_free(root->scratchpad);
list_free(root->non_desktop_outputs); list_free(root->non_desktop_outputs);
list_free(root->outputs); list_free(root->outputs);
wlr_output_layout_destroy(root->output_layout);
free(root); free(root);
} }

View File

@ -882,6 +882,8 @@ void view_unmap(struct sway_view *view) {
wl_list_remove(&view->surface_new_subsurface.link); wl_list_remove(&view->surface_new_subsurface.link);
view->executed_criteria->length = 0;
if (view->urgent_timer) { if (view->urgent_timer) {
wl_event_source_remove(view->urgent_timer); wl_event_source_remove(view->urgent_timer);
view->urgent_timer = NULL; view->urgent_timer = NULL;

View File

@ -23,6 +23,45 @@ static void xdg_decoration_handle_request_mode(struct wl_listener *listener,
void *data) { void *data) {
struct sway_xdg_decoration *deco = struct sway_xdg_decoration *deco =
wl_container_of(listener, deco, request_mode); wl_container_of(listener, deco, request_mode);
set_xdg_decoration_mode(deco);
}
void handle_xdg_decoration(struct wl_listener *listener, void *data) {
struct wlr_xdg_toplevel_decoration_v1 *wlr_deco = data;
struct sway_xdg_shell_view *xdg_shell_view = wlr_deco->toplevel->base->data;
struct sway_xdg_decoration *deco = calloc(1, sizeof(*deco));
if (deco == NULL) {
return;
}
deco->view = &xdg_shell_view->view;
deco->view->xdg_decoration = deco;
deco->wlr_xdg_decoration = wlr_deco;
wl_signal_add(&wlr_deco->events.destroy, &deco->destroy);
deco->destroy.notify = xdg_decoration_handle_destroy;
wl_signal_add(&wlr_deco->events.request_mode, &deco->request_mode);
deco->request_mode.notify = xdg_decoration_handle_request_mode;
wl_list_insert(&server.xdg_decorations, &deco->link);
set_xdg_decoration_mode(deco);
}
struct sway_xdg_decoration *xdg_decoration_from_surface(
struct wlr_surface *surface) {
struct sway_xdg_decoration *deco;
wl_list_for_each(deco, &server.xdg_decorations, link) {
if (deco->wlr_xdg_decoration->toplevel->base->surface == surface) {
return deco;
}
}
return NULL;
}
void set_xdg_decoration_mode(struct sway_xdg_decoration *deco) {
struct sway_view *view = deco->view; struct sway_view *view = deco->view;
enum wlr_xdg_toplevel_decoration_v1_mode mode = enum wlr_xdg_toplevel_decoration_v1_mode mode =
WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE; WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE;
@ -47,41 +86,7 @@ static void xdg_decoration_handle_request_mode(struct wl_listener *listener,
mode = client_mode; mode = client_mode;
} }
wlr_xdg_toplevel_decoration_v1_set_mode(deco->wlr_xdg_decoration, if (view->wlr_xdg_toplevel->base->initialized) {
mode); wlr_xdg_toplevel_decoration_v1_set_mode(deco->wlr_xdg_decoration, mode);
}
void handle_xdg_decoration(struct wl_listener *listener, void *data) {
struct wlr_xdg_toplevel_decoration_v1 *wlr_deco = data;
struct sway_xdg_shell_view *xdg_shell_view = wlr_deco->toplevel->base->data;
struct sway_xdg_decoration *deco = calloc(1, sizeof(*deco));
if (deco == NULL) {
return;
} }
deco->view = &xdg_shell_view->view;
deco->view->xdg_decoration = deco;
deco->wlr_xdg_decoration = wlr_deco;
wl_signal_add(&wlr_deco->events.destroy, &deco->destroy);
deco->destroy.notify = xdg_decoration_handle_destroy;
wl_signal_add(&wlr_deco->events.request_mode, &deco->request_mode);
deco->request_mode.notify = xdg_decoration_handle_request_mode;
wl_list_insert(&server.xdg_decorations, &deco->link);
xdg_decoration_handle_request_mode(&deco->request_mode, wlr_deco);
}
struct sway_xdg_decoration *xdg_decoration_from_surface(
struct wlr_surface *surface) {
struct sway_xdg_decoration *deco;
wl_list_for_each(deco, &server.xdg_decorations, link) {
if (deco->wlr_xdg_decoration->toplevel->base->surface == surface) {
return deco;
}
}
return NULL;
} }

View File

@ -1,29 +1,12 @@
#include <assert.h> #include <assert.h>
#include "background-image.h" #include "config.h"
#include "cairo_util.h"
#include "log.h" #include "log.h"
#include "swaybar/image.h"
#if HAVE_GDK_PIXBUF #if HAVE_GDK_PIXBUF
#include <gdk-pixbuf/gdk-pixbuf.h> #include <gdk-pixbuf/gdk-pixbuf.h>
#endif #endif
enum background_mode parse_background_mode(const char *mode) {
if (strcmp(mode, "stretch") == 0) {
return BACKGROUND_MODE_STRETCH;
} else if (strcmp(mode, "fill") == 0) {
return BACKGROUND_MODE_FILL;
} else if (strcmp(mode, "fit") == 0) {
return BACKGROUND_MODE_FIT;
} else if (strcmp(mode, "center") == 0) {
return BACKGROUND_MODE_CENTER;
} else if (strcmp(mode, "tile") == 0) {
return BACKGROUND_MODE_TILE;
} else if (strcmp(mode, "solid_color") == 0) {
return BACKGROUND_MODE_SOLID_COLOR;
}
sway_log(SWAY_ERROR, "Unsupported background mode: %s", mode);
return BACKGROUND_MODE_INVALID;
}
#if HAVE_GDK_PIXBUF #if HAVE_GDK_PIXBUF
static cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf( static cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf(
const GdkPixbuf *gdkbuf) { const GdkPixbuf *gdkbuf) {
@ -121,7 +104,7 @@ static cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf(
} }
#endif // HAVE_GDK_PIXBUF #endif // HAVE_GDK_PIXBUF
cairo_surface_t *load_background_image(const char *path) { cairo_surface_t *load_image(const char *path) {
cairo_surface_t *image; cairo_surface_t *image;
#if HAVE_GDK_PIXBUF #if HAVE_GDK_PIXBUF
GError *err = NULL; GError *err = NULL;
@ -151,70 +134,3 @@ cairo_surface_t *load_background_image(const char *path) {
} }
return image; return image;
} }
void render_background_image(cairo_t *cairo, cairo_surface_t *image,
enum background_mode mode, int buffer_width, int buffer_height) {
double width = cairo_image_surface_get_width(image);
double height = cairo_image_surface_get_height(image);
cairo_save(cairo);
switch (mode) {
case BACKGROUND_MODE_STRETCH:
cairo_scale(cairo,
(double)buffer_width / width,
(double)buffer_height / height);
cairo_set_source_surface(cairo, image, 0, 0);
break;
case BACKGROUND_MODE_FILL: {
double window_ratio = (double)buffer_width / buffer_height;
double bg_ratio = width / height;
if (window_ratio > bg_ratio) {
double scale = (double)buffer_width / width;
cairo_scale(cairo, scale, scale);
cairo_set_source_surface(cairo, image,
0, (double)buffer_height / 2 / scale - height / 2);
} else {
double scale = (double)buffer_height / height;
cairo_scale(cairo, scale, scale);
cairo_set_source_surface(cairo, image,
(double)buffer_width / 2 / scale - width / 2, 0);
}
break;
}
case BACKGROUND_MODE_FIT: {
double window_ratio = (double)buffer_width / buffer_height;
double bg_ratio = width / height;
if (window_ratio > bg_ratio) {
double scale = (double)buffer_height / height;
cairo_scale(cairo, scale, scale);
cairo_set_source_surface(cairo, image,
(double)buffer_width / 2 / scale - width / 2, 0);
} else {
double scale = (double)buffer_width / width;
cairo_scale(cairo, scale, scale);
cairo_set_source_surface(cairo, image,
0, (double)buffer_height / 2 / scale - height / 2);
}
break;
}
case BACKGROUND_MODE_CENTER:
cairo_set_source_surface(cairo, image,
(double)buffer_width / 2 - width / 2,
(double)buffer_height / 2 - height / 2);
break;
case BACKGROUND_MODE_TILE: {
cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image);
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
cairo_set_source(cairo, pattern);
break;
}
case BACKGROUND_MODE_SOLID_COLOR:
case BACKGROUND_MODE_INVALID:
assert(0);
break;
}
cairo_paint(cairo);
cairo_restore(cairo);
}

View File

@ -26,6 +26,7 @@ executable(
'bar.c', 'bar.c',
'config.c', 'config.c',
'i3bar.c', 'i3bar.c',
'image.c',
'input.c', 'input.c',
'ipc.c', 'ipc.c',
'main.c', 'main.c',

View File

@ -7,12 +7,12 @@
#include <string.h> #include <string.h>
#include "swaybar/bar.h" #include "swaybar/bar.h"
#include "swaybar/config.h" #include "swaybar/config.h"
#include "swaybar/image.h"
#include "swaybar/input.h" #include "swaybar/input.h"
#include "swaybar/tray/host.h" #include "swaybar/tray/host.h"
#include "swaybar/tray/icon.h" #include "swaybar/tray/icon.h"
#include "swaybar/tray/item.h" #include "swaybar/tray/item.h"
#include "swaybar/tray/tray.h" #include "swaybar/tray/tray.h"
#include "background-image.h"
#include "cairo_util.h" #include "cairo_util.h"
#include "list.h" #include "list.h"
#include "log.h" #include "log.h"
@ -431,7 +431,7 @@ static void reload_sni(struct swaybar_sni *sni, char *icon_theme,
list_free(icon_search_paths); list_free(icon_search_paths);
if (icon_path) { if (icon_path) {
cairo_surface_destroy(sni->icon); cairo_surface_destroy(sni->icon);
sni->icon = load_background_image(icon_path); sni->icon = load_image(icon_path);
free(icon_path); free(icon_path);
return; return;
} }