Kaynağa Gözat

x0vncserver: add support for led state notifications

Listen for XKb XkbIndicatorStateNotify events for scroll/num/caps lock and
map them to the RFB protocol.

Signed-off-by: Peter Korsgaard <peter.korsgaard@barco.com>
tags/v1.8.90
Peter Korsgaard 7 yıl önce
ebeveyn
işleme
5b7ff37267
1 değiştirilmiş dosya ile 77 ekleme ve 15 silme
  1. 77
    15
      unix/x0vncserver/x0vncserver.cxx

+ 77
- 15
unix/x0vncserver/x0vncserver.cxx Dosyayı Görüntüle

@@ -39,6 +39,7 @@
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/XKBlib.h>
#ifdef HAVE_XTEST
#include <X11/extensions/XTest.h>
#endif
@@ -61,6 +62,14 @@ extern char buildtime[];
using namespace rfb;
using namespace network;

// number of XKb indicator leds to handle
static const int N_LEDS = 3;

// order is important as it must match RFB extension
static const char * ledNames[N_LEDS] = {
"Scroll Lock", "Num Lock", "Caps Lock"
};

static LogWriter vlog("Main");

IntParameter pollingCycle("PollingCycle", "Milliseconds per one polling "
@@ -141,12 +150,42 @@ public:
XDesktop(Display* dpy_, Geometry *geometry_)
: dpy(dpy_), geometry(geometry_), pb(0), server(0),
oldButtonMask(0), haveXtest(false), haveDamage(false),
maxButtons(0), running(false)
maxButtons(0), running(false), ledMasks(), ledState(0)
{
int major, minor;

int xkbOpcode, xkbErrorBase;

major = XkbMajorVersion;
minor = XkbMinorVersion;
if (!XkbQueryExtension(dpy, &xkbOpcode, &xkbEventBase,
&xkbErrorBase, &major, &minor)) {
vlog.error("XKEYBOARD extension not present");
throw Exception();
}

XkbSelectEvents(dpy, XkbUseCoreKbd, XkbIndicatorStateNotifyMask,
XkbIndicatorStateNotifyMask);

// figure out bit masks for the indicators we are interested in
for (int i = 0; i < N_LEDS; i++) {
Atom a;
int shift;
Bool on;

a = XInternAtom(dpy, ledNames[i], True);
if (!a || !XkbGetNamedIndicator(dpy, a, &shift, &on, NULL, NULL))
continue;

ledMasks[i] = 1u << shift;
vlog.debug("Mask for '%s' is 0x%x", ledNames[i], ledMasks[i]);
if (on)
ledState |= 1u << i;
}

#ifdef HAVE_XTEST
int xtestEventBase;
int xtestErrorBase;
int major, minor;

if (XTestQueryExtension(dpy, &xtestEventBase,
&xtestErrorBase, &major, &minor)) {
@@ -165,7 +204,6 @@ public:
int xdamageErrorBase;

if (XDamageQueryExtension(dpy, &xdamageEventBase, &xdamageErrorBase)) {
TXWindow::setGlobalEventHandler(this);
haveDamage = true;
} else {
#endif
@@ -174,6 +212,8 @@ public:
#ifdef HAVE_XDAMAGE
}
#endif

TXWindow::setGlobalEventHandler(this);
}
virtual ~XDesktop() {
stop();
@@ -212,6 +252,8 @@ public:
}
#endif

server->setLEDState(ledState);

running = true;
}

@@ -272,24 +314,41 @@ public:
// -=- TXGlobalEventHandler interface

virtual bool handleGlobalEvent(XEvent* ev) {
#ifdef HAVE_XDAMAGE
XDamageNotifyEvent* dev;
Rect rect;
if (ev->type == xkbEventBase + XkbEventCode) {
XkbEvent *kb = (XkbEvent *)ev;

if (ev->type != xdamageEventBase)
return false;
if (kb->any.xkb_type != XkbIndicatorStateNotify)
return false;

vlog.debug("Got indicator update, mask is now 0x%x", kb->indicators.state);

ledState = 0;
for (int i = 0; i < N_LEDS; i++) {
if (kb->indicators.state & ledMasks[i])
ledState |= 1u << i;
}

if (running)
server->setLEDState(ledState);

if (!running)
return true;
#ifdef HAVE_XDAMAGE
} else if (ev->type == xdamageEventBase) {
XDamageNotifyEvent* dev;
Rect rect;

dev = (XDamageNotifyEvent*)ev;
rect.setXYWH(dev->area.x, dev->area.y, dev->area.width, dev->area.height);
server->add_changed(rect);
if (!running)
return true;

return true;
#else
return false;
dev = (XDamageNotifyEvent*)ev;
rect.setXYWH(dev->area.x, dev->area.y, dev->area.width, dev->area.height);
server->add_changed(rect);

return true;
#endif
}

return false;
}

protected:
@@ -306,6 +365,9 @@ protected:
Damage damage;
int xdamageEventBase;
#endif
int xkbEventBase;
int ledMasks[N_LEDS];
unsigned ledState;
};



Loading…
İptal
Kaydet