diff options
| -rw-r--r-- | indra/llwindow/llkeyboardmacosx.cpp | 1 | ||||
| -rw-r--r-- | indra/llwindow/llopenglview-objc.h | 4 | ||||
| -rw-r--r-- | indra/llwindow/llopenglview-objc.mm | 97 | ||||
| -rw-r--r-- | indra/llwindow/llwindowmacosx-objc.h | 11 | ||||
| -rw-r--r-- | indra/llwindow/llwindowmacosx-objc.mm | 45 | ||||
| -rw-r--r-- | indra/llwindow/llwindowmacosx.cpp | 126 | ||||
| -rw-r--r-- | indra/newview/Info-SecondLife.plist | 2 | ||||
| -rw-r--r-- | indra/newview/llviewerkeyboard.cpp | 1 | ||||
| -rwxr-xr-x | indra/newview/llviewerwindow.cpp | 1 | 
9 files changed, 252 insertions, 36 deletions
diff --git a/indra/llwindow/llkeyboardmacosx.cpp b/indra/llwindow/llkeyboardmacosx.cpp index 274e92c225..85bb7b9aeb 100644 --- a/indra/llwindow/llkeyboardmacosx.cpp +++ b/indra/llwindow/llkeyboardmacosx.cpp @@ -253,7 +253,6 @@ BOOL LLKeyboardMacOSX::handleKeyUp(const U16 key, const U32 mask)  	if(translateNumpadKey(key, &translated_key))  	{ -		LL_INFOS("Keyboard") << "Handled key!" << LL_ENDL;  		handled = handleTranslatedKeyUp(translated_key, translated_mask);  	} diff --git a/indra/llwindow/llopenglview-objc.h b/indra/llwindow/llopenglview-objc.h index 5134063193..8140421e44 100644 --- a/indra/llwindow/llopenglview-objc.h +++ b/indra/llwindow/llopenglview-objc.h @@ -20,6 +20,8 @@  	std::string mLastDraggedUrl;  	unsigned int mModifiers;  	float mMousePos[2]; +	bool mHasMarkedText; +	unsigned int mMarkedTextLength;  }  - (id) initWithSamples:(NSUInteger)samples;  - (id) initWithSamples:(NSUInteger)samples andVsync:(BOOL)vsync; @@ -40,6 +42,8 @@  - (unsigned long) getVramSize; +- (segment_t) getSegments:(NSAttributedString*)str; +  @end  @interface LLNSWindow : NSWindow diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index de159816e0..31b0e02ad8 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -281,15 +281,18 @@  - (void) keyDown:(NSEvent *)theEvent  {  	[[self inputContext] handleEvent:theEvent]; -	uint keycode = [theEvent keyCode]; -	callKeyDown(keycode, mModifiers); -	 -	// OS X intentionally does not send us key-up information on cmd-key combinations. -	// This behaviour is not a bug, and only applies to cmd-combinations (no others). -	// Since SL assumes we receive those, we fake it here. -	if (mModifiers & NSCommandKeyMask) +	if (!mHasMarkedText)  	{ -		callKeyUp([theEvent keyCode], mModifiers); +		uint keycode = [theEvent keyCode]; +		callKeyDown(keycode, mModifiers); +		 +		// OS X intentionally does not send us key-up information on cmd-key combinations. +		// This behaviour is not a bug, and only applies to cmd-combinations (no others). +		// Since SL assumes we receive those, we fake it here. +		if (mModifiers & NSCommandKeyMask) +		{ +			callKeyUp([theEvent keyCode], mModifiers); +		}  	}  } @@ -348,7 +351,7 @@  - (BOOL)hasMarkedText  { -	return NO; +	return mHasMarkedText;  }  - (NSRange)markedRange @@ -365,21 +368,73 @@  	return NSMakeRange(range[0], range[1]);  } -- (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange +- (segment_t) getSegments:(NSAttributedString*)str  { +	segment_t segments; +	 +	int segment = 0; +	 +	NSRange l; +	NSRange r = NSMakeRange(0, [str length]); +	 +	while (r.length > 0) +	{ +		NSNumber *segmentAttrib = [str attribute:NSUnderlineStyleAttributeName atIndex:r.location longestEffectiveRange:&l inRange:r]; +		 +		r = NSMakeRange(NSMaxRange(l), NSMaxRange(r) - NSMaxRange(l)); +		bool standout; +		if ([segmentAttrib integerValue] == 1) +		{ +			standout = false; +		} else { +			standout = true; +		} +		segments.insert(std::pair<int, bool>(l.length, standout)); +		 +		segment++; +	} +	return segments; +} + +- (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange +{ +	if ([aString class] == NSClassFromString(@"NSConcreteMutableAttributedString")) +	{ +		unsigned int selected[2] = { +			selectedRange.location, +			selectedRange.length +		}; +		 +		unsigned int replacement[2] = { +			replacementRange.location, +			replacementRange.length +		}; +		 +		NSLog(@"Attributed string: %@", aString); +		 +		unichar text[[aString length]]; +		[[aString mutableString] getCharacters:text range:NSMakeRange(0, [aString length])]; +		segment_t segments = [self getSegments:(NSAttributedString *)aString]; +		setMarkedText(text, selected, replacement, [aString length], segments); +		mHasMarkedText = TRUE; +		mMarkedTextLength = [aString length]; +	}  }  - (void)unmarkText  { -	 +	resetPreedit(); +	mHasMarkedText = FALSE;  } +// We don't support attributed strings.  - (NSArray *)validAttributesForMarkedText  {  	return [NSArray array];  } +// See above.  - (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange  {  	return nil; @@ -387,9 +442,21 @@  - (void)insertText:(id)aString replacementRange:(NSRange)replacementRange  { -	for (NSInteger i = 0; i < [aString length]; i++) +	if (!mHasMarkedText)  	{ -		callUnicodeCallback([aString characterAtIndex:i], mModifiers); +		for (NSInteger i = 0; i < [aString length]; i++) +		{ +			callUnicodeCallback([aString characterAtIndex:i], mModifiers); +		} +	} else { +		// We may never get this point since unmarkText may be called before insertText ever gets called once we submit our text. +		// But just in case... +		resetPreedit(); +		for (NSInteger i = 0; i < [aString length]; i++) +		{ +			handleUnicodeCharacter([aString characterAtIndex:i]); +		} +		mHasMarkedText = FALSE;  	}  } @@ -412,7 +479,9 @@  - (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange  { -	return NSZeroRect; +	float pos[4] = {0, 0, 0, 0}; +	getPreeditLocation(pos, mMarkedTextLength); +	return NSMakeRect(pos[0], pos[1], pos[2], pos[3]);  }  - (void)doCommandBySelector:(SEL)aSelector diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index 57bb071690..2de185fed3 100644 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -25,6 +25,10 @@   * $/LicenseInfo$   */ +#include <map> + +typedef std::map<int, bool> segment_t; +  // This will actually hold an NSCursor*, but that type is only available in objective C.  typedef void *CursorRef;  typedef void *NSWindowRef; @@ -71,6 +75,8 @@ void makeWindowOrderFront(NSWindowRef window);  void convertScreenToWindow(NSWindowRef window, float *coord);  void convertWindowToScreen(NSWindowRef window, float *coord);  void convertScreenToView(NSWindowRef window, float *coord); +void convertRectToScreen(NSWindowRef window, float *coord); +void convertRectFromScreen(NSWindowRef window, float *coord);  void setWindowPos(NSWindowRef window, float* pos);  void closeWindow(NSWindowRef window);  void removeGLView(GLViewRef view); @@ -113,6 +119,11 @@ void getPreeditSelectionRange(int *position, int *length);  void getPreeditMarkedRange(int *position, int *length);  void handleUnicodeCharacter(wchar_t c);  void updatePreeditor(unsigned short *str); +void setPreeditMarkedRange(int position, int length); +void resetPreedit(); +int wstring_length(const std::basic_string<wchar_t> & wstr, const int woffset, const int utf16_length, int *unaligned); +void setMarkedText(unsigned short *text, unsigned int *selectedRange, unsigned int *replacementRange, long text_len, segment_t segments); +void getPreeditLocation(float *location, unsigned int length);  NSWindowRef getMainAppWindow();  GLViewRef getGLView(); diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index 9530785b83..1a0647485c 100644 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -119,6 +119,7 @@ CursorRef createImageCursor(const char *fullpath, int hotspotX, int hotspotY)  void setArrowCursor()  {  	NSCursor *cursor = [NSCursor arrowCursor]; +	[NSCursor unhide];  	[cursor set];  } @@ -290,12 +291,44 @@ void makeWindowOrderFront(NSWindowRef window)  void convertScreenToWindow(NSWindowRef window, float *coord)  { -	NSPoint point; -	point.x = coord[0]; -	point.y = coord[1]; -	point = [(LLNSWindow*)window convertScreenToBase:point]; -	coord[0] = point.x; -	coord[1] = point.y; +	NSRect point; +	point.origin.x = coord[0]; +	point.origin.y = coord[1]; +	point = [(LLNSWindow*)window convertRectFromScreen:point]; +	coord[0] = point.origin.x; +	coord[1] = point.origin.y; +} + +void convertRectToScreen(NSWindowRef window, float *coord) +{ +	NSRect point; +	point.origin.x = coord[0]; +	point.origin.y = coord[1]; +	point.size.width = coord[2]; +	point.size.height = coord[3]; +	 +	point = [(LLNSWindow*)window convertRectToScreen:point]; +	 +	coord[0] = point.origin.x; +	coord[1] = point.origin.y; +	coord[2] = point.size.width; +	coord[3] = point.size.height; +} + +void convertRectFromScreen(NSWindowRef window, float *coord) +{ +	NSRect point; +	point.origin.x = coord[0]; +	point.origin.y = coord[1]; +	point.size.width = coord[2]; +	point.size.height = coord[3]; +	 +	point = [(LLNSWindow*)window convertRectFromScreen:point]; +	 +	coord[0] = point.origin.x; +	coord[1] = point.origin.y; +	coord[2] = point.size.width; +	coord[3] = point.size.height;  }  void convertScreenToView(NSWindowRef window, float *coord) diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 7e4b9a84a1..4e8934b149 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -381,30 +381,27 @@ void callQuitHandler()  	}  } -std::basic_string<wchar_t> getPreeditString() +void getPreeditSelectionRange(int *position, int *length)  { -	std::basic_string<wchar_t> str;  	if (gWindowImplementation->getPreeditor())  	{ -		str = gWindowImplementation->getPreeditor()->getPreeditString(); +		gWindowImplementation->getPreeditor()->getSelectionRange(position, length);  	} -	 -	return str;  } -void getPreeditSelectionRange(int *position, int *length) +void getPreeditMarkedRange(int *position, int *length)  {  	if (gWindowImplementation->getPreeditor())  	{ -		gWindowImplementation->getPreeditor()->getSelectionRange(position, length); +		gWindowImplementation->getPreeditor()->getPreeditRange(position, length);  	}  } -void getPreeditMarkedRange(int *position, int *length) +void setPreeditMarkedRange(int position, int length)  {  	if (gWindowImplementation->getPreeditor())  	{ -		gWindowImplementation->getPreeditor()->getPreeditRange(position, length); +		gWindowImplementation->getPreeditor()->markAsPreedit(position, length);  	}  } @@ -416,6 +413,69 @@ void handleUnicodeCharacter(wchar_t c)  	}  } +void resetPreedit() +{ +	if (gWindowImplementation->getPreeditor()) +	{ +		gWindowImplementation->getPreeditor()->resetPreedit(); +	} +} + +// For reasons of convenience, handle IME updates here. +// This largely mirrors the old implementation, only sans the carbon parameters. +void setMarkedText(unsigned short *unitext, unsigned int *selectedRange, unsigned int *replacementRange, long text_len, segment_t segments) +{ +	if (gWindowImplementation->getPreeditor()) +	{ +		LLPreeditor *preeditor = gWindowImplementation->getPreeditor(); +		 +		// This should be a viable replacement for the kEventParamTextInputSendReplaceRange parameter. +		if (replacementRange[0] < replacementRange[1]) +		{ +			const LLWString& text = preeditor->getPreeditString(); +			const S32 location = wstring_wstring_length_from_utf16_length(text, 0, replacementRange[0]); +			const S32 length = wstring_wstring_length_from_utf16_length(text, location, replacementRange[1]); +			preeditor->markAsPreedit(location, length); +		} +		 +		preeditor->resetPreedit(); +		 +		LLWString fix_str = utf16str_to_wstring(llutf16string(unitext, text_len)); +		 +		LLPreeditor::segment_lengths_t preedit_segment_lengths; +		LLPreeditor::standouts_t preedit_standouts; +		S32 caret_position = fix_str.length(); +		 +		for (segment_t::iterator i = segments.begin(); i != segments.end(); i++) +		{ +			preedit_segment_lengths.push_back(i->first); +			preedit_standouts.push_back(i->second); +		} +		 +		preeditor->updatePreedit(fix_str, preedit_segment_lengths, preedit_standouts, caret_position); +	} +} + +void getPreeditLocation(float *location, unsigned int length) +{ +	if (gWindowImplementation->getPreeditor()) +	{ +		LLPreeditor *preeditor = gWindowImplementation->getPreeditor(); +		LLCoordGL coord; +		LLCoordScreen screen; +		LLRect rect; +		 +		preeditor->getPreeditLocation(length, &coord, &rect, NULL); +		 +		float c[4] = {coord.mX, coord.mY, 0, 0}; +		 +		convertRectToScreen(gWindowImplementation->getWindow(), c); +		 +		location[0] = c[0]; +		location[1] = c[1]; +	} +} +  void LLWindowMacOSX::updateMouseDeltas(float* deltas)  {  	if (mCursorDecoupled) @@ -1295,8 +1355,22 @@ BOOL LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordGL *to)  BOOL LLWindowMacOSX::convertCoords(LLCoordGL from, LLCoordScreen *to)  {  	LLCoordWindow window_coord; +	if (mFullscreen) +	{ +		to->mX = from.mX; +		to->mY = from.mY; +		return TRUE; +	} else if (mWindow) +	{ +		convertCoords(from, &window_coord); +		convertCoords(window_coord, to); +		 +		LL_INFOS("Coords") << to->mX << ", " << to->mY << LL_ENDL; +		 +		return TRUE; +	} -	return(convertCoords(from, &window_coord) && convertCoords(window_coord, to)); +	return FALSE;  } @@ -1425,7 +1499,7 @@ void LLWindowMacOSX::updateCursor()  		//    Find out what they look like and replicate them.  		// These are essentially correct -	case UI_CURSOR_WAIT:		/* Apple purposely doesn't allow us to set the beachball cursor manually. */	break; +	case UI_CURSOR_WAIT:		/* Apple purposely doesn't allow us to set the beachball cursor manually.  Let NSApp figure out when to do this. */	break;  	case UI_CURSOR_IBEAM:		setIBeamCursor();	break;  	case UI_CURSOR_CROSS:		setCrossCursor();	break;  	case UI_CURSOR_HAND:		setPointingHandCursor();	break; @@ -1810,7 +1884,35 @@ static long getDictLong (CFDictionaryRef refDict, CFStringRef key)  void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b)  { -	// TODO: IME support +	if (preeditor != mPreeditor && !b) +	{ +		// This condition may occur by a call to +		// setEnabled(BOOL) against LLTextEditor or LLLineEditor +		// when the control is not focused. +		// We need to silently ignore the case so that +		// the language input status of the focused control +		// is not disturbed. +		return; +	} +	 +	// Take care of old and new preeditors. +	if (preeditor != mPreeditor || !b) +	{ +		// We need to interrupt before updating mPreeditor, +		// so that the fix string from input method goes to +		// the old preeditor. +		if (mLanguageTextInputAllowed) +		{ +			interruptLanguageTextInput(); +		} +		mPreeditor = (b ? preeditor : NULL); +	} +	 +	if (b == mLanguageTextInputAllowed) +	{ +		return; +	} +	mLanguageTextInputAllowed = b;  }  void LLWindowMacOSX::interruptLanguageTextInput() diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist index 5db52f040f..8fb4e88bc3 100644 --- a/indra/newview/Info-SecondLife.plist +++ b/indra/newview/Info-SecondLife.plist @@ -13,7 +13,7 @@  	<key>CFBundleInfoDictionaryVersion</key>  	<string>6.0</string>  	<key>CFBundleName</key> -	<string>Second Life</string> +	<string>SecondLife</string>  	<key>CFBundlePackageType</key>  	<string>APPL</string>  	<key>CFBundleSignature</key> diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index 92d8f2937e..f3b7c0fad4 100644 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -653,7 +653,6 @@ BOOL LLViewerKeyboard::modeFromString(const std::string& string, S32 *mode)  BOOL LLViewerKeyboard::handleKey(KEY translated_key,  MASK translated_mask, BOOL repeated)  { -	LL_INFOS("Keyboard Handling") << "Handling key " << translated_key << LL_ENDL;  	// check for re-map  	EKeyboardMode mode = gViewerKeyboard.getMode();  	U32 keyidx = (translated_mask<<16) | translated_key; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index ccaa9245cf..48a69129eb 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2429,7 +2429,6 @@ void LLViewerWindow::draw()  // Takes a single keydown event, usually when UI is visible  BOOL LLViewerWindow::handleKey(KEY key, MASK mask)  { -	LL_INFOS("Keyboard Handling") << "Handling key " << key << LL_ENDL;  	// hide tooltips on keypress  	LLToolTipMgr::instance().blockToolTips();  | 
