As promised here are various patches against git next. The content
is the same as I've posted before modulo a few tweaks.
Patch 1 ensures that the workspace name which pops up when changing
workspaces does not end up illegible in the middle of two Xinerama heads.
Patch 2 adds extra padding to the aforementioned workspace name so
it's easier to read.
Patch 3 allows wmsetbg to stretch an image across all Xinerama heads.
Patch 4 implements Mac-style window cycling by populating the
switch panel with only windows matching the current window's WM_CLASS
when the GroupNext or GroupPrev shortcuts are used.
>From 5a122d05464f8f8b6e3cd7d6500dda808142e0ae Mon Sep 17 00:00:00 2001
From: Iain Patterson <[email protected]>
Date: Mon, 14 Sep 2009 12:59:10 +0100
Subject: [PATCH 1/4] Constrain switching workspace name to one head.
When switching workspaces, force the name to be shown entirely within
one head of a Xinerama display. Previously the name would span heads if
set to TOP, CENTER or BOTTOM alignment, and was hence hard to read when
the display comprised an even number of heads.
---
src/workspace.c | 31 +++++++++++++++++++++++++++++++
1 files changed, 31 insertions(+), 0 deletions(-)
diff --git a/src/workspace.c b/src/workspace.c
index 2114ff4..277f746 100644
--- a/src/workspace.c
+++ b/src/workspace.c
@@ -262,6 +262,11 @@ static void showWorkspaceName(WScreen * scr, int workspace)
char *name = scr->workspaces[workspace]->name;
int len = strlen(name);
int x, y;
+#ifdef XINERAMA
+ int head;
+ WMRect rect;
+ int xx, yy;
+#endif
if (wPreferences.workspace_name_display_position == WD_NONE ||
scr->workspace_count < 2) {
return;
@@ -286,13 +291,34 @@ static void showWorkspaceName(WScreen * scr, int
workspace)
w = WMWidthOfString(scr->workspace_name_font, name, len);
h = WMFontHeight(scr->workspace_name_font);
+#ifdef XINERAMA
+ head = wGetHeadForPointerLocation(scr);
+ rect = wGetRectForHead(scr, head);
+ if (scr->xine_info.count) {
+ xx = rect.pos.x + (scr->xine_info.screens[head].size.width -
(w+4))/2;
+ yy = rect.pos.y + (scr->xine_info.screens[head].size.height -
(h+4))/2;
+ }
+ else {
+ xx = (scr->scr_width - (w+4))/2;
+ yy = (scr->scr_height - (h+4))/2;
+ }
+#endif
+
switch (wPreferences.workspace_name_display_position) {
case WD_TOP:
+#ifdef XINERAMA
+ px = xx;
+#else
px = (scr->scr_width - (w + 4)) / 2;
+#endif
py = 0;
break;
case WD_BOTTOM:
+#ifdef XINERAMA
+ px = xx;
+#else
px = (scr->scr_width - (w + 4)) / 2;
+#endif
py = scr->scr_height - (h + 4);
break;
case WD_TOPLEFT:
@@ -313,8 +339,13 @@ static void showWorkspaceName(WScreen * scr, int workspace)
break;
case WD_CENTER:
default:
+#ifdef XINERAMA
+ px = xx;
+ py = yy;
+#else
px = (scr->scr_width - (w + 4)) / 2;
py = (scr->scr_height - (h + 4)) / 2;
+#endif
break;
}
XResizeWindow(dpy, scr->workspace_name, w + 4, h + 4);
--
1.6.3.1
>From 937d234509672b943b4d89fedc3ad34cb6aa62cc Mon Sep 17 00:00:00 2001
From: Iain Patterson <[email protected]>
Date: Mon, 14 Sep 2009 13:28:37 +0100
Subject: [PATCH 2/4] Pad workspace name display.
Shift the workspace name, shown when switching workspaces, by 32
pixels. This is purely for aesthetic reasons. It just looks better
(IMO) than having the name flush against the screen edge.
---
src/workspace.c | 29 +++++++++++++++--------------
1 files changed, 15 insertions(+), 14 deletions(-)
diff --git a/src/workspace.c b/src/workspace.c
index 277f746..af0f544 100644
--- a/src/workspace.c
+++ b/src/workspace.c
@@ -55,6 +55,7 @@
#include "xinerama.h"
#define MAX_SHORTCUT_LENGTH 32
+#define WORKSPACE_NAME_DISPLAY_PADDING 32
extern WPreferences wPreferences;
extern XContext wWinContext;
@@ -295,12 +296,12 @@ static void showWorkspaceName(WScreen * scr, int
workspace)
head = wGetHeadForPointerLocation(scr);
rect = wGetRectForHead(scr, head);
if (scr->xine_info.count) {
- xx = rect.pos.x + (scr->xine_info.screens[head].size.width -
(w+4))/2;
- yy = rect.pos.y + (scr->xine_info.screens[head].size.height -
(h+4))/2;
+ xx = rect.pos.x + (scr->xine_info.screens[head].size.width - (w
+ 4)) / 2;
+ yy = rect.pos.y + (scr->xine_info.screens[head].size.height -
(h + 4)) / 2;
}
else {
- xx = (scr->scr_width - (w+4))/2;
- yy = (scr->scr_height - (h+4))/2;
+ xx = (scr->scr_width - (w + 4)) / 2;
+ yy = (scr->scr_height - (h + 4)) / 2;
}
#endif
@@ -311,7 +312,7 @@ static void showWorkspaceName(WScreen * scr, int workspace)
#else
px = (scr->scr_width - (w + 4)) / 2;
#endif
- py = 0;
+ py = WORKSPACE_NAME_DISPLAY_PADDING;
break;
case WD_BOTTOM:
#ifdef XINERAMA
@@ -319,23 +320,23 @@ static void showWorkspaceName(WScreen * scr, int
workspace)
#else
px = (scr->scr_width - (w + 4)) / 2;
#endif
- py = scr->scr_height - (h + 4);
+ py = scr->scr_height - (h + 4 + WORKSPACE_NAME_DISPLAY_PADDING);
break;
case WD_TOPLEFT:
- px = 0;
- py = 0;
+ px = WORKSPACE_NAME_DISPLAY_PADDING;
+ py = WORKSPACE_NAME_DISPLAY_PADDING;
break;
case WD_TOPRIGHT:
- px = scr->scr_width - (w + 4);
- py = 0;
+ px = scr->scr_width - (w + 4 + WORKSPACE_NAME_DISPLAY_PADDING);
+ py = WORKSPACE_NAME_DISPLAY_PADDING;
break;
case WD_BOTTOMLEFT:
- px = 0;
- py = scr->scr_height - (h + 4);
+ px = WORKSPACE_NAME_DISPLAY_PADDING;
+ py = scr->scr_height - (h + 4 + WORKSPACE_NAME_DISPLAY_PADDING);
break;
case WD_BOTTOMRIGHT:
- px = scr->scr_width - (w + 4);
- py = scr->scr_height - (h + 4);
+ px = scr->scr_width - (w + 4 + WORKSPACE_NAME_DISPLAY_PADDING);
+ py = scr->scr_height - (h + 4 + WORKSPACE_NAME_DISPLAY_PADDING);
break;
case WD_CENTER:
default:
--
1.6.3.1
>From 736b55d77c82cf0860f20a01e5857b89c5887d2a Mon Sep 17 00:00:00 2001
From: Iain Patterson <[email protected]>
Date: Mon, 14 Sep 2009 14:13:58 +0100
Subject: [PATCH 3/4] Support Xinerama in wmsetbg.
Allow wmsetbg to revert to pre-0.90.0 behaviour when choosing a
background image that is large enough to span several heads in a
Xinerama setup. If the -X flag is passed to wmsetbg, the background
image will be stretched to fill the logical screen (as it would be by
default in older versions of wmsetbg) instead of being tiled across
screens.
---
util/wmsetbg.c | 12 +++++++++++-
1 files changed, 11 insertions(+), 1 deletions(-)
diff --git a/util/wmsetbg.c b/util/wmsetbg.c
index d5328bc..96e14b5 100644
--- a/util/wmsetbg.c
+++ b/util/wmsetbg.c
@@ -80,6 +80,9 @@ int scrX, scrY;
WXineramaInfo xineInfo;
Bool smooth = False;
+#ifdef XINERAMA
+Bool xineStretch = False;
+#endif
Pixmap CurrentPixmap = None;
char *PixmapPath = NULL;
@@ -543,7 +546,7 @@ BackgroundTexture *parseTexture(RContext * rc, char *text)
texture->height = scrHeight;
#ifdef XINERAMA
- if (xineInfo.count) {
+ if (xineInfo.count && ! xineStretch) {
int i;
for (i = 0; i < xineInfo.count; ++i) {
applyImage(rc, texture, image,
type[0],
@@ -1214,6 +1217,9 @@ void print_help(char *ProgName)
P(" -d, --dither dither image");
P(" -m, --match match colors");
P(" -S, --smooth smooth scaled image");
+#ifdef XINERAMA
+ P(" -X, --xinerama stretch image across Xinerama
heads");
+#endif
P(" -b, --back-color <color> background color");
P(" -t, --tile tile image");
P(" -e, --center center image");
@@ -1319,6 +1325,10 @@ int main(int argc, char **argv)
obey_user++;
} else if (strcmp(argv[i], "-S") == 0 || strcmp(argv[i],
"--smooth") == 0) {
smooth = True;
+#ifdef XINERAMA
+ } else if (strcmp(argv[i], "-X") == 0 || strcmp(argv[i],
"--xinerama") == 0) {
+ xineStretch = True;
+#endif
} else if (strcmp(argv[i], "-u") == 0 || strcmp(argv[i],
"--update-wmaker") == 0) {
update++;
} else if (strcmp(argv[i], "-D") == 0 || strcmp(argv[i],
"--update-domain") == 0) {
--
1.6.3.1
>From 88fac09ad38e91fc2534f85d2206dc11f68b5b96 Mon Sep 17 00:00:00 2001
From: Iain Patterson <[email protected]>
Date: Mon, 14 Sep 2009 14:37:15 +0100
Subject: [PATCH 4/4] Mac OS X-style window cycling.
For those not familiar with the way Macs cycle windows, the Command-Tab
sequence (Alt-Tab elsewhere) switches between DIFFERENT application windows
and Command-Grave (key above tab) switches between windows owned by the
SAME application as is currently focused. So if you had three Safari and
two Finder windows open, and Safari had focus, Command-Tab would switch to
Finder; Command-Tab would switch back to Safari; Command-Grave would switch
to a different Safari window etc.
This patch implements "something like" the above by only populating the
switchpanel with windows matching the currently-focused WWindow's wm_class
when the new cycling mode is activated. In practice this means you can
switch to The Next XTerm or The Next Firefox Window using this method.
The configuration names for these new shortcuts are GroupNext and
GroupPrev. The patch tells WPrefs.app about them. Of course switching to
The Next Window is still possible with the (unchanged) FocusNext and
FocusPrev keys.
---
WPrefs.app/KeyboardShortcuts.c | 4 ++++
src/cycling.c | 12 +++++++++---
src/defaults.c | 4 ++++
src/event.c | 12 ++++++++++--
src/funcs.h | 2 +-
src/keybind.h | 2 ++
src/switchpanel.c | 18 +++++++++++++++---
src/switchpanel.h | 2 +-
8 files changed, 46 insertions(+), 10 deletions(-)
diff --git a/WPrefs.app/KeyboardShortcuts.c b/WPrefs.app/KeyboardShortcuts.c
index 919d73b..ff41c7f 100644
--- a/WPrefs.app/KeyboardShortcuts.c
+++ b/WPrefs.app/KeyboardShortcuts.c
@@ -82,6 +82,8 @@ static char *keyOptions[] = {
"SelectKey",
"FocusNextKey",
"FocusPrevKey",
+ "GroupNextKey",
+ "GroupPrevKey",
"NextWorkspaceKey",
"PrevWorkspaceKey",
"NextWorkspaceLayerKey",
@@ -485,6 +487,8 @@ static void createPanel(Panel * p)
WMAddListItem(panel->actLs, _("Select active window"));
WMAddListItem(panel->actLs, _("Focus next window"));
WMAddListItem(panel->actLs, _("Focus previous window"));
+ WMAddListItem(panel->actLs, _("Focus next group window"));
+ WMAddListItem(panel->actLs, _("Focus previous group window"));
WMAddListItem(panel->actLs, _("Switch to next workspace"));
WMAddListItem(panel->actLs, _("Switch to previous workspace"));
WMAddListItem(panel->actLs, _("Switch to next ten workspaces"));
diff --git a/src/cycling.c b/src/cycling.c
index 2510d2f..c064f1d 100644
--- a/src/cycling.c
+++ b/src/cycling.c
@@ -81,7 +81,7 @@ static WWindow *change_focus_and_raise(WWindow *newFocused,
WWindow *oldFocused,
return oldFocused;
}
-void StartWindozeCycle(WWindow * wwin, XEvent * event, Bool next)
+void StartWindozeCycle(WWindow * wwin, XEvent * event, Bool next, Bool
class_only)
{
XModifierKeymap *keymap = NULL;
@@ -123,7 +123,7 @@ void StartWindozeCycle(WWindow * wwin, XEvent * event, Bool
next)
scr->flags.doing_alt_tab = 1;
- swpanel = wInitSwitchPanel(scr, wwin, scr->current_workspace);
+ swpanel = wInitSwitchPanel(scr, wwin, scr->current_workspace,
class_only);
oldFocused = wwin;
if (swpanel) {
@@ -159,6 +159,8 @@ void StartWindozeCycle(WWindow * wwin, XEvent * event, Bool
next)
if ((wKeyBindings[WKBD_FOCUSNEXT].keycode ==
ev.xkey.keycode
&& wKeyBindings[WKBD_FOCUSNEXT].modifier ==
modifiers)
+ || (wKeyBindings[WKBD_GROUPNEXT].keycode ==
ev.xkey.keycode
+ && wKeyBindings[WKBD_GROUPNEXT].modifier ==
modifiers)
|| ev.xkey.keycode == rightKey) {
newFocused = wSwitchPanelSelectNext(swpanel,
False);
@@ -166,6 +168,8 @@ void StartWindozeCycle(WWindow * wwin, XEvent * event, Bool
next)
} else if ((wKeyBindings[WKBD_FOCUSPREV].keycode ==
ev.xkey.keycode
&& wKeyBindings[WKBD_FOCUSPREV].modifier ==
modifiers)
+ || (wKeyBindings[WKBD_GROUPPREV].keycode ==
ev.xkey.keycode
+ && wKeyBindings[WKBD_GROUPPREV].modifier ==
modifiers)
|| ev.xkey.keycode == leftKey) {
newFocused = wSwitchPanelSelectNext(swpanel,
True);
@@ -199,7 +203,9 @@ void StartWindozeCycle(WWindow * wwin, XEvent * event, Bool
next)
if (keymap->modifiermap[i] == ev.xkey.keycode &&
((wKeyBindings[WKBD_FOCUSNEXT].modifier &
mask)
- || (wKeyBindings[WKBD_FOCUSPREV].modifier
& mask))) {
+ || (wKeyBindings[WKBD_FOCUSPREV].modifier
& mask)
+ || (wKeyBindings[WKBD_GROUPNEXT].modifier
& mask)
+ || (wKeyBindings[WKBD_GROUPPREV].modifier
& mask))) {
done = True;
break;
}
diff --git a/src/defaults.c b/src/defaults.c
index 61756b0..555bdac 100644
--- a/src/defaults.c
+++ b/src/defaults.c
@@ -601,6 +601,10 @@ WDefaultEntry optionList[] = {
NULL, getKeybind, setKeyGrab},
{"FocusPrevKey", "None", (void *)WKBD_FOCUSPREV,
NULL, getKeybind, setKeyGrab},
+ {"GroupNextKey", "None", (void *)WKBD_GROUPNEXT,
+ NULL, getKeybind, setKeyGrab},
+ {"GroupPrevKey", "None", (void *)WKBD_GROUPPREV,
+ NULL, getKeybind, setKeyGrab},
{"NextWorkspaceKey", "None", (void *)WKBD_NEXTWORKSPACE,
NULL, getKeybind, setKeyGrab},
{"PrevWorkspaceKey", "None", (void *)WKBD_PREVWORKSPACE,
diff --git a/src/event.c b/src/event.c
index 023e896..71720b6 100644
--- a/src/event.c
+++ b/src/event.c
@@ -1542,11 +1542,19 @@ static void handleKeyPress(XEvent * event)
}
break;
case WKBD_FOCUSNEXT:
- StartWindozeCycle(wwin, event, True);
+ StartWindozeCycle(wwin, event, True, False);
break;
case WKBD_FOCUSPREV:
- StartWindozeCycle(wwin, event, False);
+ StartWindozeCycle(wwin, event, False, False);
+ break;
+
+ case WKBD_GROUPNEXT:
+ StartWindozeCycle(wwin, event, True, True);
+ break;
+
+ case WKBD_GROUPPREV:
+ StartWindozeCycle(wwin, event, False, True);
break;
case WKBD_WORKSPACE1 ... WKBD_WORKSPACE10:
diff --git a/src/funcs.h b/src/funcs.h
index c900976..f49536e 100644
--- a/src/funcs.h
+++ b/src/funcs.h
@@ -85,7 +85,7 @@ void PlaceWindow(WWindow *wwin, int *x_ret, int *y_ret,
unsigned int width, unsigned int height);
-void StartWindozeCycle(WWindow *wwin, XEvent *event, Bool next);
+void StartWindozeCycle(WWindow *wwin, XEvent *event, Bool next, Bool
class_only);
#ifdef USECPP
char *MakeCPPArgs(char *path);
diff --git a/src/keybind.h b/src/keybind.h
index 995e7a7..2daca8d 100644
--- a/src/keybind.h
+++ b/src/keybind.h
@@ -44,6 +44,8 @@ enum {
WKBD_SHADE,
WKBD_FOCUSNEXT,
WKBD_FOCUSPREV,
+ WKBD_GROUPNEXT,
+ WKBD_GROUPPREV,
/* window, menu */
WKBD_CLOSE,
diff --git a/src/switchpanel.c b/src/switchpanel.c
index 3e1ae15..41cb1ba 100644
--- a/src/switchpanel.c
+++ b/src/switchpanel.c
@@ -374,7 +374,7 @@ static void drawTitle(WSwitchPanel * panel, int idecks,
char *title)
free(ntitle);
}
-static WMArray *makeWindowListArray(WScreen * scr, WWindow * curwin, int
workspace, int include_unmapped)
+static WMArray *makeWindowListArray(WScreen * scr, WWindow * curwin, int
workspace, int include_unmapped, Bool class_only)
{
WMArray *windows = WMCreateArray(10);
int fl;
@@ -385,6 +385,12 @@ static WMArray *makeWindowListArray(WScreen * scr, WWindow
* curwin, int workspa
if (((!fl && canReceiveFocus(wwin) > 0) || (fl &&
canReceiveFocus(wwin) < 0)) &&
(!WFLAGP(wwin, skip_window_list) ||
wwin->flags.internal_window) &&
(wwin->flags.mapped || include_unmapped)) {
+ if (class_only) {
+ if (!wwin->wm_class || !curwin->wm_class)
+ continue;
+ if (strcmp(wwin->wm_class,
curwin->wm_class))
+ continue;
+ }
WMAddToArray(windows, wwin);
}
}
@@ -397,6 +403,12 @@ static WMArray *makeWindowListArray(WScreen * scr, WWindow
* curwin, int workspa
if (((!fl && canReceiveFocus(wwin) > 0) || (fl &&
canReceiveFocus(wwin) < 0)) &&
(!WFLAGP(wwin, skip_window_list) ||
wwin->flags.internal_window) &&
(wwin->flags.mapped || include_unmapped)) {
+ if (class_only) {
+ if (!wwin->wm_class || !curwin->wm_class)
+ continue;
+ if (strcmp(wwin->wm_class,
curwin->wm_class))
+ continue;
+ }
WMAddToArray(windows, wwin);
}
}
@@ -405,7 +417,7 @@ static WMArray *makeWindowListArray(WScreen * scr, WWindow
* curwin, int workspa
return windows;
}
-WSwitchPanel *wInitSwitchPanel(WScreen * scr, WWindow * curwin, int workspace)
+WSwitchPanel *wInitSwitchPanel(WScreen * scr, WWindow * curwin, int workspace,
Bool class_only)
{
WWindow *wwin;
WSwitchPanel *panel = wmalloc(sizeof(WSwitchPanel));
@@ -421,7 +433,7 @@ WSwitchPanel *wInitSwitchPanel(WScreen * scr, WWindow *
curwin, int workspace)
panel->scr = scr;
- panel->windows = makeWindowListArray(scr, curwin, workspace,
wPreferences.swtileImage != 0);
+ panel->windows = makeWindowListArray(scr, curwin, workspace,
wPreferences.swtileImage != 0, class_only);
count = WMGetArrayItemCount(panel->windows);
if (count == 0) {
diff --git a/src/switchpanel.h b/src/switchpanel.h
index 6a931b0..0ed1928 100644
--- a/src/switchpanel.h
+++ b/src/switchpanel.h
@@ -24,7 +24,7 @@
typedef struct SwitchPanel WSwitchPanel;
-WSwitchPanel *wInitSwitchPanel(WScreen *scr, WWindow *curwin, int workspace);
+WSwitchPanel *wInitSwitchPanel(WScreen *scr, WWindow *curwin, int workspace,
Bool class_only);
void wSwitchPanelDestroy(WSwitchPanel *panel);
--
1.6.3.1