merge sway master

This commit is contained in:
William McKinnon 2022-04-27 17:33:23 -04:00
parent c37aba2736
commit 7460d9f565
63 changed files with 642 additions and 461 deletions

View file

@ -12,6 +12,7 @@ packages:
- mesa-dev - mesa-dev
- meson - meson
- pango-dev - pango-dev
- pcre2-dev
- pixman-dev - pixman-dev
- scdoc - scdoc
- wayland-dev - wayland-dev

View file

@ -9,6 +9,7 @@ packages:
- libxkbcommon - libxkbcommon
- meson - meson
- pango - pango
- pcre2
- scdoc - scdoc
- wayland - wayland
- wayland-protocols - wayland-protocols

View file

@ -4,6 +4,7 @@ packages:
- devel/json-c - devel/json-c
- devel/libevdev - devel/libevdev
- devel/meson - devel/meson
- devel/pcre2
- devel/pkgconf - devel/pkgconf
- graphics/cairo - graphics/cairo
- graphics/gdk-pixbuf2 - graphics/gdk-pixbuf2

View file

@ -2,7 +2,7 @@
_sway() _sway()
{ {
local cur prev local cur prev short long
_get_comp_words_by_ref cur prev _get_comp_words_by_ref cur prev
short=( short=(

View file

@ -2,7 +2,7 @@
_swaybar() _swaybar()
{ {
local cur prev local cur prev short long
_get_comp_words_by_ref cur prev _get_comp_words_by_ref cur prev
short=( short=(

View file

@ -2,7 +2,7 @@
_swaymsg() _swaymsg()
{ {
local cur prev local cur prev types short long
_get_comp_words_by_ref cur prev _get_comp_words_by_ref cur prev
types=( types=(

View file

@ -13,18 +13,32 @@
## See `man 1 grimshot` or `grimshot usage` for further details. ## See `man 1 grimshot` or `grimshot usage` for further details.
getTargetDirectory() { getTargetDirectory() {
test -f ${XDG_CONFIG_HOME:-~/.config}/user-dirs.dirs && \ test -f "${XDG_CONFIG_HOME:-~/.config}/user-dirs.dirs" && \
. ${XDG_CONFIG_HOME:-~/.config}/user-dirs.dirs . "${XDG_CONFIG_HOME:-~/.config}/user-dirs.dirs"
echo ${XDG_SCREENSHOTS_DIR:-${XDG_PICTURES_DIR:-$HOME}} echo "${XDG_SCREENSHOTS_DIR:-${XDG_PICTURES_DIR:-$HOME}}"
} }
if [ "$1" = "--notify" ]; then NOTIFY=no
NOTIFY=yes CURSOR=
shift 1
else while [ $# -gt 0 ]; do
NOTIFY=no key="$1"
fi
case $key in
-n|--notify)
NOTIFY=yes
shift # past argument
;;
-c|--cursor)
CURSOR=yes
shift # past argument
;;
*) # unknown option
break # done with parsing --flags
;;
esac
done
ACTION=${1:-usage} ACTION=${1:-usage}
SUBJECT=${2:-screen} SUBJECT=${2:-screen}
@ -32,7 +46,7 @@ FILE=${3:-$(getTargetDirectory)/$(date -Ins).png}
if [ "$ACTION" != "save" ] && [ "$ACTION" != "copy" ] && [ "$ACTION" != "check" ]; then if [ "$ACTION" != "save" ] && [ "$ACTION" != "copy" ] && [ "$ACTION" != "check" ]; then
echo "Usage:" echo "Usage:"
echo " grimshot [--notify] (copy|save) [active|screen|output|area|window] [FILE|-]" echo " grimshot [--notify] [--cursor] (copy|save) [active|screen|output|area|window] [FILE|-]"
echo " grimshot check" echo " grimshot check"
echo " grimshot usage" echo " grimshot usage"
echo "" echo ""
@ -67,7 +81,7 @@ notifyError() {
MESSAGE=${1:-"Error taking screenshot with grim"} MESSAGE=${1:-"Error taking screenshot with grim"}
notify -u critical "$TITLE" "$MESSAGE" notify -u critical "$TITLE" "$MESSAGE"
else else
echo $1 echo "$1"
fi fi
} }
@ -91,12 +105,12 @@ takeScreenshot() {
FILE=$1 FILE=$1
GEOM=$2 GEOM=$2
OUTPUT=$3 OUTPUT=$3
if [ ! -z "$OUTPUT" ]; then if [ -n "$OUTPUT" ]; then
grim -o "$OUTPUT" "$FILE" || die "Unable to invoke grim" grim ${CURSOR:+-c} -o "$OUTPUT" "$FILE" || die "Unable to invoke grim"
elif [ -z "$GEOM" ]; then elif [ -z "$GEOM" ]; then
grim "$FILE" || die "Unable to invoke grim" grim ${CURSOR:+-c} "$FILE" || die "Unable to invoke grim"
else else
grim -g "$GEOM" "$FILE" || die "Unable to invoke grim" grim ${CURSOR:+-c} -g "$GEOM" "$FILE" || die "Unable to invoke grim"
fi fi
} }
@ -147,7 +161,7 @@ else
TITLE="Screenshot of $SUBJECT" TITLE="Screenshot of $SUBJECT"
MESSAGE=$(basename "$FILE") MESSAGE=$(basename "$FILE")
notifyOk "$MESSAGE" "$TITLE" notifyOk "$MESSAGE" "$TITLE"
echo $FILE echo "$FILE"
else else
notifyError "Error taking screenshot with grim" notifyError "Error taking screenshot with grim"
fi fi

View file

@ -1,11 +1,11 @@
.\" Generated by scdoc 1.11.1 .\" Generated by scdoc 1.11.2
.\" Complete documentation for this program is not available as a GNU info page .\" Complete documentation for this program is not available as a GNU info page
.ie \n(.g .ds Aq \(aq .ie \n(.g .ds Aq \(aq
.el .ds Aq ' .el .ds Aq '
.nh .nh
.ad l .ad l
.\" Begin generated content: .\" Begin generated content:
.TH "grimshot" "1" "2021-02-23" .TH "grimshot" "1" "2022-03-31"
.P .P
.SH NAME .SH NAME
.P .P
@ -13,7 +13,7 @@ grimshot - a helper for screenshots within sway
.P .P
.SH SYNOPSIS .SH SYNOPSIS
.P .P
\fBgrimshot\fR [--notify] (copy|save) [TARGET] [FILE] \fBgrimshot\fR [--notify] [--cursor] (copy|save) [TARGET] [FILE]
.br .br
\fBgrimshot\fR check \fBgrimshot\fR check
.br .br
@ -26,12 +26,17 @@ grimshot - a helper for screenshots within sway
Show notifications to the user that a screenshot has been taken.\& Show notifications to the user that a screenshot has been taken.\&
.P .P
.RE .RE
\fB--cursor\fR
.RS 4
Include cursors in the screenshot.\&
.P
.RE
\fBsave\fR \fBsave\fR
.RS 4 .RS 4
Save the screenshot into a regular file.\& Grimshot will write images Save the screenshot into a regular file.\& Grimshot will write images
files to \fBXDG_SCREENSHOTS_DIR\fR if this is set (or defined files to \fBXDG_SCREENSHOTS_DIR\fR if this is set (or defined
in \fBuser-dirs.\&dir\fR), or otherwise fall back to \fBXDG_PICTURES_DIR\fR.\& in \fBuser-dirs.\&dir\fR), or otherwise fall back to \fBXDG_PICTURES_DIR\fR.\&
Set FILE to '-' to pipe the output to STDOUT.\& Set FILE to '\&-'\& to pipe the output to STDOUT.\&
.P .P
.RE .RE
\fBcopy\fR \fBcopy\fR

View file

@ -6,7 +6,7 @@ grimshot - a helper for screenshots within sway
# SYNOPSIS # SYNOPSIS
*grimshot* [--notify] (copy|save) [TARGET] [FILE]++ *grimshot* [--notify] [--cursor] (copy|save) [TARGET] [FILE]++
*grimshot* check++ *grimshot* check++
*grimshot* usage *grimshot* usage
@ -15,8 +15,11 @@ grimshot - a helper for screenshots within sway
*--notify* *--notify*
Show notifications to the user that a screenshot has been taken. Show notifications to the user that a screenshot has been taken.
*--cursor*
Include cursors in the screenshot.
*save* *save*
Save the screenshot into a regular file. Grimshot will write images Save the screenshot into a regular file. Grimshot will write image
files to *XDG_SCREENSHOTS_DIR* if this is set (or defined files to *XDG_SCREENSHOTS_DIR* if this is set (or defined
in *user-dirs.dir*), or otherwise fall back to *XDG_PICTURES_DIR*. in *user-dirs.dir*), or otherwise fall back to *XDG_PICTURES_DIR*.
Set FILE to '-' to pipe the output to STDOUT. Set FILE to '-' to pipe the output to STDOUT.

View file

@ -70,12 +70,18 @@ struct sway_mouse_binding {
char *command; char *command;
}; };
enum sway_switch_trigger {
SWAY_SWITCH_TRIGGER_OFF,
SWAY_SWITCH_TRIGGER_ON,
SWAY_SWITCH_TRIGGER_TOGGLE,
};
/** /**
* A laptop switch binding and an associated command. * A laptop switch binding and an associated command.
*/ */
struct sway_switch_binding { struct sway_switch_binding {
enum wlr_switch_type type; enum wlr_switch_type type;
enum wlr_switch_state state; enum sway_switch_trigger trigger;
uint32_t flags; uint32_t flags;
char *command; char *command;
}; };

View file

@ -1,7 +1,8 @@
#ifndef _SWAY_CRITERIA_H #ifndef _SWAY_CRITERIA_H
#define _SWAY_CRITERIA_H #define _SWAY_CRITERIA_H
#include <pcre.h> #define PCRE2_CODE_UNIT_WIDTH 8
#include <pcre2.h>
#include "config.h" #include "config.h"
#include "list.h" #include "list.h"
#include "tree/view.h" #include "tree/view.h"
@ -15,13 +16,13 @@ enum criteria_type {
}; };
enum pattern_type { enum pattern_type {
PATTERN_PCRE, PATTERN_PCRE2,
PATTERN_FOCUSED, PATTERN_FOCUSED,
}; };
struct pattern { struct pattern {
enum pattern_type match_type; enum pattern_type match_type;
pcre *regex; pcre2_code *regex;
}; };
struct criteria { struct criteria {

View file

@ -1,4 +1,4 @@
#include <wlr/types/wlr_surface.h> #include <wlr/types/wlr_compositor.h>
struct sway_container; struct sway_container;
struct sway_view; struct sway_view;

View file

@ -4,7 +4,7 @@
#include <stdint.h> #include <stdint.h>
#include <wlr/types/wlr_pointer_constraints_v1.h> #include <wlr/types/wlr_pointer_constraints_v1.h>
#include <wlr/types/wlr_pointer_gestures_v1.h> #include <wlr/types/wlr_pointer_gestures_v1.h>
#include <wlr/types/wlr_surface.h> #include <wlr/types/wlr_compositor.h>
#include "sway/input/seat.h" #include "sway/input/seat.h"
#include "config.h" #include "config.h"
@ -42,6 +42,8 @@ struct sway_cursor {
struct wl_listener swipe_begin; struct wl_listener swipe_begin;
struct wl_listener swipe_update; struct wl_listener swipe_update;
struct wl_listener swipe_end; struct wl_listener swipe_end;
struct wl_listener hold_begin;
struct wl_listener hold_end;
struct wl_listener motion; struct wl_listener motion;
struct wl_listener motion_absolute; struct wl_listener motion_absolute;
@ -110,7 +112,7 @@ void dispatch_cursor_button(struct sway_cursor *cursor,
enum wlr_button_state state); enum wlr_button_state state);
void dispatch_cursor_axis(struct sway_cursor *cursor, void dispatch_cursor_axis(struct sway_cursor *cursor,
struct wlr_event_pointer_axis *event); struct wlr_pointer_axis_event *event);
void cursor_set_image(struct sway_cursor *cursor, const char *image, void cursor_set_image(struct sway_cursor *cursor, const char *image,
struct wl_client *client); struct wl_client *client);

View file

@ -18,7 +18,7 @@ struct sway_seatop_impl {
enum wlr_button_state state); enum wlr_button_state state);
void (*pointer_motion)(struct sway_seat *seat, uint32_t time_msec); void (*pointer_motion)(struct sway_seat *seat, uint32_t time_msec);
void (*pointer_axis)(struct sway_seat *seat, void (*pointer_axis)(struct sway_seat *seat,
struct wlr_event_pointer_axis *event); struct wlr_pointer_axis_event *event);
void (*rebase)(struct sway_seat *seat, uint32_t time_msec); void (*rebase)(struct sway_seat *seat, uint32_t time_msec);
void (*tablet_tool_motion)(struct sway_seat *seat, void (*tablet_tool_motion)(struct sway_seat *seat,
struct sway_tablet_tool *tool, uint32_t time_msec); struct sway_tablet_tool *tool, uint32_t time_msec);
@ -274,7 +274,7 @@ void seatop_button(struct sway_seat *seat, uint32_t time_msec,
void seatop_pointer_motion(struct sway_seat *seat, uint32_t time_msec); void seatop_pointer_motion(struct sway_seat *seat, uint32_t time_msec);
void seatop_pointer_axis(struct sway_seat *seat, void seatop_pointer_axis(struct sway_seat *seat,
struct wlr_event_pointer_axis *event); struct wlr_pointer_axis_event *event);
void seatop_tablet_tool_tip(struct sway_seat *seat, void seatop_tablet_tool_tip(struct sway_seat *seat,
struct sway_tablet_tool *tool, uint32_t time_msec, struct sway_tablet_tool *tool, uint32_t time_msec,

View file

@ -3,7 +3,7 @@
#include <wlr/types/wlr_text_input_v3.h> #include <wlr/types/wlr_text_input_v3.h>
#include <wlr/types/wlr_input_method_v2.h> #include <wlr/types/wlr_input_method_v2.h>
#include <wlr/types/wlr_surface.h> #include <wlr/types/wlr_compositor.h>
#include "sway/input/seat.h" #include "sway/input/seat.h"
/** /**

View file

@ -1,7 +1,7 @@
#ifndef _SWAY_LAYERS_H #ifndef _SWAY_LAYERS_H
#define _SWAY_LAYERS_H #define _SWAY_LAYERS_H
#include <stdbool.h> #include <stdbool.h>
#include <wlr/types/wlr_surface.h> #include <wlr/types/wlr_compositor.h>
#include <wlr/types/wlr_layer_shell_v1.h> #include <wlr/types/wlr_layer_shell_v1.h>
enum layer_parent { enum layer_parent {

View file

@ -1,6 +1,6 @@
#ifndef _SWAY_SURFACE_H #ifndef _SWAY_SURFACE_H
#define _SWAY_SURFACE_H #define _SWAY_SURFACE_H
#include <wlr/types/wlr_surface.h> #include <wlr/types/wlr_compositor.h>
struct sway_surface { struct sway_surface {
struct wlr_surface *wlr_surface; struct wlr_surface *wlr_surface;

View file

@ -2,7 +2,7 @@
#define _SWAY_CONTAINER_H #define _SWAY_CONTAINER_H
#include <stdint.h> #include <stdint.h>
#include <sys/types.h> #include <sys/types.h>
#include <wlr/types/wlr_surface.h> #include <wlr/types/wlr_compositor.h>
#include "list.h" #include "list.h"
#include "sway/tree/node.h" #include "sway/tree/node.h"
@ -364,7 +364,7 @@ bool container_is_sticky_or_child(struct sway_container *con);
* This will destroy pairs of redundant H/V splits * This will destroy pairs of redundant H/V splits
* e.g. H[V[H[app app]] app] -> H[app app app] * e.g. H[V[H[app app]] app] -> H[app app app]
* The middle "V[H[" are eliminated by a call to container_squash * The middle "V[H[" are eliminated by a call to container_squash
* on the V[ con. It's grandchildren are added to it's parent. * on the V[ con. It's grandchildren are added to its parent.
* *
* This function is roughly equivalent to i3's tree_flatten here: * This function is roughly equivalent to i3's tree_flatten here:
* https://github.com/i3/i3/blob/1f0c628cde40cf87371481041b7197344e0417c6/src/tree.c#L651 * https://github.com/i3/i3/blob/1f0c628cde40cf87371481041b7197344e0417c6/src/tree.c#L651

View file

@ -1,7 +1,7 @@
#ifndef _SWAY_VIEW_H #ifndef _SWAY_VIEW_H
#define _SWAY_VIEW_H #define _SWAY_VIEW_H
#include <wayland-server-core.h> #include <wayland-server-core.h>
#include <wlr/types/wlr_surface.h> #include <wlr/types/wlr_compositor.h>
#include "config.h" #include "config.h"
#if HAVE_XWAYLAND #if HAVE_XWAYLAND
#include <wlr/xwayland.h> #include <wlr/xwayland.h>
@ -109,7 +109,7 @@ struct sway_view {
list_t *executed_criteria; // struct criteria * list_t *executed_criteria; // struct criteria *
union { union {
struct wlr_xdg_surface *wlr_xdg_surface; struct wlr_xdg_toplevel *wlr_xdg_toplevel;
#if HAVE_XWAYLAND #if HAVE_XWAYLAND
struct wlr_xwayland_surface *wlr_xwayland_surface; struct wlr_xwayland_surface *wlr_xwayland_surface;
#endif #endif
@ -170,6 +170,7 @@ struct sway_xwayland_unmanaged {
int lx, ly; int lx, ly;
struct wl_listener request_activate;
struct wl_listener request_configure; struct wl_listener request_configure;
struct wl_listener request_fullscreen; struct wl_listener request_fullscreen;
struct wl_listener commit; struct wl_listener commit;
@ -217,7 +218,7 @@ struct sway_subsurface {
struct sway_xdg_popup { struct sway_xdg_popup {
struct sway_view_child child; struct sway_view_child child;
struct wlr_xdg_surface *wlr_xdg_surface; struct wlr_xdg_popup *wlr_xdg_popup;
struct wl_listener new_popup; struct wl_listener new_popup;
struct wl_listener destroy; struct wl_listener destroy;

View file

@ -58,7 +58,6 @@ struct swaybar_output {
struct zxdg_output_v1 *xdg_output; struct zxdg_output_v1 *xdg_output;
struct wl_surface *surface; struct wl_surface *surface;
struct zwlr_layer_surface_v1 *layer_surface; struct zwlr_layer_surface_v1 *layer_surface;
struct wl_region *input_region;
uint32_t wl_name; uint32_t wl_name;
struct wl_list workspaces; // swaybar_workspace::link struct wl_list workspaces; // swaybar_workspace::link

View file

@ -67,7 +67,7 @@ struct swaynag_details {
int offset; int offset;
int visible_lines; int visible_lines;
int total_lines; int total_lines;
struct swaynag_button *button_details; struct swaynag_button button_details;
struct swaynag_button button_up; struct swaynag_button button_up;
struct swaynag_button button_down; struct swaynag_button button_down;
}; };

View file

@ -1,7 +1,7 @@
project( project(
'sway', 'sway',
'c', 'c',
version: '1.7', version: '1.8-dev',
license: 'MIT', license: 'MIT',
meson_version: '>=0.60.0', meson_version: '>=0.60.0',
default_options: [ default_options: [
@ -35,13 +35,23 @@ if is_freebsd
add_project_arguments('-D_C11_SOURCE', language: 'c') add_project_arguments('-D_C11_SOURCE', language: 'c')
endif endif
# Execute the wlroots subproject, if any
wlroots_version = ['>=0.16.0', '<0.17.0']
subproject(
'wlroots',
default_options: ['examples=false'],
required: false,
version: wlroots_version,
)
jsonc = dependency('json-c', version: '>=0.13') jsonc = dependency('json-c', version: '>=0.13')
pcre = dependency('libpcre') pcre2 = dependency('libpcre2-8')
wayland_server = dependency('wayland-server', version: '>=1.20.0') wayland_server = dependency('wayland-server', version: '>=1.20.0')
wayland_client = dependency('wayland-client') wayland_client = dependency('wayland-client')
wayland_cursor = dependency('wayland-cursor') wayland_cursor = dependency('wayland-cursor')
wayland_egl = dependency('wayland-egl') wayland_egl = dependency('wayland-egl')
wayland_protos = dependency('wayland-protocols', version: '>=1.24') wayland_protos = dependency('wayland-protocols', version: '>=1.24')
wlroots = dependency('wlroots', version: wlroots_version)
xkbcommon = dependency('xkbcommon') xkbcommon = dependency('xkbcommon')
cairo = dependency('cairo') cairo = dependency('cairo')
pango = dependency('pango') pango = dependency('pango')
@ -59,20 +69,7 @@ bash_comp = dependency('bash-completion', required: false)
fish_comp = dependency('fish', required: false) fish_comp = dependency('fish', required: false)
math = cc.find_library('m') math = cc.find_library('m')
rt = cc.find_library('rt') rt = cc.find_library('rt')
xcb_icccm = dependency('xcb-icccm', required: get_option('xwayland'))
# Try first to find wlroots as a subproject, then as a system dependency
wlroots_version = ['>=0.15.0', '<0.16.0']
wlroots_proj = subproject(
'wlroots',
default_options: ['examples=false'],
required: false,
version: wlroots_version,
)
if wlroots_proj.found()
wlroots = wlroots_proj.get_variable('wlroots')
else
wlroots = dependency('wlroots', version: wlroots_version)
endif
wlroots_features = { wlroots_features = {
'xwayland': false, 'xwayland': false,

View file

@ -47,7 +47,7 @@ static bool binding_switch_compare(struct sway_switch_binding *binding_a,
if (binding_a->type != binding_b->type) { if (binding_a->type != binding_b->type) {
return false; return false;
} }
if (binding_a->state != binding_b->state) { if (binding_a->trigger != binding_b->trigger) {
return false; return false;
} }
if ((binding_a->flags & BINDING_LOCKED) != if ((binding_a->flags & BINDING_LOCKED) !=
@ -551,11 +551,11 @@ struct cmd_results *cmd_bind_or_unbind_switch(int argc, char **argv,
"unknown switch %s)", bindtype, split->items[0]); "unknown switch %s)", bindtype, split->items[0]);
} }
if (strcmp(split->items[1], "on") == 0) { if (strcmp(split->items[1], "on") == 0) {
binding->state = WLR_SWITCH_STATE_ON; binding->trigger = SWAY_SWITCH_TRIGGER_ON;
} else if (strcmp(split->items[1], "off") == 0) { } else if (strcmp(split->items[1], "off") == 0) {
binding->state = WLR_SWITCH_STATE_OFF; binding->trigger = SWAY_SWITCH_TRIGGER_OFF;
} else if (strcmp(split->items[1], "toggle") == 0) { } else if (strcmp(split->items[1], "toggle") == 0) {
binding->state = WLR_SWITCH_STATE_TOGGLE; binding->trigger = SWAY_SWITCH_TRIGGER_TOGGLE;
} else { } else {
free_switch_binding(binding); free_switch_binding(binding);
return cmd_results_new(CMD_FAILURE, return cmd_results_new(CMD_FAILURE,

View file

@ -285,7 +285,7 @@ static struct cmd_results *focus_mode(struct sway_workspace *ws,
} }
} else { } else {
return cmd_results_new(CMD_FAILURE, return cmd_results_new(CMD_FAILURE,
"Failed to find a %s container in workspace", "Failed to find a %s container in workspace.",
floating ? "floating" : "tiling"); floating ? "floating" : "tiling");
} }
return cmd_results_new(CMD_SUCCESS, NULL); return cmd_results_new(CMD_SUCCESS, NULL);
@ -295,7 +295,7 @@ static struct cmd_results *focus_output(struct sway_seat *seat,
int argc, char **argv) { int argc, char **argv) {
if (!argc) { if (!argc) {
return cmd_results_new(CMD_INVALID, return cmd_results_new(CMD_INVALID,
"Expected 'focus output <direction|name>'"); "Expected 'focus output <direction|name>'.");
} }
char *identifier = join_args(argv, argc); char *identifier = join_args(argv, argc);
struct sway_output *output = output_by_name_or_id(identifier); struct sway_output *output = output_by_name_or_id(identifier);
@ -305,13 +305,13 @@ static struct cmd_results *focus_output(struct sway_seat *seat,
if (!parse_direction(identifier, &direction)) { if (!parse_direction(identifier, &direction)) {
free(identifier); free(identifier);
return cmd_results_new(CMD_INVALID, return cmd_results_new(CMD_INVALID,
"There is no output with that name"); "There is no output with that name.");
} }
struct sway_workspace *ws = seat_get_focused_workspace(seat); struct sway_workspace *ws = seat_get_focused_workspace(seat);
if (!ws) { if (!ws) {
free(identifier); free(identifier);
return cmd_results_new(CMD_FAILURE, return cmd_results_new(CMD_FAILURE,
"No focused workspace to base directions off of"); "No focused workspace to base directions off of.");
} }
output = output_get_in_direction(ws->output, direction); output = output_get_in_direction(ws->output, direction);
@ -375,10 +375,14 @@ struct cmd_results *cmd_focus(int argc, char **argv) {
struct sway_seat *seat = config->handler_context.seat; struct sway_seat *seat = config->handler_context.seat;
if (node->type < N_WORKSPACE) { if (node->type < N_WORKSPACE) {
return cmd_results_new(CMD_FAILURE, return cmd_results_new(CMD_FAILURE,
"Command 'focus' cannot be used above the workspace level"); "Command 'focus' cannot be used above the workspace level.");
} }
if (argc == 0 && container) { if (argc == 0) {
if (!container) {
return cmd_results_new(CMD_FAILURE, "No container to focus was specified.");
}
if (container_is_scratchpad_hidden_or_child(container)) { if (container_is_scratchpad_hidden_or_child(container)) {
root_scratchpad_show(container); root_scratchpad_show(container);
} }

View file

@ -1,5 +1,6 @@
#define _POSIX_C_SOURCE 200809L #define _POSIX_C_SOURCE 200809L
#include <assert.h> #include <assert.h>
#include <wlr/interfaces/wlr_keyboard.h>
#include "sway/config.h" #include "sway/config.h"
#include "sway/commands.h" #include "sway/commands.h"
#include "sway/input/input-manager.h" #include "sway/input/input-manager.h"

View file

@ -788,15 +788,15 @@ static struct cmd_results *cmd_move_to_position_pointer(
struct wlr_output *output = wlr_output_layout_output_at( struct wlr_output *output = wlr_output_layout_output_at(
root->output_layout, cursor->x, cursor->y); root->output_layout, cursor->x, cursor->y);
if (output) { if (output) {
struct wlr_box *box = struct wlr_box box;
wlr_output_layout_get_box(root->output_layout, output); wlr_output_layout_get_box(root->output_layout, output, &box);
lx = fmax(lx, box->x); lx = fmax(lx, box.x);
ly = fmax(ly, box->y); ly = fmax(ly, box.y);
if (lx + container->pending.width > box->x + box->width) { if (lx + container->pending.width > box.x + box.width) {
lx = box->x + box->width - container->pending.width; lx = box.x + box.width - container->pending.width;
} }
if (ly + container->pending.height > box->y + box->height) { if (ly + container->pending.height > box.y + box.height) {
ly = box->y + box->height - container->pending.height; ly = box.y + box.height - container->pending.height;
} }
} }

View file

@ -102,19 +102,19 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
} }
char *conf_path = dirname(conf); char *conf_path = dirname(conf);
char *rel_path = src; char *real_src = malloc(strlen(conf_path) + strlen(src) + 2);
src = malloc(strlen(conf_path) + strlen(src) + 2); if (!real_src) {
if (!src) { free(src);
free(rel_path);
free(conf); free(conf);
sway_log(SWAY_ERROR, "Unable to allocate memory"); sway_log(SWAY_ERROR, "Unable to allocate memory");
return cmd_results_new(CMD_FAILURE, return cmd_results_new(CMD_FAILURE,
"Unable to allocate resources"); "Unable to allocate resources");
} }
sprintf(src, "%s/%s", conf_path, rel_path); snprintf(real_src, strlen(conf_path) + strlen(src) + 2, "%s/%s", conf_path, src);
free(rel_path); free(src);
free(conf); free(conf);
src = real_src;
} }
bool can_access = access(src, F_OK) != -1; bool can_access = access(src, F_OK) != -1;

View file

@ -111,8 +111,8 @@ static struct cmd_results *press_or_release(struct sway_cursor *cursor,
: WLR_AXIS_ORIENTATION_HORIZONTAL; : WLR_AXIS_ORIENTATION_HORIZONTAL;
double delta = (button == SWAY_SCROLL_UP || button == SWAY_SCROLL_LEFT) double delta = (button == SWAY_SCROLL_UP || button == SWAY_SCROLL_LEFT)
? -1 : 1; ? -1 : 1;
struct wlr_event_pointer_axis event = { struct wlr_pointer_axis_event event = {
.device = NULL, .pointer = NULL,
.time_msec = 0, .time_msec = 0,
.source = WLR_AXIS_SOURCE_WHEEL, .source = WLR_AXIS_SOURCE_WHEEL,
.orientation = orientation, .orientation = orientation,

View file

@ -546,12 +546,12 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) {
} }
// Update output->{lx, ly, width, height} // Update output->{lx, ly, width, height}
struct wlr_box *output_box = struct wlr_box output_box;
wlr_output_layout_get_box(root->output_layout, wlr_output); wlr_output_layout_get_box(root->output_layout, wlr_output, &output_box);
output->lx = output_box->x; output->lx = output_box.x;
output->ly = output_box->y; output->ly = output_box.y;
output->width = output_box->width; output->width = output_box.width;
output->height = output_box->height; output->height = output_box.height;
if (!output->enabled) { if (!output->enabled) {
output_enable(output); output_enable(output);

View file

@ -3,7 +3,8 @@
#include <stdio.h> #include <stdio.h>
#include <stdbool.h> #include <stdbool.h>
#include <strings.h> #include <strings.h>
#include <pcre.h> #define PCRE2_CODE_UNIT_WIDTH 8
#include <pcre2.h>
#include "sway/criteria.h" #include "sway/criteria.h"
#include "sway/tree/container.h" #include "sway/tree/container.h"
#include "sway/config.h" #include "sway/config.h"
@ -40,17 +41,19 @@ bool criteria_is_empty(struct criteria *criteria) {
char *error = NULL; char *error = NULL;
// Returns error string on failure or NULL otherwise. // Returns error string on failure or NULL otherwise.
static bool generate_regex(pcre **regex, char *value) { static bool generate_regex(pcre2_code **regex, char *value) {
const char *reg_err; int errorcode;
int offset; PCRE2_SIZE offset;
*regex = pcre_compile(value, PCRE_UTF8 | PCRE_UCP, &reg_err, &offset, NULL);
*regex = pcre2_compile((PCRE2_SPTR)value, PCRE2_ZERO_TERMINATED, PCRE2_UTF | PCRE2_UCP, &errorcode, &offset, NULL);
if (!*regex) { if (!*regex) {
PCRE2_UCHAR buffer[256];
pcre2_get_error_message(errorcode, buffer, sizeof(buffer));
const char *fmt = "Regex compilation for '%s' failed: %s"; const char *fmt = "Regex compilation for '%s' failed: %s";
int len = strlen(fmt) + strlen(value) + strlen(reg_err) - 3; int len = strlen(fmt) + strlen(value) + strlen((char*) buffer) - 3;
error = malloc(len); error = malloc(len);
snprintf(error, len, fmt, value, reg_err); snprintf(error, len, fmt, value, buffer);
return false; return false;
} }
@ -66,7 +69,7 @@ static bool pattern_create(struct pattern **pattern, char *value) {
if (strcmp(value, "__focused__") == 0) { if (strcmp(value, "__focused__") == 0) {
(*pattern)->match_type = PATTERN_FOCUSED; (*pattern)->match_type = PATTERN_FOCUSED;
} else { } else {
(*pattern)->match_type = PATTERN_PCRE; (*pattern)->match_type = PATTERN_PCRE2;
if (!generate_regex(&(*pattern)->regex, value)) { if (!generate_regex(&(*pattern)->regex, value)) {
return false; return false;
}; };
@ -77,7 +80,7 @@ static bool pattern_create(struct pattern **pattern, char *value) {
static void pattern_destroy(struct pattern *pattern) { static void pattern_destroy(struct pattern *pattern) {
if (pattern) { if (pattern) {
if (pattern->regex) { if (pattern->regex) {
pcre_free(pattern->regex); pcre2_code_free(pattern->regex);
} }
free(pattern); free(pattern);
} }
@ -99,8 +102,11 @@ void criteria_destroy(struct criteria *criteria) {
free(criteria); free(criteria);
} }
static int regex_cmp(const char *item, const pcre *regex) { static int regex_cmp(const char *item, const pcre2_code *regex) {
return pcre_exec(regex, NULL, item, strlen(item), 0, 0, NULL, 0); pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(regex, NULL);
int result = pcre2_match(regex, (PCRE2_SPTR)item, strlen(item), 0, 0, match_data, NULL);
pcre2_match_data_free(match_data);
return result;
} }
#if HAVE_XWAYLAND #if HAVE_XWAYLAND
@ -155,7 +161,7 @@ static bool criteria_matches_container(struct criteria *criteria,
bool exists = false; bool exists = false;
struct sway_container *con = container; struct sway_container *con = container;
for (int i = 0; i < con->marks->length; ++i) { for (int i = 0; i < con->marks->length; ++i) {
if (regex_cmp(con->marks->items[i], criteria->con_mark->regex) == 0) { if (regex_cmp(con->marks->items[i], criteria->con_mark->regex) >= 0) {
exists = true; exists = true;
break; break;
} }
@ -192,8 +198,8 @@ static bool criteria_matches_view(struct criteria *criteria,
return false; return false;
} }
break; break;
case PATTERN_PCRE: case PATTERN_PCRE2:
if (regex_cmp(title, criteria->title->regex) != 0) { if (regex_cmp(title, criteria->title->regex) < 0) {
return false; return false;
} }
break; break;
@ -212,8 +218,8 @@ static bool criteria_matches_view(struct criteria *criteria,
return false; return false;
} }
break; break;
case PATTERN_PCRE: case PATTERN_PCRE2:
if (regex_cmp(shell, criteria->shell->regex) != 0) { if (regex_cmp(shell, criteria->shell->regex) < 0) {
return false; return false;
} }
break; break;
@ -232,8 +238,8 @@ static bool criteria_matches_view(struct criteria *criteria,
return false; return false;
} }
break; break;
case PATTERN_PCRE: case PATTERN_PCRE2:
if (regex_cmp(app_id, criteria->app_id->regex) != 0) { if (regex_cmp(app_id, criteria->app_id->regex) < 0) {
return false; return false;
} }
break; break;
@ -264,8 +270,8 @@ static bool criteria_matches_view(struct criteria *criteria,
return false; return false;
} }
break; break;
case PATTERN_PCRE: case PATTERN_PCRE2:
if (regex_cmp(class, criteria->class->regex) != 0) { if (regex_cmp(class, criteria->class->regex) < 0) {
return false; return false;
} }
break; break;
@ -284,8 +290,8 @@ static bool criteria_matches_view(struct criteria *criteria,
return false; return false;
} }
break; break;
case PATTERN_PCRE: case PATTERN_PCRE2:
if (regex_cmp(instance, criteria->instance->regex) != 0) { if (regex_cmp(instance, criteria->instance->regex) < 0) {
return false; return false;
} }
break; break;
@ -304,8 +310,8 @@ static bool criteria_matches_view(struct criteria *criteria,
return false; return false;
} }
break; break;
case PATTERN_PCRE: case PATTERN_PCRE2:
if (regex_cmp(window_role, criteria->window_role->regex) != 0) { if (regex_cmp(window_role, criteria->window_role->regex) < 0) {
return false; return false;
} }
break; break;
@ -363,8 +369,8 @@ static bool criteria_matches_view(struct criteria *criteria,
return false; return false;
} }
break; break;
case PATTERN_PCRE: case PATTERN_PCRE2:
if (regex_cmp(ws->name, criteria->workspace->regex) != 0) { if (regex_cmp(ws->name, criteria->workspace->regex) < 0) {
return false; return false;
} }
break; break;

View file

@ -6,10 +6,11 @@ void desktop_damage_surface(struct wlr_surface *surface, double lx, double ly,
bool whole) { bool whole) {
for (int i = 0; i < root->outputs->length; ++i) { for (int i = 0; i < root->outputs->length; ++i) {
struct sway_output *output = root->outputs->items[i]; struct sway_output *output = root->outputs->items[i];
struct wlr_box *output_box = wlr_output_layout_get_box( struct wlr_box output_box;
root->output_layout, output->wlr_output); wlr_output_layout_get_box(root->output_layout,
output_damage_surface(output, lx - output_box->x, output->wlr_output, &output_box);
ly - output_box->y, surface, whole); output_damage_surface(output, lx - output_box.x,
ly - output_box.y, surface, whole);
} }
} }

View file

@ -5,6 +5,7 @@
#include <wlr/types/wlr_layer_shell_v1.h> #include <wlr/types/wlr_layer_shell_v1.h>
#include <wlr/types/wlr_output_damage.h> #include <wlr/types/wlr_output_damage.h>
#include <wlr/types/wlr_output.h> #include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_subcompositor.h>
#include "log.h" #include "log.h"
#include "sway/desktop/transaction.h" #include "sway/desktop/transaction.h"
#include "sway/input/cursor.h" #include "sway/input/cursor.h"
@ -270,10 +271,6 @@ static void handle_output_destroy(struct wl_listener *listener, void *data) {
wl_resource_get_client(sway_layer->layer_surface->resource); wl_resource_get_client(sway_layer->layer_surface->resource);
bool set_focus = seat->exclusive_client == client; bool set_focus = seat->exclusive_client == client;
wl_list_remove(&sway_layer->output_destroy.link);
wl_list_remove(&sway_layer->link);
wl_list_init(&sway_layer->link);
if (set_focus) { if (set_focus) {
struct sway_layer_surface *layer = struct sway_layer_surface *layer =
find_mapped_layer_by_client(client, sway_layer->layer_surface->output); find_mapped_layer_by_client(client, sway_layer->layer_surface->output);
@ -282,7 +279,6 @@ static void handle_output_destroy(struct wl_listener *listener, void *data) {
} }
} }
sway_layer->layer_surface->output = NULL;
wlr_layer_surface_v1_destroy(sway_layer->layer_surface); wlr_layer_surface_v1_destroy(sway_layer->layer_surface);
} }
@ -291,10 +287,7 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) {
wl_container_of(listener, layer, surface_commit); wl_container_of(listener, layer, surface_commit);
struct wlr_layer_surface_v1 *layer_surface = layer->layer_surface; struct wlr_layer_surface_v1 *layer_surface = layer->layer_surface;
struct wlr_output *wlr_output = layer_surface->output; struct wlr_output *wlr_output = layer_surface->output;
if (wlr_output == NULL) { sway_assert(wlr_output, "wlr_layer_surface_v1 has null output");
return;
}
struct sway_output *output = wlr_output->data; struct sway_output *output = wlr_output->data;
struct wlr_box old_extent = layer->extent; struct wlr_box old_extent = layer->extent;
@ -341,13 +334,8 @@ static void unmap(struct sway_layer_surface *sway_layer) {
cursor_rebase_all(); cursor_rebase_all();
struct wlr_output *wlr_output = sway_layer->layer_surface->output; struct wlr_output *wlr_output = sway_layer->layer_surface->output;
if (wlr_output == NULL) { sway_assert(wlr_output, "wlr_layer_surface_v1 has null output");
return;
}
struct sway_output *output = wlr_output->data; struct sway_output *output = wlr_output->data;
if (output == NULL) {
return;
}
output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y, output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y,
sway_layer->layer_surface->surface, true); sway_layer->layer_surface->surface, true);
} }
@ -375,22 +363,24 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
wl_list_remove(&sway_layer->surface_commit.link); wl_list_remove(&sway_layer->surface_commit.link);
wl_list_remove(&sway_layer->new_popup.link); wl_list_remove(&sway_layer->new_popup.link);
wl_list_remove(&sway_layer->new_subsurface.link); wl_list_remove(&sway_layer->new_subsurface.link);
if (sway_layer->layer_surface->output != NULL) {
struct sway_output *output = sway_layer->layer_surface->output->data; struct wlr_output *wlr_output = sway_layer->layer_surface->output;
if (output != NULL) { sway_assert(wlr_output, "wlr_layer_surface_v1 has null output");
arrange_layers(output); struct sway_output *output = wlr_output->data;
transaction_commit_dirty(); arrange_layers(output);
} transaction_commit_dirty();
wl_list_remove(&sway_layer->output_destroy.link); wl_list_remove(&sway_layer->output_destroy.link);
sway_layer->layer_surface->output = NULL; sway_layer->layer_surface->output = NULL;
}
free(sway_layer); free(sway_layer);
} }
static void handle_map(struct wl_listener *listener, void *data) { static void handle_map(struct wl_listener *listener, void *data) {
struct sway_layer_surface *sway_layer = wl_container_of(listener, struct sway_layer_surface *sway_layer = wl_container_of(listener,
sway_layer, map); sway_layer, map);
struct sway_output *output = sway_layer->layer_surface->output->data; struct wlr_output *wlr_output = sway_layer->layer_surface->output;
sway_assert(wlr_output, "wlr_layer_surface_v1 has null output");
struct sway_output *output = wlr_output->data;
output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y, output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y,
sway_layer->layer_surface->surface, true); sway_layer->layer_surface->surface, true);
wlr_surface_send_enter(sway_layer->layer_surface->surface, wlr_surface_send_enter(sway_layer->layer_surface->surface,
@ -408,9 +398,7 @@ static void subsurface_damage(struct sway_layer_subsurface *subsurface,
bool whole) { bool whole) {
struct sway_layer_surface *layer = subsurface->layer_surface; struct sway_layer_surface *layer = subsurface->layer_surface;
struct wlr_output *wlr_output = layer->layer_surface->output; struct wlr_output *wlr_output = layer->layer_surface->output;
if (!wlr_output) { sway_assert(wlr_output, "wlr_layer_surface_v1 has null output");
return;
}
struct sway_output *output = wlr_output->data; struct sway_output *output = wlr_output->data;
int ox = subsurface->wlr_subsurface->current.x + layer->geo.x; int ox = subsurface->wlr_subsurface->current.x + layer->geo.x;
int oy = subsurface->wlr_subsurface->current.y + layer->geo.y; int oy = subsurface->wlr_subsurface->current.y + layer->geo.y;
@ -513,6 +501,7 @@ static void popup_damage(struct sway_layer_popup *layer_popup, bool whole) {
} }
} }
struct wlr_output *wlr_output = layer->layer_surface->output; struct wlr_output *wlr_output = layer->layer_surface->output;
sway_assert(wlr_output, "wlr_layer_surface_v1 has null output");
struct sway_output *output = wlr_output->data; struct sway_output *output = wlr_output->data;
output_damage_surface(output, ox, oy, surface, whole); output_damage_surface(output, ox, oy, surface, whole);
} }
@ -521,6 +510,7 @@ 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_popup *popup = wl_container_of(listener, popup, map);
struct sway_layer_surface *layer = popup_get_layer(popup); struct sway_layer_surface *layer = popup_get_layer(popup);
struct wlr_output *wlr_output = layer->layer_surface->output; struct wlr_output *wlr_output = layer->layer_surface->output;
sway_assert(wlr_output, "wlr_layer_surface_v1 has null output");
wlr_surface_send_enter(popup->wlr_popup->base->surface, wlr_output); wlr_surface_send_enter(popup->wlr_popup->base->surface, wlr_output);
popup_damage(popup, true); popup_damage(popup, true);
} }
@ -550,7 +540,9 @@ static void popup_unconstrain(struct sway_layer_popup *popup) {
struct sway_layer_surface *layer = popup_get_layer(popup); struct sway_layer_surface *layer = popup_get_layer(popup);
struct wlr_xdg_popup *wlr_popup = popup->wlr_popup; struct wlr_xdg_popup *wlr_popup = popup->wlr_popup;
struct sway_output *output = layer->layer_surface->output->data; struct wlr_output *wlr_output = layer->layer_surface->output;
sway_assert(wlr_output, "wlr_layer_surface_v1 has null output");
struct sway_output *output = wlr_output->data;
// the output box expressed in the coordinate system of the toplevel parent // the output box expressed in the coordinate system of the toplevel parent
// of the popup // of the popup
@ -642,6 +634,10 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
sway_log(SWAY_ERROR, sway_log(SWAY_ERROR,
"no output to auto-assign layer surface '%s' to", "no output to auto-assign layer surface '%s' to",
layer_surface->namespace); layer_surface->namespace);
// Note that layer_surface->output can be NULL
// here, but none of our destroy callbacks are
// registered yet so we don't have to make them
// handle that case.
wlr_layer_surface_v1_destroy(layer_surface); wlr_layer_surface_v1_destroy(layer_surface);
return; return;
} }

View file

@ -14,7 +14,7 @@
#include <wlr/types/wlr_output_layout.h> #include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_output.h> #include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_presentation_time.h> #include <wlr/types/wlr_presentation_time.h>
#include <wlr/types/wlr_surface.h> #include <wlr/types/wlr_compositor.h>
#include <wlr/util/region.h> #include <wlr/util/region.h>
#include "config.h" #include "config.h"
#include "log.h" #include "log.h"
@ -737,14 +737,15 @@ static void update_output_manager_config(struct sway_server *server) {
} }
struct wlr_output_configuration_head_v1 *config_head = struct wlr_output_configuration_head_v1 *config_head =
wlr_output_configuration_head_v1_create(config, output->wlr_output); wlr_output_configuration_head_v1_create(config, output->wlr_output);
struct wlr_box *output_box = wlr_output_layout_get_box( struct wlr_box output_box;
root->output_layout, output->wlr_output); wlr_output_layout_get_box(root->output_layout,
output->wlr_output, &output_box);
// We mark the output enabled even if it is switched off by DPMS // We mark the output enabled even if it is switched off by DPMS
config_head->state.enabled = output->current_mode != NULL && output->enabled; config_head->state.enabled = output->current_mode != NULL && output->enabled;
config_head->state.mode = output->current_mode; config_head->state.mode = output->current_mode;
if (output_box) { if (!wlr_box_empty(&output_box)) {
config_head->state.x = output_box->x; config_head->state.x = output_box.x;
config_head->state.y = output_box->y; config_head->state.y = output_box.y;
} }
} }

View file

@ -12,7 +12,7 @@
#include <wlr/types/wlr_output_damage.h> #include <wlr/types/wlr_output_damage.h>
#include <wlr/types/wlr_output_layout.h> #include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_output.h> #include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_surface.h> #include <wlr/types/wlr_compositor.h>
#include <wlr/util/region.h> #include <wlr/util/region.h>
#include "log.h" #include "log.h"
#include "config.h" #include "config.h"

View file

@ -1,7 +1,7 @@
#define _POSIX_C_SOURCE 200112L #define _POSIX_C_SOURCE 200112L
#include <stdlib.h> #include <stdlib.h>
#include <time.h> #include <time.h>
#include <wlr/types/wlr_surface.h> #include <wlr/types/wlr_compositor.h>
#include "sway/server.h" #include "sway/server.h"
#include "sway/surface.h" #include "sway/surface.h"

View file

@ -24,11 +24,11 @@ static const struct sway_view_child_impl popup_impl;
static void popup_get_view_coords(struct sway_view_child *child, static void popup_get_view_coords(struct sway_view_child *child,
int *sx, int *sy) { int *sx, int *sy) {
struct sway_xdg_popup *popup = (struct sway_xdg_popup *)child; struct sway_xdg_popup *popup = (struct sway_xdg_popup *)child;
struct wlr_xdg_surface *surface = popup->wlr_xdg_surface; struct wlr_xdg_popup *wlr_popup = popup->wlr_xdg_popup;
wlr_xdg_popup_get_toplevel_coords(surface->popup, wlr_xdg_popup_get_toplevel_coords(wlr_popup,
surface->popup->geometry.x - surface->current.geometry.x, wlr_popup->geometry.x - wlr_popup->base->current.geometry.x,
surface->popup->geometry.y - surface->current.geometry.y, wlr_popup->geometry.y - wlr_popup->base->current.geometry.y,
sx, sy); sx, sy);
} }
@ -65,7 +65,7 @@ static void popup_handle_destroy(struct wl_listener *listener, void *data) {
static void popup_unconstrain(struct sway_xdg_popup *popup) { static void popup_unconstrain(struct sway_xdg_popup *popup) {
struct sway_view *view = popup->child.view; struct sway_view *view = popup->child.view;
struct wlr_xdg_popup *wlr_popup = popup->wlr_xdg_surface->popup; struct wlr_xdg_popup *wlr_popup = popup->wlr_xdg_popup;
struct sway_output *output = view->container->pending.workspace->output; struct sway_output *output = view->container->pending.workspace->output;
@ -91,7 +91,7 @@ static struct sway_xdg_popup *popup_create(
return NULL; return NULL;
} }
view_child_init(&popup->child, &popup_impl, view, xdg_surface->surface); view_child_init(&popup->child, &popup_impl, view, xdg_surface->surface);
popup->wlr_xdg_surface = xdg_surface; popup->wlr_xdg_popup = xdg_surface->popup;
wl_signal_add(&xdg_surface->events.new_popup, &popup->new_popup); wl_signal_add(&xdg_surface->events.new_popup, &popup->new_popup);
popup->new_popup.notify = popup_handle_new_popup; popup->new_popup.notify = popup_handle_new_popup;
@ -119,7 +119,7 @@ static struct sway_xdg_shell_view *xdg_shell_view_from_view(
static void get_constraints(struct sway_view *view, double *min_width, static void get_constraints(struct sway_view *view, double *min_width,
double *max_width, double *min_height, double *max_height) { double *max_width, double *min_height, double *max_height) {
struct wlr_xdg_toplevel_state *state = struct wlr_xdg_toplevel_state *state =
&view->wlr_xdg_surface->toplevel->current; &view->wlr_xdg_toplevel->current;
*min_width = state->min_width > 0 ? state->min_width : DBL_MIN; *min_width = state->min_width > 0 ? state->min_width : DBL_MIN;
*max_width = state->max_width > 0 ? state->max_width : DBL_MAX; *max_width = state->max_width > 0 ? state->max_width : DBL_MAX;
*min_height = state->min_height > 0 ? state->min_height : DBL_MIN; *min_height = state->min_height > 0 ? state->min_height : DBL_MIN;
@ -133,9 +133,9 @@ static const char *get_string_prop(struct sway_view *view,
} }
switch (prop) { switch (prop) {
case VIEW_PROP_TITLE: case VIEW_PROP_TITLE:
return view->wlr_xdg_surface->toplevel->title; return view->wlr_xdg_toplevel->title;
case VIEW_PROP_APP_ID: case VIEW_PROP_APP_ID:
return view->wlr_xdg_surface->toplevel->app_id; return view->wlr_xdg_toplevel->app_id;
default: default:
return NULL; return NULL;
} }
@ -148,50 +148,45 @@ static uint32_t configure(struct sway_view *view, double lx, double ly,
if (xdg_shell_view == NULL) { if (xdg_shell_view == NULL) {
return 0; return 0;
} }
return wlr_xdg_toplevel_set_size(view->wlr_xdg_surface, width, height); return wlr_xdg_toplevel_set_size(view->wlr_xdg_toplevel,
width, height);
} }
static void set_activated(struct sway_view *view, bool activated) { static void set_activated(struct sway_view *view, bool activated) {
if (xdg_shell_view_from_view(view) == NULL) { if (xdg_shell_view_from_view(view) == NULL) {
return; return;
} }
struct wlr_xdg_surface *surface = view->wlr_xdg_surface; wlr_xdg_toplevel_set_activated(view->wlr_xdg_toplevel, activated);
if (surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
wlr_xdg_toplevel_set_activated(surface, activated);
}
} }
static void set_tiled(struct sway_view *view, bool tiled) { static void set_tiled(struct sway_view *view, bool tiled) {
if (xdg_shell_view_from_view(view) == NULL) { if (xdg_shell_view_from_view(view) == NULL) {
return; return;
} }
struct wlr_xdg_surface *surface = view->wlr_xdg_surface;
enum wlr_edges edges = WLR_EDGE_NONE; enum wlr_edges edges = WLR_EDGE_NONE;
if (tiled) { if (tiled) {
edges = WLR_EDGE_LEFT | WLR_EDGE_RIGHT | WLR_EDGE_TOP | edges = WLR_EDGE_LEFT | WLR_EDGE_RIGHT | WLR_EDGE_TOP |
WLR_EDGE_BOTTOM; WLR_EDGE_BOTTOM;
} }
wlr_xdg_toplevel_set_tiled(surface, edges); wlr_xdg_toplevel_set_tiled(view->wlr_xdg_toplevel, edges);
} }
static void set_fullscreen(struct sway_view *view, bool fullscreen) { static void set_fullscreen(struct sway_view *view, bool fullscreen) {
if (xdg_shell_view_from_view(view) == NULL) { if (xdg_shell_view_from_view(view) == NULL) {
return; return;
} }
struct wlr_xdg_surface *surface = view->wlr_xdg_surface; wlr_xdg_toplevel_set_fullscreen(view->wlr_xdg_toplevel, fullscreen);
wlr_xdg_toplevel_set_fullscreen(surface, fullscreen);
} }
static void set_resizing(struct sway_view *view, bool resizing) { static void set_resizing(struct sway_view *view, bool resizing) {
if (xdg_shell_view_from_view(view) == NULL) { if (xdg_shell_view_from_view(view) == NULL) {
return; return;
} }
struct wlr_xdg_surface *surface = view->wlr_xdg_surface; wlr_xdg_toplevel_set_resizing(view->wlr_xdg_toplevel, resizing);
wlr_xdg_toplevel_set_resizing(surface, resizing);
} }
static bool wants_floating(struct sway_view *view) { static bool wants_floating(struct sway_view *view) {
struct wlr_xdg_toplevel *toplevel = view->wlr_xdg_surface->toplevel; struct wlr_xdg_toplevel *toplevel = view->wlr_xdg_toplevel;
struct wlr_xdg_toplevel_state *state = &toplevel->current; struct wlr_xdg_toplevel_state *state = &toplevel->current;
return (state->min_width != 0 && state->min_height != 0 return (state->min_width != 0 && state->min_height != 0
&& (state->min_width == state->max_width && (state->min_width == state->max_width
@ -204,7 +199,7 @@ static void for_each_surface(struct sway_view *view,
if (xdg_shell_view_from_view(view) == NULL) { if (xdg_shell_view_from_view(view) == NULL) {
return; return;
} }
wlr_xdg_surface_for_each_surface(view->wlr_xdg_surface, iterator, wlr_xdg_surface_for_each_surface(view->wlr_xdg_toplevel->base, iterator,
user_data); user_data);
} }
@ -213,8 +208,8 @@ static void for_each_popup_surface(struct sway_view *view,
if (xdg_shell_view_from_view(view) == NULL) { if (xdg_shell_view_from_view(view) == NULL) {
return; return;
} }
wlr_xdg_surface_for_each_popup_surface(view->wlr_xdg_surface, iterator, wlr_xdg_surface_for_each_popup_surface(view->wlr_xdg_toplevel->base,
user_data); iterator, user_data);
} }
static bool is_transient_for(struct sway_view *child, static bool is_transient_for(struct sway_view *child,
@ -222,12 +217,12 @@ static bool is_transient_for(struct sway_view *child,
if (xdg_shell_view_from_view(child) == NULL) { if (xdg_shell_view_from_view(child) == NULL) {
return false; return false;
} }
struct wlr_xdg_surface *surface = child->wlr_xdg_surface; struct wlr_xdg_toplevel *toplevel = child->wlr_xdg_toplevel;
while (surface && surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) { while (toplevel) {
if (surface->toplevel->parent == ancestor->wlr_xdg_surface) { if (toplevel->parent == ancestor->wlr_xdg_toplevel) {
return true; return true;
} }
surface = surface->toplevel->parent; toplevel = toplevel->parent;
} }
return false; return false;
} }
@ -236,17 +231,13 @@ static void _close(struct sway_view *view) {
if (xdg_shell_view_from_view(view) == NULL) { if (xdg_shell_view_from_view(view) == NULL) {
return; return;
} }
struct wlr_xdg_surface *surface = view->wlr_xdg_surface; wlr_xdg_toplevel_send_close(view->wlr_xdg_toplevel);
if (surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL
&& surface->toplevel) {
wlr_xdg_toplevel_send_close(surface);
}
} }
static void close_popups(struct sway_view *view) { static void close_popups(struct sway_view *view) {
struct wlr_xdg_popup *popup, *tmp; struct wlr_xdg_popup *popup, *tmp;
wl_list_for_each_safe(popup, tmp, &view->wlr_xdg_surface->popups, link) { wl_list_for_each_safe(popup, tmp, &view->wlr_xdg_toplevel->base->popups, link) {
wlr_xdg_popup_destroy(popup->base); wlr_xdg_popup_destroy(popup);
} }
} }
@ -280,7 +271,7 @@ static void handle_commit(struct wl_listener *listener, void *data) {
struct sway_xdg_shell_view *xdg_shell_view = struct sway_xdg_shell_view *xdg_shell_view =
wl_container_of(listener, xdg_shell_view, commit); wl_container_of(listener, xdg_shell_view, commit);
struct sway_view *view = &xdg_shell_view->view; struct sway_view *view = &xdg_shell_view->view;
struct wlr_xdg_surface *xdg_surface = view->wlr_xdg_surface; struct wlr_xdg_surface *xdg_surface = view->wlr_xdg_toplevel->base;
struct wlr_box new_geo; struct wlr_box new_geo;
wlr_xdg_surface_get_geometry(xdg_surface, &new_geo); wlr_xdg_surface_get_geometry(xdg_surface, &new_geo);
@ -337,23 +328,17 @@ static void handle_new_popup(struct wl_listener *listener, void *data) {
static void handle_request_fullscreen(struct wl_listener *listener, void *data) { static void handle_request_fullscreen(struct wl_listener *listener, void *data) {
struct sway_xdg_shell_view *xdg_shell_view = struct sway_xdg_shell_view *xdg_shell_view =
wl_container_of(listener, xdg_shell_view, request_fullscreen); wl_container_of(listener, xdg_shell_view, request_fullscreen);
struct wlr_xdg_toplevel_set_fullscreen_event *e = data; struct wlr_xdg_toplevel *toplevel = xdg_shell_view->view.wlr_xdg_toplevel;
struct wlr_xdg_surface *xdg_surface =
xdg_shell_view->view.wlr_xdg_surface;
struct sway_view *view = &xdg_shell_view->view; struct sway_view *view = &xdg_shell_view->view;
if (!sway_assert(xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL, if (!toplevel->base->mapped) {
"xdg_shell requested fullscreen of surface with role %i",
xdg_surface->role)) {
return;
}
if (!xdg_surface->mapped) {
return; return;
} }
struct sway_container *container = view->container; struct sway_container *container = view->container;
if (e->fullscreen && e->output && e->output->data) { struct wlr_xdg_toplevel_requested *req = &toplevel->requested;
struct sway_output *output = e->output->data; if (req->fullscreen && req->fullscreen_output && req->fullscreen_output->data) {
struct sway_output *output = req->fullscreen_output->data;
struct sway_workspace *ws = output_get_active_workspace(output); struct sway_workspace *ws = output_get_active_workspace(output);
if (ws && !container_is_scratchpad_hidden(container) && if (ws && !container_is_scratchpad_hidden(container) &&
container->pending.workspace != ws) { container->pending.workspace != ws) {
@ -365,7 +350,7 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data)
} }
} }
container_set_fullscreen(container, e->fullscreen); container_set_fullscreen(container, req->fullscreen);
arrange_root(); arrange_root();
transaction_commit_dirty(); transaction_commit_dirty();
@ -375,7 +360,8 @@ static void handle_request_move(struct wl_listener *listener, void *data) {
struct sway_xdg_shell_view *xdg_shell_view = struct sway_xdg_shell_view *xdg_shell_view =
wl_container_of(listener, xdg_shell_view, request_move); wl_container_of(listener, xdg_shell_view, request_move);
struct sway_view *view = &xdg_shell_view->view; struct sway_view *view = &xdg_shell_view->view;
if (!container_is_floating(view->container)) { if (!container_is_floating(view->container) ||
view->container->pending.fullscreen_mode) {
return; return;
} }
struct wlr_xdg_toplevel_move_event *e = data; struct wlr_xdg_toplevel_move_event *e = data;
@ -423,13 +409,13 @@ static void handle_map(struct wl_listener *listener, void *data) {
struct sway_xdg_shell_view *xdg_shell_view = struct sway_xdg_shell_view *xdg_shell_view =
wl_container_of(listener, xdg_shell_view, map); wl_container_of(listener, xdg_shell_view, map);
struct sway_view *view = &xdg_shell_view->view; struct sway_view *view = &xdg_shell_view->view;
struct wlr_xdg_surface *xdg_surface = view->wlr_xdg_surface; struct wlr_xdg_toplevel *toplevel = view->wlr_xdg_toplevel;
view->natural_width = view->wlr_xdg_surface->current.geometry.width; view->natural_width = toplevel->base->current.geometry.width;
view->natural_height = view->wlr_xdg_surface->current.geometry.height; view->natural_height = toplevel->base->current.geometry.height;
if (!view->natural_width && !view->natural_height) { if (!view->natural_width && !view->natural_height) {
view->natural_width = view->wlr_xdg_surface->surface->current.width; view->natural_width = toplevel->base->surface->current.width;
view->natural_height = view->wlr_xdg_surface->surface->current.height; view->natural_height = toplevel->base->surface->current.height;
} }
bool csd = false; bool csd = false;
@ -440,44 +426,44 @@ static void handle_map(struct wl_listener *listener, void *data) {
csd = mode == WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE; csd = mode == WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE;
} else { } else {
struct sway_server_decoration *deco = struct sway_server_decoration *deco =
decoration_from_surface(xdg_surface->surface); decoration_from_surface(toplevel->base->surface);
csd = !deco || deco->wlr_server_decoration->mode == csd = !deco || deco->wlr_server_decoration->mode ==
WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT; WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT;
} }
view_map(view, view->wlr_xdg_surface->surface, view_map(view, toplevel->base->surface,
xdg_surface->toplevel->requested.fullscreen, toplevel->requested.fullscreen,
xdg_surface->toplevel->requested.fullscreen_output, toplevel->requested.fullscreen_output,
csd); csd);
transaction_commit_dirty(); transaction_commit_dirty();
xdg_shell_view->commit.notify = handle_commit; xdg_shell_view->commit.notify = handle_commit;
wl_signal_add(&xdg_surface->surface->events.commit, wl_signal_add(&toplevel->base->surface->events.commit,
&xdg_shell_view->commit); &xdg_shell_view->commit);
xdg_shell_view->new_popup.notify = handle_new_popup; xdg_shell_view->new_popup.notify = handle_new_popup;
wl_signal_add(&xdg_surface->events.new_popup, wl_signal_add(&toplevel->base->events.new_popup,
&xdg_shell_view->new_popup); &xdg_shell_view->new_popup);
xdg_shell_view->request_fullscreen.notify = handle_request_fullscreen; xdg_shell_view->request_fullscreen.notify = handle_request_fullscreen;
wl_signal_add(&xdg_surface->toplevel->events.request_fullscreen, wl_signal_add(&toplevel->events.request_fullscreen,
&xdg_shell_view->request_fullscreen); &xdg_shell_view->request_fullscreen);
xdg_shell_view->request_move.notify = handle_request_move; xdg_shell_view->request_move.notify = handle_request_move;
wl_signal_add(&xdg_surface->toplevel->events.request_move, wl_signal_add(&toplevel->events.request_move,
&xdg_shell_view->request_move); &xdg_shell_view->request_move);
xdg_shell_view->request_resize.notify = handle_request_resize; xdg_shell_view->request_resize.notify = handle_request_resize;
wl_signal_add(&xdg_surface->toplevel->events.request_resize, wl_signal_add(&toplevel->events.request_resize,
&xdg_shell_view->request_resize); &xdg_shell_view->request_resize);
xdg_shell_view->set_title.notify = handle_set_title; xdg_shell_view->set_title.notify = handle_set_title;
wl_signal_add(&xdg_surface->toplevel->events.set_title, wl_signal_add(&toplevel->events.set_title,
&xdg_shell_view->set_title); &xdg_shell_view->set_title);
xdg_shell_view->set_app_id.notify = handle_set_app_id; xdg_shell_view->set_app_id.notify = handle_set_app_id;
wl_signal_add(&xdg_surface->toplevel->events.set_app_id, wl_signal_add(&toplevel->events.set_app_id,
&xdg_shell_view->set_app_id); &xdg_shell_view->set_app_id);
} }
@ -491,7 +477,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
wl_list_remove(&xdg_shell_view->destroy.link); wl_list_remove(&xdg_shell_view->destroy.link);
wl_list_remove(&xdg_shell_view->map.link); wl_list_remove(&xdg_shell_view->map.link);
wl_list_remove(&xdg_shell_view->unmap.link); wl_list_remove(&xdg_shell_view->unmap.link);
view->wlr_xdg_surface = NULL; view->wlr_xdg_toplevel = NULL;
if (view->xdg_decoration) { if (view->xdg_decoration) {
view->xdg_decoration->view = NULL; view->xdg_decoration->view = NULL;
} }
@ -522,7 +508,7 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data) {
} }
view_init(&xdg_shell_view->view, SWAY_VIEW_XDG_SHELL, &view_impl); view_init(&xdg_shell_view->view, SWAY_VIEW_XDG_SHELL, &view_impl);
xdg_shell_view->view.wlr_xdg_surface = xdg_surface; xdg_shell_view->view.wlr_xdg_toplevel = xdg_surface->toplevel;
xdg_shell_view->map.notify = handle_map; xdg_shell_view->map.notify = handle_map;
wl_signal_add(&xdg_surface->events.map, &xdg_shell_view->map); wl_signal_add(&xdg_surface->events.map, &xdg_shell_view->map);

View file

@ -6,6 +6,7 @@
#include <wlr/types/wlr_output_layout.h> #include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_output.h> #include <wlr/types/wlr_output.h>
#include <wlr/xwayland.h> #include <wlr/xwayland.h>
#include <xcb/xcb_icccm.h>
#include "log.h" #include "log.h"
#include "sway/desktop.h" #include "sway/desktop.h"
#include "sway/desktop/transaction.h" #include "sway/desktop/transaction.h"
@ -121,6 +122,20 @@ static void unmanaged_handle_unmap(struct wl_listener *listener, void *data) {
} }
} }
static void unmanaged_handle_request_activate(struct wl_listener *listener, void *data) {
struct wlr_xwayland_surface *xsurface = data;
if (!xsurface->mapped) {
return;
}
struct sway_seat *seat = input_manager_current_seat();
struct sway_container *focus = seat_get_focused_container(seat);
if (focus && focus->view && focus->view->pid != xsurface->pid) {
return;
}
seat_set_focus_surface(seat, xsurface->surface, false);
}
static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) { static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) {
struct sway_xwayland_unmanaged *surface = struct sway_xwayland_unmanaged *surface =
wl_container_of(listener, surface, destroy); wl_container_of(listener, surface, destroy);
@ -129,6 +144,7 @@ static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) {
wl_list_remove(&surface->unmap.link); wl_list_remove(&surface->unmap.link);
wl_list_remove(&surface->destroy.link); wl_list_remove(&surface->destroy.link);
wl_list_remove(&surface->override_redirect.link); wl_list_remove(&surface->override_redirect.link);
wl_list_remove(&surface->request_activate.link);
free(surface); free(surface);
} }
@ -176,6 +192,8 @@ static struct sway_xwayland_unmanaged *create_unmanaged(
surface->destroy.notify = unmanaged_handle_destroy; surface->destroy.notify = unmanaged_handle_destroy;
wl_signal_add(&xsurface->events.set_override_redirect, &surface->override_redirect); wl_signal_add(&xsurface->events.set_override_redirect, &surface->override_redirect);
surface->override_redirect.notify = unmanaged_handle_override_redirect; surface->override_redirect.notify = unmanaged_handle_override_redirect;
wl_signal_add(&xsurface->events.request_activate, &surface->request_activate);
surface->request_activate.notify = unmanaged_handle_request_activate;
return surface; return surface;
} }
@ -294,7 +312,7 @@ static bool wants_floating(struct sway_view *view) {
} }
} }
struct wlr_xwayland_surface_size_hints *size_hints = surface->size_hints; xcb_size_hints_t *size_hints = surface->size_hints;
if (size_hints != NULL && if (size_hints != NULL &&
size_hints->min_width > 0 && size_hints->min_height > 0 && size_hints->min_width > 0 && size_hints->min_height > 0 &&
(size_hints->max_width == size_hints->min_width || (size_hints->max_width == size_hints->min_width ||
@ -348,7 +366,7 @@ static void destroy(struct sway_view *view) {
static void get_constraints(struct sway_view *view, double *min_width, static void get_constraints(struct sway_view *view, double *min_width,
double *max_width, double *min_height, double *max_height) { double *max_width, double *min_height, double *max_height) {
struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface; struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface;
struct wlr_xwayland_surface_size_hints *size_hints = surface->size_hints; xcb_size_hints_t *size_hints = surface->size_hints;
if (size_hints == NULL) { if (size_hints == NULL) {
*min_width = DBL_MIN; *min_width = DBL_MIN;
@ -577,7 +595,8 @@ static void handle_request_move(struct wl_listener *listener, void *data) {
if (!xsurface->mapped) { if (!xsurface->mapped) {
return; return;
} }
if (!container_is_floating(view->container)) { if (!container_is_floating(view->container) ||
view->container->pending.fullscreen_mode) {
return; return;
} }
struct sway_seat *seat = input_manager_current_seat(); struct sway_seat *seat = input_manager_current_seat();
@ -666,14 +685,15 @@ static void handle_set_hints(struct wl_listener *listener, void *data) {
if (!xsurface->mapped) { if (!xsurface->mapped) {
return; return;
} }
if (!xsurface->hints_urgency && view->urgent_timer) { const bool hints_urgency = xcb_icccm_wm_hints_get_urgency(xsurface->hints);
if (!hints_urgency && view->urgent_timer) {
// The view is in the timeout period. We'll ignore the request to // The view is in the timeout period. We'll ignore the request to
// unset urgency so that the view remains urgent until the timer clears // unset urgency so that the view remains urgent until the timer clears
// it. // it.
return; return;
} }
if (view->allow_request_urgent) { if (view->allow_request_urgent) {
view_set_urgent(view, (bool)xsurface->hints_urgency); view_set_urgent(view, hints_urgency);
} }
} }

View file

@ -386,28 +386,29 @@ static void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec,
static void handle_pointer_motion_relative( static void handle_pointer_motion_relative(
struct wl_listener *listener, void *data) { struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = wl_container_of(listener, cursor, motion); struct sway_cursor *cursor = wl_container_of(listener, cursor, motion);
struct wlr_event_pointer_motion *e = data; struct wlr_pointer_motion_event *e = data;
cursor_handle_activity_from_device(cursor, e->device); cursor_handle_activity_from_device(cursor, &e->pointer->base);
pointer_motion(cursor, e->time_msec, e->device, e->delta_x, e->delta_y, pointer_motion(cursor, e->time_msec, &e->pointer->base, e->delta_x,
e->unaccel_dx, e->unaccel_dy); e->delta_y, e->unaccel_dx, e->unaccel_dy);
} }
static void handle_pointer_motion_absolute( static void handle_pointer_motion_absolute(
struct wl_listener *listener, void *data) { struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = struct sway_cursor *cursor =
wl_container_of(listener, cursor, motion_absolute); wl_container_of(listener, cursor, motion_absolute);
struct wlr_event_pointer_motion_absolute *event = data; struct wlr_pointer_motion_absolute_event *event = data;
cursor_handle_activity_from_device(cursor, event->device); cursor_handle_activity_from_device(cursor, &event->pointer->base);
double lx, ly; double lx, ly;
wlr_cursor_absolute_to_layout_coords(cursor->cursor, event->device, wlr_cursor_absolute_to_layout_coords(cursor->cursor, &event->pointer->base,
event->x, event->y, &lx, &ly); event->x, event->y, &lx, &ly);
double dx = lx - cursor->cursor->x; double dx = lx - cursor->cursor->x;
double dy = ly - cursor->cursor->y; double dy = ly - cursor->cursor->y;
pointer_motion(cursor, event->time_msec, event->device, dx, dy, dx, dy); pointer_motion(cursor, event->time_msec, &event->pointer->base, dx, dy,
dx, dy);
} }
void dispatch_cursor_button(struct sway_cursor *cursor, void dispatch_cursor_button(struct sway_cursor *cursor,
@ -422,7 +423,7 @@ void dispatch_cursor_button(struct sway_cursor *cursor,
static void handle_pointer_button(struct wl_listener *listener, void *data) { static void handle_pointer_button(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = wl_container_of(listener, cursor, button); struct sway_cursor *cursor = wl_container_of(listener, cursor, button);
struct wlr_event_pointer_button *event = data; struct wlr_pointer_button_event *event = data;
if (event->state == WLR_BUTTON_PRESSED) { if (event->state == WLR_BUTTON_PRESSED) {
cursor->pressed_button_count++; cursor->pressed_button_count++;
@ -434,20 +435,20 @@ static void handle_pointer_button(struct wl_listener *listener, void *data) {
} }
} }
cursor_handle_activity_from_device(cursor, event->device); cursor_handle_activity_from_device(cursor, &event->pointer->base);
dispatch_cursor_button(cursor, event->device, dispatch_cursor_button(cursor, &event->pointer->base,
event->time_msec, event->button, event->state); event->time_msec, event->button, event->state);
} }
void dispatch_cursor_axis(struct sway_cursor *cursor, void dispatch_cursor_axis(struct sway_cursor *cursor,
struct wlr_event_pointer_axis *event) { struct wlr_pointer_axis_event *event) {
seatop_pointer_axis(cursor->seat, event); seatop_pointer_axis(cursor->seat, event);
} }
static void handle_pointer_axis(struct wl_listener *listener, void *data) { static void handle_pointer_axis(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = wl_container_of(listener, cursor, axis); struct sway_cursor *cursor = wl_container_of(listener, cursor, axis);
struct wlr_event_pointer_axis *event = data; struct wlr_pointer_axis_event *event = data;
cursor_handle_activity_from_device(cursor, event->device); cursor_handle_activity_from_device(cursor, &event->pointer->base);
dispatch_cursor_axis(cursor, event); dispatch_cursor_axis(cursor, event);
} }
@ -458,8 +459,8 @@ static void handle_pointer_frame(struct wl_listener *listener, void *data) {
static void handle_touch_down(struct wl_listener *listener, void *data) { static void handle_touch_down(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_down); struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_down);
struct wlr_event_touch_down *event = data; struct wlr_touch_down_event *event = data;
cursor_handle_activity_from_device(cursor, event->device); cursor_handle_activity_from_device(cursor, &event->touch->base);
cursor_hide(cursor); cursor_hide(cursor);
struct sway_seat *seat = cursor->seat; struct sway_seat *seat = cursor->seat;
@ -467,7 +468,7 @@ static void handle_touch_down(struct wl_listener *listener, void *data) {
struct wlr_surface *surface = NULL; struct wlr_surface *surface = NULL;
double lx, ly; double lx, ly;
wlr_cursor_absolute_to_layout_coords(cursor->cursor, event->device, wlr_cursor_absolute_to_layout_coords(cursor->cursor, &event->touch->base,
event->x, event->y, &lx, &ly); event->x, event->y, &lx, &ly);
double sx, sy; double sx, sy;
struct sway_node *focused_node = node_at_coords(seat, lx, ly, &surface, &sx, &sy); struct sway_node *focused_node = node_at_coords(seat, lx, ly, &surface, &sx, &sy);
@ -495,24 +496,25 @@ static void handle_touch_down(struct wl_listener *listener, void *data) {
double dx, dy; double dx, dy;
dx = lx - cursor->cursor->x; dx = lx - cursor->cursor->x;
dy = ly - cursor->cursor->y; dy = ly - cursor->cursor->y;
pointer_motion(cursor, event->time_msec, event->device, dx, dy, dx, dy); pointer_motion(cursor, event->time_msec, &event->touch->base, dx, dy,
dispatch_cursor_button(cursor, event->device, event->time_msec, dx, dy);
dispatch_cursor_button(cursor, &event->touch->base, event->time_msec,
BTN_LEFT, WLR_BUTTON_PRESSED); BTN_LEFT, WLR_BUTTON_PRESSED);
} }
} }
static void handle_touch_up(struct wl_listener *listener, void *data) { static void handle_touch_up(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_up); struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_up);
struct wlr_event_touch_up *event = data; struct wlr_touch_up_event *event = data;
cursor_handle_activity_from_device(cursor, event->device); cursor_handle_activity_from_device(cursor, &event->touch->base);
struct wlr_seat *wlr_seat = cursor->seat->wlr_seat; struct wlr_seat *wlr_seat = cursor->seat->wlr_seat;
if (cursor->simulating_pointer_from_touch) { if (cursor->simulating_pointer_from_touch) {
if (cursor->pointer_touch_id == cursor->seat->touch_id) { if (cursor->pointer_touch_id == cursor->seat->touch_id) {
cursor->pointer_touch_up = true; cursor->pointer_touch_up = true;
dispatch_cursor_button(cursor, event->device, event->time_msec, dispatch_cursor_button(cursor, &event->touch->base,
BTN_LEFT, WLR_BUTTON_RELEASED); event->time_msec, BTN_LEFT, WLR_BUTTON_RELEASED);
} }
} else { } else {
wlr_seat_touch_notify_up(wlr_seat, event->time_msec, event->touch_id); wlr_seat_touch_notify_up(wlr_seat, event->time_msec, event->touch_id);
@ -522,15 +524,15 @@ static void handle_touch_up(struct wl_listener *listener, void *data) {
static void handle_touch_motion(struct wl_listener *listener, void *data) { static void handle_touch_motion(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = struct sway_cursor *cursor =
wl_container_of(listener, cursor, touch_motion); wl_container_of(listener, cursor, touch_motion);
struct wlr_event_touch_motion *event = data; struct wlr_touch_motion_event *event = data;
cursor_handle_activity_from_device(cursor, event->device); cursor_handle_activity_from_device(cursor, &event->touch->base);
struct sway_seat *seat = cursor->seat; struct sway_seat *seat = cursor->seat;
struct wlr_seat *wlr_seat = seat->wlr_seat; struct wlr_seat *wlr_seat = seat->wlr_seat;
struct wlr_surface *surface = NULL; struct wlr_surface *surface = NULL;
double lx, ly; double lx, ly;
wlr_cursor_absolute_to_layout_coords(cursor->cursor, event->device, wlr_cursor_absolute_to_layout_coords(cursor->cursor, &event->touch->base,
event->x, event->y, &lx, &ly); event->x, event->y, &lx, &ly);
double sx, sy; double sx, sy;
node_at_coords(cursor->seat, lx, ly, &surface, &sx, &sy); node_at_coords(cursor->seat, lx, ly, &surface, &sx, &sy);
@ -552,7 +554,8 @@ static void handle_touch_motion(struct wl_listener *listener, void *data) {
double dx, dy; double dx, dy;
dx = lx - cursor->cursor->x; dx = lx - cursor->cursor->x;
dy = ly - cursor->cursor->y; dy = ly - cursor->cursor->y;
pointer_motion(cursor, event->time_msec, event->device, dx, dy, dx, dy); pointer_motion(cursor, event->time_msec, &event->touch->base,
dx, dy, dx, dy);
} }
} else if (surface) { } else if (surface) {
wlr_seat_touch_notify_motion(wlr_seat, event->time_msec, wlr_seat_touch_notify_motion(wlr_seat, event->time_msec,
@ -591,14 +594,15 @@ static void apply_mapping_from_region(struct wlr_input_device *device,
double x1 = region->x1, x2 = region->x2; double x1 = region->x1, x2 = region->x2;
double y1 = region->y1, y2 = region->y2; double y1 = region->y1, y2 = region->y2;
if (region->mm) { if (region->mm && device->type == WLR_INPUT_DEVICE_TABLET_TOOL) {
if (device->width_mm == 0 || device->height_mm == 0) { struct wlr_tablet *tablet = device->tablet;
if (tablet->width_mm == 0 || tablet->height_mm == 0) {
return; return;
} }
x1 /= device->width_mm; x1 /= tablet->width_mm;
x2 /= device->width_mm; x2 /= tablet->width_mm;
y1 /= device->height_mm; y1 /= tablet->height_mm;
y2 /= device->height_mm; y2 /= tablet->height_mm;
} }
*x = apply_mapping_from_coord(x1, x2, *x); *x = apply_mapping_from_coord(x1, x2, *x);
@ -660,8 +664,8 @@ static void handle_tablet_tool_position(struct sway_cursor *cursor,
static void handle_tool_axis(struct wl_listener *listener, void *data) { static void handle_tool_axis(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_axis); struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_axis);
struct wlr_event_tablet_tool_axis *event = data; struct wlr_tablet_tool_axis_event *event = data;
cursor_handle_activity_from_device(cursor, event->device); cursor_handle_activity_from_device(cursor, &event->tablet->base);
struct sway_tablet_tool *sway_tool = event->tool->data; struct sway_tablet_tool *sway_tool = event->tool->data;
if (!sway_tool) { if (!sway_tool) {
@ -716,8 +720,8 @@ static void handle_tool_axis(struct wl_listener *listener, void *data) {
static void handle_tool_tip(struct wl_listener *listener, void *data) { static void handle_tool_tip(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_tip); struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_tip);
struct wlr_event_tablet_tool_tip *event = data; struct wlr_tablet_tool_tip_event *event = data;
cursor_handle_activity_from_device(cursor, event->device); cursor_handle_activity_from_device(cursor, &event->tablet->base);
struct sway_tablet_tool *sway_tool = event->tool->data; struct sway_tablet_tool *sway_tool = event->tool->data;
struct wlr_tablet_v2_tablet *tablet_v2 = sway_tool->tablet->tablet_v2; struct wlr_tablet_v2_tablet *tablet_v2 = sway_tool->tablet->tablet_v2;
@ -732,7 +736,7 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) {
if (cursor->simulating_pointer_from_tool_tip && if (cursor->simulating_pointer_from_tool_tip &&
event->state == WLR_TABLET_TOOL_TIP_UP) { event->state == WLR_TABLET_TOOL_TIP_UP) {
cursor->simulating_pointer_from_tool_tip = false; cursor->simulating_pointer_from_tool_tip = false;
dispatch_cursor_button(cursor, event->device, event->time_msec, dispatch_cursor_button(cursor, &event->tablet->base, event->time_msec,
BTN_LEFT, WLR_BUTTON_RELEASED); BTN_LEFT, WLR_BUTTON_RELEASED);
wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
} else if (!surface || !wlr_surface_accepts_tablet_v2(tablet_v2, surface)) { } else if (!surface || !wlr_surface_accepts_tablet_v2(tablet_v2, surface)) {
@ -744,8 +748,8 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) {
WLR_TABLET_TOOL_TIP_UP); WLR_TABLET_TOOL_TIP_UP);
} else { } else {
cursor->simulating_pointer_from_tool_tip = true; cursor->simulating_pointer_from_tool_tip = true;
dispatch_cursor_button(cursor, event->device, event->time_msec, dispatch_cursor_button(cursor, &event->tablet->base,
BTN_LEFT, WLR_BUTTON_PRESSED); event->time_msec, BTN_LEFT, WLR_BUTTON_PRESSED);
wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
} }
} else { } else {
@ -767,12 +771,13 @@ static struct sway_tablet *get_tablet_for_device(struct sway_cursor *cursor,
static void handle_tool_proximity(struct wl_listener *listener, void *data) { static void handle_tool_proximity(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = struct sway_cursor *cursor =
wl_container_of(listener, cursor, tool_proximity); wl_container_of(listener, cursor, tool_proximity);
struct wlr_event_tablet_tool_proximity *event = data; struct wlr_tablet_tool_proximity_event *event = data;
cursor_handle_activity_from_device(cursor, event->device); cursor_handle_activity_from_device(cursor, &event->tablet->base);
struct wlr_tablet_tool *tool = event->tool; struct wlr_tablet_tool *tool = event->tool;
if (!tool->data) { if (!tool->data) {
struct sway_tablet *tablet = get_tablet_for_device(cursor, event->device); struct sway_tablet *tablet = get_tablet_for_device(cursor,
&event->tablet->base);
if (!tablet) { if (!tablet) {
sway_log(SWAY_ERROR, "no tablet for tablet tool"); sway_log(SWAY_ERROR, "no tablet for tablet tool");
return; return;
@ -797,8 +802,8 @@ static void handle_tool_proximity(struct wl_listener *listener, void *data) {
static void handle_tool_button(struct wl_listener *listener, void *data) { static void handle_tool_button(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_button); struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_button);
struct wlr_event_tablet_tool_button *event = data; struct wlr_tablet_tool_button_event *event = data;
cursor_handle_activity_from_device(cursor, event->device); cursor_handle_activity_from_device(cursor, &event->tablet->base);
struct sway_tablet_tool *sway_tool = event->tool->data; struct sway_tablet_tool *sway_tool = event->tool->data;
if (!sway_tool) { if (!sway_tool) {
@ -819,14 +824,14 @@ static void handle_tool_button(struct wl_listener *listener, void *data) {
switch (event->state) { switch (event->state) {
case WLR_BUTTON_PRESSED: case WLR_BUTTON_PRESSED:
if (cursor->tool_buttons == 0) { if (cursor->tool_buttons == 0) {
dispatch_cursor_button(cursor, event->device, dispatch_cursor_button(cursor, &event->tablet->base,
event->time_msec, BTN_RIGHT, event->state); event->time_msec, BTN_RIGHT, event->state);
} }
cursor->tool_buttons++; cursor->tool_buttons++;
break; break;
case WLR_BUTTON_RELEASED: case WLR_BUTTON_RELEASED:
if (cursor->tool_buttons == 1) { if (cursor->tool_buttons == 1) {
dispatch_cursor_button(cursor, event->device, dispatch_cursor_button(cursor, &event->tablet->base,
event->time_msec, BTN_RIGHT, event->state); event->time_msec, BTN_RIGHT, event->state);
} }
cursor->tool_buttons--; cursor->tool_buttons--;
@ -926,8 +931,8 @@ static void handle_request_pointer_set_cursor(struct wl_listener *listener,
static void handle_pointer_pinch_begin(struct wl_listener *listener, void *data) { static void handle_pointer_pinch_begin(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = wl_container_of( struct sway_cursor *cursor = wl_container_of(
listener, cursor, pinch_begin); listener, cursor, pinch_begin);
struct wlr_event_pointer_pinch_begin *event = data; struct wlr_pointer_pinch_begin_event *event = data;
cursor_handle_activity_from_device(cursor, event->device); cursor_handle_activity_from_device(cursor, &event->pointer->base);
wlr_pointer_gestures_v1_send_pinch_begin( wlr_pointer_gestures_v1_send_pinch_begin(
cursor->pointer_gestures, cursor->seat->wlr_seat, cursor->pointer_gestures, cursor->seat->wlr_seat,
event->time_msec, event->fingers); event->time_msec, event->fingers);
@ -936,8 +941,8 @@ static void handle_pointer_pinch_begin(struct wl_listener *listener, void *data)
static void handle_pointer_pinch_update(struct wl_listener *listener, void *data) { static void handle_pointer_pinch_update(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = wl_container_of( struct sway_cursor *cursor = wl_container_of(
listener, cursor, pinch_update); listener, cursor, pinch_update);
struct wlr_event_pointer_pinch_update *event = data; struct wlr_pointer_pinch_update_event *event = data;
cursor_handle_activity_from_device(cursor, event->device); cursor_handle_activity_from_device(cursor, &event->pointer->base);
wlr_pointer_gestures_v1_send_pinch_update( wlr_pointer_gestures_v1_send_pinch_update(
cursor->pointer_gestures, cursor->seat->wlr_seat, cursor->pointer_gestures, cursor->seat->wlr_seat,
event->time_msec, event->dx, event->dy, event->time_msec, event->dx, event->dy,
@ -947,8 +952,8 @@ static void handle_pointer_pinch_update(struct wl_listener *listener, void *data
static void handle_pointer_pinch_end(struct wl_listener *listener, void *data) { static void handle_pointer_pinch_end(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = wl_container_of( struct sway_cursor *cursor = wl_container_of(
listener, cursor, pinch_end); listener, cursor, pinch_end);
struct wlr_event_pointer_pinch_end *event = data; struct wlr_pointer_pinch_end_event *event = data;
cursor_handle_activity_from_device(cursor, event->device); cursor_handle_activity_from_device(cursor, &event->pointer->base);
wlr_pointer_gestures_v1_send_pinch_end( wlr_pointer_gestures_v1_send_pinch_end(
cursor->pointer_gestures, cursor->seat->wlr_seat, cursor->pointer_gestures, cursor->seat->wlr_seat,
event->time_msec, event->cancelled); event->time_msec, event->cancelled);
@ -957,8 +962,8 @@ static void handle_pointer_pinch_end(struct wl_listener *listener, void *data) {
static void handle_pointer_swipe_begin(struct wl_listener *listener, void *data) { static void handle_pointer_swipe_begin(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = wl_container_of( struct sway_cursor *cursor = wl_container_of(
listener, cursor, swipe_begin); listener, cursor, swipe_begin);
struct wlr_event_pointer_swipe_begin *event = data; struct wlr_pointer_swipe_begin_event *event = data;
cursor_handle_activity_from_device(cursor, event->device); cursor_handle_activity_from_device(cursor, &event->pointer->base);
wlr_pointer_gestures_v1_send_swipe_begin( wlr_pointer_gestures_v1_send_swipe_begin(
cursor->pointer_gestures, cursor->seat->wlr_seat, cursor->pointer_gestures, cursor->seat->wlr_seat,
event->time_msec, event->fingers); event->time_msec, event->fingers);
@ -967,8 +972,8 @@ static void handle_pointer_swipe_begin(struct wl_listener *listener, void *data)
static void handle_pointer_swipe_update(struct wl_listener *listener, void *data) { static void handle_pointer_swipe_update(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = wl_container_of( struct sway_cursor *cursor = wl_container_of(
listener, cursor, swipe_update); listener, cursor, swipe_update);
struct wlr_event_pointer_swipe_update *event = data; struct wlr_pointer_swipe_update_event *event = data;
cursor_handle_activity_from_device(cursor, event->device); cursor_handle_activity_from_device(cursor, &event->pointer->base);
wlr_pointer_gestures_v1_send_swipe_update( wlr_pointer_gestures_v1_send_swipe_update(
cursor->pointer_gestures, cursor->seat->wlr_seat, cursor->pointer_gestures, cursor->seat->wlr_seat,
event->time_msec, event->dx, event->dy); event->time_msec, event->dx, event->dy);
@ -977,13 +982,33 @@ static void handle_pointer_swipe_update(struct wl_listener *listener, void *data
static void handle_pointer_swipe_end(struct wl_listener *listener, void *data) { static void handle_pointer_swipe_end(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = wl_container_of( struct sway_cursor *cursor = wl_container_of(
listener, cursor, swipe_end); listener, cursor, swipe_end);
struct wlr_event_pointer_swipe_end *event = data; struct wlr_pointer_swipe_end_event *event = data;
cursor_handle_activity_from_device(cursor, event->device); cursor_handle_activity_from_device(cursor, &event->pointer->base);
wlr_pointer_gestures_v1_send_swipe_end( wlr_pointer_gestures_v1_send_swipe_end(
cursor->pointer_gestures, cursor->seat->wlr_seat, cursor->pointer_gestures, cursor->seat->wlr_seat,
event->time_msec, event->cancelled); event->time_msec, event->cancelled);
} }
static void handle_pointer_hold_begin(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = wl_container_of(
listener, cursor, hold_begin);
struct wlr_pointer_hold_begin_event *event = data;
cursor_handle_activity_from_device(cursor, &event->pointer->base);
wlr_pointer_gestures_v1_send_hold_begin(
cursor->pointer_gestures, cursor->seat->wlr_seat,
event->time_msec, event->fingers);
}
static void handle_pointer_hold_end(struct wl_listener *listener, void *data) {
struct sway_cursor *cursor = wl_container_of(
listener, cursor, hold_end);
struct wlr_pointer_hold_end_event *event = data;
cursor_handle_activity_from_device(cursor, &event->pointer->base);
wlr_pointer_gestures_v1_send_hold_end(
cursor->pointer_gestures, cursor->seat->wlr_seat,
event->time_msec, event->cancelled);
}
static void handle_image_surface_destroy(struct wl_listener *listener, static void handle_image_surface_destroy(struct wl_listener *listener,
void *data) { void *data) {
struct sway_cursor *cursor = struct sway_cursor *cursor =
@ -1061,6 +1086,8 @@ void sway_cursor_destroy(struct sway_cursor *cursor) {
wl_list_remove(&cursor->swipe_begin.link); wl_list_remove(&cursor->swipe_begin.link);
wl_list_remove(&cursor->swipe_update.link); wl_list_remove(&cursor->swipe_update.link);
wl_list_remove(&cursor->swipe_end.link); wl_list_remove(&cursor->swipe_end.link);
wl_list_remove(&cursor->hold_begin.link);
wl_list_remove(&cursor->hold_end.link);
wl_list_remove(&cursor->motion.link); wl_list_remove(&cursor->motion.link);
wl_list_remove(&cursor->motion_absolute.link); wl_list_remove(&cursor->motion_absolute.link);
wl_list_remove(&cursor->button.link); wl_list_remove(&cursor->button.link);
@ -1117,6 +1144,10 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) {
wl_signal_add(&wlr_cursor->events.swipe_update, &cursor->swipe_update); wl_signal_add(&wlr_cursor->events.swipe_update, &cursor->swipe_update);
cursor->swipe_end.notify = handle_pointer_swipe_end; cursor->swipe_end.notify = handle_pointer_swipe_end;
wl_signal_add(&wlr_cursor->events.swipe_end, &cursor->swipe_end); wl_signal_add(&wlr_cursor->events.swipe_end, &cursor->swipe_end);
cursor->hold_begin.notify = handle_pointer_hold_begin;
wl_signal_add(&wlr_cursor->events.hold_begin, &cursor->hold_begin);
cursor->hold_end.notify = handle_pointer_hold_end;
wl_signal_add(&wlr_cursor->events.hold_end, &cursor->hold_end);
// input events // input events
wl_signal_add(&wlr_cursor->events.motion, &cursor->motion); wl_signal_add(&wlr_cursor->events.motion, &cursor->motion);

View file

@ -377,7 +377,7 @@ void handle_virtual_keyboard(struct wl_listener *listener, void *data) {
struct sway_input_manager *input_manager = struct sway_input_manager *input_manager =
wl_container_of(listener, input_manager, virtual_keyboard_new); wl_container_of(listener, input_manager, virtual_keyboard_new);
struct wlr_virtual_keyboard_v1 *keyboard = data; struct wlr_virtual_keyboard_v1 *keyboard = data;
struct wlr_input_device *device = &keyboard->input_device; struct wlr_input_device *device = &keyboard->keyboard.base;
// TODO: Amend protocol to allow NULL seat // TODO: Amend protocol to allow NULL seat
struct sway_seat *seat = keyboard->seat ? struct sway_seat *seat = keyboard->seat ?
@ -410,7 +410,7 @@ void handle_virtual_pointer(struct wl_listener *listener, void *data) {
wl_container_of(listener, input_manager, virtual_pointer_new); wl_container_of(listener, input_manager, virtual_pointer_new);
struct wlr_virtual_pointer_v1_new_pointer_event *event = data; struct wlr_virtual_pointer_v1_new_pointer_event *event = data;
struct wlr_virtual_pointer_v1 *pointer = event->new_pointer; struct wlr_virtual_pointer_v1 *pointer = event->new_pointer;
struct wlr_input_device *device = &pointer->input_device; struct wlr_input_device *device = &pointer->pointer.base;
struct sway_seat *seat = event->suggested_seat ? struct sway_seat *seat = event->suggested_seat ?
input_manager_sway_seat_from_wlr_seat(event->suggested_seat) : input_manager_sway_seat_from_wlr_seat(event->suggested_seat) :

View file

@ -401,7 +401,7 @@ static struct wlr_input_method_keyboard_grab_v2 *keyboard_get_im_grab(
} }
static void handle_key_event(struct sway_keyboard *keyboard, static void handle_key_event(struct sway_keyboard *keyboard,
struct wlr_event_keyboard_key *event) { struct wlr_keyboard_key_event *event) {
struct sway_seat *seat = keyboard->seat_device->sway_seat; struct sway_seat *seat = keyboard->seat_device->sway_seat;
struct wlr_seat *wlr_seat = seat->wlr_seat; struct wlr_seat *wlr_seat = seat->wlr_seat;
struct wlr_input_device *wlr_device = struct wlr_input_device *wlr_device =
@ -517,7 +517,7 @@ static void handle_key_event(struct sway_keyboard *keyboard,
&keyboard->state_pressed_sent, event->keycode, &keyboard->state_pressed_sent, event->keycode,
event->state, keyinfo.keycode, 0); event->state, keyinfo.keycode, 0);
if (pressed_sent) { if (pressed_sent) {
wlr_seat_set_keyboard(wlr_seat, wlr_device); wlr_seat_set_keyboard(wlr_seat, wlr_device->keyboard);
wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec, wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec,
event->keycode, event->state); event->keycode, event->state);
handled = true; handled = true;
@ -542,7 +542,7 @@ static void handle_key_event(struct sway_keyboard *keyboard,
update_shortcut_state( update_shortcut_state(
&keyboard->state_pressed_sent, event->keycode, event->state, &keyboard->state_pressed_sent, event->keycode, event->state,
keyinfo.keycode, 0); keyinfo.keycode, 0);
wlr_seat_set_keyboard(wlr_seat, wlr_device); wlr_seat_set_keyboard(wlr_seat, wlr_device->keyboard);
wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec, wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec,
event->keycode, event->state); event->keycode, event->state);
} }
@ -670,7 +670,7 @@ static void handle_modifier_event(struct sway_keyboard *keyboard) {
&wlr_device->keyboard->modifiers); &wlr_device->keyboard->modifiers);
} else { } else {
struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat; struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat;
wlr_seat_set_keyboard(wlr_seat, wlr_device); wlr_seat_set_keyboard(wlr_seat, wlr_device->keyboard);
wlr_seat_keyboard_notify_modifiers(wlr_seat, wlr_seat_keyboard_notify_modifiers(wlr_seat,
&wlr_device->keyboard->modifiers); &wlr_device->keyboard->modifiers);
} }
@ -950,7 +950,7 @@ static void sway_keyboard_group_add(struct sway_keyboard *keyboard) {
goto cleanup; goto cleanup;
} }
sway_group->seat_device->input_device->wlr_device = sway_group->seat_device->input_device->wlr_device =
sway_group->wlr_group->input_device; &sway_group->wlr_group->keyboard.base;
if (!sway_keyboard_create(seat, sway_group->seat_device)) { if (!sway_keyboard_create(seat, sway_group->seat_device)) {
sway_log(SWAY_ERROR, "Failed to allocate sway_keyboard for group"); sway_log(SWAY_ERROR, "Failed to allocate sway_keyboard for group");
@ -1086,7 +1086,7 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) {
} }
struct wlr_seat *seat = keyboard->seat_device->sway_seat->wlr_seat; struct wlr_seat *seat = keyboard->seat_device->sway_seat->wlr_seat;
wlr_seat_set_keyboard(seat, wlr_device); wlr_seat_set_keyboard(seat, wlr_device->keyboard);
wl_list_remove(&keyboard->keyboard_key.link); wl_list_remove(&keyboard->keyboard_key.link);
wl_signal_add(&wlr_device->keyboard->events.key, &keyboard->keyboard_key); wl_signal_add(&wlr_device->keyboard->events.key, &keyboard->keyboard_key);

View file

@ -11,6 +11,7 @@
#include <wlr/types/wlr_output_layout.h> #include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_primary_selection.h> #include <wlr/types/wlr_primary_selection.h>
#include <wlr/types/wlr_tablet_v2.h> #include <wlr/types/wlr_tablet_v2.h>
#include <wlr/types/wlr_touch.h>
#include <wlr/types/wlr_xcursor_manager.h> #include <wlr/types/wlr_xcursor_manager.h>
#include "config.h" #include "config.h"
#include "list.h" #include "list.h"
@ -42,6 +43,7 @@ static void seat_device_destroy(struct sway_seat_device *seat_device) {
sway_keyboard_destroy(seat_device->keyboard); sway_keyboard_destroy(seat_device->keyboard);
sway_tablet_destroy(seat_device->tablet); sway_tablet_destroy(seat_device->tablet);
sway_tablet_pad_destroy(seat_device->tablet_pad); sway_tablet_pad_destroy(seat_device->tablet_pad);
sway_switch_destroy(seat_device->switch_device);
wlr_cursor_detach_input_device(seat_device->sway_seat->cursor->cursor, wlr_cursor_detach_input_device(seat_device->sway_seat->cursor->cursor,
seat_device->input_device->wlr_device); seat_device->input_device->wlr_device);
wl_list_remove(&seat_device->link); wl_list_remove(&seat_device->link);
@ -245,7 +247,7 @@ static void handle_seat_node_destroy(struct wl_listener *listener, void *data) {
seat_node_destroy(seat_node); seat_node_destroy(seat_node);
// If an unmanaged or layer surface is focused when an output gets // If an unmanaged or layer surface is focused when an output gets
// disabled and an empty workspace on the output was focused by the // disabled and an empty workspace on the output was focused by the
// seat, the seat needs to refocus it's focus inactive to update the // seat, the seat needs to refocus its focus inactive to update the
// value of seat->workspace. // value of seat->workspace.
if (seat->workspace == node->sway_workspace) { if (seat->workspace == node->sway_workspace) {
struct sway_node *node = seat_get_focus_inactive(seat, &root->node); struct sway_node *node = seat_get_focus_inactive(seat, &root->node);
@ -378,8 +380,8 @@ void drag_icon_update_position(struct sway_drag_icon *icon) {
case WLR_DRAG_GRAB_KEYBOARD: case WLR_DRAG_GRAB_KEYBOARD:
return; return;
case WLR_DRAG_GRAB_KEYBOARD_POINTER: case WLR_DRAG_GRAB_KEYBOARD_POINTER:
icon->x = cursor->x; icon->x = cursor->x + wlr_icon->surface->sx;
icon->y = cursor->y; icon->y = cursor->y + wlr_icon->surface->sy;
break; break;
case WLR_DRAG_GRAB_KEYBOARD_TOUCH:; case WLR_DRAG_GRAB_KEYBOARD_TOUCH:;
struct wlr_touch_point *point = struct wlr_touch_point *point =
@ -387,8 +389,8 @@ void drag_icon_update_position(struct sway_drag_icon *icon) {
if (point == NULL) { if (point == NULL) {
return; return;
} }
icon->x = seat->touch_x; icon->x = seat->touch_x + wlr_icon->surface->sx;
icon->y = seat->touch_y; icon->y = seat->touch_y + wlr_icon->surface->sy;
} }
drag_icon_damage_whole(icon); drag_icon_damage_whole(icon);
@ -724,14 +726,25 @@ static void seat_apply_input_config(struct sway_seat *seat,
ic == NULL ? MAPPED_TO_DEFAULT : ic->mapped_to; ic == NULL ? MAPPED_TO_DEFAULT : ic->mapped_to;
switch (mapped_to) { switch (mapped_to) {
case MAPPED_TO_DEFAULT: case MAPPED_TO_DEFAULT:;
/* /*
* If the wlroots backend provides an output name, use that. * If the wlroots backend provides an output name, use that.
* *
* Otherwise, try to map built-in touch and tablet tool devices to the * Otherwise, try to map built-in touch and pointer devices to the
* built-in output. * built-in output.
*/ */
mapped_to_output = sway_device->input_device->wlr_device->output_name; struct wlr_input_device *dev = sway_device->input_device->wlr_device;
switch (dev->type) {
case WLR_INPUT_DEVICE_POINTER:
mapped_to_output = dev->pointer->output_name;
break;
case WLR_INPUT_DEVICE_TOUCH:
mapped_to_output = dev->touch->output_name;
break;
default:
mapped_to_output = NULL;
break;
}
if (mapped_to_output == NULL && is_touch_or_tablet_tool(sway_device) && if (mapped_to_output == NULL && is_touch_or_tablet_tool(sway_device) &&
sway_libinput_device_is_builtin(sway_device->input_device)) { sway_libinput_device_is_builtin(sway_device->input_device)) {
mapped_to_output = get_builtin_output_name(); mapped_to_output = get_builtin_output_name();
@ -800,7 +813,7 @@ static void seat_configure_keyboard(struct sway_seat *seat,
} }
sway_keyboard_configure(seat_device->keyboard); sway_keyboard_configure(seat_device->keyboard);
wlr_seat_set_keyboard(seat->wlr_seat, wlr_seat_set_keyboard(seat->wlr_seat,
seat_device->input_device->wlr_device); seat_device->input_device->wlr_device->keyboard);
struct sway_node *focus = seat_get_focus(seat); struct sway_node *focus = seat_get_focus(seat);
if (focus && node_is_view(focus)) { if (focus && node_is_view(focus)) {
// force notify reenter to pick up the new configuration // force notify reenter to pick up the new configuration
@ -1561,7 +1574,7 @@ void seatop_pointer_motion(struct sway_seat *seat, uint32_t time_msec) {
} }
void seatop_pointer_axis(struct sway_seat *seat, void seatop_pointer_axis(struct sway_seat *seat,
struct wlr_event_pointer_axis *event) { struct wlr_pointer_axis_event *event) {
if (seat->seatop_impl->pointer_axis) { if (seat->seatop_impl->pointer_axis) {
seat->seatop_impl->pointer_axis(seat, event); seat->seatop_impl->pointer_axis(seat, event);
} }

View file

@ -474,7 +474,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
seat_set_focus(seat, node); seat_set_focus(seat, node);
} }
// If moving a container by it's title bar, use a threshold for the drag // If moving a container by its title bar, use a threshold for the drag
if (!mod_pressed && config->tiling_drag_threshold > 0) { if (!mod_pressed && config->tiling_drag_threshold > 0) {
seatop_begin_move_tiling_threshold(seat, cont); seatop_begin_move_tiling_threshold(seat, cont);
} else { } else {
@ -645,7 +645,7 @@ static void handle_tablet_tool_motion(struct sway_seat *seat,
* Functions used by handle_pointer_axis / * Functions used by handle_pointer_axis /
*--------------------------------------*/ *--------------------------------------*/
static uint32_t wl_axis_to_button(struct wlr_event_pointer_axis *event) { static uint32_t wl_axis_to_button(struct wlr_pointer_axis_event *event) {
switch (event->orientation) { switch (event->orientation) {
case WLR_AXIS_ORIENTATION_VERTICAL: case WLR_AXIS_ORIENTATION_VERTICAL:
return event->delta < 0 ? SWAY_SCROLL_UP : SWAY_SCROLL_DOWN; return event->delta < 0 ? SWAY_SCROLL_UP : SWAY_SCROLL_DOWN;
@ -658,9 +658,9 @@ static uint32_t wl_axis_to_button(struct wlr_event_pointer_axis *event) {
} }
static void handle_pointer_axis(struct sway_seat *seat, static void handle_pointer_axis(struct sway_seat *seat,
struct wlr_event_pointer_axis *event) { struct wlr_pointer_axis_event *event) {
struct sway_input_device *input_device = struct sway_input_device *input_device =
event->device ? event->device->data : NULL; event->pointer ? event->pointer->base.data : NULL;
struct input_config *ic = struct input_config *ic =
input_device ? input_device_get_config(input_device) : NULL; input_device ? input_device_get_config(input_device) : NULL;
struct sway_cursor *cursor = seat->cursor; struct sway_cursor *cursor = seat->cursor;

View file

@ -18,9 +18,9 @@ struct seatop_down_event {
}; };
static void handle_pointer_axis(struct sway_seat *seat, static void handle_pointer_axis(struct sway_seat *seat,
struct wlr_event_pointer_axis *event) { struct wlr_pointer_axis_event *event) {
struct sway_input_device *input_device = struct sway_input_device *input_device =
event->device ? event->device->data : NULL; event->pointer ? event->pointer->base.data : NULL;
struct input_config *ic = struct input_config *ic =
input_device ? input_device_get_config(input_device) : NULL; input_device ? input_device_get_config(input_device) : NULL;
float scroll_factor = float scroll_factor =

View file

@ -19,6 +19,19 @@ struct sway_switch *sway_switch_create(struct sway_seat *seat,
return switch_device; return switch_device;
} }
static bool sway_switch_trigger_test(enum sway_switch_trigger trigger,
enum wlr_switch_state state) {
switch (trigger) {
case SWAY_SWITCH_TRIGGER_ON:
return state == WLR_SWITCH_STATE_ON;
case SWAY_SWITCH_TRIGGER_OFF:
return state == WLR_SWITCH_STATE_OFF;
case SWAY_SWITCH_TRIGGER_TOGGLE:
return true;
}
abort(); // unreachable
}
static void execute_binding(struct sway_switch *sway_switch) { static void execute_binding(struct sway_switch *sway_switch) {
struct sway_seat* seat = sway_switch->seat_device->sway_seat; struct sway_seat* seat = sway_switch->seat_device->sway_seat;
bool input_inhibited = seat->exclusive_client != NULL; bool input_inhibited = seat->exclusive_client != NULL;
@ -30,11 +43,10 @@ static void execute_binding(struct sway_switch *sway_switch) {
if (binding->type != sway_switch->type) { if (binding->type != sway_switch->type) {
continue; continue;
} }
if (binding->state != WLR_SWITCH_STATE_TOGGLE && if (!sway_switch_trigger_test(binding->trigger, sway_switch->state)) {
binding->state != sway_switch->state) {
continue; continue;
} }
if (config->reloading && (binding->state == WLR_SWITCH_STATE_TOGGLE if (config->reloading && (binding->trigger == SWAY_SWITCH_TRIGGER_TOGGLE
|| (binding->flags & BINDING_RELOAD) == 0)) { || (binding->flags & BINDING_RELOAD) == 0)) {
continue; continue;
} }
@ -65,7 +77,7 @@ static void execute_binding(struct sway_switch *sway_switch) {
static void handle_switch_toggle(struct wl_listener *listener, void *data) { static void handle_switch_toggle(struct wl_listener *listener, void *data) {
struct sway_switch *sway_switch = struct sway_switch *sway_switch =
wl_container_of(listener, sway_switch, switch_toggle); wl_container_of(listener, sway_switch, switch_toggle);
struct wlr_event_switch_toggle *event = data; struct wlr_switch_toggle_event *event = data;
struct sway_seat *seat = sway_switch->seat_device->sway_seat; struct sway_seat *seat = sway_switch->seat_device->sway_seat;
seat_idle_notify_activity(seat, IDLE_SOURCE_SWITCH); seat_idle_notify_activity(seat, IDLE_SOURCE_SWITCH);

View file

@ -196,7 +196,7 @@ static void handle_tablet_pad_attach(struct wl_listener *listener,
static void handle_tablet_pad_ring(struct wl_listener *listener, void *data) { static void handle_tablet_pad_ring(struct wl_listener *listener, void *data) {
struct sway_tablet_pad *pad = wl_container_of(listener, pad, ring); struct sway_tablet_pad *pad = wl_container_of(listener, pad, ring);
struct wlr_event_tablet_pad_ring *event = data; struct wlr_tablet_pad_ring_event *event = data;
if (!pad->current_surface) { if (!pad->current_surface) {
return; return;
@ -210,7 +210,7 @@ static void handle_tablet_pad_ring(struct wl_listener *listener, void *data) {
static void handle_tablet_pad_strip(struct wl_listener *listener, void *data) { static void handle_tablet_pad_strip(struct wl_listener *listener, void *data) {
struct sway_tablet_pad *pad = wl_container_of(listener, pad, strip); struct sway_tablet_pad *pad = wl_container_of(listener, pad, strip);
struct wlr_event_tablet_pad_strip *event = data; struct wlr_tablet_pad_strip_event *event = data;
if (!pad->current_surface) { if (!pad->current_surface) {
return; return;
@ -224,7 +224,7 @@ static void handle_tablet_pad_strip(struct wl_listener *listener, void *data) {
static void handle_tablet_pad_button(struct wl_listener *listener, void *data) { static void handle_tablet_pad_button(struct wl_listener *listener, void *data) {
struct sway_tablet_pad *pad = wl_container_of(listener, pad, button); struct sway_tablet_pad *pad = wl_container_of(listener, pad, button);
struct wlr_event_tablet_pad_button *event = data; struct wlr_tablet_pad_button_event *event = data;
if (!pad->current_surface) { if (!pad->current_surface) {
return; return;

View file

@ -77,8 +77,6 @@ static void handle_im_grab_keyboard(struct wl_listener *listener, void *data) {
struct wlr_keyboard *active_keyboard = wlr_seat_get_keyboard(relay->seat->wlr_seat); struct wlr_keyboard *active_keyboard = wlr_seat_get_keyboard(relay->seat->wlr_seat);
wlr_input_method_keyboard_grab_v2_set_keyboard(keyboard_grab, wlr_input_method_keyboard_grab_v2_set_keyboard(keyboard_grab,
active_keyboard); active_keyboard);
wlr_input_method_keyboard_grab_v2_send_modifiers(keyboard_grab,
&active_keyboard->modifiers);
wl_signal_add(&keyboard_grab->events.destroy, wl_signal_add(&keyboard_grab->events.destroy,
&relay->input_method_keyboard_grab_destroy); &relay->input_method_keyboard_grab_destroy);

View file

@ -981,6 +981,11 @@ json_object *ipc_json_describe_input(struct sway_input_device *device) {
struct xkb_keymap *keymap = keyboard->keymap; struct xkb_keymap *keymap = keyboard->keymap;
struct xkb_state *state = keyboard->xkb_state; struct xkb_state *state = keyboard->xkb_state;
json_object_object_add(object, "repeat_delay",
json_object_new_int(keyboard->repeat_info.delay));
json_object_object_add(object, "repeat_rate",
json_object_new_int(keyboard->repeat_info.rate));
json_object *layouts_arr = json_object_new_array(); json_object *layouts_arr = json_object_new_array();
json_object_object_add(object, "xkb_layout_names", layouts_arr); json_object_object_add(object, "xkb_layout_names", layouts_arr);

View file

@ -240,35 +240,35 @@ static void handle_wlr_log(enum wlr_log_importance importance,
_sway_vlog(convert_wlr_log_importance(importance), sway_fmt, args); _sway_vlog(convert_wlr_log_importance(importance), sway_fmt, args);
} }
int main(int argc, char **argv) { static const struct option long_options[] = {
static int verbose = 0, debug = 0, validate = 0, allow_unsupported_gpu = 0; {"help", no_argument, NULL, 'h'},
{"config", required_argument, NULL, 'c'},
{"validate", no_argument, NULL, 'C'},
{"debug", no_argument, NULL, 'd'},
{"version", no_argument, NULL, 'v'},
{"verbose", no_argument, NULL, 'V'},
{"get-socketpath", no_argument, NULL, 'p'},
{"unsupported-gpu", no_argument, NULL, 'u'},
{0, 0, 0, 0}
};
static const struct option long_options[] = { static const char usage[] =
{"help", no_argument, NULL, 'h'}, "Usage: sway [options] [command]\n"
{"config", required_argument, NULL, 'c'}, "\n"
{"validate", no_argument, NULL, 'C'}, " -h, --help Show help message and quit.\n"
{"debug", no_argument, NULL, 'd'}, " -c, --config <config> Specify a config file.\n"
{"version", no_argument, NULL, 'v'}, " -C, --validate Check the validity of the config file, then exit.\n"
{"verbose", no_argument, NULL, 'V'}, " -d, --debug Enables full logging, including debug information.\n"
{"get-socketpath", no_argument, NULL, 'p'}, " -v, --version Show the version number and quit.\n"
{"unsupported-gpu", no_argument, NULL, 'u'}, " -V, --verbose Enables more verbose logging.\n"
{0, 0, 0, 0} " --get-socketpath Gets the IPC socket path and prints it, then exits.\n"
}; "\n";
int main(int argc, char **argv) {
static bool verbose = false, debug = false, validate = false, allow_unsupported_gpu = false;
char *config_path = NULL; char *config_path = NULL;
const char* usage =
"Usage: sway [options] [command]\n"
"\n"
" -h, --help Show help message and quit.\n"
" -c, --config <config> Specify a config file.\n"
" -C, --validate Check the validity of the config file, then exit.\n"
" -d, --debug Enables full logging, including debug information.\n"
" -v, --version Show the version number and quit.\n"
" -V, --verbose Enables more verbose logging.\n"
" --get-socketpath Gets the IPC socket path and prints it, then exits.\n"
"\n";
int c; int c;
while (1) { while (1) {
int option_index = 0; int option_index = 0;
@ -286,23 +286,23 @@ int main(int argc, char **argv) {
config_path = strdup(optarg); config_path = strdup(optarg);
break; break;
case 'C': // validate case 'C': // validate
validate = 1; validate = true;
break; break;
case 'd': // debug case 'd': // debug
debug = 1; debug = true;
break; break;
case 'D': // extended debug options case 'D': // extended debug options
enable_debug_flag(optarg); enable_debug_flag(optarg);
break; break;
case 'u': case 'u':
allow_unsupported_gpu = 1; allow_unsupported_gpu = true;
break; break;
case 'v': // version case 'v': // version
printf("sway version " SWAY_VERSION "\n"); printf("sway version " SWAY_VERSION "\n");
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
break; break;
case 'V': // verbose case 'V': // verbose
verbose = 1; verbose = true;
break; break;
case 'p': ; // --get-socketpath case 'p': ; // --get-socketpath
if (getenv("SWAYSOCK")) { if (getenv("SWAYSOCK")) {

View file

@ -213,13 +213,14 @@ sway_deps = [
libudev, libudev,
math, math,
pango, pango,
pcre, pcre2,
glesv2, glesv2,
pixman, pixman,
server_protos, server_protos,
wayland_server, wayland_server,
wlroots, wlroots,
xkbcommon, xkbcommon,
xcb_icccm,
] ]
if have_xwayland if have_xwayland

View file

@ -24,6 +24,7 @@
#include <wlr/types/wlr_relative_pointer_v1.h> #include <wlr/types/wlr_relative_pointer_v1.h>
#include <wlr/types/wlr_screencopy_v1.h> #include <wlr/types/wlr_screencopy_v1.h>
#include <wlr/types/wlr_server_decoration.h> #include <wlr/types/wlr_server_decoration.h>
#include <wlr/types/wlr_subcompositor.h>
#include <wlr/types/wlr_tablet_v2.h> #include <wlr/types/wlr_tablet_v2.h>
#include <wlr/types/wlr_viewporter.h> #include <wlr/types/wlr_viewporter.h>
#include <wlr/types/wlr_xcursor_manager.h> #include <wlr/types/wlr_xcursor_manager.h>
@ -101,6 +102,8 @@ bool server_init(struct sway_server *server) {
wl_signal_add(&server->compositor->events.new_surface, wl_signal_add(&server->compositor->events.new_surface,
&server->compositor_new_surface); &server->compositor_new_surface);
wlr_subcompositor_create(server->wl_display);
server->data_device_manager = server->data_device_manager =
wlr_data_device_manager_create(server->wl_display); wlr_data_device_manager_create(server->wl_display);
@ -210,8 +213,8 @@ bool server_init(struct sway_server *server) {
// Avoid using "wayland-0" as display socket // Avoid using "wayland-0" as display socket
char name_candidate[16]; char name_candidate[16];
for (int i = 1; i <= 32; ++i) { for (unsigned int i = 1; i <= 32; ++i) {
sprintf(name_candidate, "wayland-%d", i); snprintf(name_candidate, sizeof(name_candidate), "wayland-%u", i);
if (wl_display_add_socket(server->wl_display, name_candidate) >= 0) { if (wl_display_add_socket(server->wl_display, name_candidate) >= 0) {
server->socket = strdup(name_candidate); server->socket = strdup(name_candidate);
break; break;

View file

@ -620,11 +620,11 @@ The default colors are:
after switching between workspaces. after switching between workspaces.
*focus_on_window_activation* smart|urgent|focus|none *focus_on_window_activation* smart|urgent|focus|none
This option determines what to do when an xwayland client requests This option determines what to do when a client requests window activation.
window activation. If set to _urgent_, the urgent state will be set If set to _urgent_, the urgent state will be set for that window. If set to
for that window. If set to _focus_, the window will become focused. _focus_, the window will become focused. If set to _smart_, the window will
If set to _smart_, the window will become focused only if it is already become focused only if it is already visible, otherwise the urgent state
visible, otherwise the urgent state will be set. Default is _urgent_. will be set. Default is _urgent_.
*focus_wrapping* yes|no|force|workspace *focus_wrapping* yes|no|force|workspace
This option determines what to do when attempting to focus over the edge This option determines what to do when attempting to focus over the edge

View file

@ -311,12 +311,13 @@ void arrange_output(struct sway_output *output) {
if (config->reloading) { if (config->reloading) {
return; return;
} }
const struct wlr_box *output_box = wlr_output_layout_get_box( struct wlr_box output_box;
root->output_layout, output->wlr_output); wlr_output_layout_get_box(root->output_layout,
output->lx = output_box->x; output->wlr_output, &output_box);
output->ly = output_box->y; output->lx = output_box.x;
output->width = output_box->width; output->ly = output_box.y;
output->height = output_box->height; output->width = output_box.width;
output->height = output_box.height;
for (int i = 0; i < output->workspaces->length; ++i) { for (int i = 0; i < output->workspaces->length; ++i) {
struct sway_workspace *workspace = output->workspaces->items[i]; struct sway_workspace *workspace = output->workspaces->items[i];
@ -328,12 +329,12 @@ void arrange_root(void) {
if (config->reloading) { if (config->reloading) {
return; return;
} }
const struct wlr_box *layout_box = struct wlr_box layout_box;
wlr_output_layout_get_box(root->output_layout, NULL); wlr_output_layout_get_box(root->output_layout, NULL, &layout_box);
root->x = layout_box->x; root->x = layout_box.x;
root->y = layout_box->y; root->y = layout_box.y;
root->width = layout_box->width; root->width = layout_box.width;
root->height = layout_box->height; root->height = layout_box.height;
if (root->fullscreen_global) { if (root->fullscreen_global) {
struct sway_container *fs = root->fullscreen_global; struct sway_container *fs = root->fullscreen_global;

View file

@ -9,6 +9,7 @@
#include <wayland-server-core.h> #include <wayland-server-core.h>
#include <wlr/types/wlr_linux_dmabuf_v1.h> #include <wlr/types/wlr_linux_dmabuf_v1.h>
#include <wlr/types/wlr_output_layout.h> #include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_subcompositor.h>
#include <wlr/render/drm_format_set.h> #include <wlr/render/drm_format_set.h>
#include "linux-dmabuf-unstable-v1-protocol.h" #include "linux-dmabuf-unstable-v1-protocol.h"
#include "cairo_util.h" #include "cairo_util.h"
@ -193,7 +194,7 @@ static struct sway_container *surface_at_view(struct sway_container *con, double
#endif #endif
case SWAY_VIEW_XDG_SHELL: case SWAY_VIEW_XDG_SHELL:
_surface = wlr_xdg_surface_surface_at( _surface = wlr_xdg_surface_surface_at(
view->wlr_xdg_surface, view->wlr_xdg_toplevel->base,
view_sx, view_sy, &_sx, &_sy); view_sx, view_sy, &_sx, &_sy);
break; break;
} }
@ -694,12 +695,13 @@ void floating_calculate_constraints(int *min_width, int *max_width,
*min_height = config->floating_minimum_height; *min_height = config->floating_minimum_height;
} }
struct wlr_box *box = wlr_output_layout_get_box(root->output_layout, NULL); struct wlr_box box;
wlr_output_layout_get_box(root->output_layout, NULL, &box);
if (config->floating_maximum_width == -1) { // no maximum if (config->floating_maximum_width == -1) { // no maximum
*max_width = INT_MAX; *max_width = INT_MAX;
} else if (config->floating_maximum_width == 0) { // automatic } else if (config->floating_maximum_width == 0) { // automatic
*max_width = box->width; *max_width = box.width;
} else { } else {
*max_width = config->floating_maximum_width; *max_width = config->floating_maximum_width;
} }
@ -707,7 +709,7 @@ void floating_calculate_constraints(int *min_width, int *max_width,
if (config->floating_maximum_height == -1) { // no maximum if (config->floating_maximum_height == -1) { // no maximum
*max_height = INT_MAX; *max_height = INT_MAX;
} else if (config->floating_maximum_height == 0) { // automatic } else if (config->floating_maximum_height == 0) { // automatic
*max_height = box->height; *max_height = box.height;
} else { } else {
*max_height = config->floating_maximum_height; *max_height = config->floating_maximum_height;
} }
@ -739,9 +741,9 @@ void container_floating_resize_and_center(struct sway_container *con) {
return; return;
} }
struct wlr_box *ob = wlr_output_layout_get_box(root->output_layout, struct wlr_box ob;
ws->output->wlr_output); wlr_output_layout_get_box(root->output_layout, ws->output->wlr_output, &ob);
if (!ob) { if (wlr_box_empty(&ob)) {
// On NOOP output. Will be called again when moved to an output // On NOOP output. Will be called again when moved to an output
con->pending.x = 0; con->pending.x = 0;
con->pending.y = 0; con->pending.y = 0;
@ -753,8 +755,8 @@ void container_floating_resize_and_center(struct sway_container *con) {
floating_natural_resize(con); floating_natural_resize(con);
if (!con->view) { if (!con->view) {
if (con->pending.width > ws->width || con->pending.height > ws->height) { if (con->pending.width > ws->width || con->pending.height > ws->height) {
con->pending.x = ob->x + (ob->width - con->pending.width) / 2; con->pending.x = ob.x + (ob.width - con->pending.width) / 2;
con->pending.y = ob->y + (ob->height - con->pending.height) / 2; con->pending.y = ob.y + (ob.height - con->pending.height) / 2;
} else { } else {
con->pending.x = ws->x + (ws->width - con->pending.width) / 2; con->pending.x = ws->x + (ws->width - con->pending.width) / 2;
con->pending.y = ws->y + (ws->height - con->pending.height) / 2; con->pending.y = ws->y + (ws->height - con->pending.height) / 2;
@ -762,8 +764,8 @@ void container_floating_resize_and_center(struct sway_container *con) {
} else { } else {
if (con->pending.content_width > ws->width if (con->pending.content_width > ws->width
|| con->pending.content_height > ws->height) { || con->pending.content_height > ws->height) {
con->pending.content_x = ob->x + (ob->width - con->pending.content_width) / 2; con->pending.content_x = ob.x + (ob.width - con->pending.content_width) / 2;
con->pending.content_y = ob->y + (ob->height - con->pending.content_height) / 2; con->pending.content_y = ob.y + (ob.height - con->pending.content_height) / 2;
} else { } else {
con->pending.content_x = ws->x + (ws->width - con->pending.content_width) / 2; con->pending.content_x = ws->x + (ws->width - con->pending.content_width) / 2;
con->pending.content_y = ws->y + (ws->height - con->pending.content_height) / 2; con->pending.content_y = ws->y + (ws->height - con->pending.content_height) / 2;
@ -1704,7 +1706,7 @@ static void update_marks_texture(struct sway_container *con,
for (int i = 0; i < con->marks->length; ++i) { for (int i = 0; i < con->marks->length; ++i) {
char *mark = con->marks->items[i]; char *mark = con->marks->items[i];
if (mark[0] != '_') { if (mark[0] != '_') {
sprintf(part, "[%s]", mark); snprintf(part, len + 1, "[%s]", mark);
strcat(buffer, part); strcat(buffer, part);
} }
} }

View file

@ -301,10 +301,10 @@ struct sway_output *output_get_in_direction(struct sway_output *reference,
if (!sway_assert(direction, "got invalid direction: %d", direction)) { if (!sway_assert(direction, "got invalid direction: %d", direction)) {
return NULL; return NULL;
} }
struct wlr_box *output_box = struct wlr_box output_box;
wlr_output_layout_get_box(root->output_layout, reference->wlr_output); wlr_output_layout_get_box(root->output_layout, reference->wlr_output, &output_box);
int lx = output_box->x + output_box->width / 2; int lx = output_box.x + output_box.width / 2;
int ly = output_box->y + output_box->height / 2; int ly = output_box.y + output_box.height / 2;
struct wlr_output *wlr_adjacent = wlr_output_layout_adjacent_output( struct wlr_output *wlr_adjacent = wlr_output_layout_adjacent_output(
root->output_layout, direction, reference->wlr_output, lx, ly); root->output_layout, direction, reference->wlr_output, lx, ly);
if (!wlr_adjacent) { if (!wlr_adjacent) {

View file

@ -209,7 +209,7 @@ static pid_t get_parent_pid(pid_t child) {
FILE *stat = NULL; FILE *stat = NULL;
size_t buf_size = 0; size_t buf_size = 0;
sprintf(file_name, "/proc/%d/stat", child); snprintf(file_name, sizeof(file_name), "/proc/%d/stat", child);
if ((stat = fopen(file_name, "r"))) { if ((stat = fopen(file_name, "r"))) {
if (getline(&buffer, &buf_size, stat) != -1) { if (getline(&buffer, &buf_size, stat) != -1) {

View file

@ -6,6 +6,7 @@
#include <wlr/types/wlr_buffer.h> #include <wlr/types/wlr_buffer.h>
#include <wlr/types/wlr_output_layout.h> #include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_server_decoration.h> #include <wlr/types/wlr_server_decoration.h>
#include <wlr/types/wlr_subcompositor.h>
#include <wlr/types/wlr_xdg_decoration_v1.h> #include <wlr/types/wlr_xdg_decoration_v1.h>
#include "config.h" #include "config.h"
#if HAVE_XWAYLAND #if HAVE_XWAYLAND

View file

@ -51,9 +51,6 @@ static void swaybar_output_free(struct swaybar_output *output) {
if (output->surface != NULL) { if (output->surface != NULL) {
wl_surface_destroy(output->surface); wl_surface_destroy(output->surface);
} }
if (output->input_region != NULL) {
wl_region_destroy(output->input_region);
}
wl_output_destroy(output->output); wl_output_destroy(output->output);
destroy_buffer(&output->buffers[0]); destroy_buffer(&output->buffers[0]);
destroy_buffer(&output->buffers[1]); destroy_buffer(&output->buffers[1]);
@ -113,10 +110,9 @@ static void add_layer_surface(struct swaybar_output *output) {
if (overlay) { if (overlay) {
// Empty input region // Empty input region
output->input_region = wl_compositor_create_region(bar->compositor); struct wl_region *region = wl_compositor_create_region(bar->compositor);
assert(output->input_region); wl_surface_set_input_region(output->surface, region);
wl_region_destroy(region);
wl_surface_set_input_region(output->surface, output->input_region);
} }
zwlr_layer_surface_v1_set_anchor(output->layer_surface, config->position); zwlr_layer_surface_v1_set_anchor(output->layer_surface, config->position);

View file

@ -831,6 +831,15 @@ void render_frame(struct swaybar_output *output) {
wl_surface_damage(output->surface, 0, 0, wl_surface_damage(output->surface, 0, 0,
output->width, output->height); output->width, output->height);
uint32_t bg_alpha = ctx.background_color & 0xFF;
if (bg_alpha == 0xFF) {
struct wl_region *region =
wl_compositor_create_region(output->bar->compositor);
wl_region_add(region, 0, 0, INT32_MAX, INT32_MAX);
wl_surface_set_opaque_region(output->surface, region);
wl_region_destroy(region);
}
struct wl_callback *frame_callback = wl_surface_frame(output->surface); struct wl_callback *frame_callback = wl_surface_frame(output->surface);
wl_callback_add_listener(frame_callback, &output_frame_listener, output); wl_callback_add_listener(frame_callback, &output_frame_listener, output);
output->frame_scheduled = true; output->frame_scheduled = true;

View file

@ -466,6 +466,11 @@ uint32_t render_sni(cairo_t *cairo, struct swaybar_output *output, double *x,
sni->target_size = target_size; sni->target_size = target_size;
} }
// Passive
if (sni->status && sni->status[0] == 'P') {
return 0;
}
int icon_size; int icon_size;
cairo_surface_t *icon; cairo_surface_t *icon;
if (sni->icon) { if (sni->icon) {

View file

@ -288,28 +288,74 @@ static void pretty_print_config(json_object *c) {
printf("%s\n", json_object_get_string(config)); printf("%s\n", json_object_get_string(config));
} }
static void pretty_print_tree(json_object *obj, int indent) {
for (int i = 0; i < indent; i++) {
printf(" ");
}
int id = json_object_get_int(json_object_object_get(obj, "id"));
const char *name = json_object_get_string(json_object_object_get(obj, "name"));
const char *type = json_object_get_string(json_object_object_get(obj, "type"));
const char *shell = json_object_get_string(json_object_object_get(obj, "shell"));
printf("#%d: %s \"%s\"", id, type, name);
if (shell != NULL) {
int pid = json_object_get_int(json_object_object_get(obj, "pid"));
const char *app_id = json_object_get_string(json_object_object_get(obj, "app_id"));
json_object *window_props_obj = json_object_object_get(obj, "window_properties");
const char *instance = json_object_get_string(json_object_object_get(window_props_obj, "instance"));
const char *class = json_object_get_string(json_object_object_get(window_props_obj, "class"));
int x11_id = json_object_get_int(json_object_object_get(obj, "window"));
printf(" (%s, pid: %d", shell, pid);
if (app_id != NULL) {
printf(", app_id: \"%s\"", app_id);
}
if (instance != NULL) {
printf(", instance: \"%s\"", instance);
}
if (class != NULL) {
printf(", class: \"%s\"", class);
}
if (x11_id != 0) {
printf(", X11 window: 0x%X", x11_id);
}
printf(")");
}
printf("\n");
json_object *nodes_obj = json_object_object_get(obj, "nodes");
size_t len = json_object_array_length(nodes_obj);
for (size_t i = 0; i < len; i++) {
pretty_print_tree(json_object_array_get_idx(nodes_obj, i), indent + 1);
}
}
static void pretty_print(int type, json_object *resp) { static void pretty_print(int type, json_object *resp) {
if (type != IPC_COMMAND && type != IPC_GET_WORKSPACES && switch (type) {
type != IPC_GET_INPUTS && type != IPC_GET_OUTPUTS && case IPC_SEND_TICK:
type != IPC_GET_VERSION && type != IPC_GET_SEATS &&
type != IPC_GET_CONFIG && type != IPC_SEND_TICK) {
printf("%s\n", json_object_to_json_string_ext(resp,
JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED));
return; return;
} case IPC_GET_VERSION:
if (type == IPC_SEND_TICK) {
return;
}
if (type == IPC_GET_VERSION) {
pretty_print_version(resp); pretty_print_version(resp);
return; return;
} case IPC_GET_CONFIG:
if (type == IPC_GET_CONFIG) {
pretty_print_config(resp); pretty_print_config(resp);
return; return;
case IPC_GET_TREE:
pretty_print_tree(resp, 0);
return;
case IPC_COMMAND:
case IPC_GET_WORKSPACES:
case IPC_GET_INPUTS:
case IPC_GET_OUTPUTS:
case IPC_GET_SEATS:
break;
default:
printf("%s\n", json_object_to_json_string_ext(resp,
JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED));
return;
} }
json_object *obj; json_object *obj;

View file

@ -19,6 +19,10 @@ static char *read_from_stdin(void) {
ssize_t nread; ssize_t nread;
while ((nread = getline(&line, &line_size, stdin)) != -1) { while ((nread = getline(&line, &line_size, stdin)) != -1) {
buffer = realloc(buffer, buffer_len + nread + 1); buffer = realloc(buffer, buffer_len + nread + 1);
if (!buffer) {
perror("realloc");
return NULL;
}
snprintf(&buffer[buffer_len], nread + 1, "%s", line); snprintf(&buffer[buffer_len], nread + 1, "%s", line);
buffer_len += nread; buffer_len += nread;
} }
@ -152,6 +156,10 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag,
} }
struct swaynag_button *button; struct swaynag_button *button;
button = calloc(sizeof(struct swaynag_button), 1); button = calloc(sizeof(struct swaynag_button), 1);
if (!button) {
perror("calloc");
return EXIT_FAILURE;
}
button->text = strdup(optarg); button->text = strdup(optarg);
button->type = SWAYNAG_ACTION_COMMAND; button->type = SWAYNAG_ACTION_COMMAND;
button->action = strdup(argv[optind]); button->action = strdup(argv[optind]);
@ -215,14 +223,17 @@ int swaynag_parse_options(int argc, char **argv, struct swaynag *swaynag,
if (swaynag) { if (swaynag) {
free(swaynag->details.message); free(swaynag->details.message);
swaynag->details.message = read_from_stdin(); swaynag->details.message = read_from_stdin();
if (!swaynag->details.message) {
return EXIT_FAILURE;
}
swaynag->details.button_up.text = strdup(""); swaynag->details.button_up.text = strdup("");
swaynag->details.button_down.text = strdup(""); swaynag->details.button_down.text = strdup("");
} }
break; break;
case 'L': // Detailed Button Text case 'L': // Detailed Button Text
if (swaynag) { if (swaynag) {
free(swaynag->details.button_details->text); free(swaynag->details.button_details.text);
swaynag->details.button_details->text = strdup(optarg); swaynag->details.button_details.text = strdup(optarg);
} }
break; break;
case 'm': // Message case 'm': // Message
@ -406,6 +417,10 @@ int swaynag_load_config(char *path, struct swaynag *swaynag, list_t *types) {
break; break;
} }
char *name = calloc(1, close - line); char *name = calloc(1, close - line);
if (!name) {
perror("calloc");
return EXIT_FAILURE;
}
strncat(name, line + 1, close - line - 1); strncat(name, line + 1, close - line - 1);
type = swaynag_type_get(types, name); type = swaynag_type_get(types, name);
if (!type) { if (!type) {
@ -414,8 +429,12 @@ int swaynag_load_config(char *path, struct swaynag *swaynag, list_t *types) {
} }
free(name); free(name);
} else { } else {
char *flag = malloc(sizeof(char) * (nread + 3)); char *flag = malloc(nread + 3);
sprintf(flag, "--%s", line); if (!flag) {
perror("calloc");
return EXIT_FAILURE;
}
snprintf(flag, nread + 3, "--%s", line);
char *argv[] = {"swaynag", flag}; char *argv[] = {"swaynag", flag};
result = swaynag_parse_options(2, argv, swaynag, types, type, result = swaynag_parse_options(2, argv, swaynag, types, type,
NULL, NULL); NULL, NULL);

View file

@ -20,33 +20,20 @@ void sway_terminate(int code) {
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
int exit_code = EXIT_SUCCESS; int status = EXIT_SUCCESS;
list_t *types = create_list(); list_t *types = create_list();
swaynag_types_add_default(types); swaynag_types_add_default(types);
memset(&swaynag, 0, sizeof(swaynag));
swaynag.buttons = create_list(); swaynag.buttons = create_list();
wl_list_init(&swaynag.outputs); wl_list_init(&swaynag.outputs);
wl_list_init(&swaynag.seats); wl_list_init(&swaynag.seats);
struct swaynag_button *button_close =
calloc(sizeof(struct swaynag_button), 1);
button_close->text = strdup("X");
button_close->type = SWAYNAG_ACTION_DISMISS;
list_add(swaynag.buttons, button_close);
swaynag.details.button_details =
calloc(sizeof(struct swaynag_button), 1);
swaynag.details.button_details->text = strdup("Toggle details");
swaynag.details.button_details->type = SWAYNAG_ACTION_EXPAND;
char *config_path = NULL; char *config_path = NULL;
bool debug = false; bool debug = false;
int launch_status = swaynag_parse_options(argc, argv, NULL, NULL, NULL, status = swaynag_parse_options(argc, argv, NULL, NULL, NULL,
&config_path, &debug); &config_path, &debug);
if (launch_status != 0) { if (status != 0) {
exit_code = launch_status;
goto cleanup; goto cleanup;
} }
sway_log_init(debug ? SWAY_DEBUG : SWAY_ERROR, NULL); sway_log_init(debug ? SWAY_DEBUG : SWAY_ERROR, NULL);
@ -56,29 +43,29 @@ int main(int argc, char **argv) {
} }
if (config_path) { if (config_path) {
sway_log(SWAY_DEBUG, "Loading config file: %s", config_path); sway_log(SWAY_DEBUG, "Loading config file: %s", config_path);
int config_status = swaynag_load_config(config_path, &swaynag, types); status = swaynag_load_config(config_path, &swaynag, types);
free(config_path); if (status != 0) {
if (config_status != 0) {
exit_code = config_status;
goto cleanup; goto cleanup;
} }
} }
swaynag.details.button_details.text = strdup("Toggle details");
swaynag.details.button_details.type = SWAYNAG_ACTION_EXPAND;
if (argc > 1) { if (argc > 1) {
struct swaynag_type *type_args = swaynag_type_new("<args>"); struct swaynag_type *type_args = swaynag_type_new("<args>");
list_add(types, type_args); list_add(types, type_args);
int result = swaynag_parse_options(argc, argv, &swaynag, types, status = swaynag_parse_options(argc, argv, &swaynag, types,
type_args, NULL, NULL); type_args, NULL, NULL);
if (result != 0) { if (status != 0) {
exit_code = result;
goto cleanup; goto cleanup;
} }
} }
if (!swaynag.message) { if (!swaynag.message) {
sway_log(SWAY_ERROR, "No message passed. Please provide --message/-m"); sway_log(SWAY_ERROR, "No message passed. Please provide --message/-m");
exit_code = EXIT_FAILURE; status = EXIT_FAILURE;
goto cleanup; goto cleanup;
} }
@ -98,11 +85,13 @@ int main(int argc, char **argv) {
swaynag_types_free(types); swaynag_types_free(types);
struct swaynag_button button_close = { 0 };
button_close.text = strdup("X");
button_close.type = SWAYNAG_ACTION_DISMISS;
list_add(swaynag.buttons, &button_close);
if (swaynag.details.message) { if (swaynag.details.message) {
list_add(swaynag.buttons, swaynag.details.button_details); list_add(swaynag.buttons, &swaynag.details.button_details);
} else {
free(swaynag.details.button_details->text);
free(swaynag.details.button_details);
} }
sway_log(SWAY_DEBUG, "Output: %s", swaynag.type->output); sway_log(SWAY_DEBUG, "Output: %s", swaynag.type->output);
@ -120,12 +109,11 @@ int main(int argc, char **argv) {
swaynag_setup(&swaynag); swaynag_setup(&swaynag);
swaynag_run(&swaynag); swaynag_run(&swaynag);
return exit_code; return status;
cleanup: cleanup:
swaynag_types_free(types); swaynag_types_free(types);
free(swaynag.details.button_details->text); free(swaynag.details.button_details.text);
free(swaynag.details.button_details);
swaynag_destroy(&swaynag); swaynag_destroy(&swaynag);
return exit_code; return status;
} }

View file

@ -28,8 +28,13 @@ static bool terminal_execute(char *terminal, char *command) {
fprintf(tmp, "#!/bin/sh\nrm %s\n%s", fname, command); fprintf(tmp, "#!/bin/sh\nrm %s\n%s", fname, command);
fclose(tmp); fclose(tmp);
chmod(fname, S_IRUSR | S_IWUSR | S_IXUSR); chmod(fname, S_IRUSR | S_IWUSR | S_IXUSR);
char *cmd = malloc(sizeof(char) * (strlen(terminal) + strlen(" -e ") + strlen(fname) + 1)); size_t cmd_size = strlen(terminal) + strlen(" -e ") + strlen(fname) + 1;
sprintf(cmd, "%s -e %s", terminal, fname); char *cmd = malloc(cmd_size);
if (!cmd) {
perror("malloc");
return false;
}
snprintf(cmd, cmd_size, "%s -e %s", terminal, fname);
execlp("sh", "sh", "-c", cmd, NULL); execlp("sh", "sh", "-c", cmd, NULL);
sway_log_errno(SWAY_ERROR, "Failed to run command, execlp() returned."); sway_log_errno(SWAY_ERROR, "Failed to run command, execlp() returned.");
free(cmd); free(cmd);
@ -58,7 +63,7 @@ static void swaynag_button_execute(struct swaynag *swaynag,
} else if (pid == 0) { } else if (pid == 0) {
// Child of the child. Will be reparented to the init process // Child of the child. Will be reparented to the init process
char *terminal = getenv("TERMINAL"); char *terminal = getenv("TERMINAL");
if (button->terminal && terminal && strlen(terminal)) { if (button->terminal && terminal && *terminal) {
sway_log(SWAY_DEBUG, "Found $TERMINAL: %s", terminal); sway_log(SWAY_DEBUG, "Found $TERMINAL: %s", terminal);
if (!terminal_execute(terminal, button->action)) { if (!terminal_execute(terminal, button->action)) {
swaynag_destroy(swaynag); swaynag_destroy(swaynag);
@ -138,7 +143,7 @@ static void update_cursor(struct swaynag_seat *seat) {
const char *cursor_theme = getenv("XCURSOR_THEME"); const char *cursor_theme = getenv("XCURSOR_THEME");
unsigned cursor_size = 24; unsigned cursor_size = 24;
const char *env_cursor_size = getenv("XCURSOR_SIZE"); const char *env_cursor_size = getenv("XCURSOR_SIZE");
if (env_cursor_size && strlen(env_cursor_size) > 0) { if (env_cursor_size && *env_cursor_size) {
errno = 0; errno = 0;
char *end; char *end;
unsigned size = strtoul(env_cursor_size, &end, 10); unsigned size = strtoul(env_cursor_size, &end, 10);
@ -339,6 +344,7 @@ static void handle_global(void *data, struct wl_registry *registry,
struct swaynag_seat *seat = struct swaynag_seat *seat =
calloc(1, sizeof(struct swaynag_seat)); calloc(1, sizeof(struct swaynag_seat));
if (!seat) { if (!seat) {
perror("calloc");
return; return;
} }
@ -356,6 +362,10 @@ static void handle_global(void *data, struct wl_registry *registry,
if (!swaynag->output) { if (!swaynag->output) {
struct swaynag_output *output = struct swaynag_output *output =
calloc(1, sizeof(struct swaynag_output)); calloc(1, sizeof(struct swaynag_output));
if (!output) {
perror("calloc");
return;
}
output->wl_output = wl_registry_bind(registry, name, output->wl_output = wl_registry_bind(registry, name,
&wl_output_interface, 4); &wl_output_interface, 4);
output->wl_name = name; output->wl_name = name;
@ -511,13 +521,8 @@ void swaynag_destroy(struct swaynag *swaynag) {
swaynag_seat_destroy(seat); swaynag_seat_destroy(seat);
} }
if (&swaynag->buffers[0]) { destroy_buffer(&swaynag->buffers[0]);
destroy_buffer(&swaynag->buffers[0]); destroy_buffer(&swaynag->buffers[1]);
}
if (&swaynag->buffers[1]) {
destroy_buffer(&swaynag->buffers[1]);
}
if (swaynag->outputs.prev || swaynag->outputs.next) { if (swaynag->outputs.prev || swaynag->outputs.next) {
struct swaynag_output *output, *temp; struct swaynag_output *output, *temp;