mirror of
https://github.com/KDE/krfb
synced 2026-07-01 07:41:17 -07:00
Add and make use of ECM clang-format integration
This formats the code according to the KDE coding style and ensures it stays that way
This commit is contained in:
@@ -24,6 +24,8 @@ include(ECMQtDeclareLoggingCategory)
|
|||||||
include(ECMDeprecationSettings)
|
include(ECMDeprecationSettings)
|
||||||
include(FeatureSummary)
|
include(FeatureSummary)
|
||||||
include(CheckIncludeFile)
|
include(CheckIncludeFile)
|
||||||
|
include(KDEClangFormat)
|
||||||
|
include(KDEGitCommitHooks)
|
||||||
|
|
||||||
check_include_file("linux/input.h" HAVE_LINUX_INPUT_H)
|
check_include_file("linux/input.h" HAVE_LINUX_INPUT_H)
|
||||||
|
|
||||||
@@ -112,4 +114,9 @@ ecm_qt_install_logging_categories(
|
|||||||
DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR}
|
DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
file(GLOB_RECURSE ALL_CLANG_FORMAT_SOURCE_FILES *.cpp *.h)
|
||||||
|
kde_clang_format(${ALL_CLANG_FORMAT_SOURCE_FILES})
|
||||||
|
|
||||||
|
kde_configure_git_pre_commit_hook(CHECKS CLANG_FORMAT)
|
||||||
|
|
||||||
feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES)
|
feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES)
|
||||||
|
|||||||
@@ -13,13 +13,13 @@
|
|||||||
#include <QtGui/private/qtx11extras_p.h>
|
#include <QtGui/private/qtx11extras_p.h>
|
||||||
|
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
#include <X11/keysym.h>
|
|
||||||
#include <X11/extensions/XTest.h>
|
#include <X11/extensions/XTest.h>
|
||||||
|
#include <X11/keysym.h>
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
LEFTSHIFT = 1,
|
LEFTSHIFT = 1,
|
||||||
RIGHTSHIFT = 2,
|
RIGHTSHIFT = 2,
|
||||||
ALTGR = 4
|
ALTGR = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
class EventData
|
class EventData
|
||||||
@@ -27,7 +27,7 @@ class EventData
|
|||||||
public:
|
public:
|
||||||
EventData();
|
EventData();
|
||||||
|
|
||||||
//keyboard
|
// keyboard
|
||||||
Display *dpy = nullptr;
|
Display *dpy = nullptr;
|
||||||
signed char modifiers[0x100] = {};
|
signed char modifiers[0x100] = {};
|
||||||
KeyCode keycodes[0x100] = {};
|
KeyCode keycodes[0x100] = {};
|
||||||
@@ -36,7 +36,7 @@ public:
|
|||||||
KeyCode altGrCode = 0;
|
KeyCode altGrCode = 0;
|
||||||
char modifierState = 0;
|
char modifierState = 0;
|
||||||
|
|
||||||
//mouse
|
// mouse
|
||||||
int buttonMask = 0;
|
int buttonMask = 0;
|
||||||
int x = 0;
|
int x = 0;
|
||||||
int y = 0;
|
int y = 0;
|
||||||
@@ -57,7 +57,7 @@ void EventData::init()
|
|||||||
buttonMask = 0;
|
buttonMask = 0;
|
||||||
|
|
||||||
dpy = QX11Info::display();
|
dpy = QX11Info::display();
|
||||||
//initialize keycodes
|
// initialize keycodes
|
||||||
KeySym key, *keymap;
|
KeySym key, *keymap;
|
||||||
int i, j, minkey, maxkey, syms_per_keycode;
|
int i, j, minkey, maxkey, syms_per_keycode;
|
||||||
|
|
||||||
@@ -66,14 +66,12 @@ void EventData::init()
|
|||||||
XDisplayKeycodes(dpy, &minkey, &maxkey);
|
XDisplayKeycodes(dpy, &minkey, &maxkey);
|
||||||
Q_ASSERT(minkey >= 8);
|
Q_ASSERT(minkey >= 8);
|
||||||
Q_ASSERT(maxkey < 256);
|
Q_ASSERT(maxkey < 256);
|
||||||
keymap = (KeySym *) XGetKeyboardMapping(dpy, minkey,
|
keymap = (KeySym *)XGetKeyboardMapping(dpy, minkey, (maxkey - minkey + 1), &syms_per_keycode);
|
||||||
(maxkey - minkey + 1),
|
|
||||||
&syms_per_keycode);
|
|
||||||
Q_ASSERT(keymap);
|
Q_ASSERT(keymap);
|
||||||
|
|
||||||
for (i = minkey; i <= maxkey; i++) {
|
for (i = minkey; i <= maxkey; i++) {
|
||||||
for (j = 0; j < syms_per_keycode; j++) {
|
for (j = 0; j < syms_per_keycode; j++) {
|
||||||
key = keymap[(i-minkey)*syms_per_keycode+j];
|
key = keymap[(i - minkey) * syms_per_keycode + j];
|
||||||
|
|
||||||
if (key >= ' ' && key < 0x100 && i == XKeysymToKeycode(dpy, key)) {
|
if (key >= ' ' && key < 0x100 && i == XKeysymToKeycode(dpy, key)) {
|
||||||
keycodes[key] = i;
|
keycodes[key] = i;
|
||||||
@@ -100,36 +98,36 @@ static void tweakModifiers(signed char mod, bool down)
|
|||||||
|
|
||||||
if (isShift && mod != 1) {
|
if (isShift && mod != 1) {
|
||||||
if (data->modifierState & LEFTSHIFT) {
|
if (data->modifierState & LEFTSHIFT) {
|
||||||
XTestFakeKeyEvent(data->dpy, data->leftShiftCode,
|
XTestFakeKeyEvent(data->dpy, data->leftShiftCode, down, CurrentTime);
|
||||||
down, CurrentTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->modifierState & RIGHTSHIFT) {
|
if (data->modifierState & RIGHTSHIFT) {
|
||||||
XTestFakeKeyEvent(data->dpy, data->rightShiftCode,
|
XTestFakeKeyEvent(data->dpy, data->rightShiftCode, down, CurrentTime);
|
||||||
down, CurrentTime);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isShift && mod == 1) {
|
if (!isShift && mod == 1) {
|
||||||
XTestFakeKeyEvent(data->dpy, data->leftShiftCode,
|
XTestFakeKeyEvent(data->dpy, data->leftShiftCode, down, CurrentTime);
|
||||||
down, CurrentTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((data->modifierState & ALTGR) && mod != 2) {
|
if ((data->modifierState & ALTGR) && mod != 2) {
|
||||||
XTestFakeKeyEvent(data->dpy, data->altGrCode,
|
XTestFakeKeyEvent(data->dpy, data->altGrCode, !down, CurrentTime);
|
||||||
!down, CurrentTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(data->modifierState & ALTGR) && mod == 2) {
|
if (!(data->modifierState & ALTGR) && mod == 2) {
|
||||||
XTestFakeKeyEvent(data->dpy, data->altGrCode,
|
XTestFakeKeyEvent(data->dpy, data->altGrCode, down, CurrentTime);
|
||||||
down, CurrentTime);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void X11EventHandler::handleKeyboard(bool down, rfbKeySym keySym)
|
void X11EventHandler::handleKeyboard(bool down, rfbKeySym keySym)
|
||||||
{
|
{
|
||||||
#define ADJUSTMOD(sym,state) \
|
#define ADJUSTMOD(sym, state) \
|
||||||
if(keySym==sym) { if(down) data->modifierState|=state; else data->modifierState&=~state; }
|
if (keySym == sym) { \
|
||||||
|
if (down) \
|
||||||
|
data->modifierState |= state; \
|
||||||
|
else \
|
||||||
|
data->modifierState &= ~state; \
|
||||||
|
}
|
||||||
|
|
||||||
if (QX11Info::isPlatformX11()) {
|
if (QX11Info::isPlatformX11()) {
|
||||||
ADJUSTMOD(XK_Shift_L, LEFTSHIFT);
|
ADJUSTMOD(XK_Shift_L, LEFTSHIFT);
|
||||||
@@ -160,11 +158,11 @@ void X11EventHandler::handleKeyboard(bool down, rfbKeySym keySym)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
// Wayland platform and pipweire plugin in use
|
// Wayland platform and pipweire plugin in use
|
||||||
if (KrfbConfig::preferredFrameBufferPlugin() == QStringLiteral("pw")) {
|
if (KrfbConfig::preferredFrameBufferPlugin() == QStringLiteral("pw")) {
|
||||||
|
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void X11EventHandler::handlePointer(int buttonMask, int x, int y)
|
void X11EventHandler::handlePointer(int buttonMask, int x, int y)
|
||||||
@@ -173,11 +171,8 @@ void X11EventHandler::handlePointer(int buttonMask, int x, int y)
|
|||||||
XTestFakeMotionEvent(data->dpy, 0, x, y, CurrentTime);
|
XTestFakeMotionEvent(data->dpy, 0, x, y, CurrentTime);
|
||||||
|
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
if ((data->buttonMask&(1 << i)) != (buttonMask&(1 << i))) {
|
if ((data->buttonMask & (1 << i)) != (buttonMask & (1 << i))) {
|
||||||
XTestFakeButtonEvent(data->dpy,
|
XTestFakeButtonEvent(data->dpy, i + 1, (buttonMask & (1 << i)) ? True : False, CurrentTime);
|
||||||
i + 1,
|
|
||||||
(buttonMask&(1 << i)) ? True : False,
|
|
||||||
CurrentTime);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,13 +16,10 @@ class X11EventHandler : public EventHandler
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit X11EventHandler(QObject *parent = nullptr)
|
explicit X11EventHandler(QObject *parent = nullptr)
|
||||||
: EventHandler(parent)
|
: EventHandler(parent) {};
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
void handleKeyboard(bool down, rfbKeySym key) override;
|
void handleKeyboard(bool down, rfbKeySym key) override;
|
||||||
void handlePointer(int buttonMask, int x, int y) override;
|
void handlePointer(int buttonMask, int x, int y) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -22,11 +22,10 @@ X11EventsPlugin::X11EventsPlugin(QObject *parent, const QVariantList &args)
|
|||||||
EventHandler *X11EventsPlugin::eventHandler()
|
EventHandler *X11EventsPlugin::eventHandler()
|
||||||
{
|
{
|
||||||
// works only under X11
|
// works only under X11
|
||||||
if(!QX11Info::isPlatformX11())
|
if (!QX11Info::isPlatformX11())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
return new X11EventHandler();
|
return new X11EventHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "x11eventsplugin.moc"
|
#include "x11eventsplugin.moc"
|
||||||
|
|
||||||
|
|||||||
@@ -25,5 +25,4 @@ private:
|
|||||||
Q_DISABLE_COPY(X11EventsPlugin)
|
Q_DISABLE_COPY(X11EventsPlugin)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // Header guard
|
||||||
#endif // Header guard
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class EventData
|
|||||||
public:
|
public:
|
||||||
EventData();
|
EventData();
|
||||||
|
|
||||||
//mouse
|
// mouse
|
||||||
int buttonMask = 0;
|
int buttonMask = 0;
|
||||||
int x = 0;
|
int x = 0;
|
||||||
int y = 0;
|
int y = 0;
|
||||||
@@ -42,7 +42,8 @@ EventData::EventData()
|
|||||||
void EventData::init()
|
void EventData::init()
|
||||||
{
|
{
|
||||||
dbusXdpRemoteDesktopService.reset(new OrgFreedesktopPortalRemoteDesktopInterface(QStringLiteral("org.freedesktop.portal.Desktop"),
|
dbusXdpRemoteDesktopService.reset(new OrgFreedesktopPortalRemoteDesktopInterface(QStringLiteral("org.freedesktop.portal.Desktop"),
|
||||||
QStringLiteral("/org/freedesktop/portal/desktop"), QDBusConnection::sessionBus()));
|
QStringLiteral("/org/freedesktop/portal/desktop"),
|
||||||
|
QDBusConnection::sessionBus()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void XdpEventHandler::handleKeyboard(bool down, rfbKeySym keySym)
|
void XdpEventHandler::handleKeyboard(bool down, rfbKeySym keySym)
|
||||||
@@ -68,7 +69,7 @@ void XdpEventHandler::handlePointer(int buttonMask, int x, int y)
|
|||||||
|
|
||||||
if (buttonMask != data->buttonMask) {
|
if (buttonMask != data->buttonMask) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
QList<int> buttons = { BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, 0, 0, 0, 0, BTN_SIDE, BTN_EXTRA };
|
QList<int> buttons = {BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, 0, 0, 0, 0, BTN_SIDE, BTN_EXTRA};
|
||||||
for (auto it = buttons.constBegin(); it != buttons.constEnd(); ++it) {
|
for (auto it = buttons.constBegin(); it != buttons.constEnd(); ++it) {
|
||||||
int prevButtonState = (data->buttonMask >> i) & 0x01;
|
int prevButtonState = (data->buttonMask >> i) & 0x01;
|
||||||
int currentButtonState = (buttonMask >> i) & 0x01;
|
int currentButtonState = (buttonMask >> i) & 0x01;
|
||||||
@@ -81,22 +82,22 @@ void XdpEventHandler::handlePointer(int buttonMask, int x, int y)
|
|||||||
int steps = 0;
|
int steps = 0;
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 3:
|
case 3:
|
||||||
axis = 0; // Vertical
|
axis = 0; // Vertical
|
||||||
steps = -1;
|
steps = -1;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
axis = 0; // Vertical
|
axis = 0; // Vertical
|
||||||
steps = 1;
|
steps = 1;
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
axis = 1; // Horizontal
|
axis = 1; // Horizontal
|
||||||
steps = -1;
|
steps = -1;
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
axis = 1; // Horizontal
|
axis = 1; // Horizontal
|
||||||
steps = 1;
|
steps = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
data->dbusXdpRemoteDesktopService->NotifyPointerAxisDiscrete(sessionHandle, QVariantMap(), axis, steps);
|
data->dbusXdpRemoteDesktopService->NotifyPointerAxisDiscrete(sessionHandle, QVariantMap(), axis, steps);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,5 +20,3 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -26,4 +26,3 @@ EventHandler *XdpEventsPlugin::eventHandler()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#include "xdpeventsplugin.moc"
|
#include "xdpeventsplugin.moc"
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,4 @@ private:
|
|||||||
Q_DISABLE_COPY(XdpEventsPlugin)
|
Q_DISABLE_COPY(XdpEventsPlugin)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // Header guard
|
||||||
#endif // Header guard
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,16 +8,16 @@
|
|||||||
#include "config-krfb.h"
|
#include "config-krfb.h"
|
||||||
|
|
||||||
// system
|
// system
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
// Qt
|
// Qt
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
#include <QDebug>
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
|
#include <QRandomGenerator>
|
||||||
#include <QScreen>
|
#include <QScreen>
|
||||||
#include <QSocketNotifier>
|
#include <QSocketNotifier>
|
||||||
#include <QDebug>
|
|
||||||
#include <QRandomGenerator>
|
|
||||||
|
|
||||||
#include <KConfigGroup>
|
#include <KConfigGroup>
|
||||||
#include <KSharedConfig>
|
#include <KSharedConfig>
|
||||||
@@ -28,13 +28,13 @@
|
|||||||
// pipewire
|
// pipewire
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
|
||||||
#include "pw_framebuffer.h"
|
|
||||||
#include "xdp_dbus_screencast_interface.h"
|
|
||||||
#include "xdp_dbus_remotedesktop_interface.h"
|
|
||||||
#include "krfb_fb_pipewire_debug.h"
|
#include "krfb_fb_pipewire_debug.h"
|
||||||
|
#include "pw_framebuffer.h"
|
||||||
#include "screencasting.h"
|
#include "screencasting.h"
|
||||||
#include <PipeWireSourceStream>
|
#include "xdp_dbus_remotedesktop_interface.h"
|
||||||
|
#include "xdp_dbus_screencast_interface.h"
|
||||||
#include <DmaBufHandler>
|
#include <DmaBufHandler>
|
||||||
|
#include <PipeWireSourceStream>
|
||||||
|
|
||||||
static const int BYTES_PER_PIXEL = 4;
|
static const int BYTES_PER_PIXEL = 4;
|
||||||
static const uint MIN_SUPPORTED_XDP_KDE_SC_VERSION = 1;
|
static const uint MIN_SUPPORTED_XDP_KDE_SC_VERSION = 1;
|
||||||
@@ -42,7 +42,7 @@ static const uint MIN_SUPPORTED_XDP_KDE_SC_VERSION = 1;
|
|||||||
Q_DECLARE_METATYPE(PWFrameBuffer::Stream);
|
Q_DECLARE_METATYPE(PWFrameBuffer::Stream);
|
||||||
Q_DECLARE_METATYPE(PWFrameBuffer::Streams);
|
Q_DECLARE_METATYPE(PWFrameBuffer::Streams);
|
||||||
|
|
||||||
const QDBusArgument &operator >> (const QDBusArgument &arg, PWFrameBuffer::Stream &stream)
|
const QDBusArgument &operator>>(const QDBusArgument &arg, PWFrameBuffer::Stream &stream)
|
||||||
{
|
{
|
||||||
arg.beginStructure();
|
arg.beginStructure();
|
||||||
arg >> stream.nodeId;
|
arg >> stream.nodeId;
|
||||||
@@ -66,7 +66,8 @@ const QDBusArgument &operator >> (const QDBusArgument &arg, PWFrameBuffer::Strea
|
|||||||
* @brief The PWFrameBuffer::Private class - private counterpart of PWFramebuffer class. This is the entity where
|
* @brief The PWFrameBuffer::Private class - private counterpart of PWFramebuffer class. This is the entity where
|
||||||
* whole logic resides, for more info search for "d-pointer pattern" information.
|
* whole logic resides, for more info search for "d-pointer pattern" information.
|
||||||
*/
|
*/
|
||||||
class PWFrameBuffer::Private {
|
class PWFrameBuffer::Private
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
Private(PWFrameBuffer *q);
|
Private(PWFrameBuffer *q);
|
||||||
~Private();
|
~Private();
|
||||||
@@ -111,7 +112,7 @@ PWFrameBuffer::Private::Private(PWFrameBuffer *q)
|
|||||||
: q(q)
|
: q(q)
|
||||||
, stream(new PipeWireSourceStream(q))
|
, stream(new PipeWireSourceStream(q))
|
||||||
{
|
{
|
||||||
QObject::connect(stream.get(), &PipeWireSourceStream::frameReceived, q, [this] (const PipeWireFrame &frame) {
|
QObject::connect(stream.get(), &PipeWireSourceStream::frameReceived, q, [this](const PipeWireFrame &frame) {
|
||||||
handleFrame(frame);
|
handleFrame(frame);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -125,11 +126,11 @@ void PWFrameBuffer::Private::initDbus()
|
|||||||
{
|
{
|
||||||
qInfo() << "Initializing D-Bus connectivity with XDG Desktop Portal";
|
qInfo() << "Initializing D-Bus connectivity with XDG Desktop Portal";
|
||||||
dbusXdpScreenCastService.reset(new OrgFreedesktopPortalScreenCastInterface(QStringLiteral("org.freedesktop.portal.Desktop"),
|
dbusXdpScreenCastService.reset(new OrgFreedesktopPortalScreenCastInterface(QStringLiteral("org.freedesktop.portal.Desktop"),
|
||||||
QStringLiteral("/org/freedesktop/portal/desktop"),
|
QStringLiteral("/org/freedesktop/portal/desktop"),
|
||||||
QDBusConnection::sessionBus()));
|
QDBusConnection::sessionBus()));
|
||||||
dbusXdpRemoteDesktopService.reset(new OrgFreedesktopPortalRemoteDesktopInterface(QStringLiteral("org.freedesktop.portal.Desktop"),
|
dbusXdpRemoteDesktopService.reset(new OrgFreedesktopPortalRemoteDesktopInterface(QStringLiteral("org.freedesktop.portal.Desktop"),
|
||||||
QStringLiteral("/org/freedesktop/portal/desktop"),
|
QStringLiteral("/org/freedesktop/portal/desktop"),
|
||||||
QDBusConnection::sessionBus()));
|
QDBusConnection::sessionBus()));
|
||||||
auto version = dbusXdpScreenCastService->version();
|
auto version = dbusXdpScreenCastService->version();
|
||||||
if (version < MIN_SUPPORTED_XDP_KDE_SC_VERSION) {
|
if (version < MIN_SUPPORTED_XDP_KDE_SC_VERSION) {
|
||||||
qCWarning(KRFB_FB_PIPEWIRE) << "Unsupported XDG Portal screencast interface version:" << version;
|
qCWarning(KRFB_FB_PIPEWIRE) << "Unsupported XDG Portal screencast interface version:" << version;
|
||||||
@@ -138,10 +139,8 @@ void PWFrameBuffer::Private::initDbus()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create session
|
// create session
|
||||||
auto sessionParameters = QVariantMap {
|
auto sessionParameters = QVariantMap{{QStringLiteral("session_handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate())},
|
||||||
{ QStringLiteral("session_handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate()) },
|
{QStringLiteral("handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate())}};
|
||||||
{ QStringLiteral("handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate()) }
|
|
||||||
};
|
|
||||||
auto sessionReply = dbusXdpRemoteDesktopService->CreateSession(sessionParameters);
|
auto sessionReply = dbusXdpRemoteDesktopService->CreateSession(sessionParameters);
|
||||||
sessionReply.waitForFinished();
|
sessionReply.waitForFinished();
|
||||||
if (!sessionReply.isValid()) {
|
if (!sessionReply.isValid()) {
|
||||||
@@ -182,11 +181,11 @@ void PWFrameBuffer::Private::handleSessionCreated(quint32 code, const QVariantMa
|
|||||||
sessionPath = QDBusObjectPath(results.value(QStringLiteral("session_handle")).toString());
|
sessionPath = QDBusObjectPath(results.value(QStringLiteral("session_handle")).toString());
|
||||||
|
|
||||||
// select sources for the session
|
// select sources for the session
|
||||||
auto selectionOptions = QVariantMap {
|
auto selectionOptions = QVariantMap{
|
||||||
// We have to specify it's an uint, otherwise xdg-desktop-portal will not forward it to backend implementation
|
// We have to specify it's an uint, otherwise xdg-desktop-portal will not forward it to backend implementation
|
||||||
{ QStringLiteral("types"), QVariant::fromValue<uint>(7) }, // request all (KeyBoard, Pointer, TouchScreen)
|
{QStringLiteral("types"), QVariant::fromValue<uint>(7)}, // request all (KeyBoard, Pointer, TouchScreen)
|
||||||
{ QStringLiteral("handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate()) },
|
{QStringLiteral("handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate())},
|
||||||
{ QStringLiteral("persist_mode"), QVariant::fromValue<uint>(2) }, // Persist permission until explicitly revoked by user
|
{QStringLiteral("persist_mode"), QVariant::fromValue<uint>(2)}, // Persist permission until explicitly revoked by user
|
||||||
};
|
};
|
||||||
|
|
||||||
KConfigGroup stateConfig = KSharedConfig::openStateConfig()->group(QStringLiteral("XdgPortal"));
|
KConfigGroup stateConfig = KSharedConfig::openStateConfig()->group(QStringLiteral("XdgPortal"));
|
||||||
@@ -231,11 +230,9 @@ void PWFrameBuffer::Private::handleDevicesSelected(quint32 code, const QVariantM
|
|||||||
}
|
}
|
||||||
|
|
||||||
// select sources for the session
|
// select sources for the session
|
||||||
auto selectionOptions = QVariantMap {
|
auto selectionOptions = QVariantMap{{QStringLiteral("types"), QVariant::fromValue<uint>(1)}, // only MONITOR is supported
|
||||||
{ QStringLiteral("types"), QVariant::fromValue<uint>(1) }, // only MONITOR is supported
|
{QStringLiteral("multiple"), false},
|
||||||
{ QStringLiteral("multiple"), false },
|
{QStringLiteral("handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate())}};
|
||||||
{ QStringLiteral("handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate()) }
|
|
||||||
};
|
|
||||||
auto selectorReply = dbusXdpScreenCastService->SelectSources(sessionPath, selectionOptions);
|
auto selectorReply = dbusXdpScreenCastService->SelectSources(sessionPath, selectionOptions);
|
||||||
selectorReply.waitForFinished();
|
selectorReply.waitForFinished();
|
||||||
if (!selectorReply.isValid()) {
|
if (!selectorReply.isValid()) {
|
||||||
@@ -273,9 +270,7 @@ void PWFrameBuffer::Private::handleSourcesSelected(quint32 code, const QVariantM
|
|||||||
}
|
}
|
||||||
|
|
||||||
// start session
|
// start session
|
||||||
auto startParameters = QVariantMap {
|
auto startParameters = QVariantMap{{QStringLiteral("handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate())}};
|
||||||
{ QStringLiteral("handle_token"), QStringLiteral("krfb%1").arg(QRandomGenerator::global()->generate()) }
|
|
||||||
};
|
|
||||||
auto startReply = dbusXdpRemoteDesktopService->Start(sessionPath, QString(), startParameters);
|
auto startReply = dbusXdpRemoteDesktopService->Start(sessionPath, QString(), startParameters);
|
||||||
startReply.waitForFinished();
|
startReply.waitForFinished();
|
||||||
QDBusConnection::sessionBus().connect(QString(),
|
QDBusConnection::sessionBus().connect(QString(),
|
||||||
@@ -286,7 +281,6 @@ void PWFrameBuffer::Private::handleSourcesSelected(quint32 code, const QVariantM
|
|||||||
SLOT(handleXdpRemoteDesktopStarted(uint, QVariantMap)));
|
SLOT(handleXdpRemoteDesktopStarted(uint, QVariantMap)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PWFrameBuffer::handleXdpRemoteDesktopStarted(quint32 code, const QVariantMap &results)
|
void PWFrameBuffer::handleXdpRemoteDesktopStarted(quint32 code, const QVariantMap &results)
|
||||||
{
|
{
|
||||||
d->handleRemoteDesktopStarted(code, results);
|
d->handleRemoteDesktopStarted(code, results);
|
||||||
@@ -376,9 +370,9 @@ void PWFrameBuffer::Private::handleFrame(const PipeWireFrame &frame)
|
|||||||
#endif
|
#endif
|
||||||
else if (frame.dmabuf) {
|
else if (frame.dmabuf) {
|
||||||
// FIXME: Assuming stride == width * 4, not sure to which extent this holds
|
// FIXME: Assuming stride == width * 4, not sure to which extent this holds
|
||||||
const QSize size = { frame.dmabuf->width, frame.dmabuf->height };
|
const QSize size = {frame.dmabuf->width, frame.dmabuf->height};
|
||||||
setVideoSize(size);
|
setVideoSize(size);
|
||||||
QImage src(reinterpret_cast<uchar*>(q->fb), size.width(), size.height(), QImage::Format_RGB32);
|
QImage src(reinterpret_cast<uchar *>(q->fb), size.width(), size.height(), QImage::Format_RGB32);
|
||||||
if (!m_dmabufHandler.downloadFrame(src, frame)) {
|
if (!m_dmabufHandler.downloadFrame(src, frame)) {
|
||||||
stream->renegotiateModifierFailed(frame.format, frame.dmabuf->modifier);
|
stream->renegotiateModifierFailed(frame.format, frame.dmabuf->modifier);
|
||||||
qCDebug(KRFB_FB_PIPEWIRE) << "Failed to download frame.";
|
qCDebug(KRFB_FB_PIPEWIRE) << "Failed to download frame.";
|
||||||
@@ -404,7 +398,7 @@ void PWFrameBuffer::Private::setVideoSize(const QSize &size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
free(q->fb);
|
free(q->fb);
|
||||||
q->fb = static_cast<char*>(malloc(size.width() * size.height() * BYTES_PER_PIXEL));
|
q->fb = static_cast<char *>(malloc(size.width() * size.height() * BYTES_PER_PIXEL));
|
||||||
if (!q->fb) {
|
if (!q->fb) {
|
||||||
qCWarning(KRFB_FB_PIPEWIRE) << "Failed to allocate buffer";
|
qCWarning(KRFB_FB_PIPEWIRE) << "Failed to allocate buffer";
|
||||||
isValid = false;
|
isValid = false;
|
||||||
@@ -420,8 +414,8 @@ PWFrameBuffer::Private::~Private()
|
|||||||
}
|
}
|
||||||
|
|
||||||
PWFrameBuffer::PWFrameBuffer(QObject *parent)
|
PWFrameBuffer::PWFrameBuffer(QObject *parent)
|
||||||
: FrameBuffer (parent),
|
: FrameBuffer(parent)
|
||||||
d(new Private(this))
|
, d(new Private(this))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -436,7 +430,7 @@ void PWFrameBuffer::initDBus()
|
|||||||
d->initDbus();
|
d->initDbus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PWFrameBuffer::startVirtualMonitor(const QString& name, const QSize& resolution, qreal dpr)
|
void PWFrameBuffer::startVirtualMonitor(const QString &name, const QSize &resolution, qreal dpr)
|
||||||
{
|
{
|
||||||
d->videoSize = resolution * dpr;
|
d->videoSize = resolution * dpr;
|
||||||
using namespace KWayland::Client;
|
using namespace KWayland::Client;
|
||||||
@@ -448,16 +442,19 @@ void PWFrameBuffer::startVirtualMonitor(const QString& name, const QSize& resolu
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto registry = new Registry(this);
|
auto registry = new Registry(this);
|
||||||
connect(registry, &KWayland::Client::Registry::interfaceAnnounced, this, [this, registry, name, dpr, resolution] (const QByteArray &interfaceName, quint32 wlname, quint32 version) {
|
connect(registry,
|
||||||
if (interfaceName != "zkde_screencast_unstable_v1")
|
&KWayland::Client::Registry::interfaceAnnounced,
|
||||||
return;
|
this,
|
||||||
|
[this, registry, name, dpr, resolution](const QByteArray &interfaceName, quint32 wlname, quint32 version) {
|
||||||
|
if (interfaceName != "zkde_screencast_unstable_v1")
|
||||||
|
return;
|
||||||
|
|
||||||
auto screencasting = new Screencasting(registry, wlname, version, this);
|
auto screencasting = new Screencasting(registry, wlname, version, this);
|
||||||
auto r = screencasting->createVirtualMonitorStream(name, resolution, dpr, Screencasting::Metadata);
|
auto r = screencasting->createVirtualMonitorStream(name, resolution, dpr, Screencasting::Metadata);
|
||||||
connect(r, &ScreencastingStream::created, this, [this] (quint32 nodeId) {
|
connect(r, &ScreencastingStream::created, this, [this](quint32 nodeId) {
|
||||||
d->stream->createStream(nodeId, 0);
|
d->stream->createStream(nodeId, 0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
registry->create(connection);
|
registry->create(connection);
|
||||||
registry->setup();
|
registry->setup();
|
||||||
}
|
}
|
||||||
@@ -498,19 +495,18 @@ void PWFrameBuffer::getServerFormat(rfbPixelFormat &format)
|
|||||||
|
|
||||||
void PWFrameBuffer::startMonitor()
|
void PWFrameBuffer::startMonitor()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PWFrameBuffer::stopMonitor()
|
void PWFrameBuffer::stopMonitor()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant PWFrameBuffer::customProperty(const QString &property) const
|
QVariant PWFrameBuffer::customProperty(const QString &property) const
|
||||||
{
|
{
|
||||||
if (property == QLatin1String("stream_node_id")) {
|
if (property == QLatin1String("stream_node_id")) {
|
||||||
return QVariant::fromValue<uint>(d->stream->nodeId());
|
return QVariant::fromValue<uint>(d->stream->nodeId());
|
||||||
} if (property == QLatin1String("session_handle")) {
|
}
|
||||||
|
if (property == QLatin1String("session_handle")) {
|
||||||
return QVariant::fromValue<QDBusObjectPath>(d->sessionPath);
|
return QVariant::fromValue<QDBusObjectPath>(d->sessionPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,8 @@
|
|||||||
#define KRFB_FRAMEBUFFER_XCB_XCB_FRAMEBUFFER_H
|
#define KRFB_FRAMEBUFFER_XCB_XCB_FRAMEBUFFER_H
|
||||||
|
|
||||||
#include "framebuffer.h"
|
#include "framebuffer.h"
|
||||||
#include <QWidget>
|
|
||||||
#include <QVariantMap>
|
#include <QVariantMap>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The PWFrameBuffer class - framebuffer implementation based on XDG Desktop Portal ScreenCast interface.
|
* @brief The PWFrameBuffer class - framebuffer implementation based on XDG Desktop Portal ScreenCast interface.
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
*
|
*
|
||||||
* @author Oleg Chernovskiy <kanedias@xaker.ru>
|
* @author Oleg Chernovskiy <kanedias@xaker.ru>
|
||||||
*/
|
*/
|
||||||
class PWFrameBuffer: public FrameBuffer
|
class PWFrameBuffer : public FrameBuffer
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@@ -33,10 +33,10 @@ public:
|
|||||||
void initDBus();
|
void initDBus();
|
||||||
void startVirtualMonitor(const QString &name, const QSize &resolution, qreal dpr);
|
void startVirtualMonitor(const QString &name, const QSize &resolution, qreal dpr);
|
||||||
|
|
||||||
int depth() override;
|
int depth() override;
|
||||||
int height() override;
|
int height() override;
|
||||||
int width() override;
|
int width() override;
|
||||||
int paddedWidth() override;
|
int paddedWidth() override;
|
||||||
void getServerFormat(rfbPixelFormat &format) override;
|
void getServerFormat(rfbPixelFormat &format) override;
|
||||||
void startMonitor() override;
|
void startMonitor() override;
|
||||||
void stopMonitor() override;
|
void stopMonitor() override;
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
SPDX-License-Identifier: GPL-3.0-or-later
|
SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "pw_framebufferplugin.h"
|
#include "pw_framebufferplugin.h"
|
||||||
#include "pw_framebuffer.h"
|
#include "pw_framebuffer.h"
|
||||||
#include <KPluginFactory>
|
#include <KPluginFactory>
|
||||||
@@ -16,12 +15,13 @@ PWFrameBufferPlugin::PWFrameBufferPlugin(QObject *parent, const QVariantList &ar
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FrameBuffer *PWFrameBufferPlugin::frameBuffer(const QVariantMap &args)
|
FrameBuffer *PWFrameBufferPlugin::frameBuffer(const QVariantMap &args)
|
||||||
{
|
{
|
||||||
auto pwfb = new PWFrameBuffer;
|
auto pwfb = new PWFrameBuffer;
|
||||||
if (args.contains(QLatin1String("name"))) {
|
if (args.contains(QLatin1String("name"))) {
|
||||||
pwfb->startVirtualMonitor(args[QStringLiteral("name")].toString(), args[QStringLiteral("resolution")].toSize(), args[QStringLiteral("scale")].toDouble());
|
pwfb->startVirtualMonitor(args[QStringLiteral("name")].toString(),
|
||||||
|
args[QStringLiteral("resolution")].toSize(),
|
||||||
|
args[QStringLiteral("scale")].toDouble());
|
||||||
} else {
|
} else {
|
||||||
// D-Bus is most important in XDG-Desktop-Portals init chain, no toys for us if something is wrong with XDP
|
// D-Bus is most important in XDG-Desktop-Portals init chain, no toys for us if something is wrong with XDP
|
||||||
// PipeWire connectivity is initialized after D-Bus session is started
|
// PipeWire connectivity is initialized after D-Bus session is started
|
||||||
|
|||||||
@@ -1,29 +1,27 @@
|
|||||||
/* This file is part of the KDE project
|
/* This file is part of the KDE project
|
||||||
SPDX-FileCopyrightText: 2018 Oleg Chernovskiy <kanedias@xaker.ru>
|
SPDX-FileCopyrightText: 2018 Oleg Chernovskiy <kanedias@xaker.ru>
|
||||||
|
|
||||||
SPDX-License-Identifier: GPL-3.0-or-later
|
SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef KRFB_FRAMEBUFFER_PW_PWFRAMEBUFFERPLUGIN_H
|
#ifndef KRFB_FRAMEBUFFER_PW_PWFRAMEBUFFERPLUGIN_H
|
||||||
#define KRFB_FRAMEBUFFER_PW_PWFRAMEBUFFERPLUGIN_H
|
#define KRFB_FRAMEBUFFER_PW_PWFRAMEBUFFERPLUGIN_H
|
||||||
|
|
||||||
|
|
||||||
#include "framebufferplugin.h"
|
#include "framebufferplugin.h"
|
||||||
|
|
||||||
class FrameBuffer;
|
class FrameBuffer;
|
||||||
|
|
||||||
class PWFrameBufferPlugin: public FrameBufferPlugin
|
class PWFrameBufferPlugin : public FrameBufferPlugin
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PWFrameBufferPlugin(QObject *parent, const QVariantList &args);
|
PWFrameBufferPlugin(QObject *parent, const QVariantList &args);
|
||||||
|
|
||||||
FrameBuffer *frameBuffer(const QVariantMap &args) override;
|
FrameBuffer *frameBuffer(const QVariantMap &args) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(PWFrameBufferPlugin)
|
Q_DISABLE_COPY(PWFrameBufferPlugin)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // Header guard
|
||||||
#endif // Header guard
|
|
||||||
|
|||||||
@@ -12,8 +12,8 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <KWayland/Client/registry.h>
|
#include <KWayland/Client/registry.h>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QRect>
|
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
|
#include <QRect>
|
||||||
|
|
||||||
using namespace KWayland::Client;
|
using namespace KWayland::Client;
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ Screencasting::Screencasting(Registry *registry, int id, int version, QObject *p
|
|||||||
|
|
||||||
Screencasting::~Screencasting() = default;
|
Screencasting::~Screencasting() = default;
|
||||||
|
|
||||||
ScreencastingStream * Screencasting::createVirtualMonitorStream(const QString& name, const QSize& resolution, qreal dpr, Screencasting::CursorMode mode)
|
ScreencastingStream *Screencasting::createVirtualMonitorStream(const QString &name, const QSize &resolution, qreal dpr, Screencasting::CursorMode mode)
|
||||||
{
|
{
|
||||||
auto stream = new ScreencastingStream(this);
|
auto stream = new ScreencastingStream(this);
|
||||||
stream->d->init(d->stream_virtual_output(name, resolution.width(), resolution.height(), wl_fixed_from_double(dpr), mode));
|
stream->d->init(d->stream_virtual_output(name, resolution.width(), resolution.height(), wl_fixed_from_double(dpr), mode));
|
||||||
|
|||||||
@@ -6,9 +6,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
#include <QList>
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
struct zkde_screencast_unstable_v1;
|
struct zkde_screencast_unstable_v1;
|
||||||
|
|||||||
@@ -7,22 +7,22 @@
|
|||||||
#include "xcb_framebuffer.h"
|
#include "xcb_framebuffer.h"
|
||||||
#include "krfb_fb_xcb_debug.h"
|
#include "krfb_fb_xcb_debug.h"
|
||||||
|
|
||||||
#include <xcb/xproto.h>
|
|
||||||
#include <xcb/damage.h>
|
#include <xcb/damage.h>
|
||||||
#include <xcb/shm.h>
|
#include <xcb/shm.h>
|
||||||
#include <xcb/xcb_image.h>
|
#include <xcb/xcb_image.h>
|
||||||
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
#include <sys/ipc.h>
|
#include <sys/ipc.h>
|
||||||
#include <sys/shm.h>
|
#include <sys/shm.h>
|
||||||
|
|
||||||
|
#include <QAbstractNativeEventFilter>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
#include <QScreen>
|
#include <QScreen>
|
||||||
#include <QAbstractNativeEventFilter>
|
|
||||||
#include <qpa/qplatformnativeinterface.h>
|
|
||||||
#include <QtGui/private/qtx11extras_p.h>
|
#include <QtGui/private/qtx11extras_p.h>
|
||||||
|
#include <qpa/qplatformnativeinterface.h>
|
||||||
|
|
||||||
class KrfbXCBEventFilter: public QAbstractNativeEventFilter
|
class KrfbXCBEventFilter : public QAbstractNativeEventFilter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
KrfbXCBEventFilter(XCBFrameBuffer *owner);
|
KrfbXCBEventFilter(XCBFrameBuffer *owner);
|
||||||
@@ -39,33 +39,29 @@ public:
|
|||||||
XCBFrameBuffer *fb_owner;
|
XCBFrameBuffer *fb_owner;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
KrfbXCBEventFilter::KrfbXCBEventFilter(XCBFrameBuffer *owner)
|
||||||
|
: xdamageBaseEvent(0)
|
||||||
KrfbXCBEventFilter::KrfbXCBEventFilter(XCBFrameBuffer *owner):
|
, xdamageBaseError(0)
|
||||||
xdamageBaseEvent(0), xdamageBaseError(0),
|
, xshmBaseEvent(0)
|
||||||
xshmBaseEvent(0), xshmBaseError(0), xshmAvail(false),
|
, xshmBaseError(0)
|
||||||
fb_owner(owner)
|
, xshmAvail(false)
|
||||||
|
, fb_owner(owner)
|
||||||
{
|
{
|
||||||
const xcb_query_extension_reply_t *xdamage_data = xcb_get_extension_data(
|
const xcb_query_extension_reply_t *xdamage_data = xcb_get_extension_data(QX11Info::connection(), &xcb_damage_id);
|
||||||
QX11Info::connection(), &xcb_damage_id);
|
|
||||||
if (xdamage_data) {
|
if (xdamage_data) {
|
||||||
// also query extension version!
|
// also query extension version!
|
||||||
// ATTENTION: if we don't do that, xcb_damage_create() will always FAIL!
|
// ATTENTION: if we don't do that, xcb_damage_create() will always FAIL!
|
||||||
xcb_damage_query_version_reply_t *xdamage_version = xcb_damage_query_version_reply(
|
xcb_damage_query_version_reply_t *xdamage_version =
|
||||||
QX11Info::connection(),
|
xcb_damage_query_version_reply(QX11Info::connection(),
|
||||||
xcb_damage_query_version(
|
xcb_damage_query_version(QX11Info::connection(), XCB_DAMAGE_MAJOR_VERSION, XCB_DAMAGE_MINOR_VERSION),
|
||||||
QX11Info::connection(),
|
nullptr);
|
||||||
XCB_DAMAGE_MAJOR_VERSION,
|
|
||||||
XCB_DAMAGE_MINOR_VERSION),
|
|
||||||
nullptr);
|
|
||||||
if (!xdamage_version) {
|
if (!xdamage_version) {
|
||||||
qWarning() << "xcb framebuffer: ERROR: Failed to get XDamage extension version!\n";
|
qWarning() << "xcb framebuffer: ERROR: Failed to get XDamage extension version!\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
qCDebug(KRFB_FB_XCB) << "xcb framebuffer: XDamage extension version:" <<
|
qCDebug(KRFB_FB_XCB) << "xcb framebuffer: XDamage extension version:" << xdamage_version->major_version << "." << xdamage_version->minor_version;
|
||||||
xdamage_version->major_version << "." << xdamage_version->minor_version;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
free(xdamage_version);
|
free(xdamage_version);
|
||||||
@@ -75,8 +71,7 @@ KrfbXCBEventFilter::KrfbXCBEventFilter(XCBFrameBuffer *owner):
|
|||||||
|
|
||||||
// XShm presence is optional. If it is present, all image getting
|
// XShm presence is optional. If it is present, all image getting
|
||||||
// operations will be faster, without XShm it will only be slower.
|
// operations will be faster, without XShm it will only be slower.
|
||||||
const xcb_query_extension_reply_t *xshm_data = xcb_get_extension_data(
|
const xcb_query_extension_reply_t *xshm_data = xcb_get_extension_data(QX11Info::connection(), &xcb_shm_id);
|
||||||
QX11Info::connection(), &xcb_shm_id);
|
|
||||||
if (xshm_data) {
|
if (xshm_data) {
|
||||||
xshmAvail = true;
|
xshmAvail = true;
|
||||||
xshmBaseEvent = xshm_data->first_event;
|
xshmBaseEvent = xshm_data->first_event;
|
||||||
@@ -93,19 +88,19 @@ KrfbXCBEventFilter::KrfbXCBEventFilter(XCBFrameBuffer *owner):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool KrfbXCBEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result)
|
||||||
|
{
|
||||||
|
Q_UNUSED(result); // "result" is only used on windows
|
||||||
|
|
||||||
bool KrfbXCBEventFilter::nativeEventFilter(const QByteArray &eventType,
|
if (xdamageBaseEvent == 0)
|
||||||
void *message, qintptr *result) {
|
return false; // no xdamage extension
|
||||||
Q_UNUSED(result); // "result" is only used on windows
|
|
||||||
|
|
||||||
if (xdamageBaseEvent == 0) return false; // no xdamage extension
|
|
||||||
|
|
||||||
if (eventType == "xcb_generic_event_t") {
|
if (eventType == "xcb_generic_event_t") {
|
||||||
auto ev = static_cast<xcb_generic_event_t *>(message);
|
auto ev = static_cast<xcb_generic_event_t *>(message);
|
||||||
if ((ev->response_type & 0x7F) == (xdamageBaseEvent + XCB_DAMAGE_NOTIFY)) {
|
if ((ev->response_type & 0x7F) == (xdamageBaseEvent + XCB_DAMAGE_NOTIFY)) {
|
||||||
// this is xdamage notification
|
// this is xdamage notification
|
||||||
this->fb_owner->handleXDamageNotify(ev);
|
this->fb_owner->handleXDamageNotify(ev);
|
||||||
return true; // filter out this event, stop its processing
|
return true; // filter out this event, stop its processing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,25 +108,25 @@ bool KrfbXCBEventFilter::nativeEventFilter(const QByteArray &eventType,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class XCBFrameBuffer::P
|
||||||
class XCBFrameBuffer::P {
|
{
|
||||||
public:
|
public:
|
||||||
xcb_damage_damage_t damage;
|
xcb_damage_damage_t damage;
|
||||||
xcb_shm_segment_info_t shminfo;
|
xcb_shm_segment_info_t shminfo;
|
||||||
xcb_screen_t *rootScreen; // X screen info (all monitors)
|
xcb_screen_t *rootScreen; // X screen info (all monitors)
|
||||||
xcb_image_t *framebufferImage;
|
xcb_image_t *framebufferImage;
|
||||||
xcb_image_t *updateTile;
|
xcb_image_t *updateTile;
|
||||||
|
|
||||||
KrfbXCBEventFilter *x11EvtFilter;
|
KrfbXCBEventFilter *x11EvtFilter;
|
||||||
|
|
||||||
bool running;
|
bool running;
|
||||||
|
|
||||||
QRect area; // capture area, primary monitor coordinates
|
QRect area; // capture area, primary monitor coordinates
|
||||||
WId win;
|
WId win;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static xcb_screen_t *get_xcb_screen(xcb_connection_t *conn, int screen_num)
|
||||||
static xcb_screen_t *get_xcb_screen(xcb_connection_t *conn, int screen_num) {
|
{
|
||||||
xcb_screen_t *screen = nullptr;
|
xcb_screen_t *screen = nullptr;
|
||||||
xcb_screen_iterator_t screens_iter = xcb_setup_roots_iterator(xcb_get_setup(conn));
|
xcb_screen_iterator_t screens_iter = xcb_setup_roots_iterator(xcb_get_setup(conn));
|
||||||
for (; screens_iter.rem; --screen_num, xcb_screen_next(&screens_iter))
|
for (; screens_iter.rem; --screen_num, xcb_screen_next(&screens_iter))
|
||||||
@@ -140,10 +135,9 @@ static xcb_screen_t *get_xcb_screen(xcb_connection_t *conn, int screen_num) {
|
|||||||
return screen;
|
return screen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XCBFrameBuffer::XCBFrameBuffer(QObject *parent)
|
||||||
|
: FrameBuffer(parent)
|
||||||
XCBFrameBuffer::XCBFrameBuffer(QObject *parent):
|
, d(new XCBFrameBuffer::P)
|
||||||
FrameBuffer(parent), d(new XCBFrameBuffer::P)
|
|
||||||
{
|
{
|
||||||
d->running = false;
|
d->running = false;
|
||||||
d->damage = XCB_NONE;
|
d->damage = XCB_NONE;
|
||||||
@@ -160,17 +154,13 @@ XCBFrameBuffer::XCBFrameBuffer(QObject *parent):
|
|||||||
|
|
||||||
QScreen *primaryScreen = QGuiApplication::primaryScreen();
|
QScreen *primaryScreen = QGuiApplication::primaryScreen();
|
||||||
if (primaryScreen) {
|
if (primaryScreen) {
|
||||||
QPlatformNativeInterface* native = qApp->platformNativeInterface();
|
QPlatformNativeInterface *native = qApp->platformNativeInterface();
|
||||||
d->win = reinterpret_cast<WId>(native->nativeResourceForScreen(QByteArrayLiteral("rootwindow"), primaryScreen));
|
d->win = reinterpret_cast<WId>(native->nativeResourceForScreen(QByteArrayLiteral("rootwindow"), primaryScreen));
|
||||||
qreal scaleFactor = primaryScreen->devicePixelRatio();
|
qreal scaleFactor = primaryScreen->devicePixelRatio();
|
||||||
d->area = { primaryScreen->geometry().topLeft() * scaleFactor,
|
d->area = {primaryScreen->geometry().topLeft() * scaleFactor, primaryScreen->geometry().bottomRight() * scaleFactor};
|
||||||
primaryScreen->geometry().bottomRight() * scaleFactor };
|
|
||||||
|
|
||||||
qCDebug(KRFB_FB_XCB) << "xcb framebuffer: Primary screen: " << primaryScreen->name()
|
qCDebug(KRFB_FB_XCB) << "xcb framebuffer: Primary screen: " << primaryScreen->name() << ", geometry: " << primaryScreen->geometry()
|
||||||
<< ", geometry: " << primaryScreen->geometry()
|
<< ", device scaling: " << scaleFactor << ", native size: " << d->area << ", depth: " << primaryScreen->depth();
|
||||||
<< ", device scaling: " << scaleFactor
|
|
||||||
<< ", native size: " << d->area
|
|
||||||
<< ", depth: " << primaryScreen->depth();
|
|
||||||
} else {
|
} else {
|
||||||
qWarning() << "xcb framebuffer: ERROR: Failed to get application's primary screen info!";
|
qWarning() << "xcb framebuffer: ERROR: Failed to get application's primary screen info!";
|
||||||
return;
|
return;
|
||||||
@@ -186,10 +176,9 @@ XCBFrameBuffer::XCBFrameBuffer(QObject *parent):
|
|||||||
XCB_IMAGE_FORMAT_Z_PIXMAP);
|
XCB_IMAGE_FORMAT_Z_PIXMAP);
|
||||||
if (d->framebufferImage) {
|
if (d->framebufferImage) {
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
qCDebug(KRFB_FB_XCB) << "xcb framebuffer: Got primary screen image. bpp: " << d->framebufferImage->bpp
|
qCDebug(KRFB_FB_XCB) << "xcb framebuffer: Got primary screen image. bpp: " << d->framebufferImage->bpp << ", size (" << d->framebufferImage->width
|
||||||
<< ", size (" << d->framebufferImage->width << d->framebufferImage->height << ")"
|
<< d->framebufferImage->height << ")"
|
||||||
<< ", depth: " << d->framebufferImage->depth
|
<< ", depth: " << d->framebufferImage->depth << ", padded width: " << d->framebufferImage->stride;
|
||||||
<< ", padded width: " << d->framebufferImage->stride;
|
|
||||||
#endif
|
#endif
|
||||||
this->fb = (char *)d->framebufferImage->data;
|
this->fb = (char *)d->framebufferImage->data;
|
||||||
} else {
|
} else {
|
||||||
@@ -203,26 +192,23 @@ XCBFrameBuffer::XCBFrameBuffer(QObject *parent):
|
|||||||
// for image data storage - it will be allocated as shared memory.
|
// for image data storage - it will be allocated as shared memory.
|
||||||
// "If base == 0 and bytes == ~0 and data == 0, no storage will be auto-allocated."
|
// "If base == 0 and bytes == ~0 and data == 0, no storage will be auto-allocated."
|
||||||
// Width and height of the image = size of the capture area.
|
// Width and height of the image = size of the capture area.
|
||||||
d->updateTile = xcb_image_create_native(
|
d->updateTile = xcb_image_create_native(QX11Info::connection(),
|
||||||
QX11Info::connection(),
|
d->area.width(), // width
|
||||||
d->area.width(), // width
|
d->area.height(), // height
|
||||||
d->area.height(), // height
|
XCB_IMAGE_FORMAT_Z_PIXMAP, // image format
|
||||||
XCB_IMAGE_FORMAT_Z_PIXMAP, // image format
|
d->rootScreen->root_depth, // depth
|
||||||
d->rootScreen->root_depth, // depth
|
nullptr, // base address = 0
|
||||||
nullptr, // base address = 0
|
(uint32_t)~0, // bytes = 0xffffffff
|
||||||
(uint32_t)~0, // bytes = 0xffffffff
|
nullptr); // data = 0
|
||||||
nullptr); // data = 0
|
|
||||||
if (d->updateTile) {
|
if (d->updateTile) {
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
qCDebug(KRFB_FB_XCB) << "xcb framebuffer: Successfully created new empty image in native format"
|
qCDebug(KRFB_FB_XCB) << "xcb framebuffer: Successfully created new empty image in native format"
|
||||||
<< "\n size: " << d->updateTile->width << "x" << d->updateTile->height
|
<< "\n size: " << d->updateTile->width << "x" << d->updateTile->height << "(stride: " << d->updateTile->stride << ")"
|
||||||
<< "(stride: " << d->updateTile->stride << ")"
|
<< "\n bpp, depth: " << d->updateTile->bpp << d->updateTile->depth // 32, 24
|
||||||
<< "\n bpp, depth: " << d->updateTile->bpp << d->updateTile->depth // 32, 24
|
<< "\n addr of base, data: " << d->updateTile->base << (void *)d->updateTile->data
|
||||||
<< "\n addr of base, data: " << d->updateTile->base << (void *)d->updateTile->data
|
<< "\n size: " << d->updateTile->size << "\n image byte order = " << d->updateTile->byte_order // == 0 .._LSB_FIRST
|
||||||
<< "\n size: " << d->updateTile->size
|
<< "\n image bit order = " << d->updateTile->bit_order // == 1 .._MSB_FIRST
|
||||||
<< "\n image byte order = " << d->updateTile->byte_order // == 0 .._LSB_FIRST
|
<< "\n image plane_mask = " << d->updateTile->plane_mask; // == 16777215 == 0x00FFFFFF
|
||||||
<< "\n image bit order = " << d->updateTile->bit_order // == 1 .._MSB_FIRST
|
|
||||||
<< "\n image plane_mask = " << d->updateTile->plane_mask; // == 16777215 == 0x00FFFFFF
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// allocate shared memory block only once, make its size large enough
|
// allocate shared memory block only once, make its size large enough
|
||||||
@@ -244,14 +230,13 @@ XCBFrameBuffer::XCBFrameBuffer(QObject *parent):
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// will return 1 on success (yes!)
|
// will return 1 on success (yes!)
|
||||||
int shmget_res = xcb_image_shm_get(
|
int shmget_res = xcb_image_shm_get(QX11Info::connection(),
|
||||||
QX11Info::connection(),
|
d->win,
|
||||||
d->win,
|
d->updateTile,
|
||||||
d->updateTile,
|
d->shminfo,
|
||||||
d->shminfo,
|
d->area.left(), // x
|
||||||
d->area.left(), // x
|
d->area.top(), // y (size taken from image structure itself)?
|
||||||
d->area.top(), // y (size taken from image structure itself)?
|
0xFFFFFFFF);
|
||||||
0xFFFFFFFF);
|
|
||||||
|
|
||||||
if (shmget_res == 0) {
|
if (shmget_res == 0) {
|
||||||
// error! shared mem not working?
|
// error! shared mem not working?
|
||||||
@@ -277,22 +262,21 @@ XCBFrameBuffer::XCBFrameBuffer(QObject *parent):
|
|||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
qCDebug(KRFB_FB_XCB) << "xcb framebuffer: XCBFrameBuffer(), xshm base event = " << d->x11EvtFilter->xshmBaseEvent
|
qCDebug(KRFB_FB_XCB) << "xcb framebuffer: XCBFrameBuffer(), xshm base event = " << d->x11EvtFilter->xshmBaseEvent
|
||||||
<< ", xshm base error = " << d->x11EvtFilter->xdamageBaseError
|
<< ", xshm base error = " << d->x11EvtFilter->xdamageBaseError << ", xdamage base event = " << d->x11EvtFilter->xdamageBaseEvent
|
||||||
<< ", xdamage base event = " << d->x11EvtFilter->xdamageBaseEvent
|
<< ", xdamage base error = " << d->x11EvtFilter->xdamageBaseError;
|
||||||
<< ", xdamage base error = " << d->x11EvtFilter->xdamageBaseError;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QCoreApplication::instance()->installNativeEventFilter(d->x11EvtFilter);
|
QCoreApplication::instance()->installNativeEventFilter(d->x11EvtFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XCBFrameBuffer::~XCBFrameBuffer()
|
||||||
XCBFrameBuffer::~XCBFrameBuffer() {
|
{
|
||||||
// first - uninstall x11 event filter
|
// first - uninstall x11 event filter
|
||||||
QCoreApplication::instance()->removeNativeEventFilter(d->x11EvtFilter);
|
QCoreApplication::instance()->removeNativeEventFilter(d->x11EvtFilter);
|
||||||
//
|
//
|
||||||
if (d->framebufferImage) {
|
if (d->framebufferImage) {
|
||||||
xcb_image_destroy(d->framebufferImage);
|
xcb_image_destroy(d->framebufferImage);
|
||||||
fb = nullptr; // image data was already destroyed by above call
|
fb = nullptr; // image data was already destroyed by above call
|
||||||
}
|
}
|
||||||
if (d->x11EvtFilter->xshmAvail) {
|
if (d->x11EvtFilter->xshmAvail) {
|
||||||
// detach shared memory
|
// detach shared memory
|
||||||
@@ -316,43 +300,45 @@ XCBFrameBuffer::~XCBFrameBuffer() {
|
|||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int XCBFrameBuffer::depth()
|
||||||
int XCBFrameBuffer::depth() {
|
{
|
||||||
if (d->framebufferImage) {
|
if (d->framebufferImage) {
|
||||||
return d->framebufferImage->depth;
|
return d->framebufferImage->depth;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int XCBFrameBuffer::height()
|
||||||
int XCBFrameBuffer::height() {
|
{
|
||||||
if (d->framebufferImage) {
|
if (d->framebufferImage) {
|
||||||
return d->framebufferImage->height;
|
return d->framebufferImage->height;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int XCBFrameBuffer::width()
|
||||||
int XCBFrameBuffer::width() {
|
{
|
||||||
if (d->framebufferImage) {
|
if (d->framebufferImage) {
|
||||||
return d->framebufferImage->width;
|
return d->framebufferImage->width;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int XCBFrameBuffer::paddedWidth() {
|
int XCBFrameBuffer::paddedWidth()
|
||||||
|
{
|
||||||
if (d->framebufferImage) {
|
if (d->framebufferImage) {
|
||||||
return d->framebufferImage->stride;
|
return d->framebufferImage->stride;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void XCBFrameBuffer::getServerFormat(rfbPixelFormat &format)
|
||||||
void XCBFrameBuffer::getServerFormat(rfbPixelFormat &format) {
|
{
|
||||||
if (!d->framebufferImage) return;
|
if (!d->framebufferImage)
|
||||||
|
return;
|
||||||
|
|
||||||
// get information about XCB visual params
|
// get information about XCB visual params
|
||||||
xcb_visualtype_t *root_visualtype = nullptr; // visual info
|
xcb_visualtype_t *root_visualtype = nullptr; // visual info
|
||||||
if (d->rootScreen) {
|
if (d->rootScreen) {
|
||||||
xcb_visualid_t root_visual = d->rootScreen->root_visual;
|
xcb_visualid_t root_visual = d->rootScreen->root_visual;
|
||||||
xcb_depth_iterator_t depth_iter;
|
xcb_depth_iterator_t depth_iter;
|
||||||
@@ -374,26 +360,26 @@ void XCBFrameBuffer::getServerFormat(rfbPixelFormat &format) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// fill in format common info
|
// fill in format common info
|
||||||
format.bitsPerPixel = d->framebufferImage->bpp;
|
format.bitsPerPixel = d->framebufferImage->bpp;
|
||||||
format.depth = d->framebufferImage->depth;
|
format.depth = d->framebufferImage->depth;
|
||||||
format.trueColour = true; // not using color palettes
|
format.trueColour = true; // not using color palettes
|
||||||
format.bigEndian = false; // always false for ZPIXMAP format!
|
format.bigEndian = false; // always false for ZPIXMAP format!
|
||||||
|
|
||||||
// information about pixels layout
|
// information about pixels layout
|
||||||
|
|
||||||
if (root_visualtype) {
|
if (root_visualtype) {
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
qDebug("xcb framebuffer: Got info about root visual:\n"
|
qDebug(
|
||||||
" bits per rgb value: %d\n"
|
"xcb framebuffer: Got info about root visual:\n"
|
||||||
" red mask: %08x\n"
|
" bits per rgb value: %d\n"
|
||||||
" green mask: %08x\n"
|
" red mask: %08x\n"
|
||||||
" blue mask: %08x\n",
|
" green mask: %08x\n"
|
||||||
(int)root_visualtype->bits_per_rgb_value,
|
" blue mask: %08x\n",
|
||||||
root_visualtype->red_mask,
|
(int)root_visualtype->bits_per_rgb_value,
|
||||||
root_visualtype->green_mask,
|
root_visualtype->red_mask,
|
||||||
root_visualtype->blue_mask);
|
root_visualtype->green_mask,
|
||||||
|
root_visualtype->blue_mask);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// calculate shifts
|
// calculate shifts
|
||||||
@@ -418,57 +404,60 @@ void XCBFrameBuffer::getServerFormat(rfbPixelFormat &format) {
|
|||||||
|
|
||||||
// calculate pixel max value.
|
// calculate pixel max value.
|
||||||
// NOTE: bits_per_rgb_value is unreliable, thus should be avoided.
|
// NOTE: bits_per_rgb_value is unreliable, thus should be avoided.
|
||||||
format.redMax = root_visualtype->red_mask >> format.redShift;
|
format.redMax = root_visualtype->red_mask >> format.redShift;
|
||||||
format.greenMax = root_visualtype->green_mask >> format.greenShift;
|
format.greenMax = root_visualtype->green_mask >> format.greenShift;
|
||||||
format.blueMax = root_visualtype->blue_mask >> format.blueShift;
|
format.blueMax = root_visualtype->blue_mask >> format.blueShift;
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
qCDebug(KRFB_FB_XCB,
|
qCDebug(KRFB_FB_XCB,
|
||||||
" Calculated redShift = %d\n"
|
" Calculated redShift = %d\n"
|
||||||
" Calculated greenShift = %d\n"
|
" Calculated greenShift = %d\n"
|
||||||
" Calculated blueShift = %d\n"
|
" Calculated blueShift = %d\n"
|
||||||
" Calculated max values: R%d G%d B%d",
|
" Calculated max values: R%d G%d B%d",
|
||||||
format.redShift, format.greenShift, format.blueShift
|
format.redShift,
|
||||||
format.redMax, format.greenMax, format.blueMax);
|
format.greenShift,
|
||||||
|
format.blueShift format.redMax,
|
||||||
|
format.greenMax,
|
||||||
|
format.blueMax);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
// some kind of fallback (unlikely code execution will go this way)
|
// some kind of fallback (unlikely code execution will go this way)
|
||||||
// idea taken from qt framefuffer sources
|
// idea taken from qt framefuffer sources
|
||||||
if (format.bitsPerPixel == 8) {
|
if (format.bitsPerPixel == 8) {
|
||||||
format.redShift = 0;
|
format.redShift = 0;
|
||||||
format.greenShift = 3;
|
format.greenShift = 3;
|
||||||
format.blueShift = 6;
|
format.blueShift = 6;
|
||||||
format.redMax = 7;
|
format.redMax = 7;
|
||||||
format.greenMax = 7;
|
format.greenMax = 7;
|
||||||
format.blueMax = 3;
|
format.blueMax = 3;
|
||||||
} else if (format.bitsPerPixel == 16) {
|
} else if (format.bitsPerPixel == 16) {
|
||||||
// TODO: 16 bits per pixel format ??
|
// TODO: 16 bits per pixel format ??
|
||||||
// what format of pixels does X server use for 16-bpp?
|
// what format of pixels does X server use for 16-bpp?
|
||||||
} else if (format.bitsPerPixel == 32) {
|
} else if (format.bitsPerPixel == 32) {
|
||||||
format.redMax = 0xff;
|
format.redMax = 0xff;
|
||||||
format.greenMax = 0xff;
|
format.greenMax = 0xff;
|
||||||
format.blueMax = 0xff;
|
format.blueMax = 0xff;
|
||||||
if (format.bigEndian) {
|
if (format.bigEndian) {
|
||||||
format.redShift = 0;
|
format.redShift = 0;
|
||||||
format.greenShift = 8;
|
format.greenShift = 8;
|
||||||
format.blueShift = 16;
|
format.blueShift = 16;
|
||||||
} else {
|
} else {
|
||||||
format.redShift = 16;
|
format.redShift = 16;
|
||||||
format.greenShift = 8;
|
format.greenShift = 8;
|
||||||
format.blueShift = 0;
|
format.blueShift = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function contents was taken from X11 framebuffer source code.
|
* This function contents was taken from X11 framebuffer source code.
|
||||||
* It simply several intersecting rectangles into one bigger rect.
|
* It simply several intersecting rectangles into one bigger rect.
|
||||||
* Non-intersecting rects are treated as different rects and exist
|
* Non-intersecting rects are treated as different rects and exist
|
||||||
* separately in this->tiles QList.
|
* separately in this->tiles QList.
|
||||||
*/
|
*/
|
||||||
void XCBFrameBuffer::cleanupRects() {
|
void XCBFrameBuffer::cleanupRects()
|
||||||
|
{
|
||||||
QList<QRect> cpy = tiles;
|
QList<QRect> cpy = tiles;
|
||||||
bool inserted = false;
|
bool inserted = false;
|
||||||
tiles.clear();
|
tiles.clear();
|
||||||
@@ -477,7 +466,8 @@ void XCBFrameBuffer::cleanupRects() {
|
|||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
const QRect &r = iter.next();
|
const QRect &r = iter.next();
|
||||||
// skip rects not intersecting with primary monitor
|
// skip rects not intersecting with primary monitor
|
||||||
if (!r.intersects(d->area)) continue;
|
if (!r.intersects(d->area))
|
||||||
|
continue;
|
||||||
// only take intersection of this rect with primary monitor rect
|
// only take intersection of this rect with primary monitor rect
|
||||||
QRect ri = r.intersected(d->area);
|
QRect ri = r.intersected(d->area);
|
||||||
|
|
||||||
@@ -520,18 +510,17 @@ void XCBFrameBuffer::cleanupRects() {
|
|||||||
}
|
}
|
||||||
// move update rects so that they are positioned relative to
|
// move update rects so that they are positioned relative to
|
||||||
// framebuffer image, not whole screen
|
// framebuffer image, not whole screen
|
||||||
tile.moveTo(tile.left() - d->area.left(),
|
tile.moveTo(tile.left() - d->area.left(), tile.top() - d->area.top());
|
||||||
tile.top() - d->area.top());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function is called by RfbServerManager::updateScreens()
|
* This function is called by RfbServerManager::updateScreens()
|
||||||
* approximately every 50ms (!!), driven by QTimer to get all
|
* approximately every 50ms (!!), driven by QTimer to get all
|
||||||
* modified rectangles on the screen
|
* modified rectangles on the screen
|
||||||
*/
|
*/
|
||||||
QList<QRect> XCBFrameBuffer::modifiedTiles() {
|
QList<QRect> XCBFrameBuffer::modifiedTiles()
|
||||||
|
{
|
||||||
QList<QRect> ret;
|
QList<QRect> ret;
|
||||||
if (!d->running) {
|
if (!d->running) {
|
||||||
return ret;
|
return ret;
|
||||||
@@ -541,10 +530,9 @@ QList<QRect> XCBFrameBuffer::modifiedTiles() {
|
|||||||
|
|
||||||
if (tiles.size() > 0) {
|
if (tiles.size() > 0) {
|
||||||
if (d->x11EvtFilter->xshmAvail) {
|
if (d->x11EvtFilter->xshmAvail) {
|
||||||
|
|
||||||
// loop over all damage rectangles gathered up to this time
|
// loop over all damage rectangles gathered up to this time
|
||||||
QListIterator<QRect> iter(tiles);
|
QListIterator<QRect> iter(tiles);
|
||||||
//foreach(const QRect &r, tiles) {
|
// foreach(const QRect &r, tiles) {
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
const QRect &r = iter.next();
|
const QRect &r = iter.next();
|
||||||
|
|
||||||
@@ -552,42 +540,39 @@ QList<QRect> XCBFrameBuffer::modifiedTiles() {
|
|||||||
// now rects are positioned relative to framebufferImage,
|
// now rects are positioned relative to framebufferImage,
|
||||||
// but we need to get image from the whole screen, so
|
// but we need to get image from the whole screen, so
|
||||||
// translate whe coordinates
|
// translate whe coordinates
|
||||||
xcb_shm_get_image_cookie_t sgi_cookie = xcb_shm_get_image(
|
xcb_shm_get_image_cookie_t sgi_cookie = xcb_shm_get_image(QX11Info::connection(),
|
||||||
QX11Info::connection(),
|
d->win,
|
||||||
d->win,
|
d->area.left() + r.left(),
|
||||||
d->area.left() + r.left(),
|
d->area.top() + r.top(),
|
||||||
d->area.top() + r.top(),
|
r.width(),
|
||||||
r.width(),
|
r.height(),
|
||||||
r.height(),
|
0xFFFFFFFF,
|
||||||
0xFFFFFFFF,
|
XCB_IMAGE_FORMAT_Z_PIXMAP,
|
||||||
XCB_IMAGE_FORMAT_Z_PIXMAP,
|
d->shminfo.shmseg,
|
||||||
d->shminfo.shmseg,
|
0);
|
||||||
0);
|
|
||||||
|
|
||||||
xcb_shm_get_image_reply_t *sgi_reply = xcb_shm_get_image_reply(
|
xcb_shm_get_image_reply_t *sgi_reply = xcb_shm_get_image_reply(QX11Info::connection(), sgi_cookie, nullptr);
|
||||||
QX11Info::connection(), sgi_cookie, nullptr);
|
|
||||||
if (sgi_reply) {
|
if (sgi_reply) {
|
||||||
// create temporary image to get update rect contents into
|
// create temporary image to get update rect contents into
|
||||||
d->updateTile = xcb_image_create_native(
|
d->updateTile = xcb_image_create_native(QX11Info::connection(),
|
||||||
QX11Info::connection(),
|
r.width(),
|
||||||
r.width(),
|
r.height(),
|
||||||
r.height(),
|
XCB_IMAGE_FORMAT_Z_PIXMAP,
|
||||||
XCB_IMAGE_FORMAT_Z_PIXMAP,
|
d->rootScreen->root_depth,
|
||||||
d->rootScreen->root_depth,
|
nullptr, // base == 0
|
||||||
nullptr, // base == 0
|
(uint32_t)~0, // bytes == ~0
|
||||||
(uint32_t)~0, // bytes == ~0
|
nullptr);
|
||||||
nullptr);
|
|
||||||
|
|
||||||
if (d->updateTile) {
|
if (d->updateTile) {
|
||||||
d->updateTile->data = d->shminfo.shmaddr;
|
d->updateTile->data = d->shminfo.shmaddr;
|
||||||
|
|
||||||
// copy pixels from this damage rectangle image
|
// copy pixels from this damage rectangle image
|
||||||
// to our total framebuffer image
|
// to our total framebuffer image
|
||||||
int pxsize = d->framebufferImage->bpp / 8;
|
int pxsize = d->framebufferImage->bpp / 8;
|
||||||
char *dest = fb + ((d->framebufferImage->stride * r.top()) + (r.left() * pxsize));
|
char *dest = fb + ((d->framebufferImage->stride * r.top()) + (r.left() * pxsize));
|
||||||
char *src = (char *)d->updateTile->data;
|
char *src = (char *)d->updateTile->data;
|
||||||
for (int i = 0; i < d->updateTile->height; i++) {
|
for (int i = 0; i < d->updateTile->height; i++) {
|
||||||
memcpy(dest, src, d->updateTile->stride); // copy whole row of pixels
|
memcpy(dest, src, d->updateTile->stride); // copy whole row of pixels
|
||||||
dest += d->framebufferImage->stride;
|
dest += d->framebufferImage->stride;
|
||||||
src += d->updateTile->stride;
|
src += d->updateTile->stride;
|
||||||
}
|
}
|
||||||
@@ -604,28 +589,27 @@ QList<QRect> XCBFrameBuffer::modifiedTiles() {
|
|||||||
} else {
|
} else {
|
||||||
// not using shared memory
|
// not using shared memory
|
||||||
// will use just xcb_image_get() and copy pixels
|
// will use just xcb_image_get() and copy pixels
|
||||||
for (const QRect& r : std::as_const(tiles)) {
|
for (const QRect &r : std::as_const(tiles)) {
|
||||||
// I did not find XGetSubImage() analog in XCB!!
|
// I did not find XGetSubImage() analog in XCB!!
|
||||||
// need function that copies pixels from one image to another
|
// need function that copies pixels from one image to another
|
||||||
xcb_image_t *damagedImage = xcb_image_get(
|
xcb_image_t *damagedImage = xcb_image_get(QX11Info::connection(),
|
||||||
QX11Info::connection(),
|
d->win,
|
||||||
d->win,
|
r.left(),
|
||||||
r.left(),
|
r.top(),
|
||||||
r.top(),
|
r.width(),
|
||||||
r.width(),
|
r.height(),
|
||||||
r.height(),
|
0xFFFFFFFF, // AllPlanes
|
||||||
0xFFFFFFFF, // AllPlanes
|
XCB_IMAGE_FORMAT_Z_PIXMAP);
|
||||||
XCB_IMAGE_FORMAT_Z_PIXMAP);
|
|
||||||
// manually copy pixels
|
// manually copy pixels
|
||||||
int pxsize = d->framebufferImage->bpp / 8;
|
int pxsize = d->framebufferImage->bpp / 8;
|
||||||
char *dest = fb + ((d->framebufferImage->stride * r.top()) + (r.left() * pxsize));
|
char *dest = fb + ((d->framebufferImage->stride * r.top()) + (r.left() * pxsize));
|
||||||
char *src = (char *)damagedImage->data;
|
char *src = (char *)damagedImage->data;
|
||||||
// loop every row in damaged image
|
// loop every row in damaged image
|
||||||
for (int i = 0; i < damagedImage->height; i++) {
|
for (int i = 0; i < damagedImage->height; i++) {
|
||||||
// copy whole row of pixels from src image to dest
|
// copy whole row of pixels from src image to dest
|
||||||
memcpy(dest, src, damagedImage->stride);
|
memcpy(dest, src, damagedImage->stride);
|
||||||
dest += d->framebufferImage->stride; // move 1 row down in dest
|
dest += d->framebufferImage->stride; // move 1 row down in dest
|
||||||
src += damagedImage->stride; // move 1 row down in src
|
src += damagedImage->stride; // move 1 row down in src
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
xcb_image_destroy(damagedImage);
|
xcb_image_destroy(damagedImage);
|
||||||
@@ -638,34 +622,34 @@ QList<QRect> XCBFrameBuffer::modifiedTiles() {
|
|||||||
// ^^ If we clear here all our known "damage areas", then we can also clear
|
// ^^ If we clear here all our known "damage areas", then we can also clear
|
||||||
// damaged area for xdamage? No, we don't need to in our case
|
// damaged area for xdamage? No, we don't need to in our case
|
||||||
// (XCB_DAMAGE_REPORT_LEVEL_RAW_RECTANGLES report mode)
|
// (XCB_DAMAGE_REPORT_LEVEL_RAW_RECTANGLES report mode)
|
||||||
//xcb_damage_subtract(QX11Info::connection(), d->damage, XCB_NONE, XCB_NONE);
|
// xcb_damage_subtract(QX11Info::connection(), d->damage, XCB_NONE, XCB_NONE);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void XCBFrameBuffer::startMonitor()
|
||||||
void XCBFrameBuffer::startMonitor() {
|
{
|
||||||
if (d->running) return;
|
if (d->running)
|
||||||
|
return;
|
||||||
|
|
||||||
d->running = true;
|
d->running = true;
|
||||||
d->damage = xcb_generate_id(QX11Info::connection());
|
d->damage = xcb_generate_id(QX11Info::connection());
|
||||||
xcb_damage_create(QX11Info::connection(), d->damage, d->win,
|
xcb_damage_create(QX11Info::connection(), d->damage, d->win, XCB_DAMAGE_REPORT_LEVEL_RAW_RECTANGLES);
|
||||||
XCB_DAMAGE_REPORT_LEVEL_RAW_RECTANGLES);
|
|
||||||
|
|
||||||
// (currently) we do not call xcb_damage_subtract() EVER, because
|
// (currently) we do not call xcb_damage_subtract() EVER, because
|
||||||
// RAW rectangles are reported. every time some area of the screen
|
// RAW rectangles are reported. every time some area of the screen
|
||||||
// was changed, we get only that rectangle
|
// was changed, we get only that rectangle
|
||||||
//xcb_damage_subtract(QX11Info::connection(), d->damage, XCB_NONE, XCB_NONE);
|
// xcb_damage_subtract(QX11Info::connection(), d->damage, XCB_NONE, XCB_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void XCBFrameBuffer::stopMonitor()
|
||||||
void XCBFrameBuffer::stopMonitor() {
|
{
|
||||||
if (!d->running) return;
|
if (!d->running)
|
||||||
|
return;
|
||||||
d->running = false;
|
d->running = false;
|
||||||
xcb_damage_destroy(QX11Info::connection(), d->damage);
|
xcb_damage_destroy(QX11Info::connection(), d->damage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// void XCBFrameBuffer::acquireEvents() {} // this function was totally unused
|
// void XCBFrameBuffer::acquireEvents() {} // this function was totally unused
|
||||||
// in X11 framebuffer, but it was the only function where XDamageSubtract() was called?
|
// in X11 framebuffer, but it was the only function where XDamageSubtract() was called?
|
||||||
// Also it had a blocking event loop like:
|
// Also it had a blocking event loop like:
|
||||||
@@ -679,12 +663,10 @@ void XCBFrameBuffer::stopMonitor() {
|
|||||||
// This loop takes all available Xdamage events from queue, and ends if there are no
|
// This loop takes all available Xdamage events from queue, and ends if there are no
|
||||||
// more such events in input queue.
|
// more such events in input queue.
|
||||||
|
|
||||||
|
void XCBFrameBuffer::handleXDamageNotify(xcb_generic_event_t *xevent)
|
||||||
void XCBFrameBuffer::handleXDamageNotify(xcb_generic_event_t *xevent) {
|
{
|
||||||
auto xdevt = (xcb_damage_notify_event_t *)xevent;
|
auto xdevt = (xcb_damage_notify_event_t *)xevent;
|
||||||
|
|
||||||
QRect r((int)xdevt->area.x, (int)xdevt->area.y,
|
QRect r((int)xdevt->area.x, (int)xdevt->area.y, (int)xdevt->area.width, (int)xdevt->area.height);
|
||||||
(int)xdevt->area.width, (int)xdevt->area.height);
|
|
||||||
this->tiles.append(r);
|
this->tiles.append(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,12 +10,10 @@
|
|||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@author Alexey Min <alexey.min@gmail.com>
|
@author Alexey Min <alexey.min@gmail.com>
|
||||||
*/
|
*/
|
||||||
class XCBFrameBuffer: public FrameBuffer
|
class XCBFrameBuffer : public FrameBuffer
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@@ -24,10 +22,10 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
QList<QRect> modifiedTiles() override;
|
QList<QRect> modifiedTiles() override;
|
||||||
int depth() override;
|
int depth() override;
|
||||||
int height() override;
|
int height() override;
|
||||||
int width() override;
|
int width() override;
|
||||||
int paddedWidth() override;
|
int paddedWidth() override;
|
||||||
void getServerFormat(rfbPixelFormat &format) override;
|
void getServerFormat(rfbPixelFormat &format) override;
|
||||||
void startMonitor() override;
|
void startMonitor() override;
|
||||||
void stopMonitor() override;
|
void stopMonitor() override;
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
SPDX-License-Identifier: GPL-2.0-or-later
|
SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "xcb_framebufferplugin.h"
|
#include "xcb_framebufferplugin.h"
|
||||||
#include "xcb_framebuffer.h"
|
#include "xcb_framebuffer.h"
|
||||||
#include <KPluginFactory>
|
#include <KPluginFactory>
|
||||||
@@ -23,4 +22,3 @@ FrameBuffer *XCBFrameBufferPlugin::frameBuffer(const QVariantMap &args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#include "xcb_framebufferplugin.moc"
|
#include "xcb_framebufferplugin.moc"
|
||||||
|
|
||||||
|
|||||||
@@ -1,31 +1,28 @@
|
|||||||
/* This file is part of the KDE project
|
/* This file is part of the KDE project
|
||||||
SPDX-FileCopyrightText: Alexey Min <alexey.min@gmail.com>
|
SPDX-FileCopyrightText: Alexey Min <alexey.min@gmail.com>
|
||||||
|
|
||||||
SPDX-License-Identifier: GPL-2.0-or-later
|
SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef KRFB_FRAMEBUFFER_XCB_XCBFRAMEBUFFERPLUGIN_H
|
#ifndef KRFB_FRAMEBUFFER_XCB_XCBFRAMEBUFFERPLUGIN_H
|
||||||
#define KRFB_FRAMEBUFFER_XCB_XCBFRAMEBUFFERPLUGIN_H
|
#define KRFB_FRAMEBUFFER_XCB_XCBFRAMEBUFFERPLUGIN_H
|
||||||
|
|
||||||
|
|
||||||
#include "framebufferplugin.h"
|
#include "framebufferplugin.h"
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
|
|
||||||
class FrameBuffer;
|
class FrameBuffer;
|
||||||
|
|
||||||
class XCBFrameBufferPlugin: public FrameBufferPlugin
|
class XCBFrameBufferPlugin : public FrameBufferPlugin
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
XCBFrameBufferPlugin(QObject *parent, const QVariantList &args);
|
XCBFrameBufferPlugin(QObject *parent, const QVariantList &args);
|
||||||
|
|
||||||
FrameBuffer *frameBuffer(const QVariantMap &args) override;
|
FrameBuffer *frameBuffer(const QVariantMap &args) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(XCBFrameBufferPlugin)
|
Q_DISABLE_COPY(XCBFrameBufferPlugin)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // Header guard
|
||||||
#endif // Header guard
|
|
||||||
|
|||||||
@@ -11,20 +11,20 @@
|
|||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
|
|
||||||
|
#include <KConfigGroup>
|
||||||
|
#include <KGuiItem>
|
||||||
#include <KLocalizedString>
|
#include <KLocalizedString>
|
||||||
#include <KStandardGuiItem>
|
#include <KStandardGuiItem>
|
||||||
#include <KConfigGroup>
|
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <KGuiItem>
|
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
template <typename UI>
|
template<typename UI>
|
||||||
ConnectionDialog<UI>::ConnectionDialog(QWidget *parent)
|
ConnectionDialog<UI>::ConnectionDialog(QWidget *parent)
|
||||||
: QDialog(parent)
|
: QDialog(parent)
|
||||||
{
|
{
|
||||||
setWindowTitle(i18n("New Connection"));
|
setWindowTitle(i18n("New Connection"));
|
||||||
auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
|
auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||||
auto mainWidget = new QWidget(this);
|
auto mainWidget = new QWidget(this);
|
||||||
auto mainLayout = new QVBoxLayout;
|
auto mainLayout = new QVBoxLayout;
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#include "ui_connectionwidget.h"
|
#include "ui_connectionwidget.h"
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
|
|
||||||
template <typename UI>
|
template<typename UI>
|
||||||
class ConnectionDialog : public QDialog
|
class ConnectionDialog : public QDialog
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -27,14 +27,14 @@ protected:
|
|||||||
UI m_ui;
|
UI m_ui;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename UI>
|
template<typename UI>
|
||||||
void ConnectionDialog<UI>::setAllowRemoteControl(bool b)
|
void ConnectionDialog<UI>::setAllowRemoteControl(bool b)
|
||||||
{
|
{
|
||||||
m_ui.cbAllowRemoteControl->setChecked(b);
|
m_ui.cbAllowRemoteControl->setChecked(b);
|
||||||
m_ui.cbAllowRemoteControl->setVisible(b);
|
m_ui.cbAllowRemoteControl->setVisible(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename UI>
|
template<typename UI>
|
||||||
bool ConnectionDialog<UI>::allowRemoteControl()
|
bool ConnectionDialog<UI>::allowRemoteControl()
|
||||||
{
|
{
|
||||||
return m_ui.cbAllowRemoteControl->isChecked();
|
return m_ui.cbAllowRemoteControl->isChecked();
|
||||||
@@ -47,10 +47,9 @@ class InvitationsConnectionDialog : public ConnectionDialog<Ui::ConnectionWidget
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit InvitationsConnectionDialog(QWidget *parent);
|
explicit InvitationsConnectionDialog(QWidget *parent);
|
||||||
void setRemoteHost(const QString & host);
|
void setRemoteHost(const QString &host);
|
||||||
};
|
};
|
||||||
|
|
||||||
//*********
|
//*********
|
||||||
|
|
||||||
#endif // CONNECTIONDIALOG_H
|
#endif // CONNECTIONDIALOG_H
|
||||||
|
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
#define EVENTS_H
|
#define EVENTS_H
|
||||||
|
|
||||||
#include "framebuffer.h"
|
#include "framebuffer.h"
|
||||||
#include "rfb.h"
|
|
||||||
#include "krfbprivate_export.h"
|
#include "krfbprivate_export.h"
|
||||||
|
#include "rfb.h"
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
@@ -29,6 +29,7 @@ public:
|
|||||||
|
|
||||||
void setFrameBufferPlugin(const QSharedPointer<FrameBuffer> &frameBuffer);
|
void setFrameBufferPlugin(const QSharedPointer<FrameBuffer> &frameBuffer);
|
||||||
QSharedPointer<FrameBuffer> frameBuffer();
|
QSharedPointer<FrameBuffer> frameBuffer();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Used to track framebuffer plugin which we need for xdp event plugin
|
// Used to track framebuffer plugin which we need for xdp event plugin
|
||||||
QSharedPointer<FrameBuffer> fb;
|
QSharedPointer<FrameBuffer> fb;
|
||||||
|
|||||||
@@ -9,15 +9,14 @@
|
|||||||
|
|
||||||
#include "eventsplugin.h"
|
#include "eventsplugin.h"
|
||||||
#include "krfbconfig.h"
|
#include "krfbconfig.h"
|
||||||
#include "rfbservermanager.h"
|
|
||||||
#include "krfbdebug.h"
|
#include "krfbdebug.h"
|
||||||
|
#include "rfbservermanager.h"
|
||||||
|
|
||||||
#include <QGlobalStatic>
|
#include <QGlobalStatic>
|
||||||
|
|
||||||
#include <KPluginFactory>
|
#include <KPluginFactory>
|
||||||
#include <KPluginMetaData>
|
#include <KPluginMetaData>
|
||||||
|
|
||||||
|
|
||||||
class EventsManagerStatic
|
class EventsManagerStatic
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -40,8 +40,7 @@ private:
|
|||||||
EventsManager();
|
EventsManager();
|
||||||
|
|
||||||
QMap<QString, EventsPlugin *> m_plugins;
|
QMap<QString, EventsPlugin *> m_plugins;
|
||||||
QList<QWeakPointer<EventHandler> > m_eventHandlers;
|
QList<QWeakPointer<EventHandler>> m_eventHandlers;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // Header guard
|
||||||
#endif // Header guard
|
|
||||||
|
|||||||
@@ -10,8 +10,8 @@
|
|||||||
|
|
||||||
#include "krfbprivate_export.h"
|
#include "krfbprivate_export.h"
|
||||||
|
|
||||||
#include <QtCore/QVariantList>
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
#include <QtCore/QVariantList>
|
||||||
|
|
||||||
class EventHandler;
|
class EventHandler;
|
||||||
|
|
||||||
@@ -25,5 +25,4 @@ public:
|
|||||||
virtual EventHandler *eventHandler() = 0;
|
virtual EventHandler *eventHandler() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // Header guard
|
#endif // Header guard
|
||||||
|
|
||||||
|
|||||||
@@ -6,9 +6,8 @@
|
|||||||
|
|
||||||
#include "framebuffer.h"
|
#include "framebuffer.h"
|
||||||
|
|
||||||
#include <config-krfb.h>
|
|
||||||
#include <QCursor>
|
#include <QCursor>
|
||||||
|
#include <config-krfb.h>
|
||||||
|
|
||||||
FrameBuffer::FrameBuffer(QObject *parent)
|
FrameBuffer::FrameBuffer(QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
@@ -25,7 +24,7 @@ char *FrameBuffer::data()
|
|||||||
return fb;
|
return fb;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList< QRect > FrameBuffer::modifiedTiles()
|
QList<QRect> FrameBuffer::modifiedTiles()
|
||||||
{
|
{
|
||||||
QList<QRect> ret = tiles;
|
QList<QRect> ret = tiles;
|
||||||
tiles.clear();
|
tiles.clear();
|
||||||
|
|||||||
@@ -11,13 +11,12 @@
|
|||||||
|
|
||||||
#include "krfbprivate_export.h"
|
#include "krfbprivate_export.h"
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QRect>
|
#include <QRect>
|
||||||
#include <QList>
|
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
|
|
||||||
class FrameBuffer;
|
class FrameBuffer;
|
||||||
/**
|
/**
|
||||||
@author Alessandro Praduroux <pradu@pradu.it>
|
@author Alessandro Praduroux <pradu@pradu.it>
|
||||||
@@ -54,7 +53,6 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(FrameBuffer)
|
Q_DISABLE_COPY(FrameBuffer)
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -11,13 +11,12 @@
|
|||||||
#include "krfbconfig.h"
|
#include "krfbconfig.h"
|
||||||
#include "krfbdebug.h"
|
#include "krfbdebug.h"
|
||||||
|
|
||||||
#include <QGuiApplication>
|
|
||||||
#include <QGlobalStatic>
|
#include <QGlobalStatic>
|
||||||
|
#include <QGuiApplication>
|
||||||
|
|
||||||
#include <KPluginFactory>
|
#include <KPluginFactory>
|
||||||
#include <KPluginMetaData>
|
#include <KPluginMetaData>
|
||||||
|
|
||||||
|
|
||||||
class FrameBufferManagerStatic
|
class FrameBufferManagerStatic
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -28,10 +27,11 @@ Q_GLOBAL_STATIC(FrameBufferManagerStatic, frameBufferManagerStatic)
|
|||||||
|
|
||||||
FrameBufferManager::FrameBufferManager()
|
FrameBufferManager::FrameBufferManager()
|
||||||
{
|
{
|
||||||
const auto platformFilter = [] (const KPluginMetaData &pluginData) {
|
const auto platformFilter = [](const KPluginMetaData &pluginData) {
|
||||||
return pluginData.value(QStringLiteral("X-KDE-OnlyShowOnQtPlatforms"), QStringList()).contains(QGuiApplication::platformName());
|
return pluginData.value(QStringLiteral("X-KDE-OnlyShowOnQtPlatforms"), QStringList()).contains(QGuiApplication::platformName());
|
||||||
};
|
};
|
||||||
const QList<KPluginMetaData> plugins = KPluginMetaData::findPlugins(QStringLiteral("krfb/framebuffer"), platformFilter, KPluginMetaData::AllowEmptyMetaData);
|
const QList<KPluginMetaData> plugins =
|
||||||
|
KPluginMetaData::findPlugins(QStringLiteral("krfb/framebuffer"), platformFilter, KPluginMetaData::AllowEmptyMetaData);
|
||||||
for (const KPluginMetaData &data : plugins) {
|
for (const KPluginMetaData &data : plugins) {
|
||||||
const KPluginFactory::Result<FrameBufferPlugin> result = KPluginFactory::instantiatePlugin<FrameBufferPlugin>(data);
|
const KPluginFactory::Result<FrameBufferPlugin> result = KPluginFactory::instantiatePlugin<FrameBufferPlugin>(data);
|
||||||
if (result.plugin) {
|
if (result.plugin) {
|
||||||
@@ -59,10 +59,10 @@ QSharedPointer<FrameBuffer> FrameBufferManager::frameBuffer(WId id, const QVaria
|
|||||||
QWeakPointer<FrameBuffer> weakFrameBuffer = m_frameBuffers.value(id);
|
QWeakPointer<FrameBuffer> weakFrameBuffer = m_frameBuffers.value(id);
|
||||||
|
|
||||||
if (weakFrameBuffer) {
|
if (weakFrameBuffer) {
|
||||||
//qDebug() << "Found cached frame buffer.";
|
// qDebug() << "Found cached frame buffer.";
|
||||||
return weakFrameBuffer.toStrongRef();
|
return weakFrameBuffer.toStrongRef();
|
||||||
} else {
|
} else {
|
||||||
//qDebug() << "Found deleted cached frame buffer. Don't use.";
|
// qDebug() << "Found deleted cached frame buffer. Don't use.";
|
||||||
m_frameBuffers.remove(id);
|
m_frameBuffers.remove(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,9 +40,7 @@ private:
|
|||||||
FrameBufferManager();
|
FrameBufferManager();
|
||||||
|
|
||||||
QMap<QString, FrameBufferPlugin *> m_plugins;
|
QMap<QString, FrameBufferPlugin *> m_plugins;
|
||||||
QMap<WId, QWeakPointer<FrameBuffer> > m_frameBuffers;
|
QMap<WId, QWeakPointer<FrameBuffer>> m_frameBuffers;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // Header guard
|
||||||
#endif // Header guard
|
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
#include <QVariantList>
|
#include <QVariantList>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
|
|
||||||
class FrameBuffer;
|
class FrameBuffer;
|
||||||
|
|
||||||
class KRFBPRIVATE_EXPORT FrameBufferPlugin : public QObject
|
class KRFBPRIVATE_EXPORT FrameBufferPlugin : public QObject
|
||||||
@@ -27,5 +26,4 @@ public:
|
|||||||
virtual FrameBuffer *frameBuffer(const QVariantMap &args) = 0;
|
virtual FrameBuffer *frameBuffer(const QVariantMap &args) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // Header guard
|
#endif // Header guard
|
||||||
|
|
||||||
|
|||||||
@@ -7,38 +7,41 @@
|
|||||||
|
|
||||||
SPDX-License-Identifier: GPL-2.0-or-later
|
SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
*/
|
*/
|
||||||
#include "rfb.h"
|
|
||||||
#include "invitationsrfbclient.h"
|
#include "invitationsrfbclient.h"
|
||||||
|
#include "connectiondialog.h"
|
||||||
#include "invitationsrfbserver.h"
|
#include "invitationsrfbserver.h"
|
||||||
#include "krfbconfig.h"
|
#include "krfbconfig.h"
|
||||||
#include "sockethelpers.h"
|
|
||||||
#include "connectiondialog.h"
|
|
||||||
#include "krfbdebug.h"
|
#include "krfbdebug.h"
|
||||||
|
#include "rfb.h"
|
||||||
|
#include "sockethelpers.h"
|
||||||
|
|
||||||
#include <KNotification>
|
|
||||||
#include <KLocalizedString>
|
#include <KLocalizedString>
|
||||||
|
#include <KNotification>
|
||||||
|
|
||||||
|
#include <KConfigGroup>
|
||||||
#include <QSocketNotifier>
|
#include <QSocketNotifier>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <KConfigGroup>
|
|
||||||
|
|
||||||
struct PendingInvitationsRfbClient::Private
|
struct PendingInvitationsRfbClient::Private {
|
||||||
{
|
Private(rfbClientPtr client)
|
||||||
Private(rfbClientPtr client) :
|
: client(client)
|
||||||
client(client),
|
, askOnConnect(true)
|
||||||
askOnConnect(true)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
rfbClientPtr client;
|
rfbClientPtr client;
|
||||||
QSocketNotifier *notifier = nullptr;
|
QSocketNotifier *notifier = nullptr;
|
||||||
bool askOnConnect;
|
bool askOnConnect;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void clientGoneHookNoop(rfbClientPtr cl) { Q_UNUSED(cl); }
|
static void clientGoneHookNoop(rfbClientPtr cl)
|
||||||
|
{
|
||||||
|
Q_UNUSED(cl);
|
||||||
|
}
|
||||||
|
|
||||||
PendingInvitationsRfbClient::PendingInvitationsRfbClient(rfbClientPtr client, QObject *parent) :
|
PendingInvitationsRfbClient::PendingInvitationsRfbClient(rfbClientPtr client, QObject *parent)
|
||||||
PendingRfbClient(client, parent),
|
: PendingRfbClient(client, parent)
|
||||||
d(new Private(client))
|
, d(new Private(client))
|
||||||
{
|
{
|
||||||
d->client->clientGoneHook = clientGoneHookNoop;
|
d->client->clientGoneHook = clientGoneHookNoop;
|
||||||
}
|
}
|
||||||
@@ -53,16 +56,11 @@ void PendingInvitationsRfbClient::processNewClient()
|
|||||||
QString host = peerAddress(m_rfbClient->sock) + QLatin1Char(':') + QString::number(peerPort(m_rfbClient->sock));
|
QString host = peerAddress(m_rfbClient->sock) + QLatin1Char(':') + QString::number(peerPort(m_rfbClient->sock));
|
||||||
|
|
||||||
if (d->askOnConnect == false) {
|
if (d->askOnConnect == false) {
|
||||||
|
KNotification::event(QStringLiteral("NewConnectionAutoAccepted"), i18n("Accepted connection from %1", host));
|
||||||
KNotification::event(QStringLiteral("NewConnectionAutoAccepted"),
|
|
||||||
i18n("Accepted connection from %1", host));
|
|
||||||
accept(new InvitationsRfbClient(m_rfbClient, parent()));
|
accept(new InvitationsRfbClient(m_rfbClient, parent()));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
KNotification::event(QStringLiteral("NewConnectionOnHold"), i18n("Received connection from %1, on hold (waiting for confirmation)", host));
|
||||||
KNotification::event(QStringLiteral("NewConnectionOnHold"),
|
|
||||||
i18n("Received connection from %1, on hold (waiting for confirmation)",
|
|
||||||
host));
|
|
||||||
|
|
||||||
auto dialog = new InvitationsConnectionDialog(nullptr);
|
auto dialog = new InvitationsConnectionDialog(nullptr);
|
||||||
dialog->setRemoteHost(host);
|
dialog->setRemoteHost(host);
|
||||||
@@ -75,20 +73,17 @@ void PendingInvitationsRfbClient::processNewClient()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PendingInvitationsRfbClient::checkPassword(const QByteArray & encryptedPassword)
|
bool PendingInvitationsRfbClient::checkPassword(const QByteArray &encryptedPassword)
|
||||||
{
|
{
|
||||||
qCDebug(KRFB) << "about to start authentication";
|
qCDebug(KRFB) << "about to start authentication";
|
||||||
|
|
||||||
if(InvitationsRfbServer::instance->allowUnattendedAccess() && vncAuthCheckPassword(
|
if (InvitationsRfbServer::instance->allowUnattendedAccess()
|
||||||
InvitationsRfbServer::instance->unattendedPassword().toLocal8Bit(),
|
&& vncAuthCheckPassword(InvitationsRfbServer::instance->unattendedPassword().toLocal8Bit(), encryptedPassword)) {
|
||||||
encryptedPassword) ) {
|
|
||||||
d->askOnConnect = false;
|
d->askOnConnect = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return vncAuthCheckPassword(
|
return vncAuthCheckPassword(InvitationsRfbServer::instance->desktopPassword().toLocal8Bit(), encryptedPassword);
|
||||||
InvitationsRfbServer::instance->desktopPassword().toLocal8Bit(),
|
|
||||||
encryptedPassword);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PendingInvitationsRfbClient::dialogAccepted()
|
void PendingInvitationsRfbClient::dialogAccepted()
|
||||||
|
|||||||
@@ -12,11 +12,12 @@
|
|||||||
class InvitationsRfbClient : public RfbClient
|
class InvitationsRfbClient : public RfbClient
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit InvitationsRfbClient(rfbClientPtr client, QObject* parent = nullptr)
|
explicit InvitationsRfbClient(rfbClientPtr client, QObject *parent = nullptr)
|
||||||
: RfbClient(client, parent) {}
|
: RfbClient(client, parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class PendingInvitationsRfbClient : public PendingRfbClient
|
class PendingInvitationsRfbClient : public PendingRfbClient
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -26,14 +27,14 @@ public:
|
|||||||
|
|
||||||
protected Q_SLOTS:
|
protected Q_SLOTS:
|
||||||
void processNewClient() override;
|
void processNewClient() override;
|
||||||
bool checkPassword(const QByteArray & encryptedPassword) override;
|
bool checkPassword(const QByteArray &encryptedPassword) override;
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void dialogAccepted();
|
void dialogAccepted();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Private;
|
struct Private;
|
||||||
Private* const d;
|
Private *const d;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INVITATIONSRFBCLIENT_H
|
#endif // INVITATIONSRFBCLIENT_H
|
||||||
|
|||||||
@@ -11,14 +11,14 @@
|
|||||||
#include "invitationsrfbclient.h"
|
#include "invitationsrfbclient.h"
|
||||||
#include "krfbconfig.h"
|
#include "krfbconfig.h"
|
||||||
#include "krfbdebug.h"
|
#include "krfbdebug.h"
|
||||||
#include <QTimer>
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QHostInfo>
|
#include <QHostInfo>
|
||||||
#include <QRandomGenerator>
|
#include <QRandomGenerator>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
#include <KLocalizedString>
|
#include <KLocalizedString>
|
||||||
#include <KUser>
|
|
||||||
#include <KStringHandler>
|
#include <KStringHandler>
|
||||||
|
#include <KUser>
|
||||||
#include <KWallet>
|
#include <KWallet>
|
||||||
|
|
||||||
#include <KDNSSD/PublicService>
|
#include <KDNSSD/PublicService>
|
||||||
@@ -28,19 +28,16 @@ using KWallet::Wallet;
|
|||||||
// used for KWallet folder name
|
// used for KWallet folder name
|
||||||
static const QString s_krfbFolderName(QStringLiteral("krfb"));
|
static const QString s_krfbFolderName(QStringLiteral("krfb"));
|
||||||
|
|
||||||
//static
|
// static
|
||||||
InvitationsRfbServer *InvitationsRfbServer::instance;
|
InvitationsRfbServer *InvitationsRfbServer::instance;
|
||||||
|
|
||||||
//static
|
// static
|
||||||
void InvitationsRfbServer::init()
|
void InvitationsRfbServer::init()
|
||||||
{
|
{
|
||||||
instance = new InvitationsRfbServer;
|
instance = new InvitationsRfbServer;
|
||||||
instance->m_publicService = new KDNSSD::PublicService(
|
instance->m_publicService = new KDNSSD::PublicService(i18n("%1@%2 (shared desktop)", KUser().loginName(), QHostInfo::localHostName()),
|
||||||
i18n("%1@%2 (shared desktop)",
|
QStringLiteral("_rfb._tcp"),
|
||||||
KUser().loginName(),
|
KrfbConfig::port());
|
||||||
QHostInfo::localHostName()),
|
|
||||||
QStringLiteral("_rfb._tcp"),
|
|
||||||
KrfbConfig::port());
|
|
||||||
instance->setListeningAddress("0.0.0.0");
|
instance->setListeningAddress("0.0.0.0");
|
||||||
instance->setListeningPort(KrfbConfig::port());
|
instance->setListeningPort(KrfbConfig::port());
|
||||||
instance->setPasswordRequired(true);
|
instance->setPasswordRequired(true);
|
||||||
@@ -53,12 +50,12 @@ void InvitationsRfbServer::init()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString& InvitationsRfbServer::desktopPassword() const
|
const QString &InvitationsRfbServer::desktopPassword() const
|
||||||
{
|
{
|
||||||
return m_desktopPassword;
|
return m_desktopPassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InvitationsRfbServer::setDesktopPassword(const QString& password)
|
void InvitationsRfbServer::setDesktopPassword(const QString &password)
|
||||||
{
|
{
|
||||||
m_desktopPassword = password;
|
m_desktopPassword = password;
|
||||||
// this is called from GUI every time desktop password is edited.
|
// this is called from GUI every time desktop password is edited.
|
||||||
@@ -66,12 +63,12 @@ void InvitationsRfbServer::setDesktopPassword(const QString& password)
|
|||||||
saveSecuritySettings();
|
saveSecuritySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString& InvitationsRfbServer::unattendedPassword() const
|
const QString &InvitationsRfbServer::unattendedPassword() const
|
||||||
{
|
{
|
||||||
return m_unattendedPassword;
|
return m_unattendedPassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InvitationsRfbServer::setUnattendedPassword(const QString& password)
|
void InvitationsRfbServer::setUnattendedPassword(const QString &password)
|
||||||
{
|
{
|
||||||
m_unattendedPassword = password;
|
m_unattendedPassword = password;
|
||||||
// this is called from GUI every time unattended password is edited.
|
// this is called from GUI every time unattended password is edited.
|
||||||
@@ -86,8 +83,8 @@ bool InvitationsRfbServer::allowUnattendedAccess() const
|
|||||||
|
|
||||||
bool InvitationsRfbServer::start()
|
bool InvitationsRfbServer::start()
|
||||||
{
|
{
|
||||||
if(RfbServer::start()) {
|
if (RfbServer::start()) {
|
||||||
if(KrfbConfig::publishService())
|
if (KrfbConfig::publishService())
|
||||||
m_publicService->publishAsync();
|
m_publicService->publishAsync();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -96,7 +93,7 @@ bool InvitationsRfbServer::start()
|
|||||||
|
|
||||||
void InvitationsRfbServer::stop()
|
void InvitationsRfbServer::stop()
|
||||||
{
|
{
|
||||||
if(m_publicService->isPublished())
|
if (m_publicService->isPublished())
|
||||||
m_publicService->stop();
|
m_publicService->stop();
|
||||||
RfbServer::stop();
|
RfbServer::stop();
|
||||||
}
|
}
|
||||||
@@ -113,14 +110,13 @@ InvitationsRfbServer::InvitationsRfbServer()
|
|||||||
{
|
{
|
||||||
m_desktopPassword = readableRandomString(4) + QLatin1Char('-') + readableRandomString(3);
|
m_desktopPassword = readableRandomString(4) + QLatin1Char('-') + readableRandomString(3);
|
||||||
m_unattendedPassword = readableRandomString(4) + QLatin1Char('-') + readableRandomString(3);
|
m_unattendedPassword = readableRandomString(4) + QLatin1Char('-') + readableRandomString(3);
|
||||||
KConfigGroup krfbConfig(KSharedConfig::openConfig(),QStringLiteral("Security"));
|
KConfigGroup krfbConfig(KSharedConfig::openConfig(), QStringLiteral("Security"));
|
||||||
m_allowUnattendedAccess = krfbConfig.readEntry(
|
m_allowUnattendedAccess = krfbConfig.readEntry("allowUnattendedAccess", QVariant(false)).toBool();
|
||||||
"allowUnattendedAccess", QVariant(false)).toBool();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InvitationsRfbServer::~InvitationsRfbServer()
|
InvitationsRfbServer::~InvitationsRfbServer()
|
||||||
{
|
{
|
||||||
InvitationsRfbServer::stop(); // calling virtual funcs in destructor is bad
|
InvitationsRfbServer::stop(); // calling virtual funcs in destructor is bad
|
||||||
saveSecuritySettings();
|
saveSecuritySettings();
|
||||||
// ^^ also saves passwords in kwallet,
|
// ^^ also saves passwords in kwallet,
|
||||||
// do it before closing kwallet
|
// do it before closing kwallet
|
||||||
@@ -129,7 +125,7 @@ InvitationsRfbServer::~InvitationsRfbServer()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PendingRfbClient* InvitationsRfbServer::newClient(rfbClientPtr client)
|
PendingRfbClient *InvitationsRfbServer::newClient(rfbClientPtr client)
|
||||||
{
|
{
|
||||||
return new PendingInvitationsRfbClient(client, this);
|
return new PendingInvitationsRfbClient(client, this);
|
||||||
}
|
}
|
||||||
@@ -138,8 +134,7 @@ void InvitationsRfbServer::openKWallet()
|
|||||||
{
|
{
|
||||||
m_wallet = Wallet::openWallet(Wallet::NetworkWallet(), 0, Wallet::Asynchronous);
|
m_wallet = Wallet::openWallet(Wallet::NetworkWallet(), 0, Wallet::Asynchronous);
|
||||||
if (m_wallet) {
|
if (m_wallet) {
|
||||||
connect(instance->m_wallet, &KWallet::Wallet::walletOpened,
|
connect(instance->m_wallet, &KWallet::Wallet::walletOpened, this, &InvitationsRfbServer::walletOpened);
|
||||||
this, &InvitationsRfbServer::walletOpened);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,15 +152,13 @@ void InvitationsRfbServer::walletOpened(bool opened)
|
|||||||
QString unattendedPassword;
|
QString unattendedPassword;
|
||||||
Q_ASSERT(m_wallet);
|
Q_ASSERT(m_wallet);
|
||||||
|
|
||||||
if (opened && m_wallet->hasFolder(s_krfbFolderName) && m_wallet->setFolder(s_krfbFolderName) ) {
|
if (opened && m_wallet->hasFolder(s_krfbFolderName) && m_wallet->setFolder(s_krfbFolderName)) {
|
||||||
if (m_wallet->readPassword(QStringLiteral("desktopSharingPassword"), desktopPassword) == 0 &&
|
if (m_wallet->readPassword(QStringLiteral("desktopSharingPassword"), desktopPassword) == 0 && !desktopPassword.isEmpty()) {
|
||||||
!desktopPassword.isEmpty()) {
|
|
||||||
m_desktopPassword = desktopPassword;
|
m_desktopPassword = desktopPassword;
|
||||||
Q_EMIT passwordChanged(m_desktopPassword);
|
Q_EMIT passwordChanged(m_desktopPassword);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_wallet->readPassword(QStringLiteral("unattendedAccessPassword"), unattendedPassword) == 0 &&
|
if (m_wallet->readPassword(QStringLiteral("unattendedAccessPassword"), unattendedPassword) == 0 && !unattendedPassword.isEmpty()) {
|
||||||
!unattendedPassword.isEmpty()) {
|
|
||||||
m_unattendedPassword = unattendedPassword;
|
m_unattendedPassword = unattendedPassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,13 +183,7 @@ QString InvitationsRfbServer::readableRandomString(int length)
|
|||||||
r += 6;
|
r += 6;
|
||||||
}
|
}
|
||||||
char c = char(r);
|
char c = char(r);
|
||||||
if ((c == 'i') ||
|
if ((c == 'i') || (c == 'I') || (c == '1') || (c == 'l') || (c == 'o') || (c == 'O') || (c == '0')) {
|
||||||
(c == 'I') ||
|
|
||||||
(c == '1') ||
|
|
||||||
(c == 'l') ||
|
|
||||||
(c == 'o') ||
|
|
||||||
(c == 'O') ||
|
|
||||||
(c == '0')) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
str += QLatin1Char(c);
|
str += QLatin1Char(c);
|
||||||
@@ -235,20 +222,18 @@ void InvitationsRfbServer::saveSecuritySettings()
|
|||||||
|
|
||||||
void InvitationsRfbServer::readPasswordFromConfig()
|
void InvitationsRfbServer::readPasswordFromConfig()
|
||||||
{
|
{
|
||||||
QString desktopPassword;
|
QString desktopPassword;
|
||||||
QString unattendedPassword;
|
QString unattendedPassword;
|
||||||
KConfigGroup krfbConfig(KSharedConfig::openConfig(),QStringLiteral("Security"));
|
KConfigGroup krfbConfig(KSharedConfig::openConfig(), QStringLiteral("Security"));
|
||||||
|
|
||||||
desktopPassword = KStringHandler::obscure(krfbConfig.readEntry(
|
desktopPassword = KStringHandler::obscure(krfbConfig.readEntry("desktopPassword", QString()));
|
||||||
"desktopPassword", QString()));
|
if (!desktopPassword.isEmpty()) {
|
||||||
if(!desktopPassword.isEmpty()) {
|
m_desktopPassword = desktopPassword;
|
||||||
m_desktopPassword = desktopPassword;
|
Q_EMIT passwordChanged(m_desktopPassword);
|
||||||
Q_EMIT passwordChanged(m_desktopPassword);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
unattendedPassword = KStringHandler::obscure(krfbConfig.readEntry(
|
unattendedPassword = KStringHandler::obscure(krfbConfig.readEntry("unattendedPassword", QString()));
|
||||||
"unattendedPassword", QString()));
|
if (!unattendedPassword.isEmpty()) {
|
||||||
if(!unattendedPassword.isEmpty()) {
|
m_unattendedPassword = unattendedPassword;
|
||||||
m_unattendedPassword = unattendedPassword;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,12 +11,14 @@
|
|||||||
|
|
||||||
#include "rfbserver.h"
|
#include "rfbserver.h"
|
||||||
|
|
||||||
namespace KWallet {
|
namespace KWallet
|
||||||
class Wallet;
|
{
|
||||||
|
class Wallet;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace KDNSSD {
|
namespace KDNSSD
|
||||||
class PublicService;
|
{
|
||||||
|
class PublicService;
|
||||||
}
|
}
|
||||||
|
|
||||||
class InvitationsRfbServer : public RfbServer
|
class InvitationsRfbServer : public RfbServer
|
||||||
@@ -26,14 +28,14 @@ public:
|
|||||||
static InvitationsRfbServer *instance;
|
static InvitationsRfbServer *instance;
|
||||||
static void init();
|
static void init();
|
||||||
|
|
||||||
const QString& desktopPassword() const;
|
const QString &desktopPassword() const;
|
||||||
void setDesktopPassword(const QString&);
|
void setDesktopPassword(const QString &);
|
||||||
const QString& unattendedPassword() const;
|
const QString &unattendedPassword() const;
|
||||||
void setUnattendedPassword(const QString&);
|
void setUnattendedPassword(const QString &);
|
||||||
bool allowUnattendedAccess() const;
|
bool allowUnattendedAccess() const;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void passwordChanged(const QString&);
|
void passwordChanged(const QString &);
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
bool start() override;
|
bool start() override;
|
||||||
@@ -46,7 +48,7 @@ public Q_SLOTS:
|
|||||||
protected:
|
protected:
|
||||||
InvitationsRfbServer();
|
InvitationsRfbServer();
|
||||||
~InvitationsRfbServer() override;
|
~InvitationsRfbServer() override;
|
||||||
PendingRfbClient* newClient(rfbClientPtr client) override;
|
PendingRfbClient *newClient(rfbClientPtr client) override;
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void walletOpened(bool);
|
void walletOpened(bool);
|
||||||
|
|||||||
@@ -4,28 +4,29 @@
|
|||||||
SPDX-License-Identifier: GPL-3.0-or-later
|
SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <QApplication>
|
|
||||||
#include <QCommandLineParser>
|
|
||||||
#include <QCommandLineOption>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QTimer>
|
|
||||||
#include <KCrash>
|
|
||||||
#include <KNotification>
|
|
||||||
#include <KLocalizedString>
|
|
||||||
#include <KWindowSystem>
|
|
||||||
#include <KAboutData>
|
|
||||||
#include "sockethelpers.h"
|
|
||||||
#include "krfb_version.h"
|
#include "krfb_version.h"
|
||||||
#include "rfbserver.h"
|
#include "rfbserver.h"
|
||||||
#include <signal.h>
|
|
||||||
#include "rfbservermanager.h"
|
#include "rfbservermanager.h"
|
||||||
|
#include "sockethelpers.h"
|
||||||
|
#include <KAboutData>
|
||||||
|
#include <KCrash>
|
||||||
|
#include <KLocalizedString>
|
||||||
|
#include <KNotification>
|
||||||
|
#include <KWindowSystem>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QCommandLineOption>
|
||||||
|
#include <QCommandLineParser>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
class VirtualMonitorRfbClient : public RfbClient
|
class VirtualMonitorRfbClient : public RfbClient
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit VirtualMonitorRfbClient(rfbClientPtr client, QObject *parent = nullptr)
|
explicit VirtualMonitorRfbClient(rfbClientPtr client, QObject *parent = nullptr)
|
||||||
: RfbClient(client, parent)
|
: RfbClient(client, parent)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class PendingVirtualMonitorRfbClient : public PendingRfbClient
|
class PendingVirtualMonitorRfbClient : public PendingRfbClient
|
||||||
@@ -33,20 +34,24 @@ class PendingVirtualMonitorRfbClient : public PendingRfbClient
|
|||||||
public:
|
public:
|
||||||
explicit PendingVirtualMonitorRfbClient(rfbClientPtr client, QObject *parent = nullptr)
|
explicit PendingVirtualMonitorRfbClient(rfbClientPtr client, QObject *parent = nullptr)
|
||||||
: PendingRfbClient(client, parent)
|
: PendingRfbClient(client, parent)
|
||||||
{}
|
{
|
||||||
~PendingVirtualMonitorRfbClient() override {}
|
}
|
||||||
|
~PendingVirtualMonitorRfbClient() override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static QByteArray password;
|
static QByteArray password;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void processNewClient() override {
|
void processNewClient() override
|
||||||
|
{
|
||||||
qDebug() << "new client!";
|
qDebug() << "new client!";
|
||||||
const QString host = peerAddress(m_rfbClient->sock) + QLatin1Char(':') + QString::number(peerPort(m_rfbClient->sock));
|
const QString host = peerAddress(m_rfbClient->sock) + QLatin1Char(':') + QString::number(peerPort(m_rfbClient->sock));
|
||||||
|
|
||||||
KNotification::event(QStringLiteral("NewConnectionAutoAccepted"),
|
KNotification::event(QStringLiteral("NewConnectionAutoAccepted"), i18n("Creating a Virtual Monitor from %1", host));
|
||||||
i18n("Creating a Virtual Monitor from %1", host));
|
|
||||||
}
|
}
|
||||||
bool checkPassword(const QByteArray & encryptedPassword) override {
|
bool checkPassword(const QByteArray &encryptedPassword) override
|
||||||
|
{
|
||||||
bool b = vncAuthCheckPassword(password, encryptedPassword);
|
bool b = vncAuthCheckPassword(password, encryptedPassword);
|
||||||
if (b) {
|
if (b) {
|
||||||
QTimer::singleShot(0, this, [this] {
|
QTimer::singleShot(0, this, [this] {
|
||||||
@@ -62,7 +67,8 @@ QByteArray PendingVirtualMonitorRfbClient::password;
|
|||||||
class VirtualMonitorRfbServer : public RfbServer
|
class VirtualMonitorRfbServer : public RfbServer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PendingRfbClient *newClient(rfbClientPtr client) override {
|
PendingRfbClient *newClient(rfbClientPtr client) override
|
||||||
|
{
|
||||||
qDebug() << "new client request";
|
qDebug() << "new client request";
|
||||||
return new PendingVirtualMonitorRfbClient(client, this);
|
return new PendingVirtualMonitorRfbClient(client, this);
|
||||||
}
|
}
|
||||||
@@ -80,40 +86,40 @@ int main(int argc, char *argv[])
|
|||||||
i18n("Offer a Virtual Monitor that can be accessed remotely"),
|
i18n("Offer a Virtual Monitor that can be accessed remotely"),
|
||||||
KAboutLicense::GPL,
|
KAboutLicense::GPL,
|
||||||
i18n("(c) 2009-2010, Collabora Ltd.\n"
|
i18n("(c) 2009-2010, Collabora Ltd.\n"
|
||||||
"(c) 2007, Alessandro Praduroux\n"
|
"(c) 2007, Alessandro Praduroux\n"
|
||||||
"(c) 2001-2003, Tim Jansen\n"
|
"(c) 2001-2003, Tim Jansen\n"
|
||||||
"(c) 2001, Johannes E. Schindelin\n"
|
"(c) 2001, Johannes E. Schindelin\n"
|
||||||
"(c) 2000-2001, Const Kaplinsky\n"
|
"(c) 2000-2001, Const Kaplinsky\n"
|
||||||
"(c) 2000, Tridia Corporation\n"
|
"(c) 2000, Tridia Corporation\n"
|
||||||
"(c) 1999, AT&T Laboratories Boston\n"));
|
"(c) 1999, AT&T Laboratories Boston\n"));
|
||||||
aboutData.addAuthor(QStringLiteral("Aleix Pol i Gonzalez"), i18n("Virtual Monitor implementation"), QStringLiteral("aleixpol@kde.org"));
|
aboutData.addAuthor(QStringLiteral("Aleix Pol i Gonzalez"), i18n("Virtual Monitor implementation"), QStringLiteral("aleixpol@kde.org"));
|
||||||
aboutData.addAuthor(i18n("George Kiagiadakis"), QString(), QStringLiteral("george.kiagiadakis@collabora.co.uk"));
|
aboutData.addAuthor(i18n("George Kiagiadakis"), QString(), QStringLiteral("george.kiagiadakis@collabora.co.uk"));
|
||||||
aboutData.addAuthor(i18n("Alessandro Praduroux"), i18n("KDE4 porting"), QStringLiteral("pradu@pradu.it"));
|
aboutData.addAuthor(i18n("Alessandro Praduroux"), i18n("KDE4 porting"), QStringLiteral("pradu@pradu.it"));
|
||||||
aboutData.addAuthor(i18n("Tim Jansen"), i18n("Original author"), QStringLiteral("tim@tjansen.de"));
|
aboutData.addAuthor(i18n("Tim Jansen"), i18n("Original author"), QStringLiteral("tim@tjansen.de"));
|
||||||
aboutData.addCredit(i18n("Johannes E. Schindelin"),
|
aboutData.addCredit(i18n("Johannes E. Schindelin"), i18n("libvncserver"));
|
||||||
i18n("libvncserver"));
|
aboutData.addCredit(i18n("Const Kaplinsky"), i18n("TightVNC encoder"));
|
||||||
aboutData.addCredit(i18n("Const Kaplinsky"),
|
aboutData.addCredit(i18n("Tridia Corporation"), i18n("ZLib encoder"));
|
||||||
i18n("TightVNC encoder"));
|
|
||||||
aboutData.addCredit(i18n("Tridia Corporation"),
|
|
||||||
i18n("ZLib encoder"));
|
|
||||||
aboutData.addCredit(i18n("AT&T Laboratories Boston"),
|
aboutData.addCredit(i18n("AT&T Laboratories Boston"),
|
||||||
i18n("original VNC encoders and "
|
i18n("original VNC encoders and "
|
||||||
"protocol design"));
|
"protocol design"));
|
||||||
KAboutData::setApplicationData(aboutData);
|
KAboutData::setApplicationData(aboutData);
|
||||||
|
|
||||||
KCrash::initialize();
|
KCrash::initialize();
|
||||||
|
|
||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
aboutData.setupCommandLine(&parser);
|
aboutData.setupCommandLine(&parser);
|
||||||
const QCommandLineOption resolutionOption({ QStringLiteral("resolution") }, i18n("Logical resolution of the new monitor"), i18n("resolution"));
|
const QCommandLineOption resolutionOption({QStringLiteral("resolution")}, i18n("Logical resolution of the new monitor"), i18n("resolution"));
|
||||||
parser.addOption(resolutionOption);
|
parser.addOption(resolutionOption);
|
||||||
const QCommandLineOption nameOption({ QStringLiteral("name") }, i18n("Name of the monitor"), i18n("name"));
|
const QCommandLineOption nameOption({QStringLiteral("name")}, i18n("Name of the monitor"), i18n("name"));
|
||||||
parser.addOption(nameOption);
|
parser.addOption(nameOption);
|
||||||
const QCommandLineOption passwordOption({ QStringLiteral("password") }, i18n("Password for the client to connect to it"), i18n("password"));
|
const QCommandLineOption passwordOption({QStringLiteral("password")}, i18n("Password for the client to connect to it"), i18n("password"));
|
||||||
parser.addOption(passwordOption);
|
parser.addOption(passwordOption);
|
||||||
const QCommandLineOption scaleOption({ QStringLiteral("scale") }, i18n("The device-pixel-ratio of the device, the scaling factor"), i18n("dpr"), QStringLiteral("1"));
|
const QCommandLineOption scaleOption({QStringLiteral("scale")},
|
||||||
|
i18n("The device-pixel-ratio of the device, the scaling factor"),
|
||||||
|
i18n("dpr"),
|
||||||
|
QStringLiteral("1"));
|
||||||
parser.addOption(scaleOption);
|
parser.addOption(scaleOption);
|
||||||
const QCommandLineOption portOption({ QStringLiteral("port") }, i18n("The port we will be listening to"), i18n("number"), QStringLiteral("9999"));
|
const QCommandLineOption portOption({QStringLiteral("port")}, i18n("The port we will be listening to"), i18n("number"), QStringLiteral("9999"));
|
||||||
parser.addOption(portOption);
|
parser.addOption(portOption);
|
||||||
|
|
||||||
parser.process(app);
|
parser.process(app);
|
||||||
@@ -149,12 +155,11 @@ int main(int argc, char *argv[])
|
|||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (parser.isSet(nameOption)) {
|
if (parser.isSet(nameOption)) {
|
||||||
RfbServerManager::s_pluginArgs = {
|
RfbServerManager::s_pluginArgs = {
|
||||||
{ QStringLiteral("name"), parser.value(nameOption) },
|
{QStringLiteral("name"), parser.value(nameOption)},
|
||||||
{ QStringLiteral("resolution"), QSize(resSplit[0].toInt(), resSplit[1].toInt()) },
|
{QStringLiteral("resolution"), QSize(resSplit[0].toInt(), resSplit[1].toInt())},
|
||||||
{ QStringLiteral("scale"), parser.value(scaleOption).toDouble() },
|
{QStringLiteral("scale"), parser.value(scaleOption).toDouble()},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,12 +3,12 @@
|
|||||||
SPDX-License-Identifier: GPL-2.0-or-later
|
SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "invitationsrfbserver.h"
|
||||||
|
#include "krfb_version.h"
|
||||||
|
#include "krfbconfig.h"
|
||||||
|
#include "krfbdebug.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "trayicon.h"
|
#include "trayicon.h"
|
||||||
#include "invitationsrfbserver.h"
|
|
||||||
#include "krfbconfig.h"
|
|
||||||
#include "krfb_version.h"
|
|
||||||
#include "krfbdebug.h"
|
|
||||||
|
|
||||||
#include <KAboutData>
|
#include <KAboutData>
|
||||||
#include <KCrash>
|
#include <KCrash>
|
||||||
@@ -18,20 +18,18 @@
|
|||||||
#include <KWindowSystem>
|
#include <KWindowSystem>
|
||||||
|
|
||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
#include <qwindowdefs.h>
|
|
||||||
#include <QtGui/private/qtx11extras_p.h>
|
#include <QtGui/private/qtx11extras_p.h>
|
||||||
|
#include <qwindowdefs.h>
|
||||||
|
|
||||||
#include <csignal>
|
|
||||||
#include <X11/extensions/XTest.h>
|
|
||||||
#include <QCommandLineParser>
|
|
||||||
#include <QCommandLineOption>
|
#include <QCommandLineOption>
|
||||||
|
#include <QCommandLineParser>
|
||||||
|
#include <X11/extensions/XTest.h>
|
||||||
|
#include <csignal>
|
||||||
|
|
||||||
static bool checkX11Capabilities()
|
static bool checkX11Capabilities()
|
||||||
{
|
{
|
||||||
int bp1, bp2, majorv, minorv;
|
int bp1, bp2, majorv, minorv;
|
||||||
Bool r = XTestQueryExtension(QX11Info::display(), &bp1, &bp2,
|
Bool r = XTestQueryExtension(QX11Info::display(), &bp1, &bp2, &majorv, &minorv);
|
||||||
&majorv, &minorv);
|
|
||||||
|
|
||||||
if ((!r) || (((majorv * 1000) + minorv) < 2002)) {
|
if ((!r) || (((majorv * 1000) + minorv) < 2002)) {
|
||||||
KMessageBox::error(nullptr,
|
KMessageBox::error(nullptr,
|
||||||
@@ -44,11 +42,11 @@ static bool checkX11Capabilities()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void checkOldX11PluginConfig() {
|
static void checkOldX11PluginConfig()
|
||||||
|
{
|
||||||
if (KrfbConfig::preferredFrameBufferPlugin() == QStringLiteral("x11")) {
|
if (KrfbConfig::preferredFrameBufferPlugin() == QStringLiteral("x11")) {
|
||||||
qCDebug(KRFB) << "Detected deprecated configuration: preferredFrameBufferPlugin = x11";
|
qCDebug(KRFB) << "Detected deprecated configuration: preferredFrameBufferPlugin = x11";
|
||||||
KConfigSkeletonItem *config_item = KrfbConfig::self()->findItem(
|
KConfigSkeletonItem *config_item = KrfbConfig::self()->findItem(QStringLiteral("preferredFrameBufferPlugin"));
|
||||||
QStringLiteral("preferredFrameBufferPlugin"));
|
|
||||||
if (config_item) {
|
if (config_item) {
|
||||||
config_item->setProperty(QStringLiteral("xcb"));
|
config_item->setProperty(QStringLiteral("xcb"));
|
||||||
KrfbConfig::self()->save();
|
KrfbConfig::self()->save();
|
||||||
@@ -61,10 +59,9 @@ static void checkWaylandPluginConfig()
|
|||||||
{
|
{
|
||||||
if (KrfbConfig::preferredFrameBufferPlugin() != QStringLiteral("pw")) {
|
if (KrfbConfig::preferredFrameBufferPlugin() != QStringLiteral("pw")) {
|
||||||
qWarning() << "Wayland: Detected invalid configuration: "
|
qWarning() << "Wayland: Detected invalid configuration: "
|
||||||
"preferredFrameBufferPlugin is not pipewire: "
|
"preferredFrameBufferPlugin is not pipewire: "
|
||||||
<< KrfbConfig::preferredFrameBufferPlugin();
|
<< KrfbConfig::preferredFrameBufferPlugin();
|
||||||
KConfigSkeletonItem *config_item = KrfbConfig::self()->findItem(
|
KConfigSkeletonItem *config_item = KrfbConfig::self()->findItem(QStringLiteral("preferredFrameBufferPlugin"));
|
||||||
QStringLiteral("preferredFrameBufferPlugin"));
|
|
||||||
if (config_item) {
|
if (config_item) {
|
||||||
config_item->setProperty(QStringLiteral("pw"));
|
config_item->setProperty(QStringLiteral("pw"));
|
||||||
KrfbConfig::self()->save();
|
KrfbConfig::self()->save();
|
||||||
@@ -85,36 +82,29 @@ int main(int argc, char *argv[])
|
|||||||
i18n("VNC-compatible server to share desktops"),
|
i18n("VNC-compatible server to share desktops"),
|
||||||
KAboutLicense::GPL,
|
KAboutLicense::GPL,
|
||||||
i18n("(c) 2009-2010, Collabora Ltd.\n"
|
i18n("(c) 2009-2010, Collabora Ltd.\n"
|
||||||
"(c) 2007, Alessandro Praduroux\n"
|
"(c) 2007, Alessandro Praduroux\n"
|
||||||
"(c) 2001-2003, Tim Jansen\n"
|
"(c) 2001-2003, Tim Jansen\n"
|
||||||
"(c) 2001, Johannes E. Schindelin\n"
|
"(c) 2001, Johannes E. Schindelin\n"
|
||||||
"(c) 2000-2001, Const Kaplinsky\n"
|
"(c) 2000-2001, Const Kaplinsky\n"
|
||||||
"(c) 2000, Tridia Corporation\n"
|
"(c) 2000, Tridia Corporation\n"
|
||||||
"(c) 1999, AT&T Laboratories Boston\n"));
|
"(c) 1999, AT&T Laboratories Boston\n"));
|
||||||
aboutData.addAuthor(i18n("George Goldberg"),
|
aboutData.addAuthor(i18n("George Goldberg"), i18n("Telepathy tubes support"), QStringLiteral("george.goldberg@collabora.co.uk"));
|
||||||
i18n("Telepathy tubes support"),
|
aboutData.addAuthor(i18n("George Kiagiadakis"), QString(), QStringLiteral("george.kiagiadakis@collabora.co.uk"));
|
||||||
QStringLiteral("george.goldberg@collabora.co.uk"));
|
|
||||||
aboutData.addAuthor(i18n("George Kiagiadakis"),
|
|
||||||
QString(),
|
|
||||||
QStringLiteral("george.kiagiadakis@collabora.co.uk"));
|
|
||||||
aboutData.addAuthor(i18n("Alessandro Praduroux"), i18n("KDE4 porting"), QStringLiteral("pradu@pradu.it"));
|
aboutData.addAuthor(i18n("Alessandro Praduroux"), i18n("KDE4 porting"), QStringLiteral("pradu@pradu.it"));
|
||||||
aboutData.addAuthor(i18n("Tim Jansen"), i18n("Original author"), QStringLiteral("tim@tjansen.de"));
|
aboutData.addAuthor(i18n("Tim Jansen"), i18n("Original author"), QStringLiteral("tim@tjansen.de"));
|
||||||
aboutData.addCredit(i18n("Johannes E. Schindelin"),
|
aboutData.addCredit(i18n("Johannes E. Schindelin"), i18n("libvncserver"));
|
||||||
i18n("libvncserver"));
|
aboutData.addCredit(i18n("Const Kaplinsky"), i18n("TightVNC encoder"));
|
||||||
aboutData.addCredit(i18n("Const Kaplinsky"),
|
aboutData.addCredit(i18n("Tridia Corporation"), i18n("ZLib encoder"));
|
||||||
i18n("TightVNC encoder"));
|
|
||||||
aboutData.addCredit(i18n("Tridia Corporation"),
|
|
||||||
i18n("ZLib encoder"));
|
|
||||||
aboutData.addCredit(i18n("AT&T Laboratories Boston"),
|
aboutData.addCredit(i18n("AT&T Laboratories Boston"),
|
||||||
i18n("original VNC encoders and "
|
i18n("original VNC encoders and "
|
||||||
"protocol design"));
|
"protocol design"));
|
||||||
KAboutData::setApplicationData(aboutData);
|
KAboutData::setApplicationData(aboutData);
|
||||||
|
|
||||||
KCrash::initialize();
|
KCrash::initialize();
|
||||||
|
|
||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
aboutData.setupCommandLine(&parser);
|
aboutData.setupCommandLine(&parser);
|
||||||
const QCommandLineOption nodialogOption(QStringList{ QStringLiteral("nodialog") }, i18n("Do not show the invitations management dialog at startup"));
|
const QCommandLineOption nodialogOption(QStringList{QStringLiteral("nodialog")}, i18n("Do not show the invitations management dialog at startup"));
|
||||||
parser.addOption(nodialogOption);
|
parser.addOption(nodialogOption);
|
||||||
|
|
||||||
parser.process(app);
|
parser.process(app);
|
||||||
@@ -142,10 +132,10 @@ int main(int argc, char *argv[])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//init the core
|
// init the core
|
||||||
InvitationsRfbServer::init();
|
InvitationsRfbServer::init();
|
||||||
|
|
||||||
//init the GUI
|
// init the GUI
|
||||||
MainWindow mainWindow;
|
MainWindow mainWindow;
|
||||||
TrayIcon trayicon(&mainWindow);
|
TrayIcon trayicon(&mainWindow);
|
||||||
|
|
||||||
@@ -159,7 +149,7 @@ int main(int argc, char *argv[])
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (KrfbConfig::startMinimized()) {
|
if (KrfbConfig::startMinimized()) {
|
||||||
mainWindow.hide();
|
mainWindow.hide();
|
||||||
} else if (app.isSessionRestored() && KMainWindow::canBeRestored(1)) {
|
} else if (app.isSessionRestored() && KMainWindow::canBeRestored(1)) {
|
||||||
mainWindow.restore(1, false);
|
mainWindow.restore(1, false);
|
||||||
} else if (!parser.isSet(nodialogOption)) {
|
} else if (!parser.isSet(nodialogOption)) {
|
||||||
|
|||||||
@@ -8,42 +8,46 @@
|
|||||||
#include "invitationsrfbserver.h"
|
#include "invitationsrfbserver.h"
|
||||||
|
|
||||||
#include "krfbconfig.h"
|
#include "krfbconfig.h"
|
||||||
#include "ui_configtcp.h"
|
|
||||||
#include "ui_configsecurity.h"
|
|
||||||
#include "ui_configframebuffer.h"
|
#include "ui_configframebuffer.h"
|
||||||
|
#include "ui_configsecurity.h"
|
||||||
|
#include "ui_configtcp.h"
|
||||||
|
|
||||||
|
#include <KActionCollection>
|
||||||
#include <KConfigDialog>
|
#include <KConfigDialog>
|
||||||
#include <KLocalizedString>
|
#include <KLocalizedString>
|
||||||
#include <KMessageBox>
|
#include <KMessageBox>
|
||||||
#include <KMessageWidget>
|
#include <KMessageWidget>
|
||||||
#include <KStandardAction>
|
|
||||||
#include <KActionCollection>
|
|
||||||
#include <KNewPasswordDialog>
|
#include <KNewPasswordDialog>
|
||||||
#include <KPluginMetaData>
|
#include <KPluginMetaData>
|
||||||
|
#include <KStandardAction>
|
||||||
|
|
||||||
#include <QIcon>
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QLineEdit>
|
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QSizePolicy>
|
|
||||||
#include <QList>
|
|
||||||
#include <QSet>
|
|
||||||
#include <QNetworkInterface>
|
|
||||||
#include <QHostInfo>
|
#include <QHostInfo>
|
||||||
|
#include <QIcon>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QList>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <QNetworkInterface>
|
||||||
|
#include <QSet>
|
||||||
|
#include <QSizePolicy>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
class TCP: public QWidget, public Ui::TCP
|
class TCP : public QWidget, public Ui::TCP
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit TCP(QWidget *parent = nullptr) : QWidget(parent) {
|
explicit TCP(QWidget *parent = nullptr)
|
||||||
|
: QWidget(parent)
|
||||||
|
{
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Security: public QWidget, public Ui::Security
|
class Security : public QWidget, public Ui::Security
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Security(QWidget *parent = nullptr) : QWidget(parent) {
|
explicit Security(QWidget *parent = nullptr)
|
||||||
|
: QWidget(parent)
|
||||||
|
{
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
walletWarning = new KMessageWidget(this);
|
walletWarning = new KMessageWidget(this);
|
||||||
walletWarning->setText(i18n("Storing passwords in config file is insecure!"));
|
walletWarning->setText(i18n("Storing passwords in config file is insecure!"));
|
||||||
@@ -53,7 +57,7 @@ public:
|
|||||||
vboxLayout->addWidget(walletWarning);
|
vboxLayout->addWidget(walletWarning);
|
||||||
|
|
||||||
// show warning when "noWallet" checkbox is checked
|
// show warning when "noWallet" checkbox is checked
|
||||||
QObject::connect(kcfg_noWallet, &QCheckBox::toggled, this, [this] (bool checked) {
|
QObject::connect(kcfg_noWallet, &QCheckBox::toggled, this, [this](bool checked) {
|
||||||
walletWarning->setVisible(checked);
|
walletWarning->setVisible(checked);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -61,10 +65,12 @@ public:
|
|||||||
KMessageWidget *walletWarning = nullptr;
|
KMessageWidget *walletWarning = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ConfigFramebuffer: public QWidget, public Ui::Framebuffer
|
class ConfigFramebuffer : public QWidget, public Ui::Framebuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ConfigFramebuffer(QWidget *parent = nullptr) : QWidget(parent) {
|
ConfigFramebuffer(QWidget *parent = nullptr)
|
||||||
|
: QWidget(parent)
|
||||||
|
{
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
// hide the line edit with framebuffer string
|
// hide the line edit with framebuffer string
|
||||||
kcfg_preferredFrameBufferPlugin->hide();
|
kcfg_preferredFrameBufferPlugin->hide();
|
||||||
@@ -74,11 +80,11 @@ public:
|
|||||||
cb_preferredFrameBufferPlugin->setCurrentText(KrfbConfig::preferredFrameBufferPlugin());
|
cb_preferredFrameBufferPlugin->setCurrentText(KrfbConfig::preferredFrameBufferPlugin());
|
||||||
// connect signals between combo<->lineedit
|
// connect signals between combo<->lineedit
|
||||||
// if we change selection in combo, lineedit is updated
|
// if we change selection in combo, lineedit is updated
|
||||||
QObject::connect(cb_preferredFrameBufferPlugin, &QComboBox::currentTextChanged,
|
QObject::connect(cb_preferredFrameBufferPlugin, &QComboBox::currentTextChanged, kcfg_preferredFrameBufferPlugin, &QLineEdit::setText);
|
||||||
kcfg_preferredFrameBufferPlugin, &QLineEdit::setText);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void fillFrameBuffersCombo() {
|
void fillFrameBuffersCombo()
|
||||||
|
{
|
||||||
const QList<KPluginMetaData> plugins = KPluginMetaData::findPlugins(QStringLiteral("krfb/framebuffer"), {}, KPluginMetaData::AllowEmptyMetaData);
|
const QList<KPluginMetaData> plugins = KPluginMetaData::findPlugins(QStringLiteral("krfb/framebuffer"), {}, KPluginMetaData::AllowEmptyMetaData);
|
||||||
for (const KPluginMetaData &metadata : plugins) {
|
for (const KPluginMetaData &metadata : plugins) {
|
||||||
cb_preferredFrameBufferPlugin->addItem(metadata.pluginId());
|
cb_preferredFrameBufferPlugin->addItem(metadata.pluginId());
|
||||||
@@ -86,7 +92,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget *parent)
|
MainWindow::MainWindow(QWidget *parent)
|
||||||
: KXmlGuiWindow(parent)
|
: KXmlGuiWindow(parent)
|
||||||
{
|
{
|
||||||
@@ -100,47 +105,36 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
auto mainWidget = new QWidget;
|
auto mainWidget = new QWidget;
|
||||||
m_ui.setupUi(mainWidget);
|
m_ui.setupUi(mainWidget);
|
||||||
m_ui.krfbIconLabel->setPixmap(QIcon::fromTheme(QStringLiteral("krfb")).pixmap(128));
|
m_ui.krfbIconLabel->setPixmap(QIcon::fromTheme(QStringLiteral("krfb")).pixmap(128));
|
||||||
m_ui.enableUnattendedCheckBox->setChecked(
|
m_ui.enableUnattendedCheckBox->setChecked(InvitationsRfbServer::instance->allowUnattendedAccess());
|
||||||
InvitationsRfbServer::instance->allowUnattendedAccess());
|
|
||||||
|
|
||||||
setCentralWidget(mainWidget);
|
setCentralWidget(mainWidget);
|
||||||
|
|
||||||
connect(m_ui.passwordEditButton, &QToolButton::clicked,
|
connect(m_ui.passwordEditButton, &QToolButton::clicked, this, &MainWindow::editPassword);
|
||||||
this, &MainWindow::editPassword);
|
connect(m_ui.enableSharingCheckBox, &QCheckBox::toggled, this, &MainWindow::toggleDesktopSharing);
|
||||||
connect(m_ui.enableSharingCheckBox, &QCheckBox::toggled,
|
connect(m_ui.enableUnattendedCheckBox, &QCheckBox::toggled, InvitationsRfbServer::instance, &InvitationsRfbServer::toggleUnattendedAccess);
|
||||||
this, &MainWindow::toggleDesktopSharing);
|
connect(m_ui.unattendedPasswordButton, &QPushButton::clicked, this, &MainWindow::editUnattendedPassword);
|
||||||
connect(m_ui.enableUnattendedCheckBox, &QCheckBox::toggled,
|
connect(m_ui.addressAboutButton, &QToolButton::clicked, this, &MainWindow::aboutConnectionAddress);
|
||||||
InvitationsRfbServer::instance, &InvitationsRfbServer::toggleUnattendedAccess);
|
connect(m_ui.unattendedAboutButton, &QToolButton::clicked, this, &MainWindow::aboutUnattendedMode);
|
||||||
connect(m_ui.unattendedPasswordButton, &QPushButton::clicked,
|
connect(InvitationsRfbServer::instance, &InvitationsRfbServer::passwordChanged, this, &MainWindow::passwordChanged);
|
||||||
this, &MainWindow::editUnattendedPassword);
|
|
||||||
connect(m_ui.addressAboutButton, &QToolButton::clicked,
|
|
||||||
this, &MainWindow::aboutConnectionAddress);
|
|
||||||
connect(m_ui.unattendedAboutButton, &QToolButton::clicked,
|
|
||||||
this, &MainWindow::aboutUnattendedMode);
|
|
||||||
connect(InvitationsRfbServer::instance, &InvitationsRfbServer::passwordChanged,
|
|
||||||
this, &MainWindow::passwordChanged);
|
|
||||||
|
|
||||||
// Figure out the address
|
// Figure out the address
|
||||||
int port = KrfbConfig::port();
|
int port = KrfbConfig::port();
|
||||||
const QList<QNetworkInterface> interfaceList = QNetworkInterface::allInterfaces();
|
const QList<QNetworkInterface> interfaceList = QNetworkInterface::allInterfaces();
|
||||||
for (const QNetworkInterface& interface : interfaceList) {
|
for (const QNetworkInterface &interface : interfaceList) {
|
||||||
if(interface.flags() & QNetworkInterface::IsLoopBack)
|
if (interface.flags() & QNetworkInterface::IsLoopBack)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if(interface.flags() & QNetworkInterface::IsRunning &&
|
if (interface.flags() & QNetworkInterface::IsRunning && !interface.addressEntries().isEmpty()) {
|
||||||
!interface.addressEntries().isEmpty()) {
|
|
||||||
const QString hostName = QHostInfo::localHostName();
|
const QString hostName = QHostInfo::localHostName();
|
||||||
const QString ipAddress = interface.addressEntries().constFirst().ip().toString();
|
const QString ipAddress = interface.addressEntries().constFirst().ip().toString();
|
||||||
const QString addressLabelText = hostName.isEmpty()
|
const QString addressLabelText =
|
||||||
? QStringLiteral("%1 : %2").arg(ipAddress).arg(port)
|
hostName.isEmpty() ? QStringLiteral("%1 : %2").arg(ipAddress).arg(port) : QStringLiteral("%1 (%2) : %3").arg(hostName, ipAddress).arg(port);
|
||||||
: QStringLiteral("%1 (%2) : %3").arg(hostName, ipAddress).arg(port);
|
|
||||||
m_ui.addressDisplayLabel->setText(addressLabelText);
|
m_ui.addressDisplayLabel->setText(addressLabelText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Figure out the password
|
// Figure out the password
|
||||||
m_ui.passwordDisplayLabel->setText(
|
m_ui.passwordDisplayLabel->setText(InvitationsRfbServer::instance->desktopPassword());
|
||||||
InvitationsRfbServer::instance->desktopPassword());
|
|
||||||
|
|
||||||
KStandardAction::quit(QCoreApplication::instance(), &QCoreApplication::quit, actionCollection());
|
KStandardAction::quit(QCoreApplication::instance(), &QCoreApplication::quit, actionCollection());
|
||||||
KStandardAction::preferences(this, &MainWindow::showConfiguration, actionCollection());
|
KStandardAction::preferences(this, &MainWindow::showConfiguration, actionCollection());
|
||||||
@@ -148,7 +142,7 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
setupGUI();
|
setupGUI();
|
||||||
|
|
||||||
if (KrfbConfig::allowDesktopControl()) {
|
if (KrfbConfig::allowDesktopControl()) {
|
||||||
m_ui.enableSharingCheckBox->setChecked(true);
|
m_ui.enableSharingCheckBox->setChecked(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
setAutoSaveSettings();
|
setAutoSaveSettings();
|
||||||
@@ -160,21 +154,18 @@ MainWindow::~MainWindow()
|
|||||||
|
|
||||||
void MainWindow::editPassword()
|
void MainWindow::editPassword()
|
||||||
{
|
{
|
||||||
if(m_passwordEditable) {
|
if (m_passwordEditable) {
|
||||||
m_passwordEditable = false;
|
m_passwordEditable = false;
|
||||||
m_ui.passwordEditButton->setIcon(QIcon::fromTheme(QStringLiteral("document-properties")));
|
m_ui.passwordEditButton->setIcon(QIcon::fromTheme(QStringLiteral("document-properties")));
|
||||||
m_ui.passwordGridLayout->removeWidget(m_passwordLineEdit);
|
m_ui.passwordGridLayout->removeWidget(m_passwordLineEdit);
|
||||||
InvitationsRfbServer::instance->setDesktopPassword(
|
InvitationsRfbServer::instance->setDesktopPassword(m_passwordLineEdit->text());
|
||||||
m_passwordLineEdit->text());
|
m_ui.passwordDisplayLabel->setText(InvitationsRfbServer::instance->desktopPassword());
|
||||||
m_ui.passwordDisplayLabel->setText(
|
|
||||||
InvitationsRfbServer::instance->desktopPassword());
|
|
||||||
m_passwordLineEdit->setVisible(false);
|
m_passwordLineEdit->setVisible(false);
|
||||||
} else {
|
} else {
|
||||||
m_passwordEditable = true;
|
m_passwordEditable = true;
|
||||||
m_ui.passwordEditButton->setIcon(QIcon::fromTheme(QStringLiteral("document-save")));
|
m_ui.passwordEditButton->setIcon(QIcon::fromTheme(QStringLiteral("document-save")));
|
||||||
m_ui.passwordGridLayout->addWidget(m_passwordLineEdit,0,0);
|
m_ui.passwordGridLayout->addWidget(m_passwordLineEdit, 0, 0);
|
||||||
m_passwordLineEdit->setText(
|
m_passwordLineEdit->setText(InvitationsRfbServer::instance->desktopPassword());
|
||||||
InvitationsRfbServer::instance->desktopPassword());
|
|
||||||
m_passwordLineEdit->setVisible(true);
|
m_passwordLineEdit->setVisible(true);
|
||||||
m_passwordLineEdit->setFocus(Qt::MouseFocusReason);
|
m_passwordLineEdit->setFocus(Qt::MouseFocusReason);
|
||||||
}
|
}
|
||||||
@@ -184,23 +175,23 @@ void MainWindow::editUnattendedPassword()
|
|||||||
{
|
{
|
||||||
KNewPasswordDialog dialog(this);
|
KNewPasswordDialog dialog(this);
|
||||||
dialog.setPrompt(i18n("Enter a new password for Unattended Access"));
|
dialog.setPrompt(i18n("Enter a new password for Unattended Access"));
|
||||||
if(dialog.exec()) {
|
if (dialog.exec()) {
|
||||||
InvitationsRfbServer::instance->setUnattendedPassword(dialog.password());
|
InvitationsRfbServer::instance->setUnattendedPassword(dialog.password());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::toggleDesktopSharing(bool enable)
|
void MainWindow::toggleDesktopSharing(bool enable)
|
||||||
{
|
{
|
||||||
if(enable) {
|
if (enable) {
|
||||||
if(!InvitationsRfbServer::instance->start()) {
|
if (!InvitationsRfbServer::instance->start()) {
|
||||||
KMessageBox::error(this,
|
KMessageBox::error(this,
|
||||||
i18n("Failed to start the krfb server. Desktop sharing "
|
i18n("Failed to start the krfb server. Desktop sharing "
|
||||||
"will not work. Try setting another port in the settings "
|
"will not work. Try setting another port in the settings "
|
||||||
"and restart krfb."));
|
"and restart krfb."));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
InvitationsRfbServer::instance->stop();
|
InvitationsRfbServer::instance->stop();
|
||||||
if(m_passwordEditable) {
|
if (m_passwordEditable) {
|
||||||
m_passwordEditable = false;
|
m_passwordEditable = false;
|
||||||
m_passwordLineEdit->setVisible(false);
|
m_passwordLineEdit->setVisible(false);
|
||||||
m_ui.passwordEditButton->setIcon(QIcon::fromTheme(QStringLiteral("document-properties")));
|
m_ui.passwordEditButton->setIcon(QIcon::fromTheme(QStringLiteral("document-properties")));
|
||||||
@@ -208,7 +199,7 @@ void MainWindow::toggleDesktopSharing(bool enable)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::passwordChanged(const QString& password)
|
void MainWindow::passwordChanged(const QString &password)
|
||||||
{
|
{
|
||||||
m_passwordLineEdit->setText(password);
|
m_passwordLineEdit->setText(password);
|
||||||
m_ui.passwordDisplayLabel->setText(password);
|
m_ui.passwordDisplayLabel->setText(password);
|
||||||
@@ -216,16 +207,20 @@ void MainWindow::passwordChanged(const QString& password)
|
|||||||
|
|
||||||
void MainWindow::aboutConnectionAddress()
|
void MainWindow::aboutConnectionAddress()
|
||||||
{
|
{
|
||||||
QMessageBox::about(this,
|
QMessageBox::about(
|
||||||
i18n("KDE Desktop Sharing"),
|
this,
|
||||||
i18n("This field contains the address of your computer and the port number, separated by a colon.\n\nThe address is just a hint - you can use any address that can reach your computer.\n\nDesktop Sharing tries to guess your address from your network configuration, but does not always succeed in doing so.\n\nIf your computer is behind a firewall it may have a different address or be unreachable for other computers."));
|
i18n("KDE Desktop Sharing"),
|
||||||
|
i18n("This field contains the address of your computer and the port number, separated by a colon.\n\nThe address is just a hint - you can use any "
|
||||||
|
"address that can reach your computer.\n\nDesktop Sharing tries to guess your address from your network configuration, but does not always "
|
||||||
|
"succeed in doing so.\n\nIf your computer is behind a firewall it may have a different address or be unreachable for other computers."));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::aboutUnattendedMode()
|
void MainWindow::aboutUnattendedMode()
|
||||||
{
|
{
|
||||||
QMessageBox::about(this,
|
QMessageBox::about(this,
|
||||||
i18n("KDE Desktop Sharing"),
|
i18n("KDE Desktop Sharing"),
|
||||||
i18n("Any remote user with normal desktop sharing password will have to be authenticated.\n\nIf unattended access is on, and the remote user provides unattended mode password, desktop sharing access will be granted without explicit confirmation."));
|
i18n("Any remote user with normal desktop sharing password will have to be authenticated.\n\nIf unattended access is on, and the remote "
|
||||||
|
"user provides unattended mode password, desktop sharing access will be granted without explicit confirmation."));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::showConfiguration()
|
void MainWindow::showConfiguration()
|
||||||
@@ -247,11 +242,12 @@ void MainWindow::showConfiguration()
|
|||||||
dialog->addPage(new Security, i18n("Security"), QStringLiteral("security-high"));
|
dialog->addPage(new Security, i18n("Security"), QStringLiteral("security-high"));
|
||||||
dialog->addPage(new ConfigFramebuffer, i18n("Screen capture"), QStringLiteral("video-display"));
|
dialog->addPage(new ConfigFramebuffer, i18n("Screen capture"), QStringLiteral("video-display"));
|
||||||
dialog->show();
|
dialog->show();
|
||||||
connect(dialog, &KConfigDialog::settingsChanged, this, [this] () {
|
connect(dialog, &KConfigDialog::settingsChanged, this, [this]() {
|
||||||
// check if framebuffer plugin config has changed
|
// check if framebuffer plugin config has changed
|
||||||
if (s_prevFramebufferPlugin != KrfbConfig::preferredFrameBufferPlugin()) {
|
if (s_prevFramebufferPlugin != KrfbConfig::preferredFrameBufferPlugin()) {
|
||||||
KMessageBox::information(this, i18n("To apply framebuffer plugin setting, "
|
KMessageBox::information(this,
|
||||||
"you need to restart the program."));
|
i18n("To apply framebuffer plugin setting, "
|
||||||
|
"you need to restart the program."));
|
||||||
}
|
}
|
||||||
// check if kwallet config has changed
|
// check if kwallet config has changed
|
||||||
if (s_prevNoWallet != KrfbConfig::noWallet()) {
|
if (s_prevNoWallet != KrfbConfig::noWallet()) {
|
||||||
@@ -269,7 +265,7 @@ void MainWindow::showConfiguration()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::readProperties(const KConfigGroup& group)
|
void MainWindow::readProperties(const KConfigGroup &group)
|
||||||
{
|
{
|
||||||
if (group.readEntry("Visible", true)) {
|
if (group.readEntry("Visible", true)) {
|
||||||
show();
|
show();
|
||||||
@@ -277,7 +273,7 @@ void MainWindow::readProperties(const KConfigGroup& group)
|
|||||||
KMainWindow::readProperties(group);
|
KMainWindow::readProperties(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::saveProperties(KConfigGroup& group)
|
void MainWindow::saveProperties(KConfigGroup &group)
|
||||||
{
|
{
|
||||||
group.writeEntry("Visible", isVisible());
|
group.writeEntry("Visible", isVisible());
|
||||||
KMainWindow::saveProperties(group);
|
KMainWindow::saveProperties(group);
|
||||||
|
|||||||
@@ -18,29 +18,29 @@ class MainWindow : public KXmlGuiWindow
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit MainWindow(QWidget *parent = nullptr);
|
explicit MainWindow(QWidget *parent = nullptr);
|
||||||
~MainWindow() override;
|
~MainWindow() override;
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void showConfiguration();
|
void showConfiguration();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void readProperties(const KConfigGroup & group) override;
|
void readProperties(const KConfigGroup &group) override;
|
||||||
void saveProperties(KConfigGroup & group) override;
|
void saveProperties(KConfigGroup &group) override;
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void editPassword();
|
void editPassword();
|
||||||
void editUnattendedPassword();
|
void editUnattendedPassword();
|
||||||
void toggleDesktopSharing(bool enable);
|
void toggleDesktopSharing(bool enable);
|
||||||
void passwordChanged(const QString&);
|
void passwordChanged(const QString &);
|
||||||
void aboutConnectionAddress();
|
void aboutConnectionAddress();
|
||||||
void aboutUnattendedMode();
|
void aboutUnattendedMode();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::MainWidget m_ui;
|
Ui::MainWidget m_ui;
|
||||||
bool m_passwordEditable;
|
bool m_passwordEditable;
|
||||||
QLineEdit *m_passwordLineEdit = nullptr;
|
QLineEdit *m_passwordLineEdit = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -16,4 +16,3 @@
|
|||||||
#undef FALSE
|
#undef FALSE
|
||||||
|
|
||||||
#endif // Header guard
|
#endif // Header guard
|
||||||
|
|
||||||
|
|||||||
@@ -8,20 +8,20 @@
|
|||||||
*/
|
*/
|
||||||
#include "rfbclient.h"
|
#include "rfbclient.h"
|
||||||
#include "connectiondialog.h"
|
#include "connectiondialog.h"
|
||||||
#include "krfbconfig.h"
|
|
||||||
#include "sockethelpers.h"
|
|
||||||
#include "eventsmanager.h"
|
#include "eventsmanager.h"
|
||||||
|
#include "krfbconfig.h"
|
||||||
|
#include "krfbdebug.h"
|
||||||
|
#include "sockethelpers.h"
|
||||||
#include <QSocketNotifier>
|
#include <QSocketNotifier>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <strings.h> //for bzero()
|
#include <strings.h> //for bzero()
|
||||||
#include "krfbdebug.h"
|
|
||||||
|
|
||||||
struct RfbClient::Private
|
struct RfbClient::Private {
|
||||||
{
|
Private(rfbClientPtr client)
|
||||||
Private(rfbClientPtr client) :
|
: controlEnabled(KrfbConfig::allowDesktopControl())
|
||||||
controlEnabled(KrfbConfig::allowDesktopControl()),
|
, client(client)
|
||||||
client(client)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
bool controlEnabled;
|
bool controlEnabled;
|
||||||
rfbClientPtr client;
|
rfbClientPtr client;
|
||||||
@@ -30,11 +30,11 @@ struct RfbClient::Private
|
|||||||
QString remoteAddressString;
|
QString remoteAddressString;
|
||||||
};
|
};
|
||||||
|
|
||||||
RfbClient::RfbClient(rfbClientPtr client, QObject* parent)
|
RfbClient::RfbClient(rfbClientPtr client, QObject *parent)
|
||||||
: QObject(parent), d(new Private(client))
|
: QObject(parent)
|
||||||
|
, d(new Private(client))
|
||||||
{
|
{
|
||||||
d->remoteAddressString = peerAddress(d->client->sock) + QLatin1Char(':') +
|
d->remoteAddressString = peerAddress(d->client->sock) + QLatin1Char(':') + QString::number(peerPort(d->client->sock));
|
||||||
QString::number(peerPort(d->client->sock));
|
|
||||||
|
|
||||||
d->notifier = new QSocketNotifier(client->sock, QSocketNotifier::Read, this);
|
d->notifier = new QSocketNotifier(client->sock, QSocketNotifier::Read, this);
|
||||||
d->notifier->setEnabled(false);
|
d->notifier->setEnabled(false);
|
||||||
@@ -45,7 +45,7 @@ RfbClient::RfbClient(rfbClientPtr client, QObject* parent)
|
|||||||
|
|
||||||
RfbClient::~RfbClient()
|
RfbClient::~RfbClient()
|
||||||
{
|
{
|
||||||
//qDebug();
|
// qDebug();
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ QString RfbClient::name() const
|
|||||||
return d->remoteAddressString;
|
return d->remoteAddressString;
|
||||||
}
|
}
|
||||||
|
|
||||||
//static
|
// static
|
||||||
bool RfbClient::controlCanBeEnabled()
|
bool RfbClient::controlCanBeEnabled()
|
||||||
{
|
{
|
||||||
return KrfbConfig::allowDesktopControl();
|
return KrfbConfig::allowDesktopControl();
|
||||||
@@ -115,23 +115,23 @@ void RfbClient::handleMouseEvent(int buttonMask, int x, int y)
|
|||||||
|
|
||||||
void RfbClient::onSocketActivated()
|
void RfbClient::onSocketActivated()
|
||||||
{
|
{
|
||||||
//Process not only one, but all pending messages.
|
// Process not only one, but all pending messages.
|
||||||
//poll() idea/code copied from vino:
|
// poll() idea/code copied from vino:
|
||||||
// Copyright (C) 2003 Sun Microsystems, Inc.
|
// Copyright (C) 2003 Sun Microsystems, Inc.
|
||||||
// License: GPL v2 or later
|
// License: GPL v2 or later
|
||||||
struct pollfd pollfd = { d->client->sock, POLLIN|POLLPRI, 0 };
|
struct pollfd pollfd = {d->client->sock, POLLIN | POLLPRI, 0};
|
||||||
|
|
||||||
while(poll(&pollfd, 1, 0) == 1) {
|
while (poll(&pollfd, 1, 0) == 1) {
|
||||||
rfbProcessClientMessage(d->client);
|
rfbProcessClientMessage(d->client);
|
||||||
|
|
||||||
//This is how we handle disconnection.
|
// This is how we handle disconnection.
|
||||||
//if rfbProcessClientMessage() finds out that it can't read the socket,
|
// if rfbProcessClientMessage() finds out that it can't read the socket,
|
||||||
//it closes it and sets it to -1. So, we just have to check this here
|
// it closes it and sets it to -1. So, we just have to check this here
|
||||||
//and call rfbClientConnectionGone() if necessary. This will call
|
// and call rfbClientConnectionGone() if necessary. This will call
|
||||||
//the clientGoneHook which in turn will remove this RfbClient instance
|
// the clientGoneHook which in turn will remove this RfbClient instance
|
||||||
//from the server manager and will call deleteLater() to delete it
|
// from the server manager and will call deleteLater() to delete it
|
||||||
if (d->client->sock == -1) {
|
if (d->client->sock == -1) {
|
||||||
//qDebug() << "disconnected from socket signal";
|
// qDebug() << "disconnected from socket signal";
|
||||||
d->notifier->setEnabled(false);
|
d->notifier->setEnabled(false);
|
||||||
rfbClientConnectionGone(d->client);
|
rfbClientConnectionGone(d->client);
|
||||||
break;
|
break;
|
||||||
@@ -143,14 +143,14 @@ void RfbClient::update()
|
|||||||
{
|
{
|
||||||
rfbUpdateClient(d->client);
|
rfbUpdateClient(d->client);
|
||||||
|
|
||||||
//This is how we handle disconnection.
|
// This is how we handle disconnection.
|
||||||
//if rfbUpdateClient() finds out that it can't write to the socket,
|
// if rfbUpdateClient() finds out that it can't write to the socket,
|
||||||
//it closes it and sets it to -1. So, we just have to check this here
|
// it closes it and sets it to -1. So, we just have to check this here
|
||||||
//and call rfbClientConnectionGone() if necessary. This will call
|
// and call rfbClientConnectionGone() if necessary. This will call
|
||||||
//the clientGoneHook which in turn will remove this RfbClient instance
|
// the clientGoneHook which in turn will remove this RfbClient instance
|
||||||
//from the server manager and will call deleteLater() to delete it
|
// from the server manager and will call deleteLater() to delete it
|
||||||
if (d->client->sock == -1) {
|
if (d->client->sock == -1) {
|
||||||
//qDebug() << "disconnected during update";
|
// qDebug() << "disconnected during update";
|
||||||
d->notifier->setEnabled(false);
|
d->notifier->setEnabled(false);
|
||||||
rfbClientConnectionGone(d->client);
|
rfbClientConnectionGone(d->client);
|
||||||
}
|
}
|
||||||
@@ -159,22 +159,23 @@ void RfbClient::update()
|
|||||||
//*************
|
//*************
|
||||||
|
|
||||||
PendingRfbClient::PendingRfbClient(rfbClientPtr client, QObject *parent)
|
PendingRfbClient::PendingRfbClient(rfbClientPtr client, QObject *parent)
|
||||||
: QObject(parent), m_rfbClient(client)
|
: QObject(parent)
|
||||||
|
, m_rfbClient(client)
|
||||||
, m_notifier(new QSocketNotifier(client->sock, QSocketNotifier::Read, this))
|
, m_notifier(new QSocketNotifier(client->sock, QSocketNotifier::Read, this))
|
||||||
{
|
{
|
||||||
m_rfbClient->clientData = this;
|
m_rfbClient->clientData = this;
|
||||||
|
|
||||||
m_notifier->setEnabled(true);
|
m_notifier->setEnabled(true);
|
||||||
connect(m_notifier, &QSocketNotifier::activated,
|
connect(m_notifier, &QSocketNotifier::activated, this, &PendingRfbClient::onSocketActivated);
|
||||||
this, &PendingRfbClient::onSocketActivated);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PendingRfbClient::~PendingRfbClient()
|
PendingRfbClient::~PendingRfbClient()
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void PendingRfbClient::accept(RfbClient *newClient)
|
void PendingRfbClient::accept(RfbClient *newClient)
|
||||||
{
|
{
|
||||||
//qDebug() << "accepted connection";
|
// qDebug() << "accepted connection";
|
||||||
|
|
||||||
m_rfbClient->clientData = newClient;
|
m_rfbClient->clientData = newClient;
|
||||||
newClient->setOnHold(false);
|
newClient->setOnHold(false);
|
||||||
@@ -183,13 +184,16 @@ void PendingRfbClient::accept(RfbClient *newClient)
|
|||||||
deleteLater();
|
deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clientGoneHookNoop(rfbClientPtr cl) { Q_UNUSED(cl); }
|
static void clientGoneHookNoop(rfbClientPtr cl)
|
||||||
|
{
|
||||||
|
Q_UNUSED(cl);
|
||||||
|
}
|
||||||
|
|
||||||
void PendingRfbClient::reject()
|
void PendingRfbClient::reject()
|
||||||
{
|
{
|
||||||
//qDebug() << "refused connection";
|
// qDebug() << "refused connection";
|
||||||
|
|
||||||
//override the clientGoneHook that was previously set by RfbServer
|
// override the clientGoneHook that was previously set by RfbServer
|
||||||
m_rfbClient->clientGoneHook = clientGoneHookNoop;
|
m_rfbClient->clientGoneHook = clientGoneHookNoop;
|
||||||
rfbCloseClient(m_rfbClient);
|
rfbCloseClient(m_rfbClient);
|
||||||
rfbClientConnectionGone(m_rfbClient);
|
rfbClientConnectionGone(m_rfbClient);
|
||||||
@@ -198,28 +202,27 @@ void PendingRfbClient::reject()
|
|||||||
deleteLater();
|
deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PendingRfbClient::checkPassword(const QByteArray & encryptedPassword)
|
bool PendingRfbClient::checkPassword(const QByteArray &encryptedPassword)
|
||||||
{
|
{
|
||||||
Q_UNUSED(encryptedPassword);
|
Q_UNUSED(encryptedPassword);
|
||||||
|
|
||||||
return m_rfbClient->screen->authPasswdData == (void*)nullptr;
|
return m_rfbClient->screen->authPasswdData == (void *)nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PendingRfbClient::vncAuthCheckPassword(const QByteArray& password, const QByteArray& encryptedPassword) const
|
bool PendingRfbClient::vncAuthCheckPassword(const QByteArray &password, const QByteArray &encryptedPassword) const
|
||||||
{
|
{
|
||||||
if (password.isEmpty() && encryptedPassword.isEmpty()) {
|
if (password.isEmpty() && encryptedPassword.isEmpty()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
char passwd[MAXPWLEN+1]; // +1 to make sure there's a nullptr at the end
|
char passwd[MAXPWLEN + 1]; // +1 to make sure there's a nullptr at the end
|
||||||
unsigned char challenge[CHALLENGESIZE];
|
unsigned char challenge[CHALLENGESIZE];
|
||||||
|
|
||||||
memcpy(challenge, m_rfbClient->authChallenge, CHALLENGESIZE);
|
memcpy(challenge, m_rfbClient->authChallenge, CHALLENGESIZE);
|
||||||
memset(passwd, 0, sizeof(passwd));
|
memset(passwd, 0, sizeof(passwd));
|
||||||
|
|
||||||
if (!password.isEmpty()) {
|
if (!password.isEmpty()) {
|
||||||
strncpy(passwd, password.constData(),
|
strncpy(passwd, password.constData(), (MAXPWLEN <= password.size()) ? MAXPWLEN : password.size());
|
||||||
(MAXPWLEN <= password.size()) ? MAXPWLEN : password.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rfbEncryptBytes(challenge, passwd);
|
rfbEncryptBytes(challenge, passwd);
|
||||||
@@ -228,27 +231,27 @@ bool PendingRfbClient::vncAuthCheckPassword(const QByteArray& password, const QB
|
|||||||
|
|
||||||
void PendingRfbClient::onSocketActivated()
|
void PendingRfbClient::onSocketActivated()
|
||||||
{
|
{
|
||||||
//Process not only one, but all pending messages.
|
// Process not only one, but all pending messages.
|
||||||
//poll() idea/code copied from vino:
|
// poll() idea/code copied from vino:
|
||||||
// Copyright (C) 2003 Sun Microsystems, Inc.
|
// Copyright (C) 2003 Sun Microsystems, Inc.
|
||||||
// License: GPL v2 or later
|
// License: GPL v2 or later
|
||||||
struct pollfd pollfd = { m_rfbClient->sock, POLLIN|POLLPRI, 0 };
|
struct pollfd pollfd = {m_rfbClient->sock, POLLIN | POLLPRI, 0};
|
||||||
|
|
||||||
while(poll(&pollfd, 1, 0) == 1) {
|
while (poll(&pollfd, 1, 0) == 1) {
|
||||||
if(m_rfbClient->state == rfbClientRec::RFB_INITIALISATION) {
|
if (m_rfbClient->state == rfbClientRec::RFB_INITIALISATION) {
|
||||||
m_notifier->setEnabled(false);
|
m_notifier->setEnabled(false);
|
||||||
//Client is Authenticated
|
// Client is Authenticated
|
||||||
processNewClient();
|
processNewClient();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
rfbProcessClientMessage(m_rfbClient);
|
rfbProcessClientMessage(m_rfbClient);
|
||||||
|
|
||||||
//This is how we handle disconnection.
|
// This is how we handle disconnection.
|
||||||
//if rfbProcessClientMessage() finds out that it can't read the socket,
|
// if rfbProcessClientMessage() finds out that it can't read the socket,
|
||||||
//it closes it and sets it to -1. So, we just have to check this here
|
// it closes it and sets it to -1. So, we just have to check this here
|
||||||
//and call rfbClientConnectionGone() if necessary. This will call
|
// and call rfbClientConnectionGone() if necessary. This will call
|
||||||
//the clientGoneHook which in turn will remove this RfbClient instance
|
// the clientGoneHook which in turn will remove this RfbClient instance
|
||||||
//from the server manager and will call deleteLater() to delete it
|
// from the server manager and will call deleteLater() to delete it
|
||||||
if (m_rfbClient->sock == -1) {
|
if (m_rfbClient->sock == -1) {
|
||||||
qCDebug(KRFB) << "disconnected from socket signal";
|
qCDebug(KRFB) << "disconnected from socket signal";
|
||||||
m_notifier->setEnabled(false);
|
m_notifier->setEnabled(false);
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ Q_SIGNALS:
|
|||||||
void holdStatusChanged(bool onHold);
|
void holdStatusChanged(bool onHold);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class RfbServer; //the following event handling methods are called by RfbServer
|
friend class RfbServer; // the following event handling methods are called by RfbServer
|
||||||
|
|
||||||
rfbClientPtr getRfbClientPtr();
|
rfbClientPtr getRfbClientPtr();
|
||||||
virtual void handleKeyboardEvent(bool down, rfbKeySym keySym);
|
virtual void handleKeyboardEvent(bool down, rfbKeySym keySym);
|
||||||
@@ -50,8 +50,8 @@ private Q_SLOTS:
|
|||||||
void onSocketActivated();
|
void onSocketActivated();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
///called by RfbServerManager to send framebuffer updates
|
/// called by RfbServerManager to send framebuffer updates
|
||||||
///and check for possible disconnection
|
/// and check for possible disconnection
|
||||||
void update();
|
void update();
|
||||||
friend class RfbServerManager;
|
friend class RfbServerManager;
|
||||||
|
|
||||||
@@ -59,7 +59,6 @@ private:
|
|||||||
Private *const d;
|
Private *const d;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class PendingRfbClient : public QObject
|
class PendingRfbClient : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -77,22 +76,21 @@ protected Q_SLOTS:
|
|||||||
void reject();
|
void reject();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
friend class RfbServer; // Following two methods are handled by RfbServer
|
||||||
friend class RfbServer; //Following two methods are handled by RfbServer
|
|
||||||
|
|
||||||
/** This method is supposed to check if the provided \a encryptedPassword
|
/** This method is supposed to check if the provided \a encryptedPassword
|
||||||
* matches the criteria for authenticating the client.
|
* matches the criteria for authenticating the client.
|
||||||
* The default implementation returns false if a password is required.
|
* The default implementation returns false if a password is required.
|
||||||
* Reimplement to do more useful stuff.
|
* Reimplement to do more useful stuff.
|
||||||
*/
|
*/
|
||||||
virtual bool checkPassword(const QByteArray & encryptedPassword);
|
virtual bool checkPassword(const QByteArray &encryptedPassword);
|
||||||
|
|
||||||
/** This method checks if the \a encryptedPassword that was sent from the remote
|
/** This method checks if the \a encryptedPassword that was sent from the remote
|
||||||
* user matches the \a password that you have specified locally to be the password
|
* user matches the \a password that you have specified locally to be the password
|
||||||
* for this connection. This assumes that the standard VNC authentication mechanism
|
* for this connection. This assumes that the standard VNC authentication mechanism
|
||||||
* is used. Returns true if the password matches or false otherwise.
|
* is used. Returns true if the password matches or false otherwise.
|
||||||
*/
|
*/
|
||||||
bool vncAuthCheckPassword(const QByteArray & password, const QByteArray & encryptedPassword) const;
|
bool vncAuthCheckPassword(const QByteArray &password, const QByteArray &encryptedPassword) const;
|
||||||
|
|
||||||
rfbClientPtr m_rfbClient;
|
rfbClientPtr m_rfbClient;
|
||||||
|
|
||||||
|
|||||||
@@ -7,16 +7,15 @@
|
|||||||
SPDX-License-Identifier: GPL-2.0-or-later
|
SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
*/
|
*/
|
||||||
#include "rfbserver.h"
|
#include "rfbserver.h"
|
||||||
#include "rfbservermanager.h"
|
|
||||||
#include "krfbdebug.h"
|
#include "krfbdebug.h"
|
||||||
#include <QSocketNotifier>
|
#include "rfbservermanager.h"
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
|
#include <QSocketNotifier>
|
||||||
#include <QtGui/private/qtx11extras_p.h>
|
#include <QtGui/private/qtx11extras_p.h>
|
||||||
|
|
||||||
struct RfbServer::Private
|
struct RfbServer::Private {
|
||||||
{
|
|
||||||
QByteArray listeningAddress;
|
QByteArray listeningAddress;
|
||||||
int listeningPort;
|
int listeningPort;
|
||||||
bool passwordRequired;
|
bool passwordRequired;
|
||||||
@@ -26,7 +25,8 @@ struct RfbServer::Private
|
|||||||
};
|
};
|
||||||
|
|
||||||
RfbServer::RfbServer(QObject *parent)
|
RfbServer::RfbServer(QObject *parent)
|
||||||
: QObject(parent), d(new Private)
|
: QObject(parent)
|
||||||
|
, d(new Private)
|
||||||
{
|
{
|
||||||
d->listeningAddress = "0.0.0.0";
|
d->listeningAddress = "0.0.0.0";
|
||||||
d->listeningPort = 0;
|
d->listeningPort = 0;
|
||||||
@@ -61,7 +61,7 @@ bool RfbServer::passwordRequired() const
|
|||||||
return d->passwordRequired;
|
return d->passwordRequired;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RfbServer::setListeningAddress(const QByteArray& address)
|
void RfbServer::setListeningAddress(const QByteArray &address)
|
||||||
{
|
{
|
||||||
d->listeningAddress = address;
|
d->listeningAddress = address;
|
||||||
}
|
}
|
||||||
@@ -93,7 +93,7 @@ bool RfbServer::start()
|
|||||||
d->screen->passwordCheck = passwordCheck;
|
d->screen->passwordCheck = passwordCheck;
|
||||||
d->screen->setXCutText = clipboardHook;
|
d->screen->setXCutText = clipboardHook;
|
||||||
} else {
|
} else {
|
||||||
//if we already have a screen, stop listening first
|
// if we already have a screen, stop listening first
|
||||||
rfbShutdownServer(d->screen, false);
|
rfbShutdownServer(d->screen, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,9 +115,7 @@ bool RfbServer::start()
|
|||||||
d->screen->authPasswdData = (void *)nullptr;
|
d->screen->authPasswdData = (void *)nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(KRFB) << "Starting server. Listen port:" << listeningPort()
|
qCDebug(KRFB) << "Starting server. Listen port:" << listeningPort() << "Listen Address:" << listeningAddress() << "Password enabled:" << passwordRequired();
|
||||||
<< "Listen Address:" << listeningAddress()
|
|
||||||
<< "Password enabled:" << passwordRequired();
|
|
||||||
|
|
||||||
rfbInitServer(d->screen);
|
rfbInitServer(d->screen);
|
||||||
|
|
||||||
@@ -136,8 +134,7 @@ bool RfbServer::start()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (QX11Info::isPlatformX11()) {
|
if (QX11Info::isPlatformX11()) {
|
||||||
connect(QApplication::clipboard(), &QClipboard::dataChanged,
|
connect(QApplication::clipboard(), &QClipboard::dataChanged, this, &RfbServer::krfbSendServerCutText);
|
||||||
this, &RfbServer::krfbSendServerCutText);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -167,11 +164,11 @@ void RfbServer::updateFrameBuffer(char *fb, int width, int height, int depth)
|
|||||||
rfbNewFramebuffer(d->screen, fb, width, height, 8, 3, bpp);
|
rfbNewFramebuffer(d->screen, fb, width, height, 8, 3, bpp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RfbServer::updateScreen(const QList<QRect> & modifiedTiles)
|
void RfbServer::updateScreen(const QList<QRect> &modifiedTiles)
|
||||||
{
|
{
|
||||||
if (d->screen) {
|
if (d->screen) {
|
||||||
QList<QRect>::const_iterator it = modifiedTiles.constBegin();
|
QList<QRect>::const_iterator it = modifiedTiles.constBegin();
|
||||||
for(; it != modifiedTiles.constEnd(); ++it) {
|
for (; it != modifiedTiles.constEnd(); ++it) {
|
||||||
rfbMarkRectAsModified(d->screen, it->x(), it->y(), it->right(), it->bottom());
|
rfbMarkRectAsModified(d->screen, it->x(), it->y(), it->right(), it->bottom());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -209,7 +206,7 @@ void krfb_rfbSetCursorPosition(rfbScreenInfoPtr screen, rfbClientPtr client, int
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RfbServer::updateCursorPosition(const QPoint & position)
|
void RfbServer::updateCursorPosition(const QPoint &position)
|
||||||
{
|
{
|
||||||
if (d->screen) {
|
if (d->screen) {
|
||||||
krfb_rfbSetCursorPosition(d->screen, nullptr, position.x(), position.y());
|
krfb_rfbSetCursorPosition(d->screen, nullptr, position.x(), position.y());
|
||||||
@@ -218,10 +215,9 @@ void RfbServer::updateCursorPosition(const QPoint & position)
|
|||||||
|
|
||||||
void RfbServer::krfbSendServerCutText()
|
void RfbServer::krfbSendServerCutText()
|
||||||
{
|
{
|
||||||
if(d->screen) {
|
if (d->screen) {
|
||||||
QString text = QApplication::clipboard()->text();
|
QString text = QApplication::clipboard()->text();
|
||||||
rfbSendServerCutText(d->screen,
|
rfbSendServerCutText(d->screen, text.toLocal8Bit().data(), text.length());
|
||||||
text.toLocal8Bit().data(),text.length());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,60 +228,59 @@ void RfbServer::onListenSocketActivated()
|
|||||||
|
|
||||||
void RfbServer::pendingClientFinished(RfbClient *client)
|
void RfbServer::pendingClientFinished(RfbClient *client)
|
||||||
{
|
{
|
||||||
//qDebug();
|
// qDebug();
|
||||||
if (client) {
|
if (client) {
|
||||||
RfbServerManager::instance()->addClient(client);
|
RfbServerManager::instance()->addClient(client);
|
||||||
client->getRfbClientPtr()->clientGoneHook = clientGoneHook;
|
client->getRfbClientPtr()->clientGoneHook = clientGoneHook;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//static
|
// static
|
||||||
rfbNewClientAction RfbServer::newClientHook(rfbClientPtr cl)
|
rfbNewClientAction RfbServer::newClientHook(rfbClientPtr cl)
|
||||||
{
|
{
|
||||||
//qDebug() << "New client";
|
// qDebug() << "New client";
|
||||||
auto server = static_cast<RfbServer*>(cl->screen->screenData);
|
auto server = static_cast<RfbServer *>(cl->screen->screenData);
|
||||||
|
|
||||||
PendingRfbClient *pendingClient = server->newClient(cl);
|
PendingRfbClient *pendingClient = server->newClient(cl);
|
||||||
connect(pendingClient, &PendingRfbClient::finished,
|
connect(pendingClient, &PendingRfbClient::finished, server, &RfbServer::pendingClientFinished);
|
||||||
server, &RfbServer::pendingClientFinished);
|
|
||||||
|
|
||||||
return RFB_CLIENT_ON_HOLD;
|
return RFB_CLIENT_ON_HOLD;
|
||||||
}
|
}
|
||||||
|
|
||||||
//static
|
// static
|
||||||
void RfbServer::clientGoneHook(rfbClientPtr cl)
|
void RfbServer::clientGoneHook(rfbClientPtr cl)
|
||||||
{
|
{
|
||||||
//qDebug() << "client gone";
|
// qDebug() << "client gone";
|
||||||
auto client = static_cast<RfbClient*>(cl->clientData);
|
auto client = static_cast<RfbClient *>(cl->clientData);
|
||||||
|
|
||||||
RfbServerManager::instance()->removeClient(client);
|
RfbServerManager::instance()->removeClient(client);
|
||||||
client->deleteLater();
|
client->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
//static
|
// static
|
||||||
rfbBool RfbServer::passwordCheck(rfbClientPtr cl, const char *encryptedPassword, int len)
|
rfbBool RfbServer::passwordCheck(rfbClientPtr cl, const char *encryptedPassword, int len)
|
||||||
{
|
{
|
||||||
auto client = static_cast<PendingRfbClient*>(cl->clientData);
|
auto client = static_cast<PendingRfbClient *>(cl->clientData);
|
||||||
Q_ASSERT(client);
|
Q_ASSERT(client);
|
||||||
return client->checkPassword(QByteArray::fromRawData(encryptedPassword, len));
|
return client->checkPassword(QByteArray::fromRawData(encryptedPassword, len));
|
||||||
}
|
}
|
||||||
|
|
||||||
//static
|
// static
|
||||||
void RfbServer::keyboardHook(rfbBool down, rfbKeySym keySym, rfbClientPtr cl)
|
void RfbServer::keyboardHook(rfbBool down, rfbKeySym keySym, rfbClientPtr cl)
|
||||||
{
|
{
|
||||||
auto client = static_cast<RfbClient*>(cl->clientData);
|
auto client = static_cast<RfbClient *>(cl->clientData);
|
||||||
client->handleKeyboardEvent(down ? true : false, keySym);
|
client->handleKeyboardEvent(down ? true : false, keySym);
|
||||||
}
|
}
|
||||||
|
|
||||||
//static
|
// static
|
||||||
void RfbServer::pointerHook(int bm, int x, int y, rfbClientPtr cl)
|
void RfbServer::pointerHook(int bm, int x, int y, rfbClientPtr cl)
|
||||||
{
|
{
|
||||||
auto client = static_cast<RfbClient*>(cl->clientData);
|
auto client = static_cast<RfbClient *>(cl->clientData);
|
||||||
client->handleMouseEvent(bm, x, y);
|
client->handleMouseEvent(bm, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
//static
|
// static
|
||||||
void RfbServer::clipboardHook(char *str, int len, rfbClientPtr /*cl*/)
|
void RfbServer::clipboardHook(char *str, int len, rfbClientPtr /*cl*/)
|
||||||
{
|
{
|
||||||
QApplication::clipboard()->setText(QString::fromLocal8Bit(str,len));
|
QApplication::clipboard()->setText(QString::fromLocal8Bit(str, len));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ public:
|
|||||||
int listeningPort() const;
|
int listeningPort() const;
|
||||||
bool passwordRequired() const;
|
bool passwordRequired() const;
|
||||||
|
|
||||||
void setListeningAddress(const QByteArray & address);
|
void setListeningAddress(const QByteArray &address);
|
||||||
void setListeningPort(int port);
|
void setListeningPort(int port);
|
||||||
void setPasswordRequired(bool passwordRequired);
|
void setPasswordRequired(bool passwordRequired);
|
||||||
|
|
||||||
@@ -33,8 +33,8 @@ public Q_SLOTS:
|
|||||||
virtual void stop();
|
virtual void stop();
|
||||||
|
|
||||||
void updateFrameBuffer(char *fb, int width, int height, int depth);
|
void updateFrameBuffer(char *fb, int width, int height, int depth);
|
||||||
void updateScreen(const QList<QRect> & modifiedTiles);
|
void updateScreen(const QList<QRect> &modifiedTiles);
|
||||||
void updateCursorPosition(const QPoint & position);
|
void updateCursorPosition(const QPoint &position);
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void krfbSendServerCutText();
|
void krfbSendServerCutText();
|
||||||
|
|||||||
@@ -8,20 +8,20 @@
|
|||||||
SPDX-License-Identifier: GPL-2.0-or-later
|
SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
*/
|
*/
|
||||||
#include "rfbservermanager.h"
|
#include "rfbservermanager.h"
|
||||||
#include "rfbserver.h"
|
|
||||||
#include "framebuffermanager.h"
|
#include "framebuffermanager.h"
|
||||||
#include "sockethelpers.h"
|
|
||||||
#include "krfbconfig.h"
|
#include "krfbconfig.h"
|
||||||
#include "krfbdebug.h"
|
#include "krfbdebug.h"
|
||||||
#include <QTimer>
|
#include "rfbserver.h"
|
||||||
|
#include "sockethelpers.h"
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QGlobalStatic>
|
#include <QGlobalStatic>
|
||||||
#include <QHostInfo>
|
#include <QHostInfo>
|
||||||
|
#include <QTimer>
|
||||||
#include <qpa/qplatformnativeinterface.h>
|
#include <qpa/qplatformnativeinterface.h>
|
||||||
|
|
||||||
#include <KLocalizedString>
|
#include <KLocalizedString>
|
||||||
#include <KUser>
|
|
||||||
#include <KNotification>
|
#include <KNotification>
|
||||||
|
#include <KUser>
|
||||||
#include <KWindowSystem>
|
#include <KWindowSystem>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
@@ -69,32 +69,29 @@ static const char *mask =
|
|||||||
" xxxxx "
|
" xxxxx "
|
||||||
" xxx ";
|
" xxx ";
|
||||||
|
|
||||||
|
struct RfbServerManagerStatic {
|
||||||
struct RfbServerManagerStatic
|
|
||||||
{
|
|
||||||
RfbServerManager server;
|
RfbServerManager server;
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_GLOBAL_STATIC(RfbServerManagerStatic, s_instance)
|
Q_GLOBAL_STATIC(RfbServerManagerStatic, s_instance)
|
||||||
|
|
||||||
RfbServerManager* RfbServerManager::instance()
|
RfbServerManager *RfbServerManager::instance()
|
||||||
{
|
{
|
||||||
return &s_instance->server;
|
return &s_instance->server;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RfbServerManager::Private
|
struct RfbServerManager::Private {
|
||||||
{
|
|
||||||
QSharedPointer<FrameBuffer> fb;
|
QSharedPointer<FrameBuffer> fb;
|
||||||
rfbCursorPtr myCursor;
|
rfbCursorPtr myCursor;
|
||||||
QByteArray desktopName;
|
QByteArray desktopName;
|
||||||
QTimer rfbUpdateTimer;
|
QTimer rfbUpdateTimer;
|
||||||
QSet<RfbServer*> servers;
|
QSet<RfbServer *> servers;
|
||||||
QSet<RfbClient*> clients;
|
QSet<RfbClient *> clients;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
RfbServerManager::RfbServerManager()
|
RfbServerManager::RfbServerManager()
|
||||||
: QObject(), d(new Private)
|
: QObject()
|
||||||
|
, d(new Private)
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
@@ -113,19 +110,20 @@ QVariantMap RfbServerManager::s_pluginArgs;
|
|||||||
|
|
||||||
void RfbServerManager::init()
|
void RfbServerManager::init()
|
||||||
{
|
{
|
||||||
//qDebug();
|
// qDebug();
|
||||||
WId rootWindow = 0;
|
WId rootWindow = 0;
|
||||||
|
|
||||||
if (KWindowSystem::isPlatformX11()) {
|
if (KWindowSystem::isPlatformX11()) {
|
||||||
QPlatformNativeInterface* native = qApp->platformNativeInterface();
|
QPlatformNativeInterface *native = qApp->platformNativeInterface();
|
||||||
rootWindow = reinterpret_cast<WId>(native->nativeResourceForScreen(QByteArrayLiteral("rootwindow"), QGuiApplication::primaryScreen()));
|
rootWindow = reinterpret_cast<WId>(native->nativeResourceForScreen(QByteArrayLiteral("rootwindow"), QGuiApplication::primaryScreen()));
|
||||||
}
|
}
|
||||||
|
|
||||||
d->fb = FrameBufferManager::instance()->frameBuffer(rootWindow, s_pluginArgs);
|
d->fb = FrameBufferManager::instance()->frameBuffer(rootWindow, s_pluginArgs);
|
||||||
d->myCursor = rfbMakeXCursor(19, 19, (char *) cur, (char *) mask);
|
d->myCursor = rfbMakeXCursor(19, 19, (char *)cur, (char *)mask);
|
||||||
d->myCursor->cleanup = false;
|
d->myCursor->cleanup = false;
|
||||||
d->desktopName = QStringLiteral("%1@%2 (shared desktop)") //FIXME check if we can use utf8
|
d->desktopName = QStringLiteral("%1@%2 (shared desktop)") // FIXME check if we can use utf8
|
||||||
.arg(KUser().loginName(),QHostInfo::localHostName()).toLatin1();
|
.arg(KUser().loginName(), QHostInfo::localHostName())
|
||||||
|
.toLatin1();
|
||||||
|
|
||||||
connect(d->fb.data(), &FrameBuffer::frameBufferChanged, this, &RfbServerManager::updateFrameBuffer);
|
connect(d->fb.data(), &FrameBuffer::frameBufferChanged, this, &RfbServerManager::updateFrameBuffer);
|
||||||
connect(&d->rfbUpdateTimer, &QTimer::timeout, this, &RfbServerManager::updateScreens);
|
connect(&d->rfbUpdateTimer, &QTimer::timeout, this, &RfbServerManager::updateScreens);
|
||||||
@@ -144,26 +142,26 @@ void RfbServerManager::updateScreens()
|
|||||||
QList<QRect> rects = d->fb->modifiedTiles();
|
QList<QRect> rects = d->fb->modifiedTiles();
|
||||||
const QPoint currentCursorPos = d->fb->cursorPosition();
|
const QPoint currentCursorPos = d->fb->cursorPosition();
|
||||||
|
|
||||||
for (RfbServer* server : std::as_const(d->servers)) {
|
for (RfbServer *server : std::as_const(d->servers)) {
|
||||||
server->updateScreen(rects);
|
server->updateScreen(rects);
|
||||||
server->updateCursorPosition(currentCursorPos);
|
server->updateCursorPosition(currentCursorPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
//update() might disconnect some of the clients, which will synchronously
|
// update() might disconnect some of the clients, which will synchronously
|
||||||
//call the removeClient() method and will change d->clients, so we need
|
// call the removeClient() method and will change d->clients, so we need
|
||||||
//to copy the set here to avoid problems.
|
// to copy the set here to avoid problems.
|
||||||
const QSet<RfbClient*> clients = d->clients;
|
const QSet<RfbClient *> clients = d->clients;
|
||||||
for (RfbClient* client : clients) {
|
for (RfbClient *client : clients) {
|
||||||
client->update();
|
client->update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RfbServerManager::cleanup()
|
void RfbServerManager::cleanup()
|
||||||
{
|
{
|
||||||
//qDebug();
|
// qDebug();
|
||||||
|
|
||||||
//copy because d->servers is going to be modified while we delete the servers
|
// copy because d->servers is going to be modified while we delete the servers
|
||||||
const QSet<RfbServer*> servers = d->servers;
|
const QSet<RfbServer *> servers = d->servers;
|
||||||
qDeleteAll(servers);
|
qDeleteAll(servers);
|
||||||
|
|
||||||
Q_ASSERT(d->servers.isEmpty());
|
Q_ASSERT(d->servers.isEmpty());
|
||||||
@@ -174,12 +172,12 @@ void RfbServerManager::cleanup()
|
|||||||
d->fb.clear();
|
d->fb.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RfbServerManager::registerServer(RfbServer* server)
|
void RfbServerManager::registerServer(RfbServer *server)
|
||||||
{
|
{
|
||||||
d->servers.insert(server);
|
d->servers.insert(server);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RfbServerManager::unregisterServer(RfbServer* server)
|
void RfbServerManager::unregisterServer(RfbServer *server)
|
||||||
{
|
{
|
||||||
d->servers.remove(server);
|
d->servers.remove(server);
|
||||||
}
|
}
|
||||||
@@ -198,7 +196,7 @@ rfbScreenInfoPtr RfbServerManager::newScreen()
|
|||||||
bpp = 4;
|
bpp = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
//qDebug() << "bpp: " << bpp;
|
// qDebug() << "bpp: " << bpp;
|
||||||
|
|
||||||
rfbLogEnable(KRFB().isDebugEnabled());
|
rfbLogEnable(KRFB().isDebugEnabled());
|
||||||
|
|
||||||
@@ -213,26 +211,25 @@ rfbScreenInfoPtr RfbServerManager::newScreen()
|
|||||||
return screen;
|
return screen;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RfbServerManager::addClient(RfbClient* cc)
|
void RfbServerManager::addClient(RfbClient *cc)
|
||||||
{
|
{
|
||||||
if (d->clients.size() == 0) {
|
if (d->clients.size() == 0) {
|
||||||
//qDebug() << "Starting framebuffer monitor";
|
// qDebug() << "Starting framebuffer monitor";
|
||||||
d->fb->startMonitor();
|
d->fb->startMonitor();
|
||||||
d->rfbUpdateTimer.start(50ms);
|
d->rfbUpdateTimer.start(50ms);
|
||||||
}
|
}
|
||||||
d->clients.insert(cc);
|
d->clients.insert(cc);
|
||||||
|
|
||||||
KNotification::event(QStringLiteral("UserAcceptsConnection"),
|
KNotification::event(QStringLiteral("UserAcceptsConnection"), i18n("The remote user %1 is now connected.", cc->name()));
|
||||||
i18n("The remote user %1 is now connected.", cc->name()));
|
|
||||||
|
|
||||||
Q_EMIT clientConnected(cc);
|
Q_EMIT clientConnected(cc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RfbServerManager::removeClient(RfbClient* cc)
|
void RfbServerManager::removeClient(RfbClient *cc)
|
||||||
{
|
{
|
||||||
d->clients.remove(cc);
|
d->clients.remove(cc);
|
||||||
if (d->clients.size() == 0) {
|
if (d->clients.size() == 0) {
|
||||||
//qDebug() << "Stopping framebuffer monitor";
|
// qDebug() << "Stopping framebuffer monitor";
|
||||||
d->fb->stopMonitor();
|
d->fb->stopMonitor();
|
||||||
d->rfbUpdateTimer.stop();
|
d->rfbUpdateTimer.stop();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
#ifndef RFBSERVERMANAGER_H
|
#ifndef RFBSERVERMANAGER_H
|
||||||
#define RFBSERVERMANAGER_H
|
#define RFBSERVERMANAGER_H
|
||||||
|
|
||||||
#include "rfb.h"
|
|
||||||
#include "framebuffer.h"
|
#include "framebuffer.h"
|
||||||
|
#include "rfb.h"
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QVariantMap>
|
#include <QVariantMap>
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,9 @@
|
|||||||
|
|
||||||
#include "sockethelpers.h"
|
#include "sockethelpers.h"
|
||||||
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
QString peerAddress(int sock)
|
QString peerAddress(int sock)
|
||||||
{
|
{
|
||||||
@@ -86,4 +86,3 @@ unsigned short localPort(int sock)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,20 +8,20 @@
|
|||||||
#include "trayicon.h"
|
#include "trayicon.h"
|
||||||
|
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "rfbservermanager.h"
|
|
||||||
#include "rfbclient.h"
|
#include "rfbclient.h"
|
||||||
|
#include "rfbservermanager.h"
|
||||||
|
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
|
|
||||||
#include <KAboutApplicationDialog>
|
#include <KAboutApplicationDialog>
|
||||||
#include <KActionCollection>
|
#include <KActionCollection>
|
||||||
#include <QDialog>
|
#include <KConfigGroup>
|
||||||
#include <KHelpMenu>
|
#include <KHelpMenu>
|
||||||
#include <KLocalizedString>
|
#include <KLocalizedString>
|
||||||
#include <KStandardAction>
|
#include <KStandardAction>
|
||||||
#include <KToggleAction>
|
#include <KToggleAction>
|
||||||
#include <KConfigGroup>
|
#include <QDialog>
|
||||||
|
|
||||||
class ClientActions
|
class ClientActions
|
||||||
{
|
{
|
||||||
@@ -37,7 +37,7 @@ private:
|
|||||||
QAction *m_separator = nullptr;
|
QAction *m_separator = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
ClientActions::ClientActions(RfbClient* client, QMenu* menu, QAction* before)
|
ClientActions::ClientActions(RfbClient *client, QMenu *menu, QAction *before)
|
||||||
: m_menu(menu)
|
: m_menu(menu)
|
||||||
{
|
{
|
||||||
m_title = m_menu->insertSection(before, client->name());
|
m_title = m_menu->insertSection(before, client->name());
|
||||||
@@ -52,10 +52,8 @@ ClientActions::ClientActions(RfbClient* client, QMenu* menu, QAction* before)
|
|||||||
m_enableControlAction->setChecked(client->controlEnabled());
|
m_enableControlAction->setChecked(client->controlEnabled());
|
||||||
m_menu->insertAction(before, m_enableControlAction);
|
m_menu->insertAction(before, m_enableControlAction);
|
||||||
|
|
||||||
QObject::connect(m_enableControlAction, &KToggleAction::triggered,
|
QObject::connect(m_enableControlAction, &KToggleAction::triggered, client, &RfbClient::setControlEnabled);
|
||||||
client, &RfbClient::setControlEnabled);
|
QObject::connect(client, &RfbClient::controlEnabledChanged, m_enableControlAction, &KToggleAction::setChecked);
|
||||||
QObject::connect(client, &RfbClient::controlEnabledChanged,
|
|
||||||
m_enableControlAction, &KToggleAction::setChecked);
|
|
||||||
} else {
|
} else {
|
||||||
m_enableControlAction = nullptr;
|
m_enableControlAction = nullptr;
|
||||||
}
|
}
|
||||||
@@ -90,29 +88,27 @@ TrayIcon::TrayIcon(QWidget *mainWindow)
|
|||||||
setToolTipTitle(i18n("Desktop Sharing - disconnected"));
|
setToolTipTitle(i18n("Desktop Sharing - disconnected"));
|
||||||
setCategory(KStatusNotifierItem::ApplicationStatus);
|
setCategory(KStatusNotifierItem::ApplicationStatus);
|
||||||
|
|
||||||
connect(RfbServerManager::instance(), &RfbServerManager::clientConnected,
|
connect(RfbServerManager::instance(), &RfbServerManager::clientConnected, this, &TrayIcon::onClientConnected);
|
||||||
this, &TrayIcon::onClientConnected);
|
connect(RfbServerManager::instance(), &RfbServerManager::clientDisconnected, this, &TrayIcon::onClientDisconnected);
|
||||||
connect(RfbServerManager::instance(), &RfbServerManager::clientDisconnected,
|
|
||||||
this, &TrayIcon::onClientDisconnected);
|
|
||||||
|
|
||||||
m_aboutAction = KStandardAction::aboutApp(this, &TrayIcon::showAbout, this);
|
m_aboutAction = KStandardAction::aboutApp(this, &TrayIcon::showAbout, this);
|
||||||
contextMenu()->addAction(m_aboutAction);
|
contextMenu()->addAction(m_aboutAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrayIcon::onClientConnected(RfbClient* client)
|
void TrayIcon::onClientConnected(RfbClient *client)
|
||||||
{
|
{
|
||||||
if (m_clientActions.isEmpty()) { //first client connected
|
if (m_clientActions.isEmpty()) { // first client connected
|
||||||
setIconByName(QStringLiteral("krfb"));
|
setIconByName(QStringLiteral("krfb"));
|
||||||
setToolTipTitle(i18n("Desktop Sharing - connected with %1", client->name()));
|
setToolTipTitle(i18n("Desktop Sharing - connected with %1", client->name()));
|
||||||
setStatus(KStatusNotifierItem::Active);
|
setStatus(KStatusNotifierItem::Active);
|
||||||
} else { //Nth client connected, N != 1
|
} else { // Nth client connected, N != 1
|
||||||
setToolTipTitle(i18n("Desktop Sharing - connected"));
|
setToolTipTitle(i18n("Desktop Sharing - connected"));
|
||||||
}
|
}
|
||||||
|
|
||||||
m_clientActions[client] = new ClientActions(client, contextMenu(), m_aboutAction);
|
m_clientActions[client] = new ClientActions(client, contextMenu(), m_aboutAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrayIcon::onClientDisconnected(RfbClient* client)
|
void TrayIcon::onClientDisconnected(RfbClient *client)
|
||||||
{
|
{
|
||||||
ClientActions *actions = m_clientActions.take(client);
|
ClientActions *actions = m_clientActions.take(client);
|
||||||
delete actions;
|
delete actions;
|
||||||
@@ -121,7 +117,7 @@ void TrayIcon::onClientDisconnected(RfbClient* client)
|
|||||||
setIconByPixmap(QIcon::fromTheme(QStringLiteral("krfb")).pixmap(22, 22, QIcon::Disabled));
|
setIconByPixmap(QIcon::fromTheme(QStringLiteral("krfb")).pixmap(22, 22, QIcon::Disabled));
|
||||||
setToolTipTitle(i18n("Desktop Sharing - disconnected"));
|
setToolTipTitle(i18n("Desktop Sharing - disconnected"));
|
||||||
setStatus(KStatusNotifierItem::Passive);
|
setStatus(KStatusNotifierItem::Passive);
|
||||||
} else if (m_clientActions.size() == 1) { //clients number dropped back to 1
|
} else if (m_clientActions.size() == 1) { // clients number dropped back to 1
|
||||||
RfbClient *client = m_clientActions.constBegin().key();
|
RfbClient *client = m_clientActions.constBegin().key();
|
||||||
setToolTipTitle(i18n("Desktop Sharing - connected with %1", client->name()));
|
setToolTipTitle(i18n("Desktop Sharing - connected with %1", client->name()));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ class RfbClient;
|
|||||||
class ClientActions;
|
class ClientActions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements the trayicon.
|
* Implements the trayicon.
|
||||||
* @author Tim Jansen
|
* @author Tim Jansen
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class TrayIcon : public KStatusNotifierItem
|
class TrayIcon : public KStatusNotifierItem
|
||||||
{
|
{
|
||||||
@@ -31,7 +31,7 @@ public Q_SLOTS:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
QAction *m_aboutAction;
|
QAction *m_aboutAction;
|
||||||
QHash<RfbClient*, ClientActions*> m_clientActions;
|
QHash<RfbClient *, ClientActions *> m_clientActions;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user