1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
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 The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
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 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qvncscreen.h"
41#include "qvnc_p.h"
42#include <QtFbSupport/private/qfbwindow_p.h>
43#include <QtFbSupport/private/qfbcursor_p.h>
44
45#include <QtGui/QPainter>
46#include <QtGui/QScreen>
47#include <QtCore/QRegularExpression>
48
49
50QT_BEGIN_NAMESPACE
51
52
53QVncScreen::QVncScreen(const QStringList &args)
54 : mArgs(args)
55{
56 initialize();
57}
58
59QVncScreen::~QVncScreen()
60{
61#if QT_CONFIG(cursor)
62 if (clientCursor)
63 delete clientCursor;
64#endif
65}
66
67bool QVncScreen::initialize()
68{
69 QRegularExpression sizeRx(QLatin1String("size=(\\d+)x(\\d+)"));
70 QRegularExpression mmSizeRx(QLatin1String("mmsize=(?<width>(\\d*\\.)?\\d+)x(?<height>(\\d*\\.)?\\d+)"));
71 QRegularExpression depthRx(QLatin1String("depth=(\\d+)"));
72
73 mGeometry = QRect(0, 0, 1024, 768);
74 mFormat = QImage::Format_ARGB32_Premultiplied;
75 mDepth = 32;
76 mPhysicalSize = QSizeF(mGeometry.width()/96.*25.4, mGeometry.height()/96.*25.4);
77
78 for (const QString &arg : qAsConst(mArgs)) {
79 QRegularExpressionMatch match;
80 if (arg.contains(mmSizeRx, &match)) {
81 mPhysicalSize = QSizeF(match.captured("width").toDouble(), match.captured("height").toDouble());
82 } else if (arg.contains(sizeRx, &match)) {
83 mGeometry.setSize(QSize(match.captured(1).toInt(), match.captured(2).toInt()));
84 } else if (arg.contains(depthRx, &match)) {
85 mDepth = match.captured(1).toInt();
86 }
87 }
88
89 QFbScreen::initializeCompositor();
90
91 switch (depth()) {
92 case 32:
93 dirty = new QVncDirtyMapOptimized<quint32>(this);
94 break;
95 case 16:
96 dirty = new QVncDirtyMapOptimized<quint16>(this);
97 break;
98 case 8:
99 dirty = new QVncDirtyMapOptimized<quint8>(this);
100 break;
101 default:
102 qWarning("QVNCScreen::initDevice: No support for screen depth %d",
103 depth());
104 dirty = nullptr;
105 return false;
106 }
107
108 setPowerState(PowerStateOff);
109
110 return true;
111}
112
113QRegion QVncScreen::doRedraw()
114{
115 QRegion touched = QFbScreen::doRedraw();
116
117 if (touched.isEmpty())
118 return touched;
119 dirtyRegion += touched;
120
121 vncServer->setDirty();
122 return touched;
123}
124
125
126void QVncScreen::enableClientCursor(QVncClient *client)
127{
128#if QT_CONFIG(cursor)
129 delete mCursor;
130 mCursor = nullptr;
131 if (!clientCursor)
132 clientCursor = new QVncClientCursor();
133 clientCursor->addClient(client);
134#else
135 Q_UNUSED(client);
136#endif
137}
138
139void QVncScreen::disableClientCursor(QVncClient *client)
140{
141#if QT_CONFIG(cursor)
142 if (!clientCursor)
143 return;
144
145 uint clientCount = clientCursor->removeClient(client);
146 if (clientCount == 0) {
147 delete clientCursor;
148 clientCursor = nullptr;
149 }
150
151 mCursor = new QFbCursor(this);
152#else
153 Q_UNUSED(client);
154#endif
155}
156
157QPlatformCursor *QVncScreen::cursor() const
158{
159#if QT_CONFIG(cursor)
160 return mCursor ? static_cast<QPlatformCursor *>(mCursor) : static_cast<QPlatformCursor *>(clientCursor);
161#else
162 return nullptr;
163#endif
164}
165
166// grabWindow() grabs "from the screen" not from the backingstores.
167// In linuxfb's case it will also include the mouse cursor.
168QPixmap QVncScreen::grabWindow(WId wid, int x, int y, int width, int height) const
169{
170 if (!wid) {
171 if (width < 0)
172 width = mScreenImage.width() - x;
173 if (height < 0)
174 height = mScreenImage.height() - y;
175 return QPixmap::fromImage(mScreenImage).copy(x, y, width, height);
176 }
177
178 QFbWindow *window = windowForId(wid);
179 if (window) {
180 const QRect geom = window->geometry();
181 if (width < 0)
182 width = geom.width() - x;
183 if (height < 0)
184 height = geom.height() - y;
185 QRect rect(geom.topLeft() + QPoint(x, y), QSize(width, height));
186 rect &= window->geometry();
187 return QPixmap::fromImage(mScreenImage).copy(rect);
188 }
189
190 return QPixmap();
191}
192
193#if Q_BYTE_ORDER == Q_BIG_ENDIAN
194bool QVncScreen::swapBytes() const
195{
196 return false;
197
198 /* TODO
199 if (depth() != 16)
200 return false;
201
202 if (screen())
203 return screen()->frameBufferLittleEndian();
204 return frameBufferLittleEndian();
205 */
206}
207#endif
208
209QFbScreen::Flags QVncScreen::flags() const
210{
211 return QFbScreen::DontForceFirstWindowToFullScreen;
212}
213
214QT_END_NAMESPACE
215
216