aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sway/view.h1
-rw-r--r--sway/commands.c1
-rw-r--r--sway/commands/include.c15
-rw-r--r--sway/config.c89
-rw-r--r--sway/desktop/wl_shell.c5
-rw-r--r--sway/desktop/xdg_shell_v6.c11
-rw-r--r--sway/desktop/xwayland.c9
-rw-r--r--sway/meson.build1
8 files changed, 132 insertions, 0 deletions
diff --git a/include/sway/view.h b/include/sway/view.h
index 18e964f3..900bd296 100644
--- a/include/sway/view.h
+++ b/include/sway/view.h
@@ -89,6 +89,7 @@ struct sway_view {
int width, int height);
void (*set_position)(struct sway_view *view,
double ox, double oy);
+ void (*set_activated)(struct sway_view *view, bool activated);
} iface;
};
diff --git a/sway/commands.c b/sway/commands.c
index 961cb867..d6cf7a64 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -95,6 +95,7 @@ static struct cmd_handler handlers[] = {
{ "exec", cmd_exec },
{ "exec_always", cmd_exec_always },
{ "exit", cmd_exit },
+ { "include", cmd_include },
{ "output", cmd_output },
};
diff --git a/sway/commands/include.c b/sway/commands/include.c
new file mode 100644
index 00000000..1ba9a10d
--- /dev/null
+++ b/sway/commands/include.c
@@ -0,0 +1,15 @@
+#include "sway/commands.h"
+#include "sway/config.h"
+
+struct cmd_results *cmd_include(int argc, char **argv) {
+ struct cmd_results *error = NULL;
+ if ((error = checkarg(argc, "include", EXPECTED_EQUAL_TO, 1))) {
+ return error;
+ }
+
+ if (!load_include_configs(argv[0], config)) {
+ return cmd_results_new(CMD_INVALID, "include", "Failed to include sub configuration file: %s", argv[0]);
+ }
+
+ return cmd_results_new(CMD_SUCCESS, NULL, NULL);
+}
diff --git a/sway/config.c b/sway/config.c
index 475e8b04..61131845 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -311,6 +311,95 @@ bool load_main_config(const char *file, bool is_active) {
return success;
}
+static bool load_include_config(const char *path, const char *parent_dir, struct sway_config *config) {
+ // save parent config
+ const char *parent_config = config->current_config;
+
+ char *full_path = strdup(path);
+ int len = strlen(path);
+ if (len >= 1 && path[0] != '/') {
+ len = len + strlen(parent_dir) + 2;
+ full_path = malloc(len * sizeof(char));
+ if (!full_path) {
+ sway_log(L_ERROR, "Unable to allocate full path to included config");
+ return false;
+ }
+ snprintf(full_path, len, "%s/%s", parent_dir, path);
+ }
+
+ char *real_path = realpath(full_path, NULL);
+ free(full_path);
+
+ if (real_path == NULL) {
+ sway_log(L_DEBUG, "%s not found.", path);
+ return false;
+ }
+
+ // check if config has already been included
+ int j;
+ for (j = 0; j < config->config_chain->length; ++j) {
+ char *old_path = config->config_chain->items[j];
+ if (strcmp(real_path, old_path) == 0) {
+ sway_log(L_DEBUG, "%s already included once, won't be included again.", real_path);
+ free(real_path);
+ return false;
+ }
+ }
+
+ config->current_config = real_path;
+ list_add(config->config_chain, real_path);
+ int index = config->config_chain->length - 1;
+
+ if (!load_config(real_path, config)) {
+ free(real_path);
+ config->current_config = parent_config;
+ list_del(config->config_chain, index);
+ return false;
+ }
+
+ // restore current_config
+ config->current_config = parent_config;
+ return true;
+}
+
+bool load_include_configs(const char *path, struct sway_config *config) {
+ char *wd = getcwd(NULL, 0);
+ char *parent_path = strdup(config->current_config);
+ const char *parent_dir = dirname(parent_path);
+
+ if (chdir(parent_dir) < 0) {
+ free(parent_path);
+ free(wd);
+ return false;
+ }
+
+ wordexp_t p;
+
+ if (wordexp(path, &p, 0) < 0) {
+ free(parent_path);
+ free(wd);
+ return false;
+ }
+
+ char **w = p.we_wordv;
+ size_t i;
+ for (i = 0; i < p.we_wordc; ++i) {
+ load_include_config(w[i], parent_dir, config);
+ }
+ free(parent_path);
+ wordfree(&p);
+
+ // restore wd
+ if (chdir(wd) < 0) {
+ free(wd);
+ sway_log(L_ERROR, "failed to restore working directory");
+ return false;
+ }
+
+ free(wd);
+ return true;
+}
+
bool read_config(FILE *file, struct sway_config *config) {
bool success = true;
enum cmd_status block = CMD_BLOCK_END;
diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c
index b2e026ef..3f5a358a 100644
--- a/sway/desktop/wl_shell.c
+++ b/sway/desktop/wl_shell.c
@@ -45,6 +45,10 @@ static void set_position(struct sway_view *view, double ox, double oy) {
view->swayc->y = oy;
}
+static void set_activated(struct sway_view *view, bool activated) {
+ // no way to activate wl_shell
+}
+
static void handle_commit(struct wl_listener *listener, void *data) {
struct sway_wl_shell_surface *sway_surface =
wl_container_of(listener, sway_surface, commit);
@@ -96,6 +100,7 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) {
sway_view->iface.get_prop = get_prop;
sway_view->iface.set_size = set_size;
sway_view->iface.set_position = set_position;
+ sway_view->iface.set_activated = set_activated;
sway_view->wlr_wl_shell_surface = shell_surface;
sway_view->sway_wl_shell_surface = sway_surface;
sway_view->surface = shell_surface->surface;
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c
index 37e39f37..2435c256 100644
--- a/sway/desktop/xdg_shell_v6.c
+++ b/sway/desktop/xdg_shell_v6.c
@@ -45,6 +45,16 @@ static void set_position(struct sway_view *view, double ox, double oy) {
view->swayc->y = oy;
}
+static void set_activated(struct sway_view *view, bool activated) {
+ if (!assert_xdg(view)) {
+ return;
+ }
+ struct wlr_xdg_surface_v6 *surface = view->wlr_xdg_surface_v6;
+ if (surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL) {
+ wlr_xdg_toplevel_v6_set_activated(surface, activated);
+ }
+}
+
static void handle_commit(struct wl_listener *listener, void *data) {
struct sway_xdg_surface_v6 *sway_surface =
wl_container_of(listener, sway_surface, commit);
@@ -96,6 +106,7 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) {
sway_view->iface.get_prop = get_prop;
sway_view->iface.set_size = set_size;
sway_view->iface.set_position = set_position;
+ sway_view->iface.set_activated = set_activated;
sway_view->wlr_xdg_surface_v6 = xdg_surface;
sway_view->sway_xdg_surface_v6 = sway_surface;
sway_view->surface = xdg_surface->surface;
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c
index 266a5869..65c7e1ec 100644
--- a/sway/desktop/xwayland.c
+++ b/sway/desktop/xwayland.c
@@ -70,6 +70,14 @@ static void set_position(struct sway_view *view, double ox, double oy) {
view->width, view->height);
}
+static void set_activated(struct sway_view *view, bool activated) {
+ if (!assert_xwayland(view)) {
+ return;
+ }
+ struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface;
+ wlr_xwayland_surface_activate(surface, activated);
+}
+
static void handle_commit(struct wl_listener *listener, void *data) {
struct sway_xwayland_surface *sway_surface =
wl_container_of(listener, sway_surface, commit);
@@ -133,6 +141,7 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {
sway_view->iface.get_prop = get_prop;
sway_view->iface.set_size = set_size;
sway_view->iface.set_position = set_position;
+ sway_view->iface.set_activated = set_activated;
sway_view->wlr_xwayland_surface = xsurface;
sway_view->sway_xwayland_surface = sway_surface;
// TODO remove from the tree when the surface goes away (unmapped)
diff --git a/sway/meson.build b/sway/meson.build
index 5ae7fbb3..e16691a8 100644
--- a/sway/meson.build
+++ b/sway/meson.build
@@ -5,6 +5,7 @@ sway_sources = files(
'commands/exit.c',
'commands/exec.c',
'commands/exec_always.c',
+ 'commands/include.c',
'commands/output.c',
'config.c',
'config/output.c',