diff options
Diffstat (limited to 'x11vnc/macosxCG.c')
-rw-r--r-- | x11vnc/macosxCG.c | 508 |
1 files changed, 508 insertions, 0 deletions
diff --git a/x11vnc/macosxCG.c b/x11vnc/macosxCG.c new file mode 100644 index 0000000..4ecf2c2 --- /dev/null +++ b/x11vnc/macosxCG.c @@ -0,0 +1,508 @@ +/* -- macosxCG.c -- */ + +/* + * We need to keep this separate from nearly everything else, e.g. rfb.h + * and the other stuff, otherwise it does not work properly, mouse drags + * will not work!! + */ + +#if (defined(__MACH__) && defined(__APPLE__)) + +#include <ApplicationServices/ApplicationServices.h> +#include <Cocoa/Cocoa.h> +#include <Carbon/Carbon.h> + +void macosxCG_init(void); +void macosxCG_event_loop(void); +char *macosxCG_get_fb_addr(void); + +int macosxCG_CGDisplayPixelsWide(void); +int macosxCG_CGDisplayPixelsHigh(void); +int macosxCG_CGDisplayBitsPerPixel(void); +int macosxCG_CGDisplayBitsPerSample(void); +int macosxCG_CGDisplaySamplesPerPixel(void); +int macosxCG_CGDisplayBytesPerRow(void); + +void macosxCG_pointer_inject(int mask, int x, int y); +int macosxCG_get_cursor_pos(int *x, int *y); +int macosxCG_get_cursor(void); +void macosxCG_init_key_table(void); +void macosxCG_key_inject(int down, unsigned int keysym); + +CGDirectDisplayID displayID = NULL; + +extern int collect_macosx_damage(int x_in, int y_in, int w_in, int h_in, int call); + +static void macosxCG_callback(CGRectCount n, const CGRect *rects, void *dum) { + int i, db = 0; + if (db) fprintf(stderr, "macosx_callback: n=%d\n", (int) n); + for (i=0; i < n; i++) { + 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); + collect_macosx_damage( (int) rects[i].origin.x, (int) rects[i].origin.y, + (int) rects[i].size.width, (int) rects[i].size.height, 1); + } +} + +int dragum(void) { + int x =200, y = 150, dy = 10, i; + CGPoint loc; + + CGDirectDisplayID displayID2 = kCGDirectMainDisplay; + (void) GetMainDevice(); + + for (i=0; i< 50; i++) { + usleep(1000*100); + loc.x = x; + loc.y = y + i*dy; + CGPostMouseEvent(loc, TRUE, 1, TRUE); + } + CGPostMouseEvent(loc, TRUE, 1, FALSE); + usleep(4*1000*1000); + return 0; +} + +static int callback_set = 0; +extern int nofb; + +void macosxCG_refresh_callback_on(void) { + if (nofb) { + return; + } + + if (! callback_set) { + if (1) fprintf(stderr, "macosxCG_callback: register\n"); + CGRegisterScreenRefreshCallback(macosxCG_callback, NULL); + } + callback_set = 1; +} + +void macosxCG_refresh_callback_off(void) { + if (callback_set) { + if (1) fprintf(stderr, "macosxCG_callback: unregister\n"); + CGUnregisterScreenRefreshCallback(macosxCG_callback, NULL); + } + callback_set = 0; +} + +extern int macosx_noscreensaver; + +void macosxCG_init(void) { + if (displayID == NULL) { + fprintf(stderr, "macosxCG_init: initializing display.\n"); + //dragum(); + + displayID = kCGDirectMainDisplay; + (void) GetMainDevice(); + + CGSetLocalEventsSuppressionInterval(0.0); + CGSetLocalEventsFilterDuringSupressionState( + kCGEventFilterMaskPermitAllEvents, + kCGEventSupressionStateSupressionInterval); + CGSetLocalEventsFilterDuringSupressionState( + kCGEventFilterMaskPermitAllEvents, + kCGEventSupressionStateRemoteMouseDrag); + + macosxCGP_init_dimming(); + if (macosx_noscreensaver) { + macosxCGP_screensaver_timer_on(); + } + } +} + +void macosxCG_fini(void) { + macosxCGP_dim_shutdown(); + if (macosx_noscreensaver) { + macosxCGP_screensaver_timer_off(); + } + macosxCG_refresh_callback_off(); +} + +extern int dpy_x, dpy_y; +extern int client_count; +extern void do_new_fb(int); + +void macosxCG_event_loop(void) { + OSStatus rc; + rc = RunCurrentEventLoop(kEventDurationSecond/30); + if (client_count) { + macosxCG_refresh_callback_on(); + } else { + macosxCG_refresh_callback_off(); + } + if (dpy_x != (int) CGDisplayPixelsWide(displayID)) { + if (dpy_y != (int) CGDisplayPixelsHigh(displayID)) { + do_new_fb(1); + } + } +} + +char *macosxCG_get_fb_addr(void) { + macosxCG_init(); + return (char *) CGDisplayBaseAddress(displayID); +} + +int macosxCG_CGDisplayPixelsWide(void) { + return (int) CGDisplayPixelsWide(displayID); +} +int macosxCG_CGDisplayPixelsHigh(void) { + return (int) CGDisplayPixelsHigh(displayID); +} +int macosxCG_CGDisplayBitsPerPixel(void) { + return (int) CGDisplayBitsPerPixel(displayID); +} +int macosxCG_CGDisplayBitsPerSample(void) { + return (int) CGDisplayBitsPerSample(displayID); +} +int macosxCG_CGDisplaySamplesPerPixel(void) { + return (int) CGDisplaySamplesPerPixel(displayID); +} +int macosxCG_CGDisplayBytesPerRow(void) { + return (int) CGDisplayBytesPerRow(displayID);; +} + +typedef int CGSConnectionRef; +static CGSConnectionRef conn = 0; +extern CGError CGSNewConnection(void*, CGSConnectionRef*); +extern CGError CGSReleaseConnection(CGSConnectionRef); +extern CGError CGSGetGlobalCursorDataSize(CGSConnectionRef, int*); +extern CGError CGSGetGlobalCursorData(CGSConnectionRef, unsigned char*, + int*, int*, CGRect*, CGPoint*, int*, int*, int*); +extern CGError CGSGetCurrentCursorLocation(CGSConnectionRef, CGPoint*); +extern int CGSCurrentCursorSeed(void); +extern int CGSHardwareCursorActive(); + +static CGPoint current_cursor_pos(void) { + CGPoint pos; + pos.x = 0; + pos.y = 0; + if (! conn) { + if (CGSNewConnection(NULL, &conn) != kCGErrorSuccess) { + fprintf(stderr, "CGSNewConnection error\n"); + } + } + if (CGSGetCurrentCursorLocation(conn, &pos) != kCGErrorSuccess) { + fprintf(stderr, "CGSGetCurrentCursorLocation error\n"); + } + return pos; +} + +int macosxCG_get_cursor_pos(int *x, int *y) { + CGPoint pos = current_cursor_pos(); + *x = pos.x; + *y = pos.y; + return 1; +} + +extern int get_cursor_serial(int); +extern int store_cursor(int serial, unsigned long *data, int w, int h, int cbpp, int xhot, int yhot); + +int macosxCG_get_cursor(void) { + int last_idx = (int) get_cursor_serial(1); + int which = 1; + static CGPoint pos, lastpos; + static foo = 0; + CGError err; + int datasize, masksize, row_bytes, cdepth, comps, bpcomp; + CGRect rect; + CGPoint hot; + unsigned char *data; + int res, cursor_seed; + + if (last_idx) { + which = last_idx; + } + + pos = current_cursor_pos(); + if (cursor_seed == CGSCurrentCursorSeed()) { + return which; + } + if (! conn) { + if (CGSNewConnection(NULL, &conn) != kCGErrorSuccess) { + fprintf(stderr, "CGSNewConnection error\n"); + return which; + } + } + if (CGSGetGlobalCursorDataSize(conn, &datasize) != kCGErrorSuccess) { + fprintf(stderr, "CGSGetGlobalCursorDataSize error\n"); + return which; + } + + data = (unsigned char*) malloc(datasize); + + err = CGSGetGlobalCursorData(conn, data, &datasize, &row_bytes, + &rect, &hot, &cdepth, &comps, &bpcomp); + if (err != kCGErrorSuccess) { + fprintf(stderr, "CGSGetGlobalCursorData error\n"); + return which; + } + + if (cdepth == 24) { + cdepth = 32; + } + cursor_seed = CGSCurrentCursorSeed(); + + which = store_cursor(cursor_seed, (unsigned long*) data, + (int) rect.size.width, (int) rect.size.height, cdepth, (int) hot.x, (int) hot.y); + + free(data); + return(which); +} + +void macosxCG_pointer_inject(int mask, int x, int y) { + int swap23 = 1, rc; + int s1 = 0, s2 = 1, s3 = 2, s4 = 3, s5 = 4; + CGPoint loc; + int wheel_distance = 10; + static int cnt = 0; + + loc.x = x; + loc.y = y; + + if (swap23) { + s2 = 2; + s3 = 1; + } + + if ((cnt++ % 10) == 0) { + macosxCGP_undim(); + } + + if ((mask & (1 << s4))) { + CGPostScrollWheelEvent(1, wheel_distance); + } + if ((mask & (1 << s5))) { + CGPostScrollWheelEvent(1, -wheel_distance); + } + + CGPostMouseEvent(loc, TRUE, 3, + (mask & (1 << s1)) ? TRUE : FALSE, + (mask & (1 << s2)) ? TRUE : FALSE, + (mask & (1 << s3)) ? TRUE : FALSE + ); +} + +#define keyTableSize 0xFFFF + +#include <rfb/keysym.h> + +static int USKeyCodes[] = { + /* The alphabet */ + XK_A, 0, /* A */ + XK_B, 11, /* B */ + XK_C, 8, /* C */ + XK_D, 2, /* D */ + XK_E, 14, /* E */ + XK_F, 3, /* F */ + XK_G, 5, /* G */ + XK_H, 4, /* H */ + XK_I, 34, /* I */ + XK_J, 38, /* J */ + XK_K, 40, /* K */ + XK_L, 37, /* L */ + XK_M, 46, /* M */ + XK_N, 45, /* N */ + XK_O, 31, /* O */ + XK_P, 35, /* P */ + XK_Q, 12, /* Q */ + XK_R, 15, /* R */ + XK_S, 1, /* S */ + XK_T, 17, /* T */ + XK_U, 32, /* U */ + XK_V, 9, /* V */ + XK_W, 13, /* W */ + XK_X, 7, /* X */ + XK_Y, 16, /* Y */ + XK_Z, 6, /* Z */ + XK_a, 0, /* a */ + XK_b, 11, /* b */ + XK_c, 8, /* c */ + XK_d, 2, /* d */ + XK_e, 14, /* e */ + XK_f, 3, /* f */ + XK_g, 5, /* g */ + XK_h, 4, /* h */ + XK_i, 34, /* i */ + XK_j, 38, /* j */ + XK_k, 40, /* k */ + XK_l, 37, /* l */ + XK_m, 46, /* m */ + XK_n, 45, /* n */ + XK_o, 31, /* o */ + XK_p, 35, /* p */ + XK_q, 12, /* q */ + XK_r, 15, /* r */ + XK_s, 1, /* s */ + XK_t, 17, /* t */ + XK_u, 32, /* u */ + XK_v, 9, /* v */ + XK_w, 13, /* w */ + XK_x, 7, /* x */ + XK_y, 16, /* y */ + XK_z, 6, /* z */ + + /* Numbers */ + XK_0, 29, /* 0 */ + XK_1, 18, /* 1 */ + XK_2, 19, /* 2 */ + XK_3, 20, /* 3 */ + XK_4, 21, /* 4 */ + XK_5, 23, /* 5 */ + XK_6, 22, /* 6 */ + XK_7, 26, /* 7 */ + XK_8, 28, /* 8 */ + XK_9, 25, /* 9 */ + + /* Symbols */ + XK_exclam, 18, /* ! */ + XK_at, 19, /* @ */ + XK_numbersign, 20, /* # */ + XK_dollar, 21, /* $ */ + XK_percent, 23, /* % */ + XK_asciicircum, 22, /* ^ */ + XK_ampersand, 26, /* & */ + XK_asterisk, 28, /* * */ + XK_parenleft, 25, /* ( */ + XK_parenright, 29, /* ) */ + XK_minus, 27, /* - */ + XK_underscore, 27, /* _ */ + XK_equal, 24, /* = */ + XK_plus, 24, /* + */ + XK_grave, 50, /* ` */ /* XXX ? */ + XK_asciitilde, 50, /* ~ */ + XK_bracketleft, 33, /* [ */ + XK_braceleft, 33, /* { */ + XK_bracketright, 30, /* ] */ + XK_braceright, 30, /* } */ + XK_semicolon, 41, /* ; */ + XK_colon, 41, /* : */ + XK_apostrophe, 39, /* ' */ + XK_quotedbl, 39, /* " */ + XK_comma, 43, /* , */ + XK_less, 43, /* < */ + XK_period, 47, /* . */ + XK_greater, 47, /* > */ + XK_slash, 44, /* / */ + XK_question, 44, /* ? */ + XK_backslash, 42, /* \ */ + XK_bar, 42, /* | */ + // OS X Sends this (END OF MEDIUM) for Shift-Tab (with US Keyboard) + 0x0019, 48, /* Tab */ + XK_space, 49, /* Space */ +}; + +static int SpecialKeyCodes[] = { + /* "Special" keys */ + XK_Return, 36, /* Return */ + XK_Delete, 117, /* Delete */ + XK_Tab, 48, /* Tab */ + XK_Escape, 53, /* Esc */ + XK_Caps_Lock, 57, /* Caps Lock */ + XK_Num_Lock, 71, /* Num Lock */ + XK_Scroll_Lock, 107, /* Scroll Lock */ + XK_Pause, 113, /* Pause */ + XK_BackSpace, 51, /* Backspace */ + XK_Insert, 114, /* Insert */ + + /* Cursor movement */ + XK_Up, 126, /* Cursor Up */ + XK_Down, 125, /* Cursor Down */ + XK_Left, 123, /* Cursor Left */ + XK_Right, 124, /* Cursor Right */ + XK_Page_Up, 116, /* Page Up */ + XK_Page_Down, 121, /* Page Down */ + XK_Home, 115, /* Home */ + XK_End, 119, /* End */ + + /* Numeric keypad */ + XK_KP_0, 82, /* KP 0 */ + XK_KP_1, 83, /* KP 1 */ + XK_KP_2, 84, /* KP 2 */ + XK_KP_3, 85, /* KP 3 */ + XK_KP_4, 86, /* KP 4 */ + XK_KP_5, 87, /* KP 5 */ + XK_KP_6, 88, /* KP 6 */ + XK_KP_7, 89, /* KP 7 */ + XK_KP_8, 91, /* KP 8 */ + XK_KP_9, 92, /* KP 9 */ + XK_KP_Enter, 76, /* KP Enter */ + XK_KP_Decimal, 65, /* KP . */ + XK_KP_Add, 69, /* KP + */ + XK_KP_Subtract, 78, /* KP - */ + XK_KP_Multiply, 67, /* KP * */ + XK_KP_Divide, 75, /* KP / */ + + /* Function keys */ + XK_F1, 122, /* F1 */ + XK_F2, 120, /* F2 */ + XK_F3, 99, /* F3 */ + XK_F4, 118, /* F4 */ + XK_F5, 96, /* F5 */ + XK_F6, 97, /* F6 */ + XK_F7, 98, /* F7 */ + XK_F8, 100, /* F8 */ + XK_F9, 101, /* F9 */ + XK_F10, 109, /* F10 */ + XK_F11, 103, /* F11 */ + XK_F12, 111, /* F12 */ + + /* Modifier keys */ + XK_Alt_L, 55, /* Alt Left (-> Command) */ + XK_Alt_R, 55, /* Alt Right (-> Command) */ + XK_Shift_L, 56, /* Shift Left */ + XK_Shift_R, 56, /* Shift Right */ + XK_Meta_L, 58, /* Option Left (-> Option) */ + XK_Meta_R, 58, /* Option Right (-> Option) */ + XK_Super_L, 58, /* Option Left (-> Option) */ + XK_Super_R, 58, /* Option Right (-> Option) */ + XK_Control_L, 59, /* Ctrl Left */ + XK_Control_R, 59, /* Ctrl Right */ +}; + +CGKeyCode keyTable[keyTableSize]; +unsigned char keyTableMods[keyTableSize]; + +void macosxCG_init_key_table(void) { + static int init = 0; + int i; + if (init) { + return; + } + init = 1; + + for (i=0; i < keyTableSize; i++) { + keyTable[i] = 0xFFFF; + keyTableMods[i] = 0; + } + for (i=0; i< (sizeof(USKeyCodes) / sizeof(int)); i += 2) { + int j = USKeyCodes[i]; + keyTable[(unsigned short) j] = (CGKeyCode) USKeyCodes[i+1]; + } + for (i=0; i< (sizeof(SpecialKeyCodes) / sizeof(int)); i += 2) { + int j = SpecialKeyCodes[i]; + keyTable[(unsigned short) j] = (CGKeyCode) SpecialKeyCodes[i+1]; + } +} + +void macosxCG_key_inject(int down, unsigned int keysym) { + static int control = 0, alt = 0; + int pressModsForKeys = FALSE; + + CGKeyCode keyCode = keyTable[(unsigned short)keysym]; + CGCharCode keyChar = 0; + UInt32 modsForKey = keyTableMods[keysym] << 8; + + init_key_table(); + + if (keysym < 0xFF) { + keyChar = (CGCharCode) keysym; + } + if (keyCode == 0xFFFF) { + return; + } + macosxCGP_undim(); + CGPostKeyboardEvent(keyChar, keyCode, down); +} + +#endif /* __APPLE__ */ + + |