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