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());
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::handleSynchronousGeometryChange(window(), geometry());
162 mSentInitialResize = true;
165 QWindowSystemInterface::handleSynchronousExposeEvent(window(), QRect(QPoint(), geometry().size()));
167 QWindowSystemInterface::handleSynchronousExposeEvent(window(), QRect(QPoint(), geometry().size()));
168 wl_surface_attach(mSurface, 0,0,0);
169 damage(QRect(QPoint(0,0),geometry().size()));
174 bool QWaylandWindow::isExposed() const
176 if (!window()->isVisible())
179 return mExtendedWindow->isExposed();
184 void QWaylandWindow::configure(uint32_t edges, int32_t width, int32_t height)
188 int widthWithoutMargins = qMax(width-(frameMargins().left() +frameMargins().right()),1);
189 int heightWithoutMargins = qMax(height-(frameMargins().top()+frameMargins().bottom()),1);
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);
199 void QWaylandWindow::attach(QWaylandBuffer *buffer)
203 if (window()->isVisible()) {
204 wl_surface_attach(mSurface, mBuffer->buffer(),0,0);
208 QWaylandBuffer *QWaylandWindow::attached() const
213 void QWaylandWindow::damage(const QRect &rect)
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;
223 wl_surface_damage(mSurface,
224 rect.x(), rect.y(), rect.width(), rect.height());
227 const wl_callback_listener QWaylandWindow::callbackListener = {
228 QWaylandWindow::frameCallback
231 void QWaylandWindow::frameCallback(void *data, struct wl_callback *callback, uint32_t time)
234 QWaylandWindow *self = static_cast<QWaylandWindow*>(data);
235 if (callback != self->mFrameCallback) // might be a callback caused by the shm backingstore
237 self->mWaitingForFrameSync = false;
238 if (self->mFrameCallback) {
239 wl_callback_destroy(self->mFrameCallback);
240 self->mFrameCallback = 0;
244 void QWaylandWindow::waitForFrameSync()
246 if (!mWaitingForFrameSync)
248 mDisplay->flushRequests();
249 while (mWaitingForFrameSync)
250 mDisplay->blockingReadEvents();
253 QMargins QWaylandWindow::frameMargins() const
255 if (mWindowDecoration)
256 return mWindowDecoration->margins();
257 return QPlatformWindow::frameMargins();
260 QWaylandShellSurface *QWaylandWindow::shellSurface() const
262 return mShellSurface;
265 QWaylandExtendedSurface *QWaylandWindow::extendedWindow() const
267 return mExtendedWindow;
270 QWaylandSubSurface *QWaylandWindow::subSurfaceWindow() const
272 return mSubSurfaceWindow;
275 void QWaylandWindow::handleContentOrientationChange(Qt::ScreenOrientation orientation)
278 mExtendedWindow->setContentOrientation(orientation);
281 Qt::ScreenOrientation QWaylandWindow::requestWindowOrientation(Qt::ScreenOrientation orientation)
283 if (mExtendedWindow) {
284 mExtendedWindow->setWindowOrientation(orientation);
288 return Qt::PrimaryOrientation;
291 Qt::WindowState QWaylandWindow::setWindowState(Qt::WindowState state)
293 if (state == Qt::WindowFullScreen || state == Qt::WindowMaximized) {
294 QScreen *screen = window()->screen();
296 QRect geometry = screen->mapBetween(window()->windowOrientation(), screen->primaryOrientation(), screen->geometry());
297 setGeometry(geometry);
299 QWindowSystemInterface::handleGeometryChange(window(), geometry);
304 return Qt::WindowNoState;
307 Qt::WindowFlags QWaylandWindow::setWindowFlags(Qt::WindowFlags flags)
310 return mExtendedWindow->setWindowFlags(flags);
311 return Qt::WindowFlags(0);
314 QWaylandDecoration *QWaylandWindow::decoration() const
316 return mWindowDecoration;
319 void QWaylandWindow::setDecoration(QWaylandDecoration *decoration)
321 mWindowDecoration = decoration;
322 if (subSurfaceWindow()) {
323 subSurfaceWindow()->adjustPositionOfChildren();
327 void QWaylandWindow::handleMouse(QWaylandInputDevice *inputDevice, ulong timestamp, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
329 if (mWindowDecoration) {
330 handleMouseEventWithDecoration(inputDevice, timestamp,local,global,b,mods);
334 QWindowSystemInterface::handleMouseEvent(window(),timestamp,local,global,b,mods);
337 void QWaylandWindow::handleMouseEnter()
339 if (!mWindowDecoration) {
340 QWindowSystemInterface::handleEnterEvent(window());
344 void QWaylandWindow::handleMouseLeave()
346 if (mWindowDecoration) {
347 if (mMouseEventsInContentArea) {
348 QWindowSystemInterface::handleLeaveEvent(window());
350 mWindowDecoration->restoreMouseCursor();
352 QWindowSystemInterface::handleLeaveEvent(window());
356 void QWaylandWindow::handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, ulong timestamp, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
358 if (mWindowDecoration->inMouseButtonPressedState()) {
359 mWindowDecoration->handleMouse(inputDevice,local,global,b,mods);
363 QMargins marg = frameMargins();
364 QRect windowRect(0 + marg.left(),
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());
379 QWindowSystemInterface::handleMouseEvent(window(), timestamp, localTranslated, globalTranslated, b, mods);
380 mMouseEventsInContentArea = true;
381 mMousePressedInContentArea = b;
383 if (mMouseEventsInContentArea) {
384 QWindowSystemInterface::handleLeaveEvent(window());
385 mMouseEventsInContentArea = false;
387 mWindowDecoration->handleMouse(inputDevice,local,global,b,mods);