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