mirror of
https://github.com/debauchee/barrier.git
synced 2026-05-11 00:58:14 +08:00
checkpoint. making win32 and X primary screen code more similar
in order to share code later.
This commit is contained in:
@@ -82,11 +82,6 @@ CMSWindowsPrimaryScreen::~CMSWindowsPrimaryScreen()
|
||||
assert(m_hookLibrary != NULL);
|
||||
assert(m_window == NULL);
|
||||
|
||||
// uninstall screen saver hook
|
||||
if (m_uninstallScreenSaver != NULL) {
|
||||
m_uninstallScreenSaver();
|
||||
}
|
||||
|
||||
// done with hook library
|
||||
FreeLibrary(m_hookLibrary);
|
||||
}
|
||||
@@ -127,54 +122,74 @@ CMSWindowsPrimaryScreen::stop()
|
||||
void
|
||||
CMSWindowsPrimaryScreen::open()
|
||||
{
|
||||
// open the display
|
||||
openDisplay();
|
||||
assert(m_window == NULL);
|
||||
|
||||
// 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;
|
||||
getScreenShape(info.m_x, info.m_y, info.m_w, info.m_h);
|
||||
info.m_zoneSize = getJumpZoneSize();
|
||||
info.m_mx = m_x;
|
||||
info.m_my = m_y;
|
||||
m_receiver->onInfoChanged(info);
|
||||
try {
|
||||
// initialize hook library
|
||||
m_threadID = GetCurrentThreadId();
|
||||
m_init(m_threadID);
|
||||
|
||||
// compute center pixel of primary screen
|
||||
m_xCenter = GetSystemMetrics(SM_CXSCREEN) >> 1;
|
||||
m_yCenter = GetSystemMetrics(SM_CYSCREEN) >> 1;
|
||||
// open the display
|
||||
openDisplay();
|
||||
|
||||
// get keyboard state
|
||||
updateKeys();
|
||||
// create and prepare our window
|
||||
createWindow();
|
||||
|
||||
// set jump zones
|
||||
m_setZone(info.m_x, info.m_y, info.m_w, info.m_h, info.m_zoneSize);
|
||||
// set jump zones
|
||||
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
|
||||
enterNoWarp();
|
||||
|
||||
// send screen info
|
||||
m_receiver->onInfoChanged(info);
|
||||
}
|
||||
|
||||
void
|
||||
CMSWindowsPrimaryScreen::close()
|
||||
{
|
||||
// close the display
|
||||
uninstallScreenSaver();
|
||||
destroyWindow();
|
||||
closeDisplay();
|
||||
m_cleanup();
|
||||
m_threadID = 0;
|
||||
}
|
||||
|
||||
void
|
||||
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_window != NULL);
|
||||
|
||||
// enter the screen
|
||||
enterNoWarp();
|
||||
@@ -190,12 +205,13 @@ CMSWindowsPrimaryScreen::leave()
|
||||
{
|
||||
log((CLOG_INFO "leaving primary"));
|
||||
assert(m_active == false);
|
||||
assert(m_window != NULL);
|
||||
|
||||
// all messages prior to now are invalid
|
||||
nextMark();
|
||||
|
||||
// save active window, show ours, and grab mouse/keyboard
|
||||
if (!onLeave()) {
|
||||
// show our window
|
||||
if (!showWindow()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -229,6 +245,48 @@ CMSWindowsPrimaryScreen::leave()
|
||||
// local client now active
|
||||
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
|
||||
// grabbed the clipboard on this screen without us knowing.
|
||||
// tell the server that this screen grabbed the clipboard.
|
||||
@@ -253,45 +311,13 @@ CMSWindowsPrimaryScreen::leave()
|
||||
// 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
|
||||
CMSWindowsPrimaryScreen::setClipboard(ClipboardID /*id*/,
|
||||
const IClipboard* src)
|
||||
{
|
||||
// FIXME -- this is identical to CMSWindowsSecondaryScreen's code
|
||||
assert(m_window != NULL);
|
||||
|
||||
CMSWindowsClipboard dst(m_window);
|
||||
@@ -301,10 +327,12 @@ CMSWindowsPrimaryScreen::setClipboard(ClipboardID /*id*/,
|
||||
void
|
||||
CMSWindowsPrimaryScreen::grabClipboard(ClipboardID /*id*/)
|
||||
{
|
||||
// FIXME -- this is identical to CMSWindowsSecondaryScreen's code
|
||||
assert(m_window != NULL);
|
||||
|
||||
CMSWindowsClipboard clipboard(m_window);
|
||||
if (clipboard.open(0)) {
|
||||
// FIXME -- don't we need to empty it?
|
||||
clipboard.close();
|
||||
}
|
||||
}
|
||||
@@ -313,6 +341,7 @@ void
|
||||
CMSWindowsPrimaryScreen::getClipboard(ClipboardID /*id*/,
|
||||
IClipboard* dst) const
|
||||
{
|
||||
// FIXME -- this is identical to CMSWindowsSecondaryScreen's code
|
||||
assert(m_window != NULL);
|
||||
|
||||
CMSWindowsClipboard src(m_window);
|
||||
@@ -378,67 +407,6 @@ CMSWindowsPrimaryScreen::isLockedToScreen() const
|
||||
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
|
||||
CMSWindowsPrimaryScreen::onPreTranslate(MSG* msg)
|
||||
{
|
||||
@@ -667,8 +635,7 @@ CMSWindowsPrimaryScreen::onEvent(HWND hwnd, UINT msg,
|
||||
// do nothing if resolution hasn't changed
|
||||
if (x != xOld || y != yOld || w != wOld || h != hOld) {
|
||||
// recompute center pixel of primary screen
|
||||
m_xCenter = GetSystemMetrics(SM_CXSCREEN) >> 1;
|
||||
m_yCenter = GetSystemMetrics(SM_CYSCREEN) >> 1;
|
||||
getCursorCenter(m_xCenter, m_yCenter);
|
||||
|
||||
// warp mouse to center if active
|
||||
if (m_active) {
|
||||
@@ -720,33 +687,14 @@ CMSWindowsPrimaryScreen::enterNoWarp()
|
||||
m_setRelay(false);
|
||||
|
||||
// restore active window and hide our window
|
||||
onEnter();
|
||||
hideWindow();
|
||||
|
||||
// all messages prior to now are invalid
|
||||
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
|
||||
CMSWindowsPrimaryScreen::onLeave()
|
||||
CMSWindowsPrimaryScreen::showWindow()
|
||||
{
|
||||
// remember the active window before we leave. GetActiveWindow()
|
||||
// will only return the active window for the thread's queue (i.e.
|
||||
@@ -776,6 +724,25 @@ CMSWindowsPrimaryScreen::onLeave()
|
||||
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
|
||||
CMSWindowsPrimaryScreen::getJumpZoneSize() const
|
||||
{
|
||||
@@ -792,6 +759,55 @@ CMSWindowsPrimaryScreen::nextMark()
|
||||
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
|
||||
CMSWindowsPrimaryScreen::openDesktop()
|
||||
{
|
||||
@@ -835,7 +851,7 @@ CMSWindowsPrimaryScreen::closeDesktop()
|
||||
if (m_window != NULL) {
|
||||
// restore active window and hide ours
|
||||
if (m_active) {
|
||||
onEnter();
|
||||
hideWindow();
|
||||
}
|
||||
|
||||
// first remove clipboard snooper
|
||||
@@ -866,7 +882,7 @@ CMSWindowsPrimaryScreen::switchDesktop(HDESK desk)
|
||||
if (m_window != NULL) {
|
||||
// restore active window and hide ours
|
||||
if (m_active) {
|
||||
onEnter();
|
||||
hideWindow();
|
||||
}
|
||||
|
||||
// first remove clipboard snooper
|
||||
@@ -948,7 +964,7 @@ CMSWindowsPrimaryScreen::switchDesktop(HDESK desk)
|
||||
|
||||
// get active window and show ours
|
||||
if (m_active) {
|
||||
onLeave();
|
||||
showWindow();
|
||||
}
|
||||
else {
|
||||
// watch jump zones
|
||||
|
||||
@@ -42,8 +42,8 @@ protected:
|
||||
|
||||
private:
|
||||
void enterNoWarp();
|
||||
void onEnter();
|
||||
bool onLeave();
|
||||
bool showWindow();
|
||||
void hideWindow();
|
||||
|
||||
SInt32 getJumpZoneSize() const;
|
||||
|
||||
@@ -51,9 +51,23 @@ private:
|
||||
// motion deltas while mouse is on secondary screen).
|
||||
void warpCursorToCenter();
|
||||
|
||||
// check clipboard ownership and, if necessary, tell the receiver
|
||||
// of a grab.
|
||||
void checkClipboard();
|
||||
|
||||
// discard posted messages
|
||||
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)
|
||||
bool openDesktop();
|
||||
void closeDesktop();
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "CXWindowsUtil.h"
|
||||
#include "CClipboard.h"
|
||||
#include "ProtocolTypes.h"
|
||||
#include "XScreen.h"
|
||||
#include "CThread.h"
|
||||
#include "CLog.h"
|
||||
#include "CStopwatch.h"
|
||||
@@ -179,9 +180,9 @@ CXWindowsPrimaryScreen::run()
|
||||
if (xevent.xmotion.send_event) {
|
||||
// we warped the mouse. discard events until we
|
||||
// find the matching sent event. see
|
||||
// warpCursorNoLockNoFlush() for where the events
|
||||
// are sent. we discard the matching sent event
|
||||
// and can be sure we've skipped the warp event.
|
||||
// warpCursorNoFlush() for where the events are
|
||||
// sent. we discard the matching sent event and
|
||||
// can be sure we've skipped the warp event.
|
||||
CDisplayLock display(this);
|
||||
do {
|
||||
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) {
|
||||
CDisplayLock display(this);
|
||||
warpCursorNoLockNoFlush(display, m_xCenter, m_yCenter);
|
||||
warpCursorNoFlush(display, m_xCenter, m_yCenter);
|
||||
}
|
||||
|
||||
// send event if mouse moved. do this after warping
|
||||
@@ -239,69 +240,67 @@ CXWindowsPrimaryScreen::stop()
|
||||
void
|
||||
CXWindowsPrimaryScreen::open()
|
||||
{
|
||||
// open the display
|
||||
openDisplay();
|
||||
assert(m_window == None);
|
||||
|
||||
// check for peculiarities
|
||||
// FIXME -- may have to get these from some database
|
||||
m_numLockHalfDuplex = false;
|
||||
m_capsLockHalfDuplex = false;
|
||||
// m_numLockHalfDuplex = true;
|
||||
// m_capsLockHalfDuplex = true;
|
||||
CClientInfo info;
|
||||
try {
|
||||
// open the display
|
||||
openDisplay();
|
||||
|
||||
// get screen shape
|
||||
SInt32 x, y, w, h;
|
||||
getScreenShape(x, y, w, h);
|
||||
// create and prepare our window
|
||||
createWindow();
|
||||
|
||||
{
|
||||
// get the display
|
||||
CDisplayLock display(this);
|
||||
|
||||
// get notified of screen saver activation/deactivation
|
||||
// initialize the clipboards
|
||||
initClipboards(m_window);
|
||||
|
||||
// miscellaneous initialization
|
||||
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
|
||||
updateModifierMap(display);
|
||||
|
||||
// get mouse position
|
||||
Window root, window;
|
||||
int mx, my, xWindow, yWindow;
|
||||
unsigned int mask;
|
||||
if (!XQueryPointer(display, m_window, &root, &window,
|
||||
&mx, &my, &xWindow, &yWindow, &mask)) {
|
||||
mx = w >> 1;
|
||||
my = h >> 1;
|
||||
}
|
||||
|
||||
// save mouse position
|
||||
m_x = mx;
|
||||
m_y = my;
|
||||
// get notified of screen saver activation/deactivation
|
||||
installScreenSaver();
|
||||
}
|
||||
catch (...) {
|
||||
close();
|
||||
throw;
|
||||
}
|
||||
|
||||
// save position of center of screen
|
||||
m_xCenter = x + (w >> 1);
|
||||
m_yCenter = y + (h >> 1);
|
||||
// enter the screen
|
||||
enterNoWarp();
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::close()
|
||||
{
|
||||
// stop being notified of screen saver activation/deactivation
|
||||
getScreenSaver()->setNotify(None);
|
||||
m_atomScreenSaver = None;
|
||||
|
||||
// close the display
|
||||
uninstallScreenSaver();
|
||||
destroyWindow();
|
||||
closeDisplay();
|
||||
}
|
||||
|
||||
@@ -312,24 +311,20 @@ CXWindowsPrimaryScreen::enter(SInt32 x, SInt32 y, bool forScreenSaver)
|
||||
assert(m_active == true);
|
||||
assert(m_window != None);
|
||||
|
||||
CDisplayLock display(this);
|
||||
|
||||
// unmap the grab window. this also ungrabs the mouse and keyboard.
|
||||
XUnmapWindow(display, m_window);
|
||||
// enter the screen
|
||||
enterNoWarp();
|
||||
|
||||
// warp to requested location
|
||||
if (!forScreenSaver) {
|
||||
warpCursorNoLock(display, x, y);
|
||||
warpCursor(x, y);
|
||||
}
|
||||
|
||||
// redirect input to root window. do not warp the mouse because
|
||||
// that will deactivate the screen saver.
|
||||
else {
|
||||
CDisplayLock display(this);
|
||||
XSetInputFocus(display, PointerRoot, PointerRoot, CurrentTime);
|
||||
}
|
||||
|
||||
// not active anymore
|
||||
m_active = false;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -339,6 +334,116 @@ CXWindowsPrimaryScreen::leave()
|
||||
assert(m_active == false);
|
||||
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);
|
||||
|
||||
// raise and show the input window
|
||||
@@ -387,82 +492,89 @@ CXWindowsPrimaryScreen::leave()
|
||||
} while (result != GrabSuccess);
|
||||
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;
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::reconfigure(UInt32)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::warpCursor(SInt32 x, SInt32 y)
|
||||
CXWindowsPrimaryScreen::hideWindow()
|
||||
{
|
||||
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
|
||||
CXWindowsPrimaryScreen::warpCursorNoLock(Display* display, SInt32 x, SInt32 y)
|
||||
CXWindowsPrimaryScreen::createWindow()
|
||||
{
|
||||
// warp mouse
|
||||
warpCursorNoLockNoFlush(display, x, y);
|
||||
assert(m_window == None);
|
||||
|
||||
// remove all input events before and including warp
|
||||
XEvent event;
|
||||
while (XCheckMaskEvent(display, PointerMotionMask |
|
||||
ButtonPressMask | ButtonReleaseMask |
|
||||
KeyPressMask | KeyReleaseMask |
|
||||
KeymapStateMask,
|
||||
&event)) {
|
||||
// do nothing
|
||||
// get size of screen
|
||||
SInt32 x, y, w, h;
|
||||
getScreenShape(x, y, w, h);
|
||||
|
||||
// grab window attributes. this window is used to capture user
|
||||
// input when the user is focused on another client. don't let
|
||||
// the window manager mess with it.
|
||||
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
|
||||
m_x = x;
|
||||
m_y = y;
|
||||
// start watching for events on other windows
|
||||
selectEvents(display, getRoot());
|
||||
}
|
||||
|
||||
void
|
||||
CXWindowsPrimaryScreen::warpCursorNoLockNoFlush(
|
||||
Display* display, SInt32 x, SInt32 y)
|
||||
CXWindowsPrimaryScreen::destroyWindow()
|
||||
{
|
||||
assert(display != NULL);
|
||||
assert(m_window != None);
|
||||
// display can be NULL if the server unexpectedly disconnected
|
||||
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
|
||||
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);
|
||||
void
|
||||
CXWindowsPrimaryScreen::installScreenSaver()
|
||||
{
|
||||
assert(getScreenSaver() != NULL);
|
||||
|
||||
// warp mouse
|
||||
XWarpPointer(display, None, getRoot(), 0, 0, 0, 0, x, y);
|
||||
getScreenSaver()->setNotify(m_window);
|
||||
}
|
||||
|
||||
// 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::uninstallScreenSaver()
|
||||
{
|
||||
// stop being notified of screen saver activation/deactivation
|
||||
if (getScreenSaver() != NULL) {
|
||||
getScreenSaver()->setNotify(None);
|
||||
}
|
||||
m_atomScreenSaver = None;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -491,7 +603,6 @@ CXWindowsPrimaryScreen::getToggleMask() const
|
||||
CDisplayLock display(this);
|
||||
|
||||
// query the pointer to get the keyboard state
|
||||
// FIXME -- is there a better way to do this?
|
||||
Window root, window;
|
||||
int xRoot, yRoot, xWindow, yWindow;
|
||||
unsigned int state;
|
||||
@@ -548,56 +659,6 @@ CXWindowsPrimaryScreen::isLockedToScreen() const
|
||||
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
|
||||
CXWindowsPrimaryScreen::onUnexpectedClose()
|
||||
{
|
||||
|
||||
@@ -30,21 +30,35 @@ public:
|
||||
|
||||
protected:
|
||||
// CXWindowsScreen overrides
|
||||
virtual void onOpenDisplay(Display*);
|
||||
virtual CXWindowsClipboard*
|
||||
createClipboard(ClipboardID);
|
||||
virtual void onCloseDisplay(Display*);
|
||||
virtual void onUnexpectedClose();
|
||||
virtual void onLostClipboard(ClipboardID);
|
||||
|
||||
private:
|
||||
void selectEvents(Display*, Window) const;
|
||||
void doSelectEvents(Display*, Window) const;
|
||||
void warpCursorNoLock(Display*,
|
||||
SInt32 xAbsolute, SInt32 yAbsolute);
|
||||
void warpCursorNoLockNoFlush(Display*,
|
||||
|
||||
void enterNoWarp();
|
||||
bool showWindow();
|
||||
void hideWindow();
|
||||
|
||||
SInt32 getJumpZoneSize() const;
|
||||
|
||||
void warpCursorToCenter();
|
||||
void warpCursorNoFlush(Display*,
|
||||
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;
|
||||
KeyID mapKey(XKeyEvent*) const;
|
||||
ButtonID mapButton(unsigned int button) const;
|
||||
|
||||
Reference in New Issue
Block a user