diff --git a/src/alttab.c b/src/alttab.c
index 504a769..902097e 100644
--- a/src/alttab.c
+++ b/src/alttab.c
@@ -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;
}
diff --git a/src/alttab.h b/src/alttab.h
index a09c821..06139a4 100644
--- a/src/alttab.h
+++ b/src/alttab.h
@@ -58,6 +58,14 @@ along with alttab. If not, see .
#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,11 +226,6 @@ 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);
@@ -221,18 +233,11 @@ 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();
diff --git a/src/ewmh.c b/src/ewmh.c
index 6dffe13..4c036eb 100644
--- a/src/ewmh.c
+++ b/src/ewmh.c
@@ -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,7 +274,7 @@ 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");
}
@@ -303,7 +282,7 @@ unsigned long ewmh_getCurrentDesktop()
//
// 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");
}
@@ -311,7 +290,7 @@ unsigned long ewmh_getDesktopOfWindow(Window w)
//
// 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,
+};
diff --git a/src/rp.c b/src/rp.c
index 1a0cfa9..f7ebc52 100644
--- a/src/rp.c
+++ b/src/rp.c
@@ -30,6 +30,8 @@ along with alttab. If not, see .
#include "alttab.h"
#include "util.h"
extern Globals g;
+extern Display *dpy;
+extern Window root;
// PRIVATE
@@ -99,12 +101,10 @@ static int rp_add_windows_in_group(int current_group, int window_group)
return 1;
}
-// PUBLIC
-
//
// early initialization in ratpoison
//
-int rp_startupWintasks()
+static int rp_startupWintasks()
{
// search for ratpoison executable for later execv
@@ -158,7 +158,7 @@ int rp_startupWintasks()
//
// initialize winlist/update sortlist from ratpoison output
//
-int rp_initWinlist()
+static int rp_initWinlist()
{
#define fallback { msg(-1, "using current rp group\n") ; \
return rp_add_windows_in_group(DESKTOP_UNKNOWN, DESKTOP_UNKNOWN); }
@@ -217,7 +217,7 @@ int rp_initWinlist()
//
// focus window in ratpoison
//
-int rp_setFocus(int winNdx)
+static int rp_setFocus(int winNdx)
{
char selarg[64];
char *args[] = { "ratpoison", "-c", selarg, NULL };
@@ -236,3 +236,49 @@ int rp_setFocus(int winNdx)
return 1;
}
+
+static bool ratpoisonProbe(void)
+{
+ unsigned long remain, len;
+ Atom nwm_prop, atype;
+ int form;
+ unsigned char *nwm;
+ bool ret = false;
+
+ 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)
+ return false;
+
+ msg(0, "_NET_WM_NAME root property present: %s\n", nwm);
+ if (strstr((char *)nwm, "ratpoison") != NULL)
+ ret = true;
+
+ XFree(nwm);
+ return ret;
+}
+
+static int ratpoisonStartup(void)
+{
+ return rp_startupWintasks();
+}
+
+static int ratpoisonWinlist(void)
+{
+ return rp_initWinlist();
+}
+
+static int ratpoisonSetFocus(int idx)
+{
+ return rp_setFocus(idx);
+}
+
+// PUBLIC
+
+struct WmOps WmRatpoisonOps = {
+ .probe = ratpoisonProbe,
+ .startup = ratpoisonStartup,
+ .winlist = ratpoisonWinlist,
+ .setFocus = ratpoisonSetFocus,
+};
diff --git a/src/win.c b/src/win.c
index 8f35bfa..4afb92c 100644
--- a/src/win.c
+++ b/src/win.c
@@ -38,6 +38,69 @@ extern Window root;
// PRIVATE
+static struct WmOps *WmOpsVariants[] = {
+ [WM_NO] = &WmNoOps,
+ [WM_EWMH] = &WmEwmhOps,
+ [WM_RATPOISON] = &WmRatpoisonOps,
+ [WM_TWM] = &WmTwmOps,
+};
+
+static struct WmOps *WmOps;
+
+static inline bool wmProbe(int wm)
+{
+ return (WmOpsVariants[wm]->probe != NULL) && (WmOpsVariants[wm]->probe());
+}
+
+static inline int wmStartup(void)
+{
+ if (WmOps->startup == NULL)
+ return 1;
+ return WmOps->startup();
+}
+
+static inline int wmInitWinlist(void)
+{
+ if (WmOps->winlist == NULL)
+ return 0;
+ return WmOps->winlist();
+}
+
+static inline int wmSetFocus(int idx)
+{
+ if (WmOps->setFocus == NULL)
+ return 0;
+ return WmOps->setFocus(idx);
+}
+
+static inline Window wmGetActiveWindow(void)
+{
+ if (WmOps->getActiveWindow == NULL)
+ return 0;
+ return WmOps->getActiveWindow();
+}
+
+static inline bool wmSkipWindowInTaskbar(Window w)
+{
+ if (WmOps->skipWindowInTaskbar == NULL)
+ return false;
+ return WmOps->skipWindowInTaskbar(w);
+}
+
+static inline bool wmSkipFocusChangeEvent(void)
+{
+ if (WmOps->skipFocusChangeEvent == NULL)
+ return false;
+ return WmOps->skipFocusChangeEvent();
+}
+
+static inline long wmEventMask(Window w)
+{
+ if (WmOps->eventMask == NULL)
+ return 0;
+ return WmOps->eventMask(w);
+}
+
//
// helper for windows' qsort
// CAUSES O(log(N)) OR EVEN WORSE! reintroduce winlist[]->order instead?
@@ -99,6 +162,26 @@ static void print_winlist()
}
}
+//
+// this is where alttab is supposed to set properties or
+// register interest in event for ANY foreign window encountered.
+// warning: this is called only on addition to sortlist.
+//
+static void winSetCommonPropertiesForAnyWindow(Window win)
+{
+ long evmask = 0;
+ // root and our window are treated elsewhere
+ if (win == root || win == getUiwin())
+ return;
+ // for delete notification
+ evmask |= StructureNotifyMask;
+ // for focusIn notification
+ evmask |= wmEventMask(win);
+ // warning: this overwrites previous value
+ if (evmask != 0)
+ XSelectInput(dpy, win, evmask);
+}
+
// PUBLIC
//
@@ -135,47 +218,53 @@ void addToSortlist(Window w, bool to_head, bool move)
if (add && !was) {
// new window
// register interest in events
- x_setCommonPropertiesForAnyWindow(w);
+ winSetCommonPropertiesForAnyWindow(w);
}
}
+//
+// wmindex is the already validated option
+void initWin(int wmindex)
+{
+ int wm;
+
+ if (wmindex != WM_GUESS) {
+ wm = wmindex;
+ goto out;
+ }
+
+ if (wmProbe(WM_EWMH)) {
+ msg(0, "EWMH-compatible WM detected: %s\n", g.ewmh.wmname);
+ wm = WM_EWMH;
+ goto out;
+ }
+
+ if (wmProbe(WM_RATPOISON)) {
+ wm = WM_RATPOISON;
+ goto out;
+ }
+
+ msg(0, "unknown WM, using WM_TWM\n");
+ wm = WM_TWM;
+
+out:
+ msg(0, "WM: %d\n", wm);
+ WmOps = WmOpsVariants[wm];
+}
+
//
// early initialization
// once per execution
//
int startupWintasks()
{
- long rootevmask = 0;
-
g.sortlist = NULL; // utlist head must be initialized to NULL
g.ic = NULL; // uthash too
if (g.option_iconSrc != ISRC_RAM) {
initIconHash(&(g.ic));
}
- // root: watching for _NET_ACTIVE_WINDOW
- if (g.option_wm == WM_EWMH) {
- 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
- if (rootevmask != 0) {
- XSelectInput(dpy, root, rootevmask);
- }
- switch (g.option_wm) {
- case WM_NO:
- return 1;
- case WM_RATPOISON:
- return rp_startupWintasks();
- case WM_EWMH:
- return 1;
- case WM_TWM:
- return 1;
- default:
- return 0;
- }
+ return wmStartup();
}
//
@@ -508,23 +597,8 @@ int initWinlist(void)
msg(1, "before initWinlist\n");
print_sortlist();
}
- switch (g.option_wm) {
- case WM_NO:
- r = x_initWindowsInfoRecursive(root, 0); // note: direction/current window index aren't used
- break;
- case WM_RATPOISON:
- r = rp_initWinlist();
- break;
- case WM_EWMH:
- r = ewmh_initWinlist();
- break;
- case WM_TWM:
- r = x_initWindowsInfoRecursive(root, 0);
- break;
- default:
- r = 0;
- break;
- }
+
+ r = wmInitWinlist();
if (!r)
__initWinlist();
@@ -571,34 +645,8 @@ void freeWinlist()
int setFocus(int winNdx)
{
int r;
- switch (g.option_wm) {
- case WM_NO:
- r = ewmh_setFocus(winNdx, 0); // for WM which isn't identified as EWMH compatible but accepts setting focus (dwm)
- x_setFocus(winNdx);
- break;
- case WM_RATPOISON:
- r = rp_setFocus(winNdx);
- break;
- case WM_EWMH:
- 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.
- XWindowAttributes att;
- XGetWindowAttributes(dpy, g.winlist[winNdx].id, &att);
- if (att.map_state == IsViewable)
- XSetInputFocus(dpy, g.winlist[winNdx].id, RevertToParent,
- CurrentTime);
- break;
- case WM_TWM:
- r = ewmh_setFocus(winNdx, 0);
- x_setFocus(winNdx);
- break;
- default:
- return 0;
- }
+
+ r = wmSetFocus(winNdx);
// pull to head
addToSortlist(g.winlist[winNdx].id, true, true);
return r;
@@ -625,7 +673,7 @@ void winPropChangeEvent(XPropertyEvent e)
if (e.atom != g.naw)
return;
// don't check for wm==EWMH, because _NET_ACTIVE_WINDOW changed for sure
- aw = ewmh_getActiveWindow();
+ aw = wmGetActiveWindow();
// can't get active window
if (!aw)
return;
@@ -636,7 +684,7 @@ void winPropChangeEvent(XPropertyEvent e)
if (g.sortlist != NULL && aw == g.sortlist->id)
return;
// is window hidden in WM?
- if (ewmh_skipWindowInTaskbar(aw))
+ if (wmSkipWindowInTaskbar(aw))
return;
/*
// the i3 sortlist bug is not here, see ewmh.c init_winlist instead
@@ -745,7 +793,7 @@ void winFocusChangeEvent(XFocusChangeEvent e)
// in non-EWMH only
// probably should also maintain _NET_ACTIVE_WINDOW
// support flag in EwmhFeatures
- if (g.option_wm == WM_EWMH)
+ if (wmSkipFocusChangeEvent())
return;
// focusIn only
if (e.type != FocusIn)
diff --git a/src/x.c b/src/x.c
index e59c6e6..6e0fe66 100644
--- a/src/x.c
+++ b/src/x.c
@@ -33,6 +33,13 @@ extern Window root;
// PRIVATE
+// 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
+static int max_reclevel;
+static int wm;
+
//
// get window group leader
// to be used later. rewritten, not tested.
@@ -57,13 +64,11 @@ Window x_get_leader(Window win)
return leader;
}
-// PUBLIC
-
//
// set winlist,maxNdx recursively using raw Xlib
// first call should be (win=root, reclevel=0)
//
-int x_initWindowsInfoRecursive(Window win, int reclevel)
+static int x_initWindowsInfoRecursive(Window win, int reclevel)
{
Window root, parent;
@@ -88,24 +93,24 @@ int x_initWindowsInfoRecursive(Window win, int reclevel)
// caveat: in rp, skips anything except of visible window
// probably add an option for this in WMs too?
wa.map_state = 0;
- if (g.option_wm != WM_TWM)
+ if (wm != WM_TWM)
XGetWindowAttributes(dpy, win, &wa);
// in twm-like, add only windows with a name
winname = NULL;
- if (g.option_wm == WM_TWM) {
+ if (wm == WM_TWM) {
winname = get_x_property(win, XA_STRING, "WM_NAME", NULL);
}
// insert detailed window data in window list
- if ((g.option_wm == WM_TWM || wa.map_state == IsViewable)
- && reclevel != 0 && (g.option_wm != WM_TWM || winname != NULL)
-// && (g.option_wm != WM_TWM || leader == win)
+ if ((wm == WM_TWM || wa.map_state == IsViewable)
+ && reclevel != 0 && (wm != WM_TWM || winname != NULL)
+// && (wm != WM_TWM || leader == win)
&& !common_skipWindow(win, DESKTOP_UNKNOWN, DESKTOP_UNKNOWN)
) {
addWindowInfo(win, reclevel, 0, DESKTOP_UNKNOWN, winname);
}
// skip children if max recursion level reached
- if (g.option_max_reclevel != -1 && reclevel >= g.option_max_reclevel)
+ if (max_reclevel != -1 && reclevel >= max_reclevel)
return 1;
// recursion
@@ -126,7 +131,7 @@ int x_initWindowsInfoRecursive(Window win, int reclevel)
//
// set window focus in raw X
//
-int x_setFocus(int wndx)
+static int x_setFocus(int wndx)
{
Window w = g.winlist[wndx].id;
@@ -149,25 +154,47 @@ int x_setFocus(int wndx)
return 1;
}
-//
-// this is where alttab is supposed to set properties or
-// register interest in event for ANY foreign window encountered.
-// warning: this is called only on addition to sortlist.
-//
-void x_setCommonPropertiesForAnyWindow(Window win)
+static int xSetFocus(int idx)
{
- long evmask = 0;
- // root and our window are treated elsewhere
- if (win == root || win == getUiwin())
- return;
- // for delete notification
- evmask |= StructureNotifyMask;
- // for focusIn notification
- if (g.option_wm != WM_EWMH) {
- msg(0, "using direct focus tracking for 0x%lx\n", win);
- evmask |= FocusChangeMask;
- }
- // warning: this overwrites previous value
- if (evmask != 0)
- XSelectInput(dpy, win, evmask);
+ int r;
+
+ // for WM which isn't identified as EWMH compatible
+ // but accepts setting focus (dwm)
+ r = ewmh_setFocus(idx, 0);
+ x_setFocus(idx);
+
+ return r;
}
+
+static int xStartup(void)
+{
+ wm = WM_NO;
+ max_reclevel = 1;
+ return 1;
+}
+
+static int twmStartup(void)
+{
+ wm = WM_TWM;
+ max_reclevel = -1;
+ return 1;
+}
+
+static int xWinlist(void)
+{
+ return x_initWindowsInfoRecursive(root, 0);
+}
+
+// PUBLIC
+
+struct WmOps WmNoOps = {
+ .startup = xStartup,
+ .winlist = xWinlist,
+ .setFocus = xSetFocus,
+};
+
+struct WmOps WmTwmOps = {
+ .startup = twmStartup,
+ .winlist = xWinlist,
+ .setFocus = xSetFocus,
+};