Home | History | Annotate | Download | only in examples
      1 
      2 /*
      3  *  OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk (at) incompleteness.net>.
      4  *  Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
      5  *  All Rights Reserved.
      6  *
      7  * Cut in two parts by Johannes Schindelin (2001): libvncserver and OSXvnc.
      8  *
      9  *
     10  * This file implements every system specific function for Mac OS X.
     11  *
     12  *  It includes the keyboard functions:
     13  *
     14      void KbdAddEvent(down, keySym, cl)
     15         rfbBool down;
     16         rfbKeySym keySym;
     17         rfbClientPtr cl;
     18      void KbdReleaseAllKeys()
     19  *
     20  *  the mouse functions:
     21  *
     22      void PtrAddEvent(buttonMask, x, y, cl)
     23         int buttonMask;
     24         int x;
     25         int y;
     26         rfbClientPtr cl;
     27  *
     28  */
     29 
     30 #include <unistd.h>
     31 #include <ApplicationServices/ApplicationServices.h>
     32 #include <Carbon/Carbon.h>
     33 /* zlib doesn't like Byte already defined */
     34 #undef Byte
     35 #undef TRUE
     36 #undef rfbBool
     37 #include <rfb/rfb.h>
     38 #include <rfb/keysym.h>
     39 
     40 #include <IOKit/pwr_mgt/IOPMLib.h>
     41 #include <IOKit/pwr_mgt/IOPM.h>
     42 #include <stdio.h>
     43 #include <signal.h>
     44 #include <pthread.h>
     45 
     46 rfbBool rfbNoDimming = FALSE;
     47 rfbBool rfbNoSleep   = TRUE;
     48 
     49 static pthread_mutex_t  dimming_mutex;
     50 static unsigned long    dim_time;
     51 static unsigned long    sleep_time;
     52 static mach_port_t      master_dev_port;
     53 static io_connect_t     power_mgt;
     54 static rfbBool initialized            = FALSE;
     55 static rfbBool dim_time_saved         = FALSE;
     56 static rfbBool sleep_time_saved       = FALSE;
     57 
     58 static int
     59 saveDimSettings(void)
     60 {
     61     if (IOPMGetAggressiveness(power_mgt,
     62                               kPMMinutesToDim,
     63                               &dim_time) != kIOReturnSuccess)
     64         return -1;
     65 
     66     dim_time_saved = TRUE;
     67     return 0;
     68 }
     69 
     70 static int
     71 restoreDimSettings(void)
     72 {
     73     if (!dim_time_saved)
     74         return -1;
     75 
     76     if (IOPMSetAggressiveness(power_mgt,
     77                               kPMMinutesToDim,
     78                               dim_time) != kIOReturnSuccess)
     79         return -1;
     80 
     81     dim_time_saved = FALSE;
     82     dim_time = 0;
     83     return 0;
     84 }
     85 
     86 static int
     87 saveSleepSettings(void)
     88 {
     89     if (IOPMGetAggressiveness(power_mgt,
     90                               kPMMinutesToSleep,
     91                               &sleep_time) != kIOReturnSuccess)
     92         return -1;
     93 
     94     sleep_time_saved = TRUE;
     95     return 0;
     96 }
     97 
     98 static int
     99 restoreSleepSettings(void)
    100 {
    101     if (!sleep_time_saved)
    102         return -1;
    103 
    104     if (IOPMSetAggressiveness(power_mgt,
    105                               kPMMinutesToSleep,
    106                               sleep_time) != kIOReturnSuccess)
    107         return -1;
    108 
    109     sleep_time_saved = FALSE;
    110     sleep_time = 0;
    111     return 0;
    112 }
    113 
    114 
    115 int
    116 rfbDimmingInit(void)
    117 {
    118     pthread_mutex_init(&dimming_mutex, NULL);
    119 
    120     if (IOMasterPort(bootstrap_port, &master_dev_port) != kIOReturnSuccess)
    121         return -1;
    122 
    123     if (!(power_mgt = IOPMFindPowerManagement(master_dev_port)))
    124         return -1;
    125 
    126     if (rfbNoDimming) {
    127         if (saveDimSettings() < 0)
    128             return -1;
    129         if (IOPMSetAggressiveness(power_mgt,
    130                                   kPMMinutesToDim, 0) != kIOReturnSuccess)
    131             return -1;
    132     }
    133 
    134     if (rfbNoSleep) {
    135         if (saveSleepSettings() < 0)
    136             return -1;
    137         if (IOPMSetAggressiveness(power_mgt,
    138                                   kPMMinutesToSleep, 0) != kIOReturnSuccess)
    139             return -1;
    140     }
    141 
    142     initialized = TRUE;
    143     return 0;
    144 }
    145 
    146 
    147 int
    148 rfbUndim(void)
    149 {
    150     int result = -1;
    151 
    152     pthread_mutex_lock(&dimming_mutex);
    153 
    154     if (!initialized)
    155         goto DONE;
    156 
    157     if (!rfbNoDimming) {
    158         if (saveDimSettings() < 0)
    159             goto DONE;
    160         if (IOPMSetAggressiveness(power_mgt, kPMMinutesToDim, 0) != kIOReturnSuccess)
    161             goto DONE;
    162         if (restoreDimSettings() < 0)
    163             goto DONE;
    164     }
    165 
    166     if (!rfbNoSleep) {
    167         if (saveSleepSettings() < 0)
    168             goto DONE;
    169         if (IOPMSetAggressiveness(power_mgt, kPMMinutesToSleep, 0) != kIOReturnSuccess)
    170             goto DONE;
    171         if (restoreSleepSettings() < 0)
    172             goto DONE;
    173     }
    174 
    175     result = 0;
    176 
    177  DONE:
    178     pthread_mutex_unlock(&dimming_mutex);
    179     return result;
    180 }
    181 
    182 
    183 int
    184 rfbDimmingShutdown(void)
    185 {
    186     int result = -1;
    187 
    188     if (!initialized)
    189         goto DONE;
    190 
    191     pthread_mutex_lock(&dimming_mutex);
    192     if (dim_time_saved)
    193         if (restoreDimSettings() < 0)
    194             goto DONE;
    195     if (sleep_time_saved)
    196         if (restoreSleepSettings() < 0)
    197             goto DONE;
    198 
    199     result = 0;
    200 
    201  DONE:
    202     pthread_mutex_unlock(&dimming_mutex);
    203     return result;
    204 }
    205 
    206 rfbScreenInfoPtr rfbScreen;
    207 
    208 void rfbShutdown(rfbClientPtr cl);
    209 
    210 /* some variables to enable special behaviour */
    211 int startTime = -1, maxSecsToConnect = 0;
    212 rfbBool disconnectAfterFirstClient = TRUE;
    213 
    214 /* Where do I get the "official" list of Mac key codes?
    215    Ripped these out of a Mac II emulator called Basilisk II
    216    that I found on the net. */
    217 static int keyTable[] = {
    218     /* The alphabet */
    219     XK_A,                  0,      /* A */
    220     XK_B,                 11,      /* B */
    221     XK_C,                  8,      /* C */
    222     XK_D,                  2,      /* D */
    223     XK_E,                 14,      /* E */
    224     XK_F,                  3,      /* F */
    225     XK_G,                  5,      /* G */
    226     XK_H,                  4,      /* H */
    227     XK_I,                 34,      /* I */
    228     XK_J,                 38,      /* J */
    229     XK_K,                 40,      /* K */
    230     XK_L,                 37,      /* L */
    231     XK_M,                 46,      /* M */
    232     XK_N,                 45,      /* N */
    233     XK_O,                 31,      /* O */
    234     XK_P,                 35,      /* P */
    235     XK_Q,                 12,      /* Q */
    236     XK_R,                 15,      /* R */
    237     XK_S,                  1,      /* S */
    238     XK_T,                 17,      /* T */
    239     XK_U,                 32,      /* U */
    240     XK_V,                  9,      /* V */
    241     XK_W,                 13,      /* W */
    242     XK_X,                  7,      /* X */
    243     XK_Y,                 16,      /* Y */
    244     XK_Z,                  6,      /* Z */
    245     XK_a,                  0,      /* a */
    246     XK_b,                 11,      /* b */
    247     XK_c,                  8,      /* c */
    248     XK_d,                  2,      /* d */
    249     XK_e,                 14,      /* e */
    250     XK_f,                  3,      /* f */
    251     XK_g,                  5,      /* g */
    252     XK_h,                  4,      /* h */
    253     XK_i,                 34,      /* i */
    254     XK_j,                 38,      /* j */
    255     XK_k,                 40,      /* k */
    256     XK_l,                 37,      /* l */
    257     XK_m,                 46,      /* m */
    258     XK_n,                 45,      /* n */
    259     XK_o,                 31,      /* o */
    260     XK_p,                 35,      /* p */
    261     XK_q,                 12,      /* q */
    262     XK_r,                 15,      /* r */
    263     XK_s,                  1,      /* s */
    264     XK_t,                 17,      /* t */
    265     XK_u,                 32,      /* u */
    266     XK_v,                  9,      /* v */
    267     XK_w,                 13,      /* w */
    268     XK_x,                  7,      /* x */
    269     XK_y,                 16,      /* y */
    270     XK_z,                  6,      /* z */
    271 
    272     /* Numbers */
    273     XK_0,                 29,      /* 0 */
    274     XK_1,                 18,      /* 1 */
    275     XK_2,                 19,      /* 2 */
    276     XK_3,                 20,      /* 3 */
    277     XK_4,                 21,      /* 4 */
    278     XK_5,                 23,      /* 5 */
    279     XK_6,                 22,      /* 6 */
    280     XK_7,                 26,      /* 7 */
    281     XK_8,                 28,      /* 8 */
    282     XK_9,                 25,      /* 9 */
    283 
    284     /* Symbols */
    285     XK_exclam,            18,      /* ! */
    286     XK_at,                19,      /* @ */
    287     XK_numbersign,        20,      /* # */
    288     XK_dollar,            21,      /* $ */
    289     XK_percent,           23,      /* % */
    290     XK_asciicircum,       22,      /* ^ */
    291     XK_ampersand,         26,      /* & */
    292     XK_asterisk,          28,      /* * */
    293     XK_parenleft,         25,      /* ( */
    294     XK_parenright,        29,      /* ) */
    295     XK_minus,             27,      /* - */
    296     XK_underscore,        27,      /* _ */
    297     XK_equal,             24,      /* = */
    298     XK_plus,              24,      /* + */
    299     XK_grave,             10,      /* ` */  /* XXX ? */
    300     XK_asciitilde,        10,      /* ~ */
    301     XK_bracketleft,       33,      /* [ */
    302     XK_braceleft,         33,      /* { */
    303     XK_bracketright,      30,      /* ] */
    304     XK_braceright,        30,      /* } */
    305     XK_semicolon,         41,      /* ; */
    306     XK_colon,             41,      /* : */
    307     XK_apostrophe,        39,      /* ' */
    308     XK_quotedbl,          39,      /* " */
    309     XK_comma,             43,      /* , */
    310     XK_less,              43,      /* < */
    311     XK_period,            47,      /* . */
    312     XK_greater,           47,      /* > */
    313     XK_slash,             44,      /* / */
    314     XK_question,          44,      /* ? */
    315     XK_backslash,         42,      /* \ */
    316     XK_bar,               42,      /* | */
    317 
    318     /* "Special" keys */
    319     XK_space,             49,      /* Space */
    320     XK_Return,            36,      /* Return */
    321     XK_Delete,           117,      /* Delete */
    322     XK_Tab,               48,      /* Tab */
    323     XK_Escape,            53,      /* Esc */
    324     XK_Caps_Lock,         57,      /* Caps Lock */
    325     XK_Num_Lock,          71,      /* Num Lock */
    326     XK_Scroll_Lock,      107,      /* Scroll Lock */
    327     XK_Pause,            113,      /* Pause */
    328     XK_BackSpace,         51,      /* Backspace */
    329     XK_Insert,           114,      /* Insert */
    330 
    331     /* Cursor movement */
    332     XK_Up,               126,      /* Cursor Up */
    333     XK_Down,             125,      /* Cursor Down */
    334     XK_Left,             123,      /* Cursor Left */
    335     XK_Right,            124,      /* Cursor Right */
    336     XK_Page_Up,          116,      /* Page Up */
    337     XK_Page_Down,        121,      /* Page Down */
    338     XK_Home,             115,      /* Home */
    339     XK_End,              119,      /* End */
    340 
    341     /* Numeric keypad */
    342     XK_KP_0,              82,      /* KP 0 */
    343     XK_KP_1,              83,      /* KP 1 */
    344     XK_KP_2,              84,      /* KP 2 */
    345     XK_KP_3,              85,      /* KP 3 */
    346     XK_KP_4,              86,      /* KP 4 */
    347     XK_KP_5,              87,      /* KP 5 */
    348     XK_KP_6,              88,      /* KP 6 */
    349     XK_KP_7,              89,      /* KP 7 */
    350     XK_KP_8,              91,      /* KP 8 */
    351     XK_KP_9,              92,      /* KP 9 */
    352     XK_KP_Enter,          76,      /* KP Enter */
    353     XK_KP_Decimal,        65,      /* KP . */
    354     XK_KP_Add,            69,      /* KP + */
    355     XK_KP_Subtract,       78,      /* KP - */
    356     XK_KP_Multiply,       67,      /* KP * */
    357     XK_KP_Divide,         75,      /* KP / */
    358 
    359     /* Function keys */
    360     XK_F1,               122,      /* F1 */
    361     XK_F2,               120,      /* F2 */
    362     XK_F3,                99,      /* F3 */
    363     XK_F4,               118,      /* F4 */
    364     XK_F5,                96,      /* F5 */
    365     XK_F6,                97,      /* F6 */
    366     XK_F7,                98,      /* F7 */
    367     XK_F8,               100,      /* F8 */
    368     XK_F9,               101,      /* F9 */
    369     XK_F10,              109,      /* F10 */
    370     XK_F11,              103,      /* F11 */
    371     XK_F12,              111,      /* F12 */
    372 
    373     /* Modifier keys */
    374     XK_Shift_L,           56,      /* Shift Left */
    375     XK_Shift_R,           56,      /* Shift Right */
    376     XK_Control_L,         59,      /* Ctrl Left */
    377     XK_Control_R,         59,      /* Ctrl Right */
    378     XK_Meta_L,            58,      /* Logo Left (-> Option) */
    379     XK_Meta_R,            58,      /* Logo Right (-> Option) */
    380     XK_Alt_L,             55,      /* Alt Left (-> Command) */
    381     XK_Alt_R,             55,      /* Alt Right (-> Command) */
    382 
    383     /* Weirdness I can't figure out */
    384 #if 0
    385     XK_3270_PrintScreen,     105,     /* PrintScrn */
    386     ???  94,          50,      /* International */
    387     XK_Menu,              50,      /* Menu (-> International) */
    388 #endif
    389 };
    390 
    391 void
    392 KbdAddEvent(rfbBool down, rfbKeySym keySym, struct _rfbClientRec* cl)
    393 {
    394     int i;
    395     CGKeyCode keyCode = -1;
    396     int found = 0;
    397 
    398     if(((int)cl->clientData)==-1) return; /* viewOnly */
    399 
    400     rfbUndim();
    401 
    402     for (i = 0; i < (sizeof(keyTable) / sizeof(int)); i += 2) {
    403         if (keyTable[i] == keySym) {
    404             keyCode = keyTable[i+1];
    405             found = 1;
    406             break;
    407         }
    408     }
    409 
    410     if (!found) {
    411         rfbErr("warning: couldn't figure out keycode for X keysym %d (0x%x)\n",
    412                (int)keySym, (int)keySym);
    413     } else {
    414         /* Hopefully I can get away with not specifying a CGCharCode.
    415            (Why would you need both?) */
    416         CGPostKeyboardEvent((CGCharCode)0, keyCode, down);
    417     }
    418 }
    419 
    420 void
    421 PtrAddEvent(buttonMask, x, y, cl)
    422     int buttonMask;
    423     int x;
    424     int y;
    425     rfbClientPtr cl;
    426 {
    427     CGPoint position;
    428 
    429     if(((int)cl->clientData)==-1) return; /* viewOnly */
    430 
    431     rfbUndim();
    432 
    433     position.x = x;
    434     position.y = y;
    435 
    436     CGPostMouseEvent(position, TRUE, 8,
    437                      (buttonMask & (1 << 0)) ? TRUE : FALSE,
    438                      (buttonMask & (1 << 1)) ? TRUE : FALSE,
    439                      (buttonMask & (1 << 2)) ? TRUE : FALSE,
    440                      (buttonMask & (1 << 3)) ? TRUE : FALSE,
    441                      (buttonMask & (1 << 4)) ? TRUE : FALSE,
    442                      (buttonMask & (1 << 5)) ? TRUE : FALSE,
    443                      (buttonMask & (1 << 6)) ? TRUE : FALSE,
    444                      (buttonMask & (1 << 7)) ? TRUE : FALSE);
    445 }
    446 
    447 rfbBool viewOnly = FALSE, sharedMode = FALSE;
    448 
    449 void
    450 ScreenInit(int argc, char**argv)
    451 {
    452   int bitsPerSample=CGDisplayBitsPerSample(kCGDirectMainDisplay);
    453   rfbScreen = rfbGetScreen(&argc,argv,
    454 			   CGDisplayPixelsWide(kCGDirectMainDisplay),
    455 			   CGDisplayPixelsHigh(kCGDirectMainDisplay),
    456 			   bitsPerSample,
    457 			   CGDisplaySamplesPerPixel(kCGDirectMainDisplay),4);
    458   if(!rfbScreen)
    459     exit(0);
    460   rfbScreen->serverFormat.redShift = bitsPerSample*2;
    461   rfbScreen->serverFormat.greenShift = bitsPerSample*1;
    462   rfbScreen->serverFormat.blueShift = 0;
    463 
    464   gethostname(rfbScreen->thisHost, 255);
    465   rfbScreen->paddedWidthInBytes = CGDisplayBytesPerRow(kCGDirectMainDisplay);
    466   rfbScreen->frameBuffer =
    467     (char *)CGDisplayBaseAddress(kCGDirectMainDisplay);
    468 
    469   /* we cannot write to the frame buffer */
    470   rfbScreen->cursor = NULL;
    471 
    472   rfbScreen->ptrAddEvent = PtrAddEvent;
    473   rfbScreen->kbdAddEvent = KbdAddEvent;
    474 
    475   if(sharedMode) {
    476     rfbScreen->alwaysShared = TRUE;
    477   }
    478 
    479   rfbInitServer(rfbScreen);
    480 }
    481 
    482 static void
    483 refreshCallback(CGRectCount count, const CGRect *rectArray, void *ignore)
    484 {
    485   int i;
    486 
    487   if(startTime>0 && time(0)>startTime+maxSecsToConnect)
    488     rfbShutdown(0);
    489 
    490   for (i = 0; i < count; i++)
    491     rfbMarkRectAsModified(rfbScreen,
    492 			  rectArray[i].origin.x,rectArray[i].origin.y,
    493 			  rectArray[i].origin.x + rectArray[i].size.width,
    494 			  rectArray[i].origin.y + rectArray[i].size.height);
    495 }
    496 
    497 void clientGone(rfbClientPtr cl)
    498 {
    499   rfbShutdown(cl);
    500 }
    501 
    502 enum rfbNewClientAction newClient(rfbClientPtr cl)
    503 {
    504   if(startTime>0 && time(0)>startTime+maxSecsToConnect)
    505     rfbShutdown(cl);
    506 
    507   if(disconnectAfterFirstClient)
    508     cl->clientGoneHook = clientGone;
    509 
    510   cl->clientData=(void*)((viewOnly)?-1:0);
    511 
    512   return(RFB_CLIENT_ACCEPT);
    513 }
    514 
    515 int main(int argc,char *argv[])
    516 {
    517   int i;
    518 
    519   for(i=argc-1;i>0;i--)
    520     if(i<argc-1 && strcmp(argv[i],"-wait4client")==0) {
    521       maxSecsToConnect = atoi(argv[i+1])/1000;
    522       startTime = time(0);
    523     } else if(strcmp(argv[i],"-runforever")==0) {
    524       disconnectAfterFirstClient = FALSE;
    525     } else if(strcmp(argv[i],"-viewonly")==0) {
    526       viewOnly=TRUE;
    527     } else if(strcmp(argv[i],"-shared")==0) {
    528       sharedMode=TRUE;
    529     }
    530 
    531   rfbDimmingInit();
    532 
    533   ScreenInit(argc,argv);
    534   rfbScreen->newClientHook = newClient;
    535 
    536   /* enter background event loop */
    537   rfbRunEventLoop(rfbScreen,40,TRUE);
    538 
    539   /* enter OS X loop */
    540   CGRegisterScreenRefreshCallback(refreshCallback, NULL);
    541   RunApplicationEventLoop();
    542 
    543   rfbDimmingShutdown();
    544 
    545   return(0); /* never ... */
    546 }
    547 
    548 void rfbShutdown(rfbClientPtr cl)
    549 {
    550   rfbScreenCleanup(rfbScreen);
    551   rfbDimmingShutdown();
    552   exit(0);
    553 }
    554