Implement wrapping left/right/up/down across screens
This commit is contained in:
parent
38d903aea5
commit
71993c9b48
|
@ -20,5 +20,6 @@ void initialize_xinerama(xcb_connection_t *conn);
|
||||||
void xinerama_requery_screens(xcb_connection_t *conn);
|
void xinerama_requery_screens(xcb_connection_t *conn);
|
||||||
i3Screen *get_screen_at(int x, int y, struct screens_head *screenlist);
|
i3Screen *get_screen_at(int x, int y, struct screens_head *screenlist);
|
||||||
i3Screen *get_screen_containing(int x, int y);
|
i3Screen *get_screen_containing(int x, int y);
|
||||||
|
i3Screen *get_screen_most(direction_t direction);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -87,16 +87,12 @@ static void focus_thing(xcb_connection_t *conn, direction_t direction, thing_t t
|
||||||
i3Screen *screen;
|
i3Screen *screen;
|
||||||
int destination_y = (direction == D_UP ? (container->y - 1) : (container->y + container->height + 1));
|
int destination_y = (direction == D_UP ? (container->y - 1) : (container->y + container->height + 1));
|
||||||
if ((screen = get_screen_containing(container->x, destination_y)) == NULL) {
|
if ((screen = get_screen_containing(container->x, destination_y)) == NULL) {
|
||||||
LOG("Not possible, no screen found.\n");
|
LOG("Wrapping screen around vertically\n");
|
||||||
return;
|
/* No screen found? Then wrap */
|
||||||
|
screen = get_screen_most((direction == D_UP ? D_DOWN : D_UP));
|
||||||
}
|
}
|
||||||
t_ws = &(workspaces[screen->current_workspace]);
|
t_ws = &(workspaces[screen->current_workspace]);
|
||||||
new_row = (direction == D_UP ? (t_ws->rows - 1) : 0);
|
new_row = (direction == D_UP ? (t_ws->rows - 1) : 0);
|
||||||
/* Bounds checking */
|
|
||||||
if (new_col >= t_ws->cols)
|
|
||||||
new_col = (t_ws->cols - 1);
|
|
||||||
if (new_row >= t_ws->rows)
|
|
||||||
new_row = (t_ws->rows - 1);
|
|
||||||
}
|
}
|
||||||
} else if (direction == D_LEFT || direction == D_RIGHT) {
|
} else if (direction == D_LEFT || direction == D_RIGHT) {
|
||||||
if (direction == D_RIGHT && cell_exists(current_col+1, current_row))
|
if (direction == D_RIGHT && cell_exists(current_col+1, current_row))
|
||||||
|
@ -109,22 +105,23 @@ static void focus_thing(xcb_connection_t *conn, direction_t direction, thing_t t
|
||||||
i3Screen *screen;
|
i3Screen *screen;
|
||||||
int destination_x = (direction == D_LEFT ? (container->x - 1) : (container->x + container->width + 1));
|
int destination_x = (direction == D_LEFT ? (container->x - 1) : (container->x + container->width + 1));
|
||||||
if ((screen = get_screen_containing(destination_x, container->y)) == NULL) {
|
if ((screen = get_screen_containing(destination_x, container->y)) == NULL) {
|
||||||
LOG("Not possible, no screen found.\n");
|
LOG("Wrapping screen around horizontally\n");
|
||||||
return;
|
screen = get_screen_most((direction == D_LEFT ? D_RIGHT : D_LEFT));
|
||||||
}
|
}
|
||||||
t_ws = &(workspaces[screen->current_workspace]);
|
t_ws = &(workspaces[screen->current_workspace]);
|
||||||
new_col = (direction == D_LEFT ? (t_ws->cols - 1) : 0);
|
new_col = (direction == D_LEFT ? (t_ws->cols - 1) : 0);
|
||||||
/* Bounds checking */
|
|
||||||
if (new_col >= t_ws->cols)
|
|
||||||
new_col = (t_ws->cols - 1);
|
|
||||||
if (new_row >= t_ws->rows)
|
|
||||||
new_row = (t_ws->rows - 1);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG("direction unhandled\n");
|
LOG("direction unhandled\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Bounds checking */
|
||||||
|
if (new_col >= t_ws->cols)
|
||||||
|
new_col = (t_ws->cols - 1);
|
||||||
|
if (new_row >= t_ws->rows)
|
||||||
|
new_row = (t_ws->rows - 1);
|
||||||
|
|
||||||
if (t_ws->table[new_col][new_row]->currently_focused != NULL)
|
if (t_ws->table[new_col][new_row]->currently_focused != NULL)
|
||||||
set_focus(conn, t_ws->table[new_col][new_row]->currently_focused);
|
set_focus(conn, t_ws->table[new_col][new_row]->currently_focused);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
#include <xcb/xinerama.h>
|
#include <xcb/xinerama.h>
|
||||||
|
@ -62,6 +63,43 @@ i3Screen *get_screen_containing(int x, int y) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gets the screen which is the last one in the given direction, for example the screen
|
||||||
|
* on the most bottom when direction == D_DOWN, the screen most right when direction == D_RIGHT
|
||||||
|
* and so on.
|
||||||
|
*
|
||||||
|
* This function always returns a screen.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
i3Screen *get_screen_most(direction_t direction) {
|
||||||
|
i3Screen *screen, *candidate = NULL;
|
||||||
|
int position = 0;
|
||||||
|
TAILQ_FOREACH(screen, virtual_screens, screens) {
|
||||||
|
/* Repeated calls of WIN determine the winner of the comparison */
|
||||||
|
#define WIN(variable, condition) \
|
||||||
|
if (variable condition) { \
|
||||||
|
candidate = screen; \
|
||||||
|
position = variable; \
|
||||||
|
} \
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (direction) {
|
||||||
|
case D_UP:
|
||||||
|
WIN(screen->rect.y, <= position);
|
||||||
|
case D_DOWN:
|
||||||
|
WIN(screen->rect.y, >= position);
|
||||||
|
case D_LEFT:
|
||||||
|
WIN(screen->rect.x, <= position);
|
||||||
|
case D_RIGHT:
|
||||||
|
WIN(screen->rect.x, >= position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(candidate != NULL);
|
||||||
|
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fills virtual_screens with exactly one screen with width/height of the whole X server.
|
* Fills virtual_screens with exactly one screen with width/height of the whole X server.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue