diff options
Diffstat (limited to 'x11vnc/macosxCGS.c')
-rw-r--r-- | x11vnc/macosxCGS.c | 377 |
1 files changed, 351 insertions, 26 deletions
diff --git a/x11vnc/macosxCGS.c b/x11vnc/macosxCGS.c index 0bc5f1b..a723242 100644 --- a/x11vnc/macosxCGS.c +++ b/x11vnc/macosxCGS.c @@ -15,6 +15,7 @@ extern CGDirectDisplayID displayID; void macosxCGS_get_all_windows(void); +int macosxCGS_get_qlook(int); void macosxGCS_set_pasteboard(char *str, int len); typedef CGError CGSError; @@ -31,6 +32,10 @@ extern CGSError CGSGetOnScreenWindowList (CGSConnectionID cid, CGSConnectionID owner, CGSWindowCount listCapacity, CGSWindowIDList list, CGSWindowCount *listCount); +extern CGSError CGSGetWindowList (CGSConnectionID cid, + CGSConnectionID owner, CGSWindowCount listCapacity, + CGSWindowIDList list, CGSWindowCount *listCount); + extern CGSError CGSGetScreenRectForWindow (CGSConnectionID cid, CGSWindowID wid, CGSRect *rect); @@ -54,40 +59,181 @@ typedef struct windat { int x, y; int width, height; int level; + int mapped; + int clipped; + int ncache_only; } windat_t; -#define MAXWINDAT 2048 +extern int ncache; + +#define MAXWINDAT 4096 windat_t macwins[MAXWINDAT]; -static CGSWindowID _wins[MAXWINDAT]; +static CGSWindowID _wins_all[MAXWINDAT]; +static CGSWindowID _wins_mapped[MAXWINDAT]; +static CGSWindowCount _wins_all_cnt, _wins_mapped_cnt; +static int _wins_int[MAXWINDAT]; + +#define WINHISTNUM 32768 +#define WINHISTMAX 4 +char whist[WINHISTMAX][WINHISTNUM]; +int whist_idx = -1; +int qlook[WINHISTNUM]; + +char is_exist = 0x1; +char is_mapped = 0x2; +char is_clipped = 0x4; +char is_offscreen = 0x8; extern double dnow(void); +extern double dnowx(void); extern int dpy_x, dpy_y; +extern int macosx_icon_anim_time; +extern void macosx_add_mapnotify(int, int, int); +extern void macosx_add_create(int, int); +extern void macosx_add_destroy(int, int); +extern void macosx_add_visnotify(int, int, int); int CGS_levelmax; int CGS_levels[16]; +int macosxCGS_get_qlook(int w) { + if (w >= WINHISTNUM) { + return -1; + } + return qlook[w]; +} + +int macosxCGS_find_index(int w) { + static int last_index = -1; + int idx; + + if (last_index >= 0) { + if (macwins[last_index].win == w) { + return last_index; + } + } + + idx = macosxCGS_get_qlook(w); + if (idx >= 0) { + if (macwins[idx].win == w) { + last_index = idx; + return idx; + } + } + + for (idx=0; idx < macwinmax; idx++) { + if (macwins[idx].win == w) { + last_index = idx; + return idx; + } + } + return -1; +} + +int macosxCGS_follow_animation_win(int win, int idx, int grow) { + double t = dnow(); + int diffs = 0; + int x, y, w, h; + int xp, yp, wp, hp; + CGSRect rect; + CGSError err; + + int reps = 0; + + if (cid == NULL) { + cid = _CGSDefaultConnection(); + if (cid == NULL) { + return 0; + } + } + + if (idx < 0) { + idx = macosxCGS_find_index(win); + } + if (idx < 0) { + return 0; + } + + while (dnow() < t + 0.001 * macosx_icon_anim_time) { + err = CGSGetScreenRectForWindow(cid, win, &rect); + if (err != 0) { + break; + } + x = (int) rect.origin.x; + y = (int) rect.origin.y; + w = (int) rect.size.width; + h = (int) rect.size.height; + + if (grow) { + macwins[idx].x = x; + macwins[idx].y = y; + macwins[idx].width = w; + macwins[idx].height = h; + } + + fprintf(stderr, " chase: %03dx%03d+%03d+%03d %d\n", w, h, x, y, win); + if (x == xp && y == yp && w == wp && h == hp) { + reps++; + if (reps >= 2) { + break; + } + } else { + diffs++; + reps = 0; + } + xp = x; + yp = y; + wp = w; + hp = h; + usleep(50 * 1000); + } + if (diffs >= 2) { + return 1; + } else { + return 0; + } +} + +extern int macosx_check_clipped(int win, int *list, int n); +extern int macosx_check_offscreen(int win); + +static int check_clipped(int win) { + int i, n = 0, win2; + for (i = 0; i < (int) _wins_mapped_cnt; i++) { + win2 = (int) _wins_mapped[i]; + if (win2 == win) { + break; + } + _wins_int[n++] = win2; + } + return macosx_check_clipped(win, _wins_int, n); +} + +static int check_offscreen(int win) { + return macosx_check_offscreen(win); +} + +extern int macosx_ncache_macmenu; + void macosxCGS_get_all_windows(void) { static double last = 0.0; - static int first = 1; + static int totcnt = 0; double dt = 0.0, now = dnow(); - int i, db = 0; + int i, db = 0, whist_prv, maxwin = 0, whist_skip = 0; CGSWindowCount cap = (CGSWindowCount) MAXWINDAT; CGSWindowCount cnt = 0; CGSError err; - if (first) { - first = 0; - CGS_levelmax = 0; - CGS_levels[CGS_levelmax++] = (int) kCGDraggingWindowLevel; /* 500 ? */ - if (0) CGS_levels[CGS_levelmax++] = (int) kCGHelpWindowLevel; /* 102 ? */ - if (0) CGS_levels[CGS_levelmax++] = (int) kCGPopUpMenuWindowLevel; /* 101 pulldown menu */ - CGS_levels[CGS_levelmax++] = (int) kCGMainMenuWindowLevelKey; /* 24 ? */ - CGS_levels[CGS_levelmax++] = (int) kCGModalPanelWindowLevel; /* 8 open dialog box */ - CGS_levels[CGS_levelmax++] = (int) kCGFloatingWindowLevel; /* 3 ? */ - CGS_levels[CGS_levelmax++] = (int) kCGNormalWindowLevel; /* 0 regular window */ - } + CGS_levelmax = 0; + CGS_levels[CGS_levelmax++] = (int) kCGDraggingWindowLevel; /* 500 ? */ + if (0) CGS_levels[CGS_levelmax++] = (int) kCGHelpWindowLevel; /* 102 ? */ + if (macosx_ncache_macmenu) CGS_levels[CGS_levelmax++] = (int) kCGPopUpMenuWindowLevel; /* 101 pulldown menu */ + CGS_levels[CGS_levelmax++] = (int) kCGMainMenuWindowLevelKey; /* 24 ? */ + CGS_levels[CGS_levelmax++] = (int) kCGModalPanelWindowLevel; /* 8 open dialog box */ + CGS_levels[CGS_levelmax++] = (int) kCGFloatingWindowLevel; /* 3 ? */ + CGS_levels[CGS_levelmax++] = (int) kCGNormalWindowLevel; /* 0 regular window */ if (cid == NULL) { cid = _CGSDefaultConnection(); @@ -100,23 +246,38 @@ void macosxCGS_get_all_windows(void) { return; } - err = CGSGetOnScreenWindowList(cid, NULL, cap, _wins, &cnt); + last = now; + + macwinmax = 0; -if (db) fprintf(stderr, "cnt: %d err: %d\n", cnt, err); + totcnt++; + + if (ncache > 0) { + whist_prv = whist_idx++; + if (whist_prv < 0) { + whist_skip = 1; + whist_prv = 0; + } + whist_idx = whist_idx % WINHISTMAX; + for (i=0; i < WINHISTNUM; i++) { + whist[whist_idx][i] = 0; + qlook[i] = -1; + } + } + + err = CGSGetWindowList(cid, NULL, cap, _wins_all, &_wins_all_cnt); + +if (db) fprintf(stderr, "cnt: %d err: %d\n", _wins_all_cnt, err); if (err != 0) { return; } - last = now; - - macwinmax = 0; - - for (i=0; i < (int) cnt; i++) { + for (i=0; i < (int) _wins_all_cnt; i++) { CGSRect rect; CGSWindowLevel level; int j, keepit = 0; - err = CGSGetScreenRectForWindow(cid, _wins[i], &rect); + err = CGSGetScreenRectForWindow(cid, _wins_all[i], &rect); if (err != 0) { continue; } @@ -127,7 +288,7 @@ if (db) fprintf(stderr, "cnt: %d err: %d\n", cnt, err); } } } - err = CGSGetWindowLevel(cid, _wins[i], &level); + err = CGSGetWindowLevel(cid, _wins_all[i], &level); if (err != 0) { continue; } @@ -142,16 +303,180 @@ if (db) fprintf(stderr, "cnt: %d err: %d\n", cnt, err); } macwins[macwinmax].level = (int) level; - macwins[macwinmax].win = (int) _wins[i]; + macwins[macwinmax].win = (int) _wins_all[i]; macwins[macwinmax].x = (int) rect.origin.x; macwins[macwinmax].y = (int) rect.origin.y; macwins[macwinmax].width = (int) rect.size.width; macwins[macwinmax].height = (int) rect.size.height; -if (db) fprintf(stderr, "i=%03d ID: %06d x: %03d y: %03d w: %03d h: %03d level: %d\n", i, _wins[i], + macwins[macwinmax].mapped = 0; + macwins[macwinmax].clipped = 0; + macwins[macwinmax].ncache_only = 0; + if (level == kCGPopUpMenuWindowLevel) { + macwins[macwinmax].ncache_only = 1; + } + +if (0 || db) fprintf(stderr, "i=%03d ID: %06d x: %03d y: %03d w: %03d h: %03d level: %d\n", i, _wins_all[i], (int) rect.origin.x, (int) rect.origin.y,(int) rect.size.width, (int) rect.size.height, (int) level); + if (macwins[macwinmax].win < WINHISTNUM) { + qlook[macwins[macwinmax].win] = macwinmax; + if (macwins[macwinmax].win > maxwin) { + maxwin = macwins[macwinmax].win; + } + } + macwinmax++; } + + err = CGSGetOnScreenWindowList(cid, NULL, cap, _wins_mapped, &_wins_mapped_cnt); + +if (db) fprintf(stderr, "cnt: %d err: %d\n", _wins_mapped_cnt, err); + + if (err != 0) { + return; + } + + for (i=0; i < (int) _wins_mapped_cnt; i++) { + int j, idx = -1; + int win = (int) _wins_mapped[i]; + + if (0 <= win && win < WINHISTNUM) { + j = qlook[win]; + if (j >= 0 && macwins[j].win == win) { + idx = j; + } + } + if (idx < 0) { + for (j=0; j < macwinmax; j++) { + if (macwins[j].win == win) { + idx = j; + break; + } + } + } + if (idx >= 0) { + macwins[idx].mapped = 1; + } + } + + if (ncache > 0) { + int nv= 0, NBMAX = 64; + int nv_win[64]; + int nv_lvl[64]; + int nv_vis[64]; + + for (i=0; i < macwinmax; i++) { + int win = macwins[i].win; + char prev, curr; + + if (win >= WINHISTNUM) { + continue; + } + + whist[whist_idx][win] |= is_exist; + if (macwins[i].mapped) { + whist[whist_idx][win] |= is_mapped; + if (check_clipped(win)) { + whist[whist_idx][win] |= is_clipped; + macwins[i].clipped = 1; + } + if (check_offscreen(win)) { + whist[whist_idx][win] |= is_offscreen; + } + } else { + whist[whist_idx][win] |= is_offscreen; + } + + curr = whist[whist_idx][win]; + prev = whist[whist_prv][win]; + + if (whist_skip) { + ; + } else if ( !(prev & is_mapped) && (curr & is_mapped)) { + /* MapNotify */ + fprintf(stderr, "MapNotify: %d/%d %d %.4f %d tot=%d\n", prev, curr, win, dnowx(), totcnt); + macosx_add_mapnotify(win, macwins[i].level, 1); + //macosxCGS_follow_animation_win(win, i, 1); + + } else if ( !(curr & is_mapped) && (prev & is_mapped)) { + /* UnmapNotify */ + fprintf(stderr, "UnmapNotify: %d/%d %d %.4f A tot=%d\n", prev, curr, win, dnowx(), totcnt); + macosx_add_mapnotify(win, macwins[i].level, 0); + } else if ( !(prev & is_exist) && (curr & is_exist)) { + /* CreateNotify */ + fprintf(stderr, "CreateNotify:%d/%d %d %.4f whist: %d/%d 0x%x tot=%d\n", prev, curr, win, dnowx(), whist_prv, whist_idx, win, totcnt); + macosx_add_create(win, macwins[i].level); + if (curr & is_mapped) { + fprintf(stderr, "MapNotify: %d/%d %d %.4f tot=%d\n", prev, curr, win, dnowx(), totcnt); + macosx_add_mapnotify(win, macwins[i].level, 1); + } + } + if (whist_skip) { + ; + } else if (nv >= NBMAX) { + ; + } else if (!(curr & is_mapped)) { + ; + } else if (!(prev & is_mapped)) { + if (1) { + ; + } else if (curr & is_clipped) { + fprintf(stderr, "VisibNotify: %d/%d %d OBS tot=%d\n", prev, curr, win, totcnt); + nv_win[nv] = win; + nv_lvl[nv] = macwins[i].level; + nv_vis[nv++] = 1; + } else { + fprintf(stderr, "VisibNotify: %d/%d %d UNOBS tot=%d\n", prev, curr, win, totcnt); + nv_win[nv] = win; + nv_lvl[nv] = macwins[i].level; + nv_vis[nv++] = 0; + } + } else { + if ( !(prev & is_clipped) && (curr & is_clipped) ) { + fprintf(stderr, "VisibNotify: %d/%d %d OBS tot=%d\n", prev, curr, win, totcnt); + nv_win[nv] = win; + nv_lvl[nv] = macwins[i].level; + nv_vis[nv++] = 1; + } else if ( (prev & is_clipped) && !(curr & is_clipped) ) { + fprintf(stderr, "VisibNotify: %d/%d %d UNOBS tot=%d\n", prev, curr, win, totcnt); + nv_win[nv] = win; + nv_lvl[nv] = macwins[i].level; + nv_vis[nv++] = 0; + } + } + } + for (i=0; i < maxwin; i++) { + char prev, curr; + int win = i; + int q = qlook[i]; + int lvl = 0; + + if (whist_skip) { + break; + } + + if (q >= 0) { + lvl = macwins[q].level; + } + curr = whist[whist_idx][win]; + prev = whist[whist_prv][win]; + if (!(curr & is_exist) && (prev & is_exist)) { + if (prev & is_mapped) { + fprintf(stderr, "UnmapNotify: %d/%d %d %.4f B tot=%d\n", prev, curr, win, dnowx(), totcnt); + macosx_add_mapnotify(win, lvl, 0); + } + /* DestroyNotify */ + fprintf(stderr, "DestroNotify:%d/%d %d %.4f tot=%d\n", prev, curr, win, dnowx(), totcnt); + macosx_add_destroy(win, lvl); + } + } + if (nv) { + int k; + for (k = 0; k < nv; k++) { + macosx_add_visnotify(nv_win[k], nv_lvl[k], nv_vis[k]); + } + } + } } #if 1 |