This commit is contained in:
dmitry 2020-08-01 22:28:54 +03:00
commit 5845c6e3c0
45 changed files with 575 additions and 292 deletions

33
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View file

@ -0,0 +1,33 @@
---
name: Bugs
about: Crashes and other bugs
labels: 'bug'
---
### Please read the following before submitting:
- Please do NOT submit bug reports for questions. Ask questions on IRC at #sway on irc.freenode.net.
- Proprietary graphics drivers, including nvidia, are not supported. Please use the open source equivalents, such as nouveau, if you would like to use Sway.
- Problems with the Wayland version of Firefox are likely to be Firefox bugs. Start by submitting your issue to the Firefox Bugzilla and come back here only after they confirm otherwise.
### Please fill out the following:
- **Sway Version:**
- `swaymsg -t get_version` or `sway -v`
- **Debug Log:**
- Run `sway -d 2> ~/sway.log` from a TTY and upload it to a pastebin, such as gist.github.com.
- This will record information about sway's activity. Please try to keep the reproduction as brief as possible and exit sway.
- **Configuration File:**
- Please try to produce with the default configuration.
- If you cannot reproduce with the default configuration, please try to find the minimal configuration to reproduce.
- Upload the config to a pastebin such as gist.github.com.
- **Stack Trace:**
- This is only needed if sway crashes.
- If you use systemd, you should be able to open the coredump of the most recent crash with gdb with
`coredumpctl gdb sway` and then `bt full` to obtain the stack trace.
- If the lines mentioning sway or wlroots have `??` for the location, your binaries were built without debug symbols. Please compile both sway and wlroots from source and try to reproduce.
- **Description:**
- The steps you took in plain English to reproduce the problem.

5
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View file

@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Questions
url: "http://webchat.freenode.net/?channels=sway&uio=d4"
about: "Please ask questions on IRC in #sway on irc.freenode.net"

13
.github/ISSUE_TEMPLATE/enhancement.md vendored Normal file
View file

@ -0,0 +1,13 @@
---
name: Enhancements
about: New functionality
labels: 'enhancement'
---
### Please read the following before submitting:
- We are not accepting any new window management features unless they get implemented by i3. Please consider searching for or opening an i3 feature request.
### Please fill out the following:
- **Description:**
Please describe in plain English what the enhancement is and what the use case is.

20
.github/ISSUE_TEMPLATE/i3_compat.md vendored Normal file
View file

@ -0,0 +1,20 @@
---
name: i3 Compatibility
about: Sway behaves differently from or lacks i3 functionality
labels: 'i3-compat'
---
### Please read the following before submitting:
- The following either do not make sense for Wayland or we have decided against supporting:
- `restart`
- `resource`
- saving and loading layouts
- the i3 sync protocol
### Please fill out the following:
- **i3 PR:**
- If this is new i3 functionality, please add a link to the i3 pull request.
- **Description:**
- Please describe in plain English how Sway and i3's behaviors differ or what functionality Sway is lacking.

View file

@ -1,48 +0,0 @@
If you want to ask a question, please check out the wiki. If you don't find an answer there, ask on IRC (#sway on irc.freenode.net). The issue tracker may not be used for questions.
If you are using the Nvidia proprietary driver for any reason, you have two choices:
1. Uninstall it and use nouveau instead
2. Use X11+i3 and close your browser tab
If `lsmod | grep nvidia | wc -l` shows anything other than zero, your bug report is not welcome here.
Additionally, problems with Firefox are almost certainly Firefox bugs, not sway bugs. Start by submitting your issue to the Firefox Bugzilla and come back here only after they confirm otherwise.
Otherwise, please include the following four components in your bug report: sway version, debug log, configuration (if applicable), and an explanation of steps taken to reproduce the issue. If sway crashes, also include a stack trace.
Obtain your version like so:
swaymsg -t get_version
If this doesn't work, use:
sway -v
* Sway Version:
Obtain a debug log by running the following command from a TTY:
sway -d 2> ~/sway.log
This will record information about sway's activity when it's running. Briefly reproduce your problem and exit sway. When preparing a debug log, brevity is important - start up sway, do the minimum work necessary to reproduce the error, then close sway.
Upload the debug log to a pastebin service such as [gist.github.com](https://gist.github.com), and link to it below.
* Debug Log:
You should try to reproduce the issue with the default configuration. If you cannot, please reproduce with a minimal configuration, upload the config to a pastebin service, and link to it below.
* Configuration File:
Finally, explain the steps you took in plain English to reproduce the problem below.
* Stack Trace, if sway crashes:
If you use systemd, you should be able to open the coredump of the most recent crash with GDB like so:
coredumpctl gdb sway
And then type `bt full` to obtain the stack trace.
If the lines mentioning sway/wlroots have "??" for the location, your binaries were built without debug symbols, and the stack trace is unlikely to be useful. You can find instructions to compile sway from source [here](https://github.com/swaywm/sway/wiki/Development-Setup#compiling-as-a-subproject). Note that debug symbols are included in Meson builds by default.

View file

@ -28,6 +28,8 @@ channel or shoot an email to sir@cmpwn.com for advice.
### Compiling from Source
Check out [this wiki page](https://github.com/swaywm/sway/wiki/Development-Setup) if you want to build the HEAD of sway and wlroots for testing or development.
Install dependencies:
* meson \*

View file

@ -79,7 +79,6 @@ bool ipc_set_recv_timeout(int socketfd, struct timeval tv) {
struct ipc_response *ipc_recv_response(int socketfd) {
char data[IPC_HEADER_SIZE];
uint32_t *data32 = (uint32_t *)(data + sizeof(ipc_magic));
size_t total = 0;
while (total < IPC_HEADER_SIZE) {
@ -95,15 +94,15 @@ struct ipc_response *ipc_recv_response(int socketfd) {
goto error_1;
}
total = 0;
memcpy(&response->size, &data32[0], sizeof(data32[0]));
memcpy(&response->type, &data32[1], sizeof(data32[1]));
memcpy(&response->size, data + sizeof(ipc_magic), sizeof(uint32_t));
memcpy(&response->type, data + sizeof(ipc_magic) + sizeof(uint32_t), sizeof(uint32_t));
char *payload = malloc(response->size + 1);
if (!payload) {
goto error_2;
}
total = 0;
while (total < response->size) {
ssize_t received = recv(socketfd, payload + total, response->size - total, 0);
if (received < 0) {
@ -129,10 +128,9 @@ void free_ipc_response(struct ipc_response *response) {
char *ipc_single_command(int socketfd, uint32_t type, const char *payload, uint32_t *len) {
char data[IPC_HEADER_SIZE];
uint32_t *data32 = (uint32_t *)(data + sizeof(ipc_magic));
memcpy(data, ipc_magic, sizeof(ipc_magic));
memcpy(&data32[0], len, sizeof(*len));
memcpy(&data32[1], &type, sizeof(type));
memcpy(data + sizeof(ipc_magic), len, sizeof(*len));
memcpy(data + sizeof(ipc_magic) + sizeof(*len), &type, sizeof(type));
if (write(socketfd, data, IPC_HEADER_SIZE) == -1) {
sway_abort("Unable to send IPC header");

View file

@ -117,9 +117,15 @@ void loop_add_fd(struct loop *loop, int fd, short mask,
struct pollfd pfd = {fd, mask, 0};
if (loop->fd_length == loop->fd_capacity) {
loop->fd_capacity += 10;
loop->fds = realloc(loop->fds,
sizeof(struct pollfd) * loop->fd_capacity);
int capacity = loop->fd_capacity + 10;
struct pollfd *tmp = realloc(loop->fds,
sizeof(struct pollfd) * capacity);
if (!tmp) {
sway_log(SWAY_ERROR, "Unable to allocate memory for pollfd");
return;
}
loop->fds = tmp;
loop->fd_capacity = capacity;
}
loop->fds[loop->fd_length++] = pfd;

View file

@ -71,6 +71,40 @@ float parse_float(const char *value) {
return flt;
}
enum movement_unit parse_movement_unit(const char *unit) {
if (strcasecmp(unit, "px") == 0) {
return MOVEMENT_UNIT_PX;
}
if (strcasecmp(unit, "ppt") == 0) {
return MOVEMENT_UNIT_PPT;
}
if (strcasecmp(unit, "default") == 0) {
return MOVEMENT_UNIT_DEFAULT;
}
return MOVEMENT_UNIT_INVALID;
}
int parse_movement_amount(int argc, char **argv,
struct movement_amount *amount) {
char *err;
amount->amount = (int)strtol(argv[0], &err, 10);
if (*err) {
// e.g. 10px
amount->unit = parse_movement_unit(err);
return 1;
}
if (argc == 1) {
amount->unit = MOVEMENT_UNIT_DEFAULT;
return 1;
}
// Try the second argument
amount->unit = parse_movement_unit(argv[1]);
if (amount->unit == MOVEMENT_UNIT_INVALID) {
amount->unit = MOVEMENT_UNIT_DEFAULT;
return 1;
}
return 2;
}
const char *sway_wl_output_subpixel_to_string(enum wl_output_subpixel subpixel) {
switch (subpixel) {

View file

@ -37,8 +37,7 @@ output * bg @datadir@/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png fill
#
# exec swayidle -w \
# timeout 300 'swaylock -f -c 000000' \
# timeout 600 'swaymsg "output * dpms off"' \
# resume 'swaymsg "output * dpms on"' \
# timeout 600 'swaymsg "output * dpms off"' resume 'swaymsg "output * dpms on"' \
# before-sleep 'swaylock -f -c 000000'
#
# This will lock your screen after 300 seconds of inactivity, then turn off
@ -112,27 +111,27 @@ output * bg @datadir@/backgrounds/sway/Sway_Wallpaper_Blue_1920x1080.png fill
# Workspaces:
#
# Switch to workspace
bindsym $mod+1 workspace 1
bindsym $mod+2 workspace 2
bindsym $mod+3 workspace 3
bindsym $mod+4 workspace 4
bindsym $mod+5 workspace 5
bindsym $mod+6 workspace 6
bindsym $mod+7 workspace 7
bindsym $mod+8 workspace 8
bindsym $mod+9 workspace 9
bindsym $mod+0 workspace 10
bindsym $mod+1 workspace number 1
bindsym $mod+2 workspace number 2
bindsym $mod+3 workspace number 3
bindsym $mod+4 workspace number 4
bindsym $mod+5 workspace number 5
bindsym $mod+6 workspace number 6
bindsym $mod+7 workspace number 7
bindsym $mod+8 workspace number 8
bindsym $mod+9 workspace number 9
bindsym $mod+0 workspace number 10
# Move focused container to workspace
bindsym $mod+Shift+1 move container to workspace 1
bindsym $mod+Shift+2 move container to workspace 2
bindsym $mod+Shift+3 move container to workspace 3
bindsym $mod+Shift+4 move container to workspace 4
bindsym $mod+Shift+5 move container to workspace 5
bindsym $mod+Shift+6 move container to workspace 6
bindsym $mod+Shift+7 move container to workspace 7
bindsym $mod+Shift+8 move container to workspace 8
bindsym $mod+Shift+9 move container to workspace 9
bindsym $mod+Shift+0 move container to workspace 10
bindsym $mod+Shift+1 move container to workspace number 1
bindsym $mod+Shift+2 move container to workspace number 2
bindsym $mod+Shift+3 move container to workspace number 3
bindsym $mod+Shift+4 move container to workspace number 4
bindsym $mod+Shift+5 move container to workspace number 5
bindsym $mod+Shift+6 move container to workspace number 6
bindsym $mod+Shift+7 move container to workspace number 7
bindsym $mod+Shift+8 move container to workspace number 8
bindsym $mod+Shift+9 move container to workspace number 9
bindsym $mod+Shift+0 move container to workspace number 10
# Note: workspaces can have any name you want, not just numbers.
# We just use 1-10 as the default.
#

View file

@ -1,6 +1,13 @@
#!/bin/sh -eu
old_version="$1"
new_version="$2"
if [ "$new_version" != "${new_version#v}" ]
then
echo "Error: The new version shouldn't be prefixed with a \"v\"." >&2
exit 1
fi
sed -i meson.build -e "s/^ version: .*#release_version/ version: '$new_version', #release_version/g"
printf "Minimum wlroots version? "

View file

@ -111,6 +111,10 @@ if [ "$ACTION" = "check" ] ; then
exit
elif [ "$SUBJECT" = "area" ] ; then
GEOM=$(slurp -d)
# Check if user exited slurp without selecting the area
if [ -z "$GEOM" ]; then
exit
fi
WHAT="Area"
elif [ "$SUBJECT" = "active" ] ; then
FOCUSED=$(swaymsg -t get_tree | jq -r 'recurse(.nodes[]?, .floating_nodes[]?) | select(.focused)')
@ -126,6 +130,10 @@ elif [ "$SUBJECT" = "output" ] ; then
WHAT="$OUTPUT"
elif [ "$SUBJECT" = "window" ] ; then
GEOM=$(swaymsg -t get_tree | jq -r '.. | select(.pid? and .visible?) | .rect | "\(.x),\(.y) \(.width)x\(.height)"' | slurp)
# Check if user exited slurp without selecting the area
if [ -z "$GEOM" ]; then
exit
fi
WHAT="Window"
else
die "Unknown subject to take a screen shot from" "$SUBJECT"

View file

@ -500,6 +500,7 @@ struct sway_config {
struct side_gaps gaps_outer;
list_t *config_chain;
bool user_config_path;
const char *current_config_path;
const char *current_config;
int current_config_line_number;

View file

@ -36,7 +36,7 @@ struct sway_output {
// last applied mode when the output is DPMS'ed
struct wlr_output_mode *current_mode;
bool enabled, configured;
bool enabling, enabled;
list_t *workspaces;
struct sway_output_state current;
@ -98,7 +98,7 @@ struct sway_output *all_output_by_name_or_id(const char *name_or_id);
void output_sort_workspaces(struct sway_output *output);
void output_configure(struct sway_output *output);
void output_enable(struct sway_output *output);
void output_disable(struct sway_output *output);

View file

@ -219,6 +219,8 @@ void container_floating_resize_and_center(struct sway_container *con);
void container_floating_set_default_size(struct sway_container *con);
void container_set_resizing(struct sway_container *con, bool resizing);
void container_set_floating(struct sway_container *container, bool enable);
void container_set_geometry_from_content(struct sway_container *con);

View file

@ -43,6 +43,7 @@ struct sway_view_impl {
void (*set_activated)(struct sway_view *view, bool activated);
void (*set_tiled)(struct sway_view *view, bool tiled);
void (*set_fullscreen)(struct sway_view *view, bool fullscreen);
void (*set_resizing)(struct sway_view *view, bool resizing);
bool (*wants_floating)(struct sway_view *view);
void (*for_each_surface)(struct sway_view *view,
wlr_surface_iterator_func_t iterator, void *user_data);
@ -146,6 +147,7 @@ struct sway_xwayland_view {
struct wl_listener request_move;
struct wl_listener request_resize;
struct wl_listener request_maximize;
struct wl_listener request_minimize;
struct wl_listener request_configure;
struct wl_listener request_fullscreen;
struct wl_listener request_activate;

View file

@ -5,6 +5,30 @@
#include <stdbool.h>
#include <wayland-server-protocol.h>
enum movement_unit {
MOVEMENT_UNIT_PX,
MOVEMENT_UNIT_PPT,
MOVEMENT_UNIT_DEFAULT,
MOVEMENT_UNIT_INVALID,
};
struct movement_amount {
int amount;
enum movement_unit unit;
};
/*
* Parse units such as "px" or "ppt"
*/
enum movement_unit parse_movement_unit(const char *unit);
/*
* Parse arguments such as "10", "10px" or "10 px".
* Returns the number of arguments consumed.
*/
int parse_movement_amount(int argc, char **argv,
struct movement_amount *amount);
/**
* Get the current time, in milliseconds.
*/

View file

@ -1,7 +1,7 @@
project(
'sway',
'c',
version: 'v1.5-rc2', #release_version
version: '1.5', #release_version
license: 'MIT',
meson_version: '>=0.53.0',
default_options: [
@ -60,7 +60,7 @@ math = cc.find_library('m')
rt = cc.find_library('rt')
# Try first to find wlroots as a subproject, then as a system dependency
wlroots_version = ['>=0.10.0', '<0.11.0']
wlroots_version = ['>=0.11.0', '<0.12.0']
wlroots_proj = subproject(
'wlroots',
default_options: ['examples=false'],

View file

@ -72,7 +72,6 @@ static struct cmd_handler handlers[] = {
{ "fullscreen", cmd_fullscreen },
{ "gaps", cmd_gaps },
{ "hide_edge_borders", cmd_hide_edge_borders },
{ "include", cmd_include },
{ "input", cmd_input },
{ "mode", cmd_mode },
{ "mouse_warping", cmd_mouse_warping },
@ -101,6 +100,7 @@ static struct cmd_handler handlers[] = {
/* Config-time only commands. Keep alphabetized */
static struct cmd_handler config_handlers[] = {
{ "default_orientation", cmd_default_orientation },
{ "include", cmd_include },
{ "swaybg_command", cmd_swaybg_command },
{ "swaynag_command", cmd_swaynag_command },
{ "workspace_layout", cmd_workspace_layout },

View file

@ -24,6 +24,9 @@ static char *hex_to_rgba_hex(const char *hex) {
return NULL;
}
char *rgba = malloc(10);
if (!rgba) {
return NULL;
}
snprintf(rgba, 10, "#%08x", color);
return rgba;
}
@ -36,7 +39,7 @@ static struct cmd_results *parse_single_color(char **color,
}
char *rgba = hex_to_rgba_hex(argv[0]);
if (!*rgba) {
if (!rgba) {
return cmd_results_new(CMD_INVALID, "Invalid color: %s", argv[0]);
}

View file

@ -715,7 +715,7 @@ bool translate_binding(struct sway_binding *binding) {
struct keycode_matches matches = get_keycode_for_keysym(*keysym);
if (matches.count != 1) {
sway_log(SWAY_INFO, "Unable to convert keysym %d into"
sway_log(SWAY_INFO, "Unable to convert keysym %" PRIu32 " into"
" a single keycode (found %d matches)",
*keysym, matches.count);
goto error;

View file

@ -1,5 +1,6 @@
#define _POSIX_C_SOURCE 200809L
#include <ctype.h>
#include <math.h>
#include <stdbool.h>
#include <string.h>
#include <strings.h>
@ -753,6 +754,38 @@ static struct cmd_results *cmd_move_in_direction(
return cmd_results_new(CMD_SUCCESS, NULL);
}
static struct cmd_results *cmd_move_to_position_pointer(
struct sway_container *container) {
struct sway_seat *seat = config->handler_context.seat;
if (!seat->cursor) {
return cmd_results_new(CMD_FAILURE, "No cursor device");
}
struct wlr_cursor *cursor = seat->cursor->cursor;
/* Determine where to put the window. */
double lx = cursor->x - container->width / 2;
double ly = cursor->y - container->height / 2;
/* Correct target coordinates to be in bounds (on screen). */
struct wlr_output *output = wlr_output_layout_output_at(
root->output_layout, cursor->x, cursor->y);
if (output) {
struct wlr_box *box =
wlr_output_layout_get_box(root->output_layout, output);
lx = fmax(lx, box->x);
ly = fmax(ly, box->y);
if (lx + container->width > box->x + box->width) {
lx = box->x + box->width - container->width;
}
if (ly + container->height > box->y + box->height) {
ly = box->y + box->height - container->height;
}
}
/* Actually move the container. */
container_floating_move_to(container, lx, ly);
return cmd_results_new(CMD_SUCCESS, NULL);
}
static const char expected_position_syntax[] =
"Expected 'move [absolute] position <x> [px] <y> [px]' or "
"'move [absolute] position center' or "
@ -790,14 +823,7 @@ static struct cmd_results *cmd_move_to_position(int argc, char **argv) {
if (absolute) {
return cmd_results_new(CMD_INVALID, expected_position_syntax);
}
struct sway_seat *seat = config->handler_context.seat;
if (!seat->cursor) {
return cmd_results_new(CMD_FAILURE, "No cursor device");
}
double lx = seat->cursor->cursor->x - container->width / 2;
double ly = seat->cursor->cursor->y - container->height / 2;
container_floating_move_to(container, lx, ly);
return cmd_results_new(CMD_SUCCESS, NULL);
return cmd_move_to_position_pointer(container);
} else if (strcmp(argv[0], "center") == 0) {
double lx, ly;
if (absolute) {
@ -820,37 +846,81 @@ static struct cmd_results *cmd_move_to_position(int argc, char **argv) {
return cmd_results_new(CMD_FAILURE, expected_position_syntax);
}
double lx, ly;
char *inv;
lx = (double)strtol(argv[0], &inv, 10);
if (*inv != '\0' && strcasecmp(inv, "px") != 0) {
return cmd_results_new(CMD_FAILURE, "Invalid position specified");
}
if (strcmp(argv[1], "px") == 0) {
--argc;
++argv;
struct movement_amount lx = { .amount = 0, .unit = MOVEMENT_UNIT_INVALID };
// X direction
int num_consumed_args = parse_movement_amount(argc, argv, &lx);
argc -= num_consumed_args;
argv += num_consumed_args;
if (lx.unit == MOVEMENT_UNIT_INVALID) {
return cmd_results_new(CMD_INVALID, "Invalid x position specified");
}
if (argc > 3) {
return cmd_results_new(CMD_FAILURE, expected_position_syntax);
struct movement_amount ly = { .amount = 0, .unit = MOVEMENT_UNIT_INVALID };
// Y direction
num_consumed_args = parse_movement_amount(argc, argv, &ly);
argc -= num_consumed_args;
argv += num_consumed_args;
if (argc > 0) {
return cmd_results_new(CMD_INVALID, expected_position_syntax);
}
if (ly.unit == MOVEMENT_UNIT_INVALID) {
return cmd_results_new(CMD_INVALID, "Invalid y position specified");
}
ly = (double)strtol(argv[1], &inv, 10);
if ((*inv != '\0' && strcasecmp(inv, "px") != 0) ||
(argc == 3 && strcmp(argv[2], "px") != 0)) {
return cmd_results_new(CMD_FAILURE, "Invalid position specified");
struct sway_workspace *ws = container->workspace;
if (!ws) {
struct sway_seat *seat = config->handler_context.seat;
ws = seat_get_focused_workspace(seat);
}
if (!absolute) {
struct sway_workspace *ws = container->workspace;
if (!ws) {
struct sway_seat *seat = config->handler_context.seat;
ws = seat_get_focused_workspace(seat);
switch (lx.unit) {
case MOVEMENT_UNIT_PPT:
if (container_is_scratchpad_hidden(container)) {
return cmd_results_new(CMD_FAILURE,
"Cannot move a hidden scratchpad container by ppt");
}
lx += ws->x;
ly += ws->y;
if (absolute) {
return cmd_results_new(CMD_FAILURE,
"Cannot move to absolute positions by ppt");
}
// Convert to px
lx.amount = ws->width * lx.amount / 100;
lx.unit = MOVEMENT_UNIT_PX;
// Falls through
case MOVEMENT_UNIT_PX:
case MOVEMENT_UNIT_DEFAULT:
break;
case MOVEMENT_UNIT_INVALID:
sway_assert(false, "invalid x unit");
break;
}
container_floating_move_to(container, lx, ly);
switch (ly.unit) {
case MOVEMENT_UNIT_PPT:
if (container_is_scratchpad_hidden(container)) {
return cmd_results_new(CMD_FAILURE,
"Cannot move a hidden scratchpad container by ppt");
}
if (absolute) {
return cmd_results_new(CMD_FAILURE,
"Cannot move to absolute positions by ppt");
}
// Convert to px
ly.amount = ws->height * ly.amount / 100;
ly.unit = MOVEMENT_UNIT_PX;
// Falls through
case MOVEMENT_UNIT_PX:
case MOVEMENT_UNIT_DEFAULT:
break;
case MOVEMENT_UNIT_INVALID:
sway_assert(false, "invalid y unit");
break;
}
if (!absolute) {
lx.amount += ws->x;
ly.amount += ws->y;
}
container_floating_move_to(container, lx.amount, ly.amount);
return cmd_results_new(CMD_SUCCESS, NULL);
}

View file

@ -22,7 +22,12 @@ static void do_reload(void *data) {
list_add(bar_ids, strdup(bar->id));
}
if (!load_main_config(config->current_config_path, true, false)) {
const char *path = NULL;
if (config->user_config_path) {
path = config->current_config_path;
}
if (!load_main_config(path, true, false)) {
sway_log(SWAY_ERROR, "Error(s) reloading config");
list_free_items_and_destroy(bar_ids);
return;
@ -55,7 +60,12 @@ struct cmd_results *cmd_reload(int argc, char **argv) {
return error;
}
if (!load_main_config(config->current_config_path, true, true)) {
const char *path = NULL;
if (config->user_config_path) {
path = config->current_config_path;
}
if (!load_main_config(path, true, true)) {
return cmd_results_new(CMD_FAILURE, "Error(s) reloading config.");
}

View file

@ -11,59 +11,11 @@
#include "sway/tree/view.h"
#include "sway/tree/workspace.h"
#include "log.h"
#include "util.h"
#define AXIS_HORIZONTAL (WLR_EDGE_LEFT | WLR_EDGE_RIGHT)
#define AXIS_VERTICAL (WLR_EDGE_TOP | WLR_EDGE_BOTTOM)
enum resize_unit {
RESIZE_UNIT_PX,
RESIZE_UNIT_PPT,
RESIZE_UNIT_DEFAULT,
RESIZE_UNIT_INVALID,
};
struct resize_amount {
int amount;
enum resize_unit unit;
};
static enum resize_unit parse_resize_unit(const char *unit) {
if (strcasecmp(unit, "px") == 0) {
return RESIZE_UNIT_PX;
}
if (strcasecmp(unit, "ppt") == 0) {
return RESIZE_UNIT_PPT;
}
if (strcasecmp(unit, "default") == 0) {
return RESIZE_UNIT_DEFAULT;
}
return RESIZE_UNIT_INVALID;
}
// Parse arguments such as "10", "10px" or "10 px".
// Returns the number of arguments consumed.
static int parse_resize_amount(int argc, char **argv,
struct resize_amount *amount) {
char *err;
amount->amount = (int)strtol(argv[0], &err, 10);
if (*err) {
// e.g. 10px
amount->unit = parse_resize_unit(err);
return 1;
}
if (argc == 1) {
amount->unit = RESIZE_UNIT_DEFAULT;
return 1;
}
// Try the second argument
amount->unit = parse_resize_unit(argv[1]);
if (amount->unit == RESIZE_UNIT_INVALID) {
amount->unit = RESIZE_UNIT_DEFAULT;
return 1;
}
return 2;
}
static uint32_t parse_resize_axis(const char *axis) {
if (strcasecmp(axis, "width") == 0 || strcasecmp(axis, "horizontal") == 0) {
return AXIS_HORIZONTAL;
@ -237,7 +189,7 @@ void container_resize_tiled(struct sway_container *con,
* Implement `resize <grow|shrink>` for a floating container.
*/
static struct cmd_results *resize_adjust_floating(uint32_t axis,
struct resize_amount *amount) {
struct movement_amount *amount) {
struct sway_container *con = config->handler_context.container;
int grow_width = 0, grow_height = 0;
@ -294,13 +246,13 @@ static struct cmd_results *resize_adjust_floating(uint32_t axis,
* Implement `resize <grow|shrink>` for a tiled container.
*/
static struct cmd_results *resize_adjust_tiled(uint32_t axis,
struct resize_amount *amount) {
struct movement_amount *amount) {
struct sway_container *current = config->handler_context.container;
if (amount->unit == RESIZE_UNIT_DEFAULT) {
amount->unit = RESIZE_UNIT_PPT;
if (amount->unit == MOVEMENT_UNIT_DEFAULT) {
amount->unit = MOVEMENT_UNIT_PPT;
}
if (amount->unit == RESIZE_UNIT_PPT) {
if (amount->unit == MOVEMENT_UNIT_PPT) {
float pct = amount->amount / 100.0f;
if (is_horizontal(axis)) {
@ -324,10 +276,10 @@ static struct cmd_results *resize_adjust_tiled(uint32_t axis,
* Implement `resize set` for a tiled container.
*/
static struct cmd_results *resize_set_tiled(struct sway_container *con,
struct resize_amount *width, struct resize_amount *height) {
struct movement_amount *width, struct movement_amount *height) {
if (width->amount) {
if (width->unit == RESIZE_UNIT_PPT ||
width->unit == RESIZE_UNIT_DEFAULT) {
if (width->unit == MOVEMENT_UNIT_PPT ||
width->unit == MOVEMENT_UNIT_DEFAULT) {
// Convert to px
struct sway_container *parent = con->parent;
while (parent && parent->layout != L_HORIZ) {
@ -338,17 +290,17 @@ static struct cmd_results *resize_set_tiled(struct sway_container *con,
} else {
width->amount = con->workspace->width * width->amount / 100;
}
width->unit = RESIZE_UNIT_PX;
width->unit = MOVEMENT_UNIT_PX;
}
if (width->unit == RESIZE_UNIT_PX) {
if (width->unit == MOVEMENT_UNIT_PX) {
container_resize_tiled(con, AXIS_HORIZONTAL,
width->amount - con->width);
}
}
if (height->amount) {
if (height->unit == RESIZE_UNIT_PPT ||
height->unit == RESIZE_UNIT_DEFAULT) {
if (height->unit == MOVEMENT_UNIT_PPT ||
height->unit == MOVEMENT_UNIT_DEFAULT) {
// Convert to px
struct sway_container *parent = con->parent;
while (parent && parent->layout != L_VERT) {
@ -359,9 +311,9 @@ static struct cmd_results *resize_set_tiled(struct sway_container *con,
} else {
height->amount = con->workspace->height * height->amount / 100;
}
height->unit = RESIZE_UNIT_PX;
height->unit = MOVEMENT_UNIT_PX;
}
if (height->unit == RESIZE_UNIT_PX) {
if (height->unit == MOVEMENT_UNIT_PX) {
container_resize_tiled(con, AXIS_VERTICAL,
height->amount - con->height);
}
@ -374,30 +326,30 @@ static struct cmd_results *resize_set_tiled(struct sway_container *con,
* Implement `resize set` for a floating container.
*/
static struct cmd_results *resize_set_floating(struct sway_container *con,
struct resize_amount *width, struct resize_amount *height) {
struct movement_amount *width, struct movement_amount *height) {
int min_width, max_width, min_height, max_height, grow_width = 0, grow_height = 0;
floating_calculate_constraints(&min_width, &max_width,
&min_height, &max_height);
if (width->amount) {
switch (width->unit) {
case RESIZE_UNIT_PPT:
case MOVEMENT_UNIT_PPT:
if (container_is_scratchpad_hidden(con)) {
return cmd_results_new(CMD_FAILURE,
"Cannot resize a hidden scratchpad container by ppt");
}
// Convert to px
width->amount = con->workspace->width * width->amount / 100;
width->unit = RESIZE_UNIT_PX;
width->unit = MOVEMENT_UNIT_PX;
// Falls through
case RESIZE_UNIT_PX:
case RESIZE_UNIT_DEFAULT:
case MOVEMENT_UNIT_PX:
case MOVEMENT_UNIT_DEFAULT:
width->amount = fmax(min_width, fmin(width->amount, max_width));
grow_width = width->amount - con->width;
con->x -= grow_width / 2;
con->width = width->amount;
break;
case RESIZE_UNIT_INVALID:
case MOVEMENT_UNIT_INVALID:
sway_assert(false, "invalid width unit");
break;
}
@ -405,23 +357,23 @@ static struct cmd_results *resize_set_floating(struct sway_container *con,
if (height->amount) {
switch (height->unit) {
case RESIZE_UNIT_PPT:
case MOVEMENT_UNIT_PPT:
if (container_is_scratchpad_hidden(con)) {
return cmd_results_new(CMD_FAILURE,
"Cannot resize a hidden scratchpad container by ppt");
}
// Convert to px
height->amount = con->workspace->height * height->amount / 100;
height->unit = RESIZE_UNIT_PX;
height->unit = MOVEMENT_UNIT_PX;
// Falls through
case RESIZE_UNIT_PX:
case RESIZE_UNIT_DEFAULT:
case MOVEMENT_UNIT_PX:
case MOVEMENT_UNIT_DEFAULT:
height->amount = fmax(min_height, fmin(height->amount, max_height));
grow_height = height->amount - con->height;
con->y -= grow_height / 2;
con->height = height->amount;
break;
case RESIZE_UNIT_INVALID:
case MOVEMENT_UNIT_INVALID:
sway_assert(false, "invalid height unit");
break;
}
@ -454,30 +406,30 @@ static struct cmd_results *cmd_resize_set(int argc, char **argv) {
"'resize set [width] <width> [px|ppt] [height] <height> [px|ppt]'";
// Width
struct resize_amount width = {0};
struct movement_amount width = {0};
if (argc >= 2 && !strcmp(argv[0], "width") && strcmp(argv[1], "height")) {
argc--; argv++;
}
if (strcmp(argv[0], "height")) {
int num_consumed_args = parse_resize_amount(argc, argv, &width);
int num_consumed_args = parse_movement_amount(argc, argv, &width);
argc -= num_consumed_args;
argv += num_consumed_args;
if (width.unit == RESIZE_UNIT_INVALID) {
if (width.unit == MOVEMENT_UNIT_INVALID) {
return cmd_results_new(CMD_INVALID, usage);
}
}
// Height
struct resize_amount height = {0};
struct movement_amount height = {0};
if (argc) {
if (argc >= 2 && !strcmp(argv[0], "height")) {
argc--; argv++;
}
int num_consumed_args = parse_resize_amount(argc, argv, &height);
int num_consumed_args = parse_movement_amount(argc, argv, &height);
if (argc > num_consumed_args) {
return cmd_results_new(CMD_INVALID, usage);
}
if (width.unit == RESIZE_UNIT_INVALID) {
if (width.unit == MOVEMENT_UNIT_INVALID) {
return cmd_results_new(CMD_INVALID, usage);
}
}
@ -515,17 +467,17 @@ static struct cmd_results *cmd_resize_adjust(int argc, char **argv,
--argc; ++argv;
// First amount
struct resize_amount first_amount;
struct movement_amount first_amount;
if (argc) {
int num_consumed_args = parse_resize_amount(argc, argv, &first_amount);
int num_consumed_args = parse_movement_amount(argc, argv, &first_amount);
argc -= num_consumed_args;
argv += num_consumed_args;
if (first_amount.unit == RESIZE_UNIT_INVALID) {
if (first_amount.unit == MOVEMENT_UNIT_INVALID) {
return cmd_results_new(CMD_INVALID, usage);
}
} else {
first_amount.amount = 10;
first_amount.unit = RESIZE_UNIT_DEFAULT;
first_amount.unit = MOVEMENT_UNIT_DEFAULT;
}
// "or"
@ -537,18 +489,18 @@ static struct cmd_results *cmd_resize_adjust(int argc, char **argv,
}
// Second amount
struct resize_amount second_amount;
struct movement_amount second_amount;
if (argc) {
int num_consumed_args = parse_resize_amount(argc, argv, &second_amount);
int num_consumed_args = parse_movement_amount(argc, argv, &second_amount);
if (argc > num_consumed_args) {
return cmd_results_new(CMD_INVALID, usage);
}
if (second_amount.unit == RESIZE_UNIT_INVALID) {
if (second_amount.unit == MOVEMENT_UNIT_INVALID) {
return cmd_results_new(CMD_INVALID, usage);
}
} else {
second_amount.amount = 0;
second_amount.unit = RESIZE_UNIT_INVALID;
second_amount.unit = MOVEMENT_UNIT_INVALID;
}
first_amount.amount *= multiplier;
@ -558,13 +510,13 @@ static struct cmd_results *cmd_resize_adjust(int argc, char **argv,
if (container_is_floating(con)) {
// Floating containers can only resize in px. Choose an amount which
// uses px, with fallback to an amount that specified no unit.
if (first_amount.unit == RESIZE_UNIT_PX) {
if (first_amount.unit == MOVEMENT_UNIT_PX) {
return resize_adjust_floating(axis, &first_amount);
} else if (second_amount.unit == RESIZE_UNIT_PX) {
} else if (second_amount.unit == MOVEMENT_UNIT_PX) {
return resize_adjust_floating(axis, &second_amount);
} else if (first_amount.unit == RESIZE_UNIT_DEFAULT) {
} else if (first_amount.unit == MOVEMENT_UNIT_DEFAULT) {
return resize_adjust_floating(axis, &first_amount);
} else if (second_amount.unit == RESIZE_UNIT_DEFAULT) {
} else if (second_amount.unit == MOVEMENT_UNIT_DEFAULT) {
return resize_adjust_floating(axis, &second_amount);
} else {
return cmd_results_new(CMD_INVALID,
@ -573,13 +525,13 @@ static struct cmd_results *cmd_resize_adjust(int argc, char **argv,
}
// For tiling, prefer ppt -> default -> px
if (first_amount.unit == RESIZE_UNIT_PPT) {
if (first_amount.unit == MOVEMENT_UNIT_PPT) {
return resize_adjust_tiled(axis, &first_amount);
} else if (second_amount.unit == RESIZE_UNIT_PPT) {
} else if (second_amount.unit == MOVEMENT_UNIT_PPT) {
return resize_adjust_tiled(axis, &second_amount);
} else if (first_amount.unit == RESIZE_UNIT_DEFAULT) {
} else if (first_amount.unit == MOVEMENT_UNIT_DEFAULT) {
return resize_adjust_tiled(axis, &first_amount);
} else if (second_amount.unit == RESIZE_UNIT_DEFAULT) {
} else if (second_amount.unit == MOVEMENT_UNIT_DEFAULT) {
return resize_adjust_tiled(axis, &second_amount);
} else {
return resize_adjust_tiled(axis, &first_amount);

View file

@ -447,6 +447,7 @@ bool load_main_config(const char *file, bool is_active, bool validating) {
}
}
config->user_config_path = file ? true : false;
config->current_config_path = path;
list_add(config->config_chain, real_path);

View file

@ -397,17 +397,8 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) {
struct wlr_output *wlr_output = output->wlr_output;
bool was_enabled = output->enabled;
if (oc && !oc->enabled) {
// Output is configured to be disabled
sway_log(SWAY_DEBUG, "Disabling output %s", oc->name);
if (output->enabled) {
output_disable(output);
wlr_output_layout_remove(root->output_layout, wlr_output);
}
} else {
output->enabled = true;
}
// Flag to prevent the output mode event handler from calling us
output->enabling = (!oc || oc->enabled);
queue_output_config(oc, output);
@ -421,11 +412,18 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) {
// Leave the output disabled for now and try again when the output gets
// the mode we asked for.
sway_log(SWAY_ERROR, "Failed to commit output %s", wlr_output->name);
output->enabled = was_enabled;
output->enabling = false;
return false;
}
output->enabling = false;
if (oc && !oc->enabled) {
sway_log(SWAY_DEBUG, "Disabling output %s", oc->name);
if (output->enabled) {
output_disable(output);
wlr_output_layout_remove(root->output_layout, wlr_output);
}
return true;
}
@ -468,8 +466,8 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) {
output->width = output_box->width;
output->height = output_box->height;
if (!output->configured) {
output_configure(output);
if (!output->enabled) {
output_enable(output);
}
if (oc && oc->max_render_time >= 0) {

View file

@ -510,11 +510,11 @@ struct sway_layer_surface *layer_from_wlr_layer_surface_v1(
void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
struct wlr_layer_surface_v1 *layer_surface = data;
sway_log(SWAY_DEBUG, "new layer surface: namespace %s layer %d anchor %d "
"size %dx%d margin %d,%d,%d,%d",
sway_log(SWAY_DEBUG, "new layer surface: namespace %s layer %d anchor %" PRIu32
" size %" PRIu32 "x%" PRIu32 " margin %" PRIu32 ",%" PRIu32 ",%" PRIu32 ",%" PRIu32 ",",
layer_surface->namespace,
layer_surface->client_pending.layer,
layer_surface->client_pending.layer,
layer_surface->client_pending.anchor,
layer_surface->client_pending.desired_width,
layer_surface->client_pending.desired_height,
layer_surface->client_pending.margin.top,

View file

@ -844,7 +844,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
static void handle_mode(struct wl_listener *listener, void *data) {
struct sway_output *output = wl_container_of(listener, output, mode);
if (!output->configured && !output->enabled) {
if (!output->enabled && !output->enabling) {
struct output_config *oc = find_output_config(output);
if (output->wlr_output->current_mode != NULL &&
(!oc || oc->enabled)) {
@ -857,7 +857,7 @@ static void handle_mode(struct wl_listener *listener, void *data) {
}
return;
}
if (!output->enabled || !output->configured) {
if (!output->enabled) {
return;
}
arrange_layers(output);
@ -869,7 +869,7 @@ static void handle_mode(struct wl_listener *listener, void *data) {
static void handle_transform(struct wl_listener *listener, void *data) {
struct sway_output *output = wl_container_of(listener, output, transform);
if (!output->enabled || !output->configured) {
if (!output->enabled) {
return;
}
arrange_layers(output);
@ -886,7 +886,7 @@ static void update_textures(struct sway_container *con, void *data) {
static void handle_scale(struct wl_listener *listener, void *data) {
struct sway_output *output = wl_container_of(listener, output, scale);
if (!output->enabled || !output->configured) {
if (!output->enabled) {
return;
}
arrange_layers(output);
@ -996,7 +996,8 @@ static void output_manager_apply(struct sway_server *server,
} else {
oc->width = config_head->state.custom_mode.width;
oc->height = config_head->state.custom_mode.height;
oc->refresh_rate = config_head->state.custom_mode.refresh;
oc->refresh_rate =
config_head->state.custom_mode.refresh / 1000.f;
}
oc->x = config_head->state.x;
oc->y = config_head->state.y;

View file

@ -185,6 +185,14 @@ static void set_fullscreen(struct sway_view *view, bool fullscreen) {
wlr_xdg_toplevel_set_fullscreen(surface, fullscreen);
}
static void set_resizing(struct sway_view *view, bool resizing) {
if (xdg_shell_view_from_view(view) == NULL) {
return;
}
struct wlr_xdg_surface *surface = view->wlr_xdg_surface;
wlr_xdg_toplevel_set_resizing(surface, resizing);
}
static bool wants_floating(struct sway_view *view) {
struct wlr_xdg_toplevel *toplevel = view->wlr_xdg_surface->toplevel;
struct wlr_xdg_toplevel_state *state = &toplevel->current;
@ -260,6 +268,7 @@ static const struct sway_view_impl view_impl = {
.set_activated = set_activated,
.set_tiled = set_tiled,
.set_fullscreen = set_fullscreen,
.set_resizing = set_resizing,
.wants_floating = wants_floating,
.for_each_surface = for_each_surface,
.for_each_popup = for_each_popup,
@ -360,6 +369,11 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data)
transaction_commit_dirty();
}
static void handle_request_maximize(struct wl_listener *listener, void *data) {
struct wlr_xdg_surface *surface = data;
wlr_xdg_surface_schedule_configure(surface);
}
static void handle_request_move(struct wl_listener *listener, void *data) {
struct sway_xdg_shell_view *xdg_shell_view =
wl_container_of(listener, xdg_shell_view, request_move);
@ -402,6 +416,7 @@ static void handle_unmap(struct wl_listener *listener, void *data) {
wl_list_remove(&xdg_shell_view->commit.link);
wl_list_remove(&xdg_shell_view->new_popup.link);
wl_list_remove(&xdg_shell_view->request_fullscreen.link);
wl_list_remove(&xdg_shell_view->request_maximize.link);
wl_list_remove(&xdg_shell_view->request_move.link);
wl_list_remove(&xdg_shell_view->request_resize.link);
wl_list_remove(&xdg_shell_view->set_title.link);
@ -450,6 +465,10 @@ static void handle_map(struct wl_listener *listener, void *data) {
wl_signal_add(&xdg_surface->toplevel->events.request_fullscreen,
&xdg_shell_view->request_fullscreen);
xdg_shell_view->request_maximize.notify = handle_request_maximize;
wl_signal_add(&xdg_surface->toplevel->events.request_maximize,
&xdg_shell_view->request_maximize);
xdg_shell_view->request_move.notify = handle_request_move;
wl_signal_add(&xdg_surface->toplevel->events.request_move,
&xdg_shell_view->request_move);

View file

@ -222,6 +222,11 @@ static void set_activated(struct sway_view *view, bool activated) {
return;
}
struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface;
if (activated && surface->minimized) {
wlr_xwayland_surface_set_minimized(surface, false);
}
wlr_xwayland_surface_activate(surface, activated);
}
@ -406,6 +411,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
wl_list_remove(&xwayland_view->destroy.link);
wl_list_remove(&xwayland_view->request_configure.link);
wl_list_remove(&xwayland_view->request_fullscreen.link);
wl_list_remove(&xwayland_view->request_minimize.link);
wl_list_remove(&xwayland_view->request_move.link);
wl_list_remove(&xwayland_view->request_resize.link);
wl_list_remove(&xwayland_view->request_activate.link);
@ -508,6 +514,21 @@ static void handle_request_fullscreen(struct wl_listener *listener, void *data)
transaction_commit_dirty();
}
static void handle_request_minimize(struct wl_listener *listener, void *data) {
struct sway_xwayland_view *xwayland_view =
wl_container_of(listener, xwayland_view, request_minimize);
struct sway_view *view = &xwayland_view->view;
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
if (!xsurface->mapped) {
return;
}
struct wlr_xwayland_minimize_event *e = data;
struct sway_seat *seat = input_manager_current_seat();
bool focused = seat_get_focus(seat) == &view->container->node;
wlr_xwayland_surface_set_minimized(xsurface, !focused && e->minimize);
}
static void handle_request_move(struct wl_listener *listener, void *data) {
struct sway_xwayland_view *xwayland_view =
wl_container_of(listener, xwayland_view, request_move);
@ -653,6 +674,10 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {
&xwayland_view->request_fullscreen);
xwayland_view->request_fullscreen.notify = handle_request_fullscreen;
wl_signal_add(&xsurface->events.request_minimize,
&xwayland_view->request_minimize);
xwayland_view->request_minimize.notify = handle_request_minimize;
wl_signal_add(&xsurface->events.request_activate,
&xwayland_view->request_activate);
xwayland_view->request_activate.notify = handle_request_activate;

View file

@ -99,8 +99,8 @@ struct sway_node *node_at_coords(
return NULL;
}
struct sway_output *output = wlr_output->data;
if (!output || !output->configured) {
// output is being destroyed or is being configured
if (!output || !output->enabled) {
// output is being destroyed or is being enabled
return NULL;
}
double ox = lx, oy = ly;
@ -1244,6 +1244,10 @@ static void warp_to_constraint_cursor_hint(struct sway_cursor *cursor) {
double ly = sy + con->content_y - view->geometry.y;
wlr_cursor_warp(cursor->cursor, NULL, lx, ly);
// Warp the pointer as well, so that on the next pointer rebase we don't
// send an unexpected synthetic motion event to clients.
wlr_seat_pointer_warp(constraint->seat, sx, sy);
}
}

View file

@ -19,7 +19,7 @@ static bool set_send_events(struct libinput_device *device, uint32_t mode) {
if (libinput_device_config_send_events_get_mode(device) == mode) {
return false;
}
sway_log(SWAY_DEBUG, "send_events_set_mode(%d)", mode);
sway_log(SWAY_DEBUG, "send_events_set_mode(%" PRIu32 ")", mode);
log_status(libinput_device_config_send_events_set_mode(device, mode));
return true;
}
@ -150,7 +150,7 @@ static bool set_scroll_button(struct libinput_device *dev, uint32_t button) {
libinput_device_config_scroll_get_button(dev) == button) {
return false;
}
sway_log(SWAY_DEBUG, "scroll_set_button(%d)", button);
sway_log(SWAY_DEBUG, "scroll_set_button(%" PRIu32 ")", button);
log_status(libinput_device_config_scroll_set_button(dev, button));
return true;
}

View file

@ -470,31 +470,29 @@ static void handle_start_drag(struct wl_listener *listener, void *data) {
wl_signal_add(&wlr_drag->events.destroy, &drag->destroy);
struct wlr_drag_icon *wlr_drag_icon = wlr_drag->icon;
if (wlr_drag_icon == NULL) {
return;
if (wlr_drag_icon != NULL) {
struct sway_drag_icon *icon = calloc(1, sizeof(struct sway_drag_icon));
if (icon == NULL) {
sway_log(SWAY_ERROR, "Allocation failed");
return;
}
icon->seat = seat;
icon->wlr_drag_icon = wlr_drag_icon;
wlr_drag_icon->data = icon;
icon->surface_commit.notify = drag_icon_handle_surface_commit;
wl_signal_add(&wlr_drag_icon->surface->events.commit, &icon->surface_commit);
icon->unmap.notify = drag_icon_handle_unmap;
wl_signal_add(&wlr_drag_icon->events.unmap, &icon->unmap);
icon->map.notify = drag_icon_handle_map;
wl_signal_add(&wlr_drag_icon->events.map, &icon->map);
icon->destroy.notify = drag_icon_handle_destroy;
wl_signal_add(&wlr_drag_icon->events.destroy, &icon->destroy);
wl_list_insert(&root->drag_icons, &icon->link);
drag_icon_update_position(icon);
}
struct sway_drag_icon *icon = calloc(1, sizeof(struct sway_drag_icon));
if (icon == NULL) {
sway_log(SWAY_ERROR, "Allocation failed");
return;
}
icon->seat = seat;
icon->wlr_drag_icon = wlr_drag_icon;
wlr_drag_icon->data = icon;
icon->surface_commit.notify = drag_icon_handle_surface_commit;
wl_signal_add(&wlr_drag_icon->surface->events.commit, &icon->surface_commit);
icon->unmap.notify = drag_icon_handle_unmap;
wl_signal_add(&wlr_drag_icon->events.unmap, &icon->unmap);
icon->map.notify = drag_icon_handle_map;
wl_signal_add(&wlr_drag_icon->events.map, &icon->map);
icon->destroy.notify = drag_icon_handle_destroy;
wl_signal_add(&wlr_drag_icon->events.destroy, &icon->destroy);
wl_list_insert(&root->drag_icons, &icon->link);
drag_icon_update_position(icon);
seatop_begin_default(seat);
}
@ -918,7 +916,7 @@ void seat_configure_xcursor(struct sway_seat *seat) {
if (seat == input_manager_get_default_seat()) {
char cursor_size_fmt[16];
snprintf(cursor_size_fmt, sizeof(cursor_size_fmt), "%d", cursor_size);
snprintf(cursor_size_fmt, sizeof(cursor_size_fmt), "%u", cursor_size);
setenv("XCURSOR_SIZE", cursor_size_fmt, 1);
if (cursor_theme != NULL) {
setenv("XCURSOR_THEME", cursor_theme, 1);

View file

@ -21,7 +21,12 @@ struct seatop_resize_floating_event {
static void handle_button(struct sway_seat *seat, uint32_t time_msec,
struct wlr_input_device *device, uint32_t button,
enum wlr_button_state state) {
struct seatop_resize_floating_event *e = seat->seatop_data;
struct sway_container *con = e->con;
if (seat->cursor->pressed_button_count == 0) {
container_set_resizing(con, false);
arrange_container(con); // Send configure w/o resizing hint
seatop_begin_default(seat);
}
}
@ -170,6 +175,7 @@ void seatop_begin_resize_floating(struct sway_seat *seat,
seat->seatop_impl = &seatop_impl;
seat->seatop_data = e;
container_set_resizing(con, true);
container_raise_floating(con);
const char *image = edge == WLR_EDGE_NONE ?

View file

@ -4,6 +4,9 @@
#include "sway/commands.h"
#include "sway/input/cursor.h"
#include "sway/input/seat.h"
#include "sway/tree/arrange.h"
#include "sway/tree/container.h"
#include "sway/tree/view.h"
struct seatop_resize_tiling_event {
struct sway_container *con; // leaf container
@ -12,6 +15,10 @@ struct seatop_resize_tiling_event {
struct sway_container *h_con;
struct sway_container *v_con;
// sibling con(s) that will be resized to accommodate
struct sway_container *h_sib;
struct sway_container *v_sib;
enum wlr_edges edge;
enum wlr_edges edge_x, edge_y;
double ref_lx, ref_ly; // cursor's x/y at start of op
@ -19,10 +26,47 @@ struct seatop_resize_tiling_event {
double v_con_orig_height; // height of the vertical ancestor at start
};
static struct sway_container *container_get_resize_sibling(
struct sway_container *con, uint32_t edge) {
if (!con) {
return NULL;
}
list_t *siblings = container_get_siblings(con);
int index = container_sibling_index(con);
int offset = edge & (WLR_EDGE_TOP | WLR_EDGE_LEFT) ? -1 : 1;
if (siblings->length == 1) {
return NULL;
} else {
return siblings->items[index + offset];
}
}
static void handle_button(struct sway_seat *seat, uint32_t time_msec,
struct wlr_input_device *device, uint32_t button,
enum wlr_button_state state) {
struct seatop_resize_tiling_event *e = seat->seatop_data;
if (seat->cursor->pressed_button_count == 0) {
if (e->h_con) {
container_set_resizing(e->h_con, false);
container_set_resizing(e->h_sib, false);
if (e->h_con->parent) {
arrange_container(e->h_con->parent);
} else {
arrange_workspace(e->h_con->workspace);
}
}
if (e->v_con) {
container_set_resizing(e->v_con, false);
container_set_resizing(e->v_sib, false);
if (e->v_con->parent) {
arrange_container(e->v_con->parent);
} else {
arrange_workspace(e->v_con->workspace);
}
}
seatop_begin_default(seat);
}
}
@ -89,16 +133,22 @@ void seatop_begin_resize_tiling(struct sway_seat *seat,
if (edge & (WLR_EDGE_LEFT | WLR_EDGE_RIGHT)) {
e->edge_x = edge & (WLR_EDGE_LEFT | WLR_EDGE_RIGHT);
e->h_con = container_find_resize_parent(e->con, e->edge_x);
e->h_sib = container_get_resize_sibling(e->h_con, e->edge_x);
if (e->h_con) {
container_set_resizing(e->h_con, true);
container_set_resizing(e->h_sib, true);
e->h_con_orig_width = e->h_con->width;
}
}
if (edge & (WLR_EDGE_TOP | WLR_EDGE_BOTTOM)) {
e->edge_y = edge & (WLR_EDGE_TOP | WLR_EDGE_BOTTOM);
e->v_con = container_find_resize_parent(e->con, e->edge_y);
e->v_sib = container_get_resize_sibling(e->v_con, e->edge_y);
if (e->v_con) {
container_set_resizing(e->v_con, true);
container_set_resizing(e->v_sib, true);
e->v_con_orig_height = e->v_con->height;
}
}

View file

@ -160,7 +160,7 @@ json_object *ipc_json_get_version(void) {
int major = 0, minor = 0, patch = 0;
json_object *version = json_object_new_object();
sscanf(SWAY_VERSION, "%u.%u.%u", &major, &minor, &patch);
sscanf(SWAY_VERSION, "%d.%d.%d", &major, &minor, &patch);
json_object_object_add(version, "human_readable", json_object_new_string(SWAY_VERSION));
json_object_object_add(version, "variant", json_object_new_string("sway"));

View file

@ -140,7 +140,7 @@ struct sockaddr_un *ipc_user_sockaddr(void) {
dir = "/tmp";
}
if (path_size <= snprintf(ipc_sockaddr->sun_path, path_size,
"%s/sway-ipc.%i.%i.sock", dir, getuid(), getpid())) {
"%s/sway-ipc.%u.%i.sock", dir, getuid(), getpid())) {
sway_abort("Socket path won't fit into ipc_sockaddr->sun_path");
}
@ -242,7 +242,6 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) {
}
uint8_t buf[IPC_HEADER_SIZE];
uint32_t *buf32 = (uint32_t*)(buf + sizeof(ipc_magic));
// Should be fully available, because read_available >= IPC_HEADER_SIZE
ssize_t received = recv(client_fd, buf, IPC_HEADER_SIZE, 0);
if (received == -1) {
@ -257,8 +256,8 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) {
return 0;
}
memcpy(&client->pending_length, &buf32[0], sizeof(buf32[0]));
memcpy(&client->pending_type, &buf32[1], sizeof(buf32[1]));
memcpy(&client->pending_length, buf + sizeof(ipc_magic), sizeof(uint32_t));
memcpy(&client->pending_type, buf + sizeof(ipc_magic) + sizeof(uint32_t), sizeof(uint32_t));
if (read_available - received >= (long)client->pending_length) {
// Reset pending values.
@ -920,11 +919,10 @@ bool ipc_send_reply(struct ipc_client *client, enum ipc_command_type payload_typ
assert(payload);
char data[IPC_HEADER_SIZE];
uint32_t *data32 = (uint32_t*)(data + sizeof(ipc_magic));
memcpy(data, ipc_magic, sizeof(ipc_magic));
memcpy(&data32[0], &payload_length, sizeof(payload_length));
memcpy(&data32[1], &payload_type, sizeof(payload_type));
memcpy(data + sizeof(ipc_magic), &payload_length, sizeof(payload_length));
memcpy(data + sizeof(ipc_magic) + sizeof(payload_length), &payload_type, sizeof(payload_type));
while (client->write_buffer_len + IPC_HEADER_SIZE + payload_length >=
client->write_buffer_size) {

View file

@ -138,7 +138,8 @@ static void log_env(void) {
"SWAYSOCK",
};
for (size_t i = 0; i < sizeof(log_vars) / sizeof(char *); ++i) {
sway_log(SWAY_INFO, "%s=%s", log_vars[i], getenv(log_vars[i]));
char *value = getenv(log_vars[i]);
sway_log(SWAY_INFO, "%s=%s", log_vars[i], value != NULL ? value : "");
}
}

View file

@ -215,9 +215,11 @@ set|plus|minus <amount>
If unspecified, the default is 10 pixels. Pixels are ignored when moving
tiled containers.
*move* [absolute] position <pos_x> [px] <pos_y> [px]
Moves the focused container to the specified position in the workspace. If
_absolute_ is used, the position is relative to all outputs.
*move* [absolute] position <pos_x> [px|ppt] <pos_y> [px|ptt]
Moves the focused container to the specified position in the workspace.
The position can be specified in pixels or percentage points, omitting
the unit defaults to pixels. If _absolute_ is used, the position is
relative to all outputs. _absolute_ can not be used with percentage points.
*move* [absolute] position center
Moves the focused container to be centered on the workspace. If _absolute_
@ -272,7 +274,9 @@ set|plus|minus <amount>
optional comment argument is ignored, but logged for debugging purposes.
*reload*
Reloads the sway config file and applies any changes.
Reloads the sway config file and applies any changes. The config file is
located at path specified by the command line arguments when started,
otherwise according to the priority stated in *sway*(1).
*rename workspace* [<old_name>] to <new_name>
Rename either <old_name> or the focused workspace to the <new_name>
@ -304,7 +308,7 @@ set|plus|minus <amount>
Shows a window from the scratchpad. Repeatedly using this command will
cycle through the windows in the scratchpad.
*shortcuts inhibitor* enable|disable
*shortcuts_inhibitor* enable|disable
Enables or disables the ability of clients to inhibit keyboard
shortcuts for a view. This is primarily useful for virtualization and
remote desktop software. It affects either the currently focused view

View file

@ -746,6 +746,28 @@ void container_floating_set_default_size(struct sway_container *con) {
free(box);
}
/**
* Indicate to clients in this container that they are participating in (or
* have just finished) an interactive resize
*/
void container_set_resizing(struct sway_container *con, bool resizing) {
if (!con) {
return;
}
if (con->view) {
if (con->view->impl->set_resizing) {
con->view->impl->set_resizing(con->view, resizing);
}
} else {
for (int i = 0; i < con->children->length; ++i ) {
struct sway_container *child = con->children->items[i];
container_set_resizing(child, resizing);
}
}
}
void container_set_floating(struct sway_container *container, bool enable) {
if (container_is_floating(container) == enable) {
return;

View file

@ -110,12 +110,12 @@ struct sway_output *output_create(struct wlr_output *wlr_output) {
return output;
}
void output_configure(struct sway_output *output) {
if (!sway_assert(!output->configured, "output is already configured")) {
void output_enable(struct sway_output *output) {
if (!sway_assert(!output->enabled, "output is already enabled")) {
return;
}
struct wlr_output *wlr_output = output->wlr_output;
output->configured = true;
output->enabled = true;
list_add(root->outputs, output);
restore_workspaces(output);
@ -251,6 +251,11 @@ void output_disable(struct sway_output *output) {
if (!sway_assert(output->enabled, "Expected an enabled output")) {
return;
}
int index = list_find(root->outputs, output);
if (!sway_assert(index >= 0, "Output not found in root node")) {
return;
}
sway_log(SWAY_DEBUG, "Disabling output '%s'", output->wlr_output->name);
wl_signal_emit(&output->events.destroy, output);
@ -258,11 +263,9 @@ void output_disable(struct sway_output *output) {
root_for_each_container(untrack_output, output);
int index = list_find(root->outputs, output);
list_del(root->outputs, index);
output->enabled = false;
output->configured = false;
output->current_mode = NULL;
arrange_root();

View file

@ -625,7 +625,12 @@ static void handle_foreign_activate_request(
struct sway_seat *seat;
wl_list_for_each(seat, &server.input->seats, link) {
if (seat->wlr_seat == event->seat) {
if (container_is_scratchpad_hidden_or_child(view->container)) {
root_scratchpad_show(view->container);
}
seat_set_focus_container(seat, view->container);
seat_consider_warp_to_focus(seat);
container_raise_floating(view->container);
break;
}
}

View file

@ -185,6 +185,7 @@ struct status_line *status_line_init(char *cmd) {
void status_line_free(struct status_line *status) {
status_line_close_fds(status);
kill(status->pid, status->cont_signal);
kill(status->pid, SIGTERM);
waitpid(status->pid, NULL, 0);
if (status->protocol == PROTOCOL_I3BAR) {

View file

@ -44,12 +44,18 @@ _swaymsg_ [options...] [message]
The message is a sway command (the same commands you can bind to keybindings
in your sway config file). It will be executed immediately.
See **sway**(5) for a list of commands.
See *sway*(5) for a list of commands.
Tip: If you are proving a command that contains a leading hyphen (_-_),
insert two hyphens (_--_) before the command to signal to swaymsg not to
parse anything beyond that point as an option. For example, use
_swaymsg -- mark --add test_ instead of _swaymsg mark --add test_
Tips:
- Command expansion is performed twice: once by swaymsg, and again by sway.
If you have quoted multi-word strings in your command, enclose the entire
command in single-quotes. For example, use
_swaymsg 'output "Foobar Display" enable'_ instead of
_swaymsg output "Foobar Display" enable_.
- If you are proving a command that contains a leading hyphen (_-_), insert
two hyphens (_--_) before the command to signal to swaymsg not to parse
anything beyond that point as an option. For example, use
_swaymsg -- mark --add test_ instead of _swaymsg mark --add test_.
*get\_workspaces*
Gets a JSON-encoded list of workspaces and their status.

View file

@ -106,7 +106,7 @@ int main(int argc, char **argv) {
}
sway_log(SWAY_DEBUG, "Output: %s", swaynag.type->output);
sway_log(SWAY_DEBUG, "Anchors: %d", swaynag.type->anchors);
sway_log(SWAY_DEBUG, "Anchors: %" PRIu32, swaynag.type->anchors);
sway_log(SWAY_DEBUG, "Type: %s", swaynag.type->name);
sway_log(SWAY_DEBUG, "Message: %s", swaynag.message);
sway_log(SWAY_DEBUG, "Font: %s", swaynag.type->font);