-2

ALL,

On Windows cursors are indicated by the cur file extension. Is there something similar for OSX Cocoa application?

Is there a way in XCode to edit such files, just like in MSVC there is some basic graphical editor?

Also, is there a special API which will allow loading such files on Cocoa? Or I can just load them as images?

TIA!!

EDIT:

In the meantime I think I found a good solution that will satisfy my needs

NSString *path;
NSBundle *bundle = [NSBundle mainBundle];
NSString *path = [bundle pathForResource:cursor_file ofType:@"cur"];
if( path )
{
    CGImageSourceRef image = CGImageSourceCreateWithURL( path, nil );
    CFDictionaryRef properties =

CGImageSourceCopyPropertiesAtIndex( image, 0, nil ); NSInteger x = properties["hotspotX"]; NSInteger y = properties["hotspotY"]; }

Except that it doesn't compile:

I need to import the file where CGImageSourceCreateWithURL() is declared, and I need to fix the last 2 lines, because the array subscript can't be strings.

Could someone help, please?

Igor
  • 5,620
  • 11
  • 51
  • 103
  • How about `NSCursor`? – Willeke Apr 29 '22 at 22:34
  • @Willeke, how do I create one? And is there a way to load fro Resource folder? I didnt find any download API... I want to use custom cursor loaded from resources – Igor Apr 29 '22 at 23:41
  • @Willeke, or maybe there is a way to convert Windows cursor to Mac cursor and se it in my application? – Igor Apr 30 '22 at 00:03
  • Does this answer your question? [How to use NSCursor to display custom cursor](https://stackoverflow.com/questions/7608733/how-to-use-nscursor-to-display-custom-cursor) – Willeke Apr 30 '22 at 10:36
  • @Willeke, it does, to some extent. I still need to know what type of file I can use - png, jpg, svg, cur or maybe osx have some specific cursor type? And how to create one? And if I can oppen one of the predefined cursors in that editor. My cursor is modified hand cursor. So if I can open that icon, I can clone it with my modification. – Igor Apr 30 '22 at 13:40
  • @Willeke, can you help me fix compiler errors? I made some edits for OP... – Igor May 02 '22 at 02:44
  • You can't use subscripts on `CFDictionaryRef`. Bridge `properties` to `NSDictionary` or use a `CFDictionary` function. – Willeke May 02 '22 at 13:53
  • @Willeke, how? And what do I import for the first question? – Igor May 02 '22 at 14:14
  • See [Casting a CFDictionaryRef to NSDictionary?](https://stackoverflow.com/questions/7018497/casting-a-cfdictionaryref-to-nsdictionary) – Willeke May 02 '22 at 16:11

1 Answers1

0

The following source code will create a custom NSCursor in Xcode from a .cur image, after retrieving its “hotspot” coordinates from the file located in the app bundle Resource folder. Replace the contents of the main.m file with the code below and delete the pre-supplied AppDelegate files to avoid duplicate symbols. You will need to copy/paste the .cur file into the Xcode project folder and also drag and drop it into the Project navigator. Xcode will not automatically place this file into the Resources folder of your application bundle (unlike a .png file), so copy/paste it there as well after you have compiled the app. Reference: Hotspot in Windows cursor .cur loaded by NSImage?

#import <Cocoa/Cocoa.h>

@interface AppDelegate : NSObject <NSApplicationDelegate> {
  NSWindow *window;
  CGFloat x,y;
}
@end

@implementation AppDelegate

- (void) customCursor {
    // **** Get HotSpot from .cur file **** //
    NSBundle *bundle = [NSBundle mainBundle];
    NSURL *url = [bundle URLForImageResource:@"myCursor.cur"];
    if( url ) {
    CGImageSourceRef image = CGImageSourceCreateWithURL( (__bridge CFURLRef)url, nil );
    NSDictionary *properties = (__bridge NSDictionary *)CGImageSourceCopyPropertiesAtIndex( image, 0, nil );
        x = [[properties objectForKey:@"hotspotX"]floatValue];
        y = [[properties objectForKey:@"hotspotY"]floatValue];
        CFBridgingRelease(image);
        CFBridgingRelease((__bridge CFTypeRef _Nullable)(properties));
    }
    NSCursor *customCursor = [[NSCursor alloc] initWithImage:[NSImage imageNamed:@"myCursor.cur"] hotSpot: NSMakePoint( x, y) ];
    [customCursor set];
    NSLog(@"x = %0.02f",x);
    NSLog(@"y = %0.02f",y);
    
}

- (void) arrowCursor {
 [[NSCursor arrowCursor] set];
}

- (void) buildMenu {
 NSMenu *menubar = [NSMenu new];
 [NSApp setMainMenu:menubar];
 NSMenuItem *menuBarItem = [NSMenuItem new];
 [menubar addItem:menuBarItem];
 NSMenu *appMenu = [NSMenu new];
 [menuBarItem setSubmenu:appMenu];
 [appMenu addItemWithTitle:@"Quit" action:@selector(terminate:) keyEquivalent:@"q"];
}

- (void) buildWnd {

 #define _wndW  500
 #define _wndH  250

 window = [[NSWindow alloc] initWithContentRect: NSMakeRect( 0, 0, _wndW, _wndH )  styleMask: NSWindowStyleMaskTitled | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskClosable backing: NSBackingStoreBuffered defer: NO];
 [window center];
 [window setTitle: @"Custom cursor"];
 [window makeKeyAndOrderFront: nil];

// **** Button 1 **** //
 NSButton *myBtn =[[NSButton alloc]initWithFrame:NSMakeRect( 30, 30, 135, 30 )];
 [myBtn setBezelStyle:NSBezelStyleRounded ];
 [myBtn setTitle: @"Custom Cursor"];
 [myBtn setAction: @selector (customCursor)];
 [[window contentView] addSubview: myBtn];

// **** Button 2 **** //
 NSButton *myBtn2 =[[NSButton alloc]initWithFrame:NSMakeRect( 190, 30, 135, 30 )];
 [myBtn2 setBezelStyle:NSBezelStyleRounded ];
 [myBtn2 setTitle: @"Arrow Cursor"];
 [myBtn2 setAction: @selector (arrowCursor)];
 [[window contentView] addSubview: myBtn2];

// **** Quit btn **** //
 NSButton *quitBtn = [[NSButton alloc]initWithFrame:NSMakeRect( _wndW - 50, 10, 40, 40 )];
 [quitBtn setBezelStyle:NSBezelStyleCircular ];
 [quitBtn setTitle: @"Q" ];
 [quitBtn setAction:@selector(terminate:)];
 [[window contentView] addSubview: quitBtn];
}

- (void) applicationWillFinishLaunching: (NSNotification *)notification {
 [self buildMenu];
 [self buildWnd];
}

@end

int main() {
NSApplication *application = [NSApplication sharedApplication];
AppDelegate *appDelegate = [[AppDelegate alloc] init];
[application setDelegate:appDelegate];
[application run];
return 0;
}

apodidae
  • 1,988
  • 2
  • 5
  • 9
  • thx for that. Just one question - does this mean that by default OSX have `png` as a cursor file? And there is no special cursor file format/extension? – Igor Apr 30 '22 at 22:05
  • There is no special format/extension for a MacOS cursor. NSCursor is an NSObject which may be initialized with an image of the user's choosing. The image has no default file type; possibilities include .png, .tiff, .icns and likely others that I have not tested. You'll have to experiment with other file types if you want something special. – apodidae May 01 '22 at 00:33
  • ok. understood. There is no special format for OSX cursor. So I think I will try to use the cur file I made on Windows. – Igor May 01 '22 at 00:44
  • I made some edits to the OP. Can you help me fix the errors? – Igor May 02 '22 at 02:42
  • It might be easier to convert the .cur to a .png; there are online services to do this (I have no experience). – apodidae May 02 '22 at 05:14
  • probably. But I' trying to decrease number of files in my project. And most importantly eliminate duplicates... – Igor May 02 '22 at 05:20
  • I just added a .cur file to my Xcode project and installed the image on the custom cursor using the code above. It worked ok; no need to convert to .png. – apodidae May 02 '22 at 14:02
  • did you change the file extension to `cur`? Also - how do you now where the hotspot is for the cursor? – Igor May 02 '22 at 14:13
  • The file had a .cur extension when I downloaded it. You'll have to change the name of the file in the demo that I posted. Hotspot is wherever you set it in the code that I posted. Xcode does not automatically put the file in your app's bundle Resource folder (like it does with png file) so you have to manually copy/paste it. – apodidae May 02 '22 at 15:05
  • I think my code is better. It gets the hotspot from the image itself and I ca. Use any extension I want. Your hardworking it which means it is not generic. – Igor May 02 '22 at 16:36
  • Original answer edited to include retrieval of hotspot coordinates from app bundle/Resource .cur file. – apodidae May 02 '22 at 22:24
  • @aptodidae,I accepted your answer with the big thank you. – Igor May 06 '22 at 15:57