1 ! Copyright (C) 2006, 2009 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors alien.c-types alien.data arrays assocs classes
4 cocoa cocoa.application cocoa.classes cocoa.messages cocoa.nibs
5 cocoa.pasteboard cocoa.runtime cocoa.subclassing cocoa.types
6 cocoa.views cocoa.windows combinators command-line
7 core-foundation core-foundation.run-loop core-graphics
8 core-graphics.types destructors fry generalizations io.thread
9 kernel libc literals locals math math.bitwise math.rectangles
10 memory namespaces sequences threads ui colors ui.backend
11 ui.backend.cocoa.views ui.clipboards ui.gadgets
12 ui.gadgets.worlds ui.pixel-formats ui.private words.symbol ;
15 TUPLE: window-handle view window ;
17 C: <window-handle> window-handle
19 SINGLETON: cocoa-ui-backend
21 CONSTANT: attrib-table H{
22 { double-buffered { $ NSOpenGLPFADoubleBuffer } }
23 { stereo { $ NSOpenGLPFAStereo } }
24 { offscreen { $ NSOpenGLPFAOffScreen } }
25 { fullscreen { $ NSOpenGLPFAFullScreen } }
26 { windowed { $ NSOpenGLPFAWindow } }
27 { accelerated { $ NSOpenGLPFAAccelerated } }
29 $ NSOpenGLPFARendererID
30 $ kCGLRendererGenericFloatID }
32 { backing-store { $ NSOpenGLPFABackingStore } }
33 { multisampled { $ NSOpenGLPFAMultisample } }
34 { supersampled { $ NSOpenGLPFASupersample } }
35 { sample-alpha { $ NSOpenGLPFASampleAlpha } }
36 { color-float { $ NSOpenGLPFAColorFloat } }
37 { color-bits { $ NSOpenGLPFAColorSize } }
38 { alpha-bits { $ NSOpenGLPFAAlphaSize } }
39 { accum-bits { $ NSOpenGLPFAAccumSize } }
40 { depth-bits { $ NSOpenGLPFADepthSize } }
41 { stencil-bits { $ NSOpenGLPFAStencilSize } }
42 { aux-buffers { $ NSOpenGLPFAAuxBuffers } }
43 { sample-buffers { $ NSOpenGLPFASampleBuffers } }
44 { samples { $ NSOpenGLPFASamples } }
47 M: cocoa-ui-backend (make-pixel-format)
48 nip { } attrib-table pixel-format-attributes>int-array
49 NSOpenGLPixelFormat -> alloc swap -> initWithAttributes: ;
51 M: cocoa-ui-backend (free-pixel-format)
54 TUPLE: pasteboard handle ;
56 C: <pasteboard> pasteboard
58 M: pasteboard clipboard-contents
59 handle>> pasteboard-string ;
61 M: pasteboard set-clipboard-contents
62 handle>> set-pasteboard-string ;
64 : init-clipboard ( -- )
65 NSPasteboard -> generalPasteboard <pasteboard>
67 <clipboard> selection set-global ;
69 : world>NSRect ( world -- NSRect )
70 [ 0 0 ] dip dim>> first2 <CGRect> ;
72 : auto-position ( window loc -- )
73 ! Note: if this is the initial window, the length of the windows
74 ! vector should be 1, since (open-window) calls auto-position
75 ! after register-window.
78 worlds get-global length 1 <= [ -> center ] [
79 worlds get-global last second window-loc>>
80 dupd first2 <CGPoint> -> cascadeTopLeftFromPoint:
81 -> setFrameTopLeftPoint:
83 ] [ first2 <CGPoint> -> setFrameTopLeftPoint: ] if ;
85 M: cocoa-ui-backend set-title ( string world -- )
86 handle>> window>> swap <NSString> -> setTitle: ;
88 : enter-fullscreen ( world -- )
90 NSScreen -> mainScreen
91 f -> enterFullScreenMode:withOptions:
94 : exit-fullscreen ( world -- )
96 [ view>> f -> exitFullScreenModeWithOptions: ]
97 [ [ window>> ] [ view>> ] bi -> makeFirstResponder: drop ] bi ;
99 M: cocoa-ui-backend (set-fullscreen) ( world ? -- )
100 [ enter-fullscreen ] [ exit-fullscreen ] if ;
102 M: cocoa-ui-backend (fullscreen?) ( world -- ? )
103 handle>> view>> -> isInFullScreenMode zero? not ;
105 ! XXX: Until someone tests OSX with a tiling window manager,
106 ! dialog-window is the same as normal-title-window
107 CONSTANT: window-control>styleMask
109 { close-button $ NSClosableWindowMask }
110 { minimize-button $ NSMiniaturizableWindowMask }
111 { maximize-button 0 }
112 { resize-handles $ NSResizableWindowMask }
113 { small-title-bar flags{ NSTitledWindowMask NSUtilityWindowMask } }
114 { textured-background $ NSTexturedBackgroundWindowMask }
115 { normal-title-bar $ NSTitledWindowMask }
116 { dialog-window $ NSTitledWindowMask }
119 : world>styleMask ( world -- n )
120 window-controls>> window-control>styleMask symbols>flags ;
122 : make-context-transparent ( view -- )
124 0 int <ref> NSOpenGLCPSurfaceOpacity -> setValues:forParameter: ;
126 M:: cocoa-ui-backend (open-window) ( world -- )
127 world [ [ dim>> ] dip <FactorView> ]
128 with-world-pixel-format :> view
129 world window-controls>> textured-background swap member-eq?
130 [ view make-context-transparent ] when
131 view world [ world>NSRect ] [ world>styleMask ] bi <ViewWindow> :> window
133 world view register-window
134 window world window-loc>> auto-position
135 world window save-position
136 window install-window-delegate
137 view window <window-handle> world handle<<
138 window f -> makeKeyAndOrderFront:
141 M: cocoa-ui-backend (close-window) ( handle -- )
143 view>> dup -> isInFullScreenMode zero?
145 [ f -> exitFullScreenModeWithOptions: ] if
146 ] [ window>> -> release ] bi ;
148 M: cocoa-ui-backend (grab-input) ( handle -- )
149 0 CGAssociateMouseAndMouseCursorPosition drop
150 CGMainDisplayID CGDisplayHideCursor drop
151 window>> -> frame CGRect>rect rect-center
152 NSScreen -> screens 0 -> objectAtIndex: -> frame CGRect-h
153 [ drop first ] [ swap second - ] 2bi <CGPoint>
154 [ GetCurrentButtonState zero? not ] [ yield ] while
155 CGWarpMouseCursorPosition drop ;
157 M: cocoa-ui-backend (ungrab-input) ( handle -- )
159 CGMainDisplayID CGDisplayShowCursor drop
160 1 CGAssociateMouseAndMouseCursorPosition drop ;
162 M: cocoa-ui-backend close-window ( gadget -- )
169 M: cocoa-ui-backend raise-window* ( world -- )
171 window>> dup f -> orderFront: -> makeKeyWindow
172 NSApp 1 -> activateIgnoringOtherApps:
175 M: window-handle select-gl-context ( handle -- )
176 view>> -> openGLContext -> makeCurrentContext ;
178 M: window-handle flush-gl-context ( handle -- )
179 view>> -> openGLContext -> flushBuffer ;
181 M: cocoa-ui-backend beep ( -- )
184 M: cocoa-ui-backend resize-window
185 [ handle>> window>> ] [ first2 ] bi* <CGSize> -> setContentSize: ;
187 M: cocoa-ui-backend system-alert
188 NSAlert -> alloc -> init -> autorelease [
190 [ swap <NSString> -> setInformativeText: ]
191 [ swap <NSString> -> setMessageText: ]
192 [ "OK" <NSString> -> addButtonWithTitle: drop ]
197 <CLASS: FactorApplicationDelegate < NSObject
199 METHOD: void applicationDidUpdate: id obj [ reset-thread-timer ] ;
201 METHOD: char applicationShouldTerminateAfterLastWindowClosed: id app [
202 ui-stop-after-last-window? get 1 0 ?
206 : install-app-delegate ( -- )
207 NSApp FactorApplicationDelegate install-delegate ;
209 SYMBOL: cocoa-startup-hook
212 [ "MiniFactor.nib" load-nib install-app-delegate ]
215 M: cocoa-ui-backend (with-ui)
218 cocoa-startup-hook get call( -- )
226 cocoa-ui-backend ui-backend set-global
228 M: cocoa-ui-backend ui-backend-available?