1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qvncscreen.h"
5#include "qvnc_p.h"
6#include <QtFbSupport/private/qfbwindow_p.h>
7#include <QtFbSupport/private/qfbcursor_p.h>
8
9#include <QtGui/QPainter>
10#include <QtGui/QScreen>
11#include <QtCore/QRegularExpression>
12
13
14QT_BEGIN_NAMESPACE
15
16using namespace Qt::StringLiterals;
17
18
19QVncScreen::QVncScreen(const QStringList &args)
20 : mArgs(args)
21{
22 initialize();
23}
24
25QVncScreen::~QVncScreen()
26{
27#if QT_CONFIG(cursor)
28 if (clientCursor)
29 delete clientCursor;
30#endif
31}
32
33bool QVncScreen::initialize()
34{
35 QRegularExpression sizeRx("size=(\\d+)x(\\d+)"_L1);
36 QRegularExpression mmSizeRx("mmsize=(?<width>(\\d*\\.)?\\d+)x(?<height>(\\d*\\.)?\\d+)"_L1);
37 QRegularExpression depthRx("depth=(\\d+)"_L1);
38
39 mGeometry = QRect(0, 0, 1024, 768);
40 mFormat = QImage::Format_ARGB32_Premultiplied;
41 mDepth = 32;
42 mPhysicalSize = QSizeF(mGeometry.width()/96.*25.4, mGeometry.height()/96.*25.4);
43
44 for (const QString &arg : std::as_const(t&: mArgs)) {
45 QRegularExpressionMatch match;
46 if (arg.contains(re: mmSizeRx, rmatch: &match)) {
47 mPhysicalSize = QSizeF(match.captured(name: "width").toDouble(), match.captured(name: "height").toDouble());
48 } else if (arg.contains(re: sizeRx, rmatch: &match)) {
49 mGeometry.setSize(QSize(match.captured(nth: 1).toInt(), match.captured(nth: 2).toInt()));
50 } else if (arg.contains(re: depthRx, rmatch: &match)) {
51 mDepth = match.captured(nth: 1).toInt();
52 }
53 }
54
55 switch (depth()) {
56 case 32:
57 dirty = new QVncDirtyMapOptimized<quint32>(this);
58 break;
59 case 16:
60 dirty = new QVncDirtyMapOptimized<quint16>(this);
61 mFormat = QImage::Format_RGB16;
62 break;
63 case 8:
64 dirty = new QVncDirtyMapOptimized<quint8>(this);
65 break;
66 default:
67 qWarning(msg: "QVNCScreen::initDevice: No support for screen depth %d",
68 depth());
69 dirty = nullptr;
70 return false;
71 }
72
73 QFbScreen::initializeCompositor();
74
75 setPowerState(PowerStateOff);
76
77 return true;
78}
79
80QRegion QVncScreen::doRedraw()
81{
82 QRegion touched = QFbScreen::doRedraw();
83
84 if (touched.isEmpty())
85 return touched;
86 dirtyRegion += touched;
87
88 vncServer->setDirty();
89 return touched;
90}
91
92
93void QVncScreen::enableClientCursor(QVncClient *client)
94{
95#if QT_CONFIG(cursor)
96 delete mCursor;
97 mCursor = nullptr;
98 if (!clientCursor)
99 clientCursor = new QVncClientCursor();
100 clientCursor->addClient(client);
101#else
102 Q_UNUSED(client);
103#endif
104}
105
106void QVncScreen::disableClientCursor(QVncClient *client)
107{
108#if QT_CONFIG(cursor)
109 if (!clientCursor)
110 return;
111
112 uint clientCount = clientCursor->removeClient(client);
113 if (clientCount == 0) {
114 delete clientCursor;
115 clientCursor = nullptr;
116
117 if (mCursor == nullptr)
118 mCursor = new QFbCursor(this);
119 }
120#else
121 Q_UNUSED(client);
122#endif
123}
124
125QPlatformCursor *QVncScreen::cursor() const
126{
127#if QT_CONFIG(cursor)
128 return mCursor ? static_cast<QPlatformCursor *>(mCursor) : static_cast<QPlatformCursor *>(clientCursor);
129#else
130 return nullptr;
131#endif
132}
133
134// grabWindow() grabs "from the screen" not from the backingstores.
135// In linuxfb's case it will also include the mouse cursor.
136QPixmap QVncScreen::grabWindow(WId wid, int x, int y, int width, int height) const
137{
138 if (!wid) {
139 if (width < 0)
140 width = mScreenImage.width() - x;
141 if (height < 0)
142 height = mScreenImage.height() - y;
143 return QPixmap::fromImage(image: mScreenImage).copy(ax: x, ay: y, awidth: width, aheight: height);
144 }
145
146 QFbWindow *window = windowForId(wid);
147 if (window) {
148 const QRect geom = window->geometry();
149 if (width < 0)
150 width = geom.width() - x;
151 if (height < 0)
152 height = geom.height() - y;
153 QRect rect(geom.topLeft() + QPoint(x, y), QSize(width, height));
154 rect &= window->geometry();
155 return QPixmap::fromImage(image: mScreenImage).copy(rect);
156 }
157
158 return QPixmap();
159}
160
161#if Q_BYTE_ORDER == Q_BIG_ENDIAN
162bool QVncScreen::swapBytes() const
163{
164 return false;
165
166 /* TODO
167 if (depth() != 16)
168 return false;
169
170 if (screen())
171 return screen()->frameBufferLittleEndian();
172 return frameBufferLittleEndian();
173 */
174}
175#endif
176
177QFbScreen::Flags QVncScreen::flags() const
178{
179 return QFbScreen::DontForceFirstWindowToFullScreen;
180}
181
182QT_END_NAMESPACE
183
184#include "moc_qvncscreen.cpp"
185
186

source code of qtbase/src/plugins/platforms/vnc/qvncscreen.cpp