summaryrefslogtreecommitdiffstats
path: root/x11vnc/macosxCGS.c
diff options
context:
space:
mode:
Diffstat (limited to 'x11vnc/macosxCGS.c')
-rw-r--r--x11vnc/macosxCGS.c377
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