QWindow::visible() -> QWindow::isVisible() compile fix
[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         } else {
101             mShellSurface->setTopLevel();
102         }
103     }
104 }
105
106 QWaylandWindow::~QWaylandWindow()
107 {
108     if (mSurface) {
109         delete mShellSurface;
110         delete mExtendedWindow;
111         wl_surface_destroy(mSurface);
112     }
113
114     QList<QWaylandInputDevice *> inputDevices = mDisplay->inputDevices();
115     for (int i = 0; i < inputDevices.size(); ++i)
116         inputDevices.at(i)->handleWindowDestroyed(this);
117 }
118
119 WId QWaylandWindow::winId() const
120 {
121     return mWindowId;
122 }
123
124 void QWaylandWindow::setParent(const QPlatformWindow *parent)
125 {
126     const QWaylandWindow *parentWaylandWindow = static_cast<const QWaylandWindow *>(parent);
127     if (subSurfaceWindow()) {
128         subSurfaceWindow()->setParent(parentWaylandWindow);
129     }
130 }
131
132 void QWaylandWindow::setWindowTitle(const QString &title)
133 {
134     Q_UNUSED(title);
135     if (mWindowDecoration && window()->isVisible()) {
136         mWindowDecoration->paintDecoration();
137     }
138 }
139
140 void QWaylandWindow::setGeometry(const QRect &rect)
141 {
142     QPlatformWindow::setGeometry(rect);
143
144     if (shellSurface() && window()->transientParent())
145         shellSurface()->updateTransientParent(window()->transientParent());
146 }
147
148 void QWaylandWindow::setVisible(bool visible)
149 {
150
151     if (visible) {
152         if (mBuffer)
153             wl_surface_attach(mSurface, mBuffer->buffer(), 0, 0);
154
155         if (!mSentInitialResize) {
156             QWindowSystemInterface::handleSynchronousGeometryChange(window(), geometry());
157             mSentInitialResize = true;
158         }
159
160         QWindowSystemInterface::handleSynchronousExposeEvent(window(), QRect(QPoint(), geometry().size()));
161     } else {
162         QWindowSystemInterface::handleSynchronousExposeEvent(window(), QRect(QPoint(), geometry().size()));
163         wl_surface_attach(mSurface, 0,0,0);
164         damage(QRect(QPoint(0,0),geometry().size()));
165     }
166 }
167
168
169 bool QWaylandWindow::isExposed() const
170 {
171     if (!window()->isVisible())
172         return false;
173     if (mExtendedWindow)
174         return mExtendedWindow->isExposed();
175     return true;
176 }
177
178
179 void QWaylandWindow::configure(uint32_t edges, int32_t width, int32_t height)
180 {
181     Q_UNUSED(edges);
182
183     int widthWithoutMargins = qMax(width-(frameMargins().left() +frameMargins().right()),1);
184     int heightWithoutMargins = qMax(height-(frameMargins().top()+frameMargins().bottom()),1);
185
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);
192 }
193
194 void QWaylandWindow::attach(QWaylandBuffer *buffer)
195 {
196     mBuffer = buffer;
197
198     if (window()->isVisible()) {
199         wl_surface_attach(mSurface, mBuffer->buffer(),0,0);
200     }
201 }
202
203 QWaylandBuffer *QWaylandWindow::attached() const
204 {
205     return mBuffer;
206 }
207
208 void QWaylandWindow::damage(const QRect &rect)
209 {
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;
216     }
217
218     wl_surface_damage(mSurface,
219                       rect.x(), rect.y(), rect.width(), rect.height());
220 }
221
222 const wl_callback_listener QWaylandWindow::callbackListener = {
223     QWaylandWindow::frameCallback
224 };
225
226 void QWaylandWindow::frameCallback(void *data, struct wl_callback *wl_callback, uint32_t time)
227 {
228     Q_UNUSED(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;
235     }
236 }
237
238 void QWaylandWindow::waitForFrameSync()
239 {
240     if (!mWaitingForFrameSync)
241         return;
242     mDisplay->flushRequests();
243     while (mWaitingForFrameSync)
244         mDisplay->blockingReadEvents();
245 }
246
247 QMargins QWaylandWindow::frameMargins() const
248 {
249     if (mWindowDecoration)
250         return mWindowDecoration->margins();
251     return QPlatformWindow::frameMargins();
252 }
253
254 QWaylandShellSurface *QWaylandWindow::shellSurface() const
255 {
256     return mShellSurface;
257 }
258
259 QWaylandExtendedSurface *QWaylandWindow::extendedWindow() const
260 {
261     return mExtendedWindow;
262 }
263
264 QWaylandSubSurface *QWaylandWindow::subSurfaceWindow() const
265 {
266     return mSubSurfaceWindow;
267 }
268
269 void QWaylandWindow::handleContentOrientationChange(Qt::ScreenOrientation orientation)
270 {
271     if (mExtendedWindow)
272         mExtendedWindow->setContentOrientation(orientation);
273 }
274
275 Qt::ScreenOrientation QWaylandWindow::requestWindowOrientation(Qt::ScreenOrientation orientation)
276 {
277     if (mExtendedWindow) {
278         mExtendedWindow->setWindowOrientation(orientation);
279         return orientation;
280     }
281
282     return Qt::PrimaryOrientation;
283 }
284
285 Qt::WindowState QWaylandWindow::setWindowState(Qt::WindowState state)
286 {
287     if (state == Qt::WindowFullScreen || state == Qt::WindowMaximized) {
288         QScreen *screen = window()->screen();
289
290         QRect geometry = screen->mapBetween(window()->windowOrientation(), screen->primaryOrientation(), screen->geometry());
291         setGeometry(geometry);
292
293         QWindowSystemInterface::handleGeometryChange(window(), geometry);
294
295         return state;
296     }
297
298     return Qt::WindowNoState;
299 }
300
301 Qt::WindowFlags QWaylandWindow::setWindowFlags(Qt::WindowFlags flags)
302 {
303     if (mExtendedWindow)
304         return mExtendedWindow->setWindowFlags(flags);
305     return Qt::WindowFlags(0);
306 }
307
308 QWaylandDecoration *QWaylandWindow::decoration() const
309 {
310     return mWindowDecoration;
311 }
312
313 void QWaylandWindow::setDecoration(QWaylandDecoration *decoration)
314 {
315     mWindowDecoration = decoration;
316     if (subSurfaceWindow()) {
317         subSurfaceWindow()->adjustPositionOfChildren();
318     }
319 }
320
321 void QWaylandWindow::handleMouse(QWaylandInputDevice *inputDevice, ulong timestamp, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
322 {
323     if (mWindowDecoration) {
324         handleMouseEventWithDecoration(inputDevice, timestamp,local,global,b,mods);
325         return;
326     }
327
328     QWindowSystemInterface::handleMouseEvent(window(),timestamp,local,global,b,mods);
329 }
330
331 void QWaylandWindow::handleMouseEnter()
332 {
333     if (!mWindowDecoration) {
334         QWindowSystemInterface::handleEnterEvent(window());
335     }
336 }
337
338 void QWaylandWindow::handleMouseLeave()
339 {
340     if (mWindowDecoration) {
341         if (mMouseEventsInContentArea) {
342             QWindowSystemInterface::handleLeaveEvent(window());
343         }
344         mWindowDecoration->restoreMouseCursor();
345     } else {
346         QWindowSystemInterface::handleLeaveEvent(window());
347     }
348 }
349
350 void QWaylandWindow::handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, ulong timestamp, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
351 {
352     if (mWindowDecoration->inMouseButtonPressedState()) {
353         mWindowDecoration->handleMouse(inputDevice,local,global,b,mods);
354         return;
355     }
356
357     QPointF localTranslated = local;
358     QMargins marg = frameMargins();
359     QRect windowRect(0 + marg.left(),
360                      0 + marg.top(),
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());
369         }
370         QWindowSystemInterface::handleMouseEvent(window(),timestamp,localTranslated,global,b,mods);
371         mMouseEventsInContentArea = true;
372         mMousePressedInContentArea = b;
373     } else {
374         if (mMouseEventsInContentArea) {
375             QWindowSystemInterface::handleLeaveEvent(window());
376             mMouseEventsInContentArea = false;
377         }
378         mWindowDecoration->handleMouse(inputDevice,local,global,b,mods);
379     }
380 }