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