d5f74e42 |
1 | // Copyright (c) 2013-2014 OPEN CASCADE SAS |
4fe56619 |
2 | // |
973c2be1 |
3 | // This file is part of Open CASCADE Technology software library. |
4fe56619 |
4 | // |
d5f74e42 |
5 | // This library is free software; you can redistribute it and/or modify it under |
6 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
7 | // by the Free Software Foundation, with special exception defined in the file |
8 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
9 | // distribution for complete text of the license and disclaimer of any warranty. |
4fe56619 |
10 | // |
973c2be1 |
11 | // Alternatively, this file may be used under the terms of Open CASCADE |
12 | // commercial license or contractual agreement. |
4fe56619 |
13 | |
14 | #if defined(__APPLE__) && !defined(MACOSX_USE_GLX) |
15 | |
16 | #import <Cocoa/Cocoa.h> |
17 | |
18 | #include <Cocoa_Window.hxx> |
19 | #include <ViewerTest.hxx> |
49582f9d |
20 | #include <ViewerTest_EventManager.hxx> |
4fe56619 |
21 | #include <V3d_View.hxx> |
22 | #include <V3d_Viewer.hxx> |
23 | #include <AIS_InteractiveContext.hxx> |
18d715bd |
24 | #include <TCollection_AsciiString.hxx> |
25 | #include <NCollection_DoubleMap.hxx> |
4fe56619 |
26 | |
e2b4dea2 |
27 | #if !defined(MAC_OS_X_VERSION_10_12) || (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12) |
28 | // replacements for macOS versions before 10.12 |
c64135f7 |
29 | #define NSEventModifierFlagControl NSControlKeyMask |
30 | #define NSEventModifierFlagShift NSShiftKeyMask |
31 | #define NSEventModifierFlagOption NSAlternateKeyMask |
32 | #define NSEventModifierFlagCommand NSCommandKeyMask |
33 | #define NSEventModifierFlagFunction NSFunctionKeyMask |
e2b4dea2 |
34 | #endif |
35 | |
4fe56619 |
36 | //! Custom Cocoa view to handle events |
37 | @interface ViewerTest_CocoaEventManagerView : NSView |
38 | @end |
39 | |
18d715bd |
40 | //! Custom Cocoa window delegate to handle window events |
41 | @interface Cocoa_WindowController : NSObject <NSWindowDelegate> |
42 | @end |
43 | |
e084dbbc |
44 | extern void ActivateView (const TCollection_AsciiString& theViewName, |
45 | Standard_Boolean theToUpdate = Standard_True); |
4fe56619 |
46 | |
18d715bd |
47 | extern NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> ViewerTest_myViews; |
18d715bd |
48 | |
49 | // ======================================================================= |
50 | // function : GetCocoaScreenResolution |
51 | // purpose : |
52 | // ======================================================================= |
53 | void GetCocoaScreenResolution (Standard_Integer& theWidth, Standard_Integer& theHeight) |
54 | { |
55 | NSRect aRect = [[NSScreen mainScreen] visibleFrame]; |
56 | theWidth = (Standard_Integer )aRect.size.width; |
57 | theHeight = (Standard_Integer )aRect.size.height; |
58 | } |
59 | |
60 | // ======================================================================= |
61 | // function : FindViewId |
62 | // purpose : |
63 | // ======================================================================= |
64 | TCollection_AsciiString FindViewId (const NSWindow* theWindow) |
65 | { |
66 | TCollection_AsciiString aViewId = ""; |
67 | NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter(ViewerTest_myViews); |
68 | for (;anIter.More();anIter.Next()) |
69 | { |
70 | NSView* aView = Handle(Cocoa_Window)::DownCast |
71 | (anIter.Value()->Window())->HView(); |
72 | NSWindow* aWindow = [aView window]; |
73 | if (aWindow == theWindow) |
74 | { |
75 | aViewId = anIter.Key1(); |
76 | return aViewId; |
77 | } |
78 | } |
79 | return aViewId; |
80 | } |
81 | |
82 | @implementation Cocoa_WindowController |
83 | |
84 | - (void )windowWillClose: (NSNotification* )theNotification |
85 | { |
5ef127d0 |
86 | (void )theNotification; |
18d715bd |
87 | TCollection_AsciiString aViewId = ""; |
88 | if (ViewerTest_myViews.IsBound2 (ViewerTest::CurrentView())) |
89 | { |
90 | aViewId = ViewerTest_myViews.Find2 (ViewerTest::CurrentView()); |
91 | } |
92 | ViewerTest::RemoveView (aViewId); |
93 | } |
94 | |
95 | - (void )windowDidBecomeKey: (NSNotification* )theNotification |
96 | { |
97 | NSWindow *aWindow = [theNotification object]; |
98 | ActivateView (FindViewId (aWindow)); |
99 | } |
100 | |
101 | @end |
102 | |
4fe56619 |
103 | // ======================================================================= |
104 | // function : ViewerMainLoop |
105 | // purpose : |
106 | // ======================================================================= |
107 | int ViewerMainLoop (Standard_Integer, const char** ) |
108 | { |
109 | // unused |
110 | return 0; |
111 | } |
112 | |
113 | // ======================================================================= |
114 | // function : ViewerTest_SetCocoaEventManagerView |
115 | // purpose : |
116 | // ======================================================================= |
117 | void ViewerTest_SetCocoaEventManagerView (const Handle(Cocoa_Window)& theWindow) |
118 | { |
119 | if (theWindow.IsNull()) |
120 | { |
121 | return; |
122 | } |
123 | |
124 | NSWindow* aWin = [theWindow->HView() window]; |
125 | NSRect aBounds = [[aWin contentView] bounds]; |
126 | |
127 | ViewerTest_CocoaEventManagerView* aView = [[ViewerTest_CocoaEventManagerView alloc] initWithFrame: aBounds]; |
128 | |
129 | // replace content view in the window |
130 | theWindow->SetHView (aView); |
131 | |
18d715bd |
132 | // set delegate for window |
133 | Cocoa_WindowController* aWindowController = [[[Cocoa_WindowController alloc] init] autorelease]; |
134 | [aWin setDelegate: aWindowController]; |
135 | |
4fe56619 |
136 | // make view as first responder in winow to capture all useful events |
137 | [aWin makeFirstResponder: aView]; |
138 | [aWin setAcceptsMouseMovedEvents: YES]; |
139 | |
140 | // should be retained by parent NSWindow |
141 | [aView release]; |
142 | } |
143 | |
49582f9d |
144 | //! Retrieve cursor position |
145 | static Graphic3d_Vec2i getMouseCoords (NSView* theView, |
146 | NSEvent* theEvent) |
4fe56619 |
147 | { |
148 | NSPoint aMouseLoc = [theView convertPoint: [theEvent locationInWindow] fromView: nil]; |
149 | NSRect aBounds = [theView bounds]; |
49582f9d |
150 | return Graphic3d_Vec2i (Standard_Integer(aMouseLoc.x), |
151 | Standard_Integer(aBounds.size.height - aMouseLoc.y)); |
152 | } |
4fe56619 |
153 | |
49582f9d |
154 | //! Convert key flags from mouse event. |
155 | static Aspect_VKeyFlags getMouseKeyFlags (NSEvent* theEvent) |
156 | { |
157 | Aspect_VKeyFlags aFlags = Aspect_VKeyFlags_NONE; |
158 | if (([theEvent modifierFlags] & NSEventModifierFlagShift) != 0) |
159 | { |
160 | aFlags |= Aspect_VKeyFlags_SHIFT; |
161 | } |
162 | if (([theEvent modifierFlags] & NSEventModifierFlagControl) != 0) |
163 | { |
164 | aFlags |= Aspect_VKeyFlags_CTRL; |
165 | } |
166 | if (([theEvent modifierFlags] & NSEventModifierFlagOption) != 0) |
167 | { |
168 | aFlags |= Aspect_VKeyFlags_ALT; |
169 | } |
170 | if (([theEvent modifierFlags] & NSEventModifierFlagFunction) != 0) |
171 | { |
172 | //aFlags |= Aspect_VKeyFlags_FUNC; |
173 | } |
174 | if (([theEvent modifierFlags] & NSEventModifierFlagCommand) != 0) |
175 | { |
176 | //aFlags |= Aspect_VKeyFlags_CMD; |
177 | } |
178 | return aFlags; |
4fe56619 |
179 | } |
180 | |
181 | @implementation ViewerTest_CocoaEventManagerView |
182 | |
183 | // ======================================================================= |
184 | // function : setFrameSize |
185 | // purpose : |
186 | // ======================================================================= |
187 | - (void )setFrameSize: (NSSize )theNewSize |
188 | { |
189 | [super setFrameSize: theNewSize]; |
49582f9d |
190 | ViewerTest::CurrentEventManager()->ProcessConfigure(); |
4fe56619 |
191 | } |
192 | |
193 | // ======================================================================= |
194 | // function : drawRect |
195 | // purpose : |
196 | // ======================================================================= |
197 | - (void )drawRect: (NSRect )theDirtyRect |
198 | { |
5ef127d0 |
199 | (void )theDirtyRect; |
49582f9d |
200 | if (!ViewerTest::CurrentEventManager().IsNull()) |
201 | { |
202 | ViewerTest::CurrentEventManager()->ProcessExpose(); |
203 | } |
4fe56619 |
204 | } |
205 | |
206 | // ======================================================================= |
207 | // function : mouseMoved |
208 | // purpose : |
209 | // ======================================================================= |
210 | - (void )mouseMoved: (NSEvent* )theEvent |
211 | { |
49582f9d |
212 | const Graphic3d_Vec2i aPos = getMouseCoords (self, theEvent); |
213 | const Aspect_VKeyFlags aFlags = getMouseKeyFlags (theEvent); |
214 | const Aspect_VKeyMouse aButtons = ViewerTest::CurrentEventManager()->PressedMouseButtons(); |
215 | ViewerTest::CurrentEventManager()->UpdateMousePosition (aPos, aButtons, aFlags, false); |
216 | ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true); |
4fe56619 |
217 | } |
218 | |
219 | // ======================================================================= |
220 | // function : acceptsFirstResponder |
221 | // purpose : |
222 | // ======================================================================= |
223 | - (BOOL )acceptsFirstResponder |
224 | { |
225 | return YES; |
226 | } |
227 | |
228 | // ======================================================================= |
229 | // function : mouseDown |
230 | // purpose : |
231 | // ======================================================================= |
232 | - (void )mouseDown: (NSEvent* )theEvent |
233 | { |
49582f9d |
234 | const Graphic3d_Vec2i aPos = getMouseCoords (self, theEvent); |
235 | const Aspect_VKeyFlags aFlags = getMouseKeyFlags (theEvent); |
236 | ViewerTest::CurrentEventManager()->PressMouseButton (aPos, Aspect_VKeyMouse_LeftButton, aFlags, false); |
237 | ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true); |
4fe56619 |
238 | } |
239 | |
240 | // ======================================================================= |
241 | // function : mouseUp |
242 | // purpose : |
243 | // ======================================================================= |
244 | - (void )mouseUp: (NSEvent* )theEvent |
245 | { |
49582f9d |
246 | const Graphic3d_Vec2i aPos = getMouseCoords (self, theEvent); |
247 | const Aspect_VKeyFlags aFlags = getMouseKeyFlags (theEvent); |
248 | ViewerTest::CurrentEventManager()->ReleaseMouseButton (aPos, Aspect_VKeyMouse_LeftButton, aFlags, false); |
249 | ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true); |
4fe56619 |
250 | } |
251 | |
4fe56619 |
252 | // ======================================================================= |
253 | // function : mouseDragged |
254 | // purpose : |
255 | // ======================================================================= |
256 | - (void )mouseDragged: (NSEvent* )theEvent |
257 | { |
49582f9d |
258 | const Graphic3d_Vec2i aPos = getMouseCoords (self, theEvent); |
259 | const Aspect_VKeyFlags aFlags = getMouseKeyFlags (theEvent); |
260 | const Aspect_VKeyMouse aButtons = ViewerTest::CurrentEventManager()->PressedMouseButtons(); |
261 | ViewerTest::CurrentEventManager()->UpdateMousePosition (aPos, aButtons, aFlags, false); |
262 | ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true); |
4fe56619 |
263 | } |
264 | |
265 | // ======================================================================= |
266 | // function : rightMouseDown |
267 | // purpose : |
268 | // ======================================================================= |
269 | - (void )rightMouseDown: (NSEvent* )theEvent |
270 | { |
49582f9d |
271 | const Graphic3d_Vec2i aPos = getMouseCoords (self, theEvent); |
272 | const Aspect_VKeyFlags aFlags = getMouseKeyFlags (theEvent); |
273 | ViewerTest::CurrentEventManager()->PressMouseButton (aPos, Aspect_VKeyMouse_RightButton, aFlags, false); |
274 | ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true); |
4fe56619 |
275 | } |
276 | |
277 | // ======================================================================= |
278 | // function : rightMouseUp |
279 | // purpose : |
280 | // ======================================================================= |
281 | - (void )rightMouseUp: (NSEvent* )theEvent |
282 | { |
49582f9d |
283 | const Graphic3d_Vec2i aPos = getMouseCoords (self, theEvent); |
284 | const Aspect_VKeyFlags aFlags = getMouseKeyFlags (theEvent); |
285 | ViewerTest::CurrentEventManager()->ReleaseMouseButton (aPos, Aspect_VKeyMouse_RightButton, aFlags, false); |
286 | ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true); |
4fe56619 |
287 | } |
288 | |
289 | // ======================================================================= |
290 | // function : rightMouseDragged |
291 | // purpose : |
292 | // ======================================================================= |
293 | - (void )rightMouseDragged: (NSEvent* )theEvent |
294 | { |
49582f9d |
295 | const Graphic3d_Vec2i aPos = getMouseCoords (self, theEvent); |
296 | const Aspect_VKeyFlags aFlags = getMouseKeyFlags (theEvent); |
297 | const Aspect_VKeyMouse aButtons = ViewerTest::CurrentEventManager()->PressedMouseButtons(); |
298 | ViewerTest::CurrentEventManager()->UpdateMousePosition (aPos, aButtons, aFlags, false); |
299 | ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true); |
4fe56619 |
300 | } |
301 | |
302 | // ======================================================================= |
303 | // function : scrollWheel |
304 | // purpose : |
305 | // ======================================================================= |
306 | - (void )scrollWheel: (NSEvent* )theEvent |
307 | { |
49582f9d |
308 | const Graphic3d_Vec2i aPos = getMouseCoords (self, theEvent); |
309 | const Aspect_VKeyFlags aFlags = getMouseKeyFlags (theEvent); |
310 | |
311 | const Standard_Real aDelta = [theEvent deltaY]; |
4fe56619 |
312 | if (Abs (aDelta) < 0.001) |
313 | { |
314 | // a lot of values near zero can be generated by touchpad |
315 | return; |
316 | } |
317 | |
49582f9d |
318 | ViewerTest::CurrentEventManager()->UpdateMouseScroll (Aspect_ScrollDelta (aPos, aDelta, aFlags)); |
319 | ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true); |
4fe56619 |
320 | } |
321 | |
322 | // ======================================================================= |
323 | // function : keyDown |
324 | // purpose : |
325 | // ======================================================================= |
326 | - (void )keyDown: (NSEvent* )theEvent |
327 | { |
49582f9d |
328 | unsigned int aKeyCode = [theEvent keyCode]; |
329 | const Aspect_VKey aVKey = Cocoa_Window::VirtualKeyFromNative (aKeyCode); |
330 | if (aVKey != Aspect_VKey_UNKNOWN) |
4fe56619 |
331 | { |
49582f9d |
332 | const double aTimeStamp = [theEvent timestamp]; |
333 | ViewerTest::CurrentEventManager()->KeyDown (aVKey, aTimeStamp); |
334 | ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true); |
4fe56619 |
335 | } |
336 | |
49582f9d |
337 | //NSString* aStringNs = [theEvent characters]; |
338 | //if (aStringNs != NULL && [aStringNs length] != 1) |
339 | //{ |
340 | // const Standard_CString aString = [aStringNs UTF8String]; |
341 | //} |
342 | } |
343 | |
344 | // ======================================================================= |
345 | // function : keyUp |
346 | // purpose : |
347 | // ======================================================================= |
348 | - (void )keyUp: (NSEvent* )theEvent |
349 | { |
350 | unsigned int aKeyCode = [theEvent keyCode]; |
351 | const Aspect_VKey aVKey = Cocoa_Window::VirtualKeyFromNative (aKeyCode); |
352 | if (aVKey != Aspect_VKey_UNKNOWN) |
353 | { |
354 | const double aTimeStamp = [theEvent timestamp]; |
355 | ViewerTest::CurrentEventManager()->KeyUp (aVKey, aTimeStamp); |
356 | ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true); |
357 | } |
4fe56619 |
358 | } |
359 | |
360 | @end |
361 | |
362 | #endif |