reflexion 0.5.2 → 0.6.0

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.
Files changed (145) hide show
  1. checksums.yaml +4 -4
  2. data/.doc/ext/reflex/application.cpp +19 -1
  3. data/.doc/ext/reflex/chase_constraint.cpp +84 -0
  4. data/.doc/ext/reflex/clipboard.cpp +65 -0
  5. data/.doc/ext/reflex/constraint.cpp +135 -0
  6. data/.doc/ext/reflex/key_event.cpp +6 -6
  7. data/.doc/ext/reflex/link_constraint.cpp +178 -0
  8. data/.doc/ext/reflex/menu.cpp +302 -0
  9. data/.doc/ext/reflex/native.cpp +22 -4
  10. data/.doc/ext/reflex/pin.cpp +156 -0
  11. data/.doc/ext/reflex/pointer.cpp +2 -0
  12. data/.doc/ext/reflex/pointer_event.cpp +1 -1
  13. data/.doc/ext/reflex/reflex.cpp +42 -7
  14. data/.doc/ext/reflex/selector.cpp +4 -4
  15. data/.doc/ext/reflex/snap_constraint.cpp +125 -0
  16. data/.doc/ext/reflex/style_length.cpp +3 -2
  17. data/.doc/ext/reflex/view.cpp +96 -23
  18. data/.doc/ext/reflex/wheel_constraint.cpp +142 -0
  19. data/.doc/ext/reflex/window.cpp +59 -17
  20. data/.github/workflows/release-gem.yml +10 -1
  21. data/.github/workflows/test.yml +9 -0
  22. data/ChangeLog.md +30 -0
  23. data/README.md +1 -0
  24. data/VERSION +1 -1
  25. data/ext/reflex/application.cpp +21 -1
  26. data/ext/reflex/chase_constraint.cpp +89 -0
  27. data/ext/reflex/clipboard.cpp +69 -0
  28. data/ext/reflex/constraint.cpp +146 -0
  29. data/ext/reflex/key_event.cpp +6 -6
  30. data/ext/reflex/link_constraint.cpp +194 -0
  31. data/ext/reflex/menu.cpp +330 -0
  32. data/ext/reflex/native.cpp +22 -4
  33. data/ext/reflex/pin.cpp +165 -0
  34. data/ext/reflex/pointer.cpp +2 -0
  35. data/ext/reflex/pointer_event.cpp +1 -1
  36. data/ext/reflex/reflex.cpp +42 -7
  37. data/ext/reflex/selector.cpp +4 -4
  38. data/ext/reflex/selector.h +1 -1
  39. data/ext/reflex/snap_constraint.cpp +135 -0
  40. data/ext/reflex/style_length.cpp +3 -2
  41. data/ext/reflex/view.cpp +117 -37
  42. data/ext/reflex/wheel_constraint.cpp +154 -0
  43. data/ext/reflex/window.cpp +65 -18
  44. data/include/reflex/application.h +9 -0
  45. data/include/reflex/clipboard.h +53 -0
  46. data/include/reflex/constraint.h +275 -0
  47. data/include/reflex/defs.h +204 -195
  48. data/include/reflex/event.h +2 -0
  49. data/include/reflex/menu.h +120 -0
  50. data/include/reflex/pin.h +68 -0
  51. data/include/reflex/pointer.h +4 -0
  52. data/include/reflex/ruby/clipboard.h +23 -0
  53. data/include/reflex/ruby/constraint.h +94 -0
  54. data/include/reflex/ruby/menu.h +103 -0
  55. data/include/reflex/ruby/pin.h +40 -0
  56. data/include/reflex/ruby/view.h +36 -0
  57. data/include/reflex/ruby/window.h +36 -18
  58. data/include/reflex/view.h +39 -12
  59. data/include/reflex/window.h +17 -4
  60. data/include/reflex.h +5 -0
  61. data/lib/reflex/chase_constraint.rb +15 -0
  62. data/lib/reflex/clipboard.rb +19 -0
  63. data/lib/reflex/constraint.rb +29 -0
  64. data/lib/reflex/extension.rb +1 -1
  65. data/lib/reflex/helper.rb +28 -0
  66. data/lib/reflex/key_event.rb +7 -12
  67. data/lib/reflex/link_constraint.rb +31 -0
  68. data/lib/reflex/menu.rb +76 -0
  69. data/lib/reflex/pin.rb +39 -0
  70. data/lib/reflex/pointer.rb +18 -0
  71. data/lib/reflex/pointer_event.rb +1 -1
  72. data/lib/reflex/snap_constraint.rb +28 -0
  73. data/lib/reflex/view.rb +56 -4
  74. data/lib/reflex/wheel_constraint.rb +28 -0
  75. data/lib/reflex/wheel_event.rb +9 -0
  76. data/lib/reflex.rb +15 -6
  77. data/pod.rake +4 -2
  78. data/reflex.gemspec +3 -3
  79. data/samples/constraint.rb +152 -0
  80. data/samples/menu.rb +29 -0
  81. data/src/application.cpp +21 -2
  82. data/src/application.h +5 -0
  83. data/src/clipboard.cpp +81 -0
  84. data/src/constraint.cpp +1662 -0
  85. data/src/constraint.h +64 -0
  86. data/src/event.cpp +7 -1
  87. data/src/event.h +1 -2
  88. data/src/ios/application.mm +5 -0
  89. data/src/ios/clipboard.mm +44 -0
  90. data/src/ios/event.h +6 -2
  91. data/src/ios/event.mm +31 -12
  92. data/src/ios/menu.mm +36 -0
  93. data/src/ios/view_controller.mm +45 -12
  94. data/src/ios/window.mm +6 -0
  95. data/src/menu.cpp +325 -0
  96. data/src/menu.h +65 -0
  97. data/src/osx/app_delegate.mm +74 -125
  98. data/src/osx/application.mm +16 -0
  99. data/src/osx/clipboard.mm +45 -0
  100. data/src/osx/event.mm +40 -10
  101. data/src/osx/menu.h +25 -0
  102. data/src/osx/menu.mm +372 -0
  103. data/src/osx/native_window.mm +27 -0
  104. data/src/osx/opengl_view.mm +51 -0
  105. data/src/osx/window.mm +11 -0
  106. data/src/pin.cpp +137 -0
  107. data/src/pointer.cpp +27 -16
  108. data/src/pointer.h +6 -0
  109. data/src/sdl/application.cpp +5 -0
  110. data/src/sdl/clipboard.cpp +39 -0
  111. data/src/sdl/event.cpp +20 -3
  112. data/src/sdl/event.h +6 -3
  113. data/src/sdl/menu.cpp +35 -0
  114. data/src/sdl/window.cpp +26 -8
  115. data/src/view.cpp +313 -52
  116. data/src/view.h +18 -2
  117. data/src/win32/application.cpp +5 -0
  118. data/src/win32/clipboard.cpp +210 -0
  119. data/src/win32/event.cpp +11 -1
  120. data/src/win32/event.h +2 -0
  121. data/src/win32/menu.cpp +352 -0
  122. data/src/win32/menu.h +27 -0
  123. data/src/win32/window.cpp +62 -0
  124. data/src/win32/window.h +3 -0
  125. data/src/window.cpp +235 -22
  126. data/src/window.h +13 -2
  127. data/src/world.cpp +77 -14
  128. data/src/world.h +9 -2
  129. data/test/helper.rb +7 -0
  130. data/test/test_application.rb +11 -0
  131. data/test/test_chase_constraint.rb +124 -0
  132. data/test/test_clipboard.rb +54 -0
  133. data/test/test_constraint.rb +186 -0
  134. data/test/test_key_event.rb +6 -0
  135. data/test/test_link_constraint.rb +239 -0
  136. data/test/test_menu.rb +207 -0
  137. data/test/test_pin.rb +65 -0
  138. data/test/test_pointer.rb +23 -9
  139. data/test/test_pointer_event.rb +1 -1
  140. data/test/test_snap_constraint.rb +142 -0
  141. data/test/test_view.rb +113 -23
  142. data/test/test_wheel_constraint.rb +127 -0
  143. data/test/test_wheel_event.rb +15 -9
  144. data/test/test_window.rb +10 -0
  145. metadata +82 -8
data/src/osx/event.mm CHANGED
@@ -18,14 +18,14 @@ namespace Reflex
18
18
  {
19
19
  NSUInteger flags = event ? event.modifierFlags : NSEvent.modifierFlags;
20
20
  return
21
- (flags & NSAlphaShiftKeyMask) ? MOD_CAPS : 0 |
22
- (flags & NSShiftKeyMask) ? MOD_SHIFT : 0 |
23
- (flags & NSControlKeyMask) ? MOD_CONTROL : 0 |
24
- (flags & NSAlternateKeyMask) ? MOD_OPTION : 0 |
25
- (flags & NSCommandKeyMask) ? MOD_COMMAND : 0 |
26
- (flags & NSNumericPadKeyMask) ? MOD_NUMPAD : 0 |
27
- (flags & NSHelpKeyMask) ? MOD_HELP : 0 |
28
- (flags & NSFunctionKeyMask) ? MOD_FUNCTION : 0;
21
+ (flags & NSAlphaShiftKeyMask ? MOD_CAPS : 0) |
22
+ (flags & NSShiftKeyMask ? MOD_SHIFT : 0) |
23
+ (flags & NSControlKeyMask ? MOD_CONTROL : 0) |
24
+ (flags & NSAlternateKeyMask ? MOD_OPTION : 0) |
25
+ (flags & NSCommandKeyMask ? MOD_COMMAND : 0) |
26
+ (flags & NSNumericPadKeyMask ? MOD_NUMPAD : 0) |
27
+ (flags & NSHelpKeyMask ? MOD_HELP : 0) |
28
+ (flags & NSFunctionKeyMask ? MOD_FUNCTION : 0);
29
29
  }
30
30
 
31
31
  static Point
@@ -52,8 +52,17 @@ namespace Reflex
52
52
  return [chars UTF8String];
53
53
  }
54
54
 
55
+ static int
56
+ get_key_code (NSEvent* e)
57
+ {
58
+ // fn+return on a laptop keyboard reports a code of its own, which
59
+ // has no kVK_* name; it is the same key as the enter on the keypad
60
+ // of an external keyboard
61
+ return e.keyCode == 0x34 ? kVK_ANSI_KeypadEnter : e.keyCode;
62
+ }
63
+
55
64
  NativeKeyEvent::NativeKeyEvent (NSEvent* e, Action action, int repeat)
56
- : KeyEvent(action, get_chars(e), [e keyCode], get_modifiers(e), repeat)
65
+ : KeyEvent(action, get_chars(e), get_key_code(e), get_modifiers(e), repeat)
57
66
  {
58
67
  }
59
68
 
@@ -137,6 +146,8 @@ namespace Reflex
137
146
  return Reflex::Pointer::MOUSE | Reflex::Pointer::MOUSE_MIDDLE;
138
147
 
139
148
  case NSMouseMoved:
149
+ case NSMouseEntered:
150
+ case NSMouseExited:
140
151
  return Reflex::Pointer::MOUSE | get_current_pointer_type();
141
152
 
142
153
  default:
@@ -144,6 +155,25 @@ namespace Reflex
144
155
  }
145
156
  }
146
157
 
158
+ static uint
159
+ get_click_count (NSEvent* e, Pointer::Action action, bool dragging)
160
+ {
161
+ switch (action)
162
+ {
163
+ case Pointer::DOWN:
164
+ case Pointer::UP:
165
+ return (uint) e.clickCount;
166
+
167
+ case Pointer::MOVE:
168
+ return dragging ? (uint) e.clickCount : 0;
169
+
170
+ default:
171
+ // asking clickCount raises NSInternalInconsistencyException for
172
+ // tracking (enter/exit) events.
173
+ return 0;
174
+ }
175
+ }
176
+
147
177
  NativePointerEvent::NativePointerEvent (
148
178
  NSEvent* event, NSView* view, Pointer::Action action)
149
179
  {
@@ -154,7 +184,7 @@ namespace Reflex
154
184
  action,
155
185
  get_pointer_position(event, view),
156
186
  get_modifiers(event),
157
- action == Pointer::MOVE && !dragging ? 0 : (uint) event.clickCount,
187
+ get_click_count(event, action, dragging),
158
188
  dragging,
159
189
  time()));
160
190
  }
data/src/osx/menu.h ADDED
@@ -0,0 +1,25 @@
1
+ // -*- objc -*-
2
+ #pragma once
3
+ #ifndef __REFLEX_SRC_OSX_MENU_H__
4
+ #define __REFLEX_SRC_OSX_MENU_H__
5
+
6
+
7
+ #import <AppKit/NSMenu.h>
8
+ #include "../menu.h"
9
+
10
+
11
+ namespace Reflex
12
+ {
13
+
14
+
15
+ NSMenu* Menu_get_nssubmenu (Menu* menu);
16
+
17
+ void Menu_set_native_action (Menu* menu, SEL action);
18
+
19
+ void Menu_apply_to_main_menu (Menu* menu);
20
+
21
+
22
+ }// Reflex
23
+
24
+
25
+ #endif//EOH
data/src/osx/menu.mm ADDED
@@ -0,0 +1,372 @@
1
+ // -*- objc -*-
2
+ #include "menu.h"
3
+
4
+
5
+ #import <Cocoa/Cocoa.h>
6
+ #import <AppKit/AppKit.h>
7
+ #import <objc/runtime.h>
8
+ #include "reflex/exception.h"
9
+ #include "reflex/event.h"
10
+ #include "reflex/view.h"
11
+ #include "window.h"
12
+ #include "screen.h"
13
+ #import "native_window.h"
14
+
15
+
16
+ namespace Rays
17
+ {
18
+ NSImage* Bitmap_get_nsimage (const Bitmap& bmp);
19
+ }
20
+
21
+
22
+ @interface ReflexMenuTarget : NSObject <NSMenuDelegate>
23
+ - (void) handleMenuItem: (NSMenuItem*) sender;
24
+ @end
25
+
26
+
27
+ static NSValue*
28
+ menu2value (Reflex::Menu* menu)
29
+ {
30
+ return [NSValue valueWithPointer: menu];
31
+ }
32
+
33
+ static Reflex::Menu*
34
+ value2menu (NSValue* value)
35
+ {
36
+ return value ? (Reflex::Menu*) value.pointerValue : NULL;
37
+ }
38
+
39
+ static void
40
+ set_owner (NSMenuItem* nsitem, Reflex::Menu* owner)
41
+ {
42
+ [nsitem setRepresentedObject: menu2value(owner)];
43
+ }
44
+
45
+ static Reflex::Menu*
46
+ get_owner (NSMenuItem* nsitem)
47
+ {
48
+ return value2menu(nsitem.representedObject);
49
+ }
50
+
51
+ static void*
52
+ associated_object_key ()
53
+ {
54
+ static char key;
55
+ return &key;
56
+ }
57
+
58
+ static void
59
+ set_owner (NSMenu* nsmenu, Reflex::Menu* owner)
60
+ {
61
+ objc_setAssociatedObject(
62
+ nsmenu, associated_object_key(), menu2value(owner),
63
+ OBJC_ASSOCIATION_RETAIN_NONATOMIC);
64
+ }
65
+
66
+ static Reflex::Menu*
67
+ get_owner (NSMenu* nsmenu)
68
+ {
69
+ return value2menu(objc_getAssociatedObject(nsmenu, associated_object_key()));
70
+ }
71
+
72
+ static ReflexMenuTarget*
73
+ menu_target ()
74
+ {
75
+ static ReflexMenuTarget* target = [[ReflexMenuTarget alloc] init];
76
+ return target;
77
+ }
78
+
79
+
80
+ namespace Reflex
81
+ {
82
+
83
+
84
+ struct MenuData : public Menu::Data
85
+ {
86
+
87
+ NSMenuItem* nsitem = nil;
88
+
89
+ NSMenu* nssubmenu = nil;
90
+
91
+ SEL native_action = NULL;
92
+
93
+ MenuData ()
94
+ {
95
+ nsitem = [[NSMenuItem alloc]
96
+ initWithTitle: @"" action: @selector(handleMenuItem:) keyEquivalent: @""];
97
+ }
98
+
99
+ virtual ~MenuData ()
100
+ {
101
+ [nsitem release];
102
+ [nssubmenu release];
103
+ }
104
+
105
+ NSMenu* get_nssubmenu (Menu* menu)
106
+ {
107
+ if (!nssubmenu)
108
+ {
109
+ nssubmenu = [[NSMenu alloc] initWithTitle: @""];
110
+ set_owner(nssubmenu, menu);
111
+ [nssubmenu setAutoenablesItems: NO];
112
+ [nssubmenu setDelegate: menu_target()];
113
+ [nsitem setSubmenu: nssubmenu];
114
+ }
115
+ return nssubmenu;
116
+ }
117
+
118
+ };// MenuData
119
+
120
+
121
+ static MenuData&
122
+ get_data (Menu* menu)
123
+ {
124
+ if (!menu)
125
+ argument_error(__FILE__, __LINE__);
126
+
127
+ return (MenuData&) *menu->self;
128
+ }
129
+
130
+ static void
131
+ Menu_validate_items (NSMenu* nsmenu)
132
+ {
133
+ for (NSMenuItem* nsitem in nsmenu.itemArray)
134
+ {
135
+ Menu* menu = get_owner(nsitem);
136
+ if (!menu) continue;
137
+
138
+ MenuData& self = get_data(menu);
139
+ if (!self.native_action) continue;
140
+
141
+ [nsitem setEnabled:
142
+ menu->is_enabled() && [NSApp targetForAction: self.native_action] != nil];
143
+ }
144
+ }
145
+
146
+ Menu::Data*
147
+ Menu_create_data ()
148
+ {
149
+ return new MenuData();
150
+ }
151
+
152
+ static NSEventModifierFlags
153
+ modifiers2mask (uint mods)
154
+ {
155
+ NSEventModifierFlags mask = 0;
156
+ if (mods & MOD_SHIFT) mask |= NSEventModifierFlagShift;
157
+ if (mods & MOD_CONTROL) mask |= NSEventModifierFlagControl;
158
+ if (mods & MOD_COMMAND) mask |= NSEventModifierFlagCommand;
159
+ if (mods & (MOD_OPTION | MOD_ALT)) mask |= NSEventModifierFlagOption;
160
+ return mask;
161
+ }
162
+
163
+ void
164
+ Menu_update (Menu* menu)
165
+ {
166
+ auto& self = get_data(menu);
167
+ bool old_sep = self.nsitem && self.nsitem.isSeparatorItem;
168
+ bool is_sep = menu->is_separator();
169
+
170
+ if (!self.nsitem || is_sep != old_sep)
171
+ {
172
+ NSMenu* parent = self.nsitem.menu;
173
+ NSInteger index = parent ? [parent indexOfItem: self.nsitem] : -1;
174
+
175
+ NSMenuItem* nsitem = is_sep
176
+ ? [[NSMenuItem separatorItem] retain]
177
+ : [[NSMenuItem alloc]
178
+ initWithTitle: @""
179
+ action: @selector(handleMenuItem:)
180
+ keyEquivalent: @""];
181
+
182
+ if (parent)
183
+ {
184
+ [parent removeItem: self.nsitem];
185
+ [parent insertItem: nsitem atIndex: index];
186
+ }
187
+
188
+ [self.nsitem release];
189
+ self.nsitem = nsitem;
190
+ }
191
+
192
+ if (is_sep) return;
193
+
194
+ set_owner(self.nsitem, menu);
195
+ [self.nsitem setTarget: self.native_action ? nil : menu_target()];
196
+ [self.nsitem setAction: self.native_action ? self.native_action : @selector(handleMenuItem:)];
197
+ [self.nsitem setTitle: [NSString stringWithUTF8String: menu->label()]];
198
+ [self.nsitem setEnabled: menu->is_enabled() ? YES : NO];
199
+ [self.nsitem setState: menu->is_checked() ? NSControlStateValueOn : NSControlStateValueOff];
200
+ [self.nsitem setKeyEquivalent: [NSString stringWithUTF8String: menu->shortcut_key()]];
201
+ [self.nsitem setKeyEquivalentModifierMask: modifiers2mask(menu->shortcut_modifiers())];
202
+ [self.nsitem setImage: menu->image() ? Rays::Bitmap_get_nsimage(menu->image().bitmap()) : nil];
203
+ [self.nsitem setSubmenu: menu->empty() ? nil : self.nssubmenu];
204
+ }
205
+
206
+ void
207
+ Menu_popup (Menu* menu, View* view, coord x, coord y)
208
+ {
209
+ MenuData& self = get_data(menu);
210
+
211
+ if (!self.nssubmenu)
212
+ invalid_state_error(__FILE__, __LINE__);
213
+
214
+ if (view)
215
+ {
216
+ Window* win = view->window();
217
+ if (!win)
218
+ invalid_state_error(__FILE__, __LINE__);
219
+
220
+ NSWindow* nswin = Window_get_data(win).native;
221
+ if (!nswin)
222
+ invalid_state_error(__FILE__, __LINE__);
223
+
224
+ NSView* nsview = nswin.contentView;
225
+ if (!nsview)
226
+ invalid_state_error(__FILE__, __LINE__);
227
+
228
+ Point win_pos = view->to_window(Point(x, y));
229
+ CGFloat win_h = nsview.frame.size.height;
230
+ [self.nssubmenu popUpMenuPositioningItem: nil
231
+ atLocation: NSMakePoint(win_pos.x, win_h - win_pos.y)
232
+ inView: nsview];
233
+ }
234
+ else
235
+ {
236
+ [self.nssubmenu popUpMenuPositioningItem: nil
237
+ atLocation: NSMakePoint(x, primary_screen_height() - y)
238
+ inView: nil];
239
+ }
240
+ }
241
+
242
+ void
243
+ Menu_child_added (Menu* parent, Menu* child, int index)
244
+ {
245
+ auto& p = get_data(parent);
246
+ auto& c = get_data(child);
247
+
248
+ [p.get_nssubmenu(parent) insertItem: c.nsitem atIndex: index];
249
+ Menu_update(child);
250
+ }
251
+
252
+ void
253
+ Menu_child_removed (Menu* parent, Menu* child)
254
+ {
255
+ auto& p = get_data(parent);
256
+ auto& c = get_data(child);
257
+
258
+ if (p.nssubmenu && c.nsitem.menu == p.nssubmenu)
259
+ [p.nssubmenu removeItem: c.nsitem];
260
+ }
261
+
262
+ NSMenu*
263
+ Menu_get_nssubmenu (Menu* menu)
264
+ {
265
+ return get_data(menu).get_nssubmenu(menu);
266
+ }
267
+
268
+ void
269
+ Menu_set_native_action (Menu* menu, SEL action)
270
+ {
271
+ MenuData& self = get_data(menu);
272
+
273
+ self.native_action = action;
274
+ Menu_update(menu);
275
+ }
276
+
277
+ void
278
+ Menu_apply_to_main_menu (Menu* menu)
279
+ {
280
+ if (!menu && app())
281
+ menu = app()->menu();
282
+
283
+ if (!menu) return;
284
+
285
+ [NSApp setMainMenu: get_data(menu).get_nssubmenu(menu)];
286
+ }
287
+
288
+
289
+ }// Reflex
290
+
291
+
292
+ @implementation ReflexMenuTarget
293
+
294
+ - (void) handleMenuItem: (NSMenuItem*) nsitem
295
+ {
296
+ Reflex::Menu* menu = get_owner(nsitem);
297
+ if (!menu) return;
298
+
299
+ Reflex::Event e;
300
+ menu->on_click(&e);
301
+ }
302
+
303
+ - (void) menuWillOpen: (NSMenu*) nsmenu
304
+ {
305
+ Reflex::Menu_validate_items(nsmenu);
306
+
307
+ Reflex::Menu* menu = get_owner(nsmenu);
308
+ if (!menu) return;
309
+
310
+ Reflex::Event e;
311
+ menu->on_open_submenu(&e);
312
+
313
+ for (NSMenuItem* nsitem in nsmenu.itemArray)
314
+ {
315
+ Reflex::Menu* child = get_owner(nsitem);
316
+ if (!child) continue;
317
+
318
+ Reflex::Event ce;
319
+ child->on_show(&ce);
320
+ }
321
+ }
322
+
323
+ - (void) menuDidClose: (NSMenu*) nsmenu
324
+ {
325
+ Reflex::Menu* menu = get_owner(nsmenu);
326
+ if (!menu) return;
327
+
328
+ for (NSMenuItem* nsitem in nsmenu.itemArray)
329
+ {
330
+ Reflex::Menu* child = get_owner(nsitem);
331
+ if (!child) continue;
332
+
333
+ Reflex::Event ce;
334
+ child->on_hide(&ce);
335
+ }
336
+
337
+ Reflex::Event e;
338
+ menu->on_close_submenu(&e);
339
+ }
340
+
341
+ - (BOOL) menuHasKeyEquivalent: (NSMenu*) nsmenu
342
+ forEvent: (NSEvent*) event
343
+ target: (id*) target
344
+ action: (SEL*) action
345
+ {
346
+ // answer key equivalent matching ourselves: AppKit's own scanning of
347
+ // delegate-backed menus caches stale results across setMainMenu calls,
348
+ // leaving every shortcut dead until the menu bar is clicked once
349
+ static const NSEventModifierFlags MODIFIER_MASK =
350
+ NSEventModifierFlagCommand |
351
+ NSEventModifierFlagShift |
352
+ NSEventModifierFlagOption |
353
+ NSEventModifierFlagControl;
354
+
355
+ NSEventModifierFlags mods = event.modifierFlags & MODIFIER_MASK;
356
+ NSString* chars = event.charactersIgnoringModifiers;
357
+
358
+ for (NSMenuItem* nsitem in nsmenu.itemArray)
359
+ {
360
+ if (nsitem.hasSubmenu || !nsitem.enabled) continue;
361
+ if (nsitem.keyEquivalent.length == 0) continue;
362
+ if (nsitem.keyEquivalentModifierMask != mods) continue;
363
+ if (![nsitem.keyEquivalent isEqualToString: chars]) continue;
364
+
365
+ *target = nsitem.target;
366
+ *action = nsitem.action;
367
+ return YES;
368
+ }
369
+ return NO;
370
+ }
371
+
372
+ @end// ReflexMenuTarget
@@ -10,6 +10,7 @@
10
10
  #include "../pointer.h"
11
11
  #include "event.h"
12
12
  #include "window.h"
13
+ #include "menu.h"
13
14
  #import "opengl_view.h"
14
15
 
15
16
 
@@ -261,6 +262,14 @@ move_to_main_screen_origin (NativeWindow* window)
261
262
  [self setDelegate: nil];
262
263
  }
263
264
 
265
+ - (void) windowDidBecomeMain: (NSNotification*) notification
266
+ {
267
+ Reflex::Window* win = self.window;
268
+ if (!win) return;
269
+
270
+ Menu_apply_to_main_menu(win->menu());
271
+ }
272
+
264
273
  - (void) windowWillMove: (NSNotification*) notification
265
274
  {
266
275
  Reflex::Window* win = self.window;
@@ -444,6 +453,24 @@ move_to_main_screen_origin (NativeWindow* window)
444
453
  Window_call_pointer_event(win, &e);
445
454
  }
446
455
 
456
+ - (void) mouseEntered: (NSEvent*) event
457
+ {
458
+ Reflex::Window* win = self.window;
459
+ if (!win) return;
460
+
461
+ Reflex::NativePointerEvent e(event, view, Reflex::Pointer::ENTER);
462
+ Window_call_pointer_event(win, &e);
463
+ }
464
+
465
+ - (void) mouseExited: (NSEvent*) event
466
+ {
467
+ Reflex::Window* win = self.window;
468
+ if (!win) return;
469
+
470
+ Reflex::NativePointerEvent e(event, view, Reflex::Pointer::LEAVE);
471
+ Window_call_pointer_event(win, &e);
472
+ }
473
+
447
474
  - (void) scrollWheel: (NSEvent*) event
448
475
  {
449
476
  Reflex::Window* win = self.window;
@@ -15,6 +15,7 @@
15
15
 
16
16
  {
17
17
  bool setup_context_done;
18
+ NSTrackingArea* tracking_area;
18
19
  }
19
20
 
20
21
  - (id) initWithFrame: (NSRect) frame
@@ -30,6 +31,7 @@
30
31
  if (!self) return nil;
31
32
 
32
33
  setup_context_done = false;
34
+ tracking_area = nil;
33
35
 
34
36
  return self;
35
37
  }
@@ -100,6 +102,39 @@
100
102
  #endif
101
103
  }
102
104
 
105
+ - (void) updateTrackingAreas
106
+ {
107
+ [super updateTrackingAreas];
108
+
109
+ if (tracking_area)
110
+ {
111
+ [self removeTrackingArea: tracking_area];
112
+ [tracking_area release];
113
+ }
114
+
115
+ // to track pointer enter/leave event of the window bounds
116
+ tracking_area = [[NSTrackingArea alloc]
117
+ initWithRect: NSZeroRect
118
+ options:
119
+ NSTrackingMouseEnteredAndExited |
120
+ NSTrackingActiveAlways |
121
+ NSTrackingInVisibleRect
122
+ owner: self
123
+ userInfo: nil];
124
+ [self addTrackingArea: tracking_area];
125
+ }
126
+
127
+ - (void) dealloc
128
+ {
129
+ if (tracking_area)
130
+ {
131
+ [self removeTrackingArea: tracking_area];
132
+ [tracking_area release];
133
+ tracking_area = nil;
134
+ }
135
+ [super dealloc];
136
+ }
137
+
103
138
  - (void) insertText: (id) str
104
139
  {
105
140
  //NSLog(@"interText: %@", str);
@@ -211,4 +246,20 @@
211
246
  [win mouseMoved: event];
212
247
  }
213
248
 
249
+ - (void) mouseEntered: (NSEvent*) event
250
+ {
251
+ NativeWindow* win = (NativeWindow*) [self window];
252
+ if (!win) return;
253
+
254
+ [win mouseEntered: event];
255
+ }
256
+
257
+ - (void) mouseExited: (NSEvent*) event
258
+ {
259
+ NativeWindow* win = (NativeWindow*) [self window];
260
+ if (!win) return;
261
+
262
+ [win mouseExited: event];
263
+ }
264
+
214
265
  @end// OpenGLView
data/src/osx/window.mm CHANGED
@@ -4,6 +4,7 @@
4
4
 
5
5
  #import <Cocoa/Cocoa.h>
6
6
  #include "reflex/exception.h"
7
+ #include "menu.h"
7
8
  #include "screen.h"
8
9
  #import "native_window.h"
9
10
 
@@ -143,6 +144,16 @@ namespace Reflex
143
144
  return Bounds(f.origin.x, f.origin.y, f.size.width, f.size.height);
144
145
  }
145
146
 
147
+ void
148
+ Window_set_menu (Window* window, Menu* menu)
149
+ {
150
+ NativeWindow* native = get_native(window);
151
+ if (!native) return;
152
+
153
+ if (native.isMainWindow)
154
+ Menu_apply_to_main_menu(menu);
155
+ }
156
+
146
157
  Screen
147
158
  Window_get_screen (const Window& window)
148
159
  {