1 // This file is part of VSTGUI. It is subject to the license terms
2 // in the LICENSE file found in the top-level directory of this
3 // distribution and at http://github.com/steinbergmedia/vstgui/LICENSE
4
5 #include "hiviewframe.h"
6
7 #if MAC_CARBON
8
9 #include "../../iplatformtextedit.h"
10 #include "../../iplatformbitmap.h"
11 #include "../../iplatformopenglview.h"
12 #include "../../iplatformviewlayer.h"
13 #include "../../../cbitmap.h"
14 #include "../../../cdrawcontext.h"
15 #include "../../../cdropsource.h"
16 #include "hiviewtextedit.h"
17 #include "hiviewoptionmenu.h"
18 #include "../cgdrawcontext.h"
19 #include "../cgbitmap.h"
20 #include "../macglobals.h"
21 #include "../quartzgraphicspath.h"
22 #include "../macclipboard.h"
23
24 #pragma clang diagnostic push
25 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
26
27 namespace VSTGUI {
28
29 #if !MAC_COCOA
30 //-----------------------------------------------------------------------------
createPlatformFrame(IPlatformFrameCallback * frame,const CRect & size,void * parent,PlatformType parentType,IPlatformFrameConfig * config)31 IPlatformFrame* IPlatformFrame::createPlatformFrame (IPlatformFrameCallback* frame, const CRect& size, void* parent, PlatformType parentType, IPlatformFrameConfig* config)
32 {
33 return new HIViewFrame (frame, size, (WindowRef)parent);
34 }
35
36 #endif
37
38 SInt32 pSystemVersion;
39
40 //-----------------------------------------------------------------------------
isWindowComposited(WindowRef window)41 bool isWindowComposited (WindowRef window)
42 {
43 WindowAttributes attr;
44 GetWindowAttributes (window, &attr);
45 if (attr & kWindowCompositingAttribute)
46 return true;
47 return false;
48 }
49
50 static SharedPointer<IDataPackage> gDragContainer;
51
52 //-----------------------------------------------------------------------------
GetMacDragMouse(HIViewFrame * frame,DragRef drag)53 static CPoint GetMacDragMouse (HIViewFrame* frame, DragRef drag)
54 {
55 HIViewRef view = frame->getPlatformControl ();
56 CPoint where;
57 Point r;
58 if (GetDragMouse (drag, NULL, &r) == noErr)
59 {
60 HIPoint location;
61 location = CGPointMake ((CGFloat)r.h, (CGFloat)r.v);
62 HIPointConvert (&location, kHICoordSpaceScreenPixel, NULL, kHICoordSpaceView, view);
63 where.x = (CCoord)location.x;
64 where.y = (CCoord)location.y;
65 }
66 return where;
67 }
68
69 static bool addViewToContentView = true;
70 //-----------------------------------------------------------------------------
setAddToContentView(bool addToContentView)71 void HIViewFrame::setAddToContentView (bool addToContentView)
72 {
73 addViewToContentView = addToContentView;
74 }
75
76 //-----------------------------------------------------------------------------
HIViewFrame(IPlatformFrameCallback * frame,const CRect & size,WindowRef parent)77 HIViewFrame::HIViewFrame (IPlatformFrameCallback* frame, const CRect& size, WindowRef parent)
78 : IPlatformFrame (frame)
79 , window (parent)
80 , controlRef (0)
81 , hasFocus (false)
82 , isInMouseTracking (false)
83 , mouseEventHandler (0)
84 {
85 Gestalt (gestaltSystemVersion, &pSystemVersion);
86
87 Rect r = {(short)size.top, (short)size.left, (short)size.bottom, (short)size.right};
88 UInt32 features = kControlSupportsDragAndDrop
89 | kControlSupportsFocus
90 | kControlHandlesTracking
91 | kControlSupportsEmbedding
92 | kHIViewIsOpaque
93 | kHIViewFeatureDoesNotUseSpecialParts;
94 OSStatus status = CreateUserPaneControl (0, &r, features, &controlRef);
95 if (status != noErr)
96 {
97 fprintf (stderr, "Could not create Control : %d\n", (int32_t)status);
98 return;
99 }
100 const EventTypeSpec controlEventTypes[] = {
101 { kEventClassControl, kEventControlDraw},
102 { kEventClassControl, kEventControlHitTest},
103 { kEventClassControl, kEventControlClick},
104 //{kEventClassControl, kEventControlTrack},
105 //{kEventClassControl, kEventControlContextualMenuClick},
106 { kEventClassKeyboard, kEventRawKeyDown},
107 { kEventClassKeyboard, kEventRawKeyRepeat},
108 { kEventClassMouse, kEventMouseWheelMoved},
109 { kEventClassControl, kEventControlDragEnter},
110 { kEventClassControl, kEventControlDragWithin},
111 { kEventClassControl, kEventControlDragLeave},
112 { kEventClassControl, kEventControlDragReceive},
113 { kEventClassControl, kEventControlInitialize},
114 { kEventClassControl, kEventControlGetClickActivation},
115 { kEventClassControl, kEventControlGetOptimalBounds},
116 { kEventClassScrollable,kEventScrollableGetInfo},
117 { kEventClassScrollable,kEventScrollableScrollTo},
118 { kEventClassControl, kEventControlSetFocusPart},
119 { kEventClassControl, kEventControlGetFocusPart},
120 { kEventClassControl, kEventControlTrackingAreaExited},
121 };
122 InstallControlEventHandler (controlRef, carbonEventHandler, GetEventTypeCount (controlEventTypes), controlEventTypes, this, NULL);
123
124 const EventTypeSpec keyWorkaroundEvents[] = {
125 { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent },
126 { kEventClassWindow, kEventWindowFocusAcquired },
127 { kEventClassWindow, kEventWindowFocusRelinquish }
128 };
129 InstallWindowEventHandler (window, carbonEventHandler, GetEventTypeCount (keyWorkaroundEvents), keyWorkaroundEvents, this, &keyboardEventHandler);
130 const EventTypeSpec mouseEvents[] = {
131 { kEventClassMouse, kEventMouseDown },
132 { kEventClassMouse, kEventMouseUp },
133 { kEventClassMouse, kEventMouseMoved },
134 { kEventClassMouse, kEventMouseDragged },
135 };
136 InstallWindowEventHandler (window, carbonMouseEventHandler, GetEventTypeCount (mouseEvents), mouseEvents, this, &mouseEventHandler);
137
138 SetControlDragTrackingEnabled (controlRef, true);
139 SetAutomaticControlDragTrackingEnabledForWindow (window, true);
140
141 if (addViewToContentView)
142 {
143 if (isWindowComposited (window))
144 {
145 HIViewRef contentView;
146 HIViewRef rootView = HIViewGetRoot (window);
147 if (HIViewFindByID (rootView, kHIViewWindowContentID, &contentView) != noErr)
148 contentView = rootView;
149 HIViewAddSubview (contentView, controlRef);
150 }
151 else
152 {
153 ControlRef rootControl;
154 GetRootControl (window, &rootControl);
155 if (rootControl == NULL)
156 CreateRootControl (window, &rootControl);
157 EmbedControl(controlRef, rootControl);
158 }
159 }
160
161 HIViewTrackingAreaRef trackingAreaRef; // will automatically removed if view is destroyed
162 HIViewNewTrackingArea (controlRef, 0, 0, &trackingAreaRef);
163
164 #if 0
165 // TODO: currently this is not supported, do we need to ?
166 size.offset (-size.left, -size.top);
167 mouseableArea.offset (-size.left, -size.top);
168 #endif
169 }
170
171 //-----------------------------------------------------------------------------
~HIViewFrame()172 HIViewFrame::~HIViewFrame () noexcept
173 {
174 if (keyboardEventHandler)
175 RemoveEventHandler (keyboardEventHandler);
176 if (mouseEventHandler)
177 RemoveEventHandler (mouseEventHandler);
178 if (controlRef)
179 {
180 if (HIViewRemoveFromSuperview (controlRef) == noErr && isWindowComposited (window))
181 CFRelease (controlRef);
182 }
183 }
184
185 // IPlatformFrame
186 //-----------------------------------------------------------------------------
getGlobalPosition(CPoint & pos) const187 bool HIViewFrame::getGlobalPosition (CPoint& pos) const
188 {
189 Rect bounds;
190 GetWindowBounds (window, kWindowContentRgn, &bounds);
191
192 CCoord x = bounds.left;
193 CCoord y = bounds.top;
194
195 if (isWindowComposited (window))
196 {
197 HIPoint hip = { 0.f, 0.f };
198 HIViewRef contentView;
199 HIViewFindByID (HIViewGetRoot (window), kHIViewWindowContentID, &contentView);
200 if (contentView)
201 HIViewConvertPoint (&hip, controlRef, contentView);
202 x += (CCoord)hip.x;
203 y += (CCoord)hip.y;
204 }
205 else
206 {
207 HIRect hirect;
208 HIViewGetFrame (controlRef, &hirect);
209 x += (CCoord)hirect.origin.x;
210 y += (CCoord)hirect.origin.y;
211 }
212 x -= hiScrollOffset.x;
213 y -= hiScrollOffset.y;
214
215 pos.x = x;
216 pos.y = y;
217 return true;
218 }
219
220 //-----------------------------------------------------------------------------
setSize(const CRect & newSize)221 bool HIViewFrame::setSize (const CRect& newSize)
222 {
223 HIRect frameRect;
224 HIViewGetFrame (controlRef, &frameRect);
225
226 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_6
227 // keep old values
228 CCoord oldWidth = frameRect.size.width;
229 CCoord oldHeight = frameRect.size.height;
230
231 if (window)
232 {
233 if (!isWindowComposited (window))
234 {
235 Rect bounds;
236 GetPortBounds (GetWindowPort (window), &bounds);
237 SizeWindow (window, (short)((bounds.right - bounds.left) - oldWidth + newSize.getWidth ()),
238 (short)((bounds.bottom - bounds.top) - oldHeight + newSize.getHeight ()), true);
239 }
240 }
241 #endif
242
243 if (controlRef)
244 {
245 HIRect frameRect;
246 HIViewGetFrame (controlRef, &frameRect);
247 frameRect.origin.x = static_cast<CGFloat> (newSize.left);
248 frameRect.origin.y = static_cast<CGFloat> (newSize.top);
249 frameRect.size.width = static_cast<CGFloat> (newSize.getWidth ());
250 frameRect.size.height = static_cast<CGFloat> (newSize.getHeight ());
251 HIViewSetFrame (controlRef, &frameRect);
252 }
253 return true;
254 }
255
256 //-----------------------------------------------------------------------------
getSize(CRect & size) const257 bool HIViewFrame::getSize (CRect& size) const
258 {
259 HIRect hiRect;
260 if (HIViewGetFrame (controlRef, &hiRect) == noErr)
261 {
262 size.left = (CCoord)hiRect.origin.x;
263 size.top = (CCoord)hiRect.origin.y;
264 size.setWidth ((CCoord)hiRect.size.width);
265 size.setHeight ((CCoord)hiRect.size.height);
266 return true;
267 }
268 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_6
269 Rect bounds;
270 GetPortBounds (GetWindowPort (window), &bounds);
271
272 size.left = bounds.left;
273 size.top = bounds.top;
274 size.right = bounds.right;
275 size.bottom = bounds.bottom;
276 return true;
277 #else
278 return false;
279 #endif
280 }
281
282 //-----------------------------------------------------------------------------
getCurrentMousePosition(CPoint & mousePosition) const283 bool HIViewFrame::getCurrentMousePosition (CPoint& mousePosition) const
284 {
285 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_6
286 // no up-to-date API call available for this, so use old QuickDraw
287 Point p;
288 CGrafPtr savedPort;
289 Boolean portChanged = QDSwapPort (GetWindowPort (window), &savedPort);
290 GetMouse (&p);
291 if (portChanged)
292 QDSwapPort (savedPort, NULL);
293 mousePosition (p.h, p.v);
294 #endif
295
296 HIPoint location;
297 HIViewRef fromView = NULL;
298 HIViewFindByID (HIViewGetRoot (window), kHIViewWindowContentID, &fromView);
299
300 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_6
301 HIGetMousePosition (kHICoordSpaceView, fromView, &location);
302 location.x = static_cast<CGFloat> (floor (location.x + 0.5));
303 location.y = static_cast<CGFloat> (floor (location.y + 0.5));
304 #else
305 location = CGPointMake (mousePosition.x, mousePosition.y);
306 #endif
307
308 HIPointConvert (&location, kHICoordSpaceView, fromView, kHICoordSpaceView, controlRef);
309 mousePosition.x = (CCoord)location.x;
310 mousePosition.y = (CCoord)location.y;
311
312 return true;
313 }
314
315 //-----------------------------------------------------------------------------
getCurrentMouseButtons(CButtonState & buttons) const316 bool HIViewFrame::getCurrentMouseButtons (CButtonState& buttons) const
317 {
318 UInt32 state = GetCurrentButtonState ();
319 if (state == kEventMouseButtonPrimary)
320 buttons |= kLButton;
321 if (state == kEventMouseButtonSecondary)
322 buttons |= kRButton;
323 if (state == kEventMouseButtonTertiary)
324 buttons |= kMButton;
325 if (state == 4)
326 buttons |= kButton4;
327 if (state == 5)
328 buttons |= kButton5;
329
330 state = GetCurrentKeyModifiers ();
331 if (state & cmdKey)
332 buttons |= kControl;
333 if (state & shiftKey)
334 buttons |= kShift;
335 if (state & optionKey)
336 buttons |= kAlt;
337 if (state & controlKey)
338 buttons |= kApple;
339 // for the one buttons
340 if (buttons & kApple && buttons & kLButton)
341 {
342 buttons &= ~(kApple | kLButton);
343 buttons |= kRButton;
344 }
345
346 return true;
347 }
348
349 //-----------------------------------------------------------------------------
setMouseCursor(CCursorType type)350 bool HIViewFrame::setMouseCursor (CCursorType type)
351 {
352 switch (type)
353 {
354 case kCursorWait:
355 SetThemeCursor (kThemeWatchCursor);
356 break;
357 case kCursorHSize:
358 SetThemeCursor (kThemeResizeLeftRightCursor);
359 break;
360 case kCursorVSize:
361 SetThemeCursor (kThemeResizeUpDownCursor);
362 break;
363 case kCursorNESWSize:
364 SetThemeCursor (kThemeCrossCursor);
365 break;
366 case kCursorNWSESize:
367 SetThemeCursor (kThemeCrossCursor);
368 break;
369 case kCursorSizeAll:
370 SetThemeCursor (kThemeCrossCursor);
371 break;
372 case kCursorCopy:
373 SetThemeCursor (kThemeCopyArrowCursor);
374 break;
375 case kCursorNotAllowed:
376 SetThemeCursor (kThemeNotAllowedCursor);
377 break;
378 case kCursorHand:
379 SetThemeCursor (kThemeOpenHandCursor);
380 break;
381 default:
382 SetThemeCursor (kThemeArrowCursor);
383 break;
384 }
385 return true;
386 }
387
388 //-----------------------------------------------------------------------------
invalidRect(const CRect & rect)389 bool HIViewFrame::invalidRect (const CRect& rect)
390 {
391 if (isWindowComposited (window))
392 {
393 HIRect r = { {static_cast<CGFloat>(rect.left), static_cast<CGFloat>(rect.top)}, {static_cast<CGFloat>(rect.getWidth ()), static_cast<CGFloat>(rect.getHeight ())} };
394 HIViewSetNeedsDisplayInRect (controlRef, &r, true);
395 }
396 else
397 {
398 HIRect hiRect;
399 HIViewGetFrame (controlRef, &hiRect);
400 CRect _rect (rect);
401 // _rect.offset (size.left, size.top);
402 _rect.offset ((CCoord)hiRect.origin.x, (CCoord)hiRect.origin.y);
403 Rect r = {(short)_rect.top, (short)_rect.left, (short)_rect.bottom, (short)_rect.right};
404 InvalWindowRect (window, &r);
405 }
406 return true;
407 }
408
409 //-----------------------------------------------------------------------------
scrollRect(const CRect & _src,const CPoint & distance)410 bool HIViewFrame::scrollRect (const CRect& _src, const CPoint& distance)
411 {
412 if (isWindowComposited (window))
413 {
414 CRect src (_src);
415 if (distance.x > 0)
416 src.right += distance.x;
417 else if (distance.x < 0)
418 src.left += distance.x;
419 if (distance.y > 0)
420 src.bottom += distance.y;
421 else if (distance.y < 0)
422 src.top += distance.y;
423 CGRect cgRect = CGRectMake ((CGFloat)src.left, (CGFloat)src.top, (CGFloat)src.getWidth (), (CGFloat)src.getHeight ());
424 if (HIViewScrollRect (controlRef, &cgRect, (CGFloat)distance.x, (CGFloat)distance.y) == noErr)
425 return true;
426 }
427 return false;
428 }
429
430 //-----------------------------------------------------------------------------
showTooltip(const CRect & _rect,const char * utf8Text)431 bool HIViewFrame::showTooltip (const CRect& _rect, const char* utf8Text)
432 {
433 CRect rect (_rect);
434 CPoint p;
435 getGlobalPosition (p);
436 rect.offset (p.x, p.y);
437
438 HMHelpContentRec helpContent = {0};
439 helpContent.version = 0;
440 helpContent.absHotRect.left = static_cast<short> (rect.left);
441 helpContent.absHotRect.right = static_cast<short> (rect.right);
442 helpContent.absHotRect.top = static_cast<short> (rect.top);
443 helpContent.absHotRect.bottom = static_cast<short> (rect.bottom);
444 helpContent.tagSide = kHMDefaultSide;
445 helpContent.content[0].contentType = kHMCFStringContent;
446 helpContent.content[0].u.tagCFString = CFStringCreateWithCString (0, utf8Text, kCFStringEncodingUTF8);
447 HMDisplayTag(&helpContent);
448 CFRelease (helpContent.content[0].u.tagCFString);
449
450 return true;
451 }
452
453 //-----------------------------------------------------------------------------
hideTooltip()454 bool HIViewFrame::hideTooltip ()
455 {
456 HMHideTag ();
457 return true;
458 }
459
460 //-----------------------------------------------------------------------------
createPlatformTextEdit(IPlatformTextEditCallback * textEdit)461 SharedPointer<IPlatformTextEdit> HIViewFrame::createPlatformTextEdit (IPlatformTextEditCallback* textEdit)
462 {
463 auto control = makeOwned<HIViewTextEdit> (controlRef, textEdit);
464 if (control->getPlatformControl ())
465 return control;
466 return nullptr;
467 }
468
469 //-----------------------------------------------------------------------------
createPlatformOptionMenu()470 SharedPointer<IPlatformOptionMenu> HIViewFrame::createPlatformOptionMenu ()
471 {
472 return makeOwned<HIViewOptionMenu> ();
473 }
474
475 //-----------------------------------------------------------------------------
createOffscreenContext(CCoord width,CCoord height,double scaleFactor)476 SharedPointer<COffscreenContext> HIViewFrame::createOffscreenContext (CCoord width, CCoord height, double scaleFactor)
477 {
478 auto bitmap = makeOwned<CGBitmap> (CPoint (width * scaleFactor, height * scaleFactor));
479 bitmap->setScaleFactor (scaleFactor);
480 auto context = makeOwned<CGDrawContext> (bitmap);
481 if (context->getCGContext ())
482 return context;
483 return nullptr;
484 }
485
486 #if VSTGUI_ENABLE_DEPRECATED_METHODS
487 //------------------------------------------------------------------------------------
doDrag(IDataPackage * source,const CPoint & offset,CBitmap * dragBitmap)488 DragResult HIViewFrame::doDrag (IDataPackage* source, const CPoint& offset, CBitmap* dragBitmap)
489 {
490 DragResult result = kDragError;
491 PasteboardRef pb;
492 if (PasteboardCreate (kPasteboardUniqueName, &pb) == noErr)
493 {
494 PasteboardClear (pb);
495 for (uint32_t i = 0; i < source->getCount (); i++)
496 {
497 const void* buffer = 0;
498 IDataPackage::Type type;
499 uint32_t bufferSize = source->getData (i, buffer, type);
500 if (bufferSize > 0)
501 {
502 switch (type)
503 {
504 case IDataPackage::kFilePath:
505 {
506 CFURLRef cfUrl = CFURLCreateFromFileSystemRepresentation (0, (const UInt8*)buffer, static_cast<CFIndex> (bufferSize), false);
507 if (cfUrl)
508 {
509 CFDataRef dataRef = CFURLCreateData (0, cfUrl, kCFStringEncodingUTF8, false);
510 if (dataRef)
511 {
512 PasteboardPutItemFlavor (pb, (void*)buffer, kUTTypeFileURL, dataRef, kPasteboardFlavorNoFlags);
513 CFRelease (dataRef);
514 }
515 CFRelease (cfUrl);
516 }
517 break;
518 }
519 case IDataPackage::kText:
520 {
521 CFStringRef stringRef = CFStringCreateWithCString (0, (const char*)buffer, kCFStringEncodingUTF8);
522 if (stringRef)
523 {
524 CFDataRef dataRef = CFStringCreateExternalRepresentation (0, stringRef, kCFStringEncodingUTF8, 0);
525 if (dataRef)
526 {
527 PasteboardPutItemFlavor (pb, (void*)buffer, kUTTypeUTF8PlainText, dataRef, kPasteboardFlavorNoFlags);
528 CFRelease (dataRef);
529 }
530 CFRelease (stringRef);
531 }
532 break;
533 }
534 case IDataPackage::kBinary:
535 {
536 CFDataRef dataRef = CFDataCreate (0, (const UInt8*)buffer, static_cast<CFIndex> (bufferSize));
537 if (dataRef)
538 {
539 PasteboardPutItemFlavor (pb, (void*)buffer, kUTTypeData, dataRef, kPasteboardFlavorSenderOnly);
540 CFRelease (dataRef);
541 }
542 break;
543 }
544 case IDataPackage::kError:
545 break;
546 }
547 }
548 }
549 DragRef drag;
550 if (NewDragWithPasteboard (pb, &drag) == noErr)
551 {
552 EventRecord eventRecord;
553 EventRef eventRef = GetCurrentEvent ();
554 if (eventRef && ConvertEventRefToEventRecord (eventRef, &eventRecord))
555 {
556
557 CGBitmap* cgBitmap = dragBitmap ? dragBitmap->getPlatformBitmap ().cast<CGBitmap> () : 0;
558 CGImageRef cgImage = cgBitmap ? cgBitmap->getCGImage () : 0;
559 if (cgImage)
560 {
561 HIPoint imageOffset = { static_cast<CGFloat>(offset.x), static_cast<CGFloat>(offset.y) };
562 SetDragImageWithCGImage (drag, cgImage, &imageOffset, 0);
563 }
564
565 if (TrackDrag (drag, &eventRecord, NULL) == noErr)
566 {
567 DragActions action;
568 if (GetDragDropAction (drag, &action) == noErr)
569 {
570 if (action == kDragActionNothing)
571 result = kDragRefused;
572 else if (action & kDragActionMove)
573 result = kDragMoved;
574 else
575 result = kDragCopied;
576 }
577 }
578 }
579 DisposeDrag (drag);
580 }
581 CFRelease (pb);
582 }
583 return result;
584 }
585 #endif
586
587 //-----------------------------------------------------------------------------
doDrag(const DragDescription & dragDescription,const SharedPointer<IDragCallback> & callback)588 bool HIViewFrame::doDrag (const DragDescription& dragDescription, const SharedPointer<IDragCallback>& callback)
589 {
590 return false;
591 }
592
593
594 //-----------------------------------------------------------------------------
setClipboard(const SharedPointer<IDataPackage> & data)595 void HIViewFrame::setClipboard (const SharedPointer<IDataPackage>& data)
596 {
597 MacClipboard::setClipboard (data);
598 }
599
600 //-----------------------------------------------------------------------------
getClipboard()601 SharedPointer<IDataPackage> HIViewFrame::getClipboard ()
602 {
603 return MacClipboard::createClipboardDataPackage ();
604 }
605
606
607 #define ENABLE_LOGGING 0
608
609 #if ENABLE_LOGGING
610 #define LOG_HIPOINT(text,point) fprintf (stdout, "%s%d, %d\n", text, (int32_t)point.x, (int32_t)point.y);
611 #define LOG(text) fprintf (stdout, "%s\n", text);
612 #else
613 #define LOG_HIPOINT(x,y)
614 #define LOG(x)
615 #endif
616
617 //-----------------------------------------------------------------------------
carbonMouseEventHandler(EventHandlerCallRef inHandlerCallRef,EventRef inEvent,void * inUserData)618 pascal OSStatus HIViewFrame::carbonMouseEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData)
619 {
620 OSStatus result = eventNotHandledErr;
621 HIViewFrame* hiviewframe = (HIViewFrame*)inUserData;
622 IPlatformFrameCallback* frame = hiviewframe->frame;
623 UInt32 eventClass = GetEventClass (inEvent);
624 UInt32 eventKind = GetEventKind (inEvent);
625 WindowRef window = (WindowRef)hiviewframe->window;
626 HIViewRef hiView = hiviewframe->controlRef;
627
628 HIViewRef view;
629 if (HIViewGetViewForMouseEvent (HIViewGetRoot (window), inEvent, &view) == noErr)
630 {
631 if (view != hiView && !((eventKind == kEventMouseDragged || eventKind == kEventMouseUp) && hiviewframe->isInMouseTracking)) // TODO: make it work as above
632 return result;
633 }
634 switch (eventClass)
635 {
636 case kEventClassMouse:
637 {
638 UInt32 modifiers = 0;
639 EventMouseButton buttonState = 0;
640 CButtonState buttons = 0;
641 HIPoint location = { 0.f, 0.f };
642 if (GetEventParameter (inEvent, kEventParamWindowMouseLocation, typeHIPoint, NULL, sizeof (HIPoint), NULL, &location) == noErr)
643 {
644 //LOG_HIPOINT("window :",location)
645 HIPointConvert (&location, kHICoordSpaceWindow, window, kHICoordSpaceView, hiView);
646 //LOG_HIPOINT("view :",location)
647 }
648 if (!isWindowComposited ((WindowRef)window))
649 {
650 HIRect viewRect;
651 HIViewGetFrame(hiView, &viewRect);
652 location.x -= viewRect.origin.x;
653 location.y -= viewRect.origin.y;
654 }
655 GetEventParameter (inEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof (UInt32), NULL, &modifiers);
656 GetEventParameter (inEvent, kEventParamMouseButton, typeMouseButton, NULL, sizeof (EventMouseButton), NULL, &buttonState);
657 if (buttonState == kEventMouseButtonPrimary)
658 buttons |= kLButton;
659 if (buttonState == kEventMouseButtonSecondary)
660 buttons |= kRButton;
661 if (buttonState == kEventMouseButtonTertiary)
662 buttons |= kMButton;
663 if (buttonState == 4)
664 buttons |= kButton4;
665 if (buttonState == 5)
666 buttons |= kButton5;
667 if (modifiers & cmdKey)
668 buttons |= kControl;
669 if (modifiers & shiftKey)
670 buttons |= kShift;
671 if (modifiers & optionKey)
672 buttons |= kAlt;
673 if (modifiers & controlKey)
674 buttons |= kApple;
675 CPoint point ((CCoord)location.x, (CCoord)location.y);
676 switch (eventKind)
677 {
678 case kEventMouseDown:
679 {
680 LOG("Mouse Down")
681 UInt32 clickCount = 0;
682 GetEventParameter (inEvent, kEventParamClickCount, typeUInt32, NULL, sizeof (UInt32), NULL, &clickCount);
683 if (clickCount > 1)
684 buttons |= kDoubleClick;
685 result = CallNextEventHandler (inHandlerCallRef, inEvent); // calls default handler, which activates the window if not already active, or sets the process to front
686 CMouseEventResult mer = frame->platformOnMouseDown (point, buttons);
687 if (mer == kMouseEventHandled)
688 hiviewframe->isInMouseTracking = true;
689 if (mer != kMouseEventNotHandled)
690 result = noErr;
691 break;
692 }
693 case kEventMouseUp:
694 {
695 LOG("Mouse Up")
696 if (frame->platformOnMouseUp (point, buttons) != kMouseEventNotHandled)
697 result = noErr;
698 hiviewframe->isInMouseTracking = false;
699 break;
700 }
701 case kEventMouseDragged:
702 {
703 //LOG("Mouse Dragged")
704 if (frame->platformOnMouseMoved (point, buttons) != kMouseEventNotHandled)
705 result = noErr;
706 break;
707 }
708 case kEventMouseMoved:
709 {
710 //LOG("Mouse Moved")
711 if (IsWindowActive (window))
712 {
713 if (frame->platformOnMouseMoved (point, buttons) != kMouseEventNotHandled)
714 result = noErr;
715 }
716 break;
717 }
718 }
719 break;
720 }
721 }
722 return result;
723 }
724
725 //------------------------------------------------------------------------------
726 static short keyTable[] = {
727 VKEY_BACK, 0x33,
728 VKEY_TAB, 0x30,
729 VKEY_RETURN, 0x24,
730 VKEY_PAUSE, 0x71,
731 VKEY_ESCAPE, 0x35,
732 VKEY_SPACE, 0x31,
733
734 VKEY_END, 0x77,
735 VKEY_HOME, 0x73,
736
737 VKEY_LEFT, 0x7B,
738 VKEY_UP, 0x7E,
739 VKEY_RIGHT, 0x7C,
740 VKEY_DOWN, 0x7D,
741 VKEY_PAGEUP, 0x74,
742 VKEY_PAGEDOWN, 0x79,
743
744 VKEY_PRINT, 0x69,
745 VKEY_ENTER, 0x4C,
746 VKEY_HELP, 0x72,
747 VKEY_DELETE, 0x75,
748 VKEY_NUMPAD0, 0x52,
749 VKEY_NUMPAD1, 0x53,
750 VKEY_NUMPAD2, 0x54,
751 VKEY_NUMPAD3, 0x55,
752 VKEY_NUMPAD4, 0x56,
753 VKEY_NUMPAD5, 0x57,
754 VKEY_NUMPAD6, 0x58,
755 VKEY_NUMPAD7, 0x59,
756 VKEY_NUMPAD8, 0x5B,
757 VKEY_NUMPAD9, 0x5C,
758 VKEY_MULTIPLY, 0x43,
759 VKEY_ADD, 0x45,
760 VKEY_SUBTRACT, 0x4E,
761 VKEY_DECIMAL, 0x41,
762 VKEY_DIVIDE, 0x4B,
763 VKEY_F1, 0x7A,
764 VKEY_F2, 0x78,
765 VKEY_F3, 0x63,
766 VKEY_F4, 0x76,
767 VKEY_F5, 0x60,
768 VKEY_F6, 0x61,
769 VKEY_F7, 0x62,
770 VKEY_F8, 0x64,
771 VKEY_F9, 0x65,
772 VKEY_F10, 0x6D,
773 VKEY_F11, 0x67,
774 VKEY_F12, 0x6F,
775 VKEY_NUMLOCK, 0x47,
776 VKEY_EQUALS, 0x51
777 };
778
779 /// @cond ignore
780 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_6
781 class VSTGUIDrawRectsHelper
782 {
783 public:
VSTGUIDrawRectsHelper(CFrame * inFrame,CDrawContext * inContext,bool inIsComposited)784 VSTGUIDrawRectsHelper (CFrame* inFrame, CDrawContext* inContext, bool inIsComposited) : frame (inFrame), context (inContext), isComposited (inIsComposited) {}
785
786 CFrame* frame;
787 CDrawContext* context;
788 bool isComposited;
789 };
790
791 //-----------------------------------------------------------------------------
Rect2CRect(Rect & rr,CRect & cr)792 static void Rect2CRect (Rect &rr, CRect &cr)
793 {
794 cr.left = rr.left;
795 cr.right = rr.right;
796 cr.top = rr.top;
797 cr.bottom = rr.bottom;
798 }
799
VSTGUIDrawRectsProc(UInt16 message,RgnHandle rgn,const Rect * rect,void * refCon)800 static OSStatus VSTGUIDrawRectsProc (UInt16 message, RgnHandle rgn, const Rect* rect, void* refCon)
801 {
802 if (message == kQDRegionToRectsMsgParse)
803 {
804 VSTGUIDrawRectsHelper* h = (VSTGUIDrawRectsHelper*)refCon;
805 CRect r;
806 Rect2CRect ((Rect&)*rect, r);
807 // if (!h->isComposited)
808 // r.offset (-h->context->offsetScreen.x, -h->context->offsetScreen.y);
809 h->context->saveGlobalState ();
810 h->frame->drawRect (h->context, r);
811 h->context->restoreGlobalState ();
812 }
813 return noErr;
814 }
815 #else
816 struct CFrameAndCDrawContext {
817 CFrame* frame;
818 CDrawContext* context;
819
CFrameAndCDrawContextVSTGUI::CFrameAndCDrawContext820 CFrameAndCDrawContext (CFrame* f, CDrawContext* c) : frame (f), context (c) {}
821 };
822
HIShapeEnumerateProc(int inMessage,HIShapeRef inShape,const CGRect * inRect,void * inRefcon)823 static OSStatus HIShapeEnumerateProc (int inMessage, HIShapeRef inShape, const CGRect *inRect, void *inRefcon)
824 {
825 if (inMessage == kHIShapeEnumerateRect)
826 {
827 CFrameAndCDrawContext* tmp = (CFrameAndCDrawContext*)inRefcon;
828 CRect r (inRect->origin.x, inRect->origin.y, 0, 0);
829 r.setWidth (inRect->size.width);
830 r.setHeight (inRect->size.height);
831 tmp->context->saveGlobalState ();
832 tmp->frame->drawRect (tmp->context, r);
833 tmp->context->restoreGlobalState ();
834 }
835 return noErr;
836 }
837
838 #endif
839 /// @endcond
840
841 #ifndef kHIViewFeatureGetsFocusOnClick
842 #define kHIViewFeatureGetsFocusOnClick (1 << 8)
843 #endif
844
845 bool hiToolboxAllowFocusChange = true;
846
847 //-----------------------------------------------------------------------------
carbonEventHandler(EventHandlerCallRef inHandlerCallRef,EventRef inEvent,void * inUserData)848 pascal OSStatus HIViewFrame::carbonEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData)
849 {
850 OSStatus result = eventNotHandledErr;
851 HIViewFrame* hiviewframe = (HIViewFrame*)inUserData;
852 IPlatformFrameCallback* frame = hiviewframe->frame;
853 UInt32 eventClass = GetEventClass (inEvent);
854 UInt32 eventKind = GetEventKind (inEvent);
855 WindowRef window = hiviewframe->window;
856
857 switch (eventClass)
858 {
859 #if 0 // TODO: make it work, or remove support for embedding the frame into a native scroll view
860 case kEventClassScrollable:
861 {
862 switch (eventKind)
863 {
864 case kEventScrollableGetInfo:
865 {
866 HISize cs = {frame->getWidth (), frame->getHeight ()};
867 SetEventParameter (inEvent, kEventParamImageSize, typeHISize, sizeof (HISize), &cs);
868 HIPoint origin = {frame->hiScrollOffset.x, frame->hiScrollOffset.y};
869 SetEventParameter (inEvent, kEventParamOrigin, typeHIPoint, sizeof (HIPoint), &origin);
870 HISize lineSize = {50.0, 20.0};
871 SetEventParameter(inEvent, kEventParamLineSize, typeHISize, sizeof(lineSize), &lineSize);
872 HIRect bounds;
873 HIViewGetBounds (hiviewframe->controlRef, &bounds);
874 SetEventParameter(inEvent, kEventParamViewSize, typeHISize, sizeof(bounds.size), &bounds.size);
875 result = noErr;
876 break;
877 }
878 case kEventScrollableScrollTo:
879 {
880 HIPoint where;
881 GetEventParameter(inEvent, kEventParamOrigin, typeHIPoint, NULL, sizeof(where), NULL, &where);
882 frame->hiScrollOffset.x = (CCoord)where.x;
883 frame->hiScrollOffset.y = (CCoord)where.y;
884 HIViewSetBoundsOrigin(hiviewframe->controlRef, where.x, where.y);
885 HIViewSetNeedsDisplay(hiviewframe->controlRef, true);
886 result = noErr;
887 break;
888 }
889 }
890 break;
891 }
892 #endif
893 case kEventClassControl:
894 {
895 switch (eventKind)
896 {
897 case kEventControlInitialize:
898 {
899 UInt32 controlFeatures = kControlSupportsDragAndDrop | kControlSupportsFocus | kControlHandlesTracking | kControlSupportsEmbedding | kHIViewFeatureGetsFocusOnClick | kHIViewIsOpaque | kHIViewGetsFocusOnClick;
900 SetEventParameter (inEvent, kEventParamControlFeatures, typeUInt32, sizeof (UInt32), &controlFeatures);
901 result = noErr;
902 break;
903 }
904 case kEventControlDraw:
905 {
906 CDrawContext* context = 0;
907 HIRect controlBounds;
908 HIViewGetBounds (hiviewframe->controlRef, &controlBounds);
909 CRect dirtyRect;
910 dirtyRect.left = controlBounds.origin.x;
911 dirtyRect.top = controlBounds.origin.y;
912 dirtyRect.setWidth (controlBounds.size.width);
913 dirtyRect.setHeight (controlBounds.size.height);
914 CGContextRef cgcontext = 0;
915 OSStatus res = GetEventParameter (inEvent, kEventParamCGContextRef, typeCGContextRef, NULL, sizeof (cgcontext), NULL, &cgcontext);
916 if (res != noErr)
917 break;
918 context = new CGDrawContext (cgcontext, dirtyRect);
919 context->beginDraw ();
920
921 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_6
922 RgnHandle dirtyRegion;
923 if (GetEventParameter (inEvent, kEventParamRgnHandle, typeQDRgnHandle, NULL, sizeof (RgnHandle), NULL, &dirtyRegion) == noErr)
924 {
925 CFrame* cframe = dynamic_cast<CFrame*> (frame);
926 VSTGUIDrawRectsHelper helper (cframe, context, isWindowComposited (window));
927 RegionToRectsUPP upp = NewRegionToRectsUPP (VSTGUIDrawRectsProc);
928 QDRegionToRects (dirtyRegion, kQDParseRegionFromTopLeft, upp, &helper);
929 DisposeRegionToRectsUPP (upp);
930 }
931 else
932 #else
933 HIShapeRef shapeRef;
934 if (GetEventParameter (inEvent, kEventParamShape, typeHIShapeRef, NULL, sizeof (HIShapeRef), NULL, &shapeRef) == noErr)
935 {
936 CFrame* cframe = dynamic_cast<CFrame*> (frame);
937 CFrameAndCDrawContext tmp (cframe, context);
938 HIShapeEnumerate (shapeRef, kHIShapeParseFromTopLeft, HIShapeEnumerateProc, &tmp);
939 }
940 #endif
941 {
942 frame->platformDrawRect (context, dirtyRect);
943 }
944 context->endDraw ();
945 context->forget ();
946 result = noErr;
947 break;
948 }
949 case kEventControlGetClickActivation:
950 {
951 ClickActivationResult activation = kActivateAndHandleClick;
952 SetEventParameter (inEvent, kEventParamClickActivation, typeClickActivationResult, sizeof (ClickActivationResult), &activation);
953 result = noErr;
954 break;
955 }
956 case kEventControlHitTest:
957 {
958 ControlPartCode code = kControlContentMetaPart;
959 SetEventParameter (inEvent, kEventParamControlPart, typeControlPartCode, sizeof (ControlPartCode), &code);
960 result = noErr;
961 break;
962 }
963 case kEventControlClick:
964 {
965 return noErr;
966 EventMouseButton buttonState;
967 GetEventParameter (inEvent, kEventParamMouseButton, typeMouseButton, NULL, sizeof (EventMouseButton), NULL, &buttonState);
968 if (buttonState == kEventMouseButtonPrimary)
969 {
970 result = CallNextEventHandler (inHandlerCallRef, inEvent);
971 break;
972 }
973 }
974 case kEventControlTrack:
975 case kEventControlContextualMenuClick:
976 {
977 break;
978 }
979 #if 0 // TODO: is this necessary
980 case kEventControlGetOptimalBounds:
981 {
982 HIRect optimalBounds = { {0, 0}, { frame->getWidth (), frame->getHeight ()}};
983 SetEventParameter (inEvent, kEventParamControlOptimalBounds, typeHIRect, sizeof (HIRect), &optimalBounds);
984 result = noErr;
985 break;
986 }
987 #endif
988 case kEventControlGetFocusPart:
989 {
990 if (hiToolboxAllowFocusChange)
991 {
992 ControlPartCode code = hiviewframe->hasFocus ? 127 : kControlFocusNoPart;
993 SetEventParameter (inEvent, kEventParamControlPart, typeControlPartCode, sizeof (ControlPartCode), &code);
994 result = noErr;
995 }
996 break;
997 }
998 case kEventControlSetFocusPart:
999 {
1000 if (hiToolboxAllowFocusChange)
1001 {
1002 CFrame* cframe = dynamic_cast<CFrame*> (frame);
1003 if (cframe)
1004 {
1005 ControlPartCode code;
1006 GetEventParameter (inEvent, kEventParamControlPart, typeControlPartCode, NULL, sizeof (ControlPartCode), NULL, &code);
1007 if (code == kControlFocusNoPart)
1008 {
1009 hiviewframe->hasFocus = false;
1010 }
1011 else
1012 {
1013 bool anfResult = false;
1014 if (code == kControlFocusNextPart)
1015 anfResult = cframe->advanceNextFocusView (cframe->getFocusView ());
1016 else if (code == kControlFocusPrevPart)
1017 anfResult = cframe->advanceNextFocusView (cframe->getFocusView (), true);
1018 if (anfResult)
1019 {
1020 hiviewframe->hasFocus = true;
1021 code = 127;
1022 }
1023 else
1024 {
1025 hiviewframe->hasFocus = false;
1026 code = kControlFocusNoPart;
1027 }
1028 SetEventParameter (inEvent, kEventParamControlPart, typeControlPartCode, sizeof (code), &code);
1029 }
1030 result = noErr;
1031 }
1032 }
1033 break;
1034 }
1035 case kEventControlDragEnter:
1036 {
1037 DragRef dragRef;
1038 if (GetEventParameter (inEvent, kEventParamDragRef, typeDragRef, NULL, sizeof (DragRef), NULL, &dragRef) == noErr)
1039 {
1040 gDragContainer = MacClipboard::createCarbonDragDataPackage (dragRef);
1041
1042 CPoint where = GetMacDragMouse (hiviewframe, dragRef);
1043 hiviewframe->setMouseCursor (kCursorNotAllowed);
1044 DragEventData data {gDragContainer, where, 0};
1045 frame->platformOnDragEnter (data);
1046
1047 Boolean acceptDrop = true;
1048 SetEventParameter (inEvent, kEventParamControlWouldAcceptDrop, typeBoolean, sizeof (Boolean), &acceptDrop);
1049 }
1050 result = noErr;
1051 break;
1052 }
1053 case kEventControlDragWithin:
1054 {
1055 DragRef dragRef;
1056 if (gDragContainer && GetEventParameter (inEvent, kEventParamDragRef, typeDragRef, NULL, sizeof (DragRef), NULL, &dragRef) == noErr)
1057 {
1058 CPoint where = GetMacDragMouse (hiviewframe, dragRef);
1059 DragEventData data {gDragContainer, where, 0};
1060 frame->platformOnDragMove (data);
1061 }
1062 result = noErr;
1063 break;
1064 }
1065 case kEventControlDragLeave:
1066 {
1067 DragRef dragRef;
1068 if (gDragContainer && GetEventParameter (inEvent, kEventParamDragRef, typeDragRef, NULL, sizeof (DragRef), NULL, &dragRef) == noErr)
1069 {
1070 CPoint where = GetMacDragMouse (hiviewframe, dragRef);
1071 DragEventData data {gDragContainer, where, 0};
1072 frame->platformOnDragLeave (data);
1073 hiviewframe->setMouseCursor (kCursorDefault);
1074 }
1075 result = noErr;
1076 break;
1077 }
1078 case kEventControlDragReceive:
1079 {
1080 DragRef dragRef;
1081 if (gDragContainer && GetEventParameter (inEvent, kEventParamDragRef, typeDragRef, NULL, sizeof (DragRef), NULL, &dragRef) == noErr)
1082 {
1083 CPoint where = GetMacDragMouse (hiviewframe, dragRef);
1084 DragEventData data {gDragContainer, where, 0};
1085 frame->platformOnDrop (data);
1086 hiviewframe->setMouseCursor (kCursorDefault);
1087 gDragContainer = nullptr;
1088 }
1089 result = noErr;
1090 break;
1091 }
1092 case kEventControlTrackingAreaExited:
1093 {
1094 HIPoint location = { 0.f, 0.f };
1095 if (GetEventParameter (inEvent, kEventParamMouseLocation, typeHIPoint, NULL, sizeof (HIPoint), NULL, &location) == noErr)
1096 {
1097 if (!isWindowComposited (window))
1098 {
1099 HIRect viewRect;
1100 HIViewGetFrame (hiviewframe->controlRef, &viewRect);
1101 location.x -= viewRect.origin.x;
1102 location.y -= viewRect.origin.y;
1103 }
1104 CPoint point ((CCoord)location.x, (CCoord)location.y);
1105 frame->platformOnMouseExited (point, 0);
1106 }
1107 break;
1108 }
1109 }
1110 break;
1111 }
1112 case kEventClassMouse:
1113 {
1114 switch (eventKind)
1115 {
1116 case kEventMouseWheelMoved:
1117 {
1118 UInt32 modifiers;
1119 HIPoint windowHIPoint;
1120 SInt32 wheelDelta;
1121 EventMouseWheelAxis wheelAxis;
1122 WindowRef windowRef;
1123 GetEventParameter (inEvent, kEventParamWindowRef, typeWindowRef, NULL, sizeof (WindowRef), NULL, &windowRef);
1124 GetEventParameter (inEvent, kEventParamMouseWheelAxis, typeMouseWheelAxis, NULL, sizeof (EventMouseWheelAxis), NULL, &wheelAxis);
1125 GetEventParameter (inEvent, kEventParamMouseWheelDelta, typeSInt32, NULL, sizeof (SInt32), NULL, &wheelDelta);
1126 GetEventParameter (inEvent, kEventParamWindowMouseLocation, typeHIPoint, NULL, sizeof (HIPoint), NULL, &windowHIPoint);
1127 GetEventParameter (inEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof (UInt32), NULL, &modifiers);
1128 CButtonState buttons = 0;
1129 if (modifiers & cmdKey)
1130 buttons |= kControl;
1131 if (modifiers & shiftKey)
1132 buttons |= kShift;
1133 if (modifiers & optionKey)
1134 buttons |= kAlt;
1135 if (modifiers & controlKey)
1136 buttons |= kApple;
1137
1138 HIPointConvert (&windowHIPoint, kHICoordSpaceWindow, windowRef, kHICoordSpaceView, hiviewframe->controlRef);
1139
1140 // non-compositing window controls need to handle offset themselves
1141 if (!isWindowComposited (windowRef))
1142 {
1143 HIRect viewRect;
1144 HIViewGetFrame(hiviewframe->controlRef, &viewRect);
1145 windowHIPoint.x -= viewRect.origin.x;
1146 windowHIPoint.y -= viewRect.origin.y;
1147 }
1148
1149 CPoint p ((CCoord)windowHIPoint.x, (CCoord)windowHIPoint.y);
1150 float distance = wheelDelta;
1151 CMouseWheelAxis axis = kMouseWheelAxisY;
1152 if (wheelAxis == kEventMouseWheelAxisX)
1153 axis = kMouseWheelAxisX;
1154 frame->platformOnMouseWheel (p, axis, distance, buttons);
1155 result = noErr;
1156 break;
1157 }
1158 }
1159 break;
1160 }
1161 case kEventClassTextInput:
1162 {
1163 switch (eventKind)
1164 {
1165 case kEventTextInputUnicodeForKeyEvent:
1166 {
1167 // The "Standard Event Handler" of a window would return noErr even though no one has handled the key event.
1168 // This prevents the "Standard Handler" to be called for this event, with the exception of the tab key as it is used for control focus changes.
1169 EventRef rawKeyEvent;
1170 GetEventParameter (inEvent, kEventParamTextInputSendKeyboardEvent, typeEventRef, NULL, sizeof (EventRef), NULL, &rawKeyEvent);
1171 if (rawKeyEvent)
1172 {
1173 UInt32 keyCode = 0;
1174 GetEventParameter (rawKeyEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof (UInt32), NULL, &keyCode);
1175 if (keyCode == (UInt32)keyTable[VKEY_TAB+1])
1176 return result;
1177 }
1178 result = eventPassToNextTargetErr;
1179 break;
1180 }
1181 }
1182 break;
1183 }
1184 case kEventClassWindow:
1185 {
1186 switch (eventKind)
1187 {
1188 case kEventWindowFocusAcquired:
1189 {
1190 frame->platformOnActivate (true);
1191 break;
1192 }
1193 case kEventWindowFocusRelinquish:
1194 {
1195 frame->platformOnActivate (false);
1196 break;
1197 }
1198 }
1199 break;
1200 }
1201 case kEventClassKeyboard:
1202 {
1203 if (hiviewframe->hasFocus)
1204 {
1205 switch (eventKind)
1206 {
1207 case kEventRawKeyDown:
1208 case kEventRawKeyRepeat:
1209 {
1210 // todo: make this work
1211
1212 char character = 0;
1213 UInt32 keyCode = 0;
1214 UInt32 modifiers = 0;
1215 GetEventParameter (inEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof (char), NULL, &character);
1216 GetEventParameter (inEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof (UInt32), NULL, &keyCode);
1217 GetEventParameter (inEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof (UInt32), NULL, &modifiers);
1218 char scanCode = static_cast<char> (keyCode);
1219 VstKeyCode vstKeyCode;
1220 memset (&vstKeyCode, 0, sizeof (VstKeyCode));
1221 KeyboardLayoutRef layout;
1222 if (KLGetCurrentKeyboardLayout (&layout) == noErr)
1223 {
1224 const void* pKCHR = 0;
1225 KLGetKeyboardLayoutProperty (layout, kKLKCHRData, &pKCHR);
1226 if (pKCHR)
1227 {
1228 static UInt32 keyTranslateState = 0;
1229 vstKeyCode.character = static_cast<int32_t> (KeyTranslate (pKCHR, static_cast<UInt16> (keyCode), &keyTranslateState));
1230 if (modifiers & shiftKey)
1231 {
1232 vstKeyCode.character = toupper (vstKeyCode.character);
1233 }
1234 }
1235 }
1236 short entries = sizeof (keyTable) / (sizeof (short));
1237 for (int32_t i = 0; i < entries; i += 2)
1238 {
1239 if (keyTable[i + 1] == scanCode)
1240 {
1241 vstKeyCode.virt = static_cast<unsigned char> (keyTable[i]);
1242 vstKeyCode.character = 0;
1243 break;
1244 }
1245 }
1246 if (modifiers & cmdKey)
1247 vstKeyCode.modifier |= MODIFIER_CONTROL;
1248 if (modifiers & shiftKey)
1249 vstKeyCode.modifier |= MODIFIER_SHIFT;
1250 if (modifiers & optionKey)
1251 vstKeyCode.modifier |= MODIFIER_ALTERNATE;
1252 if (modifiers & controlKey)
1253 vstKeyCode.modifier |= MODIFIER_COMMAND;
1254 if (frame->platformOnKeyDown (vstKeyCode))
1255 result = noErr;
1256
1257 break;
1258 }
1259 }
1260 }
1261 break;
1262 }
1263 }
1264 return result;
1265 }
1266
1267
1268 } // VSTGUI
1269
1270 #pragma clang diagnostic pop
1271
1272 #endif // MAC_CARBON
1273