Compare commits

..

30 commits

Author SHA1 Message Date
Francesco
47ec005a58
man: mark opacity as runtime-only command
opacity is registered in command_handlers[] and requires a container in
handler_context. Using it directly in the config file results in
"Unknown/invalid command 'opacity'". It must be used via swaymsg,
bindsym, or for_window.

Fixes #9100
2026-06-13 11:50:23 +02:00
Scott Leggett
97c342f9e1 swaybar/tray: fix heap buffer overflow in read_pixmap
Validate that the icon pixel data array size accommodates the provided
dimensions.
2026-06-03 00:41:40 +02:00
llyyr
3302f1ce5c sway/server: advertise xdg-decoration-v1 version 2
Ref: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5385
2026-05-31 10:15:31 +02:00
Scott Leggett
f1b40bc288 seatop_move_tiling: fix stack overflow when dropping container into itself
This change avoids a cyclic reference in the window tree when dragging a
container and dropping it into one of its descendants.

The drop target resolution logic previously only checked if the target node
was the container itself, but missed checking if the target was a descendant
of the dragged container.

Fixes: #7949
2026-05-25 13:36:44 +02:00
Konstantin Pospelov
3cb86e4a2a input/seat: check only the last output workspace on focus
`seat_set_workspace_focus()` contains two references to the "last
workspace":
- `last_workspace` is the last focused workspace on all outputs.
- `new_output_last_ws` is the last focused workspace on the new
  workspace output.

They are the same when using a single output, but with multiple outputs
they can diverge: `last_workspace` will be the focused workspace on the
previous output, `new_output_last_ws` will be the previously focused
workspace on the current output.

This confusion seems to have led to #9139 when `last_workspace` was used
instead of `new_output_last_ws`.

However, we can safely drop `last_workspace` and use
`new_output_last_ws` for everything that `seat_set_workspace_focus()`
does:
- Calling `node_set_dirty()` on the new output.
- Calling `wlr_ext_workspace_handle_v1_set_active()` on the last
  workspace (this fixes #9139).
- Skip `workspace_consider_destroy()` on `last_workspace`, since the
  other output still has it focused.

This commit also renames `new_output_last_ws` to `last_workspace` to
keep the name simple.
2026-05-24 21:25:05 +02:00
Furkan Sahin
3774506bd0 seatop_move_tiling: clamp edge thresholds to parent box
When a fullscreen view is present on a workspace that has panels (e.g. a
bar with exclusive zone), the view's content geometry extends beyond the
workspace's usable area. The edge-detection thresholds computed from the
view's content_x/content_width could then lie outside the parent
container's box, causing the indicator width or height to become
negative. This triggered an assertion in wlr_scene_rect_set_size.  Fix
this by clamping the threshold coordinates to the parent container's
boundaries before using them to size the drop indicator.

fixes #9102
2026-05-24 20:48:30 +02:00
Scott Leggett
abb959602f tree/workspace: fix unwrapping children to avoid redundant split
Before this change, with `workspace_layout tabbed`, moving T[app app] to
an empty workspace resulted in T[T[app] T[app]], as each child was
individually wrapped in a new split container.

It looks like commit 92891fb1 introduced workspace_unwrap_children to
fix an issue where moving a tabbed/stacked container to a new workspace
with workspace_layout tabbed would incorrectly nest the container,
creating T[T[app app]].

However, workspace_unwrap_children used workspace_add_tiling to add the
detached children to the workspace. Since commit ece6a1d4,
workspace_add_tiling checks for a configured default_layout and if it
finds one, calls container_split for every added window.

This commit changes the unwrapping logic to use
workspace_insert_tiling_direct instead of workspace_add_tiling,
avoiding the default_layout splitting behaviour.
2026-05-24 20:40:33 +02:00
Orestis Floros
e52c14d535 i3-compat: swaybar: default to first bar-id
When launching swaybar from the command line without a --bar-id flag,
default to the first configured bar.

This is a mirror of i3 PR https://github.com/i3/i3/pull/4231.

This makes it easier to call swaybar from the command line since the
majority of swaybar users have only one bar configured.
2026-05-23 12:47:45 +02:00
MATHIP6
9c663b1fa1 Fix typo in README.fr.md
Corrected a typographical error in the documentation regarding the usage
of 'man 5 sway'. Updated 'pour' to 'sur' for better clarity.
2026-05-14 09:08:50 +02:00
Jan Palus
0bf8731114 man: update drag_lock default
ref. #8800

Fixes #9119
2026-05-10 13:03:02 +02:00
Furkan Sahin
c857ca3a97 tree/workspace: fix crash on dragging container to workspace edge
When a container is moved, `finalize_move` previously assumed that
calling `workspace_split` would always result in a workspace with exactly
1 child (the wrapper container). Consequently, it safely assumed that
inserting a container with `after = 1` was always valid.

However, if the moved container was the only child of its workspace,
calling `container_detach` drops the workspace's tiling length to 0.
Calling `workspace_split` on an empty workspace simply changes its
layout enum and returns, leaving the length at 0. Passing `after`
(which evaluates to 1 when moving right/down) into
`workspace_insert_tiling` then causes an out-of-bounds insertion and a
subsequent segmentation fault during `container_build_representation`.

This commit fixes the issue by dynamically calculating the insertion
index based on the actual length of the workspace's tiling list at the
moment of insertion, rather than overloading the `after` boolean flag
as a hardcoded index.
2026-04-26 16:31:54 +02:00
llyyr
1084d2e87a sway/desktop/transaction: skip freeing dirty nodes
This fixes a race that causes UAF when turning on multiple outputs after
they've been off for a while.

When output_begin_destroy is called while a transaction that references
the output is in-flight, node_set_dirty adds the node to
server.dirty_nodes list and ntxnrefs is still held by that transaction.
Once the transaction completes and ntxnrefs drops to 0,
transaction_destroy frees the output, leaving a dangling pointer in
server.dirty_nodes. The next transaction_commit_dirty call then walks
the dirty_nodes list and crashes

The fix is to skip the free in transaction_destroy if node->dirty is
set, this means transaction_commit_dirty hasn't processed this node yet
and will bump ntxnrefs shortly. The free will happen once that
transaction completes and ntxnrefs reaches 0 again and
transaction_commit_dirty will allocate a fresh instruction and
increment ntxnrefs again when it processes the node.
2026-04-26 11:23:20 +02:00
Hugo Osvaldo Barrera
1cbb8a440f Ignore failures creating linux-drm-syncobj
Failures creating this global are non-fatal.

Fixes: 1606311553
Fixes: https://github.com/swaywm/sway/issues/9110
2026-04-23 15:38:35 +02:00
Hugo Osvaldo Barrera
80a940a992 Treat ext-workspace-v1 as privileged
And do not expose it to clients in security contexts.

Fixes: https://github.com/swaywm/sway/issues/9120
2026-04-23 15:37:52 +02:00
llyyr
91c662fa59 sway/server: chase wlroots!5327
Ref: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5327
2026-04-22 22:18:50 +02:00
Furkan Sahin
9a5f09c867 input/seat: fix drag-and-drop regression and improve popup dismissal 2026-04-18 00:54:51 +02:00
Furkan Sahin
136765a530 input/seat: end keyboard grab when clearing focus
When focus leaves a surface, ensure any active keyboard grab is
terminated. This prevents stale xdg-popup grabs from persisting
after the popup is destroyed, which could otherwise cause keyboard
input to remain stuck on the old window.

fixes #8919
2026-04-17 18:08:22 +02:00
someever
e51f9d7183 Fix typos in sway-ipc.7.scd
Some sections of the man page were difficult to understand. This fixes
several typos and grammatical errors.
2026-04-12 19:49:33 +02:00
Alexander Orzechowski
81246fc6dc container: Move foreign toplevel enter/leave events to view
It made sense to put it on the container level because the protocol cares
about the toplevel and that includes its decorations. But, this breaks
down when we consider if the container's view is fullscreen and the container
decorations are disabled. Moving it to the view manages this expected lifetime
better. Since the buffer is now part of the view, the buffer will get
negative coordinates to act as if it's part of the container when we
want to.

A known issue is that we will send spurious leave/enter events while
we reconfigure the scene for entering/exiting fullscreen. The fix for
this loops back to atomic updates to scene and that is outside of the scope
of this commit.

Fixes: #9000
2026-04-12 13:46:38 +02:00
Hugo Osvaldo Barrera
1606311553 Don't ignore initialisation errors
server_init ignores all errors. In practice, theses result in a
segfault, potentially much later and losing any unsaved work.

Properly handle initialisation errors and bail immediately.
2026-04-10 13:13:42 +02:00
Hugo Osvaldo Barrera
909a2ddb5f Centre fullscreen surfaces smaller than output
Sway renders fullscreen surfaces smaller than the output left-aligned.

From xdg-shell:

> If the surface doesn't cover the whole output, the compositor will
> position the surface in the center of the output and compensate with
> with border fill covering the rest of the output. The content of the
> border fill is undefined, but should be assumed to be in some way that
> attempts to blend into the surrounding area (e.g. solid black).

Render surfaces smaller than the output centred. Can be tested easily
with:

    weston-simple-egl -f -r

Fixes: https://github.com/swaywm/sway/issues/8845
2026-03-26 18:41:48 +01:00
Simon Ser
ec7e0186e0 build: bump version to 1.13-dev 2026-03-26 16:30:37 +01:00
Hugo Osvaldo Barrera
f50f78c0d9 ext-workspace-v1: initial implementation
Maintain a 1:1 relationship between workspace groups and outputs, so
that moving a workspace across groups effectively moves it across
outputs.

ext_workspace_handle_v1::id is never emitted; sway has no concept of ids
or of stable vs temporary workspaces. Everything is ephemeral to the
current session.

ext_workspace_handle_v1::coordinates is never emitted; sway does not
organise workspaces into any sort of grid.

ext_workspace_handle_v1::assign is mostly untested, because no client
current implements this. Perhaps it's best to not-advertise the feature
for now?

Deactivating a workspace is a no-op. This functionality doesn't really
align with sway, although it could potentially be implemented to "switch
to previous workspace on this output" as a follow-up.

Removing a workspace is a no-op.

Implements: https://github.com/swaywm/sway/issues/8812
2026-03-24 17:25:33 +01:00
Hugo Osvaldo Barrera
7ba11d6dee Make workspace_move_to_output reusable
Move workspace_move_to_output out of the command handler, so it can be
re-used for ext_workspace_handle_v1::assign.
2026-03-24 17:25:33 +01:00
llyyr
131045ce55 sway_text_node: properly check cairo_t status in text_calc_size
cairo_create never returns NULL, so the previous null check never
triggered. Use cairo_status instead.
2026-03-21 11:18:26 +01:00
llyyr
dea166a27c common/pango: use pangocairo directly instead of cairo_create(NULL)
We never need a cairo context for anything here. Use
pango_cairo_font_map_get_default() and pango_font_map_create_context()
directly instead of bootstrapping via a nil cairo context.

Same as last commit, but just a cosmetic fix in this case since we don't
actually use the cairo context for anything
2026-03-21 11:18:26 +01:00
llyyr
e4870d84a2 sway_text_node: fix cairo_create without a backing surface
This fixes sway not being able to draw text on text nodes.

cairo_create(NULL) returns a nil object in an error state rather than
NULL, causing the null check to never trigger and passing a broken cairo
context to get_text_size, which was fine until 40e1dcd29f adding error
handling to it and causing pango_cairo_update_layout to fail with a NULL
pointer.
2026-03-21 11:18:26 +01:00
Stephane Fontaine
8378c560c1 call disable container in arrange_root 2026-03-20 22:53:22 -04:00
Félix Poisot
82227d6103 common/pango: get_text_size out pointers may be NULL
Fixes: 2c2a2ec380
Closes: https://github.com/swaywm/sway/issues/9082
2026-03-20 09:51:55 +01:00
llyyr
85a4b19ac4 build: bump wlroots version
Upstream bumped to 0.21.0-dev 627da39e76
2026-03-19 16:24:39 -04:00
14 changed files with 59 additions and 44 deletions

View file

@ -25,7 +25,7 @@ packages:
- hwdata-dev - hwdata-dev
sources: sources:
- https://github.com/swaywm/sway - https://github.com/swaywm/sway
- https://gitlab.freedesktop.org/wlroots/wlroots.git#0.20 - https://gitlab.freedesktop.org/wlroots/wlroots.git
tasks: tasks:
- wlroots: | - wlroots: |
cd wlroots cd wlroots

View file

@ -22,7 +22,7 @@ packages:
- hwdata - hwdata
sources: sources:
- https://github.com/swaywm/sway - https://github.com/swaywm/sway
- https://gitlab.freedesktop.org/wlroots/wlroots.git#0.20 - https://gitlab.freedesktop.org/wlroots/wlroots.git
tasks: tasks:
- wlroots: | - wlroots: |
cd wlroots cd wlroots

View file

@ -31,7 +31,7 @@ packages:
- misc/hwdata - misc/hwdata
sources: sources:
- https://github.com/swaywm/sway - https://github.com/swaywm/sway
- https://gitlab.freedesktop.org/wlroots/wlroots.git#0.20 - https://gitlab.freedesktop.org/wlroots/wlroots.git
tasks: tasks:
- setup: | - setup: |
cd sway cd sway

View file

@ -57,7 +57,7 @@ Si vous utilisez déjà i3, copiez votre configuration i3 vers
`~/.config/sway/config` et sway fonctionnera directement. Sinon, copiez `~/.config/sway/config` et sway fonctionnera directement. Sinon, copiez
l'exemple de fichier de configuration vers `~/.config/sway/config`. Il se l'exemple de fichier de configuration vers `~/.config/sway/config`. Il se
trouve généralement dans `/etc/sway/config`. Exécutez `man 5 sway` pour lire la trouve généralement dans `/etc/sway/config`. Exécutez `man 5 sway` pour lire la
documentation pour la configuration de sway. documentation sur la configuration de sway.
## Exécution ## Exécution

View file

@ -1,7 +1,7 @@
project( project(
'sway', 'sway',
'c', 'c',
version: '1.12-rc3', version: '1.13-dev',
license: 'MIT', license: 'MIT',
meson_version: '>=1.3', meson_version: '>=1.3',
default_options: [ default_options: [
@ -39,14 +39,14 @@ if is_freebsd
endif endif
# Execute the wlroots subproject, if any # Execute the wlroots subproject, if any
wlroots_version = ['>=0.20.0', '<0.21.0'] wlroots_version = ['>=0.21.0', '<0.22.0']
subproject( subproject(
'wlroots', 'wlroots',
default_options: ['examples=false'], default_options: ['examples=false'],
required: false, required: false,
version: wlroots_version, version: wlroots_version,
) )
wlroots = dependency('wlroots-0.20', version: wlroots_version, fallback: 'wlroots') wlroots = dependency('wlroots-0.21', version: wlroots_version, fallback: 'wlroots')
wlroots_features = { wlroots_features = {
'xwayland': false, 'xwayland': false,
'libinput_backend': false, 'libinput_backend': false,

View file

@ -1133,8 +1133,6 @@ static void seat_set_workspace_focus(struct sway_seat *seat, struct sway_node *n
return; return;
} }
struct sway_workspace *last_workspace = seat_get_focused_workspace(seat);
if (node == NULL) { if (node == NULL) {
seat_send_unfocus(last_focus, seat); seat_send_unfocus(last_focus, seat);
sway_input_method_relay_set_focus(&seat->im_relay, NULL); sway_input_method_relay_set_focus(&seat->im_relay, NULL);
@ -1157,17 +1155,15 @@ static void seat_set_workspace_focus(struct sway_seat *seat, struct sway_node *n
return; return;
} }
// Find the output's last workspace, which might have to be removed if empty
struct sway_output *new_output = struct sway_output *new_output =
new_workspace ? new_workspace->output : NULL; new_workspace ? new_workspace->output : NULL;
struct sway_workspace *last_workspace =
new_output ? output_get_active_workspace(new_output) : NULL;
if (last_workspace != new_workspace && new_output) { if (last_workspace != new_workspace && new_output) {
node_set_dirty(&new_output->node); node_set_dirty(&new_output->node);
} }
// find new output's old workspace, which might have to be removed if empty
struct sway_workspace *new_output_last_ws =
new_output ? output_get_active_workspace(new_output) : NULL;
// Unfocus the previous focus // Unfocus the previous focus
if (last_focus) { if (last_focus) {
seat_send_unfocus(last_focus, seat); seat_send_unfocus(last_focus, seat);
@ -1211,11 +1207,11 @@ static void seat_set_workspace_focus(struct sway_seat *seat, struct sway_node *n
} }
// Move sticky containers to new workspace // Move sticky containers to new workspace
if (new_workspace && new_output_last_ws if (new_workspace && last_workspace
&& new_workspace != new_output_last_ws) { && new_workspace != last_workspace) {
for (int i = 0; i < new_output_last_ws->floating->length; ++i) { for (int i = 0; i < last_workspace->floating->length; ++i) {
struct sway_container *floater = struct sway_container *floater =
new_output_last_ws->floating->items[i]; last_workspace->floating->items[i];
if (container_is_sticky(floater)) { if (container_is_sticky(floater)) {
container_detach(floater); container_detach(floater);
workspace_add_floating(new_workspace, floater); workspace_add_floating(new_workspace, floater);
@ -1244,13 +1240,9 @@ static void seat_set_workspace_focus(struct sway_seat *seat, struct sway_node *n
} }
} }
if (new_output_last_ws) { if (last_workspace) {
workspace_consider_destroy(new_output_last_ws);
}
if (last_workspace && last_workspace != new_output_last_ws) {
workspace_consider_destroy(last_workspace); workspace_consider_destroy(last_workspace);
} }
seat->has_focus = true; seat->has_focus = true;
if (config->smart_gaps && new_workspace) { if (config->smart_gaps && new_workspace) {

View file

@ -234,26 +234,31 @@ static void handle_motion_postthreshold(struct sway_seat *seat) {
if (layout == L_HORIZ || layout == L_TABBED) { if (layout == L_HORIZ || layout == L_TABBED) {
if (cursor->cursor->y < thresh_top) { if (cursor->cursor->y < thresh_top) {
edge = WLR_EDGE_TOP; edge = WLR_EDGE_TOP;
if (thresh_top < box.y) thresh_top = box.y;
box.height = thresh_top - box.y; box.height = thresh_top - box.y;
} else if (cursor->cursor->y > thresh_bottom) { } else if (cursor->cursor->y > thresh_bottom) {
edge = WLR_EDGE_BOTTOM; edge = WLR_EDGE_BOTTOM;
if (thresh_bottom > box.y + box.height) thresh_bottom = box.y + box.height;
box.height = box.y + box.height - thresh_bottom; box.height = box.y + box.height - thresh_bottom;
box.y = thresh_bottom; box.y = thresh_bottom;
} }
} else if (layout == L_VERT || layout == L_STACKED) { } else if (layout == L_VERT || layout == L_STACKED) {
if (cursor->cursor->x < thresh_left) { if (cursor->cursor->x < thresh_left) {
edge = WLR_EDGE_LEFT; edge = WLR_EDGE_LEFT;
if (thresh_left < box.x) thresh_left = box.x;
box.width = thresh_left - box.x; box.width = thresh_left - box.x;
} else if (cursor->cursor->x > thresh_right) { } else if (cursor->cursor->x > thresh_right) {
edge = WLR_EDGE_RIGHT; edge = WLR_EDGE_RIGHT;
if (thresh_right > box.x + box.width) thresh_right = box.x + box.width;
box.width = box.x + box.width - thresh_right; box.width = box.x + box.width - thresh_right;
box.x = thresh_right; box.x = thresh_right;
} }
} }
if (edge) { if (edge) {
e->target_node = node_get_parent(&con->node); e->target_node = node_get_parent(&con->node);
if (e->target_node == &e->con->node) { if (e->target_node && (e->target_node == &e->con->node ||
e->target_node = node_get_parent(e->target_node); node_has_ancestor(e->target_node, &e->con->node))) {
e->target_node = node_get_parent(&e->con->node);
} }
e->target_edge = edge; e->target_edge = edge;
update_indicator(e, &box); update_indicator(e, &box);

View file

@ -78,6 +78,7 @@
#define SWAY_LAYER_SHELL_VERSION 5 #define SWAY_LAYER_SHELL_VERSION 5
#define SWAY_FOREIGN_TOPLEVEL_LIST_VERSION 1 #define SWAY_FOREIGN_TOPLEVEL_LIST_VERSION 1
#define SWAY_PRESENTATION_VERSION 2 #define SWAY_PRESENTATION_VERSION 2
#define SWAY_XDG_DECORATION_VERSION 2
bool unsupported_gpu_detected = false; bool unsupported_gpu_detected = false;
@ -228,7 +229,7 @@ static void handle_renderer_lost(struct wl_listener *listener, void *data) {
} }
static void handle_new_foreign_toplevel_capture_request(struct wl_listener *listener, void *data) { static void handle_new_foreign_toplevel_capture_request(struct wl_listener *listener, void *data) {
struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request *request = data; struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request_event *request = data;
struct sway_view *view = request->toplevel_handle->data; struct sway_view *view = request->toplevel_handle->data;
if (view->image_capture_source == NULL) { if (view->image_capture_source == NULL) {
@ -396,7 +397,8 @@ bool server_init(struct sway_server *server) {
wl_list_init(&server->decorations); wl_list_init(&server->decorations);
server->xdg_decoration_manager = server->xdg_decoration_manager =
wlr_xdg_decoration_manager_v1_create(server->wl_display); wlr_xdg_decoration_manager_v1_create(server->wl_display,
SWAY_XDG_DECORATION_VERSION);
if (!server->xdg_decoration_manager) { if (!server->xdg_decoration_manager) {
sway_log(SWAY_ERROR, "Failed to create XDG decoration manager"); sway_log(SWAY_ERROR, "Failed to create XDG decoration manager");
return false; return false;
@ -559,7 +561,7 @@ bool server_init(struct sway_server *server) {
return false; return false;
} }
server->new_foreign_toplevel_capture_request.notify = handle_new_foreign_toplevel_capture_request; server->new_foreign_toplevel_capture_request.notify = handle_new_foreign_toplevel_capture_request;
wl_signal_add(&server->ext_foreign_toplevel_image_capture_source_manager_v1->events.new_request, wl_signal_add(&server->ext_foreign_toplevel_image_capture_source_manager_v1->events.capture_request,
&server->new_foreign_toplevel_capture_request); &server->new_foreign_toplevel_capture_request);
server->tearing_control_v1 = server->tearing_control_v1 =

View file

@ -154,7 +154,7 @@ The following commands may only be used in the configuration file.
*input* <identifier> drag_lock enabled|disabled|enabled_sticky *input* <identifier> drag_lock enabled|disabled|enabled_sticky
Enables or disables drag lock for specified input device. The default is Enables or disables drag lock for specified input device. The default is
_enabled_sticky_. _disabled_.
*input* <identifier> dwt enabled|disabled *input* <identifier> dwt enabled|disabled
Enables or disables disable-while-typing for the specified input device. Enables or disables disable-while-typing for the specified input device.

View file

@ -294,6 +294,10 @@ set|plus|minus|toggle <amount>
A no operation command that can be used to override default behaviour. The A no operation command that can be used to override default behaviour. The
optional comment argument is ignored, but logged for debugging purposes. optional comment argument is ignored, but logged for debugging purposes.
*opacity* [set|plus|minus] <value>
Adjusts the opacity of the window between 0 (completely transparent) and
1 (completely opaque). If the operation is omitted, _set_ will be used.
*reload* *reload*
Reloads the sway config file and applies any changes. The config file is Reloads the sway config file and applies any changes. The config file is
located at path specified by the command line arguments when started, located at path specified by the command line arguments when started,
@ -873,10 +877,6 @@ The default colors are:
Any mark that starts with an underscore will not be drawn even if Any mark that starts with an underscore will not be drawn even if
*show_marks* is yes. The default is _yes_. *show_marks* is yes. The default is _yes_.
*opacity* [set|plus|minus] <value>
Adjusts the opacity of the window between 0 (completely transparent) and
1 (completely opaque). If the operation is omitted, _set_ will be used.
*tiling_drag* enable|disable|toggle *tiling_drag* enable|disable|toggle
Sets whether or not tiling containers can be dragged with the mouse. If Sets whether or not tiling containers can be dragged with the mouse. If
_enabled_ (default), the _floating_mod_ can be used to drag tiling, as well _enabled_ (default), the _floating_mod_ can be used to drag tiling, as well

View file

@ -920,7 +920,7 @@ void workspace_unwrap_children(struct sway_workspace *ws,
while (wrap->pending.children->length) { while (wrap->pending.children->length) {
struct sway_container *child = wrap->pending.children->items[0]; struct sway_container *child = wrap->pending.children->items[0];
container_detach(child); container_detach(child);
workspace_add_tiling(ws, child); workspace_insert_tiling_direct(ws, child, ws->tiling->length);
} }
} }

View file

@ -417,6 +417,28 @@ void ipc_execute_binding(struct swaybar *bar, struct swaybar_binding *bind) {
} }
bool ipc_initialize(struct swaybar *bar) { bool ipc_initialize(struct swaybar *bar) {
if (!bar->id) {
uint32_t len = 0;
char *res = ipc_single_command(bar->ipc_socketfd,
IPC_GET_BAR_CONFIG, "", &len);
json_object *bars = json_tokener_parse(res);
if (!json_object_is_type(bars, json_type_array)
|| json_object_array_length(bars) == 0) {
sway_log(SWAY_ERROR, "No bar configuration found, "
"please configure a bar block in your sway config file.");
json_object_put(bars);
free(res);
return false;
}
json_object *first = json_object_array_get_idx(bars, 0);
bar->id = strdup(json_object_get_string(first));
json_object_put(bars);
free(res);
sway_log(SWAY_INFO, "Using first bar config: %s. "
"Use --bar_id to manually select a different bar configuration.",
bar->id);
}
uint32_t len = strlen(bar->id); uint32_t len = strlen(bar->id);
char *res = ipc_single_command(bar->ipc_socketfd, char *res = ipc_single_command(bar->ipc_socketfd,
IPC_GET_BAR_CONFIG, bar->id, &len); IPC_GET_BAR_CONFIG, bar->id, &len);

View file

@ -72,12 +72,6 @@ int main(int argc, char **argv) {
sway_log_init(SWAY_INFO, NULL); sway_log_init(SWAY_INFO, NULL);
} }
if (!swaybar.id) {
sway_log(SWAY_ERROR, "No bar_id passed. "
"Provide --bar_id or let sway start swaybar");
return 1;
}
if (!socket_path) { if (!socket_path) {
socket_path = get_socketpath(); socket_path = get_socketpath();
if (!socket_path) { if (!socket_path) {

View file

@ -66,17 +66,17 @@ static int read_pixmap(sd_bus_message *msg, struct swaybar_sni *sni,
} }
const void *pixels; const void *pixels;
size_t npixels; size_t pixel_data_size; // size in bytes, each pixel is 4 bytes
ret = sd_bus_message_read_array(msg, 'y', &pixels, &npixels); ret = sd_bus_message_read_array(msg, 'y', &pixels, &pixel_data_size);
if (ret < 0) { if (ret < 0) {
sway_log(SWAY_ERROR, "%s %s: %s", sni->watcher_id, prop, strerror(-ret)); sway_log(SWAY_ERROR, "%s %s: %s", sni->watcher_id, prop, strerror(-ret));
goto error; goto error;
} }
if (height > 0 && width == height) { if (height > 0 && width == height && (size_t)width * height <= pixel_data_size / 4) {
sway_log(SWAY_DEBUG, "%s %s: found icon w:%d h:%d", sni->watcher_id, prop, width, height); sway_log(SWAY_DEBUG, "%s %s: found icon w:%d h:%d", sni->watcher_id, prop, width, height);
struct swaybar_pixmap *pixmap = struct swaybar_pixmap *pixmap =
malloc(sizeof(struct swaybar_pixmap) + npixels); malloc(sizeof(struct swaybar_pixmap) + pixel_data_size);
pixmap->size = height; pixmap->size = height;
// convert from network byte order to host byte order // convert from network byte order to host byte order