blob: 12041e0ad6a984ddf6bf52cb12259c66f0462874 [file] [log] [blame]
San Mehata430b2b2014-09-23 08:30:51 -07001/*
2 Copyright (C) 2002-2010 Karl J. Runge <runge@karlrunge.com>
3 All rights reserved.
4
5This file is part of x11vnc.
6
7x11vnc is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or (at
10your option) any later version.
11
12x11vnc is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with x11vnc; if not, write to the Free Software
19Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
20or see <http://www.gnu.org/licenses/>.
21
22In addition, as a special exception, Karl J. Runge
23gives permission to link the code of its release of x11vnc with the
24OpenSSL project's "OpenSSL" library (or with modified versions of it
25that use the same license as the "OpenSSL" library), and distribute
26the linked executables. You must obey the GNU General Public License
27in all respects for all of the code used other than "OpenSSL". If you
28modify this file, you may extend this exception to your version of the
29file, but you are not obligated to do so. If you do not wish to do
30so, 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
41void 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
49void macosxCG_init(void);
50void macosxCG_fini(void);
51void macosxCG_event_loop(void);
52char *macosxCG_get_fb_addr(void);
53
54int macosxCG_CGDisplayPixelsWide(void);
55int macosxCG_CGDisplayPixelsHigh(void);
56int macosxCG_CGDisplayBitsPerPixel(void);
57int macosxCG_CGDisplayBitsPerSample(void);
58int macosxCG_CGDisplaySamplesPerPixel(void);
59int macosxCG_CGDisplayBytesPerRow(void);
60
61void macosxCG_pointer_inject(int mask, int x, int y);
62int macosxCG_get_cursor_pos(int *x, int *y);
63int macosxCG_get_cursor(void);
64void macosxCG_init_key_table(void);
65void macosxCG_keysym_inject(int down, unsigned int keysym);
66void macosxCG_keycode_inject(int down, int keycode);
67
68CGDirectDisplayID displayID = 0;
69
70extern void macosx_log(char *);
71extern int collect_non_X_xdamage(int x_in, int y_in, int w_in, int h_in, int call);
72
73static 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
103X11VNC_MACOSX_NO_DEPRECATED_LOCALEVENTS
104X11VNC_MACOSX_NO_DEPRECATED_POSTEVENTS
105X11VNC_MACOSX_NO_DEPRECATED_FRAMEBUFFER
106X11VNC_MACOSX_NO_DEPRECATED
107
108#endif
109
110static int callback_set = 0;
111extern int nofb;
112
113void 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
125void 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
133extern int macosx_noscreensaver;
134extern int macosx_read_opengl;
135extern int macosx_read_rawfb;
136
137extern void macosxGCS_initpb(void);
138extern int macosxCGP_init_dimming(void);
139extern int macosxCGP_undim(void);
140extern int macosxCGP_dim_shutdown(void);
141extern void macosxCGP_screensaver_timer_off(void);
142extern void macosxCGP_screensaver_timer_on(void);
143extern void macosx_opengl_init(void);
144extern void macosx_opengl_fini(void);
145
146int x11vnc_macosx_no_deprecated_localevents = 0;
147int x11vnc_macosx_no_deprecated_postevents = 0;
148int x11vnc_macosx_no_deprecated_framebuffer = 0;
149
150void 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
218void 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
228extern int dpy_x, dpy_y, bpp, wdpy_x, wdpy_y;
229extern int client_count, nofb;
230extern void do_new_fb(int);
231extern int macosx_wait_for_switch, macosx_resize;
232
233extern void macosxGCS_poll_pb(void);
234#if 0
235extern void usleep(unsigned long usec);
236#else
237extern int usleep(useconds_t usec);
238#endif
239extern unsigned int sleep(unsigned int seconds);
240extern void clean_up_exit(int ret);
241
242void 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
305extern int macosx_no_rawfb;
306extern int macosx_read_opengl;
307extern int macosx_opengl_get_width();
308extern int macosx_opengl_get_height();
309extern int macosx_opengl_get_bpp();
310extern int macosx_opengl_get_bps();
311extern int macosx_opengl_get_spp();
312
313#if X11VNC_MACOSX_NO_DEPRECATED_FRAMEBUFFER || X11VNC_MACOSX_NO_DEPRECATED
314
315char *macosxCG_get_fb_addr(void) {
316 return NULL;
317}
318int macosxCG_CGDisplayPixelsWide(void) {
319 return macosx_opengl_get_width();
320}
321int macosxCG_CGDisplayPixelsHigh(void) {
322 return macosx_opengl_get_height();
323}
324int macosxCG_CGDisplayBitsPerPixel(void) {
325 return macosx_opengl_get_bpp();
326}
327int macosxCG_CGDisplayBitsPerSample(void) {
328 return macosx_opengl_get_bps();
329}
330int macosxCG_CGDisplaySamplesPerPixel(void) {
331 return macosx_opengl_get_spp();
332}
333int macosxCG_CGDisplayBytesPerRow(void) {
334 return macosx_opengl_get_width() * macosx_opengl_get_bpp() / 8;
335}
336
337#else
338
339char *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
355int 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}
361int 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}
367int 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}
373int 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}
379int 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}
385int 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
394typedef int CGSConnectionRef;
395static CGSConnectionRef conn = 0;
396extern CGError CGSNewConnection(void*, CGSConnectionRef*);
397extern CGError CGSReleaseConnection(CGSConnectionRef);
398extern CGError CGSGetGlobalCursorDataSize(CGSConnectionRef, int*);
399extern CGError CGSGetGlobalCursorData(CGSConnectionRef, unsigned char*,
400 int*, int*, CGRect*, CGPoint*, int*, int*, int*);
401extern CGError CGSGetCurrentCursorLocation(CGSConnectionRef, CGPoint*);
402extern int CGSCurrentCursorSeed(void);
403extern int CGSHardwareCursorActive();
404
405static unsigned int last_local_button_mask = 0;
406static unsigned int last_local_mod_mask = 0;
407static int last_local_x = 0;
408static int last_local_y = 0;
409
410extern unsigned int display_button_mask;
411extern unsigned int display_mod_mask;
412extern int got_local_pointer_input;
413extern time_t last_local_input;
414
415static 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
452int 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
459extern int get_cursor_serial(int);
460extern int store_cursor(int serial, unsigned long *data, int w, int h, int cbpp, int xhot, int yhot);
461
462int 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
544extern int macosx_mouse_wheel_speed;
545extern int macosx_swap23;
546extern int off_x, coff_x, off_y, coff_y;
547
548extern int debug_pointer;
549
550static 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
580static 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
671void 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
721static 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
826static 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
894CGKeyCode keyTable[keyTableSize];
895unsigned char keyTableMods[keyTableSize];
896
897void 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
919extern void init_key_table(void);
920extern int macosx_us_kbd;
921
922extern int debug_keyboard;
923
924void 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
954void 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
963void 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