From 596331a5c3124f080cdcbb400c188c095048ef35 Mon Sep 17 00:00:00 2001 From: runge Date: Wed, 29 Dec 2010 10:05:52 -0500 Subject: [PATCH] x11vnc: Use opengl to read screen on macosx. non-deprecated macosx interfaces for input injection. --- configure.ac | 8 + x11vnc/ChangeLog | 24 ++- x11vnc/Makefile.am | 12 +- x11vnc/README | 297 ++++++++++++++++++++--------- x11vnc/avahi.c | 1 - x11vnc/cleanup.c | 9 + x11vnc/connections.c | 64 +++++++ x11vnc/connections.h | 1 + x11vnc/help.c | 50 +++++ x11vnc/inet.c | 58 ++++++ x11vnc/inet.h | 2 + x11vnc/macosx.c | 35 ++-- x11vnc/macosxCG.c | 423 ++++++++++++++++++++++++++++++++++++----- x11vnc/macosxCG.h | 2 +- x11vnc/macosx_opengl.c | 176 +++++++++++++++++ x11vnc/macosx_opengl.h | 41 ++++ x11vnc/options.c | 6 + x11vnc/options.h | 6 + x11vnc/rates.c | 7 + x11vnc/screen.c | 10 +- x11vnc/ssltools.h | 18 ++ x11vnc/util.c | 25 +++ x11vnc/x11vnc.1 | 60 +++++- x11vnc/x11vnc.c | 35 +++- x11vnc/x11vnc.h | 34 ++++ x11vnc/x11vnc_defs.c | 2 +- x11vnc/xwrappers.c | 11 ++ 27 files changed, 1251 insertions(+), 166 deletions(-) create mode 100644 x11vnc/macosx_opengl.c create mode 100644 x11vnc/macosx_opengl.h diff --git a/configure.ac b/configure.ac index 1bdef8c..4ad489b 100644 --- a/configure.ac +++ b/configure.ac @@ -90,6 +90,7 @@ AH_TEMPLATE(HAVE_LINUX_FB_H, [linux fb device build environment present]) AH_TEMPLATE(HAVE_LINUX_INPUT_H, [linux/input.h present]) AH_TEMPLATE(HAVE_LINUX_UINPUT_H, [linux uinput device build environment present]) AH_TEMPLATE(HAVE_MACOSX_NATIVE_DISPLAY, [build MacOS X native display support]) +AH_TEMPLATE(HAVE_MACOSX_OPENGL_H, [MacOS X OpenGL present]) AC_ARG_WITH(xkeyboard, [ --without-xkeyboard disable xkeyboard extension support],,) @@ -399,6 +400,10 @@ if test "x$with_macosx_native" != "xno"; then AC_DEFINE(HAVE_MACOSX_NATIVE_DISPLAY) fi +# Check for OS X opengl header +AC_CHECK_HEADER(OpenGL/OpenGL.h, + [AC_DEFINE(HAVE_MACOSX_OPENGL_H) HAVE_MACOSX_OPENGL_H="true"],,) + AH_TEMPLATE(HAVE_AVAHI, [Avahi/mDNS client build environment present]) AC_ARG_WITH(avahi, [ --without-avahi disable support for Avahi/mDNS] @@ -429,6 +434,9 @@ fi fi # end x11vnc only. +# only used in x11vnc/Makefile.am but needs to always be defined: +AM_CONDITIONAL(OSX_OPENGL, test "$HAVE_MACOSX_OPENGL_H" = "true") + # Checks for libraries. if test ! -z "$with_system_libvncserver" -a "x$with_system_libvncserver" != "xno"; then diff --git a/x11vnc/ChangeLog b/x11vnc/ChangeLog index 7ed6f78..24e33b2 100644 --- a/x11vnc/ChangeLog +++ b/x11vnc/ChangeLog @@ -1,10 +1,16 @@ +2010-12-29 Karl Runge + * x11vnc: Use opengl to read screen on macosx. Experimental + use of non-deprecated macosx interfaces for input injection. + Fix cursors for 64bit macosx. Add -unixsock option. Work around + grep issue on OpenBSD in create_display. + 2010-12-21 Karl Runge * x11vnc: Add RELEASE-NOTES. Call shutdown_uinput() when exiting. Free some minor memory. Do not use GetMainDevice() on macosx. Add utility scripts qt_tslib_inject.pl and uinput.pl. Option -ungrabboth (not useful.) X11VNC_SB_FACTOR -sb user tweak. X11VNC_REFLECT_{bitsPerSample,samplesPerPixel,bytesPerPixel} - for -reflect vncclient. Fix minor fd leaks. For -create mode + for -reflect vncclient. Fix minor fd leaks. For -create mode preserve LC_ALL; FIND_DISPLAY_NO_VT_FIND, FIND_DISPLAY_NO_LSOF, and X11VNC_CREATE_LC_ALL_C_OK. Speed up -find and -create scripts for large installations. Enable direct event input modes to @@ -54,7 +60,7 @@ dotted_ip() and -listen6. Improvements to ipv6 mode. http interface for X11VNC_HTTP_LISTEN_LOCALHOST. Print warning about missing Xvfb, Xdummy, or Xvnc in -create. - Fix __LINUX_VIDEODEV2_H / HAVE_V4L2. Always print out info + Fix __LINUX_VIDEODEV2_H / HAVE_V4L2. Always print out info about Xinerama screens. * x11vnc/misc/enhanced_tightvnc_viewer: check for host cmd. fix stunnel mode w/o proxy. Update to stunnel 4.33, Fix @@ -128,7 +134,7 @@ x11vnc instances.) The -quiet option documented better. Add fakebuttonevent remote control action. Improve child test for connecting to port 113. Add connect_switch and - ultravnc_repeater.pl to CVS. Report X server number of mouse + ultravnc_repeater.pl to CVS. Report X server number of mouse buttons. Change find_display script to check for stale pids in /tmp/.XNN-lock. If root under find_display, try FD_XDM if previous failed to find auth. Print error reasons for @@ -162,11 +168,11 @@ Delay calling xfixes at the beginning of 1st connection to avoid display manager Xorg server crash. Delay selwin creation at the begin 1st connection to avoid being killed by display manager. - Options -findauth and '-auth guess'. Export icon_mode query. + Options -findauth and '-auth guess'. Export icon_mode query. Do not open X display in -rawfb mode unless asked. Bugfix for -sid/-id handling window offscreen or bigger than display. Search for windows with _DBUS_SESSION_BUS_PID to decide which - dbus_launch is ours. Fix missing displays in FIND_DISPLAY + dbus_launch is ours. Fix missing displays in FIND_DISPLAY script. Add X11VNC_SKIP_DISPLAY_NEGATE. Improvements to 'x11vnc Properties' gui dialog and connecting with x11vnc via socket (client list.) X11VNC_SYSTEM_GREETER1 for previous text @@ -275,9 +281,9 @@ 2008-12-10 Karl Runge * x11vnc: 0.9.6 release. Some strtok bugfixes. rename -tlsvnc - to -anontls. Disable ssl caching. No cert creation prompting + to -anontls. Disable ssl caching. No cert creation prompting in inetd or bg modes. waitpid a bit more carefully on ssl - helpers. Tune ssl initial timeouts. Let -create user specify + helpers. Tune ssl initial timeouts. Let -create user specify starting X display. fix -rfbport prompt gui for older tk. -sslonly option. Error if no -ssl with related options. -rand option. -ssl implies -ssl SAVE @@ -301,7 +307,7 @@ 2008-10-19 Karl Runge * x11vnc: -chatwindow for chat window on X console using SSVNC - as a helper. Print suggestion for X_ShmAttach failure. + as a helper. Print suggestion for X_ShmAttach failure. Allow -scale WxH for different X- and Y-scaling factors. Workaround for missing -enc cipher EVP_aes_256_cfb. Modify message digest and salt/IV parameters. Try to improve compile @@ -383,7 +389,7 @@ 2007-09-11 Karl Runge * x11vnc: fix wireframe crash under -clip. Add -redirect for VNC redir. -rawfb nullbig, randbig, solid, swirl, etc. - FD_XDM mode to find_display. -listdpy. Add enlightenment. + FD_XDM mode to find_display. -listdpy. Add enlightenment. Xvnc.redirect FINDDISPLAY-vnc_redirect. -xvnc, -xvnc_redirect, -svc_xvnc. AUTO_PORT. * ssvnc: sshvnc ssh-only, tsvnc Terminal Services modes. diff --git a/x11vnc/Makefile.am b/x11vnc/Makefile.am index 32f0978..cef82f3 100644 --- a/x11vnc/Makefile.am +++ b/x11vnc/Makefile.am @@ -5,7 +5,15 @@ LDADD = ../libvncserver/libvncserver.la ../libvncclient/libvncclient.la @WSOCKLI endif if OSX -x11vnc_LDFLAGS = -framework ApplicationServices -framework Carbon -framework IOKit -framework Cocoa +FRAMEWORKS = -framework ApplicationServices -framework Carbon -framework IOKit -framework Cocoa +if OSX_OPENGL +FRAMEWORKS += -framework OpenGL +if HAVE_X11 +GL = /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib +FRAMEWORKS += -dylib_file $(GL):$(GL) +endif +endif +x11vnc_LDFLAGS = $(FRAMEWORKS) x11vnc_CFLAGS = -ObjC endif @@ -23,7 +31,7 @@ LD_CYGIPC=-lcygipc endif bin_PROGRAMS=x11vnc -x11vnc_SOURCES = 8to24.c appshare.c avahi.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 avahi.h blackout_t.h cleanup.h connections.h cursor.h enc.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 +x11vnc_SOURCES = 8to24.c appshare.c avahi.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 macosx_opengl.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 avahi.h blackout_t.h cleanup.h connections.h cursor.h enc.h enums.h gui.h help.h inet.h keyboard.h linuxfb.h macosx.h macosxCG.h macosxCGP.h macosxCGS.h macosx_opengl.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_SYSTEM_LIBVNCSERVER INCLUDES_LIBVNCSERVER = @SYSTEM_LIBVNCSERVER_CFLAGS@ diff --git a/x11vnc/README b/x11vnc/README index 42cab34..e8457e6 100644 --- a/x11vnc/README +++ b/x11vnc/README @@ -2,7 +2,7 @@ Copyright (C) 2002-2010 Karl J. Runge All rights reserved. -x11vnc README file Date: Tue Dec 21 13:47:44 EST 2010 +x11vnc README file Date: Mon Dec 27 20:58:57 EST 2010 The following information is taken from these URLs: @@ -924,12 +924,19 @@ make * The list of new uinput parameters for the above two features is: pressure, tslib_cal, touch_always, dragskip, btn_touch; direct_rel, direct_abs, direct_btn, direct_key. + * The MacOSX native server can now use OpenGL for the screen + capture. In nearly all cases this is faster than the raw + framebuffer capture method. There are build and run time flags, + X11VNC_MACOSX_NO_DEPRECATED, etc. to disable use of deprecated + input injection and screen access interfaces. Cursor shape now + works for 64bit binaries. * The included SSL enabled Java VNC Viewers now handle Mouse Wheel events. - * miscellaneous new features and changes: In -reflect mode, the - libvncclient connection can now have the pixel format modified via - the environment variables X11VNC_REFLECT_bitsPerSample, - X11VNC_REFLECT_samplesPerPixel, and X11VNC_REFLECT_bytesPerPixel + * miscellaneous new features and changes: + * In -reflect mode, the libvncclient connection can now have the + pixel format modified via the environment variables + X11VNC_REFLECT_bitsPerSample, X11VNC_REFLECT_samplesPerPixel, and + X11VNC_REFLECT_bytesPerPixel * In -create mode the following environment variables are added to fine tune the behavior: FIND_DISPLAY_NO_LSOF: do not use lsof(1) to try to determine the Linux VT, FIND_DISPLAY_NO_VT_FIND: do not @@ -941,6 +948,9 @@ make * In -unixpw mode, one can now Tab from login: to Password. * An environment variable, X11VNC_SB_FACTOR, allows one to scale the -sb screenblank sleep time from the default 2 secs. + * An experimental option -unixsock is available for testing. Note, + however, that it requires a manual change to + libvncserver/rfbserver.c for it to work. * Documented that -grabkbd is no longer working with some/most window managers (it can prevent resizing and menu posting.) @@ -3489,8 +3499,8 @@ if [ "$RFB_CLIENT_IP" != "127.0.0.1" -o "$RFB_SERVER_IP" != "127.0.0.1" ]; then exit 1 # something fishy... reject it. fi user=`echo "$RFB_CLIENT_PORT, $RFB_SERVER_PORT" | nc -w 1 $RFB_CLIENT_IP 113 \ - | grep 'USERID.*UNIX' | head -1 | sed -e 's/[\r ]//g' | awk -F: '{print - $4}'` + | grep 'USERID.*UNIX' | head -n 1 | sed -e 's/[\r ]//g' | awk -F: '{pri +nt $4}'` for okuser in fred barney wilma betty do @@ -3504,6 +3514,67 @@ exit 1 # reject it UsePrivilegeSeparation must be enabled otherwise the userid will always be "root". + Here is a similar example based on Linux netstat(1) output: +#!/bin/sh +# +# accept_local_netstat: x11vnc -accept command to accept a local +# vncviewer connection from acceptable users. Linux netstat -nte is used. + +PATH=/bin:/usr/bin:$PATH; export PATH; # set to get system utils + +allowed="`id -u fred`"; # add more user numbers if desired. + +# check required settings +ok=1 +if [ "X$allowed" = "X" ]; then + ok=0; # something wrong with allowed list +fi +if [ "X$RFB_CLIENT_IP" != "X127.0.0.1" -o "X$RFB_SERVER_IP" != "X127.0.0.1" ]; +then + ok=0; # connection not over localhost +fi +if [ "$RFB_CLIENT_PORT" -le 0 -o "$RFB_SERVER_PORT" -le 0 ]; then + ok=0; # something wrong with tcp port numbers +fi +if [ "$ok" = 0 ]; then + echo "$0: invalid setting:" 1>&2 + env | grep ^RFB | sort 1>&2 + exit 1 +fi + +# Linux netstat -nte: +# Proto Recv-Q Send-Q Local Address Foreign Address State + User Inode +# 0 0 0 RFB_CLIENT RFB_SERVER ESTABLISHED + nnnn .... +# +user=`netstat -nte | grep ESTABLISHED \ + | grep " $RFB_CLIENT_IP:$RFB_CLIENT_PORT *$RFB_SERVER_IP:$RFB_SERVER_P +ORT "` + +echo "netstat match: $user" 1>&2 +user=`echo "$user" | head -n 1 | sed -e 's/^.*ESTABLISHED/ /' | awk '{print $1} +'` + +ok=0 +for u in $allowed +do + if [ "X$user" = "X$u" ]; then + ok=1 + break + fi +done + +if [ "X$ok" = "X1" ]; then + echo "$0: user accepted: '$user'" 1>&2 + exit 0 +else + echo "$0: user '$user' invalid:" 1>&2 + echo "$0: allowed: $allowed" 1>&2 + env | grep ^RFB | sort 1>&2 + exit 1 +fi + Q-39: Can I supply an external program to provide my own custom login method (e.g. Dynamic/One-time passwords or non-Unix (LDAP) usernames @@ -8184,9 +8255,9 @@ rm -f $tmp Terminal windows (you can't delete them since that will kill x11vnc.) Update Aug/2010: A user reports the following useful information: -This is not a problem on Mac OS X 10.6.x when connecting via ssh to -start x11vnc. And, on Mac OS X 10.5.x, the problem can be permanently -eliminated by doing this: +This is not a problem on Mac OS X 10.6.x (Snow Leopard) when connecting +via ssh to start x11vnc. And, on Mac OS X 10.5.x (Leopard), the problem +can be permanently eliminated by doing this: sudo /usr/libexec/PlistBuddy -c 'delete :LimitLoadToSessionType' \ @@ -8198,6 +8269,9 @@ and then restarting (yes, you must restart not just log off). But ONLY do that for Mac OS X 10.5.x and NOT for 10.6.x (which doesn't need it anyway). + We recently got access to a MacOSX 10.6.4 (Snow Leopard) macbook and + have confirmed that the above is correct. + Q-120: Can x11vnc be used as a VNC reflector/repeater to improve performance for the case of a large number of simultaneous VNC viewers @@ -12285,7 +12359,7 @@ x11vnc: a VNC server for real X displays Here are all of x11vnc command line options: % x11vnc -opts (see below for -help long descriptions) -x11vnc: allow VNC connections to real X11 displays. 0.9.13 lastmod: 2010-12-21 +x11vnc: allow VNC connections to real X11 displays. 0.9.13 lastmod: 2010-12-27 x11vnc options: -display disp -auth file -N @@ -12304,80 +12378,81 @@ x11vnc options: -avahi -mdns -zeroconf -connect string -connect_or_exit str -proxy string -vncconnect -novncconnect -allow host1[,host2..] - -localhost -listen6 str -nolookup - -input string -grabkbd -grabptr - -ungrabboth -grabalways -viewpasswd string - -passwdfile filename -showrfbauth filename -unixpw [list] - -unixpw_nis [list] -unixpw_cmd cmd -find - -finddpy -listdpy -findauth [disp] - -create -xdummy -xvnc - -xvnc_redirect -xdummy_xvfb -create_xsrv str - -svc -svc_xdummy -svc_xvnc - -svc_xdummy_xvfb -xdmsvc -sshxdmsvc - -unixpw_system_greeter -redirect port -display WAIT:... - -vencrypt mode -anontls mode -sslonly - -dhparams file -nossl -ssl [pem] - -ssltimeout n -sslnofail -ssldir dir - -sslverify path -sslCRL path -sslGenCA [dir] - -sslGenCert type name -sslEncKey pem -sslCertInfo pem - -sslDelCert pem -sslScripts -stunnel [pem] - -stunnel3 [pem] -enc cipher:keyfile -https [port] - -httpsredir [port] -http_oneport -ssh user@host:disp - -usepw -storepasswd pass file -nopw - -accept string -afteraccept string -gone string - -users list -noshm -flipbyteorder - -onetile -solid [color] -blackout string - -xinerama -noxinerama -xtrap - -xrandr [mode] -rotate string -padgeom WxH - -o logfile -flag file -rmflag file - -rc filename -norc -env VAR=VALUE - -prog /path/to/x11vnc -h, -help -?, -opts - -V, -version -license -dbg - -q, -quiet -v, -verbose -bg - -modtweak -nomodtweak -xkb - -noxkb -capslock -skip_lockkeys - -noskip_lockkeys -skip_keycodes string -sloppy_keys - -skip_dups -noskip_dups -add_keysyms - -noadd_keysyms -clear_mods -clear_keys - -clear_all -remap string -norepeat - -repeat -nofb -nobell - -nosel -noprimary -nosetprimary - -noclipboard -nosetclipboard -seldir string - -cursor [mode] -nocursor -cursor_drag - -arrow n -noxfixes -alphacut n - -alphafrac fraction -alpharemove -noalphablend - -nocursorshape -cursorpos -nocursorpos - -xwarppointer -noxwarppointer -always_inject - -buttonmap string -nodragging -ncache n - -ncache_cr -ncache_no_moveraise -ncache_no_dtchange - -ncache_no_rootpixmap -ncache_keep_anims -ncache_old_wm - -ncache_pad n -debug_ncache -wireframe [str] - -nowireframe -nowireframelocal -wirecopyrect mode - -nowirecopyrect -debug_wireframe -scrollcopyrect mode - -noscrollcopyrect -scr_area n -scr_skip list - -scr_inc list -scr_keys list -scr_term list - -scr_keyrepeat lo-hi -scr_parms string -fixscreen string - -debug_scroll -noxrecord -grab_buster - -nograb_buster -debug_grabs -debug_sel - -pointer_mode n -input_skip n -allinput - -input_eagerly -speeds rd,bw,lat -wmdt string - -debug_pointer -debug_keyboard -defer time - -wait time -extra_fbur n -wait_ui factor - -setdefer n -nowait_bog -slow_fb time - -xrefresh time -nap -nonap - -sb time -readtimeout n -ping n - -nofbpm -fbpm -nodpms - -dpms -forcedpms -clientdpms - -noserverdpms -noultraext -chatwindow - -noxdamage -xd_area A -xd_mem f - -sigpipe string -threads -nothreads - -fs f -gaps n -grow n - -fuzz n -debug_tiles -snapfb - -rawfb string -freqtab file -pipeinput cmd - -macnodim -macnosleep -macnosaver - -macnowait -macwheel n -macnoswap - -macnoresize -maciconanim n -macmenu - -macuskbd -gui [gui-opts] -remote command + -localhost -unixsock str -listen6 str + -nolookup -input string -grabkbd + -grabptr -ungrabboth -grabalways + -viewpasswd string -passwdfile filename -showrfbauth filename + -unixpw [list] -unixpw_nis [list] -unixpw_cmd cmd + -find -finddpy -listdpy + -findauth [disp] -create -xdummy + -xvnc -xvnc_redirect -xdummy_xvfb + -create_xsrv str -svc -svc_xdummy + -svc_xvnc -svc_xdummy_xvfb -xdmsvc + -sshxdmsvc -unixpw_system_greeter -redirect port + -display WAIT:... -vencrypt mode -anontls mode + -sslonly -dhparams file -nossl + -ssl [pem] -ssltimeout n -sslnofail + -ssldir dir -sslverify path -sslCRL path + -sslGenCA [dir] -sslGenCert type name -sslEncKey pem + -sslCertInfo pem -sslDelCert pem -sslScripts + -stunnel [pem] -stunnel3 [pem] -enc cipher:keyfile + -https [port] -httpsredir [port] -http_oneport + -ssh user@host:disp -usepw -storepasswd pass file + -nopw -accept string -afteraccept string + -gone string -users list -noshm + -flipbyteorder -onetile -solid [color] + -blackout string -xinerama -noxinerama + -xtrap -xrandr [mode] -rotate string + -padgeom WxH -o logfile -flag file + -rmflag file -rc filename -norc + -env VAR=VALUE -prog /path/to/x11vnc -h, -help + -?, -opts -V, -version -license + -dbg -q, -quiet -v, -verbose + -bg -modtweak -nomodtweak + -xkb -noxkb -capslock + -skip_lockkeys -noskip_lockkeys -skip_keycodes string + -sloppy_keys -skip_dups -noskip_dups + -add_keysyms -noadd_keysyms -clear_mods + -clear_keys -clear_all -remap string + -norepeat -repeat -nofb + -nobell -nosel -noprimary + -nosetprimary -noclipboard -nosetclipboard + -seldir string -cursor [mode] -nocursor + -cursor_drag -arrow n -noxfixes + -alphacut n -alphafrac fraction -alpharemove + -noalphablend -nocursorshape -cursorpos + -nocursorpos -xwarppointer -noxwarppointer + -always_inject -buttonmap string -nodragging + -ncache n -ncache_cr -ncache_no_moveraise + -ncache_no_dtchange -ncache_no_rootpixmap -ncache_keep_anims + -ncache_old_wm -ncache_pad n -debug_ncache + -wireframe [str] -nowireframe -nowireframelocal + -wirecopyrect mode -nowirecopyrect -debug_wireframe + -scrollcopyrect mode -noscrollcopyrect -scr_area n + -scr_skip list -scr_inc list -scr_keys list + -scr_term list -scr_keyrepeat lo-hi -scr_parms string + -fixscreen string -debug_scroll -noxrecord + -grab_buster -nograb_buster -debug_grabs + -debug_sel -pointer_mode n -input_skip n + -allinput -input_eagerly -speeds rd,bw,lat + -wmdt string -debug_pointer -debug_keyboard + -defer time -wait time -extra_fbur n + -wait_ui factor -setdefer n -nowait_bog + -slow_fb time -xrefresh time -nap + -nonap -sb time -readtimeout n + -ping n -nofbpm -fbpm + -nodpms -dpms -forcedpms + -clientdpms -noserverdpms -noultraext + -chatwindow -noxdamage -xd_area A + -xd_mem f -sigpipe string -threads + -nothreads -fs f -gaps n + -grow n -fuzz n -debug_tiles + -snapfb -rawfb string -freqtab file + -pipeinput cmd -macnodim -macnosleep + -macnosaver -macnowait -macwheel n + -macnoswap -macnoresize -maciconanim n + -macmenu -macuskbd -macnoopengl + -macnorawfb -gui [gui-opts] -remote command -query variable -QD variable -sync -query_retries str -remote_prefix str -noremote -yesremote -unsafe -safer @@ -12416,7 +12491,7 @@ libvncserver-tight-extension options: % x11vnc -help -x11vnc: allow VNC connections to real X11 displays. 0.9.13 lastmod: 2010-12-21 +x11vnc: allow VNC connections to real X11 displays. 0.9.13 lastmod: 2010-12-27 (type "x11vnc -opts" to just list the options.) @@ -13162,6 +13237,20 @@ Options: IPv6: if IPv6 is supported, this option automatically implies the IPv6 loopback address '::1' as well. +-unixsock str Listen on the unix socket (AF_UNIX) 'str' + for connections. This mode is for either local + connections or a tunnel endpoint where one wants the + file permission of the unix socket file to determine + what can connect to it. (This currently requires an + edit to libvnserver/rfbserver.c: comment out lines 310 + and 311, 'close(sock)' and 'return NULL' in rfbserver.c + after the setsockopt() call.) Note that to disable all + tcp listening ports specify '-rfbport 0' and should be + useful with this mode. Example: + mkdir ~/s; chmod 700 ~/s; + x11vnc -unixsock ~/s/mysock -rfbport 0 ... + The SSVNC unix vncviewer can connect to unix sockets. + -listen6 str When in IPv6 listen mode "-6", listen only on the network interface with address "str". It also works for link scope addresses (fe80::219:dbff:fee5:3f92%eth0) @@ -17193,6 +17282,42 @@ er because they have animated fades, etc.) -macuskbd For the native MacOSX server, use the original keystroke insertion code based on a US keyboard. +-macnoopengl For the native MacOSX server, do not use OpenGL for + screen capture, but rather use the original, deprecated + raw memory access method: addr = CGDisplayBaseAddress(). +-macnorawfb For the native MacOSX server, disable the raw memory + address screen capture method. + + MACOSX NOTE: There are some deprecated MacOSX interfaces + to inject keyboard and mouse events and the raw memory + access method is deprecated as well (however, OpenGL + will be preferred if available because it is faster.) + One can force not using any deprecated interfaces at + compile time by setting -DX11VNC_MACOSX_NO_DEPRECATED=1 + in CPPFLAGS. Or to turn them off one by one: + -DX11VNC_MACOSX_NO_DEPRECATED_LOCALEVENTS=1, + -DX11VNC_MACOSX_NO_DEPRECATED_POSTEVENTS=1 or + -DX11VNC_MACOSX_NO_DEPRECATED_FRAMEBUFFER=1 + At run time, for testing and workarounds, one can + disable them by using: + -env X11VNC_MACOSX_NO_DEPRECATED=1 + -env X11VNC_MACOSX_NO_DEPRECATED_LOCALEVENTS=1 + -env X11VNC_MACOSX_NO_DEPRECATED_POSTEVENTS=1 or + -env X11VNC_MACOSX_NO_DEPRECATED_FRAMEBUFFER=1 + Note: When doing either of these for the mouse input + not everything works currently, e.g. double clicks and + wireframing. Also, screen resolution and pixel depth + changes will not be automatically detected unless the + deprecated framebuffer interfaces are allowed. + + Conversely, if you are compiling on an + older machine that does not have some of + the newer interfaces, you may need to specify + -DX11VNC_MACOSX_NO_CGEVENTCREATESCROLLWHEELEVENT + -DX11VNC_MACOSX_NO_CGEVENTCREATEMOUSEEVENT or + -DX11VNC_MACOSX_NO_CGEVENTCREATEKEYBOARDEVENT. Use + -DX11VNC_MACOSX_USE_GETMAINDEVICE to regain the very + old QuickDraw GetMainDevice() interface (rare...) -gui [gui-opts] Start up a simple tcl/tk gui based on the remote control options -remote/-query described below. diff --git a/x11vnc/avahi.c b/x11vnc/avahi.c index 7c646b7..939a34f 100644 --- a/x11vnc/avahi.c +++ b/x11vnc/avahi.c @@ -399,7 +399,6 @@ if (db) fprintf(stderr, "out avahi_reset\n"); } static void avahi_timeout (int sig) { - int i; rfbLog("sig: %d, avahi_cleanup timed out.\n", sig); exit(1); } diff --git a/x11vnc/cleanup.c b/x11vnc/cleanup.c index 232311c..60db819 100644 --- a/x11vnc/cleanup.c +++ b/x11vnc/cleanup.c @@ -190,6 +190,15 @@ void clean_up_exit(int ret) { shutdown_uinput(); + if (unix_sock) { + if (unix_sock_fd >= 0) { + rfbLog("deleting unix sock: %s\n", unix_sock); + close(unix_sock_fd); + unix_sock_fd = -1; + unlink(unix_sock); + } + } + if (! dpy) { /* raw_rb hack */ if (rm_flagfile) { unlink(rm_flagfile); diff --git a/x11vnc/connections.c b/x11vnc/connections.c index abb7a27..d2a9b5c 100644 --- a/x11vnc/connections.c +++ b/x11vnc/connections.c @@ -93,6 +93,7 @@ void adjust_grabs(int grab, int quiet); void check_new_clients(void); int accept_client(rfbClientPtr client); void check_ipv6_listen(long usec); +void check_unix_sock(long usec); int run_user_command(char *cmd, rfbClientPtr client, char *mode, char *input, int len, FILE *output); int check_access(char *addr); @@ -1837,6 +1838,69 @@ void check_ipv6_listen(long usec) { if (usec) {} } +void check_unix_sock(long usec) { + fd_set fds; + struct timeval tv; + int nfds, csock = -1; + rfbClientPtr cl; + int nmax = 0; + char *name; + + if (!unix_sock || unix_sock_fd < 0) { + return; + } + + FD_ZERO(&fds); + if (unix_sock_fd >= 0) { + FD_SET(unix_sock_fd, &fds); + nmax = unix_sock_fd; + } + + tv.tv_sec = 0; + tv.tv_usec = 0; + + nfds = select(nmax+1, &fds, NULL, NULL, &tv); + + if (nfds <= 0) { + return; + } + + if (unix_sock_fd >= 0 && FD_ISSET(unix_sock_fd, &fds)) { + csock = accept_unix(unix_sock_fd); + if (csock < 0) { + return; + } + if (fcntl(csock, F_SETFL, O_NONBLOCK) < 0) { + rfbLogPerror("check_unix_sock: fcntl"); + close(csock); + return; + } + + /* rfbNewClient() will screw us with setsockopt TCP_NODELAY... + you need to comment out in libvncserver/rfbserver.c: + rfbLogPerror("setsockopt failed"); + close(sock); + return NULL; + */ + cl = rfbNewClient(screen, csock); + + if (cl == NULL) { + close(csock); + return; + } + + name = strdup(unix_sock); + + if (name) { + if (cl->host) { + free(cl->host); + } + cl->host = name; + rfbLog("unix sock client: %s\n", name); + } + } +} + /* * For the -connect option: periodically read the file looking for * a connect string. If one is found set client_connect to it. diff --git a/x11vnc/connections.h b/x11vnc/connections.h index a646bc5..3bdeffb 100644 --- a/x11vnc/connections.h +++ b/x11vnc/connections.h @@ -69,6 +69,7 @@ extern void adjust_grabs(int grab, int quiet); extern void check_new_clients(void); extern int accept_client(rfbClientPtr client); extern void check_ipv6_listen(long usec); +extern void check_unix_sock(long usec); extern int run_user_command(char *cmd, rfbClientPtr client, char *mode, char *input, int len, FILE *output); extern int check_access(char *addr); diff --git a/x11vnc/help.c b/x11vnc/help.c index c268b3f..5cd5c12 100644 --- a/x11vnc/help.c +++ b/x11vnc/help.c @@ -810,6 +810,20 @@ void print_help(int mode) { " IPv6: if IPv6 is supported, this option automatically\n" " implies the IPv6 loopback address '::1' as well.\n" "\n" +"-unixsock str Listen on the unix socket (AF_UNIX) 'str'\n" +" for connections. This mode is for either local\n" +" connections or a tunnel endpoint where one wants the\n" +" file permission of the unix socket file to determine\n" +" what can connect to it. (This currently requires an\n" +" edit to libvnserver/rfbserver.c: comment out lines 310\n" +" and 311, 'close(sock)' and 'return NULL' in rfbserver.c\n" +" after the setsockopt() call.) Note that to disable all\n" +" tcp listening ports specify '-rfbport 0' and should be\n" +" useful with this mode. Example:\n" +" mkdir ~/s; chmod 700 ~/s;\n" +" x11vnc -unixsock ~/s/mysock -rfbport 0 ...\n" +" The SSVNC unix vncviewer can connect to unix sockets.\n" +"\n" #if X11VNC_IPV6 "-listen6 str When in IPv6 listen mode \"-6\", listen only on the\n" " network interface with address \"str\". It also works\n" @@ -4851,6 +4865,42 @@ void print_help(int mode) { " because they have animated fades, etc.)\n" "-macuskbd For the native MacOSX server, use the original\n" " keystroke insertion code based on a US keyboard.\n" +"-macnoopengl For the native MacOSX server, do not use OpenGL for\n" +" screen capture, but rather use the original, deprecated\n" +" raw memory access method: addr = CGDisplayBaseAddress().\n" +"-macnorawfb For the native MacOSX server, disable the raw memory\n" +" address screen capture method.\n" +"\n" +" MACOSX NOTE: There are some deprecated MacOSX interfaces\n" +" to inject keyboard and mouse events and the raw memory\n" +" access method is deprecated as well (however, OpenGL\n" +" will be preferred if available because it is faster.)\n" +" One can force not using any deprecated interfaces at\n" +" compile time by setting -DX11VNC_MACOSX_NO_DEPRECATED=1\n" +" in CPPFLAGS. Or to turn them off one by one:\n" +" -DX11VNC_MACOSX_NO_DEPRECATED_LOCALEVENTS=1,\n" +" -DX11VNC_MACOSX_NO_DEPRECATED_POSTEVENTS=1 or\n" +" -DX11VNC_MACOSX_NO_DEPRECATED_FRAMEBUFFER=1\n" +" At run time, for testing and workarounds, one can\n" +" disable them by using:\n" +" -env X11VNC_MACOSX_NO_DEPRECATED=1\n" +" -env X11VNC_MACOSX_NO_DEPRECATED_LOCALEVENTS=1\n" +" -env X11VNC_MACOSX_NO_DEPRECATED_POSTEVENTS=1 or\n" +" -env X11VNC_MACOSX_NO_DEPRECATED_FRAMEBUFFER=1\n" +" Note: When doing either of these for the mouse input\n" +" not everything works currently, e.g. double clicks and\n" +" wireframing. Also, screen resolution and pixel depth\n" +" changes will not be automatically detected unless the\n" +" deprecated framebuffer interfaces are allowed.\n" +"\n" +" Conversely, if you are compiling on an\n" +" older machine that does not have some of\n" +" the newer interfaces, you may need to specify\n" +" -DX11VNC_MACOSX_NO_CGEVENTCREATESCROLLWHEELEVENT\n" +" -DX11VNC_MACOSX_NO_CGEVENTCREATEMOUSEEVENT or\n" +" -DX11VNC_MACOSX_NO_CGEVENTCREATEKEYBOARDEVENT. Use\n" +" -DX11VNC_MACOSX_USE_GETMAINDEVICE to regain the very\n" +" old QuickDraw GetMainDevice() interface (rare...)\n" "\n" "-gui [gui-opts] Start up a simple tcl/tk gui based on the remote\n" " control options -remote/-query described below.\n" diff --git a/x11vnc/inet.c b/x11vnc/inet.c index a7410ee..23a911e 100644 --- a/x11vnc/inet.c +++ b/x11vnc/inet.c @@ -57,6 +57,8 @@ int have_ssh_env(void); char *ipv6_getnameinfo(struct sockaddr *paddr, int addrlen); char *ipv6_getipaddr(struct sockaddr *paddr, int addrlen); int listen6(int port); +int listen_unix(char *file); +int accept_unix(int s); int connect_tcp(char *host, int port); int listen_tcp(int port, in_addr_t iface, int try6); @@ -652,6 +654,62 @@ int listen6(int port) { #endif } +#ifdef LIBVNCSERVER_HAVE_SYS_SOCKET_H +#include +#endif + +int listen_unix(char *file) { +#if !defined(AF_UNIX) || !defined(LIBVNCSERVER_HAVE_SYS_SOCKET_H) + if (sock) {} + return -1; +#else + int s, len; + struct sockaddr_un saun; + + s = socket(AF_UNIX, SOCK_STREAM, 0); + if (s < 0) { + rfbLogPerror("listen_unix: socket"); + return -1; + } + saun.sun_family = AF_UNIX; + strcpy(saun.sun_path, file); + unlink(file); + + len = sizeof(saun.sun_family) + strlen(saun.sun_path); + + if (bind(s, (struct sockaddr *)&saun, len) < 0) { + rfbLogPerror("listen_unix: bind"); + close(s); + return -1; + } + + if (listen(s, 32) < 0) { + rfbLogPerror("listen_unix: listen"); + close(s); + return -1; + } + rfbLog("listening on unix socket: %s fd=%d\n", file, s); + return s; +#endif +} + +int accept_unix(int s) { +#if !defined(AF_UNIX) || !defined(LIBVNCSERVER_HAVE_SYS_SOCKET_H) + if (s) {} + return -1; +#else + int fd, fromlen; + struct sockaddr_un fsaun; + + fd = accept(s, (struct sockaddr *)&fsaun, &fromlen); + if (fd < 0) { + rfbLogPerror("accept_unix: accept"); + return -1; + } + return fd; +#endif +} + int connect_tcp(char *host, int port) { double t0 = dnow(); int fd = -1; diff --git a/x11vnc/inet.h b/x11vnc/inet.h index f74251e..b76dbb4 100644 --- a/x11vnc/inet.h +++ b/x11vnc/inet.h @@ -52,6 +52,8 @@ extern int have_ssh_env(void); extern char *ipv6_getnameinfo(struct sockaddr *paddr, int addrlen); extern char *ipv6_getipaddr(struct sockaddr *paddr, int addrlen); extern int listen6(int port); +extern int listen_unix(char *file); +extern int accept_unix(int s); extern int connect_tcp(char *host, int port); extern int listen_tcp(int port, in_addr_t iface, int try6); diff --git a/x11vnc/macosx.c b/x11vnc/macosx.c index 4b13528..34126f4 100644 --- a/x11vnc/macosx.c +++ b/x11vnc/macosx.c @@ -149,8 +149,6 @@ int macosx_checkevent(XEvent *ev) { } -int dragum(void) {return 1;} - #else void macosx_event_loop(void) { @@ -162,6 +160,12 @@ char *macosx_get_fb_addr(void) { return macosxCG_get_fb_addr(); } +int macosx_opengl_get_width(void); +int macosx_opengl_get_height(void); +int macosx_opengl_get_bpp(void); +int macosx_opengl_get_bps(void); +int macosx_opengl_get_spp(void); + char *macosx_console_guess(char *str, int *fd) { char *q, *in = strdup(str); char *atparms = NULL, *file = NULL; @@ -200,12 +204,22 @@ char *macosx_console_guess(char *str, int *fd) { int w, h, b, bps, dep; unsigned long rm = 0, gm = 0, bm = 0; - w = macosxCG_CGDisplayPixelsWide(); - h = macosxCG_CGDisplayPixelsHigh(); - b = macosxCG_CGDisplayBitsPerPixel(); + if (macosx_read_opengl) { + w = macosx_opengl_get_width(); + h = macosx_opengl_get_height(); + b = macosx_opengl_get_bpp(); - bps = macosxCG_CGDisplayBitsPerSample(); - dep = macosxCG_CGDisplaySamplesPerPixel() * bps; + bps = macosx_opengl_get_bps(); + dep = macosx_opengl_get_spp() * bps; + + } else { + w = macosxCG_CGDisplayPixelsWide(); + h = macosxCG_CGDisplayPixelsHigh(); + b = macosxCG_CGDisplayBitsPerPixel(); + + bps = macosxCG_CGDisplayBitsPerSample(); + dep = macosxCG_CGDisplaySamplesPerPixel() * bps; + } rm = (1 << bps) - 1; gm = (1 << bps) - 1; @@ -223,8 +237,7 @@ char *macosx_console_guess(char *str, int *fd) { /* @66666x66666x32:0xffffffff:... */ atparms = (char *) malloc(200); - sprintf(atparms, "%dx%dx%d:%lx/%lx/%lx", - w, h, b, rm, gm, bm); + sprintf(atparms, "%dx%dx%d:%lx/%lx/%lx", w, h, b, rm, gm, bm); } if (atparms) { int gw, gh, gb; @@ -303,7 +316,7 @@ void macosx_pointer_command(int mask, int x, int y, rfbClientPtr client) { if (0) fprintf(stderr, "about to get all windows: %.4f\n", dnowx()); for (i=0; i < 2; i++) { macosxCGS_get_all_windows(); - fprintf(stderr, "!"); + if (0) fprintf(stderr, "!"); if (macosx_checkevent(NULL)) { break; } @@ -340,7 +353,7 @@ void macosx_key_command(rfbBool down, rfbKeySym keysym, rfbClientPtr client) { } init_key_table(); - macosxCG_key_inject((int) down, (unsigned int) keysym); + macosxCG_keysym_inject((int) down, (unsigned int) keysym); } extern void macosxGCS_poll_pb(void); diff --git a/x11vnc/macosxCG.c b/x11vnc/macosxCG.c index a465493..12041e0 100644 --- a/x11vnc/macosxCG.c +++ b/x11vnc/macosxCG.c @@ -62,7 +62,7 @@ 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); +void macosxCG_keysym_inject(int down, unsigned int keysym); void macosxCG_keycode_inject(int down, int keycode); CGDirectDisplayID displayID = 0; @@ -81,27 +81,31 @@ static void macosxCG_callback(CGRectCount n, const CGRect *rects, void *dum) { } } -int dragum(void) { #if 0 - int x =200, y = 150, dy = 10, i; - CGPoint loc; +> +> if gcc -DHAVE_CONFIG_H -I. -I. -I.. -I/opt/local/include -I/opt/local/include -ObjC -g -O2 -Wall -MT x11vnc-macosxCG.o -MD -MP -MF ".deps/x11vnc-macosxCG.Tpo" -c -o x11vnc-macosxCG.o `test -f 'macosxCG.c' || echo './'`macosxCG.c; \ +> then mv -f ".deps/x11vnc-macosxCG.Tpo" ".deps/x11vnc-macosxCG.Po"; else rm -f ".deps/x11vnc-macosxCG.Tpo"; exit 1; fi +> macosxCG.c:149: warning: CGSetLocalEventsSuppressionInterval is deprecated (declared at /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Headers/CGRemoteOperation.h:373) +> macosxCG.c:150: warning: CGSetLocalEventsFilterDuringSuppressionState is deprecated (declared at /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Headers/CGRemoteOperation.h:366) +> macosxCG.c:153: warning: CGSetLocalEventsFilterDuringSuppressionState is deprecated (declared at /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Headers/CGRemoteOperation.h:366) +> macosxCG.c:244: warning: CGDisplayBaseAddress is deprecated (declared at /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Headers/CGDirectDisplay.h:466) +> macosxCG.c:254: warning: CGDisplayBitsPerPixel is deprecated (declared at /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Headers/CGDirectDisplay.h:517) +> macosxCG.c:257: warning: CGDisplayBitsPerSample is deprecated (declared at /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Headers/CGDirectDisplay.h:522) +> macosxCG.c:260: warning: CGDisplaySamplesPerPixel is deprecated (declared at /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Headers/CGDirectDisplay.h:526) +> macosxCG.c:263: warning: CGDisplayBytesPerRow is deprecated (declared at /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Headers/CGDirectDisplay.h:476) +> macosxCG.c:419: warning: CGPostScrollWheelEvent is deprecated (declared at /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Headers/CGRemoteOperation.h:327) +> macosxCG.c:422: warning: CGPostScrollWheelEvent is deprecated (declared at /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Headers/CGRemoteOperation.h:327) +> macosxCG.c:425: warning: CGPostMouseEvent is deprecated (declared at /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Headers/CGRemoteOperation.h:307) +> macosxCG.c:641: warning: CGPostKeyboardEvent is deprecated (declared at /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Headers/CGRemoteOperation.h:333) +> macosxCG.c:661: warning: CGPostKeyboardEvent is deprecated (declared at /System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreGraphics.framework/Headers/CGRemoteOperation.h:333) +> + +X11VNC_MACOSX_NO_DEPRECATED_LOCALEVENTS +X11VNC_MACOSX_NO_DEPRECATED_POSTEVENTS +X11VNC_MACOSX_NO_DEPRECATED_FRAMEBUFFER +X11VNC_MACOSX_NO_DEPRECATED - CGDirectDisplayID displayID2 = kCGDirectMainDisplay; -#ifdef X11VNC_MACOSX_USE_GETMAINDEVICE - (void) GetMainDevice(); -#endif - - 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); #endif - return 0; -} static int callback_set = 0; extern int nofb; @@ -112,7 +116,7 @@ void macosxCG_refresh_callback_on(void) { } if (! callback_set) { - if (1) macosx_log("macosxCG_callback: register\n"); + if (1) macosx_log("macosxCG_refresh_callback: register\n"); CGRegisterScreenRefreshCallback(macosxCG_callback, NULL); } callback_set = 1; @@ -120,44 +124,93 @@ void macosxCG_refresh_callback_on(void) { void macosxCG_refresh_callback_off(void) { if (callback_set) { - if (1) macosx_log("macosxCG_callback: unregister\n"); + if (1) macosx_log("macosxCG_refresh_callback: unregister\n"); CGUnregisterScreenRefreshCallback(macosxCG_callback, NULL); } callback_set = 0; } extern int macosx_noscreensaver; +extern int macosx_read_opengl; +extern int macosx_read_rawfb; + extern void macosxGCS_initpb(void); extern int macosxCGP_init_dimming(void); extern int macosxCGP_undim(void); extern int macosxCGP_dim_shutdown(void); extern void macosxCGP_screensaver_timer_off(void); extern void macosxCGP_screensaver_timer_on(void); +extern void macosx_opengl_init(void); +extern void macosx_opengl_fini(void); + +int x11vnc_macosx_no_deprecated_localevents = 0; +int x11vnc_macosx_no_deprecated_postevents = 0; +int x11vnc_macosx_no_deprecated_framebuffer = 0; void macosxCG_init(void) { + + x11vnc_macosx_no_deprecated_localevents = 0; + x11vnc_macosx_no_deprecated_postevents = 0; + x11vnc_macosx_no_deprecated_framebuffer = 0; + + if (getenv("X11VNC_MACOSX_NO_DEPRECATED_LOCALEVENTS") || getenv("X11VNC_MACOSX_NO_DEPRECATED")) { + x11vnc_macosx_no_deprecated_localevents = 1; + } + if (getenv("X11VNC_MACOSX_NO_DEPRECATED_POSTEVENTS") || getenv("X11VNC_MACOSX_NO_DEPRECATED")) { + x11vnc_macosx_no_deprecated_postevents = 1; + } + if (getenv("X11VNC_MACOSX_NO_DEPRECATED_FRAMEBUFFER") || getenv("X11VNC_MACOSX_NO_DEPRECATED")) { + x11vnc_macosx_no_deprecated_framebuffer = 1; + } + if (displayID == 0) { macosx_log("macosxCG_init: initializing display.\n"); -#if 0 - dragum(); -#endif displayID = kCGDirectMainDisplay; #ifdef X11VNC_MACOSX_USE_GETMAINDEVICE + /* not sure this ever did anything. */ (void) GetMainDevice(); #endif + if (displayID == 0) { + macosx_log("macosxCG_init: could not get kCGDirectMainDisplay / CGMainDisplayID() display.\n"); + exit(1); + } + +#if X11VNC_MACOSX_NO_DEPRECATED_LOCALEVENTS || X11VNC_MACOSX_NO_DEPRECATED + macosx_log("NO_DEPRECATED_LOCALEVENTS: not calling CGSetLocalEventsSuppressionInterval()\n"); + macosx_log("NO_DEPRECATED_LOCALEVENTS: not calling CGSetLocalEventsFilterDuringSupressionState()\n"); +#else + if (!x11vnc_macosx_no_deprecated_localevents) { + CGSetLocalEventsSuppressionInterval(0.0); + CGSetLocalEventsFilterDuringSupressionState( + kCGEventFilterMaskPermitAllEvents, + kCGEventSupressionStateSupressionInterval); + CGSetLocalEventsFilterDuringSupressionState( + kCGEventFilterMaskPermitAllEvents, + kCGEventSupressionStateRemoteMouseDrag); + } else { + macosx_log("NO_DEPRECATED_LOCALEVENTS: not calling CGSetLocalEventsSuppressionInterval()\n"); + macosx_log("NO_DEPRECATED_LOCALEVENTS: not calling CGSetLocalEventsFilterDuringSupressionState()\n"); + } +#endif - CGSetLocalEventsSuppressionInterval(0.0); - CGSetLocalEventsFilterDuringSupressionState( - kCGEventFilterMaskPermitAllEvents, - kCGEventSupressionStateSupressionInterval); - CGSetLocalEventsFilterDuringSupressionState( - kCGEventFilterMaskPermitAllEvents, - kCGEventSupressionStateRemoteMouseDrag); + macosx_opengl_init(); + + if (!macosx_read_opengl) { + char *addr = macosxCG_get_fb_addr(); + if (addr == NULL) { + macosx_log("macosxCG_init: could not get raw framebuffer address / CGDisplayBaseAddress().\n"); + exit(1); + } + macosx_read_rawfb = 1; + macosx_log("macosxCG_init: using raw framebuffer address for screen capture.\n"); + } macosxCGP_init_dimming(); if (macosx_noscreensaver) { macosxCGP_screensaver_timer_on(); } + macosxGCS_initpb(); } } @@ -168,6 +221,8 @@ void macosxCG_fini(void) { macosxCGP_screensaver_timer_off(); } macosxCG_refresh_callback_off(); + macosx_opengl_fini(); + displayID = 0; } extern int dpy_x, dpy_y, bpp, wdpy_x, wdpy_y; @@ -187,6 +242,7 @@ extern void clean_up_exit(int ret); void macosxCG_event_loop(void) { OSStatus rc; int nbpp; + static int nbpp_save = -1; macosxGCS_poll_pb(); if (nofb) { @@ -203,18 +259,22 @@ void macosxCG_event_loop(void) { nbpp = macosxCG_CGDisplayBitsPerPixel(); + if (nbpp_save < 0) { + nbpp_save = nbpp; + } - if (nbpp > 0 && nbpp != bpp) { + if (nbpp > 0 && nbpp != nbpp_save) { + nbpp_save = nbpp; if (macosx_resize) { do_new_fb(1); } - } else if (wdpy_x != (int) CGDisplayPixelsWide(displayID)) { - if (wdpy_y != (int) CGDisplayPixelsHigh(displayID)) { + } else if (wdpy_x != macosxCG_CGDisplayPixelsWide()) { + if (wdpy_y != macosxCG_CGDisplayPixelsHigh()) { if (macosx_wait_for_switch) { int cnt = 0; while (1) { - if(CGDisplayPixelsWide(displayID) > 0) { - if(CGDisplayPixelsHigh(displayID) > 0) { + if(macosxCG_CGDisplayPixelsWide() > 0) { + if(macosxCG_CGDisplayPixelsHigh() > 0) { usleep(500*1000); break; } @@ -225,8 +285,8 @@ void macosxCG_event_loop(void) { } sleep(1); } - if (wdpy_x == (int) CGDisplayPixelsWide(displayID)) { - if (wdpy_y == (int) CGDisplayPixelsHigh(displayID)) { + if (wdpy_x == macosxCG_CGDisplayPixelsWide()) { + if (wdpy_y == macosxCG_CGDisplayPixelsHigh()) { macosx_log("we're back...\n"); return; } @@ -237,32 +297,100 @@ void macosxCG_event_loop(void) { } } } + if (nbpp > 0) { + nbpp_save = nbpp; + } } +extern int macosx_no_rawfb; +extern int macosx_read_opengl; +extern int macosx_opengl_get_width(); +extern int macosx_opengl_get_height(); +extern int macosx_opengl_get_bpp(); +extern int macosx_opengl_get_bps(); +extern int macosx_opengl_get_spp(); + +#if X11VNC_MACOSX_NO_DEPRECATED_FRAMEBUFFER || X11VNC_MACOSX_NO_DEPRECATED + char *macosxCG_get_fb_addr(void) { - macosxCG_init(); + return NULL; +} +int macosxCG_CGDisplayPixelsWide(void) { + return macosx_opengl_get_width(); +} +int macosxCG_CGDisplayPixelsHigh(void) { + return macosx_opengl_get_height(); +} +int macosxCG_CGDisplayBitsPerPixel(void) { + return macosx_opengl_get_bpp(); +} +int macosxCG_CGDisplayBitsPerSample(void) { + return macosx_opengl_get_bps(); +} +int macosxCG_CGDisplaySamplesPerPixel(void) { + return macosx_opengl_get_spp(); +} +int macosxCG_CGDisplayBytesPerRow(void) { + return macosx_opengl_get_width() * macosx_opengl_get_bpp() / 8; +} + +#else + +char *macosxCG_get_fb_addr(void) { + if (x11vnc_macosx_no_deprecated_framebuffer) { + macosx_log("CGDisplayBaseAddress disabled by env. var\n"); + return NULL; + } + if (macosx_no_rawfb) { + macosx_log("CGDisplayBaseAddress disabled by user.\n"); + return NULL; + } + if (macosx_read_opengl) { + macosx_log("CGDisplayBaseAddress disabled by OpenGL.\n"); + return NULL; + } return (char *) CGDisplayBaseAddress(displayID); } int macosxCG_CGDisplayPixelsWide(void) { + if ((0 && macosx_read_opengl) || x11vnc_macosx_no_deprecated_framebuffer) { + return macosx_opengl_get_width(); + } return (int) CGDisplayPixelsWide(displayID); } int macosxCG_CGDisplayPixelsHigh(void) { + if ((0 && macosx_read_opengl) || x11vnc_macosx_no_deprecated_framebuffer) { + return macosx_opengl_get_height(); + } return (int) CGDisplayPixelsHigh(displayID); } int macosxCG_CGDisplayBitsPerPixel(void) { + if ((0 && macosx_read_opengl) || x11vnc_macosx_no_deprecated_framebuffer) { + return macosx_opengl_get_bpp(); + } return (int) CGDisplayBitsPerPixel(displayID); } int macosxCG_CGDisplayBitsPerSample(void) { + if (macosx_read_opengl || x11vnc_macosx_no_deprecated_framebuffer) { + return macosx_opengl_get_bps(); + } return (int) CGDisplayBitsPerSample(displayID); } int macosxCG_CGDisplaySamplesPerPixel(void) { + if (macosx_read_opengl || x11vnc_macosx_no_deprecated_framebuffer) { + return macosx_opengl_get_spp(); + } return (int) CGDisplaySamplesPerPixel(displayID); } int macosxCG_CGDisplayBytesPerRow(void) { + if (macosx_read_opengl || x11vnc_macosx_no_deprecated_framebuffer) { + return macosx_opengl_get_width() * macosx_opengl_get_bpp()/8; + } return (int) CGDisplayBytesPerRow(displayID);; } +#endif + typedef int CGSConnectionRef; static CGSConnectionRef conn = 0; extern CGError CGSNewConnection(void*, CGSConnectionRef*); @@ -358,6 +486,8 @@ int macosxCG_get_cursor(void) { } } + /* XXX all of these interfaces are undocumented. */ + cursor_seed = CGSCurrentCursorSeed(); if (last_idx && cursor_seed == last_cursor_seed) { if (now < last_fetch + 2) { @@ -376,6 +506,10 @@ int macosxCG_get_cursor(void) { err = CGSGetGlobalCursorData(conn, data, &datasize, &row_bytes, &rect, &hot, &cdepth, &comps, &bpcomp); +#if 0 + fprintf(stderr, "datasize: %d row_bytes: %d cdepth: %d comps: %d bpcomp: %d w: %d h: %d\n", + datasize, row_bytes, cdepth, comps, bpcomp, (int) rect.size.width, (int) rect.size.height); +#endif if (err != kCGErrorSuccess) { macosx_log("CGSGetGlobalCursorData error\n"); return which; @@ -385,6 +519,21 @@ int macosxCG_get_cursor(void) { cdepth = 32; } + if (sizeof(long) == 8 && comps * bpcomp <= 32) { + /* pad it out to unsigned long array size (like xfixes) */ + int i; + unsigned char *dsave; + unsigned char *data64 = (unsigned char*) malloc(2 *datasize); + unsigned int *uI = (unsigned int *) data; + unsigned long *uL = (unsigned long *) data64; + for (i=0; i < datasize/4; i++) { + uL[i] = uI[i]; + } + dsave = data; + data = data64; + free(dsave); + } + which = store_cursor(cursor_seed, (unsigned long*) data, (int) rect.size.width, (int) rect.size.height, cdepth, (int) hot.x, (int) hot.y); @@ -396,12 +545,137 @@ extern int macosx_mouse_wheel_speed; extern int macosx_swap23; extern int off_x, coff_x, off_y, coff_y; +extern int debug_pointer; + +static void CGPostScrollWheelEvent_wr(CGWheelCount wheel_count, int wheel_distance) { + static int post_mode = -1, mcnt = 0; + +#if !X11VNC_MACOSX_NO_DEPRECATED_POSTEVENTS && !X11VNC_MACOSX_NO_DEPRECATED + if (post_mode < 0) { + post_mode = 1; + if (getenv("X11VNC_MACOSX_NO_DEPRECATED_POSTEVENTS") || getenv("X11VNC_MACOSX_NO_DEPRECATED")) { + post_mode = 0; + } + } + + if (post_mode) { + if (mcnt++ < 10 || debug_pointer) fprintf(stderr, "CGPostScrollWheelEvent()\n"); + CGPostScrollWheelEvent(wheel_count, wheel_distance); + } else +#endif + { + /* XXX 10.5 and later */ +#ifndef X11VNC_MACOSX_NO_CGEVENTCREATESCROLLWHEELEVENT + CGEventRef event; + event = CGEventCreateScrollWheelEvent(NULL, kCGScrollEventUnitLine, wheel_count, wheel_distance); + if (event != NULL) { + CGEventPost(kCGHIDEventTap, event); + CFRelease(event); + } +#endif + if (mcnt++ < 10 || debug_pointer) fprintf(stderr, "CGEventCreateScrollWheelEvent()\n"); + } +} + +static void CGPostMouseEvent_wr(CGPoint loc, int update, int count, int d1, int d2, int d3, int p1, int p2, int p3) { + static int post_mode = -1, mcnt = 0; + +#if !X11VNC_MACOSX_NO_DEPRECATED_POSTEVENTS && !X11VNC_MACOSX_NO_DEPRECATED + if (post_mode < 0) { + post_mode = 1; + if (getenv("X11VNC_MACOSX_NO_DEPRECATED_POSTEVENTS") || getenv("X11VNC_MACOSX_NO_DEPRECATED")) { + post_mode = 0; + } + } + + if (post_mode) { + if (mcnt++ < 10 || debug_pointer) fprintf(stderr, "CGPostMouseEvent()\n"); + CGPostMouseEvent(loc, update, count, d1, d2, d3); + } else +#endif + { + /* XXX 10.4 and later */ +#ifndef X11VNC_MACOSX_NO_CGEVENTCREATEMOUSEEVENT + CGEventRef event; + static int xp = -1, yp; + + if (xp == -1) { + xp = loc.x; + yp = loc.y; + } + if (xp != loc.x || yp != loc.y) { + int moved = 0; + if (p1 && p1 == d1) { + event = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDragged, loc, 0); + if (event != NULL) { + moved = 1; + CGEventPost(kCGHIDEventTap, event); + CFRelease(event); + } + } + if (p3 && p3 == d3) { + event = CGEventCreateMouseEvent(NULL, kCGEventOtherMouseDragged, loc, 0); + if (event != NULL) { + moved = 1; + CGEventPost(kCGHIDEventTap, event); + CFRelease(event); + } + } + if (p2 && p2 == d2) { + event = CGEventCreateMouseEvent(NULL, kCGEventRightMouseDragged, loc, 0); + if (event != NULL) { + moved = 1; + CGEventPost(kCGHIDEventTap, event); + CFRelease(event); + } + } + if (!moved) { + event = CGEventCreateMouseEvent(NULL, kCGEventMouseMoved, loc, 0); + if (event != NULL) { + CGEventPost(kCGHIDEventTap, event); + CFRelease(event); + } + } + } + xp = loc.x; + yp = loc.y; + if (p1 != d1) { + CGEventType type = (!p1 && d1) ? kCGEventLeftMouseDown : kCGEventLeftMouseUp; + event = CGEventCreateMouseEvent(NULL, type, loc, 0); + if (event != NULL) { + CGEventPost(kCGHIDEventTap, event); + CFRelease(event); + } + } + if (p3 != d3) { + CGEventType type = (!p3 && d3) ? kCGEventOtherMouseDown : kCGEventOtherMouseUp; + event = CGEventCreateMouseEvent(NULL, type, loc, kCGMouseButtonCenter); + if (event != NULL) { + CGEventPost(kCGHIDEventTap, event); + CFRelease(event); + } + } + if (p2 != d2) { + CGEventType type = (!p2 && d2) ? kCGEventRightMouseDown : kCGEventRightMouseUp; + event = CGEventCreateMouseEvent(NULL, type, loc, 0); + if (event != NULL) { + CGEventPost(kCGHIDEventTap, event); + CFRelease(event); + } + } +#endif + if (mcnt++ < 10 || debug_pointer) fprintf(stderr, "CGEventCreateMouseEvent()\n"); + } +} + void macosxCG_pointer_inject(int mask, int x, int y) { int swap23 = macosx_swap23; int s1 = 0, s2 = 1, s3 = 2, s4 = 3, s5 = 4; CGPoint loc; int wheel_distance = macosx_mouse_wheel_speed; static int cnt = 0; + static int first = 1, prev1 = 0, prev2 = 0, prev3 = 0; + int curr1, curr2, curr3; if (swap23) { s2 = 2; @@ -416,17 +690,28 @@ void macosxCG_pointer_inject(int mask, int x, int y) { } if ((mask & (1 << s4))) { - CGPostScrollWheelEvent(1, wheel_distance); + CGPostScrollWheelEvent_wr(1, wheel_distance); } if ((mask & (1 << s5))) { - CGPostScrollWheelEvent(1, -wheel_distance); + CGPostScrollWheelEvent_wr(1, -wheel_distance); } - - CGPostMouseEvent(loc, TRUE, 3, - (mask & (1 << s1)) ? TRUE : FALSE, - (mask & (1 << s2)) ? TRUE : FALSE, - (mask & (1 << s3)) ? TRUE : FALSE - ); + + curr1 = (mask & (1 << s1)) ? TRUE : FALSE; + curr2 = (mask & (1 << s2)) ? TRUE : FALSE; + curr3 = (mask & (1 << s3)) ? TRUE : FALSE; + + if (first) { + prev1 = curr1; + prev2 = curr2; + prev3 = curr3; + first = 0; + } + + CGPostMouseEvent_wr(loc, TRUE, 3, curr1, curr2, curr3, prev1, prev2, prev3); + + prev1 = curr1; + prev2 = curr2; + prev3 = curr3; } #define keyTableSize 0xFFFF @@ -634,14 +919,48 @@ void macosxCG_init_key_table(void) { extern void init_key_table(void); extern int macosx_us_kbd; +extern int debug_keyboard; + +void CGPostKeyboardEvent_wr(CGCharCode keyChar, CGKeyCode keyCode, int down) { + static int post_mode = -1, mcnt = 0; + +#if !X11VNC_MACOSX_NO_DEPRECATED_POSTEVENTS && !X11VNC_MACOSX_NO_DEPRECATED + if (post_mode < 0) { + post_mode = 1; + if (getenv("X11VNC_MACOSX_NO_DEPRECATED_POSTEVENTS") || getenv("X11VNC_MACOSX_NO_DEPRECATED")) { + post_mode = 0; + } + } + + if (post_mode) { + if (mcnt++ < 10 || debug_keyboard) fprintf(stderr, "CGPostKeyboardEvent(keyChar=%d, keyCode=%d, down=%d)\n", keyChar, keyCode, down); + CGPostKeyboardEvent(keyChar, keyCode, down); + } else +#endif + { + /* XXX 10.4 and later */ +#ifndef X11VNC_MACOSX_NO_CGEVENTCREATEKEYBOARDEVENT + CGEventRef event; + event = CGEventCreateKeyboardEvent(NULL, keyCode, down); + if (event != NULL) { + CGEventPost(kCGHIDEventTap, event); + CFRelease(event); + } +#endif + if (mcnt++ < 10 || debug_keyboard) fprintf(stderr, "CGEventCreateKeyboardEvent(NULL, keyCode=%d, down=%d)\n", keyCode, down); + } +} + void macosxCG_keycode_inject(int down, int keycode) { CGKeyCode keyCode = (CGKeyCode) keycode; CGCharCode keyChar = 0; - CGPostKeyboardEvent(keyChar, keyCode, down); + if (debug_keyboard) fprintf(stderr, "macosxCG_keycode_inject(down=%d, keycode=%d)\n", down, keycode); + + CGPostKeyboardEvent_wr(keyChar, keyCode, down); } -void macosxCG_key_inject(int down, unsigned int keysym) { +void macosxCG_keysym_inject(int down, unsigned int keysym) { CGKeyCode keyCode = keyTable[(unsigned short)keysym]; CGCharCode keyChar = 0; #if 0 @@ -651,14 +970,18 @@ void macosxCG_key_inject(int down, unsigned int keysym) { init_key_table(); + if (debug_keyboard) fprintf(stderr, "macosxCG_keysym_inject(down=%d, keysym=%d)\n", down, (int) keysym); + if (keysym < 0xFF && macosx_us_kbd) { keyChar = (CGCharCode) keysym; + if (debug_keyboard) fprintf(stderr, "macosxCG_keysym_inject keyChar=>%d\n", (int) keyChar); } if (keyCode == 0xFFFF) { return; } macosxCGP_undim(); - CGPostKeyboardEvent(keyChar, keyCode, down); + + CGPostKeyboardEvent_wr(keyChar, keyCode, down); } #endif /* __APPLE__ */ diff --git a/x11vnc/macosxCG.h b/x11vnc/macosxCG.h index 60beab1..fb9e497 100644 --- a/x11vnc/macosxCG.h +++ b/x11vnc/macosxCG.h @@ -51,7 +51,7 @@ extern void macosxCG_pointer_inject(int mask, int x, int y); extern int macosxCG_get_cursor_pos(int *x, int *y); extern int macosxCG_get_cursor(void); extern void macosxCG_init_key_table(void); -extern void macosxCG_key_inject(int down, unsigned int keysym); +extern void macosxCG_keysym_inject(int down, unsigned int keysym); extern void macosxCG_keycode_inject(int down, int keycode); extern void macosxCG_refresh_callback_off(void); diff --git a/x11vnc/macosx_opengl.c b/x11vnc/macosx_opengl.c new file mode 100644 index 0000000..9788279 --- /dev/null +++ b/x11vnc/macosx_opengl.c @@ -0,0 +1,176 @@ +/* + Copyright (C) 2002-2010 Karl J. Runge + All rights reserved. + +This file is part of x11vnc. + +x11vnc is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +x11vnc is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with x11vnc; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA +or see . + +In addition, as a special exception, Karl J. Runge +gives permission to link the code of its release of x11vnc with the +OpenSSL project's "OpenSSL" library (or with modified versions of it +that use the same license as the "OpenSSL" library), and distribute +the linked executables. You must obey the GNU General Public License +in all respects for all of the code used other than "OpenSSL". If you +modify this file, you may extend this exception to your version of the +file, but you are not obligated to do so. If you do not wish to do +so, delete this exception statement from your version. +*/ + +/* -- macosx_opengl.c -- */ + +#if (defined(__MACH__) && defined(__APPLE__)) + +#include +#include + +#include +#if LIBVNCSERVER_HAVE_MACOSX_OPENGL_H +#include +#include +#endif + +extern int macosx_no_opengl, macosx_read_opengl; +extern CGDirectDisplayID displayID; + +static CGLContextObj glContextObj; + +int macosx_opengl_width = 0; +int macosx_opengl_height = 0; +int macosx_opengl_bpp = 0; + +int macosx_opengl_get_width(void) { + GLint viewport[4]; + + glGetIntegerv(GL_VIEWPORT, viewport); + return (int) viewport[2]; +} + +int macosx_opengl_get_height(void) { + GLint viewport[4]; + + glGetIntegerv(GL_VIEWPORT, viewport); + return (int) viewport[3]; +} + +int macosx_opengl_get_bpp(void) { + return 32; +} + +int macosx_opengl_get_bps(void) { + return 8; +} + +int macosx_opengl_get_spp(void) { + return 3; +} + +void macosx_opengl_init(void) { + CGLPixelFormatObj pixelFormatObj; + GLint numPixelFormats; + CGLPixelFormatAttribute attribs[] = { + kCGLPFAFullScreen, + kCGLPFADisplayMask, + 0, + 0 + }; + + if (macosx_no_opengl) { + return; + } + + attribs[2] = CGDisplayIDToOpenGLDisplayMask(displayID); + + CGLChoosePixelFormat(attribs, &pixelFormatObj, &numPixelFormats); + if (pixelFormatObj == NULL) { + rfbLog("macosx_opengl_init: CGLChoosePixelFormat failed. Not using OpenGL.\n"); + return; + } + + CGLCreateContext(pixelFormatObj, NULL, &glContextObj); + CGLDestroyPixelFormat(pixelFormatObj); + + if (glContextObj == NULL) { + rfbLog("macosx_opengl_init: CGLCreateContext failed. Not using OpenGL.\n"); + return; + } + + CGLSetCurrentContext(glContextObj); + CGLSetFullScreen(glContextObj); + + macosx_opengl_width = macosx_opengl_get_width(); + macosx_opengl_height = macosx_opengl_get_height(); + + macosx_opengl_bpp = macosx_opengl_get_bpp(); + + glFinish(); + + glPixelStorei(GL_PACK_ALIGNMENT, 4); + glPixelStorei(GL_PACK_ROW_LENGTH, 0); + glPixelStorei(GL_PACK_SKIP_ROWS, 0); + glPixelStorei(GL_PACK_SKIP_PIXELS, 0); + + rfbLog("macosx_opengl_init: Using OpenGL for screen capture.\n"); + macosx_read_opengl = 1; +} + +void macosx_opengl_fini(void) { + if (!macosx_read_opengl) { + return; + } + CGLSetCurrentContext(NULL); + CGLClearDrawable(glContextObj); + CGLDestroyContext(glContextObj); +} + +void macosx_copy_opengl(char *dest, int x, int y, unsigned int w, unsigned int h) { + int yflip = macosx_opengl_height - y - h; + + CGLSetCurrentContext(glContextObj); + + glReadPixels((GLint) x, (GLint) yflip, (int) w, (int) h, + GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, dest); + + if (h > 1) { + static char *pbuf = NULL; + static int buflen = 0; + int top = 0, bot = h - 1, rowlen = w * macosx_opengl_bpp/8; + char *ptop, *pbot; + + if (rowlen > buflen || buflen == 0) { + buflen = rowlen + 128; + if (pbuf) { + free(pbuf); + } + pbuf = (char *) malloc(buflen); + } + while (top < bot) { + ptop = dest + top * rowlen; + pbot = dest + bot * rowlen; + memcpy(pbuf, ptop, rowlen); + memcpy(ptop, pbot, rowlen); + memcpy(pbot, pbuf, rowlen); + top++; + bot--; + } + } +} + + +#else + +#endif /* __APPLE__ */ + diff --git a/x11vnc/macosx_opengl.h b/x11vnc/macosx_opengl.h new file mode 100644 index 0000000..5531a0c --- /dev/null +++ b/x11vnc/macosx_opengl.h @@ -0,0 +1,41 @@ +/* + Copyright (C) 2002-2010 Karl J. Runge + All rights reserved. + +This file is part of x11vnc. + +x11vnc is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +x11vnc is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with x11vnc; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA +or see . + +In addition, as a special exception, Karl J. Runge +gives permission to link the code of its release of x11vnc with the +OpenSSL project's "OpenSSL" library (or with modified versions of it +that use the same license as the "OpenSSL" library), and distribute +the linked executables. You must obey the GNU General Public License +in all respects for all of the code used other than "OpenSSL". If you +modify this file, you may extend this exception to your version of the +file, but you are not obligated to do so. If you do not wish to do +so, delete this exception statement from your version. +*/ + +#ifndef _X11VNC_MACOSX_OPENGL_H +#define _X11VNC_MACOSX_OPENGL_H + +/* -- macosx_opengl.h -- */ + +extern void macosx_opengl_init(void); + + +#endif /* _X11VNC_MACOSX_OPENGL_H */ diff --git a/x11vnc/options.c b/x11vnc/options.c index 890a8a4..ab119b6 100644 --- a/x11vnc/options.c +++ b/x11vnc/options.c @@ -134,6 +134,8 @@ int no_external_cmds = 1; /* cannot be turned back on. */ char *allowed_external_cmds = NULL; int started_as_root = 0; int host_lookup = 1; +char *unix_sock = NULL; +int unix_sock_fd = -1; #if X11VNC_LISTEN6 int ipv6_listen = 1; /* -6 / -no6 */ int got_ipv6_listen = 1; @@ -217,6 +219,10 @@ int macosx_console = 0; int macosx_swap23 = 1; int macosx_resize = 1; int macosx_icon_anim_time = 450; +int macosx_no_opengl = 0; +int macosx_no_rawfb = 0; +int macosx_read_opengl = 0; +int macosx_read_rawfb = 0; unsigned long subwin = 0x0; /* -id, -sid */ int subwin_wait_mapped = 0; diff --git a/x11vnc/options.h b/x11vnc/options.h index cfe0cdd..609f4ce 100644 --- a/x11vnc/options.h +++ b/x11vnc/options.h @@ -115,6 +115,8 @@ extern int no_external_cmds; extern char *allowed_external_cmds; extern int started_as_root; extern int host_lookup; +extern char *unix_sock; +extern int unix_sock_fd; extern int ipv6_listen; extern int got_ipv6_listen; extern int ipv6_listen_fd; @@ -184,6 +186,10 @@ extern int macosx_console; extern int macosx_swap23; extern int macosx_resize; extern int macosx_icon_anim_time; +extern int macosx_no_opengl; +extern int macosx_no_rawfb; +extern int macosx_read_opengl; +extern int macosx_read_rawfb; extern unsigned long subwin; extern int subwin_wait_mapped; diff --git a/x11vnc/rates.c b/x11vnc/rates.c index 0af5e42..ee9ca05 100644 --- a/x11vnc/rates.c +++ b/x11vnc/rates.c @@ -240,6 +240,13 @@ void initialize_speeds(void) { if (! speeds_read_rate) { int n = 0; double dt, timer; +#ifdef MACOSX + if (macosx_console && macosx_read_opengl && fullscreen) { + copy_image(fullscreen, 0, 0, 0, 0); + usleep(10 * 1000); + } +#endif + dtime0(&timer); if (fullscreen) { copy_image(fullscreen, 0, 0, 0, 0); diff --git a/x11vnc/screen.c b/x11vnc/screen.c index 067d144..d0851f6 100644 --- a/x11vnc/screen.c +++ b/x11vnc/screen.c @@ -1028,6 +1028,11 @@ void do_new_fb(int reset_mem) { settle_clients(1); } +#ifdef MACOSX + if (macosx_console) { + macosxCG_fini(); + } +#endif if (reset_mem == 1) { /* reset_mem == 2 is a hack for changing users... */ clean_shm(0); @@ -1694,7 +1699,7 @@ if (db) fprintf(stderr, "initialize_raw_fb reset\n"); raw_fb_addr = NULL; } #endif - + if (raw_fb_addr || raw_fb_seek) { if (raw_fb_shm) { shmdt(raw_fb_addr); @@ -3196,6 +3201,9 @@ void initialize_screen(int *argc, char **argv, XImage *fb) { if (screen && http_dir) { http_connections(1); } + if (unix_sock) { + unix_sock_fd = listen_unix(unix_sock); + } } else { /* set set frameBuffer member below. */ rfbLog("rfbNewFramebuffer(0x%x, 0x%x, %d, %d, %d, %d, %d)\n", diff --git a/x11vnc/ssltools.h b/x11vnc/ssltools.h index 6557a9b..b4ad7d0 100644 --- a/x11vnc/ssltools.h +++ b/x11vnc/ssltools.h @@ -1010,12 +1010,20 @@ char find_display[] = " else\n" " skip=\":$skip\"\n" " fi\n" +" skip2=`echo \"$skip\" | sed -e 's/\\.[0-9][0-9]*$//'`\n" +"\n" " if echo \"$skip\" | grep \":$dtry1\\>\" > /dev/null; then\n" " mat=1\n" " break\n" " elif echo \"$skip\" | grep \":$dtry2\\>\" > /dev/null; then\n" " mat=1\n" " break\n" +" elif [ \"X$skip2\" = \"X:$dtry1\" ]; then\n" +" mat=1\n" +" break\n" +" elif [ \"X$skip2\" = \"X:$dtry2\" ]; then\n" +" mat=1\n" +" break\n" " fi\n" " done\n" " if [ \"X$X11VNC_SKIP_DISPLAY_NEGATE\" = \"X\" ]; then\n" @@ -2402,14 +2410,24 @@ char create_display[] = "\n" " if echo \"$curr_try\" | grep -i '^Xdummy\\>' > /dev/null; then\n" " try_Xdummy\n" +" elif echo \"$curr_try\" | grep -i '^Xdummy$' > /dev/null; then\n" +" try_Xdummy\n" " elif echo \"$curr_try\" | grep -i '^Xvfb\\>' > /dev/null; then\n" " try_Xvfb\n" +" elif echo \"$curr_try\" | grep -i '^Xvfb$' > /dev/null; then\n" +" try_Xvfb\n" " elif echo \"$curr_try\" | grep -i '^Xvnc\\>' > /dev/null; then\n" " try_Xvnc\n" +" elif echo \"$curr_try\" | grep -i '^Xvnc$' > /dev/null; then\n" +" try_Xvnc\n" " elif echo \"$curr_try\" | grep -i '^Xsrv\\>' > /dev/null; then\n" " try_Xsrv\n" +" elif echo \"$curr_try\" | grep -i '^Xsrv$' > /dev/null; then\n" +" try_Xsrv\n" " elif echo \"$curr_try\" | grep -i '^X\\>' > /dev/null; then\n" " try_X\n" +" elif echo \"$curr_try\" | grep -i '^X$' > /dev/null; then\n" +" try_X\n" " fi\n" " if [ \"X$result\" = \"X1\" ]; then\n" " echo \"DISPLAY=:$N\"\n" diff --git a/x11vnc/util.c b/x11vnc/util.c index 9c8c294..80b1607 100644 --- a/x11vnc/util.c +++ b/x11vnc/util.c @@ -594,6 +594,9 @@ int rfbPE(long usec) { if (ipv6_listen) { check_ipv6_listen(usec); } + if (unix_sock) { + check_unix_sock(usec); + } if (check_rate != 0) { if (check_rate < 0) { if (getenv("CHECK_RATE")) { @@ -713,9 +716,31 @@ char *choose_title(char *display) { if (display == NULL) { display = getenv("DISPLAY"); } + +#ifdef MACOSX + if (display == NULL || strstr(display, "/tmp/") == display) { + char *u = get_user_name(); + char *th = this_host(); + if (strlen(u) > MAXN/4) { + u = "someone"; + } + strcpy(title, u); + if (th == NULL && UT.nodename) { + th = UT.nodename; + } + if (th) { + strcat(title, "@"); + strncat(title, th, MAXN - strlen(title)); + } + return title; + } +#endif + if (display == NULL) { return title; } + + /* use display: */ title[0] = '\0'; if (display[0] == ':') { char *th = this_host(); diff --git a/x11vnc/x11vnc.1 b/x11vnc/x11vnc.1 index 08a2cd8..d4dd0a2 100644 --- a/x11vnc/x11vnc.1 +++ b/x11vnc/x11vnc.1 @@ -2,7 +2,7 @@ .TH X11VNC "1" "December 2010" "x11vnc " "User Commands" .SH NAME x11vnc - allow VNC connections to real X11 displays - version: 0.9.13, lastmod: 2010-12-21 + version: 0.9.13, lastmod: 2010-12-27 .SH SYNOPSIS .B x11vnc [OPTION]... @@ -879,6 +879,22 @@ or plan to use remote control: \fB-R\fR connect:host), use IPv6: if IPv6 is supported, this option automatically implies the IPv6 loopback address '::1' as well. .PP +\fB-unixsock\fR \fIstr\fR +.IP +Listen on the unix socket (AF_UNIX) 'str' +for connections. This mode is for either local +connections or a tunnel endpoint where one wants the +file permission of the unix socket file to determine +what can connect to it. (This currently requires an +edit to libvnserver/rfbserver.c: comment out lines 310 +and 311, 'close(sock)' and 'return NULL' in rfbserver.c +after the setsockopt() call.) Note that to disable all +tcp listening ports specify '-rfbport 0' and should be +useful with this mode. Example: +mkdir ~/s; chmod 700 ~/s; +x11vnc \fB-unixsock\fR ~/s/mysock \fB-rfbport\fR 0 ... +The SSVNC unix vncviewer can connect to unix sockets. +.PP \fB-listen6\fR \fIstr\fR .IP When in IPv6 listen mode "-6", listen only on the @@ -5500,6 +5516,48 @@ because they have animated fades, etc.) For the native MacOSX server, use the original keystroke insertion code based on a US keyboard. .PP +\fB-macnoopengl\fR +.IP +For the native MacOSX server, do not use OpenGL for +screen capture, but rather use the original, deprecated +raw memory access method: addr = CGDisplayBaseAddress(). +.PP +\fB-macnorawfb\fR +.IP +For the native MacOSX server, disable the raw memory +address screen capture method. +.IP +MACOSX NOTE: There are some deprecated MacOSX interfaces +to inject keyboard and mouse events and the raw memory +access method is deprecated as well (however, OpenGL +will be preferred if available because it is faster.) +One can force not using any deprecated interfaces at +compile time by setting \fB-DX11VNC_MACOSX_NO_DEPRECATED=1\fR +in CPPFLAGS. Or to turn them off one by one: +\fB-DX11VNC_MACOSX_NO_DEPRECATED_LOCALEVENTS=1,\fR +\fB-DX11VNC_MACOSX_NO_DEPRECATED_POSTEVENTS=1\fR or +\fB-DX11VNC_MACOSX_NO_DEPRECATED_FRAMEBUFFER=1\fR +At run time, for testing and workarounds, one can +disable them by using: +\fB-env\fR X11VNC_MACOSX_NO_DEPRECATED=1 +\fB-env\fR X11VNC_MACOSX_NO_DEPRECATED_LOCALEVENTS=1 +\fB-env\fR X11VNC_MACOSX_NO_DEPRECATED_POSTEVENTS=1 or +\fB-env\fR X11VNC_MACOSX_NO_DEPRECATED_FRAMEBUFFER=1 +Note: When doing either of these for the mouse input +not everything works currently, e.g. double clicks and +wireframing. Also, screen resolution and pixel depth +changes will not be automatically detected unless the +deprecated framebuffer interfaces are allowed. +.IP +Conversely, if you are compiling on an +older machine that does not have some of +the newer interfaces, you may need to specify +\fB-DX11VNC_MACOSX_NO_CGEVENTCREATESCROLLWHEELEVENT\fR +\fB-DX11VNC_MACOSX_NO_CGEVENTCREATEMOUSEEVENT\fR or +\fB-DX11VNC_MACOSX_NO_CGEVENTCREATEKEYBOARDEVENT.\fR Use +\fB-DX11VNC_MACOSX_USE_GETMAINDEVICE\fR to regain the very +old QuickDraw GetMainDevice() interface (rare...) +.PP \fB-gui\fR \fI[gui-opts]\fR .IP Start up a simple tcl/tk gui based on the remote diff --git a/x11vnc/x11vnc.c b/x11vnc/x11vnc.c index d427f32..64a73de 100644 --- a/x11vnc/x11vnc.c +++ b/x11vnc/x11vnc.c @@ -2026,7 +2026,6 @@ static void check_guess_auth_file(void) { } } -extern int dragum(void); extern int is_decimal(char *); int main(int argc, char* argv[]) { @@ -2530,9 +2529,17 @@ int main(int argc, char* argv[]) { got_localhost = 1; continue; } + if (!strcmp(arg, "-unixsock")) { + CHECK_ARGC + unix_sock = strdup(argv[++i]); + continue; + } if (!strcmp(arg, "-listen6")) { + CHECK_ARGC #if X11VNC_IPV6 listen_str6 = strdup(argv[++i]); +#else + ++i; #endif continue; } @@ -3931,6 +3938,14 @@ int main(int argc, char* argv[]) { macosx_us_kbd = 1; continue; } + if (!strcmp(arg, "-macnoopengl")) { + macosx_no_opengl = 1; + continue; + } + if (!strcmp(arg, "-macnorawfb")) { + macosx_no_rawfb = 1; + continue; + } if (!strcmp(arg, "-gui")) { launch_gui = 1; if (i < argc-1) { @@ -5775,7 +5790,7 @@ int main(int argc, char* argv[]) { waitms = 5; } if (!quiet) { - rfbLog("fast read: reset wait ms to: %d\n", waitms); + rfbLog("fast read: reset -wait ms to: %d\n", waitms); } } if (! got_deferupdate && ! got_defer) { @@ -5788,7 +5803,7 @@ int main(int argc, char* argv[]) { if (screen) { screen->deferUpdateTime = defer_update; } - rfbLog("fast read: reset defer ms to: %d\n", defer_update); + rfbLog("fast read: reset -defer ms to: %d\n", defer_update); } } } @@ -5816,6 +5831,20 @@ int main(int argc, char* argv[]) { } } } + +#ifdef MACOSX + if (remote_cmd || query_cmd) { + ; + } else if (macosx_console) { + double dt = dnow(); + copy_screen(); + dt = dnow() - dt; + rfbLog("macosx_console: copied screen in %.3f sec %.1f MB/sec\n", + dt, dpy_x * dpy_y * bpp / (1e+6 * 8 * dt)); + + } +#endif + if (! quiet) { rfbLog("screen setup finished.\n"); if (SHOW_NO_PASSWORD_WARNING && !nopw) { diff --git a/x11vnc/x11vnc.h b/x11vnc/x11vnc.h index 3299109..015531d 100644 --- a/x11vnc/x11vnc.h +++ b/x11vnc/x11vnc.h @@ -135,6 +135,16 @@ so, delete this exception statement from your version. * * -DX11VNC_MACOSX_USE_GETMAINDEVICE use deprecated GetMainDevice on macosx * + * -DX11VNC_MACOSX_NO_DEPRECATED_LOCALEVENTS={0,1} + * -DX11VNC_MACOSX_NO_DEPRECATED_POSTEVENTS={0,1} + * -DX11VNC_MACOSX_NO_DEPRECATED_FRAMEBUFFER={0,1} + * + * or for all: + * + * -DX11VNC_MACOSX_NO_DEPRECATED=1 + * + * env. var. of the same names as above can be set to imply true. + * * Set these in CPPFLAGS before running configure. E.g.: * * % env CPPFLAGS="-DFOREVER -DREMOTE_CONTROL=0" ./configure @@ -248,6 +258,30 @@ so, delete this exception statement from your version. #define REMOTE_CONTROL 0 #endif +#ifndef X11VNC_MACOSX_NO_DEPRECATED_LOCALEVENTS +#if X11VNC_MACOSX_NO_DEPRECATED +#define X11VNC_MACOSX_NO_DEPRECATED_LOCALEVENTS 1 +#else +#define X11VNC_MACOSX_NO_DEPRECATED_LOCALEVENTS 0 +#endif +#endif + +#ifndef X11VNC_MACOSX_NO_DEPRECATED_POSTEVENTS +#if X11VNC_MACOSX_NO_DEPRECATED +#define X11VNC_MACOSX_NO_DEPRECATED_POSTEVENTS 1 +#else +#define X11VNC_MACOSX_NO_DEPRECATED_POSTEVENTS 0 +#endif +#endif + +#ifndef X11VNC_MACOSX_NO_DEPRECATED_FRAMEBUFFER +#if X11VNC_MACOSX_NO_DEPRECATED +#define X11VNC_MACOSX_NO_DEPRECATED_FRAMEBUFFER 1 +#else +#define X11VNC_MACOSX_NO_DEPRECATED_FRAMEBUFFER 0 +#endif +#endif + /* * Not recommended unless you know what you are getting into, but if you * define the HARDWIRE_PASSWD or HARDWIRE_VIEWPASSWD variables here or in diff --git a/x11vnc/x11vnc_defs.c b/x11vnc/x11vnc_defs.c index 06318d5..8234aff 100644 --- a/x11vnc/x11vnc_defs.c +++ b/x11vnc/x11vnc_defs.c @@ -47,7 +47,7 @@ int xtrap_base_event_type = 0; int xdamage_base_event_type = 0; /* date +'lastmod: %Y-%m-%d' */ -char lastmod[] = "0.9.13 lastmod: 2010-12-21"; +char lastmod[] = "0.9.13 lastmod: 2010-12-27"; /* X display info */ diff --git a/x11vnc/xwrappers.c b/x11vnc/xwrappers.c index bb73565..e7158cf 100644 --- a/x11vnc/xwrappers.c +++ b/x11vnc/xwrappers.c @@ -681,12 +681,23 @@ static void copy_raw_fb_24_to_32(XImage *dest, int x, int y, unsigned int w, } } +#ifdef MACOSX +void macosx_copy_opengl(char *, int, int, unsigned int, unsigned int); +#endif + void copy_raw_fb(XImage *dest, int x, int y, unsigned int w, unsigned int h) { char *src, *dst; unsigned int line; int pixelsize = bpp/8; static int db = -1; +#ifdef MACOSX + if (macosx_console && macosx_read_opengl) { + macosx_copy_opengl(dest->data, x, y, w, h); + return; + } +#endif + if (xform24to32) { copy_raw_fb_24_to_32(dest, x, y, w, h); return;