Add support for lock LED state to Xvnc/libvnc.so
diff --git a/unix/xserver/hw/vnc/Input.c b/unix/xserver/hw/vnc/Input.c
index 1d7183b..998121b 100644
--- a/unix/xserver/hw/vnc/Input.c
+++ b/unix/xserver/hw/vnc/Input.c
@@ -273,6 +273,11 @@
 		vncBell();
 }
 
+static void vncKeyboardCtrl(DeviceIntPtr pDevice, KeybdCtrl *ctrl)
+{
+	vncSetLEDState(ctrl->leds);
+}
+
 static int vncKeyboardProc(DeviceIntPtr pDevice, int onoff)
 {
 	DevicePtr pDev = (DevicePtr)pDevice;
@@ -280,7 +285,7 @@
 	switch (onoff) {
 	case DEVICE_INIT:
 		InitKeyboardDeviceStruct(pDevice, NULL, vncKeyboardBell,
-					 (KbdCtrlProcPtr)NoopDDA);
+					 vncKeyboardCtrl);
 		break;
 	case DEVICE_ON:
 		pDev->on = TRUE;
diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc
index 4836782..1c74bc6 100644
--- a/unix/xserver/hw/vnc/XserverDesktop.cc
+++ b/unix/xserver/hw/vnc/XserverDesktop.cc
@@ -322,6 +322,11 @@
   server->bell();
 }
 
+void XserverDesktop::setLEDState(unsigned int state)
+{
+  server->setLEDState(state);
+}
+
 void XserverDesktop::serverCutText(const char* str, int len)
 {
   try {
diff --git a/unix/xserver/hw/vnc/XserverDesktop.h b/unix/xserver/hw/vnc/XserverDesktop.h
index c766c26..cd85e4b 100644
--- a/unix/xserver/hw/vnc/XserverDesktop.h
+++ b/unix/xserver/hw/vnc/XserverDesktop.h
@@ -63,6 +63,7 @@
   void setFramebuffer(int w, int h, void* fbptr, int stride);
   void refreshScreenLayout();
   void bell();
+  void setLEDState(unsigned int state);
   void serverCutText(const char* str, int len);
   void setDesktopName(const char* name);
   void setCursor(int width, int height, int hotX, int hotY,
diff --git a/unix/xserver/hw/vnc/vncExtInit.cc b/unix/xserver/hw/vnc/vncExtInit.cc
index 57bf6d8..13248f9 100644
--- a/unix/xserver/hw/vnc/vncExtInit.cc
+++ b/unix/xserver/hw/vnc/vncExtInit.cc
@@ -32,6 +32,7 @@
 #include <rfb/LogWriter.h>
 #include <rfb/Hostname.h>
 #include <rfb/Region.h>
+#include <rfb/ledStates.h>
 #include <network/TcpSocket.h>
 
 #include "XserverDesktop.h"
@@ -358,6 +359,25 @@
   }
 }
 
+void vncSetLEDState(unsigned long leds)
+{
+  unsigned int state;
+
+  state = 0;
+  if (leds & (1 << 0))
+    state |= ledCapsLock;
+  if (leds & (1 << 1))
+    state |= ledNumLock;
+  if (leds & (1 << 2))
+    state |= ledScrollLock;
+
+  for (int scr = 0; scr < vncGetScreenCount(); scr++) {
+    if (desktop[scr] == NULL)
+      continue;
+    desktop[scr]->setLEDState(state);
+  }
+}
+
 void vncAddChanged(int scrIdx, const struct UpdateRect *extents,
                    int nRects, const struct UpdateRect *rects)
 {
diff --git a/unix/xserver/hw/vnc/vncExtInit.h b/unix/xserver/hw/vnc/vncExtInit.h
index 9f8d9e7..99fee27 100644
--- a/unix/xserver/hw/vnc/vncExtInit.h
+++ b/unix/xserver/hw/vnc/vncExtInit.h
@@ -70,6 +70,8 @@
 
 void vncBell(void);
 
+void vncSetLEDState(unsigned long leds);
+
 // Must match rfb::ShortRect in common/rfb/Region.h, and BoxRec in the
 // Xorg source.
 struct UpdateRect {