diff --git a/Make-linux b/Make-linux index 98572f46..8300b12d 100644 --- a/Make-linux +++ b/Make-linux @@ -13,7 +13,7 @@ RMR = /bin/rm -rf # # compiler options # -GCXXDEFS = -D_XOPEN_SOURCE=600 +GCXXDEFS = -D_XOPEN_SOURCE=600 -D_SVID_SOURCE GCXXINCS = -I$(DEPTH)/include -I/usr/X11R6/include GCXXOPTS = -Wall -W -fexceptions CXXOPTIMIZER = -g diff --git a/net/CNetwork.h b/net/CNetwork.h index fcc65e40..8d6e9842 100644 --- a/net/CNetwork.h +++ b/net/CNetwork.h @@ -9,6 +9,9 @@ # define INCL_WINSOCK_API_TYPEDEFS 0 # include typedef int ssize_t; +# if !defined(SOL_TCP) +# define SOL_TCP IPPROTO_TCP +# endif #else # define FAR # define PASCAL @@ -21,6 +24,9 @@ typedef int ssize_t; # include # include # include +# if !defined(TCP_NODELAY) || !defined(SOL_TCP) +# include +# endif #endif // FIXME -- must handle htonl and ilk when defined as macros @@ -31,6 +37,7 @@ public: typedef SOCKET Socket; typedef struct sockaddr Address; typedef int AddressLength; + typedef BOOL TCPNoDelayType; struct PollEntry { Socket fd; short events; @@ -47,6 +54,7 @@ public: typedef struct sockaddr Address; typedef socklen_t AddressLength; typedef struct pollfd PollEntry; + typedef int TCPNoDelayType; enum { kPOLLIN = POLLIN, kPOLLOUT = POLLOUT, diff --git a/net/CTCPSocket.cpp b/net/CTCPSocket.cpp index ce32c846..f5f4f3a5 100644 --- a/net/CTCPSocket.cpp +++ b/net/CTCPSocket.cpp @@ -128,6 +128,16 @@ void CTCPSocket::init() m_output = new CBufferedOutputStream(m_mutex, new TMethodJob( this, &CTCPSocket::closeOutput)); + + // 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. + CNetwork::TCPNoDelayType flag = 1; + CNetwork::setsockopt(m_fd, SOL_TCP, TCP_NODELAY, &flag, sizeof(flag)); + + // don't buffer sends, we merge messages ourself + int data = 0; + CNetwork::setsockopt(m_fd, SOL_SOCKET, SO_SNDBUF, &data, sizeof(data)); } void CTCPSocket::ioThread(void*) diff --git a/synergy/CXWindowsScreen.cpp b/synergy/CXWindowsScreen.cpp index b3dd2bf2..58fb5d0a 100644 --- a/synergy/CXWindowsScreen.cpp +++ b/synergy/CXWindowsScreen.cpp @@ -261,6 +261,23 @@ void CXWindowsScreen::getDisplayClipboard( CLock lock(&m_mutex); Atom selection = m_atomClipboard[id]; + // if we're trying to request the clipboard from the same + // unresponsive owner then immediately give up. this is lame + // because we can't be sure the owner won't become responsive; + // we can only ask the X server for the current owner, not the + // owner at time timestamp, allowing a race condition; and we + // don't detect if the owner window is destroyed in order to + // reset the unresponsive flag. + Window owner = XGetSelectionOwner(m_display, selection); + if (m_clipboards[id].m_unresponsive) { + if (owner != None && owner == m_clipboards[id].m_owner) { + clipboard->close(); + return; + } + } + CClipboardInfo& clipboardInfo = + const_cast(m_clipboards[id]); + // ask the selection for all the formats it has. some owners return // the TARGETS atom and some the ATOM atom when TARGETS is requested. Atom format; @@ -268,6 +285,10 @@ void CXWindowsScreen::getDisplayClipboard( if (getDisplayClipboard(selection, m_atomTargets, requestor, timestamp, &format, &targets) && (format == m_atomTargets || format == XA_ATOM)) { + // save owner info + clipboardInfo.m_owner = owner; + clipboardInfo.m_unresponsive = false; + // get each target (that we can interpret). some owners return // some targets multiple times in the list so don't try to get // those multiple times. @@ -330,6 +351,11 @@ void CXWindowsScreen::getDisplayClipboard( else { // non-ICCCM conforming selection owner. try TEXT format. // FIXME + + // save owner info + clipboardInfo.m_owner = owner; + clipboardInfo.m_unresponsive = true; + log((CLOG_DEBUG1 "selection doesn't support TARGETS, format is %d", format)); } @@ -1014,7 +1040,9 @@ Time CXWindowsScreen::getCurrentTimeNoLock( CXWindowsScreen::CClipboardInfo::CClipboardInfo() : m_clipboard(), m_lostClipboard(CurrentTime), - m_requests() + m_requests(), + m_owner(None), + m_unresponsive(false) { // do nothing } diff --git a/synergy/CXWindowsScreen.h b/synergy/CXWindowsScreen.h index 66df2968..0f81414a 100644 --- a/synergy/CXWindowsScreen.h +++ b/synergy/CXWindowsScreen.h @@ -161,6 +161,12 @@ private: // the request queues CRequestMap m_requests; + + // owner of clipboard when we last asked for it + Window m_owner; + + // true iff the previous request to m_owner got no reply + bool m_unresponsive; }; Display* m_display;