1 /*
2 * Copyright (c) 2004-2015 Derelict Developers
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 *   notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 *   notice, this list of conditions and the following disclaimer in the
14 *   documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the names 'Derelict', 'DerelictSDL', nor the names of its contributors
17 *   may be used to endorse or promote products derived from this software
18 *   without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 module derelict.cocoa.appkit;
33 
34 import std.string;
35 
36 import derelict.cocoa.runtime;
37 import derelict.cocoa.foundation;
38 import derelict.cocoa.coreimage;
39 import derelict.cocoa.coregraphics;
40 
41 
42 // free functions
43 extern (C) nothrow @nogc
44 {
45     alias bool function() pfNSApplicationLoad;
46 }
47 
48 __gshared
49 {
50     pfNSApplicationLoad NSApplicationLoad;
51 }
52 
53 alias NSApplicationActivationPolicy = NSInteger;
54 enum : NSApplicationActivationPolicy
55 {
56    NSApplicationActivationPolicyRegular = 0,
57    NSApplicationActivationPolicyAccessory = 1,
58    NSApplicationActivationPolicyProhibited = 2
59 }
60 
61 struct NSApplication
62 {
63 nothrow @nogc:
64 
65     NSObject parent;
66     alias parent this;
67 
68     mixin NSObjectTemplate!(NSApplication, "NSApplication");
69 
70     public static NSApplication sharedApplication ()
71     {
72         alias fun_t = extern(C) id function (id, SEL) nothrow @nogc;
73         id result = (cast(fun_t)objc_msgSend)(lazyClass!"NSApplication", sel!"sharedApplication");
74         return NSApplication(result);
75     }
76 
77     void setDelegate (id object)
78     {
79         alias fun_t = extern(C) void function (id, SEL, id) nothrow @nogc;
80         (cast(fun_t)objc_msgSend)(_id, sel!"setDelegate:", object.id);
81     }
82 
83     void setActivationPolicy(NSApplicationActivationPolicy policy)
84     {
85         alias fun_t = extern(C) void function (id, SEL, NSApplicationActivationPolicy) nothrow @nogc;
86         (cast(fun_t)objc_msgSend)(_id, sel!"setActivationPolicy:", policy);
87     }
88 
89     void activateIgnoringOtherApps(BOOL b)
90     {
91         alias fun_t = extern(C) void function (id, SEL, BOOL) nothrow @nogc;
92         (cast(fun_t)objc_msgSend)(_id, sel!"activateIgnoringOtherApps:", b);
93     }
94 
95     void run ()
96     {
97         alias fun_t = extern(C) void function (id, SEL) nothrow @nogc;
98         (cast(fun_t)objc_msgSend)(_id, sel!"run");
99     }
100 
101     void stop (id sender)
102     {
103         alias fun_t = extern(C) void function (id, SEL, id) nothrow @nogc;
104         (cast(fun_t)objc_msgSend)(_id, sel!"stop:", sender);
105     }
106 
107     void sendEvent(NSEvent event)
108     {
109         alias fun_t = extern(C) void function (id, SEL, id) nothrow @nogc;
110         (cast(fun_t)objc_msgSend)(_id, sel!"sendEvent:", event._id);
111     }
112 }
113 
114 
115 // NSResponder
116 
117 struct NSResponder
118 {
119 nothrow @nogc:
120     NSObject parent;
121     alias parent this;
122 
123     mixin NSObjectTemplate!(NSResponder, "NSResponder");
124 }
125 
126 
127 // NSView
128 
129 alias NSBorderType = NSUInteger;
130 enum : NSBorderType
131 {
132     NSNoBorder     = 0,
133     NSLineBorder   = 1,
134     NSBezelBorder  = 2,
135     NSGrooveBorder = 3
136 }
137 
138 alias NSAutoresizingMaskOptions = NSUInteger;
139 enum : NSAutoresizingMaskOptions
140 {
141     NSViewNotSizable     = 0,
142     NSViewMinXMargin     = 1,
143     NSViewWidthSizable   = 2,
144     NSViewMaxXMargin     = 4,
145     NSViewMinYMargin     = 8,
146     NSViewHeightSizable  = 16,
147     NSViewMaxYMargin     = 32
148 }
149 
150 
151 struct NSView
152 {
153 nothrow @nogc:
154 
155     NSResponder parent;
156     alias parent this;
157 
158     mixin NSObjectTemplate!(NSView, "NSView");
159 
160     void initWithFrame(NSRect rect)
161     {
162         alias fun_t = extern(C) void function (id, SEL, NSRect) nothrow @nogc;
163         (cast(fun_t)objc_msgSend)(_id, sel!"initWithFrame:", rect);
164     }
165 
166     void addSubview(NSView subView)
167     {
168         alias fun_t = extern(C) void function (id, SEL, id) nothrow @nogc;
169         (cast(fun_t)objc_msgSend)(_id, sel!"addSubview:", subView._id);
170     }
171 
172     void removeFromSuperview()
173     {
174         alias fun_t = extern(C) void function (id, SEL) nothrow @nogc;
175         (cast(fun_t)objc_msgSend)(_id, sel!"removeFromSuperview");
176     }
177 
178     NSWindow window()
179     {
180         alias fun_t = extern(C) id function (id, SEL) nothrow @nogc;
181         id result = (cast(fun_t)objc_msgSend)(_id, sel!"window");
182         return NSWindow(result);
183     }
184 
185     void setNeedsDisplayInRect(NSRect rect)
186     {
187         alias fun_t = extern(C) void function (id, SEL, NSRect) nothrow @nogc;
188         (cast(fun_t)objc_msgSend)(_id, sel!"setNeedsDisplayInRect:", rect);
189     }
190 
191     NSPoint convertPoint(NSPoint point, NSView view)
192     {
193         alias fun_t = extern(C) NSPoint function (id, const(SEL), NSPoint, id) nothrow @nogc;
194         return (cast(fun_t)objc_msgSend)(_id, sel!"convertPoint:fromView:", point, view._id);
195     }
196 
197     NSRect convertRect(NSRect rect, NSView view)
198     {
199         alias fun_t = extern(C) NSRect function (id, const(SEL), NSRect, id) nothrow @nogc;
200         return (cast(fun_t)objc_msgSend_stret)(_id, sel!"convertRect:fromView:", rect, view._id);
201     }
202 
203     NSRect frame()
204     {
205         alias fun_t = extern(C) NSRect function (id, const(SEL)) nothrow @nogc;
206         return (cast(fun_t)objc_msgSend_stret)(_id, sel!"frame");
207     }
208 
209     NSRect bounds()
210     {
211         alias fun_t = extern(C) NSRect function (id, const(SEL)) nothrow @nogc;
212         return (cast(fun_t)objc_msgSend_stret)(_id, sel!"bounds");
213     }
214 }
215 
216 
217 // NSWindow
218 
219 alias NSBackingStoreType = NSUInteger;
220 enum : NSBackingStoreType
221 {
222     NSBackingStoreRetained     = 0,
223     NSBackingStoreNonretained  = 1,
224     NSBackingStoreBuffered     = 2
225 }
226 
227 enum : NSUInteger
228 {
229    NSBorderlessWindowMask = 0,
230    NSTitledWindowMask = 1 << 0,
231    NSClosableWindowMask = 1 << 1,
232    NSMiniaturizableWindowMask = 1 << 2,
233    NSResizableWindowMask = 1 << 3,
234    NSTexturedBackgroundWindowMask = 1 << 8
235 }
236 
237 struct NSWindow
238 {
239 nothrow @nogc:
240 
241     NSResponder parent;
242     alias parent this;
243 
244     mixin NSObjectTemplate!(NSWindow, "NSWindow");
245 
246     void initWithContentRect(NSRect contentRect)
247     {
248         alias fun_t = extern(C) void function (id, SEL, NSRect) nothrow @nogc;
249         (cast(fun_t)objc_msgSend)(_id, sel!"initWithContentRect:", contentRect);
250     }
251 
252     void initWithContentRect(NSRect contentRect, NSUInteger windowStyle, NSBackingStoreType bufferingType, BOOL deferCreation)
253     {
254         alias fun_t = extern(C) void function (id, SEL, NSRect, NSUInteger, NSBackingStoreType, BOOL) nothrow @nogc;
255         (cast(fun_t)objc_msgSend)(_id, sel!"initWithContentRect:styleMask:backing:defer:", contentRect, windowStyle, bufferingType, deferCreation);
256     }
257 
258     NSView contentView()
259     {
260         alias fun_t = extern(C) id function (id, SEL) nothrow @nogc;
261         id result = (cast(fun_t)objc_msgSend)(_id, sel!"contentView");
262         return NSView(result);
263     }
264 
265     void makeKeyAndOrderFront()
266     {
267         alias fun_t = extern(C) void function (id, SEL) nothrow @nogc;
268         (cast(fun_t)objc_msgSend)(_id, sel!"makeKeyAndOrderFront:");
269     }
270 
271     bool makeFirstResponder(NSResponder responder)
272     {
273         alias fun_t = extern(C) BOOL function (id, SEL, id) nothrow @nogc;
274         BOOL result = (cast(fun_t)objc_msgSend)(_id, sel!"makeFirstResponder:", responder._id);
275         return result != NO;
276     }
277 
278     NSEvent nextEventMatchingMask(NSUInteger eventMask)
279     {
280         alias fun_t = extern(C) id function (id, SEL, NSUInteger) nothrow @nogc;
281         id result = (cast(fun_t)objc_msgSend)(_id, sel!"nextEventMatchingMask:", eventMask);
282         return NSEvent(result);
283     }
284 
285     NSPoint mouseLocationOutsideOfEventStream()
286     {
287         alias fun_t = extern(C) NSPoint function (id, SEL) nothrow @nogc;
288         return (cast(fun_t)objc_msgSend)(_id, sel!"mouseLocationOutsideOfEventStream");
289     }
290 
291     void setAcceptsMouseMovedEvents(bool b)
292     {
293         alias fun_t = extern(C) void function (id, SEL, BOOL) nothrow @nogc;
294         (cast(fun_t)objc_msgSend)(_id, sel!"setAcceptsMouseMovedEvents:", b ? YES : NO);
295     }
296 }
297 
298 
299 alias NSEventType = int;
300 enum : NSEventType
301 {
302     NSLeftMouseDown       = 1,
303     NSLeftMouseUp         = 2,
304     NSRightMouseDown      = 3,
305     NSRightMouseUp        = 4,
306     NSMouseMoved          = 5,
307     NSLeftMouseDragged    = 6,
308     NSRightMouseDragged   = 7,
309     NSMouseEntered        = 8,
310     NSMouseExited         = 9,
311     NSKeyDown             = 10,
312     NSKeyUp               = 11,
313     NSFlagsChanged        = 12,
314     NSAppKitDefined       = 13,
315     NSSystemDefined       = 14,
316     NSApplicationDefined  = 15,
317     NSPeriodic            = 16,
318     NSCursorUpdate        = 17,
319     NSScrollWheel         = 22,
320     NSTabletPoint         = 23,
321     NSTabletProximity     = 24,
322     NSOtherMouseDown      = 25,
323     NSOtherMouseUp        = 26,
324     NSOtherMouseDragged   = 27,
325     NSRotate              = 18,
326     NSBeginGesture        = 19,
327     NSEndGesture          = 20,
328     NSMagnify             = 30,
329     NSSwipe               = 31
330 }
331 
332 enum : NSUInteger
333 {
334     NSLeftMouseDownMask      = 1 << NSLeftMouseDown,
335     NSLeftMouseUpMask        = 1 << NSLeftMouseUp,
336     NSRightMouseDownMask     = 1 << NSRightMouseDown,
337     NSRightMouseUpMask       = 1 << NSRightMouseUp,
338     NSMouseMovedMask         = 1 << NSMouseMoved,
339     NSLeftMouseDraggedMask   = 1 << NSLeftMouseDragged,
340     NSRightMouseDraggedMask  = 1 << NSRightMouseDragged,
341     NSMouseEnteredMask       = 1 << NSMouseEntered,
342     NSMouseExitedMask        = 1 << NSMouseExited,
343     NSKeyDownMask            = 1 << NSKeyDown,
344     NSKeyUpMask              = 1 << NSKeyUp,
345     NSFlagsChangedMask       = 1 << NSFlagsChanged,
346     NSAppKitDefinedMask      = 1 << NSAppKitDefined,
347     NSSystemDefinedMask      = 1 << NSSystemDefined,
348     NSApplicationDefinedMask = 1 << NSApplicationDefined,
349     NSPeriodicMask           = 1 << NSPeriodic,
350     NSCursorUpdateMask       = 1 << NSCursorUpdate,
351     NSScrollWheelMask        = 1 << NSScrollWheel,
352     NSTabletPointMask        = 1 << NSTabletPoint,
353     NSTabletProximityMask    = 1 << NSTabletProximity,
354     NSOtherMouseDownMask     = 1 << NSOtherMouseDown,
355     NSOtherMouseUpMask       = 1 << NSOtherMouseUp,
356     NSOtherMouseDraggedMask  = 1 << NSOtherMouseDragged,
357     NSRotateMask             = 1 << NSRotate,
358     NSBeginGestureMask       = 1 << NSBeginGesture,
359     NSEndGestureMask         = 1 << NSEndGesture,
360     NSMagnifyMask            = 1 << NSMagnify,
361     NSSwipeMask              = 1 << NSSwipe,
362     NSAnyEventMask           = 0xffffffffU,
363 }
364 
365 /// Keycodes
366 enum : ushort
367 {
368     kVK_ANSI_A                    = 0x00,
369     kVK_ANSI_S                    = 0x01,
370     kVK_ANSI_D                    = 0x02,
371     kVK_ANSI_F                    = 0x03,
372     kVK_ANSI_H                    = 0x04,
373     kVK_ANSI_G                    = 0x05,
374     kVK_ANSI_Z                    = 0x06,
375     kVK_ANSI_X                    = 0x07,
376     kVK_ANSI_C                    = 0x08,
377     kVK_ANSI_V                    = 0x09,
378     kVK_ANSI_B                    = 0x0B,
379     kVK_ANSI_Q                    = 0x0C,
380     kVK_ANSI_W                    = 0x0D,
381     kVK_ANSI_E                    = 0x0E,
382     kVK_ANSI_R                    = 0x0F,
383     kVK_ANSI_Y                    = 0x10,
384     kVK_ANSI_T                    = 0x11,
385     kVK_ANSI_1                    = 0x12,
386     kVK_ANSI_2                    = 0x13,
387     kVK_ANSI_3                    = 0x14,
388     kVK_ANSI_4                    = 0x15,
389     kVK_ANSI_6                    = 0x16,
390     kVK_ANSI_5                    = 0x17,
391     kVK_ANSI_Equal                = 0x18,
392     kVK_ANSI_9                    = 0x19,
393     kVK_ANSI_7                    = 0x1A,
394     kVK_ANSI_Minus                = 0x1B,
395     kVK_ANSI_8                    = 0x1C,
396     kVK_ANSI_0                    = 0x1D,
397     kVK_ANSI_RightBracket         = 0x1E,
398     kVK_ANSI_O                    = 0x1F,
399     kVK_ANSI_U                    = 0x20,
400     kVK_ANSI_LeftBracket          = 0x21,
401     kVK_ANSI_I                    = 0x22,
402     kVK_ANSI_P                    = 0x23,
403     kVK_ANSI_L                    = 0x25,
404     kVK_ANSI_J                    = 0x26,
405     kVK_ANSI_Quote                = 0x27,
406     kVK_ANSI_K                    = 0x28,
407     kVK_ANSI_Semicolon            = 0x29,
408     kVK_ANSI_Backslash            = 0x2A,
409     kVK_ANSI_Comma                = 0x2B,
410     kVK_ANSI_Slash                = 0x2C,
411     kVK_ANSI_N                    = 0x2D,
412     kVK_ANSI_M                    = 0x2E,
413     kVK_ANSI_Period               = 0x2F,
414     kVK_ANSI_Grave                = 0x32,
415     kVK_ANSI_KeypadDecimal        = 0x41,
416     kVK_ANSI_KeypadMultiply       = 0x43,
417     kVK_ANSI_KeypadPlus           = 0x45,
418     kVK_ANSI_KeypadClear          = 0x47,
419     kVK_ANSI_KeypadDivide         = 0x4B,
420     kVK_ANSI_KeypadEnter          = 0x4C,
421     kVK_ANSI_KeypadMinus          = 0x4E,
422     kVK_ANSI_KeypadEquals         = 0x51,
423     kVK_ANSI_Keypad0              = 0x52,
424     kVK_ANSI_Keypad1              = 0x53,
425     kVK_ANSI_Keypad2              = 0x54,
426     kVK_ANSI_Keypad3              = 0x55,
427     kVK_ANSI_Keypad4              = 0x56,
428     kVK_ANSI_Keypad5              = 0x57,
429     kVK_ANSI_Keypad6              = 0x58,
430     kVK_ANSI_Keypad7              = 0x59,
431     kVK_ANSI_Keypad8              = 0x5B,
432     kVK_ANSI_Keypad9              = 0x5C
433 }
434 
435 /// Keycodes for keys that are independent of keyboard layout.
436 enum : ushort
437 {
438     kVK_Return                    = 0x24,
439     kVK_Tab                       = 0x30,
440     kVK_Space                     = 0x31,
441     kVK_Delete                    = 0x33,
442     kVK_Escape                    = 0x35,
443     kVK_Command                   = 0x37,
444     kVK_Shift                     = 0x38,
445     kVK_CapsLock                  = 0x39,
446     kVK_Option                    = 0x3A,
447     kVK_Control                   = 0x3B,
448     kVK_RightShift                = 0x3C,
449     kVK_RightOption               = 0x3D,
450     kVK_RightControl              = 0x3E,
451     kVK_Function                  = 0x3F,
452     kVK_F17                       = 0x40,
453     kVK_VolumeUp                  = 0x48,
454     kVK_VolumeDown                = 0x49,
455     kVK_Mute                      = 0x4A,
456     kVK_F18                       = 0x4F,
457     kVK_F19                       = 0x50,
458     kVK_F20                       = 0x5A,
459     kVK_F5                        = 0x60,
460     kVK_F6                        = 0x61,
461     kVK_F7                        = 0x62,
462     kVK_F3                        = 0x63,
463     kVK_F8                        = 0x64,
464     kVK_F9                        = 0x65,
465     kVK_F11                       = 0x67,
466     kVK_F13                       = 0x69,
467     kVK_F16                       = 0x6A,
468     kVK_F14                       = 0x6B,
469     kVK_F10                       = 0x6D,
470     kVK_F12                       = 0x6F,
471     kVK_F15                       = 0x71,
472     kVK_Help                      = 0x72,
473     kVK_Home                      = 0x73,
474     kVK_PageUp                    = 0x74,
475     kVK_ForwardDelete             = 0x75,
476     kVK_F4                        = 0x76,
477     kVK_End                       = 0x77,
478     kVK_F2                        = 0x78,
479     kVK_PageDown                  = 0x79,
480     kVK_F1                        = 0x7A,
481     kVK_LeftArrow                 = 0x7B,
482     kVK_RightArrow                = 0x7C,
483     kVK_DownArrow                 = 0x7D,
484     kVK_UpArrow                   = 0x7E
485 }
486 
487 /// ISO keyboards only.
488 enum : ushort
489 {
490   kVK_ISO_Section               = 0x0A
491 }
492 
493 ///JIS keyboards only.
494 enum : ushort
495 {
496   kVK_JIS_Yen                   = 0x5D,
497   kVK_JIS_Underscore            = 0x5E,
498   kVK_JIS_KeypadComma           = 0x5F,
499   kVK_JIS_Eisu                  = 0x66,
500   kVK_JIS_Kana                  = 0x68
501 }
502 
503 alias NSEventModifierFlags = int;
504 enum : NSEventModifierFlags
505 {
506    NSAlphaShiftKeyMask = 1 << 16,
507    NSShiftKeyMask      = 1 << 17,
508    NSControlKeyMask    = 1 << 18,
509    NSAlternateKeyMask  = 1 << 19,
510    NSCommandKeyMask    = 1 << 20,
511    NSNumericPadKeyMask = 1 << 21,
512    NSHelpKeyMask       = 1 << 22,
513    NSFunctionKeyMask   = 1 << 23,
514    NSDeviceIndependentModifierFlagsMask = 0xffff0000U
515 }
516 
517 struct NSEvent
518 {
519 nothrow @nogc:
520 
521     NSObject parent;
522     alias parent this;
523 
524     mixin NSObjectTemplate!(NSEvent, "NSEvent");
525 
526     NSWindow window()
527     {
528         alias fun_t = extern(C) id function (id, SEL) nothrow @nogc;
529         id result = (cast(fun_t)objc_msgSend)(_id, sel!"window");
530         return NSWindow(result);
531     }
532 
533     NSEventType type()
534     {
535         alias fun_t = extern(C) id function (id, SEL) nothrow @nogc;
536         id result = (cast(fun_t)objc_msgSend)(_id, sel!"type");
537         return cast(NSEventType)result;
538     }
539 
540     int clickCount()
541     {
542         alias fun_t = extern(C) NSInteger function (id, SEL) nothrow @nogc;
543         return cast(int)( (cast(fun_t)objc_msgSend)(_id, sel!"clickCount") );
544     }
545 
546     int buttonNumber()
547     {
548         alias fun_t = extern(C) NSInteger function (id, SEL) nothrow @nogc;
549         return cast(int)( (cast(fun_t)objc_msgSend)(_id, sel!"buttonNumber") );
550     }
551 
552     uint pressedMouseButtons()
553     {
554         alias fun_t = extern(C) NSUInteger function (id, SEL) nothrow @nogc;
555         return cast(uint)( (cast(fun_t)objc_msgSend)(getClassID(), sel!"pressedMouseButtons") );
556     }
557 
558     NSEventModifierFlags modifierFlags()
559     {
560         alias fun_t = extern(C) NSEventModifierFlags function (id, SEL) nothrow @nogc;
561         return cast(uint)( (cast(fun_t)objc_msgSend)(_id, sel!"modifierFlags") );
562     }
563 
564     NSPoint mouseLocation()
565     {
566         alias fun_t = extern(C) NSPoint function (id, SEL) nothrow @nogc;
567         return (cast(fun_t)objc_msgSend)(getClassID(), sel!"mouseLocation");
568     }
569 
570     double deltaX()
571     {
572         alias fun_t = extern(C) double function (id, SEL) nothrow @nogc;
573         version(X86)
574             return (cast(fun_t)objc_msgSend_fpret)(_id, sel!"deltaX");
575         else version(X86_64)
576             return (cast(fun_t)objc_msgSend)(_id, sel!"deltaX");
577         else
578             static assert(false);
579     }
580 
581     double deltaY()
582     {
583         alias fun_t = extern(C) double function (id, SEL) nothrow @nogc;
584         version(X86)
585             return (cast(fun_t)objc_msgSend_fpret)(_id, sel!"deltaY");
586         else version(X86_64)
587             return (cast(fun_t)objc_msgSend)(_id, sel!"deltaY");
588         else
589             static assert(false);
590     }
591 
592     ushort keyCode()
593     {
594         alias fun_t = extern(C) ushort function (id, SEL) nothrow @nogc;
595         return (cast(fun_t)objc_msgSend)(_id, sel!"keyCode");
596     }
597 
598     NSPoint locationInWindow()
599     {
600         alias fun_t = extern(C) NSPoint function (id, SEL) nothrow @nogc;
601         fun_t fun = cast(fun_t)objc_msgSend;
602         SEL sel = sel!"locationInWindow";
603         return fun(_id, sel);
604     }
605 }
606 
607 struct NSGraphicsContext
608 {
609 nothrow @nogc:
610     NSObject parent;
611     alias parent this;
612 
613     mixin NSObjectTemplate!(NSGraphicsContext, "NSGraphicsContext");
614 
615     static NSGraphicsContext currentContext()
616     {
617         alias fun_t = extern(C) id function (id, SEL) nothrow @nogc;
618         id result = (cast(fun_t)objc_msgSend)(getClassID(), sel!"currentContext");
619         return NSGraphicsContext(result);
620     }
621 
622     void saveGraphicsState()
623     {
624         alias fun_t = extern(C) void function (id, SEL) nothrow @nogc;
625         (cast(fun_t)objc_msgSend)(_id, sel!"saveGraphicsState");
626     }
627 
628     void restoreGraphicsState()
629     {
630         alias fun_t = extern(C) void function (id, SEL) nothrow @nogc;
631         (cast(fun_t)objc_msgSend)(_id, sel!"restoreGraphicsState");
632     }
633 
634     bool flipped()
635     {
636         alias fun_t = extern(C) BOOL function (id, SEL) nothrow @nogc;
637         return (cast(fun_t)objc_msgSend)(_id, sel!"flipped") != NO;
638     }
639 
640     CIContext getCIContext()
641     {
642         alias fun_t = extern(C) id function (id, SEL) nothrow @nogc;
643         id result = (cast(fun_t)objc_msgSend)(_id, sel!"CIContext");
644         return CIContext(result);
645     }
646 }
647 
648 struct NSColorSpace
649 {
650 nothrow @nogc:
651 
652     NSObject parent;
653     alias parent this;
654 
655     mixin NSObjectTemplate!(NSColorSpace, "NSColorSpace");
656 
657     static NSColorSpace sRGBColorSpace()
658     {
659         alias fun_t = extern(C) id function (id, SEL) nothrow @nogc;
660         return NSColorSpace( (cast(fun_t)objc_msgSend)(getClassID(), sel!"sRGBColorSpace") );
661     }
662 
663     // Should the NSColorSpace outlive the returned reference? Documentation says nothing.
664     CGColorSpaceRef CGColorSpace()
665     {
666         alias fun_t = extern(C) CGColorSpaceRef function (id, SEL) nothrow @nogc;
667         return (cast(fun_t)objc_msgSend)(_id, sel!"CGColorSpace");
668     }
669 }
670 
671 struct NSCursor
672 {
673 nothrow @nogc:
674 
675     NSObject parent;
676     alias parent this;
677 
678     mixin NSObjectTemplate!(NSCursor, "NSCursor");
679 
680     static NSCursor arrowCursor()
681     {
682         alias fun_t = extern(C) id function (id, SEL) nothrow @nogc;
683         return NSCursor( (cast(fun_t)objc_msgSend)(getClassID(), sel!"arrowCursor") );
684     }
685 
686     static void hide()
687     {
688         alias fun_t = extern(C) id function (id, SEL) nothrow @nogc;
689         (cast(fun_t)objc_msgSend)(getClassID(), sel!"hide");
690     }
691 
692     static void unhide()
693     {
694         alias fun_t = extern(C) id function (id, SEL) nothrow @nogc;
695         (cast(fun_t)objc_msgSend)(getClassID(), sel!"unhide");
696     }
697 
698     static void pop()
699     {
700         alias fun_t = extern(C) id function (id, SEL) nothrow @nogc;
701         (cast(fun_t)objc_msgSend)(getClassID(), sel!"pop");
702     }
703 
704     void push()
705     {
706         alias fun_t = extern(C) void function (id, SEL) nothrow @nogc;
707         objc_msgSend(_id, sel!"push");
708     }
709 
710     void set()
711     {
712         alias fun_t = extern(C) void function (id, SEL) nothrow @nogc;
713         objc_msgSend(_id, sel!"set");
714     }
715 }