Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] Abstract wm #90

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 4 additions & 37 deletions src/alttab.c
Original file line number Diff line number Diff line change
@@ -95,10 +95,6 @@ static int use_args_and_xrm(int *argc, char **argv)
char *rm;
char *empty = "";
int uo;
Atom nwm_prop, atype;
unsigned char *nwm;
int form;
unsigned long remain, len;
XrmOptionDescRec xrmTable[] = {
{"-w", "*windowmanager", XrmoptionSepArg, NULL},
{"-d", "*desktops", XrmoptionSepArg, NULL},
@@ -169,43 +165,20 @@ static int use_args_and_xrm(int *argc, char **argv)

switch (xresource_load_int(&db, XRMAPPNAME, "windowmanager", &wmindex)) {
case 1:
if (wmindex >= WM_MIN && wmindex <= WM_MAX) {
g.option_wm = wmindex;
goto wmDone;
} else {
if (wmindex < WM_MIN || wmindex > WM_MAX) {
die(inv, "windowmanager argument range");
}
break;
case 0:
msg(0, "no WM index or unknown, guessing\n");
wmindex = WM_GUESS;
break;
case -1:
die(inv, "windowmanager argument");
break;
}
// EWMH?
if (ewmh_detectFeatures(&(g.ewmh))) {
msg(0, "EWMH-compatible WM detected: %s\n", g.ewmh.wmname);
g.option_wm = WM_EWMH;
goto wmDone;
}
// ratpoison?
nwm_prop = XInternAtom(dpy, "_NET_WM_NAME", false);
if (XGetWindowProperty(dpy, root, nwm_prop, 0, MAXNAMESZ, false,
AnyPropertyType, &atype, &form, &len, &remain,
&nwm) == Success && nwm) {
msg(0, "_NET_WM_NAME root property present: %s\n", nwm);
if (strstr((char *)nwm, "ratpoison") != NULL) {
g.option_wm = WM_RATPOISON;
XFree(nwm);
goto wmDone;
}
XFree(nwm);
}
msg(0, "unknown WM, using WM_TWM\n");
g.option_wm = WM_TWM;
wmDone:
msg(0, "WM: %d\n", g.option_wm);

initWin(wmindex);

switch (xresource_load_int(&db, XRMAPPNAME, "desktops", &dsindex)) {
case 1:
@@ -430,12 +403,6 @@ static int use_args_and_xrm(int *argc, char **argv)
g.option_font = DEFFONT + 4;
}

// max recursion for searching windows
// -1 is "everything"
// in raw X this returns too much windows, "1" is probably sufficient
// no need for an option
g.option_max_reclevel = (g.option_wm == WM_NO) ? 1 : -1;

return 1;
}

45 changes: 25 additions & 20 deletions src/alttab.h
Original file line number Diff line number Diff line change
@@ -58,6 +58,14 @@ along with alttab. If not, see <http://www.gnu.org/licenses/>.
#define DEFPREVKEYKS XK_VoidSymbol
#define DEFNEXTKEYKS XK_VoidSymbol

#define WM_MIN 0
#define WM_NO 0
#define WM_EWMH 1
#define WM_RATPOISON 2
#define WM_TWM 3
#define WM_MAX 3
#define WM_GUESS -1

#include "icon.h"

#ifndef COMTYPES
@@ -107,6 +115,22 @@ typedef struct PermanentWindowInfo {
struct PermanentWindowInfo *next, *prev;
} PermanentWindowInfo;

struct WmOps {
bool (*probe)(void);
int (*startup)(void);
int (*winlist)(void);
int (*setFocus)(int idx);
Window (*getActiveWindow)(void);
bool (*skipWindowInTaskbar)(Window w);
bool (*skipFocusChangeEvent)(void);
long (*eventMask)(Window w);
};

extern struct WmOps WmNoOps;
extern struct WmOps WmEwmhOps;
extern struct WmOps WmRatpoisonOps;
extern struct WmOps WmTwmOps;

/*
typedef struct SwitchMoment {
Window prev;
@@ -126,14 +150,6 @@ typedef struct {
* unlike g.winlist, survives uiHide */
PermanentWindowInfo *sortlist;
// option_* are initialized from command line arguments or X resources or defaults
int option_max_reclevel; // max reclevel. -1 is "everything"
#define WM_MIN 0
#define WM_NO 0
#define WM_EWMH 1
#define WM_RATPOISON 2
#define WM_TWM 3
#define WM_MAX 3
int option_wm;
#define DESK_MIN 0
#define DESK_CURRENT 0
#define DESK_ALL 1
@@ -200,6 +216,7 @@ Window getUiwin();
void shutdownGUI(void);

// windows
void initWin(int wmindex);
int startupWintasks();
int addIconFromProperty(WindowInfo * wi);
int addIconFromHints(WindowInfo * wi);
@@ -209,30 +226,18 @@ int addWindowInfo(Window win, int reclevel, int wm_id, unsigned long desktop,
int initWinlist(void);
void freeWinlist();
int setFocus(int winNdx);
int rp_startupWintasks();
int x_initWindowsInfoRecursive(Window win, int reclevel);
int rp_initWinlist();
int x_setFocus(int wndx);
int rp_setFocus(int winNdx);
int execAndReadStdout(char *exe, char *args[], char *buf, int bufsize);
int pulloutWindowToTop(int winNdx);
void winPropChangeEvent(XPropertyEvent e);
void winDestroyEvent(XDestroyWindowEvent e);
void winFocusChangeEvent(XFocusChangeEvent e);
bool common_skipWindow(Window w, unsigned long current_desktop,
unsigned long window_desktop);
void x_setCommonPropertiesForAnyWindow(Window win);
void addToSortlist(Window w, bool to_head, bool move);
void shutdownWin(void);

/* EWHM */
bool ewmh_detectFeatures(EwmhFeatures * e);
Window ewmh_getActiveWindow();
int ewmh_initWinlist();
int ewmh_setFocus(int winNdx, Window fwin); // fwin used if non-zero
unsigned long ewmh_getCurrentDesktop();
unsigned long ewmh_getDesktopOfWindow(Window w);
bool ewmh_skipWindowInTaskbar(Window w);

/* RANDR */
bool randrAvailable();
124 changes: 94 additions & 30 deletions src/ewmh.c
Original file line number Diff line number Diff line change
@@ -36,6 +36,9 @@ extern int scr;
extern Window root;

// PRIVATE
static unsigned long ewmh_getCurrentDesktop();
static unsigned long ewmh_getDesktopOfWindow(Window w);
static bool ewmh_skipWindowInTaskbar(Window w);

//
// returns ptr to EWMH client list and client_list_size
@@ -116,13 +119,11 @@ static int ewmh_switch_window(unsigned long window)
return ewmh_send_wm_evt(window, "_NET_ACTIVE_WINDOW", edata);
}

// PUBLIC

//
// initialize EwmhFeatures
// return true if usable at all
//
bool ewmh_detectFeatures(EwmhFeatures * e)
static bool ewmh_detectFeatures(EwmhFeatures * e)
{
Window *chld_win;
char *r;
@@ -178,7 +179,7 @@ bool ewmh_detectFeatures(EwmhFeatures * e)
//
// active window or 0
//
Window ewmh_getActiveWindow()
static Window ewmh_getActiveWindow()
{
Window w = (Window) 0;
char *awp;
@@ -196,7 +197,7 @@ Window ewmh_getActiveWindow()
// initialize winlist, correcting sortlist
// return 1 if ok
//
int ewmh_initWinlist()
static int ewmh_initWinlist()
{
Window *client_list;
unsigned long client_list_size;
@@ -254,28 +255,6 @@ int ewmh_initWinlist()
return 1;
}

//
// focus window in EWMH WM
// fwin used if non-zero, winNdx otherwise
//
int ewmh_setFocus(int winNdx, Window fwin)
{
Window win = (fwin != 0) ? fwin : g.winlist[winNdx].id;
msg(1, "ewmh_setFocus win 0x%lx\n", win);
if (fwin == 0 && g.option_desktop != DESK_CURRENT) {
unsigned long wdesk = g.winlist[winNdx].desktop;
unsigned long cdesk = ewmh_getCurrentDesktop();
msg(1, "ewmh_setFocus fwin 0x%lx opt %d wdesk %lu cdesk %lu\n",
fwin, g.option_desktop, wdesk, cdesk);
if (cdesk != wdesk && wdesk != DESKTOP_UNKNOWN) {
ewmh_switch_desktop(wdesk);
}
}
ewmh_switch_window(win);
XMapRaised(dpy, win);
return 1;
}

static unsigned long ewmh_getDesktopFromProp(Window w, char *prop1, char *prop2)
{
unsigned long *d;
@@ -295,23 +274,23 @@ static unsigned long ewmh_getDesktopFromProp(Window w, char *prop1, char *prop2)
//
// get current desktop in EWMH WM
//
unsigned long ewmh_getCurrentDesktop()
static unsigned long ewmh_getCurrentDesktop()
{
return ewmh_getDesktopFromProp(root, "_NET_CURRENT_DESKTOP", "_WIN_WORKSPACE");
}

//
// get desktop of window w in EWMH WM
//
unsigned long ewmh_getDesktopOfWindow(Window w)
static unsigned long ewmh_getDesktopOfWindow(Window w)
{
return ewmh_getDesktopFromProp(w, "_NET_WM_DESKTOP", "_WIN_WORKSPACE");
}

//
// does window have _NET_WM_STATE_SKIP_TASKBAR
//
bool ewmh_skipWindowInTaskbar(Window w)
static bool ewmh_skipWindowInTaskbar(Window w)
{
Atom *state;
long unsigned int state_propsize;
@@ -338,3 +317,88 @@ bool ewmh_skipWindowInTaskbar(Window w)
free(state);
return ret;
}

static bool ewmhProbe(void)
{
return ewmh_detectFeatures(&g.ewmh);
}

static int ewmhStartup(void)
{
long rootevmask = 0;

// root: watching for _NET_ACTIVE_WINDOW
g.naw = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", true);
rootevmask |= PropertyChangeMask;

// warning: this overwrites any previous value.
// note: x_setCommonPropertiesForAnyWindow does the similar thing
// for any window other than root and uiwin
XSelectInput(dpy, root, rootevmask);

return 1;
}

static int ewmhSetFocus(int winNdx)
{
int r;
XWindowAttributes att;

r = ewmh_setFocus(winNdx, 0);
// XSetInputFocus stuff.
// skippy-xd does it and notes that "order is important".
// fixes #28.
// it must be protected by testing IsViewable in the same way
// as in x.c, or BadMatch happens after switching desktops.
XGetWindowAttributes(dpy, g.winlist[winNdx].id, &att);
if (att.map_state == IsViewable)
XSetInputFocus(dpy, g.winlist[winNdx].id, RevertToParent,
CurrentTime);
return r;
}

static bool ewmhSkipFocusChangeEvent(void)
{
return true;
}

static long ewmhEventMask(Window w)
{
msg(0, "using direct focus tracking for 0x%lx\n", w);
return FocusChangeMask;
}

// PUBLIC

//
// focus window in EWMH WM
// fwin used if non-zero, winNdx otherwise
//
int ewmh_setFocus(int winNdx, Window fwin)
{
Window win = (fwin != 0) ? fwin : g.winlist[winNdx].id;
msg(1, "ewmh_setFocus win 0x%lx\n", win);
if (fwin == 0 && g.option_desktop != DESK_CURRENT) {
unsigned long wdesk = g.winlist[winNdx].desktop;
unsigned long cdesk = ewmh_getCurrentDesktop();
msg(1, "ewmh_setFocus fwin 0x%lx opt %d wdesk %lu cdesk %lu\n",
fwin, g.option_desktop, wdesk, cdesk);
if (cdesk != wdesk && wdesk != DESKTOP_UNKNOWN) {
ewmh_switch_desktop(wdesk);
}
}
ewmh_switch_window(win);
XMapRaised(dpy, win);
return 1;
}

struct WmOps WmEwmhOps = {
.probe = ewmhProbe,
.startup = ewmhStartup,
.winlist = ewmh_initWinlist,
.setFocus = ewmhSetFocus,
.getActiveWindow = ewmh_getActiveWindow,
.skipWindowInTaskbar = ewmh_skipWindowInTaskbar,
.skipFocusChangeEvent = ewmhSkipFocusChangeEvent,
.eventMask = ewmhEventMask,
};
Loading