• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  *  OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@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
saveDimSettings(void)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
restoreDimSettings(void)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
saveSleepSettings(void)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
restoreSleepSettings(void)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
rfbDimmingInit(void)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
rfbUndim(void)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
rfbDimmingShutdown(void)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
KbdAddEvent(rfbBool down,rfbKeySym keySym,struct _rfbClientRec * cl)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
PtrAddEvent(buttonMask,x,y,cl)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
ScreenInit(int argc,char ** argv)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
refreshCallback(CGRectCount count,const CGRect * rectArray,void * ignore)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 
clientGone(rfbClientPtr cl)497 void clientGone(rfbClientPtr cl)
498 {
499   rfbShutdown(cl);
500 }
501 
newClient(rfbClientPtr cl)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 
main(int argc,char * argv[])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 
rfbShutdown(rfbClientPtr cl)548 void rfbShutdown(rfbClientPtr cl)
549 {
550   rfbScreenCleanup(rfbScreen);
551   rfbDimmingShutdown();
552   exit(0);
553 }
554