summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimmo Hämäläinen <kimmo.hamalainen@nokia.com>2010-11-22 16:24:10 +0200
committerAdam Endrodi <ext-adam.endrodi@nokia.com>2010-12-14 10:52:35 +0200
commit8c71bda3c1b57f6c2cde2297c09b2469dca1e4ee (patch)
treebff146ebb6c449a837160b815290e297681ad359
parent8fdc9bf05f8d3b4a62ad07461099e4d930019676 (diff)
Implement support for multi-part decorator
-rw-r--r--decorators/mdecorator/mdecoratorwindow.cpp113
-rw-r--r--decorators/mdecorator/mdecoratorwindow.h4
-rw-r--r--src/mcompositemanager.cpp4
-rw-r--r--src/mcompositemanager.h4
-rw-r--r--src/mcompositewindow.cpp23
-rw-r--r--src/mdecoratorframe.cpp42
-rw-r--r--src/mdecoratorframe.h4
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