mirror of
https://github.com/swaywm/sway.git
synced 2024-11-14 06:24:20 +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).
|
||||
|
||||
## 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
|
||||
### 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
|
||||
|
||||
@ -23,8 +23,8 @@ sway benötigt die folgenden Pakete:
|
||||
* pango
|
||||
* cairo
|
||||
* 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)
|
||||
* git\*
|
||||
* [scdoc](https://git.sr.ht/~sircmpwn/scdoc) (Optional, wird für die Dokumentation (Man Pages) benötigt)\*
|
||||
* git (Optional: Versionsinfo)\*
|
||||
|
||||
_\*Werden nur während des Kompilierens benötigt_
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
lib_sway_common = static_library(
|
||||
'sway-common',
|
||||
files(
|
||||
'background-image.c',
|
||||
'cairo.c',
|
||||
'gesture.c',
|
||||
'ipc-client.c',
|
||||
@ -14,7 +13,6 @@ lib_sway_common = static_library(
|
||||
),
|
||||
dependencies: [
|
||||
cairo,
|
||||
gdk_pixbuf,
|
||||
pango,
|
||||
pangocairo,
|
||||
wayland_client.partial_dependency(compile_args: true)
|
||||
|
@ -205,7 +205,7 @@ bar {
|
||||
|
||||
# When the status_command prints a new line to stdout, swaybar updates.
|
||||
# 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 {
|
||||
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
|
||||
#define _SWAY_INPUT_INPUT_MANAGER_H
|
||||
#include <libinput.h>
|
||||
#include <wlr/types/wlr_input_inhibitor.h>
|
||||
#include <wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h>
|
||||
#include <wlr/types/wlr_virtual_keyboard_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 seats;
|
||||
|
||||
struct wlr_input_inhibit_manager *inhibit;
|
||||
struct wlr_keyboard_shortcuts_inhibit_manager_v1 *keyboard_shortcuts_inhibit;
|
||||
struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard;
|
||||
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
|
||||
bool has_exclusive_layer;
|
||||
|
||||
// If exclusive_client is set, no other clients will receive input events
|
||||
struct wl_client *exclusive_client;
|
||||
|
||||
// Last touch point
|
||||
int32_t touch_id;
|
||||
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,
|
||||
struct wlr_layer_surface_v1 *layer);
|
||||
|
||||
void seat_set_exclusive_client(struct sway_seat *seat,
|
||||
struct wl_client *client);
|
||||
void seat_unfocus_unless_client(struct sway_seat *seat, struct wl_client *client);
|
||||
|
||||
struct sway_node *seat_get_focus(struct sway_seat *seat);
|
||||
|
||||
|
@ -39,6 +39,7 @@ struct sway_output {
|
||||
|
||||
struct sway_output_state current;
|
||||
|
||||
struct wl_listener layout_destroy;
|
||||
struct wl_listener destroy;
|
||||
struct wl_listener commit;
|
||||
struct wl_listener present;
|
||||
|
@ -59,7 +59,7 @@ struct sway_server {
|
||||
struct wl_listener layer_shell_surface;
|
||||
|
||||
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;
|
||||
|
||||
@ -114,6 +114,10 @@ struct sway_server {
|
||||
struct wlr_text_input_manager_v3 *text_input;
|
||||
struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_manager;
|
||||
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 wl_listener xdg_activation_v1_request_activate;
|
||||
@ -159,6 +163,8 @@ struct sway_debug {
|
||||
|
||||
extern struct sway_debug debug;
|
||||
|
||||
extern bool allow_unsupported_gpu;
|
||||
|
||||
bool server_init(struct sway_server *server);
|
||||
void server_fini(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_layer_shell_surface(struct wl_listener *listener, void *data);
|
||||
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
|
||||
void handle_xwayland_surface(struct wl_listener *listener, void *data);
|
||||
#endif
|
||||
|
@ -41,7 +41,7 @@ struct sway_root {
|
||||
} events;
|
||||
};
|
||||
|
||||
struct sway_root *root_create(void);
|
||||
struct sway_root *root_create(struct wl_display *display);
|
||||
|
||||
void root_destroy(struct sway_root *root);
|
||||
|
||||
|
@ -226,6 +226,7 @@ struct sway_xdg_popup {
|
||||
|
||||
struct wlr_xdg_popup *wlr_xdg_popup;
|
||||
|
||||
struct wl_listener surface_commit;
|
||||
struct wl_listener new_popup;
|
||||
struct wl_listener destroy;
|
||||
};
|
||||
|
@ -16,4 +16,6 @@ struct sway_xdg_decoration {
|
||||
struct sway_xdg_decoration *xdg_decoration_from_surface(
|
||||
struct wlr_surface *surface);
|
||||
|
||||
void set_xdg_decoration_mode(struct sway_xdg_decoration *deco);
|
||||
|
||||
#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
|
||||
|
||||
# Execute the wlroots subproject, if any
|
||||
wlroots_version = ['>=0.17.0', '<0.18.0']
|
||||
wlroots_version = ['>=0.18.0', '<0.19.0']
|
||||
subproject(
|
||||
'wlroots',
|
||||
default_options: ['examples=false'],
|
||||
@ -77,8 +77,7 @@ pixman = dependency('pixman-1')
|
||||
libevdev = dependency('libevdev')
|
||||
libinput = wlroots_features['libinput_backend'] ? dependency('libinput', version: '>=1.21.0') : null_dep
|
||||
xcb = dependency('xcb', required: get_option('xwayland'))
|
||||
drm_full = dependency('libdrm') # only needed for drm_fourcc.h
|
||||
drm = drm_full.partial_dependency(compile_args: true, includes: true)
|
||||
drm = dependency('libdrm')
|
||||
libudev = wlroots_features['libinput_backend'] ? dependency('libudev') : null_dep
|
||||
math = cc.find_library('m')
|
||||
rt = cc.find_library('rt')
|
||||
|
@ -16,7 +16,6 @@ protocols = [
|
||||
wl_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml',
|
||||
'wlr-layer-shell-unstable-v1.xml',
|
||||
'idle.xml',
|
||||
'wlr-input-inhibitor-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);
|
||||
config_add_swaynag_warning("Unable to access background file '%s'",
|
||||
src);
|
||||
struct cmd_results *result = cmd_results_new(CMD_FAILURE,
|
||||
"unable to access background file '%s'", src);
|
||||
free(src);
|
||||
return result;
|
||||
} else {
|
||||
output->background = src;
|
||||
output->background_option = strdup(mode);
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <string.h>
|
||||
#include <wlr/util/transform.h>
|
||||
#include "sway/commands.h"
|
||||
#include "sway/config.h"
|
||||
#include "log.h"
|
||||
|
@ -975,7 +975,7 @@ char *do_var_replacement(char *str) {
|
||||
int offset = find - str;
|
||||
strncpy(newptr, str, offset);
|
||||
newptr += offset;
|
||||
strncpy(newptr, var->value, vvlen);
|
||||
memcpy(newptr, var->value, vvlen);
|
||||
newptr += vvlen;
|
||||
strcpy(newptr, find + vnlen);
|
||||
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 wl_client *client =
|
||||
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 =
|
||||
find_mapped_layer_by_client(client, sway_layer->layer_surface->output);
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
struct sway_layer_surface *layer = popup_get_layer(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);
|
||||
}
|
||||
|
||||
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 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;
|
||||
wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup);
|
||||
|
||||
popup_unconstrain(popup);
|
||||
|
||||
return popup;
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <wlr/types/wlr_presentation_time.h>
|
||||
#include <wlr/types/wlr_compositor.h>
|
||||
#include <wlr/util/region.h>
|
||||
#include <wlr/util/transform.h>
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
#include "sway/config.h"
|
||||
@ -891,8 +892,7 @@ static void update_output_manager_config(struct sway_server *server) {
|
||||
ipc_event_output();
|
||||
}
|
||||
|
||||
static void handle_destroy(struct wl_listener *listener, void *data) {
|
||||
struct sway_output *output = wl_container_of(listener, output, destroy);
|
||||
static void begin_destroy(struct sway_output *output) {
|
||||
struct sway_server *server = output->server;
|
||||
|
||||
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->layout_destroy.link);
|
||||
wl_list_remove(&output->destroy.link);
|
||||
wl_list_remove(&output->commit.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);
|
||||
}
|
||||
|
||||
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) {
|
||||
container_update_title_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_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) {
|
||||
@ -1030,6 +1046,8 @@ void handle_new_output(struct wl_listener *listener, void *data) {
|
||||
output->server = server;
|
||||
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);
|
||||
output->destroy.notify = handle_destroy;
|
||||
wl_signal_add(&wlr_output->events.commit, &output->commit);
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <wlr/types/wlr_output.h>
|
||||
#include <wlr/types/wlr_compositor.h>
|
||||
#include <wlr/util/region.h>
|
||||
#include <wlr/util/transform.h>
|
||||
#include "log.h"
|
||||
#include "config.h"
|
||||
#include "sway/config.h"
|
||||
|
@ -38,6 +38,7 @@ static void popup_destroy(struct sway_view_child *child) {
|
||||
return;
|
||||
}
|
||||
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->destroy.link);
|
||||
free(popup);
|
||||
@ -51,18 +52,6 @@ static const struct sway_view_child_impl popup_impl = {
|
||||
static struct sway_xdg_popup *popup_create(
|
||||
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) {
|
||||
struct sway_view *view = popup->child.view;
|
||||
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);
|
||||
}
|
||||
|
||||
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(
|
||||
struct wlr_xdg_popup *wlr_popup, struct sway_view *view) {
|
||||
struct wlr_xdg_surface *xdg_surface = wlr_popup->base;
|
||||
@ -97,22 +105,21 @@ static struct sway_xdg_popup *popup_create(
|
||||
return NULL;
|
||||
}
|
||||
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);
|
||||
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;
|
||||
|
||||
wl_signal_add(&xdg_surface->surface->events.map, &popup->child.surface_map);
|
||||
wl_signal_add(&xdg_surface->surface->events.unmap, &popup->child.surface_unmap);
|
||||
|
||||
popup_unconstrain(popup);
|
||||
|
||||
return popup;
|
||||
}
|
||||
|
||||
|
||||
static struct sway_xdg_shell_view *xdg_shell_view_from_view(
|
||||
struct sway_view *view) {
|
||||
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 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;
|
||||
wlr_xdg_surface_get_geometry(xdg_surface, &new_geo);
|
||||
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);
|
||||
|
||||
wl_list_remove(&xdg_shell_view->commit.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_fullscreen.link);
|
||||
@ -464,10 +483,6 @@ static void handle_map(struct wl_listener *listener, void *data) {
|
||||
|
||||
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;
|
||||
wl_signal_add(&toplevel->base->events.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->map.link);
|
||||
wl_list_remove(&xdg_shell_view->unmap.link);
|
||||
wl_list_remove(&xdg_shell_view->commit.link);
|
||||
view->wlr_xdg_toplevel = NULL;
|
||||
if (view->xdg_decoration) {
|
||||
view->xdg_decoration->view = NULL;
|
||||
@ -519,17 +535,12 @@ struct sway_view *view_from_wlr_xdg_surface(
|
||||
return xdg_surface->data;
|
||||
}
|
||||
|
||||
void handle_xdg_shell_surface(struct wl_listener *listener, void *data) {
|
||||
struct wlr_xdg_surface *xdg_surface = data;
|
||||
|
||||
if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) {
|
||||
sway_log(SWAY_DEBUG, "New xdg_shell popup");
|
||||
return;
|
||||
}
|
||||
void handle_xdg_shell_toplevel(struct wl_listener *listener, void *data) {
|
||||
struct wlr_xdg_toplevel *xdg_toplevel = data;
|
||||
|
||||
sway_log(SWAY_DEBUG, "New xdg_shell toplevel title='%s' app_id='%s'",
|
||||
xdg_surface->toplevel->title, xdg_surface->toplevel->app_id);
|
||||
wlr_xdg_surface_ping(xdg_surface);
|
||||
xdg_toplevel->title, xdg_toplevel->app_id);
|
||||
wlr_xdg_surface_ping(xdg_toplevel->base);
|
||||
|
||||
struct sway_xdg_shell_view *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);
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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_associate(struct wl_listener *listener, void *data);
|
||||
|
||||
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);
|
||||
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) {
|
||||
unmanaged_handle_unmap(&surface->unmap, NULL);
|
||||
}
|
||||
if (associated) {
|
||||
unmanaged_handle_dissociate(&surface->dissociate, NULL);
|
||||
}
|
||||
|
||||
unmanaged_handle_destroy(&surface->destroy, NULL);
|
||||
xsurface->data = NULL;
|
||||
|
||||
struct sway_xwayland_view *xwayland_view = create_xwayland_view(xsurface);
|
||||
if (associated) {
|
||||
handle_associate(&xwayland_view->associate, NULL);
|
||||
}
|
||||
if (mapped) {
|
||||
handle_map(&xwayland_view->map, xsurface);
|
||||
}
|
||||
@ -531,20 +540,30 @@ static void handle_map(struct wl_listener *listener, void *data) {
|
||||
transaction_commit_dirty();
|
||||
}
|
||||
|
||||
static void handle_dissociate(struct wl_listener *listener, void *data);
|
||||
|
||||
static void handle_override_redirect(struct wl_listener *listener, void *data) {
|
||||
struct sway_xwayland_view *xwayland_view =
|
||||
wl_container_of(listener, xwayland_view, override_redirect);
|
||||
struct sway_view *view = &xwayland_view->view;
|
||||
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) {
|
||||
handle_unmap(&xwayland_view->unmap, NULL);
|
||||
}
|
||||
if (associated) {
|
||||
handle_dissociate(&xwayland_view->dissociate, NULL);
|
||||
}
|
||||
|
||||
handle_destroy(&xwayland_view->destroy, view);
|
||||
xsurface->data = NULL;
|
||||
|
||||
struct sway_xwayland_unmanaged *unmanaged = create_unmanaged(xsurface);
|
||||
if (associated) {
|
||||
unmanaged_handle_associate(&unmanaged->associate, NULL);
|
||||
}
|
||||
if (mapped) {
|
||||
unmanaged_handle_map(&unmanaged->map, xsurface);
|
||||
}
|
||||
|
@ -6,7 +6,6 @@
|
||||
#include <wlr/config.h>
|
||||
#include <wlr/types/wlr_cursor.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_pointer_v1.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(
|
||||
struct wl_listener *listener, void *data) {
|
||||
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.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 =
|
||||
wlr_keyboard_shortcuts_inhibit_v1_create(server->wl_display);
|
||||
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);
|
||||
bool exact_identifier = keyboard->wlr->group != NULL;
|
||||
seat_idle_notify_activity(seat, IDLE_SOURCE_KEYBOARD);
|
||||
bool input_inhibited = seat->exclusive_client != NULL ||
|
||||
server.session_lock.locked;
|
||||
bool locked = server.session_lock.locked;
|
||||
struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor =
|
||||
keyboard_shortcuts_inhibitor_get_for_focused_surface(seat);
|
||||
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;
|
||||
get_active_binding(&keyboard->state_keycodes,
|
||||
config->current_mode->keycode_bindings, &binding_released,
|
||||
keyinfo.code_modifiers, true, input_inhibited,
|
||||
keyinfo.code_modifiers, true, locked,
|
||||
shortcuts_inhibited, device_identifier,
|
||||
exact_identifier, keyboard->effective_layout);
|
||||
get_active_binding(&keyboard->state_keysyms_raw,
|
||||
config->current_mode->keysym_bindings, &binding_released,
|
||||
keyinfo.raw_modifiers, true, input_inhibited,
|
||||
keyinfo.raw_modifiers, true, locked,
|
||||
shortcuts_inhibited, device_identifier,
|
||||
exact_identifier, keyboard->effective_layout);
|
||||
get_active_binding(&keyboard->state_keysyms_translated,
|
||||
config->current_mode->keysym_bindings, &binding_released,
|
||||
keyinfo.translated_modifiers, true, input_inhibited,
|
||||
keyinfo.translated_modifiers, true, locked,
|
||||
shortcuts_inhibited, device_identifier,
|
||||
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) {
|
||||
get_active_binding(&keyboard->state_keycodes,
|
||||
config->current_mode->keycode_bindings, &binding,
|
||||
keyinfo.code_modifiers, false, input_inhibited,
|
||||
keyinfo.code_modifiers, false, locked,
|
||||
shortcuts_inhibited, device_identifier,
|
||||
exact_identifier, keyboard->effective_layout);
|
||||
get_active_binding(&keyboard->state_keysyms_raw,
|
||||
config->current_mode->keysym_bindings, &binding,
|
||||
keyinfo.raw_modifiers, false, input_inhibited,
|
||||
keyinfo.raw_modifiers, false, locked,
|
||||
shortcuts_inhibited, device_identifier,
|
||||
exact_identifier, keyboard->effective_layout);
|
||||
get_active_binding(&keyboard->state_keysyms_translated,
|
||||
config->current_mode->keysym_bindings, &binding,
|
||||
keyinfo.translated_modifiers, false, input_inhibited,
|
||||
keyinfo.translated_modifiers, false, locked,
|
||||
shortcuts_inhibited, device_identifier,
|
||||
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,
|
||||
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,
|
||||
sway_device->input_device->wlr_device);
|
||||
wl_event_source_timer_update(
|
||||
@ -1069,44 +1067,44 @@ void seat_configure_xcursor(struct sway_seat *seat) {
|
||||
sway_log(SWAY_ERROR,
|
||||
"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];
|
||||
struct wlr_output *output = sway_output->wlr_output;
|
||||
bool result =
|
||||
wlr_xcursor_manager_load(seat->cursor->xcursor_manager,
|
||||
output->scale);
|
||||
if (!result) {
|
||||
sway_log(SWAY_ERROR,
|
||||
"Cannot load xcursor theme for output '%s' with scale %f",
|
||||
output->name, output->scale);
|
||||
|
||||
for (int i = 0; i < root->outputs->length; ++i) {
|
||||
struct sway_output *sway_output = root->outputs->items[i];
|
||||
struct wlr_output *output = sway_output->wlr_output;
|
||||
bool result =
|
||||
wlr_xcursor_manager_load(seat->cursor->xcursor_manager,
|
||||
output->scale);
|
||||
if (!result) {
|
||||
sway_log(SWAY_ERROR,
|
||||
"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
|
||||
cursor_set_image(seat->cursor, NULL, NULL);
|
||||
cursor_set_image(seat->cursor, "default", NULL);
|
||||
wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x,
|
||||
seat->cursor->cursor->y);
|
||||
// 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, "default", NULL);
|
||||
wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x,
|
||||
seat->cursor->cursor->y);
|
||||
}
|
||||
}
|
||||
|
||||
bool seat_is_input_allowed(struct sway_seat *seat,
|
||||
struct wlr_surface *surface) {
|
||||
if (server.session_lock.locked) {
|
||||
if (server.session_lock.lock == NULL) {
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (!server.session_lock.locked) {
|
||||
return true;
|
||||
}
|
||||
if (server.session_lock.lock == NULL) {
|
||||
return false;
|
||||
}
|
||||
struct wl_client *client = wl_resource_get_client(surface->resource);
|
||||
return seat->exclusive_client == client || seat->exclusive_client == 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void seat_set_exclusive_client(struct sway_seat *seat,
|
||||
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;
|
||||
}
|
||||
void seat_unfocus_unless_client(struct sway_seat *seat, struct wl_client *client) {
|
||||
if (seat->focused_layer) {
|
||||
if (wl_resource_get_client(seat->focused_layer->resource) != client) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
seat->exclusive_client = client;
|
||||
}
|
||||
|
||||
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) {
|
||||
struct sway_seat* seat = sway_switch->seat_device->sway_seat;
|
||||
bool input_inhibited = seat->exclusive_client != NULL ||
|
||||
server.session_lock.locked;
|
||||
struct sway_seat *seat = sway_switch->seat_device->sway_seat;
|
||||
bool locked = server.session_lock.locked;
|
||||
|
||||
list_t *bindings = config->current_mode->switch_bindings;
|
||||
struct sway_switch_binding *matched_binding = NULL;
|
||||
@ -52,13 +51,13 @@ static void execute_binding(struct sway_switch *sway_switch) {
|
||||
continue;
|
||||
}
|
||||
bool binding_locked = binding->flags & BINDING_LOCKED;
|
||||
if (!binding_locked && input_inhibited) {
|
||||
if (!binding_locked && locked) {
|
||||
continue;
|
||||
}
|
||||
|
||||
matched_binding = binding;
|
||||
|
||||
if (binding_locked == input_inhibited) {
|
||||
if (binding_locked == locked) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -58,9 +58,7 @@ void sway_configure_tablet(struct sway_tablet *tablet) {
|
||||
tablet->seat_device->input_device->wlr_device;
|
||||
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) {
|
||||
tablet->tablet_v2 =
|
||||
|
16
sway/lock.c
16
sway/lock.c
@ -4,6 +4,7 @@
|
||||
#include "sway/input/cursor.h"
|
||||
#include "sway/input/keyboard.h"
|
||||
#include "sway/input/seat.h"
|
||||
#include "sway/layers.h"
|
||||
#include "sway/output.h"
|
||||
#include "sway/server.h"
|
||||
#include "sway/surface.h"
|
||||
@ -129,7 +130,6 @@ static void handle_unlock(struct wl_listener *listener, void *data) {
|
||||
|
||||
struct sway_seat *seat;
|
||||
wl_list_for_each(seat, &server.input->seats, link) {
|
||||
seat_set_exclusive_client(seat, NULL);
|
||||
// copied from seat_set_focus_layer -- deduplicate?
|
||||
struct sway_node *previous = seat_get_focus_inactive(seat, &root->node);
|
||||
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
|
||||
for (int i = 0; i < root->outputs->length; ++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_destroy.link);
|
||||
|
||||
struct sway_seat *seat;
|
||||
wl_list_for_each(seat, &server.input->seats, link) {
|
||||
seat->exclusive_client = NULL;
|
||||
}
|
||||
|
||||
// redraw everything
|
||||
for (int i = 0; i < root->outputs->length; ++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;
|
||||
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);
|
||||
|
43
sway/main.c
43
sway/main.c
@ -49,44 +49,6 @@ void sig_handler(int signal) {
|
||||
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) {
|
||||
int socketfd = ipc_open_socket(socket_path);
|
||||
uint32_t len = strlen(command);
|
||||
@ -255,7 +217,7 @@ static const char usage[] =
|
||||
"\n";
|
||||
|
||||
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;
|
||||
|
||||
@ -363,7 +325,6 @@ int main(int argc, char **argv) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
detect_proprietary(allow_unsupported_gpu);
|
||||
increase_nofile_limit();
|
||||
|
||||
// handle SIGTERM signals
|
||||
@ -375,8 +336,6 @@ int main(int argc, char **argv) {
|
||||
|
||||
sway_log(SWAY_INFO, "Starting sway version " SWAY_VERSION);
|
||||
|
||||
root = root_create();
|
||||
|
||||
if (!server_init(&server)) {
|
||||
return 1;
|
||||
}
|
||||
|
@ -24,8 +24,9 @@
|
||||
#include <wlr/types/wlr_primary_selection_v1.h>
|
||||
#include <wlr/types/wlr_relative_pointer_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_single_pixel_buffer_v1.h>
|
||||
#include <wlr/types/wlr_subcompositor.h>
|
||||
#include <wlr/types/wlr_tablet_v2.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_v2.h>
|
||||
#include <wlr/types/wlr_xdg_output_v1.h>
|
||||
#include <xf86drm.h>
|
||||
#include "config.h"
|
||||
#include "list.h"
|
||||
#include "log.h"
|
||||
@ -59,6 +61,8 @@
|
||||
#define SWAY_XDG_SHELL_VERSION 2
|
||||
#define SWAY_LAYER_SHELL_VERSION 4
|
||||
|
||||
bool allow_unsupported_gpu = false;
|
||||
|
||||
#if WLR_HAS_DRM_BACKEND
|
||||
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
|
||||
@ -73,6 +77,24 @@ static void handle_drm_lease_request(struct wl_listener *listener, void *data) {
|
||||
}
|
||||
#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,
|
||||
const struct wl_global *global, void *data) {
|
||||
#if HAVE_XWAYLAND
|
||||
@ -82,9 +104,54 @@ static bool filter_global(const struct wl_client *client,
|
||||
}
|
||||
#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;
|
||||
}
|
||||
|
||||
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) {
|
||||
sway_log(SWAY_DEBUG, "Initializing Wayland server");
|
||||
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);
|
||||
|
||||
root = root_create(server->wl_display);
|
||||
|
||||
server->backend = wlr_backend_autocreate(server->wl_display, &server->session);
|
||||
if (!server->backend) {
|
||||
sway_log(SWAY_ERROR, "Unable to create backend");
|
||||
return false;
|
||||
}
|
||||
|
||||
wlr_multi_for_each_backend(server->backend, detect_proprietary, NULL);
|
||||
|
||||
server->renderer = wlr_renderer_autocreate(server->backend);
|
||||
if (!server->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,
|
||||
SWAY_XDG_SHELL_VERSION);
|
||||
wl_signal_add(&server->xdg_shell->events.new_surface,
|
||||
&server->xdg_shell_surface);
|
||||
server->xdg_shell_surface.notify = handle_xdg_shell_surface;
|
||||
wl_signal_add(&server->xdg_shell->events.new_toplevel,
|
||||
&server->xdg_shell_toplevel);
|
||||
server->xdg_shell_toplevel.notify = handle_xdg_shell_toplevel;
|
||||
|
||||
server->tablet_v2 = wlr_tablet_v2_create(server->wl_display);
|
||||
|
||||
@ -226,9 +297,10 @@ bool server_init(struct sway_server *server) {
|
||||
}
|
||||
#endif
|
||||
|
||||
wlr_export_dmabuf_manager_v1_create(server->wl_display);
|
||||
wlr_screencopy_manager_v1_create(server->wl_display);
|
||||
wlr_data_control_manager_v1_create(server->wl_display);
|
||||
server->export_dmabuf_manager_v1 = wlr_export_dmabuf_manager_v1_create(server->wl_display);
|
||||
server->screencopy_manager_v1 = wlr_screencopy_manager_v1_create(server->wl_display);
|
||||
server->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_single_pixel_buffer_manager_v1_create(server->wl_display);
|
||||
server->content_type_manager_v1 =
|
||||
|
@ -649,7 +649,8 @@ The default colors are:
|
||||
|
||||
|
||||
*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>]
|
||||
Set default border style for new floating windows. This only applies to
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wlr/types/wlr_output_layout.h>
|
||||
#include <wlr/util/transform.h>
|
||||
#include "sway/desktop/transaction.h"
|
||||
#include "sway/input/seat.h"
|
||||
#include "sway/ipc-server.h"
|
||||
@ -23,14 +24,14 @@ static void output_layout_handle_change(struct wl_listener *listener,
|
||||
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));
|
||||
if (!root) {
|
||||
sway_log(SWAY_ERROR, "Unable to allocate sway_root");
|
||||
return NULL;
|
||||
}
|
||||
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);
|
||||
#if HAVE_XWAYLAND
|
||||
wl_list_init(&root->xwayland_unmanaged);
|
||||
@ -52,7 +53,6 @@ void root_destroy(struct sway_root *root) {
|
||||
list_free(root->scratchpad);
|
||||
list_free(root->non_desktop_outputs);
|
||||
list_free(root->outputs);
|
||||
wlr_output_layout_destroy(root->output_layout);
|
||||
free(root);
|
||||
}
|
||||
|
||||
|
@ -882,6 +882,8 @@ void view_unmap(struct sway_view *view) {
|
||||
|
||||
wl_list_remove(&view->surface_new_subsurface.link);
|
||||
|
||||
view->executed_criteria->length = 0;
|
||||
|
||||
if (view->urgent_timer) {
|
||||
wl_event_source_remove(view->urgent_timer);
|
||||
view->urgent_timer = NULL;
|
||||
|
@ -23,6 +23,45 @@ static void xdg_decoration_handle_request_mode(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct sway_xdg_decoration *deco =
|
||||
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;
|
||||
enum wlr_xdg_toplevel_decoration_v1_mode mode =
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
if (view->wlr_xdg_toplevel->base->initialized) {
|
||||
wlr_xdg_toplevel_decoration_v1_set_mode(deco->wlr_xdg_decoration, mode);
|
||||
}
|
||||
|
||||
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 "background-image.h"
|
||||
#include "cairo_util.h"
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
#include "swaybar/image.h"
|
||||
|
||||
#if HAVE_GDK_PIXBUF
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#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
|
||||
static cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf(
|
||||
const GdkPixbuf *gdkbuf) {
|
||||
@ -121,7 +104,7 @@ static cairo_surface_t* gdk_cairo_image_surface_create_from_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;
|
||||
#if HAVE_GDK_PIXBUF
|
||||
GError *err = NULL;
|
||||
@ -151,70 +134,3 @@ cairo_surface_t *load_background_image(const char *path) {
|
||||
}
|
||||
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',
|
||||
'config.c',
|
||||
'i3bar.c',
|
||||
'image.c',
|
||||
'input.c',
|
||||
'ipc.c',
|
||||
'main.c',
|
||||
|
@ -7,12 +7,12 @@
|
||||
#include <string.h>
|
||||
#include "swaybar/bar.h"
|
||||
#include "swaybar/config.h"
|
||||
#include "swaybar/image.h"
|
||||
#include "swaybar/input.h"
|
||||
#include "swaybar/tray/host.h"
|
||||
#include "swaybar/tray/icon.h"
|
||||
#include "swaybar/tray/item.h"
|
||||
#include "swaybar/tray/tray.h"
|
||||
#include "background-image.h"
|
||||
#include "cairo_util.h"
|
||||
#include "list.h"
|
||||
#include "log.h"
|
||||
@ -431,7 +431,7 @@ static void reload_sni(struct swaybar_sni *sni, char *icon_theme,
|
||||
list_free(icon_search_paths);
|
||||
if (icon_path) {
|
||||
cairo_surface_destroy(sni->icon);
|
||||
sni->icon = load_background_image(icon_path);
|
||||
sni->icon = load_image(icon_path);
|
||||
free(icon_path);
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user