aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/platform/OSXScreen.mm
diff options
context:
space:
mode:
authorLibravatarUnit 193 <unit193@unit193.net>2021-11-10 00:54:35 -0500
committerLibravatarUnit 193 <unit193@unit193.net>2021-11-10 00:54:35 -0500
commit58fb7a0cee13d84170aac52f3f89d91888e1afe3 (patch)
tree1d6312ba15f9ece5a8031e5280dfb8b38be8dfa3 /src/lib/platform/OSXScreen.mm
parent28db84b46139c9bb2bbcac8c6cc56e71d1e35629 (diff)
parentbeb08eb751fa8e1f72042f263316ab5e5ddb596d (diff)
Update upstream source from tag 'upstream/2.4.0+dfsg'
Update to upstream version '2.4.0+dfsg' with Debian dir 4b6668cc08c7b0e56b1e1f7b4e89ecdb316182a0
Diffstat (limited to 'src/lib/platform/OSXScreen.mm')
-rw-r--r--src/lib/platform/OSXScreen.mm218
1 files changed, 106 insertions, 112 deletions
diff --git a/src/lib/platform/OSXScreen.mm b/src/lib/platform/OSXScreen.mm
index 2b4594f..d41e321 100644
--- a/src/lib/platform/OSXScreen.mm
+++ b/src/lib/platform/OSXScreen.mm
@@ -2,11 +2,11 @@
* barrier -- mouse and keyboard sharing utility
* Copyright (C) 2012-2016 Symless Ltd.
* 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 LICENSE 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
@@ -38,7 +38,6 @@
#include "base/Log.h"
#include "base/IEventQueue.h"
#include "base/TMethodEventJob.h"
-#include "base/TMethodJob.h"
#include <math.h>
#include <mach-o/dyld.h>
@@ -110,10 +109,10 @@ OSXScreen::OSXScreen(IEventQueue* events, bool isPrimary, bool autoShowHideCurso
updateScreenShape(m_displayID, 0);
m_screensaver = new OSXScreenSaver(m_events, getEventTarget());
m_keyState = new OSXKeyState(m_events);
-
+
// only needed when running as a server.
if (m_isPrimary) {
-
+
#if defined(MAC_OS_X_VERSION_10_9)
// we can't pass options to show the dialog, this must be done by the gui.
if (!AXIsProcessTrusted()) {
@@ -126,7 +125,7 @@ OSXScreen::OSXScreen(IEventQueue* events, bool isPrimary, bool autoShowHideCurso
}
#endif
}
-
+
// install display manager notification handler
CGDisplayRegisterReconfigurationCallback(displayReconfigurationCallback, this);
@@ -157,8 +156,7 @@ OSXScreen::OSXScreen(IEventQueue* events, bool isPrimary, bool autoShowHideCurso
m_carbonLoopReady = new CondVar<bool>(m_carbonLoopMutex, false);
#endif
LOG((CLOG_DEBUG "starting watchSystemPowerThread"));
- m_pmWatchThread = new Thread(new TMethodJob<OSXScreen>
- (this, &OSXScreen::watchSystemPowerThread));
+ m_pmWatchThread = new Thread([this](){ watchSystemPowerThread(); });
}
catch (...) {
m_events->removeHandler(m_events->forOSXScreen().confirmSleep(),
@@ -166,7 +164,7 @@ OSXScreen::OSXScreen(IEventQueue* events, bool isPrimary, bool autoShowHideCurso
if (m_switchEventHandlerRef != 0) {
RemoveEventHandler(m_switchEventHandlerRef);
}
-
+
CGDisplayRemoveReconfigurationCallback(displayReconfigurationCallback, this);
delete m_keyState;
@@ -217,7 +215,7 @@ OSXScreen::~OSXScreen()
delete m_keyState;
delete m_screensaver;
-
+
#if defined(MAC_OS_X_VERSION_10_7)
delete m_carbonLoopMutex;
delete m_carbonLoopReady;
@@ -273,7 +271,7 @@ OSXScreen::warpCursor(SInt32 x, SInt32 y)
pos.x = x;
pos.y = y;
CGWarpMouseCursorPosition(pos);
-
+
// save new cursor position
m_xCursor = x;
m_yCursor = y;
@@ -325,7 +323,7 @@ OSXScreen::registerHotKey(KeyID key, KeyModifierMask mask)
LOG((CLOG_DEBUG "could not map hotkey id=%04x mask=%04x", key, mask));
return 0;
}
-
+
// choose hotkey id
UInt32 id;
if (!m_oldHotKeyIDs.empty()) {
@@ -351,7 +349,7 @@ OSXScreen::registerHotKey(KeyID key, KeyModifierMask mask)
}
else {
EventHotKeyID hkid = { 'SNRG', (UInt32)id };
- OSStatus status = RegisterEventHotKey(macKey, macMask, hkid,
+ OSStatus status = RegisterEventHotKey(macKey, macMask, hkid,
GetApplicationEventTarget(), 0,
&ref);
okay = (status == noErr);
@@ -366,7 +364,7 @@ OSXScreen::registerHotKey(KeyID key, KeyModifierMask mask)
}
m_hotKeys.insert(std::make_pair(id, HotKeyItem(ref, macKey, macMask)));
-
+
LOG((CLOG_DEBUG "registered hotkey %s (id=%04x mask=%04x) as id=%d", barrier::KeyMap::formatKey(key, mask).c_str(), key, mask, id));
return id;
}
@@ -468,7 +466,7 @@ OSXScreen::postMouseEvent(CGPoint& pos) const
}
}
}
-
+
CGEventType type = kCGEventMouseMoved;
SInt8 button = m_buttonState.getFirstButtonDown();
@@ -478,10 +476,10 @@ OSXScreen::postMouseEvent(CGPoint& pos) const
}
CGEventRef event = CGEventCreateMouseEvent(NULL, type, pos, static_cast<CGMouseButton>(button));
-
+
// Dragging events also need the click state
CGEventSetIntegerValueField(event, kCGMouseEventClickState, m_clickState);
-
+
// Fix for sticky keys
CGEventFlags modifiers = m_keyState->getModifierStateAsOSXFlags();
CGEventSetFlags(event, modifiers);
@@ -503,7 +501,7 @@ OSXScreen::postMouseEvent(CGPoint& pos) const
CGEventSetDoubleValueField(event, kCGMouseEventDeltaY, deltaFY);
CGEventPost(kCGHIDEventTap, event);
-
+
CFRelease(event);
}
@@ -515,7 +513,7 @@ OSXScreen::fakeMouseButton(ButtonID id, bool press)
if (index >= NumButtonIDs) {
return;
}
-
+
CGPoint pos;
if (!m_cursorPosValid) {
SInt32 x, y;
@@ -533,79 +531,77 @@ OSXScreen::fakeMouseButton(ButtonID id, bool press)
// since we don't have double click distance in NX APIs
// we define our own defaults.
const double maxDiff = sqrt(2) + 0.0001;
-
+
double clickTime = [NSEvent doubleClickInterval];
-
+
// As long as the click is within the time window and distance window
// increase clickState (double click, triple click, etc)
- // This will allow for higher than triple click but the quartz documenation
+ // This will allow for higher than triple click but the quartz documentation
// does not specify that this should be limited to triple click
if (press) {
- if ((ARCH->time() - m_lastClickTime) <= clickTime && diff <= maxDiff){
+ if ((ARCH->time() - m_lastClickTime) <= clickTime && diff <= maxDiff) {
m_clickState++;
}
else {
m_clickState = 1;
}
-
+
m_lastClickTime = ARCH->time();
}
-
- if (m_clickState == 1){
+
+ if (m_clickState == 1) {
m_lastSingleClickXCursor = m_xCursor;
m_lastSingleClickYCursor = m_yCursor;
}
-
+
EMouseButtonState state = press ? kMouseButtonDown : kMouseButtonUp;
-
+
LOG((CLOG_DEBUG1 "faking mouse button id: %d press: %s", index, press ? "pressed" : "released"));
-
+
MouseButtonEventMapType thisButtonMap = MouseButtonEventMap[index];
CGEventType type = thisButtonMap[state];
CGEventRef event = CGEventCreateMouseEvent(NULL, type, pos, static_cast<CGMouseButton>(index));
-
+
CGEventSetIntegerValueField(event, kCGMouseEventClickState, m_clickState);
-
+
// Fix for sticky keys
CGEventFlags modifiers = m_keyState->getModifierStateAsOSXFlags();
CGEventSetFlags(event, modifiers);
-
+
m_buttonState.set(index, state);
CGEventPost(kCGHIDEventTap, event);
-
+
CFRelease(event);
-
+
if (!press && (id == kButtonLeft)) {
if (m_fakeDraggingStarted) {
- m_getDropTargetThread = new Thread(new TMethodJob<OSXScreen>(
- this, &OSXScreen::getDropTargetThread));
+ m_getDropTargetThread = new Thread([this](){ get_drop_target_thread(); });
}
-
+
m_draggingStarted = false;
}
}
-void
-OSXScreen::getDropTargetThread(void*)
+void OSXScreen::get_drop_target_thread()
{
#if defined(MAC_OS_X_VERSION_10_7)
char* cstr = NULL;
-
+
// wait for 5 secs for the drop destinaiton string to be filled.
UInt32 timeout = ARCH->time() + 5;
-
+
while (ARCH->time() < timeout) {
CFStringRef cfstr = getCocoaDropTarget();
cstr = CFStringRefToUTF8String(cfstr);
CFRelease(cfstr);
-
+
if (cstr != NULL) {
break;
}
ARCH->sleep(.1f);
}
-
+
if (cstr != NULL) {
LOG((CLOG_DEBUG "drop target: %s", cstr));
m_dropTarget = cstr;
@@ -626,12 +622,12 @@ OSXScreen::fakeMouseMove(SInt32 x, SInt32 y)
if (m_fakeDraggingStarted) {
m_buttonState.set(0, kMouseButtonDown);
}
-
+
// index 0 means left mouse button
if (m_buttonState.test(0)) {
m_draggingStarted = true;
}
-
+
// synthesize event
CGPoint pos;
pos.x = x;
@@ -679,11 +675,11 @@ OSXScreen::fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const
NULL, kCGScrollEventUnitLine, 2,
mapScrollWheelFromBarrier(yDelta),
-mapScrollWheelFromBarrier(xDelta));
-
+
// Fix for sticky keys
CGEventFlags modifiers = m_keyState->getModifierStateAsOSXFlags();
CGEventSetFlags(scrollEvent, modifiers);
-
+
CGEventPost(kCGHIDEventTap, scrollEvent);
CFRelease(scrollEvent);
}
@@ -754,11 +750,11 @@ OSXScreen::enable()
if (m_isPrimary) {
// FIXME -- start watching jump zones
-
+
// kCGEventTapOptionDefault = 0x00000000 (Missing in 10.4, so specified literally)
m_eventTapPort = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault,
- kCGEventMaskForAllEvents,
- handleCGInputEvent,
+ kCGEventMaskForAllEvents,
+ handleCGInputEvent,
this);
}
else {
@@ -773,10 +769,10 @@ OSXScreen::enable()
// there may be a better way to do this, but we register an event handler even if we're
// not on the primary display (acting as a client). This way, if a local event comes in
- // (either keyboard or mouse), we can make sure to show the cursor if we've hidden it.
+ // (either keyboard or mouse), we can make sure to show the cursor if we've hidden it.
m_eventTapPort = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault,
- kCGEventMaskForAllEvents,
- handleCGInputEventSecondary,
+ kCGEventMaskForAllEvents,
+ handleCGInputEventSecondary,
this);
}
@@ -798,9 +794,9 @@ OSXScreen::disable()
if (m_autoShowHideCursor) {
showCursor();
}
-
+
// FIXME -- stop watching jump zones, stop capturing input
-
+
if (m_eventTapRLSR) {
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m_eventTapRLSR, kCFRunLoopDefaultMode);
CFRelease(m_eventTapRLSR);
@@ -846,7 +842,7 @@ OSXScreen::enter()
io_registry_entry_t entry = IORegistryEntryFromPath(
kIOMasterPortDefault,
"IOService:/IOResources/IODisplayWrangler");
-
+
if (entry != MACH_PORT_NULL) {
IORegistryEntrySetCFProperty(entry, CFSTR("IORequestIdle"), kCFBooleanFalse);
IOObjectRelease(entry);
@@ -863,15 +859,15 @@ bool
OSXScreen::leave()
{
hideCursor();
-
+
if (isDraggingStarted()) {
String& fileList = getDraggingFilename();
-
+
if (!m_isPrimary) {
if (fileList.empty() == false) {
ClientApp& app = ClientApp::instance();
Client* client = app.getClientPtr();
-
+
DragInformation di;
di.setFilename(fileList);
DragFileList dragFileList;
@@ -881,7 +877,7 @@ OSXScreen::leave()
dragFileList, info);
client->sendDragInfo(fileCount, info, info.size());
LOG((CLOG_DEBUG "send dragging file to server"));
-
+
// TODO: what to do with multiple file or even
// a folder
client->sendFileToServer(fileList.c_str());
@@ -889,7 +885,7 @@ OSXScreen::leave()
}
m_draggingStarted = false;
}
-
+
if (m_isPrimary) {
avoidHesitatingCursor();
@@ -906,8 +902,8 @@ OSXScreen::setClipboard(ClipboardID, const IClipboard* src)
{
if (src != NULL) {
LOG((CLOG_DEBUG "setting clipboard"));
- Clipboard::copy(&m_pasteboard, src);
- }
+ Clipboard::copy(&m_pasteboard, src);
+ }
return true;
}
@@ -1036,16 +1032,16 @@ OSXScreen::handleSystemEvent(const Event& event, void*)
}
break;
- case kEventClassKeyboard:
+ case kEventClassKeyboard:
switch (GetEventKind(*carbonEvent)) {
case kEventHotKeyPressed:
case kEventHotKeyReleased:
onHotKey(*carbonEvent);
break;
}
-
+
break;
-
+
case kEventClassWindow:
// 2nd param was formerly GetWindowEventTarget(m_userInputWindow) which is 32-bit only,
// however as m_userInputWindow is never initialized to anything we can take advantage of
@@ -1076,7 +1072,7 @@ OSXScreen::handleSystemEvent(const Event& event, void*)
}
}
-bool
+bool
OSXScreen::onMouseMove(CGFloat mx, CGFloat my)
{
LOG((CLOG_DEBUG2 "mouse move %+f,%+f", mx, my));
@@ -1140,7 +1136,7 @@ OSXScreen::onMouseMove(CGFloat mx, CGFloat my)
return true;
}
-bool
+bool
OSXScreen::onMouseButton(bool pressed, UInt16 macButton)
{
// Buttons 2 and 3 are inverted on the mac
@@ -1176,7 +1172,7 @@ OSXScreen::onMouseButton(bool pressed, UInt16 macButton)
}
}
}
-
+
if (macButton == kButtonLeft) {
EMouseButtonState state = pressed ? kMouseButtonDown : kMouseButtonUp;
m_buttonState.set(kButtonLeft - 1, state);
@@ -1186,10 +1182,9 @@ OSXScreen::onMouseButton(bool pressed, UInt16 macButton)
}
else {
if (m_fakeDraggingStarted) {
- m_getDropTargetThread = new Thread(new TMethodJob<OSXScreen>(
- this, &OSXScreen::getDropTargetThread));
+ m_getDropTargetThread = new Thread([this](){ get_drop_target_thread(); });
}
-
+
m_draggingStarted = false;
}
}
@@ -1218,16 +1213,16 @@ OSXScreen::displayReconfigurationCallback(CGDirectDisplayID displayID, CGDisplay
// Closing or opening the lid when an external monitor is
// connected causes an kCGDisplayBeginConfigurationFlag event
- CGDisplayChangeSummaryFlags mask = kCGDisplayBeginConfigurationFlag | kCGDisplayMovedFlag |
- kCGDisplaySetModeFlag | kCGDisplayAddFlag | kCGDisplayRemoveFlag |
- kCGDisplayEnabledFlag | kCGDisplayDisabledFlag |
- kCGDisplayMirrorFlag | kCGDisplayUnMirrorFlag |
+ CGDisplayChangeSummaryFlags mask = kCGDisplayBeginConfigurationFlag | kCGDisplayMovedFlag |
+ kCGDisplaySetModeFlag | kCGDisplayAddFlag | kCGDisplayRemoveFlag |
+ kCGDisplayEnabledFlag | kCGDisplayDisabledFlag |
+ kCGDisplayMirrorFlag | kCGDisplayUnMirrorFlag |
kCGDisplayDesktopShapeChangedFlag;
-
+
LOG((CLOG_DEBUG1 "event: display was reconfigured: %x %x %x", flags, mask, flags & mask));
if (flags & mask) { /* Something actually did change */
-
+
LOG((CLOG_DEBUG1 "event: screen changed shape; refreshing dimensions"));
screen->updateScreenShape(displayID, flags);
}
@@ -1274,7 +1269,7 @@ OSXScreen::onKey(CGEventRef event)
m_activeModifierHotKeyMask = 0;
}
}
-
+
return true;
}
@@ -1342,7 +1337,7 @@ OSXScreen::onKey(CGEventRef event)
}
void
-OSXScreen::onMediaKey(CGEventRef event)
+OSXScreen::onMediaKey(CGEventRef event)
{
KeyID keyID;
bool down;
@@ -1405,7 +1400,7 @@ OSXScreen::mapBarrierButtonToMac(UInt16 button) const
return static_cast<ButtonID>(button);
}
-ButtonID
+ButtonID
OSXScreen::mapMacButtonToBarrier(UInt16 macButton) const
{
switch (macButton) {
@@ -1418,7 +1413,7 @@ OSXScreen::mapMacButtonToBarrier(UInt16 macButton) const
case 3:
return kButtonMiddle;
}
-
+
return static_cast<ButtonID>(macButton);
}
@@ -1445,8 +1440,8 @@ OSXScreen::getScrollSpeed() const
double scaling = 0.0;
CFPropertyListRef pref = ::CFPreferencesCopyValue(
- CFSTR("com.apple.scrollwheel.scaling") ,
- kCFPreferencesAnyApplication,
+ CFSTR("com.apple.scrollwheel.scaling") ,
+ kCFPreferencesAnyApplication,
kCFPreferencesCurrentUser,
kCFPreferencesAnyHost);
if (pref != NULL) {
@@ -1535,7 +1530,7 @@ OSXScreen::updateScreenShape()
if (CGGetActiveDisplayList(0, NULL, &displayCount) != CGDisplayNoErr) {
return;
}
-
+
if (displayCount == 0) {
return;
}
@@ -1579,13 +1574,13 @@ OSXScreen::updateScreenShape()
(displayCount == 1) ? "display" : "displays"));
}
-#pragma mark -
+#pragma mark -
//
// FAST USER SWITCH NOTIFICATION SUPPORT
//
// OSXScreen::userSwitchCallback(void*)
-//
+//
// gets called if a fast user switch occurs
//
@@ -1611,18 +1606,17 @@ OSXScreen::userSwitchCallback(EventHandlerCallRef nextHandler,
return (CallNextEventHandler(nextHandler, theEvent));
}
-#pragma mark -
+#pragma mark -
//
// SLEEP/WAKEUP NOTIFICATION SUPPORT
//
// OSXScreen::watchSystemPowerThread(void*)
-//
-// main of thread monitoring system power (sleep/wakup) using a CFRunLoop
+//
+// main of thread monitoring system power (sleep/wakeup) using a CFRunLoop
//
-void
-OSXScreen::watchSystemPowerThread(void*)
+void OSXScreen::watchSystemPowerThread()
{
io_object_t notifier;
IONotificationPortRef notificationPortRef;
@@ -1641,7 +1635,7 @@ OSXScreen::watchSystemPowerThread(void*)
CFRunLoopAddSource(m_pmRunloop, runloopSourceRef,
kCFRunLoopCommonModes);
}
-
+
// thread is ready
{
Lock lock(m_pmMutex);
@@ -1658,15 +1652,15 @@ OSXScreen::watchSystemPowerThread(void*)
}
LOG((CLOG_DEBUG "started watchSystemPowerThread"));
-
+
LOG((CLOG_DEBUG "waiting for event loop"));
m_events->waitForReady();
-
+
#if defined(MAC_OS_X_VERSION_10_7)
{
Lock lockCarbon(m_carbonLoopMutex);
if (*m_carbonLoopReady == false) {
-
+
// we signalling carbon loop ready before starting
// unless we know how to do it within the loop
LOG((CLOG_DEBUG "signalling carbon loop ready"));
@@ -1676,12 +1670,12 @@ OSXScreen::watchSystemPowerThread(void*)
}
}
#endif
-
+
// start the run loop
LOG((CLOG_DEBUG "starting carbon loop"));
CFRunLoopRun();
LOG((CLOG_DEBUG "carbon loop has stopped"));
-
+
// cleanup
if (notificationPortRef) {
CFRunLoopRemoveSource(m_pmRunloop,
@@ -1716,7 +1710,7 @@ OSXScreen::handlePowerChangeRequest(natural_t messageType, void* messageArg)
getEventTarget(), messageArg,
Event::kDontFreeData));
return;
-
+
case kIOMessageSystemHasPoweredOn:
LOG((CLOG_DEBUG "system wakeup"));
m_events->addEvent(Event(m_events->forIScreen().resume(),
@@ -1742,16 +1736,16 @@ OSXScreen::handleConfirmSleep(const Event& event, void*)
if (m_pmRootPort != 0) {
// deliver suspend event immediately.
m_events->addEvent(Event(m_events->forIScreen().suspend(),
- getEventTarget(), NULL,
+ getEventTarget(), NULL,
Event::kDeliverImmediately));
-
+
LOG((CLOG_DEBUG "system will sleep"));
IOAllowPowerChange(m_pmRootPort, messageArg);
}
}
}
-#pragma mark -
+#pragma mark -
//
// GLOBAL HOTKEY OPERATING MODE SUPPORT (10.3)
@@ -1941,7 +1935,7 @@ OSXScreen::handleCGInputEvent(CGEventTapProxy proxy,
case kCGEventMouseMoved:
pos = CGEventGetLocation(event);
screen->onMouseMove(pos.x, pos.y);
-
+
// The system ignores our cursor-centering calls if
// we don't return the event. This should be harmless,
// but might register as slight movement to other apps
@@ -1980,10 +1974,10 @@ OSXScreen::handleCGInputEvent(CGEventTapProxy proxy,
}
break;
}
-
+
LOG((CLOG_DEBUG3 "unknown quartz event type: 0x%02x", type));
}
-
+
if (screen->m_isOnScreen) {
return event;
} else {
@@ -1992,38 +1986,38 @@ OSXScreen::handleCGInputEvent(CGEventTapProxy proxy,
}
void
-OSXScreen::MouseButtonState::set(UInt32 button, EMouseButtonState state)
+OSXScreen::MouseButtonState::set(UInt32 button, EMouseButtonState state)
{
bool newState = (state == kMouseButtonDown);
m_buttons.set(button, newState);
}
bool
-OSXScreen::MouseButtonState::any()
+OSXScreen::MouseButtonState::any()
{
return m_buttons.any();
}
void
-OSXScreen::MouseButtonState::reset()
+OSXScreen::MouseButtonState::reset()
{
m_buttons.reset();
}
void
-OSXScreen::MouseButtonState::overwrite(UInt32 buttons)
+OSXScreen::MouseButtonState::overwrite(UInt32 buttons)
{
m_buttons = std::bitset<NumButtonIDs>(buttons);
}
bool
-OSXScreen::MouseButtonState::test(UInt32 button) const
+OSXScreen::MouseButtonState::test(UInt32 button) const
{
return m_buttons.test(button);
}
SInt8
-OSXScreen::MouseButtonState::getFirstButtonDown() const
+OSXScreen::MouseButtonState::getFirstButtonDown() const
{
if (m_buttons.any()) {
for (unsigned short button = 0; button < m_buttons.size(); button++) {
@@ -2041,7 +2035,7 @@ OSXScreen::CFStringRefToUTF8String(CFStringRef aString)
if (aString == NULL) {
return NULL;
}
-
+
CFIndex length = CFStringGetLength(aString);
CFIndex maxSize = CFStringGetMaximumSizeForEncoding(
length,