Browse Source

Added method Component::mouseMagnify(), to respond to pinch-to-zoom gestures. Supported in OSX and (untested) Windows.

tags/2021-05-28
jules 12 years ago
parent
commit
7bc0cf13b1
9 changed files with 192 additions and 31 deletions
  1. +10
    -5
      extras/JuceDemo/Source/demos/RenderingTestComponent.cpp
  2. +18
    -0
      modules/juce_gui_basics/components/juce_Component.cpp
  3. +13
    -0
      modules/juce_gui_basics/components/juce_Component.h
  4. +49
    -16
      modules/juce_gui_basics/mouse/juce_MouseInputSource.cpp
  5. +4
    -2
      modules/juce_gui_basics/mouse/juce_MouseInputSource.h
  6. +10
    -0
      modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm
  7. +80
    -8
      modules/juce_gui_basics/native/juce_win32_Windowing.cpp
  8. +7
    -0
      modules/juce_gui_basics/windows/juce_ComponentPeer.cpp
  9. +1
    -0
      modules/juce_gui_basics/windows/juce_ComponentPeer.h

+ 10
- 5
extras/JuceDemo/Source/demos/RenderingTestComponent.cpp View File

@@ -138,6 +138,11 @@ public:
}
}
void mouseMagnify (const MouseEvent&, float zoomFactor)
{
owner.sizeSlider->setValue (owner.sizeSlider->getValue() * zoomFactor);
}
private:
RenderingTestComponent& owner;
double averageTime;
@@ -151,13 +156,13 @@ private:
float speeds[8];
Time lastSVGLoadTime;
const AffineTransform getTransform()
AffineTransform getTransform()
{
return AffineTransform::rotation ((float) owner.angleSlider->getValue() / (180.0f / float_Pi))
.scaled ((float) owner.sizeSlider->getValue(),
(float) owner.sizeSlider->getValue())
.translated (getWidth() / 2 + (float) owner.xSlider->getValue(),
getHeight() / 2 + (float) owner.ySlider->getValue());
.scaled ((float) owner.sizeSlider->getValue(),
(float) owner.sizeSlider->getValue())
.translated (getWidth() / 2 + (float) owner.xSlider->getValue(),
getHeight() / 2 + (float) owner.ySlider->getValue());
}
void clipToRectangle (Graphics& g)


+ 18
- 0
modules/juce_gui_basics/components/juce_Component.cpp View File

@@ -2151,6 +2151,12 @@ void Component::mouseWheelMove (const MouseEvent& e, const MouseWheelDetails& wh
parentComponent->mouseWheelMove (e.getEventRelativeTo (parentComponent), wheel);
}
void Component::mouseMagnify (const MouseEvent& e, float magnifyAmount)
{
// the base class just passes this event up to its parent..
if (parentComponent != nullptr)
parentComponent->mouseMagnify (e.getEventRelativeTo (parentComponent), magnifyAmount);
}
//==============================================================================
void Component::resized() {}
@@ -2477,6 +2483,18 @@ void Component::internalMouseWheel (MouseInputSource& source, const Point<int>&
}
}
void Component::internalMagnifyGesture (MouseInputSource& source, const Point<int>& relativePos,
const Time& time, float amount)
{
if (! isCurrentlyBlockedByAnotherModalComponent())
{
const MouseEvent me (source, relativePos, source.getCurrentModifiers(),
this, this, time, relativePos, time, 0, false);
mouseMagnify (me, amount);
}
}
void Component::sendFakeMouseMove() const
{
MouseInputSource& mainMouse = Desktop::getInstance().getMainMouseSource();


+ 13
- 0
modules/juce_gui_basics/components/juce_Component.h View File

@@ -1559,6 +1559,18 @@ public:
virtual void mouseWheelMove (const MouseEvent& event,
const MouseWheelDetails& wheel);
/** Called when a pinch-to-zoom mouse-gesture is used.
If not overridden, a component will forward this message to its parent, so
that parent components can collect gesture messages that are unused by child
components.
@param scaleFactor a multiplier to indicate by how much the size of the target
should be changed. A value of 1.0 would indicate no change,
values greater than 1.0 mean it should be enlarged.
*/
virtual void mouseMagnify (const MouseEvent& event, float scaleFactor);
//==============================================================================
/** Ensures that a non-stop stream of mouse-drag events will be sent during the
current mouse-drag operation.
@@ -2281,6 +2293,7 @@ private:
void internalMouseDrag (MouseInputSource&, const Point<int>&, const Time&);
void internalMouseMove (MouseInputSource&, const Point<int>&, const Time&);
void internalMouseWheel (MouseInputSource&, const Point<int>&, const Time&, const MouseWheelDetails&);
void internalMagnifyGesture (MouseInputSource&, const Point<int>&, const Time&, float);
void internalBroughtToFront();
void internalFocusGain (const FocusChangeType, const WeakReference<Component>&);
void internalFocusGain (const FocusChangeType);


+ 49
- 16
modules/juce_gui_basics/mouse/juce_MouseInputSource.cpp View File

@@ -82,48 +82,62 @@ public:
}
//==============================================================================
#if JUCE_DUMP_MOUSE_EVENTS
#define JUCE_MOUSE_EVENT_DBG(desc) DBG ("Mouse " desc << " #" << source.getIndex() \
<< ": " << comp->getLocalPoint (nullptr, screenPos).toString() \
<< " - Comp: " << String::toHexString ((int) comp));
#else
#define JUCE_MOUSE_EVENT_DBG(desc)
#endif
void sendMouseEnter (Component* const comp, const Point<int>& screenPos, const Time& time)
{
//DBG ("Mouse " + String (source.getIndex()) + " enter: " + comp->getLocalPoint (nullptr, screenPos).toString() + " - Comp: " + String::toHexString ((int) comp));
JUCE_MOUSE_EVENT_DBG ("enter")
comp->internalMouseEnter (source, comp->getLocalPoint (nullptr, screenPos), time);
}
void sendMouseExit (Component* const comp, const Point<int>& screenPos, const Time& time)
{
//DBG ("Mouse " + String (source.getIndex()) + " exit: " + comp->getLocalPoint (nullptr, screenPos).toString() + " - Comp: " + String::toHexString ((int) comp));
JUCE_MOUSE_EVENT_DBG ("exit")
comp->internalMouseExit (source, comp->getLocalPoint (nullptr, screenPos), time);
}
void sendMouseMove (Component* const comp, const Point<int>& screenPos, const Time& time)
{
//DBG ("Mouse " + String (source.getIndex()) + " move: " + comp->getLocalPoint (nullptr, screenPos).toString() + " - Comp: " + String::toHexString ((int) comp));
JUCE_MOUSE_EVENT_DBG ("move")
comp->internalMouseMove (source, comp->getLocalPoint (nullptr, screenPos), time);
}
void sendMouseDown (Component* const comp, const Point<int>& screenPos, const Time& time)
{
//DBG ("Mouse " + String (source.getIndex()) + " down: " + comp->getLocalPoint (nullptr, screenPos).toString() + " - Comp: " + String::toHexString ((int) comp));
JUCE_MOUSE_EVENT_DBG ("down")
comp->internalMouseDown (source, comp->getLocalPoint (nullptr, screenPos), time);
}
void sendMouseDrag (Component* const comp, const Point<int>& screenPos, const Time& time)
{
//DBG ("Mouse " + String (source.getIndex()) + " drag: " + comp->getLocalPoint (nullptr, screenPos).toString() + " - Comp: " + String::toHexString ((int) comp));
JUCE_MOUSE_EVENT_DBG ("drag")
comp->internalMouseDrag (source, comp->getLocalPoint (nullptr, screenPos), time);
}
void sendMouseUp (Component* const comp, const Point<int>& screenPos, const Time& time, const ModifierKeys& oldMods)
{
//DBG ("Mouse " + String (source.getIndex()) + " up: " + comp->getLocalPoint (nullptr, screenPos).toString() + " - Comp: " + String::toHexString ((int) comp));
JUCE_MOUSE_EVENT_DBG ("up")
comp->internalMouseUp (source, comp->getLocalPoint (nullptr, screenPos), time, oldMods);
}
void sendMouseWheel (Component* const comp, const Point<int>& screenPos, const Time& time, const MouseWheelDetails& wheel)
{
//DBG ("Mouse " + String (source.getIndex()) + " wheel: " + comp->getLocalPoint (nullptr, screenPos).toString() + " - Comp: " + String::toHexString ((int) comp));
JUCE_MOUSE_EVENT_DBG ("wheel")
comp->internalMouseWheel (source, comp->getLocalPoint (nullptr, screenPos), time, wheel);
}
void sendMagnifyGesture (Component* const comp, const Point<int>& screenPos, const Time& time, const float amount)
{
JUCE_MOUSE_EVENT_DBG ("magnify")
comp->internalMagnifyGesture (source, comp->getLocalPoint (nullptr, screenPos), time, amount);
}
//==============================================================================
// (returns true if the button change caused a modal event loop)
bool setButtons (const Point<int>& screenPos, const Time& time, const ModifierKeys& newButtonState)
@@ -276,24 +290,37 @@ public:
}
}
void handleWheel (ComponentPeer* const peer, const Point<int>& positionWithinPeer,
const Time& time, const MouseWheelDetails& wheel)
Component* getTargetForGesture (ComponentPeer* const peer, const Point<int>& positionWithinPeer,
const Time& time, Point<int>& screenPos)
{
jassert (peer != nullptr);
lastTime = time;
++mouseEventCounter;
Desktop::getInstance().incrementMouseWheelCounter();
const Point<int> screenPos (peer->localToGlobal (positionWithinPeer));
screenPos = peer->localToGlobal (positionWithinPeer);
setPeer (peer, screenPos, time);
setScreenPos (screenPos, time, false);
triggerFakeMove();
if (! isDragging())
{
if (Component* current = getComponentUnderMouse())
sendMouseWheel (current, screenPos, time, wheel);
}
return isDragging() ? nullptr : getComponentUnderMouse();
}
void handleWheel (ComponentPeer* const peer, const Point<int>& positionWithinPeer,
const Time& time, const MouseWheelDetails& wheel)
{
Desktop::getInstance().incrementMouseWheelCounter();
Point<int> screenPos;
if (Component* current = getTargetForGesture (peer, positionWithinPeer, time, screenPos))
sendMouseWheel (current, screenPos, time, wheel);
}
void handleMagnifyGesture (ComponentPeer* const peer, const Point<int>& positionWithinPeer,
const Time& time, const float scaleFactor)
{
Point<int> screenPos;
if (Component* current = getTargetForGesture (peer, positionWithinPeer, time, screenPos))
sendMagnifyGesture (current, screenPos, time, scaleFactor);
}
//==============================================================================
@@ -518,3 +545,9 @@ void MouseInputSource::handleWheel (ComponentPeer* const peer, const Point<int>&
{
pimpl->handleWheel (peer, positionWithinPeer, Time (time), wheel);
}
void MouseInputSource::handleMagnifyGesture (ComponentPeer* const peer, const Point<int>& positionWithinPeer,
const int64 time, const float scaleFactor)
{
pimpl->handleMagnifyGesture (peer, positionWithinPeer, Time (time), scaleFactor);
}

+ 4
- 2
modules/juce_gui_basics/mouse/juce_MouseInputSource.h View File

@@ -166,9 +166,11 @@ public:
//==============================================================================
/** @internal */
void handleEvent (ComponentPeer*, const Point<int>& positionWithinPeer, int64 time, const ModifierKeys&);
void handleEvent (ComponentPeer*, const Point<int>&, int64 time, const ModifierKeys&);
/** @internal */
void handleWheel (ComponentPeer*, const Point<int>& positionWithinPeer, int64 time, const MouseWheelDetails&);
void handleWheel (ComponentPeer*, const Point<int>&, int64 time, const MouseWheelDetails&);
/** @internal */
void handleMagnifyGesture (ComponentPeer*, const Point<int>&, int64 time, float scaleFactor);
private:
//==============================================================================


+ 10
- 0
modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm View File

@@ -626,6 +626,14 @@ public:
handleMouseWheel (0, getMousePos (ev, view), getMouseTime (ev), wheel);
}
void redirectMagnify (NSEvent* ev)
{
const float invScale = 1.0f - [ev magnification];
if (invScale != 0.0f)
handleMagnifyGesture (0, getMousePos (ev, view), getMouseTime (ev), 1.0f / invScale);
}
void sendMouseEvent (NSEvent* ev)
{
updateModifiers (ev);
@@ -1347,6 +1355,7 @@ struct JuceNSViewClass : public ObjCClass <NSView>
addMethod (@selector (otherMouseDragged:), mouseDragged, "v@:@");
addMethod (@selector (otherMouseUp:), mouseUp, "v@:@");
addMethod (@selector (scrollWheel:), scrollWheel, "v@:@");
addMethod (@selector (magnifyWithEvent:), magnify, "v@:@");
addMethod (@selector (acceptsFirstMouse:), acceptsFirstMouse, "v@:@");
addMethod (@selector (frameChanged:), frameChanged, "v@:@");
addMethod (@selector (viewDidMoveToWindow), viewDidMoveToWindow, "v@:");
@@ -1425,6 +1434,7 @@ private:
static void mouseEntered (id self, SEL, NSEvent* ev) { if (NSViewComponentPeer* const p = getOwner (self)) p->redirectMouseEnter (ev); }
static void mouseExited (id self, SEL, NSEvent* ev) { if (NSViewComponentPeer* const p = getOwner (self)) p->redirectMouseExit (ev); }
static void scrollWheel (id self, SEL, NSEvent* ev) { if (NSViewComponentPeer* const p = getOwner (self)) p->redirectMouseWheel (ev); }
static void magnify (id self, SEL, NSEvent* ev) { if (NSViewComponentPeer* const p = getOwner (self)) p->redirectMagnify (ev); }
static BOOL acceptsFirstMouse (id, SEL, NSEvent*) { return YES; }


+ 80
- 8
modules/juce_gui_basics/native/juce_win32_Windowing.cpp View File

@@ -77,8 +77,9 @@ bool Desktop::canUseSemiTransparentWindows() noexcept
#define TOUCHEVENTF_DOWN 0x0002
#define TOUCHEVENTF_UP 0x0004
DECLARE_HANDLE (HTOUCHINPUT);
DECLARE_HANDLE (HGESTUREINFO);
typedef struct tagTOUCHINPUT
struct TOUCHINPUT
{
LONG x;
LONG y;
@@ -90,16 +91,32 @@ bool Desktop::canUseSemiTransparentWindows() noexcept
ULONG_PTR dwExtraInfo;
DWORD cxContact;
DWORD cyContact;
} TOUCHINPUT, *PTOUCHINPUT;
};
struct GESTUREINFO
{
UINT cbSize;
DWORD dwFlags;
DWORD dwID;
HWND hwndTarget;
POINTS ptsLocation;
DWORD dwInstanceID;
DWORD dwSequenceID;
ULONGLONG ullArguments;
UINT cbExtraArgs;
};
#endif
typedef BOOL (WINAPI* RegisterTouchWindowFunc) (HWND, ULONG);
typedef BOOL (WINAPI* GetTouchInputInfoFunc) (HTOUCHINPUT, UINT, PTOUCHINPUT, int);
typedef BOOL (WINAPI* GetTouchInputInfoFunc) (HTOUCHINPUT, UINT, TOUCHINPUT*, int);
typedef BOOL (WINAPI* CloseTouchInputHandleFunc) (HTOUCHINPUT);
typedef BOOL (WINAPI* GetGestureInfoFunc) (HGESTUREINFO, GESTUREINFO*);
static RegisterTouchWindowFunc registerTouchWindow = nullptr;
static GetTouchInputInfoFunc getTouchInputInfo = nullptr;
static CloseTouchInputHandleFunc closeTouchInputHandle = nullptr;
static GetGestureInfoFunc getGestureInfo = nullptr;
static bool hasCheckedForMultiTouch = false;
@@ -112,6 +129,7 @@ static bool canUseMultiTouch()
registerTouchWindow = (RegisterTouchWindowFunc) getUser32Function ("RegisterTouchWindow");
getTouchInputInfo = (GetTouchInputInfoFunc) getUser32Function ("GetTouchInputInfo");
closeTouchInputHandle = (CloseTouchInputHandleFunc) getUser32Function ("CloseTouchInputHandle");
getGestureInfo = (GetGestureInfoFunc) getUser32Function ("GetGestureInfo");
}
return registerTouchWindow != nullptr;
@@ -473,6 +491,7 @@ public:
parentToAddTo (parent),
currentRenderingEngine (softwareRenderingEngine),
lastPaintTime (0),
lastMagnifySize (0),
fullScreen (false),
isDragging (false),
isMouseOver (false),
@@ -1070,6 +1089,7 @@ private:
ScopedPointer<Direct2DLowLevelGraphicsContext> direct2DContext;
#endif
uint32 lastPaintTime;
ULONGLONG lastMagnifySize;
bool fullScreen, isDragging, isMouseOver, hasCreatedCaret, constrainerIsResizing;
BorderSize<int> windowBorder;
HICON currentWindowIcon;
@@ -1690,10 +1710,9 @@ private:
doMouseEvent (getCurrentMousePos());
}
void doMouseWheel (const Point<int>& globalPos, const WPARAM wParam, const bool isVertical)
ComponentPeer* findPeerUnderMouse (Point<int>& localPos)
{
updateKeyModifiers();
const float amount = jlimit (-1000.0f, 1000.0f, 0.5f * (short) HIWORD (wParam));
const Point<int> globalPos (getCurrentMousePosGlobal());
// Because Windows stupidly sends all wheel events to the window with the keyboard
// focus, we have to redirect them here according to the mouse pos..
@@ -1703,13 +1722,60 @@ private:
if (peer == nullptr)
peer = this;
localPos = peer->globalToLocal (globalPos);
return peer;
}
void doMouseWheel (const WPARAM wParam, const bool isVertical)
{
updateKeyModifiers();
const float amount = jlimit (-1000.0f, 1000.0f, 0.5f * (short) HIWORD (wParam));
MouseWheelDetails wheel;
wheel.deltaX = isVertical ? 0.0f : amount / -256.0f;
wheel.deltaY = isVertical ? amount / 256.0f : 0.0f;
wheel.isReversed = false;
wheel.isSmooth = false;
peer->handleMouseWheel (0, peer->globalToLocal (globalPos), getMouseEventTime(), wheel);
Point<int> localPos;
if (ComponentPeer* const peer = findPeerUnderMouse (localPos))
peer->handleMouseWheel (0, localPos, getMouseEventTime(), wheel);
}
bool doGestureEvent (LPARAM lParam)
{
GESTUREINFO gi;
zerostruct (gi);
gi.cbSize = sizeof (gi);
if (getGestureInfo != nullptr && getGestureInfo ((HGESTUREINFO) lParam, &gi))
{
updateKeyModifiers();
Point<int> localPos;
if (ComponentPeer* const peer = findPeerUnderMouse (localPos))
{
switch (gi.dwID)
{
case 3: /*GID_ZOOM*/
if (gi.dwFlags != 1 /*GF_BEGIN*/ && lastMagnifySize > 0)
peer->handleMagnifyGesture (0, localPos, getMouseEventTime(),
(float) (gi.ullArguments / (double) lastMagnifySize));
lastMagnifySize = gi.ullArguments;
return true;
case 4: /*GID_PAN*/
case 5: /*GID_ROTATE*/
case 6: /*GID_TWOFINGERTAP*/
case 7: /*GID_PRESSANDTAP*/
default:
break;
}
}
}
return false;
}
void doTouchEvent (const int numInputs, HTOUCHINPUT eventHandle)
@@ -2226,7 +2292,7 @@ private:
case 0x020A: /* WM_MOUSEWHEEL */
case 0x020E: /* WM_MOUSEHWHEEL */
doMouseWheel (getCurrentMousePosGlobal(), wParam, message == 0x020A);
doMouseWheel (wParam, message == 0x020A);
return 0;
case WM_TOUCH:
@@ -2236,6 +2302,12 @@ private:
doTouchEvent ((int) wParam, (HTOUCHINPUT) lParam);
return 0;
case 0x119: /* WM_GESTURE */
if (doGestureEvent (lParam))
return 0;
break;
//==============================================================================
case WM_SIZING: return handleSizeConstraining (*(RECT*) lParam, wParam);
case WM_WINDOWPOSCHANGING: return handlePositionChanging (*(WINDOWPOS*) lParam);


+ 7
- 0
modules/juce_gui_basics/windows/juce_ComponentPeer.cpp View File

@@ -113,6 +113,13 @@ void ComponentPeer::handleMouseWheel (const int touchIndex, const Point<int>& po
mouse->handleWheel (this, positionWithinPeer, time, wheel);
}
void ComponentPeer::handleMagnifyGesture (const int touchIndex, const Point<int>& positionWithinPeer,
const int64 time, const float scaleFactor)
{
if (MouseInputSource* mouse = getOrCreateMouseInputSource (touchIndex))
mouse->handleMagnifyGesture (this, positionWithinPeer, time, scaleFactor);
}
//==============================================================================
void ComponentPeer::handlePaint (LowLevelGraphicsContext& contextToPaintTo)
{


+ 1
- 0
modules/juce_gui_basics/windows/juce_ComponentPeer.h View File

@@ -315,6 +315,7 @@ public:
//==============================================================================
void handleMouseEvent (int touchIndex, const Point<int>& positionWithinPeer, const ModifierKeys& newMods, int64 time);
void handleMouseWheel (int touchIndex, const Point<int>& positionWithinPeer, int64 time, const MouseWheelDetails&);
void handleMagnifyGesture (int touchIndex, const Point<int>& positionWithinPeer, int64 time, float scaleFactor);
void handleUserClosingWindow();


Loading…
Cancel
Save