Initial commit of the synergy trunk sources from sf.net

This commit is contained in:
Sorin Sbarnea
2009-02-27 11:54:59 +00:00
commit 958fa80d1d
429 changed files with 96848 additions and 0 deletions

View File

@@ -0,0 +1,209 @@
/*
* 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;
}

View File

@@ -0,0 +1,104 @@
/*
* 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 <windows.h>
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<IMSWindowsClipboardConverter*> 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

View File

@@ -0,0 +1,145 @@
/*
* 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;
}

View File

@@ -0,0 +1,56 @@
/*
* 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

View File

@@ -0,0 +1,146 @@
/*
* 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<const BITMAPINFO*>(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;
}

View File

@@ -0,0 +1,35 @@
/*
* 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

View File

@@ -0,0 +1,107 @@
/*
* 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"
"<!DOCTYPE><HTML><BODY><!--StartFragment-->");
CString suffix("<!--EndFragment--></BODY></HTML>\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);
}

View File

@@ -0,0 +1,44 @@
/*
* 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

View File

@@ -0,0 +1,55 @@
/*
* 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;
}

View File

@@ -0,0 +1,36 @@
/*
* 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

View File

@@ -0,0 +1,55 @@
/*
* 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;
}

View File

@@ -0,0 +1,36 @@
/*
* 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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,296 @@
/*
* 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 <windows.h>
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<CString, CDesk*> 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<bool> 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

View File

@@ -0,0 +1,138 @@
/*
* 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<UInt32>(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<WPARAM>(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;
}

View File

@@ -0,0 +1,44 @@
/*
* 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 <windows.h>
//! 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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,216 @@
/*
* 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 <windows.h>
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<HKL> 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<HKL, SInt32> GroupMap;
typedef std::map<KeyID, UINT> 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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,308 @@
/*
* 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 <windows.h>
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<UInt32, CHotKeyItem> HotKeyMap;
typedef std::vector<UInt32> HotKeyIDList;
typedef std::map<CHotKeyItem, UInt32> 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

View File

@@ -0,0 +1,498 @@
/*
* 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 <malloc.h>
#include <tchar.h>
#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<LPARAM>(&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<LPARAM>(&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<CFindScreenSaverInfo*>(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<bool*>(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<CMSWindowsScreenSaver>(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<CMSWindowsScreenSaver>(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;
}

View File

@@ -0,0 +1,92 @@
/*
* 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 <windows.h>
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

View File

@@ -0,0 +1,75 @@
/*
* 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 <stdio.h>
//
// CMSWindowsUtil
//
CString
CMSWindowsUtil::getString(HINSTANCE instance, DWORD id)
{
char buffer[1024];
int size = static_cast<int>(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;
}
}

View File

@@ -0,0 +1,38 @@
/*
* 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 <windows.h>
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

View File

@@ -0,0 +1,220 @@
/*
* 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';
}

View File

@@ -0,0 +1,94 @@
/*
* 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 <vector>
#include <Carbon/Carbon.h>
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<IOSXClipboardConverter*> 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

View File

@@ -0,0 +1,85 @@
/*
* 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 <algorithm>
//
// 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;
}

View File

@@ -0,0 +1,52 @@
/*
* 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

View File

@@ -0,0 +1,88 @@
/*
* 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);
}

View File

@@ -0,0 +1,41 @@
/*
* 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

View File

@@ -0,0 +1,50 @@
/*
* 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);
}

View File

@@ -0,0 +1,36 @@
/*
* 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

View File

@@ -0,0 +1,124 @@
/*
* 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;
}

View File

@@ -0,0 +1,40 @@
/*
* 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 <Carbon/Carbon.h>
//! 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

File diff suppressed because it is too large Load Diff

235
lib/platform/COSXKeyState.h Normal file
View File

@@ -0,0 +1,235 @@
/*
* 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 <Carbon/Carbon.h>
//! OS X key state
/*!
A key state for OS X.
*/
class COSXKeyState : public CKeyState {
public:
typedef std::vector<KeyID> 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<KeyboardLayoutRef> 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<KeyID> 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<KeyboardLayoutRef, SInt32> GroupMap;
typedef std::map<UInt32, KeyID> CVirtualKeyMap;
CVirtualKeyMap m_virtualKeyMap;
mutable UInt32 m_deadKeyState;
GroupList m_groups;
GroupMap m_groupMap;
};
#endif

1699
lib/platform/COSXScreen.cpp Normal file

File diff suppressed because it is too large Load Diff

252
lib/platform/COSXScreen.h Normal file
View File

@@ -0,0 +1,252 @@
/*
* 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 <Carbon/Carbon.h>
#include <mach/mach_port.h>
#include <mach/mach_interface.h>
#include <mach/mach_init.h>
#include <IOKit/pwr_mgt/IOPMLib.h>
#include <IOKit/IOMessage.h>
template <class T>
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<UInt32, CHotKeyItem> HotKeyMap;
typedef std::vector<UInt32> HotKeyIDList;
typedef std::map<KeyModifierMask, UInt32> ModifierHotKeyMap;
typedef std::map<CHotKeyItem, UInt32> 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<bool>* 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

View File

@@ -0,0 +1,175 @@
/*
* 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 <string.h>
//
// 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));
}

View File

@@ -0,0 +1,54 @@
/*
* 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 <Carbon/Carbon.h>
//! 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

View File

@@ -0,0 +1,39 @@
/*
* 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

View File

@@ -0,0 +1,81 @@
/*
* 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 <Foundation/NSAutoreleasePool.h>
//
// 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];
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,81 @@
/*
* 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 <windows.h>
#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; <unused>
#define SYNERGY_MSG_KEY WM_APP + 0x0012 // vk code; key data
#define SYNERGY_MSG_MOUSE_BUTTON WM_APP + 0x0013 // button msg; <unused>
#define SYNERGY_MSG_MOUSE_WHEEL WM_APP + 0x0014 // delta; <unused>
#define SYNERGY_MSG_MOUSE_MOVE WM_APP + 0x0015 // x; y
#define SYNERGY_MSG_POST_WARP WM_APP + 0x0016 // <unused>; <unused>
#define SYNERGY_MSG_PRE_WARP WM_APP + 0x0017 // x; y
#define SYNERGY_MSG_SCREEN_SAVER WM_APP + 0x0018 // activated; <unused>
#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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,376 @@
/*
* 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 <X11/Xlib.h>
#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<CReply*> CReplyList;
typedef std::map<Window, CReplyList> CReplyMap;
typedef std::map<Window, long> 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<IXWindowsClipboardConverter*> 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

View File

@@ -0,0 +1,187 @@
/*
* 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<UInt8>(src & 0xffu);
dst[1] = static_cast<UInt8>((src >> 8) & 0xffu);
dst += 2;
}
static
void
toLE(UInt8*& dst, SInt32 src)
{
dst[0] = static_cast<UInt8>(src & 0xffu);
dst[1] = static_cast<UInt8>((src >> 8) & 0xffu);
dst[2] = static_cast<UInt8>((src >> 16) & 0xffu);
dst[3] = static_cast<UInt8>((src >> 24) & 0xffu);
dst += 4;
}
static
void
toLE(UInt8*& dst, UInt32 src)
{
dst[0] = static_cast<UInt8>(src & 0xffu);
dst[1] = static_cast<UInt8>((src >> 8) & 0xffu);
dst[2] = static_cast<UInt8>((src >> 16) & 0xffu);
dst[3] = static_cast<UInt8>((src >> 24) & 0xffu);
dst += 4;
}
static inline
UInt16
fromLEU16(const UInt8* data)
{
return static_cast<UInt16>(data[0]) |
(static_cast<UInt16>(data[1]) << 8);
}
static inline
SInt32
fromLES32(const UInt8* data)
{
return static_cast<SInt32>(static_cast<UInt32>(data[0]) |
(static_cast<UInt32>(data[1]) << 8) |
(static_cast<UInt32>(data[2]) << 16) |
(static_cast<UInt32>(data[3]) << 24));
}
static inline
UInt32
fromLEU32(const UInt8* data)
{
return static_cast<UInt32>(data[0]) |
(static_cast<UInt32>(data[1]) << 8) |
(static_cast<UInt32>(data[2]) << 16) |
(static_cast<UInt32>(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<const UInt8*>(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<UInt32>(40));
toLE(dst, static_cast<SInt32>(w));
toLE(dst, static_cast<SInt32>(h));
toLE(dst, static_cast<UInt16>(1));
toLE(dst, static_cast<UInt16>(depth));
toLE(dst, static_cast<UInt32>(0)); // BI_RGB
toLE(dst, static_cast<UInt32>(image.size()));
toLE(dst, static_cast<SInt32>(2834)); // 72 dpi
toLE(dst, static_cast<SInt32>(2834)); // 72 dpi
toLE(dst, static_cast<UInt32>(0));
toLE(dst, static_cast<UInt32>(0));
// construct image
return CString(reinterpret_cast<const char*>(infoHeader),
sizeof(infoHeader)) + rawBMP;
}

View File

@@ -0,0 +1,59 @@
/*
* 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

View File

@@ -0,0 +1,139 @@
/*
* 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<UInt32>(data[0]) |
(static_cast<UInt32>(data[1]) << 8) |
(static_cast<UInt32>(data[2]) << 16) |
(static_cast<UInt32>(data[3]) << 24);
}
static
void
toLE(UInt8*& dst, char src)
{
dst[0] = static_cast<UInt8>(src);
dst += 1;
}
static
void
toLE(UInt8*& dst, UInt16 src)
{
dst[0] = static_cast<UInt8>(src & 0xffu);
dst[1] = static_cast<UInt8>((src >> 8) & 0xffu);
dst += 2;
}
static
void
toLE(UInt8*& dst, UInt32 src)
{
dst[0] = static_cast<UInt8>(src & 0xffu);
dst[1] = static_cast<UInt8>((src >> 8) & 0xffu);
dst[2] = static_cast<UInt8>((src >> 16) & 0xffu);
dst[3] = static_cast<UInt8>((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<UInt32>(14 + bmp.size()));
toLE(dst, static_cast<UInt16>(0));
toLE(dst, static_cast<UInt16>(0));
toLE(dst, static_cast<UInt32>(14 + 40));
return CString(reinterpret_cast<const char*>(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<const UInt8*>(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);
}
}

View File

@@ -0,0 +1,39 @@
/*
* 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

View File

@@ -0,0 +1,62 @@
/*
* 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);
}

View File

@@ -0,0 +1,41 @@
/*
* 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

View File

@@ -0,0 +1,74 @@
/*
* 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;
}

View File

@@ -0,0 +1,41 @@
/*
* 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

View File

@@ -0,0 +1,62 @@
/*
* 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);
}

View File

@@ -0,0 +1,41 @@
/*
* 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

View File

@@ -0,0 +1,61 @@
/*
* 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;
}

View File

@@ -0,0 +1,41 @@
/*
* 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

View File

@@ -0,0 +1,208 @@
/*
* 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 <poll.h>
#else
# if HAVE_SYS_SELECT_H
# include <sys/select.h>
# endif
# if HAVE_SYS_TIME_H
# include <sys/time.h>
# endif
# if HAVE_SYS_TYPES_H
# include <sys/types.h>
# endif
# if HAVE_UNISTD_H
# include <unistd.h>
# 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<int>(1000.0 * dtimeout);
#else
struct timeval timeout;
struct timeval* timeoutPtr;
if (dtimeout < 0.0) {
timeoutPtr = NULL;
}
else {
timeout.tv_sec = static_cast<int>(dtimeout);
timeout.tv_usec = static_cast<int>(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<UInt32>(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<long>(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();
}

View File

@@ -0,0 +1,57 @@
/*
* 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 <X11/Xlib.h>
#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<XEvent> CEventList;
CMutex m_mutex;
Display* m_display;
Window m_window;
Atom m_userEvent;
XEvent m_event;
CEventList m_postedEvents;
bool m_waiting;
};
#endif

View File

@@ -0,0 +1,826 @@
/*
* 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 <X11/X.h>
# include <X11/Xutil.h>
# define XK_MISCELLANY
# define XK_XKB_KEYS
# include <X11/keysymdef.h>
#if HAVE_XKB_EXTENSION
# include <X11/XKBlib.h>
#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<KeyToKeyCodeMap::const_iterator,
KeyToKeyCodeMap::const_iterator> 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<KeyCode, unsigned int> 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<KeyCode>(i + minKeycode);
item.m_button = static_cast<KeyButton>(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<KeyCode>(i));
if (numGroups > maxNumGroups) {
maxNumGroups = numGroups;
}
}
// prepare map from X modifier to KeyModifierMask
std::vector<int> 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<KeyCode>(i);
item.m_button = static_cast<KeyButton>(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<CXWindowsKeyState*>(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<KeyCode>(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;
}

View File

@@ -0,0 +1,155 @@
/*
* 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 <X11/Xlib.h>
# if HAVE_X11_EXTENSIONS_XTEST_H
# include <X11/extensions/XTest.h>
# else
# error The XTest extension is required to build synergy
# endif
# if HAVE_XKB_EXTENSION
# include <X11/extensions/XKBstr.h>
# endif
#endif
//! X Windows key state
/*!
A key state for X Windows.
*/
class CXWindowsKeyState : public CKeyState {
public:
typedef std::vector<int> 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<KeyModifierMask> KeyModifierMaskList;
typedef std::map<KeyModifierMask, unsigned int> KeyModifierToXMask;
typedef std::multimap<KeyID, KeyCode> KeyToKeyCodeMap;
typedef std::map<KeyCode, unsigned int> NonXKBModifierMap;
typedef std::map<UInt32, XKBModifierInfo> 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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,229 @@
/*
* 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 <X11/Xlib.h>
#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<bool> CFilteredKeycodes;
typedef std::vector<std::pair<int, unsigned int> > HotKeyList;
typedef std::map<UInt32, HotKeyList> HotKeyMap;
typedef std::vector<UInt32> HotKeyIDList;
typedef std::map<CHotKeyItem, UInt32> 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<unsigned char> 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

View File

@@ -0,0 +1,598 @@
/*
* 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 <X11/Xatom.h>
#if HAVE_X11_EXTENSIONS_XTEST_H
# include <X11/extensions/XTest.h>
#else
# error The XTest extension is required to build synergy
#endif
#if HAVE_X11_EXTENSIONS_DPMS_H
extern "C" {
# include <X11/Xmd.h>
# include <X11/extensions/dpms.h>
# 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<CXWindowsScreenSaver>(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<long>(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
}

View File

@@ -0,0 +1,164 @@
/*
* 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 <X11/Xlib.h>
#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<Window, long> 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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,185 @@
/*
* 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 <X11/Xlib.h>
#endif
//! X11 utility functions
class CXWindowsUtil {
public:
typedef std::vector<KeySym> 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<KeySym, UInt32> CKeySymMap;
static CKeySymMap s_keySymToUCS4;
};
#endif

123
lib/platform/Makefile.am Normal file
View File

@@ -0,0 +1,123 @@
# 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)

119
lib/platform/Makefile.win Normal file
View File

@@ -0,0 +1,119 @@
# 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)

View File

@@ -0,0 +1,36 @@
// ScreenSaver.framework private API
// Class dumping by Alex Harper http://www.ragingmenace.com/
#import <Foundation/NSObject.h>
@protocol ScreenSaverControl
- (double)screenSaverTimeRemaining;
- (void)restartForUser:fp12;
- (void)screenSaverStopNow;
- (void)screenSaverStartNow;
- (void)setScreenSaverCanRun:(char)fp12;
- (BOOL)screenSaverCanRun;
- (BOOL)screenSaverIsRunning;
@end
@interface ScreenSaverController:NSObject <ScreenSaverControl>
+ 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