summaryrefslogtreecommitdiff
path: root/src/Fl_cocoa.mm
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2014-06-16 11:17:57 +0000
committerPierre Ossman <ossman@cendio.se>2014-06-16 11:17:57 +0000
commit332dc1b7acfedbf80b71cc6f538a14f24d435df3 (patch)
treef690751dd9b592b2b00b4d54c803f98073d74b97 /src/Fl_cocoa.mm
parentb4013ef60225b91af17d664b0938a074b7115202 (diff)
Add method to set any custom cursor, based on a Fl_RGB_Image object.
Also change our fallback cursors to use this method, so that fallback cursors are handled in a platform independent manner. STR #2660. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@10196 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src/Fl_cocoa.mm')
-rw-r--r--src/Fl_cocoa.mm174
1 files changed, 112 insertions, 62 deletions
diff --git a/src/Fl_cocoa.mm b/src/Fl_cocoa.mm
index c9fe2db44..722ece9cd 100644
--- a/src/Fl_cocoa.mm
+++ b/src/Fl_cocoa.mm
@@ -97,7 +97,6 @@ Fl_Display_Device *Fl_Display_Device::_display = new Fl_Display_Device(new Fl_Qu
// public variables
CGContextRef fl_gc = 0;
-NSCursor *fl_default_cursor;
void *fl_capture = 0; // (NSWindow*) we need this to compensate for a missing(?) mouse capture
bool fl_show_iconic; // true if called from iconize() - shows the next created window in collapsed state
//int fl_disable_transient_for; // secret method of removing TRANSIENT_FOR
@@ -1413,8 +1412,6 @@ void fl_open_display() {
dequeue:YES];
while (ign_event);
- fl_default_cursor = [NSCursor arrowCursor];
-
// bring the application into foreground without a 'CARB' resource
Boolean same_psn;
ProcessSerialNumber cur_psn, front_psn;
@@ -1832,6 +1829,7 @@ static void cocoaKeyboardHandler(NSEvent *theEvent)
- (void)drawRect:(NSRect)rect;
- (BOOL)acceptsFirstResponder;
- (BOOL)acceptsFirstMouse:(NSEvent*)theEvent;
+- (void)resetCursorRects;
- (BOOL)performKeyEquivalent:(NSEvent*)theEvent;
- (void)mouseUp:(NSEvent *)theEvent;
- (void)rightMouseUp:(NSEvent *)theEvent;
@@ -1921,6 +1919,16 @@ static void cocoaKeyboardHandler(NSEvent *theEvent)
Fl_Window *first = Fl::first_window();
return (first == w || !first->modal());
}
+- (void)resetCursorRects {
+ Fl_Window *w = [(FLWindow*)[self window] getFl_Window];
+ Fl_X *i = Fl_X::i(w);
+ // We have to have at least one cursor rect for invalidateCursorRectsForView
+ // to work, hence the "else" clause.
+ if (i->cursor)
+ [self addCursorRect:[self visibleRect] cursor:(NSCursor*)i->cursor];
+ else
+ [self addCursorRect:[self visibleRect] cursor:[NSCursor arrowCursor]];
+}
- (void)mouseUp:(NSEvent *)theEvent {
cocoaMouseHandler(theEvent);
}
@@ -2367,7 +2375,7 @@ void Fl_X::make(Fl_Window* w)
x->other_xid = 0;
x->region = 0;
x->subRegion = 0;
- x->cursor = fl_default_cursor;
+ x->cursor = NULL;
x->gc = 0; // stay 0 for Quickdraw; fill with CGContext for Quartz
w->set_visible();
Fl_Window *win = w->window();
@@ -2464,7 +2472,7 @@ void Fl_X::make(Fl_Window* w)
x->other_xid = 0; // room for doublebuffering image map. On OS X this is only used by overlay windows
x->region = 0;
x->subRegion = 0;
- x->cursor = fl_default_cursor;
+ x->cursor = NULL;
x->xidChildren = 0;
x->xidNext = 0;
x->gc = 0;
@@ -3148,6 +3156,10 @@ void Fl_X::map() {
Fl_X::relink(w, w->window() );
w->redraw();
}
+ if (cursor) {
+ [(NSCursor*)cursor release];
+ cursor = NULL;
+ }
}
void Fl_X::unmap() {
@@ -3282,68 +3294,106 @@ CFDataRef Fl_X::CGBitmapContextToTIFF(CGContextRef c)
return (CFDataRef)tiff;
}
-static NSCursor *PrepareCursor(NSCursor *cursor, CGContextRef (*f)() )
+int Fl_X::set_cursor(Fl_Cursor c)
{
- if (cursor == nil) {
- CGContextRef c = f();
- NSImage *image = CGBitmapContextToNSImage(c);
- fl_delete_offscreen( (Fl_Offscreen)c );
- NSPoint pt = {[image size].width/2, [image size].height/2};
- cursor = [[NSCursor alloc] initWithImage:image hotSpot:pt];
+ if (cursor) {
+ [(NSCursor*)cursor release];
+ cursor = NULL;
}
- return cursor;
-}
-void Fl_X::set_cursor(Fl_Cursor c)
-{
- NSCursor *icrsr;
switch (c) {
- case FL_CURSOR_CROSS: icrsr = [NSCursor crosshairCursor]; break;
- case FL_CURSOR_WAIT:
- static NSCursor *watch = nil;
- watch = PrepareCursor(watch, &Fl_X::watch_cursor_image);
- icrsr = watch;
- break;
- case FL_CURSOR_INSERT: icrsr = [NSCursor IBeamCursor]; break;
- case FL_CURSOR_N: icrsr = [NSCursor resizeUpCursor]; break;
- case FL_CURSOR_S: icrsr = [NSCursor resizeDownCursor]; break;
- case FL_CURSOR_NS: icrsr = [NSCursor resizeUpDownCursor]; break;
- case FL_CURSOR_HELP:
- static NSCursor *help = nil;
- help = PrepareCursor(help, &Fl_X::help_cursor_image);
- icrsr = help;
- break;
- case FL_CURSOR_HAND: icrsr = [NSCursor pointingHandCursor]; break;
- case FL_CURSOR_MOVE: icrsr = [NSCursor openHandCursor]; break;
- case FL_CURSOR_NE:
- case FL_CURSOR_SW:
- case FL_CURSOR_NESW:
- static NSCursor *nesw = nil;
- nesw = PrepareCursor(nesw, &Fl_X::nesw_cursor_image);
- icrsr = nesw;
- break;
- case FL_CURSOR_E: icrsr = [NSCursor resizeRightCursor]; break;
- case FL_CURSOR_W: icrsr = [NSCursor resizeLeftCursor]; break;
- case FL_CURSOR_WE: icrsr = [NSCursor resizeLeftRightCursor]; break;
- case FL_CURSOR_SE:
- case FL_CURSOR_NW:
- case FL_CURSOR_NWSE:
- static NSCursor *nwse = nil;
- nwse = PrepareCursor(nwse, &Fl_X::nwse_cursor_image);
- icrsr = nwse;
- break;
- case FL_CURSOR_NONE:
- static NSCursor *none = nil;
- none = PrepareCursor(none, &Fl_X::none_cursor_image);
- icrsr = none;
- break;
- case FL_CURSOR_ARROW:
- case FL_CURSOR_DEFAULT:
- default: icrsr = [NSCursor arrowCursor];
- break;
+ case FL_CURSOR_ARROW: cursor = [NSCursor arrowCursor]; break;
+ case FL_CURSOR_CROSS: cursor = [NSCursor crosshairCursor]; break;
+ case FL_CURSOR_INSERT: cursor = [NSCursor IBeamCursor]; break;
+ case FL_CURSOR_HAND: cursor = [NSCursor pointingHandCursor]; break;
+ case FL_CURSOR_MOVE: cursor = [NSCursor openHandCursor]; break;
+ case FL_CURSOR_NS: cursor = [NSCursor resizeUpDownCursor]; break;
+ case FL_CURSOR_WE: cursor = [NSCursor resizeLeftRightCursor]; break;
+ case FL_CURSOR_N: cursor = [NSCursor resizeUpCursor]; break;
+ case FL_CURSOR_E: cursor = [NSCursor resizeRightCursor]; break;
+ case FL_CURSOR_W: cursor = [NSCursor resizeLeftCursor]; break;
+ case FL_CURSOR_S: cursor = [NSCursor resizeDownCursor]; break;
+ default:
+ return 0;
+ }
+
+ [(NSCursor*)cursor retain];
+
+ [(NSWindow*)xid invalidateCursorRectsForView:[(NSWindow*)xid contentView]];
+
+ return 1;
+}
+
+int Fl_X::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) {
+ if (cursor) {
+ [(NSCursor*)cursor release];
+ cursor = NULL;
+ }
+
+ if ((hotx < 0) || (hotx >= image->w()))
+ return 0;
+ if ((hoty < 0) || (hoty >= image->h()))
+ return 0;
+
+ // OS X >= 10.6 can create a NSImage from a CGImage, but we need to
+ // support older versions, hence this pesky handling.
+
+ NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc]
+ initWithBitmapDataPlanes:NULL
+ pixelsWide:image->w()
+ pixelsHigh:image->h()
+ bitsPerSample:8
+ samplesPerPixel:image->d()
+ hasAlpha:!(image->d() & 1)
+ isPlanar:NO
+ colorSpaceName:(image->d()<=2) ? NSDeviceWhiteColorSpace : NSDeviceRGBColorSpace
+ bytesPerRow:(image->w() * image->d())
+ bitsPerPixel:(image->d()*8)];
+
+ // Alpha needs to be premultiplied for this format
+
+ const uchar *i = (const uchar*)*image->data();
+ unsigned char *o = [bitmap bitmapData];
+ for (int y = 0;y < image->h();y++) {
+ if (image->d() & 1) {
+ for (int x = 0;x < image->w();x++) {
+ unsigned int alpha;
+ if (image->d() == 4) {
+ alpha = i[3];
+ *o++ = (unsigned char)((unsigned int)*i++ * alpha / 255);
+ *o++ = (unsigned char)((unsigned int)*i++ * alpha / 255);
+ }
+
+ alpha = i[1];
+ *o++ = (unsigned char)((unsigned int)*i++ * alpha / 255);
+ *o++ = alpha;
+ i++;
+ }
+ } else {
+ // No alpha, so we can just copy everything directly.
+ int len = image->w() * image->d();
+ memcpy(o, i, len);
+ o += len;
+ i += len;
+ }
+ i += image->ld();
}
- [icrsr set];
- cursor = icrsr;
+
+ NSImage *nsimage = [[NSImage alloc]
+ initWithSize:NSMakeSize(image->w(), image->h())];
+
+ [nsimage addRepresentation:bitmap];
+
+ cursor = [[NSCursor alloc]
+ initWithImage:nsimage
+ hotSpot:NSMakePoint(hotx, hoty)];
+
+ [(NSWindow*)xid invalidateCursorRectsForView:[(NSWindow*)xid contentView]];
+
+ [bitmap release];
+ [nsimage release];
+
+ return 1;
}
@interface FLaboutItemTarget : NSObject