2011-09-06 10:10:43 -04:00
|
|
|
/*
|
2011-10-12 13:40:35 -04:00
|
|
|
* Cocoa's event loop must be in main thread.
|
2011-09-06 10:10:43 -04:00
|
|
|
*/
|
|
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
#define Cursor OSXCursor
|
2011-09-06 10:10:43 -04:00
|
|
|
#define Point OSXPoint
|
|
|
|
|
#define Rect OSXRect
|
|
|
|
|
|
|
|
|
|
#import <Cocoa/Cocoa.h>
|
|
|
|
|
|
|
|
|
|
#undef Cursor
|
2011-10-12 13:40:35 -04:00
|
|
|
#undef Point
|
|
|
|
|
#undef Rect
|
2011-09-06 10:10:43 -04:00
|
|
|
|
|
|
|
|
#include <u.h>
|
|
|
|
|
#include <libc.h>
|
2011-10-12 13:40:35 -04:00
|
|
|
#include "cocoa-thread.h"
|
2011-09-06 10:10:43 -04:00
|
|
|
#include <draw.h>
|
|
|
|
|
#include <memdraw.h>
|
|
|
|
|
#include <keyboard.h>
|
|
|
|
|
#include <cursor.h>
|
|
|
|
|
#include "cocoa-screen.h"
|
|
|
|
|
#include "osx-keycodes.h"
|
|
|
|
|
#include "devdraw.h"
|
|
|
|
|
#include "glendapng.h"
|
|
|
|
|
|
|
|
|
|
AUTOFRAMEWORK(Cocoa)
|
|
|
|
|
|
|
|
|
|
#define panic sysfatal
|
|
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
int usegestures = 0;
|
2011-09-19 08:58:59 -04:00
|
|
|
int useoldfullscreen = 0;
|
2011-10-23 18:47:29 -04:00
|
|
|
int usebigarrow = 0;
|
|
|
|
|
|
|
|
|
|
extern Cursor bigarrow;
|
|
|
|
|
|
|
|
|
|
void setcursor0(Cursor *c);
|
2011-09-06 10:10:43 -04:00
|
|
|
|
|
|
|
|
void
|
|
|
|
|
usage(void)
|
|
|
|
|
{
|
|
|
|
|
fprint(2, "usage: devdraw (don't run directly)\n");
|
2011-10-12 13:40:35 -04:00
|
|
|
threadexitsall("usage");
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
|
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
@interface appdelegate : NSObject
|
|
|
|
|
@end
|
|
|
|
|
|
2011-09-06 10:10:43 -04:00
|
|
|
void
|
2011-10-12 13:40:35 -04:00
|
|
|
threadmain(int argc, char **argv)
|
2011-09-06 10:10:43 -04:00
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* Move the protocol off stdin/stdout so that
|
|
|
|
|
* any inadvertent prints don't screw things up.
|
|
|
|
|
*/
|
|
|
|
|
dup(0,3);
|
|
|
|
|
dup(1,4);
|
|
|
|
|
close(0);
|
|
|
|
|
close(1);
|
|
|
|
|
open("/dev/null", OREAD);
|
|
|
|
|
open("/dev/null", OWRITE);
|
|
|
|
|
|
|
|
|
|
ARGBEGIN{
|
2011-10-12 13:40:35 -04:00
|
|
|
case 'D': /* for good ps -a listings */
|
|
|
|
|
break;
|
|
|
|
|
case 'f':
|
|
|
|
|
useoldfullscreen = 1;
|
|
|
|
|
break;
|
|
|
|
|
case 'g':
|
|
|
|
|
usegestures = 1;
|
2011-09-06 10:10:43 -04:00
|
|
|
break;
|
2011-10-23 18:47:29 -04:00
|
|
|
case 'b':
|
|
|
|
|
usebigarrow = 1;
|
|
|
|
|
break;
|
2011-09-06 10:10:43 -04:00
|
|
|
default:
|
|
|
|
|
usage();
|
|
|
|
|
}ARGEND
|
|
|
|
|
|
2011-10-03 18:16:09 -04:00
|
|
|
if(OSX_VERSION < 100700)
|
|
|
|
|
[NSAutoreleasePool new];
|
|
|
|
|
|
2011-10-23 18:47:29 -04:00
|
|
|
// Reset cursor to ensure we start
|
|
|
|
|
// with bigarrow.
|
|
|
|
|
if(usebigarrow)
|
|
|
|
|
setcursor0(nil);
|
|
|
|
|
|
2011-09-06 10:10:43 -04:00
|
|
|
[NSApplication sharedApplication];
|
|
|
|
|
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
|
|
|
|
[NSApp setDelegate:[appdelegate new]];
|
|
|
|
|
[NSApp activateIgnoringOtherApps:YES];
|
|
|
|
|
[NSApp run];
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
#define WIN win.ofs[win.isofs]
|
|
|
|
|
|
|
|
|
|
struct
|
|
|
|
|
{
|
|
|
|
|
NSWindow *ofs[2]; /* ofs[1] for old fullscreen; ofs[0] else */
|
|
|
|
|
int isofs;
|
2011-11-08 13:23:55 -05:00
|
|
|
int isnfs;
|
2011-10-12 13:40:35 -04:00
|
|
|
NSView *content;
|
|
|
|
|
char *rectstr;
|
2011-09-19 08:58:59 -04:00
|
|
|
NSBitmapImageRep *img;
|
2011-10-12 13:40:35 -04:00
|
|
|
NSRect flushrect;
|
|
|
|
|
int needflush;
|
|
|
|
|
NSCursor *cursor;
|
|
|
|
|
QLock cursorl;
|
2011-09-19 08:58:59 -04:00
|
|
|
} win;
|
|
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
struct
|
|
|
|
|
{
|
|
|
|
|
int kalting;
|
|
|
|
|
int kbuttons;
|
|
|
|
|
int mbuttons;
|
|
|
|
|
Point mpos;
|
|
|
|
|
int mscroll;
|
|
|
|
|
int undo;
|
|
|
|
|
int touchevent;
|
|
|
|
|
} in;
|
|
|
|
|
|
2011-11-08 13:23:55 -05:00
|
|
|
static void hidebars(int);
|
2011-09-19 08:58:59 -04:00
|
|
|
static void drawimg(void);
|
|
|
|
|
static void flushwin(void);
|
2011-10-12 13:40:35 -04:00
|
|
|
static void followzoombutton(NSRect);
|
2011-09-06 10:10:43 -04:00
|
|
|
static void getmousepos(void);
|
2011-09-19 08:58:59 -04:00
|
|
|
static void makeicon(void);
|
|
|
|
|
static void makemenu(void);
|
|
|
|
|
static void makewin(void);
|
2011-10-03 18:16:09 -04:00
|
|
|
static void sendmouse(void);
|
2011-09-26 08:19:56 -07:00
|
|
|
static void togglefs(void);
|
2011-09-06 10:10:43 -04:00
|
|
|
|
|
|
|
|
@implementation appdelegate
|
|
|
|
|
- (void)applicationDidFinishLaunching:(id)arg
|
|
|
|
|
{
|
2011-09-19 08:58:59 -04:00
|
|
|
makeicon();
|
|
|
|
|
makemenu();
|
|
|
|
|
[NSApplication
|
|
|
|
|
detachDrawingThread:@selector(callservep9p:)
|
|
|
|
|
toTarget:[self class] withObject:nil];
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
2011-09-19 08:58:59 -04:00
|
|
|
- (void)windowDidBecomeKey:(id)arg
|
2011-09-06 10:10:43 -04:00
|
|
|
{
|
2011-11-08 13:23:55 -05:00
|
|
|
if(win.isnfs || win.isofs)
|
|
|
|
|
hidebars(1);
|
|
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
in.touchevent = 0;
|
|
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
getmousepos();
|
2011-10-03 18:16:09 -04:00
|
|
|
sendmouse();
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
|
|
|
|
- (void)windowDidResize:(id)arg
|
|
|
|
|
{
|
2011-09-19 08:58:59 -04:00
|
|
|
getmousepos();
|
2011-10-03 18:16:09 -04:00
|
|
|
sendmouse();
|
2011-09-19 08:58:59 -04:00
|
|
|
}
|
|
|
|
|
- (void)windowDidEndLiveResize:(id)arg
|
|
|
|
|
{
|
2011-10-12 13:40:35 -04:00
|
|
|
[win.content display];
|
2011-09-26 08:19:56 -07:00
|
|
|
}
|
|
|
|
|
- (void)windowDidChangeScreen:(id)arg
|
|
|
|
|
{
|
2011-11-08 13:23:55 -05:00
|
|
|
if(win.isnfs || win.isofs)
|
|
|
|
|
hidebars(1);
|
2011-10-12 13:40:35 -04:00
|
|
|
[win.ofs[1] setFrame:[[WIN screen] frame] display:YES];
|
|
|
|
|
}
|
|
|
|
|
- (BOOL)windowShouldZoom:(id)arg toFrame:(NSRect)r
|
|
|
|
|
{
|
|
|
|
|
followzoombutton(r);
|
|
|
|
|
return YES;
|
2011-09-26 08:19:56 -07:00
|
|
|
}
|
2011-09-06 10:10:43 -04:00
|
|
|
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(id)arg
|
|
|
|
|
{
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
2011-11-08 13:23:55 -05:00
|
|
|
- (void)windowDidEnterFullScreen:(id)arg{ win.isnfs = 1; hidebars(1);}
|
|
|
|
|
- (void)windowWillExitFullScreen:(id)arg{ win.isnfs = 0; hidebars(0);}
|
|
|
|
|
- (void)windowDidExitFullScreen:(id)arg
|
|
|
|
|
{
|
|
|
|
|
NSButton *b;
|
|
|
|
|
|
|
|
|
|
b = [WIN standardWindowButton:NSWindowMiniaturizeButton];
|
|
|
|
|
|
|
|
|
|
if([b isEnabled] == 0){
|
|
|
|
|
[b setEnabled:YES];
|
|
|
|
|
hidebars(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
+ (void)callservep9p:(id)arg
|
2011-09-06 10:10:43 -04:00
|
|
|
{
|
|
|
|
|
servep9p();
|
|
|
|
|
[NSApp terminate:self];
|
|
|
|
|
}
|
2011-09-19 08:58:59 -04:00
|
|
|
+ (void)calldrawimg:(id)arg{ drawimg();}
|
|
|
|
|
+ (void)callflushwin:(id)arg{ flushwin();}
|
|
|
|
|
+ (void)callmakewin:(id)arg{ makewin();}
|
2011-10-23 18:47:29 -04:00
|
|
|
+ (void)callsetcursor0:(id)arg{ setcursor0([[arg autorelease] pointerValue]);}
|
2011-09-26 08:19:56 -07:00
|
|
|
- (void)calltogglefs:(id)arg{ togglefs();}
|
2011-09-06 10:10:43 -04:00
|
|
|
@end
|
|
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
static Memimage* initimg(void);
|
2011-09-19 08:58:59 -04:00
|
|
|
|
2011-09-06 10:10:43 -04:00
|
|
|
Memimage*
|
|
|
|
|
attachscreen(char *label, char *winsize)
|
|
|
|
|
{
|
|
|
|
|
static int first = 1;
|
|
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
if(first)
|
|
|
|
|
first = 0;
|
|
|
|
|
else
|
2011-09-06 10:10:43 -04:00
|
|
|
panic("attachscreen called twice");
|
|
|
|
|
|
|
|
|
|
if(label == nil)
|
|
|
|
|
label = "gnot a label";
|
|
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
win.rectstr = strdup(winsize);
|
2011-09-06 10:10:43 -04:00
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
/*
|
|
|
|
|
* Create window in main thread, else no cursor
|
|
|
|
|
* change while resizing.
|
|
|
|
|
*/
|
2011-09-06 10:10:43 -04:00
|
|
|
[appdelegate
|
|
|
|
|
performSelectorOnMainThread:@selector(callmakewin:)
|
|
|
|
|
withObject:nil
|
|
|
|
|
waitUntilDone:YES];
|
|
|
|
|
// makewin();
|
|
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
kicklabel(label);
|
2011-10-12 13:40:35 -04:00
|
|
|
return initimg();
|
2011-09-19 08:58:59 -04:00
|
|
|
}
|
2011-09-06 10:10:43 -04:00
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
@interface appview : NSView
|
|
|
|
|
@end
|
2011-09-06 10:10:43 -04:00
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
@interface appwin : NSWindow
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
@implementation appwin
|
|
|
|
|
- (NSTimeInterval)animationResizeTime:(NSRect)r
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
2011-09-26 08:19:56 -07:00
|
|
|
- (BOOL)canBecomeKeyWindow
|
|
|
|
|
{
|
2011-10-12 13:40:35 -04:00
|
|
|
return YES; /* else no keyboard with old fullscreen */
|
2011-09-26 08:19:56 -07:00
|
|
|
}
|
2011-09-19 08:58:59 -04:00
|
|
|
@end
|
2011-09-06 10:10:43 -04:00
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
enum
|
|
|
|
|
{
|
|
|
|
|
Winstyle = NSTitledWindowMask
|
|
|
|
|
| NSClosableWindowMask
|
|
|
|
|
| NSMiniaturizableWindowMask
|
|
|
|
|
| NSResizableWindowMask
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
makewin(void)
|
2011-09-06 10:10:43 -04:00
|
|
|
{
|
|
|
|
|
NSRect r, sr;
|
2011-10-12 13:40:35 -04:00
|
|
|
NSWindow *w;
|
2011-09-06 10:10:43 -04:00
|
|
|
Rectangle wr;
|
2011-09-19 08:58:59 -04:00
|
|
|
char *s;
|
2011-10-12 13:40:35 -04:00
|
|
|
int i, set;
|
2011-09-06 10:10:43 -04:00
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
s = win.rectstr;
|
2011-09-26 08:19:56 -07:00
|
|
|
sr = [[NSScreen mainScreen] frame];
|
2011-09-06 10:10:43 -04:00
|
|
|
|
|
|
|
|
if(s && *s){
|
2011-09-19 08:58:59 -04:00
|
|
|
if(parsewinsize(s, &wr, &set) < 0)
|
2011-09-06 10:10:43 -04:00
|
|
|
sysfatal("%r");
|
|
|
|
|
}else{
|
|
|
|
|
wr = Rect(0, 0, sr.size.width*2/3, sr.size.height*2/3);
|
2011-09-19 08:58:59 -04:00
|
|
|
set = 0;
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
|
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
/*
|
|
|
|
|
* The origin is the left bottom corner for Cocoa.
|
|
|
|
|
*/
|
|
|
|
|
r.origin.y = sr.size.height-wr.max.y;
|
|
|
|
|
r = NSMakeRect(wr.min.x, r.origin.y, Dx(wr), Dy(wr));
|
|
|
|
|
r = [NSWindow contentRectForFrameRect:r
|
|
|
|
|
styleMask:Winstyle];
|
|
|
|
|
|
|
|
|
|
w = [[appwin alloc]
|
2011-09-06 10:10:43 -04:00
|
|
|
initWithContentRect:r
|
2011-09-19 08:58:59 -04:00
|
|
|
styleMask:Winstyle
|
2011-09-26 08:19:56 -07:00
|
|
|
backing:NSBackingStoreBuffered defer:NO];
|
2011-09-19 08:58:59 -04:00
|
|
|
if(!set)
|
2011-10-12 13:40:35 -04:00
|
|
|
[w center];
|
2011-09-06 10:10:43 -04:00
|
|
|
#if OSX_VERSION >= 100700
|
2011-10-12 13:40:35 -04:00
|
|
|
[w setCollectionBehavior:
|
|
|
|
|
NSWindowCollectionBehaviorFullScreenPrimary];
|
2011-09-06 10:10:43 -04:00
|
|
|
#endif
|
2011-10-12 13:40:35 -04:00
|
|
|
[w setContentMinSize:NSMakeSize(128,128)];
|
2011-09-26 08:19:56 -07:00
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
win.ofs[0] = w;
|
|
|
|
|
win.ofs[1] = [[appwin alloc]
|
2011-09-26 08:19:56 -07:00
|
|
|
initWithContentRect:sr
|
|
|
|
|
styleMask:NSBorderlessWindowMask
|
2011-10-12 13:40:35 -04:00
|
|
|
backing:NSBackingStoreBuffered defer:YES];
|
|
|
|
|
for(i=0; i<2; i++){
|
|
|
|
|
[win.ofs[i] setAcceptsMouseMovedEvents:YES];
|
|
|
|
|
[win.ofs[i] setDelegate:[NSApp delegate]];
|
|
|
|
|
[win.ofs[i] setDisplaysWhenScreenProfileChanges:NO];
|
|
|
|
|
}
|
|
|
|
|
win.isofs = 0;
|
2011-09-26 08:19:56 -07:00
|
|
|
win.content = [appview new];
|
|
|
|
|
[win.content setAcceptsTouchEvents:YES];
|
2011-10-12 13:40:35 -04:00
|
|
|
[WIN setContentView:win.content];
|
|
|
|
|
[WIN makeKeyAndOrderFront:nil];
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
|
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
static Memimage*
|
2011-10-12 13:40:35 -04:00
|
|
|
initimg(void)
|
2011-09-06 10:10:43 -04:00
|
|
|
{
|
2011-10-12 13:40:35 -04:00
|
|
|
Memimage *i;
|
2011-09-06 10:10:43 -04:00
|
|
|
NSSize size;
|
|
|
|
|
Rectangle r;
|
|
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
size = [win.content bounds].size;
|
2011-09-06 10:10:43 -04:00
|
|
|
|
|
|
|
|
r = Rect(0, 0, size.width, size.height);
|
2011-10-12 13:40:35 -04:00
|
|
|
i = allocmemimage(r, XBGR32);
|
|
|
|
|
if(i == nil)
|
2011-09-06 10:10:43 -04:00
|
|
|
panic("allocmemimage: %r");
|
2011-10-12 13:40:35 -04:00
|
|
|
if(i->data == nil)
|
|
|
|
|
panic("i->data == nil");
|
2011-09-06 10:10:43 -04:00
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
win.img = [[NSBitmapImageRep alloc]
|
2011-10-12 13:40:35 -04:00
|
|
|
initWithBitmapDataPlanes:&i->data->bdata
|
2011-09-19 08:58:59 -04:00
|
|
|
pixelsWide:Dx(r)
|
|
|
|
|
pixelsHigh:Dy(r)
|
|
|
|
|
bitsPerSample:8
|
2011-10-12 13:40:35 -04:00
|
|
|
samplesPerPixel:3
|
|
|
|
|
hasAlpha:NO
|
2011-09-19 08:58:59 -04:00
|
|
|
isPlanar:NO
|
|
|
|
|
colorSpaceName:NSDeviceRGBColorSpace
|
|
|
|
|
bytesPerRow:bytesperline(r, 32)
|
|
|
|
|
bitsPerPixel:32];
|
2011-09-06 10:10:43 -04:00
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
return i;
|
2011-09-19 08:58:59 -04:00
|
|
|
}
|
2011-09-06 10:10:43 -04:00
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
void
|
|
|
|
|
_flushmemscreen(Rectangle r)
|
|
|
|
|
{
|
|
|
|
|
win.flushrect = NSMakeRect(r.min.x, r.min.y, Dx(r), Dy(r));
|
2011-09-06 10:10:43 -04:00
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
/*
|
|
|
|
|
* Call "lockFocusIfCanDraw" from main thread, else
|
|
|
|
|
* we deadlock while synchronizing both threads with
|
|
|
|
|
* qlock(): main thread must apparently be idle while
|
|
|
|
|
* we call it. (This is also why Devdraw shows
|
|
|
|
|
* occasionally an empty window: I found no
|
|
|
|
|
* satisfactory way to wait for P9P's image.)
|
|
|
|
|
*/
|
2011-09-19 08:58:59 -04:00
|
|
|
[appdelegate
|
|
|
|
|
performSelectorOnMainThread:@selector(calldrawimg:)
|
|
|
|
|
withObject:nil
|
|
|
|
|
waitUntilDone:YES];
|
|
|
|
|
}
|
2011-09-06 10:10:43 -04:00
|
|
|
|
2011-10-03 18:16:09 -04:00
|
|
|
static void drawresizehandle(void);
|
|
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
static void
|
|
|
|
|
drawimg(void)
|
|
|
|
|
{
|
|
|
|
|
static int first = 1;
|
|
|
|
|
NSRect dr, sr;
|
|
|
|
|
|
|
|
|
|
if(first){
|
|
|
|
|
[NSTimer scheduledTimerWithTimeInterval:0.033
|
|
|
|
|
target:[appdelegate class]
|
|
|
|
|
selector:@selector(callflushwin:) userInfo:nil
|
|
|
|
|
repeats:YES];
|
|
|
|
|
first = 0;
|
|
|
|
|
}
|
|
|
|
|
dr = win.flushrect;
|
|
|
|
|
sr = [win.content convertRect:dr fromView:nil];
|
|
|
|
|
|
|
|
|
|
if([win.content lockFocusIfCanDraw]){
|
2011-10-12 13:40:35 -04:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* To round the window's bottom corners, we can use
|
|
|
|
|
* "NSCompositeSourceIn", but this slows down
|
|
|
|
|
* trackpad scrolling considerably in Acme. Else we
|
|
|
|
|
* can use "bezierPathWithRoundedRect" with "addClip",
|
|
|
|
|
* but it's still too slow for wide Acme windows.
|
|
|
|
|
*/
|
2011-09-19 08:58:59 -04:00
|
|
|
[win.img drawInRect:dr fromRect:sr
|
2011-10-12 13:40:35 -04:00
|
|
|
// operation:NSCompositeSourceIn fraction:1
|
2011-09-19 08:58:59 -04:00
|
|
|
operation:NSCompositeCopy fraction:1
|
|
|
|
|
respectFlipped:YES hints:nil];
|
2011-10-03 18:16:09 -04:00
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
if(OSX_VERSION<100700 && win.isofs==0)
|
2011-10-03 18:16:09 -04:00
|
|
|
drawresizehandle();
|
|
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
[win.content unlockFocus];
|
|
|
|
|
win.needflush = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-09-06 10:10:43 -04:00
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
static void
|
|
|
|
|
flushwin(void)
|
|
|
|
|
{
|
|
|
|
|
if(win.needflush){
|
2011-10-12 13:40:35 -04:00
|
|
|
[WIN flushWindow];
|
2011-09-19 08:58:59 -04:00
|
|
|
win.needflush = 0;
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-03 18:16:09 -04:00
|
|
|
enum
|
|
|
|
|
{
|
|
|
|
|
Pixel = 1,
|
2011-10-12 13:40:35 -04:00
|
|
|
Barsize = 4*Pixel,
|
|
|
|
|
Handlesize = 3*Barsize + 1*Pixel,
|
2011-10-03 18:16:09 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
drawresizehandle(void)
|
|
|
|
|
{
|
2011-10-12 13:40:35 -04:00
|
|
|
NSColor *color[Barsize];
|
|
|
|
|
NSPoint a,b;
|
2011-10-03 18:16:09 -04:00
|
|
|
NSRect r;
|
|
|
|
|
NSSize size;
|
2011-10-12 13:40:35 -04:00
|
|
|
Point c;
|
|
|
|
|
int i,j;
|
2011-10-03 18:16:09 -04:00
|
|
|
|
|
|
|
|
size = [win.img size];
|
2011-10-12 13:40:35 -04:00
|
|
|
c = Pt(size.width, size.height);
|
|
|
|
|
r = NSMakeRect(0, 0, Handlesize, Handlesize);
|
|
|
|
|
r.origin = NSMakePoint(c.x-Handlesize, c.y-Handlesize);
|
2011-10-03 18:16:09 -04:00
|
|
|
if(NSIntersectsRect(r, win.flushrect) == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
[[WIN graphicsContext] setShouldAntialias:NO];
|
2011-10-03 18:16:09 -04:00
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
color[0] = [NSColor clearColor];
|
|
|
|
|
color[1] = [NSColor darkGrayColor];
|
|
|
|
|
color[2] = [NSColor lightGrayColor];
|
|
|
|
|
color[3] = [NSColor whiteColor];
|
2011-10-03 18:16:09 -04:00
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
for(i=1; i+Barsize <= Handlesize; )
|
|
|
|
|
for(j=0; j<Barsize; j++){
|
|
|
|
|
[color[j] setStroke];
|
|
|
|
|
i++;
|
|
|
|
|
a = NSMakePoint(c.x-i, c.y-1);
|
|
|
|
|
b = NSMakePoint(c.x-2, c.y+1-i);
|
|
|
|
|
[NSBezierPath strokeLineFromPoint:a toPoint:b];
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-10-03 18:16:09 -04:00
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
static void
|
|
|
|
|
resizeimg()
|
|
|
|
|
{
|
|
|
|
|
[win.img release];
|
|
|
|
|
_drawreplacescreenimage(initimg());
|
|
|
|
|
mouseresized = 1;
|
|
|
|
|
sendmouse();
|
2011-10-03 18:16:09 -04:00
|
|
|
}
|
|
|
|
|
|
2011-09-06 10:10:43 -04:00
|
|
|
static void getgesture(NSEvent*);
|
|
|
|
|
static void getkeyboard(NSEvent*);
|
|
|
|
|
static void getmouse(NSEvent*);
|
2011-09-19 08:58:59 -04:00
|
|
|
static void gettouch(NSEvent*, int);
|
2011-09-06 10:10:43 -04:00
|
|
|
|
|
|
|
|
@implementation appview
|
|
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
- (void)drawRect:(NSRect)r
|
|
|
|
|
{
|
2011-10-12 13:40:35 -04:00
|
|
|
static int first = 1;
|
|
|
|
|
|
|
|
|
|
if([WIN inLiveResize])
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if(first)
|
|
|
|
|
first = 0;
|
|
|
|
|
else
|
|
|
|
|
resizeimg();
|
|
|
|
|
|
|
|
|
|
/* We should wait for P9P's image here. */
|
|
|
|
|
}
|
|
|
|
|
- (void)resetCursorRects
|
|
|
|
|
{
|
|
|
|
|
NSCursor *c;
|
|
|
|
|
|
2011-10-23 18:47:29 -04:00
|
|
|
[super resetCursorRects];
|
|
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
qlock(&win.cursorl);
|
|
|
|
|
|
|
|
|
|
c = win.cursor;
|
|
|
|
|
if(c == nil)
|
|
|
|
|
c = [NSCursor arrowCursor];
|
|
|
|
|
|
2011-10-23 18:47:29 -04:00
|
|
|
[self addCursorRect:[self bounds] cursor:c];
|
2011-10-12 13:40:35 -04:00
|
|
|
qunlock(&win.cursorl);
|
2011-09-19 08:58:59 -04:00
|
|
|
}
|
|
|
|
|
- (BOOL)isFlipped
|
|
|
|
|
{
|
2011-10-12 13:40:35 -04:00
|
|
|
return YES; /* to have the origin at top left */
|
2011-09-19 08:58:59 -04:00
|
|
|
}
|
|
|
|
|
- (BOOL)acceptsFirstResponder
|
|
|
|
|
{
|
2011-10-12 13:40:35 -04:00
|
|
|
return YES; /* to receive mouseMoved events */
|
2011-09-19 08:58:59 -04:00
|
|
|
}
|
2011-09-06 10:10:43 -04:00
|
|
|
- (void)mouseMoved:(NSEvent*)e{ getmouse(e);}
|
|
|
|
|
- (void)mouseDown:(NSEvent*)e{ getmouse(e);}
|
|
|
|
|
- (void)mouseDragged:(NSEvent*)e{ getmouse(e);}
|
|
|
|
|
- (void)mouseUp:(NSEvent*)e{ getmouse(e);}
|
|
|
|
|
- (void)otherMouseDown:(NSEvent*)e{ getmouse(e);}
|
|
|
|
|
- (void)otherMouseDragged:(NSEvent*)e{ getmouse(e);}
|
|
|
|
|
- (void)otherMouseUp:(NSEvent*)e{ getmouse(e);}
|
|
|
|
|
- (void)rightMouseDown:(NSEvent*)e{ getmouse(e);}
|
|
|
|
|
- (void)rightMouseDragged:(NSEvent*)e{ getmouse(e);}
|
|
|
|
|
- (void)rightMouseUp:(NSEvent*)e{ getmouse(e);}
|
|
|
|
|
- (void)scrollWheel:(NSEvent*)e{ getmouse(e);}
|
|
|
|
|
|
|
|
|
|
- (void)keyDown:(NSEvent*)e{ getkeyboard(e);}
|
|
|
|
|
- (void)flagsChanged:(NSEvent*)e{ getkeyboard(e);}
|
|
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
- (void)swipeWithEvent:(NSEvent*)e{ getgesture(e);}
|
|
|
|
|
- (void)magnifyWithEvent:(NSEvent*)e{ getgesture(e);}
|
2011-09-06 10:10:43 -04:00
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
- (void)touchesBeganWithEvent:(NSEvent*)e
|
2011-09-06 10:10:43 -04:00
|
|
|
{
|
2011-09-19 08:58:59 -04:00
|
|
|
gettouch(e, NSTouchPhaseBegan);
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
2011-09-19 08:58:59 -04:00
|
|
|
- (void)touchesMovedWithEvent:(NSEvent*)e
|
2011-09-06 10:10:43 -04:00
|
|
|
{
|
2011-09-19 08:58:59 -04:00
|
|
|
gettouch(e, NSTouchPhaseMoved);
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
2011-09-19 08:58:59 -04:00
|
|
|
- (void)touchesEndedWithEvent:(NSEvent*)e
|
|
|
|
|
{
|
|
|
|
|
gettouch(e, NSTouchPhaseEnded);
|
|
|
|
|
}
|
|
|
|
|
- (void)touchesCancelledWithEvent:(NSEvent*)e
|
|
|
|
|
{
|
|
|
|
|
gettouch(e, NSTouchPhaseCancelled);
|
|
|
|
|
}
|
|
|
|
|
@end
|
|
|
|
|
|
2011-09-06 10:10:43 -04:00
|
|
|
static int keycvt[] =
|
|
|
|
|
{
|
|
|
|
|
[QZ_IBOOK_ENTER] '\n',
|
|
|
|
|
[QZ_RETURN] '\n',
|
|
|
|
|
[QZ_ESCAPE] 27,
|
|
|
|
|
[QZ_BACKSPACE] '\b',
|
|
|
|
|
[QZ_LALT] Kalt,
|
|
|
|
|
[QZ_LCTRL] Kctl,
|
|
|
|
|
[QZ_LSHIFT] Kshift,
|
|
|
|
|
[QZ_F1] KF+1,
|
|
|
|
|
[QZ_F2] KF+2,
|
|
|
|
|
[QZ_F3] KF+3,
|
|
|
|
|
[QZ_F4] KF+4,
|
|
|
|
|
[QZ_F5] KF+5,
|
|
|
|
|
[QZ_F6] KF+6,
|
|
|
|
|
[QZ_F7] KF+7,
|
|
|
|
|
[QZ_F8] KF+8,
|
|
|
|
|
[QZ_F9] KF+9,
|
|
|
|
|
[QZ_F10] KF+10,
|
|
|
|
|
[QZ_F11] KF+11,
|
|
|
|
|
[QZ_F12] KF+12,
|
|
|
|
|
[QZ_INSERT] Kins,
|
|
|
|
|
[QZ_DELETE] 0x7F,
|
|
|
|
|
[QZ_HOME] Khome,
|
|
|
|
|
[QZ_END] Kend,
|
|
|
|
|
[QZ_KP_PLUS] '+',
|
|
|
|
|
[QZ_KP_MINUS] '-',
|
|
|
|
|
[QZ_TAB] '\t',
|
|
|
|
|
[QZ_PAGEUP] Kpgup,
|
|
|
|
|
[QZ_PAGEDOWN] Kpgdown,
|
|
|
|
|
[QZ_UP] Kup,
|
|
|
|
|
[QZ_DOWN] Kdown,
|
|
|
|
|
[QZ_LEFT] Kleft,
|
|
|
|
|
[QZ_RIGHT] Kright,
|
|
|
|
|
[QZ_KP_MULTIPLY] '*',
|
|
|
|
|
[QZ_KP_DIVIDE] '/',
|
|
|
|
|
[QZ_KP_ENTER] '\n',
|
|
|
|
|
[QZ_KP_PERIOD] '.',
|
|
|
|
|
[QZ_KP0] '0',
|
|
|
|
|
[QZ_KP1] '1',
|
|
|
|
|
[QZ_KP2] '2',
|
|
|
|
|
[QZ_KP3] '3',
|
|
|
|
|
[QZ_KP4] '4',
|
|
|
|
|
[QZ_KP5] '5',
|
|
|
|
|
[QZ_KP6] '6',
|
|
|
|
|
[QZ_KP7] '7',
|
|
|
|
|
[QZ_KP8] '8',
|
|
|
|
|
[QZ_KP9] '9',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
getkeyboard(NSEvent *e)
|
|
|
|
|
{
|
2011-10-12 13:40:35 -04:00
|
|
|
NSString *s;
|
2011-09-06 10:10:43 -04:00
|
|
|
char c;
|
2011-09-19 08:58:59 -04:00
|
|
|
int k, m;
|
|
|
|
|
uint code;
|
2011-09-06 10:10:43 -04:00
|
|
|
|
|
|
|
|
m = [e modifierFlags];
|
|
|
|
|
|
|
|
|
|
switch([e type]){
|
|
|
|
|
case NSKeyDown:
|
2011-09-19 08:58:59 -04:00
|
|
|
in.kalting = 0;
|
2011-10-12 13:40:35 -04:00
|
|
|
|
|
|
|
|
s = [e characters];
|
|
|
|
|
c = [s UTF8String][0];
|
|
|
|
|
|
2011-09-06 10:10:43 -04:00
|
|
|
if(m & NSCommandKeyMask){
|
2011-10-12 13:40:35 -04:00
|
|
|
if(' '<=c && c<='~')
|
2011-09-06 10:10:43 -04:00
|
|
|
keystroke(Kcmd+c);
|
2011-10-12 13:40:35 -04:00
|
|
|
break;
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
|
|
|
|
k = c;
|
|
|
|
|
code = [e keyCode];
|
2011-10-12 13:40:35 -04:00
|
|
|
if(code<nelem(keycvt) && keycvt[code])
|
2011-09-06 10:10:43 -04:00
|
|
|
k = keycvt[code];
|
2011-10-12 13:40:35 -04:00
|
|
|
if(k==0)
|
|
|
|
|
break;
|
|
|
|
|
if(k>0)
|
2011-09-06 10:10:43 -04:00
|
|
|
keystroke(k);
|
|
|
|
|
else
|
2011-10-12 13:40:35 -04:00
|
|
|
keystroke([s characterAtIndex:0]);
|
2011-09-06 10:10:43 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case NSFlagsChanged:
|
2011-09-19 08:58:59 -04:00
|
|
|
if(in.mbuttons || in.kbuttons){
|
|
|
|
|
in.kbuttons = 0;
|
2011-09-06 10:10:43 -04:00
|
|
|
if(m & NSAlternateKeyMask)
|
2011-09-19 08:58:59 -04:00
|
|
|
in.kbuttons |= 2;
|
2011-09-06 10:10:43 -04:00
|
|
|
if(m & NSCommandKeyMask)
|
2011-09-19 08:58:59 -04:00
|
|
|
in.kbuttons |= 4;
|
2011-10-03 18:16:09 -04:00
|
|
|
sendmouse();
|
2011-09-06 10:10:43 -04:00
|
|
|
}else
|
2011-09-19 08:58:59 -04:00
|
|
|
if(m & NSAlternateKeyMask){
|
|
|
|
|
in.kalting = 1;
|
2011-09-06 10:10:43 -04:00
|
|
|
keystroke(Kalt);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
panic("getkey: unexpected event type");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
getmousepos(void)
|
|
|
|
|
{
|
|
|
|
|
NSPoint p;
|
|
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
p = [WIN mouseLocationOutsideOfEventStream];
|
2011-09-19 08:58:59 -04:00
|
|
|
p = [win.content convertPoint:p fromView:nil];
|
|
|
|
|
in.mpos = Pt(p.x, p.y);
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
getmouse(NSEvent *e)
|
|
|
|
|
{
|
|
|
|
|
float d;
|
2011-09-19 08:58:59 -04:00
|
|
|
int b, m;
|
2011-09-06 10:10:43 -04:00
|
|
|
|
|
|
|
|
getmousepos();
|
|
|
|
|
|
|
|
|
|
switch([e type]){
|
|
|
|
|
case NSLeftMouseDown:
|
|
|
|
|
case NSLeftMouseUp:
|
|
|
|
|
case NSOtherMouseDown:
|
|
|
|
|
case NSOtherMouseUp:
|
|
|
|
|
case NSRightMouseDown:
|
|
|
|
|
case NSRightMouseUp:
|
|
|
|
|
b = [NSEvent pressedMouseButtons];
|
|
|
|
|
b = b&~6 | (b&4)>>1 | (b&2)<<1;
|
|
|
|
|
b = mouseswap(b);
|
|
|
|
|
|
|
|
|
|
if(b == 1){
|
|
|
|
|
m = [e modifierFlags];
|
2011-09-19 08:58:59 -04:00
|
|
|
if(m & NSAlternateKeyMask){
|
2011-09-06 10:10:43 -04:00
|
|
|
b = 2;
|
|
|
|
|
// Take the ALT away from the keyboard handler.
|
2011-09-19 08:58:59 -04:00
|
|
|
if(in.kalting){
|
|
|
|
|
in.kalting = 0;
|
2011-09-06 10:10:43 -04:00
|
|
|
keystroke(Kalt);
|
|
|
|
|
}
|
|
|
|
|
}else
|
|
|
|
|
if(m & NSCommandKeyMask)
|
|
|
|
|
b = 4;
|
|
|
|
|
}
|
2011-09-19 08:58:59 -04:00
|
|
|
in.mbuttons = b;
|
2011-09-06 10:10:43 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case NSScrollWheel:
|
|
|
|
|
#if OSX_VERSION >= 100700
|
|
|
|
|
d = [e scrollingDeltaY];
|
|
|
|
|
#else
|
|
|
|
|
d = [e deltaY];
|
|
|
|
|
#endif
|
|
|
|
|
if(d>0)
|
2011-09-19 08:58:59 -04:00
|
|
|
in.mscroll = 8;
|
|
|
|
|
else
|
|
|
|
|
if(d<0)
|
|
|
|
|
in.mscroll = 16;
|
2011-09-06 10:10:43 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case NSMouseMoved:
|
|
|
|
|
case NSLeftMouseDragged:
|
|
|
|
|
case NSRightMouseDragged:
|
|
|
|
|
case NSOtherMouseDragged:
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
panic("getmouse: unexpected event type");
|
|
|
|
|
}
|
2011-10-03 18:16:09 -04:00
|
|
|
sendmouse();
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
|
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
#define Minpinch 0.050
|
|
|
|
|
|
|
|
|
|
enum
|
|
|
|
|
{
|
|
|
|
|
Left = -1,
|
|
|
|
|
Right = +1,
|
|
|
|
|
Up = +2,
|
|
|
|
|
Down = -2,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
getdir(int dx, int dy)
|
|
|
|
|
{
|
|
|
|
|
return dx + 2*dy;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void interpretswipe(int);
|
2011-09-06 10:10:43 -04:00
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
getgesture(NSEvent *e)
|
|
|
|
|
{
|
2011-10-12 13:40:35 -04:00
|
|
|
static float sum;
|
|
|
|
|
int dir;
|
|
|
|
|
|
|
|
|
|
if(usegestures == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
2011-09-06 10:10:43 -04:00
|
|
|
switch([e type]){
|
|
|
|
|
|
|
|
|
|
case NSEventTypeMagnify:
|
2011-10-12 13:40:35 -04:00
|
|
|
sum += [e magnification];
|
|
|
|
|
if(fabs(sum) > Minpinch){
|
2011-09-26 08:19:56 -07:00
|
|
|
togglefs();
|
2011-10-12 13:40:35 -04:00
|
|
|
sum = 0;
|
|
|
|
|
}
|
2011-09-06 10:10:43 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case NSEventTypeSwipe:
|
2011-10-12 13:40:35 -04:00
|
|
|
dir = getdir(-[e deltaX], [e deltaY]);
|
2011-09-06 10:10:43 -04:00
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
if(in.touchevent)
|
|
|
|
|
if(dir==Up || dir==Down)
|
|
|
|
|
break;
|
|
|
|
|
interpretswipe(dir);
|
2011-09-06 10:10:43 -04:00
|
|
|
break;
|
2011-09-19 08:58:59 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void sendclick(int);
|
|
|
|
|
static void sendchord(int, int);
|
|
|
|
|
static void sendcmd(int);
|
2011-09-06 10:10:43 -04:00
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
static uint
|
|
|
|
|
msec(void)
|
|
|
|
|
{
|
|
|
|
|
return nsec()/1000000;
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
#define Inch 72
|
|
|
|
|
#define Cm Inch/2.54
|
|
|
|
|
|
|
|
|
|
#define Mindelta 0.0*Cm
|
|
|
|
|
#define Xminswipe 0.5*Cm
|
|
|
|
|
#define Yminswipe 0.1*Cm
|
|
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
enum
|
|
|
|
|
{
|
2011-10-12 13:40:35 -04:00
|
|
|
Finger = 1,
|
2011-09-19 08:58:59 -04:00
|
|
|
Msec = 1,
|
2011-10-12 13:40:35 -04:00
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
Maxtap = 400*Msec,
|
2011-10-12 13:40:35 -04:00
|
|
|
Maxtouch = 3*Finger,
|
2011-09-19 08:58:59 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gettouch(NSEvent *e, int type)
|
|
|
|
|
{
|
2011-10-12 13:40:35 -04:00
|
|
|
static NSPoint delta;
|
2011-09-19 08:58:59 -04:00
|
|
|
static NSTouch *toucha[Maxtouch];
|
|
|
|
|
static NSTouch *touchb[Maxtouch];
|
2011-10-12 13:40:35 -04:00
|
|
|
static int done, ntouch, odir, tapping;
|
2011-09-19 08:58:59 -04:00
|
|
|
static uint taptime;
|
|
|
|
|
NSArray *a;
|
|
|
|
|
NSPoint d;
|
|
|
|
|
NSSet *set;
|
|
|
|
|
NSSize s;
|
2011-10-12 13:40:35 -04:00
|
|
|
int dir, i, p;
|
2011-09-19 08:58:59 -04:00
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
if(usegestures == 0)
|
2011-09-19 08:58:59 -04:00
|
|
|
return;
|
2011-09-06 10:10:43 -04:00
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
switch(type){
|
2011-09-06 10:10:43 -04:00
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
case NSTouchPhaseBegan:
|
2011-10-12 13:40:35 -04:00
|
|
|
in.touchevent = 1;
|
2011-09-19 08:58:59 -04:00
|
|
|
p = NSTouchPhaseTouching;
|
|
|
|
|
set = [e touchesMatchingPhase:p inView:nil];
|
|
|
|
|
if(set.count == 3){
|
|
|
|
|
tapping = 1;
|
|
|
|
|
taptime = msec();
|
|
|
|
|
}else
|
|
|
|
|
if(set.count > 3)
|
|
|
|
|
tapping = 0;
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
case NSTouchPhaseMoved:
|
|
|
|
|
p = NSTouchPhaseMoved;
|
|
|
|
|
set = [e touchesMatchingPhase:p inView:nil];
|
|
|
|
|
a = [set allObjects];
|
|
|
|
|
if(set.count > Maxtouch)
|
|
|
|
|
return;
|
|
|
|
|
if(ntouch==0){
|
|
|
|
|
ntouch = set.count;
|
|
|
|
|
for(i=0; i<ntouch; i++){
|
2011-10-12 13:40:35 -04:00
|
|
|
// assert(toucha[i] == nil);
|
2011-09-19 08:58:59 -04:00
|
|
|
toucha[i] = [[a objectAtIndex:i] retain];
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(ntouch != set.count)
|
|
|
|
|
break;
|
|
|
|
|
if(done)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
d = NSMakePoint(0,0);
|
|
|
|
|
for(i=0; i<ntouch; i++){
|
2011-10-12 13:40:35 -04:00
|
|
|
// assert(touchb[i] == nil);
|
2011-09-19 08:58:59 -04:00
|
|
|
touchb[i] = [a objectAtIndex:i];
|
|
|
|
|
d.x += touchb[i].normalizedPosition.x;
|
|
|
|
|
d.y += touchb[i].normalizedPosition.y;
|
|
|
|
|
d.x -= toucha[i].normalizedPosition.x;
|
|
|
|
|
d.y -= toucha[i].normalizedPosition.y;
|
|
|
|
|
}
|
|
|
|
|
s = toucha[0].deviceSize;
|
|
|
|
|
d.x = d.x/ntouch * s.width;
|
|
|
|
|
d.y = d.y/ntouch * s.height;
|
|
|
|
|
if(fabs(d.x)>Mindelta || fabs(d.y)>Mindelta){
|
|
|
|
|
tapping = 0;
|
|
|
|
|
if(ntouch != 3){
|
|
|
|
|
done = 1;
|
|
|
|
|
goto Return;
|
|
|
|
|
}
|
|
|
|
|
delta = NSMakePoint(delta.x+d.x, delta.y+d.y);
|
|
|
|
|
d = NSMakePoint(fabs(delta.x), fabs(delta.y));
|
2011-10-12 13:40:35 -04:00
|
|
|
if(d.x>Xminswipe || d.y>Yminswipe){
|
2011-09-19 08:58:59 -04:00
|
|
|
if(d.x > d.y)
|
2011-10-12 13:40:35 -04:00
|
|
|
dir = delta.x>0? Right : Left;
|
2011-09-19 08:58:59 -04:00
|
|
|
else
|
2011-10-12 13:40:35 -04:00
|
|
|
dir = delta.y>0? Up : Down;
|
|
|
|
|
if(dir != odir){
|
2011-09-19 08:58:59 -04:00
|
|
|
// if(ntouch == 3)
|
2011-10-12 13:40:35 -04:00
|
|
|
if(dir==Up || dir==Down)
|
|
|
|
|
interpretswipe(dir);
|
|
|
|
|
odir = dir;
|
2011-09-19 08:58:59 -04:00
|
|
|
}
|
|
|
|
|
goto Return;
|
|
|
|
|
}
|
|
|
|
|
for(i=0; i<ntouch; i++){
|
|
|
|
|
[toucha[i] release];
|
|
|
|
|
toucha[i] = [touchb[i] retain];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Return:
|
|
|
|
|
for(i=0; i<ntouch; i++)
|
|
|
|
|
touchb[i] = nil;
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
case NSTouchPhaseEnded:
|
|
|
|
|
p = NSTouchPhaseTouching;
|
|
|
|
|
set = [e touchesMatchingPhase:p inView:nil];
|
|
|
|
|
if(set.count == 0){
|
2011-10-12 13:40:35 -04:00
|
|
|
if(tapping && msec()-taptime<Maxtap)
|
|
|
|
|
sendclick(2);
|
|
|
|
|
odir = 0;
|
2011-09-19 08:58:59 -04:00
|
|
|
tapping = 0;
|
2011-10-12 13:40:35 -04:00
|
|
|
in.undo = 0;
|
|
|
|
|
in.touchevent = 0;
|
2011-09-19 08:58:59 -04:00
|
|
|
}
|
2011-09-06 10:10:43 -04:00
|
|
|
break;
|
|
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
case NSTouchPhaseCancelled:
|
2011-09-06 10:10:43 -04:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
2011-10-12 13:40:35 -04:00
|
|
|
panic("gettouch: unexpected event type");
|
2011-09-19 08:58:59 -04:00
|
|
|
}
|
|
|
|
|
for(i=0; i<ntouch; i++){
|
|
|
|
|
[toucha[i] release];
|
|
|
|
|
toucha[i] = nil;
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
2011-09-19 08:58:59 -04:00
|
|
|
delta = NSMakePoint(0,0);
|
|
|
|
|
done = 0;
|
2011-10-12 13:40:35 -04:00
|
|
|
ntouch = 0;
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2011-10-12 13:40:35 -04:00
|
|
|
interpretswipe(int dir)
|
2011-09-06 10:10:43 -04:00
|
|
|
{
|
2011-10-12 13:40:35 -04:00
|
|
|
if(dir == Left)
|
2011-09-19 08:58:59 -04:00
|
|
|
sendcmd('x');
|
2011-10-12 13:40:35 -04:00
|
|
|
else
|
|
|
|
|
if(dir == Right)
|
2011-09-19 08:58:59 -04:00
|
|
|
sendcmd('v');
|
2011-10-12 13:40:35 -04:00
|
|
|
else
|
|
|
|
|
if(dir == Up)
|
|
|
|
|
sendcmd('c');
|
|
|
|
|
else
|
|
|
|
|
if(dir == Down)
|
2011-09-19 08:58:59 -04:00
|
|
|
sendchord(2,1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
sendcmd(int c)
|
|
|
|
|
{
|
2011-10-12 13:40:35 -04:00
|
|
|
if(in.touchevent && (c=='x' || c=='v')){
|
2011-09-19 08:58:59 -04:00
|
|
|
if(in.undo)
|
|
|
|
|
c = 'z';
|
|
|
|
|
in.undo = ! in.undo;
|
|
|
|
|
}
|
2011-09-06 10:10:43 -04:00
|
|
|
keystroke(Kcmd+c);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2011-09-19 08:58:59 -04:00
|
|
|
sendclick(int b)
|
2011-09-06 10:10:43 -04:00
|
|
|
{
|
2011-09-19 08:58:59 -04:00
|
|
|
in.mbuttons = b;
|
2011-10-03 18:16:09 -04:00
|
|
|
sendmouse();
|
2011-09-19 08:58:59 -04:00
|
|
|
in.mbuttons = 0;
|
2011-10-03 18:16:09 -04:00
|
|
|
sendmouse();
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
|
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
static void
|
|
|
|
|
sendchord(int b1, int b2)
|
2011-09-06 10:10:43 -04:00
|
|
|
{
|
2011-09-19 08:58:59 -04:00
|
|
|
in.mbuttons = b1;
|
2011-10-03 18:16:09 -04:00
|
|
|
sendmouse();
|
2011-09-19 08:58:59 -04:00
|
|
|
in.mbuttons |= b2;
|
2011-10-03 18:16:09 -04:00
|
|
|
sendmouse();
|
2011-09-19 08:58:59 -04:00
|
|
|
in.mbuttons = 0;
|
2011-10-03 18:16:09 -04:00
|
|
|
sendmouse();
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2011-10-03 18:16:09 -04:00
|
|
|
sendmouse(void)
|
2011-09-06 10:10:43 -04:00
|
|
|
{
|
2011-09-19 08:58:59 -04:00
|
|
|
NSSize size;
|
|
|
|
|
int b;
|
|
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
size = [win.content bounds].size;
|
2011-09-19 08:58:59 -04:00
|
|
|
mouserect = Rect(0, 0, size.width, size.height);
|
|
|
|
|
|
|
|
|
|
b = in.kbuttons | in.mbuttons | in.mscroll;
|
|
|
|
|
mousetrack(in.mpos.x, in.mpos.y, b, msec());
|
|
|
|
|
in.mscroll = 0;
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
setmouse(Point p)
|
|
|
|
|
{
|
2011-09-19 08:58:59 -04:00
|
|
|
static int first = 1;
|
2011-09-06 10:10:43 -04:00
|
|
|
NSPoint q;
|
|
|
|
|
NSRect r;
|
|
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
if(first){
|
2011-10-12 13:40:35 -04:00
|
|
|
/* Try to move Acme's scrollbars without that! */
|
2011-09-19 08:58:59 -04:00
|
|
|
CGSetLocalEventsSuppressionInterval(0);
|
|
|
|
|
first = 0;
|
|
|
|
|
}
|
2011-10-12 13:40:35 -04:00
|
|
|
r = [[WIN screen] frame];
|
2011-09-06 10:10:43 -04:00
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
q = NSMakePoint(p.x, p.y);
|
2011-09-19 08:58:59 -04:00
|
|
|
q = [win.content convertPoint:q toView:nil];
|
2011-10-12 13:40:35 -04:00
|
|
|
q = [WIN convertBaseToScreen:q];
|
2011-09-06 10:10:43 -04:00
|
|
|
q.y = r.size.height - q.y;
|
|
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
CGWarpMouseCursorPosition(NSPointToCGPoint(q));
|
2011-09-06 10:10:43 -04:00
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
in.mpos = p; // race condition
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
followzoombutton(NSRect r)
|
|
|
|
|
{
|
|
|
|
|
NSRect wr;
|
|
|
|
|
Point p;
|
|
|
|
|
|
|
|
|
|
wr = [WIN frame];
|
|
|
|
|
wr.origin.y += wr.size.height;
|
|
|
|
|
r.origin.y += r.size.height;
|
|
|
|
|
|
|
|
|
|
p.x = (r.origin.x - wr.origin.x) + in.mpos.x;
|
|
|
|
|
p.y = -(r.origin.y - wr.origin.y) + in.mpos.y;
|
|
|
|
|
setmouse(p);
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2011-09-26 08:19:56 -07:00
|
|
|
togglefs(void)
|
2011-09-06 10:10:43 -04:00
|
|
|
{
|
2011-11-08 13:23:55 -05:00
|
|
|
uint opt, tmp;
|
|
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
#if OSX_VERSION >= 100700
|
2011-11-08 13:23:55 -05:00
|
|
|
if(useoldfullscreen==0 || win.isnfs){
|
2011-10-12 13:40:35 -04:00
|
|
|
[WIN toggleFullScreen:nil];
|
2011-09-19 08:58:59 -04:00
|
|
|
return;
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
2011-09-19 08:58:59 -04:00
|
|
|
#endif
|
2011-09-26 08:19:56 -07:00
|
|
|
[win.content retain];
|
2011-10-12 13:40:35 -04:00
|
|
|
[WIN orderOut:nil];
|
|
|
|
|
[WIN setContentView:nil];
|
2011-10-03 18:16:09 -04:00
|
|
|
|
2011-11-08 13:23:55 -05:00
|
|
|
win.isofs = ! win.isofs;
|
|
|
|
|
hidebars(win.isofs);
|
2011-10-03 18:16:09 -04:00
|
|
|
|
2011-11-08 13:23:55 -05:00
|
|
|
/*
|
|
|
|
|
* If we move the window from one space to another,
|
|
|
|
|
* ofs[0] and ofs[1] can be on different spaces.
|
|
|
|
|
* This "setCollectionBehavior" trick moves the
|
|
|
|
|
* window to the active space.
|
|
|
|
|
*/
|
|
|
|
|
opt = [WIN collectionBehavior];
|
|
|
|
|
tmp = opt | NSWindowCollectionBehaviorCanJoinAllSpaces;
|
2011-10-12 13:40:35 -04:00
|
|
|
[WIN setContentView:win.content];
|
2011-11-08 13:23:55 -05:00
|
|
|
[WIN setCollectionBehavior:tmp];
|
2011-10-12 13:40:35 -04:00
|
|
|
[WIN makeKeyAndOrderFront:nil];
|
2011-11-08 13:23:55 -05:00
|
|
|
[WIN setCollectionBehavior:opt];
|
2011-09-26 08:19:56 -07:00
|
|
|
[win.content release];
|
2011-10-03 18:16:09 -04:00
|
|
|
}
|
2011-09-19 08:58:59 -04:00
|
|
|
|
2011-11-08 13:23:55 -05:00
|
|
|
enum
|
|
|
|
|
{
|
|
|
|
|
Autohiddenbars = NSApplicationPresentationAutoHideDock
|
|
|
|
|
| NSApplicationPresentationAutoHideMenuBar,
|
|
|
|
|
|
|
|
|
|
Hiddenbars = NSApplicationPresentationHideDock
|
|
|
|
|
| NSApplicationPresentationHideMenuBar,
|
|
|
|
|
};
|
|
|
|
|
|
2011-10-03 18:16:09 -04:00
|
|
|
static void
|
2011-11-08 13:23:55 -05:00
|
|
|
hidebars(int set)
|
2011-10-03 18:16:09 -04:00
|
|
|
{
|
|
|
|
|
NSScreen *s,*s0;
|
2011-11-08 13:23:55 -05:00
|
|
|
uint old, opt;
|
2011-10-03 18:16:09 -04:00
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
s = [WIN screen];
|
2011-10-03 18:16:09 -04:00
|
|
|
s0 = [[NSScreen screens] objectAtIndex:0];
|
2011-11-08 13:23:55 -05:00
|
|
|
old = [NSApp presentationOptions];
|
2011-10-03 18:16:09 -04:00
|
|
|
|
|
|
|
|
if(set && s==s0)
|
2011-11-08 13:23:55 -05:00
|
|
|
opt = (old & ~Autohiddenbars) | Hiddenbars;
|
2011-10-03 18:16:09 -04:00
|
|
|
else
|
2011-11-08 13:23:55 -05:00
|
|
|
opt = old & ~(Autohiddenbars | Hiddenbars);
|
2011-10-03 18:16:09 -04:00
|
|
|
|
2011-11-08 13:23:55 -05:00
|
|
|
if(opt != old)
|
|
|
|
|
[NSApp setPresentationOptions:opt];
|
2011-10-03 18:16:09 -04:00
|
|
|
}
|
2011-09-19 08:58:59 -04:00
|
|
|
|
2011-09-06 10:10:43 -04:00
|
|
|
static void
|
2011-09-19 08:58:59 -04:00
|
|
|
makemenu(void)
|
2011-09-06 10:10:43 -04:00
|
|
|
{
|
2011-10-12 13:40:35 -04:00
|
|
|
NSMenu *m;
|
|
|
|
|
NSMenuItem *i,*i0;
|
|
|
|
|
|
|
|
|
|
m = [NSMenu new];
|
|
|
|
|
i0 = [NSMenuItem new];
|
|
|
|
|
[m addItem:i0];
|
|
|
|
|
[NSApp setMainMenu:m];
|
|
|
|
|
[m release];
|
|
|
|
|
|
|
|
|
|
m = [NSMenu new];
|
|
|
|
|
|
|
|
|
|
i = [[NSMenuItem alloc] initWithTitle:@"Full Screen"
|
|
|
|
|
action:@selector(calltogglefs:)
|
|
|
|
|
keyEquivalent:@"f"];
|
|
|
|
|
[m addItem:i];
|
|
|
|
|
[i release];
|
|
|
|
|
|
|
|
|
|
i = [[NSMenuItem alloc] initWithTitle:@"Quit"
|
|
|
|
|
action:@selector(terminate:)
|
|
|
|
|
keyEquivalent:@"q"];
|
|
|
|
|
[m addItem:i];
|
|
|
|
|
[i release];
|
|
|
|
|
|
|
|
|
|
[i0 setSubmenu:m];
|
|
|
|
|
[i0 release];
|
|
|
|
|
[m release];
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
|
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
static void
|
|
|
|
|
makeicon(void)
|
|
|
|
|
{
|
|
|
|
|
NSData *d;
|
|
|
|
|
NSImage *i;
|
|
|
|
|
|
|
|
|
|
d = [[NSData alloc]
|
|
|
|
|
initWithBytes:glenda_png
|
|
|
|
|
length:(sizeof glenda_png)];
|
|
|
|
|
|
|
|
|
|
i = [[NSImage alloc] initWithData:d];
|
|
|
|
|
[NSApp setApplicationIconImage:i];
|
|
|
|
|
[[NSApp dockTile] display];
|
|
|
|
|
[i release];
|
|
|
|
|
[d release];
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-06 10:10:43 -04:00
|
|
|
QLock snarfl;
|
|
|
|
|
|
|
|
|
|
char*
|
|
|
|
|
getsnarf(void)
|
|
|
|
|
{
|
|
|
|
|
NSPasteboard *pb;
|
2011-09-19 08:58:59 -04:00
|
|
|
NSString *s;
|
2011-09-06 10:10:43 -04:00
|
|
|
|
|
|
|
|
pb = [NSPasteboard generalPasteboard];
|
|
|
|
|
|
|
|
|
|
qlock(&snarfl);
|
2011-10-03 18:16:09 -04:00
|
|
|
s = [pb stringForType:NSPasteboardTypeString];
|
2011-09-06 10:10:43 -04:00
|
|
|
qunlock(&snarfl);
|
|
|
|
|
|
|
|
|
|
if(s)
|
|
|
|
|
return strdup((char*)[s UTF8String]);
|
|
|
|
|
else
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
putsnarf(char *s)
|
|
|
|
|
{
|
|
|
|
|
NSArray *t;
|
|
|
|
|
NSPasteboard *pb;
|
2011-09-19 08:58:59 -04:00
|
|
|
NSString *str;
|
2011-09-06 10:10:43 -04:00
|
|
|
|
|
|
|
|
if(strlen(s) >= SnarfSize)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
t = [NSArray arrayWithObject:NSPasteboardTypeString];
|
|
|
|
|
pb = [NSPasteboard generalPasteboard];
|
|
|
|
|
str = [[NSString alloc] initWithUTF8String:s];
|
|
|
|
|
|
|
|
|
|
qlock(&snarfl);
|
|
|
|
|
[pb declareTypes:t owner:nil];
|
2011-10-03 18:16:09 -04:00
|
|
|
[pb setString:str forType:NSPasteboardTypeString];
|
2011-09-06 10:10:43 -04:00
|
|
|
qunlock(&snarfl);
|
|
|
|
|
|
2011-10-03 18:16:09 -04:00
|
|
|
[str release];
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2011-09-19 08:58:59 -04:00
|
|
|
kicklabel(char *label)
|
2011-09-06 10:10:43 -04:00
|
|
|
{
|
2011-10-03 18:16:09 -04:00
|
|
|
NSString *s;
|
|
|
|
|
|
2011-09-19 08:58:59 -04:00
|
|
|
if(label == nil)
|
|
|
|
|
return;
|
|
|
|
|
|
2011-10-03 18:16:09 -04:00
|
|
|
s = [[NSString alloc] initWithUTF8String:label];
|
2011-10-12 13:40:35 -04:00
|
|
|
[win.ofs[0] setTitle:s];
|
|
|
|
|
[win.ofs[1] setTitle:s];
|
2011-10-03 18:16:09 -04:00
|
|
|
[[NSApp dockTile] setBadgeLabel:s];
|
|
|
|
|
[s release];
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2011-10-23 18:47:29 -04:00
|
|
|
setcursor(Cursor *cursor)
|
|
|
|
|
{
|
|
|
|
|
[appdelegate
|
|
|
|
|
performSelectorOnMainThread:@selector(callsetcursor0:)
|
|
|
|
|
withObject:[[NSValue valueWithPointer:cursor] retain]
|
|
|
|
|
waitUntilDone:YES];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
setcursor0(Cursor *c)
|
2011-09-19 08:58:59 -04:00
|
|
|
{
|
|
|
|
|
NSBitmapImageRep *r;
|
|
|
|
|
NSImage *i;
|
|
|
|
|
NSPoint p;
|
|
|
|
|
int b;
|
|
|
|
|
uchar *plane[5];
|
|
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
qlock(&win.cursorl);
|
2011-09-19 08:58:59 -04:00
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
if(win.cursor){
|
|
|
|
|
[win.cursor release];
|
|
|
|
|
win.cursor = nil;
|
2011-09-19 08:58:59 -04:00
|
|
|
}
|
2011-10-23 18:47:29 -04:00
|
|
|
|
|
|
|
|
if(c == nil && usebigarrow)
|
|
|
|
|
c = &bigarrow;
|
|
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
if(c){
|
|
|
|
|
r = [[NSBitmapImageRep alloc]
|
|
|
|
|
initWithBitmapDataPlanes:nil
|
|
|
|
|
pixelsWide:16
|
|
|
|
|
pixelsHigh:16
|
|
|
|
|
bitsPerSample:1
|
|
|
|
|
samplesPerPixel:2
|
|
|
|
|
hasAlpha:YES
|
|
|
|
|
isPlanar:YES
|
|
|
|
|
colorSpaceName:NSDeviceBlackColorSpace
|
|
|
|
|
bytesPerRow:2
|
|
|
|
|
bitsPerPixel:1];
|
|
|
|
|
|
|
|
|
|
[r getBitmapDataPlanes:plane];
|
|
|
|
|
|
|
|
|
|
for(b=0; b<2*16; b++){
|
|
|
|
|
plane[0][b] = c->set[b];
|
|
|
|
|
plane[1][b] = c->clr[b];
|
|
|
|
|
}
|
|
|
|
|
p = NSMakePoint(-c->offset.x, -c->offset.y);
|
|
|
|
|
i = [NSImage new];
|
|
|
|
|
[i addRepresentation:r];
|
2011-09-19 08:58:59 -04:00
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
win.cursor = [[NSCursor alloc] initWithImage:i hotSpot:p];
|
|
|
|
|
|
2011-10-23 18:47:29 -04:00
|
|
|
[win.cursor set];
|
2011-10-12 13:40:35 -04:00
|
|
|
[i release];
|
|
|
|
|
[r release];
|
|
|
|
|
}
|
2011-10-23 18:47:29 -04:00
|
|
|
|
2011-10-12 13:40:35 -04:00
|
|
|
qunlock(&win.cursorl);
|
|
|
|
|
[WIN invalidateCursorRectsForView:win.content];
|
2011-09-06 10:10:43 -04:00
|
|
|
}
|