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

@@ -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(&currentKeyboardLayout);
#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<char>(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,

View File

@@ -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<TISInputSourceRef> GroupList;
typedef std::vector<KeyLayout> GroupList;
// Add hard coded special keys to a CKeyMap.
void getKeyMapForSpecialKeys(
@@ -197,7 +203,7 @@ private:
KeyButtonOffset = 1
};
typedef std::map<TISInputSourceRef, SInt32> GroupMap;
typedef std::map<KeyLayout, SInt32> GroupMap;
typedef std::map<UInt32, KeyID> CVirtualKeyMap;
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."));
}
}
// 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;

View File

@@ -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;