diff options
author | Kimmo Hämäläinen <kimmo.hamalainen@nokia.com> | 2010-11-22 16:24:10 +0200 |
---|---|---|
committer | Adam Endrodi <ext-adam.endrodi@nokia.com> | 2010-12-14 10:52:35 +0200 |
commit | 8c71bda3c1b57f6c2cde2297c09b2469dca1e4ee (patch) | |
tree | bff146ebb6c449a837160b815290e297681ad359 | |
parent | 8fdc9bf05f8d3b4a62ad07461099e4d930019676 (diff) |
Implement support for multi-part decorator
-rw-r--r-- | decorators/mdecorator/mdecoratorwindow.cpp | 113 | ||||
-rw-r--r-- | decorators/mdecorator/mdecoratorwindow.h | 4 | ||||
-rw-r--r-- | src/mcompositemanager.cpp | 4 | ||||
-rw-r--r-- | src/mcompositemanager.h | 4 | ||||
-rw-r--r-- | src/mcompositewindow.cpp | 23 | ||||
-rw-r--r-- | src/mdecoratorframe.cpp | 42 | ||||
-rw-r--r-- | src/mdecoratorframe.h | 4 |
7 files changed, 90 insertions, 104 deletions
diff --git a/decorators/mdecorator/mdecoratorwindow.cpp b/decorators/mdecorator/mdecoratorwindow.cpp index 9a7f01d..4e20aff 100644 --- a/decorators/mdecorator/mdecoratorwindow.cpp +++ b/decorators/mdecorator/mdecoratorwindow.cpp @@ -282,92 +282,97 @@ void MDecoratorWindow::screenRotated(const M::Orientation &orientation) d->setAvailableGeometry(availableClientRect()); } -XRectangle MDecoratorWindow::itemRectToScreenRect(const QRect& r) +// NOTE: this works with fullscreen-width rects only +QRect MDecoratorWindow::itemRectToScreenRect(const QRect& r) { - XRectangle rect; + QRect rect; Display *dpy = QX11Info::display(); int xres = ScreenOfDisplay(dpy, DefaultScreen(dpy))->width; int yres = ScreenOfDisplay(dpy, DefaultScreen(dpy))->height; switch (sceneManager()->orientationAngle()) { case 0: - rect.x = r.x(); - rect.y = r.y(); - rect.width = r.width(); - rect.height = r.height(); + rect = r; break; case 90: - rect.x = xres - r.height(); - rect.y = 0; - rect.width = r.height(); - rect.height = r.width(); + rect = QRect(xres - r.height(), 0, r.height(), r.width()); break; case 270: - rect.x = rect.y = 0; - rect.width = r.height(); - rect.height = r.width(); + rect = QRect(0, 0, r.height(), r.width()); break; case 180: - rect.x = 0; - rect.y = yres - r.height(); - rect.width = r.width(); - rect.height = r.height(); + rect = QRect(0, yres - r.height(), r.width(), r.height()); break; default: - memset(&rect, 0, sizeof(rect)); break; } return rect; } +static void set_shape(Window win, XRectangle *r, int n) +{ + static XRectangle *prev_rects = 0; + static int prev_n = 0; + if (prev_n != n || + (prev_rects && memcmp(prev_rects, r, sizeof(XRectangle[n])))) { + Display *dpy = QX11Info::display(); + XserverRegion shapeRegion = XFixesCreateRegion(dpy, r, n); + XShapeCombineRectangles(dpy, win, ShapeBounding, 0, 0, r, n, + ShapeSet, Unsorted); + XFixesSetWindowShapeRegion(dpy, win, ShapeInput, 0, 0, shapeRegion); + XFixesDestroyRegion(dpy, shapeRegion); + } else + return; + if (prev_rects && prev_n != n) { + delete[] prev_rects; + prev_rects = new XRectangle[n]; + } + prev_n = n; + if (prev_rects) + memcpy(prev_rects, r, sizeof(XRectangle[n])); +} + void MDecoratorWindow::setInputRegion() { - static XRectangle prev_rect = {0, 0, 0, 0}; QRegion region; const QRect fs(QApplication::desktop()->screenGeometry()); - XRectangle rect; if (messageBox) { - region = decoratorRect = fs; + XRectangle rect; + region = fs; rect.x = fs.x(); rect.y = fs.y(); rect.width = fs.width(); rect.height = fs.height(); + availableRect = QRect(0, 0, 0, 0); + set_shape(winId(), &rect, 1); } else { - QRect r_tmp(statusBar->geometry().toRect()); - region += statusBar->mapToScene(r_tmp).boundingRect().toRect(); + region += statusBar->geometry().toRect(); if (!only_statusbar) { - r_tmp = QRect(navigationBar->geometry().toRect()); - region += navigationBar->mapToScene(r_tmp).boundingRect().toRect(); - r_tmp = QRect(homeButtonPanel->geometry().toRect()); - region += homeButtonPanel->mapToScene(r_tmp).boundingRect().toRect(); - r_tmp = QRect(escapeButtonPanel->geometry().toRect()); - region += escapeButtonPanel->mapToScene(r_tmp).boundingRect().toRect(); + region += navigationBar->geometry().toRect(); + region += homeButtonPanel->geometry().toRect(); + region += escapeButtonPanel->geometry().toRect(); } - decoratorRect = region.boundingRect(); - // crop it to fullscreen to work around a weird issue - if (decoratorRect.width() > fs.width()) - decoratorRect.setWidth(fs.width()); - if (decoratorRect.height() > fs.height()) - decoratorRect.setHeight(fs.height()); - - 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(); + const QVector<QRect> rects = region.rects(); + QRegion screen_region; + XRectangle *xrects = new XRectangle[rects.count()]; + int count = 0; + for (int i = 0; i < rects.count(); ++i) { + QRect r = itemRectToScreenRect(rects[i]); + if (r.x() || (r.width() != fs.width() && r.width() != fs.height())) + // only fullscreen-width components supported + continue; + screen_region += r; + xrects[count].x = r.x(); + xrects[count].y = r.y(); + xrects[count].width = r.width(); + xrects[count].height = r.height(); + ++count; } - rect = itemRectToScreenRect(decoratorRect); - } - if (memcmp(&prev_rect, &rect, sizeof(XRectangle))) { - Display *dpy = QX11Info::display(); - XserverRegion shapeRegion = XFixesCreateRegion(dpy, &rect, 1); - XShapeCombineRectangles(dpy, winId(), ShapeBounding, 0, 0, &rect, 1, - ShapeSet, Unsorted); - XFixesSetWindowShapeRegion(dpy, winId(), ShapeInput, 0, 0, shapeRegion); - XFixesDestroyRegion(dpy, shapeRegion); - XSync(dpy, False); - prev_rect = rect; + set_shape(winId(), xrects, count); + delete[] xrects; + + // NOTE: assumes that the available region is a single rectangle + availableRect = QRegion(QRegion(fs) - screen_region).boundingRect(); } } @@ -397,7 +402,7 @@ void MDecoratorWindow::setMDecoratorWindowProperty() const QRect MDecoratorWindow::availableClientRect() const { - return decoratorRect; + return availableRect; } void MDecoratorWindow::closeEvent(QCloseEvent * event ) diff --git a/decorators/mdecorator/mdecoratorwindow.h b/decorators/mdecorator/mdecoratorwindow.h index d6cf589..aaaf1ff 100644 --- a/decorators/mdecorator/mdecoratorwindow.h +++ b/decorators/mdecorator/mdecoratorwindow.h @@ -78,7 +78,7 @@ signals: private: void setSceneSize(); void setMDecoratorWindowProperty(); - XRectangle itemRectToScreenRect(const QRect& r); + QRect itemRectToScreenRect(const QRect& r); MHomeButtonPanel *homeButtonPanel; MEscapeButtonPanel *escapeButtonPanel; @@ -86,7 +86,7 @@ private: MStatusBar *statusBar; MMessageBox *messageBox; Window managed_window; - QRect decoratorRect; + QRect availableRect; // available area for the managed window bool only_statusbar, requested_only_statusbar; Atom onlyStatusbarAtom, managedWindowAtom; MDecorator *d; diff --git a/src/mcompositemanager.cpp b/src/mcompositemanager.cpp index 5283554..a027cba 100644 --- a/src/mcompositemanager.cpp +++ b/src/mcompositemanager.cpp @@ -3406,9 +3406,9 @@ void MCompositeManager::positionWindow(Window w, d->positionWindow(w, pos == MCompositeManager::STACK_TOP ? true : false); } -const QRect &MCompositeManager::decoratorRect() const +const QRect &MCompositeManager::availableRect() const { - return MDecoratorFrame::instance()->decoratorRect(); + return MDecoratorFrame::instance()->availableRect(); } const QList<Window> &MCompositeManager::stackingList() const diff --git a/src/mcompositemanager.h b/src/mcompositemanager.h index e038aa2..07b2082 100644 --- a/src/mcompositemanager.h +++ b/src/mcompositemanager.h @@ -175,9 +175,9 @@ public slots: void exposeSwitcher(); /*! - * Area the decorator occupies. + * Area that is free after the area that decorator occupies. */ - const QRect &decoratorRect() const; + const QRect &availableRect() const; #ifdef WINDOW_DEBUG void remoteControl(int fd); diff --git a/src/mcompositewindow.cpp b/src/mcompositewindow.cpp index e01814a..62b116a 100644 --- a/src/mcompositewindow.cpp +++ b/src/mcompositewindow.cpp @@ -686,14 +686,23 @@ QVariant MCompositeWindow::itemChange(GraphicsItemChange change, const QVariant findBehindWindow(); p->d->setWindowDebugProperties(window()); } - - /* disabled to avoid glSwapBuffers call without painting any item (Qt bug) - * see NB#189519 - if (zvalChanged || change == ItemVisibleHasChanged || change == ItemParentHasChanged) - { + + // Be careful that there is a changed visible item, to not reopen NB#189519. + // Update is needed if visibility changes for a visible item + // (other visible items get redrawn also) + QList<QGraphicsItem*> l; + if (scene()) + l = scene()->items(); + int highest_visible_z = -1000; + for (QList<QGraphicsItem*>::const_iterator i = l.begin(); i != l.end(); ++i) + if ((*i)->isVisible()) { + highest_visible_z = (*i)->zValue(); + break; + } + + // case requiring this: status menu closed on top of decorated FieldTest app + if (zValue() >= highest_visible_z && change == ItemVisibleHasChanged) p->d->glwidget->update(); - } - */ return QGraphicsItem::itemChange(change, value); } diff --git a/src/mdecoratorframe.cpp b/src/mdecoratorframe.cpp index ad2ed19..a6e91f0 100644 --- a/src/mdecoratorframe.cpp +++ b/src/mdecoratorframe.cpp @@ -80,17 +80,8 @@ void MDecoratorFrame::raise() void MDecoratorFrame::updateManagedWindowGeometry() { - if (client && client->needDecoration()) { -#if 0 - Display *dpy = QX11Info::display(); - XWindowAttributes a; - if (!XGetWindowAttributes(dpy, decorator_window, &a)) { - qWarning("%s: invalid window 0x%lx", __func__, decorator_window); - return; - } -#endif - setDecoratorAvailableRect(decorator_rect); - } + if (client && client->needDecoration()) + setDecoratorAvailableRect(available_rect); } void MDecoratorFrame::setManagedWindow(MCompositeWindow *cw, @@ -163,7 +154,7 @@ void MDecoratorFrame::visualizeDecorator(bool visible) decorator_item->setVisible(visible); } -void MDecoratorFrame::setDecoratorAvailableRect(const QRect& decorect) +void MDecoratorFrame::setDecoratorAvailableRect(const QRect& r) { if (!client || no_resize || !decorator_item || !decorator_item->propertyCache()) @@ -171,30 +162,11 @@ void MDecoratorFrame::setDecoratorAvailableRect(const QRect& decorect) Display* dpy = QX11Info::display(); - int actual_decor_ypos = decorator_item->propertyCache()->realGeometry().y(); + available_rect = r; - decorator_rect = decorect; - - // if window is not same width as screen, stretch it. - QRect appgeometry = client->propertyCache()->requestedGeometry(); - if(appgeometry.width() < decorect.width()) - appgeometry = QApplication::desktop()->screenGeometry(); - - // region of decorator + statusbar window. remove this once we removed the statubar - QRect actual_decorect = decorect; - actual_decorect.setHeight(decorect.height() + actual_decor_ypos); - QRect r = (QRegion(appgeometry) - actual_decorect).boundingRect(); - - int xres = ScreenOfDisplay(dpy, DefaultScreen(dpy))->width; - int yres = ScreenOfDisplay(dpy, DefaultScreen(dpy))->height; - int excess = r.y() + r.height() - yres; - if (excess > 0) - r.setHeight(r.height() - excess); - excess = r.x() + r.width() - xres; - if (excess > 0) - r.setWidth(r.width() - excess); - - XMoveResizeWindow(dpy, client->window(), r.x(), r.y(), r.width(), r.height()); + if (client->propertyCache()->realGeometry() != available_rect) + // resize app window to occupy the free area + XMoveResizeWindow(dpy, client->window(), r.x(), r.y(), r.width(), r.height()); } void MDecoratorFrame::setAutoRotation(bool mode) diff --git a/src/mdecoratorframe.h b/src/mdecoratorframe.h index b8ef400..1fc87f2 100644 --- a/src/mdecoratorframe.h +++ b/src/mdecoratorframe.h @@ -97,7 +97,7 @@ public: void setDecoratorItem(MCompositeWindow *window); MCompositeWindow *decoratorItem() const; - const QRect &decoratorRect() const { return decorator_rect; } + const QRect &availableRect() const { return available_rect; } public slots: void setDecoratorAvailableRect(const QRect& r); @@ -117,7 +117,7 @@ private: MRmiClient *remote_decorator; int top_offset; bool no_resize; - QRect decorator_rect; + QRect available_rect; }; #endif // DUIDECORATORFRAME_H |