checkpoint. making win32 and X primary screen code more similar

in order to share code later.
This commit is contained in:
crs 2002-07-11 18:58:49 +00:00
parent feeb15a08d
commit ef7fe1f283
10 changed files with 625 additions and 467 deletions

View File

@ -85,19 +85,46 @@ void
CXWindowsSecondaryScreen::open() CXWindowsSecondaryScreen::open()
{ {
assert(m_receiver != NULL); assert(m_receiver != NULL);
assert(m_window == None);
// open the display // open the display
openDisplay(); openDisplay();
{ {
// verify the availability of the XTest extension
CDisplayLock display(this); CDisplayLock display(this);
// verify the availability of the XTest extension
int majorOpcode, firstEvent, firstError; int majorOpcode, firstEvent, firstError;
if (!XQueryExtension(display, XTestExtensionName, if (!XQueryExtension(display, XTestExtensionName,
&majorOpcode, &firstEvent, &firstError)) { &majorOpcode, &firstEvent, &firstError)) {
throw int(6); // FIXME -- make exception for this throw int(6); // FIXME -- make exception for this
} }
// create the cursor hiding window. 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 cursor is
// moved.
XSetWindowAttributes attr;
attr.event_mask = LeaveWindowMask;
attr.do_not_propagate_mask = 0;
attr.override_redirect = True;
attr.cursor = getBlankCursor();
m_window = XCreateWindow(display, getRoot(), 0, 0, 1, 1, 0, 0,
InputOnly, CopyFromParent,
CWDontPropagate | CWEventMask |
CWOverrideRedirect | CWCursor,
&attr);
log((CLOG_DEBUG "window is 0x%08x", m_window));
// become impervious to server grabs
XTestGrabControl(display, True);
// hide the cursor
leaveNoLock(display);
// initialize the clipboards
initClipboards(m_window);
// update key state // update key state
updateKeys(display); updateKeys(display);
updateKeycodeMap(display); updateKeycodeMap(display);
@ -130,6 +157,18 @@ CXWindowsSecondaryScreen::close()
// restore the screen saver settings // restore the screen saver settings
getScreenSaver()->enable(); getScreenSaver()->enable();
{
CDisplayLock display(this);
if (display != NULL) {
// no longer impervious to server grabs
XTestGrabControl(display, False);
// destroy window
XDestroyWindow(display, m_window);
}
m_window = None;
}
// close the display // close the display
closeDisplay(); closeDisplay();
} }
@ -304,13 +343,7 @@ void
CXWindowsSecondaryScreen::getMousePos(SInt32& x, SInt32& y) const CXWindowsSecondaryScreen::getMousePos(SInt32& x, SInt32& y) const
{ {
CDisplayLock display(this); CDisplayLock display(this);
int xTmp, yTmp, dummy; getCursorPos(x, y);
unsigned int dummyMask;
Window dummyWindow;
XQueryPointer(display, getRoot(), &dummyWindow, &dummyWindow,
&xTmp, &yTmp, &dummy, &dummy, &dummyMask);
x = xTmp;
y = yTmp;
} }
void void
@ -333,56 +366,6 @@ CXWindowsSecondaryScreen::getClipboard(ClipboardID id,
getDisplayClipboard(id, clipboard); getDisplayClipboard(id, clipboard);
} }
void
CXWindowsSecondaryScreen::onOpenDisplay(Display* display)
{
assert(m_window == None);
// create the cursor hiding window. 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 cursor is
// moved.
XSetWindowAttributes attr;
attr.event_mask = LeaveWindowMask;
attr.do_not_propagate_mask = 0;
attr.override_redirect = True;
attr.cursor = createBlankCursor();
m_window = XCreateWindow(display, getRoot(), 0, 0, 1, 1, 0, 0,
InputOnly, CopyFromParent,
CWDontPropagate | CWEventMask |
CWOverrideRedirect | CWCursor,
&attr);
log((CLOG_DEBUG "window is 0x%08x", m_window));
// become impervious to server grabs
XTestGrabControl(display, True);
// hide the cursor
leaveNoLock(display);
}
CXWindowsClipboard*
CXWindowsSecondaryScreen::createClipboard(ClipboardID id)
{
CDisplayLock display(this);
return new CXWindowsClipboard(display, m_window, id);
}
void
CXWindowsSecondaryScreen::onCloseDisplay(Display* display)
{
assert(m_window != None);
if (display != NULL) {
// no longer impervious to server grabs
XTestGrabControl(display, False);
// destroy window
XDestroyWindow(display, m_window);
}
m_window = None;
}
void void
CXWindowsSecondaryScreen::onLostClipboard(ClipboardID id) CXWindowsSecondaryScreen::onLostClipboard(ClipboardID id)
{ {

View File

@ -39,10 +39,6 @@ public:
protected: protected:
// CXWindowsScreen overrides // CXWindowsScreen overrides
virtual void onOpenDisplay(Display*);
virtual CXWindowsClipboard*
createClipboard(ClipboardID);
virtual void onCloseDisplay(Display*);
virtual void onLostClipboard(ClipboardID); virtual void onLostClipboard(ClipboardID);
private: private:

View File

@ -84,16 +84,8 @@ CMSWindowsScreen::openDisplay()
assert(s_instance != NULL); assert(s_instance != NULL);
assert(m_class == 0); assert(m_class == 0);
// create a transparent cursor // create the transparent cursor
int cw = GetSystemMetrics(SM_CXCURSOR); createBlankCursor();
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));
m_cursor = CreateCursor(s_instance, 0, 0, cw, ch, cursorAND, cursorXOR);
delete[] cursorXOR;
delete[] cursorAND;
// register a window class // register a window class
WNDCLASSEX classInfo; WNDCLASSEX classInfo;
@ -109,14 +101,11 @@ CMSWindowsScreen::openDisplay()
classInfo.lpszMenuName = NULL; classInfo.lpszMenuName = NULL;
classInfo.lpszClassName = "Synergy"; classInfo.lpszClassName = "Synergy";
classInfo.hIconSm = NULL; classInfo.hIconSm = NULL;
m_class = RegisterClassEx(&classInfo); m_class = RegisterClassEx(&classInfo);
// get screen shape // get screen shape
updateScreenShape(); updateScreenShape();
// let subclass prep display
onOpenDisplay();
// initialize the screen saver // initialize the screen saver
m_screenSaver = new CMSWindowsScreenSaver(); m_screenSaver = new CMSWindowsScreenSaver();
} }
@ -125,22 +114,22 @@ void
CMSWindowsScreen::closeDisplay() CMSWindowsScreen::closeDisplay()
{ {
assert(s_instance != NULL); assert(s_instance != NULL);
assert(m_class != 0);
// done with screen saver // done with screen saver
delete m_screenSaver; delete m_screenSaver;
m_screenSaver = NULL; m_screenSaver = NULL;
// let subclass close down display
onCloseDisplay();
// unregister the window class // unregister the window class
UnregisterClass((LPCTSTR)m_class, s_instance); if (m_class != 0) {
m_class = 0; UnregisterClass((LPCTSTR)m_class, s_instance);
m_class = 0;
}
// delete resources // delete resources
DestroyCursor(m_cursor); if (m_cursor != NULL) {
m_cursor = NULL; DestroyCursor(m_cursor);
m_cursor = NULL;
}
log((CLOG_DEBUG "closed display")); log((CLOG_DEBUG "closed display"));
} }
@ -168,8 +157,8 @@ CMSWindowsScreen::updateScreenShape()
} }
void void
CMSWindowsScreen::getScreenShape( CMSWindowsScreen::getScreenShape(SInt32& x, SInt32& y,
SInt32& x, SInt32& y, SInt32& w, SInt32& h) const SInt32& w, SInt32& h) const
{ {
assert(m_class != 0); assert(m_class != 0);
@ -179,6 +168,43 @@ CMSWindowsScreen::getScreenShape(
h = m_h; h = m_h;
} }
void
CMSWindowsScreen::getCursorPos(SInt32& x, SInt32& y) const
{
POINT pos;
GetCursorPos(&pos);
x = pos.x;
y = pos.y;
}
void
CMSWindowsScreen::getCursorCenter(SInt32& x, SInt32& y) const
{
x = GetSystemMetrics(SM_CXSCREEN) >> 1;
y = GetSystemMetrics(SM_CYSCREEN) >> 1;
}
HCURSOR
CMSWindowsScreen::getBlankCursor() const
{
return m_cursor;
}
void
CMSWindowsScreen::createBlankCursor()
{
// 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));
m_cursor = CreateCursor(s_instance, 0, 0, cw, ch, cursorAND, cursorXOR);
delete[] cursorXOR;
delete[] cursorAND;
}
HDESK HDESK
CMSWindowsScreen::openInputDesktop() const CMSWindowsScreen::openInputDesktop() const
{ {

View File

@ -51,6 +51,12 @@ protected:
void getScreenShape(SInt32& x, SInt32& y, void getScreenShape(SInt32& x, SInt32& y,
SInt32& width, SInt32& height) const; SInt32& width, SInt32& height) const;
// get the current cursor position
void getCursorPos(SInt32& x, SInt32& y) const;
// get the cursor center position
void getCursorCenter(SInt32& x, SInt32& y) const;
// get the input desktop. caller must CloseDesktop() the result. // get the input desktop. caller must CloseDesktop() the result.
// do not call under windows 95/98/me. // do not call under windows 95/98/me.
HDESK openInputDesktop() const; HDESK openInputDesktop() const;
@ -76,16 +82,13 @@ protected:
// called by window proc. subclass must call DefWindowProc() if necessary // called by window proc. subclass must call DefWindowProc() if necessary
virtual LRESULT onEvent(HWND, UINT, WPARAM, LPARAM) = 0; virtual LRESULT onEvent(HWND, UINT, WPARAM, LPARAM) = 0;
// called by openDisplay() to allow subclasses to prepare the display
virtual void onOpenDisplay() = 0;
// called by closeDisplay() to
virtual void onCloseDisplay() = 0;
// called by isCurrentDesktop() to get the current desktop name // called by isCurrentDesktop() to get the current desktop name
virtual CString getCurrentDesktopName() const = 0; virtual CString getCurrentDesktopName() const = 0;
private: private:
// create the transparent cursor
void createBlankCursor();
static LRESULT CALLBACK wndProc(HWND, UINT, WPARAM, LPARAM); static LRESULT CALLBACK wndProc(HWND, UINT, WPARAM, LPARAM);
private: private:

View File

@ -141,27 +141,15 @@ CXWindowsScreen::openDisplay()
throw XScreenOpenFailure(); throw XScreenOpenFailure();
} }
// get default screen // get default screen and root window
m_screen = DefaultScreen(m_display); m_screen = DefaultScreen(m_display);
Screen* screen = ScreenOfDisplay(m_display, m_screen); m_root = RootWindow(m_display, m_screen);
// create the transparent cursor
createBlankCursor();
// get screen shape // get screen shape
m_x = 0; updateScreenShape();
m_y = 0;
m_w = WidthOfScreen(screen);
m_h = HeightOfScreen(screen);
log((CLOG_INFO "screen shape: %d,%d %dx%d", m_x, m_y, m_w, m_h));
// get the root window
m_root = RootWindow(m_display, m_screen);
// let subclass prep display
onOpenDisplay(m_display);
// initialize clipboards
for (ClipboardID id = 0; id < kClipboardEnd; ++id) {
m_clipboard[id] = createClipboard(id);
}
// initialize the screen saver // initialize the screen saver
m_screenSaver = new CXWindowsScreenSaver(this, m_display); m_screenSaver = new CXWindowsScreenSaver(this, m_display);
@ -172,9 +160,6 @@ CXWindowsScreen::closeDisplay()
{ {
CLock lock(&m_mutex); CLock lock(&m_mutex);
// let subclass close down display
onCloseDisplay(m_display);
// done with screen saver // done with screen saver
delete m_screenSaver; delete m_screenSaver;
m_screenSaver = NULL; m_screenSaver = NULL;
@ -209,8 +194,30 @@ CXWindowsScreen::getRoot() const
} }
void void
CXWindowsScreen::getScreenShape( CXWindowsScreen::initClipboards(Window window)
SInt32& x, SInt32& y, SInt32& w, SInt32& h) const {
assert(m_display != NULL);
assert(window != None);
// initialize clipboards
for (ClipboardID id = 0; id < kClipboardEnd; ++id) {
m_clipboard[id] = new CXWindowsClipboard(m_display, window, id);
}
}
void
CXWindowsScreen::updateScreenShape()
{
m_x = 0;
m_y = 0;
m_w = WidthOfScreen(ScreenOfDisplay(m_display, m_screen));
m_h = HeightOfScreen(ScreenOfDisplay(m_display, m_screen));
log((CLOG_INFO "screen shape: %d,%d %dx%d", m_x, m_y, m_w, m_h));
}
void
CXWindowsScreen::getScreenShape(SInt32& x, SInt32& y,
SInt32& w, SInt32& h) const
{ {
assert(m_display != NULL); assert(m_display != NULL);
@ -220,8 +227,35 @@ CXWindowsScreen::getScreenShape(
h = m_h; h = m_h;
} }
Cursor void
CXWindowsScreen::createBlankCursor() const CXWindowsScreen::getCursorPos(SInt32& x, SInt32& y) const
{
assert(m_display != NULL);
Window root, window;
int mx, my, xWindow, yWindow;
unsigned int mask;
if (XQueryPointer(m_display, getRoot(), &root, &window,
&mx, &my, &xWindow, &yWindow, &mask)) {
x = mx;
y = my;
}
else {
getCursorCenter(x, y);
}
}
void
CXWindowsScreen::getCursorCenter(SInt32& x, SInt32& y) const
{
assert(m_display != NULL);
x = m_x + (m_w >> 1);
y = m_y + (m_h >> 1);
}
void
CXWindowsScreen::createBlankCursor()
{ {
// this seems just a bit more complicated than really necessary // this seems just a bit more complicated than really necessary
@ -246,14 +280,18 @@ CXWindowsScreen::createBlankCursor() const
color.flags = DoRed | DoGreen | DoBlue; color.flags = DoRed | DoGreen | DoBlue;
// make cursor from bitmap // make cursor from bitmap
Cursor cursor = XCreatePixmapCursor(m_display, bitmap, bitmap, m_cursor = XCreatePixmapCursor(m_display, bitmap, bitmap,
&color, &color, 0, 0); &color, &color, 0, 0);
// don't need bitmap or the data anymore // don't need bitmap or the data anymore
delete[] data; delete[] data;
XFreePixmap(m_display, bitmap); XFreePixmap(m_display, bitmap);
}
return cursor; Cursor
CXWindowsScreen::getBlankCursor() const
{
return m_cursor;
} }
bool bool

View File

@ -57,17 +57,31 @@ protected:
// is closed. // is closed.
void closeDisplay(); void closeDisplay();
// get the opened screen, its shape, its root window. to get the // get the opened screen and its root window. to get the display
// display create a CDisplayLock object passing this. while the // create a CDisplayLock object passing this. while the object
// object exists no other threads may access the display. do not // exists no other threads may access the display. do not save
// save the Display* beyond the lifetime of the CDisplayLock. // the Display* beyond the lifetime of the CDisplayLock.
int getScreen() const; int getScreen() const;
void getScreenShape(
SInt32& x, SInt32& y, SInt32& w, SInt32& h) const;
Window getRoot() const; Window getRoot() const;
// create a cursor that is transparent everywhere // initialize the clipboards
Cursor createBlankCursor() const; void initClipboards(Window);
// update screen size cache
void updateScreenShape();
// get the shape of the screen
void getScreenShape(SInt32& x, SInt32& y,
SInt32& width, SInt32& height) const;
// get the current cursor position
void getCursorPos(SInt32& x, SInt32& y) const;
// get the cursor center position
void getCursorCenter(SInt32& x, SInt32& y) const;
// get a cursor that is transparent everywhere
Cursor getBlankCursor() const;
// wait for and get the next X event. cancellable. // wait for and get the next X event. cancellable.
bool getEvent(XEvent*) const; bool getEvent(XEvent*) const;
@ -88,19 +102,6 @@ protected:
CXWindowsScreenSaver* CXWindowsScreenSaver*
getScreenSaver() const; getScreenSaver() const;
// called by openDisplay() to allow subclasses to prepare the display.
// the display is locked and passed to the subclass.
virtual void onOpenDisplay(Display*) = 0;
// called by openDisplay() after onOpenDisplay() to create each clipboard
virtual CXWindowsClipboard*
createClipboard(ClipboardID) = 0;
// called by closeDisplay() to allow subclasses to clean up the display.
// the display is locked and passed to the subclass. note that the
// display may be NULL if the display has unexpectedly disconnected.
virtual void onCloseDisplay(Display*) = 0;
// called if the display is unexpectedly closing. default does nothing. // called if the display is unexpectedly closing. default does nothing.
virtual void onUnexpectedClose(); virtual void onUnexpectedClose();
@ -108,6 +109,9 @@ protected:
virtual void onLostClipboard(ClipboardID) = 0; virtual void onLostClipboard(ClipboardID) = 0;
private: private:
// create the transparent cursor
void createBlankCursor();
// remove a timer without locking // remove a timer without locking
void removeTimerNoLock(IJob*); void removeTimerNoLock(IJob*);
@ -248,6 +252,9 @@ private:
// clipboards // clipboards
CXWindowsClipboard* m_clipboard[kClipboardEnd]; CXWindowsClipboard* m_clipboard[kClipboardEnd];
// the transparent cursor
Cursor m_cursor;
// screen saver // screen saver
CXWindowsScreenSaver* m_screenSaver; CXWindowsScreenSaver* m_screenSaver;

View File

@ -82,11 +82,6 @@ CMSWindowsPrimaryScreen::~CMSWindowsPrimaryScreen()
assert(m_hookLibrary != NULL); assert(m_hookLibrary != NULL);
assert(m_window == NULL); assert(m_window == NULL);
// uninstall screen saver hook
if (m_uninstallScreenSaver != NULL) {
m_uninstallScreenSaver();
}
// done with hook library // done with hook library
FreeLibrary(m_hookLibrary); FreeLibrary(m_hookLibrary);
} }
@ -127,54 +122,74 @@ CMSWindowsPrimaryScreen::stop()
void void
CMSWindowsPrimaryScreen::open() CMSWindowsPrimaryScreen::open()
{ {
// open the display assert(m_window == NULL);
openDisplay();
// initialize marks
m_mark = 0;
m_markReceived = 0;
nextMark();
// save cursor pos
POINT pos;
GetCursorPos(&pos);
m_x = pos.x;
m_y = pos.y;
// send screen info
CClientInfo info; CClientInfo info;
getScreenShape(info.m_x, info.m_y, info.m_w, info.m_h); try {
info.m_zoneSize = getJumpZoneSize(); // initialize hook library
info.m_mx = m_x; m_threadID = GetCurrentThreadId();
info.m_my = m_y; m_init(m_threadID);
m_receiver->onInfoChanged(info);
// compute center pixel of primary screen // open the display
m_xCenter = GetSystemMetrics(SM_CXSCREEN) >> 1; openDisplay();
m_yCenter = GetSystemMetrics(SM_CYSCREEN) >> 1;
// get keyboard state // create and prepare our window
updateKeys(); createWindow();
// set jump zones // set jump zones
m_setZone(info.m_x, info.m_y, info.m_w, info.m_h, info.m_zoneSize); m_setZone(info.m_x, info.m_y, info.m_w, info.m_h, info.m_zoneSize);
// initialize marks
m_mark = 0;
m_markReceived = 0;
nextMark();
// collect screen info
getScreenShape(info.m_x, info.m_y, info.m_w, info.m_h);
getCursorPos(info.m_mx, info.m_my);
info.m_zoneSize = getJumpZoneSize();
// save mouse position
m_x = info.m_mx;
m_y = info.m_my;
// compute center pixel of primary screen
getCursorCenter(m_xCenter, m_yCenter);
// get keyboard state
updateKeys();
// get notified of screen saver activation/deactivation
installScreenSaver();
}
catch (...) {
close();
throw;
}
// enter the screen // enter the screen
enterNoWarp(); enterNoWarp();
// send screen info
m_receiver->onInfoChanged(info);
} }
void void
CMSWindowsPrimaryScreen::close() CMSWindowsPrimaryScreen::close()
{ {
// close the display uninstallScreenSaver();
destroyWindow();
closeDisplay(); closeDisplay();
m_cleanup();
m_threadID = 0;
} }
void void
CMSWindowsPrimaryScreen::enter(SInt32 x, SInt32 y, bool forScreenSaver) CMSWindowsPrimaryScreen::enter(SInt32 x, SInt32 y, bool forScreenSaver)
{ {
log((CLOG_INFO "entering primary at %d,%d", x, y)); log((CLOG_INFO "entering primary at %d,%d%s", x, y, forScreenSaver ? " for screen saver" : ""));
assert(m_active == true); assert(m_active == true);
assert(m_window != NULL);
// enter the screen // enter the screen
enterNoWarp(); enterNoWarp();
@ -190,12 +205,13 @@ CMSWindowsPrimaryScreen::leave()
{ {
log((CLOG_INFO "leaving primary")); log((CLOG_INFO "leaving primary"));
assert(m_active == false); assert(m_active == false);
assert(m_window != NULL);
// all messages prior to now are invalid // all messages prior to now are invalid
nextMark(); nextMark();
// save active window, show ours, and grab mouse/keyboard // show our window
if (!onLeave()) { if (!showWindow()) {
return false; return false;
} }
@ -229,6 +245,48 @@ CMSWindowsPrimaryScreen::leave()
// local client now active // local client now active
m_active = true; m_active = true;
// make sure our idea of clipboard ownership is correct
checkClipboard();
return true;
}
void
CMSWindowsPrimaryScreen::reconfigure(UInt32 activeSides)
{
m_setSides(activeSides);
}
void
CMSWindowsPrimaryScreen::warpCursor(SInt32 x, SInt32 y)
{
// set the cursor position without generating an event
// FIXME -- doesn't this generate an event anyway?
SetCursorPos(x, y);
// save position as last position
m_x = x;
m_y = y;
}
void
CMSWindowsPrimaryScreen::warpCursorToCenter()
{
// warp to center. the extra info tells the hook DLL to send
// SYNERGY_MSG_POST_WARP instead of SYNERGY_MSG_MOUSE_MOVE.
SInt32 x, y, w, h;
getScreenShape(x, y, w, h);
mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE,
(DWORD)((65535.99 * (m_xCenter - x)) / (w - 1)),
(DWORD)((65535.99 * (m_yCenter - y)) / (h - 1)),
0,
0x12345678);
// FIXME -- ignore mouse until we get warp notification?
}
void
CMSWindowsPrimaryScreen::checkClipboard()
{
// if we think we own the clipboard but we don't then somebody // if we think we own the clipboard but we don't then somebody
// grabbed the clipboard on this screen without us knowing. // grabbed the clipboard on this screen without us knowing.
// tell the server that this screen grabbed the clipboard. // tell the server that this screen grabbed the clipboard.
@ -253,45 +311,13 @@ CMSWindowsPrimaryScreen::leave()
// ignore // ignore
} }
} }
return true;
}
void
CMSWindowsPrimaryScreen::reconfigure(UInt32 activeSides)
{
m_setSides(activeSides);
}
void
CMSWindowsPrimaryScreen::warpCursor(SInt32 x, SInt32 y)
{
// set the cursor position without generating an event
SetCursorPos(x, y);
// save position as last position
m_x = x;
m_y = y;
}
void
CMSWindowsPrimaryScreen::warpCursorToCenter()
{
// warp to center. the extra info tells the hook DLL to send
// SYNERGY_MSG_POST_WARP instead of SYNERGY_MSG_MOUSE_MOVE.
SInt32 x, y, w, h;
getScreenShape(x, y, w, h);
mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE,
(DWORD)((65535.99 * (m_xCenter - x)) / (w - 1)),
(DWORD)((65535.99 * (m_yCenter - y)) / (h - 1)),
0,
0x12345678);
} }
void void
CMSWindowsPrimaryScreen::setClipboard(ClipboardID /*id*/, CMSWindowsPrimaryScreen::setClipboard(ClipboardID /*id*/,
const IClipboard* src) const IClipboard* src)
{ {
// FIXME -- this is identical to CMSWindowsSecondaryScreen's code
assert(m_window != NULL); assert(m_window != NULL);
CMSWindowsClipboard dst(m_window); CMSWindowsClipboard dst(m_window);
@ -301,10 +327,12 @@ CMSWindowsPrimaryScreen::setClipboard(ClipboardID /*id*/,
void void
CMSWindowsPrimaryScreen::grabClipboard(ClipboardID /*id*/) CMSWindowsPrimaryScreen::grabClipboard(ClipboardID /*id*/)
{ {
// FIXME -- this is identical to CMSWindowsSecondaryScreen's code
assert(m_window != NULL); assert(m_window != NULL);
CMSWindowsClipboard clipboard(m_window); CMSWindowsClipboard clipboard(m_window);
if (clipboard.open(0)) { if (clipboard.open(0)) {
// FIXME -- don't we need to empty it?
clipboard.close(); clipboard.close();
} }
} }
@ -313,6 +341,7 @@ void
CMSWindowsPrimaryScreen::getClipboard(ClipboardID /*id*/, CMSWindowsPrimaryScreen::getClipboard(ClipboardID /*id*/,
IClipboard* dst) const IClipboard* dst) const
{ {
// FIXME -- this is identical to CMSWindowsSecondaryScreen's code
assert(m_window != NULL); assert(m_window != NULL);
CMSWindowsClipboard src(m_window); CMSWindowsClipboard src(m_window);
@ -378,67 +407,6 @@ CMSWindowsPrimaryScreen::isLockedToScreen() const
return false; return false;
} }
void
CMSWindowsPrimaryScreen::onOpenDisplay()
{
assert(m_window == NULL);
// save thread id. we'll need to pass this to the hook library.
m_threadID = GetCurrentThreadId();
// initialize hook library
m_init(m_threadID);
try {
// install the screen saver hook
if (m_installScreenSaver != NULL) {
m_installScreenSaver();
}
// get the input desktop and switch to it
if (m_is95Family) {
if (!openDesktop()) {
throw XScreenOpenFailure();
}
}
else {
if (!switchDesktop(openInputDesktop())) {
throw XScreenOpenFailure();
}
}
}
catch (...) {
m_cleanup();
throw;
}
}
void
CMSWindowsPrimaryScreen::onCloseDisplay()
{
// disconnect from desktop
if (m_is95Family) {
closeDesktop();
}
else {
switchDesktop(NULL);
}
// uninstall the screen saver hook
if (m_uninstallScreenSaver != NULL) {
m_uninstallScreenSaver();
}
// cleanup hook library
m_cleanup();
// clear thread id
m_threadID = 0;
assert(m_window == NULL);
assert(m_desk == NULL);
}
bool bool
CMSWindowsPrimaryScreen::onPreTranslate(MSG* msg) CMSWindowsPrimaryScreen::onPreTranslate(MSG* msg)
{ {
@ -667,8 +635,7 @@ CMSWindowsPrimaryScreen::onEvent(HWND hwnd, UINT msg,
// do nothing if resolution hasn't changed // do nothing if resolution hasn't changed
if (x != xOld || y != yOld || w != wOld || h != hOld) { if (x != xOld || y != yOld || w != wOld || h != hOld) {
// recompute center pixel of primary screen // recompute center pixel of primary screen
m_xCenter = GetSystemMetrics(SM_CXSCREEN) >> 1; getCursorCenter(m_xCenter, m_yCenter);
m_yCenter = GetSystemMetrics(SM_CYSCREEN) >> 1;
// warp mouse to center if active // warp mouse to center if active
if (m_active) { if (m_active) {
@ -720,33 +687,14 @@ CMSWindowsPrimaryScreen::enterNoWarp()
m_setRelay(false); m_setRelay(false);
// restore active window and hide our window // restore active window and hide our window
onEnter(); hideWindow();
// all messages prior to now are invalid // all messages prior to now are invalid
nextMark(); nextMark();
} }
void
CMSWindowsPrimaryScreen::onEnter()
{
// restore the active window and hide our window. we can only set
// the active window for another thread if we first attach our input
// to that thread.
ReleaseCapture();
if (m_lastActiveWindow != NULL) {
DWORD myThread = GetCurrentThreadId();
if (AttachThreadInput(myThread, m_lastActiveThread, TRUE)) {
// FIXME -- shouldn't raise window if X-Mouse is enabled
// but i have no idea how to do that or check if enabled.
SetActiveWindow(m_lastActiveWindow);
AttachThreadInput(myThread, m_lastActiveThread, FALSE);
}
}
ShowWindow(m_window, SW_HIDE);
}
bool bool
CMSWindowsPrimaryScreen::onLeave() CMSWindowsPrimaryScreen::showWindow()
{ {
// remember the active window before we leave. GetActiveWindow() // remember the active window before we leave. GetActiveWindow()
// will only return the active window for the thread's queue (i.e. // will only return the active window for the thread's queue (i.e.
@ -776,6 +724,25 @@ CMSWindowsPrimaryScreen::onLeave()
return true; return true;
} }
void
CMSWindowsPrimaryScreen::hideWindow()
{
// restore the active window and hide our window. we can only set
// the active window for another thread if we first attach our input
// to that thread.
ReleaseCapture();
if (m_lastActiveWindow != NULL) {
DWORD myThread = GetCurrentThreadId();
if (AttachThreadInput(myThread, m_lastActiveThread, TRUE)) {
// FIXME -- shouldn't raise window if X-Mouse is enabled
// but i have no idea how to do that or check if enabled.
SetActiveWindow(m_lastActiveWindow);
AttachThreadInput(myThread, m_lastActiveThread, FALSE);
}
}
ShowWindow(m_window, SW_HIDE);
}
SInt32 SInt32
CMSWindowsPrimaryScreen::getJumpZoneSize() const CMSWindowsPrimaryScreen::getJumpZoneSize() const
{ {
@ -792,6 +759,55 @@ CMSWindowsPrimaryScreen::nextMark()
PostThreadMessage(m_threadID, SYNERGY_MSG_MARK, m_mark, 0); PostThreadMessage(m_threadID, SYNERGY_MSG_MARK, m_mark, 0);
} }
void
CMSWindowsPrimaryScreen::createWindow()
{
// get the input desktop and switch to it
if (m_is95Family) {
if (!openDesktop()) {
throw XScreenOpenFailure();
}
}
else {
if (!switchDesktop(openInputDesktop())) {
throw XScreenOpenFailure();
}
}
}
void
CMSWindowsPrimaryScreen::destroyWindow()
{
// disconnect from desktop
if (m_is95Family) {
closeDesktop();
}
else {
switchDesktop(NULL);
}
assert(m_window == NULL);
assert(m_desk == NULL);
}
void
CMSWindowsPrimaryScreen::installScreenSaver()
{
// install the screen saver hook
if (m_installScreenSaver != NULL) {
m_installScreenSaver();
}
}
void
CMSWindowsPrimaryScreen::uninstallScreenSaver()
{
// uninstall the screen saver hook
if (m_uninstallScreenSaver != NULL) {
m_uninstallScreenSaver();
}
}
bool bool
CMSWindowsPrimaryScreen::openDesktop() CMSWindowsPrimaryScreen::openDesktop()
{ {
@ -835,7 +851,7 @@ CMSWindowsPrimaryScreen::closeDesktop()
if (m_window != NULL) { if (m_window != NULL) {
// restore active window and hide ours // restore active window and hide ours
if (m_active) { if (m_active) {
onEnter(); hideWindow();
} }
// first remove clipboard snooper // first remove clipboard snooper
@ -866,7 +882,7 @@ CMSWindowsPrimaryScreen::switchDesktop(HDESK desk)
if (m_window != NULL) { if (m_window != NULL) {
// restore active window and hide ours // restore active window and hide ours
if (m_active) { if (m_active) {
onEnter(); hideWindow();
} }
// first remove clipboard snooper // first remove clipboard snooper
@ -948,7 +964,7 @@ CMSWindowsPrimaryScreen::switchDesktop(HDESK desk)
// get active window and show ours // get active window and show ours
if (m_active) { if (m_active) {
onLeave(); showWindow();
} }
else { else {
// watch jump zones // watch jump zones

View File

@ -42,8 +42,8 @@ protected:
private: private:
void enterNoWarp(); void enterNoWarp();
void onEnter(); bool showWindow();
bool onLeave(); void hideWindow();
SInt32 getJumpZoneSize() const; SInt32 getJumpZoneSize() const;
@ -51,9 +51,23 @@ private:
// motion deltas while mouse is on secondary screen). // motion deltas while mouse is on secondary screen).
void warpCursorToCenter(); void warpCursorToCenter();
// check clipboard ownership and, if necessary, tell the receiver
// of a grab.
void checkClipboard();
// discard posted messages // discard posted messages
void nextMark(); void nextMark();
// create/destroy window
// also attach to desktop; this destroys and recreates the window
// as necessary.
void createWindow();
void destroyWindow();
// start/stop watch for screen saver changes
void installScreenSaver();
void uninstallScreenSaver();
// open/close desktop (for windows 95/98/me) // open/close desktop (for windows 95/98/me)
bool openDesktop(); bool openDesktop();
void closeDesktop(); void closeDesktop();

View File

@ -6,6 +6,7 @@
#include "CXWindowsUtil.h" #include "CXWindowsUtil.h"
#include "CClipboard.h" #include "CClipboard.h"
#include "ProtocolTypes.h" #include "ProtocolTypes.h"
#include "XScreen.h"
#include "CThread.h" #include "CThread.h"
#include "CLog.h" #include "CLog.h"
#include "CStopwatch.h" #include "CStopwatch.h"
@ -179,9 +180,9 @@ CXWindowsPrimaryScreen::run()
if (xevent.xmotion.send_event) { if (xevent.xmotion.send_event) {
// we warped the mouse. discard events until we // we warped the mouse. discard events until we
// find the matching sent event. see // find the matching sent event. see
// warpCursorNoLockNoFlush() for where the events // warpCursorNoFlush() for where the events are
// are sent. we discard the matching sent event // sent. we discard the matching sent event and
// and can be sure we've skipped the warp event. // can be sure we've skipped the warp event.
CDisplayLock display(this); CDisplayLock display(this);
do { do {
XMaskEvent(display, PointerMotionMask, &xevent); XMaskEvent(display, PointerMotionMask, &xevent);
@ -210,7 +211,7 @@ CXWindowsPrimaryScreen::run()
xevent.xmotion.y_root - m_yCenter < -s_size || xevent.xmotion.y_root - m_yCenter < -s_size ||
xevent.xmotion.y_root - m_yCenter > s_size) { xevent.xmotion.y_root - m_yCenter > s_size) {
CDisplayLock display(this); CDisplayLock display(this);
warpCursorNoLockNoFlush(display, m_xCenter, m_yCenter); warpCursorNoFlush(display, m_xCenter, m_yCenter);
} }
// send event if mouse moved. do this after warping // send event if mouse moved. do this after warping
@ -239,69 +240,67 @@ CXWindowsPrimaryScreen::stop()
void void
CXWindowsPrimaryScreen::open() CXWindowsPrimaryScreen::open()
{ {
// open the display assert(m_window == None);
openDisplay();
// check for peculiarities CClientInfo info;
// FIXME -- may have to get these from some database try {
m_numLockHalfDuplex = false; // open the display
m_capsLockHalfDuplex = false; openDisplay();
// m_numLockHalfDuplex = true;
// m_capsLockHalfDuplex = true;
// get screen shape // create and prepare our window
SInt32 x, y, w, h; createWindow();
getScreenShape(x, y, w, h);
{ // get the display
CDisplayLock display(this); CDisplayLock display(this);
// get notified of screen saver activation/deactivation // initialize the clipboards
initClipboards(m_window);
// miscellaneous initialization
m_atomScreenSaver = XInternAtom(display, "SCREENSAVER", False); m_atomScreenSaver = XInternAtom(display, "SCREENSAVER", False);
getScreenSaver()->setNotify(m_window);
// check for peculiarities
// FIXME -- may have to get these from some database
m_numLockHalfDuplex = false;
m_capsLockHalfDuplex = false;
// m_numLockHalfDuplex = true;
// m_capsLockHalfDuplex = true;
// collect screen info
getScreenShape(info.m_x, info.m_y, info.m_w, info.m_h);
getCursorPos(info.m_mx, info.m_my);
info.m_zoneSize = getJumpZoneSize();
// save mouse position
m_x = info.m_mx;
m_y = info.m_my;
// compute center pixel of primary screen
getCursorCenter(m_xCenter, m_yCenter);
// update key state // update key state
updateModifierMap(display); updateModifierMap(display);
// get mouse position // get notified of screen saver activation/deactivation
Window root, window; installScreenSaver();
int mx, my, xWindow, yWindow; }
unsigned int mask; catch (...) {
if (!XQueryPointer(display, m_window, &root, &window, close();
&mx, &my, &xWindow, &yWindow, &mask)) { throw;
mx = w >> 1;
my = h >> 1;
}
// save mouse position
m_x = mx;
m_y = my;
} }
// save position of center of screen // enter the screen
m_xCenter = x + (w >> 1); enterNoWarp();
m_yCenter = y + (h >> 1);
// send screen info // send screen info
CClientInfo info;
info.m_x = x;
info.m_y = y;
info.m_w = w;
info.m_h = h;
info.m_zoneSize = 1;
info.m_mx = m_x;
info.m_my = m_y;
m_receiver->onInfoChanged(info); m_receiver->onInfoChanged(info);
} }
void void
CXWindowsPrimaryScreen::close() CXWindowsPrimaryScreen::close()
{ {
// stop being notified of screen saver activation/deactivation uninstallScreenSaver();
getScreenSaver()->setNotify(None); destroyWindow();
m_atomScreenSaver = None;
// close the display
closeDisplay(); closeDisplay();
} }
@ -312,24 +311,20 @@ CXWindowsPrimaryScreen::enter(SInt32 x, SInt32 y, bool forScreenSaver)
assert(m_active == true); assert(m_active == true);
assert(m_window != None); assert(m_window != None);
CDisplayLock display(this); // enter the screen
enterNoWarp();
// unmap the grab window. this also ungrabs the mouse and keyboard.
XUnmapWindow(display, m_window);
// warp to requested location // warp to requested location
if (!forScreenSaver) { if (!forScreenSaver) {
warpCursorNoLock(display, x, y); warpCursor(x, y);
} }
// redirect input to root window. do not warp the mouse because // redirect input to root window. do not warp the mouse because
// that will deactivate the screen saver. // that will deactivate the screen saver.
else { else {
CDisplayLock display(this);
XSetInputFocus(display, PointerRoot, PointerRoot, CurrentTime); XSetInputFocus(display, PointerRoot, PointerRoot, CurrentTime);
} }
// not active anymore
m_active = false;
} }
bool bool
@ -339,6 +334,116 @@ CXWindowsPrimaryScreen::leave()
assert(m_active == false); assert(m_active == false);
assert(m_window != None); assert(m_window != None);
// show our window
if (!showWindow()) {
return false;
}
// warp mouse to center
warpCursorToCenter();
// FIXME -- this doesn't match the win32 version. that just does
// the warp while we flush the input queue until we find the warp
// and we discard that too. would prefer to at least match our
// own warping when we receive MotionNotify; that just does the
// warp. however, the win32 version sometimes stutters when
// leaving and perhaps this is why. hmm, win32 does ignore the
// events until after the warp (via the mark).
// local client now active
m_active = true;
// make sure our idea of clipboard ownership is correct
checkClipboard();
return true;
}
void
CXWindowsPrimaryScreen::reconfigure(UInt32)
{
// do nothing
}
void
CXWindowsPrimaryScreen::warpCursor(SInt32 x, SInt32 y)
{
CDisplayLock display(this);
// warp mouse
warpCursorNoFlush(display, x, y);
// remove all input events before and including warp
XEvent event;
while (XCheckMaskEvent(display, PointerMotionMask |
ButtonPressMask | ButtonReleaseMask |
KeyPressMask | KeyReleaseMask |
KeymapStateMask,
&event)) {
// do nothing
}
// save position as last position
m_x = x;
m_y = y;
}
void
CXWindowsPrimaryScreen::warpCursorToCenter()
{
warpCursor(m_xCenter, m_yCenter);
}
void
CXWindowsPrimaryScreen::warpCursorNoFlush(
Display* display, SInt32 x, SInt32 y)
{
assert(display != NULL);
assert(m_window != None);
// send an event that we can recognize before the mouse warp
XEvent eventBefore;
eventBefore.type = MotionNotify;
eventBefore.xmotion.display = display;
eventBefore.xmotion.window = m_window;
eventBefore.xmotion.root = getRoot();
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 = False;
eventBefore.xmotion.same_screen = True;
XEvent eventAfter = eventBefore;
XSendEvent(display, m_window, False, 0, &eventBefore);
// warp mouse
XWarpPointer(display, None, getRoot(), 0, 0, 0, 0, x, y);
// send an event that we can recognize after the mouse warp
XSendEvent(display, m_window, False, 0, &eventAfter);
XSync(display, False);
log((CLOG_DEBUG2 "warped to %d,%d", x, y));
}
void
CXWindowsPrimaryScreen::checkClipboard()
{
// do nothing, we're always up to date
}
void
CXWindowsPrimaryScreen::enterNoWarp()
{
m_active = false;
hideWindow();
}
bool
CXWindowsPrimaryScreen::showWindow()
{
CDisplayLock display(this); CDisplayLock display(this);
// raise and show the input window // raise and show the input window
@ -387,82 +492,89 @@ CXWindowsPrimaryScreen::leave()
} while (result != GrabSuccess); } while (result != GrabSuccess);
log((CLOG_DEBUG1 "grabbed pointer and keyboard")); log((CLOG_DEBUG1 "grabbed pointer and keyboard"));
// warp mouse to center
warpCursorNoLock(display, m_xCenter, m_yCenter);
// local client now active
m_active = true;
return true; return true;
} }
void void
CXWindowsPrimaryScreen::reconfigure(UInt32) CXWindowsPrimaryScreen::hideWindow()
{
// do nothing
}
void
CXWindowsPrimaryScreen::warpCursor(SInt32 x, SInt32 y)
{ {
CDisplayLock display(this); CDisplayLock display(this);
warpCursorNoLock(display, x, y);
// unmap the grab window. this also ungrabs the mouse and keyboard.
XUnmapWindow(display, m_window);
}
SInt32
CXWindowsPrimaryScreen::getJumpZoneSize() const
{
return 1;
} }
void void
CXWindowsPrimaryScreen::warpCursorNoLock(Display* display, SInt32 x, SInt32 y) CXWindowsPrimaryScreen::createWindow()
{ {
// warp mouse assert(m_window == None);
warpCursorNoLockNoFlush(display, x, y);
// remove all input events before and including warp // get size of screen
XEvent event; SInt32 x, y, w, h;
while (XCheckMaskEvent(display, PointerMotionMask | getScreenShape(x, y, w, h);
ButtonPressMask | ButtonReleaseMask |
KeyPressMask | KeyReleaseMask | // grab window attributes. this window is used to capture user
KeymapStateMask, // input when the user is focused on another client. don't let
&event)) { // the window manager mess with it.
// do nothing XSetWindowAttributes attr;
attr.event_mask = PointerMotionMask |
ButtonPressMask | ButtonReleaseMask |
KeyPressMask | KeyReleaseMask |
KeymapStateMask | PropertyChangeMask;
attr.do_not_propagate_mask = 0;
attr.override_redirect = True;
attr.cursor = getBlankCursor();
// create the grab window
CDisplayLock display(this);
m_window = XCreateWindow(display, getRoot(),
x, y, w, h, 0, 0,
InputOnly, CopyFromParent,
CWDontPropagate | CWEventMask |
CWOverrideRedirect | CWCursor,
&attr);
if (m_window == None) {
throw XScreenOpenFailure();
} }
log((CLOG_DEBUG "window is 0x%08x", m_window));
// save position as last position // start watching for events on other windows
m_x = x; selectEvents(display, getRoot());
m_y = y;
} }
void void
CXWindowsPrimaryScreen::warpCursorNoLockNoFlush( CXWindowsPrimaryScreen::destroyWindow()
Display* display, SInt32 x, SInt32 y)
{ {
assert(display != NULL); // display can be NULL if the server unexpectedly disconnected
assert(m_window != None); CDisplayLock display(this);
if (display != NULL && m_window != None) {
XDestroyWindow(display, m_window);
}
m_window = None;
}
// send an event that we can recognize before the mouse warp void
XEvent eventBefore; CXWindowsPrimaryScreen::installScreenSaver()
eventBefore.type = MotionNotify; {
eventBefore.xmotion.display = display; assert(getScreenSaver() != NULL);
eventBefore.xmotion.window = m_window;
eventBefore.xmotion.root = getRoot();
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 = False;
eventBefore.xmotion.same_screen = True;
XEvent eventAfter = eventBefore;
XSendEvent(display, m_window, False, 0, &eventBefore);
// warp mouse getScreenSaver()->setNotify(m_window);
XWarpPointer(display, None, getRoot(), 0, 0, 0, 0, x, y); }
// send an event that we can recognize after the mouse warp void
XSendEvent(display, m_window, False, 0, &eventAfter); CXWindowsPrimaryScreen::uninstallScreenSaver()
XSync(display, False); {
// stop being notified of screen saver activation/deactivation
log((CLOG_DEBUG2 "warped to %d,%d", x, y)); if (getScreenSaver() != NULL) {
getScreenSaver()->setNotify(None);
}
m_atomScreenSaver = None;
} }
void void
@ -491,7 +603,6 @@ CXWindowsPrimaryScreen::getToggleMask() const
CDisplayLock display(this); CDisplayLock display(this);
// query the pointer to get the keyboard state // query the pointer to get the keyboard state
// FIXME -- is there a better way to do this?
Window root, window; Window root, window;
int xRoot, yRoot, xWindow, yWindow; int xRoot, yRoot, xWindow, yWindow;
unsigned int state; unsigned int state;
@ -548,56 +659,6 @@ CXWindowsPrimaryScreen::isLockedToScreen() const
return false; return false;
} }
void
CXWindowsPrimaryScreen::onOpenDisplay(Display* display)
{
assert(m_window == None);
// get size of screen
SInt32 x, y, w, h;
getScreenShape(x, y, w, h);
// create the grab window. this window is used to capture user
// input when the user is focussed on another client. don't let
// the window manager mess with it.
XSetWindowAttributes attr;
attr.event_mask = PointerMotionMask |// PointerMotionHintMask |
ButtonPressMask | ButtonReleaseMask |
KeyPressMask | KeyReleaseMask |
KeymapStateMask | PropertyChangeMask;
attr.do_not_propagate_mask = 0;
attr.override_redirect = True;
attr.cursor = createBlankCursor();
m_window = XCreateWindow(display, getRoot(), x, y, w, h, 0, 0,
InputOnly, CopyFromParent,
CWDontPropagate | CWEventMask |
CWOverrideRedirect | CWCursor,
&attr);
log((CLOG_DEBUG "window is 0x%08x", m_window));
// start watching for events on other windows
selectEvents(display, getRoot());
}
CXWindowsClipboard*
CXWindowsPrimaryScreen::createClipboard(ClipboardID id)
{
CDisplayLock display(this);
return new CXWindowsClipboard(display, m_window, id);
}
void
CXWindowsPrimaryScreen::onCloseDisplay(Display* display)
{
assert(m_window != None);
// destroy window
if (display != NULL) {
XDestroyWindow(display, m_window);
}
m_window = None;
}
void void
CXWindowsPrimaryScreen::onUnexpectedClose() CXWindowsPrimaryScreen::onUnexpectedClose()
{ {

View File

@ -30,21 +30,35 @@ public:
protected: protected:
// CXWindowsScreen overrides // CXWindowsScreen overrides
virtual void onOpenDisplay(Display*);
virtual CXWindowsClipboard*
createClipboard(ClipboardID);
virtual void onCloseDisplay(Display*);
virtual void onUnexpectedClose(); virtual void onUnexpectedClose();
virtual void onLostClipboard(ClipboardID); virtual void onLostClipboard(ClipboardID);
private: private:
void selectEvents(Display*, Window) const; void selectEvents(Display*, Window) const;
void doSelectEvents(Display*, Window) const; void doSelectEvents(Display*, Window) const;
void warpCursorNoLock(Display*,
SInt32 xAbsolute, SInt32 yAbsolute); void enterNoWarp();
void warpCursorNoLockNoFlush(Display*, bool showWindow();
void hideWindow();
SInt32 getJumpZoneSize() const;
void warpCursorToCenter();
void warpCursorNoFlush(Display*,
SInt32 xAbsolute, SInt32 yAbsolute); SInt32 xAbsolute, SInt32 yAbsolute);
// check clipboard ownership and, if necessary, tell the receiver
// of a grab.
void checkClipboard();
// create/destroy window
void createWindow();
void destroyWindow();
// start/stop watch for screen saver changes
void installScreenSaver();
void uninstallScreenSaver();
KeyModifierMask mapModifier(unsigned int state) const; KeyModifierMask mapModifier(unsigned int state) const;
KeyID mapKey(XKeyEvent*) const; KeyID mapKey(XKeyEvent*) const;
ButtonID mapButton(unsigned int button) const; ButtonID mapButton(unsigned int button) const;