mirror of
https://github.com/swaywm/sway.git
synced 2024-11-14 14:34:07 +01:00
Merge branch 'master' of https://github.com/swaywm/sway
This commit is contained in:
commit
eb2dbe26f1
12
README.de.md
12
README.de.md
@ -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_
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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
|
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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
7
include/swaybar/image.h
Normal 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
|
@ -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')
|
||||||
|
@ -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',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -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>
|
|
@ -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);
|
||||||
|
@ -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"
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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"
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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 =
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 =
|
||||||
|
16
sway/lock.c
16
sway/lock.c
@ -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);
|
||||||
|
43
sway/main.c
43
sway/main.c
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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 =
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
|
||||||
}
|
|
@ -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',
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user