Revert "Suppress QWindowSystemInterface inclusion warnings."
[profile/ivi/qtwayland.git] / src / plugins / platforms / wayland / qwaylandwindow.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the config.tests of the Qt Toolkit.
7 **
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.
16 **
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.
20 **
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.
28 **
29 ** Other Usage
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.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qwaylandwindow.h"
43
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"
53
54 #include <QtGui/QWindow>
55
56 #ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT
57 #include "windowmanager_integration/qwaylandwindowmanagerintegration.h"
58 #endif
59
60 #include <QCoreApplication>
61 #include <QtGui/QWindowSystemInterface>
62
63 #include <QtCore/QDebug>
64
65 QWaylandWindow::QWaylandWindow(QWindow *window)
66     : QPlatformWindow(window)
67     , mDisplay(QWaylandScreen::waylandScreenFromWindow(window)->display())
68     , mSurface(mDisplay->createSurface(this))
69     , mShellSurface(0)
70     , mExtendedWindow(0)
71     , mSubSurfaceWindow(0)
72     , mWindowDecoration(0)
73     , mMouseEventsInContentArea(false)
74     , mMousePressedInContentArea(Qt::NoButton)
75     , mBuffer(0)
76     , mWaitingForFrameSync(false)
77     , mFrameCallback(0)
78     , mSentInitialResize(false)
79 {
80     static WId id = 1;
81     mWindowId = id++;
82
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);
89
90 #ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT
91     mDisplay->windowManagerIntegration()->mapClientToProcess(qApp->applicationPid());
92     mDisplay->windowManagerIntegration()->authenticateWithToken();
93 #endif
94
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());
100         }
101     } else {
102         mShellSurface->setTopLevel();
103     }
104
105     setWindowFlags(window->windowFlags());
106 }
107
108 QWaylandWindow::~QWaylandWindow()
109 {
110     if (mSurface) {
111         delete mShellSurface;
112         delete mExtendedWindow;
113         wl_surface_destroy(mSurface);
114     }
115
116     QList<QWaylandInputDevice *> inputDevices = mDisplay->inputDevices();
117     for (int i = 0; i < inputDevices.size(); ++i)
118         inputDevices.at(i)->handleWindowDestroyed(this);
119 }
120
121 WId QWaylandWindow::winId() const
122 {
123     return mWindowId;
124 }
125
126 void QWaylandWindow::setParent(const QPlatformWindow *parent)
127 {
128     const QWaylandWindow *parentWaylandWindow = static_cast<const QWaylandWindow *>(parent);
129     if (subSurfaceWindow()) {
130         subSurfaceWindow()->setParent(parentWaylandWindow);
131     }
132 }
133
134 void QWaylandWindow::setWindowTitle(const QString &title)
135 {
136     if (mShellSurface) {
137         QByteArray titleUtf8 = title.toUtf8();
138         mShellSurface->setTitle(titleUtf8.constData());
139     }
140     if (mWindowDecoration && window()->isVisible()) {
141         mWindowDecoration->paintDecoration();
142     }
143 }
144
145 void QWaylandWindow::setGeometry(const QRect &rect)
146 {
147     QPlatformWindow::setGeometry(rect);
148
149     if (shellSurface() && window()->transientParent())
150         shellSurface()->updateTransientParent(window()->transientParent());
151 }
152
153 void QWaylandWindow::setVisible(bool visible)
154 {
155
156     if (visible) {
157         if (mBuffer)
158             wl_surface_attach(mSurface, mBuffer->buffer(), 0, 0);
159
160         if (!mSentInitialResize) {
161             QWindowSystemInterface::handleSynchronousGeometryChange(window(), geometry());
162             mSentInitialResize = true;
163         }
164
165         QWindowSystemInterface::handleSynchronousExposeEvent(window(), QRect(QPoint(), geometry().size()));
166     } else {
167         QWindowSystemInterface::handleSynchronousExposeEvent(window(), QRect(QPoint(), geometry().size()));
168         wl_surface_attach(mSurface, 0,0,0);
169         damage(QRect(QPoint(0,0),geometry().size()));
170     }
171 }
172
173
174 bool QWaylandWindow::isExposed() const
175 {
176     if (!window()->isVisible())
177         return false;
178     if (mExtendedWindow)
179         return mExtendedWindow->isExposed();
180     return true;
181 }
182
183
184 void QWaylandWindow::configure(uint32_t edges, int32_t width, int32_t height)
185 {
186     Q_UNUSED(edges);
187
188     int widthWithoutMargins = qMax(width-(frameMargins().left() +frameMargins().right()),1);
189     int heightWithoutMargins = qMax(height-(frameMargins().top()+frameMargins().bottom()),1);
190
191     widthWithoutMargins = qMax(widthWithoutMargins, window()->minimumSize().width());
192     heightWithoutMargins = qMax(heightWithoutMargins, window()->minimumSize().height());
193     QRect geometry = QRect(0,0,
194                            widthWithoutMargins, heightWithoutMargins);
195     setGeometry(geometry);
196     QWindowSystemInterface::handleGeometryChange(window(), geometry);
197 }
198
199 void QWaylandWindow::attach(QWaylandBuffer *buffer)
200 {
201     mBuffer = buffer;
202
203     if (window()->isVisible()) {
204         wl_surface_attach(mSurface, mBuffer->buffer(),0,0);
205     }
206 }
207
208 QWaylandBuffer *QWaylandWindow::attached() const
209 {
210     return mBuffer;
211 }
212
213 void QWaylandWindow::damage(const QRect &rect)
214 {
215     //We have to do sync stuff before calling damage, or we might
216     //get a frame callback before we get the timestamp
217     if (!mWaitingForFrameSync) {
218         mFrameCallback = wl_surface_frame(mSurface);
219         wl_callback_add_listener(mFrameCallback,&QWaylandWindow::callbackListener,this);
220         mWaitingForFrameSync = true;
221     }
222
223     wl_surface_damage(mSurface,
224                       rect.x(), rect.y(), rect.width(), rect.height());
225 }
226
227 const wl_callback_listener QWaylandWindow::callbackListener = {
228     QWaylandWindow::frameCallback
229 };
230
231 void QWaylandWindow::frameCallback(void *data, struct wl_callback *callback, uint32_t time)
232 {
233     Q_UNUSED(time);
234     QWaylandWindow *self = static_cast<QWaylandWindow*>(data);
235     if (callback != self->mFrameCallback) // might be a callback caused by the shm backingstore
236         return;
237     self->mWaitingForFrameSync = false;
238     if (self->mFrameCallback) {
239         wl_callback_destroy(self->mFrameCallback);
240         self->mFrameCallback = 0;
241     }
242 }
243
244 void QWaylandWindow::waitForFrameSync()
245 {
246     if (!mWaitingForFrameSync)
247         return;
248     mDisplay->flushRequests();
249     while (mWaitingForFrameSync)
250         mDisplay->blockingReadEvents();
251 }
252
253 QMargins QWaylandWindow::frameMargins() const
254 {
255     if (mWindowDecoration)
256         return mWindowDecoration->margins();
257     return QPlatformWindow::frameMargins();
258 }
259
260 QWaylandShellSurface *QWaylandWindow::shellSurface() const
261 {
262     return mShellSurface;
263 }
264
265 QWaylandExtendedSurface *QWaylandWindow::extendedWindow() const
266 {
267     return mExtendedWindow;
268 }
269
270 QWaylandSubSurface *QWaylandWindow::subSurfaceWindow() const
271 {
272     return mSubSurfaceWindow;
273 }
274
275 void QWaylandWindow::handleContentOrientationChange(Qt::ScreenOrientation orientation)
276 {
277     if (mExtendedWindow)
278         mExtendedWindow->setContentOrientation(orientation);
279 }
280
281 Qt::ScreenOrientation QWaylandWindow::requestWindowOrientation(Qt::ScreenOrientation orientation)
282 {
283     if (mExtendedWindow) {
284         mExtendedWindow->setWindowOrientation(orientation);
285         return orientation;
286     }
287
288     return Qt::PrimaryOrientation;
289 }
290
291 Qt::WindowState QWaylandWindow::setWindowState(Qt::WindowState state)
292 {
293     if (state == Qt::WindowFullScreen || state == Qt::WindowMaximized) {
294         QScreen *screen = window()->screen();
295
296         QRect geometry = screen->mapBetween(window()->windowOrientation(), screen->primaryOrientation(), screen->geometry());
297         setGeometry(geometry);
298
299         QWindowSystemInterface::handleGeometryChange(window(), geometry);
300
301         return state;
302     }
303
304     return Qt::WindowNoState;
305 }
306
307 Qt::WindowFlags QWaylandWindow::setWindowFlags(Qt::WindowFlags flags)
308 {
309     if (mExtendedWindow)
310         return mExtendedWindow->setWindowFlags(flags);
311     return Qt::WindowFlags(0);
312 }
313
314 QWaylandDecoration *QWaylandWindow::decoration() const
315 {
316     return mWindowDecoration;
317 }
318
319 void QWaylandWindow::setDecoration(QWaylandDecoration *decoration)
320 {
321     mWindowDecoration = decoration;
322     if (subSurfaceWindow()) {
323         subSurfaceWindow()->adjustPositionOfChildren();
324     }
325 }
326
327 void QWaylandWindow::handleMouse(QWaylandInputDevice *inputDevice, ulong timestamp, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
328 {
329     if (mWindowDecoration) {
330         handleMouseEventWithDecoration(inputDevice, timestamp,local,global,b,mods);
331         return;
332     }
333
334     QWindowSystemInterface::handleMouseEvent(window(),timestamp,local,global,b,mods);
335 }
336
337 void QWaylandWindow::handleMouseEnter()
338 {
339     if (!mWindowDecoration) {
340         QWindowSystemInterface::handleEnterEvent(window());
341     }
342 }
343
344 void QWaylandWindow::handleMouseLeave()
345 {
346     if (mWindowDecoration) {
347         if (mMouseEventsInContentArea) {
348             QWindowSystemInterface::handleLeaveEvent(window());
349         }
350         mWindowDecoration->restoreMouseCursor();
351     } else {
352         QWindowSystemInterface::handleLeaveEvent(window());
353     }
354 }
355
356 void QWaylandWindow::handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, ulong timestamp, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
357 {
358     if (mWindowDecoration->inMouseButtonPressedState()) {
359         mWindowDecoration->handleMouse(inputDevice,local,global,b,mods);
360         return;
361     }
362
363     QMargins marg = frameMargins();
364     QRect windowRect(0 + marg.left(),
365                      0 + marg.top(),
366                      geometry().size().width() - marg.right(),
367                      geometry().size().height() - marg.bottom());
368     if (windowRect.contains(local.toPoint()) || mMousePressedInContentArea != Qt::NoButton) {
369         QPointF localTranslated = local;
370         QPointF globalTranslated = global;
371         localTranslated.setX(localTranslated.x() - marg.left());
372         localTranslated.setY(localTranslated.y() - marg.top());
373         globalTranslated.setX(globalTranslated.x() - marg.left());
374         globalTranslated.setY(globalTranslated.y() - marg.top());
375         if (!mMouseEventsInContentArea) {
376             mWindowDecoration->restoreMouseCursor();
377             QWindowSystemInterface::handleEnterEvent(window());
378         }
379         QWindowSystemInterface::handleMouseEvent(window(), timestamp, localTranslated, globalTranslated, b, mods);
380         mMouseEventsInContentArea = true;
381         mMousePressedInContentArea = b;
382     } else {
383         if (mMouseEventsInContentArea) {
384             QWindowSystemInterface::handleLeaveEvent(window());
385             mMouseEventsInContentArea = false;
386         }
387         mWindowDecoration->handleMouse(inputDevice,local,global,b,mods);
388     }
389 }