Merge branch 'master' into idle_v2

This commit is contained in:
Mattias Eriksson 2018-04-24 19:25:38 +02:00
commit ce344e1130
18 changed files with 238 additions and 74 deletions

View file

@ -131,6 +131,7 @@ sway_cmd cmd_output;
sway_cmd cmd_permit; sway_cmd cmd_permit;
sway_cmd cmd_reject; sway_cmd cmd_reject;
sway_cmd cmd_reload; sway_cmd cmd_reload;
sway_cmd cmd_rename;
sway_cmd cmd_resize; sway_cmd cmd_resize;
sway_cmd cmd_scratchpad; sway_cmd cmd_scratchpad;
sway_cmd cmd_seamless_mouse; sway_cmd cmd_seamless_mouse;

View file

@ -29,7 +29,7 @@ struct sway_cursor {
void sway_cursor_destroy(struct sway_cursor *cursor); void sway_cursor_destroy(struct sway_cursor *cursor);
struct sway_cursor *sway_cursor_create(struct sway_seat *seat); struct sway_cursor *sway_cursor_create(struct sway_seat *seat);
void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time); void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec);
void dispatch_cursor_button(struct sway_cursor *cursor, uint32_t time_msec, void dispatch_cursor_button(struct sway_cursor *cursor, uint32_t time_msec,
uint32_t button, enum wlr_button_state state); uint32_t button, enum wlr_button_state state);

View file

@ -170,6 +170,7 @@ static struct cmd_handler command_handlers[] = {
{ "move", cmd_move }, { "move", cmd_move },
{ "opacity", cmd_opacity }, { "opacity", cmd_opacity },
{ "reload", cmd_reload }, { "reload", cmd_reload },
{ "rename", cmd_rename },
{ "resize", cmd_resize }, { "resize", cmd_resize },
{ "split", cmd_split }, { "split", cmd_split },
{ "splith", cmd_splith }, { "splith", cmd_splith },

79
sway/commands/rename.c Normal file
View file

@ -0,0 +1,79 @@
#define _XOPEN_SOURCE 500
#include <string.h>
#include <strings.h>
#include "log.h"
#include "stringop.h"
#include "sway/commands.h"
#include "sway/config.h"
#include "sway/ipc-server.h"
#include "sway/tree/container.h"
#include "sway/tree/workspace.h"
static const char* expected_syntax =
"Expected 'rename workspace <old_name> to <new_name>' or "
"'rename workspace to <new_name>'";
struct cmd_results *cmd_rename(int argc, char **argv) {
struct cmd_results *error = NULL;
if ((error = checkarg(argc, "rename", EXPECTED_AT_LEAST, 3))) {
return error;
}
if (strcasecmp(argv[0], "workspace") != 0) {
return cmd_results_new(CMD_INVALID, "rename", expected_syntax);
}
int argn = 1;
struct sway_container *workspace;
if (strcasecmp(argv[1], "to") == 0) {
// 'rename workspace to new_name'
workspace = config->handler_context.current_container;
if (workspace->type != C_WORKSPACE) {
workspace = container_parent(workspace, C_WORKSPACE);
}
} else if (strcasecmp(argv[1], "number") == 0) {
// 'rename workspace number x to new_name'
workspace = workspace_by_number(argv[2]);
while (argn < argc && strcasecmp(argv[argn], "to") != 0) {
++argn;
}
} else {
// 'rename workspace old_name to new_name'
int end = argn;
while (end < argc && strcasecmp(argv[end], "to") != 0) {
++end;
}
char *old_name = join_args(argv + argn, end - argn);
workspace = workspace_by_name(old_name);
free(old_name);
argn = end;
}
if (!workspace) {
return cmd_results_new(CMD_INVALID, "rename",
"There is no workspace with that name");
}
++argn; // move past "to"
if (argn >= argc) {
return cmd_results_new(CMD_INVALID, "rename", expected_syntax);
}
char *new_name = join_args(argv + argn, argc - argn);
struct sway_container *tmp_workspace = workspace_by_name(new_name);
if (tmp_workspace) {
free(new_name);
return cmd_results_new(CMD_INVALID, "rename",
"Workspace already exists");
}
wlr_log(L_DEBUG, "renaming workspace '%s' to '%s'", workspace->name, new_name);
free(workspace->name);
workspace->name = new_name;
container_sort_workspaces(workspace->parent);
ipc_event_workspace(NULL, workspace, "rename");
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}

View file

@ -11,7 +11,7 @@
#include "sway/input/cursor.h" #include "sway/input/cursor.h"
static struct cmd_results *press_or_release(struct sway_cursor *cursor, static struct cmd_results *press_or_release(struct sway_cursor *cursor,
char *action, char *button_str, uint32_t time); char *action, char *button_str);
static const char *expected_syntax = "Expected 'cursor <move> <x> <y>' or " static const char *expected_syntax = "Expected 'cursor <move> <x> <y>' or "
"'cursor <set> <x> <y>' or " "'cursor <set> <x> <y>' or "
@ -29,10 +29,6 @@ struct cmd_results *seat_cmd_cursor(int argc, char **argv) {
struct sway_cursor *cursor = seat->cursor; struct sway_cursor *cursor = seat->cursor;
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
uint32_t time = now.tv_nsec / 1000;
if (strcasecmp(argv[0], "move") == 0) { if (strcasecmp(argv[0], "move") == 0) {
if (argc < 3) { if (argc < 3) {
return cmd_results_new(CMD_INVALID, "cursor", expected_syntax); return cmd_results_new(CMD_INVALID, "cursor", expected_syntax);
@ -40,7 +36,7 @@ struct cmd_results *seat_cmd_cursor(int argc, char **argv) {
int delta_x = strtol(argv[1], NULL, 10); int delta_x = strtol(argv[1], NULL, 10);
int delta_y = strtol(argv[2], NULL, 10); int delta_y = strtol(argv[2], NULL, 10);
wlr_cursor_move(cursor->cursor, NULL, delta_x, delta_y); wlr_cursor_move(cursor->cursor, NULL, delta_x, delta_y);
cursor_send_pointer_motion(cursor, time); cursor_send_pointer_motion(cursor, 0);
} else if (strcasecmp(argv[0], "set") == 0) { } else if (strcasecmp(argv[0], "set") == 0) {
if (argc < 3) { if (argc < 3) {
return cmd_results_new(CMD_INVALID, "cursor", expected_syntax); return cmd_results_new(CMD_INVALID, "cursor", expected_syntax);
@ -49,12 +45,12 @@ struct cmd_results *seat_cmd_cursor(int argc, char **argv) {
float x = strtof(argv[1], NULL) / root_container.width; float x = strtof(argv[1], NULL) / root_container.width;
float y = strtof(argv[2], NULL) / root_container.height; float y = strtof(argv[2], NULL) / root_container.height;
wlr_cursor_warp_absolute(cursor->cursor, NULL, x, y); wlr_cursor_warp_absolute(cursor->cursor, NULL, x, y);
cursor_send_pointer_motion(cursor, time); cursor_send_pointer_motion(cursor, 0);
} else { } else {
if (argc < 2) { if (argc < 2) {
return cmd_results_new(CMD_INVALID, "cursor", expected_syntax); return cmd_results_new(CMD_INVALID, "cursor", expected_syntax);
} }
if ((error = press_or_release(cursor, argv[0], argv[1], time))) { if ((error = press_or_release(cursor, argv[0], argv[1]))) {
return error; return error;
} }
} }
@ -63,7 +59,7 @@ struct cmd_results *seat_cmd_cursor(int argc, char **argv) {
} }
static struct cmd_results *press_or_release(struct sway_cursor *cursor, static struct cmd_results *press_or_release(struct sway_cursor *cursor,
char *action, char *button_str, uint32_t time) { char *action, char *button_str) {
enum wlr_button_state state; enum wlr_button_state state;
uint32_t button; uint32_t button;
if (strcasecmp(action, "press") == 0) { if (strcasecmp(action, "press") == 0) {
@ -84,6 +80,6 @@ static struct cmd_results *press_or_release(struct sway_cursor *cursor,
return cmd_results_new(CMD_INVALID, "cursor", expected_syntax); return cmd_results_new(CMD_INVALID, "cursor", expected_syntax);
} }
} }
dispatch_cursor_button(cursor, time, button, state); dispatch_cursor_button(cursor, 0, button, state);
return cmd_results_new(CMD_SUCCESS, NULL, NULL); return cmd_results_new(CMD_SUCCESS, NULL, NULL);
} }

View file

@ -13,6 +13,7 @@
#include "sway/output.h" #include "sway/output.h"
#include "sway/server.h" #include "sway/server.h"
#include "sway/tree/layout.h" #include "sway/tree/layout.h"
#include "log.h"
static void apply_exclusive(struct wlr_box *usable_area, static void apply_exclusive(struct wlr_box *usable_area,
uint32_t anchor, int32_t exclusive, uint32_t anchor, int32_t exclusive,
@ -316,6 +317,27 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
return; return;
} }
if (!layer_surface->output) {
// Assign last active output
struct sway_container *output = NULL;
struct sway_seat *seat = input_manager_get_default_seat(input_manager);
if (seat) {
output = seat_get_focus_inactive(seat, &root_container);
}
if (!output) {
if (!sway_assert(root_container.children->length,
"cannot auto-assign output for layer")) {
wlr_layer_surface_close(layer_surface);
return;
}
output = root_container.children->items[0];
}
if (output->type != C_OUTPUT) {
output = container_parent(output, C_OUTPUT);
}
layer_surface->output = output->sway_output->wlr_output;
}
sway_layer->surface_commit.notify = handle_surface_commit; sway_layer->surface_commit.notify = handle_surface_commit;
wl_signal_add(&layer_surface->surface->events.commit, wl_signal_add(&layer_surface->surface->events.commit,
&sway_layer->surface_commit); &sway_layer->surface_commit);

View file

@ -282,6 +282,11 @@ static void render_output(struct sway_output *output, struct timespec *when,
wlr_renderer_clear(renderer, clear_color); wlr_renderer_clear(renderer, clear_color);
// TODO: handle views smaller than the output // TODO: handle views smaller than the output
render_container(output, workspace->sway_workspace->fullscreen->swayc); render_container(output, workspace->sway_workspace->fullscreen->swayc);
if (workspace->sway_workspace->fullscreen->type == SWAY_VIEW_XWAYLAND) {
render_unmanaged(output,
&root_container.sway_root->xwayland_unmanaged);
}
} else { } else {
float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f};
wlr_renderer_clear(renderer, clear_color); wlr_renderer_clear(renderer, clear_color);

View file

@ -257,11 +257,6 @@ static void handle_map(struct wl_listener *listener, void *data) {
static void handle_destroy(struct wl_listener *listener, void *data) { static void handle_destroy(struct wl_listener *listener, void *data) {
struct sway_xwayland_view *xwayland_view = struct sway_xwayland_view *xwayland_view =
wl_container_of(listener, xwayland_view, destroy); wl_container_of(listener, xwayland_view, destroy);
struct sway_view *view = &xwayland_view->view;
struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
if (xsurface->mapped) {
handle_unmap(&xwayland_view->unmap, xsurface);
}
view_destroy(&xwayland_view->view); view_destroy(&xwayland_view->view);
} }

View file

@ -16,6 +16,12 @@
#include "sway/tree/workspace.h" #include "sway/tree/workspace.h"
#include "wlr-layer-shell-unstable-v1-protocol.h" #include "wlr-layer-shell-unstable-v1-protocol.h"
static uint32_t get_current_time_msec() {
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
return now.tv_nsec / 1000;
}
static struct wlr_surface *layer_surface_at(struct sway_output *output, static struct wlr_surface *layer_surface_at(struct sway_output *output,
struct wl_list *layer, double ox, double oy, double *sx, double *sy) { struct wl_list *layer, double ox, double oy, double *sx, double *sy) {
struct sway_layer_surface *sway_layer; struct sway_layer_surface *sway_layer;
@ -60,8 +66,7 @@ static struct sway_container *container_at_cursor(struct sway_cursor *cursor,
// find the output the cursor is on // find the output the cursor is on
struct wlr_output_layout *output_layout = struct wlr_output_layout *output_layout =
root_container.sway_root->output_layout; root_container.sway_root->output_layout;
struct wlr_output *wlr_output = struct wlr_output *wlr_output = wlr_output_layout_output_at(output_layout,
wlr_output_layout_output_at(output_layout,
cursor->cursor->x, cursor->cursor->y); cursor->cursor->x, cursor->cursor->y);
if (wlr_output == NULL) { if (wlr_output == NULL) {
return NULL; return NULL;
@ -130,7 +135,11 @@ static struct sway_container *container_at_cursor(struct sway_cursor *cursor,
return output->swayc; return output->swayc;
} }
void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time) { void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec) {
if (time_msec == 0) {
time_msec = get_current_time_msec();
}
struct wlr_seat *seat = cursor->seat->wlr_seat; struct wlr_seat *seat = cursor->seat->wlr_seat;
struct wlr_surface *surface = NULL; struct wlr_surface *surface = NULL;
double sx, sy; double sx, sy;
@ -154,7 +163,7 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time) {
if (surface != NULL) { if (surface != NULL) {
if (seat_is_input_allowed(cursor->seat, surface)) { if (seat_is_input_allowed(cursor->seat, surface)) {
wlr_seat_pointer_notify_enter(seat, surface, sx, sy); wlr_seat_pointer_notify_enter(seat, surface, sx, sy);
wlr_seat_pointer_notify_motion(seat, time, sx, sy); wlr_seat_pointer_notify_motion(seat, time_msec, sx, sy);
} }
} else { } else {
wlr_seat_pointer_clear_focus(seat); wlr_seat_pointer_clear_focus(seat);
@ -182,6 +191,10 @@ static void handle_cursor_motion_absolute(
void dispatch_cursor_button(struct sway_cursor *cursor, void dispatch_cursor_button(struct sway_cursor *cursor,
uint32_t time_msec, uint32_t button, enum wlr_button_state state) { uint32_t time_msec, uint32_t button, enum wlr_button_state state) {
if (time_msec == 0) {
time_msec = get_current_time_msec();
}
struct wlr_surface *surface = NULL; struct wlr_surface *surface = NULL;
double sx, sy; double sx, sy;
struct sway_container *cont = struct sway_container *cont =

View file

@ -553,9 +553,7 @@ void seat_set_focus_warp(struct sway_seat *seat,
wlr_output, seat->cursor->cursor->x, wlr_output, seat->cursor->cursor->x,
seat->cursor->cursor->y)) { seat->cursor->cursor->y)) {
wlr_cursor_warp(seat->cursor->cursor, NULL, x, y); wlr_cursor_warp(seat->cursor->cursor, NULL, x, y);
struct timespec now; cursor_send_pointer_motion(seat->cursor, 0);
clock_gettime(CLOCK_MONOTONIC, &now);
cursor_send_pointer_motion(seat->cursor, now.tv_nsec / 1000);
} }
} }
} }
@ -567,6 +565,10 @@ void seat_set_focus_warp(struct sway_seat *seat,
view_set_activated(view, false); view_set_activated(view, false);
} }
if (last_workspace && last_workspace != new_workspace) {
cursor_send_pointer_motion(seat->cursor, 0);
}
seat->has_focus = (container != NULL); seat->has_focus = (container != NULL);
update_debug_tree(); update_debug_tree();

View file

@ -46,6 +46,7 @@ sway_sources = files(
'commands/move.c', 'commands/move.c',
'commands/output.c', 'commands/output.c',
'commands/reload.c', 'commands/reload.c',
'commands/rename.c',
'commands/resize.c', 'commands/resize.c',
'commands/seat.c', 'commands/seat.c',
'commands/seat/attach.c', 'commands/seat/attach.c',

View file

@ -51,7 +51,7 @@ bool server_init(struct sway_server *server) {
struct wlr_renderer *renderer = wlr_backend_get_renderer(server->backend); struct wlr_renderer *renderer = wlr_backend_get_renderer(server->backend);
assert(renderer); assert(renderer);
wl_display_init_shm(server->wl_display); wlr_renderer_init_wl_shm(renderer, server->wl_display);
server->compositor = wlr_compositor_create(server->wl_display, renderer); server->compositor = wlr_compositor_create(server->wl_display, renderer);
server->data_device_manager = server->data_device_manager =

View file

@ -355,15 +355,16 @@ struct sway_container *container_view_create(struct sway_container *sibling,
void container_descendants(struct sway_container *root, void container_descendants(struct sway_container *root,
enum sway_container_type type, enum sway_container_type type,
void (*func)(struct sway_container *item, void *data), void *data) { void (*func)(struct sway_container *item, void *data), void *data) {
if (!root->children || !root->children->length) {
return;
}
for (int i = 0; i < root->children->length; ++i) { for (int i = 0; i < root->children->length; ++i) {
struct sway_container *item = root->children->items[i]; struct sway_container *item = root->children->items[i];
if (item->type == type) { if (item->type == type) {
func(item, data); func(item, data);
} }
if (item->children && item->children->length) {
container_descendants(item, type, func, data); container_descendants(item, type, func, data);
} }
}
} }
struct sway_container *container_find(struct sway_container *container, struct sway_container *container_find(struct sway_container *container,

View file

@ -150,8 +150,8 @@ void container_add_child(struct sway_container *parent,
parent, parent->type, parent->width, parent->height); parent, parent->type, parent->width, parent->height);
struct sway_container *old_parent = child->parent; struct sway_container *old_parent = child->parent;
list_add(parent->children, child); list_add(parent->children, child);
container_handle_fullscreen_reparent(child, old_parent);
child->parent = parent; child->parent = parent;
container_handle_fullscreen_reparent(child, old_parent);
} }
struct sway_container *container_remove_child(struct sway_container *child) { struct sway_container *container_remove_child(struct sway_container *child) {

View file

@ -327,7 +327,7 @@ static void view_child_handle_view_unmap(struct wl_listener *listener,
static void view_init_subsurfaces(struct sway_view *view, static void view_init_subsurfaces(struct sway_view *view,
struct wlr_surface *surface) { struct wlr_surface *surface) {
struct wlr_subsurface *subsurface; struct wlr_subsurface *subsurface;
wl_list_for_each(subsurface, &surface->subsurface_list, parent_link) { wl_list_for_each(subsurface, &surface->subsurfaces, parent_link) {
view_subsurface_create(view, subsurface); view_subsurface_create(view, subsurface);
} }
} }

View file

@ -156,31 +156,56 @@ static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer,
if (!sway_assert(output, "axis with no active output")) { if (!sway_assert(output, "axis with no active output")) {
return; return;
} }
double amt = wl_fixed_to_double(value); double amt = wl_fixed_to_double(value);
if (!bar->config->wrap_scroll) { if (amt == 0.0) {
int i = 0;
struct swaybar_workspace *ws = NULL;
wl_list_for_each(ws, &output->workspaces, link) {
if (ws->focused) {
break;
}
++i;
}
int len = wl_list_length(&output->workspaces);
if (!sway_assert(i != len, "axis with null workspace")) {
return; return;
} }
if (i == 0 && amt > 0) {
return; // Do not wrap struct swaybar_workspace *first = NULL;
} struct swaybar_workspace *active = NULL;
if (i == len - 1 && amt < 0) { struct swaybar_workspace *last;
return; // Do not wrap
} struct swaybar_workspace *iter;
wl_list_for_each(iter, &output->workspaces, link) {
if (!first) {
first = iter;
} }
const char *workspace_name = if (iter->visible) {
amt < 0 ? "prev_on_output" : "next_on_output"; active = iter;
ipc_send_workspace_command(bar, workspace_name); }
last = iter;
}
if (!sway_assert(active, "axis with null workspace")) {
return;
}
struct swaybar_workspace *new;
if (amt > 0.0) {
if (active == first) {
if (!bar->config->wrap_scroll) {
return;
}
new = last;
}
new = wl_container_of(active->link.prev, new, link);
} else {
if (active == last) {
if (!bar->config->wrap_scroll) {
return;
}
new = first;
}
new = wl_container_of(active->link.next, new, link);
}
ipc_send_workspace_command(bar, new->name);
} }
static void wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) { static void wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) {
@ -401,24 +426,28 @@ void bar_setup(struct swaybar *bar,
render_all_frames(bar); render_all_frames(bar);
} }
static void display_in(int fd, short mask, void *_bar) { static void display_in(int fd, short mask, void *data) {
struct swaybar *bar = (struct swaybar *)_bar; struct swaybar *bar = data;
if (wl_display_dispatch(bar->display) == -1) { if (wl_display_dispatch(bar->display) == -1) {
bar_teardown(bar); bar_teardown(bar);
exit(0); exit(0);
} }
} }
static void ipc_in(int fd, short mask, void *_bar) { static void ipc_in(int fd, short mask, void *data) {
struct swaybar *bar = (struct swaybar *)_bar; struct swaybar *bar = data;
if (handle_ipc_readable(bar)) { if (handle_ipc_readable(bar)) {
render_all_frames(bar); render_all_frames(bar);
} }
} }
static void status_in(int fd, short mask, void *_bar) { static void status_in(int fd, short mask, void *data) {
struct swaybar *bar = (struct swaybar *)_bar; struct swaybar *bar = data;
if (status_handle_readable(bar->status)) { if (mask & (POLLHUP | POLLERR)) {
status_error(bar->status, "[error reading from status command]");
render_all_frames(bar);
remove_event(fd);
} else if (status_handle_readable(bar->status)) {
render_all_frames(bar); render_all_frames(bar);
} }
} }

View file

@ -72,24 +72,18 @@ void add_event(int fd, short mask,
} }
bool remove_event(int fd) { bool remove_event(int fd) {
int index = -1; /*
* Instead of removing events immediately, we mark them for deletion
* and clean them up later. This is so we can call remove_event inside
* an event callback safely.
*/
for (int i = 0; i < event_loop.fds.length; ++i) { for (int i = 0; i < event_loop.fds.length; ++i) {
if (event_loop.fds.items[i].fd == fd) { if (event_loop.fds.items[i].fd == fd) {
index = i; event_loop.fds.items[i].fd = -1;
}
}
if (index != -1) {
free(event_loop.items->items[index]);
--event_loop.fds.length;
memmove(&event_loop.fds.items[index], &event_loop.fds.items[index + 1],
sizeof(struct pollfd) * event_loop.fds.length - index);
list_del(event_loop.items, index);
return true; return true;
} else {
return false;
} }
}
return false;
} }
static int timer_item_timer_cmp(const void *_timer_item, const void *_timer) { static int timer_item_timer_cmp(const void *_timer_item, const void *_timer) {
@ -118,11 +112,29 @@ void event_loop_poll() {
struct pollfd pfd = event_loop.fds.items[i]; struct pollfd pfd = event_loop.fds.items[i];
struct event_item *item = (struct event_item *)event_loop.items->items[i]; struct event_item *item = (struct event_item *)event_loop.items->items[i];
if (pfd.revents & pfd.events) { // Always send these events
unsigned events = pfd.events | POLLHUP | POLLERR;
if (pfd.revents & events) {
item->cb(pfd.fd, pfd.revents, item->data); item->cb(pfd.fd, pfd.revents, item->data);
} }
} }
// Cleanup removed events
int end = 0;
int length = event_loop.fds.length;
for (int i = 0; i < length; ++i) {
if (event_loop.fds.items[i].fd == -1) {
free(event_loop.items->items[i]);
list_del(event_loop.items, i);
--event_loop.fds.length;
} else if (end != i) {
event_loop.fds.items[end++] = event_loop.fds.items[i];
} else {
end = i + 1;
}
}
// check timers // check timers
// not tested, but seems to work // not tested, but seems to work
for (int i = 0; i < event_loop.timers->length; ++i) { for (int i = 0; i < event_loop.timers->length; ++i) {

View file

@ -1,3 +1,5 @@
sysconfdir = get_option('sysconfdir')
executable( executable(
'swaylock', [ 'swaylock', [
'main.c', 'main.c',
@ -21,3 +23,8 @@ executable(
link_with: [lib_sway_common, lib_sway_client], link_with: [lib_sway_common, lib_sway_client],
install: true install: true
) )
install_data(
'pam/swaylock',
install_dir: sysconfdir + '/pam.d/'
)