1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the config.tests of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
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 <qpa/qwindowsysteminterface.h>
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());
102 mShellSurface->setTopLevel();
105 setWindowFlags(window->windowFlags());
108 QWaylandWindow::~QWaylandWindow()
111 delete mShellSurface;
112 delete mExtendedWindow;
113 wl_surface_destroy(mSurface);
116 QList<QWaylandInputDevice *> inputDevices = mDisplay->inputDevices();
117 for (int i = 0; i < inputDevices.size(); ++i)
118 inputDevices.at(i)->handleWindowDestroyed(this);
121 WId QWaylandWindow::winId() const
126 void QWaylandWindow::setParent(const QPlatformWindow *parent)
128 const QWaylandWindow *parentWaylandWindow = static_cast<const QWaylandWindow *>(parent);
129 if (subSurfaceWindow()) {
130 subSurfaceWindow()->setParent(parentWaylandWindow);
134 void QWaylandWindow::setWindowTitle(const QString &title)
137 QByteArray titleUtf8 = title.toUtf8();
138 mShellSurface->setTitle(titleUtf8.constData());
140 if (mWindowDecoration && window()->isVisible()) {
141 mWindowDecoration->paintDecoration();
145 void QWaylandWindow::setGeometry(const QRect &rect)
147 QPlatformWindow::setGeometry(rect);
149 if (shellSurface() && window()->transientParent())
150 shellSurface()->updateTransientParent(window()->transientParent());
153 void QWaylandWindow::setVisible(bool visible)
158 wl_surface_attach(mSurface, mBuffer->buffer(), 0, 0);
160 if (!mSentInitialResize) {
161 QWindowSystemInterface::handleGeometryChange(window(), geometry());
162 QWindowSystemInterface::flushWindowSystemEvents();
163 mSentInitialResize = true;
166 QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
167 QWindowSystemInterface::flushWindowSystemEvents();
169 QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
170 QWindowSystemInterface::flushWindowSystemEvents();
171 wl_surface_attach(mSurface, 0,0,0);
172 damage(QRect(QPoint(0,0),geometry().size()));
177 bool QWaylandWindow::isExposed() const
179 if (!window()->isVisible())
182 return mExtendedWindow->isExposed();
187 void QWaylandWindow::configure(uint32_t edges, int32_t width, int32_t height)
191 int widthWithoutMargins = qMax(width-(frameMargins().left() +frameMargins().right()),1);
192 int heightWithoutMargins = qMax(height-(frameMargins().top()+frameMargins().bottom()),1);
194 widthWithoutMargins = qMax(widthWithoutMargins, window()->minimumSize().width());
195 heightWithoutMargins = qMax(heightWithoutMargins, window()->minimumSize().height());
196 QRect geometry = QRect(0,0,
197 widthWithoutMargins, heightWithoutMargins);
198 setGeometry(geometry);
199 QWindowSystemInterface::handleGeometryChange(window(), geometry);
202 void QWaylandWindow::attach(QWaylandBuffer *buffer)
206 if (window()->isVisible()) {
207 wl_surface_attach(mSurface, mBuffer->buffer(),0,0);
211 QWaylandBuffer *QWaylandWindow::attached() const
216 void QWaylandWindow::damage(const QRect &rect)
218 //We have to do sync stuff before calling damage, or we might
219 //get a frame callback before we get the timestamp
220 if (!mWaitingForFrameSync) {
221 mFrameCallback = wl_surface_frame(mSurface);
222 wl_callback_add_listener(mFrameCallback,&QWaylandWindow::callbackListener,this);
223 mWaitingForFrameSync = true;
226 wl_surface_damage(mSurface,
227 rect.x(), rect.y(), rect.width(), rect.height());
230 const wl_callback_listener QWaylandWindow::callbackListener = {
231 QWaylandWindow::frameCallback
234 void QWaylandWindow::frameCallback(void *data, struct wl_callback *callback, uint32_t time)
237 QWaylandWindow *self = static_cast<QWaylandWindow*>(data);
238 if (callback != self->mFrameCallback) // might be a callback caused by the shm backingstore
240 self->mWaitingForFrameSync = false;
241 if (self->mFrameCallback) {
242 wl_callback_destroy(self->mFrameCallback);
243 self->mFrameCallback = 0;
247 void QWaylandWindow::waitForFrameSync()
249 if (!mWaitingForFrameSync)
251 mDisplay->flushRequests();
252 while (mWaitingForFrameSync)
253 mDisplay->blockingReadEvents();
256 QMargins QWaylandWindow::frameMargins() const
258 if (mWindowDecoration)
259 return mWindowDecoration->margins();
260 return QPlatformWindow::frameMargins();
263 QWaylandShellSurface *QWaylandWindow::shellSurface() const
265 return mShellSurface;
268 QWaylandExtendedSurface *QWaylandWindow::extendedWindow() const
270 return mExtendedWindow;
273 QWaylandSubSurface *QWaylandWindow::subSurfaceWindow() const
275 return mSubSurfaceWindow;
278 void QWaylandWindow::handleContentOrientationChange(Qt::ScreenOrientation orientation)
281 mExtendedWindow->setContentOrientation(orientation);
284 Qt::ScreenOrientation QWaylandWindow::requestWindowOrientation(Qt::ScreenOrientation orientation)
286 if (mExtendedWindow) {
287 mExtendedWindow->setWindowOrientation(orientation);
291 return Qt::PrimaryOrientation;
294 Qt::WindowState QWaylandWindow::setWindowState(Qt::WindowState state)
296 if (state == Qt::WindowFullScreen || state == Qt::WindowMaximized) {
297 QScreen *screen = window()->screen();
299 QRect geometry = screen->mapBetween(window()->windowOrientation(), screen->primaryOrientation(), screen->geometry());
300 setGeometry(geometry);
302 QWindowSystemInterface::handleGeometryChange(window(), geometry);
307 return Qt::WindowNoState;
310 void QWaylandWindow::setWindowFlags(Qt::WindowFlags flags)
313 mExtendedWindow->setWindowFlags(flags);
316 QWaylandDecoration *QWaylandWindow::decoration() const
318 return mWindowDecoration;
321 void QWaylandWindow::setDecoration(QWaylandDecoration *decoration)
323 mWindowDecoration = decoration;
324 if (subSurfaceWindow()) {
325 subSurfaceWindow()->adjustPositionOfChildren();
329 void QWaylandWindow::handleMouse(QWaylandInputDevice *inputDevice, ulong timestamp, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
331 if (mWindowDecoration) {
332 handleMouseEventWithDecoration(inputDevice, timestamp,local,global,b,mods);
336 QWindowSystemInterface::handleMouseEvent(window(),timestamp,local,global,b,mods);
339 void QWaylandWindow::handleMouseEnter()
341 if (!mWindowDecoration) {
342 QWindowSystemInterface::handleEnterEvent(window());
346 void QWaylandWindow::handleMouseLeave()
348 if (mWindowDecoration) {
349 if (mMouseEventsInContentArea) {
350 QWindowSystemInterface::handleLeaveEvent(window());
352 mWindowDecoration->restoreMouseCursor();
354 QWindowSystemInterface::handleLeaveEvent(window());
358 void QWaylandWindow::handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, ulong timestamp, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
360 if (mWindowDecoration->inMouseButtonPressedState()) {
361 mWindowDecoration->handleMouse(inputDevice,local,global,b,mods);
365 QMargins marg = frameMargins();
366 QRect windowRect(0 + marg.left(),
368 geometry().size().width() - marg.right(),
369 geometry().size().height() - marg.bottom());
370 if (windowRect.contains(local.toPoint()) || mMousePressedInContentArea != Qt::NoButton) {
371 QPointF localTranslated = local;
372 QPointF globalTranslated = global;
373 localTranslated.setX(localTranslated.x() - marg.left());
374 localTranslated.setY(localTranslated.y() - marg.top());
375 globalTranslated.setX(globalTranslated.x() - marg.left());
376 globalTranslated.setY(globalTranslated.y() - marg.top());
377 if (!mMouseEventsInContentArea) {
378 mWindowDecoration->restoreMouseCursor();
379 QWindowSystemInterface::handleEnterEvent(window());
381 QWindowSystemInterface::handleMouseEvent(window(), timestamp, localTranslated, globalTranslated, b, mods);
382 mMouseEventsInContentArea = true;
383 mMousePressedInContentArea = b;
385 if (mMouseEventsInContentArea) {
386 QWindowSystemInterface::handleLeaveEvent(window());
387 mMouseEventsInContentArea = false;
389 mWindowDecoration->handleMouse(inputDevice,local,global,b,mods);