merge 1.4 r887:888 into trunk

This commit is contained in:
Nick Bolton 2011-01-23 19:48:38 +00:00
parent 76c47c2346
commit cc520f08d8
10 changed files with 360 additions and 119 deletions

View File

@ -15,7 +15,10 @@
# TODO: split this file up, it's too long! # TODO: split this file up, it's too long!
import sys, os, ConfigParser, subprocess, shutil, re, ftputil import sys, os, ConfigParser, shutil, re, ftputil
if sys.version_info >= (2, 4):
import subprocess
class InternalCommands: class InternalCommands:
@ -42,7 +45,11 @@ class InternalCommands:
config_filename = '%s.cfg' % this_cmd config_filename = '%s.cfg' % this_cmd
qtpro_filename = 'qsynergy.pro' qtpro_filename = 'qsynergy.pro'
doxygen_filename = 'doxygen.cfg' doxygen_filename = 'doxygen.cfg'
macPackageName = 'MacOSX-Universal'
macZipFiles = [
'synergyc', 'synergys',
'../../doc/synergy.conf.example',
'../../doc/MacReadme.txt']
cmake_url = 'http://www.cmake.org/cmake/resources/software.html' cmake_url = 'http://www.cmake.org/cmake/resources/software.html'
@ -59,40 +66,21 @@ class InternalCommands:
enable_make_gui = False enable_make_gui = False
win32_generators = { win32_generators = {
'1' : 'Visual Studio 10', 1 : 'Visual Studio 10',
'2' : 'Visual Studio 10 Win64', 2 : 'Visual Studio 10 Win64',
'3' : 'Visual Studio 9 2008', 3 : 'Visual Studio 9 2008',
'4' : 'Visual Studio 9 2008 Win64', 4 : 'Visual Studio 9 2008 Win64',
'5' : 'Visual Studio 8 2005', 5 : 'Visual Studio 8 2005',
'6' : 'Visual Studio 8 2005 Win64', 6 : 'Visual Studio 8 2005 Win64',
# '10' : 'CodeBlocks - MinGW Makefiles',
# '11' : 'CodeBlocks - Unix Makefiles',
# '12': 'Eclipse CDT4 - MinGW Makefiles',
# '13': 'Eclipse CDT4 - NMake Makefiles',
# '14': 'Eclipse CDT4 - Unix Makefiles',
# '15': 'MinGW Makefiles',
# '16': 'NMake Makefiles',
# '17': 'Unix Makefiles',
# '18': 'Borland Makefiles',
# '19': 'MSYS Makefiles',
# '20': 'Watcom WMake',
} }
unix_generators = { unix_generators = {
'1' : 'Unix Makefiles', 1 : 'Unix Makefiles',
# '2' : 'CodeBlocks - Unix Makefiles',
# '3' : 'Eclipse CDT4 - Unix Makefiles',
# '4' : 'KDevelop3',
# '5' : 'KDevelop3 - Unix Makefiles',
} }
darwin_generators = { darwin_generators = {
'1' : 'Xcode', 1 : 'Unix Makefiles',
'2' : 'Unix Makefiles', 2 : 'Xcode',
# '3' : 'CodeBlocks - Unix Makefiles',
# '4' : 'Eclipse CDT4 - Unix Makefiles',
# '5' : 'KDevelop3',
# '6' : 'KDevelop3 - Unix Makefiles',
} }
def getBinDir(self, target=''): def getBinDir(self, target=''):
@ -264,7 +252,7 @@ class InternalCommands:
# TODO # TODO
pass pass
def build(self, targets=[]): def build(self, targets=[], skipConfig=False):
# if no mode specified, default to debug # if no mode specified, default to debug
if len(targets) == 0: if len(targets) == 0:
@ -277,7 +265,7 @@ class InternalCommands:
if generator.startswith('Visual Studio'): if generator.startswith('Visual Studio'):
# only need to configure once for vs # only need to configure once for vs
if not self.has_conf_run(): if not self.has_conf_run() and not skipConfig:
self.configure_internal() self.configure_internal()
for target in targets: for target in targets:
@ -297,7 +285,7 @@ class InternalCommands:
for target in targets: for target in targets:
if not self.has_conf_run(target): if not self.has_conf_run(target) and not skipConfig:
self.configure_internal(target) self.configure_internal(target)
self.try_chdir(self.getBinDir(target)) self.try_chdir(self.getBinDir(target))
@ -449,6 +437,9 @@ class InternalCommands:
if type != 'win': if type != 'win':
self.configure_internal(unixTarget, '-DCONF_CPACK:BOOL=TRUE') self.configure_internal(unixTarget, '-DCONF_CPACK:BOOL=TRUE')
# make sure we have a release build to package
self.build(['release'], skipConfig=True)
if type == None: if type == None:
self.dist_usage() self.dist_usage()
return return
@ -479,27 +470,7 @@ class InternalCommands:
elif type == 'mac': elif type == 'mac':
if sys.platform == 'darwin': if sys.platform == 'darwin':
# nb: disabling package maker, as it doesn't self.distMac(unixTarget)
# work too well (screws with permissions).
#self.dist_run('cpack -G PackageMaker', unixTarget)
# nb: temporary fix (just distribute a zip)
bin = self.getBinDir(unixTarget)
version = self.getVersionFromCmake()
zipFile = (self.project + '-' +
version + '-' +
self.macPackageName + '.zip')
zipCmd = ('zip ' + zipFile + ' ' +
'synergyc synergys');
print 'Creating package: ' + zipCmd
self.try_chdir(self.getBinDir(unixTarget))
err = os.system(zipCmd)
self.restore_chdir()
if err != 0:
raise Exception(
'Zip failed, code: ' + err)
else: else:
package_unsupported = True package_unsupported = True
@ -512,6 +483,34 @@ class InternalCommands:
% (type, sys.platform)) % (type, sys.platform))
def distMac(self, unixTarget):
# nb: disabling package maker, as it doesn't
# work too well (screws with permissions and causes boot to fail).
#self.dist_run('cpack -G PackageMaker', unixTarget)
version = self.getVersionFromCmake()
zipFile = (self.project + '-' + version + '-' +
self.getMacPackageName() + '.zip')
# nb: temporary fix (just distribute a zip)
bin = self.getBinDir(unixTarget)
self.try_chdir(bin)
try:
for f in self.macZipFiles:
if not os.path.exists(f):
raise Exception('File does not exist: ' + f)
zipCmd = ('zip ' + zipFile + ' ' + ' '.join(self.macZipFiles));
print 'Creating package: ' + zipCmd
err = os.system(zipCmd)
if err != 0:
raise Exception('Zip failed, code: ' + err)
finally:
self.restore_chdir()
def distNsis(self, vcRedistDir, qtDir): def distNsis(self, vcRedistDir, qtDir):
if vcRedistDir == '': if vcRedistDir == '':
@ -746,8 +745,7 @@ class InternalCommands:
def get_generator_from_config(self): def get_generator_from_config(self):
if self.generator_id: if self.generator_id:
generators = self.get_generators() return self.getGenerator()
return generators[self.generator_id]
else: else:
config = ConfigParser.RawConfigParser() config = ConfigParser.RawConfigParser()
config.read(self.config_filepath()) config.read(self.config_filepath())
@ -796,28 +794,20 @@ class InternalCommands:
raise Exception('Unsupported platform: ' + sys.platform) raise Exception('Unsupported platform: ' + sys.platform)
def get_generator_from_prompt(self): def get_generator_from_prompt(self):
return self.getGenerator()
def getGenerator(self):
generators = self.get_generators() generators = self.get_generators()
if len(generators.keys()) == 1:
return generators[generators.keys()[0]]
# if user has specified a generator as an argument # if user has specified a generator as an argument
if self.generator_id: if self.generator_id:
return generators[self.generator_id] return generators[int(self.generator_id)]
# if we can accept user input
elif not self.no_prompts:
generator_options = ''
generators_sorted = sorted(generators.iteritems(), key=lambda t: int(t[0]))
for id, generator in generators_sorted:
generator_options += '\n ' + id + ': ' + generator
print ('\nChoose a CMake generator:%s'
) % generator_options
return self.setup_generator_prompt(generators)
else: else:
raise Exception('No generator specified, and cannot prompt user.') raise Exception(
'Generator not specified, use -g arg ' +
'(use `hm genlist` for a list of generators).')
def setup_generator_prompt(self, generators): def setup_generator_prompt(self, generators):
@ -936,6 +926,27 @@ class InternalCommands:
if err != 0: if err != 0:
raise Exception('Reformat failed with error code: ' + str(err)) raise Exception('Reformat failed with error code: ' + str(err))
def printGeneratorList(self):
generators = self.get_generators()
keys = generators.keys()
keys.sort()
for k in keys:
print str(k) + ': ' + generators[k]
def getMacPackageName(self):
import commands
versions = commands.getoutput('/usr/bin/sw_vers')
result = re.search('ProductVersion:\t(\d+)\.(\d+)', versions)
if not result:
print versions
raise Exception(
'Could not find Mac OS X version in sw_vers output.')
# version is major and minor with no dots (e.g. 106)
return ('MacOSX' + str(result.group(1)) +
str(result.group(2)) + '-Universal');
# the command handler should be called only from hm.py (i.e. directly # the command handler should be called only from hm.py (i.e. directly
# from the command prompt). the purpose of this class is so that we # from the command prompt). the purpose of this class is so that we
# don't need to do argument handling all over the place in the internal # don't need to do argument handling all over the place in the internal
@ -1051,3 +1062,6 @@ class CommandHandler:
def open(self): def open(self):
self.ic.open() self.ic.open()
def genlist(self):
self.ic.printGeneratorList()

18
doc/MacReadme.txt Executable file
View File

@ -0,0 +1,18 @@
Mac OS X Readme
===============
To install on Mac OS X with the .zip distribution (first seen in 1.3.6) you must follow these steps:
1. Extract the zip file to any location (usually double click will do this)
2. Open Terminal, and cd to the extracted directory (e.g. /Users/my-name/Downloads/extracted-dir/)
3. Change to super user (use the su command)
4. Copy the binaries to /usr/bin using: cp synergy* /usr/bin
How to enable the root user in Mac OS X:
http://support.apple.com/kb/ht1528
Once the binaries have been copied to /usr/bin, you should follow the configuration guide:
http://synergy2.sourceforge.net/configuration.html
If you have any problems, see the [[Support]] page:
http://synergy-foss.org/support

17
hm.py
View File

@ -30,9 +30,13 @@
# This will create an in-source UNIX Makefile. # This will create an in-source UNIX Makefile.
import sys, os import sys, os
from build import commands from build import toolchain
from getopt import gnu_getopt from getopt import gnu_getopt
# minimum required version
requiredMajor = 2
requiredMinor = 3
# options used by all commands # options used by all commands
global_options = 'g:v' global_options = 'g:v'
global_options_long = ['no-prompts', 'generator=', 'verbose', 'make-gui'] global_options_long = ['no-prompts', 'generator=', 'verbose', 'make-gui']
@ -59,6 +63,7 @@ cmd_opt_dict = {
'revision' : ['', []], 'revision' : ['', []],
'reformat' : ['', []], 'reformat' : ['', []],
'open' : ['', []], 'open' : ['', []],
'genlist' : ['', []]
} }
# aliases to valid commands # aliases to valid commands
@ -171,7 +176,7 @@ def run_cmd(cmd, argv = []):
# pass args and optarg data to command handler, which figures out # pass args and optarg data to command handler, which figures out
# how to handle the arguments # how to handle the arguments
handler = commands.CommandHandler(argv, opts, args, verbose) handler = toolchain.CommandHandler(argv, opts, args, verbose)
# use reflection to get the function pointer # use reflection to get the function pointer
cmd_func = getattr(handler, cmd) cmd_func = getattr(handler, cmd)
@ -181,15 +186,17 @@ def run_cmd(cmd, argv = []):
if not verbose: if not verbose:
# print friendly error for users # print friendly error for users
sys.stderr.write('Error: ' + sys.exc_info()[1].__str__() + '\n') sys.stderr.write('Error: ' + sys.exc_info()[1].__str__() + '\n')
exit(1) sys.exit(1)
else: else:
# if user wants to be verbose let python do it's thing # if user wants to be verbose let python do it's thing
raise raise
def main(argv): def main(argv):
if sys.version_info < (2, 4): if sys.version_info < (requiredMajor, requiredMinor):
print 'Python version must be at least: 2.4' print ('Python version must be at least ' +
str(requiredMajor) + '.' + str(requiredMinor) + ', but is ' +
str(sys.version_info[0]) + '.' + str(sys.version_info[1]))
sys.exit(1) sys.exit(1)
try: try:

View File

@ -232,7 +232,12 @@ COSXKeyState::mapKeyFromEvent(CKeyIDs& ids,
// get keyboard info // get keyboard info
#if defined(MAC_OS_X_VERSION_10_5)
TISInputSourceRef currentKeyboardLayout = TISCopyCurrentKeyboardLayoutInputSource(); TISInputSourceRef currentKeyboardLayout = TISCopyCurrentKeyboardLayoutInputSource();
#else
KeyboardLayoutRef currentKeyboardLayout;
OSStatus status = KLGetCurrentKeyboardLayout(&currentKeyboardLayout);
#endif
if (currentKeyboardLayout == NULL) { if (currentKeyboardLayout == NULL) {
return kKeyNone; return kKeyNone;
} }
@ -265,22 +270,49 @@ COSXKeyState::mapKeyFromEvent(CKeyIDs& ids,
return 0; return 0;
} }
const bool layoutValid = false;
const UCKeyboardLayout* layout;
// translate via uchr resource // translate via uchr resource
#if defined(MAC_OS_X_VERSION_10_5)
CFDataRef ref = (CFDataRef) TISGetInputSourceProperty(currentKeyboardLayout, CFDataRef ref = (CFDataRef) TISGetInputSourceProperty(currentKeyboardLayout,
kTISPropertyUnicodeKeyLayoutData); kTISPropertyUnicodeKeyLayoutData);
const UCKeyboardLayout* layout = (const UCKeyboardLayout*) CFDataGetBytePtr(ref); layout = (const UCKeyboardLayout*) CFDataGetBytePtr(ref);
if (layout != NULL) { layoutValid = (layout != null);
#else
const void* resource;
int err = KLGetKeyboardLayoutProperty(currentKeyboardLayout, kKLuchrData, &resource);
layoutValid == (err == noErr);
layout = (const UCKeyboardLayout*)resource;
#endif
if (layoutValid) {
// choose action
UInt16 action;
switch (eventKind) {
case kEventRawKeyDown:
action = kUCKeyActionDown;
break;
case kEventRawKeyRepeat:
action = kUCKeyActionAutoKey;
break;
default:
return 0;
}
// translate key // translate key
UniCharCount count; UniCharCount count;
UniChar chars[2]; UniChar chars[2];
//LOG((CLOG_DEBUG "modifiers: %08x", modifiers & 0xffu)); LOG((CLOG_DEBUG2 "modifiers: %08x", modifiers & 0xffu));
OSStatus status = UCKeyTranslate(layout, OSStatus status = UCKeyTranslate(layout,
vkCode & 0xffu, action, vkCode & 0xffu, action,
(modifiers >> 8) & 0xffu, (modifiers >> 8) & 0xffu,
LMGetKbdType(), 0, &m_deadKeyState, LMGetKbdType(), 0, &m_deadKeyState,
sizeof(chars) / sizeof(chars[0]), &count, chars); sizeof(chars) / sizeof(chars[0]), &count, chars);
// get the characters // get the characters
if (status == 0) { if (status == 0) {
if (count != 0 || m_deadKeyState == 0) { if (count != 0 || m_deadKeyState == 0) {
@ -314,11 +346,21 @@ COSXKeyState::pollActiveModifiers() const
SInt32 SInt32
COSXKeyState::pollActiveGroup() const COSXKeyState::pollActiveGroup() const
{ {
TISInputSourceRef inputSource = TISCopyCurrentKeyboardLayoutInputSource(); bool layoutValid = true;
GroupMap::const_iterator i = m_groupMap.find(inputSource); #if defined(MAC_OS_X_VERSION_10_5)
if (i != m_groupMap.end()) { TISInputSourceRef keyboardLayout = TISCopyCurrentKeyboardLayoutInputSource();
return i->second; #else
} KeyboardLayoutRef keyboardLayout;
OSStatus status = KLGetCurrentKeyboardLayout(&keyboardLayout);
layoutValid = (status == noErr);
#endif
if (layoutValid) {
GroupMap::const_iterator i = m_groupMap.find(keyboardLayout);
if (i != m_groupMap.end()) {
return i->second;
}
}
return 0; return 0;
} }
@ -354,10 +396,23 @@ COSXKeyState::getKeyMap(CKeyMap& keyMap)
// add special keys // add special keys
getKeyMapForSpecialKeys(keyMap, g); getKeyMapForSpecialKeys(keyMap, g);
CFDataRef resource_ref; const void* resource;
if ((resource_ref = (CFDataRef)TISGetInputSourceProperty(m_groups[g], bool layoutValid = false;
kTISPropertyUnicodeKeyLayoutData)) != NULL) {
const void* resource = CFDataGetBytePtr(resource_ref); // add regular keys
// try uchr resource first
#if defined(MAC_OS_X_VERSION_10_5)
CFDataRef resourceRef = (CFDataRef)TISGetInputSourceProperty(
m_groups[g], kTISPropertyUnicodeKeyLayoutData);
layoutValid = resourceRef != NULL;
if (layoutValid)
resource = CFDataGetBytePtr(resourceRef);
#else
layoutValid = KLGetKeyboardLayoutProperty(
m_groups[g], kKLuchrData, &resource);
#endif
if (layoutValid) {
CUCHRKeyResource uchr(resource, keyboardType); CUCHRKeyResource uchr(resource, keyboardType);
if (uchr.isValid()) { if (uchr.isValid()) {
LOG((CLOG_DEBUG1 "using uchr resource for group %d", g)); LOG((CLOG_DEBUG1 "using uchr resource for group %d", g));
@ -366,6 +421,21 @@ COSXKeyState::getKeyMap(CKeyMap& keyMap)
} }
} }
// NB: not sure why support for KCHR was
// remvoed in 10.5 version?
#if defined(MAC_OS_X_VERSION_10_5)
// try KCHR resource
if (KLGetKeyboardLayoutProperty(m_groups[g],
kKLKCHRData, &resource) == noErr) {
CKCHRKeyResource kchr(resource);
if (kchr.isValid()) {
LOG((CLOG_DEBUG1 "using KCHR resource for group %d", g));
getKeyMap(keyMap, g, kchr);
continue;
}
}
#endif
LOG((CLOG_DEBUG1 "no keyboard resource for group %d", g)); LOG((CLOG_DEBUG1 "no keyboard resource for group %d", g));
} }
} }
@ -663,23 +733,41 @@ COSXKeyState::handleModifierKey(void* target,
bool bool
COSXKeyState::getGroups(GroupList& groups) const COSXKeyState::getGroups(GroupList& groups) const
{ {
CFIndex n;
bool gotLayouts = false;
#if defined(MAC_OS_X_VERSION_10_5)
// get number of layouts // get number of layouts
CFStringRef keys[] = { kTISPropertyInputSourceCategory }; CFStringRef keys[] = { kTISPropertyInputSourceCategory };
CFStringRef values[] = { kTISCategoryKeyboardInputSource }; CFStringRef values[] = { kTISCategoryKeyboardInputSource };
CFDictionaryRef dict = CFDictionaryCreate(NULL, (const void **)keys, (const void **)values, 1, NULL, NULL); CFDictionaryRef dict = CFDictionaryCreate(NULL, (const void **)keys, (const void **)values, 1, NULL, NULL);
CFArrayRef kbds = TISCreateInputSourceList(dict, false); CFArrayRef kbds = TISCreateInputSourceList(dict, false);
CFIndex n = CFArrayGetCount(kbds); n = CFArrayGetCount(kbds);
if (n == 0) { gotLayouts = (n != 0);
#else
OSStatus status = KLGetKeyboardLayoutCount(&n);
gotLayouts = (status == noErr);
#endif
if (!gotLayouts) {
LOG((CLOG_DEBUG1 "can't get keyboard layouts")); LOG((CLOG_DEBUG1 "can't get keyboard layouts"));
return false; return false;
} }
// get each layout // get each layout
groups.clear(); groups.clear();
TISInputSourceRef inputKeyboardLayout;
for (CFIndex i = 0; i < n; ++i) { for (CFIndex i = 0; i < n; ++i) {
inputKeyboardLayout = (TISInputSourceRef) CFArrayGetValueAtIndex(kbds, i); bool addToGroups = true;
groups.push_back(inputKeyboardLayout); #if defined(MAC_OS_X_VERSION_10_5)
TISInputSourceRef keyboardLayout =
(TISInputSourceRef)CFArrayGetValueAtIndex(kbds, i);
#else
KeyboardLayoutRef keyboardLayout;
status = KLGetKeyboardLayoutAtIndex(i, &keyboardLayout);
addToGroups == (status == noErr);
#endif
if (addToGroups)
groups.push_back(keyboardLayout);
} }
return true; return true;
} }
@ -687,7 +775,11 @@ COSXKeyState::getGroups(GroupList& groups) const
void void
COSXKeyState::setGroup(SInt32 group) COSXKeyState::setGroup(SInt32 group)
{ {
#if defined(MAC_OS_X_VERSION_10_5)
TISSetInputMethodKeyboardLayoutOverride(m_groups[group]); TISSetInputMethodKeyboardLayoutOverride(m_groups[group]);
#else
KLSetCurrentKeyboardLayout(m_groups[group]);
#endif
} }
void void
@ -832,16 +924,18 @@ COSXKeyState::CKeyResource::getKeyID(UInt8 c)
str[0] = static_cast<char>(c); str[0] = static_cast<char>(c);
str[1] = 0; str[1] = 0;
#if defined(MAC_OS_X_VERSION_10_5)
// get current keyboard script // get current keyboard script
TISInputSourceRef isref = TISCopyCurrentKeyboardInputSource();
TISInputSourceRef isref = TISCopyCurrentKeyboardInputSource(); CFArrayRef langs = (CFArrayRef) TISGetInputSourceProperty(isref, kTISPropertyInputSourceLanguages);
CFArrayRef langs = (CFArrayRef) TISGetInputSourceProperty(isref, kTISPropertyInputSourceLanguages); CFStringEncoding encoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)CFArrayGetValueAtIndex(langs, 0));
#else
CFStringEncoding encoding = GetScriptManagerVariable(smKeyScript);
#endif
// convert to unicode // convert to unicode
CFStringRef cfString = CFStringRef cfString =
CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, CFStringCreateWithCStringNoCopy(
str, CFStringConvertIANACharSetNameToEncoding((CFStringRef) CFArrayGetValueAtIndex(langs, 0)), kCFAllocatorDefault, str, encoding, kCFAllocatorNull);
kCFAllocatorNull);
// sometimes CFStringCreate...() returns NULL (e.g. Apple Korean // sometimes CFStringCreate...() returns NULL (e.g. Apple Korean
// encoding with char value 214). if it did then make no key, // encoding with char value 214). if it did then make no key,

View File

@ -24,6 +24,12 @@
#include "stdset.h" #include "stdset.h"
#include "stdvector.h" #include "stdvector.h"
#if defined(MAC_OS_X_VERSION_10_5)
typedef TISInputSourceRef KeyLayout;
#else
typedef KeyboardLayoutRef KeyLayout;
#endif
//! OS X key state //! OS X key state
/*! /*!
A key state for OS X. A key state for OS X.
@ -99,7 +105,7 @@ protected:
private: private:
class CKeyResource; class CKeyResource;
typedef std::vector<TISInputSourceRef> GroupList; typedef std::vector<KeyLayout> GroupList;
// Add hard coded special keys to a CKeyMap. // Add hard coded special keys to a CKeyMap.
void getKeyMapForSpecialKeys( void getKeyMapForSpecialKeys(
@ -197,7 +203,7 @@ private:
KeyButtonOffset = 1 KeyButtonOffset = 1
}; };
typedef std::map<TISInputSourceRef, SInt32> GroupMap; typedef std::map<KeyLayout, SInt32> GroupMap;
typedef std::map<UInt32, KeyID> CVirtualKeyMap; typedef std::map<UInt32, KeyID> CVirtualKeyMap;
CVirtualKeyMap m_virtualKeyMap; CVirtualKeyMap m_virtualKeyMap;

View File

@ -97,9 +97,17 @@ COSXScreen::COSXScreen(bool isPrimary) :
LOG((CLOG_ERR "Synergy server requires accessibility API enabled. Please check the option for \"Enable access for assistive devices\" in the Universal Access System Preferences panel. Unintentional key-replication will occur until this is fixed.")); LOG((CLOG_ERR "Synergy server requires accessibility API enabled. Please check the option for \"Enable access for assistive devices\" in the Universal Access System Preferences panel. Unintentional key-replication will occur until this is fixed."));
} }
} }
// install display manager notification handler // install display manager notification handler
#if defined(MAC_OS_X_VERSION_10_5)
CGDisplayRegisterReconfigurationCallback(displayReconfigurationCallback, this); CGDisplayRegisterReconfigurationCallback(displayReconfigurationCallback, this);
#else
m_displayManagerNotificationUPP =
NewDMExtendedNotificationUPP(displayManagerCallback);
OSStatus err = GetCurrentProcess(&m_PSN);
err = DMRegisterExtendedNotifyProc(m_displayManagerNotificationUPP,
this, 0, &m_PSN);
#endif
// install fast user switching event handler // install fast user switching event handler
EventTypeSpec switchEventTypes[2]; EventTypeSpec switchEventTypes[2];
@ -132,7 +140,24 @@ COSXScreen::COSXScreen(bool isPrimary) :
if (m_switchEventHandlerRef != 0) { if (m_switchEventHandlerRef != 0) {
RemoveEventHandler(m_switchEventHandlerRef); RemoveEventHandler(m_switchEventHandlerRef);
} }
#if defined(MAC_OS_X_VERSION_10_5)
CGDisplayRemoveReconfigurationCallback(displayReconfigurationCallback, this); CGDisplayRemoveReconfigurationCallback(displayReconfigurationCallback, this);
#else
if (m_displayManagerNotificationUPP != NULL) {
DMRemoveExtendedNotifyProc(m_displayManagerNotificationUPP,
NULL, &m_PSN, 0);
}
if (m_hiddenWindow) {
ReleaseWindow(m_hiddenWindow);
m_hiddenWindow = NULL;
}
if (m_userInputWindow) {
ReleaseWindow(m_userInputWindow);
m_userInputWindow = NULL;
}
#endif
delete m_keyState; delete m_keyState;
delete m_screensaver; delete m_screensaver;
@ -178,7 +203,22 @@ COSXScreen::~COSXScreen()
RemoveEventHandler(m_switchEventHandlerRef); RemoveEventHandler(m_switchEventHandlerRef);
#if defined(MAC_OS_X_VERSION_10_5)
CGDisplayRemoveReconfigurationCallback(displayReconfigurationCallback, this); CGDisplayRemoveReconfigurationCallback(displayReconfigurationCallback, this);
#else
DMRemoveExtendedNotifyProc(m_displayManagerNotificationUPP,
NULL, &m_PSN, 0);
if (m_hiddenWindow) {
ReleaseWindow(m_hiddenWindow);
m_hiddenWindow = NULL;
}
if (m_userInputWindow) {
ReleaseWindow(m_userInputWindow);
m_userInputWindow = NULL;
}
#endif
delete m_keyState; delete m_keyState;
delete m_screensaver; delete m_screensaver;
@ -526,17 +566,22 @@ void
COSXScreen::fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const COSXScreen::fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const
{ {
if (xDelta != 0 || yDelta != 0) { if (xDelta != 0 || yDelta != 0) {
#if defined(MAC_OS_X_VERSION_10_5)
// create a scroll event, post it and release it. not sure if kCGScrollEventUnitLine // create a scroll event, post it and release it. not sure if kCGScrollEventUnitLine
// is the right choice here over kCGScrollEventUnitPixel // is the right choice here over kCGScrollEventUnitPixel
CGEventRef scrollEvent = CGEventCreateScrollWheelEvent(NULL, CGEventRef scrollEvent = CGEventCreateScrollWheelEvent(
kCGScrollEventUnitLine, NULL, kCGScrollEventUnitLine, 2,
2, mapScrollWheelFromSynergy(yDelta),
mapScrollWheelFromSynergy(yDelta), -mapScrollWheelFromSynergy(xDelta));
-mapScrollWheelFromSynergy(xDelta));
CGEventPost(kCGHIDEventTap, scrollEvent); CGEventPost(kCGHIDEventTap, scrollEvent);
CFRelease(scrollEvent); CFRelease(scrollEvent);
#else
CGPostScrollWheelEvent(
2, mapScrollWheelFromSynergy(yDelta),
-mapScrollWheelFromSynergy(xDelta));
#endif
} }
} }
@ -988,6 +1033,42 @@ COSXScreen::handleClipboardCheck(const CEvent&, void*)
checkClipboards(); checkClipboards();
} }
#if !defined(MAC_OS_X_VERSION_10_5)
pascal void
COSXScreen::displayManagerCallback(void* inUserData, SInt16 inMessage, void*)
{
COSXScreen* screen = (COSXScreen*)inUserData;
if (inMessage == kDMNotifyEvent) {
screen->onDisplayChange();
}
}
bool
COSXScreen::onDisplayChange()
{
// screen resolution may have changed. save old shape.
SInt32 xOld = m_x, yOld = m_y, wOld = m_w, hOld = m_h;
// update shape
updateScreenShape();
// do nothing if resolution hasn't changed
if (xOld != m_x || yOld != m_y || wOld != m_w || hOld != m_h) {
if (m_isPrimary) {
// warp mouse to center if off screen
if (!m_isOnScreen) {
warpCursor(m_xCenter, m_yCenter);
}
}
// send new screen info
sendEvent(getShapeChangedEvent());
}
return true;
}
#else
void void
COSXScreen::displayReconfigurationCallback(CGDirectDisplayID displayID, CGDisplayChangeSummaryFlags flags, void* inUserData) COSXScreen::displayReconfigurationCallback(CGDirectDisplayID displayID, CGDisplayChangeSummaryFlags flags, void* inUserData)
{ {
@ -1007,6 +1088,7 @@ COSXScreen::displayReconfigurationCallback(CGDirectDisplayID displayID, CGDispla
screen->updateScreenShape(displayID, flags); screen->updateScreenShape(displayID, flags);
} }
} }
#endif
bool bool
COSXScreen::onKey(CGEventRef event) COSXScreen::onKey(CGEventRef event)
@ -1275,7 +1357,12 @@ COSXScreen::getKeyState() const
void void
COSXScreen::updateScreenShape(const CGDirectDisplayID, const CGDisplayChangeSummaryFlags flags) COSXScreen::updateScreenShape(const CGDirectDisplayID, const CGDisplayChangeSummaryFlags flags)
{ {
updateScreenShape();
}
void
COSXScreen::updateScreenShape()
{
// get info for each display // get info for each display
CGDisplayCount displayCount = 0; CGDisplayCount displayCount = 0;

View File

@ -100,6 +100,7 @@ protected:
virtual IKeyState* getKeyState() const; virtual IKeyState* getKeyState() const;
private: private:
void updateScreenShape();
void updateScreenShape(const CGDirectDisplayID, const CGDisplayChangeSummaryFlags); void updateScreenShape(const CGDirectDisplayID, const CGDisplayChangeSummaryFlags);
void postMouseEvent(CGPoint&) const; void postMouseEvent(CGPoint&) const;
@ -114,10 +115,14 @@ private:
// of the button pressed using the mac button mapping. // of the button pressed using the mac button mapping.
bool onMouseButton(bool pressed, UInt16 macButton); bool onMouseButton(bool pressed, UInt16 macButton);
bool onMouseWheel(SInt32 xDelta, SInt32 yDelta) const; bool onMouseWheel(SInt32 xDelta, SInt32 yDelta) const;
#if !defined(MAC_OS_X_VERSION_10_5)
bool onDisplayChange();
#endif
void constructMouseButtonEventMap(); void constructMouseButtonEventMap();
bool onKey(CGEventRef event); bool onKey(CGEventRef event);
bool onHotKey(EventRef event) const; bool onHotKey(EventRef event) const;
// Added here to allow the carbon cursor hack to be called. // Added here to allow the carbon cursor hack to be called.
@ -148,10 +153,14 @@ private:
// clipboard check timer handler // clipboard check timer handler
void handleClipboardCheck(const CEvent&, void*); void handleClipboardCheck(const CEvent&, void*);
#if defined(MAC_OS_X_VERSION_10_5)
// Resolution switch callback // Resolution switch callback
static void displayReconfigurationCallback(CGDirectDisplayID, static void displayReconfigurationCallback(CGDirectDisplayID,
CGDisplayChangeSummaryFlags, void*); CGDisplayChangeSummaryFlags, void*);
#else
static pascal void displayManagerCallback(void* inUserData,
SInt16 inMessage, void* inNotifyData);
#endif
// fast user switch callback // fast user switch callback
static pascal OSStatus static pascal OSStatus
userSwitchCallback(EventHandlerCallRef nextHandler, userSwitchCallback(EventHandlerCallRef nextHandler,
@ -279,6 +288,12 @@ private:
// does not have focus. // does not have focus.
WindowRef m_userInputWindow; WindowRef m_userInputWindow;
#if !defined(MAC_OS_X_VERSION_10_5)
// display manager stuff (to get screen resolution switches).
DMExtendedNotificationUPP m_displayManagerNotificationUPP;
ProcessSerialNumber m_PSN;
#endif
// fast user switching // fast user switching
EventHandlerRef m_switchEventHandlerRef; EventHandlerRef m_switchEventHandlerRef;