Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright 2009 Vincent Sanders <vince@simtec.co.uk>
  3.  *
  4.  * This file is part of libnsfb, http://www.netsurf-browser.org/
  5.  * Licenced under the MIT License,
  6.  *                http://www.opensource.org/licenses/mit-license.php
  7.  */
  8.  
  9. #include <stdbool.h>
  10. #include <stdio.h>
  11.  
  12. #include <rfb/rfb.h>
  13. #include <rfb/keysym.h>
  14.  
  15. #include "libnsfb.h"
  16. #include "libnsfb_event.h"
  17. #include "libnsfb_plot.h"
  18.  
  19. #include "nsfb.h"
  20. #include "surface.h"
  21. #include "plot.h"
  22. #include "cursor.h"
  23.  
  24. #define UNUSED(x) ((x) = (x))
  25.  
  26. static nsfb_event_t *gevent;
  27.  
  28. /* vnc special set codes */
  29. static enum nsfb_key_code_e vnc_nsfb_map[256] = {
  30.     NSFB_KEY_UNKNOWN, /* 0x00 */
  31.     NSFB_KEY_UNKNOWN,
  32.     NSFB_KEY_UNKNOWN,
  33.     NSFB_KEY_UNKNOWN,
  34.     NSFB_KEY_UNKNOWN,
  35.     NSFB_KEY_UNKNOWN,
  36.     NSFB_KEY_UNKNOWN,
  37.     NSFB_KEY_UNKNOWN,
  38.     NSFB_KEY_BACKSPACE, /* 0x08 */
  39.     NSFB_KEY_TAB,
  40.     NSFB_KEY_LF,
  41.     NSFB_KEY_CLEAR,
  42.     NSFB_KEY_UNKNOWN,
  43.     NSFB_KEY_RETURN,
  44.     NSFB_KEY_UNKNOWN,
  45.     NSFB_KEY_UNKNOWN,
  46.     NSFB_KEY_UNKNOWN, /* 0x10 */
  47.     NSFB_KEY_UNKNOWN,
  48.     NSFB_KEY_UNKNOWN,
  49.     NSFB_KEY_RETURN,
  50.     NSFB_KEY_UNKNOWN,
  51.     NSFB_KEY_UNKNOWN,
  52.     NSFB_KEY_UNKNOWN,
  53.     NSFB_KEY_UNKNOWN,
  54.     NSFB_KEY_UNKNOWN, /* 0x18 */
  55.     NSFB_KEY_UNKNOWN,
  56.     NSFB_KEY_UNKNOWN,
  57.     NSFB_KEY_ESCAPE,
  58.     NSFB_KEY_UNKNOWN,
  59.     NSFB_KEY_UNKNOWN,
  60.     NSFB_KEY_UNKNOWN,
  61.     NSFB_KEY_UNKNOWN,
  62.     NSFB_KEY_COMPOSE, /* 0x20 */
  63.     NSFB_KEY_UNKNOWN,
  64.     NSFB_KEY_UNKNOWN,
  65.     NSFB_KEY_UNKNOWN,
  66.     NSFB_KEY_UNKNOWN,
  67.     NSFB_KEY_UNKNOWN,
  68.     NSFB_KEY_UNKNOWN,
  69.     NSFB_KEY_UNKNOWN,
  70.     NSFB_KEY_UNKNOWN, /* 0x28 */
  71.     NSFB_KEY_UNKNOWN,
  72.     NSFB_KEY_UNKNOWN,
  73.     NSFB_KEY_UNKNOWN,
  74.     NSFB_KEY_UNKNOWN,
  75.     NSFB_KEY_UNKNOWN,
  76.     NSFB_KEY_UNKNOWN,
  77.     NSFB_KEY_UNKNOWN,
  78.     NSFB_KEY_UNKNOWN, /* 0x30 */
  79.     NSFB_KEY_UNKNOWN,
  80.     NSFB_KEY_UNKNOWN,
  81.     NSFB_KEY_UNKNOWN,
  82.     NSFB_KEY_UNKNOWN,
  83.     NSFB_KEY_UNKNOWN,
  84.     NSFB_KEY_UNKNOWN,
  85.     NSFB_KEY_UNKNOWN,
  86.     NSFB_KEY_UNKNOWN, /* 0x38 */
  87.     NSFB_KEY_UNKNOWN,
  88.     NSFB_KEY_UNKNOWN,
  89.     NSFB_KEY_UNKNOWN,
  90.     NSFB_KEY_UNKNOWN,
  91.     NSFB_KEY_UNKNOWN,
  92.     NSFB_KEY_UNKNOWN,
  93.     NSFB_KEY_UNKNOWN,
  94.     NSFB_KEY_UNKNOWN, /* 0x40 */
  95.     NSFB_KEY_UNKNOWN,
  96.     NSFB_KEY_UNKNOWN,
  97.     NSFB_KEY_UNKNOWN,
  98.     NSFB_KEY_UNKNOWN,
  99.     NSFB_KEY_UNKNOWN,
  100.     NSFB_KEY_UNKNOWN,
  101.     NSFB_KEY_UNKNOWN,
  102.     NSFB_KEY_UNKNOWN, /* 0x48 */
  103.     NSFB_KEY_UNKNOWN,
  104.     NSFB_KEY_UNKNOWN,
  105.     NSFB_KEY_UNKNOWN,
  106.     NSFB_KEY_UNKNOWN,
  107.     NSFB_KEY_UNKNOWN,
  108.     NSFB_KEY_UNKNOWN,
  109.     NSFB_KEY_UNKNOWN,
  110.     NSFB_KEY_HOME, /* 0x50 */
  111.     NSFB_KEY_LEFT,
  112.     NSFB_KEY_UP,
  113.     NSFB_KEY_RIGHT,
  114.     NSFB_KEY_DOWN,
  115.     NSFB_KEY_PAGEUP,
  116.     NSFB_KEY_PAGEDOWN,
  117.     NSFB_KEY_END,
  118.     NSFB_KEY_HOME, /* 0x58 */
  119.     NSFB_KEY_UNKNOWN,
  120.     NSFB_KEY_UNKNOWN,
  121.     NSFB_KEY_UNKNOWN,
  122.     NSFB_KEY_UNKNOWN,
  123.     NSFB_KEY_UNKNOWN,
  124.     NSFB_KEY_UNKNOWN,
  125.     NSFB_KEY_UNKNOWN,
  126.     NSFB_KEY_UNKNOWN, /* 0x60 */
  127.     NSFB_KEY_PRINT,
  128.     NSFB_KEY_HELP,
  129.     NSFB_KEY_UNKNOWN,
  130.     NSFB_KEY_UNKNOWN,
  131.     NSFB_KEY_UNDO,
  132.     NSFB_KEY_UNKNOWN,
  133.     NSFB_KEY_MENU,
  134.     NSFB_KEY_UNKNOWN, /* 0x68 */
  135.     NSFB_KEY_UNKNOWN,
  136.     NSFB_KEY_UNKNOWN,
  137.     NSFB_KEY_BREAK,
  138.     NSFB_KEY_UNKNOWN,
  139.     NSFB_KEY_UNKNOWN,
  140.     NSFB_KEY_UNKNOWN,
  141.     NSFB_KEY_UNKNOWN,
  142.     NSFB_KEY_UNKNOWN, /* 0x70 */
  143.     NSFB_KEY_UNKNOWN,
  144.     NSFB_KEY_UNKNOWN,
  145.     NSFB_KEY_UNKNOWN,
  146.     NSFB_KEY_UNKNOWN,
  147.     NSFB_KEY_UNKNOWN,
  148.     NSFB_KEY_UNKNOWN,
  149.     NSFB_KEY_UNKNOWN,
  150.     NSFB_KEY_UNKNOWN, /* 0x78 */
  151.     NSFB_KEY_UNKNOWN,
  152.     NSFB_KEY_UNKNOWN,
  153.     NSFB_KEY_UNKNOWN,
  154.     NSFB_KEY_UNKNOWN,
  155.     NSFB_KEY_UNKNOWN,
  156.     NSFB_KEY_MODE,
  157.     NSFB_KEY_NUMLOCK,
  158.     NSFB_KEY_UNKNOWN, /* 0x80 */
  159.     NSFB_KEY_UNKNOWN,
  160.     NSFB_KEY_UNKNOWN,
  161.     NSFB_KEY_UNKNOWN,
  162.     NSFB_KEY_UNKNOWN,
  163.     NSFB_KEY_UNKNOWN,
  164.     NSFB_KEY_UNKNOWN,
  165.     NSFB_KEY_UNKNOWN,
  166.     NSFB_KEY_UNKNOWN, /* 0x88 */
  167.     NSFB_KEY_UNKNOWN,
  168.     NSFB_KEY_UNKNOWN,
  169.     NSFB_KEY_UNKNOWN,
  170.     NSFB_KEY_UNKNOWN,
  171.     NSFB_KEY_KP_ENTER,
  172.     NSFB_KEY_UNKNOWN,
  173.     NSFB_KEY_UNKNOWN,
  174.     NSFB_KEY_UNKNOWN, /* 0x90 */
  175.     NSFB_KEY_UNKNOWN,
  176.     NSFB_KEY_UNKNOWN,
  177.     NSFB_KEY_UNKNOWN,
  178.     NSFB_KEY_UNKNOWN,
  179.     NSFB_KEY_UNKNOWN,
  180.     NSFB_KEY_UNKNOWN,
  181.     NSFB_KEY_UNKNOWN,
  182.     NSFB_KEY_UNKNOWN, /* 0x98 */
  183.     NSFB_KEY_UNKNOWN,
  184.     NSFB_KEY_UNKNOWN,
  185.     NSFB_KEY_UNKNOWN,
  186.     NSFB_KEY_UNKNOWN,
  187.     NSFB_KEY_UNKNOWN,
  188.     NSFB_KEY_UNKNOWN,
  189.     NSFB_KEY_UNKNOWN,
  190.     NSFB_KEY_UNKNOWN, /* 0xA0 */
  191.     NSFB_KEY_UNKNOWN,
  192.     NSFB_KEY_UNKNOWN,
  193.     NSFB_KEY_UNKNOWN,
  194.     NSFB_KEY_UNKNOWN,
  195.     NSFB_KEY_UNKNOWN,
  196.     NSFB_KEY_UNKNOWN,
  197.     NSFB_KEY_UNKNOWN,
  198.     NSFB_KEY_UNKNOWN, /* 0xA8 */
  199.     NSFB_KEY_UNKNOWN,
  200.     NSFB_KEY_KP_MULTIPLY,
  201.     NSFB_KEY_KP_PLUS,
  202.     NSFB_KEY_UNKNOWN,
  203.     NSFB_KEY_KP_MINUS,
  204.     NSFB_KEY_KP_PERIOD,
  205.     NSFB_KEY_KP_DIVIDE,
  206.     NSFB_KEY_KP0, /* 0xB0 */
  207.     NSFB_KEY_KP1,
  208.     NSFB_KEY_KP2,
  209.     NSFB_KEY_KP3,
  210.     NSFB_KEY_KP4,
  211.     NSFB_KEY_KP5,
  212.     NSFB_KEY_KP6,
  213.     NSFB_KEY_KP7,
  214.     NSFB_KEY_KP8, /* 0xB8 */
  215.     NSFB_KEY_KP9,
  216.     NSFB_KEY_UNKNOWN,
  217.     NSFB_KEY_UNKNOWN,
  218.     NSFB_KEY_UNKNOWN,
  219.     NSFB_KEY_KP_EQUALS,
  220.     NSFB_KEY_F1,
  221.     NSFB_KEY_F2,
  222.     NSFB_KEY_F3, /* 0xC0 */
  223.     NSFB_KEY_F4,
  224.     NSFB_KEY_F5,
  225.     NSFB_KEY_F6,
  226.     NSFB_KEY_F7,
  227.     NSFB_KEY_F8,
  228.     NSFB_KEY_F9,
  229.     NSFB_KEY_F10,
  230.     NSFB_KEY_F11, /* 0xC8 */
  231.     NSFB_KEY_F12,
  232.     NSFB_KEY_F13,
  233.     NSFB_KEY_F14,
  234.     NSFB_KEY_F15,
  235.     NSFB_KEY_UNKNOWN,
  236.     NSFB_KEY_UNKNOWN,
  237.     NSFB_KEY_UNKNOWN,
  238.     NSFB_KEY_UNKNOWN, /* 0xD0 */
  239.     NSFB_KEY_UNKNOWN,
  240.     NSFB_KEY_UNKNOWN,
  241.     NSFB_KEY_UNKNOWN,
  242.     NSFB_KEY_UNKNOWN,
  243.     NSFB_KEY_UNKNOWN,
  244.     NSFB_KEY_UNKNOWN,
  245.     NSFB_KEY_UNKNOWN,
  246.     NSFB_KEY_UNKNOWN, /* 0xD8 */
  247.     NSFB_KEY_UNKNOWN,
  248.     NSFB_KEY_UNKNOWN,
  249.     NSFB_KEY_UNKNOWN,
  250.     NSFB_KEY_UNKNOWN,
  251.     NSFB_KEY_UNKNOWN,
  252.     NSFB_KEY_UNKNOWN,
  253.     NSFB_KEY_UNKNOWN,
  254.     NSFB_KEY_UNKNOWN, /* 0xE0 */
  255.     NSFB_KEY_LSHIFT,
  256.     NSFB_KEY_RSHIFT,
  257.     NSFB_KEY_LCTRL,
  258.     NSFB_KEY_RCTRL,
  259.     NSFB_KEY_CAPSLOCK,
  260.     NSFB_KEY_SCROLLOCK,
  261.     NSFB_KEY_LMETA,
  262.     NSFB_KEY_RMETA, /* 0xE8 */
  263.     NSFB_KEY_LALT,
  264.     NSFB_KEY_RALT,
  265.     NSFB_KEY_LSUPER,
  266.     NSFB_KEY_RSUPER,
  267.     NSFB_KEY_UNKNOWN,
  268.     NSFB_KEY_UNKNOWN,
  269.     NSFB_KEY_UNKNOWN,
  270.     NSFB_KEY_UNKNOWN, /* 0xF0 */
  271.     NSFB_KEY_UNKNOWN,
  272.     NSFB_KEY_UNKNOWN,
  273.     NSFB_KEY_UNKNOWN,
  274.     NSFB_KEY_UNKNOWN,
  275.     NSFB_KEY_UNKNOWN,
  276.     NSFB_KEY_UNKNOWN,
  277.     NSFB_KEY_UNKNOWN,
  278.     NSFB_KEY_UNKNOWN, /* 0xF8 */
  279.     NSFB_KEY_UNKNOWN,
  280.     NSFB_KEY_UNKNOWN,
  281.     NSFB_KEY_UNKNOWN,
  282.     NSFB_KEY_UNKNOWN,
  283.     NSFB_KEY_UNKNOWN,
  284.     NSFB_KEY_UNKNOWN,
  285.     NSFB_KEY_DELETE,
  286. };
  287.  
  288.  
  289. static void vnc_doptr(int buttonMask,int x,int y,rfbClientPtr cl)
  290. {
  291.     static int prevbuttonMask = 0;
  292.  
  293.     UNUSED(cl);
  294.  
  295.     if (prevbuttonMask != buttonMask) {
  296.         /* button click */
  297.         if (((prevbuttonMask ^ buttonMask) & 0x01) == 0x01) {
  298.             if ((buttonMask & 0x01) == 0x01) {
  299.                 gevent->type = NSFB_EVENT_KEY_DOWN;
  300.             } else {
  301.                 gevent->type = NSFB_EVENT_KEY_UP;
  302.             }
  303.             gevent->value.keycode = NSFB_KEY_MOUSE_1;
  304.         } else if (((prevbuttonMask ^ buttonMask) & 0x02) == 0x02) {
  305.             if ((buttonMask & 0x01) == 0x01) {
  306.                 gevent->type = NSFB_EVENT_KEY_DOWN;
  307.             } else {
  308.                 gevent->type = NSFB_EVENT_KEY_UP;
  309.             }
  310.             gevent->value.keycode = NSFB_KEY_MOUSE_2;
  311.         } else if (((prevbuttonMask ^ buttonMask) & 0x04) == 0x04) {
  312.             if ((buttonMask & 0x01) == 0x01) {
  313.                 gevent->type = NSFB_EVENT_KEY_DOWN;
  314.             } else {
  315.                 gevent->type = NSFB_EVENT_KEY_UP;
  316.             }
  317.             gevent->value.keycode = NSFB_KEY_MOUSE_3;
  318.         } else if (((prevbuttonMask ^ buttonMask) & 0x08) == 0x08) {
  319.             if ((buttonMask & 0x01) == 0x01) {
  320.                 gevent->type = NSFB_EVENT_KEY_DOWN;
  321.             } else {
  322.                 gevent->type = NSFB_EVENT_KEY_UP;
  323.             }
  324.             gevent->value.keycode = NSFB_KEY_MOUSE_4;
  325.         } else if (((prevbuttonMask ^ buttonMask) & 0x10) == 0x10) {
  326.             if ((buttonMask & 0x01) == 0x01) {
  327.                 gevent->type = NSFB_EVENT_KEY_DOWN;
  328.             } else {
  329.                 gevent->type = NSFB_EVENT_KEY_UP;
  330.             }
  331.             gevent->value.keycode = NSFB_KEY_MOUSE_5;
  332.         }
  333.         prevbuttonMask = buttonMask;
  334.     } else {
  335.         gevent->type = NSFB_EVENT_MOVE_ABSOLUTE;
  336.         gevent->value.vector.x = x;
  337.         gevent->value.vector.y = y;
  338.         gevent->value.vector.z = 0;    
  339.     }
  340.  
  341. }
  342.  
  343.  
  344. static void vnc_dokey(rfbBool down, rfbKeySym key, rfbClientPtr cl)
  345. {
  346.     enum nsfb_key_code_e keycode = NSFB_KEY_UNKNOWN;
  347.  
  348.     UNUSED(cl);
  349.  
  350.     if ((key >= XK_space) && (key <= XK_asciitilde)) {
  351.         /* ascii codes line up */
  352.         keycode = key;
  353.     } else if ((key & 0xff00) == 0xff00) {
  354.         /* bottom 8bits of keysyms in this range map via table */
  355.         keycode = vnc_nsfb_map[(key & 0xff)];
  356.     }
  357.  
  358.     if (down == 0) {
  359.         /* key up */
  360.         gevent->type = NSFB_EVENT_KEY_UP;
  361.     } else {
  362.         /* key down */
  363.         gevent->type = NSFB_EVENT_KEY_DOWN;
  364.     }
  365.     gevent->value.keycode = keycode;
  366.  
  367. }
  368.  
  369.  
  370. static int vnc_set_geometry(nsfb_t *nsfb, int width, int height, enum nsfb_format_e format)
  371. {
  372.     if (nsfb->surface_priv != NULL)
  373.         return -1; /* fail if surface already initialised */
  374.  
  375.     if (width > 0) {
  376.         nsfb->width = width;
  377.     }
  378.  
  379.     if (height > 0) {
  380.         nsfb->height = height;
  381.     }
  382.  
  383.     if (format != NSFB_FMT_ANY) {
  384.         nsfb->format = format;
  385.     }
  386.  
  387.     /* select soft plotters appropriate for format */
  388.     select_plotters(nsfb);
  389.  
  390.     return 0;
  391. }
  392.  
  393. static int vnc_initialise(nsfb_t *nsfb)
  394. {
  395.     rfbScreenInfoPtr vncscreen;
  396.     int argc = 0;
  397.     char **argv = NULL;
  398.  
  399.     if (nsfb->surface_priv != NULL)
  400.         return -1; /* fail if surface already initialised */
  401.  
  402.     /* sanity checked depth. */
  403.     if (nsfb->bpp != 32)
  404.         return -1;
  405.  
  406.     /* create vnc screen with 8bits per sample, three samples per
  407.      * pixel and 4 bytes per pixel. */
  408.     vncscreen = rfbGetScreen(&argc, argv,
  409.                              nsfb->width, nsfb->height,
  410.                              8, 3, (nsfb->bpp / 8));
  411.  
  412.     if (vncscreen == NULL) {
  413.         /* Note libvncserver does not check its own allocations/error
  414.          * paths so the faliure mode of the rfbGetScreen is to segfault.
  415.          */
  416.         return -1;
  417.     }
  418.  
  419.     vncscreen->frameBuffer = malloc(nsfb->width * nsfb->height * (nsfb->bpp / 8));
  420.  
  421.     if (vncscreen->frameBuffer == NULL) {
  422.         rfbScreenCleanup(vncscreen);
  423.         return -1;
  424.     }
  425.  
  426.  
  427.     switch (nsfb->bpp) {
  428.     case 8:
  429.         break;
  430.  
  431.     case 16:
  432.         vncscreen->serverFormat.trueColour=TRUE;
  433.         vncscreen->serverFormat.redShift = 11;
  434.         vncscreen->serverFormat.greenShift = 5;
  435.         vncscreen->serverFormat.blueShift = 0;
  436.         vncscreen->serverFormat.redMax = 31;
  437.         vncscreen->serverFormat.greenMax = 63;
  438.         vncscreen->serverFormat.blueMax = 31;
  439.         break;
  440.  
  441.     case 32:
  442.         vncscreen->serverFormat.trueColour=TRUE;
  443.         vncscreen->serverFormat.redShift = 16;
  444.         vncscreen->serverFormat.greenShift = 8;
  445.         vncscreen->serverFormat.blueShift = 0;
  446.         break;
  447.     }
  448.  
  449.     vncscreen->alwaysShared = TRUE;
  450.     vncscreen->autoPort = 1;
  451.     vncscreen->ptrAddEvent = vnc_doptr;
  452.     vncscreen->kbdAddEvent = vnc_dokey;
  453.  
  454.     rfbInitServer(vncscreen);
  455.  
  456.     /* keep parameters */
  457.     nsfb->surface_priv = vncscreen;
  458.     nsfb->ptr = (uint8_t *)vncscreen->frameBuffer;
  459.     nsfb->linelen = (nsfb->width * nsfb->bpp) / 8;
  460.  
  461.     return 0;
  462. }
  463.  
  464. static int vnc_finalise(nsfb_t *nsfb)
  465. {
  466.     rfbScreenInfoPtr vncscreen = nsfb->surface_priv;
  467.    
  468.     if (vncscreen != NULL) {
  469.         rfbScreenCleanup(vncscreen);
  470.     }
  471.  
  472.     return 0;
  473. }
  474.  
  475.  
  476. static int vnc_update(nsfb_t *nsfb, nsfb_bbox_t *box)
  477. {
  478.     rfbScreenInfoPtr vncscreen = nsfb->surface_priv;
  479.  
  480.     rfbMarkRectAsModified(vncscreen, box->x0, box->y0, box->x1, box->y1);
  481.  
  482.     return 0;
  483. }
  484.  
  485.  
  486. static bool vnc_input(nsfb_t *nsfb, nsfb_event_t *event, int timeout)
  487. {
  488.     rfbScreenInfoPtr vncscreen = nsfb->surface_priv;
  489.     int ret;
  490.  
  491.     if (vncscreen != NULL) {
  492.  
  493.         gevent = event; /* blergh - have to use global state to pass data */
  494.  
  495.         /* set default to timeout */
  496.         event->type = NSFB_EVENT_CONTROL;
  497.         event->value.controlcode = NSFB_CONTROL_TIMEOUT;
  498.  
  499.         ret = rfbProcessEvents(vncscreen, timeout * 1000);
  500.         return true;
  501.     }
  502.  
  503.     return false;
  504. }
  505.  
  506. static int
  507. vnc_cursor(nsfb_t *nsfb, struct nsfb_cursor_s *cursor)
  508. {
  509.     rfbScreenInfoPtr vncscreen = nsfb->surface_priv;
  510.     rfbCursorPtr vnccursor = calloc(1,sizeof(rfbCursor));
  511.     int rwidth; /* rounded width */
  512.     int row;
  513.     int col;
  514.     const nsfb_colour_t *pixel;
  515.     uint8_t bit;
  516.  
  517.     rwidth = (cursor->bmp_width + 7) / 8;
  518.  
  519.     vnccursor->cleanup = 1; /* rfb lib will free this allocation */
  520.     vnccursor->width = cursor->bmp_width;
  521.     vnccursor->height = cursor->bmp_height;
  522.     vnccursor->foreRed = vnccursor->foreGreen = vnccursor->foreBlue = 0xffff;
  523.  
  524.     vnccursor->source = calloc(rwidth, vnccursor->height);
  525.     vnccursor->cleanupSource = 1; /* rfb lib will free this allocation */
  526.     vnccursor->mask = calloc(rwidth, vnccursor->height);
  527.     vnccursor->cleanupMask = 1; /* rfb lib will free this allocation */
  528.  
  529.     for (row = 0, pixel = cursor->pixel; row < vnccursor->height; row++) {
  530.         for (col = 0, bit = 0x80;
  531.              col < vnccursor->width;
  532.              col++, bit = (bit & 1)? 0x80 : bit>>1, pixel++) {
  533.  
  534.             /* pixel luminance more than 50% */
  535.             if ((((((*pixel) & 0xff) * 77) +
  536.                   ((((*pixel) & 0xff00) >> 8) * 151) +
  537.                   ((((*pixel) & 0xff0000) >> 16) * 28)) / 256) > 128) {
  538.                
  539.                 vnccursor->source[row * rwidth + col/8] |= bit;
  540.             }
  541.             if (((*pixel) & 0xff000000) != 0) {
  542.                 vnccursor->mask[row * rwidth + col/8] |= bit;
  543.             }
  544.         }
  545.     }
  546.  
  547.     rfbSetCursor(vncscreen, vnccursor);
  548.     return true;
  549. }
  550.  
  551. const nsfb_surface_rtns_t vnc_rtns = {
  552.     .initialise = vnc_initialise,
  553.     .finalise = vnc_finalise,
  554.     .input = vnc_input,
  555.     .update = vnc_update,
  556.     .cursor = vnc_cursor,
  557.     .geometry = vnc_set_geometry,
  558. };
  559.  
  560. NSFB_SURFACE_DEF(vnc, NSFB_SURFACE_VNC, &vnc_rtns)
  561.  
  562. /*
  563.  * Local variables:
  564.  *  c-basic-offset: 4
  565.  *  tab-width: 8
  566.  * End:
  567.  */
  568.