From c8aa1fb7c8ed44886599ea4e04eed403392e2e34 Mon Sep 17 00:00:00 2001 From: Geenz Date: Mon, 17 Dec 2012 18:00:30 -0500 Subject: LLWindow: Move to using Cocoa for window and view creation along with setting up callbacks for event handling as such. --- indra/llwindow/CMakeLists.txt | 2 + indra/llwindow/llkeyboardmacosx.cpp | 33 +- indra/llwindow/llkeyboardmacosx.h | 9 + indra/llwindow/llopenglview-objc.h | 72 + indra/llwindow/llopenglview-objc.mm | 352 +++++ indra/llwindow/llwindowmacosx-objc.h | 53 +- indra/llwindow/llwindowmacosx-objc.mm | 221 ++- indra/llwindow/llwindowmacosx.cpp | 2632 ++++++--------------------------- indra/llwindow/llwindowmacosx.h | 52 +- 9 files changed, 1214 insertions(+), 2212 deletions(-) create mode 100644 indra/llwindow/llopenglview-objc.h create mode 100644 indra/llwindow/llopenglview-objc.mm (limited to 'indra/llwindow') diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt index 341bddfffd..8a38db751e 100644 --- a/indra/llwindow/CMakeLists.txt +++ b/indra/llwindow/CMakeLists.txt @@ -75,11 +75,13 @@ if (DARWIN) llkeyboardmacosx.cpp llwindowmacosx.cpp llwindowmacosx-objc.mm + llopenglview-objc.mm ) list(APPEND llwindow_HEADER_FILES llkeyboardmacosx.h llwindowmacosx.h llwindowmacosx-objc.h + llopenglview-objc.h ) # We use a bunch of deprecated system APIs. diff --git a/indra/llwindow/llkeyboardmacosx.cpp b/indra/llwindow/llkeyboardmacosx.cpp index 7f8f303517..3f357c600e 100644 --- a/indra/llwindow/llkeyboardmacosx.cpp +++ b/indra/llwindow/llkeyboardmacosx.cpp @@ -30,7 +30,7 @@ #include "llkeyboardmacosx.h" #include "llwindowcallbacks.h" -#include +#include "llwindowmacosx-objc.h" LLKeyboardMacOSX::LLKeyboardMacOSX() { @@ -162,23 +162,23 @@ LLKeyboardMacOSX::LLKeyboardMacOSX() void LLKeyboardMacOSX::resetMaskKeys() { - U32 mask = GetCurrentEventKeyModifiers(); + U32 mask = getModifiers(); // MBW -- XXX -- This mirrors the operation of the Windows version of resetMaskKeys(). // It looks a bit suspicious, as it won't correct for keys that have been released. // Is this the way it's supposed to work? - if(mask & shiftKey) + if(mask & MAC_SHIFT_KEY) { mKeyLevel[KEY_SHIFT] = TRUE; } - if(mask & (controlKey)) + if(mask & (MAC_CTRL_KEY)) { mKeyLevel[KEY_CONTROL] = TRUE; } - if(mask & optionKey) + if(mask & MAC_ALT_KEY) { mKeyLevel[KEY_ALT] = TRUE; } @@ -201,17 +201,17 @@ MASK LLKeyboardMacOSX::updateModifiers(const U32 mask) // translate the mask MASK out_mask = 0; - if(mask & shiftKey) + if(mask & MAC_SHIFT_KEY) { out_mask |= MASK_SHIFT; } - if(mask & (controlKey | cmdKey)) + if(mask & (MAC_CTRL_KEY | MAC_CMD_KEY)) { out_mask |= MASK_CONTROL; } - if(mask & optionKey) + if(mask & MAC_ALT_KEY) { out_mask |= MASK_ALT; } @@ -231,7 +231,12 @@ BOOL LLKeyboardMacOSX::handleKeyDown(const U16 key, const U32 mask) { handled = handleTranslatedKeyDown(translated_key, translated_mask); } - + if (!handled) + { + LL_INFOS("Keyboard") << "Unhandled key: " << mTranslateKeyMap[key] << LL_ENDL; + } else { + LL_INFOS("Keyboard") << "Handled key: " << mTranslateKeyMap[key] << LL_ENDL; + } return handled; } @@ -255,16 +260,16 @@ BOOL LLKeyboardMacOSX::handleKeyUp(const U16 key, const U32 mask) MASK LLKeyboardMacOSX::currentMask(BOOL for_mouse_event) { MASK result = MASK_NONE; - U32 mask = GetCurrentEventKeyModifiers(); + U32 mask = getModifiers(); - if (mask & shiftKey) result |= MASK_SHIFT; - if (mask & controlKey) result |= MASK_CONTROL; - if (mask & optionKey) result |= MASK_ALT; + if (mask & MAC_SHIFT_KEY) result |= MASK_SHIFT; + if (mask & MAC_CTRL_KEY) result |= MASK_CONTROL; + if (mask & MAC_ALT_KEY) result |= MASK_ALT; // For keyboard events, consider Command equivalent to Control if (!for_mouse_event) { - if (mask & cmdKey) result |= MASK_CONTROL; + if (mask & MAC_CMD_KEY) result |= MASK_CONTROL; } return result; diff --git a/indra/llwindow/llkeyboardmacosx.h b/indra/llwindow/llkeyboardmacosx.h index f09ff720ce..6e1f4d3b96 100644 --- a/indra/llwindow/llkeyboardmacosx.h +++ b/indra/llwindow/llkeyboardmacosx.h @@ -29,6 +29,15 @@ #include "llkeyboard.h" +// These more or less mirror their equivalents in NSEvent.h. +enum EMacEventKeys { + MAC_SHIFT_KEY = 1 << 17, + MAC_CTRL_KEY = 1 << 18, + MAC_ALT_KEY = 1 << 19, + MAC_CMD_KEY = 1 << 20, + MAC_FN_KEY = 1 << 23 +}; + class LLKeyboardMacOSX : public LLKeyboard { public: diff --git a/indra/llwindow/llopenglview-objc.h b/indra/llwindow/llopenglview-objc.h new file mode 100644 index 0000000000..8abe81ce9e --- /dev/null +++ b/indra/llwindow/llopenglview-objc.h @@ -0,0 +1,72 @@ +// +// LLOpenGLView.h +// SecondLife +// +// Created by Geenz on 10/2/12. +// +// + +#import +#include "llwindowmacosx-objc.h" + +// Some nasty shovelling of LLOpenGLView from LLNativeBindings to prevent any C++ <-> Obj-C interop oddities. +// Redraw callback handling removed (for now) due to being unneeded in the patch that preceeds this addition. + +@interface LLOpenGLView : NSOpenGLView +{ + NSPoint mousePos; + ResizeCallback mResizeCallback; +} + +- (id) initWithFrame:(NSRect)frame withSamples:(NSUInteger)samples andVsync:(BOOL)vsync; + +// rebuildContext +// Destroys and recreates a context with the view's internal format set via setPixelFormat; +// Use this in event of needing to rebuild a context for whatever reason, without needing to assign a new pixel format. +- (BOOL) rebuildContext; + +// rebuildContextWithFormat +// Destroys and recreates a context with the specified pixel format. +- (BOOL) rebuildContextWithFormat:(NSOpenGLPixelFormat *)format; + +// These are mostly just for C++ <-> Obj-C interop. We can manipulate the CGLContext from C++ without reprecussions. +- (CGLContextObj) getCGLContextObj; +- (CGLPixelFormatObj*)getCGLPixelFormatObj; + +- (void) registerResizeCallback:(ResizeCallback)callback; +@end + +@interface LLNSWindow : NSWindow { + float mMousePos[2]; + unsigned int mModifiers; + + KeyCallback mKeyDownCallback; + KeyCallback mKeyUpCallback; + UnicodeCallback mUnicodeCallback; + ModifierCallback mModifierCallback; + MouseCallback mMouseDownCallback; + MouseCallback mMouseUpCallback; + MouseCallback mMouseDoubleClickCallback; + MouseCallback mRightMouseDownCallback; + MouseCallback mRightMouseUpCallback; + MouseCallback mMouseMovedCallback; + ScrollWheelCallback mScrollWhellCallback; + VoidCallback mMouseExitCallback; + MouseCallback mDeltaUpdateCallback; +} + +- (void) registerKeyDownCallback:(KeyCallback)callback; +- (void) registerKeyUpCallback:(KeyCallback)callback; +- (void) registerUnicodeCallback:(UnicodeCallback)callback; +- (void) registerModifierCallback:(ModifierCallback)callback; +- (void) registerMouseDownCallback:(MouseCallback)callback; +- (void) registerMouseUpCallback:(MouseCallback)callback; +- (void) registerRightMouseDownCallback:(MouseCallback)callback; +- (void) registerRightMouseUpCallback:(MouseCallback)callback; +- (void) registerDoubleClickCallback:(MouseCallback)callback; +- (void) registerMouseMovedCallback:(MouseCallback)callback; +- (void) registerScrollCallback:(ScrollWheelCallback)callback; +- (void) registerMouseExitCallback:(VoidCallback)callback; +- (void) registerDeltaUpdateCallback:(MouseCallback)callback; + +@end \ No newline at end of file diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm new file mode 100644 index 0000000000..a96c4cf82c --- /dev/null +++ b/indra/llwindow/llopenglview-objc.mm @@ -0,0 +1,352 @@ +// +// LLOpenGLView.m +// SecondLife +// +// Created by Geenz on 10/2/12. +// +// + +#import "llopenglview-objc.h" + +@implementation LLOpenGLView + +- (void)viewDidMoveToWindow +{ + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(windowResized:) name:NSWindowDidResizeNotification + object:[self window]]; +} + +- (void)windowResized:(NSNotification *)notification; +{ + NSSize size = [[self window] frame].size; + + mResizeCallback(size.width, size.height); +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [super dealloc]; +} + +- (id) initWithFrame:(NSRect)frame withSamples:(NSUInteger)samples andVsync:(BOOL)vsync +{ + + [self initWithFrame:frame]; + + // Initialize with a default "safe" pixel format that will work with versions dating back to OS X 10.6. + // Any specialized pixel formats, i.e. a core profile pixel format, should be initialized through rebuildContextWithFormat. + // 10.7 and 10.8 don't really care if we're defining a profile or not. If we don't explicitly request a core or legacy profile, it'll always assume a legacy profile (for compatibility reasons). + NSOpenGLPixelFormatAttribute attrs[] = { + NSOpenGLPFANoRecovery, + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAClosestPolicy, + NSOpenGLPFAAccelerated, + NSOpenGLPFASampleBuffers, (samples > 0 ? 1 : 0), + NSOpenGLPFASamples, samples, + NSOpenGLPFAStencilSize, 8, + NSOpenGLPFADepthSize, 24, + NSOpenGLPFAAlphaSize, 8, + NSOpenGLPFAColorSize, 24, + 0 + }; + + NSOpenGLPixelFormat *pixelFormat = [[[NSOpenGLPixelFormat alloc] initWithAttributes:attrs] autorelease]; + + if (pixelFormat == nil) + { + NSLog(@"Failed to create pixel format!", nil); + return nil; + } + + NSOpenGLContext *glContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil]; + + if (glContext == nil) + { + NSLog(@"Failed to create OpenGL context!", nil); + return nil; + } + + [self setPixelFormat:pixelFormat]; + + [self setOpenGLContext:glContext]; + + [glContext setView:self]; + + [glContext makeCurrentContext]; + + if (vsync) + { + [glContext setValues:(const GLint*)1 forParameter:NSOpenGLCPSwapInterval]; + } else { + [glContext setValues:(const GLint*)0 forParameter:NSOpenGLCPSwapInterval]; + } + + return self; +} + +- (BOOL) rebuildContext +{ + return [self rebuildContextWithFormat:[self pixelFormat]]; +} + +- (BOOL) rebuildContextWithFormat:(NSOpenGLPixelFormat *)format +{ + NSOpenGLContext *ctx = [self openGLContext]; + + [ctx clearDrawable]; + [ctx initWithFormat:format shareContext:nil]; + + if (ctx == nil) + { + NSLog(@"Failed to create OpenGL context!", nil); + return false; + } + + [self setOpenGLContext:ctx]; + [ctx setView:self]; + [ctx makeCurrentContext]; + return true; +} + +- (CGLContextObj)getCGLContextObj +{ + NSOpenGLContext *ctx = [self openGLContext]; + return (CGLContextObj)[ctx CGLContextObj]; +} + +- (CGLPixelFormatObj*)getCGLPixelFormatObj +{ + NSOpenGLPixelFormat *fmt = [self pixelFormat]; + return (CGLPixelFormatObj*)[fmt CGLPixelFormatObj]; +} + +- (void) registerResizeCallback:(ResizeCallback)callback +{ + mResizeCallback = callback; +} + +// Various events can be intercepted by our view, thus not reaching our window. +// Intercept these events, and pass them to the window as needed. - Geenz + +- (void) mouseDragged:(NSEvent *)theEvent +{ + [super mouseDragged:theEvent]; +} + +- (void) scrollWheel:(NSEvent *)theEvent +{ + [super scrollWheel:theEvent]; +} + +- (void) mouseDown:(NSEvent *)theEvent +{ + [super mouseDown:theEvent]; +} + +- (void) mouseUp:(NSEvent *)theEvent +{ + [super mouseUp:theEvent]; +} + +- (void) rightMouseDown:(NSEvent *)theEvent +{ + [super rightMouseDown:theEvent]; +} + +- (void) rightMouseUp:(NSEvent *)theEvent +{ + [super rightMouseUp:theEvent]; +} + +- (void) keyUp:(NSEvent *)theEvent +{ + [super keyUp:theEvent]; +} + +- (void) keyDown:(NSEvent *)theEvent +{ + [super keyDown:theEvent]; +} + +- (void) mouseMoved:(NSEvent *)theEvent +{ + [super mouseMoved:theEvent]; +} + +- (void) flagsChanged:(NSEvent *)theEvent +{ + [super flagsChanged:theEvent]; +} + +@end + +// We use a custom NSWindow for our event handling. +// Why not an NSWindowController you may ask? +// Answer: this is easier. + +@implementation LLNSWindow + +- (id) init +{ + return self; +} + +- (void) keyDown:(NSEvent *)theEvent { + mKeyDownCallback([theEvent keyCode], [theEvent modifierFlags]); + + NSString *chars = [theEvent charactersIgnoringModifiers]; + for (uint i = 0; i < [chars length]; i++) + { + mUnicodeCallback([chars characterAtIndex:i], [theEvent modifierFlags]); + } + + // The viewer expects return to be submitted separately as a unicode character. + if ([theEvent keyCode] == 3 || [theEvent keyCode] == 13) + { + mUnicodeCallback([theEvent keyCode], [theEvent modifierFlags]); + } +} + +- (void) keyUp:(NSEvent *)theEvent { + mKeyUpCallback([theEvent keyCode], [theEvent modifierFlags]); +} + +- (void)flagsChanged:(NSEvent *)theEvent { + mModifiers = [theEvent modifierFlags]; +} + +- (void) mouseDown:(NSEvent *)theEvent +{ + if ([theEvent clickCount] == 2) + { + mMouseDoubleClickCallback(mMousePos, [theEvent modifierFlags]); + } else if ([theEvent clickCount] == 1) { + mMouseDownCallback(mMousePos, [theEvent modifierFlags]); + } +} + +- (void) mouseUp:(NSEvent *)theEvent +{ + mMouseUpCallback(mMousePos, [theEvent modifierFlags]); +} + +- (void) rightMouseDown:(NSEvent *)theEvent +{ + mRightMouseDownCallback(mMousePos, [theEvent modifierFlags]); +} + +- (void) rightMouseUp:(NSEvent *)theEvent +{ + mRightMouseUpCallback(mMousePos, [theEvent modifierFlags]); +} + +- (void)mouseMoved:(NSEvent *)theEvent { + float mouseDeltas[2] = { + [theEvent deltaX], + [theEvent deltaZ] + }; + + mDeltaUpdateCallback(mouseDeltas, 0); + + NSPoint mPoint = [theEvent locationInWindow]; + mMousePos[0] = mPoint.x; + mMousePos[1] = mPoint.y; + mMouseMovedCallback(mMousePos, 0); +} + +// NSWindow doesn't trigger mouseMoved when the mouse is being clicked and dragged. +// Use mouseDragged for situations like this to trigger our movement callback instead. + +- (void) mouseDragged:(NSEvent *)theEvent +{ + float mouseDeltas[2] = { + [theEvent deltaX], + [theEvent deltaZ] + }; + + mDeltaUpdateCallback(mouseDeltas, 0); + + NSPoint mPoint = [theEvent locationInWindow]; + mMousePos[0] = mPoint.x; + mMousePos[1] = mPoint.y; + mMouseMovedCallback(mMousePos, 0); +} + +- (void) scrollWheel:(NSEvent *)theEvent +{ + mScrollWhellCallback(-[theEvent deltaY]); +} + +- (void) mouseExited:(NSEvent *)theEvent +{ + mMouseExitCallback(); +} + +- (void) registerKeyDownCallback:(KeyCallback)callback +{ + mKeyDownCallback = callback; +} + +- (void) registerKeyUpCallback:(KeyCallback)callback +{ + mKeyUpCallback = callback; +} + +- (void) registerUnicodeCallback:(UnicodeCallback)callback +{ + mUnicodeCallback = callback; +} + +- (void) registerModifierCallback:(ModifierCallback)callback +{ + mModifierCallback = callback; +} + +- (void) registerMouseDownCallback:(MouseCallback)callback +{ + mMouseDownCallback = callback; +} + +- (void) registerMouseUpCallback:(MouseCallback)callback +{ + mMouseUpCallback = callback; +} + +- (void) registerRightMouseDownCallback:(MouseCallback)callback +{ + mRightMouseDownCallback = callback; +} + +- (void) registerRightMouseUpCallback:(MouseCallback)callback +{ + mRightMouseUpCallback = callback; +} + +- (void) registerDoubleClickCallback:(MouseCallback)callback +{ + mMouseDoubleClickCallback = callback; +} + +- (void) registerMouseMovedCallback:(MouseCallback)callback +{ + mMouseMovedCallback = callback; +} + +- (void) registerScrollCallback:(ScrollWheelCallback)callback +{ + mScrollWhellCallback = callback; +} + +- (void) registerMouseExitCallback:(VoidCallback)callback +{ + mMouseExitCallback = callback; +} + +- (void) registerDeltaUpdateCallback:(MouseCallback)callback +{ + mDeltaUpdateCallback = callback; +} + +@end \ No newline at end of file diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index 7893dedda4..47ae13cb25 100644 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -24,14 +24,61 @@ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ - +#include +typedef std::tr1::function KeyCallback; +typedef std::tr1::function ModifierCallback; +typedef std::tr1::function MouseCallback; +typedef std::tr1::function UnicodeCallback; +typedef std::tr1::function ResizeCallback; +typedef std::tr1::function ScrollWheelCallback; +typedef std::tr1::function VoidCallback; // This will actually hold an NSCursor*, but that type is only available in objective C. typedef void *CursorRef; +typedef void *NSWindowRef; +typedef void *GLViewRef; /* Defined in llwindowmacosx-objc.mm: */ void setupCocoa(); CursorRef createImageCursor(const char *fullpath, int hotspotX, int hotspotY); -OSErr releaseImageCursor(CursorRef ref); -OSErr setImageCursor(CursorRef ref); +short releaseImageCursor(CursorRef ref); +short setImageCursor(CursorRef ref); +void setArrowCursor(); +void setIBeamCursor(); +void setPointingHandCursor(); +void setCopyCursor(); +void setCrossCursor(); +void hideNSCursor(); +void showNSCursor(); +void hideNSCursorTillMove(bool hide); + +NSWindowRef createNSWindow(int x, int y, int width, int height); + +#include +GLViewRef createOpenGLView(NSWindowRef window); +void glSwapBuffers(void* context); +CGLContextObj getCGLContextObj(NSWindowRef window); +void getContentViewBounds(NSWindowRef window, float* bounds); +void getWindowSize(NSWindowRef window, float* size); +void setWindowSize(NSWindowRef window, int width, int height); +void getCursorPos(NSWindowRef window, float* pos); +void makeWindowOrderFront(NSWindowRef window); +void convertScreenToWindow(NSWindowRef window, float *coord); +void convertWindowToScreen(NSWindowRef window, float *coord); +void setWindowPos(NSWindowRef window, float* pos); + +void registerKeyUpCallback(NSWindowRef window, KeyCallback callback); +void registerKeyDownCallback(NSWindowRef window, KeyCallback callback); +void registerUnicodeCallback(NSWindowRef window, UnicodeCallback callback); +void registerMouseUpCallback(NSWindowRef window, MouseCallback callback); +void registerMouseDownCallback(NSWindowRef window, MouseCallback callback); +void registerRightMouseUpCallback(NSWindowRef window, MouseCallback callback); +void registerRightMouseDownCallback(NSWindowRef window, MouseCallback callback); +void registerDoubleClickCallback(NSWindowRef window, MouseCallback callback); +void registerResizeEventCallback(GLViewRef window, ResizeCallback callback); +void registerMouseMovedCallback(NSWindowRef window, MouseCallback callback); +void registerScrollCallback(NSWindowRef window, ScrollWheelCallback callback); +void registerMouseExitCallback(NSWindowRef window, VoidCallback callback); +void registerDeltaUpdateCallback(NSWindowRef window, MouseCallback callback); +unsigned int getModifiers(); diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index bebb537cd8..03c0f55883 100644 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -26,6 +26,9 @@ */ #include +#include +#include "llwindowmacosx-objc.h" +#include "llopenglview-objc.h" /* * These functions are broken out into a separate file because the @@ -34,8 +37,6 @@ * linden headers with any objective-C++ source. */ -#include "llwindowmacosx-objc.h" - void setupCocoa() { static bool inited = false; @@ -83,6 +84,51 @@ CursorRef createImageCursor(const char *fullpath, int hotspotX, int hotspotY) return (CursorRef)cursor; } +void setArrowCursor() +{ + NSCursor *cursor = [NSCursor arrowCursor]; + [cursor set]; +} + +void setIBeamCursor() +{ + NSCursor *cursor = [NSCursor IBeamCursor]; + [cursor set]; +} + +void setPointingHandCursor() +{ + NSCursor *cursor = [NSCursor pointingHandCursor]; + [cursor set]; +} + +void setCopyCursor() +{ + NSCursor *cursor = [NSCursor dragCopyCursor]; + [cursor set]; +} + +void setCrossCursor() +{ + NSCursor *cursor = [NSCursor crosshairCursor]; + [cursor set]; +} + +void hideNSCursor() +{ + [NSCursor hide]; +} + +void showNSCursor() +{ + [NSCursor unhide]; +} + +void hideNSCursorTillMove(bool hide) +{ + [NSCursor setHiddenUntilMouseMoves:hide]; +} + // This is currently unused, since we want all our cursors to persist for the life of the app, but I've included it for completeness. OSErr releaseImageCursor(CursorRef ref) { @@ -118,3 +164,174 @@ OSErr setImageCursor(CursorRef ref) return noErr; } +// Now for some unholy juggling between generic pointers and casting them to Obj-C objects! +// Note: things can get a bit hairy from here. This is not for the faint of heart. + +NSWindowRef createNSWindow(int x, int y, int width, int height) +{ + LLNSWindow *window = [[LLNSWindow alloc]initWithContentRect:NSMakeRect(x, y, width, height) + styleMask:NSTitledWindowMask | NSResizableWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSTexturedBackgroundWindowMask backing:NSBackingStoreBuffered defer:NO]; + [window makeKeyAndOrderFront:nil]; + [window setAcceptsMouseMovedEvents:TRUE]; + return window; +} + +GLViewRef createOpenGLView(NSWindowRef window) +{ + LLOpenGLView *glview = [[LLOpenGLView alloc]initWithFrame:[(LLNSWindow*)window frame] withSamples:0 andVsync:FALSE]; + [(LLNSWindow*)window setContentView:glview]; + return glview; +} + +void glSwapBuffers(void* context) +{ + [(NSOpenGLContext*)context flushBuffer]; +} + +CGLContextObj getCGLContextObj(NSWindowRef window) +{ + LLOpenGLView *glview = [(LLNSWindow*)window contentView]; + return [glview getCGLContextObj]; +} + +CGLPixelFormatObj* getCGLPixelFormatObj(NSWindowRef window) +{ + LLOpenGLView *glview = [(LLNSWindow*)window contentView]; + return [glview getCGLPixelFormatObj]; +} + +void getContentViewBounds(NSWindowRef window, float* bounds) +{ + bounds[0] = [[(LLNSWindow*)window contentView] bounds].origin.x; + bounds[1] = [[(LLNSWindow*)window contentView] bounds].origin.y; + bounds[2] = [[(LLNSWindow*)window contentView] bounds].size.width; + bounds[3] = [[(LLNSWindow*)window contentView] bounds].size.height; +} + +void getWindowSize(NSWindowRef window, float* size) +{ + NSRect frame = [(LLNSWindow*)window frame]; + size[0] = frame.origin.x; + size[1] = frame.origin.y; + size[2] = frame.size.width; + size[3] = frame.size.height; +} + +void setWindowSize(NSWindowRef window, int width, int height) +{ + NSRect frame = [(LLNSWindow*)window frame]; + frame.size.width = width; + frame.size.height = height; + [(LLNSWindow*)window setFrame:frame display:TRUE]; +} + +void setWindowPos(NSWindowRef window, float* pos) +{ + NSPoint point; + point.x = pos[0]; + point.y = pos[1]; + [(LLNSWindow*)window setFrameOrigin:point]; +} + +void getCursorPos(NSWindowRef window, float* pos) +{ + NSPoint mLoc; + mLoc = [(LLNSWindow*)window mouseLocationOutsideOfEventStream]; + pos[0] = mLoc.x; + pos[1] = mLoc.y; +} + +void makeWindowOrderFront(NSWindowRef window) +{ + [(LLNSWindow*)window makeKeyAndOrderFront:nil]; +} + +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; +} + +void convertWindowToScreen(NSWindowRef window, float *coord) +{ + NSPoint point; + point.x = coord[0]; + point.y = coord[1]; + point = [(LLNSWindow*)window convertBaseToScreen:point]; + coord[0] = point.x; + coord[1] = point.y; +} + +void registerKeyUpCallback(NSWindowRef window, std::tr1::function callback) +{ + [(LLNSWindow*)window registerKeyUpCallback:callback]; +} + +void registerKeyDownCallback(NSWindowRef window, std::tr1::function callback) +{ + [(LLNSWindow*)window registerKeyDownCallback:callback]; +} + +void registerUnicodeCallback(NSWindowRef window, std::tr1::function callback) +{ + [(LLNSWindow*)window registerUnicodeCallback:callback]; +} + +void registerMouseUpCallback(NSWindowRef window, MouseCallback callback) +{ + [(LLNSWindow*)window registerMouseUpCallback:callback]; +} + +void registerMouseDownCallback(NSWindowRef window, MouseCallback callback) +{ + [(LLNSWindow*)window registerMouseDownCallback:callback]; +} + +void registerRightMouseUpCallback(NSWindowRef window, MouseCallback callback) +{ + [(LLNSWindow*)window registerRightMouseUpCallback:callback]; +} + +void registerRightMouseDownCallback(NSWindowRef window, MouseCallback callback) +{ + [(LLNSWindow*)window registerRightMouseDownCallback:callback]; +} + +void registerDoubleClickCallback(NSWindowRef window, MouseCallback callback) +{ + [(LLNSWindow*)window registerDoubleClickCallback:callback]; +} + +void registerResizeEventCallback(GLViewRef glview, ResizeCallback callback) +{ + [(LLOpenGLView*)glview registerResizeCallback:callback]; +} + +void registerMouseMovedCallback(NSWindowRef window, MouseCallback callback) +{ + [(LLNSWindow*)window registerMouseMovedCallback:callback]; +} + +void registerScrollCallback(NSWindowRef window, ScrollWheelCallback callback) +{ + [(LLNSWindow*)window registerScrollCallback:callback]; +} + +void registerMouseExitCallback(NSWindowRef window, VoidCallback callback) +{ + [(LLNSWindow*)window registerMouseExitCallback:callback]; +} + +void registerDeltaUpdateCallback(NSWindowRef window, MouseCallback callback) +{ + [(LLNSWindow*)window registerDeltaUpdateCallback:callback]; +} + +unsigned int getModifiers() +{ + return [NSEvent modifierFlags]; +} diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 97637c937f..1fb8bea802 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -30,7 +30,6 @@ #include "llkeyboardmacosx.h" #include "llwindowcallbacks.h" -#include "llwindowmacosx-objc.h" #include "llpreeditor.h" #include "llerror.h" @@ -58,7 +57,6 @@ const S32 MAX_NUM_RESOLUTIONS = 32; // BOOL LLWindowMacOSX::sUseMultGL = FALSE; -WindowRef LLWindowMacOSX::sMediaWindow = NULL; // Cross-platform bits: @@ -98,105 +96,9 @@ BOOL check_for_card(const char* RENDERER, const char* bad_card) // We may want to base this on the setting of _DEBUG... #define CAPTURE_ALL_DISPLAYS 0 -static double getDictDouble (CFDictionaryRef refDict, CFStringRef key); +//static double getDictDouble (CFDictionaryRef refDict, CFStringRef key); static long getDictLong (CFDictionaryRef refDict, CFStringRef key); - - - -// CarbonEvents we're interested in. -static EventTypeSpec WindowHandlerEventList[] = -{ - // Window-related events - { kEventClassWindow, kEventWindowActivated }, - { kEventClassWindow, kEventWindowDeactivated }, - { kEventClassWindow, kEventWindowShown }, - { kEventClassWindow, kEventWindowHidden }, - { kEventClassWindow, kEventWindowCollapsed }, - { kEventClassWindow, kEventWindowExpanded }, - { kEventClassWindow, kEventWindowGetClickActivation }, - { kEventClassWindow, kEventWindowClose }, - { kEventClassWindow, kEventWindowBoundsChanging }, - { kEventClassWindow, kEventWindowBoundsChanged }, - { kEventClassWindow, kEventWindowGetIdealSize }, - - // Mouse events - { kEventClassMouse, kEventMouseDown }, - { kEventClassMouse, kEventMouseUp }, - { kEventClassMouse, kEventMouseDragged }, - { kEventClassMouse, kEventMouseWheelMoved }, - { kEventClassMouse, kEventMouseMoved }, - - // Keyboard events - // No longer handle raw key down events directly. - // When text input events come in, extract the raw key events from them and process at that point. - // This allows input methods to eat keystrokes the way they're supposed to. -// { kEventClassKeyboard, kEventRawKeyDown }, -// { kEventClassKeyboard, kEventRawKeyRepeat }, - { kEventClassKeyboard, kEventRawKeyUp }, - { kEventClassKeyboard, kEventRawKeyModifiersChanged }, - - // Text input events - { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent }, - { kEventClassTextInput, kEventTextInputUpdateActiveInputArea }, - { kEventClassTextInput, kEventTextInputOffsetToPos }, - { kEventClassTextInput, kEventTextInputPosToOffset }, - { kEventClassTextInput, kEventTextInputShowHideBottomWindow }, - { kEventClassTextInput, kEventTextInputGetSelectedText }, - { kEventClassTextInput, kEventTextInputFilterText }, - - // TSM Document Access events (advanced input method support) - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetLength }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetSelectedRange }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetCharacters }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetFont }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetGlyphInfo }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessLockDocument }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessUnlockDocument } -}; - -static EventTypeSpec GlobalHandlerEventList[] = -{ - // Mouse events - { kEventClassMouse, kEventMouseDown }, - { kEventClassMouse, kEventMouseUp }, - { kEventClassMouse, kEventMouseDragged }, - { kEventClassMouse, kEventMouseWheelMoved }, - { kEventClassMouse, kEventMouseMoved }, - - // Keyboard events - // No longer handle raw key down events directly. - // When text input events come in, extract the raw key events from them and process at that point. - // This allows input methods to eat keystrokes the way they're supposed to. -// { kEventClassKeyboard, kEventRawKeyDown }, -// { kEventClassKeyboard, kEventRawKeyRepeat }, - { kEventClassKeyboard, kEventRawKeyUp }, - { kEventClassKeyboard, kEventRawKeyModifiersChanged }, - - // Text input events - { kEventClassTextInput, kEventTextInputUpdateActiveInputArea }, - { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent }, - { kEventClassTextInput, kEventTextInputOffsetToPos }, - { kEventClassTextInput, kEventTextInputPosToOffset }, - { kEventClassTextInput, kEventTextInputShowHideBottomWindow }, - { kEventClassTextInput, kEventTextInputGetSelectedText }, - { kEventClassTextInput, kEventTextInputFilterText }, - - // TSM Document Access events (advanced input method support) - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetLength }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetSelectedRange }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetCharacters }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetFont }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessGetGlyphInfo }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessLockDocument }, - { kEventClassTSMDocumentAccess, kEventTSMDocumentAccessUnlockDocument } -}; - -static EventTypeSpec CommandHandlerEventList[] = -{ - { kEventClassCommand, kEventCommandProcess } -}; - // MBW -- HACK ALERT // On the Mac, to put up an OS dialog in full screen mode, we must first switch OUT of full screen mode. // The proper way to do this is to bracket the dialog with calls to beforeDialog() and afterDialog(), but these @@ -204,8 +106,6 @@ static EventTypeSpec CommandHandlerEventList[] = // This assumes that there will be only one object of this class at any time. Hopefully this is true. static LLWindowMacOSX *gWindowImplementation = NULL; - - LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, U32 flags, @@ -233,8 +133,6 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks, mContext = NULL; mPixelFormat = NULL; mDisplay = CGMainDisplayID(); - mOldDisplayMode = NULL; - mTimer = NULL; mSimulatedRightClick = FALSE; mLastModifiers = 0; mHandsOffEvents = FALSE; @@ -246,12 +144,8 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks, mOverrideAspectRatio = 0.f; mMaximized = FALSE; mMinimized = FALSE; - mTSMDocument = NULL; // Just in case. mLanguageTextInputAllowed = FALSE; - mTSMScriptCode = 0; - mTSMLangCode = 0; mPreeditor = NULL; - mRawKeyEvent = NULL; mFSAASamples = fsaa_samples; mForceRebuild = FALSE; @@ -263,43 +157,23 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks, mOriginalAspectRatio = (double)CGDisplayPixelsWide(mDisplay) / (double)CGDisplayPixelsHigh(mDisplay); // Stash the window title - strcpy((char*)mWindowTitle + 1, title.c_str()); /* Flawfinder: ignore */ - mWindowTitle[0] = title.length(); - - mEventHandlerUPP = NewEventHandlerUPP(staticEventHandler); - mMoveEventCampartorUPP = NewEventComparatorUPP(staticMoveEventComparator); - mGlobalHandlerRef = NULL; - mWindowHandlerRef = NULL; + mWindowTitle = title; + //mWindowTitle[0] = title.length(); mDragOverrideCursor = -1; - // We're not clipping yet - SetRect( &mOldMouseClip, 0, 0, 0, 0 ); - // Set up global event handlers (the fullscreen case needs this) - InstallStandardEventHandler(GetApplicationEventTarget()); + //InstallStandardEventHandler(GetApplicationEventTarget()); // Stash an object pointer for OSMessageBox() gWindowImplementation = this; - // Create the GL context and set it up for windowed or fullscreen, as appropriate. + LL_INFOS("Window") << "Creating context..." << LL_ENDL; if(createContext(x, y, width, height, 32, fullscreen, disable_vsync)) { if(mWindow != NULL) { - // MBW -- XXX -- I think we can now do this here? - // Constrain the window to the screen it's mostly on, resizing if necessary. - ConstrainWindowToScreen( - mWindow, - kWindowStructureRgn, - kWindowConstrainMayResize | - // kWindowConstrainStandardOptions | - 0, - NULL, - NULL); - - MacShowWindow(mWindow); - BringToFront(mWindow); + makeWindowOrderFront(mWindow); } if (!gGLManager.initGL()) @@ -321,463 +195,193 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks, mCallbacks = callbacks; stop_glerror(); + + } -BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL disable_vsync) -{ - OSStatus err; - BOOL glNeedsInit = FALSE; - - if(mGlobalHandlerRef == NULL) - { - InstallApplicationEventHandler(mEventHandlerUPP, GetEventTypeCount (CommandHandlerEventList), CommandHandlerEventList, (void*)this, &mGlobalHandlerRef); - } - - mFullscreen = fullscreen; - - if (mFullscreen && (mOldDisplayMode == NULL)) - { - LL_INFOS("Window") << "createContext: setting up fullscreen " << width << "x" << height << LL_ENDL; - - // NOTE: The refresh rate will be REPORTED AS 0 for many DVI and notebook displays. Plan accordingly. - double refresh = getDictDouble (CGDisplayCurrentMode (mDisplay), kCGDisplayRefreshRate); +// These functions are used as callbacks for event handling within Cocoa. +// It's a good idea to wrap these to avoid reworking more code than we need to within LLWindow. - // If the requested width or height is 0, find the best default for the monitor. - if((width == 0) || (height == 0)) - { - // Scan through the list of modes, looking for one which has: - // height between 700 and 800 - // aspect ratio closest to the user's original mode - S32 resolutionCount = 0; - LLWindowResolution *resolutionList = getSupportedResolutions(resolutionCount); +void callKeyUp(unsigned short key, unsigned int mask) +{ + gKeyboard->handleKeyUp(key, mask); +} - if(resolutionList != NULL) - { - F32 closestAspect = 0; - U32 closestHeight = 0; - U32 closestWidth = 0; - int i; +void callKeyDown(unsigned short key, unsigned int mask) +{ + gKeyboard->handleKeyDown(key, mask); +} - LL_DEBUGS("Window") << "createContext: searching for a display mode, original aspect is " << mOriginalAspectRatio << LL_ENDL; +void callUnicodeCallback(wchar_t character, unsigned int mask) +{ + gWindowImplementation->getCallbacks()->handleUnicodeChar(character, mask); +} - for(i=0; i < resolutionCount; i++) - { - F32 aspect = (F32)resolutionList[i].mWidth / (F32)resolutionList[i].mHeight; +void callModifierCallback(unsigned int mask) +{ + +} - LL_DEBUGS("Window") << "createContext: width " << resolutionList[i].mWidth << " height " << resolutionList[i].mHeight << " aspect " << aspect << LL_ENDL; +void callRightMouseDown(float *pos, MASK mask) +{ + LLCoordGL outCoords; + outCoords.mX = llround(pos[0]); + outCoords.mY = llround(pos[1]); + gWindowImplementation->getCallbacks()->handleRightMouseDown(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); +} - if( (resolutionList[i].mHeight >= 700) && (resolutionList[i].mHeight <= 800) && - (fabs(aspect - mOriginalAspectRatio) < fabs(closestAspect - mOriginalAspectRatio))) - { - LL_DEBUGS("Window") << " (new closest mode) " << LL_ENDL; +void callRightMouseUp(float *pos, MASK mask) +{ + LLCoordGL outCoords; + outCoords.mX = llround(pos[0]); + outCoords.mY = llround(pos[1]); + gWindowImplementation->getCallbacks()->handleRightMouseUp(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); +} - // This is the closest mode we've seen yet. - closestWidth = resolutionList[i].mWidth; - closestHeight = resolutionList[i].mHeight; - closestAspect = aspect; - } - } +void callLeftMouseDown(float *pos, MASK mask) +{ + LLCoordGL outCoords; + outCoords.mX = llround(pos[0]); + outCoords.mY = llround(pos[1]); + gWindowImplementation->getCallbacks()->handleMouseDown(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); + LL_INFOS("Window") << outCoords.mX << ", " << outCoords.mY << LL_ENDL; +} - width = closestWidth; - height = closestHeight; - } - } +void callLeftMouseUp(float *pos, MASK mask) +{ + LLCoordGL outCoords; + outCoords.mX = llround(pos[0]); + outCoords.mY = llround(pos[1]); + gWindowImplementation->getCallbacks()->handleMouseUp(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); + +} - if((width == 0) || (height == 0)) - { - // Mode search failed for some reason. Use the old-school default. - width = 1024; - height = 768; - } +void callDoubleClick(float *pos, MASK mask) +{ + LLCoordGL outCoords; + outCoords.mX = llround(pos[0]); + outCoords.mY = llround(pos[1]); + gWindowImplementation->getCallbacks()->handleDoubleClick(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); +} - if (true) - { - // Fullscreen support - CFDictionaryRef refDisplayMode = 0; - boolean_t exactMatch = false; - -#if CAPTURE_ALL_DISPLAYS - // Capture all displays (may want to do this for final build) - CGCaptureAllDisplays (); -#else - // Capture only the main display (useful for debugging) - CGDisplayCapture (mDisplay); -#endif +void callResize(unsigned int width, unsigned int height) +{ + gWindowImplementation->getCallbacks()->handleResize(gWindowImplementation, width, height); +} - // Switch the display to the desired resolution and refresh - refDisplayMode = CGDisplayBestModeForParametersAndRefreshRate( - mDisplay, - BITS_PER_PIXEL, - width, - height, - refresh, - &exactMatch); +void callMouseMoved(float *pos, MASK mask) +{ + LLCoordGL outCoords; + outCoords.mX = llround(pos[0]); + outCoords.mY = llround(pos[1]); + float deltas[2]; + gWindowImplementation->getMouseDeltas(deltas); + outCoords.mX += deltas[0]; + outCoords.mY += deltas[1]; + gWindowImplementation->getCallbacks()->handleMouseMove(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); +} - if (refDisplayMode) - { - LL_DEBUGS("Window") << "createContext: switching display resolution" << LL_ENDL; - mOldDisplayMode = CGDisplayCurrentMode (mDisplay); - CGDisplaySwitchToMode (mDisplay, refDisplayMode); - // CFRelease(refDisplayMode); +void callScrollMoved(float delta) +{ + gWindowImplementation->getCallbacks()->handleScrollWheel(gWindowImplementation, delta); +} - AddEventTypesToHandler(mGlobalHandlerRef, GetEventTypeCount (GlobalHandlerEventList), GlobalHandlerEventList); - } +void callMouseExit() +{ + gWindowImplementation->getCallbacks()->handleMouseLeave(gWindowImplementation); +} +void callWindowFocus() +{ + gWindowImplementation->getCallbacks()->handleFocus(gWindowImplementation); +} - mFullscreen = TRUE; - mFullscreenWidth = CGDisplayPixelsWide(mDisplay); - mFullscreenHeight = CGDisplayPixelsHigh(mDisplay); - mFullscreenBits = CGDisplayBitsPerPixel(mDisplay); - mFullscreenRefresh = llround(getDictDouble (CGDisplayCurrentMode (mDisplay), kCGDisplayRefreshRate)); +void callWindowUnfocus() +{ + gWindowImplementation->getCallbacks()->handleFocusLost(gWindowImplementation); +} - LL_INFOS("Window") << "Running at " << mFullscreenWidth - << "x" << mFullscreenHeight - << "x" << mFullscreenBits - << " @ " << mFullscreenRefresh - << LL_ENDL; - } - else - { - // No fullscreen support - mFullscreen = FALSE; - mFullscreenWidth = -1; - mFullscreenHeight = -1; - mFullscreenBits = -1; - mFullscreenRefresh = -1; - - std::string error= llformat("Unable to run fullscreen at %d x %d.\nRunning in window.", width, height); - OSMessageBox(error, "Error", OSMB_OK); - } - } +void callDeltaUpdate(float *delta, MASK mask) +{ + gWindowImplementation->updateMouseDeltas(); +} - if(!mFullscreen && (mWindow == NULL)) +void LLWindowMacOSX::updateMouseDeltas() +{ + if (mCursorDecoupled) { - //int displayWidth = CGDisplayPixelsWide(mDisplay); - //int displayHeight = CGDisplayPixelsHigh(mDisplay); - //const int menuBarPlusTitleBar = 44; // Ugly magic number. - - LL_DEBUGS("Window") << "createContext: creating window" << LL_ENDL; - - mPreviousWindowRect.left = (long) x; - mPreviousWindowRect.right = (long) x + width; - mPreviousWindowRect.top = (long) y; - mPreviousWindowRect.bottom = (long) y + height; - - //----------------------------------------------------------------------- - // Create the window - //----------------------------------------------------------------------- - mWindow = NewCWindow( - NULL, - &mPreviousWindowRect, - mWindowTitle, - false, // Create the window invisible. Whoever calls createContext() should show it after any moving/resizing. - // noGrowDocProc, // Window with no grow box and no zoom box - zoomDocProc, // Window with a grow box and a zoom box - // zoomNoGrow, // Window with a zoom box but no grow box - kFirstWindowOfClass, - true, - (long)this); - - if (!mWindow) + CGMouseDelta x, y; + CGGetLastMouseDelta( &x, &y ); + mCursorLastEventDeltaX = x; + mCursorLastEventDeltaY = y; + + if (mCursorIgnoreNextDelta) { - setupFailure("Window creation error", "Error", OSMB_OK); - return FALSE; + mCursorLastEventDeltaX = 0; + mCursorLastEventDeltaY = 0; + mCursorIgnoreNextDelta = FALSE; } + } else { + mCursorLastEventDeltaX = 0; + mCursorLastEventDeltaY = 0; + } +} - // Turn on live resize. - // For this to work correctly, we need to be able to call LLViewerWindow::draw from - // the event handler for kEventWindowBoundsChanged. It's not clear that we have access from here. - // err = ChangeWindowAttributes(mWindow, kWindowLiveResizeAttribute, 0); +void LLWindowMacOSX::getMouseDeltas(float* delta) +{ + delta[0] = mCursorLastEventDeltaX; + delta[1] = mCursorLastEventDeltaY; +} - // Set up window event handlers (some window-related events ONLY go to window handlers.) - InstallStandardEventHandler(GetWindowEventTarget(mWindow)); - InstallWindowEventHandler(mWindow, mEventHandlerUPP, GetEventTypeCount (WindowHandlerEventList), WindowHandlerEventList, (void*)this, &mWindowHandlerRef); // add event handler -#if LL_OS_DRAGDROP_ENABLED - InstallTrackingHandler( dragTrackingHandler, mWindow, (void*)this ); - InstallReceiveHandler( dragReceiveHandler, mWindow, (void*)this ); -#endif // LL_OS_DRAGDROP_ENABLED - } +BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL disable_vsync) +{ + BOOL glNeedsInit = FALSE; - { - // Create and initialize our TSM document for language text input. - // If an error occured, we can do nothing better than simply ignore it. - // mTSMDocument will be kept NULL in case. - if (mTSMDocument) - { - DeactivateTSMDocument(mTSMDocument); - DeleteTSMDocument(mTSMDocument); - mTSMDocument = NULL; - } - static InterfaceTypeList types = { kUnicodeDocument }; - err = NewTSMDocument(1, types, &mTSMDocument, 0); - if (err != noErr) - { - LL_WARNS("Window") << "createContext: couldn't create a TSMDocument (" << err << ")" << LL_ENDL; - } - if (mTSMDocument) - { - ActivateTSMDocument(mTSMDocument); - allowLanguageTextInput(NULL, FALSE); - } + mFullscreen = fullscreen; + + if (mWindow == NULL) + { + LL_INFOS("Window") << "Creating window..." << LL_ENDL; + mWindow = createNSWindow(x, y, width, height); + LL_INFOS("Window") << "Registering key callbacks..." << LL_ENDL; + registerKeyDownCallback(mWindow, callKeyDown); + registerKeyUpCallback(mWindow, callKeyUp); + registerUnicodeCallback(mWindow, callUnicodeCallback); + registerMouseDownCallback(mWindow, callLeftMouseDown); + registerMouseUpCallback(mWindow, callLeftMouseUp); + registerRightMouseDownCallback(mWindow, callRightMouseDown); + registerRightMouseUpCallback(mWindow, callRightMouseUp); + registerDoubleClickCallback(mWindow, callDoubleClick); + registerMouseMovedCallback(mWindow, callMouseMoved); + registerScrollCallback(mWindow, callScrollMoved); + registerDeltaUpdateCallback(mWindow, callDeltaUpdate); + registerMouseExitCallback(mWindow, callMouseExit); } if(mContext == NULL) { - AGLRendererInfo rendererInfo = NULL; - - //----------------------------------------------------------------------- - // Create GL drawing context - //----------------------------------------------------------------------- - - if(mPixelFormat == NULL) - { - if(mFullscreen) - { - GLint fullscreenAttrib[] = - { - AGL_RGBA, - AGL_FULLSCREEN, - AGL_NO_RECOVERY, - AGL_SAMPLE_BUFFERS_ARB, mFSAASamples > 0 ? 1 : 0, - AGL_SAMPLES_ARB, mFSAASamples, - AGL_DOUBLEBUFFER, - AGL_CLOSEST_POLICY, - AGL_ACCELERATED, - AGL_RED_SIZE, 8, - AGL_GREEN_SIZE, 8, - AGL_BLUE_SIZE, 8, - AGL_ALPHA_SIZE, 8, - AGL_DEPTH_SIZE, 24, - AGL_STENCIL_SIZE, 8, - AGL_NONE - }; - - LL_DEBUGS("Window") << "createContext: creating fullscreen pixelformat" << LL_ENDL; - - GDHandle gdhDisplay = NULL; - err = DMGetGDeviceByDisplayID ((DisplayIDType)mDisplay, &gdhDisplay, false); - - mPixelFormat = aglChoosePixelFormat(&gdhDisplay, 1, fullscreenAttrib); - rendererInfo = aglQueryRendererInfo(&gdhDisplay, 1); - } - else - { - // NOTE from Leslie: - // - // AGL_NO_RECOVERY, when combined with AGL_ACCELERATED prevents software rendering - // fallback which means we won't hvae shaders that compile and link but then don't - // work. The drawback is that our shader compilation will be a bit more finicky though. - - GLint windowedAttrib[] = - { - AGL_RGBA, - AGL_NO_RECOVERY, - AGL_DOUBLEBUFFER, - AGL_CLOSEST_POLICY, - AGL_ACCELERATED, - AGL_SAMPLE_BUFFERS_ARB, mFSAASamples > 0 ? 1 : 0, - AGL_SAMPLES_ARB, mFSAASamples, - AGL_RED_SIZE, 8, - AGL_GREEN_SIZE, 8, - AGL_BLUE_SIZE, 8, - AGL_ALPHA_SIZE, 8, - AGL_DEPTH_SIZE, 24, - AGL_STENCIL_SIZE, 8, - AGL_NONE - }; - - LL_DEBUGS("Window") << "createContext: creating windowed pixelformat" << LL_ENDL; - - mPixelFormat = aglChoosePixelFormat(NULL, 0, windowedAttrib); - - GDHandle gdhDisplay = GetMainDevice(); - rendererInfo = aglQueryRendererInfo(&gdhDisplay, 1); - } - - // May want to get the real error text like this: - // (char *) aglErrorString(aglGetError()); - - if(aglGetError() != AGL_NO_ERROR) - { - setupFailure("Can't find suitable pixel format", "Error", OSMB_OK); - return FALSE; - } - } - - if(mPixelFormat) - { - LL_DEBUGS("Window") << "createContext: creating GL context" << LL_ENDL; - mContext = aglCreateContext(mPixelFormat, NULL); - } - - if(mContext == NULL) - { - setupFailure("Can't make GL context", "Error", OSMB_OK); - return FALSE; - } - - gGLManager.mVRAM = 0; - - if(rendererInfo != NULL) - { - GLint result; - - if(aglDescribeRenderer(rendererInfo, AGL_VIDEO_MEMORY, &result)) - { - // llinfos << "createContext: aglDescribeRenderer(AGL_VIDEO_MEMORY) returned " << result << llendl; - gGLManager.mVRAM = result / (1024 * 1024); - } - else - { - // llinfos << "createContext: aglDescribeRenderer(AGL_VIDEO_MEMORY) failed." << llendl; - } - - // This could be useful at some point, if it takes into account the memory already used by screen buffers, etc... - if(aglDescribeRenderer(rendererInfo, AGL_TEXTURE_MEMORY, &result)) - { - // llinfos << "createContext: aglDescribeRenderer(AGL_TEXTURE_MEMORY) returned " << result << llendl; - } - else - { - // llinfos << "createContext: aglDescribeRenderer(AGL_TEXTURE_MEMORY) failed." << llendl; - } - - aglDestroyRendererInfo(rendererInfo); - } - + LL_INFOS("Window") << "Creating GL view..." << LL_ENDL; + mGLView = createOpenGLView(mWindow); + registerResizeEventCallback(mGLView, callResize); + mContext = getCGLContextObj(mWindow); // Since we just created the context, it needs to be set up. glNeedsInit = TRUE; } // Hook up the context to a drawable - if (mFullscreen && (mOldDisplayMode != NULL)) - { - // We successfully captured the display. Use a fullscreen drawable - - LL_DEBUGS("Window") << "createContext: attaching fullscreen drawable" << LL_ENDL; - -#if CAPTURE_ALL_DISPLAYS - // Capture all displays (may want to do this for final build) - aglDisable (mContext, AGL_FS_CAPTURE_SINGLE); -#else - // Capture only the main display (useful for debugging) - aglEnable (mContext, AGL_FS_CAPTURE_SINGLE); -#endif - - if (!aglSetFullScreen (mContext, 0, 0, 0, 0)) - { - setupFailure("Can't set GL fullscreen", "Error", OSMB_OK); - return FALSE; - } - } - else if(!mFullscreen && (mWindow != NULL)) - { - LL_DEBUGS("Window") << "createContext: attaching windowed drawable" << LL_ENDL; - - // We created a window. Use it as the drawable. - if(!aglSetDrawable(mContext, GetWindowPort (mWindow))) - { - setupFailure("Can't set GL drawable", "Error", OSMB_OK); - return FALSE; - } - } - else - { - setupFailure("Can't get fullscreen or windowed drawable.", "Error", OSMB_OK); - return FALSE; - } if(mContext != NULL) { + LL_INFOS("Window") << "Setting CGL Context..." << LL_ENDL; LL_DEBUGS("Window") << "createContext: setting current context" << LL_ENDL; - - if (!aglSetCurrentContext(mContext)) + U32 err = CGLSetCurrentContext(mContext); + if (err != kCGLNoError) { setupFailure("Can't activate GL rendering context", "Error", OSMB_OK); return FALSE; } } - if(glNeedsInit) - { - // Check for some explicitly unsupported cards. - const char* RENDERER = (const char*) glGetString(GL_RENDERER); - - const char* CARD_LIST[] = - { "RAGE 128", - "RIVA TNT2", - "Intel 810", - "3Dfx/Voodoo3", - "Radeon 7000", - "Radeon 7200", - "Radeon 7500", - "Radeon DDR", - "Radeon VE", - "GDI Generic" }; - const S32 CARD_COUNT = LL_ARRAY_SIZE(CARD_LIST); - - // Future candidates: - // ProSavage/Twister - // SuperSavage - - S32 i; - for (i = 0; i < CARD_COUNT; i++) - { - if (check_for_card(RENDERER, CARD_LIST[i])) - { - close(); - return FALSE; - } - } - } - - GLint colorBits, alphaBits, depthBits, stencilBits; - - if( !aglDescribePixelFormat(mPixelFormat, AGL_BUFFER_SIZE, &colorBits) || - !aglDescribePixelFormat(mPixelFormat, AGL_ALPHA_SIZE, &alphaBits) || - !aglDescribePixelFormat(mPixelFormat, AGL_DEPTH_SIZE, &depthBits) || - !aglDescribePixelFormat(mPixelFormat, AGL_STENCIL_SIZE, &stencilBits)) - { - close(); - setupFailure("Can't get pixel format description", "Error", OSMB_OK); - return FALSE; - } - - LL_INFOS("GLInit") << "GL buffer: Color Bits " << S32(colorBits) - << " Alpha Bits " << S32(alphaBits) - << " Depth Bits " << S32(depthBits) - << " Stencil Bits" << S32(stencilBits) - << LL_ENDL; - - if (colorBits < 32) - { - close(); - setupFailure( - "Second Life requires True Color (32-bit) to run in a window.\n" - "Please go to Control Panels -> Display -> Settings and\n" - "set the screen to 32-bit color.\n" - "Alternately, if you choose to run fullscreen, Second Life\n" - "will automatically adjust the screen each time it runs.", - "Error", - OSMB_OK); - return FALSE; - } - - if (alphaBits < 8) - { - close(); - setupFailure( - "Second Life is unable to run because it can't get an 8 bit alpha\n" - "channel. Usually this is due to video card driver issues.\n" - "Please make sure you have the latest video card drivers installed.\n" - "Also be sure your monitor is set to True Color (32-bit) in\n" - "Control Panels -> Display -> Settings.\n" - "If you continue to receive this message, contact customer service.", - "Error", - OSMB_OK); - return FALSE; - } - // Disable vertical sync for swap GLint frames_per_swap = 0; if (disable_vsync) @@ -790,7 +394,8 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits LL_DEBUGS("GLinit") << "Keeping vertical sync" << LL_ENDL; frames_per_swap = 1; } - aglSetInteger(mContext, AGL_SWAP_INTERVAL, &frames_per_swap); + + CGLSetParameter(mContext, kCGLCPSwapInterval, &frames_per_swap); //enable multi-threaded OpenGL if (sUseMultGL) @@ -809,109 +414,17 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits LL_DEBUGS("GLInit") << "Multi-threaded OpenGL enabled." << LL_ENDL; } } - + LL_INFOS("Window") << "Completed context creation." << LL_ENDL; // Don't need to get the current gamma, since there's a call that restores it to the system defaults. return TRUE; } -// changing fullscreen resolution, or switching between windowed and fullscreen mode. +// We only support OS X 10.7's fullscreen app mode which is literally a full screen window that fills a virtual desktop. +// This makes this method obsolete. BOOL LLWindowMacOSX::switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp) { - BOOL needsRebuild = FALSE; - BOOL result = true; - - if(fullscreen) - { - if(mFullscreen) - { - // Switching resolutions in fullscreen mode. Don't need to rebuild for this. - // Fullscreen support - CFDictionaryRef refDisplayMode = 0; - boolean_t exactMatch = false; - - // Switch the display to the desired resolution and refresh - refDisplayMode = CGDisplayBestModeForParametersAndRefreshRate( - mDisplay, - BITS_PER_PIXEL, - size.mX, - size.mY, - getDictDouble (CGDisplayCurrentMode (mDisplay), kCGDisplayRefreshRate), - &exactMatch); - - if (refDisplayMode) - { - CGDisplaySwitchToMode (mDisplay, refDisplayMode); - // CFRelease(refDisplayMode); - } - - mFullscreenWidth = CGDisplayPixelsWide(mDisplay); - mFullscreenHeight = CGDisplayPixelsHigh(mDisplay); - mFullscreenBits = CGDisplayBitsPerPixel(mDisplay); - mFullscreenRefresh = llround(getDictDouble (CGDisplayCurrentMode (mDisplay), kCGDisplayRefreshRate)); - - LL_INFOS("Window") << "Switched resolution to " << mFullscreenWidth - << "x" << mFullscreenHeight - << "x" << mFullscreenBits - << " @ " << mFullscreenRefresh - << LL_ENDL; - - // Update the GL context to the new screen size - if (!aglUpdateContext(mContext)) - { - setupFailure("Can't set GL fullscreen", "Error", OSMB_OK); - result = FALSE; - } - } - else - { - // Switching from windowed to fullscreen - needsRebuild = TRUE; - } - } - else - { - if(mFullscreen) - { - // Switching from fullscreen to windowed - needsRebuild = TRUE; - } - else - { - // Windowed to windowed -- not sure why we would be called like this. Just change the window size. - // The bounds changed event handler will do the rest. - if(mWindow != NULL) - { - ::SizeWindow(mWindow, size.mX, size.mY, true); - } - } - } - - stop_glerror(); - if(needsRebuild || mForceRebuild) - { - mForceRebuild = FALSE; - destroyContext(); - result = createContext(0, 0, size.mX, size.mY, 0, fullscreen, disable_vsync); - if (result) - { - if(mWindow != NULL) - { - MacShowWindow(mWindow); - BringToFront(mWindow); - } - - llverify(gGLManager.initGL()); - - //start with arrow cursor - initCursors(); - setCursor( UI_CURSOR_ARROW ); - } - } - - stop_glerror(); - - return result; + return FALSE; } void LLWindowMacOSX::destroyContext() @@ -926,31 +439,8 @@ void LLWindowMacOSX::destroyContext() { LL_DEBUGS("Window") << "destroyContext: unhooking drawable " << LL_ENDL; - aglSetCurrentContext (NULL); - aglSetDrawable(mContext, NULL); - } - - // Make sure the display resolution gets restored - if(mOldDisplayMode != NULL) - { - LL_DEBUGS("Window") << "destroyContext: restoring display resolution " << LL_ENDL; - - CGDisplaySwitchToMode (mDisplay, mOldDisplayMode); - -#if CAPTURE_ALL_DISPLAYS - // Uncapture all displays (may want to do this for final build) - CGReleaseAllDisplays (); -#else - // Uncapture only the main display (useful for debugging) - CGDisplayRelease (mDisplay); -#endif - - // CFRelease(mOldDisplayMode); - - mOldDisplayMode = NULL; - - // Remove the global event handlers the fullscreen case needed - RemoveEventTypesFromHandler(mGlobalHandlerRef, GetEventTypeCount (GlobalHandlerEventList), GlobalHandlerEventList); + CGLSetCurrentContext(NULL); + mContext = NULL; } // Clean up remaining GL state before blowing away window @@ -959,49 +449,19 @@ void LLWindowMacOSX::destroyContext() // Clean up the pixel format if(mPixelFormat != NULL) { - LL_DEBUGS("Window") << "destroyContext: destroying pixel format " << LL_ENDL; - aglDestroyPixelFormat(mPixelFormat); + CGLDestroyPixelFormat(mPixelFormat); mPixelFormat = NULL; } - // Remove any Carbon Event handlers we installed - if(mGlobalHandlerRef != NULL) - { - LL_DEBUGS("Window") << "destroyContext: removing global event handler" << LL_ENDL; - RemoveEventHandler(mGlobalHandlerRef); - mGlobalHandlerRef = NULL; - } - - if(mWindowHandlerRef != NULL) - { - LL_DEBUGS("Window") << "destroyContext: removing window event handler" << LL_ENDL; - RemoveEventHandler(mWindowHandlerRef); - mWindowHandlerRef = NULL; - } - - // Cleanup any TSM document we created. - if(mTSMDocument != NULL) - { - LL_DEBUGS("Window") << "destroyContext: deleting TSM document" << LL_ENDL; - DeactivateTSMDocument(mTSMDocument); - DeleteTSMDocument(mTSMDocument); - mTSMDocument = NULL; - } - // Close the window if(mWindow != NULL) { - LL_DEBUGS("Window") << "destroyContext: disposing window" << LL_ENDL; - DisposeWindow(mWindow); - mWindow = NULL; } // Clean up the GL context if(mContext != NULL) { - LL_DEBUGS("Window") << "destroyContext: destroying GL context" << LL_ENDL; - aglDestroyContext(mContext); - mContext = NULL; + CGLDestroyContext(mContext); } } @@ -1022,17 +482,11 @@ LLWindowMacOSX::~LLWindowMacOSX() void LLWindowMacOSX::show() { - if(IsWindowCollapsed(mWindow)) - CollapseWindow(mWindow, false); - - MacShowWindow(mWindow); - BringToFront(mWindow); } void LLWindowMacOSX::hide() { setMouseClipping(FALSE); - HideWindow(mWindow); } //virtual @@ -1040,7 +494,6 @@ void LLWindowMacOSX::minimize() { setMouseClipping(FALSE); showCursor(); - CollapseWindow(mWindow, true); } //virtual @@ -1086,7 +539,6 @@ BOOL LLWindowMacOSX::getVisible() result = TRUE; }if (mWindow) { - if(MacIsWindowVisible(mWindow)) result = TRUE; } @@ -1107,7 +559,6 @@ BOOL LLWindowMacOSX::maximize() { if (mWindow && !mMaximized) { - ZoomWindow(mWindow, inContent, true); } return mMaximized; @@ -1125,17 +576,14 @@ void LLWindowMacOSX::gatherInput() { stopDockTileBounce(); } - - // Use the old-school version so we get AppleEvent handler dispatch and menuselect handling. - // Anything that has an event handler will get processed inside WaitNextEvent, so we only need to handle - // the odd stuff here. + EventRecord evt; while(WaitNextEvent(everyEvent, &evt, 0, NULL)) { // printf("WaitNextEvent returned true, event is %d.\n", evt.what); switch(evt.what) { - case mouseDown: + case mouseDown: { short part; WindowRef window; @@ -1143,35 +591,125 @@ void LLWindowMacOSX::gatherInput() part = FindWindow(evt.where, &window); switch ( part ) { - case inMenuBar: - selectResult = MenuSelect(evt.where); - - HiliteMenu(0); - break; + case inMenuBar: + selectResult = MenuSelect(evt.where); + + HiliteMenu(0); + break; } } - break; - - case kHighLevelEvent: - AEProcessAppleEvent (&evt); - break; - - case updateEvt: - // We shouldn't be getting these regularly (since our window will be buffered), but we need to handle them correctly... - BeginUpdate((WindowRef)evt.message); - EndUpdate((WindowRef)evt.message); - break; - + break; + + case kHighLevelEvent: + AEProcessAppleEvent (&evt); + break; + + case updateEvt: + // We shouldn't be getting these regularly (since our window will be buffered), but we need to handle them correctly... + BeginUpdate((WindowRef)evt.message); + EndUpdate((WindowRef)evt.message); + break; + } } + /* + U32 event = getLatestEvent(mWindow); + switch (event) { + case 0: + // Nothing's happened since our last handled event. + break; + + case 1: + { + gKeyboard->handleKeyDown(getKeyDown(mWindow), getModifiers(mWindow)); + mCallbacks->handleUnicodeChar(getLastCharacter(mWindow), gKeyboard->currentMask(FALSE)); // currentMask has the appropriately translated modifiers. + mLastModifiers = gKeyboard->currentMask(FALSE); + } + break; + + case 2: + gKeyboard->handleKeyUp(getKeyUp(mWindow), getModifiers(mWindow)); + mLastModifiers = gKeyboard->currentMask(FALSE); + break; + + case 3: + break; + + case 4: + { + LLCoordScreen inCoords; + LLCoordGL outCoords; + float* mouseCoords = getMouseDown(mWindow); + inCoords.mX = llround(mouseCoords[0]); + inCoords.mY = llround(mouseCoords[1]); + convertCoords(inCoords, &outCoords); + mCallbacks->handleMouseDown(this, outCoords, getModifiers(mWindow)); + mLastModifiers = gKeyboard->currentMask(FALSE); + } + break; + case 5: + { + LLCoordScreen inCoords; + LLCoordGL outCoords; + float* mouseCoords = getMouseUp(mWindow); + inCoords.mX = llround(mouseCoords[0]); + inCoords.mY = llround(mouseCoords[1]); + convertCoords(inCoords, &outCoords); + mCallbacks->handleMouseUp(this, outCoords, getModifiers(mWindow)); + mLastModifiers = gKeyboard->currentMask(FALSE); + } + break; + case 6: + { + LLCoordScreen inCoords; + LLCoordGL outCoords; + float* mouseCoords = getRightMouseDown(mWindow); + inCoords.mX = llround(mouseCoords[0]); + inCoords.mY = llround(mouseCoords[1]); + convertCoords(inCoords, &outCoords); + mCallbacks->handleRightMouseDown(this, outCoords, getModifiers(mWindow)); + mLastModifiers = gKeyboard->currentMask(FALSE); + } + break; + case 7: + { + LLCoordScreen inCoords; + LLCoordGL outCoords; + float* mouseCoords = getRightMouseDown(mWindow); + inCoords.mX = llround(mouseCoords[0]); + inCoords.mY = llround(mouseCoords[1]); + convertCoords(inCoords, &outCoords); + mCallbacks->handleRightMouseDown(this, outCoords, getModifiers(mWindow)); + mLastModifiers = gKeyboard->currentMask(FALSE); + } + break; + case 8: // Double click + { + LLCoordScreen inCoords; + LLCoordGL outCoords; + float* mouseCoords = getRightMouseDown(mWindow); + inCoords.mX = llround(mouseCoords[0]); + inCoords.mY = llround(mouseCoords[1]); + convertCoords(inCoords, &outCoords); + mCallbacks->handleDoubleClick(this, outCoords, getModifiers(mWindow)); + mLastModifiers = gKeyboard->currentMask(FALSE); + } + break; + case 10: // Text input (for IMEs) + + break; + default: + break; + + }*/ updateCursor(); } BOOL LLWindowMacOSX::getPosition(LLCoordScreen *position) { - Rect window_rect; - OSStatus err = -1; + float rect[4]; + S32 err = -1; if(mFullscreen) { @@ -1181,10 +719,10 @@ BOOL LLWindowMacOSX::getPosition(LLCoordScreen *position) } else if(mWindow) { - err = GetWindowBounds(mWindow, kWindowContentRgn, &window_rect); + getContentViewBounds(mWindow, rect); - position->mX = window_rect.left; - position->mY = window_rect.top; + position->mX = rect[0]; + position->mY = rect[1]; } else { @@ -1196,8 +734,8 @@ BOOL LLWindowMacOSX::getPosition(LLCoordScreen *position) BOOL LLWindowMacOSX::getSize(LLCoordScreen *size) { - Rect window_rect; - OSStatus err = -1; + float rect[4]; + S32 err = -1; if(mFullscreen) { @@ -1207,10 +745,10 @@ BOOL LLWindowMacOSX::getSize(LLCoordScreen *size) } else if(mWindow) { - err = GetWindowBounds(mWindow, kWindowContentRgn, &window_rect); + getContentViewBounds(mWindow, rect); - size->mX = window_rect.right - window_rect.left; - size->mY = window_rect.bottom - window_rect.top; + size->mX = rect[2]; + size->mY = rect[3]; } else { @@ -1222,9 +760,9 @@ BOOL LLWindowMacOSX::getSize(LLCoordScreen *size) BOOL LLWindowMacOSX::getSize(LLCoordWindow *size) { - Rect window_rect; - OSStatus err = -1; - + float rect[4]; + S32 err = -1; + if(mFullscreen) { size->mX = mFullscreenWidth; @@ -1233,16 +771,16 @@ BOOL LLWindowMacOSX::getSize(LLCoordWindow *size) } else if(mWindow) { - err = GetWindowBounds(mWindow, kWindowContentRgn, &window_rect); - - size->mX = window_rect.right - window_rect.left; - size->mY = window_rect.bottom - window_rect.top; + getContentViewBounds(mWindow, rect); + + size->mX = rect[2]; + size->mY = rect[3]; } else { llerrs << "LLWindowMacOSX::getPosition(): no window and not fullscreen!" << llendl; } - + return (err == noErr); } @@ -1250,7 +788,8 @@ BOOL LLWindowMacOSX::setPosition(const LLCoordScreen position) { if(mWindow) { - MacMoveWindow(mWindow, position.mX, position.mY, false); + float pos[2] = {position.mX, position.mY}; + setWindowPos(mWindow, pos); } return TRUE; @@ -1260,7 +799,7 @@ BOOL LLWindowMacOSX::setSizeImpl(const LLCoordScreen size) { if(mWindow) { - SizeWindow(mWindow, size.mX, size.mY, true); + setWindowSize(mWindow, size.mX, size.mY); } return TRUE; @@ -1268,15 +807,16 @@ BOOL LLWindowMacOSX::setSizeImpl(const LLCoordScreen size) BOOL LLWindowMacOSX::setSizeImpl(const LLCoordWindow size) { - Rect client_rect; + float client_rect[4]; if (mWindow) { - OSStatus err = GetWindowBounds(mWindow, kWindowContentRgn, &client_rect); + S32 err = noErr; + getContentViewBounds(mWindow, client_rect); if (err == noErr) { - client_rect.right = client_rect.left + size.mX; - client_rect.bottom = client_rect.top + size.mY; - err = SetWindowBounds(mWindow, kWindowContentRgn, &client_rect); + client_rect[2] += size.mX; + client_rect[3] += size.mY; + setWindowSize(mWindow, client_rect[2], client_rect[3]); } if (err == noErr) { @@ -1293,7 +833,7 @@ BOOL LLWindowMacOSX::setSizeImpl(const LLCoordWindow size) void LLWindowMacOSX::swapBuffers() { - aglSwapBuffers(mContext); + CGLFlushDrawable(mContext); } F32 LLWindowMacOSX::getGamma() @@ -1453,7 +993,7 @@ BOOL LLWindowMacOSX::setCursorPosition(const LLCoordWindow position) return result; } - +/* static void fixOrigin(void) { GrafPtr port; @@ -1467,26 +1007,16 @@ static void fixOrigin(void) ::SetOrigin(0,0); } } - +*/ BOOL LLWindowMacOSX::getCursorPosition(LLCoordWindow *position) { - Point cursor_point; + float cursor_point[2]; LLCoordScreen screen_pos; - GrafPtr save; if(mWindow == NULL) return FALSE; - - ::GetPort(&save); - ::SetPort(GetWindowPort(mWindow)); - fixOrigin(); - - // gets the mouse location in local coordinates - ::GetMouse(&cursor_point); - -// lldebugs << "getCursorPosition(): cursor is at " << cursor_point.h << ", " << cursor_point.v << " port origin: " << portrect.left << ", " << portrect.top << llendl; - - ::SetPort(save); + + getCursorPos(mWindow, cursor_point); if(mCursorDecoupled) { @@ -1499,12 +1029,12 @@ BOOL LLWindowMacOSX::getCursorPosition(LLCoordWindow *position) // CGGetLastMouseDelta may behave strangely when the cursor's first captured. // Stash in the event handler instead. - cursor_point.h += mCursorLastEventDeltaX; - cursor_point.v += mCursorLastEventDeltaY; + cursor_point[0] += mCursorLastEventDeltaX; + cursor_point[1] += mCursorLastEventDeltaY; } - position->mX = cursor_point.h; - position->mY = cursor_point.v; + position->mX = cursor_point[0]; + position->mY = cursor_point[1]; return TRUE; } @@ -1521,7 +1051,6 @@ void LLWindowMacOSX::adjustCursorDecouple(bool warpingMouse) // llinfos << "adjustCursorDecouple: decoupling cursor" << llendl; CGAssociateMouseAndMouseCursorPosition(false); mCursorDecoupled = true; - FlushSpecificEventsFromQueue(GetCurrentEventQueue(), mMoveEventCampartorUPP, NULL); mCursorIgnoreNextDelta = TRUE; } } @@ -1568,52 +1097,13 @@ F32 LLWindowMacOSX::getPixelAspectRatio() // MBW -- XXX -- There's got to be a better way than this. Find it, please... +// Since we're no longer supporting the "typical" fullscreen mode with CGL or NSOpenGL anymore, these are unnecessary. -Geenz void LLWindowMacOSX::beforeDialog() { - if(mFullscreen) - { - -#if CAPTURE_ALL_DISPLAYS - // Uncapture all displays (may want to do this for final build) - CGReleaseAllDisplays (); -#else - // Uncapture only the main display (useful for debugging) - CGDisplayRelease (mDisplay); -#endif - // kDocumentWindowClass - // kMovableModalWindowClass - // kAllWindowClasses - - // GLint order = 0; - // aglSetInteger(mContext, AGL_ORDER_CONTEXT_TO_FRONT, &order); - aglSetDrawable(mContext, NULL); - // GetWindowGroupLevel(GetWindowGroupOfClass(kAllWindowClasses), &oldWindowLevel); - // SetWindowGroupLevel(GetWindowGroupOfClass(kAllWindowClasses), CGShieldingWindowLevel()); - - mHandsOffEvents = TRUE; - - } } void LLWindowMacOSX::afterDialog() { - if(mFullscreen) - { - mHandsOffEvents = FALSE; - - // SetWindowGroupLevel(GetWindowGroupOfClass(kAllWindowClasses), oldWindowLevel); - aglSetFullScreen(mContext, 0, 0, 0, 0); - // GLint order = 1; - // aglSetInteger(mContext, AGL_ORDER_CONTEXT_TO_FRONT, &order); - -#if CAPTURE_ALL_DISPLAYS - // Capture all displays (may want to do this for final build) - CGCaptureAllDisplays (); -#else - // Capture only the main display (useful for debugging) - CGDisplayCapture (mDisplay); -#endif - } } @@ -1622,14 +1112,10 @@ void LLWindowMacOSX::flashIcon(F32 seconds) // Don't do this if we're already started, since this would try to install the NMRec twice. if(!mBounceTimer.getStarted()) { - OSErr err; - + S32 err = 0; + // TODO: Implement icon bouncing mBounceTime = seconds; - memset(&mBounceRec, 0, sizeof(mBounceRec)); - mBounceRec.qType = nmType; - mBounceRec.nmMark = 1; - err = NMInstall(&mBounceRec); - if(err == noErr) + if(err == 0) { mBounceTimer.start(); } @@ -1643,104 +1129,25 @@ void LLWindowMacOSX::flashIcon(F32 seconds) BOOL LLWindowMacOSX::isClipboardTextAvailable() { - OSStatus err; - ScrapRef scrap; - ScrapFlavorFlags flags; BOOL result = false; - - err = GetCurrentScrap(&scrap); - - if(err == noErr) - { - err = GetScrapFlavorFlags(scrap, kScrapFlavorTypeUnicode, &flags); - } - - if(err == noErr) - result = true; - + // TODO: Clipboard support. return result; } BOOL LLWindowMacOSX::pasteTextFromClipboard(LLWString &dst) { - OSStatus err; - ScrapRef scrap; - Size len; BOOL result = false; - - err = GetCurrentScrap(&scrap); - - if(err == noErr) - { - err = GetScrapFlavorSize(scrap, kScrapFlavorTypeUnicode, &len); - } - - if((err == noErr) && (len > 0)) - { - int u16len = len / sizeof(U16); - U16 *temp = new U16[u16len + 1]; - if (temp) - { - memset(temp, 0, (u16len + 1) * sizeof(temp[0])); - err = GetScrapFlavorData(scrap, kScrapFlavorTypeUnicode, &len, temp); - if (err == noErr) - { - // convert \r\n to \n and \r to \n in the incoming text. - U16 *s, *d; - for(s = d = temp; s[0] != '\0'; s++, d++) - { - if(s[0] == '\r') - { - if(s[1] == '\n') - { - // CRLF, a.k.a. DOS newline. Collapse to a single '\n'. - s++; - } - - d[0] = '\n'; - } - else - { - d[0] = s[0]; - } - } - - d[0] = '\0'; - - dst = utf16str_to_wstring(temp); - - result = true; - } - delete[] temp; - } - } + + // TODO: Clipboard support. return result; } BOOL LLWindowMacOSX::copyTextToClipboard(const LLWString &s) { - OSStatus err; - ScrapRef scrap; - //Size len; - //char *temp; BOOL result = false; - - if (!s.empty()) - { - err = GetCurrentScrap(&scrap); - if (err == noErr) - err = ClearScrap(&scrap); - - if (err == noErr) - { - llutf16string utf16str = wstring_to_utf16str(s); - size_t u16len = utf16str.length() * sizeof(U16); - err = PutScrapFlavor(scrap, kScrapFlavorTypeUnicode, kScrapFlavorMaskNone, u16len, utf16str.data()); - if (err == noErr) - result = true; - } - } + + // TODO: Clipboard support. return result; } @@ -1761,1048 +1168,162 @@ LLWindow::LLWindowResolution* LLWindowMacOSX::getSupportedResolutions(S32 &num_r CFArrayRef modes = CGDisplayAvailableModes(mDisplay); if(modes != NULL) - { - CFIndex index, cnt; - - mSupportedResolutions = new LLWindowResolution[MAX_NUM_RESOLUTIONS]; - mNumSupportedResolutions = 0; - - // Examine each mode - cnt = CFArrayGetCount( modes ); - - for ( index = 0; (index < cnt) && (mNumSupportedResolutions < MAX_NUM_RESOLUTIONS); index++ ) - { - // Pull the mode dictionary out of the CFArray - CFDictionaryRef mode = (CFDictionaryRef)CFArrayGetValueAtIndex( modes, index ); - long width = getDictLong(mode, kCGDisplayWidth); - long height = getDictLong(mode, kCGDisplayHeight); - long bits = getDictLong(mode, kCGDisplayBitsPerPixel); - - if(bits == BITS_PER_PIXEL && width >= 800 && height >= 600) - { - BOOL resolution_exists = FALSE; - for(S32 i = 0; i < mNumSupportedResolutions; i++) - { - if (mSupportedResolutions[i].mWidth == width && - mSupportedResolutions[i].mHeight == height) - { - resolution_exists = TRUE; - } - } - if (!resolution_exists) - { - mSupportedResolutions[mNumSupportedResolutions].mWidth = width; - mSupportedResolutions[mNumSupportedResolutions].mHeight = height; - mNumSupportedResolutions++; - } - } - } - } - } - - num_resolutions = mNumSupportedResolutions; - return mSupportedResolutions; -} - -BOOL LLWindowMacOSX::convertCoords(LLCoordGL from, LLCoordWindow *to) -{ - S32 client_height; - Rect client_rect; - - if(mFullscreen) - { - // In the fullscreen case, the "window" is the entire screen. - client_rect.left = 0; - client_rect.top = 0; - client_rect.right = mFullscreenWidth; - client_rect.bottom = mFullscreenHeight; - } - else if (!mWindow || - (GetWindowBounds(mWindow, kWindowContentRgn, &client_rect) != noErr) || - NULL == to) - { - return FALSE; - } - - to->mX = from.mX; - client_height = client_rect.bottom - client_rect.top; - to->mY = client_height - from.mY - 1; - - return TRUE; -} - -BOOL LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordGL* to) -{ - S32 client_height; - Rect client_rect; - - if(mFullscreen) - { - // In the fullscreen case, the "window" is the entire screen. - client_rect.left = 0; - client_rect.top = 0; - client_rect.right = mFullscreenWidth; - client_rect.bottom = mFullscreenHeight; - } - else if (!mWindow || - (GetWindowBounds(mWindow, kWindowContentRgn, &client_rect) != noErr) || - NULL == to) - { - return FALSE; - } - - to->mX = from.mX; - client_height = client_rect.bottom - client_rect.top; - to->mY = client_height - from.mY - 1; - - return TRUE; -} - -BOOL LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordWindow* to) -{ - if(mFullscreen) - { - // In the fullscreen case, window and screen coordinates are the same. - to->mX = from.mX; - to->mY = from.mY; - return TRUE; - } - else if(mWindow) - { - GrafPtr save; - Point mouse_point; - - mouse_point.h = from.mX; - mouse_point.v = from.mY; - - ::GetPort(&save); - ::SetPort(GetWindowPort(mWindow)); - fixOrigin(); - - ::GlobalToLocal(&mouse_point); - - to->mX = mouse_point.h; - to->mY = mouse_point.v; - - ::SetPort(save); - - return TRUE; - } - - return FALSE; -} - -BOOL LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordScreen *to) -{ - if(mFullscreen) - { - // In the fullscreen case, window and screen coordinates are the same. - to->mX = from.mX; - to->mY = from.mY; - return TRUE; - } - else if(mWindow) - { - GrafPtr save; - Point mouse_point; - - mouse_point.h = from.mX; - mouse_point.v = from.mY; - ::GetPort(&save); - ::SetPort(GetWindowPort(mWindow)); - fixOrigin(); - - LocalToGlobal(&mouse_point); - - to->mX = mouse_point.h; - to->mY = mouse_point.v; - - ::SetPort(save); - - return TRUE; - } - - return FALSE; -} - -BOOL LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordGL *to) -{ - LLCoordWindow window_coord; - - return(convertCoords(from, &window_coord) && convertCoords(window_coord, to)); -} - -BOOL LLWindowMacOSX::convertCoords(LLCoordGL from, LLCoordScreen *to) -{ - LLCoordWindow window_coord; - - return(convertCoords(from, &window_coord) && convertCoords(window_coord, to)); -} - - - - -void LLWindowMacOSX::setupFailure(const std::string& text, const std::string& caption, U32 type) -{ - destroyContext(); - - OSMessageBox(text, caption, type); -} - -pascal Boolean LLWindowMacOSX::staticMoveEventComparator( EventRef event, void* data) -{ - UInt32 evtClass = GetEventClass (event); - UInt32 evtKind = GetEventKind (event); - - if ((evtClass == kEventClassMouse) && ((evtKind == kEventMouseDragged) || (evtKind == kEventMouseMoved))) - { - return true; - } - - else - { - return false; - } -} - - -pascal OSStatus LLWindowMacOSX::staticEventHandler(EventHandlerCallRef myHandler, EventRef event, void* userData) -{ - LLWindowMacOSX *self = (LLWindowMacOSX*)userData; - - return(self->eventHandler(myHandler, event)); -} - -OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef event) -{ - OSStatus result = eventNotHandledErr; - UInt32 evtClass = GetEventClass (event); - UInt32 evtKind = GetEventKind (event); - - // Always handle command events, even in hands-off mode. - if((evtClass == kEventClassCommand) && (evtKind == kEventCommandProcess)) - { - HICommand command; - GetEventParameter (event, kEventParamDirectObject, typeHICommand, NULL, sizeof(command), NULL, &command); - - switch(command.commandID) - { - case kHICommandQuit: - if(mCallbacks->handleCloseRequest(this)) - { - // Get the app to initiate cleanup. - mCallbacks->handleQuit(this); - // The app is responsible for calling destroyWindow when done with GL - } - result = noErr; - break; - - default: - // MBW -- XXX -- Should we handle other events here? - break; - } - } - - if(mHandsOffEvents) - { - return(result); - } - - switch (evtClass) - { - case kEventClassTextInput: - { - switch (evtKind) - { - case kEventTextInputUpdateActiveInputArea: - { - EventParamType param_type; - - long fix_len; - UInt32 text_len; - if (mPreeditor - && (result = GetEventParameter(event, kEventParamTextInputSendFixLen, - typeLongInteger, ¶m_type, sizeof(fix_len), NULL, &fix_len)) == noErr - && typeLongInteger == param_type - && (result = GetEventParameter(event, kEventParamTextInputSendText, - typeUnicodeText, ¶m_type, 0, &text_len, NULL)) == noErr - && typeUnicodeText == param_type) - { - // Handle an optional (but essential to facilitate TSMDA) ReplaceRange param. - CFRange range; - if (GetEventParameter(event, kEventParamTextInputSendReplaceRange, - typeCFRange, ¶m_type, sizeof(range), NULL, &range) == noErr - && typeCFRange == param_type) - { - // Although the spec. is unclear, replace range should - // not present when there is an active preedit. We just - // ignore the case. markAsPreedit will detect the case and warn it. - const LLWString & text = mPreeditor->getPreeditString(); - const S32 location = wstring_wstring_length_from_utf16_length(text, 0, range.location); - const S32 length = wstring_wstring_length_from_utf16_length(text, location, range.length); - mPreeditor->markAsPreedit(location, length); - } - mPreeditor->resetPreedit(); - - // Receive the text from input method. - U16 *const text = new U16[text_len / sizeof(U16)]; - GetEventParameter(event, kEventParamTextInputSendText, typeUnicodeText, NULL, text_len, NULL, text); - if (fix_len < 0) - { - // Do we still need this? Seems obsolete... - fix_len = text_len; - } - const LLWString fix_string - = utf16str_to_wstring(llutf16string(text, fix_len / sizeof(U16))); - const LLWString preedit_string - = utf16str_to_wstring(llutf16string(text + fix_len / sizeof(U16), (text_len - fix_len) / sizeof(U16))); - delete[] text; - - // Handle fixed (comitted) string. - if (fix_string.length() > 0) - { - for (LLWString::const_iterator i = fix_string.begin(); i != fix_string.end(); i++) - { - mPreeditor->handleUnicodeCharHere(*i); - } - } - - // Receive the segment info and caret position. - LLPreeditor::segment_lengths_t preedit_segment_lengths; - LLPreeditor::standouts_t preedit_standouts; - S32 caret_position = preedit_string.length(); - UInt32 text_range_array_size; - if (GetEventParameter(event, kEventParamTextInputSendHiliteRng, typeTextRangeArray, - ¶m_type, 0, &text_range_array_size, NULL) == noErr - && typeTextRangeArray == param_type - && text_range_array_size > sizeof(TextRangeArray)) - { - // TextRangeArray is a variable-length struct. - TextRangeArray * const text_range_array = (TextRangeArray *) new char[text_range_array_size]; - GetEventParameter(event, kEventParamTextInputSendHiliteRng, typeTextRangeArray, - NULL, text_range_array_size, NULL, text_range_array); - - // WARNING: We assume ranges are in ascending order, - // although the condition is undocumented. It seems - // OK to assume this. I also assumed - // the ranges are contiguous in previous versions, but I - // have heard a rumore that older versions os ATOK may - // return ranges with some _gap_. I don't know whether - // it is true, but I'm preparing my code for the case. - - const S32 ranges = text_range_array->fNumOfRanges; - preedit_segment_lengths.reserve(ranges); - preedit_standouts.reserve(ranges); - - S32 last_bytes = 0; - S32 last_utf32 = 0; - for (S32 i = 0; i < ranges; i++) - { - const TextRange &range = text_range_array->fRange[i]; - if (range.fStart > last_bytes) - { - const S32 length_utf16 = (range.fStart - last_bytes) / sizeof(U16); - const S32 length_utf32 = wstring_wstring_length_from_utf16_length(preedit_string, last_utf32, length_utf16); - preedit_segment_lengths.push_back(length_utf32); - preedit_standouts.push_back(FALSE); - last_utf32 += length_utf32; - } - if (range.fEnd > range.fStart) - { - const S32 length_utf16 = (range.fEnd - range.fStart) / sizeof(U16); - const S32 length_utf32 = wstring_wstring_length_from_utf16_length(preedit_string, last_utf32, length_utf16); - preedit_segment_lengths.push_back(length_utf32); - preedit_standouts.push_back( - kTSMHiliteSelectedRawText == range.fHiliteStyle - || kTSMHiliteSelectedConvertedText == range.fHiliteStyle - || kTSMHiliteSelectedText == range.fHiliteStyle); - last_utf32 += length_utf32; - } - if (kTSMHiliteCaretPosition == range.fHiliteStyle) - { - caret_position = last_utf32; - } - last_bytes = range.fEnd; - } - if (preedit_string.length() > last_utf32) - { - preedit_segment_lengths.push_back(preedit_string.length() - last_utf32); - preedit_standouts.push_back(FALSE); - } - - delete[] (char *) text_range_array; - } - - // Handle preedit string. - if (preedit_string.length() == 0) - { - preedit_segment_lengths.clear(); - preedit_standouts.clear(); - } - else if (preedit_segment_lengths.size() == 0) - { - preedit_segment_lengths.push_back(preedit_string.length()); - preedit_standouts.push_back(FALSE); - } - mPreeditor->updatePreedit(preedit_string, preedit_segment_lengths, preedit_standouts, caret_position); - - result = noErr; - } - } - break; - - case kEventTextInputUnicodeForKeyEvent: - { - UInt32 modifiers = 0; - - - // First, process the raw event. - { - EventRef rawEvent = NULL; - - // Get the original event and extract the modifier keys, so we can ignore command-key events. - if (GetEventParameter(event, kEventParamTextInputSendKeyboardEvent, typeEventRef, NULL, sizeof(rawEvent), NULL, &rawEvent) == noErr) - { - // Grab the modifiers for later use in this function... - GetEventParameter (rawEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers); - - // and call this function recursively to handle the raw key event. - eventHandler (myHandler, rawEvent); - - // save the raw event until we're done processing the unicode input as well. - mRawKeyEvent = rawEvent; - } - } - - OSStatus err = noErr; - EventParamType actualType = typeUnicodeText; - UInt32 actualSize = 0; - size_t actualCount = 0; - U16 *buffer = NULL; - - // Get the size of the unicode data - err = GetEventParameter (event, kEventParamTextInputSendText, typeUnicodeText, &actualType, 0, &actualSize, NULL); - if(err == noErr) - { - // allocate a buffer and get the actual data. - actualCount = actualSize / sizeof(U16); - buffer = new U16[actualCount]; - err = GetEventParameter (event, kEventParamTextInputSendText, typeUnicodeText, &actualType, actualSize, &actualSize, buffer); - } - - if(err == noErr) - { - if(modifiers & (cmdKey | controlKey)) - { - // This was a menu key equivalent. Ignore it. - } - else - { - MASK mask = LLWindowMacOSX::modifiersToMask(modifiers); - - llassert( actualType == typeUnicodeText ); - - // The result is a UTF16 buffer. Pass the characters in turn to handleUnicodeChar. - - // Convert to UTF32 and go character-by-character. - llutf16string utf16(buffer, actualCount); - LLWString utf32 = utf16str_to_wstring(utf16); - LLWString::iterator iter; - - for(iter = utf32.begin(); iter != utf32.end(); iter++) - { - mCallbacks->handleUnicodeChar(*iter, mask); - } - } - } - - if(buffer != NULL) - { - delete[] buffer; - } - - mRawKeyEvent = NULL; - result = err; - } - break; - - case kEventTextInputOffsetToPos: - { - EventParamType param_type; - long offset; - if (mPreeditor - && GetEventParameter(event, kEventParamTextInputSendTextOffset, typeLongInteger, - ¶m_type, sizeof(offset), NULL, &offset) == noErr - && typeLongInteger == param_type) - { - S32 preedit, preedit_length; - mPreeditor->getPreeditRange(&preedit, &preedit_length); - const LLWString & text = mPreeditor->getPreeditString(); - - LLCoordGL caret_coord; - LLRect preedit_bounds; - if (0 <= offset - && mPreeditor->getPreeditLocation(wstring_wstring_length_from_utf16_length(text, preedit, offset / sizeof(U16)), - &caret_coord, &preedit_bounds, NULL)) - { - LLCoordGL caret_base_coord(caret_coord.mX, preedit_bounds.mBottom); - LLCoordScreen caret_base_coord_screen; - convertCoords(caret_base_coord, &caret_base_coord_screen); - Point qd_point; - qd_point.h = caret_base_coord_screen.mX; - qd_point.v = caret_base_coord_screen.mY; - SetEventParameter(event, kEventParamTextInputReplyPoint, typeQDPoint, sizeof(qd_point), &qd_point); - - short line_height = (short) preedit_bounds.getHeight(); - SetEventParameter(event, kEventParamTextInputReplyLineHeight, typeShortInteger, sizeof(line_height), &line_height); - - result = noErr; - } - else - { - result = errOffsetInvalid; - } - } - } - break; - - case kEventTextInputGetSelectedText: - { - if (mPreeditor) - { - S32 selection, selection_length; - mPreeditor->getSelectionRange(&selection, &selection_length); - if (selection_length) - { - const LLWString text = mPreeditor->getPreeditString().substr(selection, selection_length); - const llutf16string text_utf16 = wstring_to_utf16str(text); - result = SetEventParameter(event, kEventParamTextInputReplyText, typeUnicodeText, - text_utf16.length() * sizeof(U16), text_utf16.c_str()); - } - } - } - break; - } - } - break; - - case kEventClassKeyboard: - { - UInt32 keyCode = 0; - char charCode = 0; - UInt32 modifiers = 0; - - // Some of these may fail for some event types. That's fine. - GetEventParameter (event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode); - GetEventParameter (event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers); - - // save the raw event so getNativeKeyData can use it. - mRawKeyEvent = event; - - // printf("key event, key code = 0x%08x, char code = 0x%02x (%c), modifiers = 0x%08x\n", keyCode, charCode, (char)charCode, modifiers); - // fflush(stdout); - - switch (evtKind) - { - case kEventRawKeyDown: - case kEventRawKeyRepeat: - if (gDebugWindowProc) - { - printf("key down, key code = 0x%08x, char code = 0x%02x (%c), modifiers = 0x%08x\n", - (unsigned int)keyCode, charCode, (char)charCode, (unsigned int)modifiers); - fflush(stdout); - } - gKeyboard->handleKeyDown(keyCode, modifiers); - result = eventNotHandledErr; - break; - - case kEventRawKeyUp: - if (gDebugWindowProc) - { - printf("key up, key code = 0x%08x, char code = 0x%02x (%c), modifiers = 0x%08x\n", - (unsigned int)keyCode, charCode, (char)charCode, (unsigned int)modifiers); - fflush(stdout); - } - gKeyboard->handleKeyUp(keyCode, modifiers); - result = eventNotHandledErr; - break; - - case kEventRawKeyModifiersChanged: - // The keyboard input system wants key up/down events for modifier keys. - // Mac OS doesn't supply these directly, but can supply events when the collective modifier state changes. - // Use these events to generate up/down events for the modifiers. - - if((modifiers & shiftKey) && !(mLastModifiers & shiftKey)) - { - if (gDebugWindowProc) printf("Shift key down event\n"); - gKeyboard->handleKeyDown(0x38, (modifiers & 0x00FFFFFF) | ((0x38 << 24) & 0xFF000000)); - } - else if(!(modifiers & shiftKey) && (mLastModifiers & shiftKey)) - { - if (gDebugWindowProc) printf("Shift key up event\n"); - gKeyboard->handleKeyUp(0x38, (modifiers & 0x00FFFFFF) | ((0x38 << 24) & 0xFF000000)); - } - - if((modifiers & alphaLock) && !(mLastModifiers & alphaLock)) - { - if (gDebugWindowProc) printf("Caps lock down event\n"); - gKeyboard->handleKeyDown(0x39, (modifiers & 0x00FFFFFF) | ((0x39 << 24) & 0xFF000000)); - } - else if(!(modifiers & alphaLock) && (mLastModifiers & alphaLock)) - { - if (gDebugWindowProc) printf("Caps lock up event\n"); - gKeyboard->handleKeyUp(0x39, (modifiers & 0x00FFFFFF) | ((0x39 << 24) & 0xFF000000)); - } - - if((modifiers & controlKey) && !(mLastModifiers & controlKey)) - { - if (gDebugWindowProc) printf("Control key down event\n"); - gKeyboard->handleKeyDown(0x3b, (modifiers & 0x00FFFFFF) | ((0x3b << 24) & 0xFF000000)); - } - else if(!(modifiers & controlKey) && (mLastModifiers & controlKey)) - { - if (gDebugWindowProc) printf("Control key up event\n"); - gKeyboard->handleKeyUp(0x3b, (modifiers & 0x00FFFFFF) | ((0x3b << 24) & 0xFF000000)); - } - - if((modifiers & optionKey) && !(mLastModifiers & optionKey)) - { - if (gDebugWindowProc) printf("Option key down event\n"); - gKeyboard->handleKeyDown(0x3a, (modifiers & 0x00FFFFFF) | ((0x3a << 24) & 0xFF000000)); - } - else if(!(modifiers & optionKey) && (mLastModifiers & optionKey)) - { - if (gDebugWindowProc) printf("Option key up event\n"); - gKeyboard->handleKeyUp(0x3a, (modifiers & 0x00FFFFFF) | ((0x3a << 24) & 0xFF000000)); - } - - // When the state of the 'Fn' key (the one that changes some of the mappings on a powerbook/macbook keyboard - // to an embedded keypad) changes, it may subsequently cause a key up event to be lost, which may lead to - // a movement key getting "stuck" down. This is bad. - // This is an OS bug -- even the GetKeys() API doesn't tell you the key has been released. - // This workaround causes all held-down keys to be reset whenever the state of the Fn key changes. This isn't - // exactly what we want, but it does avoid the case where you get stuck running forward. - if((modifiers & kEventKeyModifierFnMask) != (mLastModifiers & kEventKeyModifierFnMask)) - { - if (gDebugWindowProc) printf("Fn key state change event\n"); - gKeyboard->resetKeys(); - } - - if (gDebugWindowProc) fflush(stdout); - - mLastModifiers = modifiers; - result = eventNotHandledErr; - break; - } - - mRawKeyEvent = NULL; - } - break; - - case kEventClassMouse: - { - result = CallNextEventHandler(myHandler, event); - if (eventNotHandledErr == result) - { // only handle events not already handled (prevents wierd resize interaction) - EventMouseButton button = kEventMouseButtonPrimary; - HIPoint location = {0.0f, 0.0f}; - UInt32 modifiers = 0; - UInt32 clickCount = 1; - long wheelDelta = 0; - LLCoordScreen inCoords; - LLCoordGL outCoords; - MASK mask = 0; - - GetEventParameter(event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(button), NULL, &button); - GetEventParameter(event, kEventParamMouseLocation, typeHIPoint, NULL, sizeof(location), NULL, &location); - GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(modifiers), NULL, &modifiers); - GetEventParameter(event, kEventParamMouseWheelDelta, typeLongInteger, NULL, sizeof(wheelDelta), NULL, &wheelDelta); - GetEventParameter(event, kEventParamClickCount, typeUInt32, NULL, sizeof(clickCount), NULL, &clickCount); - - inCoords.mX = llround(location.x); - inCoords.mY = llround(location.y); - - if(modifiers & shiftKey) { mask |= MASK_SHIFT; } - if(modifiers & controlKey) { mask |= MASK_CONTROL; } - if(modifiers & optionKey) { mask |= MASK_ALT; } - - if(mCursorDecoupled) - { - CGMouseDelta x, y; - - // If the cursor's decoupled, we need to read the latest movement delta as well. - CGGetLastMouseDelta( &x, &y ); - mCursorLastEventDeltaX = x; - mCursorLastEventDeltaY = y; - - if(mCursorIgnoreNextDelta) - { - mCursorLastEventDeltaX = 0; - mCursorLastEventDeltaY = 0; - mCursorIgnoreNextDelta = FALSE; - } - } - else - { - mCursorLastEventDeltaX = 0; - mCursorLastEventDeltaY = 0; - } - - inCoords.mX += mCursorLastEventDeltaX; - inCoords.mY += mCursorLastEventDeltaY; - - convertCoords(inCoords, &outCoords); - - // printf("coords in: %d, %d; coords out: %d, %d\n", inCoords.mX, inCoords.mY, outCoords.mX, outCoords.mY); - // fflush(stdout); - - - switch (evtKind) - { - case kEventMouseDown: - if (mLanguageTextInputAllowed) - { - // We need to interrupt before handling mouse events, - // so that the fixed string from IM are delivered to - // the currently focused UI component. - interruptLanguageTextInput(); - } - switch(button) - { - case kEventMouseButtonPrimary: - if(modifiers & cmdKey) - { - // Simulate a right click - mSimulatedRightClick = true; - mCallbacks->handleRightMouseDown(this, outCoords, mask); - } - else if(clickCount == 2) - { - // Windows double-click events replace the second mousedown event in a double-click. - mCallbacks->handleDoubleClick(this, outCoords, mask); - } - else - { - mCallbacks->handleMouseDown(this, outCoords, mask); - } - break; - case kEventMouseButtonSecondary: - mCallbacks->handleRightMouseDown(this, outCoords, mask); - break; - - case kEventMouseButtonTertiary: - mCallbacks->handleMiddleMouseDown(this, outCoords, mask); - break; - } - result = noErr; - break; - case kEventMouseUp: - - switch(button) - { - case kEventMouseButtonPrimary: - if(mSimulatedRightClick) - { - // End of simulated right click - mSimulatedRightClick = false; - mCallbacks->handleRightMouseUp(this, outCoords, mask); - } - else - { - mCallbacks->handleMouseUp(this, outCoords, mask); - } - break; - case kEventMouseButtonSecondary: - mCallbacks->handleRightMouseUp(this, outCoords, mask); - break; + { + CFIndex index, cnt; - case kEventMouseButtonTertiary: - mCallbacks->handleMiddleMouseUp(this, outCoords, mask); - break; - } - result = noErr; - break; + mSupportedResolutions = new LLWindowResolution[MAX_NUM_RESOLUTIONS]; + mNumSupportedResolutions = 0; - case kEventMouseWheelMoved: - { - static S32 z_delta = 0; + // Examine each mode + cnt = CFArrayGetCount( modes ); - z_delta += wheelDelta; + for ( index = 0; (index < cnt) && (mNumSupportedResolutions < MAX_NUM_RESOLUTIONS); index++ ) + { + // Pull the mode dictionary out of the CFArray + CFDictionaryRef mode = (CFDictionaryRef)CFArrayGetValueAtIndex( modes, index ); + long width = getDictLong(mode, kCGDisplayWidth); + long height = getDictLong(mode, kCGDisplayHeight); + long bits = getDictLong(mode, kCGDisplayBitsPerPixel); - if (z_delta <= -WHEEL_DELTA || WHEEL_DELTA <= z_delta) + if(bits == BITS_PER_PIXEL && width >= 800 && height >= 600) + { + BOOL resolution_exists = FALSE; + for(S32 i = 0; i < mNumSupportedResolutions; i++) + { + if (mSupportedResolutions[i].mWidth == width && + mSupportedResolutions[i].mHeight == height) { - mCallbacks->handleScrollWheel(this, -z_delta / WHEEL_DELTA); - z_delta = 0; + resolution_exists = TRUE; } } - result = noErr; - break; - - case kEventMouseDragged: - case kEventMouseMoved: - mCallbacks->handleMouseMove(this, outCoords, mask); - result = noErr; - break; - + if (!resolution_exists) + { + mSupportedResolutions[mNumSupportedResolutions].mWidth = width; + mSupportedResolutions[mNumSupportedResolutions].mHeight = height; + mNumSupportedResolutions++; + } } } } - break; - - case kEventClassWindow: - switch(evtKind) - { - case kEventWindowActivated: - if (mTSMDocument) - { - ActivateTSMDocument(mTSMDocument); - } - mCallbacks->handleFocus(this); - break; - case kEventWindowDeactivated: - if (mTSMDocument) - { - DeactivateTSMDocument(mTSMDocument); - } - mCallbacks->handleFocusLost(this); - break; - - case kEventWindowBoundsChanging: - { - // This is where we would constrain move/resize to a particular screen - - const S32 MIN_WIDTH = mMinWindowWidth; - const S32 MIN_HEIGHT = mMinWindowHeight; - - Rect currentBounds; - Rect previousBounds; - - GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, ¤tBounds); - GetEventParameter(event, kEventParamPreviousBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &previousBounds); - - // Put an offset into window un-maximize operation since the kEventWindowGetIdealSize - // event only allows the specification of size and not position. - if (mMaximized) - { - short leftOffset = mPreviousWindowRect.left - currentBounds.left; - currentBounds.left += leftOffset; - currentBounds.right += leftOffset; + } - short topOffset = mPreviousWindowRect.top - currentBounds.top; - currentBounds.top += topOffset; - currentBounds.bottom += topOffset; - } - else - { - // Store off the size for future un-maximize operations - mPreviousWindowRect = previousBounds; - } + num_resolutions = mNumSupportedResolutions; + return mSupportedResolutions; +} - if ((currentBounds.right - currentBounds.left) < MIN_WIDTH) - { - currentBounds.right = currentBounds.left + MIN_WIDTH; - } +BOOL LLWindowMacOSX::convertCoords(LLCoordGL from, LLCoordWindow *to) +{ + S32 client_height; + float client_rect[4]; + getContentViewBounds(mWindow, client_rect); + if (!mWindow || + NULL == to) + { + return FALSE; + } - if ((currentBounds.bottom - currentBounds.top) < MIN_HEIGHT) - { - currentBounds.bottom = currentBounds.top + MIN_HEIGHT; - } + to->mX = from.mX; + client_height = client_rect[3]; + to->mY = from.mY - 1; - SetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, sizeof(Rect), ¤tBounds); - result = noErr; - } - break; + return TRUE; +} - case kEventWindowBoundsChanged: - { - // Get new window bounds - Rect newBounds; - GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &newBounds); +BOOL LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordGL* to) +{ + S32 client_height; + float client_rect[4]; + + getContentViewBounds(mWindow, client_rect); + + if (!mWindow || + NULL == to) + { + return FALSE; + } - // Get previous window bounds - Rect oldBounds; - GetEventParameter(event, kEventParamPreviousBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &oldBounds); + to->mX = from.mX; + client_height = client_rect[3]; + to->mY = from.mY - 1; - // Determine if the new size is larger than the old - bool newBoundsLarger = ((newBounds.right - newBounds.left) >= (oldBounds.right - oldBounds.left)); - newBoundsLarger &= ((newBounds.bottom - newBounds.top) >= (oldBounds.bottom - oldBounds.top)); + return TRUE; +} - // Check to see if this is a zoom event (+ button on window pane) - unsigned int eventParams; - GetEventParameter(event, kEventParamAttributes, typeUInt32, NULL, sizeof(int), NULL, &eventParams); - bool isZoomEvent = ((eventParams & kWindowBoundsChangeZoom) != 0); +BOOL LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordWindow* to) +{ + if(mFullscreen) + { + // In the fullscreen case, window and screen coordinates are the same. + to->mX = from.mX; + to->mY = from.mY; + return TRUE; + } + else if(mWindow) + { + float mouse_point[2]; - // Maximized flag is if zoom event and increasing window size - mMaximized = (isZoomEvent && newBoundsLarger); + mouse_point[0] = from.mX; + mouse_point[1] = from.mY; + + convertScreenToWindow(mWindow, mouse_point); - aglUpdateContext(mContext); + to->mX = mouse_point[0]; + to->mY = mouse_point[1]; - mCallbacks->handleResize(this, newBounds.right - newBounds.left, newBounds.bottom - newBounds.top); - } - break; + return TRUE; + } - case kEventWindowGetIdealSize: - // Only recommend a new ideal size when un-maximizing - if (mMaximized == TRUE) - { - Point nonMaximizedSize; + return FALSE; +} - nonMaximizedSize.v = mPreviousWindowRect.bottom - mPreviousWindowRect.top; - nonMaximizedSize.h = mPreviousWindowRect.right - mPreviousWindowRect.left; +BOOL LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordScreen *to) +{ + if(mFullscreen) + { + // In the fullscreen case, window and screen coordinates are the same. + to->mX = from.mX; + to->mY = from.mY; + return TRUE; + } + else if(mWindow) + { + float mouse_point[2]; - SetEventParameter(event, kEventParamDimensions, typeQDPoint, sizeof(Point), &nonMaximizedSize); - result = noErr; - } - break; + mouse_point[0] = from.mX; + mouse_point[1] = from.mY; + convertWindowToScreen(mWindow, mouse_point); - case kEventWindowClose: - if(mCallbacks->handleCloseRequest(this)) - { - // Get the app to initiate cleanup. - mCallbacks->handleQuit(this); - // The app is responsible for calling destroyWindow when done with GL - } - result = noErr; - break; + to->mX = mouse_point[0]; + to->mY = mouse_point[1]; - case kEventWindowHidden: - // llinfos << "LLWindowMacOSX: Deactivating on hide" << llendl; - mMinimized = TRUE; - mCallbacks->handleActivate(this, false); - // result = noErr; - break; + return TRUE; + } - case kEventWindowShown: - // llinfos << "LLWindowMacOSX: Activating on show" << llendl; - mMinimized = FALSE; - mCallbacks->handleActivate(this, true); - // result = noErr; - break; + return FALSE; +} - case kEventWindowCollapsed: - // llinfos << "LLWindowMacOSX: Deactivating on collapse" << llendl; - mMinimized = TRUE; - mCallbacks->handleActivate(this, false); - // result = noErr; - break; +BOOL LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordGL *to) +{ + LLCoordWindow window_coord; - case kEventWindowExpanded: - // llinfos << "LLWindowMacOSX: Activating on expand" << llendl; - mMinimized = FALSE; - mCallbacks->handleActivate(this, true); - // result = noErr; - break; + return(convertCoords(from, &window_coord) && convertCoords(window_coord, to)); +} - case kEventWindowGetClickActivation: - // BringToFront(mWindow); - // result = noErr; - break; - } - break; +BOOL LLWindowMacOSX::convertCoords(LLCoordGL from, LLCoordScreen *to) +{ + LLCoordWindow window_coord; - case kEventClassTSMDocumentAccess: - if (mPreeditor) - { - switch(evtKind) - { + return(convertCoords(from, &window_coord) && convertCoords(window_coord, to)); +} - case kEventTSMDocumentAccessGetLength: - { - // Return the number of UTF-16 units in the text, excluding those for preedit. - - S32 preedit, preedit_length; - mPreeditor->getPreeditRange(&preedit, &preedit_length); - const LLWString & text = mPreeditor->getPreeditString(); - const CFIndex length = wstring_utf16_length(text, 0, preedit) - + wstring_utf16_length(text, preedit + preedit_length, text.length()); - result = SetEventParameter(event, kEventParamTSMDocAccessCharacterCount, typeCFIndex, sizeof(length), &length); - } - break; - case kEventTSMDocumentAccessGetSelectedRange: - { - // Return the selected range, excluding preedit. - // In our preeditor, preedit and selection are exclusive, so, - // when it has a preedit, there is no selection and the - // insertion point is on the preedit that corrupses into the - // beginning of the preedit when the preedit was removed. - - S32 preedit, preedit_length; - mPreeditor->getPreeditRange(&preedit, &preedit_length); - const LLWString & text = mPreeditor->getPreeditString(); - - CFRange range; - if (preedit_length) - { - range.location = wstring_utf16_length(text, 0, preedit); - range.length = 0; - } - else - { - S32 selection, selection_length; - mPreeditor->getSelectionRange(&selection, &selection_length); - range.location = wstring_utf16_length(text, 0, selection); - range.length = wstring_utf16_length(text, selection, selection_length); - } - result = SetEventParameter(event, kEventParamTSMDocAccessReplyCharacterRange, typeCFRange, sizeof(range), &range); - } - break; - case kEventTSMDocumentAccessGetCharacters: - { - UniChar *target_pointer; - CFRange range; - EventParamType param_type; - if ((result = GetEventParameter(event, kEventParamTSMDocAccessSendCharacterRange, - typeCFRange, ¶m_type, sizeof(range), NULL, &range)) == noErr - && typeCFRange == param_type - && (result = GetEventParameter(event, kEventParamTSMDocAccessSendCharactersPtr, - typePtr, ¶m_type, sizeof(target_pointer), NULL, &target_pointer)) == noErr - && typePtr == param_type) - { - S32 preedit, preedit_length; - mPreeditor->getPreeditRange(&preedit, &preedit_length); - const LLWString & text = mPreeditor->getPreeditString(); - - // The GetCharacters event of TSMDA has a fundamental flaw; - // An input method need to decide the starting offset and length - // *before* it actually see the contents, so it is impossible - // to guarantee the character-aligned access. The event reply - // has no way to indicate a condition something like "Request - // was not fulfilled due to unaligned access. Please retry." - // Any error sent back to the input method stops use of TSMDA - // entirely during the session... - // We need to simulate very strictly the behaviour as if the - // underlying *text engine* holds the contents in UTF-16. - // I guess this is the reason why Apple repeats saying "all - // text handling application should use UTF-16." They are - // trying to _fix_ the flaw by changing the appliations... - // ... or, domination of UTF-16 in the industry may be a part - // of the company vision, and Apple is trying to force third - // party developers to obey their vision. Remember that use - // of 16 bits per _a_character_ was one of the very fundamental - // Unicode design policy on its early days (during late 80s) - // and the original Unicode design was by two Apple employees... - - const llutf16string text_utf16 - = wstring_to_utf16str(text, preedit) - + wstring_to_utf16str(text.substr(preedit + preedit_length)); - - llassert_always(sizeof(U16) == sizeof(UniChar)); - llassert(0 <= range.location && 0 <= range.length && range.location + range.length <= text_utf16.length()); - memcpy(target_pointer, text_utf16.c_str() + range.location, range.length * sizeof(UniChar)); - - // Note that result has already been set above. - } - } - break; +void LLWindowMacOSX::setupFailure(const std::string& text, const std::string& caption, U32 type) +{ + destroyContext(); - } - } - break; - } - return result; + OSMessageBox(text, caption, type); } const char* cursorIDToName(int id) @@ -2876,7 +1397,7 @@ static void initPixmapCursor(int cursorid, int hotspotX, int hotspotY) void LLWindowMacOSX::updateCursor() { - OSStatus result = noErr; + S32 result = 0; if (mDragOverrideCursor != -1) { @@ -2913,7 +1434,7 @@ void LLWindowMacOSX::updateCursor() if(mCursorHidden) { // Since InitCursor resets the hide level, correct for it here. - ::HideCursor(); + hideNSCursor(); } break; @@ -2921,12 +1442,12 @@ void LLWindowMacOSX::updateCursor() // Find out what they look like and replicate them. // These are essentially correct - case UI_CURSOR_WAIT: SetThemeCursor(kThemeWatchCursor); break; - case UI_CURSOR_IBEAM: SetThemeCursor(kThemeIBeamCursor); break; - case UI_CURSOR_CROSS: SetThemeCursor(kThemeCrossCursor); break; - case UI_CURSOR_HAND: SetThemeCursor(kThemePointingHandCursor); break; + case UI_CURSOR_WAIT: /* Apple purposely doesn't allow us to set the beachball cursor manually. */ break; + case UI_CURSOR_IBEAM: setIBeamCursor(); break; + case UI_CURSOR_CROSS: setCrossCursor(); break; + case UI_CURSOR_HAND: setPointingHandCursor(); break; // case UI_CURSOR_NO: SetThemeCursor(kThemeNotAllowedCursor); break; - case UI_CURSOR_ARROWCOPY: SetThemeCursor(kThemeCopyArrowCursor); break; + case UI_CURSOR_ARROWCOPY: setCopyCursor(); break; // Double-check these case UI_CURSOR_NO: @@ -3039,7 +1560,7 @@ void LLWindowMacOSX::hideCursor() // llinfos << "hideCursor: hiding" << llendl; mCursorHidden = TRUE; mHideCursorPermanent = TRUE; - ::HideCursor(); + hideNSCursor(); } else { @@ -3056,7 +1577,7 @@ void LLWindowMacOSX::showCursor() // llinfos << "showCursor: showing" << llendl; mCursorHidden = FALSE; mHideCursorPermanent = FALSE; - ::ShowCursor(); + showNSCursor(); } else { @@ -3102,7 +1623,7 @@ void LLSplashScreenMacOSX::showImpl() // This code _could_ be used to display a spash screen... #if 0 IBNibRef nib = NULL; - OSStatus err; + S32 err; err = CreateNibReference(CFSTR("SecondLife"), &nib); @@ -3127,25 +1648,6 @@ void LLSplashScreenMacOSX::updateImpl(const std::string& mesg) CFStringRef string = NULL; string = CFStringCreateWithCString(NULL, mesg.c_str(), kCFStringEncodingUTF8); - - if(string != NULL) - { - ControlRef progressText = NULL; - ControlID id; - OSStatus err; - - id.signature = 'what'; - id.id = 0; - - err = GetControlByID(mWindow, &id, &progressText); - if(err == noErr) - { - err = SetControlData(progressText, kControlEntireControl, kControlStaticTextCFStringTag, sizeof(CFStringRef), (Ptr)&string); - Draw1Control(progressText); - } - - CFRelease(string); - } } } @@ -3154,7 +1656,6 @@ void LLSplashScreenMacOSX::hideImpl() { if(mWindow != NULL) { - DisposeWindow(mWindow); mWindow = NULL; } } @@ -3163,102 +1664,16 @@ void LLSplashScreenMacOSX::hideImpl() S32 OSMessageBoxMacOSX(const std::string& text, const std::string& caption, U32 type) { - S32 result = OSBTN_CANCEL; - SInt16 retval_mac = 1; - AlertStdCFStringAlertParamRec params; - CFStringRef errorString = NULL; - CFStringRef explanationString = NULL; - DialogRef alert = NULL; - AlertType alertType = kAlertCautionAlert; - OSStatus err; - - explanationString = CFStringCreateWithCString(NULL, text.c_str(), kCFStringEncodingUTF8); - errorString = CFStringCreateWithCString(NULL, caption.c_str(), kCFStringEncodingUTF8); - - params.version = kStdCFStringAlertVersionOne; - params.movable = false; - params.helpButton = false; - params.defaultText = (CFStringRef)kAlertDefaultOKText; - params.cancelText = 0; - params.otherText = 0; - params.defaultButton = 1; - params.cancelButton = 0; - params.position = kWindowDefaultPosition; - params.flags = 0; - - switch(type) - { - case OSMB_OK: - default: - break; - case OSMB_OKCANCEL: - params.cancelText = (CFStringRef)kAlertDefaultCancelText; - params.cancelButton = 2; - break; - case OSMB_YESNO: - alertType = kAlertNoteAlert; - params.defaultText = CFSTR("Yes"); - params.cancelText = CFSTR("No"); - params.cancelButton = 2; - break; - } - - if(gWindowImplementation != NULL) - gWindowImplementation->beforeDialog(); - - err = CreateStandardAlert( - alertType, - errorString, - explanationString, - ¶ms, - &alert); - - if(err == noErr) - { - err = RunStandardAlert( - alert, - NULL, - &retval_mac); - } - - if(gWindowImplementation != NULL) - gWindowImplementation->afterDialog(); - - switch(type) - { - case OSMB_OK: - case OSMB_OKCANCEL: - default: - if(retval_mac == 1) - result = OSBTN_OK; - else - result = OSBTN_CANCEL; - break; - case OSMB_YESNO: - if(retval_mac == 1) - result = OSBTN_YES; - else - result = OSBTN_NO; - break; - } - - if(errorString != NULL) - { - CFRelease(errorString); - } - - if(explanationString != NULL) - { - CFRelease(explanationString); - } - - return result; + // TODO: Implement a native NSAlert function that replicates all of this. + return 0; } // Open a URL with the user's default web browser. // Must begin with protocol identifier. void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url, bool async) { + // I'm fairly certain that this is all legitimate under Apple's currently supported APIs. + bool found = false; S32 i; for (i = 0; i < gURLProtocolWhitelistCount; i++) @@ -3276,7 +1691,7 @@ void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url, bool async) return; } - OSStatus result = noErr; + S32 result = 0; CFURLRef urlRef = NULL; llinfos << "Opening URL " << escaped_url << llendl; @@ -3313,7 +1728,7 @@ void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url, bool async) LLSD LLWindowMacOSX::getNativeKeyData() { LLSD result = LLSD::emptyMap(); - +#if 0 if(mRawKeyEvent) { char char_code = 0; @@ -3335,7 +1750,7 @@ LLSD LLWindowMacOSX::getNativeKeyData() // This causes trouble for control characters -- apparently character codes less than 32 (escape, control-A, etc) // cause llsd serialization to create XML that the llsd deserializer won't parse! std::string unicode; - OSStatus err = noErr; + S32 err = noErr; EventParamType actualType = typeUTF8Text; UInt32 actualSize = 0; char *buffer = NULL; @@ -3357,7 +1772,7 @@ LLSD LLWindowMacOSX::getNativeKeyData() #endif } - +#endif lldebugs << "native key data is: " << result << llendl; @@ -3367,34 +1782,9 @@ LLSD LLWindowMacOSX::getNativeKeyData() BOOL LLWindowMacOSX::dialogColorPicker( F32 *r, F32 *g, F32 *b) { + // Is this even used anywhere? Do we really need an OS color picker? BOOL retval = FALSE; - OSErr error = noErr; - NColorPickerInfo info; - - memset(&info, 0, sizeof(info)); - info.theColor.color.rgb.red = (UInt16)(*r * 65535.f); - info.theColor.color.rgb.green = (UInt16)(*g * 65535.f); - info.theColor.color.rgb.blue = (UInt16)(*b * 65535.f); - info.placeWhere = kCenterOnMainScreen; - - if(gWindowImplementation != NULL) - gWindowImplementation->beforeDialog(); - - error = NPickColor(&info); - - if(gWindowImplementation != NULL) - gWindowImplementation->afterDialog(); - - if (error == noErr) - { - retval = info.newColorChosen; - if (info.newColorChosen) - { - *r = ((float) info.theColor.color.rgb.red) / 65535.0; - *g = ((float) info.theColor.color.rgb.green) / 65535.0; - *b = ((float) info.theColor.color.rgb.blue) / 65535.0; - } - } + //S32 error = 0; return (retval); } @@ -3405,44 +1795,13 @@ void *LLWindowMacOSX::getPlatformWindow() return (void*)mWindow; } -void *LLWindowMacOSX::getMediaWindow() -{ - /* - Mozilla needs to be initialized with a WindowRef to function properly. - (There's no good reason for this, since it shouldn't be interacting with our window in any way, but that's another issue.) - If we're in windowed mode, we _could_ hand it our actual window pointer, but a subsequent switch to fullscreen will destroy that window, - which trips up Mozilla. - Instead of using our actual window, we create an invisible window which will persist for the lifetime of the application and pass that to Mozilla. - This satisfies its deep-seated need to latch onto a WindowRef and solves the issue with switching between fullscreen and windowed modes. - - Note that we will never destroy this window (by design!), but since only one will ever be created per run of the application, that's okay. - */ - - if(sMediaWindow == NULL) - { - Rect window_rect = {100, 100, 200, 200}; - - sMediaWindow = NewCWindow( - NULL, - &window_rect, - (ConstStr255Param) "\p", - false, // Create the window invisible. - zoomDocProc, // Window with a grow box and a zoom box - kLastWindowOfClass, // create it behind other windows - false, // no close box - 0); - } - - return (void*)sMediaWindow; -} - void LLWindowMacOSX::stopDockTileBounce() { - NMRemove(&mBounceRec); mBounceTimer.stop(); } // get a double value from a dictionary +/* static double getDictDouble (CFDictionaryRef refDict, CFStringRef key) { double double_value; @@ -3452,7 +1811,7 @@ static double getDictDouble (CFDictionaryRef refDict, CFStringRef key) if (!CFNumberGetValue(number_value, kCFNumberDoubleType, &double_value)) // or if cant convert it return -1; // fail return double_value; // otherwise return the long value -} +}*/ // get a long value from a dictionary static long getDictLong (CFDictionaryRef refDict, CFStringRef key) @@ -3468,71 +1827,12 @@ static long getDictLong (CFDictionaryRef refDict, CFStringRef key) void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) { - ScriptLanguageRecord script_language; - - 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; - } - - UseInputWindow(mTSMDocument, !b); - - // 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; - - if (b) - { - if (mTSMScriptCode != smRoman) - { - script_language.fScript = mTSMScriptCode; - script_language.fLanguage = mTSMLangCode; - SetTextServiceLanguage(&script_language); - } - } - else - { - GetTextServiceLanguage(&script_language); - mTSMScriptCode = script_language.fScript; - mTSMLangCode = script_language.fLanguage; - if (mTSMScriptCode != smRoman) - { - script_language.fScript = smRoman; - script_language.fLanguage = langEnglish; - SetTextServiceLanguage(&script_language); - } - } + // TODO: IME support } void LLWindowMacOSX::interruptLanguageTextInput() { - if (mTSMDocument) - { - FixTSMDocument(mTSMDocument); - } - // Don't we need to call resetPreedit here? - // Well, if Apple's TSM document is correct, we don't. + // TODO: IME support } //static @@ -3543,21 +1843,21 @@ std::vector LLWindowMacOSX::getDynamicFallbackFontList() } // static -MASK LLWindowMacOSX::modifiersToMask(SInt16 modifiers) +MASK LLWindowMacOSX::modifiersToMask(S16 modifiers) { MASK mask = 0; - if(modifiers & shiftKey) { mask |= MASK_SHIFT; } - if(modifiers & (cmdKey | controlKey)) { mask |= MASK_CONTROL; } - if(modifiers & optionKey) { mask |= MASK_ALT; } + if(modifiers & MAC_SHIFT_KEY) { mask |= MASK_SHIFT; } + if(modifiers & (MAC_CMD_KEY | MAC_CTRL_KEY)) { mask |= MASK_CONTROL; } + if(modifiers & MAC_ALT_KEY) { mask |= MASK_ALT; } return mask; } #if LL_OS_DRAGDROP_ENABLED - -OSErr LLWindowMacOSX::dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow, +/* +S16 LLWindowMacOSX::dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow, void * handlerRefCon, DragRef drag) { - OSErr result = noErr; + S16 result = 0; LLWindowMacOSX *self = (LLWindowMacOSX*)handlerRefCon; lldebugs << "drag tracking handler, message = " << message << llendl; @@ -3711,5 +2011,5 @@ OSErr LLWindowMacOSX::handleDragNDrop(DragRef drag, LLWindowCallbacks::DragNDrop return result; } - +*/ #endif // LL_OS_DRAGDROP_ENABLED diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h index af83b50097..a821dcabd8 100644 --- a/indra/llwindow/llwindowmacosx.h +++ b/indra/llwindow/llwindowmacosx.h @@ -29,11 +29,14 @@ #include "llwindow.h" #include "llwindowcallbacks.h" +#include "llwindowmacosx-objc.h" #include "lltimer.h" -#include -#include +//#include +//#include +#include +#include // AssertMacros.h does bad things. #include "fix_macros.h" @@ -106,7 +109,6 @@ public: /*virtual*/ BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b); /*virtual*/ void *getPlatformWindow(); - /*virtual*/ void *getMediaWindow(); /*virtual*/ void bringToFront() {}; /*virtual*/ void allowLanguageTextInput(LLPreeditor *preeditor, BOOL b); @@ -117,6 +119,12 @@ public: // Provide native key event data /*virtual*/ LLSD getNativeKeyData(); + + void* getWindow() { return mWindow; } + LLWindowCallbacks* getCallbacks() { return mCallbacks; } + + void updateMouseDeltas(); + void getMouseDeltas(float* delta); protected: @@ -153,40 +161,35 @@ protected: BOOL createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL disable_vsync); void destroyContext(); void setupFailure(const std::string& text, const std::string& caption, U32 type); - static pascal OSStatus staticEventHandler (EventHandlerCallRef myHandler, EventRef event, void* userData); - static pascal Boolean staticMoveEventComparator( EventRef event, void* data); - OSStatus eventHandler (EventHandlerCallRef myHandler, EventRef event); void adjustCursorDecouple(bool warpingMouse = false); void stopDockTileBounce(); - static MASK modifiersToMask(SInt16 modifiers); + static MASK modifiersToMask(S16 modifiers); #if LL_OS_DRAGDROP_ENABLED + /* static OSErr dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow, void * handlerRefCon, DragRef theDrag); static OSErr dragReceiveHandler(WindowRef theWindow, void * handlerRefCon, DragRef theDrag); OSErr handleDragNDrop(DragRef theDrag, LLWindowCallbacks::DragNDropAction action); + */ #endif // LL_OS_DRAGDROP_ENABLED // // Platform specific variables // - WindowRef mWindow; - AGLContext mContext; - AGLPixelFormat mPixelFormat; + + // Use generic pointers here. This lets us do some funky Obj-C interop using Obj-C objects without having to worry about any compilation problems that may arise. + NSWindowRef mWindow; + GLViewRef mGLView; + CGLContextObj mContext; + CGLPixelFormatObj mPixelFormat; CGDirectDisplayID mDisplay; - CFDictionaryRef mOldDisplayMode; - EventLoopTimerRef mTimer; - EventHandlerUPP mEventHandlerUPP; - EventHandlerRef mGlobalHandlerRef; - EventHandlerRef mWindowHandlerRef; - EventComparatorUPP mMoveEventCampartorUPP; - Rect mOldMouseClip; // Screen rect to which the mouse cursor was globally constrained before we changed it in clipMouse() - Rect mPreviousWindowRect; // Save previous window for un-maximize event - Str255 mWindowTitle; + LLRect mOldMouseClip; // Screen rect to which the mouse cursor was globally constrained before we changed it in clipMouse() + std::string mWindowTitle; double mOriginalAspectRatio; BOOL mSimulatedRightClick; - UInt32 mLastModifiers; + U32 mLastModifiers; BOOL mHandsOffEvents; // When true, temporarially disable CarbonEvent processing. // Used to allow event processing when putting up dialogs in fullscreen mode. BOOL mCursorDecoupled; @@ -204,22 +207,17 @@ protected: S32 mDragOverrideCursor; F32 mBounceTime; - NMRec mBounceRec; + //NMRec mBounceRec; LLTimer mBounceTimer; // Input method management through Text Service Manager. - TSMDocumentID mTSMDocument; BOOL mLanguageTextInputAllowed; - ScriptCode mTSMScriptCode; - LangCode mTSMLangCode; LLPreeditor* mPreeditor; static BOOL sUseMultGL; friend class LLWindowManager; - static WindowRef sMediaWindow; - EventRef mRawKeyEvent; - + }; -- cgit v1.3 From bd152c1fb75c4a8d4b9271896c44243ca8759e58 Mon Sep 17 00:00:00 2001 From: Geenz Date: Sat, 29 Dec 2012 06:59:43 -0500 Subject: Huge amount of refactoring to use Cocoa here: - Updated to .xib format. To produce a new nib (which is required after changing the xib file), use "ibtool SecondLife.xib --compile SecondLife.nib" within the newview directory. - xib file now defines the viewer's window. VIews are still being pragmatically added to the main window. This may change in the future. - LLAppViewer's main loop has been slightly refactored to be executed on a timer for OS X. This probably needs a bit more work. - Event handling still needs more work to work within a timer based event loop. It works fairly sporadically at the moment, as if events are being dropped between timer executions, at least for the mouse. - Carbon has been purged from the viewer's startup, and from LLWindow entirely. There's likely still a few odds and ends fragmented throughout the viewer and its dependencies. Need to track these down. - LLAppViewerMacOSX now uses NSApplicationMain, and also implements the NSApplicationDelegate protocol in LLAppDelegate. - Fullscreen support has been implemented for OS X 10.7+ This is still a work in progress, however at this stage everything needed for a functional viewer is (mostly) complete. From here, it's mostly just bug hunting and fixing. --- indra/llwindow/llopenglview-objc.h | 7 +- indra/llwindow/llopenglview-objc.mm | 140 +- indra/llwindow/llwindowmacosx-objc.h | 4 +- indra/llwindow/llwindowmacosx-objc.mm | 19 +- indra/llwindow/llwindowmacosx.cpp | 133 +- indra/llwindow/llwindowmacosx.h | 2 - indra/media_plugins/webkit/mac_volume_catcher.cpp | 1 - indra/newview/CMakeLists.txt | 6 +- indra/newview/Info-SecondLife.plist | 4 + indra/newview/SecondLife.nib/classes.nib | 4 - indra/newview/SecondLife.nib/info.nib | 23 - indra/newview/SecondLife.nib/objects.xib | 259 --- indra/newview/SecondLife.xib | 1848 +++++++++++++++++++++ indra/newview/llappviewer.cpp | 118 +- indra/newview/llappviewer.h | 3 + indra/newview/llappviewermacosx-delegate.h | 24 + indra/newview/llappviewermacosx-delegate.mm | 49 + indra/newview/llappviewermacosx-objc.h | 19 + indra/newview/llappviewermacosx-objc.mm | 20 + indra/newview/llappviewermacosx.cpp | 234 +-- indra/newview/macutil_Prefix.h | 1 - 21 files changed, 2195 insertions(+), 723 deletions(-) delete mode 100644 indra/newview/SecondLife.nib/classes.nib delete mode 100644 indra/newview/SecondLife.nib/info.nib delete mode 100644 indra/newview/SecondLife.nib/objects.xib create mode 100644 indra/newview/SecondLife.xib create mode 100644 indra/newview/llappviewermacosx-delegate.h create mode 100644 indra/newview/llappviewermacosx-delegate.mm create mode 100644 indra/newview/llappviewermacosx-objc.h create mode 100644 indra/newview/llappviewermacosx-objc.mm (limited to 'indra/llwindow') diff --git a/indra/llwindow/llopenglview-objc.h b/indra/llwindow/llopenglview-objc.h index 8abe81ce9e..6b055bc665 100644 --- a/indra/llwindow/llopenglview-objc.h +++ b/indra/llwindow/llopenglview-objc.h @@ -69,4 +69,9 @@ - (void) registerMouseExitCallback:(VoidCallback)callback; - (void) registerDeltaUpdateCallback:(MouseCallback)callback; -@end \ No newline at end of file +@end + +void setLLNSWindowRef(LLNSWindow* window); +void setLLOpenGLViewRef(LLOpenGLView* view); +LLNSWindow* winRef; +LLOpenGLView* glviewRef; diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index a96c4cf82c..7c148f4acd 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -19,9 +19,12 @@ - (void)windowResized:(NSNotification *)notification; { - NSSize size = [[self window] frame].size; - - mResizeCallback(size.width, size.height); + if (mResizeCallback != nil) + { + NSSize size = [[self window] frame].size; + + mResizeCallback(size.width, size.height); + } } - (void)dealloc @@ -194,23 +197,29 @@ } - (void) keyDown:(NSEvent *)theEvent { - mKeyDownCallback([theEvent keyCode], [theEvent modifierFlags]); - - NSString *chars = [theEvent charactersIgnoringModifiers]; - for (uint i = 0; i < [chars length]; i++) + if (mKeyDownCallback != nil && mUnicodeCallback != nil) { - mUnicodeCallback([chars characterAtIndex:i], [theEvent modifierFlags]); - } - - // The viewer expects return to be submitted separately as a unicode character. - if ([theEvent keyCode] == 3 || [theEvent keyCode] == 13) - { - mUnicodeCallback([theEvent keyCode], [theEvent modifierFlags]); + mKeyDownCallback([theEvent keyCode], [theEvent modifierFlags]); + + NSString *chars = [theEvent charactersIgnoringModifiers]; + for (uint i = 0; i < [chars length]; i++) + { + mUnicodeCallback([chars characterAtIndex:i], [theEvent modifierFlags]); + } + + // The viewer expects return to be submitted separately as a unicode character. + if ([theEvent keyCode] == 3 || [theEvent keyCode] == 13) + { + mUnicodeCallback([theEvent keyCode], [theEvent modifierFlags]); + } } } - (void) keyUp:(NSEvent *)theEvent { - mKeyUpCallback([theEvent keyCode], [theEvent modifierFlags]); + if (mKeyUpCallback != nil) + { + mKeyUpCallback([theEvent keyCode], [theEvent modifierFlags]); + } } - (void)flagsChanged:(NSEvent *)theEvent { @@ -219,41 +228,59 @@ - (void) mouseDown:(NSEvent *)theEvent { - if ([theEvent clickCount] == 2) + if (mMouseDoubleClickCallback != nil && mMouseDownCallback != nil) { - mMouseDoubleClickCallback(mMousePos, [theEvent modifierFlags]); - } else if ([theEvent clickCount] == 1) { - mMouseDownCallback(mMousePos, [theEvent modifierFlags]); + if ([theEvent clickCount] == 2) + { + mMouseDoubleClickCallback(mMousePos, [theEvent modifierFlags]); + } else if ([theEvent clickCount] == 1) { + mMouseDownCallback(mMousePos, [theEvent modifierFlags]); + } } } - (void) mouseUp:(NSEvent *)theEvent { - mMouseUpCallback(mMousePos, [theEvent modifierFlags]); + if (mMouseUpCallback != nil) + { + mMouseUpCallback(mMousePos, [theEvent modifierFlags]); + } } - (void) rightMouseDown:(NSEvent *)theEvent { - mRightMouseDownCallback(mMousePos, [theEvent modifierFlags]); + if (mRightMouseDownCallback != nil) + { + mRightMouseDownCallback(mMousePos, [theEvent modifierFlags]); + } } - (void) rightMouseUp:(NSEvent *)theEvent { - mRightMouseUpCallback(mMousePos, [theEvent modifierFlags]); + if (mRightMouseUpCallback != nil) + { + mRightMouseUpCallback(mMousePos, [theEvent modifierFlags]); + } } - (void)mouseMoved:(NSEvent *)theEvent { - float mouseDeltas[2] = { - [theEvent deltaX], - [theEvent deltaZ] - }; - - mDeltaUpdateCallback(mouseDeltas, 0); - - NSPoint mPoint = [theEvent locationInWindow]; - mMousePos[0] = mPoint.x; - mMousePos[1] = mPoint.y; - mMouseMovedCallback(mMousePos, 0); + if (mDeltaUpdateCallback != nil && mMouseMovedCallback != nil) + { + float mouseDeltas[2] = { + [theEvent deltaX], + [theEvent deltaZ] + }; + + mDeltaUpdateCallback(mouseDeltas, 0); + + NSPoint mPoint = [theEvent locationInWindow]; + mMousePos[0] = mPoint.x; + mMousePos[1] = mPoint.y; + if (mMouseMovedCallback != nil) + { + mMouseMovedCallback(mMousePos, 0); + } + } } // NSWindow doesn't trigger mouseMoved when the mouse is being clicked and dragged. @@ -261,27 +288,36 @@ - (void) mouseDragged:(NSEvent *)theEvent { - float mouseDeltas[2] = { - [theEvent deltaX], - [theEvent deltaZ] - }; - - mDeltaUpdateCallback(mouseDeltas, 0); - - NSPoint mPoint = [theEvent locationInWindow]; - mMousePos[0] = mPoint.x; - mMousePos[1] = mPoint.y; - mMouseMovedCallback(mMousePos, 0); + if (mDeltaUpdateCallback != nil && mMouseMovedCallback != nil) + { + float mouseDeltas[2] = { + [theEvent deltaX], + [theEvent deltaZ] + }; + + mDeltaUpdateCallback(mouseDeltas, 0); + + NSPoint mPoint = [theEvent locationInWindow]; + mMousePos[0] = mPoint.x; + mMousePos[1] = mPoint.y; + mMouseMovedCallback(mMousePos, 0); + } } - (void) scrollWheel:(NSEvent *)theEvent { - mScrollWhellCallback(-[theEvent deltaY]); + if (mScrollWhellCallback != nil) + { + mScrollWhellCallback(-[theEvent deltaY]); + } } - (void) mouseExited:(NSEvent *)theEvent { - mMouseExitCallback(); + if (mMouseExitCallback != nil) + { + mMouseExitCallback(); + } } - (void) registerKeyDownCallback:(KeyCallback)callback @@ -349,4 +385,14 @@ mDeltaUpdateCallback = callback; } -@end \ No newline at end of file +@end + +void setLLNSWindowRef(LLNSWindow* window) +{ + winRef = window; +} + +void setLLOpenGLViewRef(LLOpenGLView* view) +{ + glviewRef = view; +} diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index 47ae13cb25..abaeda1f91 100644 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -57,7 +57,7 @@ NSWindowRef createNSWindow(int x, int y, int width, int height); #include GLViewRef createOpenGLView(NSWindowRef window); void glSwapBuffers(void* context); -CGLContextObj getCGLContextObj(NSWindowRef window); +CGLContextObj getCGLContextObj(GLViewRef view); void getContentViewBounds(NSWindowRef window, float* bounds); void getWindowSize(NSWindowRef window, float* size); void setWindowSize(NSWindowRef window, int width, int height); @@ -80,5 +80,7 @@ void registerMouseMovedCallback(NSWindowRef window, MouseCallback callback); void registerScrollCallback(NSWindowRef window, ScrollWheelCallback callback); void registerMouseExitCallback(NSWindowRef window, VoidCallback callback); void registerDeltaUpdateCallback(NSWindowRef window, MouseCallback callback); +NSWindowRef getMainAppWindow(); +GLViewRef getGLView(NSWindowRef window); unsigned int getModifiers(); diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index 03c0f55883..07efc25ea6 100644 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -54,10 +54,10 @@ void setupCocoa() // http://developer.apple.com/samplecode/CarbonCocoa_PictureCursor/index.html // Needed for Carbon based applications which call into Cocoa - NSApplicationLoad(); + // NSApplicationLoad(); // Must first call [[[NSWindow alloc] init] release] to get the NSWindow machinery set up so that NSCursor can use a window to cache the cursor image - [[[NSWindow alloc] init] release]; + //[[[NSWindow alloc] init] release]; [pool release]; @@ -188,10 +188,9 @@ void glSwapBuffers(void* context) [(NSOpenGLContext*)context flushBuffer]; } -CGLContextObj getCGLContextObj(NSWindowRef window) +CGLContextObj getCGLContextObj(GLViewRef view) { - LLOpenGLView *glview = [(LLNSWindow*)window contentView]; - return [glview getCGLContextObj]; + return [(LLOpenGLView *)view getCGLContextObj]; } CGLPixelFormatObj* getCGLPixelFormatObj(NSWindowRef window) @@ -331,6 +330,16 @@ void registerDeltaUpdateCallback(NSWindowRef window, MouseCallback callback) [(LLNSWindow*)window registerDeltaUpdateCallback:callback]; } +NSWindowRef getMainAppWindow() +{ + return winRef; +} + +GLViewRef getGLView(NSWindowRef window) +{ + return glviewRef; +} + unsigned int getModifiers() { return [NSEvent modifierFlags]; diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 1fb8bea802..a616b2df2d 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -38,7 +38,6 @@ #include "lldir.h" #include "indra_constants.h" -#include #include extern BOOL gDebugWindowProc; @@ -342,7 +341,7 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits if (mWindow == NULL) { LL_INFOS("Window") << "Creating window..." << LL_ENDL; - mWindow = createNSWindow(x, y, width, height); + mWindow = getMainAppWindow(); LL_INFOS("Window") << "Registering key callbacks..." << LL_ENDL; registerKeyDownCallback(mWindow, callKeyDown); registerKeyUpCallback(mWindow, callKeyUp); @@ -361,9 +360,11 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits if(mContext == NULL) { LL_INFOS("Window") << "Creating GL view..." << LL_ENDL; + // Our OpenGL view is already defined within SecondLife.xib. + // Get the view instead. mGLView = createOpenGLView(mWindow); registerResizeEventCallback(mGLView, callResize); - mContext = getCGLContextObj(mWindow); + mContext = getCGLContextObj(mGLView); // Since we just created the context, it needs to be set up. glNeedsInit = TRUE; } @@ -577,132 +578,6 @@ void LLWindowMacOSX::gatherInput() stopDockTileBounce(); } - EventRecord evt; - while(WaitNextEvent(everyEvent, &evt, 0, NULL)) - { - // printf("WaitNextEvent returned true, event is %d.\n", evt.what); - switch(evt.what) - { - case mouseDown: - { - short part; - WindowRef window; - long selectResult; - part = FindWindow(evt.where, &window); - switch ( part ) - { - case inMenuBar: - selectResult = MenuSelect(evt.where); - - HiliteMenu(0); - break; - } - } - break; - - case kHighLevelEvent: - AEProcessAppleEvent (&evt); - break; - - case updateEvt: - // We shouldn't be getting these regularly (since our window will be buffered), but we need to handle them correctly... - BeginUpdate((WindowRef)evt.message); - EndUpdate((WindowRef)evt.message); - break; - - } - } - /* - U32 event = getLatestEvent(mWindow); - switch (event) { - case 0: - // Nothing's happened since our last handled event. - break; - - case 1: - { - gKeyboard->handleKeyDown(getKeyDown(mWindow), getModifiers(mWindow)); - mCallbacks->handleUnicodeChar(getLastCharacter(mWindow), gKeyboard->currentMask(FALSE)); // currentMask has the appropriately translated modifiers. - mLastModifiers = gKeyboard->currentMask(FALSE); - } - break; - - case 2: - gKeyboard->handleKeyUp(getKeyUp(mWindow), getModifiers(mWindow)); - mLastModifiers = gKeyboard->currentMask(FALSE); - break; - - case 3: - break; - - case 4: - { - LLCoordScreen inCoords; - LLCoordGL outCoords; - float* mouseCoords = getMouseDown(mWindow); - inCoords.mX = llround(mouseCoords[0]); - inCoords.mY = llround(mouseCoords[1]); - convertCoords(inCoords, &outCoords); - mCallbacks->handleMouseDown(this, outCoords, getModifiers(mWindow)); - mLastModifiers = gKeyboard->currentMask(FALSE); - } - break; - case 5: - { - LLCoordScreen inCoords; - LLCoordGL outCoords; - float* mouseCoords = getMouseUp(mWindow); - inCoords.mX = llround(mouseCoords[0]); - inCoords.mY = llround(mouseCoords[1]); - convertCoords(inCoords, &outCoords); - mCallbacks->handleMouseUp(this, outCoords, getModifiers(mWindow)); - mLastModifiers = gKeyboard->currentMask(FALSE); - } - break; - case 6: - { - LLCoordScreen inCoords; - LLCoordGL outCoords; - float* mouseCoords = getRightMouseDown(mWindow); - inCoords.mX = llround(mouseCoords[0]); - inCoords.mY = llround(mouseCoords[1]); - convertCoords(inCoords, &outCoords); - mCallbacks->handleRightMouseDown(this, outCoords, getModifiers(mWindow)); - mLastModifiers = gKeyboard->currentMask(FALSE); - } - break; - case 7: - { - LLCoordScreen inCoords; - LLCoordGL outCoords; - float* mouseCoords = getRightMouseDown(mWindow); - inCoords.mX = llround(mouseCoords[0]); - inCoords.mY = llround(mouseCoords[1]); - convertCoords(inCoords, &outCoords); - mCallbacks->handleRightMouseDown(this, outCoords, getModifiers(mWindow)); - mLastModifiers = gKeyboard->currentMask(FALSE); - } - break; - case 8: // Double click - { - LLCoordScreen inCoords; - LLCoordGL outCoords; - float* mouseCoords = getRightMouseDown(mWindow); - inCoords.mX = llround(mouseCoords[0]); - inCoords.mY = llround(mouseCoords[1]); - convertCoords(inCoords, &outCoords); - mCallbacks->handleDoubleClick(this, outCoords, getModifiers(mWindow)); - mLastModifiers = gKeyboard->currentMask(FALSE); - } - break; - case 10: // Text input (for IMEs) - - break; - default: - break; - - }*/ - updateCursor(); } diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h index a821dcabd8..487af7658f 100644 --- a/indra/llwindow/llwindowmacosx.h +++ b/indra/llwindow/llwindowmacosx.h @@ -33,8 +33,6 @@ #include "lltimer.h" -//#include -//#include #include #include diff --git a/indra/media_plugins/webkit/mac_volume_catcher.cpp b/indra/media_plugins/webkit/mac_volume_catcher.cpp index 8a06bb8487..2f3f2211a3 100644 --- a/indra/media_plugins/webkit/mac_volume_catcher.cpp +++ b/indra/media_plugins/webkit/mac_volume_catcher.cpp @@ -35,7 +35,6 @@ #include "volume_catcher.h" -#include #include #include diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index dff2c04fbc..73f5ecc38c 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1231,6 +1231,10 @@ source_group("CMake Rules" FILES ViewerInstall.cmake) if (DARWIN) LIST(APPEND viewer_SOURCE_FILES llappviewermacosx.cpp) + LIST(APPEND viewer_SOURCE_FILES llappviewermacosx-objc.h) + LIST(APPEND viewer_SOURCE_FILES llappviewermacosx-objc.mm) + LIST(APPEND viewer_SOURCE_FILES llappviewermacosx-delegate.h) + LIST(APPEND viewer_SOURCE_FILES llappviewermacosx-delegate.mm) find_library(AGL_LIBRARY AGL) find_library(APPKIT_LIBRARY AppKit) @@ -1251,7 +1255,7 @@ if (DARWIN) macview.r gpu_table.txt Info-SecondLife.plist - SecondLife.nib/ + SecondLife.xib/ # CMake doesn't seem to support Xcode language variants well just yet English.lproj/InfoPlist.strings English.lproj/language.txt diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist index f7b11b217c..5db52f040f 100644 --- a/indra/newview/Info-SecondLife.plist +++ b/indra/newview/Info-SecondLife.plist @@ -61,6 +61,10 @@ CFBundleVersion 2.1.0.13828 + NSPrincipalClass + NSApplication + NSMainNibFile + SecondLife CSResourcesFileMapped diff --git a/indra/newview/SecondLife.nib/classes.nib b/indra/newview/SecondLife.nib/classes.nib deleted file mode 100644 index ea58db1189..0000000000 --- a/indra/newview/SecondLife.nib/classes.nib +++ /dev/null @@ -1,4 +0,0 @@ -{ -IBClasses = (); -IBVersion = 1; -} diff --git a/indra/newview/SecondLife.nib/info.nib b/indra/newview/SecondLife.nib/info.nib deleted file mode 100644 index 1b531de104..0000000000 --- a/indra/newview/SecondLife.nib/info.nib +++ /dev/null @@ -1,23 +0,0 @@ - - - - - IBDocumentLocation - 85 13 356 240 0 0 1280 1002 - IBEditorPositions - - 29 - 27 314 247 44 0 0 1280 1002 - - IBFramework Version - 362.0 - IBOpenObjects - - 191 - - IBSystem Version - 7D24 - targetFramework - IBCarbonFramework - - diff --git a/indra/newview/SecondLife.nib/objects.xib b/indra/newview/SecondLife.nib/objects.xib deleted file mode 100644 index b7ff30f2b2..0000000000 --- a/indra/newview/SecondLife.nib/objects.xib +++ /dev/null @@ -1,259 +0,0 @@ - - - IBCarbonFramework - - NSApplication - - - - SecondLife - - - Second Life - - Second Life - - - TRUE - TRUE - About Second Life - 0 - abou - - - _NSAppleMenu - - - - File - - File - - - - Edit - - Edit - - - TRUE - Undo - z - undo - - - TRUE - Redo - Z - redo - - - TRUE - - - TRUE - Cut - x - cut - - - TRUE - Copy - c - copy - - - TRUE - Paste - v - past - - - TRUE - Delete - clea - - - TRUE - Select All - a - sall - - - TRUE - - - TRUE - Special Characters… - chrp - - - - - - Window - - Window - - - TRUE - TRUE - Minimize Window - m - mini - - - TRUE - TRUE - Minimize All Windows - m - 1572864 - mina - - - TRUE - Zoom - zoom - - - TRUE - - - TRUE - TRUE - Bring All to Front - bfrt - - - TRUE - TRUE - Arrange in Front - 1572864 - frnt - - - _NSWindowsMenu - - - - _NSMainMenu - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 0 482 694 - 0 0 694 482 - - - 442 604 462 674 - 604 442 70 20 - OK - ok - - 2 - 2 - - 1 - - - 20 20 422 674 - 20 20 654 402 - - - 20 20 422 659 - 0 0 639 402 - text - 5 - TRUE - - - FALSE - - - - - 84 72 566 766 - Release Notes - - FALSE - FALSE - FALSE - FALSE - FALSE - FALSE - TRUE - TRUE - 4 - 1 - FALSE - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Files Owner - - MenuBar - - Release Notes - - - 202 - diff --git a/indra/newview/SecondLife.xib b/indra/newview/SecondLife.xib new file mode 100644 index 0000000000..2fc83bd009 --- /dev/null +++ b/indra/newview/SecondLife.xib @@ -0,0 +1,1848 @@ + + + + 1060 + 12C60 + 2844 + 1187.34 + 625.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 2844 + + + NSCustomObject + NSMenu + NSMenuItem + NSView + NSWindowTemplate + + + com.apple.InterfaceBuilder.CocoaPlugin + + + PluginDependencyRecalculationVersion + + + + + NSApplication + + + FirstResponder + + + NSApplication + + + Main Menu + + + + Second Life + + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + Second Life + + + + About Second Life + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Preferences… + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Services + + 2147483647 + + + submenuAction: + + Services + + _NSServicesMenu + + + + + YES + YES + + + 2147483647 + + + + + + Hide NewApplication + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Quit NewApplication + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 2147483647 + + + submenuAction: + + File + + + + New + n + 1048576 + 2147483647 + + + + + + Open… + o + 1048576 + 2147483647 + + + + + + Open Recent + + 2147483647 + + + submenuAction: + + Open Recent + + + + Clear Menu + + 2147483647 + + + + + _NSRecentDocumentsMenu + + + + + YES + YES + + + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + Save… + s + 1048576 + 2147483647 + + + + + + Revert to Saved + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Page Setup... + P + 1179648 + 2147483647 + + + + + + + Print… + p + 1048576 + 2147483647 + + + + + + + + + Edit + + 2147483647 + + + submenuAction: + + Edit + + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Paste and Match Style + V + 1572864 + 2147483647 + + + + + + Delete + + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Find + + 2147483647 + + + submenuAction: + + Find + + + + Find… + f + 1048576 + 2147483647 + + + 1 + + + + Find and Replace… + f + 1572864 + 2147483647 + + + 12 + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + + + + Find Previous + G + 1048576 + 2147483647 + + + 3 + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + + + + Jump to Selection + j + 1048576 + 2147483647 + + + + + + + + + Spelling and Grammar + + 2147483647 + + + submenuAction: + + Spelling + + + + Show Spelling and Grammar + : + 1048576 + 2147483647 + + + + + + Check Document Now + ; + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Check Spelling While Typing + + 2147483647 + + + + + + Check Grammar With Spelling + + 2147483647 + + + + + + Correct Spelling Automatically + + 2147483647 + + + + + + + + + Substitutions + + 2147483647 + + + submenuAction: + + Substitutions + + + + Show Substitutions + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Smart Copy/Paste + + 2147483647 + + + + + + Smart Quotes + + 2147483647 + + + + + + Smart Dashes + + 2147483647 + + + + + + Smart Links + + 2147483647 + + + + + + Data Detectors + + 2147483647 + + + + + + Text Replacement + + 2147483647 + + + + + + + + + Transformations + + 2147483647 + + + submenuAction: + + Transformations + + + + Make Upper Case + + 2147483647 + + + + + + Make Lower Case + + 2147483647 + + + + + + Capitalize + + 2147483647 + + + + + + + + + Speech + + 2147483647 + + + submenuAction: + + Speech + + + + Start Speaking + + 2147483647 + + + + + + Stop Speaking + + 2147483647 + + + + + + + + + + + + Window + + 2147483647 + + + submenuAction: + + Window + + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 2147483647 + + + + + + Enter Full Screen + f + 1310720 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Bring All to Front + + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 2147483647 + + + submenuAction: + + Help + + + + NewApplication Help + ? + 1048576 + 2147483647 + + + + + _NSHelpMenu + + + + _NSMainMenu + + + LLAppDelegate + + + 15 + 2 + {{196, 240}, {1024, 768}} + 74974208 + Second Life + LLNSWindow + + + {1024, 768} + + + 256 + + {1024, 768} + + + + _NS:20 + + {{0, 0}, {1920, 1178}} + {1024, 790} + {10000000000000, 10000000000000} + 128 + YES + + + + + + + terminate: + + + + 823 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + delegate + + + + 845 + + + + performMiniaturize: + + + + 37 + + + + arrangeInFront: + + + + 39 + + + + print: + + + + 86 + + + + runPageLayout: + + + + 87 + + + + clearRecentDocuments: + + + + 127 + + + + performClose: + + + + 193 + + + + performZoom: + + + + 240 + + + + showHelp: + + + + 360 + + + + saveDocument: + + + + 362 + + + + revertDocumentToSaved: + + + + 364 + + + + hide: + + + + 369 + + + + hideOtherApplications: + + + + 370 + + + + unhideAllApplications: + + + + 372 + + + + cut: + + + + 768 + + + + paste: + + + + 769 + + + + toggleSmartInsertDelete: + + + + 770 + + + + toggleAutomaticDashSubstitution: + + + + 773 + + + + toggleContinuousSpellChecking: + + + + 774 + + + + toggleAutomaticDataDetection: + + + + 775 + + + + undo: + + + + 776 + + + + startSpeaking: + + + + 778 + + + + showGuessPanel: + + + + 779 + + + + checkSpelling: + + + + 780 + + + + copy: + + + + 782 + + + + delete: + + + + 783 + + + + selectAll: + + + + 785 + + + + stopSpeaking: + + + + 786 + + + + orderFrontSubstitutionsPanel: + + + + 787 + + + + toggleAutomaticTextReplacement: + + + + 788 + + + + toggleAutomaticSpellingCorrection: + + + + 790 + + + + toggleFullScreen: + + + + 842 + + + + window + + + + 850 + + + + + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + + + + + + + + Main Menu + + + 19 + + + + + + + + 56 + + + + + + + + 103 + + + + + + + + 83 + + + + + + + + 81 + + + + + + + + + + + + + + + + + 75 + + + + + 78 + + + + + 72 + + + + + 82 + + + + + 124 + + + + + + + + 77 + + + + + 73 + + + + + 79 + + + + + 112 + + + + + 74 + + + + + 125 + + + + + + + + 126 + + + + + 106 + + + + + + + + 111 + + + + + 57 + + + + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + + + 144 + + + + + 129 + + + + + 143 + + + + + 236 + + + + + 131 + + + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 24 + + + + + + + + + + + + 92 + + + + + 5 + + + + + 239 + + + + + 23 + + + + + 711 + + + + + + + + 712 + + + + + + + + + + + + + + + + + + + + + + 713 + + + + + 714 + + + + + 715 + + + + + 716 + + + + + 717 + + + + + 718 + + + + + 719 + + + + + 720 + + + + + 721 + + + + + 722 + + + + + 723 + + + + + + + + 724 + + + + + + + + 725 + + + + + + + + 726 + + + + + + + + 727 + + + + + + + + 738 + + + + + + + + + 739 + + + + + 740 + + + + + 741 + + + + + + + + + + 742 + + + + + 743 + + + + + 744 + + + + + 745 + + + + + + + + + + + + + + + 746 + + + + + 747 + + + + + 748 + + + + + 749 + + + + + 750 + + + + + 751 + + + + + 752 + + + + + 753 + + + + + 754 + + + + + + + + + + + + + 755 + + + + + 756 + + + + + 757 + + + + + 758 + + + + + 759 + + + + + 760 + + + + + 761 + + + + + + + + + + + + + 762 + + + + + 763 + + + + + 764 + + + + + 765 + + + + + 766 + + + + + 821 + + + + + 824 + + + + + 841 + + + + + 828 + + + + + + + + 829 + + + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + + 852 + + + + + LLAppDelegate + NSObject + + LLOpenGLView + LLNSWindow + + + + glview + LLOpenGLView + + + window + LLNSWindow + + + + IBProjectSource + ./Classes/LLAppDelegate.h + + + + LLNSWindow + NSWindow + + IBProjectSource + ./Classes/LLNSWindow.h + + + + LLOpenGLView + NSOpenGLView + + IBProjectSource + ./Classes/LLOpenGLView.h + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + YES + 3 + + {11, 11} + {10, 3} + + YES + + diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 30f82926f1..6a87f7306d 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -250,10 +250,6 @@ static LLAppViewerListener sAppViewerListener(LLAppViewer::instance); //---------------------------------------------------------------------------- // viewer.cpp - these are only used in viewer, should be easily moved. -#if LL_DARWIN -extern void init_apple_menu(const char* product); -#endif // LL_DARWIN - extern BOOL gRandomizeFramerate; extern BOOL gPeriodicSlowFrame; extern BOOL gDebugGL; @@ -1196,43 +1192,56 @@ static LLFastTimer::DeclareTimer FTM_SERVICE_CALLBACK("Callback"); static LLFastTimer::DeclareTimer FTM_AGENT_AUTOPILOT("Autopilot"); static LLFastTimer::DeclareTimer FTM_AGENT_UPDATE("Update"); +LLMemType mt1(LLMemType::MTYPE_MAIN); + bool LLAppViewer::mainLoop() { - LLMemType mt1(LLMemType::MTYPE_MAIN); - mMainloopTimeout = new LLWatchdogTimeout(); + if (!mMainLoopInitialized) + { + mMainloopTimeout = new LLWatchdogTimeout(); + + //------------------------------------------- + // Run main loop until time to quit + //------------------------------------------- + + // Create IO Pump to use for HTTP Requests. + gServicePump = new LLPumpIO(gAPRPoolp); + LLHTTPClient::setPump(*gServicePump); + LLCurl::setCAFile(gDirUtilp->getCAFile()); + + // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated. + + LLVoiceChannel::initClass(); + LLVoiceClient::getInstance()->init(gServicePump); + LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLCallFloater::sOnCurrentChannelChanged, _1), true); + + joystick = LLViewerJoystick::getInstance(); + joystick->setNeedsReset(true); + + + // As we do not (yet) send data on the mainloop LLEventPump that varies + // with each frame, no need to instantiate a new LLSD event object each + // time. Obviously, if that changes, just instantiate the LLSD at the + // point of posting. + mMainLoopInitialized = true; + } + LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop")); + + LLSD newFrame; - //------------------------------------------- - // Run main loop until time to quit - //------------------------------------------- - - // Create IO Pump to use for HTTP Requests. - gServicePump = new LLPumpIO(gAPRPoolp); - LLHTTPClient::setPump(*gServicePump); - LLCurl::setCAFile(gDirUtilp->getCAFile()); - - // Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated. - - LLVoiceChannel::initClass(); - LLVoiceClient::getInstance()->init(gServicePump); - LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLCallFloater::sOnCurrentChannelChanged, _1), true); LLTimer frameTimer,idleTimer; LLTimer debugTime; - LLViewerJoystick* joystick(LLViewerJoystick::getInstance()); - joystick->setNeedsReset(true); - - LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop")); - // As we do not (yet) send data on the mainloop LLEventPump that varies - // with each frame, no need to instantiate a new LLSD event object each - // time. Obviously, if that changes, just instantiate the LLSD at the - // point of posting. - LLSD newFrame; - + //LLPrivateMemoryPoolTester::getInstance()->run(false) ; //LLPrivateMemoryPoolTester::getInstance()->run(true) ; //LLPrivateMemoryPoolTester::destroy() ; // Handle messages +#ifdef LL_DARWIN + if (!LLApp::isExiting()) +#else while (!LLApp::isExiting()) +#endif { LLFastTimer::nextFrame(); // Should be outside of any timer instances @@ -1510,34 +1519,37 @@ bool LLAppViewer::mainLoop() } } - // Save snapshot for next time, if we made it through initialization - if (STATE_STARTED == LLStartUp::getStartupState()) + if (LLApp::isExiting()) { - try + // Save snapshot for next time, if we made it through initialization + if (STATE_STARTED == LLStartUp::getStartupState()) { - saveFinalSnapshot(); - } - catch(std::bad_alloc) - { - llwarns << "Bad memory allocation when saveFinalSnapshot() is called!" << llendl ; - - //stop memory leaking simulation - LLFloaterMemLeak* mem_leak_instance = - LLFloaterReg::findTypedInstance("mem_leaking"); - if(mem_leak_instance) + try { - mem_leak_instance->stop() ; - } + saveFinalSnapshot(); + } + catch(std::bad_alloc) + { + llwarns << "Bad memory allocation when saveFinalSnapshot() is called!" << llendl ; + + //stop memory leaking simulation + LLFloaterMemLeak* mem_leak_instance = + LLFloaterReg::findTypedInstance("mem_leaking"); + if(mem_leak_instance) + { + mem_leak_instance->stop() ; + } + } } + + delete gServicePump; + + destroyMainloopTimeout(); + + llinfos << "Exiting main_loop" << llendflush; } - - delete gServicePump; - - destroyMainloopTimeout(); - - llinfos << "Exiting main_loop" << llendflush; - return true; + return LLApp::isExiting(); } void LLAppViewer::flushVFSIO() @@ -2618,8 +2630,6 @@ bool LLAppViewer::initConfiguration() //} #if LL_DARWIN - // Initialize apple menubar and various callbacks - init_apple_menu(LLTrans::getString("APP_NAME").c_str()); #if __ppc__ // If the CPU doesn't have Altivec (i.e. it's not at least a G4), don't go any further. diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 7a474f9122..a09bdb2496 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -41,6 +41,7 @@ class LLImageDecodeThread; class LLTextureFetch; class LLWatchdogTimeout; class LLUpdaterService; +class LLViewerJoystick; class LLAppViewer : public LLApp { @@ -250,6 +251,8 @@ private: std::string mSerialNumber; bool mPurgeCache; bool mPurgeOnExit; + bool mMainLoopInitialized; + LLViewerJoystick* joystick; bool mSavedFinalSnapshot; bool mSavePerAccountSettings; // only save per account settings if login succeeded diff --git a/indra/newview/llappviewermacosx-delegate.h b/indra/newview/llappviewermacosx-delegate.h new file mode 100644 index 0000000000..ac234c14be --- /dev/null +++ b/indra/newview/llappviewermacosx-delegate.h @@ -0,0 +1,24 @@ +// +// LLAppDelegate.h +// SecondLife +// +// Created by Geenz on 12/16/12. +// +// + +#import +#import "llopenglview-objc.h" +#include "llappviewermacosx-objc.h" + +@interface LLAppDelegate : NSObject { + LLNSWindow *window; + LLOpenGLView *glview; + NSTimer *frameTimer; +} + +@property (assign) IBOutlet LLNSWindow *window; +@property (assign) IBOutlet LLOpenGLView *glview; + +- (void) mainLoop; + +@end diff --git a/indra/newview/llappviewermacosx-delegate.mm b/indra/newview/llappviewermacosx-delegate.mm new file mode 100644 index 0000000000..80cc1010e9 --- /dev/null +++ b/indra/newview/llappviewermacosx-delegate.mm @@ -0,0 +1,49 @@ +// +// LLAppDelegate.m +// SecondLife +// +// Created by Geenz on 12/16/12. +// +// + +#import "llappviewermacosx-delegate.h" + +@implementation LLAppDelegate + +@synthesize window; +@synthesize glview; + +- (void)dealloc +{ + [super dealloc]; +} + +- (void) applicationDidFinishLaunching:(NSNotification *)notification +{ + frameTimer = nil; + + setLLNSWindowRef([self window]); + setLLOpenGLViewRef([self glview]); + if (initViewer()) + { + frameTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/60 target:self selector:@selector(mainLoop) userInfo:nil repeats:YES]; + } else { + handleQuit(); + } +} + +- (void) applicationWillTerminate:(NSNotification *)notification +{ +} + +- (void) mainLoop +{ + bool appExiting = runMainLoop(); + if (appExiting) + { + [frameTimer release]; + handleQuit(); + } +} + +@end diff --git a/indra/newview/llappviewermacosx-objc.h b/indra/newview/llappviewermacosx-objc.h new file mode 100644 index 0000000000..9ece6a1a6a --- /dev/null +++ b/indra/newview/llappviewermacosx-objc.h @@ -0,0 +1,19 @@ +// +// NSObject_llappviewermacosx_objc.h +// SecondLife +// +// Created by Geenz on 12/16/12. +// +// + +#include +typedef std::tr1::function VoidCallback; +typedef void* ViewerAppRef; + +int createNSApp(int argc, const char **argv); + +bool initViewer(); +void handleQuit(); +bool runMainLoop(); +void initMainLoop(); +void destroyMainLoop(); \ No newline at end of file diff --git a/indra/newview/llappviewermacosx-objc.mm b/indra/newview/llappviewermacosx-objc.mm new file mode 100644 index 0000000000..ca2090b790 --- /dev/null +++ b/indra/newview/llappviewermacosx-objc.mm @@ -0,0 +1,20 @@ +// +// llappviewermacosx.m +// SecondLife +// +// Created by Geenz on 12/12/12. +// +// + +#import +#import +#include "llappviewermacosx-objc.h" +#import "llappviewermacosx-delegate.h" + +int createNSApp(int argc, const char *argv[]) +{ + return NSApplicationMain(argc, argv); +} + + + diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index c2916717bd..a1c8b7699d 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -31,6 +31,7 @@ #endif #include "llappviewermacosx.h" +#include "llappviewermacosx-objc.h" #include "llcommandlineparser.h" #include "llmemtype.h" @@ -53,7 +54,7 @@ namespace int gArgC; char** gArgV; - bool sCrashReporterIsRunning = false; + LLAppViewerMacOSX* gViewerAppPtr; OSErr AEQuitHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn) { @@ -65,55 +66,61 @@ namespace } } -int main( int argc, char **argv ) +bool initViewer() { LLMemType mt1(LLMemType::MTYPE_STARTUP); - -#if LL_SOLARIS && defined(__sparc) - asm ("ta\t6"); // NOTE: Make sure memory alignment is enforced on SPARC -#endif - + // Set the working dir to /Contents/Resources if (chdir(gDirUtilp->getAppRODataDir().c_str()) == -1) { llwarns << "Could not change directory to " - << gDirUtilp->getAppRODataDir() << ": " << strerror(errno) - << llendl; + << gDirUtilp->getAppRODataDir() << ": " << strerror(errno) + << llendl; } - - LLAppViewerMacOSX* viewer_app_ptr = new LLAppViewerMacOSX(); - - viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash); - - // Store off the command line args for use later. - gArgC = argc; - gArgV = argv; - bool ok = viewer_app_ptr->init(); + gViewerAppPtr = new LLAppViewerMacOSX(); + + gViewerAppPtr->setErrorHandler(LLAppViewer::handleViewerCrash); + + + + bool ok = gViewerAppPtr->init(); if(!ok) { llwarns << "Application init failed." << llendl; - return -1; } + + return ok; +} - // Run the application main loop - if(!LLApp::isQuitting()) +void handleQuit() +{ + if(!LLApp::isError()) { - viewer_app_ptr->mainLoop(); + gViewerAppPtr->cleanup(); } + + delete gViewerAppPtr; + gViewerAppPtr = NULL; +} - if (!LLApp::isError()) +bool runMainLoop() +{ + bool ret = LLApp::isQuitting(); + if (!ret) { - // - // We don't want to do cleanup here if the error handler got called - - // the assumption is that the error handler is responsible for doing - // app cleanup if there was a problem. - // - viewer_app_ptr->cleanup(); + ret = gViewerAppPtr->mainLoop(); } - delete viewer_app_ptr; - viewer_app_ptr = NULL; - return 0; + + return ret; +} + +int main( int argc, char **argv ) +{ + // Store off the command line args for use later. + gArgC = argc; + gArgV = argv; + return createNSApp(argc, (const char**)argv); } LLAppViewerMacOSX::LLAppViewerMacOSX() @@ -258,33 +265,6 @@ bool LLAppViewerMacOSX::restoreErrorTrap() return reset_count == 0; } -static OSStatus CarbonEventHandler(EventHandlerCallRef inHandlerCallRef, - EventRef inEvent, - void* inUserData) -{ - ProcessSerialNumber psn; - - GetEventParameter(inEvent, - kEventParamProcessID, - typeProcessSerialNumber, - NULL, - sizeof(psn), - NULL, - &psn); - - if( GetEventKind(inEvent) == kEventAppTerminated ) - { - Boolean matching_psn = FALSE; - OSErr os_result = SameProcess(&psn, (ProcessSerialNumber*)inUserData, &matching_psn); - if(os_result >= 0 && matching_psn) - { - sCrashReporterIsRunning = false; - QuitApplicationEventLoop(); - } - } - return noErr; -} - void LLAppViewerMacOSX::handleCrashReporting(bool reportFreeze) { // This used to use fork&exec, but is switched to LSOpenApplication to @@ -306,72 +286,6 @@ void LLAppViewerMacOSX::handleCrashReporting(bool reportFreeze) appParams.version = 0; appParams.flags = kLSLaunchNoParams | kLSLaunchStartClassic; appParams.application = &appRef; - - if(reportFreeze) - { - // Make sure freeze reporting launches the crash logger synchronously, lest - // Log files get changed by SL while the logger is running. - - // *NOTE:Mani A better way - make a copy of the data that the crash reporter will send - // and let SL go about its business. This way makes the mac work like windows and linux - // and is the smallest patch for the issue. - sCrashReporterIsRunning = false; - ProcessSerialNumber o_psn; - - static EventHandlerRef sCarbonEventsRef = NULL; - static const EventTypeSpec kEvents[] = - { - { kEventClassApplication, kEventAppTerminated } - }; - - // Install the handler to detect crash logger termination - InstallEventHandler(GetApplicationEventTarget(), - (EventHandlerUPP) CarbonEventHandler, - GetEventTypeCount(kEvents), - kEvents, - &o_psn, - &sCarbonEventsRef - ); - - // Remove, temporarily the quit handler - which has *crash* behavior before - // the mainloop gets running! - AERemoveEventHandler(kCoreEventClass, - kAEQuitApplication, - NewAEEventHandlerUPP(AEQuitHandler), - false); - - // Launch the crash reporter. - os_result = LSOpenApplication(&appParams, &o_psn); - - if(os_result >= 0) - { - sCrashReporterIsRunning = true; - } - - while(sCrashReporterIsRunning) - { - RunApplicationEventLoop(); - } - - // Re-install the apps quit handler. - AEInstallEventHandler(kCoreEventClass, - kAEQuitApplication, - NewAEEventHandlerUPP(AEQuitHandler), - 0, - false); - - // Remove the crash reporter quit handler. - RemoveEventHandler(sCarbonEventsRef); - } - else - { - appParams.flags |= kLSLaunchAsync; - clear_signals(); - - ProcessSerialNumber o_psn; - os_result = LSOpenApplication(&appParams, &o_psn); - } - } } @@ -505,73 +419,3 @@ OSErr AEGURLHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn) return(result); } - -OSStatus simpleDialogHandler(EventHandlerCallRef handler, EventRef event, void *userdata) -{ - OSStatus result = eventNotHandledErr; - OSStatus err; - UInt32 evtClass = GetEventClass(event); - UInt32 evtKind = GetEventKind(event); - WindowRef window = (WindowRef)userdata; - - if((evtClass == kEventClassCommand) && (evtKind == kEventCommandProcess)) - { - HICommand cmd; - err = GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL, sizeof(cmd), NULL, &cmd); - - if(err == noErr) - { - switch(cmd.commandID) - { - case kHICommandOK: - QuitAppModalLoopForWindow(window); - result = noErr; - break; - - case kHICommandCancel: - QuitAppModalLoopForWindow(window); - result = userCanceledErr; - break; - } - } - } - - return(result); -} - -void init_apple_menu(const char* product) -{ - // Load up a proper menu bar. - { - OSStatus err; - IBNibRef nib = NULL; - // NOTE: DO NOT translate or brand this string. It's an internal name in the .nib file, and MUST match exactly. - err = CreateNibReference(CFSTR("SecondLife"), &nib); - - if(err == noErr) - { - // NOTE: DO NOT translate or brand this string. It's an internal name in the .nib file, and MUST match exactly. - SetMenuBarFromNib(nib, CFSTR("MenuBar")); - } - - if(nib != NULL) - { - DisposeNibReference(nib); - } - } - - // Install a handler for 'gurl' AppleEvents. This is how secondlife:// URLs get passed to the viewer. - - if(AEInstallEventHandler('GURL', 'GURL', NewAEEventHandlerUPP(AEGURLHandler),0, false) != noErr) - { - // Couldn't install AppleEvent handler. This error shouldn't be fatal. - llinfos << "Couldn't install 'GURL' AppleEvent handler. Continuing..." << llendl; - } - - // Install a handler for 'quit' AppleEvents. This makes quitting the application from the dock work. - if(AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, NewAEEventHandlerUPP(AEQuitHandler),0, false) != noErr) - { - // Couldn't install AppleEvent handler. This error shouldn't be fatal. - llinfos << "Couldn't install Quit AppleEvent handler. Continuing..." << llendl; - } -} diff --git a/indra/newview/macutil_Prefix.h b/indra/newview/macutil_Prefix.h index b54a764a62..b8df961cac 100644 --- a/indra/newview/macutil_Prefix.h +++ b/indra/newview/macutil_Prefix.h @@ -32,7 +32,6 @@ * */ -#include #include "fix_macros.h" #undef verify -- cgit v1.3 From ddb48d51d996b18063b111faa3b7e709160074d9 Mon Sep 17 00:00:00 2001 From: Geenz Date: Tue, 1 Jan 2013 11:32:53 -0500 Subject: More things in this commit: - Removed the callback system in favor of simply defining functions in a header to later be implemented in whichever file is most convenient for what we want to do (i.e., calling LLWindow callbacks within LLWindowMacOSX, setting cursors in llwindowmacosx-objc.mm, etc.) - Viewer shutdown now works appropriately - Added a bit of debugging code to test if a key has been handled by the UI or not (useful for tracking down the mystery of the enter key not being handled) - Setup a cocoa quit handler within the application delegate that intercepts any termination requests --- indra/llwindow/llopenglview-objc.h | 30 ---- indra/llwindow/llopenglview-objc.mm | 214 ++++++++++------------------ indra/llwindow/llwindowmacosx-objc.h | 38 +++-- indra/llwindow/llwindowmacosx-objc.mm | 74 ++-------- indra/llwindow/llwindowmacosx.cpp | 73 +++++++--- indra/llwindow/llwindowmacosx.h | 2 +- indra/newview/llappviewermacosx-delegate.mm | 18 ++- indra/newview/llappviewermacosx-objc.h | 2 +- indra/newview/llappviewermacosx.cpp | 32 ++--- indra/newview/llviewerkeyboard.cpp | 2 +- 10 files changed, 201 insertions(+), 284 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llopenglview-objc.h b/indra/llwindow/llopenglview-objc.h index 6b055bc665..20589e321d 100644 --- a/indra/llwindow/llopenglview-objc.h +++ b/indra/llwindow/llopenglview-objc.h @@ -15,7 +15,6 @@ @interface LLOpenGLView : NSOpenGLView { NSPoint mousePos; - ResizeCallback mResizeCallback; } - (id) initWithFrame:(NSRect)frame withSamples:(NSUInteger)samples andVsync:(BOOL)vsync; @@ -33,42 +32,13 @@ - (CGLContextObj) getCGLContextObj; - (CGLPixelFormatObj*)getCGLPixelFormatObj; -- (void) registerResizeCallback:(ResizeCallback)callback; @end @interface LLNSWindow : NSWindow { float mMousePos[2]; unsigned int mModifiers; - - KeyCallback mKeyDownCallback; - KeyCallback mKeyUpCallback; - UnicodeCallback mUnicodeCallback; - ModifierCallback mModifierCallback; - MouseCallback mMouseDownCallback; - MouseCallback mMouseUpCallback; - MouseCallback mMouseDoubleClickCallback; - MouseCallback mRightMouseDownCallback; - MouseCallback mRightMouseUpCallback; - MouseCallback mMouseMovedCallback; - ScrollWheelCallback mScrollWhellCallback; - VoidCallback mMouseExitCallback; - MouseCallback mDeltaUpdateCallback; } -- (void) registerKeyDownCallback:(KeyCallback)callback; -- (void) registerKeyUpCallback:(KeyCallback)callback; -- (void) registerUnicodeCallback:(UnicodeCallback)callback; -- (void) registerModifierCallback:(ModifierCallback)callback; -- (void) registerMouseDownCallback:(MouseCallback)callback; -- (void) registerMouseUpCallback:(MouseCallback)callback; -- (void) registerRightMouseDownCallback:(MouseCallback)callback; -- (void) registerRightMouseUpCallback:(MouseCallback)callback; -- (void) registerDoubleClickCallback:(MouseCallback)callback; -- (void) registerMouseMovedCallback:(MouseCallback)callback; -- (void) registerScrollCallback:(ScrollWheelCallback)callback; -- (void) registerMouseExitCallback:(VoidCallback)callback; -- (void) registerDeltaUpdateCallback:(MouseCallback)callback; - @end void setLLNSWindowRef(LLNSWindow* window); diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index 7c148f4acd..cb8d7b315f 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -19,12 +19,9 @@ - (void)windowResized:(NSNotification *)notification; { - if (mResizeCallback != nil) - { - NSSize size = [[self window] frame].size; - - mResizeCallback(size.width, size.height); - } + NSSize size = [self frame].size; + + callResize(size.width, size.height); } - (void)dealloc @@ -125,11 +122,6 @@ return (CGLPixelFormatObj*)[fmt CGLPixelFormatObj]; } -- (void) registerResizeCallback:(ResizeCallback)callback -{ - mResizeCallback = callback; -} - // Various events can be intercepted by our view, thus not reaching our window. // Intercept these events, and pass them to the window as needed. - Geenz @@ -183,6 +175,16 @@ [super flagsChanged:theEvent]; } +- (BOOL) becomeFirstResponder +{ + return [super becomeFirstResponder]; +} + +- (BOOL) resignFirstResponder +{ + return [super resignFirstResponder]; +} + @end // We use a custom NSWindow for our event handling. @@ -196,30 +198,19 @@ return self; } -- (void) keyDown:(NSEvent *)theEvent { - if (mKeyDownCallback != nil && mUnicodeCallback != nil) +- (void) keyDown:(NSEvent *)theEvent +{ + callKeyDown([theEvent keyCode], [theEvent modifierFlags]); + + NSString *chars = [theEvent characters]; + for (uint i = 0; i < [chars length]; i++) { - mKeyDownCallback([theEvent keyCode], [theEvent modifierFlags]); - - NSString *chars = [theEvent charactersIgnoringModifiers]; - for (uint i = 0; i < [chars length]; i++) - { - mUnicodeCallback([chars characterAtIndex:i], [theEvent modifierFlags]); - } - - // The viewer expects return to be submitted separately as a unicode character. - if ([theEvent keyCode] == 3 || [theEvent keyCode] == 13) - { - mUnicodeCallback([theEvent keyCode], [theEvent modifierFlags]); - } + callUnicodeCallback([chars characterAtIndex:i], [theEvent modifierFlags]); } } - (void) keyUp:(NSEvent *)theEvent { - if (mKeyUpCallback != nil) - { - mKeyUpCallback([theEvent keyCode], [theEvent modifierFlags]); - } + callKeyUp([theEvent keyCode], [theEvent modifierFlags]); } - (void)flagsChanged:(NSEvent *)theEvent { @@ -228,59 +219,42 @@ - (void) mouseDown:(NSEvent *)theEvent { - if (mMouseDoubleClickCallback != nil && mMouseDownCallback != nil) + if ([theEvent clickCount] >= 2) { - if ([theEvent clickCount] == 2) - { - mMouseDoubleClickCallback(mMousePos, [theEvent modifierFlags]); - } else if ([theEvent clickCount] == 1) { - mMouseDownCallback(mMousePos, [theEvent modifierFlags]); - } + callDoubleClick(mMousePos, [theEvent modifierFlags]); + } else if ([theEvent clickCount] == 1) { + callLeftMouseDown(mMousePos, [theEvent modifierFlags]); } } - (void) mouseUp:(NSEvent *)theEvent { - if (mMouseUpCallback != nil) - { - mMouseUpCallback(mMousePos, [theEvent modifierFlags]); - } + callLeftMouseUp(mMousePos, [theEvent modifierFlags]); } - (void) rightMouseDown:(NSEvent *)theEvent { - if (mRightMouseDownCallback != nil) - { - mRightMouseDownCallback(mMousePos, [theEvent modifierFlags]); - } + callRightMouseDown(mMousePos, [theEvent modifierFlags]); } - (void) rightMouseUp:(NSEvent *)theEvent { - if (mRightMouseUpCallback != nil) - { - mRightMouseUpCallback(mMousePos, [theEvent modifierFlags]); - } + callRightMouseUp(mMousePos, [theEvent modifierFlags]); } -- (void)mouseMoved:(NSEvent *)theEvent { - if (mDeltaUpdateCallback != nil && mMouseMovedCallback != nil) - { - float mouseDeltas[2] = { - [theEvent deltaX], - [theEvent deltaZ] - }; - - mDeltaUpdateCallback(mouseDeltas, 0); - - NSPoint mPoint = [theEvent locationInWindow]; - mMousePos[0] = mPoint.x; - mMousePos[1] = mPoint.y; - if (mMouseMovedCallback != nil) - { - mMouseMovedCallback(mMousePos, 0); - } - } +- (void)mouseMoved:(NSEvent *)theEvent +{ + float mouseDeltas[2] = { + [theEvent deltaX], + [theEvent deltaY] + }; + + callDeltaUpdate(mouseDeltas, 0); + + NSPoint mPoint = [theEvent locationInWindow]; + mMousePos[0] = mPoint.x; + mMousePos[1] = mPoint.y; + callMouseMoved(mMousePos, 0); } // NSWindow doesn't trigger mouseMoved when the mouse is being clicked and dragged. @@ -288,101 +262,59 @@ - (void) mouseDragged:(NSEvent *)theEvent { - if (mDeltaUpdateCallback != nil && mMouseMovedCallback != nil) - { - float mouseDeltas[2] = { - [theEvent deltaX], - [theEvent deltaZ] - }; - - mDeltaUpdateCallback(mouseDeltas, 0); - - NSPoint mPoint = [theEvent locationInWindow]; - mMousePos[0] = mPoint.x; - mMousePos[1] = mPoint.y; - mMouseMovedCallback(mMousePos, 0); - } -} - -- (void) scrollWheel:(NSEvent *)theEvent -{ - if (mScrollWhellCallback != nil) - { - mScrollWhellCallback(-[theEvent deltaY]); - } -} - -- (void) mouseExited:(NSEvent *)theEvent -{ - if (mMouseExitCallback != nil) - { - mMouseExitCallback(); - } -} - -- (void) registerKeyDownCallback:(KeyCallback)callback -{ - mKeyDownCallback = callback; -} - -- (void) registerKeyUpCallback:(KeyCallback)callback -{ - mKeyUpCallback = callback; -} - -- (void) registerUnicodeCallback:(UnicodeCallback)callback -{ - mUnicodeCallback = callback; -} - -- (void) registerModifierCallback:(ModifierCallback)callback -{ - mModifierCallback = callback; -} - -- (void) registerMouseDownCallback:(MouseCallback)callback -{ - mMouseDownCallback = callback; -} - -- (void) registerMouseUpCallback:(MouseCallback)callback -{ - mMouseUpCallback = callback; + // Trust the deltas supplied by NSEvent. + // The old CoreGraphics APIs we previously relied on are now flagged as obsolete. + // NSEvent isn't obsolete, and provides us with the correct deltas. + float mouseDeltas[2] = { + [theEvent deltaX], + [theEvent deltaY] + }; + + callDeltaUpdate(mouseDeltas, 0); + + NSPoint mPoint = [theEvent locationInWindow]; + mMousePos[0] = mPoint.x; + mMousePos[1] = mPoint.y; + callMouseMoved(mMousePos, 0); } -- (void) registerRightMouseDownCallback:(MouseCallback)callback +- (void) otherMouseDown:(NSEvent *)theEvent { - mRightMouseDownCallback = callback; + callMiddleMouseDown(mMousePos, 0); } -- (void) registerRightMouseUpCallback:(MouseCallback)callback +- (void) otherMouseUp:(NSEvent *)theEvent { - mRightMouseUpCallback = callback; + callMiddleMouseUp(mMousePos, 0); } -- (void) registerDoubleClickCallback:(MouseCallback)callback +- (void) otherMouseDragged:(NSEvent *)theEvent { - mMouseDoubleClickCallback = callback; + } -- (void) registerMouseMovedCallback:(MouseCallback)callback +- (void) scrollWheel:(NSEvent *)theEvent { - mMouseMovedCallback = callback; + callScrollMoved(-[theEvent deltaY]); } -- (void) registerScrollCallback:(ScrollWheelCallback)callback +- (void) mouseExited:(NSEvent *)theEvent { - mScrollWhellCallback = callback; + callMouseExit(); } -- (void) registerMouseExitCallback:(VoidCallback)callback +- (BOOL) becomeFirstResponder { - mMouseExitCallback = callback; + NSLog(@"Window gained focus!"); + callFocus(); + return true; } -- (void) registerDeltaUpdateCallback:(MouseCallback)callback +- (BOOL) resignFirstResponder { - mDeltaUpdateCallback = callback; + NSLog(@"Window lost focus!"); + callFocus(); + return true; } @end diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index abaeda1f91..655d63ac12 100644 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -65,21 +65,33 @@ void getCursorPos(NSWindowRef window, float* pos); void makeWindowOrderFront(NSWindowRef window); void convertScreenToWindow(NSWindowRef window, float *coord); void convertWindowToScreen(NSWindowRef window, float *coord); +void convertScreenToView(NSWindowRef window, float *coord); void setWindowPos(NSWindowRef window, float* pos); +void closeWindow(NSWindowRef window); +void removeGLView(GLViewRef view); + +// These are all implemented in llwindowmacosx.cpp. +// This is largely for easier interop between Obj-C and C++ (at least in the viewer's case due to the BOOL vs. BOOL conflict) +void callKeyUp(unsigned short key, unsigned int mask); +void callKeyDown(unsigned short key, unsigned int mask); +void callUnicodeCallback(wchar_t character, unsigned int mask); +void callRightMouseDown(float *pos, unsigned int mask); +void callRightMouseUp(float *pos, unsigned int mask); +void callLeftMouseDown(float *pos, unsigned int mask); +void callLeftMouseUp(float *pos, unsigned int mask); +void callDoubleClick(float *pos, unsigned int mask); +void callResize(unsigned int width, unsigned int height); +void callMouseMoved(float *pos, unsigned int mask); +void callScrollMoved(float delta); +void callMouseExit(); +void callWindowFocus(); +void callWindowUnfocus(); +void callDeltaUpdate(float *delta, unsigned int mask); +void callMiddleMouseDown(float *pos, unsigned int mask); +void callMiddleMouseUp(float *pos, unsigned int mask); +void callFocus(); +void callFocusLost(); -void registerKeyUpCallback(NSWindowRef window, KeyCallback callback); -void registerKeyDownCallback(NSWindowRef window, KeyCallback callback); -void registerUnicodeCallback(NSWindowRef window, UnicodeCallback callback); -void registerMouseUpCallback(NSWindowRef window, MouseCallback callback); -void registerMouseDownCallback(NSWindowRef window, MouseCallback callback); -void registerRightMouseUpCallback(NSWindowRef window, MouseCallback callback); -void registerRightMouseDownCallback(NSWindowRef window, MouseCallback callback); -void registerDoubleClickCallback(NSWindowRef window, MouseCallback callback); -void registerResizeEventCallback(GLViewRef window, ResizeCallback callback); -void registerMouseMovedCallback(NSWindowRef window, MouseCallback callback); -void registerScrollCallback(NSWindowRef window, ScrollWheelCallback callback); -void registerMouseExitCallback(NSWindowRef window, VoidCallback callback); -void registerDeltaUpdateCallback(NSWindowRef window, MouseCallback callback); NSWindowRef getMainAppWindow(); GLViewRef getGLView(NSWindowRef window); diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index 07efc25ea6..f3972303f1 100644 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -255,6 +255,15 @@ void convertScreenToWindow(NSWindowRef window, float *coord) coord[1] = point.y; } +void convertScreenToView(NSWindowRef window, float *coord) +{ + NSRect point; + point.origin.x = coord[0]; + point.origin.y = coord[1]; + point.origin = [(LLNSWindow*)window convertScreenToBase:point.origin]; + point.origin = [[(LLNSWindow*)window contentView] convertPoint:point.origin fromView:nil]; +} + void convertWindowToScreen(NSWindowRef window, float *coord) { NSPoint point; @@ -265,73 +274,20 @@ void convertWindowToScreen(NSWindowRef window, float *coord) coord[1] = point.y; } -void registerKeyUpCallback(NSWindowRef window, std::tr1::function callback) -{ - [(LLNSWindow*)window registerKeyUpCallback:callback]; -} - -void registerKeyDownCallback(NSWindowRef window, std::tr1::function callback) -{ - [(LLNSWindow*)window registerKeyDownCallback:callback]; -} - -void registerUnicodeCallback(NSWindowRef window, std::tr1::function callback) -{ - [(LLNSWindow*)window registerUnicodeCallback:callback]; -} - -void registerMouseUpCallback(NSWindowRef window, MouseCallback callback) -{ - [(LLNSWindow*)window registerMouseUpCallback:callback]; -} - -void registerMouseDownCallback(NSWindowRef window, MouseCallback callback) -{ - [(LLNSWindow*)window registerMouseDownCallback:callback]; -} - -void registerRightMouseUpCallback(NSWindowRef window, MouseCallback callback) -{ - [(LLNSWindow*)window registerRightMouseUpCallback:callback]; -} - -void registerRightMouseDownCallback(NSWindowRef window, MouseCallback callback) -{ - [(LLNSWindow*)window registerRightMouseDownCallback:callback]; -} - -void registerDoubleClickCallback(NSWindowRef window, MouseCallback callback) -{ - [(LLNSWindow*)window registerDoubleClickCallback:callback]; -} - -void registerResizeEventCallback(GLViewRef glview, ResizeCallback callback) -{ - [(LLOpenGLView*)glview registerResizeCallback:callback]; -} - -void registerMouseMovedCallback(NSWindowRef window, MouseCallback callback) -{ - [(LLNSWindow*)window registerMouseMovedCallback:callback]; -} - -void registerScrollCallback(NSWindowRef window, ScrollWheelCallback callback) -{ - [(LLNSWindow*)window registerScrollCallback:callback]; -} - -void registerMouseExitCallback(NSWindowRef window, VoidCallback callback) +void closeWindow(NSWindowRef window) { - [(LLNSWindow*)window registerMouseExitCallback:callback]; + [(LLNSWindow*)window close]; } -void registerDeltaUpdateCallback(NSWindowRef window, MouseCallback callback) +void removeGLView(GLViewRef view) { - [(LLNSWindow*)window registerDeltaUpdateCallback:callback]; + [(LLOpenGLView*)view removeFromSuperview]; + [(LLOpenGLView*)view release]; } NSWindowRef getMainAppWindow() { + [(LLNSWindow*)winRef setAcceptsMouseMovedEvents:TRUE]; return winRef; } diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index a616b2df2d..cfdfbe2138 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -198,7 +198,7 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks, } -// These functions are used as callbacks for event handling within Cocoa. +// These functions are used as wrappers for our internal event handling callbacks. // It's a good idea to wrap these to avoid reworking more code than we need to within LLWindow. void callKeyUp(unsigned short key, unsigned int mask) @@ -216,9 +216,14 @@ void callUnicodeCallback(wchar_t character, unsigned int mask) gWindowImplementation->getCallbacks()->handleUnicodeChar(character, mask); } -void callModifierCallback(unsigned int mask) +void callFocus() { - + gWindowImplementation->getCallbacks()->handleFocus(gWindowImplementation); +} + +void callFocusLost() +{ + gWindowImplementation->getCallbacks()->handleFocusLost(gWindowImplementation); } void callRightMouseDown(float *pos, MASK mask) @@ -302,17 +307,41 @@ void callWindowUnfocus() void callDeltaUpdate(float *delta, MASK mask) { - gWindowImplementation->updateMouseDeltas(); + gWindowImplementation->updateMouseDeltas(delta); +} + +void callMiddleMouseDown(float *pos, MASK mask) +{ + LLCoordGL outCoords; + outCoords.mX = llround(pos[0]); + outCoords.mY = llround(pos[1]); + float deltas[2]; + gWindowImplementation->getMouseDeltas(deltas); + outCoords.mX += deltas[0]; + outCoords.mY += deltas[1]; + gWindowImplementation->getCallbacks()->handleMiddleMouseDown(gWindowImplementation, outCoords, mask); +} + +void callMiddleMouseUp(float *pos, MASK mask) +{ + LLCoordGL outCoords; + outCoords.mX = llround(pos[0]); + outCoords.mY = llround(pos[1]); + float deltas[2]; + gWindowImplementation->getMouseDeltas(deltas); + outCoords.mX += deltas[0]; + outCoords.mY += deltas[1]; + gWindowImplementation->getCallbacks()->handleMiddleMouseUp(gWindowImplementation, outCoords, mask); } -void LLWindowMacOSX::updateMouseDeltas() +void LLWindowMacOSX::updateMouseDeltas(float* deltas) { if (mCursorDecoupled) { - CGMouseDelta x, y; - CGGetLastMouseDelta( &x, &y ); - mCursorLastEventDeltaX = x; - mCursorLastEventDeltaY = y; + mCursorLastEventDeltaX = llround(deltas[0]); + mCursorLastEventDeltaY = llround(-deltas[1]); + + if (mCursorIgnoreNextDelta) { @@ -320,6 +349,7 @@ void LLWindowMacOSX::updateMouseDeltas() mCursorLastEventDeltaY = 0; mCursorIgnoreNextDelta = FALSE; } + LL_INFOS("Delta Update") << "Last event delta: " << mCursorLastEventDeltaX << ", " << mCursorLastEventDeltaY << LL_ENDL; } else { mCursorLastEventDeltaX = 0; mCursorLastEventDeltaY = 0; @@ -342,6 +372,7 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits { LL_INFOS("Window") << "Creating window..." << LL_ENDL; mWindow = getMainAppWindow(); + /* LL_INFOS("Window") << "Registering key callbacks..." << LL_ENDL; registerKeyDownCallback(mWindow, callKeyDown); registerKeyUpCallback(mWindow, callKeyUp); @@ -355,6 +386,7 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits registerScrollCallback(mWindow, callScrollMoved); registerDeltaUpdateCallback(mWindow, callDeltaUpdate); registerMouseExitCallback(mWindow, callMouseExit); + */ } if(mContext == NULL) @@ -363,7 +395,7 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits // Our OpenGL view is already defined within SecondLife.xib. // Get the view instead. mGLView = createOpenGLView(mWindow); - registerResizeEventCallback(mGLView, callResize); + //registerResizeEventCallback(mGLView, callResize); mContext = getCGLContextObj(mGLView); // Since we just created the context, it needs to be set up. glNeedsInit = TRUE; @@ -439,9 +471,7 @@ void LLWindowMacOSX::destroyContext() if(mContext != NULL) { LL_DEBUGS("Window") << "destroyContext: unhooking drawable " << LL_ENDL; - CGLSetCurrentContext(NULL); - mContext = NULL; } // Clean up remaining GL state before blowing away window @@ -454,16 +484,25 @@ void LLWindowMacOSX::destroyContext() mPixelFormat = NULL; } - // Close the window - if(mWindow != NULL) - { - } - // Clean up the GL context if(mContext != NULL) { CGLDestroyContext(mContext); } + + // Destroy our LLOpenGLView + if(mGLView != NULL) + { + removeGLView(mGLView); + mGLView = NULL; + } + + // Close the window + if(mWindow != NULL) + { + closeWindow(mWindow); + mWindow = NULL; + } } diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h index 487af7658f..c5e1b2290b 100644 --- a/indra/llwindow/llwindowmacosx.h +++ b/indra/llwindow/llwindowmacosx.h @@ -121,7 +121,7 @@ public: void* getWindow() { return mWindow; } LLWindowCallbacks* getCallbacks() { return mCallbacks; } - void updateMouseDeltas(); + void updateMouseDeltas(float* deltas); void getMouseDeltas(float* delta); diff --git a/indra/newview/llappviewermacosx-delegate.mm b/indra/newview/llappviewermacosx-delegate.mm index 80cc1010e9..2e25997d32 100644 --- a/indra/newview/llappviewermacosx-delegate.mm +++ b/indra/newview/llappviewermacosx-delegate.mm @@ -23,17 +23,26 @@ frameTimer = nil; setLLNSWindowRef([self window]); - setLLOpenGLViewRef([self glview]); + //setLLOpenGLViewRef([self glview]); if (initViewer()) { - frameTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/60 target:self selector:@selector(mainLoop) userInfo:nil repeats:YES]; + frameTimer = [NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(mainLoop) userInfo:nil repeats:YES]; } else { handleQuit(); } } -- (void) applicationWillTerminate:(NSNotification *)notification +- (NSApplicationDelegateReply) applicationShouldTerminate:(NSApplication *)sender { + if (!runMainLoop()) + { + handleQuit(); + return NSTerminateCancel; + } else { + [frameTimer release]; + cleanupViewer(); + return NSTerminateNow; + } } - (void) mainLoop @@ -42,7 +51,8 @@ if (appExiting) { [frameTimer release]; - handleQuit(); + cleanupViewer(); + [[NSApplication sharedApplication] terminate:self]; } } diff --git a/indra/newview/llappviewermacosx-objc.h b/indra/newview/llappviewermacosx-objc.h index 9ece6a1a6a..ed9017ca5d 100644 --- a/indra/newview/llappviewermacosx-objc.h +++ b/indra/newview/llappviewermacosx-objc.h @@ -16,4 +16,4 @@ bool initViewer(); void handleQuit(); bool runMainLoop(); void initMainLoop(); -void destroyMainLoop(); \ No newline at end of file +void cleanupViewer(); \ No newline at end of file diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index a1c8b7699d..6e7b91347b 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -55,15 +55,6 @@ namespace char** gArgV; LLAppViewerMacOSX* gViewerAppPtr; - - OSErr AEQuitHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn) - { - OSErr result = noErr; - - LLAppViewer::instance()->userQuit(); - - return(result); - } } bool initViewer() @@ -95,26 +86,33 @@ bool initViewer() void handleQuit() { - if(!LLApp::isError()) - { - gViewerAppPtr->cleanup(); - } - - delete gViewerAppPtr; - gViewerAppPtr = NULL; + LLAppViewer::instance()->userQuit(); } bool runMainLoop() { bool ret = LLApp::isQuitting(); - if (!ret) + if (!ret && gViewerAppPtr != NULL) { ret = gViewerAppPtr->mainLoop(); + } else { + ret = true; } return ret; } +void cleanupViewer() +{ + if(!LLApp::isError()) + { + gViewerAppPtr->cleanup(); + } + + delete gViewerAppPtr; + gViewerAppPtr = NULL; +} + int main( int argc, char **argv ) { // Store off the command line args for use later. diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index 6d91dad70e..92d8f2937e 100644 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -654,7 +654,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; - LL_INFOS("Keyboard Handling") << "Keyboard has focus? " << gFocusMgr.getKeyboardFocus() << LL_ENDL; // check for re-map EKeyboardMode mode = gViewerKeyboard.getMode(); U32 keyidx = (translated_mask<<16) | translated_key; @@ -677,6 +676,7 @@ BOOL LLViewerKeyboard::handleKey(KEY translated_key, MASK translated_mask, BOOL if(mKeysSkippedByUI.find(translated_key) != mKeysSkippedByUI.end()) { mKeyHandledByUI[translated_key] = FALSE; + LL_INFOS("Keyboard Handling") << "Key wasn't handled by UI!" << LL_ENDL; } else { -- cgit v1.3 From 2b0f50dd821848d18ab35095623c3bdbcdeb910c Mon Sep 17 00:00:00 2001 From: Geenz Date: Wed, 2 Jan 2013 15:57:21 -0500 Subject: Crash on exit fix + general code cleanup in LLWindowMacOSX. --- indra/llwindow/llwindowmacosx.cpp | 21 ++------------------- indra/newview/llappviewermacosx-delegate.mm | 1 - 2 files changed, 2 insertions(+), 20 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index cfdfbe2138..cc0959edf8 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -283,6 +283,7 @@ void callMouseMoved(float *pos, MASK mask) outCoords.mX += deltas[0]; outCoords.mY += deltas[1]; gWindowImplementation->getCallbacks()->handleMouseMove(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); + } void callScrollMoved(float delta) @@ -339,9 +340,7 @@ void LLWindowMacOSX::updateMouseDeltas(float* deltas) if (mCursorDecoupled) { mCursorLastEventDeltaX = llround(deltas[0]); - mCursorLastEventDeltaY = llround(-deltas[1]); - - + mCursorLastEventDeltaY = llround(deltas[1]); if (mCursorIgnoreNextDelta) { @@ -372,21 +371,6 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits { LL_INFOS("Window") << "Creating window..." << LL_ENDL; mWindow = getMainAppWindow(); - /* - LL_INFOS("Window") << "Registering key callbacks..." << LL_ENDL; - registerKeyDownCallback(mWindow, callKeyDown); - registerKeyUpCallback(mWindow, callKeyUp); - registerUnicodeCallback(mWindow, callUnicodeCallback); - registerMouseDownCallback(mWindow, callLeftMouseDown); - registerMouseUpCallback(mWindow, callLeftMouseUp); - registerRightMouseDownCallback(mWindow, callRightMouseDown); - registerRightMouseUpCallback(mWindow, callRightMouseUp); - registerDoubleClickCallback(mWindow, callDoubleClick); - registerMouseMovedCallback(mWindow, callMouseMoved); - registerScrollCallback(mWindow, callScrollMoved); - registerDeltaUpdateCallback(mWindow, callDeltaUpdate); - registerMouseExitCallback(mWindow, callMouseExit); - */ } if(mContext == NULL) @@ -395,7 +379,6 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits // Our OpenGL view is already defined within SecondLife.xib. // Get the view instead. mGLView = createOpenGLView(mWindow); - //registerResizeEventCallback(mGLView, callResize); mContext = getCGLContextObj(mGLView); // Since we just created the context, it needs to be set up. glNeedsInit = TRUE; diff --git a/indra/newview/llappviewermacosx-delegate.mm b/indra/newview/llappviewermacosx-delegate.mm index 2e25997d32..5c54736993 100644 --- a/indra/newview/llappviewermacosx-delegate.mm +++ b/indra/newview/llappviewermacosx-delegate.mm @@ -51,7 +51,6 @@ if (appExiting) { [frameTimer release]; - cleanupViewer(); [[NSApplication sharedApplication] terminate:self]; } } -- cgit v1.3 From 9ce3ab1a5248423eeea4d843bfb8407ed62b305e Mon Sep 17 00:00:00 2001 From: Geenz Date: Wed, 2 Jan 2013 18:53:44 -0500 Subject: Fixed the enter and return keys not being sent appropriately as unicode characters. --- indra/llwindow/llkeyboardmacosx.cpp | 2 +- indra/llwindow/llopenglview-objc.mm | 14 +++++++++++++- indra/llwindow/llwindowmacosx-objc.h | 2 +- indra/llwindow/llwindowmacosx-objc.mm | 2 +- indra/llwindow/llwindowmacosx.cpp | 5 ++++- indra/newview/SecondLife.nib | Bin 15670 -> 15670 bytes indra/newview/SecondLife.xib | 2 +- indra/newview/llappviewermacosx-delegate.h | 2 -- indra/newview/llappviewermacosx-delegate.mm | 3 +-- 9 files changed, 22 insertions(+), 10 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llkeyboardmacosx.cpp b/indra/llwindow/llkeyboardmacosx.cpp index 3f357c600e..077ebea909 100644 --- a/indra/llwindow/llkeyboardmacosx.cpp +++ b/indra/llwindow/llkeyboardmacosx.cpp @@ -206,7 +206,7 @@ MASK LLKeyboardMacOSX::updateModifiers(const U32 mask) out_mask |= MASK_SHIFT; } - if(mask & (MAC_CTRL_KEY | MAC_CMD_KEY)) + if(mask & MAC_CTRL_KEY || mask & MAC_CMD_KEY) { out_mask |= MASK_CONTROL; } diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index cb8d7b315f..e5e198b856 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -30,6 +30,11 @@ [super dealloc]; } +- (id) init +{ + return [self initWithFrame:[self bounds] withSamples:2 andVsync:TRUE]; +} + - (id) initWithFrame:(NSRect)frame withSamples:(NSUInteger)samples andVsync:(BOOL)vsync { @@ -205,7 +210,14 @@ NSString *chars = [theEvent characters]; for (uint i = 0; i < [chars length]; i++) { - callUnicodeCallback([chars characterAtIndex:i], [theEvent modifierFlags]); + // Enter and Return are special cases. + unichar returntest = [chars characterAtIndex:i]; + if ((returntest == NSCarriageReturnCharacter || returntest == NSEnterCharacter) && !([theEvent modifierFlags] & NSCommandKeyMask) && !([theEvent modifierFlags] & NSAlternateKeyMask) && !([theEvent modifierFlags] & NSControlKeyMask)) + { + callUnicodeCallback(returntest, 0); + } else { + callUnicodeCallback([chars characterAtIndex:i], [theEvent modifierFlags]); + } } } diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index 655d63ac12..414491f948 100644 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -93,6 +93,6 @@ void callFocus(); void callFocusLost(); NSWindowRef getMainAppWindow(); -GLViewRef getGLView(NSWindowRef window); +GLViewRef getGLView(); unsigned int getModifiers(); diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index f3972303f1..5a024eda46 100644 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -291,7 +291,7 @@ NSWindowRef getMainAppWindow() return winRef; } -GLViewRef getGLView(NSWindowRef window) +GLViewRef getGLView() { return glviewRef; } diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index cc0959edf8..902391e170 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -270,7 +270,10 @@ void callDoubleClick(float *pos, MASK mask) void callResize(unsigned int width, unsigned int height) { - gWindowImplementation->getCallbacks()->handleResize(gWindowImplementation, width, height); + if (gWindowImplementation != NULL) + { + gWindowImplementation->getCallbacks()->handleResize(gWindowImplementation, width, height); + } } void callMouseMoved(float *pos, MASK mask) diff --git a/indra/newview/SecondLife.nib b/indra/newview/SecondLife.nib index b2495036a6..cd69b1b812 100644 Binary files a/indra/newview/SecondLife.nib and b/indra/newview/SecondLife.nib differ diff --git a/indra/newview/SecondLife.xib b/indra/newview/SecondLife.xib index 2fc83bd009..212bc5830d 100644 --- a/indra/newview/SecondLife.xib +++ b/indra/newview/SecondLife.xib @@ -1787,7 +1787,7 @@ - 852 + 864 diff --git a/indra/newview/llappviewermacosx-delegate.h b/indra/newview/llappviewermacosx-delegate.h index ac234c14be..848ccbde62 100644 --- a/indra/newview/llappviewermacosx-delegate.h +++ b/indra/newview/llappviewermacosx-delegate.h @@ -12,12 +12,10 @@ @interface LLAppDelegate : NSObject { LLNSWindow *window; - LLOpenGLView *glview; NSTimer *frameTimer; } @property (assign) IBOutlet LLNSWindow *window; -@property (assign) IBOutlet LLOpenGLView *glview; - (void) mainLoop; diff --git a/indra/newview/llappviewermacosx-delegate.mm b/indra/newview/llappviewermacosx-delegate.mm index 5c54736993..7baeeb1de8 100644 --- a/indra/newview/llappviewermacosx-delegate.mm +++ b/indra/newview/llappviewermacosx-delegate.mm @@ -11,7 +11,6 @@ @implementation LLAppDelegate @synthesize window; -@synthesize glview; - (void)dealloc { @@ -23,7 +22,7 @@ frameTimer = nil; setLLNSWindowRef([self window]); - //setLLOpenGLViewRef([self glview]); + if (initViewer()) { frameTimer = [NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(mainLoop) userInfo:nil repeats:YES]; -- cgit v1.3 From 09b07e3619a71f142c1a3af41244d756e1230142 Mon Sep 17 00:00:00 2001 From: Geenz Date: Tue, 8 Jan 2013 16:22:54 -0500 Subject: Big change set: - LLAppDelegate header relocated to LLWindow. Definition is still present in secondlife-bin (for compatibility reasons when loading a nib). - Return key handling fixed. - Command key now acts the same as the control key by issuing control character codes when the command key is pressed. - We now retrieve the window pointer directly from the app delegate in LLWindow. --- indra/llwindow/CMakeLists.txt | 1 + indra/llwindow/llappdelegate-objc.h | 22 ++++++ indra/llwindow/llkeyboardmacosx.cpp | 35 ++------- indra/llwindow/llopenglview-objc.h | 5 -- indra/llwindow/llopenglview-objc.mm | 113 +++++++++++++++++++--------- indra/llwindow/llwindowmacosx-objc.h | 11 +++ indra/llwindow/llwindowmacosx-objc.mm | 56 ++++++++++---- indra/llwindow/llwindowmacosx.cpp | 22 +++--- indra/newview/CMakeLists.txt | 8 +- indra/newview/llappdelegate-objc.mm | 55 ++++++++++++++ indra/newview/llappviewermacosx-delegate.h | 22 ------ indra/newview/llappviewermacosx-delegate.mm | 57 -------------- indra/newview/llappviewermacosx-objc.h | 19 ----- indra/newview/llappviewermacosx-objc.mm | 20 ----- indra/newview/llappviewermacosx.cpp | 2 +- 15 files changed, 232 insertions(+), 216 deletions(-) create mode 100644 indra/llwindow/llappdelegate-objc.h create mode 100644 indra/newview/llappdelegate-objc.mm delete mode 100644 indra/newview/llappviewermacosx-delegate.h delete mode 100644 indra/newview/llappviewermacosx-delegate.mm delete mode 100644 indra/newview/llappviewermacosx-objc.h delete mode 100644 indra/newview/llappviewermacosx-objc.mm (limited to 'indra/llwindow') diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt index 8a38db751e..84e0169826 100644 --- a/indra/llwindow/CMakeLists.txt +++ b/indra/llwindow/CMakeLists.txt @@ -82,6 +82,7 @@ if (DARWIN) llwindowmacosx.h llwindowmacosx-objc.h llopenglview-objc.h + llappdelegate-objc.h ) # We use a bunch of deprecated system APIs. diff --git a/indra/llwindow/llappdelegate-objc.h b/indra/llwindow/llappdelegate-objc.h new file mode 100644 index 0000000000..56b7a30797 --- /dev/null +++ b/indra/llwindow/llappdelegate-objc.h @@ -0,0 +1,22 @@ +// +// LLAppDelegate.h +// SecondLife +// +// Created by Geenz on 12/16/12. +// +// + +#import +#import "llopenglview-objc.h" +#include "llwindowmacosx-objc.h" + +@interface LLAppDelegate : NSObject { + LLNSWindow *window; + NSTimer *frameTimer; +} + +@property (assign) IBOutlet LLNSWindow *window; + +- (void) mainLoop; + +@end diff --git a/indra/llwindow/llkeyboardmacosx.cpp b/indra/llwindow/llkeyboardmacosx.cpp index 077ebea909..3db94e8835 100644 --- a/indra/llwindow/llkeyboardmacosx.cpp +++ b/indra/llwindow/llkeyboardmacosx.cpp @@ -167,13 +167,15 @@ void LLKeyboardMacOSX::resetMaskKeys() // MBW -- XXX -- This mirrors the operation of the Windows version of resetMaskKeys(). // It looks a bit suspicious, as it won't correct for keys that have been released. // Is this the way it's supposed to work? + + // We apply the modifier masks directly within getModifiers. So check to see which masks we've applied. if(mask & MAC_SHIFT_KEY) { mKeyLevel[KEY_SHIFT] = TRUE; } - if(mask & (MAC_CTRL_KEY)) + if(mask & MAC_CTRL_KEY) { mKeyLevel[KEY_CONTROL] = TRUE; } @@ -198,25 +200,9 @@ static BOOL translateKeyMac(const U16 key, const U32 mask, KEY &outKey, U32 &out MASK LLKeyboardMacOSX::updateModifiers(const U32 mask) { - // translate the mask - MASK out_mask = 0; - - if(mask & MAC_SHIFT_KEY) - { - out_mask |= MASK_SHIFT; - } - - if(mask & MAC_CTRL_KEY || mask & MAC_CMD_KEY) - { - out_mask |= MASK_CONTROL; - } - - if(mask & MAC_ALT_KEY) - { - out_mask |= MASK_ALT; - } - - return out_mask; + // This is handled for us in LLNSWindow on OS X. + + return mask; } BOOL LLKeyboardMacOSX::handleKeyDown(const U16 key, const U32 mask) @@ -231,12 +217,7 @@ BOOL LLKeyboardMacOSX::handleKeyDown(const U16 key, const U32 mask) { handled = handleTranslatedKeyDown(translated_key, translated_mask); } - if (!handled) - { - LL_INFOS("Keyboard") << "Unhandled key: " << mTranslateKeyMap[key] << LL_ENDL; - } else { - LL_INFOS("Keyboard") << "Handled key: " << mTranslateKeyMap[key] << LL_ENDL; - } + return handled; } @@ -272,7 +253,7 @@ MASK LLKeyboardMacOSX::currentMask(BOOL for_mouse_event) if (mask & MAC_CMD_KEY) result |= MASK_CONTROL; } - return result; + return mask; } void LLKeyboardMacOSX::scanKeyboard() diff --git a/indra/llwindow/llopenglview-objc.h b/indra/llwindow/llopenglview-objc.h index 20589e321d..8412621392 100644 --- a/indra/llwindow/llopenglview-objc.h +++ b/indra/llwindow/llopenglview-objc.h @@ -40,8 +40,3 @@ } @end - -void setLLNSWindowRef(LLNSWindow* window); -void setLLOpenGLViewRef(LLOpenGLView* view); -LLNSWindow* winRef; -LLOpenGLView* glviewRef; diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index e5e198b856..d91601152b 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -132,62 +132,72 @@ - (void) mouseDragged:(NSEvent *)theEvent { - [super mouseDragged:theEvent]; + [_window mouseDragged:theEvent]; } - (void) scrollWheel:(NSEvent *)theEvent { - [super scrollWheel:theEvent]; + [_window scrollWheel:theEvent]; } - (void) mouseDown:(NSEvent *)theEvent { - [super mouseDown:theEvent]; + [_window mouseDown:theEvent]; } - (void) mouseUp:(NSEvent *)theEvent { - [super mouseUp:theEvent]; + [_window mouseUp:theEvent]; } - (void) rightMouseDown:(NSEvent *)theEvent { - [super rightMouseDown:theEvent]; + [_window rightMouseDown:theEvent]; } - (void) rightMouseUp:(NSEvent *)theEvent { - [super rightMouseUp:theEvent]; + [_window rightMouseUp:theEvent]; +} + +- (void) otherMouseDown:(NSEvent *)theEvent +{ + [_window otherMouseDown:theEvent]; +} + +- (void) otherMouseUp:(NSEvent *)theEvent +{ + [_window otherMouseUp:theEvent]; } - (void) keyUp:(NSEvent *)theEvent { - [super keyUp:theEvent]; + [_window keyUp:theEvent]; } - (void) keyDown:(NSEvent *)theEvent { - [super keyDown:theEvent]; + [_window keyDown:theEvent]; } - (void) mouseMoved:(NSEvent *)theEvent { - [super mouseMoved:theEvent]; + [_window mouseMoved:theEvent]; } - (void) flagsChanged:(NSEvent *)theEvent { - [super flagsChanged:theEvent]; + [_window flagsChanged:theEvent]; } - (BOOL) becomeFirstResponder { - return [super becomeFirstResponder]; + return [_window becomeFirstResponder]; } - (BOOL) resignFirstResponder { - return [super resignFirstResponder]; + return [_window resignFirstResponder]; } @end @@ -200,58 +210,99 @@ - (id) init { + //[self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType, nil]]; return self; } - (void) keyDown:(NSEvent *)theEvent { - callKeyDown([theEvent keyCode], [theEvent modifierFlags]); - + callKeyDown([theEvent keyCode], mModifiers); NSString *chars = [theEvent characters]; for (uint i = 0; i < [chars length]; i++) { // Enter and Return are special cases. unichar returntest = [chars characterAtIndex:i]; - if ((returntest == NSCarriageReturnCharacter || returntest == NSEnterCharacter) && !([theEvent modifierFlags] & NSCommandKeyMask) && !([theEvent modifierFlags] & NSAlternateKeyMask) && !([theEvent modifierFlags] & NSControlKeyMask)) + if ((returntest == NSCarriageReturnCharacter || returntest == NSEnterCharacter) && + !([theEvent modifierFlags] & NSCommandKeyMask) && + !([theEvent modifierFlags] & NSAlternateKeyMask) && + !([theEvent modifierFlags] & NSControlKeyMask)) { - callUnicodeCallback(returntest, 0); + callUnicodeCallback(13, 0); } else { - callUnicodeCallback([chars characterAtIndex:i], [theEvent modifierFlags]); + // The command key being pressed is also a special case. + // Control + produces an ASCII control character code. + // Command + produces just the character's code. + // Check to see if the command key is pressed, then filter through the different character ranges that are relevant to control characters, and subtract the appropriate range. + if ([theEvent modifierFlags] & NSCommandKeyMask) + { + if (returntest >= 64 && returntest <= 95) + { + callUnicodeCallback(returntest - 63, mModifiers); + } else if (returntest >= 97 && returntest <= 122) + { + callUnicodeCallback(returntest - 96, mModifiers); + } + } else { + callUnicodeCallback(returntest, mModifiers); + } } } } - (void) keyUp:(NSEvent *)theEvent { - callKeyUp([theEvent keyCode], [theEvent modifierFlags]); + callKeyUp([theEvent keyCode], mModifiers); } - (void)flagsChanged:(NSEvent *)theEvent { - mModifiers = [theEvent modifierFlags]; + uint modifiers = [theEvent modifierFlags]; + + // Filter through our modifier keys, and only pick out the ones we care about. + + mModifiers = 0; + if (modifiers & NSCommandKeyMask) + { + mModifiers |= 0x0001; + } + + if (modifiers & NSAlternateKeyMask) + { + mModifiers |= 0x0002; + } + + if (modifiers & NSShiftKeyMask) + { + mModifiers |= 0x0004; + } + + if (modifiers & NSControlKeyMask) + { + mModifiers |= 0x0001; + } } - (void) mouseDown:(NSEvent *)theEvent { if ([theEvent clickCount] >= 2) { - callDoubleClick(mMousePos, [theEvent modifierFlags]); + callDoubleClick(mMousePos, mModifiers); } else if ([theEvent clickCount] == 1) { - callLeftMouseDown(mMousePos, [theEvent modifierFlags]); + callLeftMouseDown(mMousePos, mModifiers); } } - (void) mouseUp:(NSEvent *)theEvent { - callLeftMouseUp(mMousePos, [theEvent modifierFlags]); + callLeftMouseUp(mMousePos, mModifiers); } - (void) rightMouseDown:(NSEvent *)theEvent { - callRightMouseDown(mMousePos, [theEvent modifierFlags]); + callRightMouseDown(mMousePos, mModifiers); } - (void) rightMouseUp:(NSEvent *)theEvent { - callRightMouseUp(mMousePos, [theEvent modifierFlags]); + callRightMouseUp(mMousePos, mModifiers); } - (void)mouseMoved:(NSEvent *)theEvent @@ -292,12 +343,12 @@ - (void) otherMouseDown:(NSEvent *)theEvent { - callMiddleMouseDown(mMousePos, 0); + callMiddleMouseDown(mMousePos, mModifiers); } - (void) otherMouseUp:(NSEvent *)theEvent { - callMiddleMouseUp(mMousePos, 0); + callMiddleMouseUp(mMousePos, mModifiers); } - (void) otherMouseDragged:(NSEvent *)theEvent @@ -330,13 +381,3 @@ } @end - -void setLLNSWindowRef(LLNSWindow* window) -{ - winRef = window; -} - -void setLLOpenGLViewRef(LLOpenGLView* view) -{ - glviewRef = view; -} diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index 414491f948..57b3d11296 100644 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -38,8 +38,19 @@ typedef void *CursorRef; typedef void *NSWindowRef; typedef void *GLViewRef; +// These are defined in llappviewermacosx.cpp. +bool initViewer(); +void handleQuit(); +bool runMainLoop(); +void initMainLoop(); +void cleanupViewer(); + /* Defined in llwindowmacosx-objc.mm: */ +int createNSApp(int argc, const char **argv); void setupCocoa(); +bool pasteBoardAvailable(); +bool copyToPBoard(const unsigned short *str, unsigned int len); +const unsigned short *copyFromPBoard(); CursorRef createImageCursor(const char *fullpath, int hotspotX, int hotspotY); short releaseImageCursor(CursorRef ref); short setImageCursor(CursorRef ref); diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index 5a024eda46..1a64c94b2d 100644 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -29,6 +29,7 @@ #include #include "llwindowmacosx-objc.h" #include "llopenglview-objc.h" +#include "llappdelegate-objc.h" /* * These functions are broken out into a separate file because the @@ -37,6 +38,11 @@ * linden headers with any objective-C++ source. */ +int createNSApp(int argc, const char *argv[]) +{ + return NSApplicationMain(argc, argv); +} + void setupCocoa() { static bool inited = false; @@ -49,15 +55,6 @@ void setupCocoa() // ie. running './secondlife -set Language fr' would cause a pop-up saying can't open document 'fr' // when init'ing the Cocoa App window. [[NSUserDefaults standardUserDefaults] setObject:@"NO" forKey:@"NSTreatUnknownArgumentsAsOpen"]; - - // This is a bit of voodoo taken from the Apple sample code "CarbonCocoa_PictureCursor": - // http://developer.apple.com/samplecode/CarbonCocoa_PictureCursor/index.html - - // Needed for Carbon based applications which call into Cocoa - // NSApplicationLoad(); - - // Must first call [[[NSWindow alloc] init] release] to get the NSWindow machinery set up so that NSCursor can use a window to cache the cursor image - //[[[NSWindow alloc] init] release]; [pool release]; @@ -65,6 +62,38 @@ void setupCocoa() } } +bool copyToPBoard(const unsigned short *str, unsigned int len) +{ + NSPasteboard *pboard = [NSPasteboard generalPasteboard]; + [pboard clearContents]; + + NSArray *contentsToPaste = [[NSArray alloc] initWithObjects:[NSString stringWithCharacters:str length:len], nil]; + + return [pboard writeObjects:contentsToPaste]; +} + +bool pasteBoardAvailable() +{ + NSArray *classArray = [NSArray arrayWithObject:[NSString class]]; + return [[NSPasteboard generalPasteboard] canReadObjectForClasses:classArray options:[NSDictionary dictionary]]; +} + +const unsigned short *copyFromPBoard() +{ + NSPasteboard *pboard = [NSPasteboard generalPasteboard]; + NSArray *classArray = [NSArray arrayWithObject:[NSString class]]; + NSString *str = NULL; + BOOL ok = [pboard canReadObjectForClasses:classArray options:[NSDictionary dictionary]]; + if (ok) + { + NSArray *objToPaste = [pboard readObjectsForClasses:classArray options:[NSDictionary dictionary]]; + str = [objToPaste objectAtIndex:0]; + } + unichar* temp = (unichar*)calloc([str length], sizeof(unichar)); + [str getCharacters:temp]; + return temp; +} + CursorRef createImageCursor(const char *fullpath, int hotspotX, int hotspotY) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -287,15 +316,12 @@ void removeGLView(GLViewRef view) NSWindowRef getMainAppWindow() { - [(LLNSWindow*)winRef setAcceptsMouseMovedEvents:TRUE]; + LLNSWindow *winRef = [(LLAppDelegate*)[[NSApplication sharedApplication] delegate] window]; + + [winRef setAcceptsMouseMovedEvents:TRUE]; return winRef; } -GLViewRef getGLView() -{ - return glviewRef; -} - unsigned int getModifiers() { return [NSEvent modifierFlags]; diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 902391e170..93b9f4c484 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -1029,25 +1029,27 @@ void LLWindowMacOSX::flashIcon(F32 seconds) BOOL LLWindowMacOSX::isClipboardTextAvailable() { - BOOL result = false; - // TODO: Clipboard support. - return result; + return pasteBoardAvailable(); } BOOL LLWindowMacOSX::pasteTextFromClipboard(LLWString &dst) -{ - BOOL result = false; - - // TODO: Clipboard support. - - return result; +{ + llutf16string str(copyFromPBoard()); + dst = utf16str_to_wstring(str); + if (dst != L"") + { + return true; + } else { + return false; + } } BOOL LLWindowMacOSX::copyTextToClipboard(const LLWString &s) { BOOL result = false; + llutf16string utf16str = wstring_to_utf16str(s); - // TODO: Clipboard support. + result = copyToPBoard(utf16str.data(), utf16str.length()); return result; } diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 73f5ecc38c..c60940f93c 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1231,10 +1231,9 @@ source_group("CMake Rules" FILES ViewerInstall.cmake) if (DARWIN) LIST(APPEND viewer_SOURCE_FILES llappviewermacosx.cpp) - LIST(APPEND viewer_SOURCE_FILES llappviewermacosx-objc.h) - LIST(APPEND viewer_SOURCE_FILES llappviewermacosx-objc.mm) - LIST(APPEND viewer_SOURCE_FILES llappviewermacosx-delegate.h) - LIST(APPEND viewer_SOURCE_FILES llappviewermacosx-delegate.mm) + + # This should be compiled with the viewer. + LIST(APPEND viewer_SOURCE_FILES llappdelegate-objc.mm) find_library(AGL_LIBRARY AGL) find_library(APPKIT_LIBRARY AppKit) @@ -1532,6 +1531,7 @@ if (FMOD) if (DARWIN) set(fmodwrapper_SOURCE_FILES fmodwrapper.cpp) add_library(fmodwrapper SHARED ${fmodwrapper_SOURCE_FILES}) + find_library(CARBON_LIBRARY Carbon) set(fmodwrapper_needed_LIBRARIES ${FMOD_LIBRARY} ${CARBON_LIBRARY}) set_target_properties( fmodwrapper diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm new file mode 100644 index 0000000000..f5143d7578 --- /dev/null +++ b/indra/newview/llappdelegate-objc.mm @@ -0,0 +1,55 @@ +// +// LLAppDelegate.m +// SecondLife +// +// Created by Geenz on 12/16/12. +// +// + +#import "llappdelegate-objc.h" + +@implementation LLAppDelegate + +@synthesize window; + +- (void)dealloc +{ + [super dealloc]; +} + +- (void) applicationDidFinishLaunching:(NSNotification *)notification +{ + frameTimer = nil; + + if (initViewer()) + { + frameTimer = [NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(mainLoop) userInfo:nil repeats:YES]; + } else { + handleQuit(); + } +} + +- (NSApplicationDelegateReply) applicationShouldTerminate:(NSApplication *)sender +{ + if (!runMainLoop()) + { + handleQuit(); + return NSTerminateCancel; + } else { + [frameTimer release]; + cleanupViewer(); + return NSTerminateNow; + } +} + +- (void) mainLoop +{ + bool appExiting = runMainLoop(); + if (appExiting) + { + [frameTimer release]; + [[NSApplication sharedApplication] terminate:self]; + } +} + +@end diff --git a/indra/newview/llappviewermacosx-delegate.h b/indra/newview/llappviewermacosx-delegate.h deleted file mode 100644 index 848ccbde62..0000000000 --- a/indra/newview/llappviewermacosx-delegate.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// LLAppDelegate.h -// SecondLife -// -// Created by Geenz on 12/16/12. -// -// - -#import -#import "llopenglview-objc.h" -#include "llappviewermacosx-objc.h" - -@interface LLAppDelegate : NSObject { - LLNSWindow *window; - NSTimer *frameTimer; -} - -@property (assign) IBOutlet LLNSWindow *window; - -- (void) mainLoop; - -@end diff --git a/indra/newview/llappviewermacosx-delegate.mm b/indra/newview/llappviewermacosx-delegate.mm deleted file mode 100644 index 7baeeb1de8..0000000000 --- a/indra/newview/llappviewermacosx-delegate.mm +++ /dev/null @@ -1,57 +0,0 @@ -// -// LLAppDelegate.m -// SecondLife -// -// Created by Geenz on 12/16/12. -// -// - -#import "llappviewermacosx-delegate.h" - -@implementation LLAppDelegate - -@synthesize window; - -- (void)dealloc -{ - [super dealloc]; -} - -- (void) applicationDidFinishLaunching:(NSNotification *)notification -{ - frameTimer = nil; - - setLLNSWindowRef([self window]); - - if (initViewer()) - { - frameTimer = [NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(mainLoop) userInfo:nil repeats:YES]; - } else { - handleQuit(); - } -} - -- (NSApplicationDelegateReply) applicationShouldTerminate:(NSApplication *)sender -{ - if (!runMainLoop()) - { - handleQuit(); - return NSTerminateCancel; - } else { - [frameTimer release]; - cleanupViewer(); - return NSTerminateNow; - } -} - -- (void) mainLoop -{ - bool appExiting = runMainLoop(); - if (appExiting) - { - [frameTimer release]; - [[NSApplication sharedApplication] terminate:self]; - } -} - -@end diff --git a/indra/newview/llappviewermacosx-objc.h b/indra/newview/llappviewermacosx-objc.h deleted file mode 100644 index ed9017ca5d..0000000000 --- a/indra/newview/llappviewermacosx-objc.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// NSObject_llappviewermacosx_objc.h -// SecondLife -// -// Created by Geenz on 12/16/12. -// -// - -#include -typedef std::tr1::function VoidCallback; -typedef void* ViewerAppRef; - -int createNSApp(int argc, const char **argv); - -bool initViewer(); -void handleQuit(); -bool runMainLoop(); -void initMainLoop(); -void cleanupViewer(); \ No newline at end of file diff --git a/indra/newview/llappviewermacosx-objc.mm b/indra/newview/llappviewermacosx-objc.mm deleted file mode 100644 index ca2090b790..0000000000 --- a/indra/newview/llappviewermacosx-objc.mm +++ /dev/null @@ -1,20 +0,0 @@ -// -// llappviewermacosx.m -// SecondLife -// -// Created by Geenz on 12/12/12. -// -// - -#import -#import -#include "llappviewermacosx-objc.h" -#import "llappviewermacosx-delegate.h" - -int createNSApp(int argc, const char *argv[]) -{ - return NSApplicationMain(argc, argv); -} - - - diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index 6e7b91347b..b199405a66 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -31,7 +31,7 @@ #endif #include "llappviewermacosx.h" -#include "llappviewermacosx-objc.h" +#include "llwindowmacosx-objc.h" #include "llcommandlineparser.h" #include "llmemtype.h" -- cgit v1.3 From da90fe352847d5f27358179cb4cdf88abc40a4af Mon Sep 17 00:00:00 2001 From: Geenz Date: Tue, 15 Jan 2013 05:46:31 -0500 Subject: This *should* put an end to our modifier key woes. --- indra/llwindow/llkeyboardmacosx.cpp | 27 +- indra/llwindow/llopenglview-objc.mm | 31 +- indra/newview/SecondLife.nib | Bin 15670 -> 8541 bytes indra/newview/SecondLife.xib | 957 ++---------------------------------- 4 files changed, 68 insertions(+), 947 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llkeyboardmacosx.cpp b/indra/llwindow/llkeyboardmacosx.cpp index 3db94e8835..59cc2acaec 100644 --- a/indra/llwindow/llkeyboardmacosx.cpp +++ b/indra/llwindow/llkeyboardmacosx.cpp @@ -200,9 +200,25 @@ static BOOL translateKeyMac(const U16 key, const U32 mask, KEY &outKey, U32 &out MASK LLKeyboardMacOSX::updateModifiers(const U32 mask) { - // This is handled for us in LLNSWindow on OS X. - - return mask; + // translate the mask + MASK out_mask = 0; + + if(mask & MAC_SHIFT_KEY) + { + out_mask |= MASK_SHIFT; + } + + if(mask & MAC_CTRL_KEY || mask & MAC_CMD_KEY) + { + out_mask |= MASK_CONTROL; + } + + if(mask & MAC_ALT_KEY) + { + out_mask |= MASK_ALT; + } + + return out_mask; } BOOL LLKeyboardMacOSX::handleKeyDown(const U16 key, const U32 mask) @@ -232,6 +248,7 @@ 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); } @@ -252,8 +269,8 @@ MASK LLKeyboardMacOSX::currentMask(BOOL for_mouse_event) { if (mask & MAC_CMD_KEY) result |= MASK_CONTROL; } - - return mask; + + return result; } void LLKeyboardMacOSX::scanKeyboard() diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index d91601152b..25669b25d3 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -190,6 +190,11 @@ [_window flagsChanged:theEvent]; } +- (void) mouseExited:(NSEvent *)theEvent +{ + [_window mouseExited:theEvent]; +} + - (BOOL) becomeFirstResponder { return [_window becomeFirstResponder]; @@ -217,6 +222,7 @@ - (void) keyDown:(NSEvent *)theEvent { callKeyDown([theEvent keyCode], mModifiers); + NSLog(@"Keycode: %hu", [theEvent keyCode]); NSString *chars = [theEvent characters]; for (uint i = 0; i < [chars length]; i++) { @@ -254,30 +260,7 @@ } - (void)flagsChanged:(NSEvent *)theEvent { - uint modifiers = [theEvent modifierFlags]; - - // Filter through our modifier keys, and only pick out the ones we care about. - - mModifiers = 0; - if (modifiers & NSCommandKeyMask) - { - mModifiers |= 0x0001; - } - - if (modifiers & NSAlternateKeyMask) - { - mModifiers |= 0x0002; - } - - if (modifiers & NSShiftKeyMask) - { - mModifiers |= 0x0004; - } - - if (modifiers & NSControlKeyMask) - { - mModifiers |= 0x0001; - } + mModifiers = [theEvent modifierFlags]; } - (void) mouseDown:(NSEvent *)theEvent diff --git a/indra/newview/SecondLife.nib b/indra/newview/SecondLife.nib index cd69b1b812..ca89033300 100644 Binary files a/indra/newview/SecondLife.nib and b/indra/newview/SecondLife.nib differ diff --git a/indra/newview/SecondLife.xib b/indra/newview/SecondLife.xib index 212bc5830d..b4e77279fd 100644 --- a/indra/newview/SecondLife.xib +++ b/indra/newview/SecondLife.xib @@ -193,29 +193,6 @@ - - - Open Recent - - 2147483647 - - - submenuAction: - - Open Recent - - - - Clear Menu - - 2147483647 - - - - - _NSRecentDocumentsMenu - - YES @@ -235,52 +212,6 @@ - - - Save… - s - 1048576 - 2147483647 - - - - - - Revert to Saved - - 2147483647 - - - - - - YES - YES - - - 2147483647 - - - - - - Page Setup... - P - 1179648 - 2147483647 - - - - - - - Print… - p - 1048576 - 2147483647 - - - @@ -350,23 +281,6 @@ - - - Paste and Match Style - V - 1572864 - 2147483647 - - - - - - Delete - - 2147483647 - - - Select All @@ -376,303 +290,6 @@ - - - YES - YES - - - 2147483647 - - - - - - Find - - 2147483647 - - - submenuAction: - - Find - - - - Find… - f - 1048576 - 2147483647 - - - 1 - - - - Find and Replace… - f - 1572864 - 2147483647 - - - 12 - - - - Find Next - g - 1048576 - 2147483647 - - - 2 - - - - Find Previous - G - 1048576 - 2147483647 - - - 3 - - - - Use Selection for Find - e - 1048576 - 2147483647 - - - 7 - - - - Jump to Selection - j - 1048576 - 2147483647 - - - - - - - - - Spelling and Grammar - - 2147483647 - - - submenuAction: - - Spelling - - - - Show Spelling and Grammar - : - 1048576 - 2147483647 - - - - - - Check Document Now - ; - 1048576 - 2147483647 - - - - - - YES - YES - - - 2147483647 - - - - - - Check Spelling While Typing - - 2147483647 - - - - - - Check Grammar With Spelling - - 2147483647 - - - - - - Correct Spelling Automatically - - 2147483647 - - - - - - - - - Substitutions - - 2147483647 - - - submenuAction: - - Substitutions - - - - Show Substitutions - - 2147483647 - - - - - - YES - YES - - - 2147483647 - - - - - - Smart Copy/Paste - - 2147483647 - - - - - - Smart Quotes - - 2147483647 - - - - - - Smart Dashes - - 2147483647 - - - - - - Smart Links - - 2147483647 - - - - - - Data Detectors - - 2147483647 - - - - - - Text Replacement - - 2147483647 - - - - - - - - - Transformations - - 2147483647 - - - submenuAction: - - Transformations - - - - Make Upper Case - - 2147483647 - - - - - - Make Lower Case - - 2147483647 - - - - - - Capitalize - - 2147483647 - - - - - - - - - Speech - - 2147483647 - - - submenuAction: - - Speech - - - - Start Speaking - - 2147483647 - - - - - - Stop Speaking - - 2147483647 - - - - - - @@ -776,13 +393,10 @@ {1024, 768} - + 256 {1024, 768} - - - _NS:20 {{0, 0}, {1920, 1178}} @@ -834,30 +448,6 @@ 39 - - - print: - - - - 86 - - - - runPageLayout: - - - - 87 - - - - clearRecentDocuments: - - - - 127 - performClose: @@ -882,22 +472,6 @@ 360 - - - saveDocument: - - - - 362 - - - - revertDocumentToSaved: - - - - 364 - hide: @@ -938,38 +512,6 @@ 769 - - - toggleSmartInsertDelete: - - - - 770 - - - - toggleAutomaticDashSubstitution: - - - - 773 - - - - toggleContinuousSpellChecking: - - - - 774 - - - - toggleAutomaticDataDetection: - - - - 775 - undo: @@ -978,30 +520,6 @@ 776 - - - startSpeaking: - - - - 778 - - - - showGuessPanel: - - - - 779 - - - - checkSpelling: - - - - 780 - copy: @@ -1010,14 +528,6 @@ 782 - - - delete: - - - - 783 - selectAll: @@ -1026,38 +536,6 @@ 785 - - - stopSpeaking: - - - - 786 - - - - orderFrontSubstitutionsPanel: - - - - 787 - - - - toggleAutomaticTextReplacement: - - - - 788 - - - - toggleAutomaticSpellingCorrection: - - - - 790 - toggleFullScreen: @@ -1150,85 +628,18 @@ 81 - - - - - - - - 75 - - - - - 78 - - - - - 72 - - - - - 82 - - - - - 124 - - - - - - - - 77 - - - 73 - - 79 - - - - - 112 - - - - - 74 - - - - - 125 - - - - - - - - 126 - - - 106 @@ -1373,33 +784,10 @@ - - - - - - - - - - 713 - - - - - 714 - - - - - 715 - - - 716 @@ -1415,251 +803,11 @@ - - 719 - - - - - 720 - - - 721 - - 722 - - - - - 723 - - - - - - - - 724 - - - - - - - - 725 - - - - - - - - 726 - - - - - - - - 727 - - - - - - - - 738 - - - - - - - - - 739 - - - - - 740 - - - - - 741 - - - - - - - - - - 742 - - - - - 743 - - - - - 744 - - - - - 745 - - - - - - - - - - - - - - - 746 - - - - - 747 - - - - - 748 - - - - - 749 - - - - - 750 - - - - - 751 - - - - - 752 - - - - - 753 - - - - - 754 - - - - - - - - - - - - - 755 - - - - - 756 - - - - - 757 - - - - - 758 - - - - - 759 - - - - - 760 - - - - - 761 - - - - - - - - - - - - - 762 - - - - - 763 - - - - - 764 - - - - - 765 - - - - - 766 - - - - - 821 - - - 824 @@ -1684,6 +832,36 @@ + + 713 + + + + + 714 + + + + + 715 + + + + + 82 + + + + + 79 + + + + + 72 + + + @@ -1693,10 +871,6 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -1725,54 +899,12 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin @@ -1794,20 +926,17 @@ LLAppDelegate NSObject - - LLOpenGLView - LLNSWindow - - - - glview - LLOpenGLView - - + + window + LLNSWindow + + + window + window LLNSWindow - + IBProjectSource ./Classes/LLAppDelegate.h @@ -1821,14 +950,6 @@ ./Classes/LLNSWindow.h - - LLOpenGLView - NSOpenGLView - - IBProjectSource - ./Classes/LLOpenGLView.h - - 0 -- cgit v1.3 From 1bbbaf8dd69a08a3e7c570e6ad14f57a4f6e91cb Mon Sep 17 00:00:00 2001 From: Geenz Date: Fri, 18 Jan 2013 13:16:12 -0500 Subject: Partial workaround for mouse delta issue. --- indra/llwindow/llwindowmacosx.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 93b9f4c484..95ad87d58f 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -285,8 +285,9 @@ void callMouseMoved(float *pos, MASK mask) gWindowImplementation->getMouseDeltas(deltas); outCoords.mX += deltas[0]; outCoords.mY += deltas[1]; + LL_INFOS("Mouse Movement") << "Moved coords: " << outCoords.mX << ", " << outCoords.mY << LL_ENDL; gWindowImplementation->getCallbacks()->handleMouseMove(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); - + gWindowImplementation->getCallbacks()->handleScrollWheel(gWindowImplementation, 0); } void callScrollMoved(float delta) @@ -343,7 +344,7 @@ void LLWindowMacOSX::updateMouseDeltas(float* deltas) if (mCursorDecoupled) { mCursorLastEventDeltaX = llround(deltas[0]); - mCursorLastEventDeltaY = llround(deltas[1]); + mCursorLastEventDeltaY = llround(-deltas[1]); if (mCursorIgnoreNextDelta) { @@ -351,7 +352,6 @@ void LLWindowMacOSX::updateMouseDeltas(float* deltas) mCursorLastEventDeltaY = 0; mCursorIgnoreNextDelta = FALSE; } - LL_INFOS("Delta Update") << "Last event delta: " << mCursorLastEventDeltaX << ", " << mCursorLastEventDeltaY << LL_ENDL; } else { mCursorLastEventDeltaX = 0; mCursorLastEventDeltaY = 0; @@ -738,7 +738,7 @@ void LLWindowMacOSX::swapBuffers() F32 LLWindowMacOSX::getGamma() { - F32 result = 1.8; // Default to something sane + F32 result = 2.2; // Default to something sane CGGammaValue redMin; CGGammaValue redMax; -- cgit v1.3 From 29e747c4f17818816c502a3aa653b828e689be4a Mon Sep 17 00:00:00 2001 From: Geenz Date: Tue, 22 Jan 2013 15:37:01 -0500 Subject: And thus, the demonic mouse position conversions from view space to screen space were tamed. --- indra/llcommon/llsys.cpp | 2 +- indra/llwindow/llopenglview-objc.h | 22 +++++++++++++++ indra/llwindow/llopenglview-objc.mm | 50 +++++++++++++++++++++++++++++++++++ indra/llwindow/llwindowmacosx-objc.mm | 2 +- indra/newview/llappviewermacosx.cpp | 2 +- 5 files changed, 75 insertions(+), 3 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index c96f2191f3..2a8eea88b6 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -67,7 +67,7 @@ using namespace llsd; # include # include # include -# include +# include # include # include # include diff --git a/indra/llwindow/llopenglview-objc.h b/indra/llwindow/llopenglview-objc.h index 8412621392..dd2f35aafc 100644 --- a/indra/llwindow/llopenglview-objc.h +++ b/indra/llwindow/llopenglview-objc.h @@ -39,4 +39,26 @@ unsigned int mModifiers; } +- (NSPoint)convertToScreenFromLocalPoint:(NSPoint)point relativeToView:(NSView *)view; +- (NSPoint)flipPoint:(NSPoint)aPoint; + +@end + +@interface NSScreen (PointConversion) + +/* + Returns the screen where the mouse resides + */ ++ (NSScreen *)currentScreenForMouseLocation; + +/* + Allows you to convert a point from global coordinates to the current screen coordinates. + */ +- (NSPoint)convertPointToScreenCoordinates:(NSPoint)aPoint; + +/* + Allows to flip the point coordinates, so y is 0 at the top instead of the bottom. x remains the same + */ +- (NSPoint)flipPoint:(NSPoint)aPoint; + @end diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index 25669b25d3..ca66143b78 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -8,6 +8,35 @@ #import "llopenglview-objc.h" +@implementation NSScreen (PointConversion) + ++ (NSScreen *)currentScreenForMouseLocation +{ + NSPoint mouseLocation = [NSEvent mouseLocation]; + + NSEnumerator *screenEnumerator = [[NSScreen screens] objectEnumerator]; + NSScreen *screen; + while ((screen = [screenEnumerator nextObject]) && !NSMouseInRect(mouseLocation, screen.frame, NO)) + ; + + return screen; +} + +- (NSPoint)convertPointToScreenCoordinates:(NSPoint)aPoint +{ + float normalizedX = fabs(fabs(self.frame.origin.x) - fabs(aPoint.x)); + float normalizedY = aPoint.y - self.frame.origin.y; + + return NSMakePoint(normalizedX, normalizedY); +} + +- (NSPoint)flipPoint:(NSPoint)aPoint +{ + return NSMakePoint(aPoint.x, self.frame.size.height - aPoint.y); +} + +@end + @implementation LLOpenGLView - (void)viewDidMoveToWindow @@ -349,6 +378,27 @@ callMouseExit(); } +- (NSPoint)convertToScreenFromLocalPoint:(NSPoint)point relativeToView:(NSView *)view +{ + NSScreen *currentScreen = [NSScreen currentScreenForMouseLocation]; + if(currentScreen) + { + NSPoint windowPoint = [view convertPoint:point toView:nil]; + NSPoint screenPoint = [[view window] convertBaseToScreen:windowPoint]; + NSPoint flippedScreenPoint = [currentScreen flipPoint:screenPoint]; + flippedScreenPoint.y += [currentScreen frame].origin.y; + + return flippedScreenPoint; + } + + return NSZeroPoint; +} + +- (NSPoint)flipPoint:(NSPoint)aPoint +{ + return NSMakePoint(aPoint.x, self.frame.size.height - aPoint.y); +} + - (BOOL) becomeFirstResponder { NSLog(@"Window gained focus!"); diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index 1a64c94b2d..b6e5767203 100644 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -298,7 +298,7 @@ void convertWindowToScreen(NSWindowRef window, float *coord) NSPoint point; point.x = coord[0]; point.y = coord[1]; - point = [(LLNSWindow*)window convertBaseToScreen:point]; + point = [(LLNSWindow*)window convertToScreenFromLocalPoint:point relativeToView:[(LLNSWindow*)window contentView]]; coord[0] = point.x; coord[1] = point.y; } diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index b199405a66..6e0becb518 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -41,7 +41,7 @@ #include "llmd5.h" #include "llfloaterworldmap.h" #include "llurldispatcher.h" -#include +#include #include "lldir.h" #include #include // for systemwide mute -- cgit v1.3 From 461ab912a58b67579fffdf70ec7e38d682927185 Mon Sep 17 00:00:00 2001 From: Geenz Date: Tue, 22 Jan 2013 19:59:49 -0500 Subject: Initial Cocoa drag and drop support. --- indra/llwindow/llopenglview-objc.h | 1 + indra/llwindow/llopenglview-objc.mm | 50 ++++++++- indra/llwindow/llwindowmacosx-objc.h | 15 ++- indra/llwindow/llwindowmacosx-objc.mm | 6 ++ indra/llwindow/llwindowmacosx.cpp | 186 +++++++++++++--------------------- indra/llwindow/llwindowmacosx.h | 16 +-- 6 files changed, 143 insertions(+), 131 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llopenglview-objc.h b/indra/llwindow/llopenglview-objc.h index dd2f35aafc..1592e6e01d 100644 --- a/indra/llwindow/llopenglview-objc.h +++ b/indra/llwindow/llopenglview-objc.h @@ -15,6 +15,7 @@ @interface LLOpenGLView : NSOpenGLView { NSPoint mousePos; + std::string mLastDraggedUrl; } - (id) initWithFrame:(NSRect)frame withSamples:(NSUInteger)samples andVsync:(BOOL)vsync; diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index ca66143b78..763cf0c981 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -61,12 +61,13 @@ - (id) init { + //[self registerForDraggedTypes:[NSArray arrayWithObjects:NSURLPboardType, NSFilenamesPboardType, nil]]; return [self initWithFrame:[self bounds] withSamples:2 andVsync:TRUE]; } - (id) initWithFrame:(NSRect)frame withSamples:(NSUInteger)samples andVsync:(BOOL)vsync { - + [self registerForDraggedTypes:[NSArray arrayWithObject:NSURLPboardType]]; [self initWithFrame:frame]; // Initialize with a default "safe" pixel format that will work with versions dating back to OS X 10.6. @@ -234,6 +235,49 @@ return [_window resignFirstResponder]; } +- (NSDragOperation) draggingEntered:(id)sender +{ + NSPasteboard *pboard; + NSDragOperation sourceDragMask; + + sourceDragMask = [sender draggingSourceOperationMask]; + + pboard = [sender draggingPasteboard]; + + if ([[pboard types] containsObject:NSURLPboardType]) + { + if (sourceDragMask & NSDragOperationLink) { + NSURL *fileUrl = [[pboard readObjectsForClasses:[NSArray arrayWithObject:[NSURL class]] options:[NSDictionary dictionary]] objectAtIndex:0]; + mLastDraggedUrl = [[fileUrl absoluteString] UTF8String]; + return NSDragOperationLink; + } + } + return NSDragOperationNone; +} + +- (NSDragOperation)draggingUpdated:(id )sender +{ + callHandleDragUpdated(mLastDraggedUrl); + + return NSDragOperationLink; +} + +- (void) draggingExited:(id)sender +{ + callHandleDragExited(mLastDraggedUrl); +} + +- (BOOL)prepareForDragOperation:(id < NSDraggingInfo >)sender +{ + return YES; +} + +- (BOOL) performDragOperation:(id)sender +{ + callHandleDragDropped(mLastDraggedUrl); + return true; +} + @end // We use a custom NSWindow for our event handling. @@ -244,7 +288,7 @@ - (id) init { - //[self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType, nil]]; + return self; } @@ -378,6 +422,8 @@ callMouseExit(); } + + - (NSPoint)convertToScreenFromLocalPoint:(NSPoint)point relativeToView:(NSView *)view { NSScreen *currentScreen = [NSScreen currentScreenForMouseLocation]; diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index 57b3d11296..ebc1633f9d 100644 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -24,14 +24,6 @@ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ -#include -typedef std::tr1::function KeyCallback; -typedef std::tr1::function ModifierCallback; -typedef std::tr1::function MouseCallback; -typedef std::tr1::function UnicodeCallback; -typedef std::tr1::function ResizeCallback; -typedef std::tr1::function ScrollWheelCallback; -typedef std::tr1::function VoidCallback; // This will actually hold an NSCursor*, but that type is only available in objective C. typedef void *CursorRef; @@ -59,6 +51,7 @@ void setIBeamCursor(); void setPointingHandCursor(); void setCopyCursor(); void setCrossCursor(); +void setNotAllowedCursor(); void hideNSCursor(); void showNSCursor(); void hideNSCursorTillMove(bool hide); @@ -103,6 +96,12 @@ void callMiddleMouseUp(float *pos, unsigned int mask); void callFocus(); void callFocusLost(); +#include +void callHandleDragEntered(std::string url); +void callHandleDragExited(std::string url); +void callHandleDragUpdated(std::string url); +void callHandleDragDropped(std::string url); + NSWindowRef getMainAppWindow(); GLViewRef getGLView(); diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index b6e5767203..7867226476 100644 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -143,6 +143,12 @@ void setCrossCursor() [cursor set]; } +void setNotAllowedCursor() +{ + NSCursor *cursor = [NSCursor operationNotAllowedCursor]; + [cursor set]; +} + void hideNSCursor() { [NSCursor hide]; diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 95ad87d58f..f25fc82896 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -248,7 +248,6 @@ void callLeftMouseDown(float *pos, MASK mask) outCoords.mX = llround(pos[0]); outCoords.mY = llround(pos[1]); gWindowImplementation->getCallbacks()->handleMouseDown(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); - LL_INFOS("Window") << outCoords.mX << ", " << outCoords.mY << LL_ENDL; } void callLeftMouseUp(float *pos, MASK mask) @@ -285,7 +284,6 @@ void callMouseMoved(float *pos, MASK mask) gWindowImplementation->getMouseDeltas(deltas); outCoords.mX += deltas[0]; outCoords.mY += deltas[1]; - LL_INFOS("Mouse Movement") << "Moved coords: " << outCoords.mX << ", " << outCoords.mY << LL_ENDL; gWindowImplementation->getCallbacks()->handleMouseMove(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); gWindowImplementation->getCallbacks()->handleScrollWheel(gWindowImplementation, 0); } @@ -339,6 +337,26 @@ void callMiddleMouseUp(float *pos, MASK mask) gWindowImplementation->getCallbacks()->handleMiddleMouseUp(gWindowImplementation, outCoords, mask); } +void callHandleDragEntered(std::string url) +{ + gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_START_TRACKING); +} + +void callHandleDragExited(std::string url) +{ + gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_STOP_TRACKING); +} + +void callHandleDragUpdated(std::string url) +{ + gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_TRACK); +} + +void callHandleDragDropped(std::string url) +{ + gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_DROPPED); +} + void LLWindowMacOSX::updateMouseDeltas(float* deltas) { if (mCursorDecoupled) @@ -1784,7 +1802,6 @@ S16 LLWindowMacOSX::dragTrackingHandler(DragTrackingMessage message, WindowRef t return result; } - OSErr LLWindowMacOSX::dragReceiveHandler(WindowRef theWindow, void * handlerRefCon, DragRef drag) { @@ -1792,126 +1809,69 @@ OSErr LLWindowMacOSX::dragReceiveHandler(WindowRef theWindow, void * handlerRefC return self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_DROPPED); } - -OSErr LLWindowMacOSX::handleDragNDrop(DragRef drag, LLWindowCallbacks::DragNDropAction action) +*/ +void LLWindowMacOSX::handleDragNDrop(std::string url, LLWindowCallbacks::DragNDropAction action) { - OSErr result = dragNotAcceptedErr; // overall function result - OSErr err = noErr; // for local error handling - - // Get the mouse position and modifiers of this drag. - SInt16 modifiers, mouseDownModifiers, mouseUpModifiers; - ::GetDragModifiers(drag, &modifiers, &mouseDownModifiers, &mouseUpModifiers); - MASK mask = LLWindowMacOSX::modifiersToMask(modifiers); + MASK mask = LLWindowMacOSX::modifiersToMask(getModifiers()); - Point mouse_point; + float mouse_point[2]; // This will return the mouse point in global screen coords - ::GetDragMouse(drag, &mouse_point, NULL); - LLCoordScreen screen_coords(mouse_point.h, mouse_point.v); + getCursorPos(mWindow, mouse_point); + LLCoordScreen screen_coords(mouse_point[0], mouse_point[1]); LLCoordGL gl_pos; convertCoords(screen_coords, &gl_pos); - - // Look at the pasteboard and try to extract an URL from it - PasteboardRef pasteboard; - if(GetDragPasteboard(drag, &pasteboard) == noErr) + + if(!url.empty()) { - ItemCount num_items = 0; - // Treat an error here as an item count of 0 - (void)PasteboardGetItemCount(pasteboard, &num_items); - - // Only deal with single-item drags. - if(num_items == 1) - { - PasteboardItemID item_id = NULL; - CFArrayRef flavors = NULL; - CFDataRef data = NULL; - - err = PasteboardGetItemIdentifier(pasteboard, 1, &item_id); // Yes, this really is 1-based. - - // Try to extract an URL from the pasteboard - if(err == noErr) - { - err = PasteboardCopyItemFlavors( pasteboard, item_id, &flavors); - } - - if(err == noErr) - { - if(CFArrayContainsValue(flavors, CFRangeMake(0, CFArrayGetCount(flavors)), kUTTypeURL)) - { - // This is an URL. - err = PasteboardCopyItemFlavorData(pasteboard, item_id, kUTTypeURL, &data); - } - else if(CFArrayContainsValue(flavors, CFRangeMake(0, CFArrayGetCount(flavors)), kUTTypeUTF8PlainText)) + LLWindowCallbacks::DragNDropResult res = + mCallbacks->handleDragNDrop(this, gl_pos, mask, action, url); + + switch (res) { + case LLWindowCallbacks::DND_NONE: // No drop allowed + if (action == LLWindowCallbacks::DNDA_TRACK) { - // This is a string that might be an URL. - err = PasteboardCopyItemFlavorData(pasteboard, item_id, kUTTypeUTF8PlainText, &data); + mDragOverrideCursor = 0; } - - } - - if(flavors != NULL) - { - CFRelease(flavors); - } - - if(data != NULL) - { - std::string url; - url.assign((char*)CFDataGetBytePtr(data), CFDataGetLength(data)); - CFRelease(data); - - if(!url.empty()) - { - LLWindowCallbacks::DragNDropResult res = - mCallbacks->handleDragNDrop(this, gl_pos, mask, action, url); - - switch (res) { - case LLWindowCallbacks::DND_NONE: // No drop allowed - if (action == LLWindowCallbacks::DNDA_TRACK) - { - mDragOverrideCursor = kThemeNotAllowedCursor; - } - else { - mDragOverrideCursor = -1; - } - break; - case LLWindowCallbacks::DND_MOVE: // Drop accepted would result in a "move" operation - mDragOverrideCursor = kThemePointingHandCursor; - result = noErr; - break; - case LLWindowCallbacks::DND_COPY: // Drop accepted would result in a "copy" operation - mDragOverrideCursor = kThemeCopyArrowCursor; - result = noErr; - break; - case LLWindowCallbacks::DND_LINK: // Drop accepted would result in a "link" operation: - mDragOverrideCursor = kThemeAliasArrowCursor; - result = noErr; - break; - default: - mDragOverrideCursor = -1; - break; - } - // This overrides the cursor being set by setCursor. - // This is a bit of a hack workaround because lots of areas - // within the viewer just blindly set the cursor. - if (mDragOverrideCursor == -1) - { - // Restore the cursor - ECursorType temp_cursor = mCurrentCursor; - // get around the "setting the same cursor" code in setCursor() - mCurrentCursor = UI_CURSOR_COUNT; - setCursor(temp_cursor); - } - else { - // Override the cursor - SetThemeCursor(mDragOverrideCursor); - } - + else { + mDragOverrideCursor = -1; } - } + break; + case LLWindowCallbacks::DND_MOVE: // Drop accepted would result in a "move" operation + mDragOverrideCursor = UI_CURSOR_NO; + break; + case LLWindowCallbacks::DND_COPY: // Drop accepted would result in a "copy" operation + mDragOverrideCursor = UI_CURSOR_ARROWCOPY; + break; + default: + mDragOverrideCursor = -1; + break; + } + // This overrides the cursor being set by setCursor. + // This is a bit of a hack workaround because lots of areas + // within the viewer just blindly set the cursor. + if (mDragOverrideCursor == -1) + { + // Restore the cursor + ECursorType temp_cursor = mCurrentCursor; + // get around the "setting the same cursor" code in setCursor() + mCurrentCursor = UI_CURSOR_COUNT; + setCursor(temp_cursor); + } + else { + // Override the cursor + switch (mDragOverrideCursor) { + case 0: + setArrowCursor(); + break; + case UI_CURSOR_NO: + setNotAllowedCursor(); + case UI_CURSOR_ARROWCOPY: + setCopyCursor(); + default: + break; + }; } } - - return result; } -*/ + #endif // LL_OS_DRAGDROP_ENABLED diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h index c5e1b2290b..14d6e70fb3 100644 --- a/indra/llwindow/llwindowmacosx.h +++ b/indra/llwindow/llwindowmacosx.h @@ -123,7 +123,8 @@ public: void updateMouseDeltas(float* deltas); void getMouseDeltas(float* delta); - + + void handleDragNDrop(std::string url, LLWindowCallbacks::DragNDropAction action); protected: LLWindowMacOSX(LLWindowCallbacks* callbacks, @@ -164,12 +165,11 @@ protected: static MASK modifiersToMask(S16 modifiers); #if LL_OS_DRAGDROP_ENABLED - /* - static OSErr dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow, - void * handlerRefCon, DragRef theDrag); - static OSErr dragReceiveHandler(WindowRef theWindow, void * handlerRefCon, DragRef theDrag); - OSErr handleDragNDrop(DragRef theDrag, LLWindowCallbacks::DragNDropAction action); - */ + + //static OSErr dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow, void * handlerRefCon, DragRef theDrag); + //static OSErr dragReceiveHandler(WindowRef theWindow, void * handlerRefCon, DragRef theDrag); + + #endif // LL_OS_DRAGDROP_ENABLED // @@ -202,7 +202,7 @@ protected: U32 mFSAASamples; BOOL mForceRebuild; - S32 mDragOverrideCursor; + S32 mDragOverrideCursor; F32 mBounceTime; //NMRec mBounceRec; -- cgit v1.3 From c52e6f9c597c67637045134d808a9039f85efc5c Mon Sep 17 00:00:00 2001 From: Geenz Date: Wed, 23 Jan 2013 09:29:32 -0500 Subject: Refactor the key input handling to make it easier to filter out keys we don't need unicode characters for (such as the arrow keys). --- indra/llwindow/llopenglview-objc.h | 1 - indra/llwindow/llopenglview-objc.mm | 67 ++++++++++++++++++++--------------- indra/llwindow/llwindowmacosx-objc.mm | 6 +++- indra/newview/llappdelegate-objc.mm | 10 ++++++ 4 files changed, 54 insertions(+), 30 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llopenglview-objc.h b/indra/llwindow/llopenglview-objc.h index 1592e6e01d..cc1618b3bc 100644 --- a/indra/llwindow/llopenglview-objc.h +++ b/indra/llwindow/llopenglview-objc.h @@ -14,7 +14,6 @@ @interface LLOpenGLView : NSOpenGLView { - NSPoint mousePos; std::string mLastDraggedUrl; } diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index 763cf0c981..b79b7b3fa5 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -294,37 +294,48 @@ - (void) keyDown:(NSEvent *)theEvent { - callKeyDown([theEvent keyCode], mModifiers); - NSLog(@"Keycode: %hu", [theEvent keyCode]); - NSString *chars = [theEvent characters]; - for (uint i = 0; i < [chars length]; i++) - { - // Enter and Return are special cases. - unichar returntest = [chars characterAtIndex:i]; - if ((returntest == NSCarriageReturnCharacter || returntest == NSEnterCharacter) && - !([theEvent modifierFlags] & NSCommandKeyMask) && - !([theEvent modifierFlags] & NSAlternateKeyMask) && - !([theEvent modifierFlags] & NSControlKeyMask)) - { - callUnicodeCallback(13, 0); - } else { - // The command key being pressed is also a special case. - // Control + produces an ASCII control character code. - // Command + produces just the character's code. - // Check to see if the command key is pressed, then filter through the different character ranges that are relevant to control characters, and subtract the appropriate range. - if ([theEvent modifierFlags] & NSCommandKeyMask) - { - if (returntest >= 64 && returntest <= 95) - { - callUnicodeCallback(returntest - 63, mModifiers); - } else if (returntest >= 97 && returntest <= 122) + uint keycode = [theEvent keyCode]; + + switch (keycode) { + case 0x7b: + case 0x7c: + case 0x7d: + case 0x7e: + callKeyDown(keycode, mModifiers); + break; + + default: + callKeyDown(keycode, mModifiers); + NSString *chars = [theEvent characters]; + for (uint i = 0; i < [chars length]; i++) { + // Enter and Return are special cases. + unichar returntest = [chars characterAtIndex:i]; + if ((returntest == NSCarriageReturnCharacter || returntest == NSEnterCharacter) && + !([theEvent modifierFlags] & NSCommandKeyMask) && + !([theEvent modifierFlags] & NSAlternateKeyMask) && + !([theEvent modifierFlags] & NSControlKeyMask)) { - callUnicodeCallback(returntest - 96, mModifiers); + callUnicodeCallback(13, 0); + } else { + // The command key being pressed is also a special case. + // Control + produces an ASCII control character code. + // Command + produces just the character's code. + // Check to see if the command key is pressed, then filter through the different character ranges that are relevant to control characters, and subtract the appropriate range. + if ([theEvent modifierFlags] & NSCommandKeyMask) + { + if (returntest >= 64 && returntest <= 95) + { + callUnicodeCallback(returntest - 63, mModifiers); + } else if (returntest >= 97 && returntest <= 122) + { + callUnicodeCallback(returntest - 96, mModifiers); + } + } else { + callUnicodeCallback(returntest, mModifiers); + } } - } else { - callUnicodeCallback(returntest, mModifiers); } - } + break; } } diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index 7867226476..b123ba0711 100644 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -64,11 +64,12 @@ void setupCocoa() bool copyToPBoard(const unsigned short *str, unsigned int len) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init]; NSPasteboard *pboard = [NSPasteboard generalPasteboard]; [pboard clearContents]; NSArray *contentsToPaste = [[NSArray alloc] initWithObjects:[NSString stringWithCharacters:str length:len], nil]; - + [pool release]; return [pboard writeObjects:contentsToPaste]; } @@ -80,6 +81,7 @@ bool pasteBoardAvailable() const unsigned short *copyFromPBoard() { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init]; NSPasteboard *pboard = [NSPasteboard generalPasteboard]; NSArray *classArray = [NSArray arrayWithObject:[NSString class]]; NSString *str = NULL; @@ -91,6 +93,7 @@ const unsigned short *copyFromPBoard() } unichar* temp = (unichar*)calloc([str length], sizeof(unichar)); [str getCharacters:temp]; + [pool release]; return temp; } @@ -312,6 +315,7 @@ void convertWindowToScreen(NSWindowRef window, float *coord) void closeWindow(NSWindowRef window) { [(LLNSWindow*)window close]; + [(LLNSWindow*)window release]; } void removeGLView(GLViewRef view) diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index f5143d7578..9bb10f3204 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -29,6 +29,16 @@ } } +- (void) applicationDidBecomeActive:(NSNotification *)notification +{ + +} + +- (void) applicationDidResignActive:(NSNotification *)notification +{ + +} + - (NSApplicationDelegateReply) applicationShouldTerminate:(NSApplication *)sender { if (!runMainLoop()) -- cgit v1.3 From bf1e9124f1530339bfa35652a3b3e329b32a3240 Mon Sep 17 00:00:00 2001 From: Geenz Date: Sat, 2 Feb 2013 12:49:39 -0500 Subject: Restore the old Carbon crash handler, and more deprecated API removal. --- indra/llwindow/llwindowmacosx.cpp | 4 +- indra/newview/llappviewermacosx.cpp | 116 +++++++++++++++++++++++++++++++++++- 2 files changed, 116 insertions(+), 4 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index f25fc82896..2e86759ec0 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -1350,7 +1350,7 @@ void LLWindowMacOSX::updateCursor() { default: case UI_CURSOR_ARROW: - InitCursor(); + setArrowCursor(); if(mCursorHidden) { // Since InitCursor resets the hide level, correct for it here. @@ -1410,7 +1410,7 @@ void LLWindowMacOSX::updateCursor() if(result != noErr) { - InitCursor(); + setArrowCursor(); } mCurrentCursor = mNextCursor; diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index 28210d18dd..4141f16647 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -30,6 +30,8 @@ #error "Use only with Mac OS X" #endif +#define LL_CARBON_CRASH_HANDLER 1 + #include "llappviewermacosx.h" #include "llwindowmacosx-objc.h" #include "llcommandlineparser.h" @@ -40,6 +42,9 @@ #include "llfloaterworldmap.h" #include "llurldispatcher.h" #include +#ifdef LL_CARBON_CRASH_HANDLER +#include +#endif #include "lldir.h" #include #include // for systemwide mute @@ -51,8 +56,18 @@ namespace // They are not used immediately by the app. int gArgC; char** gArgV; - + bool sCrashReporterIsRunning = false; LLAppViewerMacOSX* gViewerAppPtr; +#ifdef LL_CARBON_CRASH_HANDLER + OSErr AEQuitHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn) + { + OSErr result = noErr; + + LLAppViewer::instance()->userQuit(); + + return(result); + } +#endif } bool initViewer() @@ -263,9 +278,39 @@ bool LLAppViewerMacOSX::restoreErrorTrap() return reset_count == 0; } +#ifdef LL_CARBON_CRASH_HANDLER +static OSStatus CarbonEventHandler(EventHandlerCallRef inHandlerCallRef, + EventRef inEvent, + void* inUserData) +{ + ProcessSerialNumber psn; + + GetEventParameter(inEvent, + kEventParamProcessID, + typeProcessSerialNumber, + NULL, + sizeof(psn), + NULL, + &psn); + + if( GetEventKind(inEvent) == kEventAppTerminated ) + { + Boolean matching_psn = FALSE; + OSErr os_result = SameProcess(&psn, (ProcessSerialNumber*)inUserData, &matching_psn); + if(os_result >= 0 && matching_psn) + { + sCrashReporterIsRunning = false; + QuitApplicationEventLoop(); + } + } + return noErr; +} +#endif + void LLAppViewerMacOSX::handleCrashReporting(bool reportFreeze) { - // This used to use fork&exec, but is switched to LSOpenApplication to +#ifdef LL_CARBON_CRASH_HANDLER + // This used to use fork&exec, but is switched to LSOpenApplication to // Make sure the crash reporter launches in front of the SL window. std::string command_str; @@ -283,8 +328,75 @@ void LLAppViewerMacOSX::handleCrashReporting(bool reportFreeze) memset(&appParams, 0, sizeof(appParams)); appParams.version = 0; appParams.flags = kLSLaunchNoParams | kLSLaunchStartClassic; + appParams.application = &appRef; + + if(reportFreeze) + { + // Make sure freeze reporting launches the crash logger synchronously, lest + // Log files get changed by SL while the logger is running. + + // *NOTE:Mani A better way - make a copy of the data that the crash reporter will send + // and let SL go about its business. This way makes the mac work like windows and linux + // and is the smallest patch for the issue. + sCrashReporterIsRunning = false; + ProcessSerialNumber o_psn; + + static EventHandlerRef sCarbonEventsRef = NULL; + static const EventTypeSpec kEvents[] = + { + { kEventClassApplication, kEventAppTerminated } + }; + + // Install the handler to detect crash logger termination + InstallEventHandler(GetApplicationEventTarget(), + (EventHandlerUPP) CarbonEventHandler, + GetEventTypeCount(kEvents), + kEvents, + &o_psn, + &sCarbonEventsRef + ); + + // Remove, temporarily the quit handler - which has *crash* behavior before + // the mainloop gets running! + AERemoveEventHandler(kCoreEventClass, + kAEQuitApplication, + NewAEEventHandlerUPP(AEQuitHandler), + false); + + // Launch the crash reporter. + os_result = LSOpenApplication(&appParams, &o_psn); + + if(os_result >= 0) + { + sCrashReporterIsRunning = true; + } + + while(sCrashReporterIsRunning) + { + RunApplicationEventLoop(); + } + + // Re-install the apps quit handler. + AEInstallEventHandler(kCoreEventClass, + kAEQuitApplication, + NewAEEventHandlerUPP(AEQuitHandler), + 0, + false); + + // Remove the crash reporter quit handler. + RemoveEventHandler(sCarbonEventsRef); + } + else + { + appParams.flags |= kLSLaunchAsync; + clear_signals(); + + ProcessSerialNumber o_psn; + os_result = LSOpenApplication(&appParams, &o_psn); + } } +#endif } std::string LLAppViewerMacOSX::generateSerialNumber() -- cgit v1.3 From 4a935b68151f9d6951a1d1312a3437a8e8150f41 Mon Sep 17 00:00:00 2001 From: Geenz Date: Fri, 22 Feb 2013 16:41:49 -0500 Subject: Fix inconsistent handling of Control, Alt, and Shift keys through a new modifier update callback. --- indra/llwindow/llkeyboard.h | 5 +++++ indra/llwindow/llkeyboardheadless.cpp | 7 +++++++ indra/llwindow/llkeyboardheadless.h | 3 +++ indra/llwindow/llkeyboardmacosx.cpp | 5 +++++ indra/llwindow/llkeyboardmacosx.h | 1 + indra/llwindow/llopenglview-objc.mm | 3 +-- indra/llwindow/llwindowmacosx-objc.h | 1 + indra/llwindow/llwindowmacosx.cpp | 5 +++++ 8 files changed, 28 insertions(+), 2 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llkeyboard.h b/indra/llwindow/llkeyboard.h index c155c1b362..92449c123f 100644 --- a/indra/llwindow/llkeyboard.h +++ b/indra/llwindow/llkeyboard.h @@ -82,6 +82,11 @@ public: virtual BOOL handleKeyUp(const U16 key, MASK mask) = 0; virtual BOOL handleKeyDown(const U16 key, MASK mask) = 0; + +#ifdef LL_DARWIN + // We only actually use this for OS X. + virtual void handleModifier(MASK mask) = 0; +#endif // LL_DARWIN // Asynchronously poll the control, alt, and shift keys and set the // appropriate internal key masks. diff --git a/indra/llwindow/llkeyboardheadless.cpp b/indra/llwindow/llkeyboardheadless.cpp index c87617c9ff..a1b6b294e0 100644 --- a/indra/llwindow/llkeyboardheadless.cpp +++ b/indra/llwindow/llkeyboardheadless.cpp @@ -45,6 +45,13 @@ BOOL LLKeyboardHeadless::handleKeyUp(const U16 key, const U32 mask) MASK LLKeyboardHeadless::currentMask(BOOL for_mouse_event) { return MASK_NONE; } +#ifdef LL_DARWIN +void LLKeyboardHeadless::handleModifier(MASK mask) +{ + +} +#endif + void LLKeyboardHeadless::scanKeyboard() { for (S32 key = 0; key < KEY_COUNT; key++) diff --git a/indra/llwindow/llkeyboardheadless.h b/indra/llwindow/llkeyboardheadless.h index 4e666f8ce8..8ed28ace90 100644 --- a/indra/llwindow/llkeyboardheadless.h +++ b/indra/llwindow/llkeyboardheadless.h @@ -40,6 +40,9 @@ public: /*virtual*/ void resetMaskKeys(); /*virtual*/ MASK currentMask(BOOL for_mouse_event); /*virtual*/ void scanKeyboard(); +#ifdef LL_DARWIN + /*virtual*/ void handleModifier(MASK mask); +#endif }; #endif diff --git a/indra/llwindow/llkeyboardmacosx.cpp b/indra/llwindow/llkeyboardmacosx.cpp index 59cc2acaec..d4c8214461 100644 --- a/indra/llwindow/llkeyboardmacosx.cpp +++ b/indra/llwindow/llkeyboardmacosx.cpp @@ -198,6 +198,11 @@ static BOOL translateKeyMac(const U16 key, const U32 mask, KEY &outKey, U32 &out } */ +void LLKeyboardMacOSX::handleModifier(MASK mask) +{ + updateModifiers(mask); +} + MASK LLKeyboardMacOSX::updateModifiers(const U32 mask) { // translate the mask diff --git a/indra/llwindow/llkeyboardmacosx.h b/indra/llwindow/llkeyboardmacosx.h index 6e1f4d3b96..f9d014ab70 100644 --- a/indra/llwindow/llkeyboardmacosx.h +++ b/indra/llwindow/llkeyboardmacosx.h @@ -49,6 +49,7 @@ public: /*virtual*/ void resetMaskKeys(); /*virtual*/ MASK currentMask(BOOL for_mouse_event); /*virtual*/ void scanKeyboard(); + /*virtual*/ void handleModifier(MASK mask); protected: MASK updateModifiers(const U32 mask); diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index b79b7b3fa5..3a6225eab5 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -345,6 +345,7 @@ - (void)flagsChanged:(NSEvent *)theEvent { mModifiers = [theEvent modifierFlags]; + callModifier([theEvent modifierFlags]); } - (void) mouseDown:(NSEvent *)theEvent @@ -433,8 +434,6 @@ callMouseExit(); } - - - (NSPoint)convertToScreenFromLocalPoint:(NSPoint)point relativeToView:(NSView *)view { NSScreen *currentScreen = [NSScreen currentScreenForMouseLocation]; diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index ebc1633f9d..32d1a4d9a2 100644 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -95,6 +95,7 @@ void callMiddleMouseDown(float *pos, unsigned int mask); void callMiddleMouseUp(float *pos, unsigned int mask); void callFocus(); void callFocusLost(); +void callModifier(unsigned int mask); #include void callHandleDragEntered(std::string url); diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 2e86759ec0..9ce19bd977 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -337,6 +337,11 @@ void callMiddleMouseUp(float *pos, MASK mask) gWindowImplementation->getCallbacks()->handleMiddleMouseUp(gWindowImplementation, outCoords, mask); } +void callModifier(MASK mask) +{ + gKeyboard->handleModifier(mask); +} + void callHandleDragEntered(std::string url) { gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_START_TRACKING); -- cgit v1.3 From e19db5668853b7d3be2ed6af289a3c35bd213bca Mon Sep 17 00:00:00 2001 From: Geenz Date: Mon, 25 Feb 2013 15:35:21 -0500 Subject: Fix for antialiasing and VSync not being enabled properly. --- indra/llwindow/llopenglview-objc.h | 3 ++- indra/llwindow/llopenglview-objc.mm | 11 ++++++++++- indra/llwindow/llwindowmacosx-objc.h | 2 +- indra/llwindow/llwindowmacosx-objc.mm | 4 ++-- indra/llwindow/llwindowmacosx.cpp | 2 +- 5 files changed, 16 insertions(+), 6 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llopenglview-objc.h b/indra/llwindow/llopenglview-objc.h index cc1618b3bc..b344bed2ef 100644 --- a/indra/llwindow/llopenglview-objc.h +++ b/indra/llwindow/llopenglview-objc.h @@ -16,7 +16,8 @@ { std::string mLastDraggedUrl; } - +- (id) initWithSamples:(NSUInteger)samples; +- (id) initWithSamples:(NSUInteger)samples andVsync:(BOOL)vsync; - (id) initWithFrame:(NSRect)frame withSamples:(NSUInteger)samples andVsync:(BOOL)vsync; // rebuildContext diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index 3a6225eab5..e89c9267d5 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -61,10 +61,19 @@ - (id) init { - //[self registerForDraggedTypes:[NSArray arrayWithObjects:NSURLPboardType, NSFilenamesPboardType, nil]]; return [self initWithFrame:[self bounds] withSamples:2 andVsync:TRUE]; } +- (id) initWithSamples:(NSUInteger)samples +{ + return [self initWithFrame:[self bounds] withSamples:samples andVsync:TRUE]; +} + +- (id) initWithSamples:(NSUInteger)samples andVsync:(BOOL)vsync +{ + return [self initWithFrame:[self bounds] withSamples:samples andVsync:vsync]; +} + - (id) initWithFrame:(NSRect)frame withSamples:(NSUInteger)samples andVsync:(BOOL)vsync { [self registerForDraggedTypes:[NSArray arrayWithObject:NSURLPboardType]]; diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index 32d1a4d9a2..a0eab61e7c 100644 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -59,7 +59,7 @@ void hideNSCursorTillMove(bool hide); NSWindowRef createNSWindow(int x, int y, int width, int height); #include -GLViewRef createOpenGLView(NSWindowRef window); +GLViewRef createOpenGLView(NSWindowRef window, unsigned int samples, bool vsync); void glSwapBuffers(void* context); CGLContextObj getCGLContextObj(GLViewRef view); void getContentViewBounds(NSWindowRef window, float* bounds); diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index b123ba0711..b288671219 100644 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -214,9 +214,9 @@ NSWindowRef createNSWindow(int x, int y, int width, int height) return window; } -GLViewRef createOpenGLView(NSWindowRef window) +GLViewRef createOpenGLView(NSWindowRef window, unsigned int samples, bool vsync) { - LLOpenGLView *glview = [[LLOpenGLView alloc]initWithFrame:[(LLNSWindow*)window frame] withSamples:0 andVsync:FALSE]; + LLOpenGLView *glview = [[LLOpenGLView alloc]initWithFrame:[(LLNSWindow*)window frame] withSamples:samples andVsync:vsync]; [(LLNSWindow*)window setContentView:glview]; return glview; } diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 9ce19bd977..ac0fa54a68 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -404,7 +404,7 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits LL_INFOS("Window") << "Creating GL view..." << LL_ENDL; // Our OpenGL view is already defined within SecondLife.xib. // Get the view instead. - mGLView = createOpenGLView(mWindow); + mGLView = createOpenGLView(mWindow, mFSAASamples, !disable_vsync); mContext = getCGLContextObj(mGLView); // Since we just created the context, it needs to be set up. glNeedsInit = TRUE; -- cgit v1.3 From 21aa4b9c2494aab408fffa6c21010b6ca0a9a626 Mon Sep 17 00:00:00 2001 From: Geenz Date: Tue, 26 Feb 2013 16:18:42 -0500 Subject: Setup the quit handler for when the user attempts to close the window. This restores the previous functionality of asking the user if they want to quit. --- indra/llwindow/llopenglview-objc.mm | 7 +++++-- indra/llwindow/llwindowmacosx-objc.h | 1 + indra/llwindow/llwindowmacosx.cpp | 8 ++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index e89c9267d5..1d26ca5ca1 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -466,16 +466,19 @@ - (BOOL) becomeFirstResponder { - NSLog(@"Window gained focus!"); callFocus(); return true; } - (BOOL) resignFirstResponder { - NSLog(@"Window lost focus!"); callFocus(); return true; } +- (void) close +{ + callQuitHandler(); +} + @end diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index a0eab61e7c..6793666927 100644 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -96,6 +96,7 @@ void callMiddleMouseUp(float *pos, unsigned int mask); void callFocus(); void callFocusLost(); void callModifier(unsigned int mask); +void callQuitHandler(); #include void callHandleDragEntered(std::string url); diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index ac0fa54a68..24f73c5631 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -362,6 +362,14 @@ void callHandleDragDropped(std::string url) gWindowImplementation->handleDragNDrop(url, LLWindowCallbacks::DNDA_DROPPED); } +void callQuitHandler() +{ + if(gWindowImplementation->getCallbacks()->handleCloseRequest(gWindowImplementation)) + { + gWindowImplementation->getCallbacks()->handleQuit(gWindowImplementation); + } +} + void LLWindowMacOSX::updateMouseDeltas(float* deltas) { if (mCursorDecoupled) -- cgit v1.3 From f5516e0fc0e6c22b25f9dca2b9b24ebd7618332a Mon Sep 17 00:00:00 2001 From: "Graham Madarasz (Graham Linden)" Date: Wed, 27 Feb 2013 06:46:53 -0800 Subject: For MAINT-2404 Fixes detection of VRAM on OSX removed along with other AGL code. Code Review: callum --- indra/llwindow/llopenglview-objc.h | 5 +++++ indra/llwindow/llopenglview-objc.mm | 22 ++++++++++++++++++++++ indra/llwindow/llwindowmacosx-objc.h | 1 + indra/llwindow/llwindowmacosx-objc.mm | 5 +++++ indra/llwindow/llwindowmacosx.cpp | 2 ++ 5 files changed, 35 insertions(+) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llopenglview-objc.h b/indra/llwindow/llopenglview-objc.h index b344bed2ef..c3ae34ea50 100644 --- a/indra/llwindow/llopenglview-objc.h +++ b/indra/llwindow/llopenglview-objc.h @@ -7,6 +7,9 @@ // #import +#import +#import +#import #include "llwindowmacosx-objc.h" // Some nasty shovelling of LLOpenGLView from LLNativeBindings to prevent any C++ <-> Obj-C interop oddities. @@ -33,6 +36,8 @@ - (CGLContextObj) getCGLContextObj; - (CGLPixelFormatObj*)getCGLPixelFormatObj; +- (unsigned long) getVramSize; + @end @interface LLNSWindow : NSWindow { diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index e89c9267d5..a1dece54f4 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -39,6 +39,28 @@ @implementation LLOpenGLView +- (unsigned long)getVramSize +{ + unsigned long vram_bytes = 0; + + io_service_t display_port = CGDisplayIOServicePort(kCGDirectMainDisplay); + + const void* type_code = IORegistryEntryCreateCFProperty(display_port, CFSTR(kIOFBMemorySizeKey), kCFAllocatorDefault, kNilOptions); + + // Ensure we have valid data from IOKit + if(type_code && CFGetTypeID(type_code) == CFNumberGetTypeID()) + { + long val; + // Retrieve actual number...is Apple ever embarrassed by this nonsense? + // + CFNumberGetValue((const __CFNumber*)type_code, kCFNumberSInt32Type, &val); + vram_bytes = (unsigned long)val; + CFRelease(type_code); + } + + return vram_bytes; +} + - (void)viewDidMoveToWindow { [[NSNotificationCenter defaultCenter] addObserver:self diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index a0eab61e7c..1724b85724 100644 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -62,6 +62,7 @@ NSWindowRef createNSWindow(int x, int y, int width, int height); GLViewRef createOpenGLView(NSWindowRef window, unsigned int samples, bool vsync); void glSwapBuffers(void* context); CGLContextObj getCGLContextObj(GLViewRef view); +unsigned long getVramSize(GLViewRef view); void getContentViewBounds(NSWindowRef window, float* bounds); void getWindowSize(NSWindowRef window, float* size); void setWindowSize(NSWindowRef window, int width, int height); diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index b288671219..9b57cd27cd 100644 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -237,6 +237,11 @@ CGLPixelFormatObj* getCGLPixelFormatObj(NSWindowRef window) return [glview getCGLPixelFormatObj]; } +unsigned long getVramSize(GLViewRef view) +{ + return [(LLOpenGLView *)view getVramSize]; +} + void getContentViewBounds(NSWindowRef window, float* bounds) { bounds[0] = [[(LLNSWindow*)window contentView] bounds].origin.x; diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index ac0fa54a68..abb3c1e50c 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -408,6 +408,8 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits mContext = getCGLContextObj(mGLView); // Since we just created the context, it needs to be set up. glNeedsInit = TRUE; + + gGLManager.mVRAM = getVramSize(mGLView); } // Hook up the context to a drawable -- cgit v1.3 From d046e606575b2c3714a88e321c88e05441cba4a8 Mon Sep 17 00:00:00 2001 From: "Graham Madarasz (Graham Linden)" Date: Wed, 27 Feb 2013 14:39:26 -0800 Subject: Fix max VRAM detection on some cards and issues with sequencing of application of mem multiplier --- indra/llwindow/llopenglview-objc.mm | 32 +++++++++++++---------------- indra/llwindow/llwindowmacosx.cpp | 5 +++-- indra/newview/llfloaterhardwaresettings.cpp | 4 +++- indra/newview/llviewertexturelist.cpp | 14 ++++++------- indra/newview/llviewertexturelist.h | 2 +- 5 files changed, 28 insertions(+), 29 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index a1dece54f4..735ef77cce 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -41,24 +41,20 @@ - (unsigned long)getVramSize { - unsigned long vram_bytes = 0; - - io_service_t display_port = CGDisplayIOServicePort(kCGDirectMainDisplay); - - const void* type_code = IORegistryEntryCreateCFProperty(display_port, CFSTR(kIOFBMemorySizeKey), kCFAllocatorDefault, kNilOptions); - - // Ensure we have valid data from IOKit - if(type_code && CFGetTypeID(type_code) == CFNumberGetTypeID()) - { - long val; - // Retrieve actual number...is Apple ever embarrassed by this nonsense? - // - CFNumberGetValue((const __CFNumber*)type_code, kCFNumberSInt32Type, &val); - vram_bytes = (unsigned long)val; - CFRelease(type_code); - } - - return vram_bytes; + CGLRendererInfoObj info = 0; + GLint vram_bytes = 0; + int num_renderers = 0; + CGLError the_err = CGLQueryRendererInfo (CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay), &info, &num_renderers); + if(0 == the_err) + { + CGLDescribeRenderer (info, 0, kCGLRPTextureMemory, &vram_bytes); + CGLDestroyRendererInfo (info); + } + else + { + vram_bytes = (256 << 20); + } + return (unsigned long)vram_bytes; } - (void)viewDidMoveToWindow diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index abb3c1e50c..2faebe5dd9 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -511,8 +511,9 @@ void LLWindowMacOSX::destroyContext() // Close the window if(mWindow != NULL) { - closeWindow(mWindow); - mWindow = NULL; + NSWindowRef dead_window = mWindow; + mWindow = NULL; + closeWindow(dead_window); } } diff --git a/indra/newview/llfloaterhardwaresettings.cpp b/indra/newview/llfloaterhardwaresettings.cpp index 116bd241c4..664f7d4fd6 100644 --- a/indra/newview/llfloaterhardwaresettings.cpp +++ b/indra/newview/llfloaterhardwaresettings.cpp @@ -89,8 +89,10 @@ void LLFloaterHardwareSettings::refresh() void LLFloaterHardwareSettings::refreshEnabledState() { + F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple"); + S32 min_tex_mem = LLViewerTextureList::getMinVideoRamSetting(); - S32 max_tex_mem = LLViewerTextureList::getMaxVideoRamSetting(); + S32 max_tex_mem = LLViewerTextureList::getMaxVideoRamSetting(false, mem_multiplier); getChild("GraphicsCardTextureMemory")->setMinValue(min_tex_mem); getChild("GraphicsCardTextureMemory")->setMaxValue(max_tex_mem); diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index b9f5c432d0..82d990cf97 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -1191,7 +1191,7 @@ S32 LLViewerTextureList::getMinVideoRamSetting() //static // Returns max setting for TextureMemory (in MB) -S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended) +S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended, float mem_multiplier) { S32 max_texmem; if (gGLManager.mVRAM != 0) @@ -1235,7 +1235,10 @@ S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended) max_texmem = llmin(max_texmem, (S32)(system_ram/2)); else max_texmem = llmin(max_texmem, (S32)(system_ram)); - + + // limit the texture memory to a multiple of the default if we've found some cards to behave poorly otherwise + max_texmem = llmin(max_texmem, (S32) (mem_multiplier * (F32) max_texmem)); + max_texmem = llclamp(max_texmem, getMinVideoRamSetting(), MAX_VIDEO_RAM_IN_MEGA_BYTES); return max_texmem; @@ -1248,7 +1251,7 @@ void LLViewerTextureList::updateMaxResidentTexMem(S32 mem) // Initialize the image pipeline VRAM settings S32 cur_mem = gSavedSettings.getS32("TextureMemory"); F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple"); - S32 default_mem = getMaxVideoRamSetting(true); // recommended default + S32 default_mem = getMaxVideoRamSetting(true, mem_multiplier); // recommended default if (mem == 0) { mem = cur_mem > 0 ? cur_mem : default_mem; @@ -1258,10 +1261,7 @@ void LLViewerTextureList::updateMaxResidentTexMem(S32 mem) mem = default_mem; } - // limit the texture memory to a multiple of the default if we've found some cards to behave poorly otherwise - mem = llmin(mem, (S32) (mem_multiplier * (F32) default_mem)); - - mem = llclamp(mem, getMinVideoRamSetting(), getMaxVideoRamSetting()); + mem = llclamp(mem, getMinVideoRamSetting(), getMaxVideoRamSetting(false, mem_multiplier)); if (mem != cur_mem) { gSavedSettings.setS32("TextureMemory", mem); diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h index 3dda973d3f..88dea4448b 100644 --- a/indra/newview/llviewertexturelist.h +++ b/indra/newview/llviewertexturelist.h @@ -114,7 +114,7 @@ public: void setDebugFetching(LLViewerFetchedTexture* tex, S32 debug_level); static S32 getMinVideoRamSetting(); - static S32 getMaxVideoRamSetting(bool get_recommended = false); + static S32 getMaxVideoRamSetting(bool get_recommended, float mem_multiplier); private: void updateImagesDecodePriorities(); -- cgit v1.3 From 93eaccae6fe6e8442a3c6e5a2d40a408aa44df77 Mon Sep 17 00:00:00 2001 From: "Graham Madarasz (Graham)" Date: Thu, 28 Feb 2013 15:35:14 -0800 Subject: Modify LLInstanceTracker to avoid using a map of strings to find a map of foo to find some pointers --- doc/contributions.txt | 1 + indra/llcommon/lleventapi.h | 5 ++-- indra/llcommon/lleventtimer.h | 3 ++- indra/llcommon/llfasttimer.h | 5 ++-- indra/llcommon/llinstancetracker.cpp | 14 ++++------- indra/llcommon/llinstancetracker.h | 46 +++++++++++++++++++++++++++-------- indra/llcommon/llleap.h | 3 ++- indra/llrender/llgl.h | 4 +-- indra/llui/llconsole.h | 3 ++- indra/llui/llfloater.h | 5 +++- indra/llui/lllayoutstack.h | 3 ++- indra/llui/llnotifications.h | 5 ++-- indra/llwindow/llwindow.h | 3 ++- indra/llxml/llcontrol.cpp | 2 +- indra/llxml/llcontrol.h | 10 ++++---- indra/newview/lldrawable.cpp | 6 +++++ indra/newview/llfloaterwebcontent.cpp | 2 +- indra/newview/llfloaterwebcontent.h | 5 ++-- indra/newview/llmediactrl.cpp | 2 +- indra/newview/llmediactrl.h | 3 ++- indra/newview/llnamelistctrl.h | 3 ++- indra/newview/lltoast.cpp | 2 +- indra/newview/lltoast.h | 3 ++- 23 files changed, 91 insertions(+), 47 deletions(-) (limited to 'indra/llwindow') diff --git a/doc/contributions.txt b/doc/contributions.txt index f2c249c7c1..33b2ded81d 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -750,6 +750,7 @@ Marine Kelley MartinRJ Fayray STORM-1844 STORM-1845 + STORM-1934 Matthew Anthony Matthew Dowd VWR-1344 diff --git a/indra/llcommon/lleventapi.h b/indra/llcommon/lleventapi.h index 1a37d780b6..10c7e7a23f 100644 --- a/indra/llcommon/lleventapi.h +++ b/indra/llcommon/lleventapi.h @@ -41,12 +41,13 @@ * Deriving from LLInstanceTracker lets us enumerate instances. */ class LL_COMMON_API LLEventAPI: public LLDispatchListener, - public LLInstanceTracker + public INSTANCE_TRACKER_KEYED(LLEventAPI, std::string) { typedef LLDispatchListener lbase; - typedef LLInstanceTracker ibase; + typedef INSTANCE_TRACKER_KEYED(LLEventAPI, std::string) ibase; public: + /** * @param name LLEventPump name on which this LLEventAPI will listen. This * also serves as the LLInstanceTracker instance key. diff --git a/indra/llcommon/lleventtimer.h b/indra/llcommon/lleventtimer.h index 7f42623d01..e55f851758 100644 --- a/indra/llcommon/lleventtimer.h +++ b/indra/llcommon/lleventtimer.h @@ -33,9 +33,10 @@ #include "lltimer.h" // class for scheduling a function to be called at a given frequency (approximate, inprecise) -class LL_COMMON_API LLEventTimer : public LLInstanceTracker +class LL_COMMON_API LLEventTimer : public INSTANCE_TRACKER(LLEventTimer) { public: + LLEventTimer(F32 period); // period is the amount of time between each call to tick() in seconds LLEventTimer(const LLDate& time); virtual ~LLEventTimer(); diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index e42e549df5..440d42ab5a 100644 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -63,7 +63,7 @@ public: // stores a "named" timer instance to be reused via multiple LLFastTimer stack instances class LL_COMMON_API NamedTimer - : public LLInstanceTracker + : public LLInstanceTracker { friend class DeclareTimer; public: @@ -137,10 +137,11 @@ public: // used to statically declare a new named timer class LL_COMMON_API DeclareTimer - : public LLInstanceTracker + : public LLInstanceTracker< DeclareTimer, InstanceTrackType_DeclareTimer > { friend class LLFastTimer; public: + DeclareTimer(const std::string& name, bool open); DeclareTimer(const std::string& name); diff --git a/indra/llcommon/llinstancetracker.cpp b/indra/llcommon/llinstancetracker.cpp index 5dc3ea5d7b..0804be358f 100644 --- a/indra/llcommon/llinstancetracker.cpp +++ b/indra/llcommon/llinstancetracker.cpp @@ -32,18 +32,14 @@ // external library headers // other Linden headers -//static -void * & LLInstanceTrackerBase::getInstances(std::type_info const & info) -{ - typedef std::map InstancesMap; - static InstancesMap instances; +static void* sInstanceTrackerData[ kInstanceTrackTypeCount ] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +void * & LLInstanceTrackerBase::getInstances(InstanceTrackType t) +{ // std::map::insert() is just what we want here. You attempt to insert a // (key, value) pair. If the specified key doesn't yet exist, it inserts // the pair and returns a std::pair of (iterator, true). If the specified // key DOES exist, insert() simply returns (iterator, false). One lookup // handles both cases. - return instances.insert(InstancesMap::value_type(info.name(), - InstancesMap::mapped_type())) - .first->second; -} + return sInstanceTrackerData[t]; +} \ No newline at end of file diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index 403df08990..70bccde992 100644 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -38,6 +38,31 @@ #include #include +enum InstanceTrackType +{ + InstanceTrackType_LLEventAPI, + InstanceTrackType_LLEventTimer, + InstanceTrackType_NamedTimer, + InstanceTrackType_DeclareTimer, + InstanceTrackType_LLLeap, + InstanceTrackType_LLGLNamePool, + InstanceTrackType_LLConsole, + InstanceTrackType_LLFloater, + InstanceTrackType_LLFloaterWebContent, + InstanceTrackType_LLLayoutStack, + InstanceTrackType_LLNotificationContext, + InstanceTrackType_LLWindow, + InstanceTrackType_LLControlGroup, + InstanceTrackType_LLControlCache, + InstanceTrackType_LLMediaCtrl, + InstanceTrackType_LLNameListCtrl, + InstanceTrackType_LLToast, + kInstanceTrackTypeCount +}; + +#define INSTANCE_TRACKER(T) LLInstanceTracker< T, InstanceTrackType_##T > +#define INSTANCE_TRACKER_KEYED(T,K) LLInstanceTracker< T, InstanceTrackType_##T, K > + /** * Base class manages "class-static" data that must actually have singleton * semantics: one instance per process, rather than one instance per module as @@ -47,14 +72,15 @@ class LL_COMMON_API LLInstanceTrackerBase : public boost::noncopyable { protected: /// Get a process-unique void* pointer slot for the specified type_info - static void * & getInstances(std::type_info const & info); + //static void * & getInstances(std::type_info const & info); + static void * & getInstances(InstanceTrackType t); /// Find or create a STATICDATA instance for the specified TRACKED class. /// STATICDATA must be default-constructible. - template + template static STATICDATA& getStatic() { - void *& instances = getInstances(typeid(TRACKED)); + void *& instances = getInstances(TRACKEDTYPE); if (! instances) { instances = new STATICDATA; @@ -78,16 +104,16 @@ protected: /// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup /// If KEY is not provided, then instances are stored in a simple set /// @NOTE: see explicit specialization below for default KEY==T* case -template +template class LLInstanceTracker : public LLInstanceTrackerBase { - typedef LLInstanceTracker MyT; + typedef LLInstanceTracker MyT; typedef typename std::map InstanceMap; struct StaticData: public StaticBase { InstanceMap sMap; }; - static StaticData& getStatic() { return LLInstanceTrackerBase::getStatic(); } + static StaticData& getStatic() { return LLInstanceTrackerBase::getStatic(); } static InstanceMap& getMap_() { return getStatic().sMap; } public: @@ -226,16 +252,16 @@ private: /// explicit specialization for default case where KEY is T* /// use a simple std::set -template -class LLInstanceTracker : public LLInstanceTrackerBase +template +class LLInstanceTracker : public LLInstanceTrackerBase { - typedef LLInstanceTracker MyT; + typedef LLInstanceTracker MyT; typedef typename std::set InstanceSet; struct StaticData: public StaticBase { InstanceSet sSet; }; - static StaticData& getStatic() { return LLInstanceTrackerBase::getStatic(); } + static StaticData& getStatic() { return LLInstanceTrackerBase::getStatic(); } static InstanceSet& getSet_() { return getStatic().sSet; } public: diff --git a/indra/llcommon/llleap.h b/indra/llcommon/llleap.h index 1a1ad23d39..d4e138f4be 100644 --- a/indra/llcommon/llleap.h +++ b/indra/llcommon/llleap.h @@ -29,9 +29,10 @@ * LLLeap* pointer should be validated before use by * LLLeap::getInstance(LLLeap*) (see LLInstanceTracker). */ -class LL_COMMON_API LLLeap: public LLInstanceTracker +class LL_COMMON_API LLLeap: public INSTANCE_TRACKER(LLLeap) { public: + /** * Pass a brief string description, mostly for logging purposes. The desc * need not be unique, but obviously the clearer we can make it, the diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 823de9d361..133c2de1f5 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -350,10 +350,10 @@ public: Generic pooling scheme for things which use GL names (used for occlusion queries and vertex buffer objects). Prevents thrashing of GL name caches by avoiding calls to glGenFoo and glDeleteFoo. */ -class LLGLNamePool : public LLInstanceTracker +class LLGLNamePool : public INSTANCE_TRACKER(LLGLNamePool) { public: - typedef LLInstanceTracker tracker_t; + typedef INSTANCE_TRACKER(LLGLNamePool) tracker_t; struct NameEntry { diff --git a/indra/llui/llconsole.h b/indra/llui/llconsole.h index f32f1dd74c..b264aeb7eb 100644 --- a/indra/llui/llconsole.h +++ b/indra/llui/llconsole.h @@ -34,9 +34,10 @@ class LLSD; -class LLConsole : public LLFixedBuffer, public LLUICtrl, public LLInstanceTracker +class LLConsole : public LLFixedBuffer, public LLUICtrl, public INSTANCE_TRACKER(LLConsole) { public: + typedef enum e_font_size { MONOSPACE = -1, diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index aef63bcf93..113fdf10e4 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -112,15 +112,18 @@ struct LLCoordFloater : LLCoord bool operator!=(const LLCoordFloater& other) const { return !(*this == other); } void setFloater(LLFloater& floater); + + }; -class LLFloater : public LLPanel, public LLInstanceTracker +class LLFloater : public LLPanel, public INSTANCE_TRACKER(LLFloater) { friend class LLFloaterView; friend class LLFloaterReg; friend class LLMultiFloater; public: + struct KeyCompare { // static bool compare(const LLSD& a, const LLSD& b); diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index 648cd5fdce..26b8a7f973 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -34,9 +34,10 @@ class LLLayoutPanel; -class LLLayoutStack : public LLView, public LLInstanceTracker +class LLLayoutStack : public LLView, public INSTANCE_TRACKER(LLLayoutStack) { public: + typedef enum e_layout_orientation { HORIZONTAL, diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index d7534c416d..faeba8f6eb 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -136,10 +136,11 @@ typedef LLFunctorRegistration LLNotificationFunctorRegi // context data that can be looked up via a notification's payload by the display logic // derive from this class to implement specific contexts -class LLNotificationContext : public LLInstanceTracker +class LLNotificationContext : public INSTANCE_TRACKER_KEYED(LLNotificationContext, LLUUID) { public: - LLNotificationContext() : LLInstanceTracker(LLUUID::generateNewID()) + + LLNotificationContext() : INSTANCE_TRACKER_KEYED(LLNotificationContext, LLUUID)(LLUUID::generateNewID()) { } diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index e9147d552e..06d7e4907a 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -39,9 +39,10 @@ class LLWindowCallbacks; // Refer to llwindow_test in test/common/llwindow for usage example -class LLWindow : public LLInstanceTracker +class LLWindow : public INSTANCE_TRACKER(LLWindow) { public: + struct LLWindowResolution { S32 mWidth; diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp index 53d9380f4f..561f4fdc73 100644 --- a/indra/llxml/llcontrol.cpp +++ b/indra/llxml/llcontrol.cpp @@ -316,7 +316,7 @@ LLPointer LLControlGroup::getControl(const std::string& name) //////////////////////////////////////////////////////////////////////////// LLControlGroup::LLControlGroup(const std::string& name) -: LLInstanceTracker(name) +: INSTANCE_TRACKER_KEYED(LLControlGroup, std::string)(name) { mTypeString[TYPE_U32] = "U32"; mTypeString[TYPE_S32] = "S32"; diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index ee7d1d50b7..6ea010f4f9 100644 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -180,7 +180,7 @@ T convert_from_llsd(const LLSD& sd, eControlType type, const std::string& contro } //const U32 STRING_CACHE_SIZE = 10000; -class LLControlGroup : public LLInstanceTracker +class LLControlGroup : public INSTANCE_TRACKER_KEYED(LLControlGroup, std::string) { LOG_CLASS(LLControlGroup); @@ -197,7 +197,7 @@ public: ~LLControlGroup(); void cleanup(); - typedef LLInstanceTracker::instance_iter instance_iter; + typedef INSTANCE_TRACKER_KEYED(LLControlGroup, std::string)::instance_iter instance_iter; LLControlVariablePtr getControl(const std::string& name); @@ -306,7 +306,7 @@ public: //! without have to manually create and bind a listener to a local //! object. template -class LLControlCache : public LLRefCount, public LLInstanceTracker, std::string> +class LLControlCache : public LLRefCount, public LLInstanceTracker, InstanceTrackType_LLControlCache, std::string> { public: // This constructor will declare a control if it doesn't exist in the contol group @@ -314,7 +314,7 @@ public: const std::string& name, const T& default_value, const std::string& comment) - : LLInstanceTracker, std::string >(name) + : LLInstanceTracker, InstanceTrackType_LLControlCache, std::string >(name) { if(!group.controlExists(name)) { @@ -329,7 +329,7 @@ public: LLControlCache(LLControlGroup& group, const std::string& name) - : LLInstanceTracker, std::string >(name) + : LLInstanceTracker, InstanceTrackType_LLControlCache, std::string >(name) { if(!group.controlExists(name)) { diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index d041baea90..119b8d24d0 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -577,6 +577,12 @@ F32 LLDrawable::updateXform(BOOL undamped) mVObjp->dirtySpatialGroup(); } } + else if (!isRoot() + && ( dist_vec_squared(old_pos, target_pos) > 0.f + || (1.f - dot(old_rot, target_rot)) > 0.f)) + { // update child prims moved from LSL + gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE); + } else if (!getVOVolume() && !isAvatar()) { movePartition(); diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index 3fe2518de6..94c3f4149c 100644 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -54,7 +54,7 @@ LLFloaterWebContent::_Params::_Params() LLFloaterWebContent::LLFloaterWebContent( const Params& params ) : LLFloater( params ), - LLInstanceTracker(params.id()), + INSTANCE_TRACKER_KEYED(LLFloaterWebContent, std::string)(params.id()), mWebBrowser(NULL), mAddressCombo(NULL), mSecureLockIcon(NULL), diff --git a/indra/newview/llfloaterwebcontent.h b/indra/newview/llfloaterwebcontent.h index cfc87e9015..409c15fb0b 100644 --- a/indra/newview/llfloaterwebcontent.h +++ b/indra/newview/llfloaterwebcontent.h @@ -40,10 +40,11 @@ class LLIconCtrl; class LLFloaterWebContent : public LLFloater, public LLViewerMediaObserver, - public LLInstanceTracker + public INSTANCE_TRACKER_KEYED(LLFloaterWebContent, std::string) { public: - typedef LLInstanceTracker instance_tracker_t; + + typedef INSTANCE_TRACKER_KEYED(LLFloaterWebContent, std::string) instance_tracker_t; LOG_CLASS(LLFloaterWebContent); struct _Params : public LLInitParam::Block<_Params> diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 99b4707158..48730f0f20 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -81,7 +81,7 @@ LLMediaCtrl::Params::Params() LLMediaCtrl::LLMediaCtrl( const Params& p) : LLPanel( p ), - LLInstanceTracker(LLUUID::generateNewID()), + INSTANCE_TRACKER_KEYED(LLMediaCtrl, LLUUID)(LLUUID::generateNewID()), mTextureDepthBytes( 4 ), mBorder(NULL), mFrequentUpdates( true ), diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index 7f2a5e1642..4fed21bf22 100644 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -42,10 +42,11 @@ class LLMediaCtrl : public LLPanel, public LLViewerMediaObserver, public LLViewerMediaEventEmitter, - public LLInstanceTracker + public INSTANCE_TRACKER_KEYED(LLMediaCtrl, LLUUID) { LOG_CLASS(LLMediaCtrl); public: + struct Params : public LLInitParam::Block { Optional start_url; diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h index 09c3d49fe7..103806a1bd 100644 --- a/indra/newview/llnamelistctrl.h +++ b/indra/newview/llnamelistctrl.h @@ -64,9 +64,10 @@ private: class LLNameListCtrl -: public LLScrollListCtrl, public LLInstanceTracker +: public LLScrollListCtrl, public INSTANCE_TRACKER(LLNameListCtrl) { public: + typedef enum e_name_type { INDIVIDUAL, diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp index 9dfb29b905..49debe67f6 100644 --- a/indra/newview/lltoast.cpp +++ b/indra/newview/lltoast.cpp @@ -572,7 +572,7 @@ S32 LLToast::notifyParent(const LLSD& info) //static void LLToast::updateClass() { - for (LLInstanceTracker::instance_iter iter = LLInstanceTracker::beginInstances(); iter != LLInstanceTracker::endInstances(); ) + for (INSTANCE_TRACKER(LLToast)::instance_iter iter = INSTANCE_TRACKER(LLToast)::beginInstances(); iter != INSTANCE_TRACKER(LLToast)::endInstances(); ) { LLToast& toast = *iter++; diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h index e1d99b1bcb..8f77e7b78b 100644 --- a/indra/newview/lltoast.h +++ b/indra/newview/lltoast.h @@ -69,10 +69,11 @@ private : * Represents toast pop-up. * This is a parent view for all toast panels. */ -class LLToast : public LLModalDialog, public LLInstanceTracker +class LLToast : public LLModalDialog, public INSTANCE_TRACKER(LLToast) { friend class LLToastLifeTimer; public: + typedef boost::function toast_callback_t; typedef boost::signals2::signal toast_signal_t; typedef boost::signals2::signal toast_hover_check_signal_t; -- cgit v1.3 From 5caa7a465e73fc9cf70f5f2c5d147a509bd5e185 Mon Sep 17 00:00:00 2001 From: Geenz Date: Mon, 11 Mar 2013 10:16:22 -0400 Subject: Bug fixing and prep-work for IME support (along with refactored text input in general). --- indra/llwindow/llkeyboardmacosx.cpp | 4 ++-- indra/llwindow/llwindowmacosx-objc.h | 8 ++++++++ indra/llwindow/llwindowmacosx-objc.mm | 9 ++++++++- indra/llwindow/llwindowmacosx.cpp | 25 +++++++++++++++++++++++++ indra/llwindow/llwindowmacosx.h | 1 + indra/newview/SecondLife.nib | Bin 7403 -> 7403 bytes indra/newview/SecondLife.xib | 14 +++++++------- 7 files changed, 51 insertions(+), 10 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llkeyboardmacosx.cpp b/indra/llwindow/llkeyboardmacosx.cpp index d4c8214461..274e92c225 100644 --- a/indra/llwindow/llkeyboardmacosx.cpp +++ b/indra/llwindow/llkeyboardmacosx.cpp @@ -213,7 +213,7 @@ MASK LLKeyboardMacOSX::updateModifiers(const U32 mask) out_mask |= MASK_SHIFT; } - if(mask & MAC_CTRL_KEY || mask & MAC_CMD_KEY) + if(mask & (MAC_CTRL_KEY | MAC_CMD_KEY)) { out_mask |= MASK_CONTROL; } @@ -267,7 +267,7 @@ MASK LLKeyboardMacOSX::currentMask(BOOL for_mouse_event) if (mask & MAC_SHIFT_KEY) result |= MASK_SHIFT; if (mask & MAC_CTRL_KEY) result |= MASK_CONTROL; - if (mask & MAC_ALT_KEY) result |= MASK_ALT; + if (mask & MAC_ALT_KEY) result |= MASK_ALT; // For keyboard events, consider Command equivalent to Control if (!for_mouse_event) diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index 6793666927..62c5b8298f 100644 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -78,6 +78,7 @@ void removeGLView(GLViewRef view); // This is largely for easier interop between Obj-C and C++ (at least in the viewer's case due to the BOOL vs. BOOL conflict) void callKeyUp(unsigned short key, unsigned int mask); void callKeyDown(unsigned short key, unsigned int mask); +void callResetKeys(); void callUnicodeCallback(wchar_t character, unsigned int mask); void callRightMouseDown(float *pos, unsigned int mask); void callRightMouseUp(float *pos, unsigned int mask); @@ -104,6 +105,13 @@ void callHandleDragExited(std::string url); void callHandleDragUpdated(std::string url); void callHandleDragDropped(std::string url); +// LLPreeditor C bindings. +std::basic_string getPreeditString(); +void getPreeditSelectionRange(int *position, int *length); +void getPreeditMarkedRange(int *position, int *length); +void handleUnicodeCharacter(wchar_t c); +void updatePreeditor(unsigned short *str); + NSWindowRef getMainAppWindow(); GLViewRef getGLView(); diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index b288671219..e4e12f4b5c 100644 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -332,7 +332,14 @@ NSWindowRef getMainAppWindow() return winRef; } -unsigned int getModifiers() +/* +GLViewRef getGLView() { + return [(LLAppDelegate*)[[NSApplication sharedApplication] delegate] glview]; +} +*/ + +unsigned int getModifiers() +{ return [NSEvent modifierFlags]; } diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 24f73c5631..2f6c2101ef 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -211,6 +211,11 @@ void callKeyDown(unsigned short key, unsigned int mask) gKeyboard->handleKeyDown(key, mask); } +void callResetKeys() +{ + gKeyboard->resetKeys(); +} + void callUnicodeCallback(wchar_t character, unsigned int mask) { gWindowImplementation->getCallbacks()->handleUnicodeChar(character, mask); @@ -370,6 +375,26 @@ void callQuitHandler() } } +std::basic_string getPreeditString() +{ + return gWindowImplementation->getPreeditor()->getPreeditString(); +} + +void getPreeditSelectionRange(int *position, int *length) +{ + gWindowImplementation->getPreeditor()->getSelectionRange(position, length); +} + +void getPreeditMarkedRange(int *position, int *length) +{ + gWindowImplementation->getPreeditor()->getPreeditRange(position, length); +} + +void handleUnicodeCharacter(wchar_t c) +{ + gWindowImplementation->getPreeditor()->handleUnicodeCharHere(c); +} + void LLWindowMacOSX::updateMouseDeltas(float* deltas) { if (mCursorDecoupled) diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h index 14d6e70fb3..de0340cf74 100644 --- a/indra/llwindow/llwindowmacosx.h +++ b/indra/llwindow/llwindowmacosx.h @@ -120,6 +120,7 @@ public: void* getWindow() { return mWindow; } LLWindowCallbacks* getCallbacks() { return mCallbacks; } + LLPreeditor* getPreeditor() { return mPreeditor; } void updateMouseDeltas(float* deltas); void getMouseDeltas(float* delta); diff --git a/indra/newview/SecondLife.nib b/indra/newview/SecondLife.nib index 09173cd26f..ff218a21c8 100644 Binary files a/indra/newview/SecondLife.nib and b/indra/newview/SecondLife.nib differ diff --git a/indra/newview/SecondLife.xib b/indra/newview/SecondLife.xib index cb91eeaea2..86e8d81ebc 100644 --- a/indra/newview/SecondLife.xib +++ b/indra/newview/SecondLife.xib @@ -2,10 +2,10 @@ 1060 - 12C60 + 12D76 3084 - 1187.34 - 625.00 + 1187.37 + 626.00 com.apple.InterfaceBuilder.CocoaPlugin 3084 @@ -318,7 +318,7 @@ 15 2 - {{196, 240}, {1024, 768}} + {{196, 240}, {1024, 600}} 74974208 Second Life LLNSWindow @@ -328,13 +328,13 @@ 256 - {1024, 768} + {1024, 600} _NS:20 - {{0, 0}, {1920, 1200}} + {{0, 0}, {2560, 1440}} {10000000000000, 10000000000000} Second Life 128 @@ -775,7 +775,7 @@ - 864 + 888 -- cgit v1.3 From ad26f3c39002b6043e5fc4e00f9793e0f0e4941c Mon Sep 17 00:00:00 2001 From: Geenz Date: Tue, 19 Mar 2013 05:50:50 -0400 Subject: IME support (and revamped text input support) semi-working. --- indra/llwindow/llopenglview-objc.h | 3 +- indra/llwindow/llopenglview-objc.mm | 126 ++++++++++++++++++++++++++++++++---- indra/llwindow/llwindowmacosx.cpp | 12 +++- indra/newview/SecondLife.nib | Bin 7403 -> 7403 bytes indra/newview/SecondLife.xib | 31 ++++++--- 5 files changed, 146 insertions(+), 26 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llopenglview-objc.h b/indra/llwindow/llopenglview-objc.h index c3ae34ea50..c144831da4 100644 --- a/indra/llwindow/llopenglview-objc.h +++ b/indra/llwindow/llopenglview-objc.h @@ -15,9 +15,10 @@ // Some nasty shovelling of LLOpenGLView from LLNativeBindings to prevent any C++ <-> Obj-C interop oddities. // Redraw callback handling removed (for now) due to being unneeded in the patch that preceeds this addition. -@interface LLOpenGLView : NSOpenGLView +@interface LLOpenGLView : NSOpenGLView { std::string mLastDraggedUrl; + unsigned int mModifiers; } - (id) initWithSamples:(NSUInteger)samples; - (id) initWithSamples:(NSUInteger)samples andVsync:(BOOL)vsync; diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index 6ea523ea05..d568ed2fe5 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -94,6 +94,7 @@ - (id) initWithFrame:(NSRect)frame withSamples:(NSUInteger)samples andVsync:(BOOL)vsync { + [[self window] makeFirstResponder:self]; [self registerForDraggedTypes:[NSArray arrayWithObject:NSURLPboardType]]; [self initWithFrame:frame]; @@ -199,6 +200,7 @@ - (void) mouseDown:(NSEvent *)theEvent { + [self becomeFirstResponder]; [_window mouseDown:theEvent]; } @@ -234,7 +236,49 @@ - (void) keyDown:(NSEvent *)theEvent { - [_window keyDown:theEvent]; + [[self inputContext] handleEvent:theEvent]; + uint keycode = [theEvent keyCode]; + + switch (keycode) { + case 0x7b: + case 0x7c: + case 0x7d: + case 0x7e: + callKeyDown(keycode, mModifiers); + break; + + default: + callKeyDown(keycode, mModifiers); + NSString *chars = [theEvent characters]; + for (uint i = 0; i < [chars length]; i++) { + // Enter and Return are special cases. + unichar returntest = [chars characterAtIndex:i]; + if ((returntest == NSCarriageReturnCharacter || returntest == NSEnterCharacter) && + !([theEvent modifierFlags] & NSCommandKeyMask) && + !([theEvent modifierFlags] & NSAlternateKeyMask) && + !([theEvent modifierFlags] & NSControlKeyMask)) + { + callUnicodeCallback(13, 0); + } else { + // The command key being pressed is also a special case. + // Control + produces an ASCII control character code. + // Command + produces just the character's code. + // Check to see if the command key is pressed, then filter through the different character ranges that are relevant to control characters, and subtract the appropriate range. + if ([theEvent modifierFlags] & NSCommandKeyMask) + { + if (returntest >= 64 && returntest <= 95) + { + callUnicodeCallback(returntest - 63, mModifiers); + } else if (returntest >= 97 && returntest <= 122) + { + callUnicodeCallback(returntest - 96, mModifiers); + } + } + } + } + break; + } + } - (void) mouseMoved:(NSEvent *)theEvent @@ -242,9 +286,9 @@ [_window mouseMoved:theEvent]; } -- (void) flagsChanged:(NSEvent *)theEvent -{ - [_window flagsChanged:theEvent]; +- (void)flagsChanged:(NSEvent *)theEvent { + mModifiers = [theEvent modifierFlags]; + callModifier([theEvent modifierFlags]); } - (void) mouseExited:(NSEvent *)theEvent @@ -252,14 +296,9 @@ [_window mouseExited:theEvent]; } -- (BOOL) becomeFirstResponder +- (BOOL) acceptsFirstResponder { - return [_window becomeFirstResponder]; -} - -- (BOOL) resignFirstResponder -{ - return [_window resignFirstResponder]; + return YES; } - (NSDragOperation) draggingEntered:(id)sender @@ -305,6 +344,67 @@ return true; } +- (BOOL)hasMarkedText +{ + return NO; +} + +- (NSRange)markedRange +{ + return NSMakeRange(NSNotFound, 0); +} + +- (NSRange)selectedRange +{ + return NSMakeRange(NSNotFound, 0); +} + +- (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange +{ +} + +- (void)unmarkText +{ + +} + +- (NSArray *)validAttributesForMarkedText +{ + return [NSArray array]; +} + +- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange +{ + return nil; +} + +- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange +{ + for (NSInteger i = 0; i < [aString length]; i++) + { + callUnicodeCallback([aString characterAtIndex:i], mModifiers); + } +} + +- (NSUInteger)characterIndexForPoint:(NSPoint)aPoint +{ + return NSNotFound; +} + +- (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange +{ + return NSZeroRect; +} + +- (void)doCommandBySelector:(SEL)aSelector +{ +} + +- (BOOL)drawsVerticallyForCharacterAtIndex:(NSUInteger)charIndex +{ + return NO; +} + @end // We use a custom NSWindow for our event handling. @@ -315,12 +415,13 @@ - (id) init { - + [self makeFirstResponder:[self contentView]]; return self; } - (void) keyDown:(NSEvent *)theEvent { + uint keycode = [theEvent keyCode]; switch (keycode) { @@ -364,6 +465,7 @@ } break; } + } - (void) keyUp:(NSEvent *)theEvent { diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 34cc371526..08612bace4 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -223,7 +223,10 @@ void callUnicodeCallback(wchar_t character, unsigned int mask) void callFocus() { - gWindowImplementation->getCallbacks()->handleFocus(gWindowImplementation); + if (gWindowImplementation) + { + gWindowImplementation->getCallbacks()->handleFocus(gWindowImplementation); + } } void callFocusLost() @@ -369,9 +372,12 @@ void callHandleDragDropped(std::string url) void callQuitHandler() { - if(gWindowImplementation->getCallbacks()->handleCloseRequest(gWindowImplementation)) + if (gWindowImplementation) { - gWindowImplementation->getCallbacks()->handleQuit(gWindowImplementation); + if(gWindowImplementation->getCallbacks()->handleCloseRequest(gWindowImplementation)) + { + gWindowImplementation->getCallbacks()->handleQuit(gWindowImplementation); + } } } diff --git a/indra/newview/SecondLife.nib b/indra/newview/SecondLife.nib index ff218a21c8..f55ddaabcd 100644 Binary files a/indra/newview/SecondLife.nib and b/indra/newview/SecondLife.nib differ diff --git a/indra/newview/SecondLife.xib b/indra/newview/SecondLife.xib index 86e8d81ebc..7d20b7fd7c 100644 --- a/indra/newview/SecondLife.xib +++ b/indra/newview/SecondLife.xib @@ -2,7 +2,7 @@ 1060 - 12D76 + 12D78 3084 1187.37 626.00 @@ -775,24 +775,27 @@ - 888 + 940 LLAppDelegate NSObject - - window - LLNSWindow - - - window - + + LLOpenGLView + LLNSWindow + + + + glview + LLOpenGLView + + window LLNSWindow - + IBProjectSource ./Classes/LLAppDelegate.h @@ -806,6 +809,14 @@ ./Classes/LLNSWindow.h + + LLOpenGLView + NSOpenGLView + + IBProjectSource + ./Classes/LLOpenGLView.h + + 0 -- cgit v1.3 From ebe320e7c3579241e2e034a424ade9f087523b75 Mon Sep 17 00:00:00 2001 From: Geenz Date: Tue, 19 Mar 2013 06:32:56 -0400 Subject: Refactored LLNSWindow and LLOpenGLView significantly. All input goes through LLOpenGLView now. --- indra/llwindow/llopenglview-objc.h | 6 +- indra/llwindow/llopenglview-objc.mm | 290 ++++++++++-------------------------- 2 files changed, 80 insertions(+), 216 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llopenglview-objc.h b/indra/llwindow/llopenglview-objc.h index c144831da4..5134063193 100644 --- a/indra/llwindow/llopenglview-objc.h +++ b/indra/llwindow/llopenglview-objc.h @@ -19,6 +19,7 @@ { std::string mLastDraggedUrl; unsigned int mModifiers; + float mMousePos[2]; } - (id) initWithSamples:(NSUInteger)samples; - (id) initWithSamples:(NSUInteger)samples andVsync:(BOOL)vsync; @@ -41,10 +42,7 @@ @end -@interface LLNSWindow : NSWindow { - float mMousePos[2]; - unsigned int mModifiers; -} +@interface LLNSWindow : NSWindow - (NSPoint)convertToScreenFromLocalPoint:(NSPoint)point relativeToView:(NSView *)view; - (NSPoint)flipPoint:(NSPoint)aPoint; diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index d568ed2fe5..45a5f24481 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -94,7 +94,6 @@ - (id) initWithFrame:(NSRect)frame withSamples:(NSUInteger)samples andVsync:(BOOL)vsync { - [[self window] makeFirstResponder:self]; [self registerForDraggedTypes:[NSArray arrayWithObject:NSURLPboardType]]; [self initWithFrame:frame]; @@ -188,102 +187,102 @@ // Various events can be intercepted by our view, thus not reaching our window. // Intercept these events, and pass them to the window as needed. - Geenz -- (void) mouseDragged:(NSEvent *)theEvent +- (void) mouseDown:(NSEvent *)theEvent { - [_window mouseDragged:theEvent]; + if ([theEvent clickCount] >= 2) + { + callDoubleClick(mMousePos, mModifiers); + } else if ([theEvent clickCount] == 1) { + callLeftMouseDown(mMousePos, mModifiers); + } } -- (void) scrollWheel:(NSEvent *)theEvent +- (void) mouseUp:(NSEvent *)theEvent { - [_window scrollWheel:theEvent]; + callLeftMouseUp(mMousePos, mModifiers); } -- (void) mouseDown:(NSEvent *)theEvent +- (void) rightMouseDown:(NSEvent *)theEvent { - [self becomeFirstResponder]; - [_window mouseDown:theEvent]; + callRightMouseDown(mMousePos, mModifiers); } -- (void) mouseUp:(NSEvent *)theEvent +- (void) rightMouseUp:(NSEvent *)theEvent { - [_window mouseUp:theEvent]; + callRightMouseUp(mMousePos, mModifiers); } -- (void) rightMouseDown:(NSEvent *)theEvent +- (void)mouseMoved:(NSEvent *)theEvent { - [_window rightMouseDown:theEvent]; + float mouseDeltas[2] = { + [theEvent deltaX], + [theEvent deltaY] + }; + + callDeltaUpdate(mouseDeltas, 0); + + NSPoint mPoint = [theEvent locationInWindow]; + mMousePos[0] = mPoint.x; + mMousePos[1] = mPoint.y; + callMouseMoved(mMousePos, 0); } -- (void) rightMouseUp:(NSEvent *)theEvent +// NSWindow doesn't trigger mouseMoved when the mouse is being clicked and dragged. +// Use mouseDragged for situations like this to trigger our movement callback instead. + +- (void) mouseDragged:(NSEvent *)theEvent { - [_window rightMouseUp:theEvent]; + // Trust the deltas supplied by NSEvent. + // The old CoreGraphics APIs we previously relied on are now flagged as obsolete. + // NSEvent isn't obsolete, and provides us with the correct deltas. + float mouseDeltas[2] = { + [theEvent deltaX], + [theEvent deltaY] + }; + + callDeltaUpdate(mouseDeltas, 0); + + NSPoint mPoint = [theEvent locationInWindow]; + mMousePos[0] = mPoint.x; + mMousePos[1] = mPoint.y; + callMouseMoved(mMousePos, 0); } - (void) otherMouseDown:(NSEvent *)theEvent { - [_window otherMouseDown:theEvent]; + callMiddleMouseDown(mMousePos, mModifiers); } - (void) otherMouseUp:(NSEvent *)theEvent { - [_window otherMouseUp:theEvent]; + callMiddleMouseUp(mMousePos, mModifiers); +} + +- (void) otherMouseDragged:(NSEvent *)theEvent +{ + +} + +- (void) scrollWheel:(NSEvent *)theEvent +{ + callScrollMoved(-[theEvent deltaY]); +} + +- (void) mouseExited:(NSEvent *)theEvent +{ + callMouseExit(); } - (void) keyUp:(NSEvent *)theEvent { - [_window keyUp:theEvent]; + callKeyUp([theEvent keyCode], mModifiers); } - (void) keyDown:(NSEvent *)theEvent { [[self inputContext] handleEvent:theEvent]; uint keycode = [theEvent keyCode]; - - switch (keycode) { - case 0x7b: - case 0x7c: - case 0x7d: - case 0x7e: - callKeyDown(keycode, mModifiers); - break; - - default: - callKeyDown(keycode, mModifiers); - NSString *chars = [theEvent characters]; - for (uint i = 0; i < [chars length]; i++) { - // Enter and Return are special cases. - unichar returntest = [chars characterAtIndex:i]; - if ((returntest == NSCarriageReturnCharacter || returntest == NSEnterCharacter) && - !([theEvent modifierFlags] & NSCommandKeyMask) && - !([theEvent modifierFlags] & NSAlternateKeyMask) && - !([theEvent modifierFlags] & NSControlKeyMask)) - { - callUnicodeCallback(13, 0); - } else { - // The command key being pressed is also a special case. - // Control + produces an ASCII control character code. - // Command + produces just the character's code. - // Check to see if the command key is pressed, then filter through the different character ranges that are relevant to control characters, and subtract the appropriate range. - if ([theEvent modifierFlags] & NSCommandKeyMask) - { - if (returntest >= 64 && returntest <= 95) - { - callUnicodeCallback(returntest - 63, mModifiers); - } else if (returntest >= 97 && returntest <= 122) - { - callUnicodeCallback(returntest - 96, mModifiers); - } - } - } - } - break; - } - -} - -- (void) mouseMoved:(NSEvent *)theEvent -{ - [_window mouseMoved:theEvent]; + callKeyDown(keycode, mModifiers); } - (void)flagsChanged:(NSEvent *)theEvent { @@ -291,11 +290,6 @@ callModifier([theEvent modifierFlags]); } -- (void) mouseExited:(NSEvent *)theEvent -{ - [_window mouseExited:theEvent]; -} - - (BOOL) acceptsFirstResponder { return YES; @@ -386,6 +380,18 @@ } } +- (void) insertNewline:(id)sender +{ + if (!(mModifiers & NSCommandKeyMask) && + !(mModifiers & NSShiftKeyMask) && + !(mModifiers & NSAlternateKeyMask)) + { + callUnicodeCallback(13, 0); + } else { + callUnicodeCallback(13, mModifiers); + } +} + - (NSUInteger)characterIndexForPoint:(NSPoint)aPoint { return NSNotFound; @@ -398,6 +404,10 @@ - (void)doCommandBySelector:(SEL)aSelector { + if (aSelector == @selector(insertNewline:)) + { + [self insertNewline:self]; + } } - (BOOL)drawsVerticallyForCharacterAtIndex:(NSUInteger)charIndex @@ -419,150 +429,6 @@ return self; } -- (void) keyDown:(NSEvent *)theEvent -{ - - uint keycode = [theEvent keyCode]; - - switch (keycode) { - case 0x7b: - case 0x7c: - case 0x7d: - case 0x7e: - callKeyDown(keycode, mModifiers); - break; - - default: - callKeyDown(keycode, mModifiers); - NSString *chars = [theEvent characters]; - for (uint i = 0; i < [chars length]; i++) { - // Enter and Return are special cases. - unichar returntest = [chars characterAtIndex:i]; - if ((returntest == NSCarriageReturnCharacter || returntest == NSEnterCharacter) && - !([theEvent modifierFlags] & NSCommandKeyMask) && - !([theEvent modifierFlags] & NSAlternateKeyMask) && - !([theEvent modifierFlags] & NSControlKeyMask)) - { - callUnicodeCallback(13, 0); - } else { - // The command key being pressed is also a special case. - // Control + produces an ASCII control character code. - // Command + produces just the character's code. - // Check to see if the command key is pressed, then filter through the different character ranges that are relevant to control characters, and subtract the appropriate range. - if ([theEvent modifierFlags] & NSCommandKeyMask) - { - if (returntest >= 64 && returntest <= 95) - { - callUnicodeCallback(returntest - 63, mModifiers); - } else if (returntest >= 97 && returntest <= 122) - { - callUnicodeCallback(returntest - 96, mModifiers); - } - } else { - callUnicodeCallback(returntest, mModifiers); - } - } - } - break; - } - -} - -- (void) keyUp:(NSEvent *)theEvent { - callKeyUp([theEvent keyCode], mModifiers); -} - -- (void)flagsChanged:(NSEvent *)theEvent { - mModifiers = [theEvent modifierFlags]; - callModifier([theEvent modifierFlags]); -} - -- (void) mouseDown:(NSEvent *)theEvent -{ - if ([theEvent clickCount] >= 2) - { - callDoubleClick(mMousePos, mModifiers); - } else if ([theEvent clickCount] == 1) { - callLeftMouseDown(mMousePos, mModifiers); - } -} - -- (void) mouseUp:(NSEvent *)theEvent -{ - callLeftMouseUp(mMousePos, mModifiers); -} - -- (void) rightMouseDown:(NSEvent *)theEvent -{ - callRightMouseDown(mMousePos, mModifiers); -} - -- (void) rightMouseUp:(NSEvent *)theEvent -{ - callRightMouseUp(mMousePos, mModifiers); -} - -- (void)mouseMoved:(NSEvent *)theEvent -{ - float mouseDeltas[2] = { - [theEvent deltaX], - [theEvent deltaY] - }; - - callDeltaUpdate(mouseDeltas, 0); - - NSPoint mPoint = [theEvent locationInWindow]; - mMousePos[0] = mPoint.x; - mMousePos[1] = mPoint.y; - callMouseMoved(mMousePos, 0); -} - -// NSWindow doesn't trigger mouseMoved when the mouse is being clicked and dragged. -// Use mouseDragged for situations like this to trigger our movement callback instead. - -- (void) mouseDragged:(NSEvent *)theEvent -{ - // Trust the deltas supplied by NSEvent. - // The old CoreGraphics APIs we previously relied on are now flagged as obsolete. - // NSEvent isn't obsolete, and provides us with the correct deltas. - float mouseDeltas[2] = { - [theEvent deltaX], - [theEvent deltaY] - }; - - callDeltaUpdate(mouseDeltas, 0); - - NSPoint mPoint = [theEvent locationInWindow]; - mMousePos[0] = mPoint.x; - mMousePos[1] = mPoint.y; - callMouseMoved(mMousePos, 0); -} - -- (void) otherMouseDown:(NSEvent *)theEvent -{ - callMiddleMouseDown(mMousePos, mModifiers); -} - -- (void) otherMouseUp:(NSEvent *)theEvent -{ - callMiddleMouseUp(mMousePos, mModifiers); -} - -- (void) otherMouseDragged:(NSEvent *)theEvent -{ - -} - -- (void) scrollWheel:(NSEvent *)theEvent -{ - callScrollMoved(-[theEvent deltaY]); -} - -- (void) mouseExited:(NSEvent *)theEvent -{ - callMouseExit(); -} - - (NSPoint)convertToScreenFromLocalPoint:(NSPoint)point relativeToView:(NSView *)view { NSScreen *currentScreen = [NSScreen currentScreenForMouseLocation]; -- cgit v1.3 From 64c0455db568e6818c483785cff0fcd9cfa47aff Mon Sep 17 00:00:00 2001 From: Geenz Date: Tue, 19 Mar 2013 23:02:47 -0400 Subject: More LLPreeditor work. --- indra/llwindow/llopenglview-objc.mm | 10 +++++++--- indra/llwindow/llwindowmacosx-objc.h | 1 + indra/llwindow/llwindowmacosx-objc.mm | 5 +++++ indra/llwindow/llwindowmacosx.cpp | 24 ++++++++++++++++++++---- 4 files changed, 33 insertions(+), 7 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index 45a5f24481..ca00185dff 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -345,16 +345,21 @@ - (NSRange)markedRange { - return NSMakeRange(NSNotFound, 0); + int range[2]; + getPreeditMarkedRange(&range[0], &range[1]); + return NSMakeRange(range[0], range[1]); } - (NSRange)selectedRange { - return NSMakeRange(NSNotFound, 0); + int range[2]; + getPreeditSelectionRange(&range[0], &range[1]); + return NSMakeRange(range[0], range[1]); } - (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange { + } - (void)unmarkText @@ -425,7 +430,6 @@ - (id) init { - [self makeFirstResponder:[self contentView]]; return self; } diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index f3d6d2b1f1..57bb071690 100644 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -74,6 +74,7 @@ void convertScreenToView(NSWindowRef window, float *coord); void setWindowPos(NSWindowRef window, float* pos); void closeWindow(NSWindowRef window); void removeGLView(GLViewRef view); +void makeFirstResponder(NSWindowRef window, GLViewRef view); // These are all implemented in llwindowmacosx.cpp. // This is largely for easier interop between Obj-C and C++ (at least in the viewer's case due to the BOOL vs. BOOL conflict) diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index b859f236d4..9530785b83 100644 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -337,6 +337,11 @@ NSWindowRef getMainAppWindow() return winRef; } +void makeFirstResponder(NSWindowRef window, GLViewRef view) +{ + [(LLNSWindow*)window makeFirstResponder:(LLOpenGLView*)view]; +} + /* GLViewRef getGLView() { diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 08612bace4..7e4b9a84a1 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -383,22 +383,37 @@ void callQuitHandler() std::basic_string getPreeditString() { - return gWindowImplementation->getPreeditor()->getPreeditString(); + std::basic_string str; + if (gWindowImplementation->getPreeditor()) + { + str = gWindowImplementation->getPreeditor()->getPreeditString(); + } + + return str; } void getPreeditSelectionRange(int *position, int *length) { - gWindowImplementation->getPreeditor()->getSelectionRange(position, length); + if (gWindowImplementation->getPreeditor()) + { + gWindowImplementation->getPreeditor()->getSelectionRange(position, length); + } } void getPreeditMarkedRange(int *position, int *length) { - gWindowImplementation->getPreeditor()->getPreeditRange(position, length); + if (gWindowImplementation->getPreeditor()) + { + gWindowImplementation->getPreeditor()->getPreeditRange(position, length); + } } void handleUnicodeCharacter(wchar_t c) { - gWindowImplementation->getPreeditor()->handleUnicodeCharHere(c); + if (gWindowImplementation->getPreeditor()) + { + gWindowImplementation->getPreeditor()->handleUnicodeCharHere(c); + } } void LLWindowMacOSX::updateMouseDeltas(float* deltas) @@ -498,6 +513,7 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits } } LL_INFOS("Window") << "Completed context creation." << LL_ENDL; + makeFirstResponder(mWindow, mGLView); // Don't need to get the current gamma, since there's a call that restores it to the system defaults. return TRUE; } -- cgit v1.3 From 6c200a94f705667201bcaf0753986da90a2748eb Mon Sep 17 00:00:00 2001 From: Geenz Date: Sat, 23 Mar 2013 01:05:21 -0400 Subject: Fix for command key presses + a letter not triggering keyUp. Fix by Katharine Berry. --- indra/llwindow/llopenglview-objc.mm | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index ca00185dff..de159816e0 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -283,6 +283,14 @@ [[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) + { + callKeyUp([theEvent keyCode], mModifiers); + } } - (void)flagsChanged:(NSEvent *)theEvent { -- cgit v1.3 From 258b77b64777a5ce5fef0ef066aa52b34b43ba65 Mon Sep 17 00:00:00 2001 From: Geenz Date: Mon, 25 Mar 2013 05:26:55 -0400 Subject: Additional IME support. LLPreeditor is largely good to go at this point, but there's still some work to do in getSegments. --- indra/llwindow/llkeyboardmacosx.cpp | 1 - indra/llwindow/llopenglview-objc.h | 4 ++ indra/llwindow/llopenglview-objc.mm | 97 ++++++++++++++++++++++---- indra/llwindow/llwindowmacosx-objc.h | 11 +++ indra/llwindow/llwindowmacosx-objc.mm | 45 ++++++++++-- indra/llwindow/llwindowmacosx.cpp | 126 ++++++++++++++++++++++++++++++---- indra/newview/Info-SecondLife.plist | 2 +- indra/newview/llviewerkeyboard.cpp | 1 - indra/newview/llviewerwindow.cpp | 1 - 9 files changed, 252 insertions(+), 36 deletions(-) (limited to 'indra/llwindow') 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(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 + +typedef std::map 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 & 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 getPreeditString() +void getPreeditSelectionRange(int *position, int *length) { - std::basic_string 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 @@ CFBundleInfoDictionaryVersion 6.0 CFBundleName - Second Life + SecondLife CFBundlePackageType APPL CFBundleSignature 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(); -- cgit v1.3 From 80a79e5d7b4f37f862b312e848b1d1e7f85b0fa9 Mon Sep 17 00:00:00 2001 From: Geenz Date: Wed, 27 Mar 2013 08:49:45 -0400 Subject: IME support is pretty much finished at this point. --- indra/llwindow/llappdelegate-objc.h | 1 - indra/llwindow/llopenglview-objc.h | 4 +-- indra/llwindow/llopenglview-objc.mm | 66 ++++++++++++++++++----------------- indra/llwindow/llwindowmacosx-objc.h | 13 +++++-- indra/llwindow/llwindowmacosx-objc.mm | 2 +- indra/llwindow/llwindowmacosx.cpp | 13 ++----- indra/newview/llappdelegate-objc.mm | 1 + 7 files changed, 51 insertions(+), 49 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llappdelegate-objc.h b/indra/llwindow/llappdelegate-objc.h index 56b7a30797..6a4794f3c3 100644 --- a/indra/llwindow/llappdelegate-objc.h +++ b/indra/llwindow/llappdelegate-objc.h @@ -8,7 +8,6 @@ #import #import "llopenglview-objc.h" -#include "llwindowmacosx-objc.h" @interface LLAppDelegate : NSObject { LLNSWindow *window; diff --git a/indra/llwindow/llopenglview-objc.h b/indra/llwindow/llopenglview-objc.h index 8140421e44..5f972b1a98 100644 --- a/indra/llwindow/llopenglview-objc.h +++ b/indra/llwindow/llopenglview-objc.h @@ -10,7 +10,7 @@ #import #import #import -#include "llwindowmacosx-objc.h" +#include // Some nasty shovelling of LLOpenGLView from LLNativeBindings to prevent any C++ <-> Obj-C interop oddities. // Redraw callback handling removed (for now) due to being unneeded in the patch that preceeds this addition. @@ -42,8 +42,6 @@ - (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 31b0e02ad8..376d238c90 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -7,6 +7,7 @@ // #import "llopenglview-objc.h" +#include "llwindowmacosx-objc.h" @implementation NSScreen (PointConversion) @@ -37,6 +38,37 @@ @end +attributedStringInfo getSegments(NSAttributedString *str) +{ + attributedStringInfo segments; + segment_lengths seg_lengths; + segment_standouts seg_standouts; + NSRange effectiveRange; + NSRange limitRange = NSMakeRange(0, [str length]); + while (limitRange.length > 0) { + NSNumber *attr = [str attribute:NSUnderlineStyleAttributeName atIndex:limitRange.location longestEffectiveRange:&effectiveRange inRange:limitRange]; + limitRange = NSMakeRange(NSMaxRange(effectiveRange), NSMaxRange(limitRange) - NSMaxRange(effectiveRange)); + + if (effectiveRange.length <= 0) + { + effectiveRange.length = 1; + } + + if ([attr integerValue] == 2) + { + seg_lengths.push_back(effectiveRange.length); + seg_standouts.push_back(true); + } else + { + seg_lengths.push_back(effectiveRange.length); + seg_standouts.push_back(false); + } + } + segments.seg_lengths = seg_lengths; + segments.seg_standouts = seg_standouts; + return segments; +} + @implementation LLOpenGLView - (unsigned long)getVramSize @@ -368,35 +400,6 @@ return NSMakeRange(range[0], range[1]); } -- (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(l.length, standout)); - - segment++; - } - - return segments; -} - - (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange { if ([aString class] == NSClassFromString(@"NSConcreteMutableAttributedString")) @@ -411,11 +414,9 @@ 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]; + attributedStringInfo segments = getSegments((NSAttributedString *)aString); setMarkedText(text, selected, replacement, [aString length], segments); mHasMarkedText = TRUE; mMarkedTextLength = [aString length]; @@ -452,6 +453,7 @@ // 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]); diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index 2de185fed3..1d05db14b2 100644 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -26,8 +26,17 @@ */ #include +#include -typedef std::map segment_t; +typedef std::vector > segment_t; + +typedef std::vector segment_lengths; +typedef std::vector segment_standouts; + +struct attributedStringInfo { + segment_lengths seg_lengths; + segment_standouts seg_standouts; +}; // This will actually hold an NSCursor*, but that type is only available in objective C. typedef void *CursorRef; @@ -122,7 +131,7 @@ void updatePreeditor(unsigned short *str); void setPreeditMarkedRange(int position, int length); void resetPreedit(); int wstring_length(const std::basic_string & 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 setMarkedText(unsigned short *text, unsigned int *selectedRange, unsigned int *replacementRange, long text_len, attributedStringInfo segments); void getPreeditLocation(float *location, unsigned int length); NSWindowRef getMainAppWindow(); diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index 1a0647485c..43f853bfd1 100644 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -27,8 +27,8 @@ #include #include -#include "llwindowmacosx-objc.h" #include "llopenglview-objc.h" +#include "llwindowmacosx-objc.h" #include "llappdelegate-objc.h" /* diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 4e8934b149..6f66da66a4 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -39,6 +39,7 @@ #include "indra_constants.h" #include +#include extern BOOL gDebugWindowProc; @@ -423,7 +424,7 @@ void 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) +void setMarkedText(unsigned short *unitext, unsigned int *selectedRange, unsigned int *replacementRange, long text_len, attributedStringInfo segments) { if (gWindowImplementation->getPreeditor()) { @@ -442,17 +443,9 @@ void setMarkedText(unsigned short *unitext, unsigned int *selectedRange, unsigne 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); + preeditor->updatePreedit(fix_str, segments.seg_lengths, segments.seg_standouts, caret_position); } } diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index 9e0e0e35c5..5fb5087cd8 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -7,6 +7,7 @@ // #import "llappdelegate-objc.h" +#include "llwindowmacosx-objc.h" @implementation LLAppDelegate -- cgit v1.3 From 2656b1f405dcf3b67d644bf47b02a64886ef2ca4 Mon Sep 17 00:00:00 2001 From: Geenz Date: Mon, 1 Apr 2013 08:15:12 -0400 Subject: First pass at adding a viable replacement for TSM's old UseInputWindow method (which is now deprecated with seemingly no Cocoa replacement). --- indra/llwindow/llappdelegate-objc.h | 6 +- indra/llwindow/llopenglview-objc.h | 12 +- indra/llwindow/llopenglview-objc.mm | 22 +- indra/llwindow/llwindowmacosx-objc.h | 2 + indra/llwindow/llwindowmacosx-objc.mm | 10 + indra/llwindow/llwindowmacosx.cpp | 14 +- indra/newview/SecondLife.nib | Bin 7403 -> 12997 bytes indra/newview/SecondLife.xib | 381 +++++++++++++++++++++++++++++++++- indra/newview/llappdelegate-objc.mm | 15 ++ 9 files changed, 444 insertions(+), 18 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llappdelegate-objc.h b/indra/llwindow/llappdelegate-objc.h index 6a4794f3c3..e7f6ecd5fc 100644 --- a/indra/llwindow/llappdelegate-objc.h +++ b/indra/llwindow/llappdelegate-objc.h @@ -11,11 +11,15 @@ @interface LLAppDelegate : NSObject { LLNSWindow *window; + NSWindow *inputWindow; + LLNonInlineTextView *inputView; NSTimer *frameTimer; } @property (assign) IBOutlet LLNSWindow *window; +@property (assign) IBOutlet NSWindow *inputWindow; +@property (assign) IBOutlet LLNonInlineTextView *inputView; - (void) mainLoop; - +- (void) showInputWindow:(bool)show; @end diff --git a/indra/llwindow/llopenglview-objc.h b/indra/llwindow/llopenglview-objc.h index 5f972b1a98..6b21148bb6 100644 --- a/indra/llwindow/llopenglview-objc.h +++ b/indra/llwindow/llopenglview-objc.h @@ -12,9 +12,6 @@ #import #include -// Some nasty shovelling of LLOpenGLView from LLNativeBindings to prevent any C++ <-> Obj-C interop oddities. -// Redraw callback handling removed (for now) due to being unneeded in the patch that preceeds this addition. - @interface LLOpenGLView : NSOpenGLView { std::string mLastDraggedUrl; @@ -44,6 +41,15 @@ @end +@interface LLNonInlineTextView : NSTextView +{ + LLOpenGLView *glview; +} + +- (void) setGLView:(LLOpenGLView*)view; + +@end + @interface LLNSWindow : NSWindow - (NSPoint)convertToScreenFromLocalPoint:(NSPoint)point relativeToView:(NSView *)view; diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index 376d238c90..a6ef35a8eb 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -501,9 +501,25 @@ attributedStringInfo getSegments(NSAttributedString *str) @end -// We use a custom NSWindow for our event handling. -// Why not an NSWindowController you may ask? -// Answer: this is easier. +@implementation LLNonInlineTextView + +- (void) setGLView:(LLOpenGLView *)view +{ + glview = view; +} + +- (void) insertText:(id)insertString +{ + [self insertText:insertString replacementRange:NSMakeRange(0, 0)]; +} + +- (void) insertText:(id)aString replacementRange:(NSRange)replacementRange +{ + [glview insertText:aString replacementRange:replacementRange]; + [_window orderOut:_window]; +} + +@end @implementation LLNSWindow diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index 1d05db14b2..14a0c22d66 100644 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -90,6 +90,8 @@ void setWindowPos(NSWindowRef window, float* pos); void closeWindow(NSWindowRef window); void removeGLView(GLViewRef view); void makeFirstResponder(NSWindowRef window, GLViewRef view); +void setupInputWindow(NSWindowRef window, GLViewRef view); +void showInputWindow(bool show); // These are all implemented in llwindowmacosx.cpp. // This is largely for easier interop between Obj-C and C++ (at least in the viewer's case due to the BOOL vs. BOOL conflict) diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index 43f853bfd1..0eef8c9f83 100644 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -362,6 +362,16 @@ void removeGLView(GLViewRef view) [(LLOpenGLView*)view release]; } +void setupInputWindow(NSWindowRef window, GLViewRef glview) +{ + [[(LLAppDelegate*)[NSApp delegate] inputView] setGLView:(LLOpenGLView*)glview]; +} + +void showInputWindow(bool show) +{ + [(LLAppDelegate*)[NSApp delegate] showInputWindow:show]; +} + NSWindowRef getMainAppWindow() { LLNSWindow *winRef = [(LLAppDelegate*)[[NSApplication sharedApplication] delegate] window]; diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 6f66da66a4..2d0f981b3e 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -191,6 +191,8 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks, //start with arrow cursor initCursors(); setCursor( UI_CURSOR_ARROW ); + + allowLanguageTextInput(NULL, FALSE); } mCallbacks = callbacks; @@ -513,18 +515,22 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits // Get the view instead. mGLView = createOpenGLView(mWindow, mFSAASamples, !disable_vsync); mContext = getCGLContextObj(mGLView); + // Since we just created the context, it needs to be set up. glNeedsInit = TRUE; gGLManager.mVRAM = getVramSize(mGLView); } - + + // This sets up our view to recieve text from our non-inline text input window. + setupInputWindow(mWindow, mGLView); + // Hook up the context to a drawable if(mContext != NULL) { - LL_INFOS("Window") << "Setting CGL Context..." << LL_ENDL; - LL_DEBUGS("Window") << "createContext: setting current context" << LL_ENDL; + + U32 err = CGLSetCurrentContext(mContext); if (err != kCGLNoError) { @@ -1888,6 +1894,8 @@ void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) return; } + showInputWindow(!b); + // Take care of old and new preeditors. if (preeditor != mPreeditor || !b) { diff --git a/indra/newview/SecondLife.nib b/indra/newview/SecondLife.nib index f55ddaabcd..0b0ff5308b 100644 Binary files a/indra/newview/SecondLife.nib and b/indra/newview/SecondLife.nib differ diff --git a/indra/newview/SecondLife.xib b/indra/newview/SecondLife.xib index 7d20b7fd7c..fdfea49c42 100644 --- a/indra/newview/SecondLife.xib +++ b/indra/newview/SecondLife.xib @@ -11,9 +11,13 @@ 3084 + IBNSLayoutConstraint NSCustomObject NSMenu NSMenuItem + NSScrollView + NSScroller + NSTextView NSView NSWindowTemplate @@ -340,6 +344,202 @@ 128 YES + + 31 + 2 + {{272, 176}, {938, 42}} + -1535638528 + Window + NSPanel + + + + + 256 + + + + 256 + + + + 2304 + + + + 2322 + + Apple HTML pasteboard type + Apple PDF pasteboard type + Apple PICT pasteboard type + Apple PNG pasteboard type + Apple URL pasteboard type + CorePasteboardFlavorType 0x6D6F6F76 + NSColor pasteboard type + NSFilenamesPboardType + NSStringPboardType + NeXT Encapsulated PostScript v1.2 pasteboard type + NeXT RTFD pasteboard type + NeXT Rich Text Format v1.0 pasteboard type + NeXT TIFF v4.0 pasteboard type + NeXT font pasteboard type + NeXT ruler pasteboard type + WebURLsWithTitlesPboardType + public.url + + {938, 42} + + + + _NS:13 + + + + + + + + + + + + 166 + + + + 938 + 1 + + + 67121127 + 0 + + + 3 + MQA + + + + 6 + System + selectedTextBackgroundColor + + 3 + MC42NjY2NjY2NjY3AA + + + + 6 + System + selectedTextColor + + 3 + MAA + + + + + + + 1 + MCAwIDEAA + + + {8, -8} + 13 + + + + + + 1 + + 6 + {939, 10000000} + + + + {{1, 1}, {938, 42}} + + + + _NS:11 + + + + {4, 5} + + 79691776 + + + + + + file://localhost/Applications/Xcode.app/Contents/SharedFrameworks/DVTKit.framework/Resources/DVTIbeamCursor.tiff + + + + + 3 + MCAwAA + + + + 4 + + + + 256 + {{923, 1}, {16, 42}} + + + + _NS:83 + NO + + _doScroller: + 0.96666666666666667 + + + + -2147483392 + {{-100, -100}, {87, 18}} + + + + _NS:33 + NO + 1 + + _doScroller: + 1 + 0.94565218687057495 + + + {{-1, -1}, {940, 44}} + + + + _NS:9 + 133138 + + + + 0.25 + 4 + 1 + + + {938, 42} + + + + _NS:21 + + {{0, 0}, {2560, 1440}} + {10000000000000, 10000000000000} + YES + @@ -471,6 +671,22 @@ 850 + + + inputWindow + + + + 953 + + + + inputView + + + + 954 + @@ -726,6 +942,131 @@ + + 941 + + + + + + + + 942 + + + + + + 4 + 0 + + 4 + 1 + + -1 + + 1000 + + 8 + 29 + 3 + + + + 6 + 0 + + 6 + 1 + + -1 + + 1000 + + 8 + 29 + 3 + + + + 3 + 0 + + 3 + 1 + + -1 + + 1000 + + 8 + 29 + 3 + + + + 5 + 0 + + 5 + 1 + + -1 + + 1000 + + 8 + 29 + 3 + + + + + + 943 + + + + + + + + + + 944 + + + + + 945 + + + + + 946 + + + + + 949 + + + + + 950 + + + + + 951 + + + + + 952 + + + @@ -770,12 +1111,31 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + LLNonInlineTextView + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin - 940 + 954 @@ -783,13 +1143,18 @@ LLAppDelegate NSObject - LLOpenGLView + LLNonInlineTextView + NSWindow LLNSWindow - - glview - LLOpenGLView + + inputView + LLNonInlineTextView + + + inputWindow + NSWindow window @@ -810,11 +1175,11 @@ - LLOpenGLView - NSOpenGLView + LLNonInlineTextView + NSTextView IBProjectSource - ./Classes/LLOpenGLView.h + ./Classes/LLNonInlineTextView.h diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index 5fb5087cd8..8da44fcf33 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -12,6 +12,8 @@ @implementation LLAppDelegate @synthesize window; +@synthesize inputWindow; +@synthesize inputView; - (void)dealloc { @@ -63,4 +65,17 @@ } } +- (void) showInputWindow:(bool)show +{ + if (show) + { + NSLog(@"Showing input window."); + [inputWindow makeKeyAndOrderFront:inputWindow]; + } else { + NSLog(@"Hiding input window."); + [inputWindow orderOut:inputWindow]; + [window makeKeyAndOrderFront:window]; + } +} + @end -- cgit v1.3 From 5098d43a9be5b9638a8806918e9bb82a096c000f Mon Sep 17 00:00:00 2001 From: Geenz Date: Mon, 1 Apr 2013 08:25:11 -0400 Subject: STORM-1941: Cocoa project viewer: some coordinate conversions are off (Katharine Berry) --- doc/contributions.txt | 2 ++ indra/llwindow/llwindowmacosx.cpp | 70 +++++---------------------------------- 2 files changed, 10 insertions(+), 62 deletions(-) (limited to 'indra/llwindow') diff --git a/doc/contributions.txt b/doc/contributions.txt index e86ef11a72..f7f528e084 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -661,6 +661,8 @@ Kagehi Kohn Kaimen Takahe Katharine Berry STORM-1900 + STORM-1940 + STORM-1941 Keklily Longfall Ken Lavender Ken March diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 2d0f981b3e..4f6ae5c799 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -1255,52 +1255,21 @@ LLWindow::LLWindowResolution* LLWindowMacOSX::getSupportedResolutions(S32 &num_r BOOL LLWindowMacOSX::convertCoords(LLCoordGL from, LLCoordWindow *to) { - S32 client_height; - float client_rect[4]; - getContentViewBounds(mWindow, client_rect); - if (!mWindow || - NULL == to) - { - return FALSE; - } - to->mX = from.mX; - client_height = client_rect[3]; - to->mY = from.mY - 1; - + to->mY = from.mY; return TRUE; } BOOL LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordGL* to) { - S32 client_height; - float client_rect[4]; - - getContentViewBounds(mWindow, client_rect); - - if (!mWindow || - NULL == to) - { - return FALSE; - } - to->mX = from.mX; - client_height = client_rect[3]; - to->mY = from.mY - 1; - + to->mY = from.mY; return TRUE; } BOOL LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordWindow* to) { - if(mFullscreen) - { - // In the fullscreen case, window and screen coordinates are the same. - to->mX = from.mX; - to->mY = from.mY; - return TRUE; - } - else if(mWindow) + if(mWindow) { float mouse_point[2]; @@ -1314,20 +1283,12 @@ BOOL LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordWindow* to) return TRUE; } - return FALSE; } BOOL LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordScreen *to) { - if(mFullscreen) - { - // In the fullscreen case, window and screen coordinates are the same. - to->mX = from.mX; - to->mY = from.mY; - return TRUE; - } - else if(mWindow) + if(mWindow) { float mouse_point[2]; @@ -1340,7 +1301,6 @@ BOOL LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordScreen *to) return TRUE; } - return FALSE; } @@ -1354,22 +1314,8 @@ 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 FALSE; + return(convertCoords(from, &window_coord) && convertCoords(window_coord, to)); } @@ -1981,11 +1927,11 @@ void LLWindowMacOSX::handleDragNDrop(std::string url, LLWindowCallbacks::DragNDr MASK mask = LLWindowMacOSX::modifiersToMask(getModifiers()); float mouse_point[2]; - // This will return the mouse point in global screen coords + // This will return the mouse point in window coords getCursorPos(mWindow, mouse_point); - LLCoordScreen screen_coords(mouse_point[0], mouse_point[1]); + LLCoordWindow window_coords(mouse_point[0], mouse_point[1]); LLCoordGL gl_pos; - convertCoords(screen_coords, &gl_pos); + convertCoords(window_coords, &gl_pos); if(!url.empty()) { -- cgit v1.3 From aa0cb35db561004c205c7aac2570407ae88ad472 Mon Sep 17 00:00:00 2001 From: Geenz Date: Sun, 7 Apr 2013 11:33:39 -0400 Subject: Support the committing of the current pre edit string when language input is interrupted per the viewer's original pre edit functionality. --- indra/llwindow/llopenglview-objc.h | 3 +++ indra/llwindow/llopenglview-objc.mm | 11 +++++++++++ indra/llwindow/llwindowmacosx-objc.h | 1 + indra/llwindow/llwindowmacosx-objc.mm | 5 +++++ indra/llwindow/llwindowmacosx.cpp | 2 +- 5 files changed, 21 insertions(+), 1 deletion(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llopenglview-objc.h b/indra/llwindow/llopenglview-objc.h index 6b21148bb6..6d0f138950 100644 --- a/indra/llwindow/llopenglview-objc.h +++ b/indra/llwindow/llopenglview-objc.h @@ -19,11 +19,14 @@ float mMousePos[2]; bool mHasMarkedText; unsigned int mMarkedTextLength; + NSAttributedString *mMarkedText; } - (id) initWithSamples:(NSUInteger)samples; - (id) initWithSamples:(NSUInteger)samples andVsync:(BOOL)vsync; - (id) initWithFrame:(NSRect)frame withSamples:(NSUInteger)samples andVsync:(BOOL)vsync; +- (void)commitCurrentPreedit; + // rebuildContext // Destroys and recreates a context with the view's internal format set via setPixelFormat; // Use this in event of needing to rebuild a context for whatever reason, without needing to assign a new pixel format. diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index a6ef35a8eb..9d55b2c551 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -420,11 +420,20 @@ attributedStringInfo getSegments(NSAttributedString *str) setMarkedText(text, selected, replacement, [aString length], segments); mHasMarkedText = TRUE; mMarkedTextLength = [aString length]; + mMarkedText = (NSAttributedString*)[aString mutableString]; } } +- (void)commitCurrentPreedit +{ + [self insertText:mMarkedText replacementRange:NSMakeRange(0, [mMarkedText length])]; + [[self inputContext] discardMarkedText]; +} + - (void)unmarkText { + [[self inputContext] discardMarkedText]; + [mMarkedText setValue:@""]; resetPreedit(); mHasMarkedText = FALSE; } @@ -517,6 +526,8 @@ attributedStringInfo getSegments(NSAttributedString *str) { [glview insertText:aString replacementRange:replacementRange]; [_window orderOut:_window]; + [[self textStorage] setValue:@""]; + [[self inputContext] discardMarkedText]; } @end diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index 14a0c22d66..59d956d4c8 100644 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -117,6 +117,7 @@ void callFocus(); void callFocusLost(); void callModifier(unsigned int mask); void callQuitHandler(); +void commitCurrentPreedit(GLViewRef glView); #include void callHandleDragEntered(std::string url); diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index 0eef8c9f83..4bd65ade82 100644 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -372,6 +372,11 @@ void showInputWindow(bool show) [(LLAppDelegate*)[NSApp delegate] showInputWindow:show]; } +void commitCurrentPreedit(GLViewRef glView) +{ + [(LLOpenGLView*)glView commitCurrentPreedit]; +} + NSWindowRef getMainAppWindow() { LLNSWindow *winRef = [(LLAppDelegate*)[[NSApplication sharedApplication] delegate] window]; diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 4f6ae5c799..e1220c83f4 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -1864,7 +1864,7 @@ void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) void LLWindowMacOSX::interruptLanguageTextInput() { - // TODO: IME support + commitCurrentPreedit(mGLView); } //static -- cgit v1.3 From 87ba85eaabbfd5fd7ad8ca8136f4783b1d932264 Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 24 Apr 2013 09:35:38 -0700 Subject: diff -r 59c7bed66dfd indra/llcommon/lleventapi.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- indra/llcommon/lleventapi.h | 4 +- indra/llcommon/lleventtimer.h | 2 +- indra/llcommon/llfasttimer.cpp | 8 +-- indra/llcommon/llfasttimer.h | 4 +- indra/llcommon/llinstancetracker.cpp | 22 -------- indra/llcommon/llinstancetracker.h | 58 +++------------------ indra/llcommon/llleap.h | 2 +- indra/llcommon/llsingleton.cpp | 1 - indra/llcommon/llsingleton.h | 60 ++++------------------ indra/llcommon/tests/llinstancetracker_test.cpp | 6 +-- indra/llrender/llgl.h | 4 +- indra/llui/llconsole.h | 2 +- indra/llui/llfloater.h | 2 +- indra/llui/lllayoutstack.h | 2 +- indra/llui/llnotifications.cpp | 4 +- indra/llui/llnotifications.h | 6 +-- indra/llwindow/llwindow.h | 2 +- indra/llxml/llcontrol.cpp | 2 +- indra/llxml/llcontrol.h | 10 ++-- indra/newview/llfloaterwebcontent.cpp | 2 +- indra/newview/llfloaterwebcontent.h | 4 +- indra/newview/llmediactrl.cpp | 2 +- indra/newview/llmediactrl.h | 2 +- indra/newview/llnamelistctrl.h | 2 +- indra/newview/lltoast.cpp | 3 +- indra/newview/lltoast.h | 2 +- indra/newview/lltoastnotifypanel.cpp | 2 +- indra/newview/lltoastnotifypanel.h | 2 +- indra/newview/lltoolselect.h | 2 +- indra/newview/tests/llagentaccess_test.cpp | 2 +- indra/newview/tests/lllogininstance_test.cpp | 2 +- indra/newview/tests/llremoteparcelrequest_test.cpp | 2 +- indra/newview/tests/llsecapi_test.cpp | 2 +- indra/newview/tests/llsechandler_basic_test.cpp | 2 +- indra/newview/tests/llslurl_test.cpp | 2 +- indra/newview/tests/lltranslate_test.cpp | 2 +- indra/newview/tests/llviewerhelputil_test.cpp | 2 +- indra/newview/tests/llviewernetwork_test.cpp | 2 +- indra/newview/tests/llworldmipmap_test.cpp | 2 +- 39 files changed, 68 insertions(+), 176 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llcommon/lleventapi.h b/indra/llcommon/lleventapi.h index 10c7e7a23f..5991fe8fd5 100644 --- a/indra/llcommon/lleventapi.h +++ b/indra/llcommon/lleventapi.h @@ -41,10 +41,10 @@ * Deriving from LLInstanceTracker lets us enumerate instances. */ class LL_COMMON_API LLEventAPI: public LLDispatchListener, - public INSTANCE_TRACKER_KEYED(LLEventAPI, std::string) + public LLInstanceTracker { typedef LLDispatchListener lbase; - typedef INSTANCE_TRACKER_KEYED(LLEventAPI, std::string) ibase; + typedef LLInstanceTracker ibase; public: diff --git a/indra/llcommon/lleventtimer.h b/indra/llcommon/lleventtimer.h index e55f851758..dc918121e1 100644 --- a/indra/llcommon/lleventtimer.h +++ b/indra/llcommon/lleventtimer.h @@ -33,7 +33,7 @@ #include "lltimer.h" // class for scheduling a function to be called at a given frequency (approximate, inprecise) -class LL_COMMON_API LLEventTimer : public INSTANCE_TRACKER(LLEventTimer) +class LL_COMMON_API LLEventTimer : public LLInstanceTracker { public: diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp index 9b15804e97..51a9441cd5 100644 --- a/indra/llcommon/llfasttimer.cpp +++ b/indra/llcommon/llfasttimer.cpp @@ -107,17 +107,13 @@ class NamedTimerFactory : public LLSingleton { public: NamedTimerFactory() - : mTimerRoot(NULL) - {} - - /*virtual */ void initSingleton() + : mTimerRoot(new LLFastTimer::NamedTimer("root")) { - mTimerRoot = new LLFastTimer::NamedTimer("root"); mRootFrameState.setNamedTimer(mTimerRoot); mTimerRoot->setFrameState(&mRootFrameState); mTimerRoot->mParent = mTimerRoot; mTimerRoot->setCollapsed(false); - mRootFrameState.mParent = &mRootFrameState; + mRootFrameState.mParent = &mRootFrameState; } ~NamedTimerFactory() diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index a6b34bdc69..a99a1d88af 100644 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -63,7 +63,7 @@ public: // stores a "named" timer instance to be reused via multiple LLFastTimer stack instances class LL_COMMON_API NamedTimer - : public LLInstanceTracker + : public LLInstanceTracker { friend class DeclareTimer; public: @@ -139,7 +139,7 @@ public: // used to statically declare a new named timer class LL_COMMON_API DeclareTimer - : public LLInstanceTracker< DeclareTimer, InstanceTrackType_DeclareTimer > + : public LLInstanceTracker< DeclareTimer > { friend class LLFastTimer; public: diff --git a/indra/llcommon/llinstancetracker.cpp b/indra/llcommon/llinstancetracker.cpp index 89430f82d7..247d0dc4fb 100644 --- a/indra/llcommon/llinstancetracker.cpp +++ b/indra/llcommon/llinstancetracker.cpp @@ -32,26 +32,4 @@ // external library headers // other Linden headers -static bool sInstanceTrackerData_initialized = false; -static void* sInstanceTrackerData[ kInstanceTrackTypeCount ]; - - -void * & LLInstanceTrackerBase::getInstances(InstanceTrackType t) -{ - // std::map::insert() is just what we want here. You attempt to insert a - // (key, value) pair. If the specified key doesn't yet exist, it inserts - // the pair and returns a std::pair of (iterator, true). If the specified - // key DOES exist, insert() simply returns (iterator, false). One lookup - // handles both cases. - if (!sInstanceTrackerData_initialized) - { - for (S32 i = 0; i < (S32) kInstanceTrackTypeCount; i++) - { - sInstanceTrackerData[i] = NULL; - } - sInstanceTrackerData_initialized = true; - } - - return sInstanceTrackerData[t]; -} diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index b290526754..361182380a 100644 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -38,33 +38,6 @@ #include #include -enum InstanceTrackType -{ - InstanceTrackType_LLEventAPI, - InstanceTrackType_LLEventTimer, - InstanceTrackType_NamedTimer, - InstanceTrackType_DeclareTimer, - InstanceTrackType_LLLeap, - InstanceTrackType_LLGLNamePool, - InstanceTrackType_LLConsole, - InstanceTrackType_LLFloater, - InstanceTrackType_LLFloaterWebContent, - InstanceTrackType_LLLayoutStack, - InstanceTrackType_LLNotificationContext, - InstanceTrackType_LLWindow, - InstanceTrackType_LLControlGroup, - InstanceTrackType_LLControlCache, - InstanceTrackType_LLMediaCtrl, - InstanceTrackType_LLNameListCtrl, - InstanceTrackType_LLToast, - InstanceTrackType_Keyed, // for integ tests - InstanceTrackType_Unkeyed, // for integ tests - kInstanceTrackTypeCount -}; - -#define INSTANCE_TRACKER(T) LLInstanceTracker< T, InstanceTrackType_##T > -#define INSTANCE_TRACKER_KEYED(T,K) LLInstanceTracker< T, InstanceTrackType_##T, K > - /** * Base class manages "class-static" data that must actually have singleton * semantics: one instance per process, rather than one instance per module as @@ -73,22 +46,7 @@ enum InstanceTrackType class LL_COMMON_API LLInstanceTrackerBase { protected: - /// Get a process-unique void* pointer slot for the specified type_info - //static void * & getInstances(std::type_info const & info); - static void * & getInstances(InstanceTrackType t); - - /// Find or create a STATICDATA instance for the specified TRACKED class. - /// STATICDATA must be default-constructible. - template - static STATICDATA& getStatic() - { - void *& instances = getInstances(TRACKEDTYPE); - if (! instances) - { - instances = new STATICDATA; - } - return *static_cast(instances); - } + /// It's not essential to derive your STATICDATA (for use with /// getStatic()) from StaticBase; it's just that both known @@ -108,16 +66,16 @@ LL_COMMON_API void assert_main_thread(); /// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup /// If KEY is not provided, then instances are stored in a simple set /// @NOTE: see explicit specialization below for default KEY==T* case -template +template class LLInstanceTracker : public LLInstanceTrackerBase { - typedef LLInstanceTracker MyT; + typedef LLInstanceTracker self_t; typedef typename std::map InstanceMap; struct StaticData: public StaticBase { InstanceMap sMap; }; - static StaticData& getStatic() { return LLInstanceTrackerBase::getStatic(); } + static StaticData& getStatic() { static StaticData sData; return sData;} static InstanceMap& getMap_() { // assert_main_thread(); fwiw this class is not thread safe, and it used by multiple threads. Bad things happen. @@ -263,16 +221,16 @@ private: /// explicit specialization for default case where KEY is T* /// use a simple std::set -template -class LLInstanceTracker : public LLInstanceTrackerBase +template +class LLInstanceTracker : public LLInstanceTrackerBase { - typedef LLInstanceTracker MyT; + typedef LLInstanceTracker self_t; typedef typename std::set InstanceSet; struct StaticData: public StaticBase { InstanceSet sSet; }; - static StaticData& getStatic() { return LLInstanceTrackerBase::getStatic(); } + static StaticData& getStatic() { static StaticData sData; return sData; } static InstanceSet& getSet_() { return getStatic().sSet; } public: diff --git a/indra/llcommon/llleap.h b/indra/llcommon/llleap.h index d4e138f4be..e33f25e530 100644 --- a/indra/llcommon/llleap.h +++ b/indra/llcommon/llleap.h @@ -29,7 +29,7 @@ * LLLeap* pointer should be validated before use by * LLLeap::getInstance(LLLeap*) (see LLInstanceTracker). */ -class LL_COMMON_API LLLeap: public INSTANCE_TRACKER(LLLeap) +class LL_COMMON_API LLLeap: public LLInstanceTracker { public: diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp index eb8e2c9456..9b49e52377 100644 --- a/indra/llcommon/llsingleton.cpp +++ b/indra/llcommon/llsingleton.cpp @@ -28,5 +28,4 @@ #include "llsingleton.h" -std::map * LLSingletonRegistry::sSingletonMap = NULL; diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h index 49d99f2cd0..84afeb563e 100644 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -30,38 +30,6 @@ #include #include -/// @brief A global registry of all singletons to prevent duplicate allocations -/// across shared library boundaries -class LL_COMMON_API LLSingletonRegistry { - private: - typedef std::map TypeMap; - static TypeMap * sSingletonMap; - - static void checkInit() - { - if(sSingletonMap == NULL) - { - sSingletonMap = new TypeMap(); - } - } - - public: - template static void * & get() - { - std::string name(typeid(T).name()); - - checkInit(); - - // the first entry of the pair returned by insert will be either the existing - // iterator matching our key, or the newly inserted NULL initialized entry - // see "Insert element" in http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html - TypeMap::iterator result = - sSingletonMap->insert(std::make_pair(name, (void*)NULL)).first; - - return result->second; - } -}; - // LLSingleton implements the getInstance() method part of the Singleton // pattern. It can't make the derived class constructors protected, though, so // you have to do that yourself. @@ -93,7 +61,6 @@ class LLSingleton : private boost::noncopyable private: typedef enum e_init_state { - UNINITIALIZED, CONSTRUCTING, INITIALIZING, INITIALIZED, @@ -109,8 +76,11 @@ private: SingletonInstanceData() : mSingletonInstance(NULL), - mInitState(UNINITIALIZED) - {} + mInitState(CONSTRUCTING) + { + mSingletonInstance = new DERIVED_TYPE(); + mInitState = INITIALIZING; + } ~SingletonInstanceData() { @@ -159,16 +129,8 @@ public: static SingletonInstanceData& getData() { // this is static to cache the lookup results - static void * & registry = LLSingletonRegistry::get(); - - // *TODO - look into making this threadsafe - if(NULL == registry) - { - static SingletonInstanceData data; - registry = &data; - } - - return *static_cast(registry); + static SingletonInstanceData sData; + return sData; } static DERIVED_TYPE* getInstance() @@ -185,13 +147,11 @@ public: llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl; } - if (!data.mSingletonInstance) + if (data.mInitState == INITIALIZING) { - data.mInitState = CONSTRUCTING; - data.mSingletonInstance = new DERIVED_TYPE(); - data.mInitState = INITIALIZING; + // go ahead and flag ourselves as initialized so we can be reentrant during initialization + data.mInitState = INITIALIZED; data.mSingletonInstance->initSingleton(); - data.mInitState = INITIALIZED; } return data.mSingletonInstance; diff --git a/indra/llcommon/tests/llinstancetracker_test.cpp b/indra/llcommon/tests/llinstancetracker_test.cpp index b2d82d1843..e769c3e22c 100644 --- a/indra/llcommon/tests/llinstancetracker_test.cpp +++ b/indra/llcommon/tests/llinstancetracker_test.cpp @@ -48,16 +48,16 @@ struct Badness: public std::runtime_error Badness(const std::string& what): std::runtime_error(what) {} }; -struct Keyed: public INSTANCE_TRACKER_KEYED(Keyed, std::string) +struct Keyed: public LLInstanceTracker { Keyed(const std::string& name): - INSTANCE_TRACKER_KEYED(Keyed, std::string)(name), + LLInstanceTracker(name), mName(name) {} std::string mName; }; -struct Unkeyed: public INSTANCE_TRACKER(Unkeyed) +struct Unkeyed: public LLInstanceTracker { Unkeyed(const std::string& thrw="") { diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 133c2de1f5..823de9d361 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -350,10 +350,10 @@ public: Generic pooling scheme for things which use GL names (used for occlusion queries and vertex buffer objects). Prevents thrashing of GL name caches by avoiding calls to glGenFoo and glDeleteFoo. */ -class LLGLNamePool : public INSTANCE_TRACKER(LLGLNamePool) +class LLGLNamePool : public LLInstanceTracker { public: - typedef INSTANCE_TRACKER(LLGLNamePool) tracker_t; + typedef LLInstanceTracker tracker_t; struct NameEntry { diff --git a/indra/llui/llconsole.h b/indra/llui/llconsole.h index b264aeb7eb..5ff05698b0 100644 --- a/indra/llui/llconsole.h +++ b/indra/llui/llconsole.h @@ -34,7 +34,7 @@ class LLSD; -class LLConsole : public LLFixedBuffer, public LLUICtrl, public INSTANCE_TRACKER(LLConsole) +class LLConsole : public LLFixedBuffer, public LLUICtrl, public LLInstanceTracker { public: diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index f28ceb0ce4..99d1d2614d 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -116,7 +116,7 @@ struct LLCoordFloater : LLCoord }; -class LLFloater : public LLPanel, public INSTANCE_TRACKER(LLFloater) +class LLFloater : public LLPanel, public LLInstanceTracker { friend class LLFloaterView; friend class LLFloaterReg; diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index a8b5466242..8e330278af 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -35,7 +35,7 @@ class LLLayoutPanel; -class LLLayoutStack : public LLView, public INSTANCE_TRACKER(LLLayoutStack) +class LLLayoutStack : public LLView, public LLInstanceTracker { public: diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 8bafbd53d8..1789f003b9 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1121,7 +1121,7 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt LLNotificationChannel::LLNotificationChannel(const Params& p) : LLNotificationChannelBase(p.filter()), - LLInstanceTracker(p.name.isProvided() ? p.name : LLUUID::generateNewID().asString()), + LLInstanceTracker(p.name.isProvided() ? p.name : LLUUID::generateNewID().asString()), mName(p.name.isProvided() ? p.name : LLUUID::generateNewID().asString()) { BOOST_FOREACH(const std::string& source, p.sources) @@ -1135,7 +1135,7 @@ LLNotificationChannel::LLNotificationChannel(const std::string& name, const std::string& parent, LLNotificationFilter filter) : LLNotificationChannelBase(filter), - LLInstanceTracker(name), + LLInstanceTracker(name), mName(name) { // bind to notification broadcast diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 2561125aa5..cd3728305e 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -135,11 +135,11 @@ typedef LLFunctorRegistration LLNotificationFunctorRegi // context data that can be looked up via a notification's payload by the display logic // derive from this class to implement specific contexts -class LLNotificationContext : public INSTANCE_TRACKER_KEYED(LLNotificationContext, LLUUID) +class LLNotificationContext : public LLInstanceTracker { public: - LLNotificationContext() : INSTANCE_TRACKER_KEYED(LLNotificationContext, LLUUID)(LLUUID::generateNewID()) + LLNotificationContext() : LLInstanceTracker(LLUUID::generateNewID()) { } @@ -815,7 +815,7 @@ typedef boost::intrusive_ptr LLNotificationChannelPtr; class LLNotificationChannel : boost::noncopyable, public LLNotificationChannelBase, - public LLInstanceTracker + public LLInstanceTracker { LOG_CLASS(LLNotificationChannel); diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index 06d7e4907a..78186004b8 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -39,7 +39,7 @@ class LLWindowCallbacks; // Refer to llwindow_test in test/common/llwindow for usage example -class LLWindow : public INSTANCE_TRACKER(LLWindow) +class LLWindow : public LLInstanceTracker { public: diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp index f82750af47..666c03e9ff 100644 --- a/indra/llxml/llcontrol.cpp +++ b/indra/llxml/llcontrol.cpp @@ -316,7 +316,7 @@ LLPointer LLControlGroup::getControl(const std::string& name) //////////////////////////////////////////////////////////////////////////// LLControlGroup::LLControlGroup(const std::string& name) -: INSTANCE_TRACKER_KEYED(LLControlGroup, std::string)(name) +: LLInstanceTracker(name) { mTypeString[TYPE_U32] = "U32"; mTypeString[TYPE_S32] = "S32"; diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index 6ea010f4f9..ee7d1d50b7 100644 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -180,7 +180,7 @@ T convert_from_llsd(const LLSD& sd, eControlType type, const std::string& contro } //const U32 STRING_CACHE_SIZE = 10000; -class LLControlGroup : public INSTANCE_TRACKER_KEYED(LLControlGroup, std::string) +class LLControlGroup : public LLInstanceTracker { LOG_CLASS(LLControlGroup); @@ -197,7 +197,7 @@ public: ~LLControlGroup(); void cleanup(); - typedef INSTANCE_TRACKER_KEYED(LLControlGroup, std::string)::instance_iter instance_iter; + typedef LLInstanceTracker::instance_iter instance_iter; LLControlVariablePtr getControl(const std::string& name); @@ -306,7 +306,7 @@ public: //! without have to manually create and bind a listener to a local //! object. template -class LLControlCache : public LLRefCount, public LLInstanceTracker, InstanceTrackType_LLControlCache, std::string> +class LLControlCache : public LLRefCount, public LLInstanceTracker, std::string> { public: // This constructor will declare a control if it doesn't exist in the contol group @@ -314,7 +314,7 @@ public: const std::string& name, const T& default_value, const std::string& comment) - : LLInstanceTracker, InstanceTrackType_LLControlCache, std::string >(name) + : LLInstanceTracker, std::string >(name) { if(!group.controlExists(name)) { @@ -329,7 +329,7 @@ public: LLControlCache(LLControlGroup& group, const std::string& name) - : LLInstanceTracker, InstanceTrackType_LLControlCache, std::string >(name) + : LLInstanceTracker, std::string >(name) { if(!group.controlExists(name)) { diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index 94c3f4149c..3fe2518de6 100644 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -54,7 +54,7 @@ LLFloaterWebContent::_Params::_Params() LLFloaterWebContent::LLFloaterWebContent( const Params& params ) : LLFloater( params ), - INSTANCE_TRACKER_KEYED(LLFloaterWebContent, std::string)(params.id()), + LLInstanceTracker(params.id()), mWebBrowser(NULL), mAddressCombo(NULL), mSecureLockIcon(NULL), diff --git a/indra/newview/llfloaterwebcontent.h b/indra/newview/llfloaterwebcontent.h index 409c15fb0b..86b5a5e00b 100644 --- a/indra/newview/llfloaterwebcontent.h +++ b/indra/newview/llfloaterwebcontent.h @@ -40,11 +40,11 @@ class LLIconCtrl; class LLFloaterWebContent : public LLFloater, public LLViewerMediaObserver, - public INSTANCE_TRACKER_KEYED(LLFloaterWebContent, std::string) + public LLInstanceTracker { public: - typedef INSTANCE_TRACKER_KEYED(LLFloaterWebContent, std::string) instance_tracker_t; + typedef LLInstanceTracker instance_tracker_t; LOG_CLASS(LLFloaterWebContent); struct _Params : public LLInitParam::Block<_Params> diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 6362165c77..2075aeed63 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -81,7 +81,7 @@ LLMediaCtrl::Params::Params() LLMediaCtrl::LLMediaCtrl( const Params& p) : LLPanel( p ), - INSTANCE_TRACKER_KEYED(LLMediaCtrl, LLUUID)(LLUUID::generateNewID()), + LLInstanceTracker(LLUUID::generateNewID()), mTextureDepthBytes( 4 ), mBorder(NULL), mFrequentUpdates( true ), diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index 4fed21bf22..6c38c1fb56 100644 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -42,7 +42,7 @@ class LLMediaCtrl : public LLPanel, public LLViewerMediaObserver, public LLViewerMediaEventEmitter, - public INSTANCE_TRACKER_KEYED(LLMediaCtrl, LLUUID) + public LLInstanceTracker { LOG_CLASS(LLMediaCtrl); public: diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h index d82727f018..92e82b672d 100644 --- a/indra/newview/llnamelistctrl.h +++ b/indra/newview/llnamelistctrl.h @@ -64,7 +64,7 @@ private: class LLNameListCtrl -: public LLScrollListCtrl, public INSTANCE_TRACKER(LLNameListCtrl) +: public LLScrollListCtrl, public LLInstanceTracker { public: diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp index 49debe67f6..a26e47e1c8 100644 --- a/indra/newview/lltoast.cpp +++ b/indra/newview/lltoast.cpp @@ -572,7 +572,8 @@ S32 LLToast::notifyParent(const LLSD& info) //static void LLToast::updateClass() { - for (INSTANCE_TRACKER(LLToast)::instance_iter iter = INSTANCE_TRACKER(LLToast)::beginInstances(); iter != INSTANCE_TRACKER(LLToast)::endInstances(); ) + for (LLInstanceTracker::instance_iter iter = LLInstanceTracker::beginInstances(); + iter != LLInstanceTracker::endInstances(); ) { LLToast& toast = *iter++; diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h index 718b464977..5da7120e84 100644 --- a/indra/newview/lltoast.h +++ b/indra/newview/lltoast.h @@ -69,7 +69,7 @@ private : * Represents toast pop-up. * This is a parent view for all toast panels. */ -class LLToast : public LLModalDialog, public INSTANCE_TRACKER(LLToast) +class LLToast : public LLModalDialog, public LLInstanceTracker { friend class LLToastLifeTimer; public: diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index 9b5ccc0150..94d07b37ef 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -57,7 +57,7 @@ LLToastNotifyPanel::button_click_signal_t LLToastNotifyPanel::sButtonClickSignal LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, const LLRect& rect, bool show_images) : LLToastPanel(notification), - LLInstanceTracker(notification->getID()) + LLInstanceTracker(notification->getID()) { init(rect, show_images); } diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h index 5de75a7a9f..d02171b512 100644 --- a/indra/newview/lltoastnotifypanel.h +++ b/indra/newview/lltoastnotifypanel.h @@ -47,7 +47,7 @@ class LLNotificationForm; * @deprecated this class will be removed after all toast panel types are * implemented in separate classes. */ -class LLToastNotifyPanel: public LLToastPanel, public LLInstanceTracker +class LLToastNotifyPanel: public LLToastPanel, public LLInstanceTracker { public: /** diff --git a/indra/newview/lltoolselect.h b/indra/newview/lltoolselect.h index baa27f6071..74dababe8c 100644 --- a/indra/newview/lltoolselect.h +++ b/indra/newview/lltoolselect.h @@ -34,7 +34,7 @@ class LLObjectSelection; -class LLToolSelect : public LLTool, public LLSingleton +class LLToolSelect : public LLTool { public: LLToolSelect( LLToolComposite* composite ); diff --git a/indra/newview/tests/llagentaccess_test.cpp b/indra/newview/tests/llagentaccess_test.cpp index 426ad40342..05289f0309 100644 --- a/indra/newview/tests/llagentaccess_test.cpp +++ b/indra/newview/tests/llagentaccess_test.cpp @@ -40,7 +40,7 @@ static U32 test_preferred_maturity = SIM_ACCESS_PG; LLControlGroup::LLControlGroup(const std::string& name) - : INSTANCE_TRACKER_KEYED(LLControlGroup, std::string)(name) +: LLInstanceTracker(name) { } diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp index 25da5939f1..7705b4c567 100644 --- a/indra/newview/tests/lllogininstance_test.cpp +++ b/indra/newview/tests/lllogininstance_test.cpp @@ -167,7 +167,7 @@ std::string LLGridManager::getAppSLURLBase(const std::string& grid_name) LLControlGroup gSavedSettings("Global"); LLControlGroup::LLControlGroup(const std::string& name) : - INSTANCE_TRACKER_KEYED(LLControlGroup, std::string)(name){} + LLInstanceTracker(name){} LLControlGroup::~LLControlGroup() {} void LLControlGroup::setBOOL(const std::string& name, BOOL val) {} BOOL LLControlGroup::getBOOL(const std::string& name) { return FALSE; } diff --git a/indra/newview/tests/llremoteparcelrequest_test.cpp b/indra/newview/tests/llremoteparcelrequest_test.cpp index da273132db..ed66066b0a 100644 --- a/indra/newview/tests/llremoteparcelrequest_test.cpp +++ b/indra/newview/tests/llremoteparcelrequest_test.cpp @@ -69,7 +69,7 @@ void LLAgent::sendReliableMessage(void) { } LLUUID gAgentSessionID; LLUUID gAgentID; LLUIColor::LLUIColor(void) { } -LLControlGroup::LLControlGroup(std::string const & name) : INSTANCE_TRACKER_KEYED(LLControlGroup, std::string)(name) { } +LLControlGroup::LLControlGroup(std::string const & name) : LLInstanceTracker(name) { } LLControlGroup::~LLControlGroup(void) { } void LLUrlEntryParcel::processParcelInfo(const LLUrlEntryParcel::LLParcelData& parcel_data) { } diff --git a/indra/newview/tests/llsecapi_test.cpp b/indra/newview/tests/llsecapi_test.cpp index 83a4149971..703603e2db 100644 --- a/indra/newview/tests/llsecapi_test.cpp +++ b/indra/newview/tests/llsecapi_test.cpp @@ -37,7 +37,7 @@ // Mock objects for the dependencies of the code we're testing LLControlGroup::LLControlGroup(const std::string& name) -: INSTANCE_TRACKER_KEYED(LLControlGroup, std::string)(name) {} +: LLInstanceTracker(name) {} LLControlGroup::~LLControlGroup() {} BOOL LLControlGroup::declareString(const std::string& name, const std::string& initial_val, diff --git a/indra/newview/tests/llsechandler_basic_test.cpp b/indra/newview/tests/llsechandler_basic_test.cpp index 814010028f..0235400976 100644 --- a/indra/newview/tests/llsechandler_basic_test.cpp +++ b/indra/newview/tests/llsechandler_basic_test.cpp @@ -69,7 +69,7 @@ extern bool _cert_hostname_wildcard_match(const std::string& hostname, const std std::string gFirstName; std::string gLastName; LLControlGroup::LLControlGroup(const std::string& name) -: INSTANCE_TRACKER_KEYED(LLControlGroup, std::string)(name) {} +: LLInstanceTracker(name) {} LLControlGroup::~LLControlGroup() {} BOOL LLControlGroup::declareString(const std::string& name, const std::string& initial_val, diff --git a/indra/newview/tests/llslurl_test.cpp b/indra/newview/tests/llslurl_test.cpp index d7debd6c67..09343ef227 100644 --- a/indra/newview/tests/llslurl_test.cpp +++ b/indra/newview/tests/llslurl_test.cpp @@ -35,7 +35,7 @@ // Mock objects for the dependencies of the code we're testing LLControlGroup::LLControlGroup(const std::string& name) -: INSTANCE_TRACKER_KEYED(LLControlGroup, std::string)(name) {} +: LLInstanceTracker(name) {} LLControlGroup::~LLControlGroup() {} BOOL LLControlGroup::declareString(const std::string& name, const std::string& initial_val, diff --git a/indra/newview/tests/lltranslate_test.cpp b/indra/newview/tests/lltranslate_test.cpp index c13660332d..fd9527d631 100644 --- a/indra/newview/tests/lltranslate_test.cpp +++ b/indra/newview/tests/lltranslate_test.cpp @@ -295,7 +295,7 @@ LLControlGroup gSavedSettings("test"); std::string LLUI::getLanguage() { return "en"; } std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args) { return "dummy"; } -LLControlGroup::LLControlGroup(const std::string& name) : INSTANCE_TRACKER_KEYED(LLControlGroup, std::string)(name) {} +LLControlGroup::LLControlGroup(const std::string& name) : LLInstanceTracker(name) {} std::string LLControlGroup::getString(const std::string& name) { return "dummy"; } LLControlGroup::~LLControlGroup() {} diff --git a/indra/newview/tests/llviewerhelputil_test.cpp b/indra/newview/tests/llviewerhelputil_test.cpp index 102cad8852..710881d811 100644 --- a/indra/newview/tests/llviewerhelputil_test.cpp +++ b/indra/newview/tests/llviewerhelputil_test.cpp @@ -47,7 +47,7 @@ static std::string gOS; // Mock objects for the dependencies of the code we're testing LLControlGroup::LLControlGroup(const std::string& name) - : INSTANCE_TRACKER_KEYED(LLControlGroup, std::string)(name) {} + : LLInstanceTracker(name) {} LLControlGroup::~LLControlGroup() {} BOOL LLControlGroup::declareString(const std::string& name, const std::string& initial_val, diff --git a/indra/newview/tests/llviewernetwork_test.cpp b/indra/newview/tests/llviewernetwork_test.cpp index 725b5122fb..a1e97ea17e 100644 --- a/indra/newview/tests/llviewernetwork_test.cpp +++ b/indra/newview/tests/llviewernetwork_test.cpp @@ -35,7 +35,7 @@ // Mock objects for the dependencies of the code we're testing LLControlGroup::LLControlGroup(const std::string& name) -: INSTANCE_TRACKER_KEYED(LLControlGroup, std::string)(name) {} +: LLInstanceTracker(name) {} LLControlGroup::~LLControlGroup() {} BOOL LLControlGroup::declareString(const std::string& name, const std::string& initial_val, diff --git a/indra/newview/tests/llworldmipmap_test.cpp b/indra/newview/tests/llworldmipmap_test.cpp index a6a2f8d7b9..142d75bcfd 100644 --- a/indra/newview/tests/llworldmipmap_test.cpp +++ b/indra/newview/tests/llworldmipmap_test.cpp @@ -46,7 +46,7 @@ void LLGLTexture::setBoostLevel(S32 ) { } LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromUrl(const std::string&, FTType, BOOL, LLGLTexture::EBoostLevel, S8, LLGLint, LLGLenum, const LLUUID& ) { return NULL; } -LLControlGroup::LLControlGroup(const std::string& name) : INSTANCE_TRACKER_KEYED(LLControlGroup, std::string)(name) { } +LLControlGroup::LLControlGroup(const std::string& name) : LLInstanceTracker(name) { } LLControlGroup::~LLControlGroup() { } std::string LLControlGroup::getString(const std::string& ) { return std::string("test_url"); } LLControlGroup gSavedSettings("test_settings"); -- cgit v1.3 From b27899ee0e035ebd4072a5e6162678f2afe81053 Mon Sep 17 00:00:00 2001 From: Geenz Date: Mon, 13 May 2013 19:39:45 -0400 Subject: Added IME input window white list. --- indra/llwindow/llappdelegate-objc.h | 4 ++++ indra/newview/SecondLife.nib | Bin 12997 -> 13009 bytes indra/newview/SecondLife.xib | 25 ++++++++++++-------- indra/newview/llappdelegate-objc.mm | 45 ++++++++++++++++++++++++++++++------ 4 files changed, 57 insertions(+), 17 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llappdelegate-objc.h b/indra/llwindow/llappdelegate-objc.h index e7f6ecd5fc..be9ad4d79f 100644 --- a/indra/llwindow/llappdelegate-objc.h +++ b/indra/llwindow/llappdelegate-objc.h @@ -14,12 +14,16 @@ NSWindow *inputWindow; LLNonInlineTextView *inputView; NSTimer *frameTimer; + NSString *currentInputLanguage; } @property (assign) IBOutlet LLNSWindow *window; @property (assign) IBOutlet NSWindow *inputWindow; @property (assign) IBOutlet LLNonInlineTextView *inputView; +@property (retain) NSString *currentInputLanguage; + - (void) mainLoop; - (void) showInputWindow:(bool)show; +- (void) languageUpdated; @end diff --git a/indra/newview/SecondLife.nib b/indra/newview/SecondLife.nib index 0b0ff5308b..cb289ebf09 100644 Binary files a/indra/newview/SecondLife.nib and b/indra/newview/SecondLife.nib differ diff --git a/indra/newview/SecondLife.xib b/indra/newview/SecondLife.xib index fdfea49c42..c6b72485a1 100644 --- a/indra/newview/SecondLife.xib +++ b/indra/newview/SecondLife.xib @@ -2,9 +2,9 @@ 1060 - 12D78 + 12E30 3084 - 1187.37 + 1187.39 626.00 com.apple.InterfaceBuilder.CocoaPlugin @@ -329,16 +329,13 @@ - + 256 {1024, 600} - - - _NS:20 - {{0, 0}, {2560, 1440}} + {{0, 0}, {2560, 1418}} {10000000000000, 10000000000000} Second Life 128 @@ -349,7 +346,7 @@ 2 {{272, 176}, {938, 42}} -1535638528 - Window + Input Window NSPanel @@ -536,7 +533,7 @@ _NS:21 - {{0, 0}, {2560, 1440}} + {{0, 0}, {2560, 1418}} {10000000000000, 10000000000000} YES @@ -1112,7 +1109,7 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - + @@ -1182,6 +1179,14 @@ ./Classes/LLNonInlineTextView.h + + NSLayoutConstraint + NSObject + + IBProjectSource + ./Classes/NSLayoutConstraint.h + + 0 diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index 8da44fcf33..de77447006 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -8,12 +8,14 @@ #import "llappdelegate-objc.h" #include "llwindowmacosx-objc.h" +#include // Used for Text Input Services ("Safe" API - it's well supported) @implementation LLAppDelegate @synthesize window; @synthesize inputWindow; @synthesize inputView; +@synthesize currentInputLanguage; - (void)dealloc { @@ -24,12 +26,16 @@ { frameTimer = nil; + [self languageUpdated]; + if (initViewer()) { frameTimer = [NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(mainLoop) userInfo:nil repeats:YES]; } else { handleQuit(); } + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(languageUpdated) name:@"NSTextInputContextKeyboardSelectionDidChangeNotification" object:nil]; } - (void) applicationDidBecomeActive:(NSNotification *)notification @@ -67,15 +73,40 @@ - (void) showInputWindow:(bool)show { - if (show) + // How to add support for new languages with the input window: + // Simply append this array with the language code (ja for japanese, ko for korean, zh for chinese, etc.) + NSArray *authorizedLanguages = [[NSArray alloc] initWithObjects:@"ja", @"ko", @"zh-Hant", @"zh-Hans", nil]; + + if ([authorizedLanguages containsObject:currentInputLanguage]) { - NSLog(@"Showing input window."); - [inputWindow makeKeyAndOrderFront:inputWindow]; - } else { - NSLog(@"Hiding input window."); - [inputWindow orderOut:inputWindow]; - [window makeKeyAndOrderFront:window]; + if (show) + { + NSLog(@"Showing input window."); + [inputWindow makeKeyAndOrderFront:inputWindow]; + } else { + NSLog(@"Hiding input window."); + [inputWindow orderOut:inputWindow]; + [window makeKeyAndOrderFront:window]; + } } } +// This will get called multiple times by NSNotificationCenter. +// It will be called every time that the window focus changes, and every time that the input language gets changed. +// The primary use case for this selector is to update our current input language when the user, for whatever reason, changes the input language. +// This is the more elegant way of handling input language changes instead of checking every time we want to use the input window. + +- (void) languageUpdated +{ + TISInputSourceRef currentInput = TISCopyCurrentKeyboardInputSource(); + CFArrayRef languages = (CFArrayRef)TISGetInputSourceProperty(currentInput, kTISPropertyInputSourceLanguages); + +#if 1 // In the event of ever needing to add new language sources, change this to 1 and watch the terminal for "languages:" + NSLog(@"languages: %@", TISGetInputSourceProperty(currentInput, kTISPropertyInputSourceLanguages)); +#endif + + // Typically the language we want is going to be the very first result in the array. + currentInputLanguage = (NSString*)CFArrayGetValueAtIndex(languages, 0); +} + @end -- cgit v1.3 From cda10266ae91e28f2ac60b8472d6b8592f877d65 Mon Sep 17 00:00:00 2001 From: Geenz Date: Thu, 23 May 2013 08:50:05 -0400 Subject: Only show the input window when we attempt to add marked text, *and* we can't submit marked text directly to the viewer. --- indra/llwindow/llopenglview-objc.h | 3 ++ indra/llwindow/llopenglview-objc.mm | 68 ++++++++++++++++++++++------------- indra/llwindow/llwindowmacosx-objc.h | 9 ++--- indra/llwindow/llwindowmacosx-objc.mm | 5 +++ indra/llwindow/llwindowmacosx.cpp | 42 ++++++++++------------ 5 files changed, 75 insertions(+), 52 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llopenglview-objc.h b/indra/llwindow/llopenglview-objc.h index 6d0f138950..e20ea533fb 100644 --- a/indra/llwindow/llopenglview-objc.h +++ b/indra/llwindow/llopenglview-objc.h @@ -20,6 +20,7 @@ bool mHasMarkedText; unsigned int mMarkedTextLength; NSAttributedString *mMarkedText; + bool mMarkedTextAllowed; } - (id) initWithSamples:(NSUInteger)samples; - (id) initWithSamples:(NSUInteger)samples andVsync:(BOOL)vsync; @@ -42,6 +43,8 @@ - (unsigned long) getVramSize; +- (void) allowMarkedTextInput:(bool)allowed; + @end @interface LLNonInlineTextView : NSTextView diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index 9d55b2c551..8ef6d4e682 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -45,6 +45,7 @@ attributedStringInfo getSegments(NSAttributedString *str) segment_standouts seg_standouts; NSRange effectiveRange; NSRange limitRange = NSMakeRange(0, [str length]); + while (limitRange.length > 0) { NSNumber *attr = [str attribute:NSUnderlineStyleAttributeName atIndex:limitRange.location longestEffectiveRange:&effectiveRange inRange:limitRange]; limitRange = NSMakeRange(NSMaxRange(effectiveRange), NSMaxRange(limitRange) - NSMaxRange(effectiveRange)); @@ -402,32 +403,40 @@ attributedStringInfo getSegments(NSAttributedString *str) - (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 - }; - - 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]; - mMarkedText = (NSAttributedString*)[aString mutableString]; - } + if (mMarkedTextAllowed) + { + if ([aString class] == NSClassFromString(@"NSConcreteMutableAttributedString")) + { + 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]; + mMarkedText = (NSAttributedString*)[aString mutableString]; + } + } else { + showInputWindow(true); + } } - (void)commitCurrentPreedit { - [self insertText:mMarkedText replacementRange:NSMakeRange(0, [mMarkedText length])]; - [[self inputContext] discardMarkedText]; + if (mMarkedText) + { + [self insertText:mMarkedText]; + [[self inputContext] discardMarkedText]; + } } - (void)unmarkText @@ -452,11 +461,12 @@ attributedStringInfo getSegments(NSAttributedString *str) - (void)insertText:(id)aString replacementRange:(NSRange)replacementRange { + bool success = false; if (!mHasMarkedText) { for (NSInteger i = 0; i < [aString length]; i++) { - callUnicodeCallback([aString characterAtIndex:i], mModifiers); + success = 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. @@ -465,10 +475,12 @@ attributedStringInfo getSegments(NSAttributedString *str) for (NSInteger i = 0; i < [aString length]; i++) { - handleUnicodeCharacter([aString characterAtIndex:i]); + success = handleUnicodeCharacter([aString characterAtIndex:i]); } mHasMarkedText = FALSE; } + + NSLog(@"Successful text input: %d", success); } - (void) insertNewline:(id)sender @@ -508,6 +520,11 @@ attributedStringInfo getSegments(NSAttributedString *str) return NO; } +- (void) allowMarkedTextInput:(bool)allowed +{ + mMarkedTextAllowed = allowed; +} + @end @implementation LLNonInlineTextView @@ -525,9 +542,10 @@ attributedStringInfo getSegments(NSAttributedString *str) - (void) insertText:(id)aString replacementRange:(NSRange)replacementRange { [glview insertText:aString replacementRange:replacementRange]; - [_window orderOut:_window]; [[self textStorage] setValue:@""]; [[self inputContext] discardMarkedText]; + [self setString:@""]; + [_window orderOut:_window]; } @end diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index 59d956d4c8..62543fa01d 100755 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -95,10 +95,10 @@ void showInputWindow(bool show); // These are all implemented in llwindowmacosx.cpp. // This is largely for easier interop between Obj-C and C++ (at least in the viewer's case due to the BOOL vs. BOOL conflict) -void callKeyUp(unsigned short key, unsigned int mask); -void callKeyDown(unsigned short key, unsigned int mask); +bool callKeyUp(unsigned short key, unsigned int mask); +bool callKeyDown(unsigned short key, unsigned int mask); void callResetKeys(); -void callUnicodeCallback(wchar_t character, unsigned int mask); +bool callUnicodeCallback(wchar_t character, unsigned int mask); void callRightMouseDown(float *pos, unsigned int mask); void callRightMouseUp(float *pos, unsigned int mask); void callLeftMouseDown(float *pos, unsigned int mask); @@ -129,13 +129,14 @@ void callHandleDragDropped(std::string url); std::basic_string getPreeditString(); void getPreeditSelectionRange(int *position, int *length); void getPreeditMarkedRange(int *position, int *length); -void handleUnicodeCharacter(wchar_t c); +bool handleUnicodeCharacter(wchar_t c); void updatePreeditor(unsigned short *str); void setPreeditMarkedRange(int position, int length); void resetPreedit(); int wstring_length(const std::basic_string & wstr, const int woffset, const int utf16_length, int *unaligned); void setMarkedText(unsigned short *text, unsigned int *selectedRange, unsigned int *replacementRange, long text_len, attributedStringInfo segments); void getPreeditLocation(float *location, unsigned int length); +void allowDirectMarkedTextInput(bool allow); NSWindowRef getMainAppWindow(); GLViewRef getGLView(); diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index 4bd65ade82..95b9cdb863 100755 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -377,6 +377,11 @@ void commitCurrentPreedit(GLViewRef glView) [(LLOpenGLView*)glView commitCurrentPreedit]; } +void allowDirectMarkedTextInput(bool allow) +{ + +} + NSWindowRef getMainAppWindow() { LLNSWindow *winRef = [(LLAppDelegate*)[[NSApplication sharedApplication] delegate] window]; diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index e1220c83f4..16fd7e3382 100755 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -204,14 +204,14 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks, // These functions are used as wrappers for our internal event handling callbacks. // It's a good idea to wrap these to avoid reworking more code than we need to within LLWindow. -void callKeyUp(unsigned short key, unsigned int mask) +bool callKeyUp(unsigned short key, unsigned int mask) { - gKeyboard->handleKeyUp(key, mask); + return gKeyboard->handleKeyUp(key, mask); } -void callKeyDown(unsigned short key, unsigned int mask) +bool callKeyDown(unsigned short key, unsigned int mask) { - gKeyboard->handleKeyDown(key, mask); + return gKeyboard->handleKeyDown(key, mask); } void callResetKeys() @@ -219,9 +219,9 @@ void callResetKeys() gKeyboard->resetKeys(); } -void callUnicodeCallback(wchar_t character, unsigned int mask) +bool callUnicodeCallback(wchar_t character, unsigned int mask) { - gWindowImplementation->getCallbacks()->handleUnicodeChar(character, mask); + return gWindowImplementation->getCallbacks()->handleUnicodeChar(character, mask); } void callFocus() @@ -408,12 +408,15 @@ void setPreeditMarkedRange(int position, int length) } } -void handleUnicodeCharacter(wchar_t c) +bool handleUnicodeCharacter(wchar_t c) { + bool success = false; if (gWindowImplementation->getPreeditor()) { - gWindowImplementation->getPreeditor()->handleUnicodeCharHere(c); + success = gWindowImplementation->getPreeditor()->handleUnicodeCharHere(c); } + + return success; } void resetPreedit() @@ -1033,21 +1036,7 @@ BOOL LLWindowMacOSX::setCursorPosition(const LLCoordWindow position) return result; } -/* -static void fixOrigin(void) -{ - GrafPtr port; - Rect portrect; - ::GetPort(&port); - ::GetPortBounds(port, &portrect); - if((portrect.left != 0) || (portrect.top != 0)) - { - // Mozilla sometimes changes our port origin. - ::SetOrigin(0,0); - } -} -*/ BOOL LLWindowMacOSX::getCursorPosition(LLCoordWindow *position) { float cursor_point[2]; @@ -1840,7 +1829,14 @@ void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) return; } - showInputWindow(!b); + if (preeditor == NULL) { + // If we don't have a pre editor, then we can't accept direct marked text input. + // We needs an input window (which is handled internally by LLOpenGLView) + allowDirectMarkedTextInput(false); + } else { + // If we have a preeditor, then accept direct marked text input. + allowDirectMarkedTextInput(true); + } // Take care of old and new preeditors. if (preeditor != mPreeditor || !b) -- cgit v1.3 From 7decac40e6453b2d8822d2677b9b59300bc260cf Mon Sep 17 00:00:00 2001 From: Geenz Date: Thu, 23 May 2013 09:39:49 -0400 Subject: Override NSPanel's close method to hide the window instead of actually removing the window. --- indra/llwindow/llopenglview-objc.h | 4 ++++ indra/llwindow/llopenglview-objc.mm | 25 ++++++++++++++++++++++++- indra/newview/SecondLife.nib | Bin 13009 -> 13021 bytes indra/newview/SecondLife.xib | 14 +++++++------- 4 files changed, 35 insertions(+), 8 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llopenglview-objc.h b/indra/llwindow/llopenglview-objc.h index e20ea533fb..5309dea664 100644 --- a/indra/llwindow/llopenglview-objc.h +++ b/indra/llwindow/llopenglview-objc.h @@ -47,6 +47,10 @@ @end +@interface LLUserInputWindow : NSPanel + +@end + @interface LLNonInlineTextView : NSTextView { LLOpenGLView *glview; diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index 8ef6d4e682..17e8c3e3cc 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -527,6 +527,15 @@ attributedStringInfo getSegments(NSAttributedString *str) @end +@implementation LLUserInputWindow + +- (void) close +{ + [self orderOut:self]; +} + +@end + @implementation LLNonInlineTextView - (void) setGLView:(LLOpenGLView *)view @@ -536,16 +545,30 @@ attributedStringInfo getSegments(NSAttributedString *str) - (void) insertText:(id)insertString { + [[self inputContext] discardMarkedText]; + [self setString:@""]; + [_window orderOut:_window]; [self insertText:insertString replacementRange:NSMakeRange(0, 0)]; } - (void) insertText:(id)aString replacementRange:(NSRange)replacementRange { [glview insertText:aString replacementRange:replacementRange]; +} + +- (void) insertNewline:(id)sender +{ [[self textStorage] setValue:@""]; [[self inputContext] discardMarkedText]; [self setString:@""]; - [_window orderOut:_window]; +} + +- (void)doCommandBySelector:(SEL)aSelector +{ + if (aSelector == @selector(insertNewline:)) + { + [self insertNewline:self]; + } } @end diff --git a/indra/newview/SecondLife.nib b/indra/newview/SecondLife.nib index cb289ebf09..a5f2717167 100644 Binary files a/indra/newview/SecondLife.nib and b/indra/newview/SecondLife.nib differ diff --git a/indra/newview/SecondLife.xib b/indra/newview/SecondLife.xib index c6b72485a1..e5736f76a4 100644 --- a/indra/newview/SecondLife.xib +++ b/indra/newview/SecondLife.xib @@ -2,7 +2,7 @@ 1060 - 12E30 + 12E52 3084 1187.39 626.00 @@ -335,7 +335,7 @@ {1024, 600} _NS:20 - {{0, 0}, {2560, 1418}} + {{0, 0}, {2560, 1440}} {10000000000000, 10000000000000} Second Life 128 @@ -347,7 +347,7 @@ {{272, 176}, {938, 42}} -1535638528 Input Window - NSPanel + LLUserInputWindow @@ -533,7 +533,7 @@ _NS:21 - {{0, 0}, {2560, 1418}} + {{0, 0}, {2560, 1440}} {10000000000000, 10000000000000} YES @@ -1180,11 +1180,11 @@ - NSLayoutConstraint - NSObject + LLUserInputWindow + NSPanel IBProjectSource - ./Classes/NSLayoutConstraint.h + ./Classes/LLUserInputWindow.h -- cgit v1.3 From f8abfb63c32a0926a393a4359c6f387482d2448e Mon Sep 17 00:00:00 2001 From: Geenz Date: Mon, 17 Jun 2013 07:52:19 -0400 Subject: This brings us to feature parity with CHUI for IME support. --- indra/llwindow/llopenglview-objc.mm | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index 17e8c3e3cc..b431321da6 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -313,12 +313,13 @@ attributedStringInfo getSegments(NSAttributedString *str) - (void) keyDown:(NSEvent *)theEvent { - [[self inputContext] handleEvent:theEvent]; if (!mHasMarkedText) { uint keycode = [theEvent keyCode]; - callKeyDown(keycode, mModifiers); - + if (callKeyDown(keycode, mModifiers)) + { + [[self inputContext] handleEvent:theEvent]; + } // 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. @@ -461,12 +462,11 @@ attributedStringInfo getSegments(NSAttributedString *str) - (void)insertText:(id)aString replacementRange:(NSRange)replacementRange { - bool success = false; if (!mHasMarkedText) { for (NSInteger i = 0; i < [aString length]; i++) { - success = callUnicodeCallback([aString characterAtIndex:i], mModifiers); + 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. @@ -475,12 +475,10 @@ attributedStringInfo getSegments(NSAttributedString *str) for (NSInteger i = 0; i < [aString length]; i++) { - success = handleUnicodeCharacter([aString characterAtIndex:i]); + handleUnicodeCharacter([aString characterAtIndex:i]); } mHasMarkedText = FALSE; } - - NSLog(@"Successful text input: %d", success); } - (void) insertNewline:(id)sender -- cgit v1.3 From 93531f3ba85748ba5c9f1d797c4925f55fe8b92c Mon Sep 17 00:00:00 2001 From: Geenz Date: Mon, 17 Jun 2013 08:59:01 -0400 Subject: Insert text into the input window when we attempt to insert text without a pre-editor. Also handle backspace as a special case when determining if the input window needs to be displayed. --- indra/llwindow/llappdelegate-objc.h | 2 +- indra/llwindow/llopenglview-objc.mm | 13 +++++++++---- indra/llwindow/llwindowmacosx-objc.h | 2 +- indra/llwindow/llwindowmacosx-objc.mm | 4 ++-- indra/newview/llappdelegate-objc.mm | 3 ++- 5 files changed, 15 insertions(+), 9 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llappdelegate-objc.h b/indra/llwindow/llappdelegate-objc.h index be9ad4d79f..b1d78d5e3c 100644 --- a/indra/llwindow/llappdelegate-objc.h +++ b/indra/llwindow/llappdelegate-objc.h @@ -24,6 +24,6 @@ @property (retain) NSString *currentInputLanguage; - (void) mainLoop; -- (void) showInputWindow:(bool)show; +- (void) showInputWindow:(bool)show withText:(id)text; - (void) languageUpdated; @end diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index b431321da6..062577baf8 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -404,10 +404,11 @@ attributedStringInfo getSegments(NSAttributedString *str) - (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange { - if (mMarkedTextAllowed) + if ([aString class] == NSClassFromString(@"NSConcreteMutableAttributedString")) { - if ([aString class] == NSClassFromString(@"NSConcreteMutableAttributedString")) + if (mMarkedTextAllowed) { + unsigned int selected[2] = { selectedRange.location, selectedRange.length @@ -425,9 +426,13 @@ attributedStringInfo getSegments(NSAttributedString *str) mHasMarkedText = TRUE; mMarkedTextLength = [aString length]; mMarkedText = (NSAttributedString*)[aString mutableString]; + } else if ([[aString mutableString] characterAtIndex:0] != NSBackspaceCharacter) { + showInputWindow(true, aString); + if (mHasMarkedText) + { + [self unmarkText]; + } } - } else { - showInputWindow(true); } } diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index 62543fa01d..daf7596cab 100755 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -91,7 +91,7 @@ void closeWindow(NSWindowRef window); void removeGLView(GLViewRef view); void makeFirstResponder(NSWindowRef window, GLViewRef view); void setupInputWindow(NSWindowRef window, GLViewRef view); -void showInputWindow(bool show); +void showInputWindow(bool show, void* text); // These are all implemented in llwindowmacosx.cpp. // This is largely for easier interop between Obj-C and C++ (at least in the viewer's case due to the BOOL vs. BOOL conflict) diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index 95b9cdb863..7f1af129b4 100755 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -367,9 +367,9 @@ void setupInputWindow(NSWindowRef window, GLViewRef glview) [[(LLAppDelegate*)[NSApp delegate] inputView] setGLView:(LLOpenGLView*)glview]; } -void showInputWindow(bool show) +void showInputWindow(bool show, void* text) { - [(LLAppDelegate*)[NSApp delegate] showInputWindow:show]; + [(LLAppDelegate*)[NSApp delegate] showInputWindow:show withText:(id)text]; } void commitCurrentPreedit(GLViewRef glView) diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index de77447006..b4f9c56b00 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -71,7 +71,7 @@ } } -- (void) showInputWindow:(bool)show +- (void) showInputWindow:(bool)show withText:(id)text { // How to add support for new languages with the input window: // Simply append this array with the language code (ja for japanese, ko for korean, zh for chinese, etc.) @@ -83,6 +83,7 @@ { NSLog(@"Showing input window."); [inputWindow makeKeyAndOrderFront:inputWindow]; + [inputView setMarkedText:text selectedRange:NSMakeRange(0, 1)]; } else { NSLog(@"Hiding input window."); [inputWindow orderOut:inputWindow]; -- cgit v1.3 From 440a1ee3bae4ea9553fa57d806f942a472923190 Mon Sep 17 00:00:00 2001 From: Geenz Date: Mon, 17 Jun 2013 09:26:11 -0400 Subject: Move logic involving the input window to keyDown. Pass input events to the input window from there. --- indra/llwindow/llopenglview-objc.h | 5 +++++ indra/llwindow/llopenglview-objc.mm | 9 +++++++-- indra/newview/llappdelegate-objc.mm | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llopenglview-objc.h b/indra/llwindow/llopenglview-objc.h index 5309dea664..d4207d598a 100644 --- a/indra/llwindow/llopenglview-objc.h +++ b/indra/llwindow/llopenglview-objc.h @@ -6,6 +6,9 @@ // // +#ifndef LLOpenGLView_H +#define LLOpenGLView_H + #import #import #import @@ -85,3 +88,5 @@ - (NSPoint)flipPoint:(NSPoint)aPoint; @end + +#endif \ No newline at end of file diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index 062577baf8..99c27e79a0 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -8,6 +8,7 @@ #import "llopenglview-objc.h" #include "llwindowmacosx-objc.h" +#import "llappdelegate-objc.h" @implementation NSScreen (PointConversion) @@ -318,6 +319,11 @@ attributedStringInfo getSegments(NSAttributedString *str) uint keycode = [theEvent keyCode]; if (callKeyDown(keycode, mModifiers)) { + if (!mMarkedTextAllowed && [[theEvent characters] characterAtIndex:0] != NSBackspaceCharacter) + { + showInputWindow(true, @""); + [[[(LLAppDelegate*)[NSApp delegate] inputView] inputContext] handleEvent:theEvent]; + } [[self inputContext] handleEvent:theEvent]; } // OS X intentionally does not send us key-up information on cmd-key combinations. @@ -426,8 +432,7 @@ attributedStringInfo getSegments(NSAttributedString *str) mHasMarkedText = TRUE; mMarkedTextLength = [aString length]; mMarkedText = (NSAttributedString*)[aString mutableString]; - } else if ([[aString mutableString] characterAtIndex:0] != NSBackspaceCharacter) { - showInputWindow(true, aString); + } else { if (mHasMarkedText) { [self unmarkText]; diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index b4f9c56b00..403c307085 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -8,7 +8,7 @@ #import "llappdelegate-objc.h" #include "llwindowmacosx-objc.h" -#include // Used for Text Input Services ("Safe" API - it's well supported) +#include // Used for Text Input Services ("Safe" API - it's supported) @implementation LLAppDelegate -- cgit v1.3 From 2253d22eb85a6b4c5e48b9905d807d0ac48b1930 Mon Sep 17 00:00:00 2001 From: Geenz Date: Mon, 17 Jun 2013 10:28:32 -0400 Subject: Have showInputWindow hand off input events to the bottom line input window. --- indra/llwindow/llappdelegate-objc.h | 2 +- indra/llwindow/llopenglview-objc.mm | 9 +++++++-- indra/llwindow/llwindowmacosx-objc.h | 1 - indra/llwindow/llwindowmacosx-objc.mm | 5 ----- indra/newview/llappdelegate-objc.mm | 7 +++++-- 5 files changed, 13 insertions(+), 11 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llappdelegate-objc.h b/indra/llwindow/llappdelegate-objc.h index b1d78d5e3c..266f417c4b 100644 --- a/indra/llwindow/llappdelegate-objc.h +++ b/indra/llwindow/llappdelegate-objc.h @@ -24,6 +24,6 @@ @property (retain) NSString *currentInputLanguage; - (void) mainLoop; -- (void) showInputWindow:(bool)show withText:(id)text; +- (void) showInputWindow:(bool)show withEvent:(NSEvent*)textEvent; - (void) languageUpdated; @end diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index 99c27e79a0..2afd4993c5 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -321,11 +321,16 @@ attributedStringInfo getSegments(NSAttributedString *str) { if (!mMarkedTextAllowed && [[theEvent characters] characterAtIndex:0] != NSBackspaceCharacter) { - showInputWindow(true, @""); - [[[(LLAppDelegate*)[NSApp delegate] inputView] inputContext] handleEvent:theEvent]; + [(LLAppDelegate*)[NSApp delegate] showInputWindow:true withEvent:theEvent]; } + + [[self inputContext] handleEvent:theEvent]; + } else if ([[theEvent charactersIgnoringModifiers] characterAtIndex:0] == 13 || [[theEvent charactersIgnoringModifiers] characterAtIndex:0] == 3) + { + // callKeyDown won't return the value we expect for enter or return. Handle them as a separate case. [[self inputContext] handleEvent:theEvent]; } + // 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. diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index daf7596cab..5b1f22046b 100755 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -91,7 +91,6 @@ void closeWindow(NSWindowRef window); void removeGLView(GLViewRef view); void makeFirstResponder(NSWindowRef window, GLViewRef view); void setupInputWindow(NSWindowRef window, GLViewRef view); -void showInputWindow(bool show, void* text); // These are all implemented in llwindowmacosx.cpp. // This is largely for easier interop between Obj-C and C++ (at least in the viewer's case due to the BOOL vs. BOOL conflict) diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index 7f1af129b4..33a8cf34ce 100755 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -367,11 +367,6 @@ void setupInputWindow(NSWindowRef window, GLViewRef glview) [[(LLAppDelegate*)[NSApp delegate] inputView] setGLView:(LLOpenGLView*)glview]; } -void showInputWindow(bool show, void* text) -{ - [(LLAppDelegate*)[NSApp delegate] showInputWindow:show withText:(id)text]; -} - void commitCurrentPreedit(GLViewRef glView) { [(LLOpenGLView*)glView commitCurrentPreedit]; diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index 403c307085..cec9c586e6 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -71,7 +71,7 @@ } } -- (void) showInputWindow:(bool)show withText:(id)text +- (void) showInputWindow:(bool)show withEvent:(NSEvent*)textEvent { // How to add support for new languages with the input window: // Simply append this array with the language code (ja for japanese, ko for korean, zh for chinese, etc.) @@ -83,7 +83,10 @@ { NSLog(@"Showing input window."); [inputWindow makeKeyAndOrderFront:inputWindow]; - [inputView setMarkedText:text selectedRange:NSMakeRange(0, 1)]; + if (textEvent != nil) + { + [[inputView inputContext] handleEvent:textEvent]; + } } else { NSLog(@"Hiding input window."); [inputWindow orderOut:inputWindow]; -- cgit v1.3 From 84f287b34e7d7edbd2e897b73008c782aabe60de Mon Sep 17 00:00:00 2001 From: Geenz Date: Mon, 17 Jun 2013 12:31:25 -0400 Subject: Moved detecting if we're using a roman-script language to it's own function in the application delegate. Also consider the delete and backspace characters to be special cases. --- indra/llwindow/llappdelegate-objc.h | 1 + indra/llwindow/llopenglview-objc.mm | 22 ++++++++++++++-------- indra/newview/llappdelegate-objc.mm | 22 ++++++++++++++++------ 3 files changed, 31 insertions(+), 14 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llappdelegate-objc.h b/indra/llwindow/llappdelegate-objc.h index 266f417c4b..a6fb77d93f 100644 --- a/indra/llwindow/llappdelegate-objc.h +++ b/indra/llwindow/llappdelegate-objc.h @@ -26,4 +26,5 @@ - (void) mainLoop; - (void) showInputWindow:(bool)show withEvent:(NSEvent*)textEvent; - (void) languageUpdated; +- (bool) romanScript; @end diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index 2afd4993c5..c3f0ef4aeb 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -317,15 +317,21 @@ attributedStringInfo getSegments(NSAttributedString *str) if (!mHasMarkedText) { uint keycode = [theEvent keyCode]; - if (callKeyDown(keycode, mModifiers)) + bool acceptsText = callKeyDown(keycode, mModifiers); + if (acceptsText && + !mMarkedTextAllowed && + ![(LLAppDelegate*)[NSApp delegate] romanScript] && + [[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSDeleteCharacter && + [[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSBackspaceCharacter) + { + [(LLAppDelegate*)[NSApp delegate] showInputWindow:true withEvent:theEvent]; + } else { - if (!mMarkedTextAllowed && [[theEvent characters] characterAtIndex:0] != NSBackspaceCharacter) - { - [(LLAppDelegate*)[NSApp delegate] showInputWindow:true withEvent:theEvent]; - } - [[self inputContext] handleEvent:theEvent]; - } else if ([[theEvent charactersIgnoringModifiers] characterAtIndex:0] == 13 || [[theEvent charactersIgnoringModifiers] characterAtIndex:0] == 3) + } + + if ([[theEvent charactersIgnoringModifiers] characterAtIndex:0] == NSCarriageReturnCharacter || + [[theEvent charactersIgnoringModifiers] characterAtIndex:0] == NSEnterCharacter) { // callKeyDown won't return the value we expect for enter or return. Handle them as a separate case. [[self inputContext] handleEvent:theEvent]; @@ -438,7 +444,7 @@ attributedStringInfo getSegments(NSAttributedString *str) mMarkedTextLength = [aString length]; mMarkedText = (NSAttributedString*)[aString mutableString]; } else { - if (mHasMarkedText) + if (mHasMarkedText || ![mMarkedText isEqual: @""]) { [self unmarkText]; } diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index cec9c586e6..6b7e613491 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -73,11 +73,7 @@ - (void) showInputWindow:(bool)show withEvent:(NSEvent*)textEvent { - // How to add support for new languages with the input window: - // Simply append this array with the language code (ja for japanese, ko for korean, zh for chinese, etc.) - NSArray *authorizedLanguages = [[NSArray alloc] initWithObjects:@"ja", @"ko", @"zh-Hant", @"zh-Hans", nil]; - - if ([authorizedLanguages containsObject:currentInputLanguage]) + if (![self romanScript]) { if (show) { @@ -85,6 +81,7 @@ [inputWindow makeKeyAndOrderFront:inputWindow]; if (textEvent != nil) { + [[inputView inputContext] discardMarkedText]; [[inputView inputContext] handleEvent:textEvent]; } } else { @@ -105,7 +102,7 @@ TISInputSourceRef currentInput = TISCopyCurrentKeyboardInputSource(); CFArrayRef languages = (CFArrayRef)TISGetInputSourceProperty(currentInput, kTISPropertyInputSourceLanguages); -#if 1 // In the event of ever needing to add new language sources, change this to 1 and watch the terminal for "languages:" +#if 0 // In the event of ever needing to add new language sources, change this to 1 and watch the terminal for "languages:" NSLog(@"languages: %@", TISGetInputSourceProperty(currentInput, kTISPropertyInputSourceLanguages)); #endif @@ -113,4 +110,17 @@ currentInputLanguage = (NSString*)CFArrayGetValueAtIndex(languages, 0); } +- (bool) romanScript +{ + // How to add support for new languages with the input window: + // Simply append this array with the language code (ja for japanese, ko for korean, zh for chinese, etc.) + NSArray *nonRomanScript = [[NSArray alloc] initWithObjects:@"ja", @"ko", @"zh-Hant", @"zh-Hans", nil]; + if ([nonRomanScript containsObject:currentInputLanguage]) + { + return false; + } + + return true; +} + @end -- cgit v1.3 From 2837ca7a474f92bb363a2a31d184431b636d2809 Mon Sep 17 00:00:00 2001 From: Geenz Date: Mon, 17 Jun 2013 17:08:48 -0400 Subject: This seems to be on par with viewer-release at this point. --- indra/llwindow/llopenglview-objc.h | 1 - indra/llwindow/llopenglview-objc.mm | 84 ++++++++++++++++++----------------- indra/llwindow/llwindowmacosx-objc.h | 2 +- indra/llwindow/llwindowmacosx-objc.mm | 4 +- indra/llwindow/llwindowmacosx.cpp | 42 ++++++++++++------ indra/llwindow/llwindowmacosx.h | 2 + 6 files changed, 78 insertions(+), 57 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llopenglview-objc.h b/indra/llwindow/llopenglview-objc.h index d4207d598a..b783c41c0b 100644 --- a/indra/llwindow/llopenglview-objc.h +++ b/indra/llwindow/llopenglview-objc.h @@ -22,7 +22,6 @@ float mMousePos[2]; bool mHasMarkedText; unsigned int mMarkedTextLength; - NSAttributedString *mMarkedText; bool mMarkedTextAllowed; } - (id) initWithSamples:(NSUInteger)samples; diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index c3f0ef4aeb..24de5912f0 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -314,37 +314,34 @@ attributedStringInfo getSegments(NSAttributedString *str) - (void) keyDown:(NSEvent *)theEvent { - if (!mHasMarkedText) - { - uint keycode = [theEvent keyCode]; - bool acceptsText = callKeyDown(keycode, mModifiers); - if (acceptsText && - !mMarkedTextAllowed && - ![(LLAppDelegate*)[NSApp delegate] romanScript] && - [[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSDeleteCharacter && - [[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSBackspaceCharacter) - { - [(LLAppDelegate*)[NSApp delegate] showInputWindow:true withEvent:theEvent]; - } else - { - [[self inputContext] handleEvent:theEvent]; - } - - if ([[theEvent charactersIgnoringModifiers] characterAtIndex:0] == NSCarriageReturnCharacter || - [[theEvent charactersIgnoringModifiers] characterAtIndex:0] == NSEnterCharacter) - { - // callKeyDown won't return the value we expect for enter or return. Handle them as a separate case. - [[self inputContext] handleEvent:theEvent]; - } - - // 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); - } - } + uint keycode = [theEvent keyCode]; + bool acceptsText = callKeyDown(keycode, mModifiers); + if (acceptsText && + !mMarkedTextAllowed && + ![(LLAppDelegate*)[NSApp delegate] romanScript] && + [[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSDeleteCharacter && + [[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSBackspaceCharacter) + { + [(LLAppDelegate*)[NSApp delegate] showInputWindow:true withEvent:theEvent]; + } else + { + [[self inputContext] handleEvent:theEvent]; + } + + if ([[theEvent charactersIgnoringModifiers] characterAtIndex:0] == NSCarriageReturnCharacter || + [[theEvent charactersIgnoringModifiers] characterAtIndex:0] == NSEnterCharacter) + { + // callKeyDown won't return the value we expect for enter or return. Handle them as a separate case. + [[self inputContext] handleEvent:theEvent]; + } + + // 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); + } } - (void)flagsChanged:(NSEvent *)theEvent { @@ -425,7 +422,6 @@ attributedStringInfo getSegments(NSAttributedString *str) { if (mMarkedTextAllowed) { - unsigned int selected[2] = { selectedRange.location, selectedRange.length @@ -442,9 +438,8 @@ attributedStringInfo getSegments(NSAttributedString *str) setMarkedText(text, selected, replacement, [aString length], segments); mHasMarkedText = TRUE; mMarkedTextLength = [aString length]; - mMarkedText = (NSAttributedString*)[aString mutableString]; } else { - if (mHasMarkedText || ![mMarkedText isEqual: @""]) + if (mHasMarkedText) { [self unmarkText]; } @@ -454,17 +449,18 @@ attributedStringInfo getSegments(NSAttributedString *str) - (void)commitCurrentPreedit { - if (mMarkedText) + if (mHasMarkedText) { - [self insertText:mMarkedText]; - [[self inputContext] discardMarkedText]; + if ([[self inputContext] respondsToSelector:@selector(commitEditing)]) + { + [[self inputContext] commitEditing]; + } } } - (void)unmarkText { [[self inputContext] discardMarkedText]; - [mMarkedText setValue:@""]; resetPreedit(); mHasMarkedText = FALSE; } @@ -481,6 +477,14 @@ attributedStringInfo getSegments(NSAttributedString *str) return nil; } +- (void)insertText:(id)insertString +{ + if (insertString != nil) + { + [self insertText:insertString replacementRange:NSMakeRange(0, [insertString length])]; + } +} + - (void)insertText:(id)aString replacementRange:(NSRange)replacementRange { if (!mHasMarkedText) @@ -490,9 +494,9 @@ attributedStringInfo getSegments(NSAttributedString *str) callUnicodeCallback([aString characterAtIndex:i], mModifiers); } } else { + resetPreedit(); // 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++) { @@ -567,7 +571,7 @@ attributedStringInfo getSegments(NSAttributedString *str) [[self inputContext] discardMarkedText]; [self setString:@""]; [_window orderOut:_window]; - [self insertText:insertString replacementRange:NSMakeRange(0, 0)]; + [self insertText:insertString replacementRange:NSMakeRange(0, [insertString length])]; } - (void) insertText:(id)aString replacementRange:(NSRange)replacementRange diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index 5b1f22046b..914fc534fb 100755 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -135,7 +135,7 @@ void resetPreedit(); int wstring_length(const std::basic_string & wstr, const int woffset, const int utf16_length, int *unaligned); void setMarkedText(unsigned short *text, unsigned int *selectedRange, unsigned int *replacementRange, long text_len, attributedStringInfo segments); void getPreeditLocation(float *location, unsigned int length); -void allowDirectMarkedTextInput(bool allow); +void allowDirectMarkedTextInput(bool allow, GLViewRef glView); NSWindowRef getMainAppWindow(); GLViewRef getGLView(); diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index 33a8cf34ce..67b5279c0b 100755 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -372,9 +372,9 @@ void commitCurrentPreedit(GLViewRef glView) [(LLOpenGLView*)glView commitCurrentPreedit]; } -void allowDirectMarkedTextInput(bool allow) +void allowDirectMarkedTextInput(bool allow, GLViewRef glView) { - + [(LLOpenGLView*)glView allowMarkedTextInput:allow]; } NSWindowRef getMainAppWindow() diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 16fd7e3382..737ecba368 100755 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -239,6 +239,11 @@ void callFocusLost() void callRightMouseDown(float *pos, MASK mask) { + if (gWindowImplementation->allowsLanguageInput()) + { + gWindowImplementation->interruptLanguageTextInput(); + } + LLCoordGL outCoords; outCoords.mX = llround(pos[0]); outCoords.mY = llround(pos[1]); @@ -247,6 +252,11 @@ void callRightMouseDown(float *pos, MASK mask) void callRightMouseUp(float *pos, MASK mask) { + if (gWindowImplementation->allowsLanguageInput()) + { + gWindowImplementation->interruptLanguageTextInput(); + } + LLCoordGL outCoords; outCoords.mX = llround(pos[0]); outCoords.mY = llround(pos[1]); @@ -255,6 +265,11 @@ void callRightMouseUp(float *pos, MASK mask) void callLeftMouseDown(float *pos, MASK mask) { + if (gWindowImplementation->allowsLanguageInput()) + { + gWindowImplementation->interruptLanguageTextInput(); + } + LLCoordGL outCoords; outCoords.mX = llround(pos[0]); outCoords.mY = llround(pos[1]); @@ -263,6 +278,11 @@ void callLeftMouseDown(float *pos, MASK mask) void callLeftMouseUp(float *pos, MASK mask) { + if (gWindowImplementation->allowsLanguageInput()) + { + gWindowImplementation->interruptLanguageTextInput(); + } + LLCoordGL outCoords; outCoords.mX = llround(pos[0]); outCoords.mY = llround(pos[1]); @@ -272,6 +292,11 @@ void callLeftMouseUp(float *pos, MASK mask) void callDoubleClick(float *pos, MASK mask) { + if (gWindowImplementation->allowsLanguageInput()) + { + gWindowImplementation->interruptLanguageTextInput(); + } + LLCoordGL outCoords; outCoords.mX = llround(pos[0]); outCoords.mY = llround(pos[1]); @@ -434,7 +459,7 @@ void setMarkedText(unsigned short *unitext, unsigned int *selectedRange, unsigne if (gWindowImplementation->getPreeditor()) { LLPreeditor *preeditor = gWindowImplementation->getPreeditor(); - + preeditor->resetPreedit(); // This should be a viable replacement for the kEventParamTextInputSendReplaceRange parameter. if (replacementRange[0] < replacementRange[1]) { @@ -444,8 +469,6 @@ void setMarkedText(unsigned short *unitext, unsigned int *selectedRange, unsigne preeditor->markAsPreedit(location, length); } - preeditor->resetPreedit(); - LLWString fix_str = utf16str_to_wstring(llutf16string(unitext, text_len)); S32 caret_position = fix_str.length(); @@ -1818,6 +1841,8 @@ 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 @@ -1828,16 +1853,7 @@ void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) // is not disturbed. return; } - - if (preeditor == NULL) { - // If we don't have a pre editor, then we can't accept direct marked text input. - // We needs an input window (which is handled internally by LLOpenGLView) - allowDirectMarkedTextInput(false); - } else { - // If we have a preeditor, then accept direct marked text input. - allowDirectMarkedTextInput(true); - } - + // Take care of old and new preeditors. if (preeditor != mPreeditor || !b) { diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h index de0340cf74..82195c2700 100755 --- a/indra/llwindow/llwindowmacosx.h +++ b/indra/llwindow/llwindowmacosx.h @@ -126,6 +126,8 @@ public: void getMouseDeltas(float* delta); void handleDragNDrop(std::string url, LLWindowCallbacks::DragNDropAction action); + + bool allowsLanguageInput() { return mLanguageTextInputAllowed; } protected: LLWindowMacOSX(LLWindowCallbacks* callbacks, -- cgit v1.3 From 90e511bbdf9e08059180218e47350e4d2b431b68 Mon Sep 17 00:00:00 2001 From: Geenz Date: Thu, 20 Jun 2013 11:28:05 -0400 Subject: Handle VRAM in megabytes. This was previously being reported as bytes. --- indra/llwindow/llopenglview-objc.mm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index 24de5912f0..aa7df2c985 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -88,7 +88,8 @@ attributedStringInfo getSegments(NSAttributedString *str) { vram_bytes = (256 << 20); } - return (unsigned long)vram_bytes; + + return (unsigned long)vram_bytes / 1048576; // We need this in megabytes. } - (void)viewDidMoveToWindow -- cgit v1.3 From 860b86e3d1c61c18be99301ea1c5027058a8353d Mon Sep 17 00:00:00 2001 From: Geenz Date: Thu, 27 Jun 2013 13:48:44 -0400 Subject: Fix for down key presses not opening up the IME character selection window, and inadvertently being handled while marked text is selected. --- indra/llwindow/llopenglview-objc.mm | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index aa7df2c985..7803d78862 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -316,12 +316,16 @@ attributedStringInfo getSegments(NSAttributedString *str) - (void) keyDown:(NSEvent *)theEvent { uint keycode = [theEvent keyCode]; - bool acceptsText = callKeyDown(keycode, mModifiers); + bool acceptsText = mHasMarkedText ? false : callKeyDown(keycode, mModifiers); if (acceptsText && !mMarkedTextAllowed && ![(LLAppDelegate*)[NSApp delegate] romanScript] && [[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSDeleteCharacter && - [[theEvent charactersIgnoringModifiers] characterAtIndex:0] != NSBackspaceCharacter) + [[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) { [(LLAppDelegate*)[NSApp delegate] showInputWindow:true withEvent:theEvent]; } else @@ -339,7 +343,7 @@ attributedStringInfo getSegments(NSAttributedString *str) // 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 (mModifiers & NSCommandKeyMask && !mHasMarkedText) { callKeyUp([theEvent keyCode], mModifiers); } -- cgit v1.3 From 623077e6a4eef516d445975eaa71d5f67e6767c5 Mon Sep 17 00:00:00 2001 From: Geenz Date: Thu, 27 Jun 2013 15:06:03 -0400 Subject: Added license headers. --- indra/llwindow/llappdelegate-objc.h | 32 ++++++++++++++++++----- indra/llwindow/llopenglview-objc.h | 32 ++++++++++++++++++----- indra/llwindow/llopenglview-objc.mm | 32 ++++++++++++++++++----- indra/llwindow/llwindowmacosx-objc.mm | 48 +++++++++++++++++------------------ indra/newview/llappdelegate-objc.mm | 32 ++++++++++++++++++----- 5 files changed, 124 insertions(+), 52 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llappdelegate-objc.h b/indra/llwindow/llappdelegate-objc.h index a6fb77d93f..faa5d3abb7 100644 --- a/indra/llwindow/llappdelegate-objc.h +++ b/indra/llwindow/llappdelegate-objc.h @@ -1,10 +1,28 @@ -// -// LLAppDelegate.h -// SecondLife -// -// Created by Geenz on 12/16/12. -// -// +/** + * @file llappdelegate-objc.h + * @brief Class interface for the Mac version's application delegate. + * + * $LicenseInfo:firstyear=2000&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library 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 GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ #import #import "llopenglview-objc.h" diff --git a/indra/llwindow/llopenglview-objc.h b/indra/llwindow/llopenglview-objc.h index b783c41c0b..f895aae577 100644 --- a/indra/llwindow/llopenglview-objc.h +++ b/indra/llwindow/llopenglview-objc.h @@ -1,10 +1,28 @@ -// -// LLOpenGLView.h -// SecondLife -// -// Created by Geenz on 10/2/12. -// -// +/** + * @file llopenglview-objc.h + * @brief Class interfaces for most of the Mac facing window functionality. + * + * $LicenseInfo:firstyear=2000&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library 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 GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ #ifndef LLOpenGLView_H #define LLOpenGLView_H diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index 7803d78862..8a6984091d 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -1,10 +1,28 @@ -// -// LLOpenGLView.m -// SecondLife -// -// Created by Geenz on 10/2/12. -// -// +/** + * @file llopenglview-objc.mm + * @brief Class implementation for most of the Mac facing window functionality. + * + * $LicenseInfo:firstyear=2000&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library 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 GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ #import "llopenglview-objc.h" #include "llwindowmacosx-objc.h" diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index 67b5279c0b..41d8e3ecd9 100755 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -1,4 +1,4 @@ -/** +/** * @file llwindowmacosx-objc.mm * @brief Definition of functions shared between llwindowmacosx.cpp * and llwindowmacosx-objc.mm. @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2006&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library 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 GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -52,10 +52,10 @@ void setupCocoa() NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // The following prevents the Cocoa command line parser from trying to open 'unknown' arguements as documents. - // ie. running './secondlife -set Language fr' would cause a pop-up saying can't open document 'fr' - // when init'ing the Cocoa App window. + // ie. running './secondlife -set Language fr' would cause a pop-up saying can't open document 'fr' + // when init'ing the Cocoa App window. [[NSUserDefaults standardUserDefaults] setObject:@"NO" forKey:@"NSTreatUnknownArgumentsAsOpen"]; - + [pool release]; inited = true; @@ -100,17 +100,17 @@ const unsigned short *copyFromPBoard() CursorRef createImageCursor(const char *fullpath, int hotspotX, int hotspotY) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - + // extra retain on the NSCursor since we want it to live for the lifetime of the app. NSCursor *cursor = - [[[NSCursor alloc] - initWithImage: - [[[NSImage alloc] initWithContentsOfFile: - [NSString stringWithFormat:@"%s", fullpath] - ]autorelease] - hotSpot:NSMakePoint(hotspotX, hotspotY) - ]retain]; - + [[[NSCursor alloc] + initWithImage: + [[[NSImage alloc] initWithContentsOfFile: + [NSString stringWithFormat:@"%s", fullpath] + ]autorelease] + hotSpot:NSMakePoint(hotspotX, hotspotY) + ]retain]; + [pool release]; return (CursorRef)cursor; @@ -209,7 +209,7 @@ OSErr setImageCursor(CursorRef ref) NSWindowRef createNSWindow(int x, int y, int width, int height) { LLNSWindow *window = [[LLNSWindow alloc]initWithContentRect:NSMakeRect(x, y, width, height) - styleMask:NSTitledWindowMask | NSResizableWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSTexturedBackgroundWindowMask backing:NSBackingStoreBuffered defer:NO]; + styleMask:NSTitledWindowMask | NSResizableWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSTexturedBackgroundWindowMask backing:NSBackingStoreBuffered defer:NO]; [window makeKeyAndOrderFront:nil]; [window setAcceptsMouseMovedEvents:TRUE]; return window; @@ -391,13 +391,13 @@ void makeFirstResponder(NSWindowRef window, GLViewRef view) } /* -GLViewRef getGLView() -{ - return [(LLAppDelegate*)[[NSApplication sharedApplication] delegate] glview]; -} -*/ + GLViewRef getGLView() + { + return [(LLAppDelegate*)[[NSApplication sharedApplication] delegate] glview]; + } + */ unsigned int getModifiers() -{ +{ return [NSEvent modifierFlags]; } diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index 6b7e613491..30476b3d22 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -1,10 +1,28 @@ -// -// LLAppDelegate.m -// SecondLife -// -// Created by Geenz on 12/16/12. -// -// +/** + * @file llappdelegate-objc.mm + * @brief Class implementation for the Mac version's application delegate. + * + * $LicenseInfo:firstyear=2000&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library 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 GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ #import "llappdelegate-objc.h" #include "llwindowmacosx-objc.h" -- cgit v1.3 From 6fbafaf056d61ab0ab49cc16a998a528f0ea22e8 Mon Sep 17 00:00:00 2001 From: Geenz Date: Thu, 11 Jul 2013 18:41:16 -0400 Subject: Restore control + right click functionality. --- indra/llwindow/llopenglview-objc.mm | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index 8a6984091d..77c2fc7e19 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -242,12 +242,18 @@ attributedStringInfo getSegments(NSAttributedString *str) - (void) mouseDown:(NSEvent *)theEvent { - if ([theEvent clickCount] >= 2) - { - callDoubleClick(mMousePos, mModifiers); - } else if ([theEvent clickCount] == 1) { - callLeftMouseDown(mMousePos, mModifiers); - } + // Apparently people still use this? + if ([theEvent modifierFlags] & NSControlKeyMask) + { + callRightMouseDown(mMousePos, mModifiers); + } else { + if ([theEvent clickCount] >= 2) + { + callDoubleClick(mMousePos, mModifiers); + } else if ([theEvent clickCount] == 1) { + callLeftMouseDown(mMousePos, mModifiers); + } + } } - (void) mouseUp:(NSEvent *)theEvent -- cgit v1.3 From 72bb473c9ed106cce6baf22ac74a13443d4630e8 Mon Sep 17 00:00:00 2001 From: Geenz Date: Thu, 11 Jul 2013 18:59:28 -0400 Subject: Ensure that the correct method is called when we're simulating a right click. --- indra/llwindow/llopenglview-objc.h | 1 + indra/llwindow/llopenglview-objc.mm | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llopenglview-objc.h b/indra/llwindow/llopenglview-objc.h index f895aae577..71149f8561 100644 --- a/indra/llwindow/llopenglview-objc.h +++ b/indra/llwindow/llopenglview-objc.h @@ -41,6 +41,7 @@ bool mHasMarkedText; unsigned int mMarkedTextLength; bool mMarkedTextAllowed; + bool mSimulatedRightClick; } - (id) initWithSamples:(NSUInteger)samples; - (id) initWithSamples:(NSUInteger)samples andVsync:(BOOL)vsync; diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index 77c2fc7e19..e5b7681435 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -246,6 +246,7 @@ attributedStringInfo getSegments(NSAttributedString *str) if ([theEvent modifierFlags] & NSControlKeyMask) { callRightMouseDown(mMousePos, mModifiers); + mSimulatedRightClick = true; } else { if ([theEvent clickCount] >= 2) { @@ -258,7 +259,13 @@ attributedStringInfo getSegments(NSAttributedString *str) - (void) mouseUp:(NSEvent *)theEvent { - callLeftMouseUp(mMousePos, mModifiers); + if (mSimulatedRightClick) + { + callRightMouseUp(mMousePos, mModifiers); + mSimulatedRightClick = false; + } else { + callLeftMouseUp(mMousePos, mModifiers); + } } - (void) rightMouseDown:(NSEvent *)theEvent -- cgit v1.3 From b2bec3f99c74d21bb1c2c68d73854f3990db26d5 Mon Sep 17 00:00:00 2001 From: Geenz Date: Thu, 11 Jul 2013 19:37:08 -0400 Subject: STORM-1942: dock icon bouncing unimplemented --- indra/llwindow/llwindowmacosx-objc.h | 1 + indra/llwindow/llwindowmacosx-objc.mm | 5 +++++ indra/llwindow/llwindowmacosx.cpp | 34 +++------------------------------- indra/llwindow/llwindowmacosx.h | 5 ----- 4 files changed, 9 insertions(+), 36 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index 914fc534fb..020e2bff5b 100755 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -68,6 +68,7 @@ void setNotAllowedCursor(); void hideNSCursor(); void showNSCursor(); void hideNSCursorTillMove(bool hide); +void requestUserAttention(); NSWindowRef createNSWindow(int x, int y, int width, int height); diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index 41d8e3ecd9..ef29515403 100755 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -390,6 +390,11 @@ void makeFirstResponder(NSWindowRef window, GLViewRef view) [(LLNSWindow*)window makeFirstResponder:(LLOpenGLView*)view]; } +void requestUserAttention() +{ + [[NSApplication sharedApplication] requestUserAttention:NSInformationalRequest]; +} + /* GLViewRef getGLView() { diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 737ecba368..e5556c23d4 100755 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -149,10 +149,6 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks, mFSAASamples = fsaa_samples; mForceRebuild = FALSE; - // For reasons that aren't clear to me, LLTimers seem to be created in the "started" state. - // Since the started state of this one is used to track whether the NMRec has been installed, it wants to start out in the "stopped" state. - mBounceTimer.stop(); - // Get the original aspect ratio of the main device. mOriginalAspectRatio = (double)CGDisplayPixelsWide(mDisplay) / (double)CGDisplayPixelsHigh(mDisplay); @@ -763,12 +759,6 @@ BOOL LLWindowMacOSX::getFullscreen() void LLWindowMacOSX::gatherInput() { - // stop bouncing icon after fixed period of time - if (mBounceTimer.getStarted() && mBounceTimer.getElapsedTimeF32() > mBounceTime) - { - stopDockTileBounce(); - } - updateCursor(); } @@ -1161,22 +1151,9 @@ void LLWindowMacOSX::afterDialog() void LLWindowMacOSX::flashIcon(F32 seconds) { - // Don't do this if we're already started, since this would try to install the NMRec twice. - if(!mBounceTimer.getStarted()) - { - S32 err = 0; - // TODO: Implement icon bouncing - mBounceTime = seconds; - if(err == 0) - { - mBounceTimer.start(); - } - else - { - // This is very not-fatal (only problem is the icon will not bounce), but we'd like to find out about it somehow... - llinfos << "NMInstall failed with error code " << err << llendl; - } - } + // For consistency with OS X conventions, the number of seconds given is ignored and + // left up to the OS (which will actually bounce it for one second). + requestUserAttention(); } BOOL LLWindowMacOSX::isClipboardTextAvailable() @@ -1809,11 +1786,6 @@ void *LLWindowMacOSX::getPlatformWindow() return (void*)mWindow; } -void LLWindowMacOSX::stopDockTileBounce() -{ - mBounceTimer.stop(); -} - // get a double value from a dictionary /* static double getDictDouble (CFDictionaryRef refDict, CFStringRef key) diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h index 82195c2700..6a6b39e674 100755 --- a/indra/llwindow/llwindowmacosx.h +++ b/indra/llwindow/llwindowmacosx.h @@ -164,7 +164,6 @@ protected: void destroyContext(); void setupFailure(const std::string& text, const std::string& caption, U32 type); void adjustCursorDecouple(bool warpingMouse = false); - void stopDockTileBounce(); static MASK modifiersToMask(S16 modifiers); #if LL_OS_DRAGDROP_ENABLED @@ -206,10 +205,6 @@ protected: BOOL mForceRebuild; S32 mDragOverrideCursor; - - F32 mBounceTime; - //NMRec mBounceRec; - LLTimer mBounceTimer; // Input method management through Text Service Manager. BOOL mLanguageTextInputAllowed; -- cgit v1.3 From dc7d287717ed42d1d8aa8b57cfd740ca75fe9e7b Mon Sep 17 00:00:00 2001 From: Geenz Date: Thu, 11 Jul 2013 19:41:57 -0400 Subject: OPEN-170: "Set Window Size" always increases window size by specified size --- indra/llwindow/llwindowmacosx.cpp | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index e5556c23d4..d657c629b9 100755 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -863,26 +863,11 @@ BOOL LLWindowMacOSX::setSizeImpl(const LLCoordScreen size) BOOL LLWindowMacOSX::setSizeImpl(const LLCoordWindow size) { - float client_rect[4]; if (mWindow) { - S32 err = noErr; - getContentViewBounds(mWindow, client_rect); - if (err == noErr) - { - client_rect[2] += size.mX; - client_rect[3] += size.mY; - setWindowSize(mWindow, client_rect[2], client_rect[3]); - } - if (err == noErr) - { - return TRUE; - } - else - { - llinfos << "Error setting size" << err << llendl; - return FALSE; - } + LLCoordScreen screen_size; + convertCoords(size, &screen_size); + return setSizeImpl(screen_size); } return FALSE; } -- cgit v1.3 From a787e272c31d8e535dae75e4d95365d17cec78db Mon Sep 17 00:00:00 2001 From: Geenz Date: Thu, 11 Jul 2013 21:31:17 -0400 Subject: Alert box support! --- indra/llwindow/llopenglview-objc.mm | 2 +- indra/llwindow/llwindowmacosx-objc.h | 1 + indra/llwindow/llwindowmacosx-objc.mm | 35 +++++++++++++++++++++++++++++++++++ indra/llwindow/llwindowmacosx.cpp | 23 +---------------------- 4 files changed, 38 insertions(+), 23 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index e5b7681435..42ad4f8723 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -668,7 +668,7 @@ attributedStringInfo getSegments(NSAttributedString *str) - (BOOL) resignFirstResponder { - callFocus(); + callFocusLost(); return true; } diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index 020e2bff5b..32b3bfb078 100755 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -69,6 +69,7 @@ void hideNSCursor(); void showNSCursor(); void hideNSCursorTillMove(bool hide); void requestUserAttention(); +long showAlert(std::string title, std::string text, int type); NSWindowRef createNSWindow(int x, int y, int width, int height); diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index ef29515403..3703dcf28d 100755 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -395,6 +395,41 @@ void requestUserAttention() [[NSApplication sharedApplication] requestUserAttention:NSInformationalRequest]; } +long showAlert(std::string text, std::string title, int type) +{ + NSAlert *alert = [[NSAlert alloc] init]; + + [alert setMessageText:[NSString stringWithCString:title.c_str() encoding:[NSString defaultCStringEncoding]]]; + [alert setInformativeText:[NSString stringWithCString:text.c_str() encoding:[NSString defaultCStringEncoding]]]; + if (type == 0) + { + [alert addButtonWithTitle:@"Okay"]; + } else if (type == 1) + { + [alert addButtonWithTitle:@"Okay"]; + [alert addButtonWithTitle:@"Cancel"]; + } else if (type == 2) + { + [alert addButtonWithTitle:@"Yes"]; + [alert addButtonWithTitle:@"No"]; + } + long ret = [alert runModal]; + [alert dealloc]; + + if (ret == NSAlertFirstButtonReturn) + { + ret = 0; + } else if (ret == NSAlertSecondButtonReturn) + { + ret = 1; + } else if (ret == NSAlertThirdButtonReturn) + { + ret = 2; + } + + return ret; +} + /* GLViewRef getGLView() { diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index d657c629b9..beb9ebe8e0 100755 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -1597,24 +1597,6 @@ LLSplashScreenMacOSX::~LLSplashScreenMacOSX() void LLSplashScreenMacOSX::showImpl() { // This code _could_ be used to display a spash screen... -#if 0 - IBNibRef nib = NULL; - S32 err; - - err = CreateNibReference(CFSTR("SecondLife"), &nib); - - if(err == noErr) - { - CreateWindowFromNib(nib, CFSTR("Splash Screen"), &mWindow); - - DisposeNibReference(nib); - } - - if(mWindow != NULL) - { - ShowWindow(mWindow); - } -#endif } void LLSplashScreenMacOSX::updateImpl(const std::string& mesg) @@ -1636,12 +1618,9 @@ void LLSplashScreenMacOSX::hideImpl() } } - - S32 OSMessageBoxMacOSX(const std::string& text, const std::string& caption, U32 type) { - // TODO: Implement a native NSAlert function that replicates all of this. - return 0; + return showAlert(text, caption, type); } // Open a URL with the user's default web browser. -- cgit v1.3 From 2f680eec93f1b06620c04af04116fe49d577cf8f Mon Sep 17 00:00:00 2001 From: Geenz Date: Thu, 11 Jul 2013 21:46:10 -0400 Subject: A bit of cleanup and make the return of showAlert match the OSBTN return types in llwindow.h. --- indra/llwindow/llwindowmacosx-objc.mm | 19 ++++++++++++++----- indra/llwindow/llwindowmacosx.cpp | 8 +------- 2 files changed, 15 insertions(+), 12 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index 3703dcf28d..0354c2b717 100755 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -418,13 +418,22 @@ long showAlert(std::string text, std::string title, int type) if (ret == NSAlertFirstButtonReturn) { - ret = 0; + if (type == 1) + { + ret = 3; + } else if (type == 2) + { + ret = 0; + } } else if (ret == NSAlertSecondButtonReturn) { - ret = 1; - } else if (ret == NSAlertThirdButtonReturn) - { - ret = 2; + if (type == 0 || type == 1) + { + ret = 2; + } else if (type == 2) + { + ret = 1; + } } return ret; diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index beb9ebe8e0..a3e88ea7dc 100755 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -164,7 +164,6 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks, // Stash an object pointer for OSMessageBox() gWindowImplementation = this; // Create the GL context and set it up for windowed or fullscreen, as appropriate. - LL_INFOS("Window") << "Creating context..." << LL_ENDL; if(createContext(x, y, width, height, 32, fullscreen, disable_vsync)) { if(mWindow != NULL) @@ -526,13 +525,11 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits if (mWindow == NULL) { - LL_INFOS("Window") << "Creating window..." << LL_ENDL; mWindow = getMainAppWindow(); } if(mContext == NULL) { - LL_INFOS("Window") << "Creating GL view..." << LL_ENDL; // Our OpenGL view is already defined within SecondLife.xib. // Get the view instead. mGLView = createOpenGLView(mWindow, mFSAASamples, !disable_vsync); @@ -565,12 +562,10 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits GLint frames_per_swap = 0; if (disable_vsync) { - LL_DEBUGS("GLInit") << "Disabling vertical sync" << LL_ENDL; frames_per_swap = 0; } else { - LL_DEBUGS("GLinit") << "Keeping vertical sync" << LL_ENDL; frames_per_swap = 1; } @@ -593,9 +588,8 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits LL_DEBUGS("GLInit") << "Multi-threaded OpenGL enabled." << LL_ENDL; } } - LL_INFOS("Window") << "Completed context creation." << LL_ENDL; makeFirstResponder(mWindow, mGLView); - // Don't need to get the current gamma, since there's a call that restores it to the system defaults. + return TRUE; } -- cgit v1.3 From dea416fd83497d22147b3c0abab1bf1240e472dd Mon Sep 17 00:00:00 2001 From: Geenz Date: Thu, 11 Jul 2013 22:07:17 -0400 Subject: Rework the command+click functionality a bit to ensure we're not mistakenly simulating a right click where we shouldn't. --- indra/llwindow/llopenglview-objc.mm | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index 42ad4f8723..5f34d03c35 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -243,7 +243,13 @@ attributedStringInfo getSegments(NSAttributedString *str) - (void) mouseDown:(NSEvent *)theEvent { // Apparently people still use this? - if ([theEvent modifierFlags] & NSControlKeyMask) + if ([theEvent modifierFlags] & NSCommandKeyMask && + !([theEvent modifierFlags] & NSControlKeyMask) && + !([theEvent modifierFlags] & NSShiftKeyMask) && + !([theEvent modifierFlags] & NSAlternateKeyMask) && + !([theEvent modifierFlags] & NSAlphaShiftKeyMask) && + !([theEvent modifierFlags] & NSFunctionKeyMask) && + !([theEvent modifierFlags] & NSHelpKeyMask)) { callRightMouseDown(mMousePos, mModifiers); mSimulatedRightClick = true; -- cgit v1.3 From 6ca0bbe3365b3d554789915ac143a87d2d39fdfa Mon Sep 17 00:00:00 2001 From: Geenz Date: Tue, 23 Jul 2013 10:39:32 -0400 Subject: Fix for BUG-3364 --- indra/llwindow/llwindowmacosx.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index a3e88ea7dc..56472e6b45 100755 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -316,7 +316,7 @@ void callMouseMoved(float *pos, MASK mask) outCoords.mX += deltas[0]; outCoords.mY += deltas[1]; gWindowImplementation->getCallbacks()->handleMouseMove(gWindowImplementation, outCoords, gKeyboard->currentMask(TRUE)); - gWindowImplementation->getCallbacks()->handleScrollWheel(gWindowImplementation, 0); + //gWindowImplementation->getCallbacks()->handleScrollWheel(gWindowImplementation, 0); } void callScrollMoved(float delta) @@ -849,20 +849,24 @@ BOOL LLWindowMacOSX::setSizeImpl(const LLCoordScreen size) { if(mWindow) { - setWindowSize(mWindow, size.mX, size.mY); + LLCoordWindow to; + convertCoords(size, &to); + setWindowSize(mWindow, to.mX, to.mY); + return TRUE; } - return TRUE; + return FALSE; } BOOL LLWindowMacOSX::setSizeImpl(const LLCoordWindow size) { if (mWindow) { - LLCoordScreen screen_size; - convertCoords(size, &screen_size); - return setSizeImpl(screen_size); + const int titlePadding = 22; + setWindowSize(mWindow, size.mX, size.mY + titlePadding); + return TRUE; } + return FALSE; } -- cgit v1.3 From ee0b66f080de53f70599c824d5ff231d6a9c739f Mon Sep 17 00:00:00 2001 From: "Jeff (Gioffredo Linden)" Date: Thu, 25 Jul 2013 16:07:16 -0400 Subject: VITA test framework - record events support --- indra/llui/CMakeLists.txt | 2 + indra/llui/llbutton.cpp | 4 + indra/llui/llfloater.cpp | 25 +- indra/llui/llfloater.h | 1 + indra/llui/lltabcontainer.cpp | 56 +++-- indra/llui/lluictrl.cpp | 20 +- indra/llui/llview.cpp | 61 ++++- indra/llui/llviewereventrecorder.cpp | 270 +++++++++++++++++++++ indra/llui/llviewereventrecorder.h | 78 ++++++ indra/llwindow/llwindowmacosx.cpp | 2 + indra/newview/app_settings/cmd_line.xml | 8 + indra/newview/app_settings/settings.xml | 21 ++ indra/newview/llappviewer.cpp | 9 + indra/newview/llviewerkeyboard.cpp | 5 +- indra/newview/llviewermenu.cpp | 41 ++++ indra/newview/llviewerwindow.cpp | 102 ++++---- indra/newview/llwindowlistener.cpp | 9 +- indra/newview/skins/default/xui/en/menu_viewer.xml | 28 +++ 18 files changed, 660 insertions(+), 82 deletions(-) create mode 100644 indra/llui/llviewereventrecorder.cpp create mode 100644 indra/llui/llviewereventrecorder.h (limited to 'indra/llwindow') diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 34a08603fa..aa6684e7a8 100755 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -128,6 +128,7 @@ set(llui_SOURCE_FILES llviewmodel.cpp llview.cpp llviewquery.cpp + llviewereventrecorder.cpp llwindowshade.cpp llxuiparser.cpp ) @@ -240,6 +241,7 @@ set(llui_HEADER_FILES llviewinject.h llviewmodel.h llview.h + llviewereventrecorder.h llviewquery.h llwindowshade.h llxuiparser.h diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index a8149a9a1d..4ccb019106 100755 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -49,6 +49,7 @@ #include "lluictrlfactory.h" #include "llhelp.h" #include "lldockablefloater.h" +#include "llviewereventrecorder.h" static LLDefaultChildRegistry::Register r("button"); @@ -443,6 +444,8 @@ BOOL LLButton::handleMouseDown(S32 x, S32 y, MASK mask) */ LLUICtrl::handleMouseDown(x, y, mask); + LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-55,-55,getPathname()); + if(mMouseDownSignal) (*mMouseDownSignal)(this, LLSD()); mMouseDownTimer.start(); @@ -473,6 +476,7 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask) * by calling LLUICtrl::mMouseUpSignal(x, y, mask); */ LLUICtrl::handleMouseUp(x, y, mask); + LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-55,-55,getPathname()); // Regardless of where mouseup occurs, handle callback if(mMouseUpSignal) (*mMouseUpSignal)(this, LLSD()); diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 09e27a264a..913de49d63 100755 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -29,7 +29,7 @@ // mini-map floater, etc. #include "linden_common.h" - +#include "llviewereventrecorder.h" #include "llfloater.h" #include "llfocusmgr.h" @@ -653,7 +653,10 @@ void LLFloater::handleVisibilityChange ( BOOL new_visibility ) void LLFloater::openFloater(const LLSD& key) { - llinfos << "Opening floater " << getName() << llendl; + llinfos << "Opening floater " << getName() << " full path: " << getPathname() << llendl; + + LLViewerEventRecorder::instance().logVisibilityChange( getPathname(), getName(), true,"floater"); // Last param is event subtype or empty string + mKey = key; // in case we need to open ourselves again if (getSoundFlags() != SILENT @@ -707,6 +710,7 @@ void LLFloater::openFloater(const LLSD& key) void LLFloater::closeFloater(bool app_quitting) { llinfos << "Closing floater " << getName() << llendl; + LLViewerEventRecorder::instance().logVisibilityChange( getPathname(), getName(), false,"floater"); // Last param is event subtype or empty string if (app_quitting) { LLFloater::sQuitting = true; @@ -1552,6 +1556,17 @@ BOOL LLFloater::handleScrollWheel(S32 x, S32 y, S32 clicks) return TRUE;//always } +// virtual +BOOL LLFloater::handleMouseUp(S32 x, S32 y, MASK mask) +{ + lldebugs << "LLFloater::handleMouseUp calling LLPanel (really LLView)'s handleMouseUp (first initialized xui to: " << getPathname() << " )" << llendl; + BOOL handled = LLPanel::handleMouseUp(x,y,mask); // Not implemented in LLPanel so this actually calls LLView + if (handled) { + LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-55,-55,getPathname()); + } + return handled; +} + // virtual BOOL LLFloater::handleMouseDown(S32 x, S32 y, MASK mask) { @@ -1572,7 +1587,11 @@ BOOL LLFloater::handleMouseDown(S32 x, S32 y, MASK mask) else { bringToFront( x, y ); - return LLPanel::handleMouseDown( x, y, mask ); + BOOL handled = LLPanel::handleMouseDown( x, y, mask ); + if (handled) { + LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-55,-55,getPathname()); + } + return handled; } } diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 4dba1e645f..09fe2219c0 100755 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -285,6 +285,7 @@ public: S32 getHeaderHeight() const { return mHeaderHeight; } virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); + virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask); virtual BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask); diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index fd98155704..76ba53ec32 100755 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -27,7 +27,7 @@ #include "linden_common.h" #include "lltabcontainer.h" - +#include "llviewereventrecorder.h" #include "llfocusmgr.h" #include "lllocalcliprect.h" #include "llrect.h" @@ -578,6 +578,11 @@ BOOL LLTabContainer::handleMouseDown( S32 x, S32 y, MASK mask ) tab_button->setFocus(TRUE); } } + if (handled) { + // Note: May need to also capture local coords right here ? + LLViewerEventRecorder::instance().update_xui(getPathname( )); + } + return handled; } @@ -629,30 +634,33 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask ) BOOL handled = FALSE; BOOL has_scroll_arrows = (getMaxScrollPos() > 0) && !getTabsHidden(); + S32 local_x = x - getRect().mLeft; + S32 local_y = y - getRect().mBottom; + if (has_scroll_arrows) { if (mJumpPrevArrowBtn && mJumpPrevArrowBtn->getRect().pointInRect(x, y)) { - S32 local_x = x - mJumpPrevArrowBtn->getRect().mLeft; - S32 local_y = y - mJumpPrevArrowBtn->getRect().mBottom; + local_x = x - mJumpPrevArrowBtn->getRect().mLeft; + local_y = y - mJumpPrevArrowBtn->getRect().mBottom; handled = mJumpPrevArrowBtn->handleMouseUp(local_x, local_y, mask); } else if (mJumpNextArrowBtn && mJumpNextArrowBtn->getRect().pointInRect(x, y)) { - S32 local_x = x - mJumpNextArrowBtn->getRect().mLeft; - S32 local_y = y - mJumpNextArrowBtn->getRect().mBottom; + local_x = x - mJumpNextArrowBtn->getRect().mLeft; + local_y = y - mJumpNextArrowBtn->getRect().mBottom; handled = mJumpNextArrowBtn->handleMouseUp(local_x, local_y, mask); } else if (mPrevArrowBtn && mPrevArrowBtn->getRect().pointInRect(x, y)) { - S32 local_x = x - mPrevArrowBtn->getRect().mLeft; - S32 local_y = y - mPrevArrowBtn->getRect().mBottom; + local_x = x - mPrevArrowBtn->getRect().mLeft; + local_y = y - mPrevArrowBtn->getRect().mBottom; handled = mPrevArrowBtn->handleMouseUp(local_x, local_y, mask); } else if (mNextArrowBtn && mNextArrowBtn->getRect().pointInRect(x, y)) { - S32 local_x = x - mNextArrowBtn->getRect().mLeft; - S32 local_y = y - mNextArrowBtn->getRect().mBottom; + local_x = x - mNextArrowBtn->getRect().mLeft; + local_y = y - mNextArrowBtn->getRect().mBottom; handled = mNextArrowBtn->handleMouseUp(local_x, local_y, mask); } } @@ -676,6 +684,10 @@ BOOL LLTabContainer::handleMouseUp( S32 x, S32 y, MASK mask ) } gFocusMgr.setMouseCapture(NULL); } + if (handled) { + // Note: may need to capture local coords here + LLViewerEventRecorder::instance().update_xui(getPathname( )); + } return handled; } @@ -1059,21 +1071,21 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel) if (mIsVertical) { - p.name(std::string("vert tab button")); - p.image_unselected(mMiddleTabParams.tab_left_image_unselected); - p.image_selected(mMiddleTabParams.tab_left_image_selected); - p.follows.flags = p.follows.flags() | FOLLOWS_TOP; + p.name("vtab_"+std::string(child->getName())); + p.image_unselected(mMiddleTabParams.tab_left_image_unselected); + p.image_selected(mMiddleTabParams.tab_left_image_selected); + p.follows.flags = p.follows.flags() | FOLLOWS_TOP; } else - { - p.name(std::string(child->getName()) + " tab"); - p.visible(false); - p.image_unselected(tab_img); - p.image_selected(tab_selected_img); - p.follows.flags = p.follows.flags() | (getTabPosition() == TOP ? FOLLOWS_TOP : FOLLOWS_BOTTOM); - // Try to squeeze in a bit more text - p.pad_left( mLabelPadLeft ); - p.pad_right(2); + { + p.name("htab_"+std::string(child->getName())); + p.visible(false); + p.image_unselected(tab_img); + p.image_selected(tab_selected_img); + p.follows.flags = p.follows.flags() | (getTabPosition() == TOP ? FOLLOWS_TOP : FOLLOWS_BOTTOM); + // Try to squeeze in a bit more text + p.pad_left( mLabelPadLeft ); + p.pad_right(2); } // *TODO : It seems wrong not to use p in both cases considering the way p is initialized diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index b9c843e931..1722bf27bd 100755 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -29,7 +29,7 @@ #define LLUICTRL_CPP #include "lluictrl.h" - +#include "llviewereventrecorder.h" #include "llfocusmgr.h" #include "llpanel.h" #include "lluictrlfactory.h" @@ -308,22 +308,40 @@ void LLUICtrl::onMouseLeave(S32 x, S32 y, MASK mask) //virtual BOOL LLUICtrl::handleMouseDown(S32 x, S32 y, MASK mask) { + + lldebugs << "LLUICtrl::handleMouseDown calling LLView)'s handleMouseUp (first initialized xui to: " << getPathname() << " )" << llendl; + BOOL handled = LLView::handleMouseDown(x,y,mask); + if (mMouseDownSignal) { (*mMouseDownSignal)(this,x,y,mask); } + lldebugs << "LLUICtrl::handleMousedown - handled is returning as: " << handled << " " << llendl; + + if (handled) { + LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-56,-56,getPathname()); + } return handled; } //virtual BOOL LLUICtrl::handleMouseUp(S32 x, S32 y, MASK mask) { + + lldebugs << "LLUICtrl::handleMouseUp calling LLView)'s handleMouseUp (first initialized xui to: " << getPathname() << " )" << llendl; + BOOL handled = LLView::handleMouseUp(x,y,mask); + if (handled) { + LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-56,-56,getPathname()); + } if (mMouseUpSignal) { (*mMouseUpSignal)(this,x,y,mask); } + + lldebugs << "LLUICtrl::handleMouseUp - handled for xui " << getPathname() << " - is returning as: " << handled << " " << llendl; + return handled; } diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 3613a40e2c..9a42fc637b 100755 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -48,7 +48,9 @@ #include "lluictrlfactory.h" #include "lltooltip.h" #include "llsdutil.h" - +#include "llsdserialize.h" +#include "llviewereventrecorder.h" +#include "llkeyboard.h" // for ui edit hack #include "llbutton.h" #include "lllineeditor.h" @@ -642,13 +644,27 @@ void LLView::setVisible(BOOL visible) // virtual void LLView::handleVisibilityChange ( BOOL new_visibility ) { + BOOL old_visibility; BOOST_FOREACH(LLView* viewp, mChildList) { // only views that are themselves visible will have their overall visibility affected by their ancestors - if (viewp->getVisible()) + old_visibility=viewp->getVisible(); + + if (old_visibility!=new_visibility) + { + LLViewerEventRecorder::instance().logVisibilityChange( viewp->getPathname(), viewp->getName(), new_visibility,"widget"); + } + + if (old_visibility) { viewp->handleVisibilityChange ( new_visibility ); } + + // Consider changing returns to confirm success and know which widget grabbed it + // For now assume success and log at highest xui possible + // NOTE we log actual state - which may differ if it somehow failed to set visibility + lldebugs << "LLView::handleVisibilityChange - now: " << getVisible() << " xui: " << viewp->getPathname() << " name: " << viewp->getName() << llendl; + } } @@ -697,6 +713,7 @@ bool LLView::visibleEnabledAndContains(S32 local_x, S32 local_y) && getEnabled(); } +// This is NOT event recording related void LLView::logMouseEvent() { if (sDebugMouseHandling) @@ -743,8 +760,15 @@ LLView* LLView::childrenHandleMouseEvent(const METHOD& method, S32 x, S32 y, XDA if ((viewp->*method)( local_x, local_y, extra ) || (allow_mouse_block && viewp->blockMouseEvent( local_x, local_y ))) { - viewp->logMouseEvent(); - return viewp; + lldebugs << "LLView::childrenHandleMouseEvent calling updatemouseeventinfo - local_x|global x "<< local_x << " " << x << "local/global y " << local_y << " " << y << llendl; + lldebugs << "LLView::childrenHandleMouseEvent getPathname for viewp result: " << viewp->getPathname() << "for this view: " << getPathname() << llendl; + + LLViewerEventRecorder::instance().updateMouseEventInfo(x,y,-55,-55,getPathname()); + + // This is NOT event recording related + viewp->logMouseEvent(); + + return viewp; } } return NULL; @@ -766,6 +790,7 @@ LLView* LLView::childrenHandleToolTip(S32 x, S32 y, MASK mask) if (viewp->handleToolTip(local_x, local_y, mask) || viewp->blockMouseEvent(local_x, local_y)) { + // This is NOT event recording related viewp->logMouseEvent(); return viewp; } @@ -824,6 +849,7 @@ LLView* LLView::childrenHandleHover(S32 x, S32 y, MASK mask) if (viewp->handleHover(local_x, local_y, mask) || viewp->blockMouseEvent(local_x, local_y)) { + // This is NOT event recording related viewp->logMouseEvent(); return viewp; } @@ -907,10 +933,11 @@ BOOL LLView::handleKey(KEY key, MASK mask, BOOL called_from_parent) if (!handled) { + // For event logging we don't care which widget handles it + // So we capture the key at the end of this function once we know if it was handled handled = handleKeyHere( key, mask ); - if (handled && LLView::sDebugKeys) - { - llinfos << "Key handled by " << getName() << llendl; + if (handled) { + llwarns << "Key handled by " << getName() << llendl; } } } @@ -958,12 +985,17 @@ BOOL LLView::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent) handled = mParentView->handleUnicodeChar(uni_char, FALSE); } + if (handled) { + LLViewerEventRecorder::instance().logKeyUnicodeEvent(uni_char); + } + return handled; } BOOL LLView::handleUnicodeCharHere(llwchar uni_char ) { + llwarns << "LLView::handleUnicodeCharHere - about to return false - key is not being handled - a class somewhere should implement this method" << llendl; return FALSE; } @@ -987,12 +1019,21 @@ BOOL LLView::hasMouseCapture() BOOL LLView::handleMouseUp(S32 x, S32 y, MASK mask) { - return childrenHandleMouseUp( x, y, mask ) != NULL; + + + LLView* r = childrenHandleMouseUp( x, y, mask ); + + return (r!=NULL); + } BOOL LLView::handleMouseDown(S32 x, S32 y, MASK mask) { - return childrenHandleMouseDown( x, y, mask ) != NULL; + + LLView* r= childrenHandleMouseDown(x, y, mask ); + + return (r!=NULL); + } BOOL LLView::handleDoubleClick(S32 x, S32 y, MASK mask) @@ -1065,7 +1106,7 @@ LLView* LLView::childrenHandleDoubleClick(S32 x, S32 y, MASK mask) LLView* LLView::childrenHandleMouseUp(S32 x, S32 y, MASK mask) { - return childrenHandleMouseEvent(&LLView::handleMouseUp, x, y, mask); + return childrenHandleMouseEvent(&LLView::handleMouseUp, x, y, mask); } LLView* LLView::childrenHandleRightMouseUp(S32 x, S32 y, MASK mask) diff --git a/indra/llui/llviewereventrecorder.cpp b/indra/llui/llviewereventrecorder.cpp new file mode 100644 index 0000000000..36df1f6ac1 --- /dev/null +++ b/indra/llui/llviewereventrecorder.cpp @@ -0,0 +1,270 @@ +#include "llviewereventrecorder.h" +#include "llui.h" +#include "llleap.h" + +LLViewerEventRecorder::LLViewerEventRecorder() { + + clear(UNDEFINED); + + // Remove any previous event log file + std::string old_log_ui_events_to_llsd_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife_Events_log.old"); + LLFile::remove(old_log_ui_events_to_llsd_file); + + + mLogFilename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife_Events_log.llsd"); + LLFile::rename(mLogFilename, old_log_ui_events_to_llsd_file); + +} + + +bool LLViewerEventRecorder::displayViewerEventRecorderMenuItems() { + return LLUI::sSettingGroups["config"]->getBOOL("ShowEventRecorderMenuItems"); +} + + +void LLViewerEventRecorder::setEventLoggingOn() { + if (! mLog.is_open()) { + mLog.open(mLogFilename, llofstream::out); + } + logEvents=true; + lldebugs << "LLViewerEventRecorder::setEventLoggingOn event logging turned on" << llendl; +} + +void LLViewerEventRecorder::setEventLoggingOff() { + logEvents=false; + mLog.flush(); + mLog.close(); + lldebugs << "LLViewerEventRecorder::setEventLoggingOff event logging turned off" << llendl; +} + + + LLViewerEventRecorder::~LLViewerEventRecorder() { + if (mLog.is_open()) { + mLog.close(); + } +} + +void LLViewerEventRecorder::clear_xui() { + xui.clear(); +} + +void LLViewerEventRecorder::clear(S32 r) { + + xui.clear(); + + local_x=r; + local_y=r; + + global_x=r; + global_y=r; + + +} + +void LLViewerEventRecorder::setMouseLocalCoords(S32 x, S32 y) { + local_x=x; + local_y=y; +} + +void LLViewerEventRecorder::setMouseGlobalCoords(S32 x, S32 y) { + global_x=x; + global_y=y; +} + +void LLViewerEventRecorder::updateMouseEventInfo(S32 local_x, S32 local_y, S32 global_x, S32 global_y, std::string mName) { + + LLView * target_view = LLUI::resolvePath(LLUI::getRootView(), xui); + if (! target_view) { + lldebugs << "LLViewerEventRecorder::updateMouseEventInfo - xui path on file at moment is NOT valid - so DO NOT record these local coords" << llendl; + return; + } + lldebugs << "LLViewerEventRecorder::updateMouseEventInfo b4 updatemouseeventinfo - local_x|global x "<< this->local_x << " " << this->global_x << "local/global y " << this->local_y << " " << this->global_y << " mname: " << mName << " xui: " << xui << llendl; + + + if (this->local_x < 1 && this->local_y<1 && local_x && local_y) { + this->local_x=local_x; + this->local_y=local_y; + } + this->global_x=global_x; + this->global_y=global_y; + + // ONLY record deepest xui path for hierarchy searches - or first/only xui for floaters/panels reached via mouse captor - and llmousehandler + if (mName!="" && mName!="/" && xui=="") { + // xui=std::string("/")+mName+xui; + //xui=mName+xui; + xui = mName; // TODO review confirm we never call with partial path - also cAN REMOVE CHECK FOR "" - ON OTHER HAND IT'S PRETTY HARMLESS + } + + lldebugs << "LLViewerEventRecorder::updateMouseEventInfo after updatemouseeventinfo - local_x|global x "<< this->local_x << " " << this->global_x << "local/global y " << this->local_y << " " << this->global_y << " mname: " << mName << " xui: " << xui << llendl; +} + +void LLViewerEventRecorder::logVisibilityChange(std::string xui, std::string name, BOOL visibility, std::string event_subtype) { + + LLSD event=LLSD::emptyMap(); + + event.insert("event",LLSD(std::string("visibility"))); + + if (visibility) { + event.insert("visibility",LLSD(true)); + } else { + event.insert("visibility",LLSD(false)); + } + + if (event_subtype!="") { + event.insert("event_subtype", LLSD(event_subtype)); + } + + if(name!="") { + event.insert("name",LLSD(name)); + } + + if (xui!="") { + event.insert("path",LLSD(xui)); + } + + event.insert("timestamp",LLSD(LLDate::now().asString())); + recordEvent(event); +} + + +std::string LLViewerEventRecorder::get_xui() { + return xui; +} +void LLViewerEventRecorder::update_xui(std::string xui) { + if (xui!="" && this->xui=="" ) { + lldebugs << "LLViewerEventRecorder::update_xui to " << xui << llendl; + this->xui=xui; + } else { + lldebugs << "LLViewerEventRecorder::update_xui called with empty string" << llendl; + } +} + +void LLViewerEventRecorder::logKeyEvent(KEY key, MASK mask) { + + // NOTE: Event recording only logs keydown events - the viewer itself hides keyup events at a fairly low level in the code and does not appear to care about them anywhere + + LLSD event = LLSD::emptyMap(); + + event.insert("event",LLSD("type")); + + // keysym ...or + // keycode...or + // char + event.insert("keysym",LLSD(LLKeyboard::stringFromKey(key))); + + // path (optional) - for now we are not recording path for key events during record - should not be needed for full record and playback of recorded steps + // as a vita script - it does become useful if you edit the resulting vita script and wish to remove some steps leading to a key event - that sort of edit might + // break the test script and it would be useful to have more context to make these sorts of edits safer + + // TODO replace this with a call which extracts to an array of names of masks (just like vita expects during playback) + // This is looking more and more like an object is a good idea, for this part a handy method call to setMask(mask) would be nice :-) + // call the func - llkeyboard::llsdStringarrayFromMask + + LLSD key_mask=LLSD::emptyArray(); + + if (mask & MASK_CONTROL) { key_mask.append(LLSD("CTL")); } // Mac command key - has code of 0x1 in llcommon/indra_contstants + if (mask & MASK_ALT) { key_mask.append(LLSD("ALT")); } + if (mask & MASK_SHIFT) { key_mask.append(LLSD("SHIFT")); } + if (mask & MASK_MAC_CONTROL) { key_mask.append(LLSD("MAC_CONTROL")); } + + event.insert("mask",key_mask); + event.insert("timestamp",LLSD(LLDate::now().asString())); + + // Although vita has keyDown and keyUp requests it does not have type as a high-level concept + // (maybe it should) - instead it has a convenience method that generates the keydown and keyup events + // Here we will use "type" as our event type + + lldebugs << "LLVIewerEventRecorder::logKeyEvent Serialized LLSD for event " << event.asString() << "\n" << llendl; + + + //lldebugs << "[VITA] key_name: " << LLKeyboard::stringFromKey(key) << "mask: "<< mask << "handled by " << getName() << llendl; + lldebugs << "LLVIewerEventRecorder::logKeyEvent key_name: " << LLKeyboard::stringFromKey(key) << "mask: "<< mask << llendl; + + + recordEvent(event); + +} + +void LLViewerEventRecorder::playbackRecording() { + + LLSD LeapCommand; + + // ivita sets this on startup, it also sends commands to the viewer to make start, stop, and playback menu items visible in viewer + LeapCommand =LLUI::sSettingGroups["config"]->getLLSD("LeapPlaybackEventsCommand"); + + lldebugs << "[VITA] launching playback - leap command is: " << LLSDXMLStreamer(LeapCommand) << llendl; + LLLeap::create("", LeapCommand, false); // exception=false + +} + + +void LLViewerEventRecorder::recordEvent(LLSD event) { + lldebugs << "LLViewerEventRecorder::recordEvent event written to log: " << LLSDXMLStreamer(event) << llendl; + mLog << event << std::endl; + +} +void LLViewerEventRecorder::logKeyUnicodeEvent(llwchar uni_char) { + if (! logEvents) return; + + // Note: keyUp is not captured since the viewer seems to not care about keyUp events + + LLSD event=LLSD::emptyMap(); + + event.insert("timestamp",LLSD(LLDate::now().asString())); + + + // keysym ...or + // keycode...or + // char + + lldebugs << "Wrapped in conversion to wstring " << wstring_to_utf8str(LLWString( 1, uni_char)) << "\n" << llendl; + + event.insert("char", + LLSD( wstring_to_utf8str(LLWString( 1,uni_char)) ) + ); + + // path (optional) - for now we are not recording path for key events during record - should not be needed for full record and playback of recorded steps + // as a vita script - it does become useful if you edit the resulting vita script and wish to remove some steps leading to a key event - that sort of edit might + // break the test script and it would be useful to have more context to make these sorts of edits safer + + // TODO need to consider mask keys too? Doesn't seem possible - at least not easily at this point + + event.insert("event",LLSD("keyDown")); + + lldebugs << "[VITA] unicode key: " << uni_char << llendl; + lldebugs << "[VITA] dumpxml " << LLSDXMLStreamer(event) << "\n" << llendl; + + + recordEvent(event); + +} + +void LLViewerEventRecorder::logMouseEvent(std::string button_state,std::string button_name) +{ + if (! logEvents) return; + + LLSD event=LLSD::emptyMap(); + + event.insert("event",LLSD(std::string("mouse"+ button_state))); + event.insert("button",LLSD(button_name)); + if (xui!="") { + event.insert("path",LLSD(xui)); + } + + if (local_x>0 && local_y>0) { + event.insert("local_x",LLSD(local_x)); + event.insert("local_y",LLSD(local_y)); + } + + if (global_x>0 && global_y>0) { + event.insert("global_x",LLSD(global_x)); + event.insert("global_y",LLSD(global_y)); + } + event.insert("timestamp",LLSD(LLDate::now().asString())); + recordEvent(event); + + + clear(UNDEFINED); + + +} diff --git a/indra/llui/llviewereventrecorder.h b/indra/llui/llviewereventrecorder.h new file mode 100644 index 0000000000..190490b51f --- /dev/null +++ b/indra/llui/llviewereventrecorder.h @@ -0,0 +1,78 @@ +#ifndef LL_VIEWER_EVENT_RECORDER +#define LL_VIEWER_EVENT_RECORDER + + +#include "linden_common.h" + +#include "lldir.h" +#include "llsd.h" +#include "llfile.h" +#include "llvfile.h" +#include "lldate.h" +#include "llsdserialize.h" +#include "llkeyboard.h" +#include "llstring.h" + +#include + +#include "llsingleton.h" // includes llerror which we need here so we can skip the include here + +class LLViewerEventRecorder : public LLSingleton +{ + + public: + + LLViewerEventRecorder(); // TODO Protect constructor better if we can (not happy in private section) - could add a factory... - we are singleton + ~LLViewerEventRecorder(); + + + void updateMouseEventInfo(S32 local_x,S32 local_y, S32 global_x, S32 global_y, std::string mName); + void setMouseLocalCoords(S32 x,S32 y); + void setMouseGlobalCoords(S32 x,S32 y); + + void logMouseEvent(std::string button_state, std::string button_name ); + void logKeyEvent(KEY key, MASK mask); + void logKeyUnicodeEvent(llwchar uni_char); + + void logVisibilityChange(std::string xui, std::string name, BOOL visibility, std::string event_subtype); + + void clear_xui(); + std::string get_xui(); + void update_xui(std::string xui); + + bool getLoggingStatus(); + void setEventLoggingOn(); + void setEventLoggingOff(); + + void playbackRecording(); + + bool displayViewerEventRecorderMenuItems(); + + + protected: + // On if we wish to log events at the moment - toggle via Develop/Recorder submenu + bool logEvents; + + std::string mLogFilename; + llofstream mLog; + + + private: + + // Mouse event info + S32 global_x; + S32 global_y; + S32 local_x; + S32 local_y; + + // XUI path of UI element + std::string xui; + + // Actually write the event out to llsd log file + void recordEvent(LLSD event); + + void clear(S32 r); + + static const S32 UNDEFINED=-1; +}; +#endif diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 97637c937f..53c7b4ff24 100755 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -2656,6 +2656,8 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e break; case kEventWindowClose: + // Note on event recording - QUIT is a known special case and we are choosing NOT to record it for the record and playback feature + // it is handled at a very low-level if(mCallbacks->handleCloseRequest(this)) { // Get the app to initiate cleanup. diff --git a/indra/newview/app_settings/cmd_line.xml b/indra/newview/app_settings/cmd_line.xml index 7ab7787d77..a6e93edc79 100755 --- a/indra/newview/app_settings/cmd_line.xml +++ b/indra/newview/app_settings/cmd_line.xml @@ -164,6 +164,14 @@ UserLoginInfo + logevents + + desc + Log ui events for later playback + map-to + LogEvents + + logmetrics desc diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 344079b640..54624e3f1d 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4842,6 +4842,16 @@ Value + LeapPlaybackEventsCommand + + Comment + Command line to use leap to launch playback of event recordings + Persist + 0 + Type + LLSD + Value + LSLFindCaseInsensitivity Comment @@ -10105,6 +10115,17 @@ Value 0 + ShowEventRecorderMenuItems + + Comment + Whether or not Event Recorder menu choices - Start / Stop event recording should appear in the (currently) Develop menu + Persist + 0 + Type + Boolean + Value + 0 + ShowGestureButton Comment diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index f92274dbbd..209e91d713 100755 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -222,6 +222,10 @@ #include "llmachineid.h" #include "llmainlooprepeater.h" + +#include "llviewereventrecorder.h" + + // *FIX: These extern globals should be cleaned up. // The globals either represent state/config/resource-storage of either // this app, or another 'component' of the viewer. App globals should be @@ -696,6 +700,7 @@ LLAppViewer::LLAppViewer() : LLAppViewer::~LLAppViewer() { delete mSettingsLocationList; + LLViewerEventRecorder::instance().~LLViewerEventRecorder(); LLLoginInstance::instance().setUpdaterService(0); @@ -2545,6 +2550,10 @@ bool LLAppViewer::initConfiguration() } } + if (clp.hasOption("logevents")) { + LLViewerEventRecorder::instance().setEventLoggingOn(); + } + if(clp.hasOption("channel")) { LLVersionInfo::resetChannel(clp.getOption("channel")[0]); diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index 4ecdc31e21..a8e82c6153 100755 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -681,7 +681,10 @@ BOOL LLViewerKeyboard::handleKey(KEY translated_key, MASK translated_mask, BOOL { // it is sufficient to set this value once per call to handlekey // without clearing it, as it is only used in the subsequent call to scanKey - mKeyHandledByUI[translated_key] = gViewerWindow->handleKey(translated_key, translated_mask); + mKeyHandledByUI[translated_key] = gViewerWindow->handleKey(translated_key, translated_mask); + // mKeyHandledByUI is not what you think ... this indicates whether the UI has handled this keypress yet (any keypress) + // NOT whether some UI shortcut wishes to handle the keypress + } return mKeyHandledByUI[translated_key]; } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 5e2f05f468..7bde5d388e 100755 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -40,6 +40,7 @@ #include "llinventorypanel.h" #include "llnotifications.h" #include "llnotificationsutil.h" +#include "llviewereventrecorder.h" // newview includes #include "llagent.h" @@ -1950,6 +1951,43 @@ class LLAdvancedDropPacket : public view_listener_t }; +//////////////////// +// EVENT Recorder // +/////////////////// + + +class LLAdvancedViewerEventRecorder : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + std::string command = userdata.asString(); + if ("start playback" == command) + { + llinfos << "Event Playback starting" << llendl; + LLViewerEventRecorder::instance().playbackRecording(); + llinfos << "Event Playback completed" << llendl; + } + else if ("stop playback" == command) + { + // Future + } + else if ("start recording" == command) + { + LLViewerEventRecorder::instance().setEventLoggingOn(); + llinfos << "Event recording started" << llendl; + } + else if ("stop recording" == command) + { + LLViewerEventRecorder::instance().setEventLoggingOff(); + llinfos << "Event recording stopped" << llendl; + } + + return true; + } +}; + + + ///////////////// // AGENT PILOT // @@ -8320,6 +8358,8 @@ void initialize_menus() // Don't prepend MenuName.Foo because these can be used in any menu. enable.add("IsGodCustomerService", boost::bind(&is_god_customer_service)); + enable.add("displayViewerEventRecorderMenuItems",boost::bind(&LLViewerEventRecorder::displayViewerEventRecorderMenuItems,&LLViewerEventRecorder::instance())); + view_listener_t::addEnable(new LLUploadCostCalculator(), "Upload.CalculateCosts"); enable.add("Conversation.IsConversationLoggingAllowed", boost::bind(&LLFloaterIMContainer::isConversationLoggingAllowed)); @@ -8578,6 +8618,7 @@ void initialize_menus() view_listener_t::addMenu(new LLAdvancedAgentPilot(), "Advanced.AgentPilot"); view_listener_t::addMenu(new LLAdvancedToggleAgentPilotLoop(), "Advanced.ToggleAgentPilotLoop"); view_listener_t::addMenu(new LLAdvancedCheckAgentPilotLoop(), "Advanced.CheckAgentPilotLoop"); + view_listener_t::addMenu(new LLAdvancedViewerEventRecorder(), "Advanced.EventRecorder"); // Advanced > Debugging view_listener_t::addMenu(new LLAdvancedForceErrorBreakpoint(), "Advanced.ForceErrorBreakpoint"); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 65a906d3c0..3f2ff7eb82 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -197,6 +197,8 @@ #include "llagentui.h" #include "llwearablelist.h" +#include "llviewereventrecorder.h" + #include "llnotifications.h" #include "llnotificationsutil.h" #include "llnotificationmanager.h" @@ -914,27 +916,18 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK { llinfos << buttonname << " Mouse " << buttonstatestr << " handled by captor " << mouse_captor->getName() << llendl; } - return mouse_captor->handleAnyMouseClick(local_x, local_y, mask, clicktype, down); - } - // Topmost view gets a chance before the hierarchy - //LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl(); - //if (top_ctrl) - //{ - // S32 local_x, local_y; - // top_ctrl->screenPointToLocal( x, y, &local_x, &local_y ); - // if (top_ctrl->pointInView(local_x, local_y)) - // { - // return top_ctrl->handleAnyMouseClick(local_x, local_y, mask, clicktype, down) ; - // } - // else - // { - // if (down) - // { - // gFocusMgr.setTopCtrl(NULL); - // } - // } - //} + BOOL r = mouse_captor->handleAnyMouseClick(local_x, local_y, mask, clicktype, down); + if (r) { + + lldebugs << "LLViewerWindow::handleAnyMouseClick viewer with mousecaptor calling updatemouseeventinfo - local_x|global x "<< local_x << " " << x << "local/global y " << local_y << " " << y << llendl; + + LLViewerEventRecorder::instance().setMouseGlobalCoords(x,y); + LLViewerEventRecorder::instance().logMouseEvent(std::string(buttonstatestr),std::string(buttonname)); + + } + return r; + } // Mark the click as handled and return if we aren't within the root view to avoid spurious bugs if( !mRootView->pointInView(x, y) ) @@ -942,27 +935,44 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK return TRUE; } // Give the UI views a chance to process the click - if( mRootView->handleAnyMouseClick(x, y, mask, clicktype, down) ) + + BOOL r= mRootView->handleAnyMouseClick(x, y, mask, clicktype, down) ; + if (r) { + + lldebugs << "LLViewerWindow::handleAnyMouseClick calling updatemouseeventinfo - global x "<< " " << x << "global y " << y << "buttonstate: " << buttonstatestr << " buttonname " << buttonname << llendl; + + LLViewerEventRecorder::instance().setMouseGlobalCoords(x,y); + + // Clear local coords - this was a click on root window so these are not needed + // By not including them, this allows the test skeleton generation tool to be smarter when generating code + // the code generator can be smarter because when local coords are present it can try the xui path with local coords + // and fallback to global coordinates only if needed. + // The drawback to this approach is sometimes a valid xui path will appear to work fine, but NOT interact with the UI element + // (VITA support not implemented yet or not visible to VITA due to widget further up xui path not being visible to VITA) + // For this reason it's best to provide hints where possible here by leaving out local coordinates + LLViewerEventRecorder::instance().setMouseLocalCoords(-1,-1); + LLViewerEventRecorder::instance().logMouseEvent(buttonstatestr,buttonname); + if (LLView::sDebugMouseHandling) { - llinfos << buttonname << " Mouse " << buttonstatestr << " " << LLView::sMouseHandlerMessage << llendl; - } + llinfos << buttonname << " Mouse " << buttonstatestr << " " << LLViewerEventRecorder::instance().get_xui() << llendl; + } return TRUE; - } - else if (LLView::sDebugMouseHandling) - { - llinfos << buttonname << " Mouse " << buttonstatestr << " not handled by view" << llendl; - } + } else if (LLView::sDebugMouseHandling) + { + llinfos << buttonname << " Mouse " << buttonstatestr << " not handled by view" << llendl; + } } // Do not allow tool manager to handle mouseclicks if we have disconnected if(!gDisconnected && LLToolMgr::getInstance()->getCurrentTool()->handleAnyMouseClick( x, y, mask, clicktype, down ) ) { + LLViewerEventRecorder::instance().clear_xui(); return TRUE; } - + // If we got this far on a down-click, it wasn't handled. // Up-clicks, though, are always handled as far as the OS is concerned. BOOL default_rtn = !down; @@ -1333,7 +1343,8 @@ BOOL LLViewerWindow::handleTranslatedKeyUp(KEY key, MASK mask) void LLViewerWindow::handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level) { LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true); - return gViewerKeyboard.scanKey(key, key_down, key_up, key_level); + gViewerKeyboard.scanKey(key, key_down, key_up, key_level); + return; // Be clear this function returns nothing } @@ -2477,6 +2488,8 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) ||(gLoginMenuBarView && gLoginMenuBarView->handleKey(key, mask, TRUE)) ||(gMenuHolder && gMenuHolder->handleKey(key, mask, TRUE))) { + lldebugs << "LLviewerWindow::handleKey handle nav keys for nav" << llendl; + LLViewerEventRecorder::instance().logKeyEvent(key,mask); return TRUE; } @@ -2491,12 +2504,14 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) && keyboard_focus && keyboard_focus->handleKey(key,mask,FALSE)) { + LLViewerEventRecorder::instance().logKeyEvent(key,mask); return TRUE; } if ((gMenuBarView && gMenuBarView->handleAcceleratorKey(key, mask)) ||(gLoginMenuBarView && gLoginMenuBarView->handleAcceleratorKey(key, mask))) { + LLViewerEventRecorder::instance().logKeyEvent(key,mask); return TRUE; } } @@ -2506,6 +2521,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) // if nothing has focus, go to first or last UI element as appropriate if (key == KEY_TAB && (mask & MASK_CONTROL || gFocusMgr.getKeyboardFocus() == NULL)) { + llwarns << "LLviewerWindow::handleKey give floaters first chance at tab key " << llendl; if (gMenuHolder) gMenuHolder->hideMenus(); // if CTRL-tabbing (and not just TAB with no focus), go into window cycle mode @@ -2520,11 +2536,13 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) { mRootView->focusNextRoot(); } + LLViewerEventRecorder::instance().logKeyEvent(key,mask); return TRUE; } // hidden edit menu for cut/copy/paste if (gEditMenu && gEditMenu->handleAcceleratorKey(key, mask)) { + LLViewerEventRecorder::instance().logKeyEvent(key,mask); return TRUE; } @@ -2564,18 +2582,27 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) if (keyboard_focus->handleKey(key, mask, FALSE)) { + + lldebugs << "LLviewerWindow::handleKey - in 'traverse up' - no loops seen... just called keyboard_focus->handleKey an it returned true" << llendl; + LLViewerEventRecorder::instance().logKeyEvent(key,mask); return TRUE; + } else { + lldebugs << "LLviewerWindow::handleKey - in 'traverse up' - no loops seen... just called keyboard_focus->handleKey an it returned FALSE" << llendl; } } if( LLToolMgr::getInstance()->getCurrentTool()->handleKey(key, mask) ) { + lldebugs << "LLviewerWindow::handleKey toolbar handling?" << llendl; + LLViewerEventRecorder::instance().logKeyEvent(key,mask); return TRUE; } // Try for a new-format gesture if (LLGestureMgr::instance().triggerGesture(key, mask)) { + lldebugs << "LLviewerWindow::handleKey new gesture feature" << llendl; + LLViewerEventRecorder::instance().logKeyEvent(key,mask); return TRUE; } @@ -2583,6 +2610,8 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) // don't pass it down to the menus. if (gGestureList.trigger(key, mask)) { + lldebugs << "LLviewerWindow::handleKey check gesture trigger" << llendl; + LLViewerEventRecorder::instance().logKeyEvent(key,mask); return TRUE; } @@ -2631,7 +2660,7 @@ BOOL LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask) // HACK: Numeric keypad on Mac is Unicode 3 // HACK: Control-M on Windows is Unicode 13 if ((uni_char == 13 && mask != MASK_CONTROL) - || (uni_char == 3 && mask == MASK_NONE)) + || (uni_char == 3 && mask == MASK_NONE) ) { if (mask != MASK_ALT) { @@ -2654,14 +2683,7 @@ BOOL LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask) return TRUE; } - //// Topmost view gets a chance before the hierarchy - //LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl(); - //if (top_ctrl && top_ctrl->handleUnicodeChar( uni_char, FALSE ) ) - //{ - // return TRUE; - //} - - return TRUE; + return TRUE; } return FALSE; @@ -2670,8 +2692,6 @@ BOOL LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask) void LLViewerWindow::handleScrollWheel(S32 clicks) { - LLView::sMouseHandlerMessage.clear(); - LLUI::resetMouseIdleTimer(); LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture(); diff --git a/indra/newview/llwindowlistener.cpp b/indra/newview/llwindowlistener.cpp index 28f959eb71..a8e06511d7 100755 --- a/indra/newview/llwindowlistener.cpp +++ b/indra/newview/llwindowlistener.cpp @@ -265,7 +265,9 @@ void LLWindowListener::getPaths(LLSD const & request) void LLWindowListener::keyDown(LLSD const & evt) { Response response(LLSD(), evt); - + KEY key = getKEY(evt); + MASK mask = getMask(evt); + if (evt.has("path")) { std::string path(evt["path"]); @@ -280,8 +282,6 @@ void LLWindowListener::keyDown(LLSD const & evt) response.setResponse(target_view->getInfo()); gFocusMgr.setKeyboardFocus(target_view); - KEY key = getKEY(evt); - MASK mask = getMask(evt); gViewerKeyboard.handleKey(key, mask, false); if(key < 0x80) mWindow->handleUnicodeChar(key, mask); } @@ -294,7 +294,8 @@ void LLWindowListener::keyDown(LLSD const & evt) } else { - mKbGetter()->handleTranslatedKeyDown(getKEY(evt), getMask(evt)); + gViewerKeyboard.handleKey(key, mask, false); + if(key < 0x80) mWindow->handleUnicodeChar(key, mask); } } diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index b01c3067ff..b71faa2d3e 100755 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -2919,6 +2919,34 @@ label="Recorder" name="Recorder" tear_off="true"> + + + + + + + + + + + + + -- cgit v1.3 From efba897e45b5065619bbe0e1451a40b6391e503c Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Mon, 5 Aug 2013 15:38:43 -0400 Subject: correct coding standards problems --- indra/llwindow/llopenglview-objc.h | 2 +- indra/newview/CMakeLists.txt | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llopenglview-objc.h b/indra/llwindow/llopenglview-objc.h index 71149f8561..41837b1eb4 100644 --- a/indra/llwindow/llopenglview-objc.h +++ b/indra/llwindow/llopenglview-objc.h @@ -107,4 +107,4 @@ @end -#endif \ No newline at end of file +#endif diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index df70cd21f1..b81b4a14bd 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1990,9 +1990,9 @@ if (DARWIN) set_target_properties( ${VIEWER_BINARY_NAME} PROPERTIES - OUTPUT_NAME "${product}" - MACOSX_BUNDLE_INFO_PLIST - "${CMAKE_CURRENT_SOURCE_DIR}/Info-SecondLife.plist" + OUTPUT_NAME "${product}" + MACOSX_BUNDLE_INFO_PLIST + "${CMAKE_CURRENT_SOURCE_DIR}/Info-SecondLife.plist" ) configure_file( -- cgit v1.3 From 0142a0c6a9c05db10423b38beab2b2b356e5f85e Mon Sep 17 00:00:00 2001 From: Drake Arconis Date: Wed, 11 Sep 2013 19:02:36 -0400 Subject: OPEN-189 Add missing header guard --- doc/contributions.txt | 1 + indra/llwindow/llwindowmacosx-objc.h | 5 +++++ 2 files changed, 6 insertions(+) (limited to 'indra/llwindow') diff --git a/doc/contributions.txt b/doc/contributions.txt index 0035d4f597..4e3ce70e0b 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -1122,6 +1122,7 @@ Slee Mayo snowy Sidran Sovereign Engineer MAINT-2334 + OPEN-189 SpacedOut Frye VWR-34 VWR-45 diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index 32b3bfb078..3b6295fba8 100755 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -25,6 +25,9 @@ * $/LicenseInfo$ */ +#ifndef LL_LLWINDOWMACOSX_OBJC_H +#define LL_LLWINDOWMACOSX_OBJC_H + #include #include @@ -143,3 +146,5 @@ NSWindowRef getMainAppWindow(); GLViewRef getGLView(); unsigned int getModifiers(); + +#endif // LL_LLWINDOWMACOSX_OBJC_H -- cgit v1.3 From 9b99ece5ab43b6cb28944d1e412f06c6b22dbc2c Mon Sep 17 00:00:00 2001 From: "Graham Madarasz (Graham Linden)" Date: Thu, 12 Sep 2013 13:17:43 -0700 Subject: MAINT-3135 WIP partial fix, addresses graphics corruption on resize, but not mouse mapping issues --- indra/llwindow/llopenglview-objc.h | 1 + indra/llwindow/llopenglview-objc.mm | 12 +++++++++--- indra/newview/pipeline.cpp | 4 +++- 3 files changed, 13 insertions(+), 4 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llopenglview-objc.h b/indra/llwindow/llopenglview-objc.h index 41837b1eb4..1e0e47cd02 100644 --- a/indra/llwindow/llopenglview-objc.h +++ b/indra/llwindow/llopenglview-objc.h @@ -65,6 +65,7 @@ - (unsigned long) getVramSize; - (void) allowMarkedTextInput:(bool)allowed; +- (void) viewDidEndLiveResize; @end diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm index 5f34d03c35..7415c9d8dc 100644 --- a/indra/llwindow/llopenglview-objc.mm +++ b/indra/llwindow/llopenglview-objc.mm @@ -91,6 +91,13 @@ attributedStringInfo getSegments(NSAttributedString *str) @implementation LLOpenGLView +// Force a high quality update after live resizing +- (void) viewDidEndLiveResize +{ + NSSize size = [self frame].size; + callResize(size.width, size.height); +} + - (unsigned long)getVramSize { CGLRendererInfoObj info = 0; @@ -119,9 +126,8 @@ attributedStringInfo getSegments(NSAttributedString *str) - (void)windowResized:(NSNotification *)notification; { - NSSize size = [self frame].size; - - callResize(size.width, size.height); + //NSSize size = [self frame].size; + //callResize(size.width, size.height); } - (void)dealloc diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index f49395da34..be5113680d 100755 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -945,11 +945,13 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) screenFormat = GL_RGBA12; } +#if !LL_DARWIN if (gGLManager.mGLVersion < 4.f && gGLManager.mIsNVIDIA) { screenFormat = GL_RGBA16F_ARB; } - +#endif + if (!mScreen.allocate(resX, resY, screenFormat, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false; if (samples > 0) { -- cgit v1.3 From 33e70236f0226b2e4ebabccfa28cca04ff01211e Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 17 Sep 2013 17:01:52 -0700 Subject: MAINT-3161 : Clean up avatar muting code and prototype feature --- indra/llwindow/lldragdropwin32.h | 2 +- indra/newview/app_settings/settings.xml | 17 +-- indra/newview/llavatarrenderinfoaccountant.cpp | 63 ++++++++-- indra/newview/llavatarrenderinfoaccountant.h | 2 +- indra/newview/llviewermenu.cpp | 18 +-- indra/newview/llviewerregion.cpp | 2 +- indra/newview/llvoavatar.cpp | 136 +++++++++++---------- indra/newview/llvoavatar.h | 2 + .../skins/default/xui/en/menu_attachment_other.xml | 24 ++-- .../skins/default/xui/en/menu_avatar_other.xml | 26 ++-- 10 files changed, 176 insertions(+), 116 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/lldragdropwin32.h b/indra/llwindow/lldragdropwin32.h index 929e7f9e37..a6824f3e90 100755 --- a/indra/llwindow/lldragdropwin32.h +++ b/indra/llwindow/lldragdropwin32.h @@ -57,7 +57,7 @@ class LLDragDropWin32 #include #include -// imposter class that does nothing +// impostor class that does nothing class LLDragDropWin32 { public: diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index eacc7fbec5..31c69f6b3e 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9735,10 +9735,11 @@ Value 1 + RenderAutoMuteByteLimit Comment - Maximum bytes of attachments before an avatar is rendered as a simple imposter (0 for no limit). + Maximum bytes of attachments before an avatar is rendered as a simple impostor (0 for no limit). Persist 1 Type @@ -9746,10 +9747,10 @@ Value 0 - RenderAutoMuteRenderCostLimit + RenderAutoMuteRenderWeightLimit Comment - Maximum render weight before an avatar is rendered as a simple imposter (0 to not use this limit). + Maximum render weight before an avatar is rendered as a simple impostor (0 to not use this limit). Persist 1 Type @@ -9760,7 +9761,7 @@ RenderAutoMuteSurfaceAreaLimit Comment - Maximum surface area of attachments before an avatar is rendered as a simple imposter (0 to not use this limit). + Maximum surface area of attachments before an avatar is rendered as a simple impostor (0 to not use this limit). Persist 1 Type @@ -9768,16 +9769,16 @@ Value 0 - RenderAutoMuteThreshold + RenderAutoMuteFunctions Comment - Threshold on the Avatar Detail slider where simple imposter mode is enabled. (less than 0 is always on, greather than 1 always off) + Developing feature to render some avatars using simple impostors or colored silhouettes. (Set to 7 for all functionality) Persist 1 Type - F32 + U32 Value - 0.25 + 0 RenderAutoMuteLogging diff --git a/indra/newview/llavatarrenderinfoaccountant.cpp b/indra/newview/llavatarrenderinfoaccountant.cpp index 89c1b2a186..e778e0c032 100644 --- a/indra/newview/llavatarrenderinfoaccountant.cpp +++ b/indra/newview/llavatarrenderinfoaccountant.cpp @@ -38,6 +38,7 @@ #include "llhttpclient.h" #include "lltimer.h" #include "llviewercontrol.h" +#include "llviewermenu.h" #include "llviewerobjectlist.h" #include "llviewerregion.h" #include "llvoavatar.h" @@ -92,7 +93,7 @@ public: { if (LLAvatarRenderInfoAccountant::logRenderInfo()) { - llinfos << "Result for avatar weights request for region " << regionp->getName() << ":" << llendl; + llinfos << "LRI: Result for avatar weights request for region " << regionp->getName() << ":" << llendl; } if (content.isMap()) @@ -115,7 +116,7 @@ public: if (LLAvatarRenderInfoAccountant::logRenderInfo()) { - llinfos << " Agent " << target_agent_id + llinfos << "LRI: Agent " << target_agent_id << ": " << agent_info_map << llendl; } @@ -186,7 +187,7 @@ public: { if (LLAvatarRenderInfoAccountant::logRenderInfo()) { - llinfos << "Result for avatar weights POST for region " << regionp->getName() + llinfos << "LRI: Result for avatar weights POST for region " << regionp->getName() << ": " << content << llendl; } @@ -224,7 +225,7 @@ void LLAvatarRenderInfoAccountant::sendRenderInfoToRegion(LLViewerRegion * regio { if (logRenderInfo()) { - llinfos << "Sending avatar render info to region " + llinfos << "LRI: Sending avatar render info to region " << regionp->getName() << " from " << url << llendl; @@ -253,7 +254,7 @@ void LLAvatarRenderInfoAccountant::sendRenderInfoToRegion(LLViewerRegion * regio if (logRenderInfo()) { - llinfos << "Sending avatar render info for " << avatar->getID() + llinfos << "LRI: Sending avatar render info for " << avatar->getID() << ": " << info << llendl; } } @@ -281,7 +282,7 @@ void LLAvatarRenderInfoAccountant::getRenderInfoFromRegion(LLViewerRegion * regi { if (logRenderInfo()) { - llinfos << "Requesting avatar render info for region " + llinfos << "LRI: Requesting avatar render info for region " << regionp->getName() << " from " << url << llendl; @@ -304,6 +305,12 @@ void LLAvatarRenderInfoAccountant::idle() S32 num_avs = LLCharacter::sInstances.size(); + if (logRenderInfo()) + { + llinfos << "LRI: Scanning all regions and checking for render info updates" + << llendl; + } + // Check all regions and see if it's time to fetch/send data for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) @@ -325,6 +332,35 @@ void LLAvatarRenderInfoAccountant::idle() // We scanned all the regions, reset the request timer. sRenderInfoReportTimer.resetWithExpiry(SECS_BETWEEN_REGION_SCANS); } + + static LLCachedControl render_auto_mute_functions(gSavedSettings, "RenderAutoMuteFunctions"); + static U32 prev_render_auto_mute_functions = (U32) -1; + if (prev_render_auto_mute_functions != render_auto_mute_functions) + { + prev_render_auto_mute_functions = render_auto_mute_functions; + + // Adjust menus + BOOL show_items = (BOOL)(render_auto_mute_functions & 0x04); + gMenuAvatarOther->setItemVisible( std::string("Normal"), show_items); + gMenuAvatarOther->setItemVisible( std::string("Always use impostor"), show_items); + gMenuAvatarOther->setItemVisible( std::string("Never use impostor"), show_items); + gMenuAvatarOther->setItemVisible( std::string("Impostor seperator"), show_items); + + gMenuAttachmentOther->setItemVisible( std::string("Normal"), show_items); + gMenuAttachmentOther->setItemVisible( std::string("Always use impostor"), show_items); + gMenuAttachmentOther->setItemVisible( std::string("Never use impostor"), show_items); + gMenuAttachmentOther->setItemVisible( std::string("Impostor seperator"), show_items); + + if (!show_items) + { // Turning off visual muting + for (std::vector::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) + { // Make sure all AVs have the setting cleared + LLVOAvatar* inst = (LLVOAvatar*) *iter; + inst->setCachedVisualMute(false); + } + } + } } @@ -332,14 +368,23 @@ void LLAvatarRenderInfoAccountant::idle() // Make sRenderInfoReportTimer expire so the next call to idle() will scan and query a new region // called via LLViewerRegion::setCapabilitiesReceived() boost signals when the capabilities // are returned for a new LLViewerRegion, and is the earliest time to get render info -void LLAvatarRenderInfoAccountant::expireRenderInfoReportTimer() +void LLAvatarRenderInfoAccountant::expireRenderInfoReportTimer(const LLUUID& region_id) { if (logRenderInfo()) { - llinfos << "Viewer has new region capabilities" << llendl; + llinfos << "LRI: Viewer has new region capabilities, clearing global render info timer" + << " and timer for region " << region_id + << llendl; } - sRenderInfoReportTimer.resetWithExpiry(0.f); + // Reset the global timer so it will scan regions immediately + sRenderInfoReportTimer.reset(); + + LLViewerRegion* regionp = LLWorld::instance().getRegionFromID(region_id); + if (regionp) + { // Reset the region's timer so it will request data immediately + regionp->getRenderInfoRequestTimer().reset(); + } } // static diff --git a/indra/newview/llavatarrenderinfoaccountant.h b/indra/newview/llavatarrenderinfoaccountant.h index 97dd9f0ad3..d68f2dccfb 100644 --- a/indra/newview/llavatarrenderinfoaccountant.h +++ b/indra/newview/llavatarrenderinfoaccountant.h @@ -42,7 +42,7 @@ public: static void sendRenderInfoToRegion(LLViewerRegion * regionp); static void getRenderInfoFromRegion(LLViewerRegion * regionp); - static void expireRenderInfoReportTimer(); + static void expireRenderInfoReportTimer(const LLUUID& region_id); static void idle(); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index c6c1090f45..9468a2d542 100755 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -2930,7 +2930,7 @@ bool enable_object_unmute() // 0 = normal, 1 = always, 2 = never -class LLAvatarCheckImposterMode : public view_listener_t +class LLAvatarCheckImpostorMode : public view_listener_t { bool handleEvent(const LLSD& userdata) { @@ -2956,7 +2956,7 @@ class LLAvatarCheckImposterMode : public view_listener_t }; // 0 = normal, 1 = always, 2 = never -class LLAvatarSetImposterMode : public view_listener_t +class LLAvatarSetImpostorMode : public view_listener_t { bool handleEvent(const LLSD& userdata) { @@ -2971,16 +2971,20 @@ class LLAvatarSetImposterMode : public view_listener_t { case 0: avatar->setVisualMuteSettings(LLVOAvatar::VISUAL_MUTE_NOT_SET); - return true; + break; case 1: avatar->setVisualMuteSettings(LLVOAvatar::ALWAYS_VISUAL_MUTE); - return true; + break; case 2: avatar->setVisualMuteSettings(LLVOAvatar::NEVER_VISUAL_MUTE); - return true; + break; default: return false; } + + avatar->forceUpdateVisualMuteSettings(); + LLVOAvatar::cullAvatarsByPixelArea(); + return true; } // handleEvent() }; @@ -8736,8 +8740,8 @@ void initialize_menus() view_listener_t::addMenu( new LLCheckPanelPeopleTab(), "SideTray.CheckPanelPeopleTab"); // Avatar pie menu - view_listener_t::addMenu(new LLAvatarCheckImposterMode(), "Avatar.CheckImposterMode"); - view_listener_t::addMenu(new LLAvatarSetImposterMode(), "Avatar.SetImposterMode"); + view_listener_t::addMenu(new LLAvatarCheckImpostorMode(), "Avatar.CheckImpostorMode"); + view_listener_t::addMenu(new LLAvatarSetImpostorMode(), "Avatar.SetImpostorMode"); view_listener_t::addMenu(new LLObjectMute(), "Avatar.Mute"); view_listener_t::addMenu(new LLAvatarAddFriend(), "Avatar.AddFriend"); view_listener_t::addMenu(new LLAvatarAddContact(), "Avatar.AddContact"); diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 778c0ee61a..b91dde4113 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -400,7 +400,7 @@ LLViewerRegion::LLViewerRegion(const U64 &handle, mImpl->mObjectPartition.push_back(NULL); //PARTITION_NONE mRenderInfoRequestTimer.resetWithExpiry(0.f); // Set timer to be expired - setCapabilitiesReceivedCallback(boost::bind(&LLAvatarRenderInfoAccountant::expireRenderInfoReportTimer)); + setCapabilitiesReceivedCallback(boost::bind(&LLAvatarRenderInfoAccountant::expireRenderInfoReportTimer, _1)); } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 6a504e10c4..d449efb7e7 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -2987,81 +2987,90 @@ bool LLVOAvatar::isVisuallyMuted() { bool muted = false; - // Priority order (highest priority first) - // * own avatar is never visually muted - // * if on the "always draw normally" list, draw them normally - // * if on the "always visually mute" list, mute them - // * draw them normally if they meet the following criteria: - // - within the closest N avatars OR on friends list OR in an IM chat - // - AND aren't over the thresholds - // * otherwise visually mute all other avatars - if (!isSelf()) { - static LLCachedControl render_mute_threshold(gSavedSettings, "RenderAutoMuteThreshold"); - static LLCachedControl max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit"); - static LLCachedControl max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit"); - static LLCachedControl max_render_cost(gSavedSettings, "RenderAutoMuteRenderCostLimit"); - - if (mVisuallyMuteSetting == ALWAYS_VISUAL_MUTE) - { // Always want to see this AV as an imposter - muted = true; - } - else if (mVisuallyMuteSetting == NEVER_VISUAL_MUTE) - { // Never show as imposter - muted = false; - } - else if (LLVOAvatar::sLODFactor <= render_mute_threshold) + static LLCachedControl render_auto_mute_functions(gSavedSettings, "RenderAutoMuteFunctions"); + if (render_auto_mute_functions) // Hacky debug switch for developing feature { - F64 now = LLFrameTimer::getTotalSeconds(); + // Priority order (highest priority first) + // * own avatar is never visually muted + // * if on the "always draw normally" list, draw them normally + // * if on the "always visually mute" list, mute them + // * draw them normally if they meet the following criteria: + // - within the closest N avatars OR on friends list OR in an IM chat + // - AND aren't over the thresholds + // * otherwise visually mute all other avatars - if (now < mCachedVisualMuteUpdateTime) - { // Use cached mute value - muted = mCachedVisualMute; + static LLCachedControl max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit"); + static LLCachedControl max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit"); + static LLCachedControl max_render_cost(gSavedSettings, "RenderAutoMuteRenderWeightLimit"); + + if (mVisuallyMuteSetting == ALWAYS_VISUAL_MUTE) + { // Always want to see this AV as an impostor + muted = true; } - else - { // Determine if visually muted or not + else if (mVisuallyMuteSetting == NEVER_VISUAL_MUTE) + { // Never show as impostor + muted = false; + } + else + { + F64 now = LLFrameTimer::getTotalSeconds(); - U32 max_cost = (U32) (max_render_cost*(LLVOAvatar::sLODFactor+0.5)); + if (now < mCachedVisualMuteUpdateTime) + { // Use cached mute value + muted = mCachedVisualMute; + } + else + { // Determine if visually muted or not - muted = LLMuteList::getInstance()->isMuted(getID()) || - (mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0) || - (mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f) || - (mVisualComplexity > max_cost && max_render_cost > 0); + U32 max_cost = (U32) (max_render_cost*(LLVOAvatar::sLODFactor+0.5)); - // Could be part of the grand || collection above, but yanked out to make the logic visible - if (!muted) - { - if (sMaxVisible > 0) - { // They are above the visibilty rank - mute them - muted = (mVisibilityRank > sMaxVisible); - } - - /* Not used - always draw friends or those in IMs. Works nicely, needs UI? - if (muted || // Don't mute friends or IMs - sMaxVisible == 0) + muted = LLMuteList::getInstance()->isMuted(getID()) || + (mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0) || + (mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f) || + (mVisualComplexity > max_cost && max_render_cost > 0); + + // Could be part of the grand || collection above, but yanked out to make the logic visible + if (!muted) { - muted = !(LLAvatarTracker::instance().isBuddy(getID())); - if (muted) - { // Not a friend, so they are muted ... are they in an IM? - LLUUID session_id = gIMMgr->computeSessionID(IM_NOTHING_SPECIAL,getID()); - muted = !gIMMgr->hasSession(session_id); + if (sMaxVisible > 0) + { // They are above the visibilty rank - mute them + muted = (mVisibilityRank > sMaxVisible); + } + + // Always draw friends or those in IMs. Needs UI? + if ((render_auto_mute_functions & 0x02) && + (muted || sMaxVisible == 0)) // Don't mute friends or IMs + { + muted = !(LLAvatarTracker::instance().isBuddy(getID())); + if (muted) + { // Not a friend, so they are muted ... are they in an IM? + LLUUID session_id = gIMMgr->computeSessionID(IM_NOTHING_SPECIAL,getID()); + muted = !gIMMgr->hasSession(session_id); + } } } - */ - } - // Save visual mute state and set interval for updating - const F64 SECONDS_BETWEEN_RENDER_AUTO_MUTE_UPDATES = 1.5; - mCachedVisualMuteUpdateTime = now + SECONDS_BETWEEN_RENDER_AUTO_MUTE_UPDATES; - mCachedVisualMute = muted; - } + // Save visual mute state and set interval for updating + const F64 SECONDS_BETWEEN_RENDER_AUTO_MUTE_UPDATES = 1.5; + mCachedVisualMuteUpdateTime = now + SECONDS_BETWEEN_RENDER_AUTO_MUTE_UPDATES; + mCachedVisualMute = muted; + } + } } } return muted; } +void LLVOAvatar::forceUpdateVisualMuteSettings() +{ + // Set the cache time so it's updated ASAP + mCachedVisualMuteUpdateTime = LLFrameTimer::getTotalSeconds() - 1.0; +} + + //------------------------------------------------------------------------ // updateCharacter() // called on both your avatar and other avatars @@ -3806,11 +3815,11 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) { //LOD changed or new mesh created, allocate new vertex buffer if needed if (needs_rebuild || mDirtyMesh >= 2 || mVisibilityRank <= 4) { - updateMeshData(); + updateMeshData(); mDirtyMesh = 0; - mNeedsSkin = TRUE; - mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); - } + mNeedsSkin = TRUE; + mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); + } } if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) <= 0) @@ -7868,8 +7877,7 @@ void LLVOAvatar::getImpostorValues(LLVector4a* extents, LLVector3& angle, F32& d void LLVOAvatar::idleUpdateRenderCost() { - static LLCachedControl max_render_cost(gSavedSettings, "RenderAutoMuteRenderCostLimit"); - + static LLCachedControl max_render_cost(gSavedSettings, "RenderAutoMuteRenderWeightLimit"); static const U32 ARC_LIMIT = 20000; if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_ATTACHMENT_BYTES)) @@ -8033,7 +8041,7 @@ LLColor4 LLVOAvatar::calcMutedAVColor(F32 value, S32 range_low, S32 range_high) LLColor4 new_color = lerp(*spectrum_color[spectrum_index_1], *spectrum_color[spectrum_index_2], fractBetween); new_color.normalize(); - new_color *= 0.9f; + new_color *= 0.7f; // Tone it down a bit //llinfos << "From value " << std::setprecision(3) << value << " returning color " << new_color // << " using indexes " << spectrum_index_1 << ", " << spectrum_index_2 diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 295175133c..931e65b3ea 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -389,6 +389,8 @@ public: public: U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255), S32 diffuse_channel = 0); bool isVisuallyMuted(); + void setCachedVisualMute(bool muted) { mCachedVisualMute = muted; }; + void forceUpdateVisualMuteSettings(); enum VisualMuteSettings { diff --git a/indra/newview/skins/default/xui/en/menu_attachment_other.xml b/indra/newview/skins/default/xui/en/menu_attachment_other.xml index 47fae51fac..ba91b0b5d9 100755 --- a/indra/newview/skins/default/xui/en/menu_attachment_other.xml +++ b/indra/newview/skins/default/xui/en/menu_attachment_other.xml @@ -117,37 +117,37 @@ + label="Normal Rendering"> + name="Always use impostor" + label="Always use impostor"> + name="Never use impostor" + label="Never use impostor"> + layout="topleft" name="Impostor seperator"/> + label="Normal Rendering"> + name="Always use impostor" + label="Always use impostor"> + name="Never use impostor" + label="Never use impostor"> - + Date: Thu, 26 Sep 2013 18:53:12 -0700 Subject: MAINT-3155 add cocoa equiv for former AppleEventManager shenanigans for SLURL handling --- indra/llwindow/llwindowmacosx-objc.h | 1 + indra/llwindow/llwindowmacosx-objc.mm | 2 +- indra/newview/llappdelegate-objc.mm | 13 +++++++++ indra/newview/llappviewermacosx.cpp | 53 ++++++++++++----------------------- 4 files changed, 33 insertions(+), 36 deletions(-) (limited to 'indra/llwindow') diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index 32b3bfb078..2cae6f3f72 100755 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -49,6 +49,7 @@ void handleQuit(); bool runMainLoop(); void initMainLoop(); void cleanupViewer(); +void handleUrl(const char* url); /* Defined in llwindowmacosx-objc.mm: */ int createNSApp(int argc, const char **argv); diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index 0354c2b717..0768d0352e 100755 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -57,7 +57,7 @@ void setupCocoa() [[NSUserDefaults standardUserDefaults] setObject:@"NO" forKey:@"NSTreatUnknownArgumentsAsOpen"]; [pool release]; - + inited = true; } } diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index 30476b3d22..91251ed7c0 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -54,6 +54,19 @@ } [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(languageUpdated) name:@"NSTextInputContextKeyboardSelectionDidChangeNotification" object:nil]; + + [[NSAppleEventManager sharedAppleEventManager] setEventHandler:self andSelector:@selector(handleGetURLEvent:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL]; +} + +- (void) handleGetURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent { + NSString *url= nil; + url = [[[[NSAppleEventManager sharedAppleEventManager]// 1 + currentAppleEvent]// 2 + paramDescriptorForKeyword:keyDirectObject]// 3 + stringValue];// 4 + + const char* url_utf8 = [url UTF8String]; + handleUrl(url_utf8); } - (void) applicationDidBecomeActive:(NSNotification *)notification diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index 316c90d9d2..2723f0b90d 100755 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -483,41 +483,24 @@ bool LLAppViewerMacOSX::getMasterSystemAudioMute() return (mute != 0); } -OSErr AEGURLHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn) +void handleUrl(const char* url_utf8) { - OSErr result = noErr; - DescType actualType; - char buffer[1024]; // Flawfinder: ignore - Size size; - - result = AEGetParamPtr ( - messagein, - keyDirectObject, - typeCString, - &actualType, - (Ptr)buffer, - sizeof(buffer), - &size); - - if(result == noErr) - { - std::string url = buffer; + if (url_utf8) + { + std::string url = url_utf8; + // Safari 3.2 silently mangles secondlife:///app/ URLs into + // secondlife:/app/ (only one leading slash). + // Fix them up to meet the URL specification. JC + const std::string prefix = "secondlife:/app/"; + std::string test_prefix = url.substr(0, prefix.length()); + LLStringUtil::toLower(test_prefix); + if (test_prefix == prefix) + { + url.replace(0, prefix.length(), "secondlife:///app/"); + } - // Safari 3.2 silently mangles secondlife:///app/ URLs into - // secondlife:/app/ (only one leading slash). - // Fix them up to meet the URL specification. JC - const std::string prefix = "secondlife:/app/"; - std::string test_prefix = url.substr(0, prefix.length()); - LLStringUtil::toLower(test_prefix); - if (test_prefix == prefix) - { - url.replace(0, prefix.length(), "secondlife:///app/"); - } - - LLMediaCtrl* web = NULL; - const bool trusted_browser = false; - LLURLDispatcher::dispatch(url, "", web, trusted_browser); - } - - return(result); + LLMediaCtrl* web = NULL; + const bool trusted_browser = false; + LLURLDispatcher::dispatch(url, "", web, trusted_browser); + } } -- cgit v1.3