Implement fake-outputs option (cmdline, cfg) for multi-monitor testing
This kills the dependency on xdmx and makes the testsuite simpler and more flexible (in the output sizes / configurations).
This commit is contained in:
@ -203,6 +203,8 @@ none { return TOK_NONE; }
|
||||
focus_follows_mouse { return TOKFOCUSFOLLOWSMOUSE; }
|
||||
force_focus_wrapping { return TOK_FORCE_FOCUS_WRAPPING; }
|
||||
force_xinerama { return TOK_FORCE_XINERAMA; }
|
||||
fake_outputs { WS_STRING; return TOK_FAKE_OUTPUTS; }
|
||||
fake-outputs { WS_STRING; return TOK_FAKE_OUTPUTS; }
|
||||
workspace_auto_back_and_forth { return TOK_WORKSPACE_AUTO_BAF; }
|
||||
workspace_bar { return TOKWORKSPACEBAR; }
|
||||
popup_during_fullscreen { return TOK_POPUP_DURING_FULLSCREEN; }
|
||||
|
@ -693,6 +693,7 @@ void parse_file(const char *f) {
|
||||
%token TOKFOCUSFOLLOWSMOUSE "focus_follows_mouse"
|
||||
%token TOK_FORCE_FOCUS_WRAPPING "force_focus_wrapping"
|
||||
%token TOK_FORCE_XINERAMA "force_xinerama"
|
||||
%token TOK_FAKE_OUTPUTS "fake_outputs"
|
||||
%token TOK_WORKSPACE_AUTO_BAF "workspace_auto_back_and_forth"
|
||||
%token TOKWORKSPACEBAR "workspace_bar"
|
||||
%token TOK_DEFAULT "default"
|
||||
@ -790,6 +791,7 @@ line:
|
||||
| focus_follows_mouse
|
||||
| force_focus_wrapping
|
||||
| force_xinerama
|
||||
| fake_outputs
|
||||
| workspace_back_and_forth
|
||||
| workspace_bar
|
||||
| workspace
|
||||
@ -1451,6 +1453,14 @@ force_xinerama:
|
||||
}
|
||||
;
|
||||
|
||||
fake_outputs:
|
||||
TOK_FAKE_OUTPUTS STR
|
||||
{
|
||||
DLOG("fake outputs = %s\n", $2);
|
||||
config.fake_outputs = $2;
|
||||
}
|
||||
;
|
||||
|
||||
workspace_back_and_forth:
|
||||
TOK_WORKSPACE_AUTO_BAF bool
|
||||
{
|
||||
|
75
src/fake_outputs.c
Normal file
75
src/fake_outputs.c
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* vim:ts=4:sw=4:expandtab
|
||||
*
|
||||
* i3 - an improved dynamic tiling window manager
|
||||
* © 2009-2012 Michael Stapelberg and contributors (see also: LICENSE)
|
||||
*
|
||||
* Faking outputs is useful in pathological situations (like network X servers
|
||||
* which don’t support multi-monitor in a useful way) and for our testsuite.
|
||||
*
|
||||
*/
|
||||
#include "all.h"
|
||||
|
||||
static int num_screens;
|
||||
|
||||
/*
|
||||
* Looks in outputs for the Output whose start coordinates are x, y
|
||||
*
|
||||
*/
|
||||
static Output *get_screen_at(int x, int y) {
|
||||
Output *output;
|
||||
TAILQ_FOREACH(output, &outputs, outputs)
|
||||
if (output->rect.x == x && output->rect.y == y)
|
||||
return output;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates outputs according to the given specification.
|
||||
* The specification must be in the format wxh+x+y, for example 1024x768+0+0,
|
||||
* with multiple outputs separated by commas:
|
||||
* 1900x1200+0+0,1280x1024+1900+0
|
||||
*
|
||||
*/
|
||||
void fake_outputs_init(const char *output_spec) {
|
||||
char useless_buffer[1024];
|
||||
const char *walk = output_spec;
|
||||
unsigned int x, y, width, height;
|
||||
while (sscanf(walk, "%ux%u+%u+%u", &width, &height, &x, &y) == 4) {
|
||||
DLOG("Parsed output as width = %u, height = %u at (%u, %u)\n",
|
||||
width, height, x, y);
|
||||
Output *new_output = get_screen_at(x, y);
|
||||
if (new_output != NULL) {
|
||||
DLOG("Re-used old output %p\n", new_output);
|
||||
/* This screen already exists. We use the littlest screen so that the user
|
||||
can always see the complete workspace */
|
||||
new_output->rect.width = min(new_output->rect.width, width);
|
||||
new_output->rect.height = min(new_output->rect.height, height);
|
||||
} else {
|
||||
new_output = scalloc(sizeof(Output));
|
||||
sasprintf(&(new_output->name), "fake-%d", num_screens);
|
||||
DLOG("Created new fake output %s (%p)\n", new_output->name, new_output);
|
||||
new_output->active = true;
|
||||
new_output->rect.x = x;
|
||||
new_output->rect.y = y;
|
||||
new_output->rect.width = width;
|
||||
new_output->rect.height = height;
|
||||
/* We always treat the screen at 0x0 as the primary screen */
|
||||
if (new_output->rect.x == 0 && new_output->rect.y == 0)
|
||||
TAILQ_INSERT_HEAD(&outputs, new_output, outputs);
|
||||
else TAILQ_INSERT_TAIL(&outputs, new_output, outputs);
|
||||
output_init_con(new_output);
|
||||
init_ws_for_output(new_output, output_get_content(new_output->con));
|
||||
num_screens++;
|
||||
}
|
||||
|
||||
/* Figure out how long the input was to skip it */
|
||||
walk += sprintf(useless_buffer, "%ux%u+%u+%u", width, height, x, y) + 1;
|
||||
}
|
||||
|
||||
if (num_screens == 0) {
|
||||
ELOG("No screens found. Please fix your setup. i3 will exit now.\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
24
src/main.c
24
src/main.c
@ -252,6 +252,7 @@ int main(int argc, char *argv[]) {
|
||||
char *layout_path = NULL;
|
||||
bool delete_layout_path = false;
|
||||
bool force_xinerama = false;
|
||||
char *fake_outputs = NULL;
|
||||
bool disable_signalhandler = false;
|
||||
static struct option long_options[] = {
|
||||
{"no-autostart", no_argument, 0, 'a'},
|
||||
@ -267,6 +268,8 @@ int main(int argc, char *argv[]) {
|
||||
{"shmlog_size", required_argument, 0, 0},
|
||||
{"get-socketpath", no_argument, 0, 0},
|
||||
{"get_socketpath", no_argument, 0, 0},
|
||||
{"fake_outputs", required_argument, 0, 0},
|
||||
{"fake-outputs", required_argument, 0, 0},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
int option_index = 0, opt;
|
||||
@ -368,6 +371,11 @@ int main(int argc, char *argv[]) {
|
||||
layout_path = sstrdup(optarg);
|
||||
delete_layout_path = true;
|
||||
break;
|
||||
} else if (strcmp(long_options[option_index].name, "fake-outputs") == 0 ||
|
||||
strcmp(long_options[option_index].name, "fake_outputs") == 0) {
|
||||
LOG("Initializing fake outputs: %s\n", optarg);
|
||||
fake_outputs = sstrdup(optarg);
|
||||
break;
|
||||
}
|
||||
/* fall-through */
|
||||
default:
|
||||
@ -656,10 +664,18 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
free(greply);
|
||||
|
||||
/* Force Xinerama (for drivers which don't support RandR yet, esp. the
|
||||
* nVidia binary graphics driver), when specified either in the config
|
||||
* file or on command-line */
|
||||
if (force_xinerama || config.force_xinerama) {
|
||||
/* Setup fake outputs for testing */
|
||||
if (fake_outputs == NULL && config.fake_outputs != NULL)
|
||||
fake_outputs = config.fake_outputs;
|
||||
|
||||
if (fake_outputs != NULL) {
|
||||
fake_outputs_init(fake_outputs);
|
||||
FREE(fake_outputs);
|
||||
config.fake_outputs = NULL;
|
||||
} else if (force_xinerama || config.force_xinerama) {
|
||||
/* Force Xinerama (for drivers which don't support RandR yet, esp. the
|
||||
* nVidia binary graphics driver), when specified either in the config
|
||||
* file or on command-line */
|
||||
xinerama_init();
|
||||
} else {
|
||||
DLOG("Checking for XRandR...\n");
|
||||
|
Reference in New Issue
Block a user