1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the config.tests of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qwaylandwindow.h"
44 #include "qwaylandbuffer.h"
45 #include "qwaylanddisplay.h"
46 #include "qwaylandinputdevice.h"
47 #include "qwaylandscreen.h"
48 #include "qwaylandshell.h"
49 #include "qwaylandshellsurface.h"
50 #include "qwaylandextendedsurface.h"
51 #include "qwaylandsubsurface.h"
52 #include "qwaylanddecoration.h"
54 #include <QtGui/QWindow>
56 #ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT
57 #include "windowmanager_integration/qwaylandwindowmanagerintegration.h"
60 #include <QCoreApplication>
61 #include <QtGui/QWindowSystemInterface>
63 #include <QtCore/QDebug>
65 QWaylandWindow::QWaylandWindow(QWindow *window)
66 : QPlatformWindow(window)
67 , mDisplay(QWaylandScreen::waylandScreenFromWindow(window)->display())
68 , mSurface(mDisplay->createSurface(this))
71 , mSubSurfaceWindow(0)
72 , mWindowDecoration(0)
73 , mMouseEventsInContentArea(false)
74 , mMousePressedInContentArea(Qt::NoButton)
76 , mWaitingForFrameSync(false)
78 , mSentInitialResize(false)
83 if (mDisplay->shell())
84 mShellSurface = mDisplay->shell()->getShellSurface(this);
85 if (mDisplay->windowExtension())
86 mExtendedWindow = mDisplay->windowExtension()->getExtendedWindow(this);
87 if (mDisplay->subSurfaceExtension())
88 mSubSurfaceWindow = mDisplay->subSurfaceExtension()->getSubSurfaceAwareWindow(this);
90 #ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT
91 mDisplay->windowManagerIntegration()->mapClientToProcess(qApp->applicationPid());
92 mDisplay->windowManagerIntegration()->authenticateWithToken();
95 if (parent() && mSubSurfaceWindow) {
96 mSubSurfaceWindow->setParent(static_cast<const QWaylandWindow *>(parent()));
97 }else if (window->transientParent()) {
98 if (window->transientParent()) {
99 mShellSurface->updateTransientParent(window->transientParent());
101 mShellSurface->setTopLevel();
106 QWaylandWindow::~QWaylandWindow()
109 delete mShellSurface;
110 delete mExtendedWindow;
111 wl_surface_destroy(mSurface);
114 QList<QWaylandInputDevice *> inputDevices = mDisplay->inputDevices();
115 for (int i = 0; i < inputDevices.size(); ++i)
116 inputDevices.at(i)->handleWindowDestroyed(this);
119 WId QWaylandWindow::winId() const
124 void QWaylandWindow::setParent(const QPlatformWindow *parent)
126 const QWaylandWindow *parentWaylandWindow = static_cast<const QWaylandWindow *>(parent);
127 if (subSurfaceWindow()) {
128 subSurfaceWindow()->setParent(parentWaylandWindow);
132 void QWaylandWindow::setWindowTitle(const QString &title)
135 if (mWindowDecoration && window()->isVisible()) {
136 mWindowDecoration->paintDecoration();
140 void QWaylandWindow::setGeometry(const QRect &rect)
142 QPlatformWindow::setGeometry(rect);
144 if (shellSurface() && window()->transientParent())
145 shellSurface()->updateTransientParent(window()->transientParent());
148 void QWaylandWindow::setVisible(bool visible)
153 wl_surface_attach(mSurface, mBuffer->buffer(), 0, 0);
155 if (!mSentInitialResize) {
156 QWindowSystemInterface::handleSynchronousGeometryChange(window(), geometry());
157 mSentInitialResize = true;
160 QWindowSystemInterface::handleSynchronousExposeEvent(window(), QRect(QPoint(), geometry().size()));
162 QWindowSystemInterface::handleSynchronousExposeEvent(window(), QRect(QPoint(), geometry().size()));
163 wl_surface_attach(mSurface, 0,0,0);
164 damage(QRect(QPoint(0,0),geometry().size()));
169 bool QWaylandWindow::isExposed() const
171 if (!window()->isVisible())
174 return mExtendedWindow->isExposed();
179 void QWaylandWindow::configure(uint32_t edges, int32_t width, int32_t height)
183 int widthWithoutMargins = qMax(width-(frameMargins().left() +frameMargins().right()),1);
184 int heightWithoutMargins = qMax(height-(frameMargins().top()+frameMargins().bottom()),1);
186 widthWithoutMargins = qMax(widthWithoutMargins, window()->minimumSize().width());
187 heightWithoutMargins = qMax(heightWithoutMargins, window()->minimumSize().height());
188 QRect geometry = QRect(0,0,
189 widthWithoutMargins, heightWithoutMargins);
190 setGeometry(geometry);
191 QWindowSystemInterface::handleGeometryChange(window(), geometry);
194 void QWaylandWindow::attach(QWaylandBuffer *buffer)
198 if (window()->isVisible()) {
199 wl_surface_attach(mSurface, mBuffer->buffer(),0,0);
203 QWaylandBuffer *QWaylandWindow::attached() const
208 void QWaylandWindow::damage(const QRect &rect)
210 //We have to do sync stuff before calling damage, or we might
211 //get a frame callback before we get the timestamp
212 if (!mWaitingForFrameSync) {
213 mFrameCallback = wl_surface_frame(mSurface);
214 wl_callback_add_listener(mFrameCallback,&QWaylandWindow::callbackListener,this);
215 mWaitingForFrameSync = true;
218 wl_surface_damage(mSurface,
219 rect.x(), rect.y(), rect.width(), rect.height());
222 const wl_callback_listener QWaylandWindow::callbackListener = {
223 QWaylandWindow::frameCallback
226 void QWaylandWindow::frameCallback(void *data, struct wl_callback *wl_callback, uint32_t time)
229 Q_UNUSED(wl_callback);
230 QWaylandWindow *self = static_cast<QWaylandWindow*>(data);
231 self->mWaitingForFrameSync = false;
232 if (self->mFrameCallback) {
233 wl_callback_destroy(self->mFrameCallback);
234 self->mFrameCallback = 0;
238 void QWaylandWindow::waitForFrameSync()
240 if (!mWaitingForFrameSync)
242 mDisplay->flushRequests();
243 while (mWaitingForFrameSync)
244 mDisplay->blockingReadEvents();
247 QMargins QWaylandWindow::frameMargins() const
249 if (mWindowDecoration)
250 return mWindowDecoration->margins();
251 return QPlatformWindow::frameMargins();
254 QWaylandShellSurface *QWaylandWindow::shellSurface() const
256 return mShellSurface;
259 QWaylandExtendedSurface *QWaylandWindow::extendedWindow() const
261 return mExtendedWindow;
264 QWaylandSubSurface *QWaylandWindow::subSurfaceWindow() const
266 return mSubSurfaceWindow;
269 void QWaylandWindow::handleContentOrientationChange(Qt::ScreenOrientation orientation)
272 mExtendedWindow->setContentOrientation(orientation);
275 Qt::ScreenOrientation QWaylandWindow::requestWindowOrientation(Qt::ScreenOrientation orientation)
277 if (mExtendedWindow) {
278 mExtendedWindow->setWindowOrientation(orientation);
282 return Qt::PrimaryOrientation;
285 Qt::WindowState QWaylandWindow::setWindowState(Qt::WindowState state)
287 if (state == Qt::WindowFullScreen || state == Qt::WindowMaximized) {
288 QScreen *screen = window()->screen();
290 QRect geometry = screen->mapBetween(window()->windowOrientation(), screen->primaryOrientation(), screen->geometry());
291 setGeometry(geometry);
293 QWindowSystemInterface::handleGeometryChange(window(), geometry);
298 return Qt::WindowNoState;
301 Qt::WindowFlags QWaylandWindow::setWindowFlags(Qt::WindowFlags flags)
304 return mExtendedWindow->setWindowFlags(flags);
305 return Qt::WindowFlags(0);
308 QWaylandDecoration *QWaylandWindow::decoration() const
310 return mWindowDecoration;
313 void QWaylandWindow::setDecoration(QWaylandDecoration *decoration)
315 mWindowDecoration = decoration;
316 if (subSurfaceWindow()) {
317 subSurfaceWindow()->adjustPositionOfChildren();
321 void QWaylandWindow::handleMouse(QWaylandInputDevice *inputDevice, ulong timestamp, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
323 if (mWindowDecoration) {
324 handleMouseEventWithDecoration(inputDevice, timestamp,local,global,b,mods);
328 QWindowSystemInterface::handleMouseEvent(window(),timestamp,local,global,b,mods);
331 void QWaylandWindow::handleMouseEnter()
333 if (!mWindowDecoration) {
334 QWindowSystemInterface::handleEnterEvent(window());
338 void QWaylandWindow::handleMouseLeave()
340 if (mWindowDecoration) {
341 if (mMouseEventsInContentArea) {
342 QWindowSystemInterface::handleLeaveEvent(window());
344 mWindowDecoration->restoreMouseCursor();
346 QWindowSystemInterface::handleLeaveEvent(window());
350 void QWaylandWindow::handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, ulong timestamp, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
352 if (mWindowDecoration->inMouseButtonPressedState()) {
353 mWindowDecoration->handleMouse(inputDevice,local,global,b,mods);
357 QPointF localTranslated = local;
358 QMargins marg = frameMargins();
359 QRect windowRect(0 + marg.left(),
361 geometry().size().width() - marg.right(),
362 geometry().size().height() - marg.bottom());
363 if (windowRect.contains(local.toPoint()) || mMousePressedInContentArea != Qt::NoButton) {
364 localTranslated.setX(localTranslated.x() - marg.left());
365 localTranslated.setY(localTranslated.y() - marg.top());
366 if (!mMouseEventsInContentArea) {
367 mWindowDecoration->restoreMouseCursor();
368 QWindowSystemInterface::handleEnterEvent(window());
370 QWindowSystemInterface::handleMouseEvent(window(),timestamp,localTranslated,global,b,mods);
371 mMouseEventsInContentArea = true;
372 mMousePressedInContentArea = b;
374 if (mMouseEventsInContentArea) {
375 QWindowSystemInterface::handleLeaveEvent(window());
376 mMouseEventsInContentArea = false;
378 mWindowDecoration->handleMouse(inputDevice,local,global,b,mods);