huge change: implement RandR instead of Xinerama
Thanks to Merovius for doing a proof of concept on this one and being a driving force behind the idea. Using RandR instead of Xinerama means that we are now able to use the full potential of the modern way of configuring screens. That means, i3 now has an idea of the outputs your graphic driver provides, which allowed us to get rid of the ugly way of detecting changes in the screen configuration which we used before. Now, your workspaces should not be confused when changing output modes anymore. Also, instead of having ugly heuristics to assign your workspaces to (the screen at position X or the second screen in the list of screens) you will be able to just specify an output name. As this change basically touches everything, you should be prepared for bugs. Please test and report them!
This commit is contained in:
@ -3,7 +3,7 @@
|
||||
*
|
||||
* i3 - an improved dynamic tiling window manager
|
||||
*
|
||||
* © 2009 Michael Stapelberg and contributors
|
||||
* © 2009-2010 Michael Stapelberg and contributors
|
||||
*
|
||||
* See file LICENSE for license information.
|
||||
*
|
||||
@ -11,6 +11,7 @@
|
||||
*
|
||||
*/
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/randr.h>
|
||||
#include <xcb/xcb_atom.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
@ -25,11 +26,12 @@
|
||||
*
|
||||
* Let’s start from the biggest to the smallest:
|
||||
*
|
||||
* - An i3Screen is a virtual screen (Xinerama). This can be a single one,
|
||||
* though two monitors might be connected, if you’re running clone
|
||||
* mode. There can also be multiple of them.
|
||||
* - An Output is a physical output on your graphics driver. Outputs which
|
||||
* are currently in use have (output->active == true). Each output has a
|
||||
* position and a mode. An output usually corresponds to one connected
|
||||
* screen (except if you are running multiple screens in clone mode).
|
||||
*
|
||||
* - Each i3Screen contains Workspaces. The concept is known from various
|
||||
* - Each Output contains Workspaces. The concept is known from various
|
||||
* other window managers. Basically, a workspace is a specific set of
|
||||
* windows, usually grouped thematically (irc, www, work, …). You can switch
|
||||
* between these.
|
||||
@ -54,7 +56,7 @@ typedef struct Client Client;
|
||||
typedef struct Binding Binding;
|
||||
typedef struct Workspace Workspace;
|
||||
typedef struct Rect Rect;
|
||||
typedef struct Screen i3Screen;
|
||||
typedef struct xoutput Output;
|
||||
|
||||
/******************************************************************************
|
||||
* Helper types
|
||||
@ -228,8 +230,8 @@ struct Workspace {
|
||||
* appended) */
|
||||
TAILQ_HEAD(floating_clients_head, Client) floating_clients;
|
||||
|
||||
/** Backpointer to the screen this workspace is on */
|
||||
i3Screen *screen;
|
||||
/** Backpointer to the output this workspace is on */
|
||||
Output *output;
|
||||
|
||||
/** This is a two-dimensional dynamic array of
|
||||
* Container-pointers. I’ve always wanted to be a three-star
|
||||
@ -496,14 +498,21 @@ struct Container {
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a virtual screen (Xinerama). This can be a single one, though two
|
||||
* monitors might be connected, if you’re running clone mode. There can also
|
||||
* be multiple of them.
|
||||
* An Output is a physical output on your graphics driver. Outputs which
|
||||
* are currently in use have (output->active == true). Each output has a
|
||||
* position and a mode. An output usually corresponds to one connected
|
||||
* screen (except if you are running multiple screens in clone mode).
|
||||
*
|
||||
*/
|
||||
struct Screen {
|
||||
/** Virtual screen number */
|
||||
int num;
|
||||
struct xoutput {
|
||||
/** Output id, so that we can requery the output directly later */
|
||||
xcb_randr_output_t id;
|
||||
/** Name of the output */
|
||||
char *name;
|
||||
|
||||
/** Whether the output is currently (has a CRTC attached with a valid
|
||||
* mode) */
|
||||
bool active;
|
||||
|
||||
/** Current workspace selected on this virtual screen */
|
||||
Workspace *current_workspace;
|
||||
@ -519,7 +528,7 @@ struct Screen {
|
||||
* _NET_WM_WINDOW_TYPE_DOCK */
|
||||
SLIST_HEAD(dock_clients_head, Client) dock_clients;
|
||||
|
||||
TAILQ_ENTRY(Screen) screens;
|
||||
TAILQ_ENTRY(xoutput) outputs;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* i3 - an improved dynamic tiling window manager
|
||||
*
|
||||
* (c) 2009 Michael Stapelberg and contributors
|
||||
* © 2009-2010 Michael Stapelberg and contributors
|
||||
*
|
||||
* See file LICENSE for license information.
|
||||
*
|
||||
@ -11,6 +11,8 @@
|
||||
#ifndef _HANDLERS_H
|
||||
#define _HANDLERS_H
|
||||
|
||||
#include <xcb/randr.h>
|
||||
|
||||
/**
|
||||
* Due to bindings like Mode_switch + <a>, we need to bind some keys in
|
||||
* XCB_GRAB_MODE_SYNC. Therefore, we just replay all key presses.
|
||||
@ -74,6 +76,14 @@ 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);
|
||||
|
||||
/**
|
||||
* Gets triggered upon a RandR screen change event, that is when the user
|
||||
* changes the screen configuration in any way (mode, position, …)
|
||||
*
|
||||
*/
|
||||
int handle_screen_change(void *prophs, xcb_connection_t *conn,
|
||||
xcb_generic_event_t *e);
|
||||
|
||||
/**
|
||||
* Configure requests are received when the application wants to resize
|
||||
* windows on their own.
|
||||
|
@ -79,7 +79,7 @@ void ignore_enter_notify_forall(xcb_connection_t *conn, Workspace *workspace,
|
||||
* Renders the given workspace on the given screen
|
||||
*
|
||||
*/
|
||||
void render_workspace(xcb_connection_t *conn, i3Screen *screen, Workspace *r_ws);
|
||||
void render_workspace(xcb_connection_t *conn, Output *output, Workspace *r_ws);
|
||||
|
||||
/**
|
||||
* Renders the whole layout, that is: Go through each screen, each workspace,
|
||||
|
62
include/randr.h
Normal file
62
include/randr.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* vim:ts=8:expandtab
|
||||
*
|
||||
* i3 - an improved dynamic tiling window manager
|
||||
*
|
||||
* © 2009-2010 Michael Stapelberg and contributors
|
||||
*
|
||||
* See file LICENSE for license information.
|
||||
*
|
||||
*/
|
||||
#include "data.h"
|
||||
#include <xcb/randr.h>
|
||||
|
||||
#ifndef _RANDR_H
|
||||
#define _RANDR_H
|
||||
|
||||
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.
|
||||
*
|
||||
*/
|
||||
void initialize_randr(xcb_connection_t *conn, int *event_base);
|
||||
|
||||
/**
|
||||
* (Re-)queries the outputs via RandR and stores them in the list of outputs.
|
||||
*
|
||||
*/
|
||||
void randr_query_screens(xcb_connection_t *conn);
|
||||
|
||||
/**
|
||||
* Returns the first output which is active.
|
||||
*
|
||||
*/
|
||||
Output *get_first_output();
|
||||
|
||||
/**
|
||||
* Looks in virtual_screens for the i3Screen which contains coordinates x, y
|
||||
*
|
||||
*/
|
||||
Output *get_screen_containing(int x, int y);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
Output *get_screen_most(direction_t direction, Output *current);
|
||||
|
||||
#endif
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* i3 - an improved dynamic tiling window manager
|
||||
*
|
||||
* © 2009 Michael Stapelberg and contributors
|
||||
* © 2009-2010 Michael Stapelberg and contributors
|
||||
*
|
||||
* See file LICENSE for license information.
|
||||
*
|
||||
@ -11,7 +11,7 @@
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
#include "data.h"
|
||||
#include "xinerama.h"
|
||||
#include "randr.h"
|
||||
|
||||
#ifndef _WORKSPACE_H
|
||||
#define _WORKSPACE_H
|
||||
@ -53,7 +53,7 @@ void workspace_show(xcb_connection_t *conn, int workspace);
|
||||
* screen 1 and you just plugged in screen 1).
|
||||
*
|
||||
*/
|
||||
void workspace_assign_to(Workspace *ws, i3Screen *screen);
|
||||
void workspace_assign_to(Workspace *ws, Output *screen);
|
||||
|
||||
/**
|
||||
* Initializes the given workspace if it is not already initialized. The given
|
||||
@ -62,14 +62,14 @@ void workspace_assign_to(Workspace *ws, i3Screen *screen);
|
||||
* the screen is not attached at the moment.
|
||||
*
|
||||
*/
|
||||
void workspace_initialize(Workspace *ws, i3Screen *screen, bool recheck);
|
||||
void workspace_initialize(Workspace *ws, Output *screen, bool recheck);
|
||||
|
||||
/**
|
||||
* Gets the first unused workspace for the given screen, taking into account
|
||||
* the preferred_screen setting of every workspace (workspace assignments).
|
||||
*
|
||||
*/
|
||||
Workspace *get_first_workspace_for_screen(struct screens_head *slist, i3Screen *screen);
|
||||
Workspace *get_first_workspace_for_screen(Output *screen);
|
||||
|
||||
/**
|
||||
* Unmaps all clients (and stack windows) of the given workspace.
|
||||
|
@ -1,62 +0,0 @@
|
||||
/*
|
||||
* vim:ts=8:expandtab
|
||||
*
|
||||
* i3 - an improved dynamic tiling window manager
|
||||
*
|
||||
* (c) 2009 Michael Stapelberg and contributors
|
||||
*
|
||||
* See file LICENSE for license information.
|
||||
*
|
||||
*/
|
||||
#include "data.h"
|
||||
|
||||
#ifndef _XINERAMA_H
|
||||
#define _XINERAMA_H
|
||||
|
||||
TAILQ_HEAD(screens_head, Screen);
|
||||
extern struct screens_head *virtual_screens;
|
||||
|
||||
/**
|
||||
* Returns true if both screen objects describe the same screen (checks their
|
||||
* size and position).
|
||||
*
|
||||
*/
|
||||
bool screens_are_equal(i3Screen *screen1, i3Screen *screen2);
|
||||
|
||||
/**
|
||||
* We have just established a connection to the X server and need the initial
|
||||
* Xinerama information to setup workspaces for each screen.
|
||||
*
|
||||
*/
|
||||
void initialize_xinerama(xcb_connection_t *conn);
|
||||
|
||||
/**
|
||||
* This is called when the rootwindow receives a configure_notify event and
|
||||
* therefore the number/position of the Xinerama screens could have changed.
|
||||
*
|
||||
*/
|
||||
void xinerama_requery_screens(xcb_connection_t *conn);
|
||||
|
||||
/**
|
||||
* Looks in virtual_screens for the i3Screen whose start coordinates are x, y
|
||||
*
|
||||
*/
|
||||
i3Screen *get_screen_at(int x, int y, struct screens_head *screenlist);
|
||||
|
||||
/**
|
||||
* Looks in virtual_screens for the i3Screen which contains coordinates x, y
|
||||
*
|
||||
*/
|
||||
i3Screen *get_screen_containing(int x, int y);
|
||||
|
||||
/**
|
||||
* 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 *current);
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user