diff --git a/AUTHORS b/AUTHORS deleted file mode 100644 index ea648387..00000000 --- a/AUTHORS +++ /dev/null @@ -1 +0,0 @@ -See doc/authors.html. diff --git a/Makefile.am b/Makefile.am deleted file mode 100644 index 26a5086f..00000000 --- a/Makefile.am +++ /dev/null @@ -1,97 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2002 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -## Process this file with automake to produce Makefile.in -NULL = - -SUBDIRS = \ - lib \ - cmd \ - doc \ - dist \ - $(NULL) - -EXTRA_DIST = \ - Makefile.win \ - examples/synergy.conf \ - win32util/autodep.cpp \ - $(NULL) - -MAINTAINERCLEANFILES = \ - Makefile.in \ - aclocal.m4 \ - config.h \ - config.h.in \ - config.log \ - config.status \ - configure \ - stamp-h.in \ - stamp-h1 \ - $(NULL) - -PKG_FILES = \ - ChangeLog \ - README \ - cmd/synergyc/synergyc \ - cmd/synergys/synergys \ - examples/synergy.conf \ - $(NULL) -PKG_DOC_FILES = \ - doc/PORTING \ - doc/*.html \ - doc/*.css \ - $(NULL) -PKG_PROG_FILES = \ - synergyc \ - synergys \ - $(NULL) - -# build doxygen documentation -doxygen: - doxygen doc/doxygen.cfg - -# build RPMs -RPMTOPDIR=/var/tmp/@PACKAGE@-@VERSION@ -dist-rpm: dist - rm -rf $(RPMTOPDIR) - mkdir $(RPMTOPDIR) - (cd $(RPMTOPDIR); mkdir BUILD SOURCES SPECS SRPMS RPMS) - cp @PACKAGE@-@VERSION@.tar.gz $(RPMTOPDIR)/SOURCES - rpm --define '_topdir $(RPMTOPDIR)' -ba dist/rpm/synergy.spec && \ - mv -f $(RPMTOPDIR)/SRPMS/*.rpm . && \ - mv -f $(RPMTOPDIR)/RPMS/*/*.rpm . && \ - rm -rf $(RPMTOPDIR) - -# build zip -# FIXME -- have automake generate this rule for us -dist-zip: distdir - zip -r $(distdir).zip $(distdir) - -chmod -R a+w $(distdir) >/dev/null 2>&1; rm -rf $(distdir) - -# build binary package. owner/group of packaged files will be -# owner/group of user running make. -PKGTOPDIR=/var/tmp/@PACKAGE@-@VERSION@ -dist-pkg: all - rm -rf $(PKGTOPDIR) - mkdir $(PKGTOPDIR) - mkdir $(PKGTOPDIR)/@PACKAGE@-@VERSION@ - mkdir $(PKGTOPDIR)/@PACKAGE@-@VERSION@/doc - cp $(PKG_FILES) $(PKGTOPDIR)/@PACKAGE@-@VERSION@ - cp $(PKG_DOC_FILES) $(PKGTOPDIR)/@PACKAGE@-@VERSION@/doc - (cd $(PKGTOPDIR)/@PACKAGE@-@VERSION@; \ - chmod 644 *; \ - chmod 755 doc $(PKG_PROG_FILES); \ - strip $(PKG_PROG_FILES) ) - type=`uname -s -m | tr '[A-Z] ' '[a-z].'`; \ - (cd $(PKGTOPDIR); tar cf - @PACKAGE@-@VERSION@ | \ - gzip - ) > @PACKAGE@-@VERSION@-1.$${type}.tar.gz && \ - rm -rf $(PKGTOPDIR) diff --git a/Makefile.win b/Makefile.win deleted file mode 100644 index d232b58a..00000000 --- a/Makefile.win +++ /dev/null @@ -1,145 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2007 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -# Name of this file for recursive make -MAKEFILE = Makefile.win - -# Default build is release is NODEBUG is defined, debug otherwise. -!if !DEFINED(DEBUG) -NODEBUG = 1 -!else -!undef NODEBUG -!endif - -# Build all by default -default: all - -# Redefine implicit rule suffixes -.SUFFIXES: -.SUFFIXES: .cpp .rc .obj - -# Shut up -.SILENT: - -# Include system macros -#APPVER = 5.0 -#TARGETOS = WINNT -!include - -# Be explicit about C++ compiler -cpp = $(cc) -cppdebug = $(cdebug) -cppflags = $(cflags) -cppvarsmt = $(cvarsmt) - -# Library tool options -ildebug = -ilflags = /nologo - -# Handy macro for defining list macros -NULL = - -# System commands -ECHO = echo -MKDIR = mkdir -RM = del /f -RMR = rmdir /q /s - -# Local build utilities -UTIL_DIR = win32util -AUTODEP = "$(UTIL_DIR)\autodep.exe" - -# Destination for intermediate build targets -BUILD_DIR = build -BUILD_DEBUG_DIR = $(BUILD_DIR)\Debug -BUILD_RELEASE_DIR = $(BUILD_DIR)\Release -!if DEFINED(NODEBUG) -BUILD_DST = $(BUILD_RELEASE_DIR) -!else -BUILD_DST = $(BUILD_DEBUG_DIR) -!endif - -# Compiler argument changes -cflags = $(cflags:-W3=-W4) /WX -cflags = $(cflags) -D_CRT_SECURE_NO_DEPRECATE -cflags = $(cflags) /GR -!if !DEFINED(OLDCOMPILER) -cflags = $(cflags) /EHsc -!else -cflags = $(cflags) /GX -!endif -!if !DEFINED(NODEBUG) -!if !DEFINED(OLDCOMPILER) -cdebug = $(cdebug) /RTC1 -!else -cdebug = $(cdebug) /GZ -!endif -!endif - -# Initialize variables for library and program makefiles -C_FILES = -CPP_FILES = -OBJ_FILES = -LIB_FILES = -PROGRAMS = -OPTPROGRAMS = $(AUTODEP) - -# Include subdirectory makefiles -!include lib\common\$(MAKEFILE) -!include lib\arch\$(MAKEFILE) -!include lib\base\$(MAKEFILE) -!include lib\mt\$(MAKEFILE) -!include lib\io\$(MAKEFILE) -!include lib\net\$(MAKEFILE) -!include lib\synergy\$(MAKEFILE) -!include lib\platform\$(MAKEFILE) -!include lib\client\$(MAKEFILE) -!include lib\server\$(MAKEFILE) -!include cmd\synergyc\$(MAKEFILE) -!include cmd\synergys\$(MAKEFILE) -!include cmd\launcher\$(MAKEFILE) -!include dist\nullsoft\$(MAKEFILE) - -# Collect library and program variables -INTERMEDIATES = $(OBJ_FILES) $(AUTODEP:.exe=.obj) -TARGETS = $(LIB_FILES) $(PROGRAMS) -OPTTARGETS = $(OPTPROGRAMS) - -# Build release by reinvoking make with NODEBUG defined -release: - @$(MAKE) /nologo /f $(MAKEFILE) NODEBUG=1 - -# Build debug by reinvoking make with DEBUG defined -debug: - @$(MAKE) /nologo /f $(MAKEFILE) DEBUG=1 - -# Build all targets -all: $(TARGETS) - -# Clean intermediate targets -clean: - -$(RMR) $(BUILD_DEBUG_DIR) - -$(RMR) $(BUILD_RELEASE_DIR) - -# Clean all targets -clobber: clean - -$(RMR) $(BUILD_DIR) - -# Utility command build rules -$(AUTODEP): $(AUTODEP:.exe=.cpp) -!if DEFINED(NODEBUG) - @$(ECHO) Build $(@F) - $(cpp) $(cppdebug) $(cppflags) $(cppvars) /Fo"$(**:.cpp=.obj)" $** - $(link) $(ldebug) $(conflags) -out:$@ $(**:.cpp=.obj) $(conlibs) -!else - @$(MAKE) /nologo /f $(MAKEFILE) NODEBUG=1 $@ -!endif diff --git a/NEWS b/NEWS deleted file mode 100644 index e9aa7916..00000000 --- a/NEWS +++ /dev/null @@ -1 +0,0 @@ -See doc/news.html. diff --git a/acinclude.m4 b/acinclude.m4 deleted file mode 100644 index 29163d5a..00000000 --- a/acinclude.m4 +++ /dev/null @@ -1,571 +0,0 @@ -dnl synergy -- mouse and keyboard sharing utility -dnl Copyright (C) 2002 Chris Schoeneman -dnl -dnl This package is free software; you can redistribute it and/or -dnl modify it under the terms of the GNU General Public License -dnl found in the file COPYING that should have accompanied this file. -dnl -dnl This package is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -dnl GNU General Public License for more details. - -AC_DEFUN([ACX_CHECK_SOCKLEN_T], [ - AC_MSG_CHECKING([for socklen_t]) - AC_TRY_COMPILE([ - #include - #include - ], - [socklen_t len;],[acx_socklen_t_ok=yes],[acx_socklen_t_ok=no]) - AC_MSG_RESULT($acx_socklen_t_ok) - if test x"$acx_socklen_t_ok" = xyes; then - ifelse([$1],,AC_DEFINE(HAVE_SOCKLEN_T,1,[Define if your compiler defines socklen_t.]),[$1]) - : - else - acx_socklen_t_ok=no - $2 - fi -])dnl ACX_CHECK_SOCKLEN_T - -# HP-UX defines socklen_t but doesn't use it in arg 3 for accept(). -AC_DEFUN([ACX_FUNC_ACCEPT], [ - AC_MSG_CHECKING([for type of arg 3 for accept]) - acx_accept_socklen_t_arg3=int - if test x"$acx_socklen_t_ok" = xyes; then - AC_TRY_COMPILE([ - #include - #include - ], - [struct sockaddr addr; socklen_t len; accept(0, &addr, &len);], - [acx_accept_socklen_t_arg3=socklen_t], - [acx_accept_socklen_t_arg3=int]) - fi - AC_MSG_RESULT($acx_accept_socklen_t_arg3) - AC_DEFINE_UNQUOTED(ACCEPT_TYPE_ARG3,$acx_accept_socklen_t_arg3,[Define to the base type of arg 3 for `accept'.]) -])dnl ACX_FUNC_ACCEPT - -AC_DEFUN([ACX_CHECK_CXX], [ - AC_MSG_CHECKING([if g++ defines correct C++ macro]) - AC_TRY_COMPILE(, [ - #if defined(_LANGUAGE_C) && !defined(_LANGUAGE_C_PLUS_PLUS) - #error wrong macro - #endif],[acx_cxx_macro_ok=yes],[acx_cxx_macro_ok=no]) - AC_MSG_RESULT($acx_cxx_macro_ok) - if test x"$acx_cxx_macro_ok" = xyes; then - SYNERGY_CXXFLAGS="" - else - SYNERGY_CXXFLAGS="-U_LANGUAGE_C -D_LANGUAGE_C_PLUS_PLUS" - fi -])dnl ACX_CHECK_CXX - -AC_DEFUN([ACX_CHECK_CXX_BOOL], [ - AC_MSG_CHECKING([for bool support]) - AC_TRY_COMPILE(, [bool t = true, f = false;], - [acx_cxx_bool_ok=yes],[acx_cxx_bool_ok=no]) - AC_MSG_RESULT($acx_cxx_bool_ok) - if test x"$acx_cxx_bool_ok" = xyes; then - ifelse([$1],,AC_DEFINE(HAVE_CXX_BOOL,1,[Define if your compiler has bool support.]),[$1]) - : - else - acx_cxx_bool_ok=no - $2 - fi -])dnl ACX_CHECK_CXX_BOOL - -AC_DEFUN([ACX_CHECK_CXX_EXCEPTIONS], [ - AC_MSG_CHECKING([for exception support]) - AC_TRY_COMPILE(, [try{throw int(4);}catch(int){throw;}catch(...){}], - [acx_cxx_exception_ok=yes],[acx_cxx_exception_ok=no]) - AC_MSG_RESULT($acx_cxx_exception_ok) - if test x"$acx_cxx_exception_ok" = xyes; then - ifelse([$1],,AC_DEFINE(HAVE_CXX_EXCEPTIONS,1,[Define if your compiler has exceptions support.]),[$1]) - : - else - acx_cxx_exception_ok=no - $2 - fi -])dnl ACX_CHECK_CXX_EXCEPTIONS - -AC_DEFUN([ACX_CHECK_CXX_CASTS], [ - AC_MSG_CHECKING([for C++ cast support]) - AC_TRY_COMPILE(, [const char* f="a";const_cast(f); - reinterpret_cast(f);static_cast(4.5);], - [acx_cxx_cast_ok=yes],[acx_cxx_cast_ok=no]) - AC_MSG_RESULT($acx_cxx_cast_ok) - if test x"$acx_cxx_cast_ok" = xyes; then - ifelse([$1],,AC_DEFINE(HAVE_CXX_CASTS,1,[Define if your compiler has C++ cast support.]),[$1]) - : - else - acx_cxx_cast_ok=no - $2 - fi -])dnl ACX_CHECK_CXX_CASTS - -AC_DEFUN([ACX_CHECK_CXX_MUTABLE], [ - AC_MSG_CHECKING([for mutable support]) - AC_TRY_COMPILE(, [struct A{mutable int b;void f() const {b=0;}}; - A a;a.f();],[acx_cxx_mutable_ok=yes],[acx_cxx_mutable_ok=no]) - AC_MSG_RESULT($acx_cxx_mutable_ok) - if test x"$acx_cxx_mutable_ok" = xyes; then - ifelse([$1],,AC_DEFINE(HAVE_CXX_MUTABLE,1,[Define if your compiler has mutable support.]),[$1]) - : - else - acx_cxx_mutable_ok=no - $2 - fi -])dnl ACX_CHECK_CXX_MUTABLE - -AC_DEFUN([ACX_CHECK_CXX_STDLIB], [ - AC_MSG_CHECKING([for C++ standard library]) - AC_TRY_LINK([#include ], [std::set a; a.insert(3);], - [acx_cxx_stdlib_ok=yes],[acx_cxx_stdlib_ok=no]) - AC_MSG_RESULT($acx_cxx_stdlib_ok) - if test x"$acx_cxx_stdlib_ok" = xyes; then - ifelse([$1],,AC_DEFINE(HAVE_CXX_STDLIB,1,[Define if your compiler has standard C++ library support.]),[$1]) - : - else - acx_cxx_stdlib_ok=no - $2 - fi -])dnl ACX_CHECK_CXX_STDLIB - -AC_DEFUN([ACX_CHECK_GETPWUID_R], [ - AC_MSG_CHECKING([for working getpwuid_r]) - AC_TRY_LINK([#include ], - [char buffer[4096]; struct passwd pwd, *pwdp; - getpwuid_r(0, &pwd, buffer, sizeof(buffer), &pwdp);], - acx_getpwuid_r_ok=yes, acx_getpwuid_r_ok=no) - AC_MSG_RESULT($acx_getpwuid_r_ok) - if test x"$acx_getpwuid_r_ok" = xyes; then - ifelse([$1],,AC_DEFINE(HAVE_GETPWUID_R,1,[Define if you have a working \`getpwuid_r\' function.]),[$1]) - : - else - acx_getpwuid_r_ok=no - $2 - fi -])dnl ACX_CHECK_GETPWUID_R - -AC_DEFUN([ACX_CHECK_POLL], [ - AC_MSG_CHECKING([for poll]) - AC_TRY_LINK([#include ], - [#if defined(_POLL_EMUL_H_) - #error emulated poll - #endif - struct pollfd ufds[] = { 0, POLLIN, 0 }; poll(ufds, 1, 10);], - acx_poll_ok=yes, acx_poll_ok=no) - AC_MSG_RESULT($acx_poll_ok) - if test x"$acx_poll_ok" = xyes; then - ifelse([$1],,AC_DEFINE(HAVE_POLL,1,[Define if you have the \`poll\' function.]),[$1]) - : - else - acx_poll_ok=no - $2 - fi -])dnl ACX_CHECK_POLL - -dnl See if we need extra libraries for nanosleep -AC_DEFUN([ACX_CHECK_NANOSLEEP], [ - acx_nanosleep_ok=no - acx_nanosleep_list="" - - dnl check if user has set NANOSLEEP_LIBS - save_user_NANOSLEEP_LIBS="$NANOSLEEP_LIBS" - if test x"$NANOSLEEP_LIBS" != x; then - acx_nanosleep_list=user - fi - - dnl check various libraries (including no extra libraries) for - dnl nanosleep. `none' should appear first. - acx_nanosleep_list="none $acx_nanosleep_list rt" - for flag in $acx_nanosleep_list; do - case $flag in - none) - AC_MSG_CHECKING([for nanosleep]) - NANOSLEEP_LIBS="" - ;; - - user) - AC_MSG_CHECKING([for nanosleep in $save_user_NANOSLEEP_LIBS]) - NANOSLEEP_LIBS="$save_user_NANOSLEEP_LIBS" - ;; - - *) - AC_MSG_CHECKING([for nanosleep in -l$flag]) - NANOSLEEP_LIBS="-l$flag" - ;; - esac - - save_LIBS="$LIBS" - LIBS="$NANOSLEEP_LIBS $LIBS" - AC_TRY_LINK([#include ], - [struct timespec t = { 1, 1000 }; nanosleep(&t, NULL);], - acx_nanosleep_ok=yes, acx_nanosleep_ok=no) - LIBS="$save_LIBS" - AC_MSG_RESULT($acx_nanosleep_ok) - if test x"$acx_nanosleep_ok" = xyes; then - break; - fi - NANOSLEEP_LIBS="" - done - - AC_SUBST(NANOSLEEP_LIBS) - - # execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: - if test x"$acx_nanosleep_ok" = xyes; then - ifelse([$1],,AC_DEFINE(HAVE_NANOSLEEP,1,[Define if you have the \`nanosleep\' function.]),[$1]) - : - else - acx_nanosleep_ok=no - $2 - fi -])dnl ACX_CHECK_NANOSLEEP - -dnl See if we need extra libraries for inet_aton -AC_DEFUN([ACX_CHECK_INET_ATON], [ - acx_inet_aton_ok=no - acx_inet_aton_list="" - - dnl check if user has set INET_ATON_LIBS - save_user_INET_ATON_LIBS="$INET_ATON_LIBS" - if test x"$INET_ATON_LIBS" != x; then - acx_inet_aton_list=user - fi - - dnl check various libraries (including no extra libraries) for - dnl inet_aton. `none' should appear first. - acx_inet_aton_list="none $acx_inet_aton_list resolv" - for flag in $acx_inet_aton_list; do - case $flag in - none) - AC_MSG_CHECKING([for inet_aton]) - INET_ATON_LIBS="" - ;; - - user) - AC_MSG_CHECKING([for inet_aton in $save_user_INET_ATON_LIBS]) - INET_ATON_LIBS="$save_user_INET_ATON_LIBS" - ;; - - *) - AC_MSG_CHECKING([for inet_aton in -l$flag]) - INET_ATON_LIBS="-l$flag" - ;; - esac - - save_LIBS="$LIBS" - LIBS="$INET_ATON_LIBS $LIBS" - AC_TRY_LINK([#include - #include - #include - #include ], - [struct in_addr addr; inet_aton("foo.bar", &addr);], - acx_inet_aton_ok=yes, acx_inet_aton_ok=no) - LIBS="$save_LIBS" - AC_MSG_RESULT($acx_inet_aton_ok) - if test x"$acx_inet_aton_ok" = xyes; then - AC_DEFINE(HAVE_INET_ATON,1,[Define if you have the \`inet_aton\' function.]) - break; - fi - INET_ATON_LIBS="" - done - - AC_SUBST(INET_ATON_LIBS) -])dnl ACX_CHECK_INET_ATON - -dnl The following macros are from http://www.gnu.org/software/ac-archive/ -dnl which distributes them under the following license: -dnl -dnl Every Autoconf macro presented on this web site is free software; you can -dnl redistribute it and/or modify it under the terms of the GNU General -dnl Public License as published by the Free Software Foundation; either -dnl version 2, or (at your option) any later version. -dnl -dnl They are distributed in the hope that they will be useful, but WITHOUT -dnl ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -dnl FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -dnl more details. (You should have received a copy of the GNU General Public -dnl License along with this program; if not, write to the Free Software -dnl Foundation, Inc., 59 Temple Place -- Suite 330, Boston, MA 02111-1307, -dnl USA.) -dnl -dnl As a special exception, the Free Software Foundation gives unlimited -dnl permission to copy, distribute and modify the configure scripts that are -dnl the output of Autoconf. You need not follow the terms of the GNU General -dnl Public License when using or distributing such scripts, even though -dnl portions of the text of Autoconf appear in them. The GNU General Public -dnl License (GPL) does govern all other use of the material that constitutes -dnl the Autoconf program. -dnl -dnl Certain portions of the Autoconf source text are designed to be copied -dnl (in certain cases, depending on the input) into the output of Autoconf. -dnl We call these the "data" portions. The rest of the Autoconf source text -dnl consists of comments plus executable code that decides which of the data -dnl portions to output in any given case. We call these comments and -dnl executable code the "non-data" portions. Autoconf never copies any of the -dnl non-data portions into its output. -dnl -dnl This special exception to the GPL applies to versions of Autoconf -dnl released by the Free Software Foundation. When you make and distribute a -dnl modified version of Autoconf, you may extend this special exception to -dnl the GPL to apply to your modified version as well, *unless* your modified -dnl version has the potential to copy into its output some of the text that -dnl was the non-data portion of the version that you started with. (In other -dnl words, unless your change moves or copies text from the non-data portions -dnl to the data portions.) If your modification has such potential, you must -dnl delete any notice of this special exception to the GPL from your modified -dnl version - -AC_DEFUN([ACX_PTHREAD], [ -AC_REQUIRE([AC_CANONICAL_HOST]) -AC_LANG_SAVE -AC_LANG_C -acx_pthread_ok=no - -# We used to check for pthread.h first, but this fails if pthread.h -# requires special compiler flags (e.g. on True64 or Sequent). -# It gets checked for in the link test anyway. - -# First of all, check if the user has set any of the PTHREAD_LIBS, -# etcetera environment variables, and if threads linking works using -# them: -if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then - save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - save_LIBS="$LIBS" - LIBS="$PTHREAD_LIBS $LIBS" - AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) - AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) - AC_MSG_RESULT($acx_pthread_ok) - if test x"$acx_pthread_ok" = xno; then - PTHREAD_LIBS="" - PTHREAD_CFLAGS="" - fi - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" -fi - -# We must check for the threads library under a number of different -# names; the ordering is very important because some systems -# (e.g. DEC) have both -lpthread and -lpthreads, where one of the -# libraries is broken (non-POSIX). - -# Create a list of thread flags to try. Items starting with a "-" are -# C compiler flags, and other items are library names, except for "none" -# which indicates that we try without any flags at all, and "pthread-config" -# which is a program returning the flags for the Pth emulation library. - -acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" - -# The ordering *is* (sometimes) important. Some notes on the -# individual items follow: - -# pthreads: AIX (must check this before -lpthread) -# none: in case threads are in libc; should be tried before -Kthread and -# other compiler flags to prevent continual compiler warnings -# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) -# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) -# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) -# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) -# -pthreads: Solaris/gcc -# -mthreads: Mingw32/gcc, Lynx/gcc -# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it -# doesn't hurt to check since this sometimes defines pthreads too; -# also defines -D_REENTRANT) -# pthread: Linux, etcetera -# --thread-safe: KAI C++ -# pthread-config: use pthread-config program (for GNU Pth library) - -case "${host_cpu}-${host_os}" in - *solaris*) - - # On Solaris (at least, for some versions), libc contains stubbed - # (non-functional) versions of the pthreads routines, so link-based - # tests will erroneously succeed. (We need to link with -pthread or - # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather - # a function called by this macro, so we could check for that, but - # who knows whether they'll stub that too in a future libc.) So, - # we'll just look for -pthreads and -lpthread first: - - acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags" - ;; -esac - -if test x"$acx_pthread_ok" = xno; then -for flag in $acx_pthread_flags; do - - case $flag in - none) - AC_MSG_CHECKING([whether pthreads work without any flags]) - ;; - - -*) - AC_MSG_CHECKING([whether pthreads work with $flag]) - PTHREAD_CFLAGS="$flag" - ;; - - pthread-config) - AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no) - if test x"$acx_pthread_config" = xno; then continue; fi - PTHREAD_CFLAGS="`pthread-config --cflags`" - PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" - ;; - - *) - AC_MSG_CHECKING([for the pthreads library -l$flag]) - PTHREAD_LIBS="-l$flag" - ;; - esac - - save_LIBS="$LIBS" - save_CFLAGS="$CFLAGS" - LIBS="$PTHREAD_LIBS $LIBS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - - # Check for various functions. We must include pthread.h, - # since some functions may be macros. (On the Sequent, we - # need a special flag -Kthread to make this header compile.) - # We check for pthread_join because it is in -lpthread on IRIX - # while pthread_create is in libc. We check for pthread_attr_init - # due to DEC craziness with -lpthreads. We check for - # pthread_cleanup_push because it is one of the few pthread - # functions on Solaris that doesn't have a non-functional libc stub. - # We try pthread_create on general principles. - AC_TRY_LINK([#include ], - [pthread_t th; pthread_join(th, 0); - pthread_attr_init(0); pthread_cleanup_push(0, 0); - pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], - [acx_pthread_ok=yes]) - - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" - - AC_MSG_RESULT($acx_pthread_ok) - if test "x$acx_pthread_ok" = xyes; then - break; - fi - - PTHREAD_LIBS="" - PTHREAD_CFLAGS="" -done -fi - -# Various other checks: -if test "x$acx_pthread_ok" = xyes; then - save_LIBS="$LIBS" - LIBS="$PTHREAD_LIBS $LIBS" - save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - - # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. - AC_MSG_CHECKING([for joinable pthread attribute]) - attr_name=unknown - for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do - AC_TRY_LINK([#include ], [int attr=$attr;], - [attr_name=$attr; break]) - done - AC_MSG_RESULT($attr_name) - if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then - AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name, - [Define to necessary symbol if this constant - uses a non-standard name on your system.]) - fi - - AC_MSG_CHECKING([if more special flags are required for pthreads]) - flag=no - case "${host_cpu}-${host_os}" in - *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; - *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; - esac - AC_MSG_RESULT(${flag}) - if test "x$flag" != xno; then - PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" - fi - - # Detect POSIX sigwait() - AC_MSG_CHECKING([for POSIX sigwait]) - AC_TRY_LINK([#include - #include ], - [sigset_t sigset; int signal; sigwait(&sigset, &signal);], - ok=yes, ok=unknown) - if test x"$ok" = xunknown; then - save_CFLAGS2="$CFLAGS" - CFLAGS="$CFLAGS -D_POSIX_PTHREAD_SEMANTICS" - AC_TRY_LINK([#include - #include ], - [sigset_t sigset; int signal; sigwait(&sigset, &signal);], - ok=-D_POSIX_PTHREAD_SEMANTICS, ok=no) - CFLAGS="$save_CFLAGS2" - fi - AC_MSG_RESULT(${ok}) - if test x"$ok" != xno; then - AC_DEFINE(HAVE_POSIX_SIGWAIT,1,[Define if you have a POSIX \`sigwait\' function.]) - if test x"$ok" != xyes; then - PTHREAD_CFLAGS="$ok $PTHREAD_CFLAGS" - fi - fi - - # Detect pthread signal functions - AC_MSG_CHECKING([for pthread signal functions]) - AC_TRY_LINK([#include - #include ], - [pthread_kill(pthread_self(), SIGTERM);], - ok=yes, ok=no) - AC_MSG_RESULT(${ok}) - if test x"$ok" = xyes; then - AC_DEFINE(HAVE_PTHREAD_SIGNAL,1,[Define if you have \`pthread_sigmask\' and \`pthread_kill\' functions.]) - fi - - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" - - # More AIX lossage: must compile with cc_r - AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC}) -else - PTHREAD_CC="$CC" -fi - -AC_SUBST(PTHREAD_LIBS) -AC_SUBST(PTHREAD_CFLAGS) -AC_SUBST(PTHREAD_CC) - -# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: -if test x"$acx_pthread_ok" = xyes; then - ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) - : -else - acx_pthread_ok=no - $2 -fi -AC_LANG_RESTORE -])dnl ACX_PTHREAD - -dnl enable maximum compiler warnings. must ignore unknown pragmas to -dnl build on solaris. -dnl we only know how to do this for g++ -AC_DEFUN([ACX_CXX_WARNINGS], [ - AC_MSG_CHECKING([for C++ compiler warning flags]) - if test "$GXX" = "yes"; then - acx_cxx_warnings="-Wall -Wno-unknown-pragmas" - fi - if test -n "$acx_cxx_warnings"; then - CXXFLAGS="$CXXFLAGS $acx_cxx_warnings" - else - acx_cxx_warnings="unknown" - fi - AC_MSG_RESULT($acx_cxx_warnings) -])dnl ACX_CXX_WARNINGS - -dnl enable compiler warnings are errors -dnl we only know how to do this for g++ -AC_DEFUN([ACX_CXX_WARNINGS_ARE_ERRORS], [ - AC_MSG_CHECKING([for C++ compiler warning are errors flags]) - if test "$GXX" = "yes"; then - acx_cxx_warnings_are_errors="-Werror" - fi - if test -n "$acx_cxx_warnings_are_errors"; then - CXXFLAGS="$CXXFLAGS $acx_cxx_warnings_are_errors" - else - acx_cxx_warnings_are_errors="unknown" - fi - AC_MSG_RESULT($acx_cxx_warnings_are_errors) -])dnl ACX_CXX_WARNINGS_ARE_ERRORS diff --git a/cmd/Makefile.am b/cmd/Makefile.am deleted file mode 100644 index 1e43b156..00000000 --- a/cmd/Makefile.am +++ /dev/null @@ -1,27 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2002 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -## Process this file with automake to produce Makefile.in -NULL = - -SUBDIRS = \ - launcher \ - synergyc \ - synergys \ - $(NULL) - -EXTRA_DIST = \ - $(NULL) - -MAINTAINERCLEANFILES = \ - Makefile.in \ - $(NULL) diff --git a/cmd/launcher/CAddScreen.cpp b/cmd/launcher/CAddScreen.cpp deleted file mode 100644 index 5a876b77..00000000 --- a/cmd/launcher/CAddScreen.cpp +++ /dev/null @@ -1,427 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CConfig.h" -#include "KeyTypes.h" -#include "OptionTypes.h" -#include "ProtocolTypes.h" -#include "CStringUtil.h" -#include "CArch.h" -#include "CAddScreen.h" -#include "LaunchUtil.h" -#include "resource.h" - -struct CModifierInfo { -public: - int m_ctrlID; - const char* m_name; - KeyModifierID m_modifierID; - OptionID m_optionID; -}; - -static const CModifierInfo s_modifiers[] = { - { IDC_ADD_MOD_SHIFT, "Shift", - kKeyModifierIDShift, kOptionModifierMapForShift }, - { IDC_ADD_MOD_CTRL, "Ctrl", - kKeyModifierIDControl, kOptionModifierMapForControl }, - { IDC_ADD_MOD_ALT, "Alt", - kKeyModifierIDAlt, kOptionModifierMapForAlt }, - { IDC_ADD_MOD_META, "Meta", - kKeyModifierIDMeta, kOptionModifierMapForMeta }, - { IDC_ADD_MOD_SUPER, "Super", - kKeyModifierIDSuper, kOptionModifierMapForSuper } -}; - -static const KeyModifierID baseModifier = kKeyModifierIDShift; - -// -// CAddScreen -// - -CAddScreen* CAddScreen::s_singleton = NULL; - -CAddScreen::CAddScreen(HWND parent, CConfig* config, const CString& name) : - m_parent(parent), - m_config(config), - m_name(name) -{ - assert(s_singleton == NULL); - s_singleton = this; -} - -CAddScreen::~CAddScreen() -{ - s_singleton = NULL; -} - -bool -CAddScreen::doModal() -{ - // do dialog - return (DialogBoxParam(s_instance, MAKEINTRESOURCE(IDD_ADD), - m_parent, (DLGPROC)dlgProc, (LPARAM)this) != 0); -} - -CString -CAddScreen::getName() const -{ - return m_name; -} - -void -CAddScreen::init(HWND hwnd) -{ - // set title - CString title; - if (m_name.empty()) { - title = getString(IDS_ADD_SCREEN); - } - else { - title = CStringUtil::format( - getString(IDS_EDIT_SCREEN).c_str(), - m_name.c_str()); - } - SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM)title.c_str()); - - // fill in screen name - HWND child = getItem(hwnd, IDC_ADD_SCREEN_NAME_EDIT); - SendMessage(child, WM_SETTEXT, 0, (LPARAM)m_name.c_str()); - - // fill in aliases - CString aliases; - for (CConfig::all_const_iterator index = m_config->beginAll(); - index != m_config->endAll(); ++index) { - if (CStringUtil::CaselessCmp::equal(index->second, m_name) && - !CStringUtil::CaselessCmp::equal(index->second, index->first)) { - if (!aliases.empty()) { - aliases += "\r\n"; - } - aliases += index->first; - } - } - child = getItem(hwnd, IDC_ADD_ALIASES_EDIT); - SendMessage(child, WM_SETTEXT, 0, (LPARAM)aliases.c_str()); - - // set options - CConfig::CScreenOptions options; - getOptions(options); - CConfig::CScreenOptions::const_iterator index; - child = getItem(hwnd, IDC_ADD_HD_CAPS_CHECK); - index = options.find(kOptionHalfDuplexCapsLock); - setItemChecked(child, (index != options.end() && index->second != 0)); - child = getItem(hwnd, IDC_ADD_HD_NUM_CHECK); - index = options.find(kOptionHalfDuplexNumLock); - setItemChecked(child, (index != options.end() && index->second != 0)); - child = getItem(hwnd, IDC_ADD_HD_SCROLL_CHECK); - index = options.find(kOptionHalfDuplexScrollLock); - setItemChecked(child, (index != options.end() && index->second != 0)); - - // modifier options - for (UInt32 i = 0; i < sizeof(s_modifiers) / - sizeof(s_modifiers[0]); ++i) { - child = getItem(hwnd, s_modifiers[i].m_ctrlID); - - // fill in options - for (UInt32 j = 0; j < sizeof(s_modifiers) / - sizeof(s_modifiers[0]); ++j) { - SendMessage(child, CB_ADDSTRING, 0, - (LPARAM)s_modifiers[j].m_name); - } - - // choose current value - index = options.find(s_modifiers[i].m_optionID); - KeyModifierID id = s_modifiers[i].m_modifierID; - if (index != options.end()) { - id = index->second; - } - SendMessage(child, CB_SETCURSEL, id - baseModifier, 0); - } - - // dead corners - UInt32 corners = 0; - index = options.find(kOptionScreenSwitchCorners); - if (index != options.end()) { - corners = index->second; - } - child = getItem(hwnd, IDC_ADD_DC_TOP_LEFT); - setItemChecked(child, (corners & kTopLeftMask) != 0); - child = getItem(hwnd, IDC_ADD_DC_TOP_RIGHT); - setItemChecked(child, (corners & kTopRightMask) != 0); - child = getItem(hwnd, IDC_ADD_DC_BOTTOM_LEFT); - setItemChecked(child, (corners & kBottomLeftMask) != 0); - child = getItem(hwnd, IDC_ADD_DC_BOTTOM_RIGHT); - setItemChecked(child, (corners & kBottomRightMask) != 0); - index = options.find(kOptionScreenSwitchCornerSize); - SInt32 size = 0; - if (index != options.end()) { - size = index->second; - } - char buffer[20]; - sprintf(buffer, "%d", size); - child = getItem(hwnd, IDC_ADD_DC_SIZE); - SendMessage(child, WM_SETTEXT, 0, (LPARAM)buffer); -} - -bool -CAddScreen::save(HWND hwnd) -{ - // get the old aliases and options - CStringList oldAliases; - getAliases(oldAliases); - CConfig::CScreenOptions options; - getOptions(options); - - // extract name and aliases - CString newName; - HWND child = getItem(hwnd, IDC_ADD_SCREEN_NAME_EDIT); - newName = getWindowText(child); - CStringList newAliases; - child = getItem(hwnd, IDC_ADD_ALIASES_EDIT); - tokenize(newAliases, getWindowText(child)); - - // name must be valid - if (!m_config->isValidScreenName(newName)) { - showError(hwnd, CStringUtil::format( - getString(IDS_INVALID_SCREEN_NAME).c_str(), - newName.c_str())); - return false; - } - - // aliases must be valid - for (CStringList::const_iterator index = newAliases.begin(); - index != newAliases.end(); ++index) { - if (!m_config->isValidScreenName(*index)) { - showError(hwnd, CStringUtil::format( - getString(IDS_INVALID_SCREEN_NAME).c_str(), - index->c_str())); - return false; - } - } - - // new name may not be in the new alias list - if (isNameInList(newAliases, newName)) { - showError(hwnd, CStringUtil::format( - getString(IDS_SCREEN_NAME_IS_ALIAS).c_str(), - newName.c_str())); - return false; - } - - // name must not exist in config but allow same name. also - // allow name if it exists in the old alias list but not the - // new one. - if (m_config->isScreen(newName) && - !CStringUtil::CaselessCmp::equal(newName, m_name) && - !isNameInList(oldAliases, newName)) { - showError(hwnd, CStringUtil::format( - getString(IDS_DUPLICATE_SCREEN_NAME).c_str(), - newName.c_str())); - return false; - } - - // aliases must not exist in config but allow same aliases and - // allow an alias to be the old name. - for (CStringList::const_iterator index = newAliases.begin(); - index != newAliases.end(); ++index) { - if (m_config->isScreen(*index) && - !CStringUtil::CaselessCmp::equal(*index, m_name) && - !isNameInList(oldAliases, *index)) { - showError(hwnd, CStringUtil::format( - getString(IDS_DUPLICATE_SCREEN_NAME).c_str(), - index->c_str())); - return false; - } - } - - // dead corner size must be non-negative - child = getItem(hwnd, IDC_ADD_DC_SIZE); - CString valueString = getWindowText(child); - int cornerSize = atoi(valueString.c_str()); - if (cornerSize < 0) { - showError(hwnd, CStringUtil::format( - getString(IDS_INVALID_CORNER_SIZE).c_str(), - valueString.c_str())); - SetFocus(child); - return false; - } - - // collect options - child = getItem(hwnd, IDC_ADD_HD_CAPS_CHECK); - if (isItemChecked(child)) { - options[kOptionHalfDuplexCapsLock] = 1; - } - else { - options.erase(kOptionHalfDuplexCapsLock); - } - child = getItem(hwnd, IDC_ADD_HD_NUM_CHECK); - if (isItemChecked(child)) { - options[kOptionHalfDuplexNumLock] = 1; - } - else { - options.erase(kOptionHalfDuplexNumLock); - } - child = getItem(hwnd, IDC_ADD_HD_SCROLL_CHECK); - if (isItemChecked(child)) { - options[kOptionHalfDuplexScrollLock] = 1; - } - else { - options.erase(kOptionHalfDuplexScrollLock); - } - - // save modifier options - for (UInt32 i = 0; i < sizeof(s_modifiers) / - sizeof(s_modifiers[0]); ++i) { - child = getItem(hwnd, s_modifiers[i].m_ctrlID); - KeyModifierID id = static_cast( - SendMessage(child, CB_GETCURSEL, 0, 0) + - baseModifier); - if (id != s_modifiers[i].m_modifierID) { - options[s_modifiers[i].m_optionID] = id; - } - else { - options.erase(s_modifiers[i].m_optionID); - } - } - - // save dead corner options - UInt32 corners = 0; - if (isItemChecked(getItem(hwnd, IDC_ADD_DC_TOP_LEFT))) { - corners |= kTopLeftMask; - } - if (isItemChecked(getItem(hwnd, IDC_ADD_DC_TOP_RIGHT))) { - corners |= kTopRightMask; - } - if (isItemChecked(getItem(hwnd, IDC_ADD_DC_BOTTOM_LEFT))) { - corners |= kBottomLeftMask; - } - if (isItemChecked(getItem(hwnd, IDC_ADD_DC_BOTTOM_RIGHT))) { - corners |= kBottomRightMask; - } - options[kOptionScreenSwitchCorners] = corners; - options[kOptionScreenSwitchCornerSize] = cornerSize; - - // save new data to config - if (m_name.empty()) { - // added screen - m_config->addScreen(newName); - } - else { - // edited screen - m_config->removeAliases(m_name); - m_config->removeOptions(m_name); - m_config->renameScreen(m_name, newName); - } - m_name = newName; - for (CStringList::const_iterator index = newAliases.begin(); - index != newAliases.end(); ++index) { - m_config->addAlias(m_name, *index); - } - for (CConfig::CScreenOptions::const_iterator - index = options.begin(); - index != options.end(); ++index) { - m_config->addOption(m_name, index->first, index->second); - } - - return true; -} - -BOOL -CAddScreen::doDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM) -{ - switch (message) { - case WM_INITDIALOG: - init(hwnd); - return TRUE; - - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDOK: - if (save(hwnd)) { - EndDialog(hwnd, 1); - } - return TRUE; - - case IDCANCEL: - EndDialog(hwnd, 0); - return TRUE; - } - break; - - default: - break; - } - - return FALSE; -} - -BOOL CALLBACK -CAddScreen::dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - return s_singleton->doDlgProc(hwnd, message, wParam, lParam); -} - -void -CAddScreen::getAliases(CStringList& aliases) const -{ - for (CConfig::all_const_iterator index = m_config->beginAll(); - index != m_config->endAll(); ++index) { - if (CStringUtil::CaselessCmp::equal(index->second, m_name) && - !CStringUtil::CaselessCmp::equal(index->second, index->first)) { - aliases.push_back(index->first); - } - } -} - -void -CAddScreen::getOptions(CConfig::CScreenOptions& optionsOut) const -{ - const CConfig::CScreenOptions* options = m_config->getOptions(m_name); - if (options == NULL) { - optionsOut = CConfig::CScreenOptions(); - } - else { - optionsOut = *options; - } -} - -void -CAddScreen::tokenize(CStringList& tokens, const CString& src) -{ - // find first non-whitespace - CString::size_type x = src.find_first_not_of(" \t\r\n"); - if (x == CString::npos) { - return; - } - - // find next whitespace - do { - CString::size_type y = src.find_first_of(" \t\r\n", x); - if (y == CString::npos) { - y = src.size(); - } - tokens.push_back(src.substr(x, y - x)); - x = src.find_first_not_of(" \t\r\n", y); - } while (x != CString::npos); -} - -bool -CAddScreen::isNameInList(const CStringList& names, const CString& name) -{ - for (CStringList::const_iterator index = names.begin(); - index != names.end(); ++index) { - if (CStringUtil::CaselessCmp::equal(name, *index)) { - return true; - } - } - return false; -} diff --git a/cmd/launcher/CAddScreen.h b/cmd/launcher/CAddScreen.h deleted file mode 100644 index e926c498..00000000 --- a/cmd/launcher/CAddScreen.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CADDSCREEN_H -#define CADDSCREEN_H - -#include "CString.h" - -#define WINDOWS_LEAN_AND_MEAN -#include - -class CConfig; - -//! Add screen dialog for Microsoft Windows launcher -class CAddScreen { -public: - CAddScreen(HWND parent, CConfig*, const CString& name); - ~CAddScreen(); - - //! @name manipulators - //@{ - - //! Run dialog - /*! - Display and handle the dialog until closed by the user. Return - \c true if the user accepted the changes, false otherwise. - */ - bool doModal(); - - //@} - //! @name accessors - //@{ - - CString getName() const; - - //@} - -private: - typedef std::vector CStringList; - - void getAliases(CStringList&) const; - void getOptions(CConfig::CScreenOptions&) const; - - static void tokenize(CStringList& tokens, const CString& src); - static bool isNameInList(const CStringList& tokens, - const CString& src); - - void init(HWND hwnd); - bool save(HWND hwnd); - - // message handling - BOOL doDlgProc(HWND, UINT, WPARAM, LPARAM); - static BOOL CALLBACK dlgProc(HWND, UINT, WPARAM, LPARAM); - -private: - static CAddScreen* s_singleton; - - HWND m_parent; - CConfig* m_config; - CString m_name; -}; - -#endif diff --git a/cmd/launcher/CAdvancedOptions.cpp b/cmd/launcher/CAdvancedOptions.cpp deleted file mode 100644 index c1ea83ef..00000000 --- a/cmd/launcher/CAdvancedOptions.cpp +++ /dev/null @@ -1,269 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CConfig.h" -#include "ProtocolTypes.h" -#include "CStringUtil.h" -#include "CArch.h" -#include "CArchMiscWindows.h" -#include "CAdvancedOptions.h" -#include "LaunchUtil.h" -#include "XArch.h" -#include "resource.h" - -// -// CAdvancedOptions -// - -CAdvancedOptions* CAdvancedOptions::s_singleton = NULL; - -CAdvancedOptions::CAdvancedOptions(HWND parent, CConfig* config) : - m_parent(parent), - m_config(config), - m_isClient(false), - m_screenName(ARCH->getHostName()), - m_port(kDefaultPort), - m_interface() -{ - assert(s_singleton == NULL); - s_singleton = this; - init(); -} - -CAdvancedOptions::~CAdvancedOptions() -{ - s_singleton = NULL; -} - -void -CAdvancedOptions::doModal(bool isClient) -{ - // save state - m_isClient = isClient; - - // do dialog - DialogBoxParam(s_instance, MAKEINTRESOURCE(IDD_ADVANCED_OPTIONS), - m_parent, (DLGPROC)dlgProc, (LPARAM)this); -} - -CString -CAdvancedOptions::getScreenName() const -{ - return m_screenName; -} - -int -CAdvancedOptions::getPort() const -{ - return m_port; -} - -CString -CAdvancedOptions::getInterface() const -{ - return m_interface; -} - -CString -CAdvancedOptions::getCommandLine(bool isClient, const CString& serverName) const -{ - CString cmdLine; - - // screen name - if (!m_screenName.empty()) { - cmdLine += " --name "; - cmdLine += m_screenName; - } - - // port - char portString[20]; - sprintf(portString, "%d", m_port); - if (isClient) { - cmdLine += " "; - cmdLine += serverName; - cmdLine += ":"; - cmdLine += portString; - } - else { - cmdLine += " --address "; - if (!m_interface.empty()) { - cmdLine += m_interface; - } - cmdLine += ":"; - cmdLine += portString; - } - - return cmdLine; -} - -void -CAdvancedOptions::init() -{ - // get values from registry - HKEY key = CArchMiscWindows::openKey(HKEY_CURRENT_USER, getSettingsPath()); - if (key != NULL) { - DWORD newPort = CArchMiscWindows::readValueInt(key, "port"); - CString newName = CArchMiscWindows::readValueString(key, "name"); - CString newInterface = - CArchMiscWindows::readValueString(key, "interface"); - if (newPort != 0) { - m_port = static_cast(newPort); - } - if (!newName.empty()) { - m_screenName = newName; - } - if (!newInterface.empty()) { - m_interface = newInterface; - } - CArchMiscWindows::closeKey(key); - } -} - -void -CAdvancedOptions::doInit(HWND hwnd) -{ - // set values in GUI - HWND child; - char buffer[20]; - sprintf(buffer, "%d", m_port); - child = getItem(hwnd, IDC_ADVANCED_PORT_EDIT); - SendMessage(child, WM_SETTEXT, 0, (LPARAM)buffer); - - child = getItem(hwnd, IDC_ADVANCED_NAME_EDIT); - SendMessage(child, WM_SETTEXT, 0, (LPARAM)m_screenName.c_str()); - - child = getItem(hwnd, IDC_ADVANCED_INTERFACE_EDIT); - SendMessage(child, WM_SETTEXT, 0, (LPARAM)m_interface.c_str()); -} - -bool -CAdvancedOptions::save(HWND hwnd) -{ - SetCursor(LoadCursor(NULL, IDC_WAIT)); - - HWND child = getItem(hwnd, IDC_ADVANCED_NAME_EDIT); - CString name = getWindowText(child); - if (!m_config->isValidScreenName(name)) { - showError(hwnd, CStringUtil::format( - getString(IDS_INVALID_SCREEN_NAME).c_str(), - name.c_str())); - SetFocus(child); - return false; - } - if (!m_isClient && !m_config->isScreen(name)) { - showError(hwnd, CStringUtil::format( - getString(IDS_UNKNOWN_SCREEN_NAME).c_str(), - name.c_str())); - SetFocus(child); - return false; - } - - child = getItem(hwnd, IDC_ADVANCED_INTERFACE_EDIT); - CString iface = getWindowText(child); - if (!m_isClient) { - try { - if (!iface.empty()) { - ARCH->nameToAddr(iface); - } - } - catch (XArchNetworkName& e) { - showError(hwnd, CStringUtil::format( - getString(IDS_INVALID_INTERFACE_NAME).c_str(), - iface.c_str(), e.what().c_str())); - SetFocus(child); - return false; - } - } - - // get and verify port - child = getItem(hwnd, IDC_ADVANCED_PORT_EDIT); - CString portString = getWindowText(child); - int port = atoi(portString.c_str()); - if (port < 1 || port > 65535) { - CString defaultPortString = CStringUtil::print("%d", kDefaultPort); - showError(hwnd, CStringUtil::format( - getString(IDS_INVALID_PORT).c_str(), - portString.c_str(), - defaultPortString.c_str())); - SetFocus(child); - return false; - } - - // save state - m_screenName = name; - m_port = port; - m_interface = iface; - - // save values to registry - HKEY key = CArchMiscWindows::addKey(HKEY_CURRENT_USER, getSettingsPath()); - if (key != NULL) { - CArchMiscWindows::setValue(key, "port", m_port); - CArchMiscWindows::setValue(key, "name", m_screenName); - CArchMiscWindows::setValue(key, "interface", m_interface); - CArchMiscWindows::closeKey(key); - } - - return true; -} - -void -CAdvancedOptions::setDefaults(HWND hwnd) -{ - // restore defaults - m_screenName = ARCH->getHostName(); - m_port = kDefaultPort; - m_interface = ""; - - // update GUI - doInit(hwnd); -} - -BOOL -CAdvancedOptions::doDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM) -{ - switch (message) { - case WM_INITDIALOG: - doInit(hwnd); - return TRUE; - - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDOK: - if (save(hwnd)) { - EndDialog(hwnd, 0); - } - return TRUE; - - case IDCANCEL: - EndDialog(hwnd, 0); - return TRUE; - - case IDC_ADVANCED_DEFAULTS: - setDefaults(hwnd); - return TRUE; - } - break; - - default: - break; - } - - return FALSE; -} - -BOOL CALLBACK -CAdvancedOptions::dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - return s_singleton->doDlgProc(hwnd, message, wParam, lParam); -} diff --git a/cmd/launcher/CAdvancedOptions.h b/cmd/launcher/CAdvancedOptions.h deleted file mode 100644 index 1dd9dc44..00000000 --- a/cmd/launcher/CAdvancedOptions.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CADVANCEDOPTIONS_H -#define CADVANCEDOPTIONS_H - -#include "CString.h" - -#define WINDOWS_LEAN_AND_MEAN -#include - -class CConfig; - -//! Advanced options dialog for Microsoft Windows launcher -class CAdvancedOptions { -public: - CAdvancedOptions(HWND parent, CConfig*); - ~CAdvancedOptions(); - - //! @name manipulators - //@{ - - //! Run dialog - /*! - Display and handle the dialog until closed by the user. - */ - void doModal(bool isClient); - - //@} - //! @name accessors - //@{ - - //! Get the screen name - CString getScreenName() const; - - //! Get the port - int getPort() const; - - //! Get the interface - CString getInterface() const; - - //! Convert options to command line string - CString getCommandLine(bool isClient, - const CString& serverName) const; - - //@} - -private: - void init(); - void doInit(HWND hwnd); - bool save(HWND hwnd); - void setDefaults(HWND hwnd); - - // message handling - BOOL doDlgProc(HWND, UINT, WPARAM, LPARAM); - static BOOL CALLBACK dlgProc(HWND, UINT, WPARAM, LPARAM); - -private: - static CAdvancedOptions* s_singleton; - - HWND m_parent; - CConfig* m_config; - bool m_isClient; - CString m_screenName; - int m_port; - CString m_interface; -}; - -#endif diff --git a/cmd/launcher/CAutoStart.cpp b/cmd/launcher/CAutoStart.cpp deleted file mode 100644 index eb18a6b0..00000000 --- a/cmd/launcher/CAutoStart.cpp +++ /dev/null @@ -1,361 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CLog.h" -#include "ILogOutputter.h" -#include "CArch.h" -#include "CStringUtil.h" -#include "XArch.h" -#include "CAutoStart.h" -#include "LaunchUtil.h" -#include "resource.h" - -static const char* CLIENT_DAEMON_NAME = "Synergy Client"; -static const char* SERVER_DAEMON_NAME = "Synergy Server"; -static const char* CLIENT_DAEMON_INFO = "Uses a shared mouse and keyboard."; -static const char* SERVER_DAEMON_INFO = "Shares this system's mouse and keyboard with others."; - -// -// CAutoStartOutputter -// -// This class detects a message above a certain level and saves it -// - -class CAutoStartOutputter : public ILogOutputter { -public: - CAutoStartOutputter(CString* msg) : m_msg(msg) { } - virtual ~CAutoStartOutputter() { } - - // ILogOutputter overrides - virtual void open(const char*) { } - virtual void close() { } - virtual void show(bool) { } - virtual bool write(ELevel level, const char* message); - virtual const char* getNewline() const { return ""; } - -private: - CString* m_msg; -}; - -bool -CAutoStartOutputter::write(ELevel level, const char* message) -{ - if (level <= CLog::kERROR) { - *m_msg = message; - } - return false; -} - - -// -// CAutoStart -// - -CAutoStart* CAutoStart::s_singleton = NULL; - -CAutoStart::CAutoStart(HWND parent, bool isServer, const CString& cmdLine) : - m_parent(parent), - m_isServer(isServer), - m_cmdLine(cmdLine), - m_name(isServer ? SERVER_DAEMON_NAME : CLIENT_DAEMON_NAME) -{ - assert(s_singleton == NULL); - s_singleton = this; -} - -CAutoStart::~CAutoStart() -{ - s_singleton = NULL; -} - -void -CAutoStart::doModal() -{ - // install our log outputter - CLOG->insert(new CAutoStartOutputter(&m_errorMessage)); - - // do dialog - DialogBoxParam(s_instance, MAKEINTRESOURCE(IDD_AUTOSTART), - m_parent, (DLGPROC)dlgProc, (LPARAM)this); - - // remove log outputter - CLOG->pop_front(); -} - -void -CAutoStart::reinstallDaemon(bool isClient, const CString& cmdLine) -{ - // get installation state - const char* name = (isClient ? CLIENT_DAEMON_NAME : SERVER_DAEMON_NAME); - bool installedSystem = ARCH->isDaemonInstalled(name, true); - bool installedUser = ARCH->isDaemonInstalled(name, false); - - // reinstall if anything is installed - if (installedSystem || installedUser) { - ARCH->installDaemon(name, - isClient ? CLIENT_DAEMON_INFO : SERVER_DAEMON_INFO, - getAppPath(isClient ? CLIENT_APP : SERVER_APP).c_str(), - cmdLine.c_str(), - NULL, - installedSystem); - } -} - -void -CAutoStart::uninstallDaemons(bool client) -{ - if (client) { - try { - ARCH->uninstallDaemon(CLIENT_DAEMON_NAME, true); - } - catch (...) { - } - try { - ARCH->uninstallDaemon(CLIENT_DAEMON_NAME, false); - } - catch (...) { - } - } - else { - try { - ARCH->uninstallDaemon(SERVER_DAEMON_NAME, true); - } - catch (...) { - } - try { - ARCH->uninstallDaemon(SERVER_DAEMON_NAME, false); - } - catch (...) { - } - } -} - -bool -CAutoStart::startDaemon() -{ - const char* name = NULL; - if (ARCH->isDaemonInstalled(CLIENT_DAEMON_NAME, true)) { - name = CLIENT_DAEMON_NAME; - } - else if (ARCH->isDaemonInstalled(SERVER_DAEMON_NAME, true)) { - name = SERVER_DAEMON_NAME; - } - if (name == NULL) { - return false; - } - - // open service manager - SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_READ); - if (mgr == NULL) { - return false; - } - - // open the service - SC_HANDLE service = OpenService(mgr, name, SERVICE_START); - if (service == NULL) { - CloseServiceHandle(mgr); - return false; - } - - // start the service - BOOL okay = StartService(service, 0, NULL); - - // clean up - CloseServiceHandle(service); - CloseServiceHandle(mgr); - - return (okay != 0); -} - -bool -CAutoStart::isDaemonInstalled() -{ - return (ARCH->isDaemonInstalled(CLIENT_DAEMON_NAME, false) || - ARCH->isDaemonInstalled(CLIENT_DAEMON_NAME, true) || - ARCH->isDaemonInstalled(SERVER_DAEMON_NAME, false) || - ARCH->isDaemonInstalled(SERVER_DAEMON_NAME, true)); -} - -void -CAutoStart::update() -{ - // get installation state - const bool installedSystem = ARCH->isDaemonInstalled( - m_name.c_str(), true); - const bool installedUser = ARCH->isDaemonInstalled( - m_name.c_str(), false); - - // get user's permissions - const bool canInstallSystem = ARCH->canInstallDaemon( - m_name.c_str(), true); - const bool canInstallUser = ARCH->canInstallDaemon( - m_name.c_str(), false); - - // update messages - CString msg, label; - if (canInstallSystem) { - if (canInstallUser) { - msg = getString(IDS_AUTOSTART_PERMISSION_ALL); - } - else { - msg = getString(IDS_AUTOSTART_PERMISSION_SYSTEM); - } - } - else if (canInstallUser) { - msg = getString(IDS_AUTOSTART_PERMISSION_USER); - } - else { - msg = getString(IDS_AUTOSTART_PERMISSION_NONE); - } - setWindowText(getItem(m_hwnd, IDC_AUTOSTART_PERMISSION_MSG), msg); - if (installedSystem) { - msg = getString(IDS_AUTOSTART_INSTALLED_SYSTEM); - label = getString(IDS_UNINSTALL_LABEL); - } - else if (installedUser) { - msg = getString(IDS_AUTOSTART_INSTALLED_USER); - label = getString(IDS_UNINSTALL_LABEL); - } - else { - msg = getString(IDS_AUTOSTART_INSTALLED_NONE); - label = getString(IDS_INSTALL_LABEL); - } - setWindowText(getItem(m_hwnd, IDC_AUTOSTART_INSTALLED_MSG), msg); - - // update buttons - setWindowText(getItem(m_hwnd, IDC_AUTOSTART_INSTALL_SYSTEM), label); - setWindowText(getItem(m_hwnd, IDC_AUTOSTART_INSTALL_USER), label); - if (installedSystem) { - enableItem(m_hwnd, IDC_AUTOSTART_INSTALL_SYSTEM, canInstallSystem); - enableItem(m_hwnd, IDC_AUTOSTART_INSTALL_USER, false); - m_install = false; - } - else if (installedUser) { - enableItem(m_hwnd, IDC_AUTOSTART_INSTALL_SYSTEM, false); - enableItem(m_hwnd, IDC_AUTOSTART_INSTALL_USER, canInstallUser); - m_install = false; - } - else { - enableItem(m_hwnd, IDC_AUTOSTART_INSTALL_SYSTEM, canInstallSystem); - enableItem(m_hwnd, IDC_AUTOSTART_INSTALL_USER, canInstallUser); - m_install = true; - } -} - -bool -CAutoStart::onInstall(bool allUsers) -{ - if (!m_install) { - return onUninstall(allUsers); - } - - // get the app path - CString appPath = getAppPath(m_isServer ? SERVER_APP : CLIENT_APP); - - // clear error message - m_errorMessage = ""; - - // install - try { - ARCH->installDaemon(m_name.c_str(), - m_isServer ? SERVER_DAEMON_INFO : CLIENT_DAEMON_INFO, - appPath.c_str(), m_cmdLine.c_str(), - NULL, allUsers); - askOkay(m_hwnd, getString(IDS_INSTALL_TITLE), - getString(allUsers ? - IDS_INSTALLED_SYSTEM : - IDS_INSTALLED_USER)); - return true; - } - catch (XArchDaemon& e) { - if (m_errorMessage.empty()) { - m_errorMessage = CStringUtil::format( - getString(IDS_INSTALL_GENERIC_ERROR).c_str(), - e.what().c_str()); - } - showError(m_hwnd, m_errorMessage); - return false; - } -} - -bool -CAutoStart::onUninstall(bool allUsers) -{ - // clear error message - m_errorMessage = ""; - - // uninstall - try { - ARCH->uninstallDaemon(m_name.c_str(), allUsers); - askOkay(m_hwnd, getString(IDS_UNINSTALL_TITLE), - getString(allUsers ? - IDS_UNINSTALLED_SYSTEM : - IDS_UNINSTALLED_USER)); - return true; - } - catch (XArchDaemon& e) { - if (m_errorMessage.empty()) { - m_errorMessage = CStringUtil::format( - getString(IDS_UNINSTALL_GENERIC_ERROR).c_str(), - e.what().c_str()); - } - showError(m_hwnd, m_errorMessage); - return false; - } -} - -BOOL -CAutoStart::doDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM) -{ - switch (message) { - case WM_INITDIALOG: - // save our hwnd - m_hwnd = hwnd; - - // update the controls - update(); - - return TRUE; - - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDC_AUTOSTART_INSTALL_SYSTEM: - onInstall(true); - update(); - return TRUE; - - case IDC_AUTOSTART_INSTALL_USER: - onInstall(false); - update(); - return TRUE; - - case IDCANCEL: - EndDialog(hwnd, 0); - m_hwnd = NULL; - return TRUE; - } - break; - - default: - break; - } - - return FALSE; -} - -BOOL CALLBACK -CAutoStart::dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - return s_singleton->doDlgProc(hwnd, message, wParam, lParam); -} diff --git a/cmd/launcher/CAutoStart.h b/cmd/launcher/CAutoStart.h deleted file mode 100644 index 46aad100..00000000 --- a/cmd/launcher/CAutoStart.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CAUTOSTART_H -#define CAUTOSTART_H - -#include "CString.h" - -#define WINDOWS_LEAN_AND_MEAN -#include - -//! Auto start dialog for Microsoft Windows launcher -class CAutoStart { -public: - CAutoStart(HWND parent, bool isServer, const CString& cmdLine); - ~CAutoStart(); - - //! @name manipulators - //@{ - - //! Run dialog - /*! - Display and handle the dialog until closed by the user. - */ - void doModal(); - - //! Reinstall daemon - /*! - Reinstalls the currently installed daemon. - */ - static void reinstallDaemon(bool isClient, const CString& cmdLine); - - //! Uninstalls daemon - /*! - Uninstalls all installed client (\p client is \c true) or server daemons. - */ - static void uninstallDaemons(bool client); - - //! Starts an installed daemon - /*! - Returns \c true iff a daemon was started. This will only start daemons - installed for all users. - */ - static bool startDaemon(); - - //@} - //! @name accessors - //@{ - - //! Tests if any daemons are installed - /*! - Returns \c true if any daemons are installed. - */ - static bool isDaemonInstalled(); - - //@} - -private: - void update(); - bool onInstall(bool allUsers); - bool onUninstall(bool allUsers); - - // message handling - BOOL doDlgProc(HWND, UINT, WPARAM, LPARAM); - static BOOL CALLBACK dlgProc(HWND, UINT, WPARAM, LPARAM); - -private: - static CAutoStart* s_singleton; - - HWND m_parent; - bool m_isServer; - CString m_cmdLine; - CString m_name; - HWND m_hwnd; - bool m_install; - CString m_errorMessage; -}; - -#endif diff --git a/cmd/launcher/CGlobalOptions.cpp b/cmd/launcher/CGlobalOptions.cpp deleted file mode 100644 index 8237a07f..00000000 --- a/cmd/launcher/CGlobalOptions.cpp +++ /dev/null @@ -1,281 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CConfig.h" -#include "ProtocolTypes.h" -#include "CStringUtil.h" -#include "CArch.h" -#include "CGlobalOptions.h" -#include "LaunchUtil.h" -#include "resource.h" - -static const int s_defaultDelay = 250; -static const int s_defaultHeartbeat = 5000; - -// -// CGlobalOptions -// - -CGlobalOptions* CGlobalOptions::s_singleton = NULL; - -CGlobalOptions::CGlobalOptions(HWND parent, CConfig* config) : - m_parent(parent), - m_config(config), - m_delayTime(s_defaultDelay), - m_twoTapTime(s_defaultDelay), - m_heartbeatTime(s_defaultHeartbeat) -{ - assert(s_singleton == NULL); - s_singleton = this; -} - -CGlobalOptions::~CGlobalOptions() -{ - s_singleton = NULL; -} - -void -CGlobalOptions::doModal() -{ - // do dialog - DialogBoxParam(s_instance, MAKEINTRESOURCE(IDD_GLOBAL_OPTIONS), - m_parent, (DLGPROC)dlgProc, (LPARAM)this); -} - -void -CGlobalOptions::init(HWND hwnd) -{ - HWND child; - char buffer[30]; - - // reset options - sprintf(buffer, "%d", m_delayTime); - child = getItem(hwnd, IDC_GLOBAL_DELAY_CHECK); - setItemChecked(child, false); - child = getItem(hwnd, IDC_GLOBAL_DELAY_TIME); - setWindowText(child, buffer); - sprintf(buffer, "%d", m_twoTapTime); - child = getItem(hwnd, IDC_GLOBAL_TWO_TAP_CHECK); - setItemChecked(child, false); - child = getItem(hwnd, IDC_GLOBAL_TWO_TAP_TIME); - setWindowText(child, buffer); - sprintf(buffer, "%d", m_heartbeatTime); - child = getItem(hwnd, IDC_GLOBAL_HEARTBEAT_CHECK); - setItemChecked(child, false); - child = getItem(hwnd, IDC_GLOBAL_HEARTBEAT_TIME); - setWindowText(child, buffer); - child = getItem(hwnd, IDC_GLOBAL_SCREENSAVER_SYNC); - setItemChecked(child, true); - child = getItem(hwnd, IDC_GLOBAL_RELATIVE_MOVES); - setItemChecked(child, false); - child = getItem(hwnd, IDC_GLOBAL_LEAVE_FOREGROUND); - setItemChecked(child, false); - - // get the global options - const CConfig::CScreenOptions* options = m_config->getOptions(""); - if (options != NULL) { - for (CConfig::CScreenOptions::const_iterator index = options->begin(); - index != options->end(); ++index) { - const OptionID id = index->first; - const OptionValue value = index->second; - if (id == kOptionScreenSwitchDelay) { - if (value > 0) { - sprintf(buffer, "%d", value); - child = getItem(hwnd, IDC_GLOBAL_DELAY_CHECK); - setItemChecked(child, true); - child = getItem(hwnd, IDC_GLOBAL_DELAY_TIME); - setWindowText(child, buffer); - } - } - else if (id == kOptionScreenSwitchTwoTap) { - if (value > 0) { - sprintf(buffer, "%d", value); - child = getItem(hwnd, IDC_GLOBAL_TWO_TAP_CHECK); - setItemChecked(child, true); - child = getItem(hwnd, IDC_GLOBAL_TWO_TAP_TIME); - setWindowText(child, buffer); - } - } - else if (id == kOptionHeartbeat) { - if (value > 0) { - sprintf(buffer, "%d", value); - child = getItem(hwnd, IDC_GLOBAL_HEARTBEAT_CHECK); - setItemChecked(child, true); - child = getItem(hwnd, IDC_GLOBAL_HEARTBEAT_TIME); - setWindowText(child, buffer); - } - } - else if (id == kOptionScreenSaverSync) { - child = getItem(hwnd, IDC_GLOBAL_SCREENSAVER_SYNC); - setItemChecked(child, (value != 0)); - } - else if (id == kOptionRelativeMouseMoves) { - child = getItem(hwnd, IDC_GLOBAL_RELATIVE_MOVES); - setItemChecked(child, (value != 0)); - } - else if (id == kOptionWin32KeepForeground) { - child = getItem(hwnd, IDC_GLOBAL_LEAVE_FOREGROUND); - setItemChecked(child, (value != 0)); - } - } - } -} - -bool -CGlobalOptions::save(HWND hwnd) -{ - HWND child; - int newDelayTime = 0; - int newTwoTapTime = 0; - int newHeartbeatTime = 0; - - // get requested options - child = getItem(hwnd, IDC_GLOBAL_DELAY_CHECK); - if (isItemChecked(child)) { - child = getItem(hwnd, IDC_GLOBAL_DELAY_TIME); - newDelayTime = getTime(hwnd, child, true); - if (newDelayTime == 0) { - return false; - } - } - else { - child = getItem(hwnd, IDC_GLOBAL_DELAY_TIME); - newDelayTime = getTime(hwnd, child, false); - if (newDelayTime == 0) { - newDelayTime = s_defaultDelay; - } - } - child = getItem(hwnd, IDC_GLOBAL_TWO_TAP_CHECK); - if (isItemChecked(child)) { - child = getItem(hwnd, IDC_GLOBAL_TWO_TAP_TIME); - newTwoTapTime = getTime(hwnd, child, true); - if (newTwoTapTime == 0) { - return false; - } - } - else { - child = getItem(hwnd, IDC_GLOBAL_TWO_TAP_TIME); - newTwoTapTime = getTime(hwnd, child, false); - if (newTwoTapTime == 0) { - newTwoTapTime = s_defaultDelay; - } - } - child = getItem(hwnd, IDC_GLOBAL_HEARTBEAT_CHECK); - if (isItemChecked(child)) { - child = getItem(hwnd, IDC_GLOBAL_HEARTBEAT_TIME); - newHeartbeatTime = getTime(hwnd, child, true); - if (newHeartbeatTime == 0) { - return false; - } - } - else { - child = getItem(hwnd, IDC_GLOBAL_HEARTBEAT_TIME); - newHeartbeatTime = getTime(hwnd, child, false); - if (newHeartbeatTime == 0) { - newHeartbeatTime = s_defaultHeartbeat; - } - } - - // remove existing config options - m_config->removeOption("", kOptionScreenSwitchDelay); - m_config->removeOption("", kOptionScreenSwitchTwoTap); - m_config->removeOption("", kOptionHeartbeat); - m_config->removeOption("", kOptionScreenSaverSync); - m_config->removeOption("", kOptionRelativeMouseMoves); - m_config->removeOption("", kOptionWin32KeepForeground); - - // add requested options - child = getItem(hwnd, IDC_GLOBAL_DELAY_CHECK); - if (isItemChecked(child)) { - m_config->addOption("", kOptionScreenSwitchDelay, newDelayTime); - } - child = getItem(hwnd, IDC_GLOBAL_TWO_TAP_CHECK); - if (isItemChecked(child)) { - m_config->addOption("", kOptionScreenSwitchTwoTap, newTwoTapTime); - } - child = getItem(hwnd, IDC_GLOBAL_HEARTBEAT_CHECK); - if (isItemChecked(child)) { - m_config->addOption("", kOptionHeartbeat, newHeartbeatTime); - } - child = getItem(hwnd, IDC_GLOBAL_SCREENSAVER_SYNC); - if (!isItemChecked(child)) { - m_config->addOption("", kOptionScreenSaverSync, 0); - } - child = getItem(hwnd, IDC_GLOBAL_RELATIVE_MOVES); - if (isItemChecked(child)) { - m_config->addOption("", kOptionRelativeMouseMoves, 1); - } - child = getItem(hwnd, IDC_GLOBAL_LEAVE_FOREGROUND); - if (isItemChecked(child)) { - m_config->addOption("", kOptionWin32KeepForeground, 1); - } - - // save last values - m_delayTime = newDelayTime; - m_twoTapTime = newTwoTapTime; - m_heartbeatTime = newHeartbeatTime; - return true; -} - -int -CGlobalOptions::getTime(HWND hwnd, HWND child, bool reportError) -{ - CString valueString = getWindowText(child); - int value = atoi(valueString.c_str()); - if (value < 1) { - if (reportError) { - showError(hwnd, CStringUtil::format( - getString(IDS_INVALID_TIME).c_str(), - valueString.c_str())); - SetFocus(child); - } - return 0; - } - return value; -} - -BOOL -CGlobalOptions::doDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM) -{ - switch (message) { - case WM_INITDIALOG: - init(hwnd); - return TRUE; - - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDOK: - if (save(hwnd)) { - EndDialog(hwnd, 0); - } - return TRUE; - - case IDCANCEL: - EndDialog(hwnd, 0); - return TRUE; - } - break; - - default: - break; - } - - return FALSE; -} - -BOOL CALLBACK -CGlobalOptions::dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - return s_singleton->doDlgProc(hwnd, message, wParam, lParam); -} diff --git a/cmd/launcher/CGlobalOptions.h b/cmd/launcher/CGlobalOptions.h deleted file mode 100644 index f04f1bae..00000000 --- a/cmd/launcher/CGlobalOptions.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CGLOBALOPTIONS_H -#define CGLOBALOPTIONS_H - -#include "CString.h" - -#define WINDOWS_LEAN_AND_MEAN -#include - -class CConfig; - -//! Global options dialog for Microsoft Windows launcher -class CGlobalOptions { -public: - CGlobalOptions(HWND parent, CConfig*); - ~CGlobalOptions(); - - //! @name manipulators - //@{ - - //! Run dialog - /*! - Display and handle the dialog until closed by the user. - */ - void doModal(); - - //@} - //! @name accessors - //@{ - - - //@} - -private: - void init(HWND hwnd); - bool save(HWND hwnd); - - int getTime(HWND hwnd, HWND child, bool reportError); - - // message handling - BOOL doDlgProc(HWND, UINT, WPARAM, LPARAM); - static BOOL CALLBACK dlgProc(HWND, UINT, WPARAM, LPARAM); - -private: - static CGlobalOptions* s_singleton; - - HWND m_parent; - CConfig* m_config; - int m_delayTime; - int m_twoTapTime; - int m_heartbeatTime; -}; - -#endif diff --git a/cmd/launcher/CHotkeyOptions.cpp b/cmd/launcher/CHotkeyOptions.cpp deleted file mode 100644 index 5aa981e0..00000000 --- a/cmd/launcher/CHotkeyOptions.cpp +++ /dev/null @@ -1,1938 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2006 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CArchMiscWindows.h" -#include "CMSWindowsKeyState.h" -#include "CConfig.h" -#include "CHotkeyOptions.h" -#include "CStringUtil.h" -#include "LaunchUtil.h" -#include "resource.h" - -#if !defined(WM_XBUTTONDOWN) -#define WM_XBUTTONDOWN 0x020B -#define WM_XBUTTONUP 0x020C -#define WM_XBUTTONDBLCLK 0x020D -#define XBUTTON1 0x0001 -#define XBUTTON2 0x0002 -#endif - -// -// CAdvancedOptions -// - -CHotkeyOptions* CHotkeyOptions::s_singleton = NULL; - -CHotkeyOptions::CHotkeyOptions(HWND parent, CConfig* config) : - m_parent(parent), - m_config(config) -{ - assert(s_singleton == NULL); - s_singleton = this; -} - -CHotkeyOptions::~CHotkeyOptions() -{ - s_singleton = NULL; -} - -void -CHotkeyOptions::doModal() -{ - // do dialog - m_inputFilter = m_config->getInputFilter(); - DialogBoxParam(s_instance, MAKEINTRESOURCE(IDD_HOTKEY_OPTIONS), - m_parent, (DLGPROC)dlgProc, (LPARAM)this); -} - -void -CHotkeyOptions::doInit(HWND hwnd) -{ - m_activeRuleIndex = (UInt32)-1; - fillHotkeys(hwnd); - openRule(hwnd); -} - -void -CHotkeyOptions::fillHotkeys(HWND hwnd, UInt32 select) -{ - HWND rules = getItem(hwnd, IDC_HOTKEY_HOTKEYS); - - SendMessage(rules, LB_RESETCONTENT, 0, 0); - for (UInt32 i = 0, n = m_inputFilter->getNumRules(); i < n; ++i) { - CInputFilter::CRule& rule = m_inputFilter->getRule(i); - SendMessage(rules, LB_INSERTSTRING, (WPARAM)-1, - (LPARAM)rule.getCondition()->format().c_str()); - } - - if (select < m_inputFilter->getNumRules()) { - SendMessage(rules, LB_SETCURSEL, select, 0); - } - - updateHotkeysControls(hwnd); -} - -void -CHotkeyOptions::updateHotkeysControls(HWND hwnd) -{ - HWND child = getItem(hwnd, IDC_HOTKEY_HOTKEYS); - bool selected = (SendMessage(child, LB_GETCURSEL, 0, 0) != LB_ERR); - - enableItem(hwnd, IDC_HOTKEY_ADD_HOTKEY, TRUE); - enableItem(hwnd, IDC_HOTKEY_EDIT_HOTKEY, selected); - enableItem(hwnd, IDC_HOTKEY_REMOVE_HOTKEY, selected); -} - -void -CHotkeyOptions::addHotkey(HWND hwnd) -{ - closeRule(hwnd); - CInputFilter::CCondition* condition = NULL; - if (editCondition(hwnd, condition)) { - m_inputFilter->addFilterRule(CInputFilter::CRule(condition)); - fillHotkeys(hwnd, m_inputFilter->getNumRules() - 1); - } - else { - delete condition; - } - openRule(hwnd); -} - -void -CHotkeyOptions::removeHotkey(HWND hwnd) -{ - UInt32 ruleIndex = m_activeRuleIndex; - closeRule(hwnd); - - m_inputFilter->removeFilterRule(ruleIndex); - UInt32 n = m_inputFilter->getNumRules(); - if (n > 0 && ruleIndex >= n) { - ruleIndex = n - 1; - } - fillHotkeys(hwnd, ruleIndex); - - openRule(hwnd); -} - -void -CHotkeyOptions::editHotkey(HWND hwnd) -{ - // save selected item in action list - HWND actions = getItem(hwnd, IDC_HOTKEY_ACTIONS); - LRESULT aIndex = SendMessage(actions, LB_GETCURSEL, 0, 0); - - UInt32 index = m_activeRuleIndex; - closeRule(hwnd); - - CInputFilter::CRule& rule = m_inputFilter->getRule(index); - CInputFilter::CCondition* condition = rule.getCondition()->clone(); - if (editCondition(hwnd, condition)) { - rule.setCondition(condition); - fillHotkeys(hwnd, index); - } - else { - delete condition; - } - - openRule(hwnd); - - // restore selected item in action list - if (aIndex != LB_ERR) { - SendMessage(actions, LB_SETCURSEL, aIndex, 0); - } -} - -void -CHotkeyOptions::fillActions(HWND hwnd, UInt32 select) -{ - HWND actions = getItem(hwnd, IDC_HOTKEY_ACTIONS); - SendMessage(actions, LB_RESETCONTENT, 0, 0); - if (m_activeRuleIndex != (UInt32)-1) { - UInt32 n = m_activeRule.getNumActions(true); - UInt32 n2 = m_activeRule.getNumActions(false); - for (UInt32 i = 0; i < n; ++i) { - const CInputFilter::CAction& action = - m_activeRule.getAction(true, i); - CString line("A "); - line += action.format(); - SendMessage(actions, LB_INSERTSTRING, (WPARAM)-1, - (LPARAM)line.c_str()); - SendMessage(actions, LB_SETITEMDATA, (WPARAM)i, (LPARAM)i); - } - for (UInt32 i = 0; i < n2; ++i) { - const CInputFilter::CAction& action = - m_activeRule.getAction(false, i); - CString line("D "); - line += action.format(); - SendMessage(actions, LB_INSERTSTRING, (WPARAM)-1, - (LPARAM)line.c_str()); - SendMessage(actions, LB_SETITEMDATA, (WPARAM)i + n, - (LPARAM)(i | 0x80000000u)); - } - - if (select < n + n2) { - SendMessage(actions, LB_SETCURSEL, select, 0); - } - } - - updateActionsControls(hwnd); -} - -void -CHotkeyOptions::updateActionsControls(HWND hwnd) -{ - HWND child = getItem(hwnd, IDC_HOTKEY_HOTKEYS); - bool active = (m_activeRuleIndex != (UInt32)-1); - - child = getItem(hwnd, IDC_HOTKEY_ACTIONS); - bool selected = - (active && (SendMessage(child, LB_GETCURSEL, 0, 0) != LB_ERR)); - - enableItem(hwnd, IDC_HOTKEY_ADD_ACTION, active); - enableItem(hwnd, IDC_HOTKEY_EDIT_ACTION, selected); - enableItem(hwnd, IDC_HOTKEY_REMOVE_ACTION, selected); -} - -void -CHotkeyOptions::addAction(HWND hwnd) -{ - CInputFilter::CAction* action = NULL; - bool onActivate = true; - if (editAction(hwnd, action, onActivate)) { - m_activeRule.adoptAction(action, onActivate); - - UInt32 actionIndex = m_activeRule.getNumActions(true) - 1; - if (!onActivate) { - actionIndex += m_activeRule.getNumActions(false); - } - fillActions(hwnd, actionIndex); - } - else { - delete action; - } -} - -void -CHotkeyOptions::removeAction(HWND hwnd) -{ - HWND child = getItem(hwnd, IDC_HOTKEY_ACTIONS); - LRESULT index = SendMessage(child, LB_GETCURSEL, 0, 0); - if (index != LB_ERR) { - UInt32 actionIndex = - (UInt32)SendMessage(child, LB_GETITEMDATA, index, 0); - bool onActivate = ((actionIndex & 0x80000000u) == 0); - actionIndex &= ~0x80000000u; - - m_activeRule.removeAction(onActivate, actionIndex); - - actionIndex = static_cast(index); - UInt32 n = m_activeRule.getNumActions(true) + - m_activeRule.getNumActions(false); - if (n > 0 && actionIndex >= n) { - actionIndex = n - 1; - } - fillActions(hwnd, actionIndex); - } -} - -void -CHotkeyOptions::editAction(HWND hwnd) -{ - HWND child = getItem(hwnd, IDC_HOTKEY_ACTIONS); - LRESULT index = SendMessage(child, LB_GETCURSEL, 0, 0); - if (index != LB_ERR) { - UInt32 actionIndex = - (UInt32)SendMessage(child, LB_GETITEMDATA, index, 0); - bool onActivate = ((actionIndex & 0x80000000u) == 0); - actionIndex &= ~0x80000000u; - - CInputFilter::CAction* action = - m_activeRule.getAction(onActivate, actionIndex).clone(); - bool newOnActivate = onActivate; - if (editAction(hwnd, action, newOnActivate)) { - if (onActivate == newOnActivate) { - m_activeRule.replaceAction(action, onActivate, actionIndex); - actionIndex = static_cast(index); - } - else { - m_activeRule.removeAction(onActivate, actionIndex); - m_activeRule.adoptAction(action, newOnActivate); - actionIndex = m_activeRule.getNumActions(true) - 1; - if (!newOnActivate) { - actionIndex += m_activeRule.getNumActions(false); - } - } - fillActions(hwnd, actionIndex); - } - else { - delete action; - } - } -} - -bool -CHotkeyOptions::editCondition(HWND hwnd, CInputFilter::CCondition*& condition) -{ - return CConditionDialog::doModal(hwnd, condition); -} - -bool -CHotkeyOptions::editAction(HWND hwnd, CInputFilter::CAction*& action, - bool& onActivate) -{ - return CActionDialog::doModal(hwnd, m_config, action, onActivate); -} - -void -CHotkeyOptions::openRule(HWND hwnd) -{ - // get the active rule and copy it, merging down/up pairs of keystroke - // and mouse button actions into single actions for the convenience of - // of the user. - HWND rules = getItem(hwnd, IDC_HOTKEY_HOTKEYS); - LRESULT index = SendMessage(rules, LB_GETCURSEL, 0, 0); - if (index != LB_ERR) { - // copy the rule as is - m_activeRuleIndex = (SInt32)index; - m_activeRule = m_inputFilter->getRule(m_activeRuleIndex); - - // look for actions to combine - for (UInt32 i = 0, n = m_activeRule.getNumActions(true); i < n; ++i) { - // get next activate action - const CInputFilter::CAction* action = - &m_activeRule.getAction(true, i); - - // check if it's a key or mouse action - const CInputFilter::CKeystrokeAction* keyAction = - dynamic_cast(action); - const CInputFilter::CMouseButtonAction* mouseAction = - dynamic_cast(action); - if (keyAction == NULL && mouseAction == NULL) { - continue; - } - - // check for matching deactivate action - UInt32 j = (UInt32)-1; - CInputFilter::CAction* newAction = NULL; - if (keyAction != NULL) { - j = findMatchingAction(keyAction); - if (j != (UInt32)-1) { - // found a match - const IPlatformScreen::CKeyInfo* oldInfo = - keyAction->getInfo(); - IPlatformScreen::CKeyInfo* newInfo = - IKeyState::CKeyInfo::alloc(*oldInfo); - newAction = new CKeystrokeDownUpAction(newInfo); - } - } - else if (mouseAction != NULL) { - j = findMatchingAction(mouseAction); - if (j != (UInt32)-1) { - // found a match - const IPlatformScreen::CButtonInfo* oldInfo = - mouseAction->getInfo(); - IPlatformScreen::CButtonInfo* newInfo = - IPrimaryScreen::CButtonInfo::alloc(*oldInfo); - newAction = new CMouseButtonDownUpAction(newInfo); - } - } - - // perform merge - if (newAction != NULL) { - m_activeRule.replaceAction(newAction, true, i); - m_activeRule.removeAction(false, j); - } - } - } - else { - m_activeRuleIndex = (UInt32)-1; - } - fillActions(hwnd); -} - -void -CHotkeyOptions::closeRule(HWND) -{ - // copy rule back to input filter, expanding merged actions into the - // two component actions. - if (m_activeRuleIndex != (UInt32)-1) { - // expand merged rules - for (UInt32 i = 0, n = m_activeRule.getNumActions(true); i < n; ++i) { - // get action - const CInputFilter::CAction* action = - &m_activeRule.getAction(true, i); - - // check if it's a merged key or mouse action - const CKeystrokeDownUpAction* keyAction = - dynamic_cast(action); - const CMouseButtonDownUpAction* mouseAction = - dynamic_cast(action); - if (keyAction == NULL && mouseAction == NULL) { - continue; - } - - // expand - if (keyAction != NULL) { - const IPlatformScreen::CKeyInfo* oldInfo = - keyAction->getInfo(); - IPlatformScreen::CKeyInfo* newInfo = - IKeyState::CKeyInfo::alloc(*oldInfo); - CInputFilter::CKeystrokeAction* downAction = - new CInputFilter::CKeystrokeAction(newInfo, true); - newInfo = IKeyState::CKeyInfo::alloc(*oldInfo); - CInputFilter::CKeystrokeAction* upAction = - new CInputFilter::CKeystrokeAction(newInfo, false); - m_activeRule.replaceAction(downAction, true, i); - m_activeRule.adoptAction(upAction, false); - } - else if (mouseAction != NULL) { - const IPlatformScreen::CButtonInfo* oldInfo = - mouseAction->getInfo(); - IPlatformScreen::CButtonInfo* newInfo = - IPrimaryScreen::CButtonInfo::alloc(*oldInfo); - CInputFilter::CMouseButtonAction* downAction = - new CInputFilter::CMouseButtonAction(newInfo, true); - newInfo = IPrimaryScreen::CButtonInfo::alloc(*oldInfo); - CInputFilter::CMouseButtonAction* upAction = - new CInputFilter::CMouseButtonAction(newInfo, false); - m_activeRule.replaceAction(downAction, true, i); - m_activeRule.adoptAction(upAction, false); - } - } - - // copy it back - m_inputFilter->getRule(m_activeRuleIndex) = m_activeRule; - } - m_activeRuleIndex = (UInt32)-1; -} - -UInt32 -CHotkeyOptions::findMatchingAction( - const CInputFilter::CKeystrokeAction* src) const -{ - for (UInt32 i = 0, n = m_activeRule.getNumActions(false); i < n; ++i) { - const CInputFilter::CKeystrokeAction* dst = - dynamic_cast( - &m_activeRule.getAction(false, i)); - if (dst != NULL && - IKeyState::CKeyInfo::equal(src->getInfo(), dst->getInfo())) { - return i; - } - } - return (UInt32)-1; -} - -UInt32 -CHotkeyOptions::findMatchingAction( - const CInputFilter::CMouseButtonAction* src) const -{ - for (UInt32 i = 0, n = m_activeRule.getNumActions(false); i < n; ++i) { - const CInputFilter::CMouseButtonAction* dst = - dynamic_cast( - &m_activeRule.getAction(false, i)); - if (dst != NULL && - IPrimaryScreen::CButtonInfo::equal( - src->getInfo(), dst->getInfo())) { - return i; - } - } - return (UInt32)-1; -} - -BOOL -CHotkeyOptions::doDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM) -{ - switch (message) { - case WM_INITDIALOG: - doInit(hwnd); - return TRUE; - - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDOK: - case IDCANCEL: - closeRule(hwnd); - EndDialog(hwnd, 0); - return TRUE; - - case IDC_HOTKEY_HOTKEYS: - switch (HIWORD(wParam)) { - case LBN_DBLCLK: - editHotkey(hwnd); - return TRUE; - - case LBN_SELCHANGE: { - HWND rules = getItem(hwnd, IDC_HOTKEY_HOTKEYS); - LRESULT index = SendMessage(rules, LB_GETCURSEL, 0, 0); - if (m_activeRuleIndex != (UInt32)index) { - closeRule(hwnd); - updateHotkeysControls(hwnd); - openRule(hwnd); - } - return TRUE; - } - } - break; - - case IDC_HOTKEY_ADD_HOTKEY: - addHotkey(hwnd); - return TRUE; - - case IDC_HOTKEY_REMOVE_HOTKEY: - removeHotkey(hwnd); - return TRUE; - - case IDC_HOTKEY_EDIT_HOTKEY: - editHotkey(hwnd); - return TRUE; - - case IDC_HOTKEY_ACTIONS: - switch (HIWORD(wParam)) { - case LBN_DBLCLK: - editAction(hwnd); - return TRUE; - - case LBN_SELCHANGE: - updateActionsControls(hwnd); - return TRUE; - } - break; - - case IDC_HOTKEY_ADD_ACTION: - addAction(hwnd); - return TRUE; - - case IDC_HOTKEY_REMOVE_ACTION: - removeAction(hwnd); - return TRUE; - - case IDC_HOTKEY_EDIT_ACTION: - editAction(hwnd); - return TRUE; - } - break; - - default: - break; - } - - return FALSE; -} - -BOOL CALLBACK -CHotkeyOptions::dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - return s_singleton->doDlgProc(hwnd, message, wParam, lParam); -} - - -// -// CHotkeyOptions::CConditionDialog -// - -CInputFilter::CCondition* - CHotkeyOptions::CConditionDialog::s_condition = NULL; -CInputFilter::CCondition* - CHotkeyOptions::CConditionDialog::s_lastGoodCondition = NULL; -WNDPROC CHotkeyOptions::CConditionDialog::s_editWndProc = NULL; - -bool -CHotkeyOptions::CConditionDialog::doModal(HWND parent, - CInputFilter::CCondition*& condition) -{ - s_condition = condition; - if (s_condition != NULL) { - s_lastGoodCondition = s_condition->clone(); - } - else { - s_lastGoodCondition = NULL; - } - int n = DialogBox(s_instance, MAKEINTRESOURCE(IDD_HOTKEY_CONDITION), - parent, dlgProc); - - condition = s_condition; - delete s_lastGoodCondition; - s_condition = NULL; - s_lastGoodCondition = NULL; - - // user effectively cancelled if the condition is NULL - if (condition == NULL) { - n = 0; - } - - return (n == 1); -} - -void -CHotkeyOptions::CConditionDialog::doInit(HWND hwnd) -{ - // subclass edit control - HWND child = getItem(hwnd, IDC_HOTKEY_CONDITION_HOTKEY); - s_editWndProc = (WNDPROC)GetWindowLong(child, GWL_WNDPROC); - SetWindowLong(child, GWL_WNDPROC, (LONG)editProc); - - // fill control - fillHotkey(hwnd); -} - -void -CHotkeyOptions::CConditionDialog::fillHotkey(HWND hwnd) -{ - HWND child = getItem(hwnd, IDC_HOTKEY_CONDITION_HOTKEY); - if (s_condition != NULL) { - setWindowText(child, s_condition->format().c_str()); - } - else { - setWindowText(child, ""); - } -} - -void -CHotkeyOptions::CConditionDialog::onButton(HWND hwnd, ButtonID button) -{ - delete s_condition; - s_condition = - new CInputFilter::CMouseButtonCondition(button, getModifiers()); - - fillHotkey(GetParent(hwnd)); -} - -void -CHotkeyOptions::CConditionDialog::onKey(HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - // ignore key repeats - if ((lParam & 0xc0000000u) == 0x40000000u) { - return; - } - - // ignore key releases if the condition is complete and for the tab - // key (in case we were just tabbed to) - if ((lParam & 0x80000000u) != 0) { - if (isGoodCondition() || wParam == VK_TAB) { - return; - } - } - - KeyID key = kKeyNone; - KeyModifierMask mask = getModifiers(); - switch (wParam) { - case VK_SHIFT: - case VK_LSHIFT: - case VK_RSHIFT: - case VK_CONTROL: - case VK_LCONTROL: - case VK_RCONTROL: - case VK_MENU: - case VK_LMENU: - case VK_RMENU: - case VK_LWIN: - case VK_RWIN: - break; - - case VK_TAB: - // allow tabbing out of control - if ((mask & (KeyModifierControl | - KeyModifierAlt | KeyModifierSuper)) == 0) { - HWND next = hwnd; - if ((mask & KeyModifierShift) == 0) { - do { - next = GetWindow(next, GW_HWNDNEXT); - if (next == NULL) { - next = GetWindow(hwnd, GW_HWNDFIRST); - } - } while (next != hwnd && - (!IsWindowVisible(next) || - (GetWindowLong(next, GWL_STYLE) & WS_TABSTOP) == 0)); - } - else { - do { - next = GetWindow(next, GW_HWNDPREV); - if (next == NULL) { - next = GetWindow(hwnd, GW_HWNDLAST); - } - } while (next != hwnd && - (!IsWindowVisible(next) || - (GetWindowLong(next, GWL_STYLE) & WS_TABSTOP) == 0)); - } - SetFocus(next); - return; - } - // fall through - - default: - key = CMSWindowsKeyState::getKeyID(wParam, - static_cast((lParam & 0x1ff0000u) >> 16)); - switch (key) { - case kKeyNone: - // could be a character - key = getChar(wParam, lParam); - if (key == kKeyNone) { - return; - } - break; - - case kKeyShift_L: - case kKeyShift_R: - case kKeyControl_L: - case kKeyControl_R: - case kKeyAlt_L: - case kKeyAlt_R: - case kKeyMeta_L: - case kKeyMeta_R: - case kKeySuper_L: - case kKeySuper_R: - case kKeyCapsLock: - case kKeyNumLock: - case kKeyScrollLock: - // bogus - return; - } - break; - } - - delete s_condition; - s_condition = new CInputFilter::CKeystrokeCondition(key, mask); - - fillHotkey(GetParent(hwnd)); -} - -KeyID -CHotkeyOptions::CConditionDialog::getChar(WPARAM wParam, LPARAM lParam) -{ - BYTE keyState[256]; - UINT virtualKey = (UINT)wParam; - UINT scanCode = (UINT)((lParam & 0x0ff0000u) >> 16); - GetKeyboardState(keyState); - - // reset modifier state - keyState[VK_SHIFT] = 0; - keyState[VK_LSHIFT] = 0; - keyState[VK_RSHIFT] = 0; - keyState[VK_CONTROL] = 0; - keyState[VK_LCONTROL] = 0; - keyState[VK_RCONTROL] = 0; - keyState[VK_MENU] = 0; - keyState[VK_LMENU] = 0; - keyState[VK_RMENU] = 0; - keyState[VK_LWIN] = 0; - keyState[VK_RWIN] = 0; - - // translate virtual key to character - int n; - KeyID id; - if (CArchMiscWindows::isWindows95Family()) { - // XXX -- how do we get characters not in Latin-1? - WORD ascii; - n = ToAscii(virtualKey, scanCode, keyState, &ascii, 0); - id = static_cast(ascii & 0xffu); - } - else { - typedef int (WINAPI *ToUnicode_t)(UINT wVirtKey, - UINT wScanCode, - PBYTE lpKeyState, - LPWSTR pwszBuff, - int cchBuff, - UINT wFlags); - ToUnicode_t s_ToUnicode = NULL; - if (s_ToUnicode == NULL) { - HMODULE userModule = GetModuleHandle("user32.dll"); - s_ToUnicode = - (ToUnicode_t)GetProcAddress(userModule, "ToUnicode"); - } - - WCHAR unicode[2]; - n = s_ToUnicode(virtualKey, scanCode, keyState, - unicode, sizeof(unicode) / sizeof(unicode[0]), - 0); - id = static_cast(unicode[0]); - } - switch (n) { - case -1: - // no hot keys on dead keys - return kKeyNone; - - default: - case 0: - // unmapped - return kKeyNone; - - case 1: - return id; - } -} - -KeyModifierMask -CHotkeyOptions::CConditionDialog::getModifiers() -{ - KeyModifierMask mask = 0; - if ((GetKeyState(VK_SHIFT) & 0x8000) != 0) { - mask |= KeyModifierShift; - } - if ((GetKeyState(VK_CONTROL) & 0x8000) != 0) { - mask |= KeyModifierControl; - } - if ((GetKeyState(VK_MENU) & 0x8000) != 0) { - mask |= KeyModifierAlt; - } - if ((GetKeyState(VK_LWIN) & 0x8000) != 0 || - (GetKeyState(VK_RWIN) & 0x8000) != 0) { - mask |= KeyModifierSuper; - } - return mask; -} - -bool -CHotkeyOptions::CConditionDialog::isGoodCondition() -{ - CInputFilter::CKeystrokeCondition* keyCondition = - dynamic_cast(s_condition); - return (keyCondition == NULL || keyCondition->getKey() != kKeyNone); -} - -BOOL CALLBACK -CHotkeyOptions::CConditionDialog::dlgProc(HWND hwnd, - UINT message, WPARAM wParam, LPARAM) -{ - switch (message) { - case WM_INITDIALOG: - doInit(hwnd); - return TRUE; - - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDOK: - EndDialog(hwnd, 1); - return TRUE; - - case IDCANCEL: - EndDialog(hwnd, 0); - return TRUE; - } - break; - - default: - break; - } - - return FALSE; -} - -LRESULT CALLBACK -CHotkeyOptions::CConditionDialog::editProc(HWND hwnd, - UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) { - case WM_LBUTTONDOWN: - if (GetFocus() == hwnd) { - onButton(hwnd, kButtonLeft); - } - else { - SetFocus(hwnd); - } - return 0; - - case WM_MBUTTONDOWN: - if (GetFocus() == hwnd) { - onButton(hwnd, kButtonMiddle); - } - return 0; - - case WM_RBUTTONDOWN: - if (GetFocus() == hwnd) { - onButton(hwnd, kButtonRight); - } - return 0; - - case WM_XBUTTONDOWN: - if (GetFocus() == hwnd) { - switch (HIWORD(wParam)) { - case XBUTTON1: - onButton(hwnd, kButtonExtra0 + 0); - break; - - case XBUTTON2: - onButton(hwnd, kButtonExtra0 + 1); - break; - } - } - return 0; - - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - case WM_KEYUP: - case WM_SYSKEYUP: - onKey(hwnd, wParam, lParam); - return 0; - - case WM_LBUTTONUP: - case WM_MBUTTONUP: - case WM_RBUTTONUP: - case WM_XBUTTONUP: - case WM_CHAR: - case WM_SYSCHAR: - case WM_DEADCHAR: - case WM_SYSDEADCHAR: - return 0; - - case WM_SETFOCUS: - if (s_condition != NULL) { - delete s_lastGoodCondition; - s_lastGoodCondition = s_condition->clone(); - } - break; - - case WM_KILLFOCUS: - if (!isGoodCondition()) { - delete s_condition; - if (s_lastGoodCondition != NULL) { - s_condition = s_lastGoodCondition->clone(); - } - else { - s_condition = NULL; - } - } - fillHotkey(GetParent(hwnd)); - break; - - case WM_GETDLGCODE: - return DLGC_WANTALLKEYS; - - default: - break; - } - return CallWindowProc(s_editWndProc, hwnd, message, wParam, lParam); -} - - -// -// CHotkeyOptions::CActionDialog -// - -CConfig* CHotkeyOptions::CActionDialog::s_config = NULL; -bool CHotkeyOptions::CActionDialog::s_onActivate = false; -CInputFilter::CAction* - CHotkeyOptions::CActionDialog::s_action = NULL; -CInputFilter::CAction* - CHotkeyOptions::CActionDialog::s_lastGoodAction = NULL; -std::set - CHotkeyOptions::CActionDialog::s_screens; -WNDPROC CHotkeyOptions::CActionDialog::s_editWndProc = NULL; - -bool -CHotkeyOptions::CActionDialog::doModal(HWND parent, CConfig* config, - CInputFilter::CAction*& action, bool& onActivate) -{ - s_config = config; - s_onActivate = onActivate; - s_action = action; - if (s_action != NULL) { - s_lastGoodAction = s_action->clone(); - } - else { - s_lastGoodAction = NULL; - } - - int n = DialogBox(s_instance, MAKEINTRESOURCE(IDD_HOTKEY_ACTION), - parent, dlgProc); - - onActivate = s_onActivate; - action = s_action; - delete s_lastGoodAction; - s_action = NULL; - s_lastGoodAction = NULL; - - return (n == 1); -} - -void -CHotkeyOptions::CActionDialog::doInit(HWND hwnd) -{ - // subclass edit control - HWND child = getItem(hwnd, IDC_HOTKEY_ACTION_HOTKEY); - s_editWndProc = (WNDPROC)GetWindowLong(child, GWL_WNDPROC); - SetWindowLong(child, GWL_WNDPROC, (LONG)editProc); - setWindowText(getItem(hwnd, IDC_HOTKEY_ACTION_HOTKEY), ""); - fillHotkey(hwnd); - - // fill screens - child = getItem(hwnd, IDC_HOTKEY_ACTION_SWITCH_TO_LIST); - SendMessage(child, CB_RESETCONTENT, 0, 0); - for (CConfig::const_iterator index = s_config->begin(); - index != s_config->end(); ) { - const CString& name = *index; - ++index; - if (index != s_config->end()) { - SendMessage(child, CB_INSERTSTRING, - (WPARAM)-1, (LPARAM)name.c_str()); - } - else { - SendMessage(child, CB_ADDSTRING, 0, (LPARAM)name.c_str()); - } - } - SendMessage(child, CB_SETCURSEL, 0, 0); - - // fill directions - child = getItem(hwnd, IDC_HOTKEY_ACTION_SWITCH_IN_LIST); - SendMessage(child, CB_ADDSTRING, 0, - (LPARAM)getString(IDS_EDGE_LEFT).c_str()); - SendMessage(child, CB_ADDSTRING, 0, - (LPARAM)getString(IDS_EDGE_RIGHT).c_str()); - SendMessage(child, CB_ADDSTRING, 0, - (LPARAM)getString(IDS_EDGE_TOP).c_str()); - SendMessage(child, CB_ADDSTRING, 0, - (LPARAM)getString(IDS_EDGE_BOTTOM).c_str()); - SendMessage(child, CB_SETCURSEL, 0, 0); - - // fill lock modes - child = getItem(hwnd, IDC_HOTKEY_ACTION_LOCK_LIST); - SendMessage(child, CB_ADDSTRING, 0, - (LPARAM)getString(IDS_MODE_OFF).c_str()); - SendMessage(child, CB_ADDSTRING, 0, - (LPARAM)getString(IDS_MODE_ON).c_str()); - SendMessage(child, CB_ADDSTRING, 0, - (LPARAM)getString(IDS_MODE_TOGGLE).c_str()); - SendMessage(child, CB_SETCURSEL, 0, 0); - - // fill keyboard broadcast modes - child = getItem(hwnd, IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST_LIST); - SendMessage(child, CB_ADDSTRING, 0, - (LPARAM)getString(IDS_MODE_OFF).c_str()); - SendMessage(child, CB_ADDSTRING, 0, - (LPARAM)getString(IDS_MODE_ON).c_str()); - SendMessage(child, CB_ADDSTRING, 0, - (LPARAM)getString(IDS_MODE_TOGGLE).c_str()); - SendMessage(child, CB_SETCURSEL, 0, 0); - - // select when - if (s_onActivate) { - child = getItem(hwnd, IDC_HOTKEY_ACTION_ON_ACTIVATE); - } - else { - child = getItem(hwnd, IDC_HOTKEY_ACTION_ON_DEACTIVATE); - } - setItemChecked(child, true); - - // no screens by default - s_screens.clear(); - - // select mode - child = NULL; - CInputFilter::CKeystrokeAction* keyAction = - dynamic_cast(s_action); - CInputFilter::CMouseButtonAction* mouseAction = - dynamic_cast(s_action); - CInputFilter::CLockCursorToScreenAction* lockAction = - dynamic_cast(s_action); - CInputFilter::CSwitchToScreenAction* switchToAction = - dynamic_cast(s_action); - CInputFilter::CSwitchInDirectionAction* switchInAction = - dynamic_cast(s_action); - CInputFilter::CKeyboardBroadcastAction* keyboardBroadcastAction= - dynamic_cast(s_action); - if (keyAction != NULL) { - if (dynamic_cast(s_action) != NULL) { - child = getItem(hwnd, IDC_HOTKEY_ACTION_DOWNUP); - } - else if (keyAction->isOnPress()) { - child = getItem(hwnd, IDC_HOTKEY_ACTION_DOWN); - } - else { - child = getItem(hwnd, IDC_HOTKEY_ACTION_UP); - } - } - else if (mouseAction != NULL) { - if (dynamic_cast(s_action) != NULL) { - child = getItem(hwnd, IDC_HOTKEY_ACTION_DOWNUP); - } - else if (keyAction->isOnPress()) { - child = getItem(hwnd, IDC_HOTKEY_ACTION_DOWN); - } - else { - child = getItem(hwnd, IDC_HOTKEY_ACTION_UP); - } - } - else if (lockAction != NULL) { - child = getItem(hwnd, IDC_HOTKEY_ACTION_LOCK_LIST); - SendMessage(child, CB_SETCURSEL, lockAction->getMode(), 0); - child = getItem(hwnd, IDC_HOTKEY_ACTION_LOCK); - } - else if (switchToAction != NULL) { - child = getItem(hwnd, IDC_HOTKEY_ACTION_SWITCH_TO_LIST); - DWORD i = SendMessage(child, CB_FINDSTRINGEXACT, (WPARAM)-1, - (LPARAM)switchToAction->getScreen().c_str()); - if (i == CB_ERR) { - i = 0; - } - SendMessage(child, CB_SETCURSEL, i, 0); - child = getItem(hwnd, IDC_HOTKEY_ACTION_SWITCH_TO); - } - else if (switchInAction != NULL) { - child = getItem(hwnd, IDC_HOTKEY_ACTION_SWITCH_IN_LIST); - SendMessage(child, CB_SETCURSEL, - switchInAction->getDirection() - kLeft, 0); - child = getItem(hwnd, IDC_HOTKEY_ACTION_SWITCH_IN); - } - else if (keyboardBroadcastAction != NULL) { - // Save the screens we're broadcasting to - s_screens = keyboardBroadcastAction->getScreens(); - - child = getItem(hwnd, IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST_LIST); - SendMessage(child, CB_SETCURSEL, keyboardBroadcastAction->getMode(), 0); - child = getItem(hwnd, IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST); - } - if (child != NULL) { - setItemChecked(child, true); - } - - updateControls(hwnd); -} - -void -CHotkeyOptions::CActionDialog::fillHotkey(HWND hwnd) -{ - HWND child = getItem(hwnd, IDC_HOTKEY_ACTION_HOTKEY); - CInputFilter::CKeystrokeAction* keyAction = - dynamic_cast(s_action); - CInputFilter::CMouseButtonAction* mouseAction = - dynamic_cast(s_action); - if (keyAction != NULL || mouseAction != NULL) { - setWindowText(child, s_action->format().c_str()); - } - else { - setWindowText(child, ""); - } - - // can only set screens in key actions - enableItem(hwnd, IDC_HOTKEY_ACTION_SCREENS, keyAction != NULL); -} - -void -CHotkeyOptions::CActionDialog::updateControls(HWND hwnd) -{ - // determine which mode we're in - UInt32 mode = 0; - if (isItemChecked(getItem(hwnd, IDC_HOTKEY_ACTION_DOWNUP)) || - isItemChecked(getItem(hwnd, IDC_HOTKEY_ACTION_DOWN)) || - isItemChecked(getItem(hwnd, IDC_HOTKEY_ACTION_UP))) { - mode = 1; - } - else if (isItemChecked(getItem(hwnd, IDC_HOTKEY_ACTION_SWITCH_TO))) { - mode = 2; - } - else if (isItemChecked(getItem(hwnd, IDC_HOTKEY_ACTION_SWITCH_IN))) { - mode = 3; - } - else if (isItemChecked(getItem(hwnd, IDC_HOTKEY_ACTION_LOCK))) { - mode = 4; - } - else if (isItemChecked(getItem(hwnd, - IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST))) { - mode = 5; - } - - // enable/disable all mode specific controls - enableItem(hwnd, IDC_HOTKEY_ACTION_HOTKEY, mode == 1); - enableItem(hwnd, IDC_HOTKEY_ACTION_SWITCH_TO_LIST, mode == 2); - enableItem(hwnd, IDC_HOTKEY_ACTION_SWITCH_IN_LIST, mode == 3); - enableItem(hwnd, IDC_HOTKEY_ACTION_LOCK_LIST, mode == 4); - enableItem(hwnd, IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST_LIST, mode == 5); - enableItem(hwnd, IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST_SCREENS, mode == 5); - - // can only set screens in key actions - CInputFilter::CKeystrokeAction* keyAction = - dynamic_cast(s_action); - enableItem(hwnd, IDC_HOTKEY_ACTION_SCREENS, keyAction != NULL); -} - -void -CHotkeyOptions::CActionDialog::onButton(HWND hwnd, ButtonID button) -{ - IPlatformScreen::CButtonInfo* info = - IPrimaryScreen::CButtonInfo::alloc(button, getModifiers()); - delete s_action; - HWND parent = GetParent(hwnd); - if (isItemChecked(getItem(parent, IDC_HOTKEY_ACTION_DOWNUP))) { - s_action = new CMouseButtonDownUpAction(info); - } - else if (isItemChecked(getItem(parent, IDC_HOTKEY_ACTION_DOWN))) { - s_action = new CInputFilter::CMouseButtonAction(info, true); - } - else if (isItemChecked(getItem(parent, IDC_HOTKEY_ACTION_UP))) { - s_action = new CInputFilter::CMouseButtonAction(info, false); - } - else { - s_action = NULL; - } - - fillHotkey(parent); -} - -void -CHotkeyOptions::CActionDialog::onKey(HWND hwnd, WPARAM wParam, LPARAM lParam) -{ - // ignore key repeats - if ((lParam & 0xc0000000u) == 0x40000000u) { - return; - } - - // ignore key releases if the action is complete and for the tab - // key (in case we were just tabbed to) - if ((lParam & 0x80000000u) != 0) { - if (isGoodAction() || wParam == VK_TAB) { - return; - } - } - - KeyID key = kKeyNone; - KeyModifierMask mask = getModifiers(); - switch (wParam) { - case VK_SHIFT: - case VK_LSHIFT: - case VK_RSHIFT: - case VK_CONTROL: - case VK_LCONTROL: - case VK_RCONTROL: - case VK_MENU: - case VK_LMENU: - case VK_RMENU: - case VK_LWIN: - case VK_RWIN: - break; - - case VK_TAB: - // allow tabbing out of control - if ((mask & (KeyModifierControl | - KeyModifierAlt | KeyModifierSuper)) == 0) { - HWND next = hwnd; - if ((mask & KeyModifierShift) == 0) { - do { - next = GetWindow(next, GW_HWNDNEXT); - if (next == NULL) { - next = GetWindow(hwnd, GW_HWNDFIRST); - } - } while (next != hwnd && - (!IsWindowVisible(next) || - (GetWindowLong(next, GWL_STYLE) & WS_TABSTOP) == 0)); - } - else { - do { - next = GetWindow(next, GW_HWNDPREV); - if (next == NULL) { - next = GetWindow(hwnd, GW_HWNDLAST); - } - } while (next != hwnd && - (!IsWindowVisible(next) || - (GetWindowLong(next, GWL_STYLE) & WS_TABSTOP) == 0)); - } - SetFocus(next); - return; - } - // fall through - - default: - key = CMSWindowsKeyState::getKeyID(wParam, - static_cast((lParam & 0x1ff0000u) >> 16)); - switch (key) { - case kKeyNone: - // could be a character - key = getChar(wParam, lParam); - if (key == kKeyNone) { - return; - } - break; - - case kKeyShift_L: - case kKeyShift_R: - case kKeyControl_L: - case kKeyControl_R: - case kKeyAlt_L: - case kKeyAlt_R: - case kKeyMeta_L: - case kKeyMeta_R: - case kKeySuper_L: - case kKeySuper_R: - case kKeyCapsLock: - case kKeyNumLock: - case kKeyScrollLock: - // bogus - return; - } - break; - } - - // get old screen list - std::set screens; - CInputFilter::CKeystrokeAction* keyAction = - dynamic_cast(s_action); - if (keyAction == NULL) { - keyAction = - dynamic_cast(s_lastGoodAction); - } - if (keyAction != NULL) { - IKeyState::CKeyInfo::split(keyAction->getInfo()->m_screens, screens); - } - - // create new action - IPlatformScreen::CKeyInfo* info = - IKeyState::CKeyInfo::alloc(key, mask, 0, 0, screens); - delete s_action; - HWND parent = GetParent(hwnd); - if (isItemChecked(getItem(parent, IDC_HOTKEY_ACTION_DOWNUP))) { - s_action = new CKeystrokeDownUpAction(info); - } - else if (isItemChecked(getItem(parent, IDC_HOTKEY_ACTION_DOWN))) { - s_action = new CInputFilter::CKeystrokeAction(info, true); - } - else if (isItemChecked(getItem(parent, IDC_HOTKEY_ACTION_UP))) { - s_action = new CInputFilter::CKeystrokeAction(info, false); - } - else { - s_action = NULL; - } - - fillHotkey(parent); -} - -void -CHotkeyOptions::CActionDialog::onLockAction(HWND hwnd) -{ - HWND child = getItem(hwnd, IDC_HOTKEY_ACTION_LOCK_LIST); - LRESULT index = SendMessage(child, CB_GETCURSEL, 0, 0); - if (index != CB_ERR) { - delete s_action; - s_action = new CInputFilter::CLockCursorToScreenAction( - (CInputFilter::CLockCursorToScreenAction::Mode)index); - } -} - -void -CHotkeyOptions::CActionDialog::onSwitchToAction(HWND hwnd) -{ - HWND child = getItem(hwnd, IDC_HOTKEY_ACTION_SWITCH_TO_LIST); - CString screen = getWindowText(child); - delete s_action; - s_action = new CInputFilter::CSwitchToScreenAction(screen); -} - -void -CHotkeyOptions::CActionDialog::onSwitchInAction(HWND hwnd) -{ - HWND child = getItem(hwnd, IDC_HOTKEY_ACTION_SWITCH_IN_LIST); - LRESULT index = SendMessage(child, CB_GETCURSEL, 0, 0); - if (index != CB_ERR) { - delete s_action; - s_action = new CInputFilter::CSwitchInDirectionAction( - (EDirection)(index + kLeft)); - } -} - -void -CHotkeyOptions::CActionDialog::onKeyboardBroadcastAction(HWND hwnd) -{ - HWND child = getItem(hwnd, IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST_LIST); - LRESULT index = SendMessage(child, CB_GETCURSEL, 0, 0); - if (index != CB_ERR) { - delete s_action; - s_action = new CInputFilter::CKeyboardBroadcastAction( - (CInputFilter::CKeyboardBroadcastAction::Mode)index, s_screens); - } -} - -KeyID -CHotkeyOptions::CActionDialog::getChar(WPARAM wParam, LPARAM lParam) -{ - BYTE keyState[256]; - UINT virtualKey = (UINT)wParam; - UINT scanCode = (UINT)((lParam & 0x0ff0000u) >> 16); - GetKeyboardState(keyState); - - // reset modifier state - keyState[VK_SHIFT] = 0; - keyState[VK_LSHIFT] = 0; - keyState[VK_RSHIFT] = 0; - keyState[VK_CONTROL] = 0; - keyState[VK_LCONTROL] = 0; - keyState[VK_RCONTROL] = 0; - keyState[VK_MENU] = 0; - keyState[VK_LMENU] = 0; - keyState[VK_RMENU] = 0; - keyState[VK_LWIN] = 0; - keyState[VK_RWIN] = 0; - - // translate virtual key to character - int n; - KeyID id; - if (CArchMiscWindows::isWindows95Family()) { - // XXX -- how do we get characters not in Latin-1? - WORD ascii; - n = ToAscii(virtualKey, scanCode, keyState, &ascii, 0); - id = static_cast(ascii & 0xffu); - } - else { - typedef int (WINAPI *ToUnicode_t)(UINT wVirtKey, - UINT wScanCode, - PBYTE lpKeyState, - LPWSTR pwszBuff, - int cchBuff, - UINT wFlags); - ToUnicode_t s_ToUnicode = NULL; - if (s_ToUnicode == NULL) { - HMODULE userModule = GetModuleHandle("user32.dll"); - s_ToUnicode = - (ToUnicode_t)GetProcAddress(userModule, "ToUnicode"); - } - - WCHAR unicode[2]; - n = s_ToUnicode(virtualKey, scanCode, keyState, - unicode, sizeof(unicode) / sizeof(unicode[0]), - 0); - id = static_cast(unicode[0]); - } - switch (n) { - case -1: - // no hot keys on dead keys - return kKeyNone; - - default: - case 0: - // unmapped - return kKeyNone; - - case 1: - return id; - } -} - -KeyModifierMask -CHotkeyOptions::CActionDialog::getModifiers() -{ - KeyModifierMask mask = 0; - if ((GetKeyState(VK_SHIFT) & 0x8000) != 0) { - mask |= KeyModifierShift; - } - if ((GetKeyState(VK_CONTROL) & 0x8000) != 0) { - mask |= KeyModifierControl; - } - if ((GetKeyState(VK_MENU) & 0x8000) != 0) { - mask |= KeyModifierAlt; - } - if ((GetKeyState(VK_LWIN) & 0x8000) != 0 || - (GetKeyState(VK_RWIN) & 0x8000) != 0) { - mask |= KeyModifierSuper; - } - return mask; -} - -bool -CHotkeyOptions::CActionDialog::isGoodAction() -{ - CInputFilter::CMouseButtonAction* mouseAction = - dynamic_cast(s_action); - CInputFilter::CKeystrokeAction* keyAction = - dynamic_cast(s_action); - return (mouseAction == NULL || keyAction == NULL || - keyAction->getInfo()->m_key != kKeyNone); -} - -void -CHotkeyOptions::CActionDialog::convertAction(HWND hwnd) -{ - if (s_lastGoodAction != NULL) { - CInputFilter::CMouseButtonAction* mouseAction = - dynamic_cast(s_lastGoodAction); - CInputFilter::CKeystrokeAction* keyAction = - dynamic_cast(s_lastGoodAction); - if (mouseAction != NULL) { - IPlatformScreen::CButtonInfo* info = - IPrimaryScreen::CButtonInfo::alloc(*mouseAction->getInfo()); - delete s_action; - if (isItemChecked(getItem(hwnd, IDC_HOTKEY_ACTION_DOWNUP))) { - s_action = new CMouseButtonDownUpAction(info); - } - else if (isItemChecked(getItem(hwnd, IDC_HOTKEY_ACTION_DOWN))) { - s_action = new CInputFilter::CMouseButtonAction(info, true); - } - else if (isItemChecked(getItem(hwnd, IDC_HOTKEY_ACTION_UP))) { - s_action = new CInputFilter::CMouseButtonAction(info, false); - } - else { - free(info); - s_action = NULL; - } - } - else if (keyAction != NULL) { - IPlatformScreen::CKeyInfo* info = - IKeyState::CKeyInfo::alloc(*keyAction->getInfo()); - delete s_action; - if (isItemChecked(getItem(hwnd, IDC_HOTKEY_ACTION_DOWNUP))) { - s_action = new CKeystrokeDownUpAction(info); - } - else if (isItemChecked(getItem(hwnd, IDC_HOTKEY_ACTION_DOWN))) { - s_action = new CInputFilter::CKeystrokeAction(info, true); - } - else if (isItemChecked(getItem(hwnd, IDC_HOTKEY_ACTION_UP))) { - s_action = new CInputFilter::CKeystrokeAction(info, false); - } - else { - free(info); - s_action = NULL; - } - } - } -} - -bool -CHotkeyOptions::CActionDialog::isDownUpAction() -{ - return (dynamic_cast(s_action) != NULL || - dynamic_cast(s_action) != NULL); -} - -BOOL CALLBACK -CHotkeyOptions::CActionDialog::dlgProc(HWND hwnd, - UINT message, WPARAM wParam, LPARAM) -{ - switch (message) { - case WM_INITDIALOG: - doInit(hwnd); - return TRUE; - - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDOK: - if (isDownUpAction()) { - s_onActivate = true; - } - EndDialog(hwnd, 1); - return TRUE; - - case IDCANCEL: - EndDialog(hwnd, 0); - return TRUE; - - case IDC_HOTKEY_ACTION_ON_ACTIVATE: - s_onActivate = true; - return TRUE; - - case IDC_HOTKEY_ACTION_ON_DEACTIVATE: - s_onActivate = false; - return TRUE; - - case IDC_HOTKEY_ACTION_DOWNUP: - case IDC_HOTKEY_ACTION_DOWN: - case IDC_HOTKEY_ACTION_UP: - convertAction(hwnd); - fillHotkey(hwnd); - updateControls(hwnd); - return TRUE; - - case IDC_HOTKEY_ACTION_LOCK: - onLockAction(hwnd); - updateControls(hwnd); - return TRUE; - - case IDC_HOTKEY_ACTION_SWITCH_TO: - onSwitchToAction(hwnd); - updateControls(hwnd); - return TRUE; - - case IDC_HOTKEY_ACTION_SWITCH_IN: - onSwitchInAction(hwnd); - updateControls(hwnd); - return TRUE; - - case IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST: - onKeyboardBroadcastAction(hwnd); - updateControls(hwnd); - return TRUE; - - case IDC_HOTKEY_ACTION_LOCK_LIST: - switch (HIWORD(wParam)) { - case LBN_SELCHANGE: - onLockAction(hwnd); - return TRUE; - } - break; - - case IDC_HOTKEY_ACTION_SWITCH_TO_LIST: - switch (HIWORD(wParam)) { - case LBN_SELCHANGE: - onSwitchToAction(hwnd); - return TRUE; - } - break; - - case IDC_HOTKEY_ACTION_SWITCH_IN_LIST: - switch (HIWORD(wParam)) { - case LBN_SELCHANGE: - onSwitchInAction(hwnd); - return TRUE; - } - break; - - case IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST_LIST: - switch (HIWORD(wParam)) { - case LBN_SELCHANGE: - onKeyboardBroadcastAction(hwnd); - return TRUE; - } - break; - - case IDC_HOTKEY_ACTION_SCREENS: - CScreensDialog::doModal(hwnd, s_config, - dynamic_cast(s_action)); - fillHotkey(hwnd); - return TRUE; - - case IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST_SCREENS: { - // convert screens to form that CScreenDialog::doModal() wants - IPlatformScreen::CKeyInfo* tmpInfo = - IPlatformScreen::CKeyInfo::alloc(0, 0, 0, 1, s_screens); - CInputFilter::CKeystrokeAction tmpAction(tmpInfo, true); - - // get the screens - CScreensDialog::doModal(hwnd, s_config, &tmpAction); - - // convert screens back - IPlatformScreen::CKeyInfo::split( - tmpAction.getInfo()->m_screens, s_screens); - - // update - onKeyboardBroadcastAction(hwnd); - return TRUE; - } - } - break; - - default: - break; - } - - return FALSE; -} - -LRESULT CALLBACK -CHotkeyOptions::CActionDialog::editProc(HWND hwnd, - UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) { - case WM_LBUTTONDOWN: - if (GetFocus() == hwnd) { - onButton(hwnd, kButtonLeft); - } - else { - SetFocus(hwnd); - } - return 0; - - case WM_MBUTTONDOWN: - if (GetFocus() == hwnd) { - onButton(hwnd, kButtonMiddle); - } - return 0; - - case WM_RBUTTONDOWN: - if (GetFocus() == hwnd) { - onButton(hwnd, kButtonRight); - } - return 0; - - case WM_XBUTTONDOWN: - if (GetFocus() == hwnd) { - switch (HIWORD(wParam)) { - case XBUTTON1: - onButton(hwnd, kButtonExtra0 + 0); - break; - - case XBUTTON2: - onButton(hwnd, kButtonExtra0 + 1); - break; - } - } - return 0; - - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - case WM_KEYUP: - case WM_SYSKEYUP: - onKey(hwnd, wParam, lParam); - return 0; - - case WM_LBUTTONUP: - case WM_MBUTTONUP: - case WM_RBUTTONUP: - case WM_XBUTTONUP: - case WM_CHAR: - case WM_SYSCHAR: - case WM_DEADCHAR: - case WM_SYSDEADCHAR: - return 0; - - case WM_SETFOCUS: - if (s_action != NULL) { - delete s_lastGoodAction; - s_lastGoodAction = s_action->clone(); - } - break; - - case WM_KILLFOCUS: - if (!isGoodAction()) { - delete s_action; - if (s_lastGoodAction != NULL) { - s_action = s_lastGoodAction->clone(); - } - else { - s_action = NULL; - } - } - else if (s_action != NULL) { - delete s_lastGoodAction; - s_lastGoodAction = s_action->clone(); - } - fillHotkey(GetParent(hwnd)); - break; - - case WM_GETDLGCODE: - return DLGC_WANTALLKEYS; - - default: - break; - } - return CallWindowProc(s_editWndProc, hwnd, message, wParam, lParam); -} - - -// -// CHotkeyOptions::CScreensDialog -// - -CConfig* CHotkeyOptions::CScreensDialog::s_config = NULL; -CInputFilter::CKeystrokeAction* - CHotkeyOptions::CScreensDialog::s_action = NULL; -CHotkeyOptions::CScreensDialog::CScreens - CHotkeyOptions::CScreensDialog::s_nonTargets; -CHotkeyOptions::CScreensDialog::CScreens - CHotkeyOptions::CScreensDialog::s_targets; -CString CHotkeyOptions::CScreensDialog::s_allScreens; - -void -CHotkeyOptions::CScreensDialog::doModal(HWND parent, CConfig* config, - CInputFilter::CKeystrokeAction* action) -{ - s_allScreens = getString(IDS_ALL_SCREENS); - s_config = config; - s_action = action; - DialogBox(s_instance, MAKEINTRESOURCE(IDD_HOTKEY_SCREENS), - parent, dlgProc); - s_config = NULL; - s_action = NULL; -} - -void -CHotkeyOptions::CScreensDialog::doInit(HWND hwnd) -{ - s_nonTargets.clear(); - s_targets.clear(); - - // get screens from config - s_nonTargets.insert("*"); - for (CConfig::const_iterator i = s_config->begin(); - i != s_config->end(); ++i) { - s_nonTargets.insert(*i); - } - - // get screens in action - IKeyState::CKeyInfo::split(s_action->getInfo()->m_screens, s_targets); - - // remove screens in action from screens in config - for (CScreens::const_iterator i = s_targets.begin(); - i != s_targets.end(); ++i) { - s_nonTargets.erase(*i); - } - - // fill dialog - fillScreens(hwnd); - updateControls(hwnd); -} - -void -CHotkeyOptions::CScreensDialog::doFini(HWND) -{ - // put screens into action - const IPlatformScreen::CKeyInfo* oldInfo = s_action->getInfo(); - IPlatformScreen::CKeyInfo* newInfo = - IKeyState::CKeyInfo::alloc(oldInfo->m_key, - oldInfo->m_mask, 0, 0, s_targets); - s_action->adoptInfo(newInfo); -} - -void -CHotkeyOptions::CScreensDialog::fillScreens(HWND hwnd) -{ - HWND child = getItem(hwnd, IDC_HOTKEY_SCREENS_SRC); - SendMessage(child, LB_RESETCONTENT, 0, 0); - for (CScreens::const_iterator i = s_nonTargets.begin(); - i != s_nonTargets.end(); ++i) { - CString name = *i; - if (name == "*") { - name = s_allScreens; - } - SendMessage(child, LB_INSERTSTRING, (WPARAM)-1, - (LPARAM)name.c_str()); - } - - child = getItem(hwnd, IDC_HOTKEY_SCREENS_DST); - SendMessage(child, LB_RESETCONTENT, 0, 0); - for (CScreens::const_iterator i = s_targets.begin(); - i != s_targets.end(); ++i) { - CString name = *i; - if (name == "*") { - name = s_allScreens; - } - SendMessage(child, LB_INSERTSTRING, (WPARAM)-1, - (LPARAM)name.c_str()); - } - if (s_targets.empty()) { - // if no targets then add a special item so the user knows - // what'll happen - CString activeScreenLabel = getString(IDS_ACTIVE_SCREEN); - SendMessage(child, LB_INSERTSTRING, (WPARAM)-1, - (LPARAM)activeScreenLabel.c_str()); - } -} - -void -CHotkeyOptions::CScreensDialog::updateControls(HWND hwnd) -{ - HWND child = getItem(hwnd, IDC_HOTKEY_SCREENS_SRC); - bool canAdd = (SendMessage(child, LB_GETSELCOUNT, 0, 0) != 0); - child = getItem(hwnd, IDC_HOTKEY_SCREENS_DST); - bool canRemove = (!s_targets.empty() && - (SendMessage(child, LB_GETSELCOUNT, 0, 0) != 0)); - - enableItem(hwnd, IDC_HOTKEY_SCREENS_ADD, canAdd); - enableItem(hwnd, IDC_HOTKEY_SCREENS_REMOVE, canRemove); -} - -void -CHotkeyOptions::CScreensDialog::add(HWND hwnd) -{ - CScreens selected; - getSelected(hwnd, IDC_HOTKEY_SCREENS_SRC, s_nonTargets, selected); - for (CScreens::const_iterator i = selected.begin(); - i != selected.end(); ++i) { - s_targets.insert(*i); - s_nonTargets.erase(*i); - } - fillScreens(hwnd); - updateControls(hwnd); -} - -void -CHotkeyOptions::CScreensDialog::remove(HWND hwnd) -{ - CScreens selected; - getSelected(hwnd, IDC_HOTKEY_SCREENS_DST, s_targets, selected); - for (CScreens::const_iterator i = selected.begin(); - i != selected.end(); ++i) { - s_nonTargets.insert(*i); - s_targets.erase(*i); - } - fillScreens(hwnd); - updateControls(hwnd); -} - -void -CHotkeyOptions::CScreensDialog::getSelected(HWND hwnd, UINT id, - const CScreens& inScreens, CScreens& outScreens) -{ - // get the selected item indices - HWND child = getItem(hwnd, id); - UInt32 n = (UInt32)SendMessage(child, LB_GETSELCOUNT, 0, 0); - int* index = new int[n]; - SendMessage(child, LB_GETSELITEMS, (WPARAM)n, (LPARAM)index); - - // get the items in a vector - std::vector tmpList; - for (CScreens::const_iterator i = inScreens.begin(); - i != inScreens.end(); ++i) { - tmpList.push_back(*i); - } - - // get selected items into the output set - outScreens.clear(); - for (UInt32 i = 0; i < n; ++i) { - outScreens.insert(tmpList[index[i]]); - } - - // clean up - delete[] index; -} - -BOOL CALLBACK -CHotkeyOptions::CScreensDialog::dlgProc(HWND hwnd, - UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) { - case WM_INITDIALOG: - doInit(hwnd); - return TRUE; - - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDOK: - doFini(hwnd); - EndDialog(hwnd, 0); - return TRUE; - - case IDCANCEL: - EndDialog(hwnd, 0); - return TRUE; - - case IDC_HOTKEY_SCREENS_ADD: - add(hwnd); - return TRUE; - - case IDC_HOTKEY_SCREENS_REMOVE: - remove(hwnd); - return TRUE; - - case IDC_HOTKEY_SCREENS_SRC: - case IDC_HOTKEY_SCREENS_DST: - switch (HIWORD(wParam)) { - case LBN_SELCANCEL: - case LBN_SELCHANGE: - updateControls(hwnd); - return TRUE; - } - break; - } - break; - - case WM_CTLCOLORLISTBOX: - if (s_targets.empty() && - (HWND)lParam == getItem(hwnd, IDC_HOTKEY_SCREENS_DST)) { - // override colors - HDC dc = (HDC)wParam; - SetTextColor(dc, GetSysColor(COLOR_GRAYTEXT)); - return (BOOL)GetSysColorBrush(COLOR_WINDOW); - } - break; - - default: - break; - } - - return FALSE; -} diff --git a/cmd/launcher/CHotkeyOptions.h b/cmd/launcher/CHotkeyOptions.h deleted file mode 100644 index dec5367a..00000000 --- a/cmd/launcher/CHotkeyOptions.h +++ /dev/null @@ -1,227 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2006 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CHOTKEYOPTIONS_H -#define CHOTKEYOPTIONS_H - -#include "CString.h" -#include "KeyTypes.h" -#include "MouseTypes.h" -#include "CInputFilter.h" - -#define WINDOWS_LEAN_AND_MEAN -#include - -class CConfig; - -//! Hotkey options dialog for Microsoft Windows launcher -class CHotkeyOptions { -public: - CHotkeyOptions(HWND parent, CConfig*); - ~CHotkeyOptions(); - - //! @name manipulators - //@{ - - //! Run dialog - /*! - Display and handle the dialog until closed by the user. - */ - void doModal(); - - //@} - //! @name accessors - //@{ - - //@} - -private: - void doInit(HWND hwnd); - - void fillHotkeys(HWND hwnd, UInt32 select = (UInt32)-1); - void updateHotkeysControls(HWND hwnd); - - void addHotkey(HWND hwnd); - void removeHotkey(HWND hwnd); - void editHotkey(HWND hwnd); - - void fillActions(HWND hwnd, UInt32 select = (UInt32)-1); - void updateActionsControls(HWND hwnd); - - void addAction(HWND hwnd); - void removeAction(HWND hwnd); - void editAction(HWND hwnd); - - bool editCondition(HWND hwnd, CInputFilter::CCondition*&); - bool editAction(HWND hwnd, CInputFilter::CAction*&, - bool& onActivate); - - void openRule(HWND hwnd); - void closeRule(HWND hwnd); - UInt32 findMatchingAction( - const CInputFilter::CKeystrokeAction*) const; - UInt32 findMatchingAction( - const CInputFilter::CMouseButtonAction*) const; - - // message handling - BOOL doDlgProc(HWND, UINT, WPARAM, LPARAM); - static BOOL CALLBACK dlgProc(HWND, UINT, WPARAM, LPARAM); - - // special actions we use to combine matching down/up actions into a - // single action for the convenience of the user. - class CKeystrokeDownUpAction : public CInputFilter::CKeystrokeAction { - public: - CKeystrokeDownUpAction(IPlatformScreen::CKeyInfo* adoptedInfo) : - CInputFilter::CKeystrokeAction(adoptedInfo, true) { } - - // CAction overrides - virtual CInputFilter::CAction* clone() const - { - IKeyState::CKeyInfo* info = IKeyState::CKeyInfo::alloc(*getInfo()); - return new CKeystrokeDownUpAction(info); - } - - protected: - // CKeystrokeAction overrides - virtual const char* formatName() const { return "keystroke"; } - }; - class CMouseButtonDownUpAction : public CInputFilter::CMouseButtonAction { - public: - CMouseButtonDownUpAction(IPrimaryScreen::CButtonInfo* adoptedInfo) : - CInputFilter::CMouseButtonAction(adoptedInfo, true) { } - - // CAction overrides - virtual CInputFilter::CAction* clone() const - { - IPlatformScreen::CButtonInfo* info = - IPrimaryScreen::CButtonInfo::alloc(*getInfo()); - return new CMouseButtonDownUpAction(info); - } - - protected: - // CMouseButtonAction overrides - virtual const char* formatName() const { return "mousebutton"; } - }; - - class CConditionDialog { - public: - static bool doModal(HWND parent, CInputFilter::CCondition*&); - - private: - static void doInit(HWND hwnd); - static void fillHotkey(HWND hwnd); - - static void onButton(HWND hwnd, ButtonID button); - static void onKey(HWND hwnd, WPARAM wParam, LPARAM lParam); - static KeyID getChar(WPARAM wParam, LPARAM lParam); - static KeyModifierMask - getModifiers(); - - static bool isGoodCondition(); - - static BOOL CALLBACK dlgProc(HWND, UINT, WPARAM, LPARAM); - static LRESULT CALLBACK editProc(HWND hwnd, UINT, WPARAM, LPARAM); - - private: - static CInputFilter::CCondition* - s_condition; - static CInputFilter::CCondition* - s_lastGoodCondition; - static WNDPROC s_editWndProc; - }; - - class CActionDialog { - public: - static bool doModal(HWND parent, CConfig* config, - CInputFilter::CAction*&, bool& onActivate); - - private: - static void doInit(HWND hwnd); - static void fillHotkey(HWND hwnd); - static void updateControls(HWND hwnd); - - static void onButton(HWND hwnd, ButtonID button); - static void onKey(HWND hwnd, WPARAM wParam, LPARAM lParam); - static void onLockAction(HWND hwnd); - static void onSwitchToAction(HWND hwnd); - static void onSwitchInAction(HWND hwnd); - static void onKeyboardBroadcastAction(HWND hwnd); - - static KeyID getChar(WPARAM wParam, LPARAM lParam); - static KeyModifierMask - getModifiers(); - - static bool isGoodAction(); - static void convertAction(HWND hwnd); - - static bool isDownUpAction(); - - static BOOL CALLBACK dlgProc(HWND, UINT, WPARAM, LPARAM); - static LRESULT CALLBACK editProc(HWND hwnd, UINT, WPARAM, LPARAM); - - private: - static CConfig* s_config; - static bool s_onActivate; - static CInputFilter::CAction* - s_action; - static CInputFilter::CAction* - s_lastGoodAction; - static std::set s_screens; - static WNDPROC s_editWndProc; - }; - -// public to allow CActionDialog to use it -public: - class CScreensDialog { - public: - static void doModal(HWND parent, CConfig* config, - CInputFilter::CKeystrokeAction*); - - // public due to compiler brokenness - typedef std::set CScreens; - - private: - - static void doInit(HWND hwnd); - static void doFini(HWND hwnd); - static void fillScreens(HWND hwnd); - static void updateControls(HWND hwnd); - - static void add(HWND hwnd); - static void remove(HWND hwnd); - - static void getSelected(HWND hwnd, UINT id, - const CScreens& inScreens, CScreens& outScreens); - - static BOOL CALLBACK dlgProc(HWND, UINT, WPARAM, LPARAM); - - private: - static CConfig* s_config; - static CInputFilter::CKeystrokeAction* s_action; - static CScreens s_nonTargets; - static CScreens s_targets; - static CString s_allScreens; - }; - -private: - static CHotkeyOptions* s_singleton; - - HWND m_parent; - CConfig* m_config; - CInputFilter* m_inputFilter; - CInputFilter::CRule m_activeRule; - UInt32 m_activeRuleIndex; -}; - -#endif diff --git a/cmd/launcher/CInfo.cpp b/cmd/launcher/CInfo.cpp deleted file mode 100644 index 669da0e2..00000000 --- a/cmd/launcher/CInfo.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2006 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "ProtocolTypes.h" -#include "CStringUtil.h" -#include "Version.h" -#include "CArch.h" -#include "CInfo.h" -#include "LaunchUtil.h" -#include "resource.h" - -// -// CInfo -// - -CInfo* CInfo::s_singleton = NULL; - -CInfo::CInfo(HWND parent) : - m_parent(parent) -{ - assert(s_singleton == NULL); - s_singleton = this; -} - -CInfo::~CInfo() -{ - s_singleton = NULL; -} - -void -CInfo::doModal() -{ - // do dialog - DialogBoxParam(s_instance, MAKEINTRESOURCE(IDD_INFO), - m_parent, (DLGPROC)dlgProc, (LPARAM)this); -} - -void -CInfo::init(HWND hwnd) -{ - // collect info - CString version = - CStringUtil::format(getString(IDS_TITLE).c_str(), VERSION); - CString hostname = ARCH->getHostName(); - CString address = ARCH->addrToString(ARCH->nameToAddr(hostname)); - CString userConfig = ARCH->getUserDirectory(); - if (!userConfig.empty()) { - userConfig = ARCH->concatPath(userConfig, CONFIG_NAME); - } - CString sysConfig = ARCH->getSystemDirectory(); - if (!sysConfig.empty()) { - sysConfig = ARCH->concatPath(sysConfig, CONFIG_NAME); - } - - // set info - HWND child; - child = getItem(hwnd, IDC_INFO_VERSION); - setWindowText(child, version); - child = getItem(hwnd, IDC_INFO_HOSTNAME); - setWindowText(child, hostname); - child = getItem(hwnd, IDC_INFO_IP_ADDRESS); - setWindowText(child, address); - child = getItem(hwnd, IDC_INFO_USER_CONFIG); - setWindowText(child, userConfig); - child = getItem(hwnd, IDC_INFO_SYS_CONFIG); - setWindowText(child, sysConfig); - - // focus on okay button - SetFocus(getItem(hwnd, IDOK)); -} - -BOOL -CInfo::doDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM) -{ - switch (message) { - case WM_INITDIALOG: - init(hwnd); - return FALSE; - - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDOK: - case IDCANCEL: - EndDialog(hwnd, 0); - return TRUE; - } - break; - - default: - break; - } - - return FALSE; -} - -BOOL CALLBACK -CInfo::dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - return s_singleton->doDlgProc(hwnd, message, wParam, lParam); -} diff --git a/cmd/launcher/CInfo.h b/cmd/launcher/CInfo.h deleted file mode 100644 index 2d85ec7d..00000000 --- a/cmd/launcher/CInfo.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2006 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CINFO_H -#define CINFO_H - -#include "CString.h" - -#define WINDOWS_LEAN_AND_MEAN -#include - -//! Info dialog for Microsoft Windows launcher -class CInfo { -public: - CInfo(HWND parent); - ~CInfo(); - - //! @name manipulators - //@{ - - //! Run dialog - /*! - Display and handle the dialog until closed by the user. - */ - void doModal(); - - //@} - //! @name accessors - //@{ - - //@} - -private: - void init(HWND hwnd); - - // message handling - BOOL doDlgProc(HWND, UINT, WPARAM, LPARAM); - static BOOL CALLBACK dlgProc(HWND, UINT, WPARAM, LPARAM); - -private: - static CInfo* s_singleton; - - HWND m_parent; -}; - -#endif diff --git a/cmd/launcher/CScreensLinks.cpp b/cmd/launcher/CScreensLinks.cpp deleted file mode 100644 index c7e58a04..00000000 --- a/cmd/launcher/CScreensLinks.cpp +++ /dev/null @@ -1,855 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CConfig.h" -#include "ProtocolTypes.h" -#include "CStringUtil.h" -#include "CArch.h" -#include "CScreensLinks.h" -#include "CAddScreen.h" -#include "LaunchUtil.h" -#include "resource.h" - -// -// CScreensLinks -// - -CScreensLinks* CScreensLinks::s_singleton = NULL; - -CScreensLinks::CScreensLinks(HWND parent, CConfig* config) : - m_parent(parent), - m_mainConfig(config), - m_config(&m_scratchConfig) -{ - assert(s_singleton == NULL); - s_singleton = this; - - // get formatting strings - m_linkFormat = getString(IDS_LINK_FORMAT); - m_intervalFormat = getString(IDS_LINK_INTERVAL_FORMAT); - m_newLinkLabel = getString(IDS_NEW_LINK); - m_sideLabel[kLeft - kFirstDirection] = getString(IDS_SIDE_LEFT); - m_sideLabel[kRight - kFirstDirection] = getString(IDS_SIDE_RIGHT); - m_sideLabel[kTop - kFirstDirection] = getString(IDS_SIDE_TOP); - m_sideLabel[kBottom - kFirstDirection] = getString(IDS_SIDE_BOTTOM); - - // GDI objects - m_redPen = CreatePen(PS_INSIDEFRAME, 1, RGB(255, 0, 0)); -} - -CScreensLinks::~CScreensLinks() -{ - DeleteObject(m_redPen); - s_singleton = NULL; -} - -void -CScreensLinks::doModal() -{ - // do dialog - DialogBoxParam(s_instance, MAKEINTRESOURCE(IDD_SCREENS_LINKS), - m_parent, (DLGPROC)dlgProc, (LPARAM)this); -} - -void -CScreensLinks::init(HWND hwnd) -{ - // get initial config - m_scratchConfig = *m_mainConfig; - - // fill side list box (in EDirection order) - HWND child = getItem(hwnd, IDC_SCREENS_SRC_SIDE); - SendMessage(child, CB_ADDSTRING, 0, (LPARAM)TEXT("---")); - SendMessage(child, CB_ADDSTRING, 0, - (LPARAM)getString(IDS_EDGE_LEFT).c_str()); - SendMessage(child, CB_ADDSTRING, 0, - (LPARAM)getString(IDS_EDGE_RIGHT).c_str()); - SendMessage(child, CB_ADDSTRING, 0, - (LPARAM)getString(IDS_EDGE_TOP).c_str()); - SendMessage(child, CB_ADDSTRING, 0, - (LPARAM)getString(IDS_EDGE_BOTTOM).c_str()); - - // create error boxes - m_srcSideError = createErrorBox(hwnd); - m_srcScreenError = createErrorBox(hwnd); - m_dstScreenError = createErrorBox(hwnd); - resizeErrorBoxes(); - - m_selectedLink = -1; - m_editedLink = CEdgeLink(); - m_edgeLinks.clear(); - updateScreens(hwnd, ""); - updateScreensControls(hwnd); - updateLinks(hwnd); - updateLinksControls(hwnd); -} - -bool -CScreensLinks::save(HWND /*hwnd*/) -{ - *m_mainConfig = m_scratchConfig; - return true; -} - -BOOL -CScreensLinks::doDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) { - case WM_INITDIALOG: - init(hwnd); - return TRUE; - - case WM_SIZE: - resizeErrorBoxes(); - break; - - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDOK: - SetFocus(getItem(hwnd, IDOK)); - if (save(hwnd)) { - EndDialog(hwnd, 0); - } - return TRUE; - - case IDCANCEL: - EndDialog(hwnd, 0); - return TRUE; - - case IDC_SCREENS_SCREENS: - switch (HIWORD(wParam)) { - case LBN_DBLCLK: - editScreen(hwnd); - return TRUE; - - case LBN_SELCHANGE: - updateScreensControls(hwnd); - updateLinkView(hwnd); - return TRUE; - - case LBN_SELCANCEL: - updateScreensControls(hwnd); - updateLinkView(hwnd); - return TRUE; - } - break; - - case IDC_SCREENS_ADD_SCREEN: - addScreen(hwnd); - return TRUE; - - case IDC_SCREENS_REMOVE_SCREEN: - removeScreen(hwnd); - return TRUE; - - case IDC_SCREENS_EDIT_SCREEN: - editScreen(hwnd); - return TRUE; - - case IDC_SCREENS_LINKS: - switch (HIWORD(wParam)) { - case LBN_SELCHANGE: - editLink(hwnd); - return TRUE; - - case LBN_SELCANCEL: - editLink(hwnd); - return TRUE; - } - break; - - case IDC_SCREENS_ADD_LINK: - addLink(hwnd); - return TRUE; - - case IDC_SCREENS_REMOVE_LINK: - removeLink(hwnd); - return TRUE; - - case IDC_SCREENS_SRC_SIDE: - switch (HIWORD(wParam)) { - case CBN_SELCHANGE: - changeSrcSide(hwnd); - break; - } - break; - - case IDC_SCREENS_SRC_SCREEN: - switch (HIWORD(wParam)) { - case CBN_SELCHANGE: - changeSrcScreen(hwnd); - break; - } - break; - - case IDC_SCREENS_DST_SCREEN: - switch (HIWORD(wParam)) { - case CBN_SELCHANGE: - changeDstScreen(hwnd); - break; - } - break; - - case IDC_SCREENS_SRC_START: - switch (HIWORD(wParam)) { - case EN_KILLFOCUS: - changeIntervalStart(hwnd, LOWORD(wParam), - m_editedLink.m_srcInterval); - break; - } - break; - - case IDC_SCREENS_SRC_END: - switch (HIWORD(wParam)) { - case EN_KILLFOCUS: - changeIntervalEnd(hwnd, LOWORD(wParam), - m_editedLink.m_srcInterval); - break; - } - break; - - case IDC_SCREENS_DST_START: - switch (HIWORD(wParam)) { - case EN_KILLFOCUS: - changeIntervalStart(hwnd, LOWORD(wParam), - m_editedLink.m_dstInterval); - break; - } - break; - - case IDC_SCREENS_DST_END: - switch (HIWORD(wParam)) { - case EN_KILLFOCUS: - changeIntervalEnd(hwnd, LOWORD(wParam), - m_editedLink.m_dstInterval); - break; - } - break; - } - - break; - - case WM_CTLCOLORSTATIC: - switch (GetDlgCtrlID((HWND)lParam)) { - case IDC_SCREENS_OVERLAP_ERROR: - SetBkColor((HDC)wParam, GetSysColor(COLOR_3DFACE)); - SetTextColor((HDC)wParam, RGB(255, 0, 0)); - return (BOOL)GetSysColorBrush(COLOR_3DFACE); - } - break; - - // error outlines - case WM_DRAWITEM: { - DRAWITEMSTRUCT* di = (DRAWITEMSTRUCT*)lParam; - if (di->CtlType == ODT_STATIC) { - HGDIOBJ oldPen = SelectObject(di->hDC, m_redPen); - HGDIOBJ oldBrush = SelectObject(di->hDC, - GetStockObject(NULL_BRUSH)); - Rectangle(di->hDC, di->rcItem.left, di->rcItem.top, - di->rcItem.right, di->rcItem.bottom); - SelectObject(di->hDC, oldPen); - SelectObject(di->hDC, oldBrush); - return TRUE; - } - break; - } - - default: - break; - } - - return FALSE; -} - -BOOL CALLBACK -CScreensLinks::dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - return s_singleton->doDlgProc(hwnd, message, wParam, lParam); -} - -CString -CScreensLinks::getSelectedScreen(HWND hwnd) const -{ - HWND child = getItem(hwnd, IDC_SCREENS_SCREENS); - LRESULT index = SendMessage(child, LB_GETCURSEL, 0, 0); - if (index == LB_ERR) { - return CString(); - } - - LRESULT size = SendMessage(child, LB_GETTEXTLEN, index, 0); - char* buffer = new char[size + 1]; - SendMessage(child, LB_GETTEXT, index, (LPARAM)buffer); - buffer[size] = '\0'; - CString result(buffer); - delete[] buffer; - return result; -} - -void -CScreensLinks::addScreen(HWND hwnd) -{ - CAddScreen dialog(hwnd, m_config, ""); - if (dialog.doModal()) { - updateScreens(hwnd, dialog.getName()); - updateScreensControls(hwnd); - updateLinks(hwnd); - updateLinksControls(hwnd); - } -} - -void -CScreensLinks::editScreen(HWND hwnd) -{ - CString oldName = getSelectedScreen(hwnd); - CAddScreen dialog(hwnd, m_config, oldName); - if (dialog.doModal()) { - CString newName = dialog.getName(); - - // rename screens in the edge list - if (newName != oldName) { - for (size_t i = 0; i < m_edgeLinks.size(); ++i) { - m_edgeLinks[i].rename(oldName, newName); - } - m_editedLink.rename(oldName, newName); - } - - updateScreens(hwnd, newName); - updateScreensControls(hwnd); - updateLinks(hwnd); - updateLinksControls(hwnd); - } -} - -void -CScreensLinks::removeScreen(HWND hwnd) -{ - // remove screen from config (this also removes aliases) - m_config->removeScreen(getSelectedScreen(hwnd)); - - // update dialog - updateScreens(hwnd, ""); - updateScreensControls(hwnd); - updateLinks(hwnd); - updateLinksControls(hwnd); -} - -void -CScreensLinks::addLink(HWND hwnd) -{ - if (m_editedLink.connect(m_config)) { - m_editedLink = CEdgeLink(); - updateLinks(hwnd); - updateLinksControls(hwnd); - } -} - -void -CScreensLinks::editLink(HWND hwnd) -{ - // get selection - HWND child = getItem(hwnd, IDC_SCREENS_LINKS); - DWORD i = SendMessage(child, LB_GETCURSEL, 0, 0); - if (i != LB_ERR && i != (DWORD)m_edgeLinks.size()) { - // existing link - m_selectedLink = (SInt32)SendMessage(child, LB_GETITEMDATA, i, 0); - m_editedLink = m_edgeLinks[m_selectedLink]; - } - else { - // new link - m_selectedLink = -1; - m_editedLink = CEdgeLink(); - } - updateLinksControls(hwnd); -} - -void -CScreensLinks::removeLink(HWND hwnd) -{ - if (m_editedLink.disconnect(m_config)) { - updateLinks(hwnd); - updateLinksControls(hwnd); - } -} - -void -CScreensLinks::updateScreens(HWND hwnd, const CString& selectName) -{ - HWND child; - - // set screen list - child = getItem(hwnd, IDC_SCREENS_SCREENS); - SendMessage(child, LB_RESETCONTENT, 0, 0); - for (CConfig::const_iterator index = m_config->begin(); - index != m_config->end(); ) { - const CString& name = *index; - ++index; - if (index != m_config->end()) { - SendMessage(child, LB_INSERTSTRING, - (WPARAM)-1, (LPARAM)name.c_str()); - } - else { - SendMessage(child, LB_ADDSTRING, 0, (LPARAM)name.c_str()); - } - } - - // find the named screen - if (!selectName.empty()) { - DWORD i = SendMessage(child, LB_FINDSTRINGEXACT, - (UINT)-1, (LPARAM)selectName.c_str()); - if (i != LB_ERR) { - SendMessage(child, LB_SETSEL, TRUE, i); - } - } -} - -void -CScreensLinks::updateScreensControls(HWND hwnd) -{ - HWND child = getItem(hwnd, IDC_SCREENS_SCREENS); - bool screenSelected = (SendMessage(child, LB_GETCURSEL, 0, 0) != LB_ERR); - - enableItem(hwnd, IDC_SCREENS_ADD_SCREEN, TRUE); - enableItem(hwnd, IDC_SCREENS_EDIT_SCREEN, screenSelected); - enableItem(hwnd, IDC_SCREENS_REMOVE_SCREEN, screenSelected); -} - -void -CScreensLinks::updateLinks(HWND hwnd) -{ - HWND links = getItem(hwnd, IDC_SCREENS_LINKS); - HWND srcScreens = getItem(hwnd, IDC_SCREENS_SRC_SCREEN); - HWND dstScreens = getItem(hwnd, IDC_SCREENS_DST_SCREEN); - - // get old selection - CEdgeLink oldLink; - if (m_selectedLink != -1) { - oldLink = m_edgeLinks[m_selectedLink]; - } - - // clear links and screens - SendMessage(links, LB_RESETCONTENT, 0, 0); - SendMessage(srcScreens, CB_RESETCONTENT, 0, 0); - SendMessage(dstScreens, CB_RESETCONTENT, 0, 0); - m_edgeLinks.clear(); - - // add "no screen" items - SendMessage(srcScreens, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)TEXT("----")); - SendMessage(dstScreens, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)TEXT("----")); - - // add links and screens - for (CConfig::const_iterator i = m_config->begin(); - i != m_config->end(); ++i) { - const CString& name = *i; - - // add screen - SendMessage(srcScreens, CB_INSERTSTRING, (WPARAM)-1, - (LPARAM)name.c_str()); - SendMessage(dstScreens, CB_INSERTSTRING, (WPARAM)-1, - (LPARAM)name.c_str()); - - // add links for screen - for (CConfig::link_const_iterator j = m_config->beginNeighbor(name), - n = m_config->endNeighbor(name); - j != n; ++j) { - DWORD k = m_edgeLinks.size(); - m_edgeLinks.push_back(CEdgeLink(name, *j)); - SendMessage(links, LB_INSERTSTRING, (WPARAM)-1, - (LPARAM)formatLink(m_edgeLinks.back()).c_str()); - SendMessage(links, LB_SETITEMDATA, (WPARAM)k, (LPARAM)k); - } - } - - // add "new link" item to sort - SendMessage(links, LB_ADDSTRING, 0, (LPARAM)m_newLinkLabel.c_str()); - - // remove the "new link" item then insert it on the end - DWORD i = SendMessage(links, LB_FINDSTRINGEXACT, - (UINT)-1, (LPARAM)m_newLinkLabel.c_str()); - if (i != LB_ERR) { - SendMessage(links, LB_DELETESTRING, i, 0); - } - SendMessage(links, LB_INSERTSTRING, (WPARAM)-1, - (LPARAM)getString(IDS_NEW_LINK).c_str()); - SendMessage(links, LB_SETITEMDATA, (WPARAM)m_edgeLinks.size(), - (LPARAM)-1); - - // select the same link as before - SendMessage(links, LB_SETCURSEL, (WPARAM)m_edgeLinks.size(), 0); - if (m_selectedLink != -1) { - m_selectedLink = -1; - for (size_t j = 0; j < m_edgeLinks.size(); ++j) { - if (m_edgeLinks[j] == oldLink) { - // found matching link - m_selectedLink = j; - for (size_t k = 0; k < m_edgeLinks.size(); ++k) { - if (SendMessage(links, LB_GETITEMDATA, k, 0) == (int)j) { - SendMessage(links, LB_SETCURSEL, k, 0); - break; - } - } - break; - } - } - - // if we can't find the link anymore then reset edited link - if (m_selectedLink == -1) { - m_editedLink = CEdgeLink(); - } - } -} - -void -CScreensLinks::updateLinksControls(HWND hwnd) -{ - // get selection. select "new link" if nothing is selected. - HWND child = getItem(hwnd, IDC_SCREENS_LINKS); - if (m_selectedLink == -1) { - SendMessage(child, LB_SETCURSEL, m_edgeLinks.size(), 0); - } - - // enable/disable remove button - enableItem(hwnd, IDC_SCREENS_REMOVE_LINK, m_selectedLink != -1); - - // fill link entry controls from m_editedLink - updateLinkEditControls(hwnd, m_editedLink); - updateLinkValid(hwnd, m_editedLink); - updateLinkView(hwnd); -} - -void -CScreensLinks::changeSrcSide(HWND hwnd) -{ - HWND child = getItem(hwnd, IDC_SCREENS_SRC_SIDE); - m_editedLink.m_srcSide = (EDirection)SendMessage(child, CB_GETCURSEL, 0, 0); - updateLink(hwnd); -} - -void -CScreensLinks::changeSrcScreen(HWND hwnd) -{ - HWND child = getItem(hwnd, IDC_SCREENS_SRC_SCREEN); - m_editedLink.m_srcName = getWindowText(child); - updateLink(hwnd); -} - -void -CScreensLinks::changeDstScreen(HWND hwnd) -{ - HWND child = getItem(hwnd, IDC_SCREENS_DST_SCREEN); - m_editedLink.m_dstName = getWindowText(child); - updateLink(hwnd); -} - -void -CScreensLinks::changeIntervalStart(HWND hwnd, int id, CConfig::CInterval& i) -{ - int x = (int)GetDlgItemInt(hwnd, id, NULL, FALSE); - if (x < 0) { - x = 0; - } - else if (x > 99) { - x = 99; - } - - i.first = 0.01f * (float)x; - if (i.first >= i.second) { - i.second = 0.01f * (float)(x + 1); - } - - updateLinkIntervalControls(hwnd, m_editedLink); - updateLink(hwnd); -} - -void -CScreensLinks::changeIntervalEnd(HWND hwnd, int id, CConfig::CInterval& i) -{ - int x = (int)GetDlgItemInt(hwnd, id, NULL, FALSE); - if (x < 1) { - x = 1; - } - else if (x > 100) { - x = 100; - } - - i.second = 0.01f * (float)x; - if (i.first >= i.second) { - i.first = 0.01f * (float)(x - 1); - } - - updateLinkIntervalControls(hwnd, m_editedLink); - updateLink(hwnd); -} - -void -CScreensLinks::selectScreen(HWND hwnd, int id, const CString& name) -{ - HWND child = getItem(hwnd, id); - DWORD i = SendMessage(child, CB_FINDSTRINGEXACT, (WPARAM)-1, - (LPARAM)name.c_str()); - if (i == CB_ERR) { - // no match, select no screen - SendMessage(child, CB_SETCURSEL, 0, 0); - } - else { - SendMessage(child, CB_SETCURSEL, i, 0); - } -} - -void -CScreensLinks::updateLinkEditControls(HWND hwnd, const CEdgeLink& link) -{ - // fill link entry controls from link - HWND child = getItem(hwnd, IDC_SCREENS_SRC_SIDE); - SendMessage(child, CB_SETCURSEL, link.m_srcSide, 0); - selectScreen(hwnd, IDC_SCREENS_SRC_SCREEN, link.m_srcName); - selectScreen(hwnd, IDC_SCREENS_DST_SCREEN, link.m_dstName); - updateLinkIntervalControls(hwnd, link); -} - -void -CScreensLinks::updateLinkIntervalControls(HWND hwnd, const CEdgeLink& link) -{ - HWND child; - - // src interval - child = getItem(hwnd, IDC_SCREENS_SRC_START); - setWindowText(child, formatIntervalValue(link.m_srcInterval.first)); - child = getItem(hwnd, IDC_SCREENS_SRC_END); - setWindowText(child, formatIntervalValue(link.m_srcInterval.second)); - - // dst interval - child = getItem(hwnd, IDC_SCREENS_DST_START); - setWindowText(child, formatIntervalValue(link.m_dstInterval.first)); - child = getItem(hwnd, IDC_SCREENS_DST_END); - setWindowText(child, formatIntervalValue(link.m_dstInterval.second)); -} - -void -CScreensLinks::updateLink(HWND hwnd) -{ - updateLinkValid(hwnd, m_editedLink); - - // update link in config - if (m_selectedLink != -1 && m_editedLinkIsValid) { - // editing an existing link and entry is valid - if (m_edgeLinks[m_selectedLink].disconnect(m_config)) { - // successfully removed old link - if (!m_editedLink.connect(m_config)) { - // couldn't set new link so restore old link - m_edgeLinks[m_selectedLink].connect(m_config); - } - else { - m_edgeLinks[m_selectedLink] = m_editedLink; - updateLinks(hwnd); - updateLinkEditControls(hwnd, m_editedLink); - } - } - } - - updateLinkView(hwnd); -} - -void -CScreensLinks::updateLinkValid(HWND hwnd, const CEdgeLink& link) -{ - m_editedLinkIsValid = true; - - // check source side and screen - if (link.m_srcSide == kNoDirection) { - m_editedLinkIsValid = false; - ShowWindow(m_srcSideError, SW_SHOWNA); - } - else { - ShowWindow(m_srcSideError, SW_HIDE); - } - if (!m_config->isCanonicalName(link.m_srcName)) { - m_editedLinkIsValid = false; - ShowWindow(m_srcScreenError, SW_SHOWNA); - } - else { - ShowWindow(m_srcScreenError, SW_HIDE); - } - - // check for overlap. if editing a link we must remove it, then - // check for overlap and restore the old link. - bool overlap = false; - if (m_editedLinkIsValid) { - if (m_selectedLink == -1) { - if (link.overlaps(m_config)) { - m_editedLinkIsValid = false; - overlap = true; - } - } - else { - if (m_edgeLinks[m_selectedLink].disconnect(m_config)) { - overlap = link.overlaps(m_config); - m_edgeLinks[m_selectedLink].connect(m_config); - if (overlap) { - m_editedLinkIsValid = false; - } - } - } - } - ShowWindow(getItem(hwnd, IDC_SCREENS_OVERLAP_ERROR), - overlap ? SW_SHOWNA : SW_HIDE); - - // check dst screen - if (!m_config->isCanonicalName(link.m_dstName)) { - m_editedLinkIsValid = false; - ShowWindow(m_dstScreenError, SW_SHOWNA); - } - else { - ShowWindow(m_dstScreenError, SW_HIDE); - } - - // update add link button - enableItem(hwnd, IDC_SCREENS_ADD_LINK, - m_selectedLink == -1 && m_editedLinkIsValid); -} - -void -CScreensLinks::updateLinkView(HWND /*hwnd*/) -{ - // XXX -- draw visual of selected screen, highlighting selected link -} - -HWND -CScreensLinks::createErrorBox(HWND parent) -{ - return CreateWindow(TEXT("STATIC"), TEXT(""), - WS_CHILD | SS_OWNERDRAW, - 0, 0, 1, 1, - parent, (HMENU)-1, - s_instance, NULL); -} - -void -CScreensLinks::resizeErrorBoxes() -{ - HWND hwnd = GetParent(m_srcSideError); - resizeErrorBox(m_srcSideError, getItem(hwnd, IDC_SCREENS_SRC_SIDE)); - resizeErrorBox(m_srcScreenError, getItem(hwnd, IDC_SCREENS_SRC_SCREEN)); - resizeErrorBox(m_dstScreenError, getItem(hwnd, IDC_SCREENS_DST_SCREEN)); -} - -void -CScreensLinks::resizeErrorBox(HWND box, HWND assoc) -{ - RECT rect; - GetWindowRect(assoc, &rect); - MapWindowPoints(NULL, GetParent(box), (POINT*)&rect, 2); - SetWindowPos(box, HWND_TOP, rect.left - 1, rect.top - 1, - rect.right - rect.left + 2, - rect.bottom - rect.top + 2, SWP_NOACTIVATE); -} - -CString -CScreensLinks::formatIntervalValue(float x) const -{ - return CStringUtil::print("%d", (int)(x * 100.0f + 0.5f)); -} - -CString -CScreensLinks::formatInterval(const CConfig::CInterval& i) const -{ - if (i.first == 0.0f && i.second == 1.0f) { - return ""; - } - else { - CString start = formatIntervalValue(i.first); - CString end = formatIntervalValue(i.second); - return CStringUtil::format(m_intervalFormat.c_str(), - start.c_str(), end.c_str()); - } -} - -CString -CScreensLinks::formatLink(const CEdgeLink& link) const -{ - CString srcInterval = formatInterval(link.m_srcInterval); - CString dstInterval = formatInterval(link.m_dstInterval); - return CStringUtil::format(m_linkFormat.c_str(), - link.m_srcName.c_str(), srcInterval.c_str(), - m_sideLabel[link.m_srcSide - kFirstDirection].c_str(), - link.m_dstName.c_str(), dstInterval.c_str()); -} - -// -// CScreensLinks::CEdgeLink -// - -CScreensLinks::CEdgeLink::CEdgeLink() : - m_srcName(), - m_srcSide(kNoDirection), - m_srcInterval(0.0f, 1.0f), - m_dstName(), - m_dstInterval(0.0f, 1.0f) -{ - // do nothing -} - -CScreensLinks::CEdgeLink::CEdgeLink(const CString& name, - const CConfigLink& link) : - m_srcName(name), - m_srcSide(link.first.getSide()), - m_srcInterval(link.first.getInterval()), - m_dstName(link.second.getName()), - m_dstInterval(link.second.getInterval()) -{ - // do nothing -} - -bool -CScreensLinks::CEdgeLink::connect(CConfig* config) -{ - return config->connect(m_srcName, m_srcSide, - m_srcInterval.first, m_srcInterval.second, - m_dstName, - m_dstInterval.first, m_dstInterval.second); -} - -bool -CScreensLinks::CEdgeLink::disconnect(CConfig* config) -{ - return config->disconnect(m_srcName, m_srcSide, 0.5f * - (m_srcInterval.first + m_srcInterval.second)); -} - -void -CScreensLinks::CEdgeLink::rename(const CString& oldName, const CString& newName) -{ - if (m_srcName == oldName) { - m_srcName = newName; - } - if (m_dstName == oldName) { - m_dstName = newName; - } -} - -bool -CScreensLinks::CEdgeLink::overlaps(const CConfig* config) const -{ - return config->hasNeighbor(m_srcName, m_srcSide, - m_srcInterval.first, m_srcInterval.second); -} - -bool -CScreensLinks::CEdgeLink::operator==(const CEdgeLink& x) const -{ - return (m_srcName == x.m_srcName && - m_srcSide == x.m_srcSide && - m_srcInterval == x.m_srcInterval && - m_dstName == x.m_dstName && - m_dstInterval == x.m_dstInterval); -} diff --git a/cmd/launcher/CScreensLinks.h b/cmd/launcher/CScreensLinks.h deleted file mode 100644 index 8ffd0089..00000000 --- a/cmd/launcher/CScreensLinks.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CSCREENSLINKS_H -#define CSCREENSLINKS_H - -#include "CConfig.h" -#include "ProtocolTypes.h" -#include "CString.h" - -#define WINDOWS_LEAN_AND_MEAN -#include - -//! Screens and links dialog for Microsoft Windows launcher -class CScreensLinks { -public: - CScreensLinks(HWND parent, CConfig*); - ~CScreensLinks(); - - //! @name manipulators - //@{ - - //! Run dialog - /*! - Display and handle the dialog until closed by the user. - */ - void doModal(); - - //@} - //! @name accessors - //@{ - - - //@} - -private: - typedef std::pair CConfigLink; - struct CEdgeLink { - public: - CEdgeLink(); - CEdgeLink(const CString& name, const CConfigLink&); - - bool connect(CConfig*); - bool disconnect(CConfig*); - void rename(const CString& oldName, const CString& newName); - - bool overlaps(const CConfig* config) const; - bool operator==(const CEdgeLink&) const; - - public: - CString m_srcName; - EDirection m_srcSide; - CConfig::CInterval m_srcInterval; - CString m_dstName; - CConfig::CInterval m_dstInterval; - }; - typedef std::vector CEdgeLinkList; - - void init(HWND hwnd); - bool save(HWND hwnd); - - CString getSelectedScreen(HWND hwnd) const; - void addScreen(HWND hwnd); - void editScreen(HWND hwnd); - void removeScreen(HWND hwnd); - void addLink(HWND hwnd); - void editLink(HWND hwnd); - void removeLink(HWND hwnd); - - void updateScreens(HWND hwnd, const CString& name); - void updateScreensControls(HWND hwnd); - void updateLinks(HWND hwnd); - void updateLinksControls(HWND hwnd); - - void changeSrcSide(HWND hwnd); - void changeSrcScreen(HWND hwnd); - void changeDstScreen(HWND hwnd); - void changeIntervalStart(HWND hwnd, int id, - CConfig::CInterval&); - void changeIntervalEnd(HWND hwnd, int id, - CConfig::CInterval&); - - void selectScreen(HWND hwnd, int id, const CString& name); - void updateLinkEditControls(HWND hwnd, - const CEdgeLink& link); - void updateLinkIntervalControls(HWND hwnd, - const CEdgeLink& link); - void updateLink(HWND hwnd); - void updateLinkValid(HWND hwnd, const CEdgeLink& link); - - void updateLinkView(HWND hwnd); - - HWND createErrorBox(HWND parent); - void resizeErrorBoxes(); - void resizeErrorBox(HWND box, HWND assoc); - - CString formatIntervalValue(float) const; - CString formatInterval(const CConfig::CInterval&) const; - CString formatLink(const CEdgeLink&) const; - - // message handling - BOOL doDlgProc(HWND, UINT, WPARAM, LPARAM); - static BOOL CALLBACK dlgProc(HWND, UINT, WPARAM, LPARAM); - -private: - static CScreensLinks* s_singleton; - - HWND m_parent; - CConfig* m_mainConfig; - CConfig m_scratchConfig; - CConfig* m_config; - - CString m_linkFormat; - CString m_intervalFormat; - CString m_newLinkLabel; - CString m_sideLabel[kNumDirections]; - CEdgeLinkList m_edgeLinks; - SInt32 m_selectedLink; - CEdgeLink m_editedLink; - bool m_editedLinkIsValid; - HPEN m_redPen; - HWND m_srcSideError; - HWND m_srcScreenError; - HWND m_dstScreenError; -}; - -#endif diff --git a/cmd/launcher/LaunchUtil.cpp b/cmd/launcher/LaunchUtil.cpp deleted file mode 100644 index 05b517e7..00000000 --- a/cmd/launcher/LaunchUtil.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CConfig.h" -#include "LaunchUtil.h" -#include "CMSWindowsUtil.h" -#include "CArch.h" -#include "resource.h" -#include "stdfstream.h" - -size_t s_showingDialog = 0; - -CString -getString(DWORD id) -{ - return CMSWindowsUtil::getString(s_instance, id); -} - -CString -getErrorString(DWORD error) -{ - return CMSWindowsUtil::getErrorString(s_instance, error, IDS_ERROR); -} - -void -showError(HWND hwnd, const CString& msg) -{ - CString title = getString(IDS_ERROR); - ++s_showingDialog; - MessageBox(hwnd, msg.c_str(), title.c_str(), MB_OK | MB_APPLMODAL); - --s_showingDialog; -} - -void -askOkay(HWND hwnd, const CString& title, const CString& msg) -{ - ++s_showingDialog; - MessageBox(hwnd, msg.c_str(), title.c_str(), MB_OK | MB_APPLMODAL); - --s_showingDialog; -} - -bool -askVerify(HWND hwnd, const CString& msg) -{ - CString title = getString(IDS_VERIFY); - ++s_showingDialog; - int result = MessageBox(hwnd, msg.c_str(), - title.c_str(), MB_OKCANCEL | MB_APPLMODAL); - --s_showingDialog; - return (result == IDOK); -} - -bool -isShowingDialog() -{ - return (s_showingDialog != 0); -} - -void -setWindowText(HWND hwnd, const CString& msg) -{ - SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM)msg.c_str()); -} - -CString -getWindowText(HWND hwnd) -{ - LRESULT size = SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0); - char* buffer = new char[size + 1]; - SendMessage(hwnd, WM_GETTEXT, size + 1, (LPARAM)buffer); - buffer[size] = '\0'; - CString result(buffer); - delete[] buffer; - return result; -} - -HWND -getItem(HWND hwnd, int id) -{ - return GetDlgItem(hwnd, id); -} - -void -enableItem(HWND hwnd, int id, bool enabled) -{ - EnableWindow(GetDlgItem(hwnd, id), enabled); -} - -void -setItemChecked(HWND hwnd, bool checked) -{ - SendMessage(hwnd, BM_SETCHECK, checked ? BST_CHECKED : BST_UNCHECKED, 0); -} - -bool -isItemChecked(HWND hwnd) -{ - return (SendMessage(hwnd, BM_GETCHECK, 0, 0) == BST_CHECKED); -} - -CString -getAppPath(const CString& appName) -{ - // prepare path to app - char myPathname[MAX_PATH]; - GetModuleFileName(s_instance, myPathname, MAX_PATH); - const char* myBasename = ARCH->getBasename(myPathname); - CString appPath = CString(myPathname, myBasename - myPathname); - appPath += appName; - return appPath; -} - -static -void -getFileTime(const CString& path, time_t& t) -{ - struct _stat s; - if (_stat(path.c_str(), &s) != -1) { - t = s.st_mtime; - } -} - -bool -isConfigNewer(time_t& oldTime, bool userConfig) -{ - time_t newTime = oldTime; - if (userConfig) { - CString path = ARCH->getUserDirectory(); - if (!path.empty()) { - path = ARCH->concatPath(path, CONFIG_NAME); - getFileTime(path, newTime); - } - } - else { - CString path = ARCH->getSystemDirectory(); - if (!path.empty()) { - path = ARCH->concatPath(path, CONFIG_NAME); - getFileTime(path, newTime); - } - } - bool result = (newTime > oldTime); - oldTime = newTime; - return result; -} - -static -bool -loadConfig(const CString& pathname, CConfig& config) -{ - try { - std::ifstream stream(pathname.c_str()); - if (stream) { - stream >> config; - return true; - } - } - catch (...) { - // ignore - } - return false; -} - -bool -loadConfig(CConfig& config, time_t& t, bool& userConfig) -{ - // load configuration - bool configLoaded = false; - CString path = ARCH->getUserDirectory(); - if (!path.empty()) { - // try loading the user's configuration - path = ARCH->concatPath(path, CONFIG_NAME); - if (loadConfig(path, config)) { - configLoaded = true; - userConfig = true; - getFileTime(path, t); - } - else { - // try the system-wide config file - path = ARCH->getSystemDirectory(); - if (!path.empty()) { - path = ARCH->concatPath(path, CONFIG_NAME); - if (loadConfig(path, config)) { - configLoaded = true; - userConfig = false; - getFileTime(path, t); - } - } - } - } - return configLoaded; -} - -static -bool -saveConfig(const CString& pathname, const CConfig& config) -{ - try { - std::ofstream stream(pathname.c_str()); - if (stream) { - stream << config; - return !!stream; - } - } - catch (...) { - // ignore - } - return false; -} - -bool -saveConfig(const CConfig& config, bool sysOnly, time_t& t) -{ - // try saving the user's configuration - if (!sysOnly) { - CString path = ARCH->getUserDirectory(); - if (!path.empty()) { - path = ARCH->concatPath(path, CONFIG_NAME); - if (saveConfig(path, config)) { - getFileTime(path, t); - return true; - } - } - } - - // try the system-wide config file - else { - CString path = ARCH->getSystemDirectory(); - if (!path.empty()) { - path = ARCH->concatPath(path, CONFIG_NAME); - if (saveConfig(path, config)) { - getFileTime(path, t); - return true; - } - } - } - - return false; -} - -const TCHAR* const* -getSettingsPath() -{ - static const TCHAR* s_keyNames[] = { - TEXT("Software"), - TEXT("Synergy"), - TEXT("Synergy"), - NULL - }; - return s_keyNames; -} diff --git a/cmd/launcher/LaunchUtil.h b/cmd/launcher/LaunchUtil.h deleted file mode 100644 index 75954046..00000000 --- a/cmd/launcher/LaunchUtil.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef LAUNCHUTIL_H -#define LAUNCHUTIL_H - -#include "CString.h" - -#define WINDOWS_LEAN_AND_MEAN -#include -#include -#include - -#define CLIENT_APP "synergyc.exe" -#define SERVER_APP "synergys.exe" -#define CONFIG_NAME "synergy.sgc" - -class CConfig; - -// client must define this and set it before calling any function here -extern HINSTANCE s_instance; - -CString getString(DWORD id); -CString getErrorString(DWORD error); - -void showError(HWND hwnd, const CString& msg); -void askOkay(HWND hwnd, const CString& title, - const CString& msg); -bool askVerify(HWND hwnd, const CString& msg); -bool isShowingDialog(); - -void setWindowText(HWND hwnd, const CString& msg); -CString getWindowText(HWND hwnd); - -HWND getItem(HWND hwnd, int id); -void enableItem(HWND hwnd, int id, bool enabled); - -void setItemChecked(HWND, bool); -bool isItemChecked(HWND); - -CString getAppPath(const CString& appName); - -bool isConfigNewer(time_t&, bool userConfig); -bool loadConfig(CConfig& config, time_t&, bool& userConfig); -bool saveConfig(const CConfig& config, - bool sysOnly, time_t&); - -const TCHAR* const* getSettingsPath(); - -#endif diff --git a/cmd/launcher/Makefile.am b/cmd/launcher/Makefile.am deleted file mode 100644 index 6fc879e3..00000000 --- a/cmd/launcher/Makefile.am +++ /dev/null @@ -1,75 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2002 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -## Process this file with automake to produce Makefile.in -NULL = - -MSWINDOWS_SOURCE_FILES = \ - CAddScreen.cpp \ - CAdvancedOptions.cpp \ - CAutoStart.cpp \ - CGlobalOptions.cpp \ - CHotkeyOptions.cpp \ - CInfo.cpp \ - CScreensLinks.cpp \ - LaunchUtil.cpp \ - launcher.cpp \ - CAddScreen.h \ - CAdvancedOptions.h \ - CAutoStart.h \ - CGlobalOptions.h \ - CHotkeyOptions.h \ - CInfo.h \ - CScreensLinks.h \ - LaunchUtil.h \ - resource.h \ - launcher.rc \ - $(NULL) - -EXTRA_DIST = \ - Makefile.win \ - synergy.ico \ - $(MSWINDOWS_SOURCE_FILES) \ - $(NULL) - -MAINTAINERCLEANFILES = \ - Makefile.in \ - $(NULL) - -if MSWINDOWS -bin_PROGRAMS = synergy -synergy_SOURCES = \ - $(MSWINDOWS_SOURCE_FILES) \ - $(NULL) -endif -synergy_LDADD = \ - $(top_builddir)/lib/server/libserver.a \ - $(top_builddir)/lib/platform/libplatform.a \ - $(top_builddir)/lib/synergy/libsynergy.a \ - $(top_builddir)/lib/net/libnet.a \ - $(top_builddir)/lib/io/libio.a \ - $(top_builddir)/lib/mt/libmt.a \ - $(top_builddir)/lib/base/libbase.a \ - $(top_builddir)/lib/common/libcommon.a \ - $(top_builddir)/lib/arch/libarch.a \ - $(NULL) -INCLUDES = \ - -I$(top_srcdir)/lib/common \ - -I$(top_srcdir)/lib/arch \ - -I$(top_srcdir)/lib/base \ - -I$(top_srcdir)/lib/mt \ - -I$(top_srcdir)/lib/io \ - -I$(top_srcdir)/lib/net \ - -I$(top_srcdir)/lib/synergy \ - -I$(top_srcdir)/lib/platform \ - -I$(top_srcdir)/lib/server \ - $(NULL) diff --git a/cmd/launcher/Makefile.win b/cmd/launcher/Makefile.win deleted file mode 100644 index 3d4f277a..00000000 --- a/cmd/launcher/Makefile.win +++ /dev/null @@ -1,101 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2007 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -BIN_LAUNCHER_SRC = cmd\launcher -BIN_LAUNCHER_DST = $(BUILD_DST)\$(BIN_LAUNCHER_SRC) -BIN_LAUNCHER_EXE = "$(BUILD_DST)\synergy.exe" -BIN_LAUNCHER_CPP = \ - "CAddScreen.cpp" \ - "CAdvancedOptions.cpp" \ - "CAutoStart.cpp" \ - "CGlobalOptions.cpp" \ - "CHotkeyOptions.cpp" \ - "CInfo.cpp" \ - "CScreensLinks.cpp" \ - "LaunchUtil.cpp" \ - "launcher.cpp" \ - $(NULL) -BIN_LAUNCHER_OBJ = \ - "$(BIN_LAUNCHER_DST)\CAddScreen.obj" \ - "$(BIN_LAUNCHER_DST)\CAdvancedOptions.obj" \ - "$(BIN_LAUNCHER_DST)\CAutoStart.obj" \ - "$(BIN_LAUNCHER_DST)\CGlobalOptions.obj" \ - "$(BIN_LAUNCHER_DST)\CHotkeyOptions.obj" \ - "$(BIN_LAUNCHER_DST)\CInfo.obj" \ - "$(BIN_LAUNCHER_DST)\CScreensLinks.obj" \ - "$(BIN_LAUNCHER_DST)\LaunchUtil.obj" \ - "$(BIN_LAUNCHER_DST)\launcher.obj" \ - $(NULL) -BIN_LAUNCHER_RC = "$(BIN_LAUNCHER_SRC)\launcher.rc" -BIN_LAUNCHER_RES = "$(BIN_LAUNCHER_DST)\launcher.res" -BIN_LAUNCHER_INC = \ - /I"lib\common" \ - /I"lib\arch" \ - /I"lib\base" \ - /I"lib\mt" \ - /I"lib\io" \ - /I"lib\net" \ - /I"lib\synergy" \ - /I"lib\platform" \ - /I"lib\server" \ - $(NULL) -BIN_LAUNCHER_LIB = \ - $(LIB_SERVER_LIB) \ - $(LIB_PLATFORM_LIB) \ - $(LIB_SYNERGY_LIB) \ - $(LIB_NET_LIB) \ - $(LIB_IO_LIB) \ - $(LIB_MT_LIB) \ - $(LIB_BASE_LIB) \ - $(LIB_ARCH_LIB) \ - $(LIB_COMMON_LIB) \ - $(NULL) - -CPP_FILES = $(CPP_FILES) $(BIN_LAUNCHER_CPP) -OBJ_FILES = $(OBJ_FILES) $(BIN_LAUNCHER_OBJ) -PROGRAMS = $(PROGRAMS) $(BIN_LAUNCHER_EXE) - -# Need shell functions. -guilibs = $(guilibs) shell32.lib - -# Dependency rules -$(BIN_LAUNCHER_OBJ): $(AUTODEP) -!if EXIST($(BIN_LAUNCHER_DST)\deps.mak) -!include $(BIN_LAUNCHER_DST)\deps.mak -!endif - -# Build rules. Use batch-mode rules if possible. -!if DEFINED(_NMAKE_VER) -{$(BIN_LAUNCHER_SRC)\}.cpp{$(BIN_LAUNCHER_DST)\}.obj:: -!else -{$(BIN_LAUNCHER_SRC)\}.cpp{$(BIN_LAUNCHER_DST)\}.obj: -!endif - @$(ECHO) Compile in $(BIN_LAUNCHER_SRC) - -@$(MKDIR) $(BIN_LAUNCHER_DST) 2>NUL: - $(cpp) $(cppdebug) $(cppflags) $(cppvarsmt) /showIncludes \ - $(BIN_LAUNCHER_INC) \ - /Fo$(BIN_LAUNCHER_DST)\ \ - /Fd$(BIN_LAUNCHER_DST)\src.pdb \ - $< | $(AUTODEP) $(BIN_LAUNCHER_SRC) $(BIN_LAUNCHER_DST) -$(BIN_LAUNCHER_RES): $(BIN_LAUNCHER_RC) - @$(ECHO) Compile $(**F) - -@$(MKDIR) $(BIN_LAUNCHER_DST) 2>NUL: - $(rc) $(rcflags) $(rcvars) \ - /fo$@ \ - $** -$(BIN_LAUNCHER_EXE): $(BIN_LAUNCHER_OBJ) $(BIN_LAUNCHER_RES) $(BIN_LAUNCHER_LIB) - @$(ECHO) Link $(@F) - $(link) $(ldebug) $(guilflags) $(guilibsmt) \ - /out:$@ \ - $** - $(AUTODEP) $(BIN_LAUNCHER_SRC) $(BIN_LAUNCHER_DST) \ - $(BIN_LAUNCHER_OBJ:.obj=.d) diff --git a/cmd/launcher/launcher.cpp b/cmd/launcher/launcher.cpp deleted file mode 100644 index 938822da..00000000 --- a/cmd/launcher/launcher.cpp +++ /dev/null @@ -1,755 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CConfig.h" -#include "KeyTypes.h" -#include "OptionTypes.h" -#include "ProtocolTypes.h" -#include "CLog.h" -#include "CStringUtil.h" -#include "CArch.h" -#include "CArchMiscWindows.h" -#include "XArch.h" -#include "Version.h" -#include "stdvector.h" -#include "resource.h" - -// these must come after the above because it includes windows.h -#include "LaunchUtil.h" -#include "CAddScreen.h" -#include "CAdvancedOptions.h" -#include "CAutoStart.h" -#include "CGlobalOptions.h" -#include "CHotkeyOptions.h" -#include "CInfo.h" -#include "CScreensLinks.h" - -typedef std::vector CStringList; - -class CChildWaitInfo { -public: - HWND m_dialog; - HANDLE m_child; - DWORD m_childID; - HANDLE m_ready; - HANDLE m_stop; -}; - -static const char* s_debugName[][2] = { - { TEXT("Error"), "ERROR" }, - { TEXT("Warning"), "WARNING" }, - { TEXT("Note"), "NOTE" }, - { TEXT("Info"), "INFO" }, - { TEXT("Debug"), "DEBUG" }, - { TEXT("Debug1"), "DEBUG1" }, - { TEXT("Debug2"), "DEBUG2" } -}; -static const int s_defaultDebug = 1; // WARNING -static const int s_minTestDebug = 3; // INFO - -HINSTANCE s_instance = NULL; - -static CGlobalOptions* s_globalOptions = NULL; -static CAdvancedOptions* s_advancedOptions = NULL; -static CHotkeyOptions* s_hotkeyOptions = NULL; -static CScreensLinks* s_screensLinks = NULL; -static CInfo* s_info = NULL; - -static bool s_userConfig = true; -static time_t s_configTime = 0; -static CConfig s_lastConfig; - -static const TCHAR* s_mainClass = TEXT("GoSynergy"); -static const TCHAR* s_layoutClass = TEXT("SynergyLayout"); - -enum SaveMode { - SAVE_QUITING, - SAVE_NORMAL, - SAVE_QUIET -}; - -// -// program arguments -// - -#define ARG CArgs::s_instance - -class CArgs { -public: - CArgs() { s_instance = this; } - ~CArgs() { s_instance = NULL; } - -public: - static CArgs* s_instance; - CConfig m_config; - CStringList m_screens; -}; - -CArgs* CArgs::s_instance = NULL; - - -static -BOOL CALLBACK -addDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); - -static -bool -isClientChecked(HWND hwnd) -{ - HWND child = getItem(hwnd, IDC_MAIN_CLIENT_RADIO); - return isItemChecked(child); -} - -static -void -enableMainWindowControls(HWND hwnd) -{ - bool client = isClientChecked(hwnd); - enableItem(hwnd, IDC_MAIN_CLIENT_SERVER_NAME_LABEL, client); - enableItem(hwnd, IDC_MAIN_CLIENT_SERVER_NAME_EDIT, client); - enableItem(hwnd, IDC_MAIN_SERVER_SCREENS_LABEL, !client); - enableItem(hwnd, IDC_MAIN_SCREENS, !client); - enableItem(hwnd, IDC_MAIN_OPTIONS, !client); - enableItem(hwnd, IDC_MAIN_HOTKEYS, !client); -} - -static -bool -execApp(const char* app, const CString& cmdLine, PROCESS_INFORMATION* procInfo) -{ - // prepare startup info - STARTUPINFO startup; - startup.cb = sizeof(startup); - startup.lpReserved = NULL; - startup.lpDesktop = NULL; - startup.lpTitle = NULL; - startup.dwX = (DWORD)CW_USEDEFAULT; - startup.dwY = (DWORD)CW_USEDEFAULT; - startup.dwXSize = (DWORD)CW_USEDEFAULT; - startup.dwYSize = (DWORD)CW_USEDEFAULT; - startup.dwXCountChars = 0; - startup.dwYCountChars = 0; - startup.dwFillAttribute = 0; - startup.dwFlags = STARTF_FORCEONFEEDBACK; - startup.wShowWindow = SW_SHOWDEFAULT; - startup.cbReserved2 = 0; - startup.lpReserved2 = NULL; - startup.hStdInput = NULL; - startup.hStdOutput = NULL; - startup.hStdError = NULL; - - // prepare path to app - CString appPath = getAppPath(app); - - // put path to app in command line - CString commandLine = "\""; - commandLine += appPath; - commandLine += "\" "; - commandLine += cmdLine; - - // start child - if (CreateProcess(NULL, (char*)commandLine.c_str(), - NULL, - NULL, - FALSE, - CREATE_DEFAULT_ERROR_MODE | - CREATE_NEW_PROCESS_GROUP | - NORMAL_PRIORITY_CLASS, - NULL, - NULL, - &startup, - procInfo) == 0) { - return false; - } - else { - return true; - } -} - -static -CString -getCommandLine(HWND hwnd, bool testing, bool silent) -{ - CString cmdLine; - - // add constant testing args - if (testing) { - cmdLine += " -z --no-restart --no-daemon"; - } - - // can't start as service on NT - else if (!CArchMiscWindows::isWindows95Family()) { - cmdLine += " --no-daemon"; - } - - // get the server name - CString server; - bool isClient = isClientChecked(hwnd); - if (isClient) { - // check server name - HWND child = getItem(hwnd, IDC_MAIN_CLIENT_SERVER_NAME_EDIT); - server = getWindowText(child); - if (!ARG->m_config.isValidScreenName(server)) { - if (!silent) { - showError(hwnd, CStringUtil::format( - getString(IDS_INVALID_SERVER_NAME).c_str(), - server.c_str())); - } - SetFocus(child); - return CString(); - } - - // compare server name to local host. a common error - // is to provide the client's name for the server. we - // don't bother to check the addresses though that'd be - // more accurate. - if (CStringUtil::CaselessCmp::equal(ARCH->getHostName(), server)) { - if (!silent) { - showError(hwnd, CStringUtil::format( - getString(IDS_SERVER_IS_CLIENT).c_str(), - server.c_str())); - } - SetFocus(child); - return CString(); - } - } - - // debug level. always include this. - if (true) { - HWND child = getItem(hwnd, IDC_MAIN_DEBUG); - int debug = (int)SendMessage(child, CB_GETCURSEL, 0, 0); - - // if testing then we force the debug level to be no less than - // s_minTestDebug. what's the point of testing if you can't - // see the debugging info? - if (testing && debug < s_minTestDebug) { - debug = s_minTestDebug; - } - - cmdLine += " --debug "; - cmdLine += s_debugName[debug][1]; - } - - // add advanced options - cmdLine += s_advancedOptions->getCommandLine(isClient, server); - - return cmdLine; -} - -static -bool -launchApp(HWND hwnd, bool testing, HANDLE* thread, DWORD* threadID) -{ - if (thread != NULL) { - *thread = NULL; - } - if (threadID != NULL) { - *threadID = 0; - } - - // start daemon if it's installed and we're not testing - if (!testing && CAutoStart::startDaemon()) { - return true; - } - - // decide if client or server - const bool isClient = isClientChecked(hwnd); - const char* app = isClient ? CLIENT_APP : SERVER_APP; - - // prepare command line - CString cmdLine = getCommandLine(hwnd, testing, false); - if (cmdLine.empty()) { - return false; - } - - // start child - PROCESS_INFORMATION procInfo; - if (!execApp(app, cmdLine, &procInfo)) { - showError(hwnd, CStringUtil::format( - getString(IDS_STARTUP_FAILED).c_str(), - getErrorString(GetLastError()).c_str())); - return false; - } - - // don't need process handle - CloseHandle(procInfo.hProcess); - - // save thread handle and thread ID if desired - if (thread != NULL) { - *thread = procInfo.hThread; - } - if (threadID != NULL) { - *threadID = procInfo.dwThreadId; - } - - return true; -} - -static -BOOL CALLBACK -waitDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - // only one wait dialog at a time! - static CChildWaitInfo* info = NULL; - - switch (message) { - case WM_INITDIALOG: - // save info pointer - info = reinterpret_cast(lParam); - - // save hwnd - info->m_dialog = hwnd; - - // signal ready - SetEvent(info->m_ready); - - return TRUE; - - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDCANCEL: - case IDOK: - // signal stop - SetEvent(info->m_stop); - - // done - EndDialog(hwnd, 0); - return TRUE; - } - } - - return FALSE; -} - -static -DWORD WINAPI -waitForChildThread(LPVOID vinfo) -{ - CChildWaitInfo* info = reinterpret_cast(vinfo); - - // wait for ready - WaitForSingleObject(info->m_ready, INFINITE); - - // wait for thread to complete or stop event - HANDLE handles[2]; - handles[0] = info->m_child; - handles[1] = info->m_stop; - DWORD n = WaitForMultipleObjects(2, handles, FALSE, INFINITE); - - // if stop was raised then terminate child and wait for it - if (n == WAIT_OBJECT_0 + 1) { - PostThreadMessage(info->m_childID, WM_QUIT, 0, 0); - WaitForSingleObject(info->m_child, INFINITE); - } - - // otherwise post IDOK to dialog box - else { - PostMessage(info->m_dialog, WM_COMMAND, MAKEWPARAM(IDOK, 0), 0); - } - - return 0; -} - -static -void -waitForChild(HWND hwnd, HANDLE thread, DWORD threadID) -{ - // prepare info for child wait dialog and thread - CChildWaitInfo info; - info.m_dialog = NULL; - info.m_child = thread; - info.m_childID = threadID; - info.m_ready = CreateEvent(NULL, TRUE, FALSE, NULL); - info.m_stop = CreateEvent(NULL, TRUE, FALSE, NULL); - - // create a thread to wait on the child thread and event - DWORD id; - HANDLE waiter = CreateThread(NULL, 0, &waitForChildThread, &info,0, &id); - - // do dialog that let's the user terminate the test - DialogBoxParam(s_instance, MAKEINTRESOURCE(IDD_WAIT), hwnd, - (DLGPROC)waitDlgProc, (LPARAM)&info); - - // force the waiter thread to finish and wait for it - SetEvent(info.m_ready); - SetEvent(info.m_stop); - WaitForSingleObject(waiter, INFINITE); - - // clean up - CloseHandle(waiter); - CloseHandle(info.m_ready); - CloseHandle(info.m_stop); -} - -static -void -initMainWindow(HWND hwnd) -{ - // append version number to title - CString titleFormat = getString(IDS_TITLE); - setWindowText(hwnd, CStringUtil::format(titleFormat.c_str(), VERSION)); - - // load configuration - bool configLoaded = - loadConfig(ARG->m_config, s_configTime, s_userConfig); - if (configLoaded) { - s_lastConfig = ARG->m_config; - } - - // get settings from registry - bool isServer = configLoaded; - int debugLevel = s_defaultDebug; - CString server; - HKEY key = CArchMiscWindows::openKey(HKEY_CURRENT_USER, getSettingsPath()); - if (key != NULL) { - if (isServer && CArchMiscWindows::hasValue(key, "isServer")) { - isServer = (CArchMiscWindows::readValueInt(key, "isServer") != 0); - } - if (CArchMiscWindows::hasValue(key, "debug")) { - debugLevel = static_cast( - CArchMiscWindows::readValueInt(key, "debug")); - if (debugLevel < 0) { - debugLevel = 0; - } - else if (debugLevel > CLog::kDEBUG2) { - debugLevel = CLog::kDEBUG2; - } - } - server = CArchMiscWindows::readValueString(key, "server"); - CArchMiscWindows::closeKey(key); - } - - // choose client/server radio buttons - HWND child; - child = getItem(hwnd, IDC_MAIN_CLIENT_RADIO); - setItemChecked(child, !isServer); - child = getItem(hwnd, IDC_MAIN_SERVER_RADIO); - setItemChecked(child, isServer); - - // set server name - child = getItem(hwnd, IDC_MAIN_CLIENT_SERVER_NAME_EDIT); - setWindowText(child, server); - - // debug level - child = getItem(hwnd, IDC_MAIN_DEBUG); - for (unsigned int i = 0; i < sizeof(s_debugName) / - sizeof(s_debugName[0]); ++i) { - SendMessage(child, CB_ADDSTRING, 0, (LPARAM)s_debugName[i][0]); - } - SendMessage(child, CB_SETCURSEL, debugLevel, 0); - - // update controls - enableMainWindowControls(hwnd); -} - -static -bool -saveMainWindow(HWND hwnd, SaveMode mode, CString* cmdLineOut = NULL) -{ - DWORD errorID = 0; - CString arg; - CString cmdLine; - - // save dialog state - bool isClient = isClientChecked(hwnd); - HKEY key = CArchMiscWindows::addKey(HKEY_CURRENT_USER, getSettingsPath()); - if (key != NULL) { - HWND child; - child = getItem(hwnd, IDC_MAIN_CLIENT_SERVER_NAME_EDIT); - CArchMiscWindows::setValue(key, "server", getWindowText(child)); - child = getItem(hwnd, IDC_MAIN_DEBUG); - CArchMiscWindows::setValue(key, "debug", - SendMessage(child, CB_GETCURSEL, 0, 0)); - CArchMiscWindows::setValue(key, "isServer", isClient ? 0 : 1); - CArchMiscWindows::closeKey(key); - } - - // save user's configuration - if (!s_userConfig || ARG->m_config != s_lastConfig) { - time_t t; - if (!saveConfig(ARG->m_config, false, t)) { - errorID = IDS_SAVE_FAILED; - arg = getErrorString(GetLastError()); - goto failed; - } - if (s_userConfig) { - s_configTime = t; - s_lastConfig = ARG->m_config; - } - } - - // save autostart configuration - if (CAutoStart::isDaemonInstalled()) { - if (s_userConfig || ARG->m_config != s_lastConfig) { - time_t t; - if (!saveConfig(ARG->m_config, true, t)) { - errorID = IDS_AUTOSTART_SAVE_FAILED; - arg = getErrorString(GetLastError()); - goto failed; - } - if (!s_userConfig) { - s_configTime = t; - s_lastConfig = ARG->m_config; - } - } - } - - // get autostart command - cmdLine = getCommandLine(hwnd, false, mode == SAVE_QUITING); - if (cmdLineOut != NULL) { - *cmdLineOut = cmdLine; - } - if (cmdLine.empty()) { - return (mode == SAVE_QUITING); - } - - // save autostart command - if (CAutoStart::isDaemonInstalled()) { - try { - CAutoStart::reinstallDaemon(isClient, cmdLine); - CAutoStart::uninstallDaemons(!isClient); - } - catch (XArchDaemon& e) { - errorID = IDS_INSTALL_GENERIC_ERROR; - arg = e.what(); - goto failed; - } - } - - return true; - -failed: - CString errorMessage = - CStringUtil::format(getString(errorID).c_str(), arg.c_str()); - if (mode == SAVE_QUITING) { - errorMessage += "\n"; - errorMessage += getString(IDS_UNSAVED_DATA_REALLY_QUIT); - if (askVerify(hwnd, errorMessage)) { - return true; - } - } - else if (mode == SAVE_NORMAL) { - showError(hwnd, errorMessage); - } - return false; -} - -static -LRESULT CALLBACK -mainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) { - case WM_ACTIVATE: - if (LOWORD(wParam) != WA_INACTIVE) { - // activated - - // see if the configuration changed - if (isConfigNewer(s_configTime, s_userConfig)) { - CString message = getString(IDS_CONFIG_CHANGED); - if (askVerify(hwnd, message)) { - time_t configTime; - bool userConfig; - CConfig newConfig; - if (loadConfig(newConfig, configTime, userConfig) && - userConfig == s_userConfig) { - ARG->m_config = newConfig; - s_lastConfig = ARG->m_config; - } - else { - message = getString(IDS_LOAD_FAILED); - showError(hwnd, message); - s_lastConfig = CConfig(); - } - } - } - } - else { - // deactivated; write configuration - if (!isShowingDialog()) { - saveMainWindow(hwnd, SAVE_QUIET); - } - } - break; - - case WM_COMMAND: - switch (LOWORD(wParam)) { - case IDCANCEL: - // save data - if (saveMainWindow(hwnd, SAVE_QUITING)) { - // quit - PostQuitMessage(0); - } - return 0; - - case IDOK: - case IDC_MAIN_TEST: { - // note if testing - const bool testing = (LOWORD(wParam) == IDC_MAIN_TEST); - - // save data - if (saveMainWindow(hwnd, SAVE_NORMAL)) { - // launch child app - DWORD threadID; - HANDLE thread; - if (!launchApp(hwnd, testing, &thread, &threadID)) { - return 0; - } - - // handle child program - if (testing) { - // wait for process to stop, allowing the user to kill it - waitForChild(hwnd, thread, threadID); - - // clean up - CloseHandle(thread); - } - else { - // don't need thread handle - if (thread != NULL) { - CloseHandle(thread); - } - - // notify of success - askOkay(hwnd, getString(IDS_STARTED_TITLE), - getString(IDS_STARTED)); - - // quit - PostQuitMessage(0); - } - } - return 0; - } - - case IDC_MAIN_AUTOSTART: { - CString cmdLine; - if (saveMainWindow(hwnd, SAVE_NORMAL, &cmdLine)) { - // run dialog - CAutoStart autoStart(hwnd, !isClientChecked(hwnd), cmdLine); - autoStart.doModal(); - } - return 0; - } - - case IDC_MAIN_CLIENT_RADIO: - case IDC_MAIN_SERVER_RADIO: - enableMainWindowControls(hwnd); - return 0; - - case IDC_MAIN_SCREENS: - s_screensLinks->doModal(); - break; - - case IDC_MAIN_OPTIONS: - s_globalOptions->doModal(); - break; - - case IDC_MAIN_ADVANCED: - s_advancedOptions->doModal(isClientChecked(hwnd)); - break; - - case IDC_MAIN_HOTKEYS: - s_hotkeyOptions->doModal(); - break; - - case IDC_MAIN_INFO: - s_info->doModal(); - break; - } - - default: - break; - } - return DefDlgProc(hwnd, message, wParam, lParam); -} - -int WINAPI -WinMain(HINSTANCE instance, HINSTANCE, LPSTR cmdLine, int nCmdShow) -{ - CArch arch(instance); - CLOG; - CArgs args; - - s_instance = instance; - - // if "/uninstall" is on the command line then just stop and - // uninstall the service and quit. this is the only option - // but we ignore any others. - if (CString(cmdLine).find("/uninstall") != CString::npos) { - CAutoStart::uninstallDaemons(false); - CAutoStart::uninstallDaemons(true); - return 0; - } - - // register main window (dialog) class - WNDCLASSEX classInfo; - classInfo.cbSize = sizeof(classInfo); - classInfo.style = CS_HREDRAW | CS_VREDRAW; - classInfo.lpfnWndProc = &mainWndProc; - classInfo.cbClsExtra = 0; - classInfo.cbWndExtra = DLGWINDOWEXTRA; - classInfo.hInstance = instance; - classInfo.hIcon = (HICON)LoadImage(instance, - MAKEINTRESOURCE(IDI_SYNERGY), - IMAGE_ICON, - 32, 32, LR_SHARED); - classInfo.hCursor = LoadCursor(NULL, IDC_ARROW); - classInfo.hbrBackground = reinterpret_cast(COLOR_3DFACE + 1); - classInfo.lpszMenuName = NULL; - classInfo.lpszClassName = s_mainClass; - classInfo.hIconSm = (HICON)LoadImage(instance, - MAKEINTRESOURCE(IDI_SYNERGY), - IMAGE_ICON, - 16, 16, LR_SHARED); - RegisterClassEx(&classInfo); - - // create main window - HWND mainWindow = CreateDialog(s_instance, - MAKEINTRESOURCE(IDD_MAIN), 0, NULL); - - // prep windows - initMainWindow(mainWindow); - s_globalOptions = new CGlobalOptions(mainWindow, &ARG->m_config); - s_advancedOptions = new CAdvancedOptions(mainWindow, &ARG->m_config); - s_hotkeyOptions = new CHotkeyOptions(mainWindow, &ARG->m_config); - s_screensLinks = new CScreensLinks(mainWindow, &ARG->m_config); - s_info = new CInfo(mainWindow); - - // show window - ShowWindow(mainWindow, nCmdShow); - - // main loop - MSG msg; - bool done = false; - do { - switch (GetMessage(&msg, NULL, 0, 0)) { - case -1: - // error - break; - - case 0: - // quit - done = true; - break; - - default: - if (!IsDialogMessage(mainWindow, &msg)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - break; - } - } while (!done); - - return msg.wParam; -} diff --git a/cmd/launcher/launcher.rc b/cmd/launcher/launcher.rc deleted file mode 100644 index ff72d069..00000000 --- a/cmd/launcher/launcher.rc +++ /dev/null @@ -1,617 +0,0 @@ -//Microsoft Developer Studio generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include -#if !defined(IDC_STATIC) -#define IDC_STATIC (-1) -#endif - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE DISCARDABLE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE DISCARDABLE -BEGIN - "#include \r\n" - "\0" -END - -3 TEXTINCLUDE DISCARDABLE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_MAIN DIALOG DISCARDABLE 32768, 0, 300, 199 -STYLE DS_MODALFRAME | WS_MINIMIZEBOX | WS_CAPTION | WS_SYSMENU -CAPTION "Synergy" -CLASS "GoSynergy" -FONT 8, "MS Sans Serif" -BEGIN - LTEXT "Choose to share or use a shared keyboard and mouse, provide the requested information, then click Test to check your settings or Start to save your settings and start Synergy.", - IDC_STATIC,7,7,286,19 - GROUPBOX "",IDC_STATIC,7,29,286,36 - GROUPBOX "",IDC_STATIC,7,72,286,36 - GROUPBOX "Options",IDC_STATIC,7,115,286,56 - CONTROL "&Use another computer's shared keyboard and mouse (client)", - IDC_MAIN_CLIENT_RADIO,"Button",BS_AUTORADIOBUTTON | - WS_GROUP | WS_TABSTOP,11,29,205,10 - CONTROL "Share this computer's keyboard and mouse (server)", - IDC_MAIN_SERVER_RADIO,"Button",BS_AUTORADIOBUTTON,11,72, - 177,10 - LTEXT "Other Computer's &Host Name:", - IDC_MAIN_CLIENT_SERVER_NAME_LABEL,12,46,94,8 - EDITTEXT IDC_MAIN_CLIENT_SERVER_NAME_EDIT,111,44,106,12, - ES_AUTOHSCROLL - LTEXT "&Screens && Links:",IDC_MAIN_SERVER_SCREENS_LABEL,12,89, - 54,8 - PUSHBUTTON "Configure...",IDC_MAIN_SCREENS,71,86,50,14 - PUSHBUTTON "&Options...",IDC_MAIN_OPTIONS,12,129,50,14 - PUSHBUTTON "Hot &Keys...",IDC_MAIN_HOTKEYS,68,129,50,14 - PUSHBUTTON "Adva&nced...",IDC_MAIN_ADVANCED,124,129,50,14 - PUSHBUTTON "&AutoStart...",IDC_MAIN_AUTOSTART,180,129,50,14 - LTEXT "&Logging Level:",IDC_STATIC,12,154,48,8 - COMBOBOX IDC_MAIN_DEBUG,68,151,61,60,CBS_DROPDOWNLIST | - WS_VSCROLL | WS_TABSTOP - PUSHBUTTON "&Info",IDC_MAIN_INFO,7,178,50,14 - DEFPUSHBUTTON "&Test",IDC_MAIN_TEST,131,179,50,14 - PUSHBUTTON "Start",IDOK,187,179,50,14 - PUSHBUTTON "Quit",IDCANCEL,243,179,50,14 -END - -IDD_ADD DIALOG DISCARDABLE 0, 0, 192, 254 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION -CAPTION "Add Screen" -FONT 8, "MS Sans Serif" -BEGIN - LTEXT "&Screen Name:",IDC_STATIC,7,9,46,8 - EDITTEXT IDC_ADD_SCREEN_NAME_EDIT,79,7,106,12,ES_AUTOHSCROLL - LTEXT "&Aliases:",IDC_STATIC,7,25,25,8 - EDITTEXT IDC_ADD_ALIASES_EDIT,79,26,106,24,ES_MULTILINE | - ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN - GROUPBOX "Options",IDC_STATIC,7,55,178,54 - LTEXT "If your Caps, Num, or Scroll Lock keys behave strangely on this client screen then try turning the half-duplex options on and reconnect the client.", - IDC_STATIC,13,65,165,25 - CONTROL "&Caps Lock",IDC_ADD_HD_CAPS_CHECK,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,13,93,51,10 - CONTROL "&Num Lock",IDC_ADD_HD_NUM_CHECK,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,69,93,51,10 - CONTROL "Sc&roll Lock",IDC_ADD_HD_SCROLL_CHECK,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,125,93,51,10 - GROUPBOX "Modifiers",IDC_STATIC,7,113,178,65 - LTEXT "Shift",IDC_STATIC,13,129,15,8 - COMBOBOX IDC_ADD_MOD_SHIFT,37,126,48,60,CBS_DROPDOWNLIST | - WS_VSCROLL | WS_TABSTOP - LTEXT "Ctrl",IDC_STATIC,13,144,11,8 - COMBOBOX IDC_ADD_MOD_CTRL,37,142,48,60,CBS_DROPDOWNLIST | - WS_VSCROLL | WS_TABSTOP - LTEXT "Alt",IDC_STATIC,13,160,9,8 - COMBOBOX IDC_ADD_MOD_ALT,37,158,48,60,CBS_DROPDOWNLIST | - WS_VSCROLL | WS_TABSTOP - LTEXT "Meta",IDC_STATIC,101,128,17,8 - COMBOBOX IDC_ADD_MOD_META,125,126,48,60,CBS_DROPDOWNLIST | - WS_VSCROLL | WS_TABSTOP - LTEXT "Super",IDC_STATIC,101,144,20,8 - COMBOBOX IDC_ADD_MOD_SUPER,125,142,48,60,CBS_DROPDOWNLIST | - WS_VSCROLL | WS_TABSTOP - GROUPBOX "Dead Corners",IDC_STATIC,7,183,178,43 - LTEXT "Don't switch in these corners:",IDC_STATIC,14,198,52,18 - CONTROL "",IDC_STATIC,"Static",SS_BLACKFRAME,68,193,47,28 - CONTROL "",IDC_ADD_DC_TOP_LEFT,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,76,197,16,8 - CONTROL "",IDC_ADD_DC_TOP_RIGHT,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,98,197,16,8 - CONTROL "",IDC_ADD_DC_BOTTOM_LEFT,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,76,210,16,8 - CONTROL "",IDC_ADD_DC_BOTTOM_RIGHT,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,98,210,16,8 - LTEXT "Size",IDC_STATIC,120,202,14,8 - EDITTEXT IDC_ADD_DC_SIZE,139,200,40,12,ES_AUTOHSCROLL | ES_NUMBER - DEFPUSHBUTTON "OK",IDOK,79,233,50,14 - PUSHBUTTON "Cancel",IDCANCEL,135,233,50,14 -END - -IDD_WAIT DIALOG DISCARDABLE 0, 0, 186, 54 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION -CAPTION "Running Test..." -FONT 8, "MS Sans Serif" -BEGIN - DEFPUSHBUTTON "Stop",IDOK,129,33,50,14 - LTEXT "Running synergy. Press Stop to end the test.", - IDC_STATIC,7,7,172,15 -END - -IDD_AUTOSTART DIALOG DISCARDABLE 0, 0, 195, 189 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Auto Start" -FONT 8, "MS Sans Serif" -BEGIN - DEFPUSHBUTTON "Close",IDCANCEL,138,168,50,14 - LTEXT "Synergy can be configured to start automatically when you log in. If you have sufficient access rights, you can instead configure synergy to start automatically when your computer starts.", - IDC_STATIC,7,7,181,33 - LTEXT "You have sufficient access rights to install and uninstall Auto Start for all users or for just yourself.", - IDC_AUTOSTART_PERMISSION_MSG,7,69,181,17 - LTEXT "Synergy is configured to start automatically when the system starts.", - IDC_AUTOSTART_INSTALLED_MSG,7,93,181,17 - GROUPBOX "When &You Log In",IDC_STATIC,7,119,84,40 - PUSHBUTTON "Install",IDC_AUTOSTART_INSTALL_USER,23,133,50,14 - GROUPBOX "When &Computer Starts",IDC_STATIC,104,119,84,40 - PUSHBUTTON "Install",IDC_AUTOSTART_INSTALL_SYSTEM,119,134,50,14 - LTEXT "Synergy can be configured to start automatically when the computer starts or when you log in but not both.", - IDC_STATIC,7,43,181,17 -END - -IDD_GLOBAL_OPTIONS DIALOG DISCARDABLE 0, 0, 207, 290 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Options" -FONT 8, "MS Sans Serif" -BEGIN - LTEXT "It's easy to unintentionally switch screens when the pointer is near a screen's edge. Synergy can prevent switching until certain conditions are met to reduce unintentional switching.", - IDC_STATIC,7,7,191,26 - LTEXT "Synergy can wait to switch until the cursor has been at a screen's edge for some amount of time.", - IDC_STATIC,7,37,193,16 - CONTROL "Switch after waiting",IDC_GLOBAL_DELAY_CHECK,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,59,77,10 - EDITTEXT IDC_GLOBAL_DELAY_TIME,112,58,45,12,ES_AUTOHSCROLL | - ES_NUMBER - LTEXT "ms",IDC_STATIC,159,60,10,8 - LTEXT "Synergy can switch only when the cursor hits a screen edge twice within some amount of time.", - IDC_STATIC,7,77,193,16 - CONTROL "Switch on double tap within",IDC_GLOBAL_TWO_TAP_CHECK, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,99,103,10 - EDITTEXT IDC_GLOBAL_TWO_TAP_TIME,112,98,45,12,ES_AUTOHSCROLL | - ES_NUMBER - LTEXT "ms",IDC_STATIC,159,100,10,8 - LTEXT "Synergy can periodically check that clients are still alive and connected. Use this only if synergy doesn't detect when clients disconnect.", - IDC_STATIC,7,122,193,24 - CONTROL "Check clients every",IDC_GLOBAL_HEARTBEAT_CHECK,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,7,153,78,10 - EDITTEXT IDC_GLOBAL_HEARTBEAT_TIME,112,152,45,12,ES_AUTOHSCROLL | - ES_NUMBER - LTEXT "ms",IDC_STATIC,159,154,10,8 - LTEXT "Synergy can synchronize screen savers across all screens.", - IDC_STATIC,7,176,193,8 - CONTROL "Synchronize screen savers",IDC_GLOBAL_SCREENSAVER_SYNC, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,192,101,10 - LTEXT "Relative mouse moves on secondary screens.",IDC_STATIC, - 7,213,193,8 - CONTROL "Use relative mouse moves",IDC_GLOBAL_RELATIVE_MOVES, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,229,99,10 - CONTROL "Don't take foreground window on Windows servers", - IDC_GLOBAL_LEAVE_FOREGROUND,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,7,250,177,10 - DEFPUSHBUTTON "OK",IDOK,94,269,50,14 - PUSHBUTTON "Cancel",IDCANCEL,150,269,50,14 -END - -IDD_ADVANCED_OPTIONS DIALOG DISCARDABLE 0, 0, 230, 186 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Advanced Options" -FONT 8, "MS Sans Serif" -BEGIN - LTEXT "Synergy normally uses this computer's name as its screen name. Enter another name here if you want to use a different screen name.", - IDC_STATIC,7,7,216,19 - LTEXT "Screen &Name:",IDC_STATIC,7,34,46,8 - EDITTEXT IDC_ADVANCED_NAME_EDIT,63,32,106,12,ES_AUTOHSCROLL - LTEXT "Synergy normally uses a particular network port number. Enter an alternative port here. (The server and all clients must use the same port number.)", - IDC_STATIC,7,56,216,26 - LTEXT "&Port:",IDC_STATIC,7,90,16,8 - EDITTEXT IDC_ADVANCED_PORT_EDIT,63,88,40,12,ES_AUTOHSCROLL | - ES_NUMBER - LTEXT "The server normally listens for client connections on all network interfaces. Enter the address of a particular interface to listen on just that interface.", - IDC_STATIC,7,110,216,26 - LTEXT "&Interface:",IDC_STATIC,7,144,31,8 - EDITTEXT IDC_ADVANCED_INTERFACE_EDIT,63,142,81,12,ES_AUTOHSCROLL - PUSHBUTTON "&Defaults",IDC_ADVANCED_DEFAULTS,7,165,50,14 - DEFPUSHBUTTON "OK",IDOK,118,165,50,14 - PUSHBUTTON "Cancel",IDCANCEL,173,165,50,14 -END - -IDD_SCREENS_LINKS DIALOG DISCARDABLE 0, 0, 354, 213 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Screens & Links" -FONT 8, "MS Sans Serif" -BEGIN - LTEXT "&Screens:",IDC_STATIC,7,7,29,8 - LISTBOX IDC_SCREENS_SCREENS,7,18,100,36,LBS_SORT | - LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON "+",IDC_SCREENS_ADD_SCREEN,7,57,17,14 - PUSHBUTTON "-",IDC_SCREENS_REMOVE_SCREEN,28,57,17,14 - PUSHBUTTON "Edit",IDC_SCREENS_EDIT_SCREEN,49,57,24,14 - LTEXT "&Links:",IDC_STATIC,7,83,20,8 - LISTBOX IDC_SCREENS_LINKS,7,94,339,59,LBS_SORT | - LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP - EDITTEXT IDC_SCREENS_SRC_START,7,156,16,12,ES_AUTOHSCROLL | - ES_NUMBER - LTEXT "to",IDC_STATIC,25,158,8,8 - EDITTEXT IDC_SCREENS_SRC_END,33,156,16,12,ES_AUTOHSCROLL | - ES_NUMBER - LTEXT "% of the",IDC_STATIC,52,158,27,8 - COMBOBOX IDC_SCREENS_SRC_SIDE,80,156,48,69,CBS_DROPDOWNLIST | - WS_VSCROLL | WS_TABSTOP - LTEXT "of",IDC_STATIC,129,158,8,8 - COMBOBOX IDC_SCREENS_SRC_SCREEN,139,156,59,53,CBS_DROPDOWNLIST | - WS_VSCROLL | WS_TABSTOP - LTEXT "goes to",IDC_STATIC,200,158,24,8 - EDITTEXT IDC_SCREENS_DST_START,225,156,16,12,ES_AUTOHSCROLL | - ES_NUMBER - LTEXT "to",IDC_STATIC,243,158,8,8 - EDITTEXT IDC_SCREENS_DST_END,251,156,16,12,ES_AUTOHSCROLL | - ES_NUMBER - LTEXT "% of",IDC_STATIC,270,158,15,8 - COMBOBOX IDC_SCREENS_DST_SCREEN,287,156,59,53,CBS_DROPDOWNLIST | - WS_VSCROLL | WS_TABSTOP - PUSHBUTTON "+",IDC_SCREENS_ADD_LINK,7,172,17,14 - PUSHBUTTON "-",IDC_SCREENS_REMOVE_LINK,28,172,17,14 - DEFPUSHBUTTON "OK",IDOK,241,192,50,14 - PUSHBUTTON "Cancel",IDCANCEL,297,192,50,14 - LTEXT "Source edge overlaps an existing edge.", - IDC_SCREENS_OVERLAP_ERROR,72,175,126,8,NOT WS_VISIBLE | - NOT WS_GROUP -END - -IDD_INFO DIALOG DISCARDABLE 0, 0, 186, 95 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Info" -FONT 8, "MS Sans Serif" -BEGIN - LTEXT "Version:",IDC_STATIC,7,7,26,8 - EDITTEXT IDC_INFO_VERSION,52,7,127,12,ES_AUTOHSCROLL | - ES_READONLY | NOT WS_BORDER - LTEXT "Hostname:",IDC_STATIC,7,19,35,8 - EDITTEXT IDC_INFO_HOSTNAME,52,19,127,12,ES_AUTOHSCROLL | - ES_READONLY | NOT WS_BORDER - LTEXT "IP Address:",IDC_STATIC,7,31,37,8 - EDITTEXT IDC_INFO_IP_ADDRESS,52,31,127,12,ES_AUTOHSCROLL | - ES_READONLY | NOT WS_BORDER - LTEXT "User Config:",IDC_STATIC,7,43,40,8 - EDITTEXT IDC_INFO_USER_CONFIG,52,43,127,12,ES_AUTOHSCROLL | - ES_READONLY | NOT WS_BORDER - LTEXT "Sys Config:",IDC_STATIC,7,55,36,8 - EDITTEXT IDC_INFO_SYS_CONFIG,52,55,127,12,ES_AUTOHSCROLL | - ES_READONLY | NOT WS_BORDER - DEFPUSHBUTTON "OK",IDOK,129,74,50,14 -END - -IDD_HOTKEY_OPTIONS DIALOG DISCARDABLE 0, 0, 360, 151 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Hot Keys" -FONT 8, "MS Sans Serif" -BEGIN - LTEXT "&Hot Keys:",IDC_STATIC,7,7,32,8 - LISTBOX IDC_HOTKEY_HOTKEYS,7,18,169,88,LBS_SORT | - LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON "+",IDC_HOTKEY_ADD_HOTKEY,7,109,17,14 - PUSHBUTTON "-",IDC_HOTKEY_REMOVE_HOTKEY,28,109,17,14 - PUSHBUTTON "Edit",IDC_HOTKEY_EDIT_HOTKEY,49,109,24,14 - LTEXT "&Actions:",IDC_STATIC,183,7,26,8 - LISTBOX IDC_HOTKEY_ACTIONS,183,18,169,88,LBS_SORT | - LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON "+",IDC_HOTKEY_ADD_ACTION,183,109,17,14 - PUSHBUTTON "-",IDC_HOTKEY_REMOVE_ACTION,204,109,17,14 - PUSHBUTTON "Edit",IDC_HOTKEY_EDIT_ACTION,225,109,24,14 - DEFPUSHBUTTON "OK",IDOK,302,130,50,14 -END - -IDD_HOTKEY_CONDITION DIALOG DISCARDABLE 0, 0, 183, 58 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Hot Key" -FONT 8, "MS Sans Serif" -BEGIN - LTEXT "Enter &new hot key or mouse button:",IDC_STATIC,7,7,113, - 8 - EDITTEXT IDC_HOTKEY_CONDITION_HOTKEY,7,17,169,12,ES_WANTRETURN - DEFPUSHBUTTON "OK",IDOK,70,37,50,14 - PUSHBUTTON "Cancel",IDCANCEL,126,37,50,14 -END - -IDD_HOTKEY_ACTION DIALOG DISCARDABLE 0, 0, 183, 218 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Action" -FONT 8, "MS Sans Serif" -BEGIN - LTEXT "&Action:",IDC_STATIC,7,7,23,8 - CONTROL "Press:",IDC_HOTKEY_ACTION_DOWN,"Button", - BS_AUTORADIOBUTTON | WS_TABSTOP,7,19,35,10 - CONTROL "Release:",IDC_HOTKEY_ACTION_UP,"Button", - BS_AUTORADIOBUTTON,7,31,44,10 - CONTROL "Press && Release:",IDC_HOTKEY_ACTION_DOWNUP,"Button", - BS_AUTORADIOBUTTON,7,43,69,10 - CONTROL "Switch To Screen:",IDC_HOTKEY_ACTION_SWITCH_TO,"Button", - BS_AUTORADIOBUTTON,7,85,75,10 - CONTROL "Switch In Direction:",IDC_HOTKEY_ACTION_SWITCH_IN, - "Button",BS_AUTORADIOBUTTON,7,101,77,10 - CONTROL "Lock Cursor to Screen:",IDC_HOTKEY_ACTION_LOCK,"Button", - BS_AUTORADIOBUTTON,7,117,89,10 - CONTROL "Keyboard broadcasting:", - IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST,"Button", - BS_AUTORADIOBUTTON,7,133,89,10 - LTEXT "&Hot key or mouse button:",IDC_STATIC,7,55,80,8 - EDITTEXT IDC_HOTKEY_ACTION_HOTKEY,7,67,152,12,ES_WANTRETURN - PUSHBUTTON "...",IDC_HOTKEY_ACTION_SCREENS,162,67,14,12 - COMBOBOX IDC_HOTKEY_ACTION_SWITCH_TO_LIST,87,83,89,62, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - COMBOBOX IDC_HOTKEY_ACTION_SWITCH_IN_LIST,106,99,70,66, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - COMBOBOX IDC_HOTKEY_ACTION_LOCK_LIST,106,115,70,58, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - COMBOBOX IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST_LIST,106,131,53,58, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON "...",IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST_SCREENS, - 162,131,14,12 - LTEXT "Action takes place &when:",IDC_STATIC,7,153,81,8 - CONTROL "Hot key is pressed",IDC_HOTKEY_ACTION_ON_ACTIVATE, - "Button",BS_AUTORADIOBUTTON | WS_TABSTOP,7,165,74,10 - CONTROL "Hot key is released",IDC_HOTKEY_ACTION_ON_DEACTIVATE, - "Button",BS_AUTORADIOBUTTON,7,177,76,10 - DEFPUSHBUTTON "OK",IDOK,70,197,50,14 - PUSHBUTTON "Cancel",IDCANCEL,126,197,50,14 -END - -IDD_HOTKEY_SCREENS DIALOG DISCARDABLE 0, 0, 237, 79 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Target Screens" -FONT 8, "MS Sans Serif" -BEGIN - LTEXT "&Available screens:",IDC_STATIC,7,7,58,8 - LISTBOX IDC_HOTKEY_SCREENS_SRC,7,17,100,36,LBS_NOINTEGRALHEIGHT | - LBS_EXTENDEDSEL | WS_VSCROLL | WS_TABSTOP - LISTBOX IDC_HOTKEY_SCREENS_DST,130,17,100,36, - LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL | WS_VSCROLL | - WS_TABSTOP - PUSHBUTTON "-->",IDC_HOTKEY_SCREENS_ADD,109,21,17,14 - PUSHBUTTON "<--",IDC_HOTKEY_SCREENS_REMOVE,109,38,17,14 - DEFPUSHBUTTON "OK",IDOK,124,58,50,14 - PUSHBUTTON "Cancel",IDCANCEL,180,58,50,14 - LTEXT "&Send action to screens:",IDC_STATIC,130,7,76,8 -END - - -///////////////////////////////////////////////////////////////////////////// -// -// DESIGNINFO -// - -#ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO DISCARDABLE -BEGIN - IDD_MAIN, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 293 - TOPMARGIN, 7 - BOTTOMMARGIN, 192 - END - - IDD_ADD, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 185 - TOPMARGIN, 7 - BOTTOMMARGIN, 247 - END - - IDD_WAIT, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 179 - TOPMARGIN, 7 - BOTTOMMARGIN, 47 - END - - IDD_AUTOSTART, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 188 - TOPMARGIN, 7 - BOTTOMMARGIN, 182 - END - - IDD_GLOBAL_OPTIONS, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 200 - TOPMARGIN, 7 - BOTTOMMARGIN, 283 - END - - IDD_ADVANCED_OPTIONS, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 223 - TOPMARGIN, 7 - BOTTOMMARGIN, 179 - END - - IDD_SCREENS_LINKS, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 347 - TOPMARGIN, 7 - BOTTOMMARGIN, 206 - END - - IDD_INFO, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 179 - TOPMARGIN, 7 - BOTTOMMARGIN, 88 - END - - IDD_HOTKEY_OPTIONS, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 353 - TOPMARGIN, 7 - BOTTOMMARGIN, 144 - END - - IDD_HOTKEY_CONDITION, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 176 - TOPMARGIN, 7 - BOTTOMMARGIN, 51 - END - - IDD_HOTKEY_ACTION, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 176 - TOPMARGIN, 7 - BOTTOMMARGIN, 195 - END - - IDD_HOTKEY_SCREENS, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 230 - TOPMARGIN, 7 - BOTTOMMARGIN, 72 - END -END -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_SYNERGY ICON DISCARDABLE "synergy.ico" - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -STRINGTABLE DISCARDABLE -BEGIN - IDS_ERROR "Error" - IDS_INVALID_SCREEN_NAME "Screen name `%{1}' is invalid." - IDS_DUPLICATE_SCREEN_NAME "The screen name `%{1}' is already being used." - IDS_SCREEN_NAME_IS_ALIAS "A name may not be an alias of itself." - IDS_VERIFY "Confirm" - IDS_UNSAVED_DATA_REALLY_QUIT "You have unsaved changes. Really quit?" - IDS_UNKNOWN_SCREEN_NAME "The screen name `%{1}' is not in the layout." - IDS_INVALID_PORT "The port `%{1}' is invalid. It must be between 1 and 65535 inclusive. %{2} is the standard port." - IDS_SAVE_FAILED "Failed to save configuration: %{1}" - IDS_STARTUP_FAILED "Failed to start synergy: %{1}" - IDS_STARTED_TITLE "Started" - IDS_STARTED "Synergy was successfully started. Use the task manager or tray icon to terminate it." - IDS_UNINSTALL_TITLE "Removed Auto-Start" -END - -STRINGTABLE DISCARDABLE -BEGIN - IDS_AUTOSTART_PERMISSION_SYSTEM - "You have sufficient access rights to install and uninstall Auto Start for all users." - IDS_AUTOSTART_PERMISSION_USER - "You have sufficient access rights to install and uninstall Auto Start for just yourself." - IDS_AUTOSTART_PERMISSION_NONE - "You do not have sufficient access rights to install or uninstall Auto Start." - IDS_AUTOSTART_INSTALLED_SYSTEM - "Synergy is configured to start automatically when the system starts." - IDS_AUTOSTART_INSTALLED_USER - "Synergy is configured to start automatically when you log in." - IDS_AUTOSTART_INSTALLED_NONE - "Synergy is not configured to start automatically." - IDS_INSTALL_LABEL "Install" - IDS_UNINSTALL_LABEL "Uninstall" - IDS_INSTALL_GENERIC_ERROR "Install failed: %{1}" - IDS_UNINSTALL_GENERIC_ERROR "Uninstall failed: %{1}" - IDS_INSTALL_TITLE "Installed Auto-Start" - IDS_INSTALLED_SYSTEM "Installed auto-start. Synergy will automatically start each time you start your computer." - IDS_INSTALLED_USER "Installed auto-start. Synergy will automatically start each time you log in." -END - -STRINGTABLE DISCARDABLE -BEGIN - IDS_UNINSTALLED_SYSTEM "Removed auto-start. Synergy will not automatically start each time you start or reboot your computer." - IDS_UNINSTALLED_USER "Removed auto-start. Synergy will not automatically start each time you log in." - IDS_INVALID_SERVER_NAME "Server name `%{1}' is invalid." - IDS_TITLE "Synergy - Version %{1}" - IDS_SERVER_IS_CLIENT "Please enter the name of the computer sharing a\nkeyboard and mouse, not the name of this computer,\nin the Other Computer's Host Name field." - IDS_ADD_SCREEN "Add Screen" - IDS_EDIT_SCREEN "Edit Screen %{1}" - IDS_ERROR_CODE "Error code: %{1}" - IDS_AUTOSTART_PERMISSION_ALL - "You have sufficient access rights to install and uninstall Auto Start for all users or for just yourself." - IDS_INVALID_INTERFACE_NAME "The interface '%{1}' is invalid: %{2}" - IDS_INVALID_CORNER_SIZE "The dead corner size %{1} is invalid; it must be 0 or higher." - IDS_NEW_LINK "[New Link]" - IDS_SIDE_LEFT "left of" - IDS_SIDE_RIGHT "right of" - IDS_SIDE_TOP "above" - IDS_SIDE_BOTTOM "below" -END - -STRINGTABLE DISCARDABLE -BEGIN - IDS_LINK_FORMAT "%{4}%{5} is %{3} %{1}%{2}" - IDS_LINK_INTERVAL_FORMAT "(%{1},%{2})" - IDS_EDGE_LEFT "left" - IDS_EDGE_RIGHT "right" - IDS_EDGE_TOP "top" - IDS_EDGE_BOTTOM "bottom" - IDS_AUTOSTART_SAVE_FAILED "Failed to save autostart configuration: %{1}" - IDS_LOAD_FAILED "Failed to load configuration." - IDS_CONFIG_CHANGED "Configuration changed on disk. Reload?" - IDS_MODE_OFF "off" - IDS_MODE_ON "on" - IDS_MODE_TOGGLE "toggle" - IDS_ALL_SCREENS "All Screens" - IDS_ACTIVE_SCREEN "Active Screen" -END - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/cmd/launcher/resource.h b/cmd/launcher/resource.h deleted file mode 100644 index f284fd62..00000000 --- a/cmd/launcher/resource.h +++ /dev/null @@ -1,186 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by launcher.rc -// -#define IDS_ERROR 1 -#define IDS_INVALID_SCREEN_NAME 2 -#define IDS_DUPLICATE_SCREEN_NAME 3 -#define IDS_SCREEN_NAME_IS_ALIAS 4 -#define IDS_VERIFY 5 -#define IDS_UNSAVED_DATA_REALLY_QUIT 6 -#define IDS_UNKNOWN_SCREEN_NAME 7 -#define IDS_INVALID_PORT 8 -#define IDS_SAVE_FAILED 9 -#define IDS_STARTUP_FAILED 10 -#define IDS_STARTED_TITLE 11 -#define IDS_STARTED 12 -#define IDS_INSTALL_FAILED 13 -#define IDS_UNINSTALL_TITLE 14 -#define IDS_UNINSTALLED 15 -#define IDS_UNINSTALL_FAILED 16 -#define IDS_CLIENT 17 -#define IDS_SERVER 18 -#define IDS_AUTOSTART_PERMISSION_SYSTEM 19 -#define IDS_AUTOSTART_PERMISSION_USER 20 -#define IDS_AUTOSTART_PERMISSION_NONE 21 -#define IDS_AUTOSTART_INSTALLED_SYSTEM 22 -#define IDS_AUTOSTART_INSTALLED_USER 23 -#define IDS_AUTOSTART_INSTALLED_NONE 24 -#define IDS_INSTALL_LABEL 25 -#define IDS_UNINSTALL_LABEL 26 -#define IDS_INSTALL_GENERIC_ERROR 27 -#define IDS_UNINSTALL_GENERIC_ERROR 28 -#define IDS_INSTALL_TITLE 29 -#define IDS_INSTALLED_SYSTEM 30 -#define IDS_INSTALLED_USER 31 -#define IDS_UNINSTALLED_SYSTEM 32 -#define IDS_UNINSTALLED_USER 33 -#define IDS_INVALID_SERVER_NAME 34 -#define IDS_TITLE 35 -#define IDS_SERVER_IS_CLIENT 36 -#define IDS_ADD_SCREEN 37 -#define IDS_EDIT_SCREEN 38 -#define IDS_INVALID_TIME 39 -#define IDS_ERROR_CODE 39 -#define IDS_AUTOSTART_PERMISSION_ALL 40 -#define IDS_INVALID_INTERFACE_NAME 41 -#define IDS_INVALID_CORNER_SIZE 42 -#define IDS_NEW_LINK 43 -#define IDS_SIDE_LEFT 44 -#define IDS_SIDE_RIGHT 45 -#define IDS_SIDE_TOP 46 -#define IDS_SIDE_BOTTOM 47 -#define IDS_LINK_FORMAT 48 -#define IDS_LINK_INTERVAL_FORMAT 49 -#define IDS_EDGE_LEFT 50 -#define IDS_EDGE_RIGHT 51 -#define IDS_EDGE_TOP 52 -#define IDS_EDGE_BOTTOM 53 -#define IDS_AUTOSTART_SAVE_FAILED 54 -#define IDS_LOAD_FAILED 55 -#define IDS_CONFIG_CHANGED 56 -#define IDS_MODE_OFF 57 -#define IDS_MODE_ON 58 -#define IDS_MODE_TOGGLE 59 -#define IDS_ALL_SCREENS 60 -#define IDS_ACTIVE_SCREEN 61 -#define IDD_MAIN 101 -#define IDD_ADD 102 -#define IDD_WAIT 103 -#define IDI_SYNERGY 104 -#define IDD_AUTOSTART 105 -#define IDD_ADVANCED_OPTIONS 106 -#define IDD_GLOBAL_OPTIONS 107 -#define IDD_SCREENS_LINKS 110 -#define IDD_INFO 111 -#define IDD_HOTKEY_OPTIONS 112 -#define IDD_HOTKEY_CONDITION 113 -#define IDD_HOTKEY_ACTION 114 -#define IDD_HOTKEY_SCREENS 115 -#define IDC_MAIN_CLIENT_RADIO 1000 -#define IDC_MAIN_SERVER_RADIO 1001 -#define IDC_MAIN_CLIENT_SERVER_NAME_LABEL 1002 -#define IDC_MAIN_CLIENT_SERVER_NAME_EDIT 1003 -#define IDC_MAIN_SERVER_SCREENS_LABEL 1004 -#define IDC_MAIN_SCREENS 1005 -#define IDC_MAIN_OPTIONS 1006 -#define IDC_MAIN_ADVANCED 1007 -#define IDC_MAIN_AUTOSTART 1008 -#define IDC_MAIN_TEST 1009 -#define IDC_MAIN_SAVE 1010 -#define IDC_MAIN_HOTKEYS 1010 -#define IDC_MAIN_DEBUG 1011 -#define IDC_ADD_SCREEN_NAME_EDIT 1020 -#define IDC_ADD_ALIASES_EDIT 1021 -#define IDC_AUTOSTART_INSTALLED_MSG 1031 -#define IDC_AUTOSTART_PERMISSION_MSG 1032 -#define IDC_AUTOSTART_INSTALL_USER 1033 -#define IDC_AUTOSTART_INSTALL_SYSTEM 1034 -#define IDC_ADD_HD_CAPS_CHECK 1037 -#define IDC_ADD_HD_NUM_CHECK 1038 -#define IDC_ADVANCED_NAME_EDIT 1038 -#define IDC_ADVANCED_PORT_EDIT 1039 -#define IDC_ADD_HD_SCROLL_CHECK 1039 -#define IDC_ADVANCED_INTERFACE_EDIT 1040 -#define IDC_GLOBAL_DELAY_CHECK 1041 -#define IDC_GLOBAL_DELAY_TIME 1042 -#define IDC_GLOBAL_TWO_TAP_CHECK 1043 -#define IDC_ADD_MOD_SHIFT 1043 -#define IDC_GLOBAL_TWO_TAP_TIME 1044 -#define IDC_ADD_MOD_CTRL 1044 -#define IDC_ADD_MOD_ALT 1045 -#define IDC_GLOBAL_HEARTBEAT_CHECK 1045 -#define IDC_ADD_MOD_META 1046 -#define IDC_GLOBAL_HEARTBEAT_TIME 1046 -#define IDC_ADD_MOD_SUPER 1047 -#define IDC_GLOBAL_SCREENSAVER_SYNC 1047 -#define IDC_GLOBAL_RELATIVE_MOVES 1048 -#define IDC_ADVANCED_DEFAULTS 1049 -#define IDC_GLOBAL_LEAVE_FOREGROUND 1049 -#define IDC_ADD_DC_SIZE 1052 -#define IDC_ADD_DC_TOP_LEFT 1053 -#define IDC_ADD_DC_TOP_RIGHT 1054 -#define IDC_ADD_DC_BOTTOM_LEFT 1055 -#define IDC_ADD_DC_BOTTOM_RIGHT 1056 -#define IDC_SCREENS_SRC_SIDE 1057 -#define IDC_SCREENS_SRC_START 1058 -#define IDC_SCREENS_SRC_END 1059 -#define IDC_SCREENS_SRC_SCREEN 1060 -#define IDC_SCREENS_SCREENS 1061 -#define IDC_SCREENS_ADD_SCREEN 1062 -#define IDC_SCREENS_LINKS 1063 -#define IDC_SCREENS_DST_START 1064 -#define IDC_SCREENS_DST_END 1065 -#define IDC_SCREENS_DST_SCREEN 1066 -#define IDC_SCREENS_REMOVE_SCREEN 1067 -#define IDC_SCREENS_EDIT_SCREEN 1068 -#define IDC_SCREENS_ADD_LINK 1069 -#define IDC_SCREENS_REMOVE_LINK 1070 -#define IDC_SCREENS_OVERLAP_ERROR 1071 -#define IDC_INFO_VERSION 1073 -#define IDC_MAIN_INFO 1074 -#define IDC_INFO_HOSTNAME 1076 -#define IDC_HOTKEY_HOTKEYS 1076 -#define IDC_INFO_IP_ADDRESS 1077 -#define IDC_HOTKEY_ADD_HOTKEY 1077 -#define IDC_INFO_USER_CONFIG 1078 -#define IDC_HOTKEY_REMOVE_HOTKEY 1078 -#define IDC_INFO_SYS_CONFIG 1079 -#define IDC_HOTKEY_EDIT_HOTKEY 1079 -#define IDC_HOTKEY_ACTIONS 1080 -#define IDC_HOTKEY_CONDITION_HOTKEY 1080 -#define IDC_HOTKEY_ACTION_DOWNUP 1081 -#define IDC_HOTKEY_ADD_ACTION 1082 -#define IDC_HOTKEY_ACTION_DOWN 1082 -#define IDC_HOTKEY_REMOVE_ACTION 1083 -#define IDC_HOTKEY_ACTION_UP 1083 -#define IDC_HOTKEY_EDIT_ACTION 1084 -#define IDC_HOTKEY_ACTION_HOTKEY 1085 -#define IDC_HOTKEY_ACTION_SWITCH_TO_LIST 1086 -#define IDC_HOTKEY_ACTION_SWITCH_TO 1087 -#define IDC_HOTKEY_ACTION_SWITCH_IN 1088 -#define IDC_HOTKEY_ACTION_LOCK 1089 -#define IDC_HOTKEY_ACTION_SWITCH_IN_LIST 1090 -#define IDC_HOTKEY_ACTION_LOCK_LIST 1091 -#define IDC_HOTKEY_ACTION_ON_ACTIVATE 1092 -#define IDC_HOTKEY_ACTION_ON_DEACTIVATE 1093 -#define IDC_HOTKEY_ACTION_SCREENS 1094 -#define IDC_HOTKEY_SCREENS_SRC 1095 -#define IDC_HOTKEY_SCREENS_DST 1096 -#define IDC_HOTKEY_SCREENS_ADD 1097 -#define IDC_HOTKEY_SCREENS_REMOVE 1098 -#define IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST 1099 -#define IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST_LIST 1100 -#define IDC_HOTKEY_ACTION_KEYBOARD_BROADCAST_SCREENS 1101 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NO_MFC 1 -#define _APS_NEXT_RESOURCE_VALUE 116 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1102 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/cmd/launcher/synergy.ico b/cmd/launcher/synergy.ico deleted file mode 100644 index 89f965f4..00000000 Binary files a/cmd/launcher/synergy.ico and /dev/null differ diff --git a/cmd/synergyc/CClientTaskBarReceiver.cpp b/cmd/synergyc/CClientTaskBarReceiver.cpp deleted file mode 100644 index 025b43f6..00000000 --- a/cmd/synergyc/CClientTaskBarReceiver.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CClientTaskBarReceiver.h" -#include "CClient.h" -#include "CLock.h" -#include "CStringUtil.h" -#include "IEventQueue.h" -#include "CArch.h" -#include "Version.h" - -// -// CClientTaskBarReceiver -// - -CClientTaskBarReceiver::CClientTaskBarReceiver() : - m_state(kNotRunning) -{ - // do nothing -} - -CClientTaskBarReceiver::~CClientTaskBarReceiver() -{ - // do nothing -} - -void -CClientTaskBarReceiver::updateStatus(CClient* client, const CString& errorMsg) -{ - { - // update our status - m_errorMessage = errorMsg; - if (client == NULL) { - if (m_errorMessage.empty()) { - m_state = kNotRunning; - } - else { - m_state = kNotWorking; - } - } - else { - m_server = client->getServerAddress().getHostname(); - - if (client->isConnected()) { - m_state = kConnected; - } - else if (client->isConnecting()) { - m_state = kConnecting; - } - else { - m_state = kNotConnected; - } - } - - // let subclasses have a go - onStatusChanged(client); - } - - // tell task bar - ARCH->updateReceiver(this); -} - -CClientTaskBarReceiver::EState -CClientTaskBarReceiver::getStatus() const -{ - return m_state; -} - -const CString& -CClientTaskBarReceiver::getErrorMessage() const -{ - return m_errorMessage; -} - -void -CClientTaskBarReceiver::quit() -{ - EVENTQUEUE->addEvent(CEvent(CEvent::kQuit)); -} - -void -CClientTaskBarReceiver::onStatusChanged(CClient*) -{ - // do nothing -} - -void -CClientTaskBarReceiver::lock() const -{ - // do nothing -} - -void -CClientTaskBarReceiver::unlock() const -{ - // do nothing -} - -std::string -CClientTaskBarReceiver::getToolTip() const -{ - switch (m_state) { - case kNotRunning: - return CStringUtil::print("%s: Not running", kAppVersion); - - case kNotWorking: - return CStringUtil::print("%s: %s", - kAppVersion, m_errorMessage.c_str()); - - case kNotConnected: - return CStringUtil::print("%s: Not connected: %s", - kAppVersion, m_errorMessage.c_str()); - - case kConnecting: - return CStringUtil::print("%s: Connecting to %s...", - kAppVersion, m_server.c_str()); - - case kConnected: - return CStringUtil::print("%s: Connected to %s", - kAppVersion, m_server.c_str()); - - default: - return ""; - } -} diff --git a/cmd/synergyc/CClientTaskBarReceiver.h b/cmd/synergyc/CClientTaskBarReceiver.h deleted file mode 100644 index 0e3440e1..00000000 --- a/cmd/synergyc/CClientTaskBarReceiver.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CCLIENTTASKBARRECEIVER_H -#define CCLIENTTASKBARRECEIVER_H - -#include "CString.h" -#include "IArchTaskBarReceiver.h" - -class CClient; - -//! Implementation of IArchTaskBarReceiver for the synergy server -class CClientTaskBarReceiver : public IArchTaskBarReceiver { -public: - CClientTaskBarReceiver(); - virtual ~CClientTaskBarReceiver(); - - //! @name manipulators - //@{ - - //! Update status - /*! - Determine the status and query required information from the client. - */ - void updateStatus(CClient*, const CString& errorMsg); - - //@} - - // IArchTaskBarReceiver overrides - virtual void showStatus() = 0; - virtual void runMenu(int x, int y) = 0; - virtual void primaryAction() = 0; - virtual void lock() const; - virtual void unlock() const; - virtual const Icon getIcon() const = 0; - virtual std::string getToolTip() const; - -protected: - enum EState { - kNotRunning, - kNotWorking, - kNotConnected, - kConnecting, - kConnected, - kMaxState - }; - - //! Get status - EState getStatus() const; - - //! Get error message - const CString& getErrorMessage() const; - - //! Quit app - /*! - Causes the application to quit gracefully - */ - void quit(); - - //! Status change notification - /*! - Called when status changes. The default implementation does nothing. - */ - virtual void onStatusChanged(CClient* client); - -private: - EState m_state; - CString m_errorMessage; - CString m_server; -}; - -#endif diff --git a/cmd/synergyc/CMSWindowsClientTaskBarReceiver.cpp b/cmd/synergyc/CMSWindowsClientTaskBarReceiver.cpp deleted file mode 100644 index c002b9f1..00000000 --- a/cmd/synergyc/CMSWindowsClientTaskBarReceiver.cpp +++ /dev/null @@ -1,346 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CMSWindowsClientTaskBarReceiver.h" -#include "CClient.h" -#include "CMSWindowsClipboard.h" -#include "LogOutputters.h" -#include "BasicTypes.h" -#include "CArch.h" -#include "CArchTaskBarWindows.h" -#include "resource.h" - -// -// CMSWindowsClientTaskBarReceiver -// - -const UINT CMSWindowsClientTaskBarReceiver::s_stateToIconID[kMaxState] = -{ - IDI_TASKBAR_NOT_RUNNING, - IDI_TASKBAR_NOT_WORKING, - IDI_TASKBAR_NOT_CONNECTED, - IDI_TASKBAR_NOT_CONNECTED, - IDI_TASKBAR_CONNECTED -}; - -CMSWindowsClientTaskBarReceiver::CMSWindowsClientTaskBarReceiver( - HINSTANCE appInstance, const CBufferedLogOutputter* logBuffer) : - CClientTaskBarReceiver(), - m_appInstance(appInstance), - m_window(NULL), - m_logBuffer(logBuffer) -{ - for (UInt32 i = 0; i < kMaxState; ++i) { - m_icon[i] = loadIcon(s_stateToIconID[i]); - } - m_menu = LoadMenu(m_appInstance, MAKEINTRESOURCE(IDR_TASKBAR)); - - // don't create the window yet. we'll create it on demand. this - // has the side benefit of being created in the thread used for - // the task bar. that's good because it means the existence of - // the window won't prevent changing the main thread's desktop. - - // add ourself to the task bar - ARCH->addReceiver(this); -} - -CMSWindowsClientTaskBarReceiver::~CMSWindowsClientTaskBarReceiver() -{ - ARCH->removeReceiver(this); - for (UInt32 i = 0; i < kMaxState; ++i) { - deleteIcon(m_icon[i]); - } - DestroyMenu(m_menu); - destroyWindow(); -} - -void -CMSWindowsClientTaskBarReceiver::showStatus() -{ - // create the window - createWindow(); - - // lock self while getting status - lock(); - - // get the current status - std::string status = getToolTip(); - - // done getting status - unlock(); - - // update dialog - HWND child = GetDlgItem(m_window, IDC_TASKBAR_STATUS_STATUS); - SendMessage(child, WM_SETTEXT, 0, (LPARAM)status.c_str()); - - if (!IsWindowVisible(m_window)) { - // position it by the mouse - POINT cursorPos; - GetCursorPos(&cursorPos); - RECT windowRect; - GetWindowRect(m_window, &windowRect); - int x = cursorPos.x; - int y = cursorPos.y; - int fw = GetSystemMetrics(SM_CXDLGFRAME); - int fh = GetSystemMetrics(SM_CYDLGFRAME); - int ww = windowRect.right - windowRect.left; - int wh = windowRect.bottom - windowRect.top; - int sw = GetSystemMetrics(SM_CXFULLSCREEN); - int sh = GetSystemMetrics(SM_CYFULLSCREEN); - if (fw < 1) { - fw = 1; - } - if (fh < 1) { - fh = 1; - } - if (x + ww - fw > sw) { - x -= ww - fw; - } - else { - x -= fw; - } - if (x < 0) { - x = 0; - } - if (y + wh - fh > sh) { - y -= wh - fh; - } - else { - y -= fh; - } - if (y < 0) { - y = 0; - } - SetWindowPos(m_window, HWND_TOPMOST, x, y, ww, wh, - SWP_SHOWWINDOW); - } -} - -void -CMSWindowsClientTaskBarReceiver::runMenu(int x, int y) -{ - // do popup menu. we need a window to pass to TrackPopupMenu(). - // the SetForegroundWindow() and SendMessage() calls around - // TrackPopupMenu() are to get the menu to be dismissed when - // another window gets activated and are just one of those - // win32 weirdnesses. - createWindow(); - SetForegroundWindow(m_window); - HMENU menu = GetSubMenu(m_menu, 0); - SetMenuDefaultItem(menu, IDC_TASKBAR_STATUS, FALSE); - HMENU logLevelMenu = GetSubMenu(menu, 3); - CheckMenuRadioItem(logLevelMenu, 0, 6, - CLOG->getFilter() - CLog::kERROR, MF_BYPOSITION); - int n = TrackPopupMenu(menu, - TPM_NONOTIFY | - TPM_RETURNCMD | - TPM_LEFTBUTTON | - TPM_RIGHTBUTTON, - x, y, 0, m_window, NULL); - SendMessage(m_window, WM_NULL, 0, 0); - - // perform the requested operation - switch (n) { - case IDC_TASKBAR_STATUS: - showStatus(); - break; - - case IDC_TASKBAR_LOG: - copyLog(); - break; - - case IDC_TASKBAR_SHOW_LOG: - ARCH->showConsole(true); - break; - - case IDC_TASKBAR_LOG_LEVEL_ERROR: - CLOG->setFilter(CLog::kERROR); - break; - - case IDC_TASKBAR_LOG_LEVEL_WARNING: - CLOG->setFilter(CLog::kWARNING); - break; - - case IDC_TASKBAR_LOG_LEVEL_NOTE: - CLOG->setFilter(CLog::kNOTE); - break; - - case IDC_TASKBAR_LOG_LEVEL_INFO: - CLOG->setFilter(CLog::kINFO); - break; - - case IDC_TASKBAR_LOG_LEVEL_DEBUG: - CLOG->setFilter(CLog::kDEBUG); - break; - - case IDC_TASKBAR_LOG_LEVEL_DEBUG1: - CLOG->setFilter(CLog::kDEBUG1); - break; - - case IDC_TASKBAR_LOG_LEVEL_DEBUG2: - CLOG->setFilter(CLog::kDEBUG2); - break; - - case IDC_TASKBAR_QUIT: - quit(); - break; - } -} - -void -CMSWindowsClientTaskBarReceiver::primaryAction() -{ - showStatus(); -} - -const IArchTaskBarReceiver::Icon -CMSWindowsClientTaskBarReceiver::getIcon() const -{ - return reinterpret_cast(m_icon[getStatus()]); -} - -void -CMSWindowsClientTaskBarReceiver::copyLog() const -{ - if (m_logBuffer != NULL) { - // collect log buffer - CString data; - for (CBufferedLogOutputter::const_iterator index = m_logBuffer->begin(); - index != m_logBuffer->end(); ++index) { - data += *index; - data += "\n"; - } - - // copy log to clipboard - if (!data.empty()) { - CMSWindowsClipboard clipboard(m_window); - clipboard.open(0); - clipboard.emptyUnowned(); - clipboard.add(IClipboard::kText, data); - clipboard.close(); - } - } -} - -void -CMSWindowsClientTaskBarReceiver::onStatusChanged() -{ - if (IsWindowVisible(m_window)) { - showStatus(); - } -} - -HICON -CMSWindowsClientTaskBarReceiver::loadIcon(UINT id) -{ - HANDLE icon = LoadImage(m_appInstance, - MAKEINTRESOURCE(id), - IMAGE_ICON, - 0, 0, - LR_DEFAULTCOLOR); - return reinterpret_cast(icon); -} - -void -CMSWindowsClientTaskBarReceiver::deleteIcon(HICON icon) -{ - if (icon != NULL) { - DestroyIcon(icon); - } -} - -void -CMSWindowsClientTaskBarReceiver::createWindow() -{ - // ignore if already created - if (m_window != NULL) { - return; - } - - // get the status dialog - m_window = CreateDialogParam(m_appInstance, - MAKEINTRESOURCE(IDD_TASKBAR_STATUS), - NULL, - (DLGPROC)&CMSWindowsClientTaskBarReceiver::staticDlgProc, - reinterpret_cast( - reinterpret_cast(this))); - - // window should appear on top of everything, including (especially) - // the task bar. - LONG_PTR style = GetWindowLongPtr(m_window, GWL_EXSTYLE); - style |= WS_EX_TOOLWINDOW | WS_EX_TOPMOST; - SetWindowLongPtr(m_window, GWL_EXSTYLE, style); - - // tell the task bar about this dialog - CArchTaskBarWindows::addDialog(m_window); -} - -void -CMSWindowsClientTaskBarReceiver::destroyWindow() -{ - if (m_window != NULL) { - CArchTaskBarWindows::removeDialog(m_window); - DestroyWindow(m_window); - m_window = NULL; - } -} - -BOOL -CMSWindowsClientTaskBarReceiver::dlgProc(HWND hwnd, - UINT msg, WPARAM wParam, LPARAM) -{ - switch (msg) { - case WM_INITDIALOG: - // use default focus - return TRUE; - - case WM_ACTIVATE: - // hide when another window is activated - if (LOWORD(wParam) == WA_INACTIVE) { - ShowWindow(hwnd, SW_HIDE); - } - break; - } - return FALSE; -} - -BOOL CALLBACK -CMSWindowsClientTaskBarReceiver::staticDlgProc(HWND hwnd, - UINT msg, WPARAM wParam, LPARAM lParam) -{ - // if msg is WM_INITDIALOG, extract the CMSWindowsClientTaskBarReceiver* - // and put it in the extra window data then forward the call. - CMSWindowsClientTaskBarReceiver* self = NULL; - if (msg == WM_INITDIALOG) { - self = reinterpret_cast( - reinterpret_cast(lParam)); - SetWindowLong(hwnd, GWL_USERDATA, lParam); - } - else { - // get the extra window data and forward the call - LONG data = GetWindowLong(hwnd, GWL_USERDATA); - if (data != 0) { - self = reinterpret_cast( - reinterpret_cast(data)); - } - } - - // forward the message - if (self != NULL) { - return self->dlgProc(hwnd, msg, wParam, lParam); - } - else { - return (msg == WM_INITDIALOG) ? TRUE : FALSE; - } -} diff --git a/cmd/synergyc/CMSWindowsClientTaskBarReceiver.h b/cmd/synergyc/CMSWindowsClientTaskBarReceiver.h deleted file mode 100644 index 72d33be5..00000000 --- a/cmd/synergyc/CMSWindowsClientTaskBarReceiver.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CMSWINDOWSCLIENTTASKBARRECEIVER_H -#define CMSWINDOWSCLIENTTASKBARRECEIVER_H - -#define WIN32_LEAN_AND_MEAN - -#include "CClientTaskBarReceiver.h" -#include - -class CBufferedLogOutputter; - -//! Implementation of CClientTaskBarReceiver for Microsoft Windows -class CMSWindowsClientTaskBarReceiver : public CClientTaskBarReceiver { -public: - CMSWindowsClientTaskBarReceiver(HINSTANCE, const CBufferedLogOutputter*); - virtual ~CMSWindowsClientTaskBarReceiver(); - - // IArchTaskBarReceiver overrides - virtual void showStatus(); - virtual void runMenu(int x, int y); - virtual void primaryAction(); - virtual const Icon getIcon() const; - -protected: - void copyLog() const; - - // CClientTaskBarReceiver overrides - virtual void onStatusChanged(); - -private: - HICON loadIcon(UINT); - void deleteIcon(HICON); - void createWindow(); - void destroyWindow(); - - BOOL dlgProc(HWND hwnd, - UINT msg, WPARAM wParam, LPARAM lParam); - static BOOL CALLBACK - staticDlgProc(HWND hwnd, - UINT msg, WPARAM wParam, LPARAM lParam); - -private: - HINSTANCE m_appInstance; - HWND m_window; - HMENU m_menu; - HICON m_icon[kMaxState]; - const CBufferedLogOutputter* m_logBuffer; - static const UINT s_stateToIconID[]; -}; - -#endif diff --git a/cmd/synergyc/COSXClientTaskBarReceiver.cpp b/cmd/synergyc/COSXClientTaskBarReceiver.cpp deleted file mode 100644 index c380ac4d..00000000 --- a/cmd/synergyc/COSXClientTaskBarReceiver.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "COSXClientTaskBarReceiver.h" -#include "CArch.h" - -// -// COSXClientTaskBarReceiver -// - -COSXClientTaskBarReceiver::COSXClientTaskBarReceiver( - const CBufferedLogOutputter*) -{ - // add ourself to the task bar - ARCH->addReceiver(this); -} - -COSXClientTaskBarReceiver::~COSXClientTaskBarReceiver() -{ - ARCH->removeReceiver(this); -} - -void -COSXClientTaskBarReceiver::showStatus() -{ - // do nothing -} - -void -COSXClientTaskBarReceiver::runMenu(int, int) -{ - // do nothing -} - -void -COSXClientTaskBarReceiver::primaryAction() -{ - // do nothing -} - -const IArchTaskBarReceiver::Icon -COSXClientTaskBarReceiver::getIcon() const -{ - return NULL; -} diff --git a/cmd/synergyc/COSXClientTaskBarReceiver.h b/cmd/synergyc/COSXClientTaskBarReceiver.h deleted file mode 100644 index 59bca97c..00000000 --- a/cmd/synergyc/COSXClientTaskBarReceiver.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef COSXCLIENTTASKBARRECEIVER_H -#define COSXCLIENTTASKBARRECEIVER_H - -#include "CClientTaskBarReceiver.h" - -class CBufferedLogOutputter; - -//! Implementation of CClientTaskBarReceiver for OS X -class COSXClientTaskBarReceiver : public CClientTaskBarReceiver { -public: - COSXClientTaskBarReceiver(const CBufferedLogOutputter*); - virtual ~COSXClientTaskBarReceiver(); - - // IArchTaskBarReceiver overrides - virtual void showStatus(); - virtual void runMenu(int x, int y); - virtual void primaryAction(); - virtual const Icon getIcon() const; -}; - -#endif diff --git a/cmd/synergyc/CXWindowsClientTaskBarReceiver.cpp b/cmd/synergyc/CXWindowsClientTaskBarReceiver.cpp deleted file mode 100644 index 681f9be5..00000000 --- a/cmd/synergyc/CXWindowsClientTaskBarReceiver.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CXWindowsClientTaskBarReceiver.h" -#include "CArch.h" - -// -// CXWindowsClientTaskBarReceiver -// - -CXWindowsClientTaskBarReceiver::CXWindowsClientTaskBarReceiver( - const CBufferedLogOutputter*) -{ - // add ourself to the task bar - ARCH->addReceiver(this); -} - -CXWindowsClientTaskBarReceiver::~CXWindowsClientTaskBarReceiver() -{ - ARCH->removeReceiver(this); -} - -void -CXWindowsClientTaskBarReceiver::showStatus() -{ - // do nothing -} - -void -CXWindowsClientTaskBarReceiver::runMenu(int, int) -{ - // do nothing -} - -void -CXWindowsClientTaskBarReceiver::primaryAction() -{ - // do nothing -} - -const IArchTaskBarReceiver::Icon -CXWindowsClientTaskBarReceiver::getIcon() const -{ - return NULL; -} diff --git a/cmd/synergyc/CXWindowsClientTaskBarReceiver.h b/cmd/synergyc/CXWindowsClientTaskBarReceiver.h deleted file mode 100644 index fa9da471..00000000 --- a/cmd/synergyc/CXWindowsClientTaskBarReceiver.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CXWINDOWSCLIENTTASKBARRECEIVER_H -#define CXWINDOWSCLIENTTASKBARRECEIVER_H - -#include "CClientTaskBarReceiver.h" - -class CBufferedLogOutputter; - -//! Implementation of CClientTaskBarReceiver for X Windows -class CXWindowsClientTaskBarReceiver : public CClientTaskBarReceiver { -public: - CXWindowsClientTaskBarReceiver(const CBufferedLogOutputter*); - virtual ~CXWindowsClientTaskBarReceiver(); - - // IArchTaskBarReceiver overrides - virtual void showStatus(); - virtual void runMenu(int x, int y); - virtual void primaryAction(); - virtual const Icon getIcon() const; -}; - -#endif diff --git a/cmd/synergyc/Makefile.am b/cmd/synergyc/Makefile.am deleted file mode 100644 index b6e8c83d..00000000 --- a/cmd/synergyc/Makefile.am +++ /dev/null @@ -1,98 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2002 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -## Process this file with automake to produce Makefile.in -NULL = - -COMMON_SOURCE_FILES = \ - CClientTaskBarReceiver.cpp \ - CClientTaskBarReceiver.h \ - synergyc.cpp \ - $(NULL) -XWINDOWS_SOURCE_FILES = \ - CXWindowsClientTaskBarReceiver.cpp \ - CXWindowsClientTaskBarReceiver.h \ - $(NULL) -MSWINDOWS_SOURCE_FILES = \ - CMSWindowsClientTaskBarReceiver.cpp \ - CMSWindowsClientTaskBarReceiver.h \ - resource.h \ - synergyc.rc \ - $(NULL) -CARBON_SOURCE_FILES = \ - COSXClientTaskBarReceiver.cpp \ - COSXClientTaskBarReceiver.h \ - $(NULL) - -EXTRA_DIST = \ - Makefile.win \ - synergyc.ico \ - tb_error.ico \ - tb_idle.ico \ - tb_run.ico \ - tb_wait.ico \ - $(XWINDOWS_SOURCE_FILES) \ - $(MSWINDOWS_SOURCE_FILES) \ - $(CARBON_SOURCE_FILES) \ - $(NULL) - -MAINTAINERCLEANFILES = \ - Makefile.in \ - $(NULL) - -bin_PROGRAMS = synergyc -if XWINDOWS -synergyc_SOURCES = \ - $(COMMON_SOURCE_FILES) \ - $(XWINDOWS_SOURCE_FILES) \ - $(NULL) -endif -if MSWINDOWS -synergyc_SOURCES = \ - $(COMMON_SOURCE_FILES) \ - $(MSWINDOWS_SOURCE_FILES) \ - $(NULL) -endif -if CARBON -synergyc_SOURCES = \ - $(COMMON_SOURCE_FILES) \ - $(CARBON_SOURCE_FILES) \ - $(NULL) -synergyc_LDFLAGS = \ - -framework ScreenSaver \ - -framework IOKit \ - -framework ApplicationServices \ - -framework Foundation \ - $(NULL) -endif -synergyc_LDADD = \ - $(top_builddir)/lib/client/libclient.a \ - $(top_builddir)/lib/platform/libplatform.a \ - $(top_builddir)/lib/synergy/libsynergy.a \ - $(top_builddir)/lib/net/libnet.a \ - $(top_builddir)/lib/io/libio.a \ - $(top_builddir)/lib/mt/libmt.a \ - $(top_builddir)/lib/base/libbase.a \ - $(top_builddir)/lib/common/libcommon.a \ - $(top_builddir)/lib/arch/libarch.a \ - $(NULL) -INCLUDES = \ - -I$(top_srcdir)/lib/common \ - -I$(top_srcdir)/lib/arch \ - -I$(top_srcdir)/lib/base \ - -I$(top_srcdir)/lib/mt \ - -I$(top_srcdir)/lib/io \ - -I$(top_srcdir)/lib/net \ - -I$(top_srcdir)/lib/synergy \ - -I$(top_srcdir)/lib/platform \ - -I$(top_srcdir)/lib/client \ - $(NULL) diff --git a/cmd/synergyc/Makefile.win b/cmd/synergyc/Makefile.win deleted file mode 100644 index 29f2e516..00000000 --- a/cmd/synergyc/Makefile.win +++ /dev/null @@ -1,89 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2007 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -BIN_SYNERGYC_SRC = cmd\synergyc -BIN_SYNERGYC_DST = $(BUILD_DST)\$(BIN_SYNERGYC_SRC) -BIN_SYNERGYC_EXE = "$(BUILD_DST)\synergyc.exe" -BIN_SYNERGYC_CPP = \ - "CClientTaskBarReceiver.cpp" \ - "CMSWindowsClientTaskBarReceiver.cpp" \ - "synergyc.cpp" \ - $(NULL) -BIN_SYNERGYC_OBJ = \ - "$(BIN_SYNERGYC_DST)\CClientTaskBarReceiver.obj" \ - "$(BIN_SYNERGYC_DST)\CMSWindowsClientTaskBarReceiver.obj" \ - "$(BIN_SYNERGYC_DST)\synergyc.obj" \ - $(NULL) -BIN_SYNERGYC_RC = "$(BIN_SYNERGYC_SRC)\synergyc.rc" -BIN_SYNERGYC_RES = "$(BIN_SYNERGYC_DST)\synergyc.res" -BIN_SYNERGYC_INC = \ - /I"lib\common" \ - /I"lib\arch" \ - /I"lib\base" \ - /I"lib\mt" \ - /I"lib\io" \ - /I"lib\net" \ - /I"lib\synergy" \ - /I"lib\platform" \ - /I"lib\client" \ - $(NULL) -BIN_SYNERGYC_LIB = \ - $(LIB_CLIENT_LIB) \ - $(LIB_PLATFORM_LIB) \ - $(LIB_SYNERGY_LIB) \ - $(LIB_NET_LIB) \ - $(LIB_IO_LIB) \ - $(LIB_MT_LIB) \ - $(LIB_BASE_LIB) \ - $(LIB_ARCH_LIB) \ - $(LIB_COMMON_LIB) \ - $(NULL) - -CPP_FILES = $(CPP_FILES) $(BIN_SYNERGYC_CPP) -OBJ_FILES = $(OBJ_FILES) $(BIN_SYNERGYC_OBJ) -PROGRAMS = $(PROGRAMS) $(BIN_SYNERGYC_EXE) - -# Need shell functions. -guilibs = $(guilibs) shell32.lib - -# Dependency rules -$(BIN_SYNERGYC_OBJ): $(AUTODEP) -!if EXIST($(BIN_SYNERGYC_DST)\deps.mak) -!include $(BIN_SYNERGYC_DST)\deps.mak -!endif - -# Build rules. Use batch-mode rules if possible. -!if DEFINED(_NMAKE_VER) -{$(BIN_SYNERGYC_SRC)\}.cpp{$(BIN_SYNERGYC_DST)\}.obj:: -!else -{$(BIN_SYNERGYC_SRC)\}.cpp{$(BIN_SYNERGYC_DST)\}.obj: -!endif - @$(ECHO) Compile in $(BIN_SYNERGYC_SRC) - -@$(MKDIR) $(BIN_SYNERGYC_DST) 2>NUL: - $(cpp) $(cppdebug) $(cppflags) $(cppvarsmt) /showIncludes \ - $(BIN_SYNERGYC_INC) \ - /Fo$(BIN_SYNERGYC_DST)\ \ - /Fd$(BIN_SYNERGYC_DST)\src.pdb \ - $< | $(AUTODEP) $(BIN_SYNERGYC_SRC) $(BIN_SYNERGYC_DST) -$(BIN_SYNERGYC_RES): $(BIN_SYNERGYC_RC) - @$(ECHO) Compile $(**F) - -@$(MKDIR) $(BIN_SYNERGYC_DST) 2>NUL: - $(rc) $(rcflags) $(rcvars) \ - /fo$@ \ - $** -$(BIN_SYNERGYC_EXE): $(BIN_SYNERGYC_OBJ) $(BIN_SYNERGYC_RES) $(BIN_SYNERGYC_LIB) - @$(ECHO) Link $(@F) - $(link) $(ldebug) $(guilflags) $(guilibsmt) \ - /out:$@ \ - $** - $(AUTODEP) $(BIN_SYNERGYC_SRC) $(BIN_SYNERGYC_DST) \ - $(BIN_SYNERGYC_OBJ:.obj=.d) diff --git a/cmd/synergyc/resource.h b/cmd/synergyc/resource.h deleted file mode 100644 index eeee6e1e..00000000 --- a/cmd/synergyc/resource.h +++ /dev/null @@ -1,37 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by synergyc.rc -// -#define IDS_FAILED 1 -#define IDS_INIT_FAILED 2 -#define IDS_UNCAUGHT_EXCEPTION 3 -#define IDI_SYNERGY 101 -#define IDI_TASKBAR_NOT_RUNNING 102 -#define IDI_TASKBAR_NOT_WORKING 103 -#define IDI_TASKBAR_NOT_CONNECTED 104 -#define IDI_TASKBAR_CONNECTED 105 -#define IDR_TASKBAR 107 -#define IDD_TASKBAR_STATUS 108 -#define IDC_TASKBAR_STATUS_STATUS 1000 -#define IDC_TASKBAR_QUIT 40001 -#define IDC_TASKBAR_STATUS 40002 -#define IDC_TASKBAR_LOG 40003 -#define IDC_TASKBAR_SHOW_LOG 40004 -#define IDC_TASKBAR_LOG_LEVEL_ERROR 40009 -#define IDC_TASKBAR_LOG_LEVEL_WARNING 40010 -#define IDC_TASKBAR_LOG_LEVEL_NOTE 40011 -#define IDC_TASKBAR_LOG_LEVEL_INFO 40012 -#define IDC_TASKBAR_LOG_LEVEL_DEBUG 40013 -#define IDC_TASKBAR_LOG_LEVEL_DEBUG1 40014 -#define IDC_TASKBAR_LOG_LEVEL_DEBUG2 40015 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 109 -#define _APS_NEXT_COMMAND_VALUE 40016 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/cmd/synergyc/synergyc.cpp b/cmd/synergyc/synergyc.cpp deleted file mode 100644 index 1a230f0d..00000000 --- a/cmd/synergyc/synergyc.cpp +++ /dev/null @@ -1,910 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CClient.h" -#include "CScreen.h" -#include "ProtocolTypes.h" -#include "Version.h" -#include "XScreen.h" -#include "CNetworkAddress.h" -#include "CSocketMultiplexer.h" -#include "CTCPSocketFactory.h" -#include "XSocket.h" -#include "CThread.h" -#include "CEventQueue.h" -#include "CFunctionEventJob.h" -#include "CFunctionJob.h" -#include "CLog.h" -#include "CString.h" -#include "CStringUtil.h" -#include "LogOutputters.h" -#include "CArch.h" -#include "XArch.h" -#include - -#define DAEMON_RUNNING(running_) -#if WINAPI_MSWINDOWS -#include "CArchMiscWindows.h" -#include "CMSWindowsScreen.h" -#include "CMSWindowsUtil.h" -#include "CMSWindowsClientTaskBarReceiver.h" -#include "resource.h" -#undef DAEMON_RUNNING -#define DAEMON_RUNNING(running_) CArchMiscWindows::daemonRunning(running_) -#elif WINAPI_XWINDOWS -#include "CXWindowsScreen.h" -#include "CXWindowsClientTaskBarReceiver.h" -#elif WINAPI_CARBON -#include "COSXScreen.h" -#include "COSXClientTaskBarReceiver.h" -#endif - -// platform dependent name of a daemon -#if SYSAPI_WIN32 -#define DAEMON_NAME "Synergy Client" -#elif SYSAPI_UNIX -#define DAEMON_NAME "synergyc" -#endif - -typedef int (*StartupFunc)(int, char**); -static bool startClient(); -static void parse(int argc, const char* const* argv); - -// -// program arguments -// - -#define ARG CArgs::s_instance - -class CArgs { -public: - CArgs() : - m_pname(NULL), - m_backend(false), - m_restartable(true), - m_daemon(true), - m_logFilter(NULL), - m_display(NULL), - m_serverAddress(NULL) - { s_instance = this; } - ~CArgs() { s_instance = NULL; } - -public: - static CArgs* s_instance; - const char* m_pname; - bool m_backend; - bool m_restartable; - bool m_daemon; - const char* m_logFilter; - const char* m_display; - CString m_name; - CNetworkAddress* m_serverAddress; -}; - -CArgs* CArgs::s_instance = NULL; - - -// -// platform dependent factories -// - -static -CScreen* -createScreen() -{ -#if WINAPI_MSWINDOWS - return new CScreen(new CMSWindowsScreen(false)); -#elif WINAPI_XWINDOWS - return new CScreen(new CXWindowsScreen(ARG->m_display, false)); -#elif WINAPI_CARBON - return new CScreen(new COSXScreen(false)); -#endif -} - -static -CClientTaskBarReceiver* -createTaskBarReceiver(const CBufferedLogOutputter* logBuffer) -{ -#if WINAPI_MSWINDOWS - return new CMSWindowsClientTaskBarReceiver( - CMSWindowsScreen::getInstance(), logBuffer); -#elif WINAPI_XWINDOWS - return new CXWindowsClientTaskBarReceiver(logBuffer); -#elif WINAPI_CARBON - return new COSXClientTaskBarReceiver(logBuffer); -#endif -} - - -// -// platform independent main -// - -static CClient* s_client = NULL; -static CScreen* s_clientScreen = NULL; -static CClientTaskBarReceiver* s_taskBarReceiver = NULL; -static double s_retryTime = 0.0; -static bool s_suspened = false; - -static -void -updateStatus() -{ - s_taskBarReceiver->updateStatus(s_client, ""); -} - -static -void -updateStatus(const CString& msg) -{ - s_taskBarReceiver->updateStatus(s_client, msg); -} - -static -void -resetRestartTimeout() -{ - s_retryTime = 0.0; -} - -static -double -nextRestartTimeout() -{ - // choose next restart timeout. we start with rapid retries - // then slow down. - if (s_retryTime < 1.0) { - s_retryTime = 1.0; - } - else if (s_retryTime < 3.0) { - s_retryTime = 3.0; - } - else if (s_retryTime < 5.0) { - s_retryTime = 5.0; - } - else if (s_retryTime < 15.0) { - s_retryTime = 15.0; - } - else if (s_retryTime < 30.0) { - s_retryTime = 30.0; - } - else { - s_retryTime = 60.0; - } - return s_retryTime; -} - -static -void -handleScreenError(const CEvent&, void*) -{ - LOG((CLOG_CRIT "error on screen")); - EVENTQUEUE->addEvent(CEvent(CEvent::kQuit)); -} - -static -CScreen* -openClientScreen() -{ - CScreen* screen = createScreen(); - EVENTQUEUE->adoptHandler(IScreen::getErrorEvent(), - screen->getEventTarget(), - new CFunctionEventJob( - &handleScreenError)); - return screen; -} - -static -void -closeClientScreen(CScreen* screen) -{ - if (screen != NULL) { - EVENTQUEUE->removeHandler(IScreen::getErrorEvent(), - screen->getEventTarget()); - delete screen; - } -} - -static -void -handleClientRestart(const CEvent&, void* vtimer) -{ - // discard old timer - CEventQueueTimer* timer = reinterpret_cast(vtimer); - EVENTQUEUE->deleteTimer(timer); - EVENTQUEUE->removeHandler(CEvent::kTimer, timer); - - // reconnect - startClient(); -} - -static -void -scheduleClientRestart(double retryTime) -{ - // install a timer and handler to retry later - LOG((CLOG_DEBUG "retry in %.0f seconds", retryTime)); - CEventQueueTimer* timer = EVENTQUEUE->newOneShotTimer(retryTime, NULL); - EVENTQUEUE->adoptHandler(CEvent::kTimer, timer, - new CFunctionEventJob(&handleClientRestart, timer)); -} - -static -void -handleClientConnected(const CEvent&, void*) -{ - LOG((CLOG_NOTE "connected to server")); - resetRestartTimeout(); - updateStatus(); -} - -static -void -handleClientFailed(const CEvent& e, void*) -{ - CClient::CFailInfo* info = - reinterpret_cast(e.getData()); - - updateStatus(CString("Failed to connect to server: ") + info->m_what); - if (!ARG->m_restartable || !info->m_retry) { - LOG((CLOG_ERR "failed to connect to server: %s", info->m_what)); - EVENTQUEUE->addEvent(CEvent(CEvent::kQuit)); - } - else { - LOG((CLOG_WARN "failed to connect to server: %s", info->m_what)); - if (!s_suspened) { - scheduleClientRestart(nextRestartTimeout()); - } - } -} - -static -void -handleClientDisconnected(const CEvent&, void*) -{ - LOG((CLOG_NOTE "disconnected from server")); - if (!ARG->m_restartable) { - EVENTQUEUE->addEvent(CEvent(CEvent::kQuit)); - } - else if (!s_suspened) { - s_client->connect(); - } - updateStatus(); -} - -static -CClient* -openClient(const CString& name, const CNetworkAddress& address, CScreen* screen) -{ - CClient* client = new CClient(name, address, - new CTCPSocketFactory, NULL, screen); - EVENTQUEUE->adoptHandler(CClient::getConnectedEvent(), - client->getEventTarget(), - new CFunctionEventJob(handleClientConnected)); - EVENTQUEUE->adoptHandler(CClient::getConnectionFailedEvent(), - client->getEventTarget(), - new CFunctionEventJob(handleClientFailed)); - EVENTQUEUE->adoptHandler(CClient::getDisconnectedEvent(), - client->getEventTarget(), - new CFunctionEventJob(handleClientDisconnected)); - return client; -} - -static -void -closeClient(CClient* client) -{ - if (client == NULL) { - return; - } - - EVENTQUEUE->removeHandler(CClient::getConnectedEvent(), client); - EVENTQUEUE->removeHandler(CClient::getConnectionFailedEvent(), client); - EVENTQUEUE->removeHandler(CClient::getDisconnectedEvent(), client); - delete client; -} - -static -bool -startClient() -{ - double retryTime; - CScreen* clientScreen = NULL; - try { - if (s_clientScreen == NULL) { - clientScreen = openClientScreen(); - s_client = openClient(ARG->m_name, - *ARG->m_serverAddress, clientScreen); - s_clientScreen = clientScreen; - LOG((CLOG_NOTE "started client")); - } - s_client->connect(); - updateStatus(); - return true; - } - catch (XScreenUnavailable& e) { - LOG((CLOG_WARN "cannot open secondary screen: %s", e.what())); - closeClientScreen(clientScreen); - updateStatus(CString("Cannot open secondary screen: ") + e.what()); - retryTime = e.getRetryTime(); - } - catch (XScreenOpenFailure& e) { - LOG((CLOG_CRIT "cannot open secondary screen: %s", e.what())); - closeClientScreen(clientScreen); - return false; - } - catch (XBase& e) { - LOG((CLOG_CRIT "failed to start client: %s", e.what())); - closeClientScreen(clientScreen); - return false; - } - - if (ARG->m_restartable) { - scheduleClientRestart(retryTime); - return true; - } - else { - // don't try again - return false; - } -} - -static -void -stopClient() -{ - closeClient(s_client); - closeClientScreen(s_clientScreen); - s_client = NULL; - s_clientScreen = NULL; -} - -static -int -mainLoop() -{ - // create socket multiplexer. this must happen after daemonization - // on unix because threads evaporate across a fork(). - CSocketMultiplexer multiplexer; - - // create the event queue - CEventQueue eventQueue; - - // start the client. if this return false then we've failed and - // we shouldn't retry. - LOG((CLOG_DEBUG1 "starting client")); - if (!startClient()) { - return kExitFailed; - } - - // run event loop. if startClient() failed we're supposed to retry - // later. the timer installed by startClient() will take care of - // that. - CEvent event; - DAEMON_RUNNING(true); - EVENTQUEUE->getEvent(event); - while (event.getType() != CEvent::kQuit) { - EVENTQUEUE->dispatchEvent(event); - CEvent::deleteData(event); - EVENTQUEUE->getEvent(event); - } - DAEMON_RUNNING(false); - - // close down - LOG((CLOG_DEBUG1 "stopping client")); - stopClient(); - updateStatus(); - LOG((CLOG_NOTE "stopped client")); - - return kExitSuccess; -} - -static -int -daemonMainLoop(int, const char**) -{ -#if SYSAPI_WIN32 - CSystemLogger sysLogger(DAEMON_NAME, false); -#else - CSystemLogger sysLogger(DAEMON_NAME, true); -#endif - return mainLoop(); -} - -static -int -standardStartup(int argc, char** argv) -{ - if (!ARG->m_daemon) { - ARCH->showConsole(false); - } - - // parse command line - parse(argc, argv); - - // daemonize if requested - if (ARG->m_daemon) { - return ARCH->daemonize(DAEMON_NAME, &daemonMainLoop); - } - else { - return mainLoop(); - } -} - -static -int -run(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup) -{ - // general initialization - ARG->m_serverAddress = new CNetworkAddress; - ARG->m_pname = ARCH->getBasename(argv[0]); - - // install caller's output filter - if (outputter != NULL) { - CLOG->insert(outputter); - } - - // save log messages - CBufferedLogOutputter logBuffer(1000); - CLOG->insert(&logBuffer, true); - - // make the task bar receiver. the user can control this app - // through the task bar. - s_taskBarReceiver = createTaskBarReceiver(&logBuffer); - - // run - int result = startup(argc, argv); - - // done with task bar receiver - delete s_taskBarReceiver; - - // done with log buffer - CLOG->remove(&logBuffer); - - delete ARG->m_serverAddress; - return result; -} - - -// -// command line parsing -// - -#define BYE "\nTry `%s --help' for more information." - -static void (*bye)(int) = &exit; - -static -void -version() -{ - LOG((CLOG_PRINT "%s %s, protocol version %d.%d\n%s", - ARG->m_pname, - kVersion, - kProtocolMajorVersion, - kProtocolMinorVersion, - kCopyright)); -} - -static -void -help() -{ -#if WINAPI_XWINDOWS -# define USAGE_DISPLAY_ARG \ -" [--display ]" -# define USAGE_DISPLAY_INFO \ -" --display connect to the X server at \n" -#else -# define USAGE_DISPLAY_ARG -# define USAGE_DISPLAY_INFO -#endif - - LOG((CLOG_PRINT -"Usage: %s" -" [--daemon|--no-daemon]" -" [--debug ]" -USAGE_DISPLAY_ARG -" [--name ]" -" [--restart|--no-restart]" -" " -"\n\n" -"Start the synergy mouse/keyboard sharing server.\n" -"\n" -" -d, --debug filter out log messages with priorty below level.\n" -" level may be: FATAL, ERROR, WARNING, NOTE, INFO,\n" -" DEBUG, DEBUG1, DEBUG2.\n" -USAGE_DISPLAY_INFO -" -f, --no-daemon run the client in the foreground.\n" -"* --daemon run the client as a daemon.\n" -" -n, --name use screen-name instead the hostname to identify\n" -" ourself to the server.\n" -" -1, --no-restart do not try to restart the client if it fails for\n" -" some reason.\n" -"* --restart restart the client automatically if it fails.\n" -" -h, --help display this help and exit.\n" -" --version display version information and exit.\n" -"\n" -"* marks defaults.\n" -"\n" -"The server address is of the form: [][:]. The hostname\n" -"must be the address or hostname of the server. The port overrides the\n" -"default port, %d.\n" -"\n" -"Where log messages go depends on the platform and whether or not the\n" -"client is running as a daemon.", - ARG->m_pname, kDefaultPort)); - -} - -static -bool -isArg(int argi, int argc, const char* const* argv, - const char* name1, const char* name2, - int minRequiredParameters = 0) -{ - if ((name1 != NULL && strcmp(argv[argi], name1) == 0) || - (name2 != NULL && strcmp(argv[argi], name2) == 0)) { - // match. check args left. - if (argi + minRequiredParameters >= argc) { - LOG((CLOG_PRINT "%s: missing arguments for `%s'" BYE, - ARG->m_pname, argv[argi], ARG->m_pname)); - bye(kExitArgs); - } - return true; - } - - // no match - return false; -} - -static -void -parse(int argc, const char* const* argv) -{ - assert(ARG->m_pname != NULL); - assert(argv != NULL); - assert(argc >= 1); - - // set defaults - ARG->m_name = ARCH->getHostName(); - - // parse options - int i; - for (i = 1; i < argc; ++i) { - if (isArg(i, argc, argv, "-d", "--debug", 1)) { - // change logging level - ARG->m_logFilter = argv[++i]; - } - - else if (isArg(i, argc, argv, "-n", "--name", 1)) { - // save screen name - ARG->m_name = argv[++i]; - } - - else if (isArg(i, argc, argv, NULL, "--camp")) { - // ignore -- included for backwards compatibility - } - - else if (isArg(i, argc, argv, NULL, "--no-camp")) { - // ignore -- included for backwards compatibility - } - - else if (isArg(i, argc, argv, "-f", "--no-daemon")) { - // not a daemon - ARG->m_daemon = false; - } - - else if (isArg(i, argc, argv, NULL, "--daemon")) { - // daemonize - ARG->m_daemon = true; - } - -#if WINAPI_XWINDOWS - else if (isArg(i, argc, argv, "-display", "--display", 1)) { - // use alternative display - ARG->m_display = argv[++i]; - } -#endif - - else if (isArg(i, argc, argv, "-1", "--no-restart")) { - // don't try to restart - ARG->m_restartable = false; - } - - else if (isArg(i, argc, argv, NULL, "--restart")) { - // try to restart - ARG->m_restartable = true; - } - - else if (isArg(i, argc, argv, "-z", NULL)) { - ARG->m_backend = true; - } - - else if (isArg(i, argc, argv, "-h", "--help")) { - help(); - bye(kExitSuccess); - } - - else if (isArg(i, argc, argv, NULL, "--version")) { - version(); - bye(kExitSuccess); - } - - else if (isArg(i, argc, argv, "--", NULL)) { - // remaining arguments are not options - ++i; - break; - } - - else if (argv[i][0] == '-') { - LOG((CLOG_PRINT "%s: unrecognized option `%s'" BYE, - ARG->m_pname, argv[i], ARG->m_pname)); - bye(kExitArgs); - } - - else { - // this and remaining arguments are not options - break; - } - } - - // exactly one non-option argument (server-address) - if (i == argc) { - LOG((CLOG_PRINT "%s: a server address or name is required" BYE, - ARG->m_pname, ARG->m_pname)); - bye(kExitArgs); - } - if (i + 1 != argc) { - LOG((CLOG_PRINT "%s: unrecognized option `%s'" BYE, - ARG->m_pname, argv[i], ARG->m_pname)); - bye(kExitArgs); - } - - // save server address - try { - *ARG->m_serverAddress = CNetworkAddress(argv[i], kDefaultPort); - ARG->m_serverAddress->resolve(); - } - catch (XSocketAddress& e) { - // allow an address that we can't look up if we're restartable. - // we'll try to resolve the address each time we connect to the - // server. a bad port will never get better. patch by Brent - // Priddy. - if (!ARG->m_restartable || e.getError() == XSocketAddress::kBadPort) { - LOG((CLOG_PRINT "%s: %s" BYE, - ARG->m_pname, e.what(), ARG->m_pname)); - bye(kExitFailed); - } - } - - // increase default filter level for daemon. the user must - // explicitly request another level for a daemon. - if (ARG->m_daemon && ARG->m_logFilter == NULL) { -#if SYSAPI_WIN32 - if (CArchMiscWindows::isWindows95Family()) { - // windows 95 has no place for logging so avoid showing - // the log console window. - ARG->m_logFilter = "FATAL"; - } - else -#endif - { - ARG->m_logFilter = "NOTE"; - } - } - - // set log filter - if (!CLOG->setFilter(ARG->m_logFilter)) { - LOG((CLOG_PRINT "%s: unrecognized log level `%s'" BYE, - ARG->m_pname, ARG->m_logFilter, ARG->m_pname)); - bye(kExitArgs); - } - - // identify system - LOG((CLOG_INFO "Synergy client %s on %s", kVersion, ARCH->getOSName().c_str())); -} - - -// -// platform dependent entry points -// - -#if SYSAPI_WIN32 - -static bool s_hasImportantLogMessages = false; - -// -// CMessageBoxOutputter -// -// This class writes severe log messages to a message box -// - -class CMessageBoxOutputter : public ILogOutputter { -public: - CMessageBoxOutputter() { } - virtual ~CMessageBoxOutputter() { } - - // ILogOutputter overrides - virtual void open(const char*) { } - virtual void close() { } - virtual void show(bool) { } - virtual bool write(ELevel level, const char* message); - virtual const char* getNewline() const { return ""; } -}; - -bool -CMessageBoxOutputter::write(ELevel level, const char* message) -{ - // note any important messages the user may need to know about - if (level <= CLog::kWARNING) { - s_hasImportantLogMessages = true; - } - - // FATAL and PRINT messages get a dialog box if not running as - // backend. if we're running as a backend the user will have - // a chance to see the messages when we exit. - if (!ARG->m_backend && level <= CLog::kFATAL) { - MessageBox(NULL, message, ARG->m_pname, MB_OK | MB_ICONWARNING); - return false; - } - else { - return true; - } -} - -static -void -byeThrow(int x) -{ - CArchMiscWindows::daemonFailed(x); -} - -static -int -daemonNTMainLoop(int argc, const char** argv) -{ - parse(argc, argv); - ARG->m_backend = false; - return CArchMiscWindows::runDaemon(mainLoop); -} - -static -int -daemonNTStartup(int, char**) -{ - CSystemLogger sysLogger(DAEMON_NAME, false); - bye = &byeThrow; - return ARCH->daemonize(DAEMON_NAME, &daemonNTMainLoop); -} - -static -int -foregroundStartup(int argc, char** argv) -{ - ARCH->showConsole(false); - - // parse command line - parse(argc, argv); - - // never daemonize - return mainLoop(); -} - -static -void -showError(HINSTANCE instance, const char* title, UINT id, const char* arg) -{ - CString fmt = CMSWindowsUtil::getString(instance, id); - CString msg = CStringUtil::format(fmt.c_str(), arg); - MessageBox(NULL, msg.c_str(), title, MB_OK | MB_ICONWARNING); -} - -int WINAPI -WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int) -{ - try { - CArchMiscWindows::setIcons((HICON)LoadImage(instance, - MAKEINTRESOURCE(IDI_SYNERGY), - IMAGE_ICON, - 32, 32, LR_SHARED), - (HICON)LoadImage(instance, - MAKEINTRESOURCE(IDI_SYNERGY), - IMAGE_ICON, - 16, 16, LR_SHARED)); - CArch arch(instance); - CMSWindowsScreen::init(instance); - CLOG; - CThread::getCurrentThread().setPriority(-14); - CArgs args; - - // set title on log window - ARCH->openConsole((CString(kAppVersion) + " " + "Client").c_str()); - - // windows NT family starts services using no command line options. - // since i'm not sure how to tell the difference between that and - // a user providing no options we'll assume that if there are no - // arguments and we're on NT then we're being invoked as a service. - // users on NT can use `--daemon' or `--no-daemon' to force us out - // of the service code path. - StartupFunc startup = &standardStartup; - if (!CArchMiscWindows::isWindows95Family()) { - if (__argc <= 1) { - startup = &daemonNTStartup; - } - else { - startup = &foregroundStartup; - } - } - - // send PRINT and FATAL output to a message box - int result = run(__argc, __argv, new CMessageBoxOutputter, startup); - - // let user examine any messages if we're running as a backend - // by putting up a dialog box before exiting. - if (args.m_backend && s_hasImportantLogMessages) { - showError(instance, args.m_pname, IDS_FAILED, ""); - } - - delete CLOG; - return result; - } - catch (XBase& e) { - showError(instance, __argv[0], IDS_UNCAUGHT_EXCEPTION, e.what()); - //throw; - } - catch (XArch& e) { - showError(instance, __argv[0], IDS_INIT_FAILED, e.what().c_str()); - } - catch (...) { - showError(instance, __argv[0], IDS_UNCAUGHT_EXCEPTION, ""); - //throw; - } - return kExitFailed; -} - -#elif SYSAPI_UNIX - -int -main(int argc, char** argv) -{ - CArgs args; - try { - int result; - CArch arch; - CLOG; - CArgs args; - result = run(argc, argv, NULL, &standardStartup); - delete CLOG; - return result; - } - catch (XBase& e) { - LOG((CLOG_CRIT "Uncaught exception: %s\n", e.what())); - throw; - } - catch (XArch& e) { - LOG((CLOG_CRIT "Initialization failed: %s" BYE, e.what().c_str())); - return kExitFailed; - } - catch (...) { - LOG((CLOG_CRIT "Uncaught exception: \n")); - throw; - } -} - -#else - -#error no main() for platform - -#endif diff --git a/cmd/synergyc/synergyc.ico b/cmd/synergyc/synergyc.ico deleted file mode 100644 index 89f965f4..00000000 Binary files a/cmd/synergyc/synergyc.ico and /dev/null differ diff --git a/cmd/synergyc/synergyc.rc b/cmd/synergyc/synergyc.rc deleted file mode 100644 index 7f2a5dc1..00000000 --- a/cmd/synergyc/synergyc.rc +++ /dev/null @@ -1,141 +0,0 @@ -//Microsoft Developer Studio generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include -#if !defined(IDC_STATIC) -#define IDC_STATIC (-1) -#endif - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE DISCARDABLE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE DISCARDABLE -BEGIN - "#include \r\n" - "\0" -END - -3 TEXTINCLUDE DISCARDABLE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_SYNERGY ICON DISCARDABLE "synergyc.ico" -IDI_TASKBAR_NOT_RUNNING ICON DISCARDABLE "tb_idle.ico" -IDI_TASKBAR_NOT_WORKING ICON DISCARDABLE "tb_error.ico" -IDI_TASKBAR_NOT_CONNECTED ICON DISCARDABLE "tb_wait.ico" -IDI_TASKBAR_CONNECTED ICON DISCARDABLE "tb_run.ico" - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_TASKBAR_STATUS DIALOG DISCARDABLE 0, 0, 145, 18 -STYLE DS_MODALFRAME | WS_POPUP -FONT 8, "MS Sans Serif" -BEGIN - EDITTEXT IDC_TASKBAR_STATUS_STATUS,3,3,139,12,ES_AUTOHSCROLL | - ES_READONLY | NOT WS_BORDER -END - - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -IDR_TASKBAR MENU DISCARDABLE -BEGIN - POPUP "Synergy" - BEGIN - MENUITEM "Show Status", IDC_TASKBAR_STATUS - MENUITEM "Show Log", IDC_TASKBAR_SHOW_LOG - MENUITEM "Copy Log To Clipboard", IDC_TASKBAR_LOG - POPUP "Set Log Level" - BEGIN - MENUITEM "Error", IDC_TASKBAR_LOG_LEVEL_ERROR - - MENUITEM "Warning", IDC_TASKBAR_LOG_LEVEL_WARNING - - MENUITEM "Note", IDC_TASKBAR_LOG_LEVEL_NOTE - - MENUITEM "Info", IDC_TASKBAR_LOG_LEVEL_INFO - - MENUITEM "Debug", IDC_TASKBAR_LOG_LEVEL_DEBUG - - MENUITEM "Debug1", IDC_TASKBAR_LOG_LEVEL_DEBUG1 - - MENUITEM "Debug2", IDC_TASKBAR_LOG_LEVEL_DEBUG2 - - END - MENUITEM SEPARATOR - MENUITEM "Quit", IDC_TASKBAR_QUIT - END -END - - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -STRINGTABLE DISCARDABLE -BEGIN - IDS_FAILED "Synergy is about to quit with errors or warnings. Please check the log then click OK." - IDS_INIT_FAILED "Synergy failed to initialize: %{1}" - IDS_UNCAUGHT_EXCEPTION "Uncaught exception: %{1}" -END - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/cmd/synergyc/tb_error.ico b/cmd/synergyc/tb_error.ico deleted file mode 100644 index 746a87c9..00000000 Binary files a/cmd/synergyc/tb_error.ico and /dev/null differ diff --git a/cmd/synergyc/tb_idle.ico b/cmd/synergyc/tb_idle.ico deleted file mode 100644 index 4e13a264..00000000 Binary files a/cmd/synergyc/tb_idle.ico and /dev/null differ diff --git a/cmd/synergyc/tb_run.ico b/cmd/synergyc/tb_run.ico deleted file mode 100644 index 88e160cb..00000000 Binary files a/cmd/synergyc/tb_run.ico and /dev/null differ diff --git a/cmd/synergyc/tb_wait.ico b/cmd/synergyc/tb_wait.ico deleted file mode 100644 index 257be0a1..00000000 Binary files a/cmd/synergyc/tb_wait.ico and /dev/null differ diff --git a/cmd/synergys/CMSWindowsServerTaskBarReceiver.cpp b/cmd/synergys/CMSWindowsServerTaskBarReceiver.cpp deleted file mode 100644 index e332ccea..00000000 --- a/cmd/synergys/CMSWindowsServerTaskBarReceiver.cpp +++ /dev/null @@ -1,374 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CMSWindowsServerTaskBarReceiver.h" -#include "CServer.h" -#include "CMSWindowsClipboard.h" -#include "IEventQueue.h" -#include "LogOutputters.h" -#include "BasicTypes.h" -#include "CArch.h" -#include "CArchTaskBarWindows.h" -#include "resource.h" - -extern CEvent::Type getReloadConfigEvent(); -extern CEvent::Type getForceReconnectEvent(); - -// -// CMSWindowsServerTaskBarReceiver -// - -const UINT CMSWindowsServerTaskBarReceiver::s_stateToIconID[kMaxState] = -{ - IDI_TASKBAR_NOT_RUNNING, - IDI_TASKBAR_NOT_WORKING, - IDI_TASKBAR_NOT_CONNECTED, - IDI_TASKBAR_CONNECTED -}; - -CMSWindowsServerTaskBarReceiver::CMSWindowsServerTaskBarReceiver( - HINSTANCE appInstance, const CBufferedLogOutputter* logBuffer) : - CServerTaskBarReceiver(), - m_appInstance(appInstance), - m_window(NULL), - m_logBuffer(logBuffer) -{ - for (UInt32 i = 0; i < kMaxState; ++i) { - m_icon[i] = loadIcon(s_stateToIconID[i]); - } - m_menu = LoadMenu(m_appInstance, MAKEINTRESOURCE(IDR_TASKBAR)); - - // don't create the window yet. we'll create it on demand. this - // has the side benefit of being created in the thread used for - // the task bar. that's good because it means the existence of - // the window won't prevent changing the main thread's desktop. - - // add ourself to the task bar - ARCH->addReceiver(this); -} - -CMSWindowsServerTaskBarReceiver::~CMSWindowsServerTaskBarReceiver() -{ - ARCH->removeReceiver(this); - for (UInt32 i = 0; i < kMaxState; ++i) { - deleteIcon(m_icon[i]); - } - DestroyMenu(m_menu); - destroyWindow(); -} - -void -CMSWindowsServerTaskBarReceiver::showStatus() -{ - // create the window - createWindow(); - - // lock self while getting status - lock(); - - // get the current status - std::string status = getToolTip(); - - // get the connect clients, if any - const CClients& clients = getClients(); - - // done getting status - unlock(); - - // update dialog - HWND child = GetDlgItem(m_window, IDC_TASKBAR_STATUS_STATUS); - SendMessage(child, WM_SETTEXT, 0, (LPARAM)status.c_str()); - child = GetDlgItem(m_window, IDC_TASKBAR_STATUS_CLIENTS); - SendMessage(child, LB_RESETCONTENT, 0, 0); - for (CClients::const_iterator index = clients.begin(); - index != clients.end(); ) { - const char* client = index->c_str(); - if (++index == clients.end()) { - SendMessage(child, LB_ADDSTRING, 0, (LPARAM)client); - } - else { - SendMessage(child, LB_INSERTSTRING, (WPARAM)-1, (LPARAM)client); - } - } - - if (!IsWindowVisible(m_window)) { - // position it by the mouse - POINT cursorPos; - GetCursorPos(&cursorPos); - RECT windowRect; - GetWindowRect(m_window, &windowRect); - int x = cursorPos.x; - int y = cursorPos.y; - int fw = GetSystemMetrics(SM_CXDLGFRAME); - int fh = GetSystemMetrics(SM_CYDLGFRAME); - int ww = windowRect.right - windowRect.left; - int wh = windowRect.bottom - windowRect.top; - int sw = GetSystemMetrics(SM_CXFULLSCREEN); - int sh = GetSystemMetrics(SM_CYFULLSCREEN); - if (fw < 1) { - fw = 1; - } - if (fh < 1) { - fh = 1; - } - if (x + ww - fw > sw) { - x -= ww - fw; - } - else { - x -= fw; - } - if (x < 0) { - x = 0; - } - if (y + wh - fh > sh) { - y -= wh - fh; - } - else { - y -= fh; - } - if (y < 0) { - y = 0; - } - SetWindowPos(m_window, HWND_TOPMOST, x, y, ww, wh, - SWP_SHOWWINDOW); - } -} - -void -CMSWindowsServerTaskBarReceiver::runMenu(int x, int y) -{ - // do popup menu. we need a window to pass to TrackPopupMenu(). - // the SetForegroundWindow() and SendMessage() calls around - // TrackPopupMenu() are to get the menu to be dismissed when - // another window gets activated and are just one of those - // win32 weirdnesses. - createWindow(); - SetForegroundWindow(m_window); - HMENU menu = GetSubMenu(m_menu, 0); - SetMenuDefaultItem(menu, IDC_TASKBAR_STATUS, FALSE); - HMENU logLevelMenu = GetSubMenu(menu, 3); - CheckMenuRadioItem(logLevelMenu, 0, 6, - CLOG->getFilter() - CLog::kERROR, MF_BYPOSITION); - int n = TrackPopupMenu(menu, - TPM_NONOTIFY | - TPM_RETURNCMD | - TPM_LEFTBUTTON | - TPM_RIGHTBUTTON, - x, y, 0, m_window, NULL); - SendMessage(m_window, WM_NULL, 0, 0); - - // perform the requested operation - switch (n) { - case IDC_TASKBAR_STATUS: - showStatus(); - break; - - case IDC_TASKBAR_LOG: - copyLog(); - break; - - case IDC_TASKBAR_SHOW_LOG: - ARCH->showConsole(true); - break; - - case IDC_RELOAD_CONFIG: - EVENTQUEUE->addEvent(CEvent(getReloadConfigEvent(), - IEventQueue::getSystemTarget())); - break; - - case IDC_FORCE_RECONNECT: - EVENTQUEUE->addEvent(CEvent(getForceReconnectEvent(), - IEventQueue::getSystemTarget())); - break; - - case IDC_TASKBAR_LOG_LEVEL_ERROR: - CLOG->setFilter(CLog::kERROR); - break; - - case IDC_TASKBAR_LOG_LEVEL_WARNING: - CLOG->setFilter(CLog::kWARNING); - break; - - case IDC_TASKBAR_LOG_LEVEL_NOTE: - CLOG->setFilter(CLog::kNOTE); - break; - - case IDC_TASKBAR_LOG_LEVEL_INFO: - CLOG->setFilter(CLog::kINFO); - break; - - case IDC_TASKBAR_LOG_LEVEL_DEBUG: - CLOG->setFilter(CLog::kDEBUG); - break; - - case IDC_TASKBAR_LOG_LEVEL_DEBUG1: - CLOG->setFilter(CLog::kDEBUG1); - break; - - case IDC_TASKBAR_LOG_LEVEL_DEBUG2: - CLOG->setFilter(CLog::kDEBUG2); - break; - - case IDC_TASKBAR_QUIT: - quit(); - break; - } -} - -void -CMSWindowsServerTaskBarReceiver::primaryAction() -{ - showStatus(); -} - -const IArchTaskBarReceiver::Icon -CMSWindowsServerTaskBarReceiver::getIcon() const -{ - return reinterpret_cast(m_icon[getStatus()]); -} - -void -CMSWindowsServerTaskBarReceiver::copyLog() const -{ - if (m_logBuffer != NULL) { - // collect log buffer - CString data; - for (CBufferedLogOutputter::const_iterator index = m_logBuffer->begin(); - index != m_logBuffer->end(); ++index) { - data += *index; - data += "\n"; - } - - // copy log to clipboard - if (!data.empty()) { - CMSWindowsClipboard clipboard(m_window); - clipboard.open(0); - clipboard.emptyUnowned(); - clipboard.add(IClipboard::kText, data); - clipboard.close(); - } - } -} - -void -CMSWindowsServerTaskBarReceiver::onStatusChanged() -{ - if (IsWindowVisible(m_window)) { - showStatus(); - } -} - -HICON -CMSWindowsServerTaskBarReceiver::loadIcon(UINT id) -{ - HANDLE icon = LoadImage(m_appInstance, - MAKEINTRESOURCE(id), - IMAGE_ICON, - 0, 0, - LR_DEFAULTCOLOR); - return reinterpret_cast(icon); -} - -void -CMSWindowsServerTaskBarReceiver::deleteIcon(HICON icon) -{ - if (icon != NULL) { - DestroyIcon(icon); - } -} - -void -CMSWindowsServerTaskBarReceiver::createWindow() -{ - // ignore if already created - if (m_window != NULL) { - return; - } - - // get the status dialog - m_window = CreateDialogParam(m_appInstance, - MAKEINTRESOURCE(IDD_TASKBAR_STATUS), - NULL, - (DLGPROC)&CMSWindowsServerTaskBarReceiver::staticDlgProc, - reinterpret_cast( - reinterpret_cast(this))); - - // window should appear on top of everything, including (especially) - // the task bar. - LONG_PTR style = GetWindowLongPtr(m_window, GWL_EXSTYLE); - style |= WS_EX_TOOLWINDOW | WS_EX_TOPMOST; - SetWindowLongPtr(m_window, GWL_EXSTYLE, style); - - // tell the task bar about this dialog - CArchTaskBarWindows::addDialog(m_window); -} - -void -CMSWindowsServerTaskBarReceiver::destroyWindow() -{ - if (m_window != NULL) { - CArchTaskBarWindows::removeDialog(m_window); - DestroyWindow(m_window); - m_window = NULL; - } -} - -BOOL -CMSWindowsServerTaskBarReceiver::dlgProc(HWND hwnd, - UINT msg, WPARAM wParam, LPARAM) -{ - switch (msg) { - case WM_INITDIALOG: - // use default focus - return TRUE; - - case WM_ACTIVATE: - // hide when another window is activated - if (LOWORD(wParam) == WA_INACTIVE) { - ShowWindow(hwnd, SW_HIDE); - } - break; - } - return FALSE; -} - -BOOL CALLBACK -CMSWindowsServerTaskBarReceiver::staticDlgProc(HWND hwnd, - UINT msg, WPARAM wParam, LPARAM lParam) -{ - // if msg is WM_INITDIALOG, extract the CMSWindowsServerTaskBarReceiver* - // and put it in the extra window data then forward the call. - CMSWindowsServerTaskBarReceiver* self = NULL; - if (msg == WM_INITDIALOG) { - self = reinterpret_cast( - reinterpret_cast(lParam)); - SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam); - } - else { - // get the extra window data and forward the call - LONG data = GetWindowLongPtr(hwnd, GWLP_USERDATA); - if (data != 0) { - self = reinterpret_cast( - reinterpret_cast(data)); - } - } - - // forward the message - if (self != NULL) { - return self->dlgProc(hwnd, msg, wParam, lParam); - } - else { - return (msg == WM_INITDIALOG) ? TRUE : FALSE; - } -} diff --git a/cmd/synergys/CMSWindowsServerTaskBarReceiver.h b/cmd/synergys/CMSWindowsServerTaskBarReceiver.h deleted file mode 100644 index ab679077..00000000 --- a/cmd/synergys/CMSWindowsServerTaskBarReceiver.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CMSWINDOWSSERVERTASKBARRECEIVER_H -#define CMSWINDOWSSERVERTASKBARRECEIVER_H - -#define WIN32_LEAN_AND_MEAN - -#include "CServerTaskBarReceiver.h" -#include - -class CBufferedLogOutputter; - -//! Implementation of CServerTaskBarReceiver for Microsoft Windows -class CMSWindowsServerTaskBarReceiver : public CServerTaskBarReceiver { -public: - CMSWindowsServerTaskBarReceiver(HINSTANCE, const CBufferedLogOutputter*); - virtual ~CMSWindowsServerTaskBarReceiver(); - - // IArchTaskBarReceiver overrides - virtual void showStatus(); - virtual void runMenu(int x, int y); - virtual void primaryAction(); - virtual const Icon getIcon() const; - -protected: - void copyLog() const; - - // CServerTaskBarReceiver overrides - virtual void onStatusChanged(); - -private: - HICON loadIcon(UINT); - void deleteIcon(HICON); - void createWindow(); - void destroyWindow(); - - BOOL dlgProc(HWND hwnd, - UINT msg, WPARAM wParam, LPARAM lParam); - static BOOL CALLBACK - staticDlgProc(HWND hwnd, - UINT msg, WPARAM wParam, LPARAM lParam); - -private: - HINSTANCE m_appInstance; - HWND m_window; - HMENU m_menu; - HICON m_icon[kMaxState]; - const CBufferedLogOutputter* m_logBuffer; - static const UINT s_stateToIconID[]; -}; - -#endif diff --git a/cmd/synergys/COSXServerTaskBarReceiver.cpp b/cmd/synergys/COSXServerTaskBarReceiver.cpp deleted file mode 100644 index 8195b84f..00000000 --- a/cmd/synergys/COSXServerTaskBarReceiver.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "COSXServerTaskBarReceiver.h" -#include "CArch.h" - -// -// COSXServerTaskBarReceiver -// - -COSXServerTaskBarReceiver::COSXServerTaskBarReceiver( - const CBufferedLogOutputter*) -{ - // add ourself to the task bar - ARCH->addReceiver(this); -} - -COSXServerTaskBarReceiver::~COSXServerTaskBarReceiver() -{ - ARCH->removeReceiver(this); -} - -void -COSXServerTaskBarReceiver::showStatus() -{ - // do nothing -} - -void -COSXServerTaskBarReceiver::runMenu(int, int) -{ - // do nothing -} - -void -COSXServerTaskBarReceiver::primaryAction() -{ - // do nothing -} - -const IArchTaskBarReceiver::Icon -COSXServerTaskBarReceiver::getIcon() const -{ - return NULL; -} diff --git a/cmd/synergys/COSXServerTaskBarReceiver.h b/cmd/synergys/COSXServerTaskBarReceiver.h deleted file mode 100644 index 7f6dc298..00000000 --- a/cmd/synergys/COSXServerTaskBarReceiver.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef COSXSERVERTASKBARRECEIVER_H -#define COSXSERVERTASKBARRECEIVER_H - -#include "CServerTaskBarReceiver.h" - -class CBufferedLogOutputter; - -//! Implementation of CServerTaskBarReceiver for OS X -class COSXServerTaskBarReceiver : public CServerTaskBarReceiver { -public: - COSXServerTaskBarReceiver(const CBufferedLogOutputter*); - virtual ~COSXServerTaskBarReceiver(); - - // IArchTaskBarReceiver overrides - virtual void showStatus(); - virtual void runMenu(int x, int y); - virtual void primaryAction(); - virtual const Icon getIcon() const; -}; - -#endif diff --git a/cmd/synergys/CServerTaskBarReceiver.cpp b/cmd/synergys/CServerTaskBarReceiver.cpp deleted file mode 100644 index 6555b214..00000000 --- a/cmd/synergys/CServerTaskBarReceiver.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CServerTaskBarReceiver.h" -#include "CServer.h" -#include "CLock.h" -#include "CStringUtil.h" -#include "IEventQueue.h" -#include "CArch.h" -#include "Version.h" - -// -// CServerTaskBarReceiver -// - -CServerTaskBarReceiver::CServerTaskBarReceiver() : - m_state(kNotRunning) -{ - // do nothing -} - -CServerTaskBarReceiver::~CServerTaskBarReceiver() -{ - // do nothing -} - -void -CServerTaskBarReceiver::updateStatus(CServer* server, const CString& errorMsg) -{ - { - // update our status - m_errorMessage = errorMsg; - if (server == NULL) { - if (m_errorMessage.empty()) { - m_state = kNotRunning; - } - else { - m_state = kNotWorking; - } - } - else { - m_clients.clear(); - server->getClients(m_clients); - if (m_clients.size() <= 1) { - m_state = kNotConnected; - } - else { - m_state = kConnected; - } - } - - // let subclasses have a go - onStatusChanged(server); - } - - // tell task bar - ARCH->updateReceiver(this); -} - -CServerTaskBarReceiver::EState -CServerTaskBarReceiver::getStatus() const -{ - return m_state; -} - -const CString& -CServerTaskBarReceiver::getErrorMessage() const -{ - return m_errorMessage; -} - -const CServerTaskBarReceiver::CClients& -CServerTaskBarReceiver::getClients() const -{ - return m_clients; -} - -void -CServerTaskBarReceiver::quit() -{ - EVENTQUEUE->addEvent(CEvent(CEvent::kQuit)); -} - -void -CServerTaskBarReceiver::onStatusChanged(CServer*) -{ - // do nothing -} - -void -CServerTaskBarReceiver::lock() const -{ - // do nothing -} - -void -CServerTaskBarReceiver::unlock() const -{ - // do nothing -} - -std::string -CServerTaskBarReceiver::getToolTip() const -{ - switch (m_state) { - case kNotRunning: - return CStringUtil::print("%s: Not running", kAppVersion); - - case kNotWorking: - return CStringUtil::print("%s: %s", - kAppVersion, m_errorMessage.c_str()); - - case kNotConnected: - return CStringUtil::print("%s: Waiting for clients", kAppVersion); - - case kConnected: - return CStringUtil::print("%s: Connected", kAppVersion); - - default: - return ""; - } -} diff --git a/cmd/synergys/CServerTaskBarReceiver.h b/cmd/synergys/CServerTaskBarReceiver.h deleted file mode 100644 index d6ec8571..00000000 --- a/cmd/synergys/CServerTaskBarReceiver.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CSERVERTASKBARRECEIVER_H -#define CSERVERTASKBARRECEIVER_H - -#include "CString.h" -#include "IArchTaskBarReceiver.h" -#include "stdvector.h" - -class CServer; - -//! Implementation of IArchTaskBarReceiver for the synergy server -class CServerTaskBarReceiver : public IArchTaskBarReceiver { -public: - CServerTaskBarReceiver(); - virtual ~CServerTaskBarReceiver(); - - //! @name manipulators - //@{ - - //! Update status - /*! - Determine the status and query required information from the server. - */ - void updateStatus(CServer*, const CString& errorMsg); - - //@} - - // IArchTaskBarReceiver overrides - virtual void showStatus() = 0; - virtual void runMenu(int x, int y) = 0; - virtual void primaryAction() = 0; - virtual void lock() const; - virtual void unlock() const; - virtual const Icon getIcon() const = 0; - virtual std::string getToolTip() const; - -protected: - typedef std::vector CClients; - enum EState { - kNotRunning, - kNotWorking, - kNotConnected, - kConnected, - kMaxState - }; - - //! Get status - EState getStatus() const; - - //! Get error message - const CString& getErrorMessage() const; - - //! Get connected clients - const CClients& getClients() const; - - //! Quit app - /*! - Causes the application to quit gracefully - */ - void quit(); - - //! Status change notification - /*! - Called when status changes. The default implementation does - nothing. - */ - virtual void onStatusChanged(CServer* server); - -private: - EState m_state; - CString m_errorMessage; - CClients m_clients; -}; - -#endif diff --git a/cmd/synergys/CXWindowsServerTaskBarReceiver.cpp b/cmd/synergys/CXWindowsServerTaskBarReceiver.cpp deleted file mode 100644 index 861d2f8c..00000000 --- a/cmd/synergys/CXWindowsServerTaskBarReceiver.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CXWindowsServerTaskBarReceiver.h" -#include "CArch.h" - -// -// CXWindowsServerTaskBarReceiver -// - -CXWindowsServerTaskBarReceiver::CXWindowsServerTaskBarReceiver( - const CBufferedLogOutputter*) -{ - // add ourself to the task bar - ARCH->addReceiver(this); -} - -CXWindowsServerTaskBarReceiver::~CXWindowsServerTaskBarReceiver() -{ - ARCH->removeReceiver(this); -} - -void -CXWindowsServerTaskBarReceiver::showStatus() -{ - // do nothing -} - -void -CXWindowsServerTaskBarReceiver::runMenu(int, int) -{ - // do nothing -} - -void -CXWindowsServerTaskBarReceiver::primaryAction() -{ - // do nothing -} - -const IArchTaskBarReceiver::Icon -CXWindowsServerTaskBarReceiver::getIcon() const -{ - return NULL; -} diff --git a/cmd/synergys/CXWindowsServerTaskBarReceiver.h b/cmd/synergys/CXWindowsServerTaskBarReceiver.h deleted file mode 100644 index 73234123..00000000 --- a/cmd/synergys/CXWindowsServerTaskBarReceiver.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CXWINDOWSSERVERTASKBARRECEIVER_H -#define CXWINDOWSSERVERTASKBARRECEIVER_H - -#include "CServerTaskBarReceiver.h" - -class CBufferedLogOutputter; - -//! Implementation of CServerTaskBarReceiver for X Windows -class CXWindowsServerTaskBarReceiver : public CServerTaskBarReceiver { -public: - CXWindowsServerTaskBarReceiver(const CBufferedLogOutputter*); - virtual ~CXWindowsServerTaskBarReceiver(); - - // IArchTaskBarReceiver overrides - virtual void showStatus(); - virtual void runMenu(int x, int y); - virtual void primaryAction(); - virtual const Icon getIcon() const; -}; - -#endif diff --git a/cmd/synergys/Makefile.am b/cmd/synergys/Makefile.am deleted file mode 100644 index 4ad48ce5..00000000 --- a/cmd/synergys/Makefile.am +++ /dev/null @@ -1,98 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2002 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -## Process this file with automake to produce Makefile.in -NULL = - -COMMON_SOURCE_FILES = \ - CServerTaskBarReceiver.cpp \ - CServerTaskBarReceiver.h \ - synergys.cpp \ - $(NULL) -XWINDOWS_SOURCE_FILES = \ - CXWindowsServerTaskBarReceiver.cpp \ - CXWindowsServerTaskBarReceiver.h \ - $(NULL) -MSWINDOWS_SOURCE_FILES = \ - CMSWindowsServerTaskBarReceiver.cpp \ - CMSWindowsServerTaskBarReceiver.h \ - resource.h \ - synergys.rc \ - $(NULL) -CARBON_SOURCE_FILES = \ - COSXServerTaskBarReceiver.cpp \ - COSXServerTaskBarReceiver.h \ - $(NULL) - -EXTRA_DIST = \ - Makefile.win \ - synergys.ico \ - tb_error.ico \ - tb_idle.ico \ - tb_run.ico \ - tb_wait.ico \ - $(XWINDOWS_SOURCE_FILES) \ - $(MSWINDOWS_SOURCE_FILES) \ - $(CARBON_SOURCE_FILES) \ - $(NULL) - -MAINTAINERCLEANFILES = \ - Makefile.in \ - $(NULL) - -bin_PROGRAMS = synergys -if XWINDOWS -synergys_SOURCES = \ - $(COMMON_SOURCE_FILES) \ - $(XWINDOWS_SOURCE_FILES) \ - $(NULL) -endif -if MSWINDOWS -synergys_SOURCES = \ - $(COMMON_SOURCE_FILES) \ - $(MSWINDOWS_SOURCE_FILES) \ - $(NULL) -endif -if CARBON -synergys_SOURCES = \ - $(COMMON_SOURCE_FILES) \ - $(CARBON_SOURCE_FILES) \ - $(NULL) -synergys_LDFLAGS = \ - -framework ScreenSaver \ - -framework IOKit \ - -framework ApplicationServices \ - -framework Foundation \ - $(NULL) -endif -synergys_LDADD = \ - $(top_builddir)/lib/server/libserver.a \ - $(top_builddir)/lib/platform/libplatform.a \ - $(top_builddir)/lib/synergy/libsynergy.a \ - $(top_builddir)/lib/net/libnet.a \ - $(top_builddir)/lib/io/libio.a \ - $(top_builddir)/lib/mt/libmt.a \ - $(top_builddir)/lib/base/libbase.a \ - $(top_builddir)/lib/common/libcommon.a \ - $(top_builddir)/lib/arch/libarch.a \ - $(NULL) -INCLUDES = \ - -I$(top_srcdir)/lib/common \ - -I$(top_srcdir)/lib/arch \ - -I$(top_srcdir)/lib/base \ - -I$(top_srcdir)/lib/mt \ - -I$(top_srcdir)/lib/io \ - -I$(top_srcdir)/lib/net \ - -I$(top_srcdir)/lib/synergy \ - -I$(top_srcdir)/lib/platform \ - -I$(top_srcdir)/lib/server \ - $(NULL) diff --git a/cmd/synergys/Makefile.win b/cmd/synergys/Makefile.win deleted file mode 100644 index 09d39958..00000000 --- a/cmd/synergys/Makefile.win +++ /dev/null @@ -1,89 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2007 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -BIN_SYNERGYS_SRC = cmd\synergys -BIN_SYNERGYS_DST = $(BUILD_DST)\$(BIN_SYNERGYS_SRC) -BIN_SYNERGYS_EXE = "$(BUILD_DST)\synergys.exe" -BIN_SYNERGYS_CPP = \ - "CServerTaskBarReceiver.cpp" \ - "CMSWindowsServerTaskBarReceiver.cpp" \ - "synergys.cpp" \ - $(NULL) -BIN_SYNERGYS_OBJ = \ - "$(BIN_SYNERGYS_DST)\CServerTaskBarReceiver.obj" \ - "$(BIN_SYNERGYS_DST)\CMSWindowsServerTaskBarReceiver.obj" \ - "$(BIN_SYNERGYS_DST)\synergys.obj" \ - $(NULL) -BIN_SYNERGYS_RC = "$(BIN_SYNERGYS_SRC)\synergys.rc" -BIN_SYNERGYS_RES = "$(BIN_SYNERGYS_DST)\synergys.res" -BIN_SYNERGYS_INC = \ - /I"lib\common" \ - /I"lib\arch" \ - /I"lib\base" \ - /I"lib\mt" \ - /I"lib\io" \ - /I"lib\net" \ - /I"lib\synergy" \ - /I"lib\platform" \ - /I"lib\server" \ - $(NULL) -BIN_SYNERGYS_LIB = \ - $(LIB_SERVER_LIB) \ - $(LIB_PLATFORM_LIB) \ - $(LIB_SYNERGY_LIB) \ - $(LIB_NET_LIB) \ - $(LIB_IO_LIB) \ - $(LIB_MT_LIB) \ - $(LIB_BASE_LIB) \ - $(LIB_ARCH_LIB) \ - $(LIB_COMMON_LIB) \ - $(NULL) - -CPP_FILES = $(CPP_FILES) $(BIN_SYNERGYS_CPP) -OBJ_FILES = $(OBJ_FILES) $(BIN_SYNERGYS_OBJ) -PROGRAMS = $(PROGRAMS) $(BIN_SYNERGYS_EXE) - -# Need shell functions. -guilibs = $(guilibs) shell32.lib - -# Dependency rules -$(BIN_SYNERGYS_OBJ): $(AUTODEP) -!if EXIST($(BIN_SYNERGYS_DST)\deps.mak) -!include $(BIN_SYNERGYS_DST)\deps.mak -!endif - -# Build rules. Use batch-mode rules if possible. -!if DEFINED(_NMAKE_VER) -{$(BIN_SYNERGYS_SRC)\}.cpp{$(BIN_SYNERGYS_DST)\}.obj:: -!else -{$(BIN_SYNERGYS_SRC)\}.cpp{$(BIN_SYNERGYS_DST)\}.obj: -!endif - @$(ECHO) Compile in $(BIN_SYNERGYS_SRC) - -@$(MKDIR) $(BIN_SYNERGYS_DST) 2>NUL: - $(cpp) $(cppdebug) $(cppflags) $(cppvarsmt) /showIncludes \ - $(BIN_SYNERGYS_INC) \ - /Fo$(BIN_SYNERGYS_DST)\ \ - /Fd$(BIN_SYNERGYS_DST)\src.pdb \ - $< | $(AUTODEP) $(BIN_SYNERGYS_SRC) $(BIN_SYNERGYS_DST) -$(BIN_SYNERGYS_RES): $(BIN_SYNERGYS_RC) - @$(ECHO) Compile $(**F) - -@$(MKDIR) $(BIN_SYNERGYS_DST) 2>NUL: - $(rc) $(rcflags) $(rcvars) \ - /fo$@ \ - $** -$(BIN_SYNERGYS_EXE): $(BIN_SYNERGYS_OBJ) $(BIN_SYNERGYS_RES) $(BIN_SYNERGYS_LIB) - @$(ECHO) Link $(@F) - $(link) $(ldebug) $(guilflags) $(guilibsmt) \ - /out:$@ \ - $** - $(AUTODEP) $(BIN_SYNERGYS_SRC) $(BIN_SYNERGYS_DST) \ - $(BIN_SYNERGYS_OBJ:.obj=.d) diff --git a/cmd/synergys/resource.h b/cmd/synergys/resource.h deleted file mode 100644 index 0ad5868a..00000000 --- a/cmd/synergys/resource.h +++ /dev/null @@ -1,40 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by synergys.rc -// -#define IDS_FAILED 1 -#define IDS_INIT_FAILED 2 -#define IDS_UNCAUGHT_EXCEPTION 3 -#define IDI_SYNERGY 101 -#define IDI_TASKBAR_NOT_RUNNING 102 -#define IDI_TASKBAR_NOT_WORKING 103 -#define IDI_TASKBAR_NOT_CONNECTED 104 -#define IDI_TASKBAR_CONNECTED 105 -#define IDR_TASKBAR 107 -#define IDD_TASKBAR_STATUS 108 -#define IDC_TASKBAR_STATUS_STATUS 1000 -#define IDC_TASKBAR_STATUS_CLIENTS 1001 -#define IDC_TASKBAR_QUIT 40003 -#define IDC_TASKBAR_STATUS 40004 -#define IDC_TASKBAR_LOG 40005 -#define IDC_RELOAD_CONFIG 40006 -#define IDC_FORCE_RECONNECT 40007 -#define IDC_TASKBAR_SHOW_LOG 40008 -#define IDC_TASKBAR_LOG_LEVEL_ERROR 40009 -#define IDC_TASKBAR_LOG_LEVEL_WARNING 40010 -#define IDC_TASKBAR_LOG_LEVEL_NOTE 40011 -#define IDC_TASKBAR_LOG_LEVEL_INFO 40012 -#define IDC_TASKBAR_LOG_LEVEL_DEBUG 40013 -#define IDC_TASKBAR_LOG_LEVEL_DEBUG1 40014 -#define IDC_TASKBAR_LOG_LEVEL_DEBUG2 40015 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 109 -#define _APS_NEXT_COMMAND_VALUE 40016 -#define _APS_NEXT_CONTROL_VALUE 1003 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/cmd/synergys/synergys.cpp b/cmd/synergys/synergys.cpp deleted file mode 100644 index 4319af1e..00000000 --- a/cmd/synergys/synergys.cpp +++ /dev/null @@ -1,1312 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CClientListener.h" -#include "CClientProxy.h" -#include "CConfig.h" -#include "CPrimaryClient.h" -#include "CServer.h" -#include "CScreen.h" -#include "ProtocolTypes.h" -#include "Version.h" -#include "XScreen.h" -#include "CSocketMultiplexer.h" -#include "CTCPSocketFactory.h" -#include "XSocket.h" -#include "CThread.h" -#include "CEventQueue.h" -#include "CFunctionEventJob.h" -#include "CLog.h" -#include "CString.h" -#include "CStringUtil.h" -#include "LogOutputters.h" -#include "CArch.h" -#include "XArch.h" -#include "stdfstream.h" -#include - -#define DAEMON_RUNNING(running_) -#if WINAPI_MSWINDOWS -#include "CArchMiscWindows.h" -#include "CMSWindowsScreen.h" -#include "CMSWindowsUtil.h" -#include "CMSWindowsServerTaskBarReceiver.h" -#include "resource.h" -#undef DAEMON_RUNNING -#define DAEMON_RUNNING(running_) CArchMiscWindows::daemonRunning(running_) -#elif WINAPI_XWINDOWS -#include "CXWindowsScreen.h" -#include "CXWindowsServerTaskBarReceiver.h" -#elif WINAPI_CARBON -#include "COSXScreen.h" -#include "COSXServerTaskBarReceiver.h" -#endif - -// platform dependent name of a daemon -#if SYSAPI_WIN32 -#define DAEMON_NAME "Synergy Server" -#elif SYSAPI_UNIX -#define DAEMON_NAME "synergys" -#endif - -// configuration file name -#if SYSAPI_WIN32 -#define USR_CONFIG_NAME "synergy.sgc" -#define SYS_CONFIG_NAME "synergy.sgc" -#elif SYSAPI_UNIX -#define USR_CONFIG_NAME ".synergy.conf" -#define SYS_CONFIG_NAME "synergy.conf" -#endif - -typedef int (*StartupFunc)(int, char**); -static void parse(int argc, const char* const* argv); -static bool loadConfig(const CString& pathname); -static void loadConfig(); - -// -// program arguments -// - -#define ARG CArgs::s_instance - -class CArgs { -public: - CArgs() : - m_pname(NULL), - m_backend(false), - m_restartable(true), - m_daemon(true), - m_configFile(), - m_logFilter(NULL), - m_display(NULL), - m_synergyAddress(NULL), - m_config(NULL) - { s_instance = this; } - ~CArgs() { s_instance = NULL; } - -public: - static CArgs* s_instance; - const char* m_pname; - bool m_backend; - bool m_restartable; - bool m_daemon; - CString m_configFile; - const char* m_logFilter; - const char* m_display; - CString m_name; - CNetworkAddress* m_synergyAddress; - CConfig* m_config; -}; - -CArgs* CArgs::s_instance = NULL; - - -// -// platform dependent factories -// - -static -CScreen* -createScreen() -{ -#if WINAPI_MSWINDOWS - return new CScreen(new CMSWindowsScreen(true)); -#elif WINAPI_XWINDOWS - return new CScreen(new CXWindowsScreen(ARG->m_display, true)); -#elif WINAPI_CARBON - return new CScreen(new COSXScreen(true)); -#endif -} - -static -CServerTaskBarReceiver* -createTaskBarReceiver(const CBufferedLogOutputter* logBuffer) -{ -#if WINAPI_MSWINDOWS - return new CMSWindowsServerTaskBarReceiver( - CMSWindowsScreen::getInstance(), logBuffer); -#elif WINAPI_XWINDOWS - return new CXWindowsServerTaskBarReceiver(logBuffer); -#elif WINAPI_CARBON - return new COSXServerTaskBarReceiver(logBuffer); -#endif -} - - -// -// platform independent main -// - -enum EServerState { - kUninitialized, - kInitializing, - kInitializingToStart, - kInitialized, - kStarting, - kStarted -}; - -static EServerState s_serverState = kUninitialized; -static CServer* s_server = NULL; -static CScreen* s_serverScreen = NULL; -static CPrimaryClient* s_primaryClient = NULL; -static CClientListener* s_listener = NULL; -static CServerTaskBarReceiver* s_taskBarReceiver = NULL; -static CEvent::Type s_reloadConfigEvent = CEvent::kUnknown; -static CEvent::Type s_forceReconnectEvent = CEvent::kUnknown; -static bool s_suspended = false; -static CEventQueueTimer* s_timer = NULL; - -CEvent::Type -getReloadConfigEvent() -{ - return CEvent::registerTypeOnce(s_reloadConfigEvent, "reloadConfig"); -} - -CEvent::Type -getForceReconnectEvent() -{ - return CEvent::registerTypeOnce(s_forceReconnectEvent, "forceReconnect"); -} - -static -void -updateStatus() -{ - s_taskBarReceiver->updateStatus(s_server, ""); -} - -static -void -updateStatus(const CString& msg) -{ - s_taskBarReceiver->updateStatus(s_server, msg); -} - -static -void -handleClientConnected(const CEvent&, void* vlistener) -{ - CClientListener* listener = reinterpret_cast(vlistener); - CClientProxy* client = listener->getNextClient(); - if (client != NULL) { - s_server->adoptClient(client); - updateStatus(); - } -} - -static -CClientListener* -openClientListener(const CNetworkAddress& address) -{ - CClientListener* listen = - new CClientListener(address, new CTCPSocketFactory, NULL); - EVENTQUEUE->adoptHandler(CClientListener::getConnectedEvent(), listen, - new CFunctionEventJob( - &handleClientConnected, listen)); - return listen; -} - -static -void -closeClientListener(CClientListener* listen) -{ - if (listen != NULL) { - EVENTQUEUE->removeHandler(CClientListener::getConnectedEvent(), listen); - delete listen; - } -} - -static -void -handleScreenError(const CEvent&, void*) -{ - LOG((CLOG_CRIT "error on screen")); - EVENTQUEUE->addEvent(CEvent(CEvent::kQuit)); -} - - -static void handleSuspend(const CEvent& event, void*); -static void handleResume(const CEvent& event, void*); - -static -CScreen* -openServerScreen() -{ - CScreen* screen = createScreen(); - EVENTQUEUE->adoptHandler(IScreen::getErrorEvent(), - screen->getEventTarget(), - new CFunctionEventJob( - &handleScreenError)); - EVENTQUEUE->adoptHandler(IScreen::getSuspendEvent(), - screen->getEventTarget(), - new CFunctionEventJob( - &handleSuspend)); - EVENTQUEUE->adoptHandler(IScreen::getResumeEvent(), - screen->getEventTarget(), - new CFunctionEventJob( - &handleResume)); - return screen; -} - -static -void -closeServerScreen(CScreen* screen) -{ - if (screen != NULL) { - EVENTQUEUE->removeHandler(IScreen::getErrorEvent(), - screen->getEventTarget()); - EVENTQUEUE->removeHandler(IScreen::getSuspendEvent(), - screen->getEventTarget()); - EVENTQUEUE->removeHandler(IScreen::getResumeEvent(), - screen->getEventTarget()); - delete screen; - } -} - -static -CPrimaryClient* -openPrimaryClient(const CString& name, CScreen* screen) -{ - LOG((CLOG_DEBUG1 "creating primary screen")); - return new CPrimaryClient(name, screen); -} - -static -void -closePrimaryClient(CPrimaryClient* primaryClient) -{ - delete primaryClient; -} - -static -void -handleNoClients(const CEvent&, void*) -{ - updateStatus(); -} - -static -void -handleClientsDisconnected(const CEvent&, void*) -{ - EVENTQUEUE->addEvent(CEvent(CEvent::kQuit)); -} - -static -CServer* -openServer(const CConfig& config, CPrimaryClient* primaryClient) -{ - CServer* server = new CServer(config, primaryClient); - EVENTQUEUE->adoptHandler(CServer::getDisconnectedEvent(), server, - new CFunctionEventJob(handleNoClients)); - return server; -} - -static -void -closeServer(CServer* server) -{ - if (server == NULL) { - return; - } - - // tell all clients to disconnect - server->disconnect(); - - // wait for clients to disconnect for up to timeout seconds - double timeout = 3.0; - CEventQueueTimer* timer = EVENTQUEUE->newOneShotTimer(timeout, NULL); - EVENTQUEUE->adoptHandler(CEvent::kTimer, timer, - new CFunctionEventJob(handleClientsDisconnected)); - EVENTQUEUE->adoptHandler(CServer::getDisconnectedEvent(), server, - new CFunctionEventJob(handleClientsDisconnected)); - CEvent event; - EVENTQUEUE->getEvent(event); - while (event.getType() != CEvent::kQuit) { - EVENTQUEUE->dispatchEvent(event); - CEvent::deleteData(event); - EVENTQUEUE->getEvent(event); - } - EVENTQUEUE->removeHandler(CEvent::kTimer, timer); - EVENTQUEUE->deleteTimer(timer); - EVENTQUEUE->removeHandler(CServer::getDisconnectedEvent(), server); - - // done with server - delete server; -} - -static bool initServer(); -static bool startServer(); - -static -void -stopRetryTimer() -{ - if (s_timer != NULL) { - EVENTQUEUE->deleteTimer(s_timer); - EVENTQUEUE->removeHandler(CEvent::kTimer, NULL); - s_timer = NULL; - } -} - -static -void -retryHandler(const CEvent&, void*) -{ - // discard old timer - assert(s_timer != NULL); - stopRetryTimer(); - - // try initializing/starting the server again - switch (s_serverState) { - case kUninitialized: - case kInitialized: - case kStarted: - assert(0 && "bad internal server state"); - break; - - case kInitializing: - LOG((CLOG_DEBUG1 "retry server initialization")); - s_serverState = kUninitialized; - if (!initServer()) { - EVENTQUEUE->addEvent(CEvent(CEvent::kQuit)); - } - break; - - case kInitializingToStart: - LOG((CLOG_DEBUG1 "retry server initialization")); - s_serverState = kUninitialized; - if (!initServer()) { - EVENTQUEUE->addEvent(CEvent(CEvent::kQuit)); - } - else if (s_serverState == kInitialized) { - LOG((CLOG_DEBUG1 "starting server")); - if (!startServer()) { - EVENTQUEUE->addEvent(CEvent(CEvent::kQuit)); - } - } - break; - - case kStarting: - LOG((CLOG_DEBUG1 "retry starting server")); - s_serverState = kInitialized; - if (!startServer()) { - EVENTQUEUE->addEvent(CEvent(CEvent::kQuit)); - } - break; - } -} - -static -bool -initServer() -{ - // skip if already initialized or initializing - if (s_serverState != kUninitialized) { - return true; - } - - double retryTime; - CScreen* serverScreen = NULL; - CPrimaryClient* primaryClient = NULL; - try { - CString name = ARG->m_config->getCanonicalName(ARG->m_name); - serverScreen = openServerScreen(); - primaryClient = openPrimaryClient(name, serverScreen); - s_serverScreen = serverScreen; - s_primaryClient = primaryClient; - s_serverState = kInitialized; - updateStatus(); - return true; - } - catch (XScreenUnavailable& e) { - LOG((CLOG_WARN "cannot open primary screen: %s", e.what())); - closePrimaryClient(primaryClient); - closeServerScreen(serverScreen); - updateStatus(CString("cannot open primary screen: ") + e.what()); - retryTime = e.getRetryTime(); - } - catch (XScreenOpenFailure& e) { - LOG((CLOG_CRIT "cannot open primary screen: %s", e.what())); - closePrimaryClient(primaryClient); - closeServerScreen(serverScreen); - return false; - } - catch (XBase& e) { - LOG((CLOG_CRIT "failed to start server: %s", e.what())); - closePrimaryClient(primaryClient); - closeServerScreen(serverScreen); - return false; - } - - if (ARG->m_restartable) { - // install a timer and handler to retry later - assert(s_timer == NULL); - LOG((CLOG_DEBUG "retry in %.0f seconds", retryTime)); - s_timer = EVENTQUEUE->newOneShotTimer(retryTime, NULL); - EVENTQUEUE->adoptHandler(CEvent::kTimer, s_timer, - new CFunctionEventJob(&retryHandler, NULL)); - s_serverState = kInitializing; - return true; - } - else { - // don't try again - return false; - } -} - -static -bool -startServer() -{ - // skip if already started or starting - if (s_serverState == kStarting || s_serverState == kStarted) { - return true; - } - - // initialize if necessary - if (s_serverState != kInitialized) { - if (!initServer()) { - // hard initialization failure - return false; - } - if (s_serverState == kInitializing) { - // not ready to start - s_serverState = kInitializingToStart; - return true; - } - assert(s_serverState == kInitialized); - } - - double retryTime; - CClientListener* listener = NULL; - try { - listener = openClientListener(ARG->m_config->getSynergyAddress()); - s_server = openServer(*ARG->m_config, s_primaryClient); - s_listener = listener; - updateStatus(); - LOG((CLOG_NOTE "started server")); - s_serverState = kStarted; - return true; - } - catch (XSocketAddressInUse& e) { - LOG((CLOG_WARN "cannot listen for clients: %s", e.what())); - closeClientListener(listener); - updateStatus(CString("cannot listen for clients: ") + e.what()); - retryTime = 10.0; - } - catch (XBase& e) { - LOG((CLOG_CRIT "failed to start server: %s", e.what())); - closeClientListener(listener); - return false; - } - - if (ARG->m_restartable) { - // install a timer and handler to retry later - assert(s_timer == NULL); - LOG((CLOG_DEBUG "retry in %.0f seconds", retryTime)); - s_timer = EVENTQUEUE->newOneShotTimer(retryTime, NULL); - EVENTQUEUE->adoptHandler(CEvent::kTimer, s_timer, - new CFunctionEventJob(&retryHandler, NULL)); - s_serverState = kStarting; - return true; - } - else { - // don't try again - return false; - } -} - -static -void -stopServer() -{ - if (s_serverState == kStarted) { - closeClientListener(s_listener); - closeServer(s_server); - s_server = NULL; - s_listener = NULL; - s_serverState = kInitialized; - } - else if (s_serverState == kStarting) { - stopRetryTimer(); - s_serverState = kInitialized; - } - assert(s_server == NULL); - assert(s_listener == NULL); -} - -static -void -cleanupServer() -{ - stopServer(); - if (s_serverState == kInitialized) { - closePrimaryClient(s_primaryClient); - closeServerScreen(s_serverScreen); - s_primaryClient = NULL; - s_serverScreen = NULL; - s_serverState = kUninitialized; - } - else if (s_serverState == kInitializing || - s_serverState == kInitializingToStart) { - stopRetryTimer(); - s_serverState = kUninitialized; - } - assert(s_primaryClient == NULL); - assert(s_serverScreen == NULL); - assert(s_serverState == kUninitialized); -} - -static -void -handleSuspend(const CEvent&, void*) -{ - if (!s_suspended) { - LOG((CLOG_INFO "suspend")); - stopServer(); - s_suspended = true; - } -} - -static -void -handleResume(const CEvent&, void*) -{ - if (s_suspended) { - LOG((CLOG_INFO "resume")); - startServer(); - s_suspended = false; - } -} - -static -void -reloadSignalHandler(CArch::ESignal, void*) -{ - EVENTQUEUE->addEvent(CEvent(getReloadConfigEvent(), - IEventQueue::getSystemTarget())); -} - -static -void -reloadConfig(const CEvent&, void*) -{ - LOG((CLOG_DEBUG "reload configuration")); - if (loadConfig(ARG->m_configFile)) { - if (s_server != NULL) { - s_server->setConfig(*ARG->m_config); - } - LOG((CLOG_NOTE "reloaded configuration")); - } -} - -static -void -forceReconnect(const CEvent&, void*) -{ - if (s_server != NULL) { - s_server->disconnect(); - } -} - -static -int -mainLoop() -{ - // create socket multiplexer. this must happen after daemonization - // on unix because threads evaporate across a fork(). - CSocketMultiplexer multiplexer; - - // create the event queue - CEventQueue eventQueue; - - // if configuration has no screens then add this system - // as the default - if (ARG->m_config->begin() == ARG->m_config->end()) { - ARG->m_config->addScreen(ARG->m_name); - } - - // set the contact address, if provided, in the config. - // otherwise, if the config doesn't have an address, use - // the default. - if (ARG->m_synergyAddress->isValid()) { - ARG->m_config->setSynergyAddress(*ARG->m_synergyAddress); - } - else if (!ARG->m_config->getSynergyAddress().isValid()) { - ARG->m_config->setSynergyAddress(CNetworkAddress(kDefaultPort)); - } - - // canonicalize the primary screen name - CString primaryName = ARG->m_config->getCanonicalName(ARG->m_name); - if (primaryName.empty()) { - LOG((CLOG_CRIT "unknown screen name `%s'", ARG->m_name.c_str())); - return kExitFailed; - } - - // start the server. if this return false then we've failed and - // we shouldn't retry. - LOG((CLOG_DEBUG1 "starting server")); - if (!startServer()) { - return kExitFailed; - } - - // handle hangup signal by reloading the server's configuration - ARCH->setSignalHandler(CArch::kHANGUP, &reloadSignalHandler, NULL); - EVENTQUEUE->adoptHandler(getReloadConfigEvent(), - IEventQueue::getSystemTarget(), - new CFunctionEventJob(&reloadConfig)); - - // handle force reconnect event by disconnecting clients. they'll - // reconnect automatically. - EVENTQUEUE->adoptHandler(getForceReconnectEvent(), - IEventQueue::getSystemTarget(), - new CFunctionEventJob(&forceReconnect)); - - // run event loop. if startServer() failed we're supposed to retry - // later. the timer installed by startServer() will take care of - // that. - CEvent event; - DAEMON_RUNNING(true); - EVENTQUEUE->getEvent(event); - while (event.getType() != CEvent::kQuit) { - EVENTQUEUE->dispatchEvent(event); - CEvent::deleteData(event); - EVENTQUEUE->getEvent(event); - } - DAEMON_RUNNING(false); - - // close down - LOG((CLOG_DEBUG1 "stopping server")); - EVENTQUEUE->removeHandler(getForceReconnectEvent(), - IEventQueue::getSystemTarget()); - EVENTQUEUE->removeHandler(getReloadConfigEvent(), - IEventQueue::getSystemTarget()); - cleanupServer(); - updateStatus(); - LOG((CLOG_NOTE "stopped server")); - - return kExitSuccess; -} - -static -int -daemonMainLoop(int, const char**) -{ -#if SYSAPI_WIN32 - CSystemLogger sysLogger(DAEMON_NAME, false); -#else - CSystemLogger sysLogger(DAEMON_NAME, true); -#endif - return mainLoop(); -} - -static -int -standardStartup(int argc, char** argv) -{ - if (!ARG->m_daemon) { - ARCH->showConsole(false); - } - - // parse command line - parse(argc, argv); - - // load configuration - loadConfig(); - - // daemonize if requested - if (ARG->m_daemon) { - return ARCH->daemonize(DAEMON_NAME, &daemonMainLoop); - } - else { - return mainLoop(); - } -} - -static -int -run(int argc, char** argv, ILogOutputter* outputter, StartupFunc startup) -{ - // general initialization - ARG->m_synergyAddress = new CNetworkAddress; - ARG->m_config = new CConfig; - ARG->m_pname = ARCH->getBasename(argv[0]); - - // install caller's output filter - if (outputter != NULL) { - CLOG->insert(outputter); - } - - // save log messages - CBufferedLogOutputter logBuffer(1000); - CLOG->insert(&logBuffer, true); - - // make the task bar receiver. the user can control this app - // through the task bar. - s_taskBarReceiver = createTaskBarReceiver(&logBuffer); - - // run - int result = startup(argc, argv); - - // done with task bar receiver - delete s_taskBarReceiver; - - // done with log buffer - CLOG->remove(&logBuffer); - - delete ARG->m_config; - delete ARG->m_synergyAddress; - return result; -} - - -// -// command line parsing -// - -#define BYE "\nTry `%s --help' for more information." - -static void (*bye)(int) = &exit; - -static -void -version() -{ - LOG((CLOG_PRINT -"%s %s, protocol version %d.%d\n" -"%s", - ARG->m_pname, - kVersion, - kProtocolMajorVersion, - kProtocolMinorVersion, - kCopyright)); -} - -static -void -help() -{ -#if WINAPI_XWINDOWS -# define USAGE_DISPLAY_ARG \ -" [--display ]" -# define USAGE_DISPLAY_INFO \ -" --display connect to the X server at \n" -#else -# define USAGE_DISPLAY_ARG -# define USAGE_DISPLAY_INFO -#endif - -#if SYSAPI_WIN32 - -# define PLATFORM_ARGS \ -" [--daemon|--no-daemon]" -# define PLATFORM_DESC -# define PLATFORM_EXTRA \ -"At least one command line argument is required. If you don't otherwise\n" \ -"need an argument use `--daemon'.\n" \ -"\n" - -#else - -# define PLATFORM_ARGS \ -" [--daemon|--no-daemon]" -# define PLATFORM_DESC -# define PLATFORM_EXTRA - -#endif - - LOG((CLOG_PRINT -"Usage: %s" -" [--address
]" -" [--config ]" -" [--debug ]" -USAGE_DISPLAY_ARG -" [--name ]" -" [--restart|--no-restart]" -PLATFORM_ARGS -"\n\n" -"Start the synergy mouse/keyboard sharing server.\n" -"\n" -" -a, --address
listen for clients on the given address.\n" -" -c, --config use the named configuration file instead.\n" -" -d, --debug filter out log messages with priorty below level.\n" -" level may be: FATAL, ERROR, WARNING, NOTE, INFO,\n" -" DEBUG, DEBUG1, DEBUG2.\n" -USAGE_DISPLAY_INFO -" -f, --no-daemon run the server in the foreground.\n" -"* --daemon run the server as a daemon.\n" -" -n, --name use screen-name instead the hostname to identify\n" -" this screen in the configuration.\n" -" -1, --no-restart do not try to restart the server if it fails for\n" -" some reason.\n" -"* --restart restart the server automatically if it fails.\n" -PLATFORM_DESC -" -h, --help display this help and exit.\n" -" --version display version information and exit.\n" -"\n" -"* marks defaults.\n" -"\n" -PLATFORM_EXTRA -"The argument for --address is of the form: [][:]. The\n" -"hostname must be the address or hostname of an interface on the system.\n" -"The default is to listen on all interfaces. The port overrides the\n" -"default port, %d.\n" -"\n" -"If no configuration file pathname is provided then the first of the\n" -"following to load successfully sets the configuration:\n" -" %s\n" -" %s\n" -"If no configuration file can be loaded then the configuration uses its\n" -"defaults with just the server screen.\n" -"\n" -"Where log messages go depends on the platform and whether or not the\n" -"server is running as a daemon.", - ARG->m_pname, - kDefaultPort, - ARCH->concatPath( - ARCH->getUserDirectory(), - USR_CONFIG_NAME).c_str(), - ARCH->concatPath( - ARCH->getSystemDirectory(), - SYS_CONFIG_NAME).c_str())); -} - -static -bool -isArg(int argi, int argc, const char* const* argv, - const char* name1, const char* name2, - int minRequiredParameters = 0) -{ - if ((name1 != NULL && strcmp(argv[argi], name1) == 0) || - (name2 != NULL && strcmp(argv[argi], name2) == 0)) { - // match. check args left. - if (argi + minRequiredParameters >= argc) { - LOG((CLOG_PRINT "%s: missing arguments for `%s'" BYE, - ARG->m_pname, argv[argi], ARG->m_pname)); - bye(kExitArgs); - } - return true; - } - - // no match - return false; -} - -static -void -parse(int argc, const char* const* argv) -{ - assert(ARG->m_pname != NULL); - assert(argv != NULL); - assert(argc >= 1); - - // set defaults - ARG->m_name = ARCH->getHostName(); - - // parse options - int i = 1; - for (; i < argc; ++i) { - if (isArg(i, argc, argv, "-d", "--debug", 1)) { - // change logging level - ARG->m_logFilter = argv[++i]; - } - - else if (isArg(i, argc, argv, "-a", "--address", 1)) { - // save listen address - try { - *ARG->m_synergyAddress = CNetworkAddress(argv[i + 1], - kDefaultPort); - ARG->m_synergyAddress->resolve(); - } - catch (XSocketAddress& e) { - LOG((CLOG_PRINT "%s: %s" BYE, - ARG->m_pname, e.what(), ARG->m_pname)); - bye(kExitArgs); - } - ++i; - } - - else if (isArg(i, argc, argv, "-n", "--name", 1)) { - // save screen name - ARG->m_name = argv[++i]; - } - - else if (isArg(i, argc, argv, "-c", "--config", 1)) { - // save configuration file path - ARG->m_configFile = argv[++i]; - } - -#if WINAPI_XWINDOWS - else if (isArg(i, argc, argv, "-display", "--display", 1)) { - // use alternative display - ARG->m_display = argv[++i]; - } -#endif - - else if (isArg(i, argc, argv, "-f", "--no-daemon")) { - // not a daemon - ARG->m_daemon = false; - } - - else if (isArg(i, argc, argv, NULL, "--daemon")) { - // daemonize - ARG->m_daemon = true; - } - - else if (isArg(i, argc, argv, "-1", "--no-restart")) { - // don't try to restart - ARG->m_restartable = false; - } - - else if (isArg(i, argc, argv, NULL, "--restart")) { - // try to restart - ARG->m_restartable = true; - } - - else if (isArg(i, argc, argv, "-z", NULL)) { - ARG->m_backend = true; - } - - else if (isArg(i, argc, argv, "-h", "--help")) { - help(); - bye(kExitSuccess); - } - - else if (isArg(i, argc, argv, NULL, "--version")) { - version(); - bye(kExitSuccess); - } - - else if (isArg(i, argc, argv, "--", NULL)) { - // remaining arguments are not options - ++i; - break; - } - - else if (argv[i][0] == '-') { - LOG((CLOG_PRINT "%s: unrecognized option `%s'" BYE, - ARG->m_pname, argv[i], ARG->m_pname)); - bye(kExitArgs); - } - - else { - // this and remaining arguments are not options - break; - } - } - - // no non-option arguments are allowed - if (i != argc) { - LOG((CLOG_PRINT "%s: unrecognized option `%s'" BYE, - ARG->m_pname, argv[i], ARG->m_pname)); - bye(kExitArgs); - } - - // increase default filter level for daemon. the user must - // explicitly request another level for a daemon. - if (ARG->m_daemon && ARG->m_logFilter == NULL) { -#if SYSAPI_WIN32 - if (CArchMiscWindows::isWindows95Family()) { - // windows 95 has no place for logging so avoid showing - // the log console window. - ARG->m_logFilter = "FATAL"; - } - else -#endif - { - ARG->m_logFilter = "NOTE"; - } - } - - // set log filter - if (!CLOG->setFilter(ARG->m_logFilter)) { - LOG((CLOG_PRINT "%s: unrecognized log level `%s'" BYE, - ARG->m_pname, ARG->m_logFilter, ARG->m_pname)); - bye(kExitArgs); - } - - // identify system - LOG((CLOG_INFO "Synergy server %s on %s", kVersion, ARCH->getOSName().c_str())); -} - -static -bool -loadConfig(const CString& pathname) -{ - try { - // load configuration - LOG((CLOG_DEBUG "opening configuration \"%s\"", pathname.c_str())); - std::ifstream configStream(pathname.c_str()); - if (!configStream.is_open()) { - // report failure to open configuration as a debug message - // since we try several paths and we expect some to be - // missing. - LOG((CLOG_DEBUG "cannot open configuration \"%s\"", - pathname.c_str())); - return false; - } - configStream >> *ARG->m_config; - LOG((CLOG_DEBUG "configuration read successfully")); - return true; - } - catch (XConfigRead& e) { - // report error in configuration file - LOG((CLOG_ERR "cannot read configuration \"%s\": %s", - pathname.c_str(), e.what())); - } - return false; -} - -static -void -loadConfig() -{ - bool loaded = false; - - // load the config file, if specified - if (!ARG->m_configFile.empty()) { - loaded = loadConfig(ARG->m_configFile); - } - - // load the default configuration if no explicit file given - else { - // get the user's home directory - CString path = ARCH->getUserDirectory(); - if (!path.empty()) { - // complete path - path = ARCH->concatPath(path, USR_CONFIG_NAME); - - // now try loading the user's configuration - if (loadConfig(path)) { - loaded = true; - ARG->m_configFile = path; - } - } - if (!loaded) { - // try the system-wide config file - path = ARCH->getSystemDirectory(); - if (!path.empty()) { - path = ARCH->concatPath(path, SYS_CONFIG_NAME); - if (loadConfig(path)) { - loaded = true; - ARG->m_configFile = path; - } - } - } - } - - if (!loaded) { - LOG((CLOG_PRINT "%s: no configuration available", ARG->m_pname)); - bye(kExitConfig); - } -} - - -// -// platform dependent entry points -// - -#if SYSAPI_WIN32 - -static bool s_hasImportantLogMessages = false; - -// -// CMessageBoxOutputter -// -// This class writes severe log messages to a message box -// - -class CMessageBoxOutputter : public ILogOutputter { -public: - CMessageBoxOutputter() { } - virtual ~CMessageBoxOutputter() { } - - // ILogOutputter overrides - virtual void open(const char*) { } - virtual void close() { } - virtual void show(bool) { } - virtual bool write(ELevel level, const char* message); - virtual const char* getNewline() const { return ""; } -}; - -bool -CMessageBoxOutputter::write(ELevel level, const char* message) -{ - // note any important messages the user may need to know about - if (level <= CLog::kWARNING) { - s_hasImportantLogMessages = true; - } - - // FATAL and PRINT messages get a dialog box if not running as - // backend. if we're running as a backend the user will have - // a chance to see the messages when we exit. - if (!ARG->m_backend && level <= CLog::kFATAL) { - MessageBox(NULL, message, ARG->m_pname, MB_OK | MB_ICONWARNING); - return false; - } - else { - return true; - } -} - -static -void -byeThrow(int x) -{ - CArchMiscWindows::daemonFailed(x); -} - -static -int -daemonNTMainLoop(int argc, const char** argv) -{ - parse(argc, argv); - ARG->m_backend = false; - loadConfig(); - return CArchMiscWindows::runDaemon(mainLoop); -} - -static -int -daemonNTStartup(int, char**) -{ - CSystemLogger sysLogger(DAEMON_NAME, false); - bye = &byeThrow; - return ARCH->daemonize(DAEMON_NAME, &daemonNTMainLoop); -} - -static -int -foregroundStartup(int argc, char** argv) -{ - ARCH->showConsole(false); - - // parse command line - parse(argc, argv); - - // load configuration - loadConfig(); - - // never daemonize - return mainLoop(); -} - -static -void -showError(HINSTANCE instance, const char* title, UINT id, const char* arg) -{ - CString fmt = CMSWindowsUtil::getString(instance, id); - CString msg = CStringUtil::format(fmt.c_str(), arg); - MessageBox(NULL, msg.c_str(), title, MB_OK | MB_ICONWARNING); -} - -int WINAPI -WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int) -{ - try { - CArchMiscWindows::setIcons((HICON)LoadImage(instance, - MAKEINTRESOURCE(IDI_SYNERGY), - IMAGE_ICON, - 32, 32, LR_SHARED), - (HICON)LoadImage(instance, - MAKEINTRESOURCE(IDI_SYNERGY), - IMAGE_ICON, - 16, 16, LR_SHARED)); - CArch arch(instance); - CMSWindowsScreen::init(instance); - CLOG; - CThread::getCurrentThread().setPriority(-14); - CArgs args; - - // set title on log window - ARCH->openConsole((CString(kAppVersion) + " " + "Server").c_str()); - - // windows NT family starts services using no command line options. - // since i'm not sure how to tell the difference between that and - // a user providing no options we'll assume that if there are no - // arguments and we're on NT then we're being invoked as a service. - // users on NT can use `--daemon' or `--no-daemon' to force us out - // of the service code path. - StartupFunc startup = &standardStartup; - if (!CArchMiscWindows::isWindows95Family()) { - if (__argc <= 1) { - startup = &daemonNTStartup; - } - else { - startup = &foregroundStartup; - } - } - - // send PRINT and FATAL output to a message box - int result = run(__argc, __argv, new CMessageBoxOutputter, startup); - - // let user examine any messages if we're running as a backend - // by putting up a dialog box before exiting. - if (args.m_backend && s_hasImportantLogMessages) { - showError(instance, args.m_pname, IDS_FAILED, ""); - } - - delete CLOG; - return result; - } - catch (XBase& e) { - showError(instance, __argv[0], IDS_UNCAUGHT_EXCEPTION, e.what()); - //throw; - } - catch (XArch& e) { - showError(instance, __argv[0], IDS_INIT_FAILED, e.what().c_str()); - } - catch (...) { - showError(instance, __argv[0], IDS_UNCAUGHT_EXCEPTION, ""); - //throw; - } - return kExitFailed; -} - -#elif SYSAPI_UNIX - -int -main(int argc, char** argv) -{ - CArgs args; - try { - int result; - CArch arch; - CLOG; - CArgs args; - result = run(argc, argv, NULL, &standardStartup); - delete CLOG; - return result; - } - catch (XBase& e) { - LOG((CLOG_CRIT "Uncaught exception: %s\n", e.what())); - throw; - } - catch (XArch& e) { - LOG((CLOG_CRIT "Initialization failed: %s" BYE, e.what().c_str())); - return kExitFailed; - } - catch (...) { - LOG((CLOG_CRIT "Uncaught exception: \n")); - throw; - } -} - -#else - -#error no main() for platform - -#endif diff --git a/cmd/synergys/synergys.ico b/cmd/synergys/synergys.ico deleted file mode 100644 index 89f965f4..00000000 Binary files a/cmd/synergys/synergys.ico and /dev/null differ diff --git a/cmd/synergys/synergys.rc b/cmd/synergys/synergys.rc deleted file mode 100644 index d56a4313..00000000 --- a/cmd/synergys/synergys.rc +++ /dev/null @@ -1,146 +0,0 @@ -//Microsoft Developer Studio generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include -#if !defined(IDC_STATIC) -#define IDC_STATIC (-1) -#endif - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE DISCARDABLE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE DISCARDABLE -BEGIN - "#include \r\n" - "\0" -END - -3 TEXTINCLUDE DISCARDABLE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_SYNERGY ICON DISCARDABLE "synergys.ico" -IDI_TASKBAR_NOT_RUNNING ICON DISCARDABLE "tb_idle.ico" -IDI_TASKBAR_NOT_WORKING ICON DISCARDABLE "tb_error.ico" -IDI_TASKBAR_NOT_CONNECTED ICON DISCARDABLE "tb_wait.ico" -IDI_TASKBAR_CONNECTED ICON DISCARDABLE "tb_run.ico" - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -IDR_TASKBAR MENU DISCARDABLE -BEGIN - POPUP "Synergy" - BEGIN - MENUITEM "Show Status", IDC_TASKBAR_STATUS - MENUITEM "Show Log", IDC_TASKBAR_SHOW_LOG - MENUITEM "Copy Log To Clipboard", IDC_TASKBAR_LOG - POPUP "Set Log Level" - BEGIN - MENUITEM "Error", IDC_TASKBAR_LOG_LEVEL_ERROR - - MENUITEM "Warning", IDC_TASKBAR_LOG_LEVEL_WARNING - - MENUITEM "Note", IDC_TASKBAR_LOG_LEVEL_NOTE - - MENUITEM "Info", IDC_TASKBAR_LOG_LEVEL_INFO - - MENUITEM "Debug", IDC_TASKBAR_LOG_LEVEL_DEBUG - - MENUITEM "Debug1", IDC_TASKBAR_LOG_LEVEL_DEBUG1 - - MENUITEM "Debug2", IDC_TASKBAR_LOG_LEVEL_DEBUG2 - - END - MENUITEM "Reload Configuration", IDC_RELOAD_CONFIG - MENUITEM "Force Reconnect", IDC_FORCE_RECONNECT - MENUITEM SEPARATOR - MENUITEM "Quit", IDC_TASKBAR_QUIT - END -END - - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_TASKBAR_STATUS DIALOG DISCARDABLE 0, 0, 145, 60 -STYLE DS_MODALFRAME | WS_POPUP -FONT 8, "MS Sans Serif" -BEGIN - EDITTEXT IDC_TASKBAR_STATUS_STATUS,3,3,139,12,ES_AUTOHSCROLL | - ES_READONLY | NOT WS_BORDER - LISTBOX IDC_TASKBAR_STATUS_CLIENTS,3,17,139,40,NOT LBS_NOTIFY | - LBS_SORT | LBS_NOINTEGRALHEIGHT | LBS_NOSEL | WS_VSCROLL | - WS_TABSTOP -END - - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -STRINGTABLE DISCARDABLE -BEGIN - IDS_FAILED "Synergy is about to quit with errors or warnings. Please check the log then click OK." - IDS_INIT_FAILED "Synergy failed to initialize: %{1}" - IDS_UNCAUGHT_EXCEPTION "Uncaught exception: %{1}" -END - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/cmd/synergys/tb_error.ico b/cmd/synergys/tb_error.ico deleted file mode 100644 index 746a87c9..00000000 Binary files a/cmd/synergys/tb_error.ico and /dev/null differ diff --git a/cmd/synergys/tb_idle.ico b/cmd/synergys/tb_idle.ico deleted file mode 100644 index 4e13a264..00000000 Binary files a/cmd/synergys/tb_idle.ico and /dev/null differ diff --git a/cmd/synergys/tb_run.ico b/cmd/synergys/tb_run.ico deleted file mode 100644 index 88e160cb..00000000 Binary files a/cmd/synergys/tb_run.ico and /dev/null differ diff --git a/cmd/synergys/tb_wait.ico b/cmd/synergys/tb_wait.ico deleted file mode 100644 index 257be0a1..00000000 Binary files a/cmd/synergys/tb_wait.ico and /dev/null differ diff --git a/config/config.guess b/config/config.guess deleted file mode 100755 index 6ead80a0..00000000 --- a/config/config.guess +++ /dev/null @@ -1,1327 +0,0 @@ -#! /bin/sh -# Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -# Free Software Foundation, Inc. - -timestamp='2001-08-21' - -# This file 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. -# -# This program 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 this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Written by Per Bothner . -# Please send patches to . -# -# This script attempts to guess a canonical system name similar to -# config.sub. If it succeeds, it prints the system name on stdout, and -# exits with 0. Otherwise, it exits with 1. -# -# The plan is that this can be called by configure scripts if you -# don't specify an explicit build system type. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] - -Output the configuration name of the system \`$me' is run on. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.guess ($timestamp) - -Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit 0 ;; - --version | -v ) - echo "$version" ; exit 0 ;; - --help | --h* | -h ) - echo "$usage"; exit 0 ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" >&2 - exit 1 ;; - * ) - break ;; - esac -done - -if test $# != 0; then - echo "$me: too many arguments$help" >&2 - exit 1 -fi - - -dummy=dummy-$$ -trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15 - -# CC_FOR_BUILD -- compiler used by this script. -# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still -# use `HOST_CC' if defined, but it is deprecated. - -set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int dummy(){}" > $dummy.c ; - for c in cc gcc c89 ; do - ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ; - if test $? = 0 ; then - CC_FOR_BUILD="$c"; break ; - fi ; - done ; - rm -f $dummy.c $dummy.o $dummy.rel ; - if test x"$CC_FOR_BUILD" = x ; then - CC_FOR_BUILD=no_compiler_found ; - fi - ;; - ,,*) CC_FOR_BUILD=$CC ;; - ,*,*) CC_FOR_BUILD=$HOST_CC ;; -esac' - -# This is needed to find uname on a Pyramid OSx when run in the BSD universe. -# (ghazi@noc.rutgers.edu 1994-08-24) -if (test -f /.attbin/uname) >/dev/null 2>&1 ; then - PATH=$PATH:/.attbin ; export PATH -fi - -UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown -UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown -UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown -UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown - -case "${UNAME_MACHINE}" in - i?86) - test -z "$VENDOR" && VENDOR=pc - ;; - *) - test -z "$VENDOR" && VENDOR=unknown - ;; -esac -test -f /etc/SuSE-release && VENDOR=suse - -# Note: order is significant - the case branches are not exclusive. - -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in - *:NetBSD:*:*) - # Netbsd (nbsd) targets should (where applicable) match one or - # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, - # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently - # switched to ELF, *-*-netbsd* would select the old - # object file format. This provides both forward - # compatibility and a consistent mechanism for selecting the - # object file format. - # Determine the machine/vendor (is the vendor relevant). - case "${UNAME_MACHINE}" in - amiga) machine=m68k-unknown ;; - arm32) machine=arm-unknown ;; - atari*) machine=m68k-atari ;; - sun3*) machine=m68k-sun ;; - mac68k) machine=m68k-apple ;; - macppc) machine=powerpc-apple ;; - hp3[0-9][05]) machine=m68k-hp ;; - ibmrt|romp-ibm) machine=romp-ibm ;; - *) machine=${UNAME_MACHINE}-unknown ;; - esac - # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE}" in - i386|sparc|amiga|arm*|hp300|mvme68k|vax|atari|luna68k|mac68k|news68k|next68k|pc532|sun3*|x68k) - eval $set_cc_for_build - if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep __ELF__ >/dev/null - then - # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). - # Return netbsd for either. FIX? - os=netbsd - else - os=netbsdelf - fi - ;; - *) - os=netbsd - ;; - esac - # The OS release - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: - # contains redundant information, the shorter form: - # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" - exit 0 ;; - alpha:OSF1:*:*) - if test $UNAME_RELEASE = "V4.0"; then - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` - fi - # A Vn.n version is a released version. - # A Tn.n version is a released field test version. - # A Xn.n version is an unreleased experimental baselevel. - # 1.2 uses "1.2" for uname -r. - cat <$dummy.s - .data -\$Lformat: - .byte 37,100,45,37,120,10,0 # "%d-%x\n" - - .text - .globl main - .align 4 - .ent main -main: - .frame \$30,16,\$26,0 - ldgp \$29,0(\$27) - .prologue 1 - .long 0x47e03d80 # implver \$0 - lda \$2,-1 - .long 0x47e20c21 # amask \$2,\$1 - lda \$16,\$Lformat - mov \$0,\$17 - not \$1,\$18 - jsr \$26,printf - ldgp \$29,0(\$26) - mov 0,\$16 - jsr \$26,exit - .end main -EOF - eval $set_cc_for_build - $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null - if test "$?" = 0 ; then - case `./$dummy` in - 0-0) - UNAME_MACHINE="alpha" - ;; - 1-0) - UNAME_MACHINE="alphaev5" - ;; - 1-1) - UNAME_MACHINE="alphaev56" - ;; - 1-101) - UNAME_MACHINE="alphapca56" - ;; - 2-303) - UNAME_MACHINE="alphaev6" - ;; - 2-307) - UNAME_MACHINE="alphaev67" - ;; - 2-1307) - UNAME_MACHINE="alphaev68" - ;; - esac - fi - rm -f $dummy.s $dummy - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - exit 0 ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit 0 ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit 0 ;; - Amiga*:UNIX_System_V:4.0:*) - echo m68k-unknown-sysv4 - exit 0;; - amiga:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos - exit 0 ;; - arc64:OpenBSD:*:*) - echo mips64el-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - arc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - hkmips:OpenBSD:*:*) - echo mips-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - pmax:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - sgi:OpenBSD:*:*) - echo mips-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - wgrisc:OpenBSD:*:*) - echo mipsel-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - *:OS/390:*:*) - echo i370-ibm-openedition - exit 0 ;; - arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} - exit 0;; - SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) - echo hppa1.1-hitachi-hiuxmpp - exit 0;; - Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) - # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. - if test "`(/bin/universe) 2>/dev/null`" = att ; then - echo pyramid-pyramid-sysv3 - else - echo pyramid-pyramid-bsd - fi - exit 0 ;; - NILE*:*:*:dcosx) - echo pyramid-pyramid-svr4 - exit 0 ;; - sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - i86pc:SunOS:5.*:*) - echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - sun4*:SunOS:6*:*) - # According to config.sub, this is the proper way to canonicalize - # SunOS6. Hard to guess exactly what SunOS6 will be like, but - # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - sun4*:SunOS:*:*) - case "`/usr/bin/arch -k`" in - Series*|S4*) - UNAME_RELEASE=`uname -v` - ;; - esac - # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` - exit 0 ;; - sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} - exit 0 ;; - sun*:*:4.2BSD:*) - UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 - case "`/bin/arch`" in - sun3) - echo m68k-sun-sunos${UNAME_RELEASE} - ;; - sun4) - echo sparc-sun-sunos${UNAME_RELEASE} - ;; - esac - exit 0 ;; - aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} - exit 0 ;; - sparc*:NetBSD:*) - echo `uname -p`-unknown-netbsd${UNAME_RELEASE} - exit 0 ;; - atari*:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - # The situation for MiNT is a little confusing. The machine name - # can be virtually everything (everything which is not - # "atarist" or "atariste" at least should have a processor - # > m68000). The system name ranges from "MiNT" over "FreeMiNT" - # to the lowercase version "mint" (or "freemint"). Finally - # the system name "TOS" denotes a system which is actually not - # MiNT. But MiNT is downward compatible to TOS, so this should - # be no problem. - atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; - atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; - *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit 0 ;; - milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit 0 ;; - hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit 0 ;; - *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit 0 ;; - sun3*:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mac68k:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvme68k:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - mvme88k:OpenBSD:*:*) - echo m88k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} - exit 0 ;; - RISC*:Mach:*:*) - echo mips-dec-mach_bsd4.3 - exit 0 ;; - RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} - exit 0 ;; - VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} - exit 0 ;; - 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} - exit 0 ;; - mips:*:*:UMIPS | mips:*:*:RISCos) - sed 's/^ //' << EOF >$dummy.c -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif - #if defined (host_mips) && defined (MIPSEB) - #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); - #endif - #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); - #endif - #endif - exit (-1); - } -EOF - eval $set_cc_for_build - $CC_FOR_BUILD $dummy.c -o $dummy \ - && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ - && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - echo mips-mips-riscos${UNAME_RELEASE} - exit 0 ;; - Motorola:PowerMAX_OS:*:*) - echo powerpc-motorola-powermax - exit 0 ;; - Night_Hawk:Power_UNIX:*:*) - echo powerpc-harris-powerunix - exit 0 ;; - m88k:CX/UX:7*:*) - echo m88k-harris-cxux7 - exit 0 ;; - m88k:*:4*:R4*) - echo m88k-motorola-sysv4 - exit 0 ;; - m88k:*:3*:R3*) - echo m88k-motorola-sysv3 - exit 0 ;; - AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] - then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] - then - echo m88k-dg-dgux${UNAME_RELEASE} - else - echo m88k-dg-dguxbcs${UNAME_RELEASE} - fi - else - echo i586-dg-dgux${UNAME_RELEASE} - fi - exit 0 ;; - M88*:DolphinOS:*:*) # DolphinOS (SVR3) - echo m88k-dolphin-sysv3 - exit 0 ;; - M88*:*:R3*:*) - # Delta 88k system running SVR3 - echo m88k-motorola-sysv3 - exit 0 ;; - XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) - echo m88k-tektronix-sysv3 - exit 0 ;; - Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) - echo m68k-tektronix-bsd - exit 0 ;; - *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` - exit 0 ;; - ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. - echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id - exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' - i*86:AIX:*:*) - echo i386-ibm-aix - exit 0 ;; - ia64:AIX:*:*) - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} - exit 0 ;; - *:AIX:2:3) - if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - sed 's/^ //' << EOF >$dummy.c - #include - - main() - { - if (!__power_pc()) - exit(1); - puts("powerpc-ibm-aix3.2.5"); - exit(0); - } -EOF - eval $set_cc_for_build - $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - echo rs6000-ibm-aix3.2.5 - elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then - echo rs6000-ibm-aix3.2.4 - else - echo rs6000-ibm-aix3.2 - fi - exit 0 ;; - *:AIX:*:[45]) - IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then - IBM_ARCH=rs6000 - else - IBM_ARCH=powerpc - fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` - else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} - fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} - exit 0 ;; - *:AIX:*:*) - echo rs6000-ibm-aix - exit 0 ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) - echo romp-ibm-bsd4.4 - exit 0 ;; - ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to - exit 0 ;; # report: romp-ibm BSD 4.3 - *:BOSX:*:*) - echo rs6000-bull-bosx - exit 0 ;; - DPX/2?00:B.O.S.:*:*) - echo m68k-bull-sysv3 - exit 0 ;; - 9000/[34]??:4.3bsd:1.*:*) - echo m68k-hp-bsd - exit 0 ;; - hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) - echo m68k-hp-bsd4.4 - exit 0 ;; - 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; - 9000/[678][0-9][0-9]) - case "${HPUX_REV}" in - 11.[0-9][0-9]) - if [ -x /usr/bin/getconf ]; then - sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - esac ;; - esac - fi ;; - esac - if [ "${HP_ARCH}" = "" ]; then - sed 's/^ //' << EOF >$dummy.c - - #define _HPUX_SOURCE - #include - #include - - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); - - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } -EOF - eval $set_cc_for_build - (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy` - if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi - rm -f $dummy.c $dummy - fi ;; - esac - echo ${HP_ARCH}-hp-hpux${HPUX_REV} - exit 0 ;; - ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} - exit 0 ;; - 3050*:HI-UX:*:*) - sed 's/^ //' << EOF >$dummy.c - #include - int - main () - { - long cpu = sysconf (_SC_CPU_VERSION); - /* The order matters, because CPU_IS_HP_MC68K erroneously returns - true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct - results, however. */ - if (CPU_IS_PA_RISC (cpu)) - { - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; - case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; - default: puts ("hppa-hitachi-hiuxwe2"); break; - } - } - else if (CPU_IS_HP_MC68K (cpu)) - puts ("m68k-hitachi-hiuxwe2"); - else puts ("unknown-hitachi-hiuxwe2"); - exit (0); - } -EOF - eval $set_cc_for_build - $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - echo unknown-hitachi-hiuxwe2 - exit 0 ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) - echo hppa1.1-hp-bsd - exit 0 ;; - 9000/8??:4.3bsd:*:*) - echo hppa1.0-hp-bsd - exit 0 ;; - *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) - echo hppa1.0-hp-mpeix - exit 0 ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) - echo hppa1.1-hp-osf - exit 0 ;; - hp8??:OSF1:*:*) - echo hppa1.0-hp-osf - exit 0 ;; - i*86:OSF1:*:*) - if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk - else - echo ${UNAME_MACHINE}-unknown-osf1 - fi - exit 0 ;; - parisc*:Lites*:*:*) - echo hppa1.1-hp-lites - exit 0 ;; - hppa*:OpenBSD:*:*) - echo hppa-unknown-openbsd - exit 0 ;; - C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) - echo c1-convex-bsd - exit 0 ;; - C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit 0 ;; - C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) - echo c34-convex-bsd - exit 0 ;; - C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) - echo c38-convex-bsd - exit 0 ;; - C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) - echo c4-convex-bsd - exit 0 ;; - CRAY*X-MP:*:*:*) - echo xmp-cray-unicos - exit 0 ;; - CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ - | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ - -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ - -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*T3D:*:*:*) - echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' - exit 0 ;; - CRAY-2:*:*:*) - echo cray2-cray-unicos - exit 0 ;; - F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit 0 ;; - hp300:OpenBSD:*:*) - echo m68k-unknown-openbsd${UNAME_RELEASE} - exit 0 ;; - i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} - exit 0 ;; - sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} - exit 0 ;; - *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} - exit 0 ;; - *:FreeBSD:*:*) - echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` - exit 0 ;; - *:OpenBSD:*:*) - echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` - exit 0 ;; - i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin - exit 0 ;; - i*:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit 0 ;; - i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 - exit 0 ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i386-pc-interix - exit 0 ;; - i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin - exit 0 ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit 0 ;; - prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` - exit 0 ;; - *:GNU:*:*) - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` - exit 0 ;; - i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix - exit 0 ;; - arm*:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux - exit 0 ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux - exit 0 ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux - exit 0 ;; - mips:Linux:*:*) - case `sed -n '/^byte/s/^.*: \(.*\) endian/\1/p' < /proc/cpuinfo` in - big) echo mips-${VENDOR}-linux && exit 0 ;; - little) echo mipsel-${VENDOR}-linux && exit 0 ;; - esac - case `sed -n '/^system type/s/^.*: \([^ ]*\).*/\1/p' < /proc/cpuinfo` in - SGI|sgi) echo mips-${VENDOR}-linux-gnu && exit 0 ;; - esac - ;; - ppc:Linux:*:*|ppc64:Linux:*:*) - echo powerpc-${VENDOR}-linux - exit 0 ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-gnu - exit 0 ;; - alpha:Linux:*:*) - case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in - EV5) UNAME_MACHINE=alphaev5 ;; - EV56) UNAME_MACHINE=alphaev56 ;; - PCA56) UNAME_MACHINE=alphapca56 ;; - PCA57) UNAME_MACHINE=alphapca56 ;; - EV6) UNAME_MACHINE=alphaev6 ;; - EV67) UNAME_MACHINE=alphaev67 ;; - EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null - if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi - echo ${UNAME_MACHINE}-${VENDOR}-linux${LIBC} - exit 0 ;; - parisc:Linux:*:* | hppa:Linux:*:*) - # Look for CPU level - case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-${VENDOR}-linux ;; - PA8*) echo hppa2.0-${VENDOR}-linux ;; - *) echo hppa-${VENDOR}-linux ;; - esac - exit 0 ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-${VENDOR}-linux - exit 0 ;; - s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux - exit 0 ;; - sh*:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux - exit 0 ;; - sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-${VENDOR}-linux - exit 0 ;; - x86_64:Linux:*:*) - echo x86_64-${VENDOR}-linux - exit 0 ;; - i*86:Linux:*:*) - # The BFD linker knows what the default object file format is, so - # first see if it will tell us. cd to the root directory to prevent - # problems with other programs or directories called `ld' in the path. - ld_supported_targets=`cd /; ld --help 2>&1 \ - | sed -ne '/supported targets:/!d - s/[ ][ ]*/ /g - s/.*supported targets: *// - s/ .*// - p'` - case "$ld_supported_targets" in - elf32-i386) - TENTATIVE="${UNAME_MACHINE}-${VENDOR}-linux" - ;; - a.out-i386-linux) - echo "${UNAME_MACHINE}-${VENDOR}-linuxaout" - exit 0 ;; - coff-i386) - echo "${UNAME_MACHINE}-${VENDOR}-linuxcoff" - exit 0 ;; - "") - # Either a pre-BFD a.out linker (linuxoldld) or - # one that does not give us useful --help. - echo "${UNAME_MACHINE}-${VENDOR}-linuxoldld" - exit 0 ;; - esac - # Determine whether the default compiler is a.out or elf - cat >$dummy.c < -#ifdef __cplusplus -#include /* for printf() prototype */ - int main (int argc, char *argv[]) { -#else - int main (argc, argv) int argc; char *argv[]; { -#endif -#ifdef __ELF__ -# ifdef __GLIBC__ -# if __GLIBC__ >= 2 - printf ("%s-${VENDOR}-linux\n", argv[1]); -# else - printf ("%s-${VENDOR}-linuxlibc1\n", argv[1]); -# endif -# else - printf ("%s-${VENDOR}-linuxlibc1\n", argv[1]); -# endif -#else - printf ("%s-${VENDOR}-linuxaout\n", argv[1]); -#endif - return 0; -} -EOF - eval $set_cc_for_build - $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm -f $dummy.c $dummy && exit 0 - rm -f $dummy.c $dummy - test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 - ;; - i*86:DYNIX/ptx:4*:*) - # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. - # earlier versions are messed up and put the nodename in both - # sysname and nodename. - echo i386-sequent-sysv4 - exit 0 ;; - i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, - # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} - exit 0 ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` - if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} - else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} - fi - exit 0 ;; - i*86:*:5:[78]*) - case `/bin/uname -X | grep "^Machine"` in - *486*) UNAME_MACHINE=i486 ;; - *Pentium) UNAME_MACHINE=i586 ;; - *Pent*|*Celeron) UNAME_MACHINE=i686 ;; - esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} - exit 0 ;; - i*86:*:3.2:*) - if test -f /usr/options/cb.name; then - UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then - UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` - (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 - (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ - && UNAME_MACHINE=i586 - (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ - && UNAME_MACHINE=i686 - (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ - && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL - else - echo ${UNAME_MACHINE}-pc-sysv32 - fi - exit 0 ;; - i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp - exit 0 ;; - pc:*:*:*) - # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i386. - echo i386-pc-msdosdjgpp - exit 0 ;; - Intel:Mach:3*:*) - echo i386-pc-mach3 - exit 0 ;; - paragon:*:*:*) - echo i860-intel-osf1 - exit 0 ;; - i860:*:4.*:*) # i860-SVR4 - if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 - else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 - fi - exit 0 ;; - mini*:CTIX:SYS*5:*) - # "miniframe" - echo m68010-convergent-sysv - exit 0 ;; - M68*:*:R3V[567]*:*) - test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; - 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0) - OS_REL='' - test -r /etc/.relid \ - && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4.3${OS_REL} && exit 0 - /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; - 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && echo i486-ncr-sysv4 && exit 0 ;; - m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - mc68030:UNIX_System_V:4.*:*) - echo m68k-atari-sysv4 - exit 0 ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} - exit 0 ;; - SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} - exit 0 ;; - RM*:ReliantUNIX-*:*:*) - echo mips-sni-sysv4 - exit 0 ;; - RM*:SINIX-*:*:*) - echo mips-sni-sysv4 - exit 0 ;; - *:SINIX-*:*:*) - if uname -p 2>/dev/null >/dev/null ; then - UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 - else - echo ns32k-sni-sysv - fi - exit 0 ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit 0 ;; - *:UNIX_System_V:4*:FTX*) - # From Gerald Hewes . - # How about differentiating between stratus architectures? -djm - echo hppa1.1-stratus-sysv4 - exit 0 ;; - *:*:*:FTX*) - # From seanf@swdc.stratus.com. - echo i860-stratus-sysv4 - exit 0 ;; - *:VOS:*:*) - # From Paul.Green@stratus.com. - echo hppa1.1-stratus-vos - exit 0 ;; - mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} - exit 0 ;; - news*:NEWS-OS:6*:*) - echo mips-sony-newsos6 - exit 0 ;; - R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) - if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} - else - echo mips-unknown-sysv${UNAME_RELEASE} - fi - exit 0 ;; - BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. - echo powerpc-be-beos - exit 0 ;; - BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. - echo powerpc-apple-beos - exit 0 ;; - BePC:BeOS:*:*) # BeOS running on Intel PC compatible. - echo i586-pc-beos - exit 0 ;; - SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} - exit 0 ;; - SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} - exit 0 ;; - Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} - exit 0 ;; - *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} - exit 0 ;; - *:Darwin:*:*) - echo `uname -p`-apple-darwin${UNAME_RELEASE} - exit 0 ;; - *:procnto*:*:* | *:QNX:[0123456789]*:*) - if test "${UNAME_MACHINE}" = "x86pc"; then - UNAME_MACHINE=pc - fi - echo `uname -p`-${UNAME_MACHINE}-nto-qnx - exit 0 ;; - *:QNX:*:4*) - echo i386-pc-qnx - exit 0 ;; - NSR-[KW]:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} - exit 0 ;; - *:NonStop-UX:*:*) - echo mips-compaq-nonstopux - exit 0 ;; - BS2000:POSIX*:*:*) - echo bs2000-siemens-sysv - exit 0 ;; - DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} - exit 0 ;; - *:Plan9:*:*) - # "uname -m" is not consistent, so use $cputype instead. 386 - # is converted to i386 for consistency with other x86 - # operating systems. - if test "$cputype" = "386"; then - UNAME_MACHINE=i386 - else - UNAME_MACHINE="$cputype" - fi - echo ${UNAME_MACHINE}-unknown-plan9 - exit 0 ;; - i*86:OS/2:*:*) - # If we were able to find `uname', then EMX Unix compatibility - # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx - exit 0 ;; - *:TOPS-10:*:*) - echo pdp10-unknown-tops10 - exit 0 ;; - *:TENEX:*:*) - echo pdp10-unknown-tenex - exit 0 ;; - KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) - echo pdp10-dec-tops20 - exit 0 ;; - XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) - echo pdp10-xkl-tops20 - exit 0 ;; - *:TOPS-20:*:*) - echo pdp10-unknown-tops20 - exit 0 ;; - *:ITS:*:*) - echo pdp10-unknown-its - exit 0 ;; - i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop - exit 0 ;; -esac - -#echo '(No uname command or uname output not recognized.)' 1>&2 -#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 - -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -eval $set_cc_for_build -$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0 -rm -f $dummy.c $dummy - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit 0 ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit 0 ;; - c34*) - echo c34-convex-bsd - exit 0 ;; - c38*) - echo c38-convex-bsd - exit 0 ;; - c4*) - echo c4-convex-bsd - exit 0 ;; - esac -fi - -cat >&2 < in order to provide the needed -information to handle your system. - -config.guess timestamp = $timestamp - -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null` - -hostinfo = `(hostinfo) 2>/dev/null` -/bin/universe = `(/bin/universe) 2>/dev/null` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` -/bin/arch = `(/bin/arch) 2>/dev/null` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` - -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} -EOF - -exit 1 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/config/config.sub b/config/config.sub deleted file mode 100755 index 83f4b015..00000000 --- a/config/config.sub +++ /dev/null @@ -1,1410 +0,0 @@ -#! /bin/sh -# Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -# Free Software Foundation, Inc. - -timestamp='2001-08-13' - -# This file is (in principle) common to ALL GNU software. -# The presence of a machine in this file suggests that SOME GNU software -# can handle that machine. It does not imply ALL GNU software can. -# -# This file 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. -# -# This program 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 this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Please send patches to . -# -# Configuration subroutine to validate and canonicalize a configuration type. -# Supply the specified configuration type as an argument. -# If it is invalid, we print an error message on stderr and exit with code 1. -# Otherwise, we print the canonical config type on stdout and succeed. - -# This file is supposed to be the same for all GNU packages -# and recognize all the CPU types, system types and aliases -# that are meaningful with *any* GNU software. -# Each package is responsible for reporting which valid configurations -# it does not support. The user should be able to distinguish -# a failure to support a valid configuration from a meaningless -# configuration. - -# The goal of this file is to map all the various variations of a given -# machine specification into a single specification in the form: -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or in some cases, the newer four-part form: -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# It is wrong to echo any other type of specification. - -me=`echo "$0" | sed -e 's,.*/,,'` - -usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS - -Canonicalize a configuration name. - -Operation modes: - -h, --help print this help, then exit - -t, --time-stamp print date of last modification, then exit - -v, --version print version number, then exit - -Report bugs and patches to ." - -version="\ -GNU config.sub ($timestamp) - -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 -Free Software Foundation, Inc. - -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." - -help=" -Try \`$me --help' for more information." - -# Parse command line -while test $# -gt 0 ; do - case $1 in - --time-stamp | --time* | -t ) - echo "$timestamp" ; exit 0 ;; - --version | -v ) - echo "$version" ; exit 0 ;; - --help | --h* | -h ) - echo "$usage"; exit 0 ;; - -- ) # Stop option processing - shift; break ;; - - ) # Use stdin as input. - break ;; - -* ) - echo "$me: invalid option $1$help" - exit 1 ;; - - *local*) - # First pass through any local machine types. - echo $1 - exit 0;; - - * ) - break ;; - esac -done - -case $# in - 0) echo "$me: missing argument$help" >&2 - exit 1;; - 1) ;; - *) echo "$me: too many arguments$help" >&2 - exit 1;; -esac - -# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). -# Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` -case $maybe_os in - nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-*) - os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` - ;; - *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` - else os=; fi - ;; -esac - -### Let's recognize common machines as not being operating systems so -### that things like config.sub decstation-3100 work. We also -### recognize some manufacturers as not being operating systems, so we -### can provide default operating systems below. -case $os in - -sun*os*) - # Prevent following clause from handling this invalid input. - ;; - -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ - -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ - -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ - -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ - -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ - -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis) - os= - basic_machine=$1 - ;; - -sim | -cisco | -oki | -wec | -winbond) - os= - basic_machine=$1 - ;; - -scout) - ;; - -wrs) - os=-vxworks - basic_machine=$1 - ;; - -chorusos*) - os=-chorusos - basic_machine=$1 - ;; - -chorusrdb) - os=-chorusrdb - basic_machine=$1 - ;; - -hiux*) - os=-hiuxwe2 - ;; - -sco5) - os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco4) - os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2.[4-9]*) - os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco3.2v[4-9]*) - # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -sco*) - os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -isc) - os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -clix*) - basic_machine=clipper-intergraph - ;; - -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` - ;; - -lynx*) - os=-lynxos - ;; - -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` - ;; - -psos*) - os=-psos - ;; - -mint | -mint[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; -esac - -# Decode aliases for certain CPU-COMPANY combinations. -case $basic_machine in - # Recognize the basic CPU types without company name. - # Some are omitted here because they have special meanings below. - 1750a | 580 \ - | a29k \ - | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ - | c4x | clipper \ - | d10v | d30v | dsp16xx \ - | fr30 \ - | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | i370 | i860 | i960 | ia64 \ - | m32r | m68000 | m68k | m88k | mcore \ - | mips16 | mips64 | mips64el | mips64orion | mips64orionel \ - | mips64vr4100 | mips64vr4100el | mips64vr4300 \ - | mips64vr4300el | mips64vr5000 | mips64vr5000el \ - | mipsbe | mipsel | mipsle | mipstx39 | mipstx39el \ - | mn10200 | mn10300 \ - | ns16k | ns32k \ - | openrisc \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ - | pyramid \ - | s390 | s390x \ - | sh | sh[34] | sh[34]eb | shbe | shle \ - | sparc | sparc64 | sparclet | sparclite | sparcv9 | sparcv9b \ - | strongarm \ - | tahoe | thumb | tic80 | tron \ - | v850 \ - | we32k \ - | x86 | xscale \ - | z8k) - basic_machine=$basic_machine-unknown - ;; - m6811 | m68hc11 | m6812 | m68hc12) - # Motorola 68HC11/12. - basic_machine=$basic_machine-unknown - os=-none - ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) - ;; - - # We use `pc' rather than `unknown' - # because (1) that's what they normally are, and - # (2) the word "unknown" tends to confuse beginning users. - i*86 | x86_64) - basic_machine=$basic_machine-pc - ;; - # Object if more than one company name word. - *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; - # Recognize the basic CPU types with company name. - 580-* \ - | a29k-* \ - | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alphapca5[67]-* | arc-* \ - | arm-* | armbe-* | armle-* | armv*-* \ - | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c54x-* \ - | clipper-* | cray2-* | cydra-* \ - | d10v-* | d30v-* \ - | elxsi-* \ - | f30[01]-* | f700-* | fr30-* | fx80-* \ - | h8300-* | h8500-* \ - | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | i*86-* | i860-* | i960-* | ia64-* \ - | m32r-* \ - | m68000-* | m680[01234]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | mcore-* \ - | mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \ - | mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipsel-* \ - | mipsle-* | mipstx39-* | mipstx39el-* \ - | none-* | np1-* | ns16k-* | ns32k-* \ - | orion-* \ - | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ - | pyramid-* \ - | romp-* | rs6000-* \ - | s390-* | s390x-* \ - | sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* \ - | sparc-* | sparc64-* | sparc86x-* | sparclite-* \ - | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* \ - | t3e-* | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \ - | v850-* | vax-* \ - | we32k-* \ - | x86-* | x86_64-* | xmp-* | xps100-* | xscale-* \ - | ymp-* \ - | z8k-*) - ;; - # Recognize the various machine names and aliases which stand - # for a CPU type and a company and sometimes even an OS. - 386bsd) - basic_machine=i386-unknown - os=-bsd - ;; - 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) - basic_machine=m68000-att - ;; - 3b*) - basic_machine=we32k-att - ;; - a29khif) - basic_machine=a29k-amd - os=-udi - ;; - adobe68k) - basic_machine=m68010-adobe - os=-scout - ;; - alliant | fx80) - basic_machine=fx80-alliant - ;; - altos | altos3068) - basic_machine=m68k-altos - ;; - am29k) - basic_machine=a29k-none - os=-bsd - ;; - amdahl) - basic_machine=580-amdahl - os=-sysv - ;; - amiga | amiga-*) - basic_machine=m68k-unknown - ;; - amigaos | amigados) - basic_machine=m68k-unknown - os=-amigaos - ;; - amigaunix | amix) - basic_machine=m68k-unknown - os=-sysv4 - ;; - apollo68) - basic_machine=m68k-apollo - os=-sysv - ;; - apollo68bsd) - basic_machine=m68k-apollo - os=-bsd - ;; - aux) - basic_machine=m68k-apple - os=-aux - ;; - balance) - basic_machine=ns32k-sequent - os=-dynix - ;; - convex-c1) - basic_machine=c1-convex - os=-bsd - ;; - convex-c2) - basic_machine=c2-convex - os=-bsd - ;; - convex-c32) - basic_machine=c32-convex - os=-bsd - ;; - convex-c34) - basic_machine=c34-convex - os=-bsd - ;; - convex-c38) - basic_machine=c38-convex - os=-bsd - ;; - cray | ymp) - basic_machine=ymp-cray - os=-unicos - ;; - cray2) - basic_machine=cray2-cray - os=-unicos - ;; - [cjt]90) - basic_machine=${basic_machine}-cray - os=-unicos - ;; - crds | unos) - basic_machine=m68k-crds - ;; - cris | cris-* | etrax*) - basic_machine=cris-axis - ;; - da30 | da30-*) - basic_machine=m68k-da30 - ;; - decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) - basic_machine=mips-dec - ;; - delta | 3300 | motorola-3300 | motorola-delta \ - | 3300-motorola | delta-motorola) - basic_machine=m68k-motorola - ;; - delta88) - basic_machine=m88k-motorola - os=-sysv3 - ;; - dpx20 | dpx20-*) - basic_machine=rs6000-bull - os=-bosx - ;; - dpx2* | dpx2*-bull) - basic_machine=m68k-bull - os=-sysv3 - ;; - ebmon29k) - basic_machine=a29k-amd - os=-ebmon - ;; - elxsi) - basic_machine=elxsi-elxsi - os=-bsd - ;; - encore | umax | mmax) - basic_machine=ns32k-encore - ;; - es1800 | OSE68k | ose68k | ose | OSE) - basic_machine=m68k-ericsson - os=-ose - ;; - fx2800) - basic_machine=i860-alliant - ;; - genix) - basic_machine=ns32k-ns - ;; - gmicro) - basic_machine=tron-gmicro - os=-sysv - ;; - go32) - basic_machine=i386-pc - os=-go32 - ;; - h3050r* | hiux*) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - h8300hms) - basic_machine=h8300-hitachi - os=-hms - ;; - h8300xray) - basic_machine=h8300-hitachi - os=-xray - ;; - h8500hms) - basic_machine=h8500-hitachi - os=-hms - ;; - harris) - basic_machine=m88k-harris - os=-sysv3 - ;; - hp300-*) - basic_machine=m68k-hp - ;; - hp300bsd) - basic_machine=m68k-hp - os=-bsd - ;; - hp300hpux) - basic_machine=m68k-hp - os=-hpux - ;; - hp3k9[0-9][0-9] | hp9[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k2[0-9][0-9] | hp9k31[0-9]) - basic_machine=m68000-hp - ;; - hp9k3[2-9][0-9]) - basic_machine=m68k-hp - ;; - hp9k6[0-9][0-9] | hp6[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hp9k7[0-79][0-9] | hp7[0-79][0-9]) - basic_machine=hppa1.1-hp - ;; - hp9k78[0-9] | hp78[0-9]) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) - # FIXME: really hppa2.0-hp - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][13679] | hp8[0-9][13679]) - basic_machine=hppa1.1-hp - ;; - hp9k8[0-9][0-9] | hp8[0-9][0-9]) - basic_machine=hppa1.0-hp - ;; - hppa-next) - os=-nextstep3 - ;; - hppaosf) - basic_machine=hppa1.1-hp - os=-osf - ;; - hppro) - basic_machine=hppa1.1-hp - os=-proelf - ;; - i370-ibm* | ibm*) - basic_machine=i370-ibm - ;; -# I'm not sure what "Sysv32" means. Should this be sysv3.2? - i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv32 - ;; - i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv4 - ;; - i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-sysv - ;; - i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` - os=-solaris2 - ;; - i386mach) - basic_machine=i386-mach - os=-mach - ;; - i386-vsta | vsta) - basic_machine=i386-unknown - os=-vsta - ;; - iris | iris4d) - basic_machine=mips-sgi - case $os in - -irix*) - ;; - *) - os=-irix4 - ;; - esac - ;; - isi68 | isi) - basic_machine=m68k-isi - os=-sysv - ;; - m88k-omron*) - basic_machine=m88k-omron - ;; - magnum | m3230) - basic_machine=mips-mips - os=-sysv - ;; - merlin) - basic_machine=ns32k-utek - os=-sysv - ;; - mingw32) - basic_machine=i386-pc - os=-mingw32 - ;; - miniframe) - basic_machine=m68000-convergent - ;; - *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) - basic_machine=m68k-atari - os=-mint - ;; - mipsel*-linux*) - basic_machine=mipsel-unknown - ;; - mips*-linux*) - basic_machine=mips-unknown - ;; - mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` - ;; - mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown - ;; - mmix*) - basic_machine=mmix-knuth - os=-mmixware - ;; - monitor) - basic_machine=m68k-rom68k - os=-coff - ;; - msdos) - basic_machine=i386-pc - os=-msdos - ;; - mvs) - basic_machine=i370-ibm - os=-mvs - ;; - ncr3000) - basic_machine=i486-ncr - os=-sysv4 - ;; - netbsd386) - basic_machine=i386-unknown - os=-netbsd - ;; - netwinder) - basic_machine=armv4l-rebel - os=-linux - ;; - news | news700 | news800 | news900) - basic_machine=m68k-sony - os=-newsos - ;; - news1000) - basic_machine=m68030-sony - os=-newsos - ;; - news-3600 | risc-news) - basic_machine=mips-sony - os=-newsos - ;; - necv70) - basic_machine=v70-nec - os=-sysv - ;; - next | m*-next ) - basic_machine=m68k-next - case $os in - -nextstep* ) - ;; - -ns2*) - os=-nextstep2 - ;; - *) - os=-nextstep3 - ;; - esac - ;; - nh3000) - basic_machine=m68k-harris - os=-cxux - ;; - nh[45]000) - basic_machine=m88k-harris - os=-cxux - ;; - nindy960) - basic_machine=i960-intel - os=-nindy - ;; - mon960) - basic_machine=i960-intel - os=-mon960 - ;; - nonstopux) - basic_machine=mips-compaq - os=-nonstopux - ;; - np1) - basic_machine=np1-gould - ;; - nsr-tandem) - basic_machine=nsr-tandem - ;; - op50n-* | op60c-*) - basic_machine=hppa1.1-oki - os=-proelf - ;; - OSE68000 | ose68000) - basic_machine=m68000-ericsson - os=-ose - ;; - os68k) - basic_machine=m68k-none - os=-os68k - ;; - pa-hitachi) - basic_machine=hppa1.1-hitachi - os=-hiuxwe2 - ;; - paragon) - basic_machine=i860-intel - os=-osf - ;; - pbd) - basic_machine=sparc-tti - ;; - pbb) - basic_machine=m68k-tti - ;; - pc532 | pc532-*) - basic_machine=ns32k-pc532 - ;; - pentium | p5 | k5 | k6 | nexgen) - basic_machine=i586-pc - ;; - pentiumpro | p6 | 6x86 | athlon) - basic_machine=i686-pc - ;; - pentiumii | pentium2) - basic_machine=i686-pc - ;; - pentium-* | p5-* | k5-* | k6-* | nexgen-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pentiumii-* | pentium2-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - pn) - basic_machine=pn-gould - ;; - power) basic_machine=power-ibm - ;; - ppc) basic_machine=powerpc-unknown - ;; - ppc64) basic_machine=powerpc-unknown - ;; - ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppcle | powerpclittle | ppc-le | powerpc-little) - basic_machine=powerpcle-unknown - ;; - ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64) basic_machine=powerpc64-unknown - ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) - basic_machine=powerpc64le-unknown - ;; - ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` - ;; - ps2) - basic_machine=i386-ibm - ;; - pw32) - basic_machine=i586-unknown - os=-pw32 - ;; - rom68k) - basic_machine=m68k-rom68k - os=-coff - ;; - rm[46]00) - basic_machine=mips-siemens - ;; - rtpc | rtpc-*) - basic_machine=romp-ibm - ;; - sa29200) - basic_machine=a29k-amd - os=-udi - ;; - sequent) - basic_machine=i386-sequent - ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; - sparclite-wrs) - basic_machine=sparclite-wrs - os=-vxworks - ;; - sps7) - basic_machine=m68k-bull - os=-sysv2 - ;; - spur) - basic_machine=spur-unknown - ;; - st2000) - basic_machine=m68k-tandem - ;; - stratus) - basic_machine=i860-stratus - os=-sysv4 - ;; - sun2) - basic_machine=m68000-sun - ;; - sun2os3) - basic_machine=m68000-sun - os=-sunos3 - ;; - sun2os4) - basic_machine=m68000-sun - os=-sunos4 - ;; - sun3os3) - basic_machine=m68k-sun - os=-sunos3 - ;; - sun3os4) - basic_machine=m68k-sun - os=-sunos4 - ;; - sun4os3) - basic_machine=sparc-sun - os=-sunos3 - ;; - sun4os4) - basic_machine=sparc-sun - os=-sunos4 - ;; - sun4sol2) - basic_machine=sparc-sun - os=-solaris2 - ;; - sun3 | sun3-*) - basic_machine=m68k-sun - ;; - sun4) - basic_machine=sparc-sun - ;; - sun386 | sun386i | roadrunner) - basic_machine=i386-sun - ;; - sv1) - basic_machine=sv1-cray - os=-unicos - ;; - symmetry) - basic_machine=i386-sequent - os=-dynix - ;; - t3e) - basic_machine=t3e-cray - os=-unicos - ;; - tic54x | c54x*) - basic_machine=tic54x-unknown - os=-coff - ;; - tx39) - basic_machine=mipstx39-unknown - ;; - tx39el) - basic_machine=mipstx39el-unknown - ;; - tower | tower-32) - basic_machine=m68k-ncr - ;; - udi29k) - basic_machine=a29k-amd - os=-udi - ;; - ultra3) - basic_machine=a29k-nyu - os=-sym1 - ;; - v810 | necv810) - basic_machine=v810-nec - os=-none - ;; - vaxv) - basic_machine=vax-dec - os=-sysv - ;; - vms) - basic_machine=vax-dec - os=-vms - ;; - vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; - vxworks960) - basic_machine=i960-wrs - os=-vxworks - ;; - vxworks68) - basic_machine=m68k-wrs - os=-vxworks - ;; - vxworks29k) - basic_machine=a29k-wrs - os=-vxworks - ;; - w65*) - basic_machine=w65-wdc - os=-none - ;; - w89k-*) - basic_machine=hppa1.1-winbond - os=-proelf - ;; - windows32) - basic_machine=i386-pc - os=-windows32-msvcrt - ;; - xmp) - basic_machine=xmp-cray - os=-unicos - ;; - xps | xps100) - basic_machine=xps100-honeywell - ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - none) - basic_machine=none-none - os=-none - ;; - -# Here we handle the default manufacturer of certain CPU types. It is in -# some cases the only manufacturer, in others, it is the most popular. - w89k) - basic_machine=hppa1.1-winbond - ;; - op50n) - basic_machine=hppa1.1-oki - ;; - op60c) - basic_machine=hppa1.1-oki - ;; - mips) - case $os in - linux*) - basic_machine=mips-unknown - ;; - *) - basic_machine=mips-mips - ;; - esac - ;; - romp) - basic_machine=romp-ibm - ;; - rs6000) - basic_machine=rs6000-ibm - ;; - vax) - basic_machine=vax-dec - ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; - pdp11) - basic_machine=pdp11-dec - ;; - we32k) - basic_machine=we32k-att - ;; - sh3 | sh4 | sh3eb | sh4eb) - basic_machine=sh-unknown - ;; - sparc | sparcv9 | sparcv9b) - basic_machine=sparc-sun - ;; - cydra) - basic_machine=cydra-cydrome - ;; - orion) - basic_machine=orion-highlevel - ;; - orion105) - basic_machine=clipper-highlevel - ;; - mac | mpw | mac-mpw) - basic_machine=m68k-apple - ;; - pmac | pmac-mpw) - basic_machine=powerpc-apple - ;; - c4x*) - basic_machine=c4x-none - os=-coff - ;; - *-unknown) - # Make sure to match an already-canonicalized machine name. - ;; - *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 - exit 1 - ;; -esac - -# Here we canonicalize certain aliases for manufacturers. -case $basic_machine in - *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` - ;; - *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` - ;; - *) - ;; -esac - -# Decode manufacturer-specific aliases for certain operating systems. - -if [ x"$os" != x"" ] -then -case $os in - # First match some system type aliases - # that might get confused with valid system types. - # -solaris* is a basic system type, with this one exception. - -solaris1 | -solaris1.*) - os=`echo $os | sed -e 's|solaris1|sunos4|'` - ;; - -solaris) - os=-solaris2 - ;; - -svr4*) - os=-sysv4 - ;; - -unixware*) - os=-sysv4.2uw - ;; - -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - # First accept the basic system types. - # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. - # -sysv* is not here because it comes later, after sysvr4. - -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ - | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* \ - | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ - | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ - | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ - | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* \ - | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux* | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ - | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ - | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos*) - # Remember, each alternative MUST END IN *, to match a version number. - ;; - -qnx*) - case $basic_machine in - x86-* | i*86-*) - ;; - *) - os=-nto$os - ;; - esac - ;; - -nto*) - os=-nto-qnx - ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ - | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) - ;; - -mac*) - os=`echo $os | sed -e 's|mac|macos|'` - ;; - -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` - ;; - -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` - ;; - -opened*) - os=-openedition - ;; - -wince*) - os=-wince - ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; - -utek*) - os=-bsd - ;; - -dynix*) - os=-bsd - ;; - -acis*) - os=-aos - ;; - -386bsd) - os=-bsd - ;; - -ctix* | -uts*) - os=-sysv - ;; - -ns2 ) - os=-nextstep2 - ;; - -nsk*) - os=-nsk - ;; - # Preserve the version number of sinix5. - -sinix5.*) - os=`echo $os | sed -e 's|sinix|sysv|'` - ;; - -sinix*) - os=-sysv4 - ;; - -triton*) - os=-sysv3 - ;; - -oss*) - os=-sysv3 - ;; - -svr4) - os=-sysv4 - ;; - -svr3) - os=-sysv3 - ;; - -sysvr4) - os=-sysv4 - ;; - # This must come after -sysvr4. - -sysv*) - ;; - -ose*) - os=-ose - ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint - ;; - -none) - ;; - *) - # Get rid of the `-' at the beginning of $os. - os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 - exit 1 - ;; -esac -else - -# Here we handle the default operating systems that come with various machines. -# The value should be what the vendor currently ships out the door with their -# machine or put another way, the most popular os provided with the machine. - -# Note that if you're going to try to match "-MANUFACTURER" here (say, -# "-sun"), then you have to tell the case statement up towards the top -# that MANUFACTURER isn't an operating system. Otherwise, code above -# will signal an error saying that MANUFACTURER isn't an operating -# system, and we'll never get to this point. - -case $basic_machine in - *-acorn) - os=-riscix1.2 - ;; - arm*-rebel) - os=-linux - ;; - arm*-semi) - os=-aout - ;; - pdp10-*) - os=-tops20 - ;; - pdp11-*) - os=-none - ;; - *-dec | vax-*) - os=-ultrix4.2 - ;; - m68*-apollo) - os=-domain - ;; - i386-sun) - os=-sunos4.0.2 - ;; - m68000-sun) - os=-sunos3 - # This also exists in the configure program, but was not the - # default. - # os=-sunos4 - ;; - m68*-cisco) - os=-aout - ;; - mips*-cisco) - os=-elf - ;; - mips*-*) - os=-elf - ;; - *-tti) # must be before sparc entry or we get the wrong os. - os=-sysv3 - ;; - sparc-* | *-sun) - os=-sunos4.1.1 - ;; - *-be) - os=-beos - ;; - *-ibm) - os=-aix - ;; - *-wec) - os=-proelf - ;; - *-winbond) - os=-proelf - ;; - *-oki) - os=-proelf - ;; - *-hp) - os=-hpux - ;; - *-hitachi) - os=-hiux - ;; - i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) - os=-sysv - ;; - *-cbm) - os=-amigaos - ;; - *-dg) - os=-dgux - ;; - *-dolphin) - os=-sysv3 - ;; - m68k-ccur) - os=-rtu - ;; - m88k-omron*) - os=-luna - ;; - *-next ) - os=-nextstep - ;; - *-sequent) - os=-ptx - ;; - *-crds) - os=-unos - ;; - *-ns) - os=-genix - ;; - i370-*) - os=-mvs - ;; - *-next) - os=-nextstep3 - ;; - *-gould) - os=-sysv - ;; - *-highlevel) - os=-bsd - ;; - *-encore) - os=-bsd - ;; - *-sgi) - os=-irix - ;; - *-siemens) - os=-sysv4 - ;; - *-masscomp) - os=-rtu - ;; - f30[01]-fujitsu | f700-fujitsu) - os=-uxpv - ;; - *-rom68k) - os=-coff - ;; - *-*bug) - os=-coff - ;; - *-apple) - os=-macos - ;; - *-atari*) - os=-mint - ;; - *) - os=-none - ;; -esac -fi - -# Here we handle the case where we know the os, and the CPU type, but not the -# manufacturer. We pick the logical manufacturer. -vendor=unknown -case $basic_machine in - *-unknown) - case $os in - -riscix*) - vendor=acorn - ;; - -sunos*) - vendor=sun - ;; - -aix*) - vendor=ibm - ;; - -beos*) - vendor=be - ;; - -hpux*) - vendor=hp - ;; - -mpeix*) - vendor=hp - ;; - -hiux*) - vendor=hitachi - ;; - -unos*) - vendor=crds - ;; - -dgux*) - vendor=dg - ;; - -luna*) - vendor=omron - ;; - -genix*) - vendor=ns - ;; - -mvs* | -opened*) - vendor=ibm - ;; - -ptx*) - vendor=sequent - ;; - -vxsim* | -vxworks*) - vendor=wrs - ;; - -aux*) - vendor=apple - ;; - -hms*) - vendor=hitachi - ;; - -mpw* | -macos*) - vendor=apple - ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - vendor=atari - ;; - -vos*) - vendor=stratus - ;; - esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` - ;; -esac - -echo $basic_machine$os -exit 0 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "timestamp='" -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "'" -# End: diff --git a/config/depcomp b/config/depcomp deleted file mode 100755 index 65899658..00000000 --- a/config/depcomp +++ /dev/null @@ -1,411 +0,0 @@ -#! /bin/sh - -# depcomp - compile a program generating dependencies as side-effects -# Copyright 1999, 2000 Free Software Foundation, Inc. - -# This program 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, or (at your option) -# any later version. - -# This program 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 this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Originally written by Alexandre Oliva . - -if test -z "$depmode" || test -z "$source" || test -z "$object"; then - echo "depcomp: Variables source, object and depmode must be set" 1>&2 - exit 1 -fi -# `libtool' can also be set to `yes' or `no'. - -depfile=${depfile-`echo "$object" | sed 's,\([^/]*\)$,.deps/\1,;s/\.\([^.]*\)$/.P\1/'`} -tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} - -rm -f "$tmpdepfile" - -# Some modes work just like other modes, but use different flags. We -# parameterize here, but still list the modes in the big case below, -# to make depend.m4 easier to write. Note that we *cannot* use a case -# here, because this file can only contain one case statement. -if test "$depmode" = hp; then - # HP compiler uses -M and no extra arg. - gccflag=-M - depmode=gcc -fi - -if test "$depmode" = dashXmstdout; then - # This is just like dashmstdout with a different argument. - dashmflag=-xM - depmode=dashmstdout -fi - -case "$depmode" in -gcc3) -## gcc 3 implements dependency tracking that does exactly what -## we want. Yay! Note: for some reason libtool 1.4 doesn't like -## it if -MD -MP comes after the -MF stuff. Hmm. - "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - mv "$tmpdepfile" "$depfile" - ;; - -gcc) -## There are various ways to get dependency output from gcc. Here's -## why we pick this rather obscure method: -## - Don't want to use -MD because we'd like the dependencies to end -## up in a subdir. Having to rename by hand is ugly. -## (We might end up doing this anyway to support other compilers.) -## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like -## -MM, not -M (despite what the docs say). -## - Using -M directly means running the compiler twice (even worse -## than renaming). - if test -z "$gccflag"; then - gccflag=-MD, - fi - "$@" -Wp,"$gccflag$tmpdepfile" - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - echo "$object : \\" > "$depfile" - alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz -## The second -e expression handles DOS-style file names with drive letters. - sed -e 's/^[^:]*: / /' \ - -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" -## This next piece of magic avoids the `deleted header file' problem. -## The problem is that when a header file which appears in a .P file -## is deleted, the dependency causes make to die (because there is -## typically no way to rebuild the header). We avoid this by adding -## dummy dependencies for each header file. Too bad gcc doesn't do -## this for us directly. - tr ' ' ' -' < "$tmpdepfile" | -## Some versions of gcc put a space before the `:'. On the theory -## that the space means something, we add a space to the output as -## well. -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -hp) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -sgi) - if test "$libtool" = yes; then - "$@" "-Wp,-MDupdate,$tmpdepfile" - else - "$@" -MDupdate "$tmpdepfile" - fi - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - - if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files - echo "$object : \\" > "$depfile" - - # Clip off the initial element (the dependent). Don't try to be - # clever and replace this with sed code, as IRIX sed won't handle - # lines with more than a fixed number of characters (4096 in - # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; - # the IRIX cc adds comments like `#:fec' to the end of the - # dependency line. - tr ' ' ' -' < "$tmpdepfile" \ - | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ - tr ' -' ' ' >> $depfile - echo >> $depfile - - # The second pass generates a dummy entry for each header file. - tr ' ' ' -' < "$tmpdepfile" \ - | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ - >> $depfile - else - # The sourcefile does not contain any dependencies, so just - # store a dummy comment line, to avoid errors with the Makefile - # "include basename.Plo" scheme. - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" - ;; - -aix) - # The C for AIX Compiler uses -M and outputs the dependencies - # in a .u file. This file always lives in the current directory. - # Also, the AIX compiler puts `$object:' at the start of each line; - # $object doesn't have directory information. - stripped=`echo "$object" | sed -e 's,^.*/,,' -e 's/\(.*\)\..*$/\1/'` - tmpdepfile="$stripped.u" - outname="$stripped.o" - if test "$libtool" = yes; then - "$@" -Wc,-M - else - "$@" -M - fi - - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - - if test -f "$tmpdepfile"; then - # Each line is of the form `foo.o: dependent.h'. - # Do two passes, one to just change these to - # `$object: dependent.h' and one to simply `dependent.h:'. - sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" - sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" - else - # The sourcefile does not contain any dependencies, so just - # store a dummy comment line, to avoid errors with the Makefile - # "include basename.Plo" scheme. - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" - ;; - -tru64) - # The Tru64 AIX compiler uses -MD to generate dependencies as a side - # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. - # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put - # dependencies in `foo.d' instead, so we check for that too. - # Subdirectories are respected. - - tmpdepfile1="$object.d" - tmpdepfile2=`echo "$object" | sed -e 's/.o$/.d/'` - if test "$libtool" = yes; then - "$@" -Wc,-MD - else - "$@" -MD - fi - - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile1" "$tmpdepfile2" - exit $stat - fi - - if test -f "$tmpdepfile1"; then - tmpdepfile="$tmpdepfile1" - else - tmpdepfile="$tmpdepfile2" - fi - if test -f "$tmpdepfile"; then - sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" - # That's a space and a tab in the []. - sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" - else - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" - ;; - -#nosideeffect) - # This comment above is used by automake to tell side-effect - # dependency tracking mechanisms from slower ones. - -dashmstdout) - # Important note: in order to support this mode, a compiler *must* - # always write the proprocessed file to stdout, regardless of -o, - # because we must use -o when running libtool. - test -z "$dashmflag" && dashmflag=-M - ( IFS=" " - case " $* " in - *" --mode=compile "*) # this is libtool, let us make it quiet - for arg - do # cycle over the arguments - case "$arg" in - "--mode=compile") - # insert --quiet before "--mode=compile" - set fnord "$@" --quiet - shift # fnord - ;; - esac - set fnord "$@" "$arg" - shift # fnord - shift # "$arg" - done - ;; - esac - "$@" $dashmflag | sed 's:^[^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" - ) & - proc=$! - "$@" - stat=$? - wait "$proc" - if test "$stat" != 0; then exit $stat; fi - rm -f "$depfile" - cat < "$tmpdepfile" > "$depfile" - tr ' ' ' -' < "$tmpdepfile" | \ -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -dashXmstdout) - # This case only exists to satisfy depend.m4. It is never actually - # run, as this mode is specially recognized in the preamble. - exit 1 - ;; - -makedepend) - # X makedepend - ( - shift - cleared=no - for arg in "$@"; do - case $cleared in no) - set ""; shift - cleared=yes - esac - case "$arg" in - -D*|-I*) - set fnord "$@" "$arg"; shift;; - -*) - ;; - *) - set fnord "$@" "$arg"; shift;; - esac - done - obj_suffix="`echo $object | sed 's/^.*\././'`" - touch "$tmpdepfile" - ${MAKEDEPEND-makedepend} 2>/dev/null -o"$obj_suffix" -f"$tmpdepfile" "$@" - ) & - proc=$! - "$@" - stat=$? - wait "$proc" - if test "$stat" != 0; then exit $stat; fi - rm -f "$depfile" - cat < "$tmpdepfile" > "$depfile" - tail +3 "$tmpdepfile" | tr ' ' ' -' | \ -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" "$tmpdepfile".bak - ;; - -cpp) - # Important note: in order to support this mode, a compiler *must* - # always write the proprocessed file to stdout, regardless of -o, - # because we must use -o when running libtool. - ( IFS=" " - case " $* " in - *" --mode=compile "*) - for arg - do # cycle over the arguments - case $arg in - "--mode=compile") - # insert --quiet before "--mode=compile" - set fnord "$@" --quiet - shift # fnord - ;; - esac - set fnord "$@" "$arg" - shift # fnord - shift # "$arg" - done - ;; - esac - "$@" -E | - sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | - sed '$ s: \\$::' > "$tmpdepfile" - ) & - proc=$! - "$@" - stat=$? - wait "$proc" - if test "$stat" != 0; then exit $stat; fi - rm -f "$depfile" - echo "$object : \\" > "$depfile" - cat < "$tmpdepfile" >> "$depfile" - sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -msvisualcpp) - # Important note: in order to support this mode, a compiler *must* - # always write the proprocessed file to stdout, regardless of -o, - # because we must use -o when running libtool. - ( IFS=" " - case " $* " in - *" --mode=compile "*) - for arg - do # cycle over the arguments - case $arg in - "--mode=compile") - # insert --quiet before "--mode=compile" - set fnord "$@" --quiet - shift # fnord - ;; - esac - set fnord "$@" "$arg" - shift # fnord - shift # "$arg" - done - ;; - esac - "$@" -E | - sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" - ) & - proc=$! - "$@" - stat=$? - wait "$proc" - if test "$stat" != 0; then exit $stat; fi - rm -f "$depfile" - echo "$object : \\" > "$depfile" - . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" - echo " " >> "$depfile" - . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -none) - exec "$@" - ;; - -*) - echo "Unknown depmode $depmode" 1>&2 - exit 1 - ;; -esac - -exit 0 diff --git a/config/install-sh b/config/install-sh deleted file mode 100755 index e9de2384..00000000 --- a/config/install-sh +++ /dev/null @@ -1,251 +0,0 @@ -#!/bin/sh -# -# install - install a program, script, or datafile -# This comes from X11R5 (mit/util/scripts/install.sh). -# -# Copyright 1991 by the Massachusetts Institute of Technology -# -# Permission to use, copy, modify, distribute, and sell this software and its -# documentation for any purpose is hereby granted without fee, provided that -# the above copyright notice appear in all copies and that both that -# copyright notice and this permission notice appear in supporting -# documentation, and that the name of M.I.T. not be used in advertising or -# publicity pertaining to distribution of the software without specific, -# written prior permission. M.I.T. makes no representations about the -# suitability of this software for any purpose. It is provided "as is" -# without express or implied warranty. -# -# Calling this script install-sh is preferred over install.sh, to prevent -# `make' implicit rules from creating a file called install from it -# when there is no Makefile. -# -# This script is compatible with the BSD install script, but was written -# from scratch. It can only install one file at a time, a restriction -# shared with many OS's install programs. - - -# set DOITPROG to echo to test this script - -# Don't use :- since 4.3BSD and earlier shells don't like it. -doit="${DOITPROG-}" - - -# put in absolute paths if you don't have them in your path; or use env. vars. - -mvprog="${MVPROG-mv}" -cpprog="${CPPROG-cp}" -chmodprog="${CHMODPROG-chmod}" -chownprog="${CHOWNPROG-chown}" -chgrpprog="${CHGRPPROG-chgrp}" -stripprog="${STRIPPROG-strip}" -rmprog="${RMPROG-rm}" -mkdirprog="${MKDIRPROG-mkdir}" - -transformbasename="" -transform_arg="" -instcmd="$mvprog" -chmodcmd="$chmodprog 0755" -chowncmd="" -chgrpcmd="" -stripcmd="" -rmcmd="$rmprog -f" -mvcmd="$mvprog" -src="" -dst="" -dir_arg="" - -while [ x"$1" != x ]; do - case $1 in - -c) instcmd="$cpprog" - shift - continue;; - - -d) dir_arg=true - shift - continue;; - - -m) chmodcmd="$chmodprog $2" - shift - shift - continue;; - - -o) chowncmd="$chownprog $2" - shift - shift - continue;; - - -g) chgrpcmd="$chgrpprog $2" - shift - shift - continue;; - - -s) stripcmd="$stripprog" - shift - continue;; - - -t=*) transformarg=`echo $1 | sed 's/-t=//'` - shift - continue;; - - -b=*) transformbasename=`echo $1 | sed 's/-b=//'` - shift - continue;; - - *) if [ x"$src" = x ] - then - src=$1 - else - # this colon is to work around a 386BSD /bin/sh bug - : - dst=$1 - fi - shift - continue;; - esac -done - -if [ x"$src" = x ] -then - echo "install: no input file specified" - exit 1 -else - true -fi - -if [ x"$dir_arg" != x ]; then - dst=$src - src="" - - if [ -d $dst ]; then - instcmd=: - chmodcmd="" - else - instcmd=mkdir - fi -else - -# Waiting for this to be detected by the "$instcmd $src $dsttmp" command -# might cause directories to be created, which would be especially bad -# if $src (and thus $dsttmp) contains '*'. - - if [ -f $src -o -d $src ] - then - true - else - echo "install: $src does not exist" - exit 1 - fi - - if [ x"$dst" = x ] - then - echo "install: no destination specified" - exit 1 - else - true - fi - -# If destination is a directory, append the input filename; if your system -# does not like double slashes in filenames, you may need to add some logic - - if [ -d $dst ] - then - dst="$dst"/`basename $src` - else - true - fi -fi - -## this sed command emulates the dirname command -dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` - -# Make sure that the destination directory exists. -# this part is taken from Noah Friedman's mkinstalldirs script - -# Skip lots of stat calls in the usual case. -if [ ! -d "$dstdir" ]; then -defaultIFS=' -' -IFS="${IFS-${defaultIFS}}" - -oIFS="${IFS}" -# Some sh's can't handle IFS=/ for some reason. -IFS='%' -set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` -IFS="${oIFS}" - -pathcomp='' - -while [ $# -ne 0 ] ; do - pathcomp="${pathcomp}${1}" - shift - - if [ ! -d "${pathcomp}" ] ; - then - $mkdirprog "${pathcomp}" - else - true - fi - - pathcomp="${pathcomp}/" -done -fi - -if [ x"$dir_arg" != x ] -then - $doit $instcmd $dst && - - if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && - if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && - if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi -else - -# If we're going to rename the final executable, determine the name now. - - if [ x"$transformarg" = x ] - then - dstfile=`basename $dst` - else - dstfile=`basename $dst $transformbasename | - sed $transformarg`$transformbasename - fi - -# don't allow the sed command to completely eliminate the filename - - if [ x"$dstfile" = x ] - then - dstfile=`basename $dst` - else - true - fi - -# Make a temp file name in the proper directory. - - dsttmp=$dstdir/#inst.$$# - -# Move or copy the file name to the temp name - - $doit $instcmd $src $dsttmp && - - trap "rm -f ${dsttmp}" 0 && - -# and set any options; do chmod last to preserve setuid bits - -# If any of these fail, we abort the whole thing. If we want to -# ignore errors from any of these, just make sure not to ignore -# errors from the above "$doit $instcmd $src $dsttmp" command. - - if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && - if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && - if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && - -# Now rename the file to the real destination. - - $doit $rmcmd -f $dstdir/$dstfile && - $doit $mvcmd $dsttmp $dstdir/$dstfile - -fi && - - -exit 0 diff --git a/config/missing b/config/missing deleted file mode 100755 index 0a7fb5a2..00000000 --- a/config/missing +++ /dev/null @@ -1,283 +0,0 @@ -#! /bin/sh -# Common stub for a few missing GNU programs while installing. -# Copyright 1996, 1997, 1999, 2000 Free Software Foundation, Inc. -# Originally by Fran,cois Pinard , 1996. - -# This program 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, or (at your option) -# any later version. - -# This program 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 this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -if test $# -eq 0; then - echo 1>&2 "Try \`$0 --help' for more information" - exit 1 -fi - -run=: - -# In the cases where this matters, `missing' is being run in the -# srcdir already. -if test -f configure.ac; then - configure_ac=configure.ac -else - configure_ac=configure.in -fi - -case "$1" in ---run) - # Try to run requested program, and just exit if it succeeds. - run= - shift - "$@" && exit 0 - ;; -esac - -# If it does not exist, or fails to run (possibly an outdated version), -# try to emulate it. -case "$1" in - - -h|--h|--he|--hel|--help) - echo "\ -$0 [OPTION]... PROGRAM [ARGUMENT]... - -Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an -error status if there is no known handling for PROGRAM. - -Options: - -h, --help display this help and exit - -v, --version output version information and exit - --run try to run the given command, and emulate it if it fails - -Supported PROGRAM values: - aclocal touch file \`aclocal.m4' - autoconf touch file \`configure' - autoheader touch file \`config.h.in' - automake touch all \`Makefile.in' files - bison create \`y.tab.[ch]', if possible, from existing .[ch] - flex create \`lex.yy.c', if possible, from existing .c - help2man touch the output file - lex create \`lex.yy.c', if possible, from existing .c - makeinfo touch the output file - tar try tar, gnutar, gtar, then tar without non-portable flags - yacc create \`y.tab.[ch]', if possible, from existing .[ch]" - ;; - - -v|--v|--ve|--ver|--vers|--versi|--versio|--version) - echo "missing 0.3 - GNU automake" - ;; - - -*) - echo 1>&2 "$0: Unknown \`$1' option" - echo 1>&2 "Try \`$0 --help' for more information" - exit 1 - ;; - - aclocal) - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified \`acinclude.m4' or \`${configure_ac}'. You might want - to install the \`Automake' and \`Perl' packages. Grab them from - any GNU archive site." - touch aclocal.m4 - ;; - - autoconf) - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified \`${configure_ac}'. You might want to install the - \`Autoconf' and \`GNU m4' packages. Grab them from any GNU - archive site." - touch configure - ;; - - autoheader) - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified \`acconfig.h' or \`${configure_ac}'. You might want - to install the \`Autoconf' and \`GNU m4' packages. Grab them - from any GNU archive site." - files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` - test -z "$files" && files="config.h" - touch_files= - for f in $files; do - case "$f" in - *:*) touch_files="$touch_files "`echo "$f" | - sed -e 's/^[^:]*://' -e 's/:.*//'`;; - *) touch_files="$touch_files $f.in";; - esac - done - touch $touch_files - ;; - - automake) - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. - You might want to install the \`Automake' and \`Perl' packages. - Grab them from any GNU archive site." - find . -type f -name Makefile.am -print | - sed 's/\.am$/.in/' | - while read f; do touch "$f"; done - ;; - - bison|yacc) - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified a \`.y' file. You may need the \`Bison' package - in order for those modifications to take effect. You can get - \`Bison' from any GNU archive site." - rm -f y.tab.c y.tab.h - if [ $# -ne 1 ]; then - eval LASTARG="\${$#}" - case "$LASTARG" in - *.y) - SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` - if [ -f "$SRCFILE" ]; then - cp "$SRCFILE" y.tab.c - fi - SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` - if [ -f "$SRCFILE" ]; then - cp "$SRCFILE" y.tab.h - fi - ;; - esac - fi - if [ ! -f y.tab.h ]; then - echo >y.tab.h - fi - if [ ! -f y.tab.c ]; then - echo 'main() { return 0; }' >y.tab.c - fi - ;; - - lex|flex) - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified a \`.l' file. You may need the \`Flex' package - in order for those modifications to take effect. You can get - \`Flex' from any GNU archive site." - rm -f lex.yy.c - if [ $# -ne 1 ]; then - eval LASTARG="\${$#}" - case "$LASTARG" in - *.l) - SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` - if [ -f "$SRCFILE" ]; then - cp "$SRCFILE" lex.yy.c - fi - ;; - esac - fi - if [ ! -f lex.yy.c ]; then - echo 'main() { return 0; }' >lex.yy.c - fi - ;; - - help2man) - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified a dependency of a manual page. You may need the - \`Help2man' package in order for those modifications to take - effect. You can get \`Help2man' from any GNU archive site." - - file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` - if test -z "$file"; then - file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` - fi - if [ -f "$file" ]; then - touch $file - else - test -z "$file" || exec >$file - echo ".ab help2man is required to generate this page" - exit 1 - fi - ;; - - makeinfo) - if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then - # We have makeinfo, but it failed. - exit 1 - fi - - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified a \`.texi' or \`.texinfo' file, or any other file - indirectly affecting the aspect of the manual. The spurious - call might also be the consequence of using a buggy \`make' (AIX, - DU, IRIX). You might want to install the \`Texinfo' package or - the \`GNU make' package. Grab either from any GNU archive site." - file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` - if test -z "$file"; then - file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` - file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` - fi - touch $file - ;; - - tar) - shift - if test -n "$run"; then - echo 1>&2 "ERROR: \`tar' requires --run" - exit 1 - fi - - # We have already tried tar in the generic part. - # Look for gnutar/gtar before invocation to avoid ugly error - # messages. - if (gnutar --version > /dev/null 2>&1); then - gnutar ${1+"$@"} && exit 0 - fi - if (gtar --version > /dev/null 2>&1); then - gtar ${1+"$@"} && exit 0 - fi - firstarg="$1" - if shift; then - case "$firstarg" in - *o*) - firstarg=`echo "$firstarg" | sed s/o//` - tar "$firstarg" ${1+"$@"} && exit 0 - ;; - esac - case "$firstarg" in - *h*) - firstarg=`echo "$firstarg" | sed s/h//` - tar "$firstarg" ${1+"$@"} && exit 0 - ;; - esac - fi - - echo 1>&2 "\ -WARNING: I can't seem to be able to run \`tar' with the given arguments. - You may want to install GNU tar or Free paxutils, or check the - command line arguments." - exit 1 - ;; - - *) - echo 1>&2 "\ -WARNING: \`$1' is needed, and you do not seem to have it handy on your - system. You might have modified some files without having the - proper tools for further handling them. Check the \`README' file, - it often tells you about the needed prerequirements for installing - this package. You may also peek at any GNU archive site, in case - some other package would contain this missing \`$1' program." - exit 1 - ;; -esac - -exit 0 diff --git a/config/mkinstalldirs b/config/mkinstalldirs deleted file mode 100755 index 6b3b5fc5..00000000 --- a/config/mkinstalldirs +++ /dev/null @@ -1,40 +0,0 @@ -#! /bin/sh -# mkinstalldirs --- make directory hierarchy -# Author: Noah Friedman -# Created: 1993-05-16 -# Public domain - -# $Id$ - -errstatus=0 - -for file -do - set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` - shift - - pathcomp= - for d - do - pathcomp="$pathcomp$d" - case "$pathcomp" in - -* ) pathcomp=./$pathcomp ;; - esac - - if test ! -d "$pathcomp"; then - echo "mkdir $pathcomp" - - mkdir "$pathcomp" || lasterr=$? - - if test ! -d "$pathcomp"; then - errstatus=$lasterr - fi - fi - - pathcomp="$pathcomp/" - done -done - -exit $errstatus - -# mkinstalldirs ends here diff --git a/configure.in b/configure.in deleted file mode 100644 index 14367546..00000000 --- a/configure.in +++ /dev/null @@ -1,289 +0,0 @@ -dnl synergy -- mouse and keyboard sharing utility -dnl Copyright (C) 2002 Chris Schoeneman -dnl -dnl This package is free software; you can redistribute it and/or -dnl modify it under the terms of the GNU General Public License -dnl found in the file COPYING that should have accompanied this file. -dnl -dnl This package is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -dnl GNU General Public License for more details. - -dnl Process this file with autoconf to produce a configure script. - -dnl initialize -AC_INIT(lib/common/common.h) -AC_CONFIG_AUX_DIR(config) - -dnl current version, extracted from $srcdir/lib/common/Version.h -MAJOR_VERSION=`grep '#.*define VERSION "' $srcdir/lib/common/Version.h | sed -e 's/.*"\([0-9]*\)\.[0-9]*\.[0-9]*".*/\1/'` -MINOR_VERSION=`grep '#.*define VERSION "' $srcdir/lib/common/Version.h | sed -e 's/.*"[0-9]*\.\([0-9]*\)\.[0-9]*".*/\1/'` -RELEASE_VERSION=`grep '#.*define VERSION "' $srcdir/lib/common/Version.h | sed -e 's/.*"[0-9]*\.[0-9]*\.\([0-9]*\)".*/\1/'` - -dnl initialize automake -AM_INIT_AUTOMAKE(synergy, $MAJOR_VERSION.$MINOR_VERSION.$RELEASE_VERSION) -AM_CONFIG_HEADER(config.h) - -dnl information on the package - -dnl decide on platform -ARCH_LIBS="" -ARCH_CFLAGS="" -AC_CANONICAL_HOST -case $host in -*-*-mingw32* | *-*-windows*) - acx_host_arch="WIN32" - acx_host_winapi="MSWINDOWS" - ;; -*-*-darwin*) - acx_host_arch="UNIX" - acx_host_winapi="CARBON" - ;; -*) - acx_host_arch="UNIX" - acx_host_winapi="XWINDOWS" - ;; -esac -ARCH_CFLAGS="$ARCH_CFLAGS -DSYSAPI_$acx_host_arch=1 -DWINAPI_$acx_host_winapi=1" -AM_CONDITIONAL(WIN32, test x$acx_host_arch = xWIN32) -AM_CONDITIONAL(UNIX, test x$acx_host_arch = xUNIX) -AM_CONDITIONAL(MSWINDOWS, test x$acx_host_winapi = xMSWINDOWS) -AM_CONDITIONAL(CARBON, test x$acx_host_winapi = xCARBON) -AM_CONDITIONAL(XWINDOWS, test x$acx_host_winapi = xXWINDOWS) - -dnl checks for programs -AC_PROG_CC -AC_PROG_CXX -AC_PROG_RANLIB -AC_CHECK_PROG(HAVE_DOT, dot, YES, NO) - -dnl AC_PROG_OBJC doesn't exist. Borrow some ideas from KDE. -dnl AC_MSG_CHECKING(for an Objective-C compiler) -OBJC="${CC}" -OBJCFLAGS="${CFLAGS}" -AC_SUBST(OBJC) -AC_SUBST(OBJCFLAGS) -_AM_DEPENDENCIES(OBJC) - -dnl do checks using C++ -AC_LANG_CPLUSPLUS - -dnl our files end in .cpp not .C so tests should also end in .cpp -ac_ext=cpp - -dnl enable debugging or disable asserts -AC_ARG_ENABLE([debug], [ --enable-debug enable debugging]) -if test "x$enable_debug" != xno; then - CXXFLAGS="$CXXFLAGS -g" -else - CXXFLAGS="$CXXFLAGS -DNDEBUG" -fi - -dnl check compiler -ACX_CHECK_CXX - -dnl checks for libraries -if test x"$acx_host_arch" = xUNIX; then - ACX_PTHREAD(,AC_MSG_ERROR(You must have pthreads to compile synergy)) - ARCH_LIBS="$PTHREAD_LIBS $ARCH_LIBS" - ARCH_CFLAGS="$ARCH_CFLAGS $PTHREAD_CFLAGS" -fi -if test x"$acx_host_winapi" = xCARBON; then - ARCH_LIBS="-framework Carbon $ARCH_LIBS" -fi -ACX_CHECK_NANOSLEEP -ACX_CHECK_INET_ATON - -dnl checks for header files -AC_HEADER_STDC -AC_CHECK_HEADERS([unistd.h sys/time.h sys/types.h locale.h wchar.h]) -AC_CHECK_HEADERS([sys/socket.h sys/select.h]) -AC_CHECK_HEADERS([sys/utsname.h]) -AC_CHECK_HEADERS([istream ostream sstream]) -AC_HEADER_TIME -if test x"$acx_host_winapi" = xXWINDOWS; then - AC_PATH_X - AC_PATH_XTRA - save_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="$X_CFLAGS $CPPFLAGS" - XEXT_LDADD= - - AC_CHECK_LIB(Xtst, - XTestQueryExtension, - [XEXT_LDADD="$XEXT_LDADD -lXtst"], - AC_MSG_ERROR(You must have the XTest library to build synergy), - [$X_LIBS -lXext -lX11 $X_EXTRA_LIBS]) - AC_CHECK_HEADERS([X11/extensions/XTest.h], - , - AC_MSG_ERROR(You must have the XTest headers to compile synergy)) - - acx_have_xkb=no - AC_CHECK_LIB(X11, - XkbQueryExtension, - [acx_have_xkb=yes], - [acx_have_xkb=no], - [$X_LIBS $X_EXTRA_LIBS]) - if test x"$acx_have_xkb" = xyes; then - AC_CHECK_HEADERS([X11/XKBlib.h X11/extensions/XKBstr.h], - [acx_have_xkb=yes], - [acx_have_xkb=no], - [#include ]) - if test x"$acx_have_xkb" = xyes; then - AC_TRY_COMPILE([ - #include - #include - ],[ - XkbQueryExtension(0, 0, 0, 0, 0, 0); - ], - [acx_have_xkb=yes], - [acx_have_xkb=no]) - fi - fi - if test x"$acx_have_xkb" = xyes; then - AC_DEFINE(HAVE_XKB_EXTENSION, 1, - [Define this if the XKB extension is available.]) - fi - - acx_have_xinerama=yes - AC_CHECK_LIB(Xinerama, - XineramaQueryExtension, - [acx_have_xinerama=yes], - [acx_have_xinerama=no], - [$X_LIBS -lXext -lX11 $X_EXTRA_LIBS]) - if test x"$acx_have_xinerama" = xyes; then - AC_CHECK_HEADERS([X11/extensions/Xinerama.h], - [acx_have_xinerama=yes], - [acx_have_xinerama=no], - [#include ]) - fi - if test x"$acx_have_xinerama" = xyes; then - XEXT_LDADD="$XEXT_LDADD -lXinerama" - fi - - X_DPMS_LDADD= - acx_have_dpms=no - AC_CHECK_LIB(Xext, - DPMSQueryExtension, - [acx_have_dpms=yes], - [acx_have_dpms=no], - [$X_LIBS -lX11 $X_EXTRA_LIBS]) - if test x"$acx_have_dpms" != xyes; then - AC_CHECK_LIB(Xdpms, - DPMSQueryExtension, - [acx_have_dpms=yes; XDPMS_LDADD=-lXdpms], - [acx_have_dpms=no], - [$X_LIBS -lX11 $X_EXTRA_LIBS]) - fi - if test x"$acx_have_dpms" = xyes; then - AC_CHECK_HEADERS([X11/extensions/dpms.h], - [acx_have_dpms_h=yes], - [acx_have_dpms_h=no], - [#include ]) - if test x"$acx_have_dpms_h" = xyes; then - XEXT_LDADD="$XEXT_LDADD $XDPMS_LDADD" - AC_MSG_CHECKING(for prototypes in X11/extensions/dpms.h) - acx_have_dpms_protos=no - AC_TRY_COMPILE([ - #include - extern "C" { - #include - } - ],[ - int s = DPMSModeOn; - DPMSQueryExtension(0, 0, 0); - ], - [acx_have_dpms_protos=yes]) - AC_MSG_RESULT($acx_have_dpms_protos) - if test x"$acx_have_dpms_protos" = xyes; then - AC_DEFINE(HAVE_DPMS_PROTOTYPES,1,[Define if the header file declares function prototypes.]) - fi - fi - fi - - CPPFLAGS="$save_CPPFLAGS" - ARCH_LIBS="$X_LIBS $X_PRE_LIBS $XEXT_LDADD -lXext -lX11 $X_EXTRA_LIBS $ARCH_LIBS" - ARCH_CFLAGS="$ARCH_CFLAGS $X_CFLAGS" -fi - -dnl checks for types -AC_TYPE_SIZE_T -ACX_CHECK_SOCKLEN_T - -dnl checks for structures -AC_STRUCT_TM - -dnl checks for compiler characteristics -AC_CHECK_SIZEOF(char, 1) -AC_CHECK_SIZEOF(short, 2) -AC_CHECK_SIZEOF(int, 2) -AC_CHECK_SIZEOF(long, 4) -ACX_CHECK_CXX_BOOL(,AC_MSG_ERROR(Your compiler must support bool to compile synergy)) -ACX_CHECK_CXX_EXCEPTIONS(,AC_MSG_ERROR(Your compiler must support exceptions to compile synergy)) -ACX_CHECK_CXX_CASTS(,AC_MSG_ERROR(Your compiler must support C++ casts to compile synergy)) -ACX_CHECK_CXX_MUTABLE(,AC_MSG_ERROR(Your compiler must support mutable to compile synergy)) -ACX_CHECK_CXX_STDLIB(,AC_MSG_ERROR(Your compiler must support the C++ standard library to compile synergy)) - -dnl checks for library functions -dnl AC_TYPE_SIGNAL -AC_FUNC_MEMCMP -AC_FUNC_STRFTIME -AC_CHECK_FUNCS(gmtime_r) -ACX_CHECK_GETPWUID_R -AC_CHECK_FUNCS(vsnprintf) -AC_FUNC_SELECT_ARGTYPES -ACX_CHECK_POLL -ACX_FUNC_ACCEPT -dnl use AC_REPLACE_FUNCS() for stuff in string.h - -dnl checks for system services - -dnl enable maximum compiler warnings and warnings are errors. -ACX_CXX_WARNINGS -ACX_CXX_WARNINGS_ARE_ERRORS - -dnl adjust compiler and linker variables -CXXFLAGS="$CXXFLAGS $SYNERGY_CXXFLAGS $ARCH_CFLAGS" -OBJCXXFLAGS="$OBJCXXFLAGS $CXXFLAGS $ARCH_CFLAGS" -LIBS="$NANOSLEEP_LIBS $INET_ATON_LIBS $ARCH_LIBS $LIBS" - -dnl we need to have an environment variable set when building on OS X. -dnl i'm not sure of the right way to do that. writing 'export ...' to -dnl the makefiles isn't portable. here we'll hijack XXXDEPMODE (where -dnl XXX depends on the language) to insert setting the environment -dnl variable when running the compiler. we'd like to put that in CC, -dnl CXX and OBJC but that breaks depcomp. let's hope this works. -if test x"$acx_host_winapi" = xCARBON; then - MACOSX_DEPLOYMENT_TARGET="10.2" - CCDEPMODE="MACOSX_DEPLOYMENT_TARGET=$MACOSX_DEPLOYMENT_TARGET $CCDEPMODE" - CXXDEPMODE="MACOSX_DEPLOYMENT_TARGET=$MACOSX_DEPLOYMENT_TARGET $CXXDEPMODE" - OBJCDEPMODE="MACOSX_DEPLOYMENT_TARGET=$MACOSX_DEPLOYMENT_TARGET $OBJCDEPMODE" -else - MACOSX_DEPLOYMENT_TARGET="5" - CXXDEPMODE="FOO=$MACOSX_DEPLOYMENT_TARGET $CXXDEPMODE" -fi - -AC_OUTPUT([ -Makefile -cmd/Makefile -cmd/launcher/Makefile -cmd/synergyc/Makefile -cmd/synergys/Makefile -dist/Makefile -dist/nullsoft/Makefile -dist/rpm/Makefile -dist/rpm/synergy.spec -doc/Makefile -doc/doxygen.cfg -lib/Makefile -lib/arch/Makefile -lib/base/Makefile -lib/client/Makefile -lib/common/Makefile -lib/io/Makefile -lib/mt/Makefile -lib/net/Makefile -lib/platform/Makefile -lib/server/Makefile -lib/synergy/Makefile -]) diff --git a/dist/Makefile.am b/dist/Makefile.am deleted file mode 100644 index 1af99c18..00000000 --- a/dist/Makefile.am +++ /dev/null @@ -1,26 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2002 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -## Process this file with automake to produce Makefile.in -NULL = - -SUBDIRS = \ - rpm \ - nullsoft \ - $(NULL) - -EXTRA_DIST = \ - $(NULL) - -MAINTAINERCLEANFILES = \ - Makefile.in \ - $(NULL) diff --git a/dist/nullsoft/Makefile.am b/dist/nullsoft/Makefile.am deleted file mode 100644 index 120cd016..00000000 --- a/dist/nullsoft/Makefile.am +++ /dev/null @@ -1,24 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2002 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -## Process this file with automake to produce Makefile.in -NULL = - -EXTRA_DIST = \ - Makefile.win \ - synergy.nsi \ - dosify.c \ - $(NULL) - -MAINTAINERCLEANFILES = \ - Makefile.in \ - $(NULL) diff --git a/dist/nullsoft/Makefile.win b/dist/nullsoft/Makefile.win deleted file mode 100644 index 91aa68bb..00000000 --- a/dist/nullsoft/Makefile.win +++ /dev/null @@ -1,63 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2007 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -NSIS = "$(PROGRAMFILES)\NSIS\makensis.exe" -NSIS_FLAGS = /NOCD /V1 - -BIN_INSTALLER_SRC = dist\nullsoft -BIN_INSTALLER_DST = $(BUILD_DST)\$(BIN_INSTALLER_SRC) -BIN_DOSIFY_EXE = "$(BIN_INSTALLER_DST)\dosify.exe" -BIN_DOSIFY_C = \ - "$(BIN_INSTALLER_SRC)\dosify.c" \ - $(NULL) -BIN_DOSIFY_OBJ = \ - "$(BIN_INSTALLER_DST)\dosify.obj" \ - $(NULL) - -BIN_INSTALLER_NSI = "$(BIN_INSTALLER_SRC)\synergy.nsi" -BIN_INSTALLER_EXE = "$(BUILD_DST)\SynergyInstaller.exe" -BIN_INSTALLER_DOCS = \ - COPYING \ - ChangeLog \ - $(NULL) -BIN_INSTALLER_DOS_DOCS = \ - $(BUILD_DST)\COPYING.txt \ - $(BUILD_DST)\ChangeLog.txt \ - $(NULL) - -C_FILES = $(C_FILES) $(BIN_DOSIFY_C) -OBJ_FILES = $(OBJ_FILES) $(BIN_DOSIFY_OBJ) -OPTPROGRAMS = $(OPTPROGRAMS) $(BIN_DOSIFY_EXE) - -# Build rules. -$(BIN_DOSIFY_OBJ): $(BIN_DOSIFY_C) - @$(ECHO) Compile $(BIN_DOSIFY_C) - -@$(MKDIR) $(BIN_INSTALLER_DST) 2>NUL: - $(cc) $(cdebug) $(cflags) $(cvars) /Fo$@ /Fd$(@:.obj=.pdb) $** -$(BIN_DOSIFY_EXE): $(BIN_DOSIFY_OBJ) - @$(ECHO) Link $(@F) - $(link) $(ldebug) $(conlflags) $(conlibsmt) /out:$@ $** - -# Convert text files from Unix to DOS format. -$(BIN_INSTALLER_DOS_DOCS): $(BIN_DOSIFY_EXE) $(BIN_INSTALLER_DOCS) - @$(ECHO) Convert text files to DOS format - $(BIN_DOSIFY_EXE) "." "$(BUILD_DST)" $(BIN_INSTALLER_DOCS) - -# Allow installers for both debug and release. -$(BIN_INSTALLER_EXE): $(BIN_INSTALLER_NSI) all $(BIN_INSTALLER_DOS_DOCS) - @$(ECHO) Build $(@F) - $(NSIS) $(NSIS_FLAGS) /DOUTPUTDIR=$(@D) /DOUTPUTFILE=$@ $(BIN_INSTALLER_NSI) -installer: $(BIN_INSTALLER_EXE) -debug-installer: - @$(MAKE) /nologo /f $(MAKEFILE) DEBUG=1 installer -release-installer: - @$(MAKE) /nologo /f $(MAKEFILE) NODEBUG=1 installer diff --git a/dist/nullsoft/dosify.c b/dist/nullsoft/dosify.c deleted file mode 100644 index 95d0caee..00000000 --- a/dist/nullsoft/dosify.c +++ /dev/null @@ -1,99 +0,0 @@ -#include -#include -#include - -static -char* -concatPath(const char* dir, const char* name, const char* ext) -{ - size_t nDir = (dir != NULL) ? strlen(dir) : 0; - size_t nPath = nDir + 1 + strlen(name) + strlen(ext?ext:"") + 1; - char* path = malloc(nPath); - - /* directory */ - if (nDir > 0 && strcmp(dir, ".") != 0) { - strcpy(path, dir); - if (path[nDir - 1] != '\\' && path[nDir - 1] != '/') { - strcat(path, "\\"); - } - } - else { - strcpy(path, ""); - } - - - /* name */ - strcat(path, name); - - /* extension */ - if (ext != NULL && strrchr(name, '.') == NULL) { - strcat(path, ext); - } - - return path; -} - -static -int -dosify(const char* srcdir, const char* dstdir, const char* name) -{ - FILE* dFile, *sFile; - char* dName, *sName; - - sName = concatPath(srcdir, name, NULL); - dName = concatPath(dstdir, name, ".txt"); - - sFile = fopen(sName, "rb"); - if (sFile == NULL) { - fprintf(stderr, "Can't open \"%s\" for reading\n", sName); - return 0; - } - else { - dFile = fopen(dName, "w"); - if (dFile == NULL) { - fclose(sFile); - fprintf(stderr, "Can't open \"%s\" for writing\n", dName); - return 0; - } - else { - char buffer[1024]; - while (!ferror(dFile) && - fgets(buffer, sizeof(buffer), sFile) != NULL) { - fprintf(dFile, "%s", buffer); - } - if (ferror(sFile) || ferror(dFile)) { - fprintf(stderr, - "Error copying \"%s\" to \"%s\"\n", sName, dName); - fclose(dFile); - fclose(sFile); - _unlink(dName); - return 0; - } - } - } - - fclose(dFile); - fclose(sFile); - free(dName); - free(sName); - return 1; -} - -#include -int -main(int argc, char** argv) -{ - int i; - - if (argc < 3) { - fprintf(stderr, "usage: %s [files]\n", argv[0]); - return 1; - } - - for (i = 3; i < argc; ++i) { - if (!dosify(argv[1], argv[2], argv[i])) - return 1; - } - - return 0; -} diff --git a/dist/nullsoft/synergy.nsi b/dist/nullsoft/synergy.nsi deleted file mode 100644 index 3370d03a..00000000 --- a/dist/nullsoft/synergy.nsi +++ /dev/null @@ -1,179 +0,0 @@ -; Synergy.nsi -; -; This script is based on example1.nsi, but it remember the directory, -; has uninstall support and (optionally) installs start menu shortcuts. -; -; It will install makensisw.exe into a directory that the user selects, - -;-------------------------------- - -!ifndef OUTPUTDIR -!define OUTPUTDIR "build\Release" -!endif - -; The name of the installer -Name "Synergy" - -; The file to write -OutFile "${OUTPUTFILE}" - -; The default installation directory -InstallDir $PROGRAMFILES\Synergy - -; Registry key to check for directory (so if you install again, it will -; overwrite the old one automatically) -InstallDirRegKey HKLM "Software\Synergy" "Install_Dir" - -;-------------------------------- - -; Pages - -Page components -Page license -Page directory -Page instfiles - -UninstPage uninstConfirm -UninstPage instfiles - -;-------------------------------- - -; Text -ComponentText "This will install Synergy on your computer. Select the optional components you want to install." -DirText "Choose a directory to install Synergy to:" -UninstallText "This will uninstall Synergy from your computer." -LicenseText "Synergy is distributed under the GNU GPL:" -LicenseData ${OUTPUTDIR}\COPYING.txt - -;-------------------------------- - -; The stuff to install -Section "Synergy (required)" - - SectionIn RO - - ; Set output path to the installation directory. - SetOutPath $INSTDIR - - ; Put files there - File "${OUTPUTDIR}\synergy.exe" - File "${OUTPUTDIR}\synergyc.exe" - File "${OUTPUTDIR}\synergys.exe" - File "${OUTPUTDIR}\*.dll" - File "${OUTPUTDIR}\COPYING.txt" - File "${OUTPUTDIR}\ChangeLog.txt" - File doc\PORTING - File doc\about.html - File doc\authors.html - File doc\autostart.html - File doc\banner.html - File doc\compiling.html - File doc\configuration.html - File doc\contact.html - File doc\developer.html - File doc\faq.html - File doc\history.html - File doc\home.html - File doc\index.html - File doc\license.html - File doc\news.html - File doc\roadmap.html - File doc\running.html - File doc\security.html - File doc\synergy.css - File doc\tips.html - File doc\toc.html - File doc\trouble.html - - SetOutPath $INSTDIR\images - File doc\images\logo.gif - File doc\images\warp.gif - - ; Write the installation path into the registry - WriteRegStr HKLM SOFTWARE\Synergy "Install_Dir" "$INSTDIR" - - ; Write the uninstall keys for Windows - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Synergy" "DisplayName" "Synergy" - WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Synergy" "UninstallString" '"$INSTDIR\uninstall.exe"' - WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Synergy" "NoModify" 1 - WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Synergy" "NoRepair" 1 - WriteUninstaller "uninstall.exe" - -SectionEnd - -; Optional section (can be disabled by the user) -Section "Start Menu Shortcuts" - - CreateDirectory "$SMPROGRAMS\Synergy" - CreateShortCut "$SMPROGRAMS\Synergy\Synergy.lnk" "$INSTDIR\synergy.exe" "" "$INSTDIR\synergy.exe" 0 - CreateShortCut "$SMPROGRAMS\Synergy\README.lnk" "$INSTDIR\index.html" - CreateShortCut "$SMPROGRAMS\Synergy\Synergy Folder.lnk" "$INSTDIR" - CreateShortCut "$SMPROGRAMS\Synergy\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 - -SectionEnd - -; Optional section (can be disabled by the user) -Section "Desktop Icon" - - CreateShortCut "$DESKTOP\Synergy.lnk" "$INSTDIR\synergy.exe" "" "$INSTDIR\synergy.exe" 0 - -SectionEnd - -;-------------------------------- - -; Uninstaller - -Section "Uninstall" - ; Stop and uninstall the daemons - ExecWait '"$INSTDIR\synergy.exe" /uninstall' - - ; Remove autorun registry keys for synergy - DeleteRegKey HKLM "SYSTEM\CurrentControlSet\Services\Synergy Server" - DeleteRegKey HKLM "SYSTEM\CurrentControlSet\Services\Synergy Client" - DeleteRegValue HKLM "Software\Microsoft\Windows\CurrentVersion\RunServices" "Synergy Server" - DeleteRegValue HKLM "Software\Microsoft\Windows\CurrentVersion\RunServices" "Synergy Client" - DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "Synergy Server" - DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "Synergy Client" - - ; not all keys will have existed, so errors WILL have happened - ClearErrors - - ; Remove registry keys - DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Synergy" - DeleteRegKey HKLM SOFTWARE\Synergy - - ClearErrors - - ; First try to remove files that might be locked (if synergy is running) - Delete /REBOOTOK $INSTDIR\synergy.exe - Delete /REBOOTOK $INSTDIR\synergyc.exe - Delete /REBOOTOK $INSTDIR\synergys.exe - Delete /REBOOTOK $INSTDIR\synrgyhk.dll - - ; Remove files and directory - Delete $INSTDIR\*.* - RMDir $INSTDIR - - ; Remove shortcuts, if any - Delete "$SMPROGRAMS\Synergy\*.*" - Delete "$DESKTOP\Synergy.lnk" - - ; Remove directories used - RMDir "$SMPROGRAMS\Synergy" - RMDir "$INSTDIR" - - IfRebootFlag 0 EndOfAll - MessageBox MB_OKCANCEL "Uninstaller needs to reboot to finish cleaning up. reboot now?" IDCANCEL NoReboot - ClearErrors - Reboot - IfErrors 0 EndOfAll - MessageBox MB_OK "Uninstaller could not reboot. Please reboot manually. Thank you." - Abort "Uninstaller could not reboot. Please reboot manually. Thank you." - NoReboot: - DetailPrint "" - DetailPrint "Uninstaller could not reboot. Please reboot manually. Thank you." - DetailPrint "" - SetDetailsView show - EndOfAll: - -SectionEnd diff --git a/dist/rpm/Makefile.am b/dist/rpm/Makefile.am deleted file mode 100644 index 0e86d9ba..00000000 --- a/dist/rpm/Makefile.am +++ /dev/null @@ -1,22 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2002 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -## Process this file with automake to produce Makefile.in -NULL = - -EXTRA_DIST = \ - synergy.spec.in \ - $(NULL) - -MAINTAINERCLEANFILES = \ - Makefile.in \ - $(NULL) diff --git a/dist/rpm/synergy.spec.in b/dist/rpm/synergy.spec.in deleted file mode 100644 index 0d2b6f48..00000000 --- a/dist/rpm/synergy.spec.in +++ /dev/null @@ -1,66 +0,0 @@ -Summary: Mouse and keyboard sharing utility -Name: @PACKAGE@ -Version: @VERSION@ -Release: 1 -License: GPL -Packager: Chris Schoeneman -Group: System Environment/Daemons -Prefixes: /usr/bin -Source: @PACKAGE@-@VERSION@.tar.gz -Buildroot: /var/tmp/@PACKAGE@-@VERSION@-root - -%description -Synergy lets you easily share a single mouse and keyboard between -multiple computers with different operating systems, each with its -own display, without special hardware. It's intended for users -with multiple computers on their desk since each system uses its -own display. - -%prep -%setup -CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=/usr - -%build -make - -%install -make install DESTDIR=$RPM_BUILD_ROOT -strip $RPM_BUILD_ROOT/usr/bin/synergyc -strip $RPM_BUILD_ROOT/usr/bin/synergys - -%clean -rm -rf $RPM_BUILD_ROOT - -%files -%defattr(-, root, root) -/usr/bin/synergyc -/usr/bin/synergys -%doc AUTHORS -%doc COPYING -%doc ChangeLog -%doc INSTALL -%doc NEWS -%doc README -%doc doc/about.html -%doc doc/authors.html -%doc doc/autostart.html -%doc doc/banner.html -%doc doc/border.html -%doc doc/compiling.html -%doc doc/configuration.html -%doc doc/contact.html -%doc doc/developer.html -%doc doc/faq.html -%doc doc/history.html -%doc doc/home.html -%doc doc/index.html -%doc doc/license.html -%doc doc/news.html -%doc doc/roadmap.html -%doc doc/running.html -%doc doc/security.html -%doc doc/tips.html -%doc doc/toc.html -%doc doc/trouble.html -%doc doc/synergy.css -%doc examples/synergy.conf diff --git a/doc/Makefile.am b/doc/Makefile.am deleted file mode 100644 index 2efec24c..00000000 --- a/doc/Makefile.am +++ /dev/null @@ -1,49 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2002 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -## Process this file with automake to produce Makefile.in -NULL = - -EXTRA_DIST = \ - PORTING \ - doxygen.cfg.in \ - synergy.css \ - about.html \ - authors.html \ - autostart.html \ - banner.html \ - border.html \ - compiling.html \ - configuration.html \ - contact.html \ - developer.html \ - faq.html \ - history.html \ - home.html \ - index.html \ - license.html \ - news.html \ - roadmap.html \ - running.html \ - security.html \ - tips.html \ - toc.html \ - trouble.html \ - images/logo.gif \ - images/warp.gif \ - $(NULL) - -MAINTAINERCLEANFILES = \ - Makefile.in \ - doc/doxygen.cfg \ - doc/doxygen/html/* \ - $(NULL) diff --git a/doc/PORTING b/doc/PORTING deleted file mode 100644 index 4e2744df..00000000 --- a/doc/PORTING +++ /dev/null @@ -1,419 +0,0 @@ -Synergy Developer and Porting Guide -=================================== - -This document is under development. - -Code Organization ------------------ - -The synergy source code organization is: - -. -- root makefiles, some standard documentation -cmd -- program source code - launcher -- synergy launcher for Windows - synergyc -- synergy client - synergys -- synergy server -config -- stuff for autoconf/automake -dist -- files for creating distributions - nullsoft -- files for creating Nullsoft NSIS installer (Windows) - rpm -- files for creating RPMs -doc -- placeholder for documentation -examples -- example files -lib -- library source code - arch -- platform dependent utility library - base -- simple utilities - client -- synergy client library - common -- commonly needed header files - io -- I/O - mt -- multithreading - net -- networking - platform -- platform dependent display/window/event stuff - server -- synergy server library - synergy -- synergy shared client/server code library - -Note how the utility code required by the programs is placed into -separate library directories. This makes the makefiles a little -more awkward but makes for a cleaner organization. The top level -directory has only the standard documentation files and the files -necessary to configure and build the rest of the project. - - -Coding Style Guide ------------------- - -Synergy uses many coding conventions. Contributed code should -following these guidelines. - -- Symbol Naming - Names always begin with a letter (never an underscore). The first - letter of interior names are always capitalized. Acronyms should - be all uppercase. For example: myTextAsASCII. - - Names come it two flavors: leading capital and leading lowercase. - The former have the first character capitalized and the latter - don't. In the following table, leading capital names are indicated - by `Name' and leading lowercase names by `name'. - - The naming convention for various things are: - - * Exceptions -- X + Name XMyException - * Interfaces -- I + Name IMyInterface - * Template Classes -- T + Name TMyTemplate<> - * Other Classes -- C + Name CMyClass - * Enumerations -- E + Name EMyEnumeration - * Constants -- k + Name kMyConstant - * Data Members -- m_ + name m_myDataMember - * Methods -- name myMethod - * Functions -- name myFunction - * Variables -- name myVariable - - Exceptions are types that get thrown and are generally derived - (possibly indirectly) from XBase. Interfaces are derived (possibly - indirectly) from IInterface and have only pure virtual functions. - Other classes are classes that aren't exceptions or interfaces. - Constants include global constants and enumerants. - - Method names should usually have the form `verbObject'. For example: - * isGameOn() - * getBeer() - * pressPowerButton() - * setChannel() - In general, use `get' and `set' to read and write state but use `is' - to read boolean state. Note that classes that contain only `is', - `get', and `set' are probably plain old data; you might want to - consider using public data members only or, better, refactor your - design to have classes that actually do something more than just - hold data. - -- File Naming - Each class should have one source and one header file. If the - class is named `CMyClass' then the source file should be named - `CMyClass.cpp' and the header file `CMyClass.h'. - - Headers files not containing a class should have some meaningful - name with a leading capital (e.g. `Version.h'). - - Source files without a header file have a leading lowercase name. - Only files containing the entry point for an application should - lack a header file. - -- Dependencies - * No circular library dependencies - Library dependencies form an acyclic graph. Conceptually - libraries can be arranged in layers where each library only - references libraries in layers below it, not in the same layer - or layers above it. The makefiles build the lowest layer - libraries first and work upwards. - - * Avoid circular uses-a relationships - When possible, design classes with one-way uses-a relationships - and avoid cycles. This makes it easier to understand the code. - However, sometimes it's not always practical so it is permitted. - - * Included files in headers - Headers should #include only the necessary headers. In - particular, if a class is referenced in a header file only as a - pointer or a reference then use `class COtherClass;' instead of - `#include "COtherClass.h".' - - * #include syntax - Non-synergy header files must be included using angle brackets - while synergy header files must be included using double quotes. - #include "CSynergyHeader.h" - #include - The file name in a #include must not be a relative path unless - it's a system header file and it's customary to use a relative - path, e.g. `#include '. Use compiler options to - add necessary directories to the include search path. - - * Included file ordering - Files should be included in the following order: - * Header for source file - The first include for CMyClass.cpp must be CMyClass.h. - * Other headers in directory, sorted alphabetically - * Headers for each library, sorted alphabetically per library - Include headers from the library closest in the dependency graph - first, then the next farthest, etc. Sort alphabetically within - each library. - * System headers - -- C++ - * C++ features - Synergy uses the following more recent C++ features: - * bool - * templates - * exceptions - * mutable - * new scoping rules - * the standard C++ library - - Do not use the following C++ features: - * dynamic_cast - * run time type information - * namespaces and using (use std:: where necessary) - - The new scoping rules say that the scope of a variable declared - in a for statement is limited to the for loop. For example: - - for (int i = 0; i < 10; ++i) { - // i is in scope here - } - // i is not in scope here - - for (int i = -10; i < 0; ++i) { - // an entirely new i is in scope here - } - // i is not in scope here - - This is used routinely in synergy, but only in for loops. There - is a macro for `for' in lib/base/common.h when building under - Microsoft Visual C++ that works around the fact that that compiler - doesn't follow the new scoping rules. Use the macro if your - compiler uses the old scoping rules. - - * Standard C++ library - The standard C++ library containers should always be used in favor - of custom containers wherever reasonable. std::string is used - throughout synergy but only as the CString typedef; always use - CString, never std::string except in the arch library. Synergy - avoids using auto_ptr due to some portability problems. Synergy - makes limited use of standard algorithms and streams but they can - be freely used in new code. - - * Limited multiple inheritance - Classes should inherit implementation from at most one superclass. - Inheriting implementation from multiple classes can have unpleasant - consequences in C++ due to it's limited capabilities. Classes can - inherit from any number of interface classes. An interface class - provides only pure virtual methods. Synergy breaks this rule in - IInterface which implements the virtual destructor for convenience. - - * No globals - Avoid global variables. All global variables must be static, making - it visible only with its source file. Most uses of global variables - are better served by static data members of a class. Global - constants are permitted in some circumstances. - - Also avoid global functions. Use public static member functions in - a class instead. - - These rules are violated by the main source file for each program - (except that the globals are still static). They could easily be - rewritten to put all the variables and functions into a class but - there's little to be gained by that. - - * Private data only - If a class is plain-old-data (i.e. it has no methods) all of its - data members should be public. Otherwise all of its data members - should be private, not public or protected. This makes it much - easier to track the use of a member when reading code. Protected - data is not allowed because `protected' is a synonym for `public - to my subclasses' and public data is a Bad Thing. While it might - seem okay in this limited situation, the situation is not at all - limited since an arbitrary number of classes can be derived, - directly or indirectly, from the class and any of those classes - have full access to the protected data. - - * Plain old data - A class that merely contains data and doesn't perform operations - on that data (other than reads and writes) is plain old data (POD). - POD should have only public data members and non-copy constructors. - It must not have any methods other than constructors, not even a - destructor or assignment operators, nor protected or private data. - Note that this definition of POD is not the definition used in the - C++ standard, which limits the contained data types to types that - have no constructors, destructors, or methods. - - * Avoid using friend - Avoid declaring friend functions or classes. They're sometimes - necessary for operator overloading. If you find it necessary to - add friends to some class C, consider creating a utility class U. - A utility class is declared as the only friend of C and provides - only static methods. Each method forwards to a private method on - an object of C type (passed as a parameter to the U's method). - This makes maintenance easier since only U has friend access to C - and finding any call to U is trivial (they're prefixed by U::). - - * Don't test for NULL when using `delete' or `delete[]' - It's unnecessary since delete does it anyway. - -- Makefiles - Automake's makefiles (named Makefile.am) have a few requirements: - * Define the following macro at the top of the file: - NULL = - * Lists should have one item per line and end in $(NULL). For - example: - EXTRA_DIST = \ - kiwi.txt \ - mango.cpp \ - papaya.h \ - $(NULL) - Indentation must use tabs in a makefile. Line continuations - (backslashes) should be aligned using tabs. - * Lists of files should be sorted alphabetically in groups (e..g - source files, header files, then other files). Lists of - subdirectories must be in the desired build order. - -- Source Formatting - Every project has its own formatting style and no style satisfies - everyone. New code should be consistent with existing code: - - * All files should include the copyright and license notice - * Use tabs to indent - * Tabs are 4 columns - * Lines should not extend past the 80th column - * Open braces ({) go on same line as introducing statement - `for (i = 0; i < 10; ++i) {' not - for (i = 0; i < 10; ++i) - { - * Close braces line up with introducing statement - * Open brace for function is on a line by itself in first column - * Close brace for function lines up with open brace - * Always use braces on: if, else, for, while, do, switch - * `else {' goes on its own line - * Always explicitly test pointers against NULL - e.g. `if (ptr == NULL)' not `if (ptr)' - * Always explicitly test integral values against 0 - e.g. `if (i == 0)' not `if (i)' - * Put spaces around binary operators and after statements - e.g. `if (a == b) {' not `if(a==b){' - * C'tor initializers are one per line, indented one tab stop - * Other indentation should follow existing practice - * Use Qt style comments for extraction by doxygen (i.e. //! and /*!) - * Mark incomplete or buggy code with `FIXME' - -- Other - * calls to LOG() should always be all on one line (even past column 80) - - -Class Relationships -------------------- - -The doxygen documentation can help in understanding the relationships -between objects. Use `make doxygen' in the top level directory to -create the doxygen documentation into doc/doxygen/html. You must have -doxygen installed, of course. - -FIXME -- high level overview of class relationships - - -Portability ------------ - -Synergy is mostly platform independent code but necessarily has -platform dependent parts. The mundane platform dependent parts -come from the usual suspects: networking, multithreading, file -system, high resolution clocks, system logging, etc. Porting -these parts is relatively straightforward. - -Synergy also has more esoteric platform dependent code. The -functions for low-level event interception and insertion, -warping the cursor position, character to keyboard event -translation, clipboard manipulation, and screen saver control -are often obscure and poorly documented. Unfortunately, these -are exactly the functions synergy requires to do its magic. - -Porting synergy to a new platform requires the following steps: - -- Setting up the build -- Adjusting lib/common/common.h -- Implementing lib/arch -- Implementing lib/platform -- Tweaks - -Setting up the build: - -The first phase is simply to create the files necessary to build the -other files. On Unix, synergy uses autoconf/automake which produces -a `configure' script that generates makefiles. On Windows, synergy -uses Visual C++ workspace and project files. If you're porting to -another Unix variant, you may need to adjust `configure.in', -`acinclude.m4', and Unix flavor dependent code in lib/arch. Note -especially the SYSAPI_* and WINAPI_* macro definitions in -ARCH_CFLAGS. Exactly one of each must be defined. It should also -add AM_CONDITIONALs if a new SYSAPI_* or WINAPI_* was added. - -Adjusting lib/common/common.h: - -The lib/common/common.h header file is included directly or indirectly -by every other file. Its primary job is to include config.h, which -defines macros depending on what the 'configure' script discovered -about the system. If the platform does not use the 'configure' script -it must define the appropriate SYSAPI_* and WINAPI_* macro. It may -also do other platform specific setup. - -Adjusting lib/common/BasicTypes.h: - -No changes should be necessary in BasicTypes.h. However, if the -platform's system header files define SInt8, et al. you may need -to adjust the typedefs to match the system's definitions. - -Implementing lib/arch: - -Much platform dependent code lives in lib/arch. There are several -interface classes there and they must all be implemented for each -platform. See the interface header files for more information. - -Platforms requiring special functions should create a class named -CArchMiscXXX where XXX is the platform name. The class should have -only static methods. Clients can include the appropriate header -file and make calls directly, surrounded by a suitable #ifdef/#endif. - -If using automake, the Makefile.am should list the system specific -files in a XXX_SOURCE_FILES macro where XXX matches the appropriate -AM_CONDITIONAL symbol. XXX_SOURCE_FILES must be added to EXTRA_DIST -and the following added above the INCLUDES macro: - - if XXX - libarch_a_SOURCES = \ - $(COMMON_SOURCE_FILES) \ - $(XXX_SOURCE_FILES) \ - $(NULL) - endif - -Implementing lib/platform: - -Most of the remaining platform dependent code lives in lib/platform. -The code there implements platform dependent window, clipboard, keyboard -and screen saver handling. If a platform is named XXX then the following -classes should be derived and implemented: - - * CXXXClipboard : IClipboard - Provides clipboard operations. Typically, this class will - have helper classes for converting between various clipboard - data formats. - - * CXXXEventQueueBuffer : IEventQueueBuffer - Provides operations for waiting for, posting and retrieving events. - Also provides operations for creating and deleting timers. - - * CXXXKeyState : CKeyState - Provides operations for synthesizing key events and for mapping a - key ID to a sequence of events to generate that key. - - * CXXXScreen : IScreen, IPrimaryScreen, ISecondaryScreen, IPlatformScreen - Provides screen operations. - - * CXXXScreenSaver : IScreenSaver - Provides screen saver operations. - -If using automake, the Makefile.am should list the window system -specific files in a XXX_SOURCE_FILES macro where XXX matches the -appropriate AM_CONDITIONAL symbol. XXX_SOURCE_FILES must be added -to EXTRA_DIST and the following added above the INCLUDES macro: - - if XXX - libplatform_a_SOURCES = $(XXX_SOURCE_FILES) - endif - -Tweaks: - -Finally, each platform typically requires various adjustments here -and there. In particular, synergyc.cpp and synergys.cpp usually -require platform dependent code for the main entry point, parsing -arguments, and reporting errors. Also, some platforms may benefit -from a graphical user interface front end. These are generally -not portable and synergy doesn't provide any infrastructure for -the code common to any platform, though it may do so someday. -There is, however, an implementation of a GUI front end for Windows -that serves as an example. diff --git a/doc/about.html b/doc/about.html deleted file mode 100644 index aadd5764..00000000 --- a/doc/about.html +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - About Synergy - - -

-With synergy, all the computers on your desktop form a single virtual -screen. You use the mouse and keyboard of only one of the computers -while you use all of the monitors on all of the computers. -You tell synergy how many screens you have and their positions relative -to one another. Synergy then detects when the mouse moves off -the edge of a screen and jumps it instantly to the neighboring screen. -The keyboard works normally on each screen; input goes to whichever -screen has the cursor. -

-In this example, the user is moving the mouse from left to right. -When the cursor reaches the right edge of the left screen it jumps -instantly to the left edge of the right screen. -

-

-

-You can arrange screens side-by-side, above and below one another, -or any combination. You can even have a screen jump to the opposite -edge of itself. Synergy also understands multiple screens attached -to the same computer. -

-Running a game and don't want synergy to jump screens? No problem. -Just toggle Scroll Lock. Synergy keeps the cursor on the same screen -when Scroll Lock is on. (This can be configured to another hot key.) -

-Do you wish you could cut and paste between computers? Now you can! -Just copy text, HTML, or an image as you normally would on one screen -then switch to another screen and paste it. It's as if all your -computers shared a single clipboard (and separate primary selection for -you X11 users). It even converts newlines to each computer's native -form so cut and paste between different operating systems works -seamlessly. And it does it all in Unicode so any text can be copied. -

-

-Do you use a screen saver? With synergy all your screen savers act in -concert. When one starts they all start. When one stops they all -stop. And, if you require a password to unlock the screen, you'll -only have to enter a password on one screen. -

-If you regularly use multiple computers on one desk, give synergy a -try. You'll wonder how you ever lived without it. -

- - - diff --git a/doc/authors.html b/doc/authors.html deleted file mode 100644 index 3fe7b4f1..00000000 --- a/doc/authors.html +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - Synergy Authors - - -

-

Synergy Authors

-

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Chris Schoeneman crs23@users.sourceforge.no_spam.net Creator, owner, primary developer
Ryan Breen ryan@ryanbreen.no_spam.com Initial Mac OS X port
Guido Poschta moolder@gmx.no_spam.net Windows installer
Bertrand Landry Hetu bertrand@landryhetu.no_spam.com Mac OS X port
Tom Chadwick vttom@users.sourceforge.no_spam.net PageUp/PageDown on X servers without mouse wheel support
Brent Priddy toopriddy@users.sourceforge.no_spam.net Re-resolving server hostname on each connection
Marc-Antoine Ruel maruel@users.sourceforge.no_spam.net Visual Studio 2005 port
-

-To avoid spam bots, the above email addresses have ".no_spam" -hidden near the end. If you copy and paste the text be sure to -remove it. -

- - - diff --git a/doc/autostart.html b/doc/autostart.html deleted file mode 100644 index 0343048a..00000000 --- a/doc/autostart.html +++ /dev/null @@ -1,428 +0,0 @@ - - - - - - - - Synergy Autostart Guide - - -

-

Starting synergy automatically

-

-You can configure synergy to start automatically when the computer -starts or when you log in. The steps to do that are different on -each platform. Note that changing these configurations doesn't -actually start or stop synergy. The changes take effect the next -time you start your computer or log in. -

-

Windows

-

-Start synergy and click the Configure... button -by the text Automatic Startup. The -Auto Start dialog will pop up. -If an error occurs then correct the problem and click -Configure again. -

-On the Auto Start dialog you'll configure -synergy to start or not start automatically when the computer starts -or when you log in. You need Administrator access rights to start -synergy automatically when the computer starts. The dialog will let -you know if you have sufficient permission. -

-If synergy is already configured to automatically start then there -will be two Uninstall buttons, at most one -of which is enabled. Click the enabled button, if any, to tell -synergy to not start automatically. -

-If synergy is not configured to start automatically then there will -be two Install buttons. If you have -sufficient permission to have synergy start automatically when the -computer does then the Install button in the -When Computer Starts box will be enabled. -Click it to have synergy start for all users when the computer starts. -In this case, synergy will be available during the login screen. -Otherwise, click the Install button in the -When You Log In box to have synergy -automatically start when you log in. -

-

Unix

-

-Synergy requires an X server. That means a server must be -running and synergy must be authorized to connect to that server. -It's best to have the display manager start synergy. You'll need -the necessary (probably root) permission to modify the display -manager configuration files. If you don't have that permission -you can start synergy after logging in via the -.xsession file. -

-Typically, you need to edit three script files. The first file -will start synergy before a user logs in, the second will kill -that copy of synergy, and the third will start it again after -the user logs in. -

-The contents of the scripts varies greatly between systems so -there's no one definite place where you should insert your edits. -However, these scripts often exit before reaching the bottom so -put the edits near the top of the script. -

-The location and names of these files depend on the operating -system and display manager you're using. A good guess for the -location is /etc/X11. If you use kdm -then try looking in /etc/kde3 or -/usr/kde/version/share/config. -Typical file names are: -

- - - - - - -
      xdm    kdm    gdm
1 xdm/Xsetup kdm/Xsetup gdm/Init/Default (*)
2 xdm/Xstartup kdm/Xstartup gdm/PostLogin/Default (*)
3 xdm/Xsession kdm/Xsession gdm/Sessions/Default (*, **)
-
-

-*) The Default file is used if no other -suitable file is found. gdm will try -displayname (e.g. :0) -and hostname (e.g. somehost), -in that order, before and instead of Default. -
-**) gdm may use gdm/Xsession, -xdm/Xsession or -dm/Xsession if -gdm/Sessions/Default doesn't exist. -

-For a synergy client, add the following to the first file: - - /usr/bin/killall synergyc - sleep 1 - /usr/bin/synergyc [<options>] synergy-server-hostname - -Of course, the path to synergyc depends on where you installed it -so adjust as necessary. -

-Add to the second file: - - /usr/bin/killall synergyc - sleep 1 - -

-And to the third file: - - /usr/bin/killall synergyc - sleep 1 - /usr/bin/synergyc [<options>] synergy-server-hostname - -Note that <options> -must not include --f or --no-daemon or -the script will never exit and you won't be able to log in. -

-The changes are the same for the synergy server except replace -synergyc with synergys -and use the appropriate synergys command -line options. Note that the -first script is run as root so synergys will look for the configuration -file in root's home directory then in /etc. -Make sure it exists in one of those places or use the ---config config-pathname -option to specify its location. -

-Note that some display managers (xdm and kdm, but not gdm) grab -the keyboard and do not release it until the user logs in for -security reasons. This prevents a synergy server from sharing -the mouse and keyboard until the user logs in. It doesn't -prevent a synergy client from synthesizing mouse and keyboard -input, though. -

-If you're configuring synergy to start only after you log in then edit -your .xsession file. Add just what you -would add to the third file above. -

-

Mac OS X

-

-[By Tor Slettnes] -

-There are three different ways to automatically start Synergy -(client or server) on Mac OS X: -

-

    -
  1. - The first method involves creating a StartupItem - at the system level, which is executed when the machine starts up - or shuts down. This script will run in the background, and - relaunch synergy as needed. -

    -

    -
    Pros:
    -
    - Synergy is persistent, so this allows for a multi-user - setup and interactive logins. -
    -
    Cons:
    -
    - The synergy process does not have access to the clipboard - of the logged-in user. -
    -
    -
  2. -

    -

  3. - The second method will launch Synergy from the - LoginWindow application, once a particular - user has logged in. -

    -

    -
    Pros:
    -
    - The synergy process inherits the - $SECURITYSESSIONID environment variable, - and therefore copy/paste works. -
    -
    Cons:
    -
    - Once the user logs out, synergy dies, and no remote - control is possible. -
    -
    -
  4. -

    -

  5. - The third method is to launch a startup script from the - "Startup Items" tab under System Preferences -> Accounts. -

    -

    -
    Pros:
    -
    - Does not require root (Administrator) access -
    -
    Cons:
    -
    - Once the user logs out, synergy dies, and no remote - control is possible. -
    -
    -
  6. -
-

-The text below describes how to implement a Synergy client using -the first two methods simultaneously. This way, Synergy is -always running, and the clipboard is available when someone is -logged in. A Mac OS X Synergy server setup will be quite similar. -

-1. Create a System Level Startup Item -

-

    -
  • - Open a Terminal window, and become root: - - $ sudo su - - -
  • -
  • - Create a folder for this item: - - # mkdir -p /Library/StartupItems/Synergy - -
  • -
  • - In this folder, create a new script file by the same name as - the directory itself, Synergy. This script - should contain the following text: -

    - -#!/bin/sh -. /etc/rc.common -  -run=(/usr/local/bin/synergyc -n $(hostname -s) -1 -f synergy-server) -  -KeepAlive () -{ - proc=${1##*/} -  - while [ -x "$1" ] - do - if ! ps axco command | grep -q "^${proc}\$" - then - "$@" - fi -  - sleep 3 - done -} -  -StartService () -{ - ConsoleMessage "Starting Synergy" - KeepAlive "${run[@]}" & -} -  -StopService () -{ - return 0 -} -  -RestartService () -{ - return 0 -} -  -RunService "$1" - -

    - However, replace synergy-server with the actual - name or IP address of your Synergy server. -

    - Note that this scripts takes care not to start - Synergy if another instance is currently running. This - allows it to run in the background even when synergy is also - started independently, e.g. from the LoginWindow - application as described below. -

  • -
  • - Make this script executable: - - # chmod 755 /Library/StartupItems/Synergy/Synergy - -
  • -
  • - In the same folder, create a file named - StartupParameters.plist containing: -

    - -{ - Description = "Synergy Client"; - Provides = ("Synergy"); - Requires = ("Network"); - OrderPreference = "None"; -} - -

  • -
-

-That's it! If you want to test this setup, you can run the -startup script as follows: -

- - # /Library/StartupItems/Synergy/Synergy start - -

-Any errors, as well as output from Synergy, will be shown in -your terminal window. -

-Next time you reboot, Synergy should start automatically. -

-2. Run Synergy When a User Logs In -

-Each time a user successfully logs in via the console, the -LoginWindow application creates a unique session -cookie and stores it in the environment variable -$SECURITYSESSIONID. For copy and paste operations -to work, Synergy needs access to this environment variable. In -other words, Synergy needs to be launched (directly or -indirectly) via the LoginWindow application. -

-However, in order to kill any synergy processes started at the -system level (as described above), we need root access. Thus, -launching Synergy within the User's environment (e.g. via the -Startup Items tab in System Preferences -> Accounts) is not an -option that work in conjunction with the method above. -

-Fortunately, the LoginWindow application provides -a "hook" for running a custom program (as root, with the username provided as -the first and only argument) once a user has authenticated, but -before the user is logged in. -

-Unfortunately, only one such hook is available. If you have -already installed a Login Hook, you may need to add the text -from below to your existing script, rather than creating a new -one. -

-

    -
  • - Launch a Terminal window, and become root: - - $ sudo su - - -
  • -

    -

  • - Find out if a LoginHook already exists: - - # defaults read com.apple.loginwindow LoginHook - - This will either show the full path to a script or - executable file, or the text: - - The domain/default pair of (com.apple.loginwindow, LoginHook) does not exist - - In the former case, you need to modify your existing script, - and/or create a "superscript" which in turn calls your - existing script plus the one we will create here. -

    - The rest of this text assumes that this item did not already - exist, and that we will create a new script. -

  • -
  • - Create a folder in which we will store our custom startup - script: - - # mkdir -p /Library/LoginWindow - -
  • -
  • - In this folder, create a new script file (let's name it - LoginHook.sh), containing the following text: -

    - -#!/bin/sh -prog=(/usr/local/bin/synergyc -n $(hostname -s) ip-address-of-server) -  -### Stop any currently running Synergy client -killall ${prog[0]##*/} -  -### Start the new client -exec "${prog[@]}" - -

  • -
  • - Make this script executable: - - # chmod 755 /Library/LoginWindow/LoginHook.sh - -
  • -
  • - Create a login hook to call the script you just created: - - # defaults write com.apple.loginwindow LoginHook /Library/LoginWindow/LoginHook.sh - -
  • -
-

-More information on setting up login hooks can be found at -Apple. -

-When running the Synergy client, you may need to use the IP -address of the Synergy server rather than its host name. -Specifically, unless you have listed the server in your -local /etc/hosts file or in your local NetInfo -database, name services (i.e. DNS) may not yet be available by the -time you log in after power-up. synergyc will -quit if it cannot resolve the server name. -

-(This is not an issue with the previous method, because the -StartupParameters.plist file specifies that this -script should not be run until "network" is available). -

-3. Good Luck! -

-Remember to look in your system log on both your server and your -client(s) for clues to any problems you may have -(/var/log/system.log on your OS X box, typically -/var/log/syslog on Linux boxes). -

- - - diff --git a/doc/banner.html b/doc/banner.html deleted file mode 100644 index eed66918..00000000 --- a/doc/banner.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - Synergy Header - - - - - -
Synergy
- - diff --git a/doc/border.html b/doc/border.html deleted file mode 100644 index ce45847a..00000000 --- a/doc/border.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - Synergy - - - -
- - diff --git a/doc/compiling.html b/doc/compiling.html deleted file mode 100644 index 69321913..00000000 --- a/doc/compiling.html +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - - - Building and Installing Synergy - - -

-

Prerequisites for building

-

-To build synergy from the sources you'll need the following: -

    -
  • Windows -
      -
    • Microsoft Windows SDK for Vista; or -
    • VC++ 6.0 or up should work -
    -

    -

  • Unix -
      -
    • gcc 2.95 or up -
    • X11R4 or up headers and libraries -
    -

    -

  • Mac OS X -
      -
    • gcc 2.95 or up -
    • Carbon development headers and libraries -
    -
-

-

Configuring the build

-

-This step is not necessary on Windows. -

-To configure the build for your platform use the configure script: -

-  ./configure
-
-For a list of options to configure use: -
-  ./configure --help
-
-On Solaris you may need to use: -
-  ./configure --x-includes=/usr/openwin/include --x-libraries=/usr/openwin/lib
-
-so synergy can find the X11 includes and libraries. -

-

Building

-

    -
  • Windows -

    - Open a command prompt window (cmd.exe or command.exe). If necessary - run vcvars.bat, created when VC++ or Visual Studio was installed. (Use - search to find it.) It's necessary to run the file if you didn't have - the installer set up environment variables for you. Then enter: -

    -  nmake /nologo /f Makefile.win
    -  
    - This will build the programs into build\Release. -

    -
  • Unix or Mac OS X -

    - Simply enter: -

    -  make
    -  
    - This will build the client and server and leave them in their - respective source directories. -

    -
-

-

Installing

-

    -
  • Windows -

    - You'll need NSIS, - the Nullsoft Scriptable Install System. As in the building on Windows - description above, enter: -

    -  nmake /nologo /f Makefile.win installer
    -  
    - to build build\Release\SynergyInstaller.exe. Run - this to install synergy. -

    - Alternatively, you can simply copy the following files from the - build\Release - directory to a directory you choose (perhaps under the - Program Files directory): -

      -
    • synergy.exe -
    • synergyc.exe -
    • synergys.exe -
    • synrgyhk.dll -
    -

    -
  • Unix or Mac OS X -

    -

    -  make install
    -  
    - will install the client and server into - /usr/local/bin unless you - specified a different directory when you ran configure. -

    - - - diff --git a/doc/configuration.html b/doc/configuration.html deleted file mode 100644 index 6c1c8baa..00000000 --- a/doc/configuration.html +++ /dev/null @@ -1,686 +0,0 @@ - - - - - - - - Synergy Configuration Guide - - -

    -

    Synergy Configuration File Format

    -

    -The synergy server requires configuration. It will try certain -pathnames to load the configuration file if you don't specify a -path using the --config command line -option. synergys --help reports those -pathnames. -

    -The configuration file is a plain text file. Use any text editor -to create the configuration file. The file is broken into sections -and each section has the form: - - section: name - args - end - -Comments are introduced by # and continue to -the end of the line. name must be one of the -following: -

      -
    • screens -
    • aliases -
    • links -
    • options -
    -See below for further explanation of each section type. The -configuration file is case-sensitive so Section, -SECTION, and section -are all different and only the last is valid. Screen names are the -exception; screen names are case-insensitive. -

    -The file is parsed top to bottom and names cannot be used before -they've been defined in the screens or -aliases sections. So the -links and aliases -must appear after the screens and links -cannot refer to aliases unless the aliases -appear before the links. -

    -

    screens

    -

    -args is a list of screen names, one name per -line, each followed by a colon. Names are arbitrary strings but they -must be unique. The hostname of each computer is recommended. (This -is the computer's network name on win32 and the name reported by the -program hostname on Unix and OS X. Note -that OS X may append .local to the name you -gave your computer; e.g. somehost.local.) -There must be a screen name for the server and each client. Each -screen can specify a number of options. Options have the form -name = -value and are listed one per line -after the screen name. -

    -Example: - - section: screens - moe: - larry: - halfDuplexCapsLock = true - halfDuplexNumLock = true - curly: - meta = alt - end - -This declares three screens named moe, -larry, and curly. -Screen larry has half-duplex Caps Lock and -Num Lock keys (see below) and screen curly -converts the meta modifier key to the alt modifier key. -

    -A screen can have the following options: -

      -
    • halfDuplexCapsLock = {true|false} -

      - This computer has a Caps Lock key that doesn't report a - press and a release event when the user presses it but - instead reports a press event when it's turned on and a - release event when it's turned off. If Caps Lock acts - strangely on all screens then you may need to set this - option to true - on the server screen. If it acts strangely on one - screen then that screen may need the option set to - true. -

      -

    • halfDuplexNumLock = {true|false} -

      - This is identical to halfDuplexCapsLock - except it applies to the Num Lock key. -

      -

    • halfDuplexScrollLock = {true|false} -

      - This is identical to halfDuplexCapsLock - except it applies to the Scroll Lock key. Note that, by default, - synergy uses Scroll Lock to keep the cursor on the current screen. That - is, when Scroll Lock is toggled on, the cursor is locked to the screen - that it's currently on. You can use that to prevent accidental switching. - You can also configure other hot keys to do that; see - lockCursorToScreen. -

      -

    • switchCorners = <corners> -

      - See switchCorners below. -

      -

    • switchCornerSize = N -

      - See switchCornerSize below. -

      -

    • xtestIsXineramaUnaware = {true|false} -

      - This option works around a bug in the XTest extension - when used in combination with Xinerama. It affects - X11 clients only. Not all versions of the XTest - extension are aware of the Xinerama extension. As a - result, they do not move the mouse correctly when - using multiple Xinerama screens. This option is - currently true by default. If - you know your XTest extension is Xinerama aware then set - this option to false. -

      -

    • shift = {shift|ctrl|alt|meta|super|none}
      - ctrl = {shift|ctrl|alt|meta|super|none}
      - alt = {shift|ctrl|alt|meta|super|none}
      - meta = {shift|ctrl|alt|meta|super|none}
      - super = {shift|ctrl|alt|meta|super|none}
      -

      - Map a modifier key pressed on the server's keyboard to - a different modifier on this client. This option only - has an effect on a client screen; it's accepted and - ignored on the server screen. -

      - You can map, say, the shift key to shift (the default), - ctrl, alt, meta, super or nothing. Normally, you - wouldn't remap shift or ctrl. You might, however, have - an X11 server with meta bound to the Alt keys. To use - this server effectively with a windows client, which - doesn't use meta but uses alt extensively, you'll want - the windows client to map meta to alt (using - meta = alt). -

      -

    -

    -

    aliases

    -

    - args is a list of screen names just like - in the screens section except each screen - is followed by a list of aliases, one per line, not followed - by a colon. An alias is a screen name and must be unique. During - screen name lookup each alias is equivalent to the screen name it - aliases. So a client can connect using its canonical screen name - or any of its aliases. -

    - Example: - - section: aliases - larry: - larry.stooges.com - curly: - shemp - end - - Screen larry is also known as - larry.stooges.com and can connect as - either name. Screen curly is also - known as shemp (hey, it's just an example). -

    -

    links

    -

    - args is a list of screen names just like - in the screens section except each screen - is followed by a list of links, one per line. Each link has the - form {left|right|up|down}[<range>] = - name[<range>]. A link indicates which - screen is adjacent in the given direction. -

    - Each side of a link can specify a range which defines a portion - of an edge. A range on the direction is the portion of edge you can - leave from while a range on the screen is the portion of edge you'll - enter into. Ranges are optional and default to the entire edge. All - ranges on a particular direction of a particular screen must not - overlap. -

    - A <range> is written as (<start>,<end>). - Both start and end - are percentages in the range 0 to 100, inclusive. The start must be - less than the end. 0 is the left or top of an edge and 100 is the - right or bottom. -

    - Example: - - section: links - moe: - right = larry - up(50,100) = curly(0,50) - larry: - left = moe - up(0,50) = curly(50,100) - curly: - down(0,50) = moe - down(50,100) = larry(0,50) - end - - This indicates that screen larry is to - the right of screen moe (so moving the - cursor off the right edge of moe would - make it appear at the left edge of larry), - the left half of - curly is above the right half of - moe, - moe is to the left of - larry (edges are not necessarily symmetric - so you have to provide both directions), the right half of - curly is above the left half of - larry, all of moe - is below the left half of curly, and the - left half of larry is below the right half of - curly. -

    - Note that links do not have to be - symmetrical; for instance, here the edge between - moe and curly - maps to different ranges depending on if you're going up or down. - In fact links don't have to be bidirectional. You can configure - the right of moe to go to - larry without a link from the left of - larry to moe. - It's possible to configure a screen with no outgoing links; the - cursor will get stuck on that screen unless you have a hot key - configured to switch off of that screen. -

    -

    options

    -

    - args is a list of lines of the form - name = value. These set the global - options. -

    - Example: - - section: options - heartbeat = 5000 - switchDelay = 500 - end - -

    - You can use the following options: -

      -
    • heartbeat = N -

      - The server will expect each client to send a message no - less than every N milliseconds. - If no message arrives from a client within - 3N seconds the server forces that - client to disconnect. -

      - If synergy fails to detect clients disconnecting while - the server is sleeping or vice versa, try using this - option. -

      -

    • switchCorners = <corners> -

      - Synergy won't switch screens when the mouse reaches the edge of - the screen if it's in a listed corner. The size of all corners - is given by the switchCornerSize - option. -

      - Corners are specified by a list using the following names: -

        -
      • none -- no corners -
      • top-left -- the top left corner -
      • top-right -- the top right corner -
      • bottom-left -- the bottom left corner -
      • bottom-right -- the bottom right corner -
      • left -- top and bottom left corners -
      • right -- top and bottom right corners -
      • top -- left and right top corners -
      • bottom -- left and right bottom corners -
      • all -- all corners -
      -

      - The first name in the list is one of the above names and defines - the initial set of corners. Subsequent names are prefixed with - + or - to add the corner to or remove the corner from the set, - respectively. For example: -

      - - all -left +top-left - -

      - starts will all corners, removes the left corners (top and bottom) - then adds the top-left back in, resulting in the top-left, - bottom-left and bottom-right corners. -

      -

    • switchCornerSize = N -

      - Sets the size of all corners in pixels. The cursor must be within - N pixels of the corner to be considered - to be in the corner. -

      -

    • switchDelay = N -

      - Synergy won't switch screens when the mouse reaches the - edge of a screen unless it stays on the edge for - N - milliseconds. This helps prevent unintentional - switching when working near the edge of a screen. -

      -

    • switchDoubleTap = N -

      - Synergy won't switch screens when the mouse reaches the - edge of a screen unless it's moved away from the edge - and then back to the edge within N - milliseconds. With - the option you have to quickly tap the edge twice to - switch. This helps prevent unintentional switching - when working near the edge of a screen. -

      -

    • screenSaverSync = {true|false} -

      - If set to false then synergy - won't synchronize screen savers. Client screen savers - will start according to their individual configurations. - The server screen saver won't start if there is input, - even if that input is directed toward a client screen. -

      -

    • relativeMouseMoves = {true|false} -

      - If set to true then secondary - screens move the mouse using relative rather than absolute - mouse moves when and only when the cursor is locked to the - screen (by Scroll Lock or a configured - hot key). - This is intended to make synergy work better with certain - games. If set to false or not - set then all mouse moves are absolute. -

      -

    • keystroke(key) = actions -

      - Binds the key combination key to the - given actions. key - is an optional list of modifiers (shift, - control, alt, - meta or super) - optionally followed by a character or a key name, all separated by - + (plus signs). You must have either - modifiers or a character/key name or both. See below for - valid key names. -

      - Actions are described below. -

      - Keyboard hot keys are handled while the cursor is on the primary - screen and secondary screens. Separate actions can be assigned - to press and release. -

      -

    • mousebutton(button) = actions -

      - Binds the modifier and mouse button combination - button to the given - actions. button - is an optional list of modifiers (shift, - control, alt, - meta or super) - followed by a button number. The primary button (the - left button for right handed users) is button 1, the middle button - is 2, etc. -

      - Actions are described below. -

      - Mouse button actions are not handled while the cursor is on the - primary screen. You cannot use these to perform an action while - on the primary screen. Separate actions can be assigned to press - and release. -

      -

    - You can use both the switchDelay and - switchDoubleTap options at the same - time. Synergy will switch when either requirement is satisfied. -

    -Actions are two lists of individual actions separated -by commas. The two lists are separated by a semicolon. Either list can be -empty and if the second list is empty then the semicolon is optional. The -first list lists actions to take when the condition becomes true (e.g. the -hot key or mouse button is pressed) and the second lists actions to take -when the condition becomes false (e.g. the hot key or button is released). -The condition becoming true is called activation and becoming false is -called deactivation. -Allowed individual actions are: -

      -
    • keystroke(key[,screens]) -
    • keyDown(key[,screens]) -
    • keyUp(key[,screens]) -

      - Synthesizes the modifiers and key given in key - which has the same form as described in the - keystroke option. If given, - screens lists the screen or screens to - direct the event to, regardless of the active screen. If not - given then the event is directed to the active screen only. - (Due to a bug, keys cannot be directed to the server while on a - client screen.) -

      - keyDown synthesizes a key press and - keyUp synthesizes a key release. - keystroke synthesizes a key press on - activation and a release on deactivation and is equivalent to - a keyDown on activation and - keyUp on deactivation. -

      - screens is either * - to indicate all screens or a colon (:) separated list of screen - names. (Note that the screen name must have already been encountered - in the configuration file so you'll probably want to put actions at - the bottom of the file.) -

      -

    • mousebutton(button) -
    • mouseDown(button) -
    • mouseUp(button) -

      - Synthesizes the modifiers and mouse button given in - button - which has the same form as described in the - mousebutton option. -

      - mouseDown synthesizes a mouse press and - mouseUp synthesizes a mouse release. - mousebutton synthesizes a mouse press on - activation and a release on deactivation and is equivalent to - a mouseDown on activation and - mouseUp on deactivation. -

      -

    • lockCursorToScreen(mode) -

      - Locks the cursor to or unlocks the cursor from the active screen. - mode can be off - to unlock the cursor, on to lock the - cursor, or toggle to toggle the current - state. The default is toggle. If the - configuration has no lockCursorToScreen - action and Scroll Lock is not used as a hot key then Scroll Lock - toggles cursor locking. -

      -

    • switchToScreen(screen) -

      - Jump to screen with name or alias screen. -

      -

    • switchInDirection(dir) -

      - Switch to the screen in the direction dir, - which may be one of left, - right, up or - down. -

      -

    • keyboardBroadcast(mode[,screens]) -

      - Turns broadcasting of keystrokes to multiple screens on and off. When - turned on all key presses and releases are sent to all of the screens - listed in screens. If not given, empty or - * then keystrokes are broadcast to all screens. - (However, due to a bug, keys cannot be sent to the server while on a - client screen.) -

      - mode can be off - to turn broadcasting off, on to turn it - on, or toggle to toggle the current - state. The default is toggle. -

      - screens is either * - to indicate all screens or a colon (:) separated list of screen - names. (Note that the screen name must have already been encountered - in the configuration file so you'll probably want to put actions at - the bottom of the file.) -

      - Multiple keyboardBroadcast actions may be - configured with different screens. The most - recently performed action defines the screens to broadcast to. -

      -

    -

    -Examples: -

      -
    • keystroke(alt+left) = switchInDirection(left) -

      - Switches to the screen to left when the left arrow key is pressed - in combination with the Alt key. -

      -

    • keystroke(shift+control+alt+super) = switchToScreen(moe) -

      - Switches to screen moe when all of the - Shift, Control, Alt, and Super modifier keys are pressed together. -

      -

    • keystroke(alt+f1) = ; lockCursorToScreen(toggle) -

      - Toggles locking the cursor to the screen when Alt+F1 is released. -

      -

    • mousebutton(2) = mouseDown(control+1) ; mouseUp(control+1) -

      - While on a secondary screen clicking the middle mouse button will - become a Control click of the primary button. -

      -

    • keystroke(super+f1) = keystroke(super+L,larry), keystroke(control+alt+delete,curly) -

      - Pressing Super+F1 (on any screen) will synthesize Super+L on screen - larry and Control+Alt+Delete on screen - curly. -

      -

    -

    -Valid key names are: -

      -
    • AppMail -
    • AppMedia -
    • AppUser1 -
    • AppUser2 -
    • AudioDown -
    • AudioMute -
    • AudioNext -
    • AudioPlay -
    • AudioPrev -
    • AudioStop -
    • AudioUp -
    • BackSpace -
    • Begin -
    • Break -
    • Cancel -
    • CapsLock -
    • Clear -
    • Delete -
    • Down -
    • Eject -
    • End -
    • Escape -
    • Execute -
    • F1 -
    • F2 -
    • F3 -
    • F4 -
    • F5 -
    • F6 -
    • F7 -
    • F8 -
    • F9 -
    • F10 -
    • F11 -
    • F12 -
    • F13 -
    • F14 -
    • F15 -
    • F16 -
    • F17 -
    • F18 -
    • F19 -
    • F20 -
    • F21 -
    • F22 -
    • F23 -
    • F24 -
    • F25 -
    • F26 -
    • F27 -
    • F28 -
    • F29 -
    • F30 -
    • F31 -
    • F32 -
    • F33 -
    • F34 -
    • F35 -
    • Find -
    • Help -
    • Home -
    • Insert -
    • KP_0 -
    • KP_1 -
    • KP_2 -
    • KP_3 -
    • KP_4 -
    • KP_5 -
    • KP_6 -
    • KP_7 -
    • KP_8 -
    • KP_9 -
    • KP_Add -
    • KP_Begin -
    • KP_Decimal -
    • KP_Delete -
    • KP_Divide -
    • KP_Down -
    • KP_End -
    • KP_Enter -
    • KP_Equal -
    • KP_F1 -
    • KP_F2 -
    • KP_F3 -
    • KP_F4 -
    • KP_Home -
    • KP_Insert -
    • KP_Left -
    • KP_Multiply -
    • KP_PageDown -
    • KP_PageUp -
    • KP_Right -
    • KP_Separator -
    • KP_Space -
    • KP_Subtract -
    • KP_Tab -
    • KP_Up -
    • Left -
    • LeftTab -
    • Linefeed -
    • Menu -
    • NumLock -
    • PageDown -
    • PageUp -
    • Pause -
    • Print -
    • Redo -
    • Return -
    • Right -
    • ScrollLock -
    • Select -
    • Sleep -
    • Space -
    • SysReq -
    • Tab -
    • Undo -
    • Up -
    • WWWBack -
    • WWWFavorites -
    • WWWForward -
    • WWWHome -
    • WWWRefresh -
    • WWWSearch -
    • WWWStop -
    • Space -
    • Exclaim -
    • DoubleQuote -
    • Number -
    • Dollar -
    • Percent -
    • Ampersand -
    • Apostrophe -
    • ParenthesisL -
    • ParenthesisR -
    • Asterisk -
    • Plus -
    • Comma -
    • Minus -
    • Period -
    • Slash -
    • Colon -
    • Semicolon -
    • Less -
    • Equal -
    • Greater -
    • Question -
    • At -
    • BracketL -
    • Backslash -
    • BracketR -
    • Circumflex -
    • Underscore -
    • Grave -
    • BraceL -
    • Bar -
    • BraceR -
    • Tilde -
    -Additionally, a name of the form \uXXXX where -XXXX is a hexadecimal number is interpreted as -a unicode character code. -Key and modifier names are case-insensitive. Keys that don't exist on -the keyboard or in the default keyboard layout will not work. -

    - - - diff --git a/doc/contact.html b/doc/contact.html deleted file mode 100644 index 1b378b85..00000000 --- a/doc/contact.html +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - Synergy Contact Info - - -

    -Use the following addresses to contact the synergy project: -

    - - - - - - - - - - - - - - - - -
    Bug reports: Add Synergy Bug
    Help: synergy-help@groundhog.pair..no_spamcom
    General: crs23@users.sourceforge..no_spamnet
    -

    -To avoid spam bots, the above email addresses have ".no_spam" -hidden near the end. If you copy and paste the text be sure to -remove it. -

    -Please check the - -bug list before reporting a bug. You may also find answers at the -synergy forums. -Emails for help asking questions answered on this site will go unanswered. -

    - - - diff --git a/doc/developer.html b/doc/developer.html deleted file mode 100644 index acfdff9a..00000000 --- a/doc/developer.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - Synergy Developer Documentation - - -

    -Synergy is reasonably well commented so reading the source code -should be enough to understand particular pieces. See the -doc/PORTING -file in the synergy source code for more high-level information. -

    -

    How it works

    -

    -The theory behind synergy is simple: the server captures mouse, -keyboard, clipboard, and screen saver events and forwards them to -one or more clients. If input is directed to the server itself -then the input is delivered normally. In practice, however, many -complications arise. -

    -First, different keyboard mappings can produce different characters. -Synergy attempts to generate the same character on the client as -would've been generated on the server, including appropriate modifier -keys (like Control and Alt). Non-character keys like Shift are also -synthesized if possible. Sometimes the client simply cannot create -the character or doesn't have a corresponding non-character key and -synergy must discard the event. Note that synergy won't necessarily -synthesize an event for the corresponding key on the client's -keyboard. For example, if the client or server can't distinguish -between the left and right shift keys then synergy can't be certain -to synthesize the shift on the same side of the keyboard as the user -pressed. -

    -Second, different systems have different clipboards and clipboard -formats. The X window system has a system-wide selection and -clipboard (and yet other buffers) while Microsoft Windows has only -a system-wide clipboard. Synergy has to choose which of these -buffers correspond to one another. Furthermore, different systems -use different text encodings and line breaks. Synergy mediates and -converts between them. -

    -Finally, there are no standards across operating systems for some -operations that synergy requires. Among these are: intercepting -and synthesizing events; enabling, disabling, starting and stopping -the screen saver; detecting when the screen saver starts; reading -and writing the clipboard(s). -

    -All this means that synergy must be customized to each operating -system (or windowing system in the case of X windows). Synergy -breaks platform differences into two groups. The first includes -the mundane platform dependent things: file system stuff, -multithreading, network I/O, multi-byte and wide character -conversion, time and sleeping, message display and logging, and -running a process detached from a terminal. This code lives in -lib/arch. -

    -The second includes screen and window management handling, user -event handling, event synthesis, the clipboards, and the screen -saver. This code lives in lib/platform. -

    -For both groups, there are particular classes or interfaces that -must be inherited and implemented for each platform. See the -doc/PORTING file in the synergy source -code for more information. -

    -

    Auto-generated Documentation

    -

    -Synergy can automatically generate documentation from the comments -in the code using doxygen. -Use make doxygen to build it yourself -from the source code into the doc/doxygen/html -directory. -

    -

    - - - diff --git a/doc/doxygen.cfg.in b/doc/doxygen.cfg.in deleted file mode 100644 index 4abf52f9..00000000 --- a/doc/doxygen.cfg.in +++ /dev/null @@ -1,898 +0,0 @@ -# Doxyfile 1.2.13.1 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# General configuration options -#--------------------------------------------------------------------------- - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. - -PROJECT_NAME = @PACKAGE@ - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = @VERSION@ - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = doc/doxygen - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Brazilian, Chinese, Croatian, Czech, Danish, Dutch, Finnish, French, -# German, Greek, Hungarian, Italian, Japanese, Korean, Norwegian, Polish, -# Portuguese, Romanian, Russian, Slovak, Slovene, Spanish and Swedish. - -OUTPUT_LANGUAGE = English - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = NO - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = NO - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = YES - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these class will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = NO - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited -# members of a class in the documentation of that class as if those members were -# ordinary class members. Constructors, destructors and assignment operators of -# the base classes will not be shown. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. - -FULL_PATH_NAMES = NO - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. It is allowed to use relative paths in the argument list. - -STRIP_FROM_PATH = - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. - -INTERNAL_DOCS = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = YES - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower case letters. If set to YES upper case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# users are adviced to set this option to NO. - -CASE_SENSE_NAMES = YES - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems -# doesn't support long names like on DOS, Mac, or CD-ROM. - -SHORT_NAMES = NO - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like the Qt-style comments (thus requiring an -# explict @brief command for a brief description. - -JAVADOC_AUTOBRIEF = NO - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# reimplements. - -INHERIT_DOCS = YES - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 4 - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consist of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources -# only. Doxygen will then generate output that is more tailored for C. -# For instance some of the names that are used will be different. The list -# of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = NO - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = YES - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = YES - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. - -WARN_FORMAT = - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = . - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp -# *.h++ *.idl - -FILE_PATTERNS = *.cpp *.h - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = YES - -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. - -EXCLUDE = - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. - -EXCLUDE_PATTERNS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. - -INPUT_FILTER = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse. - -FILTER_SOURCE_FILES = NO - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. - -SOURCE_BROWSER = YES - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = NO - -# If the REFERENCED_BY_RELATION tag is set to YES (the default) -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = YES - -# If the REFERENCES_RELATION tag is set to YES (the default) -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = YES - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = YES - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 3 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet - -HTML_STYLESHEET = - -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the Html help documentation and to the tree view. - -TOC_EXPAND = NO - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. - -DISABLE_INDEX = NO - -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 4 - -# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be -# generated containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript and frames is required (for instance Mozilla, Netscape 4.0+, -# or Internet explorer 4.0+). Note that for large projects the tree generation -# can take a very long time. In such cases it is better to disable this feature. -# Windows users are probably better off using the HTML help feature. - -GENERATE_TREEVIEW = NO - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = NO - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = a4wide - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = NO - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = NO - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimised for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assigments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_XML = NO - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = YES - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_PREDEFINED tags. - -EXPAND_ONLY_PREDEF = NO - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. - -PREDEFINED = - -# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line and do not end with a semicolon. Such function macros are typically -# used for boiler-plate code, and will confuse the parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::addtions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES tag can be used to specify one or more tagfiles. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in Html, RTF and LaTeX) for classes with base or -# super classes. Setting the tag to NO turns the diagrams off. Note that this -# option is superceded by the HAVE_DOT option below. This is only a fallback. It is -# recommended to install and use dot, since it yield more powerful graphs. - -CLASS_DIAGRAMS = NO - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = @HAVE_DOT@ - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = YES - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = YES - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found on the path. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = - -# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width -# (in pixels) of the graphs generated by dot. If a graph becomes larger than -# this value, doxygen will try to truncate the graph, so that it fits within -# the specified constraint. Beware that most browsers cannot cope with very -# large images. - -MAX_DOT_GRAPH_WIDTH = 1024 - -# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height -# (in pixels) of the graphs generated by dot. If a graph becomes larger than -# this value, doxygen will try to truncate the graph, so that it fits within -# the specified constraint. Beware that most browsers cannot cope with very -# large images. - -MAX_DOT_GRAPH_HEIGHT = 1024 - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermedate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES - -#--------------------------------------------------------------------------- -# Configuration::addtions related to the search engine -#--------------------------------------------------------------------------- - -# The SEARCHENGINE tag specifies whether or not a search engine should be -# used. If set to NO the values of all tags below this one will be ignored. - -SEARCHENGINE = NO - -# The CGI_NAME tag should be the name of the CGI script that -# starts the search engine (doxysearch) with the correct parameters. -# A script with this name will be generated by doxygen. - -CGI_NAME = - -# The CGI_URL tag should be the absolute URL to the directory where the -# cgi binaries are located. See the documentation of your http daemon for -# details. - -CGI_URL = - -# The DOC_URL tag should be the absolute URL to the directory where the -# documentation is located. If left blank the absolute path to the -# documentation, with file:// prepended to it, will be used. - -DOC_URL = - -# The DOC_ABSPATH tag should be the absolute path to the directory where the -# documentation is located. If left blank the directory on the local machine -# will be used. - -DOC_ABSPATH = - -# The BIN_ABSPATH tag must point to the directory where the doxysearch binary -# is installed. - -BIN_ABSPATH = - -# The EXT_DOC_PATHS tag can be used to specify one or more paths to -# documentation generated for other projects. This allows doxysearch to search -# the documentation for these projects as well. - -EXT_DOC_PATHS = diff --git a/doc/faq.html b/doc/faq.html deleted file mode 100644 index b9696391..00000000 --- a/doc/faq.html +++ /dev/null @@ -1,266 +0,0 @@ - - - - - - - - Synergy Frequently Asked Questions - - -

    -

    Synergy Frequently Asked Questions

    -

    -

    Questions

    -
      -
    1. Why doesn't ctrl+alt+del work on secondary screens? -
    2. Can the server and client be using different operating systems? -
    3. What's the difference between synergy and x2x, x2vnc, etc? -
    4. What does "Cannot initialize hook library" mean? -
    5. What security/encryption does synergy provide? -
    6. What should I call my screens in the configuration? -
    7. Why do my Caps-Lock, Num-Lock, Scroll-Lock keys act funny? -
    8. Can synergy share the display in addition to the mouse and keyboard? -
    9. Can synergy do drag and drop between computers? -
    10. Do AltGr or Mode-Switch or ISO_Level3_Shift work? -
    11. Why isn't synergy ported to platform XYZ? -
    12. My client can't connect. What's wrong? -
    13. Linking fails on Solaris. What's wrong? -
    14. The screen saver never starts. Why not? -
    15. I can't switch screens anymore for no apparent reason. Why? -
    16. I get the error 'Xlib: No protocol specified'. Why? -
    17. The cursor goes to secondary screen but won't come back. Why? -
    18. The cursor wraps from one edge of the screen to the opposite. Why? -
    19. How do I stop my game from minimizing when I leave the screen? -
    -

    Answers

    -
      -
    1. Why doesn't ctrl+alt+del work on secondary screens? -

      - Synergy isn't able to capture ctrl+alt+del on PC compatible - primary screens because it's handled completely differently than - other keystrokes. However, when the mouse is on a client - screen, pressing ctrl+alt+pause will simulate ctrl+alt+del - on the client. (A client running on Windows NT, 2000, or XP - must be configured to autostart when the computer starts for - this to work.) -

      - On a primary screen running on an OS X system, you can use - ctrl+command+del. Using the pause key isn't necessary since OS X - doesn't treat ctrl+command+del differently. And using the pause - key isn't usually possible because there isn't one on most OS X - systems. Use command instead of option/alt because - the command key, not the option/alt key, maps to alt on windows. - The reason is because the command key is in the same physical - location and performs the same general function (menu shortcuts) - as alt on a windows system. This mapping can be modified in - the configuration. -

      - On mac laptops, the key labeled "delete" is actually backspace - and ctrl+command+delete won't work. However fn+delete really - is delete so fn+ctrl+command+delete will act as ctrl+alt+del - on a windows secondary screen. -

      -
    2. Can the server and client be using different operating systems? -

      - Yes. The synergy network protocol is platform neutral so - synergy doesn't care what operating systems are running on - the server and clients. -

      -
    3. What's the difference between synergy and -x2x, x2vnc, etc? -

      - Unlike x2x, synergy supports any number of computers and - it doesn't require X on Microsoft Windows platforms. It - also has more advanced clipboard support and synchronizes - screensavers. x2vnc is also limited to two computers, - requires the separate vnc package, and is really only - appropriate for using an X system to control a non-X system. - However, the right tool for the job is whatever tool works - best for you. -

      -
    4. What does "Cannot initialize hook library" mean? -

      - This error can occur on a synergy server running on a - Microsoft Windows operating system. It means that synergy - is already running or possibly was not shut down properly. - If it's running then first end the synergy task. If it's - not then try logging off and back on or rebooting then - starting synergy again. -

      -
    5. What security/encryption does synergy provide? -

      - Synergy provides no built-in encryption or authentication. - Given that, synergy should not be used on or over any untrusted - network, especially the Internet. It's generally fine for home - networks. Future versions may provide built-in encryption and - authentication. -

      - Strong encryption and authentication is available through SSH - (secure shell). Run the SSH daemon (i.e. server) on the same - computer that you run the synergy server. It requires no - special configuration to support synergy. On each synergy - client system, run SSH with port forwarding: -

      -

      -        ssh -f -N -L 24800:server-hostname:24800 server-hostname
      -
      -

      - where server-hostname is the name of the - SSH/synergy server. - Once ssh authenticates itself, start the synergy client - normally except use localhost or - 127.0.0.1 as the server's - address. SSH will then encrypt all communication on behalf of - synergy. Authentication is handled by the SSH authentication. -

      - A free implementation of SSH for Linux and many Unix systems is - OpenSSH. For - Windows there's a port of OpenSSH using - Cygwin. -

      -
    6. What should I call my screens in the configuration? -

      - You can use any unique name in the configuration file for each - screen but it's easiest to use the hostname of the computer. - That's the computer name not including the domain. For example, - a computer with the fully qualified domain name xyz.foo.com has - the hostname xyz. There should also be an alias for xyz to - xyz.foo.com. If you don't use the computer's hostname, you - have to tell synergy the name of the screen using a command line - option, or the startup dialog on Windows. -

      - Some systems are configured to report the fully qualified domain - name as the hostname. For those systems it will be easier to use - the FQDN as the screen name. Also note that a Mac OS X system - named xyz may report its hostname as - xyz.local. If that's the case for you - then use xyz.local as the screen name. -

      -
    7. Why do my Caps-Lock, Num-Lock, Scroll-Lock keys act funny? -

      - Some systems treat the Caps-Lock, Num-Lock, and Scroll-Lock keys - differently than all the others. Whereas most keys report going down - when physically pressed and going up when physically released, on - these systems the Caps-Lock and Num-Lock keys report going down - when being activated and going up when being deactivated. That - is, when you press and release, say, Caps-Lock to activate it, it - only reports going down, and when you press and release to - deactivate it, it only reports going up. This confuses synergy. -

      - You can solve the problem by changing your configuration file. - In the screens section, following each screen that has the - problem, any or all of these lines as appropriate: -

      -

      -        halfDuplexCapsLock = true
      -        halfDuplexNumLock = true
      -        halfDuplexScrollLock = true
      -
      -

      - Then restart synergy on the server or reload the configuration. -

      -
    8. Can synergy share the display in addition to the mouse and keyboard? -

      - No. Synergy is a KM solution not a KVM (keyboard, video, mouse) - solution. However, future versions will probably support KVM. - Hopefully, this will make synergy suitable for managing large - numbers of headless servers. -

      -
    9. Can synergy do drag and drop between computers? -

      - No. That's a very cool idea and it'll be explored. However, it's - also clearly difficult and may take a long time to implement. -

      -
    10. Does AltGr/Mode-Switch/ISO_Level3_Shift work? -

      - Yes, as of 1.0.12 synergy has full support for AltGr/Mode-switch. - That includes support for most (all?) European keyboard layouts. - All systems should be using the same keyboard layout, though, for - all characters to work. (Any character missing from a client's - layout cannot be generated by synergy.) There is experimental - support for ISO_Level3_Shift in 1.1.3. -

      -
    11. Why isn't synergy ported to platform XYZ? -

      - Probably because the developers don't have access to platform XYZ - and/or are unfamiliar with development on XYZ. Also, synergy has - inherently non-portable aspects so there's a not insignificant - effort involved in porting. -

      -
    12. My client can't connect. What's wrong? -

      - A common mistake when starting the client is to give the wrong - server host name. The last synergyc command line option (Unix) - or the "Server Host Name" edit field (Windows) should be the - host name (or IP address) of the server not the client's host - name. If you get the error connection failed: cannot connect - socket followed by the attempt to connect was forcefully - rejected or connection refused then the server isn't started, - can't bind the address, or the client is connecting to the wrong - host name/address or port. See the - troublshooting page for more help. -

      -
    13. Linking fails on Solaris. What's wrong? -

      - Did you add -

      -

      -        --x-includes=/usr/openwin/include --x-libraries=/usr/openwin/lib
      -
      -

      - to the configure command line? Solaris puts - the X11 includes and libraries in an unusual place and the above lets - synergy find them. -

      -
    14. The screen saver never starts. Why not? -

      - If the synergy server is on X Windows then the screen saver will - not start while the mouse is on a client screen. This is a - consequence of how X Windows, synergy and xscreensaver work. -

      -
    15. I can't switch screens anymore for no apparent reason. Why? -

      - This should not happen with 1.1.3 and up. Earlier versions of - synergy would not allow switching screens when a key was down and - sometimes it would believe a key was down when it was not. -

      -
    16. I get the error 'Xlib: No protocol specified'. Why? -

      - You're running synergy without authorization to connect to the - X display. Typically the reason is running synergy as root when - logged in as non-root. Just run synergy as the same user that's - logged in. -

      -
    17. The cursor goes to secondary screen but won't come back. Why? -

      - Your configuration is incorrect. You must indicate the neighbors - of every screen. Just because you've configured 'Apple' to be to - the left of 'Orange' does not mean that 'Orange' is to the right - of 'Apple'. You must provide both in the configuration. -

      -
    18. The cursor wraps from one edge of the screen to the opposite. Why? -

      - Because you told it to. If you list 'Orange' to be to the left of - 'Orange' then moving the mouse off the left edge of 'Orange' will - make it jump to the right edge. Remove the offending line from the - configuration if you don't want that behavior. -

      -
    19. How do I stop my game from minimizing when I leave the screen? -

      - Many full screen applications, particularly games, automatically - minimize when they're no longer the active (foreground) application - on Microsoft Windows. The synergy server normally becomes the foreground - when you switch to another screen in order to more reliably capture all - user input causing those full screen applications to minimize. To - prevent synergy from stealing the foreground just click "Options..." - and check "Don't take foreground window on Windows servers." If you - turn this on then be aware that synergy may not function correctly when - certain programs, particularly the command prompt, are the foreground - when you switch to other screens. Simply make a different program the - foreground before switching to work around that. -

      -
    - - - diff --git a/doc/history.html b/doc/history.html deleted file mode 100644 index 48f921c3..00000000 --- a/doc/history.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - Synergy History - - -

    -

    Synergy History

    -

    -The first incarnation of synergy was CosmoSynergy, created by -Richard Lee and Adam Feder then at Cosmo Software, Inc., a -subsidiary of SGI (nee Silicon Graphics, Inc.), at the end of -1996. They wrote it, and Chris Schoeneman contributed, to -solve a problem: most of the engineers in Cosmo Software had -both an Irix and a Windows box on their desks and switchboxes -were expensive and annoying. CosmoSynergy was a great success -but Cosmo Software declined to productize it and the company -was later closed. -

    -Synergy is a from-scratch reimplementation of CosmoSynergy. -It provides most of the features of the original and adds a -few improvements. -

    - - - diff --git a/doc/home.html b/doc/home.html deleted file mode 100644 index df0775db..00000000 --- a/doc/home.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - Synergy - - -

    -

    Introduction

    -synergy: [noun] a mutually advantageous conjunction of distinct elements -

    -Synergy lets you easily share a single mouse and keyboard between -multiple computers with different operating systems, each with its -own display, without special hardware. It's intended for users -with multiple computers on their desk since each system uses its -own monitor(s). -

    -Redirecting the mouse and keyboard is as simple as moving the mouse -off the edge of your screen. Synergy also merges the clipboards of -all the systems into one, allowing cut-and-paste between systems. -Furthermore, it synchronizes screen savers so they all start and stop -together and, if screen locking is enabled, only one screen requires -a password to unlock them all. Learn more -about how it works. -

    -Synergy is open source and released under the -GNU Public License (GPL). -

    -

    System Requirements

    -

    -

      -
    • Microsoft Windows 95, Windows 98, Windows Me (the Windows 95 family) -
    • Microsoft Windows NT, Windows 2000, Windows XP (the Windows NT family) -
    • Mac OS X 10.2 or higher -
    • Unix -
        -
      • X Windows version 11 revision 4 or up -
      • XTEST extension
        - (use "xdpyinfo | grep XTEST" to check for XTEST) -
      -
    -All systems must support TCP/IP networking. -

    -"Unix" includes Linux, Solaris, Irix and other variants. Synergy has -only been extensively tested on Linux and may not work completely or -at all on other versions of Unix. Patches are welcome (including -patches that package binaries) at the -patches page. -

    -The Mac OS X port is incomplete. It does not synchronize the screen saver, -only text clipboard data works (i.e. HTML and bitmap data do not work), -the cursor won't hide when not on the screen, and there may be problems -with mouse wheel acceleration. Other problems should be -filed as bugs. -

    - - - diff --git a/doc/images/logo.gif b/doc/images/logo.gif deleted file mode 100644 index d9750ba3..00000000 Binary files a/doc/images/logo.gif and /dev/null differ diff --git a/doc/images/warp.gif b/doc/images/warp.gif deleted file mode 100644 index fd10033d..00000000 Binary files a/doc/images/warp.gif and /dev/null differ diff --git a/doc/index.html b/doc/index.html deleted file mode 100644 index 9e9ef302..00000000 --- a/doc/index.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - Synergy - - - - diff --git a/doc/license.html b/doc/license.html deleted file mode 100644 index 5e748123..00000000 --- a/doc/license.html +++ /dev/null @@ -1,313 +0,0 @@ - - - - - - - - Synergy License and Copyright - - -

    -

    Synergy License and Copyright

    -

    -Synergy is copyright (C) 2002 Chris Schoeneman.
    -Synergy is distributed under the GNU GENERAL PUBLIC LICENSE. -

    -

    GNU GENERAL PUBLIC LICENSE

    -Version 2, June 1991 -

    -Copyright (C) 1989, 1991 Free Software Foundation, Inc.
    -59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    -Everyone is permitted to copy and distribute verbatim copies -of this license document, but changing it is not allowed. -

    -

    Preamble

    -

    - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. -

    - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. -

    - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. -

    - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. -

    - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. -

    - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. -

    - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. -

    - The precise terms and conditions for copying, distribution and -modification follow. -

    -

    GNU GENERAL PUBLIC LICENSE
    -TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

    -

    - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". -

    -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. -

    - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. -

    -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. -

    - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: -

    - -
         -

    - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. -

    - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. -

    - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) -

    -

    -

    -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. -

    -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. -

    -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. -

    - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: -

    - -
         -

    - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, -

    - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, -

    - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) -

    -

    -

    -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. -

    -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. -

    - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. -

    - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. -

    - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. -

    - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. -

    -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. -

    -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. -

    -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. -

    - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. -

    - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. -

    -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. -

    - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. -

    -NO WARRANTY -

    - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE -IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE -COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM -"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR -IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE -ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. -

    - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED -TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY -WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED -ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, -SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF -THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT -LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR -LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE -PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH -HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. -

    -END OF TERMS AND CONDITIONS -

    - - - diff --git a/doc/news.html b/doc/news.html deleted file mode 100644 index b3729ec6..00000000 --- a/doc/news.html +++ /dev/null @@ -1,599 +0,0 @@ - - - - - - - - Synergy News - - -

    -Apr-02-2006 - Synergy 1.3.1 released -

    -Made following changes: -

      -
    • Hot key screen switching now restores last cursor position -
    • Fixed loss of hot keys when reloading configuration -
    • Fixed autorepeating on win32 (no longer sending repeating key releases) -
    • Fixed autorepeating on X11 (non-repeating keys were repeating) -
    • Fixed AltGr issues on X11 -
    • Fixed modifier mapping bug on OS X client (caused wrong characters) -
    • Fixed one way for modifiers to get stuck active on all platforms -
    • Fixed bugs in win32 GUI -
    • Removed alloca() from unix code (should fix FreeBSD build) -
    • Added more debugging output for network problems -
    • Fixed failure to detect some errors on X11 -
    -

    -Mar-22-2006 - Synergy 1.3.0 released -

    -Made following additions: -

      -
    • Console window on win32 can now be closed (reopened from tray menu) -
    • Can now change logging level on the fly from win32 tray menu -
    • Added client keep alive (lost connections are now detected reliably) -
    • Added support for linking portions of screen edges -
    • Added version number to UI in win32 -
    • Added GUI for hot key configuration on win32 -
    • Hot keys can now perform actions on press and/or release -
    • Added key down, key up, mouse down, and mouse up hot key actions -
    • Key actions can be directed to particular screens -
    • Hot keys can each perform multiple actions -
    -

    -Made following fixes: -

      -
    • Fixed AltGr key mappings (again) -
    • Fixed assertion when pasting on X11 -
    • Fixed modifier keys in VMware on X11 -
    • OS X server now treats sends option/alt as AltGr or super depending on key -
    • Improved handling of AltGr on win32 -
    • Fixed not removing client when connection is lost -
    • Clients now detect loss of connection to server and reconnect -
    • Fixed mouse jumping on OS X multimonitor systems -
    • Closing console on win32 no longer quits synergy -
    • Fixed Num Lock breaking certain keys -
    • Fixed Scroll Lock not locking cursor to screen -
    • Fixed mapping of delete key on X11 -
    • Fixed loss of clipboard after a particular copy/paste sequence -
    • Fixed compatibility with windows 95/98/Me (ToUnicodeEx) -
    • Fixed bad argument to function on OS X -
    • Fixed error parsing comments in configuration -
    • Fixed autorepeat on win32 servers -
    • Fixed X11 keyboard focus bug when reentering screen -
    • Fixed (suppressed) hot key autorepeating -
    • Fixed mousebutton action when Caps/Num/Scroll Lock were on -
    • Added documentation on firewalls -
    • Fixed documentation formatting on IE6 -
    -

    -Hot keys support has one known major bug: key actions cannot be directed -to the server (primary) screen. The configuration file syntax has changed -from earlier versions; users will have to modify the configurations by -hand. -

    -Dec-18-2005 - Synergy 1.2.7 released -

    -Made following changes: -

      -
    • Added preliminary support for configurable hot keys (Lorenz Schori) -
    • Major rewrite of keyboard handling code -
    • Fixed non-US keyboard handling (AltGr and ISO_Level3_Shift) -
    • Now supporting all installed keyboard layouts simultaneously -
    • Fixed bug in handling remapped caps-lock on X11 -
    • Fixed control and alt keys getting stuck on on X11 -
    • Fixed desktop focus problems requiring extra clicks on win32 -
    • Fixed alt key event getting passed to server when on client on win32 -
    • Synergy would prevent alt+numpad character entry; this is fixed -
    • Fixed suppression of xscreensaver 2.21 on X11 -
    • Fixed middle mouse button dragging on OSX server (Brian Kendall) -
    • Fixed caps/num/scroll lock toggles getting out of sync -
    • Enhanced support for converting clipboard text to the Latin-1 encoding -
    • Added autostart documentation for KDE users -
    • Added more details about using Terminal for OSX users -
    • Fixed crash when using --help on certain platforms -
    -

    -The hot key support is known to have bugs. The configuration file -syntax for hot keys is likely to change and the documentation for it -is minimal. The graphical UI on windows does not provide any support -for editing hot keys. -

    -Nov-12-2005 - Synergy 1.2.6 released -

    -Made following changes: -

      -
    • Fixed permission problem saving autostart configuration in win32 launcher -
    • Disabled buggy fix for loss of clipboard change detection -
    • Restored pthread signal autoconf code -
    -

    -Oct-17-2005 - Synergy 1.2.5 released -

    -Made following changes: -

      -
    • Win32 launcher now saves configuration automatically -
    • Fixed failure to save autostart configuration on win32 -
    • Fixed output bottom-right configuration flag -
    • Now properly releasing keys when leaving a client screen -
    • Fixed stuck-Alt on win32 -
    • Fixed 64-bit problem with clipboard on X11 -
    • Fixed BadAtom bug on X11 -
    • Fixed loss of detection of clipboard changes on win32 -
    • Added support for the MightyMouse -
    • Added support for buttons 4 and 5 on OSX -
    • Now shutting down win32 services when uninstalling -
    -

    -Aug-07-2005 - Synergy 1.2.4 released -

    -Made following changes: -

      -
    • Fixed gcc 4.0 warnings -
    • Fixed autoconf/automake problems -
    • Fixed scroll-lock on X windows -
    • Added option to suppress foreground window grabbing on win32 -
    • Fixed --daemon option on win32 client -
    • Fixed --no-restart on client -
    • Updated OS X autostart documentation -
    -

    -Jul-27-2005 - Synergy 1.2.3 released -

    -Made following changes: -

      -
    • Added OS X screensaver synchronization support (Lorenz Schori) -
    • Added OS X sleep support (Lorenz Schori) -
    • Added OS X fast user switching support (Lorenz Schori) -
    • Fixed international keyboard support on OS X (Lorenz Schori) -
    • Now capturing global hotkeys (e.g. cmd+tab, etc) on OS X (Lorenz Schori) -
    • Added support for SO_REUSEADDR (Don Eisele) -
    • Added "dead" corners feature -
    • Fixed "resource temporarily unavailable" warning when quiting on OS X -
    • Win32 now defaults to WARNING log level to avoid console window -
    • Now disabling foreground window on win32 when leaving server (Brent Priddy) -
    -

    -Jan-26-2005 - Synergy 1.2.2 released -

    -Made following changes: -

      -
    • Fixed major OS X modifier key handling bug -
    • Fixed handling of ISO_Level3_Shift on X11 -
    -

    -Jan-04-2005 - Synergy 1.2.1 released -

    -Made following changes: -

      -
    • Fixed major OS X keyboard handling bug -
    • Fixed some minor documentation bugs -
    -

    -Dec-30-2004 - Synergy 1.2.0 released -

    -Made following changes: -

      -
    • Improved support for moving laptops between networks (Brent Priddy) -
    • Added ISO_Level3_Shift support on X windows -
    • Now doing PageUp/PageDown if no mouse wheel on X windows (Tom Chadwick) -
    • Fixed handling of number pad number keys on Windows 95/98/Me -
    • Fixed handling of non-existant 4th and 5th mouse buttons on Windows -
    • Added support for Unicode keyboard layouts on OS X -
    • Fixed memory leak on OS X -
    • Added OS X autostart documentation (Tor Slettnes) -
    -

    -Nov-12-2004 - Synergy 1.1.10 released -

    -Made following changes: -

      -
    • Fixed race in condition variable wrapper; caused synergy to hang randomly -
    • Fixed modifier key and caps-lock handling on OSX -
    • System info log message now filtered like all other messages -
    -

    -Nov-07-2004 - Synergy 1.1.9 released -

    -Made following changes: -

      -
    • Fixed compiler error on gcc 3.4 and later -
    • Worked around minor gcc -O3 compiler bug -
    • Now logging system info at startup -
    • Config file errors now logged as errors rather than debug warnings -
    • Added half-duplex scroll lock option -
    • Fixed tracking of half-duplex toggle key state -
    • Now accepting screen names ending in dot (.) for OS X convenience -
    • OS X key mapping now loaded from system resources rather than hard coded -
    • Fixed multimonitor OS X pimary screen bug; multimon OS X should now work -
    • Added experimental workaround for laggy mouse when running linux -> OS X -
    • Fixed bug in win32 installer packaging -
    • Fixed unrequested continuous mouse wheel scrolling on win32 -
    • Added win32 GUI to set server address to listen on -
    • Fixed resource leak on win32 -
    • Fixed screensaver detection on windows 2000 and XP -
    • Fixed flickering mouse on multimon windows NT/2000/XP -
    • Fixed quiting when powerdvd stops playing (may fix other situations, too) -
    • Added tray icon menu item to force clients to reconnect -
    • Fixed handling of number pad keys with num-lock off on win32 -
    • Fixed shift key not working when a console windows has focus on win32 server -
    • Improved configure of Xinerama and DPMS -
    • Improved portability (removed recursive mutexes and _*_SOURCE defines) -
    • Now handling DPMS headers without prototypes -
    • Fixed dead key and AltGr+shift handling on X11 -
    • Fixed use of freed memory on unix -
    • Fixed AltGr mapping to Ctrl and not Ctrl+Alt on X11 without Alt_R mapped -
    • Added -display option for X11 -
    • Added support for X11 compose key (Multi_key) -
    -

    -Aug-05-2004 - Synergy 1.1.8 released -

    -Made following changes: -

      -
    • Removed key event capture on X11 (was breaking terminal keyboard input) -
    • Worked around win32 command prompt stealing shift key events -
    • Fixed handling of pause key on win32 -
    • Fixed handling of backslash on win32 internation keyboard mapping -
    • Fixed handling of ctrl and alt keys on NT/2k/XP -
    • Fixed XCode project (removed cross-compile) -
    • Worked around select() bug in OS X -
    • Worked around bug in ifstream on OS X -
    • Fixed handling of modifier keys on OS X synergy server -
    • Fixed handling of space key on OS X synergy server -
    • Fixed handling of key autorepeat on OS X server -
    • Fixed mouse wheel drift on OS X client -
    • Reorganized documentation and converted to HTML -
    -

    -Jun-13-2004 - Synergy 1.1.7 released -

    -Made following changes: -

      -
    • Added OS X precompiled header file forgotten in last build -
    • Fixed bug in fix for 'unexpected async reply' on X11 -
    • Removed dependency on "browser" service on win32 -
    • Fixed assertion failure when connection fails immediately -
    • Fixed failure to connect on AIX -
    • Fixed error in conversion from multibyte to wide characters -
    • Maybe fixed win32 screen saver detection -
    -

    -May-26-2004 - Synergy 1.1.6 released -

    -Made following changes: -

      -
    • Added preliminary Mac OS X support (client and server) -
    • Fixed ctrl+alt+del emulation on win32 -
    • Fixed ctrl+alt+del on win32 server acting on both client and server -
    • Fixed handling of screen resolution changes on win32 -
    • Fixed 'unexpected async reply' on X11 -
    • Added dependency to win32 service to avoid startup race condition -
    • Fixed reference count bug -
    • Keyboard input focus now restored on X11 (fixes loss of input in some games) -
    -

    -The OS X port does not yet support: -

      -
    • HTML and bitmap clipboard data -
    • Screen saver synchronization -
    • Non-US English keyboards -
    -

    -May-05-2004 - Synergy 1.1.5 released -

    -Made following changes: -

      -
    • No longer switching screens when a mouse button is down -
    • Worked around win32 mouse hook bug, fixing switch on double tap -
    • Added support for HTML and bitmap (image/bmp) clipboard data -
    • Physical mouse no longer necessary on win32 secondary screens to see cursor -
    • Added experimental relative mouse moves on secondary screen option -
    • Fixed win32 lock up when closing server with clients still connected -
    • Fixed bug in handling duplicate connections -
    • Fixed pthread mutex initialization -
    • Made synergy dependent on NetBT on win32 (for service startup order) -
    • Automake fixes; now mostly works on darwin and MinGW -
    • Fixed builds on Solaris 9, FreeBSD, and OpenBSD -
    • Partial support for MSYS/MinGW builds (NOT COMPLETE) -
    • Partial merge of OS X port (NOT COMPLETE) -
    -

    -Mar-31-2004 - Synergy 1.1.4 released -

    -Made following changes: -

      -
    • Fixed lookup of hosts by name of win32 -
    • Reverted tray icon code to 1.0.15 version; seems to fix the bugs -
    • Fixed crash when caps, num, or scroll lock not in key map on X11 -
    • Fixed double tap and wait to switch features -
    -

    -Mar-28-2004 - Synergy 1.1.3 released -

    -Made following changes: -

      -
    • Major code refactoring; reduced use of threads, added event queue -
    • Removed unused HTTP support code -
    • No longer interfering with mouse when scroll lock is toggled on -
    • Fixed minor mispositioning of mouse on win32 -
    • Unix portability fixes -
    • Added support for power management -
    • Improved keyboard handling and bug fixes -
    • Fixed dead key handling -
    -

    -Note: the tray icon on windows is known to not work correctly when -running the synergy server on Windows 95/95/Me. -

    -Aug-24-2003 - Synergy 1.0.14 released -

    -Made following changes: -

      -
    • Fixed bugs in setting win32 process/thread priority -
    • Fixed resource leak in opening win32 system log -
    • Fixed win32 launcher not getting non-default advanced options -
    • Synergy log copied to clipboard now transferred to other screens -
    • Hack to work around lesstif clipboard removed (fixes pasting on X) -
    -

    -Jul-20-2003 - Synergy 1.0.12 released -

    -Made following changes: -

    -This release finally completes support for non-ASCII characters, -fully supporting most (all?) European keyboard layouts including -dead key composition. This release includes changes from several -experimental versions (1.0.9, 1.0.11, 1.1.0, 1.1.1, 1.1.2, and -1.1.3). -

    -Made following changes: -

      -
    • Added non-ASCII support to win32 and X11 -
    • Added dead key support to win32 and X11 -
    • Fixed AltGr handling -
    • Added ctrl+alt+del simulation using ctrl+alt+pause -
    • Fixed loss of key event when user releases ctrl+alt+del -
    • Fixed incorrect synthesis of pointer-keys event on X11 -
    • Fixed Xinerama support -
    • Made some clipboard fixes on win32 and X11 -
    • Add tray icon menu item to copy log to clipboard -
    • Fixed mouse warping on unconnected client -
    • Stopped unconnected client from filling up event logs -
    -

    -May-10-2003 - Synergy 1.0.8 released -

    -Made following changes: -

    -

      -
    • Fixed hook forwarding (fixing interaction with objectbar) -
    • Fixed "Windows" key handling and added support Win+E, Win+F, etc -
    • Added win 95/98/me support for Alt+Tab, Alt+Esc, Ctrl+Esc -
    • Fixed scroll lock locking to server screen -
    • Fixed screen flashing on X11 and Windows -
    • Fixed compile problem on 64 bit systems -
    • Fixed Xinerama support -
    • Now allowing screen names that include underscores -
    • Improved non-ASCII key handling on Windows -
    • Fixed lagginess -
    • Fixed failure to capture all mouse input on Windows -
    • Fixed auto-repeat bugs on X11 -
    • Added option to disable screen saver synchronization -
    • Added support for 4th and 5th mouse buttons on Windows -
    • Added support for "Internet" and "Multimedia" keys -
    • Fixed jumping from client to itself (mouse wrapping) -
    -

    -Apr-26-2003 - Added roadmap -

    -There's now a roadmap for Synergy -describing the plans for further development. -

    -Apr-26-2003 - Added Paypal donation page -

    -There's now a donate button for those -who'd like to make a monetary contribution to the further -development of Synergy. -

    -Apr-26-2003 - Development update -

    -Synergy 1.0.8 will include fixes for the following problems. -These are already fixed and some are in development version 1.0.7. -

    -

      -
    • Mouse events at edge of screen are stolen -
    • Windows key doesn't work on clients -
    • Alt+[Shift+]Tab, Alt+[Shift+]Esc, Ctrl+Esc don't work on Win 95/98/Me -
    • Scroll lock doesn't lock to Windows server screen -
    • Screen flashes every 5 seconds on some X11 systems -
    • Synergy doesn't work properly with Xinerama -
    • Screen names with underscores are not allowed -
    -

    -Synergy 1.0.8 will probably include fixes for these problems: -

    -

      -
    • AltGr/Mode_switch doesn't work -
    • Non-ASCII keys aren't supported -
    • Synergy performs badly on a busy Windows system -
    • Unexpected key repeats on X11 clients -
    -

    -Synergy 1.0.8 should be available in the first half of May. -

    -Mar-27-2003 - Synergy 1.0.6 released -

    -Made following changes: -

    -

      -
    • Added tray icon on win32 -
    • Fixed multi-monitor support on win32 -
    • Fixed win32 screen saver detection on NT/2k/XP -
    • Added per-screen options to remap modifier keys -
    • Added global options for restricting screen jumping -
    • Added global option for detecting unresponsive clients -
    • Added more logging for why screen jump won't happen -
    • Fixed problem sending the CLIPBOARD to motif/lesstif apps -
    • Win32 launcher now remembers non-config-file state -
    -

    -In addition, the version number scheme has been changed. Given a -version number X.Y.Z, release versions will always have Y and Z -even while development versions will have Y and Z odd. -

    -Mar-27-2003 - Synergy featured in Linux Journal. -

    -The April 2003 issue of Linux Journal includes an article on Synergy. -Written by Chris Schoeneman, it describes configuring synergy between -two linux systems. -

    -Mar-27-2003 - Contributions to Synergy. -

    -Many thanks to Girard Thibaut for providing a version of the win32 -launch dialog translated into French. I hope to integrate these -changes into future releases. -

    -Thanks also to "wrhodes" who provided source files for -building an InstallShield installer for Synergy. They'll be -integrated into an upcoming release. -

    -Feb-18-2003 - Synergy 1.0.3 released -

    -Made following changes: -

    -

      -
    • Added support for X11 keymaps with only uppercase letters -
    • Fixed memory leaks -
    • Added documentation on using synergy with SSH -
    • Fixed unnecessary left-handed mouse button swapping -
    • Fixed debug build error on win32 -
    • Reduced frequency of large cursor jumps when leaving win32 server -
    • Changed cursor motion on win32 multimon to relative moves only -
    -

    -Jan-25-2003 - Synergy 1.0.2 released -

    -Made following changes: -

    -

      -
    • Fixed out-of-bounds array lookup in the BSD and Windows network code -
    • Added ability to set screen options from Windows launch dialog -
    -

    -Jan-22-2003 - Synergy 1.0.1 released -

    -Made following changes: -

    -

      -
    • Fixed running as a service on Windows NT family -
    -

    -Jan-20-2003 - Synergy 1.0.0 released -

    -Made following changes: -

    -

      -
    • Refactored to centralize platform dependent code -
    • Added support for mouse wheel on Windows NT (SP3 and up) -
    • Portability improvements -
    • Added more documentation -
    • Fixes for working with xscreensaver -
    • Fixes for circular screen links -
    -

    -This release has been tested on Linux and Windows. It builds and -is believed to run on Solaris and FreeBSD. It is believed to -build and run on Irix and AIX. It builds but does not work on -MacOS X. -

    -Dec-25-2002 - Synergy 0.9.14 released -

    -Made following changes: -

    -

      -
    • Fixed solaris compile problems (untested) -
    • Fixed irix compile problems (untested) -
    • Fixed windows client not reconnecting when server dies bug -
    • Fixed loss of ctrl+alt from windows server to non-windows clients -
    • Fixed handling of password protected windows client screen saver -
    • Now handling any number of pointer buttons on X11 -
    • Toggle key states now restored when leaving clients -
    • Added support for per-screen config options -
    • Added config options for half-duplex toggle keys on X11 -
    • Enabled class diagrams in doxygen documentation -
    -

    -Nov-05-2002 - Synergy 0.9.13 released -

    -Made following changes: -

    -

      -
    • Fixed solaris compile problems (untested) -
    • Fixed MacOS X compile problems (semi-functional) -
    • Fixed gcc-3.2 compile problems -
    • Fixed some thread startup and shutdown bugs -
    • Server now quits if bind() fails with an error other than in use -
    • Fixed bug in moving mouse on Win98 without multiple monitors -
    • Fixed bug in handling TCP socket errors on read and write -
    • Fixed spurious screen saver activation on X11 -
    • Unix platforms can now read Win32 configuration files -
    • Minor error reporting fixes -
    -

    -Sep-14-2002 - Synergy 0.9.12 released -

    -Made following changes: -

    -

      -
    • Win32 was not reporting log messages properly when run from synergy.exe -
    • Network error messages weren't reporting useful information -
    • Synergy won't build on gcc 3.2; added workaround for known problem -
    • X11 wasn't handling some keys/key combinations correctly -
    • Added option to change logging level when testing from synergy.exe -
    -

    -Sep-04-2002 - Synergy 0.9.11 released -

    -Fixed following bugs: -

    -

      -
    • Worked around missing SendInput() on windows 95/NT 4 prior to SP3 -
    • Fixed keyboard mapping on X11 synergy client -
    -

    -Sep-02-2002 - Synergy 0.9.10 released -

    -Fixed following bugs: -

    -

      -
    • The Pause/Break and keypad Enter buttons were not working correctly on windows -
    • Configuration options were being lost on windows after a reboot -
    • Added support for AltGr/ModeSwitch keys -
    • Added support for auto-start on windows when not administrator -
    • Improved autoconf -
    • Added workaround for lack of sstream header on g++ 2.95. -
    -

    -Aug-18-2002 - Synergy 0.9.9 released -

    -Fixed three bugs: -

    -

      -
    • The PrintScrn button was not working correctly on windows -
    • The Win32 server could hang when a client disconnected -
    • Using the mouse wheel could hang the X server -
    -

    -Aug-11-2002 - Synergy 0.9.8 released -

    -Supports any number of clients under Linux or Windows 95 or NT4 -or later. Includes mouse and keyboard sharing, clipboard -synchronization and screen saver synchronization. Supports ASCII -keystrokes, 5 button mouse with wheel, and Unicode text clipboard -format. -

    - - - diff --git a/doc/roadmap.html b/doc/roadmap.html deleted file mode 100644 index 7f8681bc..00000000 --- a/doc/roadmap.html +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - Synergy Roadmap - - -

    -

    Synergy Roadmap

    -

    -This page describes the planned development of Synergy. There are -no dates or deadlines. Instead, you'll find the features to come -and the rough order they'll arrive. -

    -

    Short term

    -

    -Synergy should work seamlessly. When it works correctly, it works -transparently so you don't even think about it. When it breaks, -you're forced out of the illusion of a unified desktop. The first -priority is fixing those bugs that break the illusion. -

    -Some of these bugs are pretty minor and some people would rather -have new features first. But I'd rather fix the current -foundation before building on it. That's not to say features -won't get added until after bug fixes; sometimes it's just too -tempting to code up a feature. -

    -The highest priority feature is currently splitting synergy into -front-ends and a back-end. The back-end does the real work. The -front-ends are console, GUI, or background applications that -communicate with the back-end, either controlling it or receiving -notifications from it. -

    -On win32, there'd be a front-end for the tray icon and a dialog to -start, stop, and control the back-end. OS X and X11 would have -similar front-ends. Splitting out the front-end has the added -benefit on X11 of keeping the back-end totally independent of -choice of GUI toolkit (KDE, Gnome, etc.) -

    -One can also imagine a front-end that does nothing but put monitors -into power-saving mode when the cursor is not on them. If you have -one monitor auto-senses two inputs, this would automatically switch -the display when you move the cursor to one screen or another. -

    -

    Medium term

    -

    -Some features fit well into Synergy's current design and may simply -enhance it's current capabilities. -

    -

      -
    • Configurable hot key to pop up a screen switch menu -
    • Configure screen saver synchronization on or off -
    • Graphical interface configuration and control on all platforms -
    • Graphical status feedback on all platforms -
    • More supported clipboard formats (particularly rich text) -
    -

    -A popup menu would be new for Synergy, which currently doesn't have -to do any drawing. That opens up many possibilities. Ideally, -front-ends request hot keys from the back-end and then tell the back -end what to do when they're invoked. This keeps the back-end -independent of the user interface. -

    -

    Long term

    -

    -Two features stand out as long term goals: -

    -

      -
    • Support N computers on -M monitors -
    • Drag and drop across computers -
    -

    -The first feature means sharing a monitor or monitors the way the -keyboard and mouse are shared. With this, Synergy would be a full -KVM solution. Not only would it support a few computers sharing -one screen (still using the mouse to roll from one screen to -another), but it should also support dozens of computers to provide -a solution for server farm administrators. In this capacity, it -may need to support text (as opposed to bitmap graphics) screens. -

    -The second feature would enhance the unified desktop illusion. It -would make it possible to drag a file and possibly other objects -to another screen. The object would be copied (or moved). I expect -this to be a very tricky feature. -

    - - - diff --git a/doc/running.html b/doc/running.html deleted file mode 100644 index 4ad2d594..00000000 --- a/doc/running.html +++ /dev/null @@ -1,394 +0,0 @@ - - - - - - - - Synergy User Guide - - -

    -

    Running Synergy

    -

    -Synergy lets you use one keyboard and mouse across multiple computers. -To do so it requires that all the computers are connected to each other -via TCP/IP networking. Most systems come with this installed. -

    -

    Step 1 - Choose a server

    -

    -The first step is to pick which keyboard and mouse you want to share. -The computer with that keyboard and mouse is called the "primary -screen" and it runs the synergy server. All of the other computers -are "secondary screens" and run the synergy client. -

    -

    Step 2 - Install the software

    -

    -Second, you install the software. Choose the appropriate package -and install it. For example, on Windows you would run -SynergyInstaller. You must install the -software on all the computers that will share the mouse and keyboard -(clients and server). On OS X you'll just have a folder with some -documentation and two programs. You can put this folder anywhere. -

    -

    Step 3 - Configure and start the server

    -

    -Next you configure the server. You'll tell synergy the name of -the primary and secondary screens, which screens are next to which, -and choose desired options. On Windows there's a dialog box for -setting the configuration. On other systems you'll create a simple -text file. -

    - -Note that when you tell synergy that screen A -is to the left of screen B this does not -imply that B is to the right of -A. You must explicitly indicate both -relations. If you don't do both then when you're running synergy you'll -find you're unable to leave one of the screens. -

    -Windows
    -On Windows run synergy by double clicking on the -synergy file. This brings up a dialog. -Configure the server: -

      -
    • Click the Share this computer's keyboard and mouse (server) radio button -
    • Click the Screens & Links Configure... button -
    • Click the + button to add the server to the - Screens list -
        -
      • Enter the name of server (the computer's name is the recommended name) -
      • Optionally enter other names the server is known by -
      • Click OK -
      -
    • Use the + button to add your other computers -
        -
      • Using a computer's name as its screen name is recommended -
      • Choose desired screen options on the Add Screen dialog -
      -
    • Use the controls under Links to link screens together -
        -
      • Click (once) on the server's name in the Screens list -
      • Choose the screen to the left of the server; use --- - if there is no screen to the left of the server -
      • Choose the screens to the right, above and below the server -
      • Repeat the above steps for all the other screens -
      -
    • Click OK to close the Screens & Links dialog -
    • Use Options... to set desired options -
    • If the server's screen name is not the server's computer name: -
        -
      • Click Advanced... -
      • Enter the server's screen name next to - Screen Name -
      • Click OK -
      -
    -

    -Now click Test. The server will start and -you'll see a console window with log messages telling you about synergy's -progress. If an error occurs you'll get one or more dialog boxes telling -you what the errors are; read the errors to determine the problem then -correct them and try Test again. See Step 5 -for typical errors. -

    -Unix or Mac OS X
    -Create a text file named synergy.conf with the -following: -

    -    section: screens
    -       screen1:
    -       screen2:
    -    end
    -    section: links
    -       screen1:
    -           right = screen2
    -       screen2:
    -           left = screen1
    -    end
    -
    -Replace each occurrence of screen1 with the host name -of the primary screen computer (as reported by the -hostname program) and screen2 -with the host name of a secondary screen computer. In the above example, -screen2 is to the right of -screen1 and screen1 is to the -left of screen2. If necessary you should replace -right and left with -left, right, -up, or down. If you -have more than two computers you can add those too: add each computer's host -name in the screens section and add the -appropriate links. See the configuration -guide for more configuration possibilities. -

    -Now start the server. Normally synergy wants to run "in the background." -It detaches from the terminal and doesn't have a visible window, effectively -disappearing from view. Until you're sure your configuration works, you -should start synergy "in the foreground" using the -f -command line option. -

    -On unix type the command below in a shell. If synergys is not in your -PATH then use the full pathname. -

    -    synergys -f --config synergy.conf
    -
    -On OS X open Terminal in the Utilities folder in the Applications folder. -Drag the synergys program from the synergy folder onto the Terminal window. -The path to the synergys program will appear. Add the following to the -same line, type a space at the end of the line but don't press enter: -
    -    -f --config 
    -
    -Now drag the synergy.conf file onto the Terminal window and press enter. -Check the reported messages for errors. Use ctrl+c to stop synergy if -it didn't stop automatically, correct any problems, and start it again. -

    -

    Step 4 - Start the clients

    -

    -Next you start the client on each computer that will share the server's -keyboard and mouse. -

    -Windows
    -On Windows run synergy by double clicking on the -synergy file. This brings up a dialog. -Configure the client: -

      -
    • Click the Use another computer's shared keyboard and mouse (client) radio button -
    • Enter the server's computer name next to Other Computer's Host Name -
        -
      • This is not the server's screen name, unless you made that the - server's host name as recommended -
      -
    • If the client's screen name is not the client's computer name: -
        -
      • Click Advanced... -
      • Enter the client's screen name next to Screen Name -
      • Click OK -
      -
    -

    -Now click Test. -

    -Unix or Mac OS X
    -To start a client on unix, enter the following: -

    -    synergyc -f server-host-name
    -
    -where server-host-name is replaced by the host -name of the computer running the synergy server. If synergyc is not in -your PATH then use the full pathname. -

    -On OS X open Terminal in the Utilities folder in the Applications folder. -Drag the synergyc program from the synergy folder onto the Terminal window. -The path to the synergys program will appear. Add the following to the -same line and press enter: -

    -    -f server-host-name
    -
    -

    -When you added the client to the server's configuration you chose a -name for the client. If that name was not client's host name then -you must tell the client the name you used. Instead of the above -command use this instead: -

    -    synergyc -f --name name server-host-name
    -
    -where name is the name for the client in -the server's configuration. (On OS X drag the synergyc program to the -Terminal window rather than typing synergyc.) -

    -

    Step 5 - Test

    -

    -Clients should immediately report a successful connection or one or -more error messages. Some typical problems and possible solutions are -below. See the troubleshooting and the -FAQ pages for more help. -

      -
    • failed to open screen (X11 only) -

      - Check permission to open the X display;
      - check that the DISPLAY environment variable is set
      - use the --display command line option. -

      -

    • address already in use -

      - Another program (maybe another copy of synergy) is using the synergy port; - stop the other program or choose a different port in the - Advanced... dialog. If you change the port - you must make the same change on all of the clients, too. -

      -

    • connection forcefully rejected -

      - The synergy client successfully contacted the server but synergy wasn't - running or it's running on a different port. You may also see this if - there's a firewall blocking the host or port. Make sure synergy is - running on the server and check for a firewall. -

      -

    • already connected -

      - Check that the synergy client isn't already running. -

      -

    • refused client -

      - Add the client to the server's configuration file. -

      -

    • connection timed out -

      - Check that server-host-name is correct.
      - Check that you don't have a firewall blocking the server or synergy port. -

      -

    • connection failed -

      - Check that server-host-name is correct. -

      -

    -If you get the error "Xlib: No protocol specified" -you're probably running synergy as root while logged in as another user. -X11 may prevent this for security reasons. Either run synergy as the same -user that's logged in or (not recommended) use -"xhost +" to allow anyone to connect -to the display. -

    -When successful you should be able to move the mouse off the appropriate -edges of your server's screen and have it appear on a client screen. -Try to move the mouse to each screen and check all the configured links. -Check the mouse buttons and wheel and try the keyboard on each client. -You can also cut-and-paste text, HTML, and images across computers (HTML -and images are not supported on OS X yet). -

    -

    Step 6 - Run

    -

    -Once everything works correctly, stop all the clients then the server. -Then start the server with the Start button -on Windows and without the -f option on Unix -and Mac OS X. Finally start the clients similarly. On Windows before -clicking Start you may want to set the -Logging Level to -Warning so the logging window doesn't pop -up (because you currently can't close it, just minimize it). -

    -You can also configure synergy to start automatically when your computer -starts or when you log in. See the autostart -guide for more information. -

    -

    Command Line Options Guide

    -

    -Common Command Line Options
    -The following options are supported by synergys -and synergyc. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     -d,--debug level  use debugging level level
     --daemonrun as a daemon (Unix) or background (Windows)
     -f,--no-daemonrun in the foreground
      --display display  connect to X server at display (X11 only)
     -n,--name nameuse name instead of the hostname
     --restartautomatically restart on failures
     -1,--no-restartdo not restart on failure
     -h,--helpprint help and exit
     --versionprint version information and exit
    -

    -Debug levels are from highest to lowest: FATAL, -ERROR, WARNING, -NOTE, INFO, -DEBUG, DEBUG1, and -DEBUG2. Only messages at or above the given -level are logged. Messages are logged to a terminal window when -running in the foreground. Unix logs messages to syslog when running -as a daemon. The Windows NT family logs messages to the event log -when running as a service. The Windows 95 family shows FATAL log -messages in a message box and others in a terminal window when running -as a service. -

    -The --name option lets the client or server -use a name other than its hostname for its screen. This name is used -when checking the configuration. -

    -Neither the client nor server will automatically restart if an error -occurs that is sure to happen every time. For example, the server -will exit immediately if it can't find itself in the configuration. -On X11 both the client and server will also terminate if the -connection to the X server is lost (usually because it died). -

    -Server Command Line Options
    -

    -

    -    synergys [options]
    -
    -The server accepts the common options and: -

    - - - - - - - - - - - -
     -a,--address address  listen for connections on address address
     -c,--config pathname  read configuration from pathname
    -

    -address has one of the following forms: -

    -    hostname
    -    :port
    -    hostname:port
    -
    -hostname is a hostname or IP address of a network -interface on the server system (e.g. somehost -or 192.168.1.100). port -is a port number from 1 to 65535. hostname defaults to -the system's hostname and port defaults to 24800. -

    -Client Command Line Options
    -

    -

    -    synergyc [options] address[:port]
    -
    -address is the hostname or IP address of -the server and port is the optional network -port on the server to connect to. The client accepts the -common options. -

    - - - diff --git a/doc/security.html b/doc/security.html deleted file mode 100644 index c8013c27..00000000 --- a/doc/security.html +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - Synergy Network Security Guide - - -

    -

    Authentication and Encryption

    -Synergy does not do any authentication or encryption. Any computer -can connect to the synergy server if it provides a screen name known -to the server, and all data is transferred between the server and the -clients unencrypted which means that anyone can, say, extract the -key presses used to type a password. Therefore, synergy should not -be used on untrusted networks. -

    -However, there are tools that can add authentication and encryption -to synergy without modifying either those tools or synergy. One -such tool is SSH (which stands for secure shell). A free implementation -of SSH is called OpenSSH and runs -on Linux, many Unixes, and Windows (in combination with -Cygwin). -

    -

    Configuring the Server

    -Install the OpenSSH server on the same computer as the synergy server. -Configure the OpenSSH server as usual (synergy doesn't demand any -special options in OpenSSH) and start it. Start the synergy server as -usual; the synergy server requires no special options to work with -OpenSSH. -

    -

    Configuring the Clients

    -Install the OpenSSH client on each synergy client computer. Then, on -each client, start the OpenSSH client using port forwarding: -

    -  ssh -f -N -L 24800:server-hostname:24800 server-hostname
    -
    -The server-hostname is the name or address -of the computer with the OpenSSH and synergy servers. -The 24800 is the default network port used by synergy; if you use -a different port then replace both instances of 24800 with the port -number that you use. Finally, start the synergy client normally -except use localhost as the server host -name. For example: -
    -  synergyc -f localhost
    -
    -Synergy will then run normally except all communication is passed -through OpenSSH which decrypts/encrypts it on behalf of synergy. -

    - - - diff --git a/doc/synergy.css b/doc/synergy.css deleted file mode 100644 index f020aa59..00000000 --- a/doc/synergy.css +++ /dev/null @@ -1,166 +0,0 @@ -body { - font-family: arial, helvetica, sans-serif; - font-size: small; - font-weight: normal; - margin-left: 0in; - margin-right: 0in; -} - -/* show underline on light blue links only on hover */ -a { - text-decoration: none; - color: #6699ff; -} -a:hover { - text-decoration: underline; -} - -/* heading */ -h3 { - display: block; - margin-top: 0em; - margin-bottom: 1.25em; - font-weight: bold; - font-variant: small-caps; - font-size: 125%; -} - -/* subheading */ -h4 { - display: block; - margin-top: 0em; - margin-bottom: 1em; - font-weight: bold; - font-variant: small-caps; - font-size: 100%; -} - -/* emphasis */ -b { - font-weight: bold; -} - -/* formatted code */ -pre { - display: block; - white-space: pre; - font-family: courier new; - font-size: 87.5%; -} - -.banner { - font-weight: normal; - font-variant: small-caps; - font-size: 400%; - width: 100%; - padding: 0px; - margin: 0px; - border: 0px; -} -.banner a { - color: #000000; -} -.banner a:hover { - text-decoration: none; - color: #000000; -} -.bannerb { - color: #ffffff; - background-color: #ffffff; - width: 100%; - height: 1px; - padding: 0px; - margin: 0px; - border-bottom: solid #6699ff 1px; -} - -.nav { - font-size: x-small; - font-weight: normal; - background-color: #d4d4d4; - - padding: 2px 0px 2px 0px; - margin: 0px; - border-bottom: solid #d4d4d4 300px; -} -.nav a:hover { - text-decoration: none; - color: #666666; -} -.nav td { - padding-right: 20px; - padding-left: 5px; - text-indent: 1em; -} -.nav .section { - width: 120px; - text-indent: 0em; - border-top: 0px; - border-left: 0px; - border-right: 0px; - border-bottom: solid #aaaaaa 1px; - padding-bottom: 0px; - font-weight: bold; - color: #777777; -} - -.main { - font-size: small; - font-weight: normal; - margin-left: 0.1in; - margin-right: 0.25in; -} - -.main table { - font-size: small; - font-weight: normal; - margin-left: 0.1in; - margin-right: 0.25in; -} - -.date { - font-weight: bold; -} - -.arg { - font-style: italic; - font-family: courier new; -} - -.userinput { - display: block; - white-space: pre; - font-family: courier new; - font-size: 87.5%; - font-weight: bold; -} - -.code { - font-family: courier new; -} - -.code table { - font-size: small; -} - -/* block of code */ -.codeblock { - display: block; - white-space: pre; - font-family: courier new; - font-size: 87.5%; - border: 1px solid #000000; - padding: 1em; - padding-top: 0em; - margin: 1em; - background-color: #cccccc; - color: #000000; -} - -.fakelink { - color: #6699ff; -} - -.hide { - display:none -} diff --git a/doc/tips.html b/doc/tips.html deleted file mode 100644 index 9f8e9e24..00000000 --- a/doc/tips.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - Synergy Tips and Tricks - - -

    -

    Tips and Tricks

    -

      -
    • - Be aware that not all keystrokes can be handled by synergy. In - particular, ctrl+alt+del is not handled. However, synergy can - convert ctrl+alt+pause into ctrl+alt+del on the client side. - (Synergy must be configured to autostart when the computer starts - on the client for this to work on the Windows NT family.) Some - non-standard keys may not work, especially "multimedia" buttons, - though several are correctly handled. -

      -

    • - A screen can be its own neighbor. That allows a screen to "wrap". - For example, if a configuration linked the left and right sides of - a screen to itself then moving off the left of the screen would put - the mouse at the right of the screen and vice versa. -

      -

    • - You cannot switch screens when the Scroll Lock is toggled on. Use - this to prevent unintentional switching. You can configure other - hot keys to do this instead; see - lockCursorToScreen. -

      -

    • - Turn off mouse driven virtual desktop switching on X windows. It - will interfere with synergy. Use keyboard shortcuts instead. -

      -

    • - Synergy's screen saver synchronization works best with xscreensaver - under X windows. Synergy works better with xscreensaver if it is - using one of the screen saver extensions. Prior to xscreensaver 4.0 - you can use -mit-extension, - -sgi-extension, or - -xidle-extension - command line options to enable an extension (assuming your server has - the extension). Starting with 4.0 you must enable the corresponding - option in your .xscreensaver file. -

      -

    • - Synergy automatically converts newlines in clipboard text (Unix - expects \n to end each line while Windows - expects \r\n). -

      -

    • - Clients can be started and stopped at any time. When a screen is - not connected, the mouse will jump over that screen as if the mouse - had moved all the way across it and jumped to the next screen. -

      -

    • - A client's keyboard and mouse are fully functional while synergy is - running. You can use them in case synergy locks up. -

      -

    • - Strong authentication and encryption is available by using SSH. See - the security guide for more information. - Synergy does not otherwise provide secure communications and it should - not be used on or over untrusted networks. -

      -

    • - Synergy doesn't work if a 16-bit Windows application has the focus - on Windows 95/98/Me. This is due to limitations of Windows. One - commonly used 16-bit application is the command prompt - (command.exe) - and this includes synergy's log window when running in test mode. -

      -

    -

    - - - diff --git a/doc/toc.html b/doc/toc.html deleted file mode 100644 index 3c43bd7c..00000000 --- a/doc/toc.html +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - Synergy TOC - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/doc/todo.html b/doc/todo.html deleted file mode 100644 index 02a12a07..00000000 --- a/doc/todo.html +++ /dev/null @@ -1,70 +0,0 @@ - - - - - Synergy To Do List - - -

    Synergy To Do List

    -

    -This page describes the planned development of Synergy. There are -no dates or deadlines. Instead, you'll find the features to come -and the rough order they can be expected to arrive. -

    - -

    Short term

    -

    -Synergy should work seamlessly. When it works correctly, it works -transparently so you don't even think about it. When it breaks, -you're forced out of the illusion of a unified desktop. The first -priority is fixing those bugs that break the illusion. -

    -

    -Some of these bugs are pretty minor and some people would rather -have new features first. But I'd rather fix the current -foundation before building on it. That's not to say features -won't get added until after bug fixes; sometimes it's just too -tempting to code up a feature. -

    - -

    Medium term

    -

    -Some features fit well into Synergy's current design and may simply -enhance it's current capabilities. -

      -
    • Configurable hot key screen switching -
    • Configurable hot key to lock to a screen -
    • Configurable hot key to pop up a screen switch menu -
    • Configure screen saver synchronization on or off -
    • Graphical interface configuration and control on all platforms -
    • Graphical status feedback on all platforms -
    • More supported clipboard formats (particularly rich text) -
    -

    - -

    Long term

    -

    -Two features stand out as long term goals: -

      -
    • Support N computers on -M monitors -
    • Drag and drop across computers -
    -

    -

    -The first feature means sharing a monitor or monitors the way the -keyboard and mouse are shared. With this, Synergy would be a full -KVM solution. Not only would it support a few computers sharing -one screen (still using the mouse to roll from one screen to -another), but it should also support dozens of computers to provide -a solution for server farm administrators. In this capacity, it -may need to support text (as opposed to bitmap graphics) screens. -

    -

    -The second feature would enhance the unified desktop illusion. It -would make it possible to drag a file and possibly other objects -to another screen. The object would be copied (or moved). I expect -this to be a very tricky feature. -

    - - diff --git a/doc/trouble.html b/doc/trouble.html deleted file mode 100644 index f2923a5b..00000000 --- a/doc/trouble.html +++ /dev/null @@ -1,204 +0,0 @@ - - - - - - - - Synergy Troubleshooting - - -

    -

    Synergy Troubleshooting

    -

    Problems

    -
      -
    1. Cannot read configuration -
    2. Connection forcefully rejected -
    3. Connection timed out -
    4. Cannot listen for clients -
    5. Unknown screen name "XXX" -
    6. Server refused client with name "XXX" -
      A client with name "XXX" is not in the map -
    7. Server already has a connected client with name "XXX" -
      A client with name "XXX" is already connected -
    8. Server has incompatible version -
    9. The cursor goes to secondary screen but won't come back -
    -

    Solutions

    -
      -
    1. Cannot read configuration -

      -There's an error in the configuration file. This error is always -accompanied by another message describing the problem. Use that -message and the configuration documentation -to determine the fix. -

      -
    2. Connection forcefully rejected -

      -The client was able to contact the server computer but the server was -not listening for clients. Possible reasons are: -

      -
        -
      • The client is using the wrong server -

        -Make sure the client is using the hostname or IP address of the computer -running the synergy server. -

        -
      • Synergy isn't running on the server -

        -Make sure the synergy server is running on the server computer. Make -sure the server is ready to accept connections. If another program is -using synergy's port (24800 by default) then synergy can't start unless -you specify a different port. -

        -
      • The client is using the wrong port -

        -Synergy uses port 24800 by default but you can specify a different port. -If you do use a different port you must use that port on the server and -all clients. -

        -
      -
    3. Connection timed out -

      -The most likely reasons for this are: -

      -
        -
      • A firewall -

        -A firewall is a program or device that deliberately blocks network -connections for security reasons. Typically, they'll silently drop -packets they don't want rather than sending a rejection to the sender. -This makes it more difficult for intruders to break in. -

        -When synergy traffic hits a firewall and gets dropped, eventually the -synergy client will give up waiting for a response and time out. To -allow synergy traffic through first find all the firewalls on the -network between and on the synergy client and server computers. -

        -A firewall on the server or any network device between the server and -any client should allow packets to TCP port 24800. (Port 24800 is the -default; use whichever port you've selected.) You'll have to consult -the manual for your operating system, device, or firewall software to -find out how to do this. -

        -Usually you'll won't need to adjust a firewall on client machines. -That's because firewalls normally allow incoming traffic on any port -they've initiated a connection on. The reasoning is, of course, if -you started a conversation you probably want to hear the reply. -

        -
      • The network is down or busy -

        -Correct the network problem and try again. You might try -ping to see if the two computers can see -each other on the network. -

        -
      • The server is frozen -

        -If the synergy server is running but locked up or very busy then the -client may get this message. If the server is locked up then you'll -probably have to restart it. If it's just very busy then the client -should successfully connect automatically once the server settles down. -

        -
      -
    4. Cannot listen for clients -

      -Synergy tried to start listening for clients but the network port is -unavailable for some reason. Typical reasons are: -

      -
        -
      • No network devices -

        -You must have a TCP/IP network device installed and enabled to use -synergy. -

        -
      • A synergy server is already running -

        -Check that a synergy server isn't already running. -

        -
      • Another program is using synergy's port -

        -Only one program at a time can listen for connections on a given port. -If the specific error is that the address is already in use and you've -ruled out the other causes, then it's likely another program is already -using synergy's port. By default synergy uses port 24800. Try having -synergy use a different port number, like 24801 or 24900. Note that -the server and all clients must use the same port number. Alternatively, -find the other program and stop it or have it use another port. -

        -
      -
    5. Unknown screen name "XXX" -

      -This error can be reported when reading the configuration; see -cannot read configuration. If the configuration -was read successfully and you get this error then it means that the -server's screen is not in the configuration. All screens must be listed -in the configuration. -

      -A common reason for this is when you haven't used the system's hostname -as its screen name. By default, synergy uses the hostname as the screen -name. If you used a different screen name in the configuration then you -must tell synergy what that name is. Let's say the hostname is -frederick but the configuration defines a screen -named fred. Then you must tell the server -that its screen name is fred by using the ---name fred command line option or setting -the screen name in the advanced options dialog to -fred. -

      -Alternatively, you can specify one name as an alias of another. See -the configuration documentation -for details. -

      -Another common reason for this is a mismatch between what you think the -hostname is and what synergy thinks it is. Typically this is a problem -with fully qualified domain names (FQDN). Perhaps you think your system -is named fred but synergy thinks it's -fred.nowhere.com or -fred.local. You can use either solution above -to fix this. -

      -
    6. Server refused client with name "XXX" -
      A client with name "XXX" is not in the map -

      -The client is using a screen name not in the server's configuration. -This is essentially the same problem as Unknown -screen name "XXX" and has the same solutions: specify another -screen name or add an alias. -

      -
    7. Server already has a connected client with name "XXX" -
      A client with name "XXX" is already connected -

      -This happens when: -

      -
        -
      • Two clients try use the same screen name -

        -Each client must have a unique screen name. Configure at least one -client to use a different screen name. -

        -
      • One client reconnects without cleanly disconnecting -

        -It's possible for a client to disconnect without the server knowing, -usually by being disconnected from the network or possibly by going -to sleep or even crashing. The server is left thinking the client is -still connected so when the client reconnects the server will think -this is a different client using the same name. Synergy will usually -detect and correct this problem within a few seconds. If it doesn't -then restart the server. -

        -
      -
    8. Server has incompatible version -

      -You're using different versions of synergy on the client and server. -You should use the same version on all systems. -

      -
    9. The cursor goes to secondary screen but won't come back -

      -This is FAQ #17 and is also mentioned in -the documentation for using synergy -and configuration. -

      -
    - - - diff --git a/examples/synergy.conf b/examples/synergy.conf deleted file mode 100644 index 2586dfaf..00000000 --- a/examples/synergy.conf +++ /dev/null @@ -1,37 +0,0 @@ -# sample synergy configuration file -# -# comments begin with the # character and continue to the end of -# line. comments may appear anywhere the syntax permits. - -section: screens - # three hosts named: moe, larry, and curly - moe: - larry: - curly: -end - -section: links - # larry is to the right of moe and curly is above moe - moe: - right = larry - up = curly - - # moe is to the left of larry and curly is above larry. - # note that curly is above both moe and larry and moe - # and larry have a symmetric connection (they're in - # opposite directions of each other). - larry: - left = moe - up = curly - - # larry is below curly. if you move up from moe and then - # down, you'll end up on larry. - curly: - down = larry -end - -section: aliases - # curly is also known as shemp - curly: - shemp -end diff --git a/lib/Makefile.am b/lib/Makefile.am deleted file mode 100644 index 2a57133c..00000000 --- a/lib/Makefile.am +++ /dev/null @@ -1,34 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2002 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -## Process this file with automake to produce Makefile.in -NULL = - -SUBDIRS = \ - common \ - arch \ - base \ - mt \ - io \ - net \ - synergy \ - platform \ - client \ - server \ - $(NULL) - -EXTRA_DIST = \ - $(NULL) - -MAINTAINERCLEANFILES = \ - Makefile.in \ - $(NULL) diff --git a/lib/arch/CArch.cpp b/lib/arch/CArch.cpp deleted file mode 100644 index 80c613ab..00000000 --- a/lib/arch/CArch.cpp +++ /dev/null @@ -1,639 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "common.h" -#include "CArch.h" - -#undef ARCH_CONSOLE -#undef ARCH_DAEMON -#undef ARCH_FILE -#undef ARCH_LOG -#undef ARCH_MULTITHREAD -#undef ARCH_NETWORK -#undef ARCH_SLEEP -#undef ARCH_STRING -#undef ARCH_SYSTEM -#undef ARCH_TASKBAR -#undef ARCH_TIME - -// include appropriate architecture implementation -#if SYSAPI_WIN32 -# include "CArchConsoleWindows.h" -# include "CArchDaemonWindows.h" -# include "CArchFileWindows.h" -# include "CArchLogWindows.h" -# include "CArchMiscWindows.h" -# include "CArchMultithreadWindows.h" -# include "CArchNetworkWinsock.h" -# include "CArchSleepWindows.h" -# include "CArchStringWindows.h" -# include "CArchSystemWindows.h" -# include "CArchTaskBarWindows.h" -# include "CArchTimeWindows.h" -#elif SYSAPI_UNIX -# include "CArchConsoleUnix.h" -# include "CArchDaemonUnix.h" -# include "CArchFileUnix.h" -# include "CArchLogUnix.h" -# if HAVE_PTHREAD -# include "CArchMultithreadPosix.h" -# endif -# include "CArchNetworkBSD.h" -# include "CArchSleepUnix.h" -# include "CArchStringUnix.h" -# include "CArchSystemUnix.h" -# include "CArchTaskBarXWindows.h" -# include "CArchTimeUnix.h" -#endif - -#if !defined(ARCH_CONSOLE) -# error unsupported platform for console -#endif - -#if !defined(ARCH_DAEMON) -# error unsupported platform for daemon -#endif - -#if !defined(ARCH_FILE) -# error unsupported platform for file -#endif - -#if !defined(ARCH_LOG) -# error unsupported platform for logging -#endif - -#if !defined(ARCH_MULTITHREAD) -# error unsupported platform for multithreading -#endif - -#if !defined(ARCH_NETWORK) -# error unsupported platform for network -#endif - -#if !defined(ARCH_SLEEP) -# error unsupported platform for sleep -#endif - -#if !defined(ARCH_STRING) -# error unsupported platform for string -#endif - -#if !defined(ARCH_SYSTEM) -# error unsupported platform for system -#endif - -#if !defined(ARCH_TASKBAR) -# error unsupported platform for taskbar -#endif - -#if !defined(ARCH_TIME) -# error unsupported platform for time -#endif - -// -// CArch -// - -CArch* CArch::s_instance = NULL; - -CArch::CArch(ARCH_ARGS* args) -{ - // only once instance of CArch - assert(s_instance == NULL); - s_instance = this; - - // create architecture implementation objects - m_mt = new ARCH_MULTITHREAD; - m_system = new ARCH_SYSTEM; - m_file = new ARCH_FILE; - m_log = new ARCH_LOG; - m_net = new ARCH_NETWORK; - m_sleep = new ARCH_SLEEP; - m_string = new ARCH_STRING; - m_time = new ARCH_TIME; - m_console = new ARCH_CONSOLE(args); - m_daemon = new ARCH_DAEMON; - m_taskbar = new ARCH_TASKBAR(args); - -#if SYSAPI_WIN32 - CArchMiscWindows::init(); -#endif -} - -CArch::~CArch() -{ - // clean up - delete m_taskbar; - delete m_daemon; - delete m_console; - delete m_time; - delete m_string; - delete m_sleep; - delete m_net; - delete m_log; - delete m_file; - delete m_system; - delete m_mt; - - // no instance - s_instance = NULL; -} - -CArch* -CArch::getInstance() -{ - assert(s_instance != NULL); - - return s_instance; -} - -void -CArch::openConsole(const char* title) -{ - m_console->openConsole(title); -} - -void -CArch::closeConsole() -{ - m_console->closeConsole(); -} - -void -CArch::showConsole(bool showIfEmpty) -{ - m_console->showConsole(showIfEmpty); -} - -void -CArch::writeConsole(const char* str) -{ - m_console->writeConsole(str); -} - -const char* -CArch::getNewlineForConsole() -{ - return m_console->getNewlineForConsole(); -} - -void -CArch::installDaemon(const char* name, - const char* description, - const char* pathname, - const char* commandLine, - const char* dependencies, - bool allUsers) -{ - m_daemon->installDaemon(name, description, pathname, - commandLine, dependencies, allUsers); -} - -void -CArch::uninstallDaemon(const char* name, bool allUsers) -{ - m_daemon->uninstallDaemon(name, allUsers); -} - -int -CArch::daemonize(const char* name, DaemonFunc func) -{ - return m_daemon->daemonize(name, func); -} - -bool -CArch::canInstallDaemon(const char* name, bool allUsers) -{ - return m_daemon->canInstallDaemon(name, allUsers); -} - -bool -CArch::isDaemonInstalled(const char* name, bool allUsers) -{ - return m_daemon->isDaemonInstalled(name, allUsers); -} - -const char* -CArch::getBasename(const char* pathname) -{ - return m_file->getBasename(pathname); -} - -std::string -CArch::getUserDirectory() -{ - return m_file->getUserDirectory(); -} - -std::string -CArch::getSystemDirectory() -{ - return m_file->getSystemDirectory(); -} - -std::string -CArch::concatPath(const std::string& prefix, const std::string& suffix) -{ - return m_file->concatPath(prefix, suffix); -} - -void -CArch::openLog(const char* name) -{ - m_log->openLog(name); -} - -void -CArch::closeLog() -{ - m_log->closeLog(); -} - -void -CArch::showLog(bool showIfEmpty) -{ - m_log->showLog(showIfEmpty); -} - -void -CArch::writeLog(ELevel level, const char* msg) -{ - m_log->writeLog(level, msg); -} - -CArchCond -CArch::newCondVar() -{ - return m_mt->newCondVar(); -} - -void -CArch::closeCondVar(CArchCond cond) -{ - m_mt->closeCondVar(cond); -} - -void -CArch::signalCondVar(CArchCond cond) -{ - m_mt->signalCondVar(cond); -} - -void -CArch::broadcastCondVar(CArchCond cond) -{ - m_mt->broadcastCondVar(cond); -} - -bool -CArch::waitCondVar(CArchCond cond, CArchMutex mutex, double timeout) -{ - return m_mt->waitCondVar(cond, mutex, timeout); -} - -CArchMutex -CArch::newMutex() -{ - return m_mt->newMutex(); -} - -void -CArch::closeMutex(CArchMutex mutex) -{ - m_mt->closeMutex(mutex); -} - -void -CArch::lockMutex(CArchMutex mutex) -{ - m_mt->lockMutex(mutex); -} - -void -CArch::unlockMutex(CArchMutex mutex) -{ - m_mt->unlockMutex(mutex); -} - -CArchThread -CArch::newThread(ThreadFunc func, void* data) -{ - return m_mt->newThread(func, data); -} - -CArchThread -CArch::newCurrentThread() -{ - return m_mt->newCurrentThread(); -} - -CArchThread -CArch::copyThread(CArchThread thread) -{ - return m_mt->copyThread(thread); -} - -void -CArch::closeThread(CArchThread thread) -{ - m_mt->closeThread(thread); -} - -void -CArch::cancelThread(CArchThread thread) -{ - m_mt->cancelThread(thread); -} - -void -CArch::setPriorityOfThread(CArchThread thread, int n) -{ - m_mt->setPriorityOfThread(thread, n); -} - -void -CArch::testCancelThread() -{ - m_mt->testCancelThread(); -} - -bool -CArch::wait(CArchThread thread, double timeout) -{ - return m_mt->wait(thread, timeout); -} - -bool -CArch::isSameThread(CArchThread thread1, CArchThread thread2) -{ - return m_mt->isSameThread(thread1, thread2); -} - -bool -CArch::isExitedThread(CArchThread thread) -{ - return m_mt->isExitedThread(thread); -} - -void* -CArch::getResultOfThread(CArchThread thread) -{ - return m_mt->getResultOfThread(thread); -} - -IArchMultithread::ThreadID -CArch::getIDOfThread(CArchThread thread) -{ - return m_mt->getIDOfThread(thread); -} - -void -CArch::setSignalHandler(ESignal signal, SignalFunc func, void* userData) -{ - m_mt->setSignalHandler(signal, func, userData); -} - -void -CArch::raiseSignal(ESignal signal) -{ - m_mt->raiseSignal(signal); -} - -CArchSocket -CArch::newSocket(EAddressFamily family, ESocketType type) -{ - return m_net->newSocket(family, type); -} - -CArchSocket -CArch::copySocket(CArchSocket s) -{ - return m_net->copySocket(s); -} - -void -CArch::closeSocket(CArchSocket s) -{ - m_net->closeSocket(s); -} - -void -CArch::closeSocketForRead(CArchSocket s) -{ - m_net->closeSocketForRead(s); -} - -void -CArch::closeSocketForWrite(CArchSocket s) -{ - m_net->closeSocketForWrite(s); -} - -void -CArch::bindSocket(CArchSocket s, CArchNetAddress addr) -{ - m_net->bindSocket(s, addr); -} - -void -CArch::listenOnSocket(CArchSocket s) -{ - m_net->listenOnSocket(s); -} - -CArchSocket -CArch::acceptSocket(CArchSocket s, CArchNetAddress* addr) -{ - return m_net->acceptSocket(s, addr); -} - -bool -CArch::connectSocket(CArchSocket s, CArchNetAddress name) -{ - return m_net->connectSocket(s, name); -} - -int -CArch::pollSocket(CPollEntry pe[], int num, double timeout) -{ - return m_net->pollSocket(pe, num, timeout); -} - -void -CArch::unblockPollSocket(CArchThread thread) -{ - m_net->unblockPollSocket(thread); -} - -size_t -CArch::readSocket(CArchSocket s, void* buf, size_t len) -{ - return m_net->readSocket(s, buf, len); -} - -size_t -CArch::writeSocket(CArchSocket s, const void* buf, size_t len) -{ - return m_net->writeSocket(s, buf, len); -} - -void -CArch::throwErrorOnSocket(CArchSocket s) -{ - m_net->throwErrorOnSocket(s); -} - -bool -CArch::setNoDelayOnSocket(CArchSocket s, bool noDelay) -{ - return m_net->setNoDelayOnSocket(s, noDelay); -} - -bool -CArch::setReuseAddrOnSocket(CArchSocket s, bool reuse) -{ - return m_net->setReuseAddrOnSocket(s, reuse); -} - -std::string -CArch::getHostName() -{ - return m_net->getHostName(); -} - -CArchNetAddress -CArch::newAnyAddr(EAddressFamily family) -{ - return m_net->newAnyAddr(family); -} - -CArchNetAddress -CArch::copyAddr(CArchNetAddress addr) -{ - return m_net->copyAddr(addr); -} - -CArchNetAddress -CArch::nameToAddr(const std::string& name) -{ - return m_net->nameToAddr(name); -} - -void -CArch::closeAddr(CArchNetAddress addr) -{ - m_net->closeAddr(addr); -} - -std::string -CArch::addrToName(CArchNetAddress addr) -{ - return m_net->addrToName(addr); -} - -std::string -CArch::addrToString(CArchNetAddress addr) -{ - return m_net->addrToString(addr); -} - -IArchNetwork::EAddressFamily -CArch::getAddrFamily(CArchNetAddress addr) -{ - return m_net->getAddrFamily(addr); -} - -void -CArch::setAddrPort(CArchNetAddress addr, int port) -{ - m_net->setAddrPort(addr, port); -} - -int -CArch::getAddrPort(CArchNetAddress addr) -{ - return m_net->getAddrPort(addr); -} - -bool -CArch::isAnyAddr(CArchNetAddress addr) -{ - return m_net->isAnyAddr(addr); -} - -bool -CArch::isEqualAddr(CArchNetAddress a, CArchNetAddress b) -{ - return m_net->isEqualAddr(a, b); -} - -void -CArch::sleep(double timeout) -{ - m_sleep->sleep(timeout); -} - -int -CArch::vsnprintf(char* str, int size, const char* fmt, va_list ap) -{ - return m_string->vsnprintf(str, size, fmt, ap); -} - -int -CArch::convStringMBToWC(wchar_t* dst, const char* src, UInt32 n, bool* errors) -{ - return m_string->convStringMBToWC(dst, src, n, errors); -} - -int -CArch::convStringWCToMB(char* dst, const wchar_t* src, UInt32 n, bool* errors) -{ - return m_string->convStringWCToMB(dst, src, n, errors); -} - -IArchString::EWideCharEncoding -CArch::getWideCharEncoding() -{ - return m_string->getWideCharEncoding(); -} - -std::string -CArch::getOSName() const -{ - return m_system->getOSName(); -} - -void -CArch::addReceiver(IArchTaskBarReceiver* receiver) -{ - m_taskbar->addReceiver(receiver); -} - -void -CArch::removeReceiver(IArchTaskBarReceiver* receiver) -{ - m_taskbar->removeReceiver(receiver); -} - -void -CArch::updateReceiver(IArchTaskBarReceiver* receiver) -{ - m_taskbar->updateReceiver(receiver); -} - -double -CArch::time() -{ - return m_time->time(); -} diff --git a/lib/arch/CArch.h b/lib/arch/CArch.h deleted file mode 100644 index 644f015c..00000000 --- a/lib/arch/CArch.h +++ /dev/null @@ -1,218 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CARCH_H -#define CARCH_H - -#include "IArchConsole.h" -#include "IArchDaemon.h" -#include "IArchFile.h" -#include "IArchLog.h" -#include "IArchMultithread.h" -#include "IArchNetwork.h" -#include "IArchSleep.h" -#include "IArchString.h" -#include "IArchSystem.h" -#include "IArchTaskBar.h" -#include "IArchTime.h" - -/*! -\def ARCH -This macro evaluates to the singleton CArch object. -*/ -#define ARCH (CArch::getInstance()) - -#define ARCH_ARGS void - -//! Delegating mplementation of architecture dependent interfaces -/*! -This class is a centralized interface to all architecture dependent -interface implementations (except miscellaneous functions). It -instantiates an implementation of each interface and delegates calls -to each method to those implementations. Clients should use the -\c ARCH macro to access this object. Clients must also instantiate -exactly one of these objects before attempting to call any method, -typically at the beginning of \c main(). -*/ -class CArch : public IArchConsole, - public IArchDaemon, - public IArchFile, - public IArchLog, - public IArchMultithread, - public IArchNetwork, - public IArchSleep, - public IArchString, - public IArchSystem, - public IArchTaskBar, - public IArchTime { -public: - CArch(ARCH_ARGS* args = NULL); - ~CArch(); - - // - // accessors - // - - //! Return the singleton instance - /*! - The client must have instantiated exactly once CArch object before - calling this function. - */ - static CArch* getInstance(); - - // IArchConsole overrides - virtual void openConsole(const char*); - virtual void closeConsole(); - virtual void showConsole(bool showIfEmpty); - virtual void writeConsole(const char*); - virtual const char* getNewlineForConsole(); - - // IArchDaemon overrides - virtual void installDaemon(const char* name, - const char* description, - const char* pathname, - const char* commandLine, - const char* dependencies, - bool allUsers); - virtual void uninstallDaemon(const char* name, bool allUsers); - virtual int daemonize(const char* name, DaemonFunc func); - virtual bool canInstallDaemon(const char* name, bool allUsers); - virtual bool isDaemonInstalled(const char* name, bool allUsers); - - // IArchFile overrides - virtual const char* getBasename(const char* pathname); - virtual std::string getUserDirectory(); - virtual std::string getSystemDirectory(); - virtual std::string concatPath(const std::string& prefix, - const std::string& suffix); - - // IArchLog overrides - virtual void openLog(const char*); - virtual void closeLog(); - virtual void showLog(bool showIfEmpty); - virtual void writeLog(ELevel, const char*); - - // IArchMultithread overrides - virtual CArchCond newCondVar(); - virtual void closeCondVar(CArchCond); - virtual void signalCondVar(CArchCond); - virtual void broadcastCondVar(CArchCond); - virtual bool waitCondVar(CArchCond, CArchMutex, double timeout); - virtual CArchMutex newMutex(); - virtual void closeMutex(CArchMutex); - virtual void lockMutex(CArchMutex); - virtual void unlockMutex(CArchMutex); - virtual CArchThread newThread(ThreadFunc, void*); - virtual CArchThread newCurrentThread(); - virtual CArchThread copyThread(CArchThread); - virtual void closeThread(CArchThread); - virtual void cancelThread(CArchThread); - virtual void setPriorityOfThread(CArchThread, int n); - virtual void testCancelThread(); - virtual bool wait(CArchThread, double timeout); - virtual bool isSameThread(CArchThread, CArchThread); - virtual bool isExitedThread(CArchThread); - virtual void* getResultOfThread(CArchThread); - virtual ThreadID getIDOfThread(CArchThread); - virtual void setSignalHandler(ESignal, SignalFunc, void*); - virtual void raiseSignal(ESignal); - - // IArchNetwork overrides - virtual CArchSocket newSocket(EAddressFamily, ESocketType); - virtual CArchSocket copySocket(CArchSocket s); - virtual void closeSocket(CArchSocket s); - virtual void closeSocketForRead(CArchSocket s); - virtual void closeSocketForWrite(CArchSocket s); - virtual void bindSocket(CArchSocket s, CArchNetAddress addr); - virtual void listenOnSocket(CArchSocket s); - virtual CArchSocket acceptSocket(CArchSocket s, CArchNetAddress* addr); - virtual bool connectSocket(CArchSocket s, CArchNetAddress name); - virtual int pollSocket(CPollEntry[], int num, double timeout); - virtual void unblockPollSocket(CArchThread thread); - virtual size_t readSocket(CArchSocket s, void* buf, size_t len); - virtual size_t writeSocket(CArchSocket s, - const void* buf, size_t len); - virtual void throwErrorOnSocket(CArchSocket); - virtual bool setNoDelayOnSocket(CArchSocket, bool noDelay); - virtual bool setReuseAddrOnSocket(CArchSocket, bool reuse); - virtual std::string getHostName(); - virtual CArchNetAddress newAnyAddr(EAddressFamily); - virtual CArchNetAddress copyAddr(CArchNetAddress); - virtual CArchNetAddress nameToAddr(const std::string&); - virtual void closeAddr(CArchNetAddress); - virtual std::string addrToName(CArchNetAddress); - virtual std::string addrToString(CArchNetAddress); - virtual EAddressFamily getAddrFamily(CArchNetAddress); - virtual void setAddrPort(CArchNetAddress, int port); - virtual int getAddrPort(CArchNetAddress); - virtual bool isAnyAddr(CArchNetAddress); - virtual bool isEqualAddr(CArchNetAddress, CArchNetAddress); - - // IArchSleep overrides - virtual void sleep(double timeout); - - // IArchString overrides - virtual int vsnprintf(char* str, - int size, const char* fmt, va_list ap); - virtual int convStringMBToWC(wchar_t*, - const char*, UInt32 n, bool* errors); - virtual int convStringWCToMB(char*, - const wchar_t*, UInt32 n, bool* errors); - virtual EWideCharEncoding - getWideCharEncoding(); - - // IArchSystem overrides - virtual std::string getOSName() const; - - // IArchTaskBar - virtual void addReceiver(IArchTaskBarReceiver*); - virtual void removeReceiver(IArchTaskBarReceiver*); - virtual void updateReceiver(IArchTaskBarReceiver*); - - // IArchTime overrides - virtual double time(); - -private: - static CArch* s_instance; - - IArchConsole* m_console; - IArchDaemon* m_daemon; - IArchFile* m_file; - IArchLog* m_log; - IArchMultithread* m_mt; - IArchNetwork* m_net; - IArchSleep* m_sleep; - IArchString* m_string; - IArchSystem* m_system; - IArchTaskBar* m_taskbar; - IArchTime* m_time; -}; - -//! Convenience object to lock/unlock an arch mutex -class CArchMutexLock { -public: - CArchMutexLock(CArchMutex mutex) : m_mutex(mutex) - { - ARCH->lockMutex(m_mutex); - } - ~CArchMutexLock() - { - ARCH->unlockMutex(m_mutex); - } - -private: - CArchMutex m_mutex; -}; - -#endif diff --git a/lib/arch/CArchConsoleUnix.cpp b/lib/arch/CArchConsoleUnix.cpp deleted file mode 100644 index dcb6e961..00000000 --- a/lib/arch/CArchConsoleUnix.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CArchConsoleUnix.h" -#include - -// -// CArchConsoleUnix -// - -CArchConsoleUnix::CArchConsoleUnix(void*) -{ - // do nothing -} - -CArchConsoleUnix::~CArchConsoleUnix() -{ - // do nothing -} - -void -CArchConsoleUnix::openConsole(const char*) -{ - // do nothing -} - -void -CArchConsoleUnix::closeConsole() -{ - // do nothing -} - -void -CArchConsoleUnix::showConsole(bool) -{ - // do nothing -} - -void -CArchConsoleUnix::writeConsole(const char* str) -{ - fprintf(stderr, "%s", str); -} - -const char* -CArchConsoleUnix::getNewlineForConsole() -{ - return "\n"; -} diff --git a/lib/arch/CArchConsoleUnix.h b/lib/arch/CArchConsoleUnix.h deleted file mode 100644 index f93630bd..00000000 --- a/lib/arch/CArchConsoleUnix.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CARCHCONSOLEUNIX_H -#define CARCHCONSOLEUNIX_H - -#include "IArchConsole.h" - -#define ARCH_CONSOLE CArchConsoleUnix - -//! Unix implementation of IArchConsole -class CArchConsoleUnix : public IArchConsole { -public: - CArchConsoleUnix(void*); - virtual ~CArchConsoleUnix(); - - // IArchConsole overrides - virtual void openConsole(const char* title); - virtual void closeConsole(); - virtual void showConsole(bool); - virtual void writeConsole(const char*); - virtual const char* getNewlineForConsole(); -}; - -#endif diff --git a/lib/arch/CArchConsoleWindows.cpp b/lib/arch/CArchConsoleWindows.cpp deleted file mode 100644 index 14d418ac..00000000 --- a/lib/arch/CArchConsoleWindows.cpp +++ /dev/null @@ -1,438 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CArchConsoleWindows.h" -#include "IArchMultithread.h" -#include "CArch.h" -#include "CArchMiscWindows.h" -#include - -#define SYNERGY_MSG_CONSOLE_OPEN WM_APP + 0x0021 -#define SYNERGY_MSG_CONSOLE_CLOSE WM_APP + 0x0022 -#define SYNERGY_MSG_CONSOLE_SHOW WM_APP + 0x0023 -#define SYNERGY_MSG_CONSOLE_WRITE WM_APP + 0x0024 -#define SYNERGY_MSG_CONSOLE_CLEAR WM_APP + 0x0025 - -// -// CArchConsoleWindows -// - -CArchConsoleWindows* CArchConsoleWindows::s_instance = NULL; -HINSTANCE CArchConsoleWindows::s_appInstance = NULL; - -CArchConsoleWindows::CArchConsoleWindows(void* appInstance) : - m_show(false), - m_maxLines(1000), - m_numCharacters(0), - m_maxCharacters(65536) -{ - // save the singleton instance - s_instance = this; - - // save app instance - s_appInstance = reinterpret_cast(appInstance); - - // we need a mutex - m_mutex = ARCH->newMutex(); - - // and a condition variable which uses the above mutex - m_ready = false; - m_condVar = ARCH->newCondVar(); - - // we're going to want to get a result from the thread we're - // about to create to know if it initialized successfully. - // so we lock the condition variable. - ARCH->lockMutex(m_mutex); - - // open a window and run an event loop in a separate thread. - // this has to happen in a separate thread because if we - // create a window on the current desktop with the current - // thread then the current thread won't be able to switch - // desktops if it needs to. - m_thread = ARCH->newThread(&CArchConsoleWindows::threadEntry, this); - - // wait for child thread - while (!m_ready) { - ARCH->waitCondVar(m_condVar, m_mutex, -1.0); - } - - // ready - ARCH->unlockMutex(m_mutex); - -} - -CArchConsoleWindows::~CArchConsoleWindows() -{ - if (m_thread != NULL) { - PostMessage(m_hwnd, WM_QUIT, 0, 0); - ARCH->wait(m_thread, -1.0); - ARCH->closeThread(m_thread); - } - ARCH->closeCondVar(m_condVar); - ARCH->closeMutex(m_mutex); - s_instance = NULL; -} - -void -CArchConsoleWindows::openConsole(const char* title) -{ - SetWindowText(m_frame, title); - SendMessage(m_frame, SYNERGY_MSG_CONSOLE_OPEN, 0, 0); -} - -void -CArchConsoleWindows::closeConsole() -{ - SendMessage(m_frame, SYNERGY_MSG_CONSOLE_CLOSE, 0, 0); - SendMessage(m_frame, SYNERGY_MSG_CONSOLE_CLEAR, 0, 0); -} - -void -CArchConsoleWindows::showConsole(bool showIfEmpty) -{ - SendMessage(m_frame, SYNERGY_MSG_CONSOLE_SHOW, showIfEmpty ? 1 : 0, 0); -} - -void -CArchConsoleWindows::writeConsole(const char* str) -{ - SendMessage(m_frame, SYNERGY_MSG_CONSOLE_WRITE, - reinterpret_cast(str), 0); -} - -const char* -CArchConsoleWindows::getNewlineForConsole() -{ - return "\r\n"; -} - -void -CArchConsoleWindows::clearBuffer() -{ - m_buffer.clear(); - m_numCharacters = 0; - SetWindowText(m_hwnd, ""); -} - -void -CArchConsoleWindows::appendBuffer(const char* msg) -{ - bool wasEmpty = m_buffer.empty(); - - // get current selection - CHARRANGE selection; - SendMessage(m_hwnd, EM_EXGETSEL, 0, reinterpret_cast(&selection)); - - // remove tail of buffer - size_t removedCharacters = 0; - while (m_buffer.size() >= m_maxLines) { - removedCharacters += m_buffer.front().size(); - m_buffer.pop_front(); - } - - // remove lines from top of control - if (removedCharacters > 0) { - CHARRANGE range; - range.cpMin = 0; - range.cpMax = static_cast(removedCharacters); - SendMessage(m_hwnd, EM_EXSETSEL, 0, reinterpret_cast(&range)); - SendMessage(m_hwnd, EM_REPLACESEL, FALSE, reinterpret_cast("")); - - // adjust selection - if (selection.cpMin < static_cast(removedCharacters) || - selection.cpMax < static_cast(removedCharacters)) { - selection.cpMin = 0; - selection.cpMax = 0; - } - else { - selection.cpMin -= static_cast(removedCharacters); - selection.cpMax -= static_cast(removedCharacters); - } - - m_numCharacters -= removedCharacters; - } - - // append message - m_buffer.push_back(msg); - size_t newNumCharacters = m_numCharacters + m_buffer.back().size(); - - // add line to bottom of control - if (newNumCharacters > m_maxCharacters) { - m_maxCharacters = newNumCharacters; - SendMessage(m_hwnd, EM_EXLIMITTEXT, 0, m_maxCharacters); - } - CHARRANGE range; - range.cpMin = m_numCharacters; - range.cpMax = m_numCharacters; - SendMessage(m_hwnd, EM_EXSETSEL, 0, reinterpret_cast(&range)); - SendMessage(m_hwnd, EM_REPLACESEL, FALSE, - reinterpret_cast(m_buffer.back().c_str())); - - // adjust selection - bool atEnd = false; - if (selection.cpMax == static_cast(m_numCharacters)) { - selection.cpMin = static_cast(newNumCharacters); - selection.cpMax = static_cast(newNumCharacters); - atEnd = true; - } - - // restore the selection - SendMessage(m_hwnd, EM_EXSETSEL, 0, reinterpret_cast(&selection)); - if (atEnd) { - SendMessage(m_hwnd, EM_SCROLLCARET, 0, 0); - } - - if (wasEmpty && m_show) { - ShowWindow(m_frame, TRUE); - } - - m_numCharacters = newNumCharacters; -} - -void -CArchConsoleWindows::setSize(int width, int height) -{ - DWORD style = GetWindowLong(m_frame, GWL_STYLE); - DWORD exStyle = GetWindowLong(m_frame, GWL_EXSTYLE); - RECT rect; - rect.left = 100; - rect.top = 100; - rect.right = rect.left + width * m_wChar; - rect.bottom = rect.top + height * m_hChar; - AdjustWindowRectEx(&rect, style, FALSE, exStyle); - SetWindowPos(m_frame, NULL, 0, 0, rect.right - rect.left, - rect.bottom - rect.top, - SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER); -} - -LRESULT -CArchConsoleWindows::wndProc(HWND hwnd, - UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) { - case WM_CLOSE: - ShowWindow(m_frame, FALSE); - m_show = false; - return 0; - - case SYNERGY_MSG_CONSOLE_OPEN: - return 0; - - case SYNERGY_MSG_CONSOLE_CLOSE: - SendMessage(m_frame, WM_CLOSE, 0, 0); - m_show = false; - return 0; - - case SYNERGY_MSG_CONSOLE_SHOW: - m_show = true; - if (wParam != 0 || !m_buffer.empty()) { - ShowWindow(m_frame, TRUE); - } - return 0; - - case SYNERGY_MSG_CONSOLE_WRITE: - appendBuffer(reinterpret_cast(wParam)); - return 0; - - case SYNERGY_MSG_CONSOLE_CLEAR: - clearBuffer(); - return 0; - - case WM_SIZE: - if (hwnd == m_frame) { - MoveWindow(m_hwnd, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE); - } - break; - - case WM_SIZING: - if (hwnd == m_frame) { - // get window vs client area info - int wBase = 40 * m_wChar; - int hBase = 40 * m_hChar; - DWORD style = GetWindowLong(m_frame, GWL_STYLE); - DWORD exStyle = GetWindowLong(m_frame, GWL_EXSTYLE); - RECT rect; - rect.left = 100; - rect.top = 100; - rect.right = rect.left + wBase; - rect.bottom = rect.top + hBase; - AdjustWindowRectEx(&rect, style, FALSE, exStyle); - wBase = rect.right - rect.left - wBase; - hBase = rect.bottom - rect.top - hBase; - - // get closest size that's a multiple of the character size - RECT* newRect = (RECT*)lParam; - int width = (newRect->right - newRect->left - wBase) / m_wChar; - int height = (newRect->bottom - newRect->top - hBase) / m_hChar; - width = width * m_wChar + wBase; - height = height * m_hChar + hBase; - - // adjust sizing rect - switch (wParam) { - case WMSZ_LEFT: - case WMSZ_TOPLEFT: - case WMSZ_BOTTOMLEFT: - newRect->left = newRect->right - width; - break; - - case WMSZ_RIGHT: - case WMSZ_TOPRIGHT: - case WMSZ_BOTTOMRIGHT: - newRect->right = newRect->left + width; - break; - } - switch (wParam) { - case WMSZ_TOP: - case WMSZ_TOPLEFT: - case WMSZ_TOPRIGHT: - newRect->top = newRect->bottom - height; - break; - - case WMSZ_BOTTOM: - case WMSZ_BOTTOMLEFT: - case WMSZ_BOTTOMRIGHT: - newRect->bottom = newRect->top + height; - break; - } - return TRUE; - } - break; - - default: - break; - } - - return DefWindowProc(hwnd, msg, wParam, lParam); -} - -LRESULT CALLBACK -CArchConsoleWindows::staticWndProc(HWND hwnd, UINT msg, - WPARAM wParam, LPARAM lParam) -{ - // forward the message - if (s_instance != NULL) { - return s_instance->wndProc(hwnd, msg, wParam, lParam); - } - else { - return DefWindowProc(hwnd, msg, wParam, lParam); - } -} - -void -CArchConsoleWindows::threadMainLoop() -{ - LoadLibrary("RICHED32.DLL"); - - // get the app icons - HICON largeIcon, smallIcon; - CArchMiscWindows::getIcons(largeIcon, smallIcon); - - // register a window class - WNDCLASSEX classInfo; - classInfo.cbSize = sizeof(classInfo); - classInfo.style = 0; - classInfo.lpfnWndProc = &CArchConsoleWindows::staticWndProc; - classInfo.cbClsExtra = 0; - classInfo.cbWndExtra = sizeof(CArchConsoleWindows*); - classInfo.hInstance = s_appInstance; - classInfo.hIcon = largeIcon; - classInfo.hCursor = NULL; - classInfo.hbrBackground = NULL; - classInfo.lpszMenuName = NULL; - classInfo.lpszClassName = TEXT("SynergyConsole"); - classInfo.hIconSm = smallIcon; - ATOM windowClass = RegisterClassEx(&classInfo); - - // create frame window - m_frame = CreateWindowEx(0, - reinterpret_cast(windowClass), - TEXT("Synergy Log"), - WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, CW_USEDEFAULT, 100, 100, - NULL, - NULL, - s_appInstance, - NULL); - - // create log window - m_hwnd = CreateWindowEx(0, - "RichEdit", - TEXT(""), - WS_CHILD | WS_VISIBLE | WS_VSCROLL | - ES_MULTILINE | ES_READONLY, - 0, 0, 1, 1, - m_frame, - (HMENU)1, - s_appInstance, - NULL); - - // select font and get info - HDC hdc = GetDC(m_hwnd); - HGDIOBJ oldFont = SelectObject(hdc, GetStockObject(ANSI_FIXED_FONT)); - TEXTMETRIC metrics; - GetTextMetrics(hdc, &metrics); - CHARFORMAT format; - format.cbSize = sizeof(format); - format.dwMask = CFM_CHARSET | CFM_COLOR | CFM_FACE | - CFM_OFFSET | CFM_SIZE | CFM_PROTECTED | - CFM_BOLD | CFM_ITALIC | - CFM_STRIKEOUT | CFM_UNDERLINE; - format.dwEffects = 0; - format.yHeight = metrics.tmHeight; - format.yOffset = 0; - format.crTextColor = RGB(0, 0, 0); - format.bCharSet = DEFAULT_CHARSET; - format.bPitchAndFamily = FIXED_PITCH | FF_MODERN; - GetTextFace(hdc, sizeof(format.szFaceName), format.szFaceName); - SelectObject(hdc, oldFont); - ReleaseDC(m_hwnd, hdc); - - // prep window - SendMessage(m_hwnd, EM_EXLIMITTEXT, 0, m_maxCharacters); - SendMessage(m_hwnd, EM_SETCHARFORMAT, 0, reinterpret_cast(&format)); - SendMessage(m_hwnd, EM_SETBKGNDCOLOR, 0, RGB(255, 255, 255)); - m_wChar = metrics.tmAveCharWidth; - m_hChar = metrics.tmHeight + metrics.tmExternalLeading; - setSize(80, 25); - - // signal ready - ARCH->lockMutex(m_mutex); - m_ready = true; - ARCH->broadcastCondVar(m_condVar); - ARCH->unlockMutex(m_mutex); - - // handle failure - if (m_hwnd == NULL) { - UnregisterClass(reinterpret_cast(windowClass), s_appInstance); - return; - } - - // main loop - MSG msg; - while (GetMessage(&msg, NULL, 0, 0)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - // clean up - DestroyWindow(m_hwnd); - UnregisterClass(reinterpret_cast(windowClass), s_appInstance); -} - -void* -CArchConsoleWindows::threadEntry(void* self) -{ - reinterpret_cast(self)->threadMainLoop(); - return NULL; -} diff --git a/lib/arch/CArchConsoleWindows.h b/lib/arch/CArchConsoleWindows.h deleted file mode 100644 index 0d59e6ef..00000000 --- a/lib/arch/CArchConsoleWindows.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CARCHCONSOLEWINDOWS_H -#define CARCHCONSOLEWINDOWS_H - -#define WIN32_LEAN_AND_MEAN - -#include "IArchConsole.h" -#include "IArchMultithread.h" -#include "stddeque.h" -#include - -#define ARCH_CONSOLE CArchConsoleWindows - -//! Win32 implementation of IArchConsole -class CArchConsoleWindows : public IArchConsole { -public: - CArchConsoleWindows(void*); - virtual ~CArchConsoleWindows(); - - // IArchConsole overrides - virtual void openConsole(const char* title); - virtual void closeConsole(); - virtual void showConsole(bool showIfEmpty); - virtual void writeConsole(const char*); - virtual const char* getNewlineForConsole(); - -private: - void clearBuffer(); - void appendBuffer(const char*); - void setSize(int width, int height); - - LRESULT wndProc(HWND, UINT, WPARAM, LPARAM); - static LRESULT CALLBACK - staticWndProc(HWND, UINT, WPARAM, LPARAM); - void threadMainLoop(); - static void* threadEntry(void*); - -private: - typedef std::deque MessageBuffer; - - static CArchConsoleWindows* s_instance; - static HINSTANCE s_appInstance; - - // multithread data - CArchMutex m_mutex; - CArchCond m_condVar; - bool m_ready; - CArchThread m_thread; - - // child thread data - HWND m_frame; - HWND m_hwnd; - LONG m_wChar; - LONG m_hChar; - bool m_show; - - // messages - size_t m_maxLines; - size_t m_maxCharacters; - size_t m_numCharacters; - MessageBuffer m_buffer; -}; - -#endif diff --git a/lib/arch/CArchDaemonNone.cpp b/lib/arch/CArchDaemonNone.cpp deleted file mode 100644 index 0281f365..00000000 --- a/lib/arch/CArchDaemonNone.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CArchDaemonNone.h" - -// -// CArchDaemonNone -// - -CArchDaemonNone::CArchDaemonNone() -{ - // do nothing -} - -CArchDaemonNone::~CArchDaemonNone() -{ - // do nothing -} - -void -CArchDaemonNone::installDaemon(const char*, - const char*, - const char*, - const char*, - const char*, - bool) -{ - // do nothing -} - -void -CArchDaemonNone::uninstallDaemon(const char*, bool) -{ - // do nothing -} - -int -CArchDaemonNone::daemonize(const char* name, DaemonFunc func) -{ - // simply forward the call to func. obviously, this doesn't - // do any daemonizing. - return func(1, &name); -} - -bool -CArchDaemonNone::canInstallDaemon(const char*, bool) -{ - return false; -} - -bool -CArchDaemonNone::isDaemonInstalled(const char*, bool) -{ - return false; -} diff --git a/lib/arch/CArchDaemonNone.h b/lib/arch/CArchDaemonNone.h deleted file mode 100644 index 1c196c5d..00000000 --- a/lib/arch/CArchDaemonNone.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CARCHDAEMONNONE_H -#define CARCHDAEMONNONE_H - -#include "IArchDaemon.h" - -#define ARCH_DAEMON CArchDaemonNone - -//! Dummy implementation of IArchDaemon -/*! -This class implements IArchDaemon for a platform that does not have -daemons. The install and uninstall functions do nothing, the query -functions return false, and \c daemonize() simply calls the passed -function and returns its result. -*/ -class CArchDaemonNone : public IArchDaemon { -public: - CArchDaemonNone(); - virtual ~CArchDaemonNone(); - - // IArchDaemon overrides - virtual void installDaemon(const char* name, - const char* description, - const char* pathname, - const char* commandLine, - const char* dependencies, - bool allUsers); - virtual void uninstallDaemon(const char* name, bool allUsers); - virtual int daemonize(const char* name, DaemonFunc func); - virtual bool canInstallDaemon(const char* name, bool allUsers); - virtual bool isDaemonInstalled(const char* name, bool allUsers); -}; - -#endif diff --git a/lib/arch/CArchDaemonUnix.cpp b/lib/arch/CArchDaemonUnix.cpp deleted file mode 100644 index 93d50d4d..00000000 --- a/lib/arch/CArchDaemonUnix.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CArchDaemonUnix.h" -#include "XArchUnix.h" -#include -#include -#include -#include -#include - -// -// CArchDaemonUnix -// - -CArchDaemonUnix::CArchDaemonUnix() -{ - // do nothing -} - -CArchDaemonUnix::~CArchDaemonUnix() -{ - // do nothing -} - -int -CArchDaemonUnix::daemonize(const char* name, DaemonFunc func) -{ - // fork so shell thinks we're done and so we're not a process - // group leader - switch (fork()) { - case -1: - // failed - throw XArchDaemonFailed(new XArchEvalUnix(errno)); - - case 0: - // child - break; - - default: - // parent exits - exit(0); - } - - // become leader of a new session - setsid(); - - // chdir to root so we don't keep mounted filesystems points busy - chdir("/"); - - // mask off permissions for any but owner - umask(077); - - // close open files. we only expect stdin, stdout, stderr to be open. - close(0); - close(1); - close(2); - - // attach file descriptors 0, 1, 2 to /dev/null so inadvertent use - // of standard I/O safely goes in the bit bucket. - open("/dev/null", O_RDONLY); - open("/dev/null", O_RDWR); - dup(1); - - // invoke function - return func(1, &name); -} diff --git a/lib/arch/CArchDaemonUnix.h b/lib/arch/CArchDaemonUnix.h deleted file mode 100644 index 923004e1..00000000 --- a/lib/arch/CArchDaemonUnix.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CARCHDAEMONUNIX_H -#define CARCHDAEMONUNIX_H - -#include "CArchDaemonNone.h" - -#undef ARCH_DAEMON -#define ARCH_DAEMON CArchDaemonUnix - -//! Unix implementation of IArchDaemon -class CArchDaemonUnix : public CArchDaemonNone { -public: - CArchDaemonUnix(); - virtual ~CArchDaemonUnix(); - - // IArchDaemon overrides - virtual int daemonize(const char* name, DaemonFunc func); -}; - -#endif diff --git a/lib/arch/CArchDaemonWindows.cpp b/lib/arch/CArchDaemonWindows.cpp deleted file mode 100644 index ab42ceab..00000000 --- a/lib/arch/CArchDaemonWindows.cpp +++ /dev/null @@ -1,770 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CArchDaemonWindows.h" -#include "CArch.h" -#include "CArchMiscWindows.h" -#include "XArchWindows.h" -#include "stdvector.h" - -// -// CArchDaemonWindows -// - -CArchDaemonWindows* CArchDaemonWindows::s_daemon = NULL; - -CArchDaemonWindows::CArchDaemonWindows() -{ - m_quitMessage = RegisterWindowMessage("SynergyDaemonExit"); -} - -CArchDaemonWindows::~CArchDaemonWindows() -{ - // do nothing -} - -int -CArchDaemonWindows::runDaemon(RunFunc runFunc) -{ - assert(s_daemon != NULL); - - return s_daemon->doRunDaemon(runFunc); -} - -void -CArchDaemonWindows::daemonRunning(bool running) -{ - // if s_daemon is NULL we assume we're running on the windows - // 95 family and we just ignore this call so the caller doesn't - // have to go through the trouble of not calling it on the - // windows 95 family. - if (s_daemon != NULL) { - s_daemon->doDaemonRunning(running); - } -} - -UINT -CArchDaemonWindows::getDaemonQuitMessage() -{ - if (s_daemon != NULL) { - return s_daemon->doGetDaemonQuitMessage(); - } - else { - return 0; - } -} - -void -CArchDaemonWindows::daemonFailed(int result) -{ - // if s_daemon is NULL we assume we're running on the windows - // 95 family and we just ignore this call so the caller doesn't - // have to go through the trouble of not calling it on the - // windows 95 family. - if (s_daemon != NULL) { - throw XArchDaemonRunFailed(result); - } -} - -void -CArchDaemonWindows::installDaemon(const char* name, - const char* description, - const char* pathname, - const char* commandLine, - const char* dependencies, - bool allUsers) -{ - // if not for all users then use the user's autostart registry. - // key. if windows 95 family then use windows 95 services key. - if (!allUsers || CArchMiscWindows::isWindows95Family()) { - // open registry - HKEY key = (allUsers && CArchMiscWindows::isWindows95Family()) ? - open95ServicesKey() : openUserStartupKey(); - if (key == NULL) { - // can't open key - throw XArchDaemonInstallFailed(new XArchEvalWindows); - } - - // construct entry - std::string value; - value += "\""; - value += pathname; - value += "\" "; - value += commandLine; - - // install entry - CArchMiscWindows::setValue(key, name, value); - - // clean up - CArchMiscWindows::closeKey(key); - } - - // windows NT family services - else { - // open service manager - SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_WRITE); - if (mgr == NULL) { - // can't open service manager - throw XArchDaemonInstallFailed(new XArchEvalWindows); - } - - // create the service - SC_HANDLE service = CreateService(mgr, - name, - name, - 0, - SERVICE_WIN32_OWN_PROCESS | - SERVICE_INTERACTIVE_PROCESS, - SERVICE_AUTO_START, - SERVICE_ERROR_NORMAL, - pathname, - NULL, - NULL, - dependencies, - NULL, - NULL); - if (service == NULL) { - // can't create service - DWORD err = GetLastError(); - if (err != ERROR_SERVICE_EXISTS) { - CloseServiceHandle(mgr); - throw XArchDaemonInstallFailed(new XArchEvalWindows(err)); - } - } - - // done with service and manager - CloseServiceHandle(service); - CloseServiceHandle(mgr); - - // open the registry key for this service - HKEY key = openNTServicesKey(); - key = CArchMiscWindows::addKey(key, name); - if (key == NULL) { - // can't open key - DWORD err = GetLastError(); - try { - uninstallDaemon(name, allUsers); - } - catch (...) { - // ignore - } - throw XArchDaemonInstallFailed(new XArchEvalWindows(err)); - } - - // set the description - CArchMiscWindows::setValue(key, _T("Description"), description); - - // set command line - key = CArchMiscWindows::addKey(key, _T("Parameters")); - if (key == NULL) { - // can't open key - DWORD err = GetLastError(); - CArchMiscWindows::closeKey(key); - try { - uninstallDaemon(name, allUsers); - } - catch (...) { - // ignore - } - throw XArchDaemonInstallFailed(new XArchEvalWindows(err)); - } - CArchMiscWindows::setValue(key, _T("CommandLine"), commandLine); - - // done with registry - CArchMiscWindows::closeKey(key); - } -} - -void -CArchDaemonWindows::uninstallDaemon(const char* name, bool allUsers) -{ - // if not for all users then use the user's autostart registry. - // key. if windows 95 family then use windows 95 services key. - if (!allUsers || CArchMiscWindows::isWindows95Family()) { - // open registry - HKEY key = (allUsers && CArchMiscWindows::isWindows95Family()) ? - open95ServicesKey() : openUserStartupKey(); - if (key == NULL) { - // can't open key. daemon is probably not installed. - throw XArchDaemonUninstallNotInstalled(new XArchEvalWindows); - } - - // remove entry - CArchMiscWindows::deleteValue(key, name); - - // clean up - CArchMiscWindows::closeKey(key); - } - - // windows NT family services - else { - // remove parameters for this service. ignore failures. - HKEY key = openNTServicesKey(); - key = CArchMiscWindows::openKey(key, name); - if (key != NULL) { - CArchMiscWindows::deleteKey(key, _T("Parameters")); - CArchMiscWindows::closeKey(key); - } - - // open service manager - SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_WRITE); - if (mgr == NULL) { - // can't open service manager - throw XArchDaemonUninstallFailed(new XArchEvalWindows); - } - - // open the service. oddly, you must open a service to delete it. - SC_HANDLE service = OpenService(mgr, name, DELETE | SERVICE_STOP); - if (service == NULL) { - DWORD err = GetLastError(); - CloseServiceHandle(mgr); - if (err != ERROR_SERVICE_DOES_NOT_EXIST) { - throw XArchDaemonUninstallFailed(new XArchEvalWindows(err)); - } - throw XArchDaemonUninstallNotInstalled(new XArchEvalWindows(err)); - } - - // stop the service. we don't care if we fail. - SERVICE_STATUS status; - ControlService(service, SERVICE_CONTROL_STOP, &status); - - // delete the service - const bool okay = (DeleteService(service) == 0); - const DWORD err = GetLastError(); - - // clean up - CloseServiceHandle(service); - CloseServiceHandle(mgr); - - // handle failure. ignore error if service isn't installed anymore. - if (!okay && isDaemonInstalled(name, allUsers)) { - if (err == ERROR_IO_PENDING) { - // this seems to be a spurious error - return; - } - if (err != ERROR_SERVICE_MARKED_FOR_DELETE) { - throw XArchDaemonUninstallFailed(new XArchEvalWindows(err)); - } - throw XArchDaemonUninstallNotInstalled(new XArchEvalWindows(err)); - } - } -} - -int -CArchDaemonWindows::daemonize(const char* name, DaemonFunc func) -{ - assert(name != NULL); - assert(func != NULL); - - // windows 95 family services - if (CArchMiscWindows::isWindows95Family()) { - typedef DWORD (WINAPI *RegisterServiceProcessT)(DWORD, DWORD); - - // mark this process as a service so it's not killed when the - // user logs off. - HINSTANCE kernel = LoadLibrary("kernel32.dll"); - if (kernel == NULL) { - throw XArchDaemonFailed(new XArchEvalWindows); - } - RegisterServiceProcessT RegisterServiceProcess = - reinterpret_cast( - GetProcAddress(kernel, - "RegisterServiceProcess")); - if (RegisterServiceProcess == NULL) { - // missing RegisterServiceProcess function - DWORD err = GetLastError(); - FreeLibrary(kernel); - throw XArchDaemonFailed(new XArchEvalWindows(err)); - } - if (RegisterServiceProcess(0, 1) == 0) { - // RegisterServiceProcess failed - DWORD err = GetLastError(); - FreeLibrary(kernel); - throw XArchDaemonFailed(new XArchEvalWindows(err)); - } - FreeLibrary(kernel); - - // now simply call the daemon function - return func(1, &name); - } - - // windows NT family services - else { - // save daemon function - m_daemonFunc = func; - - // construct the service entry - SERVICE_TABLE_ENTRY entry[2]; - entry[0].lpServiceName = const_cast(name); - entry[0].lpServiceProc = &CArchDaemonWindows::serviceMainEntry; - entry[1].lpServiceName = NULL; - entry[1].lpServiceProc = NULL; - - // hook us up to the service control manager. this won't return - // (if successful) until the processes have terminated. - s_daemon = this; - if (StartServiceCtrlDispatcher(entry) == 0) { - // StartServiceCtrlDispatcher failed - s_daemon = NULL; - throw XArchDaemonFailed(new XArchEvalWindows); - } - - s_daemon = NULL; - return m_daemonResult; - } -} - -bool -CArchDaemonWindows::canInstallDaemon(const char* /*name*/, bool allUsers) -{ - // if not for all users then use the user's autostart registry. - // key. if windows 95 family then use windows 95 services key. - if (!allUsers || CArchMiscWindows::isWindows95Family()) { - // check if we can open the registry key - HKEY key = (allUsers && CArchMiscWindows::isWindows95Family()) ? - open95ServicesKey() : openUserStartupKey(); - CArchMiscWindows::closeKey(key); - return (key != NULL); - } - - // windows NT family services - else { - // check if we can open service manager for write - SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_WRITE); - if (mgr == NULL) { - return false; - } - CloseServiceHandle(mgr); - - // check if we can open the registry key - HKEY key = openNTServicesKey(); -// key = CArchMiscWindows::addKey(key, name); -// key = CArchMiscWindows::addKey(key, _T("Parameters")); - CArchMiscWindows::closeKey(key); - - return (key != NULL); - } -} - -bool -CArchDaemonWindows::isDaemonInstalled(const char* name, bool allUsers) -{ - // if not for all users then use the user's autostart registry. - // key. if windows 95 family then use windows 95 services key. - if (!allUsers || CArchMiscWindows::isWindows95Family()) { - // check if we can open the registry key - HKEY key = (allUsers && CArchMiscWindows::isWindows95Family()) ? - open95ServicesKey() : openUserStartupKey(); - if (key == NULL) { - return false; - } - - // check for entry - const bool installed = !CArchMiscWindows::readValueString(key, - name).empty(); - - // clean up - CArchMiscWindows::closeKey(key); - - return installed; - } - - // windows NT family services - else { - // check parameters for this service - HKEY key = openNTServicesKey(); - key = CArchMiscWindows::openKey(key, name); - key = CArchMiscWindows::openKey(key, _T("Parameters")); - if (key != NULL) { - const bool installed = !CArchMiscWindows::readValueString(key, - _T("CommandLine")).empty(); - CArchMiscWindows::closeKey(key); - if (!installed) { - return false; - } - } - - // open service manager - SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_READ); - if (mgr == NULL) { - return false; - } - - // open the service - SC_HANDLE service = OpenService(mgr, name, GENERIC_READ); - - // clean up - if (service != NULL) { - CloseServiceHandle(service); - } - CloseServiceHandle(mgr); - - return (service != NULL); - } -} - -HKEY -CArchDaemonWindows::openNTServicesKey() -{ - static const char* s_keyNames[] = { - _T("SYSTEM"), - _T("CurrentControlSet"), - _T("Services"), - NULL - }; - - return CArchMiscWindows::addKey(HKEY_LOCAL_MACHINE, s_keyNames); -} - -HKEY -CArchDaemonWindows::open95ServicesKey() -{ - static const char* s_keyNames[] = { - _T("Software"), - _T("Microsoft"), - _T("Windows"), - _T("CurrentVersion"), - _T("RunServices"), - NULL - }; - - return CArchMiscWindows::addKey(HKEY_LOCAL_MACHINE, s_keyNames); -} - -HKEY -CArchDaemonWindows::openUserStartupKey() -{ - static const char* s_keyNames[] = { - _T("Software"), - _T("Microsoft"), - _T("Windows"), - _T("CurrentVersion"), - _T("Run"), - NULL - }; - - return CArchMiscWindows::addKey(HKEY_CURRENT_USER, s_keyNames); -} - -bool -CArchDaemonWindows::isRunState(DWORD state) -{ - switch (state) { - case SERVICE_START_PENDING: - case SERVICE_CONTINUE_PENDING: - case SERVICE_RUNNING: - return true; - - default: - return false; - } -} - -int -CArchDaemonWindows::doRunDaemon(RunFunc run) -{ - // should only be called from DaemonFunc - assert(m_serviceMutex != NULL); - assert(run != NULL); - - // create message queue for this thread - MSG dummy; - PeekMessage(&dummy, NULL, 0, 0, PM_NOREMOVE); - - int result = 0; - ARCH->lockMutex(m_serviceMutex); - m_daemonThreadID = GetCurrentThreadId(); - while (m_serviceState != SERVICE_STOPPED) { - // wait until we're told to start - while (!isRunState(m_serviceState) && - m_serviceState != SERVICE_STOP_PENDING) { - ARCH->waitCondVar(m_serviceCondVar, m_serviceMutex, -1.0); - } - - // run unless told to stop - if (m_serviceState != SERVICE_STOP_PENDING) { - ARCH->unlockMutex(m_serviceMutex); - try { - result = run(); - } - catch (...) { - ARCH->lockMutex(m_serviceMutex); - setStatusError(0); - m_serviceState = SERVICE_STOPPED; - setStatus(m_serviceState); - ARCH->broadcastCondVar(m_serviceCondVar); - ARCH->unlockMutex(m_serviceMutex); - throw; - } - ARCH->lockMutex(m_serviceMutex); - } - - // notify of new state - if (m_serviceState == SERVICE_PAUSE_PENDING) { - m_serviceState = SERVICE_PAUSED; - } - else { - m_serviceState = SERVICE_STOPPED; - } - setStatus(m_serviceState); - ARCH->broadcastCondVar(m_serviceCondVar); - } - ARCH->unlockMutex(m_serviceMutex); - return result; -} - -void -CArchDaemonWindows::doDaemonRunning(bool running) -{ - ARCH->lockMutex(m_serviceMutex); - if (running) { - m_serviceState = SERVICE_RUNNING; - setStatus(m_serviceState); - ARCH->broadcastCondVar(m_serviceCondVar); - } - ARCH->unlockMutex(m_serviceMutex); -} - -UINT -CArchDaemonWindows::doGetDaemonQuitMessage() -{ - return m_quitMessage; -} - -void -CArchDaemonWindows::setStatus(DWORD state) -{ - setStatus(state, 0, 0); -} - -void -CArchDaemonWindows::setStatus(DWORD state, DWORD step, DWORD waitHint) -{ - assert(s_daemon != NULL); - - SERVICE_STATUS status; - status.dwServiceType = SERVICE_WIN32_OWN_PROCESS | - SERVICE_INTERACTIVE_PROCESS; - status.dwCurrentState = state; - status.dwControlsAccepted = SERVICE_ACCEPT_STOP | - SERVICE_ACCEPT_PAUSE_CONTINUE | - SERVICE_ACCEPT_SHUTDOWN; - status.dwWin32ExitCode = NO_ERROR; - status.dwServiceSpecificExitCode = 0; - status.dwCheckPoint = step; - status.dwWaitHint = waitHint; - SetServiceStatus(s_daemon->m_statusHandle, &status); -} - -void -CArchDaemonWindows::setStatusError(DWORD error) -{ - assert(s_daemon != NULL); - - SERVICE_STATUS status; - status.dwServiceType = SERVICE_WIN32_OWN_PROCESS | - SERVICE_INTERACTIVE_PROCESS; - status.dwCurrentState = SERVICE_STOPPED; - status.dwControlsAccepted = SERVICE_ACCEPT_STOP | - SERVICE_ACCEPT_PAUSE_CONTINUE | - SERVICE_ACCEPT_SHUTDOWN; - status.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR; - status.dwServiceSpecificExitCode = error; - status.dwCheckPoint = 0; - status.dwWaitHint = 0; - SetServiceStatus(s_daemon->m_statusHandle, &status); -} - -void -CArchDaemonWindows::serviceMain(DWORD argc, LPTSTR* argvIn) -{ - typedef std::vector ArgList; - typedef std::vector Arguments; - const char** argv = const_cast(argvIn); - - // create synchronization objects - m_serviceMutex = ARCH->newMutex(); - m_serviceCondVar = ARCH->newCondVar(); - - // register our service handler function - m_statusHandle = RegisterServiceCtrlHandler(argv[0], - &CArchDaemonWindows::serviceHandlerEntry); - if (m_statusHandle == 0) { - // cannot start as service - m_daemonResult = -1; - ARCH->closeCondVar(m_serviceCondVar); - ARCH->closeMutex(m_serviceMutex); - return; - } - - // tell service control manager that we're starting - m_serviceState = SERVICE_START_PENDING; - setStatus(m_serviceState, 0, 10000); - - // if no arguments supplied then try getting them from the registry. - // the first argument doesn't count because it's the service name. - Arguments args; - ArgList myArgv; - if (argc <= 1) { - // read command line - std::string commandLine; - HKEY key = openNTServicesKey(); - key = CArchMiscWindows::openKey(key, argvIn[0]); - key = CArchMiscWindows::openKey(key, _T("Parameters")); - if (key != NULL) { - commandLine = CArchMiscWindows::readValueString(key, - _T("CommandLine")); - } - - // if the command line isn't empty then parse and use it - if (!commandLine.empty()) { - // parse, honoring double quoted substrings - std::string::size_type i = commandLine.find_first_not_of(" \t"); - while (i != std::string::npos && i != commandLine.size()) { - // find end of string - std::string::size_type e; - if (commandLine[i] == '\"') { - // quoted. find closing quote. - ++i; - e = commandLine.find("\"", i); - - // whitespace must follow closing quote - if (e == std::string::npos || - (e + 1 != commandLine.size() && - commandLine[e + 1] != ' ' && - commandLine[e + 1] != '\t')) { - args.clear(); - break; - } - - // extract - args.push_back(commandLine.substr(i, e - i)); - i = e + 1; - } - else { - // unquoted. find next whitespace. - e = commandLine.find_first_of(" \t", i); - if (e == std::string::npos) { - e = commandLine.size(); - } - - // extract - args.push_back(commandLine.substr(i, e - i)); - i = e + 1; - } - - // next argument - i = commandLine.find_first_not_of(" \t", i); - } - - // service name goes first - myArgv.push_back(argv[0]); - - // get pointers - for (size_t i = 0; i < args.size(); ++i) { - myArgv.push_back(args[i].c_str()); - } - - // adjust argc/argv - argc = myArgv.size(); - argv = &myArgv[0]; - } - } - - try { - // invoke daemon function - m_daemonResult = m_daemonFunc(static_cast(argc), argv); - } - catch (XArchDaemonRunFailed& e) { - setStatusError(e.m_result); - m_daemonResult = -1; - } - catch (...) { - setStatusError(1); - m_daemonResult = -1; - } - - // clean up - ARCH->closeCondVar(m_serviceCondVar); - ARCH->closeMutex(m_serviceMutex); -} - -void WINAPI -CArchDaemonWindows::serviceMainEntry(DWORD argc, LPTSTR* argv) -{ - s_daemon->serviceMain(argc, argv); -} - -void -CArchDaemonWindows::serviceHandler(DWORD ctrl) -{ - assert(m_serviceMutex != NULL); - assert(m_serviceCondVar != NULL); - - ARCH->lockMutex(m_serviceMutex); - - // ignore request if service is already stopped - if (s_daemon == NULL || m_serviceState == SERVICE_STOPPED) { - if (s_daemon != NULL) { - setStatus(m_serviceState); - } - ARCH->unlockMutex(m_serviceMutex); - return; - } - - switch (ctrl) { - case SERVICE_CONTROL_PAUSE: - m_serviceState = SERVICE_PAUSE_PENDING; - setStatus(m_serviceState, 0, 5000); - PostThreadMessage(m_daemonThreadID, m_quitMessage, 0, 0); - while (isRunState(m_serviceState)) { - ARCH->waitCondVar(m_serviceCondVar, m_serviceMutex, -1.0); - } - break; - - case SERVICE_CONTROL_CONTINUE: - // FIXME -- maybe should flush quit messages from queue - m_serviceState = SERVICE_CONTINUE_PENDING; - setStatus(m_serviceState, 0, 5000); - ARCH->broadcastCondVar(m_serviceCondVar); - break; - - case SERVICE_CONTROL_STOP: - case SERVICE_CONTROL_SHUTDOWN: - m_serviceState = SERVICE_STOP_PENDING; - setStatus(m_serviceState, 0, 5000); - PostThreadMessage(m_daemonThreadID, m_quitMessage, 0, 0); - ARCH->broadcastCondVar(m_serviceCondVar); - while (isRunState(m_serviceState)) { - ARCH->waitCondVar(m_serviceCondVar, m_serviceMutex, -1.0); - } - break; - - default: - // unknown service command - // fall through - - case SERVICE_CONTROL_INTERROGATE: - setStatus(m_serviceState); - break; - } - - ARCH->unlockMutex(m_serviceMutex); -} - -void WINAPI -CArchDaemonWindows::serviceHandlerEntry(DWORD ctrl) -{ - s_daemon->serviceHandler(ctrl); -} diff --git a/lib/arch/CArchDaemonWindows.h b/lib/arch/CArchDaemonWindows.h deleted file mode 100644 index ed09fab9..00000000 --- a/lib/arch/CArchDaemonWindows.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CARCHDAEMONWINDOWS_H -#define CARCHDAEMONWINDOWS_H - -#define WIN32_LEAN_AND_MEAN - -#include "IArchDaemon.h" -#include "IArchMultithread.h" -#include "stdstring.h" -#include -#include - -#define ARCH_DAEMON CArchDaemonWindows - -//! Win32 implementation of IArchDaemon -class CArchDaemonWindows : public IArchDaemon { -public: - typedef int (*RunFunc)(void); - - CArchDaemonWindows(); - virtual ~CArchDaemonWindows(); - - //! Run the daemon - /*! - When the client calls \c daemonize(), the \c DaemonFunc should call this - function after initialization and argument parsing to perform the - daemon processing. The \c runFunc should perform the daemon's - main loop, calling \c daemonRunning(true) when it enters the main loop - (i.e. after initialization) and \c daemonRunning(false) when it leaves - the main loop. The \c runFunc is called in a new thread and when the - daemon must exit the main loop due to some external control the - getDaemonQuitMessage() is posted to the thread. This function returns - what \c runFunc returns. \c runFunc should call \c daemonFailed() if - the daemon fails. - */ - static int runDaemon(RunFunc runFunc); - - //! Indicate daemon is in main loop - /*! - The \c runFunc passed to \c runDaemon() should call this function - to indicate when it has entered (\c running is \c true) or exited - (\c running is \c false) the main loop. - */ - static void daemonRunning(bool running); - - //! Indicate failure of running daemon - /*! - The \c runFunc passed to \c runDaemon() should call this function - to indicate failure. \c result is returned by \c daemonize(). - */ - static void daemonFailed(int result); - - //! Get daemon quit message - /*! - The windows NT daemon tells daemon thread to exit by posting this - message to it. The thread must, of course, have a message queue - for this to work. - */ - static UINT getDaemonQuitMessage(); - - // IArchDaemon overrides - virtual void installDaemon(const char* name, - const char* description, - const char* pathname, - const char* commandLine, - const char* dependencies, - bool allUsers); - virtual void uninstallDaemon(const char* name, bool allUsers); - virtual int daemonize(const char* name, DaemonFunc func); - virtual bool canInstallDaemon(const char* name, bool allUsers); - virtual bool isDaemonInstalled(const char* name, bool allUsers); - -private: - static HKEY openNTServicesKey(); - static HKEY open95ServicesKey(); - static HKEY openUserStartupKey(); - - int doRunDaemon(RunFunc runFunc); - void doDaemonRunning(bool running); - UINT doGetDaemonQuitMessage(); - - static void setStatus(DWORD state); - static void setStatus(DWORD state, DWORD step, DWORD waitHint); - static void setStatusError(DWORD error); - - static bool isRunState(DWORD state); - - void serviceMain(DWORD, LPTSTR*); - static void WINAPI serviceMainEntry(DWORD, LPTSTR*); - - void serviceHandler(DWORD ctrl); - static void WINAPI serviceHandlerEntry(DWORD ctrl); - -private: - class XArchDaemonRunFailed { - public: - XArchDaemonRunFailed(int result) : m_result(result) { } - - public: - int m_result; - }; - -private: - static CArchDaemonWindows* s_daemon; - - CArchMutex m_serviceMutex; - CArchCond m_serviceCondVar; - DWORD m_serviceState; - bool m_serviceHandlerWaiting; - bool m_serviceRunning; - - DWORD m_daemonThreadID; - DaemonFunc m_daemonFunc; - int m_daemonResult; - - SERVICE_STATUS_HANDLE m_statusHandle; - - UINT m_quitMessage; -}; - -#endif diff --git a/lib/arch/CArchFileUnix.cpp b/lib/arch/CArchFileUnix.cpp deleted file mode 100644 index 89bb51dc..00000000 --- a/lib/arch/CArchFileUnix.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CArchFileUnix.h" -#include -#include -#include -#include -#include - -// -// CArchFileUnix -// - -CArchFileUnix::CArchFileUnix() -{ - // do nothing -} - -CArchFileUnix::~CArchFileUnix() -{ - // do nothing -} - -const char* -CArchFileUnix::getBasename(const char* pathname) -{ - if (pathname == NULL) { - return NULL; - } - - const char* basename = strrchr(pathname, '/'); - if (basename != NULL) { - return basename + 1; - } - else { - return pathname; - } -} - -std::string -CArchFileUnix::getUserDirectory() -{ - char* buffer = NULL; - std::string dir; -#if HAVE_GETPWUID_R - struct passwd pwent; - struct passwd* pwentp; -#if defined(_SC_GETPW_R_SIZE_MAX) - long size = sysconf(_SC_GETPW_R_SIZE_MAX); - if (size == -1) { - size = BUFSIZ; - } -#else - long size = BUFSIZ; -#endif - buffer = new char[size]; - getpwuid_r(getuid(), &pwent, buffer, size, &pwentp); -#else - struct passwd* pwentp = getpwuid(getuid()); -#endif - if (pwentp != NULL && pwentp->pw_dir != NULL) { - dir = pwentp->pw_dir; - } - delete[] buffer; - return dir; -} - -std::string -CArchFileUnix::getSystemDirectory() -{ - return "/etc"; -} - -std::string -CArchFileUnix::concatPath(const std::string& prefix, - const std::string& suffix) -{ - std::string path; - path.reserve(prefix.size() + 1 + suffix.size()); - path += prefix; - if (path.size() == 0 || path[path.size() - 1] != '/') { - path += '/'; - } - path += suffix; - return path; -} diff --git a/lib/arch/CArchFileUnix.h b/lib/arch/CArchFileUnix.h deleted file mode 100644 index 41d00e90..00000000 --- a/lib/arch/CArchFileUnix.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CARCHFILEUNIX_H -#define CARCHFILEUNIX_H - -#include "IArchFile.h" - -#define ARCH_FILE CArchFileUnix - -//! Unix implementation of IArchFile -class CArchFileUnix : public IArchFile { -public: - CArchFileUnix(); - virtual ~CArchFileUnix(); - - // IArchFile overrides - virtual const char* getBasename(const char* pathname); - virtual std::string getUserDirectory(); - virtual std::string getSystemDirectory(); - virtual std::string concatPath(const std::string& prefix, - const std::string& suffix); -}; - -#endif diff --git a/lib/arch/CArchFileWindows.cpp b/lib/arch/CArchFileWindows.cpp deleted file mode 100644 index 5debb17b..00000000 --- a/lib/arch/CArchFileWindows.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CArchFileWindows.h" -#include -#include -#include -#include - -// -// CArchFileWindows -// - -CArchFileWindows::CArchFileWindows() -{ - // do nothing -} - -CArchFileWindows::~CArchFileWindows() -{ - // do nothing -} - -const char* -CArchFileWindows::getBasename(const char* pathname) -{ - if (pathname == NULL) { - return NULL; - } - - // check for last slash - const char* basename = strrchr(pathname, '/'); - if (basename != NULL) { - ++basename; - } - else { - basename = pathname; - } - - // check for last backslash - const char* basename2 = strrchr(pathname, '\\'); - if (basename2 != NULL && basename2 > basename) { - basename = basename2 + 1; - } - - return basename; -} - -std::string -CArchFileWindows::getUserDirectory() -{ - // try %HOMEPATH% - TCHAR dir[MAX_PATH]; - DWORD size = sizeof(dir) / sizeof(TCHAR); - DWORD result = GetEnvironmentVariable(_T("HOMEPATH"), dir, size); - if (result != 0 && result <= size) { - // sanity check -- if dir doesn't appear to start with a - // drive letter and isn't a UNC name then don't use it - // FIXME -- allow UNC names - if (dir[0] != '\0' && (dir[1] == ':' || - ((dir[0] == '\\' || dir[0] == '/') && - (dir[1] == '\\' || dir[1] == '/')))) { - return dir; - } - } - - // get the location of the personal files. that's as close to - // a home directory as we're likely to find. - ITEMIDLIST* idl; - if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_PERSONAL, &idl))) { - TCHAR* path = NULL; - if (SHGetPathFromIDList(idl, dir)) { - DWORD attr = GetFileAttributes(dir); - if (attr != 0xffffffff && (attr & FILE_ATTRIBUTE_DIRECTORY) != 0) - path = dir; - } - - IMalloc* shalloc; - if (SUCCEEDED(SHGetMalloc(&shalloc))) { - shalloc->Free(idl); - shalloc->Release(); - } - - if (path != NULL) { - return path; - } - } - - // use root of C drive as a default - return "C:"; -} - -std::string -CArchFileWindows::getSystemDirectory() -{ - // get windows directory - char dir[MAX_PATH]; - if (GetWindowsDirectory(dir, sizeof(dir)) != 0) { - return dir; - } - else { - // can't get it. use C:\ as a default. - return "C:"; - } -} - -std::string -CArchFileWindows::concatPath(const std::string& prefix, - const std::string& suffix) -{ - std::string path; - path.reserve(prefix.size() + 1 + suffix.size()); - path += prefix; - if (path.size() == 0 || - (path[path.size() - 1] != '\\' && - path[path.size() - 1] != '/')) { - path += '\\'; - } - path += suffix; - return path; -} diff --git a/lib/arch/CArchFileWindows.h b/lib/arch/CArchFileWindows.h deleted file mode 100644 index 617b1c40..00000000 --- a/lib/arch/CArchFileWindows.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CARCHFILEWINDOWS_H -#define CARCHFILEWINDOWS_H - -#include "IArchFile.h" - -#define ARCH_FILE CArchFileWindows - -//! Win32 implementation of IArchFile -class CArchFileWindows : public IArchFile { -public: - CArchFileWindows(); - virtual ~CArchFileWindows(); - - // IArchFile overrides - virtual const char* getBasename(const char* pathname); - virtual std::string getUserDirectory(); - virtual std::string getSystemDirectory(); - virtual std::string concatPath(const std::string& prefix, - const std::string& suffix); -}; - -#endif diff --git a/lib/arch/CArchLogUnix.cpp b/lib/arch/CArchLogUnix.cpp deleted file mode 100644 index 093d89f9..00000000 --- a/lib/arch/CArchLogUnix.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CArchLogUnix.h" -#include - -// -// CArchLogUnix -// - -CArchLogUnix::CArchLogUnix() -{ - // do nothing -} - -CArchLogUnix::~CArchLogUnix() -{ - // do nothing -} - -void -CArchLogUnix::openLog(const char* name) -{ - openlog(name, 0, LOG_DAEMON); -} - -void -CArchLogUnix::closeLog() -{ - closelog(); -} - -void -CArchLogUnix::showLog(bool) -{ - // do nothing -} - -void -CArchLogUnix::writeLog(ELevel level, const char* msg) -{ - // convert level - int priority; - switch (level) { - case kERROR: - priority = LOG_ERR; - break; - - case kWARNING: - priority = LOG_WARNING; - break; - - case kNOTE: - priority = LOG_NOTICE; - break; - - case kINFO: - priority = LOG_INFO; - break; - - default: - priority = LOG_DEBUG; - break; - } - - // log it - syslog(priority, "%s", msg); -} diff --git a/lib/arch/CArchLogUnix.h b/lib/arch/CArchLogUnix.h deleted file mode 100644 index 91070b45..00000000 --- a/lib/arch/CArchLogUnix.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CARCHLOGUNIX_H -#define CARCHLOGUNIX_H - -#include "IArchLog.h" - -#define ARCH_LOG CArchLogUnix - -//! Unix implementation of IArchLog -class CArchLogUnix : public IArchLog { -public: - CArchLogUnix(); - virtual ~CArchLogUnix(); - - // IArchLog overrides - virtual void openLog(const char* name); - virtual void closeLog(); - virtual void showLog(bool); - virtual void writeLog(ELevel, const char*); -}; - -#endif diff --git a/lib/arch/CArchLogWindows.cpp b/lib/arch/CArchLogWindows.cpp deleted file mode 100644 index 0ac89131..00000000 --- a/lib/arch/CArchLogWindows.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CArchLogWindows.h" -#include "CArchMiscWindows.h" -#include - -// -// CArchLogWindows -// - -CArchLogWindows::CArchLogWindows() : m_eventLog(NULL) -{ - // do nothing -} - -CArchLogWindows::~CArchLogWindows() -{ - // do nothing -} - -void -CArchLogWindows::openLog(const char* name) -{ - if (m_eventLog == NULL && !CArchMiscWindows::isWindows95Family()) { - m_eventLog = RegisterEventSource(NULL, name); - } -} - -void -CArchLogWindows::closeLog() -{ - if (m_eventLog != NULL) { - DeregisterEventSource(m_eventLog); - m_eventLog = NULL; - } -} - -void -CArchLogWindows::showLog(bool) -{ - // do nothing -} - -void -CArchLogWindows::writeLog(ELevel level, const char* msg) -{ - if (m_eventLog != NULL) { - // convert priority - WORD type; - switch (level) { - case kERROR: - type = EVENTLOG_ERROR_TYPE; - break; - - case kWARNING: - type = EVENTLOG_WARNING_TYPE; - break; - - default: - type = EVENTLOG_INFORMATION_TYPE; - break; - } - - // log it - // FIXME -- win32 wants to use a message table to look up event - // strings. log messages aren't organized that way so we'll - // just dump our string into the raw data section of the event - // so users can at least see the message. note that we use our - // level as the event category. - ReportEvent(m_eventLog, type, static_cast(level), - 0, // event ID - NULL, - 0, - strlen(msg) + 1, // raw data size - NULL, - const_cast(msg));// raw data - } -} diff --git a/lib/arch/CArchLogWindows.h b/lib/arch/CArchLogWindows.h deleted file mode 100644 index e8812536..00000000 --- a/lib/arch/CArchLogWindows.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CARCHLOGWINDOWS_H -#define CARCHLOGWINDOWS_H - -#define WIN32_LEAN_AND_MEAN - -#include "IArchLog.h" -#include - -#define ARCH_LOG CArchLogWindows - -//! Win32 implementation of IArchLog -class CArchLogWindows : public IArchLog { -public: - CArchLogWindows(); - virtual ~CArchLogWindows(); - - // IArchLog overrides - virtual void openLog(const char* name); - virtual void closeLog(); - virtual void showLog(bool showIfEmpty); - virtual void writeLog(ELevel, const char*); - -private: - HANDLE m_eventLog; -}; - -#endif diff --git a/lib/arch/CArchMiscWindows.cpp b/lib/arch/CArchMiscWindows.cpp deleted file mode 100644 index e2fb2dce..00000000 --- a/lib/arch/CArchMiscWindows.cpp +++ /dev/null @@ -1,416 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CArchMiscWindows.h" -#include "CArchDaemonWindows.h" - -#ifndef ES_SYSTEM_REQUIRED -#define ES_SYSTEM_REQUIRED ((DWORD)0x00000001) -#endif -#ifndef ES_DISPLAY_REQUIRED -#define ES_DISPLAY_REQUIRED ((DWORD)0x00000002) -#endif -#ifndef ES_CONTINUOUS -#define ES_CONTINUOUS ((DWORD)0x80000000) -#endif -typedef DWORD EXECUTION_STATE; - -// -// CArchMiscWindows -// - -CArchMiscWindows::CDialogs* CArchMiscWindows::s_dialogs = NULL; -DWORD CArchMiscWindows::s_busyState = 0; -CArchMiscWindows::STES_t CArchMiscWindows::s_stes = NULL; -HICON CArchMiscWindows::s_largeIcon = NULL; -HICON CArchMiscWindows::s_smallIcon = NULL; - -void -CArchMiscWindows::init() -{ - s_dialogs = new CDialogs; - isWindows95Family(); -} - -bool -CArchMiscWindows::isWindows95Family() -{ - static bool init = false; - static bool result = false; - - if (!init) { - OSVERSIONINFO version; - version.dwOSVersionInfoSize = sizeof(version); - if (GetVersionEx(&version) == 0) { - // cannot determine OS; assume windows 95 family - result = true; - } - else { - result = (version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS); - } - init = true; - } - return result; -} - -bool -CArchMiscWindows::isWindowsModern() -{ - static bool init = false; - static bool result = false; - - if (!init) { - OSVERSIONINFO version; - version.dwOSVersionInfoSize = sizeof(version); - if (GetVersionEx(&version) == 0) { - // cannot determine OS; assume not modern - result = false; - } - else { - result = ((version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && - version.dwMajorVersion == 4 && - version.dwMinorVersion > 0) || - (version.dwPlatformId == VER_PLATFORM_WIN32_NT && - version.dwMajorVersion > 4)); - } - init = true; - } - return result; -} - -void -CArchMiscWindows::setIcons(HICON largeIcon, HICON smallIcon) -{ - s_largeIcon = largeIcon; - s_smallIcon = smallIcon; -} - -void -CArchMiscWindows::getIcons(HICON& largeIcon, HICON& smallIcon) -{ - largeIcon = s_largeIcon; - smallIcon = s_smallIcon; -} - -int -CArchMiscWindows::runDaemon(RunFunc runFunc) -{ - return CArchDaemonWindows::runDaemon(runFunc); -} - -void -CArchMiscWindows::daemonRunning(bool running) -{ - CArchDaemonWindows::daemonRunning(running); -} - -void -CArchMiscWindows::daemonFailed(int result) -{ - CArchDaemonWindows::daemonFailed(result); -} - -UINT -CArchMiscWindows::getDaemonQuitMessage() -{ - return CArchDaemonWindows::getDaemonQuitMessage(); -} - -HKEY -CArchMiscWindows::openKey(HKEY key, const TCHAR* keyName) -{ - return openKey(key, keyName, false); -} - -HKEY -CArchMiscWindows::openKey(HKEY key, const TCHAR* const* keyNames) -{ - return openKey(key, keyNames, false); -} - -HKEY -CArchMiscWindows::addKey(HKEY key, const TCHAR* keyName) -{ - return openKey(key, keyName, true); -} - -HKEY -CArchMiscWindows::addKey(HKEY key, const TCHAR* const* keyNames) -{ - return openKey(key, keyNames, true); -} - -HKEY -CArchMiscWindows::openKey(HKEY key, const TCHAR* keyName, bool create) -{ - // ignore if parent is NULL - if (key == NULL) { - return NULL; - } - - // open next key - HKEY newKey; - LONG result = RegOpenKeyEx(key, keyName, 0, - KEY_WRITE | KEY_QUERY_VALUE, &newKey); - if (result != ERROR_SUCCESS && create) { - DWORD disp; - result = RegCreateKeyEx(key, keyName, 0, TEXT(""), - 0, KEY_WRITE | KEY_QUERY_VALUE, - NULL, &newKey, &disp); - } - if (result != ERROR_SUCCESS) { - RegCloseKey(key); - return NULL; - } - - // switch to new key - RegCloseKey(key); - return newKey; -} - -HKEY -CArchMiscWindows::openKey(HKEY key, const TCHAR* const* keyNames, bool create) -{ - for (size_t i = 0; key != NULL && keyNames[i] != NULL; ++i) { - // open next key - key = openKey(key, keyNames[i], create); - } - return key; -} - -void -CArchMiscWindows::closeKey(HKEY key) -{ - assert(key != NULL); - RegCloseKey(key); -} - -void -CArchMiscWindows::deleteKey(HKEY key, const TCHAR* name) -{ - assert(key != NULL); - assert(name != NULL); - RegDeleteKey(key, name); -} - -void -CArchMiscWindows::deleteValue(HKEY key, const TCHAR* name) -{ - assert(key != NULL); - assert(name != NULL); - RegDeleteValue(key, name); -} - -bool -CArchMiscWindows::hasValue(HKEY key, const TCHAR* name) -{ - DWORD type; - LONG result = RegQueryValueEx(key, name, 0, &type, NULL, NULL); - return (result == ERROR_SUCCESS && - (type == REG_DWORD || type == REG_SZ)); -} - -CArchMiscWindows::EValueType -CArchMiscWindows::typeOfValue(HKEY key, const TCHAR* name) -{ - DWORD type; - LONG result = RegQueryValueEx(key, name, 0, &type, NULL, NULL); - if (result != ERROR_SUCCESS) { - return kNO_VALUE; - } - switch (type) { - case REG_DWORD: - return kUINT; - - case REG_SZ: - return kSTRING; - - case REG_BINARY: - return kBINARY; - - default: - return kUNKNOWN; - } -} - -void -CArchMiscWindows::setValue(HKEY key, - const TCHAR* name, const std::string& value) -{ - assert(key != NULL); - assert(name != NULL); - RegSetValueEx(key, name, 0, REG_SZ, - reinterpret_cast(value.c_str()), - value.size() + 1); -} - -void -CArchMiscWindows::setValue(HKEY key, const TCHAR* name, DWORD value) -{ - assert(key != NULL); - assert(name != NULL); - RegSetValueEx(key, name, 0, REG_DWORD, - reinterpret_cast(&value), - sizeof(DWORD)); -} - -void -CArchMiscWindows::setValueBinary(HKEY key, - const TCHAR* name, const std::string& value) -{ - assert(key != NULL); - assert(name != NULL); - RegSetValueEx(key, name, 0, REG_BINARY, - reinterpret_cast(value.data()), - value.size()); -} - -std::string -CArchMiscWindows::readBinaryOrString(HKEY key, const TCHAR* name, DWORD type) -{ - // get the size of the string - DWORD actualType; - DWORD size = 0; - LONG result = RegQueryValueEx(key, name, 0, &actualType, NULL, &size); - if (result != ERROR_SUCCESS || actualType != type) { - return std::string(); - } - - // if zero size then return empty string - if (size == 0) { - return std::string(); - } - - // allocate space - char* buffer = new char[size]; - - // read it - result = RegQueryValueEx(key, name, 0, &actualType, - reinterpret_cast(buffer), &size); - if (result != ERROR_SUCCESS || actualType != type) { - delete[] buffer; - return std::string(); - } - - // clean up and return value - if (type == REG_SZ && buffer[size - 1] == '\0') { - // don't include terminating nul; std::string will add one. - --size; - } - std::string value(buffer, size); - delete[] buffer; - return value; -} - -std::string -CArchMiscWindows::readValueString(HKEY key, const TCHAR* name) -{ - return readBinaryOrString(key, name, REG_SZ); -} - -std::string -CArchMiscWindows::readValueBinary(HKEY key, const TCHAR* name) -{ - return readBinaryOrString(key, name, REG_BINARY); -} - -DWORD -CArchMiscWindows::readValueInt(HKEY key, const TCHAR* name) -{ - DWORD type; - DWORD value; - DWORD size = sizeof(value); - LONG result = RegQueryValueEx(key, name, 0, &type, - reinterpret_cast(&value), &size); - if (result != ERROR_SUCCESS || type != REG_DWORD) { - return 0; - } - return value; -} - -void -CArchMiscWindows::addDialog(HWND hwnd) -{ - s_dialogs->insert(hwnd); -} - -void -CArchMiscWindows::removeDialog(HWND hwnd) -{ - s_dialogs->erase(hwnd); -} - -bool -CArchMiscWindows::processDialog(MSG* msg) -{ - for (CDialogs::const_iterator index = s_dialogs->begin(); - index != s_dialogs->end(); ++index) { - if (IsDialogMessage(*index, msg)) { - return true; - } - } - return false; -} - -void -CArchMiscWindows::addBusyState(DWORD busyModes) -{ - s_busyState |= busyModes; - setThreadExecutionState(s_busyState); -} - -void -CArchMiscWindows::removeBusyState(DWORD busyModes) -{ - s_busyState &= ~busyModes; - setThreadExecutionState(s_busyState); -} - -void -CArchMiscWindows::setThreadExecutionState(DWORD busyModes) -{ - // look up function dynamically so we work on older systems - if (s_stes == NULL) { - HINSTANCE kernel = LoadLibrary("kernel32.dll"); - if (kernel != NULL) { - s_stes = reinterpret_cast(GetProcAddress(kernel, - "SetThreadExecutionState")); - } - if (s_stes == NULL) { - s_stes = &CArchMiscWindows::dummySetThreadExecutionState; - } - } - - // convert to STES form - EXECUTION_STATE state = 0; - if ((busyModes & kSYSTEM) != 0) { - state |= ES_SYSTEM_REQUIRED; - } - if ((busyModes & kDISPLAY) != 0) { - state |= ES_DISPLAY_REQUIRED; - } - if (state != 0) { - state |= ES_CONTINUOUS; - } - - // do it - s_stes(state); -} - -DWORD -CArchMiscWindows::dummySetThreadExecutionState(DWORD) -{ - // do nothing - return 0; -} diff --git a/lib/arch/CArchMiscWindows.h b/lib/arch/CArchMiscWindows.h deleted file mode 100644 index 95a1d136..00000000 --- a/lib/arch/CArchMiscWindows.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CARCHMISCWINDOWS_H -#define CARCHMISCWINDOWS_H - -#define WIN32_LEAN_AND_MEAN - -#include "common.h" -#include "stdstring.h" -#include "stdset.h" -#include - -//! Miscellaneous win32 functions. -class CArchMiscWindows { -public: - enum EValueType { - kUNKNOWN, - kNO_VALUE, - kUINT, - kSTRING, - kBINARY - }; - enum EBusyModes { - kIDLE = 0x0000, - kSYSTEM = 0x0001, - kDISPLAY = 0x0002 - }; - - typedef int (*RunFunc)(void); - - //! Initialize - static void init(); - - //! Test if windows 95, et al. - /*! - Returns true iff the platform is win95/98/me. - */ - static bool isWindows95Family(); - - //! Test if windows 95, et al. - /*! - Returns true iff the platform is win98 or win2k or higher (i.e. - not windows 95 or windows NT). - */ - static bool isWindowsModern(); - - //! Set the application icons - /*! - Set the application icons. - */ - static void setIcons(HICON largeIcon, HICON smallIcon); - - //! Get the application icons - /*! - Get the application icons. - */ - static void getIcons(HICON& largeIcon, HICON& smallIcon); - - //! Run the daemon - /*! - Delegates to CArchDaemonWindows. - */ - static int runDaemon(RunFunc runFunc); - - //! Indicate daemon is in main loop - /*! - Delegates to CArchDaemonWindows. - */ - static void daemonRunning(bool running); - - //! Indicate failure of running daemon - /*! - Delegates to CArchDaemonWindows. - */ - static void daemonFailed(int result); - - //! Get daemon quit message - /*! - Delegates to CArchDaemonWindows. - */ - static UINT getDaemonQuitMessage(); - - //! Open and return a registry key, closing the parent key - static HKEY openKey(HKEY parent, const TCHAR* child); - - //! Open and return a registry key, closing the parent key - static HKEY openKey(HKEY parent, const TCHAR* const* keyPath); - - //! Open/create and return a registry key, closing the parent key - static HKEY addKey(HKEY parent, const TCHAR* child); - - //! Open/create and return a registry key, closing the parent key - static HKEY addKey(HKEY parent, const TCHAR* const* keyPath); - - //! Close a key - static void closeKey(HKEY); - - //! Delete a key (which should have no subkeys) - static void deleteKey(HKEY parent, const TCHAR* name); - - //! Delete a value - static void deleteValue(HKEY parent, const TCHAR* name); - - //! Test if a value exists - static bool hasValue(HKEY key, const TCHAR* name); - - //! Get type of value - static EValueType typeOfValue(HKEY key, const TCHAR* name); - - //! Set a string value in the registry - static void setValue(HKEY key, const TCHAR* name, - const std::string& value); - - //! Set a DWORD value in the registry - static void setValue(HKEY key, const TCHAR* name, DWORD value); - - //! Set a BINARY value in the registry - /*! - Sets the \p name value of \p key to \p value.data(). - */ - static void setValueBinary(HKEY key, const TCHAR* name, - const std::string& value); - - //! Read a string value from the registry - static std::string readValueString(HKEY, const TCHAR* name); - - //! Read a DWORD value from the registry - static DWORD readValueInt(HKEY, const TCHAR* name); - - //! Read a BINARY value from the registry - static std::string readValueBinary(HKEY, const TCHAR* name); - - //! Add a dialog - static void addDialog(HWND); - - //! Remove a dialog - static void removeDialog(HWND); - - //! Process dialog message - /*! - Checks if the message is destined for a dialog. If so the message - is passed to the dialog and returns true, otherwise returns false. - */ - static bool processDialog(MSG*); - - //! Disable power saving - static void addBusyState(DWORD busyModes); - - //! Enable power saving - static void removeBusyState(DWORD busyModes); - -private: - //! Open and return a registry key, closing the parent key - static HKEY openKey(HKEY parent, const TCHAR* child, bool create); - - //! Open and return a registry key, closing the parent key - static HKEY openKey(HKEY parent, const TCHAR* const* keyPath, - bool create); - - //! Read a string value from the registry - static std::string readBinaryOrString(HKEY, const TCHAR* name, DWORD type); - - //! Set thread busy state - static void setThreadExecutionState(DWORD); - - static DWORD WINAPI dummySetThreadExecutionState(DWORD); - -private: - typedef std::set CDialogs; - typedef DWORD (WINAPI *STES_t)(DWORD); - - static CDialogs* s_dialogs; - static DWORD s_busyState; - static STES_t s_stes; - static HICON s_largeIcon; - static HICON s_smallIcon; -}; - -#endif diff --git a/lib/arch/CArchMultithreadPosix.cpp b/lib/arch/CArchMultithreadPosix.cpp deleted file mode 100644 index ec11fc50..00000000 --- a/lib/arch/CArchMultithreadPosix.cpp +++ /dev/null @@ -1,806 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CArchMultithreadPosix.h" -#include "CArch.h" -#include "XArch.h" -#include -#if TIME_WITH_SYS_TIME -# include -# include -#else -# if HAVE_SYS_TIME_H -# include -# else -# include -# endif -#endif -#include - -#define SIGWAKEUP SIGUSR1 - -#if !HAVE_PTHREAD_SIGNAL - // boy, is this platform broken. forget about pthread signal - // handling and let signals through to every process. synergy - // will not terminate cleanly when it gets SIGTERM or SIGINT. -# define pthread_sigmask sigprocmask -# define pthread_kill(tid_, sig_) kill(0, (sig_)) -# define sigwait(set_, sig_) -# undef HAVE_POSIX_SIGWAIT -# define HAVE_POSIX_SIGWAIT 1 -#endif - -static -void -setSignalSet(sigset_t* sigset) -{ - sigemptyset(sigset); - sigaddset(sigset, SIGHUP); - sigaddset(sigset, SIGINT); - sigaddset(sigset, SIGTERM); - sigaddset(sigset, SIGUSR2); -} - -// -// CArchThreadImpl -// - -class CArchThreadImpl { -public: - CArchThreadImpl(); - -public: - int m_refCount; - IArchMultithread::ThreadID m_id; - pthread_t m_thread; - IArchMultithread::ThreadFunc m_func; - void* m_userData; - bool m_cancel; - bool m_cancelling; - bool m_exited; - void* m_result; - void* m_networkData; -}; - -CArchThreadImpl::CArchThreadImpl() : - m_refCount(1), - m_id(0), - m_func(NULL), - m_userData(NULL), - m_cancel(false), - m_cancelling(false), - m_exited(false), - m_result(NULL), - m_networkData(NULL) -{ - // do nothing -} - - -// -// CArchMultithreadPosix -// - -CArchMultithreadPosix* CArchMultithreadPosix::s_instance = NULL; - -CArchMultithreadPosix::CArchMultithreadPosix() : - m_newThreadCalled(false), - m_nextID(0) -{ - assert(s_instance == NULL); - - s_instance = this; - - // no signal handlers - for (size_t i = 0; i < kNUM_SIGNALS; ++i) { - m_signalFunc[i] = NULL; - m_signalUserData[i] = NULL; - } - - // create mutex for thread list - m_threadMutex = newMutex(); - - // create thread for calling (main) thread and add it to our - // list. no need to lock the mutex since we're the only thread. - m_mainThread = new CArchThreadImpl; - m_mainThread->m_thread = pthread_self(); - insert(m_mainThread); - - // install SIGWAKEUP handler. this causes SIGWAKEUP to interrupt - // system calls. we use that when cancelling a thread to force it - // to wake up immediately if it's blocked in a system call. we - // won't need this until another thread is created but it's fine - // to install it now. - struct sigaction act; - sigemptyset(&act.sa_mask); -# if defined(SA_INTERRUPT) - act.sa_flags = SA_INTERRUPT; -# else - act.sa_flags = 0; -# endif - act.sa_handler = &threadCancel; - sigaction(SIGWAKEUP, &act, NULL); - - // set desired signal dispositions. let SIGWAKEUP through but - // ignore SIGPIPE (we'll handle EPIPE). - sigset_t sigset; - sigemptyset(&sigset); - sigaddset(&sigset, SIGWAKEUP); - pthread_sigmask(SIG_UNBLOCK, &sigset, NULL); - sigemptyset(&sigset); - sigaddset(&sigset, SIGPIPE); - pthread_sigmask(SIG_BLOCK, &sigset, NULL); -} - -CArchMultithreadPosix::~CArchMultithreadPosix() -{ - assert(s_instance != NULL); - - closeMutex(m_threadMutex); - s_instance = NULL; -} - -void -CArchMultithreadPosix::setNetworkDataForCurrentThread(void* data) -{ - lockMutex(m_threadMutex); - CArchThreadImpl* thread = find(pthread_self()); - thread->m_networkData = data; - unlockMutex(m_threadMutex); -} - -void* -CArchMultithreadPosix::getNetworkDataForThread(CArchThread thread) -{ - lockMutex(m_threadMutex); - void* data = thread->m_networkData; - unlockMutex(m_threadMutex); - return data; -} - -CArchMultithreadPosix* -CArchMultithreadPosix::getInstance() -{ - return s_instance; -} - -CArchCond -CArchMultithreadPosix::newCondVar() -{ - CArchCondImpl* cond = new CArchCondImpl; - int status = pthread_cond_init(&cond->m_cond, NULL); - (void)status; - assert(status == 0); - return cond; -} - -void -CArchMultithreadPosix::closeCondVar(CArchCond cond) -{ - int status = pthread_cond_destroy(&cond->m_cond); - (void)status; - assert(status == 0); - delete cond; -} - -void -CArchMultithreadPosix::signalCondVar(CArchCond cond) -{ - int status = pthread_cond_signal(&cond->m_cond); - (void)status; - assert(status == 0); -} - -void -CArchMultithreadPosix::broadcastCondVar(CArchCond cond) -{ - int status = pthread_cond_broadcast(&cond->m_cond); - (void)status; - assert(status == 0); -} - -bool -CArchMultithreadPosix::waitCondVar(CArchCond cond, - CArchMutex mutex, double timeout) -{ - // we can't wait on a condition variable and also wake it up for - // cancellation since we don't use posix cancellation. so we - // must wake up periodically to check for cancellation. we - // can't simply go back to waiting after the check since the - // condition may have changed and we'll have lost the signal. - // so we have to return to the caller. since the caller will - // always check for spurious wakeups the only drawback here is - // performance: we're waking up a lot more than desired. - static const double maxCancellationLatency = 0.1; - if (timeout < 0.0 || timeout > maxCancellationLatency) { - timeout = maxCancellationLatency; - } - - // see if we should cancel this thread - testCancelThread(); - - // get final time - struct timeval now; - gettimeofday(&now, NULL); - struct timespec finalTime; - finalTime.tv_sec = now.tv_sec; - finalTime.tv_nsec = now.tv_usec * 1000; - long timeout_sec = (long)timeout; - long timeout_nsec = (long)(1.0e+9 * (timeout - timeout_sec)); - finalTime.tv_sec += timeout_sec; - finalTime.tv_nsec += timeout_nsec; - if (finalTime.tv_nsec >= 1000000000) { - finalTime.tv_nsec -= 1000000000; - finalTime.tv_sec += 1; - } - - // wait - int status = pthread_cond_timedwait(&cond->m_cond, - &mutex->m_mutex, &finalTime); - - // check for cancel again - testCancelThread(); - - switch (status) { - case 0: - // success - return true; - - case ETIMEDOUT: - return false; - - default: - assert(0 && "condition variable wait error"); - return false; - } -} - -CArchMutex -CArchMultithreadPosix::newMutex() -{ - pthread_mutexattr_t attr; - int status = pthread_mutexattr_init(&attr); - assert(status == 0); - CArchMutexImpl* mutex = new CArchMutexImpl; - status = pthread_mutex_init(&mutex->m_mutex, &attr); - assert(status == 0); - return mutex; -} - -void -CArchMultithreadPosix::closeMutex(CArchMutex mutex) -{ - int status = pthread_mutex_destroy(&mutex->m_mutex); - (void)status; - assert(status == 0); - delete mutex; -} - -void -CArchMultithreadPosix::lockMutex(CArchMutex mutex) -{ - int status = pthread_mutex_lock(&mutex->m_mutex); - - switch (status) { - case 0: - // success - return; - - case EDEADLK: - assert(0 && "lock already owned"); - break; - - case EAGAIN: - assert(0 && "too many recursive locks"); - break; - - default: - assert(0 && "unexpected error"); - break; - } -} - -void -CArchMultithreadPosix::unlockMutex(CArchMutex mutex) -{ - int status = pthread_mutex_unlock(&mutex->m_mutex); - - switch (status) { - case 0: - // success - return; - - case EPERM: - assert(0 && "thread doesn't own a lock"); - break; - - default: - assert(0 && "unexpected error"); - break; - } -} - -CArchThread -CArchMultithreadPosix::newThread(ThreadFunc func, void* data) -{ - assert(func != NULL); - - // initialize signal handler. we do this here instead of the - // constructor so we can avoid daemonizing (using fork()) - // when there are multiple threads. clients can safely - // use condition variables and mutexes before creating a - // new thread and they can safely use the only thread - // they have access to, the main thread, so they really - // can't tell the difference. - if (!m_newThreadCalled) { - m_newThreadCalled = true; -#if HAVE_PTHREAD_SIGNAL - startSignalHandler(); -#endif - } - - lockMutex(m_threadMutex); - - // create thread impl for new thread - CArchThreadImpl* thread = new CArchThreadImpl; - thread->m_func = func; - thread->m_userData = data; - - // create the thread. pthread_create() on RedHat 7.2 smp fails - // if passed a NULL attr so use a default attr. - pthread_attr_t attr; - int status = pthread_attr_init(&attr); - if (status == 0) { - status = pthread_create(&thread->m_thread, &attr, - &CArchMultithreadPosix::threadFunc, thread); - pthread_attr_destroy(&attr); - } - - // check if thread was started - if (status != 0) { - // failed to start thread so clean up - delete thread; - thread = NULL; - } - else { - // add thread to list - insert(thread); - - // increment ref count to account for the thread itself - refThread(thread); - } - - // note that the child thread will wait until we release this mutex - unlockMutex(m_threadMutex); - - return thread; -} - -CArchThread -CArchMultithreadPosix::newCurrentThread() -{ - lockMutex(m_threadMutex); - CArchThreadImpl* thread = find(pthread_self()); - unlockMutex(m_threadMutex); - assert(thread != NULL); - return thread; -} - -void -CArchMultithreadPosix::closeThread(CArchThread thread) -{ - assert(thread != NULL); - - // decrement ref count and clean up thread if no more references - if (--thread->m_refCount == 0) { - // detach from thread (unless it's the main thread) - if (thread->m_func != NULL) { - pthread_detach(thread->m_thread); - } - - // remove thread from list - lockMutex(m_threadMutex); - assert(findNoRef(thread->m_thread) == thread); - erase(thread); - unlockMutex(m_threadMutex); - - // done with thread - delete thread; - } -} - -CArchThread -CArchMultithreadPosix::copyThread(CArchThread thread) -{ - refThread(thread); - return thread; -} - -void -CArchMultithreadPosix::cancelThread(CArchThread thread) -{ - assert(thread != NULL); - - // set cancel and wakeup flags if thread can be cancelled - bool wakeup = false; - lockMutex(m_threadMutex); - if (!thread->m_exited && !thread->m_cancelling) { - thread->m_cancel = true; - wakeup = true; - } - unlockMutex(m_threadMutex); - - // force thread to exit system calls if wakeup is true - if (wakeup) { - pthread_kill(thread->m_thread, SIGWAKEUP); - } -} - -void -CArchMultithreadPosix::setPriorityOfThread(CArchThread thread, int /*n*/) -{ - assert(thread != NULL); - - // FIXME -} - -void -CArchMultithreadPosix::testCancelThread() -{ - // find current thread - lockMutex(m_threadMutex); - CArchThreadImpl* thread = findNoRef(pthread_self()); - unlockMutex(m_threadMutex); - - // test cancel on thread - testCancelThreadImpl(thread); -} - -bool -CArchMultithreadPosix::wait(CArchThread target, double timeout) -{ - assert(target != NULL); - - lockMutex(m_threadMutex); - - // find current thread - CArchThreadImpl* self = findNoRef(pthread_self()); - - // ignore wait if trying to wait on ourself - if (target == self) { - unlockMutex(m_threadMutex); - return false; - } - - // ref the target so it can't go away while we're watching it - refThread(target); - - unlockMutex(m_threadMutex); - - try { - // do first test regardless of timeout - testCancelThreadImpl(self); - if (isExitedThread(target)) { - closeThread(target); - return true; - } - - // wait and repeat test if there's a timeout - if (timeout != 0.0) { - const double start = ARCH->time(); - do { - // wait a little - ARCH->sleep(0.05); - - // repeat test - testCancelThreadImpl(self); - if (isExitedThread(target)) { - closeThread(target); - return true; - } - - // repeat wait and test until timed out - } while (timeout < 0.0 || (ARCH->time() - start) <= timeout); - } - - closeThread(target); - return false; - } - catch (...) { - closeThread(target); - throw; - } -} - -bool -CArchMultithreadPosix::isSameThread(CArchThread thread1, CArchThread thread2) -{ - return (thread1 == thread2); -} - -bool -CArchMultithreadPosix::isExitedThread(CArchThread thread) -{ - lockMutex(m_threadMutex); - bool exited = thread->m_exited; - unlockMutex(m_threadMutex); - return exited; -} - -void* -CArchMultithreadPosix::getResultOfThread(CArchThread thread) -{ - lockMutex(m_threadMutex); - void* result = thread->m_result; - unlockMutex(m_threadMutex); - return result; -} - -IArchMultithread::ThreadID -CArchMultithreadPosix::getIDOfThread(CArchThread thread) -{ - return thread->m_id; -} - -void -CArchMultithreadPosix::setSignalHandler( - ESignal signal, SignalFunc func, void* userData) -{ - lockMutex(m_threadMutex); - m_signalFunc[signal] = func; - m_signalUserData[signal] = userData; - unlockMutex(m_threadMutex); -} - -void -CArchMultithreadPosix::raiseSignal(ESignal signal) -{ - lockMutex(m_threadMutex); - if (m_signalFunc[signal] != NULL) { - m_signalFunc[signal](signal, m_signalUserData[signal]); - pthread_kill(m_mainThread->m_thread, SIGWAKEUP); - } - else if (signal == kINTERRUPT || signal == kTERMINATE) { - ARCH->cancelThread(m_mainThread); - } - unlockMutex(m_threadMutex); -} - -void -CArchMultithreadPosix::startSignalHandler() -{ - // set signal mask. the main thread blocks these signals and - // the signal handler thread will listen for them. - sigset_t sigset, oldsigset; - setSignalSet(&sigset); - pthread_sigmask(SIG_BLOCK, &sigset, &oldsigset); - - // fire up the INT and TERM signal handler thread. we could - // instead arrange to catch and handle these signals but - // we'd be unable to cancel the main thread since no pthread - // calls are allowed in a signal handler. - pthread_attr_t attr; - int status = pthread_attr_init(&attr); - if (status == 0) { - status = pthread_create(&m_signalThread, &attr, - &CArchMultithreadPosix::threadSignalHandler, - NULL); - pthread_attr_destroy(&attr); - } - if (status != 0) { - // can't create thread to wait for signal so don't block - // the signals. - pthread_sigmask(SIG_UNBLOCK, &oldsigset, NULL); - } -} - -CArchThreadImpl* -CArchMultithreadPosix::find(pthread_t thread) -{ - CArchThreadImpl* impl = findNoRef(thread); - if (impl != NULL) { - refThread(impl); - } - return impl; -} - -CArchThreadImpl* -CArchMultithreadPosix::findNoRef(pthread_t thread) -{ - // linear search - for (CThreadList::const_iterator index = m_threadList.begin(); - index != m_threadList.end(); ++index) { - if ((*index)->m_thread == thread) { - return *index; - } - } - return NULL; -} - -void -CArchMultithreadPosix::insert(CArchThreadImpl* thread) -{ - assert(thread != NULL); - - // thread shouldn't already be on the list - assert(findNoRef(thread->m_thread) == NULL); - - // set thread id. note that we don't worry about m_nextID - // wrapping back to 0 and duplicating thread ID's since the - // likelihood of synergy running that long is vanishingly - // small. - thread->m_id = ++m_nextID; - - // append to list - m_threadList.push_back(thread); -} - -void -CArchMultithreadPosix::erase(CArchThreadImpl* thread) -{ - for (CThreadList::iterator index = m_threadList.begin(); - index != m_threadList.end(); ++index) { - if (*index == thread) { - m_threadList.erase(index); - break; - } - } -} - -void -CArchMultithreadPosix::refThread(CArchThreadImpl* thread) -{ - assert(thread != NULL); - assert(findNoRef(thread->m_thread) != NULL); - ++thread->m_refCount; -} - -void -CArchMultithreadPosix::testCancelThreadImpl(CArchThreadImpl* thread) -{ - assert(thread != NULL); - - // update cancel state - lockMutex(m_threadMutex); - bool cancel = false; - if (thread->m_cancel && !thread->m_cancelling) { - thread->m_cancelling = true; - thread->m_cancel = false; - cancel = true; - } - unlockMutex(m_threadMutex); - - // unwind thread's stack if cancelling - if (cancel) { - throw XThreadCancel(); - } -} - -void* -CArchMultithreadPosix::threadFunc(void* vrep) -{ - // get the thread - CArchThreadImpl* thread = reinterpret_cast(vrep); - - // setup pthreads - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); - pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); - - // run thread - s_instance->doThreadFunc(thread); - - // terminate the thread - return NULL; -} - -void -CArchMultithreadPosix::doThreadFunc(CArchThread thread) -{ - // default priority is slightly below normal - setPriorityOfThread(thread, 1); - - // wait for parent to initialize this object - lockMutex(m_threadMutex); - unlockMutex(m_threadMutex); - - void* result = NULL; - try { - // go - result = (*thread->m_func)(thread->m_userData); - } - - catch (XThreadCancel&) { - // client called cancel() - } - catch (...) { - // note -- don't catch (...) to avoid masking bugs - lockMutex(m_threadMutex); - thread->m_exited = true; - unlockMutex(m_threadMutex); - closeThread(thread); - throw; - } - - // thread has exited - lockMutex(m_threadMutex); - thread->m_result = result; - thread->m_exited = true; - unlockMutex(m_threadMutex); - - // done with thread - closeThread(thread); -} - -void -CArchMultithreadPosix::threadCancel(int) -{ - // do nothing -} - -void* -CArchMultithreadPosix::threadSignalHandler(void*) -{ - // detach - pthread_detach(pthread_self()); - - // add signal to mask - sigset_t sigset; - setSignalSet(&sigset); - - // also wait on SIGABRT. on linux (others?) this thread (process) - // will persist after all the other threads evaporate due to an - // assert unless we wait on SIGABRT. that means our resources (like - // the socket we're listening on) are not released and never will be - // until the lingering thread is killed. i don't know why sigwait() - // should protect the thread from being killed. note that sigwait() - // doesn't actually return if we receive SIGABRT and, for some - // reason, we don't have to block SIGABRT. - sigaddset(&sigset, SIGABRT); - - // we exit the loop via thread cancellation in sigwait() - for (;;) { - // wait -#if HAVE_POSIX_SIGWAIT - int signal = 0; - sigwait(&sigset, &signal); -#else - sigwait(&sigset); -#endif - - // if we get here then the signal was raised - switch (signal) { - case SIGINT: - ARCH->raiseSignal(kINTERRUPT); - break; - - case SIGTERM: - ARCH->raiseSignal(kTERMINATE); - break; - - case SIGHUP: - ARCH->raiseSignal(kHANGUP); - break; - - case SIGUSR2: - ARCH->raiseSignal(kUSER); - break; - - default: - // ignore - break; - } - } - - return NULL; -} diff --git a/lib/arch/CArchMultithreadPosix.h b/lib/arch/CArchMultithreadPosix.h deleted file mode 100644 index 4e587cfc..00000000 --- a/lib/arch/CArchMultithreadPosix.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CARCHMULTITHREADPOSIX_H -#define CARCHMULTITHREADPOSIX_H - -#include "IArchMultithread.h" -#include "stdlist.h" -#include - -#define ARCH_MULTITHREAD CArchMultithreadPosix - -class CArchCondImpl { -public: - pthread_cond_t m_cond; -}; - -class CArchMutexImpl { -public: - pthread_mutex_t m_mutex; -}; - -//! Posix implementation of IArchMultithread -class CArchMultithreadPosix : public IArchMultithread { -public: - CArchMultithreadPosix(); - virtual ~CArchMultithreadPosix(); - - //! @name manipulators - //@{ - - void setNetworkDataForCurrentThread(void*); - - //@} - //! @name accessors - //@{ - - void* getNetworkDataForThread(CArchThread); - - static CArchMultithreadPosix* getInstance(); - - //@} - - // IArchMultithread overrides - virtual CArchCond newCondVar(); - virtual void closeCondVar(CArchCond); - virtual void signalCondVar(CArchCond); - virtual void broadcastCondVar(CArchCond); - virtual bool waitCondVar(CArchCond, CArchMutex, double timeout); - virtual CArchMutex newMutex(); - virtual void closeMutex(CArchMutex); - virtual void lockMutex(CArchMutex); - virtual void unlockMutex(CArchMutex); - virtual CArchThread newThread(ThreadFunc, void*); - virtual CArchThread newCurrentThread(); - virtual CArchThread copyThread(CArchThread); - virtual void closeThread(CArchThread); - virtual void cancelThread(CArchThread); - virtual void setPriorityOfThread(CArchThread, int n); - virtual void testCancelThread(); - virtual bool wait(CArchThread, double timeout); - virtual bool isSameThread(CArchThread, CArchThread); - virtual bool isExitedThread(CArchThread); - virtual void* getResultOfThread(CArchThread); - virtual ThreadID getIDOfThread(CArchThread); - virtual void setSignalHandler(ESignal, SignalFunc, void*); - virtual void raiseSignal(ESignal); - -private: - void startSignalHandler(); - - CArchThreadImpl* find(pthread_t thread); - CArchThreadImpl* findNoRef(pthread_t thread); - void insert(CArchThreadImpl* thread); - void erase(CArchThreadImpl* thread); - - void refThread(CArchThreadImpl* rep); - void testCancelThreadImpl(CArchThreadImpl* rep); - - void doThreadFunc(CArchThread thread); - static void* threadFunc(void* vrep); - static void threadCancel(int); - static void* threadSignalHandler(void* vrep); - -private: - typedef std::list CThreadList; - - static CArchMultithreadPosix* s_instance; - - bool m_newThreadCalled; - - CArchMutex m_threadMutex; - CArchThread m_mainThread; - CThreadList m_threadList; - ThreadID m_nextID; - - pthread_t m_signalThread; - SignalFunc m_signalFunc[kNUM_SIGNALS]; - void* m_signalUserData[kNUM_SIGNALS]; -}; - -#endif diff --git a/lib/arch/CArchMultithreadWindows.cpp b/lib/arch/CArchMultithreadWindows.cpp deleted file mode 100644 index 3adcd46a..00000000 --- a/lib/arch/CArchMultithreadWindows.cpp +++ /dev/null @@ -1,699 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#if defined(_MSC_VER) && !defined(_MT) -# error multithreading compile option is required -#endif - -#include "CArchMultithreadWindows.h" -#include "CArch.h" -#include "XArch.h" -#include - -// -// note -- implementation of condition variable taken from: -// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html -// titled "Strategies for Implementing POSIX Condition Variables -// on Win32." it also provides an implementation that doesn't -// suffer from the incorrectness problem described in our -// corresponding header but it is slower, still unfair, and -// can cause busy waiting. -// - -// -// CArchThreadImpl -// - -class CArchThreadImpl { -public: - CArchThreadImpl(); - ~CArchThreadImpl(); - -public: - int m_refCount; - HANDLE m_thread; - DWORD m_id; - IArchMultithread::ThreadFunc m_func; - void* m_userData; - HANDLE m_cancel; - bool m_cancelling; - HANDLE m_exit; - void* m_result; - void* m_networkData; -}; - -CArchThreadImpl::CArchThreadImpl() : - m_refCount(1), - m_thread(NULL), - m_id(0), - m_func(NULL), - m_userData(NULL), - m_cancelling(false), - m_result(NULL), - m_networkData(NULL) -{ - m_exit = CreateEvent(NULL, TRUE, FALSE, NULL); - m_cancel = CreateEvent(NULL, TRUE, FALSE, NULL); -} - -CArchThreadImpl::~CArchThreadImpl() -{ - CloseHandle(m_exit); - CloseHandle(m_cancel); -} - - -// -// CArchMultithreadWindows -// - -CArchMultithreadWindows* CArchMultithreadWindows::s_instance = NULL; - -CArchMultithreadWindows::CArchMultithreadWindows() -{ - assert(s_instance == NULL); - s_instance = this; - - // no signal handlers - for (size_t i = 0; i < kNUM_SIGNALS; ++i) { - m_signalFunc[i] = NULL; - m_signalUserData[i] = NULL; - } - - // create mutex for thread list - m_threadMutex = newMutex(); - - // create thread for calling (main) thread and add it to our - // list. no need to lock the mutex since we're the only thread. - m_mainThread = new CArchThreadImpl; - m_mainThread->m_thread = NULL; - m_mainThread->m_id = GetCurrentThreadId(); - insert(m_mainThread); -} - -CArchMultithreadWindows::~CArchMultithreadWindows() -{ - s_instance = NULL; - - // clean up thread list - for (CThreadList::iterator index = m_threadList.begin(); - index != m_threadList.end(); ++index) { - delete *index; - } - - // done with mutex - delete m_threadMutex; -} - -void -CArchMultithreadWindows::setNetworkDataForCurrentThread(void* data) -{ - lockMutex(m_threadMutex); - CArchThreadImpl* thread = findNoRef(GetCurrentThreadId()); - thread->m_networkData = data; - unlockMutex(m_threadMutex); -} - -void* -CArchMultithreadWindows::getNetworkDataForThread(CArchThread thread) -{ - lockMutex(m_threadMutex); - void* data = thread->m_networkData; - unlockMutex(m_threadMutex); - return data; -} - -HANDLE -CArchMultithreadWindows::getCancelEventForCurrentThread() -{ - lockMutex(m_threadMutex); - CArchThreadImpl* thread = findNoRef(GetCurrentThreadId()); - unlockMutex(m_threadMutex); - return thread->m_cancel; -} - -CArchMultithreadWindows* -CArchMultithreadWindows::getInstance() -{ - return s_instance; -} - -CArchCond -CArchMultithreadWindows::newCondVar() -{ - CArchCondImpl* cond = new CArchCondImpl; - cond->m_events[CArchCondImpl::kSignal] = CreateEvent(NULL, - FALSE, FALSE, NULL); - cond->m_events[CArchCondImpl::kBroadcast] = CreateEvent(NULL, - TRUE, FALSE, NULL); - cond->m_waitCountMutex = newMutex(); - cond->m_waitCount = 0; - return cond; -} - -void -CArchMultithreadWindows::closeCondVar(CArchCond cond) -{ - CloseHandle(cond->m_events[CArchCondImpl::kSignal]); - CloseHandle(cond->m_events[CArchCondImpl::kBroadcast]); - closeMutex(cond->m_waitCountMutex); - delete cond; -} - -void -CArchMultithreadWindows::signalCondVar(CArchCond cond) -{ - // is anybody waiting? - lockMutex(cond->m_waitCountMutex); - const bool hasWaiter = (cond->m_waitCount > 0); - unlockMutex(cond->m_waitCountMutex); - - // wake one thread if anybody is waiting - if (hasWaiter) { - SetEvent(cond->m_events[CArchCondImpl::kSignal]); - } -} - -void -CArchMultithreadWindows::broadcastCondVar(CArchCond cond) -{ - // is anybody waiting? - lockMutex(cond->m_waitCountMutex); - const bool hasWaiter = (cond->m_waitCount > 0); - unlockMutex(cond->m_waitCountMutex); - - // wake all threads if anybody is waiting - if (hasWaiter) { - SetEvent(cond->m_events[CArchCondImpl::kBroadcast]); - } -} - -bool -CArchMultithreadWindows::waitCondVar(CArchCond cond, - CArchMutex mutex, double timeout) -{ - // prepare to wait - const DWORD winTimeout = (timeout < 0.0) ? INFINITE : - static_cast(1000.0 * timeout); - - // make a list of the condition variable events and the cancel event - // for the current thread. - HANDLE handles[4]; - handles[0] = cond->m_events[CArchCondImpl::kSignal]; - handles[1] = cond->m_events[CArchCondImpl::kBroadcast]; - handles[2] = getCancelEventForCurrentThread(); - - // update waiter count - lockMutex(cond->m_waitCountMutex); - ++cond->m_waitCount; - unlockMutex(cond->m_waitCountMutex); - - // release mutex. this should be atomic with the wait so that it's - // impossible for another thread to signal us between the unlock and - // the wait, which would lead to a lost signal on broadcasts. - // however, we're using a manual reset event for broadcasts which - // stays set until we reset it, so we don't lose the broadcast. - unlockMutex(mutex); - - // wait for a signal or broadcast - DWORD result = WaitForMultipleObjects(3, handles, FALSE, winTimeout); - - // cancel takes priority - if (result != WAIT_OBJECT_0 + 2 && - WaitForSingleObject(handles[2], 0) == WAIT_OBJECT_0) { - result = WAIT_OBJECT_0 + 2; - } - - // update the waiter count and check if we're the last waiter - lockMutex(cond->m_waitCountMutex); - --cond->m_waitCount; - const bool last = (result == WAIT_OBJECT_0 + 1 && cond->m_waitCount == 0); - unlockMutex(cond->m_waitCountMutex); - - // reset the broadcast event if we're the last waiter - if (last) { - ResetEvent(cond->m_events[CArchCondImpl::kBroadcast]); - } - - // reacquire the mutex - lockMutex(mutex); - - // cancel thread if necessary - if (result == WAIT_OBJECT_0 + 2) { - ARCH->testCancelThread(); - } - - // return success or failure - return (result == WAIT_OBJECT_0 + 0 || - result == WAIT_OBJECT_0 + 1); -} - -CArchMutex -CArchMultithreadWindows::newMutex() -{ - CArchMutexImpl* mutex = new CArchMutexImpl; - InitializeCriticalSection(&mutex->m_mutex); - return mutex; -} - -void -CArchMultithreadWindows::closeMutex(CArchMutex mutex) -{ - DeleteCriticalSection(&mutex->m_mutex); - delete mutex; -} - -void -CArchMultithreadWindows::lockMutex(CArchMutex mutex) -{ - EnterCriticalSection(&mutex->m_mutex); -} - -void -CArchMultithreadWindows::unlockMutex(CArchMutex mutex) -{ - LeaveCriticalSection(&mutex->m_mutex); -} - -CArchThread -CArchMultithreadWindows::newThread(ThreadFunc func, void* data) -{ - lockMutex(m_threadMutex); - - // create thread impl for new thread - CArchThreadImpl* thread = new CArchThreadImpl; - thread->m_func = func; - thread->m_userData = data; - - // create thread - unsigned int id; - thread->m_thread = reinterpret_cast(_beginthreadex(NULL, 0, - threadFunc, (void*)thread, 0, &id)); - thread->m_id = static_cast(id); - - // check if thread was started - if (thread->m_thread == 0) { - // failed to start thread so clean up - delete thread; - thread = NULL; - } - else { - // add thread to list - insert(thread); - - // increment ref count to account for the thread itself - refThread(thread); - } - - // note that the child thread will wait until we release this mutex - unlockMutex(m_threadMutex); - - return thread; -} - -CArchThread -CArchMultithreadWindows::newCurrentThread() -{ - lockMutex(m_threadMutex); - CArchThreadImpl* thread = find(GetCurrentThreadId()); - unlockMutex(m_threadMutex); - assert(thread != NULL); - return thread; -} - -void -CArchMultithreadWindows::closeThread(CArchThread thread) -{ - assert(thread != NULL); - - // decrement ref count and clean up thread if no more references - if (--thread->m_refCount == 0) { - // close the handle (main thread has a NULL handle) - if (thread->m_thread != NULL) { - CloseHandle(thread->m_thread); - } - - // remove thread from list - lockMutex(m_threadMutex); - assert(findNoRefOrCreate(thread->m_id) == thread); - erase(thread); - unlockMutex(m_threadMutex); - - // done with thread - delete thread; - } -} - -CArchThread -CArchMultithreadWindows::copyThread(CArchThread thread) -{ - refThread(thread); - return thread; -} - -void -CArchMultithreadWindows::cancelThread(CArchThread thread) -{ - assert(thread != NULL); - - // set cancel flag - SetEvent(thread->m_cancel); -} - -void -CArchMultithreadWindows::setPriorityOfThread(CArchThread thread, int n) -{ - struct CPriorityInfo { - public: - DWORD m_class; - int m_level; - }; - static const CPriorityInfo s_pClass[] = { - { IDLE_PRIORITY_CLASS, THREAD_PRIORITY_IDLE }, - { IDLE_PRIORITY_CLASS, THREAD_PRIORITY_LOWEST }, - { IDLE_PRIORITY_CLASS, THREAD_PRIORITY_BELOW_NORMAL }, - { IDLE_PRIORITY_CLASS, THREAD_PRIORITY_NORMAL }, - { IDLE_PRIORITY_CLASS, THREAD_PRIORITY_ABOVE_NORMAL }, - { IDLE_PRIORITY_CLASS, THREAD_PRIORITY_HIGHEST }, - { NORMAL_PRIORITY_CLASS, THREAD_PRIORITY_LOWEST }, - { NORMAL_PRIORITY_CLASS, THREAD_PRIORITY_BELOW_NORMAL }, - { NORMAL_PRIORITY_CLASS, THREAD_PRIORITY_NORMAL }, - { NORMAL_PRIORITY_CLASS, THREAD_PRIORITY_ABOVE_NORMAL }, - { NORMAL_PRIORITY_CLASS, THREAD_PRIORITY_HIGHEST }, - { HIGH_PRIORITY_CLASS, THREAD_PRIORITY_LOWEST }, - { HIGH_PRIORITY_CLASS, THREAD_PRIORITY_BELOW_NORMAL }, - { HIGH_PRIORITY_CLASS, THREAD_PRIORITY_NORMAL }, - { HIGH_PRIORITY_CLASS, THREAD_PRIORITY_ABOVE_NORMAL }, - { HIGH_PRIORITY_CLASS, THREAD_PRIORITY_HIGHEST }, - { REALTIME_PRIORITY_CLASS, THREAD_PRIORITY_IDLE }, - { REALTIME_PRIORITY_CLASS, THREAD_PRIORITY_LOWEST }, - { REALTIME_PRIORITY_CLASS, THREAD_PRIORITY_BELOW_NORMAL }, - { REALTIME_PRIORITY_CLASS, THREAD_PRIORITY_NORMAL }, - { REALTIME_PRIORITY_CLASS, THREAD_PRIORITY_ABOVE_NORMAL }, - { REALTIME_PRIORITY_CLASS, THREAD_PRIORITY_HIGHEST }, - { REALTIME_PRIORITY_CLASS, THREAD_PRIORITY_TIME_CRITICAL} - }; -#if defined(_DEBUG) - // don't use really high priorities when debugging - static const size_t s_pMax = 13; -#else - static const size_t s_pMax = sizeof(s_pClass) / sizeof(s_pClass[0]) - 1; -#endif - static const size_t s_pBase = 8; // index of normal priority - - assert(thread != NULL); - - size_t index; - if (n > 0 && s_pBase < (size_t)n) { - // lowest priority - index = 0; - } - else { - index = (size_t)((int)s_pBase - n); - if (index > s_pMax) { - // highest priority - index = s_pMax; - } - } - SetPriorityClass(GetCurrentProcess(), s_pClass[index].m_class); - SetThreadPriority(thread->m_thread, s_pClass[index].m_level); -} - -void -CArchMultithreadWindows::testCancelThread() -{ - // find current thread - lockMutex(m_threadMutex); - CArchThreadImpl* thread = findNoRef(GetCurrentThreadId()); - unlockMutex(m_threadMutex); - - // test cancel on thread - testCancelThreadImpl(thread); -} - -bool -CArchMultithreadWindows::wait(CArchThread target, double timeout) -{ - assert(target != NULL); - - lockMutex(m_threadMutex); - - // find current thread - CArchThreadImpl* self = findNoRef(GetCurrentThreadId()); - - // ignore wait if trying to wait on ourself - if (target == self) { - unlockMutex(m_threadMutex); - return false; - } - - // ref the target so it can't go away while we're watching it - refThread(target); - - unlockMutex(m_threadMutex); - - // convert timeout - DWORD t; - if (timeout < 0.0) { - t = INFINITE; - } - else { - t = (DWORD)(1000.0 * timeout); - } - - // wait for this thread to be cancelled or woken up or for the - // target thread to terminate. - HANDLE handles[2]; - handles[0] = target->m_exit; - handles[1] = self->m_cancel; - DWORD result = WaitForMultipleObjects(2, handles, FALSE, t); - - // cancel takes priority - if (result != WAIT_OBJECT_0 + 1 && - WaitForSingleObject(handles[1], 0) == WAIT_OBJECT_0) { - result = WAIT_OBJECT_0 + 1; - } - - // release target - closeThread(target); - - // handle result - switch (result) { - case WAIT_OBJECT_0 + 0: - // target thread terminated - return true; - - case WAIT_OBJECT_0 + 1: - // this thread was cancelled. does not return. - testCancelThreadImpl(self); - - default: - // timeout or error - return false; - } -} - -bool -CArchMultithreadWindows::isSameThread(CArchThread thread1, CArchThread thread2) -{ - return (thread1 == thread2); -} - -bool -CArchMultithreadWindows::isExitedThread(CArchThread thread) -{ - // poll exit event - return (WaitForSingleObject(thread->m_exit, 0) == WAIT_OBJECT_0); -} - -void* -CArchMultithreadWindows::getResultOfThread(CArchThread thread) -{ - lockMutex(m_threadMutex); - void* result = thread->m_result; - unlockMutex(m_threadMutex); - return result; -} - -IArchMultithread::ThreadID -CArchMultithreadWindows::getIDOfThread(CArchThread thread) -{ - return static_cast(thread->m_id); -} - -void -CArchMultithreadWindows::setSignalHandler( - ESignal signal, SignalFunc func, void* userData) -{ - lockMutex(m_threadMutex); - m_signalFunc[signal] = func; - m_signalUserData[signal] = userData; - unlockMutex(m_threadMutex); -} - -void -CArchMultithreadWindows::raiseSignal(ESignal signal) -{ - lockMutex(m_threadMutex); - if (m_signalFunc[signal] != NULL) { - m_signalFunc[signal](signal, m_signalUserData[signal]); - ARCH->unblockPollSocket(m_mainThread); - } - else if (signal == kINTERRUPT || signal == kTERMINATE) { - ARCH->cancelThread(m_mainThread); - } - unlockMutex(m_threadMutex); -} - -CArchThreadImpl* -CArchMultithreadWindows::find(DWORD id) -{ - CArchThreadImpl* impl = findNoRef(id); - if (impl != NULL) { - refThread(impl); - } - return impl; -} - -CArchThreadImpl* -CArchMultithreadWindows::findNoRef(DWORD id) -{ - CArchThreadImpl* impl = findNoRefOrCreate(id); - if (impl == NULL) { - // create thread for calling thread which isn't in our list and - // add it to the list. this won't normally happen but it can if - // the system calls us under a new thread, like it does when we - // run as a service. - impl = new CArchThreadImpl; - impl->m_thread = NULL; - impl->m_id = GetCurrentThreadId(); - insert(impl); - } - return impl; -} - -CArchThreadImpl* -CArchMultithreadWindows::findNoRefOrCreate(DWORD id) -{ - // linear search - for (CThreadList::const_iterator index = m_threadList.begin(); - index != m_threadList.end(); ++index) { - if ((*index)->m_id == id) { - return *index; - } - } - return NULL; -} - -void -CArchMultithreadWindows::insert(CArchThreadImpl* thread) -{ - assert(thread != NULL); - - // thread shouldn't already be on the list - assert(findNoRefOrCreate(thread->m_id) == NULL); - - // append to list - m_threadList.push_back(thread); -} - -void -CArchMultithreadWindows::erase(CArchThreadImpl* thread) -{ - for (CThreadList::iterator index = m_threadList.begin(); - index != m_threadList.end(); ++index) { - if (*index == thread) { - m_threadList.erase(index); - break; - } - } -} - -void -CArchMultithreadWindows::refThread(CArchThreadImpl* thread) -{ - assert(thread != NULL); - assert(findNoRefOrCreate(thread->m_id) != NULL); - ++thread->m_refCount; -} - -void -CArchMultithreadWindows::testCancelThreadImpl(CArchThreadImpl* thread) -{ - assert(thread != NULL); - - // poll cancel event. return if not set. - const DWORD result = WaitForSingleObject(thread->m_cancel, 0); - if (result != WAIT_OBJECT_0) { - return; - } - - // update cancel state - lockMutex(m_threadMutex); - bool cancel = !thread->m_cancelling; - thread->m_cancelling = true; - ResetEvent(thread->m_cancel); - unlockMutex(m_threadMutex); - - // unwind thread's stack if cancelling - if (cancel) { - throw XThreadCancel(); - } -} - -unsigned int __stdcall -CArchMultithreadWindows::threadFunc(void* vrep) -{ - // get the thread - CArchThreadImpl* thread = reinterpret_cast(vrep); - - // run thread - s_instance->doThreadFunc(thread); - - // terminate the thread - return 0; -} - -void -CArchMultithreadWindows::doThreadFunc(CArchThread thread) -{ - // wait for parent to initialize this object - lockMutex(m_threadMutex); - unlockMutex(m_threadMutex); - - void* result = NULL; - try { - // go - result = (*thread->m_func)(thread->m_userData); - } - - catch (XThreadCancel&) { - // client called cancel() - } - catch (...) { - // note -- don't catch (...) to avoid masking bugs - SetEvent(thread->m_exit); - closeThread(thread); - throw; - } - - // thread has exited - lockMutex(m_threadMutex); - thread->m_result = result; - unlockMutex(m_threadMutex); - SetEvent(thread->m_exit); - - // done with thread - closeThread(thread); -} diff --git a/lib/arch/CArchMultithreadWindows.h b/lib/arch/CArchMultithreadWindows.h deleted file mode 100644 index d009c842..00000000 --- a/lib/arch/CArchMultithreadWindows.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CARCHMULTITHREADWINDOWS_H -#define CARCHMULTITHREADWINDOWS_H - -#define WIN32_LEAN_AND_MEAN - -#include "IArchMultithread.h" -#include "stdlist.h" -#include - -#define ARCH_MULTITHREAD CArchMultithreadWindows - -class CArchCondImpl { -public: - enum { kSignal = 0, kBroadcast }; - - HANDLE m_events[2]; - mutable int m_waitCount; - CArchMutex m_waitCountMutex; -}; - -class CArchMutexImpl { -public: - CRITICAL_SECTION m_mutex; -}; - -//! Win32 implementation of IArchMultithread -class CArchMultithreadWindows : public IArchMultithread { -public: - CArchMultithreadWindows(); - virtual ~CArchMultithreadWindows(); - - //! @name manipulators - //@{ - - void setNetworkDataForCurrentThread(void*); - - //@} - //! @name accessors - //@{ - - HANDLE getCancelEventForCurrentThread(); - - void* getNetworkDataForThread(CArchThread); - - static CArchMultithreadWindows* getInstance(); - - //@} - - // IArchMultithread overrides - virtual CArchCond newCondVar(); - virtual void closeCondVar(CArchCond); - virtual void signalCondVar(CArchCond); - virtual void broadcastCondVar(CArchCond); - virtual bool waitCondVar(CArchCond, CArchMutex, double timeout); - virtual CArchMutex newMutex(); - virtual void closeMutex(CArchMutex); - virtual void lockMutex(CArchMutex); - virtual void unlockMutex(CArchMutex); - virtual CArchThread newThread(ThreadFunc, void*); - virtual CArchThread newCurrentThread(); - virtual CArchThread copyThread(CArchThread); - virtual void closeThread(CArchThread); - virtual void cancelThread(CArchThread); - virtual void setPriorityOfThread(CArchThread, int n); - virtual void testCancelThread(); - virtual bool wait(CArchThread, double timeout); - virtual bool isSameThread(CArchThread, CArchThread); - virtual bool isExitedThread(CArchThread); - virtual void* getResultOfThread(CArchThread); - virtual ThreadID getIDOfThread(CArchThread); - virtual void setSignalHandler(ESignal, SignalFunc, void*); - virtual void raiseSignal(ESignal); - -private: - CArchThreadImpl* find(DWORD id); - CArchThreadImpl* findNoRef(DWORD id); - CArchThreadImpl* findNoRefOrCreate(DWORD id); - void insert(CArchThreadImpl* thread); - void erase(CArchThreadImpl* thread); - - void refThread(CArchThreadImpl* rep); - void testCancelThreadImpl(CArchThreadImpl* rep); - - void doThreadFunc(CArchThread thread); - static unsigned int __stdcall threadFunc(void* vrep); - -private: - typedef std::list CThreadList; - - static CArchMultithreadWindows* s_instance; - - CArchMutex m_threadMutex; - - CThreadList m_threadList; - CArchThread m_mainThread; - - SignalFunc m_signalFunc[kNUM_SIGNALS]; - void* m_signalUserData[kNUM_SIGNALS]; -}; - -#endif diff --git a/lib/arch/CArchNetworkBSD.cpp b/lib/arch/CArchNetworkBSD.cpp deleted file mode 100644 index af474e86..00000000 --- a/lib/arch/CArchNetworkBSD.cpp +++ /dev/null @@ -1,974 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CArchNetworkBSD.h" -#include "CArch.h" -#include "CArchMultithreadPosix.h" -#include "XArchUnix.h" -#if HAVE_UNISTD_H -# include -#endif -#include -#include -#if !defined(TCP_NODELAY) -# include -#endif -#include -#include -#include -#include - -#if HAVE_POLL -# include -#else -# if HAVE_SYS_SELECT_H -# include -# endif -# if HAVE_SYS_TIME_H -# include -# endif -#endif - -#if !HAVE_INET_ATON -# include -#endif - -static const int s_family[] = { - PF_UNSPEC, - PF_INET -}; -static const int s_type[] = { - SOCK_DGRAM, - SOCK_STREAM -}; - -#if !HAVE_INET_ATON -// parse dotted quad addresses. we don't bother with the weird BSD'ism -// of handling octal and hex and partial forms. -static -in_addr_t -inet_aton(const char* cp, struct in_addr* inp) -{ - unsigned int a, b, c, d; - if (sscanf(cp, "%u.%u.%u.%u", &a, &b, &c, &d) != 4) { - return 0; - } - if (a >= 256 || b >= 256 || c >= 256 || d >= 256) { - return 0; - } - unsigned char* incp = (unsigned char*)inp; - incp[0] = (unsigned char)(a & 0xffu); - incp[1] = (unsigned char)(b & 0xffu); - incp[2] = (unsigned char)(c & 0xffu); - incp[3] = (unsigned char)(d & 0xffu); - return inp->s_addr; -} -#endif - -// -// CArchNetworkBSD -// - -CArchNetworkBSD::CArchNetworkBSD() -{ - // create mutex to make some calls thread safe - m_mutex = ARCH->newMutex(); -} - -CArchNetworkBSD::~CArchNetworkBSD() -{ - ARCH->closeMutex(m_mutex); -} - -CArchSocket -CArchNetworkBSD::newSocket(EAddressFamily family, ESocketType type) -{ - // create socket - int fd = socket(s_family[family], s_type[type], 0); - if (fd == -1) { - throwError(errno); - } - try { - setBlockingOnSocket(fd, false); - } - catch (...) { - close(fd); - throw; - } - - // allocate socket object - CArchSocketImpl* newSocket = new CArchSocketImpl; - newSocket->m_fd = fd; - newSocket->m_refCount = 1; - return newSocket; -} - -CArchSocket -CArchNetworkBSD::copySocket(CArchSocket s) -{ - assert(s != NULL); - - // ref the socket and return it - ARCH->lockMutex(m_mutex); - ++s->m_refCount; - ARCH->unlockMutex(m_mutex); - return s; -} - -void -CArchNetworkBSD::closeSocket(CArchSocket s) -{ - assert(s != NULL); - - // unref the socket and note if it should be released - ARCH->lockMutex(m_mutex); - const bool doClose = (--s->m_refCount == 0); - ARCH->unlockMutex(m_mutex); - - // close the socket if necessary - if (doClose) { - if (close(s->m_fd) == -1) { - // close failed. restore the last ref and throw. - int err = errno; - ARCH->lockMutex(m_mutex); - ++s->m_refCount; - ARCH->unlockMutex(m_mutex); - throwError(err); - } - delete s; - } -} - -void -CArchNetworkBSD::closeSocketForRead(CArchSocket s) -{ - assert(s != NULL); - - if (shutdown(s->m_fd, 0) == -1) { - if (errno != ENOTCONN) { - throwError(errno); - } - } -} - -void -CArchNetworkBSD::closeSocketForWrite(CArchSocket s) -{ - assert(s != NULL); - - if (shutdown(s->m_fd, 1) == -1) { - if (errno != ENOTCONN) { - throwError(errno); - } - } -} - -void -CArchNetworkBSD::bindSocket(CArchSocket s, CArchNetAddress addr) -{ - assert(s != NULL); - assert(addr != NULL); - - if (bind(s->m_fd, &addr->m_addr, addr->m_len) == -1) { - throwError(errno); - } -} - -void -CArchNetworkBSD::listenOnSocket(CArchSocket s) -{ - assert(s != NULL); - - // hardcoding backlog - if (listen(s->m_fd, 3) == -1) { - throwError(errno); - } -} - -CArchSocket -CArchNetworkBSD::acceptSocket(CArchSocket s, CArchNetAddress* addr) -{ - assert(s != NULL); - - // if user passed NULL in addr then use scratch space - CArchNetAddress dummy; - if (addr == NULL) { - addr = &dummy; - } - - // create new socket and address - CArchSocketImpl* newSocket = new CArchSocketImpl; - *addr = new CArchNetAddressImpl; - - // accept on socket - ACCEPT_TYPE_ARG3 len = (ACCEPT_TYPE_ARG3)((*addr)->m_len); - int fd = accept(s->m_fd, &(*addr)->m_addr, &len); - (*addr)->m_len = (socklen_t)len; - if (fd == -1) { - int err = errno; - delete newSocket; - delete *addr; - *addr = NULL; - if (err == EAGAIN) { - return NULL; - } - throwError(err); - } - - try { - setBlockingOnSocket(fd, false); - } - catch (...) { - close(fd); - delete newSocket; - delete *addr; - *addr = NULL; - throw; - } - - // initialize socket - newSocket->m_fd = fd; - newSocket->m_refCount = 1; - - // discard address if not requested - if (addr == &dummy) { - ARCH->closeAddr(dummy); - } - - return newSocket; -} - -bool -CArchNetworkBSD::connectSocket(CArchSocket s, CArchNetAddress addr) -{ - assert(s != NULL); - assert(addr != NULL); - - if (connect(s->m_fd, &addr->m_addr, addr->m_len) == -1) { - if (errno == EISCONN) { - return true; - } - if (errno == EINPROGRESS) { - return false; - } - throwError(errno); - } - return true; -} - -#if HAVE_POLL - -int -CArchNetworkBSD::pollSocket(CPollEntry pe[], int num, double timeout) -{ - assert(pe != NULL || num == 0); - - // return if nothing to do - if (num == 0) { - if (timeout > 0.0) { - ARCH->sleep(timeout); - } - return 0; - } - - // allocate space for translated query - struct pollfd* pfd = new struct pollfd[1 + num]; - - // translate query - for (int i = 0; i < num; ++i) { - pfd[i].fd = (pe[i].m_socket == NULL) ? -1 : pe[i].m_socket->m_fd; - pfd[i].events = 0; - if ((pe[i].m_events & kPOLLIN) != 0) { - pfd[i].events |= POLLIN; - } - if ((pe[i].m_events & kPOLLOUT) != 0) { - pfd[i].events |= POLLOUT; - } - } - int n = num; - - // add the unblock pipe - const int* unblockPipe = getUnblockPipe(); - if (unblockPipe != NULL) { - pfd[n].fd = unblockPipe[0]; - pfd[n].events = POLLIN; - ++n; - } - - // prepare timeout - int t = (timeout < 0.0) ? -1 : static_cast(1000.0 * timeout); - - // do the poll - n = poll(pfd, n, t); - - // reset the unblock pipe - if (n > 0 && unblockPipe != NULL && (pfd[num].revents & POLLIN) != 0) { - // the unblock event was signalled. flush the pipe. - char dummy[100]; - do { - read(unblockPipe[0], dummy, sizeof(dummy)); - } while (errno != EAGAIN); - - // don't count this unblock pipe in return value - --n; - } - - // handle results - if (n == -1) { - if (errno == EINTR) { - // interrupted system call - ARCH->testCancelThread(); - delete[] pfd; - return 0; - } - delete[] pfd; - throwError(errno); - } - - // translate back - for (int i = 0; i < num; ++i) { - pe[i].m_revents = 0; - if ((pfd[i].revents & POLLIN) != 0) { - pe[i].m_revents |= kPOLLIN; - } - if ((pfd[i].revents & POLLOUT) != 0) { - pe[i].m_revents |= kPOLLOUT; - } - if ((pfd[i].revents & POLLERR) != 0) { - pe[i].m_revents |= kPOLLERR; - } - if ((pfd[i].revents & POLLNVAL) != 0) { - pe[i].m_revents |= kPOLLNVAL; - } - } - - delete[] pfd; - return n; -} - -#else - -int -CArchNetworkBSD::pollSocket(CPollEntry pe[], int num, double timeout) -{ - int i, n; - - // prepare sets for select - n = 0; - fd_set readSet, writeSet, errSet; - fd_set* readSetP = NULL; - fd_set* writeSetP = NULL; - fd_set* errSetP = NULL; - FD_ZERO(&readSet); - FD_ZERO(&writeSet); - FD_ZERO(&errSet); - for (i = 0; i < num; ++i) { - // reset return flags - pe[i].m_revents = 0; - - // set invalid flag if socket is bogus then go to next socket - if (pe[i].m_socket == NULL) { - pe[i].m_revents |= kPOLLNVAL; - continue; - } - - int fdi = pe[i].m_socket->m_fd; - if (pe[i].m_events & kPOLLIN) { - FD_SET(pe[i].m_socket->m_fd, &readSet); - readSetP = &readSet; - if (fdi > n) { - n = fdi; - } - } - if (pe[i].m_events & kPOLLOUT) { - FD_SET(pe[i].m_socket->m_fd, &writeSet); - writeSetP = &writeSet; - if (fdi > n) { - n = fdi; - } - } - if (true) { - FD_SET(pe[i].m_socket->m_fd, &errSet); - errSetP = &errSet; - if (fdi > n) { - n = fdi; - } - } - } - - // add the unblock pipe - const int* unblockPipe = getUnblockPipe(); - if (unblockPipe != NULL) { - FD_SET(unblockPipe[0], &readSet); - readSetP = &readSet; - if (unblockPipe[0] > n) { - n = unblockPipe[0]; - } - } - - // if there are no sockets then don't block forever - if (n == 0 && timeout < 0.0) { - timeout = 0.0; - } - - // prepare timeout for select - struct timeval timeout2; - struct timeval* timeout2P; - if (timeout < 0.0) { - timeout2P = NULL; - } - else { - timeout2P = &timeout2; - timeout2.tv_sec = static_cast(timeout); - timeout2.tv_usec = static_cast(1.0e+6 * - (timeout - timeout2.tv_sec)); - } - - // do the select - n = select((SELECT_TYPE_ARG1) n + 1, - SELECT_TYPE_ARG234 readSetP, - SELECT_TYPE_ARG234 writeSetP, - SELECT_TYPE_ARG234 errSetP, - SELECT_TYPE_ARG5 timeout2P); - - // reset the unblock pipe - if (n > 0 && unblockPipe != NULL && FD_ISSET(unblockPipe[0], &readSet)) { - // the unblock event was signalled. flush the pipe. - char dummy[100]; - do { - read(unblockPipe[0], dummy, sizeof(dummy)); - } while (errno != EAGAIN); - } - - // handle results - if (n == -1) { - if (errno == EINTR) { - // interrupted system call - ARCH->testCancelThread(); - return 0; - } - throwError(errno); - } - n = 0; - for (i = 0; i < num; ++i) { - if (pe[i].m_socket != NULL) { - if (FD_ISSET(pe[i].m_socket->m_fd, &readSet)) { - pe[i].m_revents |= kPOLLIN; - } - if (FD_ISSET(pe[i].m_socket->m_fd, &writeSet)) { - pe[i].m_revents |= kPOLLOUT; - } - if (FD_ISSET(pe[i].m_socket->m_fd, &errSet)) { - pe[i].m_revents |= kPOLLERR; - } - } - if (pe[i].m_revents != 0) { - ++n; - } - } - - return n; -} - -#endif - -void -CArchNetworkBSD::unblockPollSocket(CArchThread thread) -{ - const int* unblockPipe = getUnblockPipeForThread(thread); - if (unblockPipe != NULL) { - char dummy = 0; - write(unblockPipe[1], &dummy, 1); - } -} - -size_t -CArchNetworkBSD::readSocket(CArchSocket s, void* buf, size_t len) -{ - assert(s != NULL); - - ssize_t n = read(s->m_fd, buf, len); - if (n == -1) { - if (errno == EINTR || errno == EAGAIN) { - return 0; - } - throwError(errno); - } - return n; -} - -size_t -CArchNetworkBSD::writeSocket(CArchSocket s, const void* buf, size_t len) -{ - assert(s != NULL); - - ssize_t n = write(s->m_fd, buf, len); - if (n == -1) { - if (errno == EINTR || errno == EAGAIN) { - return 0; - } - throwError(errno); - } - return n; -} - -void -CArchNetworkBSD::throwErrorOnSocket(CArchSocket s) -{ - assert(s != NULL); - - // get the error from the socket layer - int err = 0; - socklen_t size = (socklen_t)sizeof(err); - if (getsockopt(s->m_fd, SOL_SOCKET, SO_ERROR, - (optval_t*)&err, &size) == -1) { - err = errno; - } - - // throw if there's an error - if (err != 0) { - throwError(err); - } -} - -void -CArchNetworkBSD::setBlockingOnSocket(int fd, bool blocking) -{ - assert(fd != -1); - - int mode = fcntl(fd, F_GETFL, 0); - if (mode == -1) { - throwError(errno); - } - if (blocking) { - mode &= ~O_NONBLOCK; - } - else { - mode |= O_NONBLOCK; - } - if (fcntl(fd, F_SETFL, mode) == -1) { - throwError(errno); - } -} - -bool -CArchNetworkBSD::setNoDelayOnSocket(CArchSocket s, bool noDelay) -{ - assert(s != NULL); - - // get old state - int oflag; - socklen_t size = (socklen_t)sizeof(oflag); - if (getsockopt(s->m_fd, IPPROTO_TCP, TCP_NODELAY, - (optval_t*)&oflag, &size) == -1) { - throwError(errno); - } - - int flag = noDelay ? 1 : 0; - size = (socklen_t)sizeof(flag); - if (setsockopt(s->m_fd, IPPROTO_TCP, TCP_NODELAY, - (optval_t*)&flag, size) == -1) { - throwError(errno); - } - - return (oflag != 0); -} - -bool -CArchNetworkBSD::setReuseAddrOnSocket(CArchSocket s, bool reuse) -{ - assert(s != NULL); - - // get old state - int oflag; - socklen_t size = (socklen_t)sizeof(oflag); - if (getsockopt(s->m_fd, SOL_SOCKET, SO_REUSEADDR, - (optval_t*)&oflag, &size) == -1) { - throwError(errno); - } - - int flag = reuse ? 1 : 0; - size = (socklen_t)sizeof(flag); - if (setsockopt(s->m_fd, SOL_SOCKET, SO_REUSEADDR, - (optval_t*)&flag, size) == -1) { - throwError(errno); - } - - return (oflag != 0); -} - -std::string -CArchNetworkBSD::getHostName() -{ - char name[256]; - if (gethostname(name, sizeof(name)) == -1) { - name[0] = '\0'; - } - else { - name[sizeof(name) - 1] = '\0'; - } - return name; -} - -CArchNetAddress -CArchNetworkBSD::newAnyAddr(EAddressFamily family) -{ - // allocate address - CArchNetAddressImpl* addr = new CArchNetAddressImpl; - - // fill it in - switch (family) { - case kINET: { - struct sockaddr_in* ipAddr = - reinterpret_cast(&addr->m_addr); - ipAddr->sin_family = AF_INET; - ipAddr->sin_port = 0; - ipAddr->sin_addr.s_addr = INADDR_ANY; - addr->m_len = (socklen_t)sizeof(struct sockaddr_in); - break; - } - - default: - delete addr; - assert(0 && "invalid family"); - } - - return addr; -} - -CArchNetAddress -CArchNetworkBSD::copyAddr(CArchNetAddress addr) -{ - assert(addr != NULL); - - // allocate and copy address - return new CArchNetAddressImpl(*addr); -} - -CArchNetAddress -CArchNetworkBSD::nameToAddr(const std::string& name) -{ - // allocate address - CArchNetAddressImpl* addr = new CArchNetAddressImpl; - - // try to convert assuming an IPv4 dot notation address - struct sockaddr_in inaddr; - memset(&inaddr, 0, sizeof(inaddr)); - if (inet_aton(name.c_str(), &inaddr.sin_addr) != 0) { - // it's a dot notation address - addr->m_len = (socklen_t)sizeof(struct sockaddr_in); - inaddr.sin_family = AF_INET; - inaddr.sin_port = 0; - memcpy(&addr->m_addr, &inaddr, addr->m_len); - } - - else { - // mutexed address lookup (ugh) - ARCH->lockMutex(m_mutex); - struct hostent* info = gethostbyname(name.c_str()); - if (info == NULL) { - ARCH->unlockMutex(m_mutex); - delete addr; - throwNameError(h_errno); - } - - // copy over address (only IPv4 currently supported) - if (info->h_addrtype == AF_INET) { - addr->m_len = (socklen_t)sizeof(struct sockaddr_in); - inaddr.sin_family = info->h_addrtype; - inaddr.sin_port = 0; - memcpy(&inaddr.sin_addr, info->h_addr_list[0], - sizeof(inaddr.sin_addr)); - memcpy(&addr->m_addr, &inaddr, addr->m_len); - } - else { - ARCH->unlockMutex(m_mutex); - delete addr; - throw XArchNetworkNameUnsupported( - "The requested name is valid but " - "does not have a supported address family"); - } - - // done with static buffer - ARCH->unlockMutex(m_mutex); - } - - return addr; -} - -void -CArchNetworkBSD::closeAddr(CArchNetAddress addr) -{ - assert(addr != NULL); - - delete addr; -} - -std::string -CArchNetworkBSD::addrToName(CArchNetAddress addr) -{ - assert(addr != NULL); - - // mutexed name lookup (ugh) - ARCH->lockMutex(m_mutex); - struct hostent* info = gethostbyaddr( - reinterpret_cast(&addr->m_addr), - addr->m_len, addr->m_addr.sa_family); - if (info == NULL) { - ARCH->unlockMutex(m_mutex); - throwNameError(h_errno); - } - - // save (primary) name - std::string name = info->h_name; - - // done with static buffer - ARCH->unlockMutex(m_mutex); - - return name; -} - -std::string -CArchNetworkBSD::addrToString(CArchNetAddress addr) -{ - assert(addr != NULL); - - switch (getAddrFamily(addr)) { - case kINET: { - struct sockaddr_in* ipAddr = - reinterpret_cast(&addr->m_addr); - ARCH->lockMutex(m_mutex); - std::string s = inet_ntoa(ipAddr->sin_addr); - ARCH->unlockMutex(m_mutex); - return s; - } - - default: - assert(0 && "unknown address family"); - return ""; - } -} - -IArchNetwork::EAddressFamily -CArchNetworkBSD::getAddrFamily(CArchNetAddress addr) -{ - assert(addr != NULL); - - switch (addr->m_addr.sa_family) { - case AF_INET: - return kINET; - - default: - return kUNKNOWN; - } -} - -void -CArchNetworkBSD::setAddrPort(CArchNetAddress addr, int port) -{ - assert(addr != NULL); - - switch (getAddrFamily(addr)) { - case kINET: { - struct sockaddr_in* ipAddr = - reinterpret_cast(&addr->m_addr); - ipAddr->sin_port = htons(port); - break; - } - - default: - assert(0 && "unknown address family"); - break; - } -} - -int -CArchNetworkBSD::getAddrPort(CArchNetAddress addr) -{ - assert(addr != NULL); - - switch (getAddrFamily(addr)) { - case kINET: { - struct sockaddr_in* ipAddr = - reinterpret_cast(&addr->m_addr); - return ntohs(ipAddr->sin_port); - } - - default: - assert(0 && "unknown address family"); - return 0; - } -} - -bool -CArchNetworkBSD::isAnyAddr(CArchNetAddress addr) -{ - assert(addr != NULL); - - switch (getAddrFamily(addr)) { - case kINET: { - struct sockaddr_in* ipAddr = - reinterpret_cast(&addr->m_addr); - return (ipAddr->sin_addr.s_addr == INADDR_ANY && - addr->m_len == (socklen_t)sizeof(struct sockaddr_in)); - } - - default: - assert(0 && "unknown address family"); - return true; - } -} - -bool -CArchNetworkBSD::isEqualAddr(CArchNetAddress a, CArchNetAddress b) -{ - return (a->m_len == b->m_len && - memcmp(&a->m_addr, &b->m_addr, a->m_len) == 0); -} - -const int* -CArchNetworkBSD::getUnblockPipe() -{ - CArchMultithreadPosix* mt = CArchMultithreadPosix::getInstance(); - CArchThread thread = mt->newCurrentThread(); - const int* p = getUnblockPipeForThread(thread); - ARCH->closeThread(thread); - return p; -} - -const int* -CArchNetworkBSD::getUnblockPipeForThread(CArchThread thread) -{ - CArchMultithreadPosix* mt = CArchMultithreadPosix::getInstance(); - int* unblockPipe = (int*)mt->getNetworkDataForThread(thread); - if (unblockPipe == NULL) { - unblockPipe = new int[2]; - if (pipe(unblockPipe) != -1) { - try { - setBlockingOnSocket(unblockPipe[0], false); - mt->setNetworkDataForCurrentThread(unblockPipe); - } - catch (...) { - delete[] unblockPipe; - unblockPipe = NULL; - } - } - else { - delete[] unblockPipe; - unblockPipe = NULL; - } - } - return unblockPipe; -} - -void -CArchNetworkBSD::throwError(int err) -{ - switch (err) { - case EINTR: - ARCH->testCancelThread(); - throw XArchNetworkInterrupted(new XArchEvalUnix(err)); - - case EACCES: - case EPERM: - throw XArchNetworkAccess(new XArchEvalUnix(err)); - - case ENFILE: - case EMFILE: - case ENODEV: - case ENOBUFS: - case ENOMEM: - case ENETDOWN: -#if defined(ENOSR) - case ENOSR: -#endif - throw XArchNetworkResource(new XArchEvalUnix(err)); - - case EPROTOTYPE: - case EPROTONOSUPPORT: - case EAFNOSUPPORT: - case EPFNOSUPPORT: - case ESOCKTNOSUPPORT: - case EINVAL: - case ENOPROTOOPT: - case EOPNOTSUPP: - case ESHUTDOWN: -#if defined(ENOPKG) - case ENOPKG: -#endif - throw XArchNetworkSupport(new XArchEvalUnix(err)); - - case EIO: - throw XArchNetworkIO(new XArchEvalUnix(err)); - - case EADDRNOTAVAIL: - throw XArchNetworkNoAddress(new XArchEvalUnix(err)); - - case EADDRINUSE: - throw XArchNetworkAddressInUse(new XArchEvalUnix(err)); - - case EHOSTUNREACH: - case ENETUNREACH: - throw XArchNetworkNoRoute(new XArchEvalUnix(err)); - - case ENOTCONN: - throw XArchNetworkNotConnected(new XArchEvalUnix(err)); - - case EPIPE: - throw XArchNetworkShutdown(new XArchEvalUnix(err)); - - case ECONNABORTED: - case ECONNRESET: - throw XArchNetworkDisconnected(new XArchEvalUnix(err)); - - case ECONNREFUSED: - throw XArchNetworkConnectionRefused(new XArchEvalUnix(err)); - - case EHOSTDOWN: - case ETIMEDOUT: - throw XArchNetworkTimedOut(new XArchEvalUnix(err)); - - default: - throw XArchNetwork(new XArchEvalUnix(err)); - } -} - -void -CArchNetworkBSD::throwNameError(int err) -{ - static const char* s_msg[] = { - "The specified host is unknown", - "The requested name is valid but does not have an IP address", - "A non-recoverable name server error occurred", - "A temporary error occurred on an authoritative name server", - "An unknown name server error occurred" - }; - - switch (err) { - case HOST_NOT_FOUND: - throw XArchNetworkNameUnknown(s_msg[0]); - - case NO_DATA: - throw XArchNetworkNameNoAddress(s_msg[1]); - - case NO_RECOVERY: - throw XArchNetworkNameFailure(s_msg[2]); - - case TRY_AGAIN: - throw XArchNetworkNameUnavailable(s_msg[3]); - - default: - throw XArchNetworkName(s_msg[4]); - } -} diff --git a/lib/arch/CArchNetworkBSD.h b/lib/arch/CArchNetworkBSD.h deleted file mode 100644 index bba60272..00000000 --- a/lib/arch/CArchNetworkBSD.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CARCHNETWORKBSD_H -#define CARCHNETWORKBSD_H - -#include "IArchNetwork.h" -#include "IArchMultithread.h" -#if HAVE_SYS_TYPES_H -# include -#endif -#if HAVE_SYS_SOCKET_H -# include -#endif - -#if !HAVE_SOCKLEN_T -typedef int socklen_t; -#endif - -// old systems may use char* for [gs]etsockopt()'s optval argument. -// this should be void on modern systems but char is forwards -// compatible so we always use it. -typedef char optval_t; - -#define ARCH_NETWORK CArchNetworkBSD - -class CArchSocketImpl { -public: - int m_fd; - int m_refCount; -}; - -class CArchNetAddressImpl { -public: - CArchNetAddressImpl() : m_len(sizeof(m_addr)) { } - -public: - struct sockaddr m_addr; - socklen_t m_len; -}; - -//! Berkeley (BSD) sockets implementation of IArchNetwork -class CArchNetworkBSD : public IArchNetwork { -public: - CArchNetworkBSD(); - virtual ~CArchNetworkBSD(); - - // IArchNetwork overrides - virtual CArchSocket newSocket(EAddressFamily, ESocketType); - virtual CArchSocket copySocket(CArchSocket s); - virtual void closeSocket(CArchSocket s); - virtual void closeSocketForRead(CArchSocket s); - virtual void closeSocketForWrite(CArchSocket s); - virtual void bindSocket(CArchSocket s, CArchNetAddress addr); - virtual void listenOnSocket(CArchSocket s); - virtual CArchSocket acceptSocket(CArchSocket s, CArchNetAddress* addr); - virtual bool connectSocket(CArchSocket s, CArchNetAddress name); - virtual int pollSocket(CPollEntry[], int num, double timeout); - virtual void unblockPollSocket(CArchThread thread); - virtual size_t readSocket(CArchSocket s, void* buf, size_t len); - virtual size_t writeSocket(CArchSocket s, - const void* buf, size_t len); - virtual void throwErrorOnSocket(CArchSocket); - virtual bool setNoDelayOnSocket(CArchSocket, bool noDelay); - virtual bool setReuseAddrOnSocket(CArchSocket, bool reuse); - virtual std::string getHostName(); - virtual CArchNetAddress newAnyAddr(EAddressFamily); - virtual CArchNetAddress copyAddr(CArchNetAddress); - virtual CArchNetAddress nameToAddr(const std::string&); - virtual void closeAddr(CArchNetAddress); - virtual std::string addrToName(CArchNetAddress); - virtual std::string addrToString(CArchNetAddress); - virtual EAddressFamily getAddrFamily(CArchNetAddress); - virtual void setAddrPort(CArchNetAddress, int port); - virtual int getAddrPort(CArchNetAddress); - virtual bool isAnyAddr(CArchNetAddress); - virtual bool isEqualAddr(CArchNetAddress, CArchNetAddress); - -private: - const int* getUnblockPipe(); - const int* getUnblockPipeForThread(CArchThread); - void setBlockingOnSocket(int fd, bool blocking); - void throwError(int); - void throwNameError(int); - -private: - CArchMutex m_mutex; -}; - -#endif diff --git a/lib/arch/CArchNetworkWinsock.cpp b/lib/arch/CArchNetworkWinsock.cpp deleted file mode 100644 index ac40596a..00000000 --- a/lib/arch/CArchNetworkWinsock.cpp +++ /dev/null @@ -1,934 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - - -#include "CArchNetworkWinsock.h" -#include "CArch.h" -#include "CArchMultithreadWindows.h" -#include "IArchMultithread.h" -#include "XArchWindows.h" -#include - -static const int s_family[] = { - PF_UNSPEC, - PF_INET -}; -static const int s_type[] = { - SOCK_DGRAM, - SOCK_STREAM -}; - -static SOCKET (PASCAL FAR *accept_winsock)(SOCKET s, struct sockaddr FAR *addr, int FAR *addrlen); -static int (PASCAL FAR *bind_winsock)(SOCKET s, const struct sockaddr FAR *addr, int namelen); -static int (PASCAL FAR *close_winsock)(SOCKET s); -static int (PASCAL FAR *connect_winsock)(SOCKET s, const struct sockaddr FAR *name, int namelen); -static int (PASCAL FAR *gethostname_winsock)(char FAR * name, int namelen); -static int (PASCAL FAR *getsockerror_winsock)(void); -static int (PASCAL FAR *getsockopt_winsock)(SOCKET s, int level, int optname, void FAR * optval, int FAR *optlen); -static u_short (PASCAL FAR *htons_winsock)(u_short v); -static char FAR * (PASCAL FAR *inet_ntoa_winsock)(struct in_addr in); -static unsigned long (PASCAL FAR *inet_addr_winsock)(const char FAR * cp); -static int (PASCAL FAR *ioctl_winsock)(SOCKET s, int cmd, void FAR * data); -static int (PASCAL FAR *listen_winsock)(SOCKET s, int backlog); -static u_short (PASCAL FAR *ntohs_winsock)(u_short v); -static int (PASCAL FAR *recv_winsock)(SOCKET s, void FAR * buf, int len, int flags); -static int (PASCAL FAR *select_winsock)(int nfds, fd_set FAR *readfds, fd_set FAR *writefds, fd_set FAR *exceptfds, const struct timeval FAR *timeout); -static int (PASCAL FAR *send_winsock)(SOCKET s, const void FAR * buf, int len, int flags); -static int (PASCAL FAR *setsockopt_winsock)(SOCKET s, int level, int optname, const void FAR * optval, int optlen); -static int (PASCAL FAR *shutdown_winsock)(SOCKET s, int how); -static SOCKET (PASCAL FAR *socket_winsock)(int af, int type, int protocol); -static struct hostent FAR * (PASCAL FAR *gethostbyaddr_winsock)(const char FAR * addr, int len, int type); -static struct hostent FAR * (PASCAL FAR *gethostbyname_winsock)(const char FAR * name); -static int (PASCAL FAR *WSACleanup_winsock)(void); -static int (PASCAL FAR *WSAFDIsSet_winsock)(SOCKET, fd_set FAR * fdset); -static WSAEVENT (PASCAL FAR *WSACreateEvent_winsock)(void); -static BOOL (PASCAL FAR *WSACloseEvent_winsock)(WSAEVENT); -static BOOL (PASCAL FAR *WSASetEvent_winsock)(WSAEVENT); -static BOOL (PASCAL FAR *WSAResetEvent_winsock)(WSAEVENT); -static int (PASCAL FAR *WSAEventSelect_winsock)(SOCKET, WSAEVENT, long); -static DWORD (PASCAL FAR *WSAWaitForMultipleEvents_winsock)(DWORD, const WSAEVENT FAR*, BOOL, DWORD, BOOL); -static int (PASCAL FAR *WSAEnumNetworkEvents_winsock)(SOCKET, WSAEVENT, LPWSANETWORKEVENTS); - -#undef FD_ISSET -#define FD_ISSET(fd, set) WSAFDIsSet_winsock((SOCKET)(fd), (fd_set FAR *)(set)) - -#define setfunc(var, name, type) var = (type)netGetProcAddress(module, #name) - -static HMODULE s_networkModule = NULL; - -static -FARPROC -netGetProcAddress(HMODULE module, LPCSTR name) -{ - FARPROC func = ::GetProcAddress(module, name); - if (!func) { - throw XArchNetworkSupport(""); - } - return func; -} - -CArchNetAddressImpl* -CArchNetAddressImpl::alloc(size_t size) -{ - size_t totalSize = size + ADDR_HDR_SIZE; - CArchNetAddressImpl* addr = (CArchNetAddressImpl*)malloc(totalSize); - addr->m_len = size; - return addr; -} - - -// -// CArchNetworkWinsock -// - -CArchNetworkWinsock::CArchNetworkWinsock() -{ - static const char* s_library[] = { "ws2_32.dll" }; - - assert(WSACleanup_winsock == NULL); - assert(s_networkModule == NULL); - - // try each winsock library - for (size_t i = 0; i < sizeof(s_library) / sizeof(s_library[0]); ++i) { - try { - init((HMODULE)::LoadLibrary(s_library[i])); - m_mutex = ARCH->newMutex(); - return; - } - catch (XArchNetwork&) { - // ignore - } - } - - // can't initialize any library - throw XArchNetworkSupport("Cannot load winsock library"); -} - -CArchNetworkWinsock::~CArchNetworkWinsock() -{ - if (s_networkModule != NULL) { - WSACleanup_winsock(); - ::FreeLibrary(s_networkModule); - - WSACleanup_winsock = NULL; - s_networkModule = NULL; - } - ARCH->closeMutex(m_mutex); -} - -void -CArchNetworkWinsock::init(HMODULE module) -{ - if (module == NULL) { - throw XArchNetworkSupport(""); - } - - // get startup function address - int (PASCAL FAR *startup)(WORD, LPWSADATA); - setfunc(startup, WSAStartup, int(PASCAL FAR*)(WORD, LPWSADATA)); - - // startup network library - WORD version = MAKEWORD(2 /*major*/, 0 /*minor*/); - WSADATA data; - int err = startup(version, &data); - if (data.wVersion != version) { - throw XArchNetworkSupport(new XArchEvalWinsock(err)); - } - if (err != 0) { - // some other initialization error - throwError(err); - } - - // get function addresses - setfunc(accept_winsock, accept, SOCKET (PASCAL FAR *)(SOCKET s, struct sockaddr FAR *addr, int FAR *addrlen)); - setfunc(bind_winsock, bind, int (PASCAL FAR *)(SOCKET s, const struct sockaddr FAR *addr, int namelen)); - setfunc(close_winsock, closesocket, int (PASCAL FAR *)(SOCKET s)); - setfunc(connect_winsock, connect, int (PASCAL FAR *)(SOCKET s, const struct sockaddr FAR *name, int namelen)); - setfunc(gethostname_winsock, gethostname, int (PASCAL FAR *)(char FAR * name, int namelen)); - setfunc(getsockerror_winsock, WSAGetLastError, int (PASCAL FAR *)(void)); - setfunc(getsockopt_winsock, getsockopt, int (PASCAL FAR *)(SOCKET s, int level, int optname, void FAR * optval, int FAR *optlen)); - setfunc(htons_winsock, htons, u_short (PASCAL FAR *)(u_short v)); - setfunc(inet_ntoa_winsock, inet_ntoa, char FAR * (PASCAL FAR *)(struct in_addr in)); - setfunc(inet_addr_winsock, inet_addr, unsigned long (PASCAL FAR *)(const char FAR * cp)); - setfunc(ioctl_winsock, ioctlsocket, int (PASCAL FAR *)(SOCKET s, int cmd, void FAR *)); - setfunc(listen_winsock, listen, int (PASCAL FAR *)(SOCKET s, int backlog)); - setfunc(ntohs_winsock, ntohs, u_short (PASCAL FAR *)(u_short v)); - setfunc(recv_winsock, recv, int (PASCAL FAR *)(SOCKET s, void FAR * buf, int len, int flags)); - setfunc(select_winsock, select, int (PASCAL FAR *)(int nfds, fd_set FAR *readfds, fd_set FAR *writefds, fd_set FAR *exceptfds, const struct timeval FAR *timeout)); - setfunc(send_winsock, send, int (PASCAL FAR *)(SOCKET s, const void FAR * buf, int len, int flags)); - setfunc(setsockopt_winsock, setsockopt, int (PASCAL FAR *)(SOCKET s, int level, int optname, const void FAR * optval, int optlen)); - setfunc(shutdown_winsock, shutdown, int (PASCAL FAR *)(SOCKET s, int how)); - setfunc(socket_winsock, socket, SOCKET (PASCAL FAR *)(int af, int type, int protocol)); - setfunc(gethostbyaddr_winsock, gethostbyaddr, struct hostent FAR * (PASCAL FAR *)(const char FAR * addr, int len, int type)); - setfunc(gethostbyname_winsock, gethostbyname, struct hostent FAR * (PASCAL FAR *)(const char FAR * name)); - setfunc(WSACleanup_winsock, WSACleanup, int (PASCAL FAR *)(void)); - setfunc(WSAFDIsSet_winsock, __WSAFDIsSet, int (PASCAL FAR *)(SOCKET, fd_set FAR *)); - setfunc(WSACreateEvent_winsock, WSACreateEvent, WSAEVENT (PASCAL FAR *)(void)); - setfunc(WSACloseEvent_winsock, WSACloseEvent, BOOL (PASCAL FAR *)(WSAEVENT)); - setfunc(WSASetEvent_winsock, WSASetEvent, BOOL (PASCAL FAR *)(WSAEVENT)); - setfunc(WSAResetEvent_winsock, WSAResetEvent, BOOL (PASCAL FAR *)(WSAEVENT)); - setfunc(WSAEventSelect_winsock, WSAEventSelect, int (PASCAL FAR *)(SOCKET, WSAEVENT, long)); - setfunc(WSAWaitForMultipleEvents_winsock, WSAWaitForMultipleEvents, DWORD (PASCAL FAR *)(DWORD, const WSAEVENT FAR*, BOOL, DWORD, BOOL)); - setfunc(WSAEnumNetworkEvents_winsock, WSAEnumNetworkEvents, int (PASCAL FAR *)(SOCKET, WSAEVENT, LPWSANETWORKEVENTS)); - - s_networkModule = module; -} - -CArchSocket -CArchNetworkWinsock::newSocket(EAddressFamily family, ESocketType type) -{ - // create socket - SOCKET fd = socket_winsock(s_family[family], s_type[type], 0); - if (fd == INVALID_SOCKET) { - throwError(getsockerror_winsock()); - } - try { - setBlockingOnSocket(fd, false); - } - catch (...) { - close_winsock(fd); - throw; - } - - // allocate socket object - CArchSocketImpl* socket = new CArchSocketImpl; - socket->m_socket = fd; - socket->m_refCount = 1; - socket->m_event = WSACreateEvent_winsock(); - socket->m_pollWrite = true; - return socket; -} - -CArchSocket -CArchNetworkWinsock::copySocket(CArchSocket s) -{ - assert(s != NULL); - - // ref the socket and return it - ARCH->lockMutex(m_mutex); - ++s->m_refCount; - ARCH->unlockMutex(m_mutex); - return s; -} - -void -CArchNetworkWinsock::closeSocket(CArchSocket s) -{ - assert(s != NULL); - - // unref the socket and note if it should be released - ARCH->lockMutex(m_mutex); - const bool doClose = (--s->m_refCount == 0); - ARCH->unlockMutex(m_mutex); - - // close the socket if necessary - if (doClose) { - if (close_winsock(s->m_socket) == SOCKET_ERROR) { - // close failed. restore the last ref and throw. - int err = getsockerror_winsock(); - ARCH->lockMutex(m_mutex); - ++s->m_refCount; - ARCH->unlockMutex(m_mutex); - throwError(err); - } - WSACloseEvent_winsock(s->m_event); - delete s; - } -} - -void -CArchNetworkWinsock::closeSocketForRead(CArchSocket s) -{ - assert(s != NULL); - - if (shutdown_winsock(s->m_socket, SD_RECEIVE) == SOCKET_ERROR) { - if (getsockerror_winsock() != WSAENOTCONN) { - throwError(getsockerror_winsock()); - } - } -} - -void -CArchNetworkWinsock::closeSocketForWrite(CArchSocket s) -{ - assert(s != NULL); - - if (shutdown_winsock(s->m_socket, SD_SEND) == SOCKET_ERROR) { - if (getsockerror_winsock() != WSAENOTCONN) { - throwError(getsockerror_winsock()); - } - } -} - -void -CArchNetworkWinsock::bindSocket(CArchSocket s, CArchNetAddress addr) -{ - assert(s != NULL); - assert(addr != NULL); - - if (bind_winsock(s->m_socket, &addr->m_addr, addr->m_len) == SOCKET_ERROR) { - throwError(getsockerror_winsock()); - } -} - -void -CArchNetworkWinsock::listenOnSocket(CArchSocket s) -{ - assert(s != NULL); - - // hardcoding backlog - if (listen_winsock(s->m_socket, 3) == SOCKET_ERROR) { - throwError(getsockerror_winsock()); - } -} - -CArchSocket -CArchNetworkWinsock::acceptSocket(CArchSocket s, CArchNetAddress* addr) -{ - assert(s != NULL); - - // create new socket and temporary address - CArchSocketImpl* socket = new CArchSocketImpl; - CArchNetAddress tmp = CArchNetAddressImpl::alloc(sizeof(struct sockaddr)); - - // accept on socket - SOCKET fd = accept_winsock(s->m_socket, &tmp->m_addr, &tmp->m_len); - if (fd == INVALID_SOCKET) { - int err = getsockerror_winsock(); - delete socket; - free(tmp); - *addr = NULL; - if (err == WSAEWOULDBLOCK) { - return NULL; - } - throwError(err); - } - - try { - setBlockingOnSocket(fd, false); - } - catch (...) { - close_winsock(fd); - delete socket; - free(tmp); - *addr = NULL; - throw; - } - - // initialize socket - socket->m_socket = fd; - socket->m_refCount = 1; - socket->m_event = WSACreateEvent_winsock(); - socket->m_pollWrite = true; - - // copy address if requested - if (addr != NULL) { - *addr = ARCH->copyAddr(tmp); - } - - free(tmp); - return socket; -} - -bool -CArchNetworkWinsock::connectSocket(CArchSocket s, CArchNetAddress addr) -{ - assert(s != NULL); - assert(addr != NULL); - - if (connect_winsock(s->m_socket, &addr->m_addr, - addr->m_len) == SOCKET_ERROR) { - if (getsockerror_winsock() == WSAEISCONN) { - return true; - } - if (getsockerror_winsock() == WSAEWOULDBLOCK) { - return false; - } - throwError(getsockerror_winsock()); - } - return true; -} - -int -CArchNetworkWinsock::pollSocket(CPollEntry pe[], int num, double timeout) -{ - int i; - DWORD n; - - // prepare sockets and wait list - bool canWrite = false; - WSAEVENT* events = (WSAEVENT*)alloca((num + 1) * sizeof(WSAEVENT)); - for (i = 0, n = 0; i < num; ++i) { - // reset return flags - pe[i].m_revents = 0; - - // set invalid flag if socket is bogus then go to next socket - if (pe[i].m_socket == NULL) { - pe[i].m_revents |= kPOLLNVAL; - continue; - } - - // select desired events - long socketEvents = 0; - if ((pe[i].m_events & kPOLLIN) != 0) { - socketEvents |= FD_READ | FD_ACCEPT | FD_CLOSE; - } - if ((pe[i].m_events & kPOLLOUT) != 0) { - socketEvents |= FD_WRITE | FD_CONNECT | FD_CLOSE; - - // if m_pollWrite is false then we assume the socket is - // writable. winsock doesn't signal writability except - // when the state changes from unwritable. - if (!pe[i].m_socket->m_pollWrite) { - canWrite = true; - pe[i].m_revents |= kPOLLOUT; - } - } - - // if no events then ignore socket - if (socketEvents == 0) { - continue; - } - - // select socket for desired events - WSAEventSelect_winsock(pe[i].m_socket->m_socket, - pe[i].m_socket->m_event, socketEvents); - - // add socket event to wait list - events[n++] = pe[i].m_socket->m_event; - } - - // if no sockets then return immediately - if (n == 0) { - return 0; - } - - // add the unblock event - CArchMultithreadWindows* mt = CArchMultithreadWindows::getInstance(); - CArchThread thread = mt->newCurrentThread(); - WSAEVENT* unblockEvent = (WSAEVENT*)mt->getNetworkDataForThread(thread); - ARCH->closeThread(thread); - if (unblockEvent == NULL) { - unblockEvent = new WSAEVENT; - *unblockEvent = WSACreateEvent_winsock(); - mt->setNetworkDataForCurrentThread(unblockEvent); - } - events[n++] = *unblockEvent; - - // prepare timeout - DWORD t = (timeout < 0.0) ? INFINITE : (DWORD)(1000.0 * timeout); - if (canWrite) { - // if we know we can write then don't block - t = 0; - } - - // wait - DWORD result = WSAWaitForMultipleEvents_winsock(n, events, FALSE, t, FALSE); - - // reset the unblock event - WSAResetEvent_winsock(*unblockEvent); - - // handle results - if (result == WSA_WAIT_FAILED) { - if (getsockerror_winsock() == WSAEINTR) { - // interrupted system call - ARCH->testCancelThread(); - return 0; - } - throwError(getsockerror_winsock()); - } - if (result == WSA_WAIT_TIMEOUT && !canWrite) { - return 0; - } - if (result == WSA_WAIT_EVENT_0 + n - 1) { - // the unblock event was signalled - return 0; - } - for (i = 0, n = 0; i < num; ++i) { - // skip events we didn't check - if (pe[i].m_socket == NULL || - (pe[i].m_events & (kPOLLIN | kPOLLOUT)) == 0) { - continue; - } - - // get events - WSANETWORKEVENTS info; - if (WSAEnumNetworkEvents_winsock(pe[i].m_socket->m_socket, - pe[i].m_socket->m_event, &info) == SOCKET_ERROR) { - continue; - } - if ((info.lNetworkEvents & FD_READ) != 0) { - pe[i].m_revents |= kPOLLIN; - } - if ((info.lNetworkEvents & FD_ACCEPT) != 0) { - pe[i].m_revents |= kPOLLIN; - } - if ((info.lNetworkEvents & FD_WRITE) != 0) { - pe[i].m_revents |= kPOLLOUT; - - // socket is now writable so don't bothing polling for - // writable until it becomes unwritable. - pe[i].m_socket->m_pollWrite = false; - } - if ((info.lNetworkEvents & FD_CONNECT) != 0) { - if (info.iErrorCode[FD_CONNECT_BIT] != 0) { - pe[i].m_revents |= kPOLLERR; - } - else { - pe[i].m_revents |= kPOLLOUT; - pe[i].m_socket->m_pollWrite = false; - } - } - if ((info.lNetworkEvents & FD_CLOSE) != 0) { - if (info.iErrorCode[FD_CLOSE_BIT] != 0) { - pe[i].m_revents |= kPOLLERR; - } - else { - if ((pe[i].m_events & kPOLLIN) != 0) { - pe[i].m_revents |= kPOLLIN; - } - if ((pe[i].m_events & kPOLLOUT) != 0) { - pe[i].m_revents |= kPOLLOUT; - } - } - } - if (pe[i].m_revents != 0) { - ++n; - } - } - - return (int)n; -} - -void -CArchNetworkWinsock::unblockPollSocket(CArchThread thread) -{ - // set the unblock event - CArchMultithreadWindows* mt = CArchMultithreadWindows::getInstance(); - WSAEVENT* unblockEvent = (WSAEVENT*)mt->getNetworkDataForThread(thread); - if (unblockEvent != NULL) { - WSASetEvent_winsock(*unblockEvent); - } -} - -size_t -CArchNetworkWinsock::readSocket(CArchSocket s, void* buf, size_t len) -{ - assert(s != NULL); - - int n = recv_winsock(s->m_socket, buf, len, 0); - if (n == SOCKET_ERROR) { - int err = getsockerror_winsock(); - if (err == WSAEINTR || err == WSAEWOULDBLOCK) { - return 0; - } - throwError(err); - } - return static_cast(n); -} - -size_t -CArchNetworkWinsock::writeSocket(CArchSocket s, const void* buf, size_t len) -{ - assert(s != NULL); - - int n = send_winsock(s->m_socket, buf, len, 0); - if (n == SOCKET_ERROR) { - int err = getsockerror_winsock(); - if (err == WSAEINTR) { - return 0; - } - if (err == WSAEWOULDBLOCK) { - s->m_pollWrite = true; - return 0; - } - throwError(err); - } - return static_cast(n); -} - -void -CArchNetworkWinsock::throwErrorOnSocket(CArchSocket s) -{ - assert(s != NULL); - - // get the error from the socket layer - int err = 0; - int size = sizeof(err); - if (getsockopt_winsock(s->m_socket, SOL_SOCKET, - SO_ERROR, &err, &size) == SOCKET_ERROR) { - err = getsockerror_winsock(); - } - - // throw if there's an error - if (err != 0) { - throwError(err); - } -} - -void -CArchNetworkWinsock::setBlockingOnSocket(SOCKET s, bool blocking) -{ - assert(s != 0); - - int flag = blocking ? 0 : 1; - if (ioctl_winsock(s, FIONBIO, &flag) == SOCKET_ERROR) { - throwError(getsockerror_winsock()); - } -} - -bool -CArchNetworkWinsock::setNoDelayOnSocket(CArchSocket s, bool noDelay) -{ - assert(s != NULL); - - // get old state - BOOL oflag; - int size = sizeof(oflag); - if (getsockopt_winsock(s->m_socket, IPPROTO_TCP, - TCP_NODELAY, &oflag, &size) == SOCKET_ERROR) { - throwError(getsockerror_winsock()); - } - - // set new state - BOOL flag = noDelay ? 1 : 0; - size = sizeof(flag); - if (setsockopt_winsock(s->m_socket, IPPROTO_TCP, - TCP_NODELAY, &flag, size) == SOCKET_ERROR) { - throwError(getsockerror_winsock()); - } - - return (oflag != 0); -} - -bool -CArchNetworkWinsock::setReuseAddrOnSocket(CArchSocket s, bool reuse) -{ - assert(s != NULL); - - // get old state - BOOL oflag; - int size = sizeof(oflag); - if (getsockopt_winsock(s->m_socket, SOL_SOCKET, - SO_REUSEADDR, &oflag, &size) == SOCKET_ERROR) { - throwError(getsockerror_winsock()); - } - - // set new state - BOOL flag = reuse ? 1 : 0; - size = sizeof(flag); - if (setsockopt_winsock(s->m_socket, SOL_SOCKET, - SO_REUSEADDR, &flag, size) == SOCKET_ERROR) { - throwError(getsockerror_winsock()); - } - - return (oflag != 0); -} - -std::string -CArchNetworkWinsock::getHostName() -{ - char name[256]; - if (gethostname_winsock(name, sizeof(name)) == -1) { - name[0] = '\0'; - } - else { - name[sizeof(name) - 1] = '\0'; - } - return name; -} - -CArchNetAddress -CArchNetworkWinsock::newAnyAddr(EAddressFamily family) -{ - CArchNetAddressImpl* addr = NULL; - switch (family) { - case kINET: { - addr = CArchNetAddressImpl::alloc(sizeof(struct sockaddr_in)); - struct sockaddr_in* ipAddr = TYPED_ADDR(struct sockaddr_in, addr); - ipAddr->sin_family = AF_INET; - ipAddr->sin_port = 0; - ipAddr->sin_addr.s_addr = INADDR_ANY; - break; - } - - default: - assert(0 && "invalid family"); - } - return addr; -} - -CArchNetAddress -CArchNetworkWinsock::copyAddr(CArchNetAddress addr) -{ - assert(addr != NULL); - - CArchNetAddressImpl* copy = CArchNetAddressImpl::alloc(addr->m_len); - memcpy(TYPED_ADDR(void, copy), TYPED_ADDR(void, addr), addr->m_len); - return copy; -} - -CArchNetAddress -CArchNetworkWinsock::nameToAddr(const std::string& name) -{ - // allocate address - CArchNetAddressImpl* addr = NULL; - - // try to convert assuming an IPv4 dot notation address - struct sockaddr_in inaddr; - memset(&inaddr, 0, sizeof(inaddr)); - inaddr.sin_family = AF_INET; - inaddr.sin_port = 0; - inaddr.sin_addr.s_addr = inet_addr_winsock(name.c_str()); - if (inaddr.sin_addr.s_addr != INADDR_NONE) { - // it's a dot notation address - addr = CArchNetAddressImpl::alloc(sizeof(struct sockaddr_in)); - memcpy(TYPED_ADDR(void, addr), &inaddr, addr->m_len); - } - - else { - // address lookup - struct hostent* info = gethostbyname_winsock(name.c_str()); - if (info == NULL) { - throwNameError(getsockerror_winsock()); - } - - // copy over address (only IPv4 currently supported) - if (info->h_addrtype == AF_INET) { - addr = CArchNetAddressImpl::alloc(sizeof(struct sockaddr_in)); - memcpy(&inaddr.sin_addr, info->h_addr_list[0], - sizeof(inaddr.sin_addr)); - memcpy(TYPED_ADDR(void, addr), &inaddr, addr->m_len); - } - else { - throw XArchNetworkNameUnsupported( - "The requested name is valid but " - "does not have a supported address family"); - } - } - - return addr; -} - -void -CArchNetworkWinsock::closeAddr(CArchNetAddress addr) -{ - assert(addr != NULL); - - free(addr); -} - -std::string -CArchNetworkWinsock::addrToName(CArchNetAddress addr) -{ - assert(addr != NULL); - - // name lookup - struct hostent* info = gethostbyaddr_winsock( - reinterpret_cast(&addr->m_addr), - addr->m_len, addr->m_addr.sa_family); - if (info == NULL) { - throwNameError(getsockerror_winsock()); - } - - // return (primary) name - return info->h_name; -} - -std::string -CArchNetworkWinsock::addrToString(CArchNetAddress addr) -{ - assert(addr != NULL); - - switch (getAddrFamily(addr)) { - case kINET: { - struct sockaddr_in* ipAddr = - reinterpret_cast(&addr->m_addr); - return inet_ntoa_winsock(ipAddr->sin_addr); - } - - default: - assert(0 && "unknown address family"); - return ""; - } -} - -IArchNetwork::EAddressFamily -CArchNetworkWinsock::getAddrFamily(CArchNetAddress addr) -{ - assert(addr != NULL); - - switch (addr->m_addr.sa_family) { - case AF_INET: - return kINET; - - default: - return kUNKNOWN; - } -} - -void -CArchNetworkWinsock::setAddrPort(CArchNetAddress addr, int port) -{ - assert(addr != NULL); - - switch (getAddrFamily(addr)) { - case kINET: { - struct sockaddr_in* ipAddr = - reinterpret_cast(&addr->m_addr); - ipAddr->sin_port = htons_winsock(static_cast(port)); - break; - } - - default: - assert(0 && "unknown address family"); - break; - } -} - -int -CArchNetworkWinsock::getAddrPort(CArchNetAddress addr) -{ - assert(addr != NULL); - - switch (getAddrFamily(addr)) { - case kINET: { - struct sockaddr_in* ipAddr = - reinterpret_cast(&addr->m_addr); - return ntohs_winsock(ipAddr->sin_port); - } - - default: - assert(0 && "unknown address family"); - return 0; - } -} - -bool -CArchNetworkWinsock::isAnyAddr(CArchNetAddress addr) -{ - assert(addr != NULL); - - switch (getAddrFamily(addr)) { - case kINET: { - struct sockaddr_in* ipAddr = - reinterpret_cast(&addr->m_addr); - return (addr->m_len == sizeof(struct sockaddr_in) && - ipAddr->sin_addr.s_addr == INADDR_ANY); - } - - default: - assert(0 && "unknown address family"); - return true; - } -} - -bool -CArchNetworkWinsock::isEqualAddr(CArchNetAddress a, CArchNetAddress b) -{ - return (a == b || (a->m_len == b->m_len && - memcmp(&a->m_addr, &b->m_addr, a->m_len) == 0)); -} - -void -CArchNetworkWinsock::throwError(int err) -{ - switch (err) { - case WSAEACCES: - throw XArchNetworkAccess(new XArchEvalWinsock(err)); - - case WSAEMFILE: - case WSAENOBUFS: - case WSAENETDOWN: - throw XArchNetworkResource(new XArchEvalWinsock(err)); - - case WSAEPROTOTYPE: - case WSAEPROTONOSUPPORT: - case WSAEAFNOSUPPORT: - case WSAEPFNOSUPPORT: - case WSAESOCKTNOSUPPORT: - case WSAEINVAL: - case WSAENOPROTOOPT: - case WSAEOPNOTSUPP: - case WSAESHUTDOWN: - case WSANOTINITIALISED: - case WSAVERNOTSUPPORTED: - case WSASYSNOTREADY: - throw XArchNetworkSupport(new XArchEvalWinsock(err)); - - case WSAEADDRNOTAVAIL: - throw XArchNetworkNoAddress(new XArchEvalWinsock(err)); - - case WSAEADDRINUSE: - throw XArchNetworkAddressInUse(new XArchEvalWinsock(err)); - - case WSAEHOSTUNREACH: - case WSAENETUNREACH: - throw XArchNetworkNoRoute(new XArchEvalWinsock(err)); - - case WSAENOTCONN: - throw XArchNetworkNotConnected(new XArchEvalWinsock(err)); - - case WSAEDISCON: - throw XArchNetworkShutdown(new XArchEvalWinsock(err)); - - case WSAENETRESET: - case WSAECONNABORTED: - case WSAECONNRESET: - throw XArchNetworkDisconnected(new XArchEvalWinsock(err)); - - case WSAECONNREFUSED: - throw XArchNetworkConnectionRefused(new XArchEvalWinsock(err)); - - case WSAEHOSTDOWN: - case WSAETIMEDOUT: - throw XArchNetworkTimedOut(new XArchEvalWinsock(err)); - - case WSAHOST_NOT_FOUND: - throw XArchNetworkNameUnknown(new XArchEvalWinsock(err)); - - case WSANO_DATA: - throw XArchNetworkNameNoAddress(new XArchEvalWinsock(err)); - - case WSANO_RECOVERY: - throw XArchNetworkNameFailure(new XArchEvalWinsock(err)); - - case WSATRY_AGAIN: - throw XArchNetworkNameUnavailable(new XArchEvalWinsock(err)); - - default: - throw XArchNetwork(new XArchEvalWinsock(err)); - } -} - -void -CArchNetworkWinsock::throwNameError(int err) -{ - switch (err) { - case WSAHOST_NOT_FOUND: - throw XArchNetworkNameUnknown(new XArchEvalWinsock(err)); - - case WSANO_DATA: - throw XArchNetworkNameNoAddress(new XArchEvalWinsock(err)); - - case WSANO_RECOVERY: - throw XArchNetworkNameFailure(new XArchEvalWinsock(err)); - - case WSATRY_AGAIN: - throw XArchNetworkNameUnavailable(new XArchEvalWinsock(err)); - - default: - throw XArchNetworkName(new XArchEvalWinsock(err)); - } -} diff --git a/lib/arch/CArchNetworkWinsock.h b/lib/arch/CArchNetworkWinsock.h deleted file mode 100644 index 3912ba5b..00000000 --- a/lib/arch/CArchNetworkWinsock.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CARCHNETWORKWINSOCK_H -#define CARCHNETWORKWINSOCK_H - -#define WIN32_LEAN_AND_MEAN - -// declare no functions in winsock2 -#define INCL_WINSOCK_API_PROTOTYPES 0 -#define INCL_WINSOCK_API_TYPEDEFS 0 - -#include "IArchNetwork.h" -#include "IArchMultithread.h" -#include -#include - -#define ARCH_NETWORK CArchNetworkWinsock - -class CArchSocketImpl { -public: - SOCKET m_socket; - int m_refCount; - WSAEVENT m_event; - bool m_pollWrite; -}; - -class CArchNetAddressImpl { -public: - static CArchNetAddressImpl* alloc(size_t); - -public: - int m_len; - struct sockaddr m_addr; -}; -#define ADDR_HDR_SIZE offsetof(CArchNetAddressImpl, m_addr) -#define TYPED_ADDR(type_, addr_) (reinterpret_cast(&addr_->m_addr)) - -//! Win32 implementation of IArchNetwork -class CArchNetworkWinsock : public IArchNetwork { -public: - CArchNetworkWinsock(); - virtual ~CArchNetworkWinsock(); - - // IArchNetwork overrides - virtual CArchSocket newSocket(EAddressFamily, ESocketType); - virtual CArchSocket copySocket(CArchSocket s); - virtual void closeSocket(CArchSocket s); - virtual void closeSocketForRead(CArchSocket s); - virtual void closeSocketForWrite(CArchSocket s); - virtual void bindSocket(CArchSocket s, CArchNetAddress addr); - virtual void listenOnSocket(CArchSocket s); - virtual CArchSocket acceptSocket(CArchSocket s, CArchNetAddress* addr); - virtual bool connectSocket(CArchSocket s, CArchNetAddress name); - virtual int pollSocket(CPollEntry[], int num, double timeout); - virtual void unblockPollSocket(CArchThread thread); - virtual size_t readSocket(CArchSocket s, void* buf, size_t len); - virtual size_t writeSocket(CArchSocket s, - const void* buf, size_t len); - virtual void throwErrorOnSocket(CArchSocket); - virtual bool setNoDelayOnSocket(CArchSocket, bool noDelay); - virtual bool setReuseAddrOnSocket(CArchSocket, bool reuse); - virtual std::string getHostName(); - virtual CArchNetAddress newAnyAddr(EAddressFamily); - virtual CArchNetAddress copyAddr(CArchNetAddress); - virtual CArchNetAddress nameToAddr(const std::string&); - virtual void closeAddr(CArchNetAddress); - virtual std::string addrToName(CArchNetAddress); - virtual std::string addrToString(CArchNetAddress); - virtual EAddressFamily getAddrFamily(CArchNetAddress); - virtual void setAddrPort(CArchNetAddress, int port); - virtual int getAddrPort(CArchNetAddress); - virtual bool isAnyAddr(CArchNetAddress); - virtual bool isEqualAddr(CArchNetAddress, CArchNetAddress); - -private: - void init(HMODULE); - - void setBlockingOnSocket(SOCKET, bool blocking); - - void throwError(int); - void throwNameError(int); - -private: - CArchMutex m_mutex; -}; - -#endif diff --git a/lib/arch/CArchSleepUnix.cpp b/lib/arch/CArchSleepUnix.cpp deleted file mode 100644 index 35010721..00000000 --- a/lib/arch/CArchSleepUnix.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CArchSleepUnix.h" -#include "CArch.h" -#if TIME_WITH_SYS_TIME -# include -# include -#else -# if HAVE_SYS_TIME_H -# include -# else -# include -# endif -#endif -#if !HAVE_NANOSLEEP -# if HAVE_SYS_SELECT_H -# include -# endif -# if HAVE_SYS_TYPES_H -# include -# endif -# if HAVE_UNISTD_H -# include -# endif -#endif - -// -// CArchSleepUnix -// - -CArchSleepUnix::CArchSleepUnix() -{ - // do nothing -} - -CArchSleepUnix::~CArchSleepUnix() -{ - // do nothing -} - -void -CArchSleepUnix::sleep(double timeout) -{ - ARCH->testCancelThread(); - if (timeout < 0.0) { - return; - } - -#if HAVE_NANOSLEEP - // prep timeout - struct timespec t; - t.tv_sec = (long)timeout; - t.tv_nsec = (long)(1.0e+9 * (timeout - (double)t.tv_sec)); - - // wait - while (nanosleep(&t, &t) < 0) - ARCH->testCancelThread(); -#else - /* emulate nanosleep() with select() */ - double startTime = ARCH->time(); - double timeLeft = timeout; - while (timeLeft > 0.0) { - struct timeval timeout2; - timeout2.tv_sec = static_cast(timeLeft); - timeout2.tv_usec = static_cast(1.0e+6 * (timeLeft - - timeout2.tv_sec)); - select((SELECT_TYPE_ARG1) 0, - SELECT_TYPE_ARG234 NULL, - SELECT_TYPE_ARG234 NULL, - SELECT_TYPE_ARG234 NULL, - SELECT_TYPE_ARG5 &timeout2); - ARCH->testCancelThread(); - timeLeft = timeout - (ARCH->time() - startTime); - } -#endif -} diff --git a/lib/arch/CArchSleepUnix.h b/lib/arch/CArchSleepUnix.h deleted file mode 100644 index 939ca401..00000000 --- a/lib/arch/CArchSleepUnix.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CARCHSLEEPUNIX_H -#define CARCHSLEEPUNIX_H - -#include "IArchSleep.h" - -#define ARCH_SLEEP CArchSleepUnix - -//! Unix implementation of IArchSleep -class CArchSleepUnix : public IArchSleep { -public: - CArchSleepUnix(); - virtual ~CArchSleepUnix(); - - // IArchSleep overrides - virtual void sleep(double timeout); -}; - -#endif diff --git a/lib/arch/CArchSleepWindows.cpp b/lib/arch/CArchSleepWindows.cpp deleted file mode 100644 index f6c8bed8..00000000 --- a/lib/arch/CArchSleepWindows.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CArchSleepWindows.h" -#include "CArch.h" -#include "CArchMultithreadWindows.h" - -// -// CArchSleepWindows -// - -CArchSleepWindows::CArchSleepWindows() -{ - // do nothing -} - -CArchSleepWindows::~CArchSleepWindows() -{ - // do nothing -} - -void -CArchSleepWindows::sleep(double timeout) -{ - ARCH->testCancelThread(); - if (timeout < 0.0) { - return; - } - - // get the cancel event from the current thread. this only - // works if we're using the windows multithread object but - // this is windows so that's pretty certain; we'll get a - // link error if we're not, though. - CArchMultithreadWindows* mt = CArchMultithreadWindows::getInstance(); - if (mt != NULL) { - HANDLE cancelEvent = mt->getCancelEventForCurrentThread(); - WaitForSingleObject(cancelEvent, (DWORD)(1000.0 * timeout)); - if (timeout == 0.0) { - Sleep(0); - } - } - else { - Sleep((DWORD)(1000.0 * timeout)); - } - ARCH->testCancelThread(); -} diff --git a/lib/arch/CArchSleepWindows.h b/lib/arch/CArchSleepWindows.h deleted file mode 100644 index a5a5fa90..00000000 --- a/lib/arch/CArchSleepWindows.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CARCHSLEEPWINDOWS_H -#define CARCHSLEEPWINDOWS_H - -#include "IArchSleep.h" - -#define ARCH_SLEEP CArchSleepWindows - -//! Win32 implementation of IArchSleep -class CArchSleepWindows : public IArchSleep { -public: - CArchSleepWindows(); - virtual ~CArchSleepWindows(); - - // IArchSleep overrides - virtual void sleep(double timeout); -}; - -#endif diff --git a/lib/arch/CArchStringUnix.cpp b/lib/arch/CArchStringUnix.cpp deleted file mode 100644 index e0ad3457..00000000 --- a/lib/arch/CArchStringUnix.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CArchStringUnix.h" -#include - -// -// CArchStringUnix -// - -#include "CMultibyte.cpp" -#include "vsnprintf.cpp" - -IArchString::EWideCharEncoding -CArchStringUnix::getWideCharEncoding() -{ - return kUCS4; -} diff --git a/lib/arch/CArchStringUnix.h b/lib/arch/CArchStringUnix.h deleted file mode 100644 index 20e5486b..00000000 --- a/lib/arch/CArchStringUnix.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CARCHSTRINGUNIX_H -#define CARCHSTRINGUNIX_H - -#include "IArchString.h" - -#define ARCH_STRING CArchStringUnix - -//! Unix implementation of IArchString -class CArchStringUnix : public IArchString { -public: - CArchStringUnix(); - virtual ~CArchStringUnix(); - - // IArchString overrides - virtual int vsnprintf(char* str, - int size, const char* fmt, va_list ap); - virtual int convStringMBToWC(wchar_t*, - const char*, UInt32 n, bool* errors); - virtual int convStringWCToMB(char*, - const wchar_t*, UInt32 n, bool* errors); - virtual EWideCharEncoding - getWideCharEncoding(); -}; - -#endif diff --git a/lib/arch/CArchStringWindows.cpp b/lib/arch/CArchStringWindows.cpp deleted file mode 100644 index a3b90765..00000000 --- a/lib/arch/CArchStringWindows.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#define WIN32_LEAN_AND_MEAN - -#include "CArchStringWindows.h" -#include -#include - -// -// CArchStringWindows -// - -#include "CMultibyte.cpp" -#define HAVE_VSNPRINTF 1 -#define ARCH_VSNPRINTF _vsnprintf -#include "vsnprintf.cpp" - -IArchString::EWideCharEncoding -CArchStringWindows::getWideCharEncoding() -{ - return kUTF16; -} diff --git a/lib/arch/CArchStringWindows.h b/lib/arch/CArchStringWindows.h deleted file mode 100644 index a67d8431..00000000 --- a/lib/arch/CArchStringWindows.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CARCHSTRINGWINDOWS_H -#define CARCHSTRINGWINDOWS_H - -#include "IArchString.h" - -#define ARCH_STRING CArchStringWindows - -//! Win32 implementation of IArchString -class CArchStringWindows : public IArchString { -public: - CArchStringWindows(); - virtual ~CArchStringWindows(); - - // IArchString overrides - virtual int vsnprintf(char* str, - int size, const char* fmt, va_list ap); - virtual int convStringMBToWC(wchar_t*, - const char*, UInt32 n, bool* errors); - virtual int convStringWCToMB(char*, - const wchar_t*, UInt32 n, bool* errors); - virtual EWideCharEncoding - getWideCharEncoding(); -}; - -#endif diff --git a/lib/arch/CArchSystemUnix.cpp b/lib/arch/CArchSystemUnix.cpp deleted file mode 100644 index 541038db..00000000 --- a/lib/arch/CArchSystemUnix.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CArchSystemUnix.h" -#include - -// -// CArchSystemUnix -// - -CArchSystemUnix::CArchSystemUnix() -{ - // do nothing -} - -CArchSystemUnix::~CArchSystemUnix() -{ - // do nothing -} - -std::string -CArchSystemUnix::getOSName() const -{ -#if defined(HAVE_SYS_UTSNAME_H) - struct utsname info; - if (uname(&info) == 0) { - std::string msg; - msg += info.sysname; - msg += " "; - msg += info.release; - msg += " "; - msg += info.version; - msg += " "; - msg += info.machine; - return msg; - } -#endif - return "Unix "; -} diff --git a/lib/arch/CArchSystemUnix.h b/lib/arch/CArchSystemUnix.h deleted file mode 100644 index 525aed1c..00000000 --- a/lib/arch/CArchSystemUnix.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CARCHSYSTEMUNIX_H -#define CARCHSYSTEMUNIX_H - -#include "IArchSystem.h" - -#define ARCH_SYSTEM CArchSystemUnix - -//! Unix implementation of IArchString -class CArchSystemUnix : public IArchSystem { -public: - CArchSystemUnix(); - virtual ~CArchSystemUnix(); - - // IArchSystem overrides - virtual std::string getOSName() const; -}; - -#endif diff --git a/lib/arch/CArchSystemWindows.cpp b/lib/arch/CArchSystemWindows.cpp deleted file mode 100644 index b634b4bc..00000000 --- a/lib/arch/CArchSystemWindows.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#define WIN32_LEAN_AND_MEAN - -#include "CArchSystemWindows.h" -#include - -// -// CArchSystemWindows -// - -CArchSystemWindows::CArchSystemWindows() -{ - // do nothing -} - -CArchSystemWindows::~CArchSystemWindows() -{ - // do nothing -} - -std::string -CArchSystemWindows::getOSName() const -{ - OSVERSIONINFO info; - info.dwOSVersionInfoSize = sizeof(info); - if (GetVersionEx(&info)) { - switch (info.dwPlatformId) { - case VER_PLATFORM_WIN32_NT: - if (info.dwMajorVersion == 5 && info.dwMinorVersion == 2) { - return "Microsoft Windows Server 2003"; - } - if (info.dwMajorVersion == 5 && info.dwMinorVersion == 1) { - return "Microsoft Windows Server XP"; - } - if (info.dwMajorVersion == 5 && info.dwMinorVersion == 0) { - return "Microsoft Windows Server 2000"; - } - if (info.dwMajorVersion <= 4) { - return "Microsoft Windows NT"; - } - char buffer[100]; - sprintf(buffer, "Microsoft Windows %d.%d", - info.dwMajorVersion, info.dwMinorVersion); - return buffer; - - case VER_PLATFORM_WIN32_WINDOWS: - if (info.dwMajorVersion == 4 && info.dwMinorVersion == 0) { - if (info.szCSDVersion[1] == 'C' || - info.szCSDVersion[1] == 'B') { - return "Microsoft Windows 95 OSR2"; - } - return "Microsoft Windows 95"; - } - if (info.dwMajorVersion == 4 && info.dwMinorVersion == 10) { - if (info.szCSDVersion[1] == 'A') { - return "Microsoft Windows 98 SE"; - } - return "Microsoft Windows 98"; - } - if (info.dwMajorVersion == 4 && info.dwMinorVersion == 90) { - return "Microsoft Windows ME"; - } - if (info.dwMajorVersion == 4) { - return "Microsoft Windows unknown 95 family"; - } - break; - - default: - break; - } - } - return "Microsoft Windows "; -} diff --git a/lib/arch/CArchSystemWindows.h b/lib/arch/CArchSystemWindows.h deleted file mode 100644 index e23913d0..00000000 --- a/lib/arch/CArchSystemWindows.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CARCHSYSTEMWINDOWS_H -#define CARCHSYSTEMWINDOWS_H - -#include "IArchSystem.h" - -#define ARCH_SYSTEM CArchSystemWindows - -//! Win32 implementation of IArchString -class CArchSystemWindows : public IArchSystem { -public: - CArchSystemWindows(); - virtual ~CArchSystemWindows(); - - // IArchSystem overrides - virtual std::string getOSName() const; -}; - -#endif diff --git a/lib/arch/CArchTaskBarWindows.cpp b/lib/arch/CArchTaskBarWindows.cpp deleted file mode 100644 index 29c57b66..00000000 --- a/lib/arch/CArchTaskBarWindows.cpp +++ /dev/null @@ -1,492 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CArchTaskBarWindows.h" -#include "CArchMiscWindows.h" -#include "IArchTaskBarReceiver.h" -#include "CArch.h" -#include "XArch.h" -#include -#include - -static const UINT kAddReceiver = WM_USER + 10; -static const UINT kRemoveReceiver = WM_USER + 11; -static const UINT kUpdateReceiver = WM_USER + 12; -static const UINT kNotifyReceiver = WM_USER + 13; -static const UINT kFirstReceiverID = WM_USER + 14; - -// -// CArchTaskBarWindows -// - -CArchTaskBarWindows* CArchTaskBarWindows::s_instance = NULL; -HINSTANCE CArchTaskBarWindows::s_appInstance = NULL; - -CArchTaskBarWindows::CArchTaskBarWindows(void* appInstance) : - m_nextID(kFirstReceiverID) -{ - // save the singleton instance - s_instance = this; - - // save app instance - s_appInstance = reinterpret_cast(appInstance); - - // we need a mutex - m_mutex = ARCH->newMutex(); - - // and a condition variable which uses the above mutex - m_ready = false; - m_condVar = ARCH->newCondVar(); - - // we're going to want to get a result from the thread we're - // about to create to know if it initialized successfully. - // so we lock the condition variable. - ARCH->lockMutex(m_mutex); - - // open a window and run an event loop in a separate thread. - // this has to happen in a separate thread because if we - // create a window on the current desktop with the current - // thread then the current thread won't be able to switch - // desktops if it needs to. - m_thread = ARCH->newThread(&CArchTaskBarWindows::threadEntry, this); - - // wait for child thread - while (!m_ready) { - ARCH->waitCondVar(m_condVar, m_mutex, -1.0); - } - - // ready - ARCH->unlockMutex(m_mutex); -} - -CArchTaskBarWindows::~CArchTaskBarWindows() -{ - if (m_thread != NULL) { - PostMessage(m_hwnd, WM_QUIT, 0, 0); - ARCH->wait(m_thread, -1.0); - ARCH->closeThread(m_thread); - } - ARCH->closeCondVar(m_condVar); - ARCH->closeMutex(m_mutex); - s_instance = NULL; -} - -void -CArchTaskBarWindows::addDialog(HWND hwnd) -{ - CArchMiscWindows::addDialog(hwnd); -} - -void -CArchTaskBarWindows::removeDialog(HWND hwnd) -{ - CArchMiscWindows::removeDialog(hwnd); -} - -void -CArchTaskBarWindows::addReceiver(IArchTaskBarReceiver* receiver) -{ - // ignore bogus receiver - if (receiver == NULL) { - return; - } - - // add receiver if necessary - CReceiverToInfoMap::iterator index = m_receivers.find(receiver); - if (index == m_receivers.end()) { - // add it, creating a new message ID for it - CReceiverInfo info; - info.m_id = getNextID(); - index = m_receivers.insert(std::make_pair(receiver, info)).first; - - // add ID to receiver mapping - m_idTable.insert(std::make_pair(info.m_id, index)); - } - - // add receiver - PostMessage(m_hwnd, kAddReceiver, index->second.m_id, 0); -} - -void -CArchTaskBarWindows::removeReceiver(IArchTaskBarReceiver* receiver) -{ - // find receiver - CReceiverToInfoMap::iterator index = m_receivers.find(receiver); - if (index == m_receivers.end()) { - return; - } - - // remove icon. wait for this to finish before returning. - SendMessage(m_hwnd, kRemoveReceiver, index->second.m_id, 0); - - // recycle the ID - recycleID(index->second.m_id); - - // discard - m_idTable.erase(index->second.m_id); - m_receivers.erase(index); -} - -void -CArchTaskBarWindows::updateReceiver(IArchTaskBarReceiver* receiver) -{ - // find receiver - CReceiverToInfoMap::const_iterator index = m_receivers.find(receiver); - if (index == m_receivers.end()) { - return; - } - - // update icon and tool tip - PostMessage(m_hwnd, kUpdateReceiver, index->second.m_id, 0); -} - -UINT -CArchTaskBarWindows::getNextID() -{ - if (m_oldIDs.empty()) { - return m_nextID++; - } - UINT id = m_oldIDs.back(); - m_oldIDs.pop_back(); - return id; -} - -void -CArchTaskBarWindows::recycleID(UINT id) -{ - m_oldIDs.push_back(id); -} - -void -CArchTaskBarWindows::addIcon(UINT id) -{ - ARCH->lockMutex(m_mutex); - CIDToReceiverMap::const_iterator index = m_idTable.find(id); - if (index != m_idTable.end()) { - modifyIconNoLock(index->second, NIM_ADD); - } - ARCH->unlockMutex(m_mutex); -} - -void -CArchTaskBarWindows::removeIcon(UINT id) -{ - ARCH->lockMutex(m_mutex); - removeIconNoLock(id); - ARCH->unlockMutex(m_mutex); -} - -void -CArchTaskBarWindows::updateIcon(UINT id) -{ - ARCH->lockMutex(m_mutex); - CIDToReceiverMap::const_iterator index = m_idTable.find(id); - if (index != m_idTable.end()) { - modifyIconNoLock(index->second, NIM_MODIFY); - } - ARCH->unlockMutex(m_mutex); -} - -void -CArchTaskBarWindows::addAllIcons() -{ - ARCH->lockMutex(m_mutex); - for (CReceiverToInfoMap::const_iterator index = m_receivers.begin(); - index != m_receivers.end(); ++index) { - modifyIconNoLock(index, NIM_ADD); - } - ARCH->unlockMutex(m_mutex); -} - -void -CArchTaskBarWindows::removeAllIcons() -{ - ARCH->lockMutex(m_mutex); - for (CReceiverToInfoMap::const_iterator index = m_receivers.begin(); - index != m_receivers.end(); ++index) { - removeIconNoLock(index->second.m_id); - } - ARCH->unlockMutex(m_mutex); -} - -void -CArchTaskBarWindows::modifyIconNoLock( - CReceiverToInfoMap::const_iterator index, DWORD taskBarMessage) -{ - // get receiver - UINT id = index->second.m_id; - IArchTaskBarReceiver* receiver = index->first; - - // lock receiver so icon and tool tip are guaranteed to be consistent - receiver->lock(); - - // get icon data - HICON icon = reinterpret_cast( - const_cast(receiver->getIcon())); - - // get tool tip - std::string toolTip = receiver->getToolTip(); - - // done querying - receiver->unlock(); - - // prepare to add icon - NOTIFYICONDATA data; - data.cbSize = sizeof(NOTIFYICONDATA); - data.hWnd = m_hwnd; - data.uID = id; - data.uFlags = NIF_MESSAGE; - data.uCallbackMessage = kNotifyReceiver; - data.hIcon = icon; - if (icon != NULL) { - data.uFlags |= NIF_ICON; - } - if (!toolTip.empty()) { - strncpy(data.szTip, toolTip.c_str(), sizeof(data.szTip)); - data.szTip[sizeof(data.szTip) - 1] = '\0'; - data.uFlags |= NIF_TIP; - } - else { - data.szTip[0] = '\0'; - } - - // add icon - if (Shell_NotifyIcon(taskBarMessage, &data) == 0) { - // failed - } -} - -void -CArchTaskBarWindows::removeIconNoLock(UINT id) -{ - NOTIFYICONDATA data; - data.cbSize = sizeof(NOTIFYICONDATA); - data.hWnd = m_hwnd; - data.uID = id; - if (Shell_NotifyIcon(NIM_DELETE, &data) == 0) { - // failed - } -} - -void -CArchTaskBarWindows::handleIconMessage( - IArchTaskBarReceiver* receiver, LPARAM lParam) -{ - // process message - switch (lParam) { - case WM_LBUTTONDOWN: - receiver->showStatus(); - break; - - case WM_LBUTTONDBLCLK: - receiver->primaryAction(); - break; - - case WM_RBUTTONUP: { - POINT p; - GetCursorPos(&p); - receiver->runMenu(p.x, p.y); - break; - } - - case WM_MOUSEMOVE: - // currently unused - break; - - default: - // unused - break; - } -} - -bool -CArchTaskBarWindows::processDialogs(MSG* msg) -{ - // only one thread can be in this method on any particular object - // at any given time. that's not a problem since only our event - // loop calls this method and there's just one of those. - - ARCH->lockMutex(m_mutex); - - // remove removed dialogs - m_dialogs.erase(false); - - // merge added dialogs into the dialog list - for (CDialogs::const_iterator index = m_addedDialogs.begin(); - index != m_addedDialogs.end(); ++index) { - m_dialogs.insert(std::make_pair(index->first, index->second)); - } - m_addedDialogs.clear(); - - ARCH->unlockMutex(m_mutex); - - // check message against all dialogs until one handles it. - // note that we don't hold a lock while checking because - // the message is processed and may make calls to this - // object. that's okay because addDialog() and - // removeDialog() don't change the map itself (just the - // values of some elements). - ARCH->lockMutex(m_mutex); - for (CDialogs::const_iterator index = m_dialogs.begin(); - index != m_dialogs.end(); ++index) { - if (index->second) { - ARCH->unlockMutex(m_mutex); - if (IsDialogMessage(index->first, msg)) { - return true; - } - ARCH->lockMutex(m_mutex); - } - } - ARCH->unlockMutex(m_mutex); - - return false; -} - -LRESULT -CArchTaskBarWindows::wndProc(HWND hwnd, - UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) { - case kNotifyReceiver: { - // lookup receiver - CIDToReceiverMap::const_iterator index = m_idTable.find(wParam); - if (index != m_idTable.end()) { - IArchTaskBarReceiver* receiver = index->second->first; - handleIconMessage(receiver, lParam); - return 0; - } - break; - } - - case kAddReceiver: - addIcon(wParam); - break; - - case kRemoveReceiver: - removeIcon(wParam); - break; - - case kUpdateReceiver: - updateIcon(wParam); - break; - - default: - if (msg == m_taskBarRestart) { - // task bar was recreated so re-add our icons - addAllIcons(); - } - break; - } - - return DefWindowProc(hwnd, msg, wParam, lParam); -} - -LRESULT CALLBACK -CArchTaskBarWindows::staticWndProc(HWND hwnd, UINT msg, - WPARAM wParam, LPARAM lParam) -{ - // if msg is WM_NCCREATE, extract the CArchTaskBarWindows* and put - // it in the extra window data then forward the call. - CArchTaskBarWindows* self = NULL; - if (msg == WM_NCCREATE) { - CREATESTRUCT* createInfo; - createInfo = reinterpret_cast(lParam); - self = reinterpret_cast( - createInfo->lpCreateParams); - SetWindowLong(hwnd, 0, reinterpret_cast(self)); - } - else { - // get the extra window data and forward the call - LONG data = GetWindowLong(hwnd, 0); - if (data != 0) { - self = reinterpret_cast( - reinterpret_cast(data)); - } - } - - // forward the message - if (self != NULL) { - return self->wndProc(hwnd, msg, wParam, lParam); - } - else { - return DefWindowProc(hwnd, msg, wParam, lParam); - } -} - -void -CArchTaskBarWindows::threadMainLoop() -{ - // register the task bar restart message - m_taskBarRestart = RegisterWindowMessage(TEXT("TaskbarCreated")); - - // register a window class - WNDCLASSEX classInfo; - classInfo.cbSize = sizeof(classInfo); - classInfo.style = CS_NOCLOSE; - classInfo.lpfnWndProc = &CArchTaskBarWindows::staticWndProc; - classInfo.cbClsExtra = 0; - classInfo.cbWndExtra = sizeof(CArchTaskBarWindows*); - classInfo.hInstance = s_appInstance; - classInfo.hIcon = NULL; - classInfo.hCursor = NULL; - classInfo.hbrBackground = NULL; - classInfo.lpszMenuName = NULL; - classInfo.lpszClassName = TEXT("SynergyTaskBar"); - classInfo.hIconSm = NULL; - ATOM windowClass = RegisterClassEx(&classInfo); - - // create window - m_hwnd = CreateWindowEx(WS_EX_TOOLWINDOW, - reinterpret_cast(windowClass), - TEXT("Synergy Task Bar"), - WS_POPUP, - 0, 0, 1, 1, - NULL, - NULL, - s_appInstance, - reinterpret_cast(this)); - - // signal ready - ARCH->lockMutex(m_mutex); - m_ready = true; - ARCH->broadcastCondVar(m_condVar); - ARCH->unlockMutex(m_mutex); - - // handle failure - if (m_hwnd == NULL) { - UnregisterClass(reinterpret_cast(windowClass), s_appInstance); - return; - } - - // main loop - MSG msg; - while (GetMessage(&msg, NULL, 0, 0)) { - if (!processDialogs(&msg)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } - - // clean up - removeAllIcons(); - DestroyWindow(m_hwnd); - UnregisterClass(reinterpret_cast(windowClass), s_appInstance); -} - -void* -CArchTaskBarWindows::threadEntry(void* self) -{ - reinterpret_cast(self)->threadMainLoop(); - return NULL; -} diff --git a/lib/arch/CArchTaskBarWindows.h b/lib/arch/CArchTaskBarWindows.h deleted file mode 100644 index 67e9af17..00000000 --- a/lib/arch/CArchTaskBarWindows.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CARCHTASKBARWINDOWS_H -#define CARCHTASKBARWINDOWS_H - -#define WIN32_LEAN_AND_MEAN - -#include "IArchTaskBar.h" -#include "IArchMultithread.h" -#include "stdmap.h" -#include "stdvector.h" -#include - -#define ARCH_TASKBAR CArchTaskBarWindows - -//! Win32 implementation of IArchTaskBar -class CArchTaskBarWindows : public IArchTaskBar { -public: - CArchTaskBarWindows(void*); - virtual ~CArchTaskBarWindows(); - - //! Add a dialog window - /*! - Tell the task bar event loop about a dialog. Win32 annoyingly - requires messages destined for modeless dialog boxes to be - dispatched differently than other messages. - */ - static void addDialog(HWND); - - //! Remove a dialog window - /*! - Remove a dialog window added via \c addDialog(). - */ - static void removeDialog(HWND); - - // IArchTaskBar overrides - virtual void addReceiver(IArchTaskBarReceiver*); - virtual void removeReceiver(IArchTaskBarReceiver*); - virtual void updateReceiver(IArchTaskBarReceiver*); - -private: - class CReceiverInfo { - public: - UINT m_id; - }; - - typedef std::map CReceiverToInfoMap; - typedef std::map CIDToReceiverMap; - typedef std::vector CIDStack; - typedef std::map CDialogs; - - UINT getNextID(); - void recycleID(UINT); - - void addIcon(UINT); - void removeIcon(UINT); - void updateIcon(UINT); - void addAllIcons(); - void removeAllIcons(); - void modifyIconNoLock(CReceiverToInfoMap::const_iterator, - DWORD taskBarMessage); - void removeIconNoLock(UINT id); - void handleIconMessage(IArchTaskBarReceiver*, LPARAM); - - bool processDialogs(MSG*); - LRESULT wndProc(HWND, UINT, WPARAM, LPARAM); - static LRESULT CALLBACK - staticWndProc(HWND, UINT, WPARAM, LPARAM); - void threadMainLoop(); - static void* threadEntry(void*); - -private: - static CArchTaskBarWindows* s_instance; - static HINSTANCE s_appInstance; - - // multithread data - CArchMutex m_mutex; - CArchCond m_condVar; - bool m_ready; - int m_result; - CArchThread m_thread; - - // child thread data - HWND m_hwnd; - UINT m_taskBarRestart; - - // shared data - CReceiverToInfoMap m_receivers; - CIDToReceiverMap m_idTable; - CIDStack m_oldIDs; - UINT m_nextID; - - // dialogs - CDialogs m_dialogs; - CDialogs m_addedDialogs; -}; - -#endif diff --git a/lib/arch/CArchTaskBarXWindows.cpp b/lib/arch/CArchTaskBarXWindows.cpp deleted file mode 100644 index 6934f271..00000000 --- a/lib/arch/CArchTaskBarXWindows.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CArchTaskBarXWindows.h" - -// -// CArchTaskBarXWindows -// - -CArchTaskBarXWindows::CArchTaskBarXWindows(void*) -{ - // do nothing -} - -CArchTaskBarXWindows::~CArchTaskBarXWindows() -{ - // do nothing -} - -void -CArchTaskBarXWindows::addReceiver(IArchTaskBarReceiver* /*receiver*/) -{ - // do nothing -} - -void -CArchTaskBarXWindows::removeReceiver(IArchTaskBarReceiver* /*receiver*/) -{ - // do nothing -} - -void -CArchTaskBarXWindows::updateReceiver(IArchTaskBarReceiver* /*receiver*/) -{ - // do nothing -} diff --git a/lib/arch/CArchTaskBarXWindows.h b/lib/arch/CArchTaskBarXWindows.h deleted file mode 100644 index abf28012..00000000 --- a/lib/arch/CArchTaskBarXWindows.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CARCHTASKBARXWINDOWS_H -#define CARCHTASKBARXWINDOWS_H - -#include "IArchTaskBar.h" - -#define ARCH_TASKBAR CArchTaskBarXWindows - -//! X11 implementation of IArchTaskBar -class CArchTaskBarXWindows : public IArchTaskBar { -public: - CArchTaskBarXWindows(void*); - virtual ~CArchTaskBarXWindows(); - - // IArchTaskBar overrides - virtual void addReceiver(IArchTaskBarReceiver*); - virtual void removeReceiver(IArchTaskBarReceiver*); - virtual void updateReceiver(IArchTaskBarReceiver*); -}; - -#endif diff --git a/lib/arch/CArchTimeUnix.cpp b/lib/arch/CArchTimeUnix.cpp deleted file mode 100644 index 49506bad..00000000 --- a/lib/arch/CArchTimeUnix.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CArchTimeUnix.h" -#if TIME_WITH_SYS_TIME -# include -# include -#else -# if HAVE_SYS_TIME_H -# include -# else -# include -# endif -#endif - -// -// CArchTimeUnix -// - -CArchTimeUnix::CArchTimeUnix() -{ - // do nothing -} - -CArchTimeUnix::~CArchTimeUnix() -{ - // do nothing -} - -double -CArchTimeUnix::time() -{ - struct timeval t; - gettimeofday(&t, NULL); - return (double)t.tv_sec + 1.0e-6 * (double)t.tv_usec; -} diff --git a/lib/arch/CArchTimeUnix.h b/lib/arch/CArchTimeUnix.h deleted file mode 100644 index 78c6ff6f..00000000 --- a/lib/arch/CArchTimeUnix.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CARCHTIMEUNIX_H -#define CARCHTIMEUNIX_H - -#include "IArchTime.h" - -#define ARCH_TIME CArchTimeUnix - -//! Generic Unix implementation of IArchTime -class CArchTimeUnix : public IArchTime { -public: - CArchTimeUnix(); - virtual ~CArchTimeUnix(); - - // IArchTime overrides - virtual double time(); -}; - -#endif diff --git a/lib/arch/CArchTimeWindows.cpp b/lib/arch/CArchTimeWindows.cpp deleted file mode 100644 index 57aee290..00000000 --- a/lib/arch/CArchTimeWindows.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -// avoid getting a lot a crap from mmsystem.h that we don't need -#define MMNODRV // Installable driver support -#define MMNOSOUND // Sound support -#define MMNOWAVE // Waveform support -#define MMNOMIDI // MIDI support -#define MMNOAUX // Auxiliary audio support -#define MMNOMIXER // Mixer support -#define MMNOJOY // Joystick support -#define MMNOMCI // MCI support -#define MMNOMMIO // Multimedia file I/O support -#define MMNOMMSYSTEM // General MMSYSTEM functions - -#define WIN32_LEAN_AND_MEAN - -#include "CArchTimeWindows.h" -#include -#include - -typedef WINMMAPI DWORD (WINAPI *PTimeGetTime)(void); - -static double s_freq = 0.0; -static HINSTANCE s_mmInstance = NULL; -static PTimeGetTime s_tgt = NULL; - - -// -// CArchTimeWindows -// - -CArchTimeWindows::CArchTimeWindows() -{ - assert(s_freq == 0.0 || s_mmInstance == NULL); - - LARGE_INTEGER freq; - if (QueryPerformanceFrequency(&freq) && freq.QuadPart != 0) { - s_freq = 1.0 / static_cast(freq.QuadPart); - } - else { - // load winmm.dll and get timeGetTime - s_mmInstance = LoadLibrary("winmm"); - if (s_mmInstance != NULL) { - s_tgt = (PTimeGetTime)GetProcAddress(s_mmInstance, "timeGetTime"); - } - } -} - -CArchTimeWindows::~CArchTimeWindows() -{ - s_freq = 0.0; - if (s_mmInstance == NULL) { - FreeLibrary(reinterpret_cast(s_mmInstance)); - s_tgt = NULL; - s_mmInstance = NULL; - } -} - -double -CArchTimeWindows::time() -{ - // get time. we try three ways, in order of descending precision - if (s_freq != 0.0) { - LARGE_INTEGER c; - QueryPerformanceCounter(&c); - return s_freq * static_cast(c.QuadPart); - } - else if (s_tgt != NULL) { - return 0.001 * static_cast(s_tgt()); - } - else { - return 0.001 * static_cast(GetTickCount()); - } -} diff --git a/lib/arch/CArchTimeWindows.h b/lib/arch/CArchTimeWindows.h deleted file mode 100644 index fb9b1e9f..00000000 --- a/lib/arch/CArchTimeWindows.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CARCHTIMEWINDOWS_H -#define CARCHTIMEWINDOWS_H - -#include "IArchTime.h" - -#define ARCH_TIME CArchTimeWindows - -//! Win32 implementation of IArchTime -class CArchTimeWindows : public IArchTime { -public: - CArchTimeWindows(); - virtual ~CArchTimeWindows(); - - // IArchTime overrides - virtual double time(); -}; - -#endif diff --git a/lib/arch/CMultibyte.cpp b/lib/arch/CMultibyte.cpp deleted file mode 100644 index 517d72d6..00000000 --- a/lib/arch/CMultibyte.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CMULTIBYTE_H -#define CMULTIBYTE_H - -#include "common.h" -#include "CArch.h" -#include -#include -#if HAVE_LOCALE_H -# include -#endif -#if HAVE_WCHAR_H || defined(_MSC_VER) -# include -#elif __APPLE__ - // wtf? Darwin puts mbtowc() et al. in stdlib -# include -#else - // platform apparently has no wchar_t support. provide dummy - // implementations. hopefully at least the C++ compiler has - // a built-in wchar_t type. - -static inline -int -mbtowc(wchar_t* dst, const char* src, int n) -{ - *dst = static_cast(*src); - return 1; -} - -static inline -int -wctomb(char* dst, wchar_t src) -{ - *dst = static_cast(src); - return 1; -} - -#endif - -// -// use C library non-reentrant multibyte conversion with mutex -// - -static CArchMutex s_mutex = NULL; - -ARCH_STRING::ARCH_STRING() -{ - s_mutex = ARCH->newMutex(); - -#if HAVE_LOCALE_H - // see if we can convert a Latin-1 character - char mb[MB_LEN_MAX]; - if (wctomb(mb, 0xe3) == -1) { - // can't convert. try another locale so we can convert latin-1. - setlocale(LC_CTYPE, "en_US"); - } -#endif -} - -ARCH_STRING::~ARCH_STRING() -{ - ARCH->closeMutex(s_mutex); - s_mutex = NULL; -} - -int -ARCH_STRING::convStringWCToMB(char* dst, - const wchar_t* src, UInt32 n, bool* errors) -{ - int len = 0; - - bool dummyErrors; - if (errors == NULL) { - errors = &dummyErrors; - } - - ARCH->lockMutex(s_mutex); - if (dst == NULL) { - char dummy[MB_LEN_MAX]; - for (const wchar_t* scan = src; n > 0; ++scan, --n) { - int mblen = wctomb(dummy, *scan); - if (mblen == -1) { - *errors = true; - mblen = 1; - } - len += mblen; - } - int mblen = wctomb(dummy, L'\0'); - if (mblen != -1) { - len += mblen - 1; - } - } - else { - char* dst0 = dst; - for (const wchar_t* scan = src; n > 0; ++scan, --n) { - int mblen = wctomb(dst, *scan); - if (mblen == -1) { - *errors = true; - *dst++ = '?'; - } - else { - dst += mblen; - } - } - int mblen = wctomb(dst, L'\0'); - if (mblen != -1) { - // don't include nul terminator - dst += mblen - 1; - } - len = (int)(dst - dst0); - } - ARCH->unlockMutex(s_mutex); - - return len; -} - -int -ARCH_STRING::convStringMBToWC(wchar_t* dst, - const char* src, UInt32 n, bool* errors) -{ - int len = 0; - wchar_t dummy; - - bool dummyErrors; - if (errors == NULL) { - errors = &dummyErrors; - } - - ARCH->lockMutex(s_mutex); - if (dst == NULL) { - for (const char* scan = src; n > 0; ) { - int mblen = mbtowc(&dummy, scan, n); - switch (mblen) { - case -2: - // incomplete last character. convert to unknown character. - *errors = true; - len += 1; - n = 0; - break; - - case -1: - // invalid character. count one unknown character and - // start at the next byte. - *errors = true; - len += 1; - scan += 1; - n -= 1; - break; - - case 0: - len += 1; - scan += 1; - n -= 1; - break; - - default: - // normal character - len += 1; - scan += mblen; - n -= mblen; - break; - } - } - } - else { - wchar_t* dst0 = dst; - for (const char* scan = src; n > 0; ++dst) { - int mblen = mbtowc(dst, scan, n); - switch (mblen) { - case -2: - // incomplete character. convert to unknown character. - *errors = true; - *dst = (wchar_t)0xfffd; - n = 0; - break; - - case -1: - // invalid character. count one unknown character and - // start at the next byte. - *errors = true; - *dst = (wchar_t)0xfffd; - scan += 1; - n -= 1; - break; - - case 0: - *dst = (wchar_t)0x0000; - scan += 1; - n -= 1; - break; - - default: - // normal character - scan += mblen; - n -= mblen; - break; - } - } - len = (int)(dst - dst0); - } - ARCH->unlockMutex(s_mutex); - - return len; -} - -#endif diff --git a/lib/arch/IArchConsole.h b/lib/arch/IArchConsole.h deleted file mode 100644 index 2befb196..00000000 --- a/lib/arch/IArchConsole.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef IARCHCONSOLE_H -#define IARCHCONSOLE_H - -#include "IInterface.h" - -//! Interface for architecture dependent console output -/*! -This interface defines the console operations required by -synergy. Each architecture must implement this interface. -*/ -class IArchConsole : public IInterface { -public: - //! @name manipulators - //@{ - - //! Open the console - /*! - Opens the console for writing. The console is opened automatically - on the first write so calling this method is optional. Uses \c title - for the console's title if appropriate for the architecture. Calling - this method on an already open console must have no effect. - */ - virtual void openConsole(const char* title) = 0; - - //! Close the console - /*! - Close the console. Calling this method on an already closed console - must have no effect. - */ - virtual void closeConsole() = 0; - - //! Show the console - /*! - Causes the console to become visible. This generally only makes sense - for a console in a graphical user interface. Other implementations - will do nothing. Iff \p showIfEmpty is \c false then the implementation - may optionally only show the console if it's not empty. - */ - virtual void showConsole(bool showIfEmpty) = 0; - - //! Write to the console - /*! - Writes the given string to the console, opening it if necessary. - */ - virtual void writeConsole(const char*) = 0; - - //! Returns the newline sequence for the console - /*! - Different consoles use different character sequences for newlines. - This method returns the appropriate newline sequence for the console. - */ - virtual const char* getNewlineForConsole() = 0; - - //@} -}; - -#endif diff --git a/lib/arch/IArchDaemon.h b/lib/arch/IArchDaemon.h deleted file mode 100644 index ba6b049b..00000000 --- a/lib/arch/IArchDaemon.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef IARCHDAEMON_H -#define IARCHDAEMON_H - -#include "IInterface.h" - -//! Interface for architecture dependent daemonizing -/*! -This interface defines the operations required by synergy for installing -uninstalling daeamons and daemonizing a process. Each architecture must -implement this interface. -*/ -class IArchDaemon : public IInterface { -public: - typedef int (*DaemonFunc)(int argc, const char** argv); - - //! @name manipulators - //@{ - - //! Install daemon - /*! - Install a daemon. \c name is the name of the daemon passed to the - system and \c description is a short human readable description of - the daemon. \c pathname is the path to the daemon executable. - \c commandLine should \b not include the name of program as the - first argument. If \c allUsers is true then the daemon will be - installed to start at boot time, otherwise it will be installed to - start when the current user logs in. If \p dependencies is not NULL - then it's a concatenation of NUL terminated other daemon names - followed by a NUL; the daemon will be configured to startup after - the listed daemons. Throws an \c XArchDaemon exception on failure. - */ - virtual void installDaemon(const char* name, - const char* description, - const char* pathname, - const char* commandLine, - const char* dependencies, - bool allUsers) = 0; - - //! Uninstall daemon - /*! - Uninstall a daemon. Throws an \c XArchDaemon on failure. - */ - virtual void uninstallDaemon(const char* name, bool allUsers) = 0; - - //! Daemonize the process - /*! - Daemonize. Throw XArchDaemonFailed on error. \c name is the name - of the daemon. Once daemonized, \c func is invoked and daemonize - returns when and what it does. - - Exactly what happens when daemonizing depends on the platform. -
      -
    • unix: - Detaches from terminal. \c func gets passed one argument, the - name passed to daemonize(). -
    • win32: - Becomes a service. Argument 0 is the name of the service - and the rest are the arguments passed to StartService(). - \c func is only called when the service is actually started. - \c func must call \c CArchMiscWindows::runDaemon() to finally - becoming a service. The \c runFunc function passed to \c runDaemon() - must call \c CArchMiscWindows::daemonRunning(true) when it - enters the main loop (i.e. after initialization) and - \c CArchMiscWindows::daemonRunning(false) when it leaves - the main loop. The \c stopFunc function passed to \c runDaemon() - is called when the daemon must exit the main loop and it must cause - \c runFunc to return. \c func should return what \c runDaemon() - returns. \c func or \c runFunc can call - \c CArchMiscWindows::daemonFailed() to indicate startup failure. -
    - */ - virtual int daemonize(const char* name, DaemonFunc func) = 0; - - //! Check if user has permission to install the daemon - /*! - Returns true iff the caller has permission to install or - uninstall the daemon. Note that even if this method returns - true it's possible that installing/uninstalling the service - may still fail. This method ignores whether or not the - service is already installed. - */ - virtual bool canInstallDaemon(const char* name, bool allUsers) = 0; - - //! Check if the daemon is installed - /*! - Returns true iff the daemon is installed. - */ - virtual bool isDaemonInstalled(const char* name, bool allUsers) = 0; - - //@} -}; - -#endif diff --git a/lib/arch/IArchFile.h b/lib/arch/IArchFile.h deleted file mode 100644 index 8594053d..00000000 --- a/lib/arch/IArchFile.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef IARCHFILE_H -#define IARCHFILE_H - -#include "IInterface.h" -#include "stdstring.h" - -//! Interface for architecture dependent file system operations -/*! -This interface defines the file system operations required by -synergy. Each architecture must implement this interface. -*/ -class IArchFile : public IInterface { -public: - //! @name manipulators - //@{ - - //! Extract base name - /*! - Find the base name in the given \c pathname. - */ - virtual const char* getBasename(const char* pathname) = 0; - - //! Get user's home directory - /*! - Returns the user's home directory. Returns the empty string if - this cannot be determined. - */ - virtual std::string getUserDirectory() = 0; - - //! Get system directory - /*! - Returns the ussystem configuration file directory. - */ - virtual std::string getSystemDirectory() = 0; - - //! Concatenate path components - /*! - Concatenate pathname components with a directory separator - between them. This should not check if the resulting path - is longer than allowed by the system; we'll rely on the - system calls to tell us that. - */ - virtual std::string concatPath( - const std::string& prefix, - const std::string& suffix) = 0; - - //@} -}; - -#endif diff --git a/lib/arch/IArchLog.h b/lib/arch/IArchLog.h deleted file mode 100644 index 7655ff95..00000000 --- a/lib/arch/IArchLog.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef IARCHLOG_H -#define IARCHLOG_H - -#include "IInterface.h" - -//! Interface for architecture dependent logging -/*! -This interface defines the logging operations required by -synergy. Each architecture must implement this interface. -*/ -class IArchLog : public IInterface { -public: - //! Log levels - /*! - The logging priority levels in order of highest to lowest priority. - */ - enum ELevel { - kERROR, //!< For serious or fatal errors - kWARNING, //!< For minor errors and warnings - kNOTE, //!< For messages about notable events - kINFO, //!< For informational messages - kDEBUG //!< For debugging messages - }; - - //! @name manipulators - //@{ - - //! Open the log - /*! - Opens the log for writing. The log must be opened before being - written to. - */ - virtual void openLog(const char* name) = 0; - - //! Close the log - /*! - Close the log. - */ - virtual void closeLog() = 0; - - //! Show the log - /*! - Causes the log to become visible. This generally only makes sense - for a log in a graphical user interface. Other implementations - will do nothing. Iff \p showIfEmpty is \c false then the implementation - may optionally only show the log if it's not empty. - */ - virtual void showLog(bool showIfEmpty) = 0; - - //! Write to the log - /*! - Writes the given string to the log with the given level. - */ - virtual void writeLog(ELevel, const char*) = 0; - - //@} -}; - -#endif diff --git a/lib/arch/IArchMultithread.h b/lib/arch/IArchMultithread.h deleted file mode 100644 index b7b72293..00000000 --- a/lib/arch/IArchMultithread.h +++ /dev/null @@ -1,272 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef IARCHMULTITHREAD_H -#define IARCHMULTITHREAD_H - -#include "IInterface.h" - -/*! -\class CArchCondImpl -\brief Internal condition variable data. -An architecture dependent type holding the necessary data for a -condition variable. -*/ -class CArchCondImpl; - -/*! -\var CArchCond -\brief Opaque condition variable type. -An opaque type representing a condition variable. -*/ -typedef CArchCondImpl* CArchCond; - -/*! -\class CArchMutexImpl -\brief Internal mutex data. -An architecture dependent type holding the necessary data for a mutex. -*/ -class CArchMutexImpl; - -/*! -\var CArchMutex -\brief Opaque mutex type. -An opaque type representing a mutex. -*/ -typedef CArchMutexImpl* CArchMutex; - -/*! -\class CArchThreadImpl -\brief Internal thread data. -An architecture dependent type holding the necessary data for a thread. -*/ -class CArchThreadImpl; - -/*! -\var CArchThread -\brief Opaque thread type. -An opaque type representing a thread. -*/ -typedef CArchThreadImpl* CArchThread; - -//! Interface for architecture dependent multithreading -/*! -This interface defines the multithreading operations required by -synergy. Each architecture must implement this interface. -*/ -class IArchMultithread : public IInterface { -public: - //! Type of thread entry point - typedef void* (*ThreadFunc)(void*); - //! Type of thread identifier - typedef unsigned int ThreadID; - //! Types of signals - /*! - Not all platforms support all signals. Unsupported signals are - ignored. - */ - enum ESignal { - kINTERRUPT, //!< Interrupt (e.g. Ctrl+C) - kTERMINATE, //!< Terminate (e.g. Ctrl+Break) - kHANGUP, //!< Hangup (SIGHUP) - kUSER, //!< User (SIGUSR2) - kNUM_SIGNALS - }; - //! Type of signal handler function - typedef void (*SignalFunc)(ESignal, void* userData); - - //! @name manipulators - //@{ - - // - // condition variable methods - // - - //! Create a condition variable - /*! - The condition variable is an opaque data type. - */ - virtual CArchCond newCondVar() = 0; - - //! Destroy a condition variable - virtual void closeCondVar(CArchCond) = 0; - - //! Signal a condition variable - /*! - Signalling a condition variable releases one waiting thread. - */ - virtual void signalCondVar(CArchCond) = 0; - - //! Broadcast a condition variable - /*! - Broadcasting a condition variable releases all waiting threads. - */ - virtual void broadcastCondVar(CArchCond) = 0; - - //! Wait on a condition variable - /*! - Wait on a conditation variable for up to \c timeout seconds. - If \c timeout is < 0 then there is no timeout. The mutex must - be locked when this method is called. The mutex is unlocked - during the wait and locked again before returning. Returns - true if the condition variable was signalled and false on - timeout. - - (Cancellation point) - */ - virtual bool waitCondVar(CArchCond, CArchMutex, double timeout) = 0; - - // - // mutex methods - // - - //! Create a recursive mutex - /*! - Creates a recursive mutex. A thread may lock a recursive mutex - when it already holds a lock on that mutex. The mutex is an - opaque data type. - */ - virtual CArchMutex newMutex() = 0; - - //! Destroy a mutex - virtual void closeMutex(CArchMutex) = 0; - - //! Lock a mutex - virtual void lockMutex(CArchMutex) = 0; - - //! Unlock a mutex - virtual void unlockMutex(CArchMutex) = 0; - - // - // thread methods - // - - //! Start a new thread - /*! - Creates and starts a new thread, using \c func as the entry point - and passing it \c userData. The thread is an opaque data type. - */ - virtual CArchThread newThread(ThreadFunc func, void* userData) = 0; - - //! Get a reference to the calling thread - /*! - Returns a thread representing the current (i.e. calling) thread. - */ - virtual CArchThread newCurrentThread() = 0; - - //! Copy a thread object - /*! - Returns a reference to to thread referred to by \c thread. - */ - virtual CArchThread copyThread(CArchThread thread) = 0; - - //! Release a thread reference - /*! - Deletes the given thread object. This does not destroy the thread - the object referred to, even if there are no remaining references. - Use cancelThread() and waitThread() to stop a thread and wait for - it to exit. - */ - virtual void closeThread(CArchThread) = 0; - - //! Force a thread to exit - /*! - Causes \c thread to exit when it next calls a cancellation point. - A thread avoids cancellation as long as it nevers calls a - cancellation point. Once it begins the cancellation process it - must always let cancellation go to completion but may take as - long as necessary to clean up. - */ - virtual void cancelThread(CArchThread thread) = 0; - - //! Change thread priority - /*! - Changes the priority of \c thread by \c n. If \c n is positive - the thread has a lower priority and if negative a higher priority. - Some architectures may not support either or both directions. - */ - virtual void setPriorityOfThread(CArchThread, int n) = 0; - - //! Cancellation point - /*! - This method does nothing but is a cancellation point. Clients - can make their own functions cancellation points by calling this - method at appropriate times. - - (Cancellation point) - */ - virtual void testCancelThread() = 0; - - //! Wait for a thread to exit - /*! - Waits for up to \c timeout seconds for \c thread to exit (normally - or by cancellation). Waits forever if \c timeout < 0. Returns - true if the thread exited, false otherwise. Waiting on the current - thread returns immediately with false. - - (Cancellation point) - */ - virtual bool wait(CArchThread thread, double timeout) = 0; - - //! Compare threads - /*! - Returns true iff two thread objects refer to the same thread. - Note that comparing thread objects directly is meaningless. - */ - virtual bool isSameThread(CArchThread, CArchThread) = 0; - - //! Test if thread exited - /*! - Returns true iff \c thread has exited. - */ - virtual bool isExitedThread(CArchThread thread) = 0; - - //! Returns the exit code of a thread - /*! - Waits indefinitely for \c thread to exit (if it hasn't yet) then - returns the thread's exit code. - - (Cancellation point) - */ - virtual void* getResultOfThread(CArchThread thread) = 0; - - //! Returns an ID for a thread - /*! - Returns some ID number for \c thread. This is for logging purposes. - All thread objects referring to the same thread return the same ID. - However, clients should us isSameThread() to compare thread objects - instead of comparing IDs. - */ - virtual ThreadID getIDOfThread(CArchThread thread) = 0; - - //! Set the interrupt handler - /*! - Sets the function to call on receipt of an external interrupt. - By default and when \p func is NULL, the main thread is cancelled. - */ - virtual void setSignalHandler(ESignal, SignalFunc func, - void* userData) = 0; - - //! Invoke the signal handler - /*! - Invokes the signal handler for \p signal, if any. If no handler - cancels the main thread for \c kINTERRUPT and \c kTERMINATE and - ignores the call otherwise. - */ - virtual void raiseSignal(ESignal signal) = 0; - - //@} -}; - -#endif diff --git a/lib/arch/IArchNetwork.h b/lib/arch/IArchNetwork.h deleted file mode 100644 index 007fb442..00000000 --- a/lib/arch/IArchNetwork.h +++ /dev/null @@ -1,279 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef IARCHNETWORK_H -#define IARCHNETWORK_H - -#include "IInterface.h" -#include "stdstring.h" - -class CArchThreadImpl; -typedef CArchThreadImpl* CArchThread; - -/*! -\class CArchSocketImpl -\brief Internal socket data. -An architecture dependent type holding the necessary data for a socket. -*/ -class CArchSocketImpl; - -/*! -\var CArchSocket -\brief Opaque socket type. -An opaque type representing a socket. -*/ -typedef CArchSocketImpl* CArchSocket; - -/*! -\class CArchNetAddressImpl -\brief Internal network address data. -An architecture dependent type holding the necessary data for a network -address. -*/ -class CArchNetAddressImpl; - -/*! -\var CArchNetAddress -\brief Opaque network address type. -An opaque type representing a network address. -*/ -typedef CArchNetAddressImpl* CArchNetAddress; - -//! Interface for architecture dependent networking -/*! -This interface defines the networking operations required by -synergy. Each architecture must implement this interface. -*/ -class IArchNetwork : public IInterface { -public: - //! Supported address families - enum EAddressFamily { - kUNKNOWN, - kINET, - }; - - //! Supported socket types - enum ESocketType { - kDGRAM, - kSTREAM - }; - - //! Events for \c poll() - /*! - Events for \c poll() are bitmasks and can be combined using the - bitwise operators. - */ - enum { - kPOLLIN = 1, //!< Socket is readable - kPOLLOUT = 2, //!< Socket is writable - kPOLLERR = 4, //!< The socket is in an error state - kPOLLNVAL = 8 //!< The socket is invalid - }; - - //! A socket query for \c poll() - class CPollEntry { - public: - //! The socket to query - CArchSocket m_socket; - - //! The events to query for - /*! - The events to query for can be any combination of kPOLLIN and - kPOLLOUT. - */ - unsigned short m_events; - - //! The result events - unsigned short m_revents; - }; - - //! @name manipulators - //@{ - - //! Create a new socket - /*! - The socket is an opaque data type. - */ - virtual CArchSocket newSocket(EAddressFamily, ESocketType) = 0; - - //! Copy a socket object - /*! - Returns a reference to to socket referred to by \c s. - */ - virtual CArchSocket copySocket(CArchSocket s) = 0; - - //! Release a socket reference - /*! - Deletes the given socket object. This does not destroy the socket - the object referred to until there are no remaining references for - the socket. - */ - virtual void closeSocket(CArchSocket s) = 0; - - //! Close socket for further reads - /*! - Calling this disallows future reads on socket \c s. - */ - virtual void closeSocketForRead(CArchSocket s) = 0; - - //! Close socket for further writes - /*! - Calling this disallows future writes on socket \c s. - */ - virtual void closeSocketForWrite(CArchSocket s) = 0; - - //! Bind socket to address - /*! - Binds socket \c s to the address \c addr. - */ - virtual void bindSocket(CArchSocket s, CArchNetAddress addr) = 0; - - //! Listen for connections on socket - /*! - Causes the socket \c s to begin listening for incoming connections. - */ - virtual void listenOnSocket(CArchSocket s) = 0; - - //! Accept connection on socket - /*! - Accepts a connection on socket \c s, returning a new socket for the - connection and filling in \c addr with the address of the remote - end. \c addr may be NULL if the remote address isn't required. - The original socket \c s is unaffected and remains in the listening - state. The new socket shares most of the properties of \c s except - it's not in the listening state and it's connected. Returns NULL - if there are no pending connection requests. - */ - virtual CArchSocket acceptSocket(CArchSocket s, CArchNetAddress* addr) = 0; - - //! Connect socket - /*! - Connects the socket \c s to the remote address \c addr. Returns - true if the connection succeed immediately, false if the connection - is in progress, and throws if the connection failed immediately. - If it returns false, \c pollSocket() can be used to wait on the - socket for writing to detect when the connection finally succeeds - or fails. - */ - virtual bool connectSocket(CArchSocket s, CArchNetAddress addr) = 0; - - //! Check socket state - /*! - Tests the state of \c num sockets for readability and/or writability. - Waits up to \c timeout seconds for some socket to become readable - and/or writable (or indefinitely if \c timeout < 0). Returns the - number of sockets that were readable (if readability was being - queried) or writable (if writablility was being queried) and sets - the \c m_revents members of the entries. \c kPOLLERR and \c kPOLLNVAL - are set in \c m_revents as appropriate. If a socket indicates - \c kPOLLERR then \c throwErrorOnSocket() can be used to determine - the type of error. Returns 0 immediately regardless of the \c timeout - if no valid sockets are selected for testing. - - (Cancellation point) - */ - virtual int pollSocket(CPollEntry[], int num, double timeout) = 0; - - //! Unblock thread in pollSocket() - /*! - Cause a thread that's in a pollSocket() call to return. This - call may return before the thread is unblocked. If the thread is - not in a pollSocket() call this call has no effect. - */ - virtual void unblockPollSocket(CArchThread thread) = 0; - - //! Read data from socket - /*! - Read up to \c len bytes from socket \c s in \c buf and return the - number of bytes read. The number of bytes can be less than \c len - if not enough data is available. Returns 0 if the remote end has - disconnected and/or there is no more queued received data. - */ - virtual size_t readSocket(CArchSocket s, void* buf, size_t len) = 0; - - //! Write data from socket - /*! - Write up to \c len bytes to socket \c s from \c buf and return the - number of bytes written. The number of bytes can be less than - \c len if the remote end disconnected or the internal buffers fill - up. - */ - virtual size_t writeSocket(CArchSocket s, - const void* buf, size_t len) = 0; - - //! Check error on socket - /*! - If the socket \c s is in an error state then throws an appropriate - XArchNetwork exception. - */ - virtual void throwErrorOnSocket(CArchSocket s) = 0; - - //! Turn Nagle algorithm on or off on socket - /*! - Set socket to send messages immediately (true) or to collect small - messages into one packet (false). Returns the previous state. - */ - virtual bool setNoDelayOnSocket(CArchSocket, bool noDelay) = 0; - - //! Turn address reuse on or off on socket - /*! - Allows the address this socket is bound to to be reused while in the - TIME_WAIT state. Returns the previous state. - */ - virtual bool setReuseAddrOnSocket(CArchSocket, bool reuse) = 0; - - //! Return local host's name - virtual std::string getHostName() = 0; - - //! Create an "any" network address - virtual CArchNetAddress newAnyAddr(EAddressFamily) = 0; - - //! Copy a network address - virtual CArchNetAddress copyAddr(CArchNetAddress) = 0; - - //! Convert a name to a network address - virtual CArchNetAddress nameToAddr(const std::string&) = 0; - - //! Destroy a network address - virtual void closeAddr(CArchNetAddress) = 0; - - //! Convert an address to a host name - virtual std::string addrToName(CArchNetAddress) = 0; - - //! Convert an address to a string - virtual std::string addrToString(CArchNetAddress) = 0; - - //! Get an address's family - virtual EAddressFamily getAddrFamily(CArchNetAddress) = 0; - - //! Set the port of an address - virtual void setAddrPort(CArchNetAddress, int port) = 0; - - //! Get the port of an address - virtual int getAddrPort(CArchNetAddress) = 0; - - //! Test addresses for equality - virtual bool isEqualAddr(CArchNetAddress, CArchNetAddress) = 0; - - //! Test for the "any" address - /*! - Returns true if \c addr is the "any" address. \c newAnyAddr() - returns an "any" address. - */ - virtual bool isAnyAddr(CArchNetAddress addr) = 0; - - //@} -}; - -#endif diff --git a/lib/arch/IArchSleep.h b/lib/arch/IArchSleep.h deleted file mode 100644 index 95a2852c..00000000 --- a/lib/arch/IArchSleep.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef IARCHSLEEP_H -#define IARCHSLEEP_H - -#include "IInterface.h" - -//! Interface for architecture dependent sleeping -/*! -This interface defines the sleep operations required by -synergy. Each architecture must implement this interface. -*/ -class IArchSleep : public IInterface { -public: - //! @name manipulators - //@{ - - //! Sleep - /*! - Blocks the calling thread for \c timeout seconds. If - \c timeout < 0.0 then the call returns immediately. If \c timeout - == 0.0 then the calling thread yields the CPU. - - (cancellation point) - */ - virtual void sleep(double timeout) = 0; - - //@} -}; - -#endif diff --git a/lib/arch/IArchString.h b/lib/arch/IArchString.h deleted file mode 100644 index 703d64b1..00000000 --- a/lib/arch/IArchString.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef IARCHSTRING_H -#define IARCHSTRING_H - -#include "IInterface.h" -#include "BasicTypes.h" -#include - -//! Interface for architecture dependent string operations -/*! -This interface defines the string operations required by -synergy. Each architecture must implement this interface. -*/ -class IArchString : public IInterface { -public: - //! Wide character encodings - /*! - The known wide character encodings - */ - enum EWideCharEncoding { - kUCS2, //!< The UCS-2 encoding - kUCS4, //!< The UCS-4 encoding - kUTF16, //!< The UTF-16 encoding - kUTF32 //!< The UTF-32 encoding - }; - - //! @name manipulators - //@{ - - //! printf() to limited size buffer with va_list - /*! - This method is equivalent to vsprintf() except it will not write - more than \c n bytes to the buffer, returning -1 if the output - was truncated and the number of bytes written not including the - trailing NUL otherwise. - */ - virtual int vsnprintf(char* str, - int size, const char* fmt, va_list ap) = 0; - - //! Convert multibyte string to wide character string - virtual int convStringMBToWC(wchar_t*, - const char*, UInt32 n, bool* errors) = 0; - - //! Convert wide character string to multibyte string - virtual int convStringWCToMB(char*, - const wchar_t*, UInt32 n, bool* errors) = 0; - - //! Return the architecture's native wide character encoding - virtual EWideCharEncoding - getWideCharEncoding() = 0; - - //@} -}; - -#endif diff --git a/lib/arch/IArchSystem.h b/lib/arch/IArchSystem.h deleted file mode 100644 index 7a6c941b..00000000 --- a/lib/arch/IArchSystem.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef IARCHSYSTEM_H -#define IARCHSYSTEM_H - -#include "IInterface.h" -#include "stdstring.h" - -//! Interface for architecture dependent system queries -/*! -This interface defines operations for querying system info. -*/ -class IArchSystem : public IInterface { -public: - //! @name accessors - //@{ - - //! Identify the OS - /*! - Returns a string identifying the operating system. - */ - virtual std::string getOSName() const = 0; - - //@} -}; - -#endif diff --git a/lib/arch/IArchTaskBar.h b/lib/arch/IArchTaskBar.h deleted file mode 100644 index e9471566..00000000 --- a/lib/arch/IArchTaskBar.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef IARCHTASKBAR_H -#define IARCHTASKBAR_H - -#include "IInterface.h" - -class IArchTaskBarReceiver; - -//! Interface for architecture dependent task bar control -/*! -This interface defines the task bar icon operations required -by synergy. Each architecture must implement this interface -though each operation can be a no-op. -*/ -class IArchTaskBar : public IInterface { -public: - //! @name manipulators - //@{ - - //! Add a receiver - /*! - Add a receiver object to be notified of user and application - events. This should be called before other methods. When - the receiver is added to the task bar, its icon appears on - the task bar. - */ - virtual void addReceiver(IArchTaskBarReceiver*) = 0; - - //! Remove a receiver - /*! - Remove a receiver object from the task bar. This removes the - icon from the task bar. - */ - virtual void removeReceiver(IArchTaskBarReceiver*) = 0; - - //! Update a receiver - /*! - Updates the display of the receiver on the task bar. This - should be called when the receiver appearance may have changed - (e.g. it's icon or tool tip has changed). - */ - virtual void updateReceiver(IArchTaskBarReceiver*) = 0; - - //@} -}; - -#endif diff --git a/lib/arch/IArchTaskBarReceiver.h b/lib/arch/IArchTaskBarReceiver.h deleted file mode 100644 index 917f2fbf..00000000 --- a/lib/arch/IArchTaskBarReceiver.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef IARCHTASKBARRECEIVER_H -#define IARCHTASKBARRECEIVER_H - -#include "IInterface.h" -#include "stdstring.h" - -//! Interface for architecture dependent task bar event handling -/*! -This interface defines the task bar icon event handlers required -by synergy. Each architecture must implement this interface -though each operation can be a no-op. -*/ -class IArchTaskBarReceiver : public IInterface { -public: - // Icon data is architecture dependent - typedef void* Icon; - - //! @name manipulators - //@{ - - //! Show status window - /*! - Open a window displaying current status. This should return - immediately without waiting for the window to be closed. - */ - virtual void showStatus() = 0; - - //! Popup menu - /*! - Popup a menu of operations at or around \c x,y and perform the - chosen operation. - */ - virtual void runMenu(int x, int y) = 0; - - //! Perform primary action - /*! - Perform the primary (default) action. - */ - virtual void primaryAction() = 0; - - //@} - //! @name accessors - //@{ - - //! Lock receiver - /*! - Locks the receiver from changing state. The receiver should be - locked when querying it's state to ensure consistent results. - Each call to \c lock() must have a matching \c unlock() and - locks cannot be nested. - */ - virtual void lock() const = 0; - - //! Unlock receiver - virtual void unlock() const = 0; - - //! Get icon - /*! - Returns the icon to display in the task bar. The interface - to set the icon is left to subclasses. Getting and setting - the icon must be thread safe. - */ - virtual const Icon getIcon() const = 0; - - //! Get tooltip - /*! - Returns the tool tip to display in the task bar. The interface - to set the tooltip is left to sublclasses. Getting and setting - the icon must be thread safe. - */ - virtual std::string getToolTip() const = 0; - - //@} -}; - -#endif diff --git a/lib/arch/IArchTime.h b/lib/arch/IArchTime.h deleted file mode 100644 index dade64bb..00000000 --- a/lib/arch/IArchTime.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef IARCHTIME_H -#define IARCHTIME_H - -#include "IInterface.h" - -//! Interface for architecture dependent time operations -/*! -This interface defines the time operations required by -synergy. Each architecture must implement this interface. -*/ -class IArchTime : public IInterface { -public: - //! @name manipulators - //@{ - - //! Get the current time - /*! - Returns the number of seconds since some arbitrary starting time. - This should return as high a precision as reasonable. - */ - virtual double time() = 0; - - //@} -}; - -#endif diff --git a/lib/arch/Makefile.am b/lib/arch/Makefile.am deleted file mode 100644 index 8a1749ab..00000000 --- a/lib/arch/Makefile.am +++ /dev/null @@ -1,118 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2002 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -## Process this file with automake to produce Makefile.in -NULL = - -COMMON_SOURCE_FILES = \ - CArch.cpp \ - CArchDaemonNone.cpp \ - CArchDaemonNone.h \ - XArch.cpp \ - CArch.h \ - IArchConsole.h \ - IArchDaemon.h \ - IArchFile.h \ - IArchLog.h \ - IArchMultithread.h \ - IArchNetwork.h \ - IArchSleep.h \ - IArchString.h \ - IArchSystem.h \ - IArchTaskBar.h \ - IArchTaskBarReceiver.h \ - IArchTime.h \ - XArch.h \ - $(NULL) -UNIX_SOURCE_FILES = \ - CArchConsoleUnix.cpp \ - CArchDaemonUnix.cpp \ - CArchFileUnix.cpp \ - CArchLogUnix.cpp \ - CArchMultithreadPosix.cpp \ - CArchNetworkBSD.cpp \ - CArchSleepUnix.cpp \ - CArchStringUnix.cpp \ - CArchSystemUnix.cpp \ - CArchTaskBarXWindows.cpp \ - CArchTimeUnix.cpp \ - XArchUnix.cpp \ - CArchConsoleUnix.h \ - CArchDaemonUnix.h \ - CArchFileUnix.h \ - CArchLogUnix.h \ - CArchMultithreadPosix.h \ - CArchNetworkBSD.h \ - CArchSleepUnix.h \ - CArchStringUnix.h \ - CArchSystemUnix.h \ - CArchTaskBarXWindows.h \ - CArchTimeUnix.h \ - XArchUnix.h \ - $(NULL) -WIN32_SOURCE_FILES = \ - CArchConsoleWindows.cpp \ - CArchDaemonWindows.cpp \ - CArchFileWindows.cpp \ - CArchLogWindows.cpp \ - CArchMiscWindows.cpp \ - CArchMultithreadWindows.cpp \ - CArchNetworkWinsock.cpp \ - CArchSleepWindows.cpp \ - CArchStringWindows.cpp \ - CArchSystemWindows.cpp \ - CArchTaskBarWindows.cpp \ - CArchTimeWindows.cpp \ - XArchWindows.cpp \ - CArchConsoleWindows.h \ - CArchDaemonWindows.h \ - CArchFileWindows.h \ - CArchLogWindows.h \ - CArchMiscWindows.h \ - CArchMultithreadWindows.h \ - CArchNetworkWinsock.h \ - CArchSleepWindows.h \ - CArchStringWindows.h \ - CArchSystemWindows.h \ - CArchTaskBarWindows.h \ - CArchTimeWindows.h \ - XArchWindows.h \ - $(NULL) - -EXTRA_DIST = \ - CMultibyte.cpp \ - Makefile.win \ - vsnprintf.cpp \ - $(UNIX_SOURCE_FILES) \ - $(WIN32_SOURCE_FILES) \ - $(NULL) - -MAINTAINERCLEANFILES = \ - Makefile.in \ - $(NULL) - -noinst_LIBRARIES = libarch.a -if UNIX -libarch_a_SOURCES = \ - $(COMMON_SOURCE_FILES) \ - $(UNIX_SOURCE_FILES) \ - $(NULL) -endif -if WIN32 -libarch_a_SOURCES = \ - $(COMMON_SOURCE_FILES) \ - $(WIN32_SOURCE_FILES) \ - $(NULL) -endif -INCLUDES = \ - -I$(top_srcdir)/lib/common \ - $(NULL) diff --git a/lib/arch/Makefile.win b/lib/arch/Makefile.win deleted file mode 100644 index 4e151976..00000000 --- a/lib/arch/Makefile.win +++ /dev/null @@ -1,84 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2007 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -LIB_ARCH_SRC = lib\arch -LIB_ARCH_DST = $(BUILD_DST)\$(LIB_ARCH_SRC) -LIB_ARCH_LIB = "$(LIB_ARCH_DST)\arch.lib" -LIB_ARCH_CPP = \ - "CArch.cpp" \ - "CArchDaemonNone.cpp" \ - "XArch.cpp" \ - "CArchConsoleWindows.cpp" \ - "CArchDaemonWindows.cpp" \ - "CArchFileWindows.cpp" \ - "CArchLogWindows.cpp" \ - "CArchMiscWindows.cpp" \ - "CArchMultithreadWindows.cpp" \ - "CArchNetworkWinsock.cpp" \ - "CArchSleepWindows.cpp" \ - "CArchStringWindows.cpp" \ - "CArchSystemWindows.cpp" \ - "CArchTaskBarWindows.cpp" \ - "CArchTimeWindows.cpp" \ - "XArchWindows.cpp" \ - $(NULL) -LIB_ARCH_OBJ = \ - "$(LIB_ARCH_DST)\CArch.obj" \ - "$(LIB_ARCH_DST)\CArchDaemonNone.obj" \ - "$(LIB_ARCH_DST)\XArch.obj" \ - "$(LIB_ARCH_DST)\CArchConsoleWindows.obj" \ - "$(LIB_ARCH_DST)\CArchDaemonWindows.obj" \ - "$(LIB_ARCH_DST)\CArchFileWindows.obj" \ - "$(LIB_ARCH_DST)\CArchLogWindows.obj" \ - "$(LIB_ARCH_DST)\CArchMiscWindows.obj" \ - "$(LIB_ARCH_DST)\CArchMultithreadWindows.obj" \ - "$(LIB_ARCH_DST)\CArchNetworkWinsock.obj" \ - "$(LIB_ARCH_DST)\CArchSleepWindows.obj" \ - "$(LIB_ARCH_DST)\CArchStringWindows.obj" \ - "$(LIB_ARCH_DST)\CArchSystemWindows.obj" \ - "$(LIB_ARCH_DST)\CArchTaskBarWindows.obj" \ - "$(LIB_ARCH_DST)\CArchTimeWindows.obj" \ - "$(LIB_ARCH_DST)\XArchWindows.obj" \ - $(NULL) -LIB_ARCH_INC = \ - /I"lib\common" \ - $(NULL) - -CPP_FILES = $(CPP_FILES) $(LIB_ARCH_CPP) -OBJ_FILES = $(OBJ_FILES) $(LIB_ARCH_OBJ) -LIB_FILES = $(LIB_FILES) $(LIB_ARCH_LIB) - -# Dependency rules -$(LIB_ARCH_OBJ): $(AUTODEP) -!if EXIST($(LIB_ARCH_DST)\deps.mak) -!include $(LIB_ARCH_DST)\deps.mak -!endif - -# Build rules. Use batch-mode rules if possible. -!if DEFINED(_NMAKE_VER) -{$(LIB_ARCH_SRC)\}.cpp{$(LIB_ARCH_DST)\}.obj:: -!else -{$(LIB_ARCH_SRC)\}.cpp{$(LIB_ARCH_DST)\}.obj: -!endif - @$(ECHO) Compile in $(LIB_ARCH_SRC) - -@$(MKDIR) $(LIB_ARCH_DST) 2>NUL: - $(cpp) $(cppdebug) $(cppflags) $(cppvarsmt) /showIncludes \ - $(LIB_ARCH_INC) \ - /Fo$(LIB_ARCH_DST)\ \ - /Fd$(LIB_ARCH_LIB:.lib=.pdb) \ - $< | $(AUTODEP) $(LIB_ARCH_SRC) $(LIB_ARCH_DST) -$(LIB_ARCH_LIB): $(LIB_ARCH_OBJ) - @$(ECHO) Link $(@F) - $(implib) $(ildebug) $(ilflags) \ - /out:$@ \ - $** - $(AUTODEP) $(LIB_ARCH_SRC) $(LIB_ARCH_DST) $(**:.obj=.d) diff --git a/lib/arch/XArch.cpp b/lib/arch/XArch.cpp deleted file mode 100644 index 9dce5283..00000000 --- a/lib/arch/XArch.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "XArch.h" - -// -// XArch -// - -std::string -XArch::what() const throw() -{ - try { - if (m_what.empty() && m_eval != NULL) { - m_what = m_eval->eval(); - } - } - catch (...) { - // ignore - } - return m_what; -} diff --git a/lib/arch/XArch.h b/lib/arch/XArch.h deleted file mode 100644 index 75083649..00000000 --- a/lib/arch/XArch.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef XARCH_H -#define XARCH_H - -#include "common.h" -#include "stdstring.h" - -//! Generic thread exception -/*! -Exceptions derived from this class are used by the multithreading -library to perform stack unwinding when a thread terminates. These -exceptions must always be rethrown by clients when caught. -*/ -class XThread { }; - -//! Thread exception to cancel -/*! -Thrown to cancel a thread. Clients must not throw this type, but -must rethrow it if caught (by XThreadCancel, XThread, or ...). -*/ -class XThreadCancel : public XThread { }; - -/*! -\def RETHROW_XTHREAD -Convenience macro to rethrow an XThread exception but ignore other -exceptions. Put this in your catch (...) handler after necessary -cleanup but before leaving or returning from the handler. -*/ -#define RETHROW_XTHREAD \ - try { throw; } catch (XThread&) { throw; } catch (...) { } - -//! Lazy error message string evaluation -/*! -This class encapsulates platform dependent error string lookup. -Platforms subclass this type, taking an appropriate error code -type in the c'tor and overriding eval() to return the error -string for that error code. -*/ -class XArchEval { -public: - XArchEval() { } - virtual ~XArchEval() { } - - virtual XArchEval* clone() const throw() = 0; - - virtual std::string eval() const throw() = 0; -}; - -//! Generic exception architecture dependent library -class XArch { -public: - XArch(XArchEval* adoptedEvaluator) : m_eval(adoptedEvaluator) { } - XArch(const std::string& msg) : m_eval(NULL), m_what(msg) { } - XArch(const XArch& e) : m_eval(e.m_eval != NULL ? e.m_eval->clone() : NULL), - m_what(e.m_what) { } - ~XArch() { delete m_eval; } - - std::string what() const throw(); - -private: - XArchEval* m_eval; - mutable std::string m_what; -}; - -// Macro to declare XArch derived types -#define XARCH_SUBCLASS(name_, super_) \ -class name_ : public super_ { \ -public: \ - name_(XArchEval* adoptedEvaluator) : super_(adoptedEvaluator) { } \ - name_(const std::string& msg) : super_(msg) { } \ -} - -//! Generic network exception -/*! -Exceptions derived from this class are used by the networking -library to indicate various errors. -*/ -XARCH_SUBCLASS(XArchNetwork, XArch); - -//! Operation was interrupted -XARCH_SUBCLASS(XArchNetworkInterrupted, XArchNetwork); - -//! Network insufficient permission -XARCH_SUBCLASS(XArchNetworkAccess, XArchNetwork); - -//! Network insufficient resources -XARCH_SUBCLASS(XArchNetworkResource, XArchNetwork); - -//! No support for requested network resource/service -XARCH_SUBCLASS(XArchNetworkSupport, XArchNetwork); - -//! Network I/O error -XARCH_SUBCLASS(XArchNetworkIO, XArchNetwork); - -//! Network address is unavailable or not local -XARCH_SUBCLASS(XArchNetworkNoAddress, XArchNetwork); - -//! Network address in use -XARCH_SUBCLASS(XArchNetworkAddressInUse, XArchNetwork); - -//! No route to address -XARCH_SUBCLASS(XArchNetworkNoRoute, XArchNetwork); - -//! Socket not connected -XARCH_SUBCLASS(XArchNetworkNotConnected, XArchNetwork); - -//! Remote read end of socket has closed -XARCH_SUBCLASS(XArchNetworkShutdown, XArchNetwork); - -//! Remote end of socket has disconnected -XARCH_SUBCLASS(XArchNetworkDisconnected, XArchNetwork); - -//! Remote end of socket refused connection -XARCH_SUBCLASS(XArchNetworkConnectionRefused, XArchNetwork); - -//! Remote end of socket is not responding -XARCH_SUBCLASS(XArchNetworkTimedOut, XArchNetwork); - -//! Generic network name lookup erros -XARCH_SUBCLASS(XArchNetworkName, XArchNetwork); - -//! The named host is unknown -XARCH_SUBCLASS(XArchNetworkNameUnknown, XArchNetworkName); - -//! The named host is known but has no address -XARCH_SUBCLASS(XArchNetworkNameNoAddress, XArchNetworkName); - -//! Non-recoverable name server error -XARCH_SUBCLASS(XArchNetworkNameFailure, XArchNetworkName); - -//! Temporary name server error -XARCH_SUBCLASS(XArchNetworkNameUnavailable, XArchNetworkName); - -//! The named host is known but no supported address -XARCH_SUBCLASS(XArchNetworkNameUnsupported, XArchNetworkName); - -//! Generic daemon exception -/*! -Exceptions derived from this class are used by the daemon -library to indicate various errors. -*/ -XARCH_SUBCLASS(XArchDaemon, XArch); - -//! Could not daemonize -XARCH_SUBCLASS(XArchDaemonFailed, XArchDaemon); - -//! Could not install daemon -XARCH_SUBCLASS(XArchDaemonInstallFailed, XArchDaemon); - -//! Could not uninstall daemon -XARCH_SUBCLASS(XArchDaemonUninstallFailed, XArchDaemon); - -//! Attempted to uninstall a daemon that was not installed -XARCH_SUBCLASS(XArchDaemonUninstallNotInstalled, XArchDaemonUninstallFailed); - - -#endif diff --git a/lib/arch/XArchUnix.cpp b/lib/arch/XArchUnix.cpp deleted file mode 100644 index 6f4047d5..00000000 --- a/lib/arch/XArchUnix.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "XArchUnix.h" -#include - -// -// XArchEvalUnix -// - -XArchEval* -XArchEvalUnix::clone() const throw() -{ - return new XArchEvalUnix(m_errno); -} - -std::string -XArchEvalUnix::eval() const throw() -{ - // FIXME -- not thread safe - return strerror(m_errno); -} diff --git a/lib/arch/XArchUnix.h b/lib/arch/XArchUnix.h deleted file mode 100644 index 19e0df4c..00000000 --- a/lib/arch/XArchUnix.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef XARCHUNIX_H -#define XARCHUNIX_H - -#include "XArch.h" - -//! Lazy error message string evaluation for unix -class XArchEvalUnix : public XArchEval { -public: - XArchEvalUnix(int err) : m_errno(err) { } - virtual ~XArchEvalUnix() { } - - // XArchEval overrides - virtual XArchEval* clone() const throw(); - virtual std::string eval() const throw(); - -private: - int m_errno; -}; - -#endif diff --git a/lib/arch/XArchWindows.cpp b/lib/arch/XArchWindows.cpp deleted file mode 100644 index eebd6449..00000000 --- a/lib/arch/XArchWindows.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "XArchWindows.h" -#include "CArchNetworkWinsock.h" - -// -// XArchEvalWindows -// - -XArchEval* -XArchEvalWindows::clone() const throw() -{ - return new XArchEvalWindows(m_errno); -} - -std::string -XArchEvalWindows::eval() const throw() -{ - char* cmsg; - if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_IGNORE_INSERTS | - FORMAT_MESSAGE_FROM_SYSTEM, - 0, - m_errno, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR)&cmsg, - 0, - NULL) == 0) { - cmsg = NULL; - return "Unknown error"; - } - std::string smsg(cmsg); - LocalFree(cmsg); - return smsg; -} - - -// -// XArchEvalWinsock -// - -XArchEval* -XArchEvalWinsock::clone() const throw() -{ - return new XArchEvalWinsock(m_errno); -} - -std::string -XArchEvalWinsock::eval() const throw() -{ - // built-in windows function for looking up error message strings - // may not look up network error messages correctly. we'll have - // to do it ourself. - static const struct { int m_code; const char* m_msg; } s_netErrorCodes[] = { - /* 10004 */{WSAEINTR, "The (blocking) call was canceled via WSACancelBlockingCall"}, - /* 10009 */{WSAEBADF, "Bad file handle"}, - /* 10013 */{WSAEACCES, "The requested address is a broadcast address, but the appropriate flag was not set"}, - /* 10014 */{WSAEFAULT, "WSAEFAULT"}, - /* 10022 */{WSAEINVAL, "WSAEINVAL"}, - /* 10024 */{WSAEMFILE, "No more file descriptors available"}, - /* 10035 */{WSAEWOULDBLOCK, "Socket is marked as non-blocking and no connections are present or the receive operation would block"}, - /* 10036 */{WSAEINPROGRESS, "A blocking Windows Sockets operation is in progress"}, - /* 10037 */{WSAEALREADY, "The asynchronous routine being canceled has already completed"}, - /* 10038 */{WSAENOTSOCK, "At least on descriptor is not a socket"}, - /* 10039 */{WSAEDESTADDRREQ, "A destination address is required"}, - /* 10040 */{WSAEMSGSIZE, "The datagram was too large to fit into the specified buffer and was truncated"}, - /* 10041 */{WSAEPROTOTYPE, "The specified protocol is the wrong type for this socket"}, - /* 10042 */{WSAENOPROTOOPT, "The option is unknown or unsupported"}, - /* 10043 */{WSAEPROTONOSUPPORT,"The specified protocol is not supported"}, - /* 10044 */{WSAESOCKTNOSUPPORT,"The specified socket type is not supported by this address family"}, - /* 10045 */{WSAEOPNOTSUPP, "The referenced socket is not a type that supports that operation"}, - /* 10046 */{WSAEPFNOSUPPORT, "BSD: Protocol family not supported"}, - /* 10047 */{WSAEAFNOSUPPORT, "The specified address family is not supported"}, - /* 10048 */{WSAEADDRINUSE, "The specified address is already in use"}, - /* 10049 */{WSAEADDRNOTAVAIL, "The specified address is not available from the local machine"}, - /* 10050 */{WSAENETDOWN, "The Windows Sockets implementation has detected that the network subsystem has failed"}, - /* 10051 */{WSAENETUNREACH, "The network can't be reached from this hos at this time"}, - /* 10052 */{WSAENETRESET, "The connection must be reset because the Windows Sockets implementation dropped it"}, - /* 10053 */{WSAECONNABORTED, "The virtual circuit was aborted due to timeout or other failure"}, - /* 10054 */{WSAECONNRESET, "The virtual circuit was reset by the remote side"}, - /* 10055 */{WSAENOBUFS, "No buffer space is available or a buffer deadlock has occured. The socket cannot be created"}, - /* 10056 */{WSAEISCONN, "The socket is already connected"}, - /* 10057 */{WSAENOTCONN, "The socket is not connected"}, - /* 10058 */{WSAESHUTDOWN, "The socket has been shutdown"}, - /* 10059 */{WSAETOOMANYREFS, "BSD: Too many references"}, - /* 10060 */{WSAETIMEDOUT, "Attempt to connect timed out without establishing a connection"}, - /* 10061 */{WSAECONNREFUSED, "The attempt to connect was forcefully rejected"}, - /* 10062 */{WSAELOOP, "Undocumented WinSock error code used in BSD"}, - /* 10063 */{WSAENAMETOOLONG, "Undocumented WinSock error code used in BSD"}, - /* 10064 */{WSAEHOSTDOWN, "Undocumented WinSock error code used in BSD"}, - /* 10065 */{WSAEHOSTUNREACH, "No route to host"}, - /* 10066 */{WSAENOTEMPTY, "Undocumented WinSock error code"}, - /* 10067 */{WSAEPROCLIM, "Undocumented WinSock error code"}, - /* 10068 */{WSAEUSERS, "Undocumented WinSock error code"}, - /* 10069 */{WSAEDQUOT, "Undocumented WinSock error code"}, - /* 10070 */{WSAESTALE, "Undocumented WinSock error code"}, - /* 10071 */{WSAEREMOTE, "Undocumented WinSock error code"}, - /* 10091 */{WSASYSNOTREADY, "Underlying network subsytem is not ready for network communication"}, - /* 10092 */{WSAVERNOTSUPPORTED, "The version of WinSock API support requested is not provided in this implementation"}, - /* 10093 */{WSANOTINITIALISED, "WinSock subsystem not properly initialized"}, - /* 10101 */{WSAEDISCON, "Virtual circuit has gracefully terminated connection"}, - /* 11001 */{WSAHOST_NOT_FOUND, "The specified host is unknown"}, - /* 11002 */{WSATRY_AGAIN, "A temporary error occurred on an authoritative name server"}, - /* 11003 */{WSANO_RECOVERY, "A non-recoverable name server error occurred"}, - /* 11004 */{WSANO_DATA, "The requested name is valid but does not have an IP address"}, - /* end */{0, NULL} - }; - - for (unsigned int i = 0; s_netErrorCodes[i].m_code != 0; ++i) { - if (s_netErrorCodes[i].m_code == m_errno) { - return s_netErrorCodes[i].m_msg; - } - } - return "Unknown error"; -} diff --git a/lib/arch/XArchWindows.h b/lib/arch/XArchWindows.h deleted file mode 100644 index 56c24007..00000000 --- a/lib/arch/XArchWindows.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef XARCHWINDOWS_H -#define XARCHWINDOWS_H - -#define WIN32_LEAN_AND_MEAN - -#include "XArch.h" -#include - -//! Lazy error message string evaluation for windows -class XArchEvalWindows : public XArchEval { -public: - XArchEvalWindows() : m_errno(GetLastError()) { } - XArchEvalWindows(DWORD err) : m_errno(err) { } - virtual ~XArchEvalWindows() { } - - // XArchEval overrides - virtual XArchEval* clone() const throw(); - virtual std::string eval() const throw(); - -private: - DWORD m_errno; -}; - -//! Lazy error message string evaluation for winsock -class XArchEvalWinsock : public XArchEval { -public: - XArchEvalWinsock(int err) : m_errno(err) { } - virtual ~XArchEvalWinsock() { } - - // XArchEval overrides - virtual XArchEval* clone() const throw(); - virtual std::string eval() const throw(); - -private: - int m_errno; -}; - -#endif diff --git a/lib/arch/vsnprintf.cpp b/lib/arch/vsnprintf.cpp deleted file mode 100644 index 10800ec7..00000000 --- a/lib/arch/vsnprintf.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#if HAVE_VSNPRINTF - -#if !defined(ARCH_VSNPRINTF) -# define ARCH_VSNPRINTF vsnprintf -#endif - -int -ARCH_STRING::vsnprintf(char* str, int size, const char* fmt, va_list ap) -{ - int n = ::ARCH_VSNPRINTF(str, size, fmt, ap); - if (n > size) { - n = -1; - } - return n; -} - -#elif SYSAPI_UNIX // !HAVE_VSNPRINTF - -#include - -int -ARCH_STRING::vsnprintf(char* str, int size, const char* fmt, va_list ap) -{ - static FILE* bitbucket = fopen("/dev/null", "w"); - if (bitbucket == NULL) { - // uh oh - if (size > 0) { - str[0] = '\0'; - } - return 0; - } - else { - // count the characters using the bitbucket - int n = vfprintf(bitbucket, fmt, ap); - if (n + 1 <= size) { - // it'll fit so print it into str - vsprintf(str, fmt, ap); - } - return n; - } -} - -#else // !HAVE_VSNPRINTF && !SYSAPI_UNIX - -#error vsnprintf not implemented - -#endif // !HAVE_VSNPRINTF diff --git a/lib/base/CEvent.cpp b/lib/base/CEvent.cpp deleted file mode 100644 index bfdf88ed..00000000 --- a/lib/base/CEvent.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CEvent.h" -#include "CEventQueue.h" - -// -// CEvent -// - -CEvent::CEvent() : - m_type(kUnknown), - m_target(NULL), - m_data(NULL), - m_flags(0) -{ - // do nothing -} - -CEvent::CEvent(Type type, void* target, void* data, Flags flags) : - m_type(type), - m_target(target), - m_data(data), - m_flags(flags) -{ - // do nothing -} - -CEvent::Type -CEvent::getType() const -{ - return m_type; -} - -void* -CEvent::getTarget() const -{ - return m_target; -} - -void* -CEvent::getData() const -{ - return m_data; -} - -CEvent::Flags -CEvent::getFlags() const -{ - return m_flags; -} - -CEvent::Type -CEvent::registerType(const char* name) -{ - return EVENTQUEUE->registerType(name); -} - -CEvent::Type -CEvent::registerTypeOnce(Type& type, const char* name) -{ - return EVENTQUEUE->registerTypeOnce(type, name); -} - -const char* -CEvent::getTypeName(Type type) -{ - return EVENTQUEUE->getTypeName(type); -} - -void -CEvent::deleteData(const CEvent& event) -{ - switch (event.getType()) { - case kUnknown: - case kQuit: - case kSystem: - case kTimer: - break; - - default: - if ((event.getFlags() & kDontFreeData) == 0) { - free(event.getData()); - } - break; - } -} diff --git a/lib/base/CEvent.h b/lib/base/CEvent.h deleted file mode 100644 index 8b637cef..00000000 --- a/lib/base/CEvent.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CEVENT_H -#define CEVENT_H - -#include "BasicTypes.h" -#include "stdmap.h" - -//! Event -/*! -A \c CEvent holds an event type and a pointer to event data. -*/ -class CEvent { -public: - typedef UInt32 Type; - enum { - kUnknown, //!< The event type is unknown - kQuit, //!< The quit event - kSystem, //!< The data points to a system event type - kTimer, //!< The data points to timer info - kLast //!< Must be last - }; - - typedef UInt32 Flags; - enum { - kNone = 0x00, //!< No flags - kDeliverImmediately = 0x01, //!< Dispatch and free event immediately - kDontFreeData = 0x02 //!< Don't free data in deleteData - }; - - CEvent(); - - //! Create \c CEvent with data - /*! - The \p type must have been registered using \c registerType(). - The \p data must be POD (plain old data) allocated by malloc(), - which means it cannot have a constructor, destructor or be - composed of any types that do. \p target is the intended - recipient of the event. \p flags is any combination of \c Flags. - */ - CEvent(Type type, void* target = NULL, void* data = NULL, - UInt32 flags = kNone); - - //! @name manipulators - //@{ - - //! Creates a new event type - /*! - Returns a unique event type id. - */ - static Type registerType(const char* name); - - //! Creates a new event type - /*! - If \p type contains \c kUnknown then it is set to a unique event - type id otherwise it is left alone. The final value of \p type - is returned. - */ - static Type registerTypeOnce(Type& type, const char* name); - - //! Get name for event - /*! - Returns the name for the event \p type. This is primarily for - debugging. - */ - static const char* getTypeName(Type type); - - //! Release event data - /*! - Deletes event data for the given event (using free()). - */ - static void deleteData(const CEvent&); - - //@} - //! @name accessors - //@{ - - //! Get event type - /*! - Returns the event type. - */ - Type getType() const; - - //! Get the event target - /*! - Returns the event target. - */ - void* getTarget() const; - - //! Get the event data - /*! - Returns the event data. - */ - void* getData() const; - - //! Get event flags - /*! - Returns the event flags. - */ - Flags getFlags() const; - - //@} - -private: - Type m_type; - void* m_target; - void* m_data; - Flags m_flags; -}; - -#endif diff --git a/lib/base/CEventQueue.cpp b/lib/base/CEventQueue.cpp deleted file mode 100644 index d0a93391..00000000 --- a/lib/base/CEventQueue.cpp +++ /dev/null @@ -1,526 +0,0 @@ -;/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CEventQueue.h" -#include "CLog.h" -#include "CSimpleEventQueueBuffer.h" -#include "CStopwatch.h" -#include "IEventJob.h" -#include "CArch.h" - -// interrupt handler. this just adds a quit event to the queue. -static -void -interrupt(CArch::ESignal, void*) -{ - EVENTQUEUE->addEvent(CEvent(CEvent::kQuit)); -} - - -// -// CEventQueue -// - -CEventQueue::CEventQueue() : - m_nextType(CEvent::kLast) -{ - setInstance(this); - m_mutex = ARCH->newMutex(); - ARCH->setSignalHandler(CArch::kINTERRUPT, &interrupt, NULL); - ARCH->setSignalHandler(CArch::kTERMINATE, &interrupt, NULL); - m_buffer = new CSimpleEventQueueBuffer; -} - -CEventQueue::~CEventQueue() -{ - delete m_buffer; - ARCH->setSignalHandler(CArch::kINTERRUPT, NULL, NULL); - ARCH->setSignalHandler(CArch::kTERMINATE, NULL, NULL); - ARCH->closeMutex(m_mutex); - setInstance(NULL); -} - -CEvent::Type -CEventQueue::registerType(const char* name) -{ - CArchMutexLock lock(m_mutex); - m_typeMap.insert(std::make_pair(m_nextType, name)); - LOG((CLOG_DEBUG1 "registered event type %s as %d", name, m_nextType)); - return m_nextType++; -} - -CEvent::Type -CEventQueue::registerTypeOnce(CEvent::Type& type, const char* name) -{ - CArchMutexLock lock(m_mutex); - if (type == CEvent::kUnknown) { - m_typeMap.insert(std::make_pair(m_nextType, name)); - LOG((CLOG_DEBUG1 "registered event type %s as %d", name, m_nextType)); - type = m_nextType++; - } - return type; -} - -const char* -CEventQueue::getTypeName(CEvent::Type type) -{ - switch (type) { - case CEvent::kUnknown: - return "nil"; - - case CEvent::kQuit: - return "quit"; - - case CEvent::kSystem: - return "system"; - - case CEvent::kTimer: - return "timer"; - - default: - CTypeMap::const_iterator i = m_typeMap.find(type); - if (i == m_typeMap.end()) { - return ""; - } - else { - return i->second; - } - } -} - -void -CEventQueue::adoptBuffer(IEventQueueBuffer* buffer) -{ - CArchMutexLock lock(m_mutex); - - // discard old buffer and old events - delete m_buffer; - for (CEventTable::iterator i = m_events.begin(); i != m_events.end(); ++i) { - CEvent::deleteData(i->second); - } - m_events.clear(); - m_oldEventIDs.clear(); - - // use new buffer - m_buffer = buffer; - if (m_buffer == NULL) { - m_buffer = new CSimpleEventQueueBuffer; - } -} - -bool -CEventQueue::getEvent(CEvent& event, double timeout) -{ - CStopwatch timer(true); -retry: - // if no events are waiting then handle timers and then wait - while (m_buffer->isEmpty()) { - // handle timers first - if (hasTimerExpired(event)) { - return true; - } - - // get time remaining in timeout - double timeLeft = timeout - timer.getTime(); - if (timeout >= 0.0 && timeLeft <= 0.0) { - return false; - } - - // get time until next timer expires. if there is a timer - // and it'll expire before the client's timeout then use - // that duration for our timeout instead. - double timerTimeout = getNextTimerTimeout(); - if (timeout < 0.0 || (timerTimeout >= 0.0 && timerTimeout < timeLeft)) { - timeLeft = timerTimeout; - } - - // wait for an event - m_buffer->waitForEvent(timeLeft); - } - - // get the event - UInt32 dataID; - IEventQueueBuffer::Type type = m_buffer->getEvent(event, dataID); - switch (type) { - case IEventQueueBuffer::kNone: - if (timeout < 0.0 || timeout <= timer.getTime()) { - // don't want to fail if client isn't expecting that - // so if getEvent() fails with an infinite timeout - // then just try getting another event. - goto retry; - } - return false; - - case IEventQueueBuffer::kSystem: - return true; - - case IEventQueueBuffer::kUser: - { - CArchMutexLock lock(m_mutex); - event = removeEvent(dataID); - return true; - } - - default: - assert(0 && "invalid event type"); - return false; - } -} - -bool -CEventQueue::dispatchEvent(const CEvent& event) -{ - void* target = event.getTarget(); - IEventJob* job = getHandler(event.getType(), target); - if (job == NULL) { - job = getHandler(CEvent::kUnknown, target); - } - if (job != NULL) { - job->run(event); - return true; - } - return false; -} - -void -CEventQueue::addEvent(const CEvent& event) -{ - // discard bogus event types - switch (event.getType()) { - case CEvent::kUnknown: - case CEvent::kSystem: - case CEvent::kTimer: - return; - - default: - break; - } - - if ((event.getFlags() & CEvent::kDeliverImmediately) != 0) { - dispatchEvent(event); - CEvent::deleteData(event); - } - else { - CArchMutexLock lock(m_mutex); - - // store the event's data locally - UInt32 eventID = saveEvent(event); - - // add it - if (!m_buffer->addEvent(eventID)) { - // failed to send event - removeEvent(eventID); - CEvent::deleteData(event); - } - } -} - -CEventQueueTimer* -CEventQueue::newTimer(double duration, void* target) -{ - assert(duration > 0.0); - - CEventQueueTimer* timer = m_buffer->newTimer(duration, false); - if (target == NULL) { - target = timer; - } - CArchMutexLock lock(m_mutex); - m_timers.insert(timer); - // initial duration is requested duration plus whatever's on - // the clock currently because the latter will be subtracted - // the next time we check for timers. - m_timerQueue.push(CTimer(timer, duration, - duration + m_time.getTime(), target, false)); - return timer; -} - -CEventQueueTimer* -CEventQueue::newOneShotTimer(double duration, void* target) -{ - assert(duration > 0.0); - - CEventQueueTimer* timer = m_buffer->newTimer(duration, true); - if (target == NULL) { - target = timer; - } - CArchMutexLock lock(m_mutex); - m_timers.insert(timer); - // initial duration is requested duration plus whatever's on - // the clock currently because the latter will be subtracted - // the next time we check for timers. - m_timerQueue.push(CTimer(timer, duration, - duration + m_time.getTime(), target, true)); - return timer; -} - -void -CEventQueue::deleteTimer(CEventQueueTimer* timer) -{ - CArchMutexLock lock(m_mutex); - for (CTimerQueue::iterator index = m_timerQueue.begin(); - index != m_timerQueue.end(); ++index) { - if (index->getTimer() == timer) { - m_timerQueue.erase(index); - break; - } - } - CTimers::iterator index = m_timers.find(timer); - if (index != m_timers.end()) { - m_timers.erase(index); - } - m_buffer->deleteTimer(timer); -} - -void -CEventQueue::adoptHandler(CEvent::Type type, void* target, IEventJob* handler) -{ - CArchMutexLock lock(m_mutex); - IEventJob*& job = m_handlers[target][type]; - delete job; - job = handler; -} - -void -CEventQueue::removeHandler(CEvent::Type type, void* target) -{ - IEventJob* handler = NULL; - { - CArchMutexLock lock(m_mutex); - CHandlerTable::iterator index = m_handlers.find(target); - if (index != m_handlers.end()) { - CTypeHandlerTable& typeHandlers = index->second; - CTypeHandlerTable::iterator index2 = typeHandlers.find(type); - if (index2 != typeHandlers.end()) { - handler = index2->second; - typeHandlers.erase(index2); - } - } - } - delete handler; -} - -void -CEventQueue::removeHandlers(void* target) -{ - std::vector handlers; - { - CArchMutexLock lock(m_mutex); - CHandlerTable::iterator index = m_handlers.find(target); - if (index != m_handlers.end()) { - // copy to handlers array and clear table for target - CTypeHandlerTable& typeHandlers = index->second; - for (CTypeHandlerTable::iterator index2 = typeHandlers.begin(); - index2 != typeHandlers.end(); ++index2) { - handlers.push_back(index2->second); - } - typeHandlers.clear(); - } - } - - // delete handlers - for (std::vector::iterator index = handlers.begin(); - index != handlers.end(); ++index) { - delete *index; - } -} - -bool -CEventQueue::isEmpty() const -{ - return (m_buffer->isEmpty() && getNextTimerTimeout() != 0.0); -} - -IEventJob* -CEventQueue::getHandler(CEvent::Type type, void* target) const -{ - CArchMutexLock lock(m_mutex); - CHandlerTable::const_iterator index = m_handlers.find(target); - if (index != m_handlers.end()) { - const CTypeHandlerTable& typeHandlers = index->second; - CTypeHandlerTable::const_iterator index2 = typeHandlers.find(type); - if (index2 != typeHandlers.end()) { - return index2->second; - } - } - return NULL; -} - -UInt32 -CEventQueue::saveEvent(const CEvent& event) -{ - // choose id - UInt32 id; - if (!m_oldEventIDs.empty()) { - // reuse an id - id = m_oldEventIDs.back(); - m_oldEventIDs.pop_back(); - } - else { - // make a new id - id = static_cast(m_events.size()); - } - - // save data - m_events[id] = event; - return id; -} - -CEvent -CEventQueue::removeEvent(UInt32 eventID) -{ - // look up id - CEventTable::iterator index = m_events.find(eventID); - if (index == m_events.end()) { - return CEvent(); - } - - // get data - CEvent event = index->second; - m_events.erase(index); - - // save old id for reuse - m_oldEventIDs.push_back(eventID); - - return event; -} - -bool -CEventQueue::hasTimerExpired(CEvent& event) -{ - // return true if there's a timer in the timer priority queue that - // has expired. if returning true then fill in event appropriately - // and reset and reinsert the timer. - if (m_timerQueue.empty()) { - return false; - } - - // get time elapsed since last check - const double time = m_time.getTime(); - m_time.reset(); - - // countdown elapsed time - for (CTimerQueue::iterator index = m_timerQueue.begin(); - index != m_timerQueue.end(); ++index) { - (*index) -= time; - } - - // done if no timers are expired - if (m_timerQueue.top() > 0.0) { - return false; - } - - // remove timer from queue - CTimer timer = m_timerQueue.top(); - m_timerQueue.pop(); - - // prepare event and reset the timer's clock - timer.fillEvent(m_timerEvent); - event = CEvent(CEvent::kTimer, timer.getTarget(), &m_timerEvent); - timer.reset(); - - // reinsert timer into queue if it's not a one-shot - if (!timer.isOneShot()) { - m_timerQueue.push(timer); - } - - return true; -} - -double -CEventQueue::getNextTimerTimeout() const -{ - // return -1 if no timers, 0 if the top timer has expired, otherwise - // the time until the top timer in the timer priority queue will - // expire. - if (m_timerQueue.empty()) { - return -1.0; - } - if (m_timerQueue.top() <= 0.0) { - return 0.0; - } - return m_timerQueue.top(); -} - - -// -// CEventQueue::CTimer -// - -CEventQueue::CTimer::CTimer(CEventQueueTimer* timer, double timeout, - double initialTime, void* target, bool oneShot) : - m_timer(timer), - m_timeout(timeout), - m_target(target), - m_oneShot(oneShot), - m_time(initialTime) -{ - assert(m_timeout > 0.0); -} - -CEventQueue::CTimer::~CTimer() -{ - // do nothing -} - -void -CEventQueue::CTimer::reset() -{ - m_time = m_timeout; -} - -CEventQueue::CTimer& -CEventQueue::CTimer::operator-=(double dt) -{ - m_time -= dt; - return *this; -} - -CEventQueue::CTimer::operator double() const -{ - return m_time; -} - -bool -CEventQueue::CTimer::isOneShot() const -{ - return m_oneShot; -} - -CEventQueueTimer* -CEventQueue::CTimer::getTimer() const -{ - return m_timer; -} - -void* -CEventQueue::CTimer::getTarget() const -{ - return m_target; -} - -void -CEventQueue::CTimer::fillEvent(CTimerEvent& event) const -{ - event.m_timer = m_timer; - event.m_count = 0; - if (m_time <= 0.0) { - event.m_count = static_cast((m_timeout - m_time) / m_timeout); - } -} - -bool -CEventQueue::CTimer::operator<(const CTimer& t) const -{ - return m_time < t.m_time; -} diff --git a/lib/base/CEventQueue.h b/lib/base/CEventQueue.h deleted file mode 100644 index a63c7b16..00000000 --- a/lib/base/CEventQueue.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CEVENTQUEUE_H -#define CEVENTQUEUE_H - -#include "IEventQueue.h" -#include "CEvent.h" -#include "CPriorityQueue.h" -#include "CStopwatch.h" -#include "IArchMultithread.h" -#include "stdmap.h" -#include "stdset.h" - -//! Event queue -/*! -An event queue that implements the platform independent parts and -delegates the platform dependent parts to a subclass. -*/ -class CEventQueue : public IEventQueue { -public: - CEventQueue(); - virtual ~CEventQueue(); - - // IEventQueue overrides - virtual void adoptBuffer(IEventQueueBuffer*); - virtual bool getEvent(CEvent& event, double timeout = -1.0); - virtual bool dispatchEvent(const CEvent& event); - virtual void addEvent(const CEvent& event); - virtual CEventQueueTimer* - newTimer(double duration, void* target); - virtual CEventQueueTimer* - newOneShotTimer(double duration, void* target); - virtual void deleteTimer(CEventQueueTimer*); - virtual void adoptHandler(CEvent::Type type, - void* target, IEventJob* handler); - virtual void removeHandler(CEvent::Type type, void* target); - virtual void removeHandlers(void* target); - virtual CEvent::Type - registerType(const char* name); - virtual CEvent::Type - registerTypeOnce(CEvent::Type& type, const char* name); - virtual bool isEmpty() const; - virtual IEventJob* getHandler(CEvent::Type type, void* target) const; - virtual const char* getTypeName(CEvent::Type type); - -private: - UInt32 saveEvent(const CEvent& event); - CEvent removeEvent(UInt32 eventID); - bool hasTimerExpired(CEvent& event); - double getNextTimerTimeout() const; - -private: - class CTimer { - public: - CTimer(CEventQueueTimer*, double timeout, double initialTime, - void* target, bool oneShot); - ~CTimer(); - - void reset(); - - CTimer& operator-=(double); - - operator double() const; - - bool isOneShot() const; - CEventQueueTimer* - getTimer() const; - void* getTarget() const; - void fillEvent(CTimerEvent&) const; - - bool operator<(const CTimer&) const; - - private: - CEventQueueTimer* m_timer; - double m_timeout; - void* m_target; - bool m_oneShot; - double m_time; - }; - typedef std::set CTimers; - typedef CPriorityQueue CTimerQueue; - typedef std::map CEventTable; - typedef std::vector CEventIDList; - typedef std::map CTypeMap; - typedef std::map CTypeHandlerTable; - typedef std::map CHandlerTable; - - CArchMutex m_mutex; - - // registered events - CEvent::Type m_nextType; - CTypeMap m_typeMap; - - // buffer of events - IEventQueueBuffer* m_buffer; - - // saved events - CEventTable m_events; - CEventIDList m_oldEventIDs; - - // timers - CStopwatch m_time; - CTimers m_timers; - CTimerQueue m_timerQueue; - CTimerEvent m_timerEvent; - - // event handlers - CHandlerTable m_handlers; -}; - -#endif diff --git a/lib/base/CFunctionEventJob.cpp b/lib/base/CFunctionEventJob.cpp deleted file mode 100644 index 5afdc988..00000000 --- a/lib/base/CFunctionEventJob.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CFunctionEventJob.h" - -// -// CFunctionEventJob -// - -CFunctionEventJob::CFunctionEventJob( - void (*func)(const CEvent&, void*), void* arg) : - m_func(func), - m_arg(arg) -{ - // do nothing -} - -CFunctionEventJob::~CFunctionEventJob() -{ - // do nothing -} - -void -CFunctionEventJob::run(const CEvent& event) -{ - if (m_func != NULL) { - m_func(event, m_arg); - } -} diff --git a/lib/base/CFunctionEventJob.h b/lib/base/CFunctionEventJob.h deleted file mode 100644 index 517b9c45..00000000 --- a/lib/base/CFunctionEventJob.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CFUNCTIONEVENTJOB_H -#define CFUNCTIONEVENTJOB_H - -#include "IEventJob.h" - -//! Use a function as an event job -/*! -An event job class that invokes a function. -*/ -class CFunctionEventJob : public IEventJob { -public: - //! run() invokes \c func(arg) - CFunctionEventJob(void (*func)(const CEvent&, void*), void* arg = NULL); - virtual ~CFunctionEventJob(); - - // IEventJob overrides - virtual void run(const CEvent&); - -private: - void (*m_func)(const CEvent&, void*); - void* m_arg; -}; - -#endif diff --git a/lib/base/CFunctionJob.cpp b/lib/base/CFunctionJob.cpp deleted file mode 100644 index bc16c509..00000000 --- a/lib/base/CFunctionJob.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CFunctionJob.h" - -// -// CFunctionJob -// - -CFunctionJob::CFunctionJob(void (*func)(void*), void* arg) : - m_func(func), - m_arg(arg) -{ - // do nothing -} - -CFunctionJob::~CFunctionJob() -{ - // do nothing -} - -void -CFunctionJob::run() -{ - if (m_func != NULL) { - m_func(m_arg); - } -} diff --git a/lib/base/CFunctionJob.h b/lib/base/CFunctionJob.h deleted file mode 100644 index e30bbfa2..00000000 --- a/lib/base/CFunctionJob.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CFUNCTIONJOB_H -#define CFUNCTIONJOB_H - -#include "IJob.h" - -//! Use a function as a job -/*! -A job class that invokes a function. -*/ -class CFunctionJob : public IJob { -public: - //! run() invokes \c func(arg) - CFunctionJob(void (*func)(void*), void* arg = NULL); - virtual ~CFunctionJob(); - - // IJob overrides - virtual void run(); - -private: - void (*m_func)(void*); - void* m_arg; -}; - -#endif diff --git a/lib/base/CLog.cpp b/lib/base/CLog.cpp deleted file mode 100644 index 7c73ac87..00000000 --- a/lib/base/CLog.cpp +++ /dev/null @@ -1,293 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CLog.h" -#include "CString.h" -#include "CStringUtil.h" -#include "LogOutputters.h" -#include "CArch.h" -#include "Version.h" -#include -#include - -// names of priorities -static const char* g_priority[] = { - "FATAL", - "ERROR", - "WARNING", - "NOTE", - "INFO", - "DEBUG", - "DEBUG1", - "DEBUG2" - }; - -// number of priorities -static const int g_numPriority = (int)(sizeof(g_priority) / - sizeof(g_priority[0])); - -// the default priority -#if defined(NDEBUG) -static const int g_defaultMaxPriority = 4; -#else -static const int g_defaultMaxPriority = 5; -#endif - -// length of longest string in g_priority -static const int g_maxPriorityLength = 7; - -// length of suffix string (": ") -static const int g_prioritySuffixLength = 2; - -// amount of padded required to fill in the priority prefix -static const int g_priorityPad = g_maxPriorityLength + - g_prioritySuffixLength; - - -// -// CLog -// - -CLog* CLog::s_log = NULL; - -CLog::CLog() -{ - assert(s_log == NULL); - - // create mutex for multithread safe operation - m_mutex = ARCH->newMutex(); - - // other initalization - m_maxPriority = g_defaultMaxPriority; - m_maxNewlineLength = 0; - insert(new CConsoleLogOutputter); -} - -CLog::~CLog() -{ - // clean up - for (COutputterList::iterator index = m_outputters.begin(); - index != m_outputters.end(); ++index) { - delete *index; - } - for (COutputterList::iterator index = m_alwaysOutputters.begin(); - index != m_alwaysOutputters.end(); ++index) { - delete *index; - } - ARCH->closeMutex(m_mutex); - s_log = NULL; -} - -CLog* -CLog::getInstance() -{ - // note -- not thread safe; client must initialize log safely - if (s_log == NULL) { - s_log = new CLog; - } - return s_log; -} - -void -CLog::print(const char* file, int line, const char* fmt, ...) const -{ - // check if fmt begins with a priority argument - int priority = 4; - if (fmt[0] == '%' && fmt[1] == 'z') { - priority = fmt[2] - '\060'; - fmt += 3; - } - - // done if below priority threshold - if (priority > getFilter()) { - return; - } - - // compute prefix padding length - char stack[1024]; - int pPad = g_priorityPad; - if (file != NULL) { - sprintf(stack, "%d", line); - pPad += strlen(file) + 1 /* comma */ + - strlen(stack) + 1 /* colon */ + 1 /* space */; - } - - // compute suffix padding length - int sPad = m_maxNewlineLength; - - // print to buffer, leaving space for a newline at the end and prefix - // at the beginning. - char* buffer = stack; - int len = (int)(sizeof(stack) / sizeof(stack[0])); - while (true) { - // try printing into the buffer - va_list args; - va_start(args, fmt); - int n = ARCH->vsnprintf(buffer + pPad, len - pPad - sPad, fmt, args); - va_end(args); - - // if the buffer wasn't big enough then make it bigger and try again - if (n < 0 || n > (int)len) { - if (buffer != stack) { - delete[] buffer; - } - len *= 2; - buffer = new char[len]; - } - - // if the buffer was big enough then continue - else { - break; - } - } - - // print the prefix to the buffer. leave space for priority label. - char* message = buffer; - if (file != NULL) { - sprintf(buffer + g_priorityPad, "%s,%d:", file, line); - buffer[pPad - 1] = ' '; - - // discard file and line if priority < 0 - if (priority < 0) { - message += pPad - g_priorityPad; - } - } - - // output buffer - output(priority, message); - - // clean up - if (buffer != stack) { - delete[] buffer; - } -} - -void -CLog::insert(ILogOutputter* outputter, bool alwaysAtHead) -{ - assert(outputter != NULL); - assert(outputter->getNewline() != NULL); - - CArchMutexLock lock(m_mutex); - if (alwaysAtHead) { - m_alwaysOutputters.push_front(outputter); - } - else { - m_outputters.push_front(outputter); - } - int newlineLength = strlen(outputter->getNewline()); - if (newlineLength > m_maxNewlineLength) { - m_maxNewlineLength = newlineLength; - } - outputter->open(kAppVersion); - outputter->show(false); -} - -void -CLog::remove(ILogOutputter* outputter) -{ - CArchMutexLock lock(m_mutex); - m_outputters.remove(outputter); - m_alwaysOutputters.remove(outputter); -} - -void -CLog::pop_front(bool alwaysAtHead) -{ - CArchMutexLock lock(m_mutex); - COutputterList* list = alwaysAtHead ? &m_alwaysOutputters : &m_outputters; - if (!list->empty()) { - delete list->front(); - list->pop_front(); - } -} - -bool -CLog::setFilter(const char* maxPriority) -{ - if (maxPriority != NULL) { - for (int i = 0; i < g_numPriority; ++i) { - if (strcmp(maxPriority, g_priority[i]) == 0) { - setFilter(i); - return true; - } - } - return false; - } - return true; -} - -void -CLog::setFilter(int maxPriority) -{ - CArchMutexLock lock(m_mutex); - m_maxPriority = maxPriority; -} - -int -CLog::getFilter() const -{ - CArchMutexLock lock(m_mutex); - return m_maxPriority; -} - -void -CLog::output(int priority, char* msg) const -{ - assert(priority >= -1 && priority < g_numPriority); - assert(msg != NULL); - - // insert priority label - int n = -g_prioritySuffixLength; - if (priority >= 0) { - n = strlen(g_priority[priority]); - strcpy(msg + g_maxPriorityLength - n, g_priority[priority]); - msg[g_maxPriorityLength + 0] = ':'; - msg[g_maxPriorityLength + 1] = ' '; - msg[g_maxPriorityLength + 1] = ' '; - } - - // find end of message - char* end = msg + g_priorityPad + strlen(msg + g_priorityPad); - - // write to each outputter - CArchMutexLock lock(m_mutex); - for (COutputterList::const_iterator index = m_alwaysOutputters.begin(); - index != m_alwaysOutputters.end(); - ++index) { - // get outputter - ILogOutputter* outputter = *index; - - // put an appropriate newline at the end - strcpy(end, outputter->getNewline()); - - // write message - outputter->write(static_cast(priority), - msg + g_maxPriorityLength - n); - } - for (COutputterList::const_iterator index = m_outputters.begin(); - index != m_outputters.end(); ++index) { - // get outputter - ILogOutputter* outputter = *index; - - // put an appropriate newline at the end - strcpy(end, outputter->getNewline()); - - // write message and break out of loop if it returns false - if (!outputter->write(static_cast(priority), - msg + g_maxPriorityLength - n)) { - break; - } - } -} diff --git a/lib/base/CLog.h b/lib/base/CLog.h deleted file mode 100644 index 391480e2..00000000 --- a/lib/base/CLog.h +++ /dev/null @@ -1,202 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CLOG_H -#define CLOG_H - -#include "common.h" -#include "IArchMultithread.h" -#include "stdlist.h" -#include - -#define CLOG (CLog::getInstance()) - -class ILogOutputter; - -//! Logging facility -/*! -The logging class; all console output should go through this class. -It supports multithread safe operation, several message priority levels, -filtering by priority, and output redirection. The macros LOG() and -LOGC() provide convenient access. -*/ -class CLog { -public: - //! Log levels - /*! - The logging priority levels in order of highest to lowest priority. - */ - enum ELevel { - kFATAL, //!< For fatal errors - kERROR, //!< For serious errors - kWARNING, //!< For minor errors and warnings - kNOTE, //!< For messages about notable events - kINFO, //!< For informational messages - kDEBUG, //!< For important debugging messages - kDEBUG1, //!< For more detailed debugging messages - kDEBUG2 //!< For even more detailed debugging messages - }; - - ~CLog(); - - //! @name manipulators - //@{ - - //! Add an outputter to the head of the list - /*! - Inserts an outputter to the head of the outputter list. When the - logger writes a message, it goes to the outputter at the head of - the outputter list. If that outputter's \c write() method returns - true then it also goes to the next outputter, as so on until an - outputter returns false or there are no more outputters. Outputters - still in the outputter list when the log is destroyed will be - deleted. If \c alwaysAtHead is true then the outputter is always - called before all outputters with \c alwaysAtHead false and the - return value of the outputter is ignored. - - By default, the logger has one outputter installed which writes to - the console. - */ - void insert(ILogOutputter* adopted, - bool alwaysAtHead = false); - - //! Remove an outputter from the list - /*! - Removes the first occurrence of the given outputter from the - outputter list. It does nothing if the outputter is not in the - list. The outputter is not deleted. - */ - void remove(ILogOutputter* orphaned); - - //! Remove the outputter from the head of the list - /*! - Removes and deletes the outputter at the head of the outputter list. - This does nothing if the outputter list is empty. Only removes - outputters that were inserted with the matching \c alwaysAtHead. - */ - void pop_front(bool alwaysAtHead = false); - - //! Set the minimum priority filter. - /*! - Set the filter. Messages below this priority are discarded. - The default priority is 4 (INFO) (unless built without NDEBUG - in which case it's 5 (DEBUG)). setFilter(const char*) returns - true if the priority \c name was recognized; if \c name is NULL - then it simply returns true. - */ - bool setFilter(const char* name); - void setFilter(int); - - //@} - //! @name accessors - //@{ - - //! Print a log message - /*! - Print a log message using the printf-like \c format and arguments - preceded by the filename and line number. If \c file is NULL then - neither the file nor the line are printed. - */ - void print(const char* file, int line, - const char* format, ...) const; - - //! Get the minimum priority level. - int getFilter() const; - - //! Get the singleton instance of the log - static CLog* getInstance(); - - //@} - -private: - CLog(); - - void output(int priority, char* msg) const; - -private: - typedef std::list COutputterList; - - static CLog* s_log; - - CArchMutex m_mutex; - COutputterList m_outputters; - COutputterList m_alwaysOutputters; - int m_maxNewlineLength; - int m_maxPriority; -}; - -/*! -\def LOG(arg) -Write to the log. Because macros cannot accept variable arguments, this -should be invoked like so: -\code -LOG((CLOG_XXX "%d and %d are %s", x, y, x == y ? "equal" : "not equal")); -\endcode -In particular, notice the double open and close parentheses. Also note -that there is no comma after the \c CLOG_XXX. The \c XXX should be -replaced by one of enumerants in \c CLog::ELevel without the leading -\c k. For example, \c CLOG_INFO. The special \c CLOG_PRINT level will -not be filtered and is never prefixed by the filename and line number. - -If \c NOLOGGING is defined during the build then this macro expands to -nothing. If \c NDEBUG is defined during the build then it expands to a -call to CLog::print. Otherwise it expands to a call to CLog::printt, -which includes the filename and line number. -*/ - -/*! -\def LOGC(expr, arg) -Write to the log if and only if expr is true. Because macros cannot accept -variable arguments, this should be invoked like so: -\code -LOGC(x == y, (CLOG_XXX "%d and %d are equal", x, y)); -\endcode -In particular, notice the parentheses around everything after the boolean -expression. Also note that there is no comma after the \c CLOG_XXX. -The \c XXX should be replaced by one of enumerants in \c CLog::ELevel -without the leading \c k. For example, \c CLOG_INFO. The special -\c CLOG_PRINT level will not be filtered and is never prefixed by the -filename and line number. - -If \c NOLOGGING is defined during the build then this macro expands to -nothing. If \c NDEBUG is not defined during the build then it expands -to a call to CLog::print that prints the filename and line number, -otherwise it expands to a call that doesn't. -*/ - -#if defined(NOLOGGING) -#define LOG(_a1) -#define LOGC(_a1, _a2) -#define CLOG_TRACE -#elif defined(NDEBUG) -#define LOG(_a1) CLOG->print _a1 -#define LOGC(_a1, _a2) if (_a1) CLOG->print _a2 -#define CLOG_TRACE NULL, 0, -#else -#define LOG(_a1) CLOG->print _a1 -#define LOGC(_a1, _a2) if (_a1) CLOG->print _a2 -#define CLOG_TRACE __FILE__, __LINE__, -#endif - -#define CLOG_PRINT CLOG_TRACE "%z\057" -#define CLOG_CRIT CLOG_TRACE "%z\060" -#define CLOG_ERR CLOG_TRACE "%z\061" -#define CLOG_WARN CLOG_TRACE "%z\062" -#define CLOG_NOTE CLOG_TRACE "%z\063" -#define CLOG_INFO CLOG_TRACE "%z\064" -#define CLOG_DEBUG CLOG_TRACE "%z\065" -#define CLOG_DEBUG1 CLOG_TRACE "%z\066" -#define CLOG_DEBUG2 CLOG_TRACE "%z\067" - -#endif diff --git a/lib/base/CPriorityQueue.h b/lib/base/CPriorityQueue.h deleted file mode 100644 index 29129e31..00000000 --- a/lib/base/CPriorityQueue.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CPRIORITYQUEUE_H -#define CPRIORITYQUEUE_H - -#include "stdvector.h" -#include -#include - -//! A priority queue with an iterator -/*! -This priority queue is the same as a standard priority queue except: -it sorts by std::greater, it has a forward iterator through the elements -(which can appear in any order), and its contents can be swapped. -*/ -template , -#if defined(_MSC_VER) - class Compare = std::greater > -#else - class Compare = std::greater > -#endif -class CPriorityQueue { -public: - typedef typename Container::value_type value_type; - typedef typename Container::size_type size_type; - typedef typename Container::iterator iterator; - typedef typename Container::const_iterator const_iterator; - typedef Container container_type; - - CPriorityQueue() { } - CPriorityQueue(Container& swappedIn) { swap(swappedIn); } - ~CPriorityQueue() { } - - //! @name manipulators - //@{ - - //! Add element - void push(const value_type& v) - { - c.push_back(v); - std::push_heap(c.begin(), c.end(), comp); - } - - //! Remove head element - void pop() - { - std::pop_heap(c.begin(), c.end(), comp); - c.pop_back(); - } - - //! Erase element - void erase(iterator i) - { - c.erase(i); - std::make_heap(c.begin(), c.end(), comp); - } - - //! Get start iterator - iterator begin() - { - return c.begin(); - } - - //! Get end iterator - iterator end() - { - return c.end(); - } - - //! Swap contents with another priority queue - void swap(CPriorityQueue& q) - { - c.swap(q.c); - } - - //! Swap contents with another container - void swap(Container& c2) - { - c.swap(c2); - std::make_heap(c.begin(), c.end(), comp); - } - - //@} - //! @name accessors - //@{ - - //! Returns true if there are no elements - bool empty() const - { - return c.empty(); - } - - //! Returns the number of elements - size_type size() const - { - return c.size(); - } - - //! Returns the head element - const value_type& top() const - { - return c.front(); - } - - //! Get start iterator - const_iterator begin() const - { - return c.begin(); - } - - //! Get end iterator - const_iterator end() const - { - return c.end(); - } - - //@} - -private: - Container c; - Compare comp; -}; - -#endif diff --git a/lib/base/CSimpleEventQueueBuffer.cpp b/lib/base/CSimpleEventQueueBuffer.cpp deleted file mode 100644 index 8f2dbd14..00000000 --- a/lib/base/CSimpleEventQueueBuffer.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CSimpleEventQueueBuffer.h" -#include "CStopwatch.h" -#include "CArch.h" - -class CEventQueueTimer { }; - -// -// CSimpleEventQueueBuffer -// - -CSimpleEventQueueBuffer::CSimpleEventQueueBuffer() -{ - m_queueMutex = ARCH->newMutex(); - m_queueReadyCond = ARCH->newCondVar(); - m_queueReady = false; -} - -CSimpleEventQueueBuffer::~CSimpleEventQueueBuffer() -{ - ARCH->closeCondVar(m_queueReadyCond); - ARCH->closeMutex(m_queueMutex); -} - -void -CSimpleEventQueueBuffer::waitForEvent(double timeout) -{ - CArchMutexLock lock(m_queueMutex); - CStopwatch timer(true); - while (!m_queueReady) { - double timeLeft = timeout; - if (timeLeft >= 0.0) { - timeLeft -= timer.getTime(); - if (timeLeft < 0.0) { - return; - } - } - ARCH->waitCondVar(m_queueReadyCond, m_queueMutex, timeLeft); - } -} - -IEventQueueBuffer::Type -CSimpleEventQueueBuffer::getEvent(CEvent&, UInt32& dataID) -{ - CArchMutexLock lock(m_queueMutex); - if (!m_queueReady) { - return kNone; - } - dataID = m_queue.back(); - m_queue.pop_back(); - m_queueReady = !m_queue.empty(); - return kUser; -} - -bool -CSimpleEventQueueBuffer::addEvent(UInt32 dataID) -{ - CArchMutexLock lock(m_queueMutex); - m_queue.push_front(dataID); - if (!m_queueReady) { - m_queueReady = true; - ARCH->broadcastCondVar(m_queueReadyCond); - } - return true; -} - -bool -CSimpleEventQueueBuffer::isEmpty() const -{ - CArchMutexLock lock(m_queueMutex); - return !m_queueReady; -} - -CEventQueueTimer* -CSimpleEventQueueBuffer::newTimer(double, bool) const -{ - return new CEventQueueTimer; -} - -void -CSimpleEventQueueBuffer::deleteTimer(CEventQueueTimer* timer) const -{ - delete timer; -} diff --git a/lib/base/CSimpleEventQueueBuffer.h b/lib/base/CSimpleEventQueueBuffer.h deleted file mode 100644 index c395fabd..00000000 --- a/lib/base/CSimpleEventQueueBuffer.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CSIMPLEEVENTQUEUEBUFFER_H -#define CSIMPLEEVENTQUEUEBUFFER_H - -#include "IEventQueueBuffer.h" -#include "IArchMultithread.h" -#include "stddeque.h" - -//! In-memory event queue buffer -/*! -An event queue buffer provides a queue of events for an IEventQueue. -*/ -class CSimpleEventQueueBuffer : public IEventQueueBuffer { -public: - CSimpleEventQueueBuffer(); - ~CSimpleEventQueueBuffer(); - - // IEventQueueBuffer overrides - virtual void waitForEvent(double timeout); - virtual Type getEvent(CEvent& event, UInt32& dataID); - virtual bool addEvent(UInt32 dataID); - virtual bool isEmpty() const; - virtual CEventQueueTimer* - newTimer(double duration, bool oneShot) const; - virtual void deleteTimer(CEventQueueTimer*) const; - -private: - typedef std::deque CEventDeque; - - CArchMutex m_queueMutex; - CArchCond m_queueReadyCond; - bool m_queueReady; - CEventDeque m_queue; -}; - -#endif diff --git a/lib/base/CStopwatch.cpp b/lib/base/CStopwatch.cpp deleted file mode 100644 index 89edce2b..00000000 --- a/lib/base/CStopwatch.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CStopwatch.h" -#include "CArch.h" - -// -// CStopwatch -// - -CStopwatch::CStopwatch(bool triggered) : - m_mark(0.0), - m_triggered(triggered), - m_stopped(triggered) -{ - if (!triggered) { - m_mark = ARCH->time(); - } -} - -CStopwatch::~CStopwatch() -{ - // do nothing -} - -double -CStopwatch::reset() -{ - if (m_stopped) { - const double dt = m_mark; - m_mark = 0.0; - return dt; - } - else { - const double t = ARCH->time(); - const double dt = t - m_mark; - m_mark = t; - return dt; - } -} - -void -CStopwatch::stop() -{ - if (m_stopped) { - return; - } - - // save the elapsed time - m_mark = ARCH->time() - m_mark; - m_stopped = true; -} - -void -CStopwatch::start() -{ - m_triggered = false; - if (!m_stopped) { - return; - } - - // set the mark such that it reports the time elapsed at stop() - m_mark = ARCH->time() - m_mark; - m_stopped = false; -} - -void -CStopwatch::setTrigger() -{ - stop(); - m_triggered = true; -} - -double -CStopwatch::getTime() -{ - if (m_triggered) { - const double dt = m_mark; - start(); - return dt; - } - else if (m_stopped) { - return m_mark; - } - else { - return ARCH->time() - m_mark; - } -} - -CStopwatch::operator double() -{ - return getTime(); -} - -bool -CStopwatch::isStopped() const -{ - return m_stopped; -} - -double -CStopwatch::getTime() const -{ - if (m_stopped) { - return m_mark; - } - else { - return ARCH->time() - m_mark; - } -} - -CStopwatch::operator double() const -{ - return getTime(); -} diff --git a/lib/base/CStopwatch.h b/lib/base/CStopwatch.h deleted file mode 100644 index e6a34719..00000000 --- a/lib/base/CStopwatch.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CSTOPWATCH_H -#define CSTOPWATCH_H - -#include "common.h" - -//! A timer class -/*! -This class measures time intervals. All time interval measurement -should use this class. -*/ -class CStopwatch { -public: - /*! - The default constructor does an implicit reset() or setTrigger(). - If triggered == false then the clock starts ticking. - */ - CStopwatch(bool triggered = false); - ~CStopwatch(); - - //! @name manipulators - //@{ - - //! Reset the timer to zero - /*! - Set the start time to the current time, returning the time since - the last reset. This does not remove the trigger if it's set nor - does it start a stopped clock. If the clock is stopped then - subsequent reset()'s will return 0. - */ - double reset(); - - //! Stop the timer - /*! - Stop the stopwatch. The time interval while stopped is not - counted by the stopwatch. stop() does not remove the trigger. - Has no effect if already stopped. - */ - void stop(); - - //! Start the timer - /*! - Start the stopwatch. start() removes the trigger, even if the - stopwatch was already started. - */ - void start(); - - //! Stop the timer and set the trigger - /*! - setTrigger() stops the clock like stop() except there's an - implicit start() the next time (non-const) getTime() is called. - This is useful when you want the clock to start the first time - you check it. - */ - void setTrigger(); - - //! Get elapsed time - /*! - Returns the time since the last reset() (or calls reset() and - returns zero if the trigger is set). - */ - double getTime(); - //! Same as getTime() - operator double(); - //@} - //! @name accessors - //@{ - - //! Check if timer is stopped - /*! - Returns true if the stopwatch is stopped. - */ - bool isStopped() const; - - // return the time since the last reset(). - //! Get elapsed time - /*! - Returns the time since the last reset(). This cannot trigger the - stopwatch to start and will not clear the trigger. - */ - double getTime() const; - //! Same as getTime() const - operator double() const; - //@} - -private: - double getClock() const; - -private: - double m_mark; - bool m_triggered; - bool m_stopped; -}; - -#endif diff --git a/lib/base/CString.h b/lib/base/CString.h deleted file mode 100644 index bc905009..00000000 --- a/lib/base/CString.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CSTRING_H -#define CSTRING_H - -#include "common.h" -#include "stdstring.h" - -// use standard C++ string class for our string class -typedef std::string CString; - -#endif - diff --git a/lib/base/CStringUtil.cpp b/lib/base/CStringUtil.cpp deleted file mode 100644 index 46361932..00000000 --- a/lib/base/CStringUtil.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CStringUtil.h" -#include "CArch.h" -#include "common.h" -#include "stdvector.h" -#include -#include -#include -#include - -// -// CStringUtil -// - -CString -CStringUtil::format(const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - CString result = vformat(fmt, args); - va_end(args); - return result; -} - -CString -CStringUtil::vformat(const char* fmt, va_list args) -{ - // find highest indexed substitution and the locations of substitutions - std::vector pos; - std::vector width; - std::vector index; - int maxIndex = 0; - for (const char* scan = fmt; *scan != '\0'; ++scan) { - if (*scan == '%') { - ++scan; - if (*scan == '\0') { - break; - } - else if (*scan == '%') { - // literal - index.push_back(0); - pos.push_back(static_cast(scan - 1 - fmt)); - width.push_back(2); - } - else if (*scan == '{') { - // get argument index - char* end; - int i = static_cast(strtol(scan + 1, &end, 10)); - if (*end != '}') { - // invalid index -- ignore - scan = end - 1; - } - else { - index.push_back(i); - pos.push_back(static_cast(scan - 1 - fmt)); - width.push_back(static_cast(end - scan + 2)); - if (i > maxIndex) { - maxIndex = i; - } - scan = end; - } - } - else { - // improper escape -- ignore - } - } - } - - // get args - std::vector value; - std::vector length; - value.push_back("%"); - length.push_back(1); - for (int i = 0; i < maxIndex; ++i) { - const char* arg = va_arg(args, const char*); - size_t len = strlen(arg); - value.push_back(arg); - length.push_back(len); - } - - // compute final length - size_t resultLength = strlen(fmt); - const int n = static_cast(pos.size()); - for (int i = 0; i < n; ++i) { - resultLength -= width[i]; - resultLength += length[index[i]]; - } - - // substitute - CString result; - result.reserve(resultLength); - size_t src = 0; - for (int i = 0; i < n; ++i) { - result.append(fmt + src, pos[i] - src); - result.append(value[index[i]]); - src = pos[i] + width[i]; - } - result.append(fmt + src); - - return result; -} - -CString -CStringUtil::print(const char* fmt, ...) -{ - char tmp[1024]; - char* buffer = tmp; - int len = (int)(sizeof(tmp) / sizeof(tmp[0])); - CString result; - while (buffer != NULL) { - // try printing into the buffer - va_list args; - va_start(args, fmt); - int n = ARCH->vsnprintf(buffer, len, fmt, args); - va_end(args); - - // if the buffer wasn't big enough then make it bigger and try again - if (n < 0 || n > len) { - if (buffer != tmp) { - delete[] buffer; - } - len *= 2; - buffer = new char[len]; - } - - // if it was big enough then save the string and don't try again - else { - result = buffer; - if (buffer != tmp) { - delete[] buffer; - } - buffer = NULL; - } - } - - return result; -} - - -// -// CStringUtil::CaselessCmp -// - -bool -CStringUtil::CaselessCmp::cmpEqual( - const CString::value_type& a, - const CString::value_type& b) -{ - // should use std::tolower but not in all versions of libstdc++ have it - return tolower(a) == tolower(b); -} - -bool -CStringUtil::CaselessCmp::cmpLess( - const CString::value_type& a, - const CString::value_type& b) -{ - // should use std::tolower but not in all versions of libstdc++ have it - return tolower(a) < tolower(b); -} - -bool -CStringUtil::CaselessCmp::less(const CString& a, const CString& b) -{ - return std::lexicographical_compare( - a.begin(), a.end(), - b.begin(), b.end(), - &CStringUtil::CaselessCmp::cmpLess); -} - -bool -CStringUtil::CaselessCmp::equal(const CString& a, const CString& b) -{ - return !(less(a, b) || less(b, a)); -} - -bool -CStringUtil::CaselessCmp::operator()(const CString& a, const CString& b) const -{ - return less(a, b); -} diff --git a/lib/base/CStringUtil.h b/lib/base/CStringUtil.h deleted file mode 100644 index 8ee86647..00000000 --- a/lib/base/CStringUtil.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CSTRINGUTIL_H -#define CSTRINGUTIL_H - -#include "CString.h" -#include - -//! String utilities -/*! -This class provides various functions for string manipulation. -*/ -class CStringUtil { -public: - //! Format positional arguments - /*! - Format a string using positional arguments. fmt has literal - characters and conversion specifications introduced by `\%': - - \c\%\% -- literal `\%' - - \c\%{n} -- positional element n, n a positive integer, {} are literal - - All arguments in the variable list are const char*. Positional - elements are indexed from 1. - */ - static CString format(const char* fmt, ...); - - //! Format positional arguments - /*! - Same as format() except takes va_list. - */ - static CString vformat(const char* fmt, va_list); - - //! Print a string using printf-style formatting - /*! - Equivalent to printf() except the result is returned as a CString. - */ - static CString print(const char* fmt, ...); - - //! Case-insensitive comparisons - /*! - This class provides case-insensitve comparison functions. - */ - class CaselessCmp { - public: - //! Same as less() - bool operator()(const CString& a, const CString& b) const; - - //! Returns true iff \c a is lexicographically less than \c b - static bool less(const CString& a, const CString& b); - - //! Returns true iff \c a is lexicographically equal to \c b - static bool equal(const CString& a, const CString& b); - - //! Returns true iff \c a is lexicographically less than \c b - static bool cmpLess(const CString::value_type& a, - const CString::value_type& b); - - //! Returns true iff \c a is lexicographically equal to \c b - static bool cmpEqual(const CString::value_type& a, - const CString::value_type& b); - }; -}; - -#endif - diff --git a/lib/base/CUnicode.cpp b/lib/base/CUnicode.cpp deleted file mode 100644 index 4dcfcd6f..00000000 --- a/lib/base/CUnicode.cpp +++ /dev/null @@ -1,779 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CUnicode.h" -#include "CArch.h" -#include - -// -// local utility functions -// - -inline -static -UInt16 -decode16(const UInt8* n, bool byteSwapped) -{ - union x16 { - UInt8 n8[2]; - UInt16 n16; - } c; - if (byteSwapped) { - c.n8[0] = n[1]; - c.n8[1] = n[0]; - } - else { - c.n8[0] = n[0]; - c.n8[1] = n[1]; - } - return c.n16; -} - -inline -static -UInt32 -decode32(const UInt8* n, bool byteSwapped) -{ - union x32 { - UInt8 n8[4]; - UInt32 n32; - } c; - if (byteSwapped) { - c.n8[0] = n[3]; - c.n8[1] = n[2]; - c.n8[2] = n[1]; - c.n8[3] = n[0]; - } - else { - c.n8[0] = n[0]; - c.n8[1] = n[1]; - c.n8[2] = n[2]; - c.n8[3] = n[3]; - } - return c.n32; -} - -inline -static -void -resetError(bool* errors) -{ - if (errors != NULL) { - *errors = false; - } -} - -inline -static -void -setError(bool* errors) -{ - if (errors != NULL) { - *errors = true; - } -} - - -// -// CUnicode -// - -UInt32 CUnicode::s_invalid = 0x0000ffff; -UInt32 CUnicode::s_replacement = 0x0000fffd; - -bool -CUnicode::isUTF8(const CString& src) -{ - // convert and test each character - const UInt8* data = reinterpret_cast(src.c_str()); - for (UInt32 n = src.size(); n > 0; ) { - if (fromUTF8(data, n) == s_invalid) { - return false; - } - } - return true; -} - -CString -CUnicode::UTF8ToUCS2(const CString& src, bool* errors) -{ - // default to success - resetError(errors); - - // get size of input string and reserve some space in output - UInt32 n = src.size(); - CString dst; - dst.reserve(2 * n); - - // convert each character - const UInt8* data = reinterpret_cast(src.c_str()); - while (n > 0) { - UInt32 c = fromUTF8(data, n); - if (c == s_invalid) { - c = s_replacement; - } - else if (c >= 0x00010000) { - setError(errors); - c = s_replacement; - } - UInt16 ucs2 = static_cast(c); - dst.append(reinterpret_cast(&ucs2), 2); - } - - return dst; -} - -CString -CUnicode::UTF8ToUCS4(const CString& src, bool* errors) -{ - // default to success - resetError(errors); - - // get size of input string and reserve some space in output - UInt32 n = src.size(); - CString dst; - dst.reserve(4 * n); - - // convert each character - const UInt8* data = reinterpret_cast(src.c_str()); - while (n > 0) { - UInt32 c = fromUTF8(data, n); - if (c == s_invalid) { - c = s_replacement; - } - dst.append(reinterpret_cast(&c), 4); - } - - return dst; -} - -CString -CUnicode::UTF8ToUTF16(const CString& src, bool* errors) -{ - // default to success - resetError(errors); - - // get size of input string and reserve some space in output - UInt32 n = src.size(); - CString dst; - dst.reserve(2 * n); - - // convert each character - const UInt8* data = reinterpret_cast(src.c_str()); - while (n > 0) { - UInt32 c = fromUTF8(data, n); - if (c == s_invalid) { - c = s_replacement; - } - else if (c >= 0x00110000) { - setError(errors); - c = s_replacement; - } - if (c < 0x00010000) { - UInt16 ucs2 = static_cast(c); - dst.append(reinterpret_cast(&ucs2), 2); - } - else { - c -= 0x00010000; - UInt16 utf16h = static_cast((c >> 10) + 0xd800); - UInt16 utf16l = static_cast((c & 0x03ff) + 0xdc00); - dst.append(reinterpret_cast(&utf16h), 2); - dst.append(reinterpret_cast(&utf16l), 2); - } - } - - return dst; -} - -CString -CUnicode::UTF8ToUTF32(const CString& src, bool* errors) -{ - // default to success - resetError(errors); - - // get size of input string and reserve some space in output - UInt32 n = src.size(); - CString dst; - dst.reserve(4 * n); - - // convert each character - const UInt8* data = reinterpret_cast(src.c_str()); - while (n > 0) { - UInt32 c = fromUTF8(data, n); - if (c == s_invalid) { - c = s_replacement; - } - else if (c >= 0x00110000) { - setError(errors); - c = s_replacement; - } - dst.append(reinterpret_cast(&c), 4); - } - - return dst; -} - -CString -CUnicode::UTF8ToText(const CString& src, bool* errors) -{ - // default to success - resetError(errors); - - // convert to wide char - UInt32 size; - wchar_t* tmp = UTF8ToWideChar(src, size, errors); - - // convert string to multibyte - int len = ARCH->convStringWCToMB(NULL, tmp, size, errors); - char* mbs = new char[len + 1]; - ARCH->convStringWCToMB(mbs, tmp, size, errors); - CString text(mbs, len); - - // clean up - delete[] mbs; - delete[] tmp; - - return text; -} - -CString -CUnicode::UCS2ToUTF8(const CString& src, bool* errors) -{ - // default to success - resetError(errors); - - // convert - UInt32 n = src.size() >> 1; - return doUCS2ToUTF8(reinterpret_cast(src.data()), n, errors); -} - -CString -CUnicode::UCS4ToUTF8(const CString& src, bool* errors) -{ - // default to success - resetError(errors); - - // convert - UInt32 n = src.size() >> 2; - return doUCS4ToUTF8(reinterpret_cast(src.data()), n, errors); -} - -CString -CUnicode::UTF16ToUTF8(const CString& src, bool* errors) -{ - // default to success - resetError(errors); - - // convert - UInt32 n = src.size() >> 1; - return doUTF16ToUTF8(reinterpret_cast(src.data()), n, errors); -} - -CString -CUnicode::UTF32ToUTF8(const CString& src, bool* errors) -{ - // default to success - resetError(errors); - - // convert - UInt32 n = src.size() >> 2; - return doUTF32ToUTF8(reinterpret_cast(src.data()), n, errors); -} - -CString -CUnicode::textToUTF8(const CString& src, bool* errors) -{ - // default to success - resetError(errors); - - // convert string to wide characters - UInt32 n = src.size(); - int len = ARCH->convStringMBToWC(NULL, src.c_str(), n, errors); - wchar_t* wcs = new wchar_t[len + 1]; - ARCH->convStringMBToWC(wcs, src.c_str(), n, errors); - - // convert to UTF8 - CString utf8 = wideCharToUTF8(wcs, len, errors); - - // clean up - delete[] wcs; - - return utf8; -} - -wchar_t* -CUnicode::UTF8ToWideChar(const CString& src, UInt32& size, bool* errors) -{ - // convert to platform's wide character encoding - CString tmp; - switch (ARCH->getWideCharEncoding()) { - case IArchString::kUCS2: - tmp = UTF8ToUCS2(src, errors); - size = tmp.size() >> 1; - break; - - case IArchString::kUCS4: - tmp = UTF8ToUCS4(src, errors); - size = tmp.size() >> 2; - break; - - case IArchString::kUTF16: - tmp = UTF8ToUTF16(src, errors); - size = tmp.size() >> 1; - break; - - case IArchString::kUTF32: - tmp = UTF8ToUTF32(src, errors); - size = tmp.size() >> 2; - break; - - default: - assert(0 && "unknown wide character encoding"); - } - - // copy to a wchar_t array - wchar_t* dst = new wchar_t[size]; - ::memcpy(dst, tmp.data(), sizeof(wchar_t) * size); - return dst; -} - -CString -CUnicode::wideCharToUTF8(const wchar_t* src, UInt32 size, bool* errors) -{ - // convert from platform's wide character encoding. - // note -- this must include a wide nul character (independent of - // the CString's nul character). - switch (ARCH->getWideCharEncoding()) { - case IArchString::kUCS2: - return doUCS2ToUTF8(reinterpret_cast(src), size, errors); - - case IArchString::kUCS4: - return doUCS4ToUTF8(reinterpret_cast(src), size, errors); - - case IArchString::kUTF16: - return doUTF16ToUTF8(reinterpret_cast(src), size, errors); - - case IArchString::kUTF32: - return doUTF32ToUTF8(reinterpret_cast(src), size, errors); - - default: - assert(0 && "unknown wide character encoding"); - return CString(); - } -} - -CString -CUnicode::doUCS2ToUTF8(const UInt8* data, UInt32 n, bool* errors) -{ - // make some space - CString dst; - dst.reserve(n); - - // check if first character is 0xfffe or 0xfeff - bool byteSwapped = false; - if (n >= 1) { - switch (decode16(data, false)) { - case 0x0000feff: - data += 2; - --n; - break; - - case 0x0000fffe: - byteSwapped = true; - data += 2; - --n; - break; - - default: - break; - } - } - - // convert each character - for (; n > 0; data += 2, --n) { - UInt32 c = decode16(data, byteSwapped); - toUTF8(dst, c, errors); - } - - return dst; -} - -CString -CUnicode::doUCS4ToUTF8(const UInt8* data, UInt32 n, bool* errors) -{ - // make some space - CString dst; - dst.reserve(n); - - // check if first character is 0xfffe or 0xfeff - bool byteSwapped = false; - if (n >= 1) { - switch (decode32(data, false)) { - case 0x0000feff: - data += 4; - --n; - break; - - case 0x0000fffe: - byteSwapped = true; - data += 4; - --n; - break; - - default: - break; - } - } - - // convert each character - for (; n > 0; data += 4, --n) { - UInt32 c = decode32(data, byteSwapped); - toUTF8(dst, c, errors); - } - - return dst; -} - -CString -CUnicode::doUTF16ToUTF8(const UInt8* data, UInt32 n, bool* errors) -{ - // make some space - CString dst; - dst.reserve(n); - - // check if first character is 0xfffe or 0xfeff - bool byteSwapped = false; - if (n >= 1) { - switch (decode16(data, false)) { - case 0x0000feff: - data += 2; - --n; - break; - - case 0x0000fffe: - byteSwapped = true; - data += 2; - --n; - break; - - default: - break; - } - } - - // convert each character - for (; n > 0; data += 2, --n) { - UInt32 c = decode16(data, byteSwapped); - if (c < 0x0000d800 || c > 0x0000dfff) { - toUTF8(dst, c, errors); - } - else if (n == 1) { - // error -- missing second word - setError(errors); - toUTF8(dst, s_replacement, NULL); - } - else if (c >= 0x0000d800 && c <= 0x0000dbff) { - UInt32 c2 = decode16(data, byteSwapped); - data += 2; - --n; - if (c2 < 0x0000dc00 || c2 > 0x0000dfff) { - // error -- [d800,dbff] not followed by [dc00,dfff] - setError(errors); - toUTF8(dst, s_replacement, NULL); - } - else { - c = (((c - 0x0000d800) << 10) | (c2 - 0x0000dc00)) + 0x00010000; - toUTF8(dst, c, errors); - } - } - else { - // error -- [dc00,dfff] without leading [d800,dbff] - setError(errors); - toUTF8(dst, s_replacement, NULL); - } - } - - return dst; -} - -CString -CUnicode::doUTF32ToUTF8(const UInt8* data, UInt32 n, bool* errors) -{ - // make some space - CString dst; - dst.reserve(n); - - // check if first character is 0xfffe or 0xfeff - bool byteSwapped = false; - if (n >= 1) { - switch (decode32(data, false)) { - case 0x0000feff: - data += 4; - --n; - break; - - case 0x0000fffe: - byteSwapped = true; - data += 4; - --n; - break; - - default: - break; - } - } - - // convert each character - for (; n > 0; data += 4, --n) { - UInt32 c = decode32(data, byteSwapped); - if (c >= 0x00110000) { - setError(errors); - c = s_replacement; - } - toUTF8(dst, c, errors); - } - - return dst; -} - -UInt32 -CUnicode::fromUTF8(const UInt8*& data, UInt32& n) -{ - assert(data != NULL); - assert(n != 0); - - // compute character encoding length, checking for overlong - // sequences (i.e. characters that don't use the shortest - // possible encoding). - UInt32 size; - if (data[0] < 0x80) { - // 0xxxxxxx - size = 1; - } - else if (data[0] < 0xc0) { - // 10xxxxxx -- in the middle of a multibyte character. counts - // as one invalid character. - --n; - ++data; - return s_invalid; - } - else if (data[0] < 0xe0) { - // 110xxxxx - size = 2; - } - else if (data[0] < 0xf0) { - // 1110xxxx - size = 3; - } - else if (data[0] < 0xf8) { - // 11110xxx - size = 4; - } - else if (data[0] < 0xfc) { - // 111110xx - size = 5; - } - else if (data[0] < 0xfe) { - // 1111110x - size = 6; - } - else { - // invalid sequence. dunno how many bytes to skip so skip one. - --n; - ++data; - return s_invalid; - } - - // make sure we have enough data - if (size > n) { - data += n; - n = 0; - return s_invalid; - } - - // extract character - UInt32 c; - switch (size) { - case 1: - c = static_cast(data[0]); - break; - - case 2: - c = ((static_cast(data[0]) & 0x1f) << 6) | - ((static_cast(data[1]) & 0x3f) ); - break; - - case 3: - c = ((static_cast(data[0]) & 0x0f) << 12) | - ((static_cast(data[1]) & 0x3f) << 6) | - ((static_cast(data[2]) & 0x3f) ); - break; - - case 4: - c = ((static_cast(data[0]) & 0x07) << 18) | - ((static_cast(data[1]) & 0x3f) << 12) | - ((static_cast(data[1]) & 0x3f) << 6) | - ((static_cast(data[1]) & 0x3f) ); - break; - - case 5: - c = ((static_cast(data[0]) & 0x03) << 24) | - ((static_cast(data[1]) & 0x3f) << 18) | - ((static_cast(data[1]) & 0x3f) << 12) | - ((static_cast(data[1]) & 0x3f) << 6) | - ((static_cast(data[1]) & 0x3f) ); - break; - - case 6: - c = ((static_cast(data[0]) & 0x01) << 30) | - ((static_cast(data[1]) & 0x3f) << 24) | - ((static_cast(data[1]) & 0x3f) << 18) | - ((static_cast(data[1]) & 0x3f) << 12) | - ((static_cast(data[1]) & 0x3f) << 6) | - ((static_cast(data[1]) & 0x3f) ); - break; - - default: - assert(0 && "invalid size"); - return s_invalid; - } - - // check that all bytes after the first have the pattern 10xxxxxx. - // truncated sequences are treated as a single malformed character. - bool truncated = false; - switch (size) { - case 6: - if ((data[5] & 0xc0) != 0x80) { - truncated = true; - size = 5; - } - // fall through - - case 5: - if ((data[4] & 0xc0) != 0x80) { - truncated = true; - size = 4; - } - // fall through - - case 4: - if ((data[3] & 0xc0) != 0x80) { - truncated = true; - size = 3; - } - // fall through - - case 3: - if ((data[2] & 0xc0) != 0x80) { - truncated = true; - size = 2; - } - // fall through - - case 2: - if ((data[1] & 0xc0) != 0x80) { - truncated = true; - size = 1; - } - } - - // update parameters - data += size; - n -= size; - - // invalid if sequence was truncated - if (truncated) { - return s_invalid; - } - - // check for characters that didn't use the smallest possible encoding - static UInt32 s_minChar[] = { - 0, - 0x00000000, - 0x00000080, - 0x00000800, - 0x00010000, - 0x00200000, - 0x04000000 - }; - if (c < s_minChar[size]) { - return s_invalid; - } - - // check for characters not in ISO-10646 - if (c >= 0x0000d800 && c <= 0x0000dfff) { - return s_invalid; - } - if (c >= 0x0000fffe && c <= 0x0000ffff) { - return s_invalid; - } - - return c; -} - -void -CUnicode::toUTF8(CString& dst, UInt32 c, bool* errors) -{ - UInt8 data[6]; - - // handle characters outside the valid range - if ((c >= 0x0000d800 && c <= 0x0000dfff) || c >= 0x80000000) { - setError(errors); - c = s_replacement; - } - - // convert to UTF-8 - if (c < 0x00000080) { - data[0] = static_cast(c); - dst.append(reinterpret_cast(data), 1); - } - else if (c < 0x00000800) { - data[0] = static_cast(((c >> 6) & 0x0000001f) + 0xc0); - data[1] = static_cast((c & 0x0000003f) + 0x80); - dst.append(reinterpret_cast(data), 2); - } - else if (c < 0x00010000) { - data[0] = static_cast(((c >> 12) & 0x0000000f) + 0xe0); - data[1] = static_cast(((c >> 6) & 0x0000003f) + 0x80); - data[2] = static_cast((c & 0x0000003f) + 0x80); - dst.append(reinterpret_cast(data), 3); - } - else if (c < 0x00200000) { - data[0] = static_cast(((c >> 18) & 0x00000007) + 0xf0); - data[1] = static_cast(((c >> 12) & 0x0000003f) + 0x80); - data[2] = static_cast(((c >> 6) & 0x0000003f) + 0x80); - data[3] = static_cast((c & 0x0000003f) + 0x80); - dst.append(reinterpret_cast(data), 4); - } - else if (c < 0x04000000) { - data[0] = static_cast(((c >> 24) & 0x00000003) + 0xf8); - data[1] = static_cast(((c >> 18) & 0x0000003f) + 0x80); - data[2] = static_cast(((c >> 12) & 0x0000003f) + 0x80); - data[3] = static_cast(((c >> 6) & 0x0000003f) + 0x80); - data[4] = static_cast((c & 0x0000003f) + 0x80); - dst.append(reinterpret_cast(data), 5); - } - else if (c < 0x80000000) { - data[0] = static_cast(((c >> 30) & 0x00000001) + 0xfc); - data[1] = static_cast(((c >> 24) & 0x0000003f) + 0x80); - data[2] = static_cast(((c >> 18) & 0x0000003f) + 0x80); - data[3] = static_cast(((c >> 12) & 0x0000003f) + 0x80); - data[4] = static_cast(((c >> 6) & 0x0000003f) + 0x80); - data[5] = static_cast((c & 0x0000003f) + 0x80); - dst.append(reinterpret_cast(data), 6); - } - else { - assert(0 && "character out of range"); - } -} diff --git a/lib/base/CUnicode.h b/lib/base/CUnicode.h deleted file mode 100644 index 85afbfd9..00000000 --- a/lib/base/CUnicode.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CUNICODE_H -#define CUNICODE_H - -#include "CString.h" -#include "BasicTypes.h" - -//! Unicode utility functions -/*! -This class provides functions for converting between various Unicode -encodings and the current locale encoding. -*/ -class CUnicode { -public: - //! @name accessors - //@{ - - //! Test UTF-8 string for validity - /*! - Returns true iff the string contains a valid sequence of UTF-8 - encoded characters. - */ - static bool isUTF8(const CString&); - - //! Convert from UTF-8 to UCS-2 encoding - /*! - Convert from UTF-8 to UCS-2. If errors is not NULL then *errors - is set to true iff any character could not be encoded in UCS-2. - Decoding errors do not set *errors. - */ - static CString UTF8ToUCS2(const CString&, bool* errors = NULL); - - //! Convert from UTF-8 to UCS-4 encoding - /*! - Convert from UTF-8 to UCS-4. If errors is not NULL then *errors - is set to true iff any character could not be encoded in UCS-4. - Decoding errors do not set *errors. - */ - static CString UTF8ToUCS4(const CString&, bool* errors = NULL); - - //! Convert from UTF-8 to UTF-16 encoding - /*! - Convert from UTF-8 to UTF-16. If errors is not NULL then *errors - is set to true iff any character could not be encoded in UTF-16. - Decoding errors do not set *errors. - */ - static CString UTF8ToUTF16(const CString&, bool* errors = NULL); - - //! Convert from UTF-8 to UTF-32 encoding - /*! - Convert from UTF-8 to UTF-32. If errors is not NULL then *errors - is set to true iff any character could not be encoded in UTF-32. - Decoding errors do not set *errors. - */ - static CString UTF8ToUTF32(const CString&, bool* errors = NULL); - - //! Convert from UTF-8 to the current locale encoding - /*! - Convert from UTF-8 to the current locale encoding. If errors is not - NULL then *errors is set to true iff any character could not be encoded. - Decoding errors do not set *errors. - */ - static CString UTF8ToText(const CString&, bool* errors = NULL); - - //! Convert from UCS-2 to UTF-8 - /*! - Convert from UCS-2 to UTF-8. If errors is not NULL then *errors is - set to true iff any character could not be decoded. - */ - static CString UCS2ToUTF8(const CString&, bool* errors = NULL); - - //! Convert from UCS-4 to UTF-8 - /*! - Convert from UCS-4 to UTF-8. If errors is not NULL then *errors is - set to true iff any character could not be decoded. - */ - static CString UCS4ToUTF8(const CString&, bool* errors = NULL); - - //! Convert from UTF-16 to UTF-8 - /*! - Convert from UTF-16 to UTF-8. If errors is not NULL then *errors is - set to true iff any character could not be decoded. - */ - static CString UTF16ToUTF8(const CString&, bool* errors = NULL); - - //! Convert from UTF-32 to UTF-8 - /*! - Convert from UTF-32 to UTF-8. If errors is not NULL then *errors is - set to true iff any character could not be decoded. - */ - static CString UTF32ToUTF8(const CString&, bool* errors = NULL); - - //! Convert from the current locale encoding to UTF-8 - /*! - Convert from the current locale encoding to UTF-8. If errors is not - NULL then *errors is set to true iff any character could not be decoded. - */ - static CString textToUTF8(const CString&, bool* errors = NULL); - - //@} - -private: - // convert UTF8 to wchar_t string (using whatever encoding is native - // to the platform). caller must delete[] the returned string. the - // string is *not* nul terminated; the length (in characters) is - // returned in size. - static wchar_t* UTF8ToWideChar(const CString&, - UInt32& size, bool* errors); - - // convert nul terminated wchar_t string (in platform's native - // encoding) to UTF8. - static CString wideCharToUTF8(const wchar_t*, - UInt32 size, bool* errors); - - // internal conversion to UTF8 - static CString doUCS2ToUTF8(const UInt8* src, UInt32 n, bool* errors); - static CString doUCS4ToUTF8(const UInt8* src, UInt32 n, bool* errors); - static CString doUTF16ToUTF8(const UInt8* src, UInt32 n, bool* errors); - static CString doUTF32ToUTF8(const UInt8* src, UInt32 n, bool* errors); - - // convert characters to/from UTF8 - static UInt32 fromUTF8(const UInt8*& src, UInt32& size); - static void toUTF8(CString& dst, UInt32 c, bool* errors); - -private: - static UInt32 s_invalid; - static UInt32 s_replacement; -}; - -#endif diff --git a/lib/base/IEventJob.h b/lib/base/IEventJob.h deleted file mode 100644 index 01ef9a96..00000000 --- a/lib/base/IEventJob.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef IEVENTJOB_H -#define IEVENTJOB_H - -#include "IInterface.h" - -class CEvent; - -//! Event handler interface -/*! -An event job is an interface for executing a event handler. -*/ -class IEventJob : public IInterface { -public: - //! Run the job - virtual void run(const CEvent&) = 0; -}; - -#endif diff --git a/lib/base/IEventQueue.cpp b/lib/base/IEventQueue.cpp deleted file mode 100644 index a10621f2..00000000 --- a/lib/base/IEventQueue.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "IEventQueue.h" - -// -// IEventQueue -// - -static int g_systemTarget = 0; -IEventQueue* IEventQueue::s_instance = NULL; - -void* -IEventQueue::getSystemTarget() -{ - // any unique arbitrary pointer will do - return &g_systemTarget; -} - -IEventQueue* -IEventQueue::getInstance() -{ - assert(s_instance != NULL); - return s_instance; -} - -void -IEventQueue::setInstance(IEventQueue* instance) -{ - assert(s_instance == NULL || instance == NULL); - s_instance = instance; -} diff --git a/lib/base/IEventQueue.h b/lib/base/IEventQueue.h deleted file mode 100644 index 6f48f25c..00000000 --- a/lib/base/IEventQueue.h +++ /dev/null @@ -1,213 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef IEVENTQUEUE_H -#define IEVENTQUEUE_H - -#include "IInterface.h" -#include "CEvent.h" - -#define EVENTQUEUE IEventQueue::getInstance() - -class IEventJob; -class IEventQueueBuffer; - -// Opaque type for timer info. This is defined by subclasses of -// IEventQueueBuffer. -class CEventQueueTimer; - -//! Event queue interface -/*! -An event queue provides a queue of CEvents. Clients can block waiting -on any event becoming available at the head of the queue and can place -new events at the end of the queue. Clients can also add and remove -timers which generate events periodically. -*/ -class IEventQueue : public IInterface { -public: - class CTimerEvent { - public: - CEventQueueTimer* m_timer; //!< The timer - UInt32 m_count; //!< Number of repeats - }; - - //! @name manipulators - //@{ - - //! Set the buffer - /*! - Replace the current event queue buffer. Any queued events are - discarded. The queue takes ownership of the buffer. - */ - virtual void adoptBuffer(IEventQueueBuffer*) = 0; - - //! Remove event from queue - /*! - Returns the next event on the queue into \p event. If no event is - available then blocks for up to \p timeout seconds, or forever if - \p timeout is negative. Returns true iff an event was available. - */ - virtual bool getEvent(CEvent& event, double timeout = -1.0) = 0; - - //! Dispatch an event - /*! - Looks up the dispatcher for the event's target and invokes it. - Returns true iff a dispatcher exists for the target. - */ - virtual bool dispatchEvent(const CEvent& event) = 0; - - //! Add event to queue - /*! - Adds \p event to the end of the queue. - */ - virtual void addEvent(const CEvent& event) = 0; - - //! Create a recurring timer - /*! - Creates and returns a timer. An event is returned after \p duration - seconds and the timer is reset to countdown again. When a timer event - is returned the data points to a \c CTimerEvent. The client must pass - the returned timer to \c deleteTimer() (whether or not the timer has - expired) to release the timer. The returned timer event uses the - given \p target. If \p target is NULL it uses the returned timer as - the target. - - Events for a single timer don't accumulate in the queue, even if the - client reading events can't keep up. Instead, the \c m_count member - of the \c CTimerEvent indicates how many events for the timer would - have been put on the queue since the last event for the timer was - removed (or since the timer was added). - */ - virtual CEventQueueTimer* - newTimer(double duration, void* target) = 0; - - //! Create a one-shot timer - /*! - Creates and returns a one-shot timer. An event is returned when - the timer expires and the timer is removed from further handling. - When a timer event is returned the data points to a \c CTimerEvent. - The \m c_count member of the \c CTimerEvent is always 1. The client - must pass the returned timer to \c deleteTimer() (whether or not the - timer has expired) to release the timer. The returned timer event - uses the given \p target. If \p target is NULL it uses the returned - timer as the target. - */ - virtual CEventQueueTimer* - newOneShotTimer(double duration, - void* target) = 0; - - //! Destroy a timer - /*! - Destroys a previously created timer. The timer is removed from the - queue and will not generate event, even if the timer has expired. - */ - virtual void deleteTimer(CEventQueueTimer*) = 0; - - //! Register an event handler for an event type - /*! - Registers an event handler for \p type and \p target. The \p handler - is adopted. Any existing handler for the type,target pair is deleted. - \c dispatchEvent() will invoke \p handler for any event for \p target - of type \p type. If no such handler exists it will use the handler - for \p target and type \p kUnknown if it exists. - */ - virtual void adoptHandler(CEvent::Type type, - void* target, IEventJob* handler) = 0; - - //! Unregister an event handler for an event type - /*! - Unregisters an event handler for the \p type, \p target pair and - deletes it. - */ - virtual void removeHandler(CEvent::Type type, void* target) = 0; - - //! Unregister all event handlers for an event target - /*! - Unregisters all event handlers for the \p target and deletes them. - */ - virtual void removeHandlers(void* target) = 0; - - //! Creates a new event type - /*! - Returns a unique event type id. - */ - virtual CEvent::Type - registerType(const char* name) = 0; - - //! Creates a new event type - /*! - If \p type contains \c kUnknown then it is set to a unique event - type id otherwise it is left alone. The final value of \p type - is returned. - */ - virtual CEvent::Type - registerTypeOnce(CEvent::Type& type, - const char* name) = 0; - - //@} - //! @name accessors - //@{ - - //! Test if queue is empty - /*! - Returns true iff the queue has no events in it, including timer - events. - */ - virtual bool isEmpty() const = 0; - - //! Get an event handler - /*! - Finds and returns the event handler for the \p type, \p target pair - if it exists, otherwise it returns NULL. - */ - virtual IEventJob* getHandler(CEvent::Type type, void* target) const = 0; - - //! Get name for event - /*! - Returns the name for the event \p type. This is primarily for - debugging. - */ - virtual const char* getTypeName(CEvent::Type type) = 0; - - //! Get the system event type target - /*! - Returns the target to use for dispatching \c CEvent::kSystem events. - */ - static void* getSystemTarget(); - - //! Get the singleton instance - /*! - Returns the singleton instance of the event queue - */ - static IEventQueue* getInstance(); - - //@} - -protected: - //! @name manipulators - //@{ - - //! Set the singleton instance - /*! - Sets the singleton instance of the event queue - */ - static void setInstance(IEventQueue*); - - //@} - -private: - static IEventQueue* s_instance; -}; - -#endif diff --git a/lib/base/IEventQueueBuffer.h b/lib/base/IEventQueueBuffer.h deleted file mode 100644 index 1aff51a6..00000000 --- a/lib/base/IEventQueueBuffer.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef IEVENTQUEUEBUFFER_H -#define IEVENTQUEUEBUFFER_H - -#include "IInterface.h" -#include "BasicTypes.h" - -class CEvent; -class CEventQueueTimer; - -//! Event queue buffer interface -/*! -An event queue buffer provides a queue of events for an IEventQueue. -*/ -class IEventQueueBuffer : public IInterface { -public: - enum Type { - kNone, //!< No event is available - kSystem, //!< Event is a system event - kUser //!< Event is a user event - }; - - //! @name manipulators - //@{ - - //! Block waiting for an event - /*! - Wait for an event in the event queue buffer for up to \p timeout - seconds. - */ - virtual void waitForEvent(double timeout) = 0; - - //! Get the next event - /*! - Get the next event from the buffer. Return kNone if no event is - available. If a system event is next, return kSystem and fill in - event. The event data in a system event can point to a static - buffer (because CEvent::deleteData() will not attempt to delete - data in a kSystem event). Otherwise, return kUser and fill in - \p dataID with the value passed to \c addEvent(). - */ - virtual Type getEvent(CEvent& event, UInt32& dataID) = 0; - - //! Post an event - /*! - Add the given event to the end of the queue buffer. This is a user - event and \c getEvent() must be able to identify it as such and - return \p dataID. This method must cause \c waitForEvent() to - return at some future time if it's blocked waiting on an event. - */ - virtual bool addEvent(UInt32 dataID) = 0; - - //@} - //! @name accessors - //@{ - - //! Check if event queue buffer is empty - /*! - Return true iff the event queue buffer is empty. - */ - virtual bool isEmpty() const = 0; - - //! Create a timer object - /*! - Create and return a timer object. The object is opaque and is - used only by the buffer but it must be a valid object (i.e. - not NULL). - */ - virtual CEventQueueTimer* - newTimer(double duration, bool oneShot) const = 0; - - //! Destroy a timer object - /*! - Destroy a timer object previously returned by \c newTimer(). - */ - virtual void deleteTimer(CEventQueueTimer*) const = 0; - - //@} -}; - -#endif diff --git a/lib/base/IJob.h b/lib/base/IJob.h deleted file mode 100644 index 30ef5f5a..00000000 --- a/lib/base/IJob.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef IJOB_H -#define IJOB_H - -#include "IInterface.h" - -//! Job interface -/*! -A job is an interface for executing some function. -*/ -class IJob : public IInterface { -public: - //! Run the job - virtual void run() = 0; -}; - -#endif diff --git a/lib/base/ILogOutputter.h b/lib/base/ILogOutputter.h deleted file mode 100644 index 2be4dcc9..00000000 --- a/lib/base/ILogOutputter.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef ILOGOUTPUTTER_H -#define ILOGOUTPUTTER_H - -#include "IInterface.h" -#include "CLog.h" - -//! Outputter interface -/*! -Type of outputter interface. The logger performs all output through -outputters. ILogOutputter overrides must not call any log functions -directly or indirectly. -*/ -class ILogOutputter : public IInterface { -public: - typedef CLog::ELevel ELevel; - - //! @name manipulators - //@{ - - //! Open the outputter - /*! - Opens the outputter for writing. Calling this method on an - already open outputter must have no effect. - */ - virtual void open(const char* title) = 0; - - //! Close the outputter - /*! - Close the outputter. Calling this method on an already closed - outputter must have no effect. - */ - virtual void close() = 0; - - //! Show the outputter - /*! - Causes the output to become visible. This generally only makes sense - for a logger in a graphical user interface. Other implementations - will do nothing. Iff \p showIfEmpty is \c false then the implementation - may optionally only show the log if it's not empty. - */ - virtual void show(bool showIfEmpty) = 0; - - //! Write a message with level - /*! - Writes \c message, which has the given \c level, to a log. - If this method returns true then CLog will stop passing the - message to all outputters in the outputter chain, otherwise - it continues. Most implementations should return true. - */ - virtual bool write(ELevel level, const char* message) = 0; - - //@} - //! @name accessors - //@{ - - //! Returns the newline sequence for the outputter - /*! - Different outputters use different character sequences for newlines. - This method returns the appropriate newline sequence for this - outputter. - */ - virtual const char* getNewline() const = 0; - - //@} -}; - -#endif diff --git a/lib/base/LogOutputters.cpp b/lib/base/LogOutputters.cpp deleted file mode 100644 index f556d53f..00000000 --- a/lib/base/LogOutputters.cpp +++ /dev/null @@ -1,267 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "LogOutputters.h" -#include "CArch.h" - -// -// CStopLogOutputter -// - -CStopLogOutputter::CStopLogOutputter() -{ - // do nothing -} - -CStopLogOutputter::~CStopLogOutputter() -{ - // do nothing -} - -void -CStopLogOutputter::open(const char*) -{ - // do nothing -} - -void -CStopLogOutputter::close() -{ - // do nothing -} - -void -CStopLogOutputter::show(bool) -{ - // do nothing -} - -bool -CStopLogOutputter::write(ELevel, const char*) -{ - return false; -} - -const char* -CStopLogOutputter::getNewline() const -{ - return ""; -} - - -// -// CConsoleLogOutputter -// - -CConsoleLogOutputter::CConsoleLogOutputter() -{ - // do nothing -} - -CConsoleLogOutputter::~CConsoleLogOutputter() -{ - // do nothing -} - -void -CConsoleLogOutputter::open(const char* title) -{ - ARCH->openConsole(title); -} - -void -CConsoleLogOutputter::close() -{ - ARCH->closeConsole(); -} - -void -CConsoleLogOutputter::show(bool showIfEmpty) -{ - ARCH->showConsole(showIfEmpty); -} - -bool -CConsoleLogOutputter::write(ELevel, const char* msg) -{ - ARCH->writeConsole(msg); - return true; -} - -const char* -CConsoleLogOutputter::getNewline() const -{ - return ARCH->getNewlineForConsole(); -} - - -// -// CSystemLogOutputter -// - -CSystemLogOutputter::CSystemLogOutputter() -{ - // do nothing -} - -CSystemLogOutputter::~CSystemLogOutputter() -{ - // do nothing -} - -void -CSystemLogOutputter::open(const char* title) -{ - ARCH->openLog(title); -} - -void -CSystemLogOutputter::close() -{ - ARCH->closeLog(); -} - -void -CSystemLogOutputter::show(bool showIfEmpty) -{ - ARCH->showLog(showIfEmpty); -} - -bool -CSystemLogOutputter::write(ELevel level, const char* msg) -{ - IArchLog::ELevel archLogLevel; - switch (level) { - case CLog::kFATAL: - case CLog::kERROR: - archLogLevel = IArchLog::kERROR; - break; - - case CLog::kWARNING: - archLogLevel = IArchLog::kWARNING; - break; - - case CLog::kNOTE: - archLogLevel = IArchLog::kNOTE; - break; - - case CLog::kINFO: - archLogLevel = IArchLog::kINFO; - break; - - default: - archLogLevel = IArchLog::kDEBUG; - break; - - }; - ARCH->writeLog(archLogLevel, msg); - return true; -} - -const char* -CSystemLogOutputter::getNewline() const -{ - return ""; -} - - -// -// CSystemLogger -// - -CSystemLogger::CSystemLogger(const char* title, bool blockConsole) : - m_stop(NULL) -{ - // redirect log messages - if (blockConsole) { - m_stop = new CStopLogOutputter; - CLOG->insert(m_stop); - } - m_syslog = new CSystemLogOutputter; - m_syslog->open(title); - CLOG->insert(m_syslog); -} - -CSystemLogger::~CSystemLogger() -{ - CLOG->remove(m_syslog); - delete m_syslog; - if (m_stop != NULL) { - CLOG->remove(m_stop); - delete m_stop; - } -} - - -// -// CBufferedLogOutputter -// - -CBufferedLogOutputter::CBufferedLogOutputter(UInt32 maxBufferSize) : - m_maxBufferSize(maxBufferSize) -{ - // do nothing -} - -CBufferedLogOutputter::~CBufferedLogOutputter() -{ - // do nothing -} - -CBufferedLogOutputter::const_iterator -CBufferedLogOutputter::begin() const -{ - return m_buffer.begin(); -} - -CBufferedLogOutputter::const_iterator -CBufferedLogOutputter::end() const -{ - return m_buffer.end(); -} - -void -CBufferedLogOutputter::open(const char*) -{ - // do nothing -} - -void -CBufferedLogOutputter::close() -{ - // remove all elements from the buffer - m_buffer.clear(); -} - -void -CBufferedLogOutputter::show(bool) -{ - // do nothing -} - -bool -CBufferedLogOutputter::write(ELevel, const char* message) -{ - while (m_buffer.size() >= m_maxBufferSize) { - m_buffer.pop_front(); - } - m_buffer.push_back(CString(message)); - return true; -} - -const char* -CBufferedLogOutputter::getNewline() const -{ - return ""; -} diff --git a/lib/base/LogOutputters.h b/lib/base/LogOutputters.h deleted file mode 100644 index a8087593..00000000 --- a/lib/base/LogOutputters.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef LOGOUTPUTTERS_H -#define LOGOUTPUTTERS_H - -#include "BasicTypes.h" -#include "ILogOutputter.h" -#include "CString.h" -#include "stddeque.h" - -//! Stop traversing log chain outputter -/*! -This outputter performs no output and returns false from \c write(), -causing the logger to stop traversing the outputter chain. Insert -this to prevent already inserted outputters from writing. -*/ -class CStopLogOutputter : public ILogOutputter { -public: - CStopLogOutputter(); - virtual ~CStopLogOutputter(); - - // ILogOutputter overrides - virtual void open(const char* title); - virtual void close(); - virtual void show(bool showIfEmpty); - virtual bool write(ELevel level, const char* message); - virtual const char* getNewline() const; -}; - -//! Write log to console -/*! -This outputter writes output to the console. The level for each -message is ignored. -*/ -class CConsoleLogOutputter : public ILogOutputter { -public: - CConsoleLogOutputter(); - virtual ~CConsoleLogOutputter(); - - // ILogOutputter overrides - virtual void open(const char* title); - virtual void close(); - virtual void show(bool showIfEmpty); - virtual bool write(ELevel level, const char* message); - virtual const char* getNewline() const; -}; - -//! Write log to system log -/*! -This outputter writes output to the system log. -*/ -class CSystemLogOutputter : public ILogOutputter { -public: - CSystemLogOutputter(); - virtual ~CSystemLogOutputter(); - - // ILogOutputter overrides - virtual void open(const char* title); - virtual void close(); - virtual void show(bool showIfEmpty); - virtual bool write(ELevel level, const char* message); - virtual const char* getNewline() const; -}; - -//! Write log to system log only -/*! -Creating an object of this type inserts a CStopLogOutputter followed -by a CSystemLogOutputter into CLog. The destructor removes those -outputters. Add one of these to any scope that needs to write to -the system log (only) and restore the old outputters when exiting -the scope. -*/ -class CSystemLogger { -public: - CSystemLogger(const char* title, bool blockConsole); - ~CSystemLogger(); - -private: - ILogOutputter* m_syslog; - ILogOutputter* m_stop; -}; - -//! Save log history -/*! -This outputter records the last N log messages. -*/ -class CBufferedLogOutputter : public ILogOutputter { -private: - typedef std::deque CBuffer; - -public: - typedef CBuffer::const_iterator const_iterator; - - CBufferedLogOutputter(UInt32 maxBufferSize); - virtual ~CBufferedLogOutputter(); - - //! @name accessors - //@{ - - //! Get start of buffer - const_iterator begin() const; - - //! Get end of buffer - const_iterator end() const; - - //@} - - // ILogOutputter overrides - virtual void open(const char* title); - virtual void close(); - virtual void show(bool showIfEmpty); - virtual bool write(ELevel level, const char* message); - virtual const char* getNewline() const; - -private: - UInt32 m_maxBufferSize; - CBuffer m_buffer; -}; - -#endif diff --git a/lib/base/Makefile.am b/lib/base/Makefile.am deleted file mode 100644 index a53c8b33..00000000 --- a/lib/base/Makefile.am +++ /dev/null @@ -1,62 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2002 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -## Process this file with automake to produce Makefile.in -NULL = - -EXTRA_DIST = \ - Makefile.win \ - $(NULL) - -MAINTAINERCLEANFILES = \ - Makefile.in \ - $(NULL) - -noinst_LIBRARIES = libbase.a -libbase_a_SOURCES = \ - CEvent.cpp \ - CEventQueue.cpp \ - CFunctionEventJob.cpp \ - CFunctionJob.cpp \ - CLog.cpp \ - CSimpleEventQueueBuffer.cpp \ - CStopwatch.cpp \ - CStringUtil.cpp \ - CUnicode.cpp \ - IEventQueue.cpp \ - LogOutputters.cpp \ - XBase.cpp \ - CEvent.h \ - CEventQueue.h \ - CFunctionEventJob.h \ - CFunctionJob.h \ - CLog.h \ - CPriorityQueue.h \ - CSimpleEventQueueBuffer.h \ - CStopwatch.h \ - CString.h \ - CStringUtil.h \ - CUnicode.h \ - IEventJob.h \ - IEventQueue.h \ - IEventQueueBuffer.h \ - IJob.h \ - ILogOutputter.h \ - LogOutputters.h \ - TMethodEventJob.h \ - TMethodJob.h \ - XBase.h \ - $(NULL) -INCLUDES = \ - -I$(top_srcdir)/lib/common \ - -I$(top_srcdir)/lib/arch \ - $(NULL) diff --git a/lib/base/Makefile.win b/lib/base/Makefile.win deleted file mode 100644 index a386da17..00000000 --- a/lib/base/Makefile.win +++ /dev/null @@ -1,77 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2007 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -LIB_BASE_SRC = lib\base -LIB_BASE_DST = $(BUILD_DST)\$(LIB_BASE_SRC) -LIB_BASE_LIB = "$(LIB_BASE_DST)\base.lib" -LIB_BASE_CPP = \ - "CEvent.cpp" \ - "CEventQueue.cpp" \ - "CFunctionEventJob.cpp" \ - "CFunctionJob.cpp" \ - "CLog.cpp" \ - "CSimpleEventQueueBuffer.cpp" \ - "CStopwatch.cpp" \ - "CStringUtil.cpp" \ - "CUnicode.cpp" \ - "IEventQueue.cpp" \ - "LogOutputters.cpp" \ - "XBase.cpp" \ - $(NULL) -LIB_BASE_OBJ = \ - "$(LIB_BASE_DST)\CEvent.obj" \ - "$(LIB_BASE_DST)\CEventQueue.obj" \ - "$(LIB_BASE_DST)\CFunctionEventJob.obj" \ - "$(LIB_BASE_DST)\CFunctionJob.obj" \ - "$(LIB_BASE_DST)\CLog.obj" \ - "$(LIB_BASE_DST)\CSimpleEventQueueBuffer.obj" \ - "$(LIB_BASE_DST)\CStopwatch.obj" \ - "$(LIB_BASE_DST)\CStringUtil.obj" \ - "$(LIB_BASE_DST)\CUnicode.obj" \ - "$(LIB_BASE_DST)\IEventQueue.obj" \ - "$(LIB_BASE_DST)\LogOutputters.obj" \ - "$(LIB_BASE_DST)\XBase.obj" \ - $(NULL) -LIB_BASE_INC = \ - /I"lib\common" \ - /I"lib\arch" \ - $(NULL) - -CPP_FILES = $(CPP_FILES) $(LIB_BASE_CPP) -OBJ_FILES = $(OBJ_FILES) $(LIB_BASE_OBJ) -LIB_FILES = $(LIB_FILES) $(LIB_BASE_LIB) - -# Dependency rules -$(LIB_BASE_OBJ): $(AUTODEP) -!if EXIST($(LIB_BASE_DST)\deps.mak) -!include $(LIB_BASE_DST)\deps.mak -!endif - -# Build rules. Use batch-mode rules if possible. -!if DEFINED(_NMAKE_VER) -{$(LIB_BASE_SRC)\}.cpp{$(LIB_BASE_DST)\}.obj:: -!else -{$(LIB_BASE_SRC)\}.cpp{$(LIB_BASE_DST)\}.obj: -!endif - @$(ECHO) Compile in $(LIB_BASE_SRC) - -@$(MKDIR) $(LIB_BASE_DST) 2>NUL: - $(cpp) $(cppdebug) $(cppflags) $(cppvarsmt) /showIncludes \ - $(LIB_BASE_INC) \ - /Fo$(LIB_BASE_DST)\ \ - /Fd$(LIB_BASE_LIB:.lib=.pdb) \ - $< | $(AUTODEP) $(LIB_BASE_SRC) $(LIB_BASE_DST) -$(LIB_BASE_LIB): $(LIB_BASE_OBJ) - @$(ECHO) Link $(@F) - $(implib) $(ildebug) $(ilflags) \ - /out:$@ \ - $** - $(AUTODEP) $(LIB_BASE_SRC) $(LIB_BASE_DST) $(**:.obj=.d) diff --git a/lib/base/TMethodEventJob.h b/lib/base/TMethodEventJob.h deleted file mode 100644 index 15826be0..00000000 --- a/lib/base/TMethodEventJob.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CMETHODEVENTJOB_H -#define CMETHODEVENTJOB_H - -#include "IEventJob.h" - -//! Use a member function as an event job -/*! -An event job class that invokes a member function. -*/ -template -class TMethodEventJob : public IEventJob { -public: - //! run(event) invokes \c object->method(event, arg) - TMethodEventJob(T* object, - void (T::*method)(const CEvent&, void*), - void* arg = NULL); - virtual ~TMethodEventJob(); - - // IJob overrides - virtual void run(const CEvent&); - -private: - T* m_object; - void (T::*m_method)(const CEvent&, void*); - void* m_arg; -}; - -template -inline -TMethodEventJob::TMethodEventJob(T* object, - void (T::*method)(const CEvent&, void*), void* arg) : - m_object(object), - m_method(method), - m_arg(arg) -{ - // do nothing -} - -template -inline -TMethodEventJob::~TMethodEventJob() -{ - // do nothing -} - -template -inline -void -TMethodEventJob::run(const CEvent& event) -{ - if (m_object != NULL) { - (m_object->*m_method)(event, m_arg); - } -} - -#endif diff --git a/lib/base/TMethodJob.h b/lib/base/TMethodJob.h deleted file mode 100644 index 54cd936b..00000000 --- a/lib/base/TMethodJob.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CMETHODJOB_H -#define CMETHODJOB_H - -#include "IJob.h" - -//! Use a function as a job -/*! -A job class that invokes a member function. -*/ -template -class TMethodJob : public IJob { -public: - //! run() invokes \c object->method(arg) - TMethodJob(T* object, void (T::*method)(void*), void* arg = NULL); - virtual ~TMethodJob(); - - // IJob overrides - virtual void run(); - -private: - T* m_object; - void (T::*m_method)(void*); - void* m_arg; -}; - -template -inline -TMethodJob::TMethodJob(T* object, void (T::*method)(void*), void* arg) : - m_object(object), - m_method(method), - m_arg(arg) -{ - // do nothing -} - -template -inline -TMethodJob::~TMethodJob() -{ - // do nothing -} - -template -inline -void -TMethodJob::run() -{ - if (m_object != NULL) { - (m_object->*m_method)(m_arg); - } -} - -#endif diff --git a/lib/base/XBase.cpp b/lib/base/XBase.cpp deleted file mode 100644 index 022be306..00000000 --- a/lib/base/XBase.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "XBase.h" -#include "CStringUtil.h" -#include -#include - -// -// XBase -// - -XBase::XBase() : - m_what() -{ - // do nothing -} - -XBase::XBase(const CString& msg) : - m_what(msg) -{ - // do nothing -} - -XBase::~XBase() -{ - // do nothing -} - -const char* -XBase::what() const -{ - if (m_what.empty()) { - m_what = getWhat(); - } - return m_what.c_str(); -} - -CString -XBase::format(const char* /*id*/, const char* fmt, ...) const throw() -{ - // FIXME -- lookup message string using id as an index. set - // fmt to that string if it exists. - - // format - CString result; - va_list args; - va_start(args, fmt); - try { - result = CStringUtil::vformat(fmt, args); - } - catch (...) { - // ignore - } - va_end(args); - - return result; -} diff --git a/lib/base/XBase.h b/lib/base/XBase.h deleted file mode 100644 index e9161d70..00000000 --- a/lib/base/XBase.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef XBASE_H -#define XBASE_H - -#include "CString.h" - -//! Exception base class -/*! -This is the base class of most exception types. -*/ -class XBase { -public: - //! Use getWhat() as the result of what() - XBase(); - //! Use \c msg as the result of what() - XBase(const CString& msg); - virtual ~XBase(); - - //! Reason for exception - virtual const char* what() const; - -protected: - //! Get a human readable string describing the exception - virtual CString getWhat() const throw() = 0; - - //! Format a string - /*! - Looks up a message format using \c id, using \c defaultFormat if - no format can be found, then replaces positional parameters in - the format string and returns the result. - */ - virtual CString format(const char* id, - const char* defaultFormat, ...) const throw(); - -private: - mutable CString m_what; -}; - -/*! -\def XBASE_SUBCLASS -Convenience macro to subclass from XBase (or a subclass of it), -providing the c'tor taking a const CString&. getWhat() is not -declared. -*/ -#define XBASE_SUBCLASS(name_, super_) \ -class name_ : public super_ { \ -public: \ - name_() : super_() { } \ - name_(const CString& msg) : super_(msg) { } \ -} - -/*! -\def XBASE_SUBCLASS -Convenience macro to subclass from XBase (or a subclass of it), -providing the c'tor taking a const CString&. getWhat() must be -implemented. -*/ -#define XBASE_SUBCLASS_WHAT(name_, super_) \ -class name_ : public super_ { \ -public: \ - name_() : super_() { } \ - name_(const CString& msg) : super_(msg) { } \ - \ -protected: \ - virtual CString getWhat() const throw(); \ -} - -/*! -\def XBASE_SUBCLASS_FORMAT -Convenience macro to subclass from XBase (or a subclass of it), -providing the c'tor taking a const CString&. what() is overridden -to call getWhat() when first called; getWhat() can format the -error message and can call what() to get the message passed to the -c'tor. -*/ -#define XBASE_SUBCLASS_FORMAT(name_, super_) \ -class name_ : public super_ { \ -private: \ - enum EState { kFirst, kFormat, kDone }; \ - \ -public: \ - name_() : super_(), m_state(kDone) { } \ - name_(const CString& msg) : super_(msg), m_state(kFirst) { } \ - \ - virtual const char* what() const \ - { \ - if (m_state == kFirst) { \ - m_state = kFormat; \ - m_formatted = getWhat(); \ - m_state = kDone; \ - } \ - if (m_state == kDone) { \ - return m_formatted.c_str(); \ - } \ - else { \ - return super_::what(); \ - } \ - } \ - \ -protected: \ - virtual CString getWhat() const throw(); \ - \ -private: \ - mutable EState m_state; \ - mutable std::string m_formatted; \ -} - -#endif diff --git a/lib/client/CClient.cpp b/lib/client/CClient.cpp deleted file mode 100644 index 1e450a17..00000000 --- a/lib/client/CClient.cpp +++ /dev/null @@ -1,662 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CClient.h" -#include "CServerProxy.h" -#include "CScreen.h" -#include "CClipboard.h" -#include "CPacketStreamFilter.h" -#include "CProtocolUtil.h" -#include "ProtocolTypes.h" -#include "XSynergy.h" -#include "IDataSocket.h" -#include "ISocketFactory.h" -#include "IStreamFilterFactory.h" -#include "CLog.h" -#include "IEventQueue.h" -#include "TMethodEventJob.h" - -// -// CClient -// - -CEvent::Type CClient::s_connectedEvent = CEvent::kUnknown; -CEvent::Type CClient::s_connectionFailedEvent = CEvent::kUnknown; -CEvent::Type CClient::s_disconnectedEvent = CEvent::kUnknown; - -CClient::CClient(const CString& name, const CNetworkAddress& address, - ISocketFactory* socketFactory, - IStreamFilterFactory* streamFilterFactory, - CScreen* screen) : - m_name(name), - m_serverAddress(address), - m_socketFactory(socketFactory), - m_streamFilterFactory(streamFilterFactory), - m_screen(screen), - m_stream(NULL), - m_timer(NULL), - m_server(NULL), - m_ready(false), - m_active(false), - m_suspended(false), - m_connectOnResume(false) -{ - assert(m_socketFactory != NULL); - assert(m_screen != NULL); - - // register suspend/resume event handlers - EVENTQUEUE->adoptHandler(IScreen::getSuspendEvent(), - getEventTarget(), - new TMethodEventJob(this, - &CClient::handleSuspend)); - EVENTQUEUE->adoptHandler(IScreen::getResumeEvent(), - getEventTarget(), - new TMethodEventJob(this, - &CClient::handleResume)); -} - -CClient::~CClient() -{ - EVENTQUEUE->removeHandler(IScreen::getSuspendEvent(), - getEventTarget()); - EVENTQUEUE->removeHandler(IScreen::getResumeEvent(), - getEventTarget()); - - cleanupTimer(); - cleanupScreen(); - cleanupConnecting(); - cleanupConnection(); - delete m_socketFactory; - delete m_streamFilterFactory; -} - -void -CClient::connect() -{ - if (m_stream != NULL) { - return; - } - if (m_suspended) { - m_connectOnResume = true; - return; - } - - try { - // resolve the server hostname. do this every time we connect - // in case we couldn't resolve the address earlier or the address - // has changed (which can happen frequently if this is a laptop - // being shuttled between various networks). patch by Brent - // Priddy. - m_serverAddress.resolve(); - - // create the socket - IDataSocket* socket = m_socketFactory->create(); - - // filter socket messages, including a packetizing filter - m_stream = socket; - if (m_streamFilterFactory != NULL) { - m_stream = m_streamFilterFactory->create(m_stream, true); - } - m_stream = new CPacketStreamFilter(m_stream, true); - - // connect - LOG((CLOG_DEBUG1 "connecting to server")); - setupConnecting(); - setupTimer(); - socket->connect(m_serverAddress); - } - catch (XBase& e) { - cleanupTimer(); - cleanupConnecting(); - delete m_stream; - m_stream = NULL; - LOG((CLOG_DEBUG1 "connection failed")); - sendConnectionFailedEvent(e.what()); - return; - } -} - -void -CClient::disconnect(const char* msg) -{ - m_connectOnResume = false; - cleanupTimer(); - cleanupScreen(); - cleanupConnecting(); - cleanupConnection(); - if (msg != NULL) { - sendConnectionFailedEvent(msg); - } - else { - sendEvent(getDisconnectedEvent(), NULL); - } -} - -void -CClient::handshakeComplete() -{ - m_ready = true; - m_screen->enable(); - sendEvent(getConnectedEvent(), NULL); -} - -bool -CClient::isConnected() const -{ - return (m_server != NULL); -} - -bool -CClient::isConnecting() const -{ - return (m_timer != NULL); -} - -CNetworkAddress -CClient::getServerAddress() const -{ - return m_serverAddress; -} - -CEvent::Type -CClient::getConnectedEvent() -{ - return CEvent::registerTypeOnce(s_connectedEvent, - "CClient::connected"); -} - -CEvent::Type -CClient::getConnectionFailedEvent() -{ - return CEvent::registerTypeOnce(s_connectionFailedEvent, - "CClient::failed"); -} - -CEvent::Type -CClient::getDisconnectedEvent() -{ - return CEvent::registerTypeOnce(s_disconnectedEvent, - "CClient::disconnected"); -} - -void* -CClient::getEventTarget() const -{ - return m_screen->getEventTarget(); -} - -bool -CClient::getClipboard(ClipboardID id, IClipboard* clipboard) const -{ - return m_screen->getClipboard(id, clipboard); -} - -void -CClient::getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h) const -{ - m_screen->getShape(x, y, w, h); -} - -void -CClient::getCursorPos(SInt32& x, SInt32& y) const -{ - m_screen->getCursorPos(x, y); -} - -void -CClient::enter(SInt32 xAbs, SInt32 yAbs, UInt32, KeyModifierMask mask, bool) -{ - m_active = true; - m_screen->mouseMove(xAbs, yAbs); - m_screen->enter(mask); -} - -bool -CClient::leave() -{ - m_screen->leave(); - - m_active = false; - - // send clipboards that we own and that have changed - for (ClipboardID id = 0; id < kClipboardEnd; ++id) { - if (m_ownClipboard[id]) { - sendClipboard(id); - } - } - - return true; -} - -void -CClient::setClipboard(ClipboardID id, const IClipboard* clipboard) -{ - m_screen->setClipboard(id, clipboard); - m_ownClipboard[id] = false; - m_sentClipboard[id] = false; -} - -void -CClient::grabClipboard(ClipboardID id) -{ - m_screen->grabClipboard(id); - m_ownClipboard[id] = false; - m_sentClipboard[id] = false; -} - -void -CClient::setClipboardDirty(ClipboardID, bool) -{ - assert(0 && "shouldn't be called"); -} - -void -CClient::keyDown(KeyID id, KeyModifierMask mask, KeyButton button) -{ - m_screen->keyDown(id, mask, button); -} - -void -CClient::keyRepeat(KeyID id, KeyModifierMask mask, - SInt32 count, KeyButton button) -{ - m_screen->keyRepeat(id, mask, count, button); -} - -void -CClient::keyUp(KeyID id, KeyModifierMask mask, KeyButton button) -{ - m_screen->keyUp(id, mask, button); -} - -void -CClient::mouseDown(ButtonID id) -{ - m_screen->mouseDown(id); -} - -void -CClient::mouseUp(ButtonID id) -{ - m_screen->mouseUp(id); -} - -void -CClient::mouseMove(SInt32 x, SInt32 y) -{ - m_screen->mouseMove(x, y); -} - -void -CClient::mouseRelativeMove(SInt32 dx, SInt32 dy) -{ - m_screen->mouseRelativeMove(dx, dy); -} - -void -CClient::mouseWheel(SInt32 xDelta, SInt32 yDelta) -{ - m_screen->mouseWheel(xDelta, yDelta); -} - -void -CClient::screensaver(bool activate) -{ - m_screen->screensaver(activate); -} - -void -CClient::resetOptions() -{ - m_screen->resetOptions(); -} - -void -CClient::setOptions(const COptionsList& options) -{ - m_screen->setOptions(options); -} - -CString -CClient::getName() const -{ - return m_name; -} - -void -CClient::sendClipboard(ClipboardID id) -{ - // note -- m_mutex must be locked on entry - assert(m_screen != NULL); - assert(m_server != NULL); - - // get clipboard data. set the clipboard time to the last - // clipboard time before getting the data from the screen - // as the screen may detect an unchanged clipboard and - // avoid copying the data. - CClipboard clipboard; - if (clipboard.open(m_timeClipboard[id])) { - clipboard.close(); - } - m_screen->getClipboard(id, &clipboard); - - // check time - if (m_timeClipboard[id] == 0 || - clipboard.getTime() != m_timeClipboard[id]) { - // save new time - m_timeClipboard[id] = clipboard.getTime(); - - // marshall the data - CString data = clipboard.marshall(); - - // save and send data if different or not yet sent - if (!m_sentClipboard[id] || data != m_dataClipboard[id]) { - m_sentClipboard[id] = true; - m_dataClipboard[id] = data; - m_server->onClipboardChanged(id, &clipboard); - } - } -} - -void -CClient::sendEvent(CEvent::Type type, void* data) -{ - EVENTQUEUE->addEvent(CEvent(type, getEventTarget(), data)); -} - -void -CClient::sendConnectionFailedEvent(const char* msg) -{ - CFailInfo* info = (CFailInfo*)malloc(sizeof(CFailInfo) + strlen(msg)); - info->m_retry = true; - strcpy(info->m_what, msg); - sendEvent(getConnectionFailedEvent(), info); -} - -void -CClient::setupConnecting() -{ - assert(m_stream != NULL); - - EVENTQUEUE->adoptHandler(IDataSocket::getConnectedEvent(), - m_stream->getEventTarget(), - new TMethodEventJob(this, - &CClient::handleConnected)); - EVENTQUEUE->adoptHandler(IDataSocket::getConnectionFailedEvent(), - m_stream->getEventTarget(), - new TMethodEventJob(this, - &CClient::handleConnectionFailed)); -} - -void -CClient::setupConnection() -{ - assert(m_stream != NULL); - - EVENTQUEUE->adoptHandler(ISocket::getDisconnectedEvent(), - m_stream->getEventTarget(), - new TMethodEventJob(this, - &CClient::handleDisconnected)); - EVENTQUEUE->adoptHandler(IStream::getInputReadyEvent(), - m_stream->getEventTarget(), - new TMethodEventJob(this, - &CClient::handleHello)); - EVENTQUEUE->adoptHandler(IStream::getOutputErrorEvent(), - m_stream->getEventTarget(), - new TMethodEventJob(this, - &CClient::handleOutputError)); - EVENTQUEUE->adoptHandler(IStream::getInputShutdownEvent(), - m_stream->getEventTarget(), - new TMethodEventJob(this, - &CClient::handleDisconnected)); - EVENTQUEUE->adoptHandler(IStream::getOutputShutdownEvent(), - m_stream->getEventTarget(), - new TMethodEventJob(this, - &CClient::handleDisconnected)); -} - -void -CClient::setupScreen() -{ - assert(m_server == NULL); - - m_ready = false; - m_server = new CServerProxy(this, m_stream); - EVENTQUEUE->adoptHandler(IScreen::getShapeChangedEvent(), - getEventTarget(), - new TMethodEventJob(this, - &CClient::handleShapeChanged)); - EVENTQUEUE->adoptHandler(IScreen::getClipboardGrabbedEvent(), - getEventTarget(), - new TMethodEventJob(this, - &CClient::handleClipboardGrabbed)); -} - -void -CClient::setupTimer() -{ - assert(m_timer == NULL); - - m_timer = EVENTQUEUE->newOneShotTimer(15.0, NULL); - EVENTQUEUE->adoptHandler(CEvent::kTimer, m_timer, - new TMethodEventJob(this, - &CClient::handleConnectTimeout)); -} - -void -CClient::cleanupConnecting() -{ - if (m_stream != NULL) { - EVENTQUEUE->removeHandler(IDataSocket::getConnectedEvent(), - m_stream->getEventTarget()); - EVENTQUEUE->removeHandler(IDataSocket::getConnectionFailedEvent(), - m_stream->getEventTarget()); - } -} - -void -CClient::cleanupConnection() -{ - if (m_stream != NULL) { - EVENTQUEUE->removeHandler(IStream::getInputReadyEvent(), - m_stream->getEventTarget()); - EVENTQUEUE->removeHandler(IStream::getOutputErrorEvent(), - m_stream->getEventTarget()); - EVENTQUEUE->removeHandler(IStream::getInputShutdownEvent(), - m_stream->getEventTarget()); - EVENTQUEUE->removeHandler(IStream::getOutputShutdownEvent(), - m_stream->getEventTarget()); - EVENTQUEUE->removeHandler(ISocket::getDisconnectedEvent(), - m_stream->getEventTarget()); - delete m_stream; - m_stream = NULL; - } -} - -void -CClient::cleanupScreen() -{ - if (m_server != NULL) { - if (m_ready) { - m_screen->disable(); - m_ready = false; - } - EVENTQUEUE->removeHandler(IScreen::getShapeChangedEvent(), - getEventTarget()); - EVENTQUEUE->removeHandler(IScreen::getClipboardGrabbedEvent(), - getEventTarget()); - delete m_server; - m_server = NULL; - } -} - -void -CClient::cleanupTimer() -{ - if (m_timer != NULL) { - EVENTQUEUE->removeHandler(CEvent::kTimer, m_timer); - EVENTQUEUE->deleteTimer(m_timer); - m_timer = NULL; - } -} - -void -CClient::handleConnected(const CEvent&, void*) -{ - LOG((CLOG_DEBUG1 "connected; wait for hello")); - cleanupConnecting(); - setupConnection(); - - // reset clipboard state - for (ClipboardID id = 0; id < kClipboardEnd; ++id) { - m_ownClipboard[id] = false; - m_sentClipboard[id] = false; - m_timeClipboard[id] = 0; - } -} - -void -CClient::handleConnectionFailed(const CEvent& event, void*) -{ - IDataSocket::CConnectionFailedInfo* info = - reinterpret_cast(event.getData()); - - cleanupTimer(); - cleanupConnecting(); - delete m_stream; - m_stream = NULL; - LOG((CLOG_DEBUG1 "connection failed")); - sendConnectionFailedEvent(info->m_what); -} - -void -CClient::handleConnectTimeout(const CEvent&, void*) -{ - cleanupTimer(); - cleanupConnecting(); - cleanupConnection(); - delete m_stream; - m_stream = NULL; - LOG((CLOG_DEBUG1 "connection timed out")); - sendConnectionFailedEvent("Timed out"); -} - -void -CClient::handleOutputError(const CEvent&, void*) -{ - cleanupTimer(); - cleanupScreen(); - cleanupConnection(); - LOG((CLOG_WARN "error sending to server")); - sendEvent(getDisconnectedEvent(), NULL); -} - -void -CClient::handleDisconnected(const CEvent&, void*) -{ - cleanupTimer(); - cleanupScreen(); - cleanupConnection(); - LOG((CLOG_DEBUG1 "disconnected")); - sendEvent(getDisconnectedEvent(), NULL); -} - -void -CClient::handleShapeChanged(const CEvent&, void*) -{ - LOG((CLOG_DEBUG "resolution changed")); - m_server->onInfoChanged(); -} - -void -CClient::handleClipboardGrabbed(const CEvent& event, void*) -{ - const IScreen::CClipboardInfo* info = - reinterpret_cast(event.getData()); - - // grab ownership - m_server->onGrabClipboard(info->m_id); - - // we now own the clipboard and it has not been sent to the server - m_ownClipboard[info->m_id] = true; - m_sentClipboard[info->m_id] = false; - m_timeClipboard[info->m_id] = 0; - - // if we're not the active screen then send the clipboard now, - // otherwise we'll wait until we leave. - if (!m_active) { - sendClipboard(info->m_id); - } -} - -void -CClient::handleHello(const CEvent&, void*) -{ - SInt16 major, minor; - if (!CProtocolUtil::readf(m_stream, kMsgHello, &major, &minor)) { - sendConnectionFailedEvent("Protocol error from server"); - cleanupTimer(); - cleanupConnection(); - return; - } - - // check versions - LOG((CLOG_DEBUG1 "got hello version %d.%d", major, minor)); - if (major < kProtocolMajorVersion || - (major == kProtocolMajorVersion && minor < kProtocolMinorVersion)) { - sendConnectionFailedEvent(XIncompatibleClient(major, minor).what()); - cleanupTimer(); - cleanupConnection(); - return; - } - - // say hello back - LOG((CLOG_DEBUG1 "say hello version %d.%d", kProtocolMajorVersion, kProtocolMinorVersion)); - CProtocolUtil::writef(m_stream, kMsgHelloBack, - kProtocolMajorVersion, - kProtocolMinorVersion, &m_name); - - // now connected but waiting to complete handshake - setupScreen(); - cleanupTimer(); - - // make sure we process any remaining messages later. we won't - // receive another event for already pending messages so we fake - // one. - if (m_stream->isReady()) { - EVENTQUEUE->addEvent(CEvent(IStream::getInputReadyEvent(), - m_stream->getEventTarget())); - } -} - -void -CClient::handleSuspend(const CEvent&, void*) -{ - LOG((CLOG_INFO "suspend")); - m_suspended = true; - bool wasConnected = isConnected(); - disconnect(NULL); - m_connectOnResume = wasConnected; -} - -void -CClient::handleResume(const CEvent&, void*) -{ - LOG((CLOG_INFO "resume")); - m_suspended = false; - if (m_connectOnResume) { - m_connectOnResume = false; - connect(); - } -} diff --git a/lib/client/CClient.h b/lib/client/CClient.h deleted file mode 100644 index 4bd11c66..00000000 --- a/lib/client/CClient.h +++ /dev/null @@ -1,198 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CCLIENT_H -#define CCLIENT_H - -#include "IClient.h" -#include "IClipboard.h" -#include "CNetworkAddress.h" - -class CEventQueueTimer; -class CScreen; -class CServerProxy; -class IDataSocket; -class ISocketFactory; -class IStream; -class IStreamFilterFactory; - -//! Synergy client -/*! -This class implements the top-level client algorithms for synergy. -*/ -class CClient : public IClient { -public: - class CFailInfo { - public: - bool m_retry; - char m_what[1]; - }; - - /*! - This client will attempt to connect to the server using \p name - as its name and \p address as the server's address and \p factory - to create the socket. \p screen is the local screen. - */ - CClient(const CString& name, const CNetworkAddress& address, - ISocketFactory* socketFactory, - IStreamFilterFactory* streamFilterFactory, - CScreen* screen); - ~CClient(); - - //! @name manipulators - //@{ - - //! Connect to server - /*! - Starts an attempt to connect to the server. This is ignored if - the client is trying to connect or is already connected. - */ - void connect(); - - //! Disconnect - /*! - Disconnects from the server with an optional error message. - */ - void disconnect(const char* msg); - - //! Notify of handshake complete - /*! - Notifies the client that the connection handshake has completed. - */ - void handshakeComplete(); - - //@} - //! @name accessors - //@{ - - //! Test if connected - /*! - Returns true iff the client is successfully connected to the server. - */ - bool isConnected() const; - - //! Test if connecting - /*! - Returns true iff the client is currently attempting to connect to - the server. - */ - bool isConnecting() const; - - //! Get address of server - /*! - Returns the address of the server the client is connected (or wants - to connect) to. - */ - CNetworkAddress getServerAddress() const; - - //! Get connected event type - /*! - Returns the connected event type. This is sent when the client has - successfully connected to the server. - */ - static CEvent::Type getConnectedEvent(); - - //! Get connection failed event type - /*! - Returns the connection failed event type. This is sent when the - server fails for some reason. The event data is a CFailInfo*. - */ - static CEvent::Type getConnectionFailedEvent(); - - //! Get disconnected event type - /*! - Returns the disconnected event type. This is sent when the client - has disconnected from the server (and only after having successfully - connected). - */ - static CEvent::Type getDisconnectedEvent(); - - //@} - - // IScreen overrides - virtual void* getEventTarget() const; - virtual bool getClipboard(ClipboardID id, IClipboard*) const; - virtual void getShape(SInt32& x, SInt32& y, - SInt32& width, SInt32& height) const; - virtual void getCursorPos(SInt32& x, SInt32& y) const; - - // IClient overrides - virtual void enter(SInt32 xAbs, SInt32 yAbs, - UInt32 seqNum, KeyModifierMask mask, - bool forScreensaver); - virtual bool leave(); - virtual void setClipboard(ClipboardID, const IClipboard*); - virtual void grabClipboard(ClipboardID); - virtual void setClipboardDirty(ClipboardID, bool); - virtual void keyDown(KeyID, KeyModifierMask, KeyButton); - virtual void keyRepeat(KeyID, KeyModifierMask, - SInt32 count, KeyButton); - virtual void keyUp(KeyID, KeyModifierMask, KeyButton); - virtual void mouseDown(ButtonID); - virtual void mouseUp(ButtonID); - virtual void mouseMove(SInt32 xAbs, SInt32 yAbs); - virtual void mouseRelativeMove(SInt32 xRel, SInt32 yRel); - virtual void mouseWheel(SInt32 xDelta, SInt32 yDelta); - virtual void screensaver(bool activate); - virtual void resetOptions(); - virtual void setOptions(const COptionsList& options); - virtual CString getName() const; - -private: - void sendClipboard(ClipboardID); - void sendEvent(CEvent::Type, void*); - void sendConnectionFailedEvent(const char* msg); - void setupConnecting(); - void setupConnection(); - void setupScreen(); - void setupTimer(); - void cleanupConnecting(); - void cleanupConnection(); - void cleanupScreen(); - void cleanupTimer(); - void handleConnected(const CEvent&, void*); - void handleConnectionFailed(const CEvent&, void*); - void handleConnectTimeout(const CEvent&, void*); - void handleOutputError(const CEvent&, void*); - void handleDisconnected(const CEvent&, void*); - void handleShapeChanged(const CEvent&, void*); - void handleClipboardGrabbed(const CEvent&, void*); - void handleHello(const CEvent&, void*); - void handleSuspend(const CEvent& event, void*); - void handleResume(const CEvent& event, void*); - -private: - CString m_name; - CNetworkAddress m_serverAddress; - ISocketFactory* m_socketFactory; - IStreamFilterFactory* m_streamFilterFactory; - CScreen* m_screen; - IStream* m_stream; - CEventQueueTimer* m_timer; - CServerProxy* m_server; - bool m_ready; - bool m_active; - bool m_suspended; - bool m_connectOnResume; - bool m_ownClipboard[kClipboardEnd]; - bool m_sentClipboard[kClipboardEnd]; - IClipboard::Time m_timeClipboard[kClipboardEnd]; - CString m_dataClipboard[kClipboardEnd]; - - static CEvent::Type s_connectedEvent; - static CEvent::Type s_connectionFailedEvent; - static CEvent::Type s_disconnectedEvent; -}; - -#endif diff --git a/lib/client/CServerProxy.cpp b/lib/client/CServerProxy.cpp deleted file mode 100644 index acef43b2..00000000 --- a/lib/client/CServerProxy.cpp +++ /dev/null @@ -1,816 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CServerProxy.h" -#include "CClient.h" -#include "CClipboard.h" -#include "CProtocolUtil.h" -#include "OptionTypes.h" -#include "ProtocolTypes.h" -#include "IStream.h" -#include "CLog.h" -#include "IEventQueue.h" -#include "TMethodEventJob.h" -#include "XBase.h" -#include - -// -// CServerProxy -// - -CServerProxy::CServerProxy(CClient* client, IStream* stream) : - m_client(client), - m_stream(stream), - m_seqNum(0), - m_compressMouse(false), - m_compressMouseRelative(false), - m_xMouse(0), - m_yMouse(0), - m_dxMouse(0), - m_dyMouse(0), - m_ignoreMouse(false), - m_keepAliveAlarm(0.0), - m_keepAliveAlarmTimer(NULL), - m_parser(&CServerProxy::parseHandshakeMessage) -{ - assert(m_client != NULL); - assert(m_stream != NULL); - - // initialize modifier translation table - for (KeyModifierID id = 0; id < kKeyModifierIDLast; ++id) - m_modifierTranslationTable[id] = id; - - // handle data on stream - EVENTQUEUE->adoptHandler(IStream::getInputReadyEvent(), - m_stream->getEventTarget(), - new TMethodEventJob(this, - &CServerProxy::handleData)); - - // send heartbeat - setKeepAliveRate(kKeepAliveRate); -} - -CServerProxy::~CServerProxy() -{ - setKeepAliveRate(-1.0); - EVENTQUEUE->removeHandler(IStream::getInputReadyEvent(), - m_stream->getEventTarget()); -} - -void -CServerProxy::resetKeepAliveAlarm() -{ - if (m_keepAliveAlarmTimer != NULL) { - EVENTQUEUE->removeHandler(CEvent::kTimer, m_keepAliveAlarmTimer); - EVENTQUEUE->deleteTimer(m_keepAliveAlarmTimer); - m_keepAliveAlarmTimer = NULL; - } - if (m_keepAliveAlarm > 0.0) { - m_keepAliveAlarmTimer = - EVENTQUEUE->newOneShotTimer(m_keepAliveAlarm, NULL); - EVENTQUEUE->adoptHandler(CEvent::kTimer, m_keepAliveAlarmTimer, - new TMethodEventJob(this, - &CServerProxy::handleKeepAliveAlarm)); - } -} - -void -CServerProxy::setKeepAliveRate(double rate) -{ - m_keepAliveAlarm = rate * kKeepAlivesUntilDeath; - resetKeepAliveAlarm(); -} - -void -CServerProxy::handleData(const CEvent&, void*) -{ - // handle messages until there are no more. first read message code. - UInt8 code[4]; - UInt32 n = m_stream->read(code, 4); - while (n != 0) { - // verify we got an entire code - if (n != 4) { - LOG((CLOG_ERR "incomplete message from server: %d bytes", n)); - m_client->disconnect("incomplete message from server"); - return; - } - - // parse message - LOG((CLOG_DEBUG2 "msg from server: %c%c%c%c", code[0], code[1], code[2], code[3])); - switch ((this->*m_parser)(code)) { - case kOkay: - break; - - case kUnknown: - LOG((CLOG_ERR "invalid message from server: %c%c%c%c", code[0], code[1], code[2], code[3])); - m_client->disconnect("invalid message from server"); - return; - - case kDisconnect: - return; - } - - // next message - n = m_stream->read(code, 4); - } - - flushCompressedMouse(); -} - -CServerProxy::EResult -CServerProxy::parseHandshakeMessage(const UInt8* code) -{ - if (memcmp(code, kMsgQInfo, 4) == 0) { - queryInfo(); - } - - else if (memcmp(code, kMsgCInfoAck, 4) == 0) { - infoAcknowledgment(); - } - - else if (memcmp(code, kMsgDSetOptions, 4) == 0) { - setOptions(); - - // handshake is complete - m_parser = &CServerProxy::parseMessage; - m_client->handshakeComplete(); - } - - else if (memcmp(code, kMsgCResetOptions, 4) == 0) { - resetOptions(); - } - - else if (memcmp(code, kMsgCKeepAlive, 4) == 0) { - // echo keep alives and reset alarm - CProtocolUtil::writef(m_stream, kMsgCKeepAlive); - resetKeepAliveAlarm(); - } - - else if (memcmp(code, kMsgCNoop, 4) == 0) { - // accept and discard no-op - } - - else if (memcmp(code, kMsgCClose, 4) == 0) { - // server wants us to hangup - LOG((CLOG_DEBUG1 "recv close")); - m_client->disconnect(NULL); - return kDisconnect; - } - - else if (memcmp(code, kMsgEIncompatible, 4) == 0) { - SInt32 major, minor; - CProtocolUtil::readf(m_stream, - kMsgEIncompatible + 4, &major, &minor); - LOG((CLOG_ERR "server has incompatible version %d.%d", major, minor)); - m_client->disconnect("server has incompatible version"); - return kDisconnect; - } - - else if (memcmp(code, kMsgEBusy, 4) == 0) { - LOG((CLOG_ERR "server already has a connected client with name \"%s\"", m_client->getName().c_str())); - m_client->disconnect("server already has a connected client with our name"); - return kDisconnect; - } - - else if (memcmp(code, kMsgEUnknown, 4) == 0) { - LOG((CLOG_ERR "server refused client with name \"%s\"", m_client->getName().c_str())); - m_client->disconnect("server refused client with our name"); - return kDisconnect; - } - - else if (memcmp(code, kMsgEBad, 4) == 0) { - LOG((CLOG_ERR "server disconnected due to a protocol error")); - m_client->disconnect("server reported a protocol error"); - return kDisconnect; - } - else { - return kUnknown; - } - - return kOkay; -} - -CServerProxy::EResult -CServerProxy::parseMessage(const UInt8* code) -{ - if (memcmp(code, kMsgDMouseMove, 4) == 0) { - mouseMove(); - } - - else if (memcmp(code, kMsgDMouseRelMove, 4) == 0) { - mouseRelativeMove(); - } - - else if (memcmp(code, kMsgDMouseWheel, 4) == 0) { - mouseWheel(); - } - - else if (memcmp(code, kMsgDKeyDown, 4) == 0) { - keyDown(); - } - - else if (memcmp(code, kMsgDKeyUp, 4) == 0) { - keyUp(); - } - - else if (memcmp(code, kMsgDMouseDown, 4) == 0) { - mouseDown(); - } - - else if (memcmp(code, kMsgDMouseUp, 4) == 0) { - mouseUp(); - } - - else if (memcmp(code, kMsgDKeyRepeat, 4) == 0) { - keyRepeat(); - } - - else if (memcmp(code, kMsgCKeepAlive, 4) == 0) { - // echo keep alives and reset alarm - CProtocolUtil::writef(m_stream, kMsgCKeepAlive); - resetKeepAliveAlarm(); - } - - else if (memcmp(code, kMsgCNoop, 4) == 0) { - // accept and discard no-op - } - - else if (memcmp(code, kMsgCEnter, 4) == 0) { - enter(); - } - - else if (memcmp(code, kMsgCLeave, 4) == 0) { - leave(); - } - - else if (memcmp(code, kMsgCClipboard, 4) == 0) { - grabClipboard(); - } - - else if (memcmp(code, kMsgCScreenSaver, 4) == 0) { - screensaver(); - } - - else if (memcmp(code, kMsgQInfo, 4) == 0) { - queryInfo(); - } - - else if (memcmp(code, kMsgCInfoAck, 4) == 0) { - infoAcknowledgment(); - } - - else if (memcmp(code, kMsgDClipboard, 4) == 0) { - setClipboard(); - } - - else if (memcmp(code, kMsgCResetOptions, 4) == 0) { - resetOptions(); - } - - else if (memcmp(code, kMsgDSetOptions, 4) == 0) { - setOptions(); - } - - else if (memcmp(code, kMsgCClose, 4) == 0) { - // server wants us to hangup - LOG((CLOG_DEBUG1 "recv close")); - m_client->disconnect(NULL); - return kDisconnect; - } - else if (memcmp(code, kMsgEBad, 4) == 0) { - LOG((CLOG_ERR "server disconnected due to a protocol error")); - m_client->disconnect("server reported a protocol error"); - return kDisconnect; - } - else { - return kUnknown; - } - - // send a reply. this is intended to work around a delay when - // running a linux server and an OS X (any BSD?) client. the - // client waits to send an ACK (if the system control flag - // net.inet.tcp.delayed_ack is 1) in hopes of piggybacking it - // on a data packet. we provide that packet here. i don't - // know why a delayed ACK should cause the server to wait since - // TCP_NODELAY is enabled. - CProtocolUtil::writef(m_stream, kMsgCNoop); - - return kOkay; -} - -void -CServerProxy::handleKeepAliveAlarm(const CEvent&, void*) -{ - LOG((CLOG_NOTE "server is dead")); - m_client->disconnect("server is not responding"); -} - -void -CServerProxy::onInfoChanged() -{ - // ignore mouse motion until we receive acknowledgment of our info - // change message. - m_ignoreMouse = true; - - // send info update - queryInfo(); -} - -bool -CServerProxy::onGrabClipboard(ClipboardID id) -{ - LOG((CLOG_DEBUG1 "sending clipboard %d changed", id)); - CProtocolUtil::writef(m_stream, kMsgCClipboard, id, m_seqNum); - return true; -} - -void -CServerProxy::onClipboardChanged(ClipboardID id, const IClipboard* clipboard) -{ - CString data = IClipboard::marshall(clipboard); - LOG((CLOG_DEBUG1 "sending clipboard %d seqnum=%d, size=%d", id, m_seqNum, data.size())); - CProtocolUtil::writef(m_stream, kMsgDClipboard, id, m_seqNum, &data); -} - -void -CServerProxy::flushCompressedMouse() -{ - if (m_compressMouse) { - m_compressMouse = false; - m_client->mouseMove(m_xMouse, m_yMouse); - } - if (m_compressMouseRelative) { - m_compressMouseRelative = false; - m_client->mouseRelativeMove(m_dxMouse, m_dyMouse); - m_dxMouse = 0; - m_dyMouse = 0; - } -} - -void -CServerProxy::sendInfo(const CClientInfo& info) -{ - LOG((CLOG_DEBUG1 "sending info shape=%d,%d %dx%d", info.m_x, info.m_y, info.m_w, info.m_h)); - CProtocolUtil::writef(m_stream, kMsgDInfo, - info.m_x, info.m_y, - info.m_w, info.m_h, 0, - info.m_mx, info.m_my); -} - -KeyID -CServerProxy::translateKey(KeyID id) const -{ - static const KeyID s_translationTable[kKeyModifierIDLast][2] = { - { kKeyNone, kKeyNone }, - { kKeyShift_L, kKeyShift_R }, - { kKeyControl_L, kKeyControl_R }, - { kKeyAlt_L, kKeyAlt_R }, - { kKeyMeta_L, kKeyMeta_R }, - { kKeySuper_L, kKeySuper_R } - }; - - KeyModifierID id2 = kKeyModifierIDNull; - UInt32 side = 0; - switch (id) { - case kKeyShift_L: - id2 = kKeyModifierIDShift; - side = 0; - break; - - case kKeyShift_R: - id2 = kKeyModifierIDShift; - side = 1; - break; - - case kKeyControl_L: - id2 = kKeyModifierIDControl; - side = 0; - break; - - case kKeyControl_R: - id2 = kKeyModifierIDControl; - side = 1; - break; - - case kKeyAlt_L: - id2 = kKeyModifierIDAlt; - side = 0; - break; - - case kKeyAlt_R: - id2 = kKeyModifierIDAlt; - side = 1; - break; - - case kKeyMeta_L: - id2 = kKeyModifierIDMeta; - side = 0; - break; - - case kKeyMeta_R: - id2 = kKeyModifierIDMeta; - side = 1; - break; - - case kKeySuper_L: - id2 = kKeyModifierIDSuper; - side = 0; - break; - - case kKeySuper_R: - id2 = kKeyModifierIDSuper; - side = 1; - break; - } - - if (id2 != kKeyModifierIDNull) { - return s_translationTable[m_modifierTranslationTable[id2]][side]; - } - else { - return id; - } -} - -KeyModifierMask -CServerProxy::translateModifierMask(KeyModifierMask mask) const -{ - static const KeyModifierMask s_masks[kKeyModifierIDLast] = { - 0x0000, - KeyModifierShift, - KeyModifierControl, - KeyModifierAlt, - KeyModifierMeta, - KeyModifierSuper - }; - - KeyModifierMask newMask = mask & ~(KeyModifierShift | - KeyModifierControl | - KeyModifierAlt | - KeyModifierMeta | - KeyModifierSuper); - if ((mask & KeyModifierShift) != 0) { - newMask |= s_masks[m_modifierTranslationTable[kKeyModifierIDShift]]; - } - if ((mask & KeyModifierControl) != 0) { - newMask |= s_masks[m_modifierTranslationTable[kKeyModifierIDControl]]; - } - if ((mask & KeyModifierAlt) != 0) { - newMask |= s_masks[m_modifierTranslationTable[kKeyModifierIDAlt]]; - } - if ((mask & KeyModifierMeta) != 0) { - newMask |= s_masks[m_modifierTranslationTable[kKeyModifierIDMeta]]; - } - if ((mask & KeyModifierSuper) != 0) { - newMask |= s_masks[m_modifierTranslationTable[kKeyModifierIDSuper]]; - } - return newMask; -} - -void -CServerProxy::enter() -{ - // parse - SInt16 x, y; - UInt16 mask; - UInt32 seqNum; - CProtocolUtil::readf(m_stream, kMsgCEnter + 4, &x, &y, &seqNum, &mask); - LOG((CLOG_DEBUG1 "recv enter, %d,%d %d %04x", x, y, seqNum, mask)); - - // discard old compressed mouse motion, if any - m_compressMouse = false; - m_compressMouseRelative = false; - m_dxMouse = 0; - m_dyMouse = 0; - m_seqNum = seqNum; - - // forward - m_client->enter(x, y, seqNum, static_cast(mask), false); -} - -void -CServerProxy::leave() -{ - // parse - LOG((CLOG_DEBUG1 "recv leave")); - - // send last mouse motion - flushCompressedMouse(); - - // forward - m_client->leave(); -} - -void -CServerProxy::setClipboard() -{ - // parse - ClipboardID id; - UInt32 seqNum; - CString data; - CProtocolUtil::readf(m_stream, kMsgDClipboard + 4, &id, &seqNum, &data); - LOG((CLOG_DEBUG "recv clipboard %d size=%d", id, data.size())); - - // validate - if (id >= kClipboardEnd) { - return; - } - - // forward - CClipboard clipboard; - clipboard.unmarshall(data, 0); - m_client->setClipboard(id, &clipboard); -} - -void -CServerProxy::grabClipboard() -{ - // parse - ClipboardID id; - UInt32 seqNum; - CProtocolUtil::readf(m_stream, kMsgCClipboard + 4, &id, &seqNum); - LOG((CLOG_DEBUG "recv grab clipboard %d", id)); - - // validate - if (id >= kClipboardEnd) { - return; - } - - // forward - m_client->grabClipboard(id); -} - -void -CServerProxy::keyDown() -{ - // get mouse up to date - flushCompressedMouse(); - - // parse - UInt16 id, mask, button; - CProtocolUtil::readf(m_stream, kMsgDKeyDown + 4, &id, &mask, &button); - LOG((CLOG_DEBUG1 "recv key down id=0x%08x, mask=0x%04x, button=0x%04x", id, mask, button)); - - // translate - KeyID id2 = translateKey(static_cast(id)); - KeyModifierMask mask2 = translateModifierMask( - static_cast(mask)); - if (id2 != static_cast(id) || - mask2 != static_cast(mask)) - LOG((CLOG_DEBUG1 "key down translated to id=0x%08x, mask=0x%04x", id2, mask2)); - - // forward - m_client->keyDown(id2, mask2, button); -} - -void -CServerProxy::keyRepeat() -{ - // get mouse up to date - flushCompressedMouse(); - - // parse - UInt16 id, mask, count, button; - CProtocolUtil::readf(m_stream, kMsgDKeyRepeat + 4, - &id, &mask, &count, &button); - LOG((CLOG_DEBUG1 "recv key repeat id=0x%08x, mask=0x%04x, count=%d, button=0x%04x", id, mask, count, button)); - - // translate - KeyID id2 = translateKey(static_cast(id)); - KeyModifierMask mask2 = translateModifierMask( - static_cast(mask)); - if (id2 != static_cast(id) || - mask2 != static_cast(mask)) - LOG((CLOG_DEBUG1 "key repeat translated to id=0x%08x, mask=0x%04x", id2, mask2)); - - // forward - m_client->keyRepeat(id2, mask2, count, button); -} - -void -CServerProxy::keyUp() -{ - // get mouse up to date - flushCompressedMouse(); - - // parse - UInt16 id, mask, button; - CProtocolUtil::readf(m_stream, kMsgDKeyUp + 4, &id, &mask, &button); - LOG((CLOG_DEBUG1 "recv key up id=0x%08x, mask=0x%04x, button=0x%04x", id, mask, button)); - - // translate - KeyID id2 = translateKey(static_cast(id)); - KeyModifierMask mask2 = translateModifierMask( - static_cast(mask)); - if (id2 != static_cast(id) || - mask2 != static_cast(mask)) - LOG((CLOG_DEBUG1 "key up translated to id=0x%08x, mask=0x%04x", id2, mask2)); - - // forward - m_client->keyUp(id2, mask2, button); -} - -void -CServerProxy::mouseDown() -{ - // get mouse up to date - flushCompressedMouse(); - - // parse - SInt8 id; - CProtocolUtil::readf(m_stream, kMsgDMouseDown + 4, &id); - LOG((CLOG_DEBUG1 "recv mouse down id=%d", id)); - - // forward - m_client->mouseDown(static_cast(id)); -} - -void -CServerProxy::mouseUp() -{ - // get mouse up to date - flushCompressedMouse(); - - // parse - SInt8 id; - CProtocolUtil::readf(m_stream, kMsgDMouseUp + 4, &id); - LOG((CLOG_DEBUG1 "recv mouse up id=%d", id)); - - // forward - m_client->mouseUp(static_cast(id)); -} - -void -CServerProxy::mouseMove() -{ - // parse - bool ignore; - SInt16 x, y; - CProtocolUtil::readf(m_stream, kMsgDMouseMove + 4, &x, &y); - - // note if we should ignore the move - ignore = m_ignoreMouse; - - // compress mouse motion events if more input follows - if (!ignore && !m_compressMouse && m_stream->isReady()) { - m_compressMouse = true; - } - - // if compressing then ignore the motion but record it - if (m_compressMouse) { - m_compressMouseRelative = false; - ignore = true; - m_xMouse = x; - m_yMouse = y; - m_dxMouse = 0; - m_dyMouse = 0; - } - LOG((CLOG_DEBUG2 "recv mouse move %d,%d", x, y)); - - // forward - if (!ignore) { - m_client->mouseMove(x, y); - } -} - -void -CServerProxy::mouseRelativeMove() -{ - // parse - bool ignore; - SInt16 dx, dy; - CProtocolUtil::readf(m_stream, kMsgDMouseRelMove + 4, &dx, &dy); - - // note if we should ignore the move - ignore = m_ignoreMouse; - - // compress mouse motion events if more input follows - if (!ignore && !m_compressMouseRelative && m_stream->isReady()) { - m_compressMouseRelative = true; - } - - // if compressing then ignore the motion but record it - if (m_compressMouseRelative) { - ignore = true; - m_dxMouse += dx; - m_dyMouse += dy; - } - LOG((CLOG_DEBUG2 "recv mouse relative move %d,%d", dx, dy)); - - // forward - if (!ignore) { - m_client->mouseRelativeMove(dx, dy); - } -} - -void -CServerProxy::mouseWheel() -{ - // get mouse up to date - flushCompressedMouse(); - - // parse - SInt16 xDelta, yDelta; - CProtocolUtil::readf(m_stream, kMsgDMouseWheel + 4, &xDelta, &yDelta); - LOG((CLOG_DEBUG2 "recv mouse wheel %+d,%+d", xDelta, yDelta)); - - // forward - m_client->mouseWheel(xDelta, yDelta); -} - -void -CServerProxy::screensaver() -{ - // parse - SInt8 on; - CProtocolUtil::readf(m_stream, kMsgCScreenSaver + 4, &on); - LOG((CLOG_DEBUG1 "recv screen saver on=%d", on)); - - // forward - m_client->screensaver(on != 0); -} - -void -CServerProxy::resetOptions() -{ - // parse - LOG((CLOG_DEBUG1 "recv reset options")); - - // forward - m_client->resetOptions(); - - // reset keep alive - setKeepAliveRate(kKeepAliveRate); - - // reset modifier translation table - for (KeyModifierID id = 0; id < kKeyModifierIDLast; ++id) { - m_modifierTranslationTable[id] = id; - } -} - -void -CServerProxy::setOptions() -{ - // parse - COptionsList options; - CProtocolUtil::readf(m_stream, kMsgDSetOptions + 4, &options); - LOG((CLOG_DEBUG1 "recv set options size=%d", options.size())); - - // forward - m_client->setOptions(options); - - // update modifier table - for (UInt32 i = 0, n = options.size(); i < n; i += 2) { - KeyModifierID id = kKeyModifierIDNull; - if (options[i] == kOptionModifierMapForShift) { - id = kKeyModifierIDShift; - } - else if (options[i] == kOptionModifierMapForControl) { - id = kKeyModifierIDControl; - } - else if (options[i] == kOptionModifierMapForAlt) { - id = kKeyModifierIDAlt; - } - else if (options[i] == kOptionModifierMapForMeta) { - id = kKeyModifierIDMeta; - } - else if (options[i] == kOptionModifierMapForSuper) { - id = kKeyModifierIDSuper; - } - else if (options[i] == kOptionHeartbeat) { - // update keep alive - setKeepAliveRate(1.0e-3 * static_cast(options[i + 1])); - } - if (id != kKeyModifierIDNull) { - m_modifierTranslationTable[id] = - static_cast(options[i + 1]); - LOG((CLOG_DEBUG1 "modifier %d mapped to %d", id, m_modifierTranslationTable[id])); - } - } -} - -void -CServerProxy::queryInfo() -{ - CClientInfo info; - m_client->getShape(info.m_x, info.m_y, info.m_w, info.m_h); - m_client->getCursorPos(info.m_mx, info.m_my); - sendInfo(info); -} - -void -CServerProxy::infoAcknowledgment() -{ - LOG((CLOG_DEBUG1 "recv info acknowledgment")); - m_ignoreMouse = false; -} diff --git a/lib/client/CServerProxy.h b/lib/client/CServerProxy.h deleted file mode 100644 index f6642696..00000000 --- a/lib/client/CServerProxy.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CSERVERPROXY_H -#define CSERVERPROXY_H - -#include "ClipboardTypes.h" -#include "KeyTypes.h" -#include "CEvent.h" - -class CClient; -class CClientInfo; -class CEventQueueTimer; -class IClipboard; -class IStream; - -//! Proxy for server -/*! -This class acts a proxy for the server, converting calls into messages -to the server and messages from the server to calls on the client. -*/ -class CServerProxy { -public: - /*! - Process messages from the server on \p stream and forward to - \p client. - */ - CServerProxy(CClient* client, IStream* stream); - ~CServerProxy(); - - //! @name manipulators - //@{ - - void onInfoChanged(); - bool onGrabClipboard(ClipboardID); - void onClipboardChanged(ClipboardID, const IClipboard*); - - //@} - -protected: - enum EResult { kOkay, kUnknown, kDisconnect }; - EResult parseHandshakeMessage(const UInt8* code); - EResult parseMessage(const UInt8* code); - -private: - // if compressing mouse motion then send the last motion now - void flushCompressedMouse(); - - void sendInfo(const CClientInfo&); - - void resetKeepAliveAlarm(); - void setKeepAliveRate(double); - - // modifier key translation - KeyID translateKey(KeyID) const; - KeyModifierMask translateModifierMask(KeyModifierMask) const; - - // event handlers - void handleData(const CEvent&, void*); - void handleKeepAliveAlarm(const CEvent&, void*); - - // message handlers - void enter(); - void leave(); - void setClipboard(); - void grabClipboard(); - void keyDown(); - void keyRepeat(); - void keyUp(); - void mouseDown(); - void mouseUp(); - void mouseMove(); - void mouseRelativeMove(); - void mouseWheel(); - void screensaver(); - void resetOptions(); - void setOptions(); - void queryInfo(); - void infoAcknowledgment(); - -private: - typedef EResult (CServerProxy::*MessageParser)(const UInt8*); - - CClient* m_client; - IStream* m_stream; - - UInt32 m_seqNum; - - bool m_compressMouse; - bool m_compressMouseRelative; - SInt32 m_xMouse, m_yMouse; - SInt32 m_dxMouse, m_dyMouse; - - bool m_ignoreMouse; - - KeyModifierID m_modifierTranslationTable[kKeyModifierIDLast]; - - double m_keepAliveAlarm; - CEventQueueTimer* m_keepAliveAlarmTimer; - - MessageParser m_parser; -}; - -#endif diff --git a/lib/client/Makefile.am b/lib/client/Makefile.am deleted file mode 100644 index 4ea5a230..00000000 --- a/lib/client/Makefile.am +++ /dev/null @@ -1,40 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2002 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -## Process this file with automake to produce Makefile.in -NULL = - -EXTRA_DIST = \ - Makefile.win \ - $(NULL) - -MAINTAINERCLEANFILES = \ - Makefile.in \ - $(NULL) - -noinst_LIBRARIES = libclient.a -libclient_a_SOURCES = \ - CClient.cpp \ - CServerProxy.cpp \ - CClient.h \ - CServerProxy.h \ - $(NULL) -INCLUDES = \ - -I$(top_srcdir)/lib/common \ - -I$(top_srcdir)/lib/arch \ - -I$(top_srcdir)/lib/base \ - -I$(top_srcdir)/lib/mt \ - -I$(top_srcdir)/lib/io \ - -I$(top_srcdir)/lib/net \ - -I$(top_srcdir)/lib/synergy \ - -I$(top_srcdir)/lib/platform \ - $(NULL) diff --git a/lib/client/Makefile.win b/lib/client/Makefile.win deleted file mode 100644 index 3da2c73c..00000000 --- a/lib/client/Makefile.win +++ /dev/null @@ -1,63 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2007 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -LIB_CLIENT_SRC = lib\client -LIB_CLIENT_DST = $(BUILD_DST)\$(LIB_CLIENT_SRC) -LIB_CLIENT_LIB = "$(LIB_CLIENT_DST)\client.lib" -LIB_CLIENT_CPP = \ - "CClient.cpp" \ - "CServerProxy.cpp" \ - $(NULL) -LIB_CLIENT_OBJ = \ - "$(LIB_CLIENT_DST)\CClient.obj" \ - "$(LIB_CLIENT_DST)\CServerProxy.obj" \ - $(NULL) -LIB_CLIENT_INC = \ - /I"lib\common" \ - /I"lib\arch" \ - /I"lib\base" \ - /I"lib\mt" \ - /I"lib\io" \ - /I"lib\net" \ - /I"lib\synergy" \ - /I"lib\platform" \ - $(NULL) - -CPP_FILES = $(CPP_FILES) $(LIB_CLIENT_CPP) -OBJ_FILES = $(OBJ_FILES) $(LIB_CLIENT_OBJ) -LIB_FILES = $(LIB_FILES) $(LIB_CLIENT_LIB) - -# Dependency rules -$(LIB_CLIENT_OBJ): $(AUTODEP) -!if EXIST($(LIB_CLIENT_DST)\deps.mak) -!include $(LIB_CLIENT_DST)\deps.mak -!endif - -# Build rules. Use batch-mode rules if possible. -!if DEFINED(_NMAKE_VER) -{$(LIB_CLIENT_SRC)\}.cpp{$(LIB_CLIENT_DST)\}.obj:: -!else -{$(LIB_CLIENT_SRC)\}.cpp{$(LIB_CLIENT_DST)\}.obj: -!endif - @$(ECHO) Compile in $(LIB_CLIENT_SRC) - -@$(MKDIR) $(LIB_CLIENT_DST) 2>NUL: - $(cpp) $(cppdebug) $(cppflags) $(cppvarsmt) /showIncludes \ - $(LIB_CLIENT_INC) \ - /Fo$(LIB_CLIENT_DST)\ \ - /Fd$(LIB_CLIENT_LIB:.lib=.pdb) \ - $< | $(AUTODEP) $(LIB_CLIENT_SRC) $(LIB_CLIENT_DST) -$(LIB_CLIENT_LIB): $(LIB_CLIENT_OBJ) - @$(ECHO) Link $(@F) - $(implib) $(ildebug) $(ilflags) \ - /out:$@ \ - $** - $(AUTODEP) $(LIB_CLIENT_SRC) $(LIB_CLIENT_DST) $(**:.obj=.d) diff --git a/lib/common/BasicTypes.h b/lib/common/BasicTypes.h deleted file mode 100644 index b9d8293e..00000000 --- a/lib/common/BasicTypes.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef BASICTYPES_H -#define BASICTYPES_H - -#include "common.h" - -// -// pick types of particular sizes -// - -#if !defined(TYPE_OF_SIZE_1) -# if SIZEOF_CHAR == 1 -# define TYPE_OF_SIZE_1 char -# endif -#endif - -#if !defined(TYPE_OF_SIZE_2) -# if SIZEOF_INT == 2 -# define TYPE_OF_SIZE_2 int -# else -# define TYPE_OF_SIZE_2 short -# endif -#endif - -#if !defined(TYPE_OF_SIZE_4) - // Carbon defines SInt32 and UInt32 in terms of long -# if SIZEOF_INT == 4 && !defined(__APPLE__) -# define TYPE_OF_SIZE_4 int -# else -# define TYPE_OF_SIZE_4 long -# endif -#endif - -// -// verify existence of required types -// - -#if !defined(TYPE_OF_SIZE_1) -# error No 1 byte integer type -#endif -#if !defined(TYPE_OF_SIZE_2) -# error No 2 byte integer type -#endif -#if !defined(TYPE_OF_SIZE_4) -# error No 4 byte integer type -#endif - - -// -// make typedefs -// -// except for SInt8 and UInt8 these types are only guaranteed to be -// at least as big as indicated (in bits). that is, they may be -// larger than indicated. -// - -typedef signed TYPE_OF_SIZE_1 SInt8; -typedef signed TYPE_OF_SIZE_2 SInt16; -typedef signed TYPE_OF_SIZE_4 SInt32; - -typedef unsigned TYPE_OF_SIZE_1 UInt8; -typedef unsigned TYPE_OF_SIZE_2 UInt16; -typedef unsigned TYPE_OF_SIZE_4 UInt32; - -// -// clean up -// - -#undef TYPE_OF_SIZE_1 -#undef TYPE_OF_SIZE_2 -#undef TYPE_OF_SIZE_4 - -#endif diff --git a/lib/common/IInterface.h b/lib/common/IInterface.h deleted file mode 100644 index 97df31c2..00000000 --- a/lib/common/IInterface.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef IINTERFACE_H -#define IINTERFACE_H - -#include "common.h" - -//! Base class of interfaces -/*! -This is the base class of all interface classes. An interface class has -only pure virtual methods. -*/ -class IInterface { -public: - //! Interface destructor does nothing - virtual ~IInterface() { } -}; - -#endif diff --git a/lib/common/MacOSXPrecomp.h b/lib/common/MacOSXPrecomp.h deleted file mode 100644 index 64e7c90a..00000000 --- a/lib/common/MacOSXPrecomp.h +++ /dev/null @@ -1,8 +0,0 @@ -// -// Prefix header for all source files of the 'deleteme' target in the 'deleteme' project. -// - -#define MAC_OS_X_VERSION_MAX_ALLOWED MAC_OS_X_VERSION_10_2 - - -#include diff --git a/lib/common/Makefile.am b/lib/common/Makefile.am deleted file mode 100644 index 74804748..00000000 --- a/lib/common/Makefile.am +++ /dev/null @@ -1,48 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2002 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -## Process this file with automake to produce Makefile.in -NULL = - -EXTRA_DIST = \ - Makefile.win \ - BasicTypes.h \ - IInterface.h \ - MacOSXPrecomp.h \ - common.h \ - stdbitset.h \ - stddeque.h \ - stdfstream.h \ - stdistream.h \ - stdlist.h \ - stdmap.h \ - stdostream.h \ - stdpost.h \ - stdpre.h \ - stdset.h \ - stdsstream.h \ - stdstring.h \ - stdvector.h \ - $(NULL) - -MAINTAINERCLEANFILES = \ - Makefile.in \ - $(NULL) - -noinst_LIBRARIES = libcommon.a -libcommon_a_SOURCES = \ - Version.cpp \ - Version.h \ - $(NULL) - -INCLUDES = \ - $(NULL) diff --git a/lib/common/Makefile.win b/lib/common/Makefile.win deleted file mode 100644 index 9b63a046..00000000 --- a/lib/common/Makefile.win +++ /dev/null @@ -1,53 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2007 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -LIB_COMMON_SRC = lib\common -LIB_COMMON_DST = $(BUILD_DST)\$(LIB_COMMON_SRC) -LIB_COMMON_LIB = "$(LIB_COMMON_DST)\common.lib" -LIB_COMMON_CPP = \ - Version.cpp \ - $(NULL) -LIB_COMMON_OBJ = \ - "$(LIB_COMMON_DST)\Version.obj" \ - $(NULL) -LIB_COMMON_INC = \ - $(NULL) - -CPP_FILES = $(CPP_FILES) $(LIB_COMMON_CPP) -OBJ_FILES = $(OBJ_FILES) $(LIB_COMMON_OBJ) -LIB_FILES = $(LIB_FILES) $(LIB_COMMON_LIB) - -# Dependency rules -$(LIB_COMMON_OBJ): $(AUTODEP) -!if EXIST($(LIB_COMMON_DST)\deps.mak) -!include $(LIB_COMMON_DST)\deps.mak -!endif - -# Build rules. Use batch-mode rules if possible. -!if DEFINED(_NMAKE_VER) -{$(LIB_COMMON_SRC)\}.cpp{$(LIB_COMMON_DST)\}.obj:: -!else -{$(LIB_COMMON_SRC)\}.cpp{$(LIB_COMMON_DST)\}.obj: -!endif - @$(ECHO) Compile in $(LIB_COMMON_SRC) - -@$(MKDIR) $(LIB_COMMON_DST) 2>NUL: - $(cpp) $(cppdebug) $(cppflags) $(cppvarsmt) /showIncludes \ - $(LIB_COMMON_INC) \ - /Fo$(LIB_COMMON_DST)\ \ - /Fd$(LIB_COMMON_LIB:.lib=.pdb) \ - $< | $(AUTODEP) $(LIB_COMMON_SRC) $(LIB_COMMON_DST) -$(LIB_COMMON_LIB): $(LIB_COMMON_OBJ) - @$(ECHO) Link $(@F) - $(implib) $(ildebug) $(ilflags) \ - /out:$@ \ - $** - $(AUTODEP) $(LIB_COMMON_SRC) $(LIB_COMMON_DST) $(**:.obj=.d) diff --git a/lib/common/Version.cpp b/lib/common/Version.cpp deleted file mode 100644 index 86fcdef7..00000000 --- a/lib/common/Version.cpp +++ /dev/null @@ -1,22 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "Version.h" - -const char* kApplication = "Synergy"; -const char* kCopyright = "Copyright (C) 2002 Chris Schoeneman"; -const char* kContact = "Chris Schoeneman, crs23@bigfoot.com"; -const char* kWebsite = "http://synergy2.sourceforge.net/"; -const char* kVersion = VERSION; -const char* kAppVersion = "Synergy " VERSION; diff --git a/lib/common/Version.h b/lib/common/Version.h deleted file mode 100644 index 43783c8c..00000000 --- a/lib/common/Version.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef VERSION_H -#define VERSION_H - -#include "common.h" - -// set version macro if not set yet -#if !defined(VERSION) -# define VERSION "1.3.2" -#endif - -// important strings -extern const char* kApplication; -extern const char* kCopyright; -extern const char* kContact; -extern const char* kWebsite; - -// build version. follows linux kernel style: an even minor number implies -// a release version, odd implies development version. -extern const char* kVersion; - -// application version -extern const char* kAppVersion; - -// exit codes -static const int kExitSuccess = 0; // successful completion -static const int kExitFailed = 1; // general failure -static const int kExitTerminated = 2; // killed by signal -static const int kExitArgs = 3; // bad arguments -static const int kExitConfig = 4; // cannot read configuration - -#endif diff --git a/lib/common/common.h b/lib/common/common.h deleted file mode 100644 index e539a7d6..00000000 --- a/lib/common/common.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef COMMON_H -#define COMMON_H - -// this file should be included, directly or indirectly by every other. - -#if HAVE_CONFIG_H -# include "config.h" - - // don't use poll() on mac -# if defined(__APPLE__) -# undef HAVE_POLL -# endif -#else - // we may not have run configure on win32 -# if defined(_WIN32) -# define SYSAPI_WIN32 1 -# define WINAPI_MSWINDOWS 1 -# endif - - // we may not have run configure on OS X -# if defined(__APPLE__) -# define SYSAPI_UNIX 1 -# define WINAPI_CARBON 1 - -# define HAVE_CXX_BOOL 1 -# define HAVE_CXX_CASTS 1 -# define HAVE_CXX_EXCEPTIONS 1 -# define HAVE_CXX_MUTABLE 1 -# define HAVE_CXX_STDLIB 1 -# define HAVE_GETPWUID_R 1 -# define HAVE_GMTIME_R 1 -# define HAVE_INET_ATON 1 -# define HAVE_INTTYPES_H 1 -# define HAVE_ISTREAM 1 -# define HAVE_MEMORY_H 1 -# define HAVE_NANOSLEEP 1 -# define HAVE_OSTREAM 1 -# define HAVE_POSIX_SIGWAIT 1 -# define HAVE_PTHREAD 1 -# define HAVE_PTHREAD_SIGNAL 1 -# include -# include -# if defined(_SOCKLEN_T) -# define HAVE_SOCKLEN_T 1 -# endif -# define HAVE_SSTREAM 1 -# define HAVE_STDINT_H 1 -# define HAVE_STDLIB_H 1 -# define HAVE_STRINGS_H 1 -# define HAVE_STRING_H 1 -# define HAVE_SYS_SELECT_H 1 -# define HAVE_SYS_SOCKET_H 1 -# define HAVE_SYS_STAT_H 1 -# define HAVE_SYS_TIME_H 1 -# define HAVE_SYS_TYPES_H 1 -# define HAVE_SYS_UTSNAME_H 1 -# define HAVE_UNISTD_H 1 -# define HAVE_VSNPRINTF 1 -/* disable this so we can build with the 10.2.8 SDK */ -/*# define HAVE_WCHAR_H 1*/ - -# define SELECT_TYPE_ARG1 int -# define SELECT_TYPE_ARG234 (fd_set *) -# define SELECT_TYPE_ARG5 (struct timeval *) -# define SIZEOF_CHAR 1 -# define SIZEOF_INT 4 -# define SIZEOF_LONG 4 -# define SIZEOF_SHORT 2 -# define STDC_HEADERS 1 -# define TIME_WITH_SYS_TIME 1 -# define X_DISPLAY_MISSING 1 -# endif -#endif - -// VC++ specific -#if (_MSC_VER >= 1200) - // work around for statement scoping bug -# define for if (false) { } else for - - // turn off bonehead warnings -# pragma warning(disable: 4786) // identifier truncated in debug info -# pragma warning(disable: 4514) // unreferenced inline function removed - - // this one's a little too aggressive -# pragma warning(disable: 4127) // conditional expression is constant - - // emitted incorrectly under release build in some circumstances -# if defined(NDEBUG) -# pragma warning(disable: 4702) // unreachable code -# pragma warning(disable: 4701) // variable maybe used uninitialized -# endif -#endif // (_MSC_VER >= 1200) - -// VC++ has built-in sized types -#if defined(_MSC_VER) -# include -# define TYPE_OF_SIZE_1 __int8 -# define TYPE_OF_SIZE_2 __int16 -# define TYPE_OF_SIZE_4 __int32 -#else -# define SIZE_OF_CHAR 1 -# define SIZE_OF_SHORT 2 -# define SIZE_OF_INT 4 -# define SIZE_OF_LONG 4 -#endif - -// FIXME -- including fp.h from Carbon.h causes a undefined symbol error -// on my build system. the symbol is scalb. since we don't need any -// math functions we define __FP__, the include guard macro for fp.h, to -// prevent fp.h from being included. -#if defined(__APPLE__) -#define __FP__ -#endif - -// define NULL -#include - -// make assert available since we use it a lot -#include - -#endif diff --git a/lib/common/stdbitset.h b/lib/common/stdbitset.h deleted file mode 100644 index 529772ca..00000000 --- a/lib/common/stdbitset.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "stdpre.h" -#include -#include "stdpost.h" diff --git a/lib/common/stddeque.h b/lib/common/stddeque.h deleted file mode 100644 index 06bdafd1..00000000 --- a/lib/common/stddeque.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "stdpre.h" -#include -#include "stdpost.h" diff --git a/lib/common/stdfstream.h b/lib/common/stdfstream.h deleted file mode 100644 index 9d1f5aa6..00000000 --- a/lib/common/stdfstream.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "stdpre.h" -#include -#include "stdpost.h" -#include "stdistream.h" diff --git a/lib/common/stdistream.h b/lib/common/stdistream.h deleted file mode 100644 index 33667398..00000000 --- a/lib/common/stdistream.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "stdpre.h" -#if HAVE_ISTREAM -#include -#else -#include -#endif -#include "stdpost.h" - -#if defined(_MSC_VER) && _MSC_VER <= 1200 -// VC++6 istream has no overloads for __int* types, .NET does -inline -std::istream& operator>>(std::istream& s, SInt8& i) -{ return s >> (signed char&)i; } -inline -std::istream& operator>>(std::istream& s, SInt16& i) -{ return s >> (short&)i; } -inline -std::istream& operator>>(std::istream& s, SInt32& i) -{ return s >> (int&)i; } -inline -std::istream& operator>>(std::istream& s, UInt8& i) -{ return s >> (unsigned char&)i; } -inline -std::istream& operator>>(std::istream& s, UInt16& i) -{ return s >> (unsigned short&)i; } -inline -std::istream& operator>>(std::istream& s, UInt32& i) -{ return s >> (unsigned int&)i; } -#endif diff --git a/lib/common/stdlist.h b/lib/common/stdlist.h deleted file mode 100644 index 6f0df8e8..00000000 --- a/lib/common/stdlist.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "stdpre.h" -#include -#include "stdpost.h" diff --git a/lib/common/stdmap.h b/lib/common/stdmap.h deleted file mode 100644 index da501615..00000000 --- a/lib/common/stdmap.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "stdpre.h" -#include -#include "stdpost.h" diff --git a/lib/common/stdostream.h b/lib/common/stdostream.h deleted file mode 100644 index 48e89862..00000000 --- a/lib/common/stdostream.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "stdpre.h" -#if HAVE_OSTREAM -#include -#else -#include -#endif -#include "stdpost.h" diff --git a/lib/common/stdpost.h b/lib/common/stdpost.h deleted file mode 100644 index 0f06b74a..00000000 --- a/lib/common/stdpost.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#if defined(_MSC_VER) -#pragma warning(pop) -#endif diff --git a/lib/common/stdpre.h b/lib/common/stdpre.h deleted file mode 100644 index 10fa7d5d..00000000 --- a/lib/common/stdpre.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#if defined(_MSC_VER) -#pragma warning(disable: 4786) // identifier truncated -#pragma warning(disable: 4514) // unreferenced inline -#pragma warning(disable: 4710) // not inlined -#pragma warning(disable: 4663) // C++ change, template specialization -#pragma warning(disable: 4503) // decorated name length too long -#pragma warning(push, 3) -#pragma warning(disable: 4018) // signed/unsigned mismatch -#pragma warning(disable: 4284) -#pragma warning(disable: 4146) // unary minus on unsigned value -#pragma warning(disable: 4127) // conditional expression is constant -#pragma warning(disable: 4701) // variable possibly used uninitialized -#endif diff --git a/lib/common/stdset.h b/lib/common/stdset.h deleted file mode 100644 index aeb491b6..00000000 --- a/lib/common/stdset.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "stdpre.h" -#include -#include "stdpost.h" diff --git a/lib/common/stdsstream.h b/lib/common/stdsstream.h deleted file mode 100644 index 45b28124..00000000 --- a/lib/common/stdsstream.h +++ /dev/null @@ -1,371 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "stdpre.h" - -#if HAVE_SSTREAM || !defined(__GNUC__) || (__GNUC__ >= 3) - -#include - -#elif defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 95) -// g++ 2.95 didn't ship with sstream. the following is a backport -// by Magnus Fromreide of the sstream in g++ 3.0. - -/* This is part of libio/iostream, providing -*- C++ -*- input/output. -Copyright (C) 2000 Free Software Foundation - -This file is part of the GNU IO Library. This library 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, or (at your option) -any later version. - -This library 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 this library; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -As a special exception, if you link this library with files -compiled with a GNU compiler to produce an executable, this does not cause -the resulting executable to be covered by the GNU General Public License. -This exception does not however invalidate any other reasons why -the executable file might be covered by the GNU General Public License. */ - -/* Written by Magnus Fromreide (magfr@lysator.liu.se). */ -/* seekoff and ideas for overflow is largely borrowed from libstdc++-v3 */ - -#include -#include -#include - -namespace std -{ - class stringbuf : public streambuf - { - public: - typedef char char_type; - typedef int int_type; - typedef streampos pos_type; - typedef streamoff off_type; - - explicit - stringbuf(int which=ios::in|ios::out) - : streambuf(), mode(static_cast(which)), - stream(NULL), stream_len(0) - { - stringbuf_init(); - } - - explicit - stringbuf(const string &str, int which=ios::in|ios::out) - : streambuf(), mode(static_cast(which)), - stream(NULL), stream_len(0) - { - if (mode & (ios::in|ios::out)) - { - stream_len = str.size(); - stream = new char_type[stream_len]; - str.copy(stream, stream_len); - } - stringbuf_init(); - } - - virtual - ~stringbuf() - { - delete[] stream; - } - - string - str() const - { - if (pbase() != 0) - return string(stream, pptr()-pbase()); - else - return string(); - } - - void - str(const string& str) - { - delete[] stream; - stream_len = str.size(); - stream = new char_type[stream_len]; - str.copy(stream, stream_len); - stringbuf_init(); - } - - protected: - // The buffer is already in gptr, so if it ends then it is out of data. - virtual int - underflow() - { - return EOF; - } - - virtual int - overflow(int c = EOF) - { - int res; - if (mode & ios::out) - { - if (c != EOF) - { - streamsize old_stream_len = stream_len; - stream_len += 1; - char_type* new_stream = new char_type[stream_len]; - memcpy(new_stream, stream, old_stream_len); - delete[] stream; - stream = new_stream; - stringbuf_sync(gptr()-eback(), pptr()-pbase()); - sputc(c); - res = c; - } - else - res = EOF; - } - else - res = 0; - return res; - } - - virtual streambuf* - setbuf(char_type* s, streamsize n) - { - if (n != 0) - { - delete[] stream; - stream = new char_type[n]; - memcpy(stream, s, n); - stream_len = n; - stringbuf_sync(0, 0); - } - return this; - } - - virtual pos_type - seekoff(off_type off, ios::seek_dir way, int which = ios::in | ios::out) - { - pos_type ret = pos_type(off_type(-1)); - bool testin = which & ios::in && mode & ios::in; - bool testout = which & ios::out && mode & ios::out; - bool testboth = testin && testout && way != ios::cur; - - if (stream_len && ((testin != testout) || testboth)) - { - char_type* beg = stream; - char_type* curi = NULL; - char_type* curo = NULL; - char_type* endi = NULL; - char_type* endo = NULL; - - if (testin) - { - curi = gptr(); - endi = egptr(); - } - if (testout) - { - curo = pptr(); - endo = epptr(); - } - - off_type newoffi = 0; - off_type newoffo = 0; - if (way == ios::beg) - { - newoffi = beg - curi; - newoffo = beg - curo; - } - else if (way == ios::end) - { - newoffi = endi - curi; - newoffo = endo - curo; - } - - if (testin && newoffi + off + curi - beg >= 0 && - endi - beg >= newoffi + off + curi - beg) - { - gbump(newoffi + off); - ret = pos_type(newoffi + off + curi); - } - if (testout && newoffo + off + curo - beg >= 0 && - endo - beg >= newoffo + off + curo - beg) - { - pbump(newoffo + off); - ret = pos_type(newoffo + off + curo); - } - } - return ret; - } - - virtual pos_type - seekpos(pos_type sp, int which = ios::in | ios::out) - { - pos_type ret = seekoff(sp, ios::beg, which); - return ret; - } - - private: - void - stringbuf_sync(streamsize i, streamsize o) - { - if (mode & ios::in) - setg(stream, stream + i, stream + stream_len); - if (mode & ios::out) - { - setp(stream, stream + stream_len); - pbump(o); - } - } - void - stringbuf_init() - { - if (mode & ios::ate) - stringbuf_sync(0, stream_len); - else - stringbuf_sync(0, 0); - } - - private: - ios::open_mode mode; - char_type* stream; - streamsize stream_len; - }; - - class istringstream : public istream { - public: - typedef char char_type; - typedef int int_type; - typedef streampos pos_type; - typedef streamoff off_type; - - explicit - istringstream(int which=ios::in) - : istream(&sb), sb(which | ios::in) - { } - - explicit - istringstream(const string& str, int which=ios::in) - : istream(&sb), sb(str, which | ios::in) - { } - - stringbuf* - rdbuf() const - { - return const_cast(&sb); - } - - string - str() const - { - return rdbuf()->str(); - } - void - str(const string& s) - { - rdbuf()->str(s); - } - private: - stringbuf sb; - }; - - class ostringstream : public ostream { - public: - typedef char char_type; - typedef int int_type; - typedef streampos pos_type; - typedef streamoff off_type; - - explicit - ostringstream(int which=ios::out) - : ostream(&sb), sb(which | ios::out) - { } - - explicit - ostringstream(const string& str, int which=ios::out) - : ostream(&sb), sb(str, which | ios::out) - { } - - stringbuf* - rdbuf() const - { - return const_cast(&sb); - } - - string - str() const - { - return rdbuf()->str(); - } - - void str(const string& s) - { - rdbuf()->str(s); - } - private: - stringbuf sb; - }; - - class stringstream : public iostream { - public: - typedef char char_type; - typedef int int_type; - typedef streampos pos_type; - typedef streamoff off_type; - - explicit - stringstream(int which=ios::out|ios::in) - : iostream(&sb), sb(which) - { } - - explicit - stringstream(const string& str, int which=ios::out|ios::in) - : iostream(&sb), sb(str, which) - { } - - stringbuf* - rdbuf() const - { - return const_cast(&sb); - } - - string - str() const - { - return rdbuf()->str(); - } - - void - str(const string& s) - { - rdbuf()->str(s); - } - private: - stringbuf sb; - }; -}; - -#else /* not g++ 2.95 and no */ - -#error "Standard C++ library is missing required sstream header." - -#endif /* not g++ 2.95 and no */ - -#include "stdpost.h" -#include "stdistream.h" diff --git a/lib/common/stdstring.h b/lib/common/stdstring.h deleted file mode 100644 index 3d83c03c..00000000 --- a/lib/common/stdstring.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "stdpre.h" -#include -#include "stdpost.h" diff --git a/lib/common/stdvector.h b/lib/common/stdvector.h deleted file mode 100644 index 1056bb46..00000000 --- a/lib/common/stdvector.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "stdpre.h" -#include -#include "stdpost.h" diff --git a/lib/io/CStreamBuffer.cpp b/lib/io/CStreamBuffer.cpp deleted file mode 100644 index d11494b4..00000000 --- a/lib/io/CStreamBuffer.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CStreamBuffer.h" - -// -// CStreamBuffer -// - -const UInt32 CStreamBuffer::kChunkSize = 4096; - -CStreamBuffer::CStreamBuffer() : - m_size(0), - m_headUsed(0) -{ - // do nothing -} - -CStreamBuffer::~CStreamBuffer() -{ - // do nothing -} - -const void* -CStreamBuffer::peek(UInt32 n) -{ - assert(n <= m_size); - - // if requesting no data then return NULL so we don't try to access - // an empty list. - if (n == 0) { - return NULL; - } - - // reserve space in first chunk - ChunkList::iterator head = m_chunks.begin(); - head->reserve(n + m_headUsed); - - // consolidate chunks into the first chunk until it has n bytes - ChunkList::iterator scan = head; - ++scan; - while (head->size() - m_headUsed < n && scan != m_chunks.end()) { - head->insert(head->end(), scan->begin(), scan->end()); - scan = m_chunks.erase(scan); - } - - return reinterpret_cast(&(head->begin()[m_headUsed])); -} - -void -CStreamBuffer::pop(UInt32 n) -{ - // discard all chunks if n is greater than or equal to m_size - if (n >= m_size) { - m_size = 0; - m_headUsed = 0; - m_chunks.clear(); - return; - } - - // update size - m_size -= n; - - // discard chunks until more than n bytes would've been discarded - ChunkList::iterator scan = m_chunks.begin(); - assert(scan != m_chunks.end()); - while (scan->size() - m_headUsed <= n) { - n -= scan->size() - m_headUsed; - m_headUsed = 0; - scan = m_chunks.erase(scan); - assert(scan != m_chunks.end()); - } - - // remove left over bytes from the head chunk - if (n > 0) { - m_headUsed += n; - } -} - -void -CStreamBuffer::write(const void* vdata, UInt32 n) -{ - assert(vdata != NULL); - - // ignore if no data, otherwise update size - if (n == 0) { - return; - } - m_size += n; - - // cast data to bytes - const UInt8* data = reinterpret_cast(vdata); - - // point to last chunk if it has space, otherwise append an empty chunk - ChunkList::iterator scan = m_chunks.end(); - if (scan != m_chunks.begin()) { - --scan; - if (scan->size() >= kChunkSize) { - ++scan; - } - } - if (scan == m_chunks.end()) { - scan = m_chunks.insert(scan, Chunk()); - } - - // append data in chunks - while (n > 0) { - // choose number of bytes for next chunk - assert(scan->size() <= kChunkSize); - UInt32 count = kChunkSize - scan->size(); - if (count > n) - count = n; - - // transfer data - scan->insert(scan->end(), data, data + count); - n -= count; - data += count; - - // append another empty chunk if we're not done yet - if (n > 0) { - ++scan; - scan = m_chunks.insert(scan, Chunk()); - } - } -} - -UInt32 -CStreamBuffer::getSize() const -{ - return m_size; -} diff --git a/lib/io/CStreamBuffer.h b/lib/io/CStreamBuffer.h deleted file mode 100644 index fafcc72b..00000000 --- a/lib/io/CStreamBuffer.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CSTREAMBUFFER_H -#define CSTREAMBUFFER_H - -#include "BasicTypes.h" -#include "stdlist.h" -#include "stdvector.h" - -//! FIFO of bytes -/*! -This class maintains a FIFO (first-in, last-out) buffer of bytes. -*/ -class CStreamBuffer { -public: - CStreamBuffer(); - ~CStreamBuffer(); - - //! @name manipulators - //@{ - - //! Read data without removing from buffer - /*! - Return a pointer to memory with the next \c n bytes in the buffer - (which must be <= getSize()). The caller must not modify the returned - memory nor delete it. - */ - const void* peek(UInt32 n); - - //! Discard data - /*! - Discards the next \c n bytes. If \c n >= getSize() then the buffer - is cleared. - */ - void pop(UInt32 n); - - //! Write data to buffer - /*! - Appends \c n bytes from \c data to the buffer. - */ - void write(const void* data, UInt32 n); - - //@} - //! @name accessors - //@{ - - //! Get size of buffer - /*! - Returns the number of bytes in the buffer. - */ - UInt32 getSize() const; - - //@} - -private: - static const UInt32 kChunkSize; - - typedef std::vector Chunk; - typedef std::list ChunkList; - - ChunkList m_chunks; - UInt32 m_size; - UInt32 m_headUsed; -}; - -#endif diff --git a/lib/io/CStreamFilter.cpp b/lib/io/CStreamFilter.cpp deleted file mode 100644 index 312b0dfd..00000000 --- a/lib/io/CStreamFilter.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CStreamFilter.h" -#include "IEventQueue.h" -#include "TMethodEventJob.h" - -// -// CStreamFilter -// - -CStreamFilter::CStreamFilter(IStream* stream, bool adoptStream) : - m_stream(stream), - m_adopted(adoptStream) -{ - // replace handlers for m_stream - EVENTQUEUE->removeHandlers(m_stream->getEventTarget()); - EVENTQUEUE->adoptHandler(CEvent::kUnknown, m_stream->getEventTarget(), - new TMethodEventJob(this, - &CStreamFilter::handleUpstreamEvent)); -} - -CStreamFilter::~CStreamFilter() -{ - EVENTQUEUE->removeHandler(CEvent::kUnknown, m_stream->getEventTarget()); - if (m_adopted) { - delete m_stream; - } -} - -void -CStreamFilter::close() -{ - getStream()->close(); -} - -UInt32 -CStreamFilter::read(void* buffer, UInt32 n) -{ - return getStream()->read(buffer, n); -} - -void -CStreamFilter::write(const void* buffer, UInt32 n) -{ - getStream()->write(buffer, n); -} - -void -CStreamFilter::flush() -{ - getStream()->flush(); -} - -void -CStreamFilter::shutdownInput() -{ - getStream()->shutdownInput(); -} - -void -CStreamFilter::shutdownOutput() -{ - getStream()->shutdownOutput(); -} - -void* -CStreamFilter::getEventTarget() const -{ - return const_cast(reinterpret_cast(this)); -} - -bool -CStreamFilter::isReady() const -{ - return getStream()->isReady(); -} - -UInt32 -CStreamFilter::getSize() const -{ - return getStream()->getSize(); -} - -IStream* -CStreamFilter::getStream() const -{ - return m_stream; -} - -void -CStreamFilter::filterEvent(const CEvent& event) -{ - EVENTQUEUE->dispatchEvent(CEvent(event.getType(), - getEventTarget(), event.getData())); -} - -void -CStreamFilter::handleUpstreamEvent(const CEvent& event, void*) -{ - filterEvent(event); -} diff --git a/lib/io/CStreamFilter.h b/lib/io/CStreamFilter.h deleted file mode 100644 index 4dc87094..00000000 --- a/lib/io/CStreamFilter.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CSTREAMFILTER_H -#define CSTREAMFILTER_H - -#include "IStream.h" - -//! A stream filter -/*! -This class wraps a stream. Subclasses provide indirect access -to the wrapped stream, typically performing some filtering. -*/ -class CStreamFilter : public IStream { -public: - /*! - Create a wrapper around \c stream. Iff \c adoptStream is true then - this object takes ownership of the stream and will delete it in the - d'tor. - */ - CStreamFilter(IStream* stream, bool adoptStream = true); - ~CStreamFilter(); - - // IStream overrides - // These all just forward to the underlying stream except getEventTarget. - // Override as necessary. getEventTarget returns a pointer to this. - virtual void close(); - virtual UInt32 read(void* buffer, UInt32 n); - virtual void write(const void* buffer, UInt32 n); - virtual void flush(); - virtual void shutdownInput(); - virtual void shutdownOutput(); - virtual void* getEventTarget() const; - virtual bool isReady() const; - virtual UInt32 getSize() const; - -protected: - //! Get the stream - /*! - Returns the stream passed to the c'tor. - */ - IStream* getStream() const; - - //! Handle events from source stream - /*! - Does the event filtering. The default simply dispatches an event - identical except using this object as the event target. - */ - virtual void filterEvent(const CEvent&); - -private: - void handleUpstreamEvent(const CEvent&, void*); - -private: - IStream* m_stream; - bool m_adopted; -}; - -#endif diff --git a/lib/io/IStream.cpp b/lib/io/IStream.cpp deleted file mode 100644 index aec65b61..00000000 --- a/lib/io/IStream.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "IStream.h" - -// -// IStream -// - -CEvent::Type IStream::s_inputReadyEvent = CEvent::kUnknown; -CEvent::Type IStream::s_outputFlushedEvent = CEvent::kUnknown; -CEvent::Type IStream::s_outputErrorEvent = CEvent::kUnknown; -CEvent::Type IStream::s_inputShutdownEvent = CEvent::kUnknown; -CEvent::Type IStream::s_outputShutdownEvent = CEvent::kUnknown; - -CEvent::Type -IStream::getInputReadyEvent() -{ - return CEvent::registerTypeOnce(s_inputReadyEvent, - "IStream::inputReady"); -} - -CEvent::Type -IStream::getOutputFlushedEvent() -{ - return CEvent::registerTypeOnce(s_outputFlushedEvent, - "IStream::outputFlushed"); -} - -CEvent::Type -IStream::getOutputErrorEvent() -{ - return CEvent::registerTypeOnce(s_outputErrorEvent, - "IStream::outputError"); -} - -CEvent::Type -IStream::getInputShutdownEvent() -{ - return CEvent::registerTypeOnce(s_inputShutdownEvent, - "IStream::inputShutdown"); -} - -CEvent::Type -IStream::getOutputShutdownEvent() -{ - return CEvent::registerTypeOnce(s_outputShutdownEvent, - "IStream::outputShutdown"); -} diff --git a/lib/io/IStream.h b/lib/io/IStream.h deleted file mode 100644 index cb5b54c9..00000000 --- a/lib/io/IStream.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef ISTREAM_H -#define ISTREAM_H - -#include "IInterface.h" -#include "CEvent.h" - -//! Bidirectional stream interface -/*! -Defines the interface for all streams. -*/ -class IStream : public IInterface { -public: - //! @name manipulators - //@{ - - //! Close the stream - /*! - Closes the stream. Pending input data and buffered output data - are discarded. Use \c flush() before \c close() to send buffered - output data. Attempts to \c read() after a close return 0, - attempts to \c write() generate output error events, and attempts - to \c flush() return immediately. - */ - virtual void close() = 0; - - //! Read from stream - /*! - Read up to \p n bytes into \p buffer, returning the number read - (zero if no data is available or input is shutdown). \p buffer - may be NULL in which case the data is discarded. - */ - virtual UInt32 read(void* buffer, UInt32 n) = 0; - - //! Write to stream - /*! - Write \c n bytes from \c buffer to the stream. If this can't - complete immediately it will block. Data may be buffered in - order to return more quickly. A output error event is generated - when writing fails. - */ - virtual void write(const void* buffer, UInt32 n) = 0; - - //! Flush the stream - /*! - Waits until all buffered data has been written to the stream. - */ - virtual void flush() = 0; - - //! Shutdown input - /*! - Shutdown the input side of the stream. Any pending input data is - discarded and further reads immediately return 0. - */ - virtual void shutdownInput() = 0; - - //! Shutdown output - /*! - Shutdown the output side of the stream. Any buffered output data - is discarded and further writes generate output error events. Use - \c flush() before \c shutdownOutput() to send buffered output data. - */ - virtual void shutdownOutput() = 0; - - //@} - //! @name accessors - //@{ - - //! Get event target - /*! - Returns the event target for events generated by this stream. It - should be the source stream in a chain of stream filters. - */ - virtual void* getEventTarget() const = 0; - - //! Test if \c read() will succeed - /*! - Returns true iff an immediate \c read() will return data. This - may or may not be the same as \c getSize() > 0, depending on the - stream type. - */ - virtual bool isReady() const = 0; - - //! Get bytes available to read - /*! - Returns a conservative estimate of the available bytes to read - (i.e. a number not greater than the actual number of bytes). - Some streams may not be able to determine this and will always - return zero. - */ - virtual UInt32 getSize() const = 0; - - //! Get input ready event type - /*! - Returns the input ready event type. A stream sends this event - when \c read() will return with data. - */ - static CEvent::Type getInputReadyEvent(); - - //! Get output flushed event type - /*! - Returns the output flushed event type. A stream sends this event - when the output buffer has been flushed. If there have been no - writes since the event was posted, calling \c shutdownOutput() or - \c close() will not discard any data and \c flush() will return - immediately. - */ - static CEvent::Type getOutputFlushedEvent(); - - //! Get output error event type - /*! - Returns the output error event type. A stream sends this event - when a write has failed. - */ - static CEvent::Type getOutputErrorEvent(); - - //! Get input shutdown event type - /*! - Returns the input shutdown event type. This is sent when the - input side of the stream has shutdown. When the input has - shutdown, no more data will ever be available to read. - */ - static CEvent::Type getInputShutdownEvent(); - - //! Get output shutdown event type - /*! - Returns the output shutdown event type. This is sent when the - output side of the stream has shutdown. When the output has - shutdown, no more data can ever be written to the stream. Any - attempt to do so will generate a output error event. - */ - static CEvent::Type getOutputShutdownEvent(); - - //@} - -private: - static CEvent::Type s_inputReadyEvent; - static CEvent::Type s_outputFlushedEvent; - static CEvent::Type s_outputErrorEvent; - static CEvent::Type s_inputShutdownEvent; - static CEvent::Type s_outputShutdownEvent; -}; - -#endif diff --git a/lib/io/IStreamFilterFactory.h b/lib/io/IStreamFilterFactory.h deleted file mode 100644 index 6e6c86ef..00000000 --- a/lib/io/IStreamFilterFactory.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef ISTREAMFILTERFACTORY_H -#define ISTREAMFILTERFACTORY_H - -#include "IInterface.h" - -class IStream; - -//! Stream filter factory interface -/*! -This interface provides factory methods to create stream filters. -*/ -class IStreamFilterFactory : public IInterface { -public: - //! Create filter - /*! - Create and return a stream filter on \p stream. The caller must - delete the returned object. - */ - virtual IStream* create(IStream* stream, bool adoptStream) = 0; -}; - -#endif diff --git a/lib/io/Makefile.am b/lib/io/Makefile.am deleted file mode 100644 index fec1dd31..00000000 --- a/lib/io/Makefile.am +++ /dev/null @@ -1,41 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2002 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -## Process this file with automake to produce Makefile.in -NULL = - -EXTRA_DIST = \ - Makefile.win \ - $(NULL) - -MAINTAINERCLEANFILES = \ - Makefile.in \ - $(NULL) - -noinst_LIBRARIES = libio.a -libio_a_SOURCES = \ - CStreamBuffer.cpp \ - CStreamFilter.cpp \ - IStream.cpp \ - XIO.cpp \ - CStreamBuffer.h \ - CStreamFilter.h \ - IStream.h \ - IStreamFilterFactory.h \ - XIO.h \ - $(NULL) -INCLUDES = \ - -I$(top_srcdir)/lib/common \ - -I$(top_srcdir)/lib/arch \ - -I$(top_srcdir)/lib/base \ - -I$(top_srcdir)/lib/mt \ - $(NULL) diff --git a/lib/io/Makefile.win b/lib/io/Makefile.win deleted file mode 100644 index 765c6909..00000000 --- a/lib/io/Makefile.win +++ /dev/null @@ -1,63 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2007 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -LIB_IO_SRC = lib\io -LIB_IO_DST = $(BUILD_DST)\$(LIB_IO_SRC) -LIB_IO_LIB = "$(LIB_IO_DST)\io.lib" -LIB_IO_CPP = \ - "CStreamBuffer.cpp" \ - "CStreamFilter.cpp" \ - "IStream.cpp" \ - "XIO.cpp" \ - $(NULL) -LIB_IO_OBJ = \ - "$(LIB_IO_DST)\CStreamBuffer.obj" \ - "$(LIB_IO_DST)\CStreamFilter.obj" \ - "$(LIB_IO_DST)\IStream.obj" \ - "$(LIB_IO_DST)\XIO.obj" \ - $(NULL) -LIB_IO_INC = \ - /I"lib\common" \ - /I"lib\arch" \ - /I"lib\base" \ - /I"lib\mt" \ - $(NULL) - -CPP_FILES = $(CPP_FILES) $(LIB_IO_CPP) -OBJ_FILES = $(OBJ_FILES) $(LIB_IO_OBJ) -LIB_FILES = $(LIB_FILES) $(LIB_IO_LIB) - -# Dependency rules -$(LIB_IO_OBJ): $(AUTODEP) -!if EXIST($(LIB_IO_DST)\deps.mak) -!include $(LIB_IO_DST)\deps.mak -!endif - -# Build rules. Use batch-mode rules if possible. -!if DEFINED(_NMAKE_VER) -{$(LIB_IO_SRC)\}.cpp{$(LIB_IO_DST)\}.obj:: -!else -{$(LIB_IO_SRC)\}.cpp{$(LIB_IO_DST)\}.obj: -!endif - @$(ECHO) Compile in $(LIB_IO_SRC) - -@$(MKDIR) $(LIB_IO_DST) 2>NUL: - $(cpp) $(cppdebug) $(cppflags) $(cppvarsmt) /showIncludes \ - $(LIB_IO_INC) \ - /Fo$(LIB_IO_DST)\ \ - /Fd$(LIB_IO_LIB:.lib=.pdb) \ - $< | $(AUTODEP) $(LIB_IO_SRC) $(LIB_IO_DST) -$(LIB_IO_LIB): $(LIB_IO_OBJ) - @$(ECHO) Link $(@F) - $(implib) $(ildebug) $(ilflags) \ - /out:$@ \ - $** - $(AUTODEP) $(LIB_IO_SRC) $(LIB_IO_DST) $(**:.obj=.d) diff --git a/lib/io/XIO.cpp b/lib/io/XIO.cpp deleted file mode 100644 index b7101a4d..00000000 --- a/lib/io/XIO.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "XIO.h" - -// -// XIOClosed -// - -CString -XIOClosed::getWhat() const throw() -{ - return format("XIOClosed", "already closed"); -} - - -// -// XIOEndOfStream -// - -CString -XIOEndOfStream::getWhat() const throw() -{ - return format("XIOEndOfStream", "reached end of stream"); -} - - -// -// XIOWouldBlock -// - -CString -XIOWouldBlock::getWhat() const throw() -{ - return format("XIOWouldBlock", "stream operation would block"); -} diff --git a/lib/io/XIO.h b/lib/io/XIO.h deleted file mode 100644 index cc41ef40..00000000 --- a/lib/io/XIO.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef XIO_H -#define XIO_H - -#include "XBase.h" - -//! Generic I/O exception -XBASE_SUBCLASS(XIO, XBase); - -//! I/O closing exception -/*! -Thrown if a stream cannot be closed. -*/ -XBASE_SUBCLASS(XIOClose, XIO); - -//! I/O already closed exception -/*! -Thrown when attempting to close or perform I/O on an already closed. -stream. -*/ -XBASE_SUBCLASS_WHAT(XIOClosed, XIO); - -//! I/O end of stream exception -/*! -Thrown when attempting to read beyond the end of a stream. -*/ -XBASE_SUBCLASS_WHAT(XIOEndOfStream, XIO); - -//! I/O would block exception -/*! -Thrown if an operation on a stream would block. -*/ -XBASE_SUBCLASS_WHAT(XIOWouldBlock, XIO); - -#endif diff --git a/lib/mt/CCondVar.cpp b/lib/mt/CCondVar.cpp deleted file mode 100644 index d13aedfd..00000000 --- a/lib/mt/CCondVar.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CCondVar.h" -#include "CStopwatch.h" -#include "CArch.h" - -// -// CCondVarBase -// - -CCondVarBase::CCondVarBase(CMutex* mutex) : - m_mutex(mutex) -{ - assert(m_mutex != NULL); - m_cond = ARCH->newCondVar(); -} - -CCondVarBase::~CCondVarBase() -{ - ARCH->closeCondVar(m_cond); -} - -void -CCondVarBase::lock() const -{ - m_mutex->lock(); -} - -void -CCondVarBase::unlock() const -{ - m_mutex->unlock(); -} - -void -CCondVarBase::signal() -{ - ARCH->signalCondVar(m_cond); -} - -void -CCondVarBase::broadcast() -{ - ARCH->broadcastCondVar(m_cond); -} - -bool -CCondVarBase::wait(CStopwatch& timer, double timeout) const -{ - // check timeout against timer - if (timeout >= 0.0) { - timeout -= timer.getTime(); - if (timeout < 0.0) - return false; - } - return wait(timeout); -} - -bool -CCondVarBase::wait(double timeout) const -{ - return ARCH->waitCondVar(m_cond, m_mutex->m_mutex, timeout); -} - -CMutex* -CCondVarBase::getMutex() const -{ - return m_mutex; -} diff --git a/lib/mt/CCondVar.h b/lib/mt/CCondVar.h deleted file mode 100644 index a04102c4..00000000 --- a/lib/mt/CCondVar.h +++ /dev/null @@ -1,224 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CCONDVAR_H -#define CCONDVAR_H - -#include "CMutex.h" -#include "BasicTypes.h" - -class CStopwatch; - -//! Generic condition variable -/*! -This class provides functionality common to all condition variables -but doesn't provide the actual variable storage. A condition variable -is a multiprocessing primitive that can be waited on. Every condition -variable has an associated mutex. -*/ -class CCondVarBase { -public: - /*! - \c mutex must not be NULL. All condition variables have an - associated mutex. The mutex needn't be unique to one condition - variable. - */ - CCondVarBase(CMutex* mutex); - ~CCondVarBase(); - - //! @name manipulators - //@{ - - //! Lock the condition variable's mutex - /*! - Lock the condition variable's mutex. The condition variable should - be locked before reading or writing it. It must be locked for a - call to wait(). Locks are not recursive; locking a locked mutex - will deadlock the thread. - */ - void lock() const; - - //! Unlock the condition variable's mutex - void unlock() const; - - //! Signal the condition variable - /*! - Wake up one waiting thread, if there are any. Which thread gets - woken is undefined. - */ - void signal(); - - //! Signal the condition variable - /*! - Wake up all waiting threads, if any. - */ - void broadcast(); - - //@} - //! @name accessors - //@{ - - //! Wait on the condition variable - /*! - Wait on the condition variable. If \c timeout < 0 then wait until - signalled, otherwise up to \c timeout seconds or until signalled, - whichever comes first. Returns true if the object was signalled - during the wait, false otherwise. - - The proper way to wait for a condition is: - \code - cv.lock(); - while (cv-expr) { - cv.wait(); - } - cv.unlock(); - \endcode - where \c cv-expr involves the value of \c cv and is false when the - condition is satisfied. - - (cancellation point) - */ - bool wait(double timeout = -1.0) const; - - //! Wait on the condition variable - /*! - Same as \c wait(double) but use \c timer to compare against \timeout. - Since clients normally wait on condition variables in a loop, clients - can use this to avoid recalculating \c timeout on each iteration. - Passing a stopwatch with a negative \c timeout is pointless (it will - never time out) but permitted. - - (cancellation point) - */ - bool wait(CStopwatch& timer, double timeout) const; - - //! Get the mutex - /*! - Get the mutex passed to the c'tor. - */ - CMutex* getMutex() const; - - //@} - -private: - // not implemented - CCondVarBase(const CCondVarBase&); - CCondVarBase& operator=(const CCondVarBase&); - -private: - CMutex* m_mutex; - CArchCond m_cond; -}; - -//! Condition variable -/*! -A condition variable with storage for type \c T. -*/ -template -class CCondVar : public CCondVarBase { -public: - //! Initialize using \c value - CCondVar(CMutex* mutex, const T& value); - //! Initialize using another condition variable's value - CCondVar(const CCondVar&); - ~CCondVar(); - - //! @name manipulators - //@{ - - //! Assigns the value of \c cv to this - /*! - Set the variable's value. The condition variable should be locked - before calling this method. - */ - CCondVar& operator=(const CCondVar& cv); - - //! Assigns \c value to this - /*! - Set the variable's value. The condition variable should be locked - before calling this method. - */ - CCondVar& operator=(const T& v); - - //@} - //! @name accessors - //@{ - - //! Get the variable's value - /*! - Get the variable's value. The condition variable should be locked - before calling this method. - */ - operator const volatile T&() const; - - //@} - -private: - volatile T m_data; -}; - -template -inline -CCondVar::CCondVar( - CMutex* mutex, - const T& data) : - CCondVarBase(mutex), - m_data(data) -{ - // do nothing -} - -template -inline -CCondVar::CCondVar( - const CCondVar& cv) : - CCondVarBase(cv.getMutex()), - m_data(cv.m_data) -{ - // do nothing -} - -template -inline -CCondVar::~CCondVar() -{ - // do nothing -} - -template -inline -CCondVar& -CCondVar::operator=(const CCondVar& cv) -{ - m_data = cv.m_data; - return *this; -} - -template -inline -CCondVar& -CCondVar::operator=(const T& data) -{ - m_data = data; - return *this; -} - -template -inline -CCondVar::operator const volatile T&() const -{ - return m_data; -} - -#endif diff --git a/lib/mt/CLock.cpp b/lib/mt/CLock.cpp deleted file mode 100644 index c943395b..00000000 --- a/lib/mt/CLock.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CLock.h" -#include "CCondVar.h" -#include "CMutex.h" - -// -// CLock -// - -CLock::CLock(const CMutex* mutex) : - m_mutex(mutex) -{ - m_mutex->lock(); -} - -CLock::CLock(const CCondVarBase* cv) : - m_mutex(cv->getMutex()) -{ - m_mutex->lock(); -} - -CLock::~CLock() -{ - m_mutex->unlock(); -} diff --git a/lib/mt/CLock.h b/lib/mt/CLock.h deleted file mode 100644 index f00e0cd1..00000000 --- a/lib/mt/CLock.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CLOCK_H -#define CLOCK_H - -#include "common.h" - -class CMutex; -class CCondVarBase; - -//! Mutual exclusion lock utility -/*! -This class locks a mutex or condition variable in the c'tor and unlocks -it in the d'tor. It's easier and safer than manually locking and -unlocking since unlocking must usually be done no matter how a function -exits (including by unwinding due to an exception). -*/ -class CLock { -public: - //! Lock the mutex \c mutex - CLock(const CMutex* mutex); - //! Lock the condition variable \c cv - CLock(const CCondVarBase* cv); - //! Unlock the mutex or condition variable - ~CLock(); - -private: - // not implemented - CLock(const CLock&); - CLock& operator=(const CLock&); - -private: - const CMutex* m_mutex; -}; - -#endif diff --git a/lib/mt/CMutex.cpp b/lib/mt/CMutex.cpp deleted file mode 100644 index 0d2bab3c..00000000 --- a/lib/mt/CMutex.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CMutex.h" -#include "CArch.h" - -// -// CMutex -// - -CMutex::CMutex() -{ - m_mutex = ARCH->newMutex(); -} - -CMutex::CMutex(const CMutex&) -{ - m_mutex = ARCH->newMutex(); -} - -CMutex::~CMutex() -{ - ARCH->closeMutex(m_mutex); -} - -CMutex& -CMutex::operator=(const CMutex&) -{ - return *this; -} - -void -CMutex::lock() const -{ - ARCH->lockMutex(m_mutex); -} - -void -CMutex::unlock() const -{ - ARCH->unlockMutex(m_mutex); -} diff --git a/lib/mt/CMutex.h b/lib/mt/CMutex.h deleted file mode 100644 index c11eeee3..00000000 --- a/lib/mt/CMutex.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CMUTEX_H -#define CMUTEX_H - -#include "IArchMultithread.h" - -//! Mutual exclusion -/*! -A non-recursive mutual exclusion object. Only one thread at a time can -hold a lock on a mutex. Any thread that attempts to lock a locked mutex -will block until the mutex is unlocked. At that time, if any threads are -blocked, exactly one waiting thread will acquire the lock and continue -running. A thread may not lock a mutex it already owns the lock on; if -it tries it will deadlock itself. -*/ -class CMutex { -public: - CMutex(); - //! Equivalent to default c'tor - /*! - Copy c'tor doesn't copy anything. It just makes it possible to - copy objects that contain a mutex. - */ - CMutex(const CMutex&); - ~CMutex(); - - //! @name manipulators - //@{ - - //! Does nothing - /*! - This does nothing. It just makes it possible to assign objects - that contain a mutex. - */ - CMutex& operator=(const CMutex&); - - //@} - //! @name accessors - //@{ - - //! Lock the mutex - /*! - Locks the mutex, which must not have been previously locked by the - calling thread. This blocks if the mutex is already locked by another - thread. - - (cancellation point) - */ - void lock() const; - - //! Unlock the mutex - /*! - Unlocks the mutex, which must have been previously locked by the - calling thread. - */ - void unlock() const; - - //@} - -private: - friend class CCondVarBase; - CArchMutex m_mutex; -}; - -#endif diff --git a/lib/mt/CThread.cpp b/lib/mt/CThread.cpp deleted file mode 100644 index 195b7b67..00000000 --- a/lib/mt/CThread.cpp +++ /dev/null @@ -1,183 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CThread.h" -#include "XMT.h" -#include "XThread.h" -#include "CLog.h" -#include "IJob.h" -#include "CArch.h" - -// -// CThread -// - -CThread::CThread(IJob* job) -{ - m_thread = ARCH->newThread(&CThread::threadFunc, job); - if (m_thread == NULL) { - // couldn't create thread - delete job; - throw XMTThreadUnavailable(); - } -} - -CThread::CThread(const CThread& thread) -{ - m_thread = ARCH->copyThread(thread.m_thread); -} - -CThread::CThread(CArchThread adoptedThread) -{ - m_thread = adoptedThread; -} - -CThread::~CThread() -{ - ARCH->closeThread(m_thread); -} - -CThread& -CThread::operator=(const CThread& thread) -{ - // copy given thread and release ours - CArchThread copy = ARCH->copyThread(thread.m_thread); - ARCH->closeThread(m_thread); - - // cut over - m_thread = copy; - - return *this; -} - -void -CThread::exit(void* result) -{ - throw XThreadExit(result); -} - -void -CThread::cancel() -{ - ARCH->cancelThread(m_thread); -} - -void -CThread::setPriority(int n) -{ - ARCH->setPriorityOfThread(m_thread, n); -} - -void -CThread::unblockPollSocket() -{ - ARCH->unblockPollSocket(m_thread); -} - -CThread -CThread::getCurrentThread() -{ - return CThread(ARCH->newCurrentThread()); -} - -void -CThread::testCancel() -{ - ARCH->testCancelThread(); -} - -bool -CThread::wait(double timeout) const -{ - return ARCH->wait(m_thread, timeout); -} - -void* -CThread::getResult() const -{ - if (wait()) - return ARCH->getResultOfThread(m_thread); - else - return NULL; -} - -IArchMultithread::ThreadID -CThread::getID() const -{ - return ARCH->getIDOfThread(m_thread); -} - -bool -CThread::operator==(const CThread& thread) const -{ - return ARCH->isSameThread(m_thread, thread.m_thread); -} - -bool -CThread::operator!=(const CThread& thread) const -{ - return !ARCH->isSameThread(m_thread, thread.m_thread); -} - -void* -CThread::threadFunc(void* vjob) -{ - // get this thread's id for logging - IArchMultithread::ThreadID id; - { - CArchThread thread = ARCH->newCurrentThread(); - id = ARCH->getIDOfThread(thread); - ARCH->closeThread(thread); - } - - // get job - IJob* job = reinterpret_cast(vjob); - - // run job - void* result = NULL; - try { - // go - LOG((CLOG_DEBUG1 "thread 0x%08x entry", id)); - job->run(); - LOG((CLOG_DEBUG1 "thread 0x%08x exit", id)); - } - - catch (XThreadCancel&) { - // client called cancel() - LOG((CLOG_DEBUG1 "caught cancel on thread 0x%08x", id)); - delete job; - throw; - } - catch (XThreadExit& e) { - // client called exit() - result = e.m_result; - LOG((CLOG_DEBUG1 "caught exit on thread 0x%08x, result %p", id, result)); - } - catch (XBase& e) { - LOG((CLOG_ERR "exception on thread 0x%08x: %s", id, e.what())); - delete job; - throw; - } - catch (...) { - LOG((CLOG_ERR "exception on thread 0x%08x: ", id)); - delete job; - throw; - } - - // done with job - delete job; - - // return exit result - return result; -} diff --git a/lib/mt/CThread.h b/lib/mt/CThread.h deleted file mode 100644 index 896d3778..00000000 --- a/lib/mt/CThread.h +++ /dev/null @@ -1,209 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CTHREAD_H -#define CTHREAD_H - -#include "IArchMultithread.h" - -class IJob; - -//! Thread handle -/*! -Creating a CThread creates a new context of execution (i.e. thread) that -runs simulatenously with the calling thread. A CThread is only a handle -to a thread; deleting a CThread does not cancel or destroy the thread it -refers to and multiple CThread objects can refer to the same thread. - -Threads can terminate themselves but cannot be forced to terminate by -other threads. However, other threads can signal a thread to terminate -itself by cancelling it. And a thread can wait (block) on another thread -to terminate. - -Most functions that can block for an arbitrary time are cancellation -points. A cancellation point is a function that can be interrupted by -a request to cancel the thread. Cancellation points are noted in the -documentation. -*/ -// note -- do not derive from this class -class CThread { -public: - //! Run \c adoptedJob in a new thread - /*! - Create and start a new thread executing the \c adoptedJob. The - new thread takes ownership of \c adoptedJob and will delete it. - */ - CThread(IJob* adoptedJob); - - //! Duplicate a thread handle - /*! - Make a new thread object that refers to an existing thread. - This does \b not start a new thread. - */ - CThread(const CThread&); - - //! Release a thread handle - /*! - Release a thread handle. This does not terminate the thread. A thread - will keep running until the job completes or calls exit() or allows - itself to be cancelled. - */ - ~CThread(); - - //! @name manipulators - //@{ - - //! Assign thread handle - /*! - Assign a thread handle. This has no effect on the threads, it simply - makes this thread object refer to another thread. It does \b not - start a new thread. - */ - CThread& operator=(const CThread&); - - //! Terminate the calling thread - /*! - Terminate the calling thread. This function does not return but - the stack is unwound and automatic objects are destroyed, as if - exit() threw an exception (which is, in fact, what it does). The - argument is saved as the result returned by getResult(). If you - have \c catch(...) blocks then you should add the following before - each to avoid catching the exit: - \code - catch(CThreadExit&) { throw; } - \endcode - or add the \c RETHROW_XTHREAD macro to the \c catch(...) block. - */ - static void exit(void*); - - //! Cancel thread - /*! - Cancel the thread. cancel() never waits for the thread to - terminate; it just posts the cancel and returns. A thread will - terminate when it enters a cancellation point with cancellation - enabled. If cancellation is disabled then the cancel is - remembered but not acted on until the first call to a - cancellation point after cancellation is enabled. - - A cancellation point is a function that can act on cancellation. - A cancellation point does not return if there's a cancel pending. - Instead, it unwinds the stack and destroys automatic objects, as - if cancel() threw an exception (which is, in fact, what it does). - Threads must take care to unlock and clean up any resources they - may have, especially mutexes. They can \c catch(XThreadCancel) to - do that then rethrow the exception or they can let it happen - automatically by doing clean up in the d'tors of automatic - objects (like CLock). Clients are strongly encouraged to do the latter. - During cancellation, further cancel() calls are ignored (i.e. - a thread cannot be interrupted by a cancel during cancellation). - - Clients that \c catch(XThreadCancel) must always rethrow the - exception. Clients that \c catch(...) must either rethrow the - exception or include a \c catch(XThreadCancel) handler that - rethrows. The \c RETHROW_XTHREAD macro may be useful for that. - */ - void cancel(); - - //! Change thread priority - /*! - Change the priority of the thread. Normal priority is 0, 1 is - the next lower, etc. -1 is the next higher, etc. but boosting - the priority may not be permitted and will be silenty ignored. - */ - void setPriority(int n); - - //! Force pollSocket() to return - /*! - Forces a currently blocked pollSocket() in the thread to return - immediately. - */ - void unblockPollSocket(); - - //@} - //! @name accessors - //@{ - - //! Get current thread's handle - /*! - Return a CThread object representing the calling thread. - */ - static CThread getCurrentThread(); - - //! Test for cancellation - /*! - testCancel() does nothing but is a cancellation point. Call - this to make a function itself a cancellation point. If the - thread was cancelled and cancellation is enabled this will - cause the thread to unwind the stack and terminate. - - (cancellation point) - */ - static void testCancel(); - - //! Wait for thread to terminate - /*! - Waits for the thread to terminate (by exit() or cancel() or - by returning from the thread job) for up to \c timeout seconds, - returning true if the thread terminated and false otherwise. - This returns immediately with false if called by a thread on - itself and immediately with true if the thread has already - terminated. This will wait forever if \c timeout < 0.0. - - (cancellation point) - */ - bool wait(double timeout = -1.0) const; - - //! Get the exit result - /*! - Returns the exit result. This does an implicit wait(). It returns - NULL immediately if called by a thread on itself or on a thread that - was cancelled. - - (cancellation point) - */ - void* getResult() const; - - //! Get the thread id - /*! - Returns an integer id for this thread. This id must not be used to - check if two CThread objects refer to the same thread. Use - operator==() for that. - */ - IArchMultithread::ThreadID - getID() const; - - //! Compare thread handles - /*! - Returns true if two CThread objects refer to the same thread. - */ - bool operator==(const CThread&) const; - - //! Compare thread handles - /*! - Returns true if two CThread objects do not refer to the same thread. - */ - bool operator!=(const CThread&) const; - - //@} - -private: - CThread(CArchThread); - - static void* threadFunc(void*); - -private: - CArchThread m_thread; -}; - -#endif diff --git a/lib/mt/Makefile.am b/lib/mt/Makefile.am deleted file mode 100644 index fbf01c03..00000000 --- a/lib/mt/Makefile.am +++ /dev/null @@ -1,42 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2002 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -## Process this file with automake to produce Makefile.in -NULL = - -EXTRA_DIST = \ - Makefile.win \ - $(NULL) - -MAINTAINERCLEANFILES = \ - Makefile.in \ - $(NULL) - -noinst_LIBRARIES = libmt.a -libmt_a_SOURCES = \ - CCondVar.cpp \ - CLock.cpp \ - CMutex.cpp \ - CThread.cpp \ - XMT.cpp \ - CCondVar.h \ - CLock.h \ - CMutex.h \ - CThread.h \ - XMT.h \ - XThread.h \ - $(NULL) -INCLUDES = \ - -I$(top_srcdir)/lib/common \ - -I$(top_srcdir)/lib/arch \ - -I$(top_srcdir)/lib/base \ - $(NULL) diff --git a/lib/mt/Makefile.win b/lib/mt/Makefile.win deleted file mode 100644 index 4ae79130..00000000 --- a/lib/mt/Makefile.win +++ /dev/null @@ -1,64 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2007 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -LIB_MT_SRC = lib\mt -LIB_MT_DST = $(BUILD_DST)\$(LIB_MT_SRC) -LIB_MT_LIB = "$(LIB_MT_DST)\mt.lib" -LIB_MT_CPP = \ - "CCondVar.cpp" \ - "CLock.cpp" \ - "CMutex.cpp" \ - "CThread.cpp" \ - "XMT.cpp" \ - $(NULL) -LIB_MT_OBJ = \ - "$(LIB_MT_DST)\CCondVar.obj" \ - "$(LIB_MT_DST)\CLock.obj" \ - "$(LIB_MT_DST)\CMutex.obj" \ - "$(LIB_MT_DST)\CThread.obj" \ - "$(LIB_MT_DST)\XMT.obj" \ - $(NULL) -LIB_MT_INC = \ - /I"lib\common" \ - /I"lib\arch" \ - /I"lib\base" \ - $(NULL) - -CPP_FILES = $(CPP_FILES) $(LIB_MT_CPP) -OBJ_FILES = $(OBJ_FILES) $(LIB_MT_OBJ) -LIB_FILES = $(LIB_FILES) $(LIB_MT_LIB) - -# Dependency rules -$(LIB_MT_OBJ): $(AUTODEP) -!if EXIST($(LIB_MT_DST)\deps.mak) -!include $(LIB_MT_DST)\deps.mak -!endif - -# Build rules. Use batch-mode rules if possible. -!if DEFINED(_NMAKE_VER) -{$(LIB_MT_SRC)\}.cpp{$(LIB_MT_DST)\}.obj:: -!else -{$(LIB_MT_SRC)\}.cpp{$(LIB_MT_DST)\}.obj: -!endif - @$(ECHO) Compile in $(LIB_MT_SRC) - -@$(MKDIR) $(LIB_MT_DST) 2>NUL: - $(cpp) $(cppdebug) $(cppflags) $(cppvarsmt) /showIncludes \ - $(LIB_MT_INC) \ - /Fo$(LIB_MT_DST)\ \ - /Fd$(LIB_MT_LIB:.lib=.pdb) \ - $< | $(AUTODEP) $(LIB_MT_SRC) $(LIB_MT_DST) -$(LIB_MT_LIB): $(LIB_MT_OBJ) - @$(ECHO) Link $(@F) - $(implib) $(ildebug) $(ilflags) \ - /out:$@ \ - $** - $(AUTODEP) $(LIB_MT_SRC) $(LIB_MT_DST) $(**:.obj=.d) diff --git a/lib/mt/XMT.cpp b/lib/mt/XMT.cpp deleted file mode 100644 index b10d2d79..00000000 --- a/lib/mt/XMT.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "XMT.h" - -// -// XMTThreadUnavailable -// - -CString -XMTThreadUnavailable::getWhat() const throw() -{ - return format("XMTThreadUnavailable", "cannot create thread"); -} diff --git a/lib/mt/XMT.h b/lib/mt/XMT.h deleted file mode 100644 index f66428ea..00000000 --- a/lib/mt/XMT.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef XMT_H -#define XMT_H - -#include "XBase.h" - -//! Generic multithreading exception -XBASE_SUBCLASS(XMT, XBase); - -//! Thread creation exception -/*! -Thrown when a thread cannot be created. -*/ -XBASE_SUBCLASS_WHAT(XMTThreadUnavailable, XMT); - -#endif diff --git a/lib/mt/XThread.h b/lib/mt/XThread.h deleted file mode 100644 index 30dff1da..00000000 --- a/lib/mt/XThread.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef XTHREAD_H -#define XTHREAD_H - -#include "XArch.h" - -//! Thread exception to exit -/*! -Thrown by CThread::exit() to exit a thread. Clients of CThread -must not throw this type but must rethrow it if caught (by -XThreadExit, XThread, or ...). -*/ -class XThreadExit : public XThread { -public: - //! \c result is the result of the thread - XThreadExit(void* result) : m_result(result) { } - ~XThreadExit() { } - -public: - void* m_result; -}; - -#endif diff --git a/lib/net/CNetworkAddress.cpp b/lib/net/CNetworkAddress.cpp deleted file mode 100644 index 7daeed55..00000000 --- a/lib/net/CNetworkAddress.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CNetworkAddress.h" -#include "XSocket.h" -#include "CArch.h" -#include "XArch.h" -#include - -// -// CNetworkAddress -// - -// name re-resolution adapted from a patch by Brent Priddy. - -CNetworkAddress::CNetworkAddress() : - m_address(NULL), - m_hostname(), - m_port(0) -{ - // note -- make no calls to CNetwork socket interface here; - // we're often called prior to CNetwork::init(). -} - -CNetworkAddress::CNetworkAddress(int port) : - m_address(NULL), - m_hostname(), - m_port(port) -{ - checkPort(); - m_address = ARCH->newAnyAddr(IArchNetwork::kINET); - ARCH->setAddrPort(m_address, m_port); -} - -CNetworkAddress::CNetworkAddress(const CNetworkAddress& addr) : - m_address(addr.m_address != NULL ? ARCH->copyAddr(addr.m_address) : NULL), - m_hostname(addr.m_hostname), - m_port(addr.m_port) -{ - // do nothing -} - -CNetworkAddress::CNetworkAddress(const CString& hostname, int port) : - m_address(NULL), - m_hostname(hostname), - m_port(port) -{ - // check for port suffix - CString::size_type i = m_hostname.rfind(':'); - if (i != CString::npos && i + 1 < m_hostname.size()) { - // found a colon. see if it looks like an IPv6 address. - bool colonNotation = false; - bool dotNotation = false; - bool doubleColon = false; - for (CString::size_type j = 0; j < i; ++j) { - if (m_hostname[j] == ':') { - colonNotation = true; - dotNotation = false; - if (m_hostname[j + 1] == ':') { - doubleColon = true; - } - } - else if (m_hostname[j] == '.' && colonNotation) { - dotNotation = true; - } - } - - // port suffix is ambiguous with IPv6 notation if there's - // a double colon and the end of the address is not in dot - // notation. in that case we assume it's not a port suffix. - // the user can replace the double colon with zeros to - // disambiguate. - if ((!doubleColon || dotNotation) || !colonNotation) { - // parse port from hostname - char* end; - const char* chostname = m_hostname.c_str(); - long suffixPort = strtol(chostname + i + 1, &end, 10); - if (end == chostname + i + 1 || *end != '\0') { - throw XSocketAddress(XSocketAddress::kBadPort, - m_hostname, m_port); - } - - // trim port from hostname - m_hostname.erase(i); - - // save port - m_port = static_cast(suffixPort); - } - } - - // check port number - checkPort(); -} - -CNetworkAddress::~CNetworkAddress() -{ - if (m_address != NULL) { - ARCH->closeAddr(m_address); - } -} - -CNetworkAddress& -CNetworkAddress::operator=(const CNetworkAddress& addr) -{ - CArchNetAddress newAddr = NULL; - if (addr.m_address != NULL) { - newAddr = ARCH->copyAddr(addr.m_address); - } - if (m_address != NULL) { - ARCH->closeAddr(m_address); - } - m_address = newAddr; - m_hostname = addr.m_hostname; - m_port = addr.m_port; - return *this; -} - -void -CNetworkAddress::resolve() -{ - // discard previous address - if (m_address != NULL) { - ARCH->closeAddr(m_address); - m_address = NULL; - } - - try { - // if hostname is empty then use wildcard address otherwise look - // up the name. - if (m_hostname.empty()) { - m_address = ARCH->newAnyAddr(IArchNetwork::kINET); - } - else { - m_address = ARCH->nameToAddr(m_hostname); - } - } - catch (XArchNetworkNameUnknown&) { - throw XSocketAddress(XSocketAddress::kNotFound, m_hostname, m_port); - } - catch (XArchNetworkNameNoAddress&) { - throw XSocketAddress(XSocketAddress::kNoAddress, m_hostname, m_port); - } - catch (XArchNetworkNameUnsupported&) { - throw XSocketAddress(XSocketAddress::kUnsupported, m_hostname, m_port); - } - catch (XArchNetworkName&) { - throw XSocketAddress(XSocketAddress::kUnknown, m_hostname, m_port); - } - - // set port in address - ARCH->setAddrPort(m_address, m_port); -} - -bool -CNetworkAddress::operator==(const CNetworkAddress& addr) const -{ - return ARCH->isEqualAddr(m_address, addr.m_address); -} - -bool -CNetworkAddress::operator!=(const CNetworkAddress& addr) const -{ - return !operator==(addr); -} - -bool -CNetworkAddress::isValid() const -{ - return (m_address != NULL); -} - -const CArchNetAddress& -CNetworkAddress::getAddress() const -{ - return m_address; -} - -int -CNetworkAddress::getPort() const -{ - return m_port; -} - -CString -CNetworkAddress::getHostname() const -{ - return m_hostname; -} - -void -CNetworkAddress::checkPort() -{ - // check port number - if (m_port <= 0 || m_port > 65535) { - throw XSocketAddress(XSocketAddress::kBadPort, m_hostname, m_port); - } -} diff --git a/lib/net/CNetworkAddress.h b/lib/net/CNetworkAddress.h deleted file mode 100644 index d29b93b1..00000000 --- a/lib/net/CNetworkAddress.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CNETWORKADDRESS_H -#define CNETWORKADDRESS_H - -#include "CString.h" -#include "BasicTypes.h" -#include "IArchNetwork.h" - -//! Network address type -/*! -This class represents a network address. -*/ -class CNetworkAddress { -public: - /*! - Constructs the invalid address - */ - CNetworkAddress(); - - /*! - Construct the wildcard address with the given port. \c port must - not be zero. - */ - CNetworkAddress(int port); - - /*! - Construct the network address for the given \c hostname and \c port. - If \c hostname can be parsed as a numerical address then that's how - it's used, otherwise it's used as a host name. If \c hostname ends - in ":[0-9]+" then that suffix is extracted and used as the port, - overridding the port parameter. The resulting port must be a valid - port number (zero is not a valid port number) otherwise \c XSocketAddress - is thrown with an error of \c XSocketAddress::kBadPort. The hostname - is not resolved by the c'tor; use \c resolve to do that. - */ - CNetworkAddress(const CString& hostname, int port); - - CNetworkAddress(const CNetworkAddress&); - - ~CNetworkAddress(); - - CNetworkAddress& operator=(const CNetworkAddress&); - - //! @name manipulators - //@{ - - //! Resolve address - /*! - Resolves the hostname to an address. This can be done any number of - times and is done automatically by the c'tor taking a hostname. - Throws XSocketAddress if resolution is unsuccessful, after which - \c isValid returns false until the next call to this method. - */ - void resolve(); - - //@} - //! @name accessors - //@{ - - //! Check address equality - /*! - Returns true if this address is equal to \p address. - */ - bool operator==(const CNetworkAddress& address) const; - - //! Check address inequality - /*! - Returns true if this address is not equal to \p address. - */ - bool operator!=(const CNetworkAddress& address) const; - - //! Check address validity - /*! - Returns true if this is not the invalid address. - */ - bool isValid() const; - - //! Get address - /*! - Returns the address in the platform's native network address - structure. - */ - const CArchNetAddress& getAddress() const; - - //! Get port - /*! - Returns the port passed to the c'tor as a suffix to the hostname, - if that existed, otherwise as passed directly to the c'tor. - */ - int getPort() const; - - //! Get hostname - /*! - Returns the hostname passed to the c'tor sans any port suffix. - */ - CString getHostname() const; - - //@} - -private: - void checkPort(); - -private: - CArchNetAddress m_address; - CString m_hostname; - int m_port; -}; - -#endif diff --git a/lib/net/CSocketMultiplexer.cpp b/lib/net/CSocketMultiplexer.cpp deleted file mode 100644 index 2082730b..00000000 --- a/lib/net/CSocketMultiplexer.cpp +++ /dev/null @@ -1,359 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CSocketMultiplexer.h" -#include "ISocketMultiplexerJob.h" -#include "CCondVar.h" -#include "CLock.h" -#include "CMutex.h" -#include "CThread.h" -#include "CLog.h" -#include "TMethodJob.h" -#include "CArch.h" -#include "XArch.h" -#include "stdvector.h" - -// -// CSocketMultiplexer -// - -CSocketMultiplexer* CSocketMultiplexer::s_instance = NULL; - -CSocketMultiplexer::CSocketMultiplexer() : - m_mutex(new CMutex), - m_thread(NULL), - m_update(false), - m_jobsReady(new CCondVar(m_mutex, false)), - m_jobListLock(new CCondVar(m_mutex, false)), - m_jobListLockLocked(new CCondVar(m_mutex, false)), - m_jobListLocker(NULL), - m_jobListLockLocker(NULL) -{ - assert(s_instance == NULL); - - // this pointer just has to be unique and not NULL. it will - // never be dereferenced. it's used to identify cursor nodes - // in the jobs list. - m_cursorMark = reinterpret_cast(this); - - // start thread - m_thread = new CThread(new TMethodJob( - this, &CSocketMultiplexer::serviceThread)); - - s_instance = this; -} - -CSocketMultiplexer::~CSocketMultiplexer() -{ - m_thread->cancel(); - m_thread->unblockPollSocket(); - m_thread->wait(); - delete m_thread; - delete m_jobsReady; - delete m_jobListLock; - delete m_jobListLockLocked; - delete m_jobListLocker; - delete m_jobListLockLocker; - delete m_mutex; - - // clean up jobs - for (CSocketJobMap::iterator i = m_socketJobMap.begin(); - i != m_socketJobMap.end(); ++i) { - delete *(i->second); - } - - s_instance = NULL; -} - -CSocketMultiplexer* -CSocketMultiplexer::getInstance() -{ - return s_instance; -} - -void -CSocketMultiplexer::addSocket(ISocket* socket, ISocketMultiplexerJob* job) -{ - assert(socket != NULL); - assert(job != NULL); - - // prevent other threads from locking the job list - lockJobListLock(); - - // break thread out of poll - m_thread->unblockPollSocket(); - - // lock the job list - lockJobList(); - - // insert/replace job - CSocketJobMap::iterator i = m_socketJobMap.find(socket); - if (i == m_socketJobMap.end()) { - // we *must* put the job at the end so the order of jobs in - // the list continue to match the order of jobs in pfds in - // serviceThread(). - CJobCursor j = m_socketJobs.insert(m_socketJobs.end(), job); - m_update = true; - m_socketJobMap.insert(std::make_pair(socket, j)); - } - else { - CJobCursor j = i->second; - if (*j != job) { - delete *j; - *j = job; - } - m_update = true; - } - - // unlock the job list - unlockJobList(); -} - -void -CSocketMultiplexer::removeSocket(ISocket* socket) -{ - assert(socket != NULL); - - // prevent other threads from locking the job list - lockJobListLock(); - - // break thread out of poll - m_thread->unblockPollSocket(); - - // lock the job list - lockJobList(); - - // remove job. rather than removing it from the map we put NULL - // in the list instead so the order of jobs in the list continues - // to match the order of jobs in pfds in serviceThread(). - CSocketJobMap::iterator i = m_socketJobMap.find(socket); - if (i != m_socketJobMap.end()) { - if (*(i->second) != NULL) { - delete *(i->second); - *(i->second) = NULL; - m_update = true; - } - } - - // unlock the job list - unlockJobList(); -} - -void -CSocketMultiplexer::serviceThread(void*) -{ - std::vector pfds; - IArchNetwork::CPollEntry pfd; - - // service the connections - for (;;) { - CThread::testCancel(); - - // wait until there are jobs to handle - { - CLock lock(m_mutex); - while (!(bool)*m_jobsReady) { - m_jobsReady->wait(); - } - } - - // lock the job list - lockJobListLock(); - lockJobList(); - - // collect poll entries - if (m_update) { - m_update = false; - pfds.clear(); - pfds.reserve(m_socketJobMap.size()); - - CJobCursor cursor = newCursor(); - CJobCursor jobCursor = nextCursor(cursor); - while (jobCursor != m_socketJobs.end()) { - ISocketMultiplexerJob* job = *jobCursor; - if (job != NULL) { - pfd.m_socket = job->getSocket(); - pfd.m_events = 0; - if (job->isReadable()) { - pfd.m_events |= IArchNetwork::kPOLLIN; - } - if (job->isWritable()) { - pfd.m_events |= IArchNetwork::kPOLLOUT; - } - pfds.push_back(pfd); - } - jobCursor = nextCursor(cursor); - } - deleteCursor(cursor); - } - - int status; - try { - // check for status - if (!pfds.empty()) { - status = ARCH->pollSocket(&pfds[0], pfds.size(), -1); - } - else { - status = 0; - } - } - catch (XArchNetwork& e) { - LOG((CLOG_WARN "error in socket multiplexer: %s", e.what().c_str())); - status = 0; - } - - if (status != 0) { - // iterate over socket jobs, invoking each and saving the - // new job. - UInt32 i = 0; - CJobCursor cursor = newCursor(); - CJobCursor jobCursor = nextCursor(cursor); - while (i < pfds.size() && jobCursor != m_socketJobs.end()) { - if (*jobCursor != NULL) { - // get poll state - unsigned short revents = pfds[i].m_revents; - bool read = ((revents & IArchNetwork::kPOLLIN) != 0); - bool write = ((revents & IArchNetwork::kPOLLOUT) != 0); - bool error = ((revents & (IArchNetwork::kPOLLERR | - IArchNetwork::kPOLLNVAL)) != 0); - - // run job - ISocketMultiplexerJob* job = *jobCursor; - ISocketMultiplexerJob* newJob = job->run(read, write, error); - - // save job, if different - if (newJob != job) { - CLock lock(m_mutex); - delete job; - *jobCursor = newJob; - m_update = true; - } - ++i; - } - - // next job - jobCursor = nextCursor(cursor); - } - deleteCursor(cursor); - } - - // delete any removed socket jobs - for (CSocketJobMap::iterator i = m_socketJobMap.begin(); - i != m_socketJobMap.end();) { - if (*(i->second) == NULL) { - m_socketJobMap.erase(i++); - m_update = true; - } - else { - ++i; - } - } - - // unlock the job list - unlockJobList(); - } -} - -CSocketMultiplexer::CJobCursor -CSocketMultiplexer::newCursor() -{ - CLock lock(m_mutex); - return m_socketJobs.insert(m_socketJobs.begin(), m_cursorMark); -} - -CSocketMultiplexer::CJobCursor -CSocketMultiplexer::nextCursor(CJobCursor cursor) -{ - CLock lock(m_mutex); - CJobCursor j = m_socketJobs.end(); - CJobCursor i = cursor; - while (++i != m_socketJobs.end()) { - if (*i != m_cursorMark) { - // found a real job (as opposed to a cursor) - j = i; - - // move our cursor just past the job - m_socketJobs.splice(++i, m_socketJobs, cursor); - break; - } - } - return j; -} - -void -CSocketMultiplexer::deleteCursor(CJobCursor cursor) -{ - CLock lock(m_mutex); - m_socketJobs.erase(cursor); -} - -void -CSocketMultiplexer::lockJobListLock() -{ - CLock lock(m_mutex); - - // wait for the lock on the lock - while (*m_jobListLockLocked) { - m_jobListLockLocked->wait(); - } - - // take ownership of the lock on the lock - *m_jobListLockLocked = true; - m_jobListLockLocker = new CThread(CThread::getCurrentThread()); -} - -void -CSocketMultiplexer::lockJobList() -{ - CLock lock(m_mutex); - - // make sure we're the one that called lockJobListLock() - assert(*m_jobListLockLocker == CThread::getCurrentThread()); - - // wait for the job list lock - while (*m_jobListLock) { - m_jobListLock->wait(); - } - - // take ownership of the lock - *m_jobListLock = true; - m_jobListLocker = m_jobListLockLocker; - m_jobListLockLocker = NULL; - - // release the lock on the lock - *m_jobListLockLocked = false; - m_jobListLockLocked->broadcast(); -} - -void -CSocketMultiplexer::unlockJobList() -{ - CLock lock(m_mutex); - - // make sure we're the one that called lockJobList() - assert(*m_jobListLocker == CThread::getCurrentThread()); - - // release the lock - delete m_jobListLocker; - m_jobListLocker = NULL; - *m_jobListLock = false; - m_jobListLock->signal(); - - // set new jobs ready state - bool isReady = !m_socketJobMap.empty(); - if (*m_jobsReady != isReady) { - *m_jobsReady = isReady; - m_jobsReady->signal(); - } -} diff --git a/lib/net/CSocketMultiplexer.h b/lib/net/CSocketMultiplexer.h deleted file mode 100644 index bb96ca70..00000000 --- a/lib/net/CSocketMultiplexer.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CSOCKETMULTIPLEXER_H -#define CSOCKETMULTIPLEXER_H - -#include "IArchNetwork.h" -#include "stdlist.h" -#include "stdmap.h" - -template -class CCondVar; -class CMutex; -class CThread; -class ISocket; -class ISocketMultiplexerJob; - -//! Socket multiplexer -/*! -A socket multiplexer services multiple sockets simultaneously. -*/ -class CSocketMultiplexer { -public: - CSocketMultiplexer(); - ~CSocketMultiplexer(); - - //! @name manipulators - //@{ - - void addSocket(ISocket*, ISocketMultiplexerJob*); - - void removeSocket(ISocket*); - - //@} - //! @name accessors - //@{ - - // maybe belongs on ISocketMultiplexer - static CSocketMultiplexer* - getInstance(); - - //@} - -private: - // list of jobs. we use a list so we can safely iterate over it - // while other threads modify it. - typedef std::list CSocketJobs; - typedef CSocketJobs::iterator CJobCursor; - typedef std::map CSocketJobMap; - - // service sockets. the service thread will only access m_sockets - // and m_update while m_pollable and m_polling are true. all other - // threads must only modify these when m_pollable and m_polling are - // false. only the service thread sets m_polling. - void serviceThread(void*); - - // create, iterate, and destroy a cursor. a cursor is used to - // safely iterate through the job list while other threads modify - // the list. it works by inserting a dummy item in the list and - // moving that item through the list. the dummy item will never - // be removed by other edits so an iterator pointing at the item - // remains valid until we remove the dummy item in deleteCursor(). - // nextCursor() finds the next non-dummy item, moves our dummy - // item just past it, and returns an iterator for the non-dummy - // item. all cursor calls lock the mutex for their duration. - CJobCursor newCursor(); - CJobCursor nextCursor(CJobCursor); - void deleteCursor(CJobCursor); - - // lock out locking the job list. this blocks if another thread - // has already locked out locking. once it returns, only the - // calling thread will be able to lock the job list after any - // current lock is released. - void lockJobListLock(); - - // lock the job list. this blocks if the job list is already - // locked. the calling thread must have called requestJobLock. - void lockJobList(); - - // unlock the job list and the lock out on locking. - void unlockJobList(); - -private: - CMutex* m_mutex; - CThread* m_thread; - bool m_update; - CCondVar* m_jobsReady; - CCondVar* m_jobListLock; - CCondVar* m_jobListLockLocked; - CThread* m_jobListLocker; - CThread* m_jobListLockLocker; - - CSocketJobs m_socketJobs; - CSocketJobMap m_socketJobMap; - ISocketMultiplexerJob* m_cursorMark; - - static CSocketMultiplexer* s_instance; -}; - -#endif diff --git a/lib/net/CTCPListenSocket.cpp b/lib/net/CTCPListenSocket.cpp deleted file mode 100644 index 938bf95a..00000000 --- a/lib/net/CTCPListenSocket.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CTCPListenSocket.h" -#include "CNetworkAddress.h" -#include "CSocketMultiplexer.h" -#include "CTCPSocket.h" -#include "TSocketMultiplexerMethodJob.h" -#include "XSocket.h" -#include "XIO.h" -#include "CLock.h" -#include "CMutex.h" -#include "IEventQueue.h" -#include "CArch.h" -#include "XArch.h" - -// -// CTCPListenSocket -// - -CTCPListenSocket::CTCPListenSocket() -{ - m_mutex = new CMutex; - try { - m_socket = ARCH->newSocket(IArchNetwork::kINET, IArchNetwork::kSTREAM); - } - catch (XArchNetwork& e) { - throw XSocketCreate(e.what()); - } -} - -CTCPListenSocket::~CTCPListenSocket() -{ - try { - if (m_socket != NULL) { - CSocketMultiplexer::getInstance()->removeSocket(this); - ARCH->closeSocket(m_socket); - } - } - catch (...) { - // ignore - } - delete m_mutex; -} - -void -CTCPListenSocket::bind(const CNetworkAddress& addr) -{ - try { - CLock lock(m_mutex); - ARCH->setReuseAddrOnSocket(m_socket, true); - ARCH->bindSocket(m_socket, addr.getAddress()); - ARCH->listenOnSocket(m_socket); - CSocketMultiplexer::getInstance()->addSocket(this, - new TSocketMultiplexerMethodJob( - this, &CTCPListenSocket::serviceListening, - m_socket, true, false)); - } - catch (XArchNetworkAddressInUse& e) { - throw XSocketAddressInUse(e.what()); - } - catch (XArchNetwork& e) { - throw XSocketBind(e.what()); - } -} - -void -CTCPListenSocket::close() -{ - CLock lock(m_mutex); - if (m_socket == NULL) { - throw XIOClosed(); - } - try { - CSocketMultiplexer::getInstance()->removeSocket(this); - ARCH->closeSocket(m_socket); - m_socket = NULL; - } - catch (XArchNetwork& e) { - throw XSocketIOClose(e.what()); - } -} - -void* -CTCPListenSocket::getEventTarget() const -{ - return const_cast(reinterpret_cast(this)); -} - -IDataSocket* -CTCPListenSocket::accept() -{ - try { - IDataSocket* socket = - new CTCPSocket(ARCH->acceptSocket(m_socket, NULL)); - if (socket != NULL) { - CSocketMultiplexer::getInstance()->addSocket(this, - new TSocketMultiplexerMethodJob( - this, &CTCPListenSocket::serviceListening, - m_socket, true, false)); - } - return socket; - } - catch (XArchNetwork&) { - return NULL; - } -} - -ISocketMultiplexerJob* -CTCPListenSocket::serviceListening(ISocketMultiplexerJob* job, - bool read, bool, bool error) -{ - if (error) { - close(); - return NULL; - } - if (read) { - EVENTQUEUE->addEvent(CEvent(getConnectingEvent(), this, NULL)); - // stop polling on this socket until the client accepts - return NULL; - } - return job; -} diff --git a/lib/net/CTCPListenSocket.h b/lib/net/CTCPListenSocket.h deleted file mode 100644 index 5321b8db..00000000 --- a/lib/net/CTCPListenSocket.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CTCPLISTENSOCKET_H -#define CTCPLISTENSOCKET_H - -#include "IListenSocket.h" -#include "IArchNetwork.h" - -class CMutex; -class ISocketMultiplexerJob; - -//! TCP listen socket -/*! -A listen socket using TCP. -*/ -class CTCPListenSocket : public IListenSocket { -public: - CTCPListenSocket(); - ~CTCPListenSocket(); - - // ISocket overrides - virtual void bind(const CNetworkAddress&); - virtual void close(); - virtual void* getEventTarget() const; - - // IListenSocket overrides - virtual IDataSocket* accept(); - -private: - ISocketMultiplexerJob* - serviceListening(ISocketMultiplexerJob*, - bool, bool, bool); - -private: - CArchSocket m_socket; - CMutex* m_mutex; -}; - -#endif diff --git a/lib/net/CTCPSocket.cpp b/lib/net/CTCPSocket.cpp deleted file mode 100644 index c44b41ea..00000000 --- a/lib/net/CTCPSocket.cpp +++ /dev/null @@ -1,542 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CTCPSocket.h" -#include "CNetworkAddress.h" -#include "CSocketMultiplexer.h" -#include "TSocketMultiplexerMethodJob.h" -#include "XSocket.h" -#include "CLock.h" -#include "CLog.h" -#include "IEventQueue.h" -#include "IEventJob.h" -#include "CArch.h" -#include "XArch.h" -#include - -// -// CTCPSocket -// - -CTCPSocket::CTCPSocket() : - m_mutex(), - m_flushed(&m_mutex, true) -{ - try { - m_socket = ARCH->newSocket(IArchNetwork::kINET, IArchNetwork::kSTREAM); - } - catch (XArchNetwork& e) { - throw XSocketCreate(e.what()); - } - - init(); -} - -CTCPSocket::CTCPSocket(CArchSocket socket) : - m_mutex(), - m_socket(socket), - m_flushed(&m_mutex, true) -{ - assert(m_socket != NULL); - - // socket starts in connected state - init(); - onConnected(); - setJob(newJob()); -} - -CTCPSocket::~CTCPSocket() -{ - try { - close(); - } - catch (...) { - // ignore - } -} - -void -CTCPSocket::bind(const CNetworkAddress& addr) -{ - try { - ARCH->bindSocket(m_socket, addr.getAddress()); - } - catch (XArchNetworkAddressInUse& e) { - throw XSocketAddressInUse(e.what()); - } - catch (XArchNetwork& e) { - throw XSocketBind(e.what()); - } -} - -void -CTCPSocket::close() -{ - // remove ourself from the multiplexer - setJob(NULL); - - CLock lock(&m_mutex); - - // clear buffers and enter disconnected state - if (m_connected) { - sendEvent(getDisconnectedEvent()); - } - onDisconnected(); - - // close the socket - if (m_socket != NULL) { - CArchSocket socket = m_socket; - m_socket = NULL; - try { - ARCH->closeSocket(socket); - } - catch (XArchNetwork& e) { - // ignore, there's not much we can do - LOG((CLOG_WARN "error closing socket: %s", e.what().c_str())); - } - } -} - -void* -CTCPSocket::getEventTarget() const -{ - return const_cast(reinterpret_cast(this)); -} - -UInt32 -CTCPSocket::read(void* buffer, UInt32 n) -{ - // copy data directly from our input buffer - CLock lock(&m_mutex); - UInt32 size = m_inputBuffer.getSize(); - if (n > size) { - n = size; - } - if (buffer != NULL && n != 0) { - memcpy(buffer, m_inputBuffer.peek(n), n); - } - m_inputBuffer.pop(n); - - // if no more data and we cannot read or write then send disconnected - if (n > 0 && m_inputBuffer.getSize() == 0 && !m_readable && !m_writable) { - sendEvent(getDisconnectedEvent()); - m_connected = false; - } - - return n; -} - -void -CTCPSocket::write(const void* buffer, UInt32 n) -{ - bool wasEmpty; - { - CLock lock(&m_mutex); - - // must not have shutdown output - if (!m_writable) { - sendEvent(getOutputErrorEvent()); - return; - } - - // ignore empty writes - if (n == 0) { - return; - } - - // copy data to the output buffer - wasEmpty = (m_outputBuffer.getSize() == 0); - m_outputBuffer.write(buffer, n); - - // there's data to write - m_flushed = false; - } - - // make sure we're waiting to write - if (wasEmpty) { - setJob(newJob()); - } -} - -void -CTCPSocket::flush() -{ - CLock lock(&m_mutex); - while (m_flushed == false) { - m_flushed.wait(); - } -} - -void -CTCPSocket::shutdownInput() -{ - bool useNewJob = false; - { - CLock lock(&m_mutex); - - // shutdown socket for reading - try { - ARCH->closeSocketForRead(m_socket); - } - catch (XArchNetwork&) { - // ignore - } - - // shutdown buffer for reading - if (m_readable) { - sendEvent(getInputShutdownEvent()); - onInputShutdown(); - useNewJob = true; - } - } - if (useNewJob) { - setJob(newJob()); - } -} - -void -CTCPSocket::shutdownOutput() -{ - bool useNewJob = false; - { - CLock lock(&m_mutex); - - // shutdown socket for writing - try { - ARCH->closeSocketForWrite(m_socket); - } - catch (XArchNetwork&) { - // ignore - } - - // shutdown buffer for writing - if (m_writable) { - sendEvent(getOutputShutdownEvent()); - onOutputShutdown(); - useNewJob = true; - } - } - if (useNewJob) { - setJob(newJob()); - } -} - -bool -CTCPSocket::isReady() const -{ - CLock lock(&m_mutex); - return (m_inputBuffer.getSize() > 0); -} - -UInt32 -CTCPSocket::getSize() const -{ - CLock lock(&m_mutex); - return m_inputBuffer.getSize(); -} - -void -CTCPSocket::connect(const CNetworkAddress& addr) -{ - { - CLock lock(&m_mutex); - - // fail on attempts to reconnect - if (m_socket == NULL || m_connected) { - sendConnectionFailedEvent("busy"); - return; - } - - try { - if (ARCH->connectSocket(m_socket, addr.getAddress())) { - sendEvent(getConnectedEvent()); - onConnected(); - } - else { - // connection is in progress - m_writable = true; - } - } - catch (XArchNetwork& e) { - throw XSocketConnect(e.what()); - } - } - setJob(newJob()); -} - -void -CTCPSocket::init() -{ - // default state - m_connected = false; - m_readable = false; - m_writable = false; - - try { - // turn off Nagle algorithm. we send lots of very short messages - // that should be sent without (much) delay. for example, the - // mouse motion messages are much less useful if they're delayed. - ARCH->setNoDelayOnSocket(m_socket, true); - } - catch (XArchNetwork& e) { - try { - ARCH->closeSocket(m_socket); - m_socket = NULL; - } - catch (XArchNetwork&) { - // ignore - } - throw XSocketCreate(e.what()); - } -} - -void -CTCPSocket::setJob(ISocketMultiplexerJob* job) -{ - // multiplexer will delete the old job - if (job == NULL) { - CSocketMultiplexer::getInstance()->removeSocket(this); - } - else { - CSocketMultiplexer::getInstance()->addSocket(this, job); - } -} - -ISocketMultiplexerJob* -CTCPSocket::newJob() -{ - // note -- must have m_mutex locked on entry - - if (m_socket == NULL) { - return NULL; - } - else if (!m_connected) { - assert(!m_readable); - if (!(m_readable || m_writable)) { - return NULL; - } - return new TSocketMultiplexerMethodJob( - this, &CTCPSocket::serviceConnecting, - m_socket, m_readable, m_writable); - } - else { - if (!(m_readable || (m_writable && (m_outputBuffer.getSize() > 0)))) { - return NULL; - } - return new TSocketMultiplexerMethodJob( - this, &CTCPSocket::serviceConnected, - m_socket, m_readable, - m_writable && (m_outputBuffer.getSize() > 0)); - } -} - -void -CTCPSocket::sendConnectionFailedEvent(const char* msg) -{ - CConnectionFailedInfo* info = (CConnectionFailedInfo*)malloc( - sizeof(CConnectionFailedInfo) + strlen(msg)); - strcpy(info->m_what, msg); - EVENTQUEUE->addEvent(CEvent(getConnectionFailedEvent(), - getEventTarget(), info)); -} - -void -CTCPSocket::sendEvent(CEvent::Type type) -{ - EVENTQUEUE->addEvent(CEvent(type, getEventTarget(), NULL)); -} - -void -CTCPSocket::onConnected() -{ - m_connected = true; - m_readable = true; - m_writable = true; -} - -void -CTCPSocket::onInputShutdown() -{ - m_inputBuffer.pop(m_inputBuffer.getSize()); - m_readable = false; -} - -void -CTCPSocket::onOutputShutdown() -{ - m_outputBuffer.pop(m_outputBuffer.getSize()); - m_writable = false; - - // we're now flushed - m_flushed = true; - m_flushed.broadcast(); -} - -void -CTCPSocket::onDisconnected() -{ - // disconnected - onInputShutdown(); - onOutputShutdown(); - m_connected = false; -} - -ISocketMultiplexerJob* -CTCPSocket::serviceConnecting(ISocketMultiplexerJob* job, - bool, bool write, bool error) -{ - CLock lock(&m_mutex); - - // should only check for errors if error is true but checking a new - // socket (and a socket that's connecting should be new) for errors - // should be safe and Mac OS X appears to have a bug where a - // non-blocking stream socket that fails to connect immediately is - // reported by select as being writable (i.e. connected) even when - // the connection has failed. this is easily demonstrated on OS X - // 10.3.4 by starting a synergy client and telling to connect to - // another system that's not running a synergy server. it will - // claim to have connected then quickly disconnect (i guess because - // read returns 0 bytes). unfortunately, synergy attempts to - // reconnect immediately, the process repeats and we end up - // spinning the CPU. luckily, OS X does set SO_ERROR on the - // socket correctly when the connection has failed so checking for - // errors works. (curiously, sometimes OS X doesn't report - // connection refused. when that happens it at least doesn't - // report the socket as being writable so synergy is able to time - // out the attempt.) - if (error || true) { - try { - // connection may have failed or succeeded - ARCH->throwErrorOnSocket(m_socket); - } - catch (XArchNetwork& e) { - sendConnectionFailedEvent(e.what().c_str()); - onDisconnected(); - return newJob(); - } - } - - if (write) { - sendEvent(getConnectedEvent()); - onConnected(); - return newJob(); - } - - return job; -} - -ISocketMultiplexerJob* -CTCPSocket::serviceConnected(ISocketMultiplexerJob* job, - bool read, bool write, bool error) -{ - CLock lock(&m_mutex); - - if (error) { - sendEvent(getDisconnectedEvent()); - onDisconnected(); - return newJob(); - } - - bool needNewJob = false; - - if (write) { - try { - // write data - UInt32 n = m_outputBuffer.getSize(); - const void* buffer = m_outputBuffer.peek(n); - n = (UInt32)ARCH->writeSocket(m_socket, buffer, n); - - // discard written data - if (n > 0) { - m_outputBuffer.pop(n); - if (m_outputBuffer.getSize() == 0) { - sendEvent(getOutputFlushedEvent()); - m_flushed = true; - m_flushed.broadcast(); - needNewJob = true; - } - } - } - catch (XArchNetworkShutdown&) { - // remote read end of stream hungup. our output side - // has therefore shutdown. - onOutputShutdown(); - sendEvent(getOutputShutdownEvent()); - if (!m_readable && m_inputBuffer.getSize() == 0) { - sendEvent(getDisconnectedEvent()); - m_connected = false; - } - needNewJob = true; - } - catch (XArchNetworkDisconnected&) { - // stream hungup - onDisconnected(); - sendEvent(getDisconnectedEvent()); - needNewJob = true; - } - catch (XArchNetwork& e) { - // other write error - LOG((CLOG_WARN "error writing socket: %s", e.what().c_str())); - onDisconnected(); - sendEvent(getOutputErrorEvent()); - sendEvent(getDisconnectedEvent()); - needNewJob = true; - } - } - - if (read && m_readable) { - try { - UInt8 buffer[4096]; - size_t n = ARCH->readSocket(m_socket, buffer, sizeof(buffer)); - if (n > 0) { - bool wasEmpty = (m_inputBuffer.getSize() == 0); - - // slurp up as much as possible - do { - m_inputBuffer.write(buffer, n); - n = ARCH->readSocket(m_socket, buffer, sizeof(buffer)); - } while (n > 0); - - // send input ready if input buffer was empty - if (wasEmpty) { - sendEvent(getInputReadyEvent()); - } - } - else { - // remote write end of stream hungup. our input side - // has therefore shutdown but don't flush our buffer - // since there's still data to be read. - sendEvent(getInputShutdownEvent()); - if (!m_writable && m_inputBuffer.getSize() == 0) { - sendEvent(getDisconnectedEvent()); - m_connected = false; - } - m_readable = false; - needNewJob = true; - } - } - catch (XArchNetworkDisconnected&) { - // stream hungup - sendEvent(getDisconnectedEvent()); - onDisconnected(); - needNewJob = true; - } - catch (XArchNetwork& e) { - // ignore other read error - LOG((CLOG_WARN "error reading socket: %s", e.what().c_str())); - } - } - - return needNewJob ? newJob() : job; -} diff --git a/lib/net/CTCPSocket.h b/lib/net/CTCPSocket.h deleted file mode 100644 index aa1df8c1..00000000 --- a/lib/net/CTCPSocket.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CTCPSOCKET_H -#define CTCPSOCKET_H - -#include "IDataSocket.h" -#include "CStreamBuffer.h" -#include "CCondVar.h" -#include "CMutex.h" -#include "IArchNetwork.h" - -class CMutex; -class CThread; -class ISocketMultiplexerJob; - -//! TCP data socket -/*! -A data socket using TCP. -*/ -class CTCPSocket : public IDataSocket { -public: - CTCPSocket(); - CTCPSocket(CArchSocket); - ~CTCPSocket(); - - // ISocket overrides - virtual void bind(const CNetworkAddress&); - virtual void close(); - virtual void* getEventTarget() const; - - // IStream overrides - virtual UInt32 read(void* buffer, UInt32 n); - virtual void write(const void* buffer, UInt32 n); - virtual void flush(); - virtual void shutdownInput(); - virtual void shutdownOutput(); - virtual bool isReady() const; - virtual UInt32 getSize() const; - - // IDataSocket overrides - virtual void connect(const CNetworkAddress&); - -private: - void init(); - - void setJob(ISocketMultiplexerJob*); - ISocketMultiplexerJob* newJob(); - void sendConnectionFailedEvent(const char*); - void sendEvent(CEvent::Type); - - void onConnected(); - void onInputShutdown(); - void onOutputShutdown(); - void onDisconnected(); - - ISocketMultiplexerJob* - serviceConnecting(ISocketMultiplexerJob*, - bool, bool, bool); - ISocketMultiplexerJob* - serviceConnected(ISocketMultiplexerJob*, - bool, bool, bool); - -private: - CMutex m_mutex; - CArchSocket m_socket; - CStreamBuffer m_inputBuffer; - CStreamBuffer m_outputBuffer; - CCondVar m_flushed; - bool m_connected; - bool m_readable; - bool m_writable; -}; - -#endif diff --git a/lib/net/CTCPSocketFactory.cpp b/lib/net/CTCPSocketFactory.cpp deleted file mode 100644 index f590efa0..00000000 --- a/lib/net/CTCPSocketFactory.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CTCPSocketFactory.h" -#include "CTCPSocket.h" -#include "CTCPListenSocket.h" - -// -// CTCPSocketFactory -// - -CTCPSocketFactory::CTCPSocketFactory() -{ - // do nothing -} - -CTCPSocketFactory::~CTCPSocketFactory() -{ - // do nothing -} - -IDataSocket* -CTCPSocketFactory::create() const -{ - return new CTCPSocket; -} - -IListenSocket* -CTCPSocketFactory::createListen() const -{ - return new CTCPListenSocket; -} diff --git a/lib/net/CTCPSocketFactory.h b/lib/net/CTCPSocketFactory.h deleted file mode 100644 index 2b946d19..00000000 --- a/lib/net/CTCPSocketFactory.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CTCPSOCKETFACTORY_H -#define CTCPSOCKETFACTORY_H - -#include "ISocketFactory.h" - -//! Socket factory for TCP sockets -class CTCPSocketFactory : public ISocketFactory { -public: - CTCPSocketFactory(); - virtual ~CTCPSocketFactory(); - - // ISocketFactory overrides - virtual IDataSocket* create() const; - virtual IListenSocket* createListen() const; -}; - -#endif diff --git a/lib/net/IDataSocket.cpp b/lib/net/IDataSocket.cpp deleted file mode 100644 index dc4b08ed..00000000 --- a/lib/net/IDataSocket.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "IDataSocket.h" - -// -// IDataSocket -// - -CEvent::Type IDataSocket::s_connectedEvent = CEvent::kUnknown; -CEvent::Type IDataSocket::s_failedEvent = CEvent::kUnknown; - -CEvent::Type -IDataSocket::getConnectedEvent() -{ - return CEvent::registerTypeOnce(s_connectedEvent, - "IDataSocket::connected"); -} - -CEvent::Type -IDataSocket::getConnectionFailedEvent() -{ - return CEvent::registerTypeOnce(s_failedEvent, - "IDataSocket::failed"); -} - -void -IDataSocket::close() -{ - // this is here to work around a VC++6 bug. see the header file. - assert(0 && "bad call"); -} - -void* -IDataSocket::getEventTarget() const -{ - // this is here to work around a VC++6 bug. see the header file. - assert(0 && "bad call"); - return NULL; -} diff --git a/lib/net/IDataSocket.h b/lib/net/IDataSocket.h deleted file mode 100644 index d760d4ab..00000000 --- a/lib/net/IDataSocket.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef IDATASOCKET_H -#define IDATASOCKET_H - -#include "ISocket.h" -#include "IStream.h" - -//! Data stream socket interface -/*! -This interface defines the methods common to all network sockets that -represent a full-duplex data stream. -*/ -class IDataSocket : public ISocket, public IStream { -public: - class CConnectionFailedInfo { - public: - // pointer to a string describing the failure - char m_what[1]; - }; - - //! @name manipulators - //@{ - - //! Connect socket - /*! - Attempt to connect to a remote endpoint. This returns immediately - and sends a connected event when successful or a connection failed - event when it fails. The stream acts as if shutdown for input and - output until the stream connects. - */ - virtual void connect(const CNetworkAddress&) = 0; - - //@} - //! @name accessors - //@{ - - //! Get connected event type - /*! - Returns the socket connected event type. A socket sends this - event when a remote connection has been established. - */ - static CEvent::Type getConnectedEvent(); - - //! Get connection failed event type - /*! - Returns the socket connection failed event type. A socket sends - this event when an attempt to connect to a remote port has failed. - The data is a pointer to a CConnectionFailedInfo. - */ - static CEvent::Type getConnectionFailedEvent(); - - //@} - - // ISocket overrides - // close() and getEventTarget() aren't pure to work around a bug - // in VC++6. it claims the methods are unused locals and warns - // that it's removing them. it's presumably tickled by inheriting - // methods with identical signatures from both superclasses. - virtual void bind(const CNetworkAddress&) = 0; - virtual void close(); - virtual void* getEventTarget() const; - - // IStream overrides - virtual UInt32 read(void* buffer, UInt32 n) = 0; - virtual void write(const void* buffer, UInt32 n) = 0; - virtual void flush() = 0; - virtual void shutdownInput() = 0; - virtual void shutdownOutput() = 0; - virtual bool isReady() const = 0; - virtual UInt32 getSize() const = 0; - -private: - static CEvent::Type s_connectedEvent; - static CEvent::Type s_failedEvent; -}; - -#endif diff --git a/lib/net/IListenSocket.cpp b/lib/net/IListenSocket.cpp deleted file mode 100644 index 20dbc9a4..00000000 --- a/lib/net/IListenSocket.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "IListenSocket.h" - -// -// IListenSocket -// - -CEvent::Type IListenSocket::s_connectingEvent = CEvent::kUnknown; - -CEvent::Type -IListenSocket::getConnectingEvent() -{ - return CEvent::registerTypeOnce(s_connectingEvent, - "IListenSocket::connecting"); -} diff --git a/lib/net/IListenSocket.h b/lib/net/IListenSocket.h deleted file mode 100644 index 894234f4..00000000 --- a/lib/net/IListenSocket.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef ILISTENSOCKET_H -#define ILISTENSOCKET_H - -#include "ISocket.h" - -class IDataSocket; - -//! Listen socket interface -/*! -This interface defines the methods common to all network sockets that -listen for incoming connections. -*/ -class IListenSocket : public ISocket { -public: - //! @name manipulators - //@{ - - //! Accept connection - /*! - Accept a connection, returning a socket representing the full-duplex - data stream. Returns NULL if no socket is waiting to be accepted. - This is only valid after a call to \c bind(). - */ - virtual IDataSocket* accept() = 0; - - //@} - //! @name accessors - //@{ - - //! Get connecting event type - /*! - Returns the socket connecting event type. A socket sends this - event when a remote connection is waiting to be accepted. - */ - static CEvent::Type getConnectingEvent(); - - //@} - - // ISocket overrides - virtual void bind(const CNetworkAddress&) = 0; - virtual void close() = 0; - virtual void* getEventTarget() const = 0; - -private: - static CEvent::Type s_connectingEvent; -}; - -#endif diff --git a/lib/net/ISocket.cpp b/lib/net/ISocket.cpp deleted file mode 100644 index a9aaf1ac..00000000 --- a/lib/net/ISocket.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "ISocket.h" - -// -// ISocket -// - -CEvent::Type ISocket::s_disconnectedEvent = CEvent::kUnknown; - -CEvent::Type -ISocket::getDisconnectedEvent() -{ - return CEvent::registerTypeOnce(s_disconnectedEvent, - "ISocket::disconnected"); -} diff --git a/lib/net/ISocket.h b/lib/net/ISocket.h deleted file mode 100644 index 4452e023..00000000 --- a/lib/net/ISocket.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef ISOCKET_H -#define ISOCKET_H - -#include "IInterface.h" -#include "CEvent.h" - -class CNetworkAddress; - -//! Generic socket interface -/*! -This interface defines the methods common to all network sockets. -Generated events use \c this as the target. -*/ -class ISocket : public IInterface { -public: - //! @name manipulators - //@{ - - //! Bind socket to address - /*! - Binds the socket to a particular address. - */ - virtual void bind(const CNetworkAddress&) = 0; - - //! Close socket - /*! - Closes the socket. This should flush the output stream. - */ - virtual void close() = 0; - - //@} - //! @name accessors - //@{ - - //! Get event target - /*! - Returns the event target for events generated by this socket. - */ - virtual void* getEventTarget() const = 0; - - //! Get disconnected event type - /*! - Returns the socket disconnected event type. A socket sends this - event when the remote side of the socket has disconnected or - shutdown both input and output. - */ - static CEvent::Type getDisconnectedEvent(); - - //@} - -private: - static CEvent::Type s_disconnectedEvent; -}; - -#endif diff --git a/lib/net/ISocketFactory.h b/lib/net/ISocketFactory.h deleted file mode 100644 index dbf9ae26..00000000 --- a/lib/net/ISocketFactory.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef ISOCKETFACTORY_H -#define ISOCKETFACTORY_H - -#include "IInterface.h" - -class IDataSocket; -class IListenSocket; - -//! Socket factory -/*! -This interface defines the methods common to all factories used to -create sockets. -*/ -class ISocketFactory : public IInterface { -public: - //! @name accessors - //@{ - - //! Create data socket - virtual IDataSocket* create() const = 0; - - //! Create listen socket - virtual IListenSocket* createListen() const = 0; - - //@} -}; - -#endif diff --git a/lib/net/ISocketMultiplexerJob.h b/lib/net/ISocketMultiplexerJob.h deleted file mode 100644 index ac722326..00000000 --- a/lib/net/ISocketMultiplexerJob.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef ISOCKETMULTIPLEXERJOB_H -#define ISOCKETMULTIPLEXERJOB_H - -#include "IArchNetwork.h" -#include "IInterface.h" - -//! Socket multiplexer job -/*! -A socket multiplexer job handles events on a socket. -*/ -class ISocketMultiplexerJob : public IInterface { -public: - //! @name manipulators - //@{ - - //! Handle socket event - /*! - Called by a socket multiplexer when the socket becomes readable, - writable, or has an error. It should return itself if the same - job can continue to service events, a new job if the socket must - be serviced differently, or NULL if the socket should no longer - be serviced. The socket is readable if \p readable is true, - writable if \p writable is true, and in error if \p error is - true. - - This call must not attempt to directly change the job for this - socket by calling \c addSocket() or \c removeSocket() on the - multiplexer. It must instead return the new job. It can, - however, add or remove jobs for other sockets. - */ - virtual ISocketMultiplexerJob* - run(bool readable, bool writable, bool error) = 0; - - //@} - //! @name accessors - //@{ - - //! Get the socket - /*! - Return the socket to multiplex - */ - virtual CArchSocket getSocket() const = 0; - - //! Check for interest in readability - /*! - Return true if the job is interested in being run if the socket - becomes readable. - */ - virtual bool isReadable() const = 0; - - //! Check for interest in writability - /*! - Return true if the job is interested in being run if the socket - becomes writable. - */ - virtual bool isWritable() const = 0; - - //@} -}; - -#endif diff --git a/lib/net/Makefile.am b/lib/net/Makefile.am deleted file mode 100644 index b49fe363..00000000 --- a/lib/net/Makefile.am +++ /dev/null @@ -1,54 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2002 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -## Process this file with automake to produce Makefile.in -NULL = - -EXTRA_DIST = \ - Makefile.win \ - $(NULL) - -MAINTAINERCLEANFILES = \ - Makefile.in \ - $(NULL) - -noinst_LIBRARIES = libnet.a -libnet_a_SOURCES = \ - CNetworkAddress.cpp \ - CSocketMultiplexer.cpp \ - CTCPListenSocket.cpp \ - CTCPSocket.cpp \ - CTCPSocketFactory.cpp \ - IDataSocket.cpp \ - IListenSocket.cpp \ - ISocket.cpp \ - XSocket.cpp \ - CNetworkAddress.h \ - CSocketMultiplexer.h \ - CTCPListenSocket.h \ - CTCPSocket.h \ - CTCPSocketFactory.h \ - IDataSocket.h \ - IListenSocket.h \ - ISocket.h \ - ISocketFactory.h \ - ISocketMultiplexerJob.h \ - TSocketMultiplexerMethodJob.h \ - XSocket.h \ - $(NULL) -INCLUDES = \ - -I$(top_srcdir)/lib/common \ - -I$(top_srcdir)/lib/arch \ - -I$(top_srcdir)/lib/base \ - -I$(top_srcdir)/lib/mt \ - -I$(top_srcdir)/lib/io \ - $(NULL) diff --git a/lib/net/Makefile.win b/lib/net/Makefile.win deleted file mode 100644 index d4cd357c..00000000 --- a/lib/net/Makefile.win +++ /dev/null @@ -1,74 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2007 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -LIB_NET_SRC = lib\net -LIB_NET_DST = $(BUILD_DST)\$(LIB_NET_SRC) -LIB_NET_LIB = "$(LIB_NET_DST)\net.lib" -LIB_NET_CPP = \ - "CNetworkAddress.cpp" \ - "CSocketMultiplexer.cpp" \ - "CTCPListenSocket.cpp" \ - "CTCPSocket.cpp" \ - "CTCPSocketFactory.cpp" \ - "IDataSocket.cpp" \ - "IListenSocket.cpp" \ - "ISocket.cpp" \ - "XSocket.cpp" \ - $(NULL) -LIB_NET_OBJ = \ - "$(LIB_NET_DST)\CNetworkAddress.obj" \ - "$(LIB_NET_DST)\CSocketMultiplexer.obj" \ - "$(LIB_NET_DST)\CTCPListenSocket.obj" \ - "$(LIB_NET_DST)\CTCPSocket.obj" \ - "$(LIB_NET_DST)\CTCPSocketFactory.obj" \ - "$(LIB_NET_DST)\IDataSocket.obj" \ - "$(LIB_NET_DST)\IListenSocket.obj" \ - "$(LIB_NET_DST)\ISocket.obj" \ - "$(LIB_NET_DST)\XSocket.obj" \ - $(NULL) -LIB_NET_INC = \ - /I"lib\common" \ - /I"lib\arch" \ - /I"lib\base" \ - /I"lib\mt" \ - /I"lib\io" \ - $(NULL) - -CPP_FILES = $(CPP_FILES) $(LIB_NET_CPP) -OBJ_FILES = $(OBJ_FILES) $(LIB_NET_OBJ) -LIB_FILES = $(LIB_FILES) $(LIB_NET_LIB) - -# Dependency rules -$(LIB_NET_OBJ): $(AUTODEP) -!if EXIST($(LIB_NET_DST)\deps.mak) -!include $(LIB_NET_DST)\deps.mak -!endif - -# Build rules. Use batch-mode rules if possible. -!if DEFINED(_NMAKE_VER) -{$(LIB_NET_SRC)\}.cpp{$(LIB_NET_DST)\}.obj:: -!else -{$(LIB_NET_SRC)\}.cpp{$(LIB_NET_DST)\}.obj: -!endif - @$(ECHO) Compile in $(LIB_NET_SRC) - -@$(MKDIR) $(LIB_NET_DST) 2>NUL: - $(cpp) $(cppdebug) $(cppflags) $(cppvarsmt) /showIncludes \ - $(LIB_NET_INC) \ - /Fo$(LIB_NET_DST)\ \ - /Fd$(LIB_NET_LIB:.lib=.pdb) \ - $< | $(AUTODEP) $(LIB_NET_SRC) $(LIB_NET_DST) -$(LIB_NET_LIB): $(LIB_NET_OBJ) - @$(ECHO) Link $(@F) - $(implib) $(ildebug) $(ilflags) \ - /out:$@ \ - $** - $(AUTODEP) $(LIB_NET_SRC) $(LIB_NET_DST) $(**:.obj=.d) diff --git a/lib/net/TSocketMultiplexerMethodJob.h b/lib/net/TSocketMultiplexerMethodJob.h deleted file mode 100644 index 992885c4..00000000 --- a/lib/net/TSocketMultiplexerMethodJob.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef TSOCKERMULTIPLEXERMETHODJOB_H -#define TSOCKERMULTIPLEXERMETHODJOB_H - -#include "ISocketMultiplexerJob.h" -#include "CArch.h" - -//! Use a method as a socket multiplexer job -/*! -A socket multiplexer job class that invokes a member function. -*/ -template -class TSocketMultiplexerMethodJob : public ISocketMultiplexerJob { -public: - typedef ISocketMultiplexerJob* - (T::*Method)(ISocketMultiplexerJob*, bool, bool, bool); - - //! run() invokes \c object->method(arg) - TSocketMultiplexerMethodJob(T* object, Method method, - CArchSocket socket, bool readable, bool writeable); - virtual ~TSocketMultiplexerMethodJob(); - - // IJob overrides - virtual ISocketMultiplexerJob* - run(bool readable, bool writable, bool error); - virtual CArchSocket getSocket() const; - virtual bool isReadable() const; - virtual bool isWritable() const; - -private: - T* m_object; - Method m_method; - CArchSocket m_socket; - bool m_readable; - bool m_writable; - void* m_arg; -}; - -template -inline -TSocketMultiplexerMethodJob::TSocketMultiplexerMethodJob(T* object, - Method method, CArchSocket socket, - bool readable, bool writable) : - m_object(object), - m_method(method), - m_socket(ARCH->copySocket(socket)), - m_readable(readable), - m_writable(writable) -{ - // do nothing -} - -template -inline -TSocketMultiplexerMethodJob::~TSocketMultiplexerMethodJob() -{ - ARCH->closeSocket(m_socket); -} - -template -inline -ISocketMultiplexerJob* -TSocketMultiplexerMethodJob::run(bool read, bool write, bool error) -{ - if (m_object != NULL) { - return (m_object->*m_method)(this, read, write, error); - } - return NULL; -} - -template -inline -CArchSocket -TSocketMultiplexerMethodJob::getSocket() const -{ - return m_socket; -} - -template -inline -bool -TSocketMultiplexerMethodJob::isReadable() const -{ - return m_readable; -} - -template -inline -bool -TSocketMultiplexerMethodJob::isWritable() const -{ - return m_writable; -} - -#endif diff --git a/lib/net/XSocket.cpp b/lib/net/XSocket.cpp deleted file mode 100644 index 8471538a..00000000 --- a/lib/net/XSocket.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "XSocket.h" -#include "CStringUtil.h" - -// -// XSocketAddress -// - -XSocketAddress::XSocketAddress(EError error, - const CString& hostname, int port) throw() : - m_error(error), - m_hostname(hostname), - m_port(port) -{ - // do nothing -} - -XSocketAddress::EError -XSocketAddress::getError() const throw() -{ - return m_error; -} - -CString -XSocketAddress::getHostname() const throw() -{ - return m_hostname; -} - -int -XSocketAddress::getPort() const throw() -{ - return m_port; -} - -CString -XSocketAddress::getWhat() const throw() -{ - static const char* s_errorID[] = { - "XSocketAddressUnknown", - "XSocketAddressNotFound", - "XSocketAddressNoAddress", - "XSocketAddressUnsupported", - "XSocketAddressBadPort" - }; - static const char* s_errorMsg[] = { - "unknown error for: %{1}:%{2}", - "address not found for: %{1}", - "no address for: %{1}", - "unsupported address for: %{1}", - "invalid port" // m_port may not be set to the bad port - }; - return format(s_errorID[m_error], s_errorMsg[m_error], - m_hostname.c_str(), - CStringUtil::print("%d", m_port).c_str()); -} - - -// -// XSocketIOClose -// - -CString -XSocketIOClose::getWhat() const throw() -{ - return format("XSocketIOClose", "close: %{1}", what()); -} - - -// -// XSocketBind -// - -CString -XSocketBind::getWhat() const throw() -{ - return format("XSocketBind", "cannot bind address: %{1}", what()); -} - - -// -// XSocketConnect -// - -CString -XSocketConnect::getWhat() const throw() -{ - return format("XSocketConnect", "cannot connect socket: %{1}", what()); -} - - -// -// XSocketCreate -// - -CString -XSocketCreate::getWhat() const throw() -{ - return format("XSocketCreate", "cannot create socket: %{1}", what()); -} diff --git a/lib/net/XSocket.h b/lib/net/XSocket.h deleted file mode 100644 index f84285b9..00000000 --- a/lib/net/XSocket.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef XSOCKET_H -#define XSOCKET_H - -#include "XIO.h" -#include "XBase.h" -#include "CString.h" -#include "BasicTypes.h" - -//! Generic socket exception -XBASE_SUBCLASS(XSocket, XBase); - -//! Socket bad address exception -/*! -Thrown when attempting to create an invalid network address. -*/ -class XSocketAddress : public XSocket { -public: - //! Failure codes - enum EError { - kUnknown, //!< Unknown error - kNotFound, //!< The hostname is unknown - kNoAddress, //!< The hostname is valid but has no IP address - kUnsupported, //!< The hostname is valid but has no supported address - kBadPort //!< The port is invalid - }; - - XSocketAddress(EError, const CString& hostname, int port) throw(); - - //! @name accessors - //@{ - - //! Get the error code - EError getError() const throw(); - //! Get the hostname - CString getHostname() const throw(); - //! Get the port - int getPort() const throw(); - - //@} - -protected: - // XBase overrides - virtual CString getWhat() const throw(); - -private: - EError m_error; - CString m_hostname; - int m_port; -}; - -//! I/O closing exception -/*! -Thrown if a stream cannot be closed. -*/ -XBASE_SUBCLASS_FORMAT(XSocketIOClose, XIOClose); - -//! Socket cannot bind address exception -/*! -Thrown when a socket cannot be bound to an address. -*/ -XBASE_SUBCLASS_FORMAT(XSocketBind, XSocket); - -//! Socket address in use exception -/*! -Thrown when a socket cannot be bound to an address because the address -is already in use. -*/ -XBASE_SUBCLASS(XSocketAddressInUse, XSocketBind); - -//! Cannot connect socket exception -/*! -Thrown when a socket cannot connect to a remote endpoint. -*/ -XBASE_SUBCLASS_FORMAT(XSocketConnect, XSocket); - -//! Cannot create socket exception -/*! -Thrown when a socket cannot be created (by the operating system). -*/ -XBASE_SUBCLASS_FORMAT(XSocketCreate, XSocket); - -#endif diff --git a/lib/platform/CMSWindowsClipboard.cpp b/lib/platform/CMSWindowsClipboard.cpp deleted file mode 100644 index 7df9db9f..00000000 --- a/lib/platform/CMSWindowsClipboard.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CMSWindowsClipboard.h" -#include "CMSWindowsClipboardTextConverter.h" -#include "CMSWindowsClipboardUTF16Converter.h" -#include "CMSWindowsClipboardBitmapConverter.h" -#include "CMSWindowsClipboardHTMLConverter.h" -#include "CLog.h" -#include "CArchMiscWindows.h" - -// -// CMSWindowsClipboard -// - -UINT CMSWindowsClipboard::s_ownershipFormat = 0; - -CMSWindowsClipboard::CMSWindowsClipboard(HWND window) : - m_window(window), - m_time(0) -{ - // add converters, most desired first - m_converters.push_back(new CMSWindowsClipboardUTF16Converter); - if (CArchMiscWindows::isWindows95Family()) { - // windows nt family converts to/from unicode automatically. - // let it do so to avoid text encoding issues. - m_converters.push_back(new CMSWindowsClipboardTextConverter); - } - m_converters.push_back(new CMSWindowsClipboardBitmapConverter); - m_converters.push_back(new CMSWindowsClipboardHTMLConverter); -} - -CMSWindowsClipboard::~CMSWindowsClipboard() -{ - clearConverters(); -} - -bool -CMSWindowsClipboard::emptyUnowned() -{ - LOG((CLOG_DEBUG "empty clipboard")); - - // empty the clipboard (and take ownership) - if (!EmptyClipboard()) { - LOG((CLOG_DEBUG "failed to grab clipboard")); - return false; - } - - return true; -} - -bool -CMSWindowsClipboard::empty() -{ - if (!emptyUnowned()) { - return false; - } - - // mark clipboard as being owned by synergy - HGLOBAL data = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, 1); - SetClipboardData(getOwnershipFormat(), data); - - return true; -} - -void -CMSWindowsClipboard::add(EFormat format, const CString& data) -{ - LOG((CLOG_DEBUG "add %d bytes to clipboard format: %d", data.size(), format)); - - // convert data to win32 form - for (ConverterList::const_iterator index = m_converters.begin(); - index != m_converters.end(); ++index) { - IMSWindowsClipboardConverter* converter = *index; - - // skip converters for other formats - if (converter->getFormat() == format) { - HANDLE win32Data = converter->fromIClipboard(data); - if (win32Data != NULL) { - UINT win32Format = converter->getWin32Format(); - if (SetClipboardData(win32Format, win32Data) == NULL) { - // free converted data if we couldn't put it on - // the clipboard - GlobalFree(win32Data); - } - } - } - } -} - -bool -CMSWindowsClipboard::open(Time time) const -{ - LOG((CLOG_DEBUG "open clipboard")); - - if (!OpenClipboard(m_window)) { - LOG((CLOG_WARN "failed to open clipboard")); - return false; - } - - m_time = time; - - return true; -} - -void -CMSWindowsClipboard::close() const -{ - LOG((CLOG_DEBUG "close clipboard")); - CloseClipboard(); -} - -IClipboard::Time -CMSWindowsClipboard::getTime() const -{ - return m_time; -} - -bool -CMSWindowsClipboard::has(EFormat format) const -{ - for (ConverterList::const_iterator index = m_converters.begin(); - index != m_converters.end(); ++index) { - IMSWindowsClipboardConverter* converter = *index; - if (converter->getFormat() == format) { - if (IsClipboardFormatAvailable(converter->getWin32Format())) { - return true; - } - } - } - return false; -} - -CString -CMSWindowsClipboard::get(EFormat format) const -{ - // find the converter for the first clipboard format we can handle - IMSWindowsClipboardConverter* converter = NULL; - UINT win32Format = EnumClipboardFormats(0); - while (converter == NULL && win32Format != 0) { - for (ConverterList::const_iterator index = m_converters.begin(); - index != m_converters.end(); ++index) { - converter = *index; - if (converter->getWin32Format() == win32Format && - converter->getFormat() == format) { - break; - } - converter = NULL; - } - win32Format = EnumClipboardFormats(win32Format); - } - - // if no converter then we don't recognize any formats - if (converter == NULL) { - return CString(); - } - - // get a handle to the clipboard data - HANDLE win32Data = GetClipboardData(converter->getWin32Format()); - if (win32Data == NULL) { - return CString(); - } - - // convert - return converter->toIClipboard(win32Data); -} - -void -CMSWindowsClipboard::clearConverters() -{ - for (ConverterList::iterator index = m_converters.begin(); - index != m_converters.end(); ++index) { - delete *index; - } - m_converters.clear(); -} - -bool -CMSWindowsClipboard::isOwnedBySynergy() -{ - // create ownership format if we haven't yet - if (s_ownershipFormat == 0) { - s_ownershipFormat = RegisterClipboardFormat(TEXT("SynergyOwnership")); - } - return (IsClipboardFormatAvailable(getOwnershipFormat()) != 0); -} - -UINT -CMSWindowsClipboard::getOwnershipFormat() -{ - // create ownership format if we haven't yet - if (s_ownershipFormat == 0) { - s_ownershipFormat = RegisterClipboardFormat(TEXT("SynergyOwnership")); - } - - // return the format - return s_ownershipFormat; -} diff --git a/lib/platform/CMSWindowsClipboard.h b/lib/platform/CMSWindowsClipboard.h deleted file mode 100644 index e9b59fb9..00000000 --- a/lib/platform/CMSWindowsClipboard.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CMSWINDOWSCLIPBOARD_H -#define CMSWINDOWSCLIPBOARD_H - -#include "IClipboard.h" -#include "stdvector.h" -#define WIN32_LEAN_AND_MEAN -#include - -class IMSWindowsClipboardConverter; - -//! Microsoft windows clipboard implementation -class CMSWindowsClipboard : public IClipboard { -public: - CMSWindowsClipboard(HWND window); - virtual ~CMSWindowsClipboard(); - - //! Empty clipboard without ownership - /*! - Take ownership of the clipboard and clear all data from it. - This must be called between a successful open() and close(). - Return false if the clipboard ownership could not be taken; - the clipboard should not be emptied in this case. Unlike - empty(), isOwnedBySynergy() will return false when emptied - this way. This is useful when synergy wants to put data on - clipboard but pretend (to itself) that some other app did it. - When using empty(), synergy assumes the data came from the - server and doesn't need to be sent back. emptyUnowned() - makes synergy send the data to the server. - */ - bool emptyUnowned(); - - //! Test if clipboard is owned by synergy - static bool isOwnedBySynergy(); - - // IClipboard overrides - virtual bool empty(); - virtual void add(EFormat, const CString& data); - virtual bool open(Time) const; - virtual void close() const; - virtual Time getTime() const; - virtual bool has(EFormat) const; - virtual CString get(EFormat) const; - -private: - void clearConverters(); - - UINT convertFormatToWin32(EFormat) const; - HANDLE convertTextToWin32(const CString& data) const; - CString convertTextFromWin32(HANDLE) const; - - static UINT getOwnershipFormat(); - -private: - typedef std::vector ConverterList; - - HWND m_window; - mutable Time m_time; - ConverterList m_converters; - static UINT s_ownershipFormat; -}; - -//! Clipboard format converter interface -/*! -This interface defines the methods common to all win32 clipboard format -converters. -*/ -class IMSWindowsClipboardConverter : public IInterface { -public: - // accessors - - // return the clipboard format this object converts from/to - virtual IClipboard::EFormat - getFormat() const = 0; - - // return the atom representing the win32 clipboard format that - // this object converts from/to - virtual UINT getWin32Format() const = 0; - - // convert from the IClipboard format to the win32 clipboard format. - // the input data must be in the IClipboard format returned by - // getFormat(). the return data will be in the win32 clipboard - // format returned by getWin32Format(), allocated by GlobalAlloc(). - virtual HANDLE fromIClipboard(const CString&) const = 0; - - // convert from the win32 clipboard format to the IClipboard format - // (i.e., the reverse of fromIClipboard()). - virtual CString toIClipboard(HANDLE data) const = 0; -}; - -#endif diff --git a/lib/platform/CMSWindowsClipboardAnyTextConverter.cpp b/lib/platform/CMSWindowsClipboardAnyTextConverter.cpp deleted file mode 100644 index 730f3424..00000000 --- a/lib/platform/CMSWindowsClipboardAnyTextConverter.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CMSWindowsClipboardAnyTextConverter.h" - -// -// CMSWindowsClipboardAnyTextConverter -// - -CMSWindowsClipboardAnyTextConverter::CMSWindowsClipboardAnyTextConverter() -{ - // do nothing -} - -CMSWindowsClipboardAnyTextConverter::~CMSWindowsClipboardAnyTextConverter() -{ - // do nothing -} - -IClipboard::EFormat -CMSWindowsClipboardAnyTextConverter::getFormat() const -{ - return IClipboard::kText; -} - -HANDLE -CMSWindowsClipboardAnyTextConverter::fromIClipboard(const CString& data) const -{ - // convert linefeeds and then convert to desired encoding - CString text = doFromIClipboard(convertLinefeedToWin32(data)); - UInt32 size = text.size(); - - // copy to memory handle - HGLOBAL gData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, size); - if (gData != NULL) { - // get a pointer to the allocated memory - char* dst = (char*)GlobalLock(gData); - if (dst != NULL) { - memcpy(dst, text.data(), size); - GlobalUnlock(gData); - } - else { - GlobalFree(gData); - gData = NULL; - } - } - - return gData; -} - -CString -CMSWindowsClipboardAnyTextConverter::toIClipboard(HANDLE data) const -{ - // get datator - const char* src = (const char*)GlobalLock(data); - UInt32 srcSize = (UInt32)GlobalSize(data); - if (src == NULL || srcSize <= 1) { - return CString(); - } - - // convert text - CString text = doToIClipboard(CString(src, srcSize)); - - // release handle - GlobalUnlock(data); - - // convert newlines - return convertLinefeedToUnix(text); -} - -CString -CMSWindowsClipboardAnyTextConverter::convertLinefeedToWin32( - const CString& src) const -{ - // note -- we assume src is a valid UTF-8 string - - // count newlines in string - UInt32 numNewlines = 0; - UInt32 n = src.size(); - for (const char* scan = src.c_str(); n > 0; ++scan, --n) { - if (*scan == '\n') { - ++numNewlines; - } - } - if (numNewlines == 0) { - return src; - } - - // allocate new string - CString dst; - dst.reserve(src.size() + numNewlines); - - // copy string, converting newlines - n = src.size(); - for (const char* scan = src.c_str(); n > 0; ++scan, --n) { - if (scan[0] == '\n') { - dst += '\r'; - } - dst += scan[0]; - } - - return dst; -} - -CString -CMSWindowsClipboardAnyTextConverter::convertLinefeedToUnix( - const CString& src) const -{ - // count newlines in string - UInt32 numNewlines = 0; - UInt32 n = src.size(); - for (const char* scan = src.c_str(); n > 0; ++scan, --n) { - if (scan[0] == '\r' && scan[1] == '\n') { - ++numNewlines; - } - } - if (numNewlines == 0) { - return src; - } - - // allocate new string - CString dst; - dst.reserve(src.size()); - - // copy string, converting newlines - n = src.size(); - for (const char* scan = src.c_str(); n > 0; ++scan, --n) { - if (scan[0] != '\r' || scan[1] != '\n') { - dst += scan[0]; - } - } - - return dst; -} diff --git a/lib/platform/CMSWindowsClipboardAnyTextConverter.h b/lib/platform/CMSWindowsClipboardAnyTextConverter.h deleted file mode 100644 index 254099f2..00000000 --- a/lib/platform/CMSWindowsClipboardAnyTextConverter.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CMSWINDOWSCLIPBOARDANYTEXTCONVERTER_H -#define CMSWINDOWSCLIPBOARDANYTEXTCONVERTER_H - -#include "CMSWindowsClipboard.h" - -//! Convert to/from some text encoding -class CMSWindowsClipboardAnyTextConverter : - public IMSWindowsClipboardConverter { -public: - CMSWindowsClipboardAnyTextConverter(); - virtual ~CMSWindowsClipboardAnyTextConverter(); - - // IMSWindowsClipboardConverter overrides - virtual IClipboard::EFormat - getFormat() const; - virtual UINT getWin32Format() const = 0; - virtual HANDLE fromIClipboard(const CString&) const; - virtual CString toIClipboard(HANDLE) const; - -protected: - //! Convert from IClipboard format - /*! - Do UTF-8 conversion only. Memory handle allocation and - linefeed conversion is done by this class. doFromIClipboard() - must include the nul terminator in the returned string (not - including the CString's nul terminator). - */ - virtual CString doFromIClipboard(const CString&) const = 0; - - //! Convert to IClipboard format - /*! - Do UTF-8 conversion only. Memory handle allocation and - linefeed conversion is done by this class. - */ - virtual CString doToIClipboard(const CString&) const = 0; - -private: - CString convertLinefeedToWin32(const CString&) const; - CString convertLinefeedToUnix(const CString&) const; -}; - -#endif diff --git a/lib/platform/CMSWindowsClipboardBitmapConverter.cpp b/lib/platform/CMSWindowsClipboardBitmapConverter.cpp deleted file mode 100644 index a17c66cf..00000000 --- a/lib/platform/CMSWindowsClipboardBitmapConverter.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CMSWindowsClipboardBitmapConverter.h" -#include "CLog.h" - -// -// CMSWindowsClipboardBitmapConverter -// - -CMSWindowsClipboardBitmapConverter::CMSWindowsClipboardBitmapConverter() -{ - // do nothing -} - -CMSWindowsClipboardBitmapConverter::~CMSWindowsClipboardBitmapConverter() -{ - // do nothing -} - -IClipboard::EFormat -CMSWindowsClipboardBitmapConverter::getFormat() const -{ - return IClipboard::kBitmap; -} - -UINT -CMSWindowsClipboardBitmapConverter::getWin32Format() const -{ - return CF_DIB; -} - -HANDLE -CMSWindowsClipboardBitmapConverter::fromIClipboard(const CString& data) const -{ - // copy to memory handle - HGLOBAL gData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, data.size()); - if (gData != NULL) { - // get a pointer to the allocated memory - char* dst = (char*)GlobalLock(gData); - if (dst != NULL) { - memcpy(dst, data.data(), data.size()); - GlobalUnlock(gData); - } - else { - GlobalFree(gData); - gData = NULL; - } - } - - return gData; -} - -CString -CMSWindowsClipboardBitmapConverter::toIClipboard(HANDLE data) const -{ - // get datator - const char* src = (const char*)GlobalLock(data); - if (src == NULL) { - return CString(); - } - UInt32 srcSize = (UInt32)GlobalSize(data); - - // check image type - const BITMAPINFO* bitmap = reinterpret_cast(src); - LOG((CLOG_INFO "bitmap: %dx%d %d", bitmap->bmiHeader.biWidth, bitmap->bmiHeader.biHeight, (int)bitmap->bmiHeader.biBitCount)); - if (bitmap->bmiHeader.biPlanes == 1 && - (bitmap->bmiHeader.biBitCount == 24 || - bitmap->bmiHeader.biBitCount == 32) && - bitmap->bmiHeader.biCompression == BI_RGB) { - // already in canonical form - CString image(src, srcSize); - GlobalUnlock(data); - return image; - } - - // create a destination DIB section - LOG((CLOG_INFO "convert image from: depth=%d comp=%d", bitmap->bmiHeader.biBitCount, bitmap->bmiHeader.biCompression)); - void* raw; - BITMAPINFOHEADER info; - LONG w = bitmap->bmiHeader.biWidth; - LONG h = bitmap->bmiHeader.biHeight; - info.biSize = sizeof(BITMAPINFOHEADER); - info.biWidth = w; - info.biHeight = h; - info.biPlanes = 1; - info.biBitCount = 32; - info.biCompression = BI_RGB; - info.biSizeImage = 0; - info.biXPelsPerMeter = 1000; - info.biYPelsPerMeter = 1000; - info.biClrUsed = 0; - info.biClrImportant = 0; - HDC dc = GetDC(NULL); - HBITMAP dst = CreateDIBSection(dc, (BITMAPINFO*)&info, - DIB_RGB_COLORS, &raw, NULL, 0); - - // find the start of the pixel data - const char* srcBits = (const char*)bitmap + bitmap->bmiHeader.biSize; - if (bitmap->bmiHeader.biBitCount >= 16) { - if (bitmap->bmiHeader.biCompression == BI_BITFIELDS && - (bitmap->bmiHeader.biBitCount == 16 || - bitmap->bmiHeader.biBitCount == 32)) { - srcBits += 3 * sizeof(DWORD); - } - } - else if (bitmap->bmiHeader.biClrUsed != 0) { - srcBits += bitmap->bmiHeader.biClrUsed * sizeof(RGBQUAD); - } - else { - srcBits += (1 << bitmap->bmiHeader.biBitCount) * sizeof(RGBQUAD); - } - - // copy source image to destination image - HDC dstDC = CreateCompatibleDC(dc); - HGDIOBJ oldBitmap = SelectObject(dstDC, dst); - SetDIBitsToDevice(dstDC, 0, 0, w, h, 0, 0, 0, h, - srcBits, bitmap, DIB_RGB_COLORS); - SelectObject(dstDC, oldBitmap); - DeleteDC(dstDC); - GdiFlush(); - - // extract data - CString image((const char*)&info, info.biSize); - image.append((const char*)raw, 4 * w * h); - - // clean up GDI - DeleteObject(dst); - ReleaseDC(NULL, dc); - - // release handle - GlobalUnlock(data); - - return image; -} diff --git a/lib/platform/CMSWindowsClipboardBitmapConverter.h b/lib/platform/CMSWindowsClipboardBitmapConverter.h deleted file mode 100644 index 6ddd7ce8..00000000 --- a/lib/platform/CMSWindowsClipboardBitmapConverter.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CMSWINDOWSCLIPBOARDBITMAPCONVERTER_H -#define CMSWINDOWSCLIPBOARDBITMAPCONVERTER_H - -#include "CMSWindowsClipboard.h" - -//! Convert to/from some text encoding -class CMSWindowsClipboardBitmapConverter : - public IMSWindowsClipboardConverter { -public: - CMSWindowsClipboardBitmapConverter(); - virtual ~CMSWindowsClipboardBitmapConverter(); - - // IMSWindowsClipboardConverter overrides - virtual IClipboard::EFormat - getFormat() const; - virtual UINT getWin32Format() const; - virtual HANDLE fromIClipboard(const CString&) const; - virtual CString toIClipboard(HANDLE) const; -}; - -#endif diff --git a/lib/platform/CMSWindowsClipboardHTMLConverter.cpp b/lib/platform/CMSWindowsClipboardHTMLConverter.cpp deleted file mode 100644 index a64a0f78..00000000 --- a/lib/platform/CMSWindowsClipboardHTMLConverter.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CMSWindowsClipboardHTMLConverter.h" -#include "CStringUtil.h" - -// -// CMSWindowsClipboardHTMLConverter -// - -CMSWindowsClipboardHTMLConverter::CMSWindowsClipboardHTMLConverter() -{ - m_format = RegisterClipboardFormat("HTML Format"); -} - -CMSWindowsClipboardHTMLConverter::~CMSWindowsClipboardHTMLConverter() -{ - // do nothing -} - -IClipboard::EFormat -CMSWindowsClipboardHTMLConverter::getFormat() const -{ - return IClipboard::kHTML; -} - -UINT -CMSWindowsClipboardHTMLConverter::getWin32Format() const -{ - return m_format; -} - -CString -CMSWindowsClipboardHTMLConverter::doFromIClipboard(const CString& data) const -{ - // prepare to CF_HTML format prefix and suffix - CString prefix("Version:0.9\nStartHTML:-1\nEndHTML:-1\n" - "StartFragment:XXXXXXXXXX\nEndFragment:YYYYYYYYYY\n" - ""); - CString suffix("\n"); - UInt32 start = prefix.size(); - UInt32 end = start + data.size(); - prefix.replace(prefix.find("XXXXXXXXXX"), 10, - CStringUtil::print("%010u", start)); - prefix.replace(prefix.find("YYYYYYYYYY"), 10, - CStringUtil::print("%010u", end)); - - // concatenate - prefix += data; - prefix += suffix; - return prefix; -} - -CString -CMSWindowsClipboardHTMLConverter::doToIClipboard(const CString& data) const -{ - // get fragment start/end args - CString startArg = findArg(data, "StartFragment"); - CString endArg = findArg(data, "EndFragment"); - if (startArg.empty() || endArg.empty()) { - return CString(); - } - - // convert args to integers - SInt32 start = (SInt32)atoi(startArg.c_str()); - SInt32 end = (SInt32)atoi(endArg.c_str()); - if (start <= 0 || end <= 0 || start >= end) { - return CString(); - } - - // extract the fragment - return data.substr(start, end - start); -} - -CString -CMSWindowsClipboardHTMLConverter::findArg( - const CString& data, const CString& name) const -{ - CString::size_type i = data.find(name); - if (i == CString::npos) { - return CString(); - } - i = data.find_first_of(":\r\n", i); - if (i == CString::npos || data[i] != ':') { - return CString(); - } - i = data.find_first_of("0123456789\r\n", i + 1); - if (i == CString::npos || data[i] == '\r' || data[i] == '\n') { - return CString(); - } - CString::size_type j = data.find_first_not_of("0123456789", i); - if (j == CString::npos) { - j = data.size(); - } - return data.substr(i, j - i); -} diff --git a/lib/platform/CMSWindowsClipboardHTMLConverter.h b/lib/platform/CMSWindowsClipboardHTMLConverter.h deleted file mode 100644 index 02cd8f88..00000000 --- a/lib/platform/CMSWindowsClipboardHTMLConverter.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CMSWINDOWSCLIPBOARDHTMLCONVERTER_H -#define CMSWINDOWSCLIPBOARDHTMLCONVERTER_H - -#include "CMSWindowsClipboardAnyTextConverter.h" - -//! Convert to/from HTML encoding -class CMSWindowsClipboardHTMLConverter : - public CMSWindowsClipboardAnyTextConverter { -public: - CMSWindowsClipboardHTMLConverter(); - virtual ~CMSWindowsClipboardHTMLConverter(); - - // IMSWindowsClipboardConverter overrides - virtual IClipboard::EFormat - getFormat() const; - virtual UINT getWin32Format() const; - -protected: - // CMSWindowsClipboardAnyTextConverter overrides - virtual CString doFromIClipboard(const CString&) const; - virtual CString doToIClipboard(const CString&) const; - -private: - CString findArg(const CString& data, const CString& name) const; - -private: - UINT m_format; -}; - -#endif diff --git a/lib/platform/CMSWindowsClipboardTextConverter.cpp b/lib/platform/CMSWindowsClipboardTextConverter.cpp deleted file mode 100644 index a735094a..00000000 --- a/lib/platform/CMSWindowsClipboardTextConverter.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CMSWindowsClipboardTextConverter.h" -#include "CUnicode.h" - -// -// CMSWindowsClipboardTextConverter -// - -CMSWindowsClipboardTextConverter::CMSWindowsClipboardTextConverter() -{ - // do nothing -} - -CMSWindowsClipboardTextConverter::~CMSWindowsClipboardTextConverter() -{ - // do nothing -} - -UINT -CMSWindowsClipboardTextConverter::getWin32Format() const -{ - return CF_TEXT; -} - -CString -CMSWindowsClipboardTextConverter::doFromIClipboard(const CString& data) const -{ - // convert and add nul terminator - return CUnicode::UTF8ToText(data) += '\0'; -} - -CString -CMSWindowsClipboardTextConverter::doToIClipboard(const CString& data) const -{ - // convert and truncate at first nul terminator - CString dst = CUnicode::textToUTF8(data); - CString::size_type n = dst.find('\0'); - if (n != CString::npos) { - dst.erase(n); - } - return dst; -} diff --git a/lib/platform/CMSWindowsClipboardTextConverter.h b/lib/platform/CMSWindowsClipboardTextConverter.h deleted file mode 100644 index 6f00d475..00000000 --- a/lib/platform/CMSWindowsClipboardTextConverter.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CMSWINDOWSCLIPBOARDTEXTCONVERTER_H -#define CMSWINDOWSCLIPBOARDTEXTCONVERTER_H - -#include "CMSWindowsClipboardAnyTextConverter.h" - -//! Convert to/from locale text encoding -class CMSWindowsClipboardTextConverter : - public CMSWindowsClipboardAnyTextConverter { -public: - CMSWindowsClipboardTextConverter(); - virtual ~CMSWindowsClipboardTextConverter(); - - // IMSWindowsClipboardConverter overrides - virtual UINT getWin32Format() const; - -protected: - // CMSWindowsClipboardAnyTextConverter overrides - virtual CString doFromIClipboard(const CString&) const; - virtual CString doToIClipboard(const CString&) const; -}; - -#endif diff --git a/lib/platform/CMSWindowsClipboardUTF16Converter.cpp b/lib/platform/CMSWindowsClipboardUTF16Converter.cpp deleted file mode 100644 index 81b85c60..00000000 --- a/lib/platform/CMSWindowsClipboardUTF16Converter.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CMSWindowsClipboardUTF16Converter.h" -#include "CUnicode.h" - -// -// CMSWindowsClipboardUTF16Converter -// - -CMSWindowsClipboardUTF16Converter::CMSWindowsClipboardUTF16Converter() -{ - // do nothing -} - -CMSWindowsClipboardUTF16Converter::~CMSWindowsClipboardUTF16Converter() -{ - // do nothing -} - -UINT -CMSWindowsClipboardUTF16Converter::getWin32Format() const -{ - return CF_UNICODETEXT; -} - -CString -CMSWindowsClipboardUTF16Converter::doFromIClipboard(const CString& data) const -{ - // convert and add nul terminator - return CUnicode::UTF8ToUTF16(data).append(sizeof(wchar_t), 0); -} - -CString -CMSWindowsClipboardUTF16Converter::doToIClipboard(const CString& data) const -{ - // convert and strip nul terminator - CString dst = CUnicode::UTF16ToUTF8(data); - CString::size_type n = dst.find('\0'); - if (n != CString::npos) { - dst.erase(n); - } - return dst; -} diff --git a/lib/platform/CMSWindowsClipboardUTF16Converter.h b/lib/platform/CMSWindowsClipboardUTF16Converter.h deleted file mode 100644 index 51f477fa..00000000 --- a/lib/platform/CMSWindowsClipboardUTF16Converter.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CMSWINDOWSCLIPBOARDUTF16CONVERTER_H -#define CMSWINDOWSCLIPBOARDUTF16CONVERTER_H - -#include "CMSWindowsClipboardAnyTextConverter.h" - -//! Convert to/from UTF-16 encoding -class CMSWindowsClipboardUTF16Converter : - public CMSWindowsClipboardAnyTextConverter { -public: - CMSWindowsClipboardUTF16Converter(); - virtual ~CMSWindowsClipboardUTF16Converter(); - - // IMSWindowsClipboardConverter overrides - virtual UINT getWin32Format() const; - -protected: - // CMSWindowsClipboardAnyTextConverter overrides - virtual CString doFromIClipboard(const CString&) const; - virtual CString doToIClipboard(const CString&) const; -}; - -#endif diff --git a/lib/platform/CMSWindowsDesks.cpp b/lib/platform/CMSWindowsDesks.cpp deleted file mode 100644 index 4a1c4474..00000000 --- a/lib/platform/CMSWindowsDesks.cpp +++ /dev/null @@ -1,1033 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CMSWindowsDesks.h" -#include "CMSWindowsScreen.h" -#include "CSynergyHook.h" -#include "IScreenSaver.h" -#include "XScreen.h" -#include "CLock.h" -#include "CThread.h" -#include "CLog.h" -#include "IEventQueue.h" -#include "IJob.h" -#include "TMethodEventJob.h" -#include "TMethodJob.h" -#include "CArchMiscWindows.h" -#include - -// these are only defined when WINVER >= 0x0500 -#if !defined(SPI_GETMOUSESPEED) -#define SPI_GETMOUSESPEED 112 -#endif -#if !defined(SPI_SETMOUSESPEED) -#define SPI_SETMOUSESPEED 113 -#endif -#if !defined(SPI_GETSCREENSAVERRUNNING) -#define SPI_GETSCREENSAVERRUNNING 114 -#endif - -// X button stuff -#if !defined(WM_XBUTTONDOWN) -#define WM_XBUTTONDOWN 0x020B -#define WM_XBUTTONUP 0x020C -#define WM_XBUTTONDBLCLK 0x020D -#define WM_NCXBUTTONDOWN 0x00AB -#define WM_NCXBUTTONUP 0x00AC -#define WM_NCXBUTTONDBLCLK 0x00AD -#define MOUSEEVENTF_XDOWN 0x0080 -#define MOUSEEVENTF_XUP 0x0100 -#define XBUTTON1 0x0001 -#define XBUTTON2 0x0002 -#endif -#if !defined(VK_XBUTTON1) -#define VK_XBUTTON1 0x05 -#define VK_XBUTTON2 0x06 -#endif - -// ; -#define SYNERGY_MSG_SWITCH SYNERGY_HOOK_LAST_MSG + 1 -// ; -#define SYNERGY_MSG_ENTER SYNERGY_HOOK_LAST_MSG + 2 -// ; -#define SYNERGY_MSG_LEAVE SYNERGY_HOOK_LAST_MSG + 3 -// wParam = flags, HIBYTE(lParam) = virtual key, LOBYTE(lParam) = scan code -#define SYNERGY_MSG_FAKE_KEY SYNERGY_HOOK_LAST_MSG + 4 - // flags, XBUTTON id -#define SYNERGY_MSG_FAKE_BUTTON SYNERGY_HOOK_LAST_MSG + 5 -// x; y -#define SYNERGY_MSG_FAKE_MOVE SYNERGY_HOOK_LAST_MSG + 6 -// xDelta; yDelta -#define SYNERGY_MSG_FAKE_WHEEL SYNERGY_HOOK_LAST_MSG + 7 -// POINT*; -#define SYNERGY_MSG_CURSOR_POS SYNERGY_HOOK_LAST_MSG + 8 -// IKeyState*; -#define SYNERGY_MSG_SYNC_KEYS SYNERGY_HOOK_LAST_MSG + 9 -// install; -#define SYNERGY_MSG_SCREENSAVER SYNERGY_HOOK_LAST_MSG + 10 -// dx; dy -#define SYNERGY_MSG_FAKE_REL_MOVE SYNERGY_HOOK_LAST_MSG + 11 -// enable; -#define SYNERGY_MSG_FAKE_INPUT SYNERGY_HOOK_LAST_MSG + 12 - -// -// CMSWindowsDesks -// - -CMSWindowsDesks::CMSWindowsDesks( - bool isPrimary, HINSTANCE hookLibrary, - const IScreenSaver* screensaver, IJob* updateKeys) : - m_isPrimary(isPrimary), - m_is95Family(CArchMiscWindows::isWindows95Family()), - m_isModernFamily(CArchMiscWindows::isWindowsModern()), - m_isOnScreen(m_isPrimary), - m_x(0), m_y(0), - m_w(0), m_h(0), - m_xCenter(0), m_yCenter(0), - m_multimon(false), - m_timer(NULL), - m_screensaver(screensaver), - m_screensaverNotify(false), - m_activeDesk(NULL), - m_activeDeskName(), - m_mutex(), - m_deskReady(&m_mutex, false), - m_updateKeys(updateKeys) -{ - queryHookLibrary(hookLibrary); - m_cursor = createBlankCursor(); - m_deskClass = createDeskWindowClass(m_isPrimary); - m_keyLayout = GetKeyboardLayout(GetCurrentThreadId()); - resetOptions(); -} - -CMSWindowsDesks::~CMSWindowsDesks() -{ - disable(); - destroyClass(m_deskClass); - destroyCursor(m_cursor); - delete m_updateKeys; -} - -void -CMSWindowsDesks::enable() -{ - m_threadID = GetCurrentThreadId(); - - // set the active desk and (re)install the hooks - checkDesk(); - - // install the desk timer. this timer periodically checks - // which desk is active and reinstalls the hooks as necessary. - // we wouldn't need this if windows notified us of a desktop - // change but as far as i can tell it doesn't. - m_timer = EVENTQUEUE->newTimer(0.2, NULL); - EVENTQUEUE->adoptHandler(CEvent::kTimer, m_timer, - new TMethodEventJob( - this, &CMSWindowsDesks::handleCheckDesk)); - - updateKeys(); -} - -void -CMSWindowsDesks::disable() -{ - // remove timer - if (m_timer != NULL) { - EVENTQUEUE->removeHandler(CEvent::kTimer, m_timer); - EVENTQUEUE->deleteTimer(m_timer); - m_timer = NULL; - } - - // destroy desks - removeDesks(); - - m_isOnScreen = m_isPrimary; -} - -void -CMSWindowsDesks::enter() -{ - sendMessage(SYNERGY_MSG_ENTER, 0, 0); -} - -void -CMSWindowsDesks::leave(HKL keyLayout) -{ - sendMessage(SYNERGY_MSG_LEAVE, (WPARAM)keyLayout, 0); -} - -void -CMSWindowsDesks::resetOptions() -{ - m_leaveForegroundOption = false; -} - -void -CMSWindowsDesks::setOptions(const COptionsList& options) -{ - for (UInt32 i = 0, n = options.size(); i < n; i += 2) { - if (options[i] == kOptionWin32KeepForeground) { - m_leaveForegroundOption = (options[i + 1] != 0); - LOG((CLOG_DEBUG1 "%s the foreground window", m_leaveForegroundOption ? "Don\'t grab" : "Grab")); - } - } -} - -void -CMSWindowsDesks::updateKeys() -{ - sendMessage(SYNERGY_MSG_SYNC_KEYS, 0, 0); -} - -void -CMSWindowsDesks::setShape(SInt32 x, SInt32 y, - SInt32 width, SInt32 height, - SInt32 xCenter, SInt32 yCenter, bool isMultimon) -{ - m_x = x; - m_y = y; - m_w = width; - m_h = height; - m_xCenter = xCenter; - m_yCenter = yCenter; - m_multimon = isMultimon; -} - -void -CMSWindowsDesks::installScreensaverHooks(bool install) -{ - if (m_isPrimary && m_screensaverNotify != install) { - m_screensaverNotify = install; - sendMessage(SYNERGY_MSG_SCREENSAVER, install, 0); - } -} - -void -CMSWindowsDesks::fakeInputBegin() -{ - sendMessage(SYNERGY_MSG_FAKE_INPUT, 1, 0); -} - -void -CMSWindowsDesks::fakeInputEnd() -{ - sendMessage(SYNERGY_MSG_FAKE_INPUT, 0, 0); -} - -void -CMSWindowsDesks::getCursorPos(SInt32& x, SInt32& y) const -{ - POINT pos; - sendMessage(SYNERGY_MSG_CURSOR_POS, reinterpret_cast(&pos), 0); - x = pos.x; - y = pos.y; -} - -void -CMSWindowsDesks::fakeKeyEvent( - KeyButton button, UINT virtualKey, - bool press, bool /*isAutoRepeat*/) const -{ - // win 95 family doesn't understand handed modifier virtual keys - if (m_is95Family) { - switch (virtualKey) { - case VK_LSHIFT: - case VK_RSHIFT: - virtualKey = VK_SHIFT; - break; - - case VK_LCONTROL: - case VK_RCONTROL: - virtualKey = VK_CONTROL; - break; - - case VK_LMENU: - case VK_RMENU: - virtualKey = VK_MENU; - break; - } - } - - // synthesize event - DWORD flags = 0; - if (((button & 0x100u) != 0)) { - flags |= KEYEVENTF_EXTENDEDKEY; - } - if (!press) { - flags |= KEYEVENTF_KEYUP; - } - sendMessage(SYNERGY_MSG_FAKE_KEY, flags, - MAKEWORD(static_cast(button & 0xffu), - static_cast(virtualKey & 0xffu))); -} - -void -CMSWindowsDesks::fakeMouseButton(ButtonID button, bool press) const -{ - // the system will swap the meaning of left/right for us if - // the user has configured a left-handed mouse but we don't - // want it to swap since we want the handedness of the - // server's mouse. so pre-swap for a left-handed mouse. - if (GetSystemMetrics(SM_SWAPBUTTON)) { - switch (button) { - case kButtonLeft: - button = kButtonRight; - break; - - case kButtonRight: - button = kButtonLeft; - break; - } - } - - // map button id to button flag and button data - DWORD data = 0; - DWORD flags; - switch (button) { - case kButtonLeft: - flags = press ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP; - break; - - case kButtonMiddle: - flags = press ? MOUSEEVENTF_MIDDLEDOWN : MOUSEEVENTF_MIDDLEUP; - break; - - case kButtonRight: - flags = press ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP; - break; - - case kButtonExtra0 + 0: - data = XBUTTON1; - flags = press ? MOUSEEVENTF_XDOWN : MOUSEEVENTF_XUP; - break; - - case kButtonExtra0 + 1: - data = XBUTTON2; - flags = press ? MOUSEEVENTF_XDOWN : MOUSEEVENTF_XUP; - break; - - default: - return; - } - - // do it - sendMessage(SYNERGY_MSG_FAKE_BUTTON, flags, data); -} - -void -CMSWindowsDesks::fakeMouseMove(SInt32 x, SInt32 y) const -{ - sendMessage(SYNERGY_MSG_FAKE_MOVE, - static_cast(x), - static_cast(y)); -} - -void -CMSWindowsDesks::fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const -{ - sendMessage(SYNERGY_MSG_FAKE_REL_MOVE, - static_cast(dx), - static_cast(dy)); -} - -void -CMSWindowsDesks::fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const -{ - sendMessage(SYNERGY_MSG_FAKE_WHEEL, xDelta, yDelta); -} - -void -CMSWindowsDesks::sendMessage(UINT msg, WPARAM wParam, LPARAM lParam) const -{ - if (m_activeDesk != NULL && m_activeDesk->m_window != NULL) { - PostThreadMessage(m_activeDesk->m_threadID, msg, wParam, lParam); - waitForDesk(); - } -} - -void -CMSWindowsDesks::queryHookLibrary(HINSTANCE hookLibrary) -{ - // look up functions - if (m_isPrimary) { - m_install = (InstallFunc)GetProcAddress(hookLibrary, "install"); - m_uninstall = (UninstallFunc)GetProcAddress(hookLibrary, "uninstall"); - m_installScreensaver = - (InstallScreenSaverFunc)GetProcAddress( - hookLibrary, "installScreenSaver"); - m_uninstallScreensaver = - (UninstallScreenSaverFunc)GetProcAddress( - hookLibrary, "uninstallScreenSaver"); - if (m_install == NULL || - m_uninstall == NULL || - m_installScreensaver == NULL || - m_uninstallScreensaver == NULL) { - LOG((CLOG_ERR "Invalid hook library")); - throw XScreenOpenFailure(); - } - } - else { - m_install = NULL; - m_uninstall = NULL; - m_installScreensaver = NULL; - m_uninstallScreensaver = NULL; - } -} - -HCURSOR -CMSWindowsDesks::createBlankCursor() const -{ - // create a transparent cursor - int cw = GetSystemMetrics(SM_CXCURSOR); - int ch = GetSystemMetrics(SM_CYCURSOR); - UInt8* cursorAND = new UInt8[ch * ((cw + 31) >> 2)]; - UInt8* cursorXOR = new UInt8[ch * ((cw + 31) >> 2)]; - memset(cursorAND, 0xff, ch * ((cw + 31) >> 2)); - memset(cursorXOR, 0x00, ch * ((cw + 31) >> 2)); - HCURSOR c = CreateCursor(CMSWindowsScreen::getInstance(), - 0, 0, cw, ch, cursorAND, cursorXOR); - delete[] cursorXOR; - delete[] cursorAND; - return c; -} - -void -CMSWindowsDesks::destroyCursor(HCURSOR cursor) const -{ - if (cursor != NULL) { - DestroyCursor(cursor); - } -} - -ATOM -CMSWindowsDesks::createDeskWindowClass(bool isPrimary) const -{ - WNDCLASSEX classInfo; - classInfo.cbSize = sizeof(classInfo); - classInfo.style = CS_DBLCLKS | CS_NOCLOSE; - classInfo.lpfnWndProc = isPrimary ? - &CMSWindowsDesks::primaryDeskProc : - &CMSWindowsDesks::secondaryDeskProc; - classInfo.cbClsExtra = 0; - classInfo.cbWndExtra = 0; - classInfo.hInstance = CMSWindowsScreen::getInstance(); - classInfo.hIcon = NULL; - classInfo.hCursor = m_cursor; - classInfo.hbrBackground = NULL; - classInfo.lpszMenuName = NULL; - classInfo.lpszClassName = "SynergyDesk"; - classInfo.hIconSm = NULL; - return RegisterClassEx(&classInfo); -} - -void -CMSWindowsDesks::destroyClass(ATOM windowClass) const -{ - if (windowClass != 0) { - UnregisterClass(reinterpret_cast(windowClass), - CMSWindowsScreen::getInstance()); - } -} - -HWND -CMSWindowsDesks::createWindow(ATOM windowClass, const char* name) const -{ - HWND window = CreateWindowEx(WS_EX_TOPMOST | - WS_EX_TRANSPARENT | - WS_EX_TOOLWINDOW, - reinterpret_cast(windowClass), - name, - WS_POPUP, - 0, 0, 1, 1, - NULL, NULL, - CMSWindowsScreen::getInstance(), - NULL); - if (window == NULL) { - LOG((CLOG_ERR "failed to create window: %d", GetLastError())); - throw XScreenOpenFailure(); - } - return window; -} - -void -CMSWindowsDesks::destroyWindow(HWND hwnd) const -{ - if (hwnd != NULL) { - DestroyWindow(hwnd); - } -} - -LRESULT CALLBACK -CMSWindowsDesks::primaryDeskProc( - HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - return DefWindowProc(hwnd, msg, wParam, lParam); -} - -LRESULT CALLBACK -CMSWindowsDesks::secondaryDeskProc( - HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - // would like to detect any local user input and hide the hider - // window but for now we just detect mouse motion. - bool hide = false; - switch (msg) { - case WM_MOUSEMOVE: - if (LOWORD(lParam) != 0 || HIWORD(lParam) != 0) { - hide = true; - } - break; - } - - if (hide && IsWindowVisible(hwnd)) { - ReleaseCapture(); - SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0, - SWP_NOMOVE | SWP_NOSIZE | - SWP_NOACTIVATE | SWP_HIDEWINDOW); - } - - return DefWindowProc(hwnd, msg, wParam, lParam); -} - -void -CMSWindowsDesks::deskMouseMove(SInt32 x, SInt32 y) const -{ - // motion is simple (i.e. it's on the primary monitor) if there - // is only one monitor. it's also simple if we're not on the - // windows 95 family since those platforms don't have a broken - // mouse_event() function (see the comment below). - bool simple = (!m_multimon || !m_is95Family); - if (!simple) { - // also simple if motion is within the primary monitor - simple = (x >= 0 && x < GetSystemMetrics(SM_CXSCREEN) && - y >= 0 && y < GetSystemMetrics(SM_CYSCREEN)); - } - - // move the mouse directly to target position if motion is simple - if (simple) { - // when using absolute positioning with mouse_event(), - // the normalized device coordinates range over only - // the primary screen. - SInt32 w = GetSystemMetrics(SM_CXSCREEN); - SInt32 h = GetSystemMetrics(SM_CYSCREEN); - mouse_event(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE, - (DWORD)((65535.0f * x) / (w - 1) + 0.5f), - (DWORD)((65535.0f * y) / (h - 1) + 0.5f), - 0, 0); - } - - // windows 98 and Me are broken. you cannot set the absolute - // position of the mouse except on the primary monitor but you - // can do relative moves onto any monitor. this is, in microsoft's - // words, "by design." apparently the designers of windows 2000 - // we're a little less lazy and did it right. - // - // microsoft recommends in Q193003 to absolute position the cursor - // somewhere on the primary monitor then relative move to the - // desired location. this doesn't work for us because when the - // user drags a scrollbar, a window, etc. it causes the dragged - // item to jump back and forth between the position on the primary - // monitor and the desired position. while it always ends up in - // the right place, the effect is disconcerting. - // - // instead we'll get the cursor's current position and do just a - // relative move from there to the desired position. - else { - POINT pos; - GetCursorPos(&pos); - deskMouseRelativeMove(x - pos.x, y - pos.y); - } -} - -void -CMSWindowsDesks::deskMouseRelativeMove(SInt32 dx, SInt32 dy) const -{ - // relative moves are subject to cursor acceleration which we don't - // want.so we disable acceleration, do the relative move, then - // restore acceleration. there's a slight chance we'll end up in - // the wrong place if the user moves the cursor using this system's - // mouse while simultaneously moving the mouse on the server - // system. that defeats the purpose of synergy so we'll assume - // that won't happen. even if it does, the next mouse move will - // correct the position. - - // save mouse speed & acceleration - int oldSpeed[4]; - bool accelChanged = - SystemParametersInfo(SPI_GETMOUSE,0, oldSpeed, 0) && - SystemParametersInfo(SPI_GETMOUSESPEED, 0, oldSpeed + 3, 0); - - // use 1:1 motion - if (accelChanged) { - int newSpeed[4] = { 0, 0, 0, 1 }; - accelChanged = - SystemParametersInfo(SPI_SETMOUSE, 0, newSpeed, 0) || - SystemParametersInfo(SPI_SETMOUSESPEED, 0, newSpeed + 3, 0); - } - - // move relative to mouse position - mouse_event(MOUSEEVENTF_MOVE, dx, dy, 0, 0); - - // restore mouse speed & acceleration - if (accelChanged) { - SystemParametersInfo(SPI_SETMOUSE, 0, oldSpeed, 0); - SystemParametersInfo(SPI_SETMOUSESPEED, 0, oldSpeed + 3, 0); - } -} - -void -CMSWindowsDesks::deskEnter(CDesk* desk) -{ - if (!m_isPrimary) { - ReleaseCapture(); - } - ShowCursor(TRUE); - SetWindowPos(desk->m_window, HWND_BOTTOM, 0, 0, 0, 0, - SWP_NOMOVE | SWP_NOSIZE | - SWP_NOACTIVATE | SWP_HIDEWINDOW); - - // restore the foreground window - // XXX -- this raises the window to the top of the Z-order. we - // want it to stay wherever it was to properly support X-mouse - // (mouse over activation) but i've no idea how to do that. - // the obvious workaround of using SetWindowPos() to move it back - // after being raised doesn't work. - DWORD thisThread = - GetWindowThreadProcessId(desk->m_window, NULL); - DWORD thatThread = - GetWindowThreadProcessId(desk->m_foregroundWindow, NULL); - AttachThreadInput(thatThread, thisThread, TRUE); - SetForegroundWindow(desk->m_foregroundWindow); - AttachThreadInput(thatThread, thisThread, FALSE); - EnableWindow(desk->m_window, desk->m_lowLevel ? FALSE : TRUE); - desk->m_foregroundWindow = NULL; -} - -void -CMSWindowsDesks::deskLeave(CDesk* desk, HKL keyLayout) -{ - ShowCursor(FALSE); - if (m_isPrimary) { - // map a window to hide the cursor and to use whatever keyboard - // layout we choose rather than the keyboard layout of the last - // active window. - int x, y, w, h; - if (desk->m_lowLevel) { - // with a low level hook the cursor will never budge so - // just a 1x1 window is sufficient. - x = m_xCenter; - y = m_yCenter; - w = 1; - h = 1; - } - else { - // with regular hooks the cursor will jitter as it's moved - // by the user then back to the center by us. to be sure - // we never lose it, cover all the monitors with the window. - x = m_x; - y = m_y; - w = m_w; - h = m_h; - } - SetWindowPos(desk->m_window, HWND_TOPMOST, x, y, w, h, - SWP_NOACTIVATE | SWP_SHOWWINDOW); - - // if not using low-level hooks we have to also activate the - // window to ensure we don't lose keyboard focus. - // FIXME -- see if this can be avoided. if so then always - // disable the window (see handling of SYNERGY_MSG_SWITCH). - if (!desk->m_lowLevel) { - SetActiveWindow(desk->m_window); - } - - // if using low-level hooks then disable the foreground window - // so it can't mess up any of our keyboard events. the console - // program, for example, will cause characters to be reported as - // unshifted, regardless of the shift key state. interestingly - // we do see the shift key go down and up. - // - // note that we must enable the window to activate it and we - // need to disable the window on deskEnter. - else { - desk->m_foregroundWindow = getForegroundWindow(); - if (desk->m_foregroundWindow != NULL) { - EnableWindow(desk->m_window, TRUE); - SetActiveWindow(desk->m_window); - DWORD thisThread = - GetWindowThreadProcessId(desk->m_window, NULL); - DWORD thatThread = - GetWindowThreadProcessId(desk->m_foregroundWindow, NULL); - AttachThreadInput(thatThread, thisThread, TRUE); - SetForegroundWindow(desk->m_window); - AttachThreadInput(thatThread, thisThread, FALSE); - } - } - - // switch to requested keyboard layout - ActivateKeyboardLayout(keyLayout, 0); - } - else { - // move hider window under the cursor center, raise, and show it - SetWindowPos(desk->m_window, HWND_TOPMOST, - m_xCenter, m_yCenter, 1, 1, - SWP_NOACTIVATE | SWP_SHOWWINDOW); - - // watch for mouse motion. if we see any then we hide the - // hider window so the user can use the physically attached - // mouse if desired. we'd rather not capture the mouse but - // we aren't notified when the mouse leaves our window. - SetCapture(desk->m_window); - - // warp the mouse to the cursor center - deskMouseMove(m_xCenter, m_yCenter); - } -} - -void -CMSWindowsDesks::deskThread(void* vdesk) -{ - MSG msg; - - // use given desktop for this thread - CDesk* desk = reinterpret_cast(vdesk); - desk->m_threadID = GetCurrentThreadId(); - desk->m_window = NULL; - desk->m_foregroundWindow = NULL; - if (desk->m_desk != NULL && SetThreadDesktop(desk->m_desk) != 0) { - // create a message queue - PeekMessage(&msg, NULL, 0,0, PM_NOREMOVE); - - // create a window. we use this window to hide the cursor. - try { - desk->m_window = createWindow(m_deskClass, "SynergyDesk"); - LOG((CLOG_DEBUG "desk %s window is 0x%08x", desk->m_name.c_str(), desk->m_window)); - } - catch (...) { - // ignore - LOG((CLOG_DEBUG "can't create desk window for %s", desk->m_name.c_str())); - } - } - - // tell main thread that we're ready - { - CLock lock(&m_mutex); - m_deskReady = true; - m_deskReady.broadcast(); - } - - while (GetMessage(&msg, NULL, 0, 0)) { - switch (msg.message) { - default: - TranslateMessage(&msg); - DispatchMessage(&msg); - continue; - - case SYNERGY_MSG_SWITCH: - if (m_isPrimary) { - m_uninstall(); - if (m_screensaverNotify) { - m_uninstallScreensaver(); - m_installScreensaver(); - } - switch (m_install()) { - case kHOOK_FAILED: - // we won't work on this desk - desk->m_lowLevel = false; - break; - - case kHOOK_OKAY: - desk->m_lowLevel = false; - break; - - case kHOOK_OKAY_LL: - desk->m_lowLevel = true; - break; - } - - // a window on the primary screen with low-level hooks - // should never activate. - EnableWindow(desk->m_window, desk->m_lowLevel ? FALSE : TRUE); - } - break; - - case SYNERGY_MSG_ENTER: - m_isOnScreen = true; - deskEnter(desk); - break; - - case SYNERGY_MSG_LEAVE: - m_isOnScreen = false; - m_keyLayout = (HKL)msg.wParam; - deskLeave(desk, m_keyLayout); - break; - - case SYNERGY_MSG_FAKE_KEY: - keybd_event(HIBYTE(msg.lParam), LOBYTE(msg.lParam), msg.wParam, 0); - break; - - case SYNERGY_MSG_FAKE_BUTTON: - if (msg.wParam != 0) { - mouse_event(msg.wParam, 0, 0, msg.lParam, 0); - } - break; - - case SYNERGY_MSG_FAKE_MOVE: - deskMouseMove(static_cast(msg.wParam), - static_cast(msg.lParam)); - break; - - case SYNERGY_MSG_FAKE_REL_MOVE: - deskMouseRelativeMove(static_cast(msg.wParam), - static_cast(msg.lParam)); - break; - - case SYNERGY_MSG_FAKE_WHEEL: - // XXX -- add support for x-axis scrolling - if (msg.lParam != 0) { - mouse_event(MOUSEEVENTF_WHEEL, 0, 0, msg.lParam, 0); - } - break; - - case SYNERGY_MSG_CURSOR_POS: { - POINT* pos = reinterpret_cast(msg.wParam); - if (!GetCursorPos(pos)) { - pos->x = m_xCenter; - pos->y = m_yCenter; - } - break; - } - - case SYNERGY_MSG_SYNC_KEYS: - m_updateKeys->run(); - break; - - case SYNERGY_MSG_SCREENSAVER: - if (msg.wParam != 0) { - m_installScreensaver(); - } - else { - m_uninstallScreensaver(); - } - break; - - case SYNERGY_MSG_FAKE_INPUT: - keybd_event(SYNERGY_HOOK_FAKE_INPUT_VIRTUAL_KEY, - SYNERGY_HOOK_FAKE_INPUT_SCANCODE, - msg.wParam ? 0 : KEYEVENTF_KEYUP, 0); - break; - } - - // notify that message was processed - CLock lock(&m_mutex); - m_deskReady = true; - m_deskReady.broadcast(); - } - - // clean up - deskEnter(desk); - if (desk->m_window != NULL) { - DestroyWindow(desk->m_window); - } - if (desk->m_desk != NULL) { - closeDesktop(desk->m_desk); - } -} - -CMSWindowsDesks::CDesk* -CMSWindowsDesks::addDesk(const CString& name, HDESK hdesk) -{ - CDesk* desk = new CDesk; - desk->m_name = name; - desk->m_desk = hdesk; - desk->m_targetID = GetCurrentThreadId(); - desk->m_thread = new CThread(new TMethodJob( - this, &CMSWindowsDesks::deskThread, desk)); - waitForDesk(); - m_desks.insert(std::make_pair(name, desk)); - return desk; -} - -void -CMSWindowsDesks::removeDesks() -{ - for (CDesks::iterator index = m_desks.begin(); - index != m_desks.end(); ++index) { - CDesk* desk = index->second; - PostThreadMessage(desk->m_threadID, WM_QUIT, 0, 0); - desk->m_thread->wait(); - delete desk->m_thread; - delete desk; - } - m_desks.clear(); - m_activeDesk = NULL; - m_activeDeskName = ""; -} - -void -CMSWindowsDesks::checkDesk() -{ - // get current desktop. if we already know about it then return. - CDesk* desk; - HDESK hdesk = openInputDesktop(); - CString name = getDesktopName(hdesk); - CDesks::const_iterator index = m_desks.find(name); - if (index == m_desks.end()) { - desk = addDesk(name, hdesk); - // hold on to hdesk until thread exits so the desk can't - // be removed by the system - } - else { - closeDesktop(hdesk); - desk = index->second; - } - - // if active desktop changed then tell the old and new desk threads - // about the change. don't switch desktops when the screensaver is - // active becaue we'd most likely switch to the screensaver desktop - // which would have the side effect of forcing the screensaver to - // stop. - if (name != m_activeDeskName && !m_screensaver->isActive()) { - // show cursor on previous desk - bool wasOnScreen = m_isOnScreen; - if (!wasOnScreen) { - sendMessage(SYNERGY_MSG_ENTER, 0, 0); - } - - // check for desk accessibility change. we don't get events - // from an inaccessible desktop so when we switch from an - // inaccessible desktop to an accessible one we have to - // update the keyboard state. - LOG((CLOG_DEBUG "switched to desk \"%s\"", name.c_str())); - bool syncKeys = false; - bool isAccessible = isDeskAccessible(desk); - if (isDeskAccessible(m_activeDesk) != isAccessible) { - if (isAccessible) { - LOG((CLOG_DEBUG "desktop is now accessible")); - syncKeys = true; - } - else { - LOG((CLOG_DEBUG "desktop is now inaccessible")); - } - } - - // switch desk - m_activeDesk = desk; - m_activeDeskName = name; - sendMessage(SYNERGY_MSG_SWITCH, 0, 0); - - // hide cursor on new desk - if (!wasOnScreen) { - sendMessage(SYNERGY_MSG_LEAVE, (WPARAM)m_keyLayout, 0); - } - - // update keys if necessary - if (syncKeys) { - updateKeys(); - } - } - else if (name != m_activeDeskName) { - // screen saver might have started - PostThreadMessage(m_threadID, SYNERGY_MSG_SCREEN_SAVER, TRUE, 0); - } -} - -bool -CMSWindowsDesks::isDeskAccessible(const CDesk* desk) const -{ - return (desk != NULL && desk->m_desk != NULL); -} - -void -CMSWindowsDesks::waitForDesk() const -{ - CMSWindowsDesks* self = const_cast(this); - - CLock lock(&m_mutex); - while (!(bool)m_deskReady) { - m_deskReady.wait(); - } - self->m_deskReady = false; -} - -void -CMSWindowsDesks::handleCheckDesk(const CEvent&, void*) -{ - checkDesk(); - - // also check if screen saver is running if on a modern OS and - // this is the primary screen. - if (m_isPrimary && m_isModernFamily) { - BOOL running; - SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &running, FALSE); - PostThreadMessage(m_threadID, SYNERGY_MSG_SCREEN_SAVER, running, 0); - } -} - -HDESK -CMSWindowsDesks::openInputDesktop() -{ - if (m_is95Family) { - // there's only one desktop on windows 95 et al. - return GetThreadDesktop(GetCurrentThreadId()); - } - else { - return OpenInputDesktop(DF_ALLOWOTHERACCOUNTHOOK, TRUE, - DESKTOP_CREATEWINDOW | - DESKTOP_HOOKCONTROL | - GENERIC_WRITE); - } -} - -void -CMSWindowsDesks::closeDesktop(HDESK desk) -{ - // on 95/98/me we don't need to close the desktop returned by - // openInputDesktop(). - if (desk != NULL && !m_is95Family) { - CloseDesktop(desk); - } -} - -CString -CMSWindowsDesks::getDesktopName(HDESK desk) -{ - if (desk == NULL) { - return CString(); - } - else if (m_is95Family) { - return "desktop"; - } - else { - DWORD size; - GetUserObjectInformation(desk, UOI_NAME, NULL, 0, &size); - TCHAR* name = (TCHAR*)alloca(size + sizeof(TCHAR)); - GetUserObjectInformation(desk, UOI_NAME, name, size, &size); - CString result(name); - return result; - } -} - -HWND -CMSWindowsDesks::getForegroundWindow() const -{ - // Ideally we'd return NULL as much as possible, only returning - // the actual foreground window when we know it's going to mess - // up our keyboard input. For now we'll just let the user - // decide. - if (m_leaveForegroundOption) { - return NULL; - } - return GetForegroundWindow(); -} diff --git a/lib/platform/CMSWindowsDesks.h b/lib/platform/CMSWindowsDesks.h deleted file mode 100644 index f0388f98..00000000 --- a/lib/platform/CMSWindowsDesks.h +++ /dev/null @@ -1,296 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CMSWINDOWSDESKS_H -#define CMSWINDOWSDESKS_H - -#include "CSynergyHook.h" -#include "KeyTypes.h" -#include "MouseTypes.h" -#include "OptionTypes.h" -#include "CCondVar.h" -#include "CMutex.h" -#include "CString.h" -#include "stdmap.h" -#define WIN32_LEAN_AND_MEAN -#include - -class CEvent; -class CEventQueueTimer; -class CThread; -class IJob; -class IScreenSaver; - -//! Microsoft Windows desk handling -/*! -Desks in Microsoft Windows are only remotely like desktops on X11 -systems. A desk is another virtual surface for windows but desks -impose serious restrictions: a thread can interact with only one -desk at a time, you can't switch desks if the thread has any hooks -installed or owns any windows, windows cannot exist on multiple -desks at once, etc. Basically, they're useless except for running -the login window or the screensaver, which is what they're used -for. Synergy must deal with them mainly because of the login -window and screensaver but users can create their own desks and -synergy should work on those too. - -This class encapsulates all the desk nastiness. Clients of this -object don't have to know anything about desks. -*/ -class CMSWindowsDesks { -public: - //! Constructor - /*! - \p isPrimary is true iff the desk is for a primary screen. - \p screensaver points to a screensaver object and it's used - only to check if the screensaver is active. The \p updateKeys - job is adopted and is called when the key state should be - updated in a thread attached to the current desk. - \p hookLibrary must be a handle to the hook library. - */ - CMSWindowsDesks(bool isPrimary, HINSTANCE hookLibrary, - const IScreenSaver* screensaver, IJob* updateKeys); - ~CMSWindowsDesks(); - - //! @name manipulators - //@{ - - //! Enable desk tracking - /*! - Enables desk tracking. While enabled, this object checks to see - if the desk has changed and ensures that the hooks are installed - on the new desk. \c setShape should be called at least once - before calling \c enable. - */ - void enable(); - - //! Disable desk tracking - /*! - Disables desk tracking. \sa enable. - */ - void disable(); - - //! Notify of entering a desk - /*! - Prepares a desk for when the cursor enters it. - */ - void enter(); - - //! Notify of leaving a desk - /*! - Prepares a desk for when the cursor leaves it. - */ - void leave(HKL keyLayout); - - //! Notify of options changes - /*! - Resets all options to their default values. - */ - void resetOptions(); - - //! Notify of options changes - /*! - Set options to given values. Ignores unknown options and doesn't - modify options that aren't given in \c options. - */ - void setOptions(const COptionsList& options); - - //! Update the key state - /*! - Causes the key state to get updated to reflect the physical keyboard - state and current keyboard mapping. - */ - void updateKeys(); - - //! Tell desk about new size - /*! - This tells the desks that the display size has changed. - */ - void setShape(SInt32 x, SInt32 y, - SInt32 width, SInt32 height, - SInt32 xCenter, SInt32 yCenter, bool isMultimon); - - //! Install/uninstall screensaver hooks - /*! - If \p install is true then the screensaver hooks are installed and, - if desk tracking is enabled, updated whenever the desk changes. If - \p install is false then the screensaver hooks are uninstalled. - */ - void installScreensaverHooks(bool install); - - //! Start ignoring user input - /*! - Starts ignoring user input so we don't pick up our own synthesized events. - */ - void fakeInputBegin(); - - //! Stop ignoring user input - /*! - Undoes whatever \c fakeInputBegin() did. - */ - void fakeInputEnd(); - - //@} - //! @name accessors - //@{ - - //! Get cursor position - /*! - Return the current position of the cursor in \c x and \c y. - */ - void getCursorPos(SInt32& x, SInt32& y) const; - - //! Fake key press/release - /*! - Synthesize a press or release of key \c button. - */ - void fakeKeyEvent(KeyButton button, UINT virtualKey, - bool press, bool isAutoRepeat) const; - - //! Fake mouse press/release - /*! - Synthesize a press or release of mouse button \c id. - */ - void fakeMouseButton(ButtonID id, bool press) const; - - //! Fake mouse move - /*! - Synthesize a mouse move to the absolute coordinates \c x,y. - */ - void fakeMouseMove(SInt32 x, SInt32 y) const; - - //! Fake mouse move - /*! - Synthesize a mouse move to the relative coordinates \c dx,dy. - */ - void fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const; - - //! Fake mouse wheel - /*! - Synthesize a mouse wheel event of amount \c delta in direction \c axis. - */ - void fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const; - - //@} - -private: - class CDesk { - public: - CString m_name; - CThread* m_thread; - DWORD m_threadID; - DWORD m_targetID; - HDESK m_desk; - HWND m_window; - HWND m_foregroundWindow; - bool m_lowLevel; - }; - typedef std::map CDesks; - - // initialization and shutdown operations - void queryHookLibrary(HINSTANCE hookLibrary); - HCURSOR createBlankCursor() const; - void destroyCursor(HCURSOR cursor) const; - ATOM createDeskWindowClass(bool isPrimary) const; - void destroyClass(ATOM windowClass) const; - HWND createWindow(ATOM windowClass, const char* name) const; - void destroyWindow(HWND) const; - - // message handlers - void deskMouseMove(SInt32 x, SInt32 y) const; - void deskMouseRelativeMove(SInt32 dx, SInt32 dy) const; - void deskEnter(CDesk* desk); - void deskLeave(CDesk* desk, HKL keyLayout); - void deskThread(void* vdesk); - - // desk switch checking and handling - CDesk* addDesk(const CString& name, HDESK hdesk); - void removeDesks(); - void checkDesk(); - bool isDeskAccessible(const CDesk* desk) const; - void handleCheckDesk(const CEvent& event, void*); - - // communication with desk threads - void waitForDesk() const; - void sendMessage(UINT, WPARAM, LPARAM) const; - - // work around for messed up keyboard events from low-level hooks - HWND getForegroundWindow() const; - - // desk API wrappers - HDESK openInputDesktop(); - void closeDesktop(HDESK); - CString getDesktopName(HDESK); - - // our desk window procs - static LRESULT CALLBACK primaryDeskProc(HWND, UINT, WPARAM, LPARAM); - static LRESULT CALLBACK secondaryDeskProc(HWND, UINT, WPARAM, LPARAM); - -private: - // true if screen is being used as a primary screen, false otherwise - bool m_isPrimary; - - // true if windows 95/98/me - bool m_is95Family; - - // true if windows 98/2k or higher (i.e. not 95/nt) - bool m_isModernFamily; - - // true if mouse has entered the screen - bool m_isOnScreen; - - // our resources - ATOM m_deskClass; - HCURSOR m_cursor; - - // screen shape stuff - SInt32 m_x, m_y; - SInt32 m_w, m_h; - SInt32 m_xCenter, m_yCenter; - - // true if system appears to have multiple monitors - bool m_multimon; - - // the timer used to check for desktop switching - CEventQueueTimer* m_timer; - - // screen saver stuff - DWORD m_threadID; - const IScreenSaver* m_screensaver; - bool m_screensaverNotify; - - // the current desk and it's name - CDesk* m_activeDesk; - CString m_activeDeskName; - - // one desk per desktop and a cond var to communicate with it - CMutex m_mutex; - CCondVar m_deskReady; - CDesks m_desks; - - // hook library stuff - InstallFunc m_install; - UninstallFunc m_uninstall; - InstallScreenSaverFunc m_installScreensaver; - UninstallScreenSaverFunc m_uninstallScreensaver; - - // keyboard stuff - IJob* m_updateKeys; - HKL m_keyLayout; - - // options - bool m_leaveForegroundOption; -}; - -#endif diff --git a/lib/platform/CMSWindowsEventQueueBuffer.cpp b/lib/platform/CMSWindowsEventQueueBuffer.cpp deleted file mode 100644 index 5bab2855..00000000 --- a/lib/platform/CMSWindowsEventQueueBuffer.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CMSWindowsEventQueueBuffer.h" -#include "CThread.h" -#include "IEventQueue.h" -#include "CArchMiscWindows.h" - -// -// CEventQueueTimer -// - -class CEventQueueTimer { }; - - -// -// CMSWindowsEventQueueBuffer -// - -CMSWindowsEventQueueBuffer::CMSWindowsEventQueueBuffer() -{ - // remember thread. we'll be posting messages to it. - m_thread = GetCurrentThreadId(); - - // create a message type for custom events - m_userEvent = RegisterWindowMessage("SYNERGY_USER_EVENT"); - - // get message type for daemon quit - m_daemonQuit = CArchMiscWindows::getDaemonQuitMessage(); - - // make sure this thread has a message queue - MSG dummy; - PeekMessage(&dummy, NULL, WM_USER, WM_USER, PM_NOREMOVE); -} - -CMSWindowsEventQueueBuffer::~CMSWindowsEventQueueBuffer() -{ - // do nothing -} - -void -CMSWindowsEventQueueBuffer::waitForEvent(double timeout) -{ - // check if messages are available first. if we don't do this then - // MsgWaitForMultipleObjects() will block even if the queue isn't - // empty if the messages in the queue were there before the last - // call to GetMessage()/PeekMessage(). - if (HIWORD(GetQueueStatus(QS_ALLINPUT)) != 0) { - return; - } - - // convert timeout - DWORD t; - if (timeout < 0.0) { - t = INFINITE; - } - else { - t = (DWORD)(1000.0 * timeout); - } - - // wait for a message. we cannot be interrupted by thread - // cancellation but that's okay because we're run in the main - // thread and we never cancel that thread. - HANDLE dummy[1]; - MsgWaitForMultipleObjects(0, dummy, FALSE, t, QS_ALLINPUT); -} - -IEventQueueBuffer::Type -CMSWindowsEventQueueBuffer::getEvent(CEvent& event, UInt32& dataID) -{ - // peek at messages first. waiting for QS_ALLINPUT will return - // if a message has been sent to our window but GetMessage will - // dispatch that message behind our backs and block. PeekMessage - // will also dispatch behind our backs but won't block. - if (!PeekMessage(&m_event, NULL, 0, 0, PM_NOREMOVE) && - !PeekMessage(&m_event, (HWND)-1, 0, 0, PM_NOREMOVE)) { - return kNone; - } - - // BOOL. yeah, right. - BOOL result = GetMessage(&m_event, NULL, 0, 0); - if (result == -1) { - return kNone; - } - else if (result == 0) { - event = CEvent(CEvent::kQuit); - return kSystem; - } - else if (m_daemonQuit != 0 && m_event.message == m_daemonQuit) { - event = CEvent(CEvent::kQuit); - return kSystem; - } - else if (m_event.message == m_userEvent) { - dataID = static_cast(m_event.wParam); - return kUser; - } - else { - event = CEvent(CEvent::kSystem, - IEventQueue::getSystemTarget(), &m_event); - return kSystem; - } -} - -bool -CMSWindowsEventQueueBuffer::addEvent(UInt32 dataID) -{ - return (PostThreadMessage(m_thread, m_userEvent, - static_cast(dataID), 0) != 0); -} - -bool -CMSWindowsEventQueueBuffer::isEmpty() const -{ - return (HIWORD(GetQueueStatus(QS_ALLINPUT)) == 0); -} - -CEventQueueTimer* -CMSWindowsEventQueueBuffer::newTimer(double, bool) const -{ - return new CEventQueueTimer; -} - -void -CMSWindowsEventQueueBuffer::deleteTimer(CEventQueueTimer* timer) const -{ - delete timer; -} diff --git a/lib/platform/CMSWindowsEventQueueBuffer.h b/lib/platform/CMSWindowsEventQueueBuffer.h deleted file mode 100644 index 28d8a2f6..00000000 --- a/lib/platform/CMSWindowsEventQueueBuffer.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CMSWINDOWSEVENTQUEUEBUFFER_H -#define CMSWINDOWSEVENTQUEUEBUFFER_H - -#include "IEventQueueBuffer.h" -#define WIN32_LEAN_AND_MEAN -#include - -//! Event queue buffer for Win32 -class CMSWindowsEventQueueBuffer : public IEventQueueBuffer { -public: - CMSWindowsEventQueueBuffer(); - virtual ~CMSWindowsEventQueueBuffer(); - - // IEventQueueBuffer overrides - virtual void waitForEvent(double timeout); - virtual Type getEvent(CEvent& event, UInt32& dataID); - virtual bool addEvent(UInt32 dataID); - virtual bool isEmpty() const; - virtual CEventQueueTimer* - newTimer(double duration, bool oneShot) const; - virtual void deleteTimer(CEventQueueTimer*) const; - -private: - DWORD m_thread; - UINT m_userEvent; - MSG m_event; - UINT m_daemonQuit; -}; - -#endif diff --git a/lib/platform/CMSWindowsKeyState.cpp b/lib/platform/CMSWindowsKeyState.cpp deleted file mode 100644 index ba105530..00000000 --- a/lib/platform/CMSWindowsKeyState.cpp +++ /dev/null @@ -1,1420 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CMSWindowsKeyState.h" -#include "CMSWindowsDesks.h" -#include "CThread.h" -#include "CFunctionJob.h" -#include "CLog.h" -#include "CStringUtil.h" -#include "IEventQueue.h" -#include "TMethodEventJob.h" -#include "CArchMiscWindows.h" - -// extended mouse buttons -#if !defined(VK_XBUTTON1) -#define VK_XBUTTON1 0x05 -#define VK_XBUTTON2 0x06 -#endif - -// -// CMSWindowsKeyState -// - -// map virtual keys to synergy key enumeration -const KeyID CMSWindowsKeyState::s_virtualKey[] = -{ - /* 0x000 */ { kKeyNone }, // reserved - /* 0x001 */ { kKeyNone }, // VK_LBUTTON - /* 0x002 */ { kKeyNone }, // VK_RBUTTON - /* 0x003 */ { kKeyNone }, // VK_CANCEL - /* 0x004 */ { kKeyNone }, // VK_MBUTTON - /* 0x005 */ { kKeyNone }, // VK_XBUTTON1 - /* 0x006 */ { kKeyNone }, // VK_XBUTTON2 - /* 0x007 */ { kKeyNone }, // undefined - /* 0x008 */ { kKeyBackSpace }, // VK_BACK - /* 0x009 */ { kKeyTab }, // VK_TAB - /* 0x00a */ { kKeyNone }, // undefined - /* 0x00b */ { kKeyNone }, // undefined - /* 0x00c */ { kKeyClear }, // VK_CLEAR - /* 0x00d */ { kKeyReturn }, // VK_RETURN - /* 0x00e */ { kKeyNone }, // undefined - /* 0x00f */ { kKeyNone }, // undefined - /* 0x010 */ { kKeyShift_L }, // VK_SHIFT - /* 0x011 */ { kKeyControl_L }, // VK_CONTROL - /* 0x012 */ { kKeyAlt_L }, // VK_MENU - /* 0x013 */ { kKeyPause }, // VK_PAUSE - /* 0x014 */ { kKeyCapsLock }, // VK_CAPITAL - /* 0x015 */ { kKeyHangulKana }, // VK_HANGUL, VK_KANA - /* 0x016 */ { kKeyNone }, // undefined - /* 0x017 */ { kKeyNone }, // VK_JUNJA - /* 0x018 */ { kKeyNone }, // VK_FINAL - /* 0x019 */ { kKeyHanjaKanzi }, // VK_KANJI - /* 0x01a */ { kKeyNone }, // undefined - /* 0x01b */ { kKeyEscape }, // VK_ESCAPE - /* 0x01c */ { kKeyHenkan }, // VK_CONVERT - /* 0x01d */ { kKeyNone }, // VK_NONCONVERT - /* 0x01e */ { kKeyNone }, // VK_ACCEPT - /* 0x01f */ { kKeyNone }, // VK_MODECHANGE - /* 0x020 */ { kKeyNone }, // VK_SPACE - /* 0x021 */ { kKeyKP_PageUp }, // VK_PRIOR - /* 0x022 */ { kKeyKP_PageDown },// VK_NEXT - /* 0x023 */ { kKeyKP_End }, // VK_END - /* 0x024 */ { kKeyKP_Home }, // VK_HOME - /* 0x025 */ { kKeyKP_Left }, // VK_LEFT - /* 0x026 */ { kKeyKP_Up }, // VK_UP - /* 0x027 */ { kKeyKP_Right }, // VK_RIGHT - /* 0x028 */ { kKeyKP_Down }, // VK_DOWN - /* 0x029 */ { kKeySelect }, // VK_SELECT - /* 0x02a */ { kKeyNone }, // VK_PRINT - /* 0x02b */ { kKeyExecute }, // VK_EXECUTE - /* 0x02c */ { kKeyPrint }, // VK_SNAPSHOT - /* 0x02d */ { kKeyKP_Insert }, // VK_INSERT - /* 0x02e */ { kKeyKP_Delete }, // VK_DELETE - /* 0x02f */ { kKeyHelp }, // VK_HELP - /* 0x030 */ { kKeyNone }, // VK_0 - /* 0x031 */ { kKeyNone }, // VK_1 - /* 0x032 */ { kKeyNone }, // VK_2 - /* 0x033 */ { kKeyNone }, // VK_3 - /* 0x034 */ { kKeyNone }, // VK_4 - /* 0x035 */ { kKeyNone }, // VK_5 - /* 0x036 */ { kKeyNone }, // VK_6 - /* 0x037 */ { kKeyNone }, // VK_7 - /* 0x038 */ { kKeyNone }, // VK_8 - /* 0x039 */ { kKeyNone }, // VK_9 - /* 0x03a */ { kKeyNone }, // undefined - /* 0x03b */ { kKeyNone }, // undefined - /* 0x03c */ { kKeyNone }, // undefined - /* 0x03d */ { kKeyNone }, // undefined - /* 0x03e */ { kKeyNone }, // undefined - /* 0x03f */ { kKeyNone }, // undefined - /* 0x040 */ { kKeyNone }, // undefined - /* 0x041 */ { kKeyNone }, // VK_A - /* 0x042 */ { kKeyNone }, // VK_B - /* 0x043 */ { kKeyNone }, // VK_C - /* 0x044 */ { kKeyNone }, // VK_D - /* 0x045 */ { kKeyNone }, // VK_E - /* 0x046 */ { kKeyNone }, // VK_F - /* 0x047 */ { kKeyNone }, // VK_G - /* 0x048 */ { kKeyNone }, // VK_H - /* 0x049 */ { kKeyNone }, // VK_I - /* 0x04a */ { kKeyNone }, // VK_J - /* 0x04b */ { kKeyNone }, // VK_K - /* 0x04c */ { kKeyNone }, // VK_L - /* 0x04d */ { kKeyNone }, // VK_M - /* 0x04e */ { kKeyNone }, // VK_N - /* 0x04f */ { kKeyNone }, // VK_O - /* 0x050 */ { kKeyNone }, // VK_P - /* 0x051 */ { kKeyNone }, // VK_Q - /* 0x052 */ { kKeyNone }, // VK_R - /* 0x053 */ { kKeyNone }, // VK_S - /* 0x054 */ { kKeyNone }, // VK_T - /* 0x055 */ { kKeyNone }, // VK_U - /* 0x056 */ { kKeyNone }, // VK_V - /* 0x057 */ { kKeyNone }, // VK_W - /* 0x058 */ { kKeyNone }, // VK_X - /* 0x059 */ { kKeyNone }, // VK_Y - /* 0x05a */ { kKeyNone }, // VK_Z - /* 0x05b */ { kKeySuper_L }, // VK_LWIN - /* 0x05c */ { kKeySuper_R }, // VK_RWIN - /* 0x05d */ { kKeyMenu }, // VK_APPS - /* 0x05e */ { kKeyNone }, // undefined - /* 0x05f */ { kKeySleep }, // VK_SLEEP - /* 0x060 */ { kKeyKP_0 }, // VK_NUMPAD0 - /* 0x061 */ { kKeyKP_1 }, // VK_NUMPAD1 - /* 0x062 */ { kKeyKP_2 }, // VK_NUMPAD2 - /* 0x063 */ { kKeyKP_3 }, // VK_NUMPAD3 - /* 0x064 */ { kKeyKP_4 }, // VK_NUMPAD4 - /* 0x065 */ { kKeyKP_5 }, // VK_NUMPAD5 - /* 0x066 */ { kKeyKP_6 }, // VK_NUMPAD6 - /* 0x067 */ { kKeyKP_7 }, // VK_NUMPAD7 - /* 0x068 */ { kKeyKP_8 }, // VK_NUMPAD8 - /* 0x069 */ { kKeyKP_9 }, // VK_NUMPAD9 - /* 0x06a */ { kKeyKP_Multiply },// VK_MULTIPLY - /* 0x06b */ { kKeyKP_Add }, // VK_ADD - /* 0x06c */ { kKeyKP_Separator },// VK_SEPARATOR - /* 0x06d */ { kKeyKP_Subtract },// VK_SUBTRACT - /* 0x06e */ { kKeyKP_Decimal }, // VK_DECIMAL - /* 0x06f */ { kKeyNone }, // VK_DIVIDE - /* 0x070 */ { kKeyF1 }, // VK_F1 - /* 0x071 */ { kKeyF2 }, // VK_F2 - /* 0x072 */ { kKeyF3 }, // VK_F3 - /* 0x073 */ { kKeyF4 }, // VK_F4 - /* 0x074 */ { kKeyF5 }, // VK_F5 - /* 0x075 */ { kKeyF6 }, // VK_F6 - /* 0x076 */ { kKeyF7 }, // VK_F7 - /* 0x077 */ { kKeyF8 }, // VK_F8 - /* 0x078 */ { kKeyF9 }, // VK_F9 - /* 0x079 */ { kKeyF10 }, // VK_F10 - /* 0x07a */ { kKeyF11 }, // VK_F11 - /* 0x07b */ { kKeyF12 }, // VK_F12 - /* 0x07c */ { kKeyF13 }, // VK_F13 - /* 0x07d */ { kKeyF14 }, // VK_F14 - /* 0x07e */ { kKeyF15 }, // VK_F15 - /* 0x07f */ { kKeyF16 }, // VK_F16 - /* 0x080 */ { kKeyF17 }, // VK_F17 - /* 0x081 */ { kKeyF18 }, // VK_F18 - /* 0x082 */ { kKeyF19 }, // VK_F19 - /* 0x083 */ { kKeyF20 }, // VK_F20 - /* 0x084 */ { kKeyF21 }, // VK_F21 - /* 0x085 */ { kKeyF22 }, // VK_F22 - /* 0x086 */ { kKeyF23 }, // VK_F23 - /* 0x087 */ { kKeyF24 }, // VK_F24 - /* 0x088 */ { kKeyNone }, // unassigned - /* 0x089 */ { kKeyNone }, // unassigned - /* 0x08a */ { kKeyNone }, // unassigned - /* 0x08b */ { kKeyNone }, // unassigned - /* 0x08c */ { kKeyNone }, // unassigned - /* 0x08d */ { kKeyNone }, // unassigned - /* 0x08e */ { kKeyNone }, // unassigned - /* 0x08f */ { kKeyNone }, // unassigned - /* 0x090 */ { kKeyNumLock }, // VK_NUMLOCK - /* 0x091 */ { kKeyScrollLock }, // VK_SCROLL - /* 0x092 */ { kKeyNone }, // unassigned - /* 0x093 */ { kKeyNone }, // unassigned - /* 0x094 */ { kKeyNone }, // unassigned - /* 0x095 */ { kKeyNone }, // unassigned - /* 0x096 */ { kKeyNone }, // unassigned - /* 0x097 */ { kKeyNone }, // unassigned - /* 0x098 */ { kKeyNone }, // unassigned - /* 0x099 */ { kKeyNone }, // unassigned - /* 0x09a */ { kKeyNone }, // unassigned - /* 0x09b */ { kKeyNone }, // unassigned - /* 0x09c */ { kKeyNone }, // unassigned - /* 0x09d */ { kKeyNone }, // unassigned - /* 0x09e */ { kKeyNone }, // unassigned - /* 0x09f */ { kKeyNone }, // unassigned - /* 0x0a0 */ { kKeyShift_L }, // VK_LSHIFT - /* 0x0a1 */ { kKeyShift_R }, // VK_RSHIFT - /* 0x0a2 */ { kKeyControl_L }, // VK_LCONTROL - /* 0x0a3 */ { kKeyControl_R }, // VK_RCONTROL - /* 0x0a4 */ { kKeyAlt_L }, // VK_LMENU - /* 0x0a5 */ { kKeyAlt_R }, // VK_RMENU - /* 0x0a6 */ { kKeyNone }, // VK_BROWSER_BACK - /* 0x0a7 */ { kKeyNone }, // VK_BROWSER_FORWARD - /* 0x0a8 */ { kKeyNone }, // VK_BROWSER_REFRESH - /* 0x0a9 */ { kKeyNone }, // VK_BROWSER_STOP - /* 0x0aa */ { kKeyNone }, // VK_BROWSER_SEARCH - /* 0x0ab */ { kKeyNone }, // VK_BROWSER_FAVORITES - /* 0x0ac */ { kKeyNone }, // VK_BROWSER_HOME - /* 0x0ad */ { kKeyNone }, // VK_VOLUME_MUTE - /* 0x0ae */ { kKeyNone }, // VK_VOLUME_DOWN - /* 0x0af */ { kKeyNone }, // VK_VOLUME_UP - /* 0x0b0 */ { kKeyNone }, // VK_MEDIA_NEXT_TRACK - /* 0x0b1 */ { kKeyNone }, // VK_MEDIA_PREV_TRACK - /* 0x0b2 */ { kKeyNone }, // VK_MEDIA_STOP - /* 0x0b3 */ { kKeyNone }, // VK_MEDIA_PLAY_PAUSE - /* 0x0b4 */ { kKeyNone }, // VK_LAUNCH_MAIL - /* 0x0b5 */ { kKeyNone }, // VK_LAUNCH_MEDIA_SELECT - /* 0x0b6 */ { kKeyNone }, // VK_LAUNCH_APP1 - /* 0x0b7 */ { kKeyNone }, // VK_LAUNCH_APP2 - /* 0x0b8 */ { kKeyNone }, // unassigned - /* 0x0b9 */ { kKeyNone }, // unassigned - /* 0x0ba */ { kKeyNone }, // OEM specific - /* 0x0bb */ { kKeyNone }, // OEM specific - /* 0x0bc */ { kKeyNone }, // OEM specific - /* 0x0bd */ { kKeyNone }, // OEM specific - /* 0x0be */ { kKeyNone }, // OEM specific - /* 0x0bf */ { kKeyNone }, // OEM specific - /* 0x0c0 */ { kKeyNone }, // OEM specific - /* 0x0c1 */ { kKeyNone }, // unassigned - /* 0x0c2 */ { kKeyNone }, // unassigned - /* 0x0c3 */ { kKeyNone }, // unassigned - /* 0x0c4 */ { kKeyNone }, // unassigned - /* 0x0c5 */ { kKeyNone }, // unassigned - /* 0x0c6 */ { kKeyNone }, // unassigned - /* 0x0c7 */ { kKeyNone }, // unassigned - /* 0x0c8 */ { kKeyNone }, // unassigned - /* 0x0c9 */ { kKeyNone }, // unassigned - /* 0x0ca */ { kKeyNone }, // unassigned - /* 0x0cb */ { kKeyNone }, // unassigned - /* 0x0cc */ { kKeyNone }, // unassigned - /* 0x0cd */ { kKeyNone }, // unassigned - /* 0x0ce */ { kKeyNone }, // unassigned - /* 0x0cf */ { kKeyNone }, // unassigned - /* 0x0d0 */ { kKeyNone }, // unassigned - /* 0x0d1 */ { kKeyNone }, // unassigned - /* 0x0d2 */ { kKeyNone }, // unassigned - /* 0x0d3 */ { kKeyNone }, // unassigned - /* 0x0d4 */ { kKeyNone }, // unassigned - /* 0x0d5 */ { kKeyNone }, // unassigned - /* 0x0d6 */ { kKeyNone }, // unassigned - /* 0x0d7 */ { kKeyNone }, // unassigned - /* 0x0d8 */ { kKeyNone }, // unassigned - /* 0x0d9 */ { kKeyNone }, // unassigned - /* 0x0da */ { kKeyNone }, // unassigned - /* 0x0db */ { kKeyNone }, // OEM specific - /* 0x0dc */ { kKeyNone }, // OEM specific - /* 0x0dd */ { kKeyNone }, // OEM specific - /* 0x0de */ { kKeyNone }, // OEM specific - /* 0x0df */ { kKeyNone }, // OEM specific - /* 0x0e0 */ { kKeyNone }, // OEM specific - /* 0x0e1 */ { kKeyNone }, // OEM specific - /* 0x0e2 */ { kKeyNone }, // OEM specific - /* 0x0e3 */ { kKeyNone }, // OEM specific - /* 0x0e4 */ { kKeyNone }, // OEM specific - /* 0x0e5 */ { kKeyNone }, // unassigned - /* 0x0e6 */ { kKeyNone }, // OEM specific - /* 0x0e7 */ { kKeyNone }, // unassigned - /* 0x0e8 */ { kKeyNone }, // unassigned - /* 0x0e9 */ { kKeyNone }, // OEM specific - /* 0x0ea */ { kKeyNone }, // OEM specific - /* 0x0eb */ { kKeyNone }, // OEM specific - /* 0x0ec */ { kKeyNone }, // OEM specific - /* 0x0ed */ { kKeyNone }, // OEM specific - /* 0x0ee */ { kKeyNone }, // OEM specific - /* 0x0ef */ { kKeyNone }, // OEM specific - /* 0x0f0 */ { kKeyNone }, // OEM specific - /* 0x0f1 */ { kKeyNone }, // OEM specific - /* 0x0f2 */ { kKeyHiraganaKatakana }, // VK_OEM_COPY - /* 0x0f3 */ { kKeyZenkaku }, // VK_OEM_AUTO - /* 0x0f4 */ { kKeyZenkaku }, // VK_OEM_ENLW - /* 0x0f5 */ { kKeyNone }, // OEM specific - /* 0x0f6 */ { kKeyNone }, // VK_ATTN - /* 0x0f7 */ { kKeyNone }, // VK_CRSEL - /* 0x0f8 */ { kKeyNone }, // VK_EXSEL - /* 0x0f9 */ { kKeyNone }, // VK_EREOF - /* 0x0fa */ { kKeyNone }, // VK_PLAY - /* 0x0fb */ { kKeyNone }, // VK_ZOOM - /* 0x0fc */ { kKeyNone }, // reserved - /* 0x0fd */ { kKeyNone }, // VK_PA1 - /* 0x0fe */ { kKeyNone }, // VK_OEM_CLEAR - /* 0x0ff */ { kKeyNone }, // reserved - - /* 0x100 */ { kKeyNone }, // reserved - /* 0x101 */ { kKeyNone }, // VK_LBUTTON - /* 0x102 */ { kKeyNone }, // VK_RBUTTON - /* 0x103 */ { kKeyBreak }, // VK_CANCEL - /* 0x104 */ { kKeyNone }, // VK_MBUTTON - /* 0x105 */ { kKeyNone }, // VK_XBUTTON1 - /* 0x106 */ { kKeyNone }, // VK_XBUTTON2 - /* 0x107 */ { kKeyNone }, // undefined - /* 0x108 */ { kKeyNone }, // VK_BACK - /* 0x109 */ { kKeyNone }, // VK_TAB - /* 0x10a */ { kKeyNone }, // undefined - /* 0x10b */ { kKeyNone }, // undefined - /* 0x10c */ { kKeyClear }, // VK_CLEAR - /* 0x10d */ { kKeyKP_Enter }, // VK_RETURN - /* 0x10e */ { kKeyNone }, // undefined - /* 0x10f */ { kKeyNone }, // undefined - /* 0x110 */ { kKeyShift_R }, // VK_SHIFT - /* 0x111 */ { kKeyControl_R }, // VK_CONTROL - /* 0x112 */ { kKeyAlt_R }, // VK_MENU - /* 0x113 */ { kKeyNone }, // VK_PAUSE - /* 0x114 */ { kKeyNone }, // VK_CAPITAL - /* 0x115 */ { kKeyNone }, // VK_KANA - /* 0x116 */ { kKeyNone }, // VK_HANGUL - /* 0x117 */ { kKeyNone }, // VK_JUNJA - /* 0x118 */ { kKeyNone }, // VK_FINAL - /* 0x119 */ { kKeyNone }, // VK_KANJI - /* 0x11a */ { kKeyNone }, // undefined - /* 0x11b */ { kKeyNone }, // VK_ESCAPE - /* 0x11c */ { kKeyNone }, // VK_CONVERT - /* 0x11d */ { kKeyNone }, // VK_NONCONVERT - /* 0x11e */ { kKeyNone }, // VK_ACCEPT - /* 0x11f */ { kKeyNone }, // VK_MODECHANGE - /* 0x120 */ { kKeyNone }, // VK_SPACE - /* 0x121 */ { kKeyPageUp }, // VK_PRIOR - /* 0x122 */ { kKeyPageDown }, // VK_NEXT - /* 0x123 */ { kKeyEnd }, // VK_END - /* 0x124 */ { kKeyHome }, // VK_HOME - /* 0x125 */ { kKeyLeft }, // VK_LEFT - /* 0x126 */ { kKeyUp }, // VK_UP - /* 0x127 */ { kKeyRight }, // VK_RIGHT - /* 0x128 */ { kKeyDown }, // VK_DOWN - /* 0x129 */ { kKeySelect }, // VK_SELECT - /* 0x12a */ { kKeyNone }, // VK_PRINT - /* 0x12b */ { kKeyExecute }, // VK_EXECUTE - /* 0x12c */ { kKeyPrint }, // VK_SNAPSHOT - /* 0x12d */ { kKeyInsert }, // VK_INSERT - /* 0x12e */ { kKeyDelete }, // VK_DELETE - /* 0x12f */ { kKeyHelp }, // VK_HELP - /* 0x130 */ { kKeyNone }, // VK_0 - /* 0x131 */ { kKeyNone }, // VK_1 - /* 0x132 */ { kKeyNone }, // VK_2 - /* 0x133 */ { kKeyNone }, // VK_3 - /* 0x134 */ { kKeyNone }, // VK_4 - /* 0x135 */ { kKeyNone }, // VK_5 - /* 0x136 */ { kKeyNone }, // VK_6 - /* 0x137 */ { kKeyNone }, // VK_7 - /* 0x138 */ { kKeyNone }, // VK_8 - /* 0x139 */ { kKeyNone }, // VK_9 - /* 0x13a */ { kKeyNone }, // undefined - /* 0x13b */ { kKeyNone }, // undefined - /* 0x13c */ { kKeyNone }, // undefined - /* 0x13d */ { kKeyNone }, // undefined - /* 0x13e */ { kKeyNone }, // undefined - /* 0x13f */ { kKeyNone }, // undefined - /* 0x140 */ { kKeyNone }, // undefined - /* 0x141 */ { kKeyNone }, // VK_A - /* 0x142 */ { kKeyNone }, // VK_B - /* 0x143 */ { kKeyNone }, // VK_C - /* 0x144 */ { kKeyNone }, // VK_D - /* 0x145 */ { kKeyNone }, // VK_E - /* 0x146 */ { kKeyNone }, // VK_F - /* 0x147 */ { kKeyNone }, // VK_G - /* 0x148 */ { kKeyNone }, // VK_H - /* 0x149 */ { kKeyNone }, // VK_I - /* 0x14a */ { kKeyNone }, // VK_J - /* 0x14b */ { kKeyNone }, // VK_K - /* 0x14c */ { kKeyNone }, // VK_L - /* 0x14d */ { kKeyNone }, // VK_M - /* 0x14e */ { kKeyNone }, // VK_N - /* 0x14f */ { kKeyNone }, // VK_O - /* 0x150 */ { kKeyNone }, // VK_P - /* 0x151 */ { kKeyNone }, // VK_Q - /* 0x152 */ { kKeyNone }, // VK_R - /* 0x153 */ { kKeyNone }, // VK_S - /* 0x154 */ { kKeyNone }, // VK_T - /* 0x155 */ { kKeyNone }, // VK_U - /* 0x156 */ { kKeyNone }, // VK_V - /* 0x157 */ { kKeyNone }, // VK_W - /* 0x158 */ { kKeyNone }, // VK_X - /* 0x159 */ { kKeyNone }, // VK_Y - /* 0x15a */ { kKeyNone }, // VK_Z - /* 0x15b */ { kKeySuper_L }, // VK_LWIN - /* 0x15c */ { kKeySuper_R }, // VK_RWIN - /* 0x15d */ { kKeyMenu }, // VK_APPS - /* 0x15e */ { kKeyNone }, // undefined - /* 0x15f */ { kKeyNone }, // VK_SLEEP - /* 0x160 */ { kKeyNone }, // VK_NUMPAD0 - /* 0x161 */ { kKeyNone }, // VK_NUMPAD1 - /* 0x162 */ { kKeyNone }, // VK_NUMPAD2 - /* 0x163 */ { kKeyNone }, // VK_NUMPAD3 - /* 0x164 */ { kKeyNone }, // VK_NUMPAD4 - /* 0x165 */ { kKeyNone }, // VK_NUMPAD5 - /* 0x166 */ { kKeyNone }, // VK_NUMPAD6 - /* 0x167 */ { kKeyNone }, // VK_NUMPAD7 - /* 0x168 */ { kKeyNone }, // VK_NUMPAD8 - /* 0x169 */ { kKeyNone }, // VK_NUMPAD9 - /* 0x16a */ { kKeyNone }, // VK_MULTIPLY - /* 0x16b */ { kKeyNone }, // VK_ADD - /* 0x16c */ { kKeyKP_Separator },// VK_SEPARATOR - /* 0x16d */ { kKeyNone }, // VK_SUBTRACT - /* 0x16e */ { kKeyNone }, // VK_DECIMAL - /* 0x16f */ { kKeyKP_Divide }, // VK_DIVIDE - /* 0x170 */ { kKeyNone }, // VK_F1 - /* 0x171 */ { kKeyNone }, // VK_F2 - /* 0x172 */ { kKeyNone }, // VK_F3 - /* 0x173 */ { kKeyNone }, // VK_F4 - /* 0x174 */ { kKeyNone }, // VK_F5 - /* 0x175 */ { kKeyNone }, // VK_F6 - /* 0x176 */ { kKeyNone }, // VK_F7 - /* 0x177 */ { kKeyNone }, // VK_F8 - /* 0x178 */ { kKeyNone }, // VK_F9 - /* 0x179 */ { kKeyNone }, // VK_F10 - /* 0x17a */ { kKeyNone }, // VK_F11 - /* 0x17b */ { kKeyNone }, // VK_F12 - /* 0x17c */ { kKeyF13 }, // VK_F13 - /* 0x17d */ { kKeyF14 }, // VK_F14 - /* 0x17e */ { kKeyF15 }, // VK_F15 - /* 0x17f */ { kKeyF16 }, // VK_F16 - /* 0x180 */ { kKeyF17 }, // VK_F17 - /* 0x181 */ { kKeyF18 }, // VK_F18 - /* 0x182 */ { kKeyF19 }, // VK_F19 - /* 0x183 */ { kKeyF20 }, // VK_F20 - /* 0x184 */ { kKeyF21 }, // VK_F21 - /* 0x185 */ { kKeyF22 }, // VK_F22 - /* 0x186 */ { kKeyF23 }, // VK_F23 - /* 0x187 */ { kKeyF24 }, // VK_F24 - /* 0x188 */ { kKeyNone }, // unassigned - /* 0x189 */ { kKeyNone }, // unassigned - /* 0x18a */ { kKeyNone }, // unassigned - /* 0x18b */ { kKeyNone }, // unassigned - /* 0x18c */ { kKeyNone }, // unassigned - /* 0x18d */ { kKeyNone }, // unassigned - /* 0x18e */ { kKeyNone }, // unassigned - /* 0x18f */ { kKeyNone }, // unassigned - /* 0x190 */ { kKeyNumLock }, // VK_NUMLOCK - /* 0x191 */ { kKeyNone }, // VK_SCROLL - /* 0x192 */ { kKeyNone }, // unassigned - /* 0x193 */ { kKeyNone }, // unassigned - /* 0x194 */ { kKeyNone }, // unassigned - /* 0x195 */ { kKeyNone }, // unassigned - /* 0x196 */ { kKeyNone }, // unassigned - /* 0x197 */ { kKeyNone }, // unassigned - /* 0x198 */ { kKeyNone }, // unassigned - /* 0x199 */ { kKeyNone }, // unassigned - /* 0x19a */ { kKeyNone }, // unassigned - /* 0x19b */ { kKeyNone }, // unassigned - /* 0x19c */ { kKeyNone }, // unassigned - /* 0x19d */ { kKeyNone }, // unassigned - /* 0x19e */ { kKeyNone }, // unassigned - /* 0x19f */ { kKeyNone }, // unassigned - /* 0x1a0 */ { kKeyShift_L }, // VK_LSHIFT - /* 0x1a1 */ { kKeyShift_R }, // VK_RSHIFT - /* 0x1a2 */ { kKeyControl_L }, // VK_LCONTROL - /* 0x1a3 */ { kKeyControl_R }, // VK_RCONTROL - /* 0x1a4 */ { kKeyAlt_L }, // VK_LMENU - /* 0x1a5 */ { kKeyAlt_R }, // VK_RMENU - /* 0x1a6 */ { kKeyWWWBack }, // VK_BROWSER_BACK - /* 0x1a7 */ { kKeyWWWForward }, // VK_BROWSER_FORWARD - /* 0x1a8 */ { kKeyWWWRefresh }, // VK_BROWSER_REFRESH - /* 0x1a9 */ { kKeyWWWStop }, // VK_BROWSER_STOP - /* 0x1aa */ { kKeyWWWSearch }, // VK_BROWSER_SEARCH - /* 0x1ab */ { kKeyWWWFavorites },// VK_BROWSER_FAVORITES - /* 0x1ac */ { kKeyWWWHome }, // VK_BROWSER_HOME - /* 0x1ad */ { kKeyAudioMute }, // VK_VOLUME_MUTE - /* 0x1ae */ { kKeyAudioDown }, // VK_VOLUME_DOWN - /* 0x1af */ { kKeyAudioUp }, // VK_VOLUME_UP - /* 0x1b0 */ { kKeyAudioNext }, // VK_MEDIA_NEXT_TRACK - /* 0x1b1 */ { kKeyAudioPrev }, // VK_MEDIA_PREV_TRACK - /* 0x1b2 */ { kKeyAudioStop }, // VK_MEDIA_STOP - /* 0x1b3 */ { kKeyAudioPlay }, // VK_MEDIA_PLAY_PAUSE - /* 0x1b4 */ { kKeyAppMail }, // VK_LAUNCH_MAIL - /* 0x1b5 */ { kKeyAppMedia }, // VK_LAUNCH_MEDIA_SELECT - /* 0x1b6 */ { kKeyAppUser1 }, // VK_LAUNCH_APP1 - /* 0x1b7 */ { kKeyAppUser2 }, // VK_LAUNCH_APP2 - /* 0x1b8 */ { kKeyNone }, // unassigned - /* 0x1b9 */ { kKeyNone }, // unassigned - /* 0x1ba */ { kKeyNone }, // OEM specific - /* 0x1bb */ { kKeyNone }, // OEM specific - /* 0x1bc */ { kKeyNone }, // OEM specific - /* 0x1bd */ { kKeyNone }, // OEM specific - /* 0x1be */ { kKeyNone }, // OEM specific - /* 0x1bf */ { kKeyNone }, // OEM specific - /* 0x1c0 */ { kKeyNone }, // OEM specific - /* 0x1c1 */ { kKeyNone }, // unassigned - /* 0x1c2 */ { kKeyNone }, // unassigned - /* 0x1c3 */ { kKeyNone }, // unassigned - /* 0x1c4 */ { kKeyNone }, // unassigned - /* 0x1c5 */ { kKeyNone }, // unassigned - /* 0x1c6 */ { kKeyNone }, // unassigned - /* 0x1c7 */ { kKeyNone }, // unassigned - /* 0x1c8 */ { kKeyNone }, // unassigned - /* 0x1c9 */ { kKeyNone }, // unassigned - /* 0x1ca */ { kKeyNone }, // unassigned - /* 0x1cb */ { kKeyNone }, // unassigned - /* 0x1cc */ { kKeyNone }, // unassigned - /* 0x1cd */ { kKeyNone }, // unassigned - /* 0x1ce */ { kKeyNone }, // unassigned - /* 0x1cf */ { kKeyNone }, // unassigned - /* 0x1d0 */ { kKeyNone }, // unassigned - /* 0x1d1 */ { kKeyNone }, // unassigned - /* 0x1d2 */ { kKeyNone }, // unassigned - /* 0x1d3 */ { kKeyNone }, // unassigned - /* 0x1d4 */ { kKeyNone }, // unassigned - /* 0x1d5 */ { kKeyNone }, // unassigned - /* 0x1d6 */ { kKeyNone }, // unassigned - /* 0x1d7 */ { kKeyNone }, // unassigned - /* 0x1d8 */ { kKeyNone }, // unassigned - /* 0x1d9 */ { kKeyNone }, // unassigned - /* 0x1da */ { kKeyNone }, // unassigned - /* 0x1db */ { kKeyNone }, // OEM specific - /* 0x1dc */ { kKeyNone }, // OEM specific - /* 0x1dd */ { kKeyNone }, // OEM specific - /* 0x1de */ { kKeyNone }, // OEM specific - /* 0x1df */ { kKeyNone }, // OEM specific - /* 0x1e0 */ { kKeyNone }, // OEM specific - /* 0x1e1 */ { kKeyNone }, // OEM specific - /* 0x1e2 */ { kKeyNone }, // OEM specific - /* 0x1e3 */ { kKeyNone }, // OEM specific - /* 0x1e4 */ { kKeyNone }, // OEM specific - /* 0x1e5 */ { kKeyNone }, // unassigned - /* 0x1e6 */ { kKeyNone }, // OEM specific - /* 0x1e7 */ { kKeyNone }, // unassigned - /* 0x1e8 */ { kKeyNone }, // unassigned - /* 0x1e9 */ { kKeyNone }, // OEM specific - /* 0x1ea */ { kKeyNone }, // OEM specific - /* 0x1eb */ { kKeyNone }, // OEM specific - /* 0x1ec */ { kKeyNone }, // OEM specific - /* 0x1ed */ { kKeyNone }, // OEM specific - /* 0x1ee */ { kKeyNone }, // OEM specific - /* 0x1ef */ { kKeyNone }, // OEM specific - /* 0x1f0 */ { kKeyNone }, // OEM specific - /* 0x1f1 */ { kKeyNone }, // OEM specific - /* 0x1f2 */ { kKeyNone }, // VK_OEM_COPY - /* 0x1f3 */ { kKeyNone }, // VK_OEM_AUTO - /* 0x1f4 */ { kKeyNone }, // VK_OEM_ENLW - /* 0x1f5 */ { kKeyNone }, // OEM specific - /* 0x1f6 */ { kKeyNone }, // VK_ATTN - /* 0x1f7 */ { kKeyNone }, // VK_CRSEL - /* 0x1f8 */ { kKeyNone }, // VK_EXSEL - /* 0x1f9 */ { kKeyNone }, // VK_EREOF - /* 0x1fa */ { kKeyNone }, // VK_PLAY - /* 0x1fb */ { kKeyNone }, // VK_ZOOM - /* 0x1fc */ { kKeyNone }, // reserved - /* 0x1fd */ { kKeyNone }, // VK_PA1 - /* 0x1fe */ { kKeyNone }, // VK_OEM_CLEAR - /* 0x1ff */ { kKeyNone } // reserved -}; - -struct CWin32Modifiers { -public: - UINT m_vk; - KeyModifierMask m_mask; -}; - -static const CWin32Modifiers s_modifiers[] = -{ - { VK_SHIFT, KeyModifierShift }, - { VK_LSHIFT, KeyModifierShift }, - { VK_RSHIFT, KeyModifierShift }, - { VK_CONTROL, KeyModifierControl }, - { VK_LCONTROL, KeyModifierControl }, - { VK_RCONTROL, KeyModifierControl }, - { VK_MENU, KeyModifierAlt }, - { VK_LMENU, KeyModifierAlt }, - { VK_RMENU, KeyModifierAlt }, - { VK_LWIN, KeyModifierSuper }, - { VK_RWIN, KeyModifierSuper } -}; - -CMSWindowsKeyState::CMSWindowsKeyState(CMSWindowsDesks* desks, - void* eventTarget) : - m_is95Family(CArchMiscWindows::isWindows95Family()), - m_eventTarget(eventTarget), - m_desks(desks), - m_keyLayout(GetKeyboardLayout(0)), - m_fixTimer(NULL), - m_lastDown(0), - m_useSavedModifiers(false), - m_savedModifiers(0), - m_originalSavedModifiers(0) -{ - // look up symbol that's available on winNT family but not win95 - HMODULE userModule = GetModuleHandle("user32.dll"); - m_ToUnicodeEx = (ToUnicodeEx_t)GetProcAddress(userModule, "ToUnicodeEx"); -} - -CMSWindowsKeyState::~CMSWindowsKeyState() -{ - disable(); -} - -void -CMSWindowsKeyState::disable() -{ - if (m_fixTimer != NULL) { - EVENTQUEUE->removeHandler(CEvent::kTimer, m_fixTimer); - EVENTQUEUE->deleteTimer(m_fixTimer); - m_fixTimer = NULL; - } - m_lastDown = 0; -} - -KeyButton -CMSWindowsKeyState::virtualKeyToButton(UINT virtualKey) const -{ - return m_virtualKeyToButton[virtualKey & 0xffu]; -} - -void -CMSWindowsKeyState::setKeyLayout(HKL keyLayout) -{ - m_keyLayout = keyLayout; -} - -bool -CMSWindowsKeyState::testAutoRepeat(bool press, bool isRepeat, KeyButton button) -{ - if (!isRepeat) { - isRepeat = (press && m_lastDown != 0 && button == m_lastDown); - } - if (press) { - m_lastDown = button; - } - else { - m_lastDown = 0; - } - return isRepeat; -} - -void -CMSWindowsKeyState::saveModifiers() -{ - m_savedModifiers = getActiveModifiers(); - m_originalSavedModifiers = m_savedModifiers; -} - -void -CMSWindowsKeyState::useSavedModifiers(bool enable) -{ - if (enable != m_useSavedModifiers) { - m_useSavedModifiers = enable; - if (!m_useSavedModifiers) { - // transfer any modifier state changes to CKeyState's state - KeyModifierMask mask = m_originalSavedModifiers ^ m_savedModifiers; - getActiveModifiersRValue() = - (getActiveModifiers() & ~mask) | (m_savedModifiers & mask); - } - } -} - -KeyID -CMSWindowsKeyState::mapKeyFromEvent(WPARAM charAndVirtKey, - LPARAM info, KeyModifierMask* maskOut) const -{ - static const KeyModifierMask s_controlAlt = - KeyModifierControl | KeyModifierAlt; - - // extract character, virtual key, and if we didn't use AltGr - char c = (char)((charAndVirtKey & 0xff00u) >> 8); - UINT vkCode = (charAndVirtKey & 0xffu); - bool noAltGr = ((charAndVirtKey & 0xff0000u) != 0); - - // handle some keys via table lookup - KeyID id = getKeyID(vkCode, (KeyButton)((info >> 16) & 0x1ffu)); - - // check if not in table; map character to key id - if (id == kKeyNone && c != 0) { - if ((c & 0x80u) == 0) { - // ASCII - id = static_cast(c) & 0xffu; - } - else { - // character is not really ASCII. instead it's some - // character in the current ANSI code page. try to - // convert that to a Unicode character. if we fail - // then use the single byte character as is. - char src = c; - wchar_t unicode; - if (MultiByteToWideChar(CP_THREAD_ACP, MB_PRECOMPOSED, - &src, 1, &unicode, 1) > 0) { - id = static_cast(unicode); - } - else { - id = static_cast(c) & 0xffu; - } - } - } - - // set modifier mask - if (maskOut != NULL) { - KeyModifierMask active = getActiveModifiers(); - if (!noAltGr && (active & s_controlAlt) == s_controlAlt) { - // if !noAltGr then we're only interested in matching the - // key, not the AltGr. AltGr is down (i.e. control and alt - // are down) but we don't want the client to have to match - // that so we clear it. - active &= ~s_controlAlt; - } - *maskOut = active; - } - - return id; -} - -bool -CMSWindowsKeyState::didGroupsChange() const -{ - GroupList groups; - return (getGroups(groups) && groups != m_groups); -} - -UINT -CMSWindowsKeyState::mapKeyToVirtualKey(KeyID key) const -{ - if (key == kKeyNone) { - return 0; - } - KeyToVKMap::const_iterator i = m_keyToVKMap.find(key); - if (i == m_keyToVKMap.end()) { - return 0; - } - else { - return i->second; - } -} - -void -CMSWindowsKeyState::onKey(KeyButton button, bool down, KeyModifierMask newState) -{ - // handle win32 brokenness and forward to superclass - fixKeys(); - CKeyState::onKey(button, down, newState); - fixKeys(); -} - -void -CMSWindowsKeyState::sendKeyEvent(void* target, - bool press, bool isAutoRepeat, - KeyID key, KeyModifierMask mask, - SInt32 count, KeyButton button) -{ - if (press || isAutoRepeat) { - // send key - if (press && !isAutoRepeat) { - CKeyState::sendKeyEvent(target, true, false, - key, mask, 1, button); - if (count > 0) { - --count; - } - } - if (count >= 1) { - CKeyState::sendKeyEvent(target, true, true, - key, mask, count, button); - } - } - else { - // do key up - CKeyState::sendKeyEvent(target, false, false, key, mask, 1, button); - } -} - -void -CMSWindowsKeyState::fakeKeyDown(KeyID id, KeyModifierMask mask, - KeyButton button) -{ - CKeyState::fakeKeyDown(id, mask, button); -} - -void -CMSWindowsKeyState::fakeKeyRepeat(KeyID id, KeyModifierMask mask, - SInt32 count, KeyButton button) -{ - CKeyState::fakeKeyRepeat(id, mask, count, button); -} - -bool -CMSWindowsKeyState::fakeCtrlAltDel() -{ - if (!m_is95Family) { - // to fake ctrl+alt+del on the NT family we broadcast a suitable - // hotkey to all windows on the winlogon desktop. however, the - // current thread must be on that desktop to do the broadcast - // and we can't switch just any thread because some own windows - // or hooks. so start a new thread to do the real work. - CThread cad(new CFunctionJob(&CMSWindowsKeyState::ctrlAltDelThread)); - cad.wait(); - } - else { - // simulate ctrl+alt+del - fakeKeyDown(kKeyDelete, KeyModifierControl | KeyModifierAlt, - virtualKeyToButton(VK_DELETE)); - } - return true; -} - -void -CMSWindowsKeyState::ctrlAltDelThread(void*) -{ - // get the Winlogon desktop at whatever privilege we can - HDESK desk = OpenDesktop("Winlogon", 0, FALSE, MAXIMUM_ALLOWED); - if (desk != NULL) { - if (SetThreadDesktop(desk)) { - PostMessage(HWND_BROADCAST, WM_HOTKEY, 0, - MAKELPARAM(MOD_CONTROL | MOD_ALT, VK_DELETE)); - } - else { - LOG((CLOG_DEBUG "can't switch to Winlogon desk: %d", GetLastError())); - } - CloseDesktop(desk); - } - else { - LOG((CLOG_DEBUG "can't open Winlogon desk: %d", GetLastError())); - } -} - -KeyModifierMask -CMSWindowsKeyState::pollActiveModifiers() const -{ - KeyModifierMask state = 0; - - // get non-toggle modifiers from our own shadow key state - for (size_t i = 0; i < sizeof(s_modifiers) / sizeof(s_modifiers[0]); ++i) { - KeyButton button = virtualKeyToButton(s_modifiers[i].m_vk); - if (button != 0 && isKeyDown(button)) { - state |= s_modifiers[i].m_mask; - } - } - - // we can get toggle modifiers from the system - if ((GetKeyState(VK_CAPITAL) & 0x01) != 0) { - state |= KeyModifierCapsLock; - } - if ((GetKeyState(VK_NUMLOCK) & 0x01) != 0) { - state |= KeyModifierNumLock; - } - if ((GetKeyState(VK_SCROLL) & 0x01) != 0) { - state |= KeyModifierScrollLock; - } - - return state; -} - -SInt32 -CMSWindowsKeyState::pollActiveGroup() const -{ - // determine the thread that'll receive this event - HWND targetWindow = GetForegroundWindow(); - DWORD targetThread = GetWindowThreadProcessId(targetWindow, NULL); - - // get keyboard layout for the thread - HKL hkl = GetKeyboardLayout(targetThread); - - // get group - GroupMap::const_iterator i = m_groupMap.find(hkl); - if (i == m_groupMap.end()) { - LOG((CLOG_DEBUG1 "can't find keyboard layout %08x", hkl)); - return 0; - } - - return i->second; -} - -void -CMSWindowsKeyState::pollPressedKeys(KeyButtonSet& pressedKeys) const -{ - BYTE keyState[256]; - GetKeyboardState(keyState); - for (KeyButton i = 1; i < 256; ++i) { - if ((keyState[i] & 0x80) != 0) { - pressedKeys.insert(i); - } - } -} - -void -CMSWindowsKeyState::getKeyMap(CKeyMap& keyMap) -{ - // update keyboard groups - if (getGroups(m_groups)) { - m_groupMap.clear(); - SInt32 numGroups = (SInt32)m_groups.size(); - for (SInt32 g = 0; g < numGroups; ++g) { - m_groupMap[m_groups[g]] = g; - } - } - HKL activeLayout = GetKeyboardLayout(0); - - // clear table - memset(m_virtualKeyToButton, 0, sizeof(m_virtualKeyToButton)); - m_keyToVKMap.clear(); - - CKeyMap::KeyItem item; - SInt32 numGroups = (SInt32)m_groups.size(); - for (SInt32 g = 0; g < numGroups; ++g) { - item.m_group = g; - ActivateKeyboardLayout(m_groups[g], 0); - - // clear tables - memset(m_buttonToVK, 0, sizeof(m_buttonToVK)); - memset(m_buttonToNumpadVK, 0, sizeof(m_buttonToNumpadVK)); - - // map buttons (scancodes) to virtual keys - for (KeyButton i = 1; i < 256; ++i) { - UINT vk = MapVirtualKey(i, 1); - if (vk == 0) { - // unmapped - continue; - } - - // deal with certain virtual keys specially - switch (vk) { - case VK_SHIFT: - if (MapVirtualKey(VK_RSHIFT, 0) == i) { - vk = VK_RSHIFT; - } - else { - vk = VK_LSHIFT; - } - break; - - case VK_CONTROL: - vk = VK_LCONTROL; - break; - - case VK_MENU: - vk = VK_LMENU; - break; - - case VK_NUMLOCK: - vk = VK_PAUSE; - break; - - case VK_NUMPAD0: - case VK_NUMPAD1: - case VK_NUMPAD2: - case VK_NUMPAD3: - case VK_NUMPAD4: - case VK_NUMPAD5: - case VK_NUMPAD6: - case VK_NUMPAD7: - case VK_NUMPAD8: - case VK_NUMPAD9: - case VK_DECIMAL: - // numpad keys are saved in their own table - m_buttonToNumpadVK[i] = vk; - continue; - - case VK_LWIN: - case VK_RWIN: - // add extended key only for these on 95 family - if (m_is95Family) { - m_buttonToVK[i | 0x100u] = vk; - continue; - } - break; - - case VK_RETURN: - case VK_PRIOR: - case VK_NEXT: - case VK_END: - case VK_HOME: - case VK_LEFT: - case VK_UP: - case VK_RIGHT: - case VK_DOWN: - case VK_INSERT: - case VK_DELETE: - // also add extended key for these - m_buttonToVK[i | 0x100u] = vk; - break; - } - - if (m_buttonToVK[i] == 0) { - m_buttonToVK[i] = vk; - } - } - - // now map virtual keys to buttons. multiple virtual keys may map - // to a single button. if the virtual key matches the one in - // m_buttonToVK then we use the button as is. if not then it's - // either a numpad key and we use the button as is or it's an - // extended button. - for (UINT i = 1; i < 255; ++i) { - // skip virtual keys we don't want - switch (i) { - case VK_LBUTTON: - case VK_RBUTTON: - case VK_MBUTTON: - case VK_XBUTTON1: - case VK_XBUTTON2: - case VK_SHIFT: - case VK_CONTROL: - case VK_MENU: - continue; - } - - // get the button - KeyButton button = static_cast(MapVirtualKey(i, 0)); - if (button == 0) { - continue; - } - - // deal with certain virtual keys specially - switch (i) { - case VK_NUMPAD0: - case VK_NUMPAD1: - case VK_NUMPAD2: - case VK_NUMPAD3: - case VK_NUMPAD4: - case VK_NUMPAD5: - case VK_NUMPAD6: - case VK_NUMPAD7: - case VK_NUMPAD8: - case VK_NUMPAD9: - case VK_DECIMAL: - m_buttonToNumpadVK[button] = i; - break; - - default: - // add extended key if virtual keys don't match - if (m_buttonToVK[button] != i) { - m_buttonToVK[button | 0x100u] = i; - } - break; - } - } - - // add alt+printscreen - if (m_buttonToVK[0x54u] == 0) { - m_buttonToVK[0x54u] = VK_SNAPSHOT; - } - - // set virtual key to button table - if (GetKeyboardLayout(0) == m_groups[g]) { - for (KeyButton i = 0; i < 512; ++i) { - if (m_buttonToVK[i] != 0) { - if (m_virtualKeyToButton[m_buttonToVK[i]] == 0) { - m_virtualKeyToButton[m_buttonToVK[i]] = i; - } - } - if (m_buttonToNumpadVK[i] != 0) { - if (m_virtualKeyToButton[m_buttonToNumpadVK[i]] == 0) { - m_virtualKeyToButton[m_buttonToNumpadVK[i]] = i; - } - } - } - } - - // add numpad keys - for (KeyButton i = 0; i < 512; ++i) { - if (m_buttonToNumpadVK[i] != 0) { - item.m_id = getKeyID(m_buttonToNumpadVK[i], i); - item.m_button = i; - item.m_required = KeyModifierNumLock; - item.m_sensitive = KeyModifierNumLock | KeyModifierShift; - item.m_generates = 0; - item.m_client = m_buttonToNumpadVK[i]; - addKeyEntry(keyMap, item); - } - } - - // add other keys - BYTE keys[256]; - memset(keys, 0, sizeof(keys)); - for (KeyButton i = 0; i < 512; ++i) { - if (m_buttonToVK[i] != 0) { - // initialize item - item.m_id = getKeyID(m_buttonToVK[i], i); - item.m_button = i; - item.m_required = 0; - item.m_sensitive = 0; - item.m_client = m_buttonToVK[i]; - - // get flags for modifier keys - CKeyMap::initModifierKey(item); - - if (item.m_id == 0) { - // translate virtual key to a character with and without - // shift, caps lock, and AltGr. - struct Modifier { - UINT m_vk1; - UINT m_vk2; - BYTE m_state; - KeyModifierMask m_mask; - }; - static const Modifier modifiers[] = { - { VK_SHIFT, VK_SHIFT, 0x80u, KeyModifierShift }, - { VK_CAPITAL, VK_CAPITAL, 0x01u, KeyModifierCapsLock }, - { VK_CONTROL, VK_MENU, 0x80u, KeyModifierControl | - KeyModifierAlt } - }; - static const size_t s_numModifiers = - sizeof(modifiers) / sizeof(modifiers[0]); - static const size_t s_numCombinations = 1 << s_numModifiers; - KeyID id[s_numCombinations]; - - bool anyFound = false; - KeyButton button = static_cast(i & 0xffu); - for (size_t j = 0; j < s_numCombinations; ++j) { - for (size_t k = 0; k < s_numModifiers; ++k) { - if ((j & (1 << k)) != 0) { - keys[modifiers[k].m_vk1] = modifiers[k].m_state; - keys[modifiers[k].m_vk2] = modifiers[k].m_state; - } - else { - keys[modifiers[k].m_vk1] = 0; - keys[modifiers[k].m_vk2] = 0; - } - } - id[j] = getIDForKey(item, button, - m_buttonToVK[i], keys, m_groups[g]); - if (id[j] != 0) { - anyFound = true; - } - } - - if (anyFound) { - // determine what modifiers we're sensitive to. - // we're sensitive if the KeyID changes when the - // modifier does. - item.m_sensitive = 0; - for (size_t k = 0; k < s_numModifiers; ++k) { - for (size_t j = 0; j < s_numCombinations; ++j) { - if (id[j] != id[j ^ (1u << k)]) { - item.m_sensitive |= modifiers[k].m_mask; - break; - } - } - } - - // save each key. the map will automatically discard - // duplicates, like an unshift and shifted version of - // a key that's insensitive to shift. - for (size_t j = 0; j < s_numCombinations; ++j) { - item.m_id = id[j]; - item.m_required = 0; - for (size_t k = 0; k < s_numModifiers; ++k) { - if ((j & (1 << k)) != 0) { - item.m_required |= modifiers[k].m_mask; - } - } - addKeyEntry(keyMap, item); - } - } - } - else { - // found in table - switch (m_buttonToVK[i]) { - case VK_TAB: - // add kKeyLeftTab, too - item.m_id = kKeyLeftTab; - item.m_required |= KeyModifierShift; - item.m_sensitive |= KeyModifierShift; - addKeyEntry(keyMap, item); - item.m_id = kKeyTab; - item.m_required &= ~KeyModifierShift; - break; - - case VK_CANCEL: - item.m_required |= KeyModifierControl; - item.m_sensitive |= KeyModifierControl; - break; - - case VK_SNAPSHOT: - item.m_sensitive |= KeyModifierAlt; - if ((i & 0x100u) == 0) { - // non-extended snapshot key requires alt - item.m_required |= KeyModifierAlt; - } - break; - } - addKeyEntry(keyMap, item); - } - } - } - } - - // restore keyboard layout - ActivateKeyboardLayout(activeLayout, 0); -} - -void -CMSWindowsKeyState::fakeKey(const Keystroke& keystroke) -{ - switch (keystroke.m_type) { - case Keystroke::kButton: { - LOG((CLOG_DEBUG1 " %03x (%08x) %s", keystroke.m_data.m_button.m_button, keystroke.m_data.m_button.m_client, keystroke.m_data.m_button.m_press ? "down" : "up")); - KeyButton button = keystroke.m_data.m_button.m_button; - - // windows doesn't send key ups for key repeats - if (keystroke.m_data.m_button.m_repeat && - !keystroke.m_data.m_button.m_press) { - LOG((CLOG_DEBUG1 " discard key repeat release")); - break; - } - - // get the virtual key for the button - UINT vk = keystroke.m_data.m_button.m_client; - - // special handling of VK_SNAPSHOT - if (vk == VK_SNAPSHOT) { - if ((getActiveModifiers() & KeyModifierAlt) != 0) { - // snapshot active window - button = 1; - } - else { - // snapshot full screen - button = 0; - } - } - - // synthesize event - m_desks->fakeKeyEvent(button, vk, - keystroke.m_data.m_button.m_press, - keystroke.m_data.m_button.m_repeat); - break; - } - - case Keystroke::kGroup: - // we don't restore the group. we'd like to but we can't be - // sure the restoring group change will be processed after the - // key events. - if (!keystroke.m_data.m_group.m_restore) { - if (keystroke.m_data.m_group.m_absolute) { - LOG((CLOG_DEBUG1 " group %d", keystroke.m_data.m_group.m_group)); - setWindowGroup(keystroke.m_data.m_group.m_group); - } - else { - LOG((CLOG_DEBUG1 " group %+d", keystroke.m_data.m_group.m_group)); - setWindowGroup(getEffectiveGroup(pollActiveGroup(), - keystroke.m_data.m_group.m_group)); - } - } - break; - } -} - -KeyModifierMask& -CMSWindowsKeyState::getActiveModifiersRValue() -{ - if (m_useSavedModifiers) { - return m_savedModifiers; - } - else { - return CKeyState::getActiveModifiersRValue(); - } -} - -bool -CMSWindowsKeyState::getGroups(GroupList& groups) const -{ - // get keyboard layouts - UInt32 newNumLayouts = GetKeyboardLayoutList(0, NULL); - if (newNumLayouts == 0) { - LOG((CLOG_DEBUG1 "can't get keyboard layouts")); - return false; - } - HKL* newLayouts = new HKL[newNumLayouts]; - newNumLayouts = GetKeyboardLayoutList(newNumLayouts, newLayouts); - if (newNumLayouts == 0) { - LOG((CLOG_DEBUG1 "can't get keyboard layouts")); - delete[] newLayouts; - return false; - } - - groups.clear(); - groups.insert(groups.end(), newLayouts, newLayouts + newNumLayouts); - delete[] newLayouts; - return true; -} - -void -CMSWindowsKeyState::setWindowGroup(SInt32 group) -{ - HWND targetWindow = GetForegroundWindow(); - - bool sysCharSet = true; - // XXX -- determine if m_groups[group] can be used with the system - // character set. - - PostMessage(targetWindow, WM_INPUTLANGCHANGEREQUEST, - sysCharSet ? 1 : 0, (LPARAM)m_groups[group]); - - // XXX -- use a short delay to let the target window process the message - // before it sees the keyboard events. i'm not sure why this is - // necessary since the messages should arrive in order. if we don't - // delay, though, some of our keyboard events may disappear. - Sleep(100); -} - -void -CMSWindowsKeyState::fixKeys() -{ - // fake key releases for the windows keys if we think they're - // down but they're really up. we have to do this because if the - // user presses and releases a windows key without pressing any - // other key while it's down then the system will eat the key - // release. if we don't detect that and synthesize the release - // then the client won't take the usual windows key release action - // (which on windows is to show the start menu). - // - // only check on the windows 95 family since the NT family reports - // the key releases as usual. - if (!m_is95Family) { - return; - } - - KeyButton leftButton = virtualKeyToButton(VK_LWIN); - KeyButton rightButton = virtualKeyToButton(VK_RWIN); - bool leftDown = isKeyDown(leftButton); - bool rightDown = isKeyDown(rightButton); - bool fix = (leftDown || rightDown); - if (fix) { - // check if either button is not really down - bool leftAsyncDown = ((GetAsyncKeyState(VK_LWIN) & 0x8000) != 0); - bool rightAsyncDown = ((GetAsyncKeyState(VK_RWIN) & 0x8000) != 0); - - if (leftAsyncDown != leftDown || rightAsyncDown != rightDown) { - KeyModifierMask state = getActiveModifiers(); - if (!leftAsyncDown && !rightAsyncDown) { - // no win keys are down so remove super modifier - state &= ~KeyModifierSuper; - } - - // report up events - if (leftDown && !leftAsyncDown) { - LOG((CLOG_DEBUG1 "event: fake key release left windows key (0x%03x)", leftButton)); - CKeyState::onKey(leftButton, false, state); - CKeyState::sendKeyEvent(m_eventTarget, false, false, - kKeySuper_L, state, 1, leftButton); - } - if (rightDown && !rightAsyncDown) { - LOG((CLOG_DEBUG1 "event: fake key release right windows key (0x%03x)", rightButton)); - CKeyState::onKey(rightButton, false, state); - CKeyState::sendKeyEvent(m_eventTarget, false, false, - kKeySuper_R, state, 1, rightButton); - } - } - } - - if (fix && m_fixTimer == NULL) { - // schedule check - m_fixTimer = EVENTQUEUE->newTimer(0.1, NULL); - EVENTQUEUE->adoptHandler(CEvent::kTimer, m_fixTimer, - new TMethodEventJob( - this, &CMSWindowsKeyState::handleFixKeys)); - } - else if (!fix && m_fixTimer != NULL) { - // remove scheduled check - EVENTQUEUE->removeHandler(CEvent::kTimer, m_fixTimer); - EVENTQUEUE->deleteTimer(m_fixTimer); - m_fixTimer = NULL; - } -} - -void -CMSWindowsKeyState::handleFixKeys(const CEvent&, void*) -{ - fixKeys(); -} - -KeyID -CMSWindowsKeyState::getKeyID(UINT virtualKey, KeyButton button) -{ - if ((button & 0x100u) != 0) { - virtualKey += 0x100u; - } - return s_virtualKey[virtualKey]; -} - -KeyID -CMSWindowsKeyState::getIDForKey(CKeyMap::KeyItem& item, - KeyButton button, UINT virtualKey, - PBYTE keyState, HKL hkl) const -{ - int n; - KeyID id; - if (m_is95Family) { - // XXX -- how do we get characters not in Latin-1? - WORD ascii; - n = ToAsciiEx(virtualKey, button, keyState, &ascii, 0, hkl); - id = static_cast(ascii & 0xffu); - } - else { - WCHAR unicode[2]; - n = m_ToUnicodeEx(virtualKey, button, keyState, - unicode, sizeof(unicode) / sizeof(unicode[0]), - 0, hkl); - id = static_cast(unicode[0]); - } - switch (n) { - case -1: - return CKeyMap::getDeadKey(id); - - default: - case 0: - // unmapped - return kKeyNone; - - case 1: - return id; - - case 2: - // left over dead key in buffer; oops. - return getIDForKey(item, button, virtualKey, keyState, hkl); - } -} - -void -CMSWindowsKeyState::addKeyEntry(CKeyMap& keyMap, CKeyMap::KeyItem& item) -{ - keyMap.addKeyEntry(item); - if (item.m_group == 0) { - m_keyToVKMap[item.m_id] = static_cast(item.m_client); - } -} diff --git a/lib/platform/CMSWindowsKeyState.h b/lib/platform/CMSWindowsKeyState.h deleted file mode 100644 index d8320a58..00000000 --- a/lib/platform/CMSWindowsKeyState.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CMSWINDOWSKEYSTATE_H -#define CMSWINDOWSKEYSTATE_H - -#include "CKeyState.h" -#include "CString.h" -#include "stdvector.h" -#define WIN32_LEAN_AND_MEAN -#include - -class CEvent; -class CEventQueueTimer; -class CMSWindowsDesks; - -//! Microsoft Windows key mapper -/*! -This class maps KeyIDs to keystrokes. -*/ -class CMSWindowsKeyState : public CKeyState { -public: - CMSWindowsKeyState(CMSWindowsDesks* desks, void* eventTarget); - virtual ~CMSWindowsKeyState(); - - //! @name manipulators - //@{ - - //! Handle screen disabling - /*! - Called when screen is disabled. This is needed to deal with platform - brokenness. - */ - void disable(); - - //! Set the active keyboard layout - /*! - Uses \p keyLayout when querying the keyboard. - */ - void setKeyLayout(HKL keyLayout); - - //! Test and set autorepeat state - /*! - Returns true if the given button is autorepeating and updates internal - state. - */ - bool testAutoRepeat(bool press, bool isRepeat, KeyButton); - - //! Remember modifier state - /*! - Records the current non-toggle modifier state. - */ - void saveModifiers(); - - //! Set effective modifier state - /*! - Temporarily sets the non-toggle modifier state to those saved by the - last call to \c saveModifiers if \p enable is \c true. Restores the - modifier state to the current modifier state if \p enable is \c false. - This is for synthesizing keystrokes on the primary screen when the - cursor is on a secondary screen. When on a secondary screen we capture - all non-toggle modifier state, track the state internally and do not - pass it on. So if Alt+F1 synthesizes Alt+X we need to synthesize - not just X but also Alt, despite the fact that our internal modifier - state indicates Alt is down, because local apps never saw the Alt down - event. - */ - void useSavedModifiers(bool enable); - - //@} - //! @name accessors - //@{ - - //! Map a virtual key to a button - /*! - Returns the button for the \p virtualKey. - */ - KeyButton virtualKeyToButton(UINT virtualKey) const; - - //! Map key event to a key - /*! - Converts a key event into a KeyID and the shadow modifier state - to a modifier mask. - */ - KeyID mapKeyFromEvent(WPARAM charAndVirtKey, - LPARAM info, KeyModifierMask* maskOut) const; - - //! Check if keyboard groups have changed - /*! - Returns true iff the number or order of the keyboard groups have - changed since the last call to updateKeys(). - */ - bool didGroupsChange() const; - - //! Map key to virtual key - /*! - Returns the virtual key for key \p key or 0 if there's no such virtual - key. - */ - UINT mapKeyToVirtualKey(KeyID key) const; - - //! Map virtual key and button to KeyID - /*! - Returns the KeyID for virtual key \p virtualKey and button \p button - (button should include the extended key bit), or kKeyNone if there is - no such key. - */ - static KeyID getKeyID(UINT virtualKey, KeyButton button); - - //@} - - // IKeyState overrides - virtual void fakeKeyDown(KeyID id, KeyModifierMask mask, - KeyButton button); - virtual void fakeKeyRepeat(KeyID id, KeyModifierMask mask, - SInt32 count, KeyButton button); - virtual bool fakeCtrlAltDel(); - virtual KeyModifierMask - pollActiveModifiers() const; - virtual SInt32 pollActiveGroup() const; - virtual void pollPressedKeys(KeyButtonSet& pressedKeys) const; - - // CKeyState overrides - virtual void onKey(KeyButton button, bool down, - KeyModifierMask newState); - virtual void sendKeyEvent(void* target, - bool press, bool isAutoRepeat, - KeyID key, KeyModifierMask mask, - SInt32 count, KeyButton button); - -protected: - // CKeyState overrides - virtual void getKeyMap(CKeyMap& keyMap); - virtual void fakeKey(const Keystroke& keystroke); - virtual KeyModifierMask& - getActiveModifiersRValue(); - -private: - typedef std::vector GroupList; - - // send ctrl+alt+del hotkey event on NT family - static void ctrlAltDelThread(void*); - - bool getGroups(GroupList&) const; - void setWindowGroup(SInt32 group); - - void fixKeys(); - void handleFixKeys(const CEvent&, void*); - - KeyID getIDForKey(CKeyMap::KeyItem& item, - KeyButton button, UINT virtualKey, - PBYTE keyState, HKL hkl) const; - - void addKeyEntry(CKeyMap& keyMap, CKeyMap::KeyItem& item); - -private: - // not implemented - CMSWindowsKeyState(const CMSWindowsKeyState&); - CMSWindowsKeyState& operator=(const CMSWindowsKeyState&); - -private: - typedef std::map GroupMap; - typedef std::map KeyToVKMap; - - bool m_is95Family; - void* m_eventTarget; - CMSWindowsDesks* m_desks; - HKL m_keyLayout; - UINT m_buttonToVK[512]; - UINT m_buttonToNumpadVK[512]; - KeyButton m_virtualKeyToButton[256]; - KeyToVKMap m_keyToVKMap; - - // the timer used to check for fixing key state - CEventQueueTimer* m_fixTimer; - - // the groups (keyboard layouts) - GroupList m_groups; - GroupMap m_groupMap; - - // the last button that we generated a key down event for. this - // is zero if the last key event was a key up. we use this to - // synthesize key repeats since the low level keyboard hook can't - // tell us if an event is a key repeat. - KeyButton m_lastDown; - - // modifier tracking - bool m_useSavedModifiers; - KeyModifierMask m_savedModifiers; - KeyModifierMask m_originalSavedModifiers; - - // pointer to ToUnicodeEx. on win95 family this will be NULL. - typedef int (WINAPI *ToUnicodeEx_t)(UINT wVirtKey, - UINT wScanCode, - PBYTE lpKeyState, - LPWSTR pwszBuff, - int cchBuff, - UINT wFlags, - HKL dwhkl); - ToUnicodeEx_t m_ToUnicodeEx; - - static const KeyID s_virtualKey[]; -}; - -#endif diff --git a/lib/platform/CMSWindowsScreen.cpp b/lib/platform/CMSWindowsScreen.cpp deleted file mode 100644 index b000b477..00000000 --- a/lib/platform/CMSWindowsScreen.cpp +++ /dev/null @@ -1,1738 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CMSWindowsScreen.h" -#include "CMSWindowsClipboard.h" -#include "CMSWindowsDesks.h" -#include "CMSWindowsEventQueueBuffer.h" -#include "CMSWindowsKeyState.h" -#include "CMSWindowsScreenSaver.h" -#include "CClipboard.h" -#include "CKeyMap.h" -#include "XScreen.h" -#include "CLock.h" -#include "CThread.h" -#include "CFunctionJob.h" -#include "CLog.h" -#include "CString.h" -#include "CStringUtil.h" -#include "IEventQueue.h" -#include "TMethodEventJob.h" -#include "TMethodJob.h" -#include "CArch.h" -#include "CArchMiscWindows.h" -#include -#include - -// -// add backwards compatible multihead support (and suppress bogus warning). -// this isn't supported on MinGW yet AFAICT. -// -#if defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable: 4706) // assignment within conditional -#define COMPILE_MULTIMON_STUBS -#include -#pragma warning(pop) -#endif - -// X button stuff -#if !defined(WM_XBUTTONDOWN) -#define WM_XBUTTONDOWN 0x020B -#define WM_XBUTTONUP 0x020C -#define WM_XBUTTONDBLCLK 0x020D -#define WM_NCXBUTTONDOWN 0x00AB -#define WM_NCXBUTTONUP 0x00AC -#define WM_NCXBUTTONDBLCLK 0x00AD -#define MOUSEEVENTF_XDOWN 0x0080 -#define MOUSEEVENTF_XUP 0x0100 -#define XBUTTON1 0x0001 -#define XBUTTON2 0x0002 -#endif -#if !defined(VK_XBUTTON1) -#define VK_XBUTTON1 0x05 -#define VK_XBUTTON2 0x06 -#endif - -// WM_POWERBROADCAST stuff -#if !defined(PBT_APMRESUMEAUTOMATIC) -#define PBT_APMRESUMEAUTOMATIC 0x0012 -#endif - -// -// CMSWindowsScreen -// - -HINSTANCE CMSWindowsScreen::s_instance = NULL; -CMSWindowsScreen* CMSWindowsScreen::s_screen = NULL; - -CMSWindowsScreen::CMSWindowsScreen(bool isPrimary) : - m_isPrimary(isPrimary), - m_is95Family(CArchMiscWindows::isWindows95Family()), - m_isOnScreen(m_isPrimary), - m_class(0), - m_x(0), m_y(0), - m_w(0), m_h(0), - m_xCenter(0), m_yCenter(0), - m_multimon(false), - m_xCursor(0), m_yCursor(0), - m_sequenceNumber(0), - m_mark(0), - m_markReceived(0), - m_fixTimer(NULL), - m_keyLayout(NULL), - m_screensaver(NULL), - m_screensaverNotify(false), - m_screensaverActive(false), - m_window(NULL), - m_nextClipboardWindow(NULL), - m_ownClipboard(false), - m_desks(NULL), - m_hookLibrary(NULL), - m_init(NULL), - m_cleanup(NULL), - m_setSides(NULL), - m_setZone(NULL), - m_setMode(NULL), - m_keyState(NULL), - m_hasMouse(GetSystemMetrics(SM_MOUSEPRESENT) != 0), - m_showingMouse(false) -{ - assert(s_instance != NULL); - assert(s_screen == NULL); - - s_screen = this; - try { - if (m_isPrimary) { - m_hookLibrary = openHookLibrary("synrgyhk"); - } - m_screensaver = new CMSWindowsScreenSaver(); - m_desks = new CMSWindowsDesks(m_isPrimary, - m_hookLibrary, m_screensaver, - new TMethodJob(this, - &CMSWindowsScreen::updateKeysCB)); - m_keyState = new CMSWindowsKeyState(m_desks, getEventTarget()); - updateScreenShape(); - m_class = createWindowClass(); - m_window = createWindow(m_class, "Synergy"); - forceShowCursor(); - LOG((CLOG_DEBUG "screen shape: %d,%d %dx%d %s", m_x, m_y, m_w, m_h, m_multimon ? "(multi-monitor)" : "")); - LOG((CLOG_DEBUG "window is 0x%08x", m_window)); - } - catch (...) { - delete m_keyState; - delete m_desks; - delete m_screensaver; - destroyWindow(m_window); - destroyClass(m_class); - closeHookLibrary(m_hookLibrary); - s_screen = NULL; - throw; - } - - // install event handlers - EVENTQUEUE->adoptHandler(CEvent::kSystem, IEventQueue::getSystemTarget(), - new TMethodEventJob(this, - &CMSWindowsScreen::handleSystemEvent)); - - // install the platform event queue - EVENTQUEUE->adoptBuffer(new CMSWindowsEventQueueBuffer); -} - -CMSWindowsScreen::~CMSWindowsScreen() -{ - assert(s_screen != NULL); - - disable(); - EVENTQUEUE->adoptBuffer(NULL); - EVENTQUEUE->removeHandler(CEvent::kSystem, IEventQueue::getSystemTarget()); - delete m_keyState; - delete m_desks; - delete m_screensaver; - destroyWindow(m_window); - destroyClass(m_class); - closeHookLibrary(m_hookLibrary); - s_screen = NULL; -} - -void -CMSWindowsScreen::init(HINSTANCE instance) -{ - assert(s_instance == NULL); - assert(instance != NULL); - - s_instance = instance; -} - -HINSTANCE -CMSWindowsScreen::getInstance() -{ - return s_instance; -} - -void -CMSWindowsScreen::enable() -{ - assert(m_isOnScreen == m_isPrimary); - - // we need to poll some things to fix them - m_fixTimer = EVENTQUEUE->newTimer(1.0, NULL); - EVENTQUEUE->adoptHandler(CEvent::kTimer, m_fixTimer, - new TMethodEventJob(this, - &CMSWindowsScreen::handleFixes)); - - // install our clipboard snooper - m_nextClipboardWindow = SetClipboardViewer(m_window); - - // track the active desk and (re)install the hooks - m_desks->enable(); - - if (m_isPrimary) { - // set jump zones - m_setZone(m_x, m_y, m_w, m_h, getJumpZoneSize()); - - // watch jump zones - m_setMode(kHOOK_WATCH_JUMP_ZONE); - } - else { - // prevent the system from entering power saving modes. if - // it did we'd be forced to disconnect from the server and - // the server would not be able to wake us up. - CArchMiscWindows::addBusyState(CArchMiscWindows::kSYSTEM); - } -} - -void -CMSWindowsScreen::disable() -{ - // stop tracking the active desk - m_desks->disable(); - - if (m_isPrimary) { - // disable hooks - m_setMode(kHOOK_DISABLE); - - // enable special key sequences on win95 family - enableSpecialKeys(true); - } - else { - // allow the system to enter power saving mode - CArchMiscWindows::removeBusyState(CArchMiscWindows::kSYSTEM | - CArchMiscWindows::kDISPLAY); - } - - // tell key state - m_keyState->disable(); - - // stop snooping the clipboard - ChangeClipboardChain(m_window, m_nextClipboardWindow); - m_nextClipboardWindow = NULL; - - // uninstall fix timer - if (m_fixTimer != NULL) { - EVENTQUEUE->removeHandler(CEvent::kTimer, m_fixTimer); - EVENTQUEUE->deleteTimer(m_fixTimer); - m_fixTimer = NULL; - } - - m_isOnScreen = m_isPrimary; - forceShowCursor(); -} - -void -CMSWindowsScreen::enter() -{ - m_desks->enter(); - if (m_isPrimary) { - // enable special key sequences on win95 family - enableSpecialKeys(true); - - // watch jump zones - m_setMode(kHOOK_WATCH_JUMP_ZONE); - - // all messages prior to now are invalid - nextMark(); - } - - // now on screen - m_isOnScreen = true; - forceShowCursor(); -} - -bool -CMSWindowsScreen::leave() -{ - // get keyboard layout of foreground window. we'll use this - // keyboard layout for translating keys sent to clients. - HWND window = GetForegroundWindow(); - DWORD thread = GetWindowThreadProcessId(window, NULL); - m_keyLayout = GetKeyboardLayout(thread); - - // tell the key mapper about the keyboard layout - m_keyState->setKeyLayout(m_keyLayout); - - // tell desk that we're leaving and tell it the keyboard layout - m_desks->leave(m_keyLayout); - - if (m_isPrimary) { - // warp to center - warpCursor(m_xCenter, m_yCenter); - - // disable special key sequences on win95 family - enableSpecialKeys(false); - - // all messages prior to now are invalid - nextMark(); - - // remember the modifier state. this is the modifier state - // reflected in the internal keyboard state. - m_keyState->saveModifiers(); - - // capture events - m_setMode(kHOOK_RELAY_EVENTS); - } - - // now off screen - m_isOnScreen = false; - forceShowCursor(); - - return true; -} - -bool -CMSWindowsScreen::setClipboard(ClipboardID, const IClipboard* src) -{ - CMSWindowsClipboard dst(m_window); - if (src != NULL) { - // save clipboard data - return CClipboard::copy(&dst, src); - } - else { - // assert clipboard ownership - if (!dst.open(0)) { - return false; - } - dst.empty(); - dst.close(); - return true; - } -} - -void -CMSWindowsScreen::checkClipboards() -{ - // if we think we own the clipboard but we don't then somebody - // grabbed the clipboard on this screen without us knowing. - // tell the server that this screen grabbed the clipboard. - // - // this works around bugs in the clipboard viewer chain. - // sometimes NT will simply never send WM_DRAWCLIPBOARD - // messages for no apparent reason and rebooting fixes the - // problem. since we don't want a broken clipboard until the - // next reboot we do this double check. clipboard ownership - // won't be reflected on other screens until we leave but at - // least the clipboard itself will work. - if (m_ownClipboard && !CMSWindowsClipboard::isOwnedBySynergy()) { - LOG((CLOG_DEBUG "clipboard changed: lost ownership and no notification received")); - m_ownClipboard = false; - sendClipboardEvent(getClipboardGrabbedEvent(), kClipboardClipboard); - sendClipboardEvent(getClipboardGrabbedEvent(), kClipboardSelection); - } -} - -void -CMSWindowsScreen::openScreensaver(bool notify) -{ - assert(m_screensaver != NULL); - - m_screensaverNotify = notify; - if (m_screensaverNotify) { - m_desks->installScreensaverHooks(true); - } - else { - m_screensaver->disable(); - } -} - -void -CMSWindowsScreen::closeScreensaver() -{ - if (m_screensaver != NULL) { - if (m_screensaverNotify) { - m_desks->installScreensaverHooks(false); - } - else { - m_screensaver->enable(); - } - } - m_screensaverNotify = false; -} - -void -CMSWindowsScreen::screensaver(bool activate) -{ - assert(m_screensaver != NULL); - - if (activate) { - m_screensaver->activate(); - } - else { - m_screensaver->deactivate(); - } -} - -void -CMSWindowsScreen::resetOptions() -{ - m_desks->resetOptions(); -} - -void -CMSWindowsScreen::setOptions(const COptionsList& options) -{ - m_desks->setOptions(options); -} - -void -CMSWindowsScreen::setSequenceNumber(UInt32 seqNum) -{ - m_sequenceNumber = seqNum; -} - -bool -CMSWindowsScreen::isPrimary() const -{ - return m_isPrimary; -} - -void* -CMSWindowsScreen::getEventTarget() const -{ - return const_cast(this); -} - -bool -CMSWindowsScreen::getClipboard(ClipboardID, IClipboard* dst) const -{ - CMSWindowsClipboard src(m_window); - CClipboard::copy(dst, &src); - return true; -} - -void -CMSWindowsScreen::getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h) const -{ - assert(m_class != 0); - - x = m_x; - y = m_y; - w = m_w; - h = m_h; -} - -void -CMSWindowsScreen::getCursorPos(SInt32& x, SInt32& y) const -{ - m_desks->getCursorPos(x, y); -} - -void -CMSWindowsScreen::reconfigure(UInt32 activeSides) -{ - assert(m_isPrimary); - - LOG((CLOG_DEBUG "active sides: %x", activeSides)); - m_setSides(activeSides); -} - -void -CMSWindowsScreen::warpCursor(SInt32 x, SInt32 y) -{ - // warp mouse - warpCursorNoFlush(x, y); - - // remove all input events before and including warp - MSG msg; - while (PeekMessage(&msg, NULL, SYNERGY_MSG_INPUT_FIRST, - SYNERGY_MSG_INPUT_LAST, PM_REMOVE)) { - // do nothing - } - - // save position as last position - m_xCursor = x; - m_yCursor = y; -} - -UInt32 -CMSWindowsScreen::registerHotKey(KeyID key, KeyModifierMask mask) -{ - // only allow certain modifiers - if ((mask & ~(KeyModifierShift | KeyModifierControl | - KeyModifierAlt | KeyModifierSuper)) != 0) { - LOG((CLOG_WARN "could not map hotkey id=%04x mask=%04x", key, mask)); - return 0; - } - - // fail if no keys - if (key == kKeyNone && mask == 0) { - return 0; - } - - // convert to win32 - UINT modifiers = 0; - if ((mask & KeyModifierShift) != 0) { - modifiers |= MOD_SHIFT; - } - if ((mask & KeyModifierControl) != 0) { - modifiers |= MOD_CONTROL; - } - if ((mask & KeyModifierAlt) != 0) { - modifiers |= MOD_ALT; - } - if ((mask & KeyModifierSuper) != 0) { - modifiers |= MOD_WIN; - } - UINT vk = m_keyState->mapKeyToVirtualKey(key); - if (key != kKeyNone && vk == 0) { - // can't map key - LOG((CLOG_WARN "could not map hotkey id=%04x mask=%04x", key, mask)); - return 0; - } - - // choose hotkey id - UInt32 id; - if (!m_oldHotKeyIDs.empty()) { - id = m_oldHotKeyIDs.back(); - m_oldHotKeyIDs.pop_back(); - } - else { - id = m_hotKeys.size() + 1; - } - - // if this hot key has modifiers only then we'll handle it specially - bool err; - if (key == kKeyNone) { - // check if already registered - err = (m_hotKeyToIDMap.count(CHotKeyItem(vk, modifiers)) > 0); - } - else { - // register with OS - err = (RegisterHotKey(NULL, id, modifiers, vk) == 0); - } - - if (!err) { - m_hotKeys.insert(std::make_pair(id, CHotKeyItem(vk, modifiers))); - m_hotKeyToIDMap[CHotKeyItem(vk, modifiers)] = id; - } - else { - m_oldHotKeyIDs.push_back(id); - m_hotKeys.erase(id); - LOG((CLOG_WARN "failed to register hotkey %s (id=%04x mask=%04x)", CKeyMap::formatKey(key, mask).c_str(), key, mask)); - return 0; - } - - LOG((CLOG_DEBUG "registered hotkey %s (id=%04x mask=%04x) as id=%d", CKeyMap::formatKey(key, mask).c_str(), key, mask, id)); - return id; -} - -void -CMSWindowsScreen::unregisterHotKey(UInt32 id) -{ - // look up hotkey - HotKeyMap::iterator i = m_hotKeys.find(id); - if (i == m_hotKeys.end()) { - return; - } - - // unregister with OS - bool err; - if (i->second.getVirtualKey() != 0) { - err = !UnregisterHotKey(NULL, id); - } - else { - err = false; - } - if (err) { - LOG((CLOG_WARN "failed to unregister hotkey id=%d", id)); - } - else { - LOG((CLOG_DEBUG "unregistered hotkey id=%d", id)); - } - - // discard hot key from map and record old id for reuse - m_hotKeyToIDMap.erase(i->second); - m_hotKeys.erase(i); - m_oldHotKeyIDs.push_back(id); -} - -void -CMSWindowsScreen::fakeInputBegin() -{ - assert(m_isPrimary); - - if (!m_isOnScreen) { - m_keyState->useSavedModifiers(true); - } - m_desks->fakeInputBegin(); -} - -void -CMSWindowsScreen::fakeInputEnd() -{ - assert(m_isPrimary); - - m_desks->fakeInputEnd(); - if (!m_isOnScreen) { - m_keyState->useSavedModifiers(false); - } -} - -SInt32 -CMSWindowsScreen::getJumpZoneSize() const -{ - return 1; -} - -bool -CMSWindowsScreen::isAnyMouseButtonDown() const -{ - static const char* buttonToName[] = { - "", - "Left Button", - "Middle Button", - "Right Button", - "X Button 1", - "X Button 2" - }; - - for (UInt32 i = 1; i < sizeof(m_buttons) / sizeof(m_buttons[0]); ++i) { - if (m_buttons[i]) { - LOG((CLOG_DEBUG "locked by \"%s\"", buttonToName[i])); - return true; - } - } - - return false; -} - -void -CMSWindowsScreen::getCursorCenter(SInt32& x, SInt32& y) const -{ - x = m_xCenter; - y = m_yCenter; -} - -void -CMSWindowsScreen::fakeMouseButton(ButtonID id, bool press) const -{ - m_desks->fakeMouseButton(id, press); -} - -void -CMSWindowsScreen::fakeMouseMove(SInt32 x, SInt32 y) const -{ - m_desks->fakeMouseMove(x, y); -} - -void -CMSWindowsScreen::fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const -{ - m_desks->fakeMouseRelativeMove(dx, dy); -} - -void -CMSWindowsScreen::fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const -{ - m_desks->fakeMouseWheel(xDelta, yDelta); -} - -void -CMSWindowsScreen::updateKeys() -{ - m_desks->updateKeys(); -} - -void -CMSWindowsScreen::fakeKeyDown(KeyID id, KeyModifierMask mask, - KeyButton button) -{ - CPlatformScreen::fakeKeyDown(id, mask, button); - updateForceShowCursor(); -} - -void -CMSWindowsScreen::fakeKeyRepeat(KeyID id, KeyModifierMask mask, - SInt32 count, KeyButton button) -{ - CPlatformScreen::fakeKeyRepeat(id, mask, count, button); - updateForceShowCursor(); -} - -void -CMSWindowsScreen::fakeKeyUp(KeyButton button) -{ - CPlatformScreen::fakeKeyUp(button); - updateForceShowCursor(); -} - -void -CMSWindowsScreen::fakeAllKeysUp() -{ - CPlatformScreen::fakeAllKeysUp(); - updateForceShowCursor(); -} - -HINSTANCE -CMSWindowsScreen::openHookLibrary(const char* name) -{ - // load the hook library - HINSTANCE hookLibrary = LoadLibrary(name); - if (hookLibrary == NULL) { - LOG((CLOG_ERR "Failed to load hook library; %s.dll is missing", name)); - throw XScreenOpenFailure(); - } - - // look up functions - m_setSides = (SetSidesFunc)GetProcAddress(hookLibrary, "setSides"); - m_setZone = (SetZoneFunc)GetProcAddress(hookLibrary, "setZone"); - m_setMode = (SetModeFunc)GetProcAddress(hookLibrary, "setMode"); - m_init = (InitFunc)GetProcAddress(hookLibrary, "init"); - m_cleanup = (CleanupFunc)GetProcAddress(hookLibrary, "cleanup"); - if (m_setSides == NULL || - m_setZone == NULL || - m_setMode == NULL || - m_init == NULL || - m_cleanup == NULL) { - LOG((CLOG_ERR "Invalid hook library; use a newer %s.dll", name)); - throw XScreenOpenFailure(); - } - - // initialize hook library - if (m_init(GetCurrentThreadId()) == 0) { - LOG((CLOG_ERR "Cannot initialize hook library; is synergy already running?")); - throw XScreenOpenFailure(); - } - - return hookLibrary; -} - -void -CMSWindowsScreen::closeHookLibrary(HINSTANCE hookLibrary) const -{ - if (hookLibrary != NULL) { - m_cleanup(); - FreeLibrary(hookLibrary); - } -} - -HCURSOR -CMSWindowsScreen::createBlankCursor() const -{ - // create a transparent cursor - int cw = GetSystemMetrics(SM_CXCURSOR); - int ch = GetSystemMetrics(SM_CYCURSOR); - UInt8* cursorAND = new UInt8[ch * ((cw + 31) >> 2)]; - UInt8* cursorXOR = new UInt8[ch * ((cw + 31) >> 2)]; - memset(cursorAND, 0xff, ch * ((cw + 31) >> 2)); - memset(cursorXOR, 0x00, ch * ((cw + 31) >> 2)); - HCURSOR c = CreateCursor(s_instance, 0, 0, cw, ch, cursorAND, cursorXOR); - delete[] cursorXOR; - delete[] cursorAND; - return c; -} - -void -CMSWindowsScreen::destroyCursor(HCURSOR cursor) const -{ - if (cursor != NULL) { - DestroyCursor(cursor); - } -} - -ATOM -CMSWindowsScreen::createWindowClass() const -{ - WNDCLASSEX classInfo; - classInfo.cbSize = sizeof(classInfo); - classInfo.style = CS_DBLCLKS | CS_NOCLOSE; - classInfo.lpfnWndProc = &CMSWindowsScreen::wndProc; - classInfo.cbClsExtra = 0; - classInfo.cbWndExtra = 0; - classInfo.hInstance = s_instance; - classInfo.hIcon = NULL; - classInfo.hCursor = NULL; - classInfo.hbrBackground = NULL; - classInfo.lpszMenuName = NULL; - classInfo.lpszClassName = "Synergy"; - classInfo.hIconSm = NULL; - return RegisterClassEx(&classInfo); -} - -void -CMSWindowsScreen::destroyClass(ATOM windowClass) const -{ - if (windowClass != 0) { - UnregisterClass(reinterpret_cast(windowClass), s_instance); - } -} - -HWND -CMSWindowsScreen::createWindow(ATOM windowClass, const char* name) const -{ - HWND window = CreateWindowEx(WS_EX_TOPMOST | - WS_EX_TRANSPARENT | - WS_EX_TOOLWINDOW, - reinterpret_cast(windowClass), - name, - WS_POPUP, - 0, 0, 1, 1, - NULL, NULL, - s_instance, - NULL); - if (window == NULL) { - LOG((CLOG_ERR "failed to create window: %d", GetLastError())); - throw XScreenOpenFailure(); - } - return window; -} - -void -CMSWindowsScreen::destroyWindow(HWND hwnd) const -{ - if (hwnd != NULL) { - DestroyWindow(hwnd); - } -} - -void -CMSWindowsScreen::sendEvent(CEvent::Type type, void* data) -{ - EVENTQUEUE->addEvent(CEvent(type, getEventTarget(), data)); -} - -void -CMSWindowsScreen::sendClipboardEvent(CEvent::Type type, ClipboardID id) -{ - CClipboardInfo* info = (CClipboardInfo*)malloc(sizeof(CClipboardInfo)); - info->m_id = id; - info->m_sequenceNumber = m_sequenceNumber; - sendEvent(type, info); -} - -void -CMSWindowsScreen::handleSystemEvent(const CEvent& event, void*) -{ - MSG* msg = reinterpret_cast(event.getData()); - assert(msg != NULL); - - if (CArchMiscWindows::processDialog(msg)) { - return; - } - if (onPreDispatch(msg->hwnd, msg->message, msg->wParam, msg->lParam)) { - return; - } - TranslateMessage(msg); - DispatchMessage(msg); -} - -void -CMSWindowsScreen::updateButtons() -{ - int numButtons = GetSystemMetrics(SM_CMOUSEBUTTONS); - m_buttons[kButtonNone] = false; - m_buttons[kButtonLeft] = (GetKeyState(VK_LBUTTON) < 0); - m_buttons[kButtonRight] = (GetKeyState(VK_RBUTTON) < 0); - m_buttons[kButtonMiddle] = (GetKeyState(VK_MBUTTON) < 0); - m_buttons[kButtonExtra0 + 0] = (numButtons >= 4) && - (GetKeyState(VK_XBUTTON1) < 0); - m_buttons[kButtonExtra0 + 1] = (numButtons >= 5) && - (GetKeyState(VK_XBUTTON2) < 0); -} - -IKeyState* -CMSWindowsScreen::getKeyState() const -{ - return m_keyState; -} - -bool -CMSWindowsScreen::onPreDispatch(HWND hwnd, - UINT message, WPARAM wParam, LPARAM lParam) -{ - // handle event - switch (message) { - case SYNERGY_MSG_SCREEN_SAVER: - return onScreensaver(wParam != 0); - - case SYNERGY_MSG_DEBUG: - LOG((CLOG_DEBUG1 "hook: 0x%08x 0x%08x", wParam, lParam)); - return true; - } - - if (m_isPrimary) { - return onPreDispatchPrimary(hwnd, message, wParam, lParam); - } - - return false; -} - -bool -CMSWindowsScreen::onPreDispatchPrimary(HWND, - UINT message, WPARAM wParam, LPARAM lParam) -{ - // handle event - switch (message) { - case SYNERGY_MSG_MARK: - return onMark(static_cast(wParam)); - - case SYNERGY_MSG_KEY: - return onKey(wParam, lParam); - - case SYNERGY_MSG_MOUSE_BUTTON: - return onMouseButton(wParam, lParam); - - case SYNERGY_MSG_MOUSE_MOVE: - return onMouseMove(static_cast(wParam), - static_cast(lParam)); - - case SYNERGY_MSG_MOUSE_WHEEL: - // XXX -- support x-axis scrolling - return onMouseWheel(0, static_cast(wParam)); - - case SYNERGY_MSG_PRE_WARP: - { - // save position to compute delta of next motion - m_xCursor = static_cast(wParam); - m_yCursor = static_cast(lParam); - - // we warped the mouse. discard events until we find the - // matching post warp event. see warpCursorNoFlush() for - // where the events are sent. we discard the matching - // post warp event and can be sure we've skipped the warp - // event. - MSG msg; - do { - GetMessage(&msg, NULL, SYNERGY_MSG_MOUSE_MOVE, - SYNERGY_MSG_POST_WARP); - } while (msg.message != SYNERGY_MSG_POST_WARP); - } - return true; - - case SYNERGY_MSG_POST_WARP: - LOG((CLOG_WARN "unmatched post warp")); - return true; - - case WM_HOTKEY: - // we discard these messages. we'll catch the hot key in the - // regular key event handling, where we can detect both key - // press and release. we only register the hot key so no other - // app will act on the key combination. - break; - } - - return false; -} - -bool -CMSWindowsScreen::onEvent(HWND, UINT msg, - WPARAM wParam, LPARAM lParam, LRESULT* result) -{ - switch (msg) { - case WM_QUERYENDSESSION: - if (m_is95Family) { - *result = TRUE; - return true; - } - break; - - case WM_ENDSESSION: - if (m_is95Family) { - if (wParam == TRUE && lParam == 0) { - EVENTQUEUE->addEvent(CEvent(CEvent::kQuit)); - } - return true; - } - break; - - case WM_DRAWCLIPBOARD: - // first pass on the message - if (m_nextClipboardWindow != NULL) { - SendMessage(m_nextClipboardWindow, msg, wParam, lParam); - } - - // now handle the message - return onClipboardChange(); - - case WM_CHANGECBCHAIN: - if (m_nextClipboardWindow == (HWND)wParam) { - m_nextClipboardWindow = (HWND)lParam; - LOG((CLOG_DEBUG "clipboard chain: new next: 0x%08x", m_nextClipboardWindow)); - } - else if (m_nextClipboardWindow != NULL) { - SendMessage(m_nextClipboardWindow, msg, wParam, lParam); - } - return true; - - case WM_DISPLAYCHANGE: - return onDisplayChange(); - - case WM_POWERBROADCAST: - switch (wParam) { - case PBT_APMRESUMEAUTOMATIC: - case PBT_APMRESUMECRITICAL: - case PBT_APMRESUMESUSPEND: - EVENTQUEUE->addEvent(CEvent(IScreen::getResumeEvent(), - getEventTarget(), NULL, - CEvent::kDeliverImmediately)); - break; - - case PBT_APMSUSPEND: - EVENTQUEUE->addEvent(CEvent(IScreen::getSuspendEvent(), - getEventTarget(), NULL, - CEvent::kDeliverImmediately)); - break; - } - *result = TRUE; - return true; - - case WM_DEVICECHANGE: - forceShowCursor(); - break; - - case WM_SETTINGCHANGE: - if (wParam == SPI_SETMOUSEKEYS) { - forceShowCursor(); - } - break; - } - - return false; -} - -bool -CMSWindowsScreen::onMark(UInt32 mark) -{ - m_markReceived = mark; - return true; -} - -bool -CMSWindowsScreen::onKey(WPARAM wParam, LPARAM lParam) -{ - static const KeyModifierMask s_ctrlAlt = - KeyModifierControl | KeyModifierAlt; - - LOG((CLOG_DEBUG1 "event: Key char=%d, vk=0x%02x, nagr=%d, lParam=0x%08x", (wParam & 0xff00u) >> 8, wParam & 0xffu, (wParam & 0x10000u) ? 1 : 0, lParam)); - - // get event info - KeyButton button = (KeyButton)((lParam & 0x01ff0000) >> 16); - bool down = ((lParam & 0x80000000u) == 0x00000000u); - bool wasDown = isKeyDown(button); - KeyModifierMask oldState = pollActiveModifiers(); - - // check for autorepeat - if (m_keyState->testAutoRepeat(down, (lParam & 0x40000000u) == 1, button)) { - lParam |= 0x40000000u; - } - - // if the button is zero then guess what the button should be. - // these are badly synthesized key events and logitech software - // that maps mouse buttons to keys is known to do this. - // alternatively, we could just throw these events out. - if (button == 0) { - button = m_keyState->virtualKeyToButton(wParam & 0xffu); - if (button == 0) { - return true; - } - wasDown = isKeyDown(button); - } - - // record keyboard state - m_keyState->onKey(button, down, oldState); - - // windows doesn't tell us the modifier key state on mouse or key - // events so we have to figure it out. most apps would use - // GetKeyState() or even GetAsyncKeyState() for that but we can't - // because our hook doesn't pass on key events for several modifiers. - // it can't otherwise the system would interpret them normally on - // the primary screen even when on a secondary screen. so tapping - // alt would activate menus and tapping the windows key would open - // the start menu. if you don't pass those events on in the hook - // then GetKeyState() understandably doesn't reflect the effect of - // the event. curiously, neither does GetAsyncKeyState(), which is - // surprising. - // - // so anyway, we have to track the modifier state ourselves for - // at least those modifiers we don't pass on. pollActiveModifiers() - // does that but we have to update the keyboard state before calling - // pollActiveModifiers() to get the right answer. but the only way - // to set the modifier state or to set the up/down state of a key - // is via onKey(). so we have to call onKey() twice. - KeyModifierMask state = pollActiveModifiers(); - m_keyState->onKey(button, down, state); - - // check for hot keys - if (oldState != state) { - // modifier key was pressed/released - if (onHotKey(0, lParam)) { - return true; - } - } - else { - // non-modifier was pressed/released - if (onHotKey(wParam, lParam)) { - return true; - } - } - - // ignore message if posted prior to last mark change - if (!ignore()) { - // check for ctrl+alt+del. we do not want to pass that to the - // client. the user can use ctrl+alt+pause to emulate it. - UINT virtKey = (wParam & 0xffu); - if (virtKey == VK_DELETE && (state & s_ctrlAlt) == s_ctrlAlt) { - LOG((CLOG_DEBUG "discard ctrl+alt+del")); - return true; - } - - // check for ctrl+alt+del emulation - if ((virtKey == VK_PAUSE || virtKey == VK_CANCEL) && - (state & s_ctrlAlt) == s_ctrlAlt) { - LOG((CLOG_DEBUG "emulate ctrl+alt+del")); - // switch wParam and lParam to be as if VK_DELETE was - // pressed or released. when mapping the key we require that - // we not use AltGr (the 0x10000 flag in wParam) and we not - // use the keypad delete key (the 0x01000000 flag in lParam). - wParam = VK_DELETE | 0x00010000u; - lParam &= 0xfe000000; - lParam |= m_keyState->virtualKeyToButton(wParam & 0xffu) << 16; - lParam |= 0x01000001; - } - - // process key - KeyModifierMask mask; - KeyID key = m_keyState->mapKeyFromEvent(wParam, lParam, &mask); - button = static_cast((lParam & 0x01ff0000u) >> 16); - if (key != kKeyNone) { - // fix key up. if the key isn't down according to - // our table then we never got the key press event - // for it. if it's not a modifier key then we'll - // synthesize the press first. only do this on - // the windows 95 family, which eats certain special - // keys like alt+tab, ctrl+esc, etc. - if (m_is95Family && !wasDown && !down) { - switch (virtKey) { - case VK_SHIFT: - case VK_LSHIFT: - case VK_RSHIFT: - case VK_CONTROL: - case VK_LCONTROL: - case VK_RCONTROL: - case VK_MENU: - case VK_LMENU: - case VK_RMENU: - case VK_LWIN: - case VK_RWIN: - case VK_CAPITAL: - case VK_NUMLOCK: - case VK_SCROLL: - break; - - default: - m_keyState->sendKeyEvent(getEventTarget(), - true, false, key, mask, 1, button); - break; - } - } - - // do it - m_keyState->sendKeyEvent(getEventTarget(), - ((lParam & 0x80000000u) == 0), - ((lParam & 0x40000000u) != 0), - key, mask, (SInt32)(lParam & 0xffff), button); - } - else { - LOG((CLOG_DEBUG1 "cannot map key")); - } - } - - return true; -} - -bool -CMSWindowsScreen::onHotKey(WPARAM wParam, LPARAM lParam) -{ - // get the key info - KeyModifierMask state = getActiveModifiers(); - UINT virtKey = (wParam & 0xffu); - UINT modifiers = 0; - if ((state & KeyModifierShift) != 0) { - modifiers |= MOD_SHIFT; - } - if ((state & KeyModifierControl) != 0) { - modifiers |= MOD_CONTROL; - } - if ((state & KeyModifierAlt) != 0) { - modifiers |= MOD_ALT; - } - if ((state & KeyModifierSuper) != 0) { - modifiers |= MOD_WIN; - } - - // find the hot key id - HotKeyToIDMap::const_iterator i = - m_hotKeyToIDMap.find(CHotKeyItem(virtKey, modifiers)); - if (i == m_hotKeyToIDMap.end()) { - return false; - } - - // find what kind of event - CEvent::Type type; - if ((lParam & 0x80000000u) == 0u) { - if ((lParam & 0x40000000u) != 0u) { - // ignore key repeats but it counts as a hot key - return true; - } - type = getHotKeyDownEvent(); - } - else { - type = getHotKeyUpEvent(); - } - - // generate event - EVENTQUEUE->addEvent(CEvent(type, getEventTarget(), - CHotKeyInfo::alloc(i->second))); - - return true; -} - -bool -CMSWindowsScreen::onMouseButton(WPARAM wParam, LPARAM lParam) -{ - // get which button - bool pressed = mapPressFromEvent(wParam, lParam); - ButtonID button = mapButtonFromEvent(wParam, lParam); - - // keep our shadow key state up to date - if (button >= kButtonLeft && button <= kButtonExtra0 + 1) { - if (pressed) { - m_buttons[button] = true; - } - else { - m_buttons[button] = false; - } - } - - // ignore message if posted prior to last mark change - if (!ignore()) { - KeyModifierMask mask = m_keyState->getActiveModifiers(); - if (pressed) { - LOG((CLOG_DEBUG1 "event: button press button=%d", button)); - if (button != kButtonNone) { - sendEvent(getButtonDownEvent(), - CButtonInfo::alloc(button, mask)); - } - } - else { - LOG((CLOG_DEBUG1 "event: button release button=%d", button)); - if (button != kButtonNone) { - sendEvent(getButtonUpEvent(), - CButtonInfo::alloc(button, mask)); - } - } - } - - return true; -} - -bool -CMSWindowsScreen::onMouseMove(SInt32 mx, SInt32 my) -{ - // compute motion delta (relative to the last known - // mouse position) - SInt32 x = mx - m_xCursor; - SInt32 y = my - m_yCursor; - - // ignore if the mouse didn't move or if message posted prior - // to last mark change. - if (ignore() || (x == 0 && y == 0)) { - return true; - } - - // save position to compute delta of next motion - m_xCursor = mx; - m_yCursor = my; - - if (m_isOnScreen) { - // motion on primary screen - sendEvent(getMotionOnPrimaryEvent(), - CMotionInfo::alloc(m_xCursor, m_yCursor)); - } - else { - // motion on secondary screen. warp mouse back to - // center. - warpCursorNoFlush(m_xCenter, m_yCenter); - - // examine the motion. if it's about the distance - // from the center of the screen to an edge then - // it's probably a bogus motion that we want to - // ignore (see warpCursorNoFlush() for a further - // description). - static SInt32 bogusZoneSize = 10; - if (-x + bogusZoneSize > m_xCenter - m_x || - x + bogusZoneSize > m_x + m_w - m_xCenter || - -y + bogusZoneSize > m_yCenter - m_y || - y + bogusZoneSize > m_y + m_h - m_yCenter) { - LOG((CLOG_DEBUG "dropped bogus motion %+d,%+d", x, y)); - } - else { - // send motion - sendEvent(getMotionOnSecondaryEvent(), CMotionInfo::alloc(x, y)); - } - } - - return true; -} - -bool -CMSWindowsScreen::onMouseWheel(SInt32 xDelta, SInt32 yDelta) -{ - // ignore message if posted prior to last mark change - if (!ignore()) { - LOG((CLOG_DEBUG1 "event: button wheel delta=%+d,%+d", xDelta, yDelta)); - sendEvent(getWheelEvent(), CWheelInfo::alloc(xDelta, yDelta)); - } - return true; -} - -bool -CMSWindowsScreen::onScreensaver(bool activated) -{ - // ignore this message if there are any other screen saver - // messages already in the queue. this is important because - // our checkStarted() function has a deliberate delay, so it - // can't respond to events at full CPU speed and will fall - // behind if a lot of screen saver events are generated. - // that can easily happen because windows will continually - // send SC_SCREENSAVE until the screen saver starts, even if - // the screen saver is disabled! - MSG msg; - if (PeekMessage(&msg, NULL, SYNERGY_MSG_SCREEN_SAVER, - SYNERGY_MSG_SCREEN_SAVER, PM_NOREMOVE)) { - return true; - } - - if (activated) { - if (!m_screensaverActive && - m_screensaver->checkStarted(SYNERGY_MSG_SCREEN_SAVER, FALSE, 0)) { - m_screensaverActive = true; - sendEvent(getScreensaverActivatedEvent()); - - // enable display power down - CArchMiscWindows::removeBusyState(CArchMiscWindows::kDISPLAY); - } - } - else { - if (m_screensaverActive) { - m_screensaverActive = false; - sendEvent(getScreensaverDeactivatedEvent()); - - // disable display power down - CArchMiscWindows::addBusyState(CArchMiscWindows::kDISPLAY); - } - } - - return true; -} - -bool -CMSWindowsScreen::onDisplayChange() -{ - // screen resolution may have changed. save old shape. - SInt32 xOld = m_x, yOld = m_y, wOld = m_w, hOld = m_h; - - // update shape - updateScreenShape(); - - // do nothing if resolution hasn't changed - if (xOld != m_x || yOld != m_y || wOld != m_w || hOld != m_h) { - if (m_isPrimary) { - // warp mouse to center if off screen - if (!m_isOnScreen) { - warpCursor(m_xCenter, m_yCenter); - } - - // tell hook about resize if on screen - else { - m_setZone(m_x, m_y, m_w, m_h, getJumpZoneSize()); - } - } - - // send new screen info - sendEvent(getShapeChangedEvent()); - - LOG((CLOG_DEBUG "screen shape: %d,%d %dx%d %s", m_x, m_y, m_w, m_h, m_multimon ? "(multi-monitor)" : "")); - } - - return true; -} - -bool -CMSWindowsScreen::onClipboardChange() -{ - // now notify client that somebody changed the clipboard (unless - // we're the owner). - if (!CMSWindowsClipboard::isOwnedBySynergy()) { - if (m_ownClipboard) { - LOG((CLOG_DEBUG "clipboard changed: lost ownership")); - m_ownClipboard = false; - sendClipboardEvent(getClipboardGrabbedEvent(), kClipboardClipboard); - sendClipboardEvent(getClipboardGrabbedEvent(), kClipboardSelection); - } - } - else if (!m_ownClipboard) { - LOG((CLOG_DEBUG "clipboard changed: synergy owned")); - m_ownClipboard = true; - } - - return true; -} - -void -CMSWindowsScreen::warpCursorNoFlush(SInt32 x, SInt32 y) -{ - // send an event that we can recognize before the mouse warp - PostThreadMessage(GetCurrentThreadId(), SYNERGY_MSG_PRE_WARP, x, y); - - // warp mouse. hopefully this inserts a mouse motion event - // between the previous message and the following message. - SetCursorPos(x, y); - - // yield the CPU. there's a race condition when warping: - // a hardware mouse event occurs - // the mouse hook is not called because that process doesn't have the CPU - // we send PRE_WARP, SetCursorPos(), send POST_WARP - // we process all of those events and update m_x, m_y - // we finish our time slice - // the hook is called - // the hook sends us a mouse event from the pre-warp position - // we get the CPU - // we compute a bogus warp - // we need the hook to process all mouse events that occur - // before we warp before we do the warp but i'm not sure how - // to guarantee that. yielding the CPU here may reduce the - // chance of undesired behavior. we'll also check for very - // large motions that look suspiciously like about half width - // or height of the screen. - ARCH->sleep(0.0); - - // send an event that we can recognize after the mouse warp - PostThreadMessage(GetCurrentThreadId(), SYNERGY_MSG_POST_WARP, 0, 0); -} - -void -CMSWindowsScreen::nextMark() -{ - // next mark - ++m_mark; - - // mark point in message queue where the mark was changed - PostThreadMessage(GetCurrentThreadId(), SYNERGY_MSG_MARK, m_mark, 0); -} - -bool -CMSWindowsScreen::ignore() const -{ - return (m_mark != m_markReceived); -} - -void -CMSWindowsScreen::updateScreenShape() -{ - // get shape - m_x = GetSystemMetrics(SM_XVIRTUALSCREEN); - m_y = GetSystemMetrics(SM_YVIRTUALSCREEN); - m_w = GetSystemMetrics(SM_CXVIRTUALSCREEN); - m_h = GetSystemMetrics(SM_CYVIRTUALSCREEN); - - // get center for cursor - m_xCenter = GetSystemMetrics(SM_CXSCREEN) >> 1; - m_yCenter = GetSystemMetrics(SM_CYSCREEN) >> 1; - - // check for multiple monitors - m_multimon = (m_w != GetSystemMetrics(SM_CXSCREEN) || - m_h != GetSystemMetrics(SM_CYSCREEN)); - - // tell the desks - m_desks->setShape(m_x, m_y, m_w, m_h, m_xCenter, m_yCenter, m_multimon); -} - -void -CMSWindowsScreen::handleFixes(const CEvent&, void*) -{ - // fix clipboard chain - fixClipboardViewer(); - - // update keys if keyboard layouts have changed - if (m_keyState->didGroupsChange()) { - updateKeys(); - } -} - -void -CMSWindowsScreen::fixClipboardViewer() -{ - // XXX -- disable this code for now. somehow it can cause an infinite - // recursion in the WM_DRAWCLIPBOARD handler. either we're sending - // the message to our own window or some window farther down the chain - // forwards the message to our window or a window farther up the chain. - // i'm not sure how that could happen. the m_nextClipboardWindow = NULL - // was not in the code that infinite loops and may fix the bug but i - // doubt it. -/* - ChangeClipboardChain(m_window, m_nextClipboardWindow); - m_nextClipboardWindow = NULL; - m_nextClipboardWindow = SetClipboardViewer(m_window); -*/ -} - -void -CMSWindowsScreen::enableSpecialKeys(bool enable) const -{ - // enable/disable ctrl+alt+del, alt+tab, etc on win95 family. - // since the win95 family doesn't support low-level hooks, we - // use this undocumented feature to suppress normal handling - // of certain key combinations. - if (m_is95Family) { - DWORD dummy = 0; - SystemParametersInfo(SPI_SETSCREENSAVERRUNNING, - enable ? FALSE : TRUE, &dummy, 0); - } -} - -ButtonID -CMSWindowsScreen::mapButtonFromEvent(WPARAM msg, LPARAM button) const -{ - switch (msg) { - case WM_LBUTTONDOWN: - case WM_LBUTTONDBLCLK: - case WM_LBUTTONUP: - case WM_NCLBUTTONDOWN: - case WM_NCLBUTTONDBLCLK: - case WM_NCLBUTTONUP: - return kButtonLeft; - - case WM_MBUTTONDOWN: - case WM_MBUTTONDBLCLK: - case WM_MBUTTONUP: - case WM_NCMBUTTONDOWN: - case WM_NCMBUTTONDBLCLK: - case WM_NCMBUTTONUP: - return kButtonMiddle; - - case WM_RBUTTONDOWN: - case WM_RBUTTONDBLCLK: - case WM_RBUTTONUP: - case WM_NCRBUTTONDOWN: - case WM_NCRBUTTONDBLCLK: - case WM_NCRBUTTONUP: - return kButtonRight; - - case WM_XBUTTONDOWN: - case WM_XBUTTONDBLCLK: - case WM_XBUTTONUP: - case WM_NCXBUTTONDOWN: - case WM_NCXBUTTONDBLCLK: - case WM_NCXBUTTONUP: - switch (button) { - case XBUTTON1: - if (GetSystemMetrics(SM_CMOUSEBUTTONS) >= 4) { - return kButtonExtra0 + 0; - } - break; - - case XBUTTON2: - if (GetSystemMetrics(SM_CMOUSEBUTTONS) >= 5) { - return kButtonExtra0 + 1; - } - break; - } - return kButtonNone; - - default: - return kButtonNone; - } -} - -bool -CMSWindowsScreen::mapPressFromEvent(WPARAM msg, LPARAM) const -{ - switch (msg) { - case WM_LBUTTONDOWN: - case WM_MBUTTONDOWN: - case WM_RBUTTONDOWN: - case WM_XBUTTONDOWN: - case WM_LBUTTONDBLCLK: - case WM_MBUTTONDBLCLK: - case WM_RBUTTONDBLCLK: - case WM_XBUTTONDBLCLK: - case WM_NCLBUTTONDOWN: - case WM_NCMBUTTONDOWN: - case WM_NCRBUTTONDOWN: - case WM_NCXBUTTONDOWN: - case WM_NCLBUTTONDBLCLK: - case WM_NCMBUTTONDBLCLK: - case WM_NCRBUTTONDBLCLK: - case WM_NCXBUTTONDBLCLK: - return true; - - case WM_LBUTTONUP: - case WM_MBUTTONUP: - case WM_RBUTTONUP: - case WM_XBUTTONUP: - case WM_NCLBUTTONUP: - case WM_NCMBUTTONUP: - case WM_NCRBUTTONUP: - case WM_NCXBUTTONUP: - return false; - - default: - return false; - } -} - -void -CMSWindowsScreen::updateKeysCB(void*) -{ - // record which keys we think are down - bool down[IKeyState::kNumButtons]; - bool sendFixes = (isPrimary() && !m_isOnScreen); - if (sendFixes) { - for (KeyButton i = 0; i < IKeyState::kNumButtons; ++i) { - down[i] = m_keyState->isKeyDown(i); - } - } - - // update layouts if necessary - if (m_keyState->didGroupsChange()) { - CPlatformScreen::updateKeyMap(); - } - - // now update the keyboard state - CPlatformScreen::updateKeyState(); - - // now see which keys we thought were down but now think are up. - // send key releases for these keys to the active client. - if (sendFixes) { - KeyModifierMask mask = pollActiveModifiers(); - for (KeyButton i = 0; i < IKeyState::kNumButtons; ++i) { - if (down[i] && !m_keyState->isKeyDown(i)) { - m_keyState->sendKeyEvent(getEventTarget(), - false, false, kKeyNone, mask, 1, i); - } - } - } -} - -void -CMSWindowsScreen::forceShowCursor() -{ - // check for mouse - m_hasMouse = (GetSystemMetrics(SM_MOUSEPRESENT) != 0); - - // decide if we should show the mouse - bool showMouse = (!m_hasMouse && !m_isPrimary && m_isOnScreen); - - // show/hide the mouse - if (showMouse != m_showingMouse) { - if (showMouse) { - m_oldMouseKeys.cbSize = sizeof(m_oldMouseKeys); - m_gotOldMouseKeys = - (SystemParametersInfo(SPI_GETMOUSEKEYS, - m_oldMouseKeys.cbSize, &m_oldMouseKeys, 0) != 0); - if (m_gotOldMouseKeys) { - m_mouseKeys = m_oldMouseKeys; - m_showingMouse = true; - updateForceShowCursor(); - } - } - else { - if (m_gotOldMouseKeys) { - SystemParametersInfo(SPI_SETMOUSEKEYS, - m_oldMouseKeys.cbSize, - &m_oldMouseKeys, SPIF_SENDCHANGE); - m_showingMouse = false; - } - } - } -} - -void -CMSWindowsScreen::updateForceShowCursor() -{ - DWORD oldFlags = m_mouseKeys.dwFlags; - - // turn on MouseKeys - m_mouseKeys.dwFlags = MKF_AVAILABLE | MKF_MOUSEKEYSON; - - // make sure MouseKeys is active in whatever state the NumLock is - // not currently in. - if ((m_keyState->getActiveModifiers() & KeyModifierNumLock) != 0) { - m_mouseKeys.dwFlags |= MKF_REPLACENUMBERS; - } - - // update MouseKeys - if (oldFlags != m_mouseKeys.dwFlags) { - SystemParametersInfo(SPI_SETMOUSEKEYS, - m_mouseKeys.cbSize, &m_mouseKeys, SPIF_SENDCHANGE); - } -} - -LRESULT CALLBACK -CMSWindowsScreen::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - assert(s_screen != NULL); - - LRESULT result = 0; - if (!s_screen->onEvent(hwnd, msg, wParam, lParam, &result)) { - result = DefWindowProc(hwnd, msg, wParam, lParam); - } - - return result; -} - - -// -// CMSWindowsScreen::CHotKeyItem -// - -CMSWindowsScreen::CHotKeyItem::CHotKeyItem(UINT keycode, UINT mask) : - m_keycode(keycode), - m_mask(mask) -{ - // do nothing -} - -UINT -CMSWindowsScreen::CHotKeyItem::getVirtualKey() const -{ - return m_keycode; -} - -bool -CMSWindowsScreen::CHotKeyItem::operator<(const CHotKeyItem& x) const -{ - return (m_keycode < x.m_keycode || - (m_keycode == x.m_keycode && m_mask < x.m_mask)); -} diff --git a/lib/platform/CMSWindowsScreen.h b/lib/platform/CMSWindowsScreen.h deleted file mode 100644 index eda3f554..00000000 --- a/lib/platform/CMSWindowsScreen.h +++ /dev/null @@ -1,308 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CMSWINDOWSSCREEN_H -#define CMSWINDOWSSCREEN_H - -#include "CPlatformScreen.h" -#include "CSynergyHook.h" -#include "CCondVar.h" -#include "CMutex.h" -#include "CString.h" -#define WIN32_LEAN_AND_MEAN -#include - -class CEventQueueTimer; -class CMSWindowsDesks; -class CMSWindowsKeyState; -class CMSWindowsScreenSaver; -class CThread; - -//! Implementation of IPlatformScreen for Microsoft Windows -class CMSWindowsScreen : public CPlatformScreen { -public: - CMSWindowsScreen(bool isPrimary); - virtual ~CMSWindowsScreen(); - - //! @name manipulators - //@{ - - //! Initialize - /*! - Saves the application's HINSTANCE. This \b must be called by - WinMain with the HINSTANCE it was passed. - */ - static void init(HINSTANCE); - - //@} - //! @name accessors - //@{ - - //! Get instance - /*! - Returns the application instance handle passed to init(). - */ - static HINSTANCE getInstance(); - - //@} - - // IScreen overrides - virtual void* getEventTarget() const; - virtual bool getClipboard(ClipboardID id, IClipboard*) const; - virtual void getShape(SInt32& x, SInt32& y, - SInt32& width, SInt32& height) const; - virtual void getCursorPos(SInt32& x, SInt32& y) const; - - // IPrimaryScreen overrides - virtual void reconfigure(UInt32 activeSides); - virtual void warpCursor(SInt32 x, SInt32 y); - virtual UInt32 registerHotKey(KeyID key, - KeyModifierMask mask); - virtual void unregisterHotKey(UInt32 id); - virtual void fakeInputBegin(); - virtual void fakeInputEnd(); - virtual SInt32 getJumpZoneSize() const; - virtual bool isAnyMouseButtonDown() const; - virtual void getCursorCenter(SInt32& x, SInt32& y) const; - - // ISecondaryScreen overrides - virtual void fakeMouseButton(ButtonID id, bool press) const; - virtual void fakeMouseMove(SInt32 x, SInt32 y) const; - virtual void fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const; - virtual void fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const; - - // IKeyState overrides - virtual void updateKeys(); - virtual void fakeKeyDown(KeyID id, KeyModifierMask mask, - KeyButton button); - virtual void fakeKeyRepeat(KeyID id, KeyModifierMask mask, - SInt32 count, KeyButton button); - virtual void fakeKeyUp(KeyButton button); - virtual void fakeAllKeysUp(); - - // IPlatformScreen overrides - virtual void enable(); - virtual void disable(); - virtual void enter(); - virtual bool leave(); - virtual bool setClipboard(ClipboardID, const IClipboard*); - virtual void checkClipboards(); - virtual void openScreensaver(bool notify); - virtual void closeScreensaver(); - virtual void screensaver(bool activate); - virtual void resetOptions(); - virtual void setOptions(const COptionsList& options); - virtual void setSequenceNumber(UInt32); - virtual bool isPrimary() const; - -protected: - // IPlatformScreen overrides - virtual void handleSystemEvent(const CEvent&, void*); - virtual void updateButtons(); - virtual IKeyState* getKeyState() const; - -private: - // initialization and shutdown operations - HINSTANCE openHookLibrary(const char* name); - void closeHookLibrary(HINSTANCE hookLibrary) const; - HCURSOR createBlankCursor() const; - void destroyCursor(HCURSOR cursor) const; - ATOM createWindowClass() const; - ATOM createDeskWindowClass(bool isPrimary) const; - void destroyClass(ATOM windowClass) const; - HWND createWindow(ATOM windowClass, const char* name) const; - void destroyWindow(HWND) const; - - // convenience function to send events - void sendEvent(CEvent::Type type, void* = NULL); - void sendClipboardEvent(CEvent::Type type, ClipboardID id); - - // handle message before it gets dispatched. returns true iff - // the message should not be dispatched. - bool onPreDispatch(HWND, UINT, WPARAM, LPARAM); - - // handle message before it gets dispatched. returns true iff - // the message should not be dispatched. - bool onPreDispatchPrimary(HWND, UINT, WPARAM, LPARAM); - - // handle message. returns true iff handled and optionally sets - // \c *result (which defaults to 0). - bool onEvent(HWND, UINT, WPARAM, LPARAM, LRESULT* result); - - // message handlers - bool onMark(UInt32 mark); - bool onKey(WPARAM, LPARAM); - bool onHotKey(WPARAM, LPARAM); - bool onMouseButton(WPARAM, LPARAM); - bool onMouseMove(SInt32 x, SInt32 y); - bool onMouseWheel(SInt32 xDelta, SInt32 yDelta); - bool onScreensaver(bool activated); - bool onDisplayChange(); - bool onClipboardChange(); - - // warp cursor without discarding queued events - void warpCursorNoFlush(SInt32 x, SInt32 y); - - // discard posted messages - void nextMark(); - - // test if event should be ignored - bool ignore() const; - - // update screen size cache - void updateScreenShape(); - - // fix timer callback - void handleFixes(const CEvent&, void*); - - // fix the clipboard viewer chain - void fixClipboardViewer(); - - // enable/disable special key combinations so we can catch/pass them - void enableSpecialKeys(bool) const; - - // map a button event to a button ID - ButtonID mapButtonFromEvent(WPARAM msg, LPARAM button) const; - - // map a button event to a press (true) or release (false) - bool mapPressFromEvent(WPARAM msg, LPARAM button) const; - - // job to update the key state - void updateKeysCB(void*); - - // determine whether the mouse is hidden by the system and force - // it to be displayed if user has entered this secondary screen. - void forceShowCursor(); - - // forceShowCursor uses MouseKeys to show the cursor. since we - // don't actually want MouseKeys behavior we have to make sure - // it applies when NumLock is in whatever state it's not in now. - // this method does that. - void updateForceShowCursor(); - - // our window proc - static LRESULT CALLBACK wndProc(HWND, UINT, WPARAM, LPARAM); - -private: - struct CHotKeyItem { - public: - CHotKeyItem(UINT vk, UINT modifiers); - - UINT getVirtualKey() const; - - bool operator<(const CHotKeyItem&) const; - - private: - UINT m_keycode; - UINT m_mask; - }; - typedef std::map HotKeyMap; - typedef std::vector HotKeyIDList; - typedef std::map HotKeyToIDMap; - - static HINSTANCE s_instance; - - // true if screen is being used as a primary screen, false otherwise - bool m_isPrimary; - - // true if windows 95/98/me - bool m_is95Family; - - // true if mouse has entered the screen - bool m_isOnScreen; - - // our resources - ATOM m_class; - - // screen shape stuff - SInt32 m_x, m_y; - SInt32 m_w, m_h; - SInt32 m_xCenter, m_yCenter; - - // true if system appears to have multiple monitors - bool m_multimon; - - // last mouse position - SInt32 m_xCursor, m_yCursor; - - // last clipboard - UInt32 m_sequenceNumber; - - // used to discard queued messages that are no longer needed - UInt32 m_mark; - UInt32 m_markReceived; - - // the main loop's thread id - DWORD m_threadID; - - // timer for periodically checking stuff that requires polling - CEventQueueTimer* m_fixTimer; - - // the keyboard layout to use when off primary screen - HKL m_keyLayout; - - // screen saver stuff - CMSWindowsScreenSaver* m_screensaver; - bool m_screensaverNotify; - bool m_screensaverActive; - - // clipboard stuff. our window is used mainly as a clipboard - // owner and as a link in the clipboard viewer chain. - HWND m_window; - HWND m_nextClipboardWindow; - bool m_ownClipboard; - - // one desk per desktop and a cond var to communicate with it - CMSWindowsDesks* m_desks; - - // hook library stuff - HINSTANCE m_hookLibrary; - InitFunc m_init; - CleanupFunc m_cleanup; - SetSidesFunc m_setSides; - SetZoneFunc m_setZone; - SetModeFunc m_setMode; - - // keyboard stuff - CMSWindowsKeyState* m_keyState; - - // hot key stuff - HotKeyMap m_hotKeys; - HotKeyIDList m_oldHotKeyIDs; - HotKeyToIDMap m_hotKeyToIDMap; - - // map of button state - bool m_buttons[1 + kButtonExtra0 + 1]; - - // the system shows the mouse cursor when an internal display count - // is >= 0. this count is maintained per application but there's - // apparently a system wide count added to the application's count. - // this system count is 0 if there's a mouse attached to the system - // and -1 otherwise. the MouseKeys accessibility feature can modify - // this system count by making the system appear to have a mouse. - // - // m_hasMouse is true iff there's a mouse attached to the system or - // MouseKeys is simulating one. we track this so we can force the - // cursor to be displayed when the user has entered this screen. - // m_showingMouse is true when we're doing that. - bool m_hasMouse; - bool m_showingMouse; - bool m_gotOldMouseKeys; - MOUSEKEYS m_mouseKeys; - MOUSEKEYS m_oldMouseKeys; - - static CMSWindowsScreen* s_screen; -}; - -#endif diff --git a/lib/platform/CMSWindowsScreenSaver.cpp b/lib/platform/CMSWindowsScreenSaver.cpp deleted file mode 100644 index 7217338f..00000000 --- a/lib/platform/CMSWindowsScreenSaver.cpp +++ /dev/null @@ -1,498 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CMSWindowsScreenSaver.h" -#include "CMSWindowsScreen.h" -#include "CThread.h" -#include "CLog.h" -#include "TMethodJob.h" -#include "CArch.h" -#include "CArchMiscWindows.h" -#include -#include - -#if !defined(SPI_GETSCREENSAVERRUNNING) -#define SPI_GETSCREENSAVERRUNNING 114 -#endif - -static const TCHAR* g_isSecureNT = "ScreenSaverIsSecure"; -static const TCHAR* g_isSecure9x = "ScreenSaveUsePassword"; -static const TCHAR* const g_pathScreenSaverIsSecure[] = { - "Control Panel", - "Desktop", - NULL -}; - -// -// CMSWindowsScreenSaver -// - -CMSWindowsScreenSaver::CMSWindowsScreenSaver() : - m_wasSecure(false), - m_wasSecureAnInt(false), - m_process(NULL), - m_watch(NULL), - m_threadID(0), - m_active(false) -{ - // detect OS - m_is95Family = false; - m_is95 = false; - m_isNT = false; - OSVERSIONINFO info; - info.dwOSVersionInfoSize = sizeof(info); - if (GetVersionEx(&info)) { - m_is95Family = (info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS); - if (info.dwPlatformId == VER_PLATFORM_WIN32_NT && - info.dwMajorVersion <= 4) { - m_isNT = true; - } - else if (info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && - info.dwMajorVersion == 4 && - info.dwMinorVersion == 0) { - m_is95 = true; - } - } - - // check if screen saver is enabled - SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, &m_wasEnabled, 0); -} - -CMSWindowsScreenSaver::~CMSWindowsScreenSaver() -{ - unwatchProcess(); -} - -bool -CMSWindowsScreenSaver::checkStarted(UINT msg, WPARAM wParam, LPARAM lParam) -{ - // if already started then say it didn't just start - if (m_active) { - return false; - } - - // screen saver may have started. look for it and get - // the process. if we can't find it then assume it - // didn't really start. we wait a moment before - // looking to give the screen saver a chance to start. - // this shouldn't be a problem since we only get here - // if the screen saver wants to kick in, meaning that - // the system is idle or the user deliberately started - // the screen saver. - Sleep(250); - - // set parameters common to all screen saver handling - m_threadID = GetCurrentThreadId(); - m_msg = msg; - m_wParam = wParam; - m_lParam = lParam; - - // we handle the screen saver differently for the windows - // 95 and nt families. - if (m_is95Family) { - // on windows 95 we wait for the screen saver process - // to terminate. get the process. - DWORD processID = findScreenSaver(); - HANDLE process = OpenProcess(SYNCHRONIZE, FALSE, processID); - if (process == NULL) { - // didn't start - LOG((CLOG_DEBUG2 "can't open screen saver process")); - return false; - } - - // watch for the process to exit - watchProcess(process); - } - else { - // on the windows nt family we wait for the desktop to - // change until it's neither the Screen-Saver desktop - // nor a desktop we can't open (the login desktop). - // since windows will send the request-to-start-screen- - // saver message even when the screen saver is disabled - // we first check that the screen saver is indeed active - // before watching for it to stop. - if (!isActive()) { - LOG((CLOG_DEBUG2 "can't open screen saver desktop")); - return false; - } - - watchDesktop(); - } - - return true; -} - -void -CMSWindowsScreenSaver::enable() -{ - SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, m_wasEnabled, 0, 0); - - // restore password protection - if (m_wasSecure) { - setSecure(true, m_wasSecureAnInt); - } - - // restore display power down - CArchMiscWindows::removeBusyState(CArchMiscWindows::kDISPLAY); -} - -void -CMSWindowsScreenSaver::disable() -{ - SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, &m_wasEnabled, 0); - SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, FALSE, 0, 0); - - // disable password protected screensaver - m_wasSecure = isSecure(&m_wasSecureAnInt); - if (m_wasSecure) { - setSecure(false, m_wasSecureAnInt); - } - - // disable display power down - CArchMiscWindows::addBusyState(CArchMiscWindows::kDISPLAY); -} - -void -CMSWindowsScreenSaver::activate() -{ - // don't activate if already active - if (!isActive()) { - // activate - HWND hwnd = GetForegroundWindow(); - if (hwnd != NULL) { - PostMessage(hwnd, WM_SYSCOMMAND, SC_SCREENSAVE, 0); - } - else { - // no foreground window. pretend we got the event instead. - DefWindowProc(NULL, WM_SYSCOMMAND, SC_SCREENSAVE, 0); - } - - // restore power save when screen saver activates - CArchMiscWindows::removeBusyState(CArchMiscWindows::kDISPLAY); - } -} - -void -CMSWindowsScreenSaver::deactivate() -{ - bool killed = false; - if (!m_is95Family) { - // NT runs screen saver in another desktop - HDESK desktop = OpenDesktop("Screen-saver", 0, FALSE, - DESKTOP_READOBJECTS | DESKTOP_WRITEOBJECTS); - if (desktop != NULL) { - EnumDesktopWindows(desktop, - &CMSWindowsScreenSaver::killScreenSaverFunc, - reinterpret_cast(&killed)); - CloseDesktop(desktop); - } - } - - // if above failed or wasn't tried, try the windows 95 way - if (!killed) { - // find screen saver window and close it - HWND hwnd = FindWindow("WindowsScreenSaverClass", NULL); - if (hwnd == NULL) { - // win2k may use a different class - hwnd = FindWindow("Default Screen Saver", NULL); - } - if (hwnd != NULL) { - PostMessage(hwnd, WM_CLOSE, 0, 0); - } - } - - // force timer to restart - SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, &m_wasEnabled, 0); - SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, - !m_wasEnabled, 0, SPIF_SENDWININICHANGE); - SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, - m_wasEnabled, 0, SPIF_SENDWININICHANGE); - - // disable display power down - CArchMiscWindows::removeBusyState(CArchMiscWindows::kDISPLAY); -} - -bool -CMSWindowsScreenSaver::isActive() const -{ - if (m_is95) { - return (FindWindow("WindowsScreenSaverClass", NULL) != NULL); - } - else if (m_isNT) { - // screen saver runs on a separate desktop - HDESK desktop = OpenDesktop("Screen-saver", 0, FALSE, MAXIMUM_ALLOWED); - if (desktop == NULL && GetLastError() != ERROR_ACCESS_DENIED) { - // desktop doesn't exist so screen saver is not running - return false; - } - - // desktop exists. this should indicate that the screen saver - // is running but an OS bug can cause a valid handle to be - // returned even if the screen saver isn't running (Q230117). - // we'll try to enumerate the windows on the desktop and, if - // there are any, we assume the screen saver is running. (note - // that if we don't have permission to enumerate then we'll - // assume that the screen saver is not running.) that'd be - // easy enough except there's another OS bug (Q198590) that can - // cause EnumDesktopWindows() to enumerate the windows of - // another desktop if the requested desktop has no windows. to - // work around that we have to verify that the enumerated - // windows are, in fact, on the expected desktop. - CFindScreenSaverInfo info; - info.m_desktop = desktop; - info.m_window = NULL; - EnumDesktopWindows(desktop, - &CMSWindowsScreenSaver::findScreenSaverFunc, - reinterpret_cast(&info)); - - // done with desktop - CloseDesktop(desktop); - - // screen saver is running if a window was found - return (info.m_window != NULL); - } - else { - BOOL running; - SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &running, 0); - return (running != FALSE); - } -} - -BOOL CALLBACK -CMSWindowsScreenSaver::findScreenSaverFunc(HWND hwnd, LPARAM arg) -{ - CFindScreenSaverInfo* info = reinterpret_cast(arg); - - if (info->m_desktop != NULL) { - DWORD threadID = GetWindowThreadProcessId(hwnd, NULL); - HDESK desktop = GetThreadDesktop(threadID); - if (desktop != NULL && desktop != info->m_desktop) { - // stop enumerating -- wrong desktop - return FALSE; - } - } - - // found a window - info->m_window = hwnd; - - // don't need to enumerate further - return FALSE; -} - -BOOL CALLBACK -CMSWindowsScreenSaver::killScreenSaverFunc(HWND hwnd, LPARAM arg) -{ - if (IsWindowVisible(hwnd)) { - HINSTANCE instance = (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE); - if (instance != CMSWindowsScreen::getInstance()) { - PostMessage(hwnd, WM_CLOSE, 0, 0); - *reinterpret_cast(arg) = true; - } - } - return TRUE; -} - -DWORD -CMSWindowsScreenSaver::findScreenSaver() -{ - // try windows 95 way - HWND hwnd = FindWindow("WindowsScreenSaverClass", NULL); - - // get process ID of process that owns the window, if found - if (hwnd != NULL) { - DWORD processID; - GetWindowThreadProcessId(hwnd, &processID); - return processID; - } - - // not found - return 0; -} - -void -CMSWindowsScreenSaver::watchDesktop() -{ - // stop watching previous process/desktop - unwatchProcess(); - - // watch desktop in another thread - LOG((CLOG_DEBUG "watching screen saver desktop")); - m_active = true; - m_watch = new CThread(new TMethodJob(this, - &CMSWindowsScreenSaver::watchDesktopThread)); -} - -void -CMSWindowsScreenSaver::watchProcess(HANDLE process) -{ - // stop watching previous process/desktop - unwatchProcess(); - - // watch new process in another thread - if (process != NULL) { - LOG((CLOG_DEBUG "watching screen saver process")); - m_process = process; - m_active = true; - m_watch = new CThread(new TMethodJob(this, - &CMSWindowsScreenSaver::watchProcessThread)); - } -} - -void -CMSWindowsScreenSaver::unwatchProcess() -{ - if (m_watch != NULL) { - LOG((CLOG_DEBUG "stopped watching screen saver process/desktop")); - m_watch->cancel(); - m_watch->wait(); - delete m_watch; - m_watch = NULL; - m_active = false; - } - if (m_process != NULL) { - CloseHandle(m_process); - m_process = NULL; - } -} - -void -CMSWindowsScreenSaver::watchDesktopThread(void*) -{ - DWORD reserved = 0; - TCHAR* name = NULL; - - for (;;) { - // wait a bit - ARCH->sleep(0.2); - - if (m_isNT) { - // get current desktop - HDESK desk = OpenInputDesktop(0, FALSE, GENERIC_READ); - if (desk == NULL) { - // can't open desktop so keep waiting - continue; - } - - // get current desktop name length - DWORD size; - GetUserObjectInformation(desk, UOI_NAME, NULL, 0, &size); - - // allocate more space for the name, if necessary - if (size > reserved) { - reserved = size; - name = (TCHAR*)alloca(reserved + sizeof(TCHAR)); - } - - // get current desktop name - GetUserObjectInformation(desk, UOI_NAME, name, size, &size); - CloseDesktop(desk); - - // compare name to screen saver desktop name - if (_tcsicmp(name, TEXT("Screen-saver")) == 0) { - // still the screen saver desktop so keep waiting - continue; - } - } - else { - // 2000/XP have a sane way to detect a runnin screensaver. - BOOL running; - SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &running, 0); - if (running) { - continue; - } - } - - // send screen saver deactivation message - m_active = false; - PostThreadMessage(m_threadID, m_msg, m_wParam, m_lParam); - return; - } -} - -void -CMSWindowsScreenSaver::watchProcessThread(void*) -{ - for (;;) { - CThread::testCancel(); - if (WaitForSingleObject(m_process, 50) == WAIT_OBJECT_0) { - // process terminated - LOG((CLOG_DEBUG "screen saver died")); - - // send screen saver deactivation message - m_active = false; - PostThreadMessage(m_threadID, m_msg, m_wParam, m_lParam); - return; - } - } -} - -void -CMSWindowsScreenSaver::setSecure(bool secure, bool saveSecureAsInt) -{ - HKEY hkey = - CArchMiscWindows::addKey(HKEY_CURRENT_USER, g_pathScreenSaverIsSecure); - if (hkey == NULL) { - return; - } - - const TCHAR* isSecure = m_is95Family ? g_isSecure9x : g_isSecureNT; - if (saveSecureAsInt) { - CArchMiscWindows::setValue(hkey, isSecure, secure ? 1 : 0); - } - else { - CArchMiscWindows::setValue(hkey, isSecure, secure ? "1" : "0"); - } - - CArchMiscWindows::closeKey(hkey); -} - -bool -CMSWindowsScreenSaver::isSecure(bool* wasSecureFlagAnInt) const -{ - // get the password protection setting key - HKEY hkey = - CArchMiscWindows::openKey(HKEY_CURRENT_USER, g_pathScreenSaverIsSecure); - if (hkey == NULL) { - return false; - } - - // get the value. the value may be an int or a string, depending - // on the version of windows. - bool result; - const TCHAR* isSecure = m_is95Family ? g_isSecure9x : g_isSecureNT; - switch (CArchMiscWindows::typeOfValue(hkey, isSecure)) { - default: - result = false; - break; - - case CArchMiscWindows::kUINT: { - DWORD value = - CArchMiscWindows::readValueInt(hkey, isSecure); - *wasSecureFlagAnInt = true; - result = (value != 0); - break; - } - - case CArchMiscWindows::kSTRING: { - std::string value = - CArchMiscWindows::readValueString(hkey, isSecure); - *wasSecureFlagAnInt = false; - result = (value != "0"); - break; - } - } - - CArchMiscWindows::closeKey(hkey); - return result; -} diff --git a/lib/platform/CMSWindowsScreenSaver.h b/lib/platform/CMSWindowsScreenSaver.h deleted file mode 100644 index bb43c703..00000000 --- a/lib/platform/CMSWindowsScreenSaver.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CMSWINDOWSSCREENSAVER_H -#define CMSWINDOWSSCREENSAVER_H - -#include "IScreenSaver.h" -#include "CString.h" -#define WIN32_LEAN_AND_MEAN -#include - -class CThread; - -//! Microsoft windows screen saver implementation -class CMSWindowsScreenSaver : public IScreenSaver { -public: - CMSWindowsScreenSaver(); - virtual ~CMSWindowsScreenSaver(); - - //! @name manipulators - //@{ - - //! Check if screen saver started - /*! - Check if the screen saver really started. Returns false if it - hasn't, true otherwise. When the screen saver stops, \c msg will - be posted to the current thread's message queue with the given - parameters. - */ - bool checkStarted(UINT msg, WPARAM, LPARAM); - - //@} - - // IScreenSaver overrides - virtual void enable(); - virtual void disable(); - virtual void activate(); - virtual void deactivate(); - virtual bool isActive() const; - -private: - class CFindScreenSaverInfo { - public: - HDESK m_desktop; - HWND m_window; - }; - - static BOOL CALLBACK findScreenSaverFunc(HWND hwnd, LPARAM lParam); - static BOOL CALLBACK killScreenSaverFunc(HWND hwnd, LPARAM lParam); - - DWORD findScreenSaver(); - void watchDesktop(); - void watchProcess(HANDLE process); - void unwatchProcess(); - void watchDesktopThread(void*); - void watchProcessThread(void*); - - void setSecure(bool secure, bool saveSecureAsInt); - bool isSecure(bool* wasSecureAnInt) const; - -private: - bool m_is95Family; - bool m_is95; - bool m_isNT; - BOOL m_wasEnabled; - bool m_wasSecure; - bool m_wasSecureAnInt; - - HANDLE m_process; - CThread* m_watch; - DWORD m_threadID; - UINT m_msg; - WPARAM m_wParam; - LPARAM m_lParam; - - // checkActive state. true if the screen saver is being watched - // for deactivation (and is therefore active). - bool m_active; -}; - -#endif diff --git a/lib/platform/CMSWindowsUtil.cpp b/lib/platform/CMSWindowsUtil.cpp deleted file mode 100644 index 4b3e3f4c..00000000 --- a/lib/platform/CMSWindowsUtil.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CMSWindowsUtil.h" -#include "CStringUtil.h" -#include - -// -// CMSWindowsUtil -// - -CString -CMSWindowsUtil::getString(HINSTANCE instance, DWORD id) -{ - char buffer[1024]; - int size = static_cast(sizeof(buffer) / sizeof(buffer[0])); - char* msg = buffer; - - // load string - int n = LoadString(instance, id, msg, size); - msg[n] = '\0'; - if (n < size) { - return msg; - } - - // not enough buffer space. keep trying larger buffers until - // we get the whole string. - msg = NULL; - do { - size <<= 1; - delete[] msg; - char* msg = new char[size]; - n = LoadString(instance, id, msg, size); - } while (n == size); - msg[n] = '\0'; - - CString result(msg); - delete[] msg; - return result; -} - -CString -CMSWindowsUtil::getErrorString(HINSTANCE hinstance, DWORD error, DWORD id) -{ - char* buffer; - if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_IGNORE_INSERTS | - FORMAT_MESSAGE_FROM_SYSTEM, - 0, - error, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR)&buffer, - 0, - NULL) == 0) { - CString errorString = CStringUtil::print("%d", error); - return CStringUtil::format(getString(hinstance, id).c_str(), - errorString.c_str()); - } - else { - CString result(buffer); - LocalFree(buffer); - return result; - } -} diff --git a/lib/platform/CMSWindowsUtil.h b/lib/platform/CMSWindowsUtil.h deleted file mode 100644 index 5c4d14f5..00000000 --- a/lib/platform/CMSWindowsUtil.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CMSWINDOWSUTIL_H -#define CMSWINDOWSUTIL_H - -#include "CString.h" -#define WINDOWS_LEAN_AND_MEAN -#include - -class CMSWindowsUtil { -public: - //! Get message string - /*! - Gets a string for \p id from the string table of \p instance. - */ - static CString getString(HINSTANCE instance, DWORD id); - - //! Get error string - /*! - Gets a system error message for \p error. If the error cannot be - found return the string for \p id, replacing ${1} with \p error. - */ - static CString getErrorString(HINSTANCE, DWORD error, DWORD id); -}; - -#endif diff --git a/lib/platform/COSXClipboard.cpp b/lib/platform/COSXClipboard.cpp deleted file mode 100644 index 7d39eaad..00000000 --- a/lib/platform/COSXClipboard.cpp +++ /dev/null @@ -1,220 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "COSXClipboard.h" -#include "COSXClipboardUTF16Converter.h" -#include "COSXClipboardTextConverter.h" -#include "CLog.h" -#include "XArch.h" - -// -// COSXClipboard -// - -COSXClipboard::COSXClipboard() : - m_time(0), - m_scrap(NULL) -{ - m_converters.push_back(new COSXClipboardUTF16Converter); - m_converters.push_back(new COSXClipboardTextConverter); -} - -COSXClipboard::~COSXClipboard() -{ - clearConverters(); -} - -bool -COSXClipboard::empty() -{ - LOG((CLOG_DEBUG "empty clipboard")); - assert(m_scrap != NULL); - - OSStatus err = ClearScrap(&m_scrap); - if (err != noErr) { - LOG((CLOG_DEBUG "failed to grab clipboard")); - return false; - } - - // we own the clipboard - err = PutScrapFlavor( - m_scrap, - getOwnershipFlavor(), - kScrapFlavorMaskNone, - 0, - 0); - if (err != noErr) { - LOG((CLOG_DEBUG "failed to grab clipboard")); - return false; - } - - return true; -} - -void -COSXClipboard::add(EFormat format, const CString & data) -{ - LOG((CLOG_DEBUG "add %d bytes to clipboard format: %d", data.size(), format)); - - for (ConverterList::const_iterator index = m_converters.begin(); - index != m_converters.end(); ++index) { - - IOSXClipboardConverter* converter = *index; - - // skip converters for other formats - if (converter->getFormat() == format) { - CString osXData = converter->fromIClipboard(data); - ScrapFlavorType flavorType = converter->getOSXFormat(); - - PutScrapFlavor( - m_scrap, - flavorType, - kScrapFlavorMaskNone, - osXData.size(), - osXData.data()); - } - } -} - -bool -COSXClipboard::open(Time time) const -{ - LOG((CLOG_DEBUG "open clipboard")); - m_time = time; - OSStatus err = GetCurrentScrap(&m_scrap); - return (err == noErr); -} - -void -COSXClipboard::close() const -{ - LOG((CLOG_DEBUG "close clipboard")); - m_scrap = NULL; -} - -IClipboard::Time -COSXClipboard::getTime() const -{ - return m_time; -} - -bool -COSXClipboard::has(EFormat format) const -{ - assert(m_scrap != NULL); - - for (ConverterList::const_iterator index = m_converters.begin(); - index != m_converters.end(); ++index) { - IOSXClipboardConverter* converter = *index; - if (converter->getFormat() == format) { - ScrapFlavorFlags flags; - ScrapFlavorType type = converter->getOSXFormat(); - - if (GetScrapFlavorFlags(m_scrap, type, &flags) == noErr) { - return true; - } - } - } - - return false; -} - -CString -COSXClipboard::get(EFormat format) const -{ - CString result; - - // find the converter for the first clipboard format we can handle - IOSXClipboardConverter* converter = NULL; - for (ConverterList::const_iterator index = m_converters.begin(); - index != m_converters.end(); ++index) { - converter = *index; - - ScrapFlavorFlags flags; - ScrapFlavorType type = converter->getOSXFormat(); - - if (converter->getFormat() == format && - GetScrapFlavorFlags(m_scrap, type, &flags) == noErr) { - break; - } - converter = NULL; - } - - // if no converter then we don't recognize any formats - if (converter == NULL) { - return result; - } - - // get the clipboard data. - char* buffer = NULL; - try { - Size flavorSize; - OSStatus err = GetScrapFlavorSize(m_scrap, - converter->getOSXFormat(), &flavorSize); - if (err != noErr) { - throw err; - } - - buffer = new char[flavorSize]; - if (buffer == NULL) { - throw memFullErr; - } - - err = GetScrapFlavorData(m_scrap, - converter->getOSXFormat(), &flavorSize, buffer); - if (err != noErr) { - throw err; - } - - result = CString(buffer, flavorSize); - } - catch (OSStatus err) { - LOG((CLOG_DEBUG "exception thrown in COSXClipboard::get MacError (%d)", err)); - } - catch (...) { - LOG((CLOG_DEBUG "unknown exception in COSXClipboard::get")); - RETHROW_XTHREAD - } - delete[] buffer; - - return converter->toIClipboard(result); -} - -void -COSXClipboard::clearConverters() -{ - for (ConverterList::iterator index = m_converters.begin(); - index != m_converters.end(); ++index) { - delete *index; - } - m_converters.clear(); -} - -bool -COSXClipboard::isOwnedBySynergy() -{ - ScrapFlavorFlags flags; - ScrapRef scrap; - OSStatus err = GetCurrentScrap(&scrap); - if (err == noErr) { - err = GetScrapFlavorFlags(scrap, getOwnershipFlavor() , &flags); - } - return (err == noErr); -} - -ScrapFlavorType -COSXClipboard::getOwnershipFlavor() -{ - return 'Syne'; -} diff --git a/lib/platform/COSXClipboard.h b/lib/platform/COSXClipboard.h deleted file mode 100644 index 19f95ec7..00000000 --- a/lib/platform/COSXClipboard.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef COSXCLIPBOARD_H -#define COSXCLIPBOARD_H - -#include "IClipboard.h" -#include -#include - -class IOSXClipboardConverter; - -//! OS X clipboard implementation -class COSXClipboard : public IClipboard { -public: - COSXClipboard(); - virtual ~COSXClipboard(); - - //! Test if clipboard is owned by synergy - static bool isOwnedBySynergy(); - - // IClipboard overrides - virtual bool empty(); - virtual void add(EFormat, const CString& data); - virtual bool open(Time) const; - virtual void close() const; - virtual Time getTime() const; - virtual bool has(EFormat) const; - virtual CString get(EFormat) const; - -private: - void clearConverters(); - static ScrapFlavorType - getOwnershipFlavor(); - -private: - typedef std::vector ConverterList; - - mutable Time m_time; - ConverterList m_converters; - mutable ScrapRef m_scrap; -}; - -//! Clipboard format converter interface -/*! -This interface defines the methods common to all Scrap book format -*/ -class IOSXClipboardConverter : public IInterface { -public: - //! @name accessors - //@{ - - //! Get clipboard format - /*! - Return the clipboard format this object converts from/to. - */ - virtual IClipboard::EFormat - getFormat() const = 0; - - //! returns the scrap flavor type that this object converts from/to - virtual ScrapFlavorType - getOSXFormat() const = 0; - - //! Convert from IClipboard format - /*! - Convert from the IClipboard format to the Carbon scrap format. - The input data must be in the IClipboard format returned by - getFormat(). The return data will be in the scrap - format returned by getOSXFormat(). - */ - virtual CString fromIClipboard(const CString&) const = 0; - - //! Convert to IClipboard format - /*! - Convert from the carbon scrap format to the IClipboard format - (i.e., the reverse of fromIClipboard()). - */ - virtual CString toIClipboard(const CString&) const = 0; - - //@} -}; - -#endif diff --git a/lib/platform/COSXClipboardAnyTextConverter.cpp b/lib/platform/COSXClipboardAnyTextConverter.cpp deleted file mode 100644 index 67fc3029..00000000 --- a/lib/platform/COSXClipboardAnyTextConverter.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "COSXClipboardAnyTextConverter.h" -#include - -// -// COSXClipboardAnyTextConverter -// - -COSXClipboardAnyTextConverter::COSXClipboardAnyTextConverter() -{ - // do nothing -} - -COSXClipboardAnyTextConverter::~COSXClipboardAnyTextConverter() -{ - // do nothing -} - -IClipboard::EFormat -COSXClipboardAnyTextConverter::getFormat() const -{ - return IClipboard::kText; -} - -CString -COSXClipboardAnyTextConverter::fromIClipboard(const CString& data) const -{ - // convert linefeeds and then convert to desired encoding - return doFromIClipboard(convertLinefeedToMacOS(data)); -} - -CString -COSXClipboardAnyTextConverter::toIClipboard(const CString& data) const -{ - // convert text then newlines - return convertLinefeedToUnix(doToIClipboard(data)); -} - -static -bool -isLF(char ch) -{ - return (ch == '\n'); -} - -static -bool -isCR(char ch) -{ - return (ch == '\r'); -} - -CString -COSXClipboardAnyTextConverter::convertLinefeedToMacOS(const CString& src) -{ - // note -- we assume src is a valid UTF-8 string - CString copy = src; - - std::replace_if(copy.begin(), copy.end(), isLF, '\r'); - - return copy; -} - -CString -COSXClipboardAnyTextConverter::convertLinefeedToUnix(const CString& src) -{ - CString copy = src; - - std::replace_if(copy.begin(), copy.end(), isCR, '\n'); - - return copy; -} diff --git a/lib/platform/COSXClipboardAnyTextConverter.h b/lib/platform/COSXClipboardAnyTextConverter.h deleted file mode 100644 index 5d0b79f3..00000000 --- a/lib/platform/COSXClipboardAnyTextConverter.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef COSXCLIPBOARDANYTEXTCONVERTER_H -#define COSXCLIPBOARDANYTEXTCONVERTER_H - -#include "COSXClipboard.h" - -//! Convert to/from some text encoding -class COSXClipboardAnyTextConverter : public IOSXClipboardConverter { -public: - COSXClipboardAnyTextConverter(); - virtual ~COSXClipboardAnyTextConverter(); - - // IOSXClipboardConverter overrides - virtual IClipboard::EFormat - getFormat() const; - virtual ScrapFlavorType - getOSXFormat() const = 0; - virtual CString fromIClipboard(const CString &) const; - virtual CString toIClipboard(const CString &) const; - -protected: - //! Convert from IClipboard format - /*! - Do UTF-8 conversion and linefeed conversion. - */ - virtual CString doFromIClipboard(const CString&) const = 0; - - //! Convert to IClipboard format - /*! - Do UTF-8 conversion and Linefeed conversion. - */ - virtual CString doToIClipboard(const CString&) const = 0; - -private: - static CString convertLinefeedToMacOS(const CString&); - static CString convertLinefeedToUnix(const CString&); -}; - -#endif diff --git a/lib/platform/COSXClipboardTextConverter.cpp b/lib/platform/COSXClipboardTextConverter.cpp deleted file mode 100644 index bcbc228e..00000000 --- a/lib/platform/COSXClipboardTextConverter.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "COSXClipboardTextConverter.h" -#include "CUnicode.h" - -// -// COSXClipboardTextConverter -// - -COSXClipboardTextConverter::COSXClipboardTextConverter() -{ - // do nothing -} - -COSXClipboardTextConverter::~COSXClipboardTextConverter() -{ - // do nothing -} - -ScrapFlavorType -COSXClipboardTextConverter::getOSXFormat() const -{ - return kScrapFlavorTypeText; -} - -CString -COSXClipboardTextConverter::convertString( - const CString& data, - CFStringEncoding fromEncoding, - CFStringEncoding toEncoding) -{ - CFStringRef stringRef = - CFStringCreateWithCString(kCFAllocatorDefault, - data.c_str(), fromEncoding); - - if (stringRef == NULL) { - return CString(); - } - - CFIndex buffSize; - CFRange entireString = CFRangeMake(0, CFStringGetLength(stringRef)); - - CFStringGetBytes(stringRef, entireString, toEncoding, - 0, false, NULL, 0, &buffSize); - - char* buffer = new char[buffSize]; - - if (buffer == NULL) { - CFRelease(stringRef); - return CString(); - } - - CFStringGetBytes(stringRef, entireString, toEncoding, - 0, false, (UInt8*)buffer, buffSize, NULL); - - CString result(buffer, buffSize); - - delete[] buffer; - CFRelease(stringRef); - - return result; -} - -CString -COSXClipboardTextConverter::doFromIClipboard(const CString& data) const -{ - return convertString(data, kCFStringEncodingUTF8, - CFStringGetSystemEncoding()); -} - -CString -COSXClipboardTextConverter::doToIClipboard(const CString& data) const -{ - return convertString(data, CFStringGetSystemEncoding(), - kCFStringEncodingUTF8); -} diff --git a/lib/platform/COSXClipboardTextConverter.h b/lib/platform/COSXClipboardTextConverter.h deleted file mode 100644 index 2a75f4f0..00000000 --- a/lib/platform/COSXClipboardTextConverter.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef COSXCLIPBOARDTEXTCONVERTER_H -#define COSXCLIPBOARDTEXTCONVERTER_H - -#include "COSXClipboardAnyTextConverter.h" - -//! Convert to/from locale text encoding -class COSXClipboardTextConverter : public COSXClipboardAnyTextConverter { -public: - COSXClipboardTextConverter(); - virtual ~COSXClipboardTextConverter(); - - // IOSXClipboardAnyTextConverter overrides - virtual ScrapFlavorType - getOSXFormat() const; - -protected: - // COSXClipboardAnyTextConverter overrides - virtual CString doFromIClipboard(const CString&) const; - virtual CString doToIClipboard(const CString&) const; - - // generic encoding converter - static CString convertString(const CString& data, - CFStringEncoding fromEncoding, - CFStringEncoding toEncoding); -}; - -#endif diff --git a/lib/platform/COSXClipboardUTF16Converter.cpp b/lib/platform/COSXClipboardUTF16Converter.cpp deleted file mode 100644 index 10693c83..00000000 --- a/lib/platform/COSXClipboardUTF16Converter.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "COSXClipboardUTF16Converter.h" -#include "CUnicode.h" - -// -// COSXClipboardUTF16Converter -// - -COSXClipboardUTF16Converter::COSXClipboardUTF16Converter() -{ - // do nothing -} - -COSXClipboardUTF16Converter::~COSXClipboardUTF16Converter() -{ - // do nothing -} - -ScrapFlavorType -COSXClipboardUTF16Converter::getOSXFormat() const -{ - return kScrapFlavorTypeUnicode; -} - -CString -COSXClipboardUTF16Converter::doFromIClipboard(const CString& data) const -{ - // convert and add nul terminator - return CUnicode::UTF8ToUTF16(data); -} - -CString -COSXClipboardUTF16Converter::doToIClipboard(const CString& data) const -{ - // convert and strip nul terminator - return CUnicode::UTF16ToUTF8(data); -} diff --git a/lib/platform/COSXClipboardUTF16Converter.h b/lib/platform/COSXClipboardUTF16Converter.h deleted file mode 100644 index 1499a7ed..00000000 --- a/lib/platform/COSXClipboardUTF16Converter.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef COSXCLIPBOARDUTF16CONVERTER_H -#define COSXCLIPBOARDUTF16CONVERTER_H - -#include "COSXClipboardAnyTextConverter.h" - -//! Convert to/from UTF-16 encoding -class COSXClipboardUTF16Converter : public COSXClipboardAnyTextConverter { -public: - COSXClipboardUTF16Converter(); - virtual ~COSXClipboardUTF16Converter(); - - // IOSXClipboardAnyTextConverter overrides - virtual ScrapFlavorType - getOSXFormat() const; - -protected: - // COSXClipboardAnyTextConverter overrides - virtual CString doFromIClipboard(const CString&) const; - virtual CString doToIClipboard(const CString&) const; -}; - -#endif diff --git a/lib/platform/COSXEventQueueBuffer.cpp b/lib/platform/COSXEventQueueBuffer.cpp deleted file mode 100644 index 5bd0d747..00000000 --- a/lib/platform/COSXEventQueueBuffer.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "COSXEventQueueBuffer.h" -#include "CEvent.h" -#include "IEventQueue.h" - -// -// CEventQueueTimer -// - -class CEventQueueTimer { }; - -// -// COSXEventQueueBuffer -// - -COSXEventQueueBuffer::COSXEventQueueBuffer() : - m_event(NULL) -{ - // do nothing -} - -COSXEventQueueBuffer::~COSXEventQueueBuffer() -{ - // release the last event - if (m_event != NULL) { - ReleaseEvent(m_event); - } -} - -void -COSXEventQueueBuffer::waitForEvent(double timeout) -{ - EventRef event; - ReceiveNextEvent(0, NULL, timeout, false, &event); -} - -IEventQueueBuffer::Type -COSXEventQueueBuffer::getEvent(CEvent& event, UInt32& dataID) -{ - // release the previous event - if (m_event != NULL) { - ReleaseEvent(m_event); - m_event = NULL; - } - - // get the next event - OSStatus error = ReceiveNextEvent(0, NULL, 0.0, true, &m_event); - - // handle the event - if (error == eventLoopQuitErr) { - event = CEvent(CEvent::kQuit); - return kSystem; - } - else if (error != noErr) { - return kNone; - } - else { - UInt32 eventClass = GetEventClass(m_event); - switch (eventClass) { - case 'Syne': - dataID = GetEventKind(m_event); - return kUser; - - default: - event = CEvent(CEvent::kSystem, - IEventQueue::getSystemTarget(), &m_event); - return kSystem; - } - } -} - -bool -COSXEventQueueBuffer::addEvent(UInt32 dataID) -{ - EventRef event; - OSStatus error = CreateEvent( - kCFAllocatorDefault, - 'Syne', - dataID, - 0, - kEventAttributeNone, - &event); - - if (error == noErr) { - error = PostEventToQueue(GetMainEventQueue(), event, - kEventPriorityStandard); - ReleaseEvent(event); - } - - return (error == noErr); -} - -bool -COSXEventQueueBuffer::isEmpty() const -{ - EventRef event; - OSStatus status = ReceiveNextEvent(0, NULL, 0.0, false, &event); - return (status == eventLoopTimedOutErr); -} - -CEventQueueTimer* -COSXEventQueueBuffer::newTimer(double, bool) const -{ - return new CEventQueueTimer; -} - -void -COSXEventQueueBuffer::deleteTimer(CEventQueueTimer* timer) const -{ - delete timer; -} diff --git a/lib/platform/COSXEventQueueBuffer.h b/lib/platform/COSXEventQueueBuffer.h deleted file mode 100644 index 659b5940..00000000 --- a/lib/platform/COSXEventQueueBuffer.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef COSXEVENTQUEUEBUFFER_H -#define COSXEVENTQUEUEBUFFER_H - -#include "IEventQueueBuffer.h" -#include - -//! Event queue buffer for OS X -class COSXEventQueueBuffer : public IEventQueueBuffer { -public: - COSXEventQueueBuffer(); - virtual ~COSXEventQueueBuffer(); - - // IEventQueueBuffer overrides - virtual void waitForEvent(double timeout); - virtual Type getEvent(CEvent& event, UInt32& dataID); - virtual bool addEvent(UInt32 dataID); - virtual bool isEmpty() const; - virtual CEventQueueTimer* - newTimer(double duration, bool oneShot) const; - virtual void deleteTimer(CEventQueueTimer*) const; - -private: - EventRef m_event; -}; - -#endif diff --git a/lib/platform/COSXKeyState.cpp b/lib/platform/COSXKeyState.cpp deleted file mode 100644 index e904d5e4..00000000 --- a/lib/platform/COSXKeyState.cpp +++ /dev/null @@ -1,1237 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "COSXKeyState.h" -#include "CLog.h" -#include "CArch.h" - -// Hardcoded virtual key table. Oddly, Apple doesn't document the -// meaning of virtual key codes. The whole point of *virtual* key -// codes is to make them hardware independent so these codes should -// be constant across OS versions and hardware. Yet they don't -// tell us what codes map to what keys so we have to figure it out -// for ourselves. -// -// Note that some virtual keys codes appear more than once. The -// first instance of a virtual key code maps to the KeyID that we -// want to generate for that code. The others are for mapping -// different KeyIDs to a single key code. -static const UInt32 s_shiftVK = 56; -static const UInt32 s_controlVK = 59; -static const UInt32 s_altVK = 55; -static const UInt32 s_superVK = 58; -static const UInt32 s_capsLockVK = 57; -static const UInt32 s_numLockVK = 71; -static const UInt32 s_osxNumLock = 1 << 16; -struct CKeyEntry { -public: - KeyID m_keyID; - UInt32 m_virtualKey; -}; -static const CKeyEntry s_controlKeys[] = { - // cursor keys. if we don't do this we'll may still get these from - // the keyboard resource but they may not correspond to the arrow - // keys. - { kKeyLeft, 123 }, - { kKeyRight, 124 }, - { kKeyUp, 126 }, - { kKeyDown, 125 }, - { kKeyHome, 115 }, - { kKeyEnd, 119 }, - { kKeyPageUp, 116 }, - { kKeyPageDown, 121 }, - - // function keys - { kKeyF1, 122 }, - { kKeyF2, 120 }, - { kKeyF3, 99 }, - { kKeyF4, 118 }, - { kKeyF5, 96 }, - { kKeyF6, 97 }, - { kKeyF7, 98 }, - { kKeyF8, 100 }, - { kKeyF9, 101 }, - { kKeyF10, 109 }, - { kKeyF11, 103 }, - { kKeyF12, 111 }, - { kKeyF13, 105 }, - { kKeyF14, 107 }, - { kKeyF15, 113 }, - { kKeyF16, 106 }, - - { kKeyKP_0, 82 }, - { kKeyKP_1, 83 }, - { kKeyKP_2, 84 }, - { kKeyKP_3, 85 }, - { kKeyKP_4, 86 }, - { kKeyKP_5, 87 }, - { kKeyKP_6, 88 }, - { kKeyKP_7, 89 }, - { kKeyKP_8, 91 }, - { kKeyKP_9, 92 }, - { kKeyKP_Decimal, 65 }, - { kKeyKP_Equal, 81 }, - { kKeyKP_Multiply, 67 }, - { kKeyKP_Add, 69 }, - { kKeyKP_Divide, 75 }, - { kKeyKP_Subtract, 79 }, - { kKeyKP_Enter, 76 }, - - // virtual key 110 is fn+enter and i have no idea what that's supposed - // to map to. also the enter key with numlock on is a modifier but i - // don't know which. - - // modifier keys. OS X doesn't seem to support right handed versions - // of modifier keys so we map them to the left handed versions. - { kKeyShift_L, s_shiftVK }, - { kKeyShift_R, s_shiftVK }, // 60 - { kKeyControl_L, s_controlVK }, - { kKeyControl_R, s_controlVK }, // 62 - { kKeyAlt_L, s_altVK }, - { kKeyAlt_R, s_altVK }, - { kKeySuper_L, s_superVK }, - { kKeySuper_R, s_superVK }, // 61 - { kKeyMeta_L, s_superVK }, - { kKeyMeta_R, s_superVK }, // 61 - - // toggle modifiers - { kKeyNumLock, s_numLockVK }, - { kKeyCapsLock, s_capsLockVK } -}; - - -// -// COSXKeyState -// - -COSXKeyState::COSXKeyState() : - m_deadKeyState(0) -{ - // enable input in scripts other that roman - KeyScript(smKeyEnableKybds); - - // build virtual key map - for (size_t i = 0; i < sizeof(s_controlKeys) / - sizeof(s_controlKeys[0]); ++i) { - m_virtualKeyMap[s_controlKeys[i].m_virtualKey] = - s_controlKeys[i].m_keyID; - } -} - -COSXKeyState::~COSXKeyState() -{ - // do nothing -} - -KeyModifierMask -COSXKeyState::mapModifiersFromOSX(UInt32 mask) const -{ -LOG((CLOG_DEBUG1 "mask: %04x", mask)); - // convert - KeyModifierMask outMask = 0; - if ((mask & shiftKey) != 0) { - outMask |= KeyModifierShift; - } - if ((mask & rightShiftKey) != 0) { - outMask |= KeyModifierShift; - } - if ((mask & controlKey) != 0) { - outMask |= KeyModifierControl; - } - if ((mask & rightControlKey) != 0) { - outMask |= KeyModifierControl; - } - if ((mask & cmdKey) != 0) { - outMask |= KeyModifierAlt; - } - if ((mask & optionKey) != 0) { - outMask |= KeyModifierSuper; - } - if ((mask & rightOptionKey) != 0) { - outMask |= KeyModifierSuper; - } - if ((mask & alphaLock) != 0) { - outMask |= KeyModifierCapsLock; - } - if ((mask & s_osxNumLock) != 0) { - outMask |= KeyModifierNumLock; - } - - return outMask; -} - -KeyButton -COSXKeyState::mapKeyFromEvent(CKeyIDs& ids, - KeyModifierMask* maskOut, EventRef event) const -{ - ids.clear(); - - // map modifier key - if (maskOut != NULL) { - KeyModifierMask activeMask = getActiveModifiers(); - activeMask &= ~KeyModifierAltGr; - *maskOut = activeMask; - } - - // get virtual key - UInt32 vkCode; - GetEventParameter(event, kEventParamKeyCode, typeUInt32, - NULL, sizeof(vkCode), NULL, &vkCode); - - // handle up events - UInt32 eventKind = GetEventKind(event); - if (eventKind == kEventRawKeyUp) { - // the id isn't used. we just need the same button we used on - // the key press. note that we don't use or reset the dead key - // state; up events should not affect the dead key state. - ids.push_back(kKeyNone); - return mapVirtualKeyToKeyButton(vkCode); - } - - // check for special keys - CVirtualKeyMap::const_iterator i = m_virtualKeyMap.find(vkCode); - if (i != m_virtualKeyMap.end()) { - m_deadKeyState = 0; - ids.push_back(i->second); - return mapVirtualKeyToKeyButton(vkCode); - } - - // get keyboard info - KeyboardLayoutRef keyboardLayout; - OSStatus status = KLGetCurrentKeyboardLayout(&keyboardLayout); - if (status != noErr) { - return kKeyNone; - } - - // get the event modifiers and remove the command and control - // keys. note if we used them though. - UInt32 modifiers; - GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, - NULL, sizeof(modifiers), NULL, &modifiers); - static const UInt32 s_commandModifiers = - cmdKey | controlKey | rightControlKey; - bool isCommand = ((modifiers & s_commandModifiers) != 0); - modifiers &= ~s_commandModifiers; - - // if we've used a command key then we want the glyph produced without - // the option key (i.e. the base glyph). - if (isCommand) { - modifiers &= ~optionKey; - } - - // translate via uchr resource - const void* resource; - if (KLGetKeyboardLayoutProperty(keyboardLayout, - kKLuchrData, &resource) == noErr) { - // choose action - UInt16 action; - switch (eventKind) { - case kEventRawKeyDown: - action = kUCKeyActionDown; - break; - - case kEventRawKeyRepeat: - action = kUCKeyActionAutoKey; - break; - - default: - return 0; - } - - // translate key - UniCharCount count; - UniChar chars[2]; - OSStatus status = UCKeyTranslate((const UCKeyboardLayout*)resource, - vkCode & 0xffu, action, - (modifiers >> 8) & 0xffu, - LMGetKbdType(), 0, &m_deadKeyState, - sizeof(chars) / sizeof(chars[0]), &count, chars); - - // get the characters - if (status == 0) { - if (count != 0 || m_deadKeyState == 0) { - m_deadKeyState = 0; - for (UniCharCount i = 0; i < count; ++i) { - ids.push_back(CKeyResource::unicharToKeyID(chars[i])); - } - adjustAltGrModifier(ids, maskOut, isCommand); - return mapVirtualKeyToKeyButton(vkCode); - } - return 0; - } - } - - // translate via KCHR resource - if (KLGetKeyboardLayoutProperty(keyboardLayout, - kKLKCHRData, &resource) == noErr) { - // build keycode - UInt16 keycode = - static_cast((modifiers & 0xff00u) | (vkCode & 0x00ffu)); - - // translate key - UInt32 result = KeyTranslate(resource, keycode, &m_deadKeyState); - - // get the characters - UInt8 c1 = static_cast((result >> 16) & 0xffu); - UInt8 c2 = static_cast( result & 0xffu); - if (c2 != 0) { - m_deadKeyState = 0; - if (c1 != 0) { - ids.push_back(CKeyResource::getKeyID(c1)); - } - ids.push_back(CKeyResource::getKeyID(c2)); - adjustAltGrModifier(ids, maskOut, isCommand); - return mapVirtualKeyToKeyButton(vkCode); - } - } - - return 0; -} - -bool -COSXKeyState::fakeCtrlAltDel() -{ - // pass keys through unchanged - return false; -} - -KeyModifierMask -COSXKeyState::pollActiveModifiers() const -{ - return mapModifiersFromOSX(GetCurrentKeyModifiers()); -} - -SInt32 -COSXKeyState::pollActiveGroup() const -{ - KeyboardLayoutRef keyboardLayout; - OSStatus status = KLGetCurrentKeyboardLayout(&keyboardLayout); - if (status == noErr) { - GroupMap::const_iterator i = m_groupMap.find(keyboardLayout); - if (i != m_groupMap.end()) { - return i->second; - } - } - return 0; -} - -void -COSXKeyState::pollPressedKeys(KeyButtonSet& pressedKeys) const -{ - KeyMap km; - GetKeys(km); - const UInt8* m = reinterpret_cast(km); - for (UInt32 i = 0; i < 16; ++i) { - for (UInt32 j = 0; j < 8; ++j) { - if ((m[i] & (1u << j)) != 0) { - pressedKeys.insert(mapVirtualKeyToKeyButton(8 * i + j)); - } - } - } -} - -void -COSXKeyState::getKeyMap(CKeyMap& keyMap) -{ - // update keyboard groups - if (getGroups(m_groups)) { - m_groupMap.clear(); - SInt32 numGroups = (SInt32)m_groups.size(); - for (SInt32 g = 0; g < numGroups; ++g) { - m_groupMap[m_groups[g]] = g; - } - } - - UInt32 keyboardType = LMGetKbdType(); - for (SInt32 g = 0, n = (SInt32)m_groups.size(); g < n; ++g) { - // add special keys - getKeyMapForSpecialKeys(keyMap, g); - - // add regular keys - - // try uchr resource first - const void* resource; - if (KLGetKeyboardLayoutProperty(m_groups[g], - kKLuchrData, &resource) == noErr) { - CUCHRKeyResource uchr(resource, keyboardType); - if (uchr.isValid()) { - LOG((CLOG_DEBUG1 "using uchr resource for group %d", g)); - getKeyMap(keyMap, g, uchr); - continue; - } - } - - // try KCHR resource - if (KLGetKeyboardLayoutProperty(m_groups[g], - kKLKCHRData, &resource) == noErr) { - CKCHRKeyResource kchr(resource); - if (kchr.isValid()) { - LOG((CLOG_DEBUG1 "using KCHR resource for group %d", g)); - getKeyMap(keyMap, g, kchr); - continue; - } - } - - LOG((CLOG_DEBUG1 "no keyboard resource for group %d", g)); - } -} - -void -COSXKeyState::fakeKey(const Keystroke& keystroke) -{ - switch (keystroke.m_type) { - case Keystroke::kButton: - LOG((CLOG_DEBUG1 " %03x (%08x) %s", keystroke.m_data.m_button.m_button, keystroke.m_data.m_button.m_client, keystroke.m_data.m_button.m_press ? "down" : "up")); - - // let system figure out character for us - CGPostKeyboardEvent(0, mapKeyButtonToVirtualKey( - keystroke.m_data.m_button.m_button), - keystroke.m_data.m_button.m_press); - - // add a delay if client data isn't zero - if (keystroke.m_data.m_button.m_client) { - ARCH->sleep(0.01); - } - break; - - case Keystroke::kGroup: - if (keystroke.m_data.m_group.m_absolute) { - LOG((CLOG_DEBUG1 " group %d", keystroke.m_data.m_group.m_group)); - setGroup(keystroke.m_data.m_group.m_group); - } - else { - LOG((CLOG_DEBUG1 " group %+d", keystroke.m_data.m_group.m_group)); - setGroup(getEffectiveGroup(pollActiveGroup(), - keystroke.m_data.m_group.m_group)); - } - break; - } -} - -void -COSXKeyState::getKeyMapForSpecialKeys(CKeyMap& keyMap, SInt32 group) const -{ - // special keys are insensitive to modifers and none are dead keys - CKeyMap::KeyItem item; - for (size_t i = 0; i < sizeof(s_controlKeys) / - sizeof(s_controlKeys[0]); ++i) { - const CKeyEntry& entry = s_controlKeys[i]; - item.m_id = entry.m_keyID; - item.m_group = group; - item.m_button = mapVirtualKeyToKeyButton(entry.m_virtualKey); - item.m_required = 0; - item.m_sensitive = 0; - item.m_dead = false; - item.m_client = 0; - CKeyMap::initModifierKey(item); - keyMap.addKeyEntry(item); - - if (item.m_lock) { - // all locking keys are half duplex on OS X - keyMap.addHalfDuplexButton(item.m_button); - } - } - - // note: we don't special case the number pad keys. querying the - // mac keyboard returns the non-keypad version of those keys but - // a CKeyState always provides a mapping from keypad keys to - // non-keypad keys so we'll be able to generate the characters - // anyway. -} - -bool -COSXKeyState::getKeyMap(CKeyMap& keyMap, - SInt32 group, const CKeyResource& r) const -{ - if (!r.isValid()) { - return false; - } - - // space for all possible modifier combinations - std::vector modifiers(r.getNumModifierCombinations()); - - // make space for the keys that any single button can synthesize - std::vector > buttonKeys(r.getNumTables()); - - // iterate over each button - CKeyMap::KeyItem item; - for (UInt32 i = 0; i < r.getNumButtons(); ++i) { - item.m_button = mapVirtualKeyToKeyButton(i); - - // the KeyIDs we've already handled - std::set keys; - - // convert the entry in each table for this button to a KeyID - for (UInt32 j = 0; j < r.getNumTables(); ++j) { - buttonKeys[j].first = r.getKey(j, i); - buttonKeys[j].second = CKeyMap::isDeadKey(buttonKeys[j].first); - } - - // iterate over each character table - for (UInt32 j = 0; j < r.getNumTables(); ++j) { - // get the KeyID for the button/table - KeyID id = buttonKeys[j].first; - if (id == kKeyNone) { - continue; - } - - // if we've already handled the KeyID in the table then - // move on to the next table - if (keys.count(id) > 0) { - continue; - } - keys.insert(id); - - // prepare item. the client state is 1 for dead keys. - item.m_id = id; - item.m_group = group; - item.m_dead = buttonKeys[j].second; - item.m_client = buttonKeys[j].second ? 1 : 0; - CKeyMap::initModifierKey(item); - if (item.m_lock) { - // all locking keys are half duplex on OS X - keyMap.addHalfDuplexButton(i); - } - - // collect the tables that map to the same KeyID. we know it - // can't be any earlier tables because of the check above. - std::set tables; - tables.insert(static_cast(j)); - for (UInt32 k = j + 1; k < r.getNumTables(); ++k) { - if (buttonKeys[k].first == id) { - tables.insert(static_cast(k)); - } - } - - // collect the modifier combinations that map to any of the - // tables we just collected - for (UInt32 k = 0; k < r.getNumModifierCombinations(); ++k) { - modifiers[k] = (tables.count(r.getTableForModifier(k)) > 0); - } - - // figure out which modifiers the key is sensitive to. the - // key is insensitive to a modifier if for every modifier mask - // with the modifier bit unset in the modifiers we also find - // the same mask with the bit set. - // - // we ignore a few modifiers that we know aren't important - // for generating characters. in fact, we want to ignore any - // characters generated by the control key. we don't map - // those and instead expect the control modifier plus a key. - UInt32 sensitive = 0; - for (UInt32 k = 0; (1u << k) < - r.getNumModifierCombinations(); ++k) { - UInt32 bit = (1u << k); - if ((bit << 8) == cmdKey || - (bit << 8) == controlKey || - (bit << 8) == rightControlKey) { - continue; - } - for (UInt32 m = 0; m < r.getNumModifierCombinations(); ++m) { - if (modifiers[m] != modifiers[m ^ bit]) { - sensitive |= bit; - break; - } - } - } - - // find each required modifier mask. the key can be synthesized - // using any of the masks. - std::set required; - for (UInt32 k = 0; k < r.getNumModifierCombinations(); ++k) { - if ((k & sensitive) == k && modifiers[k & sensitive]) { - required.insert(k); - } - } - - // now add a key entry for each key/required modifier pair. - item.m_sensitive = mapModifiersFromOSX(sensitive << 8); - for (std::set::iterator k = required.begin(); - k != required.end(); ++k) { - item.m_required = mapModifiersFromOSX(*k << 8); - keyMap.addKeyEntry(item); - } - } - } - - return true; -} - -bool -COSXKeyState::mapSynergyHotKeyToMac(KeyID key, KeyModifierMask mask, - UInt32 &macVirtualKey, UInt32 &macModifierMask) const -{ - // look up button for key - KeyButton button = getButton(key, pollActiveGroup()); - if (button == 0 && key != kKeyNone) { - return false; - } - macVirtualKey = mapKeyButtonToVirtualKey(button); - - // calculate modifier mask - macModifierMask = 0; - if ((mask & KeyModifierShift) != 0) { - macModifierMask |= shiftKey; - } - if ((mask & KeyModifierControl) != 0) { - macModifierMask |= controlKey; - } - if ((mask & KeyModifierAlt) != 0) { - macModifierMask |= cmdKey; - } - if ((mask & KeyModifierSuper) != 0) { - macModifierMask |= optionKey; - } - if ((mask & KeyModifierCapsLock) != 0) { - macModifierMask |= alphaLock; - } - if ((mask & KeyModifierNumLock) != 0) { - macModifierMask |= s_osxNumLock; - } - - return true; -} - -void -COSXKeyState::handleModifierKeys(void* target, - KeyModifierMask oldMask, KeyModifierMask newMask) -{ - // compute changed modifiers - KeyModifierMask changed = (oldMask ^ newMask); - - // synthesize changed modifier keys - if ((changed & KeyModifierShift) != 0) { - handleModifierKey(target, s_shiftVK, kKeyShift_L, - (newMask & KeyModifierShift) != 0, newMask); - } - if ((changed & KeyModifierControl) != 0) { - handleModifierKey(target, s_controlVK, kKeyControl_L, - (newMask & KeyModifierControl) != 0, newMask); - } - if ((changed & KeyModifierAlt) != 0) { - handleModifierKey(target, s_altVK, kKeyAlt_L, - (newMask & KeyModifierAlt) != 0, newMask); - } - if ((changed & KeyModifierSuper) != 0) { - handleModifierKey(target, s_superVK, kKeySuper_L, - (newMask & KeyModifierSuper) != 0, newMask); - } - if ((changed & KeyModifierCapsLock) != 0) { - handleModifierKey(target, s_capsLockVK, kKeyCapsLock, - (newMask & KeyModifierCapsLock) != 0, newMask); - } - if ((changed & KeyModifierNumLock) != 0) { - handleModifierKey(target, s_numLockVK, kKeyNumLock, - (newMask & KeyModifierNumLock) != 0, newMask); - } -} - -void -COSXKeyState::handleModifierKey(void* target, - UInt32 virtualKey, KeyID id, - bool down, KeyModifierMask newMask) -{ - KeyButton button = mapVirtualKeyToKeyButton(virtualKey); - onKey(button, down, newMask); - sendKeyEvent(target, down, false, id, newMask, 0, button); -} - -bool -COSXKeyState::getGroups(GroupList& groups) const -{ - // get number of layouts - CFIndex n; - OSStatus status = KLGetKeyboardLayoutCount(&n); - if (status != noErr) { - LOG((CLOG_DEBUG1 "can't get keyboard layouts")); - return false; - } - - // get each layout - groups.clear(); - for (CFIndex i = 0; i < n; ++i) { - KeyboardLayoutRef keyboardLayout; - status = KLGetKeyboardLayoutAtIndex(i, &keyboardLayout); - if (status == noErr) { - groups.push_back(keyboardLayout); - } - } - return true; -} - -void -COSXKeyState::setGroup(SInt32 group) -{ - KLSetCurrentKeyboardLayout(m_groups[group]); -} - -void -COSXKeyState::checkKeyboardLayout() -{ - // XXX -- should call this when notified that groups have changed. - // if no notification for that then we should poll. - GroupList groups; - if (getGroups(groups) && groups != m_groups) { - updateKeyMap(); - updateKeyState(); - } -} - -void -COSXKeyState::adjustAltGrModifier(const CKeyIDs& ids, - KeyModifierMask* mask, bool isCommand) const -{ - if (!isCommand) { - for (CKeyIDs::const_iterator i = ids.begin(); i != ids.end(); ++i) { - KeyID id = *i; - if (id != kKeyNone && - ((id < 0xe000u || id > 0xefffu) || - (id >= kKeyKP_Equal && id <= kKeyKP_9))) { - *mask |= KeyModifierAltGr; - return; - } - } - } -} - -KeyButton -COSXKeyState::mapVirtualKeyToKeyButton(UInt32 keyCode) -{ - // 'A' maps to 0 so shift every id - return static_cast(keyCode + KeyButtonOffset); -} - -UInt32 -COSXKeyState::mapKeyButtonToVirtualKey(KeyButton keyButton) -{ - return static_cast(keyButton - KeyButtonOffset); -} - - -// -// COSXKeyState::CKeyResource -// - -KeyID -COSXKeyState::CKeyResource::getKeyID(UInt8 c) -{ - if (c == 0) { - return kKeyNone; - } - else if (c >= 32 && c < 127) { - // ASCII - return static_cast(c); - } - else { - // handle special keys - switch (c) { - case 0x01: - return kKeyHome; - - case 0x02: - return kKeyKP_Enter; - - case 0x03: - return kKeyKP_Enter; - - case 0x04: - return kKeyEnd; - - case 0x05: - return kKeyHelp; - - case 0x08: - return kKeyBackSpace; - - case 0x09: - return kKeyTab; - - case 0x0b: - return kKeyPageUp; - - case 0x0c: - return kKeyPageDown; - - case 0x0d: - return kKeyReturn; - - case 0x10: - // OS X maps all the function keys (F1, etc) to this one key. - // we can't determine the right key here so we have to do it - // some other way. - return kKeyNone; - - case 0x1b: - return kKeyEscape; - - case 0x1c: - return kKeyLeft; - - case 0x1d: - return kKeyRight; - - case 0x1e: - return kKeyUp; - - case 0x1f: - return kKeyDown; - - case 0x7f: - return kKeyDelete; - - case 0x06: - case 0x07: - case 0x0a: - case 0x0e: - case 0x0f: - case 0x11: - case 0x12: - case 0x13: - case 0x14: - case 0x15: - case 0x16: - case 0x17: - case 0x18: - case 0x19: - case 0x1a: - // discard other control characters - return kKeyNone; - - default: - // not special or unknown - break; - } - - // create string with character - char str[2]; - str[0] = static_cast(c); - str[1] = 0; - - // convert to unicode - CFStringRef cfString = - CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, - str, GetScriptManagerVariable(smKeyScript), - kCFAllocatorNull); - - // sometimes CFStringCreate...() returns NULL (e.g. Apple Korean - // encoding with char value 214). if it did then make no key, - // otherwise CFStringCreateMutableCopy() will crash. - if (cfString == NULL) { - return kKeyNone; - } - - // convert to precomposed - CFMutableStringRef mcfString = - CFStringCreateMutableCopy(kCFAllocatorDefault, 0, cfString); - CFRelease(cfString); - CFStringNormalize(mcfString, kCFStringNormalizationFormC); - - // check result - int unicodeLength = CFStringGetLength(mcfString); - if (unicodeLength == 0) { - CFRelease(mcfString); - return kKeyNone; - } - if (unicodeLength > 1) { - // FIXME -- more than one character, we should handle this - CFRelease(mcfString); - return kKeyNone; - } - - // get unicode character - UniChar uc = CFStringGetCharacterAtIndex(mcfString, 0); - CFRelease(mcfString); - - // convert to KeyID - return static_cast(uc); - } -} - -KeyID -COSXKeyState::CKeyResource::unicharToKeyID(UniChar c) -{ - switch (c) { - case 3: - return kKeyKP_Enter; - - case 8: - return kKeyBackSpace; - - case 9: - return kKeyTab; - - case 13: - return kKeyReturn; - - case 27: - return kKeyEscape; - - case 127: - return kKeyDelete; - - default: - if (c < 32) { - return kKeyNone; - } - return static_cast(c); - } -} - - -// -// COSXKeyState::CKCHRKeyResource -// - -COSXKeyState::CKCHRKeyResource::CKCHRKeyResource(const void* resource) -{ - m_resource = reinterpret_cast(resource); -} - -bool -COSXKeyState::CKCHRKeyResource::isValid() const -{ - return (m_resource != NULL); -} - -UInt32 -COSXKeyState::CKCHRKeyResource::getNumModifierCombinations() const -{ - // only 32 (not 256) because the righthanded modifier bits are ignored - return 32; -} - -UInt32 -COSXKeyState::CKCHRKeyResource::getNumTables() const -{ - return m_resource->m_numTables; -} - -UInt32 -COSXKeyState::CKCHRKeyResource::getNumButtons() const -{ - return 128; -} - -UInt32 -COSXKeyState::CKCHRKeyResource::getTableForModifier(UInt32 mask) const -{ - assert(mask < getNumModifierCombinations()); - - return m_resource->m_tableSelectionIndex[mask]; -} - -KeyID -COSXKeyState::CKCHRKeyResource::getKey(UInt32 table, UInt32 button) const -{ - assert(table < getNumTables()); - assert(button < getNumButtons()); - - UInt8 c = m_resource->m_characterTables[table][button]; - if (c == 0) { - // could be a dead key - const CKCHRDeadKeys* dkp = - reinterpret_cast( - m_resource->m_characterTables[getNumTables()]); - const CKCHRDeadKeyRecord* dkr = dkp->m_records; - for (SInt16 i = 0; i < dkp->m_numRecords; ++i) { - if (dkr->m_tableIndex == table && dkr->m_virtualKey == button) { - // get the no completion entry - c = dkr->m_completion[dkr->m_numCompletions][1]; - return CKeyMap::getDeadKey(getKeyID(c)); - } - - // next table. skip all the completions and the no match - // pair to get the next table. - dkr = reinterpret_cast( - dkr->m_completion[dkr->m_numCompletions + 1]); - } - } - - return getKeyID(c); -} - - -// -// COSXKeyState::CUCHRKeyResource -// - -COSXKeyState::CUCHRKeyResource::CUCHRKeyResource(const void* resource, - UInt32 keyboardType) : - m_m(NULL), - m_cti(NULL), - m_sdi(NULL), - m_sri(NULL), - m_st(NULL) -{ - m_resource = reinterpret_cast(resource); - if (m_resource == NULL) { - return; - } - - // find the keyboard info for the current keyboard type - const UCKeyboardTypeHeader* th = NULL; - const UCKeyboardLayout* r = m_resource; - for (ItemCount i = 0; i < r->keyboardTypeCount; ++i) { - if (keyboardType >= r->keyboardTypeList[i].keyboardTypeFirst && - keyboardType <= r->keyboardTypeList[i].keyboardTypeLast) { - th = r->keyboardTypeList + i; - break; - } - if (r->keyboardTypeList[i].keyboardTypeFirst == 0) { - // found the default. use it unless we find a match. - th = r->keyboardTypeList + i; - } - } - if (th == NULL) { - // cannot find a suitable keyboard type - return; - } - - // get tables for keyboard type - const UInt8* base = reinterpret_cast(m_resource); - m_m = reinterpret_cast(base + - th->keyModifiersToTableNumOffset); - m_cti = reinterpret_cast(base + - th->keyToCharTableIndexOffset); - m_sdi = reinterpret_cast(base + - th->keySequenceDataIndexOffset); - if (th->keyStateRecordsIndexOffset != 0) { - m_sri = reinterpret_cast(base + - th->keyStateRecordsIndexOffset); - } - if (th->keyStateTerminatorsOffset != 0) { - m_st = reinterpret_cast(base + - th->keyStateTerminatorsOffset); - } - - // find the space key, but only if it can combine with dead keys. - // a dead key followed by a space yields the non-dead version of - // the dead key. - m_spaceOutput = 0xffffu; - UInt32 table = getTableForModifier(0); - for (UInt32 button = 0, n = getNumButtons(); button < n; ++button) { - KeyID id = getKey(table, button); - if (id == 0x20) { - UCKeyOutput c = - reinterpret_cast(base + - m_cti->keyToCharTableOffsets[table])[button]; - if ((c & kUCKeyOutputTestForIndexMask) == - kUCKeyOutputStateIndexMask) { - m_spaceOutput = (c & kUCKeyOutputGetIndexMask); - break; - } - } - } -} - -bool -COSXKeyState::CUCHRKeyResource::isValid() const -{ - return (m_m != NULL); -} - -UInt32 -COSXKeyState::CUCHRKeyResource::getNumModifierCombinations() const -{ - // only 32 (not 256) because the righthanded modifier bits are ignored - return 32; -} - -UInt32 -COSXKeyState::CUCHRKeyResource::getNumTables() const -{ - return m_cti->keyToCharTableCount; -} - -UInt32 -COSXKeyState::CUCHRKeyResource::getNumButtons() const -{ - return m_cti->keyToCharTableSize; -} - -UInt32 -COSXKeyState::CUCHRKeyResource::getTableForModifier(UInt32 mask) const -{ - if (mask >= m_m->modifiersCount) { - return m_m->defaultTableNum; - } - else { - return m_m->tableNum[mask]; - } -} - -KeyID -COSXKeyState::CUCHRKeyResource::getKey(UInt32 table, UInt32 button) const -{ - assert(table < getNumTables()); - assert(button < getNumButtons()); - - const UInt8* base = reinterpret_cast(m_resource); - const UCKeyOutput c = reinterpret_cast(base + - m_cti->keyToCharTableOffsets[table])[button]; - - KeySequence keys; - switch (c & kUCKeyOutputTestForIndexMask) { - case kUCKeyOutputStateIndexMask: - if (!getDeadKey(keys, c & kUCKeyOutputGetIndexMask)) { - return kKeyNone; - } - break; - - case kUCKeyOutputSequenceIndexMask: - default: - if (!addSequence(keys, c)) { - return kKeyNone; - } - break; - } - - // XXX -- no support for multiple characters - if (keys.size() != 1) { - return kKeyNone; - } - - return keys.front(); -} - -bool -COSXKeyState::CUCHRKeyResource::getDeadKey( - KeySequence& keys, UInt16 index) const -{ - if (m_sri == NULL || index >= m_sri->keyStateRecordCount) { - // XXX -- should we be using some other fallback? - return false; - } - - UInt16 state = 0; - if (!getKeyRecord(keys, index, state)) { - return false; - } - if (state == 0) { - // not a dead key - return true; - } - - // no dead keys if we couldn't find the space key - if (m_spaceOutput == 0xffffu) { - return false; - } - - // the dead key should not have put anything in the key list - if (!keys.empty()) { - return false; - } - - // get the character generated by pressing the space key after the - // dead key. if we're still in a compose state afterwards then we're - // confused so we bail. - if (!getKeyRecord(keys, m_spaceOutput, state) || state != 0) { - return false; - } - - // convert keys to their dead counterparts - for (KeySequence::iterator i = keys.begin(); i != keys.end(); ++i) { - *i = CKeyMap::getDeadKey(*i); - } - - return true; -} - -bool -COSXKeyState::CUCHRKeyResource::getKeyRecord( - KeySequence& keys, UInt16 index, UInt16& state) const -{ - const UInt8* base = reinterpret_cast(m_resource); - const UCKeyStateRecord* sr = - reinterpret_cast(base + - m_sri->keyStateRecordOffsets[index]); - const UCKeyStateEntryTerminal* kset = - reinterpret_cast(sr->stateEntryData); - - UInt16 nextState = 0; - bool found = false; - if (state == 0) { - found = true; - nextState = sr->stateZeroNextState; - if (!addSequence(keys, sr->stateZeroCharData)) { - return false; - } - } - else { - // we have a next entry - switch (sr->stateEntryFormat) { - case kUCKeyStateEntryTerminalFormat: - for (UInt16 j = 0; j < sr->stateEntryCount; ++j) { - if (kset[j].curState == state) { - if (!addSequence(keys, kset[j].charData)) { - return false; - } - nextState = 0; - found = true; - break; - } - } - break; - - case kUCKeyStateEntryRangeFormat: - // XXX -- not supported yet - break; - - default: - // XXX -- unknown format - return false; - } - } - if (!found) { - // use a terminator - if (m_st != NULL && state < m_st->keyStateTerminatorCount) { - if (!addSequence(keys, m_st->keyStateTerminators[state - 1])) { - return false; - } - } - nextState = sr->stateZeroNextState; - if (!addSequence(keys, sr->stateZeroCharData)) { - return false; - } - } - - // next - state = nextState; - - return true; -} - -bool -COSXKeyState::CUCHRKeyResource::addSequence( - KeySequence& keys, UCKeyCharSeq c) const -{ - if ((c & kUCKeyOutputTestForIndexMask) == kUCKeyOutputSequenceIndexMask) { - UInt16 index = (c & kUCKeyOutputGetIndexMask); - if (index < m_sdi->charSequenceCount && - m_sdi->charSequenceOffsets[index] != - m_sdi->charSequenceOffsets[index + 1]) { - // XXX -- sequences not supported yet - return false; - } - } - - if (c != 0xfffe && c != 0xffff) { - KeyID id = unicharToKeyID(c); - if (id != kKeyNone) { - keys.push_back(id); - } - } - - return true; -} diff --git a/lib/platform/COSXKeyState.h b/lib/platform/COSXKeyState.h deleted file mode 100644 index baf69713..00000000 --- a/lib/platform/COSXKeyState.h +++ /dev/null @@ -1,235 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef COSXKEYSTATE_H -#define COSXKEYSTATE_H - -#include "CKeyState.h" -#include "stdmap.h" -#include "stdset.h" -#include "stdvector.h" -#include - -//! OS X key state -/*! -A key state for OS X. -*/ -class COSXKeyState : public CKeyState { -public: - typedef std::vector CKeyIDs; - - COSXKeyState(); - virtual ~COSXKeyState(); - - //! @name modifiers - //@{ - - //! Handle modifier key change - /*! - Determines which modifier keys have changed and updates the modifier - state and sends key events as appropriate. - */ - void handleModifierKeys(void* target, - KeyModifierMask oldMask, KeyModifierMask newMask); - - //@} - //! @name accessors - //@{ - - //! Convert OS X modifier mask to synergy mask - /*! - Returns the synergy modifier mask corresponding to the OS X modifier - mask in \p mask. - */ - KeyModifierMask mapModifiersFromOSX(UInt32 mask) const; - - //! Map key event to keys - /*! - Converts a key event into a sequence of KeyIDs and the shadow modifier - state to a modifier mask. The KeyIDs list, in order, the characters - generated by the key press/release. It returns the id of the button - that was pressed or released, or 0 if the button doesn't map to a known - KeyID. - */ - KeyButton mapKeyFromEvent(CKeyIDs& ids, - KeyModifierMask* maskOut, EventRef event) const; - - //! Map key and mask to native values - /*! - Calculates mac virtual key and mask for a key \p key and modifiers - \p mask. Returns \c true if the key can be mapped, \c false otherwise. - */ - bool mapSynergyHotKeyToMac(KeyID key, KeyModifierMask mask, - UInt32& macVirtualKey, - UInt32& macModifierMask) const; - - //@} - - // IKeyState overrides - virtual bool fakeCtrlAltDel(); - virtual KeyModifierMask - pollActiveModifiers() const; - virtual SInt32 pollActiveGroup() const; - virtual void pollPressedKeys(KeyButtonSet& pressedKeys) const; - -protected: - // CKeyState overrides - virtual void getKeyMap(CKeyMap& keyMap); - virtual void fakeKey(const Keystroke& keystroke); - -private: - class CKeyResource; - typedef std::vector GroupList; - - // Add hard coded special keys to a CKeyMap. - void getKeyMapForSpecialKeys( - CKeyMap& keyMap, SInt32 group) const; - - // Convert keyboard resource to a key map - bool getKeyMap(CKeyMap& keyMap, - SInt32 group, const CKeyResource& r) const; - - // Get the available keyboard groups - bool getGroups(GroupList&) const; - - // Change active keyboard group to group - void setGroup(SInt32 group); - - // Check if the keyboard layout has changed and update keyboard state - // if so. - void checkKeyboardLayout(); - - // Send an event for the given modifier key - void handleModifierKey(void* target, - UInt32 virtualKey, KeyID id, - bool down, KeyModifierMask newMask); - - // Checks if any in \p ids is a glyph key and if \p isCommand is false. - // If so it adds the AltGr modifier to \p mask. This allows OS X - // servers to use the option key both as AltGr and as a modifier. If - // option is acting as AltGr (i.e. it generates a glyph and there are - // no command modifiers active) then we don't send the super modifier - // to clients because they'd try to match it as a command modifier. - void adjustAltGrModifier(const CKeyIDs& ids, - KeyModifierMask* mask, bool isCommand) const; - - // Maps an OS X virtual key id to a KeyButton. This simply remaps - // the ids so we don't use KeyButton 0. - static KeyButton mapVirtualKeyToKeyButton(UInt32 keyCode); - - // Maps a KeyButton to an OS X key code. This is the inverse of - // mapVirtualKeyToKeyButton. - static UInt32 mapKeyButtonToVirtualKey(KeyButton keyButton); - -private: - class CKeyResource : public IInterface { - public: - virtual bool isValid() const = 0; - virtual UInt32 getNumModifierCombinations() const = 0; - virtual UInt32 getNumTables() const = 0; - virtual UInt32 getNumButtons() const = 0; - virtual UInt32 getTableForModifier(UInt32 mask) const = 0; - virtual KeyID getKey(UInt32 table, UInt32 button) const = 0; - - // Convert a character in the current script to the equivalent KeyID - static KeyID getKeyID(UInt8); - - // Convert a unicode character to the equivalent KeyID. - static KeyID unicharToKeyID(UniChar); - }; - - class CKCHRKeyResource : public CKeyResource { - public: - CKCHRKeyResource(const void*); - - // CKeyResource overrides - virtual bool isValid() const; - virtual UInt32 getNumModifierCombinations() const; - virtual UInt32 getNumTables() const; - virtual UInt32 getNumButtons() const; - virtual UInt32 getTableForModifier(UInt32 mask) const; - virtual KeyID getKey(UInt32 table, UInt32 button) const; - - private: - struct KCHRResource { - public: - SInt16 m_version; - UInt8 m_tableSelectionIndex[256]; - SInt16 m_numTables; - UInt8 m_characterTables[1][128]; - }; - struct CKCHRDeadKeyRecord { - public: - UInt8 m_tableIndex; - UInt8 m_virtualKey; - SInt16 m_numCompletions; - UInt8 m_completion[1][2]; - }; - struct CKCHRDeadKeys { - public: - SInt16 m_numRecords; - CKCHRDeadKeyRecord m_records[1]; - }; - - const KCHRResource* m_resource; - }; - - class CUCHRKeyResource : public CKeyResource { - public: - CUCHRKeyResource(const void*, UInt32 keyboardType); - - // CKeyResource overrides - virtual bool isValid() const; - virtual UInt32 getNumModifierCombinations() const; - virtual UInt32 getNumTables() const; - virtual UInt32 getNumButtons() const; - virtual UInt32 getTableForModifier(UInt32 mask) const; - virtual KeyID getKey(UInt32 table, UInt32 button) const; - - private: - typedef std::vector KeySequence; - - bool getDeadKey(KeySequence& keys, UInt16 index) const; - bool getKeyRecord(KeySequence& keys, - UInt16 index, UInt16& state) const; - bool addSequence(KeySequence& keys, UCKeyCharSeq c) const; - - private: - const UCKeyboardLayout* m_resource; - const UCKeyModifiersToTableNum* m_m; - const UCKeyToCharTableIndex* m_cti; - const UCKeySequenceDataIndex* m_sdi; - const UCKeyStateRecordsIndex* m_sri; - const UCKeyStateTerminators* m_st; - UInt16 m_spaceOutput; - }; - - // OS X uses a physical key if 0 for the 'A' key. synergy reserves - // KeyButton 0 so we offset all OS X physical key ids by this much - // when used as a KeyButton and by minus this much to map a KeyButton - // to a physical button. - enum { - KeyButtonOffset = 1 - }; - - typedef std::map GroupMap; - typedef std::map CVirtualKeyMap; - - CVirtualKeyMap m_virtualKeyMap; - mutable UInt32 m_deadKeyState; - GroupList m_groups; - GroupMap m_groupMap; -}; - -#endif diff --git a/lib/platform/COSXScreen.cpp b/lib/platform/COSXScreen.cpp deleted file mode 100644 index 82574cf4..00000000 --- a/lib/platform/COSXScreen.cpp +++ /dev/null @@ -1,1699 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "COSXScreen.h" -#include "COSXClipboard.h" -#include "COSXEventQueueBuffer.h" -#include "COSXKeyState.h" -#include "COSXScreenSaver.h" -#include "CClipboard.h" -#include "CKeyMap.h" -#include "CCondVar.h" -#include "CLock.h" -#include "CMutex.h" -#include "CThread.h" -#include "CLog.h" -#include "IEventQueue.h" -#include "TMethodEventJob.h" -#include "TMethodJob.h" -#include "XArch.h" - -#include -#include - -// Set some enums for fast user switching if we're building with an SDK -// from before such support was added. -#if !defined(MAC_OS_X_VERSION_10_3) || \ - (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_3) -enum { - kEventClassSystem = 'macs', - kEventSystemUserSessionActivated = 10, - kEventSystemUserSessionDeactivated = 11 -}; -#endif - -// This isn't in any Apple SDK that I know of as of yet. -enum { - kSynergyEventMouseScroll = 11, - kSynergyMouseScrollAxisX = 'saxx', - kSynergyMouseScrollAxisY = 'saxy' -}; - -// -// COSXScreen -// - -bool COSXScreen::s_testedForGHOM = false; -bool COSXScreen::s_hasGHOM = false; -CEvent::Type COSXScreen::s_confirmSleepEvent = CEvent::kUnknown; - -COSXScreen::COSXScreen(bool isPrimary) : - m_isPrimary(isPrimary), - m_isOnScreen(m_isPrimary), - m_cursorPosValid(false), - m_cursorHidden(false), - m_dragNumButtonsDown(0), - m_dragTimer(NULL), - m_keyState(NULL), - m_sequenceNumber(0), - m_screensaver(NULL), - m_screensaverNotify(false), - m_ownClipboard(false), - m_clipboardTimer(NULL), - m_hiddenWindow(NULL), - m_userInputWindow(NULL), - m_displayManagerNotificationUPP(NULL), - m_switchEventHandlerRef(0), - m_pmMutex(new CMutex), - m_pmWatchThread(NULL), - m_pmThreadReady(new CCondVar(m_pmMutex, false)), - m_activeModifierHotKey(0), - m_activeModifierHotKeyMask(0) -{ - try { - m_displayID = CGMainDisplayID(); - updateScreenShape(); - m_screensaver = new COSXScreenSaver(getEventTarget()); - m_keyState = new COSXKeyState(); - - if (m_isPrimary) { - // 1x1 window (to minimze the back buffer allocated for this - // window. - Rect bounds = { 100, 100, 101, 101 }; - - // m_hiddenWindow is a window meant to let us get mouse moves - // when the focus is on another computer. If you get your event - // from the application event target you'll get every mouse - // moves. On the other hand the Window event target will only - // get events when the mouse moves over the window. - - // The ignoreClicks attributes makes it impossible for the - // user to click on our invisible window. - CreateNewWindow(kUtilityWindowClass, - kWindowNoShadowAttribute | - kWindowIgnoreClicksAttribute | - kWindowNoActivatesAttribute, - &bounds, &m_hiddenWindow); - - // Make it invisible - SetWindowAlpha(m_hiddenWindow, 0); - ShowWindow(m_hiddenWindow); - - // m_userInputWindow is a window meant to let us get mouse moves - // when the focus is on this computer. - Rect inputBounds = { 100, 100, 200, 200 }; - CreateNewWindow(kUtilityWindowClass, - kWindowNoShadowAttribute | - kWindowOpaqueForEventsAttribute | - kWindowStandardHandlerAttribute, - &inputBounds, &m_userInputWindow); - - SetWindowAlpha(m_userInputWindow, 0); - } - - // install display manager notification handler - m_displayManagerNotificationUPP = - NewDMExtendedNotificationUPP(displayManagerCallback); - OSStatus err = GetCurrentProcess(&m_PSN); - err = DMRegisterExtendedNotifyProc(m_displayManagerNotificationUPP, - this, 0, &m_PSN); - - // install fast user switching event handler - EventTypeSpec switchEventTypes[2]; - switchEventTypes[0].eventClass = kEventClassSystem; - switchEventTypes[0].eventKind = kEventSystemUserSessionDeactivated; - switchEventTypes[1].eventClass = kEventClassSystem; - switchEventTypes[1].eventKind = kEventSystemUserSessionActivated; - EventHandlerUPP switchEventHandler = - NewEventHandlerUPP(userSwitchCallback); - InstallApplicationEventHandler(switchEventHandler, 2, switchEventTypes, - this, &m_switchEventHandlerRef); - DisposeEventHandlerUPP(switchEventHandler); - - // watch for requests to sleep - EVENTQUEUE->adoptHandler(COSXScreen::getConfirmSleepEvent(), - getEventTarget(), - new TMethodEventJob(this, - &COSXScreen::handleConfirmSleep)); - - // create thread for monitoring system power state. - LOG((CLOG_DEBUG "starting watchSystemPowerThread")); - m_pmWatchThread = new CThread(new TMethodJob - (this, &COSXScreen::watchSystemPowerThread)); - } - catch (...) { - EVENTQUEUE->removeHandler(COSXScreen::getConfirmSleepEvent(), - getEventTarget()); - if (m_switchEventHandlerRef != 0) { - RemoveEventHandler(m_switchEventHandlerRef); - } - if (m_displayManagerNotificationUPP != NULL) { - DMRemoveExtendedNotifyProc(m_displayManagerNotificationUPP, - NULL, &m_PSN, 0); - } - - if (m_hiddenWindow) { - ReleaseWindow(m_hiddenWindow); - m_hiddenWindow = NULL; - } - - if (m_userInputWindow) { - ReleaseWindow(m_userInputWindow); - m_userInputWindow = NULL; - } - delete m_keyState; - delete m_screensaver; - throw; - } - - // install event handlers - EVENTQUEUE->adoptHandler(CEvent::kSystem, IEventQueue::getSystemTarget(), - new TMethodEventJob(this, - &COSXScreen::handleSystemEvent)); - - // install the platform event queue - EVENTQUEUE->adoptBuffer(new COSXEventQueueBuffer); -} - -COSXScreen::~COSXScreen() -{ - disable(); - EVENTQUEUE->adoptBuffer(NULL); - EVENTQUEUE->removeHandler(CEvent::kSystem, IEventQueue::getSystemTarget()); - - if (m_pmWatchThread) { - // make sure the thread has setup the runloop. - { - CLock lock(m_pmMutex); - while (!(bool)*m_pmThreadReady) { - m_pmThreadReady->wait(); - } - } - - // now exit the thread's runloop and wait for it to exit - LOG((CLOG_DEBUG "stopping watchSystemPowerThread")); - CFRunLoopStop(m_pmRunloop); - m_pmWatchThread->wait(); - delete m_pmWatchThread; - m_pmWatchThread = NULL; - } - delete m_pmThreadReady; - delete m_pmMutex; - - EVENTQUEUE->removeHandler(COSXScreen::getConfirmSleepEvent(), - getEventTarget()); - - RemoveEventHandler(m_switchEventHandlerRef); - - DMRemoveExtendedNotifyProc(m_displayManagerNotificationUPP, - NULL, &m_PSN, 0); - - if (m_hiddenWindow) { - ReleaseWindow(m_hiddenWindow); - m_hiddenWindow = NULL; - } - - if (m_userInputWindow) { - ReleaseWindow(m_userInputWindow); - m_userInputWindow = NULL; - } - - delete m_keyState; - delete m_screensaver; -} - -void* -COSXScreen::getEventTarget() const -{ - return const_cast(this); -} - -bool -COSXScreen::getClipboard(ClipboardID, IClipboard* dst) const -{ - COSXClipboard src; - CClipboard::copy(dst, &src); - return true; -} - -void -COSXScreen::getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h) const -{ - x = m_x; - y = m_y; - w = m_w; - h = m_h; -} - -void -COSXScreen::getCursorPos(SInt32& x, SInt32& y) const -{ - Point mouse; - GetGlobalMouse(&mouse); - x = mouse.h; - y = mouse.v; - m_cursorPosValid = true; - m_xCursor = x; - m_yCursor = y; -} - -void -COSXScreen::reconfigure(UInt32) -{ - // do nothing -} - -void -COSXScreen::warpCursor(SInt32 x, SInt32 y) -{ - // move cursor without generating events - CGPoint pos; - pos.x = x; - pos.y = y; - CGWarpMouseCursorPosition(pos); - - // save new cursor position - m_xCursor = x; - m_yCursor = y; - m_cursorPosValid = true; -} - -void -COSXScreen::fakeInputBegin() -{ - // FIXME -- not implemented -} - -void -COSXScreen::fakeInputEnd() -{ - // FIXME -- not implemented -} - -SInt32 -COSXScreen::getJumpZoneSize() const -{ - return 1; -} - -bool -COSXScreen::isAnyMouseButtonDown() const -{ - return (GetCurrentButtonState() != 0); -} - -void -COSXScreen::getCursorCenter(SInt32& x, SInt32& y) const -{ - x = m_xCenter; - y = m_yCenter; -} - -UInt32 -COSXScreen::registerHotKey(KeyID key, KeyModifierMask mask) -{ - // get mac virtual key and modifier mask matching synergy key and mask - UInt32 macKey, macMask; - if (!m_keyState->mapSynergyHotKeyToMac(key, mask, macKey, macMask)) { - LOG((CLOG_WARN "could not map hotkey id=%04x mask=%04x", key, mask)); - return 0; - } - - // choose hotkey id - UInt32 id; - if (!m_oldHotKeyIDs.empty()) { - id = m_oldHotKeyIDs.back(); - m_oldHotKeyIDs.pop_back(); - } - else { - id = m_hotKeys.size() + 1; - } - - // if this hot key has modifiers only then we'll handle it specially - EventHotKeyRef ref = NULL; - bool okay; - if (key == kKeyNone) { - if (m_modifierHotKeys.count(mask) > 0) { - // already registered - okay = false; - } - else { - m_modifierHotKeys[mask] = id; - okay = true; - } - } - else { - EventHotKeyID hkid = { 'SNRG', (UInt32)id }; - OSStatus status = RegisterEventHotKey(macKey, macMask, hkid, - GetApplicationEventTarget(), 0, - &ref); - okay = (status == noErr); - m_hotKeyToIDMap[CHotKeyItem(macKey, macMask)] = id; - } - - if (!okay) { - m_oldHotKeyIDs.push_back(id); - m_hotKeyToIDMap.erase(CHotKeyItem(macKey, macMask)); - LOG((CLOG_WARN "failed to register hotkey %s (id=%04x mask=%04x)", CKeyMap::formatKey(key, mask).c_str(), key, mask)); - return 0; - } - - m_hotKeys.insert(std::make_pair(id, CHotKeyItem(ref, macKey, macMask))); - - LOG((CLOG_DEBUG "registered hotkey %s (id=%04x mask=%04x) as id=%d", CKeyMap::formatKey(key, mask).c_str(), key, mask, id)); - return id; -} - -void -COSXScreen::unregisterHotKey(UInt32 id) -{ - // look up hotkey - HotKeyMap::iterator i = m_hotKeys.find(id); - if (i == m_hotKeys.end()) { - return; - } - - // unregister with OS - bool okay; - if (i->second.getRef() != NULL) { - okay = (UnregisterEventHotKey(i->second.getRef()) == noErr); - } - else { - okay = false; - // XXX -- this is inefficient - for (ModifierHotKeyMap::iterator j = m_modifierHotKeys.begin(); - j != m_modifierHotKeys.end(); ++j) { - if (j->second == id) { - m_modifierHotKeys.erase(j); - okay = true; - break; - } - } - } - if (!okay) { - LOG((CLOG_WARN "failed to unregister hotkey id=%d", id)); - } - else { - LOG((CLOG_DEBUG "unregistered hotkey id=%d", id)); - } - - // discard hot key from map and record old id for reuse - m_hotKeyToIDMap.erase(i->second); - m_hotKeys.erase(i); - m_oldHotKeyIDs.push_back(id); - if (m_activeModifierHotKey == id) { - m_activeModifierHotKey = 0; - m_activeModifierHotKeyMask = 0; - } -} - -void -COSXScreen::postMouseEvent(CGPoint& pos) const -{ - // check if cursor position is valid on the client display configuration - // stkamp@users.sourceforge.net - CGDisplayCount displayCount = 0; - CGGetDisplaysWithPoint(pos, 0, NULL, &displayCount); - if (displayCount == 0) { - // cursor position invalid - clamp to bounds of last valid display. - // find the last valid display using the last cursor position. - displayCount = 0; - CGDirectDisplayID displayID; - CGGetDisplaysWithPoint(CGPointMake(m_xCursor, m_yCursor), 1, - &displayID, &displayCount); - if (displayCount != 0) { - CGRect displayRect = CGDisplayBounds(displayID); - if (pos.x < displayRect.origin.x) { - pos.x = displayRect.origin.x; - } - else if (pos.x > displayRect.origin.x + - displayRect.size.width - 1) { - pos.x = displayRect.origin.x + displayRect.size.width - 1; - } - if (pos.y < displayRect.origin.y) { - pos.y = displayRect.origin.y; - } - else if (pos.y > displayRect.origin.y + - displayRect.size.height - 1) { - pos.y = displayRect.origin.y + displayRect.size.height - 1; - } - } - } - - // synthesize event. CGPostMouseEvent is a particularly good - // example of a bad API. we have to shadow the mouse state to - // use this API and if we want to support more buttons we have - // to recompile. - // - // the order of buttons on the mac is: - // 1 - Left - // 2 - Right - // 3 - Middle - // Whatever the USB device defined. - // - // It is a bit weird that the behaviour of buttons over 3 are dependent - // on currently plugged in USB devices. - CGPostMouseEvent(pos, true, sizeof(m_buttons) / sizeof(m_buttons[0]), - m_buttons[0], - m_buttons[2], - m_buttons[1], - m_buttons[3], - m_buttons[4]); -} - - -void -COSXScreen::fakeMouseButton(ButtonID id, bool press) const -{ - // get button index - UInt32 index = id - kButtonLeft; - if (index >= sizeof(m_buttons) / sizeof(m_buttons[0])) { - return; - } - - // update state - m_buttons[index] = press; - - CGPoint pos; - if (!m_cursorPosValid) { - SInt32 x, y; - getCursorPos(x, y); - } - pos.x = m_xCursor; - pos.y = m_yCursor; - postMouseEvent(pos); -} - -void -COSXScreen::fakeMouseMove(SInt32 x, SInt32 y) const -{ - // synthesize event - CGPoint pos; - pos.x = x; - pos.y = y; - postMouseEvent(pos); - - // save new cursor position - m_xCursor = static_cast(pos.x); - m_yCursor = static_cast(pos.y); - m_cursorPosValid = true; -} - -void -COSXScreen::fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const -{ - // OS X does not appear to have a fake relative mouse move function. - // simulate it by getting the current mouse position and adding to - // that. this can yield the wrong answer but there's not much else - // we can do. - - // get current position - Point oldPos; - GetGlobalMouse(&oldPos); - - // synthesize event - CGPoint pos; - m_xCursor = static_cast(oldPos.h); - m_yCursor = static_cast(oldPos.v); - pos.x = oldPos.h + dx; - pos.y = oldPos.v + dy; - postMouseEvent(pos); - - // we now assume we don't know the current cursor position - m_cursorPosValid = false; -} - -void -COSXScreen::fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const -{ - if (xDelta != 0 || yDelta != 0) { - CGPostScrollWheelEvent(2, mapScrollWheelFromSynergy(yDelta), - -mapScrollWheelFromSynergy(xDelta)); - } -} - -void -COSXScreen::enable() -{ - // watch the clipboard - m_clipboardTimer = EVENTQUEUE->newTimer(1.0, NULL); - EVENTQUEUE->adoptHandler(CEvent::kTimer, m_clipboardTimer, - new TMethodEventJob(this, - &COSXScreen::handleClipboardCheck)); - - if (m_isPrimary) { - // FIXME -- start watching jump zones - } - else { - // FIXME -- prevent system from entering power save mode - - // hide cursor - if (!m_cursorHidden) { -// CGDisplayHideCursor(m_displayID); - m_cursorHidden = true; - } - - // warp the mouse to the cursor center - fakeMouseMove(m_xCenter, m_yCenter); - - // FIXME -- prepare to show cursor if it moves - } -} - -void -COSXScreen::disable() -{ - if (m_isPrimary) { - // FIXME -- stop watching jump zones, stop capturing input - } - else { - // show cursor - if (m_cursorHidden) { -// CGDisplayShowCursor(m_displayID); - m_cursorHidden = false; - } - - // FIXME -- allow system to enter power saving mode - } - - // disable drag handling - m_dragNumButtonsDown = 0; - enableDragTimer(false); - - // uninstall clipboard timer - if (m_clipboardTimer != NULL) { - EVENTQUEUE->removeHandler(CEvent::kTimer, m_clipboardTimer); - EVENTQUEUE->deleteTimer(m_clipboardTimer); - m_clipboardTimer = NULL; - } - - m_isOnScreen = m_isPrimary; -} - -void -COSXScreen::enter() -{ - if (m_isPrimary) { - // stop capturing input, watch jump zones - HideWindow( m_userInputWindow ); - ShowWindow( m_hiddenWindow ); - - SetMouseCoalescingEnabled(true, NULL); - - CGSetLocalEventsSuppressionInterval(0.0); - - // enable global hotkeys - setGlobalHotKeysEnabled(true); - } - else { - // show cursor - if (m_cursorHidden) { -// CGDisplayShowCursor(m_displayID); - m_cursorHidden = false; - } - - // reset buttons - for (UInt32 i = 0; i < sizeof(m_buttons) / sizeof(m_buttons[0]); ++i) { - m_buttons[i] = false; - } - - // avoid suppression of local hardware events - // stkamp@users.sourceforge.net - CGSetLocalEventsFilterDuringSupressionState( - kCGEventFilterMaskPermitAllEvents, - kCGEventSupressionStateSupressionInterval); - CGSetLocalEventsFilterDuringSupressionState( - (kCGEventFilterMaskPermitLocalKeyboardEvents | - kCGEventFilterMaskPermitSystemDefinedEvents), - kCGEventSupressionStateRemoteMouseDrag); - } - - // now on screen - m_isOnScreen = true; -} - -bool -COSXScreen::leave() -{ - if (m_isPrimary) { - // warp to center - warpCursor(m_xCenter, m_yCenter); - - // capture events - HideWindow(m_hiddenWindow); - ShowWindow(m_userInputWindow); - RepositionWindow(m_userInputWindow, - m_userInputWindow, kWindowCenterOnMainScreen); - SetUserFocusWindow(m_userInputWindow); - - // The OS will coalesce some events if they are similar enough in a - // short period of time this is bad for us since we need every event - // to send it over to other machines. So disable it. - SetMouseCoalescingEnabled(false, NULL); - CGSetLocalEventsSuppressionInterval(0.0001); - - // disable global hotkeys - setGlobalHotKeysEnabled(false); - } - else { - // hide cursor - if (!m_cursorHidden) { -// CGDisplayHideCursor(m_displayID); - m_cursorHidden = true; - } - - // warp the mouse to the cursor center - fakeMouseMove(m_xCenter, m_yCenter); - - // FIXME -- prepare to show cursor if it moves - - // take keyboard focus - // FIXME - } - - // now off screen - m_isOnScreen = false; - - return true; -} - -bool -COSXScreen::setClipboard(ClipboardID, const IClipboard* src) -{ - COSXClipboard dst; - if (src != NULL) { - // save clipboard data - if (!CClipboard::copy(&dst, src)) { - return false; - } - } - else { - // assert clipboard ownership - if (!dst.open(0)) { - return false; - } - dst.empty(); - dst.close(); - } - checkClipboards(); - return true; -} - -void -COSXScreen::checkClipboards() -{ - // check if clipboard ownership changed - if (!COSXClipboard::isOwnedBySynergy()) { - if (m_ownClipboard) { - LOG((CLOG_DEBUG "clipboard changed: lost ownership")); - m_ownClipboard = false; - sendClipboardEvent(getClipboardGrabbedEvent(), kClipboardClipboard); - sendClipboardEvent(getClipboardGrabbedEvent(), kClipboardSelection); - } - } - else if (!m_ownClipboard) { - LOG((CLOG_DEBUG "clipboard changed: synergy owned")); - m_ownClipboard = true; - } -} - -void -COSXScreen::openScreensaver(bool notify) -{ - m_screensaverNotify = notify; - if (!m_screensaverNotify) { - m_screensaver->disable(); - } -} - -void -COSXScreen::closeScreensaver() -{ - if (!m_screensaverNotify) { - m_screensaver->enable(); - } -} - -void -COSXScreen::screensaver(bool activate) -{ - if (activate) { - m_screensaver->activate(); - } - else { - m_screensaver->deactivate(); - } -} - -void -COSXScreen::resetOptions() -{ - // no options -} - -void -COSXScreen::setOptions(const COptionsList&) -{ - // no options -} - -void -COSXScreen::setSequenceNumber(UInt32 seqNum) -{ - m_sequenceNumber = seqNum; -} - -bool -COSXScreen::isPrimary() const -{ - return m_isPrimary; -} - -void -COSXScreen::sendEvent(CEvent::Type type, void* data) const -{ - EVENTQUEUE->addEvent(CEvent(type, getEventTarget(), data)); -} - -void -COSXScreen::sendClipboardEvent(CEvent::Type type, ClipboardID id) const -{ - CClipboardInfo* info = (CClipboardInfo*)malloc(sizeof(CClipboardInfo)); - info->m_id = id; - info->m_sequenceNumber = m_sequenceNumber; - sendEvent(type, info); -} - -void -COSXScreen::handleSystemEvent(const CEvent& event, void*) -{ - EventRef* carbonEvent = reinterpret_cast(event.getData()); - assert(carbonEvent != NULL); - - UInt32 eventClass = GetEventClass(*carbonEvent); - - switch (eventClass) { - case kEventClassMouse: - switch (GetEventKind(*carbonEvent)) { - case kEventMouseDown: - { - UInt16 myButton; - GetEventParameter(*carbonEvent, - kEventParamMouseButton, - typeMouseButton, - NULL, - sizeof(myButton), - NULL, - &myButton); - onMouseButton(true, myButton); - break; - } - - case kEventMouseUp: - { - UInt16 myButton; - GetEventParameter(*carbonEvent, - kEventParamMouseButton, - typeMouseButton, - NULL, - sizeof(myButton), - NULL, - &myButton); - onMouseButton(false, myButton); - break; - } - - case kEventMouseDragged: - case kEventMouseMoved: - { - HIPoint point; - GetEventParameter(*carbonEvent, - kEventParamMouseLocation, - typeHIPoint, - NULL, - sizeof(point), - NULL, - &point); - onMouseMove((SInt32)point.x, (SInt32)point.y); - break; - } - - case kEventMouseWheelMoved: - { - EventMouseWheelAxis axis; - SInt32 delta; - GetEventParameter(*carbonEvent, - kEventParamMouseWheelAxis, - typeMouseWheelAxis, - NULL, - sizeof(axis), - NULL, - &axis); - if (axis == kEventMouseWheelAxisX || - axis == kEventMouseWheelAxisY) { - GetEventParameter(*carbonEvent, - kEventParamMouseWheelDelta, - typeLongInteger, - NULL, - sizeof(delta), - NULL, - &delta); - if (axis == kEventMouseWheelAxisX) { - onMouseWheel(-mapScrollWheelToSynergy((SInt32)delta), 0); - } - else { - onMouseWheel(0, mapScrollWheelToSynergy((SInt32)delta)); - } - } - break; - } - - case kSynergyEventMouseScroll: - { - OSStatus r; - long xScroll; - long yScroll; - - // get scroll amount - r = GetEventParameter(*carbonEvent, - kSynergyMouseScrollAxisX, - typeLongInteger, - NULL, - sizeof(xScroll), - NULL, - &xScroll); - if (r != noErr) { - xScroll = 0; - } - r = GetEventParameter(*carbonEvent, - kSynergyMouseScrollAxisY, - typeLongInteger, - NULL, - sizeof(yScroll), - NULL, - &yScroll); - if (r != noErr) { - yScroll = 0; - } - - if (xScroll != 0 || yScroll != 0) { - onMouseWheel(-mapScrollWheelToSynergy(xScroll), - mapScrollWheelToSynergy(yScroll)); - } - } - } - break; - - case kEventClassKeyboard: - switch (GetEventKind(*carbonEvent)) { - case kEventRawKeyUp: - case kEventRawKeyDown: - case kEventRawKeyRepeat: - case kEventRawKeyModifiersChanged: - onKey(*carbonEvent); - break; - - case kEventHotKeyPressed: - case kEventHotKeyReleased: - onHotKey(*carbonEvent); - break; - } - - break; - - case kEventClassWindow: - SendEventToWindow(*carbonEvent, m_userInputWindow); - switch (GetEventKind(*carbonEvent)) { - case kEventWindowActivated: - LOG((CLOG_DEBUG1 "window activated")); - break; - - case kEventWindowDeactivated: - LOG((CLOG_DEBUG1 "window deactivated")); - break; - - case kEventWindowFocusAcquired: - LOG((CLOG_DEBUG1 "focus acquired")); - break; - - case kEventWindowFocusRelinquish: - LOG((CLOG_DEBUG1 "focus released")); - break; - } - break; - - default: - SendEventToEventTarget(*carbonEvent, GetEventDispatcherTarget()); - break; - } -} - -bool -COSXScreen::onMouseMove(SInt32 mx, SInt32 my) -{ - LOG((CLOG_DEBUG2 "mouse move %+d,%+d", mx, my)); - - SInt32 x = mx - m_xCursor; - SInt32 y = my - m_yCursor; - - if ((x == 0 && y == 0) || (mx == m_xCenter && mx == m_yCenter)) { - return true; - } - - // save position to compute delta of next motion - m_xCursor = mx; - m_yCursor = my; - - if (m_isOnScreen) { - // motion on primary screen - sendEvent(getMotionOnPrimaryEvent(), - CMotionInfo::alloc(m_xCursor, m_yCursor)); - } - else { - // motion on secondary screen. warp mouse back to - // center. - warpCursor(m_xCenter, m_yCenter); - - // examine the motion. if it's about the distance - // from the center of the screen to an edge then - // it's probably a bogus motion that we want to - // ignore (see warpCursorNoFlush() for a further - // description). - static SInt32 bogusZoneSize = 10; - if (-x + bogusZoneSize > m_xCenter - m_x || - x + bogusZoneSize > m_x + m_w - m_xCenter || - -y + bogusZoneSize > m_yCenter - m_y || - y + bogusZoneSize > m_y + m_h - m_yCenter) { - LOG((CLOG_DEBUG "dropped bogus motion %+d,%+d", x, y)); - } - else { - // send motion - sendEvent(getMotionOnSecondaryEvent(), CMotionInfo::alloc(x, y)); - } - } - - return true; -} - -bool -COSXScreen::onMouseButton(bool pressed, UInt16 macButton) -{ - // Buttons 2 and 3 are inverted on the mac - ButtonID button = mapMacButtonToSynergy(macButton); - - if (pressed) { - LOG((CLOG_DEBUG1 "event: button press button=%d", button)); - if (button != kButtonNone) { - KeyModifierMask mask = m_keyState->getActiveModifiers(); - sendEvent(getButtonDownEvent(), CButtonInfo::alloc(button, mask)); - } - } - else { - LOG((CLOG_DEBUG1 "event: button release button=%d", button)); - if (button != kButtonNone) { - KeyModifierMask mask = m_keyState->getActiveModifiers(); - sendEvent(getButtonUpEvent(), CButtonInfo::alloc(button, mask)); - } - } - - // handle drags with any button other than button 1 or 2 - if (macButton > 2) { - if (pressed) { - // one more button - if (m_dragNumButtonsDown++ == 0) { - enableDragTimer(true); - } - } - else { - // one less button - if (--m_dragNumButtonsDown == 0) { - enableDragTimer(false); - } - } - } - - return true; -} - -bool -COSXScreen::onMouseWheel(SInt32 xDelta, SInt32 yDelta) const -{ - LOG((CLOG_DEBUG1 "event: button wheel delta=%+d,%+d", xDelta, yDelta)); - sendEvent(getWheelEvent(), CWheelInfo::alloc(xDelta, yDelta)); - return true; -} - -void -COSXScreen::handleClipboardCheck(const CEvent&, void*) -{ - checkClipboards(); -} - -pascal void -COSXScreen::displayManagerCallback(void* inUserData, SInt16 inMessage, void*) -{ - COSXScreen* screen = (COSXScreen*)inUserData; - - if (inMessage == kDMNotifyEvent) { - screen->onDisplayChange(); - } -} - -bool -COSXScreen::onDisplayChange() -{ - // screen resolution may have changed. save old shape. - SInt32 xOld = m_x, yOld = m_y, wOld = m_w, hOld = m_h; - - // update shape - updateScreenShape(); - - // do nothing if resolution hasn't changed - if (xOld != m_x || yOld != m_y || wOld != m_w || hOld != m_h) { - if (m_isPrimary) { - // warp mouse to center if off screen - if (!m_isOnScreen) { - warpCursor(m_xCenter, m_yCenter); - } - } - - // send new screen info - sendEvent(getShapeChangedEvent()); - } - - return true; -} - -bool -COSXScreen::onKey(EventRef event) -{ - UInt32 eventKind = GetEventKind(event); - - // get the key and active modifiers - UInt32 virtualKey, macMask; - GetEventParameter(event, kEventParamKeyCode, typeUInt32, - NULL, sizeof(virtualKey), NULL, &virtualKey); - GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, - NULL, sizeof(macMask), NULL, &macMask); - LOG((CLOG_DEBUG1 "event: Key event kind: %d, keycode=%d", eventKind, virtualKey)); - - // sadly, OS X doesn't report the virtualKey for modifier keys. - // virtualKey will be zero for modifier keys. since that's not good - // enough we'll have to figure out what the key was. - if (virtualKey == 0 && eventKind == kEventRawKeyModifiersChanged) { - // get old and new modifier state - KeyModifierMask oldMask = getActiveModifiers(); - KeyModifierMask newMask = m_keyState->mapModifiersFromOSX(macMask); - m_keyState->handleModifierKeys(getEventTarget(), oldMask, newMask); - - // if the current set of modifiers exactly matches a modifiers-only - // hot key then generate a hot key down event. - if (m_activeModifierHotKey == 0) { - if (m_modifierHotKeys.count(newMask) > 0) { - m_activeModifierHotKey = m_modifierHotKeys[newMask]; - m_activeModifierHotKeyMask = newMask; - EVENTQUEUE->addEvent(CEvent(getHotKeyDownEvent(), - getEventTarget(), - CHotKeyInfo::alloc(m_activeModifierHotKey))); - } - } - - // if a modifiers-only hot key is active and should no longer be - // then generate a hot key up event. - else if (m_activeModifierHotKey != 0) { - KeyModifierMask mask = (newMask & m_activeModifierHotKeyMask); - if (mask != m_activeModifierHotKeyMask) { - EVENTQUEUE->addEvent(CEvent(getHotKeyUpEvent(), - getEventTarget(), - CHotKeyInfo::alloc(m_activeModifierHotKey))); - m_activeModifierHotKey = 0; - m_activeModifierHotKeyMask = 0; - } - } - - return true; - } - - // check for hot key. when we're on a secondary screen we disable - // all hotkeys so we can capture the OS defined hot keys as regular - // keystrokes but that means we don't get our own hot keys either. - // so we check for a key/modifier match in our hot key map. - if (!m_isOnScreen) { - HotKeyToIDMap::const_iterator i = - m_hotKeyToIDMap.find(CHotKeyItem(virtualKey, macMask & 0xff00u)); - if (i != m_hotKeyToIDMap.end()) { - UInt32 id = i->second; - - // determine event type - CEvent::Type type; - UInt32 eventKind = GetEventKind(event); - if (eventKind == kEventRawKeyDown) { - type = getHotKeyDownEvent(); - } - else if (eventKind == kEventRawKeyUp) { - type = getHotKeyUpEvent(); - } - else { - return false; - } - - EVENTQUEUE->addEvent(CEvent(type, getEventTarget(), - CHotKeyInfo::alloc(id))); - - return true; - } - } - - // decode event type - bool down = (eventKind == kEventRawKeyDown); - bool up = (eventKind == kEventRawKeyUp); - bool isRepeat = (eventKind == kEventRawKeyRepeat); - - // map event to keys - KeyModifierMask mask; - COSXKeyState::CKeyIDs keys; - KeyButton button = m_keyState->mapKeyFromEvent(keys, &mask, event); - if (button == 0) { - return false; - } - - // check for AltGr in mask. if set we send neither the AltGr nor - // the super modifiers to clients then remove AltGr before passing - // the modifiers to onKey. - KeyModifierMask sendMask = (mask & ~KeyModifierAltGr); - if ((mask & KeyModifierAltGr) != 0) { - sendMask &= ~KeyModifierSuper; - } - mask &= ~KeyModifierAltGr; - - // update button state - if (down) { - m_keyState->onKey(button, true, mask); - } - else if (up) { - if (!m_keyState->isKeyDown(button)) { - // up event for a dead key. throw it away. - return false; - } - m_keyState->onKey(button, false, mask); - } - - // send key events - for (COSXKeyState::CKeyIDs::const_iterator i = keys.begin(); - i != keys.end(); ++i) { - m_keyState->sendKeyEvent(getEventTarget(), down, isRepeat, - *i, sendMask, 1, button); - } - - return true; -} - -bool -COSXScreen::onHotKey(EventRef event) const -{ - // get the hotkey id - EventHotKeyID hkid; - GetEventParameter(event, kEventParamDirectObject, typeEventHotKeyID, - NULL, sizeof(EventHotKeyID), NULL, &hkid); - UInt32 id = hkid.id; - - // determine event type - CEvent::Type type; - UInt32 eventKind = GetEventKind(event); - if (eventKind == kEventHotKeyPressed) { - type = getHotKeyDownEvent(); - } - else if (eventKind == kEventHotKeyReleased) { - type = getHotKeyUpEvent(); - } - else { - return false; - } - - EVENTQUEUE->addEvent(CEvent(type, getEventTarget(), - CHotKeyInfo::alloc(id))); - - return true; -} - -ButtonID -COSXScreen::mapMacButtonToSynergy(UInt16 macButton) const -{ - switch (macButton) { - case 1: - return kButtonLeft; - - case 2: - return kButtonRight; - - case 3: - return kButtonMiddle; - } - - return static_cast(macButton); -} - -SInt32 -COSXScreen::mapScrollWheelToSynergy(SInt32 x) const -{ - // return accelerated scrolling but not exponentially scaled as it is - // on the mac. - double d = (1.0 + getScrollSpeed()) * x / getScrollSpeedFactor(); - return static_cast(120.0 * d); -} - -SInt32 -COSXScreen::mapScrollWheelFromSynergy(SInt32 x) const -{ - // use server's acceleration with a little boost since other platforms - // take one wheel step as a larger step than the mac does. - return static_cast(3.0 * x / 120.0); -} - -double -COSXScreen::getScrollSpeed() const -{ - double scaling = 0.0; - - CFPropertyListRef pref = ::CFPreferencesCopyValue( - CFSTR("com.apple.scrollwheel.scaling") , - kCFPreferencesAnyApplication, - kCFPreferencesCurrentUser, - kCFPreferencesAnyHost); - if (pref != NULL) { - CFTypeID id = CFGetTypeID(pref); - if (id == CFNumberGetTypeID()) { - CFNumberRef value = static_cast(pref); - if (CFNumberGetValue(value, kCFNumberDoubleType, &scaling)) { - if (scaling < 0.0) { - scaling = 0.0; - } - } - } - CFRelease(pref); - } - - return scaling; -} - -double -COSXScreen::getScrollSpeedFactor() const -{ - return pow(10.0, getScrollSpeed()); -} - -void -COSXScreen::enableDragTimer(bool enable) -{ - if (enable && m_dragTimer == NULL) { - m_dragTimer = EVENTQUEUE->newTimer(0.01, NULL); - EVENTQUEUE->adoptHandler(CEvent::kTimer, m_dragTimer, - new TMethodEventJob(this, - &COSXScreen::handleDrag)); - GetMouse(&m_dragLastPoint); - } - else if (!enable && m_dragTimer != NULL) { - EVENTQUEUE->removeHandler(CEvent::kTimer, m_dragTimer); - EVENTQUEUE->deleteTimer(m_dragTimer); - m_dragTimer = NULL; - } -} - -void -COSXScreen::handleDrag(const CEvent&, void*) -{ - Point p; - GetMouse(&p); - if (p.h != m_dragLastPoint.h || p.v != m_dragLastPoint.v) { - m_dragLastPoint = p; - onMouseMove((SInt32)p.h, (SInt32)p.v); - } -} - -void -COSXScreen::updateButtons() -{ - UInt32 buttons = GetCurrentButtonState(); - for (size_t i = 0; i < sizeof(m_buttons) / sizeof(m_buttons[0]); ++i) { - m_buttons[i] = ((buttons & (1u << i)) != 0); - } -} - -IKeyState* -COSXScreen::getKeyState() const -{ - return m_keyState; -} - -void -COSXScreen::updateScreenShape() -{ - // get info for each display - CGDisplayCount displayCount = 0; - - if (CGGetActiveDisplayList(0, NULL, &displayCount) != CGDisplayNoErr) { - return; - } - - if (displayCount == 0) { - return; - } - - CGDirectDisplayID* displays = new CGDirectDisplayID[displayCount]; - if (displays == NULL) { - return; - } - - if (CGGetActiveDisplayList(displayCount, - displays, &displayCount) != CGDisplayNoErr) { - delete[] displays; - return; - } - - // get smallest rect enclosing all display rects - CGRect totalBounds = CGRectZero; - for (CGDisplayCount i = 0; i < displayCount; ++i) { - CGRect bounds = CGDisplayBounds(displays[i]); - totalBounds = CGRectUnion(totalBounds, bounds); - } - - // get shape of default screen - m_x = (SInt32)totalBounds.origin.x; - m_y = (SInt32)totalBounds.origin.y; - m_w = (SInt32)totalBounds.size.width; - m_h = (SInt32)totalBounds.size.height; - - // get center of default screen - GDHandle mainScreen = GetMainDevice(); - if (mainScreen != NULL) { - const Rect& rect = (*mainScreen)->gdRect; - m_xCenter = (rect.left + rect.right) / 2; - m_yCenter = (rect.top + rect.bottom) / 2; - } - else { - m_xCenter = m_x + (m_w >> 1); - m_yCenter = m_y + (m_h >> 1); - } - - delete[] displays; - - LOG((CLOG_DEBUG "screen shape: %d,%d %dx%d on %u %s", m_x, m_y, m_w, m_h, displayCount, (displayCount == 1) ? "display" : "displays")); -} - -#pragma mark - - -// -// FAST USER SWITCH NOTIFICATION SUPPORT -// -// COSXScreen::userSwitchCallback(void*) -// -// gets called if a fast user switch occurs -// - -pascal OSStatus -COSXScreen::userSwitchCallback(EventHandlerCallRef nextHandler, - EventRef theEvent, - void* inUserData) -{ - COSXScreen* screen = (COSXScreen*)inUserData; - UInt32 kind = GetEventKind(theEvent); - - if (kind == kEventSystemUserSessionDeactivated) { - LOG((CLOG_DEBUG "user session deactivated")); - EVENTQUEUE->addEvent(CEvent(IScreen::getSuspendEvent(), - screen->getEventTarget())); - } - else if (kind == kEventSystemUserSessionActivated) { - LOG((CLOG_DEBUG "user session activated")); - EVENTQUEUE->addEvent(CEvent(IScreen::getResumeEvent(), - screen->getEventTarget())); - } - return (CallNextEventHandler(nextHandler, theEvent)); -} - -#pragma mark - - -// -// SLEEP/WAKEUP NOTIFICATION SUPPORT -// -// COSXScreen::watchSystemPowerThread(void*) -// -// main of thread monitoring system power (sleep/wakup) using a CFRunLoop -// - -void -COSXScreen::watchSystemPowerThread(void*) -{ - io_object_t notifier; - IONotificationPortRef notificationPortRef; - CFRunLoopSourceRef runloopSourceRef = 0; - - m_pmRunloop = CFRunLoopGetCurrent(); - - // install system power change callback - m_pmRootPort = IORegisterForSystemPower(this, ¬ificationPortRef, - powerChangeCallback, ¬ifier); - if (m_pmRootPort == 0) { - LOG((CLOG_WARN "IORegisterForSystemPower failed")); - } - else { - runloopSourceRef = - IONotificationPortGetRunLoopSource(notificationPortRef); - CFRunLoopAddSource(m_pmRunloop, runloopSourceRef, - kCFRunLoopCommonModes); - } - - // thread is ready - { - CLock lock(m_pmMutex); - *m_pmThreadReady = true; - m_pmThreadReady->signal(); - } - - // if we were unable to initialize then exit. we must do this after - // setting m_pmThreadReady to true otherwise the parent thread will - // block waiting for it. - if (m_pmRootPort == 0) { - return; - } - - // start the run loop - LOG((CLOG_DEBUG "started watchSystemPowerThread")); - CFRunLoopRun(); - - // cleanup - if (notificationPortRef) { - CFRunLoopRemoveSource(m_pmRunloop, - runloopSourceRef, kCFRunLoopDefaultMode); - CFRunLoopSourceInvalidate(runloopSourceRef); - CFRelease(runloopSourceRef); - } - - CLock lock(m_pmMutex); - IODeregisterForSystemPower(¬ifier); - m_pmRootPort = 0; - LOG((CLOG_DEBUG "stopped watchSystemPowerThread")); -} - -void -COSXScreen::powerChangeCallback(void* refcon, io_service_t service, - natural_t messageType, void* messageArg) -{ - ((COSXScreen*)refcon)->handlePowerChangeRequest(messageType, messageArg); -} - -void -COSXScreen::handlePowerChangeRequest(natural_t messageType, void* messageArg) -{ - // we've received a power change notification - switch (messageType) { - case kIOMessageSystemWillSleep: - // COSXScreen has to handle this in the main thread so we have to - // queue a confirm sleep event here. we actually don't allow the - // system to sleep until the event is handled. - EVENTQUEUE->addEvent(CEvent(COSXScreen::getConfirmSleepEvent(), - getEventTarget(), messageArg, - CEvent::kDontFreeData)); - return; - - case kIOMessageSystemHasPoweredOn: - LOG((CLOG_DEBUG "system wakeup")); - EVENTQUEUE->addEvent(CEvent(IScreen::getResumeEvent(), - getEventTarget())); - break; - - default: - break; - } - - CLock lock(m_pmMutex); - if (m_pmRootPort != 0) { - IOAllowPowerChange(m_pmRootPort, (long)messageArg); - } -} - -CEvent::Type -COSXScreen::getConfirmSleepEvent() -{ - return CEvent::registerTypeOnce(s_confirmSleepEvent, - "COSXScreen::confirmSleep"); -} - -void -COSXScreen::handleConfirmSleep(const CEvent& event, void*) -{ - long messageArg = (long)event.getData(); - if (messageArg != 0) { - CLock lock(m_pmMutex); - if (m_pmRootPort != 0) { - // deliver suspend event immediately. - EVENTQUEUE->addEvent(CEvent(IScreen::getSuspendEvent(), - getEventTarget(), NULL, - CEvent::kDeliverImmediately)); - - LOG((CLOG_DEBUG "system will sleep")); - IOAllowPowerChange(m_pmRootPort, messageArg); - } - } -} - -#pragma mark - - -// -// GLOBAL HOTKEY OPERATING MODE SUPPORT (10.3) -// -// CoreGraphics private API (OSX 10.3) -// Source: http://ichiro.nnip.org/osx/Cocoa/GlobalHotkey.html -// -// We load the functions dynamically because they're not available in -// older SDKs. We don't use weak linking because we want users of -// older SDKs to build an app that works on newer systems and older -// SDKs will not provide the symbols. -// - -#ifdef __cplusplus -extern "C" { -#endif - -typedef int CGSConnection; -typedef enum { - CGSGlobalHotKeyEnable = 0, - CGSGlobalHotKeyDisable = 1, -} CGSGlobalHotKeyOperatingMode; - -extern CGSConnection _CGSDefaultConnection(void) WEAK_IMPORT_ATTRIBUTE; -extern CGError CGSGetGlobalHotKeyOperatingMode(CGSConnection connection, CGSGlobalHotKeyOperatingMode *mode) WEAK_IMPORT_ATTRIBUTE; -extern CGError CGSSetGlobalHotKeyOperatingMode(CGSConnection connection, CGSGlobalHotKeyOperatingMode mode) WEAK_IMPORT_ATTRIBUTE; - -typedef CGSConnection (*_CGSDefaultConnection_t)(void); -typedef CGError (*CGSGetGlobalHotKeyOperatingMode_t)(CGSConnection connection, CGSGlobalHotKeyOperatingMode *mode); -typedef CGError (*CGSSetGlobalHotKeyOperatingMode_t)(CGSConnection connection, CGSGlobalHotKeyOperatingMode mode); - -static _CGSDefaultConnection_t s__CGSDefaultConnection; -static CGSGetGlobalHotKeyOperatingMode_t s_CGSGetGlobalHotKeyOperatingMode; -static CGSSetGlobalHotKeyOperatingMode_t s_CGSSetGlobalHotKeyOperatingMode; - -#ifdef __cplusplus -} -#endif - -#define LOOKUP(name_) \ - s_ ## name_ = NULL; \ - if (NSIsSymbolNameDefinedWithHint("_" #name_, "CoreGraphics")) { \ - s_ ## name_ = (name_ ## _t)NSAddressOfSymbol( \ - NSLookupAndBindSymbolWithHint( \ - "_" #name_, "CoreGraphics")); \ - } - -bool -COSXScreen::isGlobalHotKeyOperatingModeAvailable() -{ - if (!s_testedForGHOM) { - s_testedForGHOM = true; - LOOKUP(_CGSDefaultConnection); - LOOKUP(CGSGetGlobalHotKeyOperatingMode); - LOOKUP(CGSSetGlobalHotKeyOperatingMode); - s_hasGHOM = (s__CGSDefaultConnection != NULL && - s_CGSGetGlobalHotKeyOperatingMode != NULL && - s_CGSSetGlobalHotKeyOperatingMode != NULL); - } - return s_hasGHOM; -} - -void -COSXScreen::setGlobalHotKeysEnabled(bool enabled) -{ - if (isGlobalHotKeyOperatingModeAvailable()) { - CGSConnection conn = s__CGSDefaultConnection(); - - CGSGlobalHotKeyOperatingMode mode; - s_CGSGetGlobalHotKeyOperatingMode(conn, &mode); - - if (enabled && mode == CGSGlobalHotKeyDisable) { - s_CGSSetGlobalHotKeyOperatingMode(conn, CGSGlobalHotKeyEnable); - } - else if (!enabled && mode == CGSGlobalHotKeyEnable) { - s_CGSSetGlobalHotKeyOperatingMode(conn, CGSGlobalHotKeyDisable); - } - } -} - -bool -COSXScreen::getGlobalHotKeysEnabled() -{ - CGSGlobalHotKeyOperatingMode mode; - if (isGlobalHotKeyOperatingModeAvailable()) { - CGSConnection conn = s__CGSDefaultConnection(); - s_CGSGetGlobalHotKeyOperatingMode(conn, &mode); - } - else { - mode = CGSGlobalHotKeyEnable; - } - return (mode == CGSGlobalHotKeyEnable); -} - - -// -// COSXScreen::CHotKeyItem -// - -COSXScreen::CHotKeyItem::CHotKeyItem(UInt32 keycode, UInt32 mask) : - m_ref(NULL), - m_keycode(keycode), - m_mask(mask) -{ - // do nothing -} - -COSXScreen::CHotKeyItem::CHotKeyItem(EventHotKeyRef ref, - UInt32 keycode, UInt32 mask) : - m_ref(ref), - m_keycode(keycode), - m_mask(mask) -{ - // do nothing -} - -EventHotKeyRef -COSXScreen::CHotKeyItem::getRef() const -{ - return m_ref; -} - -bool -COSXScreen::CHotKeyItem::operator<(const CHotKeyItem& x) const -{ - return (m_keycode < x.m_keycode || - (m_keycode == x.m_keycode && m_mask < x.m_mask)); -} diff --git a/lib/platform/COSXScreen.h b/lib/platform/COSXScreen.h deleted file mode 100644 index f280d802..00000000 --- a/lib/platform/COSXScreen.h +++ /dev/null @@ -1,252 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef COSXSCREEN_H -#define COSXSCREEN_H - -#include "CPlatformScreen.h" -#include "stdmap.h" -#include "stdvector.h" -#include - -#include -#include -#include -#include -#include - -template -class CCondVar; -class CEventQueueTimer; -class CMutex; -class CThread; -class COSXKeyState; -class COSXScreenSaver; - -//! Implementation of IPlatformScreen for OS X -class COSXScreen : public CPlatformScreen { -public: - COSXScreen(bool isPrimary); - virtual ~COSXScreen(); - - // IScreen overrides - virtual void* getEventTarget() const; - virtual bool getClipboard(ClipboardID id, IClipboard*) const; - virtual void getShape(SInt32& x, SInt32& y, - SInt32& width, SInt32& height) const; - virtual void getCursorPos(SInt32& x, SInt32& y) const; - - // IPrimaryScreen overrides - virtual void reconfigure(UInt32 activeSides); - virtual void warpCursor(SInt32 x, SInt32 y); - virtual UInt32 registerHotKey(KeyID key, KeyModifierMask mask); - virtual void unregisterHotKey(UInt32 id); - virtual void fakeInputBegin(); - virtual void fakeInputEnd(); - virtual SInt32 getJumpZoneSize() const; - virtual bool isAnyMouseButtonDown() const; - virtual void getCursorCenter(SInt32& x, SInt32& y) const; - - // ISecondaryScreen overrides - virtual void fakeMouseButton(ButtonID id, bool press) const; - virtual void fakeMouseMove(SInt32 x, SInt32 y) const; - virtual void fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const; - virtual void fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const; - - // IPlatformScreen overrides - virtual void enable(); - virtual void disable(); - virtual void enter(); - virtual bool leave(); - virtual bool setClipboard(ClipboardID, const IClipboard*); - virtual void checkClipboards(); - virtual void openScreensaver(bool notify); - virtual void closeScreensaver(); - virtual void screensaver(bool activate); - virtual void resetOptions(); - virtual void setOptions(const COptionsList& options); - virtual void setSequenceNumber(UInt32); - virtual bool isPrimary() const; - -protected: - // IPlatformScreen overrides - virtual void handleSystemEvent(const CEvent&, void*); - virtual void updateButtons(); - virtual IKeyState* getKeyState() const; - -private: - void updateScreenShape(); - void postMouseEvent(CGPoint&) const; - - // convenience function to send events - void sendEvent(CEvent::Type type, void* = NULL) const; - void sendClipboardEvent(CEvent::Type type, ClipboardID id) const; - - // message handlers - bool onMouseMove(SInt32 x, SInt32 y); - // mouse button handler. pressed is true if this is a mousedown - // event, false if it is a mouseup event. macButton is the index - // of the button pressed using the mac button mapping. - bool onMouseButton(bool pressed, UInt16 macButton); - bool onMouseWheel(SInt32 xDelta, SInt32 yDelta) const; - - bool onDisplayChange(); - - bool onKey(EventRef event); - bool onHotKey(EventRef event) const; - - // map mac mouse button to synergy buttons - ButtonID mapMacButtonToSynergy(UInt16) const; - - // map mac scroll wheel value to a synergy scroll wheel value - SInt32 mapScrollWheelToSynergy(SInt32) const; - - // map synergy scroll wheel value to a mac scroll wheel value - SInt32 mapScrollWheelFromSynergy(SInt32) const; - - // get the current scroll wheel speed - double getScrollSpeed() const; - - // get the current scroll wheel speed - double getScrollSpeedFactor() const; - - // enable/disable drag handling for buttons 3 and up - void enableDragTimer(bool enable); - - // drag timer handler - void handleDrag(const CEvent&, void*); - - // clipboard check timer handler - void handleClipboardCheck(const CEvent&, void*); - - // Resolution switch callback - static pascal void displayManagerCallback(void* inUserData, - SInt16 inMessage, void* inNotifyData); - - // fast user switch callback - static pascal OSStatus - userSwitchCallback(EventHandlerCallRef nextHandler, - EventRef theEvent, void* inUserData); - - // sleep / wakeup support - void watchSystemPowerThread(void*); - static void testCanceled(CFRunLoopTimerRef timer, void*info); - static void powerChangeCallback(void* refcon, io_service_t service, - natural_t messageType, void* messageArgument); - void handlePowerChangeRequest(natural_t messageType, - void* messageArgument); - - static CEvent::Type getConfirmSleepEvent(); - void handleConfirmSleep(const CEvent& event, void*); - - // global hotkey operating mode - static bool isGlobalHotKeyOperatingModeAvailable(); - static void setGlobalHotKeysEnabled(bool enabled); - static bool getGlobalHotKeysEnabled(); - -private: - struct CHotKeyItem { - public: - CHotKeyItem(UInt32, UInt32); - CHotKeyItem(EventHotKeyRef, UInt32, UInt32); - - EventHotKeyRef getRef() const; - - bool operator<(const CHotKeyItem&) const; - - private: - EventHotKeyRef m_ref; - UInt32 m_keycode; - UInt32 m_mask; - }; - typedef std::map HotKeyMap; - typedef std::vector HotKeyIDList; - typedef std::map ModifierHotKeyMap; - typedef std::map HotKeyToIDMap; - - // true if screen is being used as a primary screen, false otherwise - bool m_isPrimary; - - // true if mouse has entered the screen - bool m_isOnScreen; - - // the display - CGDirectDisplayID m_displayID; - - // screen shape stuff - SInt32 m_x, m_y; - SInt32 m_w, m_h; - SInt32 m_xCenter, m_yCenter; - - // mouse state - mutable SInt32 m_xCursor, m_yCursor; - mutable bool m_cursorPosValid; - mutable boolean_t m_buttons[5]; - bool m_cursorHidden; - SInt32 m_dragNumButtonsDown; - Point m_dragLastPoint; - CEventQueueTimer* m_dragTimer; - - // keyboard stuff - COSXKeyState* m_keyState; - - // clipboards - UInt32 m_sequenceNumber; - - // screen saver stuff - COSXScreenSaver* m_screensaver; - bool m_screensaverNotify; - - // clipboard stuff - bool m_ownClipboard; - CEventQueueTimer* m_clipboardTimer; - - // window object that gets user input events when the server - // has focus. - WindowRef m_hiddenWindow; - // window object that gets user input events when the server - // does not have focus. - WindowRef m_userInputWindow; - - // display manager stuff (to get screen resolution switches). - DMExtendedNotificationUPP m_displayManagerNotificationUPP; - ProcessSerialNumber m_PSN; - - // fast user switching - EventHandlerRef m_switchEventHandlerRef; - - // sleep / wakeup - CMutex* m_pmMutex; - CThread* m_pmWatchThread; - CCondVar* m_pmThreadReady; - CFRunLoopRef m_pmRunloop; - io_connect_t m_pmRootPort; - - // hot key stuff - HotKeyMap m_hotKeys; - HotKeyIDList m_oldHotKeyIDs; - ModifierHotKeyMap m_modifierHotKeys; - UInt32 m_activeModifierHotKey; - KeyModifierMask m_activeModifierHotKeyMask; - HotKeyToIDMap m_hotKeyToIDMap; - - // global hotkey operating mode - static bool s_testedForGHOM; - static bool s_hasGHOM; - - // events - static CEvent::Type s_confirmSleepEvent; -}; - -#endif diff --git a/lib/platform/COSXScreenSaver.cpp b/lib/platform/COSXScreenSaver.cpp deleted file mode 100644 index 9cc6a678..00000000 --- a/lib/platform/COSXScreenSaver.cpp +++ /dev/null @@ -1,175 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#import "COSXScreenSaver.h" -#import "COSXScreenSaverUtil.h" -#import "CLog.h" -#import "IEventQueue.h" -#import "IPrimaryScreen.h" -#import - -// -// COSXScreenSaver -// - -COSXScreenSaver::COSXScreenSaver(void* eventTarget) : - m_eventTarget(eventTarget), - m_enabled(true) -{ - m_autoReleasePool = screenSaverUtilCreatePool(); - m_screenSaverController = screenSaverUtilCreateController(); - - // install launch/termination event handlers - EventTypeSpec launchEventTypes[2]; - launchEventTypes[0].eventClass = kEventClassApplication; - launchEventTypes[0].eventKind = kEventAppLaunched; - launchEventTypes[1].eventClass = kEventClassApplication; - launchEventTypes[1].eventKind = kEventAppTerminated; - - EventHandlerUPP launchTerminationEventHandler = - NewEventHandlerUPP(launchTerminationCallback); - InstallApplicationEventHandler(launchTerminationEventHandler, 2, - launchEventTypes, this, - &m_launchTerminationEventHandlerRef); - DisposeEventHandlerUPP(launchTerminationEventHandler); - - m_screenSaverPSN.highLongOfPSN = 0; - m_screenSaverPSN.lowLongOfPSN = 0; - - // test if screensaver is running and find process number - if (isActive()) { - ProcessInfoRec procInfo; - Str31 procName; // pascal string. first byte holds length. - memset(&procInfo, 0, sizeof(procInfo)); - procInfo.processName = procName; - procInfo.processInfoLength = sizeof(ProcessInfoRec); - - ProcessSerialNumber psn; - OSErr err = GetNextProcess(&psn); - while (err == 0) { - memset(procName, 0, sizeof(procName)); - err = GetProcessInformation(&psn, &procInfo); - if (err != 0) { - break; - } - if (strcmp("ScreenSaverEngine", (const char*)&procName[1]) == 0) { - m_screenSaverPSN = psn; - break; - } - err = GetNextProcess(&psn); - } - } -} - -COSXScreenSaver::~COSXScreenSaver() -{ - RemoveEventHandler(m_launchTerminationEventHandlerRef); -// screenSaverUtilReleaseController(m_screenSaverController); - screenSaverUtilReleasePool(m_autoReleasePool); -} - -void -COSXScreenSaver::enable() -{ - m_enabled = true; - screenSaverUtilEnable(m_screenSaverController); -} - -void -COSXScreenSaver::disable() -{ - m_enabled = false; - screenSaverUtilDisable(m_screenSaverController); -} - -void -COSXScreenSaver::activate() -{ - screenSaverUtilActivate(m_screenSaverController); -} - -void -COSXScreenSaver::deactivate() -{ - screenSaverUtilDeactivate(m_screenSaverController, m_enabled); -} - -bool -COSXScreenSaver::isActive() const -{ - return (screenSaverUtilIsActive(m_screenSaverController) != 0); -} - -void -COSXScreenSaver::processLaunched(ProcessSerialNumber psn) -{ - CFStringRef processName; - OSStatus err = CopyProcessName(&psn, &processName); - - if (err == 0 && CFEqual(CFSTR("ScreenSaverEngine"), processName)) { - m_screenSaverPSN = psn; - LOG((CLOG_DEBUG1 "ScreenSaverEngine launched. Enabled=%d", m_enabled)); - if (m_enabled) { - EVENTQUEUE->addEvent( - CEvent(IPrimaryScreen::getScreensaverActivatedEvent(), - m_eventTarget)); - } - } -} - -void -COSXScreenSaver::processTerminated(ProcessSerialNumber psn) -{ - if (m_screenSaverPSN.highLongOfPSN == psn.highLongOfPSN && - m_screenSaverPSN.lowLongOfPSN == psn.lowLongOfPSN) { - LOG((CLOG_DEBUG1 "ScreenSaverEngine terminated. Enabled=%d", m_enabled)); - if (m_enabled) { - EVENTQUEUE->addEvent( - CEvent(IPrimaryScreen::getScreensaverDeactivatedEvent(), - m_eventTarget)); - } - - m_screenSaverPSN.highLongOfPSN = 0; - m_screenSaverPSN.lowLongOfPSN = 0; - } -} - -pascal OSStatus -COSXScreenSaver::launchTerminationCallback( - EventHandlerCallRef nextHandler, - EventRef theEvent, void* userData) -{ - OSStatus result; - ProcessSerialNumber psn; - EventParamType actualType; - UInt32 actualSize; - - result = GetEventParameter(theEvent, kEventParamProcessID, - typeProcessSerialNumber, &actualType, - sizeof(psn), &actualSize, &psn); - - if ((result == noErr) && - (actualSize > 0) && - (actualType == typeProcessSerialNumber)) { - COSXScreenSaver* screenSaver = (COSXScreenSaver*)userData; - UInt32 eventKind = GetEventKind(theEvent); - if (eventKind == kEventAppLaunched) { - screenSaver->processLaunched(psn); - } - else if (eventKind == kEventAppTerminated) { - screenSaver->processTerminated(psn); - } - } - return (CallNextEventHandler(nextHandler, theEvent)); -} diff --git a/lib/platform/COSXScreenSaver.h b/lib/platform/COSXScreenSaver.h deleted file mode 100644 index 40c4e742..00000000 --- a/lib/platform/COSXScreenSaver.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef COSXSCREENSAVER_H -#define COSXSCREENSAVER_H - -#include "IScreenSaver.h" -#include - -//! OSX screen saver implementation -class COSXScreenSaver : public IScreenSaver { -public: - COSXScreenSaver(void* eventTarget); - virtual ~COSXScreenSaver(); - - // IScreenSaver overrides - virtual void enable(); - virtual void disable(); - virtual void activate(); - virtual void deactivate(); - virtual bool isActive() const; - -private: - void processLaunched(ProcessSerialNumber psn); - void processTerminated(ProcessSerialNumber psn); - - static pascal OSStatus - launchTerminationCallback( - EventHandlerCallRef nextHandler, - EventRef theEvent, void* userData); - -private: - // the target for the events we generate - void* m_eventTarget; - - bool m_enabled; - void* m_screenSaverController; - void* m_autoReleasePool; - EventHandlerRef m_launchTerminationEventHandlerRef; - ProcessSerialNumber m_screenSaverPSN; -}; - -#endif diff --git a/lib/platform/COSXScreenSaverUtil.h b/lib/platform/COSXScreenSaverUtil.h deleted file mode 100644 index d4124ab3..00000000 --- a/lib/platform/COSXScreenSaverUtil.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef COSXSCREENSAVERUTIL_H -#define COSXSCREENSAVERUTIL_H - -#include "common.h" - -#if defined(__cplusplus) -extern "C" { -#endif - -void* screenSaverUtilCreatePool(); -void screenSaverUtilReleasePool(void*); - -void* screenSaverUtilCreateController(); -void screenSaverUtilReleaseController(void*); -void screenSaverUtilEnable(void*); -void screenSaverUtilDisable(void*); -void screenSaverUtilActivate(void*); -void screenSaverUtilDeactivate(void*, int isEnabled); -int screenSaverUtilIsActive(void*); - -#if defined(__cplusplus) -} -#endif - -#endif diff --git a/lib/platform/COSXScreenSaverUtil.m b/lib/platform/COSXScreenSaverUtil.m deleted file mode 100644 index 1376d1f2..00000000 --- a/lib/platform/COSXScreenSaverUtil.m +++ /dev/null @@ -1,81 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#import "COSXScreenSaverUtil.h" -#import "OSXScreenSaverControl.h" -#import - -// -// screenSaverUtil functions -// -// Note: these helper functions exist only so we can avoid using ObjC++. -// autoconf/automake don't know about ObjC++ and I don't know how to -// teach them about it. -// - -void* -screenSaverUtilCreatePool() -{ - return [[NSAutoreleasePool alloc] init]; -} - -void -screenSaverUtilReleasePool(void* pool) -{ - [(NSAutoreleasePool*)pool release]; -} - -void* -screenSaverUtilCreateController() -{ - return [[ScreenSaverController controller] retain]; -} - -void -screenSaverUtilReleaseController(void* controller) -{ - [(ScreenSaverController*)controller release]; -} - -void -screenSaverUtilEnable(void* controller) -{ - [(ScreenSaverController*)controller setScreenSaverCanRun:YES]; -} - -void -screenSaverUtilDisable(void* controller) -{ - [(ScreenSaverController*)controller setScreenSaverCanRun:NO]; -} - -void -screenSaverUtilActivate(void* controller) -{ - [(ScreenSaverController*)controller setScreenSaverCanRun:YES]; - [(ScreenSaverController*)controller screenSaverStartNow]; -} - -void -screenSaverUtilDeactivate(void* controller, int isEnabled) -{ - [(ScreenSaverController*)controller screenSaverStopNow]; - [(ScreenSaverController*)controller setScreenSaverCanRun:isEnabled]; -} - -int -screenSaverUtilIsActive(void* controller) -{ - return [(ScreenSaverController*)controller screenSaverIsRunning]; -} diff --git a/lib/platform/CSynergyHook.cpp b/lib/platform/CSynergyHook.cpp deleted file mode 100644 index f4deb476..00000000 --- a/lib/platform/CSynergyHook.cpp +++ /dev/null @@ -1,1110 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CSynergyHook.h" -#include "ProtocolTypes.h" -#include -#include - -#if _MSC_VER >= 1400 -// VS2005 hack - we don't use assert here because we don't want to link with the CRT. -#undef assert -#if _DEBUG -#define assert(_X_) if (!(_X_)) __debugbreak() -#else -#define assert(_X_) __noop() -#endif -// VS2005 is a bit more smart than VC6 and optimize simple copy loop to -// intrinsic memcpy. -#pragma function(memcpy) -#endif - -// -// debugging compile flag. when not zero the server doesn't grab -// the keyboard when the mouse leaves the server screen. this -// makes it possible to use the debugger (via the keyboard) when -// all user input would normally be caught by the hook procedures. -// -#define NO_GRAB_KEYBOARD 0 - -// -// debugging compile flag. when not zero the server will not -// install low level hooks. -// -#define NO_LOWLEVEL_HOOKS 0 - -// -// extra mouse wheel stuff -// - -enum EWheelSupport { - kWheelNone, - kWheelOld, - kWheelWin2000, - kWheelModern -}; - -// declare extended mouse hook struct. useable on win2k -typedef struct tagMOUSEHOOKSTRUCTWin2000 { - MOUSEHOOKSTRUCT mhs; - DWORD mouseData; -} MOUSEHOOKSTRUCTWin2000; - -#if !defined(SM_MOUSEWHEELPRESENT) -#define SM_MOUSEWHEELPRESENT 75 -#endif - -// X button stuff -#if !defined(WM_XBUTTONDOWN) -#define WM_XBUTTONDOWN 0x020B -#define WM_XBUTTONUP 0x020C -#define WM_XBUTTONDBLCLK 0x020D -#define WM_NCXBUTTONDOWN 0x00AB -#define WM_NCXBUTTONUP 0x00AC -#define WM_NCXBUTTONDBLCLK 0x00AD -#define MOUSEEVENTF_XDOWN 0x0080 -#define MOUSEEVENTF_XUP 0x0100 -#define XBUTTON1 0x0001 -#define XBUTTON2 0x0002 -#endif - - -// -// globals -// - -#if defined(_MSC_VER) -#pragma comment(linker, "-section:shared,rws") -#pragma data_seg("shared") -#endif -// all data in this shared section *must* be initialized - -static HINSTANCE g_hinstance = NULL; -static DWORD g_processID = 0; -static EWheelSupport g_wheelSupport = kWheelNone; -static UINT g_wmMouseWheel = 0; -static DWORD g_threadID = 0; -static HHOOK g_keyboard = NULL; -static HHOOK g_mouse = NULL; -static HHOOK g_getMessage = NULL; -static HHOOK g_keyboardLL = NULL; -static HHOOK g_mouseLL = NULL; -static bool g_screenSaver = false; -static EHookMode g_mode = kHOOK_DISABLE; -static UInt32 g_zoneSides = 0; -static SInt32 g_zoneSize = 0; -static SInt32 g_xScreen = 0; -static SInt32 g_yScreen = 0; -static SInt32 g_wScreen = 0; -static SInt32 g_hScreen = 0; -static WPARAM g_deadVirtKey = 0; -static LPARAM g_deadLParam = 0; -static BYTE g_deadKeyState[256] = { 0 }; -static DWORD g_hookThread = 0; -static DWORD g_attachedThread = 0; -static bool g_fakeInput = false; - -#if defined(_MSC_VER) -#pragma data_seg() -#endif - -// keep linker quiet about floating point stuff. we don't use any -// floating point operations but our includes may define some -// (unused) floating point values. -#ifndef _DEBUG -extern "C" { -int _fltused=0; -} -#endif - - -// -// internal functions -// - -static -void -detachThread() -{ - if (g_attachedThread != 0 && g_hookThread != g_attachedThread) { - AttachThreadInput(g_hookThread, g_attachedThread, FALSE); - g_attachedThread = 0; - } -} - -static -bool -attachThreadToForeground() -{ - // only attach threads if using low level hooks. a low level hook - // runs in the thread that installed the hook but we have to make - // changes that require being attached to the target thread (which - // should be the foreground window). a regular hook runs in the - // thread that just removed the event from its queue so we're - // already in the right thread. - if (g_hookThread != 0) { - HWND window = GetForegroundWindow(); - DWORD threadID = GetWindowThreadProcessId(window, NULL); - // skip if no change - if (g_attachedThread != threadID) { - // detach from previous thread - detachThread(); - - // attach to new thread - if (threadID != 0 && threadID != g_hookThread) { - AttachThreadInput(g_hookThread, threadID, TRUE); - g_attachedThread = threadID; - } - return true; - } - } - return false; -} - -#if !NO_GRAB_KEYBOARD -static -WPARAM -makeKeyMsg(UINT virtKey, char c, bool noAltGr) -{ - return MAKEWPARAM(MAKEWORD(virtKey & 0xff, (BYTE)c), noAltGr ? 1 : 0); -} - -static -void -keyboardGetState(BYTE keys[256]) -{ - // we have to use GetAsyncKeyState() rather than GetKeyState() because - // we don't pass through most keys so the event synchronous state - // doesn't get updated. we do that because certain modifier keys have - // side effects, like alt and the windows key. - SHORT key; - for (int i = 0; i < 256; ++i) { - key = GetAsyncKeyState(i); - keys[i] = (BYTE)((key < 0) ? 0x80u : 0); - } - key = GetKeyState(VK_CAPITAL); - keys[VK_CAPITAL] = (BYTE)(((key < 0) ? 0x80 : 0) | (key & 1)); -} - -static -bool -doKeyboardHookHandler(WPARAM wParam, LPARAM lParam) -{ - // check for special events indicating if we should start or stop - // passing events through and not report them to the server. this - // is used to allow the server to synthesize events locally but - // not pick them up as user events. - if (wParam == SYNERGY_HOOK_FAKE_INPUT_VIRTUAL_KEY && - ((lParam >> 16) & 0xffu) == SYNERGY_HOOK_FAKE_INPUT_SCANCODE) { - // update flag - g_fakeInput = ((lParam & 0x80000000u) == 0); - PostThreadMessage(g_threadID, SYNERGY_MSG_DEBUG, - 0xff000000u | wParam, lParam); - - // discard event - return true; - } - - // if we're expecting fake input then just pass the event through - // and do not forward to the server - if (g_fakeInput) { - PostThreadMessage(g_threadID, SYNERGY_MSG_DEBUG, - 0xfe000000u | wParam, lParam); - return false; - } - - // VK_RSHIFT may be sent with an extended scan code but right shift - // is not an extended key so we reset that bit. - if (wParam == VK_RSHIFT) { - lParam &= ~0x01000000u; - } - - // tell server about event - PostThreadMessage(g_threadID, SYNERGY_MSG_DEBUG, wParam, lParam); - - // ignore dead key release - if (g_deadVirtKey == wParam && - (lParam & 0x80000000u) != 0) { - PostThreadMessage(g_threadID, SYNERGY_MSG_DEBUG, - wParam | 0x04000000, lParam); - return false; - } - - // we need the keyboard state for ToAscii() - BYTE keys[256]; - keyboardGetState(keys); - - // ToAscii() maps ctrl+letter to the corresponding control code - // and ctrl+backspace to delete. we don't want those translations - // so clear the control modifier state. however, if we want to - // simulate AltGr (which is ctrl+alt) then we must not clear it. - UINT control = keys[VK_CONTROL] | keys[VK_LCONTROL] | keys[VK_RCONTROL]; - UINT menu = keys[VK_MENU] | keys[VK_LMENU] | keys[VK_RMENU]; - if ((control & 0x80) == 0 || (menu & 0x80) == 0) { - keys[VK_LCONTROL] = 0; - keys[VK_RCONTROL] = 0; - keys[VK_CONTROL] = 0; - } - else { - keys[VK_LCONTROL] = 0x80; - keys[VK_RCONTROL] = 0x80; - keys[VK_CONTROL] = 0x80; - keys[VK_LMENU] = 0x80; - keys[VK_RMENU] = 0x80; - keys[VK_MENU] = 0x80; - } - - // ToAscii() needs to know if a menu is active for some reason. - // we don't know and there doesn't appear to be any way to find - // out. so we'll just assume a menu is active if the menu key - // is down. - // FIXME -- figure out some way to check if a menu is active - UINT flags = 0; - if ((menu & 0x80) != 0) - flags |= 1; - - // if we're on the server screen then just pass numpad keys with alt - // key down as-is. we won't pick up the resulting character but the - // local app will. if on a client screen then grab keys as usual; - // if the client is a windows system it'll synthesize the expected - // character. if not then it'll probably just do nothing. - if (g_mode != kHOOK_RELAY_EVENTS) { - // we don't use virtual keys because we don't know what the - // state of the numlock key is. we'll hard code the scan codes - // instead. hopefully this works across all keyboards. - UINT sc = (lParam & 0x01ff0000u) >> 16; - if (menu && - (sc >= 0x47u && sc <= 0x52u && sc != 0x4au && sc != 0x4eu)) { - return false; - } - } - - // map the key event to a character. we have to put the dead - // key back first and this has the side effect of removing it. - if (g_deadVirtKey != 0) { - WORD c = 0; - ToAscii(g_deadVirtKey, (g_deadLParam & 0x10ff0000u) >> 16, - g_deadKeyState, &c, flags); - } - WORD c = 0; - UINT scanCode = ((lParam & 0x10ff0000u) >> 16); - int n = ToAscii(wParam, scanCode, keys, &c, flags); - - // if mapping failed and ctrl and alt are pressed then try again - // with both not pressed. this handles the case where ctrl and - // alt are being used as individual modifiers rather than AltGr. - // we note that's the case in the message sent back to synergy - // because there's no simple way to deduce it after the fact. - // we have to put the dead key back first, if there was one. - bool noAltGr = false; - if (n == 0 && (control & 0x80) != 0 && (menu & 0x80) != 0) { - noAltGr = true; - PostThreadMessage(g_threadID, SYNERGY_MSG_DEBUG, - wParam | 0x05000000, lParam); - if (g_deadVirtKey != 0) { - ToAscii(g_deadVirtKey, (g_deadLParam & 0x10ff0000u) >> 16, - g_deadKeyState, &c, flags); - } - BYTE keys2[256]; - for (size_t i = 0; i < sizeof(keys) / sizeof(keys[0]); ++i) { - keys2[i] = keys[i]; - } - keys2[VK_LCONTROL] = 0; - keys2[VK_RCONTROL] = 0; - keys2[VK_CONTROL] = 0; - keys2[VK_LMENU] = 0; - keys2[VK_RMENU] = 0; - keys2[VK_MENU] = 0; - n = ToAscii(wParam, scanCode, keys2, &c, flags); - } - - PostThreadMessage(g_threadID, SYNERGY_MSG_DEBUG, - wParam | ((c & 0xff) << 8) | - ((n & 0xff) << 16) | 0x06000000, - lParam); - WPARAM charAndVirtKey = 0; - bool clearDeadKey = false; - switch (n) { - default: - // key is a dead key - g_deadVirtKey = wParam; - g_deadLParam = lParam; - for (size_t i = 0; i < sizeof(keys) / sizeof(keys[0]); ++i) { - g_deadKeyState[i] = keys[i]; - } - break; - - case 0: - // key doesn't map to a character. this can happen if - // non-character keys are pressed after a dead key. - charAndVirtKey = makeKeyMsg(wParam, (char)0, noAltGr); - break; - - case 1: - // key maps to a character composed with dead key - charAndVirtKey = makeKeyMsg(wParam, (char)LOBYTE(c), noAltGr); - clearDeadKey = true; - break; - - case 2: { - // previous dead key not composed. send a fake key press - // and release for the dead key to our window. - WPARAM deadCharAndVirtKey = - makeKeyMsg(g_deadVirtKey, (char)LOBYTE(c), noAltGr); - PostThreadMessage(g_threadID, SYNERGY_MSG_KEY, - deadCharAndVirtKey, g_deadLParam & 0x7fffffffu); - PostThreadMessage(g_threadID, SYNERGY_MSG_KEY, - deadCharAndVirtKey, g_deadLParam | 0x80000000u); - - // use uncomposed character - charAndVirtKey = makeKeyMsg(wParam, (char)HIBYTE(c), noAltGr); - clearDeadKey = true; - break; - } - } - - // put back the dead key, if any, for the application to use - if (g_deadVirtKey != 0) { - ToAscii(g_deadVirtKey, (g_deadLParam & 0x10ff0000u) >> 16, - g_deadKeyState, &c, flags); - } - - // clear out old dead key state - if (clearDeadKey) { - g_deadVirtKey = 0; - g_deadLParam = 0; - } - - // forward message to our window. do this whether or not we're - // forwarding events to clients because this'll keep our thread's - // key state table up to date. that's important for querying - // the scroll lock toggle state. - // XXX -- with hot keys for actions we may only need to do this when - // forwarding. - if (charAndVirtKey != 0) { - PostThreadMessage(g_threadID, SYNERGY_MSG_DEBUG, - charAndVirtKey | 0x07000000, lParam); - PostThreadMessage(g_threadID, SYNERGY_MSG_KEY, charAndVirtKey, lParam); - } - - if (g_mode == kHOOK_RELAY_EVENTS) { - // let certain keys pass through - switch (wParam) { - case VK_CAPITAL: - case VK_NUMLOCK: - case VK_SCROLL: - // pass event on. we want to let these through to - // the window proc because otherwise the keyboard - // lights may not stay synchronized. - break; - - case VK_HANGUL: - // pass these modifiers if using a low level hook, discard - // them if not. - if (g_hookThread == 0) { - return true; - } - break; - - default: - // discard - return true; - } - } - - return false; -} - -static -bool -keyboardHookHandler(WPARAM wParam, LPARAM lParam) -{ - attachThreadToForeground(); - return doKeyboardHookHandler(wParam, lParam); -} -#endif - -static -bool -doMouseHookHandler(WPARAM wParam, SInt32 x, SInt32 y, SInt32 data) -{ - switch (wParam) { - case WM_LBUTTONDOWN: - case WM_MBUTTONDOWN: - case WM_RBUTTONDOWN: - case WM_XBUTTONDOWN: - case WM_LBUTTONDBLCLK: - case WM_MBUTTONDBLCLK: - case WM_RBUTTONDBLCLK: - case WM_XBUTTONDBLCLK: - case WM_LBUTTONUP: - case WM_MBUTTONUP: - case WM_RBUTTONUP: - case WM_XBUTTONUP: - case WM_NCLBUTTONDOWN: - case WM_NCMBUTTONDOWN: - case WM_NCRBUTTONDOWN: - case WM_NCXBUTTONDOWN: - case WM_NCLBUTTONDBLCLK: - case WM_NCMBUTTONDBLCLK: - case WM_NCRBUTTONDBLCLK: - case WM_NCXBUTTONDBLCLK: - case WM_NCLBUTTONUP: - case WM_NCMBUTTONUP: - case WM_NCRBUTTONUP: - case WM_NCXBUTTONUP: - // always relay the event. eat it if relaying. - PostThreadMessage(g_threadID, SYNERGY_MSG_MOUSE_BUTTON, wParam, data); - return (g_mode == kHOOK_RELAY_EVENTS); - - case WM_MOUSEWHEEL: - if (g_mode == kHOOK_RELAY_EVENTS) { - // relay event - PostThreadMessage(g_threadID, SYNERGY_MSG_MOUSE_WHEEL, data, 0); - } - return (g_mode == kHOOK_RELAY_EVENTS); - - case WM_NCMOUSEMOVE: - case WM_MOUSEMOVE: - if (g_mode == kHOOK_RELAY_EVENTS) { - // relay and eat event - PostThreadMessage(g_threadID, SYNERGY_MSG_MOUSE_MOVE, x, y); - return true; - } - else if (g_mode == kHOOK_WATCH_JUMP_ZONE) { - // low level hooks can report bogus mouse positions that are - // outside of the screen. jeez. naturally we end up getting - // fake motion in the other direction to get the position back - // on the screen, which plays havoc with switch on double tap. - // CServer deals with that. we'll clamp positions onto the - // screen. also, if we discard events for positions outside - // of the screen then the mouse appears to get a bit jerky - // near the edge. we can either accept that or pass the bogus - // events. we'll try passing the events. - bool bogus = false; - if (x < g_xScreen) { - x = g_xScreen; - bogus = true; - } - else if (x >= g_xScreen + g_wScreen) { - x = g_xScreen + g_wScreen - 1; - bogus = true; - } - if (y < g_yScreen) { - y = g_yScreen; - bogus = true; - } - else if (y >= g_yScreen + g_hScreen) { - y = g_yScreen + g_hScreen - 1; - bogus = true; - } - - // check for mouse inside jump zone - bool inside = false; - if (!inside && (g_zoneSides & kLeftMask) != 0) { - inside = (x < g_xScreen + g_zoneSize); - } - if (!inside && (g_zoneSides & kRightMask) != 0) { - inside = (x >= g_xScreen + g_wScreen - g_zoneSize); - } - if (!inside && (g_zoneSides & kTopMask) != 0) { - inside = (y < g_yScreen + g_zoneSize); - } - if (!inside && (g_zoneSides & kBottomMask) != 0) { - inside = (y >= g_yScreen + g_hScreen - g_zoneSize); - } - - // relay the event - PostThreadMessage(g_threadID, SYNERGY_MSG_MOUSE_MOVE, x, y); - - // if inside and not bogus then eat the event - return inside && !bogus; - } - } - - // pass the event - return false; -} - -static -bool -mouseHookHandler(WPARAM wParam, SInt32 x, SInt32 y, SInt32 data) -{ -// attachThreadToForeground(); - return doMouseHookHandler(wParam, x, y, data); -} - -#if !NO_GRAB_KEYBOARD -static -LRESULT CALLBACK -keyboardHook(int code, WPARAM wParam, LPARAM lParam) -{ - if (code >= 0) { - // handle the message - if (keyboardHookHandler(wParam, lParam)) { - return 1; - } - } - - return CallNextHookEx(g_keyboard, code, wParam, lParam); -} -#endif - -static -LRESULT CALLBACK -mouseHook(int code, WPARAM wParam, LPARAM lParam) -{ - if (code >= 0) { - // decode message - const MOUSEHOOKSTRUCT* info = (const MOUSEHOOKSTRUCT*)lParam; - SInt32 x = (SInt32)info->pt.x; - SInt32 y = (SInt32)info->pt.y; - SInt32 w = 0; - if (wParam == WM_MOUSEWHEEL) { - // win2k and other systems supporting WM_MOUSEWHEEL in - // the mouse hook are gratuitously different (and poorly - // documented). if a low-level mouse hook is in place - // it should capture these events so we'll never see - // them. - switch (g_wheelSupport) { - case kWheelModern: - w = static_cast(LOWORD(info->dwExtraInfo)); - break; - - case kWheelWin2000: { - const MOUSEHOOKSTRUCTWin2000* info2k = - (const MOUSEHOOKSTRUCTWin2000*)lParam; - w = static_cast(HIWORD(info2k->mouseData)); - break; - } - - default: - break; - } - } - - // handle the message. note that we don't handle X buttons - // here. that's okay because they're only supported on - // win2k and winxp and up and on those platforms we'll get - // get the mouse events through the low level hook. - if (mouseHookHandler(wParam, x, y, w)) { - return 1; - } - } - - return CallNextHookEx(g_mouse, code, wParam, lParam); -} - -static -LRESULT CALLBACK -getMessageHook(int code, WPARAM wParam, LPARAM lParam) -{ - if (code >= 0) { - if (g_screenSaver) { - MSG* msg = reinterpret_cast(lParam); - if (msg->message == WM_SYSCOMMAND && - msg->wParam == SC_SCREENSAVE) { - // broadcast screen saver started message - PostThreadMessage(g_threadID, - SYNERGY_MSG_SCREEN_SAVER, TRUE, 0); - } - } - if (g_mode == kHOOK_RELAY_EVENTS) { - MSG* msg = reinterpret_cast(lParam); - if (g_wheelSupport == kWheelOld && msg->message == g_wmMouseWheel) { - // post message to our window - PostThreadMessage(g_threadID, - SYNERGY_MSG_MOUSE_WHEEL, - static_cast(msg->wParam & 0xffffu), 0); - - // zero out the delta in the message so it's (hopefully) - // ignored - msg->wParam = 0; - } - } - } - - return CallNextHookEx(g_getMessage, code, wParam, lParam); -} - -#if (_WIN32_WINNT >= 0x0400) && defined(_MSC_VER) && !NO_LOWLEVEL_HOOKS - -// -// low-level keyboard hook -- this allows us to capture and handle -// alt+tab, alt+esc, ctrl+esc, and windows key hot keys. on the down -// side, key repeats are not reported to us. -// - -#if !NO_GRAB_KEYBOARD -static -LRESULT CALLBACK -keyboardLLHook(int code, WPARAM wParam, LPARAM lParam) -{ - if (code >= 0) { - // decode the message - KBDLLHOOKSTRUCT* info = reinterpret_cast(lParam); - WPARAM wParam = info->vkCode; - LPARAM lParam = 1; // repeat code - lParam |= (info->scanCode << 16); // scan code - if (info->flags & LLKHF_EXTENDED) { - lParam |= (1lu << 24); // extended key - } - if (info->flags & LLKHF_ALTDOWN) { - lParam |= (1lu << 29); // context code - } - if (info->flags & LLKHF_UP) { - lParam |= (1lu << 31); // transition - } - // FIXME -- bit 30 should be set if key was already down but - // we don't know that info. as a result we'll never generate - // key repeat events. - - // handle the message - if (keyboardHookHandler(wParam, lParam)) { - return 1; - } - } - - return CallNextHookEx(g_keyboardLL, code, wParam, lParam); -} -#endif - -// -// low-level mouse hook -- this allows us to capture and handle mouse -// events very early. the earlier the better. -// - -static -LRESULT CALLBACK -mouseLLHook(int code, WPARAM wParam, LPARAM lParam) -{ - if (code >= 0) { - // decode the message - MSLLHOOKSTRUCT* info = reinterpret_cast(lParam); - SInt32 x = static_cast(info->pt.x); - SInt32 y = static_cast(info->pt.y); - SInt32 w = static_cast(HIWORD(info->mouseData)); - - // handle the message - if (mouseHookHandler(wParam, x, y, w)) { - return 1; - } - } - - return CallNextHookEx(g_mouseLL, code, wParam, lParam); -} - -#endif - -static -EWheelSupport -getWheelSupport() -{ - // get operating system - OSVERSIONINFO info; - info.dwOSVersionInfoSize = sizeof(info); - if (!GetVersionEx(&info)) { - return kWheelNone; - } - - // see if modern wheel is present - if (GetSystemMetrics(SM_MOUSEWHEELPRESENT)) { - // note if running on win2k - if (info.dwPlatformId == VER_PLATFORM_WIN32_NT && - info.dwMajorVersion == 5 && - info.dwMinorVersion == 0) { - return kWheelWin2000; - } - return kWheelModern; - } - - // not modern. see if we've got old-style support. -#if defined(MSH_WHEELSUPPORT) - UINT wheelSupportMsg = RegisterWindowMessage(MSH_WHEELSUPPORT); - HWND wheelSupportWindow = FindWindow(MSH_WHEELMODULE_CLASS, - MSH_WHEELMODULE_TITLE); - if (wheelSupportWindow != NULL && wheelSupportMsg != 0) { - if (SendMessage(wheelSupportWindow, wheelSupportMsg, 0, 0) != 0) { - g_wmMouseWheel = RegisterWindowMessage(MSH_MOUSEWHEEL); - if (g_wmMouseWheel != 0) { - return kWheelOld; - } - } - } -#endif - - // assume modern. we don't do anything special in this case - // except respond to WM_MOUSEWHEEL messages. GetSystemMetrics() - // can apparently return FALSE even if a mouse wheel is present - // though i'm not sure exactly when it does that (WinME returns - // FALSE for my logitech USB trackball). - return kWheelModern; -} - - -// -// external functions -// - -BOOL WINAPI -DllMain(HINSTANCE instance, DWORD reason, LPVOID) -{ - if (reason == DLL_PROCESS_ATTACH) { - DisableThreadLibraryCalls(instance); - if (g_processID == 0) { - g_hinstance = instance; - g_processID = GetCurrentProcessId(); - } - } - else if (reason == DLL_PROCESS_DETACH) { - if (g_processID == GetCurrentProcessId()) { - uninstall(); - uninstallScreenSaver(); - g_processID = 0; - g_hinstance = NULL; - } - } - return TRUE; -} - -extern "C" { - -// VS2005 hack to not link with the CRT -#if _MSC_VER >= 1400 -BOOL WINAPI _DllMainCRTStartup( - HINSTANCE instance, DWORD reason, LPVOID lpreserved) -{ - return DllMain(instance, reason, lpreserved); -} - -// VS2005 is a bit more bright than VC6 and optimize simple copy loop to -// intrinsic memcpy. -void * __cdecl memcpy(void * _Dst, const void * _Src, size_t _MaxCount) -{ - void * _DstBackup = _Dst; - switch (_MaxCount & 3) { - case 3: - ((char*)_Dst)[0] = ((char*)_Src)[0]; - ++(char*&)_Dst; - ++(char*&)_Src; - --_MaxCount; - case 2: - ((char*)_Dst)[0] = ((char*)_Src)[0]; - ++(char*&)_Dst; - ++(char*&)_Src; - --_MaxCount; - case 1: - ((char*)_Dst)[0] = ((char*)_Src)[0]; - ++(char*&)_Dst; - ++(char*&)_Src; - --_MaxCount; - break; - case 0: - break; - - default: - __assume(0); - break; - } - - // I think it's faster on intel to deference than modify the pointer. - const size_t max = _MaxCount / sizeof(UINT_PTR); - for (size_t i = 0; i < max; ++i) { - ((UINT_PTR*)_Dst)[i] = ((UINT_PTR*)_Src)[i]; - } - - (UINT_PTR*&)_Dst += max; - (UINT_PTR*&)_Src += max; - - switch (_MaxCount & 3) { - case 3: - ((char*)_Dst)[0] = ((char*)_Src)[0]; - ++(char*&)_Dst; - ++(char*&)_Src; - case 2: - ((char*)_Dst)[0] = ((char*)_Src)[0]; - ++(char*&)_Dst; - ++(char*&)_Src; - case 1: - ((char*)_Dst)[0] = ((char*)_Src)[0]; - ++(char*&)_Dst; - ++(char*&)_Src; - break; - case 0: - break; - - default: - __assume(0); - break; - } - - return _DstBackup; -} -#endif - -int -init(DWORD threadID) -{ - assert(g_hinstance != NULL); - - // try to open process that last called init() to see if it's - // still running or if it died without cleaning up. - if (g_processID != 0 && g_processID != GetCurrentProcessId()) { - HANDLE process = OpenProcess(STANDARD_RIGHTS_REQUIRED, - FALSE, g_processID); - if (process != NULL) { - // old process (probably) still exists so refuse to - // reinitialize this DLL (and thus steal it from the - // old process). - CloseHandle(process); - return 0; - } - - // clean up after old process. the system should've already - // removed the hooks so we just need to reset our state. - g_hinstance = GetModuleHandle(_T("synrgyhk")); - g_processID = GetCurrentProcessId(); - g_wheelSupport = kWheelNone; - g_threadID = 0; - g_keyboard = NULL; - g_mouse = NULL; - g_getMessage = NULL; - g_keyboardLL = NULL; - g_mouseLL = NULL; - g_screenSaver = false; - } - - // save thread id. we'll post messages to this thread's - // message queue. - g_threadID = threadID; - - // set defaults - g_mode = kHOOK_DISABLE; - g_zoneSides = 0; - g_zoneSize = 0; - g_xScreen = 0; - g_yScreen = 0; - g_wScreen = 0; - g_hScreen = 0; - - return 1; -} - -int -cleanup(void) -{ - assert(g_hinstance != NULL); - - if (g_processID == GetCurrentProcessId()) { - g_threadID = 0; - } - - return 1; -} - -EHookResult -install() -{ - assert(g_hinstance != NULL); - assert(g_keyboard == NULL); - assert(g_mouse == NULL); - assert(g_getMessage == NULL || g_screenSaver); - - // must be initialized - if (g_threadID == 0) { - return kHOOK_FAILED; - } - - // discard old dead keys - g_deadVirtKey = 0; - g_deadLParam = 0; - - // reset fake input flag - g_fakeInput = false; - - // check for mouse wheel support - g_wheelSupport = getWheelSupport(); - - // install GetMessage hook (unless already installed) - if (g_wheelSupport == kWheelOld && g_getMessage == NULL) { - g_getMessage = SetWindowsHookEx(WH_GETMESSAGE, - &getMessageHook, - g_hinstance, - 0); - } - - // install low-level hooks. we require that they both get installed. -#if (_WIN32_WINNT >= 0x0400) && defined(_MSC_VER) && !NO_LOWLEVEL_HOOKS - g_mouseLL = SetWindowsHookEx(WH_MOUSE_LL, - &mouseLLHook, - g_hinstance, - 0); -#if !NO_GRAB_KEYBOARD - g_keyboardLL = SetWindowsHookEx(WH_KEYBOARD_LL, - &keyboardLLHook, - g_hinstance, - 0); - if (g_mouseLL == NULL || g_keyboardLL == NULL) { - if (g_keyboardLL != NULL) { - UnhookWindowsHookEx(g_keyboardLL); - g_keyboardLL = NULL; - } - if (g_mouseLL != NULL) { - UnhookWindowsHookEx(g_mouseLL); - g_mouseLL = NULL; - } - } -#endif -#endif - - // install regular hooks - if (g_mouseLL == NULL) { - g_mouse = SetWindowsHookEx(WH_MOUSE, - &mouseHook, - g_hinstance, - 0); - } -#if !NO_GRAB_KEYBOARD - if (g_keyboardLL == NULL) { - g_keyboard = SetWindowsHookEx(WH_KEYBOARD, - &keyboardHook, - g_hinstance, - 0); - } -#endif - - // check that we got all the hooks we wanted - if ((g_getMessage == NULL && g_wheelSupport == kWheelOld) || -#if !NO_GRAB_KEYBOARD - (g_keyboardLL == NULL && g_keyboard == NULL) || -#endif - (g_mouseLL == NULL && g_mouse == NULL)) { - uninstall(); - return kHOOK_FAILED; - } - - if (g_keyboardLL != NULL || g_mouseLL != NULL) { - g_hookThread = GetCurrentThreadId(); - return kHOOK_OKAY_LL; - } - - return kHOOK_OKAY; -} - -int -uninstall(void) -{ - assert(g_hinstance != NULL); - - // discard old dead keys - g_deadVirtKey = 0; - g_deadLParam = 0; - - // detach from thread - detachThread(); - - // uninstall hooks - if (g_keyboardLL != NULL) { - UnhookWindowsHookEx(g_keyboardLL); - g_keyboardLL = NULL; - } - if (g_mouseLL != NULL) { - UnhookWindowsHookEx(g_mouseLL); - g_mouseLL = NULL; - } - if (g_keyboard != NULL) { - UnhookWindowsHookEx(g_keyboard); - g_keyboard = NULL; - } - if (g_mouse != NULL) { - UnhookWindowsHookEx(g_mouse); - g_mouse = NULL; - } - if (g_getMessage != NULL && !g_screenSaver) { - UnhookWindowsHookEx(g_getMessage); - g_getMessage = NULL; - } - g_wheelSupport = kWheelNone; - - return 1; -} - -int -installScreenSaver(void) -{ - assert(g_hinstance != NULL); - - // must be initialized - if (g_threadID == 0) { - return 0; - } - - // generate screen saver messages - g_screenSaver = true; - - // install hook unless it's already installed - if (g_getMessage == NULL) { - g_getMessage = SetWindowsHookEx(WH_GETMESSAGE, - &getMessageHook, - g_hinstance, - 0); - } - - return (g_getMessage != NULL) ? 1 : 0; -} - -int -uninstallScreenSaver(void) -{ - assert(g_hinstance != NULL); - - // uninstall hook unless the mouse wheel hook is installed - if (g_getMessage != NULL && g_wheelSupport != kWheelOld) { - UnhookWindowsHookEx(g_getMessage); - g_getMessage = NULL; - } - - // screen saver hook is no longer installed - g_screenSaver = false; - - return 1; -} - -void -setSides(UInt32 sides) -{ - g_zoneSides = sides; -} - -void -setZone(SInt32 x, SInt32 y, SInt32 w, SInt32 h, SInt32 jumpZoneSize) -{ - g_zoneSize = jumpZoneSize; - g_xScreen = x; - g_yScreen = y; - g_wScreen = w; - g_hScreen = h; -} - -void -setMode(EHookMode mode) -{ - if (mode == g_mode) { - // no change - return; - } - g_mode = mode; -} - -} diff --git a/lib/platform/CSynergyHook.h b/lib/platform/CSynergyHook.h deleted file mode 100644 index e8661815..00000000 --- a/lib/platform/CSynergyHook.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CSYNERGYHOOK_H -#define CSYNERGYHOOK_H - -#include "BasicTypes.h" -#define WIN32_LEAN_AND_MEAN -#include - -#if defined(SYNRGYHK_EXPORTS) -#define CSYNERGYHOOK_API __declspec(dllexport) -#else -#define CSYNERGYHOOK_API __declspec(dllimport) -#endif - -#define SYNERGY_MSG_MARK WM_APP + 0x0011 // mark id; -#define SYNERGY_MSG_KEY WM_APP + 0x0012 // vk code; key data -#define SYNERGY_MSG_MOUSE_BUTTON WM_APP + 0x0013 // button msg; -#define SYNERGY_MSG_MOUSE_WHEEL WM_APP + 0x0014 // delta; -#define SYNERGY_MSG_MOUSE_MOVE WM_APP + 0x0015 // x; y -#define SYNERGY_MSG_POST_WARP WM_APP + 0x0016 // ; -#define SYNERGY_MSG_PRE_WARP WM_APP + 0x0017 // x; y -#define SYNERGY_MSG_SCREEN_SAVER WM_APP + 0x0018 // activated; -#define SYNERGY_MSG_DEBUG WM_APP + 0x0019 // data, data -#define SYNERGY_MSG_INPUT_FIRST SYNERGY_MSG_KEY -#define SYNERGY_MSG_INPUT_LAST SYNERGY_MSG_PRE_WARP -#define SYNERGY_HOOK_LAST_MSG SYNERGY_MSG_DEBUG - -#define SYNERGY_HOOK_FAKE_INPUT_VIRTUAL_KEY VK_CANCEL -#define SYNERGY_HOOK_FAKE_INPUT_SCANCODE 0 - -extern "C" { - -enum EHookResult { - kHOOK_FAILED, - kHOOK_OKAY, - kHOOK_OKAY_LL -}; - -enum EHookMode { - kHOOK_DISABLE, - kHOOK_WATCH_JUMP_ZONE, - kHOOK_RELAY_EVENTS -}; - -typedef int (*InitFunc)(DWORD targetQueueThreadID); -typedef int (*CleanupFunc)(void); -typedef EHookResult (*InstallFunc)(void); -typedef int (*UninstallFunc)(void); -typedef int (*InstallScreenSaverFunc)(void); -typedef int (*UninstallScreenSaverFunc)(void); -typedef void (*SetSidesFunc)(UInt32); -typedef void (*SetZoneFunc)(SInt32, SInt32, SInt32, SInt32, SInt32); -typedef void (*SetModeFunc)(int); - -CSYNERGYHOOK_API int init(DWORD); -CSYNERGYHOOK_API int cleanup(void); -CSYNERGYHOOK_API EHookResult install(void); -CSYNERGYHOOK_API int uninstall(void); -CSYNERGYHOOK_API int installScreenSaver(void); -CSYNERGYHOOK_API int uninstallScreenSaver(void); -CSYNERGYHOOK_API void setSides(UInt32 sides); -CSYNERGYHOOK_API void setZone(SInt32 x, SInt32 y, SInt32 w, SInt32 h, - SInt32 jumpZoneSize); -CSYNERGYHOOK_API void setMode(EHookMode mode); - -} - -#endif diff --git a/lib/platform/CXWindowsClipboard.cpp b/lib/platform/CXWindowsClipboard.cpp deleted file mode 100644 index 33252af9..00000000 --- a/lib/platform/CXWindowsClipboard.cpp +++ /dev/null @@ -1,1507 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CXWindowsClipboard.h" -#include "CXWindowsClipboardTextConverter.h" -#include "CXWindowsClipboardUCS2Converter.h" -#include "CXWindowsClipboardUTF8Converter.h" -#include "CXWindowsClipboardHTMLConverter.h" -#include "CXWindowsClipboardBMPConverter.h" -#include "CXWindowsUtil.h" -#include "CThread.h" -#include "CLog.h" -#include "CStopwatch.h" -#include "CArch.h" -#include "stdvector.h" -#include -#include - -// -// CXWindowsClipboard -// - -CXWindowsClipboard::CXWindowsClipboard(Display* display, - Window window, ClipboardID id) : - m_display(display), - m_window(window), - m_id(id), - m_open(false), - m_time(0), - m_owner(false), - m_timeOwned(0), - m_timeLost(0) -{ - // get some atoms - m_atomTargets = XInternAtom(m_display, "TARGETS", False); - m_atomMultiple = XInternAtom(m_display, "MULTIPLE", False); - m_atomTimestamp = XInternAtom(m_display, "TIMESTAMP", False); - m_atomInteger = XInternAtom(m_display, "INTEGER", False); - m_atomAtom = XInternAtom(m_display, "ATOM", False); - m_atomAtomPair = XInternAtom(m_display, "ATOM_PAIR", False); - m_atomData = XInternAtom(m_display, "CLIP_TEMPORARY", False); - m_atomINCR = XInternAtom(m_display, "INCR", False); - m_atomMotifClipLock = XInternAtom(m_display, "_MOTIF_CLIP_LOCK", False); - m_atomMotifClipHeader = XInternAtom(m_display, "_MOTIF_CLIP_HEADER", False); - m_atomMotifClipAccess = XInternAtom(m_display, - "_MOTIF_CLIP_LOCK_ACCESS_VALID", False); - m_atomGDKSelection = XInternAtom(m_display, "GDK_SELECTION", False); - - // set selection atom based on clipboard id - switch (id) { - case kClipboardClipboard: - m_selection = XInternAtom(m_display, "CLIPBOARD", False); - break; - - case kClipboardSelection: - default: - m_selection = XA_PRIMARY; - break; - } - - // add converters, most desired first - m_converters.push_back(new CXWindowsClipboardHTMLConverter(m_display, - "text/html")); - m_converters.push_back(new CXWindowsClipboardBMPConverter(m_display)); - m_converters.push_back(new CXWindowsClipboardUTF8Converter(m_display, - "text/plain;charset=UTF-8")); - m_converters.push_back(new CXWindowsClipboardUTF8Converter(m_display, - "UTF8_STRING")); - m_converters.push_back(new CXWindowsClipboardUCS2Converter(m_display, - "text/plain;charset=ISO-10646-UCS-2")); - m_converters.push_back(new CXWindowsClipboardUCS2Converter(m_display, - "text/unicode")); - m_converters.push_back(new CXWindowsClipboardTextConverter(m_display, - "text/plain")); - m_converters.push_back(new CXWindowsClipboardTextConverter(m_display, - "STRING")); - - // we have no data - clearCache(); -} - -CXWindowsClipboard::~CXWindowsClipboard() -{ - clearReplies(); - clearConverters(); -} - -void -CXWindowsClipboard::lost(Time time) -{ - LOG((CLOG_DEBUG "lost clipboard %d ownership at %d", m_id, time)); - if (m_owner) { - m_owner = false; - m_timeLost = time; - clearCache(); - } -} - -void -CXWindowsClipboard::addRequest(Window owner, Window requestor, - Atom target, ::Time time, Atom property) -{ - // must be for our window and we must have owned the selection - // at the given time. - bool success = false; - if (owner == m_window) { - LOG((CLOG_DEBUG1 "request for clipboard %d, target %s by 0x%08x (property=%s)", m_selection, CXWindowsUtil::atomToString(m_display, target).c_str(), requestor, CXWindowsUtil::atomToString(m_display, property).c_str())); - if (wasOwnedAtTime(time)) { - if (target == m_atomMultiple) { - // add a multiple request. property may not be None - // according to ICCCM. - if (property != None) { - success = insertMultipleReply(requestor, time, property); - } - } - else { - addSimpleRequest(requestor, target, time, property); - - // addSimpleRequest() will have already handled failure - success = true; - } - } - else { - LOG((CLOG_DEBUG1 "failed, not owned at time %d", time)); - } - } - - if (!success) { - // send failure - LOG((CLOG_DEBUG1 "failed")); - insertReply(new CReply(requestor, target, time)); - } - - // send notifications that are pending - pushReplies(); -} - -bool -CXWindowsClipboard::addSimpleRequest(Window requestor, - Atom target, ::Time time, Atom property) -{ - // obsolete requestors may supply a None property. in - // that case we use the target as the property to store - // the conversion. - if (property == None) { - property = target; - } - - // handle targets - CString data; - Atom type = None; - int format = 0; - if (target == m_atomTargets) { - type = getTargetsData(data, &format); - } - else if (target == m_atomTimestamp) { - type = getTimestampData(data, &format); - } - else { - IXWindowsClipboardConverter* converter = getConverter(target); - if (converter != NULL) { - IClipboard::EFormat clipboardFormat = converter->getFormat(); - if (m_added[clipboardFormat]) { - try { - data = converter->fromIClipboard(m_data[clipboardFormat]); - format = converter->getDataSize(); - type = converter->getAtom(); - } - catch (...) { - // ignore -- cannot convert - } - } - } - } - - if (type != None) { - // success - LOG((CLOG_DEBUG1 "success")); - insertReply(new CReply(requestor, target, time, - property, data, type, format)); - return true; - } - else { - // failure - LOG((CLOG_DEBUG1 "failed")); - insertReply(new CReply(requestor, target, time)); - return false; - } -} - -bool -CXWindowsClipboard::processRequest(Window requestor, - ::Time /*time*/, Atom property) -{ - CReplyMap::iterator index = m_replies.find(requestor); - if (index == m_replies.end()) { - // unknown requestor window - return false; - } - LOG((CLOG_DEBUG1 "received property %s delete from 0x08%x", CXWindowsUtil::atomToString(m_display, property).c_str(), requestor)); - - // find the property in the known requests. it should be the - // first property but we'll check 'em all if we have to. - CReplyList& replies = index->second; - for (CReplyList::iterator index2 = replies.begin(); - index2 != replies.end(); ++index2) { - CReply* reply = *index2; - if (reply->m_replied && reply->m_property == property) { - // if reply is complete then remove it and start the - // next one. - pushReplies(index, replies, index2); - return true; - } - } - - return false; -} - -bool -CXWindowsClipboard::destroyRequest(Window requestor) -{ - CReplyMap::iterator index = m_replies.find(requestor); - if (index == m_replies.end()) { - // unknown requestor window - return false; - } - - // destroy all replies for this window - clearReplies(index->second); - m_replies.erase(index); - - // note -- we don't stop watching the window for events because - // we're called in response to the window being destroyed. - - return true; -} - -Window -CXWindowsClipboard::getWindow() const -{ - return m_window; -} - -Atom -CXWindowsClipboard::getSelection() const -{ - return m_selection; -} - -bool -CXWindowsClipboard::empty() -{ - assert(m_open); - - LOG((CLOG_DEBUG "empty clipboard %d", m_id)); - - // assert ownership of clipboard - XSetSelectionOwner(m_display, m_selection, m_window, m_time); - if (XGetSelectionOwner(m_display, m_selection) != m_window) { - LOG((CLOG_DEBUG "failed to grab clipboard %d", m_id)); - return false; - } - - // clear all data. since we own the data now, the cache is up - // to date. - clearCache(); - m_cached = true; - - // FIXME -- actually delete motif clipboard items? - // FIXME -- do anything to motif clipboard properties? - - // save time - m_timeOwned = m_time; - m_timeLost = 0; - - // we're the owner now - m_owner = true; - LOG((CLOG_DEBUG "grabbed clipboard %d", m_id)); - - return true; -} - -void -CXWindowsClipboard::add(EFormat format, const CString& data) -{ - assert(m_open); - assert(m_owner); - - LOG((CLOG_DEBUG "add %d bytes to clipboard %d format: %d", data.size(), m_id, format)); - - m_data[format] = data; - m_added[format] = true; - - // FIXME -- set motif clipboard item? -} - -bool -CXWindowsClipboard::open(Time time) const -{ - assert(!m_open); - - LOG((CLOG_DEBUG "open clipboard %d", m_id)); - - // assume not motif - m_motif = false; - - // lock clipboard - if (m_id == kClipboardClipboard) { - if (!motifLockClipboard()) { - return false; - } - - // check if motif owns the selection. unlock motif clipboard - // if it does not. - m_motif = motifOwnsClipboard(); - LOG((CLOG_DEBUG1 "motif does %sown clipboard", m_motif ? "" : "not ")); - if (!m_motif) { - motifUnlockClipboard(); - } - } - - // now open - m_open = true; - m_time = time; - - // be sure to flush the cache later if it's dirty - m_checkCache = true; - - return true; -} - -void -CXWindowsClipboard::close() const -{ - assert(m_open); - - LOG((CLOG_DEBUG "close clipboard %d", m_id)); - - // unlock clipboard - if (m_motif) { - motifUnlockClipboard(); - } - - m_motif = false; - m_open = false; -} - -IClipboard::Time -CXWindowsClipboard::getTime() const -{ - checkCache(); - return m_timeOwned; -} - -bool -CXWindowsClipboard::has(EFormat format) const -{ - assert(m_open); - - fillCache(); - return m_added[format]; -} - -CString -CXWindowsClipboard::get(EFormat format) const -{ - assert(m_open); - - fillCache(); - return m_data[format]; -} - -void -CXWindowsClipboard::clearConverters() -{ - for (ConverterList::iterator index = m_converters.begin(); - index != m_converters.end(); ++index) { - delete *index; - } - m_converters.clear(); -} - -IXWindowsClipboardConverter* -CXWindowsClipboard::getConverter(Atom target, bool onlyIfNotAdded) const -{ - IXWindowsClipboardConverter* converter = NULL; - for (ConverterList::const_iterator index = m_converters.begin(); - index != m_converters.end(); ++index) { - converter = *index; - if (converter->getAtom() == target) { - break; - } - } - if (converter == NULL) { - LOG((CLOG_DEBUG1 " no converter for target %s", CXWindowsUtil::atomToString(m_display, target).c_str())); - return NULL; - } - - // optionally skip already handled targets - if (onlyIfNotAdded) { - if (m_added[converter->getFormat()]) { - LOG((CLOG_DEBUG1 " skipping handled format %d", converter->getFormat())); - return NULL; - } - } - - return converter; -} - -void -CXWindowsClipboard::checkCache() const -{ - if (!m_checkCache) { - return; - } - m_checkCache = false; - - // get the time the clipboard ownership was taken by the current - // owner. - if (m_motif) { - m_timeOwned = motifGetTime(); - } - else { - m_timeOwned = icccmGetTime(); - } - - // if we can't get the time then use the time passed to us - if (m_timeOwned == 0) { - m_timeOwned = m_time; - } - - // if the cache is dirty then flush it - if (m_timeOwned != m_cacheTime) { - clearCache(); - } -} - -void -CXWindowsClipboard::clearCache() const -{ - const_cast(this)->doClearCache(); -} - -void -CXWindowsClipboard::doClearCache() -{ - m_checkCache = false; - m_cached = false; - for (SInt32 index = 0; index < kNumFormats; ++index) { - m_data[index] = ""; - m_added[index] = false; - } -} - -void -CXWindowsClipboard::fillCache() const -{ - // get the selection data if not already cached - checkCache(); - if (!m_cached) { - const_cast(this)->doFillCache(); - } -} - -void -CXWindowsClipboard::doFillCache() -{ - if (m_motif) { - motifFillCache(); - } - else { - icccmFillCache(); - } - m_checkCache = false; - m_cached = true; - m_cacheTime = m_timeOwned; -} - -void -CXWindowsClipboard::icccmFillCache() -{ - LOG((CLOG_DEBUG "ICCCM fill clipboard %d", m_id)); - - // see if we can get the list of available formats from the selection. - // if not then use a default list of formats. note that some clipboard - // owners are broken and report TARGETS as the type of the TARGETS data - // instead of the correct type ATOM; allow either. - const Atom atomTargets = m_atomTargets; - Atom target; - CString data; - if (!icccmGetSelection(atomTargets, &target, &data) || - (target != m_atomAtom && target != m_atomTargets)) { - LOG((CLOG_DEBUG1 "selection doesn't support TARGETS")); - data = ""; - CXWindowsUtil::appendAtomData(data, XA_STRING); - } - - CXWindowsUtil::convertAtomProperty(data); - const Atom* targets = reinterpret_cast(data.data()); - const UInt32 numTargets = data.size() / sizeof(Atom); - LOG((CLOG_DEBUG " available targets: %s", CXWindowsUtil::atomsToString(m_display, targets, numTargets).c_str())); - - // try each converter in order (because they're in order of - // preference). - for (ConverterList::const_iterator index = m_converters.begin(); - index != m_converters.end(); ++index) { - IXWindowsClipboardConverter* converter = *index; - - // skip already handled targets - if (m_added[converter->getFormat()]) { - continue; - } - - // see if atom is in target list - Atom target = None; - // XXX -- just ask for the converter's target to see if it's - // available rather than checking TARGETS. i've seen clipboard - // owners that don't report all the targets they support. - target = converter->getAtom(); - /* - for (UInt32 i = 0; i < numTargets; ++i) { - if (converter->getAtom() == targets[i]) { - target = targets[i]; - break; - } - } - */ - if (target == None) { - continue; - } - - // get the data - Atom actualTarget; - CString targetData; - if (!icccmGetSelection(target, &actualTarget, &targetData)) { - LOG((CLOG_DEBUG1 " no data for target %s", CXWindowsUtil::atomToString(m_display, target).c_str())); - continue; - } - - // add to clipboard and note we've done it - IClipboard::EFormat format = converter->getFormat(); - m_data[format] = converter->toIClipboard(targetData); - m_added[format] = true; - LOG((CLOG_DEBUG " added format %d for target %s (%u %s)", format, CXWindowsUtil::atomToString(m_display, target).c_str(), targetData.size(), targetData.size() == 1 ? "byte" : "bytes")); - } -} - -bool -CXWindowsClipboard::icccmGetSelection(Atom target, - Atom* actualTarget, CString* data) const -{ - assert(actualTarget != NULL); - assert(data != NULL); - - // request data conversion - CICCCMGetClipboard getter(m_window, m_time, m_atomData); - if (!getter.readClipboard(m_display, m_selection, - target, actualTarget, data)) { - LOG((CLOG_DEBUG1 "can't get data for selection target %s", CXWindowsUtil::atomToString(m_display, target).c_str())); - LOGC(getter.m_error, (CLOG_WARN "ICCCM violation by clipboard owner")); - return false; - } - else if (*actualTarget == None) { - LOG((CLOG_DEBUG1 "selection conversion failed for target %s", CXWindowsUtil::atomToString(m_display, target).c_str())); - return false; - } - return true; -} - -IClipboard::Time -CXWindowsClipboard::icccmGetTime() const -{ - Atom actualTarget; - CString data; - if (icccmGetSelection(m_atomTimestamp, &actualTarget, &data) && - actualTarget == m_atomInteger) { - Time time = *reinterpret_cast(data.data()); - LOG((CLOG_DEBUG1 "got ICCCM time %d", time)); - return time; - } - else { - // no timestamp - LOG((CLOG_DEBUG1 "can't get ICCCM time")); - return 0; - } -} - -bool -CXWindowsClipboard::motifLockClipboard() const -{ - // fail if anybody owns the lock (even us, so this is non-recursive) - Window lockOwner = XGetSelectionOwner(m_display, m_atomMotifClipLock); - if (lockOwner != None) { - LOG((CLOG_DEBUG1 "motif lock owner 0x%08x", lockOwner)); - return false; - } - - // try to grab the lock - // FIXME -- is this right? there's a race condition here -- - // A grabs successfully, B grabs successfully, A thinks it - // still has the grab until it gets a SelectionClear. - Time time = CXWindowsUtil::getCurrentTime(m_display, m_window); - XSetSelectionOwner(m_display, m_atomMotifClipLock, m_window, time); - lockOwner = XGetSelectionOwner(m_display, m_atomMotifClipLock); - if (lockOwner != m_window) { - LOG((CLOG_DEBUG1 "motif lock owner 0x%08x", lockOwner)); - return false; - } - - LOG((CLOG_DEBUG1 "locked motif clipboard")); - return true; -} - -void -CXWindowsClipboard::motifUnlockClipboard() const -{ - LOG((CLOG_DEBUG1 "unlocked motif clipboard")); - - // fail if we don't own the lock - Window lockOwner = XGetSelectionOwner(m_display, m_atomMotifClipLock); - if (lockOwner != m_window) { - return; - } - - // release lock - Time time = CXWindowsUtil::getCurrentTime(m_display, m_window); - XSetSelectionOwner(m_display, m_atomMotifClipLock, None, time); -} - -bool -CXWindowsClipboard::motifOwnsClipboard() const -{ - // get the current selection owner - // FIXME -- this can't be right. even if the window is destroyed - // Motif will still have a valid clipboard. how can we tell if - // some other client owns CLIPBOARD? - Window owner = XGetSelectionOwner(m_display, m_selection); - if (owner == None) { - return false; - } - - // get the Motif clipboard header property from the root window - Atom target; - SInt32 format; - CString data; - Window root = RootWindow(m_display, DefaultScreen(m_display)); - if (!CXWindowsUtil::getWindowProperty(m_display, root, - m_atomMotifClipHeader, - &data, &target, &format, False)) { - return false; - } - - // check the owner window against the current clipboard owner - const CMotifClipHeader* header = - reinterpret_cast(data.data()); - if (data.size() >= sizeof(CMotifClipHeader) && - header->m_id == kMotifClipHeader) { - if (static_cast(header->m_selectionOwner) == owner) { - return true; - } - } - - return false; -} - -void -CXWindowsClipboard::motifFillCache() -{ - LOG((CLOG_DEBUG "Motif fill clipboard %d", m_id)); - - // get the Motif clipboard header property from the root window - Atom target; - SInt32 format; - CString data; - Window root = RootWindow(m_display, DefaultScreen(m_display)); - if (!CXWindowsUtil::getWindowProperty(m_display, root, - m_atomMotifClipHeader, - &data, &target, &format, False)) { - return; - } - - // check that the header is okay - const CMotifClipHeader* header = - reinterpret_cast(data.data()); - if (data.size() < sizeof(CMotifClipHeader) || - header->m_id != kMotifClipHeader || - header->m_numItems < 1) { - return; - } - - // get the Motif item property from the root window - char name[18 + 20]; - sprintf(name, "_MOTIF_CLIP_ITEM_%d", header->m_item); - Atom atomItem = XInternAtom(m_display, name, False); - data = ""; - if (!CXWindowsUtil::getWindowProperty(m_display, root, - atomItem, &data, - &target, &format, False)) { - return; - } - - // check that the item is okay - const CMotifClipItem* item = - reinterpret_cast(data.data()); - if (data.size() < sizeof(CMotifClipItem) || - item->m_id != kMotifClipItem || - item->m_numFormats - item->m_numDeletedFormats < 1) { - return; - } - - // format list is after static item structure elements - const SInt32 numFormats = item->m_numFormats - item->m_numDeletedFormats; - const SInt32* formats = reinterpret_cast(item->m_size + - reinterpret_cast(data.data())); - - // get the available formats - typedef std::map CMotifFormatMap; - CMotifFormatMap motifFormats; - for (SInt32 i = 0; i < numFormats; ++i) { - // get Motif format property from the root window - sprintf(name, "_MOTIF_CLIP_ITEM_%d", formats[i]); - Atom atomFormat = XInternAtom(m_display, name, False); - CString data; - if (!CXWindowsUtil::getWindowProperty(m_display, root, - atomFormat, &data, - &target, &format, False)) { - continue; - } - - // check that the format is okay - const CMotifClipFormat* motifFormat = - reinterpret_cast(data.data()); - if (data.size() < sizeof(CMotifClipFormat) || - motifFormat->m_id != kMotifClipFormat || - motifFormat->m_length < 0 || - motifFormat->m_type == None || - motifFormat->m_deleted != 0) { - continue; - } - - // save it - motifFormats.insert(std::make_pair(motifFormat->m_type, data)); - } - //const UInt32 numMotifFormats = motifFormats.size(); - - // try each converter in order (because they're in order of - // preference). - for (ConverterList::const_iterator index = m_converters.begin(); - index != m_converters.end(); ++index) { - IXWindowsClipboardConverter* converter = *index; - - // skip already handled targets - if (m_added[converter->getFormat()]) { - continue; - } - - // see if atom is in target list - CMotifFormatMap::const_iterator index2 = - motifFormats.find(converter->getAtom()); - if (index2 == motifFormats.end()) { - continue; - } - - // get format - const CMotifClipFormat* motifFormat = - reinterpret_cast( - index2->second.data()); - const Atom target = motifFormat->m_type; - - // get the data (finally) - Atom actualTarget; - CString targetData; - if (!motifGetSelection(motifFormat, &actualTarget, &targetData)) { - LOG((CLOG_DEBUG1 " no data for target %s", CXWindowsUtil::atomToString(m_display, target).c_str())); - continue; - } - - // add to clipboard and note we've done it - IClipboard::EFormat format = converter->getFormat(); - m_data[format] = converter->toIClipboard(targetData); - m_added[format] = true; - LOG((CLOG_DEBUG " added format %d for target %s", format, CXWindowsUtil::atomToString(m_display, target).c_str())); - } -} - -bool -CXWindowsClipboard::motifGetSelection(const CMotifClipFormat* format, - Atom* actualTarget, CString* data) const -{ - // if the current clipboard owner and the owner indicated by the - // motif clip header are the same then transfer via a property on - // the root window, otherwise transfer as a normal ICCCM client. - if (!motifOwnsClipboard()) { - return icccmGetSelection(format->m_type, actualTarget, data); - } - - // use motif way - // FIXME -- this isn't right. it'll only work if the data is - // already stored on the root window and only if it fits in a - // property. motif has some scheme for transferring part by - // part that i don't know. - char name[18 + 20]; - sprintf(name, "_MOTIF_CLIP_ITEM_%d", format->m_data); - Atom target = XInternAtom(m_display, name, False); - Window root = RootWindow(m_display, DefaultScreen(m_display)); - return CXWindowsUtil::getWindowProperty(m_display, root, - target, data, - actualTarget, NULL, False); -} - -IClipboard::Time -CXWindowsClipboard::motifGetTime() const -{ - return icccmGetTime(); -} - -bool -CXWindowsClipboard::insertMultipleReply(Window requestor, - ::Time time, Atom property) -{ - // get the requested targets - Atom target; - SInt32 format; - CString data; - if (!CXWindowsUtil::getWindowProperty(m_display, requestor, - property, &data, &target, &format, False)) { - // can't get the requested targets - return false; - } - - // fail if the requested targets isn't of the correct form - if (format != 32 || target != m_atomAtomPair) { - return false; - } - - // data is a list of atom pairs: target, property - CXWindowsUtil::convertAtomProperty(data); - const Atom* targets = reinterpret_cast(data.data()); - const UInt32 numTargets = data.size() / sizeof(Atom); - - // add replies for each target - bool changed = false; - for (UInt32 i = 0; i < numTargets; i += 2) { - const Atom target = targets[i + 0]; - const Atom property = targets[i + 1]; - if (!addSimpleRequest(requestor, target, time, property)) { - // note that we can't perform the requested conversion - CXWindowsUtil::replaceAtomData(data, i, None); - changed = true; - } - } - - // update the targets property if we changed it - if (changed) { - CXWindowsUtil::setWindowProperty(m_display, requestor, - property, data.data(), data.size(), - target, format); - } - - // add reply for MULTIPLE request - insertReply(new CReply(requestor, m_atomMultiple, - time, property, CString(), None, 32)); - - return true; -} - -void -CXWindowsClipboard::insertReply(CReply* reply) -{ - assert(reply != NULL); - - // note -- we must respond to requests in order if requestor,target,time - // are the same, otherwise we can use whatever order we like with one - // exception: each reply in a MULTIPLE reply must be handled in order - // as well. those replies will almost certainly not share targets so - // we can't simply use requestor,target,time as map index. - // - // instead we'll use just the requestor. that's more restrictive than - // necessary but we're guaranteed to do things in the right order. - // note that we could also include the time in the map index and still - // ensure the right order. but since that'll just make it harder to - // find the right reply when handling property notify events we stick - // to just the requestor. - - const bool newWindow = (m_replies.count(reply->m_requestor) == 0); - m_replies[reply->m_requestor].push_back(reply); - - // adjust requestor's event mask if we haven't done so already. we - // want events in case the window is destroyed or any of its - // properties change. - if (newWindow) { - // note errors while we adjust event masks - bool error = false; - { - CXWindowsUtil::CErrorLock lock(m_display, &error); - - // get and save the current event mask - XWindowAttributes attr; - XGetWindowAttributes(m_display, reply->m_requestor, &attr); - m_eventMasks[reply->m_requestor] = attr.your_event_mask; - - // add the events we want - XSelectInput(m_display, reply->m_requestor, attr.your_event_mask | - StructureNotifyMask | PropertyChangeMask); - } - - // if we failed then the window has already been destroyed - if (error) { - m_replies.erase(reply->m_requestor); - delete reply; - } - } -} - -void -CXWindowsClipboard::pushReplies() -{ - // send the first reply for each window if that reply hasn't - // been sent yet. - for (CReplyMap::iterator index = m_replies.begin(); - index != m_replies.end(); ) { - assert(!index->second.empty()); - if (!index->second.front()->m_replied) { - pushReplies(index, index->second, index->second.begin()); - } - else { - ++index; - } - } -} - -void -CXWindowsClipboard::pushReplies(CReplyMap::iterator& mapIndex, - CReplyList& replies, CReplyList::iterator index) -{ - CReply* reply = *index; - while (sendReply(reply)) { - // reply is complete. discard it and send the next reply, - // if any. - index = replies.erase(index); - delete reply; - if (index == replies.end()) { - break; - } - reply = *index; - } - - // if there are no more replies in the list then remove the list - // and stop watching the requestor for events. - if (replies.empty()) { - CXWindowsUtil::CErrorLock lock(m_display); - Window requestor = mapIndex->first; - XSelectInput(m_display, requestor, m_eventMasks[requestor]); - m_replies.erase(mapIndex++); - m_eventMasks.erase(requestor); - } - else { - ++mapIndex; - } -} - -bool -CXWindowsClipboard::sendReply(CReply* reply) -{ - assert(reply != NULL); - - // bail out immediately if reply is done - if (reply->m_done) { - LOG((CLOG_DEBUG1 "clipboard: finished reply to 0x%08x,%d,%d", reply->m_requestor, reply->m_target, reply->m_property)); - return true; - } - - // start in failed state if property is None - bool failed = (reply->m_property == None); - if (!failed) { - LOG((CLOG_DEBUG1 "clipboard: setting property on 0x%08x,%d,%d", reply->m_requestor, reply->m_target, reply->m_property)); - - // send using INCR if already sending incrementally or if reply - // is too large, otherwise just send it. - const UInt32 maxRequestSize = 3 * XMaxRequestSize(m_display); - const bool useINCR = (reply->m_data.size() > maxRequestSize); - - // send INCR reply if incremental and we haven't replied yet - if (useINCR && !reply->m_replied) { - UInt32 size = reply->m_data.size(); - if (!CXWindowsUtil::setWindowProperty(m_display, - reply->m_requestor, reply->m_property, - &size, 4, m_atomINCR, 32)) { - failed = true; - } - } - - // send more INCR reply or entire non-incremental reply - else { - // how much more data should we send? - UInt32 size = reply->m_data.size() - reply->m_ptr; - if (size > maxRequestSize) - size = maxRequestSize; - - // send it - if (!CXWindowsUtil::setWindowProperty(m_display, - reply->m_requestor, reply->m_property, - reply->m_data.data() + reply->m_ptr, - size, - reply->m_type, reply->m_format)) { - failed = true; - } - else { - reply->m_ptr += size; - - // we've finished the reply if we just sent the zero - // size incremental chunk or if we're not incremental. - reply->m_done = (size == 0 || !useINCR); - } - } - } - - // if we've failed then delete the property and say we're done. - // if we haven't replied yet then we can send a failure notify, - // otherwise we've failed in the middle of an incremental - // transfer; i don't know how to cancel that so i'll just send - // the final zero-length property. - // FIXME -- how do you gracefully cancel an incremental transfer? - if (failed) { - LOG((CLOG_DEBUG1 "clipboard: sending failure to 0x%08x,%d,%d", reply->m_requestor, reply->m_target, reply->m_property)); - reply->m_done = true; - if (reply->m_property != None) { - CXWindowsUtil::CErrorLock lock(m_display); - XDeleteProperty(m_display, reply->m_requestor, reply->m_property); - } - - if (!reply->m_replied) { - sendNotify(reply->m_requestor, m_selection, - reply->m_target, None, - reply->m_time); - - // don't wait for any reply (because we're not expecting one) - return true; - } - else { - static const char dummy = 0; - CXWindowsUtil::setWindowProperty(m_display, - reply->m_requestor, reply->m_property, - &dummy, - 0, - reply->m_type, reply->m_format); - - // wait for delete notify - return false; - } - } - - // send notification if we haven't yet - if (!reply->m_replied) { - LOG((CLOG_DEBUG1 "clipboard: sending notify to 0x%08x,%d,%d", reply->m_requestor, reply->m_target, reply->m_property)); - reply->m_replied = true; - - // dump every property on the requestor window to the debug2 - // log. we've seen what appears to be a bug in lesstif and - // knowing the properties may help design a workaround, if - // it becomes necessary. - if (CLOG->getFilter() >= CLog::kDEBUG2) { - CXWindowsUtil::CErrorLock lock(m_display); - int n; - Atom* props = XListProperties(m_display, reply->m_requestor, &n); - LOG((CLOG_DEBUG2 "properties of 0x%08x:", reply->m_requestor)); - for (int i = 0; i < n; ++i) { - Atom target; - CString data; - char* name = XGetAtomName(m_display, props[i]); - if (!CXWindowsUtil::getWindowProperty(m_display, - reply->m_requestor, - props[i], &data, &target, NULL, False)) { - LOG((CLOG_DEBUG2 " %s: ", name)); - } - else { - // if there are any non-ascii characters in string - // then print the binary data. - static const char* hex = "0123456789abcdef"; - for (CString::size_type j = 0; j < data.size(); ++j) { - if (data[j] < 32 || data[j] > 126) { - CString tmp; - tmp.reserve(data.size() * 3); - for (j = 0; j < data.size(); ++j) { - unsigned char v = (unsigned char)data[j]; - tmp += hex[v >> 16]; - tmp += hex[v & 15]; - tmp += ' '; - } - data = tmp; - break; - } - } - char* type = XGetAtomName(m_display, target); - LOG((CLOG_DEBUG2 " %s (%s): %s", name, type, data.c_str())); - if (type != NULL) { - XFree(type); - } - } - if (name != NULL) { - XFree(name); - } - } - if (props != NULL) { - XFree(props); - } - } - - sendNotify(reply->m_requestor, m_selection, - reply->m_target, reply->m_property, - reply->m_time); - } - - // wait for delete notify - return false; -} - -void -CXWindowsClipboard::clearReplies() -{ - for (CReplyMap::iterator index = m_replies.begin(); - index != m_replies.end(); ++index) { - clearReplies(index->second); - } - m_replies.clear(); - m_eventMasks.clear(); -} - -void -CXWindowsClipboard::clearReplies(CReplyList& replies) -{ - for (CReplyList::iterator index = replies.begin(); - index != replies.end(); ++index) { - delete *index; - } - replies.clear(); -} - -void -CXWindowsClipboard::sendNotify(Window requestor, - Atom selection, Atom target, Atom property, Time time) -{ - XEvent event; - event.xselection.type = SelectionNotify; - event.xselection.display = m_display; - event.xselection.requestor = requestor; - event.xselection.selection = selection; - event.xselection.target = target; - event.xselection.property = property; - event.xselection.time = time; - CXWindowsUtil::CErrorLock lock(m_display); - XSendEvent(m_display, requestor, False, 0, &event); -} - -bool -CXWindowsClipboard::wasOwnedAtTime(::Time time) const -{ - // not owned if we've never owned the selection - checkCache(); - if (m_timeOwned == 0) { - return false; - } - - // if time is CurrentTime then return true if we still own the - // selection and false if we do not. else if we still own the - // selection then get the current time, otherwise use - // m_timeLost as the end time. - Time lost = m_timeLost; - if (m_timeLost == 0) { - if (time == CurrentTime) { - return true; - } - else { - lost = CXWindowsUtil::getCurrentTime(m_display, m_window); - } - } - else { - if (time == CurrentTime) { - return false; - } - } - - // compare time to range - Time duration = lost - m_timeOwned; - Time when = time - m_timeOwned; - return (/*when >= 0 &&*/ when <= duration); -} - -Atom -CXWindowsClipboard::getTargetsData(CString& data, int* format) const -{ - assert(format != NULL); - - // add standard targets - CXWindowsUtil::appendAtomData(data, m_atomTargets); - CXWindowsUtil::appendAtomData(data, m_atomMultiple); - CXWindowsUtil::appendAtomData(data, m_atomTimestamp); - - // add targets we can convert to - for (ConverterList::const_iterator index = m_converters.begin(); - index != m_converters.end(); ++index) { - IXWindowsClipboardConverter* converter = *index; - - // skip formats we don't have - if (m_added[converter->getFormat()]) { - CXWindowsUtil::appendAtomData(data, converter->getAtom()); - } - } - - *format = 32; - return m_atomAtom; -} - -Atom -CXWindowsClipboard::getTimestampData(CString& data, int* format) const -{ - assert(format != NULL); - - checkCache(); - CXWindowsUtil::appendTimeData(data, m_timeOwned); - *format = 32; - return m_atomInteger; -} - - -// -// CXWindowsClipboard::CICCCMGetClipboard -// - -CXWindowsClipboard::CICCCMGetClipboard::CICCCMGetClipboard( - Window requestor, Time time, Atom property) : - m_requestor(requestor), - m_time(time), - m_property(property), - m_incr(false), - m_failed(false), - m_done(false), - m_reading(false), - m_data(NULL), - m_actualTarget(NULL), - m_error(false) -{ - // do nothing -} - -CXWindowsClipboard::CICCCMGetClipboard::~CICCCMGetClipboard() -{ - // do nothing -} - -bool -CXWindowsClipboard::CICCCMGetClipboard::readClipboard(Display* display, - Atom selection, Atom target, Atom* actualTarget, CString* data) -{ - assert(actualTarget != NULL); - assert(data != NULL); - - LOG((CLOG_DEBUG1 "request selection=%s, target=%s, window=%x", CXWindowsUtil::atomToString(display, selection).c_str(), CXWindowsUtil::atomToString(display, target).c_str(), m_requestor)); - - m_atomNone = XInternAtom(display, "NONE", False); - m_atomIncr = XInternAtom(display, "INCR", False); - - // save output pointers - m_actualTarget = actualTarget; - m_data = data; - - // assume failure - *m_actualTarget = None; - *m_data = ""; - - // delete target property - XDeleteProperty(display, m_requestor, m_property); - - // select window for property changes - XWindowAttributes attr; - XGetWindowAttributes(display, m_requestor, &attr); - XSelectInput(display, m_requestor, - attr.your_event_mask | PropertyChangeMask); - - // request data conversion - XConvertSelection(display, selection, target, - m_property, m_requestor, m_time); - - // synchronize with server before we start following timeout countdown - XSync(display, False); - - // Xlib inexplicably omits the ability to wait for an event with - // a timeout. (it's inexplicable because there's no portable way - // to do it.) we'll poll until we have what we're looking for or - // a timeout expires. we use a timeout so we don't get locked up - // by badly behaved selection owners. - XEvent xevent; - std::vector events; - CStopwatch timeout(true); - static const double s_timeout = 0.25; // FIXME -- is this too short? - bool noWait = false; - while (!m_done && !m_failed) { - // fail if timeout has expired - if (timeout.getTime() >= s_timeout) { - m_failed = true; - break; - } - - // process events if any otherwise sleep - if (noWait || XPending(display) > 0) { - while (!m_done && !m_failed && (noWait || XPending(display) > 0)) { - XNextEvent(display, &xevent); - if (!processEvent(display, &xevent)) { - // not processed so save it - events.push_back(xevent); - } - else { - // reset timer since we've made some progress - timeout.reset(); - - // don't sleep anymore, just block waiting for events. - // we're assuming here that the clipboard owner will - // complete the protocol correctly. if we continue to - // sleep we'll get very bad performance. - noWait = true; - } - } - } - else { - ARCH->sleep(0.01); - } - } - - // put unprocessed events back - for (UInt32 i = events.size(); i > 0; --i) { - XPutBackEvent(display, &events[i - 1]); - } - - // restore mask - XSelectInput(display, m_requestor, attr.your_event_mask); - - // return success or failure - LOG((CLOG_DEBUG1 "request %s", m_failed ? "failed" : "succeeded")); - return !m_failed; -} - -bool -CXWindowsClipboard::CICCCMGetClipboard::processEvent( - Display* display, XEvent* xevent) -{ - // process event - switch (xevent->type) { - case DestroyNotify: - if (xevent->xdestroywindow.window == m_requestor) { - m_failed = true; - return true; - } - - // not interested - return false; - - case SelectionNotify: - if (xevent->xselection.requestor == m_requestor) { - // done if we can't convert - if (xevent->xselection.property == None || - xevent->xselection.property == m_atomNone) { - m_done = true; - return true; - } - - // proceed if conversion successful - else if (xevent->xselection.property == m_property) { - m_reading = true; - break; - } - } - - // otherwise not interested - return false; - - case PropertyNotify: - // proceed if conversion successful and we're receiving more data - if (xevent->xproperty.window == m_requestor && - xevent->xproperty.atom == m_property && - xevent->xproperty.state == PropertyNewValue) { - if (!m_reading) { - // we haven't gotten the SelectionNotify yet - return true; - } - break; - } - - // otherwise not interested - return false; - - default: - // not interested - return false; - } - - // get the data from the property - Atom target; - const CString::size_type oldSize = m_data->size(); - if (!CXWindowsUtil::getWindowProperty(display, m_requestor, - m_property, m_data, &target, NULL, True)) { - // unable to read property - m_failed = true; - return true; - } - - // note if incremental. if we're already incremental then the - // selection owner is busted. if the INCR property has no size - // then the selection owner is busted. - if (target == m_atomIncr) { - if (m_incr) { - m_failed = true; - m_error = true; - } - else if (m_data->size() == oldSize) { - m_failed = true; - m_error = true; - } - else { - m_incr = true; - - // discard INCR data - *m_data = ""; - } - } - - // handle incremental chunks - else if (m_incr) { - // if first incremental chunk then save target - if (oldSize == 0) { - LOG((CLOG_DEBUG1 " INCR first chunk, target %s", CXWindowsUtil::atomToString(display, target).c_str())); - *m_actualTarget = target; - } - - // secondary chunks must have the same target - else { - if (target != *m_actualTarget) { - LOG((CLOG_WARN " INCR target mismatch")); - m_failed = true; - m_error = true; - } - } - - // note if this is the final chunk - if (m_data->size() == oldSize) { - LOG((CLOG_DEBUG1 " INCR final chunk: %d bytes total", m_data->size())); - m_done = true; - } - } - - // not incremental; save the target. - else { - LOG((CLOG_DEBUG1 " target %s", CXWindowsUtil::atomToString(display, target).c_str())); - *m_actualTarget = target; - m_done = true; - } - - // this event has been processed - LOGC(!m_incr, (CLOG_DEBUG1 " got data, %d bytes", m_data->size())); - return true; -} - - -// -// CXWindowsClipboard::CReply -// - -CXWindowsClipboard::CReply::CReply(Window requestor, Atom target, ::Time time) : - m_requestor(requestor), - m_target(target), - m_time(time), - m_property(None), - m_replied(false), - m_done(false), - m_data(), - m_type(None), - m_format(32), - m_ptr(0) -{ - // do nothing -} - -CXWindowsClipboard::CReply::CReply(Window requestor, Atom target, ::Time time, - Atom property, const CString& data, Atom type, int format) : - m_requestor(requestor), - m_target(target), - m_time(time), - m_property(property), - m_replied(false), - m_done(false), - m_data(data), - m_type(type), - m_format(format), - m_ptr(0) -{ - // do nothing -} diff --git a/lib/platform/CXWindowsClipboard.h b/lib/platform/CXWindowsClipboard.h deleted file mode 100644 index b36a6c8d..00000000 --- a/lib/platform/CXWindowsClipboard.h +++ /dev/null @@ -1,376 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CXWINDOWSCLIPBOARD_H -#define CXWINDOWSCLIPBOARD_H - -#include "IClipboard.h" -#include "ClipboardTypes.h" -#include "stdmap.h" -#include "stdlist.h" -#include "stdvector.h" -#if X_DISPLAY_MISSING -# error X11 is required to build synergy -#else -# include -#endif - -class IXWindowsClipboardConverter; - -//! X11 clipboard implementation -class CXWindowsClipboard : public IClipboard { -public: - /*! - Use \c window as the window that owns or interacts with the - clipboard identified by \c id. - */ - CXWindowsClipboard(Display*, Window window, ClipboardID id); - virtual ~CXWindowsClipboard(); - - //! Notify clipboard was lost - /*! - Tells clipboard it lost ownership at the given time. - */ - void lost(Time); - - //! Add clipboard request - /*! - Adds a selection request to the request list. If the given - owner window isn't this clipboard's window then this simply - sends a failure event to the requestor. - */ - void addRequest(Window owner, - Window requestor, Atom target, - ::Time time, Atom property); - - //! Process clipboard request - /*! - Continues processing a selection request. Returns true if the - request was handled, false if the request was unknown. - */ - bool processRequest(Window requestor, - ::Time time, Atom property); - - //! Cancel clipboard request - /*! - Terminate a selection request. Returns true iff the request - was known and handled. - */ - bool destroyRequest(Window requestor); - - //! Get window - /*! - Returns the clipboard's window (passed the c'tor). - */ - Window getWindow() const; - - //! Get selection atom - /*! - Returns the selection atom that identifies the clipboard to X11 - (e.g. XA_PRIMARY). - */ - Atom getSelection() const; - - // IClipboard overrides - virtual bool empty(); - virtual void add(EFormat, const CString& data); - virtual bool open(Time) const; - virtual void close() const; - virtual Time getTime() const; - virtual bool has(EFormat) const; - virtual CString get(EFormat) const; - -private: - // remove all converters from our list - void clearConverters(); - - // get the converter for a clipboard format. returns NULL if no - // suitable converter. iff onlyIfNotAdded is true then also - // return NULL if a suitable converter was found but we already - // have data of the converter's clipboard format. - IXWindowsClipboardConverter* - getConverter(Atom target, - bool onlyIfNotAdded = false) const; - - // convert target atom to clipboard format - EFormat getFormat(Atom target) const; - - // add a non-MULTIPLE request. does not verify that the selection - // was owned at the given time. returns true if the conversion - // could be performed, false otherwise. in either case, the - // reply is inserted. - bool addSimpleRequest( - Window requestor, Atom target, - ::Time time, Atom property); - - // if not already checked then see if the cache is stale and, if so, - // clear it. this has the side effect of updating m_timeOwned. - void checkCache() const; - - // clear the cache, resetting the cached flag and the added flag for - // each format. - void clearCache() const; - void doClearCache(); - - // cache all formats of the selection - void fillCache() const; - void doFillCache(); - - // - // helper classes - // - - // read an ICCCM conforming selection - class CICCCMGetClipboard { - public: - CICCCMGetClipboard(Window requestor, Time time, Atom property); - ~CICCCMGetClipboard(); - - // convert the given selection to the given type. returns - // true iff the conversion was successful or the conversion - // cannot be performed (in which case *actualTarget == None). - bool readClipboard(Display* display, - Atom selection, Atom target, - Atom* actualTarget, CString* data); - - private: - bool processEvent(Display* display, XEvent* event); - - private: - Window m_requestor; - Time m_time; - Atom m_property; - bool m_incr; - bool m_failed; - bool m_done; - - // atoms needed for the protocol - Atom m_atomNone; // NONE, not None - Atom m_atomIncr; - - // true iff we've received the selection notify - bool m_reading; - - // the converted selection data - CString* m_data; - - // the actual type of the data. if this is None then the - // selection owner cannot convert to the requested type. - Atom* m_actualTarget; - - public: - // true iff the selection owner didn't follow ICCCM conventions - bool m_error; - }; - - // Motif structure IDs - enum { kMotifClipFormat = 1, kMotifClipItem, kMotifClipHeader }; - - // _MOTIF_CLIP_HEADER structure - class CMotifClipHeader { - public: - SInt32 m_id; // kMotifClipHeader - SInt32 m_pad1[3]; - SInt32 m_item; - SInt32 m_pad2[4]; - SInt32 m_numItems; - SInt32 m_pad3[3]; - SInt32 m_selectionOwner; // a Window - SInt32 m_pad4[2]; - }; - - // Motif clip item structure - class CMotifClipItem { - public: - SInt32 m_id; // kMotifClipItem - SInt32 m_pad1[5]; - SInt32 m_size; - SInt32 m_numFormats; - SInt32 m_numDeletedFormats; - SInt32 m_pad2[6]; - }; - - // Motif clip format structure - class CMotifClipFormat { - public: - SInt32 m_id; // kMotifClipFormat - SInt32 m_pad1[6]; - SInt32 m_length; - SInt32 m_data; - SInt32 m_type; // an Atom - SInt32 m_pad2[1]; - SInt32 m_deleted; - SInt32 m_pad3[4]; - }; - - // stores data needed to respond to a selection request - class CReply { - public: - CReply(Window, Atom target, ::Time); - CReply(Window, Atom target, ::Time, Atom property, - const CString& data, Atom type, int format); - - public: - // information about the request - Window m_requestor; - Atom m_target; - ::Time m_time; - Atom m_property; - - // true iff we've sent the notification for this reply - bool m_replied; - - // true iff the reply has sent its last message - bool m_done; - - // the data to send and its type and format - CString m_data; - Atom m_type; - int m_format; - - // index of next byte in m_data to send - UInt32 m_ptr; - }; - typedef std::list CReplyList; - typedef std::map CReplyMap; - typedef std::map CReplyEventMask; - - // ICCCM interoperability methods - void icccmFillCache(); - bool icccmGetSelection(Atom target, - Atom* actualTarget, CString* data) const; - Time icccmGetTime() const; - - // motif interoperability methods - bool motifLockClipboard() const; - void motifUnlockClipboard() const; - bool motifOwnsClipboard() const; - void motifFillCache(); - bool motifGetSelection(const CMotifClipFormat*, - Atom* actualTarget, CString* data) const; - Time motifGetTime() const; - - // reply methods - bool insertMultipleReply(Window, ::Time, Atom); - void insertReply(CReply*); - void pushReplies(); - void pushReplies(CReplyMap::iterator&, - CReplyList&, CReplyList::iterator); - bool sendReply(CReply*); - void clearReplies(); - void clearReplies(CReplyList&); - void sendNotify(Window requestor, Atom selection, - Atom target, Atom property, Time time); - bool wasOwnedAtTime(::Time) const; - - // data conversion methods - Atom getTargetsData(CString&, int* format) const; - Atom getTimestampData(CString&, int* format) const; - -private: - typedef std::vector ConverterList; - - Display* m_display; - Window m_window; - ClipboardID m_id; - Atom m_selection; - mutable bool m_open; - mutable Time m_time; - bool m_owner; - mutable Time m_timeOwned; - Time m_timeLost; - - // true iff open and clipboard owned by a motif app - mutable bool m_motif; - - // the added/cached clipboard data - mutable bool m_checkCache; - bool m_cached; - Time m_cacheTime; - bool m_added[kNumFormats]; - CString m_data[kNumFormats]; - - // conversion request replies - CReplyMap m_replies; - CReplyEventMask m_eventMasks; - - // clipboard format converters - ConverterList m_converters; - - // atoms we'll need - Atom m_atomTargets; - Atom m_atomMultiple; - Atom m_atomTimestamp; - Atom m_atomInteger; - Atom m_atomAtom; - Atom m_atomAtomPair; - Atom m_atomData; - Atom m_atomINCR; - Atom m_atomMotifClipLock; - Atom m_atomMotifClipHeader; - Atom m_atomMotifClipAccess; - Atom m_atomGDKSelection; -}; - -//! Clipboard format converter interface -/*! -This interface defines the methods common to all X11 clipboard format -converters. -*/ -class IXWindowsClipboardConverter : public IInterface { -public: - //! @name accessors - //@{ - - //! Get clipboard format - /*! - Return the clipboard format this object converts from/to. - */ - virtual IClipboard::EFormat - getFormat() const = 0; - - //! Get X11 format atom - /*! - Return the atom representing the X selection format that - this object converts from/to. - */ - virtual Atom getAtom() const = 0; - - //! Get X11 property datum size - /*! - Return the size (in bits) of data elements returned by - toIClipboard(). - */ - virtual int getDataSize() const = 0; - - //! Convert from IClipboard format - /*! - Convert from the IClipboard format to the X selection format. - The input data must be in the IClipboard format returned by - getFormat(). The return data will be in the X selection - format returned by getAtom(). - */ - virtual CString fromIClipboard(const CString&) const = 0; - - //! Convert to IClipboard format - /*! - Convert from the X selection format to the IClipboard format - (i.e., the reverse of fromIClipboard()). - */ - virtual CString toIClipboard(const CString&) const = 0; - - //@} -}; - -#endif diff --git a/lib/platform/CXWindowsClipboardAnyBitmapConverter.cpp b/lib/platform/CXWindowsClipboardAnyBitmapConverter.cpp deleted file mode 100644 index ab6afae2..00000000 --- a/lib/platform/CXWindowsClipboardAnyBitmapConverter.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CXWindowsClipboardAnyBitmapConverter.h" - -// BMP info header structure -struct CBMPInfoHeader { -public: - UInt32 biSize; - SInt32 biWidth; - SInt32 biHeight; - UInt16 biPlanes; - UInt16 biBitCount; - UInt32 biCompression; - UInt32 biSizeImage; - SInt32 biXPelsPerMeter; - SInt32 biYPelsPerMeter; - UInt32 biClrUsed; - UInt32 biClrImportant; -}; - -// BMP is little-endian - -static -void -toLE(UInt8*& dst, UInt16 src) -{ - dst[0] = static_cast(src & 0xffu); - dst[1] = static_cast((src >> 8) & 0xffu); - dst += 2; -} - -static -void -toLE(UInt8*& dst, SInt32 src) -{ - dst[0] = static_cast(src & 0xffu); - dst[1] = static_cast((src >> 8) & 0xffu); - dst[2] = static_cast((src >> 16) & 0xffu); - dst[3] = static_cast((src >> 24) & 0xffu); - dst += 4; -} - -static -void -toLE(UInt8*& dst, UInt32 src) -{ - dst[0] = static_cast(src & 0xffu); - dst[1] = static_cast((src >> 8) & 0xffu); - dst[2] = static_cast((src >> 16) & 0xffu); - dst[3] = static_cast((src >> 24) & 0xffu); - dst += 4; -} - -static inline -UInt16 -fromLEU16(const UInt8* data) -{ - return static_cast(data[0]) | - (static_cast(data[1]) << 8); -} - -static inline -SInt32 -fromLES32(const UInt8* data) -{ - return static_cast(static_cast(data[0]) | - (static_cast(data[1]) << 8) | - (static_cast(data[2]) << 16) | - (static_cast(data[3]) << 24)); -} - -static inline -UInt32 -fromLEU32(const UInt8* data) -{ - return static_cast(data[0]) | - (static_cast(data[1]) << 8) | - (static_cast(data[2]) << 16) | - (static_cast(data[3]) << 24); -} - - -// -// CXWindowsClipboardAnyBitmapConverter -// - -CXWindowsClipboardAnyBitmapConverter::CXWindowsClipboardAnyBitmapConverter() -{ - // do nothing -} - -CXWindowsClipboardAnyBitmapConverter::~CXWindowsClipboardAnyBitmapConverter() -{ - // do nothing -} - -IClipboard::EFormat -CXWindowsClipboardAnyBitmapConverter::getFormat() const -{ - return IClipboard::kBitmap; -} - -int -CXWindowsClipboardAnyBitmapConverter::getDataSize() const -{ - return 8; -} - -CString -CXWindowsClipboardAnyBitmapConverter::fromIClipboard(const CString& bmp) const -{ - // fill BMP info header with native-endian data - CBMPInfoHeader infoHeader; - const UInt8* rawBMPInfoHeader = reinterpret_cast(bmp.data()); - infoHeader.biSize = fromLEU32(rawBMPInfoHeader + 0); - infoHeader.biWidth = fromLES32(rawBMPInfoHeader + 4); - infoHeader.biHeight = fromLES32(rawBMPInfoHeader + 8); - infoHeader.biPlanes = fromLEU16(rawBMPInfoHeader + 12); - infoHeader.biBitCount = fromLEU16(rawBMPInfoHeader + 14); - infoHeader.biCompression = fromLEU32(rawBMPInfoHeader + 16); - infoHeader.biSizeImage = fromLEU32(rawBMPInfoHeader + 20); - infoHeader.biXPelsPerMeter = fromLES32(rawBMPInfoHeader + 24); - infoHeader.biYPelsPerMeter = fromLES32(rawBMPInfoHeader + 28); - infoHeader.biClrUsed = fromLEU32(rawBMPInfoHeader + 32); - infoHeader.biClrImportant = fromLEU32(rawBMPInfoHeader + 36); - - // check that format is acceptable - if (infoHeader.biSize != 40 || - infoHeader.biWidth == 0 || infoHeader.biHeight == 0 || - infoHeader.biPlanes != 0 || infoHeader.biCompression != 0 || - (infoHeader.biBitCount != 24 && infoHeader.biBitCount != 32)) { - return CString(); - } - - // convert to image format - const UInt8* rawBMPPixels = rawBMPInfoHeader + 40; - if (infoHeader.biBitCount == 24) { - return doBGRFromIClipboard(rawBMPPixels, - infoHeader.biWidth, infoHeader.biHeight); - } - else { - return doBGRAFromIClipboard(rawBMPPixels, - infoHeader.biWidth, infoHeader.biHeight); - } -} - -CString -CXWindowsClipboardAnyBitmapConverter::toIClipboard(const CString& image) const -{ - // convert to raw BMP data - UInt32 w, h, depth; - CString rawBMP = doToIClipboard(image, w, h, depth); - if (rawBMP.empty() || w == 0 || h == 0 || (depth != 24 && depth != 32)) { - return CString(); - } - - // fill BMP info header with little-endian data - UInt8 infoHeader[40]; - UInt8* dst = infoHeader; - toLE(dst, static_cast(40)); - toLE(dst, static_cast(w)); - toLE(dst, static_cast(h)); - toLE(dst, static_cast(1)); - toLE(dst, static_cast(depth)); - toLE(dst, static_cast(0)); // BI_RGB - toLE(dst, static_cast(image.size())); - toLE(dst, static_cast(2834)); // 72 dpi - toLE(dst, static_cast(2834)); // 72 dpi - toLE(dst, static_cast(0)); - toLE(dst, static_cast(0)); - - // construct image - return CString(reinterpret_cast(infoHeader), - sizeof(infoHeader)) + rawBMP; -} diff --git a/lib/platform/CXWindowsClipboardAnyBitmapConverter.h b/lib/platform/CXWindowsClipboardAnyBitmapConverter.h deleted file mode 100644 index 6a153422..00000000 --- a/lib/platform/CXWindowsClipboardAnyBitmapConverter.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CXWINDOWSCLIPBOARDANYBITMAPCONVERTER_H -#define CXWINDOWSCLIPBOARDANYBITMAPCONVERTER_H - -#include "CXWindowsClipboard.h" - -//! Convert to/from some text encoding -class CXWindowsClipboardAnyBitmapConverter : - public IXWindowsClipboardConverter { -public: - CXWindowsClipboardAnyBitmapConverter(); - virtual ~CXWindowsClipboardAnyBitmapConverter(); - - // IXWindowsClipboardConverter overrides - virtual IClipboard::EFormat - getFormat() const; - virtual Atom getAtom() const = 0; - virtual int getDataSize() const; - virtual CString fromIClipboard(const CString&) const; - virtual CString toIClipboard(const CString&) const; - -protected: - //! Convert from IClipboard format - /*! - Convert raw BGR pixel data to another image format. - */ - virtual CString doBGRFromIClipboard(const UInt8* bgrData, - UInt32 w, UInt32 h) const = 0; - - //! Convert from IClipboard format - /*! - Convert raw BGRA pixel data to another image format. - */ - virtual CString doBGRAFromIClipboard(const UInt8* bgrData, - UInt32 w, UInt32 h) const = 0; - - //! Convert to IClipboard format - /*! - Convert an image into raw BGR or BGRA image data and store the - width, height, and image depth (24 or 32). - */ - virtual CString doToIClipboard(const CString&, - UInt32& w, UInt32& h, UInt32& depth) const = 0; -}; - -#endif diff --git a/lib/platform/CXWindowsClipboardBMPConverter.cpp b/lib/platform/CXWindowsClipboardBMPConverter.cpp deleted file mode 100644 index 747d6850..00000000 --- a/lib/platform/CXWindowsClipboardBMPConverter.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CXWindowsClipboardBMPConverter.h" - -// BMP file header structure -struct CBMPHeader { -public: - UInt16 type; - UInt32 size; - UInt16 reserved1; - UInt16 reserved2; - UInt32 offset; -}; - -// BMP is little-endian -static inline -UInt32 -fromLEU32(const UInt8* data) -{ - return static_cast(data[0]) | - (static_cast(data[1]) << 8) | - (static_cast(data[2]) << 16) | - (static_cast(data[3]) << 24); -} - -static -void -toLE(UInt8*& dst, char src) -{ - dst[0] = static_cast(src); - dst += 1; -} - -static -void -toLE(UInt8*& dst, UInt16 src) -{ - dst[0] = static_cast(src & 0xffu); - dst[1] = static_cast((src >> 8) & 0xffu); - dst += 2; -} - -static -void -toLE(UInt8*& dst, UInt32 src) -{ - dst[0] = static_cast(src & 0xffu); - dst[1] = static_cast((src >> 8) & 0xffu); - dst[2] = static_cast((src >> 16) & 0xffu); - dst[3] = static_cast((src >> 24) & 0xffu); - dst += 4; -} - -// -// CXWindowsClipboardBMPConverter -// - -CXWindowsClipboardBMPConverter::CXWindowsClipboardBMPConverter( - Display* display) : - m_atom(XInternAtom(display, "image/bmp", False)) -{ - // do nothing -} - -CXWindowsClipboardBMPConverter::~CXWindowsClipboardBMPConverter() -{ - // do nothing -} - -IClipboard::EFormat -CXWindowsClipboardBMPConverter::getFormat() const -{ - return IClipboard::kBitmap; -} - -Atom -CXWindowsClipboardBMPConverter::getAtom() const -{ - return m_atom; -} - -int -CXWindowsClipboardBMPConverter::getDataSize() const -{ - return 8; -} - -CString -CXWindowsClipboardBMPConverter::fromIClipboard(const CString& bmp) const -{ - // create BMP image - UInt8 header[14]; - UInt8* dst = header; - toLE(dst, 'B'); - toLE(dst, 'M'); - toLE(dst, static_cast(14 + bmp.size())); - toLE(dst, static_cast(0)); - toLE(dst, static_cast(0)); - toLE(dst, static_cast(14 + 40)); - return CString(reinterpret_cast(header), 14) + bmp; -} - -CString -CXWindowsClipboardBMPConverter::toIClipboard(const CString& bmp) const -{ - // make sure data is big enough for a BMP file - if (bmp.size() <= 14 + 40) { - return CString(); - } - - // check BMP file header - const UInt8* rawBMPHeader = reinterpret_cast(bmp.data()); - if (rawBMPHeader[0] != 'B' || rawBMPHeader[1] != 'M') { - return CString(); - } - - // get offset to image data - UInt32 offset = fromLEU32(rawBMPHeader + 10); - - // construct BMP - if (offset == 14 + 40) { - return bmp.substr(14); - } - else { - return bmp.substr(14, 40) + bmp.substr(offset, bmp.size() - offset); - } -} diff --git a/lib/platform/CXWindowsClipboardBMPConverter.h b/lib/platform/CXWindowsClipboardBMPConverter.h deleted file mode 100644 index a7d44549..00000000 --- a/lib/platform/CXWindowsClipboardBMPConverter.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CXWINDOWSCLIPBOARDBMPCONVERTER_H -#define CXWINDOWSCLIPBOARDBMPCONVERTER_H - -#include "CXWindowsClipboard.h" - -//! Convert to/from some text encoding -class CXWindowsClipboardBMPConverter : - public IXWindowsClipboardConverter { -public: - CXWindowsClipboardBMPConverter(Display* display); - virtual ~CXWindowsClipboardBMPConverter(); - - // IXWindowsClipboardConverter overrides - virtual IClipboard::EFormat - getFormat() const; - virtual Atom getAtom() const; - virtual int getDataSize() const; - virtual CString fromIClipboard(const CString&) const; - virtual CString toIClipboard(const CString&) const; - -private: - Atom m_atom; -}; - -#endif diff --git a/lib/platform/CXWindowsClipboardHTMLConverter.cpp b/lib/platform/CXWindowsClipboardHTMLConverter.cpp deleted file mode 100644 index fafca54e..00000000 --- a/lib/platform/CXWindowsClipboardHTMLConverter.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CXWindowsClipboardHTMLConverter.h" -#include "CUnicode.h" - -// -// CXWindowsClipboardHTMLConverter -// - -CXWindowsClipboardHTMLConverter::CXWindowsClipboardHTMLConverter( - Display* display, const char* name) : - m_atom(XInternAtom(display, name, False)) -{ - // do nothing -} - -CXWindowsClipboardHTMLConverter::~CXWindowsClipboardHTMLConverter() -{ - // do nothing -} - -IClipboard::EFormat -CXWindowsClipboardHTMLConverter::getFormat() const -{ - return IClipboard::kHTML; -} - -Atom -CXWindowsClipboardHTMLConverter::getAtom() const -{ - return m_atom; -} - -int -CXWindowsClipboardHTMLConverter::getDataSize() const -{ - return 8; -} - -CString -CXWindowsClipboardHTMLConverter::fromIClipboard(const CString& data) const -{ - return CUnicode::UTF8ToUTF16(data); -} - -CString -CXWindowsClipboardHTMLConverter::toIClipboard(const CString& data) const -{ - return CUnicode::UTF16ToUTF8(data); -} diff --git a/lib/platform/CXWindowsClipboardHTMLConverter.h b/lib/platform/CXWindowsClipboardHTMLConverter.h deleted file mode 100644 index 7f761f20..00000000 --- a/lib/platform/CXWindowsClipboardHTMLConverter.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CXWINDOWSCLIPBOARDHTMLCONVERTER_H -#define CXWINDOWSCLIPBOARDHTMLCONVERTER_H - -#include "CXWindowsClipboard.h" - -//! Convert to/from HTML encoding -class CXWindowsClipboardHTMLConverter : public IXWindowsClipboardConverter { -public: - /*! - \c name is converted to an atom and that is reported by getAtom(). - */ - CXWindowsClipboardHTMLConverter(Display* display, const char* name); - virtual ~CXWindowsClipboardHTMLConverter(); - - // IXWindowsClipboardConverter overrides - virtual IClipboard::EFormat - getFormat() const; - virtual Atom getAtom() const; - virtual int getDataSize() const; - virtual CString fromIClipboard(const CString&) const; - virtual CString toIClipboard(const CString&) const; - -private: - Atom m_atom; -}; - -#endif diff --git a/lib/platform/CXWindowsClipboardTextConverter.cpp b/lib/platform/CXWindowsClipboardTextConverter.cpp deleted file mode 100644 index bd1a520c..00000000 --- a/lib/platform/CXWindowsClipboardTextConverter.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CXWindowsClipboardTextConverter.h" -#include "CUnicode.h" - -// -// CXWindowsClipboardTextConverter -// - -CXWindowsClipboardTextConverter::CXWindowsClipboardTextConverter( - Display* display, const char* name) : - m_atom(XInternAtom(display, name, False)) -{ - // do nothing -} - -CXWindowsClipboardTextConverter::~CXWindowsClipboardTextConverter() -{ - // do nothing -} - -IClipboard::EFormat -CXWindowsClipboardTextConverter::getFormat() const -{ - return IClipboard::kText; -} - -Atom -CXWindowsClipboardTextConverter::getAtom() const -{ - return m_atom; -} - -int -CXWindowsClipboardTextConverter::getDataSize() const -{ - return 8; -} - -CString -CXWindowsClipboardTextConverter::fromIClipboard(const CString& data) const -{ - return CUnicode::UTF8ToText(data); -} - -CString -CXWindowsClipboardTextConverter::toIClipboard(const CString& data) const -{ - // convert to UTF-8 - bool errors; - CString utf8 = CUnicode::textToUTF8(data, &errors); - - // if there were decoding errors then, to support old applications - // that don't understand UTF-8 but can report the exact binary - // UTF-8 representation, see if the data appears to be UTF-8. if - // so then use it as is. - if (errors && CUnicode::isUTF8(data)) { - return data; - } - - return utf8; -} diff --git a/lib/platform/CXWindowsClipboardTextConverter.h b/lib/platform/CXWindowsClipboardTextConverter.h deleted file mode 100644 index 3840b7df..00000000 --- a/lib/platform/CXWindowsClipboardTextConverter.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CXWINDOWSCLIPBOARDTEXTCONVERTER_H -#define CXWINDOWSCLIPBOARDTEXTCONVERTER_H - -#include "CXWindowsClipboard.h" - -//! Convert to/from locale text encoding -class CXWindowsClipboardTextConverter : public IXWindowsClipboardConverter { -public: - /*! - \c name is converted to an atom and that is reported by getAtom(). - */ - CXWindowsClipboardTextConverter(Display* display, const char* name); - virtual ~CXWindowsClipboardTextConverter(); - - // IXWindowsClipboardConverter overrides - virtual IClipboard::EFormat - getFormat() const; - virtual Atom getAtom() const; - virtual int getDataSize() const; - virtual CString fromIClipboard(const CString&) const; - virtual CString toIClipboard(const CString&) const; - -private: - Atom m_atom; -}; - -#endif diff --git a/lib/platform/CXWindowsClipboardUCS2Converter.cpp b/lib/platform/CXWindowsClipboardUCS2Converter.cpp deleted file mode 100644 index 86b8d13f..00000000 --- a/lib/platform/CXWindowsClipboardUCS2Converter.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CXWindowsClipboardUCS2Converter.h" -#include "CUnicode.h" - -// -// CXWindowsClipboardUCS2Converter -// - -CXWindowsClipboardUCS2Converter::CXWindowsClipboardUCS2Converter( - Display* display, const char* name) : - m_atom(XInternAtom(display, name, False)) -{ - // do nothing -} - -CXWindowsClipboardUCS2Converter::~CXWindowsClipboardUCS2Converter() -{ - // do nothing -} - -IClipboard::EFormat -CXWindowsClipboardUCS2Converter::getFormat() const -{ - return IClipboard::kText; -} - -Atom -CXWindowsClipboardUCS2Converter::getAtom() const -{ - return m_atom; -} - -int -CXWindowsClipboardUCS2Converter::getDataSize() const -{ - return 16; -} - -CString -CXWindowsClipboardUCS2Converter::fromIClipboard(const CString& data) const -{ - return CUnicode::UTF8ToUCS2(data); -} - -CString -CXWindowsClipboardUCS2Converter::toIClipboard(const CString& data) const -{ - return CUnicode::UCS2ToUTF8(data); -} diff --git a/lib/platform/CXWindowsClipboardUCS2Converter.h b/lib/platform/CXWindowsClipboardUCS2Converter.h deleted file mode 100644 index e848e302..00000000 --- a/lib/platform/CXWindowsClipboardUCS2Converter.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CXWINDOWSCLIPBOARDUCS2CONVERTER_H -#define CXWINDOWSCLIPBOARDUCS2CONVERTER_H - -#include "CXWindowsClipboard.h" - -//! Convert to/from UCS-2 encoding -class CXWindowsClipboardUCS2Converter : public IXWindowsClipboardConverter { -public: - /*! - \c name is converted to an atom and that is reported by getAtom(). - */ - CXWindowsClipboardUCS2Converter(Display* display, const char* name); - virtual ~CXWindowsClipboardUCS2Converter(); - - // IXWindowsClipboardConverter overrides - virtual IClipboard::EFormat - getFormat() const; - virtual Atom getAtom() const; - virtual int getDataSize() const; - virtual CString fromIClipboard(const CString&) const; - virtual CString toIClipboard(const CString&) const; - -private: - Atom m_atom; -}; - -#endif diff --git a/lib/platform/CXWindowsClipboardUTF8Converter.cpp b/lib/platform/CXWindowsClipboardUTF8Converter.cpp deleted file mode 100644 index 7edc850f..00000000 --- a/lib/platform/CXWindowsClipboardUTF8Converter.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CXWindowsClipboardUTF8Converter.h" - -// -// CXWindowsClipboardUTF8Converter -// - -CXWindowsClipboardUTF8Converter::CXWindowsClipboardUTF8Converter( - Display* display, const char* name) : - m_atom(XInternAtom(display, name, False)) -{ - // do nothing -} - -CXWindowsClipboardUTF8Converter::~CXWindowsClipboardUTF8Converter() -{ - // do nothing -} - -IClipboard::EFormat -CXWindowsClipboardUTF8Converter::getFormat() const -{ - return IClipboard::kText; -} - -Atom -CXWindowsClipboardUTF8Converter::getAtom() const -{ - return m_atom; -} - -int -CXWindowsClipboardUTF8Converter::getDataSize() const -{ - return 8; -} - -CString -CXWindowsClipboardUTF8Converter::fromIClipboard(const CString& data) const -{ - return data; -} - -CString -CXWindowsClipboardUTF8Converter::toIClipboard(const CString& data) const -{ - return data; -} diff --git a/lib/platform/CXWindowsClipboardUTF8Converter.h b/lib/platform/CXWindowsClipboardUTF8Converter.h deleted file mode 100644 index 5ac8b153..00000000 --- a/lib/platform/CXWindowsClipboardUTF8Converter.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CXWINDOWSCLIPBOARDUTF8CONVERTER_H -#define CXWINDOWSCLIPBOARDUTF8CONVERTER_H - -#include "CXWindowsClipboard.h" - -//! Convert to/from UTF-8 encoding -class CXWindowsClipboardUTF8Converter : public IXWindowsClipboardConverter { -public: - /*! - \c name is converted to an atom and that is reported by getAtom(). - */ - CXWindowsClipboardUTF8Converter(Display* display, const char* name); - virtual ~CXWindowsClipboardUTF8Converter(); - - // IXWindowsClipboardConverter overrides - virtual IClipboard::EFormat - getFormat() const; - virtual Atom getAtom() const; - virtual int getDataSize() const; - virtual CString fromIClipboard(const CString&) const; - virtual CString toIClipboard(const CString&) const; - -private: - Atom m_atom; -}; - -#endif diff --git a/lib/platform/CXWindowsEventQueueBuffer.cpp b/lib/platform/CXWindowsEventQueueBuffer.cpp deleted file mode 100644 index 170e5bc6..00000000 --- a/lib/platform/CXWindowsEventQueueBuffer.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CXWindowsEventQueueBuffer.h" -#include "CLock.h" -#include "CThread.h" -#include "CEvent.h" -#include "IEventQueue.h" -#if HAVE_POLL -# include -#else -# if HAVE_SYS_SELECT_H -# include -# endif -# if HAVE_SYS_TIME_H -# include -# endif -# if HAVE_SYS_TYPES_H -# include -# endif -# if HAVE_UNISTD_H -# include -# endif -#endif - -// -// CEventQueueTimer -// - -class CEventQueueTimer { }; - - -// -// CXWindowsEventQueueBuffer -// - -CXWindowsEventQueueBuffer::CXWindowsEventQueueBuffer( - Display* display, Window window) : - m_display(display), - m_window(window), - m_waiting(false) -{ - assert(m_display != NULL); - assert(m_window != None); - - m_userEvent = XInternAtom(m_display, "SYNERGY_USER_EVENT", False); -} - -CXWindowsEventQueueBuffer::~CXWindowsEventQueueBuffer() -{ - // do nothing -} - -void -CXWindowsEventQueueBuffer::waitForEvent(double dtimeout) -{ - CThread::testCancel(); - - { - CLock lock(&m_mutex); - // we're now waiting for events - m_waiting = true; - - // push out pending events - flush(); - } - - // use poll() to wait for a message from the X server or for timeout. - // this is a good deal more efficient than polling and sleeping. -#if HAVE_POLL - struct pollfd pfds[1]; - pfds[0].fd = ConnectionNumber(m_display); - pfds[0].events = POLLIN; - int timeout = (dtimeout < 0.0) ? -1 : - static_cast(1000.0 * dtimeout); -#else - struct timeval timeout; - struct timeval* timeoutPtr; - if (dtimeout < 0.0) { - timeoutPtr = NULL; - } - else { - timeout.tv_sec = static_cast(dtimeout); - timeout.tv_usec = static_cast(1.0e+6 * - (dtimeout - timeout.tv_sec)); - timeoutPtr = &timeout; - } - - // initialize file descriptor sets - fd_set rfds; - FD_ZERO(&rfds); - FD_SET(ConnectionNumber(m_display), &rfds); -#endif - - // wait for message from X server or for timeout. also check - // if the thread has been cancelled. poll() should return -1 - // with EINTR when the thread is cancelled. -#if HAVE_POLL - poll(pfds, 1, timeout); -#else - select(ConnectionNumber(m_display) + 1, - SELECT_TYPE_ARG234 &rfds, - SELECT_TYPE_ARG234 NULL, - SELECT_TYPE_ARG234 NULL, - SELECT_TYPE_ARG5 timeoutPtr); -#endif - - { - // we're no longer waiting for events - CLock lock(&m_mutex); - m_waiting = false; - } - - CThread::testCancel(); -} - -IEventQueueBuffer::Type -CXWindowsEventQueueBuffer::getEvent(CEvent& event, UInt32& dataID) -{ - CLock lock(&m_mutex); - - // push out pending events - flush(); - - // get next event - XNextEvent(m_display, &m_event); - - // process event - if (m_event.xany.type == ClientMessage && - m_event.xclient.message_type == m_userEvent) { - dataID = static_cast(m_event.xclient.data.l[0]); - return kUser; - } - else { - event = CEvent(CEvent::kSystem, - IEventQueue::getSystemTarget(), &m_event); - return kSystem; - } -} - -bool -CXWindowsEventQueueBuffer::addEvent(UInt32 dataID) -{ - // prepare a message - XEvent xevent; - xevent.xclient.type = ClientMessage; - xevent.xclient.window = m_window; - xevent.xclient.message_type = m_userEvent; - xevent.xclient.format = 32; - xevent.xclient.data.l[0] = static_cast(dataID); - - // save the message - CLock lock(&m_mutex); - m_postedEvents.push_back(xevent); - - // if we're currently waiting for an event then send saved events to - // the X server now. if we're not waiting then some other thread - // might be using the display connection so we can't safely use it - // too. - if (m_waiting) { - flush(); - } - - return true; -} - -bool -CXWindowsEventQueueBuffer::isEmpty() const -{ - CLock lock(&m_mutex); - return (XPending(m_display) == 0); -} - -CEventQueueTimer* -CXWindowsEventQueueBuffer::newTimer(double, bool) const -{ - return new CEventQueueTimer; -} - -void -CXWindowsEventQueueBuffer::deleteTimer(CEventQueueTimer* timer) const -{ - delete timer; -} - -void -CXWindowsEventQueueBuffer::flush() -{ - // note -- m_mutex must be locked on entry - - // flush the posted event list to the X server - for (size_t i = 0; i < m_postedEvents.size(); ++i) { - XSendEvent(m_display, m_window, False, 0, &m_postedEvents[i]); - } - XFlush(m_display); - m_postedEvents.clear(); -} diff --git a/lib/platform/CXWindowsEventQueueBuffer.h b/lib/platform/CXWindowsEventQueueBuffer.h deleted file mode 100644 index 5d9b6dd4..00000000 --- a/lib/platform/CXWindowsEventQueueBuffer.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CXWINDOWSEVENTQUEUEBUFFER_H -#define CXWINDOWSEVENTQUEUEBUFFER_H - -#include "IEventQueueBuffer.h" -#include "CMutex.h" -#include "stdvector.h" -#if X_DISPLAY_MISSING -# error X11 is required to build synergy -#else -# include -#endif - -//! Event queue buffer for X11 -class CXWindowsEventQueueBuffer : public IEventQueueBuffer { -public: - CXWindowsEventQueueBuffer(Display*, Window); - virtual ~CXWindowsEventQueueBuffer(); - - // IEventQueueBuffer overrides - virtual void waitForEvent(double timeout); - virtual Type getEvent(CEvent& event, UInt32& dataID); - virtual bool addEvent(UInt32 dataID); - virtual bool isEmpty() const; - virtual CEventQueueTimer* - newTimer(double duration, bool oneShot) const; - virtual void deleteTimer(CEventQueueTimer*) const; - -private: - void flush(); - -private: - typedef std::vector CEventList; - - CMutex m_mutex; - Display* m_display; - Window m_window; - Atom m_userEvent; - XEvent m_event; - CEventList m_postedEvents; - bool m_waiting; -}; - -#endif diff --git a/lib/platform/CXWindowsKeyState.cpp b/lib/platform/CXWindowsKeyState.cpp deleted file mode 100644 index 9f98ded4..00000000 --- a/lib/platform/CXWindowsKeyState.cpp +++ /dev/null @@ -1,826 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CXWindowsKeyState.h" -#include "CXWindowsUtil.h" -#include "CLog.h" -#include "CStringUtil.h" -#include "stdmap.h" -#if X_DISPLAY_MISSING -# error X11 is required to build synergy -#else -# include -# include -# define XK_MISCELLANY -# define XK_XKB_KEYS -# include -#if HAVE_XKB_EXTENSION -# include -#endif -#endif - -CXWindowsKeyState::CXWindowsKeyState(Display* display, bool useXKB) : - m_display(display) -{ - XGetKeyboardControl(m_display, &m_keyboardState); -#if HAVE_XKB_EXTENSION - if (useXKB) { - m_xkb = XkbGetMap(m_display, XkbKeyActionsMask | XkbKeyBehaviorsMask | - XkbAllClientInfoMask, XkbUseCoreKbd); - } - else { - m_xkb = NULL; - } -#endif - setActiveGroup(kGroupPollAndSet); -} - -CXWindowsKeyState::~CXWindowsKeyState() -{ -#if HAVE_XKB_EXTENSION - if (m_xkb != NULL) { - XkbFreeKeyboard(m_xkb, 0, True); - } -#endif -} - -void -CXWindowsKeyState::setActiveGroup(SInt32 group) -{ - if (group == kGroupPollAndSet) { - m_group = -1; - m_group = pollActiveGroup(); - } - else if (group == kGroupPoll) { - m_group = -1; - } - else { - assert(group >= 0); - m_group = group; - } -} - -void -CXWindowsKeyState::setAutoRepeat(const XKeyboardState& state) -{ - m_keyboardState = state; -} - -KeyModifierMask -CXWindowsKeyState::mapModifiersFromX(unsigned int state) const -{ - UInt32 offset = 8 * getGroupFromState(state); - KeyModifierMask mask = 0; - for (int i = 0; i < 8; ++i) { - if ((state & (1u << i)) != 0) { - mask |= m_modifierFromX[offset + i]; - } - } - return mask; -} - -bool -CXWindowsKeyState::mapModifiersToX(KeyModifierMask mask, - unsigned int& modifiers) const -{ - modifiers = 0; - - for (SInt32 i = 0; i < kKeyModifierNumBits; ++i) { - KeyModifierMask bit = (1u << i); - if ((mask & bit) != 0) { - KeyModifierToXMask::const_iterator j = m_modifierToX.find(bit); - if (j == m_modifierToX.end()) { - return false; - } - else { - modifiers |= j->second; - } - } - } - - return true; -} - -void -CXWindowsKeyState::mapKeyToKeycodes(KeyID key, CKeycodeList& keycodes) const -{ - keycodes.clear(); - std::pair range = - m_keyCodeFromKey.equal_range(key); - for (KeyToKeyCodeMap::const_iterator i = range.first; - i != range.second; ++i) { - keycodes.push_back(i->second); - } -} - -bool -CXWindowsKeyState::fakeCtrlAltDel() -{ - // pass keys through unchanged - return false; -} - -KeyModifierMask -CXWindowsKeyState::pollActiveModifiers() const -{ - Window root = DefaultRootWindow(m_display), window; - int xRoot, yRoot, xWindow, yWindow; - unsigned int state; - if (!XQueryPointer(m_display, root, &root, &window, - &xRoot, &yRoot, &xWindow, &yWindow, &state)) { - state = 0; - } - return mapModifiersFromX(state); -} - -SInt32 -CXWindowsKeyState::pollActiveGroup() const -{ - if (m_group != -1) { - assert(m_group >= 0); - return m_group; - } - -#if HAVE_XKB_EXTENSION - if (m_xkb != NULL) { - XkbStateRec state; - if (XkbGetState(m_display, XkbUseCoreKbd, &state)) { - return state.group; - } - } -#endif - return 0; -} - -void -CXWindowsKeyState::pollPressedKeys(KeyButtonSet& pressedKeys) const -{ - char keys[32]; - XQueryKeymap(m_display, keys); - for (UInt32 i = 0; i < 32; ++i) { - for (UInt32 j = 0; j < 8; ++j) { - if ((keys[i] & (1u << j)) != 0) { - pressedKeys.insert(8 * i + j); - } - } - } -} - -void -CXWindowsKeyState::getKeyMap(CKeyMap& keyMap) -{ - // get autorepeat info. we must use the global_auto_repeat told to - // us because it may have modified by synergy. - int oldGlobalAutoRepeat = m_keyboardState.global_auto_repeat; - XGetKeyboardControl(m_display, &m_keyboardState); - m_keyboardState.global_auto_repeat = oldGlobalAutoRepeat; - -#if HAVE_XKB_EXTENSION - if (m_xkb != NULL) { - XkbGetUpdatedMap(m_display, XkbKeyActionsMask | XkbKeyBehaviorsMask | - XkbAllClientInfoMask, m_xkb); - updateKeysymMapXKB(keyMap); - } - else -#endif - { - updateKeysymMap(keyMap); - } -} - -void -CXWindowsKeyState::fakeKey(const Keystroke& keystroke) -{ - switch (keystroke.m_type) { - case Keystroke::kButton: - LOG((CLOG_DEBUG1 " %03x (%08x) %s", keystroke.m_data.m_button.m_button, keystroke.m_data.m_button.m_client, keystroke.m_data.m_button.m_press ? "down" : "up")); - if (keystroke.m_data.m_button.m_repeat) { - int c = keystroke.m_data.m_button.m_button; - int i = (c >> 3); - int b = 1 << (c & 7); - if (m_keyboardState.global_auto_repeat == AutoRepeatModeOff || - (m_keyboardState.auto_repeats[i] & b) == 0) { - LOG((CLOG_DEBUG1 " discard autorepeat")); - break; - } - } - XTestFakeKeyEvent(m_display, keystroke.m_data.m_button.m_button, - keystroke.m_data.m_button.m_press ? True : False, - CurrentTime); - break; - - case Keystroke::kGroup: - if (keystroke.m_data.m_group.m_absolute) { - LOG((CLOG_DEBUG1 " group %d", keystroke.m_data.m_group.m_group)); -#if HAVE_XKB_EXTENSION - if (m_xkb != NULL) { - XkbLockGroup(m_display, XkbUseCoreKbd, - keystroke.m_data.m_group.m_group); - } - else -#endif - { - LOG((CLOG_DEBUG1 " ignored")); - } - } - else { - LOG((CLOG_DEBUG1 " group %+d", keystroke.m_data.m_group.m_group)); -#if HAVE_XKB_EXTENSION - if (m_xkb != NULL) { - XkbLockGroup(m_display, XkbUseCoreKbd, - getEffectiveGroup(pollActiveGroup(), - keystroke.m_data.m_group.m_group)); - } - else -#endif - { - LOG((CLOG_DEBUG1 " ignored")); - } - } - break; - } - XFlush(m_display); -} - -void -CXWindowsKeyState::updateKeysymMap(CKeyMap& keyMap) -{ - // there are up to 4 keysyms per keycode - static const int maxKeysyms = 4; - - LOG((CLOG_DEBUG1 "non-XKB mapping")); - - // prepare map from X modifier to KeyModifierMask. certain bits - // are predefined. - m_modifierFromX.clear(); - m_modifierFromX.resize(8); - m_modifierFromX[ShiftMapIndex] = KeyModifierShift; - m_modifierFromX[LockMapIndex] = KeyModifierCapsLock; - m_modifierFromX[ControlMapIndex] = KeyModifierControl; - m_modifierToX.clear(); - m_modifierToX[KeyModifierShift] = ShiftMask; - m_modifierToX[KeyModifierCapsLock] = LockMask; - m_modifierToX[KeyModifierControl] = ControlMask; - - // prepare map from KeyID to KeyCode - m_keyCodeFromKey.clear(); - - // get the number of keycodes - int minKeycode, maxKeycode; - XDisplayKeycodes(m_display, &minKeycode, &maxKeycode); - int numKeycodes = maxKeycode - minKeycode + 1; - - // get the keyboard mapping for all keys - int keysymsPerKeycode; - KeySym* allKeysyms = XGetKeyboardMapping(m_display, - minKeycode, numKeycodes, - &keysymsPerKeycode); - - // it's more convenient to always have maxKeysyms KeySyms per key - { - KeySym* tmpKeysyms = new KeySym[maxKeysyms * numKeycodes]; - for (int i = 0; i < numKeycodes; ++i) { - for (int j = 0; j < maxKeysyms; ++j) { - if (j < keysymsPerKeycode) { - tmpKeysyms[maxKeysyms * i + j] = - allKeysyms[keysymsPerKeycode * i + j]; - } - else { - tmpKeysyms[maxKeysyms * i + j] = NoSymbol; - } - } - } - XFree(allKeysyms); - allKeysyms = tmpKeysyms; - } - - // get the buttons assigned to modifiers. X11 does not predefine - // the meaning of any modifiers except shift, caps lock, and the - // control key. the meaning of a modifier bit (other than those) - // depends entirely on the KeySyms mapped to that bit. unfortunately - // you cannot map a bit back to the KeySym used to produce it. - // for example, let's say button 1 maps to Alt_L without shift and - // Meta_L with shift. now if mod1 is mapped to button 1 that could - // mean the user used Alt or Meta to turn on that modifier and there's - // no way to know which. it's also possible for one button to be - // mapped to multiple bits so both mod1 and mod2 could be generated - // by button 1. - // - // we're going to ignore any modifier for a button except the first. - // with the above example, that means we'll ignore the mod2 modifier - // bit unless it's also mapped to some other button. we're also - // going to ignore all KeySyms except the first modifier KeySym, - // which means button 1 above won't map to Meta, just Alt. - std::map modifierButtons; - XModifierKeymap* modifiers = XGetModifierMapping(m_display); - for (unsigned int i = 0; i < 8; ++i) { - const KeyCode* buttons = - modifiers->modifiermap + i * modifiers->max_keypermod; - for (int j = 0; j < modifiers->max_keypermod; ++j) { - modifierButtons.insert(std::make_pair(buttons[j], i)); - } - } - XFreeModifiermap(modifiers); - modifierButtons.erase(0); - - // Hack to deal with VMware. When a VMware client grabs input the - // player clears out the X modifier map for whatever reason. We're - // notified of the change and arrive here to discover that there - // are no modifiers at all. Since this prevents the modifiers from - // working in the VMware client we'll use the last known good set - // of modifiers when there are no modifiers. If there are modifiers - // we update the last known good set. - if (!modifierButtons.empty()) { - m_lastGoodNonXKBModifiers = modifierButtons; - } - else { - modifierButtons = m_lastGoodNonXKBModifiers; - } - - // add entries for each keycode - CKeyMap::KeyItem item; - for (int i = 0; i < numKeycodes; ++i) { - KeySym* keysyms = allKeysyms + maxKeysyms * i; - KeyCode keycode = static_cast(i + minKeycode); - item.m_button = static_cast(keycode); - item.m_client = 0; - - // determine modifier sensitivity - item.m_sensitive = 0; - - // if the keysyms in levels 2 or 3 exist and differ from levels - // 0 and 1 then the key is sensitive AltGr (Mode_switch) - if ((keysyms[2] != NoSymbol && keysyms[2] != keysyms[0]) || - (keysyms[3] != NoSymbol && keysyms[2] != keysyms[1])) { - item.m_sensitive |= KeyModifierAltGr; - } - - // check if the key is caps-lock sensitive. some systems only - // provide one keysym for keys sensitive to caps-lock. if we - // find that then fill in the missing keysym. - if (keysyms[0] != NoSymbol && keysyms[1] == NoSymbol && - keysyms[2] == NoSymbol && keysyms[3] == NoSymbol) { - KeySym lKeysym, uKeysym; - XConvertCase(keysyms[0], &lKeysym, &uKeysym); - if (lKeysym != uKeysym) { - keysyms[0] = lKeysym; - keysyms[1] = uKeysym; - item.m_sensitive |= KeyModifierCapsLock; - } - } - else if (keysyms[0] != NoSymbol && keysyms[1] != NoSymbol) { - KeySym lKeysym, uKeysym; - XConvertCase(keysyms[0], &lKeysym, &uKeysym); - if (lKeysym != uKeysym && - lKeysym == keysyms[0] && - uKeysym == keysyms[1]) { - item.m_sensitive |= KeyModifierCapsLock; - } - else if (keysyms[2] != NoSymbol && keysyms[3] != NoSymbol) { - XConvertCase(keysyms[2], &lKeysym, &uKeysym); - if (lKeysym != uKeysym && - lKeysym == keysyms[2] && - uKeysym == keysyms[3]) { - item.m_sensitive |= KeyModifierCapsLock; - } - } - } - - // key is sensitive to shift if keysyms in levels 0 and 1 or - // levels 2 and 3 don't match. it's also sensitive to shift - // if it's sensitive to caps-lock. - if ((item.m_sensitive & KeyModifierCapsLock) != 0) { - item.m_sensitive |= KeyModifierShift; - } - else if ((keysyms[0] != NoSymbol && keysyms[1] != NoSymbol && - keysyms[0] != keysyms[1]) || - (keysyms[2] != NoSymbol && keysyms[3] != NoSymbol && - keysyms[2] != keysyms[3])) { - item.m_sensitive |= KeyModifierShift; - } - - // key is sensitive to numlock if any keysym on it is - if (IsKeypadKey(keysyms[0]) || IsPrivateKeypadKey(keysyms[0]) || - IsKeypadKey(keysyms[1]) || IsPrivateKeypadKey(keysyms[1]) || - IsKeypadKey(keysyms[2]) || IsPrivateKeypadKey(keysyms[2]) || - IsKeypadKey(keysyms[3]) || IsPrivateKeypadKey(keysyms[3])) { - item.m_sensitive |= KeyModifierNumLock; - } - - // do each keysym (shift level) - for (int j = 0; j < maxKeysyms; ++j) { - item.m_id = CXWindowsUtil::mapKeySymToKeyID(keysyms[j]); - if (item.m_id == kKeyNone) { - if (j != 0 && modifierButtons.count(keycode) > 0) { - // pretend the modifier works in other shift levels - // because it probably does. - if (keysyms[1] == NoSymbol || j != 3) { - item.m_id = CXWindowsUtil::mapKeySymToKeyID(keysyms[0]); - } - else { - item.m_id = CXWindowsUtil::mapKeySymToKeyID(keysyms[1]); - } - } - if (item.m_id == kKeyNone) { - continue; - } - } - - // group is 0 for levels 0 and 1 and 1 for levels 2 and 3 - item.m_group = (j >= 2) ? 1 : 0; - - // compute required modifiers - item.m_required = 0; - if ((j & 1) != 0) { - item.m_required |= KeyModifierShift; - } - if ((j & 2) != 0) { - item.m_required |= KeyModifierAltGr; - } - - item.m_generates = 0; - item.m_lock = false; - if (modifierButtons.count(keycode) > 0) { - // get flags for modifier keys - CKeyMap::initModifierKey(item); - - // add mapping from X (unless we already have) - if (item.m_generates != 0) { - unsigned int bit = modifierButtons[keycode]; - if (m_modifierFromX[bit] == 0) { - m_modifierFromX[bit] = item.m_generates; - m_modifierToX[item.m_generates] = (1u << bit); - } - } - } - - // add key - keyMap.addKeyEntry(item); - m_keyCodeFromKey.insert(std::make_pair(item.m_id, keycode)); - - // add other ways to synthesize the key - if ((j & 1) != 0) { - // add capslock version of key is sensitive to capslock - KeySym lKeysym, uKeysym; - XConvertCase(keysyms[j], &lKeysym, &uKeysym); - if (lKeysym != uKeysym && - lKeysym == keysyms[j - 1] && - uKeysym == keysyms[j]) { - item.m_required &= ~KeyModifierShift; - item.m_required |= KeyModifierCapsLock; - keyMap.addKeyEntry(item); - item.m_required |= KeyModifierShift; - item.m_required &= ~KeyModifierCapsLock; - } - - // add numlock version of key if sensitive to numlock - if (IsKeypadKey(keysyms[j]) || IsPrivateKeypadKey(keysyms[j])) { - item.m_required &= ~KeyModifierShift; - item.m_required |= KeyModifierNumLock; - keyMap.addKeyEntry(item); - item.m_required |= KeyModifierShift; - item.m_required &= ~KeyModifierNumLock; - } - } - } - } - - delete[] allKeysyms; -} - -#if HAVE_XKB_EXTENSION -void -CXWindowsKeyState::updateKeysymMapXKB(CKeyMap& keyMap) -{ - static const XkbKTMapEntryRec defMapEntry = { - True, // active - 0, // level - { - 0, // mods.mask - 0, // mods.real_mods - 0 // mods.vmods - } - }; - - LOG((CLOG_DEBUG1 "XKB mapping")); - - // find the number of groups - int maxNumGroups = 0; - for (int i = m_xkb->min_key_code; i <= m_xkb->max_key_code; ++i) { - int numGroups = XkbKeyNumGroups(m_xkb, static_cast(i)); - if (numGroups > maxNumGroups) { - maxNumGroups = numGroups; - } - } - - // prepare map from X modifier to KeyModifierMask - std::vector modifierLevel(maxNumGroups * 8, 4); - m_modifierFromX.clear(); - m_modifierFromX.resize(maxNumGroups * 8); - m_modifierToX.clear(); - - // prepare map from KeyID to KeyCode - m_keyCodeFromKey.clear(); - - // Hack to deal with VMware. When a VMware client grabs input the - // player clears out the X modifier map for whatever reason. We're - // notified of the change and arrive here to discover that there - // are no modifiers at all. Since this prevents the modifiers from - // working in the VMware client we'll use the last known good set - // of modifiers when there are no modifiers. If there are modifiers - // we update the last known good set. - bool useLastGoodModifiers = !hasModifiersXKB(); - if (!useLastGoodModifiers) { - m_lastGoodXKBModifiers.clear(); - } - - // check every button. on this pass we save all modifiers as native - // X modifier masks. - CKeyMap::KeyItem item; - for (int i = m_xkb->min_key_code; i <= m_xkb->max_key_code; ++i) { - KeyCode keycode = static_cast(i); - item.m_button = static_cast(keycode); - item.m_client = 0; - - // skip keys with no groups (they generate no symbols) - if (XkbKeyNumGroups(m_xkb, keycode) == 0) { - continue; - } - - // note half-duplex keys - const XkbBehavior& b = m_xkb->server->behaviors[keycode]; - if ((b.type & XkbKB_OpMask) == XkbKB_Lock) { - keyMap.addHalfDuplexButton(item.m_button); - } - - // iterate over all groups - for (int group = 0; group < maxNumGroups; ++group) { - item.m_group = group; - int eGroup = getEffectiveGroup(keycode, group); - - // get key info - XkbKeyTypePtr type = XkbKeyKeyType(m_xkb, keycode, eGroup); - - // set modifiers the item is sensitive to - item.m_sensitive = type->mods.mask; - - // iterate over all shift levels for the button (including none) - for (int j = -1; j < type->map_count; ++j) { - const XkbKTMapEntryRec* mapEntry = - ((j == -1) ? &defMapEntry : type->map + j); - if (!mapEntry->active) { - continue; - } - int level = mapEntry->level; - - // set required modifiers for this item - item.m_required = mapEntry->mods.mask; - if ((item.m_required & LockMask) != 0 && - j != -1 && type->preserve != NULL && - (type->preserve[j].mask & LockMask) != 0) { - // sensitive caps lock and we preserve caps-lock. - // preserving caps-lock means we Xlib functions would - // yield the capitialized KeySym so we'll adjust the - // level accordingly. - if ((level ^ 1) < type->num_levels) { - level ^= 1; - } - } - - // get the keysym for this item - KeySym keysym = XkbKeySymEntry(m_xkb, keycode, level, eGroup); - - // check for group change actions, locking modifiers, and - // modifier masks. - item.m_lock = false; - bool isModifier = false; - UInt32 modifierMask = m_xkb->map->modmap[keycode]; - if (XkbKeyHasActions(m_xkb, keycode)) { - XkbAction* action = - XkbKeyActionEntry(m_xkb, keycode, level, eGroup); - if (action->type == XkbSA_SetMods || - action->type == XkbSA_LockMods) { - isModifier = true; - - // note toggles - item.m_lock = (action->type == XkbSA_LockMods); - - // maybe use action's mask - if ((action->mods.flags & XkbSA_UseModMapMods) == 0) { - modifierMask = action->mods.mask; - } - } - else if (action->type == XkbSA_SetGroup || - action->type == XkbSA_LatchGroup || - action->type == XkbSA_LockGroup) { - // ignore group change key - continue; - } - } - level = mapEntry->level; - - // VMware modifier hack - if (useLastGoodModifiers) { - XKBModifierMap::const_iterator k = - m_lastGoodXKBModifiers.find(eGroup * 256 + keycode); - if (k != m_lastGoodXKBModifiers.end()) { - // Use last known good modifier - isModifier = true; - level = k->second.m_level; - modifierMask = k->second.m_mask; - item.m_lock = k->second.m_lock; - } - } - else if (isModifier) { - // Save known good modifier - XKBModifierInfo& info = - m_lastGoodXKBModifiers[eGroup * 256 + keycode]; - info.m_level = level; - info.m_mask = modifierMask; - info.m_lock = item.m_lock; - } - - // record the modifier mask for this key. don't bother - // for keys that change the group. - item.m_generates = 0; - UInt32 modifierBit = - CXWindowsUtil::getModifierBitForKeySym(keysym); - if (isModifier && modifierBit != kKeyModifierBitNone) { - item.m_generates = (1u << modifierBit); - for (SInt32 j = 0; j < 8; ++j) { - // skip modifiers this key doesn't generate - if ((modifierMask & (1u << j)) == 0) { - continue; - } - - // skip keys that map to a modifier that we've - // already seen using fewer modifiers. that is - // if this key must combine with other modifiers - // and we know of a key that combines with fewer - // modifiers (or no modifiers) then prefer the - // other key. - if (level >= modifierLevel[8 * group + j]) { - continue; - } - modifierLevel[8 * group + j] = level; - - // save modifier - m_modifierFromX[8 * group + j] |= (1u << modifierBit); - m_modifierToX.insert(std::make_pair( - 1u << modifierBit, 1u << j)); - } - } - - // handle special cases of just one keysym for the keycode - if (type->num_levels == 1) { - // if there are upper- and lowercase versions of the - // keysym then add both. - KeySym lKeysym, uKeysym; - XConvertCase(keysym, &lKeysym, &uKeysym); - if (lKeysym != uKeysym) { - if (j != -1) { - continue; - } - - item.m_sensitive |= ShiftMask | LockMask; - - KeyID lKeyID = CXWindowsUtil::mapKeySymToKeyID(lKeysym); - KeyID uKeyID = CXWindowsUtil::mapKeySymToKeyID(uKeysym); - if (lKeyID == kKeyNone || uKeyID == kKeyNone) { - continue; - } - - item.m_id = lKeyID; - item.m_required = 0; - keyMap.addKeyEntry(item); - - item.m_id = uKeyID; - item.m_required = ShiftMask; - keyMap.addKeyEntry(item); - item.m_required = LockMask; - keyMap.addKeyEntry(item); - - if (group == 0) { - m_keyCodeFromKey.insert( - std::make_pair(lKeyID, keycode)); - m_keyCodeFromKey.insert( - std::make_pair(uKeyID, keycode)); - } - continue; - } - } - - // add entry - item.m_id = CXWindowsUtil::mapKeySymToKeyID(keysym); - keyMap.addKeyEntry(item); - if (group == 0) { - m_keyCodeFromKey.insert(std::make_pair(item.m_id, keycode)); - } - } - } - } - - // change all modifier masks to synergy masks from X masks - keyMap.foreachKey(&CXWindowsKeyState::remapKeyModifiers, this); - - // allow composition across groups - keyMap.allowGroupSwitchDuringCompose(); -} -#endif - -void -CXWindowsKeyState::remapKeyModifiers(KeyID id, SInt32 group, - CKeyMap::KeyItem& item, void* vself) -{ - CXWindowsKeyState* self = reinterpret_cast(vself); - item.m_required = - self->mapModifiersFromX(XkbBuildCoreState(item.m_required, group)); - item.m_sensitive = - self->mapModifiersFromX(XkbBuildCoreState(item.m_sensitive, group)); -} - -bool -CXWindowsKeyState::hasModifiersXKB() const -{ -#if HAVE_XKB_EXTENSION - // iterate over all keycodes - for (int i = m_xkb->min_key_code; i <= m_xkb->max_key_code; ++i) { - KeyCode keycode = static_cast(i); - if (XkbKeyHasActions(m_xkb, keycode)) { - // iterate over all groups - int numGroups = XkbKeyNumGroups(m_xkb, keycode); - for (int group = 0; group < numGroups; ++group) { - // iterate over all shift levels for the button (including none) - XkbKeyTypePtr type = XkbKeyKeyType(m_xkb, keycode, group); - for (int j = -1; j < type->map_count; ++j) { - if (j != -1 && !type->map[j].active) { - continue; - } - int level = ((j == -1) ? 0 : type->map[j].level); - XkbAction* action = - XkbKeyActionEntry(m_xkb, keycode, level, group); - if (action->type == XkbSA_SetMods || - action->type == XkbSA_LockMods) { - return true; - } - } - } - } - } -#endif - return false; -} - -int -CXWindowsKeyState::getEffectiveGroup(KeyCode keycode, int group) const -{ - (void)keycode; -#if HAVE_XKB_EXTENSION - // get effective group for key - int numGroups = XkbKeyNumGroups(m_xkb, keycode); - if (group >= numGroups) { - unsigned char groupInfo = XkbKeyGroupInfo(m_xkb, keycode); - switch (XkbOutOfRangeGroupAction(groupInfo)) { - case XkbClampIntoRange: - group = numGroups - 1; - break; - - case XkbRedirectIntoRange: - group = XkbOutOfRangeGroupNumber(groupInfo); - if (group >= numGroups) { - group = 0; - } - break; - - default: - // wrap - group %= numGroups; - break; - } - } -#endif - return group; -} - -UInt32 -CXWindowsKeyState::getGroupFromState(unsigned int state) const -{ -#if HAVE_XKB_EXTENSION - if (m_xkb != NULL) { - return XkbGroupForCoreState(state); - } -#endif - return 0; -} diff --git a/lib/platform/CXWindowsKeyState.h b/lib/platform/CXWindowsKeyState.h deleted file mode 100644 index 02ed4520..00000000 --- a/lib/platform/CXWindowsKeyState.h +++ /dev/null @@ -1,155 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CXWINDOWSKEYSTATE_H -#define CXWINDOWSKEYSTATE_H - -#include "CKeyState.h" -#include "stdmap.h" -#include "stdvector.h" -#if X_DISPLAY_MISSING -# error X11 is required to build synergy -#else -# include -# if HAVE_X11_EXTENSIONS_XTEST_H -# include -# else -# error The XTest extension is required to build synergy -# endif -# if HAVE_XKB_EXTENSION -# include -# endif -#endif - -//! X Windows key state -/*! -A key state for X Windows. -*/ -class CXWindowsKeyState : public CKeyState { -public: - typedef std::vector CKeycodeList; - enum { - kGroupPoll = -1, - kGroupPollAndSet = -2 - }; - - CXWindowsKeyState(Display*, bool useXKB); - ~CXWindowsKeyState(); - - //! @name modifiers - //@{ - - //! Set active group - /*! - Sets the active group to \p group. This is the group returned by - \c pollActiveGroup(). If \p group is \c kGroupPoll then - \c pollActiveGroup() will really poll, but that's a slow operation - on X11. If \p group is \c kGroupPollAndSet then this will poll the - active group now and use it for future calls to \c pollActiveGroup(). - */ - void setActiveGroup(SInt32 group); - - //! Set the auto-repeat state - /*! - Sets the auto-repeat state. - */ - void setAutoRepeat(const XKeyboardState&); - - //@} - //! @name accessors - //@{ - - //! Convert X modifier mask to synergy mask - /*! - Returns the synergy modifier mask corresponding to the X modifier - mask in \p state. - */ - KeyModifierMask mapModifiersFromX(unsigned int state) const; - - //! Convert synergy modifier mask to X mask - /*! - Converts the synergy modifier mask to the corresponding X modifier - mask. Returns \c true if successful and \c false if any modifier - could not be converted. - */ - bool mapModifiersToX(KeyModifierMask, unsigned int&) const; - - //! Convert synergy key to all corresponding X keycodes - /*! - Converts the synergy key \p key to all of the keycodes that map to - that key. - */ - void mapKeyToKeycodes(KeyID key, - CKeycodeList& keycodes) const; - - //@} - - // IKeyState overrides - virtual bool fakeCtrlAltDel(); - virtual KeyModifierMask - pollActiveModifiers() const; - virtual SInt32 pollActiveGroup() const; - virtual void pollPressedKeys(KeyButtonSet& pressedKeys) const; - -protected: - // CKeyState overrides - virtual void getKeyMap(CKeyMap& keyMap); - virtual void fakeKey(const Keystroke& keystroke); - -private: - void updateKeysymMap(CKeyMap&); - void updateKeysymMapXKB(CKeyMap&); - bool hasModifiersXKB() const; - int getEffectiveGroup(KeyCode, int group) const; - UInt32 getGroupFromState(unsigned int state) const; - - static void remapKeyModifiers(KeyID, SInt32, - CKeyMap::KeyItem&, void*); - -private: - struct XKBModifierInfo { - public: - unsigned char m_level; - UInt32 m_mask; - bool m_lock; - }; - - typedef std::vector KeyModifierMaskList; - typedef std::map KeyModifierToXMask; - typedef std::multimap KeyToKeyCodeMap; - typedef std::map NonXKBModifierMap; - typedef std::map XKBModifierMap; - - Display* m_display; -#if HAVE_XKB_EXTENSION - XkbDescPtr m_xkb; -#endif - SInt32 m_group; - XKBModifierMap m_lastGoodXKBModifiers; - NonXKBModifierMap m_lastGoodNonXKBModifiers; - - // X modifier (bit number) to synergy modifier (mask) mapping - KeyModifierMaskList m_modifierFromX; - - // synergy modifier (mask) to X modifier (mask) - KeyModifierToXMask m_modifierToX; - - // map KeyID to all keycodes that can synthesize that KeyID - KeyToKeyCodeMap m_keyCodeFromKey; - - // autorepeat state - XKeyboardState m_keyboardState; -}; - -#endif diff --git a/lib/platform/CXWindowsScreen.cpp b/lib/platform/CXWindowsScreen.cpp deleted file mode 100644 index 9c4ab134..00000000 --- a/lib/platform/CXWindowsScreen.cpp +++ /dev/null @@ -1,1901 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CXWindowsScreen.h" -#include "CXWindowsClipboard.h" -#include "CXWindowsEventQueueBuffer.h" -#include "CXWindowsKeyState.h" -#include "CXWindowsScreenSaver.h" -#include "CXWindowsUtil.h" -#include "CClipboard.h" -#include "CKeyMap.h" -#include "XScreen.h" -#include "CLog.h" -#include "CStopwatch.h" -#include "CStringUtil.h" -#include "IEventQueue.h" -#include "TMethodEventJob.h" -#include -#if X_DISPLAY_MISSING -# error X11 is required to build synergy -#else -# include -# include -# define XK_MISCELLANY -# define XK_XKB_KEYS -# include -# if HAVE_X11_EXTENSIONS_XTEST_H -# include -# else -# error The XTest extension is required to build synergy -# endif -# if HAVE_X11_EXTENSIONS_XINERAMA_H - // Xinerama.h may lack extern "C" for inclusion by C++ - extern "C" { -# include - } -# endif -# if HAVE_XKB_EXTENSION -# include -# endif -#endif -#include "CArch.h" - - -// -// CXWindowsScreen -// - -// NOTE -- the X display is shared among several objects but is owned -// by the CXWindowsScreen. Xlib is not reentrant so we must ensure -// that no two objects can simultaneously call Xlib with the display. -// this is easy since we only make X11 calls from the main thread. -// we must also ensure that these objects do not use the display in -// their destructors or, if they do, we can tell them not to. This -// is to handle unexpected disconnection of the X display, when any -// call on the display is invalid. In that situation we discard the -// display and the X11 event queue buffer, ignore any calls that try -// to use the display, and wait to be destroyed. - -CXWindowsScreen* CXWindowsScreen::s_screen = NULL; - -CXWindowsScreen::CXWindowsScreen(const char* displayName, bool isPrimary) : - m_isPrimary(isPrimary), - m_display(NULL), - m_root(None), - m_window(None), - m_isOnScreen(m_isPrimary), - m_x(0), m_y(0), - m_w(0), m_h(0), - m_xCenter(0), m_yCenter(0), - m_xCursor(0), m_yCursor(0), - m_keyState(NULL), - m_lastFocus(None), - m_lastFocusRevert(RevertToNone), - m_im(NULL), - m_ic(NULL), - m_lastKeycode(0), - m_sequenceNumber(0), - m_screensaver(NULL), - m_screensaverNotify(false), - m_xtestIsXineramaUnaware(true), - m_xkb(false) -{ - assert(s_screen == NULL); - - s_screen = this; - - // set the X I/O error handler so we catch the display disconnecting - XSetIOErrorHandler(&CXWindowsScreen::ioErrorHandler); - - try { - m_display = openDisplay(displayName); - m_root = DefaultRootWindow(m_display); - saveShape(); - m_window = openWindow(); - m_screensaver = new CXWindowsScreenSaver(m_display, - m_window, getEventTarget()); - m_keyState = new CXWindowsKeyState(m_display, m_xkb); - LOG((CLOG_DEBUG "screen shape: %d,%d %dx%d %s", m_x, m_y, m_w, m_h, m_xinerama ? "(xinerama)" : "")); - LOG((CLOG_DEBUG "window is 0x%08x", m_window)); - } - catch (...) { - if (m_display != NULL) { - XCloseDisplay(m_display); - } - throw; - } - - // primary/secondary screen only initialization - if (m_isPrimary) { - // start watching for events on other windows - selectEvents(m_root); - - // prepare to use input methods - openIM(); - } - else { - // become impervious to server grabs - XTestGrabControl(m_display, True); - } - - // initialize the clipboards - for (ClipboardID id = 0; id < kClipboardEnd; ++id) { - m_clipboard[id] = new CXWindowsClipboard(m_display, m_window, id); - } - - // install event handlers - EVENTQUEUE->adoptHandler(CEvent::kSystem, IEventQueue::getSystemTarget(), - new TMethodEventJob(this, - &CXWindowsScreen::handleSystemEvent)); - - // install the platform event queue - EVENTQUEUE->adoptBuffer(new CXWindowsEventQueueBuffer(m_display, m_window)); -} - -CXWindowsScreen::~CXWindowsScreen() -{ - assert(s_screen != NULL); - assert(m_display != NULL); - - EVENTQUEUE->adoptBuffer(NULL); - EVENTQUEUE->removeHandler(CEvent::kSystem, IEventQueue::getSystemTarget()); - for (ClipboardID id = 0; id < kClipboardEnd; ++id) { - delete m_clipboard[id]; - } - delete m_keyState; - delete m_screensaver; - m_keyState = NULL; - m_screensaver = NULL; - if (m_display != NULL) { - // FIXME -- is it safe to clean up the IC and IM without a display? - if (m_ic != NULL) { - XDestroyIC(m_ic); - } - if (m_im != NULL) { - XCloseIM(m_im); - } - XDestroyWindow(m_display, m_window); - XCloseDisplay(m_display); - } - XSetIOErrorHandler(NULL); - - s_screen = NULL; -} - -void -CXWindowsScreen::enable() -{ - if (!m_isPrimary) { - // get the keyboard control state - XKeyboardState keyControl; - XGetKeyboardControl(m_display, &keyControl); - m_autoRepeat = (keyControl.global_auto_repeat == AutoRepeatModeOn); - m_keyState->setAutoRepeat(keyControl); - - // move hider window under the cursor center - XMoveWindow(m_display, m_window, m_xCenter, m_yCenter); - - // raise and show the window - // FIXME -- take focus? - XMapRaised(m_display, m_window); - - // warp the mouse to the cursor center - fakeMouseMove(m_xCenter, m_yCenter); - } -} - -void -CXWindowsScreen::disable() -{ - // release input context focus - if (m_ic != NULL) { - XUnsetICFocus(m_ic); - } - - // unmap the hider/grab window. this also ungrabs the mouse and - // keyboard if they're grabbed. - XUnmapWindow(m_display, m_window); - - // restore auto-repeat state - if (!m_isPrimary && m_autoRepeat) { - XAutoRepeatOn(m_display); - } -} - -void -CXWindowsScreen::enter() -{ - // release input context focus - if (m_ic != NULL) { - XUnsetICFocus(m_ic); - } - - // set the input focus to what it had been when we took it - if (m_lastFocus != None) { - // the window may not exist anymore so ignore errors - CXWindowsUtil::CErrorLock lock(m_display); - XSetInputFocus(m_display, m_lastFocus, m_lastFocusRevert, CurrentTime); - } - - // unmap the hider/grab window. this also ungrabs the mouse and - // keyboard if they're grabbed. - XUnmapWindow(m_display, m_window); - -/* maybe call this if entering for the screensaver - // set keyboard focus to root window. the screensaver should then - // pick up key events for when the user enters a password to unlock. - XSetInputFocus(m_display, PointerRoot, PointerRoot, CurrentTime); -*/ - - if (!m_isPrimary) { - // get the keyboard control state - XKeyboardState keyControl; - XGetKeyboardControl(m_display, &keyControl); - m_autoRepeat = (keyControl.global_auto_repeat == AutoRepeatModeOn); - m_keyState->setAutoRepeat(keyControl); - - // turn off auto-repeat. we do this so fake key press events don't - // cause the local server to generate their own auto-repeats of - // those keys. - XAutoRepeatOff(m_display); - } - - // now on screen - m_isOnScreen = true; -} - -bool -CXWindowsScreen::leave() -{ - if (!m_isPrimary) { - // restore the previous keyboard auto-repeat state. if the user - // changed the auto-repeat configuration while on the client then - // that state is lost. that's because we can't get notified by - // the X server when the auto-repeat configuration is changed so - // we can't track the desired configuration. - if (m_autoRepeat) { - XAutoRepeatOn(m_display); - } - - // move hider window under the cursor center - XMoveWindow(m_display, m_window, m_xCenter, m_yCenter); - } - - // raise and show the window - XMapRaised(m_display, m_window); - - // grab the mouse and keyboard, if primary and possible - if (m_isPrimary && !grabMouseAndKeyboard()) { - XUnmapWindow(m_display, m_window); - return false; - } - - // save current focus - XGetInputFocus(m_display, &m_lastFocus, &m_lastFocusRevert); - - // take focus - XSetInputFocus(m_display, m_window, RevertToPointerRoot, CurrentTime); - - // now warp the mouse. we warp after showing the window so we're - // guaranteed to get the mouse leave event and to prevent the - // keyboard focus from changing under point-to-focus policies. - if (m_isPrimary) { - warpCursor(m_xCenter, m_yCenter); - } - else { - fakeMouseMove(m_xCenter, m_yCenter); - } - - // set input context focus to our window - if (m_ic != NULL) { - XmbResetIC(m_ic); - XSetICFocus(m_ic); - m_filtered.clear(); - } - - // now off screen - m_isOnScreen = false; - - return true; -} - -bool -CXWindowsScreen::setClipboard(ClipboardID id, const IClipboard* clipboard) -{ - // fail if we don't have the requested clipboard - if (m_clipboard[id] == NULL) { - return false; - } - - // get the actual time. ICCCM does not allow CurrentTime. - Time timestamp = CXWindowsUtil::getCurrentTime( - m_display, m_clipboard[id]->getWindow()); - - if (clipboard != NULL) { - // save clipboard data - return CClipboard::copy(m_clipboard[id], clipboard, timestamp); - } - else { - // assert clipboard ownership - if (!m_clipboard[id]->open(timestamp)) { - return false; - } - m_clipboard[id]->empty(); - m_clipboard[id]->close(); - return true; - } -} - -void -CXWindowsScreen::checkClipboards() -{ - // do nothing, we're always up to date -} - -void -CXWindowsScreen::openScreensaver(bool notify) -{ - m_screensaverNotify = notify; - if (!m_screensaverNotify) { - m_screensaver->disable(); - } -} - -void -CXWindowsScreen::closeScreensaver() -{ - if (!m_screensaverNotify) { - m_screensaver->enable(); - } -} - -void -CXWindowsScreen::screensaver(bool activate) -{ - if (activate) { - m_screensaver->activate(); - } - else { - m_screensaver->deactivate(); - } -} - -void -CXWindowsScreen::resetOptions() -{ - m_xtestIsXineramaUnaware = true; -} - -void -CXWindowsScreen::setOptions(const COptionsList& options) -{ - for (UInt32 i = 0, n = options.size(); i < n; i += 2) { - if (options[i] == kOptionXTestXineramaUnaware) { - m_xtestIsXineramaUnaware = (options[i + 1] != 0); - LOG((CLOG_DEBUG1 "XTest is Xinerama unaware %s", m_xtestIsXineramaUnaware ? "true" : "false")); - } - } -} - -void -CXWindowsScreen::setSequenceNumber(UInt32 seqNum) -{ - m_sequenceNumber = seqNum; -} - -bool -CXWindowsScreen::isPrimary() const -{ - return m_isPrimary; -} - -void* -CXWindowsScreen::getEventTarget() const -{ - return const_cast(this); -} - -bool -CXWindowsScreen::getClipboard(ClipboardID id, IClipboard* clipboard) const -{ - assert(clipboard != NULL); - - // fail if we don't have the requested clipboard - if (m_clipboard[id] == NULL) { - return false; - } - - // get the actual time. ICCCM does not allow CurrentTime. - Time timestamp = CXWindowsUtil::getCurrentTime( - m_display, m_clipboard[id]->getWindow()); - - // copy the clipboard - return CClipboard::copy(clipboard, m_clipboard[id], timestamp); -} - -void -CXWindowsScreen::getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h) const -{ - x = m_x; - y = m_y; - w = m_w; - h = m_h; -} - -void -CXWindowsScreen::getCursorPos(SInt32& x, SInt32& y) const -{ - Window root, window; - int mx, my, xWindow, yWindow; - unsigned int mask; - if (XQueryPointer(m_display, m_root, &root, &window, - &mx, &my, &xWindow, &yWindow, &mask)) { - x = mx; - y = my; - } - else { - x = m_xCenter; - y = m_yCenter; - } -} - -void -CXWindowsScreen::reconfigure(UInt32) -{ - // do nothing -} - -void -CXWindowsScreen::warpCursor(SInt32 x, SInt32 y) -{ - // warp mouse - warpCursorNoFlush(x, y); - - // remove all input events before and including warp - XEvent event; - while (XCheckMaskEvent(m_display, PointerMotionMask | - ButtonPressMask | ButtonReleaseMask | - KeyPressMask | KeyReleaseMask | - KeymapStateMask, - &event)) { - // do nothing - } - - // save position as last position - m_xCursor = x; - m_yCursor = y; -} - -UInt32 -CXWindowsScreen::registerHotKey(KeyID key, KeyModifierMask mask) -{ - // only allow certain modifiers - if ((mask & ~(KeyModifierShift | KeyModifierControl | - KeyModifierAlt | KeyModifierSuper)) != 0) { - LOG((CLOG_WARN "could not map hotkey id=%04x mask=%04x", key, mask)); - return 0; - } - - // fail if no keys - if (key == kKeyNone && mask == 0) { - return 0; - } - - // convert to X - unsigned int modifiers; - if (!m_keyState->mapModifiersToX(mask, modifiers)) { - // can't map all modifiers - LOG((CLOG_WARN "could not map hotkey id=%04x mask=%04x", key, mask)); - return 0; - } - CXWindowsKeyState::CKeycodeList keycodes; - m_keyState->mapKeyToKeycodes(key, keycodes); - if (key != kKeyNone && keycodes.empty()) { - // can't map key - LOG((CLOG_WARN "could not map hotkey id=%04x mask=%04x", key, mask)); - return 0; - } - - // choose hotkey id - UInt32 id; - if (!m_oldHotKeyIDs.empty()) { - id = m_oldHotKeyIDs.back(); - m_oldHotKeyIDs.pop_back(); - } - else { - id = m_hotKeys.size() + 1; - } - HotKeyList& hotKeys = m_hotKeys[id]; - - // all modifier hotkey must be treated specially. for each modifier - // we need to grab the modifier key in combination with all the other - // requested modifiers. - bool err = false; - { - CXWindowsUtil::CErrorLock lock(m_display, &err); - if (key == kKeyNone) { - static const KeyModifierMask s_hotKeyModifiers[] = { - KeyModifierShift, - KeyModifierControl, - KeyModifierAlt, - KeyModifierMeta, - KeyModifierSuper - }; - - XModifierKeymap* modKeymap = XGetModifierMapping(m_display); - for (size_t j = 0; j < sizeof(s_hotKeyModifiers) / - sizeof(s_hotKeyModifiers[0]) && !err; ++j) { - // skip modifier if not in mask - if ((mask & s_hotKeyModifiers[j]) == 0) { - continue; - } - - // skip with error if we can't map remaining modifiers - unsigned int modifiers2; - KeyModifierMask mask2 = (mask & ~s_hotKeyModifiers[j]); - if (!m_keyState->mapModifiersToX(mask2, modifiers2)) { - err = true; - continue; - } - - // compute modifier index for modifier. there should be - // exactly one X modifier missing - int index; - switch (modifiers ^ modifiers2) { - case ShiftMask: - index = ShiftMapIndex; - break; - - case LockMask: - index = LockMapIndex; - break; - - case ControlMask: - index = ControlMapIndex; - break; - - case Mod1Mask: - index = Mod1MapIndex; - break; - - case Mod2Mask: - index = Mod2MapIndex; - break; - - case Mod3Mask: - index = Mod3MapIndex; - break; - - case Mod4Mask: - index = Mod4MapIndex; - break; - - case Mod5Mask: - index = Mod5MapIndex; - break; - - default: - err = true; - continue; - } - - // grab each key for the modifier - const KeyCode* modifiermap = - modKeymap->modifiermap + index * modKeymap->max_keypermod; - for (int k = 0; k < modKeymap->max_keypermod && !err; ++k) { - KeyCode code = modifiermap[k]; - if (modifiermap[k] != 0) { - XGrabKey(m_display, code, modifiers2, m_root, - False, GrabModeAsync, GrabModeAsync); - if (!err) { - hotKeys.push_back(std::make_pair(code, modifiers2)); - m_hotKeyToIDMap[CHotKeyItem(code, modifiers2)] = id; - } - } - } - } - XFreeModifiermap(modKeymap); - } - - // a non-modifier key must be insensitive to CapsLock, NumLock and - // ScrollLock, so we have to grab the key with every combination of - // those. - else { - // collect available toggle modifiers - unsigned int modifier; - unsigned int toggleModifiers[3]; - size_t numToggleModifiers = 0; - if (m_keyState->mapModifiersToX(KeyModifierCapsLock, modifier)) { - toggleModifiers[numToggleModifiers++] = modifier; - } - if (m_keyState->mapModifiersToX(KeyModifierNumLock, modifier)) { - toggleModifiers[numToggleModifiers++] = modifier; - } - if (m_keyState->mapModifiersToX(KeyModifierScrollLock, modifier)) { - toggleModifiers[numToggleModifiers++] = modifier; - } - - - for (CXWindowsKeyState::CKeycodeList::iterator j = keycodes.begin(); - j != keycodes.end() && !err; ++j) { - for (size_t i = 0; i < (1u << numToggleModifiers); ++i) { - // add toggle modifiers for index i - unsigned int tmpModifiers = modifiers; - if ((i & 1) != 0) { - tmpModifiers |= toggleModifiers[0]; - } - if ((i & 2) != 0) { - tmpModifiers |= toggleModifiers[1]; - } - if ((i & 4) != 0) { - tmpModifiers |= toggleModifiers[2]; - } - - // add grab - XGrabKey(m_display, *j, tmpModifiers, m_root, - False, GrabModeAsync, GrabModeAsync); - if (!err) { - hotKeys.push_back(std::make_pair(*j, tmpModifiers)); - m_hotKeyToIDMap[CHotKeyItem(*j, tmpModifiers)] = id; - } - } - } - } - } - - if (err) { - // if any failed then unregister any we did get - for (HotKeyList::iterator j = hotKeys.begin(); - j != hotKeys.end(); ++j) { - XUngrabKey(m_display, j->first, j->second, m_root); - m_hotKeyToIDMap.erase(CHotKeyItem(j->first, j->second)); - } - - m_oldHotKeyIDs.push_back(id); - m_hotKeys.erase(id); - LOG((CLOG_WARN "failed to register hotkey %s (id=%04x mask=%04x)", CKeyMap::formatKey(key, mask).c_str(), key, mask)); - return 0; - } - - LOG((CLOG_DEBUG "registered hotkey %s (id=%04x mask=%04x) as id=%d", CKeyMap::formatKey(key, mask).c_str(), key, mask, id)); - return id; -} - -void -CXWindowsScreen::unregisterHotKey(UInt32 id) -{ - // look up hotkey - HotKeyMap::iterator i = m_hotKeys.find(id); - if (i == m_hotKeys.end()) { - return; - } - - // unregister with OS - bool err = false; - { - CXWindowsUtil::CErrorLock lock(m_display, &err); - HotKeyList& hotKeys = i->second; - for (HotKeyList::iterator j = hotKeys.begin(); - j != hotKeys.end(); ++j) { - XUngrabKey(m_display, j->first, j->second, m_root); - m_hotKeyToIDMap.erase(CHotKeyItem(j->first, j->second)); - } - } - if (err) { - LOG((CLOG_WARN "failed to unregister hotkey id=%d", id)); - } - else { - LOG((CLOG_DEBUG "unregistered hotkey id=%d", id)); - } - - // discard hot key from map and record old id for reuse - m_hotKeys.erase(i); - m_oldHotKeyIDs.push_back(id); -} - -void -CXWindowsScreen::fakeInputBegin() -{ - // FIXME -- not implemented -} - -void -CXWindowsScreen::fakeInputEnd() -{ - // FIXME -- not implemented -} - -SInt32 -CXWindowsScreen::getJumpZoneSize() const -{ - return 1; -} - -bool -CXWindowsScreen::isAnyMouseButtonDown() const -{ - // query the pointer to get the button state - Window root, window; - int xRoot, yRoot, xWindow, yWindow; - unsigned int state; - if (XQueryPointer(m_display, m_root, &root, &window, - &xRoot, &yRoot, &xWindow, &yWindow, &state)) { - return ((state & (Button1Mask | Button2Mask | Button3Mask | - Button4Mask | Button5Mask)) != 0); - } - - return false; -} - -void -CXWindowsScreen::getCursorCenter(SInt32& x, SInt32& y) const -{ - x = m_xCenter; - y = m_yCenter; -} - -void -CXWindowsScreen::fakeMouseButton(ButtonID button, bool press) const -{ - const unsigned int xButton = mapButtonToX(button); - if (xButton != 0) { - XTestFakeButtonEvent(m_display, xButton, - press ? True : False, CurrentTime); - XFlush(m_display); - } -} - -void -CXWindowsScreen::fakeMouseMove(SInt32 x, SInt32 y) const -{ - if (m_xinerama && m_xtestIsXineramaUnaware) { - XWarpPointer(m_display, None, m_root, 0, 0, 0, 0, x, y); - } - else { - XTestFakeMotionEvent(m_display, DefaultScreen(m_display), - x, y, CurrentTime); - } - XFlush(m_display); -} - -void -CXWindowsScreen::fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const -{ - // FIXME -- ignore xinerama for now - if (false && m_xinerama && m_xtestIsXineramaUnaware) { -// XWarpPointer(m_display, None, m_root, 0, 0, 0, 0, x, y); - } - else { - XTestFakeRelativeMotionEvent(m_display, dx, dy, CurrentTime); - } - XFlush(m_display); -} - -void -CXWindowsScreen::fakeMouseWheel(SInt32, SInt32 yDelta) const -{ - // XXX -- support x-axis scrolling - if (yDelta == 0) { - return; - } - - // choose button depending on rotation direction - const unsigned int xButton = mapButtonToX(static_cast( - (yDelta >= 0) ? -1 : -2)); - if (xButton == 0) { - // If we get here, then the XServer does not support the scroll - // wheel buttons, so send PageUp/PageDown keystrokes instead. - // Patch by Tom Chadwick. - KeyCode keycode = 0; - if (yDelta >= 0) { - keycode = XKeysymToKeycode(m_display, XK_Page_Up); - } - else { - keycode = XKeysymToKeycode(m_display, XK_Page_Down); - } - if (keycode != 0) { - XTestFakeKeyEvent(m_display, keycode, True, CurrentTime); - XTestFakeKeyEvent(m_display, keycode, False, CurrentTime); - } - return; - } - - // now use absolute value of delta - if (yDelta < 0) { - yDelta = -yDelta; - } - - // send as many clicks as necessary - for (; yDelta >= 120; yDelta -= 120) { - XTestFakeButtonEvent(m_display, xButton, True, CurrentTime); - XTestFakeButtonEvent(m_display, xButton, False, CurrentTime); - } - XFlush(m_display); -} - -Display* -CXWindowsScreen::openDisplay(const char* displayName) -{ - // get the DISPLAY - if (displayName == NULL) { - displayName = getenv("DISPLAY"); - if (displayName == NULL) { - displayName = ":0.0"; - } - } - - // open the display - LOG((CLOG_DEBUG "XOpenDisplay(\"%s\")", displayName)); - Display* display = XOpenDisplay(displayName); - if (display == NULL) { - throw XScreenUnavailable(60.0); - } - - // verify the availability of the XTest extension - if (!m_isPrimary) { - int majorOpcode, firstEvent, firstError; - if (!XQueryExtension(display, XTestExtensionName, - &majorOpcode, &firstEvent, &firstError)) { - LOG((CLOG_ERR "XTEST extension not available")); - XCloseDisplay(display); - throw XScreenOpenFailure(); - } - } - -#if HAVE_XKB_EXTENSION - { - m_xkb = false; - int major = XkbMajorVersion, minor = XkbMinorVersion; - if (XkbLibraryVersion(&major, &minor)) { - int opcode, firstError; - if (XkbQueryExtension(display, &opcode, &m_xkbEventBase, - &firstError, &major, &minor)) { - m_xkb = true; - XkbSelectEvents(display, XkbUseCoreKbd, - XkbMapNotifyMask, XkbMapNotifyMask); - XkbSelectEventDetails(display, XkbUseCoreKbd, - XkbStateNotifyMask, - XkbGroupStateMask, XkbGroupStateMask); - } - } - } -#endif - - return display; -} - -void -CXWindowsScreen::saveShape() -{ - // get shape of default screen - m_x = 0; - m_y = 0; - m_w = WidthOfScreen(DefaultScreenOfDisplay(m_display)); - m_h = HeightOfScreen(DefaultScreenOfDisplay(m_display)); - - // get center of default screen - m_xCenter = m_x + (m_w >> 1); - m_yCenter = m_y + (m_h >> 1); - - // check if xinerama is enabled and there is more than one screen. - // get center of first Xinerama screen. Xinerama appears to have - // a bug when XWarpPointer() is used in combination with - // XGrabPointer(). in that case, the warp is successful but the - // next pointer motion warps the pointer again, apparently to - // constrain it to some unknown region, possibly the region from - // 0,0 to Wm,Hm where Wm (Hm) is the minimum width (height) over - // all physical screens. this warp only seems to happen if the - // pointer wasn't in that region before the XWarpPointer(). the - // second (unexpected) warp causes synergy to think the pointer - // has been moved when it hasn't. to work around the problem, - // we warp the pointer to the center of the first physical - // screen instead of the logical screen. - m_xinerama = false; -#if HAVE_X11_EXTENSIONS_XINERAMA_H - int eventBase, errorBase; - if (XineramaQueryExtension(m_display, &eventBase, &errorBase) && - XineramaIsActive(m_display)) { - int numScreens; - XineramaScreenInfo* screens; - screens = XineramaQueryScreens(m_display, &numScreens); - if (screens != NULL) { - if (numScreens > 1) { - m_xinerama = true; - m_xCenter = screens[0].x_org + (screens[0].width >> 1); - m_yCenter = screens[0].y_org + (screens[0].height >> 1); - } - XFree(screens); - } - } -#endif -} - -Window -CXWindowsScreen::openWindow() const -{ - // default window attributes. we don't want the window manager - // messing with our window and we don't want the cursor to be - // visible inside the window. - XSetWindowAttributes attr; - attr.do_not_propagate_mask = 0; - attr.override_redirect = True; - attr.cursor = createBlankCursor(); - - // adjust attributes and get size and shape - SInt32 x, y, w, h; - if (m_isPrimary) { - // grab window attributes. this window is used to capture user - // input when the user is focused on another client. it covers - // the whole screen. - attr.event_mask = PointerMotionMask | - ButtonPressMask | ButtonReleaseMask | - KeyPressMask | KeyReleaseMask | - KeymapStateMask | PropertyChangeMask; - x = m_x; - y = m_y; - w = m_w; - h = m_h; - } - else { - // cursor hider window attributes. this window is used to hide the - // cursor when it's not on the screen. the window is hidden as soon - // as the cursor enters the screen or the display's real mouse is - // moved. we'll reposition the window as necessary so its - // position here doesn't matter. it only needs to be 1x1 because - // it only needs to contain the cursor's hotspot. - attr.event_mask = LeaveWindowMask; - x = 0; - y = 0; - w = 1; - h = 1; - } - - // create and return the window - Window window = XCreateWindow(m_display, m_root, x, y, w, h, 0, 0, - InputOnly, CopyFromParent, - CWDontPropagate | CWEventMask | - CWOverrideRedirect | CWCursor, - &attr); - if (window == None) { - throw XScreenOpenFailure(); - } - return window; -} - -void -CXWindowsScreen::openIM() -{ - // open the input methods - XIM im = XOpenIM(m_display, NULL, NULL, NULL); - if (im == NULL) { - LOG((CLOG_INFO "no support for IM")); - return; - } - - // find the appropriate style. synergy supports XIMPreeditNothing - // only at the moment. - XIMStyles* styles; - if (XGetIMValues(im, XNQueryInputStyle, &styles, NULL) != NULL || - styles == NULL) { - LOG((CLOG_WARN "cannot get IM styles")); - XCloseIM(im); - return; - } - XIMStyle style = 0; - for (unsigned short i = 0; i < styles->count_styles; ++i) { - style = styles->supported_styles[i]; - if ((style & XIMPreeditNothing) != 0) { - if ((style & (XIMStatusNothing | XIMStatusNone)) != 0) { - break; - } - } - } - XFree(styles); - if (style == 0) { - LOG((CLOG_INFO "no supported IM styles")); - XCloseIM(im); - return; - } - - // create an input context for the style and tell it about our window - XIC ic = XCreateIC(im, XNInputStyle, style, XNClientWindow, m_window, NULL); - if (ic == NULL) { - LOG((CLOG_WARN "cannot create IC")); - XCloseIM(im); - return; - } - - // find out the events we must select for and do so - unsigned long mask; - if (XGetICValues(ic, XNFilterEvents, &mask, NULL) != NULL) { - LOG((CLOG_WARN "cannot get IC filter events")); - XDestroyIC(ic); - XCloseIM(im); - return; - } - - // we have IM - m_im = im; - m_ic = ic; - m_lastKeycode = 0; - - // select events on our window that IM requires - XWindowAttributes attr; - XGetWindowAttributes(m_display, m_window, &attr); - XSelectInput(m_display, m_window, attr.your_event_mask | mask); -} - -void -CXWindowsScreen::sendEvent(CEvent::Type type, void* data) -{ - EVENTQUEUE->addEvent(CEvent(type, getEventTarget(), data)); -} - -void -CXWindowsScreen::sendClipboardEvent(CEvent::Type type, ClipboardID id) -{ - CClipboardInfo* info = (CClipboardInfo*)malloc(sizeof(CClipboardInfo)); - info->m_id = id; - info->m_sequenceNumber = m_sequenceNumber; - sendEvent(type, info); -} - -IKeyState* -CXWindowsScreen::getKeyState() const -{ - return m_keyState; -} - -Bool -CXWindowsScreen::findKeyEvent(Display*, XEvent* xevent, XPointer arg) -{ - CKeyEventFilter* filter = reinterpret_cast(arg); - return (xevent->type == filter->m_event && - xevent->xkey.window == filter->m_window && - xevent->xkey.time == filter->m_time && - xevent->xkey.keycode == filter->m_keycode) ? True : False; -} - -void -CXWindowsScreen::handleSystemEvent(const CEvent& event, void*) -{ - XEvent* xevent = reinterpret_cast(event.getData()); - assert(xevent != NULL); - - // update key state - bool isRepeat = false; - if (m_isPrimary) { - if (xevent->type == KeyRelease) { - // check if this is a key repeat by getting the next - // KeyPress event that has the same key and time as - // this release event, if any. first prepare the - // filter info. - CKeyEventFilter filter; - filter.m_event = KeyPress; - filter.m_window = xevent->xkey.window; - filter.m_time = xevent->xkey.time; - filter.m_keycode = xevent->xkey.keycode; - XEvent xevent2; - isRepeat = (XCheckIfEvent(m_display, &xevent2, - &CXWindowsScreen::findKeyEvent, - (XPointer)&filter) == True); - } - - if (xevent->type == KeyPress || xevent->type == KeyRelease) { - if (xevent->xkey.window == m_root) { - // this is a hot key - onHotKey(xevent->xkey, isRepeat); - return; - } - else if (!m_isOnScreen) { - // this might be a hot key - if (onHotKey(xevent->xkey, isRepeat)) { - return; - } - } - - bool down = (isRepeat || xevent->type == KeyPress); - KeyModifierMask state = - m_keyState->mapModifiersFromX(xevent->xkey.state); - m_keyState->onKey(xevent->xkey.keycode, down, state); - } - } - - // let input methods try to handle event first - if (m_ic != NULL) { - // XFilterEvent() may eat the event and generate a new KeyPress - // event with a keycode of 0 because there isn't an actual key - // associated with the keysym. but the KeyRelease may pass - // through XFilterEvent() and keep its keycode. this means - // there's a mismatch between KeyPress and KeyRelease keycodes. - // since we use the keycode on the client to detect when a key - // is released this won't do. so we remember the keycode on - // the most recent KeyPress (and clear it on a matching - // KeyRelease) so we have a keycode for a synthesized KeyPress. - if (xevent->type == KeyPress && xevent->xkey.keycode != 0) { - m_lastKeycode = xevent->xkey.keycode; - } - else if (xevent->type == KeyRelease && - xevent->xkey.keycode == m_lastKeycode) { - m_lastKeycode = 0; - } - - // now filter the event - if (XFilterEvent(xevent, None)) { - if (xevent->type == KeyPress) { - // add filtered presses to the filtered list - m_filtered.insert(m_lastKeycode); - } - return; - } - - // discard matching key releases for key presses that were - // filtered and remove them from our filtered list. - else if (xevent->type == KeyRelease && - m_filtered.count(xevent->xkey.keycode) > 0) { - m_filtered.erase(xevent->xkey.keycode); - return; - } - } - - // let screen saver have a go - if (m_screensaver->handleXEvent(xevent)) { - // screen saver handled it - return; - } - - // handle the event ourself - switch (xevent->type) { - case CreateNotify: - if (m_isPrimary) { - // select events on new window - selectEvents(xevent->xcreatewindow.window); - } - break; - - case MappingNotify: - refreshKeyboard(xevent); - break; - - case LeaveNotify: - if (!m_isPrimary) { - // mouse moved out of hider window somehow. hide the window. - XUnmapWindow(m_display, m_window); - } - break; - - case SelectionClear: - { - // we just lost the selection. that means someone else - // grabbed the selection so this screen is now the - // selection owner. report that to the receiver. - ClipboardID id = getClipboardID(xevent->xselectionclear.selection); - if (id != kClipboardEnd) { - LOG((CLOG_DEBUG "lost clipboard %d ownership at time %d", id, xevent->xselectionclear.time)); - m_clipboard[id]->lost(xevent->xselectionclear.time); - sendClipboardEvent(getClipboardGrabbedEvent(), id); - return; - } - } - break; - - case SelectionNotify: - // notification of selection transferred. we shouldn't - // get this here because we handle them in the selection - // retrieval methods. we'll just delete the property - // with the data (satisfying the usual ICCCM protocol). - if (xevent->xselection.property != None) { - XDeleteProperty(m_display, - xevent->xselection.requestor, - xevent->xselection.property); - } - break; - - case SelectionRequest: - { - // somebody is asking for clipboard data - ClipboardID id = getClipboardID( - xevent->xselectionrequest.selection); - if (id != kClipboardEnd) { - m_clipboard[id]->addRequest( - xevent->xselectionrequest.owner, - xevent->xselectionrequest.requestor, - xevent->xselectionrequest.target, - xevent->xselectionrequest.time, - xevent->xselectionrequest.property); - return; - } - } - break; - - case PropertyNotify: - // property delete may be part of a selection conversion - if (xevent->xproperty.state == PropertyDelete) { - processClipboardRequest(xevent->xproperty.window, - xevent->xproperty.time, - xevent->xproperty.atom); - } - break; - - case DestroyNotify: - // looks like one of the windows that requested a clipboard - // transfer has gone bye-bye. - destroyClipboardRequest(xevent->xdestroywindow.window); - break; - - case KeyPress: - if (m_isPrimary) { - onKeyPress(xevent->xkey); - } - return; - - case KeyRelease: - if (m_isPrimary) { - onKeyRelease(xevent->xkey, isRepeat); - } - return; - - case ButtonPress: - if (m_isPrimary) { - onMousePress(xevent->xbutton); - } - return; - - case ButtonRelease: - if (m_isPrimary) { - onMouseRelease(xevent->xbutton); - } - return; - - case MotionNotify: - if (m_isPrimary) { - onMouseMove(xevent->xmotion); - } - return; - - default: -#if HAVE_XKB_EXTENSION - if (m_xkb && xevent->type == m_xkbEventBase) { - XkbEvent* xkbEvent = reinterpret_cast(xevent); - switch (xkbEvent->any.xkb_type) { - case XkbMapNotify: - refreshKeyboard(xevent); - return; - - case XkbStateNotify: - LOG((CLOG_INFO "group change: %d", xkbEvent->state.group)); - m_keyState->setActiveGroup((SInt32)xkbEvent->state.group); - return; - } - } -#endif - break; - } -} - -void -CXWindowsScreen::onKeyPress(XKeyEvent& xkey) -{ - LOG((CLOG_DEBUG1 "event: KeyPress code=%d, state=0x%04x", xkey.keycode, xkey.state)); - const KeyModifierMask mask = m_keyState->mapModifiersFromX(xkey.state); - KeyID key = mapKeyFromX(&xkey); - if (key != kKeyNone) { - // check for ctrl+alt+del emulation - if ((key == kKeyPause || key == kKeyBreak) && - (mask & (KeyModifierControl | KeyModifierAlt)) == - (KeyModifierControl | KeyModifierAlt)) { - // pretend it's ctrl+alt+del - LOG((CLOG_DEBUG "emulate ctrl+alt+del")); - key = kKeyDelete; - } - - // get which button. see call to XFilterEvent() in onEvent() - // for more info. - bool isFake = false; - KeyButton keycode = static_cast(xkey.keycode); - if (keycode == 0) { - isFake = true; - keycode = static_cast(m_lastKeycode); - if (keycode == 0) { - // no keycode - return; - } - } - - // handle key - m_keyState->sendKeyEvent(getEventTarget(), - true, false, key, mask, 1, keycode); - - // do fake release if this is a fake press - if (isFake) { - m_keyState->sendKeyEvent(getEventTarget(), - false, false, key, mask, 1, keycode); - } - } -} - -void -CXWindowsScreen::onKeyRelease(XKeyEvent& xkey, bool isRepeat) -{ - const KeyModifierMask mask = m_keyState->mapModifiersFromX(xkey.state); - KeyID key = mapKeyFromX(&xkey); - if (key != kKeyNone) { - // check for ctrl+alt+del emulation - if ((key == kKeyPause || key == kKeyBreak) && - (mask & (KeyModifierControl | KeyModifierAlt)) == - (KeyModifierControl | KeyModifierAlt)) { - // pretend it's ctrl+alt+del and ignore autorepeat - LOG((CLOG_DEBUG "emulate ctrl+alt+del")); - key = kKeyDelete; - isRepeat = false; - } - - KeyButton keycode = static_cast(xkey.keycode); - if (!isRepeat) { - // no press event follows so it's a plain release - LOG((CLOG_DEBUG1 "event: KeyRelease code=%d, state=0x%04x", keycode, xkey.state)); - m_keyState->sendKeyEvent(getEventTarget(), - false, false, key, mask, 1, keycode); - } - else { - // found a press event following so it's a repeat. - // we could attempt to count the already queued - // repeats but we'll just send a repeat of 1. - // note that we discard the press event. - LOG((CLOG_DEBUG1 "event: repeat code=%d, state=0x%04x", keycode, xkey.state)); - m_keyState->sendKeyEvent(getEventTarget(), - false, true, key, mask, 1, keycode); - } - } -} - -bool -CXWindowsScreen::onHotKey(XKeyEvent& xkey, bool isRepeat) -{ - // find the hot key id - HotKeyToIDMap::const_iterator i = - m_hotKeyToIDMap.find(CHotKeyItem(xkey.keycode, xkey.state)); - if (i == m_hotKeyToIDMap.end()) { - return false; - } - - // find what kind of event - CEvent::Type type; - if (xkey.type == KeyPress) { - type = getHotKeyDownEvent(); - } - else if (xkey.type == KeyRelease) { - type = getHotKeyUpEvent(); - } - else { - return false; - } - - // generate event (ignore key repeats) - if (!isRepeat) { - EVENTQUEUE->addEvent(CEvent(type, getEventTarget(), - CHotKeyInfo::alloc(i->second))); - } - return true; -} - -void -CXWindowsScreen::onMousePress(const XButtonEvent& xbutton) -{ - LOG((CLOG_DEBUG1 "event: ButtonPress button=%d", xbutton.button)); - ButtonID button = mapButtonFromX(&xbutton); - KeyModifierMask mask = m_keyState->mapModifiersFromX(xbutton.state); - if (button != kButtonNone) { - sendEvent(getButtonDownEvent(), CButtonInfo::alloc(button, mask)); - } -} - -void -CXWindowsScreen::onMouseRelease(const XButtonEvent& xbutton) -{ - LOG((CLOG_DEBUG1 "event: ButtonRelease button=%d", xbutton.button)); - ButtonID button = mapButtonFromX(&xbutton); - KeyModifierMask mask = m_keyState->mapModifiersFromX(xbutton.state); - if (button != kButtonNone) { - sendEvent(getButtonUpEvent(), CButtonInfo::alloc(button, mask)); - } - else if (xbutton.button == 4) { - // wheel forward (away from user) - sendEvent(getWheelEvent(), CWheelInfo::alloc(0, 120)); - } - else if (xbutton.button == 5) { - // wheel backward (toward user) - sendEvent(getWheelEvent(), CWheelInfo::alloc(0, -120)); - } - // XXX -- support x-axis scrolling -} - -void -CXWindowsScreen::onMouseMove(const XMotionEvent& xmotion) -{ - LOG((CLOG_DEBUG2 "event: MotionNotify %d,%d", xmotion.x_root, xmotion.y_root)); - - // compute motion delta (relative to the last known - // mouse position) - SInt32 x = xmotion.x_root - m_xCursor; - SInt32 y = xmotion.y_root - m_yCursor; - - // save position to compute delta of next motion - m_xCursor = xmotion.x_root; - m_yCursor = xmotion.y_root; - - if (xmotion.send_event) { - // we warped the mouse. discard events until we - // find the matching sent event. see - // warpCursorNoFlush() for where the events are - // sent. we discard the matching sent event and - // can be sure we've skipped the warp event. - XEvent xevent; - do { - XMaskEvent(m_display, PointerMotionMask, &xevent); - } while (!xevent.xany.send_event); - } - else if (m_isOnScreen) { - // motion on primary screen - sendEvent(getMotionOnPrimaryEvent(), - CMotionInfo::alloc(m_xCursor, m_yCursor)); - } - else { - // motion on secondary screen. warp mouse back to - // center. - // - // my lombard (powerbook g3) running linux and - // using the adbmouse driver has two problems: - // first, the driver only sends motions of +/-2 - // pixels and, second, it seems to discard some - // physical input after a warp. the former isn't a - // big deal (we're just limited to every other - // pixel) but the latter is a PITA. to work around - // it we only warp when the mouse has moved more - // than s_size pixels from the center. - static const SInt32 s_size = 32; - if (xmotion.x_root - m_xCenter < -s_size || - xmotion.x_root - m_xCenter > s_size || - xmotion.y_root - m_yCenter < -s_size || - xmotion.y_root - m_yCenter > s_size) { - warpCursorNoFlush(m_xCenter, m_yCenter); - } - - // send event if mouse moved. do this after warping - // back to center in case the motion takes us onto - // the primary screen. if we sent the event first - // in that case then the warp would happen after - // warping to the primary screen's enter position, - // effectively overriding it. - if (x != 0 || y != 0) { - sendEvent(getMotionOnSecondaryEvent(), CMotionInfo::alloc(x, y)); - } - } -} - -Cursor -CXWindowsScreen::createBlankCursor() const -{ - // this seems just a bit more complicated than really necessary - - // get the closet cursor size to 1x1 - unsigned int w, h; - XQueryBestCursor(m_display, m_root, 1, 1, &w, &h); - - // make bitmap data for cursor of closet size. since the cursor - // is blank we can use the same bitmap for shape and mask: all - // zeros. - const int size = ((w + 7) >> 3) * h; - char* data = new char[size]; - memset(data, 0, size); - - // make bitmap - Pixmap bitmap = XCreateBitmapFromData(m_display, m_root, data, w, h); - - // need an arbitrary color for the cursor - XColor color; - color.pixel = 0; - color.red = color.green = color.blue = 0; - color.flags = DoRed | DoGreen | DoBlue; - - // make cursor from bitmap - Cursor cursor = XCreatePixmapCursor(m_display, bitmap, bitmap, - &color, &color, 0, 0); - - // don't need bitmap or the data anymore - delete[] data; - XFreePixmap(m_display, bitmap); - - return cursor; -} - -ClipboardID -CXWindowsScreen::getClipboardID(Atom selection) const -{ - for (ClipboardID id = 0; id < kClipboardEnd; ++id) { - if (m_clipboard[id] != NULL && - m_clipboard[id]->getSelection() == selection) { - return id; - } - } - return kClipboardEnd; -} - -void -CXWindowsScreen::processClipboardRequest(Window requestor, - Time time, Atom property) -{ - // check every clipboard until one returns success - for (ClipboardID id = 0; id < kClipboardEnd; ++id) { - if (m_clipboard[id] != NULL && - m_clipboard[id]->processRequest(requestor, time, property)) { - break; - } - } -} - -void -CXWindowsScreen::destroyClipboardRequest(Window requestor) -{ - // check every clipboard until one returns success - for (ClipboardID id = 0; id < kClipboardEnd; ++id) { - if (m_clipboard[id] != NULL && - m_clipboard[id]->destroyRequest(requestor)) { - break; - } - } -} - -void -CXWindowsScreen::onError() -{ - // prevent further access to the X display - EVENTQUEUE->adoptBuffer(NULL); - m_screensaver->destroy(); - m_screensaver = NULL; - m_display = NULL; - - // notify of failure - sendEvent(getErrorEvent(), NULL); - - // FIXME -- should ensure that we ignore operations that involve - // m_display from now on. however, Xlib will simply exit the - // application in response to the X I/O error so there's no - // point in trying to really handle the error. if we did want - // to handle the error, it'd probably be easiest to delegate to - // one of two objects. one object would take the implementation - // from this class. the other object would be stub methods that - // don't use X11. on error, we'd switch to the latter. -} - -int -CXWindowsScreen::ioErrorHandler(Display*) -{ - // the display has disconnected, probably because X is shutting - // down. X forces us to exit at this point which is annoying. - // we'll pretend as if we won't exit so we try to make sure we - // don't access the display anymore. - LOG((CLOG_CRIT "X display has unexpectedly disconnected")); - s_screen->onError(); - return 0; -} - -void -CXWindowsScreen::selectEvents(Window w) const -{ - // ignore errors while we adjust event masks. windows could be - // destroyed at any time after the XQueryTree() in doSelectEvents() - // so we must ignore BadWindow errors. - CXWindowsUtil::CErrorLock lock(m_display); - - // adjust event masks - doSelectEvents(w); -} - -void -CXWindowsScreen::doSelectEvents(Window w) const -{ - // we want to track the mouse everywhere on the display. to achieve - // that we select PointerMotionMask on every window. we also select - // SubstructureNotifyMask in order to get CreateNotify events so we - // select events on new windows too. - // - // note that this can break certain clients due a design flaw of X. - // X will deliver a PointerMotion event to the deepest window in the - // hierarchy that contains the pointer and has PointerMotionMask - // selected by *any* client. if another client doesn't select - // motion events in a subwindow so the parent window will get them - // then by selecting for motion events on the subwindow we break - // that client because the parent will no longer get the events. - - // FIXME -- should provide some workaround for event selection - // design flaw. perhaps only select for motion events on windows - // that already do or are top-level windows or don't propagate - // pointer events. or maybe an option to simply poll the mouse. - - // we don't want to adjust our grab window - if (w == m_window) { - return; - } - - // select events of interest. do this before querying the tree so - // we'll get notifications of children created after the XQueryTree() - // so we won't miss them. - XSelectInput(m_display, w, PointerMotionMask | SubstructureNotifyMask); - - // recurse on child windows - Window rw, pw, *cw; - unsigned int nc; - if (XQueryTree(m_display, w, &rw, &pw, &cw, &nc)) { - for (unsigned int i = 0; i < nc; ++i) { - doSelectEvents(cw[i]); - } - XFree(cw); - } -} - -KeyID -CXWindowsScreen::mapKeyFromX(XKeyEvent* event) const -{ - // convert to a keysym - KeySym keysym; - if (event->type == KeyPress && m_ic != NULL) { - // do multibyte lookup. can only call XmbLookupString with a - // key press event and a valid XIC so we checked those above. - char scratch[32]; - int n = sizeof(scratch) / sizeof(scratch[0]); - char* buffer = scratch; - int status; - n = XmbLookupString(m_ic, event, buffer, n, &keysym, &status); - if (status == XBufferOverflow) { - // not enough space. grow buffer and try again. - buffer = new char[n]; - n = XmbLookupString(m_ic, event, buffer, n, &keysym, &status); - delete[] buffer; - } - - // see what we got. since we don't care about the string - // we'll just look for a keysym. - switch (status) { - default: - case XLookupNone: - case XLookupChars: - keysym = 0; - break; - - case XLookupKeySym: - case XLookupBoth: - break; - } - } - else { - // plain old lookup - char dummy[1]; - XLookupString(event, dummy, 0, &keysym, NULL); - } - - // convert key - return CXWindowsUtil::mapKeySymToKeyID(keysym); -} - -ButtonID -CXWindowsScreen::mapButtonFromX(const XButtonEvent* event) const -{ - unsigned int button = event->button; - - // first three buttons map to 1, 2, 3 (kButtonLeft, Middle, Right) - if (button >= 1 && button <= 3) { - return static_cast(button); - } - - // buttons 4 and 5 are ignored here. they're used for the wheel. - // buttons 6, 7, etc and up map to 4, 5, etc. - else if (button >= 6) { - return static_cast(button - 2); - } - - // unknown button - else { - return kButtonNone; - } -} - -unsigned int -CXWindowsScreen::mapButtonToX(ButtonID id) const -{ - // map button -1 to button 4 (+wheel) - if (id == static_cast(-1)) { - id = 4; - } - - // map button -2 to button 5 (-wheel) - else if (id == static_cast(-2)) { - id = 5; - } - - // map buttons 4, 5, etc. to 6, 7, etc. to make room for buttons - // 4 and 5 used to simulate the mouse wheel. - else if (id >= 4) { - id += 2; - } - - // check button is in legal range - if (id < 1 || id > m_buttons.size()) { - // out of range - return 0; - } - - // map button - return static_cast(id); -} - -void -CXWindowsScreen::warpCursorNoFlush(SInt32 x, SInt32 y) -{ - assert(m_window != None); - - // send an event that we can recognize before the mouse warp - XEvent eventBefore; - eventBefore.type = MotionNotify; - eventBefore.xmotion.display = m_display; - eventBefore.xmotion.window = m_window; - eventBefore.xmotion.root = m_root; - eventBefore.xmotion.subwindow = m_window; - eventBefore.xmotion.time = CurrentTime; - eventBefore.xmotion.x = x; - eventBefore.xmotion.y = y; - eventBefore.xmotion.x_root = x; - eventBefore.xmotion.y_root = y; - eventBefore.xmotion.state = 0; - eventBefore.xmotion.is_hint = NotifyNormal; - eventBefore.xmotion.same_screen = True; - XEvent eventAfter = eventBefore; - XSendEvent(m_display, m_window, False, 0, &eventBefore); - - // warp mouse - XWarpPointer(m_display, None, m_root, 0, 0, 0, 0, x, y); - - // send an event that we can recognize after the mouse warp - XSendEvent(m_display, m_window, False, 0, &eventAfter); - XSync(m_display, False); - - LOG((CLOG_DEBUG2 "warped to %d,%d", x, y)); -} - -void -CXWindowsScreen::updateButtons() -{ - // query the button mapping - UInt32 numButtons = XGetPointerMapping(m_display, NULL, 0); - unsigned char* tmpButtons = new unsigned char[numButtons]; - XGetPointerMapping(m_display, tmpButtons, numButtons); - - // find the largest logical button id - unsigned char maxButton = 0; - for (UInt32 i = 0; i < numButtons; ++i) { - if (tmpButtons[i] > maxButton) { - maxButton = tmpButtons[i]; - } - } - - // allocate button array - m_buttons.resize(maxButton); - - // fill in button array values. m_buttons[i] is the physical - // button number for logical button i+1. - for (UInt32 i = 0; i < numButtons; ++i) { - m_buttons[i] = 0; - } - for (UInt32 i = 0; i < numButtons; ++i) { - m_buttons[tmpButtons[i] - 1] = i + 1; - } - - // clean up - delete[] tmpButtons; -} - -bool -CXWindowsScreen::grabMouseAndKeyboard() -{ - // grab the mouse and keyboard. keep trying until we get them. - // if we can't grab one after grabbing the other then ungrab - // and wait before retrying. give up after s_timeout seconds. - static const double s_timeout = 1.0; - int result; - CStopwatch timer; - do { - // keyboard first - do { - result = XGrabKeyboard(m_display, m_window, True, - GrabModeAsync, GrabModeAsync, CurrentTime); - assert(result != GrabNotViewable); - if (result != GrabSuccess) { - LOG((CLOG_DEBUG2 "waiting to grab keyboard")); - ARCH->sleep(0.05); - if (timer.getTime() >= s_timeout) { - LOG((CLOG_DEBUG2 "grab keyboard timed out")); - return false; - } - } - } while (result != GrabSuccess); - LOG((CLOG_DEBUG2 "grabbed keyboard")); - - // now the mouse - result = XGrabPointer(m_display, m_window, True, 0, - GrabModeAsync, GrabModeAsync, - m_window, None, CurrentTime); - assert(result != GrabNotViewable); - if (result != GrabSuccess) { - // back off to avoid grab deadlock - XUngrabKeyboard(m_display, CurrentTime); - LOG((CLOG_DEBUG2 "ungrabbed keyboard, waiting to grab pointer")); - ARCH->sleep(0.05); - if (timer.getTime() >= s_timeout) { - LOG((CLOG_DEBUG2 "grab pointer timed out")); - return false; - } - } - } while (result != GrabSuccess); - - LOG((CLOG_DEBUG1 "grabbed pointer and keyboard")); - return true; -} - -void -CXWindowsScreen::refreshKeyboard(XEvent* event) -{ - if (XPending(m_display) > 0) { - XEvent tmpEvent; - XPeekEvent(m_display, &tmpEvent); - if (tmpEvent.type == MappingNotify) { - // discard this event since another follows. - // we tend to get a bunch of these in a row. - return; - } - } - - // keyboard mapping changed -#if HAVE_XKB_EXTENSION - if (m_xkb && event->type == m_xkbEventBase) { - XkbRefreshKeyboardMapping((XkbMapNotifyEvent*)event); - } - else -#else - { - XRefreshKeyboardMapping(&event->xmapping); - } -#endif - m_keyState->updateKeyMap(); - m_keyState->updateKeyState(); -} - - -// -// CXWindowsScreen::CHotKeyItem -// - -CXWindowsScreen::CHotKeyItem::CHotKeyItem(int keycode, unsigned int mask) : - m_keycode(keycode), - m_mask(mask) -{ - // do nothing -} - -bool -CXWindowsScreen::CHotKeyItem::operator<(const CHotKeyItem& x) const -{ - return (m_keycode < x.m_keycode || - (m_keycode == x.m_keycode && m_mask < x.m_mask)); -} diff --git a/lib/platform/CXWindowsScreen.h b/lib/platform/CXWindowsScreen.h deleted file mode 100644 index 99c45576..00000000 --- a/lib/platform/CXWindowsScreen.h +++ /dev/null @@ -1,229 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CXWINDOWSSCREEN_H -#define CXWINDOWSSCREEN_H - -#include "CPlatformScreen.h" -#include "stdset.h" -#include "stdvector.h" -#if X_DISPLAY_MISSING -# error X11 is required to build synergy -#else -# include -#endif - -class CXWindowsClipboard; -class CXWindowsKeyState; -class CXWindowsScreenSaver; - -//! Implementation of IPlatformScreen for X11 -class CXWindowsScreen : public CPlatformScreen { -public: - CXWindowsScreen(const char* displayName, bool isPrimary); - virtual ~CXWindowsScreen(); - - //! @name manipulators - //@{ - - //@} - - // IScreen overrides - virtual void* getEventTarget() const; - virtual bool getClipboard(ClipboardID id, IClipboard*) const; - virtual void getShape(SInt32& x, SInt32& y, - SInt32& width, SInt32& height) const; - virtual void getCursorPos(SInt32& x, SInt32& y) const; - - // IPrimaryScreen overrides - virtual void reconfigure(UInt32 activeSides); - virtual void warpCursor(SInt32 x, SInt32 y); - virtual UInt32 registerHotKey(KeyID key, KeyModifierMask mask); - virtual void unregisterHotKey(UInt32 id); - virtual void fakeInputBegin(); - virtual void fakeInputEnd(); - virtual SInt32 getJumpZoneSize() const; - virtual bool isAnyMouseButtonDown() const; - virtual void getCursorCenter(SInt32& x, SInt32& y) const; - - // ISecondaryScreen overrides - virtual void fakeMouseButton(ButtonID id, bool press) const; - virtual void fakeMouseMove(SInt32 x, SInt32 y) const; - virtual void fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const; - virtual void fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const; - - // IPlatformScreen overrides - virtual void enable(); - virtual void disable(); - virtual void enter(); - virtual bool leave(); - virtual bool setClipboard(ClipboardID, const IClipboard*); - virtual void checkClipboards(); - virtual void openScreensaver(bool notify); - virtual void closeScreensaver(); - virtual void screensaver(bool activate); - virtual void resetOptions(); - virtual void setOptions(const COptionsList& options); - virtual void setSequenceNumber(UInt32); - virtual bool isPrimary() const; - -protected: - // IPlatformScreen overrides - virtual void handleSystemEvent(const CEvent&, void*); - virtual void updateButtons(); - virtual IKeyState* getKeyState() const; - -private: - // event sending - void sendEvent(CEvent::Type, void* = NULL); - void sendClipboardEvent(CEvent::Type, ClipboardID); - - // create the transparent cursor - Cursor createBlankCursor() const; - - // determine the clipboard from the X selection. returns - // kClipboardEnd if no such clipboard. - ClipboardID getClipboardID(Atom selection) const; - - // continue processing a selection request - void processClipboardRequest(Window window, - Time time, Atom property); - - // terminate a selection request - void destroyClipboardRequest(Window window); - - // X I/O error handler - void onError(); - static int ioErrorHandler(Display*); - -private: - class CKeyEventFilter { - public: - int m_event; - Window m_window; - Time m_time; - KeyCode m_keycode; - }; - - Display* openDisplay(const char* displayName); - void saveShape(); - Window openWindow() const; - void openIM(); - - bool grabMouseAndKeyboard(); - void onKeyPress(XKeyEvent&); - void onKeyRelease(XKeyEvent&, bool isRepeat); - bool onHotKey(XKeyEvent&, bool isRepeat); - void onMousePress(const XButtonEvent&); - void onMouseRelease(const XButtonEvent&); - void onMouseMove(const XMotionEvent&); - - void selectEvents(Window) const; - void doSelectEvents(Window) const; - - KeyID mapKeyFromX(XKeyEvent*) const; - ButtonID mapButtonFromX(const XButtonEvent*) const; - unsigned int mapButtonToX(ButtonID id) const; - - void warpCursorNoFlush(SInt32 x, SInt32 y); - - void refreshKeyboard(XEvent*); - - static Bool findKeyEvent(Display*, XEvent* xevent, XPointer arg); - -private: - struct CHotKeyItem { - public: - CHotKeyItem(int, unsigned int); - - bool operator<(const CHotKeyItem&) const; - - private: - int m_keycode; - unsigned int m_mask; - }; - typedef std::set CFilteredKeycodes; - typedef std::vector > HotKeyList; - typedef std::map HotKeyMap; - typedef std::vector HotKeyIDList; - typedef std::map HotKeyToIDMap; - - // true if screen is being used as a primary screen, false otherwise - bool m_isPrimary; - - Display* m_display; - Window m_root; - Window m_window; - - // true if mouse has entered the screen - bool m_isOnScreen; - - // screen shape stuff - SInt32 m_x, m_y; - SInt32 m_w, m_h; - SInt32 m_xCenter, m_yCenter; - - // last mouse position - SInt32 m_xCursor, m_yCursor; - - // keyboard stuff - CXWindowsKeyState* m_keyState; - - // hot key stuff - HotKeyMap m_hotKeys; - HotKeyIDList m_oldHotKeyIDs; - HotKeyToIDMap m_hotKeyToIDMap; - - // input focus stuff - Window m_lastFocus; - int m_lastFocusRevert; - - // input method stuff - XIM m_im; - XIC m_ic; - KeyCode m_lastKeycode; - CFilteredKeycodes m_filtered; - - // clipboards - CXWindowsClipboard* m_clipboard[kClipboardEnd]; - UInt32 m_sequenceNumber; - - // screen saver stuff - CXWindowsScreenSaver* m_screensaver; - bool m_screensaverNotify; - - // logical to physical button mapping. m_buttons[i] gives the - // physical button for logical button i+1. - std::vector m_buttons; - - // true if global auto-repeat was enabled before we turned it off - bool m_autoRepeat; - - // stuff to workaround xtest being xinerama unaware. attempting - // to fake a mouse motion under xinerama may behave strangely, - // especially if screen 0 is not at 0,0 or if faking a motion on - // a screen other than screen 0. - bool m_xtestIsXineramaUnaware; - bool m_xinerama; - - // XKB extension stuff - bool m_xkb; - int m_xkbEventBase; - - // pointer to (singleton) screen. this is only needed by - // ioErrorHandler(). - static CXWindowsScreen* s_screen; -}; - -#endif diff --git a/lib/platform/CXWindowsScreenSaver.cpp b/lib/platform/CXWindowsScreenSaver.cpp deleted file mode 100644 index 65af34e1..00000000 --- a/lib/platform/CXWindowsScreenSaver.cpp +++ /dev/null @@ -1,598 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CXWindowsScreenSaver.h" -#include "CXWindowsUtil.h" -#include "IPlatformScreen.h" -#include "CLog.h" -#include "CEvent.h" -#include "IEventQueue.h" -#include "TMethodEventJob.h" -#include -#if HAVE_X11_EXTENSIONS_XTEST_H -# include -#else -# error The XTest extension is required to build synergy -#endif -#if HAVE_X11_EXTENSIONS_DPMS_H -extern "C" { -# include -# include -# if !HAVE_DPMS_PROTOTYPES -# undef DPMSModeOn -# undef DPMSModeStandby -# undef DPMSModeSuspend -# undef DPMSModeOff -# define DPMSModeOn 0 -# define DPMSModeStandby 1 -# define DPMSModeSuspend 2 -# define DPMSModeOff 3 -extern Bool DPMSQueryExtension(Display *, int *, int *); -extern Bool DPMSCapable(Display *); -extern Status DPMSEnable(Display *); -extern Status DPMSDisable(Display *); -extern Status DPMSForceLevel(Display *, CARD16); -extern Status DPMSInfo(Display *, CARD16 *, BOOL *); -# endif -} -#endif - -// -// CXWindowsScreenSaver -// - -CXWindowsScreenSaver::CXWindowsScreenSaver( - Display* display, Window window, void* eventTarget) : - m_display(display), - m_xscreensaverSink(window), - m_eventTarget(eventTarget), - m_xscreensaver(None), - m_xscreensaverActive(false), - m_dpms(false), - m_disabled(false), - m_suppressDisable(false), - m_disableTimer(NULL), - m_disablePos(0) -{ - // get atoms - m_atomScreenSaver = XInternAtom(m_display, - "SCREENSAVER", False); - m_atomScreenSaverVersion = XInternAtom(m_display, - "_SCREENSAVER_VERSION", False); - m_atomScreenSaverActivate = XInternAtom(m_display, - "ACTIVATE", False); - m_atomScreenSaverDeactivate = XInternAtom(m_display, - "DEACTIVATE", False); - - // check for DPMS extension. this is an alternative screen saver - // that powers down the display. -#if HAVE_X11_EXTENSIONS_DPMS_H - int eventBase, errorBase; - if (DPMSQueryExtension(m_display, &eventBase, &errorBase)) { - if (DPMSCapable(m_display)) { - // we have DPMS - m_dpms = true; - } - } -#endif - - // watch top-level windows for changes - bool error = false; - { - CXWindowsUtil::CErrorLock lock(m_display, &error); - Window root = DefaultRootWindow(m_display); - XWindowAttributes attr; - XGetWindowAttributes(m_display, root, &attr); - m_rootEventMask = attr.your_event_mask; - XSelectInput(m_display, root, m_rootEventMask | SubstructureNotifyMask); - } - if (error) { - LOG((CLOG_DEBUG "didn't set root event mask")); - m_rootEventMask = 0; - } - - // get the built-in settings - XGetScreenSaver(m_display, &m_timeout, &m_interval, - &m_preferBlanking, &m_allowExposures); - - // get the DPMS settings - m_dpmsEnabled = isDPMSEnabled(); - - // get the xscreensaver window, if any - if (!findXScreenSaver()) { - setXScreenSaver(None); - } - - // install disable timer event handler - EVENTQUEUE->adoptHandler(CEvent::kTimer, this, - new TMethodEventJob(this, - &CXWindowsScreenSaver::handleDisableTimer)); -} - -CXWindowsScreenSaver::~CXWindowsScreenSaver() -{ - // done with disable job - if (m_disableTimer != NULL) { - EVENTQUEUE->deleteTimer(m_disableTimer); - } - EVENTQUEUE->removeHandler(CEvent::kTimer, this); - - if (m_display != NULL) { - enableDPMS(m_dpmsEnabled); - XSetScreenSaver(m_display, m_timeout, m_interval, - m_preferBlanking, m_allowExposures); - clearWatchForXScreenSaver(); - CXWindowsUtil::CErrorLock lock(m_display); - XSelectInput(m_display, DefaultRootWindow(m_display), m_rootEventMask); - } -} - -void -CXWindowsScreenSaver::destroy() -{ - m_display = NULL; - delete this; -} - -bool -CXWindowsScreenSaver::handleXEvent(const XEvent* xevent) -{ - switch (xevent->type) { - case CreateNotify: - if (m_xscreensaver == None) { - if (isXScreenSaver(xevent->xcreatewindow.window)) { - // found the xscreensaver - setXScreenSaver(xevent->xcreatewindow.window); - } - else { - // another window to watch. to detect the xscreensaver - // window we look for a property but that property may - // not yet exist by the time we get this event so we - // have to watch the window for property changes. - // this would be so much easier if xscreensaver did the - // smart thing and stored its window in a property on - // the root window. - addWatchXScreenSaver(xevent->xcreatewindow.window); - } - } - break; - - case DestroyNotify: - if (xevent->xdestroywindow.window == m_xscreensaver) { - // xscreensaver is gone - LOG((CLOG_DEBUG "xscreensaver died")); - setXScreenSaver(None); - return true; - } - break; - - case PropertyNotify: - if (xevent->xproperty.state == PropertyNewValue) { - if (isXScreenSaver(xevent->xproperty.window)) { - // found the xscreensaver - setXScreenSaver(xevent->xcreatewindow.window); - } - } - break; - - case MapNotify: - if (xevent->xmap.window == m_xscreensaver) { - // xscreensaver has activated - setXScreenSaverActive(true); - return true; - } - break; - - case UnmapNotify: - if (xevent->xunmap.window == m_xscreensaver) { - // xscreensaver has deactivated - setXScreenSaverActive(false); - return true; - } - break; - } - - return false; -} - -void -CXWindowsScreenSaver::enable() -{ - // for xscreensaver - m_disabled = false; - updateDisableTimer(); - - // for built-in X screen saver - XSetScreenSaver(m_display, m_timeout, m_interval, - m_preferBlanking, m_allowExposures); - - // for DPMS - enableDPMS(m_dpmsEnabled); -} - -void -CXWindowsScreenSaver::disable() -{ - // for xscreensaver - m_disabled = true; - updateDisableTimer(); - - // use built-in X screen saver - XGetScreenSaver(m_display, &m_timeout, &m_interval, - &m_preferBlanking, &m_allowExposures); - XSetScreenSaver(m_display, 0, m_interval, - m_preferBlanking, m_allowExposures); - - // for DPMS - m_dpmsEnabled = isDPMSEnabled(); - enableDPMS(false); - - // FIXME -- now deactivate? -} - -void -CXWindowsScreenSaver::activate() -{ - // remove disable job timer - m_suppressDisable = true; - updateDisableTimer(); - - // enable DPMS if it was enabled - enableDPMS(m_dpmsEnabled); - - // try xscreensaver - findXScreenSaver(); - if (m_xscreensaver != None) { - sendXScreenSaverCommand(m_atomScreenSaverActivate); - return; - } - - // try built-in X screen saver - if (m_timeout != 0) { - XForceScreenSaver(m_display, ScreenSaverActive); - } - - // try DPMS - activateDPMS(true); -} - -void -CXWindowsScreenSaver::deactivate() -{ - // reinstall disable job timer - m_suppressDisable = false; - updateDisableTimer(); - - // try DPMS - activateDPMS(false); - - // disable DPMS if screen saver is disabled - if (m_disabled) { - enableDPMS(false); - } - - // try xscreensaver - findXScreenSaver(); - if (m_xscreensaver != None) { - sendXScreenSaverCommand(m_atomScreenSaverDeactivate); - return; - } - - // use built-in X screen saver - XForceScreenSaver(m_display, ScreenSaverReset); -} - -bool -CXWindowsScreenSaver::isActive() const -{ - // check xscreensaver - if (m_xscreensaver != None) { - return m_xscreensaverActive; - } - - // check DPMS - if (isDPMSActivated()) { - return true; - } - - // can't check built-in X screen saver activity - return false; -} - -bool -CXWindowsScreenSaver::findXScreenSaver() -{ - // do nothing if we've already got the xscreensaver window - if (m_xscreensaver == None) { - // find top-level window xscreensaver window - Window root = DefaultRootWindow(m_display); - Window rw, pw, *cw; - unsigned int nc; - if (XQueryTree(m_display, root, &rw, &pw, &cw, &nc)) { - for (unsigned int i = 0; i < nc; ++i) { - if (isXScreenSaver(cw[i])) { - setXScreenSaver(cw[i]); - break; - } - } - XFree(cw); - } - } - - return (m_xscreensaver != None); -} - -void -CXWindowsScreenSaver::setXScreenSaver(Window window) -{ - LOG((CLOG_DEBUG "xscreensaver window: 0x%08x", window)); - - // save window - m_xscreensaver = window; - - if (m_xscreensaver != None) { - // clear old watch list - clearWatchForXScreenSaver(); - - // see if xscreensaver is active - bool error = false; - XWindowAttributes attr; - { - CXWindowsUtil::CErrorLock lock(m_display, &error); - XGetWindowAttributes(m_display, m_xscreensaver, &attr); - } - setXScreenSaverActive(!error && attr.map_state != IsUnmapped); - - // save current DPMS state; xscreensaver may have changed it. - m_dpmsEnabled = isDPMSEnabled(); - } - else { - // screen saver can't be active if it doesn't exist - setXScreenSaverActive(false); - - // start watching for xscreensaver - watchForXScreenSaver(); - } -} - -bool -CXWindowsScreenSaver::isXScreenSaver(Window w) const -{ - // check for m_atomScreenSaverVersion string property - Atom type; - return (CXWindowsUtil::getWindowProperty(m_display, w, - m_atomScreenSaverVersion, - NULL, &type, NULL, False) && - type == XA_STRING); -} - -void -CXWindowsScreenSaver::setXScreenSaverActive(bool activated) -{ - if (m_xscreensaverActive != activated) { - LOG((CLOG_DEBUG "xscreensaver %s on window 0x%08x", activated ? "activated" : "deactivated", m_xscreensaver)); - m_xscreensaverActive = activated; - - // if screen saver was activated forcefully (i.e. against - // our will) then just accept it. don't try to keep it - // from activating since that'll just pop up the password - // dialog if locking is enabled. - m_suppressDisable = activated; - updateDisableTimer(); - - if (activated) { - EVENTQUEUE->addEvent(CEvent( - IPlatformScreen::getScreensaverActivatedEvent(), - m_eventTarget)); - } - else { - EVENTQUEUE->addEvent(CEvent( - IPlatformScreen::getScreensaverDeactivatedEvent(), - m_eventTarget)); - } - } -} - -void -CXWindowsScreenSaver::sendXScreenSaverCommand(Atom cmd, long arg1, long arg2) -{ - XEvent event; - event.xclient.type = ClientMessage; - event.xclient.display = m_display; - event.xclient.window = m_xscreensaverSink; - event.xclient.message_type = m_atomScreenSaver; - event.xclient.format = 32; - event.xclient.data.l[0] = static_cast(cmd); - event.xclient.data.l[1] = arg1; - event.xclient.data.l[2] = arg2; - event.xclient.data.l[3] = 0; - event.xclient.data.l[4] = 0; - - LOG((CLOG_DEBUG "send xscreensaver command: %d %d %d", (long)cmd, arg1, arg2)); - bool error = false; - { - CXWindowsUtil::CErrorLock lock(m_display, &error); - XSendEvent(m_display, m_xscreensaver, False, 0, &event); - } - if (error) { - findXScreenSaver(); - } -} - -void -CXWindowsScreenSaver::watchForXScreenSaver() -{ - // clear old watch list - clearWatchForXScreenSaver(); - - // add every child of the root to the list of windows to watch - Window root = DefaultRootWindow(m_display); - Window rw, pw, *cw; - unsigned int nc; - if (XQueryTree(m_display, root, &rw, &pw, &cw, &nc)) { - for (unsigned int i = 0; i < nc; ++i) { - addWatchXScreenSaver(cw[i]); - } - XFree(cw); - } - - // now check for xscreensaver window in case it set the property - // before we could request property change events. - if (findXScreenSaver()) { - // found it so clear out our watch list - clearWatchForXScreenSaver(); - } -} - -void -CXWindowsScreenSaver::clearWatchForXScreenSaver() -{ - // stop watching all windows - CXWindowsUtil::CErrorLock lock(m_display); - for (CWatchList::iterator index = m_watchWindows.begin(); - index != m_watchWindows.end(); ++index) { - XSelectInput(m_display, index->first, index->second); - } - m_watchWindows.clear(); -} - -void -CXWindowsScreenSaver::addWatchXScreenSaver(Window window) -{ - // get window attributes - bool error = false; - XWindowAttributes attr; - { - CXWindowsUtil::CErrorLock lock(m_display, &error); - XGetWindowAttributes(m_display, window, &attr); - } - - // if successful and window uses override_redirect (like xscreensaver - // does) then watch it for property changes. - if (!error && attr.override_redirect == True) { - error = false; - { - CXWindowsUtil::CErrorLock lock(m_display, &error); - XSelectInput(m_display, window, - attr.your_event_mask | PropertyChangeMask); - } - if (!error) { - // if successful then add the window to our list - m_watchWindows.insert(std::make_pair(window, attr.your_event_mask)); - } - } -} - -void -CXWindowsScreenSaver::updateDisableTimer() -{ - if (m_disabled && !m_suppressDisable && m_disableTimer == NULL) { - // 5 seconds should be plenty often to suppress the screen saver - m_disableTimer = EVENTQUEUE->newTimer(5.0, this); - } - else if ((!m_disabled || m_suppressDisable) && m_disableTimer != NULL) { - EVENTQUEUE->deleteTimer(m_disableTimer); - m_disableTimer = NULL; - } -} - -void -CXWindowsScreenSaver::handleDisableTimer(const CEvent&, void*) -{ - // send fake mouse motion directly to xscreensaver - if (m_xscreensaver != None) { - XEvent event; - event.xmotion.type = MotionNotify; - event.xmotion.display = m_display; - event.xmotion.window = m_xscreensaver; - event.xmotion.root = DefaultRootWindow(m_display); - event.xmotion.subwindow = None; - event.xmotion.time = CurrentTime; - event.xmotion.x = m_disablePos; - event.xmotion.y = 0; - event.xmotion.x_root = m_disablePos; - event.xmotion.y_root = 0; - event.xmotion.state = 0; - event.xmotion.is_hint = NotifyNormal; - event.xmotion.same_screen = True; - - CXWindowsUtil::CErrorLock lock(m_display); - XSendEvent(m_display, m_xscreensaver, False, 0, &event); - - m_disablePos = 20 - m_disablePos; - } -} - -void -CXWindowsScreenSaver::activateDPMS(bool activate) -{ -#if HAVE_X11_EXTENSIONS_DPMS_H - if (m_dpms) { - // DPMSForceLevel will generate a BadMatch if DPMS is disabled - CXWindowsUtil::CErrorLock lock(m_display); - DPMSForceLevel(m_display, activate ? DPMSModeStandby : DPMSModeOn); - } -#endif -} - -void -CXWindowsScreenSaver::enableDPMS(bool enable) -{ -#if HAVE_X11_EXTENSIONS_DPMS_H - if (m_dpms) { - if (enable) { - DPMSEnable(m_display); - } - else { - DPMSDisable(m_display); - } - } -#endif -} - -bool -CXWindowsScreenSaver::isDPMSEnabled() const -{ -#if HAVE_X11_EXTENSIONS_DPMS_H - if (m_dpms) { - CARD16 level; - BOOL state; - DPMSInfo(m_display, &level, &state); - return (state != False); - } - else { - return false; - } -#else - return false; -#endif -} - -bool -CXWindowsScreenSaver::isDPMSActivated() const -{ -#if HAVE_X11_EXTENSIONS_DPMS_H - if (m_dpms) { - CARD16 level; - BOOL state; - DPMSInfo(m_display, &level, &state); - return (level != DPMSModeOn); - } - else { - return false; - } -#else - return false; -#endif -} diff --git a/lib/platform/CXWindowsScreenSaver.h b/lib/platform/CXWindowsScreenSaver.h deleted file mode 100644 index 991b20e1..00000000 --- a/lib/platform/CXWindowsScreenSaver.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CXWINDOWSSCREENSAVER_H -#define CXWINDOWSSCREENSAVER_H - -#include "IScreenSaver.h" -#include "stdmap.h" -#if X_DISPLAY_MISSING -# error X11 is required to build synergy -#else -# include -#endif - -class CEvent; -class CEventQueueTimer; - -//! X11 screen saver implementation -class CXWindowsScreenSaver : public IScreenSaver { -public: - CXWindowsScreenSaver(Display*, Window, void* eventTarget); - virtual ~CXWindowsScreenSaver(); - - //! @name manipulators - //@{ - - //! Event filtering - /*! - Should be called for each system event before event translation and - dispatch. Returns true to skip translation and dispatch. - */ - bool handleXEvent(const XEvent*); - - //! Destroy without the display - /*! - Tells this object to delete itself without using the X11 display. - It may leak some resources as a result. - */ - void destroy(); - - //@} - - // IScreenSaver overrides - virtual void enable(); - virtual void disable(); - virtual void activate(); - virtual void deactivate(); - virtual bool isActive() const; - -private: - // find and set the running xscreensaver's window. returns true iff - // found. - bool findXScreenSaver(); - - // set the xscreensaver's window, updating the activation state flag - void setXScreenSaver(Window); - - // returns true if the window appears to be the xscreensaver window - bool isXScreenSaver(Window) const; - - // set xscreensaver's activation state flag. sends notification - // if the state has changed. - void setXScreenSaverActive(bool activated); - - // send a command to xscreensaver - void sendXScreenSaverCommand(Atom, long = 0, long = 0); - - // watch all windows that could potentially be the xscreensaver for - // the events that will confirm it. - void watchForXScreenSaver(); - - // stop watching all watched windows - void clearWatchForXScreenSaver(); - - // add window to the watch list - void addWatchXScreenSaver(Window window); - - // install/uninstall the job used to suppress the screensaver - void updateDisableTimer(); - - // called periodically to prevent the screen saver from starting - void handleDisableTimer(const CEvent&, void*); - - // force DPMS to activate or deactivate - void activateDPMS(bool activate); - - // enable/disable DPMS screen saver - void enableDPMS(bool); - - // check if DPMS is enabled - bool isDPMSEnabled() const; - - // check if DPMS is activate - bool isDPMSActivated() const; - -private: - typedef std::map CWatchList; - - // the X display - Display* m_display; - - // window to receive xscreensaver repsonses - Window m_xscreensaverSink; - - // the target for the events we generate - void* m_eventTarget; - - // xscreensaver's window - Window m_xscreensaver; - - // xscreensaver activation state - bool m_xscreensaverActive; - - // old event mask on root window - long m_rootEventMask; - - // potential xscreensaver windows being watched - CWatchList m_watchWindows; - - // atoms used to communicate with xscreensaver's window - Atom m_atomScreenSaver; - Atom m_atomScreenSaverVersion; - Atom m_atomScreenSaverActivate; - Atom m_atomScreenSaverDeactivate; - - // built-in screen saver settings - int m_timeout; - int m_interval; - int m_preferBlanking; - int m_allowExposures; - - // DPMS screen saver settings - bool m_dpms; - bool m_dpmsEnabled; - - // true iff the client wants the screen saver suppressed - bool m_disabled; - - // true iff we're ignoring m_disabled. this is true, for example, - // when the client has called activate() and so presumably wants - // to activate the screen saver even if disabled. - bool m_suppressDisable; - - // the disable timer (NULL if not installed) - CEventQueueTimer* m_disableTimer; - - // fake mouse motion position for suppressing the screen saver. - // xscreensaver since 2.21 requires the mouse to move more than 10 - // pixels to be considered significant. - SInt32 m_disablePos; -}; - -#endif diff --git a/lib/platform/CXWindowsUtil.cpp b/lib/platform/CXWindowsUtil.cpp deleted file mode 100644 index a33fc4ee..00000000 --- a/lib/platform/CXWindowsUtil.cpp +++ /dev/null @@ -1,1766 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CXWindowsUtil.h" -#include "KeyTypes.h" -#include "CThread.h" -#include "CLog.h" -#include "CStringUtil.h" -#include -#define XK_APL -#define XK_ARABIC -#define XK_ARMENIAN -#define XK_CAUCASUS -#define XK_CURRENCY -#define XK_CYRILLIC -#define XK_GEORGIAN -#define XK_GREEK -#define XK_HEBREW -#define XK_KATAKANA -#define XK_KOREAN -#define XK_LATIN1 -#define XK_LATIN2 -#define XK_LATIN3 -#define XK_LATIN4 -#define XK_LATIN8 -#define XK_LATIN9 -#define XK_MISCELLANY -#define XK_PUBLISHING -#define XK_SPECIAL -#define XK_TECHNICAL -#define XK_THAI -#define XK_VIETNAMESE -#define XK_XKB_KEYS -#include - -#if !defined(XK_OE) -#define XK_OE 0x13bc -#endif -#if !defined(XK_oe) -#define XK_oe 0x13bd -#endif -#if !defined(XK_Ydiaeresis) -#define XK_Ydiaeresis 0x13be -#endif - -/* - * This table maps keysym values into the corresponding ISO 10646 - * (UCS, Unicode) values. - * - * The array keysymtab[] contains pairs of X11 keysym values for graphical - * characters and the corresponding Unicode value. - * - * Author: Markus G. Kuhn , - * University of Cambridge, April 2001 - * - * Special thanks to Richard Verhoeven for preparing - * an initial draft of the mapping table. - * - * This software is in the public domain. Share and enjoy! - */ - -struct codepair { - KeySym keysym; - UInt32 ucs4; -} s_keymap[] = { -{ XK_Aogonek, 0x0104 }, /* LATIN CAPITAL LETTER A WITH OGONEK */ -{ XK_breve, 0x02d8 }, /* BREVE */ -{ XK_Lstroke, 0x0141 }, /* LATIN CAPITAL LETTER L WITH STROKE */ -{ XK_Lcaron, 0x013d }, /* LATIN CAPITAL LETTER L WITH CARON */ -{ XK_Sacute, 0x015a }, /* LATIN CAPITAL LETTER S WITH ACUTE */ -{ XK_Scaron, 0x0160 }, /* LATIN CAPITAL LETTER S WITH CARON */ -{ XK_Scedilla, 0x015e }, /* LATIN CAPITAL LETTER S WITH CEDILLA */ -{ XK_Tcaron, 0x0164 }, /* LATIN CAPITAL LETTER T WITH CARON */ -{ XK_Zacute, 0x0179 }, /* LATIN CAPITAL LETTER Z WITH ACUTE */ -{ XK_Zcaron, 0x017d }, /* LATIN CAPITAL LETTER Z WITH CARON */ -{ XK_Zabovedot, 0x017b }, /* LATIN CAPITAL LETTER Z WITH DOT ABOVE */ -{ XK_aogonek, 0x0105 }, /* LATIN SMALL LETTER A WITH OGONEK */ -{ XK_ogonek, 0x02db }, /* OGONEK */ -{ XK_lstroke, 0x0142 }, /* LATIN SMALL LETTER L WITH STROKE */ -{ XK_lcaron, 0x013e }, /* LATIN SMALL LETTER L WITH CARON */ -{ XK_sacute, 0x015b }, /* LATIN SMALL LETTER S WITH ACUTE */ -{ XK_caron, 0x02c7 }, /* CARON */ -{ XK_scaron, 0x0161 }, /* LATIN SMALL LETTER S WITH CARON */ -{ XK_scedilla, 0x015f }, /* LATIN SMALL LETTER S WITH CEDILLA */ -{ XK_tcaron, 0x0165 }, /* LATIN SMALL LETTER T WITH CARON */ -{ XK_zacute, 0x017a }, /* LATIN SMALL LETTER Z WITH ACUTE */ -{ XK_doubleacute, 0x02dd }, /* DOUBLE ACUTE ACCENT */ -{ XK_zcaron, 0x017e }, /* LATIN SMALL LETTER Z WITH CARON */ -{ XK_zabovedot, 0x017c }, /* LATIN SMALL LETTER Z WITH DOT ABOVE */ -{ XK_Racute, 0x0154 }, /* LATIN CAPITAL LETTER R WITH ACUTE */ -{ XK_Abreve, 0x0102 }, /* LATIN CAPITAL LETTER A WITH BREVE */ -{ XK_Lacute, 0x0139 }, /* LATIN CAPITAL LETTER L WITH ACUTE */ -{ XK_Cacute, 0x0106 }, /* LATIN CAPITAL LETTER C WITH ACUTE */ -{ XK_Ccaron, 0x010c }, /* LATIN CAPITAL LETTER C WITH CARON */ -{ XK_Eogonek, 0x0118 }, /* LATIN CAPITAL LETTER E WITH OGONEK */ -{ XK_Ecaron, 0x011a }, /* LATIN CAPITAL LETTER E WITH CARON */ -{ XK_Dcaron, 0x010e }, /* LATIN CAPITAL LETTER D WITH CARON */ -{ XK_Dstroke, 0x0110 }, /* LATIN CAPITAL LETTER D WITH STROKE */ -{ XK_Nacute, 0x0143 }, /* LATIN CAPITAL LETTER N WITH ACUTE */ -{ XK_Ncaron, 0x0147 }, /* LATIN CAPITAL LETTER N WITH CARON */ -{ XK_Odoubleacute, 0x0150 }, /* LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */ -{ XK_Rcaron, 0x0158 }, /* LATIN CAPITAL LETTER R WITH CARON */ -{ XK_Uring, 0x016e }, /* LATIN CAPITAL LETTER U WITH RING ABOVE */ -{ XK_Udoubleacute, 0x0170 }, /* LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */ -{ XK_Tcedilla, 0x0162 }, /* LATIN CAPITAL LETTER T WITH CEDILLA */ -{ XK_racute, 0x0155 }, /* LATIN SMALL LETTER R WITH ACUTE */ -{ XK_abreve, 0x0103 }, /* LATIN SMALL LETTER A WITH BREVE */ -{ XK_lacute, 0x013a }, /* LATIN SMALL LETTER L WITH ACUTE */ -{ XK_cacute, 0x0107 }, /* LATIN SMALL LETTER C WITH ACUTE */ -{ XK_ccaron, 0x010d }, /* LATIN SMALL LETTER C WITH CARON */ -{ XK_eogonek, 0x0119 }, /* LATIN SMALL LETTER E WITH OGONEK */ -{ XK_ecaron, 0x011b }, /* LATIN SMALL LETTER E WITH CARON */ -{ XK_dcaron, 0x010f }, /* LATIN SMALL LETTER D WITH CARON */ -{ XK_dstroke, 0x0111 }, /* LATIN SMALL LETTER D WITH STROKE */ -{ XK_nacute, 0x0144 }, /* LATIN SMALL LETTER N WITH ACUTE */ -{ XK_ncaron, 0x0148 }, /* LATIN SMALL LETTER N WITH CARON */ -{ XK_odoubleacute, 0x0151 }, /* LATIN SMALL LETTER O WITH DOUBLE ACUTE */ -{ XK_rcaron, 0x0159 }, /* LATIN SMALL LETTER R WITH CARON */ -{ XK_uring, 0x016f }, /* LATIN SMALL LETTER U WITH RING ABOVE */ -{ XK_udoubleacute, 0x0171 }, /* LATIN SMALL LETTER U WITH DOUBLE ACUTE */ -{ XK_tcedilla, 0x0163 }, /* LATIN SMALL LETTER T WITH CEDILLA */ -{ XK_abovedot, 0x02d9 }, /* DOT ABOVE */ -{ XK_Hstroke, 0x0126 }, /* LATIN CAPITAL LETTER H WITH STROKE */ -{ XK_Hcircumflex, 0x0124 }, /* LATIN CAPITAL LETTER H WITH CIRCUMFLEX */ -{ XK_Iabovedot, 0x0130 }, /* LATIN CAPITAL LETTER I WITH DOT ABOVE */ -{ XK_Gbreve, 0x011e }, /* LATIN CAPITAL LETTER G WITH BREVE */ -{ XK_Jcircumflex, 0x0134 }, /* LATIN CAPITAL LETTER J WITH CIRCUMFLEX */ -{ XK_hstroke, 0x0127 }, /* LATIN SMALL LETTER H WITH STROKE */ -{ XK_hcircumflex, 0x0125 }, /* LATIN SMALL LETTER H WITH CIRCUMFLEX */ -{ XK_idotless, 0x0131 }, /* LATIN SMALL LETTER DOTLESS I */ -{ XK_gbreve, 0x011f }, /* LATIN SMALL LETTER G WITH BREVE */ -{ XK_jcircumflex, 0x0135 }, /* LATIN SMALL LETTER J WITH CIRCUMFLEX */ -{ XK_Cabovedot, 0x010a }, /* LATIN CAPITAL LETTER C WITH DOT ABOVE */ -{ XK_Ccircumflex, 0x0108 }, /* LATIN CAPITAL LETTER C WITH CIRCUMFLEX */ -{ XK_Gabovedot, 0x0120 }, /* LATIN CAPITAL LETTER G WITH DOT ABOVE */ -{ XK_Gcircumflex, 0x011c }, /* LATIN CAPITAL LETTER G WITH CIRCUMFLEX */ -{ XK_Ubreve, 0x016c }, /* LATIN CAPITAL LETTER U WITH BREVE */ -{ XK_Scircumflex, 0x015c }, /* LATIN CAPITAL LETTER S WITH CIRCUMFLEX */ -{ XK_cabovedot, 0x010b }, /* LATIN SMALL LETTER C WITH DOT ABOVE */ -{ XK_ccircumflex, 0x0109 }, /* LATIN SMALL LETTER C WITH CIRCUMFLEX */ -{ XK_gabovedot, 0x0121 }, /* LATIN SMALL LETTER G WITH DOT ABOVE */ -{ XK_gcircumflex, 0x011d }, /* LATIN SMALL LETTER G WITH CIRCUMFLEX */ -{ XK_ubreve, 0x016d }, /* LATIN SMALL LETTER U WITH BREVE */ -{ XK_scircumflex, 0x015d }, /* LATIN SMALL LETTER S WITH CIRCUMFLEX */ -{ XK_kra, 0x0138 }, /* LATIN SMALL LETTER KRA */ -{ XK_Rcedilla, 0x0156 }, /* LATIN CAPITAL LETTER R WITH CEDILLA */ -{ XK_Itilde, 0x0128 }, /* LATIN CAPITAL LETTER I WITH TILDE */ -{ XK_Lcedilla, 0x013b }, /* LATIN CAPITAL LETTER L WITH CEDILLA */ -{ XK_Emacron, 0x0112 }, /* LATIN CAPITAL LETTER E WITH MACRON */ -{ XK_Gcedilla, 0x0122 }, /* LATIN CAPITAL LETTER G WITH CEDILLA */ -{ XK_Tslash, 0x0166 }, /* LATIN CAPITAL LETTER T WITH STROKE */ -{ XK_rcedilla, 0x0157 }, /* LATIN SMALL LETTER R WITH CEDILLA */ -{ XK_itilde, 0x0129 }, /* LATIN SMALL LETTER I WITH TILDE */ -{ XK_lcedilla, 0x013c }, /* LATIN SMALL LETTER L WITH CEDILLA */ -{ XK_emacron, 0x0113 }, /* LATIN SMALL LETTER E WITH MACRON */ -{ XK_gcedilla, 0x0123 }, /* LATIN SMALL LETTER G WITH CEDILLA */ -{ XK_tslash, 0x0167 }, /* LATIN SMALL LETTER T WITH STROKE */ -{ XK_ENG, 0x014a }, /* LATIN CAPITAL LETTER ENG */ -{ XK_eng, 0x014b }, /* LATIN SMALL LETTER ENG */ -{ XK_Amacron, 0x0100 }, /* LATIN CAPITAL LETTER A WITH MACRON */ -{ XK_Iogonek, 0x012e }, /* LATIN CAPITAL LETTER I WITH OGONEK */ -{ XK_Eabovedot, 0x0116 }, /* LATIN CAPITAL LETTER E WITH DOT ABOVE */ -{ XK_Imacron, 0x012a }, /* LATIN CAPITAL LETTER I WITH MACRON */ -{ XK_Ncedilla, 0x0145 }, /* LATIN CAPITAL LETTER N WITH CEDILLA */ -{ XK_Omacron, 0x014c }, /* LATIN CAPITAL LETTER O WITH MACRON */ -{ XK_Kcedilla, 0x0136 }, /* LATIN CAPITAL LETTER K WITH CEDILLA */ -{ XK_Uogonek, 0x0172 }, /* LATIN CAPITAL LETTER U WITH OGONEK */ -{ XK_Utilde, 0x0168 }, /* LATIN CAPITAL LETTER U WITH TILDE */ -{ XK_Umacron, 0x016a }, /* LATIN CAPITAL LETTER U WITH MACRON */ -{ XK_amacron, 0x0101 }, /* LATIN SMALL LETTER A WITH MACRON */ -{ XK_iogonek, 0x012f }, /* LATIN SMALL LETTER I WITH OGONEK */ -{ XK_eabovedot, 0x0117 }, /* LATIN SMALL LETTER E WITH DOT ABOVE */ -{ XK_imacron, 0x012b }, /* LATIN SMALL LETTER I WITH MACRON */ -{ XK_ncedilla, 0x0146 }, /* LATIN SMALL LETTER N WITH CEDILLA */ -{ XK_omacron, 0x014d }, /* LATIN SMALL LETTER O WITH MACRON */ -{ XK_kcedilla, 0x0137 }, /* LATIN SMALL LETTER K WITH CEDILLA */ -{ XK_uogonek, 0x0173 }, /* LATIN SMALL LETTER U WITH OGONEK */ -{ XK_utilde, 0x0169 }, /* LATIN SMALL LETTER U WITH TILDE */ -{ XK_umacron, 0x016b }, /* LATIN SMALL LETTER U WITH MACRON */ -#if defined(XK_Babovedot) -{ XK_Babovedot, 0x1e02 }, /* LATIN CAPITAL LETTER B WITH DOT ABOVE */ -{ XK_babovedot, 0x1e03 }, /* LATIN SMALL LETTER B WITH DOT ABOVE */ -{ XK_Dabovedot, 0x1e0a }, /* LATIN CAPITAL LETTER D WITH DOT ABOVE */ -{ XK_Wgrave, 0x1e80 }, /* LATIN CAPITAL LETTER W WITH GRAVE */ -{ XK_Wacute, 0x1e82 }, /* LATIN CAPITAL LETTER W WITH ACUTE */ -{ XK_dabovedot, 0x1e0b }, /* LATIN SMALL LETTER D WITH DOT ABOVE */ -{ XK_Ygrave, 0x1ef2 }, /* LATIN CAPITAL LETTER Y WITH GRAVE */ -{ XK_Fabovedot, 0x1e1e }, /* LATIN CAPITAL LETTER F WITH DOT ABOVE */ -{ XK_fabovedot, 0x1e1f }, /* LATIN SMALL LETTER F WITH DOT ABOVE */ -{ XK_Mabovedot, 0x1e40 }, /* LATIN CAPITAL LETTER M WITH DOT ABOVE */ -{ XK_mabovedot, 0x1e41 }, /* LATIN SMALL LETTER M WITH DOT ABOVE */ -{ XK_Pabovedot, 0x1e56 }, /* LATIN CAPITAL LETTER P WITH DOT ABOVE */ -{ XK_wgrave, 0x1e81 }, /* LATIN SMALL LETTER W WITH GRAVE */ -{ XK_pabovedot, 0x1e57 }, /* LATIN SMALL LETTER P WITH DOT ABOVE */ -{ XK_wacute, 0x1e83 }, /* LATIN SMALL LETTER W WITH ACUTE */ -{ XK_Sabovedot, 0x1e60 }, /* LATIN CAPITAL LETTER S WITH DOT ABOVE */ -{ XK_ygrave, 0x1ef3 }, /* LATIN SMALL LETTER Y WITH GRAVE */ -{ XK_Wdiaeresis, 0x1e84 }, /* LATIN CAPITAL LETTER W WITH DIAERESIS */ -{ XK_wdiaeresis, 0x1e85 }, /* LATIN SMALL LETTER W WITH DIAERESIS */ -{ XK_sabovedot, 0x1e61 }, /* LATIN SMALL LETTER S WITH DOT ABOVE */ -{ XK_Wcircumflex, 0x0174 }, /* LATIN CAPITAL LETTER W WITH CIRCUMFLEX */ -{ XK_Tabovedot, 0x1e6a }, /* LATIN CAPITAL LETTER T WITH DOT ABOVE */ -{ XK_Ycircumflex, 0x0176 }, /* LATIN CAPITAL LETTER Y WITH CIRCUMFLEX */ -{ XK_wcircumflex, 0x0175 }, /* LATIN SMALL LETTER W WITH CIRCUMFLEX */ -{ XK_tabovedot, 0x1e6b }, /* LATIN SMALL LETTER T WITH DOT ABOVE */ -{ XK_ycircumflex, 0x0177 }, /* LATIN SMALL LETTER Y WITH CIRCUMFLEX */ -#endif // defined(XK_Babovedot) -#if defined(XK_overline) -{ XK_overline, 0x203e }, /* OVERLINE */ -{ XK_kana_fullstop, 0x3002 }, /* IDEOGRAPHIC FULL STOP */ -{ XK_kana_openingbracket, 0x300c }, /* LEFT CORNER BRACKET */ -{ XK_kana_closingbracket, 0x300d }, /* RIGHT CORNER BRACKET */ -{ XK_kana_comma, 0x3001 }, /* IDEOGRAPHIC COMMA */ -{ XK_kana_conjunctive, 0x30fb }, /* KATAKANA MIDDLE DOT */ -{ XK_kana_WO, 0x30f2 }, /* KATAKANA LETTER WO */ -{ XK_kana_a, 0x30a1 }, /* KATAKANA LETTER SMALL A */ -{ XK_kana_i, 0x30a3 }, /* KATAKANA LETTER SMALL I */ -{ XK_kana_u, 0x30a5 }, /* KATAKANA LETTER SMALL U */ -{ XK_kana_e, 0x30a7 }, /* KATAKANA LETTER SMALL E */ -{ XK_kana_o, 0x30a9 }, /* KATAKANA LETTER SMALL O */ -{ XK_kana_ya, 0x30e3 }, /* KATAKANA LETTER SMALL YA */ -{ XK_kana_yu, 0x30e5 }, /* KATAKANA LETTER SMALL YU */ -{ XK_kana_yo, 0x30e7 }, /* KATAKANA LETTER SMALL YO */ -{ XK_kana_tsu, 0x30c3 }, /* KATAKANA LETTER SMALL TU */ -{ XK_prolongedsound, 0x30fc }, /* KATAKANA-HIRAGANA PROLONGED SOUND MARK */ -{ XK_kana_A, 0x30a2 }, /* KATAKANA LETTER A */ -{ XK_kana_I, 0x30a4 }, /* KATAKANA LETTER I */ -{ XK_kana_U, 0x30a6 }, /* KATAKANA LETTER U */ -{ XK_kana_E, 0x30a8 }, /* KATAKANA LETTER E */ -{ XK_kana_O, 0x30aa }, /* KATAKANA LETTER O */ -{ XK_kana_KA, 0x30ab }, /* KATAKANA LETTER KA */ -{ XK_kana_KI, 0x30ad }, /* KATAKANA LETTER KI */ -{ XK_kana_KU, 0x30af }, /* KATAKANA LETTER KU */ -{ XK_kana_KE, 0x30b1 }, /* KATAKANA LETTER KE */ -{ XK_kana_KO, 0x30b3 }, /* KATAKANA LETTER KO */ -{ XK_kana_SA, 0x30b5 }, /* KATAKANA LETTER SA */ -{ XK_kana_SHI, 0x30b7 }, /* KATAKANA LETTER SI */ -{ XK_kana_SU, 0x30b9 }, /* KATAKANA LETTER SU */ -{ XK_kana_SE, 0x30bb }, /* KATAKANA LETTER SE */ -{ XK_kana_SO, 0x30bd }, /* KATAKANA LETTER SO */ -{ XK_kana_TA, 0x30bf }, /* KATAKANA LETTER TA */ -{ XK_kana_CHI, 0x30c1 }, /* KATAKANA LETTER TI */ -{ XK_kana_TSU, 0x30c4 }, /* KATAKANA LETTER TU */ -{ XK_kana_TE, 0x30c6 }, /* KATAKANA LETTER TE */ -{ XK_kana_TO, 0x30c8 }, /* KATAKANA LETTER TO */ -{ XK_kana_NA, 0x30ca }, /* KATAKANA LETTER NA */ -{ XK_kana_NI, 0x30cb }, /* KATAKANA LETTER NI */ -{ XK_kana_NU, 0x30cc }, /* KATAKANA LETTER NU */ -{ XK_kana_NE, 0x30cd }, /* KATAKANA LETTER NE */ -{ XK_kana_NO, 0x30ce }, /* KATAKANA LETTER NO */ -{ XK_kana_HA, 0x30cf }, /* KATAKANA LETTER HA */ -{ XK_kana_HI, 0x30d2 }, /* KATAKANA LETTER HI */ -{ XK_kana_FU, 0x30d5 }, /* KATAKANA LETTER HU */ -{ XK_kana_HE, 0x30d8 }, /* KATAKANA LETTER HE */ -{ XK_kana_HO, 0x30db }, /* KATAKANA LETTER HO */ -{ XK_kana_MA, 0x30de }, /* KATAKANA LETTER MA */ -{ XK_kana_MI, 0x30df }, /* KATAKANA LETTER MI */ -{ XK_kana_MU, 0x30e0 }, /* KATAKANA LETTER MU */ -{ XK_kana_ME, 0x30e1 }, /* KATAKANA LETTER ME */ -{ XK_kana_MO, 0x30e2 }, /* KATAKANA LETTER MO */ -{ XK_kana_YA, 0x30e4 }, /* KATAKANA LETTER YA */ -{ XK_kana_YU, 0x30e6 }, /* KATAKANA LETTER YU */ -{ XK_kana_YO, 0x30e8 }, /* KATAKANA LETTER YO */ -{ XK_kana_RA, 0x30e9 }, /* KATAKANA LETTER RA */ -{ XK_kana_RI, 0x30ea }, /* KATAKANA LETTER RI */ -{ XK_kana_RU, 0x30eb }, /* KATAKANA LETTER RU */ -{ XK_kana_RE, 0x30ec }, /* KATAKANA LETTER RE */ -{ XK_kana_RO, 0x30ed }, /* KATAKANA LETTER RO */ -{ XK_kana_WA, 0x30ef }, /* KATAKANA LETTER WA */ -{ XK_kana_N, 0x30f3 }, /* KATAKANA LETTER N */ -{ XK_voicedsound, 0x309b }, /* KATAKANA-HIRAGANA VOICED SOUND MARK */ -{ XK_semivoicedsound, 0x309c }, /* KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */ -#endif // defined(XK_overline) -#if defined(XK_Farsi_0) -{ XK_Farsi_0, 0x06f0 }, /* EXTENDED ARABIC-INDIC DIGIT 0 */ -{ XK_Farsi_1, 0x06f1 }, /* EXTENDED ARABIC-INDIC DIGIT 1 */ -{ XK_Farsi_2, 0x06f2 }, /* EXTENDED ARABIC-INDIC DIGIT 2 */ -{ XK_Farsi_3, 0x06f3 }, /* EXTENDED ARABIC-INDIC DIGIT 3 */ -{ XK_Farsi_4, 0x06f4 }, /* EXTENDED ARABIC-INDIC DIGIT 4 */ -{ XK_Farsi_5, 0x06f5 }, /* EXTENDED ARABIC-INDIC DIGIT 5 */ -{ XK_Farsi_6, 0x06f6 }, /* EXTENDED ARABIC-INDIC DIGIT 6 */ -{ XK_Farsi_7, 0x06f7 }, /* EXTENDED ARABIC-INDIC DIGIT 7 */ -{ XK_Farsi_8, 0x06f8 }, /* EXTENDED ARABIC-INDIC DIGIT 8 */ -{ XK_Farsi_9, 0x06f9 }, /* EXTENDED ARABIC-INDIC DIGIT 9 */ -{ XK_Arabic_percent, 0x066a }, /* ARABIC PERCENT */ -{ XK_Arabic_superscript_alef, 0x0670 }, /* ARABIC LETTER SUPERSCRIPT ALEF */ -{ XK_Arabic_tteh, 0x0679 }, /* ARABIC LETTER TTEH */ -{ XK_Arabic_peh, 0x067e }, /* ARABIC LETTER PEH */ -{ XK_Arabic_tcheh, 0x0686 }, /* ARABIC LETTER TCHEH */ -{ XK_Arabic_ddal, 0x0688 }, /* ARABIC LETTER DDAL */ -{ XK_Arabic_rreh, 0x0691 }, /* ARABIC LETTER RREH */ -{ XK_Arabic_comma, 0x060c }, /* ARABIC COMMA */ -{ XK_Arabic_fullstop, 0x06d4 }, /* ARABIC FULLSTOP */ -{ XK_Arabic_semicolon, 0x061b }, /* ARABIC SEMICOLON */ -{ XK_Arabic_0, 0x0660 }, /* ARABIC 0 */ -{ XK_Arabic_1, 0x0661 }, /* ARABIC 1 */ -{ XK_Arabic_2, 0x0662 }, /* ARABIC 2 */ -{ XK_Arabic_3, 0x0663 }, /* ARABIC 3 */ -{ XK_Arabic_4, 0x0664 }, /* ARABIC 4 */ -{ XK_Arabic_5, 0x0665 }, /* ARABIC 5 */ -{ XK_Arabic_6, 0x0666 }, /* ARABIC 6 */ -{ XK_Arabic_7, 0x0667 }, /* ARABIC 7 */ -{ XK_Arabic_8, 0x0668 }, /* ARABIC 8 */ -{ XK_Arabic_9, 0x0669 }, /* ARABIC 9 */ -{ XK_Arabic_question_mark, 0x061f }, /* ARABIC QUESTION MARK */ -{ XK_Arabic_hamza, 0x0621 }, /* ARABIC LETTER HAMZA */ -{ XK_Arabic_maddaonalef, 0x0622 }, /* ARABIC LETTER ALEF WITH MADDA ABOVE */ -{ XK_Arabic_hamzaonalef, 0x0623 }, /* ARABIC LETTER ALEF WITH HAMZA ABOVE */ -{ XK_Arabic_hamzaonwaw, 0x0624 }, /* ARABIC LETTER WAW WITH HAMZA ABOVE */ -{ XK_Arabic_hamzaunderalef, 0x0625 }, /* ARABIC LETTER ALEF WITH HAMZA BELOW */ -{ XK_Arabic_hamzaonyeh, 0x0626 }, /* ARABIC LETTER YEH WITH HAMZA ABOVE */ -{ XK_Arabic_alef, 0x0627 }, /* ARABIC LETTER ALEF */ -{ XK_Arabic_beh, 0x0628 }, /* ARABIC LETTER BEH */ -{ XK_Arabic_tehmarbuta, 0x0629 }, /* ARABIC LETTER TEH MARBUTA */ -{ XK_Arabic_teh, 0x062a }, /* ARABIC LETTER TEH */ -{ XK_Arabic_theh, 0x062b }, /* ARABIC LETTER THEH */ -{ XK_Arabic_jeem, 0x062c }, /* ARABIC LETTER JEEM */ -{ XK_Arabic_hah, 0x062d }, /* ARABIC LETTER HAH */ -{ XK_Arabic_khah, 0x062e }, /* ARABIC LETTER KHAH */ -{ XK_Arabic_dal, 0x062f }, /* ARABIC LETTER DAL */ -{ XK_Arabic_thal, 0x0630 }, /* ARABIC LETTER THAL */ -{ XK_Arabic_ra, 0x0631 }, /* ARABIC LETTER REH */ -{ XK_Arabic_zain, 0x0632 }, /* ARABIC LETTER ZAIN */ -{ XK_Arabic_seen, 0x0633 }, /* ARABIC LETTER SEEN */ -{ XK_Arabic_sheen, 0x0634 }, /* ARABIC LETTER SHEEN */ -{ XK_Arabic_sad, 0x0635 }, /* ARABIC LETTER SAD */ -{ XK_Arabic_dad, 0x0636 }, /* ARABIC LETTER DAD */ -{ XK_Arabic_tah, 0x0637 }, /* ARABIC LETTER TAH */ -{ XK_Arabic_zah, 0x0638 }, /* ARABIC LETTER ZAH */ -{ XK_Arabic_ain, 0x0639 }, /* ARABIC LETTER AIN */ -{ XK_Arabic_ghain, 0x063a }, /* ARABIC LETTER GHAIN */ -{ XK_Arabic_tatweel, 0x0640 }, /* ARABIC TATWEEL */ -{ XK_Arabic_feh, 0x0641 }, /* ARABIC LETTER FEH */ -{ XK_Arabic_qaf, 0x0642 }, /* ARABIC LETTER QAF */ -{ XK_Arabic_kaf, 0x0643 }, /* ARABIC LETTER KAF */ -{ XK_Arabic_lam, 0x0644 }, /* ARABIC LETTER LAM */ -{ XK_Arabic_meem, 0x0645 }, /* ARABIC LETTER MEEM */ -{ XK_Arabic_noon, 0x0646 }, /* ARABIC LETTER NOON */ -{ XK_Arabic_ha, 0x0647 }, /* ARABIC LETTER HEH */ -{ XK_Arabic_waw, 0x0648 }, /* ARABIC LETTER WAW */ -{ XK_Arabic_alefmaksura, 0x0649 }, /* ARABIC LETTER ALEF MAKSURA */ -{ XK_Arabic_yeh, 0x064a }, /* ARABIC LETTER YEH */ -{ XK_Arabic_fathatan, 0x064b }, /* ARABIC FATHATAN */ -{ XK_Arabic_dammatan, 0x064c }, /* ARABIC DAMMATAN */ -{ XK_Arabic_kasratan, 0x064d }, /* ARABIC KASRATAN */ -{ XK_Arabic_fatha, 0x064e }, /* ARABIC FATHA */ -{ XK_Arabic_damma, 0x064f }, /* ARABIC DAMMA */ -{ XK_Arabic_kasra, 0x0650 }, /* ARABIC KASRA */ -{ XK_Arabic_shadda, 0x0651 }, /* ARABIC SHADDA */ -{ XK_Arabic_sukun, 0x0652 }, /* ARABIC SUKUN */ -{ XK_Arabic_madda_above, 0x0653 }, /* ARABIC MADDA ABOVE */ -{ XK_Arabic_hamza_above, 0x0654 }, /* ARABIC HAMZA ABOVE */ -{ XK_Arabic_hamza_below, 0x0655 }, /* ARABIC HAMZA BELOW */ -{ XK_Arabic_jeh, 0x0698 }, /* ARABIC LETTER JEH */ -{ XK_Arabic_veh, 0x06a4 }, /* ARABIC LETTER VEH */ -{ XK_Arabic_keheh, 0x06a9 }, /* ARABIC LETTER KEHEH */ -{ XK_Arabic_gaf, 0x06af }, /* ARABIC LETTER GAF */ -{ XK_Arabic_noon_ghunna, 0x06ba }, /* ARABIC LETTER NOON GHUNNA */ -{ XK_Arabic_heh_doachashmee, 0x06be }, /* ARABIC LETTER HEH DOACHASHMEE */ -{ XK_Arabic_farsi_yeh, 0x06cc }, /* ARABIC LETTER FARSI YEH */ -{ XK_Arabic_yeh_baree, 0x06d2 }, /* ARABIC LETTER YEH BAREE */ -{ XK_Arabic_heh_goal, 0x06c1 }, /* ARABIC LETTER HEH GOAL */ -#endif // defined(XK_Farsi_0) -#if defined(XK_Serbian_dje) -{ XK_Serbian_dje, 0x0452 }, /* CYRILLIC SMALL LETTER DJE */ -{ XK_Macedonia_gje, 0x0453 }, /* CYRILLIC SMALL LETTER GJE */ -{ XK_Cyrillic_io, 0x0451 }, /* CYRILLIC SMALL LETTER IO */ -{ XK_Ukrainian_ie, 0x0454 }, /* CYRILLIC SMALL LETTER UKRAINIAN IE */ -{ XK_Macedonia_dse, 0x0455 }, /* CYRILLIC SMALL LETTER DZE */ -{ XK_Ukrainian_i, 0x0456 }, /* CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */ -{ XK_Ukrainian_yi, 0x0457 }, /* CYRILLIC SMALL LETTER YI */ -{ XK_Cyrillic_je, 0x0458 }, /* CYRILLIC SMALL LETTER JE */ -{ XK_Cyrillic_lje, 0x0459 }, /* CYRILLIC SMALL LETTER LJE */ -{ XK_Cyrillic_nje, 0x045a }, /* CYRILLIC SMALL LETTER NJE */ -{ XK_Serbian_tshe, 0x045b }, /* CYRILLIC SMALL LETTER TSHE */ -{ XK_Macedonia_kje, 0x045c }, /* CYRILLIC SMALL LETTER KJE */ -#if defined(XK_Ukrainian_ghe_with_upturn) -{ XK_Ukrainian_ghe_with_upturn, 0x0491 }, /* CYRILLIC SMALL LETTER GHE WITH UPTURN */ -#endif -{ XK_Byelorussian_shortu, 0x045e }, /* CYRILLIC SMALL LETTER SHORT U */ -{ XK_Cyrillic_dzhe, 0x045f }, /* CYRILLIC SMALL LETTER DZHE */ -{ XK_numerosign, 0x2116 }, /* NUMERO SIGN */ -{ XK_Serbian_DJE, 0x0402 }, /* CYRILLIC CAPITAL LETTER DJE */ -{ XK_Macedonia_GJE, 0x0403 }, /* CYRILLIC CAPITAL LETTER GJE */ -{ XK_Cyrillic_IO, 0x0401 }, /* CYRILLIC CAPITAL LETTER IO */ -{ XK_Ukrainian_IE, 0x0404 }, /* CYRILLIC CAPITAL LETTER UKRAINIAN IE */ -{ XK_Macedonia_DSE, 0x0405 }, /* CYRILLIC CAPITAL LETTER DZE */ -{ XK_Ukrainian_I, 0x0406 }, /* CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */ -{ XK_Ukrainian_YI, 0x0407 }, /* CYRILLIC CAPITAL LETTER YI */ -{ XK_Cyrillic_JE, 0x0408 }, /* CYRILLIC CAPITAL LETTER JE */ -{ XK_Cyrillic_LJE, 0x0409 }, /* CYRILLIC CAPITAL LETTER LJE */ -{ XK_Cyrillic_NJE, 0x040a }, /* CYRILLIC CAPITAL LETTER NJE */ -{ XK_Serbian_TSHE, 0x040b }, /* CYRILLIC CAPITAL LETTER TSHE */ -{ XK_Macedonia_KJE, 0x040c }, /* CYRILLIC CAPITAL LETTER KJE */ -#if defined(XK_Ukrainian_GHE_WITH_UPTURN) -{ XK_Ukrainian_GHE_WITH_UPTURN, 0x0490 }, /* CYRILLIC CAPITAL LETTER GHE WITH UPTURN */ -#endif -{ XK_Byelorussian_SHORTU, 0x040e }, /* CYRILLIC CAPITAL LETTER SHORT U */ -{ XK_Cyrillic_DZHE, 0x040f }, /* CYRILLIC CAPITAL LETTER DZHE */ -{ XK_Cyrillic_yu, 0x044e }, /* CYRILLIC SMALL LETTER YU */ -{ XK_Cyrillic_a, 0x0430 }, /* CYRILLIC SMALL LETTER A */ -{ XK_Cyrillic_be, 0x0431 }, /* CYRILLIC SMALL LETTER BE */ -{ XK_Cyrillic_tse, 0x0446 }, /* CYRILLIC SMALL LETTER TSE */ -{ XK_Cyrillic_de, 0x0434 }, /* CYRILLIC SMALL LETTER DE */ -{ XK_Cyrillic_ie, 0x0435 }, /* CYRILLIC SMALL LETTER IE */ -{ XK_Cyrillic_ef, 0x0444 }, /* CYRILLIC SMALL LETTER EF */ -{ XK_Cyrillic_ghe, 0x0433 }, /* CYRILLIC SMALL LETTER GHE */ -{ XK_Cyrillic_ha, 0x0445 }, /* CYRILLIC SMALL LETTER HA */ -{ XK_Cyrillic_i, 0x0438 }, /* CYRILLIC SMALL LETTER I */ -{ XK_Cyrillic_shorti, 0x0439 }, /* CYRILLIC SMALL LETTER SHORT I */ -{ XK_Cyrillic_ka, 0x043a }, /* CYRILLIC SMALL LETTER KA */ -{ XK_Cyrillic_el, 0x043b }, /* CYRILLIC SMALL LETTER EL */ -{ XK_Cyrillic_em, 0x043c }, /* CYRILLIC SMALL LETTER EM */ -{ XK_Cyrillic_en, 0x043d }, /* CYRILLIC SMALL LETTER EN */ -{ XK_Cyrillic_o, 0x043e }, /* CYRILLIC SMALL LETTER O */ -{ XK_Cyrillic_pe, 0x043f }, /* CYRILLIC SMALL LETTER PE */ -{ XK_Cyrillic_ya, 0x044f }, /* CYRILLIC SMALL LETTER YA */ -{ XK_Cyrillic_er, 0x0440 }, /* CYRILLIC SMALL LETTER ER */ -{ XK_Cyrillic_es, 0x0441 }, /* CYRILLIC SMALL LETTER ES */ -{ XK_Cyrillic_te, 0x0442 }, /* CYRILLIC SMALL LETTER TE */ -{ XK_Cyrillic_u, 0x0443 }, /* CYRILLIC SMALL LETTER U */ -{ XK_Cyrillic_zhe, 0x0436 }, /* CYRILLIC SMALL LETTER ZHE */ -{ XK_Cyrillic_ve, 0x0432 }, /* CYRILLIC SMALL LETTER VE */ -{ XK_Cyrillic_softsign, 0x044c }, /* CYRILLIC SMALL LETTER SOFT SIGN */ -{ XK_Cyrillic_yeru, 0x044b }, /* CYRILLIC SMALL LETTER YERU */ -{ XK_Cyrillic_ze, 0x0437 }, /* CYRILLIC SMALL LETTER ZE */ -{ XK_Cyrillic_sha, 0x0448 }, /* CYRILLIC SMALL LETTER SHA */ -{ XK_Cyrillic_e, 0x044d }, /* CYRILLIC SMALL LETTER E */ -{ XK_Cyrillic_shcha, 0x0449 }, /* CYRILLIC SMALL LETTER SHCHA */ -{ XK_Cyrillic_che, 0x0447 }, /* CYRILLIC SMALL LETTER CHE */ -{ XK_Cyrillic_hardsign, 0x044a }, /* CYRILLIC SMALL LETTER HARD SIGN */ -{ XK_Cyrillic_YU, 0x042e }, /* CYRILLIC CAPITAL LETTER YU */ -{ XK_Cyrillic_A, 0x0410 }, /* CYRILLIC CAPITAL LETTER A */ -{ XK_Cyrillic_BE, 0x0411 }, /* CYRILLIC CAPITAL LETTER BE */ -{ XK_Cyrillic_TSE, 0x0426 }, /* CYRILLIC CAPITAL LETTER TSE */ -{ XK_Cyrillic_DE, 0x0414 }, /* CYRILLIC CAPITAL LETTER DE */ -{ XK_Cyrillic_IE, 0x0415 }, /* CYRILLIC CAPITAL LETTER IE */ -{ XK_Cyrillic_EF, 0x0424 }, /* CYRILLIC CAPITAL LETTER EF */ -{ XK_Cyrillic_GHE, 0x0413 }, /* CYRILLIC CAPITAL LETTER GHE */ -{ XK_Cyrillic_HA, 0x0425 }, /* CYRILLIC CAPITAL LETTER HA */ -{ XK_Cyrillic_I, 0x0418 }, /* CYRILLIC CAPITAL LETTER I */ -{ XK_Cyrillic_SHORTI, 0x0419 }, /* CYRILLIC CAPITAL LETTER SHORT I */ -{ XK_Cyrillic_KA, 0x041a }, /* CYRILLIC CAPITAL LETTER KA */ -{ XK_Cyrillic_EL, 0x041b }, /* CYRILLIC CAPITAL LETTER EL */ -{ XK_Cyrillic_EM, 0x041c }, /* CYRILLIC CAPITAL LETTER EM */ -{ XK_Cyrillic_EN, 0x041d }, /* CYRILLIC CAPITAL LETTER EN */ -{ XK_Cyrillic_O, 0x041e }, /* CYRILLIC CAPITAL LETTER O */ -{ XK_Cyrillic_PE, 0x041f }, /* CYRILLIC CAPITAL LETTER PE */ -{ XK_Cyrillic_YA, 0x042f }, /* CYRILLIC CAPITAL LETTER YA */ -{ XK_Cyrillic_ER, 0x0420 }, /* CYRILLIC CAPITAL LETTER ER */ -{ XK_Cyrillic_ES, 0x0421 }, /* CYRILLIC CAPITAL LETTER ES */ -{ XK_Cyrillic_TE, 0x0422 }, /* CYRILLIC CAPITAL LETTER TE */ -{ XK_Cyrillic_U, 0x0423 }, /* CYRILLIC CAPITAL LETTER U */ -{ XK_Cyrillic_ZHE, 0x0416 }, /* CYRILLIC CAPITAL LETTER ZHE */ -{ XK_Cyrillic_VE, 0x0412 }, /* CYRILLIC CAPITAL LETTER VE */ -{ XK_Cyrillic_SOFTSIGN, 0x042c }, /* CYRILLIC CAPITAL LETTER SOFT SIGN */ -{ XK_Cyrillic_YERU, 0x042b }, /* CYRILLIC CAPITAL LETTER YERU */ -{ XK_Cyrillic_ZE, 0x0417 }, /* CYRILLIC CAPITAL LETTER ZE */ -{ XK_Cyrillic_SHA, 0x0428 }, /* CYRILLIC CAPITAL LETTER SHA */ -{ XK_Cyrillic_E, 0x042d }, /* CYRILLIC CAPITAL LETTER E */ -{ XK_Cyrillic_SHCHA, 0x0429 }, /* CYRILLIC CAPITAL LETTER SHCHA */ -{ XK_Cyrillic_CHE, 0x0427 }, /* CYRILLIC CAPITAL LETTER CHE */ -{ XK_Cyrillic_HARDSIGN, 0x042a }, /* CYRILLIC CAPITAL LETTER HARD SIGN */ -#endif // defined(XK_Serbian_dje) -#if defined(XK_Greek_ALPHAaccent) -{ XK_Greek_ALPHAaccent, 0x0386 }, /* GREEK CAPITAL LETTER ALPHA WITH TONOS */ -{ XK_Greek_EPSILONaccent, 0x0388 }, /* GREEK CAPITAL LETTER EPSILON WITH TONOS */ -{ XK_Greek_ETAaccent, 0x0389 }, /* GREEK CAPITAL LETTER ETA WITH TONOS */ -{ XK_Greek_IOTAaccent, 0x038a }, /* GREEK CAPITAL LETTER IOTA WITH TONOS */ -{ XK_Greek_IOTAdiaeresis, 0x03aa }, /* GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */ -{ XK_Greek_OMICRONaccent, 0x038c }, /* GREEK CAPITAL LETTER OMICRON WITH TONOS */ -{ XK_Greek_UPSILONaccent, 0x038e }, /* GREEK CAPITAL LETTER UPSILON WITH TONOS */ -{ XK_Greek_UPSILONdieresis, 0x03ab }, /* GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */ -{ XK_Greek_OMEGAaccent, 0x038f }, /* GREEK CAPITAL LETTER OMEGA WITH TONOS */ -{ XK_Greek_accentdieresis, 0x0385 }, /* GREEK DIALYTIKA TONOS */ -{ XK_Greek_horizbar, 0x2015 }, /* HORIZONTAL BAR */ -{ XK_Greek_alphaaccent, 0x03ac }, /* GREEK SMALL LETTER ALPHA WITH TONOS */ -{ XK_Greek_epsilonaccent, 0x03ad }, /* GREEK SMALL LETTER EPSILON WITH TONOS */ -{ XK_Greek_etaaccent, 0x03ae }, /* GREEK SMALL LETTER ETA WITH TONOS */ -{ XK_Greek_iotaaccent, 0x03af }, /* GREEK SMALL LETTER IOTA WITH TONOS */ -{ XK_Greek_iotadieresis, 0x03ca }, /* GREEK SMALL LETTER IOTA WITH DIALYTIKA */ -{ XK_Greek_iotaaccentdieresis, 0x0390 }, /* GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */ -{ XK_Greek_omicronaccent, 0x03cc }, /* GREEK SMALL LETTER OMICRON WITH TONOS */ -{ XK_Greek_upsilonaccent, 0x03cd }, /* GREEK SMALL LETTER UPSILON WITH TONOS */ -{ XK_Greek_upsilondieresis, 0x03cb }, /* GREEK SMALL LETTER UPSILON WITH DIALYTIKA */ -{ XK_Greek_upsilonaccentdieresis, 0x03b0 }, /* GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */ -{ XK_Greek_omegaaccent, 0x03ce }, /* GREEK SMALL LETTER OMEGA WITH TONOS */ -{ XK_Greek_ALPHA, 0x0391 }, /* GREEK CAPITAL LETTER ALPHA */ -{ XK_Greek_BETA, 0x0392 }, /* GREEK CAPITAL LETTER BETA */ -{ XK_Greek_GAMMA, 0x0393 }, /* GREEK CAPITAL LETTER GAMMA */ -{ XK_Greek_DELTA, 0x0394 }, /* GREEK CAPITAL LETTER DELTA */ -{ XK_Greek_EPSILON, 0x0395 }, /* GREEK CAPITAL LETTER EPSILON */ -{ XK_Greek_ZETA, 0x0396 }, /* GREEK CAPITAL LETTER ZETA */ -{ XK_Greek_ETA, 0x0397 }, /* GREEK CAPITAL LETTER ETA */ -{ XK_Greek_THETA, 0x0398 }, /* GREEK CAPITAL LETTER THETA */ -{ XK_Greek_IOTA, 0x0399 }, /* GREEK CAPITAL LETTER IOTA */ -{ XK_Greek_KAPPA, 0x039a }, /* GREEK CAPITAL LETTER KAPPA */ -{ XK_Greek_LAMBDA, 0x039b }, /* GREEK CAPITAL LETTER LAMDA */ -{ XK_Greek_MU, 0x039c }, /* GREEK CAPITAL LETTER MU */ -{ XK_Greek_NU, 0x039d }, /* GREEK CAPITAL LETTER NU */ -{ XK_Greek_XI, 0x039e }, /* GREEK CAPITAL LETTER XI */ -{ XK_Greek_OMICRON, 0x039f }, /* GREEK CAPITAL LETTER OMICRON */ -{ XK_Greek_PI, 0x03a0 }, /* GREEK CAPITAL LETTER PI */ -{ XK_Greek_RHO, 0x03a1 }, /* GREEK CAPITAL LETTER RHO */ -{ XK_Greek_SIGMA, 0x03a3 }, /* GREEK CAPITAL LETTER SIGMA */ -{ XK_Greek_TAU, 0x03a4 }, /* GREEK CAPITAL LETTER TAU */ -{ XK_Greek_UPSILON, 0x03a5 }, /* GREEK CAPITAL LETTER UPSILON */ -{ XK_Greek_PHI, 0x03a6 }, /* GREEK CAPITAL LETTER PHI */ -{ XK_Greek_CHI, 0x03a7 }, /* GREEK CAPITAL LETTER CHI */ -{ XK_Greek_PSI, 0x03a8 }, /* GREEK CAPITAL LETTER PSI */ -{ XK_Greek_OMEGA, 0x03a9 }, /* GREEK CAPITAL LETTER OMEGA */ -{ XK_Greek_alpha, 0x03b1 }, /* GREEK SMALL LETTER ALPHA */ -{ XK_Greek_beta, 0x03b2 }, /* GREEK SMALL LETTER BETA */ -{ XK_Greek_gamma, 0x03b3 }, /* GREEK SMALL LETTER GAMMA */ -{ XK_Greek_delta, 0x03b4 }, /* GREEK SMALL LETTER DELTA */ -{ XK_Greek_epsilon, 0x03b5 }, /* GREEK SMALL LETTER EPSILON */ -{ XK_Greek_zeta, 0x03b6 }, /* GREEK SMALL LETTER ZETA */ -{ XK_Greek_eta, 0x03b7 }, /* GREEK SMALL LETTER ETA */ -{ XK_Greek_theta, 0x03b8 }, /* GREEK SMALL LETTER THETA */ -{ XK_Greek_iota, 0x03b9 }, /* GREEK SMALL LETTER IOTA */ -{ XK_Greek_kappa, 0x03ba }, /* GREEK SMALL LETTER KAPPA */ -{ XK_Greek_lambda, 0x03bb }, /* GREEK SMALL LETTER LAMDA */ -{ XK_Greek_mu, 0x03bc }, /* GREEK SMALL LETTER MU */ -{ XK_Greek_nu, 0x03bd }, /* GREEK SMALL LETTER NU */ -{ XK_Greek_xi, 0x03be }, /* GREEK SMALL LETTER XI */ -{ XK_Greek_omicron, 0x03bf }, /* GREEK SMALL LETTER OMICRON */ -{ XK_Greek_pi, 0x03c0 }, /* GREEK SMALL LETTER PI */ -{ XK_Greek_rho, 0x03c1 }, /* GREEK SMALL LETTER RHO */ -{ XK_Greek_sigma, 0x03c3 }, /* GREEK SMALL LETTER SIGMA */ -{ XK_Greek_finalsmallsigma, 0x03c2 }, /* GREEK SMALL LETTER FINAL SIGMA */ -{ XK_Greek_tau, 0x03c4 }, /* GREEK SMALL LETTER TAU */ -{ XK_Greek_upsilon, 0x03c5 }, /* GREEK SMALL LETTER UPSILON */ -{ XK_Greek_phi, 0x03c6 }, /* GREEK SMALL LETTER PHI */ -{ XK_Greek_chi, 0x03c7 }, /* GREEK SMALL LETTER CHI */ -{ XK_Greek_psi, 0x03c8 }, /* GREEK SMALL LETTER PSI */ -{ XK_Greek_omega, 0x03c9 }, /* GREEK SMALL LETTER OMEGA */ -#endif // defined(XK_Greek_ALPHAaccent) -{ XK_leftradical, 0x23b7 }, /* ??? */ -{ XK_topleftradical, 0x250c }, /* BOX DRAWINGS LIGHT DOWN AND RIGHT */ -{ XK_horizconnector, 0x2500 }, /* BOX DRAWINGS LIGHT HORIZONTAL */ -{ XK_topintegral, 0x2320 }, /* TOP HALF INTEGRAL */ -{ XK_botintegral, 0x2321 }, /* BOTTOM HALF INTEGRAL */ -{ XK_vertconnector, 0x2502 }, /* BOX DRAWINGS LIGHT VERTICAL */ -{ XK_topleftsqbracket, 0x23a1 }, /* ??? */ -{ XK_botleftsqbracket, 0x23a3 }, /* ??? */ -{ XK_toprightsqbracket, 0x23a4 }, /* ??? */ -{ XK_botrightsqbracket, 0x23a6 }, /* ??? */ -{ XK_topleftparens, 0x239b }, /* ??? */ -{ XK_botleftparens, 0x239d }, /* ??? */ -{ XK_toprightparens, 0x239e }, /* ??? */ -{ XK_botrightparens, 0x23a0 }, /* ??? */ -{ XK_leftmiddlecurlybrace, 0x23a8 }, /* ??? */ -{ XK_rightmiddlecurlybrace, 0x23ac }, /* ??? */ -{ XK_lessthanequal, 0x2264 }, /* LESS-THAN OR EQUAL TO */ -{ XK_notequal, 0x2260 }, /* NOT EQUAL TO */ -{ XK_greaterthanequal, 0x2265 }, /* GREATER-THAN OR EQUAL TO */ -{ XK_integral, 0x222b }, /* INTEGRAL */ -{ XK_therefore, 0x2234 }, /* THEREFORE */ -{ XK_variation, 0x221d }, /* PROPORTIONAL TO */ -{ XK_infinity, 0x221e }, /* INFINITY */ -{ XK_nabla, 0x2207 }, /* NABLA */ -{ XK_approximate, 0x223c }, /* TILDE OPERATOR */ -{ XK_similarequal, 0x2243 }, /* ASYMPTOTICALLY EQUAL TO */ -{ XK_ifonlyif, 0x21d4 }, /* LEFT RIGHT DOUBLE ARROW */ -{ XK_implies, 0x21d2 }, /* RIGHTWARDS DOUBLE ARROW */ -{ XK_identical, 0x2261 }, /* IDENTICAL TO */ -{ XK_radical, 0x221a }, /* SQUARE ROOT */ -{ XK_includedin, 0x2282 }, /* SUBSET OF */ -{ XK_includes, 0x2283 }, /* SUPERSET OF */ -{ XK_intersection, 0x2229 }, /* INTERSECTION */ -{ XK_union, 0x222a }, /* UNION */ -{ XK_logicaland, 0x2227 }, /* LOGICAL AND */ -{ XK_logicalor, 0x2228 }, /* LOGICAL OR */ -{ XK_partialderivative, 0x2202 }, /* PARTIAL DIFFERENTIAL */ -{ XK_function, 0x0192 }, /* LATIN SMALL LETTER F WITH HOOK */ -{ XK_leftarrow, 0x2190 }, /* LEFTWARDS ARROW */ -{ XK_uparrow, 0x2191 }, /* UPWARDS ARROW */ -{ XK_rightarrow, 0x2192 }, /* RIGHTWARDS ARROW */ -{ XK_downarrow, 0x2193 }, /* DOWNWARDS ARROW */ -/*{ XK_blank, ??? }, */ -{ XK_soliddiamond, 0x25c6 }, /* BLACK DIAMOND */ -{ XK_checkerboard, 0x2592 }, /* MEDIUM SHADE */ -{ XK_ht, 0x2409 }, /* SYMBOL FOR HORIZONTAL TABULATION */ -{ XK_ff, 0x240c }, /* SYMBOL FOR FORM FEED */ -{ XK_cr, 0x240d }, /* SYMBOL FOR CARRIAGE RETURN */ -{ XK_lf, 0x240a }, /* SYMBOL FOR LINE FEED */ -{ XK_nl, 0x2424 }, /* SYMBOL FOR NEWLINE */ -{ XK_vt, 0x240b }, /* SYMBOL FOR VERTICAL TABULATION */ -{ XK_lowrightcorner, 0x2518 }, /* BOX DRAWINGS LIGHT UP AND LEFT */ -{ XK_uprightcorner, 0x2510 }, /* BOX DRAWINGS LIGHT DOWN AND LEFT */ -{ XK_upleftcorner, 0x250c }, /* BOX DRAWINGS LIGHT DOWN AND RIGHT */ -{ XK_lowleftcorner, 0x2514 }, /* BOX DRAWINGS LIGHT UP AND RIGHT */ -{ XK_crossinglines, 0x253c }, /* BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */ -{ XK_horizlinescan1, 0x23ba }, /* HORIZONTAL SCAN LINE-1 (Unicode 3.2 draft) */ -{ XK_horizlinescan3, 0x23bb }, /* HORIZONTAL SCAN LINE-3 (Unicode 3.2 draft) */ -{ XK_horizlinescan5, 0x2500 }, /* BOX DRAWINGS LIGHT HORIZONTAL */ -{ XK_horizlinescan7, 0x23bc }, /* HORIZONTAL SCAN LINE-7 (Unicode 3.2 draft) */ -{ XK_horizlinescan9, 0x23bd }, /* HORIZONTAL SCAN LINE-9 (Unicode 3.2 draft) */ -{ XK_leftt, 0x251c }, /* BOX DRAWINGS LIGHT VERTICAL AND RIGHT */ -{ XK_rightt, 0x2524 }, /* BOX DRAWINGS LIGHT VERTICAL AND LEFT */ -{ XK_bott, 0x2534 }, /* BOX DRAWINGS LIGHT UP AND HORIZONTAL */ -{ XK_topt, 0x252c }, /* BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */ -{ XK_vertbar, 0x2502 }, /* BOX DRAWINGS LIGHT VERTICAL */ -{ XK_emspace, 0x2003 }, /* EM SPACE */ -{ XK_enspace, 0x2002 }, /* EN SPACE */ -{ XK_em3space, 0x2004 }, /* THREE-PER-EM SPACE */ -{ XK_em4space, 0x2005 }, /* FOUR-PER-EM SPACE */ -{ XK_digitspace, 0x2007 }, /* FIGURE SPACE */ -{ XK_punctspace, 0x2008 }, /* PUNCTUATION SPACE */ -{ XK_thinspace, 0x2009 }, /* THIN SPACE */ -{ XK_hairspace, 0x200a }, /* HAIR SPACE */ -{ XK_emdash, 0x2014 }, /* EM DASH */ -{ XK_endash, 0x2013 }, /* EN DASH */ -/*{ XK_signifblank, ??? }, */ -{ XK_ellipsis, 0x2026 }, /* HORIZONTAL ELLIPSIS */ -{ XK_doubbaselinedot, 0x2025 }, /* TWO DOT LEADER */ -{ XK_onethird, 0x2153 }, /* VULGAR FRACTION ONE THIRD */ -{ XK_twothirds, 0x2154 }, /* VULGAR FRACTION TWO THIRDS */ -{ XK_onefifth, 0x2155 }, /* VULGAR FRACTION ONE FIFTH */ -{ XK_twofifths, 0x2156 }, /* VULGAR FRACTION TWO FIFTHS */ -{ XK_threefifths, 0x2157 }, /* VULGAR FRACTION THREE FIFTHS */ -{ XK_fourfifths, 0x2158 }, /* VULGAR FRACTION FOUR FIFTHS */ -{ XK_onesixth, 0x2159 }, /* VULGAR FRACTION ONE SIXTH */ -{ XK_fivesixths, 0x215a }, /* VULGAR FRACTION FIVE SIXTHS */ -{ XK_careof, 0x2105 }, /* CARE OF */ -{ XK_figdash, 0x2012 }, /* FIGURE DASH */ -{ XK_leftanglebracket, 0x2329 }, /* LEFT-POINTING ANGLE BRACKET */ -/*{ XK_decimalpoint, ??? }, */ -{ XK_rightanglebracket, 0x232a }, /* RIGHT-POINTING ANGLE BRACKET */ -/*{ XK_marker, ??? }, */ -{ XK_oneeighth, 0x215b }, /* VULGAR FRACTION ONE EIGHTH */ -{ XK_threeeighths, 0x215c }, /* VULGAR FRACTION THREE EIGHTHS */ -{ XK_fiveeighths, 0x215d }, /* VULGAR FRACTION FIVE EIGHTHS */ -{ XK_seveneighths, 0x215e }, /* VULGAR FRACTION SEVEN EIGHTHS */ -{ XK_trademark, 0x2122 }, /* TRADE MARK SIGN */ -{ XK_signaturemark, 0x2613 }, /* SALTIRE */ -/*{ XK_trademarkincircle, ??? }, */ -{ XK_leftopentriangle, 0x25c1 }, /* WHITE LEFT-POINTING TRIANGLE */ -{ XK_rightopentriangle, 0x25b7 }, /* WHITE RIGHT-POINTING TRIANGLE */ -{ XK_emopencircle, 0x25cb }, /* WHITE CIRCLE */ -{ XK_emopenrectangle, 0x25af }, /* WHITE VERTICAL RECTANGLE */ -{ XK_leftsinglequotemark, 0x2018 }, /* LEFT SINGLE QUOTATION MARK */ -{ XK_rightsinglequotemark, 0x2019 }, /* RIGHT SINGLE QUOTATION MARK */ -{ XK_leftdoublequotemark, 0x201c }, /* LEFT DOUBLE QUOTATION MARK */ -{ XK_rightdoublequotemark, 0x201d }, /* RIGHT DOUBLE QUOTATION MARK */ -{ XK_prescription, 0x211e }, /* PRESCRIPTION TAKE */ -{ XK_minutes, 0x2032 }, /* PRIME */ -{ XK_seconds, 0x2033 }, /* DOUBLE PRIME */ -{ XK_latincross, 0x271d }, /* LATIN CROSS */ -/*{ XK_hexagram, ??? }, */ -{ XK_filledrectbullet, 0x25ac }, /* BLACK RECTANGLE */ -{ XK_filledlefttribullet, 0x25c0 }, /* BLACK LEFT-POINTING TRIANGLE */ -{ XK_filledrighttribullet, 0x25b6 }, /* BLACK RIGHT-POINTING TRIANGLE */ -{ XK_emfilledcircle, 0x25cf }, /* BLACK CIRCLE */ -{ XK_emfilledrect, 0x25ae }, /* BLACK VERTICAL RECTANGLE */ -{ XK_enopencircbullet, 0x25e6 }, /* WHITE BULLET */ -{ XK_enopensquarebullet, 0x25ab }, /* WHITE SMALL SQUARE */ -{ XK_openrectbullet, 0x25ad }, /* WHITE RECTANGLE */ -{ XK_opentribulletup, 0x25b3 }, /* WHITE UP-POINTING TRIANGLE */ -{ XK_opentribulletdown, 0x25bd }, /* WHITE DOWN-POINTING TRIANGLE */ -{ XK_openstar, 0x2606 }, /* WHITE STAR */ -{ XK_enfilledcircbullet, 0x2022 }, /* BULLET */ -{ XK_enfilledsqbullet, 0x25aa }, /* BLACK SMALL SQUARE */ -{ XK_filledtribulletup, 0x25b2 }, /* BLACK UP-POINTING TRIANGLE */ -{ XK_filledtribulletdown, 0x25bc }, /* BLACK DOWN-POINTING TRIANGLE */ -{ XK_leftpointer, 0x261c }, /* WHITE LEFT POINTING INDEX */ -{ XK_rightpointer, 0x261e }, /* WHITE RIGHT POINTING INDEX */ -{ XK_club, 0x2663 }, /* BLACK CLUB SUIT */ -{ XK_diamond, 0x2666 }, /* BLACK DIAMOND SUIT */ -{ XK_heart, 0x2665 }, /* BLACK HEART SUIT */ -{ XK_maltesecross, 0x2720 }, /* MALTESE CROSS */ -{ XK_dagger, 0x2020 }, /* DAGGER */ -{ XK_doubledagger, 0x2021 }, /* DOUBLE DAGGER */ -{ XK_checkmark, 0x2713 }, /* CHECK MARK */ -{ XK_ballotcross, 0x2717 }, /* BALLOT X */ -{ XK_musicalsharp, 0x266f }, /* MUSIC SHARP SIGN */ -{ XK_musicalflat, 0x266d }, /* MUSIC FLAT SIGN */ -{ XK_malesymbol, 0x2642 }, /* MALE SIGN */ -{ XK_femalesymbol, 0x2640 }, /* FEMALE SIGN */ -{ XK_telephone, 0x260e }, /* BLACK TELEPHONE */ -{ XK_telephonerecorder, 0x2315 }, /* TELEPHONE RECORDER */ -{ XK_phonographcopyright, 0x2117 }, /* SOUND RECORDING COPYRIGHT */ -{ XK_caret, 0x2038 }, /* CARET */ -{ XK_singlelowquotemark, 0x201a }, /* SINGLE LOW-9 QUOTATION MARK */ -{ XK_doublelowquotemark, 0x201e }, /* DOUBLE LOW-9 QUOTATION MARK */ -/*{ XK_cursor, ??? }, */ -{ XK_leftcaret, 0x003c }, /* LESS-THAN SIGN */ -{ XK_rightcaret, 0x003e }, /* GREATER-THAN SIGN */ -{ XK_downcaret, 0x2228 }, /* LOGICAL OR */ -{ XK_upcaret, 0x2227 }, /* LOGICAL AND */ -{ XK_overbar, 0x00af }, /* MACRON */ -{ XK_downtack, 0x22a5 }, /* UP TACK */ -{ XK_upshoe, 0x2229 }, /* INTERSECTION */ -{ XK_downstile, 0x230a }, /* LEFT FLOOR */ -{ XK_underbar, 0x005f }, /* LOW LINE */ -{ XK_jot, 0x2218 }, /* RING OPERATOR */ -{ XK_quad, 0x2395 }, /* APL FUNCTIONAL SYMBOL QUAD */ -{ XK_uptack, 0x22a4 }, /* DOWN TACK */ -{ XK_circle, 0x25cb }, /* WHITE CIRCLE */ -{ XK_upstile, 0x2308 }, /* LEFT CEILING */ -{ XK_downshoe, 0x222a }, /* UNION */ -{ XK_rightshoe, 0x2283 }, /* SUPERSET OF */ -{ XK_leftshoe, 0x2282 }, /* SUBSET OF */ -{ XK_lefttack, 0x22a2 }, /* RIGHT TACK */ -{ XK_righttack, 0x22a3 }, /* LEFT TACK */ -#if defined(XK_hebrew_doublelowline) -{ XK_hebrew_doublelowline, 0x2017 }, /* DOUBLE LOW LINE */ -{ XK_hebrew_aleph, 0x05d0 }, /* HEBREW LETTER ALEF */ -{ XK_hebrew_bet, 0x05d1 }, /* HEBREW LETTER BET */ -{ XK_hebrew_gimel, 0x05d2 }, /* HEBREW LETTER GIMEL */ -{ XK_hebrew_dalet, 0x05d3 }, /* HEBREW LETTER DALET */ -{ XK_hebrew_he, 0x05d4 }, /* HEBREW LETTER HE */ -{ XK_hebrew_waw, 0x05d5 }, /* HEBREW LETTER VAV */ -{ XK_hebrew_zain, 0x05d6 }, /* HEBREW LETTER ZAYIN */ -{ XK_hebrew_chet, 0x05d7 }, /* HEBREW LETTER HET */ -{ XK_hebrew_tet, 0x05d8 }, /* HEBREW LETTER TET */ -{ XK_hebrew_yod, 0x05d9 }, /* HEBREW LETTER YOD */ -{ XK_hebrew_finalkaph, 0x05da }, /* HEBREW LETTER FINAL KAF */ -{ XK_hebrew_kaph, 0x05db }, /* HEBREW LETTER KAF */ -{ XK_hebrew_lamed, 0x05dc }, /* HEBREW LETTER LAMED */ -{ XK_hebrew_finalmem, 0x05dd }, /* HEBREW LETTER FINAL MEM */ -{ XK_hebrew_mem, 0x05de }, /* HEBREW LETTER MEM */ -{ XK_hebrew_finalnun, 0x05df }, /* HEBREW LETTER FINAL NUN */ -{ XK_hebrew_nun, 0x05e0 }, /* HEBREW LETTER NUN */ -{ XK_hebrew_samech, 0x05e1 }, /* HEBREW LETTER SAMEKH */ -{ XK_hebrew_ayin, 0x05e2 }, /* HEBREW LETTER AYIN */ -{ XK_hebrew_finalpe, 0x05e3 }, /* HEBREW LETTER FINAL PE */ -{ XK_hebrew_pe, 0x05e4 }, /* HEBREW LETTER PE */ -{ XK_hebrew_finalzade, 0x05e5 }, /* HEBREW LETTER FINAL TSADI */ -{ XK_hebrew_zade, 0x05e6 }, /* HEBREW LETTER TSADI */ -{ XK_hebrew_qoph, 0x05e7 }, /* HEBREW LETTER QOF */ -{ XK_hebrew_resh, 0x05e8 }, /* HEBREW LETTER RESH */ -{ XK_hebrew_shin, 0x05e9 }, /* HEBREW LETTER SHIN */ -{ XK_hebrew_taw, 0x05ea }, /* HEBREW LETTER TAV */ -#endif // defined(XK_hebrew_doublelowline) -#if defined(XK_Thai_kokai) -{ XK_Thai_kokai, 0x0e01 }, /* THAI CHARACTER KO KAI */ -{ XK_Thai_khokhai, 0x0e02 }, /* THAI CHARACTER KHO KHAI */ -{ XK_Thai_khokhuat, 0x0e03 }, /* THAI CHARACTER KHO KHUAT */ -{ XK_Thai_khokhwai, 0x0e04 }, /* THAI CHARACTER KHO KHWAI */ -{ XK_Thai_khokhon, 0x0e05 }, /* THAI CHARACTER KHO KHON */ -{ XK_Thai_khorakhang, 0x0e06 }, /* THAI CHARACTER KHO RAKHANG */ -{ XK_Thai_ngongu, 0x0e07 }, /* THAI CHARACTER NGO NGU */ -{ XK_Thai_chochan, 0x0e08 }, /* THAI CHARACTER CHO CHAN */ -{ XK_Thai_choching, 0x0e09 }, /* THAI CHARACTER CHO CHING */ -{ XK_Thai_chochang, 0x0e0a }, /* THAI CHARACTER CHO CHANG */ -{ XK_Thai_soso, 0x0e0b }, /* THAI CHARACTER SO SO */ -{ XK_Thai_chochoe, 0x0e0c }, /* THAI CHARACTER CHO CHOE */ -{ XK_Thai_yoying, 0x0e0d }, /* THAI CHARACTER YO YING */ -{ XK_Thai_dochada, 0x0e0e }, /* THAI CHARACTER DO CHADA */ -{ XK_Thai_topatak, 0x0e0f }, /* THAI CHARACTER TO PATAK */ -{ XK_Thai_thothan, 0x0e10 }, /* THAI CHARACTER THO THAN */ -{ XK_Thai_thonangmontho, 0x0e11 }, /* THAI CHARACTER THO NANGMONTHO */ -{ XK_Thai_thophuthao, 0x0e12 }, /* THAI CHARACTER THO PHUTHAO */ -{ XK_Thai_nonen, 0x0e13 }, /* THAI CHARACTER NO NEN */ -{ XK_Thai_dodek, 0x0e14 }, /* THAI CHARACTER DO DEK */ -{ XK_Thai_totao, 0x0e15 }, /* THAI CHARACTER TO TAO */ -{ XK_Thai_thothung, 0x0e16 }, /* THAI CHARACTER THO THUNG */ -{ XK_Thai_thothahan, 0x0e17 }, /* THAI CHARACTER THO THAHAN */ -{ XK_Thai_thothong, 0x0e18 }, /* THAI CHARACTER THO THONG */ -{ XK_Thai_nonu, 0x0e19 }, /* THAI CHARACTER NO NU */ -{ XK_Thai_bobaimai, 0x0e1a }, /* THAI CHARACTER BO BAIMAI */ -{ XK_Thai_popla, 0x0e1b }, /* THAI CHARACTER PO PLA */ -{ XK_Thai_phophung, 0x0e1c }, /* THAI CHARACTER PHO PHUNG */ -{ XK_Thai_fofa, 0x0e1d }, /* THAI CHARACTER FO FA */ -{ XK_Thai_phophan, 0x0e1e }, /* THAI CHARACTER PHO PHAN */ -{ XK_Thai_fofan, 0x0e1f }, /* THAI CHARACTER FO FAN */ -{ XK_Thai_phosamphao, 0x0e20 }, /* THAI CHARACTER PHO SAMPHAO */ -{ XK_Thai_moma, 0x0e21 }, /* THAI CHARACTER MO MA */ -{ XK_Thai_yoyak, 0x0e22 }, /* THAI CHARACTER YO YAK */ -{ XK_Thai_rorua, 0x0e23 }, /* THAI CHARACTER RO RUA */ -{ XK_Thai_ru, 0x0e24 }, /* THAI CHARACTER RU */ -{ XK_Thai_loling, 0x0e25 }, /* THAI CHARACTER LO LING */ -{ XK_Thai_lu, 0x0e26 }, /* THAI CHARACTER LU */ -{ XK_Thai_wowaen, 0x0e27 }, /* THAI CHARACTER WO WAEN */ -{ XK_Thai_sosala, 0x0e28 }, /* THAI CHARACTER SO SALA */ -{ XK_Thai_sorusi, 0x0e29 }, /* THAI CHARACTER SO RUSI */ -{ XK_Thai_sosua, 0x0e2a }, /* THAI CHARACTER SO SUA */ -{ XK_Thai_hohip, 0x0e2b }, /* THAI CHARACTER HO HIP */ -{ XK_Thai_lochula, 0x0e2c }, /* THAI CHARACTER LO CHULA */ -{ XK_Thai_oang, 0x0e2d }, /* THAI CHARACTER O ANG */ -{ XK_Thai_honokhuk, 0x0e2e }, /* THAI CHARACTER HO NOKHUK */ -{ XK_Thai_paiyannoi, 0x0e2f }, /* THAI CHARACTER PAIYANNOI */ -{ XK_Thai_saraa, 0x0e30 }, /* THAI CHARACTER SARA A */ -{ XK_Thai_maihanakat, 0x0e31 }, /* THAI CHARACTER MAI HAN-AKAT */ -{ XK_Thai_saraaa, 0x0e32 }, /* THAI CHARACTER SARA AA */ -{ XK_Thai_saraam, 0x0e33 }, /* THAI CHARACTER SARA AM */ -{ XK_Thai_sarai, 0x0e34 }, /* THAI CHARACTER SARA I */ -{ XK_Thai_saraii, 0x0e35 }, /* THAI CHARACTER SARA II */ -{ XK_Thai_saraue, 0x0e36 }, /* THAI CHARACTER SARA UE */ -{ XK_Thai_sarauee, 0x0e37 }, /* THAI CHARACTER SARA UEE */ -{ XK_Thai_sarau, 0x0e38 }, /* THAI CHARACTER SARA U */ -{ XK_Thai_sarauu, 0x0e39 }, /* THAI CHARACTER SARA UU */ -{ XK_Thai_phinthu, 0x0e3a }, /* THAI CHARACTER PHINTHU */ -/*{ XK_Thai_maihanakat_maitho, ??? }, */ -{ XK_Thai_baht, 0x0e3f }, /* THAI CURRENCY SYMBOL BAHT */ -{ XK_Thai_sarae, 0x0e40 }, /* THAI CHARACTER SARA E */ -{ XK_Thai_saraae, 0x0e41 }, /* THAI CHARACTER SARA AE */ -{ XK_Thai_sarao, 0x0e42 }, /* THAI CHARACTER SARA O */ -{ XK_Thai_saraaimaimuan, 0x0e43 }, /* THAI CHARACTER SARA AI MAIMUAN */ -{ XK_Thai_saraaimaimalai, 0x0e44 }, /* THAI CHARACTER SARA AI MAIMALAI */ -{ XK_Thai_lakkhangyao, 0x0e45 }, /* THAI CHARACTER LAKKHANGYAO */ -{ XK_Thai_maiyamok, 0x0e46 }, /* THAI CHARACTER MAIYAMOK */ -{ XK_Thai_maitaikhu, 0x0e47 }, /* THAI CHARACTER MAITAIKHU */ -{ XK_Thai_maiek, 0x0e48 }, /* THAI CHARACTER MAI EK */ -{ XK_Thai_maitho, 0x0e49 }, /* THAI CHARACTER MAI THO */ -{ XK_Thai_maitri, 0x0e4a }, /* THAI CHARACTER MAI TRI */ -{ XK_Thai_maichattawa, 0x0e4b }, /* THAI CHARACTER MAI CHATTAWA */ -{ XK_Thai_thanthakhat, 0x0e4c }, /* THAI CHARACTER THANTHAKHAT */ -{ XK_Thai_nikhahit, 0x0e4d }, /* THAI CHARACTER NIKHAHIT */ -{ XK_Thai_leksun, 0x0e50 }, /* THAI DIGIT ZERO */ -{ XK_Thai_leknung, 0x0e51 }, /* THAI DIGIT ONE */ -{ XK_Thai_leksong, 0x0e52 }, /* THAI DIGIT TWO */ -{ XK_Thai_leksam, 0x0e53 }, /* THAI DIGIT THREE */ -{ XK_Thai_leksi, 0x0e54 }, /* THAI DIGIT FOUR */ -{ XK_Thai_lekha, 0x0e55 }, /* THAI DIGIT FIVE */ -{ XK_Thai_lekhok, 0x0e56 }, /* THAI DIGIT SIX */ -{ XK_Thai_lekchet, 0x0e57 }, /* THAI DIGIT SEVEN */ -{ XK_Thai_lekpaet, 0x0e58 }, /* THAI DIGIT EIGHT */ -{ XK_Thai_lekkao, 0x0e59 }, /* THAI DIGIT NINE */ -#endif // defined(XK_Thai_kokai) -#if defined(XK_Hangul_Kiyeog) -{ XK_Hangul_Kiyeog, 0x3131 }, /* HANGUL LETTER KIYEOK */ -{ XK_Hangul_SsangKiyeog, 0x3132 }, /* HANGUL LETTER SSANGKIYEOK */ -{ XK_Hangul_KiyeogSios, 0x3133 }, /* HANGUL LETTER KIYEOK-SIOS */ -{ XK_Hangul_Nieun, 0x3134 }, /* HANGUL LETTER NIEUN */ -{ XK_Hangul_NieunJieuj, 0x3135 }, /* HANGUL LETTER NIEUN-CIEUC */ -{ XK_Hangul_NieunHieuh, 0x3136 }, /* HANGUL LETTER NIEUN-HIEUH */ -{ XK_Hangul_Dikeud, 0x3137 }, /* HANGUL LETTER TIKEUT */ -{ XK_Hangul_SsangDikeud, 0x3138 }, /* HANGUL LETTER SSANGTIKEUT */ -{ XK_Hangul_Rieul, 0x3139 }, /* HANGUL LETTER RIEUL */ -{ XK_Hangul_RieulKiyeog, 0x313a }, /* HANGUL LETTER RIEUL-KIYEOK */ -{ XK_Hangul_RieulMieum, 0x313b }, /* HANGUL LETTER RIEUL-MIEUM */ -{ XK_Hangul_RieulPieub, 0x313c }, /* HANGUL LETTER RIEUL-PIEUP */ -{ XK_Hangul_RieulSios, 0x313d }, /* HANGUL LETTER RIEUL-SIOS */ -{ XK_Hangul_RieulTieut, 0x313e }, /* HANGUL LETTER RIEUL-THIEUTH */ -{ XK_Hangul_RieulPhieuf, 0x313f }, /* HANGUL LETTER RIEUL-PHIEUPH */ -{ XK_Hangul_RieulHieuh, 0x3140 }, /* HANGUL LETTER RIEUL-HIEUH */ -{ XK_Hangul_Mieum, 0x3141 }, /* HANGUL LETTER MIEUM */ -{ XK_Hangul_Pieub, 0x3142 }, /* HANGUL LETTER PIEUP */ -{ XK_Hangul_SsangPieub, 0x3143 }, /* HANGUL LETTER SSANGPIEUP */ -{ XK_Hangul_PieubSios, 0x3144 }, /* HANGUL LETTER PIEUP-SIOS */ -{ XK_Hangul_Sios, 0x3145 }, /* HANGUL LETTER SIOS */ -{ XK_Hangul_SsangSios, 0x3146 }, /* HANGUL LETTER SSANGSIOS */ -{ XK_Hangul_Ieung, 0x3147 }, /* HANGUL LETTER IEUNG */ -{ XK_Hangul_Jieuj, 0x3148 }, /* HANGUL LETTER CIEUC */ -{ XK_Hangul_SsangJieuj, 0x3149 }, /* HANGUL LETTER SSANGCIEUC */ -{ XK_Hangul_Cieuc, 0x314a }, /* HANGUL LETTER CHIEUCH */ -{ XK_Hangul_Khieuq, 0x314b }, /* HANGUL LETTER KHIEUKH */ -{ XK_Hangul_Tieut, 0x314c }, /* HANGUL LETTER THIEUTH */ -{ XK_Hangul_Phieuf, 0x314d }, /* HANGUL LETTER PHIEUPH */ -{ XK_Hangul_Hieuh, 0x314e }, /* HANGUL LETTER HIEUH */ -{ XK_Hangul_A, 0x314f }, /* HANGUL LETTER A */ -{ XK_Hangul_AE, 0x3150 }, /* HANGUL LETTER AE */ -{ XK_Hangul_YA, 0x3151 }, /* HANGUL LETTER YA */ -{ XK_Hangul_YAE, 0x3152 }, /* HANGUL LETTER YAE */ -{ XK_Hangul_EO, 0x3153 }, /* HANGUL LETTER EO */ -{ XK_Hangul_E, 0x3154 }, /* HANGUL LETTER E */ -{ XK_Hangul_YEO, 0x3155 }, /* HANGUL LETTER YEO */ -{ XK_Hangul_YE, 0x3156 }, /* HANGUL LETTER YE */ -{ XK_Hangul_O, 0x3157 }, /* HANGUL LETTER O */ -{ XK_Hangul_WA, 0x3158 }, /* HANGUL LETTER WA */ -{ XK_Hangul_WAE, 0x3159 }, /* HANGUL LETTER WAE */ -{ XK_Hangul_OE, 0x315a }, /* HANGUL LETTER OE */ -{ XK_Hangul_YO, 0x315b }, /* HANGUL LETTER YO */ -{ XK_Hangul_U, 0x315c }, /* HANGUL LETTER U */ -{ XK_Hangul_WEO, 0x315d }, /* HANGUL LETTER WEO */ -{ XK_Hangul_WE, 0x315e }, /* HANGUL LETTER WE */ -{ XK_Hangul_WI, 0x315f }, /* HANGUL LETTER WI */ -{ XK_Hangul_YU, 0x3160 }, /* HANGUL LETTER YU */ -{ XK_Hangul_EU, 0x3161 }, /* HANGUL LETTER EU */ -{ XK_Hangul_YI, 0x3162 }, /* HANGUL LETTER YI */ -{ XK_Hangul_I, 0x3163 }, /* HANGUL LETTER I */ -{ XK_Hangul_J_Kiyeog, 0x11a8 }, /* HANGUL JONGSEONG KIYEOK */ -{ XK_Hangul_J_SsangKiyeog, 0x11a9 }, /* HANGUL JONGSEONG SSANGKIYEOK */ -{ XK_Hangul_J_KiyeogSios, 0x11aa }, /* HANGUL JONGSEONG KIYEOK-SIOS */ -{ XK_Hangul_J_Nieun, 0x11ab }, /* HANGUL JONGSEONG NIEUN */ -{ XK_Hangul_J_NieunJieuj, 0x11ac }, /* HANGUL JONGSEONG NIEUN-CIEUC */ -{ XK_Hangul_J_NieunHieuh, 0x11ad }, /* HANGUL JONGSEONG NIEUN-HIEUH */ -{ XK_Hangul_J_Dikeud, 0x11ae }, /* HANGUL JONGSEONG TIKEUT */ -{ XK_Hangul_J_Rieul, 0x11af }, /* HANGUL JONGSEONG RIEUL */ -{ XK_Hangul_J_RieulKiyeog, 0x11b0 }, /* HANGUL JONGSEONG RIEUL-KIYEOK */ -{ XK_Hangul_J_RieulMieum, 0x11b1 }, /* HANGUL JONGSEONG RIEUL-MIEUM */ -{ XK_Hangul_J_RieulPieub, 0x11b2 }, /* HANGUL JONGSEONG RIEUL-PIEUP */ -{ XK_Hangul_J_RieulSios, 0x11b3 }, /* HANGUL JONGSEONG RIEUL-SIOS */ -{ XK_Hangul_J_RieulTieut, 0x11b4 }, /* HANGUL JONGSEONG RIEUL-THIEUTH */ -{ XK_Hangul_J_RieulPhieuf, 0x11b5 }, /* HANGUL JONGSEONG RIEUL-PHIEUPH */ -{ XK_Hangul_J_RieulHieuh, 0x11b6 }, /* HANGUL JONGSEONG RIEUL-HIEUH */ -{ XK_Hangul_J_Mieum, 0x11b7 }, /* HANGUL JONGSEONG MIEUM */ -{ XK_Hangul_J_Pieub, 0x11b8 }, /* HANGUL JONGSEONG PIEUP */ -{ XK_Hangul_J_PieubSios, 0x11b9 }, /* HANGUL JONGSEONG PIEUP-SIOS */ -{ XK_Hangul_J_Sios, 0x11ba }, /* HANGUL JONGSEONG SIOS */ -{ XK_Hangul_J_SsangSios, 0x11bb }, /* HANGUL JONGSEONG SSANGSIOS */ -{ XK_Hangul_J_Ieung, 0x11bc }, /* HANGUL JONGSEONG IEUNG */ -{ XK_Hangul_J_Jieuj, 0x11bd }, /* HANGUL JONGSEONG CIEUC */ -{ XK_Hangul_J_Cieuc, 0x11be }, /* HANGUL JONGSEONG CHIEUCH */ -{ XK_Hangul_J_Khieuq, 0x11bf }, /* HANGUL JONGSEONG KHIEUKH */ -{ XK_Hangul_J_Tieut, 0x11c0 }, /* HANGUL JONGSEONG THIEUTH */ -{ XK_Hangul_J_Phieuf, 0x11c1 }, /* HANGUL JONGSEONG PHIEUPH */ -{ XK_Hangul_J_Hieuh, 0x11c2 }, /* HANGUL JONGSEONG HIEUH */ -{ XK_Hangul_RieulYeorinHieuh, 0x316d }, /* HANGUL LETTER RIEUL-YEORINHIEUH */ -{ XK_Hangul_SunkyeongeumMieum, 0x3171 }, /* HANGUL LETTER KAPYEOUNMIEUM */ -{ XK_Hangul_SunkyeongeumPieub, 0x3178 }, /* HANGUL LETTER KAPYEOUNPIEUP */ -{ XK_Hangul_PanSios, 0x317f }, /* HANGUL LETTER PANSIOS */ -{ XK_Hangul_KkogjiDalrinIeung, 0x3181 }, /* HANGUL LETTER YESIEUNG */ -{ XK_Hangul_SunkyeongeumPhieuf, 0x3184 }, /* HANGUL LETTER KAPYEOUNPHIEUPH */ -{ XK_Hangul_YeorinHieuh, 0x3186 }, /* HANGUL LETTER YEORINHIEUH */ -{ XK_Hangul_AraeA, 0x318d }, /* HANGUL LETTER ARAEA */ -{ XK_Hangul_AraeAE, 0x318e }, /* HANGUL LETTER ARAEAE */ -{ XK_Hangul_J_PanSios, 0x11eb }, /* HANGUL JONGSEONG PANSIOS */ -{ XK_Hangul_J_KkogjiDalrinIeung, 0x11f0 }, /* HANGUL JONGSEONG YESIEUNG */ -{ XK_Hangul_J_YeorinHieuh, 0x11f9 }, /* HANGUL JONGSEONG YEORINHIEUH */ -{ XK_Korean_Won, 0x20a9 }, /* WON SIGN */ -#endif // defined(XK_Hangul_Kiyeog) -{ XK_OE, 0x0152 }, /* LATIN CAPITAL LIGATURE OE */ -{ XK_oe, 0x0153 }, /* LATIN SMALL LIGATURE OE */ -{ XK_Ydiaeresis, 0x0178 }, /* LATIN CAPITAL LETTER Y WITH DIAERESIS */ -{ XK_EuroSign, 0x20ac }, /* EURO SIGN */ - -/* combining dead keys */ -{ XK_dead_abovedot, 0x0307 }, /* COMBINING DOT ABOVE */ -{ XK_dead_abovering, 0x030a }, /* COMBINING RING ABOVE */ -{ XK_dead_acute, 0x0301 }, /* COMBINING ACUTE ACCENT */ -{ XK_dead_breve, 0x0306 }, /* COMBINING BREVE */ -{ XK_dead_caron, 0x030c }, /* COMBINING CARON */ -{ XK_dead_cedilla, 0x0327 }, /* COMBINING CEDILLA */ -{ XK_dead_circumflex, 0x0302 }, /* COMBINING CIRCUMFLEX ACCENT */ -{ XK_dead_diaeresis, 0x0308 }, /* COMBINING DIAERESIS */ -{ XK_dead_doubleacute, 0x030b }, /* COMBINING DOUBLE ACUTE ACCENT */ -{ XK_dead_grave, 0x0300 }, /* COMBINING GRAVE ACCENT */ -{ XK_dead_macron, 0x0304 }, /* COMBINING MACRON */ -{ XK_dead_ogonek, 0x0328 }, /* COMBINING OGONEK */ -{ XK_dead_tilde, 0x0303 } /* COMBINING TILDE */ -}; -/* XXX -- map these too -XK_Cyrillic_GHE_bar -XK_Cyrillic_ZHE_descender -XK_Cyrillic_KA_descender -XK_Cyrillic_KA_vertstroke -XK_Cyrillic_EN_descender -XK_Cyrillic_U_straight -XK_Cyrillic_U_straight_bar -XK_Cyrillic_HA_descender -XK_Cyrillic_CHE_descender -XK_Cyrillic_CHE_vertstroke -XK_Cyrillic_SHHA -XK_Cyrillic_SCHWA -XK_Cyrillic_I_macron -XK_Cyrillic_O_bar -XK_Cyrillic_U_macron -XK_Cyrillic_ghe_bar -XK_Cyrillic_zhe_descender -XK_Cyrillic_ka_descender -XK_Cyrillic_ka_vertstroke -XK_Cyrillic_en_descender -XK_Cyrillic_u_straight -XK_Cyrillic_u_straight_bar -XK_Cyrillic_ha_descender -XK_Cyrillic_che_descender -XK_Cyrillic_che_vertstroke -XK_Cyrillic_shha -XK_Cyrillic_schwa -XK_Cyrillic_i_macron -XK_Cyrillic_o_bar -XK_Cyrillic_u_macron - -XK_Armenian_eternity -XK_Armenian_ligature_ew -XK_Armenian_full_stop -XK_Armenian_verjaket -XK_Armenian_parenright -XK_Armenian_parenleft -XK_Armenian_guillemotright -XK_Armenian_guillemotleft -XK_Armenian_em_dash -XK_Armenian_dot -XK_Armenian_mijaket -XK_Armenian_but -XK_Armenian_separation_mark -XK_Armenian_comma -XK_Armenian_en_dash -XK_Armenian_hyphen -XK_Armenian_yentamna -XK_Armenian_ellipsis -XK_Armenian_amanak -XK_Armenian_exclam -XK_Armenian_accent -XK_Armenian_shesht -XK_Armenian_paruyk -XK_Armenian_question -XK_Armenian_AYB -XK_Armenian_ayb -XK_Armenian_BEN -XK_Armenian_ben -XK_Armenian_GIM -XK_Armenian_gim -XK_Armenian_DA -XK_Armenian_da -XK_Armenian_YECH -XK_Armenian_yech -XK_Armenian_ZA -XK_Armenian_za -XK_Armenian_E -XK_Armenian_e -XK_Armenian_AT -XK_Armenian_at -XK_Armenian_TO -XK_Armenian_to -XK_Armenian_ZHE -XK_Armenian_zhe -XK_Armenian_INI -XK_Armenian_ini -XK_Armenian_LYUN -XK_Armenian_lyun -XK_Armenian_KHE -XK_Armenian_khe -XK_Armenian_TSA -XK_Armenian_tsa -XK_Armenian_KEN -XK_Armenian_ken -XK_Armenian_HO -XK_Armenian_ho -XK_Armenian_DZA -XK_Armenian_dza -XK_Armenian_GHAT -XK_Armenian_ghat -XK_Armenian_TCHE -XK_Armenian_tche -XK_Armenian_MEN -XK_Armenian_men -XK_Armenian_HI -XK_Armenian_hi -XK_Armenian_NU -XK_Armenian_nu -XK_Armenian_SHA -XK_Armenian_sha -XK_Armenian_VO -XK_Armenian_vo -XK_Armenian_CHA -XK_Armenian_cha -XK_Armenian_PE -XK_Armenian_pe -XK_Armenian_JE -XK_Armenian_je -XK_Armenian_RA -XK_Armenian_ra -XK_Armenian_SE -XK_Armenian_se -XK_Armenian_VEV -XK_Armenian_vev -XK_Armenian_TYUN -XK_Armenian_tyun -XK_Armenian_RE -XK_Armenian_re -XK_Armenian_TSO -XK_Armenian_tso -XK_Armenian_VYUN -XK_Armenian_vyun -XK_Armenian_PYUR -XK_Armenian_pyur -XK_Armenian_KE -XK_Armenian_ke -XK_Armenian_O -XK_Armenian_o -XK_Armenian_FE -XK_Armenian_fe -XK_Armenian_apostrophe -XK_Armenian_section_sign - -XK_Georgian_an -XK_Georgian_ban -XK_Georgian_gan -XK_Georgian_don -XK_Georgian_en -XK_Georgian_vin -XK_Georgian_zen -XK_Georgian_tan -XK_Georgian_in -XK_Georgian_kan -XK_Georgian_las -XK_Georgian_man -XK_Georgian_nar -XK_Georgian_on -XK_Georgian_par -XK_Georgian_zhar -XK_Georgian_rae -XK_Georgian_san -XK_Georgian_tar -XK_Georgian_un -XK_Georgian_phar -XK_Georgian_khar -XK_Georgian_ghan -XK_Georgian_qar -XK_Georgian_shin -XK_Georgian_chin -XK_Georgian_can -XK_Georgian_jil -XK_Georgian_cil -XK_Georgian_char -XK_Georgian_xan -XK_Georgian_jhan -XK_Georgian_hae -XK_Georgian_he -XK_Georgian_hie -XK_Georgian_we -XK_Georgian_har -XK_Georgian_hoe -XK_Georgian_fi - -XK_Ccedillaabovedot -XK_Xabovedot -XK_Qabovedot -XK_Ibreve -XK_IE -XK_UO -XK_Zstroke -XK_Gcaron -XK_Obarred -XK_ccedillaabovedot -XK_xabovedot -XK_Ocaron -XK_qabovedot -XK_ibreve -XK_ie -XK_uo -XK_zstroke -XK_gcaron -XK_ocaron -XK_obarred -XK_SCHWA -XK_Lbelowdot -XK_Lstrokebelowdot -XK_Gtilde -XK_lbelowdot -XK_lstrokebelowdot -XK_gtilde -XK_schwa - -XK_Abelowdot -XK_abelowdot -XK_Ahook -XK_ahook -XK_Acircumflexacute -XK_acircumflexacute -XK_Acircumflexgrave -XK_acircumflexgrave -XK_Acircumflexhook -XK_acircumflexhook -XK_Acircumflextilde -XK_acircumflextilde -XK_Acircumflexbelowdot -XK_acircumflexbelowdot -XK_Abreveacute -XK_abreveacute -XK_Abrevegrave -XK_abrevegrave -XK_Abrevehook -XK_abrevehook -XK_Abrevetilde -XK_abrevetilde -XK_Abrevebelowdot -XK_abrevebelowdot -XK_Ebelowdot -XK_ebelowdot -XK_Ehook -XK_ehook -XK_Etilde -XK_etilde -XK_Ecircumflexacute -XK_ecircumflexacute -XK_Ecircumflexgrave -XK_ecircumflexgrave -XK_Ecircumflexhook -XK_ecircumflexhook -XK_Ecircumflextilde -XK_ecircumflextilde -XK_Ecircumflexbelowdot -XK_ecircumflexbelowdot -XK_Ihook -XK_ihook -XK_Ibelowdot -XK_ibelowdot -XK_Obelowdot -XK_obelowdot -XK_Ohook -XK_ohook -XK_Ocircumflexacute -XK_ocircumflexacute -XK_Ocircumflexgrave -XK_ocircumflexgrave -XK_Ocircumflexhook -XK_ocircumflexhook -XK_Ocircumflextilde -XK_ocircumflextilde -XK_Ocircumflexbelowdot -XK_ocircumflexbelowdot -XK_Ohornacute -XK_ohornacute -XK_Ohorngrave -XK_ohorngrave -XK_Ohornhook -XK_ohornhook -XK_Ohorntilde -XK_ohorntilde -XK_Ohornbelowdot -XK_ohornbelowdot -XK_Ubelowdot -XK_ubelowdot -XK_Uhook -XK_uhook -XK_Uhornacute -XK_uhornacute -XK_Uhorngrave -XK_uhorngrave -XK_Uhornhook -XK_uhornhook -XK_Uhorntilde -XK_uhorntilde -XK_Uhornbelowdot -XK_uhornbelowdot -XK_Ybelowdot -XK_ybelowdot -XK_Yhook -XK_yhook -XK_Ytilde -XK_ytilde -XK_Ohorn -XK_ohorn -XK_Uhorn -XK_uhorn -*/ - -// map "Internet" keys to KeyIDs -static const KeySym s_map1008FF[] = -{ - /* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x08 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x10 */ 0, kKeyAudioDown, kKeyAudioMute, kKeyAudioUp, - /* 0x14 */ kKeyAudioPlay, kKeyAudioStop, kKeyAudioPrev, kKeyAudioNext, - /* 0x18 */ kKeyWWWHome, kKeyAppMail, 0, kKeyWWWSearch, 0, 0, 0, 0, - /* 0x20 */ 0, 0, 0, 0, 0, 0, kKeyWWWBack, kKeyWWWForward, - /* 0x28 */ kKeyWWWStop, kKeyWWWRefresh, 0, 0, kKeyEject, 0, 0, 0, - /* 0x30 */ kKeyWWWFavorites, 0, kKeyAppMedia, 0, 0, 0, 0, 0, - /* 0x38 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x40 */ kKeyAppUser1, kKeyAppUser2, 0, 0, 0, 0, 0, 0, - /* 0x48 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x50 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x58 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x60 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x68 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x70 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x78 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x80 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x88 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x90 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 0x98 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 0xa0 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 0xa8 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 0xb0 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 0xb8 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 0xc0 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 0xc8 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 0xd0 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 0xd8 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 0xe0 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 0xe8 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 0xf0 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* 0xf8 */ 0, 0, 0, 0, 0, 0, 0, 0 -}; - - -// -// CXWindowsUtil -// - -CXWindowsUtil::CKeySymMap CXWindowsUtil::s_keySymToUCS4; - -bool -CXWindowsUtil::getWindowProperty(Display* display, Window window, - Atom property, CString* data, Atom* type, - SInt32* format, bool deleteProperty) -{ - assert(display != NULL); - - Atom actualType; - int actualDatumSize; - - // ignore errors. XGetWindowProperty() will report failure. - CXWindowsUtil::CErrorLock lock(display); - - // read the property - bool okay = true; - const long length = XMaxRequestSize(display); - long offset = 0; - unsigned long bytesLeft = 1; - while (bytesLeft != 0) { - // get more data - unsigned long numItems; - unsigned char* rawData; - if (XGetWindowProperty(display, window, property, - offset, length, False, AnyPropertyType, - &actualType, &actualDatumSize, - &numItems, &bytesLeft, &rawData) != Success || - actualType == None || actualDatumSize == 0) { - // failed - okay = false; - break; - } - - // compute bytes read and advance offset - unsigned long numBytes; - switch (actualDatumSize) { - case 8: - default: - numBytes = numItems; - offset += numItems / 4; - break; - - case 16: - numBytes = 2 * numItems; - offset += numItems / 2; - break; - - case 32: - numBytes = 4 * numItems; - offset += numItems; - break; - } - - // append data - if (data != NULL) { - data->append((char*)rawData, numBytes); - } - else { - // data is not required so don't try to get any more - bytesLeft = 0; - } - - // done with returned data - XFree(rawData); - } - - // delete the property if requested - if (deleteProperty) { - XDeleteProperty(display, window, property); - } - - // save property info - if (type != NULL) { - *type = actualType; - } - if (format != NULL) { - *format = static_cast(actualDatumSize); - } - - if (okay) { - LOG((CLOG_DEBUG2 "read property %d on window 0x%08x: bytes=%d", property, window, (data == NULL) ? 0 : data->size())); - return true; - } - else { - LOG((CLOG_DEBUG2 "can't read property %d on window 0x%08x", property, window)); - return false; - } -} - -bool -CXWindowsUtil::setWindowProperty(Display* display, Window window, - Atom property, const void* vdata, UInt32 size, - Atom type, SInt32 format) -{ - const UInt32 length = 4 * XMaxRequestSize(display); - const unsigned char* data = reinterpret_cast(vdata); - const UInt32 datumSize = static_cast(format / 8); - - // save errors - bool error = false; - CXWindowsUtil::CErrorLock lock(display, &error); - - // how much data to send in first chunk? - UInt32 chunkSize = size; - if (chunkSize > length) { - chunkSize = length; - } - - // send first chunk - XChangeProperty(display, window, property, - type, format, PropModeReplace, - data, chunkSize / datumSize); - - // append remaining chunks - data += chunkSize; - size -= chunkSize; - while (!error && size > 0) { - chunkSize = size; - if (chunkSize > length) { - chunkSize = length; - } - XChangeProperty(display, window, property, - type, format, PropModeAppend, - data, chunkSize / datumSize); - data += chunkSize; - size -= chunkSize; - } - - return !error; -} - -Time -CXWindowsUtil::getCurrentTime(Display* display, Window window) -{ - // select property events on window - XWindowAttributes attr; - XGetWindowAttributes(display, window, &attr); - XSelectInput(display, window, attr.your_event_mask | PropertyChangeMask); - - // make a property name to receive dummy change - Atom atom = XInternAtom(display, "TIMESTAMP", False); - - // do a zero-length append to get the current time - unsigned char dummy; - XChangeProperty(display, window, atom, - XA_INTEGER, 8, - PropModeAppend, - &dummy, 0); - - // look for property notify events with the following - CPropertyNotifyPredicateInfo filter; - filter.m_window = window; - filter.m_property = atom; - - // wait for reply - XEvent xevent; - XIfEvent(display, &xevent, &CXWindowsUtil::propertyNotifyPredicate, - (XPointer)&filter); - assert(xevent.type == PropertyNotify); - assert(xevent.xproperty.window == window); - assert(xevent.xproperty.atom == atom); - - // restore event mask - XSelectInput(display, window, attr.your_event_mask); - - return xevent.xproperty.time; -} - -KeyID -CXWindowsUtil::mapKeySymToKeyID(KeySym k) -{ - initKeyMaps(); - - switch (k & 0xffffff00) { - case 0x0000: - // Latin-1 - return static_cast(k); - - case 0xfe00: - // ISO 9995 Function and Modifier Keys - switch (k) { - case XK_ISO_Left_Tab: - return kKeyLeftTab; - - case XK_ISO_Level3_Shift: - return kKeyAltGr; - - case XK_ISO_Next_Group: - return kKeyNextGroup; - - case XK_ISO_Prev_Group: - return kKeyPrevGroup; - - case XK_dead_grave: - return kKeyDeadGrave; - - case XK_dead_acute: - return kKeyDeadAcute; - - case XK_dead_circumflex: - return kKeyDeadCircumflex; - - case XK_dead_tilde: - return kKeyDeadTilde; - - case XK_dead_macron: - return kKeyDeadMacron; - - case XK_dead_breve: - return kKeyDeadBreve; - - case XK_dead_abovedot: - return kKeyDeadAbovedot; - - case XK_dead_diaeresis: - return kKeyDeadDiaeresis; - - case XK_dead_abovering: - return kKeyDeadAbovering; - - case XK_dead_doubleacute: - return kKeyDeadDoubleacute; - - case XK_dead_caron: - return kKeyDeadCaron; - - case XK_dead_cedilla: - return kKeyDeadCedilla; - - case XK_dead_ogonek: - return kKeyDeadOgonek; - - default: - return kKeyNone; - } - - case 0xff00: - // MISCELLANY - return static_cast(k - 0xff00 + 0xef00); - - case 0x1008ff00: - // "Internet" keys - return s_map1008FF[k & 0xff]; - - default: { - // lookup character in table - CKeySymMap::const_iterator index = s_keySymToUCS4.find(k); - if (index != s_keySymToUCS4.end()) { - return static_cast(index->second); - } - - // unknown character - return kKeyNone; - } - } -} - -UInt32 -CXWindowsUtil::getModifierBitForKeySym(KeySym keysym) -{ - switch (keysym) { - case XK_Shift_L: - case XK_Shift_R: - return kKeyModifierBitShift; - - case XK_Control_L: - case XK_Control_R: - return kKeyModifierBitControl; - - case XK_Alt_L: - case XK_Alt_R: - return kKeyModifierBitAlt; - - case XK_Meta_L: - case XK_Meta_R: - return kKeyModifierBitMeta; - - case XK_Super_L: - case XK_Super_R: - case XK_Hyper_L: - case XK_Hyper_R: - return kKeyModifierBitSuper; - - case XK_Mode_switch: - case XK_ISO_Level3_Shift: - return kKeyModifierBitAltGr; - - case XK_Caps_Lock: - return kKeyModifierBitCapsLock; - - case XK_Num_Lock: - return kKeyModifierBitNumLock; - - case XK_Scroll_Lock: - return kKeyModifierBitScrollLock; - - default: - return kKeyModifierBitNone; - } -} - -CString -CXWindowsUtil::atomToString(Display* display, Atom atom) -{ - if (atom == 0) { - return "None"; - } - - bool error = false; - CXWindowsUtil::CErrorLock lock(display, &error); - char* name = XGetAtomName(display, atom); - if (error) { - return CStringUtil::print(" (%d)", (int)atom); - } - else { - CString msg = CStringUtil::print("%s (%d)", name, (int)atom); - XFree(name); - return msg; - } -} - -CString -CXWindowsUtil::atomsToString(Display* display, const Atom* atom, UInt32 num) -{ - char** names = new char*[num]; - bool error = false; - CXWindowsUtil::CErrorLock lock(display, &error); - XGetAtomNames(display, const_cast(atom), (int)num, names); - CString msg; - if (error) { - for (UInt32 i = 0; i < num; ++i) { - msg += CStringUtil::print(" (%d), ", (int)atom[i]); - } - } - else { - for (UInt32 i = 0; i < num; ++i) { - msg += CStringUtil::print("%s (%d), ", names[i], (int)atom[i]); - XFree(names[i]); - } - } - delete[] names; - if (msg.size() > 2) { - msg.erase(msg.size() - 2); - } - return msg; -} - -void -CXWindowsUtil::convertAtomProperty(CString& data) -{ - // as best i can tell, 64-bit systems don't pack Atoms into properties - // as 32-bit numbers but rather as the 64-bit numbers they are. that - // seems wrong but we have to cope. sometimes we'll get a list of - // atoms that's 8*n+4 bytes long, missing the trailing 4 bytes which - // should all be 0. since we're going to reference the Atoms as - // 64-bit numbers we have to ensure the last number is a full 64 bits. - if (sizeof(Atom) != 4 && ((data.size() / 4) & 1) != 0) { - UInt32 zero = 0; - data.append(reinterpret_cast(&zero), sizeof(zero)); - } -} - -void -CXWindowsUtil::appendAtomData(CString& data, Atom atom) -{ - data.append(reinterpret_cast(&atom), sizeof(Atom)); -} - -void -CXWindowsUtil::replaceAtomData(CString& data, UInt32 index, Atom atom) -{ - data.replace(index * sizeof(Atom), sizeof(Atom), - reinterpret_cast(&atom), - sizeof(Atom)); -} - -void -CXWindowsUtil::appendTimeData(CString& data, Time time) -{ - data.append(reinterpret_cast(&time), sizeof(Time)); -} - -Bool -CXWindowsUtil::propertyNotifyPredicate(Display*, XEvent* xevent, XPointer arg) -{ - CPropertyNotifyPredicateInfo* filter = - reinterpret_cast(arg); - return (xevent->type == PropertyNotify && - xevent->xproperty.window == filter->m_window && - xevent->xproperty.atom == filter->m_property && - xevent->xproperty.state == PropertyNewValue) ? True : False; -} - -void -CXWindowsUtil::initKeyMaps() -{ - if (s_keySymToUCS4.empty()) { - for (size_t i =0; i < sizeof(s_keymap) / sizeof(s_keymap[0]); ++i) { - s_keySymToUCS4[s_keymap[i].keysym] = s_keymap[i].ucs4; - } - } -} - - -// -// CXWindowsUtil::CErrorLock -// - -CXWindowsUtil::CErrorLock* CXWindowsUtil::CErrorLock::s_top = NULL; - -CXWindowsUtil::CErrorLock::CErrorLock(Display* display) : - m_display(display) -{ - install(&CXWindowsUtil::CErrorLock::ignoreHandler, NULL); -} - -CXWindowsUtil::CErrorLock::CErrorLock(Display* display, bool* flag) : - m_display(display) -{ - install(&CXWindowsUtil::CErrorLock::saveHandler, flag); -} - -CXWindowsUtil::CErrorLock::CErrorLock(Display* display, - ErrorHandler handler, void* data) : - m_display(display) -{ - install(handler, data); -} - -CXWindowsUtil::CErrorLock::~CErrorLock() -{ - // make sure everything finishes before uninstalling handler - if (m_display != NULL) { - XSync(m_display, False); - } - - // restore old handler - XSetErrorHandler(m_oldXHandler); - s_top = m_next; -} - -void -CXWindowsUtil::CErrorLock::install(ErrorHandler handler, void* data) -{ - // make sure everything finishes before installing handler - if (m_display != NULL) { - XSync(m_display, False); - } - - // install handler - m_handler = handler; - m_userData = data; - m_oldXHandler = XSetErrorHandler( - &CXWindowsUtil::CErrorLock::internalHandler); - m_next = s_top; - s_top = this; -} - -int -CXWindowsUtil::CErrorLock::internalHandler(Display* display, XErrorEvent* event) -{ - if (s_top != NULL && s_top->m_handler != NULL) { - s_top->m_handler(display, event, s_top->m_userData); - } - return 0; -} - -void -CXWindowsUtil::CErrorLock::ignoreHandler(Display*, XErrorEvent* e, void*) -{ - LOG((CLOG_DEBUG1 "ignoring X error: %d", e->error_code)); -} - -void -CXWindowsUtil::CErrorLock::saveHandler(Display*, XErrorEvent* e, void* flag) -{ - LOG((CLOG_DEBUG1 "flagging X error: %d", e->error_code)); - *reinterpret_cast(flag) = true; -} diff --git a/lib/platform/CXWindowsUtil.h b/lib/platform/CXWindowsUtil.h deleted file mode 100644 index a9049ef6..00000000 --- a/lib/platform/CXWindowsUtil.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CXWINDOWSUTIL_H -#define CXWINDOWSUTIL_H - -#include "CString.h" -#include "BasicTypes.h" -#include "stdmap.h" -#include "stdvector.h" -#if X_DISPLAY_MISSING -# error X11 is required to build synergy -#else -# include -#endif - -//! X11 utility functions -class CXWindowsUtil { -public: - typedef std::vector KeySyms; - - //! Get property - /*! - Gets property \c property on \c window. \b Appends the data to - \c *data if \c data is not NULL, saves the property type in \c *type - if \c type is not NULL, and saves the property format in \c *format - if \c format is not NULL. If \c deleteProperty is true then the - property is deleted after being read. - */ - static bool getWindowProperty(Display*, - Window window, Atom property, - CString* data, Atom* type, - SInt32* format, bool deleteProperty); - - //! Set property - /*! - Sets property \c property on \c window to \c size bytes of data from - \c data. - */ - static bool setWindowProperty(Display*, - Window window, Atom property, - const void* data, UInt32 size, - Atom type, SInt32 format); - - //! Get X server time - /*! - Returns the current X server time. - */ - static Time getCurrentTime(Display*, Window); - - //! Convert KeySym to KeyID - /*! - Converts a KeySym to the equivalent KeyID. Returns kKeyNone if the - KeySym cannot be mapped. - */ - static UInt32 mapKeySymToKeyID(KeySym); - - //! Convert KeySym to corresponding KeyModifierMask - /*! - Converts a KeySym to the corresponding KeyModifierMask, or 0 if the - KeySym is not a modifier. - */ - static UInt32 getModifierBitForKeySym(KeySym keysym); - - //! Convert Atom to its string - /*! - Converts \p atom to its string representation. - */ - static CString atomToString(Display*, Atom atom); - - //! Convert several Atoms to a string - /*! - Converts each atom in \p atoms to its string representation and - concatenates the results. - */ - static CString atomsToString(Display* display, - const Atom* atom, UInt32 num); - - //! Prepare a property of atoms for use - /*! - 64-bit systems may need to modify a property's data if it's a - list of Atoms before using it. - */ - static void convertAtomProperty(CString& data); - - //! Append an Atom to property data - /*! - Converts \p atom to a 32-bit on-the-wire format and appends it to - \p data. - */ - static void appendAtomData(CString& data, Atom atom); - - //! Replace an Atom in property data - /*! - Converts \p atom to a 32-bit on-the-wire format and replaces the atom - at index \p index in \p data. - */ - static void replaceAtomData(CString& data, - UInt32 index, Atom atom); - - //! Append an Time to property data - /*! - Converts \p time to a 32-bit on-the-wire format and appends it to - \p data. - */ - static void appendTimeData(CString& data, Time time); - - //! X11 error handler - /*! - This class sets an X error handler in the c'tor and restores the - previous error handler in the d'tor. A lock should only be - installed while the display is locked by the thread. - - CErrorLock() ignores errors - CErrorLock(bool* flag) sets *flag to true if any error occurs - */ - class CErrorLock { - public: - //! Error handler type - typedef void (*ErrorHandler)(Display*, XErrorEvent*, void* userData); - - /*! - Ignore X11 errors. - */ - CErrorLock(Display*); - - /*! - Set \c *errorFlag if any error occurs. - */ - CErrorLock(Display*, bool* errorFlag); - - /*! - Call \c handler on each error. - */ - CErrorLock(Display*, ErrorHandler handler, void* userData); - - ~CErrorLock(); - - private: - void install(ErrorHandler, void*); - static int internalHandler(Display*, XErrorEvent*); - static void ignoreHandler(Display*, XErrorEvent*, void*); - static void saveHandler(Display*, XErrorEvent*, void*); - - private: - typedef int (*XErrorHandler)(Display*, XErrorEvent*); - - Display* m_display; - ErrorHandler m_handler; - void* m_userData; - XErrorHandler m_oldXHandler; - CErrorLock* m_next; - static CErrorLock* s_top; - }; - -private: - class CPropertyNotifyPredicateInfo { - public: - Window m_window; - Atom m_property; - }; - - static Bool propertyNotifyPredicate(Display*, - XEvent* xevent, XPointer arg); - - static void initKeyMaps(); - -private: - typedef std::map CKeySymMap; - - static CKeySymMap s_keySymToUCS4; -}; - -#endif diff --git a/lib/platform/Makefile.am b/lib/platform/Makefile.am deleted file mode 100644 index 6ff0523c..00000000 --- a/lib/platform/Makefile.am +++ /dev/null @@ -1,123 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2002 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -## Process this file with automake to produce Makefile.in -NULL = - -XWINDOWS_SOURCE_FILES = \ - CXWindowsClipboard.cpp \ - CXWindowsClipboardAnyBitmapConverter.cpp\ - CXWindowsClipboardBMPConverter.cpp \ - CXWindowsClipboardHTMLConverter.cpp \ - CXWindowsClipboardTextConverter.cpp \ - CXWindowsClipboardUCS2Converter.cpp \ - CXWindowsClipboardUTF8Converter.cpp \ - CXWindowsEventQueueBuffer.cpp \ - CXWindowsKeyState.cpp \ - CXWindowsScreen.cpp \ - CXWindowsScreenSaver.cpp \ - CXWindowsUtil.cpp \ - CXWindowsClipboard.h \ - CXWindowsClipboardAnyBitmapConverter.h \ - CXWindowsClipboardBMPConverter.h \ - CXWindowsClipboardHTMLConverter.h \ - CXWindowsClipboardTextConverter.h \ - CXWindowsClipboardUCS2Converter.h \ - CXWindowsClipboardUTF8Converter.h \ - CXWindowsEventQueueBuffer.h \ - CXWindowsKeyState.h \ - CXWindowsScreen.h \ - CXWindowsScreenSaver.h \ - CXWindowsUtil.h \ - $(NULL) -MSWINDOWS_SOURCE_FILES = \ - CMSWindowsClipboard.cpp \ - CMSWindowsClipboardAnyTextConverter.cpp \ - CMSWindowsClipboardBitmapConverter.cpp \ - CMSWindowsClipboardHTMLConverter.cpp \ - CMSWindowsClipboardTextConverter.cpp \ - CMSWindowsClipboardUTF16Converter.cpp \ - CMSWindowsDesks.cpp \ - CMSWindowsEventQueueBuffer.cpp \ - CMSWindowsKeyState.cpp \ - CMSWindowsScreen.cpp \ - CMSWindowsScreenSaver.cpp \ - CMSWindowsUtil.cpp \ - CMSWindowsClipboard.h \ - CMSWindowsClipboardAnyTextConverter.h \ - CMSWindowsClipboardBitmapConverter.h \ - CMSWindowsClipboardHTMLConverter.h \ - CMSWindowsClipboardTextConverter.h \ - CMSWindowsClipboardUTF16Converter.h \ - CMSWindowsDesks.h \ - CMSWindowsEventQueueBuffer.h \ - CMSWindowsKeyState.h \ - CMSWindowsScreen.h \ - CMSWindowsScreenSaver.h \ - CMSWindowsUtil.h \ - $(NULL) -MSWINDOWS_HOOK_SOURCE_FILES = \ - CSynergyHook.cpp \ - CSynergyHook.h \ - $(NULL) -CARBON_SOURCE_FILES = \ - COSXClipboard.cpp \ - COSXClipboardAnyTextConverter.cpp \ - COSXClipboardTextConverter.cpp \ - COSXClipboardUTF16Converter.cpp \ - COSXEventQueueBuffer.cpp \ - COSXKeyState.cpp \ - COSXScreen.cpp \ - COSXScreenSaver.cpp \ - COSXScreenSaverUtil.m \ - COSXClipboard.h \ - COSXClipboardAnyTextConverter.h \ - COSXClipboardTextConverter.h \ - COSXClipboardUTF16Converter.h \ - COSXEventQueueBuffer.h \ - COSXKeyState.h \ - COSXScreen.h \ - COSXScreenSaver.h \ - COSXScreenSaverUtil.h \ - OSXScreenSaverControl.h \ - $(NULL) - -EXTRA_DIST = \ - Makefile.win \ - $(XWINDOWS_SOURCE_FILES) \ - $(MSWINDOWS_SOURCE_FILES) \ - $(MSWINDOWS_HOOK_SOURCE_FILES) \ - $(CARBON_SOURCE_FILES) \ - $(NULL) - -MAINTAINERCLEANFILES = \ - Makefile.in \ - $(NULL) - -noinst_LIBRARIES = libplatform.a -if XWINDOWS -libplatform_a_SOURCES = $(XWINDOWS_SOURCE_FILES) -endif -if MSWINDOWS -libplatform_a_SOURCES = $(MSWINDOWS_SOURCE_FILES) -endif -if CARBON -libplatform_a_SOURCES = $(CARBON_SOURCE_FILES) -endif -INCLUDES = \ - -I$(top_srcdir)/lib/common \ - -I$(top_srcdir)/lib/arch \ - -I$(top_srcdir)/lib/base \ - -I$(top_srcdir)/lib/mt \ - -I$(top_srcdir)/lib/io \ - -I$(top_srcdir)/lib/synergy \ - $(NULL) diff --git a/lib/platform/Makefile.win b/lib/platform/Makefile.win deleted file mode 100644 index 001200d1..00000000 --- a/lib/platform/Makefile.win +++ /dev/null @@ -1,119 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2007 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -LIB_PLATFORM_SRC = lib\platform -LIB_PLATFORM_DST = $(BUILD_DST)\$(LIB_PLATFORM_SRC) -LIB_PLATFORM_LIB = "$(LIB_PLATFORM_DST)\platform.lib" -LIB_PLATFORM_CPP = \ - "CMSWindowsClipboard.cpp" \ - "CMSWindowsClipboardAnyTextConverter.cpp" \ - "CMSWindowsClipboardBitmapConverter.cpp" \ - "CMSWindowsClipboardHTMLConverter.cpp" \ - "CMSWindowsClipboardTextConverter.cpp" \ - "CMSWindowsClipboardUTF16Converter.cpp" \ - "CMSWindowsDesks.cpp" \ - "CMSWindowsEventQueueBuffer.cpp" \ - "CMSWindowsKeyState.cpp" \ - "CMSWindowsScreen.cpp" \ - "CMSWindowsScreenSaver.cpp" \ - "CMSWindowsUtil.cpp" \ - $(NULL) -LIB_PLATFORM_OBJ = \ - "$(LIB_PLATFORM_DST)\CMSWindowsClipboard.obj" \ - "$(LIB_PLATFORM_DST)\CMSWindowsClipboardAnyTextConverter.obj" \ - "$(LIB_PLATFORM_DST)\CMSWindowsClipboardBitmapConverter.obj" \ - "$(LIB_PLATFORM_DST)\CMSWindowsClipboardHTMLConverter.obj" \ - "$(LIB_PLATFORM_DST)\CMSWindowsClipboardTextConverter.obj" \ - "$(LIB_PLATFORM_DST)\CMSWindowsClipboardUTF16Converter.obj" \ - "$(LIB_PLATFORM_DST)\CMSWindowsDesks.obj" \ - "$(LIB_PLATFORM_DST)\CMSWindowsEventQueueBuffer.obj" \ - "$(LIB_PLATFORM_DST)\CMSWindowsKeyState.obj" \ - "$(LIB_PLATFORM_DST)\CMSWindowsScreen.obj" \ - "$(LIB_PLATFORM_DST)\CMSWindowsScreenSaver.obj" \ - "$(LIB_PLATFORM_DST)\CMSWindowsUtil.obj" \ - $(NULL) -LIB_PLATFORM_HOOK_CPP = \ - "$(LIB_PLATFORM_SRC)\CSynergyHook.cpp" \ - $(NULL) -LIB_PLATFORM_HOOK_OBJ = \ - "$(LIB_PLATFORM_DST)\CSynergyHook.obj" \ - $(NULL) -LIB_PLATFORM_HOOK_DLL = "$(BUILD_DST)\synrgyhk.dll" -LIB_PLATFORM_INC = \ - /I"lib\common" \ - /I"lib\arch" \ - /I"lib\base" \ - /I"lib\mt" \ - /I"lib\io" \ - /I"lib\net" \ - /I"lib\synergy" \ - $(NULL) - -CPP_FILES = $(CPP_FILES) $(LIB_PLATFORM_CPP) -OBJ_FILES = $(OBJ_FILES) $(LIB_PLATFORM_OBJ) -LIB_FILES = $(LIB_FILES) $(LIB_PLATFORM_LIB) $(LIB_PLATFORM_HOOK_DLL) - -# Hook should be as small as possible. -cpphookdebug = $(cppdebug:-Ox=-O1) - -# Don't do security checks or run time error checking on hook. -cpphookflags = $(cppflags:-GS=) -cpphookdebug = $(cpphookdebug:/GZ=) -cpphookdebug = $(cpphookdebug:/RTC1=) - -# Dependency rules -$(LIB_PLATFORM_OBJ): $(AUTODEP) -!if EXIST($(LIB_PLATFORM_DST)\deps.mak) -!include $(LIB_PLATFORM_DST)\deps.mak -!endif - -# Build rules. Use batch-mode rules if possible. -!if DEFINED(_NMAKE_VER) -{$(LIB_PLATFORM_SRC)\}.cpp{$(LIB_PLATFORM_DST)\}.obj:: -!else -{$(LIB_PLATFORM_SRC)\}.cpp{$(LIB_PLATFORM_DST)\}.obj: -!endif - @$(ECHO) Compile in $(LIB_PLATFORM_SRC) - -@$(MKDIR) $(LIB_PLATFORM_DST) 2>NUL: - $(cpp) $(cppdebug) $(cppflags) $(cppvarsmt) /showIncludes \ - $(LIB_PLATFORM_INC) \ - /Fo$(LIB_PLATFORM_DST)\ \ - /Fd$(LIB_PLATFORM_LIB:.lib=.pdb) \ - $< | $(AUTODEP) $(LIB_PLATFORM_SRC) $(LIB_PLATFORM_DST) -$(LIB_PLATFORM_LIB): $(LIB_PLATFORM_OBJ) - @$(ECHO) Link $(@F) - $(implib) $(ildebug) $(ilflags) \ - /out:$@ \ - $** - $(AUTODEP) $(LIB_PLATFORM_SRC) $(LIB_PLATFORM_DST) \ - $(LIB_PLATFORM_OBJ:.obj=.d) $(LIB_PLATFORM_HOOK_OBJ:.obj=.d) - -# Hook build rules -$(LIB_PLATFORM_HOOK_OBJ): \ - $(LIB_PLATFORM_HOOK_CPP) $(LIB_PLATFORM_HOOK_CPP:.cpp=.h) - @$(ECHO) Compile $(LIB_PLATFORM_HOOK_CPP) - -@$(MKDIR) $(LIB_PLATFORM_DST) 2>NUL: - $(cpp) $(cpphookdebug) $(cpphookflags) $(cppvarsmt) /showIncludes \ - -D_DLL -D_USRDLL -DSYNRGYHK_EXPORTS \ - $(LIB_PLATFORM_INC) \ - /Fo$(LIB_PLATFORM_DST)\ \ - /Fd$(@:.obj=.pdb) \ - $(LIB_PLATFORM_HOOK_CPP) | \ - $(AUTODEP) $(LIB_PLATFORM_SRC) $(LIB_PLATFORM_DST) -$(LIB_PLATFORM_HOOK_DLL): $(LIB_PLATFORM_HOOK_OBJ) - @$(ECHO) Link $(@F) - $(link) $(ldebug) $(lflags) $(guilibsmt) \ - /entry:"DllMain$(DLLENTRY)" /dll \ - /out:$@ \ - $** - $(AUTODEP) $(LIB_PLATFORM_SRC) $(LIB_PLATFORM_DST) \ - $(LIB_PLATFORM_OBJ:.obj=.d) $(LIB_PLATFORM_HOOK_OBJ:.obj=.d) diff --git a/lib/platform/OSXScreenSaverControl.h b/lib/platform/OSXScreenSaverControl.h deleted file mode 100644 index 75aecb17..00000000 --- a/lib/platform/OSXScreenSaverControl.h +++ /dev/null @@ -1,36 +0,0 @@ -// ScreenSaver.framework private API -// Class dumping by Alex Harper http://www.ragingmenace.com/ - -#import - -@protocol ScreenSaverControl -- (double)screenSaverTimeRemaining; -- (void)restartForUser:fp12; -- (void)screenSaverStopNow; -- (void)screenSaverStartNow; -- (void)setScreenSaverCanRun:(char)fp12; -- (BOOL)screenSaverCanRun; -- (BOOL)screenSaverIsRunning; -@end - - -@interface ScreenSaverController:NSObject - -+ controller; -+ monitor; -+ daemonConnectionName; -+ daemonPath; -+ enginePath; -- init; -- (void)dealloc; -- (void)_connectionClosed:fp12; -- (BOOL)screenSaverIsRunning; -- (BOOL)screenSaverCanRun; -- (void)setScreenSaverCanRun:(char)fp12; -- (void)screenSaverStartNow; -- (void)screenSaverStopNow; -- (void)restartForUser:fp12; -- (double)screenSaverTimeRemaining; - -@end - diff --git a/lib/server/CBaseClientProxy.cpp b/lib/server/CBaseClientProxy.cpp deleted file mode 100644 index 0f049e35..00000000 --- a/lib/server/CBaseClientProxy.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2006 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CBaseClientProxy.h" - -// -// CBaseClientProxy -// - -CBaseClientProxy::CBaseClientProxy(const CString& name) : - m_name(name), - m_x(0), - m_y(0) -{ - // do nothing -} - -CBaseClientProxy::~CBaseClientProxy() -{ - // do nothing -} - -void -CBaseClientProxy::setJumpCursorPos(SInt32 x, SInt32 y) -{ - m_x = x; - m_y = y; -} - -void -CBaseClientProxy::getJumpCursorPos(SInt32& x, SInt32& y) const -{ - x = m_x; - y = m_y; -} - -CString -CBaseClientProxy::getName() const -{ - return m_name; -} diff --git a/lib/server/CBaseClientProxy.h b/lib/server/CBaseClientProxy.h deleted file mode 100644 index e9cceca4..00000000 --- a/lib/server/CBaseClientProxy.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CBASECLIENTPROXY_H -#define CBASECLIENTPROXY_H - -#include "IClient.h" -#include "CString.h" - -//! Generic proxy for client or primary -class CBaseClientProxy : public IClient { -public: - /*! - \c name is the name of the client. - */ - CBaseClientProxy(const CString& name); - ~CBaseClientProxy(); - - //! @name manipulators - //@{ - - //! Save cursor position - /*! - Save the position of the cursor when jumping from client. - */ - void setJumpCursorPos(SInt32 x, SInt32 y); - - //@} - //! @name accessors - //@{ - - //! Get cursor position - /*! - Get the position of the cursor when last jumping from client. - */ - void getJumpCursorPos(SInt32& x, SInt32& y) const; - - //@} - - // IScreen - virtual void* getEventTarget() const = 0; - virtual bool getClipboard(ClipboardID id, IClipboard*) const = 0; - virtual void getShape(SInt32& x, SInt32& y, - SInt32& width, SInt32& height) const = 0; - virtual void getCursorPos(SInt32& x, SInt32& y) const = 0; - - // IClient overrides - virtual void enter(SInt32 xAbs, SInt32 yAbs, - UInt32 seqNum, KeyModifierMask mask, - bool forScreensaver) = 0; - virtual bool leave() = 0; - virtual void setClipboard(ClipboardID, const IClipboard*) = 0; - virtual void grabClipboard(ClipboardID) = 0; - virtual void setClipboardDirty(ClipboardID, bool) = 0; - virtual void keyDown(KeyID, KeyModifierMask, KeyButton) = 0; - virtual void keyRepeat(KeyID, KeyModifierMask, - SInt32 count, KeyButton) = 0; - virtual void keyUp(KeyID, KeyModifierMask, KeyButton) = 0; - virtual void mouseDown(ButtonID) = 0; - virtual void mouseUp(ButtonID) = 0; - virtual void mouseMove(SInt32 xAbs, SInt32 yAbs) = 0; - virtual void mouseRelativeMove(SInt32 xRel, SInt32 yRel) = 0; - virtual void mouseWheel(SInt32 xDelta, SInt32 yDelta) = 0; - virtual void screensaver(bool activate) = 0; - virtual void resetOptions() = 0; - virtual void setOptions(const COptionsList& options) = 0; - virtual CString getName() const; - -private: - CString m_name; - SInt32 m_x, m_y; -}; - -#endif diff --git a/lib/server/CClientListener.cpp b/lib/server/CClientListener.cpp deleted file mode 100644 index 803f44a0..00000000 --- a/lib/server/CClientListener.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CClientListener.h" -#include "CClientProxy.h" -#include "CClientProxyUnknown.h" -#include "CPacketStreamFilter.h" -#include "IStreamFilterFactory.h" -#include "IDataSocket.h" -#include "IListenSocket.h" -#include "ISocketFactory.h" -#include "XSocket.h" -#include "CLog.h" -#include "IEventQueue.h" -#include "TMethodEventJob.h" - -// -// CClientListener -// - -CEvent::Type CClientListener::s_connectedEvent = CEvent::kUnknown; - -CClientListener::CClientListener(const CNetworkAddress& address, - ISocketFactory* socketFactory, - IStreamFilterFactory* streamFilterFactory) : - m_socketFactory(socketFactory), - m_streamFilterFactory(streamFilterFactory) -{ - assert(m_socketFactory != NULL); - - try { - // create listen socket - m_listen = m_socketFactory->createListen(); - - // bind listen address - LOG((CLOG_DEBUG1 "binding listen socket")); - m_listen->bind(address); - } - catch (XSocketAddressInUse&) { - delete m_listen; - delete m_socketFactory; - delete m_streamFilterFactory; - throw; - } - catch (XBase&) { - delete m_listen; - delete m_socketFactory; - delete m_streamFilterFactory; - throw; - } - LOG((CLOG_DEBUG1 "listening for clients")); - - // setup event handler - EVENTQUEUE->adoptHandler(IListenSocket::getConnectingEvent(), m_listen, - new TMethodEventJob(this, - &CClientListener::handleClientConnecting)); -} - -CClientListener::~CClientListener() -{ - LOG((CLOG_DEBUG1 "stop listening for clients")); - - // discard already connected clients - for (CNewClients::iterator index = m_newClients.begin(); - index != m_newClients.end(); ++index) { - CClientProxyUnknown* client = *index; - EVENTQUEUE->removeHandler( - CClientProxyUnknown::getSuccessEvent(), client); - EVENTQUEUE->removeHandler( - CClientProxyUnknown::getFailureEvent(), client); - EVENTQUEUE->removeHandler( - CClientProxy::getDisconnectedEvent(), client); - delete client; - } - - // discard waiting clients - CClientProxy* client = getNextClient(); - while (client != NULL) { - delete client; - client = getNextClient(); - } - - EVENTQUEUE->removeHandler(IListenSocket::getConnectingEvent(), m_listen); - delete m_listen; - delete m_socketFactory; - delete m_streamFilterFactory; -} - -CClientProxy* -CClientListener::getNextClient() -{ - CClientProxy* client = NULL; - if (!m_waitingClients.empty()) { - client = m_waitingClients.front(); - m_waitingClients.pop_front(); - EVENTQUEUE->removeHandler(CClientProxy::getDisconnectedEvent(), client); - } - return client; -} - -CEvent::Type -CClientListener::getConnectedEvent() -{ - return CEvent::registerTypeOnce(s_connectedEvent, - "CClientListener::connected"); -} - -void -CClientListener::handleClientConnecting(const CEvent&, void*) -{ - // accept client connection - IStream* stream = m_listen->accept(); - if (stream == NULL) { - return; - } - LOG((CLOG_NOTE "accepted client connection")); - - // filter socket messages, including a packetizing filter - if (m_streamFilterFactory != NULL) { - stream = m_streamFilterFactory->create(stream, true); - } - stream = new CPacketStreamFilter(stream, true); - - // create proxy for unknown client - CClientProxyUnknown* client = new CClientProxyUnknown(stream, 30.0); - m_newClients.insert(client); - - // watch for events from unknown client - EVENTQUEUE->adoptHandler(CClientProxyUnknown::getSuccessEvent(), client, - new TMethodEventJob(this, - &CClientListener::handleUnknownClient, client)); - EVENTQUEUE->adoptHandler(CClientProxyUnknown::getFailureEvent(), client, - new TMethodEventJob(this, - &CClientListener::handleUnknownClient, client)); -} - -void -CClientListener::handleUnknownClient(const CEvent&, void* vclient) -{ - CClientProxyUnknown* unknownClient = - reinterpret_cast(vclient); - - // we should have the client in our new client list - assert(m_newClients.count(unknownClient) == 1); - - // get the real client proxy and install it - CClientProxy* client = unknownClient->orphanClientProxy(); - if (client != NULL) { - // handshake was successful - m_waitingClients.push_back(client); - EVENTQUEUE->addEvent(CEvent(getConnectedEvent(), this)); - - // watch for client to disconnect while it's in our queue - EVENTQUEUE->adoptHandler(CClientProxy::getDisconnectedEvent(), client, - new TMethodEventJob(this, - &CClientListener::handleClientDisconnected, - client)); - } - - // now finished with unknown client - EVENTQUEUE->removeHandler(CClientProxyUnknown::getSuccessEvent(), client); - EVENTQUEUE->removeHandler(CClientProxyUnknown::getFailureEvent(), client); - m_newClients.erase(unknownClient); - delete unknownClient; -} - -void -CClientListener::handleClientDisconnected(const CEvent&, void* vclient) -{ - CClientProxy* client = reinterpret_cast(vclient); - - // find client in waiting clients queue - for (CWaitingClients::iterator i = m_waitingClients.begin(), - n = m_waitingClients.end(); i != n; ++i) { - if (*i == client) { - m_waitingClients.erase(i); - EVENTQUEUE->removeHandler(CClientProxy::getDisconnectedEvent(), - client); - delete client; - break; - } - } -} diff --git a/lib/server/CClientListener.h b/lib/server/CClientListener.h deleted file mode 100644 index e5302e69..00000000 --- a/lib/server/CClientListener.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CCLIENTLISTENER_H -#define CCLIENTLISTENER_H - -#include "CConfig.h" -#include "CEvent.h" -#include "stddeque.h" -#include "stdset.h" - -class CClientProxy; -class CClientProxyUnknown; -class CNetworkAddress; -class IListenSocket; -class ISocketFactory; -class IStreamFilterFactory; - -class CClientListener { -public: - // The factories are adopted. - CClientListener(const CNetworkAddress&, - ISocketFactory*, IStreamFilterFactory*); - ~CClientListener(); - - //! @name accessors - //@{ - - //! Get next connected client - /*! - Returns the next connected client and removes it from the internal - list. The client is responsible for deleting the returned client. - Returns NULL if no clients are available. - */ - CClientProxy* getNextClient(); - - //! Get connected event type - /*! - Returns the connected event type. This is sent whenever a - a client connects. - */ - static CEvent::Type getConnectedEvent(); - - //@} - -private: - // client connection event handlers - void handleClientConnecting(const CEvent&, void*); - void handleUnknownClient(const CEvent&, void*); - void handleClientDisconnected(const CEvent&, void*); - -private: - typedef std::set CNewClients; - typedef std::deque CWaitingClients; - - IListenSocket* m_listen; - ISocketFactory* m_socketFactory; - IStreamFilterFactory* m_streamFilterFactory; - CNewClients m_newClients; - CWaitingClients m_waitingClients; - - static CEvent::Type s_connectedEvent; -}; - -#endif diff --git a/lib/server/CClientProxy.cpp b/lib/server/CClientProxy.cpp deleted file mode 100644 index 715126d5..00000000 --- a/lib/server/CClientProxy.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CClientProxy.h" -#include "CProtocolUtil.h" -#include "IStream.h" -#include "CLog.h" - -// -// CClientProxy -// - -CEvent::Type CClientProxy::s_readyEvent = CEvent::kUnknown; -CEvent::Type CClientProxy::s_disconnectedEvent = CEvent::kUnknown; -CEvent::Type CClientProxy::s_clipboardChangedEvent= CEvent::kUnknown; - -CClientProxy::CClientProxy(const CString& name, IStream* stream) : - CBaseClientProxy(name), - m_stream(stream) -{ - // do nothing -} - -CClientProxy::~CClientProxy() -{ - delete m_stream; -} - -void -CClientProxy::close(const char* msg) -{ - LOG((CLOG_DEBUG1 "send close \"%s\" to \"%s\"", msg, getName().c_str())); - CProtocolUtil::writef(getStream(), msg); - - // force the close to be sent before we return - getStream()->flush(); -} - -IStream* -CClientProxy::getStream() const -{ - return m_stream; -} - -CEvent::Type -CClientProxy::getReadyEvent() -{ - return CEvent::registerTypeOnce(s_readyEvent, - "CClientProxy::ready"); -} - -CEvent::Type -CClientProxy::getDisconnectedEvent() -{ - return CEvent::registerTypeOnce(s_disconnectedEvent, - "CClientProxy::disconnected"); -} - -CEvent::Type -CClientProxy::getClipboardChangedEvent() -{ - return CEvent::registerTypeOnce(s_clipboardChangedEvent, - "CClientProxy::clipboardChanged"); -} - -void* -CClientProxy::getEventTarget() const -{ - return static_cast(const_cast(this)); -} diff --git a/lib/server/CClientProxy.h b/lib/server/CClientProxy.h deleted file mode 100644 index 51ad014b..00000000 --- a/lib/server/CClientProxy.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CCLIENTPROXY_H -#define CCLIENTPROXY_H - -#include "CBaseClientProxy.h" -#include "CEvent.h" -#include "CString.h" - -class IStream; - -//! Generic proxy for client -class CClientProxy : public CBaseClientProxy { -public: - /*! - \c name is the name of the client. - */ - CClientProxy(const CString& name, IStream* adoptedStream); - ~CClientProxy(); - - //! @name manipulators - //@{ - - //! Disconnect - /*! - Ask the client to disconnect, using \p msg as the reason. - */ - void close(const char* msg); - - //@} - //! @name accessors - //@{ - - //! Get stream - /*! - Returns the stream passed to the c'tor. - */ - IStream* getStream() const; - - //! Get ready event type - /*! - Returns the ready event type. This is sent when the client has - completed the initial handshake. Until it is sent, the client is - not fully connected. - */ - static CEvent::Type getReadyEvent(); - - //! Get disconnect event type - /*! - Returns the disconnect event type. This is sent when the client - disconnects or is disconnected. The target is getEventTarget(). - */ - static CEvent::Type getDisconnectedEvent(); - - //! Get clipboard changed event type - /*! - Returns the clipboard changed event type. This is sent whenever the - contents of the clipboard has changed. The data is a pointer to a - IScreen::CClipboardInfo. - */ - static CEvent::Type getClipboardChangedEvent(); - - //@} - - // IScreen - virtual void* getEventTarget() const; - virtual bool getClipboard(ClipboardID id, IClipboard*) const = 0; - virtual void getShape(SInt32& x, SInt32& y, - SInt32& width, SInt32& height) const = 0; - virtual void getCursorPos(SInt32& x, SInt32& y) const = 0; - - // IClient overrides - virtual void enter(SInt32 xAbs, SInt32 yAbs, - UInt32 seqNum, KeyModifierMask mask, - bool forScreensaver) = 0; - virtual bool leave() = 0; - virtual void setClipboard(ClipboardID, const IClipboard*) = 0; - virtual void grabClipboard(ClipboardID) = 0; - virtual void setClipboardDirty(ClipboardID, bool) = 0; - virtual void keyDown(KeyID, KeyModifierMask, KeyButton) = 0; - virtual void keyRepeat(KeyID, KeyModifierMask, - SInt32 count, KeyButton) = 0; - virtual void keyUp(KeyID, KeyModifierMask, KeyButton) = 0; - virtual void mouseDown(ButtonID) = 0; - virtual void mouseUp(ButtonID) = 0; - virtual void mouseMove(SInt32 xAbs, SInt32 yAbs) = 0; - virtual void mouseRelativeMove(SInt32 xRel, SInt32 yRel) = 0; - virtual void mouseWheel(SInt32 xDelta, SInt32 yDelta) = 0; - virtual void screensaver(bool activate) = 0; - virtual void resetOptions() = 0; - virtual void setOptions(const COptionsList& options) = 0; - -private: - IStream* m_stream; - - static CEvent::Type s_readyEvent; - static CEvent::Type s_disconnectedEvent; - static CEvent::Type s_clipboardChangedEvent; -}; - -#endif diff --git a/lib/server/CClientProxy1_0.cpp b/lib/server/CClientProxy1_0.cpp deleted file mode 100644 index b40372e5..00000000 --- a/lib/server/CClientProxy1_0.cpp +++ /dev/null @@ -1,498 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CClientProxy1_0.h" -#include "CProtocolUtil.h" -#include "XSynergy.h" -#include "IStream.h" -#include "CLog.h" -#include "IEventQueue.h" -#include "TMethodEventJob.h" -#include - -// -// CClientProxy1_0 -// - -CClientProxy1_0::CClientProxy1_0(const CString& name, IStream* stream) : - CClientProxy(name, stream), - m_heartbeatTimer(NULL), - m_parser(&CClientProxy1_0::parseHandshakeMessage) -{ - // install event handlers - EVENTQUEUE->adoptHandler(IStream::getInputReadyEvent(), - stream->getEventTarget(), - new TMethodEventJob(this, - &CClientProxy1_0::handleData, NULL)); - EVENTQUEUE->adoptHandler(IStream::getOutputErrorEvent(), - stream->getEventTarget(), - new TMethodEventJob(this, - &CClientProxy1_0::handleWriteError, NULL)); - EVENTQUEUE->adoptHandler(IStream::getInputShutdownEvent(), - stream->getEventTarget(), - new TMethodEventJob(this, - &CClientProxy1_0::handleDisconnect, NULL)); - EVENTQUEUE->adoptHandler(IStream::getOutputShutdownEvent(), - stream->getEventTarget(), - new TMethodEventJob(this, - &CClientProxy1_0::handleWriteError, NULL)); - EVENTQUEUE->adoptHandler(CEvent::kTimer, this, - new TMethodEventJob(this, - &CClientProxy1_0::handleFlatline, NULL)); - - setHeartbeatRate(kHeartRate, kHeartRate * kHeartBeatsUntilDeath); - - LOG((CLOG_DEBUG1 "querying client \"%s\" info", getName().c_str())); - CProtocolUtil::writef(getStream(), kMsgQInfo); -} - -CClientProxy1_0::~CClientProxy1_0() -{ - removeHandlers(); -} - -void -CClientProxy1_0::disconnect() -{ - removeHandlers(); - getStream()->close(); - EVENTQUEUE->addEvent(CEvent(getDisconnectedEvent(), getEventTarget())); -} - -void -CClientProxy1_0::removeHandlers() -{ - // uninstall event handlers - EVENTQUEUE->removeHandler(IStream::getInputReadyEvent(), - getStream()->getEventTarget()); - EVENTQUEUE->removeHandler(IStream::getOutputErrorEvent(), - getStream()->getEventTarget()); - EVENTQUEUE->removeHandler(IStream::getInputShutdownEvent(), - getStream()->getEventTarget()); - EVENTQUEUE->removeHandler(IStream::getOutputShutdownEvent(), - getStream()->getEventTarget()); - EVENTQUEUE->removeHandler(CEvent::kTimer, this); - - // remove timer - removeHeartbeatTimer(); -} - -void -CClientProxy1_0::addHeartbeatTimer() -{ - if (m_heartbeatAlarm > 0.0) { - m_heartbeatTimer = EVENTQUEUE->newOneShotTimer(m_heartbeatAlarm, this); - } -} - -void -CClientProxy1_0::removeHeartbeatTimer() -{ - if (m_heartbeatTimer != NULL) { - EVENTQUEUE->deleteTimer(m_heartbeatTimer); - m_heartbeatTimer = NULL; - } -} - -void -CClientProxy1_0::resetHeartbeatTimer() -{ - // reset the alarm - removeHeartbeatTimer(); - addHeartbeatTimer(); -} - -void -CClientProxy1_0::resetHeartbeatRate() -{ - setHeartbeatRate(kHeartRate, kHeartRate * kHeartBeatsUntilDeath); -} - -void -CClientProxy1_0::setHeartbeatRate(double, double alarm) -{ - m_heartbeatAlarm = alarm; -} - -void -CClientProxy1_0::handleData(const CEvent&, void*) -{ - // handle messages until there are no more. first read message code. - UInt8 code[4]; - UInt32 n = getStream()->read(code, 4); - while (n != 0) { - // verify we got an entire code - if (n != 4) { - LOG((CLOG_ERR "incomplete message from \"%s\": %d bytes", getName().c_str(), n)); - disconnect(); - return; - } - - // parse message - LOG((CLOG_DEBUG2 "msg from \"%s\": %c%c%c%c", getName().c_str(), code[0], code[1], code[2], code[3])); - if (!(this->*m_parser)(code)) { - LOG((CLOG_ERR "invalid message from client \"%s\": %c%c%c%c", getName().c_str(), code[0], code[1], code[2], code[3])); - disconnect(); - return; - } - - // next message - n = getStream()->read(code, 4); - } - - // restart heartbeat timer - resetHeartbeatTimer(); -} - -bool -CClientProxy1_0::parseHandshakeMessage(const UInt8* code) -{ - if (memcmp(code, kMsgCNoop, 4) == 0) { - // discard no-ops - LOG((CLOG_DEBUG2 "no-op from", getName().c_str())); - return true; - } - else if (memcmp(code, kMsgDInfo, 4) == 0) { - // future messages get parsed by parseMessage - m_parser = &CClientProxy1_0::parseMessage; - if (recvInfo()) { - EVENTQUEUE->addEvent(CEvent(getReadyEvent(), getEventTarget())); - addHeartbeatTimer(); - return true; - } - } - return false; -} - -bool -CClientProxy1_0::parseMessage(const UInt8* code) -{ - if (memcmp(code, kMsgDInfo, 4) == 0) { - if (recvInfo()) { - EVENTQUEUE->addEvent( - CEvent(getShapeChangedEvent(), getEventTarget())); - return true; - } - return false; - } - else if (memcmp(code, kMsgCNoop, 4) == 0) { - // discard no-ops - LOG((CLOG_DEBUG2 "no-op from", getName().c_str())); - return true; - } - else if (memcmp(code, kMsgCClipboard, 4) == 0) { - return recvGrabClipboard(); - } - else if (memcmp(code, kMsgDClipboard, 4) == 0) { - return recvClipboard(); - } - return false; -} - -void -CClientProxy1_0::handleDisconnect(const CEvent&, void*) -{ - LOG((CLOG_NOTE "client \"%s\" has disconnected", getName().c_str())); - disconnect(); -} - -void -CClientProxy1_0::handleWriteError(const CEvent&, void*) -{ - LOG((CLOG_WARN "error writing to client \"%s\"", getName().c_str())); - disconnect(); -} - -void -CClientProxy1_0::handleFlatline(const CEvent&, void*) -{ - // didn't get a heartbeat fast enough. assume client is dead. - LOG((CLOG_NOTE "client \"%s\" is dead", getName().c_str())); - disconnect(); -} - -bool -CClientProxy1_0::getClipboard(ClipboardID id, IClipboard* clipboard) const -{ - CClipboard::copy(clipboard, &m_clipboard[id].m_clipboard); - return true; -} - -void -CClientProxy1_0::getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h) const -{ - x = m_info.m_x; - y = m_info.m_y; - w = m_info.m_w; - h = m_info.m_h; -} - -void -CClientProxy1_0::getCursorPos(SInt32& x, SInt32& y) const -{ - // note -- this returns the cursor pos from when we last got client info - x = m_info.m_mx; - y = m_info.m_my; -} - -void -CClientProxy1_0::enter(SInt32 xAbs, SInt32 yAbs, - UInt32 seqNum, KeyModifierMask mask, bool) -{ - LOG((CLOG_DEBUG1 "send enter to \"%s\", %d,%d %d %04x", getName().c_str(), xAbs, yAbs, seqNum, mask)); - CProtocolUtil::writef(getStream(), kMsgCEnter, - xAbs, yAbs, seqNum, mask); -} - -bool -CClientProxy1_0::leave() -{ - LOG((CLOG_DEBUG1 "send leave to \"%s\"", getName().c_str())); - CProtocolUtil::writef(getStream(), kMsgCLeave); - - // we can never prevent the user from leaving - return true; -} - -void -CClientProxy1_0::setClipboard(ClipboardID id, const IClipboard* clipboard) -{ - // ignore if this clipboard is already clean - if (m_clipboard[id].m_dirty) { - // this clipboard is now clean - m_clipboard[id].m_dirty = false; - CClipboard::copy(&m_clipboard[id].m_clipboard, clipboard); - - CString data = m_clipboard[id].m_clipboard.marshall(); - LOG((CLOG_DEBUG "send clipboard %d to \"%s\" size=%d", id, getName().c_str(), data.size())); - CProtocolUtil::writef(getStream(), kMsgDClipboard, id, 0, &data); - } -} - -void -CClientProxy1_0::grabClipboard(ClipboardID id) -{ - LOG((CLOG_DEBUG "send grab clipboard %d to \"%s\"", id, getName().c_str())); - CProtocolUtil::writef(getStream(), kMsgCClipboard, id, 0); - - // this clipboard is now dirty - m_clipboard[id].m_dirty = true; -} - -void -CClientProxy1_0::setClipboardDirty(ClipboardID id, bool dirty) -{ - m_clipboard[id].m_dirty = dirty; -} - -void -CClientProxy1_0::keyDown(KeyID key, KeyModifierMask mask, KeyButton) -{ - LOG((CLOG_DEBUG1 "send key down to \"%s\" id=%d, mask=0x%04x", getName().c_str(), key, mask)); - CProtocolUtil::writef(getStream(), kMsgDKeyDown1_0, key, mask); -} - -void -CClientProxy1_0::keyRepeat(KeyID key, KeyModifierMask mask, - SInt32 count, KeyButton) -{ - LOG((CLOG_DEBUG1 "send key repeat to \"%s\" id=%d, mask=0x%04x, count=%d", getName().c_str(), key, mask, count)); - CProtocolUtil::writef(getStream(), kMsgDKeyRepeat1_0, key, mask, count); -} - -void -CClientProxy1_0::keyUp(KeyID key, KeyModifierMask mask, KeyButton) -{ - LOG((CLOG_DEBUG1 "send key up to \"%s\" id=%d, mask=0x%04x", getName().c_str(), key, mask)); - CProtocolUtil::writef(getStream(), kMsgDKeyUp1_0, key, mask); -} - -void -CClientProxy1_0::mouseDown(ButtonID button) -{ - LOG((CLOG_DEBUG1 "send mouse down to \"%s\" id=%d", getName().c_str(), button)); - CProtocolUtil::writef(getStream(), kMsgDMouseDown, button); -} - -void -CClientProxy1_0::mouseUp(ButtonID button) -{ - LOG((CLOG_DEBUG1 "send mouse up to \"%s\" id=%d", getName().c_str(), button)); - CProtocolUtil::writef(getStream(), kMsgDMouseUp, button); -} - -void -CClientProxy1_0::mouseMove(SInt32 xAbs, SInt32 yAbs) -{ - LOG((CLOG_DEBUG2 "send mouse move to \"%s\" %d,%d", getName().c_str(), xAbs, yAbs)); - CProtocolUtil::writef(getStream(), kMsgDMouseMove, xAbs, yAbs); -} - -void -CClientProxy1_0::mouseRelativeMove(SInt32, SInt32) -{ - // ignore -- not supported in protocol 1.0 -} - -void -CClientProxy1_0::mouseWheel(SInt32, SInt32 yDelta) -{ - // clients prior to 1.3 only support the y axis - LOG((CLOG_DEBUG2 "send mouse wheel to \"%s\" %+d", getName().c_str(), yDelta)); - CProtocolUtil::writef(getStream(), kMsgDMouseWheel1_0, yDelta); -} - -void -CClientProxy1_0::screensaver(bool on) -{ - LOG((CLOG_DEBUG1 "send screen saver to \"%s\" on=%d", getName().c_str(), on ? 1 : 0)); - CProtocolUtil::writef(getStream(), kMsgCScreenSaver, on ? 1 : 0); -} - -void -CClientProxy1_0::resetOptions() -{ - LOG((CLOG_DEBUG1 "send reset options to \"%s\"", getName().c_str())); - CProtocolUtil::writef(getStream(), kMsgCResetOptions); - - // reset heart rate and death - resetHeartbeatRate(); - removeHeartbeatTimer(); - addHeartbeatTimer(); -} - -void -CClientProxy1_0::setOptions(const COptionsList& options) -{ - LOG((CLOG_DEBUG1 "send set options to \"%s\" size=%d", getName().c_str(), options.size())); - CProtocolUtil::writef(getStream(), kMsgDSetOptions, &options); - - // check options - for (UInt32 i = 0, n = options.size(); i < n; i += 2) { - if (options[i] == kOptionHeartbeat) { - double rate = 1.0e-3 * static_cast(options[i + 1]); - if (rate <= 0.0) { - rate = -1.0; - } - setHeartbeatRate(rate, rate * kHeartBeatsUntilDeath); - removeHeartbeatTimer(); - addHeartbeatTimer(); - } - } -} - -bool -CClientProxy1_0::recvInfo() -{ - // parse the message - SInt16 x, y, w, h, dummy1, mx, my; - if (!CProtocolUtil::readf(getStream(), kMsgDInfo + 4, - &x, &y, &w, &h, &dummy1, &mx, &my)) { - return false; - } - LOG((CLOG_DEBUG "received client \"%s\" info shape=%d,%d %dx%d at %d,%d", getName().c_str(), x, y, w, h, mx, my)); - - // validate - if (w <= 0 || h <= 0) { - return false; - } - if (mx < x || mx >= x + w || my < y || my >= y + h) { - mx = x + w / 2; - my = y + h / 2; - } - - // save - m_info.m_x = x; - m_info.m_y = y; - m_info.m_w = w; - m_info.m_h = h; - m_info.m_mx = mx; - m_info.m_my = my; - - // acknowledge receipt - LOG((CLOG_DEBUG1 "send info ack to \"%s\"", getName().c_str())); - CProtocolUtil::writef(getStream(), kMsgCInfoAck); - return true; -} - -bool -CClientProxy1_0::recvClipboard() -{ - // parse message - ClipboardID id; - UInt32 seqNum; - CString data; - if (!CProtocolUtil::readf(getStream(), - kMsgDClipboard + 4, &id, &seqNum, &data)) { - return false; - } - LOG((CLOG_DEBUG "received client \"%s\" clipboard %d seqnum=%d, size=%d", getName().c_str(), id, seqNum, data.size())); - - // validate - if (id >= kClipboardEnd) { - return false; - } - - // save clipboard - m_clipboard[id].m_clipboard.unmarshall(data, 0); - m_clipboard[id].m_sequenceNumber = seqNum; - - // notify - CClipboardInfo* info = new CClipboardInfo; - info->m_id = id; - info->m_sequenceNumber = seqNum; - EVENTQUEUE->addEvent(CEvent(getClipboardChangedEvent(), - getEventTarget(), info)); - - return true; -} - -bool -CClientProxy1_0::recvGrabClipboard() -{ - // parse message - ClipboardID id; - UInt32 seqNum; - if (!CProtocolUtil::readf(getStream(), kMsgCClipboard + 4, &id, &seqNum)) { - return false; - } - LOG((CLOG_DEBUG "received client \"%s\" grabbed clipboard %d seqnum=%d", getName().c_str(), id, seqNum)); - - // validate - if (id >= kClipboardEnd) { - return false; - } - - // notify - CClipboardInfo* info = new CClipboardInfo; - info->m_id = id; - info->m_sequenceNumber = seqNum; - EVENTQUEUE->addEvent(CEvent(getClipboardGrabbedEvent(), - getEventTarget(), info)); - - return true; -} - - -// -// CClientProxy1_0::CClientClipboard -// - -CClientProxy1_0::CClientClipboard::CClientClipboard() : - m_clipboard(), - m_sequenceNumber(0), - m_dirty(true) -{ - // do nothing -} diff --git a/lib/server/CClientProxy1_0.h b/lib/server/CClientProxy1_0.h deleted file mode 100644 index 9ebfc18d..00000000 --- a/lib/server/CClientProxy1_0.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CCLIENTPROXY1_0_H -#define CCLIENTPROXY1_0_H - -#include "CClientProxy.h" -#include "CClipboard.h" -#include "ProtocolTypes.h" - -class CEvent; -class CEventQueueTimer; - -//! Proxy for client implementing protocol version 1.0 -class CClientProxy1_0 : public CClientProxy { -public: - CClientProxy1_0(const CString& name, IStream* adoptedStream); - ~CClientProxy1_0(); - - // IScreen - virtual bool getClipboard(ClipboardID id, IClipboard*) const; - virtual void getShape(SInt32& x, SInt32& y, - SInt32& width, SInt32& height) const; - virtual void getCursorPos(SInt32& x, SInt32& y) const; - - // IClient overrides - virtual void enter(SInt32 xAbs, SInt32 yAbs, - UInt32 seqNum, KeyModifierMask mask, - bool forScreensaver); - virtual bool leave(); - virtual void setClipboard(ClipboardID, const IClipboard*); - virtual void grabClipboard(ClipboardID); - virtual void setClipboardDirty(ClipboardID, bool); - virtual void keyDown(KeyID, KeyModifierMask, KeyButton); - virtual void keyRepeat(KeyID, KeyModifierMask, - SInt32 count, KeyButton); - virtual void keyUp(KeyID, KeyModifierMask, KeyButton); - virtual void mouseDown(ButtonID); - virtual void mouseUp(ButtonID); - virtual void mouseMove(SInt32 xAbs, SInt32 yAbs); - virtual void mouseRelativeMove(SInt32 xRel, SInt32 yRel); - virtual void mouseWheel(SInt32 xDelta, SInt32 yDelta); - virtual void screensaver(bool activate); - virtual void resetOptions(); - virtual void setOptions(const COptionsList& options); - -protected: - virtual bool parseHandshakeMessage(const UInt8* code); - virtual bool parseMessage(const UInt8* code); - - virtual void resetHeartbeatRate(); - virtual void setHeartbeatRate(double rate, double alarm); - virtual void resetHeartbeatTimer(); - virtual void addHeartbeatTimer(); - virtual void removeHeartbeatTimer(); - -private: - void disconnect(); - void removeHandlers(); - - void handleData(const CEvent&, void*); - void handleDisconnect(const CEvent&, void*); - void handleWriteError(const CEvent&, void*); - void handleFlatline(const CEvent&, void*); - - bool recvInfo(); - bool recvClipboard(); - bool recvGrabClipboard(); - -private: - typedef bool (CClientProxy1_0::*MessageParser)(const UInt8*); - struct CClientClipboard { - public: - CClientClipboard(); - - public: - CClipboard m_clipboard; - UInt32 m_sequenceNumber; - bool m_dirty; - }; - - CClientInfo m_info; - CClientClipboard m_clipboard[kClipboardEnd]; - double m_heartbeatAlarm; - CEventQueueTimer* m_heartbeatTimer; - MessageParser m_parser; -}; - -#endif diff --git a/lib/server/CClientProxy1_1.cpp b/lib/server/CClientProxy1_1.cpp deleted file mode 100644 index ccce9305..00000000 --- a/lib/server/CClientProxy1_1.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CClientProxy1_1.h" -#include "CProtocolUtil.h" -#include "CLog.h" -#include - -// -// CClientProxy1_1 -// - -CClientProxy1_1::CClientProxy1_1(const CString& name, IStream* stream) : - CClientProxy1_0(name, stream) -{ - // do nothing -} - -CClientProxy1_1::~CClientProxy1_1() -{ - // do nothing -} - -void -CClientProxy1_1::keyDown(KeyID key, KeyModifierMask mask, KeyButton button) -{ - LOG((CLOG_DEBUG1 "send key down to \"%s\" id=%d, mask=0x%04x, button=0x%04x", getName().c_str(), key, mask, button)); - CProtocolUtil::writef(getStream(), kMsgDKeyDown, key, mask, button); -} - -void -CClientProxy1_1::keyRepeat(KeyID key, KeyModifierMask mask, - SInt32 count, KeyButton button) -{ - LOG((CLOG_DEBUG1 "send key repeat to \"%s\" id=%d, mask=0x%04x, count=%d, button=0x%04x", getName().c_str(), key, mask, count, button)); - CProtocolUtil::writef(getStream(), kMsgDKeyRepeat, key, mask, count, button); -} - -void -CClientProxy1_1::keyUp(KeyID key, KeyModifierMask mask, KeyButton button) -{ - LOG((CLOG_DEBUG1 "send key up to \"%s\" id=%d, mask=0x%04x, button=0x%04x", getName().c_str(), key, mask, button)); - CProtocolUtil::writef(getStream(), kMsgDKeyUp, key, mask, button); -} diff --git a/lib/server/CClientProxy1_1.h b/lib/server/CClientProxy1_1.h deleted file mode 100644 index 08764829..00000000 --- a/lib/server/CClientProxy1_1.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CCLIENTPROXY1_1_H -#define CCLIENTPROXY1_1_H - -#include "CClientProxy1_0.h" - -//! Proxy for client implementing protocol version 1.1 -class CClientProxy1_1 : public CClientProxy1_0 { -public: - CClientProxy1_1(const CString& name, IStream* adoptedStream); - ~CClientProxy1_1(); - - // IClient overrides - virtual void keyDown(KeyID, KeyModifierMask, KeyButton); - virtual void keyRepeat(KeyID, KeyModifierMask, - SInt32 count, KeyButton); - virtual void keyUp(KeyID, KeyModifierMask, KeyButton); -}; - -#endif diff --git a/lib/server/CClientProxy1_2.cpp b/lib/server/CClientProxy1_2.cpp deleted file mode 100644 index 29f0a56b..00000000 --- a/lib/server/CClientProxy1_2.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CClientProxy1_2.h" -#include "CProtocolUtil.h" -#include "CLog.h" - -// -// CClientProxy1_1 -// - -CClientProxy1_2::CClientProxy1_2(const CString& name, IStream* stream) : - CClientProxy1_1(name, stream) -{ - // do nothing -} - -CClientProxy1_2::~CClientProxy1_2() -{ - // do nothing -} - -void -CClientProxy1_2::mouseRelativeMove(SInt32 xRel, SInt32 yRel) -{ - LOG((CLOG_DEBUG2 "send mouse relative move to \"%s\" %d,%d", getName().c_str(), xRel, yRel)); - CProtocolUtil::writef(getStream(), kMsgDMouseRelMove, xRel, yRel); -} diff --git a/lib/server/CClientProxy1_2.h b/lib/server/CClientProxy1_2.h deleted file mode 100644 index 3f8bb0e3..00000000 --- a/lib/server/CClientProxy1_2.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CCLIENTPROXY1_2_H -#define CCLIENTPROXY1_2_H - -#include "CClientProxy1_1.h" - -//! Proxy for client implementing protocol version 1.2 -class CClientProxy1_2 : public CClientProxy1_1 { -public: - CClientProxy1_2(const CString& name, IStream* adoptedStream); - ~CClientProxy1_2(); - - // IClient overrides - virtual void mouseRelativeMove(SInt32 xRel, SInt32 yRel); -}; - -#endif diff --git a/lib/server/CClientProxy1_3.cpp b/lib/server/CClientProxy1_3.cpp deleted file mode 100644 index f68b550e..00000000 --- a/lib/server/CClientProxy1_3.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2006 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CClientProxy1_3.h" -#include "CProtocolUtil.h" -#include "CLog.h" -#include "IEventQueue.h" -#include "TMethodEventJob.h" - -// -// CClientProxy1_3 -// - -CClientProxy1_3::CClientProxy1_3(const CString& name, IStream* stream) : - CClientProxy1_2(name, stream), - m_keepAliveRate(kKeepAliveRate), - m_keepAliveTimer(NULL) -{ - setHeartbeatRate(kKeepAliveRate, kKeepAliveRate * kKeepAlivesUntilDeath); -} - -CClientProxy1_3::~CClientProxy1_3() -{ - // cannot do this in superclass or our override wouldn't get called - removeHeartbeatTimer(); -} - -void -CClientProxy1_3::mouseWheel(SInt32 xDelta, SInt32 yDelta) -{ - LOG((CLOG_DEBUG2 "send mouse wheel to \"%s\" %+d,%+d", getName().c_str(), xDelta, yDelta)); - CProtocolUtil::writef(getStream(), kMsgDMouseWheel, xDelta, yDelta); -} - -bool -CClientProxy1_3::parseMessage(const UInt8* code) -{ - // process message - if (memcmp(code, kMsgCKeepAlive, 4) == 0) { - // reset alarm - resetHeartbeatTimer(); - return true; - } - else { - return CClientProxy1_2::parseMessage(code); - } -} - -void -CClientProxy1_3::resetHeartbeatRate() -{ - setHeartbeatRate(kKeepAliveRate, kKeepAliveRate * kKeepAlivesUntilDeath); -} - -void -CClientProxy1_3::setHeartbeatRate(double rate, double) -{ - m_keepAliveRate = rate; - CClientProxy1_2::setHeartbeatRate(rate, rate * kKeepAlivesUntilDeath); -} - -void -CClientProxy1_3::resetHeartbeatTimer() -{ - // reset the alarm but not the keep alive timer - CClientProxy1_2::removeHeartbeatTimer(); - CClientProxy1_2::addHeartbeatTimer(); -} - -void -CClientProxy1_3::addHeartbeatTimer() -{ - // create and install a timer to periodically send keep alives - if (m_keepAliveRate > 0.0) { - m_keepAliveTimer = EVENTQUEUE->newTimer(m_keepAliveRate, NULL); - EVENTQUEUE->adoptHandler(CEvent::kTimer, m_keepAliveTimer, - new TMethodEventJob(this, - &CClientProxy1_3::handleKeepAlive, NULL)); - } - - // superclass does the alarm - CClientProxy1_2::addHeartbeatTimer(); -} - -void -CClientProxy1_3::removeHeartbeatTimer() -{ - // remove the timer that sends keep alives periodically - if (m_keepAliveTimer != NULL) { - EVENTQUEUE->removeHandler(CEvent::kTimer, m_keepAliveTimer); - EVENTQUEUE->deleteTimer(m_keepAliveTimer); - m_keepAliveTimer = NULL; - } - - // superclass does the alarm - CClientProxy1_2::removeHeartbeatTimer(); -} - -void -CClientProxy1_3::handleKeepAlive(const CEvent&, void*) -{ - CProtocolUtil::writef(getStream(), kMsgCKeepAlive); -} diff --git a/lib/server/CClientProxy1_3.h b/lib/server/CClientProxy1_3.h deleted file mode 100644 index 681094b6..00000000 --- a/lib/server/CClientProxy1_3.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2006 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CCLIENTPROXY1_3_H -#define CCLIENTPROXY1_3_H - -#include "CClientProxy1_2.h" - -//! Proxy for client implementing protocol version 1.3 -class CClientProxy1_3 : public CClientProxy1_2 { -public: - CClientProxy1_3(const CString& name, IStream* adoptedStream); - ~CClientProxy1_3(); - - // IClient overrides - virtual void mouseWheel(SInt32 xDelta, SInt32 yDelta); - -protected: - // CClientProxy overrides - virtual bool parseMessage(const UInt8* code); - virtual void resetHeartbeatRate(); - virtual void setHeartbeatRate(double rate, double alarm); - virtual void resetHeartbeatTimer(); - virtual void addHeartbeatTimer(); - virtual void removeHeartbeatTimer(); - -private: - void handleKeepAlive(const CEvent&, void*); - - -private: - double m_keepAliveRate; - CEventQueueTimer* m_keepAliveTimer; -}; - -#endif diff --git a/lib/server/CClientProxyUnknown.cpp b/lib/server/CClientProxyUnknown.cpp deleted file mode 100644 index 51a25efa..00000000 --- a/lib/server/CClientProxyUnknown.cpp +++ /dev/null @@ -1,287 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CClientProxyUnknown.h" -#include "CClientProxy1_0.h" -#include "CClientProxy1_1.h" -#include "CClientProxy1_2.h" -#include "CClientProxy1_3.h" -#include "ProtocolTypes.h" -#include "CProtocolUtil.h" -#include "XSynergy.h" -#include "IStream.h" -#include "XIO.h" -#include "CLog.h" -#include "CString.h" -#include "IEventQueue.h" -#include "TMethodEventJob.h" - -// -// CClientProxyUnknown -// - -CEvent::Type CClientProxyUnknown::s_successEvent = CEvent::kUnknown; -CEvent::Type CClientProxyUnknown::s_failureEvent = CEvent::kUnknown; - -CClientProxyUnknown::CClientProxyUnknown(IStream* stream, double timeout) : - m_stream(stream), - m_proxy(NULL), - m_ready(false) -{ - EVENTQUEUE->adoptHandler(CEvent::kTimer, this, - new TMethodEventJob(this, - &CClientProxyUnknown::handleTimeout, NULL)); - m_timer = EVENTQUEUE->newOneShotTimer(timeout, this); - addStreamHandlers(); - - LOG((CLOG_DEBUG1 "saying hello")); - CProtocolUtil::writef(m_stream, kMsgHello, - kProtocolMajorVersion, - kProtocolMinorVersion); -} - -CClientProxyUnknown::~CClientProxyUnknown() -{ - removeHandlers(); - removeTimer(); - delete m_stream; - delete m_proxy; -} - -CClientProxy* -CClientProxyUnknown::orphanClientProxy() -{ - if (m_ready) { - removeHandlers(); - CClientProxy* proxy = m_proxy; - m_proxy = NULL; - return proxy; - } - else { - return NULL; - } -} - -CEvent::Type -CClientProxyUnknown::getSuccessEvent() -{ - return CEvent::registerTypeOnce(s_successEvent, - "CClientProxy::success"); -} - -CEvent::Type -CClientProxyUnknown::getFailureEvent() -{ - return CEvent::registerTypeOnce(s_failureEvent, - "CClientProxy::failure"); -} - -void -CClientProxyUnknown::sendSuccess() -{ - m_ready = true; - removeTimer(); - EVENTQUEUE->addEvent(CEvent(getSuccessEvent(), this)); -} - -void -CClientProxyUnknown::sendFailure() -{ - delete m_proxy; - m_proxy = NULL; - m_ready = false; - removeHandlers(); - removeTimer(); - EVENTQUEUE->addEvent(CEvent(getFailureEvent(), this)); -} - -void -CClientProxyUnknown::addStreamHandlers() -{ - assert(m_stream != NULL); - - EVENTQUEUE->adoptHandler(IStream::getInputReadyEvent(), - m_stream->getEventTarget(), - new TMethodEventJob(this, - &CClientProxyUnknown::handleData)); - EVENTQUEUE->adoptHandler(IStream::getOutputErrorEvent(), - m_stream->getEventTarget(), - new TMethodEventJob(this, - &CClientProxyUnknown::handleWriteError)); - EVENTQUEUE->adoptHandler(IStream::getInputShutdownEvent(), - m_stream->getEventTarget(), - new TMethodEventJob(this, - &CClientProxyUnknown::handleDisconnect)); - EVENTQUEUE->adoptHandler(IStream::getOutputShutdownEvent(), - m_stream->getEventTarget(), - new TMethodEventJob(this, - &CClientProxyUnknown::handleWriteError)); -} - -void -CClientProxyUnknown::addProxyHandlers() -{ - assert(m_proxy != NULL); - - EVENTQUEUE->adoptHandler(CClientProxy::getReadyEvent(), - m_proxy, - new TMethodEventJob(this, - &CClientProxyUnknown::handleReady)); - EVENTQUEUE->adoptHandler(CClientProxy::getDisconnectedEvent(), - m_proxy, - new TMethodEventJob(this, - &CClientProxyUnknown::handleDisconnect)); -} - -void -CClientProxyUnknown::removeHandlers() -{ - if (m_stream != NULL) { - EVENTQUEUE->removeHandler(IStream::getInputReadyEvent(), - m_stream->getEventTarget()); - EVENTQUEUE->removeHandler(IStream::getOutputErrorEvent(), - m_stream->getEventTarget()); - EVENTQUEUE->removeHandler(IStream::getInputShutdownEvent(), - m_stream->getEventTarget()); - EVENTQUEUE->removeHandler(IStream::getOutputShutdownEvent(), - m_stream->getEventTarget()); - } - if (m_proxy != NULL) { - EVENTQUEUE->removeHandler(CClientProxy::getReadyEvent(), - m_proxy); - EVENTQUEUE->removeHandler(CClientProxy::getDisconnectedEvent(), - m_proxy); - } -} - -void -CClientProxyUnknown::removeTimer() -{ - if (m_timer != NULL) { - EVENTQUEUE->deleteTimer(m_timer); - EVENTQUEUE->removeHandler(CEvent::kTimer, this); - m_timer = NULL; - } -} - -void -CClientProxyUnknown::handleData(const CEvent&, void*) -{ - LOG((CLOG_DEBUG1 "parsing hello reply")); - - CString name(""); - try { - // limit the maximum length of the hello - UInt32 n = m_stream->getSize(); - if (n > kMaxHelloLength) { - LOG((CLOG_DEBUG1 "hello reply too long")); - throw XBadClient(); - } - - // parse the reply to hello - SInt16 major, minor; - if (!CProtocolUtil::readf(m_stream, kMsgHelloBack, - &major, &minor, &name)) { - throw XBadClient(); - } - - // disallow invalid version numbers - if (major <= 0 || minor < 0) { - throw XIncompatibleClient(major, minor); - } - - // remove stream event handlers. the proxy we're about to create - // may install its own handlers and we don't want to accidentally - // remove those later. - removeHandlers(); - - // create client proxy for highest version supported by the client - if (major == 1) { - switch (minor) { - case 0: - m_proxy = new CClientProxy1_0(name, m_stream); - break; - - case 1: - m_proxy = new CClientProxy1_1(name, m_stream); - break; - - case 2: - m_proxy = new CClientProxy1_2(name, m_stream); - break; - - case 3: - m_proxy = new CClientProxy1_3(name, m_stream); - break; - } - } - - // hangup (with error) if version isn't supported - if (m_proxy == NULL) { - throw XIncompatibleClient(major, minor); - } - - // the proxy is created and now proxy now owns the stream - LOG((CLOG_DEBUG1 "created proxy for client \"%s\" version %d.%d", name.c_str(), major, minor)); - m_stream = NULL; - - // wait until the proxy signals that it's ready or has disconnected - addProxyHandlers(); - return; - } - catch (XIncompatibleClient& e) { - // client is incompatible - LOG((CLOG_WARN "client \"%s\" has incompatible version %d.%d)", name.c_str(), e.getMajor(), e.getMinor())); - CProtocolUtil::writef(m_stream, - kMsgEIncompatible, - kProtocolMajorVersion, kProtocolMinorVersion); - } - catch (XBadClient&) { - // client not behaving - LOG((CLOG_WARN "protocol error from client \"%s\"", name.c_str())); - CProtocolUtil::writef(m_stream, kMsgEBad); - } - catch (XBase& e) { - // misc error - LOG((CLOG_WARN "error communicating with client \"%s\": %s", name.c_str(), e.what())); - } - sendFailure(); -} - -void -CClientProxyUnknown::handleWriteError(const CEvent&, void*) -{ - LOG((CLOG_NOTE "error communicating with new client")); - sendFailure(); -} - -void -CClientProxyUnknown::handleTimeout(const CEvent&, void*) -{ - LOG((CLOG_NOTE "new client is unresponsive")); - sendFailure(); -} - -void -CClientProxyUnknown::handleDisconnect(const CEvent&, void*) -{ - LOG((CLOG_NOTE "new client disconnected")); - sendFailure(); -} - -void -CClientProxyUnknown::handleReady(const CEvent&, void*) -{ - sendSuccess(); -} diff --git a/lib/server/CClientProxyUnknown.h b/lib/server/CClientProxyUnknown.h deleted file mode 100644 index 140a1aee..00000000 --- a/lib/server/CClientProxyUnknown.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CCLIENTPROXYUNKNOWN_H -#define CCLIENTPROXYUNKNOWN_H - -#include "CEvent.h" - -class CClientProxy; -class CEventQueueTimer; -class IStream; - -class CClientProxyUnknown { -public: - CClientProxyUnknown(IStream* stream, double timeout); - ~CClientProxyUnknown(); - - //! @name manipulators - //@{ - - //! Get the client proxy - /*! - Returns the client proxy created after a successful handshake - (i.e. when this object sends a success event). Returns NULL - if the handshake is unsuccessful or incomplete. - */ - CClientProxy* orphanClientProxy(); - - //@} - //! @name accessors - //@{ - - //! Get success event type - /*! - Returns the success event type. This is sent when the client has - correctly responded to the hello message. The target is this. - */ - static CEvent::Type getSuccessEvent(); - - //! Get failure event type - /*! - Returns the failure event type. This is sent when a client fails - to correctly respond to the hello message. The target is this. - */ - static CEvent::Type getFailureEvent(); - - //@} - -private: - void sendSuccess(); - void sendFailure(); - void addStreamHandlers(); - void addProxyHandlers(); - void removeHandlers(); - void removeTimer(); - void handleData(const CEvent&, void*); - void handleWriteError(const CEvent&, void*); - void handleTimeout(const CEvent&, void*); - void handleDisconnect(const CEvent&, void*); - void handleReady(const CEvent&, void*); - -private: - IStream* m_stream; - CEventQueueTimer* m_timer; - CClientProxy* m_proxy; - bool m_ready; - - static CEvent::Type s_successEvent; - static CEvent::Type s_failureEvent; -}; - -#endif diff --git a/lib/server/CConfig.cpp b/lib/server/CConfig.cpp deleted file mode 100644 index 92054f42..00000000 --- a/lib/server/CConfig.cpp +++ /dev/null @@ -1,2277 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CConfig.h" -#include "CServer.h" -#include "CKeyMap.h" -#include "KeyTypes.h" -#include "XSocket.h" -#include "stdistream.h" -#include "stdostream.h" -#include - -// -// CConfig -// - -CConfig::CConfig() : m_hasLockToScreenAction(false) -{ - // do nothing -} - -CConfig::~CConfig() -{ - // do nothing -} - -bool -CConfig::addScreen(const CString& name) -{ - // alias name must not exist - if (m_nameToCanonicalName.find(name) != m_nameToCanonicalName.end()) { - return false; - } - - // add cell - m_map.insert(std::make_pair(name, CCell())); - - // add name - m_nameToCanonicalName.insert(std::make_pair(name, name)); - - return true; -} - -bool -CConfig::renameScreen(const CString& oldName, - const CString& newName) -{ - // get canonical name and find cell - CString oldCanonical = getCanonicalName(oldName); - CCellMap::iterator index = m_map.find(oldCanonical); - if (index == m_map.end()) { - return false; - } - - // accept if names are equal but replace with new name to maintain - // case. otherwise, the new name must not exist. - if (!CStringUtil::CaselessCmp::equal(oldName, newName) && - m_nameToCanonicalName.find(newName) != m_nameToCanonicalName.end()) { - return false; - } - - // update cell - CCell tmpCell = index->second; - m_map.erase(index); - m_map.insert(std::make_pair(newName, tmpCell)); - - // update name - m_nameToCanonicalName.erase(oldCanonical); - m_nameToCanonicalName.insert(std::make_pair(newName, newName)); - - // update connections - CName oldNameObj(this, oldName); - for (index = m_map.begin(); index != m_map.end(); ++index) { - index->second.rename(oldNameObj, newName); - } - - // update alias targets - if (CStringUtil::CaselessCmp::equal(oldName, oldCanonical)) { - for (CNameMap::iterator index = m_nameToCanonicalName.begin(); - index != m_nameToCanonicalName.end(); ++index) { - if (CStringUtil::CaselessCmp::equal( - index->second, oldCanonical)) { - index->second = newName; - } - } - } - - return true; -} - -void -CConfig::removeScreen(const CString& name) -{ - // get canonical name and find cell - CString canonical = getCanonicalName(name); - CCellMap::iterator index = m_map.find(canonical); - if (index == m_map.end()) { - return; - } - - // remove from map - m_map.erase(index); - - // disconnect - CName nameObj(this, name); - for (index = m_map.begin(); index != m_map.end(); ++index) { - index->second.remove(nameObj); - } - - // remove aliases (and canonical name) - for (CNameMap::iterator index = m_nameToCanonicalName.begin(); - index != m_nameToCanonicalName.end(); ) { - if (index->second == canonical) { - m_nameToCanonicalName.erase(index++); - } - else { - ++index; - } - } -} - -void -CConfig::removeAllScreens() -{ - m_map.clear(); - m_nameToCanonicalName.clear(); -} - -bool -CConfig::addAlias(const CString& canonical, const CString& alias) -{ - // alias name must not exist - if (m_nameToCanonicalName.find(alias) != m_nameToCanonicalName.end()) { - return false; - } - - // canonical name must be known - if (m_map.find(canonical) == m_map.end()) { - return false; - } - - // insert alias - m_nameToCanonicalName.insert(std::make_pair(alias, canonical)); - - return true; -} - -bool -CConfig::removeAlias(const CString& alias) -{ - // must not be a canonical name - if (m_map.find(alias) != m_map.end()) { - return false; - } - - // find alias - CNameMap::iterator index = m_nameToCanonicalName.find(alias); - if (index == m_nameToCanonicalName.end()) { - return false; - } - - // remove alias - m_nameToCanonicalName.erase(index); - - return true; -} - -bool -CConfig::removeAliases(const CString& canonical) -{ - // must be a canonical name - if (m_map.find(canonical) == m_map.end()) { - return false; - } - - // find and removing matching aliases - for (CNameMap::iterator index = m_nameToCanonicalName.begin(); - index != m_nameToCanonicalName.end(); ) { - if (index->second == canonical && index->first != canonical) { - m_nameToCanonicalName.erase(index++); - } - else { - ++index; - } - } - - return true; -} - -void -CConfig::removeAllAliases() -{ - // remove all names - m_nameToCanonicalName.clear(); - - // put the canonical names back in - for (CCellMap::iterator index = m_map.begin(); - index != m_map.end(); ++index) { - m_nameToCanonicalName.insert( - std::make_pair(index->first, index->first)); - } -} - -bool -CConfig::connect(const CString& srcName, - EDirection srcSide, - float srcStart, float srcEnd, - const CString& dstName, - float dstStart, float dstEnd) -{ - assert(srcSide >= kFirstDirection && srcSide <= kLastDirection); - - // find source cell - CCellMap::iterator index = m_map.find(getCanonicalName(srcName)); - if (index == m_map.end()) { - return false; - } - - // add link - CCellEdge srcEdge(srcSide, CInterval(srcStart, srcEnd)); - CCellEdge dstEdge(dstName, srcSide, CInterval(dstStart, dstEnd)); - return index->second.add(srcEdge, dstEdge); -} - -bool -CConfig::disconnect(const CString& srcName, EDirection srcSide) -{ - assert(srcSide >= kFirstDirection && srcSide <= kLastDirection); - - // find source cell - CCellMap::iterator index = m_map.find(srcName); - if (index == m_map.end()) { - return false; - } - - // disconnect side - index->second.remove(srcSide); - - return true; -} - -bool -CConfig::disconnect(const CString& srcName, EDirection srcSide, float position) -{ - assert(srcSide >= kFirstDirection && srcSide <= kLastDirection); - - // find source cell - CCellMap::iterator index = m_map.find(srcName); - if (index == m_map.end()) { - return false; - } - - // disconnect side - index->second.remove(srcSide, position); - - return true; -} - -void -CConfig::setSynergyAddress(const CNetworkAddress& addr) -{ - m_synergyAddress = addr; -} - -bool -CConfig::addOption(const CString& name, OptionID option, OptionValue value) -{ - // find options - CScreenOptions* options = NULL; - if (name.empty()) { - options = &m_globalOptions; - } - else { - CCellMap::iterator index = m_map.find(name); - if (index != m_map.end()) { - options = &index->second.m_options; - } - } - if (options == NULL) { - return false; - } - - // add option - options->insert(std::make_pair(option, value)); - return true; -} - -bool -CConfig::removeOption(const CString& name, OptionID option) -{ - // find options - CScreenOptions* options = NULL; - if (name.empty()) { - options = &m_globalOptions; - } - else { - CCellMap::iterator index = m_map.find(name); - if (index != m_map.end()) { - options = &index->second.m_options; - } - } - if (options == NULL) { - return false; - } - - // remove option - options->erase(option); - return true; -} - -bool -CConfig::removeOptions(const CString& name) -{ - // find options - CScreenOptions* options = NULL; - if (name.empty()) { - options = &m_globalOptions; - } - else { - CCellMap::iterator index = m_map.find(name); - if (index != m_map.end()) { - options = &index->second.m_options; - } - } - if (options == NULL) { - return false; - } - - // remove options - options->clear(); - return true; -} - -bool -CConfig::isValidScreenName(const CString& name) const -{ - // name is valid if matches validname - // name ::= [_A-Za-z0-9] | [_A-Za-z0-9][-_A-Za-z0-9]*[_A-Za-z0-9] - // domain ::= . name - // validname ::= name domain* - // we also accept names ending in . because many OS X users have - // so misconfigured their systems. - - // empty name is invalid - if (name.empty()) { - return false; - } - - // check each dot separated part - CString::size_type b = 0; - for (;;) { - // accept trailing . - if (b == name.size()) { - break; - } - - // find end of part - CString::size_type e = name.find('.', b); - if (e == CString::npos) { - e = name.size(); - } - - // part may not be empty - if (e - b < 1) { - return false; - } - - // check first and last characters - if (!(isalnum(name[b]) || name[b] == '_') || - !(isalnum(name[e - 1]) || name[e - 1] == '_')) { - return false; - } - - // check interior characters - for (CString::size_type i = b; i < e; ++i) { - if (!isalnum(name[i]) && name[i] != '_' && name[i] != '-') { - return false; - } - } - - // next part - if (e == name.size()) { - // no more parts - break; - } - b = e + 1; - } - - return true; -} - -CConfig::const_iterator -CConfig::begin() const -{ - return const_iterator(m_map.begin()); -} - -CConfig::const_iterator -CConfig::end() const -{ - return const_iterator(m_map.end()); -} - -CConfig::all_const_iterator -CConfig::beginAll() const -{ - return m_nameToCanonicalName.begin(); -} - -CConfig::all_const_iterator -CConfig::endAll() const -{ - return m_nameToCanonicalName.end(); -} - -bool -CConfig::isScreen(const CString& name) const -{ - return (m_nameToCanonicalName.count(name) > 0); -} - -bool -CConfig::isCanonicalName(const CString& name) const -{ - return (!name.empty() && - CStringUtil::CaselessCmp::equal(getCanonicalName(name), name)); -} - -CString -CConfig::getCanonicalName(const CString& name) const -{ - CNameMap::const_iterator index = m_nameToCanonicalName.find(name); - if (index == m_nameToCanonicalName.end()) { - return CString(); - } - else { - return index->second; - } -} - -CString -CConfig::getNeighbor(const CString& srcName, EDirection srcSide, - float position, float* positionOut) const -{ - assert(srcSide >= kFirstDirection && srcSide <= kLastDirection); - - // find source cell - CCellMap::const_iterator index = m_map.find(getCanonicalName(srcName)); - if (index == m_map.end()) { - return CString(); - } - - // find edge - const CCellEdge* srcEdge, *dstEdge; - if (!index->second.getLink(srcSide, position, srcEdge, dstEdge)) { - // no neighbor - return ""; - } - else { - // compute position on neighbor - if (positionOut != NULL) { - *positionOut = - dstEdge->inverseTransform(srcEdge->transform(position)); - } - - // return neighbor's name - return getCanonicalName(dstEdge->getName()); - } -} - -bool -CConfig::hasNeighbor(const CString& srcName, EDirection srcSide) const -{ - return hasNeighbor(srcName, srcSide, 0.0f, 1.0f); -} - -bool -CConfig::hasNeighbor(const CString& srcName, EDirection srcSide, - float start, float end) const -{ - assert(srcSide >= kFirstDirection && srcSide <= kLastDirection); - - // find source cell - CCellMap::const_iterator index = m_map.find(getCanonicalName(srcName)); - if (index == m_map.end()) { - return false; - } - - return index->second.overlaps(CCellEdge(srcSide, CInterval(start, end))); -} - -CConfig::link_const_iterator -CConfig::beginNeighbor(const CString& srcName) const -{ - CCellMap::const_iterator index = m_map.find(getCanonicalName(srcName)); - assert(index != m_map.end()); - return index->second.begin(); -} - -CConfig::link_const_iterator -CConfig::endNeighbor(const CString& srcName) const -{ - CCellMap::const_iterator index = m_map.find(getCanonicalName(srcName)); - assert(index != m_map.end()); - return index->second.end(); -} - -const CNetworkAddress& -CConfig::getSynergyAddress() const -{ - return m_synergyAddress; -} - -const CConfig::CScreenOptions* -CConfig::getOptions(const CString& name) const -{ - // find options - const CScreenOptions* options = NULL; - if (name.empty()) { - options = &m_globalOptions; - } - else { - CCellMap::const_iterator index = m_map.find(name); - if (index != m_map.end()) { - options = &index->second.m_options; - } - } - - // return options - return options; -} - -bool -CConfig::hasLockToScreenAction() const -{ - return m_hasLockToScreenAction; -} - -bool -CConfig::operator==(const CConfig& x) const -{ - if (m_synergyAddress != x.m_synergyAddress) { - return false; - } - if (m_map.size() != x.m_map.size()) { - return false; - } - if (m_nameToCanonicalName.size() != x.m_nameToCanonicalName.size()) { - return false; - } - - // compare global options - if (m_globalOptions != x.m_globalOptions) { - return false; - } - - for (CCellMap::const_iterator index1 = m_map.begin(), - index2 = x.m_map.begin(); - index1 != m_map.end(); ++index1, ++index2) { - // compare names - if (!CStringUtil::CaselessCmp::equal(index1->first, index2->first)) { - return false; - } - - // compare cells - if (index1->second != index2->second) { - return false; - } - } - - for (CNameMap::const_iterator index1 = m_nameToCanonicalName.begin(), - index2 = x.m_nameToCanonicalName.begin(); - index1 != m_nameToCanonicalName.end(); - ++index1, ++index2) { - if (!CStringUtil::CaselessCmp::equal(index1->first, index2->first) || - !CStringUtil::CaselessCmp::equal(index1->second, index2->second)) { - return false; - } - } - - // compare input filters - if (m_inputFilter != x.m_inputFilter) { - return false; - } - - return true; -} - -bool -CConfig::operator!=(const CConfig& x) const -{ - return !operator==(x); -} - -void -CConfig::read(CConfigReadContext& context) -{ - CConfig tmp; - while (context) { - tmp.readSection(context); - } - *this = tmp; -} - -const char* -CConfig::dirName(EDirection dir) -{ - static const char* s_name[] = { "left", "right", "up", "down" }; - - assert(dir >= kFirstDirection && dir <= kLastDirection); - - return s_name[dir - kFirstDirection]; -} - -CInputFilter* -CConfig::getInputFilter() -{ - return &m_inputFilter; -} - -CString -CConfig::formatInterval(const CInterval& x) -{ - if (x.first == 0.0f && x.second == 1.0f) { - return ""; - } - return CStringUtil::print("(%d,%d)", (int)(x.first * 100.0f + 0.5f), - (int)(x.second * 100.0f + 0.5f)); -} - -void -CConfig::readSection(CConfigReadContext& s) -{ - static const char s_section[] = "section:"; - static const char s_options[] = "options"; - static const char s_screens[] = "screens"; - static const char s_links[] = "links"; - static const char s_aliases[] = "aliases"; - - CString line; - if (!s.readLine(line)) { - // no more sections - return; - } - - // should be a section header - if (line.find(s_section) != 0) { - throw XConfigRead(s, "found data outside section"); - } - - // get section name - CString::size_type i = line.find_first_not_of(" \t", sizeof(s_section) - 1); - if (i == CString::npos) { - throw XConfigRead(s, "section name is missing"); - } - CString name = line.substr(i); - i = name.find_first_of(" \t"); - if (i != CString::npos) { - throw XConfigRead(s, "unexpected data after section name"); - } - - // read section - if (name == s_options) { - readSectionOptions(s); - } - else if (name == s_screens) { - readSectionScreens(s); - } - else if (name == s_links) { - readSectionLinks(s); - } - else if (name == s_aliases) { - readSectionAliases(s); - } - else { - throw XConfigRead(s, "unknown section name \"%{1}\"", name); - } -} - -void -CConfig::readSectionOptions(CConfigReadContext& s) -{ - CString line; - while (s.readLine(line)) { - // check for end of section - if (line == "end") { - return; - } - - // parse argument: `nameAndArgs = [values][;[values]]' - // nameAndArgs := [(arg[,...])] - // values := valueAndArgs[,valueAndArgs]... - // valueAndArgs := [(arg[,...])] - CString::size_type i = 0; - CString name, value; - CConfigReadContext::ArgList nameArgs, valueArgs; - s.parseNameWithArgs("name", line, "=", i, name, nameArgs); - ++i; - s.parseNameWithArgs("value", line, ",;\n", i, value, valueArgs); - - bool handled = true; - if (name == "address") { - try { - m_synergyAddress = CNetworkAddress(value, kDefaultPort); - m_synergyAddress.resolve(); - } - catch (XSocketAddress& e) { - throw XConfigRead(s, - CString("invalid address argument ") + e.what()); - } - } - else if (name == "heartbeat") { - addOption("", kOptionHeartbeat, s.parseInt(value)); - } - else if (name == "switchCorners") { - addOption("", kOptionScreenSwitchCorners, s.parseCorners(value)); - } - else if (name == "switchCornerSize") { - addOption("", kOptionScreenSwitchCornerSize, s.parseInt(value)); - } - else if (name == "switchDelay") { - addOption("", kOptionScreenSwitchDelay, s.parseInt(value)); - } - else if (name == "switchDoubleTap") { - addOption("", kOptionScreenSwitchTwoTap, s.parseInt(value)); - } - else if (name == "screenSaverSync") { - addOption("", kOptionScreenSaverSync, s.parseBoolean(value)); - } - else if (name == "relativeMouseMoves") { - addOption("", kOptionRelativeMouseMoves, s.parseBoolean(value)); - } - else if (name == "win32KeepForeground") { - addOption("", kOptionWin32KeepForeground, s.parseBoolean(value)); - } - else { - handled = false; - } - - if (handled) { - // make sure handled options aren't followed by more values - if (i < line.size() && (line[i] == ',' || line[i] == ';')) { - throw XConfigRead(s, "to many arguments to %s", name.c_str()); - } - } - else { - // make filter rule - CInputFilter::CRule rule(parseCondition(s, name, nameArgs)); - - // save first action (if any) - if (!value.empty() || line[i] != ';') { - parseAction(s, value, valueArgs, rule, true); - } - - // get remaining activate actions - while (i < line.length() && line[i] != ';') { - ++i; - s.parseNameWithArgs("value", line, ",;\n", i, value, valueArgs); - parseAction(s, value, valueArgs, rule, true); - } - - // get deactivate actions - if (i < line.length() && line[i] == ';') { - // allow trailing ';' - i = line.find_first_not_of(" \t", i + 1); - if (i == CString::npos) { - i = line.length(); - } - else { - --i; - } - - // get actions - while (i < line.length()) { - ++i; - s.parseNameWithArgs("value", line, ",\n", - i, value, valueArgs); - parseAction(s, value, valueArgs, rule, false); - } - } - - // add rule - m_inputFilter.addFilterRule(rule); - } - } - throw XConfigRead(s, "unexpected end of options section"); -} - -void -CConfig::readSectionScreens(CConfigReadContext& s) -{ - CString line; - CString screen; - while (s.readLine(line)) { - // check for end of section - if (line == "end") { - return; - } - - // see if it's the next screen - if (line[line.size() - 1] == ':') { - // strip : - screen = line.substr(0, line.size() - 1); - - // verify validity of screen name - if (!isValidScreenName(screen)) { - throw XConfigRead(s, "invalid screen name \"%{1}\"", screen); - } - - // add the screen to the configuration - if (!addScreen(screen)) { - throw XConfigRead(s, "duplicate screen name \"%{1}\"", screen); - } - } - else if (screen.empty()) { - throw XConfigRead(s, "argument before first screen"); - } - else { - // parse argument: `=' - CString::size_type i = line.find_first_of(" \t="); - if (i == 0) { - throw XConfigRead(s, "missing argument name"); - } - if (i == CString::npos) { - throw XConfigRead(s, "missing ="); - } - CString name = line.substr(0, i); - i = line.find_first_not_of(" \t", i); - if (i == CString::npos || line[i] != '=') { - throw XConfigRead(s, "missing ="); - } - i = line.find_first_not_of(" \t", i + 1); - CString value; - if (i != CString::npos) { - value = line.substr(i); - } - - // handle argument - if (name == "halfDuplexCapsLock") { - addOption(screen, kOptionHalfDuplexCapsLock, - s.parseBoolean(value)); - } - else if (name == "halfDuplexNumLock") { - addOption(screen, kOptionHalfDuplexNumLock, - s.parseBoolean(value)); - } - else if (name == "halfDuplexScrollLock") { - addOption(screen, kOptionHalfDuplexScrollLock, - s.parseBoolean(value)); - } - else if (name == "shift") { - addOption(screen, kOptionModifierMapForShift, - s.parseModifierKey(value)); - } - else if (name == "ctrl") { - addOption(screen, kOptionModifierMapForControl, - s.parseModifierKey(value)); - } - else if (name == "alt") { - addOption(screen, kOptionModifierMapForAlt, - s.parseModifierKey(value)); - } - else if (name == "meta") { - addOption(screen, kOptionModifierMapForMeta, - s.parseModifierKey(value)); - } - else if (name == "super") { - addOption(screen, kOptionModifierMapForSuper, - s.parseModifierKey(value)); - } - else if (name == "xtestIsXineramaUnaware") { - addOption(screen, kOptionXTestXineramaUnaware, - s.parseBoolean(value)); - } - else if (name == "switchCorners") { - addOption(screen, kOptionScreenSwitchCorners, - s.parseCorners(value)); - } - else if (name == "switchCornerSize") { - addOption(screen, kOptionScreenSwitchCornerSize, - s.parseInt(value)); - } - else { - // unknown argument - throw XConfigRead(s, "unknown argument \"%{1}\"", name); - } - } - } - throw XConfigRead(s, "unexpected end of screens section"); -} - -void -CConfig::readSectionLinks(CConfigReadContext& s) -{ - CString line; - CString screen; - while (s.readLine(line)) { - // check for end of section - if (line == "end") { - return; - } - - // see if it's the next screen - if (line[line.size() - 1] == ':') { - // strip : - screen = line.substr(0, line.size() - 1); - - // verify we know about the screen - if (!isScreen(screen)) { - throw XConfigRead(s, "unknown screen name \"%{1}\"", screen); - } - if (!isCanonicalName(screen)) { - throw XConfigRead(s, "cannot use screen name alias here"); - } - } - else if (screen.empty()) { - throw XConfigRead(s, "argument before first screen"); - } - else { - // parse argument: `[(,)]=[(,)]' - // the stuff in brackets is optional. interval values must be - // in the range [0,100] and start < end. if not given the - // interval is taken to be (0,100). - CString::size_type i = 0; - CString side, dstScreen, srcArgString, dstArgString; - CConfigReadContext::ArgList srcArgs, dstArgs; - s.parseNameWithArgs("link", line, "=", i, side, srcArgs); - ++i; - s.parseNameWithArgs("screen", line, "", i, dstScreen, dstArgs); - CInterval srcInterval(s.parseInterval(srcArgs)); - CInterval dstInterval(s.parseInterval(dstArgs)); - - // handle argument - EDirection dir; - if (side == "left") { - dir = kLeft; - } - else if (side == "right") { - dir = kRight; - } - else if (side == "up") { - dir = kTop; - } - else if (side == "down") { - dir = kBottom; - } - else { - // unknown argument - throw XConfigRead(s, "unknown side \"%{1}\" in link", side); - } - if (!isScreen(dstScreen)) { - throw XConfigRead(s, "unknown screen name \"%{1}\"", dstScreen); - } - if (!connect(screen, dir, - srcInterval.first, srcInterval.second, - dstScreen, - dstInterval.first, dstInterval.second)) { - throw XConfigRead(s, "overlapping range"); - } - } - } - throw XConfigRead(s, "unexpected end of links section"); -} - -void -CConfig::readSectionAliases(CConfigReadContext& s) -{ - CString line; - CString screen; - while (s.readLine(line)) { - // check for end of section - if (line == "end") { - return; - } - - // see if it's the next screen - if (line[line.size() - 1] == ':') { - // strip : - screen = line.substr(0, line.size() - 1); - - // verify we know about the screen - if (!isScreen(screen)) { - throw XConfigRead(s, "unknown screen name \"%{1}\"", screen); - } - if (!isCanonicalName(screen)) { - throw XConfigRead(s, "cannot use screen name alias here"); - } - } - else if (screen.empty()) { - throw XConfigRead(s, "argument before first screen"); - } - else { - // verify validity of screen name - if (!isValidScreenName(line)) { - throw XConfigRead(s, "invalid screen alias \"%{1}\"", line); - } - - // add alias - if (!addAlias(screen, line)) { - throw XConfigRead(s, "alias \"%{1}\" is already used", line); - } - } - } - throw XConfigRead(s, "unexpected end of aliases section"); -} - - -CInputFilter::CCondition* -CConfig::parseCondition(CConfigReadContext& s, - const CString& name, const std::vector& args) -{ - if (name == "keystroke") { - if (args.size() != 1) { - throw XConfigRead(s, "syntax for condition: keystroke(modifiers+key)"); - } - - IPlatformScreen::CKeyInfo* keyInfo = s.parseKeystroke(args[0]); - - return new CInputFilter::CKeystrokeCondition(keyInfo); - } - - if (name == "mousebutton") { - if (args.size() != 1) { - throw XConfigRead(s, "syntax for condition: mousebutton(modifiers+button)"); - } - - IPlatformScreen::CButtonInfo* mouseInfo = s.parseMouse(args[0]); - - return new CInputFilter::CMouseButtonCondition(mouseInfo); - } - - if (name == "connect") { - if (args.size() != 1) { - throw XConfigRead(s, "syntax for condition: connect([screen])"); - } - - CString screen = args[0]; - if (isScreen(screen)) { - screen = getCanonicalName(screen); - } - else if (!screen.empty()) { - throw XConfigRead(s, "unknown screen name \"%{1}\" in connect", screen); - } - - return new CInputFilter::CScreenConnectedCondition(screen); - } - - throw XConfigRead(s, "unknown argument \"%{1}\"", name); -} - -void -CConfig::parseAction(CConfigReadContext& s, - const CString& name, const std::vector& args, - CInputFilter::CRule& rule, bool activate) -{ - CInputFilter::CAction* action; - - if (name == "keystroke" || name == "keyDown" || name == "keyUp") { - if (args.size() < 1 || args.size() > 2) { - throw XConfigRead(s, "syntax for action: keystroke(modifiers+key[,screens])"); - } - - IPlatformScreen::CKeyInfo* keyInfo; - if (args.size() == 1) { - keyInfo = s.parseKeystroke(args[0]); - } - else { - std::set screens; - parseScreens(s, args[1], screens); - keyInfo = s.parseKeystroke(args[0], screens); - } - - if (name == "keystroke") { - IPlatformScreen::CKeyInfo* keyInfo2 = - IKeyState::CKeyInfo::alloc(*keyInfo); - action = new CInputFilter::CKeystrokeAction(keyInfo2, true); - rule.adoptAction(action, true); - action = new CInputFilter::CKeystrokeAction(keyInfo, false); - activate = false; - } - else if (name == "keyDown") { - action = new CInputFilter::CKeystrokeAction(keyInfo, true); - } - else { - action = new CInputFilter::CKeystrokeAction(keyInfo, false); - } - } - - else if (name == "mousebutton" || - name == "mouseDown" || name == "mouseUp") { - if (args.size() != 1) { - throw XConfigRead(s, "syntax for action: mousebutton(modifiers+button)"); - } - - IPlatformScreen::CButtonInfo* mouseInfo = s.parseMouse(args[0]); - - if (name == "mousebutton") { - IPlatformScreen::CButtonInfo* mouseInfo2 = - IPlatformScreen::CButtonInfo::alloc(*mouseInfo); - action = new CInputFilter::CMouseButtonAction(mouseInfo2, true); - rule.adoptAction(action, true); - action = new CInputFilter::CMouseButtonAction(mouseInfo, false); - activate = false; - } - else if (name == "mouseDown") { - action = new CInputFilter::CMouseButtonAction(mouseInfo, true); - } - else { - action = new CInputFilter::CMouseButtonAction(mouseInfo, false); - } - } - -/* XXX -- not supported - else if (name == "modifier") { - if (args.size() != 1) { - throw XConfigRead(s, "syntax for action: modifier(modifiers)"); - } - - KeyModifierMask mask = s.parseModifier(args[0]); - - action = new CInputFilter::CModifierAction(mask, ~mask); - } -*/ - - else if (name == "switchToScreen") { - if (args.size() != 1) { - throw XConfigRead(s, "syntax for action: switchToScreen(name)"); - } - - CString screen = args[0]; - if (isScreen(screen)) { - screen = getCanonicalName(screen); - } - else if (!screen.empty()) { - throw XConfigRead(s, "unknown screen name in switchToScreen"); - } - - action = new CInputFilter::CSwitchToScreenAction(screen); - } - - else if (name == "switchInDirection") { - if (args.size() != 1) { - throw XConfigRead(s, "syntax for action: switchInDirection()"); - } - - EDirection direction; - if (args[0] == "left") { - direction = kLeft; - } - else if (args[0] == "right") { - direction = kRight; - } - else if (args[0] == "up") { - direction = kTop; - } - else if (args[0] == "down") { - direction = kBottom; - } - else { - throw XConfigRead(s, "unknown direction \"%{1}\" in switchToScreen", args[0]); - } - - action = new CInputFilter::CSwitchInDirectionAction(direction); - } - - else if (name == "lockCursorToScreen") { - if (args.size() > 1) { - throw XConfigRead(s, "syntax for action: lockCursorToScreen([{off|on|toggle}])"); - } - - CInputFilter::CLockCursorToScreenAction::Mode mode = - CInputFilter::CLockCursorToScreenAction::kToggle; - if (args.size() == 1) { - if (args[0] == "off") { - mode = CInputFilter::CLockCursorToScreenAction::kOff; - } - else if (args[0] == "on") { - mode = CInputFilter::CLockCursorToScreenAction::kOn; - } - else if (args[0] == "toggle") { - mode = CInputFilter::CLockCursorToScreenAction::kToggle; - } - else { - throw XConfigRead(s, "syntax for action: lockCursorToScreen([{off|on|toggle}])"); - } - } - - if (mode != CInputFilter::CLockCursorToScreenAction::kOff) { - m_hasLockToScreenAction = true; - } - - action = new CInputFilter::CLockCursorToScreenAction(mode); - } - - else if (name == "keyboardBroadcast") { - if (args.size() > 2) { - throw XConfigRead(s, "syntax for action: keyboardBroadcast([{off|on|toggle}[,screens]])"); - } - - CInputFilter::CKeyboardBroadcastAction::Mode mode = - CInputFilter::CKeyboardBroadcastAction::kToggle; - if (args.size() >= 1) { - if (args[0] == "off") { - mode = CInputFilter::CKeyboardBroadcastAction::kOff; - } - else if (args[0] == "on") { - mode = CInputFilter::CKeyboardBroadcastAction::kOn; - } - else if (args[0] == "toggle") { - mode = CInputFilter::CKeyboardBroadcastAction::kToggle; - } - else { - throw XConfigRead(s, "syntax for action: keyboardBroadcast([{off|on|toggle}[,screens]])"); - } - } - - std::set screens; - if (args.size() >= 2) { - parseScreens(s, args[1], screens); - } - - action = new CInputFilter::CKeyboardBroadcastAction(mode, screens); - } - - else { - throw XConfigRead(s, "unknown action argument \"%{1}\"", name); - } - - rule.adoptAction(action, activate); -} - -void -CConfig::parseScreens(CConfigReadContext& c, - const CString& s, std::set& screens) const -{ - screens.clear(); - - CString::size_type i = 0; - while (i < s.size()) { - // find end of next screen name - CString::size_type j = s.find(':', i); - if (j == CString::npos) { - j = s.size(); - } - - // extract name - CString rawName; - i = s.find_first_not_of(" \t", i); - if (i < j) { - rawName = s.substr(i, s.find_last_not_of(" \t", j - 1) - i + 1); - } - - // add name - if (rawName == "*") { - screens.insert("*"); - } - else if (!rawName.empty()) { - CString name = getCanonicalName(rawName); - if (name.empty()) { - throw XConfigRead(c, "unknown screen name \"%{1}\"", rawName); - } - screens.insert(name); - } - - // next - i = j + 1; - } -} - -const char* -CConfig::getOptionName(OptionID id) -{ - if (id == kOptionHalfDuplexCapsLock) { - return "halfDuplexCapsLock"; - } - if (id == kOptionHalfDuplexNumLock) { - return "halfDuplexNumLock"; - } - if (id == kOptionHalfDuplexScrollLock) { - return "halfDuplexScrollLock"; - } - if (id == kOptionModifierMapForShift) { - return "shift"; - } - if (id == kOptionModifierMapForControl) { - return "ctrl"; - } - if (id == kOptionModifierMapForAlt) { - return "alt"; - } - if (id == kOptionModifierMapForMeta) { - return "meta"; - } - if (id == kOptionModifierMapForSuper) { - return "super"; - } - if (id == kOptionHeartbeat) { - return "heartbeat"; - } - if (id == kOptionScreenSwitchCorners) { - return "switchCorners"; - } - if (id == kOptionScreenSwitchCornerSize) { - return "switchCornerSize"; - } - if (id == kOptionScreenSwitchDelay) { - return "switchDelay"; - } - if (id == kOptionScreenSwitchTwoTap) { - return "switchDoubleTap"; - } - if (id == kOptionScreenSaverSync) { - return "screenSaverSync"; - } - if (id == kOptionXTestXineramaUnaware) { - return "xtestIsXineramaUnaware"; - } - if (id == kOptionRelativeMouseMoves) { - return "relativeMouseMoves"; - } - if (id == kOptionWin32KeepForeground) { - return "win32KeepForeground"; - } - return NULL; -} - -CString -CConfig::getOptionValue(OptionID id, OptionValue value) -{ - if (id == kOptionHalfDuplexCapsLock || - id == kOptionHalfDuplexNumLock || - id == kOptionHalfDuplexScrollLock || - id == kOptionScreenSaverSync || - id == kOptionXTestXineramaUnaware || - id == kOptionRelativeMouseMoves || - id == kOptionWin32KeepForeground) { - return (value != 0) ? "true" : "false"; - } - if (id == kOptionModifierMapForShift || - id == kOptionModifierMapForControl || - id == kOptionModifierMapForAlt || - id == kOptionModifierMapForMeta || - id == kOptionModifierMapForSuper) { - switch (value) { - case kKeyModifierIDShift: - return "shift"; - - case kKeyModifierIDControl: - return "ctrl"; - - case kKeyModifierIDAlt: - return "alt"; - - case kKeyModifierIDMeta: - return "meta"; - - case kKeyModifierIDSuper: - return "super"; - - default: - return "none"; - } - } - if (id == kOptionHeartbeat || - id == kOptionScreenSwitchCornerSize || - id == kOptionScreenSwitchDelay || - id == kOptionScreenSwitchTwoTap) { - return CStringUtil::print("%d", value); - } - if (id == kOptionScreenSwitchCorners) { - std::string result("none"); - if ((value & kTopLeftMask) != 0) { - result += " +top-left"; - } - if ((value & kTopRightMask) != 0) { - result += " +top-right"; - } - if ((value & kBottomLeftMask) != 0) { - result += " +bottom-left"; - } - if ((value & kBottomRightMask) != 0) { - result += " +bottom-right"; - } - return result; - } - - return ""; -} - - -// -// CConfig::CName -// - -CConfig::CName::CName(CConfig* config, const CString& name) : - m_config(config), - m_name(config->getCanonicalName(name)) -{ - // do nothing -} - -bool -CConfig::CName::operator==(const CString& name) const -{ - CString canonical = m_config->getCanonicalName(name); - return CStringUtil::CaselessCmp::equal(canonical, m_name); -} - - -// -// CConfig::CCellEdge -// - -CConfig::CCellEdge::CCellEdge(EDirection side, float position) -{ - init("", side, CInterval(position, position)); -} - -CConfig::CCellEdge::CCellEdge(EDirection side, const CInterval& interval) -{ - assert(interval.first >= 0.0f); - assert(interval.second <= 1.0f); - assert(interval.first < interval.second); - - init("", side, interval); -} - -CConfig::CCellEdge::CCellEdge(const CString& name, - EDirection side, const CInterval& interval) -{ - assert(interval.first >= 0.0f); - assert(interval.second <= 1.0f); - assert(interval.first < interval.second); - - init(name, side, interval); -} - -CConfig::CCellEdge::~CCellEdge() -{ - // do nothing -} - -void -CConfig::CCellEdge::init(const CString& name, EDirection side, - const CInterval& interval) -{ - assert(side != kNoDirection); - - m_name = name; - m_side = side; - m_interval = interval; -} - -CConfig::CInterval -CConfig::CCellEdge::getInterval() const -{ - return m_interval; -} - -void -CConfig::CCellEdge::setName(const CString& newName) -{ - m_name = newName; -} - -CString -CConfig::CCellEdge::getName() const -{ - return m_name; -} - -EDirection -CConfig::CCellEdge::getSide() const -{ - return m_side; -} - -bool -CConfig::CCellEdge::overlaps(const CCellEdge& edge) const -{ - const CInterval& x = m_interval; - const CInterval& y = edge.m_interval; - if (m_side != edge.m_side) { - return false; - } - return (x.first >= y.first && x.first < y.second) || - (x.second > y.first && x.second <= y.second) || - (y.first >= x.first && y.first < x.second) || - (y.second > x.first && y.second <= x.second); -} - -bool -CConfig::CCellEdge::isInside(float x) const -{ - return (x >= m_interval.first && x < m_interval.second); -} - -float -CConfig::CCellEdge::transform(float x) const -{ - return (x - m_interval.first) / (m_interval.second - m_interval.first); -} - - -float -CConfig::CCellEdge::inverseTransform(float x) const -{ - return x * (m_interval.second - m_interval.first) + m_interval.first; -} - -bool -CConfig::CCellEdge::operator<(const CCellEdge& o) const -{ - if (static_cast(m_side) < static_cast(o.m_side)) { - return true; - } - else if (static_cast(m_side) > static_cast(o.m_side)) { - return false; - } - - return (m_interval.first < o.m_interval.first); -} - -bool -CConfig::CCellEdge::operator==(const CCellEdge& x) const -{ - return (m_side == x.m_side && m_interval == x.m_interval); -} - -bool -CConfig::CCellEdge::operator!=(const CCellEdge& x) const -{ - return !operator==(x); -} - - -// -// CConfig::CCell -// - -bool -CConfig::CCell::add(const CCellEdge& src, const CCellEdge& dst) -{ - // cannot add an edge that overlaps other existing edges but we - // can exactly replace an edge. - if (!hasEdge(src) && overlaps(src)) { - return false; - } - - m_neighbors.erase(src); - m_neighbors.insert(std::make_pair(src, dst)); - return true; -} - -void -CConfig::CCell::remove(EDirection side) -{ - for (CEdgeLinks::iterator j = m_neighbors.begin(); - j != m_neighbors.end(); ) { - if (j->first.getSide() == side) { - m_neighbors.erase(j++); - } - else { - ++j; - } - } -} - -void -CConfig::CCell::remove(EDirection side, float position) -{ - for (CEdgeLinks::iterator j = m_neighbors.begin(); - j != m_neighbors.end(); ++j) { - if (j->first.getSide() == side && j->first.isInside(position)) { - m_neighbors.erase(j); - break; - } - } -} -void -CConfig::CCell::remove(const CName& name) -{ - for (CEdgeLinks::iterator j = m_neighbors.begin(); - j != m_neighbors.end(); ) { - if (name == j->second.getName()) { - m_neighbors.erase(j++); - } - else { - ++j; - } - } -} - -void -CConfig::CCell::rename(const CName& oldName, const CString& newName) -{ - for (CEdgeLinks::iterator j = m_neighbors.begin(); - j != m_neighbors.end(); ++j) { - if (oldName == j->second.getName()) { - j->second.setName(newName); - } - } -} - -bool -CConfig::CCell::hasEdge(const CCellEdge& edge) const -{ - CEdgeLinks::const_iterator i = m_neighbors.find(edge); - return (i != m_neighbors.end() && i->first == edge); -} - -bool -CConfig::CCell::overlaps(const CCellEdge& edge) const -{ - CEdgeLinks::const_iterator i = m_neighbors.upper_bound(edge); - if (i != m_neighbors.end() && i->first.overlaps(edge)) { - return true; - } - if (i != m_neighbors.begin() && (--i)->first.overlaps(edge)) { - return true; - } - return false; -} - -bool -CConfig::CCell::getLink(EDirection side, float position, - const CCellEdge*& src, const CCellEdge*& dst) const -{ - CCellEdge edge(side, position); - CEdgeLinks::const_iterator i = m_neighbors.upper_bound(edge); - if (i == m_neighbors.begin()) { - return false; - } - --i; - if (i->first.getSide() == side && i->first.isInside(position)) { - src = &i->first; - dst = &i->second; - return true; - } - return false; -} - -bool -CConfig::CCell::operator==(const CCell& x) const -{ - // compare options - if (m_options != x.m_options) { - return false; - } - - // compare links - if (m_neighbors.size() != x.m_neighbors.size()) { - return false; - } - for (CEdgeLinks::const_iterator index1 = m_neighbors.begin(), - index2 = x.m_neighbors.begin(); - index1 != m_neighbors.end(); - ++index1, ++index2) { - if (index1->first != index2->first) { - return false; - } - if (index1->second != index2->second) { - return false; - } - - // operator== doesn't compare names. only compare destination - // names. - if (!CStringUtil::CaselessCmp::equal(index1->second.getName(), - index2->second.getName())) { - return false; - } - } - return true; -} - -bool -CConfig::CCell::operator!=(const CCell& x) const -{ - return !operator==(x); -} - -CConfig::CCell::const_iterator -CConfig::CCell::begin() const -{ - return m_neighbors.begin(); -} - -CConfig::CCell::const_iterator -CConfig::CCell::end() const -{ - return m_neighbors.end(); -} - - -// -// CConfig I/O -// - -std::istream& -operator>>(std::istream& s, CConfig& config) -{ - CConfigReadContext context(s); - config.read(context); - return s; -} - -std::ostream& -operator<<(std::ostream& s, const CConfig& config) -{ - // screens section - s << "section: screens" << std::endl; - for (CConfig::const_iterator screen = config.begin(); - screen != config.end(); ++screen) { - s << "\t" << screen->c_str() << ":" << std::endl; - const CConfig::CScreenOptions* options = config.getOptions(*screen); - if (options != NULL && options->size() > 0) { - for (CConfig::CScreenOptions::const_iterator - option = options->begin(); - option != options->end(); ++option) { - const char* name = CConfig::getOptionName(option->first); - CString value = CConfig::getOptionValue(option->first, - option->second); - if (name != NULL && !value.empty()) { - s << "\t\t" << name << " = " << value << std::endl; - } - } - } - } - s << "end" << std::endl; - - // links section - CString neighbor; - s << "section: links" << std::endl; - for (CConfig::const_iterator screen = config.begin(); - screen != config.end(); ++screen) { - s << "\t" << screen->c_str() << ":" << std::endl; - - for (CConfig::link_const_iterator - link = config.beginNeighbor(*screen), - nend = config.endNeighbor(*screen); link != nend; ++link) { - s << "\t\t" << CConfig::dirName(link->first.getSide()) << - CConfig::formatInterval(link->first.getInterval()) << - " = " << link->second.getName().c_str() << - CConfig::formatInterval(link->second.getInterval()) << - std::endl; - } - } - s << "end" << std::endl; - - // aliases section (if there are any) - if (config.m_map.size() != config.m_nameToCanonicalName.size()) { - // map canonical to alias - typedef std::multimap CMNameMap; - CMNameMap aliases; - for (CConfig::CNameMap::const_iterator - index = config.m_nameToCanonicalName.begin(); - index != config.m_nameToCanonicalName.end(); - ++index) { - if (index->first != index->second) { - aliases.insert(std::make_pair(index->second, index->first)); - } - } - - // dump it - CString screen; - s << "section: aliases" << std::endl; - for (CMNameMap::const_iterator index = aliases.begin(); - index != aliases.end(); ++index) { - if (index->first != screen) { - screen = index->first; - s << "\t" << screen.c_str() << ":" << std::endl; - } - s << "\t\t" << index->second.c_str() << std::endl; - } - s << "end" << std::endl; - } - - // options section - s << "section: options" << std::endl; - const CConfig::CScreenOptions* options = config.getOptions(""); - if (options != NULL && options->size() > 0) { - for (CConfig::CScreenOptions::const_iterator - option = options->begin(); - option != options->end(); ++option) { - const char* name = CConfig::getOptionName(option->first); - CString value = CConfig::getOptionValue(option->first, - option->second); - if (name != NULL && !value.empty()) { - s << "\t" << name << " = " << value << std::endl; - } - } - } - if (config.m_synergyAddress.isValid()) { - s << "\taddress = " << - config.m_synergyAddress.getHostname().c_str() << std::endl; - } - s << config.m_inputFilter.format("\t"); - s << "end" << std::endl; - - return s; -} - - -// -// CConfigReadContext -// - -CConfigReadContext::CConfigReadContext(std::istream& s, SInt32 firstLine) : - m_stream(s), - m_line(firstLine - 1) -{ - // do nothing -} - -CConfigReadContext::~CConfigReadContext() -{ - // do nothing -} - -bool -CConfigReadContext::readLine(CString& line) -{ - ++m_line; - while (std::getline(m_stream, line)) { - // strip leading whitespace - CString::size_type i = line.find_first_not_of(" \t"); - if (i != CString::npos) { - line.erase(0, i); - } - - // strip comments and then trailing whitespace - i = line.find('#'); - if (i != CString::npos) { - line.erase(i); - } - i = line.find_last_not_of(" \r\t"); - if (i != CString::npos) { - line.erase(i + 1); - } - - // return non empty line - if (!line.empty()) { - // make sure there are no invalid characters - for (i = 0; i < line.length(); ++i) { - if (!isgraph(line[i]) && line[i] != ' ' && line[i] != '\t') { - throw XConfigRead(*this, - "invalid character %{1}", - CStringUtil::print("%#2x", line[i])); - } - } - - return true; - } - - // next line - ++m_line; - } - return false; -} - -UInt32 -CConfigReadContext::getLineNumber() const -{ - return m_line; -} - -CConfigReadContext::operator void*() const -{ - return m_stream; -} - -bool -CConfigReadContext::operator!() const -{ - return !m_stream; -} - -OptionValue -CConfigReadContext::parseBoolean(const CString& arg) const -{ - if (CStringUtil::CaselessCmp::equal(arg, "true")) { - return static_cast(true); - } - if (CStringUtil::CaselessCmp::equal(arg, "false")) { - return static_cast(false); - } - throw XConfigRead(*this, "invalid boolean argument \"%{1}\"", arg); -} - -OptionValue -CConfigReadContext::parseInt(const CString& arg) const -{ - const char* s = arg.c_str(); - char* end; - long tmp = strtol(s, &end, 10); - if (*end != '\0') { - // invalid characters - throw XConfigRead(*this, "invalid integer argument \"%{1}\"", arg); - } - OptionValue value = static_cast(tmp); - if (value != tmp) { - // out of range - throw XConfigRead(*this, "integer argument \"%{1}\" out of range", arg); - } - return value; -} - -OptionValue -CConfigReadContext::parseModifierKey(const CString& arg) const -{ - if (CStringUtil::CaselessCmp::equal(arg, "shift")) { - return static_cast(kKeyModifierIDShift); - } - if (CStringUtil::CaselessCmp::equal(arg, "ctrl")) { - return static_cast(kKeyModifierIDControl); - } - if (CStringUtil::CaselessCmp::equal(arg, "alt")) { - return static_cast(kKeyModifierIDAlt); - } - if (CStringUtil::CaselessCmp::equal(arg, "meta")) { - return static_cast(kKeyModifierIDMeta); - } - if (CStringUtil::CaselessCmp::equal(arg, "super")) { - return static_cast(kKeyModifierIDSuper); - } - if (CStringUtil::CaselessCmp::equal(arg, "none")) { - return static_cast(kKeyModifierIDNull); - } - throw XConfigRead(*this, "invalid argument \"%{1}\"", arg); -} - -OptionValue -CConfigReadContext::parseCorner(const CString& arg) const -{ - if (CStringUtil::CaselessCmp::equal(arg, "left")) { - return kTopLeftMask | kBottomLeftMask; - } - else if (CStringUtil::CaselessCmp::equal(arg, "right")) { - return kTopRightMask | kBottomRightMask; - } - else if (CStringUtil::CaselessCmp::equal(arg, "top")) { - return kTopLeftMask | kTopRightMask; - } - else if (CStringUtil::CaselessCmp::equal(arg, "bottom")) { - return kBottomLeftMask | kBottomRightMask; - } - else if (CStringUtil::CaselessCmp::equal(arg, "top-left")) { - return kTopLeftMask; - } - else if (CStringUtil::CaselessCmp::equal(arg, "top-right")) { - return kTopRightMask; - } - else if (CStringUtil::CaselessCmp::equal(arg, "bottom-left")) { - return kBottomLeftMask; - } - else if (CStringUtil::CaselessCmp::equal(arg, "bottom-right")) { - return kBottomRightMask; - } - else if (CStringUtil::CaselessCmp::equal(arg, "none")) { - return kNoCornerMask; - } - else if (CStringUtil::CaselessCmp::equal(arg, "all")) { - return kAllCornersMask; - } - throw XConfigRead(*this, "invalid argument \"%{1}\"", arg); -} - -OptionValue -CConfigReadContext::parseCorners(const CString& args) const -{ - // find first token - CString::size_type i = args.find_first_not_of(" \t", 0); - if (i == CString::npos) { - throw XConfigRead(*this, "missing corner argument"); - } - CString::size_type j = args.find_first_of(" \t", i); - - // parse first corner token - OptionValue corners = parseCorner(args.substr(i, j - i)); - - // get +/- - i = args.find_first_not_of(" \t", j); - while (i != CString::npos) { - // parse +/- - bool add; - if (args[i] == '-') { - add = false; - } - else if (args[i] == '+') { - add = true; - } - else { - throw XConfigRead(*this, - "invalid corner operator \"%{1}\"", - CString(args.c_str() + i, 1)); - } - - // get next corner token - i = args.find_first_not_of(" \t", i + 1); - j = args.find_first_of(" \t", i); - if (i == CString::npos) { - throw XConfigRead(*this, "missing corner argument"); - } - - // parse next corner token - if (add) { - corners |= parseCorner(args.substr(i, j - i)); - } - else { - corners &= ~parseCorner(args.substr(i, j - i)); - } - i = args.find_first_not_of(" \t", j); - } - - return corners; -} - -CConfig::CInterval -CConfigReadContext::parseInterval(const ArgList& args) const -{ - if (args.size() == 0) { - return CConfig::CInterval(0.0f, 1.0f); - } - if (args.size() != 2 || args[0].empty() || args[1].empty()) { - throw XConfigRead(*this, "invalid interval \"%{1}\"", concatArgs(args)); - } - - char* end; - long startValue = strtol(args[0].c_str(), &end, 10); - if (end[0] != '\0') { - throw XConfigRead(*this, "invalid interval \"%{1}\"", concatArgs(args)); - } - long endValue = strtol(args[1].c_str(), &end, 10); - if (end[0] != '\0') { - throw XConfigRead(*this, "invalid interval \"%{1}\"", concatArgs(args)); - } - - if (startValue < 0 || startValue > 100 || - endValue < 0 || endValue > 100 || - startValue >= endValue) { - throw XConfigRead(*this, "invalid interval \"%{1}\"", concatArgs(args)); - } - - return CConfig::CInterval(startValue / 100.0f, endValue / 100.0f); -} - -void -CConfigReadContext::parseNameWithArgs( - const CString& type, const CString& line, - const CString& delim, CString::size_type& index, - CString& name, ArgList& args) const -{ - // skip leading whitespace - CString::size_type i = line.find_first_not_of(" \t", index); - if (i == CString::npos) { - throw XConfigRead(*this, CString("missing ") + type); - } - - // find end of name - CString::size_type j = line.find_first_of(" \t(" + delim, i); - if (j == CString::npos) { - j = line.length(); - } - - // save name - name = line.substr(i, j - i); - args.clear(); - - // is it okay to not find a delimiter? - bool needDelim = (!delim.empty() && delim.find('\n') == CString::npos); - - // skip whitespace - i = line.find_first_not_of(" \t", j); - if (i == CString::npos && needDelim) { - // expected delimiter but didn't find it - throw XConfigRead(*this, CString("missing ") + delim[0]); - } - if (i == CString::npos) { - // no arguments - index = line.length(); - return; - } - if (line[i] != '(') { - // no arguments - index = i; - return; - } - - // eat '(' - ++i; - - // parse arguments - j = line.find_first_of(",)", i); - while (j != CString::npos) { - // extract arg - CString arg(line.substr(i, j - i)); - i = j; - - // trim whitespace - j = arg.find_first_not_of(" \t"); - if (j != CString::npos) { - arg.erase(0, j); - } - j = arg.find_last_not_of(" \t"); - if (j != CString::npos) { - arg.erase(j + 1); - } - - // save arg - args.push_back(arg); - - // exit loop at end of arguments - if (line[i] == ')') { - break; - } - - // eat ',' - ++i; - - // next - j = line.find_first_of(",)", i); - } - - // verify ')' - if (j == CString::npos) { - // expected ) - throw XConfigRead(*this, "missing )"); - } - - // eat ')' - ++i; - - // skip whitespace - j = line.find_first_not_of(" \t", i); - if (j == CString::npos && needDelim) { - // expected delimiter but didn't find it - throw XConfigRead(*this, CString("missing ") + delim[0]); - } - - // verify delimiter - if (needDelim && delim.find(line[j]) == CString::npos) { - throw XConfigRead(*this, CString("expected ") + delim[0]); - } - - if (j == CString::npos) { - j = line.length(); - } - - index = j; - return; -} - -IPlatformScreen::CKeyInfo* -CConfigReadContext::parseKeystroke(const CString& keystroke) const -{ - return parseKeystroke(keystroke, std::set()); -} - -IPlatformScreen::CKeyInfo* -CConfigReadContext::parseKeystroke(const CString& keystroke, - const std::set& screens) const -{ - CString s = keystroke; - - KeyModifierMask mask; - if (!CKeyMap::parseModifiers(s, mask)) { - throw XConfigRead(*this, "unable to parse key modifiers"); - } - - KeyID key; - if (!CKeyMap::parseKey(s, key)) { - throw XConfigRead(*this, "unable to parse key"); - } - - if (key == kKeyNone && mask == 0) { - throw XConfigRead(*this, "missing key and/or modifiers in keystroke"); - } - - return IPlatformScreen::CKeyInfo::alloc(key, mask, 0, 0, screens); -} - -IPlatformScreen::CButtonInfo* -CConfigReadContext::parseMouse(const CString& mouse) const -{ - CString s = mouse; - - KeyModifierMask mask; - if (!CKeyMap::parseModifiers(s, mask)) { - throw XConfigRead(*this, "unable to parse button modifiers"); - } - - char* end; - ButtonID button = (ButtonID)strtol(s.c_str(), &end, 10); - if (*end != '\0') { - throw XConfigRead(*this, "unable to parse button"); - } - if (s.empty() || button <= 0) { - throw XConfigRead(*this, "invalid button"); - } - - return IPlatformScreen::CButtonInfo::alloc(button, mask); -} - -KeyModifierMask -CConfigReadContext::parseModifier(const CString& modifiers) const -{ - CString s = modifiers; - - KeyModifierMask mask; - if (!CKeyMap::parseModifiers(s, mask)) { - throw XConfigRead(*this, "unable to parse modifiers"); - } - - if (mask == 0) { - throw XConfigRead(*this, "no modifiers specified"); - } - - return mask; -} - -CString -CConfigReadContext::concatArgs(const ArgList& args) -{ - CString s("("); - for (size_t i = 0; i < args.size(); ++i) { - if (i != 0) { - s += ","; - } - s += args[i]; - } - s += ")"; - return s; -} - - -// -// CConfig I/O exceptions -// - -XConfigRead::XConfigRead(const CConfigReadContext& context, - const CString& error) : - m_error(CStringUtil::print("line %d: %s", - context.getLineNumber(), error.c_str())) -{ - // do nothing -} - -XConfigRead::XConfigRead(const CConfigReadContext& context, - const char* errorFmt, const CString& arg) : - m_error(CStringUtil::print("line %d: ", context.getLineNumber()) + - CStringUtil::format(errorFmt, arg.c_str())) -{ - // do nothing -} - -XConfigRead::~XConfigRead() -{ - // do nothing -} - -CString -XConfigRead::getWhat() const throw() -{ - return format("XConfigRead", "read error: %{1}", m_error.c_str()); -} diff --git a/lib/server/CConfig.h b/lib/server/CConfig.h deleted file mode 100644 index c0d2faa8..00000000 --- a/lib/server/CConfig.h +++ /dev/null @@ -1,536 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CCONFIG_H -#define CCONFIG_H - -#include "OptionTypes.h" -#include "ProtocolTypes.h" -#include "CNetworkAddress.h" -#include "CStringUtil.h" -#include "CInputFilter.h" -#include "XBase.h" -#include "stdmap.h" -#include "stdset.h" -#include "IPlatformScreen.h" -#include - -class CConfig; -class CConfigReadContext; - -namespace std { -template <> -struct iterator_traits { - typedef CString value_type; - typedef ptrdiff_t difference_type; - typedef bidirectional_iterator_tag iterator_category; - typedef CString* pointer; - typedef CString& reference; -}; -}; - -//! Server configuration -/*! -This class holds server configuration information. That includes -the names of screens and their aliases, the links between them, -and network addresses. - -Note that case is preserved in screen names but is ignored when -comparing names. Screen names and their aliases share a -namespace and must be unique. -*/ -class CConfig { -public: - typedef std::map CScreenOptions; - typedef std::pair CInterval; - - class CCellEdge { - public: - CCellEdge(EDirection side, float position); - CCellEdge(EDirection side, const CInterval&); - CCellEdge(const CString& name, EDirection side, const CInterval&); - ~CCellEdge(); - - CInterval getInterval() const; - void setName(const CString& newName); - CString getName() const; - EDirection getSide() const; - bool overlaps(const CCellEdge&) const; - bool isInside(float x) const; - - // transform position to [0,1] - float transform(float x) const; - - // transform [0,1] to position - float inverseTransform(float x) const; - - // compares side and start of interval - bool operator<(const CCellEdge&) const; - - // compares side and interval - bool operator==(const CCellEdge&) const; - bool operator!=(const CCellEdge&) const; - - private: - void init(const CString& name, EDirection side, - const CInterval&); - - private: - CString m_name; - EDirection m_side; - CInterval m_interval; - }; - -private: - class CName { - public: - CName(CConfig*, const CString& name); - - bool operator==(const CString& name) const; - - private: - CConfig* m_config; - CString m_name; - }; - - class CCell { - private: - typedef std::map CEdgeLinks; - - public: - typedef CEdgeLinks::const_iterator const_iterator; - - bool add(const CCellEdge& src, const CCellEdge& dst); - void remove(EDirection side); - void remove(EDirection side, float position); - void remove(const CName& destinationName); - void rename(const CName& oldName, const CString& newName); - - bool hasEdge(const CCellEdge&) const; - bool overlaps(const CCellEdge&) const; - - bool getLink(EDirection side, float position, - const CCellEdge*& src, const CCellEdge*& dst) const; - - bool operator==(const CCell&) const; - bool operator!=(const CCell&) const; - - const_iterator begin() const; - const_iterator end() const; - - private: - CEdgeLinks m_neighbors; - - public: - CScreenOptions m_options; - }; - typedef std::map CCellMap; - typedef std::map CNameMap; - -public: - typedef CCell::const_iterator link_const_iterator; - typedef CCellMap::const_iterator internal_const_iterator; - typedef CNameMap::const_iterator all_const_iterator; - class const_iterator : std::iterator_traits { - public: - explicit const_iterator() : m_i() { } - explicit const_iterator(const internal_const_iterator& i) : m_i(i) { } - - const_iterator& operator=(const const_iterator& i) { - m_i = i.m_i; - return *this; - } - CString operator*() { return m_i->first; } - const CString* operator->() { return &(m_i->first); } - const_iterator& operator++() { ++m_i; return *this; } - const_iterator operator++(int) { return const_iterator(m_i++); } - const_iterator& operator--() { --m_i; return *this; } - const_iterator operator--(int) { return const_iterator(m_i--); } - bool operator==(const const_iterator& i) const { - return (m_i == i.m_i); - } - bool operator!=(const const_iterator& i) const { - return (m_i != i.m_i); - } - - private: - internal_const_iterator m_i; - }; - - CConfig(); - virtual ~CConfig(); - - //! @name manipulators - //@{ - - //! Add screen - /*! - Adds a screen, returning true iff successful. If a screen or - alias with the given name exists then it fails. - */ - bool addScreen(const CString& name); - - //! Rename screen - /*! - Renames a screen. All references to the name are updated. - Returns true iff successful. - */ - bool renameScreen(const CString& oldName, - const CString& newName); - - //! Remove screen - /*! - Removes a screen. This also removes aliases for the screen and - disconnects any connections to the screen. \c name may be an - alias. - */ - void removeScreen(const CString& name); - - //! Remove all screens - /*! - Removes all screens, aliases, and connections. - */ - void removeAllScreens(); - - //! Add alias - /*! - Adds an alias for a screen name. An alias can be used - any place the canonical screen name can (except addScreen()). - Returns false if the alias name already exists or the canonical - name is unknown, otherwise returns true. - */ - bool addAlias(const CString& canonical, - const CString& alias); - - //! Remove alias - /*! - Removes an alias for a screen name. It returns false if the - alias is unknown or a canonical name, otherwise returns true. - */ - bool removeAlias(const CString& alias); - - //! Remove aliases - /*! - Removes all aliases for a canonical screen name. It returns false - if the canonical name is unknown, otherwise returns true. - */ - bool removeAliases(const CString& canonical); - - //! Remove all aliases - /*! - This removes all aliases but not the screens. - */ - void removeAllAliases(); - - //! Connect screens - /*! - Establishes a one-way connection between portions of opposite edges - of two screens. Each portion is described by an interval defined - by two numbers, the start and end of the interval half-open on the - end. The numbers range from 0 to 1, inclusive, for the left/top - to the right/bottom. The user will be able to jump from the - \c srcStart to \c srcSend interval of \c srcSide of screen - \c srcName to the opposite side of screen \c dstName in the interval - \c dstStart and \c dstEnd when both screens are connected to the - server and the user isn't locked to a screen. Returns false if - \c srcName is unknown. \c srcStart must be less than or equal to - \c srcEnd and \c dstStart must be less then or equal to \c dstEnd - and all of \c srcStart, \c srcEnd, \c dstStart, or \c dstEnd must - be inside the range [0,1]. - */ - bool connect(const CString& srcName, - EDirection srcSide, - float srcStart, float srcEnd, - const CString& dstName, - float dstStart, float dstEnd); - - //! Disconnect screens - /*! - Removes all connections created by connect() on side \c srcSide. - Returns false if \c srcName is unknown. - */ - bool disconnect(const CString& srcName, - EDirection srcSide); - - //! Disconnect screens - /*! - Removes the connections created by connect() on side \c srcSide - covering position \c position. Returns false if \c srcName is - unknown. - */ - bool disconnect(const CString& srcName, - EDirection srcSide, float position); - - //! Set server address - /*! - Set the synergy listen addresses. There is no default address so - this must be called to run a server using this configuration. - */ - void setSynergyAddress(const CNetworkAddress&); - - //! Add a screen option - /*! - Adds an option and its value to the named screen. Replaces the - existing option's value if there is one. Returns true iff \c name - is a known screen. - */ - bool addOption(const CString& name, - OptionID option, OptionValue value); - - //! Remove a screen option - /*! - Removes an option and its value from the named screen. Does - nothing if the option doesn't exist on the screen. Returns true - iff \c name is a known screen. - */ - bool removeOption(const CString& name, OptionID option); - - //! Remove a screen options - /*! - Removes all options and values from the named screen. Returns true - iff \c name is a known screen. - */ - bool removeOptions(const CString& name); - - //! Get the hot key input filter - /*! - Returns the hot key input filter. Clients can modify hotkeys using - that object. - */ - CInputFilter* getInputFilter(); - - //@} - //! @name accessors - //@{ - - //! Test screen name validity - /*! - Returns true iff \c name is a valid screen name. - */ - bool isValidScreenName(const CString& name) const; - - //! Get beginning (canonical) screen name iterator - const_iterator begin() const; - //! Get ending (canonical) screen name iterator - const_iterator end() const; - - //! Get beginning screen name iterator - all_const_iterator beginAll() const; - //! Get ending screen name iterator - all_const_iterator endAll() const; - - //! Test for screen name - /*! - Returns true iff \c name names a screen. - */ - bool isScreen(const CString& name) const; - - //! Test for canonical screen name - /*! - Returns true iff \c name is the canonical name of a screen. - */ - bool isCanonicalName(const CString& name) const; - - //! Get canonical name - /*! - Returns the canonical name of a screen or the empty string if - the name is unknown. Returns the canonical name if one is given. - */ - CString getCanonicalName(const CString& name) const; - - //! Get neighbor - /*! - Returns the canonical screen name of the neighbor in the given - direction (set through connect()) at position \c position. Returns - the empty string if there is no neighbor in that direction, otherwise - saves the position on the neighbor in \c positionOut if it's not - \c NULL. - */ - CString getNeighbor(const CString&, EDirection, - float position, float* positionOut) const; - - //! Check for neighbor - /*! - Returns \c true if the screen has a neighbor anywhere along the edge - given by the direction. - */ - bool hasNeighbor(const CString&, EDirection) const; - - //! Check for neighbor - /*! - Returns \c true if the screen has a neighbor in the given range along - the edge given by the direction. - */ - bool hasNeighbor(const CString&, EDirection, - float start, float end) const; - - //! Get beginning neighbor iterator - link_const_iterator beginNeighbor(const CString&) const; - //! Get ending neighbor iterator - link_const_iterator endNeighbor(const CString&) const; - - //! Get the server address - const CNetworkAddress& getSynergyAddress() const; - - //! Get the screen options - /*! - Returns all the added options for the named screen. Returns NULL - if the screen is unknown and an empty collection if there are no - options. - */ - const CScreenOptions* getOptions(const CString& name) const; - - //! Check for lock to screen action - /*! - Returns \c true if this configuration has a lock to screen action. - This is for backwards compatible support of ScrollLock locking. - */ - bool hasLockToScreenAction() const; - - //! Compare configurations - bool operator==(const CConfig&) const; - //! Compare configurations - bool operator!=(const CConfig&) const; - - //! Read configuration - /*! - Reads a configuration from a context. Throws XConfigRead on error - and context is unchanged. - */ - void read(CConfigReadContext& context); - - //! Read configuration - /*! - Reads a configuration from a stream. Throws XConfigRead on error. - */ - friend std::istream& operator>>(std::istream&, CConfig&); - - //! Write configuration - /*! - Writes a configuration to a stream. - */ - friend std::ostream& operator<<(std::ostream&, const CConfig&); - - //! Get direction name - /*! - Returns the name of a direction (for debugging). - */ - static const char* dirName(EDirection); - - //! Get interval as string - /*! - Returns an interval as a parseable string. - */ - static CString formatInterval(const CInterval&); - - //@} - -private: - void readSection(CConfigReadContext&); - void readSectionOptions(CConfigReadContext&); - void readSectionScreens(CConfigReadContext&); - void readSectionLinks(CConfigReadContext&); - void readSectionAliases(CConfigReadContext&); - - CInputFilter::CCondition* - parseCondition(CConfigReadContext&, - const CString& condition, - const std::vector& args); - void parseAction(CConfigReadContext&, - const CString& action, - const std::vector& args, - CInputFilter::CRule&, bool activate); - - void parseScreens(CConfigReadContext&, const CString&, - std::set& screens) const; - static const char* getOptionName(OptionID); - static CString getOptionValue(OptionID, OptionValue); - -private: - CCellMap m_map; - CNameMap m_nameToCanonicalName; - CNetworkAddress m_synergyAddress; - CScreenOptions m_globalOptions; - CInputFilter m_inputFilter; - bool m_hasLockToScreenAction; -}; - -//! Configuration read context -/*! -Maintains a context when reading a configuration from a stream. -*/ -class CConfigReadContext { -public: - typedef std::vector ArgList; - - CConfigReadContext(std::istream&, SInt32 firstLine = 1); - ~CConfigReadContext(); - - bool readLine(CString&); - UInt32 getLineNumber() const; - - operator void*() const; - bool operator!() const; - - OptionValue parseBoolean(const CString&) const; - OptionValue parseInt(const CString&) const; - OptionValue parseModifierKey(const CString&) const; - OptionValue parseCorner(const CString&) const; - OptionValue parseCorners(const CString&) const; - CConfig::CInterval - parseInterval(const ArgList& args) const; - void parseNameWithArgs( - const CString& type, const CString& line, - const CString& delim, CString::size_type& index, - CString& name, ArgList& args) const; - IPlatformScreen::CKeyInfo* - parseKeystroke(const CString& keystroke) const; - IPlatformScreen::CKeyInfo* - parseKeystroke(const CString& keystroke, - const std::set& screens) const; - IPlatformScreen::CButtonInfo* - parseMouse(const CString& mouse) const; - KeyModifierMask parseModifier(const CString& modifiers) const; - -private: - // not implemented - CConfigReadContext& operator=(const CConfigReadContext&); - - static CString concatArgs(const ArgList& args); - -private: - std::istream& m_stream; - SInt32 m_line; -}; - -//! Configuration stream read exception -/*! -Thrown when a configuration stream cannot be parsed. -*/ -class XConfigRead : public XBase { -public: - XConfigRead(const CConfigReadContext& context, const CString&); - XConfigRead(const CConfigReadContext& context, - const char* errorFmt, const CString& arg); - ~XConfigRead(); - -protected: - // XBase overrides - virtual CString getWhat() const throw(); - -private: - CString m_error; -}; - -#endif diff --git a/lib/server/CInputFilter.cpp b/lib/server/CInputFilter.cpp deleted file mode 100644 index d5d7fc20..00000000 --- a/lib/server/CInputFilter.cpp +++ /dev/null @@ -1,1066 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2005 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CInputFilter.h" -#include "CServer.h" -#include "CPrimaryClient.h" -#include "CKeyMap.h" -#include "CEventQueue.h" -#include "CLog.h" -#include "TMethodEventJob.h" -#include -#include - -// ----------------------------------------------------------------------------- -// Input Filter Condition Classes -// ----------------------------------------------------------------------------- -CInputFilter::CCondition::CCondition() -{ - // do nothing -} - -CInputFilter::CCondition::~CCondition() -{ - // do nothing -} - -void -CInputFilter::CCondition::enablePrimary(CPrimaryClient*) -{ - // do nothing -} - -void -CInputFilter::CCondition::disablePrimary(CPrimaryClient*) -{ - // do nothing -} - -CInputFilter::CKeystrokeCondition::CKeystrokeCondition( - IPlatformScreen::CKeyInfo* info) : - m_id(0), - m_key(info->m_key), - m_mask(info->m_mask) -{ - free(info); -} - -CInputFilter::CKeystrokeCondition::CKeystrokeCondition( - KeyID key, KeyModifierMask mask) : - m_id(0), - m_key(key), - m_mask(mask) -{ - // do nothing -} - -CInputFilter::CKeystrokeCondition::~CKeystrokeCondition() -{ - // do nothing -} - -KeyID -CInputFilter::CKeystrokeCondition::getKey() const -{ - return m_key; -} - -KeyModifierMask -CInputFilter::CKeystrokeCondition::getMask() const -{ - return m_mask; -} - -CInputFilter::CCondition* -CInputFilter::CKeystrokeCondition::clone() const -{ - return new CKeystrokeCondition(m_key, m_mask); -} - -CString -CInputFilter::CKeystrokeCondition::format() const -{ - return CStringUtil::print("keystroke(%s)", - CKeyMap::formatKey(m_key, m_mask).c_str()); -} - -CInputFilter::EFilterStatus -CInputFilter::CKeystrokeCondition::match(const CEvent& event) -{ - EFilterStatus status; - - // check for hotkey events - CEvent::Type type = event.getType(); - if (type == IPrimaryScreen::getHotKeyDownEvent()) { - status = kActivate; - } - else if (type == IPrimaryScreen::getHotKeyUpEvent()) { - status = kDeactivate; - } - else { - return kNoMatch; - } - - // check if it's our hotkey - IPrimaryScreen::CHotKeyInfo* kinfo = - reinterpret_cast(event.getData()); - if (kinfo->m_id != m_id) { - return kNoMatch; - } - - return status; -} - -void -CInputFilter::CKeystrokeCondition::enablePrimary(CPrimaryClient* primary) -{ - m_id = primary->registerHotKey(m_key, m_mask); -} - -void -CInputFilter::CKeystrokeCondition::disablePrimary(CPrimaryClient* primary) -{ - primary->unregisterHotKey(m_id); - m_id = 0; -} - -CInputFilter::CMouseButtonCondition::CMouseButtonCondition( - IPlatformScreen::CButtonInfo* info) : - m_button(info->m_button), - m_mask(info->m_mask) -{ - free(info); -} - -CInputFilter::CMouseButtonCondition::CMouseButtonCondition( - ButtonID button, KeyModifierMask mask) : - m_button(button), - m_mask(mask) -{ - // do nothing -} - -CInputFilter::CMouseButtonCondition::~CMouseButtonCondition() -{ - // do nothing -} - -ButtonID -CInputFilter::CMouseButtonCondition::getButton() const -{ - return m_button; -} - -KeyModifierMask -CInputFilter::CMouseButtonCondition::getMask() const -{ - return m_mask; -} - -CInputFilter::CCondition* -CInputFilter::CMouseButtonCondition::clone() const -{ - return new CMouseButtonCondition(m_button, m_mask); -} - -CString -CInputFilter::CMouseButtonCondition::format() const -{ - CString key = CKeyMap::formatKey(kKeyNone, m_mask); - if (!key.empty()) { - key += "+"; - } - return CStringUtil::print("mousebutton(%s%d)", key.c_str(), m_button); -} - -CInputFilter::EFilterStatus -CInputFilter::CMouseButtonCondition::match(const CEvent& event) -{ - static const KeyModifierMask s_ignoreMask = - KeyModifierAltGr | KeyModifierCapsLock | - KeyModifierNumLock | KeyModifierScrollLock; - - EFilterStatus status; - - // check for hotkey events - CEvent::Type type = event.getType(); - if (type == IPrimaryScreen::getButtonDownEvent()) { - status = kActivate; - } - else if (type == IPrimaryScreen::getButtonUpEvent()) { - status = kDeactivate; - } - else { - return kNoMatch; - } - - // check if it's the right button and modifiers. ignore modifiers - // that cannot be combined with a mouse button. - IPlatformScreen::CButtonInfo* minfo = - reinterpret_cast(event.getData()); - if (minfo->m_button != m_button || - (minfo->m_mask & ~s_ignoreMask) != m_mask) { - return kNoMatch; - } - - return status; -} - -CInputFilter::CScreenConnectedCondition::CScreenConnectedCondition( - const CString& screen) : - m_screen(screen) -{ - // do nothing -} - -CInputFilter::CScreenConnectedCondition::~CScreenConnectedCondition() -{ - // do nothing -} - -CInputFilter::CCondition* -CInputFilter::CScreenConnectedCondition::clone() const -{ - return new CScreenConnectedCondition(m_screen); -} - -CString -CInputFilter::CScreenConnectedCondition::format() const -{ - return CStringUtil::print("connect(%s)", m_screen.c_str()); -} - -CInputFilter::EFilterStatus -CInputFilter::CScreenConnectedCondition::match(const CEvent& event) -{ - if (event.getType() == CServer::getConnectedEvent()) { - CServer::CScreenConnectedInfo* info = - reinterpret_cast(event.getData()); - if (m_screen == info->m_screen || m_screen.empty()) { - return kActivate; - } - } - - return kNoMatch; -} - -// ----------------------------------------------------------------------------- -// Input Filter Action Classes -// ----------------------------------------------------------------------------- -CInputFilter::CAction::CAction() -{ - // do nothing -} - -CInputFilter::CAction::~CAction() -{ - // do nothing -} - -CInputFilter::CLockCursorToScreenAction::CLockCursorToScreenAction(Mode mode) : - m_mode(mode) -{ - // do nothing -} - -CInputFilter::CLockCursorToScreenAction::Mode -CInputFilter::CLockCursorToScreenAction::getMode() const -{ - return m_mode; -} - -CInputFilter::CAction* -CInputFilter::CLockCursorToScreenAction::clone() const -{ - return new CLockCursorToScreenAction(*this); -} - -CString -CInputFilter::CLockCursorToScreenAction::format() const -{ - static const char* s_mode[] = { "off", "on", "toggle" }; - - return CStringUtil::print("lockCursorToScreen(%s)", s_mode[m_mode]); -} - -void -CInputFilter::CLockCursorToScreenAction::perform(const CEvent& event) -{ - static const CServer::CLockCursorToScreenInfo::State s_state[] = { - CServer::CLockCursorToScreenInfo::kOff, - CServer::CLockCursorToScreenInfo::kOn, - CServer::CLockCursorToScreenInfo::kToggle - }; - - // send event - CServer::CLockCursorToScreenInfo* info = - CServer::CLockCursorToScreenInfo::alloc(s_state[m_mode]); - EVENTQUEUE->addEvent(CEvent(CServer::getLockCursorToScreenEvent(), - event.getTarget(), info, - CEvent::kDeliverImmediately)); -} - -CInputFilter::CSwitchToScreenAction::CSwitchToScreenAction( - const CString& screen) : - m_screen(screen) -{ - // do nothing -} - -CString -CInputFilter::CSwitchToScreenAction::getScreen() const -{ - return m_screen; -} - -CInputFilter::CAction* -CInputFilter::CSwitchToScreenAction::clone() const -{ - return new CSwitchToScreenAction(*this); -} - -CString -CInputFilter::CSwitchToScreenAction::format() const -{ - return CStringUtil::print("switchToScreen(%s)", m_screen.c_str()); -} - -void -CInputFilter::CSwitchToScreenAction::perform(const CEvent& event) -{ - // pick screen name. if m_screen is empty then use the screen from - // event if it has one. - CString screen = m_screen; - if (screen.empty() && event.getType() == CServer::getConnectedEvent()) { - CServer::CScreenConnectedInfo* info = - reinterpret_cast(event.getData()); - screen = info->m_screen; - } - - // send event - CServer::CSwitchToScreenInfo* info = - CServer::CSwitchToScreenInfo::alloc(screen); - EVENTQUEUE->addEvent(CEvent(CServer::getSwitchToScreenEvent(), - event.getTarget(), info, - CEvent::kDeliverImmediately)); -} - -CInputFilter::CSwitchInDirectionAction::CSwitchInDirectionAction( - EDirection direction) : - m_direction(direction) -{ - // do nothing -} - -EDirection -CInputFilter::CSwitchInDirectionAction::getDirection() const -{ - return m_direction; -} - -CInputFilter::CAction* -CInputFilter::CSwitchInDirectionAction::clone() const -{ - return new CSwitchInDirectionAction(*this); -} - -CString -CInputFilter::CSwitchInDirectionAction::format() const -{ - static const char* s_names[] = { - "", - "left", - "right", - "up", - "down" - }; - - return CStringUtil::print("switchInDirection(%s)", s_names[m_direction]); -} - -void -CInputFilter::CSwitchInDirectionAction::perform(const CEvent& event) -{ - CServer::CSwitchInDirectionInfo* info = - CServer::CSwitchInDirectionInfo::alloc(m_direction); - EVENTQUEUE->addEvent(CEvent(CServer::getSwitchInDirectionEvent(), - event.getTarget(), info, - CEvent::kDeliverImmediately)); -} - -CInputFilter::CKeyboardBroadcastAction::CKeyboardBroadcastAction(Mode mode) : - m_mode(mode) -{ - // do nothing -} - -CInputFilter::CKeyboardBroadcastAction::CKeyboardBroadcastAction( - Mode mode, - const std::set& screens) : - m_mode(mode), - m_screens(IKeyState::CKeyInfo::join(screens)) -{ - // do nothing -} - -CInputFilter::CKeyboardBroadcastAction::Mode -CInputFilter::CKeyboardBroadcastAction::getMode() const -{ - return m_mode; -} - -std::set -CInputFilter::CKeyboardBroadcastAction::getScreens() const -{ - std::set screens; - IKeyState::CKeyInfo::split(m_screens.c_str(), screens); - return screens; -} - -CInputFilter::CAction* -CInputFilter::CKeyboardBroadcastAction::clone() const -{ - return new CKeyboardBroadcastAction(*this); -} - -CString -CInputFilter::CKeyboardBroadcastAction::format() const -{ - static const char* s_mode[] = { "off", "on", "toggle" }; - static const char* s_name = "keyboardBroadcast"; - - if (m_screens.empty() || m_screens[0] == '*') { - return CStringUtil::print("%s(%s)", s_name, s_mode[m_mode]); - } - else { - return CStringUtil::print("%s(%s,%.*s)", s_name, s_mode[m_mode], - m_screens.size() - 2, - m_screens.c_str() + 1); - } -} - -void -CInputFilter::CKeyboardBroadcastAction::perform(const CEvent& event) -{ - static const CServer::CKeyboardBroadcastInfo::State s_state[] = { - CServer::CKeyboardBroadcastInfo::kOff, - CServer::CKeyboardBroadcastInfo::kOn, - CServer::CKeyboardBroadcastInfo::kToggle - }; - - // send event - CServer::CKeyboardBroadcastInfo* info = - CServer::CKeyboardBroadcastInfo::alloc(s_state[m_mode], m_screens); - EVENTQUEUE->addEvent(CEvent(CServer::getKeyboardBroadcastEvent(), - event.getTarget(), info, - CEvent::kDeliverImmediately)); -} - -CInputFilter::CKeystrokeAction::CKeystrokeAction( - IPlatformScreen::CKeyInfo* info, bool press) : - m_keyInfo(info), - m_press(press) -{ - // do nothing -} - -CInputFilter::CKeystrokeAction::~CKeystrokeAction() -{ - free(m_keyInfo); -} - -void -CInputFilter::CKeystrokeAction::adoptInfo(IPlatformScreen::CKeyInfo* info) -{ - free(m_keyInfo); - m_keyInfo = info; -} - -const IPlatformScreen::CKeyInfo* -CInputFilter::CKeystrokeAction::getInfo() const -{ - return m_keyInfo; -} - -bool -CInputFilter::CKeystrokeAction::isOnPress() const -{ - return m_press; -} - -CInputFilter::CAction* -CInputFilter::CKeystrokeAction::clone() const -{ - IKeyState::CKeyInfo* info = IKeyState::CKeyInfo::alloc(*m_keyInfo); - return new CKeystrokeAction(info, m_press); -} - -CString -CInputFilter::CKeystrokeAction::format() const -{ - const char* type = formatName(); - - if (m_keyInfo->m_screens[0] == '\0') { - return CStringUtil::print("%s(%s)", type, - CKeyMap::formatKey(m_keyInfo->m_key, - m_keyInfo->m_mask).c_str()); - } - else if (m_keyInfo->m_screens[0] == '*') { - return CStringUtil::print("%s(%s,*)", type, - CKeyMap::formatKey(m_keyInfo->m_key, - m_keyInfo->m_mask).c_str()); - } - else { - return CStringUtil::print("%s(%s,%.*s)", type, - CKeyMap::formatKey(m_keyInfo->m_key, - m_keyInfo->m_mask).c_str(), - strlen(m_keyInfo->m_screens + 1) - 1, - m_keyInfo->m_screens + 1); - } -} - -void -CInputFilter::CKeystrokeAction::perform(const CEvent& event) -{ - CEvent::Type type = m_press ? IPlatformScreen::getKeyDownEvent() : - IPlatformScreen::getKeyUpEvent(); - EVENTQUEUE->addEvent(CEvent(IPlatformScreen::getFakeInputBeginEvent(), - event.getTarget(), NULL, - CEvent::kDeliverImmediately)); - EVENTQUEUE->addEvent(CEvent(type, event.getTarget(), m_keyInfo, - CEvent::kDeliverImmediately | - CEvent::kDontFreeData)); - EVENTQUEUE->addEvent(CEvent(IPlatformScreen::getFakeInputEndEvent(), - event.getTarget(), NULL, - CEvent::kDeliverImmediately)); -} - -const char* -CInputFilter::CKeystrokeAction::formatName() const -{ - return (m_press ? "keyDown" : "keyUp"); -} - -CInputFilter::CMouseButtonAction::CMouseButtonAction( - IPlatformScreen::CButtonInfo* info, bool press) : - m_buttonInfo(info), - m_press(press) -{ - // do nothing -} - -CInputFilter::CMouseButtonAction::~CMouseButtonAction() -{ - free(m_buttonInfo); -} - -const IPlatformScreen::CButtonInfo* -CInputFilter::CMouseButtonAction::getInfo() const -{ - return m_buttonInfo; -} - -bool -CInputFilter::CMouseButtonAction::isOnPress() const -{ - return m_press; -} - -CInputFilter::CAction* -CInputFilter::CMouseButtonAction::clone() const -{ - IPlatformScreen::CButtonInfo* info = - IPrimaryScreen::CButtonInfo::alloc(*m_buttonInfo); - return new CMouseButtonAction(info, m_press); -} - -CString -CInputFilter::CMouseButtonAction::format() const -{ - const char* type = formatName(); - - CString key = CKeyMap::formatKey(kKeyNone, m_buttonInfo->m_mask); - return CStringUtil::print("%s(%s%s%d)", type, - key.c_str(), key.empty() ? "" : "+", - m_buttonInfo->m_button); -} - -void -CInputFilter::CMouseButtonAction::perform(const CEvent& event) - -{ - // send modifiers - IPlatformScreen::CKeyInfo* modifierInfo = NULL; - if (m_buttonInfo->m_mask != 0) { - KeyID key = m_press ? kKeySetModifiers : kKeyClearModifiers; - modifierInfo = - IKeyState::CKeyInfo::alloc(key, m_buttonInfo->m_mask, 0, 1); - EVENTQUEUE->addEvent(CEvent(IPlatformScreen::getKeyDownEvent(), - event.getTarget(), modifierInfo, - CEvent::kDeliverImmediately)); - } - - // send button - CEvent::Type type = m_press ? IPlatformScreen::getButtonDownEvent() : - IPlatformScreen::getButtonUpEvent(); - EVENTQUEUE->addEvent(CEvent(type, event.getTarget(), m_buttonInfo, - CEvent::kDeliverImmediately | - CEvent::kDontFreeData)); -} - -const char* -CInputFilter::CMouseButtonAction::formatName() const -{ - return (m_press ? "mouseDown" : "mouseUp"); -} - -// -// CInputFilter::CRule -// - -CInputFilter::CRule::CRule() : - m_condition(NULL) -{ - // do nothing -} - -CInputFilter::CRule::CRule(CCondition* adoptedCondition) : - m_condition(adoptedCondition) -{ - // do nothing -} - -CInputFilter::CRule::CRule(const CRule& rule) : - m_condition(NULL) -{ - copy(rule); -} - -CInputFilter::CRule::~CRule() -{ - clear(); -} - -CInputFilter::CRule& -CInputFilter::CRule::operator=(const CRule& rule) -{ - if (&rule != this) { - copy(rule); - } - return *this; -} - -void -CInputFilter::CRule::clear() -{ - delete m_condition; - for (CActionList::iterator i = m_activateActions.begin(); - i != m_activateActions.end(); ++i) { - delete *i; - } - for (CActionList::iterator i = m_deactivateActions.begin(); - i != m_deactivateActions.end(); ++i) { - delete *i; - } - - m_condition = NULL; - m_activateActions.clear(); - m_deactivateActions.clear(); -} - -void -CInputFilter::CRule::copy(const CRule& rule) -{ - clear(); - if (rule.m_condition != NULL) { - m_condition = rule.m_condition->clone(); - } - for (CActionList::const_iterator i = rule.m_activateActions.begin(); - i != rule.m_activateActions.end(); ++i) { - m_activateActions.push_back((*i)->clone()); - } - for (CActionList::const_iterator i = rule.m_deactivateActions.begin(); - i != rule.m_deactivateActions.end(); ++i) { - m_deactivateActions.push_back((*i)->clone()); - } -} - -void -CInputFilter::CRule::setCondition(CCondition* adopted) -{ - delete m_condition; - m_condition = adopted; -} - -void -CInputFilter::CRule::adoptAction(CAction* action, bool onActivation) -{ - if (action != NULL) { - if (onActivation) { - m_activateActions.push_back(action); - } - else { - m_deactivateActions.push_back(action); - } - } -} - -void -CInputFilter::CRule::removeAction(bool onActivation, UInt32 index) -{ - if (onActivation) { - delete m_activateActions[index]; - m_activateActions.erase(m_activateActions.begin() + index); - } - else { - delete m_deactivateActions[index]; - m_deactivateActions.erase(m_deactivateActions.begin() + index); - } -} - -void -CInputFilter::CRule::replaceAction(CAction* adopted, - bool onActivation, UInt32 index) -{ - if (adopted == NULL) { - removeAction(onActivation, index); - } - else if (onActivation) { - delete m_activateActions[index]; - m_activateActions[index] = adopted; - } - else { - delete m_deactivateActions[index]; - m_deactivateActions[index] = adopted; - } -} - -void -CInputFilter::CRule::enable(CPrimaryClient* primaryClient) -{ - if (m_condition != NULL) { - m_condition->enablePrimary(primaryClient); - } -} - -void -CInputFilter::CRule::disable(CPrimaryClient* primaryClient) -{ - if (m_condition != NULL) { - m_condition->disablePrimary(primaryClient); - } -} - -bool -CInputFilter::CRule::handleEvent(const CEvent& event) -{ - // NULL condition never matches - if (m_condition == NULL) { - return false; - } - - // match - const CActionList* actions; - switch (m_condition->match(event)) { - default: - // not handled - return false; - - case kActivate: - actions = &m_activateActions; - LOG((CLOG_DEBUG1 "activate actions")); - break; - - case kDeactivate: - actions = &m_deactivateActions; - LOG((CLOG_DEBUG1 "deactivate actions")); - break; - } - - // perform actions - for (CActionList::const_iterator i = actions->begin(); - i != actions->end(); ++i) { - LOG((CLOG_DEBUG1 "hotkey: %s", (*i)->format().c_str())); - (*i)->perform(event); - } - - return true; -} - -CString -CInputFilter::CRule::format() const -{ - CString s; - if (m_condition != NULL) { - // condition - s += m_condition->format(); - s += " = "; - - // activate actions - CActionList::const_iterator i = m_activateActions.begin(); - if (i != m_activateActions.end()) { - s += (*i)->format(); - while (++i != m_activateActions.end()) { - s += ", "; - s += (*i)->format(); - } - } - - // deactivate actions - if (!m_deactivateActions.empty()) { - s += "; "; - i = m_deactivateActions.begin(); - if (i != m_deactivateActions.end()) { - s += (*i)->format(); - while (++i != m_deactivateActions.end()) { - s += ", "; - s += (*i)->format(); - } - } - } - } - return s; -} - -const CInputFilter::CCondition* -CInputFilter::CRule::getCondition() const -{ - return m_condition; -} - -UInt32 -CInputFilter::CRule::getNumActions(bool onActivation) const -{ - if (onActivation) { - return static_cast(m_activateActions.size()); - } - else { - return static_cast(m_deactivateActions.size()); - } -} - -const CInputFilter::CAction& -CInputFilter::CRule::getAction(bool onActivation, UInt32 index) const -{ - if (onActivation) { - return *m_activateActions[index]; - } - else { - return *m_deactivateActions[index]; - } -} - - -// ----------------------------------------------------------------------------- -// Input Filter Class -// ----------------------------------------------------------------------------- -CInputFilter::CInputFilter() : - m_primaryClient(NULL) -{ - // do nothing -} - -CInputFilter::CInputFilter(const CInputFilter& x) : - m_ruleList(x.m_ruleList), - m_primaryClient(NULL) -{ - setPrimaryClient(x.m_primaryClient); -} - -CInputFilter::~CInputFilter() -{ - setPrimaryClient(NULL); -} - -CInputFilter& -CInputFilter::operator=(const CInputFilter& x) -{ - if (&x != this) { - CPrimaryClient* oldClient = m_primaryClient; - setPrimaryClient(NULL); - - m_ruleList = x.m_ruleList; - - setPrimaryClient(oldClient); - } - return *this; -} - -void -CInputFilter::addFilterRule(const CRule& rule) -{ - m_ruleList.push_back(rule); - if (m_primaryClient != NULL) { - m_ruleList.back().enable(m_primaryClient); - } -} - -void -CInputFilter::removeFilterRule(UInt32 index) -{ - if (m_primaryClient != NULL) { - m_ruleList[index].disable(m_primaryClient); - } - m_ruleList.erase(m_ruleList.begin() + index); -} - -CInputFilter::CRule& -CInputFilter::getRule(UInt32 index) -{ - return m_ruleList[index]; -} - -void -CInputFilter::setPrimaryClient(CPrimaryClient* client) -{ - if (m_primaryClient == client) { - return; - } - - if (m_primaryClient != NULL) { - for (CRuleList::iterator rule = m_ruleList.begin(); - rule != m_ruleList.end(); ++rule) { - rule->disable(m_primaryClient); - } - - EVENTQUEUE->removeHandler(IPlatformScreen::getKeyDownEvent(), - m_primaryClient->getEventTarget()); - EVENTQUEUE->removeHandler(IPlatformScreen::getKeyUpEvent(), - m_primaryClient->getEventTarget()); - EVENTQUEUE->removeHandler(IPlatformScreen::getKeyRepeatEvent(), - m_primaryClient->getEventTarget()); - EVENTQUEUE->removeHandler(IPlatformScreen::getButtonDownEvent(), - m_primaryClient->getEventTarget()); - EVENTQUEUE->removeHandler(IPlatformScreen::getButtonUpEvent(), - m_primaryClient->getEventTarget()); - EVENTQUEUE->removeHandler(IPlatformScreen::getHotKeyDownEvent(), - m_primaryClient->getEventTarget()); - EVENTQUEUE->removeHandler(IPlatformScreen::getHotKeyUpEvent(), - m_primaryClient->getEventTarget()); - EVENTQUEUE->removeHandler(CServer::getConnectedEvent(), - m_primaryClient->getEventTarget()); - } - - m_primaryClient = client; - - if (m_primaryClient != NULL) { - EVENTQUEUE->adoptHandler(IPlatformScreen::getKeyDownEvent(), - m_primaryClient->getEventTarget(), - new TMethodEventJob(this, - &CInputFilter::handleEvent)); - EVENTQUEUE->adoptHandler(IPlatformScreen::getKeyUpEvent(), - m_primaryClient->getEventTarget(), - new TMethodEventJob(this, - &CInputFilter::handleEvent)); - EVENTQUEUE->adoptHandler(IPlatformScreen::getKeyRepeatEvent(), - m_primaryClient->getEventTarget(), - new TMethodEventJob(this, - &CInputFilter::handleEvent)); - EVENTQUEUE->adoptHandler(IPlatformScreen::getButtonDownEvent(), - m_primaryClient->getEventTarget(), - new TMethodEventJob(this, - &CInputFilter::handleEvent)); - EVENTQUEUE->adoptHandler(IPlatformScreen::getButtonUpEvent(), - m_primaryClient->getEventTarget(), - new TMethodEventJob(this, - &CInputFilter::handleEvent)); - EVENTQUEUE->adoptHandler(IPlatformScreen::getHotKeyDownEvent(), - m_primaryClient->getEventTarget(), - new TMethodEventJob(this, - &CInputFilter::handleEvent)); - EVENTQUEUE->adoptHandler(IPlatformScreen::getHotKeyUpEvent(), - m_primaryClient->getEventTarget(), - new TMethodEventJob(this, - &CInputFilter::handleEvent)); - EVENTQUEUE->adoptHandler(CServer::getConnectedEvent(), - m_primaryClient->getEventTarget(), - new TMethodEventJob(this, - &CInputFilter::handleEvent)); - - for (CRuleList::iterator rule = m_ruleList.begin(); - rule != m_ruleList.end(); ++rule) { - rule->enable(m_primaryClient); - } - } -} - -CString -CInputFilter::format(const CString& linePrefix) const -{ - CString s; - for (CRuleList::const_iterator i = m_ruleList.begin(); - i != m_ruleList.end(); ++i) { - s += linePrefix; - s += i->format(); - s += "\n"; - } - return s; -} - -UInt32 -CInputFilter::getNumRules() const -{ - return static_cast(m_ruleList.size()); -} - -bool -CInputFilter::operator==(const CInputFilter& x) const -{ - // if there are different numbers of rules then we can't be equal - if (m_ruleList.size() != x.m_ruleList.size()) { - return false; - } - - // compare rule lists. the easiest way to do that is to format each - // rule into a string, sort the strings, then compare the results. - std::vector aList, bList; - for (CRuleList::const_iterator i = m_ruleList.begin(); - i != m_ruleList.end(); ++i) { - aList.push_back(i->format()); - } - for (CRuleList::const_iterator i = x.m_ruleList.begin(); - i != x.m_ruleList.end(); ++i) { - bList.push_back(i->format()); - } - std::partial_sort(aList.begin(), aList.end(), aList.end()); - std::partial_sort(bList.begin(), bList.end(), bList.end()); - return (aList == bList); -} - -bool -CInputFilter::operator!=(const CInputFilter& x) const -{ - return !operator==(x); -} - -void -CInputFilter::handleEvent(const CEvent& event, void*) -{ - // copy event and adjust target - CEvent myEvent(event.getType(), this, event.getData(), - event.getFlags() | CEvent::kDontFreeData | - CEvent::kDeliverImmediately); - - // let each rule try to match the event until one does - for (CRuleList::iterator rule = m_ruleList.begin(); - rule != m_ruleList.end(); ++rule) { - if (rule->handleEvent(myEvent)) { - // handled - return; - } - } - - // not handled so pass through - EVENTQUEUE->addEvent(myEvent); -} diff --git a/lib/server/CInputFilter.h b/lib/server/CInputFilter.h deleted file mode 100644 index 571ec82b..00000000 --- a/lib/server/CInputFilter.h +++ /dev/null @@ -1,344 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2005 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CINPUTFILTER_H -#define CINPUTFILTER_H - -#include "KeyTypes.h" -#include "MouseTypes.h" -#include "ProtocolTypes.h" -#include "IPlatformScreen.h" -#include "CString.h" -#include "stdmap.h" -#include "stdset.h" - -class CPrimaryClient; -class CEvent; - -class CInputFilter { -public: - // ------------------------------------------------------------------------- - // Input Filter Condition Classes - // ------------------------------------------------------------------------- - enum EFilterStatus { - kNoMatch, - kActivate, - kDeactivate - }; - - class CCondition { - public: - CCondition(); - virtual ~CCondition(); - - virtual CCondition* clone() const = 0; - virtual CString format() const = 0; - - virtual EFilterStatus match(const CEvent&) = 0; - - virtual void enablePrimary(CPrimaryClient*); - virtual void disablePrimary(CPrimaryClient*); - }; - - // CKeystrokeCondition - class CKeystrokeCondition : public CCondition { - public: - CKeystrokeCondition(IPlatformScreen::CKeyInfo*); - CKeystrokeCondition(KeyID key, KeyModifierMask mask); - virtual ~CKeystrokeCondition(); - - KeyID getKey() const; - KeyModifierMask getMask() const; - - // CCondition overrides - virtual CCondition* clone() const; - virtual CString format() const; - virtual EFilterStatus match(const CEvent&); - virtual void enablePrimary(CPrimaryClient*); - virtual void disablePrimary(CPrimaryClient*); - - private: - UInt32 m_id; - KeyID m_key; - KeyModifierMask m_mask; - }; - - // CMouseButtonCondition - class CMouseButtonCondition : public CCondition { - public: - CMouseButtonCondition(IPlatformScreen::CButtonInfo*); - CMouseButtonCondition(ButtonID, KeyModifierMask mask); - virtual ~CMouseButtonCondition(); - - ButtonID getButton() const; - KeyModifierMask getMask() const; - - // CCondition overrides - virtual CCondition* clone() const; - virtual CString format() const; - virtual EFilterStatus match(const CEvent&); - - private: - ButtonID m_button; - KeyModifierMask m_mask; - }; - - // CScreenConnectedCondition - class CScreenConnectedCondition : public CCondition { - public: - CScreenConnectedCondition(const CString& screen); - virtual ~CScreenConnectedCondition(); - - // CCondition overrides - virtual CCondition* clone() const; - virtual CString format() const; - virtual EFilterStatus match(const CEvent&); - - private: - CString m_screen; - }; - - // ------------------------------------------------------------------------- - // Input Filter Action Classes - // ------------------------------------------------------------------------- - - class CAction { - public: - CAction(); - virtual ~CAction(); - - virtual CAction* clone() const = 0; - virtual CString format() const = 0; - - virtual void perform(const CEvent&) = 0; - }; - - // CLockCursorToScreenAction - class CLockCursorToScreenAction : public CAction { - public: - enum Mode { kOff, kOn, kToggle }; - - CLockCursorToScreenAction(Mode = kToggle); - - Mode getMode() const; - - // CAction overrides - virtual CAction* clone() const; - virtual CString format() const; - virtual void perform(const CEvent&); - - private: - Mode m_mode; - }; - - // CSwitchToScreenAction - class CSwitchToScreenAction : public CAction { - public: - CSwitchToScreenAction(const CString& screen); - - CString getScreen() const; - - // CAction overrides - virtual CAction* clone() const; - virtual CString format() const; - virtual void perform(const CEvent&); - - private: - CString m_screen; - }; - - // CSwitchInDirectionAction - class CSwitchInDirectionAction : public CAction { - public: - CSwitchInDirectionAction(EDirection); - - EDirection getDirection() const; - - // CAction overrides - virtual CAction* clone() const; - virtual CString format() const; - virtual void perform(const CEvent&); - - private: - EDirection m_direction; - }; - - // CKeyboardBroadcastAction - class CKeyboardBroadcastAction : public CAction { - public: - enum Mode { kOff, kOn, kToggle }; - - CKeyboardBroadcastAction(Mode = kToggle); - CKeyboardBroadcastAction(Mode, const std::set& screens); - - Mode getMode() const; - std::set getScreens() const; - - // CAction overrides - virtual CAction* clone() const; - virtual CString format() const; - virtual void perform(const CEvent&); - - private: - Mode m_mode; - CString m_screens; - }; - - // CKeystrokeAction - class CKeystrokeAction : public CAction { - public: - CKeystrokeAction(IPlatformScreen::CKeyInfo* adoptedInfo, bool press); - ~CKeystrokeAction(); - - void adoptInfo(IPlatformScreen::CKeyInfo*); - const IPlatformScreen::CKeyInfo* - getInfo() const; - bool isOnPress() const; - - // CAction overrides - virtual CAction* clone() const; - virtual CString format() const; - virtual void perform(const CEvent&); - - protected: - virtual const char* formatName() const; - - private: - IPlatformScreen::CKeyInfo* m_keyInfo; - bool m_press; - }; - - // CMouseButtonAction -- modifier combinations not implemented yet - class CMouseButtonAction : public CAction { - public: - CMouseButtonAction(IPlatformScreen::CButtonInfo* adoptedInfo, - bool press); - ~CMouseButtonAction(); - - const IPlatformScreen::CButtonInfo* - getInfo() const; - bool isOnPress() const; - - // CAction overrides - virtual CAction* clone() const; - virtual CString format() const; - virtual void perform(const CEvent&); - - protected: - virtual const char* formatName() const; - - private: - IPlatformScreen::CButtonInfo* m_buttonInfo; - bool m_press; - }; - - class CRule { - public: - CRule(); - CRule(CCondition* adopted); - CRule(const CRule&); - ~CRule(); - - CRule& operator=(const CRule&); - - // replace the condition - void setCondition(CCondition* adopted); - - // add an action to the rule - void adoptAction(CAction*, bool onActivation); - - // remove an action from the rule - void removeAction(bool onActivation, UInt32 index); - - // replace an action in the rule - void replaceAction(CAction* adopted, - bool onActivation, UInt32 index); - - // enable/disable - void enable(CPrimaryClient*); - void disable(CPrimaryClient*); - - // event handling - bool handleEvent(const CEvent&); - - // convert rule to a string - CString format() const; - - // get the rule's condition - const CCondition* - getCondition() const; - - // get number of actions - UInt32 getNumActions(bool onActivation) const; - - // get action by index - const CAction& getAction(bool onActivation, UInt32 index) const; - - private: - void clear(); - void copy(const CRule&); - - private: - typedef std::vector CActionList; - - CCondition* m_condition; - CActionList m_activateActions; - CActionList m_deactivateActions; - }; - - // ------------------------------------------------------------------------- - // Input Filter Class - // ------------------------------------------------------------------------- - typedef std::vector CRuleList; - - CInputFilter(); - CInputFilter(const CInputFilter&); - virtual ~CInputFilter(); - - CInputFilter& operator=(const CInputFilter&); - - // add rule, adopting the condition and the actions - void addFilterRule(const CRule& rule); - - // remove a rule - void removeFilterRule(UInt32 index); - - // get rule by index - CRule& getRule(UInt32 index); - - // enable event filtering using the given primary client. disable - // if client is NULL. - void setPrimaryClient(CPrimaryClient* client); - - // convert rules to a string - CString format(const CString& linePrefix) const; - - // get number of rules - UInt32 getNumRules() const; - - //! Compare filters - bool operator==(const CInputFilter&) const; - //! Compare filters - bool operator!=(const CInputFilter&) const; - -private: - // event handling - void handleEvent(const CEvent&, void*); - -private: - CRuleList m_ruleList; - CPrimaryClient* m_primaryClient; -}; - -#endif diff --git a/lib/server/CPrimaryClient.cpp b/lib/server/CPrimaryClient.cpp deleted file mode 100644 index 03146655..00000000 --- a/lib/server/CPrimaryClient.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CPrimaryClient.h" -#include "CScreen.h" -#include "CClipboard.h" -#include "CLog.h" - -// -// CPrimaryClient -// - -CPrimaryClient::CPrimaryClient(const CString& name, CScreen* screen) : - CBaseClientProxy(name), - m_screen(screen), - m_fakeInputCount(0) -{ - // all clipboards are clean - for (UInt32 i = 0; i < kClipboardEnd; ++i) { - m_clipboardDirty[i] = false; - } -} - -CPrimaryClient::~CPrimaryClient() -{ - // do nothing -} - -void -CPrimaryClient::reconfigure(UInt32 activeSides) -{ - m_screen->reconfigure(activeSides); -} - -UInt32 -CPrimaryClient::registerHotKey(KeyID key, KeyModifierMask mask) -{ - return m_screen->registerHotKey(key, mask); -} - -void -CPrimaryClient::unregisterHotKey(UInt32 id) -{ - m_screen->unregisterHotKey(id); -} - -void -CPrimaryClient::fakeInputBegin() -{ - if (++m_fakeInputCount == 1) { - m_screen->fakeInputBegin(); - } -} - -void -CPrimaryClient::fakeInputEnd() -{ - if (--m_fakeInputCount == 0) { - m_screen->fakeInputEnd(); - } -} - -SInt32 -CPrimaryClient::getJumpZoneSize() const -{ - return m_screen->getJumpZoneSize(); -} - -void -CPrimaryClient::getCursorCenter(SInt32& x, SInt32& y) const -{ - m_screen->getCursorCenter(x, y); -} - -KeyModifierMask -CPrimaryClient::getToggleMask() const -{ - return m_screen->pollActiveModifiers(); -} - -bool -CPrimaryClient::isLockedToScreen() const -{ - return m_screen->isLockedToScreen(); -} - -void* -CPrimaryClient::getEventTarget() const -{ - return m_screen->getEventTarget(); -} - -bool -CPrimaryClient::getClipboard(ClipboardID id, IClipboard* clipboard) const -{ - return m_screen->getClipboard(id, clipboard); -} - -void -CPrimaryClient::getShape(SInt32& x, SInt32& y, - SInt32& width, SInt32& height) const -{ - m_screen->getShape(x, y, width, height); -} - -void -CPrimaryClient::getCursorPos(SInt32& x, SInt32& y) const -{ - m_screen->getCursorPos(x, y); -} - -void -CPrimaryClient::enable() -{ - m_screen->enable(); -} - -void -CPrimaryClient::disable() -{ - m_screen->disable(); -} - -void -CPrimaryClient::enter(SInt32 xAbs, SInt32 yAbs, - UInt32 seqNum, KeyModifierMask mask, bool screensaver) -{ - m_screen->setSequenceNumber(seqNum); - if (!screensaver) { - m_screen->warpCursor(xAbs, yAbs); - } - m_screen->enter(mask); -} - -bool -CPrimaryClient::leave() -{ - return m_screen->leave(); -} - -void -CPrimaryClient::setClipboard(ClipboardID id, const IClipboard* clipboard) -{ - // ignore if this clipboard is already clean - if (m_clipboardDirty[id]) { - // this clipboard is now clean - m_clipboardDirty[id] = false; - - // set clipboard - m_screen->setClipboard(id, clipboard); - } -} - -void -CPrimaryClient::grabClipboard(ClipboardID id) -{ - // grab clipboard - m_screen->grabClipboard(id); - - // clipboard is dirty (because someone else owns it now) - m_clipboardDirty[id] = true; -} - -void -CPrimaryClient::setClipboardDirty(ClipboardID id, bool dirty) -{ - m_clipboardDirty[id] = dirty; -} - -void -CPrimaryClient::keyDown(KeyID key, KeyModifierMask mask, KeyButton button) -{ - if (m_fakeInputCount > 0) { -// XXX -- don't forward keystrokes to primary screen for now - (void)key; - (void)mask; - (void)button; -// m_screen->keyDown(key, mask, button); - } -} - -void -CPrimaryClient::keyRepeat(KeyID, KeyModifierMask, SInt32, KeyButton) -{ - // ignore -} - -void -CPrimaryClient::keyUp(KeyID key, KeyModifierMask mask, KeyButton button) -{ - if (m_fakeInputCount > 0) { -// XXX -- don't forward keystrokes to primary screen for now - (void)key; - (void)mask; - (void)button; -// m_screen->keyUp(key, mask, button); - } -} - -void -CPrimaryClient::mouseDown(ButtonID) -{ - // ignore -} - -void -CPrimaryClient::mouseUp(ButtonID) -{ - // ignore -} - -void -CPrimaryClient::mouseMove(SInt32 x, SInt32 y) -{ - m_screen->warpCursor(x, y); -} - -void -CPrimaryClient::mouseRelativeMove(SInt32, SInt32) -{ - // ignore -} - -void -CPrimaryClient::mouseWheel(SInt32, SInt32) -{ - // ignore -} - -void -CPrimaryClient::screensaver(bool) -{ - // ignore -} - -void -CPrimaryClient::resetOptions() -{ - m_screen->resetOptions(); -} - -void -CPrimaryClient::setOptions(const COptionsList& options) -{ - m_screen->setOptions(options); -} diff --git a/lib/server/CPrimaryClient.h b/lib/server/CPrimaryClient.h deleted file mode 100644 index e768a21d..00000000 --- a/lib/server/CPrimaryClient.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CPRIMARYCLIENT_H -#define CPRIMARYCLIENT_H - -#include "CBaseClientProxy.h" -#include "ProtocolTypes.h" - -class CScreen; - -//! Primary screen as pseudo-client -/*! -The primary screen does not have a client associated with it. This -class provides a pseudo-client to allow the primary screen to be -treated as if it was a client. -*/ -class CPrimaryClient : public CBaseClientProxy { -public: - /*! - \c name is the name of the server and \p screen is primary screen. - */ - CPrimaryClient(const CString& name, CScreen* screen); - ~CPrimaryClient(); - - //! @name manipulators - //@{ - - //! Update configuration - /*! - Handles reconfiguration of jump zones. - */ - void reconfigure(UInt32 activeSides); - - //! Register a system hotkey - /*! - Registers a system-wide hotkey for key \p key with modifiers \p mask. - Returns an id used to unregister the hotkey. - */ - UInt32 registerHotKey(KeyID key, KeyModifierMask mask); - - //! Unregister a system hotkey - /*! - Unregisters a previously registered hot key. - */ - void unregisterHotKey(UInt32 id); - - //! Prepare to synthesize input on primary screen - /*! - Prepares the primary screen to receive synthesized input. We do not - want to receive this synthesized input as user input so this method - ensures that we ignore it. Calls to \c fakeInputBegin() and - \c fakeInputEnd() may be nested; only the outermost have an effect. - */ - void fakeInputBegin(); - - //! Done synthesizing input on primary screen - /*! - Undoes whatever \c fakeInputBegin() did. - */ - void fakeInputEnd(); - - //@} - //! @name accessors - //@{ - - //! Get jump zone size - /*! - Return the jump zone size, the size of the regions on the edges of - the screen that cause the cursor to jump to another screen. - */ - SInt32 getJumpZoneSize() const; - - //! Get cursor center position - /*! - Return the cursor center position which is where we park the - cursor to compute cursor motion deltas and should be far from - the edges of the screen, typically the center. - */ - void getCursorCenter(SInt32& x, SInt32& y) const; - - //! Get toggle key state - /*! - Returns the primary screen's current toggle modifier key state. - */ - KeyModifierMask getToggleMask() const; - - //! Get screen lock state - /*! - Returns true if the user is locked to the screen. - */ - bool isLockedToScreen() const; - - //@} - - // FIXME -- these probably belong on IScreen - virtual void enable(); - virtual void disable(); - - // IScreen overrides - virtual void* getEventTarget() const; - virtual bool getClipboard(ClipboardID id, IClipboard*) const; - virtual void getShape(SInt32& x, SInt32& y, - SInt32& width, SInt32& height) const; - virtual void getCursorPos(SInt32& x, SInt32& y) const; - - // IClient overrides - virtual void enter(SInt32 xAbs, SInt32 yAbs, - UInt32 seqNum, KeyModifierMask mask, - bool forScreensaver); - virtual bool leave(); - virtual void setClipboard(ClipboardID, const IClipboard*); - virtual void grabClipboard(ClipboardID); - virtual void setClipboardDirty(ClipboardID, bool); - virtual void keyDown(KeyID, KeyModifierMask, KeyButton); - virtual void keyRepeat(KeyID, KeyModifierMask, - SInt32 count, KeyButton); - virtual void keyUp(KeyID, KeyModifierMask, KeyButton); - virtual void mouseDown(ButtonID); - virtual void mouseUp(ButtonID); - virtual void mouseMove(SInt32 xAbs, SInt32 yAbs); - virtual void mouseRelativeMove(SInt32 xRel, SInt32 yRel); - virtual void mouseWheel(SInt32 xDelta, SInt32 yDelta); - virtual void screensaver(bool activate); - virtual void resetOptions(); - virtual void setOptions(const COptionsList& options); - -private: - CScreen* m_screen; - bool m_clipboardDirty[kClipboardEnd]; - SInt32 m_fakeInputCount; -}; - -#endif diff --git a/lib/server/CServer.cpp b/lib/server/CServer.cpp deleted file mode 100644 index 3d4d32c2..00000000 --- a/lib/server/CServer.cpp +++ /dev/null @@ -1,2176 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CServer.h" -#include "CClientProxy.h" -#include "CClientProxyUnknown.h" -#include "CPrimaryClient.h" -#include "IPlatformScreen.h" -#include "OptionTypes.h" -#include "ProtocolTypes.h" -#include "XScreen.h" -#include "XSynergy.h" -#include "IDataSocket.h" -#include "IListenSocket.h" -#include "XSocket.h" -#include "IEventQueue.h" -#include "CLog.h" -#include "TMethodEventJob.h" -#include "CArch.h" -#include - -// -// CServer -// - -CEvent::Type CServer::s_errorEvent = CEvent::kUnknown; -CEvent::Type CServer::s_connectedEvent = CEvent::kUnknown; -CEvent::Type CServer::s_disconnectedEvent = CEvent::kUnknown; -CEvent::Type CServer::s_switchToScreen = CEvent::kUnknown; -CEvent::Type CServer::s_switchInDirection = CEvent::kUnknown; -CEvent::Type CServer::s_keyboardBroadcast = CEvent::kUnknown; -CEvent::Type CServer::s_lockCursorToScreen = CEvent::kUnknown; - -CServer::CServer(const CConfig& config, CPrimaryClient* primaryClient) : - m_primaryClient(primaryClient), - m_active(primaryClient), - m_seqNum(0), - m_xDelta(0), - m_yDelta(0), - m_xDelta2(0), - m_yDelta2(0), - m_config(), - m_inputFilter(m_config.getInputFilter()), - m_activeSaver(NULL), - m_switchDir(kNoDirection), - m_switchScreen(NULL), - m_switchWaitDelay(0.0), - m_switchWaitTimer(NULL), - m_switchTwoTapDelay(0.0), - m_switchTwoTapEngaged(false), - m_switchTwoTapArmed(false), - m_switchTwoTapZone(3), - m_relativeMoves(false), - m_keyboardBroadcasting(false), - m_lockedToScreen(false) -{ - // must have a primary client and it must have a canonical name - assert(m_primaryClient != NULL); - assert(config.isScreen(primaryClient->getName())); - - CString primaryName = getName(primaryClient); - - // clear clipboards - for (ClipboardID id = 0; id < kClipboardEnd; ++id) { - CClipboardInfo& clipboard = m_clipboards[id]; - clipboard.m_clipboardOwner = primaryName; - clipboard.m_clipboardSeqNum = m_seqNum; - if (clipboard.m_clipboard.open(0)) { - clipboard.m_clipboard.empty(); - clipboard.m_clipboard.close(); - } - clipboard.m_clipboardData = clipboard.m_clipboard.marshall(); - } - - // install event handlers - EVENTQUEUE->adoptHandler(CEvent::kTimer, this, - new TMethodEventJob(this, - &CServer::handleSwitchWaitTimeout)); - EVENTQUEUE->adoptHandler(IPlatformScreen::getKeyDownEvent(), - m_inputFilter, - new TMethodEventJob(this, - &CServer::handleKeyDownEvent)); - EVENTQUEUE->adoptHandler(IPlatformScreen::getKeyUpEvent(), - m_inputFilter, - new TMethodEventJob(this, - &CServer::handleKeyUpEvent)); - EVENTQUEUE->adoptHandler(IPlatformScreen::getKeyRepeatEvent(), - m_inputFilter, - new TMethodEventJob(this, - &CServer::handleKeyRepeatEvent)); - EVENTQUEUE->adoptHandler(IPlatformScreen::getButtonDownEvent(), - m_inputFilter, - new TMethodEventJob(this, - &CServer::handleButtonDownEvent)); - EVENTQUEUE->adoptHandler(IPlatformScreen::getButtonUpEvent(), - m_inputFilter, - new TMethodEventJob(this, - &CServer::handleButtonUpEvent)); - EVENTQUEUE->adoptHandler(IPlatformScreen::getMotionOnPrimaryEvent(), - m_primaryClient->getEventTarget(), - new TMethodEventJob(this, - &CServer::handleMotionPrimaryEvent)); - EVENTQUEUE->adoptHandler(IPlatformScreen::getMotionOnSecondaryEvent(), - m_primaryClient->getEventTarget(), - new TMethodEventJob(this, - &CServer::handleMotionSecondaryEvent)); - EVENTQUEUE->adoptHandler(IPlatformScreen::getWheelEvent(), - m_primaryClient->getEventTarget(), - new TMethodEventJob(this, - &CServer::handleWheelEvent)); - EVENTQUEUE->adoptHandler(IPlatformScreen::getScreensaverActivatedEvent(), - m_primaryClient->getEventTarget(), - new TMethodEventJob(this, - &CServer::handleScreensaverActivatedEvent)); - EVENTQUEUE->adoptHandler(IPlatformScreen::getScreensaverDeactivatedEvent(), - m_primaryClient->getEventTarget(), - new TMethodEventJob(this, - &CServer::handleScreensaverDeactivatedEvent)); - EVENTQUEUE->adoptHandler(getSwitchToScreenEvent(), - m_inputFilter, - new TMethodEventJob(this, - &CServer::handleSwitchToScreenEvent)); - EVENTQUEUE->adoptHandler(getSwitchInDirectionEvent(), - m_inputFilter, - new TMethodEventJob(this, - &CServer::handleSwitchInDirectionEvent)); - EVENTQUEUE->adoptHandler(getKeyboardBroadcastEvent(), - m_inputFilter, - new TMethodEventJob(this, - &CServer::handleKeyboardBroadcastEvent)); - EVENTQUEUE->adoptHandler(getLockCursorToScreenEvent(), - m_inputFilter, - new TMethodEventJob(this, - &CServer::handleLockCursorToScreenEvent)); - EVENTQUEUE->adoptHandler(IPlatformScreen::getFakeInputBeginEvent(), - m_inputFilter, - new TMethodEventJob(this, - &CServer::handleFakeInputBeginEvent)); - EVENTQUEUE->adoptHandler(IPlatformScreen::getFakeInputEndEvent(), - m_inputFilter, - new TMethodEventJob(this, - &CServer::handleFakeInputEndEvent)); - - // add connection - addClient(m_primaryClient); - - // set initial configuration - setConfig(config); - - // enable primary client - m_primaryClient->enable(); - m_inputFilter->setPrimaryClient(m_primaryClient); -} - -CServer::~CServer() -{ - // remove event handlers and timers - EVENTQUEUE->removeHandler(IPlatformScreen::getKeyDownEvent(), - m_inputFilter); - EVENTQUEUE->removeHandler(IPlatformScreen::getKeyUpEvent(), - m_inputFilter); - EVENTQUEUE->removeHandler(IPlatformScreen::getKeyRepeatEvent(), - m_inputFilter); - EVENTQUEUE->removeHandler(IPlatformScreen::getButtonDownEvent(), - m_inputFilter); - EVENTQUEUE->removeHandler(IPlatformScreen::getButtonUpEvent(), - m_inputFilter); - EVENTQUEUE->removeHandler(IPlatformScreen::getMotionOnPrimaryEvent(), - m_primaryClient->getEventTarget()); - EVENTQUEUE->removeHandler(IPlatformScreen::getMotionOnSecondaryEvent(), - m_primaryClient->getEventTarget()); - EVENTQUEUE->removeHandler(IPlatformScreen::getWheelEvent(), - m_primaryClient->getEventTarget()); - EVENTQUEUE->removeHandler(IPlatformScreen::getScreensaverActivatedEvent(), - m_primaryClient->getEventTarget()); - EVENTQUEUE->removeHandler(IPlatformScreen::getScreensaverDeactivatedEvent(), - m_primaryClient->getEventTarget()); - EVENTQUEUE->removeHandler(IPlatformScreen::getFakeInputBeginEvent(), - m_inputFilter); - EVENTQUEUE->removeHandler(IPlatformScreen::getFakeInputEndEvent(), - m_inputFilter); - EVENTQUEUE->removeHandler(CEvent::kTimer, this); - stopSwitch(); - - // force immediate disconnection of secondary clients - disconnect(); - for (COldClients::iterator index = m_oldClients.begin(); - index != m_oldClients.begin(); ++index) { - CBaseClientProxy* client = index->first; - EVENTQUEUE->deleteTimer(index->second); - EVENTQUEUE->removeHandler(CEvent::kTimer, client); - EVENTQUEUE->removeHandler(CClientProxy::getDisconnectedEvent(), client); - delete client; - } - - // remove input filter - m_inputFilter->setPrimaryClient(NULL); - - // disable and disconnect primary client - m_primaryClient->disable(); - removeClient(m_primaryClient); -} - -bool -CServer::setConfig(const CConfig& config) -{ - // refuse configuration if it doesn't include the primary screen - if (!config.isScreen(m_primaryClient->getName())) { - return false; - } - - // close clients that are connected but being dropped from the - // configuration. - closeClients(config); - - // cut over - m_config = config; - processOptions(); - - // add ScrollLock as a hotkey to lock to the screen. this was a - // built-in feature in earlier releases and is now supported via - // the user configurable hotkey mechanism. if the user has already - // registered ScrollLock for something else then that will win but - // we will unfortunately generate a warning. if the user has - // configured a CLockCursorToScreenAction then we don't add - // ScrollLock as a hotkey. - if (!m_config.hasLockToScreenAction()) { - IPlatformScreen::CKeyInfo* key = - IPlatformScreen::CKeyInfo::alloc(kKeyScrollLock, 0, 0, 0); - CInputFilter::CRule rule(new CInputFilter::CKeystrokeCondition(key)); - rule.adoptAction(new CInputFilter::CLockCursorToScreenAction, true); - m_inputFilter->addFilterRule(rule); - } - - // tell primary screen about reconfiguration - m_primaryClient->reconfigure(getActivePrimarySides()); - - // tell all (connected) clients about current options - for (CClientList::const_iterator index = m_clients.begin(); - index != m_clients.end(); ++index) { - CBaseClientProxy* client = index->second; - sendOptions(client); - } - - return true; -} - -void -CServer::adoptClient(CBaseClientProxy* client) -{ - assert(client != NULL); - - // watch for client disconnection - EVENTQUEUE->adoptHandler(CClientProxy::getDisconnectedEvent(), client, - new TMethodEventJob(this, - &CServer::handleClientDisconnected, client)); - - // name must be in our configuration - if (!m_config.isScreen(client->getName())) { - LOG((CLOG_WARN "a client with name \"%s\" is not in the map", client->getName().c_str())); - closeClient(client, kMsgEUnknown); - return; - } - - // add client to client list - if (!addClient(client)) { - // can only have one screen with a given name at any given time - LOG((CLOG_WARN "a client with name \"%s\" is already connected", getName(client).c_str())); - closeClient(client, kMsgEBusy); - return; - } - LOG((CLOG_NOTE "client \"%s\" has connected", getName(client).c_str())); - - // send configuration options to client - sendOptions(client); - - // activate screen saver on new client if active on the primary screen - if (m_activeSaver != NULL) { - client->screensaver(true); - } - - // send notification - CServer::CScreenConnectedInfo* info = - CServer::CScreenConnectedInfo::alloc(getName(client)); - EVENTQUEUE->addEvent(CEvent(CServer::getConnectedEvent(), - m_primaryClient->getEventTarget(), info)); -} - -void -CServer::disconnect() -{ - // close all secondary clients - if (m_clients.size() > 1 || !m_oldClients.empty()) { - CConfig emptyConfig; - closeClients(emptyConfig); - } - else { - EVENTQUEUE->addEvent(CEvent(getDisconnectedEvent(), this)); - } -} - -UInt32 -CServer::getNumClients() const -{ - return m_clients.size(); -} - -void -CServer::getClients(std::vector& list) const -{ - list.clear(); - for (CClientList::const_iterator index = m_clients.begin(); - index != m_clients.end(); ++index) { - list.push_back(index->first); - } -} - -CEvent::Type -CServer::getErrorEvent() -{ - return CEvent::registerTypeOnce(s_errorEvent, - "CServer::error"); -} - -CEvent::Type -CServer::getConnectedEvent() -{ - return CEvent::registerTypeOnce(s_connectedEvent, - "CServer::connected"); -} - -CEvent::Type -CServer::getDisconnectedEvent() -{ - return CEvent::registerTypeOnce(s_disconnectedEvent, - "CServer::disconnected"); -} - -CEvent::Type -CServer::getSwitchToScreenEvent() -{ - return CEvent::registerTypeOnce(s_switchToScreen, - "CServer::switchToScreen"); -} - -CEvent::Type -CServer::getSwitchInDirectionEvent() -{ - return CEvent::registerTypeOnce(s_switchInDirection, - "CServer::switchInDirection"); -} - -CEvent::Type -CServer::getKeyboardBroadcastEvent() -{ - return CEvent::registerTypeOnce(s_keyboardBroadcast, - "CServer:keyboardBroadcast"); -} - -CEvent::Type -CServer::getLockCursorToScreenEvent() -{ - return CEvent::registerTypeOnce(s_lockCursorToScreen, - "CServer::lockCursorToScreen"); -} - -CString -CServer::getName(const CBaseClientProxy* client) const -{ - CString name = m_config.getCanonicalName(client->getName()); - if (name.empty()) { - name = client->getName(); - } - return name; -} - -UInt32 -CServer::getActivePrimarySides() const -{ - UInt32 sides = 0; - if (!isLockedToScreenServer()) { - if (hasAnyNeighbor(m_primaryClient, kLeft)) { - sides |= kLeftMask; - } - if (hasAnyNeighbor(m_primaryClient, kRight)) { - sides |= kRightMask; - } - if (hasAnyNeighbor(m_primaryClient, kTop)) { - sides |= kTopMask; - } - if (hasAnyNeighbor(m_primaryClient, kBottom)) { - sides |= kBottomMask; - } - } - return sides; -} - -bool -CServer::isLockedToScreenServer() const -{ - // locked if scroll-lock is toggled on - return m_lockedToScreen; -} - -bool -CServer::isLockedToScreen() const -{ - // locked if we say we're locked - if (isLockedToScreenServer()) { - LOG((CLOG_DEBUG "locked to screen")); - return true; - } - - // locked if primary says we're locked - if (m_primaryClient->isLockedToScreen()) { - return true; - } - - // not locked - return false; -} - -SInt32 -CServer::getJumpZoneSize(CBaseClientProxy* client) const -{ - if (client == m_primaryClient) { - return m_primaryClient->getJumpZoneSize(); - } - else { - return 0; - } -} - -void -CServer::switchScreen(CBaseClientProxy* dst, - SInt32 x, SInt32 y, bool forScreensaver) -{ - assert(dst != NULL); -#ifndef NDEBUG - { - SInt32 dx, dy, dw, dh; - dst->getShape(dx, dy, dw, dh); - assert(x >= dx && y >= dy && x < dx + dw && y < dy + dh); - } -#endif - assert(m_active != NULL); - - LOG((CLOG_INFO "switch from \"%s\" to \"%s\" at %d,%d", getName(m_active).c_str(), getName(dst).c_str(), x, y)); - - // stop waiting to switch - stopSwitch(); - - // record new position - m_x = x; - m_y = y; - m_xDelta = 0; - m_yDelta = 0; - m_xDelta2 = 0; - m_yDelta2 = 0; - - // wrapping means leaving the active screen and entering it again. - // since that's a waste of time we skip that and just warp the - // mouse. - if (m_active != dst) { - // leave active screen - if (!m_active->leave()) { - // cannot leave screen - LOG((CLOG_WARN "can't leave screen")); - return; - } - - // update the primary client's clipboards if we're leaving the - // primary screen. - if (m_active == m_primaryClient) { - for (ClipboardID id = 0; id < kClipboardEnd; ++id) { - CClipboardInfo& clipboard = m_clipboards[id]; - if (clipboard.m_clipboardOwner == getName(m_primaryClient)) { - onClipboardChanged(m_primaryClient, - id, clipboard.m_clipboardSeqNum); - } - } - } - - // cut over - m_active = dst; - - // increment enter sequence number - ++m_seqNum; - - // enter new screen - m_active->enter(x, y, m_seqNum, - m_primaryClient->getToggleMask(), - forScreensaver); - - // send the clipboard data to new active screen - for (ClipboardID id = 0; id < kClipboardEnd; ++id) { - m_active->setClipboard(id, &m_clipboards[id].m_clipboard); - } - } - else { - m_active->mouseMove(x, y); - } -} - -void -CServer::jumpToScreen(CBaseClientProxy* newScreen) -{ - assert(newScreen != NULL); - - // record the current cursor position on the active screen - m_active->setJumpCursorPos(m_x, m_y); - - // get the last cursor position on the target screen - SInt32 x, y; - newScreen->getJumpCursorPos(x, y); - - switchScreen(newScreen, x, y, false); -} - -float -CServer::mapToFraction(CBaseClientProxy* client, - EDirection dir, SInt32 x, SInt32 y) const -{ - SInt32 sx, sy, sw, sh; - client->getShape(sx, sy, sw, sh); - switch (dir) { - case kLeft: - case kRight: - return static_cast(y - sy + 0.5f) / static_cast(sh); - - case kTop: - case kBottom: - return static_cast(x - sx + 0.5f) / static_cast(sw); - - case kNoDirection: - assert(0 && "bad direction"); - break; - } - return 0.0f; -} - -void -CServer::mapToPixel(CBaseClientProxy* client, - EDirection dir, float f, SInt32& x, SInt32& y) const -{ - SInt32 sx, sy, sw, sh; - client->getShape(sx, sy, sw, sh); - switch (dir) { - case kLeft: - case kRight: - y = static_cast(f * sh) + sy; - break; - - case kTop: - case kBottom: - x = static_cast(f * sw) + sx; - break; - - case kNoDirection: - assert(0 && "bad direction"); - break; - } -} - -bool -CServer::hasAnyNeighbor(CBaseClientProxy* client, EDirection dir) const -{ - assert(client != NULL); - - return m_config.hasNeighbor(getName(client), dir); -} - -CBaseClientProxy* -CServer::getNeighbor(CBaseClientProxy* src, - EDirection dir, SInt32& x, SInt32& y) const -{ - // note -- must be locked on entry - - assert(src != NULL); - - // get source screen name - CString srcName = getName(src); - assert(!srcName.empty()); - LOG((CLOG_DEBUG2 "find neighbor on %s of \"%s\"", CConfig::dirName(dir), srcName.c_str())); - - // convert position to fraction - float t = mapToFraction(src, dir, x, y); - - // search for the closest neighbor that exists in direction dir - float tTmp; - for (;;) { - CString dstName(m_config.getNeighbor(srcName, dir, t, &tTmp)); - - // if nothing in that direction then return NULL. if the - // destination is the source then we can make no more - // progress in this direction. since we haven't found a - // connected neighbor we return NULL. - if (dstName.empty()) { - LOG((CLOG_DEBUG2 "no neighbor on %s of \"%s\"", CConfig::dirName(dir), srcName.c_str())); - return NULL; - } - - // look up neighbor cell. if the screen is connected and - // ready then we can stop. - CClientList::const_iterator index = m_clients.find(dstName); - if (index != m_clients.end()) { - LOG((CLOG_DEBUG2 "\"%s\" is on %s of \"%s\" at %f", dstName.c_str(), CConfig::dirName(dir), srcName.c_str(), t)); - mapToPixel(index->second, dir, tTmp, x, y); - return index->second; - } - - // skip over unconnected screen - LOG((CLOG_DEBUG2 "ignored \"%s\" on %s of \"%s\"", dstName.c_str(), CConfig::dirName(dir), srcName.c_str())); - srcName = dstName; - - // use position on skipped screen - t = tTmp; - } -} - -CBaseClientProxy* -CServer::mapToNeighbor(CBaseClientProxy* src, - EDirection srcSide, SInt32& x, SInt32& y) const -{ - // note -- must be locked on entry - - assert(src != NULL); - - // get the first neighbor - CBaseClientProxy* dst = getNeighbor(src, srcSide, x, y); - if (dst == NULL) { - return NULL; - } - - // get the source screen's size - SInt32 dx, dy, dw, dh; - CBaseClientProxy* lastGoodScreen = src; - lastGoodScreen->getShape(dx, dy, dw, dh); - - // find destination screen, adjusting x or y (but not both). the - // searches are done in a sort of canonical screen space where - // the upper-left corner is 0,0 for each screen. we adjust from - // actual to canonical position on entry to and from canonical to - // actual on exit from the search. - switch (srcSide) { - case kLeft: - x -= dx; - while (dst != NULL) { - lastGoodScreen = dst; - lastGoodScreen->getShape(dx, dy, dw, dh); - x += dw; - if (x >= 0) { - break; - } - LOG((CLOG_DEBUG2 "skipping over screen %s", getName(dst).c_str())); - dst = getNeighbor(lastGoodScreen, srcSide, x, y); - } - assert(lastGoodScreen != NULL); - x += dx; - break; - - case kRight: - x -= dx; - while (dst != NULL) { - x -= dw; - lastGoodScreen = dst; - lastGoodScreen->getShape(dx, dy, dw, dh); - if (x < dw) { - break; - } - LOG((CLOG_DEBUG2 "skipping over screen %s", getName(dst).c_str())); - dst = getNeighbor(lastGoodScreen, srcSide, x, y); - } - assert(lastGoodScreen != NULL); - x += dx; - break; - - case kTop: - y -= dy; - while (dst != NULL) { - lastGoodScreen = dst; - lastGoodScreen->getShape(dx, dy, dw, dh); - y += dh; - if (y >= 0) { - break; - } - LOG((CLOG_DEBUG2 "skipping over screen %s", getName(dst).c_str())); - dst = getNeighbor(lastGoodScreen, srcSide, x, y); - } - assert(lastGoodScreen != NULL); - y += dy; - break; - - case kBottom: - y -= dy; - while (dst != NULL) { - y -= dh; - lastGoodScreen = dst; - lastGoodScreen->getShape(dx, dy, dw, dh); - if (y < dh) { - break; - } - LOG((CLOG_DEBUG2 "skipping over screen %s", getName(dst).c_str())); - dst = getNeighbor(lastGoodScreen, srcSide, x, y); - } - assert(lastGoodScreen != NULL); - y += dy; - break; - - case kNoDirection: - assert(0 && "bad direction"); - return NULL; - } - - // save destination screen - assert(lastGoodScreen != NULL); - dst = lastGoodScreen; - - // if entering primary screen then be sure to move in far enough - // to avoid the jump zone. if entering a side that doesn't have - // a neighbor (i.e. an asymmetrical side) then we don't need to - // move inwards because that side can't provoke a jump. - avoidJumpZone(dst, srcSide, x, y); - - return dst; -} - -void -CServer::avoidJumpZone(CBaseClientProxy* dst, - EDirection dir, SInt32& x, SInt32& y) const -{ - // we only need to avoid jump zones on the primary screen - if (dst != m_primaryClient) { - return; - } - - const CString dstName(getName(dst)); - SInt32 dx, dy, dw, dh; - dst->getShape(dx, dy, dw, dh); - float t = mapToFraction(dst, dir, x, y); - SInt32 z = getJumpZoneSize(dst); - - // move in far enough to avoid the jump zone. if entering a side - // that doesn't have a neighbor (i.e. an asymmetrical side) then we - // don't need to move inwards because that side can't provoke a jump. - switch (dir) { - case kLeft: - if (!m_config.getNeighbor(dstName, kRight, t, NULL).empty() && - x > dx + dw - 1 - z) - x = dx + dw - 1 - z; - break; - - case kRight: - if (!m_config.getNeighbor(dstName, kLeft, t, NULL).empty() && - x < dx + z) - x = dx + z; - break; - - case kTop: - if (!m_config.getNeighbor(dstName, kBottom, t, NULL).empty() && - y > dy + dh - 1 - z) - y = dy + dh - 1 - z; - break; - - case kBottom: - if (!m_config.getNeighbor(dstName, kTop, t, NULL).empty() && - y < dy + z) - y = dy + z; - break; - - case kNoDirection: - assert(0 && "bad direction"); - } -} - -bool -CServer::isSwitchOkay(CBaseClientProxy* newScreen, - EDirection dir, SInt32 x, SInt32 y, - SInt32 xActive, SInt32 yActive) -{ - LOG((CLOG_DEBUG1 "try to leave \"%s\" on %s", getName(m_active).c_str(), CConfig::dirName(dir))); - - // is there a neighbor? - if (newScreen == NULL) { - // there's no neighbor. we don't want to switch and we don't - // want to try to switch later. - LOG((CLOG_DEBUG1 "no neighbor %s", CConfig::dirName(dir))); - stopSwitch(); - return false; - } - - // should we switch or not? - bool preventSwitch = false; - bool allowSwitch = false; - - // note if the switch direction has changed. save the new - // direction and screen if so. - bool isNewDirection = (dir != m_switchDir); - if (isNewDirection || m_switchScreen == NULL) { - m_switchDir = dir; - m_switchScreen = newScreen; - } - - // is this a double tap and do we care? - if (!allowSwitch && m_switchTwoTapDelay > 0.0) { - if (isNewDirection || - !isSwitchTwoTapStarted() || !shouldSwitchTwoTap()) { - // tapping a different or new edge or second tap not - // fast enough. prepare for second tap. - preventSwitch = true; - startSwitchTwoTap(); - } - else { - // got second tap - allowSwitch = true; - } - } - - // if waiting before a switch then prepare to switch later - if (!allowSwitch && m_switchWaitDelay > 0.0) { - if (isNewDirection || !isSwitchWaitStarted()) { - startSwitchWait(x, y); - } - preventSwitch = true; - } - - // are we in a locked corner? first check if screen has the option set - // and, if not, check the global options. - const CConfig::CScreenOptions* options = - m_config.getOptions(getName(m_active)); - if (options == NULL || options->count(kOptionScreenSwitchCorners) == 0) { - options = m_config.getOptions(""); - } - if (options != NULL && options->count(kOptionScreenSwitchCorners) > 0) { - // get corner mask and size - CConfig::CScreenOptions::const_iterator i = - options->find(kOptionScreenSwitchCorners); - UInt32 corners = static_cast(i->second); - i = options->find(kOptionScreenSwitchCornerSize); - SInt32 size = 0; - if (i != options->end()) { - size = i->second; - } - - // see if we're in a locked corner - if ((getCorner(m_active, xActive, yActive, size) & corners) != 0) { - // yep, no switching - LOG((CLOG_DEBUG1 "locked in corner")); - preventSwitch = true; - stopSwitch(); - } - } - - // ignore if mouse is locked to screen and don't try to switch later - if (!preventSwitch && isLockedToScreen()) { - LOG((CLOG_DEBUG1 "locked to screen")); - preventSwitch = true; - stopSwitch(); - } - - return !preventSwitch; -} - -void -CServer::noSwitch(SInt32 x, SInt32 y) -{ - armSwitchTwoTap(x, y); - stopSwitchWait(); -} - -void -CServer::stopSwitch() -{ - if (m_switchScreen != NULL) { - m_switchScreen = NULL; - m_switchDir = kNoDirection; - stopSwitchTwoTap(); - stopSwitchWait(); - } -} - -void -CServer::startSwitchTwoTap() -{ - m_switchTwoTapEngaged = true; - m_switchTwoTapArmed = false; - m_switchTwoTapTimer.reset(); - LOG((CLOG_DEBUG1 "waiting for second tap")); -} - -void -CServer::armSwitchTwoTap(SInt32 x, SInt32 y) -{ - if (m_switchTwoTapEngaged) { - if (m_switchTwoTapTimer.getTime() > m_switchTwoTapDelay) { - // second tap took too long. disengage. - stopSwitchTwoTap(); - } - else if (!m_switchTwoTapArmed) { - // still time for a double tap. see if we left the tap - // zone and, if so, arm the two tap. - SInt32 ax, ay, aw, ah; - m_active->getShape(ax, ay, aw, ah); - SInt32 tapZone = m_primaryClient->getJumpZoneSize(); - if (tapZone < m_switchTwoTapZone) { - tapZone = m_switchTwoTapZone; - } - if (x >= ax + tapZone && x < ax + aw - tapZone && - y >= ay + tapZone && y < ay + ah - tapZone) { - // win32 can generate bogus mouse events that appear to - // move in the opposite direction that the mouse actually - // moved. try to ignore that crap here. - switch (m_switchDir) { - case kLeft: - m_switchTwoTapArmed = (m_xDelta > 0 && m_xDelta2 > 0); - break; - - case kRight: - m_switchTwoTapArmed = (m_xDelta < 0 && m_xDelta2 < 0); - break; - - case kTop: - m_switchTwoTapArmed = (m_yDelta > 0 && m_yDelta2 > 0); - break; - - case kBottom: - m_switchTwoTapArmed = (m_yDelta < 0 && m_yDelta2 < 0); - break; - - default: - break; - } - } - } - } -} - -void -CServer::stopSwitchTwoTap() -{ - m_switchTwoTapEngaged = false; - m_switchTwoTapArmed = false; -} - -bool -CServer::isSwitchTwoTapStarted() const -{ - return m_switchTwoTapEngaged; -} - -bool -CServer::shouldSwitchTwoTap() const -{ - // this is the second tap if two-tap is armed and this tap - // came fast enough - return (m_switchTwoTapArmed && - m_switchTwoTapTimer.getTime() <= m_switchTwoTapDelay); -} - -void -CServer::startSwitchWait(SInt32 x, SInt32 y) -{ - stopSwitchWait(); - m_switchWaitX = x; - m_switchWaitY = y; - m_switchWaitTimer = EVENTQUEUE->newOneShotTimer(m_switchWaitDelay, this); - LOG((CLOG_DEBUG1 "waiting to switch")); -} - -void -CServer::stopSwitchWait() -{ - if (m_switchWaitTimer != NULL) { - EVENTQUEUE->deleteTimer(m_switchWaitTimer); - m_switchWaitTimer = NULL; - } -} - -bool -CServer::isSwitchWaitStarted() const -{ - return (m_switchWaitTimer != NULL); -} - -UInt32 -CServer::getCorner(CBaseClientProxy* client, - SInt32 x, SInt32 y, SInt32 size) const -{ - assert(client != NULL); - - // get client screen shape - SInt32 ax, ay, aw, ah; - client->getShape(ax, ay, aw, ah); - - // check for x,y on the left or right - SInt32 xSide; - if (x <= ax) { - xSide = -1; - } - else if (x >= ax + aw - 1) { - xSide = 1; - } - else { - xSide = 0; - } - - // check for x,y on the top or bottom - SInt32 ySide; - if (y <= ay) { - ySide = -1; - } - else if (y >= ay + ah - 1) { - ySide = 1; - } - else { - ySide = 0; - } - - // if against the left or right then check if y is within size - if (xSide != 0) { - if (y < ay + size) { - return (xSide < 0) ? kTopLeftMask : kTopRightMask; - } - else if (y >= ay + ah - size) { - return (xSide < 0) ? kBottomLeftMask : kBottomRightMask; - } - } - - // if against the left or right then check if y is within size - if (ySide != 0) { - if (x < ax + size) { - return (ySide < 0) ? kTopLeftMask : kBottomLeftMask; - } - else if (x >= ax + aw - size) { - return (ySide < 0) ? kTopRightMask : kBottomRightMask; - } - } - - return kNoCornerMask; -} - -void -CServer::stopRelativeMoves() -{ - if (m_relativeMoves && m_active != m_primaryClient) { - // warp to the center of the active client so we know where we are - SInt32 ax, ay, aw, ah; - m_active->getShape(ax, ay, aw, ah); - m_x = ax + (aw >> 1); - m_y = ay + (ah >> 1); - m_xDelta = 0; - m_yDelta = 0; - m_xDelta2 = 0; - m_yDelta2 = 0; - LOG((CLOG_DEBUG2 "synchronize move on %s by %d,%d", getName(m_active).c_str(), m_x, m_y)); - m_active->mouseMove(m_x, m_y); - } -} - -void -CServer::sendOptions(CBaseClientProxy* client) const -{ - COptionsList optionsList; - - // look up options for client - const CConfig::CScreenOptions* options = - m_config.getOptions(getName(client)); - if (options != NULL) { - // convert options to a more convenient form for sending - optionsList.reserve(2 * options->size()); - for (CConfig::CScreenOptions::const_iterator index = options->begin(); - index != options->end(); ++index) { - optionsList.push_back(index->first); - optionsList.push_back(static_cast(index->second)); - } - } - - // look up global options - options = m_config.getOptions(""); - if (options != NULL) { - // convert options to a more convenient form for sending - optionsList.reserve(optionsList.size() + 2 * options->size()); - for (CConfig::CScreenOptions::const_iterator index = options->begin(); - index != options->end(); ++index) { - optionsList.push_back(index->first); - optionsList.push_back(static_cast(index->second)); - } - } - - // send the options - client->resetOptions(); - client->setOptions(optionsList); -} - -void -CServer::processOptions() -{ - const CConfig::CScreenOptions* options = m_config.getOptions(""); - if (options == NULL) { - return; - } - - bool newRelativeMoves = m_relativeMoves; - for (CConfig::CScreenOptions::const_iterator index = options->begin(); - index != options->end(); ++index) { - const OptionID id = index->first; - const OptionValue value = index->second; - if (id == kOptionScreenSwitchDelay) { - m_switchWaitDelay = 1.0e-3 * static_cast(value); - if (m_switchWaitDelay < 0.0) { - m_switchWaitDelay = 0.0; - } - stopSwitchWait(); - } - else if (id == kOptionScreenSwitchTwoTap) { - m_switchTwoTapDelay = 1.0e-3 * static_cast(value); - if (m_switchTwoTapDelay < 0.0) { - m_switchTwoTapDelay = 0.0; - } - stopSwitchTwoTap(); - } - else if (id == kOptionRelativeMouseMoves) { - newRelativeMoves = (value != 0); - } - } - - if (m_relativeMoves && !newRelativeMoves) { - stopRelativeMoves(); - } - m_relativeMoves = newRelativeMoves; -} - -void -CServer::handleShapeChanged(const CEvent&, void* vclient) -{ - // ignore events from unknown clients - CBaseClientProxy* client = reinterpret_cast(vclient); - if (m_clientSet.count(client) == 0) { - return; - } - - LOG((CLOG_INFO "screen \"%s\" shape changed", getName(client).c_str())); - - // update jump coordinate - SInt32 x, y; - client->getCursorPos(x, y); - client->setJumpCursorPos(x, y); - - // update the mouse coordinates - if (client == m_active) { - m_x = x; - m_y = y; - } - - // handle resolution change to primary screen - if (client == m_primaryClient) { - if (client == m_active) { - onMouseMovePrimary(m_x, m_y); - } - else { - onMouseMoveSecondary(0, 0); - } - } -} - -void -CServer::handleClipboardGrabbed(const CEvent& event, void* vclient) -{ - // ignore events from unknown clients - CBaseClientProxy* grabber = reinterpret_cast(vclient); - if (m_clientSet.count(grabber) == 0) { - return; - } - const IScreen::CClipboardInfo* info = - reinterpret_cast(event.getData()); - - // ignore grab if sequence number is old. always allow primary - // screen to grab. - CClipboardInfo& clipboard = m_clipboards[info->m_id]; - if (grabber != m_primaryClient && - info->m_sequenceNumber < clipboard.m_clipboardSeqNum) { - LOG((CLOG_INFO "ignored screen \"%s\" grab of clipboard %d", getName(grabber).c_str(), info->m_id)); - return; - } - - // mark screen as owning clipboard - LOG((CLOG_INFO "screen \"%s\" grabbed clipboard %d from \"%s\"", getName(grabber).c_str(), info->m_id, clipboard.m_clipboardOwner.c_str())); - clipboard.m_clipboardOwner = getName(grabber); - clipboard.m_clipboardSeqNum = info->m_sequenceNumber; - - // clear the clipboard data (since it's not known at this point) - if (clipboard.m_clipboard.open(0)) { - clipboard.m_clipboard.empty(); - clipboard.m_clipboard.close(); - } - clipboard.m_clipboardData = clipboard.m_clipboard.marshall(); - - // tell all other screens to take ownership of clipboard. tell the - // grabber that it's clipboard isn't dirty. - for (CClientList::iterator index = m_clients.begin(); - index != m_clients.end(); ++index) { - CBaseClientProxy* client = index->second; - if (client == grabber) { - client->setClipboardDirty(info->m_id, false); - } - else { - client->grabClipboard(info->m_id); - } - } -} - -void -CServer::handleClipboardChanged(const CEvent& event, void* vclient) -{ - // ignore events from unknown clients - CBaseClientProxy* sender = reinterpret_cast(vclient); - if (m_clientSet.count(sender) == 0) { - return; - } - const IScreen::CClipboardInfo* info = - reinterpret_cast(event.getData()); - onClipboardChanged(sender, info->m_id, info->m_sequenceNumber); -} - -void -CServer::handleKeyDownEvent(const CEvent& event, void*) -{ - IPlatformScreen::CKeyInfo* info = - reinterpret_cast(event.getData()); - onKeyDown(info->m_key, info->m_mask, info->m_button, info->m_screens); -} - -void -CServer::handleKeyUpEvent(const CEvent& event, void*) -{ - IPlatformScreen::CKeyInfo* info = - reinterpret_cast(event.getData()); - onKeyUp(info->m_key, info->m_mask, info->m_button, info->m_screens); -} - -void -CServer::handleKeyRepeatEvent(const CEvent& event, void*) -{ - IPlatformScreen::CKeyInfo* info = - reinterpret_cast(event.getData()); - onKeyRepeat(info->m_key, info->m_mask, info->m_count, info->m_button); -} - -void -CServer::handleButtonDownEvent(const CEvent& event, void*) -{ - IPlatformScreen::CButtonInfo* info = - reinterpret_cast(event.getData()); - onMouseDown(info->m_button); -} - -void -CServer::handleButtonUpEvent(const CEvent& event, void*) -{ - IPlatformScreen::CButtonInfo* info = - reinterpret_cast(event.getData()); - onMouseUp(info->m_button); -} - -void -CServer::handleMotionPrimaryEvent(const CEvent& event, void*) -{ - IPlatformScreen::CMotionInfo* info = - reinterpret_cast(event.getData()); - onMouseMovePrimary(info->m_x, info->m_y); -} - -void -CServer::handleMotionSecondaryEvent(const CEvent& event, void*) -{ - IPlatformScreen::CMotionInfo* info = - reinterpret_cast(event.getData()); - onMouseMoveSecondary(info->m_x, info->m_y); -} - -void -CServer::handleWheelEvent(const CEvent& event, void*) -{ - IPlatformScreen::CWheelInfo* info = - reinterpret_cast(event.getData()); - onMouseWheel(info->m_xDelta, info->m_yDelta); -} - -void -CServer::handleScreensaverActivatedEvent(const CEvent&, void*) -{ - onScreensaver(true); -} - -void -CServer::handleScreensaverDeactivatedEvent(const CEvent&, void*) -{ - onScreensaver(false); -} - -void -CServer::handleSwitchWaitTimeout(const CEvent&, void*) -{ - // ignore if mouse is locked to screen - if (isLockedToScreen()) { - LOG((CLOG_DEBUG1 "locked to screen")); - stopSwitch(); - return; - } - - // switch screen - switchScreen(m_switchScreen, m_switchWaitX, m_switchWaitY, false); -} - -void -CServer::handleClientDisconnected(const CEvent&, void* vclient) -{ - // client has disconnected. it might be an old client or an - // active client. we don't care so just handle it both ways. - CBaseClientProxy* client = reinterpret_cast(vclient); - removeActiveClient(client); - removeOldClient(client); - delete client; -} - -void -CServer::handleClientCloseTimeout(const CEvent&, void* vclient) -{ - // client took too long to disconnect. just dump it. - CBaseClientProxy* client = reinterpret_cast(vclient); - LOG((CLOG_NOTE "forced disconnection of client \"%s\"", getName(client).c_str())); - removeOldClient(client); - delete client; -} - -void -CServer::handleSwitchToScreenEvent(const CEvent& event, void*) -{ - CSwitchToScreenInfo* info = - reinterpret_cast(event.getData()); - - CClientList::const_iterator index = m_clients.find(info->m_screen); - if (index == m_clients.end()) { - LOG((CLOG_DEBUG1 "screen \"%s\" not active", info->m_screen)); - } - else { - jumpToScreen(index->second); - } -} - -void -CServer::handleSwitchInDirectionEvent(const CEvent& event, void*) -{ - CSwitchInDirectionInfo* info = - reinterpret_cast(event.getData()); - - // jump to screen in chosen direction from center of this screen - SInt32 x = m_x, y = m_y; - CBaseClientProxy* newScreen = - getNeighbor(m_active, info->m_direction, x, y); - if (newScreen == NULL) { - LOG((CLOG_DEBUG1 "no neighbor %s", CConfig::dirName(info->m_direction))); - } - else { - jumpToScreen(newScreen); - } -} - -void -CServer::handleKeyboardBroadcastEvent(const CEvent& event, void*) -{ - CKeyboardBroadcastInfo* info = (CKeyboardBroadcastInfo*)event.getData(); - - // choose new state - bool newState; - switch (info->m_state) { - case CKeyboardBroadcastInfo::kOff: - newState = false; - break; - - default: - case CKeyboardBroadcastInfo::kOn: - newState = true; - break; - - case CKeyboardBroadcastInfo::kToggle: - newState = !m_keyboardBroadcasting; - break; - } - - // enter new state - if (newState != m_keyboardBroadcasting || - info->m_screens != m_keyboardBroadcastingScreens) { - m_keyboardBroadcasting = newState; - m_keyboardBroadcastingScreens = info->m_screens; - LOG((CLOG_DEBUG "keyboard broadcasting %s: %s", m_keyboardBroadcasting ? "on" : "off", m_keyboardBroadcastingScreens.c_str())); - } -} - -void -CServer::handleLockCursorToScreenEvent(const CEvent& event, void*) -{ - CLockCursorToScreenInfo* info = (CLockCursorToScreenInfo*)event.getData(); - - // choose new state - bool newState; - switch (info->m_state) { - case CLockCursorToScreenInfo::kOff: - newState = false; - break; - - default: - case CLockCursorToScreenInfo::kOn: - newState = true; - break; - - case CLockCursorToScreenInfo::kToggle: - newState = !m_lockedToScreen; - break; - } - - // enter new state - if (newState != m_lockedToScreen) { - m_lockedToScreen = newState; - LOG((CLOG_DEBUG "cursor %s current screen", m_lockedToScreen ? "locked to" : "unlocked from")); - - m_primaryClient->reconfigure(getActivePrimarySides()); - if (!isLockedToScreenServer()) { - stopRelativeMoves(); - } - } -} - -void -CServer::handleFakeInputBeginEvent(const CEvent&, void*) -{ - m_primaryClient->fakeInputBegin(); -} - -void -CServer::handleFakeInputEndEvent(const CEvent&, void*) -{ - m_primaryClient->fakeInputEnd(); -} - -void -CServer::onClipboardChanged(CBaseClientProxy* sender, - ClipboardID id, UInt32 seqNum) -{ - CClipboardInfo& clipboard = m_clipboards[id]; - - // ignore update if sequence number is old - if (seqNum < clipboard.m_clipboardSeqNum) { - LOG((CLOG_INFO "ignored screen \"%s\" update of clipboard %d (missequenced)", getName(sender).c_str(), id)); - return; - } - - // should be the expected client - assert(sender == m_clients.find(clipboard.m_clipboardOwner)->second); - - // get data - sender->getClipboard(id, &clipboard.m_clipboard); - - // ignore if data hasn't changed - CString data = clipboard.m_clipboard.marshall(); - if (data == clipboard.m_clipboardData) { - LOG((CLOG_DEBUG "ignored screen \"%s\" update of clipboard %d (unchanged)", clipboard.m_clipboardOwner.c_str(), id)); - return; - } - - // got new data - LOG((CLOG_INFO "screen \"%s\" updated clipboard %d", clipboard.m_clipboardOwner.c_str(), id)); - clipboard.m_clipboardData = data; - - // tell all clients except the sender that the clipboard is dirty - for (CClientList::const_iterator index = m_clients.begin(); - index != m_clients.end(); ++index) { - CBaseClientProxy* client = index->second; - client->setClipboardDirty(id, client != sender); - } - - // send the new clipboard to the active screen - m_active->setClipboard(id, &clipboard.m_clipboard); -} - -void -CServer::onScreensaver(bool activated) -{ - LOG((CLOG_DEBUG "onScreenSaver %s", activated ? "activated" : "deactivated")); - - if (activated) { - // save current screen and position - m_activeSaver = m_active; - m_xSaver = m_x; - m_ySaver = m_y; - - // jump to primary screen - if (m_active != m_primaryClient) { - switchScreen(m_primaryClient, 0, 0, true); - } - } - else { - // jump back to previous screen and position. we must check - // that the position is still valid since the screen may have - // changed resolutions while the screen saver was running. - if (m_activeSaver != NULL && m_activeSaver != m_primaryClient) { - // check position - CBaseClientProxy* screen = m_activeSaver; - SInt32 x, y, w, h; - screen->getShape(x, y, w, h); - SInt32 zoneSize = getJumpZoneSize(screen); - if (m_xSaver < x + zoneSize) { - m_xSaver = x + zoneSize; - } - else if (m_xSaver >= x + w - zoneSize) { - m_xSaver = x + w - zoneSize - 1; - } - if (m_ySaver < y + zoneSize) { - m_ySaver = y + zoneSize; - } - else if (m_ySaver >= y + h - zoneSize) { - m_ySaver = y + h - zoneSize - 1; - } - - // jump - switchScreen(screen, m_xSaver, m_ySaver, false); - } - - // reset state - m_activeSaver = NULL; - } - - // send message to all clients - for (CClientList::const_iterator index = m_clients.begin(); - index != m_clients.end(); ++index) { - CBaseClientProxy* client = index->second; - client->screensaver(activated); - } -} - -void -CServer::onKeyDown(KeyID id, KeyModifierMask mask, KeyButton button, - const char* screens) -{ - LOG((CLOG_DEBUG1 "onKeyDown id=%d mask=0x%04x button=0x%04x", id, mask, button)); - assert(m_active != NULL); - - // relay - if (!m_keyboardBroadcasting || - (screens && IKeyState::CKeyInfo::isDefault(screens))) { - m_active->keyDown(id, mask, button); - } - else { - if (!screens && m_keyboardBroadcasting) { - screens = m_keyboardBroadcastingScreens.c_str(); - if (IKeyState::CKeyInfo::isDefault(screens)) { - screens = "*"; - } - } - for (CClientList::const_iterator index = m_clients.begin(); - index != m_clients.end(); ++index) { - if (IKeyState::CKeyInfo::contains(screens, index->first)) { - index->second->keyDown(id, mask, button); - } - } - } -} - -void -CServer::onKeyUp(KeyID id, KeyModifierMask mask, KeyButton button, - const char* screens) -{ - LOG((CLOG_DEBUG1 "onKeyUp id=%d mask=0x%04x button=0x%04x", id, mask, button)); - assert(m_active != NULL); - - // relay - if (!m_keyboardBroadcasting || - (screens && IKeyState::CKeyInfo::isDefault(screens))) { - m_active->keyUp(id, mask, button); - } - else { - if (!screens && m_keyboardBroadcasting) { - screens = m_keyboardBroadcastingScreens.c_str(); - if (IKeyState::CKeyInfo::isDefault(screens)) { - screens = "*"; - } - } - for (CClientList::const_iterator index = m_clients.begin(); - index != m_clients.end(); ++index) { - if (IKeyState::CKeyInfo::contains(screens, index->first)) { - index->second->keyUp(id, mask, button); - } - } - } -} - -void -CServer::onKeyRepeat(KeyID id, KeyModifierMask mask, - SInt32 count, KeyButton button) -{ - LOG((CLOG_DEBUG1 "onKeyRepeat id=%d mask=0x%04x count=%d button=0x%04x", id, mask, count, button)); - assert(m_active != NULL); - - // relay - m_active->keyRepeat(id, mask, count, button); -} - -void -CServer::onMouseDown(ButtonID id) -{ - LOG((CLOG_DEBUG1 "onMouseDown id=%d", id)); - assert(m_active != NULL); - - // relay - m_active->mouseDown(id); -} - -void -CServer::onMouseUp(ButtonID id) -{ - LOG((CLOG_DEBUG1 "onMouseUp id=%d", id)); - assert(m_active != NULL); - - // relay - m_active->mouseUp(id); -} - -bool -CServer::onMouseMovePrimary(SInt32 x, SInt32 y) -{ - LOG((CLOG_DEBUG2 "onMouseMovePrimary %d,%d", x, y)); - - // mouse move on primary (server's) screen - if (m_active != m_primaryClient) { - // stale event -- we're actually on a secondary screen - return false; - } - - // save last delta - m_xDelta2 = m_xDelta; - m_yDelta2 = m_yDelta; - - // save current delta - m_xDelta = x - m_x; - m_yDelta = y - m_y; - - // save position - m_x = x; - m_y = y; - - // get screen shape - SInt32 ax, ay, aw, ah; - m_active->getShape(ax, ay, aw, ah); - SInt32 zoneSize = getJumpZoneSize(m_active); - - // clamp position to screen - SInt32 xc = x, yc = y; - if (xc < ax + zoneSize) { - xc = ax; - } - else if (xc >= ax + aw - zoneSize) { - xc = ax + aw - 1; - } - if (yc < ay + zoneSize) { - yc = ay; - } - else if (yc >= ay + ah - zoneSize) { - yc = ay + ah - 1; - } - - // see if we should change screens - EDirection dir; - if (x < ax + zoneSize) { - x -= zoneSize; - dir = kLeft; - } - else if (x >= ax + aw - zoneSize) { - x += zoneSize; - dir = kRight; - } - else if (y < ay + zoneSize) { - y -= zoneSize; - dir = kTop; - } - else if (y >= ay + ah - zoneSize) { - y += zoneSize; - dir = kBottom; - } - else { - // still on local screen - noSwitch(x, y); - return false; - } - - // get jump destination - CBaseClientProxy* newScreen = mapToNeighbor(m_active, dir, x, y); - - // should we switch or not? - if (isSwitchOkay(newScreen, dir, x, y, xc, yc)) { - // switch screen - switchScreen(newScreen, x, y, false); - return true; - } - else { - return false; - } -} - -void -CServer::onMouseMoveSecondary(SInt32 dx, SInt32 dy) -{ - LOG((CLOG_DEBUG2 "onMouseMoveSecondary %+d,%+d", dx, dy)); - - // mouse move on secondary (client's) screen - assert(m_active != NULL); - if (m_active == m_primaryClient) { - // stale event -- we're actually on the primary screen - return; - } - - // if doing relative motion on secondary screens and we're locked - // to the screen (which activates relative moves) then send a - // relative mouse motion. when we're doing this we pretend as if - // the mouse isn't actually moving because we're expecting some - // program on the secondary screen to warp the mouse on us, so we - // have no idea where it really is. - if (m_relativeMoves && isLockedToScreenServer()) { - LOG((CLOG_DEBUG2 "relative move on %s by %d,%d", getName(m_active).c_str(), dx, dy)); - m_active->mouseRelativeMove(dx, dy); - return; - } - - // save old position - const SInt32 xOld = m_x; - const SInt32 yOld = m_y; - - // save last delta - m_xDelta2 = m_xDelta; - m_yDelta2 = m_yDelta; - - // save current delta - m_xDelta = dx; - m_yDelta = dy; - - // accumulate motion - m_x += dx; - m_y += dy; - - // get screen shape - SInt32 ax, ay, aw, ah; - m_active->getShape(ax, ay, aw, ah); - - // find direction of neighbor and get the neighbor - bool jump = true; - CBaseClientProxy* newScreen; - do { - // clamp position to screen - SInt32 xc = m_x, yc = m_y; - if (xc < ax) { - xc = ax; - } - else if (xc >= ax + aw) { - xc = ax + aw - 1; - } - if (yc < ay) { - yc = ay; - } - else if (yc >= ay + ah) { - yc = ay + ah - 1; - } - - EDirection dir; - if (m_x < ax) { - dir = kLeft; - } - else if (m_x > ax + aw - 1) { - dir = kRight; - } - else if (m_y < ay) { - dir = kTop; - } - else if (m_y > ay + ah - 1) { - dir = kBottom; - } - else { - // we haven't left the screen - newScreen = m_active; - jump = false; - - // if waiting and mouse is not on the border we're waiting - // on then stop waiting. also if it's not on the border - // then arm the double tap. - if (m_switchScreen != NULL) { - bool clearWait; - SInt32 zoneSize = m_primaryClient->getJumpZoneSize(); - switch (m_switchDir) { - case kLeft: - clearWait = (m_x >= ax + zoneSize); - break; - - case kRight: - clearWait = (m_x <= ax + aw - 1 - zoneSize); - break; - - case kTop: - clearWait = (m_y >= ay + zoneSize); - break; - - case kBottom: - clearWait = (m_y <= ay + ah - 1 + zoneSize); - break; - - default: - clearWait = false; - break; - } - if (clearWait) { - // still on local screen - noSwitch(m_x, m_y); - } - } - - // skip rest of block - break; - } - - // try to switch screen. get the neighbor. - newScreen = mapToNeighbor(m_active, dir, m_x, m_y); - - // see if we should switch - if (!isSwitchOkay(newScreen, dir, m_x, m_y, xc, yc)) { - newScreen = m_active; - jump = false; - } - } while (false); - - if (jump) { - // switch screens - switchScreen(newScreen, m_x, m_y, false); - } - else { - // same screen. clamp mouse to edge. - m_x = xOld + dx; - m_y = yOld + dy; - if (m_x < ax) { - m_x = ax; - LOG((CLOG_DEBUG2 "clamp to left of \"%s\"", getName(m_active).c_str())); - } - else if (m_x > ax + aw - 1) { - m_x = ax + aw - 1; - LOG((CLOG_DEBUG2 "clamp to right of \"%s\"", getName(m_active).c_str())); - } - if (m_y < ay) { - m_y = ay; - LOG((CLOG_DEBUG2 "clamp to top of \"%s\"", getName(m_active).c_str())); - } - else if (m_y > ay + ah - 1) { - m_y = ay + ah - 1; - LOG((CLOG_DEBUG2 "clamp to bottom of \"%s\"", getName(m_active).c_str())); - } - - // warp cursor if it moved. - if (m_x != xOld || m_y != yOld) { - LOG((CLOG_DEBUG2 "move on %s to %d,%d", getName(m_active).c_str(), m_x, m_y)); - m_active->mouseMove(m_x, m_y); - } - } -} - -void -CServer::onMouseWheel(SInt32 xDelta, SInt32 yDelta) -{ - LOG((CLOG_DEBUG1 "onMouseWheel %+d,%+d", xDelta, yDelta)); - assert(m_active != NULL); - - // relay - m_active->mouseWheel(xDelta, yDelta); -} - -bool -CServer::addClient(CBaseClientProxy* client) -{ - CString name = getName(client); - if (m_clients.count(name) != 0) { - return false; - } - - // add event handlers - EVENTQUEUE->adoptHandler(IScreen::getShapeChangedEvent(), - client->getEventTarget(), - new TMethodEventJob(this, - &CServer::handleShapeChanged, client)); - EVENTQUEUE->adoptHandler(IScreen::getClipboardGrabbedEvent(), - client->getEventTarget(), - new TMethodEventJob(this, - &CServer::handleClipboardGrabbed, client)); - EVENTQUEUE->adoptHandler(CClientProxy::getClipboardChangedEvent(), - client->getEventTarget(), - new TMethodEventJob(this, - &CServer::handleClipboardChanged, client)); - - // add to list - m_clientSet.insert(client); - m_clients.insert(std::make_pair(name, client)); - - // initialize client data - SInt32 x, y; - client->getCursorPos(x, y); - client->setJumpCursorPos(x, y); - - // tell primary client about the active sides - m_primaryClient->reconfigure(getActivePrimarySides()); - - return true; -} - -bool -CServer::removeClient(CBaseClientProxy* client) -{ - // return false if not in list - CClientSet::iterator i = m_clientSet.find(client); - if (i == m_clientSet.end()) { - return false; - } - - // remove event handlers - EVENTQUEUE->removeHandler(IScreen::getShapeChangedEvent(), - client->getEventTarget()); - EVENTQUEUE->removeHandler(IScreen::getClipboardGrabbedEvent(), - client->getEventTarget()); - EVENTQUEUE->removeHandler(CClientProxy::getClipboardChangedEvent(), - client->getEventTarget()); - - // remove from list - m_clients.erase(getName(client)); - m_clientSet.erase(i); - - return true; -} - -void -CServer::closeClient(CBaseClientProxy* client, const char* msg) -{ - assert(client != m_primaryClient); - assert(msg != NULL); - - // send message to client. this message should cause the client - // to disconnect. we add this client to the closed client list - // and install a timer to remove the client if it doesn't respond - // quickly enough. we also remove the client from the active - // client list since we're not going to listen to it anymore. - // note that this method also works on clients that are not in - // the m_clients list. adoptClient() may call us with such a - // client. - LOG((CLOG_NOTE "disconnecting client \"%s\"", getName(client).c_str())); - - // send message - // FIXME -- avoid type cast (kinda hard, though) - ((CClientProxy*)client)->close(msg); - - // install timer. wait timeout seconds for client to close. - double timeout = 5.0; - CEventQueueTimer* timer = EVENTQUEUE->newOneShotTimer(timeout, NULL); - EVENTQUEUE->adoptHandler(CEvent::kTimer, timer, - new TMethodEventJob(this, - &CServer::handleClientCloseTimeout, client)); - - // move client to closing list - removeClient(client); - m_oldClients.insert(std::make_pair(client, timer)); - - // if this client is the active screen then we have to - // jump off of it - forceLeaveClient(client); -} - -void -CServer::closeClients(const CConfig& config) -{ - // collect the clients that are connected but are being dropped - // from the configuration (or who's canonical name is changing). - typedef std::set CRemovedClients; - CRemovedClients removed; - for (CClientList::iterator index = m_clients.begin(); - index != m_clients.end(); ++index) { - if (!config.isCanonicalName(index->first)) { - removed.insert(index->second); - } - } - - // don't close the primary client - removed.erase(m_primaryClient); - - // now close them. we collect the list then close in two steps - // because closeClient() modifies the collection we iterate over. - for (CRemovedClients::iterator index = removed.begin(); - index != removed.end(); ++index) { - closeClient(*index, kMsgCClose); - } -} - -void -CServer::removeActiveClient(CBaseClientProxy* client) -{ - if (removeClient(client)) { - forceLeaveClient(client); - EVENTQUEUE->removeHandler(CClientProxy::getDisconnectedEvent(), client); - if (m_clients.size() == 1 && m_oldClients.empty()) { - EVENTQUEUE->addEvent(CEvent(getDisconnectedEvent(), this)); - } - } -} - -void -CServer::removeOldClient(CBaseClientProxy* client) -{ - COldClients::iterator i = m_oldClients.find(client); - if (i != m_oldClients.end()) { - EVENTQUEUE->removeHandler(CClientProxy::getDisconnectedEvent(), client); - EVENTQUEUE->removeHandler(CEvent::kTimer, i->second); - EVENTQUEUE->deleteTimer(i->second); - m_oldClients.erase(i); - if (m_clients.size() == 1 && m_oldClients.empty()) { - EVENTQUEUE->addEvent(CEvent(getDisconnectedEvent(), this)); - } - } -} - -void -CServer::forceLeaveClient(CBaseClientProxy* client) -{ - CBaseClientProxy* active = - (m_activeSaver != NULL) ? m_activeSaver : m_active; - if (active == client) { - // record new position (center of primary screen) - m_primaryClient->getCursorCenter(m_x, m_y); - - // stop waiting to switch to this client - if (active == m_switchScreen) { - stopSwitch(); - } - - // don't notify active screen since it has probably already - // disconnected. - LOG((CLOG_INFO "jump from \"%s\" to \"%s\" at %d,%d", getName(active).c_str(), getName(m_primaryClient).c_str(), m_x, m_y)); - - // cut over - m_active = m_primaryClient; - - // enter new screen (unless we already have because of the - // screen saver) - if (m_activeSaver == NULL) { - m_primaryClient->enter(m_x, m_y, m_seqNum, - m_primaryClient->getToggleMask(), false); - } - } - - // if this screen had the cursor when the screen saver activated - // then we can't switch back to it when the screen saver - // deactivates. - if (m_activeSaver == client) { - m_activeSaver = NULL; - } - - // tell primary client about the active sides - m_primaryClient->reconfigure(getActivePrimarySides()); -} - - -// -// CServer::CClipboardInfo -// - -CServer::CClipboardInfo::CClipboardInfo() : - m_clipboard(), - m_clipboardData(), - m_clipboardOwner(), - m_clipboardSeqNum(0) -{ - // do nothing -} - - -// -// CServer::CLockCursorToScreenInfo -// - -CServer::CLockCursorToScreenInfo* -CServer::CLockCursorToScreenInfo::alloc(State state) -{ - CLockCursorToScreenInfo* info = - (CLockCursorToScreenInfo*)malloc(sizeof(CLockCursorToScreenInfo)); - info->m_state = state; - return info; -} - - -// -// CServer::CSwitchToScreenInfo -// - -CServer::CSwitchToScreenInfo* -CServer::CSwitchToScreenInfo::alloc(const CString& screen) -{ - CSwitchToScreenInfo* info = - (CSwitchToScreenInfo*)malloc(sizeof(CSwitchToScreenInfo) + - screen.size()); - strcpy(info->m_screen, screen.c_str()); - return info; -} - - -// -// CServer::CSwitchInDirectionInfo -// - -CServer::CSwitchInDirectionInfo* -CServer::CSwitchInDirectionInfo::alloc(EDirection direction) -{ - CSwitchInDirectionInfo* info = - (CSwitchInDirectionInfo*)malloc(sizeof(CSwitchInDirectionInfo)); - info->m_direction = direction; - return info; -} - - -// -// CServer::CScreenConnectedInfo -// - -CServer::CScreenConnectedInfo* -CServer::CScreenConnectedInfo::alloc(const CString& screen) -{ - CScreenConnectedInfo* info = - (CScreenConnectedInfo*)malloc(sizeof(CScreenConnectedInfo) + - screen.size()); - strcpy(info->m_screen, screen.c_str()); - return info; -} - - -// -// CServer::CKeyboardBroadcastInfo -// - -CServer::CKeyboardBroadcastInfo* -CServer::CKeyboardBroadcastInfo::alloc(State state) -{ - CKeyboardBroadcastInfo* info = - (CKeyboardBroadcastInfo*)malloc(sizeof(CKeyboardBroadcastInfo)); - info->m_state = state; - info->m_screens[0] = '\0'; - return info; -} - -CServer::CKeyboardBroadcastInfo* -CServer::CKeyboardBroadcastInfo::alloc(State state, const CString& screens) -{ - CKeyboardBroadcastInfo* info = - (CKeyboardBroadcastInfo*)malloc(sizeof(CKeyboardBroadcastInfo) + - screens.size()); - info->m_state = state; - strcpy(info->m_screens, screens.c_str()); - return info; -} diff --git a/lib/server/CServer.h b/lib/server/CServer.h deleted file mode 100644 index 36cf5e83..00000000 --- a/lib/server/CServer.h +++ /dev/null @@ -1,464 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CSERVER_H -#define CSERVER_H - -#include "CConfig.h" -#include "CClipboard.h" -#include "ClipboardTypes.h" -#include "KeyTypes.h" -#include "MouseTypes.h" -#include "CEvent.h" -#include "CStopwatch.h" -#include "stdmap.h" -#include "stdset.h" -#include "stdvector.h" - -class CBaseClientProxy; -class CEventQueueTimer; -class CPrimaryClient; -class CInputFilter; - -//! Synergy server -/*! -This class implements the top-level server algorithms for synergy. -*/ -class CServer { -public: - //! Lock cursor to screen data - class CLockCursorToScreenInfo { - public: - enum State { kOff, kOn, kToggle }; - - static CLockCursorToScreenInfo* alloc(State state = kToggle); - - public: - State m_state; - }; - - //! Switch to screen data - class CSwitchToScreenInfo { - public: - static CSwitchToScreenInfo* alloc(const CString& screen); - - public: - // this is a C-string; this type is a variable size structure - char m_screen[1]; - }; - - //! Switch in direction data - class CSwitchInDirectionInfo { - public: - static CSwitchInDirectionInfo* alloc(EDirection direction); - - public: - EDirection m_direction; - }; - - //! Screen connected data - class CScreenConnectedInfo { - public: - static CScreenConnectedInfo* alloc(const CString& screen); - - public: - // this is a C-string; this type is a variable size structure - char m_screen[1]; - }; - - //! Keyboard broadcast data - class CKeyboardBroadcastInfo { - public: - enum State { kOff, kOn, kToggle }; - - static CKeyboardBroadcastInfo* alloc(State state = kToggle); - static CKeyboardBroadcastInfo* alloc(State state, - const CString& screens); - - public: - State m_state; - char m_screens[1]; - }; - - /*! - Start the server with the configuration \p config and the primary - client (local screen) \p primaryClient. The client retains - ownership of \p primaryClient. - */ - CServer(const CConfig& config, CPrimaryClient* primaryClient); - ~CServer(); - - //! @name manipulators - //@{ - - //! Set configuration - /*! - Change the server's configuration. Returns true iff the new - configuration was accepted (it must include the server's name). - This will disconnect any clients no longer in the configuration. - */ - bool setConfig(const CConfig&); - - //! Add a client - /*! - Adds \p client to the server. The client is adopted and will be - destroyed when the client disconnects or is disconnected. - */ - void adoptClient(CBaseClientProxy* client); - - //! Disconnect clients - /*! - Disconnect clients. This tells them to disconnect but does not wait - for them to actually do so. The server sends the disconnected event - when they're all disconnected (or immediately if none are connected). - The caller can also just destroy this object to force the disconnection. - */ - void disconnect(); - - //@} - //! @name accessors - //@{ - - //! Get number of connected clients - /*! - Returns the number of connected clients, including the server itself. - */ - UInt32 getNumClients() const; - - //! Get the list of connected clients - /*! - Set the \c list to the names of the currently connected clients. - */ - void getClients(std::vector& list) const; - - //! Get error event type - /*! - Returns the error event type. This is sent when the server fails - for some reason. - */ - static CEvent::Type getErrorEvent(); - - //! Get connected event type - /*! - Returns the connected event type. This is sent when a client screen - has connected. The event data is a \c CScreenConnectedInfo* that - indicates the connected screen. - */ - static CEvent::Type getConnectedEvent(); - - //! Get disconnected event type - /*! - Returns the disconnected event type. This is sent when all the - clients have disconnected. - */ - static CEvent::Type getDisconnectedEvent(); - - //! Get switch to screen event type - /*! - Returns the switch to screen event type. The server responds to this - by switching screens. The event data is a \c CSwitchToScreenInfo* - that indicates the target screen. - */ - static CEvent::Type getSwitchToScreenEvent(); - - //! Get switch in direction event type - /*! - Returns the switch in direction event type. The server responds to this - by switching screens. The event data is a \c CSwitchInDirectionInfo* - that indicates the target direction. - */ - static CEvent::Type getSwitchInDirectionEvent(); - - //! Get keyboard broadcast event type - /*! - Returns the keyboard broadcast event type. The server responds - to this by turning on keyboard broadcasting or turning it off. The - event data is a \c CKeyboardBroadcastInfo*. - */ - static CEvent::Type getKeyboardBroadcastEvent(); - - //! Get lock cursor event type - /*! - Returns the lock cursor event type. The server responds to this - by locking the cursor to the active screen or unlocking it. The - event data is a \c CLockCursorToScreenInfo*. - */ - static CEvent::Type getLockCursorToScreenEvent(); - - //@} - -private: - // get canonical name of client - CString getName(const CBaseClientProxy*) const; - - // get the sides of the primary screen that have neighbors - UInt32 getActivePrimarySides() const; - - // returns true iff mouse should be locked to the current screen - // according to this object only, ignoring what the primary client - // says. - bool isLockedToScreenServer() const; - - // returns true iff mouse should be locked to the current screen - // according to this object or the primary client. - bool isLockedToScreen() const; - - // returns the jump zone of the client - SInt32 getJumpZoneSize(CBaseClientProxy*) const; - - // change the active screen - void switchScreen(CBaseClientProxy*, - SInt32 x, SInt32 y, bool forScreenSaver); - - // jump to screen - void jumpToScreen(CBaseClientProxy*); - - // convert pixel position to fraction, using x or y depending on the - // direction. - float mapToFraction(CBaseClientProxy*, EDirection, - SInt32 x, SInt32 y) const; - - // convert fraction to pixel position, writing only x or y depending - // on the direction. - void mapToPixel(CBaseClientProxy*, EDirection, float f, - SInt32& x, SInt32& y) const; - - // returns true if the client has a neighbor anywhere along the edge - // indicated by the direction. - bool hasAnyNeighbor(CBaseClientProxy*, EDirection) const; - - // lookup neighboring screen, mapping the coordinate independent of - // the direction to the neighbor's coordinate space. - CBaseClientProxy* getNeighbor(CBaseClientProxy*, EDirection, - SInt32& x, SInt32& y) const; - - // lookup neighboring screen. given a position relative to the - // source screen, find the screen we should move onto and where. - // if the position is sufficiently far from the source then we - // cross multiple screens. if there is no suitable screen then - // return NULL and x,y are not modified. - CBaseClientProxy* mapToNeighbor(CBaseClientProxy*, EDirection, - SInt32& x, SInt32& y) const; - - // adjusts x and y or neither to avoid ending up in a jump zone - // after entering the client in the given direction. - void avoidJumpZone(CBaseClientProxy*, EDirection, - SInt32& x, SInt32& y) const; - - // test if a switch is permitted. this includes testing user - // options like switch delay and tracking any state required to - // implement them. returns true iff a switch is permitted. - bool isSwitchOkay(CBaseClientProxy* dst, EDirection, - SInt32 x, SInt32 y, SInt32 xActive, SInt32 yActive); - - // update switch state due to a mouse move at \p x, \p y that - // doesn't switch screens. - void noSwitch(SInt32 x, SInt32 y); - - // stop switch timers - void stopSwitch(); - - // start two tap switch timer - void startSwitchTwoTap(); - - // arm the two tap switch timer if \p x, \p y is outside the tap zone - void armSwitchTwoTap(SInt32 x, SInt32 y); - - // stop the two tap switch timer - void stopSwitchTwoTap(); - - // returns true iff the two tap switch timer is started - bool isSwitchTwoTapStarted() const; - - // returns true iff should switch because of two tap - bool shouldSwitchTwoTap() const; - - // start delay switch timer - void startSwitchWait(SInt32 x, SInt32 y); - - // stop delay switch timer - void stopSwitchWait(); - - // returns true iff the delay switch timer is started - bool isSwitchWaitStarted() const; - - // returns the corner (EScreenSwitchCornerMasks) where x,y is on the - // given client. corners have the given size. - UInt32 getCorner(CBaseClientProxy*, - SInt32 x, SInt32 y, SInt32 size) const; - - // stop relative mouse moves - void stopRelativeMoves(); - - // send screen options to \c client - void sendOptions(CBaseClientProxy* client) const; - - // process options from configuration - void processOptions(); - - // event handlers - void handleShapeChanged(const CEvent&, void*); - void handleClipboardGrabbed(const CEvent&, void*); - void handleClipboardChanged(const CEvent&, void*); - void handleKeyDownEvent(const CEvent&, void*); - void handleKeyUpEvent(const CEvent&, void*); - void handleKeyRepeatEvent(const CEvent&, void*); - void handleButtonDownEvent(const CEvent&, void*); - void handleButtonUpEvent(const CEvent&, void*); - void handleMotionPrimaryEvent(const CEvent&, void*); - void handleMotionSecondaryEvent(const CEvent&, void*); - void handleWheelEvent(const CEvent&, void*); - void handleScreensaverActivatedEvent(const CEvent&, void*); - void handleScreensaverDeactivatedEvent(const CEvent&, void*); - void handleSwitchWaitTimeout(const CEvent&, void*); - void handleClientDisconnected(const CEvent&, void*); - void handleClientCloseTimeout(const CEvent&, void*); - void handleSwitchToScreenEvent(const CEvent&, void*); - void handleSwitchInDirectionEvent(const CEvent&, void*); - void handleKeyboardBroadcastEvent(const CEvent&,void*); - void handleLockCursorToScreenEvent(const CEvent&, void*); - void handleFakeInputBeginEvent(const CEvent&, void*); - void handleFakeInputEndEvent(const CEvent&, void*); - - // event processing - void onClipboardChanged(CBaseClientProxy* sender, - ClipboardID id, UInt32 seqNum); - void onScreensaver(bool activated); - void onKeyDown(KeyID, KeyModifierMask, KeyButton, - const char* screens); - void onKeyUp(KeyID, KeyModifierMask, KeyButton, - const char* screens); - void onKeyRepeat(KeyID, KeyModifierMask, SInt32, KeyButton); - void onMouseDown(ButtonID); - void onMouseUp(ButtonID); - bool onMouseMovePrimary(SInt32 x, SInt32 y); - void onMouseMoveSecondary(SInt32 dx, SInt32 dy); - void onMouseWheel(SInt32 xDelta, SInt32 yDelta); - - // add client to list and attach event handlers for client - bool addClient(CBaseClientProxy*); - - // remove client from list and detach event handlers for client - bool removeClient(CBaseClientProxy*); - - // close a client - void closeClient(CBaseClientProxy*, const char* msg); - - // close clients not in \p config - void closeClients(const CConfig& config); - - // close all clients whether they've completed the handshake or not, - // except the primary client - void closeAllClients(); - - // remove clients from internal state - void removeActiveClient(CBaseClientProxy*); - void removeOldClient(CBaseClientProxy*); - - // force the cursor off of \p client - void forceLeaveClient(CBaseClientProxy* client); - -private: - class CClipboardInfo { - public: - CClipboardInfo(); - - public: - CClipboard m_clipboard; - CString m_clipboardData; - CString m_clipboardOwner; - UInt32 m_clipboardSeqNum; - }; - - // the primary screen client - CPrimaryClient* m_primaryClient; - - // all clients (including the primary client) indexed by name - typedef std::map CClientList; - typedef std::set CClientSet; - CClientList m_clients; - CClientSet m_clientSet; - - // all old connections that we're waiting to hangup - typedef std::map COldClients; - COldClients m_oldClients; - - // the client with focus - CBaseClientProxy* m_active; - - // the sequence number of enter messages - UInt32 m_seqNum; - - // current mouse position (in absolute screen coordinates) on - // whichever screen is active - SInt32 m_x, m_y; - - // last mouse deltas. this is needed to smooth out double tap - // on win32 which reports bogus mouse motion at the edge of - // the screen when using low level hooks, synthesizing motion - // in the opposite direction the mouse actually moved. - SInt32 m_xDelta, m_yDelta; - SInt32 m_xDelta2, m_yDelta2; - - // current configuration - CConfig m_config; - - // input filter (from m_config); - CInputFilter* m_inputFilter; - - // clipboard cache - CClipboardInfo m_clipboards[kClipboardEnd]; - - // state saved when screen saver activates - CBaseClientProxy* m_activeSaver; - SInt32 m_xSaver, m_ySaver; - - // common state for screen switch tests. all tests are always - // trying to reach the same screen in the same direction. - EDirection m_switchDir; - CBaseClientProxy* m_switchScreen; - - // state for delayed screen switching - double m_switchWaitDelay; - CEventQueueTimer* m_switchWaitTimer; - SInt32 m_switchWaitX, m_switchWaitY; - - // state for double-tap screen switching - double m_switchTwoTapDelay; - CStopwatch m_switchTwoTapTimer; - bool m_switchTwoTapEngaged; - bool m_switchTwoTapArmed; - SInt32 m_switchTwoTapZone; - - // relative mouse move option - bool m_relativeMoves; - - // flag whether or not we have broadcasting enabled and the screens to - // which we should send broadcasted keys. - bool m_keyboardBroadcasting; - CString m_keyboardBroadcastingScreens; - - // screen locking (former scroll lock) - bool m_lockedToScreen; - - static CEvent::Type s_errorEvent; - static CEvent::Type s_connectedEvent; - static CEvent::Type s_disconnectedEvent; - static CEvent::Type s_switchToScreen; - static CEvent::Type s_switchInDirection; - static CEvent::Type s_keyboardBroadcast; - static CEvent::Type s_lockCursorToScreen; -}; - -#endif diff --git a/lib/server/Makefile.am b/lib/server/Makefile.am deleted file mode 100644 index e03d9b7c..00000000 --- a/lib/server/Makefile.am +++ /dev/null @@ -1,60 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2002 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -## Process this file with automake to produce Makefile.in -NULL = - -EXTRA_DIST = \ - Makefile.win \ - $(NULL) - -MAINTAINERCLEANFILES = \ - Makefile.in \ - $(NULL) - -noinst_LIBRARIES = libserver.a -libserver_a_SOURCES = \ - CBaseClientProxy.cpp \ - CClientListener.cpp \ - CClientProxy.cpp \ - CClientProxy1_0.cpp \ - CClientProxy1_1.cpp \ - CClientProxy1_2.cpp \ - CClientProxy1_3.cpp \ - CClientProxyUnknown.cpp \ - CConfig.cpp \ - CInputFilter.cpp \ - CPrimaryClient.cpp \ - CServer.cpp \ - CBaseClientProxy.h \ - CClientListener.h \ - CClientProxy.h \ - CClientProxy1_0.h \ - CClientProxy1_1.h \ - CClientProxy1_2.h \ - CClientProxy1_3.h \ - CClientProxyUnknown.h \ - CConfig.h \ - CInputFilter.h \ - CPrimaryClient.h \ - CServer.h \ - $(NULL) -INCLUDES = \ - -I$(top_srcdir)/lib/common \ - -I$(top_srcdir)/lib/arch \ - -I$(top_srcdir)/lib/base \ - -I$(top_srcdir)/lib/mt \ - -I$(top_srcdir)/lib/io \ - -I$(top_srcdir)/lib/net \ - -I$(top_srcdir)/lib/synergy \ - -I$(top_srcdir)/lib/platform \ - $(NULL) diff --git a/lib/server/Makefile.win b/lib/server/Makefile.win deleted file mode 100644 index ed059e51..00000000 --- a/lib/server/Makefile.win +++ /dev/null @@ -1,83 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2007 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -LIB_SERVER_SRC = lib\server -LIB_SERVER_DST = $(BUILD_DST)\$(LIB_SERVER_SRC) -LIB_SERVER_LIB = "$(LIB_SERVER_DST)\server.lib" -LIB_SERVER_CPP = \ - "CBaseClientProxy.cpp" \ - "CClientListener.cpp" \ - "CClientProxy.cpp" \ - "CClientProxy1_0.cpp" \ - "CClientProxy1_1.cpp" \ - "CClientProxy1_2.cpp" \ - "CClientProxy1_3.cpp" \ - "CClientProxyUnknown.cpp" \ - "CConfig.cpp" \ - "CInputFilter.cpp" \ - "CPrimaryClient.cpp" \ - "CServer.cpp" \ - $(NULL) -LIB_SERVER_OBJ = \ - "$(LIB_SERVER_DST)\CBaseClientProxy.obj" \ - "$(LIB_SERVER_DST)\CClientListener.obj" \ - "$(LIB_SERVER_DST)\CClientProxy.obj" \ - "$(LIB_SERVER_DST)\CClientProxy1_0.obj" \ - "$(LIB_SERVER_DST)\CClientProxy1_1.obj" \ - "$(LIB_SERVER_DST)\CClientProxy1_2.obj" \ - "$(LIB_SERVER_DST)\CClientProxy1_3.obj" \ - "$(LIB_SERVER_DST)\CClientProxyUnknown.obj" \ - "$(LIB_SERVER_DST)\CConfig.obj" \ - "$(LIB_SERVER_DST)\CInputFilter.obj" \ - "$(LIB_SERVER_DST)\CPrimaryClient.obj" \ - "$(LIB_SERVER_DST)\CServer.obj" \ - $(NULL) -LIB_SERVER_INC = \ - /I"lib\common" \ - /I"lib\arch" \ - /I"lib\base" \ - /I"lib\mt" \ - /I"lib\io" \ - /I"lib\net" \ - /I"lib\synergy" \ - /I"lib\platform" \ - $(NULL) - -CPP_FILES = $(CPP_FILES) $(LIB_SERVER_CPP) -OBJ_FILES = $(OBJ_FILES) $(LIB_SERVER_OBJ) -LIB_FILES = $(LIB_FILES) $(LIB_SERVER_LIB) - -# Dependency rules -$(LIB_SERVER_OBJ): $(AUTODEP) -!if EXIST($(LIB_SERVER_DST)\deps.mak) -!include $(LIB_SERVER_DST)\deps.mak -!endif - -# Build rules. Use batch-mode rules if possible. -!if DEFINED(_NMAKE_VER) -{$(LIB_SERVER_SRC)\}.cpp{$(LIB_SERVER_DST)\}.obj:: -!else -{$(LIB_SERVER_SRC)\}.cpp{$(LIB_SERVER_DST)\}.obj: -!endif - @$(ECHO) Compile in $(LIB_SERVER_SRC) - -@$(MKDIR) $(LIB_SERVER_DST) 2>NUL: - $(cpp) $(cppdebug) $(cppflags) $(cppvarsmt) /showIncludes \ - $(LIB_SERVER_INC) \ - /Fo$(LIB_SERVER_DST)\ \ - /Fd$(LIB_SERVER_LIB:.lib=.pdb) \ - $< | $(AUTODEP) $(LIB_SERVER_SRC) $(LIB_SERVER_DST) -$(LIB_SERVER_LIB): $(LIB_SERVER_OBJ) - @$(ECHO) Link $(@F) - $(implib) $(ildebug) $(ilflags) \ - /out:$@ \ - $** - $(AUTODEP) $(LIB_SERVER_SRC) $(LIB_SERVER_DST) $(**:.obj=.d) diff --git a/lib/synergy/CClipboard.cpp b/lib/synergy/CClipboard.cpp deleted file mode 100644 index d0388a01..00000000 --- a/lib/synergy/CClipboard.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CClipboard.h" - -// -// CClipboard -// - -CClipboard::CClipboard() : - m_open(false), - m_owner(false) -{ - open(0); - empty(); - close(); -} - -CClipboard::~CClipboard() -{ - // do nothing -} - -bool -CClipboard::empty() -{ - assert(m_open); - - // clear all data - for (SInt32 index = 0; index < kNumFormats; ++index) { - m_data[index] = ""; - m_added[index] = false; - } - - // save time - m_timeOwned = m_time; - - // we're the owner now - m_owner = true; - - return true; -} - -void -CClipboard::add(EFormat format, const CString& data) -{ - assert(m_open); - assert(m_owner); - - m_data[format] = data; - m_added[format] = true; -} - -bool -CClipboard::open(Time time) const -{ - assert(!m_open); - - m_open = true; - m_time = time; - - return true; -} - -void -CClipboard::close() const -{ - assert(m_open); - - m_open = false; -} - -CClipboard::Time -CClipboard::getTime() const -{ - return m_timeOwned; -} - -bool -CClipboard::has(EFormat format) const -{ - assert(m_open); - return m_added[format]; -} - -CString -CClipboard::get(EFormat format) const -{ - assert(m_open); - return m_data[format]; -} - -void -CClipboard::unmarshall(const CString& data, Time time) -{ - IClipboard::unmarshall(this, data, time); -} - -CString -CClipboard::marshall() const -{ - return IClipboard::marshall(this); -} diff --git a/lib/synergy/CClipboard.h b/lib/synergy/CClipboard.h deleted file mode 100644 index f8d10aff..00000000 --- a/lib/synergy/CClipboard.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CCLIPBOARD_H -#define CCLIPBOARD_H - -#include "IClipboard.h" - -//! Memory buffer clipboard -/*! -This class implements a clipboard that stores data in memory. -*/ -class CClipboard : public IClipboard { -public: - CClipboard(); - virtual ~CClipboard(); - - //! @name manipulators - //@{ - - //! Unmarshall clipboard data - /*! - Extract marshalled clipboard data and store it in this clipboard. - Sets the clipboard time to \c time. - */ - void unmarshall(const CString& data, Time time); - - //@} - //! @name accessors - //@{ - - //! Marshall clipboard data - /*! - Merge this clipboard's data into a single buffer that can be later - unmarshalled to restore the clipboard and return the buffer. - */ - CString marshall() const; - - //@} - - // IClipboard overrides - virtual bool empty(); - virtual void add(EFormat, const CString& data); - virtual bool open(Time) const; - virtual void close() const; - virtual Time getTime() const; - virtual bool has(EFormat) const; - virtual CString get(EFormat) const; - -private: - mutable bool m_open; - mutable Time m_time; - bool m_owner; - Time m_timeOwned; - bool m_added[kNumFormats]; - CString m_data[kNumFormats]; -}; - -#endif diff --git a/lib/synergy/CKeyMap.cpp b/lib/synergy/CKeyMap.cpp deleted file mode 100644 index 4141c8b1..00000000 --- a/lib/synergy/CKeyMap.cpp +++ /dev/null @@ -1,1330 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2005 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CKeyMap.h" -#include "KeyTypes.h" -#include "CLog.h" -#include -#include -#include - -CKeyMap::CNameToKeyMap* CKeyMap::s_nameToKeyMap = NULL; -CKeyMap::CNameToModifierMap* CKeyMap::s_nameToModifierMap = NULL; -CKeyMap::CKeyToNameMap* CKeyMap::s_keyToNameMap = NULL; -CKeyMap::CModifierToNameMap* CKeyMap::s_modifierToNameMap = NULL; - -CKeyMap::CKeyMap() : - m_numGroups(0), - m_composeAcrossGroups(false) -{ - m_modifierKeyItem.m_id = kKeyNone; - m_modifierKeyItem.m_group = 0; - m_modifierKeyItem.m_button = 0; - m_modifierKeyItem.m_required = 0; - m_modifierKeyItem.m_sensitive = 0; - m_modifierKeyItem.m_generates = 0; - m_modifierKeyItem.m_dead = false; - m_modifierKeyItem.m_lock = false; - m_modifierKeyItem.m_client = 0; -} - -CKeyMap::~CKeyMap() -{ - // do nothing -} - -void -CKeyMap::swap(CKeyMap& x) -{ - m_keyIDMap.swap(x.m_keyIDMap); - m_modifierKeys.swap(x.m_modifierKeys); - m_halfDuplex.swap(x.m_halfDuplex); - m_halfDuplexMods.swap(x.m_halfDuplexMods); - SInt32 tmp1 = m_numGroups; - m_numGroups = x.m_numGroups; - x.m_numGroups = tmp1; - bool tmp2 = m_composeAcrossGroups; - m_composeAcrossGroups = x.m_composeAcrossGroups; - x.m_composeAcrossGroups = tmp2; -} - -void -CKeyMap::addKeyEntry(const KeyItem& item) -{ - // ignore kKeyNone - if (item.m_id == kKeyNone) { - return; - } - - // resize number of groups for key - SInt32 numGroups = item.m_group + 1; - if (getNumGroups() > numGroups) { - numGroups = getNumGroups(); - } - KeyGroupTable& groupTable = m_keyIDMap[item.m_id]; - if (groupTable.size() < static_cast(numGroups)) { - groupTable.resize(numGroups); - } - - // make a list from the item - KeyItemList items; - items.push_back(item); - - // set group and dead key flag on the item - KeyItem& newItem = items.back(); - newItem.m_dead = isDeadKey(item.m_id); - - // mask the required bits with the sensitive bits - newItem.m_required &= newItem.m_sensitive; - - // see if we already have this item; just return if so - KeyEntryList& entries = groupTable[item.m_group]; - for (size_t i = 0, n = entries.size(); i < n; ++i) { - if (entries[i].size() == 1 && newItem == entries[i][0]) { - return; - } - } - - // add item list - entries.push_back(items); - LOG((CLOG_DEBUG1 "add key: %04x %d %03x %04x (%04x %04x %04x)%s", newItem.m_id, newItem.m_group, newItem.m_button, newItem.m_client, newItem.m_required, newItem.m_sensitive, newItem.m_generates, newItem.m_dead ? " dead" : "")); -} - -void -CKeyMap::addKeyAliasEntry(KeyID targetID, SInt32 group, - KeyModifierMask targetRequired, - KeyModifierMask targetSensitive, - KeyID sourceID, - KeyModifierMask sourceRequired, - KeyModifierMask sourceSensitive) -{ - // if we can already generate the target as desired then we're done. - if (findCompatibleKey(targetID, group, targetRequired, - targetSensitive) != NULL) { - return; - } - - // find a compatible source, preferably in the same group - for (SInt32 gd = 0, n = getNumGroups(); gd < n; ++gd) { - SInt32 eg = getEffectiveGroup(group, gd); - const KeyItemList* sourceEntry = - findCompatibleKey(sourceID, eg, - sourceRequired, sourceSensitive); - if (sourceEntry != NULL && sourceEntry->size() == 1) { - CKeyMap::KeyItem targetItem = sourceEntry->back(); - targetItem.m_id = targetID; - targetItem.m_group = eg; - addKeyEntry(targetItem); - break; - } - } -} - -bool -CKeyMap::addKeyCombinationEntry(KeyID id, SInt32 group, - const KeyID* keys, UInt32 numKeys) -{ - // disallow kKeyNone - if (id == kKeyNone) { - return false; - } - - SInt32 numGroups = group + 1; - if (getNumGroups() > numGroups) { - numGroups = getNumGroups(); - } - KeyGroupTable& groupTable = m_keyIDMap[id]; - if (groupTable.size() < static_cast(numGroups)) { - groupTable.resize(numGroups); - } - if (!groupTable[group].empty()) { - // key is already in the table - return false; - } - - // convert to buttons - KeyItemList items; - for (UInt32 i = 0; i < numKeys; ++i) { - KeyIDMap::const_iterator gtIndex = m_keyIDMap.find(keys[i]); - if (gtIndex == m_keyIDMap.end()) { - return false; - } - const KeyGroupTable& groupTable = gtIndex->second; - - // if we allow group switching during composition then search all - // groups for keys, otherwise search just the given group. - SInt32 n = 1; - if (m_composeAcrossGroups) { - n = (SInt32)groupTable.size(); - } - - bool found = false; - for (SInt32 gd = 0; gd < n && !found; ++gd) { - SInt32 eg = (group + gd) % getNumGroups(); - const KeyEntryList& entries = groupTable[eg]; - for (size_t j = 0; j < entries.size(); ++j) { - if (entries[j].size() == 1) { - found = true; - items.push_back(entries[j][0]); - break; - } - } - } - if (!found) { - // required key is not in keyboard group - return false; - } - } - - // add key - groupTable[group].push_back(items); - return true; -} - -void -CKeyMap::allowGroupSwitchDuringCompose() -{ - m_composeAcrossGroups = true; -} - -void -CKeyMap::addHalfDuplexButton(KeyButton button) -{ - m_halfDuplex.insert(button); -} - -void -CKeyMap::clearHalfDuplexModifiers() -{ - m_halfDuplexMods.clear(); -} - -void -CKeyMap::addHalfDuplexModifier(KeyID key) -{ - m_halfDuplexMods.insert(key); -} - -void -CKeyMap::finish() -{ - m_numGroups = findNumGroups(); - - // make sure every key has the same number of groups - for (KeyIDMap::iterator i = m_keyIDMap.begin(); - i != m_keyIDMap.end(); ++i) { - i->second.resize(m_numGroups); - } - - // compute keys that generate each modifier - setModifierKeys(); -} - -void -CKeyMap::foreachKey(ForeachKeyCallback cb, void* userData) -{ - for (KeyIDMap::iterator i = m_keyIDMap.begin(); - i != m_keyIDMap.end(); ++i) { - KeyGroupTable& groupTable = i->second; - for (size_t group = 0; group < groupTable.size(); ++group) { - KeyEntryList& entryList = groupTable[group]; - for (size_t j = 0; j < entryList.size(); ++j) { - KeyItemList& itemList = entryList[j]; - for (size_t k = 0; k < itemList.size(); ++k) { - (*cb)(i->first, static_cast(group), - itemList[k], userData); - } - } - } - } -} - -const CKeyMap::KeyItem* -CKeyMap::mapKey(Keystrokes& keys, KeyID id, SInt32 group, - ModifierToKeys& activeModifiers, - KeyModifierMask& currentState, - KeyModifierMask desiredMask, - bool isAutoRepeat) const -{ - LOG((CLOG_DEBUG1 "mapKey %04x (%d) with mask %04x, start state: %04x", id, id, desiredMask, currentState)); - - // handle group change - if (id == kKeyNextGroup) { - keys.push_back(Keystroke(1, false, false)); - return NULL; - } - else if (id == kKeyPrevGroup) { - keys.push_back(Keystroke(-1, false, false)); - return NULL; - } - - const KeyItem* item; - switch (id) { - case kKeyShift_L: - case kKeyShift_R: - case kKeyControl_L: - case kKeyControl_R: - case kKeyAlt_L: - case kKeyAlt_R: - case kKeyMeta_L: - case kKeyMeta_R: - case kKeySuper_L: - case kKeySuper_R: - case kKeyAltGr: - case kKeyCapsLock: - case kKeyNumLock: - case kKeyScrollLock: - item = mapModifierKey(keys, id, group, activeModifiers, - currentState, desiredMask, isAutoRepeat); - break; - - case kKeySetModifiers: - if (!keysForModifierState(0, group, activeModifiers, currentState, - desiredMask, desiredMask, 0, keys)) { - LOG((CLOG_DEBUG1 "unable to set modifiers %04x", desiredMask)); - return NULL; - } - return &m_modifierKeyItem; - - case kKeyClearModifiers: - if (!keysForModifierState(0, group, activeModifiers, currentState, - currentState & ~desiredMask, - desiredMask, 0, keys)) { - LOG((CLOG_DEBUG1 "unable to clear modifiers %04x", desiredMask)); - return NULL; - } - return &m_modifierKeyItem; - - default: - if (isCommand(desiredMask)) { - item = mapCommandKey(keys, id, group, activeModifiers, - currentState, desiredMask, isAutoRepeat); - } - else { - item = mapCharacterKey(keys, id, group, activeModifiers, - currentState, desiredMask, isAutoRepeat); - } - break; - } - - if (item != NULL) { - LOG((CLOG_DEBUG1 "mapped to %03x, new state %04x", item->m_button, currentState)); - } - return item; -} - -SInt32 -CKeyMap::getNumGroups() const -{ - return m_numGroups; -} - -SInt32 -CKeyMap::getEffectiveGroup(SInt32 group, SInt32 offset) const -{ - return (group + offset + getNumGroups()) % getNumGroups(); -} - -const CKeyMap::KeyItemList* -CKeyMap::findCompatibleKey(KeyID id, SInt32 group, - KeyModifierMask required, KeyModifierMask sensitive) const -{ - assert(group >= 0 && group < getNumGroups()); - - KeyIDMap::const_iterator i = m_keyIDMap.find(id); - if (i == m_keyIDMap.end()) { - return NULL; - } - - const KeyEntryList& entries = i->second[group]; - for (size_t j = 0; j < entries.size(); ++j) { - if ((entries[j].back().m_sensitive & sensitive) == 0 || - (entries[j].back().m_required & sensitive) == - (required & sensitive)) { - return &entries[j]; - } - } - - return NULL; -} - -bool -CKeyMap::isHalfDuplex(KeyID key, KeyButton button) const -{ - return (m_halfDuplex.count(button) + m_halfDuplexMods.count(key) > 0); -} - -bool -CKeyMap::isCommand(KeyModifierMask mask) const -{ - return ((mask & getCommandModifiers()) != 0); -} - -KeyModifierMask -CKeyMap::getCommandModifiers() const -{ - // we currently treat ctrl, alt, meta and super as command modifiers. - // some platforms may have a more limited set (OS X only needs Alt) - // but this works anyway. - return KeyModifierControl | - KeyModifierAlt | - KeyModifierMeta | - KeyModifierSuper; -} - -void -CKeyMap::collectButtons(const ModifierToKeys& mods, ButtonToKeyMap& keys) -{ - keys.clear(); - for (ModifierToKeys::const_iterator i = mods.begin(); - i != mods.end(); ++i) { - keys.insert(std::make_pair(i->second.m_button, &i->second)); - } -} - -void -CKeyMap::initModifierKey(KeyItem& item) -{ - item.m_generates = 0; - item.m_lock = false; - switch (item.m_id) { - case kKeyShift_L: - case kKeyShift_R: - item.m_generates = KeyModifierShift; - break; - - case kKeyControl_L: - case kKeyControl_R: - item.m_generates = KeyModifierControl; - break; - - case kKeyAlt_L: - case kKeyAlt_R: - item.m_generates = KeyModifierAlt; - break; - - case kKeyMeta_L: - case kKeyMeta_R: - item.m_generates = KeyModifierMeta; - break; - - case kKeySuper_L: - case kKeySuper_R: - item.m_generates = KeyModifierSuper; - break; - - case kKeyAltGr: - item.m_generates = KeyModifierAltGr; - break; - - case kKeyCapsLock: - item.m_generates = KeyModifierCapsLock; - item.m_lock = true; - break; - - case kKeyNumLock: - item.m_generates = KeyModifierNumLock; - item.m_lock = true; - break; - - case kKeyScrollLock: - item.m_generates = KeyModifierScrollLock; - item.m_lock = true; - break; - - default: - // not a modifier - break; - } -} - -SInt32 -CKeyMap::findNumGroups() const -{ - size_t max = 0; - for (KeyIDMap::const_iterator i = m_keyIDMap.begin(); - i != m_keyIDMap.end(); ++i) { - if (i->second.size() > max) { - max = i->second.size(); - } - } - return static_cast(max); -} - -void -CKeyMap::setModifierKeys() -{ - m_modifierKeys.clear(); - m_modifierKeys.resize(kKeyModifierNumBits * getNumGroups()); - for (KeyIDMap::const_iterator i = m_keyIDMap.begin(); - i != m_keyIDMap.end(); ++i) { - const KeyGroupTable& groupTable = i->second; - for (size_t g = 0; g < groupTable.size(); ++g) { - const KeyEntryList& entries = groupTable[g]; - for (size_t j = 0; j < entries.size(); ++j) { - // skip multi-key sequences - if (entries[j].size() != 1) { - continue; - } - - // skip keys that don't generate a modifier - const KeyItem& item = entries[j].back(); - if (item.m_generates == 0) { - continue; - } - - // add key to each indicated modifier in this group - for (SInt32 b = 0; b < kKeyModifierNumBits; ++b) { - // skip if item doesn't generate bit b - if (((1u << b) & item.m_generates) != 0) { - SInt32 mIndex = g * kKeyModifierNumBits + b; - m_modifierKeys[mIndex].push_back(&item); - } - } - } - } - } -} - -const CKeyMap::KeyItem* -CKeyMap::mapCommandKey(Keystrokes& keys, KeyID id, SInt32 group, - ModifierToKeys& activeModifiers, - KeyModifierMask& currentState, - KeyModifierMask desiredMask, - bool isAutoRepeat) const -{ - static const KeyModifierMask s_overrideModifiers = 0xffffu; - - // find KeySym in table - KeyIDMap::const_iterator i = m_keyIDMap.find(id); - if (i == m_keyIDMap.end()) { - // unknown key - LOG((CLOG_DEBUG1 "key %04x is not on keyboard", id)); - return NULL; - } - const KeyGroupTable& keyGroupTable = i->second; - - // find the first key that generates this KeyID - const KeyItem* keyItem = NULL; - SInt32 numGroups = getNumGroups(); - for (SInt32 groupOffset = 0; groupOffset < numGroups; ++groupOffset) { - SInt32 effectiveGroup = getEffectiveGroup(group, groupOffset); - const KeyEntryList& entryList = keyGroupTable[effectiveGroup]; - for (size_t i = 0; i < entryList.size(); ++i) { - if (entryList[i].size() != 1) { - // ignore multikey entries - continue; - } - - // only match based on shift; we're after the right button - // not the right character. we'll use desiredMask as-is, - // overriding the key's required modifiers, when synthesizing - // this button. - const KeyItem& item = entryList[i].back(); - if ((item.m_required & KeyModifierShift & desiredMask) == - (item.m_sensitive & KeyModifierShift & desiredMask)) { - LOG((CLOG_DEBUG1 "found key in group %d", effectiveGroup)); - keyItem = &item; - break; - } - } - if (keyItem != NULL) { - break; - } - } - if (keyItem == NULL) { - // no mapping for this keysym - LOG((CLOG_DEBUG1 "no mapping for key %04x", id)); - return NULL; - } - - // make working copy of modifiers - ModifierToKeys newModifiers = activeModifiers; - KeyModifierMask newState = currentState; - SInt32 newGroup = group; - - // don't try to change CapsLock - desiredMask = (desiredMask & ~KeyModifierCapsLock) | - (currentState & KeyModifierCapsLock); - - // add the key - if (!keysForKeyItem(*keyItem, newGroup, newModifiers, - newState, desiredMask, - s_overrideModifiers, isAutoRepeat, keys)) { - LOG((CLOG_DEBUG1 "can't map key")); - keys.clear(); - return NULL; - } - - // add keystrokes to restore modifier keys - if (!keysToRestoreModifiers(*keyItem, group, newModifiers, newState, - activeModifiers, keys)) { - LOG((CLOG_DEBUG1 "failed to restore modifiers")); - keys.clear(); - return NULL; - } - - // add keystrokes to restore group - if (newGroup != group) { - keys.push_back(Keystroke(group, true, true)); - } - - // save new modifiers - activeModifiers = newModifiers; - currentState = newState; - - return keyItem; -} - -const CKeyMap::KeyItem* -CKeyMap::mapCharacterKey(Keystrokes& keys, KeyID id, SInt32 group, - ModifierToKeys& activeModifiers, - KeyModifierMask& currentState, - KeyModifierMask desiredMask, - bool isAutoRepeat) const -{ - // find KeySym in table - KeyIDMap::const_iterator i = m_keyIDMap.find(id); - if (i == m_keyIDMap.end()) { - // unknown key - LOG((CLOG_DEBUG1 "key %04x is not on keyboard", id)); - return NULL; - } - const KeyGroupTable& keyGroupTable = i->second; - - // find best key in any group, starting with the active group - SInt32 keyIndex = -1; - SInt32 numGroups = getNumGroups(); - SInt32 groupOffset; - LOG((CLOG_DEBUG1 "find best: %04x %04x", currentState, desiredMask)); - for (groupOffset = 0; groupOffset < numGroups; ++groupOffset) { - SInt32 effectiveGroup = getEffectiveGroup(group, groupOffset); - keyIndex = findBestKey(keyGroupTable[effectiveGroup], - currentState, desiredMask); - if (keyIndex != -1) { - LOG((CLOG_DEBUG1 "found key in group %d", effectiveGroup)); - break; - } - } - if (keyIndex == -1) { - // no mapping for this keysym - LOG((CLOG_DEBUG1 "no mapping for key %04x", id)); - return NULL; - } - - // get keys to press for key - SInt32 effectiveGroup = getEffectiveGroup(group, groupOffset); - const KeyItemList& itemList = keyGroupTable[effectiveGroup][keyIndex]; - if (itemList.empty()) { - return NULL; - } - const KeyItem& keyItem = itemList.back(); - - // make working copy of modifiers - ModifierToKeys newModifiers = activeModifiers; - KeyModifierMask newState = currentState; - SInt32 newGroup = group; - - // add each key - for (size_t j = 0; j < itemList.size(); ++j) { - if (!keysForKeyItem(itemList[j], newGroup, newModifiers, - newState, desiredMask, - 0, isAutoRepeat, keys)) { - LOG((CLOG_DEBUG1 "can't map key")); - keys.clear(); - return NULL; - } - } - - // add keystrokes to restore modifier keys - if (!keysToRestoreModifiers(keyItem, group, newModifiers, newState, - activeModifiers, keys)) { - LOG((CLOG_DEBUG1 "failed to restore modifiers")); - keys.clear(); - return NULL; - } - - // add keystrokes to restore group - if (newGroup != group) { - keys.push_back(Keystroke(group, true, true)); - } - - // save new modifiers - activeModifiers = newModifiers; - currentState = newState; - - return &keyItem; -} - -const CKeyMap::KeyItem* -CKeyMap::mapModifierKey(Keystrokes& keys, KeyID id, SInt32 group, - ModifierToKeys& activeModifiers, - KeyModifierMask& currentState, - KeyModifierMask desiredMask, - bool isAutoRepeat) const -{ - return mapCharacterKey(keys, id, group, activeModifiers, - currentState, desiredMask, isAutoRepeat); -} - -SInt32 -CKeyMap::findBestKey(const KeyEntryList& entryList, - KeyModifierMask /*currentState*/, - KeyModifierMask desiredState) const -{ - // check for an item that can accommodate the desiredState exactly - for (size_t i = 0; i < entryList.size(); ++i) { - const KeyItem& item = entryList[i].back(); - if ((item.m_required & desiredState) == - (item.m_sensitive & desiredState)) { - LOG((CLOG_DEBUG1 "best key index %d of %d (exact)", i, entryList.size())); - return i; - } - } - - // choose the item that requires the fewest modifier changes - SInt32 bestCount = 32; - SInt32 bestIndex = -1; - for (size_t i = 0; i < entryList.size(); ++i) { - const KeyItem& item = entryList[i].back(); - KeyModifierMask change = - ((item.m_required ^ desiredState) & item.m_sensitive); - SInt32 n = getNumModifiers(change); - if (n < bestCount) { - bestCount = n; - bestIndex = i; - } - } - if (bestIndex != -1) { - LOG((CLOG_DEBUG1 "best key index %d of %d (%d modifiers)", bestIndex, entryList.size(), bestCount)); - } - - return bestIndex; -} - - -const CKeyMap::KeyItem* -CKeyMap::keyForModifier(KeyButton button, SInt32 group, - SInt32 modifierBit) const -{ - assert(modifierBit >= 0 && modifierBit < kKeyModifierNumBits); - assert(group >= 0 && group < getNumGroups()); - - // find a key that generates the given modifier in the given group - // but doesn't use the given button, presumably because we're trying - // to generate a KeyID that's only bound the the given button. - // this is important when a shift button is modified by shift; we - // must use the other shift button to do the shifting. - const ModifierKeyItemList& items = - m_modifierKeys[group * kKeyModifierNumBits + modifierBit]; - for (ModifierKeyItemList::const_iterator i = items.begin(); - i != items.end(); ++i) { - if ((*i)->m_button != button) { - return (*i); - } - } - return NULL; -} - -bool -CKeyMap::keysForKeyItem(const KeyItem& keyItem, SInt32& group, - ModifierToKeys& activeModifiers, - KeyModifierMask& currentState, KeyModifierMask desiredState, - KeyModifierMask overrideModifiers, - bool isAutoRepeat, - Keystrokes& keystrokes) const -{ - static const KeyModifierMask s_notRequiredMask = - KeyModifierAltGr | KeyModifierNumLock | KeyModifierScrollLock; - - // add keystrokes to adjust the group - if (group != keyItem.m_group) { - group = keyItem.m_group; - keystrokes.push_back(Keystroke(group, true, false)); - } - - EKeystroke type; - if (keyItem.m_dead) { - // adjust modifiers for dead key - if (!keysForModifierState(keyItem.m_button, group, - activeModifiers, currentState, - keyItem.m_required, keyItem.m_sensitive, - 0, keystrokes)) { - LOG((CLOG_DEBUG1 "unable to match modifier state for dead key %d", keyItem.m_button)); - return false; - } - - // press and release the dead key - type = kKeystrokeClick; - } - else { - // if this a command key then we don't have to match some of the - // key's required modifiers. - KeyModifierMask sensitive = keyItem.m_sensitive & ~overrideModifiers; - - // XXX -- must handle pressing a modifier. in particular, if we want - // to synthesize a KeyID on level 1 of a KeyButton that has Shift_L - // mapped to level 0 then we must release that button if it's down - // (in order to satisfy a shift modifier) then press a different - // button (any other button) mapped to the shift modifier and then - // the Shift_L button. - // match key's required state - LOG((CLOG_DEBUG1 "state: %04x,%04x,%04x", currentState, keyItem.m_required, sensitive)); - if (!keysForModifierState(keyItem.m_button, group, - activeModifiers, currentState, - keyItem.m_required, sensitive, - 0, keystrokes)) { - LOG((CLOG_DEBUG1 "unable to match modifier state (%04x,%04x) for key %d", keyItem.m_required, keyItem.m_sensitive, keyItem.m_button)); - return false; - } - - // match desiredState as closely as possible. we must not - // change any modifiers in keyItem.m_sensitive. and if the key - // is a modifier, we don't want to change that modifier. - LOG((CLOG_DEBUG1 "desired state: %04x %04x,%04x,%04x", desiredState, currentState, keyItem.m_required, keyItem.m_sensitive)); - if (!keysForModifierState(keyItem.m_button, group, - activeModifiers, currentState, - desiredState, - ~(sensitive | keyItem.m_generates), - s_notRequiredMask, keystrokes)) { - LOG((CLOG_DEBUG1 "unable to match desired modifier state (%04x,%04x) for key %d", desiredState, ~keyItem.m_sensitive & 0xffffu, keyItem.m_button)); - return false; - } - - // repeat or press of key - type = isAutoRepeat ? kKeystrokeRepeat : kKeystrokePress; - } - addKeystrokes(type, keyItem, activeModifiers, currentState, keystrokes); - - return true; -} - -bool -CKeyMap::keysToRestoreModifiers(const KeyItem& keyItem, SInt32, - ModifierToKeys& activeModifiers, - KeyModifierMask& currentState, - const ModifierToKeys& desiredModifiers, - Keystrokes& keystrokes) const -{ - // XXX -- we're not considering modified modifiers here - - ModifierToKeys oldModifiers = activeModifiers; - - // get the pressed modifier buttons before and after - ButtonToKeyMap oldKeys, newKeys; - collectButtons(oldModifiers, oldKeys); - collectButtons(desiredModifiers, newKeys); - - // release unwanted keys - for (ModifierToKeys::const_iterator i = oldModifiers.begin(); - i != oldModifiers.end(); ++i) { - KeyButton button = i->second.m_button; - if (button != keyItem.m_button && newKeys.count(button) == 0) { - EKeystroke type = kKeystrokeRelease; - if (i->second.m_lock) { - type = kKeystrokeUnmodify; - } - addKeystrokes(type, i->second, - activeModifiers, currentState, keystrokes); - } - } - - // press wanted keys - for (ModifierToKeys::const_iterator i = desiredModifiers.begin(); - i != desiredModifiers.end(); ++i) { - KeyButton button = i->second.m_button; - if (button != keyItem.m_button && oldKeys.count(button) == 0) { - EKeystroke type = kKeystrokePress; - if (i->second.m_lock) { - type = kKeystrokeModify; - } - addKeystrokes(type, i->second, - activeModifiers, currentState, keystrokes); - } - } - - return true; -} - -bool -CKeyMap::keysForModifierState(KeyButton button, SInt32 group, - ModifierToKeys& activeModifiers, - KeyModifierMask& currentState, - KeyModifierMask requiredState, KeyModifierMask sensitiveMask, - KeyModifierMask notRequiredMask, - Keystrokes& keystrokes) const -{ - // compute which modifiers need changing - KeyModifierMask flipMask = ((currentState ^ requiredState) & sensitiveMask); - // if a modifier is not required then don't even try to match it. if - // we don't mask out notRequiredMask then we'll try to match those - // modifiers but succeed if we can't. however, this is known not - // to work if the key itself is a modifier (the numlock toggle can - // interfere) so we don't try to match at all. - flipMask &= ~notRequiredMask; - LOG((CLOG_DEBUG1 "flip: %04x (%04x vs %04x in %04x - %04x)", flipMask, currentState, requiredState, sensitiveMask & 0xffffu, notRequiredMask & 0xffffu)); - if (flipMask == 0) { - return true; - } - - // fix modifiers. this is complicated by the fact that a modifier may - // be sensitive to other modifiers! (who thought that up?) - // - // we'll assume that modifiers with higher bits are affected by modifiers - // with lower bits. there's not much basis for that assumption except - // that we're pretty sure shift isn't changed by other modifiers. - for (SInt32 bit = kKeyModifierNumBits; bit-- > 0; ) { - KeyModifierMask mask = (1u << bit); - if ((flipMask & mask) == 0) { - // modifier is already correct - continue; - } - - // do we want the modifier active or inactive? - bool active = ((requiredState & mask) != 0); - - // get the KeyItem for the modifier in the group - const KeyItem* keyItem = keyForModifier(button, group, bit); - if (keyItem == NULL) { - if ((mask & notRequiredMask) == 0) { - LOG((CLOG_DEBUG1 "no key for modifier %04x", mask)); - return false; - } - else { - continue; - } - } - - // if this modifier is sensitive to modifiers then adjust those - // modifiers. also check if our assumption was correct. note - // that we only need to adjust the modifiers on key down. - KeyModifierMask sensitive = keyItem->m_sensitive; - if ((sensitive & mask) != 0) { - // modifier is sensitive to itself. that makes no sense - // so ignore it. - LOG((CLOG_DEBUG1 "modifier %04x modified by itself", mask)); - sensitive &= ~mask; - } - if (sensitive != 0) { - if (sensitive > mask) { - // our assumption is incorrect - LOG((CLOG_DEBUG1 "modifier %04x modified by %04x", mask, sensitive)); - return false; - } - if (active && !keysForModifierState(button, group, - activeModifiers, currentState, - keyItem->m_required, sensitive, - notRequiredMask, keystrokes)) { - return false; - } - else if (!active) { - // release the modifier - // XXX -- this doesn't work! if Alt and Meta are mapped - // to one key and we want to release Meta we can't do - // that without also releasing Alt. - // need to think about support for modified modifiers. - } - } - - // current state should match required state - if ((currentState & sensitive) != (keyItem->m_required & sensitive)) { - LOG((CLOG_DEBUG1 "unable to match modifier state for modifier %04x (%04x vs %04x in %04x)", mask, currentState, keyItem->m_required, sensitive)); - return false; - } - - // add keystrokes - EKeystroke type = active ? kKeystrokeModify : kKeystrokeUnmodify; - addKeystrokes(type, *keyItem, activeModifiers, currentState, - keystrokes); - } - - return true; -} - -void -CKeyMap::addKeystrokes(EKeystroke type, const KeyItem& keyItem, - ModifierToKeys& activeModifiers, - KeyModifierMask& currentState, - Keystrokes& keystrokes) const -{ - KeyButton button = keyItem.m_button; - UInt32 data = keyItem.m_client; - switch (type) { - case kKeystrokePress: - keystrokes.push_back(Keystroke(button, true, false, data)); - if (keyItem.m_generates != 0) { - if (!keyItem.m_lock || (currentState & keyItem.m_generates) == 0) { - // add modifier key and activate modifier - activeModifiers.insert(std::make_pair( - keyItem.m_generates, keyItem)); - currentState |= keyItem.m_generates; - } - else { - // deactivate locking modifier - activeModifiers.erase(keyItem.m_generates); - currentState &= ~keyItem.m_generates; - } - } - break; - - case kKeystrokeRelease: - keystrokes.push_back(Keystroke(button, false, false, data)); - if (keyItem.m_generates != 0 && !keyItem.m_lock) { - // remove key from active modifiers - std::pair range = - activeModifiers.equal_range(keyItem.m_generates); - for (ModifierToKeys::iterator i = range.first; - i != range.second; ++i) { - if (i->second.m_button == button) { - activeModifiers.erase(i); - break; - } - } - - // if no more keys for this modifier then deactivate modifier - if (activeModifiers.count(keyItem.m_generates) == 0) { - currentState &= ~keyItem.m_generates; - } - } - break; - - case kKeystrokeRepeat: - keystrokes.push_back(Keystroke(button, false, true, data)); - keystrokes.push_back(Keystroke(button, true, true, data)); - // no modifier changes on key repeat - break; - - case kKeystrokeClick: - keystrokes.push_back(Keystroke(button, true, false, data)); - keystrokes.push_back(Keystroke(button, false, false, data)); - // no modifier changes on key click - break; - - case kKeystrokeModify: - case kKeystrokeUnmodify: - if (keyItem.m_lock) { - // we assume there's just one button for this modifier - if (m_halfDuplex.count(button) > 0) { - if (type == kKeystrokeModify) { - // turn half-duplex toggle on (press) - keystrokes.push_back(Keystroke(button, true, false, data)); - } - else { - // turn half-duplex toggle off (release) - keystrokes.push_back(Keystroke(button, false, false, data)); - } - } - else { - // toggle (click) - keystrokes.push_back(Keystroke(button, true, false, data)); - keystrokes.push_back(Keystroke(button, false, false, data)); - } - } - else if (type == kKeystrokeModify) { - // press modifier - keystrokes.push_back(Keystroke(button, true, false, data)); - } - else { - // release all the keys that generate the modifier that are - // currently down - std::pair range = - activeModifiers.equal_range(keyItem.m_generates); - for (ModifierToKeys::const_iterator i = range.first; - i != range.second; ++i) { - keystrokes.push_back(Keystroke(i->second.m_button, - false, false, i->second.m_client)); - } - } - - if (type == kKeystrokeModify) { - activeModifiers.insert(std::make_pair( - keyItem.m_generates, keyItem)); - currentState |= keyItem.m_generates; - } - else { - activeModifiers.erase(keyItem.m_generates); - currentState &= ~keyItem.m_generates; - } - break; - } -} - -SInt32 -CKeyMap::getNumModifiers(KeyModifierMask state) -{ - SInt32 n = 0; - for (; state != 0; state >>= 1) { - if ((state & 1) != 0) { - ++n; - } - } - return n; -} - -bool -CKeyMap::isDeadKey(KeyID key) -{ - return (key == kKeyCompose || (key >= 0x0300 && key <= 0x036f)); -} - -KeyID -CKeyMap::getDeadKey(KeyID key) -{ - if (isDeadKey(key)) { - // already dead - return key; - } - - switch (key) { - case '`': - return kKeyDeadGrave; - - case 0xb4u: - return kKeyDeadAcute; - - case '^': - case 0x2c6: - return kKeyDeadCircumflex; - - case '~': - case 0x2dcu: - return kKeyDeadTilde; - - case 0xafu: - return kKeyDeadMacron; - - case 0x2d8u: - return kKeyDeadBreve; - - case 0x2d9u: - return kKeyDeadAbovedot; - - case 0xa8u: - return kKeyDeadDiaeresis; - - case 0xb0u: - case 0x2dau: - return kKeyDeadAbovering; - - case '\"': - case 0x2ddu: - return kKeyDeadDoubleacute; - - case 0x2c7u: - return kKeyDeadCaron; - - case 0xb8u: - return kKeyDeadCedilla; - - case 0x2dbu: - return kKeyDeadOgonek; - - default: - // unknown - return kKeyNone; - } -} - -CString -CKeyMap::formatKey(KeyID key, KeyModifierMask mask) -{ - // initialize tables - initKeyNameMaps(); - - CString x; - for (SInt32 i = 0; i < kKeyModifierNumBits; ++i) { - KeyModifierMask mod = (1u << i); - if ((mask & mod) != 0 && s_modifierToNameMap->count(mod) > 0) { - x += s_modifierToNameMap->find(mod)->second; - x += "+"; - } - } - if (key != kKeyNone) { - if (s_keyToNameMap->count(key) > 0) { - x += s_keyToNameMap->find(key)->second; - } - // XXX -- we're assuming ASCII here - else if (key >= 33 && key < 127) { - x += (char)key; - } - else { - x += CStringUtil::print("\\u%04x", key); - } - } - else if (!x.empty()) { - // remove trailing '+' - x.erase(x.size() - 1); - } - return x; -} - -bool -CKeyMap::parseKey(const CString& x, KeyID& key) -{ - // initialize tables - initKeyNameMaps(); - - // parse the key - key = kKeyNone; - if (s_nameToKeyMap->count(x) > 0) { - key = s_nameToKeyMap->find(x)->second; - } - // XXX -- we're assuming ASCII encoding here - else if (x.size() == 1) { - if (!isgraph(x[0])) { - // unknown key - return false; - } - key = (KeyID)x[0]; - } - else if (x.size() == 6 && x[0] == '\\' && x[1] == 'u') { - // escaped unicode (\uXXXX where XXXX is a hex number) - char* end; - key = (KeyID)strtol(x.c_str() + 2, &end, 16); - if (*end != '\0') { - return false; - } - } - else if (!x.empty()) { - // unknown key - return false; - } - - return true; -} - -bool -CKeyMap::parseModifiers(CString& x, KeyModifierMask& mask) -{ - // initialize tables - initKeyNameMaps(); - - mask = 0; - CString::size_type tb = x.find_first_not_of(" \t", 0); - while (tb != CString::npos) { - // get next component - CString::size_type te = x.find_first_of(" \t+)", tb); - if (te == CString::npos) { - te = x.size(); - } - CString c = x.substr(tb, te - tb); - if (c.empty()) { - // missing component - return false; - } - - if (s_nameToModifierMap->count(c) > 0) { - KeyModifierMask mod = s_nameToModifierMap->find(c)->second; - if ((mask & mod) != 0) { - // modifier appears twice - return false; - } - mask |= mod; - } - else { - // unknown string - x.erase(0, tb); - CString::size_type tb = x.find_first_not_of(" \t"); - CString::size_type te = x.find_last_not_of(" \t"); - if (tb == CString::npos) { - x = ""; - } - else { - x = x.substr(tb, te - tb + 1); - } - return true; - } - - // check for '+' or end of string - tb = x.find_first_not_of(" \t", te); - if (tb != CString::npos) { - if (x[tb] != '+') { - // expected '+' - return false; - } - tb = x.find_first_not_of(" \t", tb + 1); - } - } - - // parsed the whole thing - x = ""; - return true; -} - -void -CKeyMap::initKeyNameMaps() -{ - // initialize tables - if (s_nameToKeyMap == NULL) { - s_nameToKeyMap = new CNameToKeyMap; - s_keyToNameMap = new CKeyToNameMap; - for (const KeyNameMapEntry* i = kKeyNameMap; i->m_name != NULL; ++i) { - (*s_nameToKeyMap)[i->m_name] = i->m_id; - (*s_keyToNameMap)[i->m_id] = i->m_name; - } - } - if (s_nameToModifierMap == NULL) { - s_nameToModifierMap = new CNameToModifierMap; - s_modifierToNameMap = new CModifierToNameMap; - for (const KeyModifierNameMapEntry* i = kModifierNameMap; - i->m_name != NULL; ++i) { - (*s_nameToModifierMap)[i->m_name] = i->m_mask; - (*s_modifierToNameMap)[i->m_mask] = i->m_name; - } - } -} - - -// -// CKeyMap::KeyItem -// - -bool -CKeyMap::KeyItem::operator==(const KeyItem& x) const -{ - return (m_id == x.m_id && - m_group == x.m_group && - m_button == x.m_button && - m_required == x.m_required && - m_sensitive == x.m_sensitive && - m_generates == x.m_generates && - m_dead == x.m_dead && - m_lock == x.m_lock && - m_client == x.m_client); -} - - -// -// CKeyMap::Keystroke -// - -CKeyMap::Keystroke::Keystroke(KeyButton button, - bool press, bool repeat, UInt32 data) : - m_type(kButton) -{ - m_data.m_button.m_button = button; - m_data.m_button.m_press = press; - m_data.m_button.m_repeat = repeat; - m_data.m_button.m_client = data; -} - -CKeyMap::Keystroke::Keystroke(SInt32 group, bool absolute, bool restore) : - m_type(kGroup) -{ - m_data.m_group.m_group = group; - m_data.m_group.m_absolute = absolute; - m_data.m_group.m_restore = restore; -} diff --git a/lib/synergy/CKeyMap.h b/lib/synergy/CKeyMap.h deleted file mode 100644 index 7f34113b..00000000 --- a/lib/synergy/CKeyMap.h +++ /dev/null @@ -1,491 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2005 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CKEYMAP_H -#define CKEYMAP_H - -#include "KeyTypes.h" -#include "CString.h" -#include "CStringUtil.h" -#include "stdmap.h" -#include "stdset.h" -#include "stdvector.h" - -//! Key map -/*! -This class provides a keyboard mapping. -*/ -class CKeyMap { -public: - CKeyMap(); - ~CKeyMap(); - - //! KeyID synthesis info - /*! - This structure contains the information necessary to synthesize a - keystroke that generates a KeyID (stored elsewhere). \c m_sensitive - lists the modifiers that the key is affected by and must therefore - be in the correct state, which is listed in \c m_required. If the - key is mapped to a modifier, that modifier is in \c m_generates and - is not in \c m_sensitive. - */ - struct KeyItem { - public: - KeyID m_id; //!< KeyID - SInt32 m_group; //!< Group for key - KeyButton m_button; //!< Button to generate KeyID - KeyModifierMask m_required; //!< Modifiers required for KeyID - KeyModifierMask m_sensitive; //!< Modifiers key is sensitive to - KeyModifierMask m_generates; //!< Modifiers key is mapped to - bool m_dead; //!< \c true if this is a dead KeyID - bool m_lock; //!< \c true if this locks a modifier - UInt32 m_client; //!< Client data - - public: - bool operator==(const KeyItem&) const; - }; - - //! The KeyButtons needed to synthesize a KeyID - /*! - An ordered list of \c KeyItems produces a particular KeyID. If - the KeyID can be synthesized directly then there is one entry in - the list. If dead keys are required then they're listed first. - A list is the minimal set of keystrokes necessary to synthesize - the KeyID, so it doesn't include no-ops. A list does not include - any modifier keys unless the KeyID is a modifier, in which case - it has exactly one KeyItem for the modifier itself. - */ - typedef std::vector KeyItemList; - - //! A keystroke - class Keystroke { - public: - enum EType { - kButton, //!< Synthesize button - kGroup //!< Set new group - }; - - Keystroke(KeyButton, bool press, bool repeat, UInt32 clientData); - Keystroke(SInt32 group, bool absolute, bool restore); - - public: - struct CButton { - public: - KeyButton m_button; //!< Button to synthesize - bool m_press; //!< \c true iff press - bool m_repeat; //!< \c true iff for an autorepeat - UInt32 m_client; //!< Client data - }; - struct CGroup { - public: - SInt32 m_group; //!< Group/offset to change to/by - bool m_absolute; //!< \c true iff change to, else by - bool m_restore; //!< \c true iff for restoring state - }; - union CData { - public: - CButton m_button; - CGroup m_group; - }; - - EType m_type; - CData m_data; - }; - - //! A sequence of keystrokes - typedef std::vector Keystrokes; - - //! A mapping of a modifier to keys for that modifier - typedef std::multimap ModifierToKeys; - - //! A set of buttons - typedef std::map ButtonToKeyMap; - - //! Callback type for \c foreachKey - typedef void (*ForeachKeyCallback)(KeyID, SInt32 group, - KeyItem&, void* userData); - - //! @name manipulators - //@{ - - //! Swap with another \c CKeyMap - void swap(CKeyMap&); - - //! Add a key entry - /*! - Adds \p item to the entries for the item's id and group. The - \c m_dead member is set automatically. - */ - void addKeyEntry(const KeyItem& item); - - //! Add an alias key entry - /*! - If \p targetID with the modifiers given by \p targetRequired and - \p targetSensitive is not available in group \p group then find an - entry for \p sourceID with modifiers given by \p sourceRequired and - \p sourceSensitive in any group with exactly one item and, if found, - add a new item just like it except using id \p targetID. This - effectively makes the \p sourceID an alias for \p targetID (i.e. we - can generate \p targetID using \p sourceID). - */ - void addKeyAliasEntry(KeyID targetID, SInt32 group, - KeyModifierMask targetRequired, - KeyModifierMask targetSensitive, - KeyID sourceID, - KeyModifierMask sourceRequired, - KeyModifierMask sourceSensitive); - - //! Add a key sequence entry - /*! - Adds the sequence of keys \p keys (\p numKeys elements long) to - synthesize key \p id in group \p group. This looks up in the - map each key in \p keys. If all are found then each key is - converted to the button for that key and the buttons are added - as the entry for \p id. If \p id is already in the map or at - least one key in \p keys is not in the map then nothing is added - and this returns \c false, otherwise it returns \c true. - */ - bool addKeyCombinationEntry(KeyID id, SInt32 group, - const KeyID* keys, UInt32 numKeys); - - //! Enable composition across groups - /*! - If called then the keyboard map will allow switching between groups - during key composition. Not all systems allow that. - */ - void allowGroupSwitchDuringCompose(); - - //! Add a half-duplex button - /*! - Records that button \p button is a half-duplex key. This is called - when translating the system's keyboard map. It's independent of the - half-duplex modifier calls. - */ - void addHalfDuplexButton(KeyButton button); - - //! Remove all half-duplex modifiers - /*! - Removes all half-duplex modifiers. This is called to set user - configurable half-duplex settings. - */ - void clearHalfDuplexModifiers(); - - //! Add a half-duplex modifier - /*! - Records that modifier key \p key is half-duplex. This is called to - set user configurable half-duplex settings. - */ - void addHalfDuplexModifier(KeyID key); - - //! Finish adding entries - /*! - Called after adding entries, this does some internal housekeeping. - */ - void finish(); - - //! Iterate over all added keys items - /*! - Calls \p cb for every key item. - */ - void foreachKey(ForeachKeyCallback cb, void* userData); - - //@} - //! @name accessors - //@{ - - //! Map key press/repeat to keystrokes. - /*! - Converts press/repeat of key \p id in group \p group with current - modifiers as given in \p currentState and the desired modifiers in - \p desiredMask into the keystrokes necessary to synthesize that key - event in \p keys. It returns the \c KeyItem of the key being - pressed/repeated, or NULL if the key cannot be mapped. - */ - const KeyItem* mapKey(Keystrokes& keys, KeyID id, SInt32 group, - ModifierToKeys& activeModifiers, - KeyModifierMask& currentState, - KeyModifierMask desiredMask, - bool isAutoRepeat) const; - - //! Get number of groups - /*! - Returns the number of keyboard groups (independent layouts) in the map. - */ - SInt32 getNumGroups() const; - - //! Compute a group number - /*! - Returns the number of the group \p offset groups after group \p group. - */ - SInt32 getEffectiveGroup(SInt32 group, SInt32 offset) const; - - //! Find key entry compatible with modifiers - /*! - Returns the \c KeyItemList for the first entry for \p id in group - \p group that is compatible with the given modifiers, or NULL - if there isn't one. A button list is compatible with a modifiers - if it is either insensitive to all modifiers in \p sensitive or - it requires the modifiers to be in the state indicated by \p required - for every modifier indicated by \p sensitive. - */ - const KeyItemList* findCompatibleKey(KeyID id, SInt32 group, - KeyModifierMask required, - KeyModifierMask sensitive) const; - - //! Test if modifier is half-duplex - /*! - Returns \c true iff modifier key \p key or button \p button is - half-duplex. - */ - bool isHalfDuplex(KeyID key, KeyButton button) const; - - //! Test if modifiers indicate a command - /*! - Returns \c true iff the modifiers in \p mask contain any command - modifiers. A command modifier is used for keyboard shortcuts and - hotkeys, Rather than trying to synthesize a character, a command - is trying to synthesize a particular set of buttons. So it's not - important to match the shift or AltGr state to achieve a character - but it is important to match the modifier state exactly. - */ - bool isCommand(KeyModifierMask mask) const; - - // Get the modifiers that indicate a command - /*! - Returns the modifiers that when combined with other keys indicate - a command (e.g. shortcut or hotkey). - */ - KeyModifierMask getCommandModifiers() const; - - //! Get buttons from modifier map - /*! - Put all the keys in \p modifiers into \p keys. - */ - static void collectButtons(const ModifierToKeys& modifiers, - ButtonToKeyMap& keys); - - //! Set modifier key state - /*! - Sets the modifier key state (\c m_generates and \c m_lock) in \p item - based on the \c m_id in \p item. - */ - static void initModifierKey(KeyItem& item); - - //! Test for a dead key - /*! - Returns \c true if \p key is a dead key. - */ - static bool isDeadKey(KeyID key); - - //! Get corresponding dead key - /*! - Returns the dead key corresponding to \p key if one exists, otherwise - return \c kKeyNone. This returns \p key if it's already a dead key. - */ - static KeyID getDeadKey(KeyID key); - - //! Get string for a key and modifier mask - /*! - Converts a key and modifier mask into a string representing the - combination. - */ - static CString formatKey(KeyID key, KeyModifierMask); - - //! Parse a string into a key - /*! - Converts a string into a key. Returns \c true on success and \c false - if the string cannot be parsed. - */ - static bool parseKey(const CString&, KeyID&); - - //! Parse a string into a modifier mask - /*! - Converts a string into a modifier mask. Returns \c true on success - and \c false if the string cannot be parsed. The modifiers plus any - remaining leading and trailing whitespace is stripped from the input - string. - */ - static bool parseModifiers(CString&, KeyModifierMask&); - - //@} - -private: - //! Ways to synthesize a key - enum EKeystroke { - kKeystrokePress, //!< Synthesize a press - kKeystrokeRelease, //!< Synthesize a release - kKeystrokeRepeat, //!< Synthesize an autorepeat - kKeystrokeClick, //!< Synthesize a press and release - kKeystrokeModify, //!< Synthesize pressing a modifier - kKeystrokeUnmodify //!< Synthesize releasing a modifier - }; - - // A list of ways to synthesize a KeyID - typedef std::vector KeyEntryList; - - // computes the number of groups - SInt32 findNumGroups() const; - - // computes the map of modifiers to the keys that generate the modifiers - void setModifierKeys(); - - // maps a command key. a command key is a keyboard shortcut and we're - // trying to synthesize a button press with an exact sets of modifiers, - // not trying to synthesize a character. so we just need to find the - // right button and synthesize the requested modifiers without regard - // to what character they would synthesize. we disallow multikey - // entries since they don't make sense as hotkeys. - const KeyItem* mapCommandKey(Keystrokes& keys, - KeyID id, SInt32 group, - ModifierToKeys& activeModifiers, - KeyModifierMask& currentState, - KeyModifierMask desiredMask, - bool isAutoRepeat) const; - - // maps a character key. a character key is trying to synthesize a - // particular KeyID and isn't entirely concerned with the modifiers - // used to do it. - const KeyItem* mapCharacterKey(Keystrokes& keys, - KeyID id, SInt32 group, - ModifierToKeys& activeModifiers, - KeyModifierMask& currentState, - KeyModifierMask desiredMask, - bool isAutoRepeat) const; - - // maps a modifier key - const KeyItem* mapModifierKey(Keystrokes& keys, - KeyID id, SInt32 group, - ModifierToKeys& activeModifiers, - KeyModifierMask& currentState, - KeyModifierMask desiredMask, - bool isAutoRepeat) const; - - // returns the index into \p entryList of the KeyItemList requiring - // the fewest modifier changes between \p currentState and - // \p desiredState. - SInt32 findBestKey(const KeyEntryList& entryList, - KeyModifierMask currentState, - KeyModifierMask desiredState) const; - - // gets the \c KeyItem used to synthesize the modifier who's bit is - // given by \p modifierBit in group \p group and does not synthesize - // the key \p button. - const KeyItem* keyForModifier(KeyButton button, SInt32 group, - SInt32 modifierBit) const; - - // fills \p keystrokes with the keys to synthesize the key in - // \p keyItem taking the modifiers into account. returns \c true - // iff successful and sets \p currentState to the - // resulting modifier state. - bool keysForKeyItem(const KeyItem& keyItem, - SInt32& group, - ModifierToKeys& activeModifiers, - KeyModifierMask& currentState, - KeyModifierMask desiredState, - KeyModifierMask overrideModifiers, - bool isAutoRepeat, - Keystrokes& keystrokes) const; - - // fills \p keystrokes with the keys to synthesize the modifiers - // in \p desiredModifiers from the active modifiers listed in - // \p activeModifiers not including the key in \p keyItem. - // returns \c true iff successful. - bool keysToRestoreModifiers(const KeyItem& keyItem, - SInt32 group, - ModifierToKeys& activeModifiers, - KeyModifierMask& currentState, - const ModifierToKeys& desiredModifiers, - Keystrokes& keystrokes) const; - - // fills \p keystrokes and \p undo with the keys to change the - // current modifier state in \p currentState to match the state in - // \p requiredState for each modifier indicated in \p sensitiveMask. - // returns \c true iff successful and sets \p currentState to the - // resulting modifier state. - bool keysForModifierState(KeyButton button, SInt32 group, - ModifierToKeys& activeModifiers, - KeyModifierMask& currentState, - KeyModifierMask requiredState, - KeyModifierMask sensitiveMask, - KeyModifierMask notRequiredMask, - Keystrokes& keystrokes) const; - - // Adds keystrokes to synthesize key \p keyItem in mode \p type to - // \p keystrokes and to undo the synthesis to \p undo. - void addKeystrokes(EKeystroke type, - const KeyItem& keyItem, - ModifierToKeys& activeModifiers, - KeyModifierMask& currentState, - Keystrokes& keystrokes) const; - - // Returns the number of modifiers indicated in \p state. - static SInt32 getNumModifiers(KeyModifierMask state); - - // Initialize key name/id maps - static void initKeyNameMaps(); - - // not implemented - CKeyMap(const CKeyMap&); - CKeyMap& operator=(const CKeyMap&); - -private: - // Ways to synthesize a KeyID over multiple keyboard groups - typedef std::vector KeyGroupTable; - - // Table of KeyID to ways to synthesize that KeyID - typedef std::map KeyIDMap; - - // List of KeyItems that generate a particular modifier - typedef std::vector ModifierKeyItemList; - - // Map a modifier to the KeyItems that synthesize that modifier - typedef std::vector ModifierToKeyTable; - - // A set of keys - typedef std::set KeySet; - - // A set of buttons - typedef std::set KeyButtonSet; - - // Key maps for parsing/formatting - typedef std::map CNameToKeyMap; - typedef std::map CNameToModifierMap; - typedef std::map CKeyToNameMap; - typedef std::map CModifierToNameMap; - - // KeyID info - KeyIDMap m_keyIDMap; - SInt32 m_numGroups; - ModifierToKeyTable m_modifierKeys; - - // composition info - bool m_composeAcrossGroups; - - // half-duplex info - KeyButtonSet m_halfDuplex; // half-duplex set by synergy - KeySet m_halfDuplexMods; // half-duplex set by user - - // dummy KeyItem for changing modifiers - KeyItem m_modifierKeyItem; - - // parsing/formatting tables - static CNameToKeyMap* s_nameToKeyMap; - static CNameToModifierMap* s_nameToModifierMap; - static CKeyToNameMap* s_keyToNameMap; - static CModifierToNameMap* s_modifierToNameMap; -}; - -#endif diff --git a/lib/synergy/CKeyState.cpp b/lib/synergy/CKeyState.cpp deleted file mode 100644 index ff374828..00000000 --- a/lib/synergy/CKeyState.cpp +++ /dev/null @@ -1,886 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CKeyState.h" -#include "IEventQueue.h" -#include "CLog.h" -#include -#include - -static const KeyButton kButtonMask = (KeyButton)(IKeyState::kNumButtons - 1); - -static const KeyID s_decomposeTable[] = { - // spacing version of dead keys - 0x0060, 0x0300, 0x0020, 0, // grave, dead_grave, space - 0x00b4, 0x0301, 0x0020, 0, // acute, dead_acute, space - 0x005e, 0x0302, 0x0020, 0, // asciicircum, dead_circumflex, space - 0x007e, 0x0303, 0x0020, 0, // asciitilde, dead_tilde, space - 0x00a8, 0x0308, 0x0020, 0, // diaeresis, dead_diaeresis, space - 0x00b0, 0x030a, 0x0020, 0, // degree, dead_abovering, space - 0x00b8, 0x0327, 0x0020, 0, // cedilla, dead_cedilla, space - 0x02db, 0x0328, 0x0020, 0, // ogonek, dead_ogonek, space - 0x02c7, 0x030c, 0x0020, 0, // caron, dead_caron, space - 0x02d9, 0x0307, 0x0020, 0, // abovedot, dead_abovedot, space - 0x02dd, 0x030b, 0x0020, 0, // doubleacute, dead_doubleacute, space - 0x02d8, 0x0306, 0x0020, 0, // breve, dead_breve, space - 0x00af, 0x0304, 0x0020, 0, // macron, dead_macron, space - - // Latin-1 (ISO 8859-1) - 0x00c0, 0x0300, 0x0041, 0, // Agrave, dead_grave, A - 0x00c1, 0x0301, 0x0041, 0, // Aacute, dead_acute, A - 0x00c2, 0x0302, 0x0041, 0, // Acircumflex, dead_circumflex, A - 0x00c3, 0x0303, 0x0041, 0, // Atilde, dead_tilde, A - 0x00c4, 0x0308, 0x0041, 0, // Adiaeresis, dead_diaeresis, A - 0x00c5, 0x030a, 0x0041, 0, // Aring, dead_abovering, A - 0x00c7, 0x0327, 0x0043, 0, // Ccedilla, dead_cedilla, C - 0x00c8, 0x0300, 0x0045, 0, // Egrave, dead_grave, E - 0x00c9, 0x0301, 0x0045, 0, // Eacute, dead_acute, E - 0x00ca, 0x0302, 0x0045, 0, // Ecircumflex, dead_circumflex, E - 0x00cb, 0x0308, 0x0045, 0, // Ediaeresis, dead_diaeresis, E - 0x00cc, 0x0300, 0x0049, 0, // Igrave, dead_grave, I - 0x00cd, 0x0301, 0x0049, 0, // Iacute, dead_acute, I - 0x00ce, 0x0302, 0x0049, 0, // Icircumflex, dead_circumflex, I - 0x00cf, 0x0308, 0x0049, 0, // Idiaeresis, dead_diaeresis, I - 0x00d1, 0x0303, 0x004e, 0, // Ntilde, dead_tilde, N - 0x00d2, 0x0300, 0x004f, 0, // Ograve, dead_grave, O - 0x00d3, 0x0301, 0x004f, 0, // Oacute, dead_acute, O - 0x00d4, 0x0302, 0x004f, 0, // Ocircumflex, dead_circumflex, O - 0x00d5, 0x0303, 0x004f, 0, // Otilde, dead_tilde, O - 0x00d6, 0x0308, 0x004f, 0, // Odiaeresis, dead_diaeresis, O - 0x00d9, 0x0300, 0x0055, 0, // Ugrave, dead_grave, U - 0x00da, 0x0301, 0x0055, 0, // Uacute, dead_acute, U - 0x00db, 0x0302, 0x0055, 0, // Ucircumflex, dead_circumflex, U - 0x00dc, 0x0308, 0x0055, 0, // Udiaeresis, dead_diaeresis, U - 0x00dd, 0x0301, 0x0059, 0, // Yacute, dead_acute, Y - 0x00e0, 0x0300, 0x0061, 0, // agrave, dead_grave, a - 0x00e1, 0x0301, 0x0061, 0, // aacute, dead_acute, a - 0x00e2, 0x0302, 0x0061, 0, // acircumflex, dead_circumflex, a - 0x00e3, 0x0303, 0x0061, 0, // atilde, dead_tilde, a - 0x00e4, 0x0308, 0x0061, 0, // adiaeresis, dead_diaeresis, a - 0x00e5, 0x030a, 0x0061, 0, // aring, dead_abovering, a - 0x00e7, 0x0327, 0x0063, 0, // ccedilla, dead_cedilla, c - 0x00e8, 0x0300, 0x0065, 0, // egrave, dead_grave, e - 0x00e9, 0x0301, 0x0065, 0, // eacute, dead_acute, e - 0x00ea, 0x0302, 0x0065, 0, // ecircumflex, dead_circumflex, e - 0x00eb, 0x0308, 0x0065, 0, // ediaeresis, dead_diaeresis, e - 0x00ec, 0x0300, 0x0069, 0, // igrave, dead_grave, i - 0x00ed, 0x0301, 0x0069, 0, // iacute, dead_acute, i - 0x00ee, 0x0302, 0x0069, 0, // icircumflex, dead_circumflex, i - 0x00ef, 0x0308, 0x0069, 0, // idiaeresis, dead_diaeresis, i - 0x00f1, 0x0303, 0x006e, 0, // ntilde, dead_tilde, n - 0x00f2, 0x0300, 0x006f, 0, // ograve, dead_grave, o - 0x00f3, 0x0301, 0x006f, 0, // oacute, dead_acute, o - 0x00f4, 0x0302, 0x006f, 0, // ocircumflex, dead_circumflex, o - 0x00f5, 0x0303, 0x006f, 0, // otilde, dead_tilde, o - 0x00f6, 0x0308, 0x006f, 0, // odiaeresis, dead_diaeresis, o - 0x00f9, 0x0300, 0x0075, 0, // ugrave, dead_grave, u - 0x00fa, 0x0301, 0x0075, 0, // uacute, dead_acute, u - 0x00fb, 0x0302, 0x0075, 0, // ucircumflex, dead_circumflex, u - 0x00fc, 0x0308, 0x0075, 0, // udiaeresis, dead_diaeresis, u - 0x00fd, 0x0301, 0x0079, 0, // yacute, dead_acute, y - 0x00ff, 0x0308, 0x0079, 0, // ydiaeresis, dead_diaeresis, y - - // Latin-2 (ISO 8859-2) - 0x0104, 0x0328, 0x0041, 0, // Aogonek, dead_ogonek, A - 0x013d, 0x030c, 0x004c, 0, // Lcaron, dead_caron, L - 0x015a, 0x0301, 0x0053, 0, // Sacute, dead_acute, S - 0x0160, 0x030c, 0x0053, 0, // Scaron, dead_caron, S - 0x015e, 0x0327, 0x0053, 0, // Scedilla, dead_cedilla, S - 0x0164, 0x030c, 0x0054, 0, // Tcaron, dead_caron, T - 0x0179, 0x0301, 0x005a, 0, // Zacute, dead_acute, Z - 0x017d, 0x030c, 0x005a, 0, // Zcaron, dead_caron, Z - 0x017b, 0x0307, 0x005a, 0, // Zabovedot, dead_abovedot, Z - 0x0105, 0x0328, 0x0061, 0, // aogonek, dead_ogonek, a - 0x013e, 0x030c, 0x006c, 0, // lcaron, dead_caron, l - 0x015b, 0x0301, 0x0073, 0, // sacute, dead_acute, s - 0x0161, 0x030c, 0x0073, 0, // scaron, dead_caron, s - 0x015f, 0x0327, 0x0073, 0, // scedilla, dead_cedilla, s - 0x0165, 0x030c, 0x0074, 0, // tcaron, dead_caron, t - 0x017a, 0x0301, 0x007a, 0, // zacute, dead_acute, z - 0x017e, 0x030c, 0x007a, 0, // zcaron, dead_caron, z - 0x017c, 0x0307, 0x007a, 0, // zabovedot, dead_abovedot, z - 0x0154, 0x0301, 0x0052, 0, // Racute, dead_acute, R - 0x0102, 0x0306, 0x0041, 0, // Abreve, dead_breve, A - 0x0139, 0x0301, 0x004c, 0, // Lacute, dead_acute, L - 0x0106, 0x0301, 0x0043, 0, // Cacute, dead_acute, C - 0x010c, 0x030c, 0x0043, 0, // Ccaron, dead_caron, C - 0x0118, 0x0328, 0x0045, 0, // Eogonek, dead_ogonek, E - 0x011a, 0x030c, 0x0045, 0, // Ecaron, dead_caron, E - 0x010e, 0x030c, 0x0044, 0, // Dcaron, dead_caron, D - 0x0143, 0x0301, 0x004e, 0, // Nacute, dead_acute, N - 0x0147, 0x030c, 0x004e, 0, // Ncaron, dead_caron, N - 0x0150, 0x030b, 0x004f, 0, // Odoubleacute, dead_doubleacute, O - 0x0158, 0x030c, 0x0052, 0, // Rcaron, dead_caron, R - 0x016e, 0x030a, 0x0055, 0, // Uring, dead_abovering, U - 0x0170, 0x030b, 0x0055, 0, // Udoubleacute, dead_doubleacute, U - 0x0162, 0x0327, 0x0054, 0, // Tcedilla, dead_cedilla, T - 0x0155, 0x0301, 0x0072, 0, // racute, dead_acute, r - 0x0103, 0x0306, 0x0061, 0, // abreve, dead_breve, a - 0x013a, 0x0301, 0x006c, 0, // lacute, dead_acute, l - 0x0107, 0x0301, 0x0063, 0, // cacute, dead_acute, c - 0x010d, 0x030c, 0x0063, 0, // ccaron, dead_caron, c - 0x0119, 0x0328, 0x0065, 0, // eogonek, dead_ogonek, e - 0x011b, 0x030c, 0x0065, 0, // ecaron, dead_caron, e - 0x010f, 0x030c, 0x0064, 0, // dcaron, dead_caron, d - 0x0144, 0x0301, 0x006e, 0, // nacute, dead_acute, n - 0x0148, 0x030c, 0x006e, 0, // ncaron, dead_caron, n - 0x0151, 0x030b, 0x006f, 0, // odoubleacute, dead_doubleacute, o - 0x0159, 0x030c, 0x0072, 0, // rcaron, dead_caron, r - 0x016f, 0x030a, 0x0075, 0, // uring, dead_abovering, u - 0x0171, 0x030b, 0x0075, 0, // udoubleacute, dead_doubleacute, u - 0x0163, 0x0327, 0x0074, 0, // tcedilla, dead_cedilla, t - - // Latin-3 (ISO 8859-3) - 0x0124, 0x0302, 0x0048, 0, // Hcircumflex, dead_circumflex, H - 0x0130, 0x0307, 0x0049, 0, // Iabovedot, dead_abovedot, I - 0x011e, 0x0306, 0x0047, 0, // Gbreve, dead_breve, G - 0x0134, 0x0302, 0x004a, 0, // Jcircumflex, dead_circumflex, J - 0x0125, 0x0302, 0x0068, 0, // hcircumflex, dead_circumflex, h - 0x011f, 0x0306, 0x0067, 0, // gbreve, dead_breve, g - 0x0135, 0x0302, 0x006a, 0, // jcircumflex, dead_circumflex, j - 0x010a, 0x0307, 0x0043, 0, // Cabovedot, dead_abovedot, C - 0x0108, 0x0302, 0x0043, 0, // Ccircumflex, dead_circumflex, C - 0x0120, 0x0307, 0x0047, 0, // Gabovedot, dead_abovedot, G - 0x011c, 0x0302, 0x0047, 0, // Gcircumflex, dead_circumflex, G - 0x016c, 0x0306, 0x0055, 0, // Ubreve, dead_breve, U - 0x015c, 0x0302, 0x0053, 0, // Scircumflex, dead_circumflex, S - 0x010b, 0x0307, 0x0063, 0, // cabovedot, dead_abovedot, c - 0x0109, 0x0302, 0x0063, 0, // ccircumflex, dead_circumflex, c - 0x0121, 0x0307, 0x0067, 0, // gabovedot, dead_abovedot, g - 0x011d, 0x0302, 0x0067, 0, // gcircumflex, dead_circumflex, g - 0x016d, 0x0306, 0x0075, 0, // ubreve, dead_breve, u - 0x015d, 0x0302, 0x0073, 0, // scircumflex, dead_circumflex, s - - // Latin-4 (ISO 8859-4) - 0x0156, 0x0327, 0x0052, 0, // Rcedilla, dead_cedilla, R - 0x0128, 0x0303, 0x0049, 0, // Itilde, dead_tilde, I - 0x013b, 0x0327, 0x004c, 0, // Lcedilla, dead_cedilla, L - 0x0112, 0x0304, 0x0045, 0, // Emacron, dead_macron, E - 0x0122, 0x0327, 0x0047, 0, // Gcedilla, dead_cedilla, G - 0x0157, 0x0327, 0x0072, 0, // rcedilla, dead_cedilla, r - 0x0129, 0x0303, 0x0069, 0, // itilde, dead_tilde, i - 0x013c, 0x0327, 0x006c, 0, // lcedilla, dead_cedilla, l - 0x0113, 0x0304, 0x0065, 0, // emacron, dead_macron, e - 0x0123, 0x0327, 0x0067, 0, // gcedilla, dead_cedilla, g - 0x0100, 0x0304, 0x0041, 0, // Amacron, dead_macron, A - 0x012e, 0x0328, 0x0049, 0, // Iogonek, dead_ogonek, I - 0x0116, 0x0307, 0x0045, 0, // Eabovedot, dead_abovedot, E - 0x012a, 0x0304, 0x0049, 0, // Imacron, dead_macron, I - 0x0145, 0x0327, 0x004e, 0, // Ncedilla, dead_cedilla, N - 0x014c, 0x0304, 0x004f, 0, // Omacron, dead_macron, O - 0x0136, 0x0327, 0x004b, 0, // Kcedilla, dead_cedilla, K - 0x0172, 0x0328, 0x0055, 0, // Uogonek, dead_ogonek, U - 0x0168, 0x0303, 0x0055, 0, // Utilde, dead_tilde, U - 0x016a, 0x0304, 0x0055, 0, // Umacron, dead_macron, U - 0x0101, 0x0304, 0x0061, 0, // amacron, dead_macron, a - 0x012f, 0x0328, 0x0069, 0, // iogonek, dead_ogonek, i - 0x0117, 0x0307, 0x0065, 0, // eabovedot, dead_abovedot, e - 0x012b, 0x0304, 0x0069, 0, // imacron, dead_macron, i - 0x0146, 0x0327, 0x006e, 0, // ncedilla, dead_cedilla, n - 0x014d, 0x0304, 0x006f, 0, // omacron, dead_macron, o - 0x0137, 0x0327, 0x006b, 0, // kcedilla, dead_cedilla, k - 0x0173, 0x0328, 0x0075, 0, // uogonek, dead_ogonek, u - 0x0169, 0x0303, 0x0075, 0, // utilde, dead_tilde, u - 0x016b, 0x0304, 0x0075, 0, // umacron, dead_macron, u - - // Latin-8 (ISO 8859-14) - 0x1e02, 0x0307, 0x0042, 0, // Babovedot, dead_abovedot, B - 0x1e03, 0x0307, 0x0062, 0, // babovedot, dead_abovedot, b - 0x1e0a, 0x0307, 0x0044, 0, // Dabovedot, dead_abovedot, D - 0x1e80, 0x0300, 0x0057, 0, // Wgrave, dead_grave, W - 0x1e82, 0x0301, 0x0057, 0, // Wacute, dead_acute, W - 0x1e0b, 0x0307, 0x0064, 0, // dabovedot, dead_abovedot, d - 0x1ef2, 0x0300, 0x0059, 0, // Ygrave, dead_grave, Y - 0x1e1e, 0x0307, 0x0046, 0, // Fabovedot, dead_abovedot, F - 0x1e1f, 0x0307, 0x0066, 0, // fabovedot, dead_abovedot, f - 0x1e40, 0x0307, 0x004d, 0, // Mabovedot, dead_abovedot, M - 0x1e41, 0x0307, 0x006d, 0, // mabovedot, dead_abovedot, m - 0x1e56, 0x0307, 0x0050, 0, // Pabovedot, dead_abovedot, P - 0x1e81, 0x0300, 0x0077, 0, // wgrave, dead_grave, w - 0x1e57, 0x0307, 0x0070, 0, // pabovedot, dead_abovedot, p - 0x1e83, 0x0301, 0x0077, 0, // wacute, dead_acute, w - 0x1e60, 0x0307, 0x0053, 0, // Sabovedot, dead_abovedot, S - 0x1ef3, 0x0300, 0x0079, 0, // ygrave, dead_grave, y - 0x1e84, 0x0308, 0x0057, 0, // Wdiaeresis, dead_diaeresis, W - 0x1e85, 0x0308, 0x0077, 0, // wdiaeresis, dead_diaeresis, w - 0x1e61, 0x0307, 0x0073, 0, // sabovedot, dead_abovedot, s - 0x0174, 0x0302, 0x0057, 0, // Wcircumflex, dead_circumflex, W - 0x1e6a, 0x0307, 0x0054, 0, // Tabovedot, dead_abovedot, T - 0x0176, 0x0302, 0x0059, 0, // Ycircumflex, dead_circumflex, Y - 0x0175, 0x0302, 0x0077, 0, // wcircumflex, dead_circumflex, w - 0x1e6b, 0x0307, 0x0074, 0, // tabovedot, dead_abovedot, t - 0x0177, 0x0302, 0x0079, 0, // ycircumflex, dead_circumflex, y - - // Latin-9 (ISO 8859-15) - 0x0178, 0x0308, 0x0059, 0, // Ydiaeresis, dead_diaeresis, Y - - // Compose key sequences - 0x00c6, kKeyCompose, 0x0041, 0x0045, 0, // AE, A, E - 0x00c1, kKeyCompose, 0x0041, 0x0027, 0, // Aacute, A, apostrophe - 0x00c2, kKeyCompose, 0x0041, 0x0053, 0, // Acircumflex, A, asciicircum - 0x00c3, kKeyCompose, 0x0041, 0x0022, 0, // Adiaeresis, A, quotedbl - 0x00c0, kKeyCompose, 0x0041, 0x0060, 0, // Agrave, A, grave - 0x00c5, kKeyCompose, 0x0041, 0x002a, 0, // Aring, A, asterisk - 0x00c3, kKeyCompose, 0x0041, 0x007e, 0, // Atilde, A, asciitilde - 0x00c7, kKeyCompose, 0x0043, 0x002c, 0, // Ccedilla, C, comma - 0x00d0, kKeyCompose, 0x0044, 0x002d, 0, // ETH, D, minus - 0x00c9, kKeyCompose, 0x0045, 0x0027, 0, // Eacute, E, apostrophe - 0x00ca, kKeyCompose, 0x0045, 0x0053, 0, // Ecircumflex, E, asciicircum - 0x00cb, kKeyCompose, 0x0045, 0x0022, 0, // Ediaeresis, E, quotedbl - 0x00c8, kKeyCompose, 0x0045, 0x0060, 0, // Egrave, E, grave - 0x00cd, kKeyCompose, 0x0049, 0x0027, 0, // Iacute, I, apostrophe - 0x00ce, kKeyCompose, 0x0049, 0x0053, 0, // Icircumflex, I, asciicircum - 0x00cf, kKeyCompose, 0x0049, 0x0022, 0, // Idiaeresis, I, quotedbl - 0x00cc, kKeyCompose, 0x0049, 0x0060, 0, // Igrave, I, grave - 0x00d1, kKeyCompose, 0x004e, 0x007e, 0, // Ntilde, N, asciitilde - 0x00d3, kKeyCompose, 0x004f, 0x0027, 0, // Oacute, O, apostrophe - 0x00d4, kKeyCompose, 0x004f, 0x0053, 0, // Ocircumflex, O, asciicircum - 0x00d6, kKeyCompose, 0x004f, 0x0022, 0, // Odiaeresis, O, quotedbl - 0x00d2, kKeyCompose, 0x004f, 0x0060, 0, // Ograve, O, grave - 0x00d8, kKeyCompose, 0x004f, 0x002f, 0, // Ooblique, O, slash - 0x00d5, kKeyCompose, 0x004f, 0x007e, 0, // Otilde, O, asciitilde - 0x00de, kKeyCompose, 0x0054, 0x0048, 0, // THORN, T, H - 0x00da, kKeyCompose, 0x0055, 0x0027, 0, // Uacute, U, apostrophe - 0x00db, kKeyCompose, 0x0055, 0x0053, 0, // Ucircumflex, U, asciicircum - 0x00dc, kKeyCompose, 0x0055, 0x0022, 0, // Udiaeresis, U, quotedbl - 0x00d9, kKeyCompose, 0x0055, 0x0060, 0, // Ugrave, U, grave - 0x00dd, kKeyCompose, 0x0059, 0x0027, 0, // Yacute, Y, apostrophe - 0x00e1, kKeyCompose, 0x0061, 0x0027, 0, // aacute, a, apostrophe - 0x00e2, kKeyCompose, 0x0061, 0x0053, 0, // acircumflex, a, asciicircum - 0x00b4, kKeyCompose, 0x0027, 0x0027, 0, // acute, apostrophe, apostrophe - 0x00e4, kKeyCompose, 0x0061, 0x0022, 0, // adiaeresis, a, quotedbl - 0x00e6, kKeyCompose, 0x0061, 0x0065, 0, // ae, a, e - 0x00e0, kKeyCompose, 0x0061, 0x0060, 0, // agrave, a, grave - 0x00e5, kKeyCompose, 0x0061, 0x002a, 0, // aring, a, asterisk - 0x0040, kKeyCompose, 0x0041, 0x0054, 0, // at, A, T - 0x00e3, kKeyCompose, 0x0061, 0x007e, 0, // atilde, a, asciitilde - 0x005c, kKeyCompose, 0x002f, 0x002f, 0, // backslash, slash, slash - 0x007c, kKeyCompose, 0x004c, 0x0056, 0, // bar, L, V - 0x007b, kKeyCompose, 0x0028, 0x002d, 0, // braceleft, parenleft, minus - 0x007d, kKeyCompose, 0x0029, 0x002d, 0, // braceright, parenright, minus - 0x005b, kKeyCompose, 0x0028, 0x0028, 0, // bracketleft, parenleft, parenleft - 0x005d, kKeyCompose, 0x0029, 0x0029, 0, // bracketright, parenright, parenright - 0x00a6, kKeyCompose, 0x0042, 0x0056, 0, // brokenbar, B, V - 0x00e7, kKeyCompose, 0x0063, 0x002c, 0, // ccedilla, c, comma - 0x00b8, kKeyCompose, 0x002c, 0x002c, 0, // cedilla, comma, comma - 0x00a2, kKeyCompose, 0x0063, 0x002f, 0, // cent, c, slash - 0x00a9, kKeyCompose, 0x0028, 0x0063, 0, // copyright, parenleft, c - 0x00a4, kKeyCompose, 0x006f, 0x0078, 0, // currency, o, x - 0x00b0, kKeyCompose, 0x0030, 0x0053, 0, // degree, 0, asciicircum - 0x00a8, kKeyCompose, 0x0022, 0x0022, 0, // diaeresis, quotedbl, quotedbl - 0x00f7, kKeyCompose, 0x003a, 0x002d, 0, // division, colon, minus - 0x00e9, kKeyCompose, 0x0065, 0x0027, 0, // eacute, e, apostrophe - 0x00ea, kKeyCompose, 0x0065, 0x0053, 0, // ecircumflex, e, asciicircum - 0x00eb, kKeyCompose, 0x0065, 0x0022, 0, // ediaeresis, e, quotedbl - 0x00e8, kKeyCompose, 0x0065, 0x0060, 0, // egrave, e, grave - 0x00f0, kKeyCompose, 0x0064, 0x002d, 0, // eth, d, minus - 0x00a1, kKeyCompose, 0x0021, 0x0021, 0, // exclamdown, exclam, exclam - 0x00ab, kKeyCompose, 0x003c, 0x003c, 0, // guillemotleft, less, less - 0x00bb, kKeyCompose, 0x003e, 0x003e, 0, // guillemotright, greater, greater - 0x0023, kKeyCompose, 0x002b, 0x002b, 0, // numbersign, plus, plus - 0x00ad, kKeyCompose, 0x002d, 0x002d, 0, // hyphen, minus, minus - 0x00ed, kKeyCompose, 0x0069, 0x0027, 0, // iacute, i, apostrophe - 0x00ee, kKeyCompose, 0x0069, 0x0053, 0, // icircumflex, i, asciicircum - 0x00ef, kKeyCompose, 0x0069, 0x0022, 0, // idiaeresis, i, quotedbl - 0x00ec, kKeyCompose, 0x0069, 0x0060, 0, // igrave, i, grave - 0x00af, kKeyCompose, 0x002d, 0x0053, 0, // macron, minus, asciicircum - 0x00ba, kKeyCompose, 0x006f, 0x005f, 0, // masculine, o, underscore - 0x00b5, kKeyCompose, 0x0075, 0x002f, 0, // mu, u, slash - 0x00d7, kKeyCompose, 0x0078, 0x0078, 0, // multiply, x, x - 0x00a0, kKeyCompose, 0x0020, 0x0020, 0, // nobreakspace, space, space - 0x00ac, kKeyCompose, 0x002c, 0x002d, 0, // notsign, comma, minus - 0x00f1, kKeyCompose, 0x006e, 0x007e, 0, // ntilde, n, asciitilde - 0x00f3, kKeyCompose, 0x006f, 0x0027, 0, // oacute, o, apostrophe - 0x00f4, kKeyCompose, 0x006f, 0x0053, 0, // ocircumflex, o, asciicircum - 0x00f6, kKeyCompose, 0x006f, 0x0022, 0, // odiaeresis, o, quotedbl - 0x00f2, kKeyCompose, 0x006f, 0x0060, 0, // ograve, o, grave - 0x00bd, kKeyCompose, 0x0031, 0x0032, 0, // onehalf, 1, 2 - 0x00bc, kKeyCompose, 0x0031, 0x0034, 0, // onequarter, 1, 4 - 0x00b9, kKeyCompose, 0x0031, 0x0053, 0, // onesuperior, 1, asciicircum - 0x00aa, kKeyCompose, 0x0061, 0x005f, 0, // ordfeminine, a, underscore - 0x00f8, kKeyCompose, 0x006f, 0x002f, 0, // oslash, o, slash - 0x00f5, kKeyCompose, 0x006f, 0x007e, 0, // otilde, o, asciitilde - 0x00b6, kKeyCompose, 0x0070, 0x0021, 0, // paragraph, p, exclam - 0x00b7, kKeyCompose, 0x002e, 0x002e, 0, // periodcentered, period, period - 0x00b1, kKeyCompose, 0x002b, 0x002d, 0, // plusminus, plus, minus - 0x00bf, kKeyCompose, 0x003f, 0x003f, 0, // questiondown, question, question - 0x00ae, kKeyCompose, 0x0028, 0x0072, 0, // registered, parenleft, r - 0x00a7, kKeyCompose, 0x0073, 0x006f, 0, // section, s, o - 0x00df, kKeyCompose, 0x0073, 0x0073, 0, // ssharp, s, s - 0x00a3, kKeyCompose, 0x004c, 0x002d, 0, // sterling, L, minus - 0x00fe, kKeyCompose, 0x0074, 0x0068, 0, // thorn, t, h - 0x00be, kKeyCompose, 0x0033, 0x0034, 0, // threequarters, 3, 4 - 0x00b3, kKeyCompose, 0x0033, 0x0053, 0, // threesuperior, 3, asciicircum - 0x00b2, kKeyCompose, 0x0032, 0x0053, 0, // twosuperior, 2, asciicircum - 0x00fa, kKeyCompose, 0x0075, 0x0027, 0, // uacute, u, apostrophe - 0x00fb, kKeyCompose, 0x0075, 0x0053, 0, // ucircumflex, u, asciicircum - 0x00fc, kKeyCompose, 0x0075, 0x0022, 0, // udiaeresis, u, quotedbl - 0x00f9, kKeyCompose, 0x0075, 0x0060, 0, // ugrave, u, grave - 0x00fd, kKeyCompose, 0x0079, 0x0027, 0, // yacute, y, apostrophe - 0x00ff, kKeyCompose, 0x0079, 0x0022, 0, // ydiaeresis, y, quotedbl - 0x00a5, kKeyCompose, 0x0079, 0x003d, 0, // yen, y, equal - - // end of table - 0 -}; - -static const KeyID s_numpadTable[] = { - kKeyKP_Space, 0x0020, - kKeyKP_Tab, kKeyTab, - kKeyKP_Enter, kKeyReturn, - kKeyKP_F1, kKeyF1, - kKeyKP_F2, kKeyF2, - kKeyKP_F3, kKeyF3, - kKeyKP_F4, kKeyF4, - kKeyKP_Home, kKeyHome, - kKeyKP_Left, kKeyLeft, - kKeyKP_Up, kKeyUp, - kKeyKP_Right, kKeyRight, - kKeyKP_Down, kKeyDown, - kKeyKP_PageUp, kKeyPageUp, - kKeyKP_PageDown, kKeyPageDown, - kKeyKP_End, kKeyEnd, - kKeyKP_Begin, kKeyBegin, - kKeyKP_Insert, kKeyInsert, - kKeyKP_Delete, kKeyDelete, - kKeyKP_Equal, 0x003d, - kKeyKP_Multiply, 0x002a, - kKeyKP_Add, 0x002b, - kKeyKP_Separator, 0x002c, - kKeyKP_Subtract, 0x002d, - kKeyKP_Decimal, 0x002e, - kKeyKP_Divide, 0x002f, - kKeyKP_0, 0x0030, - kKeyKP_1, 0x0031, - kKeyKP_2, 0x0032, - kKeyKP_3, 0x0033, - kKeyKP_4, 0x0034, - kKeyKP_5, 0x0035, - kKeyKP_6, 0x0036, - kKeyKP_7, 0x0037, - kKeyKP_8, 0x0038, - kKeyKP_9, 0x0039 -}; - -// -// CKeyState -// - -CKeyState::CKeyState() : - m_mask(0) -{ - memset(&m_keys, 0, sizeof(m_keys)); - memset(&m_syntheticKeys, 0, sizeof(m_syntheticKeys)); - memset(&m_keyClientData, 0, sizeof(m_keyClientData)); - memset(&m_serverKeys, 0, sizeof(m_serverKeys)); -} - -CKeyState::~CKeyState() -{ - // do nothing -} - -void -CKeyState::onKey(KeyButton button, bool down, KeyModifierMask newState) -{ - // update modifier state - m_mask = newState; - LOG((CLOG_DEBUG1 "new mask: 0x%04x", m_mask)); - - // ignore bogus buttons - button &= kButtonMask; - if (button == 0) { - return; - } - - // update key state - if (down) { - m_keys[button] = 1; - m_syntheticKeys[button] = 1; - } - else { - m_keys[button] = 0; - m_syntheticKeys[button] = 0; - } -} - -void -CKeyState::sendKeyEvent( - void* target, bool press, bool isAutoRepeat, - KeyID key, KeyModifierMask mask, - SInt32 count, KeyButton button) -{ - if (m_keyMap.isHalfDuplex(key, button)) { - if (isAutoRepeat) { - // ignore auto-repeat on half-duplex keys - } - else { - EVENTQUEUE->addEvent(CEvent(getKeyDownEvent(), target, - CKeyInfo::alloc(key, mask, button, 1))); - EVENTQUEUE->addEvent(CEvent(getKeyUpEvent(), target, - CKeyInfo::alloc(key, mask, button, 1))); - } - } - else { - if (isAutoRepeat) { - EVENTQUEUE->addEvent(CEvent(getKeyRepeatEvent(), target, - CKeyInfo::alloc(key, mask, button, count))); - } - else if (press) { - EVENTQUEUE->addEvent(CEvent(getKeyDownEvent(), target, - CKeyInfo::alloc(key, mask, button, 1))); - } - else { - EVENTQUEUE->addEvent(CEvent(getKeyUpEvent(), target, - CKeyInfo::alloc(key, mask, button, 1))); - } - } -} - -void -CKeyState::updateKeyMap() -{ - // get the current keyboard map - CKeyMap keyMap; - getKeyMap(keyMap); - m_keyMap.swap(keyMap); - m_keyMap.finish(); - - // add special keys - addCombinationEntries(); - addKeypadEntries(); - addAliasEntries(); -} - -void -CKeyState::updateKeyState() -{ - // reset our state - memset(&m_keys, 0, sizeof(m_keys)); - memset(&m_syntheticKeys, 0, sizeof(m_syntheticKeys)); - memset(&m_keyClientData, 0, sizeof(m_keyClientData)); - memset(&m_serverKeys, 0, sizeof(m_serverKeys)); - m_activeModifiers.clear(); - - // get the current keyboard state - KeyButtonSet keysDown; - pollPressedKeys(keysDown); - for (KeyButtonSet::const_iterator i = keysDown.begin(); - i != keysDown.end(); ++i) { - m_keys[*i] = 1; - } - - // get the current modifier state - m_mask = pollActiveModifiers(); - - // set active modifiers - CAddActiveModifierContext addModifierContext(pollActiveGroup(), m_mask, - m_activeModifiers); - m_keyMap.foreachKey(&CKeyState::addActiveModifierCB, &addModifierContext); - - LOG((CLOG_DEBUG1 "modifiers on update: 0x%04x", m_mask)); -} - -void -CKeyState::addActiveModifierCB(KeyID, SInt32 group, - CKeyMap::KeyItem& keyItem, void* vcontext) -{ - CAddActiveModifierContext* context = - reinterpret_cast(vcontext); - if (group == context->m_activeGroup && - (keyItem.m_generates & context->m_mask) != 0) { - context->m_activeModifiers.insert(std::make_pair( - keyItem.m_generates, keyItem)); - } -} - -void -CKeyState::setHalfDuplexMask(KeyModifierMask mask) -{ - m_keyMap.clearHalfDuplexModifiers(); - if ((mask & KeyModifierCapsLock) != 0) { - m_keyMap.addHalfDuplexModifier(kKeyCapsLock); - } - if ((mask & KeyModifierNumLock) != 0) { - m_keyMap.addHalfDuplexModifier(kKeyNumLock); - } - if ((mask & KeyModifierScrollLock) != 0) { - m_keyMap.addHalfDuplexModifier(kKeyScrollLock); - } -} - -void -CKeyState::fakeKeyDown(KeyID id, KeyModifierMask mask, KeyButton serverID) -{ - // if this server key is already down then this is probably a - // mis-reported autorepeat. - serverID &= kButtonMask; - if (m_serverKeys[serverID] != 0) { - fakeKeyRepeat(id, mask, 1, serverID); - return; - } - - // ignore certain keys - if (isIgnoredKey(id, mask)) { - LOG((CLOG_DEBUG1 "ignored key %04x %04x", id, mask)); - return; - } - - // get keys for key press - Keystrokes keys; - ModifierToKeys oldActiveModifiers = m_activeModifiers; - const CKeyMap::KeyItem* keyItem = - m_keyMap.mapKey(keys, id, pollActiveGroup(), m_activeModifiers, - getActiveModifiersRValue(), mask, false); - if (keyItem == NULL) { - return; - } - KeyButton localID = (KeyButton)(keyItem->m_button & kButtonMask); - updateModifierKeyState(localID, oldActiveModifiers, m_activeModifiers); - if (localID != 0) { - // note keys down - ++m_keys[localID]; - ++m_syntheticKeys[localID]; - m_keyClientData[localID] = keyItem->m_client; - m_serverKeys[serverID] = localID; - } - - // generate key events - fakeKeys(keys, 1); -} - -void -CKeyState::fakeKeyRepeat( - KeyID id, KeyModifierMask mask, - SInt32 count, KeyButton serverID) -{ - serverID &= kButtonMask; - - // if we haven't seen this button go down then ignore it - KeyButton oldLocalID = m_serverKeys[serverID]; - if (oldLocalID == 0) { - return; - } - - // get keys for key repeat - Keystrokes keys; - ModifierToKeys oldActiveModifiers = m_activeModifiers; - const CKeyMap::KeyItem* keyItem = - m_keyMap.mapKey(keys, id, pollActiveGroup(), m_activeModifiers, - getActiveModifiersRValue(), mask, true); - if (keyItem == NULL) { - return; - } - KeyButton localID = (KeyButton)(keyItem->m_button & kButtonMask); - if (localID == 0) { - return; - } - - // if the KeyButton for the auto-repeat is not the same as for the - // initial press then mark the initial key as released and the new - // key as pressed. this can happen when we auto-repeat after a - // dead key. for example, a dead accent followed by 'a' will - // generate an 'a with accent' followed by a repeating 'a'. the - // KeyButtons for the two KeyIDs might be different. - if (localID != oldLocalID) { - // replace key up with previous KeyButton but leave key down - // alone so it uses the new KeyButton. - for (Keystrokes::iterator index = keys.begin(); - index != keys.end(); ++index) { - if (index->m_type == Keystroke::kButton && - index->m_data.m_button.m_button == localID) { - index->m_data.m_button.m_button = oldLocalID; - break; - } - } - - // note that old key is now up - --m_keys[oldLocalID]; - --m_syntheticKeys[oldLocalID]; - - // note keys down - updateModifierKeyState(localID, oldActiveModifiers, m_activeModifiers); - ++m_keys[localID]; - ++m_syntheticKeys[localID]; - m_keyClientData[localID] = keyItem->m_client; - m_serverKeys[serverID] = localID; - } - - // generate key events - fakeKeys(keys, count); -} - -void -CKeyState::fakeKeyUp(KeyButton serverID) -{ - // if we haven't seen this button go down then ignore it - KeyButton localID = m_serverKeys[serverID & kButtonMask]; - if (localID == 0) { - return; - } - - // get the sequence of keys to simulate key release - Keystrokes keys; - keys.push_back(Keystroke(localID, false, false, m_keyClientData[localID])); - - // note keys down - --m_keys[localID]; - --m_syntheticKeys[localID]; - m_serverKeys[serverID] = 0; - - // check if this is a modifier - for (ModifierToKeys::iterator i = m_activeModifiers.begin(); - i != m_activeModifiers.end(); ++i) { - if (i->second.m_button == localID && !i->second.m_lock) { - // modifier is no longer down - KeyModifierMask mask = i->first; - m_activeModifiers.erase(i); - - if (m_activeModifiers.count(mask) == 0) { - // no key for modifier is down so deactivate modifier - m_mask &= ~mask; - LOG((CLOG_DEBUG1 "new state %04x", m_mask)); - } - - break; - } - } - - // generate key events - fakeKeys(keys, 1); -} - -void -CKeyState::fakeAllKeysUp() -{ - Keystrokes keys; - for (KeyButton i = 0; i < IKeyState::kNumButtons; ++i) { - if (m_syntheticKeys[i] > 0) { - keys.push_back(Keystroke(i, false, false, m_keyClientData[i])); - m_keys[i] = 0; - m_syntheticKeys[i] = 0; - } - } - fakeKeys(keys, 1); - memset(&m_serverKeys, 0, sizeof(m_serverKeys)); - m_activeModifiers.clear(); - m_mask = pollActiveModifiers(); -} - -bool -CKeyState::isKeyDown(KeyButton button) const -{ - return (m_keys[button & kButtonMask] > 0); -} - -KeyModifierMask -CKeyState::getActiveModifiers() const -{ - return m_mask; -} - -KeyModifierMask& -CKeyState::getActiveModifiersRValue() -{ - return m_mask; -} - -SInt32 -CKeyState::getEffectiveGroup(SInt32 group, SInt32 offset) const -{ - return m_keyMap.getEffectiveGroup(group, offset); -} - -bool -CKeyState::isIgnoredKey(KeyID key, KeyModifierMask) const -{ - switch (key) { - case kKeyCapsLock: - case kKeyNumLock: - case kKeyScrollLock: - return true; - - default: - return false; - } -} - -KeyButton -CKeyState::getButton(KeyID id, SInt32 group) const -{ - const CKeyMap::KeyItemList* items = - m_keyMap.findCompatibleKey(id, group, 0, 0); - if (items == NULL) { - return 0; - } - else { - return items->back().m_button; - } -} - -void -CKeyState::addAliasEntries() -{ - for (SInt32 g = 0, n = m_keyMap.getNumGroups(); g < n; ++g) { - // if we can't shift any kKeyTab key in a particular group but we can - // shift kKeyLeftTab then add a shifted kKeyTab entry that matches a - // shifted kKeyLeftTab entry. - m_keyMap.addKeyAliasEntry(kKeyTab, g, - KeyModifierShift, KeyModifierShift, - kKeyLeftTab, - KeyModifierShift, KeyModifierShift); - - // if we have no kKeyLeftTab but we do have a kKeyTab that can be - // shifted then add kKeyLeftTab that matches a kKeyTab. - m_keyMap.addKeyAliasEntry(kKeyLeftTab, g, - KeyModifierShift, KeyModifierShift, - kKeyTab, - 0, KeyModifierShift); - - // map non-breaking space to space - m_keyMap.addKeyAliasEntry(0x20, g, 0, 0, 0xa0, 0, 0); - } -} - -void -CKeyState::addKeypadEntries() -{ - // map every numpad key to its equivalent non-numpad key if it's not - // on the keyboard. - for (SInt32 g = 0, n = m_keyMap.getNumGroups(); g < n; ++g) { - for (size_t i = 0; i < sizeof(s_numpadTable) / - sizeof(s_numpadTable[0]); i += 2) { - m_keyMap.addKeyCombinationEntry(s_numpadTable[i], g, - s_numpadTable + i + 1, 1); - } - } -} - -void -CKeyState::addCombinationEntries() -{ - for (SInt32 g = 0, n = m_keyMap.getNumGroups(); g < n; ++g) { - // add dead and compose key composition sequences - for (const KeyID* i = s_decomposeTable; *i != 0; ++i) { - // count the decomposed keys for this key - UInt32 numKeys = 0; - for (const KeyID* j = i; *++j != 0; ) { - ++numKeys; - } - - // add an entry for this key - m_keyMap.addKeyCombinationEntry(*i, g, i + 1, numKeys); - - // next key - i += numKeys + 1; - } - } -} - -void -CKeyState::fakeKeys(const Keystrokes& keys, UInt32 count) -{ - // do nothing if no keys or no repeats - if (count == 0 || keys.empty()) { - return; - } - - // generate key events - LOG((CLOG_DEBUG1 "keystrokes:")); - for (Keystrokes::const_iterator k = keys.begin(); k != keys.end(); ) { - if (k->m_type == Keystroke::kButton && k->m_data.m_button.m_repeat) { - // repeat from here up to but not including the next key - // with m_repeat == false count times. - Keystrokes::const_iterator start = k; - while (count-- > 0) { - // send repeating events - for (k = start; k != keys.end() && - k->m_type == Keystroke::kButton && - k->m_data.m_button.m_repeat; ++k) { - fakeKey(*k); - } - } - - // note -- k is now on the first non-repeat key after the - // repeat keys, exactly where we'd like to continue from. - } - else { - // send event - fakeKey(*k); - - // next key - ++k; - } - } -} - -void -CKeyState::updateModifierKeyState(KeyButton button, - const ModifierToKeys& oldModifiers, - const ModifierToKeys& newModifiers) -{ - // get the pressed modifier buttons before and after - CKeyMap::ButtonToKeyMap oldKeys, newKeys; - for (ModifierToKeys::const_iterator i = oldModifiers.begin(); - i != oldModifiers.end(); ++i) { - oldKeys.insert(std::make_pair(i->second.m_button, &i->second)); - } - for (ModifierToKeys::const_iterator i = newModifiers.begin(); - i != newModifiers.end(); ++i) { - newKeys.insert(std::make_pair(i->second.m_button, &i->second)); - } - - // get the modifier buttons that were pressed or released - CKeyMap::ButtonToKeyMap pressed, released; - std::set_difference(oldKeys.begin(), oldKeys.end(), - newKeys.begin(), newKeys.end(), - std::inserter(released, released.end()), - ButtonToKeyLess()); - std::set_difference(newKeys.begin(), newKeys.end(), - oldKeys.begin(), oldKeys.end(), - std::inserter(pressed, pressed.end()), - ButtonToKeyLess()); - - // update state - for (CKeyMap::ButtonToKeyMap::const_iterator i = released.begin(); - i != released.end(); ++i) { - if (i->first != button) { - m_keys[i->first] = 0; - m_syntheticKeys[i->first] = 0; - } - } - for (CKeyMap::ButtonToKeyMap::const_iterator i = pressed.begin(); - i != pressed.end(); ++i) { - if (i->first != button) { - m_keys[i->first] = 1; - m_syntheticKeys[i->first] = 1; - m_keyClientData[i->first] = i->second->m_client; - } - } -} - - -// -// CKeyState::CAddActiveModifierContext -// - -CKeyState::CAddActiveModifierContext::CAddActiveModifierContext( - SInt32 group, KeyModifierMask mask, - ModifierToKeys& activeModifiers) : - m_activeGroup(group), - m_mask(mask), - m_activeModifiers(activeModifiers) -{ - // do nothing -} diff --git a/lib/synergy/CKeyState.h b/lib/synergy/CKeyState.h deleted file mode 100644 index 6bfd9d8b..00000000 --- a/lib/synergy/CKeyState.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CKEYSTATE_H -#define CKEYSTATE_H - -#include "IKeyState.h" -#include "CKeyMap.h" - -//! Core key state -/*! -This class provides key state services. Subclasses must implement a few -platform specific methods. -*/ -class CKeyState : public IKeyState { -public: - CKeyState(); - virtual ~CKeyState(); - - //! @name manipulators - //@{ - - //! Handle key event - /*! - Sets the state of \p button to down or up and updates the current - modifier state to \p newState. This method should be called by - primary screens only in response to local events. For auto-repeat - set \p down to \c true. Overrides must forward to the superclass. - */ - virtual void onKey(KeyButton button, bool down, - KeyModifierMask newState); - - //! Post a key event - /*! - Posts a key event. This may adjust the event or post additional - events in some circumstances. If this is overridden it must forward - to the superclass. - */ - virtual void sendKeyEvent(void* target, - bool press, bool isAutoRepeat, - KeyID key, KeyModifierMask mask, - SInt32 count, KeyButton button); - - //@} - //! @name accessors - //@{ - - //@} - - // IKeyState overrides - virtual void updateKeyMap(); - virtual void updateKeyState(); - virtual void setHalfDuplexMask(KeyModifierMask); - virtual void fakeKeyDown(KeyID id, KeyModifierMask mask, - KeyButton button); - virtual void fakeKeyRepeat(KeyID id, KeyModifierMask mask, - SInt32 count, KeyButton button); - virtual void fakeKeyUp(KeyButton button); - virtual void fakeAllKeysUp(); - virtual bool fakeCtrlAltDel() = 0; - virtual bool isKeyDown(KeyButton) const; - virtual KeyModifierMask - getActiveModifiers() const; - virtual KeyModifierMask - pollActiveModifiers() const = 0; - virtual SInt32 pollActiveGroup() const = 0; - virtual void pollPressedKeys(KeyButtonSet& pressedKeys) const = 0; - -protected: - typedef CKeyMap::Keystroke Keystroke; - - //! @name protected manipulators - //@{ - - //! Get the keyboard map - /*! - Fills \p keyMap with the current keyboard map. - */ - virtual void getKeyMap(CKeyMap& keyMap) = 0; - - //! Fake a key event - /*! - Synthesize an event for \p keystroke. - */ - virtual void fakeKey(const Keystroke& keystroke) = 0; - - //! Get the active modifiers - /*! - Returns the modifiers that are currently active according to our - shadowed state. The state may be modified. - */ - virtual KeyModifierMask& - getActiveModifiersRValue(); - - //@} - //! @name protected accessors - //@{ - - //! Compute a group number - /*! - Returns the number of the group \p offset groups after group \p group. - */ - SInt32 getEffectiveGroup(SInt32 group, SInt32 offset) const; - - //! Check if key is ignored - /*! - Returns \c true if and only if the key should always be ignored. - The default returns \c true only for the toggle keys. - */ - virtual bool isIgnoredKey(KeyID key, KeyModifierMask mask) const; - - //! Get button for a KeyID - /*! - Return the button mapped to key \p id in group \p group if any, - otherwise returns 0. - */ - KeyButton getButton(KeyID id, SInt32 group) const; - - //@} - -private: - typedef CKeyMap::Keystrokes Keystrokes; - typedef CKeyMap::ModifierToKeys ModifierToKeys; - struct CAddActiveModifierContext { - public: - CAddActiveModifierContext(SInt32 group, KeyModifierMask mask, - ModifierToKeys& activeModifiers); - - public: - SInt32 m_activeGroup; - KeyModifierMask m_mask; - ModifierToKeys& m_activeModifiers; - - private: - // not implemented - CAddActiveModifierContext(const CAddActiveModifierContext&); - CAddActiveModifierContext& operator=(const CAddActiveModifierContext&); - }; - - class ButtonToKeyLess { - public: - bool operator()(const CKeyMap::ButtonToKeyMap::value_type& a, - const CKeyMap::ButtonToKeyMap::value_type b) const - { - return (a.first < b.first); - } - }; - - // not implemented - CKeyState(const CKeyState&); - CKeyState& operator=(const CKeyState&); - - // adds alias key sequences. these are sequences that are equivalent - // to other sequences. - void addAliasEntries(); - - // adds non-keypad key sequences for keypad KeyIDs - void addKeypadEntries(); - - // adds key sequences for combination KeyIDs (those built using - // dead keys) - void addCombinationEntries(); - - // synthesize key events. synthesize auto-repeat events count times. - void fakeKeys(const Keystrokes&, UInt32 count); - - // update key state to match changes to modifiers - void updateModifierKeyState(KeyButton button, - const ModifierToKeys& oldModifiers, - const ModifierToKeys& newModifiers); - - // active modifiers collection callback - static void addActiveModifierCB(KeyID id, SInt32 group, - CKeyMap::KeyItem& keyItem, void* vcontext); - -private: - // the keyboard map - CKeyMap m_keyMap; - - // current modifier state - KeyModifierMask m_mask; - - // the active modifiers and the buttons activating them - ModifierToKeys m_activeModifiers; - - // current keyboard state (> 0 if pressed, 0 otherwise). this is - // initialized to the keyboard state according to the system then - // it tracks synthesized events. - SInt32 m_keys[kNumButtons]; - - // synthetic keyboard state (> 0 if pressed, 0 otherwise). this - // tracks the synthesized keyboard state. if m_keys[n] > 0 but - // m_syntheticKeys[n] == 0 then the key was pressed locally and - // not synthesized yet. - SInt32 m_syntheticKeys[kNumButtons]; - - // client data for each pressed key - UInt32 m_keyClientData[kNumButtons]; - - // server keyboard state. an entry is 0 if not the key isn't pressed - // otherwise it's the local KeyButton synthesized for the server key. - KeyButton m_serverKeys[kNumButtons]; -}; - -#endif diff --git a/lib/synergy/CPacketStreamFilter.cpp b/lib/synergy/CPacketStreamFilter.cpp deleted file mode 100644 index 4aad9c02..00000000 --- a/lib/synergy/CPacketStreamFilter.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CPacketStreamFilter.h" -#include "IEventQueue.h" -#include "CLock.h" -#include "TMethodEventJob.h" - -// -// CPacketStreamFilter -// - -CPacketStreamFilter::CPacketStreamFilter(IStream* stream, bool adoptStream) : - CStreamFilter(stream, adoptStream), - m_size(0), - m_inputShutdown(false) -{ - // do nothing -} - -CPacketStreamFilter::~CPacketStreamFilter() -{ - // do nothing -} - -void -CPacketStreamFilter::close() -{ - CLock lock(&m_mutex); - m_size = 0; - m_buffer.pop(m_buffer.getSize()); - CStreamFilter::close(); -} - -UInt32 -CPacketStreamFilter::read(void* buffer, UInt32 n) -{ - if (n == 0) { - return 0; - } - - CLock lock(&m_mutex); - - // if not enough data yet then give up - if (!isReadyNoLock()) { - return 0; - } - - // read no more than what's left in the buffered packet - if (n > m_size) { - n = m_size; - } - - // read it - if (buffer != NULL) { - memcpy(buffer, m_buffer.peek(n), n); - } - m_buffer.pop(n); - m_size -= n; - - // get next packet's size if we've finished with this packet and - // there's enough data to do so. - readPacketSize(); - - if (m_inputShutdown && m_size == 0) { - EVENTQUEUE->addEvent(CEvent(getInputShutdownEvent(), - getEventTarget(), NULL)); - } - - return n; -} - -void -CPacketStreamFilter::write(const void* buffer, UInt32 count) -{ - // write the length of the payload - UInt8 length[4]; - length[0] = (UInt8)((count >> 24) & 0xff); - length[1] = (UInt8)((count >> 16) & 0xff); - length[2] = (UInt8)((count >> 8) & 0xff); - length[3] = (UInt8)( count & 0xff); - getStream()->write(length, sizeof(length)); - - // write the payload - getStream()->write(buffer, count); -} - -void -CPacketStreamFilter::shutdownInput() -{ - CLock lock(&m_mutex); - m_size = 0; - m_buffer.pop(m_buffer.getSize()); - CStreamFilter::shutdownInput(); -} - -bool -CPacketStreamFilter::isReady() const -{ - CLock lock(&m_mutex); - return isReadyNoLock(); -} - -UInt32 -CPacketStreamFilter::getSize() const -{ - CLock lock(&m_mutex); - return isReadyNoLock() ? m_size : 0; -} - -bool -CPacketStreamFilter::isReadyNoLock() const -{ - return (m_size != 0 && m_buffer.getSize() >= m_size); -} - -void -CPacketStreamFilter::readPacketSize() -{ - // note -- m_mutex must be locked on entry - - if (m_size == 0 && m_buffer.getSize() >= 4) { - UInt8 buffer[4]; - memcpy(buffer, m_buffer.peek(sizeof(buffer)), sizeof(buffer)); - m_buffer.pop(sizeof(buffer)); - m_size = ((UInt32)buffer[0] << 24) | - ((UInt32)buffer[1] << 16) | - ((UInt32)buffer[2] << 8) | - (UInt32)buffer[3]; - } -} - -bool -CPacketStreamFilter::readMore() -{ - // note if we have whole packet - bool wasReady = isReadyNoLock(); - - // read more data - char buffer[4096]; - UInt32 n = getStream()->read(buffer, sizeof(buffer)); - while (n > 0) { - m_buffer.write(buffer, n); - n = getStream()->read(buffer, sizeof(buffer)); - } - - // if we don't yet have the next packet size then get it, - // if possible. - readPacketSize(); - - // note if we now have a whole packet - bool isReady = isReadyNoLock(); - - // if we weren't ready before but now we are then send a - // input ready event apparently from the filtered stream. - return (wasReady != isReady); -} - -void -CPacketStreamFilter::filterEvent(const CEvent& event) -{ - if (event.getType() == getInputReadyEvent()) { - CLock lock(&m_mutex); - if (!readMore()) { - return; - } - } - else if (event.getType() == getInputShutdownEvent()) { - // discard this if we have buffered data - CLock lock(&m_mutex); - m_inputShutdown = true; - if (m_size != 0) { - return; - } - } - - // pass event - CStreamFilter::filterEvent(event); -} diff --git a/lib/synergy/CPacketStreamFilter.h b/lib/synergy/CPacketStreamFilter.h deleted file mode 100644 index 93ddd8fa..00000000 --- a/lib/synergy/CPacketStreamFilter.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CPACKETSTREAMFILTER_H -#define CPACKETSTREAMFILTER_H - -#include "CStreamFilter.h" -#include "CStreamBuffer.h" -#include "CMutex.h" - -//! Packetizing stream filter -/*! -Filters a stream to read and write packets. -*/ -class CPacketStreamFilter : public CStreamFilter { -public: - CPacketStreamFilter(IStream* stream, bool adoptStream = true); - ~CPacketStreamFilter(); - - // IStream overrides - virtual void close(); - virtual UInt32 read(void* buffer, UInt32 n); - virtual void write(const void* buffer, UInt32 n); - virtual void shutdownInput(); - virtual bool isReady() const; - virtual UInt32 getSize() const; - -protected: - // CStreamFilter overrides - virtual void filterEvent(const CEvent&); - -private: - bool isReadyNoLock() const; - void readPacketSize(); - bool readMore(); - -private: - CMutex m_mutex; - UInt32 m_size; - CStreamBuffer m_buffer; - bool m_inputShutdown; -}; - -#endif diff --git a/lib/synergy/CPlatformScreen.cpp b/lib/synergy/CPlatformScreen.cpp deleted file mode 100644 index ca33d5a9..00000000 --- a/lib/synergy/CPlatformScreen.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CPlatformScreen.h" - -CPlatformScreen::CPlatformScreen() -{ - // do nothing -} - -CPlatformScreen::~CPlatformScreen() -{ - // do nothing -} - -void -CPlatformScreen::updateKeyMap() -{ - getKeyState()->updateKeyMap(); -} - -void -CPlatformScreen::updateKeyState() -{ - getKeyState()->updateKeyState(); - updateButtons(); -} - -void -CPlatformScreen::setHalfDuplexMask(KeyModifierMask mask) -{ - getKeyState()->setHalfDuplexMask(mask); -} - -void -CPlatformScreen::fakeKeyDown(KeyID id, KeyModifierMask mask, - KeyButton button) -{ - getKeyState()->fakeKeyDown(id, mask, button); -} - -void -CPlatformScreen::fakeKeyRepeat(KeyID id, KeyModifierMask mask, - SInt32 count, KeyButton button) -{ - getKeyState()->fakeKeyRepeat(id, mask, count, button); -} - -void -CPlatformScreen::fakeKeyUp(KeyButton button) -{ - getKeyState()->fakeKeyUp(button); -} - -void -CPlatformScreen::fakeAllKeysUp() -{ - getKeyState()->fakeAllKeysUp(); -} - -bool -CPlatformScreen::fakeCtrlAltDel() -{ - return getKeyState()->fakeCtrlAltDel(); -} - -bool -CPlatformScreen::isKeyDown(KeyButton button) const -{ - return getKeyState()->isKeyDown(button); -} - -KeyModifierMask -CPlatformScreen::getActiveModifiers() const -{ - return getKeyState()->getActiveModifiers(); -} - -KeyModifierMask -CPlatformScreen::pollActiveModifiers() const -{ - return getKeyState()->pollActiveModifiers(); -} - -SInt32 -CPlatformScreen::pollActiveGroup() const -{ - return getKeyState()->pollActiveGroup(); -} - -void -CPlatformScreen::pollPressedKeys(KeyButtonSet& pressedKeys) const -{ - getKeyState()->pollPressedKeys(pressedKeys); -} diff --git a/lib/synergy/CPlatformScreen.h b/lib/synergy/CPlatformScreen.h deleted file mode 100644 index 2e5c87f1..00000000 --- a/lib/synergy/CPlatformScreen.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CPLATFORMSCREEN_H -#define CPLATFORMSCREEN_H - -#include "IPlatformScreen.h" - -//! Base screen implementation -/*! -This screen implementation is the superclass of all other screen -implementations. It implements a handful of methods and requires -subclasses to implement the rest. -*/ -class CPlatformScreen : public IPlatformScreen { -public: - CPlatformScreen(); - virtual ~CPlatformScreen(); - - // IScreen overrides - virtual void* getEventTarget() const = 0; - virtual bool getClipboard(ClipboardID id, IClipboard*) const = 0; - virtual void getShape(SInt32& x, SInt32& y, - SInt32& width, SInt32& height) const = 0; - virtual void getCursorPos(SInt32& x, SInt32& y) const = 0; - - // IPrimaryScreen overrides - virtual void reconfigure(UInt32 activeSides) = 0; - virtual void warpCursor(SInt32 x, SInt32 y) = 0; - virtual UInt32 registerHotKey(KeyID key, - KeyModifierMask mask) = 0; - virtual void unregisterHotKey(UInt32 id) = 0; - virtual void fakeInputBegin() = 0; - virtual void fakeInputEnd() = 0; - virtual SInt32 getJumpZoneSize() const = 0; - virtual bool isAnyMouseButtonDown() const = 0; - virtual void getCursorCenter(SInt32& x, SInt32& y) const = 0; - - // ISecondaryScreen overrides - virtual void fakeMouseButton(ButtonID id, bool press) const = 0; - virtual void fakeMouseMove(SInt32 x, SInt32 y) const = 0; - virtual void fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const = 0; - virtual void fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const = 0; - - // IKeyState overrides - virtual void updateKeyMap(); - virtual void updateKeyState(); - virtual void setHalfDuplexMask(KeyModifierMask); - virtual void fakeKeyDown(KeyID id, KeyModifierMask mask, - KeyButton button); - virtual void fakeKeyRepeat(KeyID id, KeyModifierMask mask, - SInt32 count, KeyButton button); - virtual void fakeKeyUp(KeyButton button); - virtual void fakeAllKeysUp(); - virtual bool fakeCtrlAltDel(); - virtual bool isKeyDown(KeyButton) const; - virtual KeyModifierMask - getActiveModifiers() const; - virtual KeyModifierMask - pollActiveModifiers() const; - virtual SInt32 pollActiveGroup() const; - virtual void pollPressedKeys(KeyButtonSet& pressedKeys) const; - - // IPlatformScreen overrides - virtual void enable() = 0; - virtual void disable() = 0; - virtual void enter() = 0; - virtual bool leave() = 0; - virtual bool setClipboard(ClipboardID, const IClipboard*) = 0; - virtual void checkClipboards() = 0; - virtual void openScreensaver(bool notify) = 0; - virtual void closeScreensaver() = 0; - virtual void screensaver(bool activate) = 0; - virtual void resetOptions() = 0; - virtual void setOptions(const COptionsList& options) = 0; - virtual void setSequenceNumber(UInt32) = 0; - virtual bool isPrimary() const = 0; - -protected: - //! Update mouse buttons - /*! - Subclasses must implement this method to update their internal mouse - button mapping and, if desired, state tracking. - */ - virtual void updateButtons() = 0; - - //! Get the key state - /*! - Subclasses must implement this method to return the platform specific - key state object that each subclass must have. - */ - virtual IKeyState* getKeyState() const = 0; - - // IPlatformScreen overrides - virtual void handleSystemEvent(const CEvent& event, void*) = 0; -}; - -#endif diff --git a/lib/synergy/CProtocolUtil.cpp b/lib/synergy/CProtocolUtil.cpp deleted file mode 100644 index f0f012a1..00000000 --- a/lib/synergy/CProtocolUtil.cpp +++ /dev/null @@ -1,538 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CProtocolUtil.h" -#include "IStream.h" -#include "CLog.h" -#include "stdvector.h" -#include -#include - -// -// CProtocolUtil -// - -void -CProtocolUtil::writef(IStream* stream, const char* fmt, ...) -{ - assert(stream != NULL); - assert(fmt != NULL); - LOG((CLOG_DEBUG2 "writef(%s)", fmt)); - - va_list args; - va_start(args, fmt); - UInt32 size = getLength(fmt, args); - va_end(args); - va_start(args, fmt); - vwritef(stream, fmt, size, args); - va_end(args); -} - -bool -CProtocolUtil::readf(IStream* stream, const char* fmt, ...) -{ - assert(stream != NULL); - assert(fmt != NULL); - LOG((CLOG_DEBUG2 "readf(%s)", fmt)); - - bool result; - va_list args; - va_start(args, fmt); - try { - vreadf(stream, fmt, args); - result = true; - } - catch (XIO&) { - result = false; - } - va_end(args); - return result; -} - -void -CProtocolUtil::vwritef(IStream* stream, - const char* fmt, UInt32 size, va_list args) -{ - assert(stream != NULL); - assert(fmt != NULL); - - // done if nothing to write - if (size == 0) { - return; - } - - // fill buffer - UInt8* buffer = new UInt8[size]; - writef(buffer, fmt, args); - - try { - // write buffer - stream->write(buffer, size); - LOG((CLOG_DEBUG2 "wrote %d bytes", size)); - - delete[] buffer; - } - catch (XBase&) { - delete[] buffer; - throw; - } -} - -void -CProtocolUtil::vreadf(IStream* stream, const char* fmt, va_list args) -{ - assert(stream != NULL); - assert(fmt != NULL); - - // begin scanning - while (*fmt) { - if (*fmt == '%') { - // format specifier. determine argument size. - ++fmt; - UInt32 len = eatLength(&fmt); - switch (*fmt) { - case 'i': { - // check for valid length - assert(len == 1 || len == 2 || len == 4); - - // read the data - UInt8 buffer[4]; - read(stream, buffer, len); - - // convert it - void* v = va_arg(args, void*); - switch (len) { - case 1: - // 1 byte integer - *reinterpret_cast(v) = buffer[0]; - LOG((CLOG_DEBUG2 "readf: read %d byte integer: %d (0x%x)", len, *reinterpret_cast(v), *reinterpret_cast(v))); - break; - - case 2: - // 2 byte integer - *reinterpret_cast(v) = - static_cast( - (static_cast(buffer[0]) << 8) | - static_cast(buffer[1])); - LOG((CLOG_DEBUG2 "readf: read %d byte integer: %d (0x%x)", len, *reinterpret_cast(v), *reinterpret_cast(v))); - break; - - case 4: - // 4 byte integer - *reinterpret_cast(v) = - (static_cast(buffer[0]) << 24) | - (static_cast(buffer[1]) << 16) | - (static_cast(buffer[2]) << 8) | - static_cast(buffer[3]); - LOG((CLOG_DEBUG2 "readf: read %d byte integer: %d (0x%x)", len, *reinterpret_cast(v), *reinterpret_cast(v))); - break; - } - break; - } - - case 'I': { - // check for valid length - assert(len == 1 || len == 2 || len == 4); - - // read the vector length - UInt8 buffer[4]; - read(stream, buffer, 4); - UInt32 n = (static_cast(buffer[0]) << 24) | - (static_cast(buffer[1]) << 16) | - (static_cast(buffer[2]) << 8) | - static_cast(buffer[3]); - - // convert it - void* v = va_arg(args, void*); - switch (len) { - case 1: - // 1 byte integer - for (UInt32 i = 0; i < n; ++i) { - read(stream, buffer, 1); - reinterpret_cast*>(v)->push_back( - buffer[0]); - LOG((CLOG_DEBUG2 "readf: read %d byte integer[%d]: %d (0x%x)", len, i, reinterpret_cast*>(v)->back(), reinterpret_cast*>(v)->back())); - } - break; - - case 2: - // 2 byte integer - for (UInt32 i = 0; i < n; ++i) { - read(stream, buffer, 2); - reinterpret_cast*>(v)->push_back( - static_cast( - (static_cast(buffer[0]) << 8) | - static_cast(buffer[1]))); - LOG((CLOG_DEBUG2 "readf: read %d byte integer[%d]: %d (0x%x)", len, i, reinterpret_cast*>(v)->back(), reinterpret_cast*>(v)->back())); - } - break; - - case 4: - // 4 byte integer - for (UInt32 i = 0; i < n; ++i) { - read(stream, buffer, 4); - reinterpret_cast*>(v)->push_back( - (static_cast(buffer[0]) << 24) | - (static_cast(buffer[1]) << 16) | - (static_cast(buffer[2]) << 8) | - static_cast(buffer[3])); - LOG((CLOG_DEBUG2 "readf: read %d byte integer[%d]: %d (0x%x)", len, i, reinterpret_cast*>(v)->back(), reinterpret_cast*>(v)->back())); - } - break; - } - break; - } - - case 's': { - assert(len == 0); - - // read the string length - UInt8 buffer[128]; - read(stream, buffer, 4); - UInt32 len = (static_cast(buffer[0]) << 24) | - (static_cast(buffer[1]) << 16) | - (static_cast(buffer[2]) << 8) | - static_cast(buffer[3]); - - // use a fixed size buffer if its big enough - const bool useFixed = (len <= sizeof(buffer)); - - // allocate a buffer to read the data - UInt8* sBuffer = buffer; - if (!useFixed) { - sBuffer = new UInt8[len]; - } - - // read the data - try { - read(stream, sBuffer, len); - } - catch (...) { - if (!useFixed) { - delete[] sBuffer; - } - throw; - } - LOG((CLOG_DEBUG2 "readf: read %d byte string: %.*s", len, len, sBuffer)); - - // save the data - CString* dst = va_arg(args, CString*); - dst->assign((const char*)sBuffer, len); - - // release the buffer - if (!useFixed) { - delete[] sBuffer; - } - break; - } - - case '%': - assert(len == 0); - break; - - default: - assert(0 && "invalid format specifier"); - } - - // next format character - ++fmt; - } - else { - // read next character - char buffer[1]; - read(stream, buffer, 1); - - // verify match - if (buffer[0] != *fmt) { - LOG((CLOG_DEBUG2 "readf: format mismatch: %c vs %c", *fmt, buffer[0])); - throw XIOReadMismatch(); - } - - // next format character - ++fmt; - } - } -} - -UInt32 -CProtocolUtil::getLength(const char* fmt, va_list args) -{ - UInt32 n = 0; - while (*fmt) { - if (*fmt == '%') { - // format specifier. determine argument size. - ++fmt; - UInt32 len = eatLength(&fmt); - switch (*fmt) { - case 'i': - assert(len == 1 || len == 2 || len == 4); - (void)va_arg(args, UInt32); - break; - - case 'I': - assert(len == 1 || len == 2 || len == 4); - switch (len) { - case 1: - len = (va_arg(args, std::vector*))->size() + 4; - break; - - case 2: - len = 2 * (va_arg(args, std::vector*))->size() + 4; - break; - - case 4: - len = 4 * (va_arg(args, std::vector*))->size() + 4; - break; - } - break; - - case 's': - assert(len == 0); - len = (va_arg(args, CString*))->size() + 4; - (void)va_arg(args, UInt8*); - break; - - case 'S': - assert(len == 0); - len = va_arg(args, UInt32) + 4; - (void)va_arg(args, UInt8*); - break; - - case '%': - assert(len == 0); - len = 1; - break; - - default: - assert(0 && "invalid format specifier"); - } - - // accumulate size - n += len; - ++fmt; - } - else { - // regular character - ++n; - ++fmt; - } - } - return n; -} - -void -CProtocolUtil::writef(void* buffer, const char* fmt, va_list args) -{ - UInt8* dst = reinterpret_cast(buffer); - - while (*fmt) { - if (*fmt == '%') { - // format specifier. determine argument size. - ++fmt; - UInt32 len = eatLength(&fmt); - switch (*fmt) { - case 'i': { - const UInt32 v = va_arg(args, UInt32); - switch (len) { - case 1: - // 1 byte integer - *dst++ = static_cast(v & 0xff); - break; - - case 2: - // 2 byte integer - *dst++ = static_cast((v >> 8) & 0xff); - *dst++ = static_cast( v & 0xff); - break; - - case 4: - // 4 byte integer - *dst++ = static_cast((v >> 24) & 0xff); - *dst++ = static_cast((v >> 16) & 0xff); - *dst++ = static_cast((v >> 8) & 0xff); - *dst++ = static_cast( v & 0xff); - break; - - default: - assert(0 && "invalid integer format length"); - return; - } - break; - } - - case 'I': { - switch (len) { - case 1: { - // 1 byte integers - const std::vector* list = - va_arg(args, const std::vector*); - const UInt32 n = list->size(); - *dst++ = static_cast((n >> 24) & 0xff); - *dst++ = static_cast((n >> 16) & 0xff); - *dst++ = static_cast((n >> 8) & 0xff); - *dst++ = static_cast( n & 0xff); - for (UInt32 i = 0; i < n; ++i) { - *dst++ = (*list)[i]; - } - break; - } - - case 2: { - // 2 byte integers - const std::vector* list = - va_arg(args, const std::vector*); - const UInt32 n = list->size(); - *dst++ = static_cast((n >> 24) & 0xff); - *dst++ = static_cast((n >> 16) & 0xff); - *dst++ = static_cast((n >> 8) & 0xff); - *dst++ = static_cast( n & 0xff); - for (UInt32 i = 0; i < n; ++i) { - const UInt16 v = (*list)[i]; - *dst++ = static_cast((v >> 8) & 0xff); - *dst++ = static_cast( v & 0xff); - } - break; - } - - case 4: { - // 4 byte integers - const std::vector* list = - va_arg(args, const std::vector*); - const UInt32 n = list->size(); - *dst++ = static_cast((n >> 24) & 0xff); - *dst++ = static_cast((n >> 16) & 0xff); - *dst++ = static_cast((n >> 8) & 0xff); - *dst++ = static_cast( n & 0xff); - for (UInt32 i = 0; i < n; ++i) { - const UInt32 v = (*list)[i]; - *dst++ = static_cast((v >> 24) & 0xff); - *dst++ = static_cast((v >> 16) & 0xff); - *dst++ = static_cast((v >> 8) & 0xff); - *dst++ = static_cast( v & 0xff); - } - break; - } - - default: - assert(0 && "invalid integer vector format length"); - return; - } - break; - } - - case 's': { - assert(len == 0); - const CString* src = va_arg(args, CString*); - const UInt32 len = (src != NULL) ? src->size() : 0; - *dst++ = static_cast((len >> 24) & 0xff); - *dst++ = static_cast((len >> 16) & 0xff); - *dst++ = static_cast((len >> 8) & 0xff); - *dst++ = static_cast( len & 0xff); - if (len != 0) { - memcpy(dst, src->data(), len); - dst += len; - } - break; - } - - case 'S': { - assert(len == 0); - const UInt32 len = va_arg(args, UInt32); - const UInt8* src = va_arg(args, UInt8*); - *dst++ = static_cast((len >> 24) & 0xff); - *dst++ = static_cast((len >> 16) & 0xff); - *dst++ = static_cast((len >> 8) & 0xff); - *dst++ = static_cast( len & 0xff); - memcpy(dst, src, len); - dst += len; - break; - } - - case '%': - assert(len == 0); - *dst++ = '%'; - break; - - default: - assert(0 && "invalid format specifier"); - } - - // next format character - ++fmt; - } - else { - // copy regular character - *dst++ = *fmt++; - } - } -} - -UInt32 -CProtocolUtil::eatLength(const char** pfmt) -{ - const char* fmt = *pfmt; - UInt32 n = 0; - for (;;) { - UInt32 d; - switch (*fmt) { - case '0': d = 0; break; - case '1': d = 1; break; - case '2': d = 2; break; - case '3': d = 3; break; - case '4': d = 4; break; - case '5': d = 5; break; - case '6': d = 6; break; - case '7': d = 7; break; - case '8': d = 8; break; - case '9': d = 9; break; - default: *pfmt = fmt; return n; - } - n = 10 * n + d; - ++fmt; - } -} - -void -CProtocolUtil::read(IStream* stream, void* vbuffer, UInt32 count) -{ - assert(stream != NULL); - assert(vbuffer != NULL); - - UInt8* buffer = reinterpret_cast(vbuffer); - while (count > 0) { - // read more - UInt32 n = stream->read(buffer, count); - - // bail if stream has hungup - if (n == 0) { - LOG((CLOG_DEBUG2 "unexpected disconnect in readf(), %d bytes left", count)); - throw XIOEndOfStream(); - } - - // prepare for next read - buffer += n; - count -= n; - } -} - - -// -// XIOReadMismatch -// - -CString -XIOReadMismatch::getWhat() const throw() -{ - return format("XIOReadMismatch", "CProtocolUtil::readf() mismatch"); -} diff --git a/lib/synergy/CProtocolUtil.h b/lib/synergy/CProtocolUtil.h deleted file mode 100644 index d4019b0b..00000000 --- a/lib/synergy/CProtocolUtil.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CPROTOCOLUTIL_H -#define CPROTOCOLUTIL_H - -#include "BasicTypes.h" -#include "XIO.h" -#include - -class IStream; - -//! Synergy protocol utilities -/*! -This class provides various functions for implementing the synergy -protocol. -*/ -class CProtocolUtil { -public: - //! Write formatted data - /*! - Write formatted binary data to a stream. \c fmt consists of - regular characters and format specifiers. Format specifiers - begin with \%. All characters not part of a format specifier - are regular and are transmitted unchanged. - - Format specifiers are: - - \%\% -- literal `\%' - - \%1i -- converts integer argument to 1 byte integer - - \%2i -- converts integer argument to 2 byte integer in NBO - - \%4i -- converts integer argument to 4 byte integer in NBO - - \%1I -- converts std::vector* to 1 byte integers - - \%2I -- converts std::vector* to 2 byte integers in NBO - - \%4I -- converts std::vector* to 4 byte integers in NBO - - \%s -- converts CString* to stream of bytes - - \%S -- converts integer N and const UInt8* to stream of N bytes - */ - static void writef(IStream*, - const char* fmt, ...); - - //! Read formatted data - /*! - Read formatted binary data from a buffer. This performs the - reverse operation of writef(). Returns true if the entire - format was successfully parsed, false otherwise. - - Format specifiers are: - - \%\% -- read (and discard) a literal `\%' - - \%1i -- reads a 1 byte integer; argument is a SInt32* or UInt32* - - \%2i -- reads an NBO 2 byte integer; arg is SInt32* or UInt32* - - \%4i -- reads an NBO 4 byte integer; arg is SInt32* or UInt32* - - \%1I -- reads 1 byte integers; arg is std::vector* - - \%2I -- reads NBO 2 byte integers; arg is std::vector* - - \%4I -- reads NBO 4 byte integers; arg is std::vector* - - \%s -- reads bytes; argument must be a CString*, \b not a char* - */ - static bool readf(IStream*, - const char* fmt, ...); - -private: - static void vwritef(IStream*, - const char* fmt, UInt32 size, va_list); - static void vreadf(IStream*, - const char* fmt, va_list); - - static UInt32 getLength(const char* fmt, va_list); - static void writef(void*, const char* fmt, va_list); - static UInt32 eatLength(const char** fmt); - static void read(IStream*, void*, UInt32); -}; - -//! Mismatched read exception -/*! -Thrown by CProtocolUtil::readf() when the data being read does not -match the format. -*/ -class XIOReadMismatch : public XIO { -public: - // XBase overrides - virtual CString getWhat() const throw(); -}; - -#endif - diff --git a/lib/synergy/CScreen.cpp b/lib/synergy/CScreen.cpp deleted file mode 100644 index bff8daca..00000000 --- a/lib/synergy/CScreen.cpp +++ /dev/null @@ -1,488 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "CScreen.h" -#include "IPlatformScreen.h" -#include "ProtocolTypes.h" -#include "CLog.h" -#include "IEventQueue.h" - -// -// CScreen -// - -CScreen::CScreen(IPlatformScreen* platformScreen) : - m_screen(platformScreen), - m_isPrimary(platformScreen->isPrimary()), - m_enabled(false), - m_entered(m_isPrimary), - m_screenSaverSync(true), - m_fakeInput(false) -{ - assert(m_screen != NULL); - - // reset options - resetOptions(); - - LOG((CLOG_DEBUG "opened display")); -} - -CScreen::~CScreen() -{ - if (m_enabled) { - disable(); - } - assert(!m_enabled); - assert(m_entered == m_isPrimary); - delete m_screen; - LOG((CLOG_DEBUG "closed display")); -} - -void -CScreen::enable() -{ - assert(!m_enabled); - - m_screen->updateKeyMap(); - m_screen->updateKeyState(); - m_screen->enable(); - if (m_isPrimary) { - enablePrimary(); - } - else { - enableSecondary(); - } - - // note activation - m_enabled = true; -} - -void -CScreen::disable() -{ - assert(m_enabled); - - if (!m_isPrimary && m_entered) { - leave(); - } - else if (m_isPrimary && !m_entered) { - enter(0); - } - m_screen->disable(); - if (m_isPrimary) { - disablePrimary(); - } - else { - disableSecondary(); - } - - // note deactivation - m_enabled = false; -} - -void -CScreen::enter(KeyModifierMask toggleMask) -{ - assert(m_entered == false); - LOG((CLOG_INFO "entering screen")); - - // now on screen - m_entered = true; - - m_screen->enter(); - if (m_isPrimary) { - enterPrimary(); - } - else { - enterSecondary(toggleMask); - } -} - -bool -CScreen::leave() -{ - assert(m_entered == true); - LOG((CLOG_INFO "leaving screen")); - - if (!m_screen->leave()) { - return false; - } - if (m_isPrimary) { - leavePrimary(); - } - else { - leaveSecondary(); - } - - // make sure our idea of clipboard ownership is correct - m_screen->checkClipboards(); - - // now not on screen - m_entered = false; - - return true; -} - -void -CScreen::reconfigure(UInt32 activeSides) -{ - assert(m_isPrimary); - m_screen->reconfigure(activeSides); -} - -void -CScreen::warpCursor(SInt32 x, SInt32 y) -{ - assert(m_isPrimary); - m_screen->warpCursor(x, y); -} - -void -CScreen::setClipboard(ClipboardID id, const IClipboard* clipboard) -{ - m_screen->setClipboard(id, clipboard); -} - -void -CScreen::grabClipboard(ClipboardID id) -{ - m_screen->setClipboard(id, NULL); -} - -void -CScreen::screensaver(bool activate) -{ - if (!m_isPrimary) { - // activate/deactivation screen saver iff synchronization enabled - if (m_screenSaverSync) { - m_screen->screensaver(activate); - } - } -} - -void -CScreen::keyDown(KeyID id, KeyModifierMask mask, KeyButton button) -{ - assert(!m_isPrimary || m_fakeInput); - - // check for ctrl+alt+del emulation - if (id == kKeyDelete && - (mask & (KeyModifierControl | KeyModifierAlt)) == - (KeyModifierControl | KeyModifierAlt)) { - LOG((CLOG_DEBUG "emulating ctrl+alt+del press")); - if (m_screen->fakeCtrlAltDel()) { - return; - } - } - m_screen->fakeKeyDown(id, mask, button); -} - -void -CScreen::keyRepeat(KeyID id, - KeyModifierMask mask, SInt32 count, KeyButton button) -{ - assert(!m_isPrimary); - m_screen->fakeKeyRepeat(id, mask, count, button); -} - -void -CScreen::keyUp(KeyID, KeyModifierMask, KeyButton button) -{ - assert(!m_isPrimary || m_fakeInput); - m_screen->fakeKeyUp(button); -} - -void -CScreen::mouseDown(ButtonID button) -{ - assert(!m_isPrimary); - m_screen->fakeMouseButton(button, true); -} - -void -CScreen::mouseUp(ButtonID button) -{ - assert(!m_isPrimary); - m_screen->fakeMouseButton(button, false); -} - -void -CScreen::mouseMove(SInt32 x, SInt32 y) -{ - assert(!m_isPrimary); - m_screen->fakeMouseMove(x, y); -} - -void -CScreen::mouseRelativeMove(SInt32 dx, SInt32 dy) -{ - assert(!m_isPrimary); - m_screen->fakeMouseRelativeMove(dx, dy); -} - -void -CScreen::mouseWheel(SInt32 xDelta, SInt32 yDelta) -{ - assert(!m_isPrimary); - m_screen->fakeMouseWheel(xDelta, yDelta); -} - -void -CScreen::resetOptions() -{ - // reset options - m_halfDuplex = 0; - - // if screen saver synchronization was off then turn it on since - // that's the default option state. - if (!m_screenSaverSync) { - m_screenSaverSync = true; - if (!m_isPrimary) { - m_screen->openScreensaver(false); - } - } - - // let screen handle its own options - m_screen->resetOptions(); -} - -void -CScreen::setOptions(const COptionsList& options) -{ - // update options - bool oldScreenSaverSync = m_screenSaverSync; - for (UInt32 i = 0, n = options.size(); i < n; i += 2) { - if (options[i] == kOptionScreenSaverSync) { - m_screenSaverSync = (options[i + 1] != 0); - LOG((CLOG_DEBUG1 "screen saver synchronization %s", m_screenSaverSync ? "on" : "off")); - } - else if (options[i] == kOptionHalfDuplexCapsLock) { - if (options[i + 1] != 0) { - m_halfDuplex |= KeyModifierCapsLock; - } - else { - m_halfDuplex &= ~KeyModifierCapsLock; - } - LOG((CLOG_DEBUG1 "half-duplex caps-lock %s", ((m_halfDuplex & KeyModifierCapsLock) != 0) ? "on" : "off")); - } - else if (options[i] == kOptionHalfDuplexNumLock) { - if (options[i + 1] != 0) { - m_halfDuplex |= KeyModifierNumLock; - } - else { - m_halfDuplex &= ~KeyModifierNumLock; - } - LOG((CLOG_DEBUG1 "half-duplex num-lock %s", ((m_halfDuplex & KeyModifierNumLock) != 0) ? "on" : "off")); - } - else if (options[i] == kOptionHalfDuplexScrollLock) { - if (options[i + 1] != 0) { - m_halfDuplex |= KeyModifierScrollLock; - } - else { - m_halfDuplex &= ~KeyModifierScrollLock; - } - LOG((CLOG_DEBUG1 "half-duplex scroll-lock %s", ((m_halfDuplex & KeyModifierScrollLock) != 0) ? "on" : "off")); - } - } - - // update half-duplex options - m_screen->setHalfDuplexMask(m_halfDuplex); - - // update screen saver synchronization - if (!m_isPrimary && oldScreenSaverSync != m_screenSaverSync) { - if (m_screenSaverSync) { - m_screen->openScreensaver(false); - } - else { - m_screen->closeScreensaver(); - } - } - - // let screen handle its own options - m_screen->setOptions(options); -} - -void -CScreen::setSequenceNumber(UInt32 seqNum) -{ - m_screen->setSequenceNumber(seqNum); -} - -UInt32 -CScreen::registerHotKey(KeyID key, KeyModifierMask mask) -{ - return m_screen->registerHotKey(key, mask); -} - -void -CScreen::unregisterHotKey(UInt32 id) -{ - m_screen->unregisterHotKey(id); -} - -void -CScreen::fakeInputBegin() -{ - assert(!m_fakeInput); - - m_fakeInput = true; - m_screen->fakeInputBegin(); -} - -void -CScreen::fakeInputEnd() -{ - assert(m_fakeInput); - - m_fakeInput = false; - m_screen->fakeInputEnd(); -} - -bool -CScreen::isOnScreen() const -{ - return m_entered; -} - -bool -CScreen::isLockedToScreen() const -{ - // check for pressed mouse buttons - if (m_screen->isAnyMouseButtonDown()) { - LOG((CLOG_DEBUG "locked by mouse button")); - return true; - } - - // not locked - return false; -} - -SInt32 -CScreen::getJumpZoneSize() const -{ - if (!m_isPrimary) { - return 0; - } - else { - return m_screen->getJumpZoneSize(); - } -} - -void -CScreen::getCursorCenter(SInt32& x, SInt32& y) const -{ - m_screen->getCursorCenter(x, y); -} - -KeyModifierMask -CScreen::getActiveModifiers() const -{ - return m_screen->getActiveModifiers(); -} - -KeyModifierMask -CScreen::pollActiveModifiers() const -{ - return m_screen->pollActiveModifiers(); -} - -void* -CScreen::getEventTarget() const -{ - return m_screen; -} - -bool -CScreen::getClipboard(ClipboardID id, IClipboard* clipboard) const -{ - return m_screen->getClipboard(id, clipboard); -} - -void -CScreen::getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h) const -{ - m_screen->getShape(x, y, w, h); -} - -void -CScreen::getCursorPos(SInt32& x, SInt32& y) const -{ - m_screen->getCursorPos(x, y); -} - -void -CScreen::enablePrimary() -{ - // get notified of screen saver activation/deactivation - m_screen->openScreensaver(true); - - // claim screen changed size - EVENTQUEUE->addEvent(CEvent(getShapeChangedEvent(), getEventTarget())); -} - -void -CScreen::enableSecondary() -{ - // assume primary has all clipboards - for (ClipboardID id = 0; id < kClipboardEnd; ++id) { - grabClipboard(id); - } - - // disable the screen saver if synchronization is enabled - if (m_screenSaverSync) { - m_screen->openScreensaver(false); - } -} - -void -CScreen::disablePrimary() -{ - // done with screen saver - m_screen->closeScreensaver(); -} - -void -CScreen::disableSecondary() -{ - // done with screen saver - m_screen->closeScreensaver(); -} - -void -CScreen::enterPrimary() -{ - // do nothing -} - -void -CScreen::enterSecondary(KeyModifierMask) -{ - // do nothing -} - -void -CScreen::leavePrimary() -{ - // we don't track keys while on the primary screen so update our - // idea of them now. this is particularly to update the state of - // the toggle modifiers. - m_screen->updateKeyState(); -} - -void -CScreen::leaveSecondary() -{ - // release any keys we think are still down - m_screen->fakeAllKeysUp(); -} diff --git a/lib/synergy/CScreen.h b/lib/synergy/CScreen.h deleted file mode 100644 index 4d216f8b..00000000 --- a/lib/synergy/CScreen.h +++ /dev/null @@ -1,304 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CSCREEN_H -#define CSCREEN_H - -#include "IScreen.h" -#include "ClipboardTypes.h" -#include "KeyTypes.h" -#include "MouseTypes.h" -#include "OptionTypes.h" - -class IClipboard; -class IPlatformScreen; - -//! Platform independent screen -/*! -This is a platform independent screen. It can work as either a -primary or secondary screen. -*/ -class CScreen : public IScreen { -public: - CScreen(IPlatformScreen* platformScreen); - virtual ~CScreen(); - - //! @name manipulators - //@{ - - //! Activate screen - /*! - Activate the screen, preparing it to report system and user events. - For a secondary screen it also means disabling the screen saver if - synchronizing it and preparing to synthesize events. - */ - void enable(); - - //! Deactivate screen - /*! - Undoes the operations in activate() and events are no longer - reported. It also releases keys that are logically pressed. - */ - void disable(); - - //! Enter screen - /*! - Called when the user navigates to this screen. \p toggleMask has the - toggle keys that should be turned on on the secondary screen. - */ - void enter(KeyModifierMask toggleMask); - - //! Leave screen - /*! - Called when the user navigates off this screen. - */ - bool leave(); - - //! Update configuration - /*! - This is called when the configuration has changed. \c activeSides - is a bitmask of EDirectionMask indicating which sides of the - primary screen are linked to clients. - */ - void reconfigure(UInt32 activeSides); - - //! Warp cursor - /*! - Warps the cursor to the absolute coordinates \c x,y. Also - discards input events up to and including the warp before - returning. - */ - void warpCursor(SInt32 x, SInt32 y); - - //! Set clipboard - /*! - Sets the system's clipboard contents. This is usually called - soon after an enter(). - */ - void setClipboard(ClipboardID, const IClipboard*); - - //! Grab clipboard - /*! - Grabs (i.e. take ownership of) the system clipboard. - */ - void grabClipboard(ClipboardID); - - //! Activate/deactivate screen saver - /*! - Forcibly activates the screen saver if \c activate is true otherwise - forcibly deactivates it. - */ - void screensaver(bool activate); - - //! Notify of key press - /*! - Synthesize key events to generate a press of key \c id. If possible - match the given modifier mask. The KeyButton identifies the physical - key on the server that generated this key down. The client must - ensure that a key up or key repeat that uses the same KeyButton will - synthesize an up or repeat for the same client key synthesized by - keyDown(). - */ - void keyDown(KeyID id, KeyModifierMask, KeyButton); - - //! Notify of key repeat - /*! - Synthesize key events to generate a press and release of key \c id - \c count times. If possible match the given modifier mask. - */ - void keyRepeat(KeyID id, KeyModifierMask, - SInt32 count, KeyButton); - - //! Notify of key release - /*! - Synthesize key events to generate a release of key \c id. If possible - match the given modifier mask. - */ - void keyUp(KeyID id, KeyModifierMask, KeyButton); - - //! Notify of mouse press - /*! - Synthesize mouse events to generate a press of mouse button \c id. - */ - void mouseDown(ButtonID id); - - //! Notify of mouse release - /*! - Synthesize mouse events to generate a release of mouse button \c id. - */ - void mouseUp(ButtonID id); - - //! Notify of mouse motion - /*! - Synthesize mouse events to generate mouse motion to the absolute - screen position \c xAbs,yAbs. - */ - void mouseMove(SInt32 xAbs, SInt32 yAbs); - - //! Notify of mouse motion - /*! - Synthesize mouse events to generate mouse motion by the relative - amount \c xRel,yRel. - */ - void mouseRelativeMove(SInt32 xRel, SInt32 yRel); - - //! Notify of mouse wheel motion - /*! - Synthesize mouse events to generate mouse wheel motion of \c xDelta - and \c yDelta. Deltas are positive for motion away from the user or - to the right and negative for motion towards the user or to the left. - Each wheel click should generate a delta of +/-120. - */ - void mouseWheel(SInt32 xDelta, SInt32 yDelta); - - //! Notify of options changes - /*! - Resets all options to their default values. - */ - void resetOptions(); - - //! Notify of options changes - /*! - Set options to given values. Ignores unknown options and doesn't - modify options that aren't given in \c options. - */ - void setOptions(const COptionsList& options); - - //! Set clipboard sequence number - /*! - Sets the sequence number to use in subsequent clipboard events. - */ - void setSequenceNumber(UInt32); - - //! Register a system hotkey - /*! - Registers a system-wide hotkey for key \p key with modifiers \p mask. - Returns an id used to unregister the hotkey. - */ - UInt32 registerHotKey(KeyID key, KeyModifierMask mask); - - //! Unregister a system hotkey - /*! - Unregisters a previously registered hot key. - */ - void unregisterHotKey(UInt32 id); - - //! Prepare to synthesize input on primary screen - /*! - Prepares the primary screen to receive synthesized input. We do not - want to receive this synthesized input as user input so this method - ensures that we ignore it. Calls to \c fakeInputBegin() may not be - nested. - */ - void fakeInputBegin(); - - //! Done synthesizing input on primary screen - /*! - Undoes whatever \c fakeInputBegin() did. - */ - void fakeInputEnd(); - - //@} - //! @name accessors - //@{ - - //! Test if cursor on screen - /*! - Returns true iff the cursor is on the screen. - */ - bool isOnScreen() const; - - //! Get screen lock state - /*! - Returns true if there's any reason that the user should not be - allowed to leave the screen (usually because a button or key is - pressed). If this method returns true it logs a message as to - why at the CLOG_DEBUG level. - */ - bool isLockedToScreen() const; - - //! Get jump zone size - /*! - Return the jump zone size, the size of the regions on the edges of - the screen that cause the cursor to jump to another screen. - */ - SInt32 getJumpZoneSize() const; - - //! Get cursor center position - /*! - Return the cursor center position which is where we park the - cursor to compute cursor motion deltas and should be far from - the edges of the screen, typically the center. - */ - void getCursorCenter(SInt32& x, SInt32& y) const; - - //! Get the active modifiers - /*! - Returns the modifiers that are currently active according to our - shadowed state. - */ - KeyModifierMask getActiveModifiers() const; - - //! Get the active modifiers from OS - /*! - Returns the modifiers that are currently active according to the - operating system. - */ - KeyModifierMask pollActiveModifiers() const; - - //@} - - // IScreen overrides - virtual void* getEventTarget() const; - virtual bool getClipboard(ClipboardID id, IClipboard*) const; - virtual void getShape(SInt32& x, SInt32& y, - SInt32& width, SInt32& height) const; - virtual void getCursorPos(SInt32& x, SInt32& y) const; - -protected: - void enablePrimary(); - void enableSecondary(); - void disablePrimary(); - void disableSecondary(); - - void enterPrimary(); - void enterSecondary(KeyModifierMask toggleMask); - void leavePrimary(); - void leaveSecondary(); - -private: - // our platform dependent screen - IPlatformScreen* m_screen; - - // true if screen is being used as a primary screen, false otherwise - bool m_isPrimary; - - // true if screen is enabled - bool m_enabled; - - // true if the cursor is on this screen - bool m_entered; - - // true if screen saver should be synchronized to server - bool m_screenSaverSync; - - // note toggle keys that toggles on up/down (false) or on - // transition (true) - KeyModifierMask m_halfDuplex; - - // true if we're faking input on a primary screen - bool m_fakeInput; -}; - -#endif diff --git a/lib/synergy/ClipboardTypes.h b/lib/synergy/ClipboardTypes.h deleted file mode 100644 index a638e821..00000000 --- a/lib/synergy/ClipboardTypes.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef CLIPBOARDTYPES_H -#define CLIPBOARDTYPES_H - -#include "BasicTypes.h" - -//! Clipboard ID -/*! -Type to hold a clipboard identifier. -*/ -typedef UInt8 ClipboardID; - -//! @name Clipboard identifiers -//@{ -// clipboard identifiers. kClipboardClipboard is what is normally -// considered the clipboard (e.g. the cut/copy/paste menu items -// affect it). kClipboardSelection is the selection on those -// platforms that can treat the selection as a clipboard (e.g. X -// windows). clipboard identifiers must be sequential starting -// at zero. -static const ClipboardID kClipboardClipboard = 0; -static const ClipboardID kClipboardSelection = 1; - -// the number of clipboards (i.e. one greater than the last clipboard id) -static const ClipboardID kClipboardEnd = 2; -//@} - -#endif diff --git a/lib/synergy/IClient.h b/lib/synergy/IClient.h deleted file mode 100644 index 81cbf06a..00000000 --- a/lib/synergy/IClient.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef ICLIENT_H -#define ICLIENT_H - -#include "IScreen.h" -#include "ClipboardTypes.h" -#include "KeyTypes.h" -#include "MouseTypes.h" -#include "OptionTypes.h" -#include "CString.h" - -//! Client interface -/*! -This interface defines the methods necessary for the server to -communicate with a client. -*/ -class IClient : public IScreen { -public: - //! @name manipulators - //@{ - - //! Enter screen - /*! - Enter the screen. The cursor should be warped to \p xAbs,yAbs. - \p mask is the expected toggle button state and the client should - update its state to match. \p forScreensaver is true iff the - screen is being entered because the screen saver is starting. - Subsequent clipboard events should report \p seqNum. - */ - virtual void enter(SInt32 xAbs, SInt32 yAbs, - UInt32 seqNum, KeyModifierMask mask, - bool forScreensaver) = 0; - - //! Leave screen - /*! - Leave the screen. Return false iff the user may not leave the - client's screen (because, for example, a button is down). - */ - virtual bool leave() = 0; - - //! Set clipboard - /*! - Update the client's clipboard. This implies that the client's - clipboard is now up to date. If the client's clipboard was - already known to be up to date then this may do nothing. \c data - has marshalled clipboard data. - */ - virtual void setClipboard(ClipboardID, const IClipboard*) = 0; - - //! Grab clipboard - /*! - Grab (i.e. take ownership of) the client's clipboard. Since this - is called when another client takes ownership of the clipboard it - implies that the client's clipboard is out of date. - */ - virtual void grabClipboard(ClipboardID) = 0; - - //! Mark clipboard dirty - /*! - Mark the client's clipboard as dirty (out of date) or clean (up to - date). - */ - virtual void setClipboardDirty(ClipboardID, bool dirty) = 0; - - //! Notify of key press - /*! - Synthesize key events to generate a press of key \c id. If possible - match the given modifier mask. The KeyButton identifies the physical - key on the server that generated this key down. The client must - ensure that a key up or key repeat that uses the same KeyButton will - synthesize an up or repeat for the same client key synthesized by - keyDown(). - */ - virtual void keyDown(KeyID id, KeyModifierMask, KeyButton) = 0; - - //! Notify of key repeat - /*! - Synthesize key events to generate a press and release of key \c id - \c count times. If possible match the given modifier mask. - */ - virtual void keyRepeat(KeyID id, KeyModifierMask, - SInt32 count, KeyButton) = 0; - - //! Notify of key release - /*! - Synthesize key events to generate a release of key \c id. If possible - match the given modifier mask. - */ - virtual void keyUp(KeyID id, KeyModifierMask, KeyButton) = 0; - - //! Notify of mouse press - /*! - Synthesize mouse events to generate a press of mouse button \c id. - */ - virtual void mouseDown(ButtonID id) = 0; - - //! Notify of mouse release - /*! - Synthesize mouse events to generate a release of mouse button \c id. - */ - virtual void mouseUp(ButtonID id) = 0; - - //! Notify of mouse motion - /*! - Synthesize mouse events to generate mouse motion to the absolute - screen position \c xAbs,yAbs. - */ - virtual void mouseMove(SInt32 xAbs, SInt32 yAbs) = 0; - - //! Notify of mouse motion - /*! - Synthesize mouse events to generate mouse motion by the relative - amount \c xRel,yRel. - */ - virtual void mouseRelativeMove(SInt32 xRel, SInt32 yRel) = 0; - - //! Notify of mouse wheel motion - /*! - Synthesize mouse events to generate mouse wheel motion of \c xDelta - and \c yDelta. Deltas are positive for motion away from the user or - to the right and negative for motion towards the user or to the left. - Each wheel click should generate a delta of +/-120. - */ - virtual void mouseWheel(SInt32 xDelta, SInt32 yDelta) = 0; - - //! Notify of screen saver change - virtual void screensaver(bool activate) = 0; - - //! Notify of options changes - /*! - Reset all options to their default values. - */ - virtual void resetOptions() = 0; - - //! Notify of options changes - /*! - Set options to given values. Ignore unknown options and don't - modify our options that aren't given in \c options. - */ - virtual void setOptions(const COptionsList& options) = 0; - - //@} - //! @name accessors - //@{ - - //! Get client name - /*! - Return the client's name. - */ - virtual CString getName() const = 0; - - //@} - - // IScreen overrides - virtual void* getEventTarget() const = 0; - virtual bool getClipboard(ClipboardID id, IClipboard*) const = 0; - virtual void getShape(SInt32& x, SInt32& y, - SInt32& width, SInt32& height) const = 0; - virtual void getCursorPos(SInt32& x, SInt32& y) const = 0; -}; - -#endif diff --git a/lib/synergy/IClipboard.cpp b/lib/synergy/IClipboard.cpp deleted file mode 100644 index 7a055612..00000000 --- a/lib/synergy/IClipboard.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "IClipboard.h" -#include "stdvector.h" - -// -// IClipboard -// - -void -IClipboard::unmarshall(IClipboard* clipboard, const CString& data, Time time) -{ - assert(clipboard != NULL); - - const char* index = data.data(); - - // clear existing data - clipboard->open(time); - clipboard->empty(); - - // read the number of formats - const UInt32 numFormats = readUInt32(index); - index += 4; - - // read each format - for (UInt32 i = 0; i < numFormats; ++i) { - // get the format id - IClipboard::EFormat format = - static_cast(readUInt32(index)); - index += 4; - - // get the size of the format data - UInt32 size = readUInt32(index); - index += 4; - - // save the data if it's a known format. if either the client - // or server supports more clipboard formats than the other - // then one of them will get a format >= kNumFormats here. - if (format add(format, CString(index, size)); - } - index += size; - } - - // done - clipboard->close(); -} - -CString -IClipboard::marshall(const IClipboard* clipboard) -{ - assert(clipboard != NULL); - - CString data; - - std::vector formatData; - formatData.resize(IClipboard::kNumFormats); - // FIXME -- use current time - clipboard->open(0); - - // compute size of marshalled data - UInt32 size = 4; - UInt32 numFormats = 0; - for (UInt32 format = 0; format != IClipboard::kNumFormats; ++format) { - if (clipboard->has(static_cast(format))) { - ++numFormats; - formatData[format] = - clipboard->get(static_cast(format)); - size += 4 + 4 + formatData[format].size(); - } - } - - // allocate space - data.reserve(size); - - // marshall the data - writeUInt32(&data, numFormats); - for (UInt32 format = 0; format != IClipboard::kNumFormats; ++format) { - if (clipboard->has(static_cast(format))) { - writeUInt32(&data, format); - writeUInt32(&data, formatData[format].size()); - data += formatData[format]; - } - } - clipboard->close(); - - return data; -} - -bool -IClipboard::copy(IClipboard* dst, const IClipboard* src) -{ - assert(dst != NULL); - assert(src != NULL); - - return copy(dst, src, src->getTime()); -} - -bool -IClipboard::copy(IClipboard* dst, const IClipboard* src, Time time) -{ - assert(dst != NULL); - assert(src != NULL); - - bool success = false; - if (src->open(time)) { - if (dst->open(time)) { - if (dst->empty()) { - for (SInt32 format = 0; - format != IClipboard::kNumFormats; ++format) { - IClipboard::EFormat eFormat = (IClipboard::EFormat)format; - if (src->has(eFormat)) { - dst->add(eFormat, src->get(eFormat)); - } - } - success = true; - } - dst->close(); - } - src->close(); - } - - return success; -} - -UInt32 -IClipboard::readUInt32(const char* buf) -{ - const unsigned char* ubuf = reinterpret_cast(buf); - return (static_cast(ubuf[0]) << 24) | - (static_cast(ubuf[1]) << 16) | - (static_cast(ubuf[2]) << 8) | - static_cast(ubuf[3]); -} - -void -IClipboard::writeUInt32(CString* buf, UInt32 v) -{ - *buf += static_cast((v >> 24) & 0xff); - *buf += static_cast((v >> 16) & 0xff); - *buf += static_cast((v >> 8) & 0xff); - *buf += static_cast( v & 0xff); -} diff --git a/lib/synergy/IClipboard.h b/lib/synergy/IClipboard.h deleted file mode 100644 index c883da8a..00000000 --- a/lib/synergy/IClipboard.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef ICLIPBOARD_H -#define ICLIPBOARD_H - -#include "IInterface.h" -#include "CString.h" -#include "BasicTypes.h" - -//! Clipboard interface -/*! -This interface defines the methods common to all clipboards. -*/ -class IClipboard : public IInterface { -public: - //! Timestamp type - /*! - Timestamp type. Timestamps are in milliseconds from some - arbitrary starting time. Timestamps will wrap around to 0 - after about 49 3/4 days. - */ - typedef UInt32 Time; - - //! Clipboard formats - /*! - The list of known clipboard formats. kNumFormats must be last and - formats must be sequential starting from zero. Clipboard data set - via add() and retrieved via get() must be in one of these formats. - Platform dependent clipboard subclasses can and should present any - suitable formats derivable from these formats. - - \c kText is a text format encoded in UTF-8. Newlines are LF (not - CR or LF/CR). - - \k kBitmap is an image format. The data is a BMP file without the - 14 byte header (i.e. starting at the INFOHEADER) and with the image - data immediately following the 40 byte INFOHEADER. - - \k kHTML is a text format encoded in UTF-8 and containing a valid - HTML fragment (but not necessarily a complete HTML document). - Newlines are LF. - */ - enum EFormat { - kText, //!< Text format, UTF-8, newline is LF - kBitmap, //!< Bitmap format, BMP 24/32bpp, BI_RGB - kHTML, //!< HTML format, HTML fragment, UTF-8, newline is LF - kNumFormats //!< The number of clipboard formats - }; - - //! @name manipulators - //@{ - - //! Empty clipboard - /*! - Take ownership of the clipboard and clear all data from it. - This must be called between a successful open() and close(). - Return false if the clipboard ownership could not be taken; - the clipboard should not be emptied in this case. - */ - virtual bool empty() = 0; - - //! Add data - /*! - Add data in the given format to the clipboard. May only be - called after a successful empty(). - */ - virtual void add(EFormat, const CString& data) = 0; - - //@} - //! @name accessors - //@{ - - //! Open clipboard - /*! - Open the clipboard. Return true iff the clipboard could be - opened. If open() returns true then the client must call - close() at some later time; if it returns false then close() - must not be called. \c time should be the current time or - a time in the past when the open should effectively have taken - place. - */ - virtual bool open(Time time) const = 0; - - //! Close clipboard - /*! - Close the clipboard. close() must match a preceding successful - open(). This signals that the clipboard has been filled with - all the necessary data or all data has been read. It does not - mean the clipboard ownership should be released (if it was - taken). - */ - virtual void close() const = 0; - - //! Get time - /*! - Return the timestamp passed to the last successful open(). - */ - virtual Time getTime() const = 0; - - //! Check for data - /*! - Return true iff the clipboard contains data in the given - format. Must be called between a successful open() and close(). - */ - virtual bool has(EFormat) const = 0; - - //! Get data - /*! - Return the data in the given format. Returns the empty string - if there is no data in that format. Must be called between - a successful open() and close(). - */ - virtual CString get(EFormat) const = 0; - - //! Marshall clipboard data - /*! - Merge \p clipboard's data into a single buffer that can be later - unmarshalled to restore the clipboard and return the buffer. - */ - static CString marshall(const IClipboard* clipboard); - - //! Unmarshall clipboard data - /*! - Extract marshalled clipboard data and store it in \p clipboard. - Sets the clipboard time to \c time. - */ - static void unmarshall(IClipboard* clipboard, - const CString& data, Time time); - - //! Copy clipboard - /*! - Transfers all the data in one clipboard to another. The - clipboards can be of any concrete clipboard type (and - they don't have to be the same type). This also sets - the destination clipboard's timestamp to source clipboard's - timestamp. Returns true iff the copy succeeded. - */ - static bool copy(IClipboard* dst, const IClipboard* src); - - //! Copy clipboard - /*! - Transfers all the data in one clipboard to another. The - clipboards can be of any concrete clipboard type (and they - don't have to be the same type). This also sets the - timestamp to \c time. Returns true iff the copy succeeded. - */ - static bool copy(IClipboard* dst, const IClipboard* src, Time); - - //@} - -private: - static UInt32 readUInt32(const char*); - static void writeUInt32(CString*, UInt32); -}; - -#endif diff --git a/lib/synergy/IKeyState.cpp b/lib/synergy/IKeyState.cpp deleted file mode 100644 index d44e17d3..00000000 --- a/lib/synergy/IKeyState.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "IKeyState.h" -#include - -// -// IKeyState -// - -CEvent::Type IKeyState::s_keyDownEvent = CEvent::kUnknown; -CEvent::Type IKeyState::s_keyUpEvent = CEvent::kUnknown; -CEvent::Type IKeyState::s_keyRepeatEvent = CEvent::kUnknown; - -CEvent::Type -IKeyState::getKeyDownEvent() -{ - return CEvent::registerTypeOnce(s_keyDownEvent, - "IKeyState::keyDown"); -} - -CEvent::Type -IKeyState::getKeyUpEvent() -{ - return CEvent::registerTypeOnce(s_keyUpEvent, - "IKeyState::keyUp"); -} - -CEvent::Type -IKeyState::getKeyRepeatEvent() -{ - return CEvent::registerTypeOnce(s_keyRepeatEvent, - "IKeyState::keyRepeat"); -} - - -// -// IKeyState::CKeyInfo -// - -IKeyState::CKeyInfo* -IKeyState::CKeyInfo::alloc(KeyID id, - KeyModifierMask mask, KeyButton button, SInt32 count) -{ - CKeyInfo* info = (CKeyInfo*)malloc(sizeof(CKeyInfo)); - info->m_key = id; - info->m_mask = mask; - info->m_button = button; - info->m_count = count; - info->m_screens = NULL; - info->m_screensBuffer[0] = '\0'; - return info; -} - -IKeyState::CKeyInfo* -IKeyState::CKeyInfo::alloc(KeyID id, - KeyModifierMask mask, KeyButton button, SInt32 count, - const std::set& destinations) -{ - CString screens = join(destinations); - - // build structure - CKeyInfo* info = (CKeyInfo*)malloc(sizeof(CKeyInfo) + screens.size()); - info->m_key = id; - info->m_mask = mask; - info->m_button = button; - info->m_count = count; - info->m_screens = info->m_screensBuffer; - strcpy(info->m_screensBuffer, screens.c_str()); - return info; -} - -IKeyState::CKeyInfo* -IKeyState::CKeyInfo::alloc(const CKeyInfo& x) -{ - CKeyInfo* info = (CKeyInfo*)malloc(sizeof(CKeyInfo) + - strlen(x.m_screensBuffer)); - info->m_key = x.m_key; - info->m_mask = x.m_mask; - info->m_button = x.m_button; - info->m_count = x.m_count; - info->m_screens = x.m_screens ? info->m_screensBuffer : NULL; - strcpy(info->m_screensBuffer, x.m_screensBuffer); - return info; -} - -bool -IKeyState::CKeyInfo::isDefault(const char* screens) -{ - return (screens == NULL || screens[0] == '\0'); -} - -bool -IKeyState::CKeyInfo::contains(const char* screens, const CString& name) -{ - // special cases - if (isDefault(screens)) { - return false; - } - if (screens[0] == '*') { - return true; - } - - // search - CString match; - match.reserve(name.size() + 2); - match += ":"; - match += name; - match += ":"; - return (strstr(screens, match.c_str()) != NULL); -} - -bool -IKeyState::CKeyInfo::equal(const CKeyInfo* a, const CKeyInfo* b) -{ - return (a->m_key == b->m_key && - a->m_mask == b->m_mask && - a->m_button == b->m_button && - a->m_count == b->m_count && - strcmp(a->m_screensBuffer, b->m_screensBuffer) == 0); -} - -CString -IKeyState::CKeyInfo::join(const std::set& destinations) -{ - // collect destinations into a string. names are surrounded by ':' - // which makes searching easy. the string is empty if there are no - // destinations and "*" means all destinations. - CString screens; - for (std::set::const_iterator i = destinations.begin(); - i != destinations.end(); ++i) { - if (*i == "*") { - screens = "*"; - break; - } - else { - if (screens.empty()) { - screens = ":"; - } - screens += *i; - screens += ":"; - } - } - return screens; -} - -void -IKeyState::CKeyInfo::split(const char* screens, std::set& dst) -{ - dst.clear(); - if (isDefault(screens)) { - return; - } - if (screens[0] == '*') { - dst.insert("*"); - return; - } - - const char* i = screens + 1; - while (*i != '\0') { - const char* j = strchr(i, ':'); - dst.insert(CString(i, j - i)); - i = j + 1; - } -} diff --git a/lib/synergy/IKeyState.h b/lib/synergy/IKeyState.h deleted file mode 100644 index 2b282487..00000000 --- a/lib/synergy/IKeyState.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef IKEYSTATE_H -#define IKEYSTATE_H - -#include "IInterface.h" -#include "KeyTypes.h" -#include "CEvent.h" -#include "CString.h" -#include "stdset.h" - -//! Key state interface -/*! -This interface provides access to set and query the keyboard state and -to synthesize key events. -*/ -class IKeyState : public IInterface { -public: - enum { - kNumButtons = 0x200 - }; - - //! Key event data - class CKeyInfo { - public: - static CKeyInfo* alloc(KeyID, KeyModifierMask, KeyButton, SInt32 count); - static CKeyInfo* alloc(KeyID, KeyModifierMask, KeyButton, SInt32 count, - const std::set& destinations); - static CKeyInfo* alloc(const CKeyInfo&); - - static bool isDefault(const char* screens); - static bool contains(const char* screens, const CString& name); - static bool equal(const CKeyInfo*, const CKeyInfo*); - static CString join(const std::set& destinations); - static void split(const char* screens, std::set&); - - public: - KeyID m_key; - KeyModifierMask m_mask; - KeyButton m_button; - SInt32 m_count; - char* m_screens; - char m_screensBuffer[1]; - }; - - typedef std::set KeyButtonSet; - - //! @name manipulators - //@{ - - //! Update the keyboard map - /*! - Causes the key state to get updated to reflect the current keyboard - mapping. - */ - virtual void updateKeyMap() = 0; - - //! Update the key state - /*! - Causes the key state to get updated to reflect the physical keyboard - state. - */ - virtual void updateKeyState() = 0; - - //! Set half-duplex mask - /*! - Sets which modifier toggle keys are half-duplex. A half-duplex - toggle key doesn't report a key release when toggled on and - doesn't report a key press when toggled off. - */ - virtual void setHalfDuplexMask(KeyModifierMask) = 0; - - //! Fake a key press - /*! - Synthesizes a key press event and updates the key state. - */ - virtual void fakeKeyDown(KeyID id, KeyModifierMask mask, - KeyButton button) = 0; - - //! Fake a key repeat - /*! - Synthesizes a key repeat event and updates the key state. - */ - virtual void fakeKeyRepeat(KeyID id, KeyModifierMask mask, - SInt32 count, KeyButton button) = 0; - - //! Fake a key release - /*! - Synthesizes a key release event and updates the key state. - */ - virtual void fakeKeyUp(KeyButton button) = 0; - - //! Fake key releases for all fake pressed keys - /*! - Synthesizes a key release event for every key that is synthetically - pressed and updates the key state. - */ - virtual void fakeAllKeysUp() = 0; - - //! Fake ctrl+alt+del - /*! - Synthesize a press of ctrl+alt+del. Return true if processing is - complete and false if normal key processing should continue. - */ - virtual bool fakeCtrlAltDel() = 0; - - //@} - //! @name accessors - //@{ - - //! Test if key is pressed - /*! - Returns true iff the given key is down. Half-duplex toggles - always return false. - */ - virtual bool isKeyDown(KeyButton) const = 0; - - //! Get the active modifiers - /*! - Returns the modifiers that are currently active according to our - shadowed state. - */ - virtual KeyModifierMask - getActiveModifiers() const = 0; - - //! Get the active modifiers from OS - /*! - Returns the modifiers that are currently active according to the - operating system. - */ - virtual KeyModifierMask - pollActiveModifiers() const = 0; - - //! Get the active keyboard layout from OS - /*! - Returns the active keyboard layout according to the operating system. - */ - virtual SInt32 pollActiveGroup() const = 0; - - //! Get the keys currently pressed from OS - /*! - Adds any keys that are currently pressed according to the operating - system to \p pressedKeys. - */ - virtual void pollPressedKeys(KeyButtonSet& pressedKeys) const = 0; - - //! Get key down event type. Event data is CKeyInfo*, count == 1. - static CEvent::Type getKeyDownEvent(); - //! Get key up event type. Event data is CKeyInfo*, count == 1. - static CEvent::Type getKeyUpEvent(); - //! Get key repeat event type. Event data is CKeyInfo*. - static CEvent::Type getKeyRepeatEvent(); - - //@} - -private: - static CEvent::Type s_keyDownEvent; - static CEvent::Type s_keyUpEvent; - static CEvent::Type s_keyRepeatEvent; -}; - -#endif diff --git a/lib/synergy/IPlatformScreen.h b/lib/synergy/IPlatformScreen.h deleted file mode 100644 index b4d1b785..00000000 --- a/lib/synergy/IPlatformScreen.h +++ /dev/null @@ -1,210 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef IPLATFORMSCREEN_H -#define IPLATFORMSCREEN_H - -#include "IScreen.h" -#include "IPrimaryScreen.h" -#include "ISecondaryScreen.h" -#include "IKeyState.h" -#include "ClipboardTypes.h" -#include "OptionTypes.h" - -class IClipboard; - -//! Screen interface -/*! -This interface defines the methods common to all platform dependent -screen implementations that are used by both primary and secondary -screens. -*/ -class IPlatformScreen : public IScreen, - public IPrimaryScreen, public ISecondaryScreen, - public IKeyState { -public: - //! @name manipulators - //@{ - - //! Enable screen - /*! - Enable the screen, preparing it to report system and user events. - For a secondary screen it also means preparing to synthesize events - and hiding the cursor. - */ - virtual void enable() = 0; - - //! Disable screen - /*! - Undoes the operations in enable() and events should no longer - be reported. - */ - virtual void disable() = 0; - - //! Enter screen - /*! - Called when the user navigates to this screen. - */ - virtual void enter() = 0; - - //! Leave screen - /*! - Called when the user navigates off the screen. Returns true on - success, false on failure. A typical reason for failure is being - unable to install the keyboard and mouse snoopers on a primary - screen. Secondary screens should not fail. - */ - virtual bool leave() = 0; - - //! Set clipboard - /*! - Set the contents of the system clipboard indicated by \c id. - */ - virtual bool setClipboard(ClipboardID id, const IClipboard*) = 0; - - //! Check clipboard owner - /*! - Check ownership of all clipboards and post grab events for any that - have changed. This is used as a backup in case the system doesn't - reliably report clipboard ownership changes. - */ - virtual void checkClipboards() = 0; - - //! Open screen saver - /*! - Open the screen saver. If \c notify is true then this object must - send events when the screen saver activates or deactivates until - \c closeScreensaver() is called. If \c notify is false then the - screen saver is disabled and restored on \c closeScreensaver(). - */ - virtual void openScreensaver(bool notify) = 0; - - //! Close screen saver - /*! - // Close the screen saver. Stop reporting screen saver activation - and deactivation and, if the screen saver was disabled by - openScreensaver(), enable the screen saver. - */ - virtual void closeScreensaver() = 0; - - //! Activate/deactivate screen saver - /*! - Forcibly activate the screen saver if \c activate is true otherwise - forcibly deactivate it. - */ - virtual void screensaver(bool activate) = 0; - - //! Notify of options changes - /*! - Reset all options to their default values. - */ - virtual void resetOptions() = 0; - - //! Notify of options changes - /*! - Set options to given values. Ignore unknown options and don't - modify options that aren't given in \c options. - */ - virtual void setOptions(const COptionsList& options) = 0; - - //! Set clipboard sequence number - /*! - Sets the sequence number to use in subsequent clipboard events. - */ - virtual void setSequenceNumber(UInt32) = 0; - - //@} - //! @name accessors - //@{ - - //! Test if is primary screen - /*! - Return true iff this screen is a primary screen. - */ - virtual bool isPrimary() const = 0; - - //@} - - // IScreen overrides - virtual void* getEventTarget() const = 0; - virtual bool getClipboard(ClipboardID id, IClipboard*) const = 0; - virtual void getShape(SInt32& x, SInt32& y, - SInt32& width, SInt32& height) const = 0; - virtual void getCursorPos(SInt32& x, SInt32& y) const = 0; - - // IPrimaryScreen overrides - virtual void reconfigure(UInt32 activeSides) = 0; - virtual void warpCursor(SInt32 x, SInt32 y) = 0; - virtual UInt32 registerHotKey(KeyID key, KeyModifierMask mask) = 0; - virtual void unregisterHotKey(UInt32 id) = 0; - virtual void fakeInputBegin() = 0; - virtual void fakeInputEnd() = 0; - virtual SInt32 getJumpZoneSize() const = 0; - virtual bool isAnyMouseButtonDown() const = 0; - virtual void getCursorCenter(SInt32& x, SInt32& y) const = 0; - - // ISecondaryScreen overrides - virtual void fakeMouseButton(ButtonID id, bool press) const = 0; - virtual void fakeMouseMove(SInt32 x, SInt32 y) const = 0; - virtual void fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const = 0; - virtual void fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const = 0; - - // IKeyState overrides - virtual void updateKeyMap() = 0; - virtual void updateKeyState() = 0; - virtual void setHalfDuplexMask(KeyModifierMask) = 0; - virtual void fakeKeyDown(KeyID id, KeyModifierMask mask, - KeyButton button) = 0; - virtual void fakeKeyRepeat(KeyID id, KeyModifierMask mask, - SInt32 count, KeyButton button) = 0; - virtual void fakeKeyUp(KeyButton button) = 0; - virtual void fakeAllKeysUp() = 0; - virtual bool fakeCtrlAltDel() = 0; - virtual bool isKeyDown(KeyButton) const = 0; - virtual KeyModifierMask - getActiveModifiers() const = 0; - virtual KeyModifierMask - pollActiveModifiers() const = 0; - virtual SInt32 pollActiveGroup() const = 0; - virtual void pollPressedKeys(KeyButtonSet& pressedKeys) const = 0; - -protected: - //! Handle system event - /*! - A platform screen is expected to install a handler for system - events in its c'tor like so: - \code - EVENTQUEUE->adoptHandler(CEvent::kSystem, - IEventQueue::getSystemTarget(), - new TMethodEventJob(this, - &CXXXPlatformScreen::handleSystemEvent)); - \endcode - It should remove the handler in its d'tor. Override the - \c handleSystemEvent() method to process system events. - It should post the events \c IScreen as appropriate. - - A primary screen has further responsibilities. It should post - the events in \c IPrimaryScreen as appropriate. It should also - call \c onKey() on its \c CKeyState whenever a key is pressed - or released (but not for key repeats). And it should call - \c updateKeyMap() on its \c CKeyState if necessary when the keyboard - mapping changes. - - The target of all events should be the value returned by - \c getEventTarget(). - */ - virtual void handleSystemEvent(const CEvent& event, void*) = 0; -}; - -#endif diff --git a/lib/synergy/IPrimaryScreen.cpp b/lib/synergy/IPrimaryScreen.cpp deleted file mode 100644 index 71b103f3..00000000 --- a/lib/synergy/IPrimaryScreen.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "IPrimaryScreen.h" - -// -// IPrimaryScreen -// - -CEvent::Type IPrimaryScreen::s_buttonDownEvent = CEvent::kUnknown; -CEvent::Type IPrimaryScreen::s_buttonUpEvent = CEvent::kUnknown; -CEvent::Type IPrimaryScreen::s_motionPrimaryEvent = CEvent::kUnknown; -CEvent::Type IPrimaryScreen::s_motionSecondaryEvent = CEvent::kUnknown; -CEvent::Type IPrimaryScreen::s_wheelEvent = CEvent::kUnknown; -CEvent::Type IPrimaryScreen::s_ssActivatedEvent = CEvent::kUnknown; -CEvent::Type IPrimaryScreen::s_ssDeactivatedEvent = CEvent::kUnknown; -CEvent::Type IPrimaryScreen::s_hotKeyDownEvent = CEvent::kUnknown; -CEvent::Type IPrimaryScreen::s_hotKeyUpEvent = CEvent::kUnknown; -CEvent::Type IPrimaryScreen::s_fakeInputBegin = CEvent::kUnknown; -CEvent::Type IPrimaryScreen::s_fakeInputEnd = CEvent::kUnknown; - -CEvent::Type -IPrimaryScreen::getButtonDownEvent() -{ - return CEvent::registerTypeOnce(s_buttonDownEvent, - "IPrimaryScreen::buttonDown"); -} - -CEvent::Type -IPrimaryScreen::getButtonUpEvent() -{ - return CEvent::registerTypeOnce(s_buttonUpEvent, - "IPrimaryScreen::buttonUp"); -} - -CEvent::Type -IPrimaryScreen::getMotionOnPrimaryEvent() -{ - return CEvent::registerTypeOnce(s_motionPrimaryEvent, - "IPrimaryScreen::motionPrimary"); -} - -CEvent::Type -IPrimaryScreen::getMotionOnSecondaryEvent() -{ - return CEvent::registerTypeOnce(s_motionSecondaryEvent, - "IPrimaryScreen::motionSecondary"); -} - -CEvent::Type -IPrimaryScreen::getWheelEvent() -{ - return CEvent::registerTypeOnce(s_wheelEvent, - "IPrimaryScreen::wheel"); -} - -CEvent::Type -IPrimaryScreen::getScreensaverActivatedEvent() -{ - return CEvent::registerTypeOnce(s_ssActivatedEvent, - "IPrimaryScreen::screensaverActivated"); -} - -CEvent::Type -IPrimaryScreen::getScreensaverDeactivatedEvent() -{ - return CEvent::registerTypeOnce(s_ssDeactivatedEvent, - "IPrimaryScreen::screensaverDeactivated"); -} - -CEvent::Type -IPrimaryScreen::getHotKeyDownEvent() -{ - return CEvent::registerTypeOnce(s_hotKeyDownEvent, - "IPrimaryScreen::hotKeyDown"); -} - -CEvent::Type -IPrimaryScreen::getHotKeyUpEvent() -{ - return CEvent::registerTypeOnce(s_hotKeyUpEvent, - "IPrimaryScreen::hotKeyUp"); -} - -CEvent::Type -IPrimaryScreen::getFakeInputBeginEvent() -{ - return CEvent::registerTypeOnce(s_fakeInputBegin, - "IPrimaryScreen::fakeInputBegin"); -} - -CEvent::Type -IPrimaryScreen::getFakeInputEndEvent() -{ - return CEvent::registerTypeOnce(s_fakeInputEnd, - "IPrimaryScreen::fakeInputEnd"); -} - - -// -// IPrimaryScreen::CButtonInfo -// - -IPrimaryScreen::CButtonInfo* -IPrimaryScreen::CButtonInfo::alloc(ButtonID id, KeyModifierMask mask) -{ - CButtonInfo* info = (CButtonInfo*)malloc(sizeof(CButtonInfo)); - info->m_button = id; - info->m_mask = mask; - return info; -} - -IPrimaryScreen::CButtonInfo* -IPrimaryScreen::CButtonInfo::alloc(const CButtonInfo& x) -{ - CButtonInfo* info = (CButtonInfo*)malloc(sizeof(CButtonInfo)); - info->m_button = x.m_button; - info->m_mask = x.m_mask; - return info; -} - -bool -IPrimaryScreen::CButtonInfo::equal(const CButtonInfo* a, const CButtonInfo* b) -{ - return (a->m_button == b->m_button && a->m_mask == b->m_mask); -} - - -// -// IPrimaryScreen::CMotionInfo -// - -IPrimaryScreen::CMotionInfo* -IPrimaryScreen::CMotionInfo::alloc(SInt32 x, SInt32 y) -{ - CMotionInfo* info = (CMotionInfo*)malloc(sizeof(CMotionInfo)); - info->m_x = x; - info->m_y = y; - return info; -} - - -// -// IPrimaryScreen::CWheelInfo -// - -IPrimaryScreen::CWheelInfo* -IPrimaryScreen::CWheelInfo::alloc(SInt32 xDelta, SInt32 yDelta) -{ - CWheelInfo* info = (CWheelInfo*)malloc(sizeof(CWheelInfo)); - info->m_xDelta = xDelta; - info->m_yDelta = yDelta; - return info; -} - - -// -// IPrimaryScreen::CHotKeyInfo -// - -IPrimaryScreen::CHotKeyInfo* -IPrimaryScreen::CHotKeyInfo::alloc(UInt32 id) -{ - CHotKeyInfo* info = (CHotKeyInfo*)malloc(sizeof(CHotKeyInfo)); - info->m_id = id; - return info; -} diff --git a/lib/synergy/IPrimaryScreen.h b/lib/synergy/IPrimaryScreen.h deleted file mode 100644 index 93166d23..00000000 --- a/lib/synergy/IPrimaryScreen.h +++ /dev/null @@ -1,206 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef IPRIMARYSCREEN_H -#define IPRIMARYSCREEN_H - -#include "IInterface.h" -#include "KeyTypes.h" -#include "MouseTypes.h" -#include "CEvent.h" - -//! Primary screen interface -/*! -This interface defines the methods common to all platform dependent -primary screen implementations. -*/ -class IPrimaryScreen : public IInterface { -public: - //! Button event data - class CButtonInfo { - public: - static CButtonInfo* alloc(ButtonID, KeyModifierMask); - static CButtonInfo* alloc(const CButtonInfo&); - - static bool equal(const CButtonInfo*, const CButtonInfo*); - - public: - ButtonID m_button; - KeyModifierMask m_mask; - }; - //! Motion event data - class CMotionInfo { - public: - static CMotionInfo* alloc(SInt32 x, SInt32 y); - - public: - SInt32 m_x; - SInt32 m_y; - }; - //! Wheel motion event data - class CWheelInfo { - public: - static CWheelInfo* alloc(SInt32 xDelta, SInt32 yDelta); - - public: - SInt32 m_xDelta; - SInt32 m_yDelta; - }; - //! Hot key event data - class CHotKeyInfo { - public: - static CHotKeyInfo* alloc(UInt32 id); - - public: - UInt32 m_id; - }; - - //! @name manipulators - //@{ - - //! Update configuration - /*! - This is called when the configuration has changed. \c activeSides - is a bitmask of EDirectionMask indicating which sides of the - primary screen are linked to clients. Override to handle the - possible change in jump zones. - */ - virtual void reconfigure(UInt32 activeSides) = 0; - - //! Warp cursor - /*! - Warp the cursor to the absolute coordinates \c x,y. Also - discard input events up to and including the warp before - returning. - */ - virtual void warpCursor(SInt32 x, SInt32 y) = 0; - - //! Register a system hotkey - /*! - Registers a system-wide hotkey. The screen should arrange for an event - to be delivered to itself when the hot key is pressed or released. When - that happens the screen should post a \c getHotKeyDownEvent() or - \c getHotKeyUpEvent(), respectively. The hot key is key \p key with - exactly the modifiers \p mask. Returns 0 on failure otherwise an id - that can be used to unregister the hotkey. - - A hot key is a set of modifiers and a key, which may itself be a modifier. - The hot key is pressed when the hot key's modifiers and only those - modifiers are logically down (active) and the key is pressed. The hot - key is released when the key is released, regardless of the modifiers. - - The hot key event should be generated no matter what window or application - has the focus. No other window or application should receive the key - press or release events (they can and should see the modifier key events). - When the key is a modifier, it's acceptable to allow the user to press - the modifiers in any order or to require the user to press the given key - last. - */ - virtual UInt32 registerHotKey(KeyID key, KeyModifierMask mask) = 0; - - //! Unregister a system hotkey - /*! - Unregisters a previously registered hot key. - */ - virtual void unregisterHotKey(UInt32 id) = 0; - - //! Prepare to synthesize input on primary screen - /*! - Prepares the primary screen to receive synthesized input. We do not - want to receive this synthesized input as user input so this method - ensures that we ignore it. Calls to \c fakeInputBegin() may not be - nested. - */ - virtual void fakeInputBegin() = 0; - - //! Done synthesizing input on primary screen - /*! - Undoes whatever \c fakeInputBegin() did. - */ - virtual void fakeInputEnd() = 0; - - //@} - //! @name accessors - //@{ - - //! Get jump zone size - /*! - Return the jump zone size, the size of the regions on the edges of - the screen that cause the cursor to jump to another screen. - */ - virtual SInt32 getJumpZoneSize() const = 0; - - //! Test if mouse is pressed - /*! - Return true if any mouse button is currently pressed. Ideally, - "current" means up to the last processed event but it can mean - the current physical mouse button state. - */ - virtual bool isAnyMouseButtonDown() const = 0; - - //! Get cursor center position - /*! - Return the cursor center position which is where we park the - cursor to compute cursor motion deltas and should be far from - the edges of the screen, typically the center. - */ - virtual void getCursorCenter(SInt32& x, SInt32& y) const = 0; - - //! Get button down event type. Event data is CButtonInfo*. - static CEvent::Type getButtonDownEvent(); - //! Get button up event type. Event data is CButtonInfo*. - static CEvent::Type getButtonUpEvent(); - //! Get mouse motion on the primary screen event type - /*! - Event data is CMotionInfo* and the values are an absolute position. - */ - static CEvent::Type getMotionOnPrimaryEvent(); - //! Get mouse motion on a secondary screen event type - /*! - Event data is CMotionInfo* and the values are motion deltas not - absolute coordinates. - */ - static CEvent::Type getMotionOnSecondaryEvent(); - //! Get mouse wheel event type. Event data is CWheelInfo*. - static CEvent::Type getWheelEvent(); - //! Get screensaver activated event type - static CEvent::Type getScreensaverActivatedEvent(); - //! Get screensaver deactivated event type - static CEvent::Type getScreensaverDeactivatedEvent(); - //! Get hot key down event type. Event data is CHotKeyInfo*. - static CEvent::Type getHotKeyDownEvent(); - //! Get hot key up event type. Event data is CHotKeyInfo*. - static CEvent::Type getHotKeyUpEvent(); - //! Get start of fake input event type - static CEvent::Type getFakeInputBeginEvent(); - //! Get end of fake input event type - static CEvent::Type getFakeInputEndEvent(); - - //@} - -private: - static CEvent::Type s_buttonDownEvent; - static CEvent::Type s_buttonUpEvent; - static CEvent::Type s_motionPrimaryEvent; - static CEvent::Type s_motionSecondaryEvent; - static CEvent::Type s_wheelEvent; - static CEvent::Type s_ssActivatedEvent; - static CEvent::Type s_ssDeactivatedEvent; - static CEvent::Type s_hotKeyDownEvent; - static CEvent::Type s_hotKeyUpEvent; - static CEvent::Type s_fakeInputBegin; - static CEvent::Type s_fakeInputEnd; -}; - -#endif diff --git a/lib/synergy/IScreen.cpp b/lib/synergy/IScreen.cpp deleted file mode 100644 index 3095b9d4..00000000 --- a/lib/synergy/IScreen.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2004 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "IScreen.h" - -// -// IScreen -// - -CEvent::Type IScreen::s_errorEvent = CEvent::kUnknown; -CEvent::Type IScreen::s_shapeChangedEvent = CEvent::kUnknown; -CEvent::Type IScreen::s_clipboardGrabbedEvent = CEvent::kUnknown; -CEvent::Type IScreen::s_suspendEvent = CEvent::kUnknown; -CEvent::Type IScreen::s_resumeEvent = CEvent::kUnknown; - -CEvent::Type -IScreen::getErrorEvent() -{ - return CEvent::registerTypeOnce(s_errorEvent, - "IScreen::error"); -} - -CEvent::Type -IScreen::getShapeChangedEvent() -{ - return CEvent::registerTypeOnce(s_shapeChangedEvent, - "IScreen::shapeChanged"); -} - -CEvent::Type -IScreen::getClipboardGrabbedEvent() -{ - return CEvent::registerTypeOnce(s_clipboardGrabbedEvent, - "IScreen::clipboardGrabbed"); -} - -CEvent::Type -IScreen::getSuspendEvent() -{ - return CEvent::registerTypeOnce(s_suspendEvent, - "IScreen::suspend"); -} - -CEvent::Type -IScreen::getResumeEvent() -{ - return CEvent::registerTypeOnce(s_resumeEvent, - "IScreen::resume"); -} diff --git a/lib/synergy/IScreen.h b/lib/synergy/IScreen.h deleted file mode 100644 index e1f94d59..00000000 --- a/lib/synergy/IScreen.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef ISCREEN_H -#define ISCREEN_H - -#include "IInterface.h" -#include "ClipboardTypes.h" -#include "CEvent.h" - -class IClipboard; - -//! Screen interface -/*! -This interface defines the methods common to all screens. -*/ -class IScreen : public IInterface { -public: - struct CClipboardInfo { - public: - ClipboardID m_id; - UInt32 m_sequenceNumber; - }; - - //! @name accessors - //@{ - - //! Get event target - /*! - Returns the target used for events created by this object. - */ - virtual void* getEventTarget() const = 0; - - //! Get clipboard - /*! - Save the contents of the clipboard indicated by \c id and return - true iff successful. - */ - virtual bool getClipboard(ClipboardID id, IClipboard*) const = 0; - - //! Get screen shape - /*! - Return the position of the upper-left corner of the screen in \c x and - \c y and the size of the screen in \c width and \c height. - */ - virtual void getShape(SInt32& x, SInt32& y, - SInt32& width, SInt32& height) const = 0; - - //! Get cursor position - /*! - Return the current position of the cursor in \c x and \c y. - */ - virtual void getCursorPos(SInt32& x, SInt32& y) const = 0; - - //! Get error event type - /*! - Returns the error event type. This is sent whenever the screen has - failed for some reason (e.g. the X Windows server died). - */ - static CEvent::Type getErrorEvent(); - - //! Get shape changed event type - /*! - Returns the shape changed event type. This is sent whenever the - screen's shape changes. - */ - static CEvent::Type getShapeChangedEvent(); - - //! Get clipboard grabbed event type - /*! - Returns the clipboard grabbed event type. This is sent whenever the - clipboard is grabbed by some other application so we don't own it - anymore. The data is a pointer to a CClipboardInfo. - */ - static CEvent::Type getClipboardGrabbedEvent(); - - //! Get suspend event type - /*! - Returns the suspend event type. This is sent whenever the system goes - to sleep or a user session is deactivated (fast user switching). - */ - static CEvent::Type getSuspendEvent(); - - //! Get resume event type - /*! - Returns the suspend event type. This is sent whenever the system wakes - up or a user session is activated (fast user switching). - */ - static CEvent::Type getResumeEvent(); - - //@} - -private: - static CEvent::Type s_errorEvent; - static CEvent::Type s_shapeChangedEvent; - static CEvent::Type s_clipboardGrabbedEvent; - static CEvent::Type s_suspendEvent; - static CEvent::Type s_resumeEvent; -}; - -#endif diff --git a/lib/synergy/IScreenSaver.h b/lib/synergy/IScreenSaver.h deleted file mode 100644 index 9076b309..00000000 --- a/lib/synergy/IScreenSaver.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef ISCREENSAVER_H -#define ISCREENSAVER_H - -#include "IInterface.h" -#include "CEvent.h" - -//! Screen saver interface -/*! -This interface defines the methods common to all screen savers. -*/ -class IScreenSaver : public IInterface { -public: - // note -- the c'tor/d'tor must *not* enable/disable the screen saver - - //! @name manipulators - //@{ - - //! Enable screen saver - /*! - Enable the screen saver, restoring the screen saver settings to - what they were when disable() was previously called. If disable() - wasn't previously called then it should keep the current settings - or use reasonable defaults. - */ - virtual void enable() = 0; - - //! Disable screen saver - /*! - Disable the screen saver, saving the old settings for the next - call to enable(). - */ - virtual void disable() = 0; - - //! Activate screen saver - /*! - Activate (i.e. show) the screen saver. - */ - virtual void activate() = 0; - - //! Deactivate screen saver - /*! - Deactivate (i.e. hide) the screen saver, reseting the screen saver - timer. - */ - virtual void deactivate() = 0; - - //@} - //! @name accessors - //@{ - - //! Test if screen saver on - /*! - Returns true iff the screen saver is currently active (showing). - */ - virtual bool isActive() const = 0; - - //@} -}; - -#endif diff --git a/lib/synergy/ISecondaryScreen.h b/lib/synergy/ISecondaryScreen.h deleted file mode 100644 index 5b3a150d..00000000 --- a/lib/synergy/ISecondaryScreen.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2003 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef ISECONDARYSCREEN_H -#define ISECONDARYSCREEN_H - -#include "IInterface.h" -#include "MouseTypes.h" - -//! Secondary screen interface -/*! -This interface defines the methods common to all platform dependent -secondary screen implementations. -*/ -class ISecondaryScreen : public IInterface { -public: - //! @name accessors - //@{ - - //! Fake mouse press/release - /*! - Synthesize a press or release of mouse button \c id. - */ - virtual void fakeMouseButton(ButtonID id, bool press) const = 0; - - //! Fake mouse move - /*! - Synthesize a mouse move to the absolute coordinates \c x,y. - */ - virtual void fakeMouseMove(SInt32 x, SInt32 y) const = 0; - - //! Fake mouse move - /*! - Synthesize a mouse move to the relative coordinates \c dx,dy. - */ - virtual void fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const = 0; - - //! Fake mouse wheel - /*! - Synthesize a mouse wheel event of amount \c xDelta and \c yDelta. - */ - virtual void fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const = 0; - - //@} -}; - -#endif diff --git a/lib/synergy/KeyTypes.cpp b/lib/synergy/KeyTypes.cpp deleted file mode 100644 index b483745d..00000000 --- a/lib/synergy/KeyTypes.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "KeyTypes.h" - -const KeyNameMapEntry kKeyNameMap[] = { - { "AltGr", kKeyAltGr }, - { "Alt_L", kKeyAlt_L }, - { "Alt_R", kKeyAlt_R }, - { "AppMail", kKeyAppMail }, - { "AppMedia", kKeyAppMedia }, - { "AppUser1", kKeyAppUser1 }, - { "AppUser2", kKeyAppUser2 }, - { "AudioDown", kKeyAudioDown }, - { "AudioMute", kKeyAudioMute }, - { "AudioNext", kKeyAudioNext }, - { "AudioPlay", kKeyAudioPlay }, - { "AudioPrev", kKeyAudioPrev }, - { "AudioStop", kKeyAudioStop }, - { "AudioUp", kKeyAudioUp }, - { "BackSpace", kKeyBackSpace }, - { "Begin", kKeyBegin }, - { "Break", kKeyBreak }, - { "Cancel", kKeyCancel }, - { "CapsLock", kKeyCapsLock }, - { "Clear", kKeyClear }, - { "Control_L", kKeyControl_L }, - { "Control_R", kKeyControl_R }, - { "Delete", kKeyDelete }, - { "Down", kKeyDown }, - { "Eject", kKeyEject }, - { "End", kKeyEnd }, - { "Escape", kKeyEscape }, - { "Execute", kKeyExecute }, - { "F1", kKeyF1 }, - { "F2", kKeyF2 }, - { "F3", kKeyF3 }, - { "F4", kKeyF4 }, - { "F5", kKeyF5 }, - { "F6", kKeyF6 }, - { "F7", kKeyF7 }, - { "F8", kKeyF8 }, - { "F9", kKeyF9 }, - { "F10", kKeyF10 }, - { "F11", kKeyF11 }, - { "F12", kKeyF12 }, - { "F13", kKeyF13 }, - { "F14", kKeyF14 }, - { "F15", kKeyF15 }, - { "F16", kKeyF16 }, - { "F17", kKeyF17 }, - { "F18", kKeyF18 }, - { "F19", kKeyF19 }, - { "F20", kKeyF20 }, - { "F21", kKeyF21 }, - { "F22", kKeyF22 }, - { "F23", kKeyF23 }, - { "F24", kKeyF24 }, - { "F25", kKeyF25 }, - { "F26", kKeyF26 }, - { "F27", kKeyF27 }, - { "F28", kKeyF28 }, - { "F29", kKeyF29 }, - { "F30", kKeyF30 }, - { "F31", kKeyF31 }, - { "F32", kKeyF32 }, - { "F33", kKeyF33 }, - { "F34", kKeyF34 }, - { "F35", kKeyF35 }, - { "Find", kKeyFind }, - { "Help", kKeyHelp }, - { "Henkan", kKeyHenkan }, - { "Home", kKeyHome }, - { "Hyper_L", kKeyHyper_L }, - { "Hyper_R", kKeyHyper_R }, - { "Insert", kKeyInsert }, - { "KP_0", kKeyKP_0 }, - { "KP_1", kKeyKP_1 }, - { "KP_2", kKeyKP_2 }, - { "KP_3", kKeyKP_3 }, - { "KP_4", kKeyKP_4 }, - { "KP_5", kKeyKP_5 }, - { "KP_6", kKeyKP_6 }, - { "KP_7", kKeyKP_7 }, - { "KP_8", kKeyKP_8 }, - { "KP_9", kKeyKP_9 }, - { "KP_Add", kKeyKP_Add }, - { "KP_Begin", kKeyKP_Begin }, - { "KP_Decimal", kKeyKP_Decimal }, - { "KP_Delete", kKeyKP_Delete }, - { "KP_Divide", kKeyKP_Divide }, - { "KP_Down", kKeyKP_Down }, - { "KP_End", kKeyKP_End }, - { "KP_Enter", kKeyKP_Enter }, - { "KP_Equal", kKeyKP_Equal }, - { "KP_F1", kKeyKP_F1 }, - { "KP_F2", kKeyKP_F2 }, - { "KP_F3", kKeyKP_F3 }, - { "KP_F4", kKeyKP_F4 }, - { "KP_Home", kKeyKP_Home }, - { "KP_Insert", kKeyKP_Insert }, - { "KP_Left", kKeyKP_Left }, - { "KP_Multiply", kKeyKP_Multiply }, - { "KP_PageDown", kKeyKP_PageDown }, - { "KP_PageUp", kKeyKP_PageUp }, - { "KP_Right", kKeyKP_Right }, - { "KP_Separator", kKeyKP_Separator }, - { "KP_Space", kKeyKP_Space }, - { "KP_Subtract", kKeyKP_Subtract }, - { "KP_Tab", kKeyKP_Tab }, - { "KP_Up", kKeyKP_Up }, - { "Left", kKeyLeft }, - { "LeftTab", kKeyLeftTab }, - { "Linefeed", kKeyLinefeed }, - { "Menu", kKeyMenu }, - { "Meta_L", kKeyMeta_L }, - { "Meta_R", kKeyMeta_R }, - { "NumLock", kKeyNumLock }, - { "PageDown", kKeyPageDown }, - { "PageUp", kKeyPageUp }, - { "Pause", kKeyPause }, - { "Print", kKeyPrint }, - { "Redo", kKeyRedo }, - { "Return", kKeyReturn }, - { "Right", kKeyRight }, - { "ScrollLock", kKeyScrollLock }, - { "Select", kKeySelect }, - { "ShiftLock", kKeyShiftLock }, - { "Shift_L", kKeyShift_L }, - { "Shift_R", kKeyShift_R }, - { "Sleep", kKeySleep }, - { "Super_L", kKeySuper_L }, - { "Super_R", kKeySuper_R }, - { "SysReq", kKeySysReq }, - { "Tab", kKeyTab }, - { "Undo", kKeyUndo }, - { "Up", kKeyUp }, - { "WWWBack", kKeyWWWBack }, - { "WWWFavorites", kKeyWWWFavorites }, - { "WWWForward", kKeyWWWForward }, - { "WWWHome", kKeyWWWHome }, - { "WWWRefresh", kKeyWWWRefresh }, - { "WWWSearch", kKeyWWWSearch }, - { "WWWStop", kKeyWWWStop }, - { "Zenkaku", kKeyZenkaku }, - { "Space", 0x0020 }, - { "Exclaim", 0x0021 }, - { "DoubleQuote", 0x0022 }, - { "Number", 0x0023 }, - { "Dollar", 0x0024 }, - { "Percent", 0x0025 }, - { "Ampersand", 0x0026 }, - { "Apostrophe", 0x0027 }, - { "ParenthesisL", 0x0028 }, - { "ParenthesisR", 0x0029 }, - { "Asterisk", 0x002a }, - { "Plus", 0x002b }, - { "Comma", 0x002c }, - { "Minus", 0x002d }, - { "Period", 0x002e }, - { "Slash", 0x002f }, - { "Colon", 0x003a }, - { "Semicolon", 0x003b }, - { "Less", 0x003c }, - { "Equal", 0x003d }, - { "Greater", 0x003e }, - { "Question", 0x003f }, - { "At", 0x0040 }, - { "BracketL", 0x005b }, - { "Backslash", 0x005c }, - { "BracketR", 0x005d }, - { "Circumflex", 0x005e }, - { "Underscore", 0x005f }, - { "Grave", 0x0060 }, - { "BraceL", 0x007b }, - { "Bar", 0x007c }, - { "BraceR", 0x007d }, - { "Tilde", 0x007e }, - { NULL, 0 }, -}; - -const KeyModifierNameMapEntry kModifierNameMap[] = { - { "Alt", KeyModifierAlt }, - { "AltGr", KeyModifierAltGr }, -// { "CapsLock", KeyModifierCapsLock }, - { "Control", KeyModifierControl }, - { "Meta", KeyModifierMeta }, -// { "NumLock", KeyModifierNumLock }, -// { "ScrollLock", KeyModifierScrollLock }, - { "Shift", KeyModifierShift }, - { "Super", KeyModifierSuper }, - { NULL, 0 }, -}; diff --git a/lib/synergy/KeyTypes.h b/lib/synergy/KeyTypes.h deleted file mode 100644 index c8b4f6b8..00000000 --- a/lib/synergy/KeyTypes.h +++ /dev/null @@ -1,306 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef KEYTYPES_H -#define KEYTYPES_H - -#include "BasicTypes.h" - -//! Key ID -/*! -Type to hold a key symbol identifier. The encoding is UTF-32, using -U+E000 through U+EFFF for the various control keys (e.g. arrow -keys, function keys, modifier keys, etc). -*/ -typedef UInt32 KeyID; - -//! Key Code -/*! -Type to hold a physical key identifier. That is, it identifies a -physical key on the keyboard. KeyButton 0 is reserved to be an -invalid key; platforms that use 0 as a physical key identifier -will have to remap that value to some arbitrary unused id. -*/ -typedef UInt16 KeyButton; - -//! Modifier key mask -/*! -Type to hold a bitmask of key modifiers (e.g. shift keys). -*/ -typedef UInt32 KeyModifierMask; - -//! Modifier key ID -/*! -Type to hold the id of a key modifier (e.g. a shift key). -*/ -typedef UInt32 KeyModifierID; - -//! @name Modifier key masks -//@{ -static const KeyModifierMask KeyModifierShift = 0x0001; -static const KeyModifierMask KeyModifierControl = 0x0002; -static const KeyModifierMask KeyModifierAlt = 0x0004; -static const KeyModifierMask KeyModifierMeta = 0x0008; -static const KeyModifierMask KeyModifierSuper = 0x0010; -static const KeyModifierMask KeyModifierAltGr = 0x0020; -static const KeyModifierMask KeyModifierCapsLock = 0x1000; -static const KeyModifierMask KeyModifierNumLock = 0x2000; -static const KeyModifierMask KeyModifierScrollLock = 0x4000; -//@} - -//! @name Modifier key bits -//@{ -static const UInt32 kKeyModifierBitNone = 16; -static const UInt32 kKeyModifierBitShift = 0; -static const UInt32 kKeyModifierBitControl = 1; -static const UInt32 kKeyModifierBitAlt = 2; -static const UInt32 kKeyModifierBitMeta = 3; -static const UInt32 kKeyModifierBitSuper = 4; -static const UInt32 kKeyModifierBitAltGr = 5; -static const UInt32 kKeyModifierBitCapsLock = 12; -static const UInt32 kKeyModifierBitNumLock = 13; -static const UInt32 kKeyModifierBitScrollLock = 14; -static const SInt32 kKeyModifierNumBits = 16; -//@} - -//! @name Modifier key identifiers -//@{ -static const KeyModifierID kKeyModifierIDNull = 0; -static const KeyModifierID kKeyModifierIDShift = 1; -static const KeyModifierID kKeyModifierIDControl = 2; -static const KeyModifierID kKeyModifierIDAlt = 3; -static const KeyModifierID kKeyModifierIDMeta = 4; -static const KeyModifierID kKeyModifierIDSuper = 5; -static const KeyModifierID kKeyModifierIDLast = 6; -//@} - -//! @name Key identifiers -//@{ -// all identifiers except kKeyNone and those in 0xE000 to 0xE0FF -// inclusive are equal to the corresponding X11 keysym - 0x1000. - -// no key -static const KeyID kKeyNone = 0x0000; - -// TTY functions -static const KeyID kKeyBackSpace = 0xEF08; /* back space, back char */ -static const KeyID kKeyTab = 0xEF09; -static const KeyID kKeyLinefeed = 0xEF0A; /* Linefeed, LF */ -static const KeyID kKeyClear = 0xEF0B; -static const KeyID kKeyReturn = 0xEF0D; /* Return, enter */ -static const KeyID kKeyPause = 0xEF13; /* Pause, hold */ -static const KeyID kKeyScrollLock = 0xEF14; -static const KeyID kKeySysReq = 0xEF15; -static const KeyID kKeyEscape = 0xEF1B; -static const KeyID kKeyHenkan = 0xEF23; /* Start/Stop Conversion */ -static const KeyID kKeyHangulKana = 0xEF26; /* Hangul, Kana */ -static const KeyID kKeyHiraganaKatakana = 0xEF27; /* Hiragana/Katakana toggle */ -static const KeyID kKeyZenkaku = 0xEF2A; /* Zenkaku/Hankaku */ -static const KeyID kKeyHanjaKanzi = 0xEF2A; /* Hanja, Kanzi */ -static const KeyID kKeyDelete = 0xEFFF; /* Delete, rubout */ - -// cursor control -static const KeyID kKeyHome = 0xEF50; -static const KeyID kKeyLeft = 0xEF51; /* Move left, left arrow */ -static const KeyID kKeyUp = 0xEF52; /* Move up, up arrow */ -static const KeyID kKeyRight = 0xEF53; /* Move right, right arrow */ -static const KeyID kKeyDown = 0xEF54; /* Move down, down arrow */ -static const KeyID kKeyPageUp = 0xEF55; -static const KeyID kKeyPageDown = 0xEF56; -static const KeyID kKeyEnd = 0xEF57; /* EOL */ -static const KeyID kKeyBegin = 0xEF58; /* BOL */ - -// misc functions -static const KeyID kKeySelect = 0xEF60; /* Select, mark */ -static const KeyID kKeyPrint = 0xEF61; -static const KeyID kKeyExecute = 0xEF62; /* Execute, run, do */ -static const KeyID kKeyInsert = 0xEF63; /* Insert, insert here */ -static const KeyID kKeyUndo = 0xEF65; /* Undo, oops */ -static const KeyID kKeyRedo = 0xEF66; /* redo, again */ -static const KeyID kKeyMenu = 0xEF67; -static const KeyID kKeyFind = 0xEF68; /* Find, search */ -static const KeyID kKeyCancel = 0xEF69; /* Cancel, stop, abort, exit */ -static const KeyID kKeyHelp = 0xEF6A; /* Help */ -static const KeyID kKeyBreak = 0xEF6B; -static const KeyID kKeyAltGr = 0xEF7E; /* Character set switch */ -static const KeyID kKeyNumLock = 0xEF7F; - -// keypad -static const KeyID kKeyKP_Space = 0xEF80; /* space */ -static const KeyID kKeyKP_Tab = 0xEF89; -static const KeyID kKeyKP_Enter = 0xEF8D; /* enter */ -static const KeyID kKeyKP_F1 = 0xEF91; /* PF1, KP_A, ... */ -static const KeyID kKeyKP_F2 = 0xEF92; -static const KeyID kKeyKP_F3 = 0xEF93; -static const KeyID kKeyKP_F4 = 0xEF94; -static const KeyID kKeyKP_Home = 0xEF95; -static const KeyID kKeyKP_Left = 0xEF96; -static const KeyID kKeyKP_Up = 0xEF97; -static const KeyID kKeyKP_Right = 0xEF98; -static const KeyID kKeyKP_Down = 0xEF99; -static const KeyID kKeyKP_PageUp = 0xEF9A; -static const KeyID kKeyKP_PageDown = 0xEF9B; -static const KeyID kKeyKP_End = 0xEF9C; -static const KeyID kKeyKP_Begin = 0xEF9D; -static const KeyID kKeyKP_Insert = 0xEF9E; -static const KeyID kKeyKP_Delete = 0xEF9F; -static const KeyID kKeyKP_Equal = 0xEFBD; /* equals */ -static const KeyID kKeyKP_Multiply = 0xEFAA; -static const KeyID kKeyKP_Add = 0xEFAB; -static const KeyID kKeyKP_Separator= 0xEFAC; /* separator, often comma */ -static const KeyID kKeyKP_Subtract = 0xEFAD; -static const KeyID kKeyKP_Decimal = 0xEFAE; -static const KeyID kKeyKP_Divide = 0xEFAF; -static const KeyID kKeyKP_0 = 0xEFB0; -static const KeyID kKeyKP_1 = 0xEFB1; -static const KeyID kKeyKP_2 = 0xEFB2; -static const KeyID kKeyKP_3 = 0xEFB3; -static const KeyID kKeyKP_4 = 0xEFB4; -static const KeyID kKeyKP_5 = 0xEFB5; -static const KeyID kKeyKP_6 = 0xEFB6; -static const KeyID kKeyKP_7 = 0xEFB7; -static const KeyID kKeyKP_8 = 0xEFB8; -static const KeyID kKeyKP_9 = 0xEFB9; - -// function keys -static const KeyID kKeyF1 = 0xEFBE; -static const KeyID kKeyF2 = 0xEFBF; -static const KeyID kKeyF3 = 0xEFC0; -static const KeyID kKeyF4 = 0xEFC1; -static const KeyID kKeyF5 = 0xEFC2; -static const KeyID kKeyF6 = 0xEFC3; -static const KeyID kKeyF7 = 0xEFC4; -static const KeyID kKeyF8 = 0xEFC5; -static const KeyID kKeyF9 = 0xEFC6; -static const KeyID kKeyF10 = 0xEFC7; -static const KeyID kKeyF11 = 0xEFC8; -static const KeyID kKeyF12 = 0xEFC9; -static const KeyID kKeyF13 = 0xEFCA; -static const KeyID kKeyF14 = 0xEFCB; -static const KeyID kKeyF15 = 0xEFCC; -static const KeyID kKeyF16 = 0xEFCD; -static const KeyID kKeyF17 = 0xEFCE; -static const KeyID kKeyF18 = 0xEFCF; -static const KeyID kKeyF19 = 0xEFD0; -static const KeyID kKeyF20 = 0xEFD1; -static const KeyID kKeyF21 = 0xEFD2; -static const KeyID kKeyF22 = 0xEFD3; -static const KeyID kKeyF23 = 0xEFD4; -static const KeyID kKeyF24 = 0xEFD5; -static const KeyID kKeyF25 = 0xEFD6; -static const KeyID kKeyF26 = 0xEFD7; -static const KeyID kKeyF27 = 0xEFD8; -static const KeyID kKeyF28 = 0xEFD9; -static const KeyID kKeyF29 = 0xEFDA; -static const KeyID kKeyF30 = 0xEFDB; -static const KeyID kKeyF31 = 0xEFDC; -static const KeyID kKeyF32 = 0xEFDD; -static const KeyID kKeyF33 = 0xEFDE; -static const KeyID kKeyF34 = 0xEFDF; -static const KeyID kKeyF35 = 0xEFE0; - -// modifiers -static const KeyID kKeyShift_L = 0xEFE1; /* Left shift */ -static const KeyID kKeyShift_R = 0xEFE2; /* Right shift */ -static const KeyID kKeyControl_L = 0xEFE3; /* Left control */ -static const KeyID kKeyControl_R = 0xEFE4; /* Right control */ -static const KeyID kKeyCapsLock = 0xEFE5; /* Caps lock */ -static const KeyID kKeyShiftLock = 0xEFE6; /* Shift lock */ -static const KeyID kKeyMeta_L = 0xEFE7; /* Left meta */ -static const KeyID kKeyMeta_R = 0xEFE8; /* Right meta */ -static const KeyID kKeyAlt_L = 0xEFE9; /* Left alt */ -static const KeyID kKeyAlt_R = 0xEFEA; /* Right alt */ -static const KeyID kKeySuper_L = 0xEFEB; /* Left super */ -static const KeyID kKeySuper_R = 0xEFEC; /* Right super */ -static const KeyID kKeyHyper_L = 0xEFED; /* Left hyper */ -static const KeyID kKeyHyper_R = 0xEFEE; /* Right hyper */ - -// multi-key character composition -static const KeyID kKeyCompose = 0xEF20; -static const KeyID kKeyDeadGrave = 0x0300; -static const KeyID kKeyDeadAcute = 0x0301; -static const KeyID kKeyDeadCircumflex = 0x0302; -static const KeyID kKeyDeadTilde = 0x0303; -static const KeyID kKeyDeadMacron = 0x0304; -static const KeyID kKeyDeadBreve = 0x0306; -static const KeyID kKeyDeadAbovedot = 0x0307; -static const KeyID kKeyDeadDiaeresis = 0x0308; -static const KeyID kKeyDeadAbovering = 0x030a; -static const KeyID kKeyDeadDoubleacute = 0x030b; -static const KeyID kKeyDeadCaron = 0x030c; -static const KeyID kKeyDeadCedilla = 0x0327; -static const KeyID kKeyDeadOgonek = 0x0328; - -// more function and modifier keys -static const KeyID kKeyLeftTab = 0xEE20; - -// update modifiers -static const KeyID kKeySetModifiers = 0xEE06; -static const KeyID kKeyClearModifiers = 0xEE07; - -// group change -static const KeyID kKeyNextGroup = 0xEE08; -static const KeyID kKeyPrevGroup = 0xEE0A; - -// extended keys -static const KeyID kKeyEject = 0xE001; -static const KeyID kKeySleep = 0xE05F; -static const KeyID kKeyWWWBack = 0xE0A6; -static const KeyID kKeyWWWForward = 0xE0A7; -static const KeyID kKeyWWWRefresh = 0xE0A8; -static const KeyID kKeyWWWStop = 0xE0A9; -static const KeyID kKeyWWWSearch = 0xE0AA; -static const KeyID kKeyWWWFavorites = 0xE0AB; -static const KeyID kKeyWWWHome = 0xE0AC; -static const KeyID kKeyAudioMute = 0xE0AD; -static const KeyID kKeyAudioDown = 0xE0AE; -static const KeyID kKeyAudioUp = 0xE0AF; -static const KeyID kKeyAudioNext = 0xE0B0; -static const KeyID kKeyAudioPrev = 0xE0B1; -static const KeyID kKeyAudioStop = 0xE0B2; -static const KeyID kKeyAudioPlay = 0xE0B3; -static const KeyID kKeyAppMail = 0xE0B4; -static const KeyID kKeyAppMedia = 0xE0B5; -static const KeyID kKeyAppUser1 = 0xE0B6; -static const KeyID kKeyAppUser2 = 0xE0B7; - -//@} - -struct KeyNameMapEntry { -public: - const char* m_name; - KeyID m_id; -}; -struct KeyModifierNameMapEntry { -public: - const char* m_name; - KeyModifierMask m_mask; -}; - -//! Key name to KeyID table -/*! -A table of key names to the corresponding KeyID. Only the keys listed -above plus non-alphanumeric ASCII characters are in the table. The end -of the table is the first pair with a NULL m_name. -*/ -extern const KeyNameMapEntry kKeyNameMap[]; - -//! Modifier key name to KeyModifierMask table -/*! -A table of modifier key names to the corresponding KeyModifierMask. -The end of the table is the first pair with a NULL m_name. -*/ -extern const KeyModifierNameMapEntry kModifierNameMap[]; - -#endif diff --git a/lib/synergy/Makefile.am b/lib/synergy/Makefile.am deleted file mode 100644 index 480102a4..00000000 --- a/lib/synergy/Makefile.am +++ /dev/null @@ -1,71 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2002 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -## Process this file with automake to produce Makefile.in -NULL = - -EXTRA_DIST = \ - Makefile.win \ - $(NULL) - -MAINTAINERCLEANFILES = \ - Makefile.in \ - $(NULL) - -noinst_LIBRARIES = libsynergy.a -libsynergy_a_SOURCES = \ - CClipboard.cpp \ - CKeyMap.cpp \ - CKeyState.cpp \ - CPacketStreamFilter.cpp \ - CPlatformScreen.cpp \ - CProtocolUtil.cpp \ - CScreen.cpp \ - IClipboard.cpp \ - IKeyState.cpp \ - IPrimaryScreen.cpp \ - IScreen.cpp \ - KeyTypes.cpp \ - ProtocolTypes.cpp \ - XScreen.cpp \ - XSynergy.cpp \ - CClipboard.h \ - CKeyMap.h \ - CKeyState.h \ - CPacketStreamFilter.h \ - CPlatformScreen.h \ - CProtocolUtil.h \ - CScreen.h \ - ClipboardTypes.h \ - IClient.h \ - IClipboard.h \ - IKeyState.h \ - IPlatformScreen.h \ - IPrimaryScreen.h \ - IScreen.h \ - IScreenSaver.h \ - ISecondaryScreen.h \ - KeyTypes.h \ - MouseTypes.h \ - OptionTypes.h \ - ProtocolTypes.h \ - XScreen.h \ - XSynergy.h \ - $(NULL) -INCLUDES = \ - -I$(top_srcdir)/lib/common \ - -I$(top_srcdir)/lib/arch \ - -I$(top_srcdir)/lib/base \ - -I$(top_srcdir)/lib/mt \ - -I$(top_srcdir)/lib/io \ - -I$(top_srcdir)/lib/net \ - $(NULL) diff --git a/lib/synergy/Makefile.win b/lib/synergy/Makefile.win deleted file mode 100644 index e6d56d42..00000000 --- a/lib/synergy/Makefile.win +++ /dev/null @@ -1,87 +0,0 @@ -# synergy -- mouse and keyboard sharing utility -# Copyright (C) 2007 Chris Schoeneman -# -# This package is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# found in the file COPYING that should have accompanied this file. -# -# This package 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. - -LIB_SYNERGY_SRC = lib\synergy -LIB_SYNERGY_DST = $(BUILD_DST)\$(LIB_SYNERGY_SRC) -LIB_SYNERGY_LIB = "$(LIB_SYNERGY_DST)\libsynergy.lib" -LIB_SYNERGY_CPP = \ - "CClipboard.cpp" \ - "CKeyMap.cpp" \ - "CKeyState.cpp" \ - "CPacketStreamFilter.cpp" \ - "CPlatformScreen.cpp" \ - "CProtocolUtil.cpp" \ - "CScreen.cpp" \ - "IClipboard.cpp" \ - "IKeyState.cpp" \ - "IPrimaryScreen.cpp" \ - "IScreen.cpp" \ - "KeyTypes.cpp" \ - "ProtocolTypes.cpp" \ - "XScreen.cpp" \ - "XSynergy.cpp" \ - $(NULL) -LIB_SYNERGY_OBJ = \ - "$(LIB_SYNERGY_DST)\CClipboard.obj" \ - "$(LIB_SYNERGY_DST)\CKeyMap.obj" \ - "$(LIB_SYNERGY_DST)\CKeyState.obj" \ - "$(LIB_SYNERGY_DST)\CPacketStreamFilter.obj" \ - "$(LIB_SYNERGY_DST)\CPlatformScreen.obj" \ - "$(LIB_SYNERGY_DST)\CProtocolUtil.obj" \ - "$(LIB_SYNERGY_DST)\CScreen.obj" \ - "$(LIB_SYNERGY_DST)\IClipboard.obj" \ - "$(LIB_SYNERGY_DST)\IKeyState.obj" \ - "$(LIB_SYNERGY_DST)\IPrimaryScreen.obj" \ - "$(LIB_SYNERGY_DST)\IScreen.obj" \ - "$(LIB_SYNERGY_DST)\KeyTypes.obj" \ - "$(LIB_SYNERGY_DST)\ProtocolTypes.obj" \ - "$(LIB_SYNERGY_DST)\XScreen.obj" \ - "$(LIB_SYNERGY_DST)\XSynergy.obj" \ - $(NULL) -LIB_SYNERGY_INC = \ - /I"lib\common" \ - /I"lib\arch" \ - /I"lib\base" \ - /I"lib\mt" \ - /I"lib\io" \ - /I"lib\net" \ - $(NULL) - -CPP_FILES = $(CPP_FILES) $(LIB_SYNERGY_CPP) -OBJ_FILES = $(OBJ_FILES) $(LIB_SYNERGY_OBJ) -LIB_FILES = $(LIB_FILES) $(LIB_SYNERGY_LIB) - -# Dependency rules -$(LIB_SYNERGY_OBJ): $(AUTODEP) -!if EXIST($(LIB_SYNERGY_DST)\deps.mak) -!include $(LIB_SYNERGY_DST)\deps.mak -!endif - -# Build rules. Use batch-mode rules if possible. -!if DEFINED(_NMAKE_VER) -{$(LIB_SYNERGY_SRC)\}.cpp{$(LIB_SYNERGY_DST)\}.obj:: -!else -{$(LIB_SYNERGY_SRC)\}.cpp{$(LIB_SYNERGY_DST)\}.obj: -!endif - @$(ECHO) Compile in $(LIB_SYNERGY_SRC) - -@$(MKDIR) $(LIB_SYNERGY_DST) 2>NUL: - $(cpp) $(cppdebug) $(cppflags) $(cppvarsmt) /showIncludes \ - $(LIB_SYNERGY_INC) \ - /Fo$(LIB_SYNERGY_DST)\ \ - /Fd$(LIB_SYNERGY_LIB:.lib=.pdb) \ - $< | $(AUTODEP) $(LIB_SYNERGY_SRC) $(LIB_SYNERGY_DST) -$(LIB_SYNERGY_LIB): $(LIB_SYNERGY_OBJ) - @$(ECHO) Link $(@F) - $(implib) $(ildebug) $(ilflags) \ - /out:$@ \ - $** - $(AUTODEP) $(LIB_SYNERGY_SRC) $(LIB_SYNERGY_DST) $(**:.obj=.d) diff --git a/lib/synergy/MouseTypes.h b/lib/synergy/MouseTypes.h deleted file mode 100644 index e4988553..00000000 --- a/lib/synergy/MouseTypes.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef MOUSETYPES_H -#define MOUSETYPES_H - -#include "BasicTypes.h" - -//! Mouse button ID -/*! -Type to hold a mouse button identifier. -*/ -typedef UInt8 ButtonID; - -//! @name Mouse button identifiers -//@{ -static const ButtonID kButtonNone = 0; -static const ButtonID kButtonLeft = 1; -static const ButtonID kButtonMiddle = 2; -static const ButtonID kButtonRight = 3; -static const ButtonID kButtonExtra0 = 4; -//@} - -#endif diff --git a/lib/synergy/OptionTypes.h b/lib/synergy/OptionTypes.h deleted file mode 100644 index 74beda00..00000000 --- a/lib/synergy/OptionTypes.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef OPTIONTYPES_H -#define OPTIONTYPES_H - -#include "BasicTypes.h" -#include "stdvector.h" - -//! Option ID -/*! -Type to hold an option identifier. -*/ -typedef UInt32 OptionID; - -//! Option Value -/*! -Type to hold an option value. -*/ -typedef SInt32 OptionValue; - -// for now, options are just pairs of integers -typedef std::vector COptionsList; - -// macro for packing 4 character strings into 4 byte integers -#define OPTION_CODE(_s) \ - (static_cast(static_cast(_s[0]) << 24) | \ - static_cast(static_cast(_s[1]) << 16) | \ - static_cast(static_cast(_s[2]) << 8) | \ - static_cast(static_cast(_s[3]) )) - -//! @name Option identifiers -//@{ -static const OptionID kOptionHalfDuplexCapsLock = OPTION_CODE("HDCL"); -static const OptionID kOptionHalfDuplexNumLock = OPTION_CODE("HDNL"); -static const OptionID kOptionHalfDuplexScrollLock = OPTION_CODE("HDSL"); -static const OptionID kOptionModifierMapForShift = OPTION_CODE("MMFS"); -static const OptionID kOptionModifierMapForControl = OPTION_CODE("MMFC"); -static const OptionID kOptionModifierMapForAlt = OPTION_CODE("MMFA"); -static const OptionID kOptionModifierMapForMeta = OPTION_CODE("MMFM"); -static const OptionID kOptionModifierMapForSuper = OPTION_CODE("MMFR"); -static const OptionID kOptionHeartbeat = OPTION_CODE("HART"); -static const OptionID kOptionScreenSwitchCorners = OPTION_CODE("SSCM"); -static const OptionID kOptionScreenSwitchCornerSize = OPTION_CODE("SSCS"); -static const OptionID kOptionScreenSwitchDelay = OPTION_CODE("SSWT"); -static const OptionID kOptionScreenSwitchTwoTap = OPTION_CODE("SSTT"); -static const OptionID kOptionScreenSaverSync = OPTION_CODE("SSVR"); -static const OptionID kOptionXTestXineramaUnaware = OPTION_CODE("XTXU"); -static const OptionID kOptionRelativeMouseMoves = OPTION_CODE("MDLT"); -static const OptionID kOptionWin32KeepForeground = OPTION_CODE("_KFW"); -//@} - -//! @name Screen switch corner enumeration -//@{ -enum EScreenSwitchCorners { - kNoCorner, - kTopLeft, - kTopRight, - kBottomLeft, - kBottomRight, - kFirstCorner = kTopLeft, - kLastCorner = kBottomRight -}; -//@} - -//! @name Screen switch corner masks -//@{ -enum EScreenSwitchCornerMasks { - kNoCornerMask = 0, - kTopLeftMask = 1 << (kTopLeft - kFirstCorner), - kTopRightMask = 1 << (kTopRight - kFirstCorner), - kBottomLeftMask = 1 << (kBottomLeft - kFirstCorner), - kBottomRightMask = 1 << (kBottomRight - kFirstCorner), - kAllCornersMask = kTopLeftMask | kTopRightMask | - kBottomLeftMask | kBottomRightMask -}; -//@} - -#undef OPTION_CODE - -#endif diff --git a/lib/synergy/ProtocolTypes.cpp b/lib/synergy/ProtocolTypes.cpp deleted file mode 100644 index 441b2f33..00000000 --- a/lib/synergy/ProtocolTypes.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "ProtocolTypes.h" - -const char* kMsgHello = "Synergy%2i%2i"; -const char* kMsgHelloBack = "Synergy%2i%2i%s"; -const char* kMsgCNoop = "CNOP"; -const char* kMsgCClose = "CBYE"; -const char* kMsgCEnter = "CINN%2i%2i%4i%2i"; -const char* kMsgCLeave = "COUT"; -const char* kMsgCClipboard = "CCLP%1i%4i"; -const char* kMsgCScreenSaver = "CSEC%1i"; -const char* kMsgCResetOptions = "CROP"; -const char* kMsgCInfoAck = "CIAK"; -const char* kMsgCKeepAlive = "CALV"; -const char* kMsgDKeyDown = "DKDN%2i%2i%2i"; -const char* kMsgDKeyDown1_0 = "DKDN%2i%2i"; -const char* kMsgDKeyRepeat = "DKRP%2i%2i%2i%2i"; -const char* kMsgDKeyRepeat1_0 = "DKRP%2i%2i%2i"; -const char* kMsgDKeyUp = "DKUP%2i%2i%2i"; -const char* kMsgDKeyUp1_0 = "DKUP%2i%2i"; -const char* kMsgDMouseDown = "DMDN%1i"; -const char* kMsgDMouseUp = "DMUP%1i"; -const char* kMsgDMouseMove = "DMMV%2i%2i"; -const char* kMsgDMouseRelMove = "DMRM%2i%2i"; -const char* kMsgDMouseWheel = "DMWM%2i%2i"; -const char* kMsgDMouseWheel1_0 = "DMWM%2i"; -const char* kMsgDClipboard = "DCLP%1i%4i%s"; -const char* kMsgDInfo = "DINF%2i%2i%2i%2i%2i%2i%2i"; -const char* kMsgDSetOptions = "DSOP%4I"; -const char* kMsgQInfo = "QINF"; -const char* kMsgEIncompatible = "EICV%2i%2i"; -const char* kMsgEBusy = "EBSY"; -const char* kMsgEUnknown = "EUNK"; -const char* kMsgEBad = "EBAD"; diff --git a/lib/synergy/ProtocolTypes.h b/lib/synergy/ProtocolTypes.h deleted file mode 100644 index c4d3c99d..00000000 --- a/lib/synergy/ProtocolTypes.h +++ /dev/null @@ -1,308 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef PROTOCOLTYPES_H -#define PROTOCOLTYPES_H - -#include "BasicTypes.h" - -// protocol version number -// 1.0: initial protocol -// 1.1: adds KeyCode to key press, release, and repeat -// 1.2: adds mouse relative motion -// 1.3: adds keep alive and deprecates heartbeats, -// adds horizontal mouse scrolling -static const SInt16 kProtocolMajorVersion = 1; -static const SInt16 kProtocolMinorVersion = 3; - -// default contact port number -static const UInt16 kDefaultPort = 24800; - -// maximum total length for greeting returned by client -static const UInt32 kMaxHelloLength = 1024; - -// time between kMsgCKeepAlive (in seconds). a non-positive value disables -// keep alives. this is the default rate that can be overridden using an -// option. -static const double kKeepAliveRate = 3.0; - -// number of skipped kMsgCKeepAlive messages that indicates a problem -static const double kKeepAlivesUntilDeath = 3.0; - -// obsolete heartbeat stuff -static const double kHeartRate = -1.0; -static const double kHeartBeatsUntilDeath = 3.0; - -// direction constants -enum EDirection { - kNoDirection, - kLeft, - kRight, - kTop, - kBottom, - kFirstDirection = kLeft, - kLastDirection = kBottom, - kNumDirections = kLastDirection - kFirstDirection + 1 -}; -enum EDirectionMask { - kNoDirMask = 0, - kLeftMask = 1 << kLeft, - kRightMask = 1 << kRight, - kTopMask = 1 << kTop, - kBottomMask = 1 << kBottom -}; - - -// -// message codes (trailing NUL is not part of code). in comments, $n -// refers to the n'th argument (counting from one). message codes are -// always 4 bytes optionally followed by message specific parameters -// except those for the greeting handshake. -// - -// -// positions and sizes are signed 16 bit integers. -// - -// -// greeting handshake messages -// - -// say hello to client; primary -> secondary -// $1 = protocol major version number supported by server. $2 = -// protocol minor version number supported by server. -extern const char* kMsgHello; - -// respond to hello from server; secondary -> primary -// $1 = protocol major version number supported by client. $2 = -// protocol minor version number supported by client. $3 = client -// name. -extern const char* kMsgHelloBack; - - -// -// command codes -// - -// no operation; secondary -> primary -extern const char* kMsgCNoop; - -// close connection; primary -> secondary -extern const char* kMsgCClose; - -// enter screen: primary -> secondary -// entering screen at screen position $1 = x, $2 = y. x,y are -// absolute screen coordinates. $3 = sequence number, which is -// used to order messages between screens. the secondary screen -// must return this number with some messages. $4 = modifier key -// mask. this will have bits set for each toggle modifier key -// that is activated on entry to the screen. the secondary screen -// should adjust its toggle modifiers to reflect that state. -extern const char* kMsgCEnter; - -// leave screen: primary -> secondary -// leaving screen. the secondary screen should send clipboard -// data in response to this message for those clipboards that -// it has grabbed (i.e. has sent a kMsgCClipboard for and has -// not received a kMsgCClipboard for with a greater sequence -// number) and that were grabbed or have changed since the -// last leave. -extern const char* kMsgCLeave; - -// grab clipboard: primary <-> secondary -// sent by screen when some other app on that screen grabs a -// clipboard. $1 = the clipboard identifier, $2 = sequence number. -// secondary screens must use the sequence number passed in the -// most recent kMsgCEnter. the primary always sends 0. -extern const char* kMsgCClipboard; - -// screensaver change: primary -> secondary -// screensaver on primary has started ($1 == 1) or closed ($1 == 0) -extern const char* kMsgCScreenSaver; - -// reset options: primary -> secondary -// client should reset all of its options to their defaults. -extern const char* kMsgCResetOptions; - -// resolution change acknowledgment: primary -> secondary -// sent by primary in response to a secondary screen's kMsgDInfo. -// this is sent for every kMsgDInfo, whether or not the primary -// had sent a kMsgQInfo. -extern const char* kMsgCInfoAck; - -// keep connection alive: primary <-> secondary -// sent by the server periodically to verify that connections are still -// up and running. clients must reply in kind on receipt. if the server -// gets an error sending the message or does not receive a reply within -// a reasonable time then the server disconnects the client. if the -// client doesn't receive these (or any message) periodically then it -// should disconnect from the server. the appropriate interval is -// defined by an option. -extern const char* kMsgCKeepAlive; - - -// -// data codes -// - -// key pressed: primary -> secondary -// $1 = KeyID, $2 = KeyModifierMask, $3 = KeyButton -// the KeyButton identifies the physical key on the primary used to -// generate this key. the secondary should note the KeyButton along -// with the physical key it uses to generate the key press. on -// release, the secondary can then use the primary's KeyButton to -// find its corresponding physical key and release it. this is -// necessary because the KeyID on release may not be the KeyID of -// the press. this can happen with combining (dead) keys or if -// the keyboard layouts are not identical and the user releases -// a modifier key before releasing the modified key. -extern const char* kMsgDKeyDown; - -// key pressed 1.0: same as above but without KeyButton -extern const char* kMsgDKeyDown1_0; - -// key auto-repeat: primary -> secondary -// $1 = KeyID, $2 = KeyModifierMask, $3 = number of repeats, $4 = KeyButton -extern const char* kMsgDKeyRepeat; - -// key auto-repeat 1.0: same as above but without KeyButton -extern const char* kMsgDKeyRepeat1_0; - -// key released: primary -> secondary -// $1 = KeyID, $2 = KeyModifierMask, $3 = KeyButton -extern const char* kMsgDKeyUp; - -// key released 1.0: same as above but without KeyButton -extern const char* kMsgDKeyUp1_0; - -// mouse button pressed: primary -> secondary -// $1 = ButtonID -extern const char* kMsgDMouseDown; - -// mouse button released: primary -> secondary -// $1 = ButtonID -extern const char* kMsgDMouseUp; - -// mouse moved: primary -> secondary -// $1 = x, $2 = y. x,y are absolute screen coordinates. -extern const char* kMsgDMouseMove; - -// relative mouse move: primary -> secondary -// $1 = dx, $2 = dy. dx,dy are motion deltas. -extern const char* kMsgDMouseRelMove; - -// mouse scroll: primary -> secondary -// $1 = xDelta, $2 = yDelta. the delta should be +120 for one tick forward -// (away from the user) or right and -120 for one tick backward (toward -// the user) or left. -extern const char* kMsgDMouseWheel; - -// mouse vertical scroll: primary -> secondary -// like as kMsgDMouseWheel except only sends $1 = yDelta. -extern const char* kMsgDMouseWheel1_0; - -// clipboard data: primary <-> secondary -// $2 = sequence number, $3 = clipboard data. the sequence number -// is 0 when sent by the primary. secondary screens should use the -// sequence number from the most recent kMsgCEnter. $1 = clipboard -// identifier. -extern const char* kMsgDClipboard; - -// client data: secondary -> primary -// $1 = coordinate of leftmost pixel on secondary screen, -// $2 = coordinate of topmost pixel on secondary screen, -// $3 = width of secondary screen in pixels, -// $4 = height of secondary screen in pixels, -// $5 = size of warp zone, (obsolete) -// $6, $7 = the x,y position of the mouse on the secondary screen. -// -// the secondary screen must send this message in response to the -// kMsgQInfo message. it must also send this message when the -// screen's resolution changes. in this case, the secondary screen -// should ignore any kMsgDMouseMove messages until it receives a -// kMsgCInfoAck in order to prevent attempts to move the mouse off -// the new screen area. -extern const char* kMsgDInfo; - -// set options: primary -> secondary -// client should set the given option/value pairs. $1 = option/value -// pairs. -extern const char* kMsgDSetOptions; - - -// -// query codes -// - -// query screen info: primary -> secondary -// client should reply with a kMsgDInfo. -extern const char* kMsgQInfo; - - -// -// error codes -// - -// incompatible versions: primary -> secondary -// $1 = major version of primary, $2 = minor version of primary. -extern const char* kMsgEIncompatible; - -// name provided when connecting is already in use: primary -> secondary -extern const char* kMsgEBusy; - -// unknown client: primary -> secondary -// name provided when connecting is not in primary's screen -// configuration map. -extern const char* kMsgEUnknown; - -// protocol violation: primary -> secondary -// primary should disconnect after sending this message. -extern const char* kMsgEBad; - - -// -// structures -// - -//! Screen information -/*! -This class contains information about a screen. -*/ -class CClientInfo { -public: - //! Screen position - /*! - The position of the upper-left corner of the screen. This is - typically 0,0. - */ - SInt32 m_x, m_y; - - //! Screen size - /*! - The size of the screen in pixels. - */ - SInt32 m_w, m_h; - - //! Obsolete (jump zone size) - SInt32 obsolete1; - - //! Mouse position - /*! - The current location of the mouse cursor. - */ - SInt32 m_mx, m_my; -}; - -#endif - diff --git a/lib/synergy/XScreen.cpp b/lib/synergy/XScreen.cpp deleted file mode 100644 index 8a694bfa..00000000 --- a/lib/synergy/XScreen.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "XScreen.h" - -// -// XScreenOpenFailure -// - -CString -XScreenOpenFailure::getWhat() const throw() -{ - return format("XScreenOpenFailure", "unable to open screen"); -} - - -// -// XScreenUnavailable -// - -XScreenUnavailable::XScreenUnavailable(double timeUntilRetry) : - m_timeUntilRetry(timeUntilRetry) -{ - // do nothing -} - -XScreenUnavailable::~XScreenUnavailable() -{ - // do nothing -} - -double -XScreenUnavailable::getRetryTime() const -{ - return m_timeUntilRetry; -} - -CString -XScreenUnavailable::getWhat() const throw() -{ - return format("XScreenUnavailable", "unable to open screen"); -} diff --git a/lib/synergy/XScreen.h b/lib/synergy/XScreen.h deleted file mode 100644 index 9966e6cf..00000000 --- a/lib/synergy/XScreen.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef XSCREEN_H -#define XSCREEN_H - -#include "XBase.h" - -//! Generic screen exception -XBASE_SUBCLASS(XScreen, XBase); - -//! Cannot open screen exception -/*! -Thrown when a screen cannot be opened or initialized. -*/ -XBASE_SUBCLASS_WHAT(XScreenOpenFailure, XScreen); - -//! Screen unavailable exception -/*! -Thrown when a screen cannot be opened or initialized but retrying later -may be successful. -*/ -class XScreenUnavailable : public XScreenOpenFailure { -public: - /*! - \c timeUntilRetry is the suggested time the caller should wait until - trying to open the screen again. - */ - XScreenUnavailable(double timeUntilRetry); - virtual ~XScreenUnavailable(); - - //! @name manipulators - //@{ - - //! Get retry time - /*! - Returns the suggested time to wait until retrying to open the screen. - */ - double getRetryTime() const; - - //@} - -protected: - virtual CString getWhat() const throw(); - -private: - double m_timeUntilRetry; -}; - -#endif diff --git a/lib/synergy/XSynergy.cpp b/lib/synergy/XSynergy.cpp deleted file mode 100644 index 1e19945f..00000000 --- a/lib/synergy/XSynergy.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#include "XSynergy.h" -#include "CStringUtil.h" - -// -// XBadClient -// - -CString -XBadClient::getWhat() const throw() -{ - return "XBadClient"; -} - - -// -// XIncompatibleClient -// - -XIncompatibleClient::XIncompatibleClient(int major, int minor) : - m_major(major), - m_minor(minor) -{ - // do nothing -} - -int -XIncompatibleClient::getMajor() const throw() -{ - return m_major; -} - -int -XIncompatibleClient::getMinor() const throw() -{ - return m_minor; -} - -CString -XIncompatibleClient::getWhat() const throw() -{ - return format("XIncompatibleClient", "incompatible client %{1}.%{2}", - CStringUtil::print("%d", m_major).c_str(), - CStringUtil::print("%d", m_minor).c_str()); -} - - -// -// XDuplicateClient -// - -XDuplicateClient::XDuplicateClient(const CString& name) : - m_name(name) -{ - // do nothing -} - -const CString& -XDuplicateClient::getName() const throw() -{ - return m_name; -} - -CString -XDuplicateClient::getWhat() const throw() -{ - return format("XDuplicateClient", "duplicate client %{1}", m_name.c_str()); -} - - -// -// XUnknownClient -// - -XUnknownClient::XUnknownClient(const CString& name) : - m_name(name) -{ - // do nothing -} - -const CString& -XUnknownClient::getName() const throw() -{ - return m_name; -} - -CString -XUnknownClient::getWhat() const throw() -{ - return format("XUnknownClient", "unknown client %{1}", m_name.c_str()); -} diff --git a/lib/synergy/XSynergy.h b/lib/synergy/XSynergy.h deleted file mode 100644 index 23131194..00000000 --- a/lib/synergy/XSynergy.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2002 Chris Schoeneman - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package 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. - */ - -#ifndef XSYNERGY_H -#define XSYNERGY_H - -#include "XBase.h" - -//! Generic synergy exception -XBASE_SUBCLASS(XSynergy, XBase); - -//! Client error exception -/*! -Thrown when the client fails to follow the protocol. -*/ -XBASE_SUBCLASS_WHAT(XBadClient, XSynergy); - -//! Incompatible client exception -/*! -Thrown when a client attempting to connect has an incompatible version. -*/ -class XIncompatibleClient : public XSynergy { -public: - XIncompatibleClient(int major, int minor); - - //! @name accessors - //@{ - - //! Get client's major version number - int getMajor() const throw(); - //! Get client's minor version number - int getMinor() const throw(); - - //@} - -protected: - virtual CString getWhat() const throw(); - -private: - int m_major; - int m_minor; -}; - -//! Client already connected exception -/*! -Thrown when a client attempting to connect is using the same name as -a client that is already connected. -*/ -class XDuplicateClient : public XSynergy { -public: - XDuplicateClient(const CString& name); - - //! @name accessors - //@{ - - //! Get client's name - virtual const CString& - getName() const throw(); - - //@} - -protected: - virtual CString getWhat() const throw(); - -private: - CString m_name; -}; - -//! Client not in map exception -/*! -Thrown when a client attempting to connect is using a name that is -unknown to the server. -*/ -class XUnknownClient : public XSynergy { -public: - XUnknownClient(const CString& name); - - //! @name accessors - //@{ - - //! Get the client's name - virtual const CString& - getName() const throw(); - - //@} - -protected: - virtual CString getWhat() const throw(); - -private: - CString m_name; -}; - -#endif diff --git a/rm-legacy.sh b/rm-legacy.sh new file mode 100755 index 00000000..abb0bb2f --- /dev/null +++ b/rm-legacy.sh @@ -0,0 +1,425 @@ +git rm AUTHORS +git rm Makefile.am +git rm Makefile.win +git rm NEWS +git rm acinclude.m4 +git rm cmd/Makefile.am +git rm cmd/launcher/CAddScreen.cpp +git rm cmd/launcher/CAddScreen.h +git rm cmd/launcher/CAdvancedOptions.cpp +git rm cmd/launcher/CAdvancedOptions.h +git rm cmd/launcher/CAutoStart.cpp +git rm cmd/launcher/CAutoStart.h +git rm cmd/launcher/CGlobalOptions.cpp +git rm cmd/launcher/CGlobalOptions.h +git rm cmd/launcher/CHotkeyOptions.cpp +git rm cmd/launcher/CHotkeyOptions.h +git rm cmd/launcher/CInfo.cpp +git rm cmd/launcher/CInfo.h +git rm cmd/launcher/CScreensLinks.cpp +git rm cmd/launcher/CScreensLinks.h +git rm cmd/launcher/LaunchUtil.cpp +git rm cmd/launcher/LaunchUtil.h +git rm cmd/launcher/Makefile.am +git rm cmd/launcher/Makefile.win +git rm cmd/launcher/launcher.cpp +git rm cmd/launcher/launcher.rc +git rm cmd/launcher/resource.h +git rm cmd/launcher/synergy.ico +git rm cmd/synergyc/CClientTaskBarReceiver.cpp +git rm cmd/synergyc/CClientTaskBarReceiver.h +git rm cmd/synergyc/CMSWindowsClientTaskBarReceiver.cpp +git rm cmd/synergyc/CMSWindowsClientTaskBarReceiver.h +git rm cmd/synergyc/COSXClientTaskBarReceiver.cpp +git rm cmd/synergyc/COSXClientTaskBarReceiver.h +git rm cmd/synergyc/CXWindowsClientTaskBarReceiver.cpp +git rm cmd/synergyc/CXWindowsClientTaskBarReceiver.h +git rm cmd/synergyc/Makefile.am +git rm cmd/synergyc/Makefile.win +git rm cmd/synergyc/resource.h +git rm cmd/synergyc/synergyc.cpp +git rm cmd/synergyc/synergyc.ico +git rm cmd/synergyc/synergyc.rc +git rm cmd/synergyc/tb_error.ico +git rm cmd/synergyc/tb_idle.ico +git rm cmd/synergyc/tb_run.ico +git rm cmd/synergyc/tb_wait.ico +git rm cmd/synergys/CMSWindowsServerTaskBarReceiver.cpp +git rm cmd/synergys/CMSWindowsServerTaskBarReceiver.h +git rm cmd/synergys/COSXServerTaskBarReceiver.cpp +git rm cmd/synergys/COSXServerTaskBarReceiver.h +git rm cmd/synergys/CServerTaskBarReceiver.cpp +git rm cmd/synergys/CServerTaskBarReceiver.h +git rm cmd/synergys/CXWindowsServerTaskBarReceiver.cpp +git rm cmd/synergys/CXWindowsServerTaskBarReceiver.h +git rm cmd/synergys/Makefile.am +git rm cmd/synergys/Makefile.win +git rm cmd/synergys/resource.h +git rm cmd/synergys/synergys.cpp +git rm cmd/synergys/synergys.ico +git rm cmd/synergys/synergys.rc +git rm cmd/synergys/tb_error.ico +git rm cmd/synergys/tb_idle.ico +git rm cmd/synergys/tb_run.ico +git rm cmd/synergys/tb_wait.ico +git rm config/config.guess +git rm config/config.sub +git rm config/depcomp +git rm config/install-sh +git rm config/missing +git rm config/mkinstalldirs +git rm configure.in +git rm dist/Makefile.am +git rm dist/nullsoft/Makefile.am +git rm dist/nullsoft/Makefile.win +git rm dist/nullsoft/dosify.c +git rm dist/nullsoft/synergy.nsi +git rm dist/rpm/Makefile.am +git rm dist/rpm/synergy.spec.in +git rm doc/Makefile.am +git rm doc/PORTING +git rm doc/about.html +git rm doc/authors.html +git rm doc/autostart.html +git rm doc/banner.html +git rm doc/border.html +git rm doc/compiling.html +git rm doc/configuration.html +git rm doc/contact.html +git rm doc/developer.html +git rm doc/doxygen.cfg.in +git rm doc/faq.html +git rm doc/history.html +git rm doc/home.html +git rm doc/images/logo.gif +git rm doc/images/warp.gif +git rm doc/index.html +git rm doc/license.html +git rm doc/news.html +git rm doc/roadmap.html +git rm doc/running.html +git rm doc/security.html +git rm doc/synergy.css +git rm doc/tips.html +git rm doc/toc.html +git rm doc/todo.html +git rm doc/trouble.html +git rm examples/synergy.conf +git rm lib/Makefile.am +git rm lib/arch/CArch.cpp +git rm lib/arch/CArch.h +git rm lib/arch/CArchConsoleUnix.cpp +git rm lib/arch/CArchConsoleUnix.h +git rm lib/arch/CArchConsoleWindows.cpp +git rm lib/arch/CArchConsoleWindows.h +git rm lib/arch/CArchDaemonNone.cpp +git rm lib/arch/CArchDaemonNone.h +git rm lib/arch/CArchDaemonUnix.cpp +git rm lib/arch/CArchDaemonUnix.h +git rm lib/arch/CArchDaemonWindows.cpp +git rm lib/arch/CArchDaemonWindows.h +git rm lib/arch/CArchFileUnix.cpp +git rm lib/arch/CArchFileUnix.h +git rm lib/arch/CArchFileWindows.cpp +git rm lib/arch/CArchFileWindows.h +git rm lib/arch/CArchLogUnix.cpp +git rm lib/arch/CArchLogUnix.h +git rm lib/arch/CArchLogWindows.cpp +git rm lib/arch/CArchLogWindows.h +git rm lib/arch/CArchMiscWindows.cpp +git rm lib/arch/CArchMiscWindows.h +git rm lib/arch/CArchMultithreadPosix.cpp +git rm lib/arch/CArchMultithreadPosix.h +git rm lib/arch/CArchMultithreadWindows.cpp +git rm lib/arch/CArchMultithreadWindows.h +git rm lib/arch/CArchNetworkBSD.cpp +git rm lib/arch/CArchNetworkBSD.h +git rm lib/arch/CArchNetworkWinsock.cpp +git rm lib/arch/CArchNetworkWinsock.h +git rm lib/arch/CArchSleepUnix.cpp +git rm lib/arch/CArchSleepUnix.h +git rm lib/arch/CArchSleepWindows.cpp +git rm lib/arch/CArchSleepWindows.h +git rm lib/arch/CArchStringUnix.cpp +git rm lib/arch/CArchStringUnix.h +git rm lib/arch/CArchStringWindows.cpp +git rm lib/arch/CArchStringWindows.h +git rm lib/arch/CArchSystemUnix.cpp +git rm lib/arch/CArchSystemUnix.h +git rm lib/arch/CArchSystemWindows.cpp +git rm lib/arch/CArchSystemWindows.h +git rm lib/arch/CArchTaskBarWindows.cpp +git rm lib/arch/CArchTaskBarWindows.h +git rm lib/arch/CArchTaskBarXWindows.cpp +git rm lib/arch/CArchTaskBarXWindows.h +git rm lib/arch/CArchTimeUnix.cpp +git rm lib/arch/CArchTimeUnix.h +git rm lib/arch/CArchTimeWindows.cpp +git rm lib/arch/CArchTimeWindows.h +git rm lib/arch/CMultibyte.cpp +git rm lib/arch/IArchConsole.h +git rm lib/arch/IArchDaemon.h +git rm lib/arch/IArchFile.h +git rm lib/arch/IArchLog.h +git rm lib/arch/IArchMultithread.h +git rm lib/arch/IArchNetwork.h +git rm lib/arch/IArchSleep.h +git rm lib/arch/IArchString.h +git rm lib/arch/IArchSystem.h +git rm lib/arch/IArchTaskBar.h +git rm lib/arch/IArchTaskBarReceiver.h +git rm lib/arch/IArchTime.h +git rm lib/arch/Makefile.am +git rm lib/arch/Makefile.win +git rm lib/arch/XArch.cpp +git rm lib/arch/XArch.h +git rm lib/arch/XArchUnix.cpp +git rm lib/arch/XArchUnix.h +git rm lib/arch/XArchWindows.cpp +git rm lib/arch/XArchWindows.h +git rm lib/arch/vsnprintf.cpp +git rm lib/base/CEvent.cpp +git rm lib/base/CEvent.h +git rm lib/base/CEventQueue.cpp +git rm lib/base/CEventQueue.h +git rm lib/base/CFunctionEventJob.cpp +git rm lib/base/CFunctionEventJob.h +git rm lib/base/CFunctionJob.cpp +git rm lib/base/CFunctionJob.h +git rm lib/base/CLog.cpp +git rm lib/base/CLog.h +git rm lib/base/CPriorityQueue.h +git rm lib/base/CSimpleEventQueueBuffer.cpp +git rm lib/base/CSimpleEventQueueBuffer.h +git rm lib/base/CStopwatch.cpp +git rm lib/base/CStopwatch.h +git rm lib/base/CString.h +git rm lib/base/CStringUtil.cpp +git rm lib/base/CStringUtil.h +git rm lib/base/CUnicode.cpp +git rm lib/base/CUnicode.h +git rm lib/base/IEventJob.h +git rm lib/base/IEventQueue.cpp +git rm lib/base/IEventQueue.h +git rm lib/base/IEventQueueBuffer.h +git rm lib/base/IJob.h +git rm lib/base/ILogOutputter.h +git rm lib/base/LogOutputters.cpp +git rm lib/base/LogOutputters.h +git rm lib/base/Makefile.am +git rm lib/base/Makefile.win +git rm lib/base/TMethodEventJob.h +git rm lib/base/TMethodJob.h +git rm lib/base/XBase.cpp +git rm lib/base/XBase.h +git rm lib/client/CClient.cpp +git rm lib/client/CClient.h +git rm lib/client/CServerProxy.cpp +git rm lib/client/CServerProxy.h +git rm lib/client/Makefile.am +git rm lib/client/Makefile.win +git rm lib/common/BasicTypes.h +git rm lib/common/IInterface.h +git rm lib/common/MacOSXPrecomp.h +git rm lib/common/Makefile.am +git rm lib/common/Makefile.win +git rm lib/common/Version.cpp +git rm lib/common/Version.h +git rm lib/common/common.h +git rm lib/common/stdbitset.h +git rm lib/common/stddeque.h +git rm lib/common/stdfstream.h +git rm lib/common/stdistream.h +git rm lib/common/stdlist.h +git rm lib/common/stdmap.h +git rm lib/common/stdostream.h +git rm lib/common/stdpost.h +git rm lib/common/stdpre.h +git rm lib/common/stdset.h +git rm lib/common/stdsstream.h +git rm lib/common/stdstring.h +git rm lib/common/stdvector.h +git rm lib/io/CStreamBuffer.cpp +git rm lib/io/CStreamBuffer.h +git rm lib/io/CStreamFilter.cpp +git rm lib/io/CStreamFilter.h +git rm lib/io/IStream.cpp +git rm lib/io/IStream.h +git rm lib/io/IStreamFilterFactory.h +git rm lib/io/Makefile.am +git rm lib/io/Makefile.win +git rm lib/io/XIO.cpp +git rm lib/io/XIO.h +git rm lib/mt/CCondVar.cpp +git rm lib/mt/CCondVar.h +git rm lib/mt/CLock.cpp +git rm lib/mt/CLock.h +git rm lib/mt/CMutex.cpp +git rm lib/mt/CMutex.h +git rm lib/mt/CThread.cpp +git rm lib/mt/CThread.h +git rm lib/mt/Makefile.am +git rm lib/mt/Makefile.win +git rm lib/mt/XMT.cpp +git rm lib/mt/XMT.h +git rm lib/mt/XThread.h +git rm lib/net/CNetworkAddress.cpp +git rm lib/net/CNetworkAddress.h +git rm lib/net/CSocketMultiplexer.cpp +git rm lib/net/CSocketMultiplexer.h +git rm lib/net/CTCPListenSocket.cpp +git rm lib/net/CTCPListenSocket.h +git rm lib/net/CTCPSocket.cpp +git rm lib/net/CTCPSocket.h +git rm lib/net/CTCPSocketFactory.cpp +git rm lib/net/CTCPSocketFactory.h +git rm lib/net/IDataSocket.cpp +git rm lib/net/IDataSocket.h +git rm lib/net/IListenSocket.cpp +git rm lib/net/IListenSocket.h +git rm lib/net/ISocket.cpp +git rm lib/net/ISocket.h +git rm lib/net/ISocketFactory.h +git rm lib/net/ISocketMultiplexerJob.h +git rm lib/net/Makefile.am +git rm lib/net/Makefile.win +git rm lib/net/TSocketMultiplexerMethodJob.h +git rm lib/net/XSocket.cpp +git rm lib/net/XSocket.h +git rm lib/platform/CMSWindowsClipboard.cpp +git rm lib/platform/CMSWindowsClipboard.h +git rm lib/platform/CMSWindowsClipboardAnyTextConverter.cpp +git rm lib/platform/CMSWindowsClipboardAnyTextConverter.h +git rm lib/platform/CMSWindowsClipboardBitmapConverter.cpp +git rm lib/platform/CMSWindowsClipboardBitmapConverter.h +git rm lib/platform/CMSWindowsClipboardHTMLConverter.cpp +git rm lib/platform/CMSWindowsClipboardHTMLConverter.h +git rm lib/platform/CMSWindowsClipboardTextConverter.cpp +git rm lib/platform/CMSWindowsClipboardTextConverter.h +git rm lib/platform/CMSWindowsClipboardUTF16Converter.cpp +git rm lib/platform/CMSWindowsClipboardUTF16Converter.h +git rm lib/platform/CMSWindowsDesks.cpp +git rm lib/platform/CMSWindowsDesks.h +git rm lib/platform/CMSWindowsEventQueueBuffer.cpp +git rm lib/platform/CMSWindowsEventQueueBuffer.h +git rm lib/platform/CMSWindowsKeyState.cpp +git rm lib/platform/CMSWindowsKeyState.h +git rm lib/platform/CMSWindowsScreen.cpp +git rm lib/platform/CMSWindowsScreen.h +git rm lib/platform/CMSWindowsScreenSaver.cpp +git rm lib/platform/CMSWindowsScreenSaver.h +git rm lib/platform/CMSWindowsUtil.cpp +git rm lib/platform/CMSWindowsUtil.h +git rm lib/platform/COSXClipboard.cpp +git rm lib/platform/COSXClipboard.h +git rm lib/platform/COSXClipboardAnyTextConverter.cpp +git rm lib/platform/COSXClipboardAnyTextConverter.h +git rm lib/platform/COSXClipboardTextConverter.cpp +git rm lib/platform/COSXClipboardTextConverter.h +git rm lib/platform/COSXClipboardUTF16Converter.cpp +git rm lib/platform/COSXClipboardUTF16Converter.h +git rm lib/platform/COSXEventQueueBuffer.cpp +git rm lib/platform/COSXEventQueueBuffer.h +git rm lib/platform/COSXKeyState.cpp +git rm lib/platform/COSXKeyState.h +git rm lib/platform/COSXScreen.cpp +git rm lib/platform/COSXScreen.h +git rm lib/platform/COSXScreenSaver.cpp +git rm lib/platform/COSXScreenSaver.h +git rm lib/platform/COSXScreenSaverUtil.h +git rm lib/platform/COSXScreenSaverUtil.m +git rm lib/platform/CSynergyHook.cpp +git rm lib/platform/CSynergyHook.h +git rm lib/platform/CXWindowsClipboard.cpp +git rm lib/platform/CXWindowsClipboard.h +git rm lib/platform/CXWindowsClipboardAnyBitmapConverter.cpp +git rm lib/platform/CXWindowsClipboardAnyBitmapConverter.h +git rm lib/platform/CXWindowsClipboardBMPConverter.cpp +git rm lib/platform/CXWindowsClipboardBMPConverter.h +git rm lib/platform/CXWindowsClipboardHTMLConverter.cpp +git rm lib/platform/CXWindowsClipboardHTMLConverter.h +git rm lib/platform/CXWindowsClipboardTextConverter.cpp +git rm lib/platform/CXWindowsClipboardTextConverter.h +git rm lib/platform/CXWindowsClipboardUCS2Converter.cpp +git rm lib/platform/CXWindowsClipboardUCS2Converter.h +git rm lib/platform/CXWindowsClipboardUTF8Converter.cpp +git rm lib/platform/CXWindowsClipboardUTF8Converter.h +git rm lib/platform/CXWindowsEventQueueBuffer.cpp +git rm lib/platform/CXWindowsEventQueueBuffer.h +git rm lib/platform/CXWindowsKeyState.cpp +git rm lib/platform/CXWindowsKeyState.h +git rm lib/platform/CXWindowsScreen.cpp +git rm lib/platform/CXWindowsScreen.h +git rm lib/platform/CXWindowsScreenSaver.cpp +git rm lib/platform/CXWindowsScreenSaver.h +git rm lib/platform/CXWindowsUtil.cpp +git rm lib/platform/CXWindowsUtil.h +git rm lib/platform/Makefile.am +git rm lib/platform/Makefile.win +git rm lib/platform/OSXScreenSaverControl.h +git rm lib/server/CBaseClientProxy.cpp +git rm lib/server/CBaseClientProxy.h +git rm lib/server/CClientListener.cpp +git rm lib/server/CClientListener.h +git rm lib/server/CClientProxy.cpp +git rm lib/server/CClientProxy.h +git rm lib/server/CClientProxy1_0.cpp +git rm lib/server/CClientProxy1_0.h +git rm lib/server/CClientProxy1_1.cpp +git rm lib/server/CClientProxy1_1.h +git rm lib/server/CClientProxy1_2.cpp +git rm lib/server/CClientProxy1_2.h +git rm lib/server/CClientProxy1_3.cpp +git rm lib/server/CClientProxy1_3.h +git rm lib/server/CClientProxyUnknown.cpp +git rm lib/server/CClientProxyUnknown.h +git rm lib/server/CConfig.cpp +git rm lib/server/CConfig.h +git rm lib/server/CInputFilter.cpp +git rm lib/server/CInputFilter.h +git rm lib/server/CPrimaryClient.cpp +git rm lib/server/CPrimaryClient.h +git rm lib/server/CServer.cpp +git rm lib/server/CServer.h +git rm lib/server/Makefile.am +git rm lib/server/Makefile.win +git rm lib/synergy/CClipboard.cpp +git rm lib/synergy/CClipboard.h +git rm lib/synergy/CKeyMap.cpp +git rm lib/synergy/CKeyMap.h +git rm lib/synergy/CKeyState.cpp +git rm lib/synergy/CKeyState.h +git rm lib/synergy/CPacketStreamFilter.cpp +git rm lib/synergy/CPacketStreamFilter.h +git rm lib/synergy/CPlatformScreen.cpp +git rm lib/synergy/CPlatformScreen.h +git rm lib/synergy/CProtocolUtil.cpp +git rm lib/synergy/CProtocolUtil.h +git rm lib/synergy/CScreen.cpp +git rm lib/synergy/CScreen.h +git rm lib/synergy/ClipboardTypes.h +git rm lib/synergy/IClient.h +git rm lib/synergy/IClipboard.cpp +git rm lib/synergy/IClipboard.h +git rm lib/synergy/IKeyState.cpp +git rm lib/synergy/IKeyState.h +git rm lib/synergy/IPlatformScreen.h +git rm lib/synergy/IPrimaryScreen.cpp +git rm lib/synergy/IPrimaryScreen.h +git rm lib/synergy/IScreen.cpp +git rm lib/synergy/IScreen.h +git rm lib/synergy/IScreenSaver.h +git rm lib/synergy/ISecondaryScreen.h +git rm lib/synergy/KeyTypes.cpp +git rm lib/synergy/KeyTypes.h +git rm lib/synergy/Makefile.am +git rm lib/synergy/Makefile.win +git rm lib/synergy/MouseTypes.h +git rm lib/synergy/OptionTypes.h +git rm lib/synergy/ProtocolTypes.cpp +git rm lib/synergy/ProtocolTypes.h +git rm lib/synergy/XScreen.cpp +git rm lib/synergy/XScreen.h +git rm lib/synergy/XSynergy.cpp +git rm lib/synergy/XSynergy.h +git rm win32util/autodep.cpp \ No newline at end of file diff --git a/win32util/autodep.cpp b/win32util/autodep.cpp deleted file mode 100644 index 2a2e9d50..00000000 --- a/win32util/autodep.cpp +++ /dev/null @@ -1,149 +0,0 @@ -#include -#include -#include -#include -#include - -using namespace std; - -static -string -baseName(const string& filename) -{ - return filename.substr(0, filename.rfind('.')); -} - -static -int -writeMakefile(const string& dstdir, const set& depFilenames) -{ - string makeFilename = dstdir + "\\deps.mak"; - ofstream makeFile(makeFilename.c_str()); - if (!makeFile) { - cerr << "Can't open '" << makeFilename << "' for writing" << endl; - return 1; - } - - for (set::const_iterator i = depFilenames.begin(); - i != depFilenames.end(); ++i) { - makeFile << "!if EXIST(\"" << *i << "\")" << endl; - makeFile << "!include \"" << *i << "\"" << endl; - makeFile << "!endif" << endl; - } - - return 0; -} - -static -void -writeDependencies( - const string& filename, - const string& srcdir, - const string& dstdir, - const set& paths) -{ - string basename = baseName(filename); - string depFilename = dstdir + "\\" + basename + ".d"; - ofstream depFile(depFilename.c_str()); - if (!depFile) { - cerr << "Can't open '" << depFilename << "' for writing" << endl; - return; - } - - // Write dependencies rule for filename - depFile << "\"" << dstdir << "\\" << basename << ".obj\": \"" << - srcdir << "\\" << filename << "\" \\" << endl; - for (set::const_iterator i = paths.begin(); i != paths.end(); ++i) { - depFile << "\t\"" << *i << "\" \\" << endl; - } - depFile << "\t$(NULL)" << endl; -} - -static -int -writeDepfiles(const string& srcdir, const string& dstdir) -{ - const string includeLine = "Note: including file:"; - - // Parse stdin - string line; - string filename; - set paths; - locale loc = locale::classic(); - const ctype& ct = use_facet >(loc); - while (getline(cin, line)) { - bool echo = true; - - // Check for include line - if (line.compare(0, includeLine.length(), includeLine) == 0) { - // Strip includeLine and leading spaces - line.erase(0, line.find_first_not_of(" ", includeLine.length())); - if (line.length() == 0) { - continue; - } - - // Uppercase all drive letters - if (line.length() > 2 && line[1] == ':') { - line[0] = ct.toupper(line[0]); - } - - // Record path - paths.insert(line); - echo = false; - } - - // Maybe a source filename - else if (line.rfind(".cpp") == line.length() - 4) { - // Write dependencies for previous source file - if (filename.length() != 0) { - writeDependencies(filename, srcdir, dstdir, paths); - paths.clear(); - } - filename = line; - } - - // Otherwise other output - else { - // do nothing - } - - if (echo) { - cout << line << endl; - } - } - - // Write dependencies for last source file - if (filename.length() != 0) { - writeDependencies(filename, srcdir, dstdir, paths); - paths.clear(); - } - - return 0; -} - -int -main(int argc, char** argv) -{ - if (argc < 3) { - cerr << "usage: " << argv[0] << - " []" << endl; - return 1; - } - string srcdir = argv[1]; - string dstdir = argv[2]; - - // If depfiles were supplied then create a makefile in outdir to load - // all of them. - int result; - if (argc > 3) { - set depFilenames(argv + 3, argv + argc); - result = writeMakefile(dstdir, depFilenames); - } - - // Otherwise parse stdin and create a depfile for each listed file - else { - result = writeDepfiles(srcdir, dstdir); - } - - return result; -}