server subbackend output add/remove

This commit is contained in:
Tony Crisci 2017-12-23 13:55:14 -05:00
parent 997c70a035
commit fa2684ae0b
7 changed files with 266 additions and 75 deletions

View file

@ -144,9 +144,6 @@ sway_cmd cmd_workspace;
sway_cmd cmd_ws_auto_back_and_forth;
sway_cmd cmd_workspace_layout;
sway_cmd backend_cmd_add;
sway_cmd backend_cmd_del;
sway_cmd bar_cmd_activate_button;
sway_cmd bar_cmd_binding_mode_indicator;
sway_cmd bar_cmd_bindsym;

View file

@ -7,6 +7,7 @@
#include <wlr/types/wlr_compositor.h>
#include <wlr/types/wlr_data_device.h>
#include <wlr/types/wlr_xdg_shell_v6.h>
#include <wlr/types/wlr_input_device.h>
#include <wlr/render.h>
// TODO WLR: make Xwayland optional
#include <wlr/xwayland.h>
@ -22,9 +23,14 @@ struct sway_subbackend {
char *name;
enum sway_subbackend_type type;
struct wlr_backend *backend;
struct wl_list link; // sway_server::subbackends
struct wl_list outputs;
struct wl_list inputs;
struct wl_listener backend_destroy;
struct wl_list link; // sway_server::subbackends
};
struct sway_server {
@ -73,5 +79,18 @@ struct sway_subbackend *sway_subbackend_create(enum sway_subbackend_type type,
void sway_server_add_subbackend(struct sway_server *server,
struct sway_subbackend *subbackend);
void sway_server_remove_subbackend(struct sway_server *server, char *name);
struct sway_subbackend *sway_server_get_subbackend(struct sway_server *server,
char *name);
void sway_subbackend_add_output(struct sway_server *server,
struct sway_subbackend *subbackend, char *name);
void sway_subbackend_remove_output(struct sway_server *server,
struct sway_subbackend *subbackend, char *name);
void sway_subbackend_add_input(struct sway_server *server,
struct sway_subbackend *subbackend, enum wlr_input_device_type type,
char *name);
void sway_subbackend_remove_input(struct sway_server *server,
struct sway_subbackend *subbackend, char *name);
#endif

View file

@ -1,7 +1,73 @@
#include <strings.h>
#include "sway/commands.h"
#include "sway/server.h"
#include "log.h"
static struct cmd_results *backend_cmd_del(int argc, char **argv) {
struct cmd_results *error = NULL;
if ((error = checkarg(argc, "del", EXPECTED_AT_LEAST, 1))) {
return error;
}
sway_server_remove_subbackend(&server, argv[0]);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
static struct cmd_results *backend_cmd_add(int argc, char **argv) {
struct cmd_results *error = NULL;
if ((error = checkarg(argc, "add", EXPECTED_AT_LEAST, 1))) {
return error;
}
const char *type_name = argv[0];
enum sway_subbackend_type type;
if (strcasecmp(type_name, "wayland") == 0) {
type = SWAY_SUBBACKEND_WAYLAND;
} else if (strcasecmp(type_name, "x11") == 0) {
type = SWAY_SUBBACKEND_X11;
} else if (strcasecmp(type_name, "drm") == 0) {
type = SWAY_SUBBACKEND_DRM;
} else if (strcasecmp(type_name, "headless") == 0) {
type = SWAY_SUBBACKEND_HEADLESS;
} else {
error =
cmd_results_new(CMD_INVALID,
"add", "Expected 'add <wayland|x11|drm|headless>'");
return error;
}
struct sway_subbackend *subbackend =
sway_subbackend_create(type, NULL);
sway_server_add_subbackend(&server, subbackend);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}
static struct cmd_results *backend_cmd_add_output(int argc, char **argv,
struct sway_subbackend *backend) {
sway_log(L_DEBUG, "TODO: backend cmd add_output");
return NULL;
}
static struct cmd_results *backend_cmd_del_output(int argc, char **argv,
struct sway_subbackend *backend) {
sway_log(L_DEBUG, "TODO: backend cmd del_output");
return NULL;
}
static struct cmd_results *backend_cmd_add_input(int argc, char **argv,
struct sway_subbackend *backend) {
sway_log(L_DEBUG, "TODO: backend cmd add_input");
return NULL;
}
static struct cmd_results *backend_cmd_del_input(int argc, char **argv,
struct sway_subbackend *backend) {
sway_log(L_DEBUG, "TODO: backend cmd del_input");
return NULL;
}
struct cmd_results *cmd_backend(int argc, char **argv) {
struct cmd_results *error = NULL;
if ((error = checkarg(argc, "backend", EXPECTED_AT_LEAST, 2))) {
@ -11,13 +77,29 @@ struct cmd_results *cmd_backend(int argc, char **argv) {
int argc_new = argc-1;
char **argv_new = argv+1;
struct cmd_results *res;
if (strcasecmp("add", argv[0]) == 0) {
res = backend_cmd_add(argc_new, argv_new);
return backend_cmd_add(argc_new, argv_new);
} else if (strcasecmp("del", argv[0]) == 0) {
res = backend_cmd_del(argc_new, argv_new);
} else {
res = cmd_results_new(CMD_INVALID, "backend <cmd> [args]", "Unknown command %s", argv[1]);
return backend_cmd_del(argc_new, argv_new);
}
return res;
struct sway_subbackend *subbackend =
sway_server_get_subbackend(&server, argv[0]);
if (subbackend == NULL) {
return cmd_results_new(CMD_INVALID, "backend <cmd> [args]",
"Cannot find backend: %s", argv[0]);
}
if (strcasecmp("add-output", argv[1]) == 0) {
return backend_cmd_add_output(argc_new, argv_new, subbackend);
} else if (strcasecmp("del-output", argv[1]) == 0) {
return backend_cmd_del_output(argc_new, argv_new, subbackend);
} else if (strcasecmp("add-input", argv[1]) == 0) {
return backend_cmd_add_input(argc_new, argv_new, subbackend);
} else if (strcasecmp("del-input", argv[1]) == 0) {
return backend_cmd_del_input(argc_new, argv_new, subbackend);
}
return cmd_results_new(CMD_INVALID, "backend <cmd> [args]", "Unknown command %s", argv[1]);
}

View file

@ -1,38 +0,0 @@
#define _XOPEN_SOURCE 700
#include <string.h>
#include <strings.h>
#include "sway/commands.h"
#include "sway/config.h"
#include "sway/server.h"
#include "log.h"
#include "stringop.h"
struct cmd_results *backend_cmd_add(int argc, char **argv) {
struct cmd_results *error = NULL;
if ((error = checkarg(argc, "add", EXPECTED_AT_LEAST, 1))) {
return error;
}
const char *type_name = argv[0];
enum sway_subbackend_type type;
if (strcasecmp(type_name, "wayland") == 0) {
type = SWAY_SUBBACKEND_WAYLAND;
} else if (strcasecmp(type_name, "x11") == 0) {
type = SWAY_SUBBACKEND_X11;
} else if (strcasecmp(type_name, "drm") == 0) {
type = SWAY_SUBBACKEND_DRM;
} else if (strcasecmp(type_name, "headless") == 0) {
type = SWAY_SUBBACKEND_HEADLESS;
} else {
error =
cmd_results_new(CMD_INVALID,
"add", "Expected 'add <wayland|x11|drm|headless>'");
return error;
}
struct sway_subbackend *subbackend =
sway_subbackend_create(type, NULL);
sway_server_add_subbackend(&server, subbackend);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}

View file

@ -1,19 +0,0 @@
#define _XOPEN_SOURCE 700
#include <string.h>
#include <strings.h>
#include "sway/commands.h"
#include "sway/config.h"
#include "sway/server.h"
#include "log.h"
#include "stringop.h"
struct cmd_results *backend_cmd_del(int argc, char **argv) {
struct cmd_results *error = NULL;
if ((error = checkarg(argc, "del", EXPECTED_AT_LEAST, 1))) {
return error;
}
sway_server_remove_subbackend(&server, argv[0]);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}

View file

@ -7,8 +7,6 @@ sway_sources = files(
'input/cursor.c',
'input/keyboard.c',
'commands/backend.c',
'commands/backend/add.c',
'commands/backend/del.c',
'commands/exit.c',
'commands/exec.c',
'commands/exec_always.c',

View file

@ -12,6 +12,8 @@
#include <wlr/render/gles2.h>
#include <wlr/types/wlr_compositor.h>
#include <wlr/types/wlr_wl_shell.h>
#include <wlr/types/wlr_input_device.h>
#include <wlr/interfaces/wlr_input_device.h>
// TODO WLR: make Xwayland optional
#include <wlr/xwayland.h>
#include "sway/server.h"
@ -95,6 +97,18 @@ static void sway_subbackend_destroy(struct sway_subbackend *subbackend) {
free(subbackend);
}
struct sway_subbackend *sway_server_get_subbackend(struct sway_server *server,
char *name) {
struct sway_subbackend *subbackend = NULL;
wl_list_for_each(subbackend, &server->subbackends, link) {
if (strcasecmp(subbackend->name, name) == 0) {
return subbackend;
}
}
return NULL;
}
struct sway_subbackend *sway_subbackend_create(enum sway_subbackend_type type,
char *name) {
struct sway_subbackend *subbackend =
@ -113,6 +127,8 @@ struct sway_subbackend *sway_subbackend_create(enum sway_subbackend_type type,
}
subbackend->type = type;
wl_list_init(&subbackend->outputs);
wl_list_init(&subbackend->inputs);
wl_list_init(&subbackend->link);
return subbackend;
@ -159,6 +175,13 @@ static struct wlr_backend *drm_backend_create(struct sway_server *server) {
void sway_server_add_subbackend(struct sway_server *server,
struct sway_subbackend *subbackend) {
if (sway_server_get_subbackend(server, subbackend->name)) {
sway_log(L_ERROR, "cannot add subbackend '%s': already exists",
subbackend->name);
sway_subbackend_destroy(subbackend);
return;
}
struct wlr_backend *backend = NULL;
switch (subbackend->type) {
@ -193,12 +216,8 @@ void sway_server_add_subbackend(struct sway_server *server,
}
void sway_server_remove_subbackend(struct sway_server *server, char *name) {
struct sway_subbackend *subbackend = NULL;
wl_list_for_each(subbackend, &server->subbackends, link) {
if (strcasecmp(subbackend->name, name) == 0) {
break;
}
}
struct sway_subbackend *subbackend =
sway_server_get_subbackend(server, name);
if (!subbackend) {
sway_log(L_DEBUG, "could not find subbackend named '%s'", name);
@ -207,3 +226,136 @@ void sway_server_remove_subbackend(struct sway_server *server, char *name) {
wlr_backend_destroy(subbackend->backend);
}
struct subbackend_output {
struct sway_subbackend *backend;
struct wlr_output *wlr_output;
struct wl_listener output_destroy;
struct wl_list link; // sway_subbackend::outputs
};
static void subbackend_output_destroy(struct subbackend_output *output) {
wl_list_remove(&output->link);
wl_list_remove(&output->output_destroy.link);
free(output);
}
static void handle_subbackend_output_destroy(struct wl_listener *listener,
void *data) {
struct subbackend_output *output =
wl_container_of(listener, output, output_destroy);
subbackend_output_destroy(output);
}
void sway_subbackend_add_output(struct sway_server *server,
struct sway_subbackend *subbackend, char *name) {
struct wlr_output *wlr_output = NULL;
switch(subbackend->type) {
case SWAY_SUBBACKEND_WAYLAND:
sway_log(L_DEBUG, "TODO: create wayland subbackend output");
break;
case SWAY_SUBBACKEND_X11:
sway_log(L_DEBUG, "TODO: create x11 subbackend output");
break;
case SWAY_SUBBACKEND_DRM:
sway_log(L_DEBUG, "creating DRM subbackend outputs is not supported");
break;
case SWAY_SUBBACKEND_HEADLESS:
wlr_output =
wlr_headless_add_output(subbackend->backend, 500, 500, name);
break;
}
if (wlr_output == NULL) {
sway_log(L_ERROR, "could not create subbackend output '%s'", name);
return;
}
struct subbackend_output *output =
calloc(1, sizeof(struct subbackend_output));
if (output == NULL) {
sway_log(L_ERROR, "could not allocate subbackend output");
return;
}
output->wlr_output = wlr_output;
wl_signal_add(&wlr_output->events.destroy, &output->output_destroy);
output->output_destroy.notify = handle_subbackend_output_destroy;
wl_list_insert(&subbackend->outputs, &output->link);
}
void sway_subbackend_remove_output(struct sway_server *server,
struct sway_subbackend *subbackend, char *name) {
struct subbackend_output *output = NULL, *tmp = NULL;
wl_list_for_each_safe(output, tmp, &subbackend->outputs, link) {
if (strcasecmp(output->wlr_output->name, name) == 0) {
wlr_output_destroy(output->wlr_output);
}
}
}
struct subbackend_input {
struct sway_subbackend *backend;
struct wlr_input_device *device;
struct wl_listener input_destroy;
struct wl_list link; // sway_subbackend::inputs
};
static void subbackend_input_destroy(struct subbackend_input *input) {
wl_list_remove(&input->link);
wl_list_remove(&input->input_destroy.link);
free(input);
}
static void handle_subbackend_device_destroy(struct wl_listener *listener,
void *data) {
struct subbackend_input *input =
wl_container_of(listener, input, input_destroy);
subbackend_input_destroy(input);
}
void sway_subbackend_add_input(struct sway_server *server,
struct sway_subbackend *subbackend, enum wlr_input_device_type type,
char *name) {
if (subbackend->type != SWAY_SUBBACKEND_HEADLESS) {
sway_log(L_DEBUG, "adding inputs is only supported for the headless backend");
return;
}
struct wlr_input_device *device =
wlr_headless_add_input_device(subbackend->backend, type, name);
if (device == NULL) {
return;
}
struct subbackend_input *input =
calloc(1, sizeof(struct subbackend_input));
if (input == NULL) {
sway_log(L_ERROR, "could not allocate subbackend input device");
return;
}
input->device = device;
wl_signal_add(&device->events.destroy, &input->input_destroy);
input->input_destroy.notify = handle_subbackend_device_destroy;
wl_list_insert(&subbackend->inputs, &input->link);
}
void sway_subbackend_remove_input(struct sway_server *server,
struct sway_subbackend *subbackend, char *name) {
struct subbackend_input *input = NULL, *tmp = NULL;
wl_list_for_each_safe(input, tmp, &subbackend->inputs, link) {
if (strcasecmp(input->device->name, name) == 0) {
wlr_input_device_destroy(input->device);
}
}
}