summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Kasprzyk <onestone@opencompositing.org>2007-08-07 23:37:57 +0200
committerDennis Kasprzyk <onestone@opencompositing.org>2007-08-07 23:37:57 +0200
commit7794861cc28f9f38b1bade96f377fe9c99863fe5 (patch)
treed0f0c58d7fbe8641b347ed5c110786989b9c7e6e
parent5aa35cd356b790d6e17372416440a3e2adc5bcff (diff)
downloadworkarounds-7794861cc28f9f38b1bade96f377fe9c99863fe5.tar.gz
workarounds-7794861cc28f9f38b1bade96f377fe9c99863fe5.tar.bz2
Added handling of "on all desktops" windows as sticky.
-rw-r--r--workarounds.c124
-rw-r--r--workarounds.xml.in18
2 files changed, 142 insertions, 0 deletions
diff --git a/workarounds.c b/workarounds.c
index 5c43ec1..af00bf0 100644
--- a/workarounds.c
+++ b/workarounds.c
@@ -1,6 +1,8 @@
/*
* Copyright (C) 2007 Andrew Riedi <andrewriedi@gmail.com>
*
+ * Sticky window handling by Dennis Kasprzyk <onestone@opencompositing.org>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -30,13 +32,21 @@ static int displayPrivateIndex;
typedef struct _WorkaroundsDisplay {
int screenPrivateIndex;
+ HandleEventProc handleEvent;
+
Atom roleAtom;
} WorkaroundsDisplay;
typedef struct _WorkaroundsScreen {
+ int windowPrivateIndex;
+
WindowResizeNotifyProc windowResizeNotify;
} WorkaroundsScreen;
+typedef struct _WorkaroundsWindow {
+ Bool madeSticky;
+} WorkaroundsWindow;
+
#define GET_WORKAROUNDS_DISPLAY(d) \
((WorkaroundsDisplay *) (d)->privates[displayPrivateIndex].ptr)
@@ -50,6 +60,12 @@ typedef struct _WorkaroundsScreen {
WorkaroundsScreen *ws = GET_WORKAROUNDS_SCREEN (s, \
GET_WORKAROUNDS_DISPLAY (s->display))
+#define GET_WORKAROUNDS_WINDOW(w, ns) \
+ ((WorkaroundsWindow *) (w)->privates[(ns)->windowPrivateIndex].ptr)
+#define WORKAROUNDS_WINDOW(w) \
+ WorkaroundsWindow *ww = GET_WORKAROUNDS_WINDOW (w, \
+ GET_WORKAROUNDS_SCREEN (w->screen, \
+ GET_WORKAROUNDS_DISPLAY (w->screen->display)))
static char *
workaroundsGetWindowRoleAtom (CompWindow *w)
@@ -86,6 +102,44 @@ workaroundsGetWindowRoleAtom (CompWindow *w)
}
static void
+workaroundsRemoveSticky (CompWindow *w)
+{
+ WORKAROUNDS_WINDOW (w);
+
+ if (w->state & CompWindowStateStickyMask && ww->madeSticky)
+ changeWindowState (w, w->state & ~CompWindowStateStickyMask);
+ ww->madeSticky = FALSE;
+}
+
+static void
+workaroundsUpdateSticky (CompWindow *w)
+{
+ WORKAROUNDS_WINDOW (w);
+
+ CompDisplay *d = w->screen->display;
+ Bool makeSticky = FALSE;
+
+ if (workaroundsGetStickyAlldesktops (d) && w->desktop == 0xffffffff &&
+ matchEval (workaroundsGetAlldesktopStickyMatch (d), w))
+ makeSticky = TRUE;
+
+ if (matchEval (workaroundsGetStickyMatch (d), w))
+ makeSticky = TRUE;
+
+ if (makeSticky)
+ {
+ if (!(w->state & CompWindowStateStickyMask))
+ {
+ ww->madeSticky = TRUE;
+ changeWindowState (w, w->state | CompWindowStateStickyMask);
+ }
+ }
+ else
+ workaroundsRemoveSticky (w);
+
+}
+
+static void
workaroundsDoFixes (CompWindow *w)
{
Bool appliedFix = FALSE;
@@ -179,6 +233,41 @@ workaroundsDoFixes (CompWindow *w)
}
static void
+workaroundsDisplayOptionChanged (CompDisplay *d,
+ CompOption *opt,
+ WorkaroundsDisplayOptions num)
+{
+ CompScreen *s;
+ CompWindow *w;
+
+ for (s = d->screens; s; s = s->next)
+ for (w = s->windows; w; w = w->next)
+ workaroundsUpdateSticky (w);
+}
+
+static void
+workaroundsHandleEvent (CompDisplay *d,
+ XEvent *event)
+{
+ CompWindow *w;
+
+ WORKAROUNDS_DISPLAY (d);
+
+ UNWRAP (wd, d, handleEvent);
+ (*d->handleEvent) (d, event);
+ WRAP (wd, d, handleEvent, workaroundsHandleEvent);
+
+ if (event->type == ClientMessage)
+ {
+ if (event->xclient.message_type == d->winDesktopAtom)
+ {
+ w = findWindowAtDisplay (d, event->xclient.window);
+ workaroundsUpdateSticky (w);
+ }
+ }
+}
+
+static void
workaroundsWindowResizeNotify (CompWindow *w, int dx, int dy,
int dwidth, int dheight)
{
@@ -212,8 +301,15 @@ workaroundsInitDisplay (CompPlugin *plugin, CompDisplay *d)
wd->roleAtom = XInternAtom (d->display, "WM_WINDOW_ROLE", 0);
+ workaroundsSetStickyAlldesktopsNotify (d, workaroundsDisplayOptionChanged);
+ workaroundsSetAlldesktopStickyMatchNotify (d,
+ workaroundsDisplayOptionChanged);
+ workaroundsSetStickyMatchNotify (d, workaroundsDisplayOptionChanged);
+
d->privates[displayPrivateIndex].ptr = wd;
+ WRAP (wd, d, handleEvent, workaroundsHandleEvent);
+
return TRUE;
}
@@ -224,6 +320,8 @@ workaroundsFiniDisplay (CompPlugin *plugin, CompDisplay *d)
freeScreenPrivateIndex (d, wd->screenPrivateIndex);
+ UNWRAP (wd, d, handleEvent);
+
free (wd);
}
@@ -238,6 +336,13 @@ workaroundsInitScreen (CompPlugin *plugin, CompScreen *s)
if (!ws)
return FALSE;
+ ws->windowPrivateIndex = allocateWindowPrivateIndex (s);
+ if (ws->windowPrivateIndex < 0)
+ {
+ free (ws);
+ return FALSE;
+ }
+
WRAP (ws, s, windowResizeNotify, workaroundsWindowResizeNotify);
s->privates[wd->screenPrivateIndex].ptr = ws;
@@ -250,6 +355,8 @@ workaroundsFiniScreen (CompPlugin *plugin, CompScreen *s)
{
WORKAROUNDS_SCREEN (s);
+ freeWindowPrivateIndex (s, ws->windowPrivateIndex);
+
UNWRAP (ws, s, windowResizeNotify);
free (ws);
@@ -258,6 +365,18 @@ workaroundsFiniScreen (CompPlugin *plugin, CompScreen *s)
static Bool
workaroundsInitWindow (CompPlugin *plugin, CompWindow *w)
{
+ WORKAROUNDS_SCREEN (w->screen);
+ WorkaroundsWindow *ww;
+
+ ww = malloc (sizeof (WorkaroundsWindow));
+ if (!ww)
+ return FALSE;
+
+ ww->madeSticky = FALSE;
+
+ w->privates[ws->windowPrivateIndex].ptr = ww;
+
+ workaroundsUpdateSticky (w);
workaroundsDoFixes (w);
return TRUE;
@@ -266,8 +385,13 @@ workaroundsInitWindow (CompPlugin *plugin, CompWindow *w)
static void
workaroundsFiniWindow (CompPlugin *plugin, CompWindow *w)
{
+ WORKAROUNDS_WINDOW (w);
+
w->wmType = getWindowType (w->screen->display, w->id);
recalcWindowType (w);
+ workaroundsRemoveSticky (w);
+
+ free (ww);
}
static Bool
diff --git a/workarounds.xml.in b/workarounds.xml.in
index 139a544..7d3e538 100644
--- a/workarounds.xml.in
+++ b/workarounds.xml.in
@@ -33,6 +33,24 @@
<_long>Fix window type of various Qt windows.</_long>
<default>true</default>
</option>
+ <subgroup>
+ <_short>Window stickyness</_short>
+ <option type="bool" name="sticky_alldesktops">
+ <_short>Make "on all desktops" windows "sticky"</_short>
+ <_long>Make "on all desktops" windows sticky. Sticky windows are visable on all viewports.</_long>
+ <default>false</default>
+ </option>
+ <option name="alldesktop_sticky_match" type="match">
+ <_short>"On all desktops" sticky match</_short>
+ <_long>Windows on all desktops that should be made sticky</_long>
+ <default>any</default>
+ </option>
+ <option name="sticky_match" type="match">
+ <_short>Stckiy windows match</_short>
+ <_long>Windows that should be made sticky</_long>
+ <default></default>
+ </option>
+ </subgroup>
</display>
<screen>
</screen>