From aae824b1f3a17644ea73998856d5699c689fdeb4 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Tue, 2 Mar 2010 13:35:43 +0100 Subject: [PATCH] Change workspace assignments to use the RandR output name instead of --- docs/userguide | 26 +++++++-------------- include/data.h | 5 ++-- include/randr.h | 13 +++++------ src/cfgparse.l | 20 +++++++++++----- src/cfgparse.y | 15 ++++-------- src/randr.c | 39 ++++++++++++++----------------- src/workspace.c | 62 ++++--------------------------------------------- 7 files changed, 58 insertions(+), 122 deletions(-) diff --git a/docs/userguide b/docs/userguide index 63f8e8ac..7f47acce 100644 --- a/docs/userguide +++ b/docs/userguide @@ -1,7 +1,7 @@ i3 User’s Guide =============== Michael Stapelberg -August 2009 +March 2010 This document contains all information you need to configuring and using the i3 window manager. If it does not, please contact me on IRC, Jabber or E-Mail and @@ -367,25 +367,17 @@ default it will use 1 for the first screen, 2 for the second screen and so on). *Syntax*: ---------------------------------- -workspace screen +workspace output ---------------------------------- -Screen can be either a number (starting at 0 for the first screen) or a -position. When using numbers, it is not guaranteed that your screens always -get the same number. Though, unless you upgrade your X server or drivers, the -order usually stays the same. When using positions, you have to specify the -exact pixel where the screen *starts*, not a pixel which is contained by the -screen. Thus, if your first screen has the dimensions 1280x800, you can match -the second screen right of it by specifying 1280. You cannot use 1281. +The output is the name of the RandR output you attach your screen to. On a +laptop, you might have VGA1 and LVDS1 as output names. You can see the +available outputs by running +xrandr --current+. *Examples*: --------------------------- -workspace 1 screen 0 -workspace 5 screen 1 - -workspace 1 screen 1280 -workspace 2 screen x800 -workspace 3 screen 1280x800 +workspace 1 output LVDS1 +workspace 5 output VGA1 --------------------------- === Named workspaces @@ -396,10 +388,10 @@ them names (of course UTF-8 is supported): *Syntax*: --------------------------------------- workspace -workspace screen name +workspace output name --------------------------------------- -For more details about the screen-part of this command, see above. +For more details about the output-part of this command, see above. *Examples*: -------------------------- diff --git a/include/data.h b/include/data.h index 10242f20..84ea1cd2 100644 --- a/include/data.h +++ b/include/data.h @@ -206,9 +206,8 @@ struct Workspace { /** Are the floating clients on this workspace currently hidden? */ bool floating_hidden; - /** A specifier on which this workspace would like to be (if - * the screen is available). screen := | */ - char *preferred_screen; + /** The name of the RandR output this screen should be on */ + char *preferred_output; /** Temporary flag needed for re-querying xinerama screens */ bool reassigned; diff --git a/include/randr.h b/include/randr.h index 50e19938..627afdbe 100644 --- a/include/randr.h +++ b/include/randr.h @@ -17,13 +17,6 @@ TAILQ_HEAD(outputs_head, xoutput); extern struct outputs_head outputs; -/** - * Returns true if both screen objects describe the same screen (checks their - * size and position). - * - */ -bool screens_are_equal(Output *screen1, Output *screen2); - /** * We have just established a connection to the X server and need the initial * XRandR information to setup workspaces for each screen. @@ -43,6 +36,12 @@ void randr_query_screens(xcb_connection_t *conn); */ Output *get_first_output(); +/** + * Returns the output with the given name if it is active (!) or NULL. + * + */ +Output *get_output_by_name(const char *name); + /** * Looks in virtual_screens for the i3Screen which contains coordinates x, y * diff --git a/src/cfgparse.l b/src/cfgparse.l index 1982452d..67a41300 100644 --- a/src/cfgparse.l +++ b/src/cfgparse.l @@ -39,8 +39,8 @@ EOL (\r?\n) %s BIND_A2WS_COND %s ASSIGN_COND %s COLOR_COND -%s SCREEN_COND -%s SCREEN_AWS_COND +%s OUTPUT_COND +%s OUTPUT_AWS_COND %x BUFFER_LINE %% @@ -67,6 +67,7 @@ EOL (\r?\n) [^\n]+ { BEGIN(INITIAL); yylval.string = strdup(yytext); return STR; } +[a-zA-Z0-9_-]+ { BEGIN(BIND_A2WS_COND); yylval.string = strdup(yytext); return OUTPUT; } ^[ \t]*#[^\n]* { return TOKCOMMENT; } [0-9a-fA-F]+ { yylval.string = strdup(yytext); return HEX; } [0-9]+ { yylval.number = atoi(yytext); return NUMBER; } @@ -75,7 +76,14 @@ bind { BEGIN(BIND_COND); return TOKBIND; } bindsym { BEGIN(BINDSYM_COND); return TOKBINDSYM; } floating_modifier { BEGIN(INITIAL); return TOKFLOATING_MODIFIER; } workspace { BEGIN(INITIAL); return TOKWORKSPACE; } -screen { BEGIN(SCREEN_COND); return TOKSCREEN; } +output { BEGIN(OUTPUT_COND); return TOKOUTPUT; } +screen { + /* for compatibility until v3.φ */ + ELOG("Assignments to screens are DEPRECATED and will not work. " \ + "Please replace them with assignments to outputs.\n"); + BEGIN(OUTPUT_COND); + return TOKOUTPUT; + } terminal { BEGIN(BIND_AWS_COND); return TOKTERMINAL; } font { BEGIN(BIND_AWS_COND); return TOKFONT; } assign { BEGIN(ASSIGN_COND); return TOKASSIGN; } @@ -112,15 +120,15 @@ shift { return TOKSHIFT; } {EOL} { FREE(context->line_copy); context->line_number++; + BEGIN(INITIAL); yy_push_state(BUFFER_LINE); } -x { return (int)yytext[0]; } [ \t]+ { BEGIN(BIND_AWS_COND); return WHITESPACE; } [ \t]+ { BEGIN(BINDSYM_AWS_COND); return WHITESPACE; } [ \t]+ { BEGIN(BIND_A2WS_COND); return WHITESPACE; } [ \t]+ { BEGIN(BIND_A2WS_COND); return WHITESPACE; } -[ \t]+ { BEGIN(SCREEN_AWS_COND); return WHITESPACE; } -[ \t]+ { BEGIN(BIND_A2WS_COND); return WHITESPACE; } +[ \t]+ { BEGIN(OUTPUT_AWS_COND); return WHITESPACE; } +[ \t]+ { BEGIN(BIND_A2WS_COND); return WHITESPACE; } [ \t]+ { return WHITESPACE; } \"[^\"]+\" { /* if ASSIGN_COND then */ diff --git a/src/cfgparse.y b/src/cfgparse.y index cc0e77cb..9ed17ea1 100644 --- a/src/cfgparse.y +++ b/src/cfgparse.y @@ -197,6 +197,7 @@ void parse_file(const char *f) { %token STR "" %token STR_NG "" %token HEX "" +%token OUTPUT "" %token TOKBIND %token TOKTERMINAL %token TOKCOMMENT "" @@ -209,7 +210,7 @@ void parse_file(const char *f) { %token TOKFLOATING_MODIFIER "floating_modifier" %token QUOTEDSTRING "" %token TOKWORKSPACE "workspace" -%token TOKSCREEN "screen" +%token TOKOUTPUT "output" %token TOKASSIGN "assign" %token TOKSET %token TOKIPCSOCKET "ipc_socket" @@ -429,14 +430,14 @@ focus_follows_mouse: ; workspace: - TOKWORKSPACE WHITESPACE NUMBER WHITESPACE TOKSCREEN WHITESPACE screen optional_workspace_name + TOKWORKSPACE WHITESPACE NUMBER WHITESPACE TOKOUTPUT WHITESPACE OUTPUT optional_workspace_name { int ws_num = $3; if (ws_num < 1) { DLOG("Invalid workspace assignment, workspace number %d out of range\n", ws_num); } else { Workspace *ws = workspace_get(ws_num - 1); - ws->preferred_screen = sstrdup($7); + ws->preferred_output = sstrdup($7); if ($8 != NULL) workspace_set_name(ws, $8); } @@ -447,6 +448,7 @@ workspace: if (ws_num < 1) { DLOG("Invalid workspace assignment, workspace number %d out of range\n", ws_num); } else { + DLOG("workspace name to: %s\n", $5); if ($5 != NULL) workspace_set_name(workspace_get(ws_num - 1), $5); } @@ -464,13 +466,6 @@ workspace_name: | WORD { $$ = $1; } ; -screen: - NUMBER { asprintf(&$$, "%d", $1); } - | NUMBER 'x' { asprintf(&$$, "%d", $1); } - | NUMBER 'x' NUMBER { asprintf(&$$, "%dx%d", $1, $3); } - | 'x' NUMBER { asprintf(&$$, "x%d", $2); } - ; - assign: TOKASSIGN WHITESPACE window_class WHITESPACE optional_arrow assign_target { diff --git a/src/randr.c b/src/randr.c index f63b2f0c..d56f01f0 100644 --- a/src/randr.c +++ b/src/randr.c @@ -45,35 +45,30 @@ typedef xcb_randr_get_screen_resources_current_reply_t resources_reply; struct outputs_head outputs = TAILQ_HEAD_INITIALIZER(outputs); /* - * Returns true if both screen objects describe the same screen (checks their - * size and position). + * Get a specific output by its internal X11 id. Used by randr_query_screens + * to check if the output is new (only in the first scan) or if we are + * re-scanning. * */ -bool screens_are_equal(Output *screen1, Output *screen2) { - /* If one of both objects (or both) are NULL, we cannot compare them */ - if (screen1 == NULL || screen2 == NULL) - return false; - - /* If the pointers are equal, take the short-circuit */ - if (screen1 == screen2) - return true; - - /* Compare their size and position - other properties are not relevant - * to determine if a screen is equal to another one */ - return (memcmp(&(screen1->rect), &(screen2->rect), sizeof(Rect)) == 0); +static Output *get_output_by_id(xcb_randr_output_t id) { + Output *output; + TAILQ_FOREACH(output, &outputs, outputs) + if (output->id == id) + return output; + + return NULL; } /* - * Get a specific output by its internal X11 id. Used by randr_query_screens - * to check if the output is new (only in the first scan) or if we are - * re-scanning. + * Returns the output with the given name if it is active (!) or NULL. * */ -static Output *get_output_by_id(xcb_randr_output_t id) { - Output *screen; - TAILQ_FOREACH(screen, &outputs, outputs) - if (screen->id == id) - return screen; +Output *get_output_by_name(const char *name) { + Output *output; + TAILQ_FOREACH(output, &outputs, outputs) + if (output->active && + strcasecmp(output->name, name) == 0) + return output; return NULL; } diff --git a/src/workspace.c b/src/workspace.c index 5a4902ca..a579bf1d 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -195,58 +195,6 @@ void workspace_show(xcb_connection_t *conn, int workspace) { } } - -/* - * Parses the preferred_screen property of a workspace. You can either specify - * the screen number (it is not given that the screen numbering always stays - * the same) or the screen coordinates (exact coordinates, e.g. 1280 will match - * the screen starting at x=1280, but 1281 will not). For coordinates, you can - * either specify an x coordinate ("1280") or an y coordinate ("x800") or both - * ("1280x800"). - * - */ -static Output *get_screen_from_preference(char *preference) { - Output *screen; - char *rest; - int preferred_screen = strtol(preference, &rest, 10); - - DLOG("Getting screen for preference \"%s\" (%d)\n", preference, preferred_screen); - - if ((rest == preference) || (preferred_screen >= num_screens)) { - int x = INT_MAX, y = INT_MAX; - if (strchr(preference, 'x') != NULL) { - /* Check if only the y coordinate was specified */ - if (*preference == 'x') - y = atoi(preference+1); - else { - x = atoi(preference); - y = atoi(strchr(preference, 'x') + 1); - } - } else { - x = atoi(preference); - } - - DLOG("Looking for screen at %d x %d\n", x, y); - - TAILQ_FOREACH(screen, &outputs, outputs) - if ((x == INT_MAX || screen->rect.x == x) && - (y == INT_MAX || screen->rect.y == y)) { - DLOG("found %p\n", screen); - return screen; - } - - DLOG("none found\n"); - return NULL; - } else { - int c = 0; - TAILQ_FOREACH(screen, &outputs, outputs) - if (c++ == preferred_screen) - return screen; - } - - return NULL; -} - /* * Assigns the given workspace to the given output by correctly updating its * state and reconfiguring all the clients on this workspace. @@ -311,8 +259,8 @@ void workspace_initialize(Workspace *ws, Output *output, bool recheck) { /* If this workspace has no preferred output or if the output it wants * to be on is not available at the moment, we initialize it with * the output which was given */ - if (ws->preferred_screen == NULL || - (ws->output = get_screen_from_preference(ws->preferred_screen)) == NULL) + if (ws->preferred_output == NULL || + (ws->output = get_output_by_name(ws->preferred_output)) == NULL) ws->output = output; DLOG("old_output = %p, ws->output = %p\n", old_output, ws->output); @@ -325,7 +273,7 @@ void workspace_initialize(Workspace *ws, Output *output, bool recheck) { /* * Gets the first unused workspace for the given screen, taking into account - * the preferred_screen setting of every workspace (workspace assignments). + * the preferred_output setting of every workspace (workspace assignments). * */ Workspace *get_first_workspace_for_screen(Output *output) { @@ -333,8 +281,8 @@ Workspace *get_first_workspace_for_screen(Output *output) { Workspace *ws; TAILQ_FOREACH(ws, workspaces, workspaces) { - if (ws->preferred_screen == NULL || - !screens_are_equal(get_screen_from_preference(ws->preferred_screen), output)) + if (ws->preferred_output == NULL || + get_output_by_name(ws->preferred_output) != output) continue; result = ws; -- 2.39.5