diff --git a/build/commands.py b/build/toolchain.py similarity index 91% rename from build/commands.py rename to build/toolchain.py index 1c667798..2e932bf1 100644 --- a/build/commands.py +++ b/build/toolchain.py @@ -15,7 +15,10 @@ # 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: @@ -42,7 +45,11 @@ class InternalCommands: config_filename = '%s.cfg' % this_cmd qtpro_filename = 'qsynergy.pro' 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' @@ -59,40 +66,21 @@ class InternalCommands: enable_make_gui = False win32_generators = { - '1' : 'Visual Studio 10', - '2' : 'Visual Studio 10 Win64', - '3' : 'Visual Studio 9 2008', - '4' : 'Visual Studio 9 2008 Win64', - '5' : 'Visual Studio 8 2005', - '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', + 1 : 'Visual Studio 10', + 2 : 'Visual Studio 10 Win64', + 3 : 'Visual Studio 9 2008', + 4 : 'Visual Studio 9 2008 Win64', + 5 : 'Visual Studio 8 2005', + 6 : 'Visual Studio 8 2005 Win64', } unix_generators = { - '1' : 'Unix Makefiles', -# '2' : 'CodeBlocks - Unix Makefiles', -# '3' : 'Eclipse CDT4 - Unix Makefiles', -# '4' : 'KDevelop3', -# '5' : 'KDevelop3 - Unix Makefiles', + 1 : 'Unix Makefiles', } darwin_generators = { - '1' : 'Xcode', - '2' : 'Unix Makefiles', -# '3' : 'CodeBlocks - Unix Makefiles', -# '4' : 'Eclipse CDT4 - Unix Makefiles', -# '5' : 'KDevelop3', -# '6' : 'KDevelop3 - Unix Makefiles', + 1 : 'Unix Makefiles', + 2 : 'Xcode', } def getBinDir(self, target=''): @@ -264,7 +252,7 @@ class InternalCommands: # TODO pass - def build(self, targets=[]): + def build(self, targets=[], skipConfig=False): # if no mode specified, default to debug if len(targets) == 0: @@ -277,7 +265,7 @@ class InternalCommands: if generator.startswith('Visual Studio'): # 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() for target in targets: @@ -297,7 +285,7 @@ class InternalCommands: 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.try_chdir(self.getBinDir(target)) @@ -449,6 +437,9 @@ class InternalCommands: if type != 'win': 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: self.dist_usage() return @@ -479,27 +470,7 @@ class InternalCommands: elif type == 'mac': if sys.platform == 'darwin': - # nb: disabling package maker, as it doesn't - # 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) + self.distMac(unixTarget) else: package_unsupported = True @@ -512,6 +483,34 @@ class InternalCommands: % (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): if vcRedistDir == '': @@ -746,8 +745,7 @@ class InternalCommands: def get_generator_from_config(self): if self.generator_id: - generators = self.get_generators() - return generators[self.generator_id] + return self.getGenerator() else: config = ConfigParser.RawConfigParser() config.read(self.config_filepath()) @@ -796,28 +794,20 @@ class InternalCommands: raise Exception('Unsupported platform: ' + sys.platform) def get_generator_from_prompt(self): - + return self.getGenerator() + + def getGenerator(self): generators = self.get_generators() + if len(generators.keys()) == 1: + return generators[generators.keys()[0]] # if user has specified a generator as an argument if self.generator_id: - return generators[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) - + return generators[int(self.generator_id)] 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): @@ -936,6 +926,27 @@ class InternalCommands: if err != 0: 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 # 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 @@ -1051,3 +1062,6 @@ class CommandHandler: def open(self): self.ic.open() + + def genlist(self): + self.ic.printGeneratorList() diff --git a/doc/MacReadme.txt b/doc/MacReadme.txt new file mode 100755 index 00000000..38dfe246 --- /dev/null +++ b/doc/MacReadme.txt @@ -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 diff --git a/doc/synergy-stooges.conf b/doc/synergy.conf.example similarity index 100% rename from doc/synergy-stooges.conf rename to doc/synergy.conf.example diff --git a/doc/synergy-advanced.conf b/doc/synergy.conf.example-advanced similarity index 100% rename from doc/synergy-advanced.conf rename to doc/synergy.conf.example-advanced diff --git a/doc/synergy-basic.conf b/doc/synergy.conf.example-basic similarity index 100% rename from doc/synergy-basic.conf rename to doc/synergy.conf.example-basic diff --git a/hm.py b/hm.py index b50b60e7..43ab17a2 100644 --- a/hm.py +++ b/hm.py @@ -30,9 +30,13 @@ # This will create an in-source UNIX Makefile. import sys, os -from build import commands +from build import toolchain from getopt import gnu_getopt +# minimum required version +requiredMajor = 2 +requiredMinor = 3 + # options used by all commands global_options = 'g:v' global_options_long = ['no-prompts', 'generator=', 'verbose', 'make-gui'] @@ -59,6 +63,7 @@ cmd_opt_dict = { 'revision' : ['', []], 'reformat' : ['', []], 'open' : ['', []], + 'genlist' : ['', []] } # aliases to valid commands @@ -171,7 +176,7 @@ def run_cmd(cmd, argv = []): # pass args and optarg data to command handler, which figures out # 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 cmd_func = getattr(handler, cmd) @@ -181,15 +186,17 @@ def run_cmd(cmd, argv = []): if not verbose: # print friendly error for users sys.stderr.write('Error: ' + sys.exc_info()[1].__str__() + '\n') - exit(1) + sys.exit(1) else: # if user wants to be verbose let python do it's thing raise def main(argv): - if sys.version_info < (2, 4): - print 'Python version must be at least: 2.4' + if sys.version_info < (requiredMajor, requiredMinor): + 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) try: diff --git a/lib/platform/COSXKeyState.cpp b/lib/platform/COSXKeyState.cpp index b868ae06..5f3f7f88 100644 --- a/lib/platform/COSXKeyState.cpp +++ b/lib/platform/COSXKeyState.cpp @@ -232,7 +232,12 @@ COSXKeyState::mapKeyFromEvent(CKeyIDs& ids, // get keyboard info +#if defined(MAC_OS_X_VERSION_10_5) TISInputSourceRef currentKeyboardLayout = TISCopyCurrentKeyboardLayoutInputSource(); +#else + KeyboardLayoutRef currentKeyboardLayout; + OSStatus status = KLGetCurrentKeyboardLayout(¤tKeyboardLayout); +#endif if (currentKeyboardLayout == NULL) { return kKeyNone; } @@ -265,22 +270,49 @@ COSXKeyState::mapKeyFromEvent(CKeyIDs& ids, return 0; } + const bool layoutValid = false; + const UCKeyboardLayout* layout; + // translate via uchr resource +#if defined(MAC_OS_X_VERSION_10_5) CFDataRef ref = (CFDataRef) TISGetInputSourceProperty(currentKeyboardLayout, kTISPropertyUnicodeKeyLayoutData); - const UCKeyboardLayout* layout = (const UCKeyboardLayout*) CFDataGetBytePtr(ref); - if (layout != NULL) { + layout = (const UCKeyboardLayout*) CFDataGetBytePtr(ref); + 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 UniCharCount count; UniChar chars[2]; - //LOG((CLOG_DEBUG "modifiers: %08x", modifiers & 0xffu)); + LOG((CLOG_DEBUG2 "modifiers: %08x", modifiers & 0xffu)); OSStatus status = UCKeyTranslate(layout, vkCode & 0xffu, action, (modifiers >> 8) & 0xffu, LMGetKbdType(), 0, &m_deadKeyState, sizeof(chars) / sizeof(chars[0]), &count, chars); - + // get the characters if (status == 0) { if (count != 0 || m_deadKeyState == 0) { @@ -314,11 +346,21 @@ COSXKeyState::pollActiveModifiers() const SInt32 COSXKeyState::pollActiveGroup() const { - TISInputSourceRef inputSource = TISCopyCurrentKeyboardLayoutInputSource(); - GroupMap::const_iterator i = m_groupMap.find(inputSource); - if (i != m_groupMap.end()) { - return i->second; - } + bool layoutValid = true; +#if defined(MAC_OS_X_VERSION_10_5) + TISInputSourceRef keyboardLayout = TISCopyCurrentKeyboardLayoutInputSource(); +#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; } @@ -354,10 +396,23 @@ COSXKeyState::getKeyMap(CKeyMap& keyMap) // add special keys getKeyMapForSpecialKeys(keyMap, g); - CFDataRef resource_ref; - if ((resource_ref = (CFDataRef)TISGetInputSourceProperty(m_groups[g], - kTISPropertyUnicodeKeyLayoutData)) != NULL) { - const void* resource = CFDataGetBytePtr(resource_ref); + const void* resource; + bool layoutValid = false; + + // 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); if (uchr.isValid()) { 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)); } } @@ -663,23 +733,41 @@ COSXKeyState::handleModifierKey(void* target, bool COSXKeyState::getGroups(GroupList& groups) const { + CFIndex n; + bool gotLayouts = false; + +#if defined(MAC_OS_X_VERSION_10_5) // get number of layouts - CFStringRef keys[] = { kTISPropertyInputSourceCategory }; - CFStringRef values[] = { kTISCategoryKeyboardInputSource }; - CFDictionaryRef dict = CFDictionaryCreate(NULL, (const void **)keys, (const void **)values, 1, NULL, NULL); - CFArrayRef kbds = TISCreateInputSourceList(dict, false); - CFIndex n = CFArrayGetCount(kbds); - if (n == 0) { + CFStringRef keys[] = { kTISPropertyInputSourceCategory }; + CFStringRef values[] = { kTISCategoryKeyboardInputSource }; + CFDictionaryRef dict = CFDictionaryCreate(NULL, (const void **)keys, (const void **)values, 1, NULL, NULL); + CFArrayRef kbds = TISCreateInputSourceList(dict, false); + n = CFArrayGetCount(kbds); + gotLayouts = (n != 0); +#else + OSStatus status = KLGetKeyboardLayoutCount(&n); + gotLayouts = (status == noErr); +#endif + + if (!gotLayouts) { LOG((CLOG_DEBUG1 "can't get keyboard layouts")); return false; } // get each layout groups.clear(); - TISInputSourceRef inputKeyboardLayout; for (CFIndex i = 0; i < n; ++i) { - inputKeyboardLayout = (TISInputSourceRef) CFArrayGetValueAtIndex(kbds, i); - groups.push_back(inputKeyboardLayout); + bool addToGroups = true; +#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; } @@ -687,7 +775,11 @@ COSXKeyState::getGroups(GroupList& groups) const void COSXKeyState::setGroup(SInt32 group) { +#if defined(MAC_OS_X_VERSION_10_5) TISSetInputMethodKeyboardLayoutOverride(m_groups[group]); +#else + KLSetCurrentKeyboardLayout(m_groups[group]); +#endif } void @@ -832,16 +924,18 @@ COSXKeyState::CKeyResource::getKeyID(UInt8 c) str[0] = static_cast(c); str[1] = 0; +#if defined(MAC_OS_X_VERSION_10_5) // get current keyboard script - - TISInputSourceRef isref = TISCopyCurrentKeyboardInputSource(); - CFArrayRef langs = (CFArrayRef) TISGetInputSourceProperty(isref, kTISPropertyInputSourceLanguages); - + TISInputSourceRef isref = TISCopyCurrentKeyboardInputSource(); + CFArrayRef langs = (CFArrayRef) TISGetInputSourceProperty(isref, kTISPropertyInputSourceLanguages); + CFStringEncoding encoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)CFArrayGetValueAtIndex(langs, 0)); +#else + CFStringEncoding encoding = GetScriptManagerVariable(smKeyScript); +#endif // convert to unicode CFStringRef cfString = - CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, - str, CFStringConvertIANACharSetNameToEncoding((CFStringRef) CFArrayGetValueAtIndex(langs, 0)), - kCFAllocatorNull); + CFStringCreateWithCStringNoCopy( + kCFAllocatorDefault, str, encoding, kCFAllocatorNull); // sometimes CFStringCreate...() returns NULL (e.g. Apple Korean // encoding with char value 214). if it did then make no key, diff --git a/lib/platform/COSXKeyState.h b/lib/platform/COSXKeyState.h index 1bebe7b7..3c9f4275 100644 --- a/lib/platform/COSXKeyState.h +++ b/lib/platform/COSXKeyState.h @@ -24,6 +24,12 @@ #include "stdset.h" #include "stdvector.h" +#if defined(MAC_OS_X_VERSION_10_5) + typedef TISInputSourceRef KeyLayout; +#else + typedef KeyboardLayoutRef KeyLayout; +#endif + //! OS X key state /*! A key state for OS X. @@ -99,7 +105,7 @@ protected: private: class CKeyResource; - typedef std::vector GroupList; + typedef std::vector GroupList; // Add hard coded special keys to a CKeyMap. void getKeyMapForSpecialKeys( @@ -197,7 +203,7 @@ private: KeyButtonOffset = 1 }; - typedef std::map GroupMap; + typedef std::map GroupMap; typedef std::map CVirtualKeyMap; CVirtualKeyMap m_virtualKeyMap; diff --git a/lib/platform/COSXScreen.cpp b/lib/platform/COSXScreen.cpp index 48501da6..ae3ee661 100644 --- a/lib/platform/COSXScreen.cpp +++ b/lib/platform/COSXScreen.cpp @@ -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.")); } } - + // install display manager notification handler +#if defined(MAC_OS_X_VERSION_10_5) 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 EventTypeSpec switchEventTypes[2]; @@ -132,7 +140,24 @@ COSXScreen::COSXScreen(bool isPrimary) : if (m_switchEventHandlerRef != 0) { RemoveEventHandler(m_switchEventHandlerRef); } +#if defined(MAC_OS_X_VERSION_10_5) 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_screensaver; @@ -178,7 +203,22 @@ COSXScreen::~COSXScreen() RemoveEventHandler(m_switchEventHandlerRef); +#if defined(MAC_OS_X_VERSION_10_5) 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_screensaver; @@ -526,17 +566,22 @@ void COSXScreen::fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const { 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 // is the right choice here over kCGScrollEventUnitPixel - CGEventRef scrollEvent = CGEventCreateScrollWheelEvent(NULL, - kCGScrollEventUnitLine, - 2, - mapScrollWheelFromSynergy(yDelta), - -mapScrollWheelFromSynergy(xDelta)); + CGEventRef scrollEvent = CGEventCreateScrollWheelEvent( + NULL, kCGScrollEventUnitLine, 2, + mapScrollWheelFromSynergy(yDelta), + -mapScrollWheelFromSynergy(xDelta)); CGEventPost(kCGHIDEventTap, scrollEvent); - CFRelease(scrollEvent); +#else + + CGPostScrollWheelEvent( + 2, mapScrollWheelFromSynergy(yDelta), + -mapScrollWheelFromSynergy(xDelta)); +#endif } } @@ -988,6 +1033,42 @@ COSXScreen::handleClipboardCheck(const CEvent&, void*) 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 COSXScreen::displayReconfigurationCallback(CGDirectDisplayID displayID, CGDisplayChangeSummaryFlags flags, void* inUserData) { @@ -1007,6 +1088,7 @@ COSXScreen::displayReconfigurationCallback(CGDirectDisplayID displayID, CGDispla screen->updateScreenShape(displayID, flags); } } +#endif bool COSXScreen::onKey(CGEventRef event) @@ -1275,7 +1357,12 @@ COSXScreen::getKeyState() const void COSXScreen::updateScreenShape(const CGDirectDisplayID, const CGDisplayChangeSummaryFlags flags) { - + updateScreenShape(); +} + +void +COSXScreen::updateScreenShape() +{ // get info for each display CGDisplayCount displayCount = 0; diff --git a/lib/platform/COSXScreen.h b/lib/platform/COSXScreen.h index c8c08cd1..9719d256 100644 --- a/lib/platform/COSXScreen.h +++ b/lib/platform/COSXScreen.h @@ -100,6 +100,7 @@ protected: virtual IKeyState* getKeyState() const; private: + void updateScreenShape(); void updateScreenShape(const CGDirectDisplayID, const CGDisplayChangeSummaryFlags); void postMouseEvent(CGPoint&) const; @@ -114,10 +115,14 @@ private: // of the button pressed using the mac button mapping. bool onMouseButton(bool pressed, UInt16 macButton); bool onMouseWheel(SInt32 xDelta, SInt32 yDelta) const; - + + #if !defined(MAC_OS_X_VERSION_10_5) + bool onDisplayChange(); + #endif void constructMouseButtonEventMap(); bool onKey(CGEventRef event); + bool onHotKey(EventRef event) const; // Added here to allow the carbon cursor hack to be called. @@ -148,10 +153,14 @@ private: // clipboard check timer handler void handleClipboardCheck(const CEvent&, void*); +#if defined(MAC_OS_X_VERSION_10_5) // Resolution switch callback static void displayReconfigurationCallback(CGDirectDisplayID, CGDisplayChangeSummaryFlags, void*); - +#else + static pascal void displayManagerCallback(void* inUserData, + SInt16 inMessage, void* inNotifyData); +#endif // fast user switch callback static pascal OSStatus userSwitchCallback(EventHandlerCallRef nextHandler, @@ -279,6 +288,12 @@ private: // does not have focus. 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 EventHandlerRef m_switchEventHandlerRef;