summaryrefslogtreecommitdiff
path: root/indra/llwindow
diff options
context:
space:
mode:
authorOz Linden <oz@lindenlab.com>2014-12-15 12:34:18 -0500
committerOz Linden <oz@lindenlab.com>2014-12-15 12:34:18 -0500
commitdab5acd972c05b4c9d23d5dfb46afe9eff6c9567 (patch)
tree6f3b1ca79eefbc2b232a5da809359eefcf59ecfb /indra/llwindow
parenteb5c0dd32a7f4e4a603fe88cfa5f18c30725d11a (diff)
parent6d48db868f7459fcf5f0e89d830a844e409d4163 (diff)
merge changes for 3.7.22-release
Diffstat (limited to 'indra/llwindow')
-rw-r--r--indra/llwindow/llopenglview-objc.h1
-rw-r--r--indra/llwindow/llopenglview-objc.mm170
-rwxr-xr-xindra/llwindow/llwindowmacosx.cpp8
3 files changed, 120 insertions, 59 deletions
diff --git a/indra/llwindow/llopenglview-objc.h b/indra/llwindow/llopenglview-objc.h
index f1fab3b2c6..072d40f739 100644
--- a/indra/llwindow/llopenglview-objc.h
+++ b/indra/llwindow/llopenglview-objc.h
@@ -79,6 +79,7 @@
@interface LLNonInlineTextView : NSTextView
{
LLOpenGLView *glview;
+ unichar mKeyPressed;
}
- (void) setGLView:(LLOpenGLView*)view;
diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm
index 141eab792a..773c093e2f 100644
--- a/indra/llwindow/llopenglview-objc.mm
+++ b/indra/llwindow/llopenglview-objc.mm
@@ -270,14 +270,14 @@ attributedStringInfo getSegments(NSAttributedString *str)
!([theEvent modifierFlags] & NSFunctionKeyMask) &&
!([theEvent modifierFlags] & NSHelpKeyMask))
{
- callRightMouseDown(mMousePos, mModifiers);
+ callRightMouseDown(mMousePos, [theEvent modifierFlags]);
mSimulatedRightClick = true;
} else {
if ([theEvent clickCount] >= 2)
{
- callDoubleClick(mMousePos, mModifiers);
+ callDoubleClick(mMousePos, [theEvent modifierFlags]);
} else if ([theEvent clickCount] == 1) {
- callLeftMouseDown(mMousePos, mModifiers);
+ callLeftMouseDown(mMousePos, [theEvent modifierFlags]);
}
}
}
@@ -286,21 +286,21 @@ attributedStringInfo getSegments(NSAttributedString *str)
{
if (mSimulatedRightClick)
{
- callRightMouseUp(mMousePos, mModifiers);
+ callRightMouseUp(mMousePos, [theEvent modifierFlags]);
mSimulatedRightClick = false;
} else {
- callLeftMouseUp(mMousePos, mModifiers);
+ callLeftMouseUp(mMousePos, [theEvent modifierFlags]);
}
}
- (void) rightMouseDown:(NSEvent *)theEvent
{
- callRightMouseDown(mMousePos, mModifiers);
+ callRightMouseDown(mMousePos, [theEvent modifierFlags]);
}
- (void) rightMouseUp:(NSEvent *)theEvent
{
- callRightMouseUp(mMousePos, mModifiers);
+ callRightMouseUp(mMousePos, [theEvent modifierFlags]);
}
- (void)mouseMoved:(NSEvent *)theEvent
@@ -341,12 +341,12 @@ attributedStringInfo getSegments(NSAttributedString *str)
- (void) otherMouseDown:(NSEvent *)theEvent
{
- callMiddleMouseDown(mMousePos, mModifiers);
+ callMiddleMouseDown(mMousePos, [theEvent modifierFlags]);
}
- (void) otherMouseUp:(NSEvent *)theEvent
{
- callMiddleMouseUp(mMousePos, mModifiers);
+ callMiddleMouseUp(mMousePos, [theEvent modifierFlags]);
}
- (void) otherMouseDragged:(NSEvent *)theEvent
@@ -366,22 +366,27 @@ attributedStringInfo getSegments(NSAttributedString *str)
- (void) keyUp:(NSEvent *)theEvent
{
- callKeyUp([theEvent keyCode], mModifiers);
+ callKeyUp([theEvent keyCode], [theEvent modifierFlags]);
}
- (void) keyDown:(NSEvent *)theEvent
{
uint keycode = [theEvent keyCode];
+ // We must not depend on flagsChange event to detect modifier flags changed,
+ // must depend on the modifire flags in the event parameter.
+ // Because flagsChange event handler misses event when other window is activated,
+ // e.g. OS Window for upload something or Input Window...
+ // mModifiers instance variable is for insertText: or insertText:replacementRange: (by Pell Smit)
+ mModifiers = [theEvent modifierFlags];
bool acceptsText = mHasMarkedText ? false : callKeyDown(keycode, mModifiers);
+ unichar ch;
if (acceptsText &&
!mMarkedTextAllowed &&
+ !(mModifiers & (NSControlKeyMask | NSCommandKeyMask)) && // commands don't invoke InputWindow
![(LLAppDelegate*)[NSApp delegate] romanScript] &&
- [[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSDeleteCharacter &&
- [[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSBackspaceCharacter &&
- [[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSDownArrowFunctionKey &&
- [[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSUpArrowFunctionKey &&
- [[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSLeftArrowFunctionKey &&
- [[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSRightArrowFunctionKey)
+ (ch = [[theEvent charactersIgnoringModifiers] characterAtIndex:0]) > ' ' &&
+ ch != NSDeleteCharacter &&
+ (ch < 0xF700 || ch > 0xF8FF)) // 0xF700-0xF8FF: reserved for function keys on the keyboard(from NSEvent.h)
{
[(LLAppDelegate*)[NSApp delegate] showInputWindow:true withEvent:theEvent];
} else
@@ -498,31 +503,58 @@ attributedStringInfo getSegments(NSAttributedString *str)
- (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange
{
- if ([aString class] == NSClassFromString(@"NSConcreteMutableAttributedString"))
+ // Apple says aString can be either an NSString or NSAttributedString instance.
+ // But actually it's NSConcreteMutableAttributedString or __NSCFConstantString.
+ // I observed aString was __NSCFConstantString only aString was null string(zero length).
+ // Apple also says when aString is an NSString object,
+ // the receiver is expected to render the marked text with distinguishing appearance.
+ // So I tried to make attributedStringInfo, but it won't be used... (Pell Smit)
+
+ if (mMarkedTextAllowed)
{
- if (mMarkedTextAllowed)
+ unsigned int selected[2] = {
+ selectedRange.location,
+ selectedRange.length
+ };
+
+ unsigned int replacement[2] = {
+ replacementRange.location,
+ replacementRange.length
+ };
+
+ int string_length = [aString length];
+ unichar text[string_length];
+ attributedStringInfo segments;
+ // I used 'respondsToSelector:@selector(string)'
+ // to judge aString is an attributed string or not.
+ if ([aString respondsToSelector:@selector(string)])
+ {
+ // aString is attibuted
+ [[aString string] getCharacters:text range:NSMakeRange(0, string_length)];
+ segments = getSegments((NSAttributedString *)aString);
+ }
+ else
+ {
+ // aString is not attributed
+ [aString getCharacters:text range:NSMakeRange(0, string_length)];
+ segments.seg_lengths.push_back(string_length);
+ segments.seg_standouts.push_back(true);
+ }
+ setMarkedText(text, selected, replacement, string_length, segments);
+ if (string_length > 0)
{
- unsigned int selected[2] = {
- selectedRange.location,
- selectedRange.length
- };
-
- unsigned int replacement[2] = {
- replacementRange.location,
- replacementRange.length
- };
-
- unichar text[[aString length]];
- [[aString mutableString] getCharacters:text range:NSMakeRange(0, [aString length])];
- attributedStringInfo segments = getSegments((NSAttributedString *)aString);
- setMarkedText(text, selected, replacement, [aString length], segments);
mHasMarkedText = TRUE;
- mMarkedTextLength = [aString length];
- } else {
- if (mHasMarkedText)
- {
- [self unmarkText];
- }
+ mMarkedTextLength = string_length;
+ }
+ else
+ {
+ // we must clear the marked text when aString is null.
+ [self unmarkText];
+ }
+ } else {
+ if (mHasMarkedText)
+ {
+ [self unmarkText];
}
}
}
@@ -641,37 +673,63 @@ attributedStringInfo getSegments(NSAttributedString *str)
@implementation LLNonInlineTextView
+/* Input Window is a legacy of 20 century, so we want to remove related classes.
+ But unfortunately, Viwer web browser has no support for modern inline input,
+ we need to leave these classes...
+ We will be back to get rid of Input Window after fixing viewer web browser.
+
+ How Input Window should work:
+ 1) Input Window must not be empty.
+ It must close when it become empty result of edithing.
+ 2) Input Window must not close when it still has input data.
+ It must keep open user types next char before commit. by Pell Smit
+*/
+
- (void) setGLView:(LLOpenGLView *)view
{
glview = view;
}
-- (void) insertText:(id)insertString
+- (void)keyDown:(NSEvent *)theEvent
{
- [[self inputContext] discardMarkedText];
- [self setString:@""];
- [_window orderOut:_window];
- [self insertText:insertString replacementRange:NSMakeRange(0, [insertString length])];
+ // mKeyPressed is used later to determine whethere Input Window should close or not
+ mKeyPressed = [[theEvent charactersIgnoringModifiers] characterAtIndex:0];
+ // setMarkedText and insertText is called indirectly from inside keyDown: method
+ [super keyDown:theEvent];
}
-- (void) insertText:(id)aString replacementRange:(NSRange)replacementRange
+// setMarkedText: is called for incomplete input(on the way to conversion).
+- (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange
{
- [glview insertText:aString replacementRange:replacementRange];
+ [super setMarkedText:aString selectedRange:selectedRange replacementRange:replacementRange];
+ if ([aString length] == 0) // this means Input Widow becomes empty
+ {
+ [_window orderOut:_window]; // Close this to avoid empty Input Window
+ }
}
-- (void) insertNewline:(id)sender
+// insertText: is called for inserting commited text.
+// There are two ways to be called here:
+// a) explicitly commited (must close)
+// In case of user typed commit key(usually return key) or delete key or something
+// b) automatically commited (must not close)
+// In case of user typed next letter after conversion
+- (void) insertText:(id)aString replacementRange:(NSRange)replacementRange
{
- [[self textStorage] setValue:@""];
- [[self inputContext] discardMarkedText];
+ [[self inputContext] discardMarkedText];
[self setString:@""];
-}
-
-- (void)doCommandBySelector:(SEL)aSelector
-{
- if (aSelector == @selector(insertNewline:))
- {
- [self insertNewline:self];
- }
+ [glview insertText:aString replacementRange:replacementRange];
+ if (mKeyPressed == NSEnterCharacter ||
+ mKeyPressed == NSBackspaceCharacter ||
+ mKeyPressed == NSTabCharacter ||
+ mKeyPressed == NSNewlineCharacter ||
+ mKeyPressed == NSCarriageReturnCharacter ||
+ mKeyPressed == NSDeleteCharacter ||
+ (mKeyPressed >= 0xF700 && mKeyPressed <= 0xF8FF))
+ {
+ // this is case a) of above comment
+ [_window orderOut:_window]; // to avoid empty Input Window
+ }
}
@end
diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp
index 09b898657c..e50999dc36 100755
--- a/indra/llwindow/llwindowmacosx.cpp
+++ b/indra/llwindow/llwindowmacosx.cpp
@@ -224,7 +224,10 @@ void callFocus()
void callFocusLost()
{
- gWindowImplementation->getCallbacks()->handleFocusLost(gWindowImplementation);
+ if (gWindowImplementation)
+ {
+ gWindowImplementation->getCallbacks()->handleFocusLost(gWindowImplementation);
+ }
}
void callRightMouseDown(float *pos, MASK mask)
@@ -1799,8 +1802,6 @@ static long getDictLong (CFDictionaryRef refDict, CFStringRef key)
void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b)
{
- allowDirectMarkedTextInput(b, mGLView);
-
if (preeditor != mPreeditor && !b)
{
// This condition may occur by a call to
@@ -1830,6 +1831,7 @@ void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b)
return;
}
mLanguageTextInputAllowed = b;
+ allowDirectMarkedTextInput(b, mGLView); // mLanguageTextInputAllowed and mMarkedTextAllowed should be updated at once (by Pell Smit
}
void LLWindowMacOSX::interruptLanguageTextInput()