From d26102284adaaa4e17abc4a1c4c9d60d0fcec502 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kimmo=20H=E4m=E4l=E4inen?= Date: Thu, 11 Nov 2010 17:18:59 +0200 Subject: 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 --- src/mcompositemanager.cpp | 35 ++++++++++++++++++++----------- src/mcompositewindow.cpp | 48 ++++++++++++++++++++++++++++--------------- src/mcompositewindow.h | 14 ++++++++++--- src/mtexturepixmapitem.h | 2 +- tests/windowctl/windowctl.cpp | 36 +++++++++++++++++++++++++++++++- 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 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::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 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 @@ -251,6 +251,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 N\n" "J - set _MEEGOTOUCH_ALWAYS_MAPPED of window to N (>= 0)\n" "Usage 8: " PROG " X x y w h\n" - "X - set _MEEGOTOUCH_MSTATUSBAR_GEOMETRY of window to (x y w h)\n"; + "X - set _MEEGOTOUCH_MSTATUSBAR_GEOMETRY of window to (x y w h)\n" + "Usage 9: " PROG " CM \n" + "CM - send a ClientMessage (where window=) to window " + "(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;*/ } -- cgit v1.2.3 From ca31ac11945ec21c090a4483680a186a72872443 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kimmo=20H=E4m=E4l=E4inen?= Date: Fri, 12 Nov 2010 13:10:44 +0200 Subject: Fixes: NB#201074 - Blank white space is getting displayed on the top part of the all facebook screens - added a check if the decorator area is bigger than half of the screen, when we fallback to only_statusbar mode - removed harmful XSelectInput() call (not needed with current LMT) - notice that Adam's commit b225ca4dfee8a6aca4aa3d26ee253c68b7ee6344 fixes this bug too but breaks something also --- decorators/mdecorator/mdecoratorwindow.cpp | 25 +++++++++++++------------ tests/windowctl/windowctl.cpp | 6 +++++- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/decorators/mdecorator/mdecoratorwindow.cpp b/decorators/mdecorator/mdecoratorwindow.cpp index d6ab04a..6b96631 100644 --- a/decorators/mdecorator/mdecoratorwindow.cpp +++ b/decorators/mdecorator/mdecoratorwindow.cpp @@ -106,7 +106,6 @@ static QRect windowRectFromGraphicsItem(const QGraphicsView &view, MDecoratorWindow::MDecoratorWindow(QWidget *parent) : MWindow(parent) { - XSelectInput(QX11Info::display(), winId(), PropertyChangeMask); onlyStatusbarAtom = XInternAtom(QX11Info::display(), "_MDECORATOR_ONLY_STATUSBAR", False); managedWindowAtom = XInternAtom(QX11Info::display(), @@ -247,21 +246,23 @@ void MDecoratorWindow::setInputRegion() { static XRectangle prev_rect = {0, 0, 0, 0}; QRegion region; - QRect r = statusBar->boundingRect().toRect(); - region += r; + region += statusBar->geometry().toRect(); if (!only_statusbar) { - QRect r2 = navigationBar->boundingRect().toRect(); - QRegion tmp(0, r.height(), r2.width(), r2.height()); - region += tmp; - r2 = homeButtonPanel->boundingRect().toRect(); - tmp = QRegion(0, r.height(), r2.width(), r2.height()); - region += tmp; - r2 = escapeButtonPanel->boundingRect().toRect(); - tmp = QRegion(0, r.height(), r2.width(), r2.height()); - region += tmp; + region += navigationBar->geometry().toRect(); + region += homeButtonPanel->geometry().toRect(); + region += escapeButtonPanel->geometry().toRect(); } + + const QRect fs(QApplication::desktop()->screenGeometry()); decoratorRect = region.boundingRect(); + if (!only_statusbar && decoratorRect.width() > fs.width() / 2 + && decoratorRect.height() > fs.height() / 2) { + // decorator is so big that it is probably in more than one part + // (which is not yet supported) + setOnlyStatusbar(true); + region = decoratorRect = statusBar->geometry().toRect(); + } XRectangle rect = itemRectToScreenRect(decoratorRect); if (memcmp(&prev_rect, &rect, sizeof(XRectangle))) { Display *dpy = QX11Info::display(); diff --git a/tests/windowctl/windowctl.cpp b/tests/windowctl/windowctl.cpp index c42b3f2..c997891 100644 --- a/tests/windowctl/windowctl.cpp +++ b/tests/windowctl/windowctl.cpp @@ -307,7 +307,11 @@ static Window create_window(Display *dpy, int width, int height, visual, attr_mask | CWColormap | CWBorderPixel, &attrs); } else { - attrs.background_pixel = BlackPixel (dpy, 0); + XColor color; + if (!XParseColor(dpy, DefaultColormap(dpy, 0), "red", &color)) + attrs.background_pixel = BlackPixel(dpy, 0); + else + attrs.background_pixel = color.pixel; w = XCreateWindow(dpy, DefaultRootWindow (dpy), 0, 0, width, height, 0, input_only ? 0 : CopyFromParent, input_only ? InputOnly : InputOutput, -- cgit v1.2.3 From 7d3ba1577b1cf01049abc2478d6a58fb43a3789b Mon Sep 17 00:00:00 2001 From: Abdiel Janulgue Date: Fri, 12 Nov 2010 13:48:41 +0200 Subject: new version for integration --- debian/changelog | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/debian/changelog b/debian/changelog index 7046a77..681eeff 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,11 @@ -mcompositor (0.7.8~1) unstable; urgency=low - - * New version [UNRELEASED] +mcompositor (0.7.8-1) unstable; urgency=low + + * Fixes: NB#201074 - Blank white space is getting displayed on the top part of the all facebook screens + * Fixes: NB#203276 - Show unmap animation on UnmapNotify, not on _NET_CLOSE_WINDOW + * Fixes: http://bugs.meego.com/show_bug.cgi?id=8957 + * Fixes: NB#198747 - text input causes device to freeze + * Fixes: NB#199378 - Only Input Method toolbar is visible after reopening Conversational View - Move all redirection of windows to MTexturePi + * Fixes: NB#199856 - Application catches tap from screen unblanking when Status Menu fails to open - allow setting NormalState when a window -- Abdiel Janulgue Thu, 28 Oct 2010 16:19:02 +0300 -- cgit v1.2.3