Re-Implement support for RandR changes
This commit is contained in:
parent
f54ce1ddda
commit
5098e45f23
|
@ -202,6 +202,7 @@ struct xoutput {
|
||||||
/** x, y, width, height */
|
/** x, y, width, height */
|
||||||
Rect rect;
|
Rect rect;
|
||||||
|
|
||||||
|
#if 0
|
||||||
/** The bar window */
|
/** The bar window */
|
||||||
xcb_window_t bar;
|
xcb_window_t bar;
|
||||||
xcb_gcontext_t bargc;
|
xcb_gcontext_t bargc;
|
||||||
|
@ -209,6 +210,7 @@ struct xoutput {
|
||||||
/** Contains all clients with _NET_WM_WINDOW_TYPE ==
|
/** Contains all clients with _NET_WM_WINDOW_TYPE ==
|
||||||
* _NET_WM_WINDOW_TYPE_DOCK */
|
* _NET_WM_WINDOW_TYPE_DOCK */
|
||||||
SLIST_HEAD(dock_clients_head, Client) dock_clients;
|
SLIST_HEAD(dock_clients_head, Client) dock_clients;
|
||||||
|
#endif
|
||||||
|
|
||||||
TAILQ_ENTRY(xoutput) outputs;
|
TAILQ_ENTRY(xoutput) outputs;
|
||||||
};
|
};
|
||||||
|
|
|
@ -71,6 +71,7 @@ int handle_map_request(void *prophs, xcb_connection_t *conn,
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int handle_configure_event(void *prophs, xcb_connection_t *conn, xcb_configure_notify_event_t *event);
|
int handle_configure_event(void *prophs, xcb_connection_t *conn, xcb_configure_notify_event_t *event);
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets triggered upon a RandR screen change event, that is when the user
|
* Gets triggered upon a RandR screen change event, that is when the user
|
||||||
|
@ -79,7 +80,6 @@ int handle_configure_event(void *prophs, xcb_connection_t *conn, xcb_configure_n
|
||||||
*/
|
*/
|
||||||
int handle_screen_change(void *prophs, xcb_connection_t *conn,
|
int handle_screen_change(void *prophs, xcb_connection_t *conn,
|
||||||
xcb_generic_event_t *e);
|
xcb_generic_event_t *e);
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configure requests are received when the application wants to resize
|
* Configure requests are received when the application wants to resize
|
||||||
|
|
|
@ -31,6 +31,16 @@ void randr_init(int *event_base);
|
||||||
*/
|
*/
|
||||||
void disable_randr(xcb_connection_t *conn);
|
void disable_randr(xcb_connection_t *conn);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a CT_OUTPUT Con (searches existing ones from inplace restart
|
||||||
|
* before) to use for the given Output.
|
||||||
|
*
|
||||||
|
* XXX: for assignments, we probably need to move workspace creation from here
|
||||||
|
* to after the loop in randr_query_outputs().
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void output_init_con(Output *output);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the specified output, assigning the specified workspace to it.
|
* Initializes the specified output, assigning the specified workspace to it.
|
||||||
*
|
*
|
||||||
|
|
|
@ -428,6 +428,7 @@ int handle_configure_event(void *prophs, xcb_connection_t *conn, xcb_configure_n
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Gets triggered upon a RandR screen change event, that is when the user
|
* Gets triggered upon a RandR screen change event, that is when the user
|
||||||
|
@ -438,13 +439,12 @@ int handle_screen_change(void *prophs, xcb_connection_t *conn,
|
||||||
xcb_generic_event_t *e) {
|
xcb_generic_event_t *e) {
|
||||||
DLOG("RandR screen change\n");
|
DLOG("RandR screen change\n");
|
||||||
|
|
||||||
randr_query_outputs(conn);
|
randr_query_outputs();
|
||||||
|
|
||||||
ipc_send_event("output", I3_IPC_EVENT_OUTPUT, "{\"change\":\"unspecified\"}");
|
ipc_send_event("output", I3_IPC_EVENT_OUTPUT, "{\"change\":\"unspecified\"}");
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Our window decorations were unmapped. That means, the window will be killed
|
* Our window decorations were unmapped. That means, the window will be killed
|
||||||
|
|
29
src/main.c
29
src/main.c
|
@ -325,21 +325,6 @@ int main(int argc, char *argv[]) {
|
||||||
translate_keysyms();
|
translate_keysyms();
|
||||||
grab_all_keys(conn, false);
|
grab_all_keys(conn, false);
|
||||||
|
|
||||||
int randr_base;
|
|
||||||
if (force_xinerama) {
|
|
||||||
xinerama_init();
|
|
||||||
} else {
|
|
||||||
DLOG("Checking for XRandR...\n");
|
|
||||||
randr_init(&randr_base);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
xcb_event_set_handler(&evenths,
|
|
||||||
randr_base + XCB_RANDR_SCREEN_CHANGE_NOTIFY,
|
|
||||||
handle_screen_change,
|
|
||||||
NULL);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
bool needs_tree_init = true;
|
bool needs_tree_init = true;
|
||||||
if (layout_path) {
|
if (layout_path) {
|
||||||
LOG("Trying to restore the layout from %s...", layout_path);
|
LOG("Trying to restore the layout from %s...", layout_path);
|
||||||
|
@ -350,6 +335,20 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
if (needs_tree_init)
|
if (needs_tree_init)
|
||||||
tree_init();
|
tree_init();
|
||||||
|
|
||||||
|
int randr_base;
|
||||||
|
if (force_xinerama) {
|
||||||
|
xinerama_init();
|
||||||
|
} else {
|
||||||
|
DLOG("Checking for XRandR...\n");
|
||||||
|
randr_init(&randr_base);
|
||||||
|
|
||||||
|
xcb_event_set_handler(&evenths,
|
||||||
|
randr_base + XCB_RANDR_SCREEN_CHANGE_NOTIFY,
|
||||||
|
handle_screen_change,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
tree_render();
|
tree_render();
|
||||||
|
|
||||||
struct ev_loop *loop = ev_loop_new(0);
|
struct ev_loop *loop = ev_loop_new(0);
|
||||||
|
|
136
src/randr.c
136
src/randr.c
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* i3 - an improved dynamic tiling window manager
|
* i3 - an improved dynamic tiling window manager
|
||||||
*
|
*
|
||||||
* © 2009-2010 Michael Stapelberg and contributors
|
* © 2009-2011 Michael Stapelberg and contributors
|
||||||
*
|
*
|
||||||
* See file LICENSE for license information.
|
* See file LICENSE for license information.
|
||||||
*
|
*
|
||||||
|
@ -215,6 +215,74 @@ void disable_randr(xcb_connection_t *conn) {
|
||||||
randr_disabled = true;
|
randr_disabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initializes a CT_OUTPUT Con (searches existing ones from inplace restart
|
||||||
|
* before) to use for the given Output.
|
||||||
|
*
|
||||||
|
* XXX: for assignments, we probably need to move workspace creation from here
|
||||||
|
* to after the loop in randr_query_outputs().
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void output_init_con(Output *output) {
|
||||||
|
Con *con = NULL, *current;
|
||||||
|
bool reused = false;
|
||||||
|
static int c = 1;
|
||||||
|
|
||||||
|
DLOG("init_con for output %s\n", output->name);
|
||||||
|
|
||||||
|
/* Search for a Con with that name directly below the root node. There
|
||||||
|
* might be one from a restored layout. */
|
||||||
|
TAILQ_FOREACH(current, &(croot->nodes_head), nodes) {
|
||||||
|
if (strcmp(current->name, output->name) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
con = current;
|
||||||
|
reused = true;
|
||||||
|
DLOG("Using existing con %p / %s\n", con, con->name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (con == NULL) {
|
||||||
|
con = con_new(croot);
|
||||||
|
FREE(con->name);
|
||||||
|
con->name = sstrdup(output->name);
|
||||||
|
con->type = CT_OUTPUT;
|
||||||
|
}
|
||||||
|
con->rect = output->rect;
|
||||||
|
output->con = con;
|
||||||
|
|
||||||
|
char *name;
|
||||||
|
asprintf(&name, "[i3 con] output %s", con->name);
|
||||||
|
x_set_name(con, name);
|
||||||
|
free(name);
|
||||||
|
|
||||||
|
if (reused) {
|
||||||
|
DLOG("Not adding workspace, this was a reused con\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DLOG("Now adding a workspace\n");
|
||||||
|
|
||||||
|
/* add a workspace to this output */
|
||||||
|
Con *ws = con_new(NULL);
|
||||||
|
ws->type = CT_WORKSPACE;
|
||||||
|
/* TODO: don't just number workspaces, but get the next assigned one / unused one */
|
||||||
|
ws->num = c;
|
||||||
|
FREE(ws->name);
|
||||||
|
asprintf(&(ws->name), "%d", c);
|
||||||
|
c++;
|
||||||
|
con_attach(ws, con, false);
|
||||||
|
|
||||||
|
asprintf(&name, "[i3 con] workspace %s", ws->name);
|
||||||
|
x_set_name(ws, name);
|
||||||
|
free(name);
|
||||||
|
|
||||||
|
ws->fullscreen_mode = CF_OUTPUT;
|
||||||
|
ws->orientation = HORIZ;
|
||||||
|
|
||||||
|
/* TODO: Set focus in main.c */
|
||||||
|
con_focus(ws);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function needs to be called when changing the mode of an output when
|
* This function needs to be called when changing the mode of an output when
|
||||||
* it already has some workspaces (or a bar window) assigned.
|
* it already has some workspaces (or a bar window) assigned.
|
||||||
|
@ -227,9 +295,12 @@ void disable_randr(xcb_connection_t *conn) {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void output_change_mode(xcb_connection_t *conn, Output *output) {
|
static void output_change_mode(xcb_connection_t *conn, Output *output) {
|
||||||
i3Font *font = load_font(conn, config.font);
|
//i3Font *font = load_font(conn, config.font);
|
||||||
|
|
||||||
DLOG("Output mode changed, reconfiguring bar, updating workspaces\n");
|
DLOG("Output mode changed, updating rect\n");
|
||||||
|
assert(output->con != NULL);
|
||||||
|
output->con->rect = output->rect;
|
||||||
|
#if 0
|
||||||
Rect bar_rect = {output->rect.x,
|
Rect bar_rect = {output->rect.x,
|
||||||
output->rect.y + output->rect.height - (font->height + 6),
|
output->rect.y + output->rect.height - (font->height + 6),
|
||||||
output->rect.x + output->rect.width,
|
output->rect.x + output->rect.width,
|
||||||
|
@ -237,7 +308,6 @@ static void output_change_mode(xcb_connection_t *conn, Output *output) {
|
||||||
|
|
||||||
xcb_set_window_rect(conn, output->bar, bar_rect);
|
xcb_set_window_rect(conn, output->bar, bar_rect);
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* go through all workspaces and set force_reconfigure */
|
/* go through all workspaces and set force_reconfigure */
|
||||||
TAILQ_FOREACH(ws, workspaces, workspaces) {
|
TAILQ_FOREACH(ws, workspaces, workspaces) {
|
||||||
if (ws->output != output)
|
if (ws->output != output)
|
||||||
|
@ -442,31 +512,47 @@ void randr_query_outputs() {
|
||||||
if ((first = get_first_output()) == NULL)
|
if ((first = get_first_output()) == NULL)
|
||||||
die("No usable outputs available\n");
|
die("No usable outputs available\n");
|
||||||
|
|
||||||
//bool needs_init = (first->current_workspace == NULL);
|
/* We need to move the workspaces from the disappearing output to the first output */
|
||||||
|
/* 1: Get the con to focus next, if the disappearing ws is focused */
|
||||||
#if 0
|
Con *next = NULL;
|
||||||
TAILQ_FOREACH(ws, workspaces, workspaces) {
|
if (TAILQ_FIRST(&(croot->focus_head)) == output->con) {
|
||||||
if (ws->output != output)
|
DLOG("This output (%p) was focused! Getting next\n", output->con);
|
||||||
continue;
|
next = con_next_focused(output->con);
|
||||||
|
DLOG("next = %p\n", next);
|
||||||
workspace_assign_to(ws, first, true);
|
|
||||||
if (!needs_init)
|
|
||||||
continue;
|
|
||||||
//initialize_output(conn, first, ws);
|
|
||||||
needs_init = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Client *dock;
|
/* 2: iterate through workspaces and re-assign them */
|
||||||
while (!SLIST_EMPTY(&(output->dock_clients))) {
|
Con *current;
|
||||||
dock = SLIST_FIRST(&(output->dock_clients));
|
while (!TAILQ_EMPTY(&(output->con->nodes_head))) {
|
||||||
SLIST_REMOVE_HEAD(&(output->dock_clients), dock_clients);
|
current = TAILQ_FIRST(&(output->con->nodes_head));
|
||||||
SLIST_INSERT_HEAD(&(first->dock_clients), dock, dock_clients);
|
DLOG("Detaching current = %p / %s\n", current, current->name);
|
||||||
|
con_detach(current);
|
||||||
|
DLOG("Re-attaching current = %p / %s\n", current, current->name);
|
||||||
|
con_attach(current, first->con, false);
|
||||||
|
DLOG("Done, next\n");
|
||||||
|
}
|
||||||
|
DLOG("re-attached all workspaces\n");
|
||||||
|
|
||||||
|
if (next) {
|
||||||
|
DLOG("now focusing next = %p\n", next);
|
||||||
|
con_focus(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
DLOG("destroying disappearing con %p\n", output->con);
|
||||||
//output->current_workspace = NULL;
|
tree_close(output->con, false, true);
|
||||||
|
DLOG("Done. Should be fine now\n");
|
||||||
|
output->con = NULL;
|
||||||
|
|
||||||
output->to_be_disabled = false;
|
output->to_be_disabled = false;
|
||||||
} else if (output->changed) {
|
}
|
||||||
|
|
||||||
|
if (output->active && output->con == NULL) {
|
||||||
|
DLOG("Need to initialize a Con for output %s\n", output->name);
|
||||||
|
output_init_con(output);
|
||||||
|
output->changed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output->changed) {
|
||||||
output_change_mode(conn, output);
|
output_change_mode(conn, output);
|
||||||
output->changed = false;
|
output->changed = false;
|
||||||
}
|
}
|
||||||
|
@ -504,7 +590,7 @@ void randr_init(int *event_base) {
|
||||||
extreply = xcb_get_extension_data(conn, &xcb_randr_id);
|
extreply = xcb_get_extension_data(conn, &xcb_randr_id);
|
||||||
if (!extreply->present)
|
if (!extreply->present)
|
||||||
disable_randr(conn);
|
disable_randr(conn);
|
||||||
else randr_query_outputs(conn);
|
else randr_query_outputs();
|
||||||
|
|
||||||
if (event_base != NULL)
|
if (event_base != NULL)
|
||||||
*event_base = extreply->first_event;
|
*event_base = extreply->first_event;
|
||||||
|
|
45
src/tree.c
45
src/tree.c
|
@ -40,56 +40,15 @@ bool tree_restore(const char *path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initializes the tree by creating the root node, adding all RandR outputs
|
* Initializes the tree by creating the root node. The CT_OUTPUT Cons below the
|
||||||
* to the tree (that means randr_init() has to be called before) and
|
* root node are created in randr.c for each Output.
|
||||||
* assigning a workspace to each RandR output.
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void tree_init() {
|
void tree_init() {
|
||||||
Output *output;
|
|
||||||
|
|
||||||
croot = con_new(NULL);
|
croot = con_new(NULL);
|
||||||
FREE(croot->name);
|
FREE(croot->name);
|
||||||
croot->name = "root";
|
croot->name = "root";
|
||||||
croot->type = CT_ROOT;
|
croot->type = CT_ROOT;
|
||||||
|
|
||||||
Con *ws;
|
|
||||||
int c = 1;
|
|
||||||
/* add the outputs */
|
|
||||||
TAILQ_FOREACH(output, &outputs, outputs) {
|
|
||||||
if (!output->active)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Con *oc = con_new(croot);
|
|
||||||
FREE(oc->name);
|
|
||||||
oc->name = strdup(output->name);
|
|
||||||
oc->type = CT_OUTPUT;
|
|
||||||
oc->rect = output->rect;
|
|
||||||
output->con = oc;
|
|
||||||
|
|
||||||
char *name;
|
|
||||||
asprintf(&name, "[i3 con] output %s", oc->name);
|
|
||||||
x_set_name(oc, name);
|
|
||||||
free(name);
|
|
||||||
|
|
||||||
/* add a workspace to this output */
|
|
||||||
ws = con_new(NULL);
|
|
||||||
ws->type = CT_WORKSPACE;
|
|
||||||
ws->num = c;
|
|
||||||
FREE(ws->name);
|
|
||||||
asprintf(&(ws->name), "%d", c);
|
|
||||||
c++;
|
|
||||||
con_attach(ws, oc, false);
|
|
||||||
|
|
||||||
asprintf(&name, "[i3 con] workspace %s", ws->name);
|
|
||||||
x_set_name(ws, name);
|
|
||||||
free(name);
|
|
||||||
|
|
||||||
ws->fullscreen_mode = CF_OUTPUT;
|
|
||||||
ws->orientation = HORIZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
con_focus(ws);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* i3 - an improved dynamic tiling window manager
|
* i3 - an improved dynamic tiling window manager
|
||||||
*
|
*
|
||||||
* © 2009-2010 Michael Stapelberg and contributors
|
* © 2009-2011 Michael Stapelberg and contributors
|
||||||
*
|
*
|
||||||
* See file LICENSE for license information.
|
* See file LICENSE for license information.
|
||||||
*
|
*
|
||||||
|
@ -70,6 +70,7 @@ static void query_screens(xcb_connection_t *conn) {
|
||||||
if (s->rect.x == 0 && s->rect.y == 0)
|
if (s->rect.x == 0 && s->rect.y == 0)
|
||||||
TAILQ_INSERT_HEAD(&outputs, s, outputs);
|
TAILQ_INSERT_HEAD(&outputs, s, outputs);
|
||||||
else TAILQ_INSERT_TAIL(&outputs, s, outputs);
|
else TAILQ_INSERT_TAIL(&outputs, s, outputs);
|
||||||
|
output_init_con(s);
|
||||||
num_screens++;
|
num_screens++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue