Added workaround for apparent Xinerama bug when warping the pointer.

This should allow synergy to be used on a system using Xinerama to
create a single logical screen from multiple physical screens.
This commit is contained in:
crs 2003-04-14 22:15:56 +00:00
parent 019994548c
commit 6a108ed2d5
3 changed files with 49 additions and 5 deletions

View File

@ -57,6 +57,8 @@ AC_PATH_XTRA
save_CPPFLAGS="$CPPFLAGS" save_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$X_CFLAGS $CPPFLAGS" CPPFLAGS="$X_CFLAGS $CPPFLAGS"
AC_CHECK_HEADERS([X11/extensions/XTest.h]) AC_CHECK_HEADERS([X11/extensions/XTest.h])
AC_CHECK_LIB(Xinerama, XineramaQueryExtension, AC_CHECK_HEADERS([X11/extensions/Xinerama.h]) [X_LIBS="$X_LIBS -lXinerama"], , [$X_LIBS -lXext -lX11 $X_EXTRA_LIBS])
CPPFLAGS="$save_CPPFLAGS" CPPFLAGS="$save_CPPFLAGS"
dnl checks for types dnl checks for types

View File

@ -30,6 +30,12 @@
#else #else
# include <X11/X.h> # include <X11/X.h>
# include <X11/Xutil.h> # include <X11/Xutil.h>
# if HAVE_X11_EXTENSIONS_XINERAMA_H
// Xinerama.h may lack extern "C" for inclusion by C++
extern "C" {
# include <X11/extensions/Xinerama.h>
}
# endif
#endif #endif
#if UNIX_LIKE #if UNIX_LIKE
# if HAVE_POLL # if HAVE_POLL
@ -119,6 +125,7 @@ CXWindowsScreen::CXWindowsScreen(IScreenReceiver* receiver,
m_window(None), m_window(None),
m_x(0), m_y(0), m_x(0), m_y(0),
m_w(0), m_h(0), m_w(0), m_h(0),
m_xCenter(0), m_yCenter(0),
m_screensaver(NULL), m_screensaver(NULL),
m_screensaverNotify(false), m_screensaverNotify(false),
m_atomScreensaver(None), m_atomScreensaver(None),
@ -561,8 +568,8 @@ CXWindowsScreen::getCursorPos(SInt32& x, SInt32& y) const
y = my; y = my;
} }
else { else {
x = m_x + (m_w >> 1); x = m_xCenter;
y = m_y + (m_h >> 1); y = m_yCenter;
} }
} }
@ -570,20 +577,54 @@ void
CXWindowsScreen::getCursorCenter(SInt32& x, SInt32& y) const CXWindowsScreen::getCursorCenter(SInt32& x, SInt32& y) const
{ {
CLock lock(&m_mutex); CLock lock(&m_mutex);
assert(m_display != NULL);
x = m_x + (m_w >> 1); x = m_xCenter;
y = m_y + (m_h >> 1); y = m_yCenter;
} }
void void
CXWindowsScreen::updateScreenShape() CXWindowsScreen::updateScreenShape()
{ {
// get shape of default screen
m_x = 0; m_x = 0;
m_y = 0; m_y = 0;
m_w = WidthOfScreen(DefaultScreenOfDisplay(m_display)); m_w = WidthOfScreen(DefaultScreenOfDisplay(m_display));
m_h = HeightOfScreen(DefaultScreenOfDisplay(m_display)); m_h = HeightOfScreen(DefaultScreenOfDisplay(m_display));
LOG((CLOG_INFO "screen shape: %d,%d %dx%d", m_x, m_y, m_w, m_h)); LOG((CLOG_INFO "screen shape: %d,%d %dx%d", m_x, m_y, m_w, m_h));
// get center of default screen
m_xCenter = m_x + (m_w >> 1);
m_yCenter = m_y + (m_h >> 1);
#if HAVE_X11_EXTENSIONS_XINERAMA_H
// 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.
int eventBase, errorBase;
if (XineramaQueryExtension(m_display, &eventBase, &errorBase)) {
if (XineramaIsActive(m_display)) {
int numScreens;
XineramaScreenInfo* screens;
screens = XineramaQueryScreens(m_display, &numScreens);
if (screens != NULL) {
if (numScreens > 1) {
m_xCenter = screens[0].x_org + (screens[0].width >> 1);
m_yCenter = screens[0].y_org + (screens[0].height >> 1);
}
XFree(screens);
}
}
}
#endif
} }
bool bool

View File

@ -271,6 +271,7 @@ private:
SInt32 m_x, m_y; SInt32 m_x, m_y;
SInt32 m_w, m_h; SInt32 m_w, m_h;
SInt32 m_xCenter, m_yCenter;
// clipboards // clipboards
CXWindowsClipboard* m_clipboard[kClipboardEnd]; CXWindowsClipboard* m_clipboard[kClipboardEnd];