3
#include "rfb/rfbconfig.h"
4
#if (defined(__MACH__) && defined(__APPLE__) && defined(LIBVNCSERVER_HAVE_MACOSX_NATIVE_DISPLAY))
19
#include "allowed_input_t.h"
22
#include "connections.h"
24
#include "macosxCGP.h"
25
#include "macosxCGS.h"
27
void macosx_log(char *);
28
char *macosx_console_guess(char *str, int *fd);
29
void macosx_key_command(rfbBool down, rfbKeySym keysym, rfbClientPtr client);
30
void macosx_pointer_command(int mask, int x, int y, rfbClientPtr client);
31
char *macosx_get_fb_addr(void);
32
int macosx_get_cursor(void);
33
int macosx_get_cursor_pos(int *, int *);
34
void macosx_send_sel(char *, int);
35
void macosx_set_sel(char *, int);
36
int macosx_valid_window(Window, XWindowAttributes*);
38
Status macosx_xquerytree(Window w, Window *root_return, Window *parent_return,
39
Window **children_return, unsigned int *nchildren_return);
40
int macosx_get_wm_frame_pos(int *px, int *py, int *x, int *y, int *w, int *h,
41
Window *frame, Window *win);
43
void macosx_add_mapnotify(Window win, int level, int map);
44
void macosx_add_create(Window win, int level);
45
void macosx_add_destroy(Window win, int level);
46
void macosx_add_visnotify(Window win, int level, int obscured);
47
int macosx_checkevent(XEvent *ev);
49
void macosx_log(char *str) {
55
void macosx_event_loop(void) {
58
char *macosx_console_guess(char *str, int *fd) {
62
void macosx_key_command(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
63
if (!down || !keysym || !client) {}
66
void macosx_pointer_command(int mask, int x, int y, rfbClientPtr client) {
67
if (!mask || !x || !y || !client) {}
70
char *macosx_get_fb_addr(void) {
73
int macosx_get_cursor(void) {
76
int macosx_get_cursor_pos(int *x, int *y) {
80
void macosx_send_sel(char * str, int len) {
84
void macosx_set_sel(char * str, int len) {
88
int macosx_valid_window(Window w, XWindowAttributes* a) {
92
Status macosx_xquerytree(Window w, Window *root_return, Window *parent_return,
93
Window **children_return, unsigned int *nchildren_return) {
94
if (!w || !root_return || !parent_return || !children_return || !nchildren_return) {}
97
void macosx_add_mapnotify(Window win, int level, int map) {
98
if (!win || !level || !map) {}
101
void macosx_add_create(Window win, int level) {
102
if (!win || !level) {}
105
void macosx_add_destroy(Window win, int level) {
106
if (!win || !level) {}
109
void macosx_add_visnotify(Window win, int level, int obscured) {
110
if (!win || !level || !obscured) {}
114
int macosx_checkevent(XEvent *ev) {
120
int dragum(void) {return 1;}
124
void macosx_event_loop(void) {
125
macosxCG_event_loop();
128
char *macosx_get_fb_addr(void) {
130
return macosxCG_get_fb_addr();
133
char *macosx_console_guess(char *str, int *fd) {
134
char *q, *in = strdup(str);
135
char *atparms = NULL, *file = NULL;
139
if (strstr(in, "console") != in) {
140
rfbLog("console_guess: unrecognized console/fb format: %s\n", str);
147
q = strrchr(in, '@');
149
atparms = strdup(q+1);
152
q = strrchr(in, ':');
157
if (! file || file[0] == '\0') {
158
file = strdup("/dev/null");
160
rfbLog("console_guess: file is %s\n", file);
162
if (! pipeinput_str) {
163
pipeinput_str = strdup("MACOSX");
164
initialize_pipeinput();
168
int w, h, b, bps, dep;
169
unsigned long rm = 0, gm = 0, bm = 0;
171
w = macosxCG_CGDisplayPixelsWide();
172
h = macosxCG_CGDisplayPixelsHigh();
173
b = macosxCG_CGDisplayBitsPerPixel();
175
bps = macosxCG_CGDisplayBitsPerSample();
176
dep = macosxCG_CGDisplaySamplesPerPixel() * bps;
185
if (b == 8 && rm == 0xff && gm == 0xff && bm == 0xff) {
186
/* I don't believe it... */
192
/* @66666x66666x32:0xffffffff:... */
193
atparms = (char *) malloc(200);
194
sprintf(atparms, "%dx%dx%d:%lx/%lx/%lx",
195
w, h, b, rm, gm, bm);
199
if (sscanf(atparms, "%dx%dx%d", &gw, &gh, &gb) == 3) {
206
rfbLog("console_guess: could not get @ parameters.\n");
210
q = (char *) malloc(strlen("map:macosx:") + strlen(file) + 1 + strlen(atparms) + 1);
211
sprintf(q, "map:macosx:%s@%s", file, atparms);
215
Window macosx_click_frame = None;
217
void macosx_pointer_command(int mask, int x, int y, rfbClientPtr client) {
218
allowed_input_t input;
219
static int last_mask = 0;
222
if (0) fprintf(stderr, "macosx_pointer_command: %d %d - %d\n", x, y, mask);
232
get_allowed_input(client, &input);
234
if (! input.motion || ! input.button) {
235
/* XXX fix me with last_x, last_y, etc. */
242
last_pointer_client = client;
243
last_pointer_time = time(NULL);
245
if (last_mask != mask) {
246
if (0) fprintf(stderr, "about to inject mask change %d -> %d: %.4f\n", last_mask, mask, dnowx());
248
int px, py, x, y, w, h;
249
macosx_click_frame = None;
250
if (!macosx_get_wm_frame_pos(&px, &py, &x, &y, &w, &h, &macosx_click_frame, NULL)) {
251
macosx_click_frame = None;
256
macosxCG_pointer_inject(mask, x, y);
258
if (cursor_x != x || cursor_y != y) {
259
last_pointer_motion_time = dnow();
265
if (last_mask != mask) {
266
last_pointer_click_time = dnow();
270
if (0) fprintf(stderr, "about to get all windows: %.4f\n", dnowx());
271
for (i=0; i < 2; i++) {
272
macosxCGS_get_all_windows();
273
fprintf(stderr, "!");
274
if (macosx_checkevent(NULL)) {
278
if (0) fprintf(stderr, "\ndone: %.4f\n", dnowx());
283
/* record the x, y position for the rfb screen as well. */
284
cursor_position(x, y);
286
/* change the cursor shape if necessary */
287
rc = set_cursor(x, y, get_which_cursor());
288
cursor_changes += rc;
290
last_event = last_input = last_pointer_input = time(NULL);
293
void init_key_table(void) {
294
macosxCG_init_key_table();
297
void macosx_key_command(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
298
allowed_input_t input;
299
if (debug_keyboard) fprintf(stderr, "macosx_key_command: %d %s\n", (int) keysym, down ? "down" : "up");
304
get_allowed_input(client, &input);
305
if (! input.keystroke) {
310
macosxCG_key_inject((int) down, (unsigned int) keysym);
313
extern void macosxGCS_poll_pb(void);
315
int macosx_get_cursor_pos(int *x, int *y) {
316
macosxCG_get_cursor_pos(x, y);
318
/* good time to poll the pasteboard */
324
static char *cuttext = NULL;
325
static int cutlen = 0;
327
void macosx_send_sel(char *str, int len) {
328
if (screen && all_clients_initialized()) {
334
if (!memcmp(str, cuttext, (size_t) n)) {
335
/* the same text we set pasteboard to ... */
340
rfbLog("macosx_send_sel: %d\n", len);
342
rfbSendServerCutText(screen, str, len);
346
void macosx_set_sel(char *str, int len) {
347
if (screen && all_clients_initialized()) {
353
cuttext = (char *) calloc(cutlen, 1);
355
memcpy(cuttext, str, (size_t) len);
358
rfbLog("macosx_set_sel: %d\n", len);
360
macosxGCS_set_pasteboard(str, len);
364
int macosx_get_cursor(void) {
365
return macosxCG_get_cursor();
368
typedef struct evdat {
376
#define MAX_EVENTS 1024
377
evdat_t mac_events[MAX_EVENTS];
378
int mac_events_ptr = 0;
379
int mac_events_last = 0;
381
void macosx_add_mapnotify(Window win, int level, int map) {
382
int i = mac_events_last++;
383
mac_events[i].win = win;
384
mac_events[i].level = level;
387
mac_events[i].type = MapNotify;
389
mac_events[i].type = UnmapNotify;
391
mac_events[i].map = map;
392
mac_events[i].vis = -1;
394
mac_events_last = mac_events_last % MAX_EVENTS;
399
void macosx_add_create(Window win, int level) {
400
int i = mac_events_last++;
401
mac_events[i].win = win;
402
mac_events[i].level = level;
404
mac_events[i].type = CreateNotify;
405
mac_events[i].map = -1;
406
mac_events[i].vis = -1;
408
mac_events_last = mac_events_last % MAX_EVENTS;
413
void macosx_add_destroy(Window win, int level) {
414
int i = mac_events_last++;
415
mac_events[i].win = win;
416
mac_events[i].level = level;
418
mac_events[i].type = DestroyNotify;
419
mac_events[i].map = -1;
420
mac_events[i].vis = -1;
422
mac_events_last = mac_events_last % MAX_EVENTS;
427
void macosx_add_visnotify(Window win, int level, int obscured) {
428
int i = mac_events_last++;
429
mac_events[i].win = win;
430
mac_events[i].level = level;
432
mac_events[i].type = VisibilityNotify;
433
mac_events[i].map = -1;
435
mac_events[i].vis = 1;
437
mac_events[i].vis = VisibilityUnobscured;
438
} else if (obscured == 1) {
439
mac_events[i].vis = VisibilityPartiallyObscured;
440
} else if (obscured == 2) {
441
mac_events[i].vis = VisibilityFullyObscured; /* NI */
444
mac_events_last = mac_events_last % MAX_EVENTS;
449
int macosx_checkevent(XEvent *ev) {
450
int i = mac_events_ptr;
452
if (mac_events_ptr == mac_events_last) {
456
return mac_events[i].type;
459
ev->xany.window = mac_events[i].win;
461
if (mac_events[i].type == CreateNotify) {
462
ev->type = CreateNotify;
463
ev->xany.window = rootwin;
464
ev->xcreatewindow.window = mac_events[i].win;
465
} else if (mac_events[i].type == DestroyNotify) {
466
ev->type = DestroyNotify;
467
ev->xdestroywindow.window = mac_events[i].win;
468
} else if (mac_events[i].type == VisibilityNotify) {
469
ev->type = VisibilityNotify;
470
ev->xvisibility.state = mac_events[i].vis;
471
} else if (mac_events[i].type == MapNotify) {
472
ev->type = MapNotify;
473
} else if (mac_events[i].type == UnmapNotify) {
474
ev->type = UnmapNotify;
476
fprintf(stderr, "unknown macosx_checkevent: %d\n", mac_events[i].type);
479
mac_events_ptr = mac_events_ptr % MAX_EVENTS;
481
return mac_events[i].type;
484
typedef struct windat {
494
extern int macwinmax;
495
extern windat_t macwins[];
497
int macosx_get_wm_frame_pos(int *px, int *py, int *x, int *y, int *w, int *h,
498
Window *frame, Window *win) {
499
static int last_idx = -1;
502
macosxCGS_get_all_windows();
503
macosxCG_get_cursor_pos(px, py);
505
for (k = 0; k<macwinmax; k++) {
506
if (! macwins[k].mapped) {
510
x2 = macwins[k].x + macwins[k].width;
512
y2 = macwins[k].y + macwins[k].height;
513
if (debug_wireframe) fprintf(stderr, "%d/%d: %d %d %d - %d %d %d\n", k, macwins[k].win, x1, *px, x2, y1, *py, y2);
514
if (x1 <= *px && *px < x2) {
515
if (y1 <= *py && *py < y2) {
527
*w = macwins[idx].width;
528
*h = macwins[idx].height;
529
*frame = (Window) macwins[idx].win;
539
int macosx_valid_window(Window w, XWindowAttributes* a) {
540
static int last_idx = -1;
544
if (last_idx >= 0 && last_idx < macwinmax) {
545
if (macwins[last_idx].win == win) {
551
idx = macosxCGS_get_qlook(w);
552
if (idx >= 0 && idx < macwinmax) {
553
if (macwins[idx].win != win) {
562
for (i = 0; i<macwinmax; i++) {
565
if (last_idx >= 0 && last_idx < macwinmax) {
572
if (macwins[k].win == win) {
582
a->x = macwins[idx].x;
583
a->y = macwins[idx].y;
584
a->width = macwins[idx].width;
585
a->height = macwins[idx].height;
588
a->backing_store = 0;
589
if (macwins[idx].mapped) {
590
a->map_state = IsViewable;
592
a->map_state = IsUnmapped;
601
static Window cret[QTMAX];
603
extern int CGS_levelmax;
604
extern int CGS_levels[];
606
Status macosx_xquerytree(Window w, Window *root_return, Window *parent_return,
607
Window **children_return, unsigned int *nchildren_return) {
611
*root_return = (Window) 0;
612
*parent_return = (Window) 0;
615
macosxCGS_get_all_windows();
618
for (k = CGS_levelmax - 1; k >= 0; k--) {
619
for (i = macwinmax - 1; i >= 0; i--) {
620
if (n >= QTMAX) break;
621
if (macwins[i].level == CGS_levels[k]) {
622
if (0) fprintf(stderr, "k=%d i=%d n=%d\n", k, i, n);
623
cret[n++] = (Window) macwins[i].win;
627
*children_return = cret;
628
*nchildren_return = (unsigned int) macwinmax;
633
int macosx_check_offscreen(int win) {
637
int i = macosxCGS_find_index(win);
645
x2 = macwins[i].x + macwins[i].width;
646
y2 = macwins[i].y + macwins[i].height;
648
r0 = sraRgnCreateRect(0, 0, dpy_x, dpy_y);
649
r1 = sraRgnCreateRect(x1, y1, x2, y2);
651
if (sraRgnAnd(r1, r0)) {
662
int macosx_check_clipped(int win, int *list, int n) {
663
sraRegionPtr r0, r1, r2;
666
int k, j, i = macosxCGS_find_index(win);
674
x2 = macwins[i].x + macwins[i].width;
675
y2 = macwins[i].y + macwins[i].height;
677
r0 = sraRgnCreateRect(0, 0, dpy_x, dpy_y);
678
r1 = sraRgnCreateRect(x1, y1, x2, y2);
681
for (k = 0; k < n; k++) {
682
j = macosxCGS_find_index(list[k]); /* XXX slow? */
688
x2 = macwins[j].x + macwins[j].width;
689
y2 = macwins[j].y + macwins[j].height;
690
r2 = sraRgnCreateRect(x1, y1, x2, y2);
691
if (sraRgnAnd(r2, r1)) {
705
#endif /* LIBVNCSERVER_HAVE_MACOSX_NATIVE_DISPLAY */