x11vnc: Native Mac OS X support.

pull/1/head
runge 16 years ago
parent 5f9693d4a2
commit 4a83f87609
  1. 4
      ChangeLog
  2. 33
      configure.ac
  3. 2
      prepare_x11vnc_dist.sh
  4. 8
      x11vnc/8to24.c
  5. 3
      x11vnc/ChangeLog
  6. 7
      x11vnc/Makefile.am
  7. 960
      x11vnc/README
  8. 12
      x11vnc/cleanup.c
  9. 21
      x11vnc/connections.c
  10. 279
      x11vnc/cursor.c
  11. 2
      x11vnc/cursor.h
  12. 13
      x11vnc/gui.c
  13. 10
      x11vnc/help.c
  14. 12
      x11vnc/keyboard.c
  15. 6
      x11vnc/linuxfb.c
  16. 377
      x11vnc/macosx.c
  17. 19
      x11vnc/macosx.h
  18. 508
      x11vnc/macosxCG.c
  19. 23
      x11vnc/macosxCG.h
  20. 186
      x11vnc/macosxCGP.c
  21. 17
      x11vnc/macosxCGP.h
  22. 156
      x11vnc/macosxCGS.c
  23. 9
      x11vnc/macosxCGS.h
  24. 4
      x11vnc/options.c
  25. 4
      x11vnc/options.h
  26. 1
      x11vnc/params.h
  27. 7
      x11vnc/pointer.c
  28. 17
      x11vnc/remote.c
  29. 20
      x11vnc/scan.c
  30. 45
      x11vnc/screen.c
  31. 8
      x11vnc/selection.c
  32. 37
      x11vnc/tkx11vnc
  33. 37
      x11vnc/tkx11vnc.h
  34. 32
      x11vnc/userinput.c
  35. 35
      x11vnc/win_utils.c
  36. 20
      x11vnc/x11vnc.1
  37. 48
      x11vnc/x11vnc.c
  38. 6
      x11vnc/x11vnc.h
  39. 2
      x11vnc/x11vnc_defs.c
  40. 130
      x11vnc/xdamage.c
  41. 1
      x11vnc/xdamage.h
  42. 4
      x11vnc/xevents.c
  43. 4
      x11vnc/xinerama.c
  44. 1
      x11vnc/xrandr.c
  45. 12
      x11vnc/xrecord.c
  46. 60
      x11vnc/xwrappers.c
  47. 7
      x11vnc/xwrappers.h

@ -1,3 +1,7 @@
2006-11-13 Karl Runge <runge@karlrunge.com>
* configure.ac: x11vnc warnings for no XTEST or SSL.
* prepare_x11vnc_dist.sh: to 0.8.4
2006-11-07 Karl Runge <runge@karlrunge.com>
* configure.ac: clean up -R linker case, add --without-macosx-native
* prepare_x11vnc_dist.sh: have "make rpm" work properly for

@ -126,7 +126,7 @@ elif test "$X_CFLAGS" != "-DX_DISPLAY_MISSING"; then
AC_CHECK_LIB(Xtst, XTestFakeKeyEvent,
X_PRELIBS="-lXtst $X_PRELIBS"
[AC_DEFINE(HAVE_XTEST)], ,
[AC_DEFINE(HAVE_XTEST) HAVE_XTEST="true"], ,
$X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS)
if test "x$with_xrecord" != "xno"; then
@ -216,6 +216,24 @@ and --x-libraries=DIR configure options or set the CPPFLAGS and LDFLAGS
environment variables to indicate where the X window system header files
and libraries may be found. On 64+32 bit machines you may need to point
to lib64 or lib32 directories to pick up the correct word size.
If you want to build x11vnc without X support (e.g. for -rawfb use only
or for native Mac OS X), specify the --without-x configure option.
==========================================================================
])
fi
if test "$PACKAGE_NAME" = "x11vnc" -a "x$HAVE_X" = "xtrue" -a "x$HAVE_XTEST" != "xtrue"; then
AC_MSG_WARN([
==========================================================================
A working build environment for the XTEST extension was not found (libXtst).
An x11vnc built this way will be only barely usable. You will be able to
move the mouse but not click or type. There can also be deadlocks if an
application grabs the X server.
It is recommended that you install the necessary development packages
for XTEST (perhaps it is named something like libxtst-dev) and run
configure again.
==========================================================================
])
fi
@ -261,6 +279,19 @@ if test "x$with_ssl" != "xno"; then
fi
AC_SUBST(SSL_LIBS)
if test "$PACKAGE_NAME" = "x11vnc"; then
if test "x$HAVE_LIBSSL" != "xtrue"; then
AC_MSG_WARN([
==========================================================================
The openssl encryption library libssl.so was not found. An x11vnc built
this way will not support SSL encryption. To enable SSL install the
necessary development packages (perhaps it is named something like
libssl-dev) and run configure again.
==========================================================================
])
fi
fi
if test "x$with_v4l" != "xno"; then
AC_CHECK_HEADER(linux/videodev.h,
[AC_DEFINE(HAVE_LINUX_VIDEODEV_H)],,)

@ -1,6 +1,6 @@
#!/bin/bash
VERSION="0.8.3"
VERSION="0.8.4"
cd "$(dirname "$0")"

@ -434,7 +434,7 @@ if (db24 > 2) fprintf(stderr, " check_for_multivis: %.4f\n", now - last_call);
old_handler = XSetErrorHandler(trap_xerror);
trapped_xerror = 0;
rc = XQueryTree(dpy, win, &r, &parent, &list0, &nc0);
rc = XQueryTree_wr(dpy, win, &r, &parent, &list0, &nc0);
XSetErrorHandler(old_handler);
if (! rc || trapped_xerror) {
@ -460,7 +460,7 @@ if (db24 > 2) fprintf(stderr, " check_for_multivis: %.4f\n", now - last_call);
old_handler = XSetErrorHandler(trap_xerror);
trapped_xerror = 0;
rc = XQueryTree(dpy, win1, &r, &parent, &list1, &nc1);
rc = XQueryTree_wr(dpy, win1, &r, &parent, &list1, &nc1);
XSetErrorHandler(old_handler);
if (! rc || trapped_xerror) {
@ -479,11 +479,11 @@ if (db24 > 2) fprintf(stderr, " check_for_multivis: %.4f\n", now - last_call);
/* more? Which wm does this? */
}
if (nc1) {
XFree(list1);
XFree_wr(list1);
}
}
if (nc0) {
XFree(list0);
XFree_wr(list0);
}
}
X_UNLOCK;

@ -1,3 +1,6 @@
2006-11-13 Karl Runge <runge@karlrunge.com>
* x11vnc: Native Mac OS X support.
2006-11-07 Karl Runge <runge@karlrunge.com>
* ssl_vncviewer: vnc:// direct connect, add -x to ssh,
SSL_VNC_LISTEN variable for direct proxy.

@ -1,6 +1,11 @@
AM_CFLAGS = -I $(top_srcdir)
LDADD = ../libvncserver/libvncserver.a @WSOCKLIB@
if OSX
x11vnc_LDFLAGS = -framework ApplicationServices -framework Carbon -framework IOKit -framework Cocoa
x11vnc_CFLAGS = -ObjC
endif
SUBDIRS = misc
DIST_SUBDIRS = misc
@ -12,7 +17,7 @@ LD_CYGIPC=-lcygipc
endif
bin_PROGRAMS=x11vnc
x11vnc_SOURCES = 8to24.c cleanup.c connections.c cursor.c gui.c help.c inet.c keyboard.c linuxfb.c options.c pm.c pointer.c rates.c remote.c scan.c screen.c selection.c solid.c sslcmds.c sslhelper.c uinput.c unixpw.c user.c userinput.c util.c v4l.c win_utils.c x11vnc.c x11vnc_defs.c xdamage.c xevents.c xinerama.c xkb_bell.c xrandr.c xrecord.c xwrappers.c 8to24.h allowed_input_t.h blackout_t.h cleanup.h connections.h cursor.h enums.h gui.h help.h inet.h keyboard.h linuxfb.h nox11.h nox11_funcs.h options.h params.h pm.h pointer.h rates.h remote.h scan.h screen.h scrollevent_t.h selection.h solid.h sslcmds.h sslhelper.h ssltools.h tkx11vnc.h uinput.h unixpw.h user.h userinput.h util.h v4l.h win_utils.h winattr_t.h x11vnc.h xdamage.h xevents.h xinerama.h xkb_bell.h xrandr.h xrecord.h xwrappers.h
x11vnc_SOURCES = 8to24.c cleanup.c connections.c cursor.c gui.c help.c inet.c keyboard.c linuxfb.c macosx.c macosxCG.c macosxCGP.c macosxCGS.c options.c pm.c pointer.c rates.c remote.c scan.c screen.c selection.c solid.c sslcmds.c sslhelper.c uinput.c unixpw.c user.c userinput.c util.c v4l.c win_utils.c x11vnc.c x11vnc_defs.c xdamage.c xevents.c xinerama.c xkb_bell.c xrandr.c xrecord.c xwrappers.c 8to24.h allowed_input_t.h blackout_t.h cleanup.h connections.h cursor.h enums.h gui.h help.h inet.h keyboard.h linuxfb.h macosx.h macosxCG.h macosxCGP.h macosxCGS.h nox11.h nox11_funcs.h options.h params.h pm.h pointer.h rates.h remote.h scan.h screen.h scrollevent_t.h selection.h solid.h sslcmds.h sslhelper.h ssltools.h tkx11vnc.h uinput.h unixpw.h user.h userinput.h util.h v4l.h win_utils.h winattr_t.h x11vnc.h xdamage.h xevents.h xinerama.h xkb_bell.h xrandr.h xrecord.h xwrappers.h
if HAVE_X
INCLUDES=@X_CFLAGS@
x11vnc_LDADD=$(LDADD) @SSL_LIBS@ @CRYPT_LIBS@ @X_LIBS@ $(LD_CYGIPC)

File diff suppressed because it is too large Load Diff

@ -126,6 +126,18 @@ void clean_up_exit (int ret) {
ssl_helper_pid(0, 0); /* killall */
}
#ifdef MACOSX
if (client_connect_file) {
if (strstr(client_connect_file, "/tmp/x11vnc-macosx-channel.")
== client_connect_file) {
unlink(client_connect_file);
}
}
if (! dpy) {
macosxCG_fini();
}
#endif
if (! dpy) exit(ret); /* raw_rb hack */
/* X keyboard cleanups */

@ -16,6 +16,7 @@
#include "sslhelper.h"
#include "xwrappers.h"
#include "xevents.h"
#include "macosxCG.h"
/*
* routines for handling incoming, outgoing, etc connections
@ -746,6 +747,11 @@ void client_gone(rfbClientPtr client) {
rfbLog("viewer exited.\n");
clean_up_exit(0);
}
#ifdef MACOSX
if (! dpy && client_count == 0) {
macosxCG_refresh_callback_off();
}
#endif
}
/*
@ -1204,7 +1210,7 @@ static unsigned char t2x2_bits[] = {
ret = out;
XSelectInput(dpy, awin, 0);
XUnmapWindow(dpy, awin);
XFreeGC(dpy, gc);
XFree_wr(gc);
XDestroyWindow(dpy, awin);
XFlush_wr(dpy);
break;
@ -1773,13 +1779,13 @@ void read_vnc_connect_prop(int nomsg) {
/* too big */
rfbLog("warning: truncating large VNC_CONNECT"
" string > %d bytes.\n", VNC_CONNECT_MAX);
XFree(data);
XFree_wr(data);
break;
}
memcpy(vnc_connect_str+slen, data, dlen);
slen += dlen;
vnc_connect_str[slen] = '\0';
XFree(data);
XFree_wr(data);
}
} while (bytes_after > 0);
@ -1823,13 +1829,13 @@ void read_x11vnc_remote_prop(int nomsg) {
/* too big */
rfbLog("warning: truncating large X11VNC_REMOTE"
" string > %d bytes.\n", X11VNC_REMOTE_MAX);
XFree(data);
XFree_wr(data);
break;
}
memcpy(x11vnc_remote_str+slen, data, dlen);
slen += dlen;
x11vnc_remote_str[slen] = '\0';
XFree(data);
XFree_wr(data);
}
} while (bytes_after > 0);
@ -2101,6 +2107,11 @@ enum rfbNewClientAction new_client(rfbClientPtr client) {
*/
autorepeat(0, 0);
}
#ifdef MACOSX
if (! dpy && client_count == 1) {
macosxCG_refresh_callback_on();
}
#endif
if (use_solid_bg && client_count == 1) {
solid_bg(0);
}

@ -33,6 +33,8 @@ void set_no_cursor(void);
void set_warrow_cursor(void);
int set_cursor(int x, int y, int which);
int check_x11_pointer(void);
int store_cursor(int serial, unsigned long *data, int w, int h, int cbpp, int xhot, int yhot);
unsigned long get_cursor_serial(int mode);
typedef struct win_str_info {
@ -57,7 +59,7 @@ static void set_rfb_cursor(int which);
static void tree_descend_cursor(int *depth, Window *w, win_str_info_t *winfo);
static rfbCursorPtr pixels2curs(unsigned long *pixels, int w, int h,
int xhot, int yhot, int Bpp);
static int get_xfixes_cursor(int init);
static int get_exact_cursor(int init);
static void set_cursor_was_changed(rfbScreenInfoPtr s);
@ -618,7 +620,7 @@ static void setup_cursors(void) {
}
/* clear any xfixes cursor cache (no freeing is done) */
get_xfixes_cursor(1);
get_exact_cursor(1);
/* manually fill in the data+masks: */
cur_empty.data = curs_empty_data;
@ -876,7 +878,7 @@ static void tree_descend_cursor(int *depth, Window *w, win_str_info_t *winfo) {
break;
}
/* TBD: query_pointer() */
XQueryPointer(dpy, c, &r, &c, &rx, &ry, &wx, &wy, &mask);
XQueryPointer_wr(dpy, c, &r, &c, &rx, &ry, &wx, &wy, &mask);
}
if (nm_info) {
@ -898,7 +900,7 @@ static void tree_descend_cursor(int *depth, Window *w, win_str_info_t *winfo) {
strcpy(winfo->wm_name, name);
got_wm_name = 1;
}
XFree(name);
XFree_wr(name);
}
}
if (classhint && (! got_res_name || ! got_res_class)) {
@ -910,7 +912,7 @@ static void tree_descend_cursor(int *depth, Window *w, win_str_info_t *winfo) {
strcpy(winfo->res_name, p);
got_res_name = 1;
}
XFree(p);
XFree_wr(p);
classhint->res_name = NULL;
}
p = classhint->res_class;
@ -919,7 +921,7 @@ static void tree_descend_cursor(int *depth, Window *w, win_str_info_t *winfo) {
strcpy(winfo->res_class, p);
got_res_class = 1;
}
XFree(p);
XFree_wr(p);
classhint->res_class = NULL;
}
}
@ -1215,11 +1217,20 @@ static rfbCursorPtr pixels2curs(unsigned long *pixels, int w, int h,
return c;
}
static int get_xfixes_cursor(int init) {
static unsigned long last_cursor = 0;
static int last_index = 0;
static time_t curs_times[CURS_MAX];
static unsigned long curs_index[CURS_MAX];
static unsigned long last_cursor = 0;
static int last_index = 0;
static time_t curs_times[CURS_MAX];
static unsigned long curs_index[CURS_MAX];
unsigned long get_cursor_serial(int mode) {
if (mode == 0) {
return last_cursor;
} else if (mode == 1) {
return (unsigned long) last_index;
}
}
static int get_exact_cursor(int init) {
int which = CURS_ARROW;
if (init) {
@ -1234,12 +1245,21 @@ static int get_xfixes_cursor(int init) {
return -1;
}
#ifdef MACOSX
if (! dpy) {
return macosx_get_cursor();
}
#endif
if (xfixes_present && dpy) {
#if LIBVNCSERVER_HAVE_LIBXFIXES
int use, oldest, i;
time_t oldtime, now;
int last_idx = (int) get_cursor_serial(1);
XFixesCursorImage *xfc;
if (last_idx) {
which = last_idx;
}
if (! got_xfixes_cursor_notify && xfixes_base_event_type) {
/* try again for XFixesCursorNotify event */
XEvent xev;
@ -1252,11 +1272,7 @@ static int get_xfixes_cursor(int init) {
}
if (! got_xfixes_cursor_notify) {
/* evidently no cursor change, just return last one */
if (last_index) {
return last_index;
} else {
return CURS_ARROW;
}
return which;
}
got_xfixes_cursor_notify = 0;
@ -1266,113 +1282,112 @@ static int get_xfixes_cursor(int init) {
X_UNLOCK;
if (! xfc) {
/* failure. */
return(which);
return which;
}
if (xfc->cursor_serial == last_cursor) {
/* same serial index: no change */
X_LOCK;
XFree(xfc);
X_UNLOCK;
if (last_index) {
return last_index;
} else {
return CURS_ARROW;
}
}
which = store_cursor(xfc->cursor_serial, xfc->pixels,
xfc->width, xfc->height, 32, xfc->xhot, xfc->yhot);
X_LOCK;
XFree_wr(xfc);
X_UNLOCK;
#endif
}
return(which);
}
int store_cursor(int serial, unsigned long *data, int w, int h, int cbpp,
int xhot, int yhot) {
int which = CURS_ARROW;
int use, oldest, i;
time_t oldtime, now;
oldest = CURS_DYN_MIN;
if (screen && screen->cursor == cursors[oldest]->rfb) {
oldest++;
#if 0
fprintf(stderr, "sc: %d %d/%d %d - %d %d\n", serial, w, h, cbpp, xhot, yhot);
#endif
oldest = CURS_DYN_MIN;
if (screen && screen->cursor == cursors[oldest]->rfb) {
oldest++;
}
oldtime = curs_times[oldest];
now = time(NULL);
for (i = CURS_DYN_MIN; i <= CURS_DYN_MAX; i++) {
if (screen && screen->cursor == cursors[i]->rfb) {
;
} else if (curs_times[i] < oldtime) {
/* watch for oldest one to overwrite */
oldest = i;
oldtime = curs_times[i];
}
oldtime = curs_times[oldest];
now = time(NULL);
for (i = CURS_DYN_MIN; i <= CURS_DYN_MAX; i++) {
if (screen && screen->cursor == cursors[i]->rfb) {
;
} else if (curs_times[i] < oldtime) {
/* watch for oldest one to overwrite */
oldest = i;
oldtime = curs_times[i];
}
if (xfc->cursor_serial == curs_index[i]) {
/*
* got a hit with an existing cursor,
* use that one.
*/
last_cursor = curs_index[i];
curs_times[i] = now;
last_index = i;
X_LOCK;
XFree(xfc);
X_UNLOCK;
return last_index;
}
if (serial == curs_index[i]) {
/*
* got a hit with an existing cursor,
* use that one.
*/
last_cursor = curs_index[i];
curs_times[i] = now;
last_index = i;
return last_index;
}
}
/* we need to create the cursor and overwrite oldest */
use = oldest;
if (cursors[use]->rfb) {
/* clean up oldest if it exists */
if (cursors[use]->rfb->richSource) {
free(cursors[use]->rfb->richSource);
cursors[use]->rfb->richSource = NULL;
}
if (cursors[use]->rfb->alphaSource) {
free(cursors[use]->rfb->alphaSource);
cursors[use]->rfb->alphaSource = NULL;
}
if (cursors[use]->rfb->source) {
free(cursors[use]->rfb->source);
cursors[use]->rfb->source = NULL;
}
if (cursors[use]->rfb->mask) {
free(cursors[use]->rfb->mask);
cursors[use]->rfb->mask = NULL;
}
free(cursors[use]->rfb);
cursors[use]->rfb = NULL;
/* we need to create the cursor and overwrite oldest */
use = oldest;
if (cursors[use]->rfb) {
/* clean up oldest if it exists */
if (cursors[use]->rfb->richSource) {
free(cursors[use]->rfb->richSource);
cursors[use]->rfb->richSource = NULL;
}
if (cursors[use]->rfb->alphaSource) {
free(cursors[use]->rfb->alphaSource);
cursors[use]->rfb->alphaSource = NULL;
}
if (cursors[use]->rfb->source) {
free(cursors[use]->rfb->source);
cursors[use]->rfb->source = NULL;
}
if (cursors[use]->rfb->mask) {
free(cursors[use]->rfb->mask);
cursors[use]->rfb->mask = NULL;
}
free(cursors[use]->rfb);
cursors[use]->rfb = NULL;
}
if (rotating && rotating_cursors) {
char *dst;
int tx, ty;
int w = xfc->width;
int h = xfc->height;
if (rotating && rotating_cursors) {
char *dst;
int tx, ty;
dst = (char *) malloc(w * h * 4);
rotate_curs(dst, (char *) xfc->pixels, w, h, 4);
dst = (char *) malloc(w * h * cbpp/8);
rotate_curs(dst, (char *) data, w, h, cbpp/8);
memcpy(xfc->pixels, dst, w * h * 4);
free(dst);
memcpy(data, dst, w * h * cbpp/8);
free(dst);
rotate_coords(xfc->xhot, xfc->yhot, &tx, &ty, w, h);
xfc->xhot = tx;
xfc->yhot = ty;
if (! rotating_same) {
xfc->width = h;
xfc->height = w;
}
rotate_coords(xhot, yhot, &tx, &ty, w, h);
xhot = tx;
yhot = ty;
if (! rotating_same) {
int tmp = w;
w = h;
h = tmp;
}
}
/* place cursor into our collection */
cursors[use]->rfb = pixels2curs(xfc->pixels, xfc->width,
xfc->height, xfc->xhot, xfc->yhot, bpp/8);
/* place cursor into our collection */
cursors[use]->rfb = pixels2curs(data, w, h, xhot, yhot, bpp/8);
/* update time and serial index: */
curs_times[use] = now;
curs_index[use] = xfc->cursor_serial;
last_index = use;
last_cursor = xfc->cursor_serial;
/* update time and serial index: */
curs_times[use] = now;
curs_index[use] = serial;
last_index = use;
last_cursor = serial;
which = last_index;
which = last_index;
X_LOCK;
XFree(xfc);
X_UNLOCK;
#endif
}
return(which);
return which;
}
int known_cursors_mode(char *s) {
@ -1465,9 +1480,15 @@ int get_which_cursor(void) {
mode = 3;
}
if (mode == 3 && xfixes_present && use_xfixes) {
if (db) fprintf(stderr, "get_which_cursor call get_xfixes_cursor\n");
return get_xfixes_cursor(0);
if (mode == 3) {
int try_macosx = 0;
#ifdef MACOSX
if (! dpy) try_macosx = 1;
#endif
if ((xfixes_present && use_xfixes) || try_macosx) {
if (db) fprintf(stderr, "get_which_cursor call get_exact_cursor\n");
return get_exact_cursor(0);
}
}
if (depth_cutoff < 0) {
@ -1518,7 +1539,7 @@ int get_which_cursor(void) {
#endif /* NO_X11 */
}
if (which == which0) {
/* the string "term" mean I-beam. */
/* the string "term" means I-beam. */
char *name, *class;
lowercase(winfo.res_name);
lowercase(winfo.res_class);
@ -1821,22 +1842,39 @@ int set_cursor(int x, int y, int which) {
*/
int check_x11_pointer(void) {
Window root_w, child_w;
rfbBool ret;
rfbBool ret = 0;
int root_x, root_y, win_x, win_y;
int x, y;
unsigned int mask;
int macosx_rawfb_ret = 0;
if (unixpw_in_progress) return 0;
#ifdef MACOSX
if (macosx_rawfb_ret) {
RAWFB_RET(0)
}
if (dpy) {
;
} else {
ret = macosx_get_cursor_pos(&root_x, &root_y);
}
#else
RAWFB_RET(0)
#if NO_X11
return 0;
#else
#endif
#endif
if (unixpw_in_progress) return 0;
X_LOCK;
ret = XQueryPointer(dpy, rootwin, &root_w, &child_w, &root_x, &root_y,
&win_x, &win_y, &mask);
X_UNLOCK;
#if ! NO_X11
if (dpy) {
X_LOCK;
ret = XQueryPointer_wr(dpy, rootwin, &root_w, &child_w, &root_x, &root_y,
&win_x, &win_y, &mask);
X_UNLOCK;
}
#endif /* NO_X11 */
if (! ret) {
return 0;
@ -1860,6 +1898,5 @@ int check_x11_pointer(void) {
/* change the cursor shape if necessary */
return set_cursor(x, y, get_which_cursor());
#endif /* NO_X11 */
}

@ -30,5 +30,7 @@ extern void set_no_cursor(void);
extern void set_warrow_cursor(void);
extern int set_cursor(int x, int y, int which);
extern int check_x11_pointer(void);
extern int store_cursor(int serial, unsigned long *data, int w, int h, int cbpp, int xhot, int yhot);
extern unsigned long get_cursor_serial(int mode);
#endif /* _X11VNC_CURSOR_H */

@ -60,7 +60,7 @@ static Window tweak_tk_window_id(Window win) {
}
}
if (name != NULL) {
XFree(name);
XFree_wr(name);
}
return new;
#endif /* NO_X11 */
@ -256,6 +256,9 @@ if (0) fprintf(stderr, "run_gui: %s -- %d %d\n", gui_xdisplay, connect_to_x11vnc
if (! dpy) {
rfbLog("gui: could not open x11vnc "
"display: %s\n", NONUL(x11vnc_xdisplay));
#ifdef MACOSX
goto macjump;
#endif
exit(1);
}
scr = DefaultScreen(dpy);
@ -263,6 +266,8 @@ if (0) fprintf(stderr, "run_gui: %s -- %d %d\n", gui_xdisplay, connect_to_x11vnc
initialize_vnc_connect_prop();
initialize_x11vnc_remote_prop();
}
macjump:
signal(SIGUSR1, sigusr1);
got_sigusr1 = 0;
@ -572,6 +577,10 @@ void do_gui(char *opts, int sleep) {
connect_to_x11vnc = 1;
}
#ifdef MACOSX
goto startit;
#endif
if (icon_mode && !got_gui_xdisplay) {
/* for tray mode, prefer the polled DISPLAY */
if (use_dpy) {
@ -620,6 +629,8 @@ void do_gui(char *opts, int sleep) {
}
XCloseDisplay_wr(test_dpy);
startit:
if (start_x11vnc) {
#if LIBVNCSERVER_HAVE_FORK

@ -2848,6 +2848,10 @@ void print_help(int mode) {
" You can also set the env. var X11VNC_UINPUT_DEBUG=1 or\n"
" higher to get debugging output for UINPUT mode.\n"
"\n"
"-macnodim For the native Mac OS X server, disable dimming. \n"
"-macnosleep For the native Mac OS X server, disable display sleep.\n"
"-macnosaver For the native Mac OS X server, disable screensaver.\n"
"\n"
"-gui [gui-opts] Start up a simple tcl/tk gui based on the the remote\n"
" control options -remote/-query described below.\n"
" Requires the \"wish\" program to be installed on the\n"
@ -3216,6 +3220,8 @@ void print_help(int mode) {
" height parameter to n.\n"
" desktop:str set -desktop name to str for new clients.\n"
" rfbport:n set -rfbport to n.\n"
" macnosaver enable -macnosaver mode.\n"
" macsaver disable -macnosaver mode.\n"
/* access */
" httpport:n set -httpport to n.\n"
" httpdir:dir set -httpdir to dir (and enable http).\n"
@ -3327,7 +3333,7 @@ void print_help(int mode) {
" debug_wireframe debug_scroll nodebug_scroll debug_scroll\n"
" debug_tiles dbt nodebug_tiles nodbt debug_tiles\n"
" debug_grabs nodebug_grabs debug_sel nodebug_sel dbg\n"
" nodbg noremote\n"
" nodbg macnosaver macsaver noremote\n"
"\n"
" aro= noop display vncdisplay desktopname guess_desktop\n"
" http_url auth xauth users rootshift clipshift\n"
@ -3665,7 +3671,7 @@ void nopassword_warning_msg(int gotloc) {
fprintf(stderr, "%s", str1);
fflush(stderr);
#if !PASSWD_REQUIRED
usleep(2500 * 1000);
usleep(1000 * 1000);
#endif
if (!quiet) {
fprintf(stderr, "%s", str2);

@ -129,7 +129,7 @@ void clear_modifiers(int init) {
kcount++;
}
}
XFree((void *) keymap);
XFree_wr((void *) keymap);
first = 0;
}
if (init) {
@ -458,7 +458,7 @@ int add_keysym(KeySym keysym) {
ret = kc;
break;
}
XFree(keymap);
XFree_wr(keymap);
return ret;
#endif /* NO_X11 */
}
@ -491,7 +491,7 @@ static void delete_keycode(KeyCode kc, int bequiet) {
kc, ksym, str ? str : "null");
}
XFree(keymap);
XFree_wr(keymap);
XFlush_wr(dpy);
#endif /* NO_X11 */
}
@ -994,7 +994,7 @@ void switch_to_xkb_if_better(void) {
}
n = k;
XFree(keymap);
XFree_wr(keymap);
if (missing_noxkb == 0 && syms_gt_4 >= 8) {
if (! raw_fb_str) {
rfbLog("XKEYBOARD: number of keysyms per keycode %d "
@ -2300,7 +2300,7 @@ void initialize_modtweak(void) {
iso_level3_code = XKeysymToKeycode(dpy, XK_ISO_Level3_Shift);
#endif
XFree ((void *) keymap);
XFree_wr ((void *) keymap);
X_UNLOCK;
#endif /* NO_X11 */
@ -2531,6 +2531,8 @@ static void pipe_keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
console_key_command(down, keysym, client);
} else if (pipeinput_int == PIPEINPUT_UINPUT) {
uinput_key_command(down, keysym, client);
} else if (pipeinput_int == PIPEINPUT_MACOSX) {
macosx_key_command(down, keysym, client);
}
if (pipeinput_fh == NULL) {
return;

@ -9,6 +9,7 @@
#include "allowed_input_t.h"
#include "uinput.h"
#include "keyboard.h"
#include "macosx.h"
#if LIBVNCSERVER_HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
@ -26,6 +27,11 @@ char *console_guess(char *str, int *fd) {
char *atparms = NULL, *file = NULL;
int do_input, have_uinput, tty = -1;
#ifdef MACOSX
return macosx_console_guess(str, fd);
#endif
if (strstr(in, "/dev/fb") == in) {
free(in);
in = (char *) malloc(strlen("console:") + strlen(str) + 1);

@ -0,0 +1,377 @@
/* -- macosx.c -- */
#include "rfb/rfbconfig.h"
#if (defined(__MACH__) && defined(__APPLE__) && defined(LIBVNCSERVER_HAVE_MACOSX_NATIVE_DISPLAY))
#define DOMAC 1
#else
#define DOMAC 0
#endif
#include "x11vnc.h"
#include "cleanup.h"
#include "scan.h"
#include "screen.h"
#include "pointer.h"
#include "allowed_input_t.h"
#include "keyboard.h"
#include "cursor.h"
#include "macosxCG.h"
#include "macosxCGP.h"
#include "macosxCGS.h"
char *macosx_console_guess(char *str, int *fd);
void macosx_key_command(rfbBool down, rfbKeySym keysym, rfbClientPtr client);
void macosx_pointer_command(int mask, int x, int y, rfbClientPtr client);
char *macosx_get_fb_addr(void);
int macosx_get_cursor(void);
int macosx_get_cursor_pos(int *, int *);
int macosx_valid_window(Window, XWindowAttributes*);
Status macosx_xquerytree(Window w, Window *root_return, Window *parent_return,
Window **children_return, unsigned int *nchildren_return);
#if (! DOMAC)
void macosx_event_loop(void) {
return;
}
char *macosx_console_guess(char *str, int *fd) {
return NULL;
}
void macosx_key_command(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
return;
}
void macosx_pointer_command(int mask, int x, int y, rfbClientPtr client) {
return;
}
char *macosx_get_fb_addr(void) {
return NULL;
}
int macosx_get_cursor(void) {
return 0;
}
int macosx_get_cursor_pos(int *x, int *y) {
return 0;
}
int macosx_valid_window(Window w, XWindowAttributes* a) {
return 0;
}
Status macosx_xquerytree(Window w, Window *root_return, Window *parent_return,
Window **children_return, unsigned int *nchildren_return) {
return (Status) 0;
}
int dragum(void) {return 1;}
#else
void macosx_event_loop(void) {
macosxCG_event_loop();
}
char *macosx_get_fb_addr(void) {
macosxCG_init();
return macosxCG_get_fb_addr();
}
char *macosx_console_guess(char *str, int *fd) {
char *q, *in = strdup(str);
char *atparms = NULL, *file = NULL;
macosxCG_init();
if (strstr(in, "console") != in) {
rfbLog("console_guess: unrecognized console/fb format: %s\n", str);
free(in);
return NULL;
}
*fd = -1;
q = strrchr(in, '@');
if (q) {
atparms = strdup(q+1);
*q = '\0';
}
q = strrchr(in, ':');
if (q) {
file = strdup(q+1);
*q = '\0';
}
if (! file || file[0] == '\0') {
file = strdup("/dev/null");
}
rfbLog("console_guess: file is %s\n", file);
if (! pipeinput_str) {
pipeinput_str = strdup("MACOSX");
initialize_pipeinput();
}
if (! atparms) {
int w, h, b, bps, dep;
unsigned long rm = 0, gm = 0, bm = 0;
w = macosxCG_CGDisplayPixelsWide();
h = macosxCG_CGDisplayPixelsHigh();
b = macosxCG_CGDisplayBitsPerPixel();
bps = macosxCG_CGDisplayBitsPerSample();
dep = macosxCG_CGDisplaySamplesPerPixel() * bps;
rm = (1 << bps) - 1;
gm = (1 << bps) - 1;
bm = (1 << bps) - 1;
rm = rm << 2 * bps;
gm = gm << 1 * bps;
bm = bm << 0 * bps;
if (b == 8 && rm == 0xff && gm == 0xff && bm == 0xff) {
/* I don't believe it... */
rm = 0x07;
gm = 0x38;
bm = 0xc0;
}
/* @66666x66666x32:0xffffffff:... */
atparms = (char *) malloc(200);
sprintf(atparms, "%dx%dx%d:%lx/%lx/%lx",
w, h, b, rm, gm, bm);
}
if (atparms) {
int gw, gh, gb;
if (sscanf(atparms, "%dx%dx%d", &gw, &gh, &gb) == 3) {
fb_x = gw;
fb_y = gh;
fb_b = gb;
}
}
if (! atparms) {
rfbLog("console_guess: could not get @ parameters.\n");
return NULL;
}
q = (char *) malloc(strlen("map:macosx:") + strlen(file) + 1 + strlen(atparms) + 1);
sprintf(q, "map:macosx:%s@%s", file, atparms);
return q;
}
void macosx_pointer_command(int mask, int x, int y, rfbClientPtr client) {
allowed_input_t input;
int rc;
if (0) fprintf(stderr, "macosx_pointer_command: %d %d - %d\n", x, y, mask);
if (mask >= 0) {
got_pointer_calls++;
}
if (view_only) {
return;
}
get_allowed_input(client, &input);
if (! input.motion || ! input.button) {
/* XXX fix me with last_x, last_y, etc. */
return;
}
if (mask >= 0) {
got_user_input++;
got_pointer_input++;
last_pointer_client = client;
last_pointer_time = time(NULL);
}
macosxCG_pointer_inject(mask, x, y);
cursor_x = x;
cursor_y = y;
/* record the x, y position for the rfb screen as well. */
cursor_position(x, y);
/* change the cursor shape if necessary */
rc = set_cursor(x, y, get_which_cursor());
cursor_changes += rc;
last_event = last_input = last_pointer_input = time(NULL);
}
void init_key_table(void) {
macosxCG_init_key_table();
}
void macosx_key_command(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
static int control = 0, alt = 0;
allowed_input_t input;
if (debug_keyboard) fprintf(stderr, "macosx_key_command: %d %s\n", (int) keysym, down ? "down" : "up");
if (view_only) {
return;
}
get_allowed_input(client, &input);
if (! input.keystroke) {
return;
}
init_key_table();
macosxCG_key_inject((int) down, (unsigned int) keysym);
}
int macosx_get_cursor_pos(int *x, int *y) {
macosxCG_get_cursor_pos(x, y);
return 1;
}
int macosx_get_cursor(void) {
return macosxCG_get_cursor();
}
typedef struct windat {
int win;
int x, y;
int width, height;
int level;
} windat_t;
extern int macwinmax;
extern windat_t macwins[];
int macosx_get_wm_frame_pos(int *px, int *py, int *x, int *y, int *w, int *h,
Window *frame, Window *win) {
static int last_idx = -1;
int x1, x2, y1, y2;
int idx = -1, i, k;
macosxCGS_get_all_windows();
macosxCG_get_cursor_pos(px, py);
for (i = -1; i<macwinmax; i++) {
k = i;
if (i == -1) {
if (last_idx >= 0 && last_idx < macwinmax) {
k = last_idx;
} else {
last_idx = -1;
continue;
}
}
x1 = macwins[k].x;
x2 = macwins[k].x + macwins[k].width;
y1 = macwins[k].y;
y2 = macwins[k].y + macwins[k].height;
if (debug_wireframe) fprintf(stderr, "%d/%d: %d %d %d - %d %d %d\n", k, macwins[k].win, x1, *px, x2, y1, *py, y2);
if (x1 <= *px && *px < x2) {
if (y1 <= *py && *py < y2) {
idx = k;
break;
}
}
}
if (idx < 0) {
return 0;
}
*x = macwins[idx].x;
*y = macwins[idx].y;
*w = macwins[idx].width;
*h = macwins[idx].height;
*frame = (Window) macwins[idx].win;
if (win != NULL) {
*win = *frame;
}
last_idx = idx;
return 1;
}
int macosx_valid_window(Window w, XWindowAttributes* a) {
static int last_idx = -1;
int win = (int) w;
int i, k, idx = -1;
for (i = -1; i<macwinmax; i++) {
k = i;
if (i == -1) {
if (last_idx >= 0 && last_idx < macwinmax) {
k = last_idx;
} else {
last_idx = -1;
continue;
}
}
if (macwins[k].win == win) {
idx = k;
break;
}
}
if (idx < 0) {
return 0;
}
a->x = macwins[idx].x;
a->y = macwins[idx].y;
a->width = macwins[idx].width;
a->height = macwins[idx].height;
a->depth = depth;
a->border_width = 0;
a->backing_store = 0;
a->map_state = IsViewable;
last_idx = idx;
return 1;
}
#define QTMAX 2048
static Window cret[QTMAX];
extern int CGS_levelmax;
extern int CGS_levels[];
Status macosx_xquerytree(Window w, Window *root_return, Window *parent_return,
Window **children_return, unsigned int *nchildren_return) {
int i, n, k, swap;
int win1, win2;
*root_return = (Window) 0;
*parent_return = (Window) 0;
#if 0
fprintf(stderr, "macosx_xquerytree in.\n");
#endif
macosxCGS_get_all_windows();
#if 0
fprintf(stderr, "macosx_xquerytree got windows.\n");
#endif
n = 0;
for (k = 0; k < CGS_levelmax; k++) {
for (i = macwinmax - 1; i >= 0; i--) {
if (macwins[i].level == CGS_levels[k]) {
#if 0
fprintf(stderr, "k=%d i=%d n=%d\n", k, i, n);
#endif
cret[n++] = (Window) macwins[i].win;
}
}
}
*children_return = cret;
*nchildren_return = (unsigned int) macwinmax;
return (Status) 1;
}
#endif /* LIBVNCSERVER_HAVE_MACOSX_NATIVE_DISPLAY */

@ -0,0 +1,19 @@
#ifndef _X11VNC_MACOSX_H
#define _X11VNC_MACOSX_H
/* -- macosx.h -- */
extern char *macosx_console_guess(char *str, int *fd);
extern char *macosx_get_fb_addr(void);
extern void macosx_key_command(rfbBool down, rfbKeySym keysym, rfbClientPtr client);
extern void macosx_pointer_command(int mask, int x, int y, rfbClientPtr client);
extern void macosx_event_loop(void);
extern int macosx_get_cursor(void);
extern int macosx_get_cursor_pos(int *, int *);
extern int macosx_valid_window(Window, XWindowAttributes*);
extern Status macosx_xquerytree(Window w, Window *root_return, Window *parent_return,
Window **children_return, unsigned int *nchildren_return);
#endif /* _X11VNC_MACOSX_H */

@ -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,