4
* We need to keep this separate from nearly everything else, e.g. rfb.h
5
* and the other stuff, otherwise it does not work properly, mouse drags
9
void macosxCG_dummy(void) {}
11
#if (defined(__MACH__) && defined(__APPLE__))
13
#include <ApplicationServices/ApplicationServices.h>
14
#include <Cocoa/Cocoa.h>
15
#include <Carbon/Carbon.h>
17
void macosxCG_init(void);
18
void macosxCG_fini(void);
19
void macosxCG_event_loop(void);
20
char *macosxCG_get_fb_addr(void);
22
int macosxCG_CGDisplayPixelsWide(void);
23
int macosxCG_CGDisplayPixelsHigh(void);
24
int macosxCG_CGDisplayBitsPerPixel(void);
25
int macosxCG_CGDisplayBitsPerSample(void);
26
int macosxCG_CGDisplaySamplesPerPixel(void);
27
int macosxCG_CGDisplayBytesPerRow(void);
29
void macosxCG_pointer_inject(int mask, int x, int y);
30
int macosxCG_get_cursor_pos(int *x, int *y);
31
int macosxCG_get_cursor(void);
32
void macosxCG_init_key_table(void);
33
void macosxCG_key_inject(int down, unsigned int keysym);
35
CGDirectDisplayID displayID = 0;
37
extern void macosx_log(char *);
38
extern int collect_non_X_xdamage(int x_in, int y_in, int w_in, int h_in, int call);
40
static void macosxCG_callback(CGRectCount n, const CGRect *rects, void *dum) {
42
if (db) fprintf(stderr, "macosx_callback: n=%d\n", (int) n);
44
for (i=0; i < (int) n; i++) {
45
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);
46
collect_non_X_xdamage( (int) rects[i].origin.x, (int) rects[i].origin.y,
47
(int) rects[i].size.width, (int) rects[i].size.height, 1);
53
int x =200, y = 150, dy = 10, i;
56
CGDirectDisplayID displayID2 = kCGDirectMainDisplay;
57
(void) GetMainDevice();
59
for (i=0; i< 50; i++) {
63
CGPostMouseEvent(loc, TRUE, 1, TRUE);
65
CGPostMouseEvent(loc, TRUE, 1, FALSE);
71
static int callback_set = 0;
74
void macosxCG_refresh_callback_on(void) {
80
if (1) macosx_log("macosxCG_callback: register\n");
81
CGRegisterScreenRefreshCallback(macosxCG_callback, NULL);
86
void macosxCG_refresh_callback_off(void) {
88
if (1) macosx_log("macosxCG_callback: unregister\n");
89
CGUnregisterScreenRefreshCallback(macosxCG_callback, NULL);
94
extern int macosx_noscreensaver;
95
extern void macosxGCS_initpb(void);
96
extern int macosxCGP_init_dimming(void);
97
extern int macosxCGP_undim(void);
98
extern int macosxCGP_dim_shutdown(void);
99
extern void macosxCGP_screensaver_timer_off(void);
100
extern void macosxCGP_screensaver_timer_on(void);
102
void macosxCG_init(void) {
103
if (displayID == 0) {
104
macosx_log("macosxCG_init: initializing display.\n");
109
displayID = kCGDirectMainDisplay;
110
(void) GetMainDevice();
112
CGSetLocalEventsSuppressionInterval(0.0);
113
CGSetLocalEventsFilterDuringSupressionState(
114
kCGEventFilterMaskPermitAllEvents,
115
kCGEventSupressionStateSupressionInterval);
116
CGSetLocalEventsFilterDuringSupressionState(
117
kCGEventFilterMaskPermitAllEvents,
118
kCGEventSupressionStateRemoteMouseDrag);
120
macosxCGP_init_dimming();
121
if (macosx_noscreensaver) {
122
macosxCGP_screensaver_timer_on();
128
void macosxCG_fini(void) {
129
macosxCGP_dim_shutdown();
130
if (macosx_noscreensaver) {
131
macosxCGP_screensaver_timer_off();
133
macosxCG_refresh_callback_off();
136
extern int dpy_x, dpy_y, bpp, wdpy_x, wdpy_y;
137
extern int client_count, nofb;
138
extern void do_new_fb(int);
139
extern int macosx_wait_for_switch, macosx_resize;
141
extern void macosxGCS_poll_pb(void);
143
extern void usleep(unsigned long usec);
145
extern int usleep(useconds_t usec);
147
extern unsigned int sleep(unsigned int seconds);
148
extern void clean_up_exit (int ret);
150
void macosxCG_event_loop(void) {
159
rc = RunCurrentEventLoop(kEventDurationSecond/30);
162
macosxCG_refresh_callback_on();
164
macosxCG_refresh_callback_off();
167
nbpp = macosxCG_CGDisplayBitsPerPixel();
170
if (nbpp > 0 && nbpp != bpp) {
174
} else if (wdpy_x != (int) CGDisplayPixelsWide(displayID)) {
175
if (wdpy_y != (int) CGDisplayPixelsHigh(displayID)) {
176
if (macosx_wait_for_switch) {
179
if(CGDisplayPixelsWide(displayID) > 0) {
180
if(CGDisplayPixelsHigh(displayID) > 0) {
185
if ((cnt++ % 120) == 0) {
186
macosx_log("waiting for user to "
191
if (wdpy_x == (int) CGDisplayPixelsWide(displayID)) {
192
if (wdpy_y == (int) CGDisplayPixelsHigh(displayID)) {
193
macosx_log("we're back...\n");
205
char *macosxCG_get_fb_addr(void) {
207
return (char *) CGDisplayBaseAddress(displayID);
210
int macosxCG_CGDisplayPixelsWide(void) {
211
return (int) CGDisplayPixelsWide(displayID);
213
int macosxCG_CGDisplayPixelsHigh(void) {
214
return (int) CGDisplayPixelsHigh(displayID);
216
int macosxCG_CGDisplayBitsPerPixel(void) {
217
return (int) CGDisplayBitsPerPixel(displayID);
219
int macosxCG_CGDisplayBitsPerSample(void) {
220
return (int) CGDisplayBitsPerSample(displayID);
222
int macosxCG_CGDisplaySamplesPerPixel(void) {
223
return (int) CGDisplaySamplesPerPixel(displayID);
225
int macosxCG_CGDisplayBytesPerRow(void) {
226
return (int) CGDisplayBytesPerRow(displayID);;
229
typedef int CGSConnectionRef;
230
static CGSConnectionRef conn = 0;
231
extern CGError CGSNewConnection(void*, CGSConnectionRef*);
232
extern CGError CGSReleaseConnection(CGSConnectionRef);
233
extern CGError CGSGetGlobalCursorDataSize(CGSConnectionRef, int*);
234
extern CGError CGSGetGlobalCursorData(CGSConnectionRef, unsigned char*,
235
int*, int*, CGRect*, CGPoint*, int*, int*, int*);
236
extern CGError CGSGetCurrentCursorLocation(CGSConnectionRef, CGPoint*);
237
extern int CGSCurrentCursorSeed(void);
238
extern int CGSHardwareCursorActive();
240
static unsigned int last_local_button_mask = 0;
241
static unsigned int last_local_mod_mask = 0;
242
static int last_local_x = 0;
243
static int last_local_y = 0;
245
extern unsigned int display_button_mask;
246
extern unsigned int display_mod_mask;
247
extern int got_local_pointer_input;
248
extern time_t last_local_input;
250
static CGPoint current_cursor_pos(void) {
255
if (CGSNewConnection(NULL, &conn) != kCGErrorSuccess) {
256
macosx_log("CGSNewConnection error.\n");
257
if (!dpy_x || !dpy_y || !wdpy_x || !wdpy_y) {
262
if (CGSGetCurrentCursorLocation(conn, &pos) != kCGErrorSuccess) {
263
macosx_log("CGSGetCurrentCursorLocation error\n");
266
display_button_mask = GetCurrentButtonState();
269
display_mod_mask = GetCurrentKeyModifiers();
272
if (last_local_button_mask != display_button_mask) {
273
got_local_pointer_input++;
274
last_local_input = time(NULL);
275
} else if (pos.x != last_local_x || pos.y != last_local_y) {
276
got_local_pointer_input++;
277
last_local_input = time(NULL);
279
last_local_button_mask = display_button_mask;
280
last_local_mod_mask = display_mod_mask;
281
last_local_x = pos.x;
282
last_local_y = pos.y;
287
int macosxCG_get_cursor_pos(int *x, int *y) {
288
CGPoint pos = current_cursor_pos();
294
extern int get_cursor_serial(int);
295
extern int store_cursor(int serial, unsigned long *data, int w, int h, int cbpp, int xhot, int yhot);
297
int macosxCG_get_cursor(void) {
298
int last_idx = (int) get_cursor_serial(1);
301
int datasize, row_bytes, cdepth, comps, bpcomp;
306
static int last_cursor_seed = -1;
307
static time_t last_fetch = 0;
308
time_t now = time(NULL);
315
if (CGSNewConnection(NULL, &conn) != kCGErrorSuccess) {
316
macosx_log("CGSNewConnection error.\n");
317
if (!dpy_x || !dpy_y || !wdpy_x || !wdpy_y) {
324
cursor_seed = CGSCurrentCursorSeed();
325
if (last_idx && cursor_seed == last_cursor_seed) {
326
if (now < last_fetch + 2) {
330
last_cursor_seed = cursor_seed;
333
if (CGSGetGlobalCursorDataSize(conn, &datasize) != kCGErrorSuccess) {
334
macosx_log("CGSGetGlobalCursorDataSize error\n");
338
data = (unsigned char*) malloc(datasize);
340
err = CGSGetGlobalCursorData(conn, data, &datasize, &row_bytes,
341
&rect, &hot, &cdepth, &comps, &bpcomp);
342
if (err != kCGErrorSuccess) {
343
macosx_log("CGSGetGlobalCursorData error\n");
351
which = store_cursor(cursor_seed, (unsigned long*) data,
352
(int) rect.size.width, (int) rect.size.height, cdepth, (int) hot.x, (int) hot.y);
358
extern int macosx_mouse_wheel_speed;
359
extern int macosx_swap23;
360
extern int off_x, coff_x, off_y, coff_y;
362
void macosxCG_pointer_inject(int mask, int x, int y) {
363
int swap23 = macosx_swap23;
364
int s1 = 0, s2 = 1, s3 = 2, s4 = 3, s5 = 4;
366
int wheel_distance = macosx_mouse_wheel_speed;
374
loc.x = x + off_x + coff_x;
375
loc.y = y + off_y + coff_y;
377
if ((cnt++ % 10) == 0) {
381
if ((mask & (1 << s4))) {
382
CGPostScrollWheelEvent(1, wheel_distance);
384
if ((mask & (1 << s5))) {
385
CGPostScrollWheelEvent(1, -wheel_distance);
388
CGPostMouseEvent(loc, TRUE, 3,
389
(mask & (1 << s1)) ? TRUE : FALSE,
390
(mask & (1 << s2)) ? TRUE : FALSE,
391
(mask & (1 << s3)) ? TRUE : FALSE
395
#define keyTableSize 0xFFFF
397
#include <rfb/keysym.h>
399
static int USKeyCodes[] = {
467
XK_exclam, 18, /* ! */
469
XK_numbersign, 20, /* # */
470
XK_dollar, 21, /* $ */
471
XK_percent, 23, /* % */
472
XK_asciicircum, 22, /* ^ */
473
XK_ampersand, 26, /* & */
474
XK_asterisk, 28, /* * */
475
XK_parenleft, 25, /* ( */
476
XK_parenright, 29, /* ) */
477
XK_minus, 27, /* - */
478
XK_underscore, 27, /* _ */
479
XK_equal, 24, /* = */
481
XK_grave, 50, /* ` */ /* XXX ? */
482
XK_asciitilde, 50, /* ~ */
483
XK_bracketleft, 33, /* [ */
484
XK_braceleft, 33, /* { */
485
XK_bracketright, 30, /* ] */
486
XK_braceright, 30, /* } */
487
XK_semicolon, 41, /* ; */
488
XK_colon, 41, /* : */
489
XK_apostrophe, 39, /* ' */
490
XK_quotedbl, 39, /* " */
491
XK_comma, 43, /* , */
493
XK_period, 47, /* . */
494
XK_greater, 47, /* > */
495
XK_slash, 44, /* / */
496
XK_question, 44, /* ? */
497
XK_backslash, 42, /* \ */
499
/* OS X Sends this (END OF MEDIUM) for Shift-Tab (with US Keyboard) */
500
0x0019, 48, /* Tab */
501
XK_space, 49, /* Space */
504
static int SpecialKeyCodes[] = {
506
XK_Return, 36, /* Return */
507
XK_Delete, 117, /* Delete */
508
XK_Tab, 48, /* Tab */
509
XK_Escape, 53, /* Esc */
510
XK_Caps_Lock, 57, /* Caps Lock */
511
XK_Num_Lock, 71, /* Num Lock */
512
XK_Scroll_Lock, 107, /* Scroll Lock */
513
XK_Pause, 113, /* Pause */
514
XK_BackSpace, 51, /* Backspace */
515
XK_Insert, 114, /* Insert */
517
/* Cursor movement */
518
XK_Up, 126, /* Cursor Up */
519
XK_Down, 125, /* Cursor Down */
520
XK_Left, 123, /* Cursor Left */
521
XK_Right, 124, /* Cursor Right */
522
XK_Page_Up, 116, /* Page Up */
523
XK_Page_Down, 121, /* Page Down */
524
XK_Home, 115, /* Home */
525
XK_End, 119, /* End */
528
XK_KP_0, 82, /* KP 0 */
529
XK_KP_1, 83, /* KP 1 */
530
XK_KP_2, 84, /* KP 2 */
531
XK_KP_3, 85, /* KP 3 */
532
XK_KP_4, 86, /* KP 4 */
533
XK_KP_5, 87, /* KP 5 */
534
XK_KP_6, 88, /* KP 6 */
535
XK_KP_7, 89, /* KP 7 */
536
XK_KP_8, 91, /* KP 8 */
537
XK_KP_9, 92, /* KP 9 */
538
XK_KP_Enter, 76, /* KP Enter */
539
XK_KP_Decimal, 65, /* KP . */
540
XK_KP_Add, 69, /* KP + */
541
XK_KP_Subtract, 78, /* KP - */
542
XK_KP_Multiply, 67, /* KP * */
543
XK_KP_Divide, 75, /* KP / */
555
XK_F10, 109, /* F10 */
556
XK_F11, 103, /* F11 */
557
XK_F12, 111, /* F12 */
560
XK_Alt_L, 55, /* Alt Left (-> Command) */
561
XK_Alt_R, 55, /* Alt Right (-> Command) */
562
XK_Shift_L, 56, /* Shift Left */
563
XK_Shift_R, 56, /* Shift Right */
564
XK_Meta_L, 58, /* Option Left (-> Option) */
565
XK_Meta_R, 58, /* Option Right (-> Option) */
566
XK_Super_L, 58, /* Option Left (-> Option) */
567
XK_Super_R, 58, /* Option Right (-> Option) */
568
XK_Control_L, 59, /* Ctrl Left */
569
XK_Control_R, 59, /* Ctrl Right */
572
CGKeyCode keyTable[keyTableSize];
573
unsigned char keyTableMods[keyTableSize];
575
void macosxCG_init_key_table(void) {
583
for (i=0; i < keyTableSize; i++) {
584
keyTable[i] = 0xFFFF;
587
for (i=0; i< (int) (sizeof(USKeyCodes) / sizeof(int)); i += 2) {
588
int j = USKeyCodes[i];
589
keyTable[(unsigned short) j] = (CGKeyCode) USKeyCodes[i+1];
591
for (i=0; i< (int) (sizeof(SpecialKeyCodes) / sizeof(int)); i += 2) {
592
int j = SpecialKeyCodes[i];
593
keyTable[(unsigned short) j] = (CGKeyCode) SpecialKeyCodes[i+1];
597
extern void init_key_table(void);
599
void macosxCG_key_inject(int down, unsigned int keysym) {
600
CGKeyCode keyCode = keyTable[(unsigned short)keysym];
601
CGCharCode keyChar = 0;
603
int pressModsForKeys = FALSE;
604
UInt32 modsForKey = keyTableMods[keysym] << 8;
610
keyChar = (CGCharCode) keysym;
612
if (keyCode == 0xFFFF) {
616
CGPostKeyboardEvent(keyChar, keyCode, down);
619
#endif /* __APPLE__ */