aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDrew DeVault <sir@cmpwn.com>2015-08-09 20:10:26 -0400
committerDrew DeVault <sir@cmpwn.com>2015-08-09 20:10:26 -0400
commit9f091c7f82a73144b4eb4ca4f5f800c811fbab46 (patch)
tree76726b112e18cc537e080568c7e5df30520a3ed9
parent1669da719c96e80cc5c462bbd648b17c7cd25a82 (diff)
Add movement support
-rw-r--r--sway/commands.c19
-rw-r--r--sway/layout.c18
-rw-r--r--sway/layout.h1
-rw-r--r--sway/list.c1
-rw-r--r--sway/movement.c58
-rw-r--r--sway/movement.h16
6 files changed, 108 insertions, 5 deletions
diff --git a/sway/commands.c b/sway/commands.c
index 322c9519..12d38244 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -8,6 +8,7 @@
#include <ctype.h>
#include "stringop.h"
#include "layout.h"
+#include "movement.h"
#include "log.h"
#include "commands.h"
@@ -97,6 +98,23 @@ int cmd_exit(struct sway_config *config, int argc, char **argv) {
return 0;
}
+int cmd_focus(struct sway_config *config, int argc, char **argv) {
+ if (argc != 1) {
+ sway_log(L_ERROR, "Invalid focus command (expected 1 arguments, got %d)", argc);
+ return 1;
+ }
+ if (strcasecmp(argv[0], "left") == 0) {
+ move_focus(MOVE_LEFT);
+ } else if (strcasecmp(argv[0], "right") == 0) {
+ move_focus(MOVE_RIGHT);
+ } else if (strcasecmp(argv[0], "up") == 0) {
+ move_focus(MOVE_UP);
+ } else if (strcasecmp(argv[0], "down") == 0) {
+ move_focus(MOVE_DOWN);
+ }
+ return 0;
+}
+
int cmd_focus_follows_mouse(struct sway_config *config, int argc, char **argv) {
if (argc != 1) {
sway_log(L_ERROR, "Invalid focus_follows_mouse command (expected 1 arguments, got %d)", argc);
@@ -184,6 +202,7 @@ struct cmd_handler handlers[] = {
{ "bindsym", cmd_bindsym },
{ "exec", cmd_exec },
{ "exit", cmd_exit },
+ { "focus", cmd_focus },
{ "focus_follows_mouse", cmd_focus_follows_mouse },
{ "layout", cmd_layout },
{ "set", cmd_set },
diff --git a/sway/layout.c b/sway/layout.c
index 6bb19d63..b320e8ad 100644
--- a/sway/layout.c
+++ b/sway/layout.c
@@ -163,6 +163,7 @@ void add_view(wlc_handle view_handle) {
view->type = C_VIEW;
add_child(parent, view);
+ unfocus_all(&root_container);
focus_view(view);
arrange_windows(parent, -1, -1);
@@ -209,6 +210,7 @@ void destroy_view(swayc_t *view) {
parent->focused = NULL;
}
+ unfocus_all(&root_container);
if (parent->children->length != 0) {
focus_view(parent->children->items[0]);
} else {
@@ -238,12 +240,17 @@ void unfocus_all(swayc_t *container) {
}
void focus_view(swayc_t *view) {
- if (view->type == C_VIEW) {
- unfocus_all(&root_container);
- wlc_view_set_state(view->handle, WLC_BIT_ACTIVATED, true);
- wlc_view_focus(view->handle);
- }
+ sway_log(L_DEBUG, "Setting focus for %p", view);
if (view == &root_container) {
+ // Propegate wayland focus down
+ swayc_t *child = view->focused;
+ while (child && child->type != C_VIEW) {
+ child = child->focused;
+ }
+ if (child) {
+ wlc_view_set_state(child->handle, WLC_BIT_ACTIVATED, true);
+ wlc_view_focus(child->handle);
+ }
return;
}
view->parent->focused = view;
@@ -285,6 +292,7 @@ void add_output(wlc_handle output) {
add_child(container, workspace);
if (root_container.focused == NULL) {
+ unfocus_all(&root_container);
focus_view(workspace);
}
}
diff --git a/sway/layout.h b/sway/layout.h
index 08f3f78b..b0aec42f 100644
--- a/sway/layout.h
+++ b/sway/layout.h
@@ -49,6 +49,7 @@ void add_output(wlc_handle output);
void destroy_output(wlc_handle output);
void destroy_view(swayc_t *view);
void add_view(wlc_handle view);
+void unfocus_all(swayc_t *container);
void focus_view(swayc_t *view);
void arrange_windows(swayc_t *container, int width, int height);
swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data);
diff --git a/sway/list.c b/sway/list.c
index 55052f85..52943efe 100644
--- a/sway/list.c
+++ b/sway/list.c
@@ -28,6 +28,7 @@ void list_add(list_t *list, void *item) {
}
void list_insert(list_t *list, int index, void *item) {
+ // TODO: Implement this properly
if (list->length == list->capacity) {
list->capacity += 10;
list->items = realloc(list->items, sizeof(void*) * list->capacity);
diff --git a/sway/movement.c b/sway/movement.c
new file mode 100644
index 00000000..197df7b2
--- /dev/null
+++ b/sway/movement.c
@@ -0,0 +1,58 @@
+#include <stdlib.h>
+#include <stdbool.h>
+#include "list.h"
+#include "log.h"
+#include "layout.h"
+#include "movement.h"
+
+void move_focus(enum movement_direction direction) {
+ swayc_t *current = get_focused_container(&root_container);
+ swayc_t *parent = current->parent;
+
+ while (true) {
+ sway_log(L_DEBUG, "Moving focus away from %p", current);
+
+ // Test if we can even make a difference here
+ bool can_move = false;
+ int diff = 0;
+ if (direction == MOVE_LEFT || direction == MOVE_RIGHT) {
+ if (parent->layout == L_HORIZ) {
+ can_move = true;
+ diff = direction == MOVE_LEFT ? -1 : 1;
+ }
+ } else {
+ if (parent->layout == L_VERT) {
+ can_move = true;
+ diff = direction == MOVE_UP ? -1 : 1;
+ }
+ }
+ sway_log(L_DEBUG, "Can move? %s", can_move ? "yes" : "no");
+ if (can_move) {
+ int i;
+ for (i = 0; i < parent->children->length; ++i) {
+ swayc_t *child = parent->children->items[i];
+ if (child == current) {
+ break;
+ }
+ }
+ int desired = i + diff;
+ sway_log(L_DEBUG, "Moving from %d to %d", i, desired);
+ if (desired < 0 || desired >= parent->children->length) {
+ can_move = false;
+ } else {
+ unfocus_all(&root_container);
+ focus_view(parent->children->items[desired]);
+ return;
+ }
+ }
+ if (!can_move) {
+ sway_log(L_DEBUG, "Can't move at current level, moving up tree");
+ current = parent;
+ parent = parent->parent;
+ if (parent->type == C_ROOT) {
+ // Nothing we can do
+ return;
+ }
+ }
+ }
+}
diff --git a/sway/movement.h b/sway/movement.h
new file mode 100644
index 00000000..c88b44bd
--- /dev/null
+++ b/sway/movement.h
@@ -0,0 +1,16 @@
+#ifndef _SWAY_MOVEMENT_H
+#define _SWAY_MOVEMENT_H
+
+#include <wlc/wlc.h>
+#include "list.h"
+
+enum movement_direction{
+ MOVE_LEFT,
+ MOVE_RIGHT,
+ MOVE_UP,
+ MOVE_DOWN
+};
+
+void move_focus(enum movement_direction direction);
+
+#endif