summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimmo Hämäläinen <kimmo.hamalainen@nokia.com>2010-11-11 17:18:59 +0200
committerAbdiel Janulgue <abdiel.janulgue@nokia.com>2010-11-12 16:26:03 +0200
commitbbff8a5cd5b21ab4a36ea21ccbc4e24eb42979e2 (patch)
tree354497d00639a1d85fe2df8cd8dc588fa9a834aa
parentc63119d3a174b346e387137b4bdf08482d354c80 (diff)
Fixes: NB#203276 - Show unmap animation on UnmapNotify, not on _NET_CLOSE_WINDOW
- save pixmap on _NET_CLOSE_WINDOW and animate on UnmapNotify - add limited support for sending ClientMessages to windowctl
-rw-r--r--src/mcompositemanager.cpp35
-rw-r--r--src/mcompositewindow.cpp48
-rw-r--r--src/mcompositewindow.h14
-rw-r--r--src/mtexturepixmapitem.h2
-rw-r--r--tests/windowctl/windowctl.cpp36
5 files changed, 102 insertions, 33 deletions
diff --git a/src/mcompositemanager.cpp b/src/mcompositemanager.cpp
index 81c7841..f450ada 100644
--- a/src/mcompositemanager.cpp
+++ b/src/mcompositemanager.cpp
@@ -1111,6 +1111,9 @@ bool MCompositeManagerPrivate::possiblyUnredirectTopmostWindow()
win_i = i;
break;
}
+ if (cw->isClosing())
+ // this window is unmapped and has unmap animation going on
+ return false;
if (cw->isMapped() && (cw->propertyCache()->hasAlpha()
|| cw->needDecoration()
|| cw->propertyCache()->isDecorator()
@@ -1170,6 +1173,9 @@ bool MCompositeManagerPrivate::possiblyUnredirectTopmostWindow()
void MCompositeManagerPrivate::unmapEvent(XUnmapEvent *e)
{
+ if (e->event != QX11Info::appRootWindow())
+ // handle root's SubstructureNotifys (top-levels) only
+ return;
if (configure_reqs.contains(e->window)) {
QList<XConfigureRequestEvent*> l = configure_reqs.value(e->window);
while (!l.isEmpty()) {
@@ -1197,6 +1203,7 @@ void MCompositeManagerPrivate::unmapEvent(XUnmapEvent *e)
MCompositeWindow *item = COMPOSITE_WINDOW(e->window);
if (item) {
+ item->closeWindowAnimation();
item->stopPing();
item->setIsMapped(false);
setWindowState(e->window, WithdrawnState);
@@ -2170,6 +2177,7 @@ void MCompositeManagerPrivate::mapEvent(XMapEvent *e)
prop_caches[win] = wpc;
}
wpc->setBeingMapped(false);
+ wpc->setIsMapped(true);
FrameData fd = framed_windows.value(win);
if (fd.frame) {
@@ -2393,12 +2401,8 @@ void MCompositeManagerPrivate::rootMessageEvent(XClientMessageEvent *event)
// use composition due to the transition effect
activateWindow(event->window, CurrentTime, false);
} else if (i && event->message_type == ATOM(_NET_CLOSE_WINDOW)) {
-
- i->closeWindow();
- // update stacking list to remove window from switcher
- if (i->propertyCache()->windowState() != IconicState)
- checkStacking(false);
-
+ // save pixmap and delete or kill this window
+ i->closeWindowRequest();
} else if (event->message_type == ATOM(WM_PROTOCOLS)) {
if (event->data.l[0] == (long) ATOM(_NET_WM_PING)) {
MCompositeWindow *ping_source = COMPOSITE_WINDOW(event->data.l[2]);
@@ -2540,7 +2544,8 @@ void MCompositeManagerPrivate::closeHandler(MCompositeWindow *window)
if ((!delete_sent || window->status() == MCompositeWindow::Hung)) {
kill_window(window->window());
- MDecoratorFrame::instance()->lower();
+ if (MDecoratorFrame::instance()->managedWindow() == window->window())
+ MDecoratorFrame::instance()->lower();
}
/* DO NOT deleteLater() this window yet because
a) it can remove a mapped window from stacking_list
@@ -2549,6 +2554,7 @@ void MCompositeManagerPrivate::closeHandler(MCompositeWindow *window)
d) we get UnmapNotify/DestroyNotify anyway when it _really_ closes */
}
+// window iconified or unmapping animation ended
void MCompositeManagerPrivate::lowerHandler(MCompositeWindow *window)
{
// TODO: (work for more)
@@ -2561,8 +2567,10 @@ void MCompositeManagerPrivate::lowerHandler(MCompositeWindow *window)
if (i)
i->iconify();
}
- // set for roughSort() before raising duihome
- setWindowState(window->window(), IconicState);
+ // don't mark unmapped windows iconic (our iconic windows are mapped)
+ if (window->isMapped())
+ // set for roughSort() before raising duihome
+ setWindowState(window->window(), IconicState);
if (stack[DESKTOP_LAYER]) {
// redirect windows for the switcher
@@ -3241,7 +3249,8 @@ void MCompositeManagerPrivate::addItem(MCompositeWindow *item)
connect(this, SIGNAL(compositingEnabled()), item, SLOT(startTransition()));
connect(item, SIGNAL(itemRestored(MCompositeWindow *)), SLOT(restoreHandler(MCompositeWindow *)));
connect(item, SIGNAL(itemIconified(MCompositeWindow *)), SLOT(lowerHandler(MCompositeWindow *)));
- connect(item, SIGNAL(windowClosed(MCompositeWindow *)), SLOT(closeHandler(MCompositeWindow *)));
+ connect(item, SIGNAL(closeWindowRequest(MCompositeWindow *)),
+ SLOT(closeHandler(MCompositeWindow *)));
// ping protocol
@@ -3361,8 +3370,10 @@ void MCompositeManagerPrivate::enableRedirection()
{
for (QHash<Window, MCompositeWindow *>::iterator it = windows.begin();
it != windows.end(); ++it) {
- MCompositeWindow *tp = it.value();
- if (tp->windowVisible())
+ MCompositeWindow *tp = it.value();
+ if (tp->isValid() && tp->isDirectRendered() && tp->propertyCache()
+ && (tp->propertyCache()->isMapped()
+ || tp->propertyCache()->beingMapped()))
((MTexturePixmapItem *)tp)->enableRedirectedRendering();
setWindowDebugProperties(it.key());
}
diff --git a/src/mcompositewindow.cpp b/src/mcompositewindow.cpp
index f0f26a6..624943b 100644
--- a/src/mcompositewindow.cpp
+++ b/src/mcompositewindow.cpp
@@ -172,6 +172,7 @@ void MCompositeWindow::iconify(const QRectF &icongeometry, bool defer)
{
if (iconify_state == ManualIconifyState) {
setIconified(true);
+ window_status = Normal;
return;
}
@@ -184,6 +185,7 @@ void MCompositeWindow::iconify(const QRectF &icongeometry, bool defer)
for (int i = 0; i < evlist.size(); ++i) {
if (evlist[i]->windowIconified(this, defer)) {
iconified = true;
+ window_status = Normal;
return;
}
}
@@ -333,7 +335,9 @@ bool MCompositeWindow::showWindow()
{
// defer putting this window in the _NET_CLIENT_LIST
// only after animation is done to prevent the switcher from rendering it
- if (!isAppWindow())
+ if (!isAppWindow() || !pc || !pc->is_valid
+ // isAppWindow() returns true for system dialogs
+ || pc->windowTypeAtom() == ATOM(_NET_WM_WINDOW_TYPE_DIALOG))
return false;
findBehindWindow();
@@ -388,19 +392,32 @@ void MCompositeWindow::q_fadeIn()
restore(fadeRect, false);
}
-void MCompositeWindow::closeWindow()
+void MCompositeWindow::closeWindowRequest()
{
- if (!isAppWindow() || propertyCache()->windowState() == IconicState) {
- setVisible(false);
- emit windowClosed(this);
+ if (!pc || !pc->is_valid || (!isMapped() && !pc->beingMapped()))
return;
+ if (!windowPixmap() && !pc->isInputOnly()) {
+ // get a Pixmap for the possible unmap animation
+ MCompositeManager *p = (MCompositeManager *) qApp;
+ if (!p->isCompositing())
+ p->d->enableCompositing(true);
+ updateWindowPixmap();
}
- if (window_status == MCompositeWindow::Hung) {
- hide();
- emit windowClosed(this);
+ emit closeWindowRequest(this);
+}
+
+void MCompositeWindow::closeWindowAnimation()
+{
+ if (!pc || !pc->is_valid || window_status == Closing
+ || pc->isInputOnly() || pc->isOverrideRedirect()
+ || !windowPixmap() || !isAppWindow()
+ // isAppWindow() returns true for system dialogs
+ || pc->windowTypeAtom() == ATOM(_NET_WM_WINDOW_TYPE_DIALOG)
+ || propertyCache()->windowState() == IconicState
+ || window_status == MCompositeWindow::Hung) {
return;
}
- window_status = MCompositeWindow::Closing;
+ window_status = Closing; // animating, do not disturb
MCompositeManager *p = (MCompositeManager *) qApp;
bool defer = false;
@@ -410,13 +427,13 @@ void MCompositeWindow::closeWindow()
defer = true;
}
- updateWindowPixmap();
origPosition = pos();
// Custom close window animation handler
QList<MCompositeManagerExtension*> evlist = p->d->m_extensions.values(MapNotify);
for (int i = 0; i < evlist.size(); ++i) {
if (evlist[i]->windowClosed(this)) {
+ window_status = Normal; // can't guarantee that Closing is cleared
return;
}
}
@@ -444,6 +461,8 @@ void MCompositeWindow::finalizeState()
{
endAnimation();
+ // as far as this window is concerned, it's OK to direct render
+ window_status = Normal;
if (pc && pc->windowTypeAtom() == ATOM(_NET_WM_WINDOW_TYPE_DESKTOP))
emit desktopActivated(this);
@@ -454,10 +473,6 @@ void MCompositeWindow::finalizeState()
hide();
iconify_state = TransitionIconifyState;
emit itemIconified(this);
- if (isClosing()) {
- emit windowClosed(this);
- return;
- }
} else {
iconify_state = NoIconifyState;
iconified_final = false;
@@ -467,7 +482,6 @@ void MCompositeWindow::finalizeState()
// to allow it)
q_itemRestored();
}
- window_status = Normal;
// item lifetime
if (destroyed)
@@ -653,7 +667,7 @@ MCompositeWindow *MCompositeWindow::compositeWindow(Qt::HANDLE window)
void MCompositeWindow::beginAnimation()
{
- if (!isMapped())
+ if (!isMapped() && window_status != Closing)
return;
if (!is_transitioning) {
@@ -769,6 +783,8 @@ int MCompositeWindow::indexInStack() const
void MCompositeWindow::setIsMapped(bool mapped)
{
+ if (mapped)
+ window_status = Normal; // make sure Closing -> Normal when remapped
if (pc) pc->setIsMapped(mapped);
}
diff --git a/src/mcompositewindow.h b/src/mcompositewindow.h
index cc53cd7..ed558a2 100644
--- a/src/mcompositewindow.h
+++ b/src/mcompositewindow.h
@@ -252,6 +252,11 @@ public:
virtual void clearTexture() = 0;
/*!
+ Returns pixmap for the window.
+ */
+ virtual Pixmap windowPixmap() const = 0;
+
+ /*!
Returns true if the window corresponding to the offscreen pixmap
is rendering directly to the framebuffer, otherwise return false.
*/
@@ -311,7 +316,10 @@ public slots:
void setBlurred(bool);
/* Operations with transition animations*/
- void closeWindow();
+ // set to Closing state and send delete/kill
+ void closeWindowRequest();
+ // start unmap animation
+ void closeWindowAnimation();
bool showWindow();
/*!
@@ -361,8 +369,8 @@ signals:
void itemIconified(MCompositeWindow *window);
/*! Emitted when desktop is raised */
void desktopActivated(MCompositeWindow *window);
- /*! Emitted when this window is closed */
- void windowClosed(MCompositeWindow *window);
+ /*! Emitted when the user wants to close this window */
+ void closeWindowRequest(MCompositeWindow *window);
protected:
diff --git a/src/mtexturepixmapitem.h b/src/mtexturepixmapitem.h
index 14a6dcf..f433dd7 100644
--- a/src/mtexturepixmapitem.h
+++ b/src/mtexturepixmapitem.h
@@ -89,7 +89,7 @@ public:
void enableDirectFbRendering();
void enableRedirectedRendering();
- Pixmap windowPixmap() const { return d->windowp; }
+ virtual Pixmap windowPixmap() const { return d->windowp; }
protected:
void paint(QPainter *painter,
diff --git a/tests/windowctl/windowctl.cpp b/tests/windowctl/windowctl.cpp
index 60f6446..c42b3f2 100644
--- a/tests/windowctl/windowctl.cpp
+++ b/tests/windowctl/windowctl.cpp
@@ -404,7 +404,11 @@ static void print_usage_and_exit(QString& stdOut)
"Usage 7: " PROG " J <XID> N\n"
"J - set _MEEGOTOUCH_ALWAYS_MAPPED of window <XID> to N (>= 0)\n"
"Usage 8: " PROG " X <XID> x y w h\n"
- "X - set _MEEGOTOUCH_MSTATUSBAR_GEOMETRY of window <XID> to (x y w h)\n";
+ "X - set _MEEGOTOUCH_MSTATUSBAR_GEOMETRY of window <XID> to (x y w h)\n"
+ "Usage 9: " PROG " CM <XID> <ClientMessage type name> <window>\n"
+ "CM - send a ClientMessage (where window=<window>) to window <XID> "
+ "(0 = the root window)\n"
+ ;
}
static void configure (Display *dpy, char *first, char *second, bool above)
@@ -829,6 +833,28 @@ static bool old_main(QStringList& args, QString& stdOut)
return true;
}
}
+ if (*p == 'C' && *(p + 1) == 'M') {
+ if (args.count() != 4) {
+ print_usage_and_exit(stdOut); return false;
+ }
+ Atom a = XInternAtom(dpy, args.at(2).toAscii().data(),
+ False);
+ XEvent ev;
+ memset(&ev, 0, sizeof(ev));
+ ev.xclient.type = ClientMessage;
+ ev.xclient.message_type = a;
+ ev.xclient.window = strtol(args.at(3).toAscii().data(),
+ NULL, 16);
+ ev.xclient.format = 32;
+ Window w = strtol(args.at(1).toAscii().data(), NULL, 16);
+ if (w == 0) {
+ w = DefaultRootWindow(dpy);
+ XSendEvent(dpy, w, False, SubstructureRedirectMask, &ev);
+ } else
+ XSendEvent(dpy, w, False, NoEventMask, &ev);
+ XSync(dpy, False);
+ return true;
+ }
if ((command = strchr("NUFCMTAWHSO", *p))) {
if (args.count() != 2) {
print_usage_and_exit(stdOut);
@@ -978,6 +1004,14 @@ static bool old_main(QStringList& args, QString& stdOut)
/* our window was unmapped */
exit(0);
}
+#if 0
+ else if (xev.type == ClientMessage) {
+ XClientMessageEvent *e = (XClientMessageEvent*)&xev;
+ printf("0x%lx: ClientMessage %d %ld %ld\n", w,
+ e->message_type,
+ e->data.l[0], e->data.l[1]);
+ }
+#endif
else if (xev.type == ConfigureNotify) {
/*XConfigureEvent *e = (XConfigureEvent*)&xev;*/
}