]> source.dussan.org Git - tigervnc.git/commitdiff
Merge branch 'cursor' of https://github.com/alanc/tigervnc
authorPierre Ossman <ossman@cendio.se>
Fri, 15 Sep 2017 11:10:54 +0000 (13:10 +0200)
committerPierre Ossman <ossman@cendio.se>
Fri, 15 Sep 2017 11:10:54 +0000 (13:10 +0200)
1  2 
unix/x0vncserver/CMakeLists.txt
unix/x0vncserver/x0vncserver.cxx

Simple merge
index 025a09533502e738b0f2c68d56444d39526c5073,315d30c5e0206229c1c9603bf070e801dc1bfbfc..d3042db0c6d785cf24d5ba03a659361003fa806d
@@@ -160,66 -144,8 +163,66 @@@ public
    XDesktop(Display* dpy_, Geometry *geometry_)
      : dpy(dpy_), geometry(geometry_), pb(0), server(0),
        oldButtonMask(0), haveXtest(false), haveDamage(false),
-       maxButtons(0), running(false), ledMasks(), ledState(0),
-       codeMap(0), codeMapLen(0)
 -      haveXfixes(false), maxButtons(0), running(false)
++      haveXfixes(false),  maxButtons(0), running(false),
++      ledMasks(), ledState(0), codeMap(0), codeMapLen(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;
 +    }
 +
 +    // X11 unfortunately uses keyboard driver specific keycodes and provides no
 +    // direct way to query this, so guess based on the keyboard mapping
 +    XkbDescPtr desc = XkbGetKeyboard(dpy, XkbAllComponentsMask, XkbUseCoreKbd);
 +    if (desc && desc->names) {
 +      char *keycodes = XGetAtomName(dpy, desc->names->keycodes);
 +
 +      if (keycodes) {
 +        if (strncmp("evdev", keycodes, strlen("evdev")) == 0) {
 +          codeMap = code_map_qnum_to_xorgevdev;
 +          codeMapLen = code_map_qnum_to_xorgevdev_len;
 +          vlog.info("Using evdev codemap\n");
 +        } else if (strncmp("xfree86", keycodes, strlen("xfree86")) == 0) {
 +          codeMap = code_map_qnum_to_xorgkbd;
 +          codeMapLen = code_map_qnum_to_xorgkbd_len;
 +          vlog.info("Using xorgkbd codemap\n");
 +        } else {
 +          vlog.info("Unknown keycode '%s', no codemap\n", keycodes);
 +        }
 +        XFree(keycodes);
 +      } else {
 +        vlog.debug("Unable to get keycode map\n");
 +      }
 +
 +      XkbFreeKeyboard(desc, XkbAllComponentsMask, True);
 +    }
 +
  #ifdef HAVE_XTEST
      int xtestEventBase;
      int xtestErrorBase;
      }
  #endif
  
 -      if (not haveDamage)
 -        TXWindow::setGlobalEventHandler(this);
+ #ifdef HAVE_XFIXES
+     int xfixesErrorBase;
+     if (XFixesQueryExtension(dpy, &xfixesEventBase, &xfixesErrorBase)) {
+       haveXfixes = true;
+     } else {
+ #endif
+       vlog.info("XFIXES extension not present");
+       vlog.info("Will not be able to display cursors");
+ #ifdef HAVE_XFIXES
+     }
+ #endif
++
 +    TXWindow::setGlobalEventHandler(this);
    }
    virtual ~XDesktop() {
      stop();
      }
  #endif
  
+ #ifdef HAVE_XFIXES
+     if (haveXfixes) {
+       XFixesSelectCursorInput(dpy, DefaultRootWindow(dpy),
+                               XFixesDisplayCursorNotifyMask);
+     }
+ #endif
 +    server->setLEDState(ledState);
 +
      running = true;
    }
  
        server->add_changed(rect);
  
        return true;
 -    }
  #endif
 -
+ #ifdef HAVE_XFIXES
 -    if (ev->type == xfixesEventBase + XFixesCursorNotify) {
++    } else if (ev->type == xfixesEventBase + XFixesCursorNotify) {
+       XFixesCursorNotifyEvent* cev;
+       XFixesCursorImage *cim;
+       if (!running)
+         return true;
+       cev = (XFixesCursorNotifyEvent*)ev;
+       if (cev->subtype != XFixesDisplayCursorNotify)
+         return false;
+       cim = XFixesGetCursorImage(dpy);
+       if (cim == NULL)
+         return false;
+       // Copied from XserverDesktop::setCursor() in
+       // unix/xserver/hw/vnc/XserverDesktop.cc and adapted to
+       // handle long -> U32 conversion for 64-bit Xlib
+       rdr::U8* cursorData;
+       rdr::U8 *out;
+       const unsigned long *pixels;
+       cursorData = new rdr::U8[cim->width * cim->height * 4];
+       // Un-premultiply alpha
+       pixels = cim->pixels;
+       out = cursorData;
+       for (int y = 0; y < cim->height; y++) {
+         for (int x = 0; x < cim->width; x++) {
+           rdr::U8 alpha;
+           rdr::U32 pixel = *pixels++;
+           rdr::U8 *in = (rdr::U8 *) &pixel;
+           alpha = in[3];
+           if (alpha == 0)
+             alpha = 1; // Avoid division by zero
+           *out++ = (unsigned)*in++ * 255/alpha;
+           *out++ = (unsigned)*in++ * 255/alpha;
+           *out++ = (unsigned)*in++ * 255/alpha;
+           *out++ = *in++;
+         }
+       }
+       try {
+         server->setCursor(cim->width, cim->height, Point(cim->xhot, cim->yhot),
+                           cursorData);
+       } catch (rdr::Exception& e) {
+         vlog.error("XserverDesktop::setCursor: %s",e.str());
+       }
+       delete [] cursorData;
+       XFree(cim);
+       return true;
 -    }
+ #endif
 +    }
  
      return false;
    }
@@@ -451,18 -383,16 +531,22 @@@ protected
    int oldButtonMask;
    bool haveXtest;
    bool haveDamage;
+   bool haveXfixes;
    int maxButtons;
 +  std::map<KeySym, KeyCode> pressedKeys;
    bool running;
  #ifdef HAVE_XDAMAGE
    Damage damage;
    int xdamageEventBase;
  #endif
 +  int xkbEventBase;
+ #ifdef HAVE_XFIXES
+   int xfixesEventBase;
+ #endif
 +  int ledMasks[N_LEDS];
 +  unsigned ledState;
 +  const unsigned short *codeMap;
 +  unsigned codeMapLen;
  };