2031 lines
54 KiB
C++
2031 lines
54 KiB
C++
// This file is part of VSTGUI. It is subject to the license terms
|
|
// in the LICENSE file found in the top-level directory of this
|
|
// distribution and at http://github.com/steinbergmedia/vstgui/LICENSE
|
|
|
|
#include "cframe.h"
|
|
#include "events.h"
|
|
#include "finally.h"
|
|
#include "coffscreencontext.h"
|
|
#include "ctooltipsupport.h"
|
|
#include "cinvalidrectlist.h"
|
|
#include "itouchevent.h"
|
|
#include "iscalefactorchangedlistener.h"
|
|
#include "idatapackage.h"
|
|
#include "iviewlayouter.h"
|
|
#include "animation/animator.h"
|
|
#include "controls/ctextedit.h"
|
|
#include "platform/platformfactory.h"
|
|
#include "platform/iplatformframe.h"
|
|
#include <cassert>
|
|
#include <vector>
|
|
#include <queue>
|
|
#include <stack>
|
|
#include <limits>
|
|
|
|
namespace VSTGUI {
|
|
|
|
IdStringPtr kMsgNewFocusView = "kMsgNewFocusView";
|
|
IdStringPtr kMsgOldFocusView = "kMsgOldFocusView";
|
|
|
|
#define DEBUG_MOUSE_VIEWS (DEBUG && 0)
|
|
|
|
//------------------------------------------------------------------------
|
|
struct CFrame::CollectInvalidRects
|
|
{
|
|
explicit CollectInvalidRects (CFrame* frame);
|
|
~CollectInvalidRects () noexcept;
|
|
|
|
void addRect (const CRect& rect);
|
|
void flush ();
|
|
|
|
private:
|
|
using InvalidRects = std::vector<CRect>;
|
|
|
|
SharedPointer<CFrame> frame;
|
|
CInvalidRectList invalidRects;
|
|
uint64_t lastTicks;
|
|
#if VSTGUI_LOG_COLLECT_INVALID_RECTS
|
|
uint32_t numAddedRects;
|
|
#endif
|
|
};
|
|
|
|
//------------------------------------------------------------------------
|
|
struct ModalViewSession
|
|
{
|
|
ModalViewSessionID identifier {};
|
|
SharedPointer<CView> view;
|
|
};
|
|
|
|
//------------------------------------------------------------------------
|
|
struct CFrame::Impl
|
|
{
|
|
using ViewList = std::list<CView*>;
|
|
using FunctionQueue = std::queue<EventProcessingFunction>;
|
|
using ModalViewSessionStack = std::stack<ModalViewSession>;
|
|
|
|
PlatformFramePtr platformFrame;
|
|
VSTGUIEditorInterface* editor {nullptr};
|
|
IViewAddedRemovedObserver* viewAddedRemovedObserver {nullptr};
|
|
SharedPointer<CTooltipSupport> tooltips;
|
|
SharedPointer<Animation::Animator> animator;
|
|
#if VSTGUI_ENABLE_DEPRECATED_METHODS
|
|
Optional<ModalViewSessionID> legacyModalViewSessionID;
|
|
#endif
|
|
CView* focusView {nullptr};
|
|
CView* activeFocusView {nullptr};
|
|
CollectInvalidRects* collectInvalidRects {nullptr};
|
|
|
|
ViewList mouseViews;
|
|
ModalViewSessionStack modalViewSessionStack;
|
|
DispatchList<CView*> windowActiveStateChangeViews;
|
|
DispatchList<IScaleFactorChangedListener*> scaleFactorChangedListenerList;
|
|
DispatchList<IMouseObserver*> mouseObservers;
|
|
DispatchList<IFocusViewObserver*> focusViewObservers;
|
|
DispatchList<IKeyboardHook*> keyboardHooks;
|
|
FunctionQueue postEventFunctionQueue;
|
|
std::optional<ViewLayout> lastCheckSizeConstraintLayout;
|
|
|
|
ModalViewSessionID modalViewSessionIDCounter {0};
|
|
double userScaleFactor {1.};
|
|
double platformScaleFactor {1.};
|
|
bool active {false};
|
|
bool windowActive {false};
|
|
bool inEventHandling {false};
|
|
BitmapInterpolationQuality bitmapQuality {BitmapInterpolationQuality::kDefault};
|
|
|
|
struct PostEventHandler
|
|
{
|
|
PostEventHandler (Impl& impl) : impl (impl)
|
|
{
|
|
wasInEventHandling = impl.inEventHandling;
|
|
impl.inEventHandling = true;
|
|
}
|
|
~PostEventHandler () noexcept
|
|
{
|
|
vstgui_assert (impl.inEventHandling == true);
|
|
impl.inEventHandling = wasInEventHandling;
|
|
FunctionQueue fl;
|
|
impl.postEventFunctionQueue.swap (fl);
|
|
while (!fl.empty ())
|
|
{
|
|
fl.front () ();
|
|
fl.pop ();
|
|
}
|
|
}
|
|
|
|
private:
|
|
Impl& impl;
|
|
bool wasInEventHandling;
|
|
};
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// CFrame Implementation
|
|
//-----------------------------------------------------------------------------
|
|
/*! @class CFrame
|
|
It creates a platform dependend view object.
|
|
|
|
On Mac OS X it is a HIView or NSView.\n
|
|
On Windows it's a WS_CHILD Window.
|
|
|
|
*/
|
|
//-----------------------------------------------------------------------------
|
|
CFrame::CFrame (const CRect& inSize, VSTGUIEditorInterface* inEditor) : CViewContainer (inSize)
|
|
{
|
|
pImpl = new Impl;
|
|
pImpl->editor = inEditor;
|
|
|
|
setParentFrame (this);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::beforeDelete ()
|
|
{
|
|
clearMouseViews (CPoint (0, 0), Modifiers (), false);
|
|
|
|
clearModalViewSessions ();
|
|
|
|
setCursor (kCursorDefault);
|
|
|
|
setParentFrame (nullptr);
|
|
removeAll ();
|
|
|
|
pImpl->tooltips = nullptr;
|
|
pImpl->animator = nullptr;
|
|
|
|
#if DEBUG
|
|
if (!pImpl->scaleFactorChangedListenerList.empty ())
|
|
{
|
|
DebugPrint ("Warning: Scale Factor Changed Listeners are not cleaned up correctly.\n If you register a change listener you must also unregister it !\n");
|
|
}
|
|
|
|
if (!pImpl->mouseObservers.empty ())
|
|
{
|
|
DebugPrint ("Warning: Mouse Observers are not cleaned up correctly.\n If you register a mouse oberver you must also unregister it !\n");
|
|
}
|
|
|
|
if (!pImpl->keyboardHooks.empty ())
|
|
{
|
|
DebugPrint ("Warning: Keyboard Hooks are not cleaned up correctly.\n If you register a keyboard hook you must also unregister it !\n");
|
|
}
|
|
#endif
|
|
|
|
if (pImpl->platformFrame)
|
|
{
|
|
pImpl->platformFrame->onFrameClosed ();
|
|
pImpl->platformFrame = nullptr;
|
|
}
|
|
|
|
setViewFlag (kIsAttached, false);
|
|
|
|
delete pImpl;
|
|
pImpl = nullptr;
|
|
|
|
CViewContainer::beforeDelete ();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::close ()
|
|
{
|
|
clearMouseViews (CPoint (0, 0), Modifiers (), false);
|
|
|
|
clearModalViewSessions ();
|
|
|
|
setCursor (kCursorDefault);
|
|
setParentFrame (nullptr);
|
|
removeAll ();
|
|
if (pImpl->platformFrame)
|
|
{
|
|
pImpl->platformFrame->onFrameClosed ();
|
|
pImpl->platformFrame = nullptr;
|
|
}
|
|
forget ();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool CFrame::open (void* systemWin, PlatformType systemWindowType, IPlatformFrameConfig* config)
|
|
{
|
|
if (!systemWin || isAttached ())
|
|
return false;
|
|
|
|
pImpl->platformFrame = getPlatformFactory ().createFrame (this, getViewSize (), systemWin,
|
|
systemWindowType, config);
|
|
if (!pImpl->platformFrame)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
CollectInvalidRects cir (this);
|
|
|
|
attached (this);
|
|
|
|
setParentView (nullptr);
|
|
|
|
invalid ();
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool CFrame::attached (CView* parent)
|
|
{
|
|
if (isAttached ())
|
|
return false;
|
|
vstgui_assert (parent == this);
|
|
if (CView::attached (parent))
|
|
{
|
|
setParentView (nullptr);
|
|
|
|
for (const auto& pV : getChildren ())
|
|
pV->attached (this);
|
|
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool CFrame::setZoom (double zoomFactor)
|
|
{
|
|
if (zoomFactor == 0.)
|
|
return false;
|
|
|
|
bool result = true;
|
|
CGraphicsTransform currentTransform = getTransform ();
|
|
CCoord origWidth = getWidth () / currentTransform.m11;
|
|
CCoord origHeight = getHeight () / currentTransform.m22;
|
|
CCoord newWidth = origWidth * zoomFactor;
|
|
CCoord newHeight = origHeight * zoomFactor;
|
|
setAutosizingEnabled (false);
|
|
setTransform (CGraphicsTransform ().scale (zoomFactor, zoomFactor));
|
|
if (!setSize (newWidth, newHeight))
|
|
{
|
|
setTransform (currentTransform);
|
|
setSize (origWidth * currentTransform.m11, origHeight * currentTransform.m22);
|
|
result = false;
|
|
}
|
|
invalid ();
|
|
setAutosizingEnabled (true);
|
|
if (result)
|
|
{
|
|
pImpl->userScaleFactor = zoomFactor;
|
|
dispatchNewScaleFactor (getScaleFactor ());
|
|
}
|
|
return result;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
double CFrame::getZoom () const
|
|
{
|
|
return pImpl->userScaleFactor;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::setBitmapInterpolationQuality (BitmapInterpolationQuality quality)
|
|
{
|
|
if (pImpl && pImpl->bitmapQuality != quality)
|
|
{
|
|
pImpl->bitmapQuality = quality;
|
|
invalid ();
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
BitmapInterpolationQuality CFrame::getBitmapInterpolationQuality () const
|
|
{
|
|
if (pImpl)
|
|
return pImpl->bitmapQuality;
|
|
return BitmapInterpolationQuality::kDefault;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
double CFrame::getScaleFactor () const
|
|
{
|
|
return pImpl->platformScaleFactor * pImpl->userScaleFactor;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::enableTooltips (bool state, uint32_t delayTimeInMs)
|
|
{
|
|
if (state)
|
|
{
|
|
if (pImpl->tooltips == nullptr)
|
|
pImpl->tooltips = makeOwned<CTooltipSupport> (this, delayTimeInMs);
|
|
}
|
|
else if (pImpl->tooltips)
|
|
{
|
|
pImpl->tooltips = nullptr;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::draw (CDrawContext* pContext)
|
|
{
|
|
return CFrame::drawRect (pContext, getViewSize ());
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::drawRect (CDrawContext* pContext, const CRect& updateRect)
|
|
{
|
|
if (updateRect.getWidth () <= 0 || updateRect.getHeight () <= 0 || pContext == nullptr)
|
|
return;
|
|
|
|
auto lifeGuard = shared (pContext);
|
|
|
|
if (pImpl)
|
|
pContext->setBitmapInterpolationQuality (pImpl->bitmapQuality);
|
|
|
|
drawClipped (pContext, updateRect, [&] () {
|
|
// draw the background and the children
|
|
CViewContainer::drawRect (pContext, updateRect);
|
|
});
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::clearMouseViews (const CPoint& where, Modifiers modifiers, bool callMouseExit)
|
|
{
|
|
auto it = pImpl->mouseViews.rbegin ();
|
|
while (it != pImpl->mouseViews.rend ())
|
|
{
|
|
if (callMouseExit)
|
|
{
|
|
MouseExitEvent exitEvent;
|
|
exitEvent.modifiers = modifiers;
|
|
exitEvent.mousePosition = (*it)->translateToLocal (where, true);
|
|
dispatchEvent ((*it), exitEvent);
|
|
#if DEBUG_MOUSE_VIEWS
|
|
DebugPrint ("mouseExited : %p[%d,%d]\n", (*it), (int)exitEvent.mousePosition.x,
|
|
(int)exitEvent.mousePosition.y);
|
|
#endif
|
|
}
|
|
if (pImpl->tooltips)
|
|
pImpl->tooltips->onMouseExited ((*it));
|
|
|
|
callMouseObserverMouseExited ((*it));
|
|
|
|
(*it)->forget ();
|
|
++it;
|
|
}
|
|
pImpl->mouseViews.clear ();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::removeFromMouseViews (CView* view)
|
|
{
|
|
bool found = false;
|
|
auto it = pImpl->mouseViews.begin ();
|
|
while (it != pImpl->mouseViews.end ())
|
|
{
|
|
if (found || (*it) == view)
|
|
{
|
|
if (pImpl->tooltips)
|
|
pImpl->tooltips->onMouseExited ((*it));
|
|
|
|
callMouseObserverMouseExited ((*it));
|
|
|
|
(*it)->forget ();
|
|
pImpl->mouseViews.erase (it++);
|
|
found = true;
|
|
}
|
|
else
|
|
++it;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::checkMouseViews (const MouseEvent& event)
|
|
{
|
|
if (getMouseDownView ())
|
|
return;
|
|
CView* mouseView = getViewAt (event.mousePosition, GetViewOptions ().deep ().mouseEnabled ().includeViewContainer ());
|
|
CView* currentMouseView = pImpl->mouseViews.empty () == false ? pImpl->mouseViews.back () : nullptr;
|
|
if (currentMouseView == mouseView)
|
|
return; // no change
|
|
|
|
if (pImpl->tooltips)
|
|
{
|
|
if (currentMouseView)
|
|
pImpl->tooltips->onMouseExited (currentMouseView);
|
|
if (mouseView && mouseView != this)
|
|
pImpl->tooltips->onMouseEntered (mouseView);
|
|
}
|
|
|
|
if (mouseView == nullptr || mouseView == this)
|
|
{
|
|
clearMouseViews (event.mousePosition, event.modifiers);
|
|
return;
|
|
}
|
|
|
|
auto callMouseExitForView = [this, &event] (CView* view) {
|
|
MouseExitEvent exitEvent (event);
|
|
exitEvent.mousePosition = view->translateToLocal (exitEvent.mousePosition, true);
|
|
dispatchEvent (view, exitEvent);
|
|
callMouseObserverMouseExited (view);
|
|
#if DEBUG_MOUSE_VIEWS
|
|
DebugPrint ("mouseExited : %p[%d,%d]\n", view, (int)exitEvent.mousePosition.x,
|
|
(int)exitEvent.mousePosition.y);
|
|
#endif
|
|
};
|
|
|
|
auto callMouseEnterForView = [this, &event] (CView* view) {
|
|
MouseEnterEvent enterEvent (event);
|
|
enterEvent.mousePosition = view->translateToLocal (enterEvent.mousePosition, true);
|
|
dispatchEvent (view, enterEvent);
|
|
callMouseObserverMouseEntered (view);
|
|
#if DEBUG_MOUSE_VIEWS
|
|
DebugPrint ("mouseEntered : %p[%d,%d]\n", view, (int)enterEvent.mousePosition.x,
|
|
(int)enterEvent.mousePosition.y);
|
|
#endif
|
|
};
|
|
|
|
CViewContainer* vc = currentMouseView ? currentMouseView->asViewContainer () : nullptr;
|
|
// if the currentMouseView is not a view container, we know that the new mouseView won't be a child of it and that all other
|
|
// views in the list are viewcontainers
|
|
if (vc == nullptr && currentMouseView)
|
|
{
|
|
callMouseExitForView (currentMouseView);
|
|
currentMouseView->forget ();
|
|
pImpl->mouseViews.remove (currentMouseView);
|
|
}
|
|
auto it = pImpl->mouseViews.rbegin ();
|
|
while (it != pImpl->mouseViews.rend ())
|
|
{
|
|
vc = static_cast<CViewContainer*> ((*it));
|
|
if (vc == mouseView)
|
|
return;
|
|
if (vc->isChild (mouseView, true) == false)
|
|
{
|
|
callMouseExitForView (vc);
|
|
vc->forget ();
|
|
pImpl->mouseViews.erase (--it.base ());
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
vc = pImpl->mouseViews.empty () == false ? pImpl->mouseViews.back ()->asViewContainer () : nullptr;
|
|
if (vc)
|
|
{
|
|
auto it2 = pImpl->mouseViews.end ();
|
|
--it2;
|
|
CView* container = mouseView;
|
|
while ((vc = static_cast<CViewContainer*> (container->getParentView ())) != *it2 && vc)
|
|
{
|
|
pImpl->mouseViews.emplace_back (vc);
|
|
vc->remember ();
|
|
container = vc;
|
|
}
|
|
pImpl->mouseViews.emplace_back (mouseView);
|
|
mouseView->remember ();
|
|
++it2;
|
|
while (it2 != pImpl->mouseViews.end ())
|
|
{
|
|
callMouseEnterForView (*it2);
|
|
++it2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// must be pMouseViews.size () == 0
|
|
vstgui_assert (pImpl->mouseViews.empty ());
|
|
pImpl->mouseViews.emplace_back (mouseView);
|
|
mouseView->remember ();
|
|
while ((vc = static_cast<CViewContainer*> (mouseView->getParentView ())) != this && vc)
|
|
{
|
|
pImpl->mouseViews.push_front (vc);
|
|
vc->remember ();
|
|
mouseView = vc;
|
|
}
|
|
auto it2 = pImpl->mouseViews.begin ();
|
|
while (it2 != pImpl->mouseViews.end ())
|
|
{
|
|
callMouseEnterForView (*it2);
|
|
++it2;
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
bool CFrame::hitTestSubViews (const CPoint& where, const Event& event)
|
|
{
|
|
if (auto modalView = getModalView ())
|
|
{
|
|
CPoint where2 (where);
|
|
getTransform ().inverse ().transform (where2);
|
|
if (modalView->isVisible () && modalView->getMouseEnabled () && modalView->hitTest (where2, event))
|
|
{
|
|
if (auto viewContainer = modalView->asViewContainer ())
|
|
{
|
|
return viewContainer->hitTestSubViews (where2, event);
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
return CViewContainer::hitTestSubViews (where, event);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::dispatchEvent (CView* view, Event& event)
|
|
{
|
|
view->dispatchEvent (event);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::dispatchEventToChildren (Event& event)
|
|
{
|
|
CView::dispatchEvent (event);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::dispatchKeyboardEvent (KeyboardEvent& event)
|
|
{
|
|
if (static_cast<uint32_t> (event.virt) > static_cast<uint32_t> (VirtualKey::Equals))
|
|
event.virt = VirtualKey::None;
|
|
dispatchKeyboardEventToHooks (event);
|
|
if (event.consumed)
|
|
return;
|
|
|
|
if (pImpl->focusView)
|
|
{
|
|
CBaseObjectGuard og (pImpl->focusView);
|
|
if (pImpl->focusView->getMouseEnabled ())
|
|
dispatchEvent (pImpl->focusView, event);
|
|
if (event.consumed)
|
|
return;
|
|
CView* parent = pImpl->focusView->getParentView ();
|
|
while (parent && parent != this)
|
|
{
|
|
if (parent->getMouseEnabled ())
|
|
{
|
|
dispatchEvent (parent, event);
|
|
if (event.consumed)
|
|
return;
|
|
}
|
|
parent = parent->getParentView ();
|
|
}
|
|
}
|
|
if (auto modalView = getModalView ())
|
|
{
|
|
CBaseObjectGuard og (modalView);
|
|
dispatchEvent (modalView, event);
|
|
if (event.consumed)
|
|
return;
|
|
}
|
|
if (event.type != EventType::KeyUp && event.virt == VirtualKey::Tab)
|
|
{
|
|
if (event.modifiers.empty () || event.modifiers.is (ModifierKey::Shift))
|
|
{
|
|
if (advanceNextFocusView (pImpl->focusView, event.modifiers.is (ModifierKey::Shift)))
|
|
event.consumed = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
void CFrame::dispatchMouseDownEvent (MouseDownEvent& event)
|
|
{
|
|
auto originMousePosition = event.mousePosition;
|
|
auto transformedMousePosition = event.mousePosition;
|
|
getTransform ().inverse ().transform (transformedMousePosition);
|
|
if (auto tooltips = pImpl->tooltips)
|
|
tooltips->onMouseDown (transformedMousePosition);
|
|
|
|
event.mousePosition = transformedMousePosition;
|
|
callMouseObserverOtherMouseEvent (event);
|
|
if (event.consumed)
|
|
return;
|
|
event.mousePosition = originMousePosition;
|
|
|
|
setMouseDownView (nullptr);
|
|
if (pImpl->focusView && dynamic_cast<CTextEdit*> (pImpl->focusView))
|
|
setFocusView (nullptr);
|
|
|
|
if (auto modalView = shared (getModalView ()))
|
|
{
|
|
if (modalView->isVisible () && modalView->getMouseEnabled ())
|
|
{
|
|
event.mousePosition = transformedMousePosition;
|
|
#if VSTGUI_ENABLE_DEPRECATED_METHODS
|
|
auto buttonState = buttonStateFromMouseEvent (event);
|
|
auto result = modalView->callMouseListener (MouseListenerCall::MouseDown, event.mousePosition, buttonState);
|
|
if (result != kMouseEventNotHandled && result != kMouseEventNotImplemented)
|
|
{
|
|
event.consumed = true;
|
|
return;
|
|
}
|
|
#endif
|
|
dispatchEvent (modalView, event);
|
|
if (event.consumed)
|
|
setMouseDownView (modalView);
|
|
}
|
|
return;
|
|
}
|
|
dispatchEventToChildren (event);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
void CFrame::dispatchMouseMoveEvent (MouseMoveEvent& event)
|
|
{
|
|
auto originMousePosition = event.mousePosition;
|
|
auto transformedMousePosition = event.mousePosition;
|
|
getTransform ().inverse ().transform (transformedMousePosition);
|
|
|
|
if (auto tooltips = pImpl->tooltips)
|
|
tooltips->onMouseMoved (transformedMousePosition);
|
|
|
|
checkMouseViews (event);
|
|
|
|
event.mousePosition = transformedMousePosition;
|
|
callMouseObserverOtherMouseEvent (event);
|
|
if (event.consumed)
|
|
return;
|
|
event.mousePosition = originMousePosition;
|
|
|
|
if (auto modalView = shared (getModalView ()))
|
|
{
|
|
if (modalView->isVisible () && modalView->getMouseEnabled ())
|
|
{
|
|
event.mousePosition = transformedMousePosition;
|
|
#if VSTGUI_ENABLE_DEPRECATED_METHODS
|
|
auto buttonState = buttonStateFromMouseEvent (event);
|
|
auto result = modalView->callMouseListener (MouseListenerCall::MouseMoved, event.mousePosition, buttonState);
|
|
if (result != kMouseEventNotHandled && result != kMouseEventNotImplemented)
|
|
{
|
|
event.consumed = true;
|
|
return;
|
|
}
|
|
#endif
|
|
dispatchEvent (modalView, event);
|
|
}
|
|
}
|
|
else
|
|
dispatchEventToChildren (event);
|
|
if (event.consumed == false)
|
|
{
|
|
event.buttonState.clear ();
|
|
auto it = pImpl->mouseViews.rbegin ();
|
|
while (it != pImpl->mouseViews.rend ())
|
|
{
|
|
CPoint p (transformedMousePosition);
|
|
auto view = *it;
|
|
if (view->asViewContainer ())
|
|
{
|
|
if (auto parent = view->getParentView ())
|
|
{
|
|
if (parent != this)
|
|
{
|
|
p.offsetInverse (parent->getViewSize ().getTopLeft ());
|
|
parent->translateToLocal (p, true);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
view->translateToLocal (p, true);
|
|
event.mousePosition = p;
|
|
dispatchEvent (view, event);
|
|
if (event.consumed)
|
|
break;
|
|
++it;
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
void CFrame::dispatchMouseUpEvent (MouseUpEvent& event)
|
|
{
|
|
auto transformedMousePosition = event.mousePosition;
|
|
getTransform ().inverse ().transform (transformedMousePosition);
|
|
|
|
auto f = finally ([this] () { setMouseDownView (nullptr); });
|
|
|
|
callMouseObserverOtherMouseEvent (event);
|
|
if (event.consumed)
|
|
return;
|
|
|
|
if (auto modalView = shared (getModalView ()))
|
|
{
|
|
if (modalView->isVisible () && modalView->getMouseEnabled ())
|
|
{
|
|
event.mousePosition = transformedMousePosition;
|
|
#if VSTGUI_ENABLE_DEPRECATED_METHODS
|
|
auto buttonState = buttonStateFromMouseEvent (event);
|
|
auto result = modalView->callMouseListener (MouseListenerCall::MouseUp, event.mousePosition, buttonState);
|
|
if (result != kMouseEventNotHandled && result != kMouseEventNotImplemented)
|
|
{
|
|
event.consumed = true;
|
|
return;
|
|
}
|
|
#endif
|
|
dispatchEvent (modalView, event);
|
|
}
|
|
return;
|
|
}
|
|
dispatchEventToChildren (event);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
void CFrame::dispatchMouseEvent (MouseEvent& event)
|
|
{
|
|
if (event.type == EventType::MouseMove)
|
|
dispatchMouseMoveEvent (castMouseMoveEvent (event));
|
|
else if (event.type == EventType::MouseDown)
|
|
dispatchMouseDownEvent (castMouseDownEvent (event));
|
|
else if (event.type == EventType::MouseUp)
|
|
dispatchMouseUpEvent (castMouseUpEvent (event));
|
|
else if (event.type == EventType::MouseEnter)
|
|
{}
|
|
else if (event.type == EventType::MouseExit)
|
|
{
|
|
if (getMouseDownView () == nullptr)
|
|
{
|
|
clearMouseViews (event.mousePosition, event.modifiers);
|
|
if (pImpl->tooltips)
|
|
pImpl->tooltips->hideTooltip ();
|
|
}
|
|
event.consumed = true;
|
|
}
|
|
else
|
|
{
|
|
vstgui_assert (false);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::dispatchEvent (Event& event)
|
|
{
|
|
Impl::PostEventHandler peh (*pImpl);
|
|
CollectInvalidRects cir (this);
|
|
|
|
if (auto mouseEvent = asMouseEvent (event))
|
|
{
|
|
dispatchMouseEvent (*mouseEvent);
|
|
return;
|
|
}
|
|
if (auto keyEvent = asKeyboardEvent (event))
|
|
{
|
|
dispatchKeyboardEvent (*keyEvent);
|
|
return;
|
|
}
|
|
|
|
auto mousePosEvent = asMousePositionEvent (event);
|
|
CPoint mousePosition;
|
|
if (mousePosEvent)
|
|
mousePosition = mousePosEvent->mousePosition;
|
|
|
|
auto modalView = getModalView ();
|
|
if (modalView && mousePosEvent)
|
|
getTransform ().inverse ().transform (mousePosEvent->mousePosition);
|
|
|
|
if (modalView)
|
|
dispatchEvent (modalView, event);
|
|
else
|
|
dispatchEventToChildren (event);
|
|
|
|
if (mousePosEvent)
|
|
{
|
|
MouseEvent mouseEvent;
|
|
mouseEvent.mousePosition = mousePosEvent->mousePosition;
|
|
mouseEvent.modifiers = mousePosEvent->modifiers;
|
|
checkMouseViews (mouseEvent);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
SharedPointer<IDataPackage> CFrame::getClipboard ()
|
|
{
|
|
return getPlatformFactory ().getClipboard ();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::setClipboard (const SharedPointer<IDataPackage>& data)
|
|
{
|
|
getPlatformFactory ().setClipboard (data);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::idle ()
|
|
{
|
|
if (CView::kDirtyCallAlwaysOnMainThread)
|
|
return;
|
|
invalidateDirtyViews ();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
Animation::Animator* CFrame::getAnimator ()
|
|
{
|
|
if (pImpl->animator == nullptr)
|
|
pImpl->animator = makeOwned<Animation::Animator> ();
|
|
return pImpl->animator;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
* @return tick count in milliseconds
|
|
*/
|
|
uint64_t CFrame::getTicks () const
|
|
{
|
|
return getPlatformFactory ().getTicks ();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
int32_t CFrame::kDefaultKnobMode = kCircularMode;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
int32_t CFrame::getKnobMode () const
|
|
{
|
|
int32_t result = pImpl->editor ? pImpl->editor->getKnobMode () : -1;
|
|
if (result == -1)
|
|
result = kDefaultKnobMode;
|
|
return result;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
* repositions the frame
|
|
* @param x x coordinate
|
|
* @param y y coordinate
|
|
* @return true on success
|
|
*/
|
|
bool CFrame::setPosition (CCoord x, CCoord y)
|
|
{
|
|
if (pImpl->platformFrame)
|
|
{
|
|
CRect rect (getViewSize ());
|
|
rect.offset (x - getViewSize ().left, y - getViewSize ().top);
|
|
if (pImpl->platformFrame->setSize (rect))
|
|
{
|
|
setViewSize (rect, false);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
* get global position of frame
|
|
* @param x x coordinate
|
|
* @param y y coordinate
|
|
* @return true on success
|
|
*/
|
|
bool CFrame::getPosition (CCoord &x, CCoord &y) const
|
|
{
|
|
if (pImpl->platformFrame)
|
|
{
|
|
CPoint p;
|
|
if (pImpl->platformFrame->getGlobalPosition (p))
|
|
{
|
|
x = p.x;
|
|
y = p.y;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::setViewSize (const CRect& rect, bool invalid)
|
|
{
|
|
if (pImpl->lastCheckSizeConstraintLayout)
|
|
{
|
|
auto layout = std::move (*pImpl->lastCheckSizeConstraintLayout);
|
|
pImpl->lastCheckSizeConstraintLayout = {};
|
|
if (layout.size == rect)
|
|
{
|
|
if (applyViewLayout (layout))
|
|
return;
|
|
}
|
|
}
|
|
CViewContainer::setViewSize (rect, invalid);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
CPoint CFrame::checkSizeConstraint (const CPoint& newSize) const
|
|
{
|
|
pImpl->lastCheckSizeConstraintLayout = calculateViewLayout ({0., 0., newSize.x, newSize.y});
|
|
if (pImpl->lastCheckSizeConstraintLayout)
|
|
return pImpl->lastCheckSizeConstraintLayout->size.getSize ();
|
|
return getViewSize ().getSize ();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
* set size of frame (and the platform representation)
|
|
* @param width new width
|
|
* @param height new height
|
|
* @return true on success
|
|
*/
|
|
bool CFrame::setSize (CCoord width, CCoord height)
|
|
{
|
|
if ((width == getViewSize ().getWidth ()) && (height == getViewSize ().getHeight ()))
|
|
return true;
|
|
|
|
CRect newSize (getViewSize ());
|
|
newSize.setWidth (width);
|
|
newSize.setHeight (height);
|
|
|
|
if (getEditor ())
|
|
{
|
|
if (getEditor ()->beforeSizeChange (newSize, getViewSize ()) == false)
|
|
return false;
|
|
}
|
|
if (pImpl->platformFrame)
|
|
{
|
|
if (pImpl->platformFrame->setSize (newSize))
|
|
{
|
|
setViewSize (newSize);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
setViewSize (newSize);
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
* get size relative to parent
|
|
* @param pRect size
|
|
* @return true on success
|
|
*/
|
|
bool CFrame::getSize (CRect* pRect) const
|
|
{
|
|
if (pImpl->platformFrame && pRect)
|
|
return pImpl->platformFrame->getSize (*pRect);
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool CFrame::getSize (CRect& outSize) const
|
|
{
|
|
return getSize (&outSize);
|
|
}
|
|
|
|
#if VSTGUI_ENABLE_DEPRECATED_METHODS
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
* @param pView the view which should be set to modal.
|
|
* @return true if view could be set as the modal view. false if there is a already a modal view or the view to be set as modal is already attached.
|
|
*/
|
|
bool CFrame::setModalView (CView* pView)
|
|
{
|
|
if (pImpl->modalViewSessionStack.empty () && pView == nullptr)
|
|
return true;
|
|
|
|
if (pView && !pImpl->modalViewSessionStack.empty ())
|
|
return false;
|
|
|
|
if (!pView)
|
|
endLegacyModalViewSession ();
|
|
else
|
|
pImpl->legacyModalViewSessionID = beginModalViewSession (pView);
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::endLegacyModalViewSession ()
|
|
{
|
|
vstgui_assert (pImpl->legacyModalViewSessionID);
|
|
vstgui_assert (pImpl->modalViewSessionStack.top ().identifier ==
|
|
*pImpl->legacyModalViewSessionID);
|
|
pImpl->modalViewSessionStack.top ().view->remember ();
|
|
endModalViewSession (*pImpl->legacyModalViewSessionID);
|
|
pImpl->legacyModalViewSessionID = {};
|
|
}
|
|
|
|
#endif
|
|
|
|
//-----------------------------------------------------------------------------
|
|
CView* CFrame::getModalView () const
|
|
{
|
|
if (!pImpl->modalViewSessionStack.empty ())
|
|
return pImpl->modalViewSessionStack.top ().view;
|
|
return nullptr;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::initModalViewSession (const ModalViewSession& session)
|
|
{
|
|
if (getMouseDownView ())
|
|
{
|
|
onMouseCancel ();
|
|
}
|
|
clearMouseViews (CPoint (0, 0), Modifiers (), true);
|
|
if (auto container = session.view->asViewContainer ())
|
|
container->advanceNextFocusView (nullptr, false);
|
|
else
|
|
setFocusView (session.view->wantsFocus () ? session.view : nullptr);
|
|
|
|
if (isAttached ())
|
|
{
|
|
CPoint where;
|
|
getCurrentMouseLocation (where);
|
|
MouseEvent mouseEvent;
|
|
mouseEvent.mousePosition = where;
|
|
// TODO: modifiers and mouse button state
|
|
checkMouseViews (mouseEvent);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::clearModalViewSessions ()
|
|
{
|
|
#if VSTGUI_ENABLE_DEPRECATED_METHODS
|
|
if (pImpl->legacyModalViewSessionID)
|
|
endLegacyModalViewSession ();
|
|
#endif
|
|
while (!pImpl->modalViewSessionStack.empty ())
|
|
endModalViewSession (pImpl->modalViewSessionStack.top ().identifier);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
Optional<ModalViewSessionID> CFrame::beginModalViewSession (CView* view)
|
|
{
|
|
if (view->isAttached ())
|
|
{
|
|
#if DEBUG
|
|
DebugPrint ("the view must not be attached when used for beginModalViewSession");
|
|
#endif
|
|
return {};
|
|
}
|
|
|
|
if (!addView (view))
|
|
{
|
|
return {};
|
|
}
|
|
|
|
ModalViewSession session;
|
|
session.identifier = ++pImpl->modalViewSessionIDCounter;
|
|
session.view = view;
|
|
pImpl->modalViewSessionStack.push (session);
|
|
|
|
initModalViewSession (session);
|
|
|
|
return makeOptional (session.identifier);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool CFrame::endModalViewSession (ModalViewSessionID sessionID)
|
|
{
|
|
if (pImpl->modalViewSessionStack.empty ())
|
|
return false;
|
|
if (pImpl->modalViewSessionStack.top ().identifier != sessionID)
|
|
return false;
|
|
|
|
auto view = pImpl->modalViewSessionStack.top ().view;
|
|
pImpl->modalViewSessionStack.pop ();
|
|
|
|
removeView (view);
|
|
|
|
if (!pImpl->modalViewSessionStack.empty ())
|
|
initModalViewSession (pImpl->modalViewSessionStack.top ());
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::beginEdit (int32_t index)
|
|
{
|
|
if (pImpl->editor)
|
|
pImpl->editor->beginEdit (index);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::endEdit (int32_t index)
|
|
{
|
|
if (pImpl->editor)
|
|
pImpl->editor->endEdit (index);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
* @param where location of mouse
|
|
* @return true on success
|
|
*/
|
|
bool CFrame::getCurrentMouseLocation (CPoint &where) const
|
|
{
|
|
if (pImpl->platformFrame)
|
|
{
|
|
if (pImpl->platformFrame->getCurrentMousePosition (where))
|
|
{
|
|
getTransform().transform (where);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
* @return mouse and modifier state
|
|
*/
|
|
CButtonState CFrame::getCurrentMouseButtons () const
|
|
{
|
|
CButtonState buttons = 0;
|
|
|
|
if (pImpl->platformFrame)
|
|
pImpl->platformFrame->getCurrentMouseButtons (buttons);
|
|
|
|
return buttons;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
* @param type cursor type see #CCursorType
|
|
*/
|
|
void CFrame::setCursor (CCursorType type)
|
|
{
|
|
if (pImpl->platformFrame)
|
|
pImpl->platformFrame->setMouseCursor (type);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
* @param pView view which was removed
|
|
*/
|
|
void CFrame::onViewRemoved (CView* pView)
|
|
{
|
|
removeFromMouseViews (pView);
|
|
|
|
if (pImpl->activeFocusView == pView)
|
|
pImpl->activeFocusView = nullptr;
|
|
if (pImpl->focusView == pView)
|
|
{
|
|
if (pImpl->active)
|
|
setFocusView (nullptr);
|
|
else
|
|
pImpl->focusView = nullptr;
|
|
}
|
|
if (auto container = pView->asViewContainer ())
|
|
{
|
|
if (container->isChild (pImpl->focusView, true))
|
|
setFocusView (nullptr);
|
|
}
|
|
if (getViewAddedRemovedObserver ())
|
|
getViewAddedRemovedObserver ()->onViewRemoved (this, pView);
|
|
if (pView->wantsWindowActiveStateChangeNotification ())
|
|
pImpl->windowActiveStateChangeViews.remove (pView);
|
|
if (pImpl->animator)
|
|
pImpl->animator->removeAnimations (pView);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
* @param pView view which was added
|
|
*/
|
|
void CFrame::onViewAdded (CView* pView)
|
|
{
|
|
if (getViewAddedRemovedObserver ())
|
|
getViewAddedRemovedObserver ()->onViewAdded (this, pView);
|
|
if (pView->wantsWindowActiveStateChangeNotification ())
|
|
{
|
|
pImpl->windowActiveStateChangeViews.add (pView);
|
|
pView->onWindowActivate (pImpl->windowActive);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
* @param pView new focus view
|
|
*/
|
|
void CFrame::setFocusView (CView *pView)
|
|
{
|
|
static bool recursion = false;
|
|
if (pView == pImpl->focusView || (recursion && pImpl->focusView != nullptr))
|
|
return;
|
|
|
|
if (pView && !pImpl->modalViewSessionStack.empty ())
|
|
{
|
|
if (auto modalContainer = pImpl->modalViewSessionStack.top ().view->asViewContainer ())
|
|
{
|
|
if (!modalContainer->isChild (pView, true))
|
|
{
|
|
#if DEBUG
|
|
DebugPrint (
|
|
"Could not set the focus view " \
|
|
"as it is not a child of the currently displayed modal view\n");
|
|
#endif
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!pImpl->active)
|
|
{
|
|
pImpl->activeFocusView = pView;
|
|
return;
|
|
}
|
|
|
|
recursion = true;
|
|
|
|
CView *pOldFocusView = pImpl->focusView;
|
|
if (pView == nullptr || (pView && pView->isAttached () == false))
|
|
pImpl->focusView = nullptr;
|
|
else
|
|
pImpl->focusView = pView;
|
|
if (pImpl->focusView && pImpl->focusView->wantsFocus ())
|
|
{
|
|
pImpl->focusView->invalid ();
|
|
|
|
CView* receiver = pImpl->focusView->getParentView ();
|
|
while (receiver != this && receiver != nullptr)
|
|
{
|
|
receiver->notify (pImpl->focusView, kMsgNewFocusView);
|
|
receiver = receiver->getParentView ();
|
|
}
|
|
notify (pImpl->focusView, kMsgNewFocusView);
|
|
}
|
|
|
|
if (pOldFocusView)
|
|
{
|
|
if (pOldFocusView->wantsFocus ())
|
|
{
|
|
pOldFocusView->invalid ();
|
|
|
|
CView* receiver = pOldFocusView->getParentView ();
|
|
while (receiver != this && receiver != nullptr)
|
|
{
|
|
receiver->notify (pOldFocusView, kMsgOldFocusView);
|
|
receiver = receiver->getParentView ();
|
|
}
|
|
notify (pOldFocusView, kMsgOldFocusView);
|
|
}
|
|
pOldFocusView->looseFocus ();
|
|
}
|
|
if (pImpl->focusView && pImpl->focusView->wantsFocus ())
|
|
pImpl->focusView->takeFocus ();
|
|
|
|
pImpl->focusViewObservers.forEach ([&] (IFocusViewObserver* observer) {
|
|
observer->onFocusViewChanged (this, pImpl->focusView, pOldFocusView);
|
|
});
|
|
|
|
recursion = false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
CView* CFrame::getFocusView () const
|
|
{
|
|
return pImpl->focusView;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool CFrame::advanceNextFocusView (CView* oldFocus, bool reverse)
|
|
{
|
|
if (auto modalView = getModalView ())
|
|
{
|
|
if (auto container = modalView->asViewContainer ())
|
|
{
|
|
if (oldFocus == nullptr || container->isChild (oldFocus, true) == false)
|
|
return container->advanceNextFocusView (nullptr, reverse);
|
|
else
|
|
{
|
|
if (auto* parentView = static_cast<CViewContainer*> (oldFocus->getParentView ()))
|
|
{
|
|
CView* tempOldFocus = oldFocus;
|
|
while (parentView != container)
|
|
{
|
|
if (parentView->advanceNextFocusView (tempOldFocus, reverse))
|
|
return true;
|
|
else
|
|
{
|
|
tempOldFocus = parentView;
|
|
parentView = static_cast<CViewContainer*> (parentView->getParentView ());
|
|
}
|
|
}
|
|
if (container->advanceNextFocusView (tempOldFocus, reverse))
|
|
return true;
|
|
return container->advanceNextFocusView (nullptr, reverse);
|
|
}
|
|
}
|
|
}
|
|
else if (oldFocus != modalView)
|
|
{
|
|
setFocusView (modalView);
|
|
return true;
|
|
}
|
|
return false; // currently not supported, but should be done sometime
|
|
}
|
|
if (oldFocus == nullptr)
|
|
{
|
|
if (pImpl->focusView == nullptr)
|
|
return CViewContainer::advanceNextFocusView (nullptr, reverse);
|
|
oldFocus = pImpl->focusView;
|
|
}
|
|
if (isChild (oldFocus))
|
|
{
|
|
if (CViewContainer::advanceNextFocusView (oldFocus, reverse))
|
|
return true;
|
|
else
|
|
{
|
|
setFocusView (nullptr);
|
|
return false;
|
|
}
|
|
}
|
|
if (auto* parentView = static_cast<CViewContainer*> (oldFocus->getParentView ()))
|
|
{
|
|
CView* tempOldFocus = oldFocus;
|
|
while (parentView)
|
|
{
|
|
if (parentView->advanceNextFocusView (tempOldFocus, reverse))
|
|
return true;
|
|
else
|
|
{
|
|
tempOldFocus = parentView;
|
|
parentView = static_cast<CViewContainer*> (parentView->getParentView ());
|
|
}
|
|
}
|
|
}
|
|
return CViewContainer::advanceNextFocusView (oldFocus, reverse);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool CFrame::removeView (CView* pView, bool withForget)
|
|
{
|
|
#if DEBUG
|
|
vstgui_assert (getModalView () != pView);
|
|
#endif
|
|
return CViewContainer::removeView (pView, withForget);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool CFrame::removeAll (bool withForget)
|
|
{
|
|
clearModalViewSessions ();
|
|
if (pImpl->focusView)
|
|
{
|
|
pImpl->focusView->looseFocus ();
|
|
pImpl->focusView = nullptr;
|
|
}
|
|
pImpl->activeFocusView = nullptr;
|
|
clearMouseViews (CPoint (0, 0), Modifiers (), false);
|
|
return CViewContainer::removeAll (withForget);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
CView* CFrame::getViewAt (const CPoint& where, const GetViewOptions& options) const
|
|
{
|
|
if (auto modalView = getModalView ())
|
|
{
|
|
CPoint where2 (where);
|
|
getTransform ().inverse ().transform (where2);
|
|
if (modalView->getViewSize ().pointInside (where2))
|
|
{
|
|
if (options.getDeep ())
|
|
{
|
|
if (auto container = modalView->asViewContainer ())
|
|
{
|
|
return container->getViewAt (where2, options);
|
|
}
|
|
}
|
|
return modalView;
|
|
}
|
|
return nullptr;
|
|
}
|
|
return CViewContainer::getViewAt (where, options);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
CViewContainer* CFrame::getContainerAt (const CPoint& where, const GetViewOptions& options) const
|
|
{
|
|
if (auto modalView = getModalView ())
|
|
{
|
|
CPoint where2 (where);
|
|
getTransform ().inverse ().transform (where2);
|
|
if (modalView->getViewSize ().pointInside (where2))
|
|
{
|
|
if (auto container = modalView->asViewContainer ())
|
|
{
|
|
if (options.getDeep ())
|
|
return container->getContainerAt (where2, options);
|
|
return container;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
return CViewContainer::getContainerAt (where, options);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
bool CFrame::getViewsAt (const CPoint& where, ViewList& views, const GetViewOptions& options) const
|
|
{
|
|
if (auto modalView = getModalView ())
|
|
{
|
|
CPoint where2 (where);
|
|
getTransform ().inverse ().transform (where2);
|
|
if (modalView->getViewSize ().pointInside (where2))
|
|
{
|
|
if (options.getDeep ())
|
|
{
|
|
if (auto container = modalView->asViewContainer ())
|
|
{
|
|
container->getViewsAt (where2, views, options);
|
|
}
|
|
}
|
|
if (!options.getIncludeViewContainer () && modalView->asViewContainer ())
|
|
return true;
|
|
if (options.getMouseEnabled () && modalView->getMouseEnabled () == false)
|
|
return true;
|
|
if (!options.getIncludeInvisible () && !modalView->isVisible ())
|
|
return true;
|
|
views.emplace_back (modalView);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
return CViewContainer::getViewsAt (where, views, options);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::onActivate (bool state)
|
|
{
|
|
if (pImpl->active != state)
|
|
{
|
|
if (state)
|
|
{
|
|
pImpl->active = true;
|
|
if (pImpl->activeFocusView)
|
|
{
|
|
setFocusView (pImpl->activeFocusView);
|
|
pImpl->activeFocusView = nullptr;
|
|
}
|
|
else
|
|
advanceNextFocusView (nullptr, false);
|
|
}
|
|
else
|
|
{
|
|
if (pImpl->tooltips)
|
|
pImpl->tooltips->hideTooltip ();
|
|
pImpl->activeFocusView = getFocusView ();
|
|
setFocusView (nullptr);
|
|
pImpl->active = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool CFrame::focusDrawingEnabled () const
|
|
{
|
|
uint32_t attrSize;
|
|
if (getAttributeSize ('vfde', attrSize))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
CColor CFrame::getFocusColor () const
|
|
{
|
|
CColor focusColor (kRedCColor);
|
|
getAttribute ('vfco', focusColor);
|
|
return focusColor;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
CCoord CFrame::getFocusWidth () const
|
|
{
|
|
CCoord focusWidth = 2;
|
|
getAttribute ('vfwi', focusWidth);
|
|
return focusWidth;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::setFocusDrawingEnabled (bool state)
|
|
{
|
|
if (state)
|
|
setAttribute ('vfde', state);
|
|
else
|
|
removeAttribute ('vfde');
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::setFocusColor (const CColor& color)
|
|
{
|
|
setAttribute ('vfco', color);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::setFocusWidth (CCoord width)
|
|
{
|
|
setAttribute ('vfwi', width);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/**
|
|
* @param src rect which to scroll
|
|
* @param distance point of distance
|
|
*/
|
|
void CFrame::scrollRect (const CRect& src, const CPoint& distance)
|
|
{
|
|
CRect rect (src);
|
|
rect.offset (getViewSize ().left, getViewSize ().top);
|
|
|
|
if (pImpl->platformFrame)
|
|
{
|
|
if (pImpl->platformFrame->scrollRect (src, distance))
|
|
return;
|
|
}
|
|
invalidRect (src);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::invalidate (const CRect &rect)
|
|
{
|
|
for (const auto& pV : getChildren ())
|
|
{
|
|
CRect rectView = pV->getViewSize ();
|
|
if (rect.rectOverlap (rectView))
|
|
pV->setDirty (true);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::invalidRect (const CRect& rect)
|
|
{
|
|
if (!isVisible () || !pImpl->platformFrame)
|
|
return;
|
|
|
|
CRect _rect (rect);
|
|
getTransform ().transform (_rect);
|
|
_rect.makeIntegral ();
|
|
if (pImpl->collectInvalidRects)
|
|
pImpl->collectInvalidRects->addRect (_rect);
|
|
else
|
|
pImpl->platformFrame->invalidRect (_rect);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
IViewAddedRemovedObserver* CFrame::getViewAddedRemovedObserver () const
|
|
{
|
|
return pImpl->viewAddedRemovedObserver;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::setViewAddedRemovedObserver (IViewAddedRemovedObserver* observer)
|
|
{
|
|
pImpl->viewAddedRemovedObserver = observer;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::registerKeyboardHook (IKeyboardHook* hook)
|
|
{
|
|
pImpl->keyboardHooks.add (hook);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::unregisterKeyboardHook (IKeyboardHook* hook)
|
|
{
|
|
pImpl->keyboardHooks.remove (hook);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::dispatchKeyboardEventToHooks (KeyboardEvent& event)
|
|
{
|
|
pImpl->keyboardHooks.forEachReverse (
|
|
[&] (IKeyboardHook* hook) {
|
|
hook->onKeyboardEvent (event, this);
|
|
return event.consumed;
|
|
},
|
|
[] (bool consumed) { return consumed; });
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::registerScaleFactorChangedListener (IScaleFactorChangedListener* listener)
|
|
{
|
|
pImpl->scaleFactorChangedListenerList.add (listener);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::unregisterScaleFactorChangedListener (IScaleFactorChangedListener* listener)
|
|
{
|
|
pImpl->scaleFactorChangedListenerList.remove (listener);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::registerMouseObserver (IMouseObserver* observer)
|
|
{
|
|
pImpl->mouseObservers.add (observer);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::registerFocusViewObserver (IFocusViewObserver* observer)
|
|
{
|
|
pImpl->focusViewObservers.add (observer);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::unregisterFocusViewObserver (IFocusViewObserver* observer)
|
|
{
|
|
pImpl->focusViewObservers.remove (observer);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::unregisterMouseObserver (IMouseObserver* observer)
|
|
{
|
|
pImpl->mouseObservers.remove (observer);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::callMouseObserverMouseEntered (CView* view)
|
|
{
|
|
#if VSTGUI_ENABLE_DEPRECATED_METHODS
|
|
view->callMouseListenerEnteredExited (true);
|
|
#endif
|
|
pImpl->mouseObservers.forEach ([&] (IMouseObserver* observer) {
|
|
observer->onMouseEntered (view, this);
|
|
});
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::callMouseObserverMouseExited (CView* view)
|
|
{
|
|
pImpl->mouseObservers.forEach ([&] (IMouseObserver* observer) {
|
|
observer->onMouseExited (view, this);
|
|
});
|
|
#if VSTGUI_ENABLE_DEPRECATED_METHODS
|
|
view->callMouseListenerEnteredExited (false);
|
|
#endif
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::callMouseObserverOtherMouseEvent (MouseEvent& event)
|
|
{
|
|
pImpl->mouseObservers.forEach (
|
|
[&] (IMouseObserver* observer) { observer->onMouseEvent (event, this); });
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
bool CFrame::performDrag (const DragDescription& desc, const SharedPointer<IDragCallback>& callback)
|
|
{
|
|
if (auto platformFrame = getPlatformFrame ())
|
|
{
|
|
if (platformFrame->doDrag (desc, callback))
|
|
{
|
|
setMouseDownView (nullptr);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
#if DEBUG
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::dumpHierarchy ()
|
|
{
|
|
dumpInfo ();
|
|
DebugPrint ("\n");
|
|
CViewContainer::dumpHierarchy ();
|
|
}
|
|
#endif
|
|
|
|
//-----------------------------------------------------------------------------
|
|
VSTGUIEditorInterface* CFrame::getEditor () const
|
|
{
|
|
return pImpl->editor;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
IPlatformFrame* CFrame::getPlatformFrame () const
|
|
{
|
|
return pImpl->platformFrame;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::platformDrawRects (const PlatformGraphicsDeviceContextPtr& context, double scaleFactor,
|
|
const std::vector<CRect>& rects)
|
|
{
|
|
CDrawContext drawContext (context, getViewSize (), scaleFactor);
|
|
for (auto rect : rects)
|
|
drawRect (&drawContext, rect);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::platformOnEvent (Event& event)
|
|
{
|
|
dispatchEvent (event);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
DragOperation CFrame::platformOnDragEnter (DragEventData data)
|
|
{
|
|
if (!getMouseEnabled ())
|
|
return DragOperation::None;
|
|
Impl::PostEventHandler peh (*pImpl);
|
|
CollectInvalidRects cir (this);
|
|
return getDropTarget ()->onDragEnter (data);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
DragOperation CFrame::platformOnDragMove (DragEventData data)
|
|
{
|
|
if (!getMouseEnabled ())
|
|
return DragOperation::None;
|
|
Impl::PostEventHandler peh (*pImpl);
|
|
CollectInvalidRects cir (this);
|
|
return getDropTarget ()->onDragMove (data);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::platformOnDragLeave (DragEventData data)
|
|
{
|
|
if (!getMouseEnabled ())
|
|
return;
|
|
Impl::PostEventHandler peh (*pImpl);
|
|
CollectInvalidRects cir (this);
|
|
getDropTarget ()->onDragLeave (data);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool CFrame::platformOnDrop (DragEventData data)
|
|
{
|
|
if (!getMouseEnabled ())
|
|
return false;
|
|
Impl::PostEventHandler peh (*pImpl);
|
|
CollectInvalidRects cir (this);
|
|
return getDropTarget ()->onDrop (data);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::platformOnActivate (bool state)
|
|
{
|
|
if (getFrame ())
|
|
{
|
|
CollectInvalidRects cir (this);
|
|
onActivate (state);
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
void CFrame::platformOnWindowActivate (bool state)
|
|
{
|
|
if (pImpl->windowActive == state)
|
|
return;
|
|
pImpl->windowActive = state;
|
|
CollectInvalidRects cir (this);
|
|
pImpl->windowActiveStateChangeViews.forEach ([&] (CView* view) {
|
|
view->onWindowActivate (state);
|
|
});
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::platformScaleFactorChanged (double newScaleFactor)
|
|
{
|
|
if (pImpl->platformScaleFactor == newScaleFactor)
|
|
return;
|
|
pImpl->platformScaleFactor = newScaleFactor;
|
|
dispatchNewScaleFactor (getScaleFactor ());
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::dispatchNewScaleFactor (double newScaleFactor)
|
|
{
|
|
pImpl->scaleFactorChangedListenerList.forEach ([&] (IScaleFactorChangedListener* listener) {
|
|
listener->onScaleFactorChanged (this, newScaleFactor);
|
|
});
|
|
}
|
|
|
|
#if VSTGUI_TOUCH_EVENT_HANDLING
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::platformOnTouchEvent (ITouchEvent& event)
|
|
{
|
|
Impl::PostEventHandler peh (*pImpl);
|
|
std::vector<CView*> targetDispatched;
|
|
bool hasBeganTouch = false;
|
|
for (const auto& e : event)
|
|
{
|
|
CView* target = e.second.target;
|
|
if (target)
|
|
{
|
|
if (e.second.targetIsSingleTouch)
|
|
{
|
|
CPoint where (e.second.location);
|
|
target->frameToLocal (where);
|
|
switch (e.second.state)
|
|
{
|
|
case ITouchEvent::kMoved:
|
|
{
|
|
MouseMoveEvent moveEvent (where, MouseButton::Left);
|
|
dispatchEvent (target, moveEvent);
|
|
if (moveEvent.ignoreFollowUpMoveAndUpEvents ())
|
|
{
|
|
event.unsetTouchTarget (e.first, target);
|
|
MouseMoveEvent mouseMoveEvent (where, MouseButton::Left);
|
|
if (target->hitTest (where, mouseMoveEvent) == false)
|
|
{
|
|
// when the touch goes out of the target and it tells us to
|
|
const_cast<ITouchEvent::Touch&> (e.second).state =
|
|
ITouchEvent::kBegan;
|
|
hasBeganTouch = true;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case ITouchEvent::kCanceled:
|
|
{
|
|
MouseCancelEvent cancelEvent;
|
|
dispatchEvent (target, cancelEvent);
|
|
if (cancelEvent.consumed == false)
|
|
{
|
|
MouseUpEvent upEvent (where, MouseButton::Left);
|
|
dispatchEvent (target, upEvent);
|
|
}
|
|
event.unsetTouchTarget (e.first, target);
|
|
break;
|
|
}
|
|
case ITouchEvent::kEnded:
|
|
{
|
|
MouseUpEvent upEvent (where, MouseButton::Left);
|
|
dispatchEvent (target, upEvent);
|
|
event.unsetTouchTarget (e.first, target);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
// do nothing
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (std::find (targetDispatched.begin (), targetDispatched.end (), target) ==
|
|
targetDispatched.end ())
|
|
{
|
|
target->onTouchEvent (event);
|
|
targetDispatched.emplace_back (target);
|
|
}
|
|
}
|
|
}
|
|
else if (e.second.state == ITouchEvent::kBegan)
|
|
{
|
|
hasBeganTouch = true;
|
|
}
|
|
}
|
|
if (hasBeganTouch)
|
|
{
|
|
if (CView* focusView = getFocusView ())
|
|
{
|
|
if (dynamic_cast<CTextEdit*> (focusView))
|
|
setFocusView (nullptr);
|
|
}
|
|
for (const auto& e : event)
|
|
{
|
|
if (e.second.target == nullptr && e.second.state == ITouchEvent::kBegan)
|
|
{
|
|
findSingleTouchEventTarget (const_cast<ITouchEvent::Touch&> (e.second));
|
|
}
|
|
}
|
|
onTouchEvent (event);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool CFrame::doAfterEventProcessing (EventProcessingFunction&& func)
|
|
{
|
|
if (pImpl->inEventHandling)
|
|
pImpl->postEventFunctionQueue.push (std::move (func));
|
|
return pImpl->inEventHandling;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool CFrame::doAfterEventProcessing (const EventProcessingFunction& func)
|
|
{
|
|
if (pImpl->inEventHandling)
|
|
pImpl->postEventFunctionQueue.push (func);
|
|
return pImpl->inEventHandling;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool CFrame::inEventProcessing () const
|
|
{
|
|
return pImpl->inEventHandling;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::onStartLocalEventLoop ()
|
|
{
|
|
if (pImpl->collectInvalidRects)
|
|
{
|
|
pImpl->collectInvalidRects->flush ();
|
|
pImpl->collectInvalidRects = nullptr;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::setCollectInvalidRects (CollectInvalidRects* cir)
|
|
{
|
|
if (pImpl->collectInvalidRects)
|
|
pImpl->collectInvalidRects->flush ();
|
|
pImpl->collectInvalidRects = cir;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
CFrame::CollectInvalidRects::CollectInvalidRects (CFrame* frame)
|
|
: frame (frame)
|
|
, lastTicks (frame->getTicks ())
|
|
{
|
|
#if VSTGUI_LOG_COLLECT_INVALID_RECTS
|
|
numAddedRects = 0;
|
|
#endif
|
|
frame->setCollectInvalidRects (this);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
CFrame::CollectInvalidRects::~CollectInvalidRects () noexcept
|
|
{
|
|
frame->setCollectInvalidRects (nullptr);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::CollectInvalidRects::flush ()
|
|
{
|
|
if (!invalidRects.data ().empty ())
|
|
{
|
|
if (frame->isVisible () && frame->pImpl->platformFrame)
|
|
{
|
|
for (auto& rect : invalidRects)
|
|
frame->pImpl->platformFrame->invalidRect (rect);
|
|
#if VSTGUI_LOG_COLLECT_INVALID_RECTS
|
|
DebugPrint ("%d -> %d\n", numAddedRects, invalidRects.size ());
|
|
numAddedRects = 0;
|
|
#endif
|
|
}
|
|
invalidRects.clear ();
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void CFrame::CollectInvalidRects::addRect (const CRect& rect)
|
|
{
|
|
#if VSTGUI_LOG_COLLECT_INVALID_RECTS
|
|
numAddedRects++;
|
|
#endif
|
|
invalidRects.add (rect);
|
|
auto now = frame->getTicks ();
|
|
if (now - lastTicks > 16)
|
|
{
|
|
flush ();
|
|
lastTicks = now;
|
|
}
|
|
}
|
|
|
|
#if VSTGUI_ENABLE_DEPRECATED_METHODS
|
|
//-----------------------------------------------------------------------------
|
|
void OldMouseObserverAdapter::onMouseEvent (MouseEvent& event, CFrame* frame)
|
|
{
|
|
if (event.type == EventType::MouseDown)
|
|
{
|
|
auto res = onMouseDown (frame, event.mousePosition, buttonStateFromMouseEvent (event));
|
|
if (res == kMouseEventHandled)
|
|
event.consumed = true;
|
|
if (res == kMouseDownEventHandledButDontNeedMovedOrUpEvents)
|
|
{
|
|
event.consumed = true;
|
|
castMouseDownEvent (event).ignoreFollowUpMoveAndUpEvents (true);
|
|
}
|
|
}
|
|
else if (event.type == EventType::MouseMove)
|
|
{
|
|
auto res = onMouseMoved (frame, event.mousePosition, buttonStateFromMouseEvent (event));
|
|
if (res == kMouseEventHandled)
|
|
event.consumed = true;
|
|
if (res == kMouseMoveEventHandledButDontNeedMoreEvents)
|
|
{
|
|
event.consumed = true;
|
|
castMouseMoveEvent (event).ignoreFollowUpMoveAndUpEvents (true);
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
CMouseEventResult OldMouseObserverAdapter::onMouseMoved (CFrame* frame, const CPoint& where, const CButtonState& buttons)
|
|
{
|
|
return kMouseEventNotHandled;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
CMouseEventResult OldMouseObserverAdapter::onMouseDown (CFrame* frame, const CPoint& where, const CButtonState& buttons)
|
|
{
|
|
return kMouseEventNotHandled;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void OldKeyboardHookAdapter::onKeyboardEvent (KeyboardEvent& event, CFrame* frame)
|
|
{
|
|
auto vstKeyCode = toVstKeyCode (event);
|
|
if (event.type == EventType::KeyDown)
|
|
{
|
|
if (onKeyDown (vstKeyCode, frame) != -1)
|
|
event.consumed = true;
|
|
}
|
|
else
|
|
{
|
|
if (onKeyUp (vstKeyCode, frame) != -1)
|
|
event.consumed = true;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
} // VSTGUI
|