summaryrefslogtreecommitdiff
path: root/indra/llwindow
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llwindow')
-rw-r--r--indra/llwindow/CMakeLists.txt3
-rw-r--r--indra/llwindow/lldxhardware.cpp4
-rw-r--r--indra/llwindow/llopenglview-objc.h22
-rw-r--r--indra/llwindow/llopenglview-objc.mm540
-rw-r--r--indra/llwindow/llwindow.cpp27
-rw-r--r--indra/llwindow/llwindow.h5
-rw-r--r--indra/llwindow/llwindowcallbacks.cpp8
-rw-r--r--indra/llwindow/llwindowcallbacks.h3
-rw-r--r--indra/llwindow/llwindowheadless.h3
-rw-r--r--indra/llwindow/llwindowmacosx-objc.h7
-rw-r--r--indra/llwindow/llwindowmacosx-objc.mm283
-rw-r--r--indra/llwindow/llwindowmacosx.cpp35
-rw-r--r--indra/llwindow/llwindowmacosx.h4
-rw-r--r--indra/llwindow/llwindowsdl.cpp9
-rw-r--r--indra/llwindow/llwindowsdl.h4
-rw-r--r--indra/llwindow/llwindowwin32.cpp419
-rw-r--r--indra/llwindow/llwindowwin32.h11
17 files changed, 773 insertions, 614 deletions
diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt
index 6debd54665..69f11991ea 100644
--- a/indra/llwindow/CMakeLists.txt
+++ b/indra/llwindow/CMakeLists.txt
@@ -108,7 +108,7 @@ if (DARWIN)
llkeyboardmacosx.cpp
llwindowmacosx.cpp
PROPERTIES
- COMPILE_FLAGS "-Wno-deprecated-declarations -fpascal-strings"
+ COMPILE_FLAGS "-fpascal-strings"
)
endif (DARWIN)
@@ -183,7 +183,6 @@ endif (SDL_FOUND)
target_include_directories(llwindow INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
if (DARWIN)
- find_library(CARBON_LIBRARY Carbon)
target_link_libraries(llwindow ${CARBON_LIBRARY})
endif (DARWIN)
diff --git a/indra/llwindow/lldxhardware.cpp b/indra/llwindow/lldxhardware.cpp
index 387982dfc2..ff85b2cb14 100644
--- a/indra/llwindow/lldxhardware.cpp
+++ b/indra/llwindow/lldxhardware.cpp
@@ -312,7 +312,7 @@ std::string get_string(IDxDiagContainer *containerp, const WCHAR *wszPropName)
WCHAR wszPropValue[256];
get_wstring(containerp, wszPropName, wszPropValue, 256);
- return utf16str_to_utf8str(wszPropValue);
+ return ll_convert<std::string>(std::wstring(wszPropValue));
}
LLDXHardware::LLDXHardware()
@@ -440,7 +440,7 @@ LLSD LLDXHardware::getDisplayInfo()
// print the value
// windows doesn't guarantee to be null terminated
release_version[RV_SIZE - 1] = NULL;
- ret["DriverVersion"] = utf16str_to_utf8str(release_version);
+ ret["DriverVersion"] = ll_convert<std::string>(std::wstring(release_version));
}
RegCloseKey(hKey);
diff --git a/indra/llwindow/llopenglview-objc.h b/indra/llwindow/llopenglview-objc.h
index 97f4125484..a2c55a2dd9 100644
--- a/indra/llwindow/llopenglview-objc.h
+++ b/indra/llwindow/llopenglview-objc.h
@@ -42,7 +42,11 @@
unsigned int mMarkedTextLength;
bool mMarkedTextAllowed;
bool mSimulatedRightClick;
- bool mOldResize;
+
+ NSOpenGLPixelFormat *pixelFormat;
+ NSOpenGLContext *glContext;
+
+ bool mHDRDisplay;
}
- (id) initWithSamples:(NSUInteger)samples;
- (id) initWithSamples:(NSUInteger)samples andVsync:(BOOL)vsync;
@@ -50,8 +54,6 @@
- (void)commitCurrentPreedit;
-- (void) setOldResize:(bool)oldresize;
-
// 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.
@@ -68,7 +70,6 @@
- (unsigned long) getVramSize;
- (void) allowMarkedTextInput:(bool)allowed;
-- (void) viewDidEndLiveResize;
@end
@@ -88,9 +89,6 @@
@interface LLNSWindow : NSWindow
-- (NSPoint)convertToScreenFromLocalPoint:(NSPoint)point relativeToView:(NSView *)view;
-- (NSPoint)flipPoint:(NSPoint)aPoint;
-
@end
@interface NSScreen (PointConversion)
@@ -100,16 +98,6 @@
*/
+ (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
#endif
diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm
index 6177eb4873..bdb5d8def0 100644
--- a/indra/llwindow/llopenglview-objc.mm
+++ b/indra/llwindow/llopenglview-objc.mm
@@ -28,7 +28,10 @@
#import "llwindowmacosx-objc.h"
#import "llappdelegate-objc.h"
+#import <Carbon/Carbon.h>
+
extern BOOL gHiDPISupport;
+extern BOOL gHDRDisplaySupport;
#pragma mark local functions
@@ -105,38 +108,24 @@ attributedStringInfo getSegments(NSAttributedString *str)
return screen;
}
+@end
-- (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);
-}
+@implementation LLOpenGLView
-- (NSPoint)flipPoint:(NSPoint)aPoint
+- (NSOpenGLContext*) glContext
{
- return NSMakePoint(aPoint.x, self.frame.size.height - aPoint.y);
+ return glContext;
}
-@end
-
-@implementation LLOpenGLView
-
-// Force a high quality update after live resizing
-- (void) viewDidEndLiveResize
+- (NSOpenGLPixelFormat*) pixelFormat
{
- if (mOldResize) //Maint-3135
- {
- NSSize size = [self frame].size;
- callResize(size.width, size.height);
- }
+ return pixelFormat;
}
- (unsigned long)getVramSize
{
CGLRendererInfoObj info = 0;
- GLint vram_megabytes = 0;
+ GLint vram_megabytes = 0;
int num_renderers = 0;
CGLError the_err = CGLQueryRendererInfo (CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay), &info, &num_renderers);
if(0 == the_err)
@@ -154,29 +143,45 @@ attributedStringInfo getSegments(NSAttributedString *str)
vram_megabytes = 256;
}
- return (unsigned long)vram_megabytes; // return value is in megabytes.
+ return (unsigned long)vram_megabytes; // return value is in megabytes.
+}
+
+- (void)viewWillMoveToWindow:(nullable NSWindow *)newWindow
+{
+ if(mHDRDisplay)
+ {
+ self.wantsExtendedDynamicRangeOpenGLSurface = YES;
+ NSLog(@"Wants Extended Dynamic Range OpenGL", nil);
+ }
+ /*
+ else
+ {
+ self.wantsExtendedDynamicRangeOpenGLSurface = NO;
+ NSLog(@"Wants Standard Color Range OpenGL", nil);
+ }
+ */
}
- (void)viewDidMoveToWindow
{
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(windowResized:) name:NSWindowDidResizeNotification
- object:[self window]];
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(windowResized:) name:NSWindowDidResizeNotification
+ object:[self window]];
[[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(windowWillMiniaturize:) name:NSWindowWillMiniaturizeNotification
- object:[self window]];
+ selector:@selector(windowWillMiniaturize:) name:NSWindowWillMiniaturizeNotification
+ object:[self window]];
[[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(windowDidDeminiaturize:) name:NSWindowDidDeminiaturizeNotification
- object:[self window]];
+ selector:@selector(windowDidDeminiaturize:) name:NSWindowDidDeminiaturizeNotification
+ object:[self window]];
[[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(windowDidBecomeKey:) name:NSWindowDidBecomeKeyNotification
- object:[self window]];
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(windowDidChangeScreen:) name:NSWindowDidChangeScreenNotification
- object:[self window]];
+ selector:@selector(windowDidBecomeKey:) name:NSWindowDidBecomeKeyNotification
+ object:[self window]];
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(windowDidChangeScreen:) name:NSWindowDidChangeScreenNotification
+ object:[self window]];
NSRect wnd_rect = [[self window] frame];
@@ -187,18 +192,10 @@ attributedStringInfo getSegments(NSAttributedString *str)
}
}
-- (void)setOldResize:(bool)oldresize
-{
- mOldResize = oldresize;
-}
-
- (void)windowResized:(NSNotification *)notification;
{
- if (!mOldResize) //Maint-3288
- {
- NSSize dev_sz = gHiDPISupport ? [self convertSizeToBacking:[self frame].size] : [self frame].size;
- callResize(dev_sz.width, dev_sz.height);
- }
+ NSSize dev_sz = [self convertSizeToBacking:[self frame].size];
+ callResize(dev_sz.width, dev_sz.height);
}
- (void)windowWillMiniaturize:(NSNotification *)notification;
@@ -218,131 +215,183 @@ attributedStringInfo getSegments(NSAttributedString *str)
-(void)windowDidChangeScreen:(NSNotification *)notification;
{
- callWindowDidChangeScreen();
+ callWindowDidChangeScreen();
}
- (void)dealloc
{
- [[NSNotificationCenter defaultCenter] removeObserver:self];
- [super dealloc];
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+ [super dealloc];
}
- (id) init
{
- return [self initWithFrame:[self bounds] withSamples:2 andVsync:TRUE];
+ return [self initWithFrame:[self bounds] withSamples:2 andVsync:TRUE];
}
- (id) initWithSamples:(NSUInteger)samples
{
- return [self initWithFrame:[self bounds] withSamples:samples andVsync:TRUE];
+ 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];
+ return [self initWithFrame:[self bounds] withSamples:samples andVsync:vsync];
}
+#if LL_DARWIN
+// For setView and opengl deprecation
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
- (id) initWithFrame:(NSRect)frame withSamples:(NSUInteger)samples andVsync:(BOOL)vsync
{
- [self registerForDraggedTypes:[NSArray arrayWithObject:NSURLPboardType]];
- [self initWithFrame:frame];
+ [self registerForDraggedTypes:[NSArray arrayWithObject:NSPasteboardTypeURL]];
+ [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 SDRAttrs[] = {
+ NSOpenGLPFANoRecovery,
+ NSOpenGLPFADoubleBuffer,
+ NSOpenGLPFAClosestPolicy,
+ NSOpenGLPFAAccelerated,
+ NSOpenGLPFADepthSize, 24,
+ NSOpenGLPFAColorSize, 32,
+ NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core,
+ 0
+ };
- // 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[] = {
+ NSOpenGLPixelFormatAttribute HDRAttrs[] = {
NSOpenGLPFANoRecovery,
- NSOpenGLPFADoubleBuffer,
- NSOpenGLPFAClosestPolicy,
- NSOpenGLPFAAccelerated,
- NSOpenGLPFASampleBuffers, 0,
- NSOpenGLPFASamples, 0,
- NSOpenGLPFAStencilSize, 8,
- NSOpenGLPFADepthSize, 24,
- NSOpenGLPFAAlphaSize, 8,
- NSOpenGLPFAColorSize, 24,
- NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core,
- 0
+ NSOpenGLPFADoubleBuffer,
+ NSOpenGLPFAClosestPolicy,
+ NSOpenGLPFAAccelerated,
+ NSOpenGLPFAColorFloat,
+ NSOpenGLPFAColorSize, 64,
+ NSOpenGLPFADepthSize, 24,
+ NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core,
+ 0
};
- NSOpenGLPixelFormat *pixelFormat = [[[NSOpenGLPixelFormat alloc] initWithAttributes:attrs] autorelease];
+ mHDRDisplay = NO;
+
+ if(gHDRDisplaySupport)
+ {
+ pixelFormat = [[[NSOpenGLPixelFormat alloc] initWithAttributes:HDRAttrs] autorelease];
+ if (pixelFormat == nil)
+ {
+ NSLog(@"Failed to create pixel format for HDR Display!", nil);
+ pixelFormat = [[[NSOpenGLPixelFormat alloc] initWithAttributes:SDRAttrs] autorelease];
+ }
+ else
+ {
+ NSLog(@"pixel format created successfully for HDR Display", nil);
+ mHDRDisplay = YES;
+ }
+ }
+ else
+ {
+ pixelFormat = [[[NSOpenGLPixelFormat alloc] initWithAttributes:SDRAttrs] autorelease];
+ }
+
+ if (pixelFormat == nil)
+ {
+ NSLog(@"Failed to create pixel format!", nil);
+ return nil;
+ }
+
+ glContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil];
+
+ if (glContext == nil)
+ {
+ NSLog(@"Failed to create OpenGL context!", nil);
+ return nil;
+ }
- if (pixelFormat == nil)
- {
- NSLog(@"Failed to create pixel format!", nil);
- return nil;
- }
+ [self setPixelFormat:pixelFormat];
- NSOpenGLContext *glContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil];
+ if(mHDRDisplay)
+ {
+ CGColorSpaceRef color_space = [self.window.colorSpace CGColorSpace];
+ CGColorSpaceRef color_space_extended = CGColorSpaceCreateExtended(color_space);
+ NSColorSpace* extended_ns_color_space
+ = [[NSColorSpace alloc] initWithCGColorSpace:color_space_extended];
- if (glContext == nil)
- {
- NSLog(@"Failed to create OpenGL context!", nil);
- return nil;
- }
+ self.window.colorSpace = extended_ns_color_space;
+ CGColorSpaceRelease(color_space_extended);
- [self setPixelFormat:pixelFormat];
+ NSLog(@"Extended color space applied for HDR Display", nil);
+ }
- //for retina support
- [self setWantsBestResolutionOpenGLSurface:gHiDPISupport];
+ //for retina support
+ [self setWantsBestResolutionOpenGLSurface:gHiDPISupport];
- [self setOpenGLContext:glContext];
+ [self setOpenGLContext:glContext];
- [glContext setView:self];
+ [glContext setView:self];
- [glContext makeCurrentContext];
+ [glContext makeCurrentContext];
- if (vsync)
- {
- GLint value = 1;
- [glContext setValues:&value forParameter:NSOpenGLCPSwapInterval];
- } else {
- // supress this error after move to Xcode 7:
- // error: null passed to a callee that requires a non-null argument [-Werror,-Wnonnull]
- // Tried using ObjC 'nonnull' keyword as per SO article but didn't build
- GLint swapInterval=0;
- [glContext setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];
- }
+ if (vsync)
+ {
+ GLint value = 1;
+ [glContext setValues:&value forParameter:NSOpenGLContextParameterSwapInterval];
+ } else {
+ // supress this error after move to Xcode 7:
+ // error: null passed to a callee that requires a non-null argument [-Werror,-Wnonnull]
+ // Tried using ObjC 'nonnull' keyword as per SO article but didn't build
+ GLint swapInterval=0;
+ [glContext setValues:&swapInterval forParameter:NSOpenGLContextParameterSwapInterval];
+ }
- mOldResize = false;
+ GLint opacity = 1;
+ [glContext setValues:&opacity forParameter:NSOpenGLCPSurfaceOpacity];
- return self;
+ return self;
}
- (BOOL) rebuildContext
{
- return [self rebuildContextWithFormat:[self pixelFormat]];
+ return [self rebuildContextWithFormat:[self pixelFormat]];
}
- (BOOL) rebuildContextWithFormat:(NSOpenGLPixelFormat *)format
{
- NSOpenGLContext *ctx = [self openGLContext];
+ NSOpenGLContext *ctx = [self openGLContext];
- [ctx clearDrawable];
- [ctx initWithFormat:format shareContext:nil];
+ [ctx clearDrawable];
+ [ctx initWithFormat:format shareContext:nil];
- if (ctx == nil)
- {
- NSLog(@"Failed to create OpenGL context!", nil);
- return false;
- }
+ if (ctx == nil)
+ {
+ NSLog(@"Failed to create OpenGL context!", nil);
+ return false;
+ }
- [self setOpenGLContext:ctx];
- [ctx setView:self];
- [ctx makeCurrentContext];
- return true;
+ [self setOpenGLContext:ctx];
+ [ctx setView:self];
+ [ctx makeCurrentContext];
+ return true;
}
+#if LL_DARWIN
+#pragma clang diagnostic pop
+#endif
+
- (CGLContextObj)getCGLContextObj
{
- NSOpenGLContext *ctx = [self openGLContext];
- return (CGLContextObj)[ctx CGLContextObj];
+ NSOpenGLContext *ctx = [self openGLContext];
+ return (CGLContextObj)[ctx CGLContextObj];
}
- (CGLPixelFormatObj*)getCGLPixelFormatObj
{
- NSOpenGLPixelFormat *fmt = [self pixelFormat];
- return (CGLPixelFormatObj*)[fmt CGLPixelFormatObj];
+ NSOpenGLPixelFormat *fmt = [self pixelFormat];
+ return (CGLPixelFormatObj*)[fmt CGLPixelFormatObj];
}
// Various events can be intercepted by our view, thus not reaching our window.
@@ -350,18 +399,14 @@ attributedStringInfo getSegments(NSAttributedString *str)
- (void) mouseDown:(NSEvent *)theEvent
{
- NSPoint mPoint = gHiDPISupport ? [self convertPointToBacking:[theEvent locationInWindow]] : [theEvent locationInWindow];
- mMousePos[0] = mPoint.x;
- mMousePos[1] = mPoint.y;
-
// Apparently people still use this?
- if ([theEvent modifierFlags] & NSCommandKeyMask &&
- !([theEvent modifierFlags] & NSControlKeyMask) &&
- !([theEvent modifierFlags] & NSShiftKeyMask) &&
- !([theEvent modifierFlags] & NSAlternateKeyMask) &&
- !([theEvent modifierFlags] & NSAlphaShiftKeyMask) &&
- !([theEvent modifierFlags] & NSFunctionKeyMask) &&
- !([theEvent modifierFlags] & NSHelpKeyMask))
+ if ([theEvent modifierFlags] & NSEventModifierFlagCommand &&
+ !([theEvent modifierFlags] & NSEventModifierFlagControl) &&
+ !([theEvent modifierFlags] & NSEventModifierFlagShift) &&
+ !([theEvent modifierFlags] & NSEventModifierFlagOption) &&
+ !([theEvent modifierFlags] & NSEventModifierFlagCapsLock) &&
+ !([theEvent modifierFlags] & NSEventModifierFlagFunction) &&
+ !([theEvent modifierFlags] & NSEventModifierFlagHelp))
{
callRightMouseDown(mMousePos, [theEvent modifierFlags]);
mSimulatedRightClick = true;
@@ -382,7 +427,7 @@ attributedStringInfo getSegments(NSAttributedString *str)
callRightMouseUp(mMousePos, [theEvent modifierFlags]);
mSimulatedRightClick = false;
} else {
- NSPoint mPoint = gHiDPISupport ? [self convertPointToBacking:[theEvent locationInWindow]] : [theEvent locationInWindow];
+ NSPoint mPoint = [self convertPointToBacking:[theEvent locationInWindow]];
mMousePos[0] = mPoint.x;
mMousePos[1] = mPoint.y;
callLeftMouseUp(mMousePos, [theEvent modifierFlags]);
@@ -391,35 +436,29 @@ attributedStringInfo getSegments(NSAttributedString *str)
- (void) rightMouseDown:(NSEvent *)theEvent
{
- NSPoint mPoint = gHiDPISupport ? [self convertPointToBacking:[theEvent locationInWindow]] : [theEvent locationInWindow];
- mMousePos[0] = mPoint.x;
- mMousePos[1] = mPoint.y;
- callRightMouseDown(mMousePos, [theEvent modifierFlags]);
+ callRightMouseDown(mMousePos, [theEvent modifierFlags]);
}
- (void) rightMouseUp:(NSEvent *)theEvent
{
- NSPoint mPoint = gHiDPISupport ? [self convertPointToBacking:[theEvent locationInWindow]] : [theEvent locationInWindow];
- mMousePos[0] = mPoint.x;
- mMousePos[1] = mPoint.y;
- callRightMouseUp(mMousePos, [theEvent modifierFlags]);
+ callRightMouseUp(mMousePos, [theEvent modifierFlags]);
}
- (void)mouseMoved:(NSEvent *)theEvent
{
- NSPoint dev_delta = gHiDPISupport ? [self convertPointToBacking:NSMakePoint([theEvent deltaX], [theEvent deltaY])] : NSMakePoint([theEvent deltaX], [theEvent deltaY]);
+ NSPoint dev_delta = [self convertPointToBacking:NSMakePoint([theEvent deltaX], [theEvent deltaY])];
- float mouseDeltas[] = {
- float(dev_delta.x),
- float(dev_delta.y)
- };
+ float mouseDeltas[] = {
+ float(dev_delta.x),
+ float(dev_delta.y)
+ };
- callDeltaUpdate(mouseDeltas, 0);
+ callDeltaUpdate(mouseDeltas, 0);
- NSPoint mPoint = gHiDPISupport ? [self convertPointToBacking:[theEvent locationInWindow]] : [theEvent locationInWindow];
- mMousePos[0] = mPoint.x;
- mMousePos[1] = mPoint.y;
- callMouseMoved(mMousePos, 0);
+ NSPoint mPoint = [self convertPointToBacking:[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.
@@ -427,66 +466,60 @@ attributedStringInfo getSegments(NSAttributedString *str)
- (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.
+ // 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.
- NSPoint dev_delta = gHiDPISupport ? [self convertPointToBacking:NSMakePoint([theEvent deltaX], [theEvent deltaY])] : NSMakePoint([theEvent deltaX], [theEvent deltaY]);
+ NSPoint dev_delta = [self convertPointToBacking:NSMakePoint([theEvent deltaX], [theEvent deltaY])];
- float mouseDeltas[] = {
- float(dev_delta.x),
- float(dev_delta.y)
- };
+ float mouseDeltas[] = {
+ float(dev_delta.x),
+ float(dev_delta.y)
+ };
- callDeltaUpdate(mouseDeltas, 0);
+ callDeltaUpdate(mouseDeltas, 0);
- NSPoint mPoint = gHiDPISupport ? [self convertPointToBacking:[theEvent locationInWindow]] : [theEvent locationInWindow];
- mMousePos[0] = mPoint.x;
- mMousePos[1] = mPoint.y;
- callMouseDragged(mMousePos, 0);
+ NSPoint mPoint = [self convertPointToBacking:[theEvent locationInWindow]];
+ mMousePos[0] = mPoint.x;
+ mMousePos[1] = mPoint.y;
+ callMouseDragged(mMousePos, 0);
}
- (void) otherMouseDown:(NSEvent *)theEvent
{
- NSPoint mPoint = gHiDPISupport ? [self convertPointToBacking:[theEvent locationInWindow]] : [theEvent locationInWindow];
- mMousePos[0] = mPoint.x;
- mMousePos[1] = mPoint.y;
callOtherMouseDown(mMousePos, [theEvent modifierFlags], [theEvent buttonNumber]);
}
- (void) otherMouseUp:(NSEvent *)theEvent
{
- NSPoint mPoint = gHiDPISupport ? [self convertPointToBacking:[theEvent locationInWindow]] : [theEvent locationInWindow];
- mMousePos[0] = mPoint.x;
- mMousePos[1] = mPoint.y;
callOtherMouseUp(mMousePos, [theEvent modifierFlags], [theEvent buttonNumber]);
}
- (void) rightMouseDragged:(NSEvent *)theEvent
{
- [self mouseDragged:theEvent];
+ [self mouseDragged:theEvent];
}
- (void) otherMouseDragged:(NSEvent *)theEvent
{
- [self mouseDragged:theEvent];
+ [self mouseDragged:theEvent];
}
- (void) scrollWheel:(NSEvent *)theEvent
{
- callScrollMoved(-[theEvent deltaX], -[theEvent deltaY]);
+ callScrollMoved(-[theEvent deltaX], -[theEvent deltaY]);
}
- (void) mouseExited:(NSEvent *)theEvent
{
- callMouseExit();
+ callMouseExit();
}
- (void) keyUp:(NSEvent *)theEvent
{
NativeKeyEventData eventData = extractKeyDataFromKeyEvent(theEvent);
eventData.mKeyEvent = NativeKeyEventData::KEYUP;
- callKeyUp(&eventData, [theEvent keyCode], [theEvent modifierFlags]);
+ callKeyUp(&eventData, [theEvent keyCode], [theEvent modifierFlags]);
}
- (void) keyDown:(NSEvent *)theEvent
@@ -500,7 +533,7 @@ attributedStringInfo getSegments(NSAttributedString *str)
// Because flagsChange event handler misses event when other window is activated,
// e.g. OS Window for upload something or Input Window...
// mModifiers instance variable is for insertText: or insertText:replacementRange: (by Pell Smit)
- mModifiers = [theEvent modifierFlags];
+ mModifiers = [theEvent modifierFlags];
NSString *str_no_modifiers = [theEvent charactersIgnoringModifiers];
unichar ch = 0;
if (str_no_modifiers.length)
@@ -511,7 +544,7 @@ attributedStringInfo getSegments(NSAttributedString *str)
if (acceptsText &&
!mMarkedTextAllowed &&
- !(mModifiers & (NSControlKeyMask | NSCommandKeyMask)) && // commands don't invoke InputWindow
+ !(mModifiers & (NSEventModifierFlagControl | NSEventModifierFlagCommand)) && // commands don't invoke InputWindow
![(LLAppDelegate*)[NSApp delegate] romanScript] &&
ch > ' ' &&
ch != NSDeleteCharacter &&
@@ -528,20 +561,20 @@ attributedStringInfo getSegments(NSAttributedString *str)
{
NativeKeyEventData eventData = extractKeyDataFromModifierEvent(theEvent);
- mModifiers = [theEvent modifierFlags];
- callModifier([theEvent modifierFlags]);
+ mModifiers = [theEvent modifierFlags];
+ callModifier([theEvent modifierFlags]);
NSInteger mask = 0;
switch([theEvent keyCode])
{
- case 56:
- mask = NSShiftKeyMask;
+ case kVK_Shift:
+ mask = NSEventModifierFlagShift;
break;
- case 58:
- mask = NSAlternateKeyMask;
+ case kVK_Option:
+ mask = NSEventModifierFlagOption;
break;
- case 59:
- mask = NSControlKeyMask;
+ case kVK_Control:
+ mask = NSEventModifierFlagControl;
break;
default:
return;
@@ -570,69 +603,69 @@ attributedStringInfo getSegments(NSAttributedString *str)
- (BOOL) acceptsFirstResponder
{
- return YES;
+ return YES;
}
- (NSDragOperation) draggingEntered:(id<NSDraggingInfo>)sender
{
- NSPasteboard *pboard;
+ NSPasteboard *pboard;
NSDragOperation sourceDragMask;
- sourceDragMask = [sender draggingSourceOperationMask];
+ sourceDragMask = [sender draggingSourceOperationMask];
- pboard = [sender draggingPasteboard];
+ 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];
+ if ([[pboard types] containsObject:NSPasteboardTypeURL])
+ {
+ if (sourceDragMask & NSDragOperationLink) {
+ NSURL *fileUrl = [[pboard readObjectsForClasses:[NSArray arrayWithObject:[NSURL class]] options:[NSDictionary dictionary]] objectAtIndex:0];
+ mLastDraggedUrl = [[fileUrl absoluteString] UTF8String];
return NSDragOperationLink;
}
- }
- return NSDragOperationNone;
+ }
+ return NSDragOperationNone;
}
- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
{
- callHandleDragUpdated(mLastDraggedUrl);
+ callHandleDragUpdated(mLastDraggedUrl);
- return NSDragOperationLink;
+ return NSDragOperationLink;
}
- (void) draggingExited:(id<NSDraggingInfo>)sender
{
- callHandleDragExited(mLastDraggedUrl);
+ callHandleDragExited(mLastDraggedUrl);
}
- (BOOL)prepareForDragOperation:(id < NSDraggingInfo >)sender
{
- return YES;
+ return YES;
}
- (BOOL) performDragOperation:(id<NSDraggingInfo>)sender
{
- callHandleDragDropped(mLastDraggedUrl);
- return true;
+ callHandleDragDropped(mLastDraggedUrl);
+ return true;
}
- (BOOL)hasMarkedText
{
- return mHasMarkedText;
+ return mHasMarkedText;
}
- (NSRange)markedRange
{
- int range[2];
- getPreeditMarkedRange(&range[0], &range[1]);
- return NSMakeRange(range[0], range[1]);
+ int range[2];
+ getPreeditMarkedRange(&range[0], &range[1]);
+ return NSMakeRange(range[0], range[1]);
}
- (NSRange)selectedRange
{
- int range[2];
- getPreeditSelectionRange(&range[0], &range[1]);
- return NSMakeRange(range[0], range[1]);
+ int range[2];
+ getPreeditSelectionRange(&range[0], &range[1]);
+ return NSMakeRange(range[0], range[1]);
}
- (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange
@@ -657,7 +690,7 @@ attributedStringInfo getSegments(NSAttributedString *str)
};
int string_length = [aString length];
- unichar text[string_length];
+ unichar *text = new unichar[string_length];
attributedStringInfo segments;
// I used 'respondsToSelector:@selector(string)'
// to judge aString is an attributed string or not.
@@ -685,6 +718,8 @@ attributedStringInfo getSegments(NSAttributedString *str)
// we must clear the marked text when aString is null.
[self unmarkText];
}
+
+ delete [] text;
} else {
if (mHasMarkedText)
{
@@ -693,6 +728,12 @@ attributedStringInfo getSegments(NSAttributedString *str)
}
}
+#if LL_DARWIN
+// For commitEditing deprecation
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
- (void)commitCurrentPreedit
{
if (mHasMarkedText)
@@ -704,23 +745,27 @@ attributedStringInfo getSegments(NSAttributedString *str)
}
}
+#if LL_DARWIN
+#pragma clang diagnostic pop
+#endif
+
- (void)unmarkText
{
- [[self inputContext] discardMarkedText];
- resetPreedit();
- mHasMarkedText = FALSE;
+ [[self inputContext] discardMarkedText];
+ resetPreedit();
+ mHasMarkedText = FALSE;
}
// We don't support attributed strings.
- (NSArray *)validAttributesForMarkedText
{
- return [NSArray array];
+ return [NSArray array];
}
// See above.
- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange
{
- return nil;
+ return nil;
}
- (void)insertText:(id)insertString
@@ -733,9 +778,9 @@ attributedStringInfo getSegments(NSAttributedString *str)
- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange
{
- // SL-19801 Special workaround for system emoji picker
- if ([aString length] == 2)
- {
+ // SL-19801 Special workaround for system emoji picker
+ if ([aString length] == 2)
+ {
@try
{
uint32_t b0 = [aString characterAtIndex:0];
@@ -753,7 +798,7 @@ attributedStringInfo getSegments(NSAttributedString *str)
NSLog(@"Encountered an unsupported attributed character. Exception: %@ String: %@", e.name, aString);
return;
}
- }
+ }
@try
{
@@ -783,39 +828,39 @@ attributedStringInfo getSegments(NSAttributedString *str)
- (void) insertNewline:(id)sender
{
- if (!(mModifiers & NSCommandKeyMask) &&
- !(mModifiers & NSShiftKeyMask) &&
- !(mModifiers & NSAlternateKeyMask))
- {
- callUnicodeCallback(13, 0);
- } else {
- callUnicodeCallback(13, mModifiers);
- }
+ if (!(mModifiers & NSEventModifierFlagCommand) &&
+ !(mModifiers & NSEventModifierFlagShift) &&
+ !(mModifiers & NSEventModifierFlagOption))
+ {
+ callUnicodeCallback(13, 0);
+ } else {
+ callUnicodeCallback(13, mModifiers);
+ }
}
- (NSUInteger)characterIndexForPoint:(NSPoint)aPoint
{
- return NSNotFound;
+ return NSNotFound;
}
- (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange
{
- float pos[4] = {0, 0, 0, 0};
- getPreeditLocation(pos, mMarkedTextLength);
- return NSMakeRect(pos[0], pos[1], pos[2], pos[3]);
+ float pos[4] = {0, 0, 0, 0};
+ getPreeditLocation(pos, mMarkedTextLength);
+ return NSMakeRect(pos[0], pos[1], pos[2], pos[3]);
}
- (void)doCommandBySelector:(SEL)aSelector
{
- if (aSelector == @selector(insertNewline:))
- {
- [self insertNewline:self];
- }
+ if (aSelector == @selector(insertNewline:))
+ {
+ [self insertNewline:self];
+ }
}
- (BOOL)drawsVerticallyForCharacterAtIndex:(NSUInteger)charIndex
{
- return NO;
+ return NO;
}
- (void) allowMarkedTextInput:(bool)allowed
@@ -850,7 +895,7 @@ attributedStringInfo getSegments(NSAttributedString *str)
- (void) setGLView:(LLOpenGLView *)view
{
- glview = view;
+ glview = view;
}
- (void)keyDown:(NSEvent *)theEvent
@@ -901,45 +946,24 @@ attributedStringInfo getSegments(NSAttributedString *str)
- (id) init
{
- return self;
-}
-
-- (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);
+ return self;
}
- (BOOL) becomeFirstResponder
{
- callFocus();
- return true;
+ callFocus();
+ return true;
}
- (BOOL) resignFirstResponder
{
- callFocusLost();
- return true;
+ callFocusLost();
+ return true;
}
- (void) close
{
- callQuitHandler();
+ callQuitHandler();
}
@end
diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp
index 4f3cc69c75..935050485f 100644
--- a/indra/llwindow/llwindow.cpp
+++ b/indra/llwindow/llwindow.cpp
@@ -74,12 +74,12 @@ S32 OSMessageBox(const std::string& text, const std::string& caption, U32 type)
LL_WARNS() << "OSMessageBox: " << text << LL_ENDL;
#if LL_MESA_HEADLESS // !!! *FIX: (?)
return OSBTN_OK;
+#elif LL_SDL
+ result = OSMessageBoxSDL(text, caption, type);
#elif LL_WINDOWS
result = OSMessageBoxWin32(text, caption, type);
-#elif LL_DARWIN && !LL_SDL
+#elif LL_DARWIN
result = OSMessageBoxMacOSX(text, caption, type);
-#elif LL_SDL
- result = OSMessageBoxSDL(text, caption, type);
#else
#error("OSMessageBox not implemented for this platform!")
#endif
@@ -103,7 +103,6 @@ LLWindow::LLWindow(LLWindowCallbacks* callbacks, bool fullscreen, U32 flags)
mFullscreen(fullscreen),
mFullscreenWidth(0),
mFullscreenHeight(0),
- mFullscreenBits(0),
mFullscreenRefresh(0),
mSupportedResolutions(NULL),
mNumSupportedResolutions(0),
@@ -259,12 +258,12 @@ bool LLWindow::copyTextToPrimary(const LLWString &src)
// static
std::vector<std::string> LLWindow::getDynamicFallbackFontList()
{
-#if LL_WINDOWS
+#if LL_SDL
+ return LLWindowSDL::getDynamicFallbackFontList();
+#elif LL_WINDOWS
return LLWindowWin32::getDynamicFallbackFontList();
-#elif LL_DARWIN && !LL_SDL
+#elif LL_DARWIN
return LLWindowMacOSX::getDynamicFallbackFontList();
-#elif LL_SDL
- return LLWindowSDL::getDynamicFallbackFontList();
#else
return std::vector<std::string>();
#endif
@@ -273,12 +272,12 @@ std::vector<std::string> LLWindow::getDynamicFallbackFontList()
// static
std::vector<std::string> LLWindow::getDisplaysResolutionList()
{
-#if LL_WINDOWS
+#if LL_SDL
+ return std::vector<std::string>();
+#elif LL_WINDOWS
return LLWindowWin32::getDisplaysResolutionList();
-#elif LL_DARWIN && !LL_SDL
+#elif LL_DARWIN
return LLWindowMacOSX::getDisplaysResolutionList();
-#else
- return std::vector<std::string>();
#endif
}
@@ -346,7 +345,7 @@ LLSplashScreen *LLSplashScreen::create()
return 0;
#elif LL_WINDOWS
return new LLSplashScreenWin32;
-#elif LL_DARWIN && !LL_SDL
+#elif LL_DARWIN
return new LLSplashScreenMacOSX;
#else
#error("LLSplashScreen not implemented on this platform!")
@@ -359,7 +358,7 @@ void LLSplashScreen::show()
{
if (!gSplashScreenp)
{
-#if LL_WINDOWS && !LL_MESA_HEADLESS
+#if LL_WINDOWS && !LL_MESA_HEADLESS && !LL_SDL
gSplashScreenp = new LLSplashScreenWin32;
#elif LL_DARWIN && !LL_SDL
gSplashScreenp = new LLSplashScreenMacOSX;
diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h
index 5e06e665f3..d63927d23d 100644
--- a/indra/llwindow/llwindow.h
+++ b/indra/llwindow/llwindow.h
@@ -92,9 +92,10 @@ public:
virtual bool setCursorPosition(LLCoordWindow position) = 0;
virtual bool getCursorPosition(LLCoordWindow *position) = 0;
-#if LL_WINDOWS
+#if LL_WINDOWS && !LL_SDL
virtual bool getCursorDelta(LLCoordCommon* delta) = 0;
#endif
+ virtual bool isWrapMouse() const = 0;
virtual void showCursor() = 0;
virtual void hideCursor() = 0;
virtual bool isCursorHidden() = 0;
@@ -147,7 +148,6 @@ public:
virtual void swapBuffers() = 0;
virtual void bringToFront() = 0;
virtual void focusClient() { }; // this may not have meaning or be required on other platforms, therefore, it's not abstract
- virtual void setOldResize(bool oldresize) { };
// handy coordinate space conversion routines
// NB: screen to window and vice verse won't work on width/height coordinate pairs,
// as the conversion must take into account left AND right border widths, etc.
@@ -223,7 +223,6 @@ protected:
bool mFullscreen;
S32 mFullscreenWidth;
S32 mFullscreenHeight;
- S32 mFullscreenBits;
S32 mFullscreenRefresh;
LLWindowResolution* mSupportedResolutions;
S32 mNumSupportedResolutions;
diff --git a/indra/llwindow/llwindowcallbacks.cpp b/indra/llwindow/llwindowcallbacks.cpp
index 195f68e08b..7331f50ba0 100644
--- a/indra/llwindow/llwindowcallbacks.cpp
+++ b/indra/llwindow/llwindowcallbacks.cpp
@@ -68,7 +68,13 @@ void LLWindowCallbacks::handleMouseLeave(LLWindow *window)
return;
}
-bool LLWindowCallbacks::handleCloseRequest(LLWindow *window)
+bool LLWindowCallbacks::handleCloseRequest(LLWindow *window, bool from_user)
+{
+ //allow the window to close
+ return true;
+}
+
+bool LLWindowCallbacks::handleSessionExit(LLWindow* window)
{
//allow the window to close
return true;
diff --git a/indra/llwindow/llwindowcallbacks.h b/indra/llwindow/llwindowcallbacks.h
index d812f93524..59dcdd3ade 100644
--- a/indra/llwindow/llwindowcallbacks.h
+++ b/indra/llwindow/llwindowcallbacks.h
@@ -42,7 +42,8 @@ public:
virtual bool handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
virtual void handleMouseLeave(LLWindow *window);
// return true to allow window to close, which will then cause handleQuit to be called
- virtual bool handleCloseRequest(LLWindow *window);
+ virtual bool handleCloseRequest(LLWindow *window, bool from_user);
+ virtual bool handleSessionExit(LLWindow* window);
// window is about to be destroyed, clean up your business
virtual void handleQuit(LLWindow *window);
virtual bool handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
diff --git a/indra/llwindow/llwindowheadless.h b/indra/llwindow/llwindowheadless.h
index 5696b69a59..0a1ecb05e0 100644
--- a/indra/llwindow/llwindowheadless.h
+++ b/indra/llwindow/llwindowheadless.h
@@ -60,9 +60,10 @@ public:
/*virtual*/ void toggleVSync(bool enable_vsync) override { }
/*virtual*/ bool setCursorPosition(LLCoordWindow position) override {return false;}
/*virtual*/ bool getCursorPosition(LLCoordWindow *position) override {return false;}
-#if LL_WINDOWS
+#if LL_WINDOWS && !LL_SDL
/*virtual*/ bool getCursorDelta(LLCoordCommon* delta) override { return false; }
#endif
+ /*virtual*/ bool isWrapMouse() const override { return true; }
/*virtual*/ void showCursor() override {}
/*virtual*/ void hideCursor() override {}
/*virtual*/ void showCursorFromMouseMove() override {}
diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h
index d9d8bfce1f..b302a705da 100644
--- a/indra/llwindow/llwindowmacosx-objc.h
+++ b/indra/llwindow/llwindowmacosx-objc.h
@@ -100,7 +100,6 @@ bool isCGCursorVisible();
void hideNSCursorTillMove(bool hide);
void requestUserAttention();
long showAlert(std::string title, std::string text, int type);
-void setResizeMode(bool oldresize, void* glview);
NSWindowRef createNSWindow(int x, int y, int width, int height);
@@ -111,16 +110,14 @@ void glSwapBuffers(void* context);
CGLContextObj getCGLContextObj(GLViewRef view);
unsigned long getVramSize(GLViewRef view);
float getDeviceUnitSize(GLViewRef view);
-CGPoint getContentViewBoundsPosition(NSWindowRef window);
-CGSize getContentViewBoundsSize(NSWindowRef window);
-CGSize getDeviceContentViewSize(NSWindowRef window, GLViewRef view);
+CGRect getContentViewRect(NSWindowRef window);
+CGRect getBackingViewRect(NSWindowRef window, GLViewRef view);
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 convertScreenToView(NSWindowRef window, float *coord);
void convertRectToScreen(NSWindowRef window, float *coord);
void convertRectFromScreen(NSWindowRef window, float *coord);
void setWindowPos(NSWindowRef window, float* pos);
diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm
index 2e75d309ea..d902a82a3c 100644
--- a/indra/llwindow/llwindowmacosx-objc.mm
+++ b/indra/llwindow/llwindowmacosx-objc.mm
@@ -41,15 +41,15 @@
int createNSApp(int argc, const char *argv[])
{
- return NSApplicationMain(argc, argv);
+ return NSApplicationMain(argc, argv);
}
void setupCocoa()
{
- static bool inited = false;
-
- if(!inited)
- {
+ static bool inited = false;
+
+ if(!inited)
+ {
@autoreleasepool {
// 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'
@@ -57,8 +57,8 @@ void setupCocoa()
[[NSUserDefaults standardUserDefaults] setObject:@"NO" forKey:@"NSTreatUnknownArgumentsAsOpen"];
}
- inited = true;
- }
+ inited = true;
+ }
}
bool copyToPBoard(const unsigned short *str, unsigned int len)
@@ -66,7 +66,7 @@ bool copyToPBoard(const unsigned short *str, unsigned int len)
@autoreleasepool {
NSPasteboard *pboard = [NSPasteboard generalPasteboard];
[pboard clearContents];
-
+
NSArray *contentsToPaste = [[[NSArray alloc] initWithObjects:[NSString stringWithCharacters:str length:len], nil] autorelease];
return [pboard writeObjects:contentsToPaste];
}
@@ -74,8 +74,8 @@ bool copyToPBoard(const unsigned short *str, unsigned int len)
bool pasteBoardAvailable()
{
- NSArray *classArray = [NSArray arrayWithObject:[NSString class]];
- return [[NSPasteboard generalPasteboard] canReadObjectForClasses:classArray options:[NSDictionary dictionary]];
+ NSArray *classArray = [NSArray arrayWithObject:[NSString class]];
+ return [[NSPasteboard generalPasteboard] canReadObjectForClasses:classArray options:[NSDictionary dictionary]];
}
unsigned short *copyFromPBoard()
@@ -111,100 +111,110 @@ CursorRef createImageCursor(const char *fullpath, int hotspotX, int hotspotY)
hotSpot:NSMakePoint(hotspotX, hotspotY)
] retain];
}
-
- return (CursorRef)cursor;
+
+ return (CursorRef)cursor;
}
void setArrowCursor()
{
- NSCursor *cursor = [NSCursor arrowCursor];
- [NSCursor unhide];
- [cursor set];
+ NSCursor *cursor = [NSCursor arrowCursor];
+ [NSCursor unhide];
+ [cursor set];
}
void setIBeamCursor()
{
- NSCursor *cursor = [NSCursor IBeamCursor];
- [cursor set];
+ NSCursor *cursor = [NSCursor IBeamCursor];
+ [cursor set];
}
void setPointingHandCursor()
{
- NSCursor *cursor = [NSCursor pointingHandCursor];
- [cursor set];
+ NSCursor *cursor = [NSCursor pointingHandCursor];
+ [cursor set];
}
void setCopyCursor()
{
- NSCursor *cursor = [NSCursor dragCopyCursor];
- [cursor set];
+ NSCursor *cursor = [NSCursor dragCopyCursor];
+ [cursor set];
}
void setCrossCursor()
{
- NSCursor *cursor = [NSCursor crosshairCursor];
- [cursor set];
+ NSCursor *cursor = [NSCursor crosshairCursor];
+ [cursor set];
}
void setNotAllowedCursor()
{
- NSCursor *cursor = [NSCursor operationNotAllowedCursor];
- [cursor set];
+ NSCursor *cursor = [NSCursor operationNotAllowedCursor];
+ [cursor set];
}
void hideNSCursor()
{
- [NSCursor hide];
+ [NSCursor hide];
}
void showNSCursor()
{
- [NSCursor unhide];
+ [NSCursor unhide];
}
+#if LL_DARWIN
+// For CGCursorIsVisible no replacement in modern API
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
bool isCGCursorVisible()
{
return CGCursorIsVisible();
}
+#if LL_DARWIN
+#pragma clang diagnostic pop
+#endif
+
void hideNSCursorTillMove(bool hide)
{
- [NSCursor setHiddenUntilMouseMoves: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)
{
- if( ref != NULL )
- {
+ if( ref != NULL )
+ {
@autoreleasepool {
NSCursor *cursor = (NSCursor*)ref;
[cursor autorelease];
}
- }
- else
- {
- return paramErr;
- }
-
- return noErr;
+ }
+ else
+ {
+ return paramErr;
+ }
+
+ return noErr;
}
OSErr setImageCursor(CursorRef ref)
{
- if( ref != NULL )
- {
+ if( ref != NULL )
+ {
@autoreleasepool {
NSCursor *cursor = (NSCursor*)ref;
[cursor set];
}
- }
- else
- {
- return paramErr;
- }
-
- return noErr;
+ }
+ else
+ {
+ return paramErr;
+ }
+
+ return noErr;
}
// Now for some unholy juggling between generic pointers and casting them to Obj-C objects!
@@ -212,186 +222,155 @@ 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];
- [window makeKeyAndOrderFront:nil];
- [window setAcceptsMouseMovedEvents:TRUE];
+ LLNSWindow *window = [[LLNSWindow alloc]initWithContentRect:NSMakeRect(x, y, width, height)
+ styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskResizable | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable
+ backing:NSBackingStoreBuffered defer:NO];
+ [window makeKeyAndOrderFront:nil];
+ [window setAcceptsMouseMovedEvents:TRUE];
[window setRestorable:FALSE]; // Viewer manages state from own settings
- return window;
+ return window;
}
GLViewRef createOpenGLView(NSWindowRef window, unsigned int samples, bool vsync)
{
- LLOpenGLView *glview = [[LLOpenGLView alloc]initWithFrame:[(LLNSWindow*)window frame] withSamples:samples andVsync:vsync];
- [(LLNSWindow*)window setContentView:glview];
- return glview;
-}
-
-void setResizeMode(bool oldresize, void* glview)
-{
- [(LLOpenGLView *)glview setOldResize:oldresize];
+ LLOpenGLView *glview = [[LLOpenGLView alloc]initWithFrame:[(LLNSWindow*)window frame] withSamples:samples andVsync:vsync];
+ [(LLNSWindow*)window setContentView:glview];
+ return glview;
}
void glSwapBuffers(void* context)
{
- [(NSOpenGLContext*)context flushBuffer];
+ [(NSOpenGLContext*)context flushBuffer];
}
CGLContextObj getCGLContextObj(GLViewRef view)
{
- return [(LLOpenGLView *)view getCGLContextObj];
+ return [(LLOpenGLView *)view getCGLContextObj];
}
CGLPixelFormatObj* getCGLPixelFormatObj(NSWindowRef window)
{
- LLOpenGLView *glview = [(LLNSWindow*)window contentView];
- return [glview getCGLPixelFormatObj];
+ LLOpenGLView *glview = [(LLNSWindow*)window contentView];
+ return [glview getCGLPixelFormatObj];
}
unsigned long getVramSize(GLViewRef view)
{
- return [(LLOpenGLView *)view getVramSize];
+ return [(LLOpenGLView *)view getVramSize];
}
float getDeviceUnitSize(GLViewRef view)
{
- return [(LLOpenGLView*)view convertSizeToBacking:NSMakeSize(1, 1)].width;
+ return [(LLOpenGLView*)view convertSizeToBacking:NSMakeSize(1, 1)].width;
}
-CGPoint getContentViewBoundsPosition(NSWindowRef window)
+CGRect getContentViewRect(NSWindowRef window)
{
- return [[(LLNSWindow*)window contentView] bounds].origin;
+ return [[(LLNSWindow*)window contentView] bounds];
}
-CGSize getContentViewBoundsSize(NSWindowRef window)
+CGRect getBackingViewRect(NSWindowRef window, GLViewRef view)
{
- return [[(LLNSWindow*)window contentView] bounds].size;
-}
-
-CGSize getDeviceContentViewSize(NSWindowRef window, GLViewRef view)
-{
- return [(NSOpenGLView*)view convertRectToBacking:[[(LLNSWindow*)window contentView] bounds]].size;
+ return [(NSOpenGLView*)view convertRectToBacking:[[(LLNSWindow*)window contentView] bounds]];
}
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;
+ 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];
+ 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];
+ 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;
+ NSPoint mLoc;
+ mLoc = [(LLNSWindow*)window mouseLocationOutsideOfEventStream];
+ pos[0] = mLoc.x;
+ pos[1] = mLoc.y;
}
void makeWindowOrderFront(NSWindowRef window)
{
- [(LLNSWindow*)window makeKeyAndOrderFront:nil];
+ [(LLNSWindow*)window makeKeyAndOrderFront:nil];
}
void convertScreenToWindow(NSWindowRef window, float *coord)
{
- 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;
+ NSRect point = NSMakeRect(coord[0], coord[1], 0,0);
+ 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;
+ NSRect rect = NSMakeRect(coord[0], coord[1], coord[2], coord[3]);;
+ rect = [(LLNSWindow*)window convertRectToScreen:rect];
+
+ coord[0] = rect.origin.x;
+ coord[1] = rect.origin.y;
+ coord[2] = rect.size.width;
+ coord[3] = rect.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;
-}
+ NSRect point = NSMakeRect(coord[0], coord[1], coord[2], coord[3]);
+ point = [(LLNSWindow*)window convertRectFromScreen:point];
-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];
+ coord[0] = point.origin.x;
+ coord[1] = point.origin.y;
+ coord[2] = point.size.width;
+ coord[3] = point.size.height;
}
void convertWindowToScreen(NSWindowRef window, float *coord)
{
- NSPoint point;
- point.x = coord[0];
- point.y = coord[1];
- point = [(LLNSWindow*)window convertToScreenFromLocalPoint:point relativeToView:[(LLNSWindow*)window contentView]];
- coord[0] = point.x;
- coord[1] = point.y;
+ NSRect rect = NSMakeRect(coord[0], coord[1], 0, 0);
+ rect = [(LLNSWindow*)window convertRectToScreen:rect];
+
+ coord[0] = rect.origin.x;
+ coord[1] = [[NSScreen screens][0] frame].size.height - rect.origin.y;
}
void closeWindow(NSWindowRef window)
{
- [(LLNSWindow*)window close];
- [(LLNSWindow*)window release];
+ [(LLNSWindow*)window close];
+ [(LLNSWindow*)window release];
}
void removeGLView(GLViewRef view)
{
- [(LLOpenGLView*)view clearGLContext];
- [(LLOpenGLView*)view removeFromSuperview];
+ [(LLOpenGLView*)view clearGLContext];
+ [(LLOpenGLView*)view removeFromSuperview];
}
void setupInputWindow(NSWindowRef window, GLViewRef glview)
{
- [[(LLAppDelegate*)[NSApp delegate] inputView] setGLView:(LLOpenGLView*)glview];
+ [[(LLAppDelegate*)[NSApp delegate] inputView] setGLView:(LLOpenGLView*)glview];
}
void commitCurrentPreedit(GLViewRef glView)
{
- [(LLOpenGLView*)glView commitCurrentPreedit];
+ [(LLOpenGLView*)glView commitCurrentPreedit];
}
void allowDirectMarkedTextInput(bool allow, GLViewRef glView)
@@ -401,20 +380,20 @@ void allowDirectMarkedTextInput(bool allow, GLViewRef glView)
NSWindowRef getMainAppWindow()
{
- LLNSWindow *winRef = [(LLAppDelegate*)[[NSApplication sharedApplication] delegate] window];
-
- [winRef setAcceptsMouseMovedEvents:TRUE];
- return winRef;
+ LLNSWindow *winRef = [(LLAppDelegate*)[[NSApplication sharedApplication] delegate] window];
+
+ [winRef setAcceptsMouseMovedEvents:TRUE];
+ return winRef;
}
void makeFirstResponder(NSWindowRef window, GLViewRef view)
{
- [(LLNSWindow*)window makeFirstResponder:(LLOpenGLView*)view];
+ [(LLNSWindow*)window makeFirstResponder:(LLOpenGLView*)view];
}
void requestUserAttention()
{
- [[NSApplication sharedApplication] requestUserAttention:NSInformationalRequest];
+ [[NSApplication sharedApplication] requestUserAttention:NSInformationalRequest];
}
long showAlert(std::string text, std::string title, int type)
@@ -422,7 +401,7 @@ long showAlert(std::string text, std::string title, int type)
long ret = 0;
@autoreleasepool {
NSAlert *alert = [[[NSAlert alloc] init] autorelease];
-
+
[alert setMessageText:[NSString stringWithCString:title.c_str() encoding:[NSString defaultCStringEncoding]]];
[alert setInformativeText:[NSString stringWithCString:text.c_str() encoding:[NSString defaultCStringEncoding]]];
if (type == 0)
@@ -439,7 +418,7 @@ long showAlert(std::string text, std::string title, int type)
}
ret = [alert runModal];
}
-
+
if (ret == NSAlertFirstButtonReturn)
{
if (type == 1)
@@ -459,7 +438,7 @@ long showAlert(std::string text, std::string title, int type)
ret = 1;
}
}
-
+
return ret;
}
@@ -472,5 +451,5 @@ long showAlert(std::string text, std::string title, int type)
unsigned int getModifiers()
{
- return [NSEvent modifierFlags];
+ return [NSEvent modifierFlags];
}
diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp
index c97e014e46..0bf1c4b057 100644
--- a/indra/llwindow/llwindowmacosx.cpp
+++ b/indra/llwindow/llwindowmacosx.cpp
@@ -38,7 +38,6 @@
#include "lldir.h"
#include "indra_constants.h"
-
#include <OpenGL/OpenGL.h>
#include <Carbon/Carbon.h>
#include <CoreServices/CoreServices.h>
@@ -53,6 +52,7 @@
extern bool gDebugWindowProc;
bool gHiDPISupport = true;
+bool gHDRDisplaySupport = false;
const S32 BITS_PER_PIXEL = 32;
const S32 MAX_NUM_RESOLUTIONS = 32;
@@ -236,6 +236,8 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks,
allowLanguageTextInput(NULL, false);
}
+ setUseMultGL(sUseMultGL);
+
mCallbacks = callbacks;
stop_glerror();
@@ -611,7 +613,7 @@ void callQuitHandler()
{
if (gWindowImplementation && gWindowImplementation->getCallbacks())
{
- if(gWindowImplementation->getCallbacks()->handleCloseRequest(gWindowImplementation))
+ if(gWindowImplementation->getCallbacks()->handleCloseRequest(gWindowImplementation, true))
{
gWindowImplementation->getCallbacks()->handleQuit(gWindowImplementation);
}
@@ -986,7 +988,7 @@ bool LLWindowMacOSX::getPosition(LLCoordScreen *position)
}
else if(mWindow)
{
- const CGPoint & pos = getContentViewBoundsPosition(mWindow);
+ CGPoint pos = getContentViewRect(mWindow).origin;
position->mX = pos.x;
position->mY = pos.y;
@@ -1013,7 +1015,7 @@ bool LLWindowMacOSX::getSize(LLCoordScreen *size)
}
else if(mWindow)
{
- const CGSize & sz = gHiDPISupport ? getDeviceContentViewSize(mWindow, mGLView) : getContentViewBoundsSize(mWindow);
+ CGSize sz = getBackingViewRect(mWindow, mGLView).size;
size->mX = sz.width;
size->mY = sz.height;
@@ -1039,7 +1041,7 @@ bool LLWindowMacOSX::getSize(LLCoordWindow *size)
}
else if(mWindow)
{
- const CGSize & sz = gHiDPISupport ? getDeviceContentViewSize(mWindow, mGLView) : getContentViewBoundsSize(mWindow);
+ CGSize sz = getBackingViewRect(mWindow, mGLView).size;
size->mX = sz.width;
size->mY = sz.height;
@@ -1225,6 +1227,12 @@ void LLWindowMacOSX::setMouseClipping( bool b )
adjustCursorDecouple();
}
+#if LL_DARWIN
+// For CGSetLocalEventsSuppressionInterval there is no replacement in modern API
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
bool LLWindowMacOSX::setCursorPosition(const LLCoordWindow position)
{
bool result = false;
@@ -1262,6 +1270,10 @@ bool LLWindowMacOSX::setCursorPosition(const LLCoordWindow position)
return result;
}
+#if LL_DARWIN
+#pragma clang diagnostic pop
+#endif
+
bool LLWindowMacOSX::getCursorPosition(LLCoordWindow *position)
{
float cursor_point[2];
@@ -1486,8 +1498,9 @@ bool LLWindowMacOSX::convertCoords(LLCoordScreen from, LLCoordWindow* to)
convertScreenToWindow(mWindow, mouse_point);
- to->mX = mouse_point[0];
- to->mY = mouse_point[1];
+ float scale_factor = getSystemUISize();
+ to->mX = mouse_point[0] * scale_factor;
+ to->mY = mouse_point[1] * scale_factor;
return true;
}
@@ -1499,9 +1512,9 @@ bool LLWindowMacOSX::convertCoords(LLCoordWindow from, LLCoordScreen *to)
if(mWindow)
{
float mouse_point[2];
-
- mouse_point[0] = from.mX;
- mouse_point[1] = from.mY;
+ float scale_factor = getSystemUISize();
+ mouse_point[0] = from.mX / scale_factor;
+ mouse_point[1] = from.mY / scale_factor;
convertWindowToScreen(mWindow, mouse_point);
@@ -2638,7 +2651,7 @@ MASK LLWindowMacOSX::modifiersToMask(S16 modifiers)
F32 LLWindowMacOSX::getSystemUISize()
{
- return gHiDPISupport ? ::getDeviceUnitSize(mGLView) : LLWindow::getSystemUISize();
+ return ::getDeviceUnitSize(mGLView);
}
#if LL_OS_DRAGDROP_ENABLED
diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h
index 7de1a40d93..d703a84d02 100644
--- a/indra/llwindow/llwindowmacosx.h
+++ b/indra/llwindow/llwindowmacosx.h
@@ -63,6 +63,7 @@ public:
bool switchContext(bool fullscreen, const LLCoordScreen &size, bool enable_vsync, const LLCoordScreen * const posp = NULL) override;
bool setCursorPosition(LLCoordWindow position) override;
bool getCursorPosition(LLCoordWindow *position) override;
+ bool isWrapMouse() const override { return !mCursorDecoupled; };
void showCursor() override;
void hideCursor() override;
void showCursorFromMouseMove() override;
@@ -174,9 +175,6 @@ protected:
bool shouldPostQuit() { return mPostQuit; }
- //Satisfy MAINT-3135 and MAINT-3288 with a flag.
- /*virtual */ void setOldResize(bool oldresize) override {setResizeMode(oldresize, mGLView); }
-
private:
void restoreGLContext();
diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp
index 69332e36b6..ad40dea0c3 100644
--- a/indra/llwindow/llwindowsdl.cpp
+++ b/indra/llwindow/llwindowsdl.cpp
@@ -106,6 +106,10 @@ bool hasHIDPI = 0;
# include <X11/Xutil.h>
#endif //LL_X11
+#if LL_WINDOWS && !LL_MESA_HEADLESS
+#pragma comment(lib, "dinput8")
+#endif
+
// TOFU HACK -- (*exactly* the same hack as LLWindowMacOSX for a similar
// set of reasons): Stash a pointer to the LLWindowSDL object here and
// maintain in the constructor and destructor. This assumes that there will
@@ -427,14 +431,12 @@ bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, b
/*
mFullscreenWidth = mSurface->w;
mFullscreenHeight = mSurface->h;
- mFullscreenBits = mSurface->format->BitsPerPixel;
*/
SDL_GetWindowSize(mWindow, &mFullscreenWidth, &mFullscreenHeight);
mFullscreenRefresh = -1;
LL_INFOS() << "Running at " << mFullscreenWidth
<< "x" << mFullscreenHeight
- << "x" << mFullscreenBits
<< " @ " << mFullscreenRefresh
<< LL_ENDL;
}
@@ -445,7 +447,6 @@ bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, b
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);
@@ -1721,7 +1722,7 @@ void LLWindowSDL::gatherInput()
break;
}
case SDL_QUIT:
- if(mCallbacks->handleCloseRequest(this))
+ if(mCallbacks->handleCloseRequest(this, true))
{
// Get the app to initiate cleanup.
mCallbacks->handleQuit(this);
diff --git a/indra/llwindow/llwindowsdl.h b/indra/llwindow/llwindowsdl.h
index 144216f658..d9b6be5fdc 100644
--- a/indra/llwindow/llwindowsdl.h
+++ b/indra/llwindow/llwindowsdl.h
@@ -32,7 +32,7 @@
#include "llwindow.h"
#include "lltimer.h"
-#if !defined(__i386__) && !defined(__x86_64__)
+#if !defined(__i386__) && !defined(__x86_64__) && !_M_X64
#define SDL_DISABLE_IMMINTRIN_H
#endif
#include "SDL2/SDL.h"
@@ -91,6 +91,8 @@ public:
bool getCursorPosition(LLCoordWindow *position) override;
+ bool isWrapMouse() const override { return true; }
+
void showCursor() override;
void hideCursor() override;
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 4fca74497f..5471e1c87a 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -76,6 +76,11 @@
#pragma comment(lib, "dxguid.lib") // needed for llurlentry test to build on some systems
#pragma comment(lib, "dinput8")
+#pragma comment(lib, "UxTheme.lib")
+#pragma comment(lib, "Dwmapi.lib")
+#include <Uxtheme.h>
+#include <dwmapi.h> // needed for DwmSetWindowAttribute to set window theme
+
const S32 MAX_MESSAGE_PER_UPDATE = 20;
const S32 BITS_PER_PIXEL = 32;
const S32 MAX_NUM_RESOLUTIONS = 32;
@@ -85,6 +90,10 @@ const F32 ICON_FLASH_TIME = 0.5f;
#define USER_DEFAULT_SCREEN_DPI 96 // Win7
#endif
+#ifndef WM_DWMCOLORIZATIONCOLORCHANGED
+#define WM_DWMCOLORIZATIONCOLORCHANGED 0x0320
+#endif
+
// Claim a couple unused GetMessage() message IDs
const UINT WM_DUMMY_(WM_USER + 0x0017);
const UINT WM_POST_FUNCTION_(WM_USER + 0x0018);
@@ -104,6 +113,7 @@ static std::thread::id sMainThreadId;
LPWSTR gIconResource = IDI_APPLICATION;
+LPWSTR gIconSmallResource = IDI_APPLICATION;
LPDIRECTINPUT8 gDirectInput8;
LLW32MsgCallback gAsyncMsgCallback = NULL;
@@ -137,6 +147,17 @@ typedef HRESULT(STDAPICALLTYPE *GetDpiForMonitorType)(
_Out_ UINT *dpiX,
_Out_ UINT *dpiY);
+typedef enum PREFERRED_APP_MODE
+{
+ DEFAULT,
+ ALLOW_DARK,
+ FORCE_DARK,
+ FORCE_LIGHT,
+ MAX
+} PREFERRED_APP_MODE;
+
+typedef PREFERRED_APP_MODE(WINAPI* fnSetPreferredAppMode)(PREFERRED_APP_MODE mode);
+
//
// LLWindowWin32
//
@@ -350,10 +371,14 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool
LLWindowWin32Thread();
void run() override;
- void close() override;
- // closes queue, wakes thread, waits until thread closes
- void wakeAndDestroy();
+ // Detroys handles and window
+ // Either post to or call from window thread
+ void destroyWindow();
+
+ // Closes queue, wakes thread, waits until thread closes.
+ // Call from main thread
+ bool wakeAndDestroy();
void glReady()
{
@@ -410,6 +435,7 @@ struct LLWindowWin32::LLWindowWin32Thread : public LL::ThreadPool
// until after some graphics setup. See SL-20177. -Cosmic,2023-09-18
bool mGLReady = false;
bool mGotGLBuffer = false;
+ LLAtomicBool mDeleteOnExit = false;
};
@@ -424,6 +450,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
F32 max_gl_version)
:
LLWindow(callbacks, fullscreen, flags),
+ mAbsoluteCursorPosition(false),
mMaxGLVersion(max_gl_version),
mMaxCores(max_cores)
{
@@ -507,6 +534,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
mFSAASamples = fsaa_samples;
mIconResource = gIconResource;
+ mIconSmallResource = gIconSmallResource;
mOverrideAspectRatio = 0.f;
mNativeAspectRatio = 0.f;
mInputProcessingPaused = false;
@@ -576,6 +604,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
// Make an instance of our window then define the window class
mhInstance = GetModuleHandle(NULL);
+#if !_M_ARM64
// Init Direct Input - needed for joystick / Spacemouse
LPDIRECTINPUT8 di8_interface;
@@ -590,6 +619,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
{
gDirectInput8 = di8_interface;
}
+#endif
mSwapMethod = SWAP_METHOD_UNDEFINED;
@@ -695,8 +725,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
}
if (dev_mode.dmPelsWidth == width &&
- dev_mode.dmPelsHeight == height &&
- dev_mode.dmBitsPerPel == BITS_PER_PIXEL)
+ dev_mode.dmPelsHeight == height)
{
success = true;
if ((dev_mode.dmDisplayFrequency - current_refresh)
@@ -736,7 +765,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
// If we found a good resolution, use it.
if (success)
{
- success = setDisplayResolution(width, height, BITS_PER_PIXEL, closest_refresh);
+ success = setDisplayResolution(width, height, closest_refresh);
}
// Keep a copy of the actual current device mode in case we minimize
@@ -749,7 +778,6 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
mFullscreen = true;
mFullscreenWidth = dev_mode.dmPelsWidth;
mFullscreenHeight = dev_mode.dmPelsHeight;
- mFullscreenBits = dev_mode.dmBitsPerPel;
mFullscreenRefresh = dev_mode.dmDisplayFrequency;
LL_INFOS("Window") << "Running at " << dev_mode.dmPelsWidth
@@ -763,7 +791,6 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
mFullscreen = false;
mFullscreenWidth = -1;
mFullscreenHeight = -1;
- mFullscreenBits = -1;
mFullscreenRefresh = -1;
std::map<std::string,std::string> args;
@@ -786,7 +813,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
// }
// SL-12971 dual GPU display
- DISPLAY_DEVICEA display_device;
+ DISPLAY_DEVICE display_device;
int display_index = -1;
DWORD display_flags = 0; // EDD_GET_DEVICE_INTERFACE_NAME ?
const size_t display_bytes = sizeof(display_device);
@@ -797,23 +824,23 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
{
// CHAR DeviceName [ 32] Adapter name
// CHAR DeviceString[128]
- CHAR text[256];
+ WCHAR text[256];
- size_t name_len = strlen(display_device.DeviceName );
- size_t desc_len = strlen(display_device.DeviceString);
+ size_t name_len = lstrlen(display_device.DeviceName );
+ size_t desc_len = lstrlen(display_device.DeviceString);
- const CHAR *name = name_len ? display_device.DeviceName : "???";
- const CHAR *desc = desc_len ? display_device.DeviceString : "???";
+ const WCHAR *name = name_len ? display_device.DeviceName : TEXT("???");
+ const WCHAR *desc = desc_len ? display_device.DeviceString : TEXT("???");
- sprintf(text, "Display Device %d: %s, %s", display_index, name, desc);
- LL_INFOS("Window") << text << LL_ENDL;
+ wsprintf(text, TEXT("Display Device %d: %s, %s"), display_index, name, desc);
+ LL_INFOS("Window") << ll_convert<std::string>(std::wstring(text)) << LL_ENDL;
}
::ZeroMemory(&display_device,display_bytes);
display_device.cb = display_bytes;
display_index++;
- } while( EnumDisplayDevicesA(NULL, display_index, &display_device, display_flags ));
+ } while( EnumDisplayDevices(NULL, display_index, &display_device, display_flags ));
LL_INFOS("Window") << "Total Display Devices: " << display_index << LL_ENDL;
@@ -842,6 +869,8 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
// Initialize (boot strap) the Language text input management,
// based on the system's (or user's) default settings.
allowLanguageTextInput(NULL, false);
+ updateWindowTheme();
+ setCustomIcon();
}
@@ -853,6 +882,7 @@ LLWindowWin32::~LLWindowWin32()
}
delete mDragDrop;
+ mDragDrop = NULL;
delete [] mWindowTitle;
mWindowTitle = NULL;
@@ -864,6 +894,7 @@ LLWindowWin32::~LLWindowWin32()
mWindowClassName = NULL;
delete mWindowThread;
+ mWindowThread = NULL;
}
void LLWindowWin32::show()
@@ -972,7 +1003,7 @@ void LLWindowWin32::close()
// Restore gamma to the system values.
restoreGamma();
- LL_DEBUGS("Window") << "Destroying Window" << LL_ENDL;
+ LL_INFOS("Window") << "Cleanup and destruction of Window Thread" << LL_ENDL;
if (sWindowHandleForMessageBox == mWindowHandle)
{
@@ -982,7 +1013,11 @@ void LLWindowWin32::close()
mhDC = NULL;
mWindowHandle = NULL;
- mWindowThread->wakeAndDestroy();
+ if (mWindowThread->wakeAndDestroy())
+ {
+ // thread will delete itselfs once done
+ mWindowThread = NULL;
+ }
}
bool LLWindowWin32::isValid()
@@ -1185,7 +1220,7 @@ bool LLWindowWin32::switchContext(bool fullscreen, const LLCoordScreen& size, bo
// If we found a good resolution, use it.
if (success)
{
- success = setDisplayResolution(width, height, BITS_PER_PIXEL, closest_refresh);
+ success = setDisplayResolution(width, height, closest_refresh);
}
// Keep a copy of the actual current device mode in case we minimize
@@ -1197,7 +1232,6 @@ bool LLWindowWin32::switchContext(bool fullscreen, const LLCoordScreen& size, bo
mFullscreen = true;
mFullscreenWidth = dev_mode.dmPelsWidth;
mFullscreenHeight = dev_mode.dmPelsHeight;
- mFullscreenBits = dev_mode.dmBitsPerPel;
mFullscreenRefresh = dev_mode.dmDisplayFrequency;
LL_INFOS("Window") << "Running at " << dev_mode.dmPelsWidth
@@ -1223,7 +1257,6 @@ bool LLWindowWin32::switchContext(bool fullscreen, const LLCoordScreen& size, bo
mFullscreen = false;
mFullscreenWidth = -1;
mFullscreenHeight = -1;
- mFullscreenBits = -1;
mFullscreenRefresh = -1;
LL_INFOS("Window") << "Unable to run fullscreen at " << width << "x" << height << LL_ENDL;
@@ -1666,6 +1699,11 @@ const S32 max_format = (S32)num_formats - 1;
return false;
}
+ // Setup Tracy gpu context
+ {
+ LL_PROFILER_GPU_CONTEXT;
+ }
+
// Disable vertical sync for swap
toggleVSync(enable_vsync);
@@ -1697,8 +1735,6 @@ const S32 max_format = (S32)num_formats - 1;
swapBuffers();
}
- LL_PROFILER_GPU_CONTEXT;
-
return true;
}
@@ -1931,7 +1967,7 @@ void LLWindowWin32::setTitle(const std::string title)
// to support non-ascii usernames (and region names?)
mWindowThread->post([=]()
{
- SetWindowTextA(mWindowHandle, title.c_str());
+ SetWindowText(mWindowHandle, ll_convert<std::wstring>(title).c_str());
});
}
@@ -2431,10 +2467,13 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
case WM_CLOSE:
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_CLOSE");
+ // todo: WM_CLOSE can be caused by user and by task manager,
+ // distinguish these cases.
+ // For now assume it is always user.
window_imp->post([=]()
{
// Will the app allow the window to close?
- if (window_imp->mCallbacks->handleCloseRequest(window_imp))
+ if (window_imp->mCallbacks->handleCloseRequest(window_imp, true))
{
// Get the app to initiate cleanup.
window_imp->mCallbacks->handleQuit(window_imp);
@@ -2452,6 +2491,50 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
}
return 0;
}
+ case WM_QUERYENDSESSION:
+ {
+ // Generally means that OS is going to shut down or user is going to log off.
+ // Can use ShutdownBlockReasonCreate here.
+ LL_INFOS("Window") << "Received WM_QUERYENDSESSION with wParam: " << (U32)w_param << " lParam: " << (U32)l_param << LL_ENDL;
+ return TRUE; // 1 = ok to end session. 0 no longer works by itself, use ShutdownBlockReasonCreate
+ }
+ case WM_ENDSESSION:
+ {
+ // OS session is shutting down, initiate cleanup.
+ // Comes after WM_QUERYENDSESSION
+ LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_ENDSESSION");
+ LL_INFOS("Window") << "Received WM_ENDSESSION with wParam: " << (U32)w_param << " lParam: " << (U32)l_param << LL_ENDL;
+ unsigned int end_session_flags = (U32)w_param;
+ if (end_session_flags == 0)
+ {
+ // session is not actually ending
+ return 0;
+ }
+
+ if ((end_session_flags & ENDSESSION_CLOSEAPP)
+ || (end_session_flags & ENDSESSION_CRITICAL)
+ || (end_session_flags & ENDSESSION_LOGOFF))
+ {
+ window_imp->post([=]()
+ {
+ // Check if app needs cleanup or can be closed immediately.
+ if (window_imp->mCallbacks->handleSessionExit(window_imp))
+ {
+ // Get the app to initiate cleanup.
+ window_imp->mCallbacks->handleQuit(window_imp);
+ // The app is responsible for calling destroyWindow when done with GL
+ }
+ });
+ // Give app a second to finish up. That's not enough for a clean exit,
+ // but better than nothing.
+ // Todo: sync this better, some kind of waitForResult? Can't wait forever,
+ // but can potentially use ShutdownBlockReasonCreate for a bigger delay.
+ ms_sleep(1000);
+ }
+ // Don't need to post quit or destroy window,
+ // if session is ending OS is going to take care of it.
+ return 0;
+ }
case WM_COMMAND:
{
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_COMMAND");
@@ -3012,6 +3095,17 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
WINDOW_IMP_POST(window_imp->mMouseVanish = true);
}
}
+ // Check if theme-related settings changed
+ else if (l_param && (wcscmp((LPCWSTR)l_param, L"ImmersiveColorSet") == 0))
+ {
+ WINDOW_IMP_POST(window_imp->updateWindowTheme());
+ }
+ }
+ break;
+
+ case WM_DWMCOLORIZATIONCOLORCHANGED:
+ {
+ WINDOW_IMP_POST(window_imp->updateWindowTheme());
}
break;
@@ -3065,6 +3159,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
prev_absolute_x = absolute_x;
prev_absolute_y = absolute_y;
+ window_imp->mAbsoluteCursorPosition = true;
}
else
{
@@ -3081,6 +3176,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
window_imp->mRawMouseDelta.mX += (S32)round((F32)raw->data.mouse.lLastX * (F32)speed / DEFAULT_SPEED);
window_imp->mRawMouseDelta.mY -= (S32)round((F32)raw->data.mouse.lLastY * (F32)speed / DEFAULT_SPEED);
}
+ window_imp->mAbsoluteCursorPosition = false;
}
}
}
@@ -3104,10 +3200,14 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
break;
}
}
- else
+ else // (NULL == window_imp)
{
- // (NULL == window_imp)
LL_DEBUGS("Window") << "No window implementation to handle message with, message code: " << U32(u_msg) << LL_ENDL;
+ if (u_msg == WM_DESTROY)
+ {
+ PostQuitMessage(0); // Posts WM_QUIT with an exit code of 0
+ return 0;
+ }
}
// pass unhandled messages down to Windows
@@ -3241,7 +3341,7 @@ bool LLWindowWin32::pasteTextFromClipboard(LLWString &dst)
WCHAR *utf16str = (WCHAR*) GlobalLock(h_data);
if (utf16str)
{
- dst = utf16str_to_wstring(utf16str);
+ dst = ll_convert<LLWString>(std::wstring(utf16str));
LLWStringUtil::removeWindowsCR(dst);
GlobalUnlock(h_data);
success = true;
@@ -3266,8 +3366,8 @@ bool LLWindowWin32::copyTextToClipboard(const LLWString& wstr)
// Provide a copy of the data in Unicode format.
LLWString sanitized_string(wstr);
LLWStringUtil::addCRLF(sanitized_string);
- llutf16string out_utf16 = wstring_to_utf16str(sanitized_string);
- const size_t size_utf16 = (out_utf16.length() + 1) * sizeof(WCHAR);
+ std::wstring out_utf16 = ll_convert<std::wstring>(sanitized_string);
+ const size_t size_utf16 = (out_utf16.length() + 1) * sizeof(wchar_t);
// Memory is allocated and then ownership of it is transfered to the system.
HGLOBAL hglobal_copy_utf16 = GlobalAlloc(GMEM_MOVEABLE, size_utf16);
@@ -3517,7 +3617,7 @@ F32 LLWindowWin32::getPixelAspectRatio()
// Change display resolution. Returns true if successful.
// protected
-bool LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh)
+bool LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 refresh)
{
DEVMODE dev_mode;
::ZeroMemory(&dev_mode, sizeof(DEVMODE));
@@ -3529,7 +3629,6 @@ bool LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 re
{
if (dev_mode.dmPelsWidth == width &&
dev_mode.dmPelsHeight == height &&
- dev_mode.dmBitsPerPel == bits &&
dev_mode.dmDisplayFrequency == refresh )
{
// ...display mode identical, do nothing
@@ -3541,9 +3640,8 @@ bool LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 re
dev_mode.dmSize = sizeof(dev_mode);
dev_mode.dmPelsWidth = width;
dev_mode.dmPelsHeight = height;
- dev_mode.dmBitsPerPel = bits;
dev_mode.dmDisplayFrequency = refresh;
- dev_mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
+ dev_mode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
// CDS_FULLSCREEN indicates that this is a temporary change to the device mode.
LONG cds_result = ChangeDisplaySettings(&dev_mode, CDS_FULLSCREEN);
@@ -3553,7 +3651,7 @@ bool LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 re
if (!success)
{
LL_WARNS("Window") << "setDisplayResolution failed, "
- << width << "x" << height << "x" << bits << " @ " << refresh << LL_ENDL;
+ << width << "x" << height << " @ " << refresh << LL_ENDL;
}
return success;
@@ -3564,7 +3662,7 @@ bool LLWindowWin32::setFullscreenResolution()
{
if (mFullscreen)
{
- return setDisplayResolution( mFullscreenWidth, mFullscreenHeight, mFullscreenBits, mFullscreenRefresh);
+ return setDisplayResolution( mFullscreenWidth, mFullscreenHeight, mFullscreenRefresh);
}
else
{
@@ -3629,7 +3727,7 @@ void LLSplashScreenWin32::showImpl()
ShowWindow(mWindow, SW_SHOW);
// Should set taskbar text without creating a header for the window (caption)
- SetWindowTextA(mWindow, "Second Life");
+ SetWindowText(mWindow, TEXT("Second Life"));
}
@@ -3766,8 +3864,7 @@ void LLWindowWin32::spawnWebBrowser(const std::string& escaped_url, bool async)
// reliablly on Vista.
// this is madness.. no, this is..
- LLWString url_wstring = utf8str_to_wstring( escaped_url );
- llutf16string url_utf16 = wstring_to_utf16str( url_wstring );
+ std::wstring url_utf16 = ll_convert<std::wstring>(escaped_url);
// let the OS decide what to use to open the URL
SHELLEXECUTEINFO sei = { sizeof( sei ) };
@@ -4055,7 +4152,7 @@ void LLWindowWin32::fillCompositionLogfont(LOGFONT *logfont)
U32 LLWindowWin32::fillReconvertString(const LLWString &text,
S32 focus, S32 focus_length, RECONVERTSTRING *reconvert_string)
{
- const llutf16string text_utf16 = wstring_to_utf16str(text);
+ const std::wstring text_utf16 = ll_convert<std::wstring>(text);
const DWORD required_size = sizeof(RECONVERTSTRING) + (static_cast<DWORD>(text_utf16.length()) + 1) * sizeof(WCHAR);
if (reconvert_string && reconvert_string->dwSize >= required_size)
{
@@ -4155,7 +4252,7 @@ void LLWindowWin32::handleCompositionMessage(const U32 indexes)
size = LLWinImm::getCompositionString(himc, GCS_RESULTSTR, data, size);
if (size > 0)
{
- result_string = utf16str_to_wstring(llutf16string(data, size / sizeof(WCHAR)));
+ result_string = ll_convert_wide_to_wstring(std::wstring(data, size / sizeof(WCHAR)));
}
delete[] data;
needs_update = true;
@@ -4172,7 +4269,7 @@ void LLWindowWin32::handleCompositionMessage(const U32 indexes)
if (size > 0)
{
preedit_string_utf16_length = size / sizeof(WCHAR);
- preedit_string = utf16str_to_wstring(llutf16string(data, size / sizeof(WCHAR)));
+ preedit_string = ll_convert_wide_to_wstring(std::wstring(data, size / sizeof(WCHAR)));
}
delete[] data;
needs_update = true;
@@ -4579,25 +4676,11 @@ std::vector<std::string> LLWindowWin32::getDynamicFallbackFontList()
#endif // LL_WINDOWS
inline LLWindowWin32::LLWindowWin32Thread::LLWindowWin32Thread()
- : LL::ThreadPool("Window Thread", 1, MAX_QUEUE_SIZE, true /*should be false, temporary workaround for SL-18721*/)
+ : LL::ThreadPool("Window Thread", 1, MAX_QUEUE_SIZE, false)
{
LL::ThreadPool::start();
}
-void LLWindowWin32::LLWindowWin32Thread::close()
-{
- if (!mQueue->isClosed())
- {
- LL_WARNS() << "Closing window thread without using destroy_window_handler" << LL_ENDL;
- LL::ThreadPool::close();
-
- // Workaround for SL-18721 in case window closes too early and abruptly
- LLSplashScreen::show();
- LLSplashScreen::update("..."); // will be updated later
- }
-}
-
-
/**
* LogChange is to log changes in status while trying to avoid spamming the
* log with repeated messages, especially in a tight loop. It refuses to log
@@ -4821,108 +4904,102 @@ void LLWindowWin32::LLWindowWin32Thread::run()
}
#endif
}
+
+ destroyWindow();
+
+ if (mDeleteOnExit)
+ {
+ delete this;
+ }
+}
+
+void LLWindowWin32::LLWindowWin32Thread::destroyWindow()
+{
+ if (mWindowHandleThrd != NULL && IsWindow(mWindowHandleThrd))
+ {
+ if (mhDCThrd)
+ {
+ if (!ReleaseDC(mWindowHandleThrd, mhDCThrd))
+ {
+ LL_WARNS("Window") << "Release of ghDC failed!" << LL_ENDL;
+ }
+ mhDCThrd = NULL;
+ }
+
+ // This causes WM_DESTROY to be sent *immediately*
+ if (!destroy_window_handler(mWindowHandleThrd))
+ {
+ LL_WARNS("Window") << "Failed to destroy Window! " << std::hex << GetLastError() << LL_ENDL;
+ }
+ }
+ else
+ {
+ // Something killed the window while we were busy destroying gl or handle somehow got broken
+ LL_WARNS("Window") << "Failed to destroy Window, invalid handle!" << LL_ENDL;
+ }
+ mWindowHandleThrd = NULL;
+ mhDCThrd = NULL;
}
-void LLWindowWin32::LLWindowWin32Thread::wakeAndDestroy()
+bool LLWindowWin32::LLWindowWin32Thread::wakeAndDestroy()
{
if (mQueue->isClosed())
{
- LL_WARNS() << "Tried to close Queue. Win32 thread Queue already closed." << LL_ENDL;
- return;
+ LL_WARNS("Window") << "Tried to close Queue. Win32 thread Queue already closed." << LL_ENDL;
+ return false;
}
- // Make sure we don't leave a blank toolbar button.
- // Also hiding window now prevents user from suspending it
- // via some action (like dragging it around)
- ShowWindow(mWindowHandleThrd, SW_HIDE);
+ // Stop checking budget
+ mGLReady = false;
- // Schedule destruction
+ // Capture current handle before we lose it
HWND old_handle = mWindowHandleThrd;
- post([this]()
- {
- if (IsWindow(mWindowHandleThrd))
- {
- if (mhDCThrd)
- {
- if (!ReleaseDC(mWindowHandleThrd, mhDCThrd))
- {
- LL_WARNS("Window") << "Release of ghDC failed!" << LL_ENDL;
- }
- mhDCThrd = NULL;
- }
-
- // This causes WM_DESTROY to be sent *immediately*
- if (!destroy_window_handler(mWindowHandleThrd))
- {
- LL_WARNS("Window") << "Failed to destroy Window! " << std::hex << GetLastError() << LL_ENDL;
- }
- }
- else
- {
- // Something killed the window while we were busy destroying gl or handle somehow got broken
- LL_WARNS("Window") << "Failed to destroy Window, invalid handle!" << LL_ENDL;
- }
- mWindowHandleThrd = NULL;
- mhDCThrd = NULL;
- mGLReady = false;
- });
-
- LL_DEBUGS("Window") << "Closing window's pool queue" << LL_ENDL;
- mQueue->close();
- // Post a nonsense user message to wake up the thread in
- // case it is waiting for a getMessage()
+ // Clear the user data to prevent callbacks from finding us
if (old_handle)
{
- WPARAM wparam{ 0xB0B0 };
- LL_DEBUGS("Window") << "PostMessage(" << std::hex << old_handle
- << ", " << WM_DUMMY_
- << ", " << wparam << ")" << std::dec << LL_ENDL;
- PostMessage(old_handle, WM_DUMMY_, wparam, 0x1337);
+ SetWindowLongPtr(old_handle, GWLP_USERDATA, NULL);
}
- // There are cases where window will refuse to close,
- // can't wait forever on join, check state instead
- LLTimer timeout;
- timeout.setTimerExpirySec(2.0);
- while (!getQueue().done() && !timeout.hasExpired() && mWindowHandleThrd)
- {
- ms_sleep(100);
- }
+ // Signal thread to clean up when done
+ mDeleteOnExit = true;
- if (getQueue().done() || mWindowHandleThrd == NULL)
+ LL_INFOS("Window") << "Detaching window's thread" << LL_ENDL;
+ // Cleanly detach threads instead of joining them to avoid blocking the main thread
+ // This is acceptable since the thread will self-delete with mDeleteOnExit
+ // Doing it before close() to make sure thread doesn't die before or mid detach.
+ for (auto& pair : mThreads)
{
- // Window is closed, started closing or is cleaning up
- // now wait for our single thread to die.
- if (mWindowHandleThrd)
- {
- LL_INFOS("Window") << "Window is closing, waiting on pool's thread to join, time since post: " << timeout.getElapsedSeconds() << "s" << LL_ENDL;
- }
- else
- {
- LL_DEBUGS("Window") << "Waiting on pool's thread, time since post: " << timeout.getElapsedSeconds() << "s" << LL_ENDL;
+ try {
+ // Only detach if the thread is joinable
+ if (pair.second.joinable())
+ {
+ pair.second.detach();
+ }
}
- for (auto& pair : mThreads)
- {
- pair.second.join();
+ catch (const std::system_error& e) {
+ LL_WARNS("Window") << "Exception detaching thread: " << e.what() << LL_ENDL;
}
}
- else
+
+ // Close the queue.
+ LL_INFOS("Window") << "Closing window's pool queue" << LL_ENDL;
+ mQueue->close();
+
+ // Wake up the thread if it's stuck in GetMessage()
+ if (old_handle)
{
- // Something suspended window thread, can't afford to wait forever
- // so kill thread instead
- // Ex: This can happen if user starts dragging window arround (if it
- // was visible) or a modal notification pops up
- LL_WARNS("Window") << "Window is frozen, couldn't perform clean exit" << LL_ENDL;
+ WPARAM wparam{ 0xB0B0 };
+ LL_DEBUGS("Window") << "PostMessage(" << std::hex << old_handle
+ << ", " << WM_DUMMY_
+ << ", " << wparam << ")" << std::dec << LL_ENDL;
- for (auto& pair : mThreads)
- {
- // very unsafe
- TerminateThread(pair.second.native_handle(), 0);
- pair.second.detach();
- }
+ // Use PostMessage to signal thread to wake up
+ PostMessage(old_handle, WM_DUMMY_, wparam, 0x1337);
}
- LL_DEBUGS("Window") << "thread pool shutdown complete" << LL_ENDL;
+
+ LL_INFOS("Window") << "Thread pool shutdown complete" << LL_ENDL;
+ return true;
}
void LLWindowWin32::post(const std::function<void()>& func)
@@ -4969,3 +5046,69 @@ void LLWindowWin32::updateWindowRect()
});
}
}
+
+bool LLWindowWin32::isSystemAppDarkMode()
+{
+ HKEY hKey;
+ DWORD dwValue = 1; // Default to light theme
+ DWORD dwSize = sizeof(DWORD);
+
+ // Check registry for system theme preference
+ LSTATUS ret_code =
+ RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", 0, KEY_READ, &hKey);
+ if (ERROR_SUCCESS == ret_code)
+ {
+ if (RegQueryValueExW(hKey, L"AppsUseLightTheme", NULL, NULL, (LPBYTE)&dwValue, &dwSize) != ERROR_SUCCESS)
+ {
+ // If AppsUseLightTheme is not found, check SystemUsesLightTheme
+ dwSize = sizeof(DWORD);
+ RegQueryValueExW(hKey, L"SystemUsesLightTheme", NULL, NULL, (LPBYTE)&dwValue, &dwSize);
+ }
+ RegCloseKey(hKey);
+ }
+
+ // Return true if dark mode
+ return dwValue == 0;
+}
+
+void LLWindowWin32::updateWindowTheme()
+{
+ bool use_dark_mode = isSystemAppDarkMode();
+ if (use_dark_mode == mCurrentDarkMode)
+ {
+ return;
+ }
+ mCurrentDarkMode = use_dark_mode;
+
+ HMODULE hUxTheme = LoadLibraryExW(L"uxtheme.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
+ if (hUxTheme)
+ {
+ auto SetPreferredAppMode = (fnSetPreferredAppMode)GetProcAddress(hUxTheme, "SetPreferredAppMode");
+ if (SetPreferredAppMode)
+ {
+ SetPreferredAppMode(use_dark_mode ? ALLOW_DARK : FORCE_LIGHT);
+ }
+ FreeLibrary(hUxTheme);
+ }
+ BOOL dark_mode(use_dark_mode);
+ DwmSetWindowAttribute(mWindowHandle, DWMWA_USE_IMMERSIVE_DARK_MODE, &dark_mode, sizeof(dark_mode));
+
+ LL_INFOS("Window") << "Viewer window theme is set to " << (use_dark_mode ? "dark" : "light") << " mode" << LL_ENDL;
+}
+
+void LLWindowWin32::setCustomIcon()
+{
+ if (mWindowHandle)
+ {
+ HICON hDefaultIcon = LoadIcon(mhInstance, mIconResource);
+ HICON hSmallIcon = LoadIcon(mhInstance, mIconSmallResource);
+ mWindowThread->post([=]()
+ {
+ SendMessage(mWindowHandle, WM_SETICON, ICON_BIG, (LPARAM)hDefaultIcon);
+ SendMessage(mWindowHandle, WM_SETICON, ICON_SMALL, (LPARAM)hSmallIcon);
+
+ SetClassLongPtr(mWindowHandle, GCLP_HICON, (LONG_PTR)hDefaultIcon);
+ SetClassLongPtr(mWindowHandle, GCLP_HICONSM, (LONG_PTR)hSmallIcon);
+ });
+ }
+}
diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h
index 36e89e4586..0fc93ad0b1 100644
--- a/indra/llwindow/llwindowwin32.h
+++ b/indra/llwindow/llwindowwin32.h
@@ -70,6 +70,7 @@ public:
/*virtual*/ bool setCursorPosition(LLCoordWindow position);
/*virtual*/ bool getCursorPosition(LLCoordWindow *position);
/*virtual*/ bool getCursorDelta(LLCoordCommon* delta);
+ /*virtual*/ bool isWrapMouse() const override { return !mAbsoluteCursorPosition; };
/*virtual*/ void showCursor();
/*virtual*/ void hideCursor();
/*virtual*/ void showCursorFromMouseMove();
@@ -150,7 +151,7 @@ protected:
virtual LLSD getNativeKeyData();
// Changes display resolution. Returns true if successful
- bool setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh);
+ bool setDisplayResolution(S32 width, S32 height, S32 refresh);
// Go back to last fullscreen display resolution.
bool setFullscreenResolution();
@@ -195,6 +196,7 @@ protected:
HCURSOR mCursor[ UI_CURSOR_COUNT ]; // Array of all mouse cursors
LLCoordWindow mCursorPosition; // mouse cursor position, should only be mutated on main thread
+ bool mAbsoluteCursorPosition; // true if last position was received in absolute coordinates.
LLMutex mRawMouseMutex;
RAWINPUTDEVICE mRawMouse;
LLCoordWindow mLastCursorPosition; // mouse cursor position from previous frame
@@ -214,6 +216,7 @@ protected:
bool mCustomGammaSet;
LPWSTR mIconResource;
+ LPWSTR mIconSmallResource;
bool mInputProcessingPaused;
// The following variables are for Language Text Input control.
@@ -246,6 +249,11 @@ protected:
RECT mRect;
RECT mClientRect;
+ void updateWindowTheme();
+ bool isSystemAppDarkMode();
+ void setCustomIcon();
+ bool mCurrentDarkMode { false };
+
struct LLWindowWin32Thread;
LLWindowWin32Thread* mWindowThread = nullptr;
LLThreadSafeQueue<std::function<void()>> mFunctionQueue;
@@ -281,6 +289,7 @@ private:
extern LLW32MsgCallback gAsyncMsgCallback;
extern LPWSTR gIconResource;
+extern LPWSTR gIconSmallResource;
S32 OSMessageBoxWin32(const std::string& text, const std::string& caption, U32 type);