hybridgroup-ruby-sdl-ffi 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,282 @@
1
+ #--
2
+ #
3
+ # This file is one part of:
4
+ #
5
+ # Ruby-SDL-FFI - Ruby-FFI bindings to SDL
6
+ #
7
+ # Copyright (c) 2009 John Croisant
8
+ #
9
+ # Permission is hereby granted, free of charge, to any person obtaining
10
+ # a copy of this software and associated documentation files (the
11
+ # "Software"), to deal in the Software without restriction, including
12
+ # without limitation the rights to use, copy, modify, merge, publish,
13
+ # distribute, sublicense, and/or sell copies of the Software, and to
14
+ # permit persons to whom the Software is furnished to do so, subject to
15
+ # the following conditions:
16
+ #
17
+ # The above copyright notice and this permission notice shall be
18
+ # included in all copies or substantial portions of the Software.
19
+ #
20
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
+ #
28
+ #++
29
+
30
+
31
+ module SDL
32
+
33
+ K_FIRST = 0
34
+ K_UNKNOWN = 0
35
+ K_BACKSPACE = 8
36
+ K_TAB = 9
37
+ K_CLEAR = 12
38
+ K_RETURN = 13
39
+ K_PAUSE = 19
40
+ K_ESCAPE = 27
41
+ K_SPACE = 32
42
+ K_EXCLAIM = 33
43
+ K_QUOTEDBL = 34
44
+ K_HASH = 35
45
+ K_DOLLAR = 36
46
+ K_AMPERSAND = 38
47
+ K_QUOTE = 39
48
+ K_LEFTPAREN = 40
49
+ K_RIGHTPAREN = 41
50
+ K_ASTERISK = 42
51
+ K_PLUS = 43
52
+ K_COMMA = 44
53
+ K_MINUS = 45
54
+ K_PERIOD = 46
55
+ K_SLASH = 47
56
+ K_0 = 48
57
+ K_1 = 49
58
+ K_2 = 50
59
+ K_3 = 51
60
+ K_4 = 52
61
+ K_5 = 53
62
+ K_6 = 54
63
+ K_7 = 55
64
+ K_8 = 56
65
+ K_9 = 57
66
+ K_COLON = 58
67
+ K_SEMICOLON = 59
68
+ K_LESS = 60
69
+ K_EQUALS = 61
70
+ K_GREATER = 62
71
+ K_QUESTION = 63
72
+ K_AT = 64
73
+ K_LEFTBRACKET = 91
74
+ K_BACKSLASH = 92
75
+ K_RIGHTBRACKET = 93
76
+ K_CARET = 94
77
+ K_UNDERSCORE = 95
78
+ K_BACKQUOTE = 96
79
+ K_a = 97
80
+ K_b = 98
81
+ K_c = 99
82
+ K_d = 100
83
+ K_e = 101
84
+ K_f = 102
85
+ K_g = 103
86
+ K_h = 104
87
+ K_i = 105
88
+ K_j = 106
89
+ K_k = 107
90
+ K_l = 108
91
+ K_m = 109
92
+ K_n = 110
93
+ K_o = 111
94
+ K_p = 112
95
+ K_q = 113
96
+ K_r = 114
97
+ K_s = 115
98
+ K_t = 116
99
+ K_u = 117
100
+ K_v = 118
101
+ K_w = 119
102
+ K_x = 120
103
+ K_y = 121
104
+ K_z = 122
105
+ K_DELETE = 127
106
+ K_WORLD_0 = 160
107
+ K_WORLD_1 = 161
108
+ K_WORLD_2 = 162
109
+ K_WORLD_3 = 163
110
+ K_WORLD_4 = 164
111
+ K_WORLD_5 = 165
112
+ K_WORLD_6 = 166
113
+ K_WORLD_7 = 167
114
+ K_WORLD_8 = 168
115
+ K_WORLD_9 = 169
116
+ K_WORLD_10 = 170
117
+ K_WORLD_11 = 171
118
+ K_WORLD_12 = 172
119
+ K_WORLD_13 = 173
120
+ K_WORLD_14 = 174
121
+ K_WORLD_15 = 175
122
+ K_WORLD_16 = 176
123
+ K_WORLD_17 = 177
124
+ K_WORLD_18 = 178
125
+ K_WORLD_19 = 179
126
+ K_WORLD_20 = 180
127
+ K_WORLD_21 = 181
128
+ K_WORLD_22 = 182
129
+ K_WORLD_23 = 183
130
+ K_WORLD_24 = 184
131
+ K_WORLD_25 = 185
132
+ K_WORLD_26 = 186
133
+ K_WORLD_27 = 187
134
+ K_WORLD_28 = 188
135
+ K_WORLD_29 = 189
136
+ K_WORLD_30 = 190
137
+ K_WORLD_31 = 191
138
+ K_WORLD_32 = 192
139
+ K_WORLD_33 = 193
140
+ K_WORLD_34 = 194
141
+ K_WORLD_35 = 195
142
+ K_WORLD_36 = 196
143
+ K_WORLD_37 = 197
144
+ K_WORLD_38 = 198
145
+ K_WORLD_39 = 199
146
+ K_WORLD_40 = 200
147
+ K_WORLD_41 = 201
148
+ K_WORLD_42 = 202
149
+ K_WORLD_43 = 203
150
+ K_WORLD_44 = 204
151
+ K_WORLD_45 = 205
152
+ K_WORLD_46 = 206
153
+ K_WORLD_47 = 207
154
+ K_WORLD_48 = 208
155
+ K_WORLD_49 = 209
156
+ K_WORLD_50 = 210
157
+ K_WORLD_51 = 211
158
+ K_WORLD_52 = 212
159
+ K_WORLD_53 = 213
160
+ K_WORLD_54 = 214
161
+ K_WORLD_55 = 215
162
+ K_WORLD_56 = 216
163
+ K_WORLD_57 = 217
164
+ K_WORLD_58 = 218
165
+ K_WORLD_59 = 219
166
+ K_WORLD_60 = 220
167
+ K_WORLD_61 = 221
168
+ K_WORLD_62 = 222
169
+ K_WORLD_63 = 223
170
+ K_WORLD_64 = 224
171
+ K_WORLD_65 = 225
172
+ K_WORLD_66 = 226
173
+ K_WORLD_67 = 227
174
+ K_WORLD_68 = 228
175
+ K_WORLD_69 = 229
176
+ K_WORLD_70 = 230
177
+ K_WORLD_71 = 231
178
+ K_WORLD_72 = 232
179
+ K_WORLD_73 = 233
180
+ K_WORLD_74 = 234
181
+ K_WORLD_75 = 235
182
+ K_WORLD_76 = 236
183
+ K_WORLD_77 = 237
184
+ K_WORLD_78 = 238
185
+ K_WORLD_79 = 239
186
+ K_WORLD_80 = 240
187
+ K_WORLD_81 = 241
188
+ K_WORLD_82 = 242
189
+ K_WORLD_83 = 243
190
+ K_WORLD_84 = 244
191
+ K_WORLD_85 = 245
192
+ K_WORLD_86 = 246
193
+ K_WORLD_87 = 247
194
+ K_WORLD_88 = 248
195
+ K_WORLD_89 = 249
196
+ K_WORLD_90 = 250
197
+ K_WORLD_91 = 251
198
+ K_WORLD_92 = 252
199
+ K_WORLD_93 = 253
200
+ K_WORLD_94 = 254
201
+ K_WORLD_95 = 255
202
+ K_KP0 = 256
203
+ K_KP1 = 257
204
+ K_KP2 = 258
205
+ K_KP3 = 259
206
+ K_KP4 = 260
207
+ K_KP5 = 261
208
+ K_KP6 = 262
209
+ K_KP7 = 263
210
+ K_KP8 = 264
211
+ K_KP9 = 265
212
+ K_KP_PERIOD = 266
213
+ K_KP_DIVIDE = 267
214
+ K_KP_MULTIPLY = 268
215
+ K_KP_MINUS = 269
216
+ K_KP_PLUS = 270
217
+ K_KP_ENTER = 271
218
+ K_KP_EQUALS = 272
219
+ K_UP = 273
220
+ K_DOWN = 274
221
+ K_RIGHT = 275
222
+ K_LEFT = 276
223
+ K_INSERT = 277
224
+ K_HOME = 278
225
+ K_END = 279
226
+ K_PAGEUP = 280
227
+ K_PAGEDOWN = 281
228
+ K_F1 = 282
229
+ K_F2 = 283
230
+ K_F3 = 284
231
+ K_F4 = 285
232
+ K_F5 = 286
233
+ K_F6 = 287
234
+ K_F7 = 288
235
+ K_F8 = 289
236
+ K_F9 = 290
237
+ K_F10 = 291
238
+ K_F11 = 292
239
+ K_F12 = 293
240
+ K_F13 = 294
241
+ K_F14 = 295
242
+ K_F15 = 296
243
+ K_NUMLOCK = 300
244
+ K_CAPSLOCK = 301
245
+ K_SCROLLOCK = 302
246
+ K_RSHIFT = 303
247
+ K_LSHIFT = 304
248
+ K_RCTRL = 305
249
+ K_LCTRL = 306
250
+ K_RALT = 307
251
+ K_LALT = 308
252
+ K_RMETA = 309
253
+ K_LMETA = 310
254
+ K_LSUPER = 311
255
+ K_RSUPER = 312
256
+ K_MODE = 313
257
+ K_COMPOSE = 314
258
+ K_HELP = 315
259
+ K_PRINT = 316
260
+ K_SYSREQ = 317
261
+ K_BREAK = 318
262
+ K_MENU = 319
263
+ K_POWER = 320
264
+ K_EURO = 321
265
+ K_UNDO = 322
266
+ K_LAST = 323
267
+
268
+ KMOD_NONE = 0x0000
269
+ KMOD_LSHIFT = 0x0001
270
+ KMOD_RSHIFT = 0x0002
271
+ KMOD_LCTRL = 0x0040
272
+ KMOD_RCTRL = 0x0080
273
+ KMOD_LALT = 0x0100
274
+ KMOD_RALT = 0x0200
275
+ KMOD_LMETA = 0x0400
276
+ KMOD_RMETA = 0x0800
277
+ KMOD_NUM = 0x1000
278
+ KMOD_CAPS = 0x2000
279
+ KMOD_MODE = 0x4000
280
+ KMOD_RESERVED = 0x8000
281
+
282
+ end
@@ -0,0 +1,443 @@
1
+ #--
2
+ #
3
+ # This file is one part of:
4
+ #
5
+ # Ruby-SDL-FFI - Ruby-FFI bindings to SDL
6
+ #
7
+ # Copyright (c) 2010 John Croisant
8
+ #
9
+ # Permission is hereby granted, free of charge, to any person obtaining
10
+ # a copy of this software and associated documentation files (the
11
+ # "Software"), to deal in the Software without restriction, including
12
+ # without limitation the rights to use, copy, modify, merge, publish,
13
+ # distribute, sublicense, and/or sell copies of the Software, and to
14
+ # permit persons to whom the Software is furnished to do so, subject to
15
+ # the following conditions:
16
+ #
17
+ # The above copyright notice and this permission notice shall be
18
+ # included in all copies or substantial portions of the Software.
19
+ #
20
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
+ #
28
+ #
29
+ # Contributions:
30
+ #
31
+ # - Bart Leusink, 2011-01-22:
32
+ # Fixed the display window not gaining focus on Mac OS X 10.6.
33
+ #
34
+ #++
35
+
36
+ #--
37
+ # Some bindings to Mac OS X system framework to allow Ruby-SDL-FFI
38
+ # to create a window on Mac without a special Ruby interpreter (rsdl).
39
+ # These are for internal use only. They are NOT part of the API.
40
+ #
41
+ # Eternal thanks to erisdiscord and jlnr for pointing the way!
42
+
43
+
44
+ # Only define this stuff if running on a Mac and not using rsdl and
45
+ # the RUBYSDLFFI_NOCOCOA environment variable is not true-ish.
46
+ if FFI::Platform.mac? and ($0 != "rsdl") and \
47
+ not (/^(1|t|true|y|yes)$/i =~ ENV["RUBYSDLFFI_NOCOCOA"])
48
+
49
+ module SDL::Mac
50
+
51
+ class << self
52
+
53
+ def make_menus( app_name )
54
+ ptr = FFI.find_type(:pointer)
55
+
56
+ nsapp = Cocoa.NSApp
57
+ menubar = Cocoa::NSMenu.new.initWithTitle("AMainMenu")
58
+ nsapp.msg( "setMainMenu:", ptr, menubar )
59
+
60
+ remove_bold_menu( nsapp, menubar )
61
+ make_app_menu( menubar, app_name )
62
+ make_window_menu( nsapp, menubar )
63
+
64
+ nil
65
+ end
66
+
67
+
68
+ def set_app_name( app_name )
69
+ ptr = FFI.find_type(:pointer)
70
+
71
+ if @appmenuitem
72
+ @appmenuitem.title = app_name
73
+ @hideitem.title = "Hide #{app_name}" if @hideitem
74
+ @quititem.title = "Quit #{app_name}" if @quititem
75
+ else
76
+ make_menus( app_name )
77
+ end
78
+
79
+ nil
80
+ end
81
+
82
+
83
+ private
84
+
85
+ # Hack to remove the bold "ruby" menu (aka the "Apple" menu).
86
+ # It's a ghost menu, it haunts us but can't be modified.
87
+ def remove_bold_menu( nsapp, menubar )
88
+ item = Cocoa::NSMenuItem.new.initWithTitle("AppleMenu")
89
+ menu = Cocoa::NSMenu.new.initWithTitle("AppleMenu")
90
+ item.submenu = menu
91
+
92
+ nsapp.msg("setAppleMenu:", FFI.find_type(:pointer), menu)
93
+ menubar.addItem(item)
94
+ menubar.removeItem(item)
95
+
96
+ item.release
97
+ menu.release
98
+ end
99
+
100
+
101
+ # Create the main menu with the app's name (Hide, Quit, etc.)
102
+ def make_app_menu( menubar, app_name )
103
+ item = Cocoa::NSMenuItem.new.initWithTitle( app_name )
104
+ menu = Cocoa::NSMenu.new.initWithTitle( app_name )
105
+ item.submenu = menu
106
+ menubar.addItem(item)
107
+
108
+ @hideitem = menu.addItemWithTitle("Hide #{app_name}", "hide:")
109
+ menu.addItemWithTitle("Hide Others", "hideOtherApplications:")
110
+ menu.addItemWithTitle("Show All", "unhideAllApplications:")
111
+
112
+ # Can't get the Quit menu item to work right yet.
113
+ # menu.addItem( Cocoa::NSMenuItem.separatorItem )
114
+ # @quititem = menu.addItemWithTitle("Quit #{app_name}", "terminate:")
115
+
116
+ @appmenuitem = item
117
+ menu.release
118
+ end
119
+
120
+
121
+ # Create the "Window" menu (Minimize, etc.)
122
+ def make_window_menu( nsapp, menubar )
123
+ ptr = FFI.find_type(:pointer)
124
+
125
+ item = Cocoa::NSMenuItem.new.initWithTitle("Window")
126
+ menu = Cocoa::NSMenu.new.initWithTitle("Window")
127
+ item.submenu = menu
128
+ menubar.addItem(item)
129
+ nsapp.msg("setWindowsMenu:", ptr, menu)
130
+
131
+ menu.addItemWithTitle("Minimize", "performMiniaturize:")
132
+
133
+ item.release
134
+ menu.release
135
+ end
136
+
137
+
138
+ def inspect_menu( menu, indent="" )
139
+ puts "%s-%s (%s \"%s\", %d items)"%[indent, menu, menu.classname,
140
+ menu.title, menu.length]
141
+ menu.each do |ob|
142
+ if ob.hasSubmenu?
143
+ inspect_menu( ob.submenu, indent+" " )
144
+ else
145
+ puts "%s -%s (%s \"%s\")"%[indent, ob, ob.classname, ob.title]
146
+ end
147
+ end
148
+ end
149
+
150
+ end
151
+
152
+
153
+ module ObjC
154
+ extend NiceFFI::Library
155
+ load_library 'objc'
156
+
157
+ typedef :pointer, :id
158
+ typedef :pointer, :sel
159
+ typedef :pointer, :ivar
160
+ typedef :pointer, :nsclass
161
+ callback :imp, [:id, :sel, :varargs], :id
162
+
163
+
164
+ class NSObject < NiceFFI::OpaqueStruct
165
+ def self.nsclassname; name.split("::")[-1]; end
166
+
167
+ # define msg, msg_ptr, msg_str, msg_int, msg_bool (and class methods)
168
+ ["", "_ptr", "_str", "_int", "_bool"].each do |suffix|
169
+ module_eval("
170
+ def msg#{suffix}( message, *args )
171
+ ObjC.msgSend#{suffix}( @pointer, message, *args )
172
+ end
173
+
174
+ def self.msg#{suffix}( message, *args )
175
+ ObjC.msgSend#{suffix}( ObjC.NSClass(self.nsclassname),
176
+ message, *args )
177
+ end")
178
+ end
179
+
180
+ def inspect; msg_str("description").to_s; end
181
+ def nsclassname; ObjC.object_getClassName(@pointer); end
182
+ def release; msg("release"); end
183
+ end
184
+
185
+ def self.NSObject( *args )
186
+ NSObject.new( *args )
187
+ end
188
+
189
+
190
+ class NSClass < NSObject
191
+ def initialize( str_or_ptr )
192
+ if str_or_ptr.is_a? String
193
+ super( ObjC.getClass(str_or_ptr) )
194
+ else
195
+ super
196
+ end
197
+ end
198
+ end
199
+
200
+ def self.NSClass( *args )
201
+ NSClass.new( *args )
202
+ end
203
+
204
+
205
+ class NSString < NSObject
206
+ def initialize( str_or_ptr )
207
+ if str_or_ptr.is_a? String
208
+ super( ObjC::NSClass("NSString").\
209
+ msg_ptr("stringWithUTF8String:",
210
+ FFI.find_type(:string), str_or_ptr) )
211
+ else
212
+ super
213
+ end
214
+ end
215
+
216
+ def to_s
217
+ str = msg_ptr( "UTF8String" )
218
+ (str.null?) ? "(NULL)" : str.read_string()
219
+ end
220
+ end
221
+
222
+ def self.NSString( *args )
223
+ NSString.new( *args )
224
+ end
225
+
226
+
227
+ func :__msgSend, :objc_msgSend, [:id, :sel, :varargs], :id
228
+ func :__msgSend_int, :objc_msgSend, [:id, :sel, :varargs], :long
229
+
230
+ def self.msgSend( id, selector, *args )
231
+ selector = self.sel(selector) if selector.is_a? String
232
+ NSObject.new( __msgSend( id, selector, *args ) )
233
+ end
234
+ def self.msgSend_ptr( id, selector, *args )
235
+ selector = self.sel(selector) if selector.is_a? String
236
+ __msgSend( id, selector, *args )
237
+ end
238
+ def self.msgSend_str( id, selector, *args )
239
+ selector = self.sel(selector) if selector.is_a? String
240
+ NSString.new( __msgSend( id, selector, *args ) )
241
+ end
242
+ def self.msgSend_int( id, selector, *args )
243
+ selector = self.sel(selector) if selector.is_a? String
244
+ __msgSend_int( id, selector, *args )
245
+ end
246
+ def self.msgSend_bool( id, selector, *args )
247
+ selector = self.sel(selector) if selector.is_a? String
248
+ ( __msgSend_int( id, selector, *args ) == 0 ) ? false : true
249
+ end
250
+
251
+ func :getClass, :objc_getClass, [:string], :id
252
+ func :class_replaceMethod, [:nsclass, :sel, :imp, :string], :imp
253
+
254
+ func :object_getClassName, [:id], :string
255
+ func :object_getInstanceVariable, [:id, :string, :pointer], :ivar
256
+ func :object_setInstanceVariable, [:id, :string, :pointer], :ivar
257
+
258
+ func :sel_registerName, [:string], :sel
259
+ func :sel_getName, [:sel], :string
260
+
261
+ def self.sel( name )
262
+ sel_registerName( name.to_s )
263
+ end
264
+
265
+ end
266
+
267
+
268
+ module Cocoa
269
+ extend NiceFFI::Library
270
+ load_library '/System/Library/Frameworks/Cocoa.framework/Cocoa'
271
+
272
+ func :NSApplicationLoad, [], :bool
273
+
274
+ func :NSPushAutoreleasePool, [], :void
275
+ func :NSPopAutoreleasePool, [], :void
276
+
277
+ NSApplicationLoad()
278
+ NSPushAutoreleasePool()
279
+
280
+ def self.NSApp
281
+ @nsapp ||= ObjC::NSClass("NSApplication").msg("sharedApplication")
282
+ end
283
+
284
+ class NSMenu < ObjC::NSObject
285
+ include Enumerable
286
+
287
+ def initialize( *args )
288
+ if args.empty?
289
+ super( ObjC::NSClass("NSMenu").msg_ptr("alloc") )
290
+ else
291
+ super( args[0] )
292
+ end
293
+ end
294
+
295
+ def initWithTitle( title )
296
+ msg( "initWithTitle:", FFI.find_type(:pointer), ObjC::NSString(title) )
297
+ self
298
+ end
299
+
300
+ def title
301
+ msg_str("title")
302
+ end
303
+
304
+ def title=( t )
305
+ msg("setTitle:", FFI.find_type(:pointer), ObjC::NSString(t))
306
+ end
307
+
308
+ def addItem( item )
309
+ msg("addItem:", FFI.find_type(:pointer), item)
310
+ self
311
+ end
312
+
313
+ def addItemWithTitle( title, action=nil, keyEquivalent="" )
314
+ ptr = FFI.find_type(:pointer)
315
+ action = ObjC.sel(action) if action.is_a? String
316
+ item = msg_ptr( "addItemWithTitle:action:keyEquivalent:",
317
+ ptr, ObjC::NSString(title),
318
+ ptr, action,
319
+ ptr, ObjC::NSString(keyEquivalent))
320
+ NSMenuItem.new(item)
321
+ end
322
+
323
+ def removeItem( item )
324
+ msg("removeItem:", FFI.find_type(:pointer), item)
325
+ self
326
+ end
327
+
328
+ def removeItemAtIndex( index )
329
+ msg("removeItemAtIndex:", FFI.find_type(:long), index)
330
+ self
331
+ end
332
+
333
+ def length
334
+ msg_int( "numberOfItems" )
335
+ end
336
+
337
+ def [](index)
338
+ Cocoa::NSMenuItem( msg_ptr("itemAtIndex:", FFI.find_type(:long), index) )
339
+ end
340
+
341
+ def each
342
+ length.times{ |i| yield self[i] }
343
+ end
344
+ end
345
+
346
+ def self.NSMenu( *args )
347
+ NSMenu.new( *args )
348
+ end
349
+
350
+
351
+ class NSMenuItem < ObjC::NSObject
352
+ def self.separatorItem
353
+ new( msg_ptr("separatorItem") )
354
+ end
355
+
356
+ def initialize( *args )
357
+ if args.empty?
358
+ super( ObjC::NSClass("NSMenuItem").msg_ptr("alloc") )
359
+ else
360
+ super( args[0] )
361
+ end
362
+ end
363
+
364
+ def initWithTitle( title, action=nil, keyEquivalent="" )
365
+ ptr = FFI.find_type(:pointer)
366
+ action = ObjC.sel(action) if action.is_a? String
367
+ msg( "initWithTitle:action:keyEquivalent:",
368
+ ptr, ObjC::NSString(title),
369
+ ptr, action,
370
+ ptr, ObjC::NSString(keyEquivalent))
371
+ self
372
+ end
373
+
374
+ def title
375
+ msg_str("title")
376
+ end
377
+
378
+ def title=( t )
379
+ msg("setTitle:", FFI.find_type(:pointer), ObjC::NSString(t))
380
+ end
381
+
382
+ def hasSubmenu?
383
+ msg_bool("hasSubmenu")
384
+ end
385
+
386
+ def submenu
387
+ Cocoa::NSMenu( msg_ptr("submenu") ) if hasSubmenu?
388
+ end
389
+
390
+ def submenu=( menu )
391
+ msg("setSubmenu:", FFI.find_type(:pointer), menu)
392
+ end
393
+ end
394
+
395
+ def self.NSMenuItem( *args )
396
+ NSMenuItem.new( *args )
397
+ end
398
+
399
+
400
+ attach_variable "vNSNibOwner", "NSNibOwner", :pointer
401
+ NSNibOwner =
402
+ ObjC::NSString( ObjC::NSString(self.vNSNibOwner).to_s )
403
+
404
+ attach_variable "vNSNibTopLevelObjects", "NSNibTopLevelObjects", :pointer
405
+ NSNibTopLevelObjects =
406
+ ObjC::NSString( ObjC::NSString(self.vNSNibTopLevelObjects).to_s )
407
+
408
+ NSAlphaShiftKeyMask = 1 << 16
409
+ NSShiftKeyMask = 1 << 17
410
+ NSControlKeyMask = 1 << 18
411
+ NSAlternateKeyMask = 1 << 19
412
+ NSCommandKeyMask = 1 << 20
413
+ NSNumericPadKeyMask = 1 << 21
414
+ NSHelpKeyMask = 1 << 22
415
+ NSFunctionKeyMask = 1 << 23
416
+ end
417
+
418
+
419
+ module HIServices
420
+ extend NiceFFI::Library
421
+ load_library '/System/Library/Frameworks/ApplicationServices.framework/Frameworks/HIServices.framework/HIServices'
422
+
423
+ class ProcessSerialNumber < NiceFFI::Struct
424
+ layout :highLongOfPSN, :ulong, :lowLongOfPSN, :ulong
425
+ end
426
+
427
+ KProcessTransformToForegroundApplication = 1
428
+
429
+ func :GetCurrentProcess, [:pointer], :long
430
+ func :TransformProcessType, [:pointer, :long], :long
431
+ func :SetFrontProcess, [:pointer], :long
432
+
433
+ # Does the magic to make the current process a front process.
434
+ def self.make_current_front
435
+ current = ProcessSerialNumber.new( [0, 0] )
436
+ GetCurrentProcess( current )
437
+ TransformProcessType(current,KProcessTransformToForegroundApplication)
438
+ SetFrontProcess( current )
439
+ end
440
+ end
441
+
442
+ end
443
+ end