Revision: 14424
          http://sourceforge.net/p/skim-app/code/14424
Author:   hofman
Date:     2024-08-15 23:40:17 +0000 (Thu, 15 Aug 2024)
Log Message:
-----------
observe universalaccess defaults to reset custom cursors instead of checking it 
for every custom cursor getter

Modified Paths:
--------------
    trunk/NSCursor_SKExtensions.m

Modified: trunk/NSCursor_SKExtensions.m
===================================================================
--- trunk/NSCursor_SKExtensions.m       2024-08-15 21:31:03 UTC (rev 14423)
+++ trunk/NSCursor_SKExtensions.m       2024-08-15 23:40:17 UTC (rev 14424)
@@ -45,6 +45,8 @@
 #import "NSShadow_SKExtensions.h"
 #import "NSBezierPath_SKExtensions.h"
 
+static char SKUniversalAccessDefaultsObservationContext;
+
 static inline void hideLaserPointer(void);
 
 @interface NSCursor (SKPrivateDeclarations)
@@ -52,11 +54,28 @@
 + (id)_windowResizeNorthEastSouthWestCursor;
 @end
 
+#pragma mark -
+
 @interface SKLaserPointerCursor : NSCursor
 @end
 
 #pragma mark -
 
+@interface SKCustomCursors : NSObject {
+    NSUserDefaults *universalaccessDefaults;
+    NSMutableDictionary *customCursors;
+}
+
+@property(class, nonatomic, readonly) SKCustomCursors *sharedCustomCursors;
+
+@property (nonatomic, readonly) NSUserDefaults *universalaccessDefaults;
+
+- (NSCursor *)cursorWithName:(NSString *)name;
+
+@end
+
+#pragma mark -
+
 @implementation NSCursor (SKExtensions)
 
 static void (*original_set)(id, SEL) = NULL;
@@ -77,43 +96,197 @@
     original_hide = (void(*)(id, 
SEL))SKReplaceClassMethodImplementationFromSelector(self, @selector(hide), 
@selector(replacement_hide));
 }
 
-static NSUserDefaults *universalaccessDefaults() {
-    static NSUserDefaults *universalaccessDefaults = nil;
-    if (universalaccessDefaults == nil)
-        universalaccessDefaults = [[NSUserDefaults alloc] 
initWithSuiteName:@"com.apple.universalaccess"];
-    return universalaccessDefaults;
++ (NSCursor *)zoomInCursor {
+    return [[SKCustomCursors sharedCustomCursors] 
cursorWithName:@"zoomInCursor"];
 }
 
-static NSDictionary *currentCursorColors() {
-    if (@available(macOS 12.0, *)) {
-        if ([universalaccessDefaults() boolForKey:@"cursorIsCustomized"]) {
-            NSDictionary *cursorOutline = [universalaccessDefaults() 
dictionaryForKey:@"cursorOutline"];
-            NSDictionary *cursorFill = [universalaccessDefaults() 
dictionaryForKey:@"cursorFill"];
-            if ([cursorOutline count] == 4 && [cursorFill count] == 4)
-                return @{@"cursorOutline":cursorOutline, 
@"cursorFill":cursorFill};
-        }
++ (NSCursor *)zoomOutCursor {
+    return [[SKCustomCursors sharedCustomCursors] 
cursorWithName:@"zoomOutCursor"];
+}
+
++ (NSCursor *)resizeDiagonal45Cursor {
+    if ([self 
respondsToSelector:@selector(_windowResizeNorthEastSouthWestCursor)]) {
+        return [NSCursor _windowResizeNorthEastSouthWestCursor];
+    } else {
+        return [[SKCustomCursors sharedCustomCursors] 
cursorWithName:@"resizeDiagonal45Cursor"];
     }
-    return @{};
 }
 
-+ (NSCursor *)customCursorWithName:(NSString *)name {
-    static NSMutableDictionary *customCursors = nil;
-    static NSDictionary *cursorColors = nil;
++ (NSCursor *)resizeDiagonal135Cursor {
+    if ([self 
respondsToSelector:@selector(_windowResizeNorthWestSouthEastCursor)]) {
+        return [NSCursor _windowResizeNorthWestSouthEastCursor];
+    } else {
+        return [[SKCustomCursors sharedCustomCursors] 
cursorWithName:@"resizeDiagonal135Cursor"];
+    }
+}
+
++ (NSCursor *)cameraCursor {
+    return [[SKCustomCursors sharedCustomCursors] 
cursorWithName:@"cameraCursor"];
+}
+
++ (NSCursor *)openHandBarCursor {
+    return [[SKCustomCursors sharedCustomCursors] 
cursorWithName:@"openHandBarCursor"];
+}
+
++ (NSCursor *)closedHandBarCursor {
+    return [[SKCustomCursors sharedCustomCursors] 
cursorWithName:@"closedHandBarCursor"];
+}
+
++ (NSCursor *)textNoteCursor {
+    return [[SKCustomCursors sharedCustomCursors] 
cursorWithName:@"textNoteCursor"];
+}
+
++ (NSCursor *)anchoredNoteCursor {
+    return [[SKCustomCursors sharedCustomCursors] 
cursorWithName:@"anchoredNoteCursor"];
+}
+
++ (NSCursor *)circleNoteCursor {
+    return [[SKCustomCursors sharedCustomCursors] 
cursorWithName:@"circleNoteCursor"];
+}
+
++ (NSCursor *)squareNoteCursor {
+    return [[SKCustomCursors sharedCustomCursors] 
cursorWithName:@"squareNoteCursor"];
+}
+
++ (NSCursor *)highlightNoteCursor {
+    return [[SKCustomCursors sharedCustomCursors] 
cursorWithName:@"highlightNoteCursor"];
+}
+
++ (NSCursor *)underlineNoteCursor {
+    return [[SKCustomCursors sharedCustomCursors] 
cursorWithName:@"underlineNoteCursor"];
+}
+
++ (NSCursor *)strikeOutNoteCursor {
+    return [[SKCustomCursors sharedCustomCursors] 
cursorWithName:@"strikeOutNoteCursor"];
+}
+
++ (NSCursor *)lineNoteCursor {
+    return [[SKCustomCursors sharedCustomCursors] 
cursorWithName:@"lineNoteCursor"];
+}
+
++ (NSCursor *)inkNoteCursor {
+    return [[SKCustomCursors sharedCustomCursors] 
cursorWithName:@"inkNoteCursor"];
+}
+
++ (NSCursor *)emptyCursor {
+    static NSCursor *emptyCursor = nil;
+    if (nil == emptyCursor) {
+        NSImage *cursorImage = [[NSImage alloc] initWithSize:NSMakeSize(16.0, 
16.0)];
+        emptyCursor = [[NSCursor alloc] initWithImage:cursorImage 
hotSpot:NSMakePoint(8.0, 8.0)];
+    }
+    return emptyCursor;
+}
+
++ (NSCursor *)laserPointerCursorWithColor:(NSInteger)color {
+    static NSPointerArray *laserPointerCursors = nil;
+    if (laserPointerCursors == nil) {
+        laserPointerCursors = [NSPointerArray strongObjectsPointerArray];
+        [laserPointerCursors setCount:7];
+    }
+    NSCursor *cursor = (__bridge id)[laserPointerCursors pointerAtIndex:color 
% 7];
+    if (nil == cursor) {
+        NSImage *cursorImage = [NSImage laserPointerImageWithColor:color % 7];
+        cursor = [[NSCursor alloc] initWithImage:cursorImage 
hotSpot:NSMakePoint(0.5 * [cursorImage size].width, 0.5 * [cursorImage 
size].height)];
+        [laserPointerCursors replacePointerAtIndex:color % 7 
withPointer:(__bridge  void *)cursor];
+    }
+    return cursor;
+}
+
++ (NSCursor *)safeLaserPointerCursorWithColor:(NSInteger)color {
+    static NSPointerArray *laserPointerCursors = nil;
+    if (laserPointerCursors == nil) {
+        laserPointerCursors = [NSPointerArray strongObjectsPointerArray];
+        [laserPointerCursors setCount:7];
+    }
+    NSCursor *cursor = (__bridge id)[laserPointerCursors pointerAtIndex:color 
% 7];
+    if (nil == cursor) {
+        NSImage *cursorImage = [NSImage laserPointerImageWithColor:color % 7];
+        cursor = [[SKLaserPointerCursor alloc] initWithImage:cursorImage 
hotSpot:NSMakePoint(0.5 * [cursorImage size].width, 0.5 * [cursorImage 
size].height)];
+        [laserPointerCursors replacePointerAtIndex:color % 7 
withPointer:(__bridge  void *)cursor];
+    }
+    return cursor;
+}
+
+@end
+
+#pragma mark -
+
+static NSWindow *laserPointerWindow = nil;
+
+static inline void hideLaserPointer(void) {
+    if (laserPointerWindow) {
+        [laserPointerWindow close];
+        laserPointerWindow = nil;
+    }
+}
+
+@implementation SKLaserPointerCursor
+
+- (void)set {
+    if (original_set)
+        original_set([NSCursor emptyCursor], _cmd);
+    else
+        [[NSCursor emptyCursor] set];
     
-    NSDictionary *currentColors = currentCursorColors();
-    
-    if ([currentColors isEqualToDictionary:cursorColors] == NO) {
-        cursorColors = currentColors;
-        
+    NSPoint p = [NSEvent mouseLocation];
+    p = NSMakePoint(round(p.x), round(p.y));
+    if (laserPointerWindow) {
+        [[[[laserPointerWindow contentView] subviews] firstObject] 
setImage:[self image]];
+        [laserPointerWindow setFrame:SKRectFromCenterAndSize(p, 
[laserPointerWindow frame].size) display:YES];
+    } else {
+        NSImage *image = [self image];
+        CGFloat size = [[[SKCustomCursors sharedCustomCursors] 
universalaccessDefaults] doubleForKey:@"mouseDriverCursorSize"];
+        CGFloat s = 2.0 * round(0.5 * (size > 0.0 ? size : 1.0) * [image 
size].width);
+        laserPointerWindow = [[SKAnimatedBorderlessWindow alloc] 
initWithContentRect:SKRectFromCenterAndSquareSize(p, s)];
+        [laserPointerWindow setLevel:(NSWindowLevel)kCGCursorWindowLevel];
+        [laserPointerWindow addImageViewWithImage:image];
+        [laserPointerWindow setHidesOnDeactivate:YES];
+        [laserPointerWindow orderFrontRegardless];
+    }
+}
+
+@end
+
+#pragma mark -
+
+@implementation SKCustomCursors
+
+@dynamic universalaccessDefaults;
+
++ (SKCustomCursors *)sharedCustomCursors {
+    static SKCustomCursors *sharedCustomCursors = nil;
+    if (sharedCustomCursors == nil)
+        sharedCustomCursors = [[self alloc] init];
+    return sharedCustomCursors;
+}
+
+- (NSUserDefaults *)universalaccessDefaults {
+    if (universalaccessDefaults == nil) {
+        universalaccessDefaults = [[NSUserDefaults alloc] 
initWithSuiteName:@"com.apple.universalaccess"];
+        [universalaccessDefaults addObserver:self 
forKeyPath:@"cursorIsCustomized" options:0 
context:&SKUniversalAccessDefaultsObservationContext];
+        [universalaccessDefaults addObserver:self forKeyPath:@"cursorOutline" 
options:0 context:&SKUniversalAccessDefaultsObservationContext];
+        [universalaccessDefaults addObserver:self forKeyPath:@"cursorFill" 
options:0 context:&SKUniversalAccessDefaultsObservationContext];
+    }
+    return universalaccessDefaults;
+}
+
+- (NSCursor *)cursorWithName:(NSString *)name {
+    if (customCursors == nil) {
         customCursors = [NSMutableDictionary dictionary];
         
+        BOOL isCustomized = NO;
         NSColor *cursorOutline = [NSColor whiteColor];
         NSColor *cursorFill = [NSColor blackColor];
-        if ([cursorColors count] == 2) {
-            NSDictionary *color = [cursorColors objectForKey:@"cursorOutline"];
-            cursorOutline = [NSColor colorWithSRGBRed:[[color 
objectForKey:@"red"] doubleValue] green:[[color objectForKey:@"green"] 
doubleValue] blue:[[color objectForKey:@"blue"] doubleValue] alpha:[[color 
objectForKey:@"alpha"] doubleValue]] ?: cursorOutline;
-            color = [cursorColors objectForKey:@"cursorFill"];
-            cursorFill = [NSColor colorWithSRGBRed:[[color 
objectForKey:@"red"] doubleValue] green:[[color objectForKey:@"green"] 
doubleValue] blue:[[color objectForKey:@"blue"] doubleValue] alpha:[[color 
objectForKey:@"alpha"] doubleValue]] ?: cursorFill;
+        if (@available(macOS 12.0, *)) {
+            if ([[self universalaccessDefaults] 
boolForKey:@"cursorIsCustomized"]) {
+                isCustomized = YES;
+                NSDictionary *outlineDict = [[self universalaccessDefaults] 
dictionaryForKey:@"cursorOutline"];
+                NSDictionary *fillDict = [[self universalaccessDefaults] 
dictionaryForKey:@"cursorfill"];
+                if ([outlineDict count] == 4 && [fillDict count] == 4) {
+                    cursorOutline = [NSColor colorWithSRGBRed:[[outlineDict 
objectForKey:@"red"] doubleValue] green:[[outlineDict objectForKey:@"green"] 
doubleValue] blue:[[outlineDict objectForKey:@"blue"] doubleValue] 
alpha:[[outlineDict objectForKey:@"alpha"] doubleValue]] ?: cursorOutline;
+                    cursorFill = [NSColor colorWithSRGBRed:[[fillDict 
objectForKey:@"red"] doubleValue] green:[[fillDict objectForKey:@"green"] 
doubleValue] blue:[[fillDict objectForKey:@"blue"] doubleValue] 
alpha:[[fillDict objectForKey:@"alpha"] doubleValue]] ?: cursorFill;
+                }
+            }
         }
         
         NSImage *image;
@@ -344,7 +517,7 @@
             [NSBezierPath fillRect:NSMakeRect(2.0, 14.0, 28.0, 4.0)];
             NSBezierPath *path = [NSBezierPath openHandBezierPath];
             [NSGraphicsContext saveGraphicsState];
-            [([cursorColors count] ? cursorFill : cursorOutline) setFill];
+            [(isCustomized ? cursorFill : cursorOutline) setFill];
             [NSShadow setShadowWithWhite:0.0 alpha:0.5 blurRadius:1.0 
yOffset:-1.4];
             [path fill];
             [NSGraphicsContext restoreGraphicsState];
@@ -354,7 +527,7 @@
             [path lineToPoint:NSMakePoint(17.5348, 14.727)];
             [path moveToPoint:NSMakePoint(15.5547, 14.6953)];
             [path lineToPoint:NSMakePoint(15.5758, 11.2691)];
-            [([cursorColors count] ? cursorOutline : cursorFill) setStroke];
+            [(isCustomized ? cursorOutline : cursorFill) setStroke];
             [path setLineWidth:0.75];
             [path stroke];
         }];
@@ -371,7 +544,7 @@
             [NSBezierPath fillRect:NSMakeRect(2.0, 14.0, 28.0, 4.0)];
             NSBezierPath *path = [NSBezierPath closedHandBezierPath];
             [NSGraphicsContext saveGraphicsState];
-            [([cursorColors count] ? cursorFill : cursorOutline) setFill];
+            [(isCustomized ? cursorFill : cursorOutline) setFill];
             [NSShadow setShadowWithWhite:0.0 alpha:0.5 blurRadius:1.0 
yOffset:-1.4];
             [path fill];
             [NSGraphicsContext restoreGraphicsState];
@@ -381,7 +554,7 @@
             [path lineToPoint:NSMakePoint(17.5348, 14.727)];
             [path moveToPoint:NSMakePoint(15.5547, 14.6953)];
             [path lineToPoint:NSMakePoint(15.5758, 11.2691)];
-            [([cursorColors count] ? cursorOutline : cursorFill) setStroke];
+            [(isCustomized ? cursorOutline : cursorFill) setStroke];
             [path setLineWidth:0.75];
             [path stroke];
         }];
@@ -399,7 +572,7 @@
         [customCursors setObject:cursor forKey:@"anchoredNoteCursor"];
         
         image = [NSImage cursorCircleNoteImageWithOutlineColor:cursorOutline 
fillColor:cursorFill];
-        cursor = [[NSCursor alloc] initWithImage:image hotSpot:[[self 
arrowCursor] hotSpot]];
+        cursor = [[NSCursor alloc] initWithImage:image hotSpot:hotspot];
         [customCursors setObject:cursor forKey:@"circleNoteCursor"];
         
         image = [NSImage cursorSquareNoteImageWithOutlineColor:cursorOutline 
fillColor:cursorFill];
@@ -430,153 +603,12 @@
     return [customCursors objectForKey:name];
 }
 
-+ (NSCursor *)zoomInCursor {
-    return [self customCursorWithName:@"zoomInCursor"];
-}
-
-+ (NSCursor *)zoomOutCursor {
-    return [self customCursorWithName:@"zoomOutCursor"];
-}
-
-+ (NSCursor *)resizeDiagonal45Cursor {
-    if ([self 
respondsToSelector:@selector(_windowResizeNorthEastSouthWestCursor)]) {
-        return [NSCursor _windowResizeNorthEastSouthWestCursor];
+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object 
change:(NSDictionary *)change context:(void *)context {
+    if (context == &SKUniversalAccessDefaultsObservationContext) {
+        customCursors = nil;
     } else {
-        return [self customCursorWithName:@"resizeDiagonal45Cursor"];
+        [super observeValueForKeyPath:keyPath ofObject:object change:change 
context:context];
     }
 }
 
-+ (NSCursor *)resizeDiagonal135Cursor {
-    if ([self 
respondsToSelector:@selector(_windowResizeNorthWestSouthEastCursor)]) {
-        return [NSCursor _windowResizeNorthWestSouthEastCursor];
-    } else {
-        return [self customCursorWithName:@"resizeDiagonal135Cursor"];
-    }
-}
-
-+ (NSCursor *)cameraCursor {
-    return [self customCursorWithName:@"cameraCursor"];
-}
-
-+ (NSCursor *)openHandBarCursor {
-    return [self customCursorWithName:@"openHandBarCursor"];
-}
-
-+ (NSCursor *)closedHandBarCursor {
-    return [self customCursorWithName:@"closedHandBarCursor"];
-}
-
-+ (NSCursor *)textNoteCursor {
-    return [self customCursorWithName:@"textNoteCursor"];
-}
-
-+ (NSCursor *)anchoredNoteCursor {
-    return [self customCursorWithName:@"anchoredNoteCursor"];
-}
-
-+ (NSCursor *)circleNoteCursor {
-    return [self customCursorWithName:@"circleNoteCursor"];
-}
-
-+ (NSCursor *)squareNoteCursor {
-    return [self customCursorWithName:@"squareNoteCursor"];
-}
-
-+ (NSCursor *)highlightNoteCursor {
-    return [self customCursorWithName:@"highlightNoteCursor"];
-}
-
-+ (NSCursor *)underlineNoteCursor {
-    return [self customCursorWithName:@"underlineNoteCursor"];
-}
-
-+ (NSCursor *)strikeOutNoteCursor {
-    return [self customCursorWithName:@"strikeOutNoteCursor"];
-}
-
-+ (NSCursor *)lineNoteCursor {
-    return [self customCursorWithName:@"lineNoteCursor"];
-}
-
-+ (NSCursor *)inkNoteCursor {
-    return [self customCursorWithName:@"inkNoteCursor"];
-}
-
-+ (NSCursor *)emptyCursor {
-    static NSCursor *emptyCursor = nil;
-    if (nil == emptyCursor) {
-        NSImage *cursorImage = [[NSImage alloc] initWithSize:NSMakeSize(16.0, 
16.0)];
-        emptyCursor = [[NSCursor alloc] initWithImage:cursorImage 
hotSpot:NSMakePoint(8.0, 8.0)];
-    }
-    return emptyCursor;
-}
-
-+ (NSCursor *)laserPointerCursorWithColor:(NSInteger)color {
-    static NSPointerArray *laserPointerCursors = nil;
-    if (laserPointerCursors == nil) {
-        laserPointerCursors = [NSPointerArray strongObjectsPointerArray];
-        [laserPointerCursors setCount:7];
-    }
-    NSCursor *cursor = (__bridge id)[laserPointerCursors pointerAtIndex:color 
% 7];
-    if (nil == cursor) {
-        NSImage *cursorImage = [NSImage laserPointerImageWithColor:color % 7];
-        cursor = [[NSCursor alloc] initWithImage:cursorImage 
hotSpot:NSMakePoint(0.5 * [cursorImage size].width, 0.5 * [cursorImage 
size].height)];
-        [laserPointerCursors replacePointerAtIndex:color % 7 
withPointer:(__bridge  void *)cursor];
-    }
-    return cursor;
-}
-
-+ (NSCursor *)safeLaserPointerCursorWithColor:(NSInteger)color {
-    static NSPointerArray *laserPointerCursors = nil;
-    if (laserPointerCursors == nil) {
-        laserPointerCursors = [NSPointerArray strongObjectsPointerArray];
-        [laserPointerCursors setCount:7];
-    }
-    NSCursor *cursor = (__bridge id)[laserPointerCursors pointerAtIndex:color 
% 7];
-    if (nil == cursor) {
-        NSImage *cursorImage = [NSImage laserPointerImageWithColor:color % 7];
-        cursor = [[SKLaserPointerCursor alloc] initWithImage:cursorImage 
hotSpot:NSMakePoint(0.5 * [cursorImage size].width, 0.5 * [cursorImage 
size].height)];
-        [laserPointerCursors replacePointerAtIndex:color % 7 
withPointer:(__bridge  void *)cursor];
-    }
-    return cursor;
-}
-
 @end
-
-#pragma mark -
-
-static NSWindow *laserPointerWindow = nil;
-
-static inline void hideLaserPointer(void) {
-    if (laserPointerWindow) {
-        [laserPointerWindow close];
-        laserPointerWindow = nil;
-    }
-}
-
-@implementation SKLaserPointerCursor
-
-- (void)set {
-    if (original_set)
-        original_set([NSCursor emptyCursor], _cmd);
-    else
-        [[NSCursor emptyCursor] set];
-    
-    NSPoint p = [NSEvent mouseLocation];
-    p = NSMakePoint(round(p.x), round(p.y));
-    if (laserPointerWindow) {
-        [[[[laserPointerWindow contentView] subviews] firstObject] 
setImage:[self image]];
-        [laserPointerWindow setFrame:SKRectFromCenterAndSize(p, 
[laserPointerWindow frame].size) display:YES];
-    } else {
-        NSImage *image = [self image];
-        CGFloat size = [universalaccessDefaults() 
doubleForKey:@"mouseDriverCursorSize"];
-        CGFloat s = 2.0 * round(0.5 * (size > 0.0 ? size : 1.0) * [image 
size].width);
-        laserPointerWindow = [[SKAnimatedBorderlessWindow alloc] 
initWithContentRect:SKRectFromCenterAndSquareSize(p, s)];
-        [laserPointerWindow setLevel:(NSWindowLevel)kCGCursorWindowLevel];
-        [laserPointerWindow addImageViewWithImage:image];
-        [laserPointerWindow setHidesOnDeactivate:YES];
-        [laserPointerWindow orderFrontRegardless];
-    }
-}
-
-@end

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.



_______________________________________________
Skim-app-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/skim-app-commit

Reply via email to