Home | History | Annotate | Download | only in x11vnc
      1 /*
      2    Copyright (C) 2002-2010 Karl J. Runge <runge (at) karlrunge.com>
      3    All rights reserved.
      4 
      5 This file is part of x11vnc.
      6 
      7 x11vnc is free software; you can redistribute it and/or modify
      8 it under the terms of the GNU General Public License as published by
      9 the Free Software Foundation; either version 2 of the License, or (at
     10 your option) any later version.
     11 
     12 x11vnc is distributed in the hope that it will be useful,
     13 but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with x11vnc; if not, write to the Free Software
     19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
     20 or see <http://www.gnu.org/licenses/>.
     21 
     22 In addition, as a special exception, Karl J. Runge
     23 gives permission to link the code of its release of x11vnc with the
     24 OpenSSL project's "OpenSSL" library (or with modified versions of it
     25 that use the same license as the "OpenSSL" library), and distribute
     26 the linked executables.  You must obey the GNU General Public License
     27 in all respects for all of the code used other than "OpenSSL".  If you
     28 modify this file, you may extend this exception to your version of the
     29 file, but you are not obligated to do so.  If you do not wish to do
     30 so, delete this exception statement from your version.
     31 */
     32 
     33 /* -- macosxCG.c -- */
     34 
     35 /*
     36  * We need to keep this separate from nearly everything else, e.g. rfb.h
     37  * and the other stuff, otherwise it does not work properly, mouse drags
     38  * will not work!!
     39  */
     40 
     41 void macosxCG_dummy(void) {}
     42 
     43 #if (defined(__MACH__) && defined(__APPLE__))
     44 
     45 #include <ApplicationServices/ApplicationServices.h>
     46 #include <Cocoa/Cocoa.h>
     47 #include <Carbon/Carbon.h>
     48 
     49 void macosxCG_init(void);
     50 void macosxCG_fini(void);
     51 void macosxCG_event_loop(void);
     52 char *macosxCG_get_fb_addr(void);
     53 
     54 int macosxCG_CGDisplayPixelsWide(void);
     55 int macosxCG_CGDisplayPixelsHigh(void);
     56 int macosxCG_CGDisplayBitsPerPixel(void);
     57 int macosxCG_CGDisplayBitsPerSample(void);
     58 int macosxCG_CGDisplaySamplesPerPixel(void);
     59 int macosxCG_CGDisplayBytesPerRow(void);
     60 
     61 void macosxCG_pointer_inject(int mask, int x, int y);
     62 int macosxCG_get_cursor_pos(int *x, int *y);
     63 int macosxCG_get_cursor(void);
     64 void macosxCG_init_key_table(void);
     65 void macosxCG_keysym_inject(int down, unsigned int keysym);
     66 void macosxCG_keycode_inject(int down, int keycode);
     67 
     68 CGDirectDisplayID displayID = 0;
     69 
     70 extern void macosx_log(char *);
     71 extern int collect_non_X_xdamage(int x_in, int y_in, int w_in, int h_in, int call);
     72 
     73 static void macosxCG_callback(CGRectCount n, const CGRect *rects, void *dum) {
     74 	int i, db = 0;
     75 	if (db) fprintf(stderr, "macosx_callback: n=%d\n", (int) n);
     76 	if (!dum) {}
     77 	for (i=0; i < (int) n; i++) {
     78 		if (db > 1) fprintf(stderr, "               : %g %g - %g %g\n", rects[i].origin.x, rects[i].origin.y, rects[i].size.width, rects[i].size.height);
     79 		collect_non_X_xdamage( (int) rects[i].origin.x, (int) rects[i].origin.y,
     80 		    (int) rects[i].size.width, (int) rects[i].size.height, 1);
     81 	}
     82 }
     83 
     84 #if 0
     85 >
     86 > if gcc -DHAVE_CONFIG_H -I. -I. -I..   -I/opt/local/include   -I/opt/local/include -ObjC -g -O2 -Wall -MT x11vnc-macosxCG.o -MD -MP -MF ".deps/x11vnc-macosxCG.Tpo" -c -o x11vnc-macosxCG.o `test -f 'macosxCG.c' || echo './'`macosxCG.c; \
     87 > 	then mv -f ".deps/x11vnc-macosxCG.Tpo" ".deps/x11vnc-macosxCG.Po"; else rm -f ".deps/x11vnc-macosxCG.Tpo"; exit 1; fi
     88 > macosxCG.c:149: warning: CGSetLocalEventsSuppressionInterval is deprecated (declared at /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Headers/CGRemoteOperation.h:373)
     89 > macosxCG.c:150: warning: CGSetLocalEventsFilterDuringSuppressionState is deprecated (declared at /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Headers/CGRemoteOperation.h:366)
     90 > macosxCG.c:153: warning: CGSetLocalEventsFilterDuringSuppressionState is deprecated (declared at /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Headers/CGRemoteOperation.h:366)
     91 > macosxCG.c:244: warning: CGDisplayBaseAddress is deprecated (declared at /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Headers/CGDirectDisplay.h:466)
     92 > macosxCG.c:254: warning: CGDisplayBitsPerPixel is deprecated (declared at /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Headers/CGDirectDisplay.h:517)
     93 > macosxCG.c:257: warning: CGDisplayBitsPerSample is deprecated (declared at /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Headers/CGDirectDisplay.h:522)
     94 > macosxCG.c:260: warning: CGDisplaySamplesPerPixel is deprecated (declared at /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Headers/CGDirectDisplay.h:526)
     95 > macosxCG.c:263: warning: CGDisplayBytesPerRow is deprecated (declared at /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Headers/CGDirectDisplay.h:476)
     96 > macosxCG.c:419: warning: CGPostScrollWheelEvent is deprecated (declared at /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Headers/CGRemoteOperation.h:327)
     97 > macosxCG.c:422: warning: CGPostScrollWheelEvent is deprecated (declared at /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Headers/CGRemoteOperation.h:327)
     98 > macosxCG.c:425: warning: CGPostMouseEvent is deprecated (declared at /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Headers/CGRemoteOperation.h:307)
     99 > macosxCG.c:641: warning: CGPostKeyboardEvent is deprecated (declared at /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Headers/CGRemoteOperation.h:333)
    100 > macosxCG.c:661: warning: CGPostKeyboardEvent is deprecated (declared at /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Headers/CGRemoteOperation.h:333)
    101 >
    102 
    103 X11VNC_MACOSX_NO_DEPRECATED_LOCALEVENTS
    104 X11VNC_MACOSX_NO_DEPRECATED_POSTEVENTS
    105 X11VNC_MACOSX_NO_DEPRECATED_FRAMEBUFFER
    106 X11VNC_MACOSX_NO_DEPRECATED
    107 
    108 #endif
    109 
    110 static int callback_set = 0;
    111 extern int nofb;
    112 
    113 void macosxCG_refresh_callback_on(void) {
    114 	if (nofb) {
    115 		return;
    116 	}
    117 
    118 	if (! callback_set) {
    119 		if (1) macosx_log("macosxCG_refresh_callback: register\n");
    120 		CGRegisterScreenRefreshCallback(macosxCG_callback, NULL);
    121 	}
    122 	callback_set = 1;
    123 }
    124 
    125 void macosxCG_refresh_callback_off(void) {
    126 	if (callback_set) {
    127 		if (1) macosx_log("macosxCG_refresh_callback: unregister\n");
    128 		CGUnregisterScreenRefreshCallback(macosxCG_callback, NULL);
    129 	}
    130 	callback_set = 0;
    131 }
    132 
    133 extern int macosx_noscreensaver;
    134 extern int macosx_read_opengl;
    135 extern int macosx_read_rawfb;
    136 
    137 extern void macosxGCS_initpb(void);
    138 extern int macosxCGP_init_dimming(void);
    139 extern int macosxCGP_undim(void);
    140 extern int macosxCGP_dim_shutdown(void);
    141 extern void macosxCGP_screensaver_timer_off(void);
    142 extern void macosxCGP_screensaver_timer_on(void);
    143 extern void macosx_opengl_init(void);
    144 extern void macosx_opengl_fini(void);
    145 
    146 int x11vnc_macosx_no_deprecated_localevents = 0;
    147 int x11vnc_macosx_no_deprecated_postevents  = 0;
    148 int x11vnc_macosx_no_deprecated_framebuffer = 0;
    149 
    150 void macosxCG_init(void) {
    151 
    152 	x11vnc_macosx_no_deprecated_localevents = 0;
    153 	x11vnc_macosx_no_deprecated_postevents  = 0;
    154 	x11vnc_macosx_no_deprecated_framebuffer = 0;
    155 
    156 	if (getenv("X11VNC_MACOSX_NO_DEPRECATED_LOCALEVENTS") || getenv("X11VNC_MACOSX_NO_DEPRECATED")) {
    157 		x11vnc_macosx_no_deprecated_localevents = 1;
    158 	}
    159 	if (getenv("X11VNC_MACOSX_NO_DEPRECATED_POSTEVENTS") || getenv("X11VNC_MACOSX_NO_DEPRECATED")) {
    160 		x11vnc_macosx_no_deprecated_postevents = 1;
    161 	}
    162 	if (getenv("X11VNC_MACOSX_NO_DEPRECATED_FRAMEBUFFER") || getenv("X11VNC_MACOSX_NO_DEPRECATED")) {
    163 		x11vnc_macosx_no_deprecated_framebuffer = 1;
    164 	}
    165 
    166 	if (displayID == 0) {
    167 		macosx_log("macosxCG_init: initializing display.\n");
    168 
    169 		displayID = kCGDirectMainDisplay;
    170 #ifdef X11VNC_MACOSX_USE_GETMAINDEVICE
    171 		/* not sure this ever did anything. */
    172 		(void) GetMainDevice();
    173 #endif
    174 		if (displayID == 0) {
    175 			macosx_log("macosxCG_init: could not get kCGDirectMainDisplay / CGMainDisplayID() display.\n");
    176 			exit(1);
    177 		}
    178 
    179 #if X11VNC_MACOSX_NO_DEPRECATED_LOCALEVENTS || X11VNC_MACOSX_NO_DEPRECATED
    180 		macosx_log("NO_DEPRECATED_LOCALEVENTS: not calling CGSetLocalEventsSuppressionInterval()\n");
    181 		macosx_log("NO_DEPRECATED_LOCALEVENTS: not calling CGSetLocalEventsFilterDuringSupressionState()\n");
    182 #else
    183 		if (!x11vnc_macosx_no_deprecated_localevents) {
    184 			CGSetLocalEventsSuppressionInterval(0.0);
    185 			CGSetLocalEventsFilterDuringSupressionState(
    186 			    kCGEventFilterMaskPermitAllEvents,
    187 			    kCGEventSupressionStateSupressionInterval);
    188 			CGSetLocalEventsFilterDuringSupressionState(
    189 			    kCGEventFilterMaskPermitAllEvents,
    190 			    kCGEventSupressionStateRemoteMouseDrag);
    191 		} else {
    192 			macosx_log("NO_DEPRECATED_LOCALEVENTS: not calling CGSetLocalEventsSuppressionInterval()\n");
    193 			macosx_log("NO_DEPRECATED_LOCALEVENTS: not calling CGSetLocalEventsFilterDuringSupressionState()\n");
    194 		}
    195 #endif
    196 
    197 		macosx_opengl_init();
    198 
    199 		if (!macosx_read_opengl) {
    200 			char *addr = macosxCG_get_fb_addr();
    201 			if (addr == NULL) {
    202 				macosx_log("macosxCG_init: could not get raw framebuffer address / CGDisplayBaseAddress().\n");
    203 				exit(1);
    204 			}
    205 			macosx_read_rawfb = 1;
    206 			macosx_log("macosxCG_init: using raw framebuffer address for screen capture.\n");
    207 		}
    208 
    209 		macosxCGP_init_dimming();
    210 		if (macosx_noscreensaver) {
    211 			macosxCGP_screensaver_timer_on();
    212 		}
    213 
    214 		macosxGCS_initpb();
    215 	}
    216 }
    217 
    218 void macosxCG_fini(void) {
    219 	macosxCGP_dim_shutdown();
    220 	if (macosx_noscreensaver) {
    221 		macosxCGP_screensaver_timer_off();
    222 	}
    223 	macosxCG_refresh_callback_off();
    224 	macosx_opengl_fini();
    225 	displayID = 0;
    226 }
    227 
    228 extern int dpy_x, dpy_y, bpp, wdpy_x, wdpy_y;
    229 extern int client_count, nofb;
    230 extern void do_new_fb(int);
    231 extern int macosx_wait_for_switch, macosx_resize;
    232 
    233 extern void macosxGCS_poll_pb(void);
    234 #if 0
    235 extern void usleep(unsigned long usec);
    236 #else
    237 extern int usleep(useconds_t usec);
    238 #endif
    239 extern unsigned int sleep(unsigned int seconds);
    240 extern void clean_up_exit(int ret);
    241 
    242 void macosxCG_event_loop(void) {
    243 	OSStatus rc;
    244 	int nbpp;
    245 	static int nbpp_save = -1;
    246 
    247 	macosxGCS_poll_pb();
    248 	if (nofb) {
    249 		return;
    250 	}
    251 
    252 	rc = RunCurrentEventLoop(kEventDurationSecond/30);
    253 
    254 	if (client_count) {
    255 		macosxCG_refresh_callback_on();
    256 	} else {
    257 		macosxCG_refresh_callback_off();
    258 	}
    259 
    260 	nbpp = macosxCG_CGDisplayBitsPerPixel();
    261 
    262 	if (nbpp_save < 0) {
    263 		nbpp_save = nbpp;
    264 	}
    265 
    266 	if (nbpp > 0 && nbpp != nbpp_save) {
    267 		nbpp_save = nbpp;
    268 		if (macosx_resize) {
    269 			do_new_fb(1);
    270 		}
    271 	} else if (wdpy_x != macosxCG_CGDisplayPixelsWide()) {
    272 	    if (wdpy_y != macosxCG_CGDisplayPixelsHigh()) {
    273 		if (macosx_wait_for_switch) {
    274 			int cnt = 0;
    275 			while (1) {
    276 				if(macosxCG_CGDisplayPixelsWide() > 0) {
    277 					if(macosxCG_CGDisplayPixelsHigh() > 0) {
    278 						usleep(500*1000);
    279 						break;
    280 					}
    281 				}
    282 				if ((cnt++ % 120) == 0) {
    283 					macosx_log("waiting for user to "
    284 					    "switch back..\n");
    285 				}
    286 				sleep(1);
    287 			}
    288 			if (wdpy_x == macosxCG_CGDisplayPixelsWide()) {
    289 				if (wdpy_y == macosxCG_CGDisplayPixelsHigh()) {
    290 					macosx_log("we're back...\n");
    291 					return;
    292 				}
    293 			}
    294 		}
    295 		if (macosx_resize) {
    296 			do_new_fb(1);
    297 		}
    298 	    }
    299 	}
    300 	if (nbpp > 0) {
    301 		nbpp_save = nbpp;
    302 	}
    303 }
    304 
    305 extern int macosx_no_rawfb;
    306 extern int macosx_read_opengl;
    307 extern int macosx_opengl_get_width();
    308 extern int macosx_opengl_get_height();
    309 extern int macosx_opengl_get_bpp();
    310 extern int macosx_opengl_get_bps();
    311 extern int macosx_opengl_get_spp();
    312 
    313 #if X11VNC_MACOSX_NO_DEPRECATED_FRAMEBUFFER || X11VNC_MACOSX_NO_DEPRECATED
    314 
    315 char *macosxCG_get_fb_addr(void) {
    316 	return NULL;
    317 }
    318 int macosxCG_CGDisplayPixelsWide(void) {
    319 	return macosx_opengl_get_width();
    320 }
    321 int macosxCG_CGDisplayPixelsHigh(void) {
    322 	return macosx_opengl_get_height();
    323 }
    324 int macosxCG_CGDisplayBitsPerPixel(void) {
    325 	return macosx_opengl_get_bpp();
    326 }
    327 int macosxCG_CGDisplayBitsPerSample(void) {
    328 	return macosx_opengl_get_bps();
    329 }
    330 int macosxCG_CGDisplaySamplesPerPixel(void) {
    331 	return macosx_opengl_get_spp();
    332 }
    333 int macosxCG_CGDisplayBytesPerRow(void) {
    334 	return macosx_opengl_get_width() * macosx_opengl_get_bpp() / 8;
    335 }
    336 
    337 #else
    338 
    339 char *macosxCG_get_fb_addr(void) {
    340 	if (x11vnc_macosx_no_deprecated_framebuffer) {
    341 		macosx_log("CGDisplayBaseAddress disabled by env. var\n");
    342 		return NULL;
    343 	}
    344 	if (macosx_no_rawfb) {
    345 		macosx_log("CGDisplayBaseAddress disabled by user.\n");
    346 		return NULL;
    347 	}
    348 	if (macosx_read_opengl) {
    349 		macosx_log("CGDisplayBaseAddress disabled by OpenGL.\n");
    350 		return NULL;
    351 	}
    352 	return (char *) CGDisplayBaseAddress(displayID);
    353 }
    354 
    355 int macosxCG_CGDisplayPixelsWide(void) {
    356 	if ((0 && macosx_read_opengl) || x11vnc_macosx_no_deprecated_framebuffer) {
    357 		return macosx_opengl_get_width();
    358 	}
    359 	return (int) CGDisplayPixelsWide(displayID);
    360 }
    361 int macosxCG_CGDisplayPixelsHigh(void) {
    362 	if ((0 && macosx_read_opengl) || x11vnc_macosx_no_deprecated_framebuffer) {
    363 		return macosx_opengl_get_height();
    364 	}
    365 	return (int) CGDisplayPixelsHigh(displayID);
    366 }
    367 int macosxCG_CGDisplayBitsPerPixel(void) {
    368 	if ((0 && macosx_read_opengl) || x11vnc_macosx_no_deprecated_framebuffer) {
    369 		return macosx_opengl_get_bpp();
    370 	}
    371 	return (int) CGDisplayBitsPerPixel(displayID);
    372 }
    373 int macosxCG_CGDisplayBitsPerSample(void) {
    374 	if (macosx_read_opengl || x11vnc_macosx_no_deprecated_framebuffer) {
    375 		return macosx_opengl_get_bps();
    376 	}
    377 	return (int) CGDisplayBitsPerSample(displayID);
    378 }
    379 int macosxCG_CGDisplaySamplesPerPixel(void) {
    380 	if (macosx_read_opengl || x11vnc_macosx_no_deprecated_framebuffer) {
    381 		return macosx_opengl_get_spp();
    382 	}
    383 	return (int) CGDisplaySamplesPerPixel(displayID);
    384 }
    385 int macosxCG_CGDisplayBytesPerRow(void) {
    386 	if (macosx_read_opengl || x11vnc_macosx_no_deprecated_framebuffer) {
    387 		return macosx_opengl_get_width() * macosx_opengl_get_bpp()/8;
    388 	}
    389 	return (int) CGDisplayBytesPerRow(displayID);;
    390 }
    391 
    392 #endif
    393 
    394 typedef int CGSConnectionRef;
    395 static CGSConnectionRef conn = 0;
    396 extern CGError CGSNewConnection(void*, CGSConnectionRef*);
    397 extern CGError CGSReleaseConnection(CGSConnectionRef);
    398 extern CGError CGSGetGlobalCursorDataSize(CGSConnectionRef, int*);
    399 extern CGError CGSGetGlobalCursorData(CGSConnectionRef, unsigned char*,
    400     int*, int*, CGRect*, CGPoint*, int*, int*, int*);
    401 extern CGError CGSGetCurrentCursorLocation(CGSConnectionRef, CGPoint*);
    402 extern int CGSCurrentCursorSeed(void);
    403 extern int CGSHardwareCursorActive();
    404 
    405 static unsigned int last_local_button_mask = 0;
    406 static unsigned int last_local_mod_mask = 0;
    407 static int last_local_x = 0;
    408 static int last_local_y = 0;
    409 
    410 extern unsigned int display_button_mask;
    411 extern unsigned int display_mod_mask;
    412 extern int got_local_pointer_input;
    413 extern time_t last_local_input;
    414 
    415 static CGPoint current_cursor_pos(void) {
    416 	CGPoint pos;
    417 	pos.x = 0;
    418 	pos.y = 0;
    419 	if (! conn) {
    420 		if (CGSNewConnection(NULL, &conn) != kCGErrorSuccess) {
    421 			macosx_log("CGSNewConnection error.\n");
    422 			if (!dpy_x || !dpy_y || !wdpy_x || !wdpy_y) {
    423 				clean_up_exit(1);
    424 			}
    425 		}
    426 	}
    427 	if (CGSGetCurrentCursorLocation(conn, &pos) != kCGErrorSuccess) {
    428 		macosx_log("CGSGetCurrentCursorLocation error\n");
    429 	}
    430 
    431 	display_button_mask = GetCurrentButtonState();
    432 #if 0
    433 /* not used yet */
    434 	display_mod_mask = GetCurrentKeyModifiers();
    435 #endif
    436 
    437 	if (last_local_button_mask != display_button_mask) {
    438 		got_local_pointer_input++;
    439 		last_local_input = time(NULL);
    440 	} else if (pos.x != last_local_x || pos.y != last_local_y) {
    441 		got_local_pointer_input++;
    442 		last_local_input = time(NULL);
    443 	}
    444 	last_local_button_mask = display_button_mask;
    445 	last_local_mod_mask = display_mod_mask;
    446 	last_local_x = pos.x;
    447 	last_local_y = pos.y;
    448 
    449 	return pos;
    450 }
    451 
    452 int macosxCG_get_cursor_pos(int *x, int *y) {
    453 	CGPoint pos = current_cursor_pos();
    454 	*x = pos.x;
    455 	*y = pos.y;
    456 	return 1;
    457 }
    458 
    459 extern int get_cursor_serial(int);
    460 extern int store_cursor(int serial, unsigned long *data, int w, int h, int cbpp, int xhot, int yhot);
    461 
    462 int macosxCG_get_cursor(void) {
    463 	int last_idx = (int) get_cursor_serial(1);
    464 	int which = 1;
    465 	CGError err;
    466 	int datasize, row_bytes, cdepth, comps, bpcomp;
    467 	CGRect rect;
    468 	CGPoint hot;
    469 	unsigned char *data;
    470 	int cursor_seed;
    471 	static int last_cursor_seed = -1;
    472 	static time_t last_fetch = 0;
    473 	time_t now = time(NULL);
    474 
    475 	if (last_idx) {
    476 		which = last_idx;
    477 	}
    478 
    479 	if (! conn) {
    480 		if (CGSNewConnection(NULL, &conn) != kCGErrorSuccess) {
    481 			macosx_log("CGSNewConnection error.\n");
    482 			if (!dpy_x || !dpy_y || !wdpy_x || !wdpy_y) {
    483 				clean_up_exit(1);
    484 			}
    485 			return which;
    486 		}
    487 	}
    488 
    489 	/* XXX all of these interfaces are undocumented. */
    490 
    491 	cursor_seed = CGSCurrentCursorSeed();
    492 	if (last_idx && cursor_seed == last_cursor_seed) {
    493 		if (now < last_fetch + 2) {
    494 			return which;
    495 		}
    496 	}
    497 	last_cursor_seed = cursor_seed;
    498 	last_fetch = now;
    499 
    500 	if (CGSGetGlobalCursorDataSize(conn, &datasize) != kCGErrorSuccess) {
    501 		macosx_log("CGSGetGlobalCursorDataSize error\n");
    502 		return which;
    503 	}
    504 
    505 	data = (unsigned char*) malloc(datasize);
    506 
    507 	err = CGSGetGlobalCursorData(conn, data, &datasize, &row_bytes,
    508 	    &rect, &hot, &cdepth, &comps, &bpcomp);
    509 #if 0
    510 	fprintf(stderr, "datasize: %d row_bytes: %d cdepth: %d comps: %d bpcomp: %d w: %d h: %d\n",
    511 	  datasize, row_bytes, cdepth, comps, bpcomp, (int) rect.size.width, (int) rect.size.height);
    512 #endif
    513 	if (err != kCGErrorSuccess) {
    514 		macosx_log("CGSGetGlobalCursorData error\n");
    515 		return which;
    516 	}
    517 
    518 	if (cdepth == 24) {
    519 		cdepth = 32;
    520 	}
    521 
    522 	if (sizeof(long) == 8 && comps * bpcomp <= 32) {
    523 		/* pad it out to unsigned long array size (like xfixes) */
    524 		int i;
    525 		unsigned char *dsave;
    526 		unsigned char *data64 = (unsigned char*) malloc(2 *datasize);
    527 		unsigned int  *uI = (unsigned int  *) data;
    528 		unsigned long *uL = (unsigned long *) data64;
    529 		for (i=0; i < datasize/4; i++) {
    530 			uL[i] = uI[i];
    531 		}
    532 		dsave = data;
    533 		data = data64;
    534 		free(dsave);
    535 	}
    536 
    537 	which = store_cursor(cursor_seed, (unsigned long*) data,
    538 	    (int) rect.size.width, (int) rect.size.height, cdepth, (int) hot.x, (int) hot.y);
    539 
    540 	free(data);
    541 	return(which);
    542 }
    543 
    544 extern int macosx_mouse_wheel_speed;
    545 extern int macosx_swap23;
    546 extern int off_x, coff_x, off_y, coff_y;
    547 
    548 extern int debug_pointer;
    549 
    550 static void CGPostScrollWheelEvent_wr(CGWheelCount wheel_count, int wheel_distance) {
    551 	static int post_mode = -1, mcnt = 0;
    552 
    553 #if !X11VNC_MACOSX_NO_DEPRECATED_POSTEVENTS && !X11VNC_MACOSX_NO_DEPRECATED
    554 	if (post_mode < 0) {
    555 		post_mode = 1;
    556 		if (getenv("X11VNC_MACOSX_NO_DEPRECATED_POSTEVENTS") || getenv("X11VNC_MACOSX_NO_DEPRECATED")) {
    557 			post_mode = 0;
    558 		}
    559 	}
    560 
    561 	if (post_mode) {
    562 		if (mcnt++ < 10 || debug_pointer) fprintf(stderr, "CGPostScrollWheelEvent()\n");
    563 		CGPostScrollWheelEvent(wheel_count, wheel_distance);
    564 	} else
    565 #endif
    566 	{
    567 		/* XXX 10.5 and later */
    568 #ifndef X11VNC_MACOSX_NO_CGEVENTCREATESCROLLWHEELEVENT
    569 		CGEventRef event;
    570 		event = CGEventCreateScrollWheelEvent(NULL, kCGScrollEventUnitLine, wheel_count, wheel_distance);
    571 		if (event != NULL) {
    572 			CGEventPost(kCGHIDEventTap, event);
    573 			CFRelease(event);
    574 		}
    575 #endif
    576 		if (mcnt++ < 10 || debug_pointer) fprintf(stderr, "CGEventCreateScrollWheelEvent()\n");
    577 	}
    578 }
    579 
    580 static void CGPostMouseEvent_wr(CGPoint loc, int update, int count, int d1, int d2, int d3, int p1, int p2, int p3) {
    581 	static int post_mode = -1, mcnt = 0;
    582 
    583 #if !X11VNC_MACOSX_NO_DEPRECATED_POSTEVENTS && !X11VNC_MACOSX_NO_DEPRECATED
    584 	if (post_mode < 0) {
    585 		post_mode = 1;
    586 		if (getenv("X11VNC_MACOSX_NO_DEPRECATED_POSTEVENTS") || getenv("X11VNC_MACOSX_NO_DEPRECATED")) {
    587 			post_mode = 0;
    588 		}
    589 	}
    590 
    591 	if (post_mode) {
    592 		if (mcnt++ < 10 || debug_pointer) fprintf(stderr, "CGPostMouseEvent()\n");
    593 		CGPostMouseEvent(loc, update, count, d1, d2, d3);
    594 	} else
    595 #endif
    596 	{
    597 		/* XXX 10.4 and later */
    598 #ifndef X11VNC_MACOSX_NO_CGEVENTCREATEMOUSEEVENT
    599 		CGEventRef event;
    600 		static int xp = -1, yp;
    601 
    602 		if (xp == -1) {
    603 			xp = loc.x;
    604 			yp = loc.y;
    605 		}
    606 		if (xp != loc.x || yp != loc.y) {
    607 			int moved = 0;
    608 			if (p1 && p1 == d1) {
    609 				event = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDragged, loc, 0);
    610 				if (event != NULL) {
    611 					moved = 1;
    612 					CGEventPost(kCGHIDEventTap, event);
    613 					CFRelease(event);
    614 				}
    615 			}
    616 			if (p3 && p3 == d3) {
    617 				event = CGEventCreateMouseEvent(NULL, kCGEventOtherMouseDragged, loc, 0);
    618 				if (event != NULL) {
    619 					moved = 1;
    620 					CGEventPost(kCGHIDEventTap, event);
    621 					CFRelease(event);
    622 				}
    623 			}
    624 			if (p2 && p2 == d2) {
    625 				event = CGEventCreateMouseEvent(NULL, kCGEventRightMouseDragged, loc, 0);
    626 				if (event != NULL) {
    627 					moved = 1;
    628 					CGEventPost(kCGHIDEventTap, event);
    629 					CFRelease(event);
    630 				}
    631 			}
    632 			if (!moved) {
    633 				event = CGEventCreateMouseEvent(NULL, kCGEventMouseMoved, loc, 0);
    634 				if (event != NULL) {
    635 					CGEventPost(kCGHIDEventTap, event);
    636 					CFRelease(event);
    637 				}
    638 			}
    639 		}
    640 		xp = loc.x;
    641 		yp = loc.y;
    642 		if (p1 != d1) {
    643 			CGEventType type = (!p1 && d1) ? kCGEventLeftMouseDown : kCGEventLeftMouseUp;
    644 			event = CGEventCreateMouseEvent(NULL, type, loc, 0);
    645 			if (event != NULL) {
    646 				CGEventPost(kCGHIDEventTap, event);
    647 				CFRelease(event);
    648 			}
    649 		}
    650 		if (p3 != d3) {
    651 			CGEventType type = (!p3 && d3) ? kCGEventOtherMouseDown : kCGEventOtherMouseUp;
    652 			event = CGEventCreateMouseEvent(NULL, type, loc, kCGMouseButtonCenter);
    653 			if (event != NULL) {
    654 				CGEventPost(kCGHIDEventTap, event);
    655 				CFRelease(event);
    656 			}
    657 		}
    658 		if (p2 != d2) {
    659 			CGEventType type = (!p2 && d2) ? kCGEventRightMouseDown : kCGEventRightMouseUp;
    660 			event = CGEventCreateMouseEvent(NULL, type, loc, 0);
    661 			if (event != NULL) {
    662 				CGEventPost(kCGHIDEventTap, event);
    663 				CFRelease(event);
    664 			}
    665 		}
    666 #endif
    667 		if (mcnt++ < 10 || debug_pointer) fprintf(stderr, "CGEventCreateMouseEvent()\n");
    668 	}
    669 }
    670 
    671 void macosxCG_pointer_inject(int mask, int x, int y) {
    672 	int swap23 = macosx_swap23;
    673 	int s1 = 0, s2 = 1, s3 = 2, s4 = 3, s5 = 4;
    674 	CGPoint loc;
    675 	int wheel_distance = macosx_mouse_wheel_speed;
    676 	static int cnt = 0;
    677 	static int first = 1, prev1 = 0, prev2 = 0, prev3 = 0;
    678 	int curr1, curr2, curr3;
    679 
    680 	if (swap23) {
    681 		s2 = 2;
    682 		s3 = 1;
    683 	}
    684 
    685 	loc.x = x + off_x + coff_x;
    686 	loc.y = y + off_y + coff_y;
    687 
    688 	if ((cnt++ % 10) == 0) {
    689 		macosxCGP_undim();
    690 	}
    691 
    692 	if ((mask & (1 << s4))) {
    693 		CGPostScrollWheelEvent_wr(1,  wheel_distance);
    694 	}
    695 	if ((mask & (1 << s5))) {
    696 		CGPostScrollWheelEvent_wr(1, -wheel_distance);
    697 	}
    698 
    699 	curr1 = (mask & (1 << s1)) ? TRUE : FALSE;
    700 	curr2 = (mask & (1 << s2)) ? TRUE : FALSE;
    701 	curr3 = (mask & (1 << s3)) ? TRUE : FALSE;
    702 
    703 	if (first) {
    704 		prev1 = curr1;
    705 		prev2 = curr2;
    706 		prev3 = curr3;
    707 		first = 0;
    708 	}
    709 
    710 	CGPostMouseEvent_wr(loc, TRUE, 3, curr1, curr2, curr3, prev1, prev2, prev3);
    711 
    712 	prev1 = curr1;
    713 	prev2 = curr2;
    714 	prev3 = curr3;
    715 }
    716 
    717 #define keyTableSize 0xFFFF
    718 
    719 #include <rfb/keysym.h>
    720 
    721 static int USKeyCodes[] = {
    722     /* The alphabet */
    723     XK_A,                  0,      /* A */
    724     XK_B,                 11,      /* B */
    725     XK_C,                  8,      /* C */
    726     XK_D,                  2,      /* D */
    727     XK_E,                 14,      /* E */
    728     XK_F,                  3,      /* F */
    729     XK_G,                  5,      /* G */
    730     XK_H,                  4,      /* H */
    731     XK_I,                 34,      /* I */
    732     XK_J,                 38,      /* J */
    733     XK_K,                 40,      /* K */
    734     XK_L,                 37,      /* L */
    735     XK_M,                 46,      /* M */
    736     XK_N,                 45,      /* N */
    737     XK_O,                 31,      /* O */
    738     XK_P,                 35,      /* P */
    739     XK_Q,                 12,      /* Q */
    740     XK_R,                 15,      /* R */
    741     XK_S,                  1,      /* S */
    742     XK_T,                 17,      /* T */
    743     XK_U,                 32,      /* U */
    744     XK_V,                  9,      /* V */
    745     XK_W,                 13,      /* W */
    746     XK_X,                  7,      /* X */
    747     XK_Y,                 16,      /* Y */
    748     XK_Z,                  6,      /* Z */
    749     XK_a,                  0,      /* a */
    750     XK_b,                 11,      /* b */
    751     XK_c,                  8,      /* c */
    752     XK_d,                  2,      /* d */
    753     XK_e,                 14,      /* e */
    754     XK_f,                  3,      /* f */
    755     XK_g,                  5,      /* g */
    756     XK_h,                  4,      /* h */
    757     XK_i,                 34,      /* i */
    758     XK_j,                 38,      /* j */
    759     XK_k,                 40,      /* k */
    760     XK_l,                 37,      /* l */
    761     XK_m,                 46,      /* m */
    762     XK_n,                 45,      /* n */
    763     XK_o,                 31,      /* o */
    764     XK_p,                 35,      /* p */
    765     XK_q,                 12,      /* q */
    766     XK_r,                 15,      /* r */
    767     XK_s,                  1,      /* s */
    768     XK_t,                 17,      /* t */
    769     XK_u,                 32,      /* u */
    770     XK_v,                  9,      /* v */
    771     XK_w,                 13,      /* w */
    772     XK_x,                  7,      /* x */
    773     XK_y,                 16,      /* y */
    774     XK_z,                  6,      /* z */
    775 
    776     /* Numbers */
    777     XK_0,                 29,      /* 0 */
    778     XK_1,                 18,      /* 1 */
    779     XK_2,                 19,      /* 2 */
    780     XK_3,                 20,      /* 3 */
    781     XK_4,                 21,      /* 4 */
    782     XK_5,                 23,      /* 5 */
    783     XK_6,                 22,      /* 6 */
    784     XK_7,                 26,      /* 7 */
    785     XK_8,                 28,      /* 8 */
    786     XK_9,                 25,      /* 9 */
    787 
    788     /* Symbols */
    789     XK_exclam,            18,      /* ! */
    790     XK_at,                19,      /* @ */
    791     XK_numbersign,        20,      /* # */
    792     XK_dollar,            21,      /* $ */
    793     XK_percent,           23,      /* % */
    794     XK_asciicircum,       22,      /* ^ */
    795     XK_ampersand,         26,      /* & */
    796     XK_asterisk,          28,      /* * */
    797     XK_parenleft,         25,      /* ( */
    798     XK_parenright,        29,      /* ) */
    799     XK_minus,             27,      /* - */
    800     XK_underscore,        27,      /* _ */
    801     XK_equal,             24,      /* = */
    802     XK_plus,              24,      /* + */
    803     XK_grave,             50,      /* ` */  /* XXX ? */
    804     XK_asciitilde,        50,      /* ~ */
    805     XK_bracketleft,       33,      /* [ */
    806     XK_braceleft,         33,      /* { */
    807     XK_bracketright,      30,      /* ] */
    808     XK_braceright,        30,      /* } */
    809     XK_semicolon,         41,      /* ; */
    810     XK_colon,             41,      /* : */
    811     XK_apostrophe,        39,      /* ' */
    812     XK_quotedbl,          39,      /* " */
    813     XK_comma,             43,      /* , */
    814     XK_less,              43,      /* < */
    815     XK_period,            47,      /* . */
    816     XK_greater,           47,      /* > */
    817     XK_slash,             44,      /* / */
    818     XK_question,          44,      /* ? */
    819     XK_backslash,         42,      /* \ */
    820     XK_bar,               42,      /* | */
    821     /* OS X Sends this (END OF MEDIUM) for Shift-Tab (with US Keyboard) */
    822     0x0019,               48,      /* Tab */
    823     XK_space,             49,      /* Space */
    824 };
    825 
    826 static int SpecialKeyCodes[] = {
    827     /* "Special" keys */
    828     XK_Return,            36,      /* Return */
    829     XK_Delete,           117,      /* Delete */
    830     XK_Tab,               48,      /* Tab */
    831     XK_Escape,            53,      /* Esc */
    832     XK_Caps_Lock,         57,      /* Caps Lock */
    833     XK_Num_Lock,          71,      /* Num Lock */
    834     XK_Scroll_Lock,      107,      /* Scroll Lock */
    835     XK_Pause,            113,      /* Pause */
    836     XK_BackSpace,         51,      /* Backspace */
    837     XK_Insert,           114,      /* Insert */
    838 
    839     /* Cursor movement */
    840     XK_Up,               126,      /* Cursor Up */
    841     XK_Down,             125,      /* Cursor Down */
    842     XK_Left,             123,      /* Cursor Left */
    843     XK_Right,            124,      /* Cursor Right */
    844     XK_Page_Up,          116,      /* Page Up */
    845     XK_Page_Down,        121,      /* Page Down */
    846     XK_Home,             115,      /* Home */
    847     XK_End,              119,      /* End */
    848 
    849     /* Numeric keypad */
    850     XK_KP_0,              82,      /* KP 0 */
    851     XK_KP_1,              83,      /* KP 1 */
    852     XK_KP_2,              84,      /* KP 2 */
    853     XK_KP_3,              85,      /* KP 3 */
    854     XK_KP_4,              86,      /* KP 4 */
    855     XK_KP_5,              87,      /* KP 5 */
    856     XK_KP_6,              88,      /* KP 6 */
    857     XK_KP_7,              89,      /* KP 7 */
    858     XK_KP_8,              91,      /* KP 8 */
    859     XK_KP_9,              92,      /* KP 9 */
    860     XK_KP_Enter,          76,      /* KP Enter */
    861     XK_KP_Decimal,        65,      /* KP . */
    862     XK_KP_Add,            69,      /* KP + */
    863     XK_KP_Subtract,       78,      /* KP - */
    864     XK_KP_Multiply,       67,      /* KP * */
    865     XK_KP_Divide,         75,      /* KP / */
    866 
    867     /* Function keys */
    868     XK_F1,               122,      /* F1 */
    869     XK_F2,               120,      /* F2 */
    870     XK_F3,                99,      /* F3 */
    871     XK_F4,               118,      /* F4 */
    872     XK_F5,                96,      /* F5 */
    873     XK_F6,                97,      /* F6 */
    874     XK_F7,                98,      /* F7 */
    875     XK_F8,               100,      /* F8 */
    876     XK_F9,               101,      /* F9 */
    877     XK_F10,              109,      /* F10 */
    878     XK_F11,              103,      /* F11 */
    879     XK_F12,              111,      /* F12 */
    880 
    881     /* Modifier keys */
    882     XK_Alt_L,             55,      /* Alt Left (-> Command) */
    883     XK_Alt_R,             55,      /* Alt Right (-> Command) */
    884     XK_Shift_L,           56,      /* Shift Left */
    885     XK_Shift_R,           56,      /* Shift Right */
    886     XK_Meta_L,            58,      /* Option Left (-> Option) */
    887     XK_Meta_R,            58,      /* Option Right (-> Option) */
    888     XK_Super_L,           58,      /* Option Left (-> Option) */
    889     XK_Super_R,           58,      /* Option Right (-> Option) */
    890     XK_Control_L,         59,      /* Ctrl Left */
    891     XK_Control_R,         59,      /* Ctrl Right */
    892 };
    893 
    894 CGKeyCode keyTable[keyTableSize];
    895 unsigned char keyTableMods[keyTableSize];
    896 
    897 void macosxCG_init_key_table(void) {
    898 	static int init = 0;
    899 	int i;
    900 	if (init) {
    901 		return;
    902 	}
    903 	init = 1;
    904 
    905 	for (i=0; i < keyTableSize; i++) {
    906 		keyTable[i] = 0xFFFF;
    907 		keyTableMods[i] = 0;
    908 	}
    909 	for (i=0; i< (int) (sizeof(USKeyCodes) / sizeof(int)); i += 2) {
    910 		int j = USKeyCodes[i];
    911 		keyTable[(unsigned short) j] = (CGKeyCode) USKeyCodes[i+1];
    912 	}
    913 	for (i=0; i< (int) (sizeof(SpecialKeyCodes) / sizeof(int)); i += 2) {
    914 		int j = SpecialKeyCodes[i];
    915 		keyTable[(unsigned short) j] = (CGKeyCode) SpecialKeyCodes[i+1];
    916 	}
    917 }
    918 
    919 extern void init_key_table(void);
    920 extern int macosx_us_kbd;
    921 
    922 extern int debug_keyboard;
    923 
    924 void CGPostKeyboardEvent_wr(CGCharCode keyChar, CGKeyCode keyCode, int down) {
    925 	static int post_mode = -1, mcnt = 0;
    926 
    927 #if !X11VNC_MACOSX_NO_DEPRECATED_POSTEVENTS && !X11VNC_MACOSX_NO_DEPRECATED
    928 	if (post_mode < 0) {
    929 		post_mode = 1;
    930 		if (getenv("X11VNC_MACOSX_NO_DEPRECATED_POSTEVENTS") || getenv("X11VNC_MACOSX_NO_DEPRECATED")) {
    931 			post_mode = 0;
    932 		}
    933 	}
    934 
    935 	if (post_mode) {
    936 		if (mcnt++ < 10 || debug_keyboard) fprintf(stderr, "CGPostKeyboardEvent(keyChar=%d, keyCode=%d, down=%d)\n", keyChar, keyCode, down);
    937 		CGPostKeyboardEvent(keyChar, keyCode, down);
    938 	} else
    939 #endif
    940 	{
    941 		/* XXX 10.4 and later */
    942 #ifndef X11VNC_MACOSX_NO_CGEVENTCREATEKEYBOARDEVENT
    943 		CGEventRef event;
    944 		event = CGEventCreateKeyboardEvent(NULL, keyCode, down);
    945 		if (event != NULL) {
    946 			CGEventPost(kCGHIDEventTap, event);
    947 			CFRelease(event);
    948 		}
    949 #endif
    950 		if (mcnt++ < 10 || debug_keyboard) fprintf(stderr, "CGEventCreateKeyboardEvent(NULL, keyCode=%d, down=%d)\n", keyCode, down);
    951 	}
    952 }
    953 
    954 void macosxCG_keycode_inject(int down, int keycode) {
    955 	CGKeyCode keyCode = (CGKeyCode) keycode;
    956 	CGCharCode keyChar = 0;
    957 
    958 	if (debug_keyboard) fprintf(stderr, "macosxCG_keycode_inject(down=%d, keycode=%d)\n", down, keycode);
    959 
    960 	CGPostKeyboardEvent_wr(keyChar, keyCode, down);
    961 }
    962 
    963 void macosxCG_keysym_inject(int down, unsigned int keysym) {
    964 	CGKeyCode keyCode = keyTable[(unsigned short)keysym];
    965 	CGCharCode keyChar = 0;
    966 #if 0
    967 	int pressModsForKeys = FALSE;
    968 	UInt32 modsForKey = keyTableMods[keysym] << 8;
    969 #endif
    970 
    971 	init_key_table();
    972 
    973 	if (debug_keyboard) fprintf(stderr, "macosxCG_keysym_inject(down=%d, keysym=%d)\n", down, (int) keysym);
    974 
    975 	if (keysym < 0xFF && macosx_us_kbd) {
    976 		keyChar = (CGCharCode) keysym;
    977 		if (debug_keyboard) fprintf(stderr, "macosxCG_keysym_inject keyChar=>%d\n", (int) keyChar);
    978 	}
    979 	if (keyCode == 0xFFFF) {
    980 		return;
    981 	}
    982 	macosxCGP_undim();
    983 
    984 	CGPostKeyboardEvent_wr(keyChar, keyCode, down);
    985 }
    986 
    987 #endif	/* __APPLE__ */
    988 
    989 
    990