Blame


1 933b9805 2020-01-13 rsc #define Cursor OSXCursor
2 933b9805 2020-01-13 rsc #define Point OSXPoint
3 933b9805 2020-01-13 rsc #define Rect OSXRect
4 933b9805 2020-01-13 rsc
5 933b9805 2020-01-13 rsc #import <Cocoa/Cocoa.h>
6 933b9805 2020-01-13 rsc #import <Metal/Metal.h>
7 933b9805 2020-01-13 rsc #import <QuartzCore/CAMetalLayer.h>
8 933b9805 2020-01-13 rsc
9 933b9805 2020-01-13 rsc #undef Cursor
10 933b9805 2020-01-13 rsc #undef Point
11 933b9805 2020-01-13 rsc #undef Rect
12 933b9805 2020-01-13 rsc
13 933b9805 2020-01-13 rsc #include <u.h>
14 933b9805 2020-01-13 rsc #include <libc.h>
15 933b9805 2020-01-13 rsc #include <thread.h>
16 933b9805 2020-01-13 rsc #include <draw.h>
17 933b9805 2020-01-13 rsc #include <memdraw.h>
18 88ed92aa 2020-01-13 rsc #include <memlayer.h>
19 88ed92aa 2020-01-13 rsc #include <mouse.h>
20 933b9805 2020-01-13 rsc #include <cursor.h>
21 88ed92aa 2020-01-13 rsc #include <keyboard.h>
22 88ed92aa 2020-01-13 rsc #include <drawfcall.h>
23 933b9805 2020-01-13 rsc #include "devdraw.h"
24 933b9805 2020-01-13 rsc #include "bigarrow.h"
25 933b9805 2020-01-13 rsc #include "glendapng.h"
26 933b9805 2020-01-13 rsc
27 933b9805 2020-01-13 rsc AUTOFRAMEWORK(Cocoa)
28 933b9805 2020-01-13 rsc AUTOFRAMEWORK(Metal)
29 933b9805 2020-01-13 rsc AUTOFRAMEWORK(QuartzCore)
30 04da0159 2020-01-13 rsc AUTOFRAMEWORK(CoreFoundation)
31 933b9805 2020-01-13 rsc
32 933b9805 2020-01-13 rsc #define LOG if(0)NSLog
33 933b9805 2020-01-13 rsc
34 892b3c46 2020-01-13 rsc // TODO: Maintain list of views for dock menu.
35 892b3c46 2020-01-13 rsc
36 933b9805 2020-01-13 rsc static void setprocname(const char*);
37 933b9805 2020-01-13 rsc static uint keycvt(uint);
38 933b9805 2020-01-13 rsc static uint msec(void);
39 94d381ec 2020-05-18 rsc
40 94d381ec 2020-05-18 rsc static void rpc_resizeimg(Client*);
41 94d381ec 2020-05-18 rsc static void rpc_resizewindow(Client*, Rectangle);
42 94d381ec 2020-05-18 rsc static void rpc_setcursor(Client*, Cursor*, Cursor2*);
43 94d381ec 2020-05-18 rsc static void rpc_setlabel(Client*, char*);
44 94d381ec 2020-05-18 rsc static void rpc_setmouse(Client*, Point);
45 94d381ec 2020-05-18 rsc static void rpc_topwin(Client*);
46 94d381ec 2020-05-18 rsc static void rpc_bouncemouse(Client*, Mouse);
47 94d381ec 2020-05-18 rsc static void rpc_flush(Client*, Rectangle);
48 94d381ec 2020-05-18 rsc
49 94d381ec 2020-05-18 rsc static ClientImpl macimpl = {
50 94d381ec 2020-05-18 rsc rpc_resizeimg,
51 94d381ec 2020-05-18 rsc rpc_resizewindow,
52 94d381ec 2020-05-18 rsc rpc_setcursor,
53 94d381ec 2020-05-18 rsc rpc_setlabel,
54 94d381ec 2020-05-18 rsc rpc_setmouse,
55 94d381ec 2020-05-18 rsc rpc_topwin,
56 94d381ec 2020-05-18 rsc rpc_bouncemouse,
57 94d381ec 2020-05-18 rsc rpc_flush
58 94d381ec 2020-05-18 rsc };
59 933b9805 2020-01-13 rsc
60 b1a086de 2020-01-13 rsc @class DrawView;
61 b1a086de 2020-01-13 rsc @class DrawLayer;
62 b1a086de 2020-01-13 rsc
63 843e5af1 2020-01-13 rsc @interface AppDelegate : NSObject<NSApplicationDelegate>
64 933b9805 2020-01-13 rsc @end
65 843e5af1 2020-01-13 rsc
66 933b9805 2020-01-13 rsc static AppDelegate *myApp = NULL;
67 933b9805 2020-01-13 rsc
68 933b9805 2020-01-13 rsc void
69 41547af3 2020-01-13 rsc gfx_main(void)
70 933b9805 2020-01-13 rsc {
71 892b3c46 2020-01-13 rsc if(client0)
72 892b3c46 2020-01-13 rsc setprocname(argv0);
73 933b9805 2020-01-13 rsc
74 933b9805 2020-01-13 rsc @autoreleasepool{
75 933b9805 2020-01-13 rsc [NSApplication sharedApplication];
76 933b9805 2020-01-13 rsc [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
77 933b9805 2020-01-13 rsc myApp = [AppDelegate new];
78 933b9805 2020-01-13 rsc [NSApp setDelegate:myApp];
79 933b9805 2020-01-13 rsc [NSApp run];
80 933b9805 2020-01-13 rsc }
81 933b9805 2020-01-13 rsc }
82 933b9805 2020-01-13 rsc
83 41547af3 2020-01-13 rsc
84 933b9805 2020-01-13 rsc void
85 41547af3 2020-01-13 rsc rpc_shutdown(void)
86 933b9805 2020-01-13 rsc {
87 933b9805 2020-01-13 rsc [NSApp terminate:myApp];
88 933b9805 2020-01-13 rsc }
89 933b9805 2020-01-13 rsc
90 933b9805 2020-01-13 rsc @implementation AppDelegate
91 b1a086de 2020-01-13 rsc - (void)applicationDidFinishLaunching:(id)arg
92 b1a086de 2020-01-13 rsc {
93 b1a086de 2020-01-13 rsc NSMenu *m, *sm;
94 b1a086de 2020-01-13 rsc NSData *d;
95 b1a086de 2020-01-13 rsc NSImage *i;
96 933b9805 2020-01-13 rsc
97 b1a086de 2020-01-13 rsc LOG(@"applicationDidFinishLaunching");
98 b1a086de 2020-01-13 rsc
99 b1a086de 2020-01-13 rsc sm = [NSMenu new];
100 b1a086de 2020-01-13 rsc [sm addItemWithTitle:@"Toggle Full Screen" action:@selector(toggleFullScreen:) keyEquivalent:@"f"];
101 b1a086de 2020-01-13 rsc [sm addItemWithTitle:@"Hide" action:@selector(hide:) keyEquivalent:@"h"];
102 b1a086de 2020-01-13 rsc [sm addItemWithTitle:@"Quit" action:@selector(terminate:) keyEquivalent:@"q"];
103 b1a086de 2020-01-13 rsc m = [NSMenu new];
104 b1a086de 2020-01-13 rsc [m addItemWithTitle:@"DEVDRAW" action:NULL keyEquivalent:@""];
105 b1a086de 2020-01-13 rsc [m setSubmenu:sm forItem:[m itemWithTitle:@"DEVDRAW"]];
106 b1a086de 2020-01-13 rsc [NSApp setMainMenu:m];
107 b1a086de 2020-01-13 rsc
108 b1a086de 2020-01-13 rsc d = [[NSData alloc] initWithBytes:glenda_png length:(sizeof glenda_png)];
109 b1a086de 2020-01-13 rsc i = [[NSImage alloc] initWithData:d];
110 b1a086de 2020-01-13 rsc [NSApp setApplicationIconImage:i];
111 b1a086de 2020-01-13 rsc [[NSApp dockTile] display];
112 50923426 2020-01-13 rsc
113 41547af3 2020-01-13 rsc gfx_started();
114 b1a086de 2020-01-13 rsc }
115 b1a086de 2020-01-13 rsc
116 b1a086de 2020-01-13 rsc - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication {
117 892b3c46 2020-01-13 rsc return client0 != nil;
118 b1a086de 2020-01-13 rsc }
119 b1a086de 2020-01-13 rsc @end
120 b1a086de 2020-01-13 rsc
121 b1a086de 2020-01-13 rsc @interface DrawLayer : CAMetalLayer
122 b1a086de 2020-01-13 rsc @property (nonatomic, retain) id<MTLCommandQueue> cmd;
123 b1a086de 2020-01-13 rsc @property (nonatomic, retain) id<MTLTexture> texture;
124 b1a086de 2020-01-13 rsc @end
125 b1a086de 2020-01-13 rsc
126 b1a086de 2020-01-13 rsc @implementation DrawLayer
127 b1a086de 2020-01-13 rsc - (void)display
128 b1a086de 2020-01-13 rsc {
129 b1a086de 2020-01-13 rsc LOG(@"display");
130 b1a086de 2020-01-13 rsc LOG(@"display query drawable");
131 b1a086de 2020-01-13 rsc
132 b1a086de 2020-01-13 rsc @autoreleasepool{
133 b1a086de 2020-01-13 rsc id<CAMetalDrawable> drawable = [self nextDrawable];
134 b1a086de 2020-01-13 rsc if(!drawable){
135 b1a086de 2020-01-13 rsc LOG(@"display couldn't get drawable");
136 b1a086de 2020-01-13 rsc [self setNeedsDisplay];
137 b1a086de 2020-01-13 rsc return;
138 b1a086de 2020-01-13 rsc }
139 50923426 2020-01-13 rsc
140 b1a086de 2020-01-13 rsc LOG(@"display got drawable");
141 50923426 2020-01-13 rsc
142 b1a086de 2020-01-13 rsc id<MTLCommandBuffer> cbuf = [self.cmd commandBuffer];
143 b1a086de 2020-01-13 rsc id<MTLBlitCommandEncoder> blit = [cbuf blitCommandEncoder];
144 b1a086de 2020-01-13 rsc [blit copyFromTexture:self.texture
145 b1a086de 2020-01-13 rsc sourceSlice:0
146 b1a086de 2020-01-13 rsc sourceLevel:0
147 b1a086de 2020-01-13 rsc sourceOrigin:MTLOriginMake(0, 0, 0)
148 b1a086de 2020-01-13 rsc sourceSize:MTLSizeMake(self.texture.width, self.texture.height, self.texture.depth)
149 b1a086de 2020-01-13 rsc toTexture:drawable.texture
150 b1a086de 2020-01-13 rsc destinationSlice:0
151 b1a086de 2020-01-13 rsc destinationLevel:0
152 b1a086de 2020-01-13 rsc destinationOrigin:MTLOriginMake(0, 0, 0)];
153 b1a086de 2020-01-13 rsc [blit endEncoding];
154 50923426 2020-01-13 rsc
155 b1a086de 2020-01-13 rsc [cbuf presentDrawable:drawable];
156 b1a086de 2020-01-13 rsc drawable = nil;
157 b1a086de 2020-01-13 rsc [cbuf addCompletedHandler:^(id<MTLCommandBuffer> cmdBuff){
158 b1a086de 2020-01-13 rsc if(cmdBuff.error){
159 b1a086de 2020-01-13 rsc NSLog(@"command buffer finished with error: %@",
160 b1a086de 2020-01-13 rsc cmdBuff.error.localizedDescription);
161 b1a086de 2020-01-13 rsc }else
162 b1a086de 2020-01-13 rsc LOG(@"command buffer finishes present drawable");
163 b1a086de 2020-01-13 rsc }];
164 b1a086de 2020-01-13 rsc [cbuf commit];
165 b1a086de 2020-01-13 rsc }
166 b1a086de 2020-01-13 rsc LOG(@"display commit");
167 b1a086de 2020-01-13 rsc }
168 b1a086de 2020-01-13 rsc @end
169 b1a086de 2020-01-13 rsc
170 b1a086de 2020-01-13 rsc @interface DrawView : NSView<NSTextInputClient,NSWindowDelegate>
171 b1a086de 2020-01-13 rsc @property (nonatomic, assign) Client *client;
172 b1a086de 2020-01-13 rsc @property (nonatomic, retain) DrawLayer *dlayer;
173 b1a086de 2020-01-13 rsc @property (nonatomic, retain) NSWindow *win;
174 b1a086de 2020-01-13 rsc @property (nonatomic, retain) NSCursor *currentCursor;
175 b1a086de 2020-01-13 rsc @property (nonatomic, assign) Memimage *img;
176 b1a086de 2020-01-13 rsc
177 b1a086de 2020-01-13 rsc - (id)attach:(Client*)client winsize:(char*)winsize label:(char*)label;
178 b1a086de 2020-01-13 rsc - (void)topwin;
179 b1a086de 2020-01-13 rsc - (void)setlabel:(char*)label;
180 b1a086de 2020-01-13 rsc - (void)setcursor:(Cursor*)c cursor2:(Cursor2*)c2;
181 b1a086de 2020-01-13 rsc - (void)setmouse:(Point)p;
182 b1a086de 2020-01-13 rsc - (void)clearInput;
183 b1a086de 2020-01-13 rsc - (void)getmouse:(NSEvent*)e;
184 b1a086de 2020-01-13 rsc - (void)sendmouse:(NSUInteger)b;
185 b1a086de 2020-01-13 rsc - (void)resetLastInputRect;
186 b1a086de 2020-01-13 rsc - (void)enlargeLastInputRect:(NSRect)r;
187 b1a086de 2020-01-13 rsc @end
188 b1a086de 2020-01-13 rsc
189 b1a086de 2020-01-13 rsc @implementation DrawView
190 933b9805 2020-01-13 rsc {
191 b1a086de 2020-01-13 rsc NSMutableString *_tmpText;
192 b1a086de 2020-01-13 rsc NSRange _markedRange;
193 b1a086de 2020-01-13 rsc NSRange _selectedRange;
194 b1a086de 2020-01-13 rsc NSRect _lastInputRect; // The view is flipped, this is not.
195 b1a086de 2020-01-13 rsc BOOL _tapping;
196 b1a086de 2020-01-13 rsc NSUInteger _tapFingers;
197 b1a086de 2020-01-13 rsc NSUInteger _tapTime;
198 b1a086de 2020-01-13 rsc }
199 b1a086de 2020-01-13 rsc
200 b1a086de 2020-01-13 rsc - (id)init
201 b1a086de 2020-01-13 rsc {
202 b1a086de 2020-01-13 rsc LOG(@"View init");
203 b1a086de 2020-01-13 rsc self = [super init];
204 b1a086de 2020-01-13 rsc [self setAllowedTouchTypes:NSTouchTypeMaskDirect|NSTouchTypeMaskIndirect];
205 b1a086de 2020-01-13 rsc _tmpText = [[NSMutableString alloc] initWithCapacity:2];
206 b1a086de 2020-01-13 rsc _markedRange = NSMakeRange(NSNotFound, 0);
207 b1a086de 2020-01-13 rsc _selectedRange = NSMakeRange(0, 0);
208 b1a086de 2020-01-13 rsc return self;
209 b1a086de 2020-01-13 rsc }
210 b1a086de 2020-01-13 rsc
211 b1a086de 2020-01-13 rsc - (CALayer*)makeBackingLayer { return [DrawLayer layer]; }
212 b1a086de 2020-01-13 rsc - (BOOL)wantsUpdateLayer { return YES; }
213 b1a086de 2020-01-13 rsc - (BOOL)isOpaque { return YES; }
214 b1a086de 2020-01-13 rsc - (BOOL)isFlipped { return YES; }
215 b1a086de 2020-01-13 rsc - (BOOL)acceptsFirstResponder { return YES; }
216 b1a086de 2020-01-13 rsc
217 41547af3 2020-01-13 rsc // rpc_attach allocates a new screen window with the given label and size
218 b1a086de 2020-01-13 rsc // and attaches it to client c (by setting c->view).
219 b1a086de 2020-01-13 rsc Memimage*
220 41547af3 2020-01-13 rsc rpc_attach(Client *c, char *label, char *winsize)
221 b1a086de 2020-01-13 rsc {
222 b1a086de 2020-01-13 rsc LOG(@"attachscreen(%s, %s)", label, winsize);
223 50923426 2020-01-13 rsc
224 94d381ec 2020-05-18 rsc c->impl = &macimpl;
225 b1a086de 2020-01-13 rsc dispatch_sync(dispatch_get_main_queue(), ^(void) {
226 b1a086de 2020-01-13 rsc @autoreleasepool {
227 b1a086de 2020-01-13 rsc DrawView *view = [[DrawView new] attach:c winsize:winsize label:label];
228 b1a086de 2020-01-13 rsc [view initimg];
229 b1a086de 2020-01-13 rsc }
230 b1a086de 2020-01-13 rsc });
231 b1a086de 2020-01-13 rsc return ((__bridge DrawView*)c->view).img;
232 b1a086de 2020-01-13 rsc }
233 b1a086de 2020-01-13 rsc
234 b1a086de 2020-01-13 rsc - (id)attach:(Client*)client winsize:(char*)winsize label:(char*)label {
235 933b9805 2020-01-13 rsc NSRect r, sr;
236 933b9805 2020-01-13 rsc Rectangle wr;
237 933b9805 2020-01-13 rsc int set;
238 933b9805 2020-01-13 rsc char *s;
239 933b9805 2020-01-13 rsc NSArray *allDevices;
240 933b9805 2020-01-13 rsc
241 7f6458b0 2021-01-06 rsc NSWindowStyleMask Winstyle = NSWindowStyleMaskTitled
242 933b9805 2020-01-13 rsc | NSWindowStyleMaskClosable
243 933b9805 2020-01-13 rsc | NSWindowStyleMaskMiniaturizable
244 933b9805 2020-01-13 rsc | NSWindowStyleMaskResizable;
245 933b9805 2020-01-13 rsc
246 7f6458b0 2021-01-06 rsc if(label == nil || *label == '\0')
247 7f6458b0 2021-01-06 rsc Winstyle &= ~NSWindowStyleMaskTitled;
248 7f6458b0 2021-01-06 rsc
249 b1a086de 2020-01-13 rsc s = winsize;
250 933b9805 2020-01-13 rsc sr = [[NSScreen mainScreen] frame];
251 933b9805 2020-01-13 rsc r = [[NSScreen mainScreen] visibleFrame];
252 933b9805 2020-01-13 rsc
253 933b9805 2020-01-13 rsc LOG(@"makewin(%s)", s);
254 892b3c46 2020-01-13 rsc if(s == nil || *s == '\0' || parsewinsize(s, &wr, &set) < 0) {
255 933b9805 2020-01-13 rsc wr = Rect(0, 0, sr.size.width*2/3, sr.size.height*2/3);
256 933b9805 2020-01-13 rsc set = 0;
257 933b9805 2020-01-13 rsc }
258 933b9805 2020-01-13 rsc
259 933b9805 2020-01-13 rsc r.origin.x = wr.min.x;
260 933b9805 2020-01-13 rsc r.origin.y = sr.size.height-wr.max.y; /* winsize is top-left-based */
261 933b9805 2020-01-13 rsc r.size.width = fmin(Dx(wr), r.size.width);
262 933b9805 2020-01-13 rsc r.size.height = fmin(Dy(wr), r.size.height);
263 933b9805 2020-01-13 rsc r = [NSWindow contentRectForFrameRect:r styleMask:Winstyle];
264 933b9805 2020-01-13 rsc
265 843e5af1 2020-01-13 rsc NSWindow *win = [[NSWindow alloc]
266 933b9805 2020-01-13 rsc initWithContentRect:r
267 933b9805 2020-01-13 rsc styleMask:Winstyle
268 933b9805 2020-01-13 rsc backing:NSBackingStoreBuffered defer:NO];
269 933b9805 2020-01-13 rsc [win setTitle:@"devdraw"];
270 933b9805 2020-01-13 rsc
271 933b9805 2020-01-13 rsc if(!set)
272 933b9805 2020-01-13 rsc [win center];
273 933b9805 2020-01-13 rsc [win setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
274 933b9805 2020-01-13 rsc [win setContentMinSize:NSMakeSize(64,64)];
275 933b9805 2020-01-13 rsc [win setOpaque:YES];
276 933b9805 2020-01-13 rsc [win setRestorable:NO];
277 933b9805 2020-01-13 rsc [win setAcceptsMouseMovedEvents:YES];
278 933b9805 2020-01-13 rsc
279 b1a086de 2020-01-13 rsc client->view = CFBridgingRetain(self);
280 b1a086de 2020-01-13 rsc self.client = client;
281 b1a086de 2020-01-13 rsc self.win = win;
282 b1a086de 2020-01-13 rsc self.currentCursor = nil;
283 b1a086de 2020-01-13 rsc [win setContentView:self];
284 b1a086de 2020-01-13 rsc [win setDelegate:self];
285 b1a086de 2020-01-13 rsc [self setWantsLayer:YES];
286 b1a086de 2020-01-13 rsc [self setLayerContentsRedrawPolicy:NSViewLayerContentsRedrawOnSetNeedsDisplay];
287 50923426 2020-01-13 rsc
288 b1a086de 2020-01-13 rsc id<MTLDevice> device = nil;
289 933b9805 2020-01-13 rsc allDevices = MTLCopyAllDevices();
290 933b9805 2020-01-13 rsc for(id mtlDevice in allDevices) {
291 933b9805 2020-01-13 rsc if ([mtlDevice isLowPower] && ![mtlDevice isRemovable]) {
292 933b9805 2020-01-13 rsc device = mtlDevice;
293 933b9805 2020-01-13 rsc break;
294 933b9805 2020-01-13 rsc }
295 933b9805 2020-01-13 rsc }
296 933b9805 2020-01-13 rsc if(!device)
297 933b9805 2020-01-13 rsc device = MTLCreateSystemDefaultDevice();
298 933b9805 2020-01-13 rsc
299 b1a086de 2020-01-13 rsc DrawLayer *layer = (DrawLayer*)[self layer];
300 b1a086de 2020-01-13 rsc self.dlayer = layer;
301 933b9805 2020-01-13 rsc layer.device = device;
302 b1a086de 2020-01-13 rsc layer.cmd = [device newCommandQueue];
303 933b9805 2020-01-13 rsc layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
304 933b9805 2020-01-13 rsc layer.framebufferOnly = YES;
305 933b9805 2020-01-13 rsc layer.opaque = YES;
306 933b9805 2020-01-13 rsc
307 933b9805 2020-01-13 rsc // We use a default transparent layer on top of the CAMetalLayer.
308 933b9805 2020-01-13 rsc // This seems to make fullscreen applications behave.
309 b1a086de 2020-01-13 rsc // Specifically, without this code if you enter full screen with Cmd-F,
310 b1a086de 2020-01-13 rsc // the screen goes black until the first mouse click.
311 b1a086de 2020-01-13 rsc if(1) {
312 933b9805 2020-01-13 rsc CALayer *stub = [CALayer layer];
313 933b9805 2020-01-13 rsc stub.frame = CGRectMake(0, 0, 1, 1);
314 933b9805 2020-01-13 rsc [stub setNeedsDisplay];
315 933b9805 2020-01-13 rsc [layer addSublayer:stub];
316 933b9805 2020-01-13 rsc }
317 933b9805 2020-01-13 rsc
318 933b9805 2020-01-13 rsc [NSEvent setMouseCoalescingEnabled:NO];
319 933b9805 2020-01-13 rsc
320 b1a086de 2020-01-13 rsc [self topwin];
321 b1a086de 2020-01-13 rsc [self setlabel:label];
322 b1a086de 2020-01-13 rsc [self setcursor:nil cursor2:nil];
323 50923426 2020-01-13 rsc
324 b1a086de 2020-01-13 rsc return self;
325 933b9805 2020-01-13 rsc }
326 933b9805 2020-01-13 rsc
327 b1a086de 2020-01-13 rsc // rpc_topwin moves the window to the top of the desktop.
328 b1a086de 2020-01-13 rsc // Called from an RPC thread with no client lock held.
329 94d381ec 2020-05-18 rsc static void
330 b1a086de 2020-01-13 rsc rpc_topwin(Client *c)
331 933b9805 2020-01-13 rsc {
332 b1a086de 2020-01-13 rsc DrawView *view = (__bridge DrawView*)c->view;
333 b1a086de 2020-01-13 rsc dispatch_sync(dispatch_get_main_queue(), ^(void) {
334 b1a086de 2020-01-13 rsc [view topwin];
335 b1a086de 2020-01-13 rsc });
336 933b9805 2020-01-13 rsc }
337 933b9805 2020-01-13 rsc
338 b1a086de 2020-01-13 rsc - (void)topwin {
339 b1a086de 2020-01-13 rsc [self.win makeKeyAndOrderFront:nil];
340 b1a086de 2020-01-13 rsc [NSApp activateIgnoringOtherApps:YES];
341 b1a086de 2020-01-13 rsc }
342 933b9805 2020-01-13 rsc
343 b1a086de 2020-01-13 rsc // rpc_setlabel updates the client window's label.
344 b1a086de 2020-01-13 rsc // If label == nil, the call is a no-op.
345 b1a086de 2020-01-13 rsc // Called from an RPC thread with no client lock held.
346 94d381ec 2020-05-18 rsc static void
347 b1a086de 2020-01-13 rsc rpc_setlabel(Client *client, char *label)
348 933b9805 2020-01-13 rsc {
349 b1a086de 2020-01-13 rsc DrawView *view = (__bridge DrawView*)client->view;
350 b1a086de 2020-01-13 rsc dispatch_sync(dispatch_get_main_queue(), ^(void){
351 b1a086de 2020-01-13 rsc [view setlabel:label];
352 b1a086de 2020-01-13 rsc });
353 b1a086de 2020-01-13 rsc }
354 933b9805 2020-01-13 rsc
355 b1a086de 2020-01-13 rsc - (void)setlabel:(char*)label {
356 b1a086de 2020-01-13 rsc LOG(@"setlabel(%s)", label);
357 b1a086de 2020-01-13 rsc if(label == nil)
358 b1a086de 2020-01-13 rsc return;
359 933b9805 2020-01-13 rsc
360 b1a086de 2020-01-13 rsc @autoreleasepool{
361 b1a086de 2020-01-13 rsc NSString *s = [[NSString alloc] initWithUTF8String:label];
362 b1a086de 2020-01-13 rsc [self.win setTitle:s];
363 892b3c46 2020-01-13 rsc if(client0)
364 892b3c46 2020-01-13 rsc [[NSApp dockTile] setBadgeLabel:s];
365 b1a086de 2020-01-13 rsc }
366 b1a086de 2020-01-13 rsc }
367 933b9805 2020-01-13 rsc
368 b1a086de 2020-01-13 rsc // rpc_setcursor updates the client window's cursor image.
369 b1a086de 2020-01-13 rsc // Either c and c2 are both non-nil, or they are both nil to use the default arrow.
370 b1a086de 2020-01-13 rsc // Called from an RPC thread with no client lock held.
371 94d381ec 2020-05-18 rsc static void
372 b1a086de 2020-01-13 rsc rpc_setcursor(Client *client, Cursor *c, Cursor2 *c2)
373 b1a086de 2020-01-13 rsc {
374 b1a086de 2020-01-13 rsc DrawView *view = (__bridge DrawView*)client->view;
375 b1a086de 2020-01-13 rsc dispatch_sync(dispatch_get_main_queue(), ^(void){
376 b1a086de 2020-01-13 rsc [view setcursor:c cursor2:c2];
377 b1a086de 2020-01-13 rsc });
378 933b9805 2020-01-13 rsc }
379 933b9805 2020-01-13 rsc
380 b1a086de 2020-01-13 rsc - (void)setcursor:(Cursor*)c cursor2:(Cursor2*)c2 {
381 b1a086de 2020-01-13 rsc if(!c) {
382 b1a086de 2020-01-13 rsc c = &bigarrow;
383 b1a086de 2020-01-13 rsc c2 = &bigarrow2;
384 b1a086de 2020-01-13 rsc }
385 933b9805 2020-01-13 rsc
386 933b9805 2020-01-13 rsc NSBitmapImageRep *r, *r2;
387 933b9805 2020-01-13 rsc NSImage *i;
388 933b9805 2020-01-13 rsc NSPoint p;
389 933b9805 2020-01-13 rsc uchar *plane[5], *plane2[5];
390 933b9805 2020-01-13 rsc uint b;
391 933b9805 2020-01-13 rsc
392 933b9805 2020-01-13 rsc r = [[NSBitmapImageRep alloc]
393 933b9805 2020-01-13 rsc initWithBitmapDataPlanes:nil
394 933b9805 2020-01-13 rsc pixelsWide:16
395 933b9805 2020-01-13 rsc pixelsHigh:16
396 933b9805 2020-01-13 rsc bitsPerSample:1
397 933b9805 2020-01-13 rsc samplesPerPixel:2
398 933b9805 2020-01-13 rsc hasAlpha:YES
399 933b9805 2020-01-13 rsc isPlanar:YES
400 933b9805 2020-01-13 rsc colorSpaceName:NSDeviceWhiteColorSpace
401 933b9805 2020-01-13 rsc bytesPerRow:2
402 933b9805 2020-01-13 rsc bitsPerPixel:0];
403 933b9805 2020-01-13 rsc [r getBitmapDataPlanes:plane];
404 933b9805 2020-01-13 rsc for(b=0; b<nelem(c->set); b++){
405 933b9805 2020-01-13 rsc plane[0][b] = ~c->set[b] & c->clr[b];
406 933b9805 2020-01-13 rsc plane[1][b] = c->set[b] | c->clr[b];
407 933b9805 2020-01-13 rsc }
408 933b9805 2020-01-13 rsc
409 933b9805 2020-01-13 rsc r2 = [[NSBitmapImageRep alloc]
410 933b9805 2020-01-13 rsc initWithBitmapDataPlanes:nil
411 933b9805 2020-01-13 rsc pixelsWide:32
412 933b9805 2020-01-13 rsc pixelsHigh:32
413 933b9805 2020-01-13 rsc bitsPerSample:1
414 933b9805 2020-01-13 rsc samplesPerPixel:2
415 933b9805 2020-01-13 rsc hasAlpha:YES
416 933b9805 2020-01-13 rsc isPlanar:YES
417 933b9805 2020-01-13 rsc colorSpaceName:NSDeviceWhiteColorSpace
418 933b9805 2020-01-13 rsc bytesPerRow:4
419 933b9805 2020-01-13 rsc bitsPerPixel:0];
420 933b9805 2020-01-13 rsc [r2 getBitmapDataPlanes:plane2];
421 933b9805 2020-01-13 rsc for(b=0; b<nelem(c2->set); b++){
422 933b9805 2020-01-13 rsc plane2[0][b] = ~c2->set[b] & c2->clr[b];
423 933b9805 2020-01-13 rsc plane2[1][b] = c2->set[b] | c2->clr[b];
424 933b9805 2020-01-13 rsc }
425 933b9805 2020-01-13 rsc
426 b1a086de 2020-01-13 rsc static BOOL debug = NO;
427 b1a086de 2020-01-13 rsc if(debug){
428 933b9805 2020-01-13 rsc NSData *data = [r representationUsingType: NSBitmapImageFileTypeBMP properties: @{}];
429 933b9805 2020-01-13 rsc [data writeToFile: @"/tmp/r.bmp" atomically: NO];
430 933b9805 2020-01-13 rsc data = [r2 representationUsingType: NSBitmapImageFileTypeBMP properties: @{}];
431 933b9805 2020-01-13 rsc [data writeToFile: @"/tmp/r2.bmp" atomically: NO];
432 b1a086de 2020-01-13 rsc debug = NO;
433 933b9805 2020-01-13 rsc }
434 933b9805 2020-01-13 rsc
435 933b9805 2020-01-13 rsc i = [[NSImage alloc] initWithSize:NSMakeSize(16, 16)];
436 933b9805 2020-01-13 rsc [i addRepresentation:r2];
437 933b9805 2020-01-13 rsc [i addRepresentation:r];
438 933b9805 2020-01-13 rsc
439 933b9805 2020-01-13 rsc p = NSMakePoint(-c->offset.x, -c->offset.y);
440 b1a086de 2020-01-13 rsc self.currentCursor = [[NSCursor alloc] initWithImage:i hotSpot:p];
441 b1a086de 2020-01-13 rsc [self.win invalidateCursorRectsForView:self];
442 933b9805 2020-01-13 rsc }
443 933b9805 2020-01-13 rsc
444 b1a086de 2020-01-13 rsc - (void)initimg {
445 41547af3 2020-01-13 rsc @autoreleasepool {
446 41547af3 2020-01-13 rsc CGFloat scale;
447 41547af3 2020-01-13 rsc NSSize size;
448 41547af3 2020-01-13 rsc MTLTextureDescriptor *textureDesc;
449 50923426 2020-01-13 rsc
450 41547af3 2020-01-13 rsc size = [self convertSizeToBacking:[self bounds].size];
451 41547af3 2020-01-13 rsc self.client->mouserect = Rect(0, 0, size.width, size.height);
452 50923426 2020-01-13 rsc
453 41547af3 2020-01-13 rsc LOG(@"initimg %.0f %.0f", size.width, size.height);
454 50923426 2020-01-13 rsc
455 41547af3 2020-01-13 rsc self.img = allocmemimage(self.client->mouserect, XRGB32);
456 41547af3 2020-01-13 rsc if(self.img == nil)
457 41547af3 2020-01-13 rsc panic("allocmemimage: %r");
458 41547af3 2020-01-13 rsc if(self.img->data == nil)
459 41547af3 2020-01-13 rsc panic("img->data == nil");
460 50923426 2020-01-13 rsc
461 41547af3 2020-01-13 rsc textureDesc = [MTLTextureDescriptor
462 41547af3 2020-01-13 rsc texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
463 41547af3 2020-01-13 rsc width:size.width
464 41547af3 2020-01-13 rsc height:size.height
465 41547af3 2020-01-13 rsc mipmapped:NO];
466 41547af3 2020-01-13 rsc textureDesc.allowGPUOptimizedContents = YES;
467 41547af3 2020-01-13 rsc textureDesc.usage = MTLTextureUsageShaderRead;
468 41547af3 2020-01-13 rsc textureDesc.cpuCacheMode = MTLCPUCacheModeWriteCombined;
469 41547af3 2020-01-13 rsc self.dlayer.texture = [self.dlayer.device newTextureWithDescriptor:textureDesc];
470 50923426 2020-01-13 rsc
471 41547af3 2020-01-13 rsc scale = [self.win backingScaleFactor];
472 41547af3 2020-01-13 rsc [self.dlayer setDrawableSize:size];
473 41547af3 2020-01-13 rsc [self.dlayer setContentsScale:scale];
474 50923426 2020-01-13 rsc
475 41547af3 2020-01-13 rsc // NOTE: This is not really the display DPI.
476 41547af3 2020-01-13 rsc // On retina, scale is 2; otherwise it is 1.
477 41547af3 2020-01-13 rsc // This formula gives us 220 for retina, 110 otherwise.
478 41547af3 2020-01-13 rsc // That's not quite right but it's close to correct.
479 41547af3 2020-01-13 rsc // https://en.wikipedia.org/wiki/Retina_display#Models
480 41547af3 2020-01-13 rsc self.client->displaydpi = scale * 110;
481 41547af3 2020-01-13 rsc }
482 933b9805 2020-01-13 rsc }
483 933b9805 2020-01-13 rsc
484 41547af3 2020-01-13 rsc // rpc_flush flushes changes to view.img's rectangle r
485 b1a086de 2020-01-13 rsc // to the on-screen window, making them visible.
486 b1a086de 2020-01-13 rsc // Called from an RPC thread with no client lock held.
487 94d381ec 2020-05-18 rsc static void
488 41547af3 2020-01-13 rsc rpc_flush(Client *client, Rectangle r)
489 933b9805 2020-01-13 rsc {
490 b1a086de 2020-01-13 rsc DrawView *view = (__bridge DrawView*)client->view;
491 b1a086de 2020-01-13 rsc dispatch_async(dispatch_get_main_queue(), ^(void){
492 41547af3 2020-01-13 rsc [view flush:r];
493 b1a086de 2020-01-13 rsc });
494 933b9805 2020-01-13 rsc }
495 933b9805 2020-01-13 rsc
496 41547af3 2020-01-13 rsc - (void)flush:(Rectangle)r {
497 b1a086de 2020-01-13 rsc @autoreleasepool{
498 41547af3 2020-01-13 rsc if(!rectclip(&r, Rect(0, 0, self.dlayer.texture.width, self.dlayer.texture.height)) || !rectclip(&r, self.img->r))
499 41547af3 2020-01-13 rsc return;
500 50923426 2020-01-13 rsc
501 587933c1 2020-05-18 rsc // drawlk protects the pixel data in self.img.
502 41547af3 2020-01-13 rsc // In addition to avoiding a technical data race,
503 41547af3 2020-01-13 rsc // the lock avoids drawing partial updates, which makes
504 41547af3 2020-01-13 rsc // animations like sweeping windows much less flickery.
505 587933c1 2020-05-18 rsc qlock(&drawlk);
506 b1a086de 2020-01-13 rsc [self.dlayer.texture
507 b1a086de 2020-01-13 rsc replaceRegion:MTLRegionMake2D(r.min.x, r.min.y, Dx(r), Dy(r))
508 b1a086de 2020-01-13 rsc mipmapLevel:0
509 b1a086de 2020-01-13 rsc withBytes:byteaddr(self.img, Pt(r.min.x, r.min.y))
510 b1a086de 2020-01-13 rsc bytesPerRow:self.img->width*sizeof(u32int)];
511 587933c1 2020-05-18 rsc qunlock(&drawlk);
512 b1a086de 2020-01-13 rsc
513 b1a086de 2020-01-13 rsc NSRect nr = NSMakeRect(r.min.x, r.min.y, Dx(r), Dy(r));
514 b1a086de 2020-01-13 rsc dispatch_time_t time;
515 b1a086de 2020-01-13 rsc
516 b1a086de 2020-01-13 rsc LOG(@"callsetNeedsDisplayInRect(%g, %g, %g, %g)", nr.origin.x, nr.origin.y, nr.size.width, nr.size.height);
517 b1a086de 2020-01-13 rsc nr = [self.win convertRectFromBacking:nr];
518 b1a086de 2020-01-13 rsc LOG(@"setNeedsDisplayInRect(%g, %g, %g, %g)", nr.origin.x, nr.origin.y, nr.size.width, nr.size.height);
519 b1a086de 2020-01-13 rsc [self.dlayer setNeedsDisplayInRect:nr];
520 50923426 2020-01-13 rsc
521 b1a086de 2020-01-13 rsc time = dispatch_time(DISPATCH_TIME_NOW, 16 * NSEC_PER_MSEC);
522 b1a086de 2020-01-13 rsc dispatch_after(time, dispatch_get_main_queue(), ^(void){
523 b1a086de 2020-01-13 rsc [self.dlayer setNeedsDisplayInRect:nr];
524 b1a086de 2020-01-13 rsc });
525 50923426 2020-01-13 rsc
526 b1a086de 2020-01-13 rsc [self enlargeLastInputRect:nr];
527 b1a086de 2020-01-13 rsc }
528 843e5af1 2020-01-13 rsc }
529 843e5af1 2020-01-13 rsc
530 b1a086de 2020-01-13 rsc // rpc_resizeimg forces the client window to discard its current window and make a new one.
531 b1a086de 2020-01-13 rsc // It is called when the user types Cmd-R to toggle whether retina mode is forced.
532 b1a086de 2020-01-13 rsc // Called from an RPC thread with no client lock held.
533 94d381ec 2020-05-18 rsc static void
534 b1a086de 2020-01-13 rsc rpc_resizeimg(Client *c)
535 933b9805 2020-01-13 rsc {
536 b1a086de 2020-01-13 rsc DrawView *view = (__bridge DrawView*)c->view;
537 f66f0a58 2020-02-03 noreply dispatch_async(dispatch_get_main_queue(), ^(void){
538 b1a086de 2020-01-13 rsc [view resizeimg];
539 b1a086de 2020-01-13 rsc });
540 933b9805 2020-01-13 rsc }
541 933b9805 2020-01-13 rsc
542 b1a086de 2020-01-13 rsc - (void)resizeimg {
543 b1a086de 2020-01-13 rsc [self initimg];
544 41547af3 2020-01-13 rsc gfx_replacescreenimage(self.client, self.img);
545 933b9805 2020-01-13 rsc }
546 933b9805 2020-01-13 rsc
547 b1a086de 2020-01-13 rsc - (void)windowDidResize:(NSNotification *)notification {
548 b1a086de 2020-01-13 rsc if(![self inLiveResize] && self.img) {
549 b1a086de 2020-01-13 rsc [self resizeimg];
550 b1a086de 2020-01-13 rsc }
551 b1a086de 2020-01-13 rsc }
552 b1a086de 2020-01-13 rsc - (void)viewDidEndLiveResize
553 933b9805 2020-01-13 rsc {
554 b1a086de 2020-01-13 rsc [super viewDidEndLiveResize];
555 b1a086de 2020-01-13 rsc if(self.img)
556 b1a086de 2020-01-13 rsc [self resizeimg];
557 933b9805 2020-01-13 rsc }
558 933b9805 2020-01-13 rsc
559 b1a086de 2020-01-13 rsc - (void)viewDidChangeBackingProperties
560 933b9805 2020-01-13 rsc {
561 b1a086de 2020-01-13 rsc [super viewDidChangeBackingProperties];
562 b1a086de 2020-01-13 rsc if(self.img)
563 b1a086de 2020-01-13 rsc [self resizeimg];
564 933b9805 2020-01-13 rsc }
565 933b9805 2020-01-13 rsc
566 b1a086de 2020-01-13 rsc // rpc_resizewindow asks for the client window to be resized to size r.
567 b1a086de 2020-01-13 rsc // Called from an RPC thread with no client lock held.
568 94d381ec 2020-05-18 rsc static void
569 b1a086de 2020-01-13 rsc rpc_resizewindow(Client *c, Rectangle r)
570 933b9805 2020-01-13 rsc {
571 b1a086de 2020-01-13 rsc DrawView *view = (__bridge DrawView*)c->view;
572 b1a086de 2020-01-13 rsc
573 b1a086de 2020-01-13 rsc LOG(@"resizewindow %d %d %d %d", r.min.x, r.min.y, Dx(r), Dy(r));
574 b1a086de 2020-01-13 rsc dispatch_async(dispatch_get_main_queue(), ^(void){
575 b1a086de 2020-01-13 rsc NSSize s;
576 b1a086de 2020-01-13 rsc
577 b1a086de 2020-01-13 rsc s = [view convertSizeFromBacking:NSMakeSize(Dx(r), Dy(r))];
578 b1a086de 2020-01-13 rsc [view.win setContentSize:s];
579 b1a086de 2020-01-13 rsc });
580 933b9805 2020-01-13 rsc }
581 933b9805 2020-01-13 rsc
582 b1a086de 2020-01-13 rsc
583 b1a086de 2020-01-13 rsc - (void)windowDidBecomeKey:(id)arg {
584 b1a086de 2020-01-13 rsc [self sendmouse:0];
585 1d0d432c 2020-01-16 rsc }
586 1d0d432c 2020-01-16 rsc
587 1d0d432c 2020-01-16 rsc - (void)windowDidResignKey:(id)arg {
588 1d0d432c 2020-01-16 rsc gfx_abortcompose(self.client);
589 b1a086de 2020-01-13 rsc }
590 b1a086de 2020-01-13 rsc
591 933b9805 2020-01-13 rsc - (void)mouseMoved:(NSEvent*)e{ [self getmouse:e];}
592 933b9805 2020-01-13 rsc - (void)mouseDown:(NSEvent*)e{ [self getmouse:e];}
593 933b9805 2020-01-13 rsc - (void)mouseDragged:(NSEvent*)e{ [self getmouse:e];}
594 933b9805 2020-01-13 rsc - (void)mouseUp:(NSEvent*)e{ [self getmouse:e];}
595 933b9805 2020-01-13 rsc - (void)otherMouseDown:(NSEvent*)e{ [self getmouse:e];}
596 933b9805 2020-01-13 rsc - (void)otherMouseDragged:(NSEvent*)e{ [self getmouse:e];}
597 933b9805 2020-01-13 rsc - (void)otherMouseUp:(NSEvent*)e{ [self getmouse:e];}
598 933b9805 2020-01-13 rsc - (void)rightMouseDown:(NSEvent*)e{ [self getmouse:e];}
599 933b9805 2020-01-13 rsc - (void)rightMouseDragged:(NSEvent*)e{ [self getmouse:e];}
600 933b9805 2020-01-13 rsc - (void)rightMouseUp:(NSEvent*)e{ [self getmouse:e];}
601 933b9805 2020-01-13 rsc
602 933b9805 2020-01-13 rsc - (void)scrollWheel:(NSEvent*)e
603 933b9805 2020-01-13 rsc {
604 933b9805 2020-01-13 rsc NSInteger s;
605 933b9805 2020-01-13 rsc
606 933b9805 2020-01-13 rsc s = [e scrollingDeltaY];
607 933b9805 2020-01-13 rsc if(s > 0)
608 933b9805 2020-01-13 rsc [self sendmouse:8];
609 933b9805 2020-01-13 rsc else if (s < 0)
610 933b9805 2020-01-13 rsc [self sendmouse:16];
611 933b9805 2020-01-13 rsc }
612 933b9805 2020-01-13 rsc
613 933b9805 2020-01-13 rsc - (void)keyDown:(NSEvent*)e
614 933b9805 2020-01-13 rsc {
615 933b9805 2020-01-13 rsc LOG(@"keyDown to interpret");
616 933b9805 2020-01-13 rsc
617 933b9805 2020-01-13 rsc [self interpretKeyEvents:[NSArray arrayWithObject:e]];
618 933b9805 2020-01-13 rsc
619 933b9805 2020-01-13 rsc [self resetLastInputRect];
620 933b9805 2020-01-13 rsc }
621 933b9805 2020-01-13 rsc
622 933b9805 2020-01-13 rsc - (void)flagsChanged:(NSEvent*)e
623 933b9805 2020-01-13 rsc {
624 933b9805 2020-01-13 rsc static NSEventModifierFlags omod;
625 933b9805 2020-01-13 rsc NSEventModifierFlags m;
626 933b9805 2020-01-13 rsc uint b;
627 933b9805 2020-01-13 rsc
628 933b9805 2020-01-13 rsc LOG(@"flagsChanged");
629 933b9805 2020-01-13 rsc m = [e modifierFlags];
630 933b9805 2020-01-13 rsc
631 933b9805 2020-01-13 rsc b = [NSEvent pressedMouseButtons];
632 933b9805 2020-01-13 rsc b = (b&~6) | (b&4)>>1 | (b&2)<<1;
633 933b9805 2020-01-13 rsc if(b){
634 933b9805 2020-01-13 rsc if(m & ~omod & NSEventModifierFlagControl)
635 933b9805 2020-01-13 rsc b |= 1;
636 933b9805 2020-01-13 rsc if(m & ~omod & NSEventModifierFlagOption)
637 933b9805 2020-01-13 rsc b |= 2;
638 933b9805 2020-01-13 rsc if(m & ~omod & NSEventModifierFlagCommand)
639 933b9805 2020-01-13 rsc b |= 4;
640 933b9805 2020-01-13 rsc [self sendmouse:b];
641 933b9805 2020-01-13 rsc }else if(m & ~omod & NSEventModifierFlagOption)
642 b1a086de 2020-01-13 rsc gfx_keystroke(self.client, Kalt);
643 933b9805 2020-01-13 rsc
644 933b9805 2020-01-13 rsc omod = m;
645 933b9805 2020-01-13 rsc }
646 933b9805 2020-01-13 rsc
647 933b9805 2020-01-13 rsc - (void)magnifyWithEvent:(NSEvent*)e
648 933b9805 2020-01-13 rsc {
649 933b9805 2020-01-13 rsc if(fabs([e magnification]) > 0.02)
650 933b9805 2020-01-13 rsc [[self window] toggleFullScreen:nil];
651 933b9805 2020-01-13 rsc }
652 933b9805 2020-01-13 rsc
653 933b9805 2020-01-13 rsc - (void)touchesBeganWithEvent:(NSEvent*)e
654 933b9805 2020-01-13 rsc {
655 933b9805 2020-01-13 rsc _tapping = YES;
656 933b9805 2020-01-13 rsc _tapFingers = [e touchesMatchingPhase:NSTouchPhaseTouching inView:nil].count;
657 933b9805 2020-01-13 rsc _tapTime = msec();
658 933b9805 2020-01-13 rsc }
659 933b9805 2020-01-13 rsc - (void)touchesMovedWithEvent:(NSEvent*)e
660 933b9805 2020-01-13 rsc {
661 933b9805 2020-01-13 rsc _tapping = NO;
662 933b9805 2020-01-13 rsc }
663 933b9805 2020-01-13 rsc - (void)touchesEndedWithEvent:(NSEvent*)e
664 933b9805 2020-01-13 rsc {
665 933b9805 2020-01-13 rsc if(_tapping
666 933b9805 2020-01-13 rsc && [e touchesMatchingPhase:NSTouchPhaseTouching inView:nil].count == 0
667 933b9805 2020-01-13 rsc && msec() - _tapTime < 250){
668 933b9805 2020-01-13 rsc switch(_tapFingers){
669 933b9805 2020-01-13 rsc case 3:
670 933b9805 2020-01-13 rsc [self sendmouse:2];
671 933b9805 2020-01-13 rsc [self sendmouse:0];
672 933b9805 2020-01-13 rsc break;
673 933b9805 2020-01-13 rsc case 4:
674 933b9805 2020-01-13 rsc [self sendmouse:2];
675 933b9805 2020-01-13 rsc [self sendmouse:1];
676 933b9805 2020-01-13 rsc [self sendmouse:0];
677 933b9805 2020-01-13 rsc break;
678 933b9805 2020-01-13 rsc }
679 933b9805 2020-01-13 rsc _tapping = NO;
680 933b9805 2020-01-13 rsc }
681 933b9805 2020-01-13 rsc }
682 933b9805 2020-01-13 rsc - (void)touchesCancelledWithEvent:(NSEvent*)e
683 933b9805 2020-01-13 rsc {
684 933b9805 2020-01-13 rsc _tapping = NO;
685 933b9805 2020-01-13 rsc }
686 933b9805 2020-01-13 rsc
687 933b9805 2020-01-13 rsc - (void)getmouse:(NSEvent *)e
688 933b9805 2020-01-13 rsc {
689 933b9805 2020-01-13 rsc NSUInteger b;
690 933b9805 2020-01-13 rsc NSEventModifierFlags m;
691 933b9805 2020-01-13 rsc
692 933b9805 2020-01-13 rsc b = [NSEvent pressedMouseButtons];
693 933b9805 2020-01-13 rsc b = b&~6 | (b&4)>>1 | (b&2)<<1;
694 933b9805 2020-01-13 rsc b = mouseswap(b);
695 933b9805 2020-01-13 rsc
696 933b9805 2020-01-13 rsc if(b == 1){
697 933b9805 2020-01-13 rsc m = [e modifierFlags];
698 933b9805 2020-01-13 rsc if(m & NSEventModifierFlagOption){
699 b1a086de 2020-01-13 rsc gfx_abortcompose(self.client);
700 933b9805 2020-01-13 rsc b = 2;
701 933b9805 2020-01-13 rsc }else
702 933b9805 2020-01-13 rsc if(m & NSEventModifierFlagCommand)
703 933b9805 2020-01-13 rsc b = 4;
704 933b9805 2020-01-13 rsc }
705 933b9805 2020-01-13 rsc [self sendmouse:b];
706 933b9805 2020-01-13 rsc }
707 933b9805 2020-01-13 rsc
708 933b9805 2020-01-13 rsc - (void)sendmouse:(NSUInteger)b
709 933b9805 2020-01-13 rsc {
710 933b9805 2020-01-13 rsc NSPoint p;
711 933b9805 2020-01-13 rsc
712 933b9805 2020-01-13 rsc p = [self.window convertPointToBacking:
713 933b9805 2020-01-13 rsc [self.window mouseLocationOutsideOfEventStream]];
714 88ed92aa 2020-01-13 rsc p.y = Dy(self.client->mouserect) - p.y;
715 933b9805 2020-01-13 rsc // LOG(@"(%g, %g) <- sendmouse(%d)", p.x, p.y, (uint)b);
716 b1a086de 2020-01-13 rsc gfx_mousetrack(self.client, p.x, p.y, b, msec());
717 933b9805 2020-01-13 rsc if(b && _lastInputRect.size.width && _lastInputRect.size.height)
718 933b9805 2020-01-13 rsc [self resetLastInputRect];
719 933b9805 2020-01-13 rsc }
720 933b9805 2020-01-13 rsc
721 b1a086de 2020-01-13 rsc // rpc_setmouse moves the mouse cursor.
722 b1a086de 2020-01-13 rsc // Called from an RPC thread with no client lock held.
723 94d381ec 2020-05-18 rsc static void
724 b1a086de 2020-01-13 rsc rpc_setmouse(Client *c, Point p)
725 b1a086de 2020-01-13 rsc {
726 b1a086de 2020-01-13 rsc DrawView *view = (__bridge DrawView*)c->view;
727 b1a086de 2020-01-13 rsc dispatch_async(dispatch_get_main_queue(), ^(void){
728 b1a086de 2020-01-13 rsc [view setmouse:p];
729 b1a086de 2020-01-13 rsc });
730 933b9805 2020-01-13 rsc }
731 933b9805 2020-01-13 rsc
732 41547af3 2020-01-13 rsc - (void)setmouse:(Point)p {
733 b1a086de 2020-01-13 rsc @autoreleasepool{
734 b1a086de 2020-01-13 rsc NSPoint q;
735 b1a086de 2020-01-13 rsc
736 b1a086de 2020-01-13 rsc LOG(@"setmouse(%d,%d)", p.x, p.y);
737 b1a086de 2020-01-13 rsc q = [self.win convertPointFromBacking:NSMakePoint(p.x, p.y)];
738 b1a086de 2020-01-13 rsc LOG(@"(%g, %g) <- fromBacking", q.x, q.y);
739 b1a086de 2020-01-13 rsc q = [self convertPoint:q toView:nil];
740 b1a086de 2020-01-13 rsc LOG(@"(%g, %g) <- toWindow", q.x, q.y);
741 b1a086de 2020-01-13 rsc q = [self.win convertPointToScreen:q];
742 b1a086de 2020-01-13 rsc LOG(@"(%g, %g) <- toScreen", q.x, q.y);
743 b1a086de 2020-01-13 rsc // Quartz has the origin of the "global display
744 b1a086de 2020-01-13 rsc // coordinate space" at the top left of the primary
745 b1a086de 2020-01-13 rsc // screen with y increasing downward, while Cocoa has
746 b1a086de 2020-01-13 rsc // the origin at the bottom left of the primary screen
747 b1a086de 2020-01-13 rsc // with y increasing upward. We flip the coordinate
748 b1a086de 2020-01-13 rsc // with a negative sign and shift upward by the height
749 b1a086de 2020-01-13 rsc // of the primary screen.
750 b1a086de 2020-01-13 rsc q.y = NSScreen.screens[0].frame.size.height - q.y;
751 b1a086de 2020-01-13 rsc LOG(@"(%g, %g) <- setmouse", q.x, q.y);
752 b1a086de 2020-01-13 rsc CGWarpMouseCursorPosition(NSPointToCGPoint(q));
753 b1a086de 2020-01-13 rsc CGAssociateMouseAndMouseCursorPosition(true);
754 b1a086de 2020-01-13 rsc }
755 933b9805 2020-01-13 rsc }
756 933b9805 2020-01-13 rsc
757 b1a086de 2020-01-13 rsc
758 b1a086de 2020-01-13 rsc - (void)resetCursorRects {
759 b1a086de 2020-01-13 rsc [super resetCursorRects];
760 b1a086de 2020-01-13 rsc [self addCursorRect:self.bounds cursor:self.currentCursor];
761 933b9805 2020-01-13 rsc }
762 933b9805 2020-01-13 rsc
763 933b9805 2020-01-13 rsc // conforms to protocol NSTextInputClient
764 41547af3 2020-01-13 rsc - (BOOL)hasMarkedText { return _markedRange.location != NSNotFound; }
765 41547af3 2020-01-13 rsc - (NSRange)markedRange { return _markedRange; }
766 41547af3 2020-01-13 rsc - (NSRange)selectedRange { return _selectedRange; }
767 41547af3 2020-01-13 rsc
768 933b9805 2020-01-13 rsc - (void)setMarkedText:(id)string
769 933b9805 2020-01-13 rsc selectedRange:(NSRange)sRange
770 933b9805 2020-01-13 rsc replacementRange:(NSRange)rRange
771 933b9805 2020-01-13 rsc {
772 933b9805 2020-01-13 rsc NSString *str;
773 933b9805 2020-01-13 rsc
774 933b9805 2020-01-13 rsc LOG(@"setMarkedText: %@ (%ld, %ld) (%ld, %ld)", string,
775 933b9805 2020-01-13 rsc sRange.location, sRange.length,
776 933b9805 2020-01-13 rsc rRange.location, rRange.length);
777 933b9805 2020-01-13 rsc
778 933b9805 2020-01-13 rsc [self clearInput];
779 933b9805 2020-01-13 rsc
780 933b9805 2020-01-13 rsc if([string isKindOfClass:[NSAttributedString class]])
781 933b9805 2020-01-13 rsc str = [string string];
782 933b9805 2020-01-13 rsc else
783 933b9805 2020-01-13 rsc str = string;
784 933b9805 2020-01-13 rsc
785 933b9805 2020-01-13 rsc if(rRange.location == NSNotFound){
786 933b9805 2020-01-13 rsc if(_markedRange.location != NSNotFound){
787 933b9805 2020-01-13 rsc rRange = _markedRange;
788 933b9805 2020-01-13 rsc }else{
789 933b9805 2020-01-13 rsc rRange = _selectedRange;
790 933b9805 2020-01-13 rsc }
791 933b9805 2020-01-13 rsc }
792 933b9805 2020-01-13 rsc
793 933b9805 2020-01-13 rsc if(str.length == 0){
794 933b9805 2020-01-13 rsc [_tmpText deleteCharactersInRange:rRange];
795 933b9805 2020-01-13 rsc [self unmarkText];
796 933b9805 2020-01-13 rsc }else{
797 933b9805 2020-01-13 rsc _markedRange = NSMakeRange(rRange.location, str.length);
798 933b9805 2020-01-13 rsc [_tmpText replaceCharactersInRange:rRange withString:str];
799 933b9805 2020-01-13 rsc }
800 933b9805 2020-01-13 rsc _selectedRange.location = rRange.location + sRange.location;
801 933b9805 2020-01-13 rsc _selectedRange.length = sRange.length;
802 933b9805 2020-01-13 rsc
803 933b9805 2020-01-13 rsc if(_tmpText.length){
804 933b9805 2020-01-13 rsc uint i;
805 933b9805 2020-01-13 rsc LOG(@"text length %ld", _tmpText.length);
806 933b9805 2020-01-13 rsc for(i = 0; i <= _tmpText.length; ++i){
807 933b9805 2020-01-13 rsc if(i == _markedRange.location)
808 b1a086de 2020-01-13 rsc gfx_keystroke(self.client, '[');
809 933b9805 2020-01-13 rsc if(_selectedRange.length){
810 933b9805 2020-01-13 rsc if(i == _selectedRange.location)
811 b1a086de 2020-01-13 rsc gfx_keystroke(self.client, '{');
812 933b9805 2020-01-13 rsc if(i == NSMaxRange(_selectedRange))
813 b1a086de 2020-01-13 rsc gfx_keystroke(self.client, '}');
814 933b9805 2020-01-13 rsc }
815 933b9805 2020-01-13 rsc if(i == NSMaxRange(_markedRange))
816 b1a086de 2020-01-13 rsc gfx_keystroke(self.client, ']');
817 933b9805 2020-01-13 rsc if(i < _tmpText.length)
818 b1a086de 2020-01-13 rsc gfx_keystroke(self.client, [_tmpText characterAtIndex:i]);
819 933b9805 2020-01-13 rsc }
820 933b9805 2020-01-13 rsc int l;
821 933b9805 2020-01-13 rsc l = 1 + _tmpText.length - NSMaxRange(_selectedRange)
822 933b9805 2020-01-13 rsc + (_selectedRange.length > 0);
823 933b9805 2020-01-13 rsc LOG(@"move left %d", l);
824 933b9805 2020-01-13 rsc for(i = 0; i < l; ++i)
825 b1a086de 2020-01-13 rsc gfx_keystroke(self.client, Kleft);
826 933b9805 2020-01-13 rsc }
827 933b9805 2020-01-13 rsc
828 933b9805 2020-01-13 rsc LOG(@"text: \"%@\" (%ld,%ld) (%ld,%ld)", _tmpText,
829 933b9805 2020-01-13 rsc _markedRange.location, _markedRange.length,
830 933b9805 2020-01-13 rsc _selectedRange.location, _selectedRange.length);
831 933b9805 2020-01-13 rsc }
832 41547af3 2020-01-13 rsc
833 41547af3 2020-01-13 rsc - (void)unmarkText {
834 933b9805 2020-01-13 rsc //NSUInteger i;
835 933b9805 2020-01-13 rsc NSUInteger len;
836 933b9805 2020-01-13 rsc
837 933b9805 2020-01-13 rsc LOG(@"unmarkText");
838 933b9805 2020-01-13 rsc len = [_tmpText length];
839 933b9805 2020-01-13 rsc //for(i = 0; i < len; ++i)
840 b1a086de 2020-01-13 rsc // gfx_keystroke(self.client, [_tmpText characterAtIndex:i]);
841 933b9805 2020-01-13 rsc [_tmpText deleteCharactersInRange:NSMakeRange(0, len)];
842 933b9805 2020-01-13 rsc _markedRange = NSMakeRange(NSNotFound, 0);
843 933b9805 2020-01-13 rsc _selectedRange = NSMakeRange(0, 0);
844 933b9805 2020-01-13 rsc }
845 41547af3 2020-01-13 rsc
846 41547af3 2020-01-13 rsc - (NSArray<NSAttributedStringKey>*)validAttributesForMarkedText {
847 933b9805 2020-01-13 rsc LOG(@"validAttributesForMarkedText");
848 933b9805 2020-01-13 rsc return @[];
849 933b9805 2020-01-13 rsc }
850 41547af3 2020-01-13 rsc
851 41547af3 2020-01-13 rsc - (NSAttributedString*)attributedSubstringForProposedRange:(NSRange)r
852 933b9805 2020-01-13 rsc actualRange:(NSRangePointer)actualRange
853 933b9805 2020-01-13 rsc {
854 933b9805 2020-01-13 rsc NSRange sr;
855 933b9805 2020-01-13 rsc NSAttributedString *s;
856 933b9805 2020-01-13 rsc
857 933b9805 2020-01-13 rsc LOG(@"attributedSubstringForProposedRange: (%ld, %ld) (%ld, %ld)",
858 933b9805 2020-01-13 rsc r.location, r.length, actualRange->location, actualRange->length);
859 933b9805 2020-01-13 rsc sr = NSMakeRange(0, [_tmpText length]);
860 933b9805 2020-01-13 rsc sr = NSIntersectionRange(sr, r);
861 933b9805 2020-01-13 rsc if(actualRange)
862 933b9805 2020-01-13 rsc *actualRange = sr;
863 933b9805 2020-01-13 rsc LOG(@"use range: %ld, %ld", sr.location, sr.length);
864 933b9805 2020-01-13 rsc s = nil;
865 933b9805 2020-01-13 rsc if(sr.length)
866 933b9805 2020-01-13 rsc s = [[NSAttributedString alloc]
867 933b9805 2020-01-13 rsc initWithString:[_tmpText substringWithRange:sr]];
868 933b9805 2020-01-13 rsc LOG(@" return %@", s);
869 933b9805 2020-01-13 rsc return s;
870 933b9805 2020-01-13 rsc }
871 41547af3 2020-01-13 rsc
872 41547af3 2020-01-13 rsc - (void)insertText:(id)s replacementRange:(NSRange)r {
873 933b9805 2020-01-13 rsc NSUInteger i;
874 933b9805 2020-01-13 rsc NSUInteger len;
875 933b9805 2020-01-13 rsc
876 933b9805 2020-01-13 rsc LOG(@"insertText: %@ replacementRange: %ld, %ld", s, r.location, r.length);
877 933b9805 2020-01-13 rsc
878 933b9805 2020-01-13 rsc [self clearInput];
879 933b9805 2020-01-13 rsc
880 933b9805 2020-01-13 rsc len = [s length];
881 933b9805 2020-01-13 rsc for(i = 0; i < len; ++i)
882 b1a086de 2020-01-13 rsc gfx_keystroke(self.client, [s characterAtIndex:i]);
883 933b9805 2020-01-13 rsc [_tmpText deleteCharactersInRange:NSMakeRange(0, _tmpText.length)];
884 933b9805 2020-01-13 rsc _markedRange = NSMakeRange(NSNotFound, 0);
885 933b9805 2020-01-13 rsc _selectedRange = NSMakeRange(0, 0);
886 933b9805 2020-01-13 rsc }
887 41547af3 2020-01-13 rsc
888 933b9805 2020-01-13 rsc - (NSUInteger)characterIndexForPoint:(NSPoint)point
889 933b9805 2020-01-13 rsc {
890 933b9805 2020-01-13 rsc LOG(@"characterIndexForPoint: %g, %g", point.x, point.y);
891 933b9805 2020-01-13 rsc return 0;
892 933b9805 2020-01-13 rsc }
893 41547af3 2020-01-13 rsc
894 41547af3 2020-01-13 rsc - (NSRect)firstRectForCharacterRange:(NSRange)r actualRange:(NSRangePointer)actualRange {
895 933b9805 2020-01-13 rsc LOG(@"firstRectForCharacterRange: (%ld, %ld) (%ld, %ld)",
896 933b9805 2020-01-13 rsc r.location, r.length, actualRange->location, actualRange->length);
897 933b9805 2020-01-13 rsc if(actualRange)
898 933b9805 2020-01-13 rsc *actualRange = r;
899 933b9805 2020-01-13 rsc return [[self window] convertRectToScreen:_lastInputRect];
900 933b9805 2020-01-13 rsc }
901 41547af3 2020-01-13 rsc
902 41547af3 2020-01-13 rsc - (void)doCommandBySelector:(SEL)s {
903 933b9805 2020-01-13 rsc NSEvent *e;
904 933b9805 2020-01-13 rsc NSEventModifierFlags m;
905 933b9805 2020-01-13 rsc uint c, k;
906 933b9805 2020-01-13 rsc
907 933b9805 2020-01-13 rsc LOG(@"doCommandBySelector (%@)", NSStringFromSelector(s));
908 933b9805 2020-01-13 rsc
909 933b9805 2020-01-13 rsc e = [NSApp currentEvent];
910 933b9805 2020-01-13 rsc c = [[e characters] characterAtIndex:0];
911 933b9805 2020-01-13 rsc k = keycvt(c);
912 933b9805 2020-01-13 rsc LOG(@"keyDown: character0: 0x%x -> 0x%x", c, k);
913 933b9805 2020-01-13 rsc m = [e modifierFlags];
914 933b9805 2020-01-13 rsc
915 933b9805 2020-01-13 rsc if(m & NSEventModifierFlagCommand){
916 933b9805 2020-01-13 rsc if((m & NSEventModifierFlagShift) && 'a' <= k && k <= 'z')
917 933b9805 2020-01-13 rsc k += 'A' - 'a';
918 933b9805 2020-01-13 rsc if(' '<=k && k<='~')
919 933b9805 2020-01-13 rsc k += Kcmd;
920 933b9805 2020-01-13 rsc }
921 933b9805 2020-01-13 rsc if(k>0)
922 b1a086de 2020-01-13 rsc gfx_keystroke(self.client, k);
923 933b9805 2020-01-13 rsc }
924 933b9805 2020-01-13 rsc
925 933b9805 2020-01-13 rsc // Helper for managing input rect approximately
926 41547af3 2020-01-13 rsc - (void)resetLastInputRect {
927 933b9805 2020-01-13 rsc LOG(@"resetLastInputRect");
928 933b9805 2020-01-13 rsc _lastInputRect.origin.x = 0.0;
929 933b9805 2020-01-13 rsc _lastInputRect.origin.y = 0.0;
930 933b9805 2020-01-13 rsc _lastInputRect.size.width = 0.0;
931 933b9805 2020-01-13 rsc _lastInputRect.size.height = 0.0;
932 933b9805 2020-01-13 rsc }
933 933b9805 2020-01-13 rsc
934 41547af3 2020-01-13 rsc - (void)enlargeLastInputRect:(NSRect)r {
935 933b9805 2020-01-13 rsc r.origin.y = [self bounds].size.height - r.origin.y - r.size.height;
936 933b9805 2020-01-13 rsc _lastInputRect = NSUnionRect(_lastInputRect, r);
937 933b9805 2020-01-13 rsc LOG(@"update last input rect (%g, %g, %g, %g)",
938 933b9805 2020-01-13 rsc _lastInputRect.origin.x, _lastInputRect.origin.y,
939 933b9805 2020-01-13 rsc _lastInputRect.size.width, _lastInputRect.size.height);
940 933b9805 2020-01-13 rsc }
941 933b9805 2020-01-13 rsc
942 41547af3 2020-01-13 rsc - (void)clearInput {
943 933b9805 2020-01-13 rsc if(_tmpText.length){
944 933b9805 2020-01-13 rsc uint i;
945 933b9805 2020-01-13 rsc int l;
946 933b9805 2020-01-13 rsc l = 1 + _tmpText.length - NSMaxRange(_selectedRange)
947 933b9805 2020-01-13 rsc + (_selectedRange.length > 0);
948 933b9805 2020-01-13 rsc LOG(@"move right %d", l);
949 933b9805 2020-01-13 rsc for(i = 0; i < l; ++i)
950 b1a086de 2020-01-13 rsc gfx_keystroke(self.client, Kright);
951 933b9805 2020-01-13 rsc l = _tmpText.length+2+2*(_selectedRange.length > 0);
952 933b9805 2020-01-13 rsc LOG(@"backspace %d", l);
953 933b9805 2020-01-13 rsc for(uint i = 0; i < l; ++i)
954 b1a086de 2020-01-13 rsc gfx_keystroke(self.client, Kbs);
955 933b9805 2020-01-13 rsc }
956 933b9805 2020-01-13 rsc }
957 b741db60 2020-01-14 rsc
958 b741db60 2020-01-14 rsc - (NSApplicationPresentationOptions)window:(id)arg
959 b741db60 2020-01-14 rsc willUseFullScreenPresentationOptions:(NSApplicationPresentationOptions)proposedOptions {
960 4c548931 2020-01-14 rsc // The default for full-screen is to auto-hide the dock and menu bar,
961 4c548931 2020-01-14 rsc // but the menu bar in particular comes back when the cursor is just
962 4c548931 2020-01-14 rsc // near the top of the screen, which makes acme's top tag line very difficult to use.
963 4c548931 2020-01-14 rsc // Disable the menu bar entirely.
964 4c548931 2020-01-14 rsc // In theory this code disables the dock entirely too, but if you drag the mouse
965 4c548931 2020-01-14 rsc // down far enough off the bottom of the screen the dock still unhides.
966 4c548931 2020-01-14 rsc // That's OK.
967 b741db60 2020-01-14 rsc NSApplicationPresentationOptions o;
968 b741db60 2020-01-14 rsc o = proposedOptions;
969 b741db60 2020-01-14 rsc o &= ~(NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar);
970 b741db60 2020-01-14 rsc o |= NSApplicationPresentationHideDock | NSApplicationPresentationHideMenuBar;
971 b741db60 2020-01-14 rsc return o;
972 b741db60 2020-01-14 rsc }
973 3d1382b9 2020-01-14 rsc
974 3d1382b9 2020-01-14 rsc - (void)windowWillEnterFullScreen:(NSNotification*)notification {
975 4c548931 2020-01-14 rsc // This is a heavier-weight way to make sure the menu bar and dock go away,
976 4c548931 2020-01-14 rsc // but this affects all screens even though the app is running on full screen
977 4c548931 2020-01-14 rsc // on only one screen, so it's not great. The behavior from the
978 4c548931 2020-01-14 rsc // willUseFullScreenPresentationOptions seems to be enough for now.
979 4c548931 2020-01-14 rsc /*
980 3d1382b9 2020-01-14 rsc [[NSApplication sharedApplication]
981 3d1382b9 2020-01-14 rsc setPresentationOptions:NSApplicationPresentationHideMenuBar | NSApplicationPresentationHideDock];
982 4c548931 2020-01-14 rsc */
983 3d1382b9 2020-01-14 rsc }
984 3d1382b9 2020-01-14 rsc
985 3d1382b9 2020-01-14 rsc - (void)windowDidExitFullScreen:(NSNotification*)notification {
986 4c548931 2020-01-14 rsc /*
987 3d1382b9 2020-01-14 rsc [[NSApplication sharedApplication]
988 3d1382b9 2020-01-14 rsc setPresentationOptions:NSApplicationPresentationDefault];
989 4c548931 2020-01-14 rsc */
990 3d1382b9 2020-01-14 rsc }
991 933b9805 2020-01-13 rsc @end
992 933b9805 2020-01-13 rsc
993 933b9805 2020-01-13 rsc static uint
994 933b9805 2020-01-13 rsc msec(void)
995 933b9805 2020-01-13 rsc {
996 933b9805 2020-01-13 rsc return nsec()/1000000;
997 933b9805 2020-01-13 rsc }
998 933b9805 2020-01-13 rsc
999 933b9805 2020-01-13 rsc static uint
1000 933b9805 2020-01-13 rsc keycvt(uint code)
1001 933b9805 2020-01-13 rsc {
1002 933b9805 2020-01-13 rsc switch(code){
1003 933b9805 2020-01-13 rsc case '\r': return '\n';
1004 933b9805 2020-01-13 rsc case 127: return '\b';
1005 933b9805 2020-01-13 rsc case NSUpArrowFunctionKey: return Kup;
1006 933b9805 2020-01-13 rsc case NSDownArrowFunctionKey: return Kdown;
1007 933b9805 2020-01-13 rsc case NSLeftArrowFunctionKey: return Kleft;
1008 933b9805 2020-01-13 rsc case NSRightArrowFunctionKey: return Kright;
1009 933b9805 2020-01-13 rsc case NSInsertFunctionKey: return Kins;
1010 933b9805 2020-01-13 rsc case NSDeleteFunctionKey: return Kdel;
1011 933b9805 2020-01-13 rsc case NSHomeFunctionKey: return Khome;
1012 933b9805 2020-01-13 rsc case NSEndFunctionKey: return Kend;
1013 933b9805 2020-01-13 rsc case NSPageUpFunctionKey: return Kpgup;
1014 933b9805 2020-01-13 rsc case NSPageDownFunctionKey: return Kpgdown;
1015 933b9805 2020-01-13 rsc case NSF1FunctionKey: return KF|1;
1016 933b9805 2020-01-13 rsc case NSF2FunctionKey: return KF|2;
1017 933b9805 2020-01-13 rsc case NSF3FunctionKey: return KF|3;
1018 933b9805 2020-01-13 rsc case NSF4FunctionKey: return KF|4;
1019 933b9805 2020-01-13 rsc case NSF5FunctionKey: return KF|5;
1020 933b9805 2020-01-13 rsc case NSF6FunctionKey: return KF|6;
1021 933b9805 2020-01-13 rsc case NSF7FunctionKey: return KF|7;
1022 933b9805 2020-01-13 rsc case NSF8FunctionKey: return KF|8;
1023 933b9805 2020-01-13 rsc case NSF9FunctionKey: return KF|9;
1024 933b9805 2020-01-13 rsc case NSF10FunctionKey: return KF|10;
1025 933b9805 2020-01-13 rsc case NSF11FunctionKey: return KF|11;
1026 933b9805 2020-01-13 rsc case NSF12FunctionKey: return KF|12;
1027 933b9805 2020-01-13 rsc case NSBeginFunctionKey:
1028 933b9805 2020-01-13 rsc case NSPrintScreenFunctionKey:
1029 933b9805 2020-01-13 rsc case NSScrollLockFunctionKey:
1030 933b9805 2020-01-13 rsc case NSF13FunctionKey:
1031 933b9805 2020-01-13 rsc case NSF14FunctionKey:
1032 933b9805 2020-01-13 rsc case NSF15FunctionKey:
1033 933b9805 2020-01-13 rsc case NSF16FunctionKey:
1034 933b9805 2020-01-13 rsc case NSF17FunctionKey:
1035 933b9805 2020-01-13 rsc case NSF18FunctionKey:
1036 933b9805 2020-01-13 rsc case NSF19FunctionKey:
1037 933b9805 2020-01-13 rsc case NSF20FunctionKey:
1038 933b9805 2020-01-13 rsc case NSF21FunctionKey:
1039 933b9805 2020-01-13 rsc case NSF22FunctionKey:
1040 933b9805 2020-01-13 rsc case NSF23FunctionKey:
1041 933b9805 2020-01-13 rsc case NSF24FunctionKey:
1042 933b9805 2020-01-13 rsc case NSF25FunctionKey:
1043 933b9805 2020-01-13 rsc case NSF26FunctionKey:
1044 933b9805 2020-01-13 rsc case NSF27FunctionKey:
1045 933b9805 2020-01-13 rsc case NSF28FunctionKey:
1046 933b9805 2020-01-13 rsc case NSF29FunctionKey:
1047 933b9805 2020-01-13 rsc case NSF30FunctionKey:
1048 933b9805 2020-01-13 rsc case NSF31FunctionKey:
1049 933b9805 2020-01-13 rsc case NSF32FunctionKey:
1050 933b9805 2020-01-13 rsc case NSF33FunctionKey:
1051 933b9805 2020-01-13 rsc case NSF34FunctionKey:
1052 933b9805 2020-01-13 rsc case NSF35FunctionKey:
1053 933b9805 2020-01-13 rsc case NSPauseFunctionKey:
1054 933b9805 2020-01-13 rsc case NSSysReqFunctionKey:
1055 933b9805 2020-01-13 rsc case NSBreakFunctionKey:
1056 933b9805 2020-01-13 rsc case NSResetFunctionKey:
1057 933b9805 2020-01-13 rsc case NSStopFunctionKey:
1058 933b9805 2020-01-13 rsc case NSMenuFunctionKey:
1059 933b9805 2020-01-13 rsc case NSUserFunctionKey:
1060 933b9805 2020-01-13 rsc case NSSystemFunctionKey:
1061 933b9805 2020-01-13 rsc case NSPrintFunctionKey:
1062 933b9805 2020-01-13 rsc case NSClearLineFunctionKey:
1063 933b9805 2020-01-13 rsc case NSClearDisplayFunctionKey:
1064 933b9805 2020-01-13 rsc case NSInsertLineFunctionKey:
1065 933b9805 2020-01-13 rsc case NSDeleteLineFunctionKey:
1066 933b9805 2020-01-13 rsc case NSInsertCharFunctionKey:
1067 933b9805 2020-01-13 rsc case NSDeleteCharFunctionKey:
1068 933b9805 2020-01-13 rsc case NSPrevFunctionKey:
1069 933b9805 2020-01-13 rsc case NSNextFunctionKey:
1070 933b9805 2020-01-13 rsc case NSSelectFunctionKey:
1071 933b9805 2020-01-13 rsc case NSExecuteFunctionKey:
1072 933b9805 2020-01-13 rsc case NSUndoFunctionKey:
1073 933b9805 2020-01-13 rsc case NSRedoFunctionKey:
1074 933b9805 2020-01-13 rsc case NSFindFunctionKey:
1075 933b9805 2020-01-13 rsc case NSHelpFunctionKey:
1076 933b9805 2020-01-13 rsc case NSModeSwitchFunctionKey: return 0;
1077 933b9805 2020-01-13 rsc default: return code;
1078 933b9805 2020-01-13 rsc }
1079 933b9805 2020-01-13 rsc }
1080 933b9805 2020-01-13 rsc
1081 41547af3 2020-01-13 rsc // rpc_getsnarf reads the current pasteboard as a plain text string.
1082 41547af3 2020-01-13 rsc // Called from an RPC thread with no client lock held.
1083 933b9805 2020-01-13 rsc char*
1084 b1a086de 2020-01-13 rsc rpc_getsnarf(void)
1085 933b9805 2020-01-13 rsc {
1086 41547af3 2020-01-13 rsc char __block *ret;
1087 50923426 2020-01-13 rsc
1088 41547af3 2020-01-13 rsc ret = nil;
1089 41547af3 2020-01-13 rsc dispatch_sync(dispatch_get_main_queue(), ^(void) {
1090 41547af3 2020-01-13 rsc @autoreleasepool {
1091 41547af3 2020-01-13 rsc NSPasteboard *pb = [NSPasteboard generalPasteboard];
1092 41547af3 2020-01-13 rsc NSString *s = [pb stringForType:NSPasteboardTypeString];
1093 41547af3 2020-01-13 rsc if(s)
1094 41547af3 2020-01-13 rsc ret = strdup((char*)[s UTF8String]);
1095 41547af3 2020-01-13 rsc }
1096 41547af3 2020-01-13 rsc });
1097 41547af3 2020-01-13 rsc return ret;
1098 933b9805 2020-01-13 rsc }
1099 933b9805 2020-01-13 rsc
1100 41547af3 2020-01-13 rsc // rpc_putsnarf writes the given text to the pasteboard.
1101 41547af3 2020-01-13 rsc // Called from an RPC thread with no client lock held.
1102 933b9805 2020-01-13 rsc void
1103 b1a086de 2020-01-13 rsc rpc_putsnarf(char *s)
1104 933b9805 2020-01-13 rsc {
1105 41547af3 2020-01-13 rsc if(s == nil || strlen(s) >= SnarfSize)
1106 933b9805 2020-01-13 rsc return;
1107 933b9805 2020-01-13 rsc
1108 41547af3 2020-01-13 rsc dispatch_sync(dispatch_get_main_queue(), ^(void) {
1109 41547af3 2020-01-13 rsc @autoreleasepool{
1110 41547af3 2020-01-13 rsc NSArray *t = [NSArray arrayWithObject:NSPasteboardTypeString];
1111 41547af3 2020-01-13 rsc NSPasteboard *pb = [NSPasteboard generalPasteboard];
1112 41547af3 2020-01-13 rsc NSString *str = [[NSString alloc] initWithUTF8String:s];
1113 41547af3 2020-01-13 rsc [pb declareTypes:t owner:nil];
1114 41547af3 2020-01-13 rsc [pb setString:str forType:NSPasteboardTypeString];
1115 41547af3 2020-01-13 rsc }
1116 41547af3 2020-01-13 rsc });
1117 50923426 2020-01-13 rsc }
1118 50923426 2020-01-13 rsc
1119 50923426 2020-01-13 rsc // rpc_bouncemouse is for sending a mouse event
1120 50923426 2020-01-13 rsc // back to the X11 window manager rio(1).
1121 50923426 2020-01-13 rsc // Does not apply here.
1122 94d381ec 2020-05-18 rsc static void
1123 50923426 2020-01-13 rsc rpc_bouncemouse(Client *c, Mouse m)
1124 50923426 2020-01-13 rsc {
1125 933b9805 2020-01-13 rsc }
1126 933b9805 2020-01-13 rsc
1127 50923426 2020-01-13 rsc // We don't use the graphics thread state during memimagedraw,
1128 50923426 2020-01-13 rsc // so rpc_gfxdrawlock and rpc_gfxdrawunlock are no-ops.
1129 50923426 2020-01-13 rsc void
1130 50923426 2020-01-13 rsc rpc_gfxdrawlock(void)
1131 50923426 2020-01-13 rsc {
1132 50923426 2020-01-13 rsc }
1133 50923426 2020-01-13 rsc
1134 50923426 2020-01-13 rsc void
1135 50923426 2020-01-13 rsc rpc_gfxdrawunlock(void)
1136 50923426 2020-01-13 rsc {
1137 50923426 2020-01-13 rsc }
1138 50923426 2020-01-13 rsc
1139 933b9805 2020-01-13 rsc static void
1140 933b9805 2020-01-13 rsc setprocname(const char *s)
1141 933b9805 2020-01-13 rsc {
1142 933b9805 2020-01-13 rsc CFStringRef process_name;
1143 933b9805 2020-01-13 rsc
1144 933b9805 2020-01-13 rsc process_name = CFStringCreateWithBytes(nil, (uchar*)s, strlen(s), kCFStringEncodingUTF8, false);
1145 933b9805 2020-01-13 rsc
1146 933b9805 2020-01-13 rsc // Adapted from Chrome's mac_util.mm.
1147 933b9805 2020-01-13 rsc // http://src.chromium.org/viewvc/chrome/trunk/src/base/mac/mac_util.mm
1148 933b9805 2020-01-13 rsc //
1149 933b9805 2020-01-13 rsc // Copyright (c) 2012 The Chromium Authors. All rights reserved.
1150 933b9805 2020-01-13 rsc //
1151 933b9805 2020-01-13 rsc // Redistribution and use in source and binary forms, with or without
1152 933b9805 2020-01-13 rsc // modification, are permitted provided that the following conditions are
1153 933b9805 2020-01-13 rsc // met:
1154 933b9805 2020-01-13 rsc //
1155 933b9805 2020-01-13 rsc // * Redistributions of source code must retain the above copyright
1156 933b9805 2020-01-13 rsc // notice, this list of conditions and the following disclaimer.
1157 933b9805 2020-01-13 rsc // * Redistributions in binary form must reproduce the above
1158 933b9805 2020-01-13 rsc // copyright notice, this list of conditions and the following disclaimer
1159 933b9805 2020-01-13 rsc // in the documentation and/or other materials provided with the
1160 933b9805 2020-01-13 rsc // distribution.
1161 933b9805 2020-01-13 rsc // * Neither the name of Google Inc. nor the names of its
1162 933b9805 2020-01-13 rsc // contributors may be used to endorse or promote products derived from
1163 933b9805 2020-01-13 rsc // this software without specific prior written permission.
1164 933b9805 2020-01-13 rsc //
1165 933b9805 2020-01-13 rsc // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1166 933b9805 2020-01-13 rsc // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1167 933b9805 2020-01-13 rsc // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1168 933b9805 2020-01-13 rsc // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1169 933b9805 2020-01-13 rsc // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1170 933b9805 2020-01-13 rsc // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
1171 933b9805 2020-01-13 rsc // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1172 933b9805 2020-01-13 rsc // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1173 933b9805 2020-01-13 rsc // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1174 933b9805 2020-01-13 rsc // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1175 933b9805 2020-01-13 rsc // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1176 933b9805 2020-01-13 rsc // Warning: here be dragons! This is SPI reverse-engineered from WebKit's
1177 933b9805 2020-01-13 rsc // plugin host, and could break at any time (although realistically it's only
1178 933b9805 2020-01-13 rsc // likely to break in a new major release).
1179 933b9805 2020-01-13 rsc // When 10.7 is available, check that this still works, and update this
1180 933b9805 2020-01-13 rsc // comment for 10.8.
1181 933b9805 2020-01-13 rsc
1182 933b9805 2020-01-13 rsc // Private CFType used in these LaunchServices calls.
1183 933b9805 2020-01-13 rsc typedef CFTypeRef PrivateLSASN;
1184 933b9805 2020-01-13 rsc typedef PrivateLSASN (*LSGetCurrentApplicationASNType)();
1185 933b9805 2020-01-13 rsc typedef OSStatus (*LSSetApplicationInformationItemType)(int, PrivateLSASN,
1186 933b9805 2020-01-13 rsc CFStringRef,
1187 933b9805 2020-01-13 rsc CFStringRef,
1188 933b9805 2020-01-13 rsc CFDictionaryRef*);
1189 933b9805 2020-01-13 rsc
1190 933b9805 2020-01-13 rsc static LSGetCurrentApplicationASNType ls_get_current_application_asn_func =
1191 933b9805 2020-01-13 rsc NULL;
1192 933b9805 2020-01-13 rsc static LSSetApplicationInformationItemType
1193 933b9805 2020-01-13 rsc ls_set_application_information_item_func = NULL;
1194 933b9805 2020-01-13 rsc static CFStringRef ls_display_name_key = NULL;
1195 933b9805 2020-01-13 rsc
1196 933b9805 2020-01-13 rsc static bool did_symbol_lookup = false;
1197 933b9805 2020-01-13 rsc if (!did_symbol_lookup) {
1198 933b9805 2020-01-13 rsc did_symbol_lookup = true;
1199 933b9805 2020-01-13 rsc CFBundleRef launch_services_bundle =
1200 933b9805 2020-01-13 rsc CFBundleGetBundleWithIdentifier(CFSTR("com.apple.LaunchServices"));
1201 933b9805 2020-01-13 rsc if (!launch_services_bundle) {
1202 933b9805 2020-01-13 rsc fprint(2, "Failed to look up LaunchServices bundle\n");
1203 933b9805 2020-01-13 rsc return;
1204 933b9805 2020-01-13 rsc }
1205 933b9805 2020-01-13 rsc
1206 933b9805 2020-01-13 rsc ls_get_current_application_asn_func =
1207 933b9805 2020-01-13 rsc (LSGetCurrentApplicationASNType)(
1208 933b9805 2020-01-13 rsc CFBundleGetFunctionPointerForName(
1209 933b9805 2020-01-13 rsc launch_services_bundle, CFSTR("_LSGetCurrentApplicationASN")));
1210 933b9805 2020-01-13 rsc if (!ls_get_current_application_asn_func)
1211 933b9805 2020-01-13 rsc fprint(2, "Could not find _LSGetCurrentApplicationASN\n");
1212 933b9805 2020-01-13 rsc
1213 933b9805 2020-01-13 rsc ls_set_application_information_item_func =
1214 933b9805 2020-01-13 rsc (LSSetApplicationInformationItemType)(
1215 933b9805 2020-01-13 rsc CFBundleGetFunctionPointerForName(
1216 933b9805 2020-01-13 rsc launch_services_bundle,
1217 933b9805 2020-01-13 rsc CFSTR("_LSSetApplicationInformationItem")));
1218 933b9805 2020-01-13 rsc if (!ls_set_application_information_item_func)
1219 933b9805 2020-01-13 rsc fprint(2, "Could not find _LSSetApplicationInformationItem\n");
1220 933b9805 2020-01-13 rsc
1221 933b9805 2020-01-13 rsc CFStringRef* key_pointer = (CFStringRef*)(
1222 933b9805 2020-01-13 rsc CFBundleGetDataPointerForName(launch_services_bundle,
1223 933b9805 2020-01-13 rsc CFSTR("_kLSDisplayNameKey")));
1224 933b9805 2020-01-13 rsc ls_display_name_key = key_pointer ? *key_pointer : NULL;
1225 933b9805 2020-01-13 rsc if (!ls_display_name_key)
1226 933b9805 2020-01-13 rsc fprint(2, "Could not find _kLSDisplayNameKey\n");
1227 933b9805 2020-01-13 rsc
1228 933b9805 2020-01-13 rsc // Internally, this call relies on the Mach ports that are started up by the
1229 933b9805 2020-01-13 rsc // Carbon Process Manager. In debug builds this usually happens due to how
1230 933b9805 2020-01-13 rsc // the logging layers are started up; but in release, it isn't started in as
1231 933b9805 2020-01-13 rsc // much of a defined order. So if the symbols had to be loaded, go ahead
1232 933b9805 2020-01-13 rsc // and force a call to make sure the manager has been initialized and hence
1233 933b9805 2020-01-13 rsc // the ports are opened.
1234 933b9805 2020-01-13 rsc ProcessSerialNumber psn;
1235 933b9805 2020-01-13 rsc GetCurrentProcess(&psn);
1236 933b9805 2020-01-13 rsc }
1237 933b9805 2020-01-13 rsc if (!ls_get_current_application_asn_func ||
1238 933b9805 2020-01-13 rsc !ls_set_application_information_item_func ||
1239 933b9805 2020-01-13 rsc !ls_display_name_key) {
1240 933b9805 2020-01-13 rsc return;
1241 933b9805 2020-01-13 rsc }
1242 933b9805 2020-01-13 rsc
1243 933b9805 2020-01-13 rsc PrivateLSASN asn = ls_get_current_application_asn_func();
1244 933b9805 2020-01-13 rsc // Constant used by WebKit; what exactly it means is unknown.
1245 933b9805 2020-01-13 rsc const int magic_session_constant = -2;
1246 933b9805 2020-01-13 rsc OSErr err =
1247 933b9805 2020-01-13 rsc ls_set_application_information_item_func(magic_session_constant, asn,
1248 933b9805 2020-01-13 rsc ls_display_name_key,
1249 933b9805 2020-01-13 rsc process_name,
1250 933b9805 2020-01-13 rsc NULL /* optional out param */);
1251 933b9805 2020-01-13 rsc if(err != noErr)
1252 933b9805 2020-01-13 rsc fprint(2, "Call to set process name failed\n");
1253 933b9805 2020-01-13 rsc }