summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSam Spilsbury <sam.spilsbury@canonical.com>2010-12-03 01:19:43 +0800
committerSam Spilsbury <sam.spilsbury@canonical.com>2010-12-03 01:19:43 +0800
commit1084f0be5c200d46ad3b4358a477963d31040736 (patch)
treee2f867114c2b18c91fae9ebdbd0365014ba38c1e /src
parent1cb5c0d4c5b0afb6587fddd749e726019d81227a (diff)
downloadunity-window-decorator-1084f0be5c200d46ad3b4358a477963d31040736.tar.gz
unity-window-decorator-1084f0be5c200d46ad3b4358a477963d31040736.tar.bz2
Ensure that we can change the input focus, even if we requested a client to take focus and it failed to do it before it was unmapped
Diffstat (limited to 'src')
-rw-r--r--src/event.cpp18
-rw-r--r--src/privatescreen.h5
-rw-r--r--src/screen.cpp28
-rw-r--r--src/window.cpp16
4 files changed, 52 insertions, 15 deletions
diff --git a/src/event.cpp b/src/event.cpp
index 6acf04f..5e214cb 100644
--- a/src/event.cpp
+++ b/src/event.cpp
@@ -1095,7 +1095,23 @@ CompScreen::handleEvent (XEvent *event)
w->unmap ();
if (!w->shaded () && !w->priv->pendingMaps)
+ {
+ /* It is possible that we requested for this window to
+ * have focus and it was unmapped before it responded
+ * to that request (eg XSetInputFocus) - if that is
+ * the case then we need to set the active window to
+ * the one being unmapped so that we can properly
+ * transfer focus away
+ */
+
+ if (priv->requestedFocusWindow == w->id ())
+ {
+ priv->activeWindow = priv->requestedFocusWindow;
+ priv->requestedFocusWindow = 0;
+ }
+
w->moveInputFocusToOtherWindow ();
+ }
}
break;
case ReparentNotify:
@@ -1660,6 +1676,8 @@ CompScreen::handleEvent (XEvent *event)
state &= ~CompWindowStateDemandsAttentionMask;
w->changeState (state);
+
+ priv->requestedFocusWindow = None;
}
}
else
diff --git a/src/privatescreen.h b/src/privatescreen.h
index fe19cff..7505549 100644
--- a/src/privatescreen.h
+++ b/src/privatescreen.h
@@ -333,8 +333,13 @@ class PrivateScreen : public CoreOptions {
unsigned int lastPing;
CompTimer pingTimer;
+ /* The window that last receieved a FocusIn and was
+ * also valid */
Window activeWindow;
+ /* The last window we sent a WM_TAKE_FOCUS to */
+ Window requestedFocusWindow;
+
Window below;
char displayString[256];
diff --git a/src/screen.cpp b/src/screen.cpp
index 2a5fd74..1befb7d 100644
--- a/src/screen.cpp
+++ b/src/screen.cpp
@@ -3332,6 +3332,33 @@ CompScreen::toolkitAction (Atom toolkitAction,
StructureNotifyMask, &ev);
}
+bool
+CompScreen::requestFocus (CompWindow *w)
+{
+ if (w->protocols () & CompWindowProtocolTakeFocusMask)
+ {
+ XEvent ev;
+
+ ev.type = ClientMessage;
+ ev.xclient.window = w->id ();
+ ev.xclient.message_type = Atoms::wmProtocols;
+ ev.xclient.format = 32;
+ ev.xclient.data.l[0] = Atoms::wmTakeFocus;
+ ev.xclient.data.l[1] = screen->getCurrentTime ();
+ ev.xclient.data.l[2] = 0;
+ ev.xclient.data.l[3] = 0;
+ ev.xclient.data.l[4] = 0;
+
+ XSendEvent (screen->dpy (), w->id (), false, NoEventMask, &ev);
+
+ priv->requestedFocusWindow = w->id ();
+
+ return true;
+ }
+
+ return false;
+}
+
void
CompScreen::runCommand (CompString command)
{
@@ -4548,6 +4575,7 @@ PrivateScreen::PrivateScreen (CompScreen *screen) :
valueMap (),
screenInfo (0),
activeWindow (0),
+ requestedFocusWindow (0),
below (None),
autoRaiseTimer (),
autoRaiseWindow (0),
diff --git a/src/window.cpp b/src/window.cpp
index e9b3260..ccfc86c 100644
--- a/src/window.cpp
+++ b/src/window.cpp
@@ -1920,21 +1920,7 @@ CompWindow::moveInputFocusTo ()
if (priv->protocols & CompWindowProtocolTakeFocusMask)
{
- XEvent ev;
-
- ev.type = ClientMessage;
- ev.xclient.window = priv->id;
- ev.xclient.message_type = Atoms::wmProtocols;
- ev.xclient.format = 32;
- ev.xclient.data.l[0] = Atoms::wmTakeFocus;
- ev.xclient.data.l[1] = s->getCurrentTime ();
- ev.xclient.data.l[2] = 0;
- ev.xclient.data.l[3] = 0;
- ev.xclient.data.l[4] = 0;
-
- XSendEvent (s->dpy (), priv->id, false, NoEventMask, &ev);
-
- setFocus = true;
+ setFocus |= screen->requestFocus (this);
}
if (!setFocus && !modalTransient)