@@ -58,7 +58,7 @@ public: | |||
trails.add (t); | |||
} | |||
t->pushPoint (e.position, e.mods); | |||
t->pushPoint (e.position, e.mods, e.pressure); | |||
repaint(); | |||
} | |||
@@ -74,22 +74,26 @@ public: | |||
: source (ms), colour (getRandomBrightColour().withAlpha (0.6f)) | |||
{} | |||
void pushPoint (Point<float> p, ModifierKeys newMods) | |||
void pushPoint (Point<float> newPoint, ModifierKeys newMods, float pressure) | |||
{ | |||
currentPosition = p; | |||
currentPosition = newPoint; | |||
modifierKeys = newMods; | |||
if (lastPoint.getDistanceFrom(p) > 5.0f) | |||
if (lastPoint.getDistanceFrom (newPoint) > 5.0f) | |||
{ | |||
if (lastPoint != Point<float>()) | |||
{ | |||
path.quadraticTo (lastPoint, p); | |||
lastPoint = Point<float>(); | |||
} | |||
else | |||
{ | |||
lastPoint = p; | |||
Path newSegment; | |||
newSegment.startNewSubPath (lastPoint); | |||
newSegment.lineTo (newPoint); | |||
float diameter = 20.0f * (pressure > 0 && pressure < 1.0f ? pressure : 1.0f); | |||
PathStrokeType (diameter, PathStrokeType::curved, PathStrokeType::rounded).createStrokedPath (newSegment, newSegment); | |||
path.addPath (newSegment); | |||
} | |||
lastPoint = newPoint; | |||
} | |||
} | |||
@@ -107,7 +111,7 @@ public: | |||
void drawTrail (Trail& trail, Graphics& g) | |||
{ | |||
g.setColour (trail.colour); | |||
g.strokePath (trail.path, PathStrokeType (20.0f, PathStrokeType::curved, PathStrokeType::rounded)); | |||
g.fillPath (trail.path); | |||
const float radius = 40.0f; | |||
@@ -121,6 +125,11 @@ public: | |||
String desc ("Mouse #"); | |||
desc << trail.source.getIndex(); | |||
float pressure = trail.source.getCurrentPressure(); | |||
if (pressure > 0.0f && pressure < 1.0f) | |||
desc << " (pressure: " << (int) (pressure * 100.0f) << "%)"; | |||
if (trail.modifierKeys.isCommandDown()) desc << " (CMD)"; | |||
if (trail.modifierKeys.isShiftDown()) desc << " (SHIFT)"; | |||
if (trail.modifierKeys.isCtrlDown()) desc << " (CTRL)"; | |||
@@ -51,7 +51,8 @@ public: | |||
if (Component* const comp = Desktop::getInstance().findComponentAt (screenPos.roundToInt())) | |||
if (ComponentPeer* const peer = comp->getPeer()) | |||
if (! peer->isFocused()) | |||
peer->handleMouseEvent (0, peer->globalToLocal (screenPos), mods, Time::currentTimeMillis()); | |||
peer->handleMouseEvent (0, peer->globalToLocal (screenPos), mods, | |||
MouseInputSource::invalidPressure, Time::currentTimeMillis()); | |||
} | |||
} | |||
@@ -2384,7 +2384,7 @@ void Component::internalMouseEnter (MouseInputSource source, Point<float> relati | |||
BailOutChecker checker (this); | |||
const MouseEvent me (source, relativePos, source.getCurrentModifiers(), | |||
const MouseEvent me (source, relativePos, source.getCurrentModifiers(), MouseInputSource::invalidPressure, | |||
this, this, time, relativePos, time, 0, false); | |||
mouseEnter (me); | |||
@@ -2403,7 +2403,7 @@ void Component::internalMouseExit (MouseInputSource source, Point<float> relativ | |||
BailOutChecker checker (this); | |||
const MouseEvent me (source, relativePos, source.getCurrentModifiers(), | |||
const MouseEvent me (source, relativePos, source.getCurrentModifiers(), MouseInputSource::invalidPressure, | |||
this, this, time, relativePos, time, 0, false); | |||
mouseExit (me); | |||
@@ -2416,7 +2416,7 @@ void Component::internalMouseExit (MouseInputSource source, Point<float> relativ | |||
MouseListenerList::sendMouseEvent (*this, checker, &MouseListener::mouseExit, me); | |||
} | |||
void Component::internalMouseDown (MouseInputSource source, Point<float> relativePos, Time time) | |||
void Component::internalMouseDown (MouseInputSource source, Point<float> relativePos, Time time, float pressure) | |||
{ | |||
Desktop& desktop = Desktop::getInstance(); | |||
BailOutChecker checker (this); | |||
@@ -2435,7 +2435,7 @@ void Component::internalMouseDown (MouseInputSource source, Point<float> relativ | |||
{ | |||
// allow blocked mouse-events to go to global listeners.. | |||
const MouseEvent me (source, relativePos, source.getCurrentModifiers(), | |||
this, this, time, relativePos, time, | |||
pressure, this, this, time, relativePos, time, | |||
source.getNumberOfMultipleClicks(), false); | |||
desktop.getMouseListeners().callChecked (checker, &MouseListener::mouseDown, me); | |||
@@ -2468,7 +2468,7 @@ void Component::internalMouseDown (MouseInputSource source, Point<float> relativ | |||
repaint(); | |||
const MouseEvent me (source, relativePos, source.getCurrentModifiers(), | |||
this, this, time, relativePos, time, | |||
pressure, this, this, time, relativePos, time, | |||
source.getNumberOfMultipleClicks(), false); | |||
mouseDown (me); | |||
@@ -2492,7 +2492,7 @@ void Component::internalMouseUp (MouseInputSource source, Point<float> relativeP | |||
repaint(); | |||
const MouseEvent me (source, relativePos, | |||
oldModifiers, this, this, time, | |||
oldModifiers, MouseInputSource::invalidPressure, this, this, time, | |||
getLocalPoint (nullptr, source.getLastMouseDownPosition()), | |||
source.getLastMouseDownTime(), | |||
source.getNumberOfMultipleClicks(), | |||
@@ -2523,14 +2523,14 @@ void Component::internalMouseUp (MouseInputSource source, Point<float> relativeP | |||
} | |||
} | |||
void Component::internalMouseDrag (MouseInputSource source, Point<float> relativePos, Time time) | |||
void Component::internalMouseDrag (MouseInputSource source, Point<float> relativePos, Time time, float pressure) | |||
{ | |||
if (! isCurrentlyBlockedByAnotherModalComponent()) | |||
{ | |||
BailOutChecker checker (this); | |||
const MouseEvent me (source, relativePos, | |||
source.getCurrentModifiers(), this, this, time, | |||
const MouseEvent me (source, relativePos, source.getCurrentModifiers(), | |||
pressure, this, this, time, | |||
getLocalPoint (nullptr, source.getLastMouseDownPosition()), | |||
source.getLastMouseDownTime(), | |||
source.getNumberOfMultipleClicks(), | |||
@@ -2559,7 +2559,7 @@ void Component::internalMouseMove (MouseInputSource source, Point<float> relativ | |||
{ | |||
BailOutChecker checker (this); | |||
const MouseEvent me (source, relativePos, source.getCurrentModifiers(), | |||
const MouseEvent me (source, relativePos, source.getCurrentModifiers(), MouseInputSource::invalidPressure, | |||
this, this, time, relativePos, time, 0, false); | |||
mouseMove (me); | |||
@@ -2578,7 +2578,7 @@ void Component::internalMouseWheel (MouseInputSource source, Point<float> relati | |||
Desktop& desktop = Desktop::getInstance(); | |||
BailOutChecker checker (this); | |||
const MouseEvent me (source, relativePos, source.getCurrentModifiers(), | |||
const MouseEvent me (source, relativePos, source.getCurrentModifiers(), MouseInputSource::invalidPressure, | |||
this, this, time, relativePos, time, 0, false); | |||
if (isCurrentlyBlockedByAnotherModalComponent()) | |||
@@ -2605,7 +2605,7 @@ void Component::internalMagnifyGesture (MouseInputSource source, Point<float> re | |||
{ | |||
if (! isCurrentlyBlockedByAnotherModalComponent()) | |||
{ | |||
const MouseEvent me (source, relativePos, source.getCurrentModifiers(), | |||
const MouseEvent me (source, relativePos, source.getCurrentModifiers(), MouseInputSource::invalidPressure, | |||
this, this, time, relativePos, time, 0, false); | |||
mouseMagnify (me, amount); | |||
@@ -2300,9 +2300,9 @@ private: | |||
//============================================================================== | |||
void internalMouseEnter (MouseInputSource, Point<float>, Time); | |||
void internalMouseExit (MouseInputSource, Point<float>, Time); | |||
void internalMouseDown (MouseInputSource, Point<float>, Time); | |||
void internalMouseDown (MouseInputSource, Point<float>, Time, float); | |||
void internalMouseUp (MouseInputSource, Point<float>, Time, const ModifierKeys oldModifiers); | |||
void internalMouseDrag (MouseInputSource, Point<float>, Time); | |||
void internalMouseDrag (MouseInputSource, Point<float>, Time, float); | |||
void internalMouseMove (MouseInputSource, Point<float>, Time); | |||
void internalMouseWheel (MouseInputSource, Point<float>, Time, const MouseWheelDetails&); | |||
void internalMagnifyGesture (MouseInputSource, Point<float>, Time, float); | |||
@@ -246,7 +246,7 @@ void Desktop::sendMouseMove() | |||
const Time now (Time::getCurrentTime()); | |||
const MouseEvent me (getMainMouseSource(), pos, ModifierKeys::getCurrentModifiers(), | |||
target, target, now, pos, now, 0, false); | |||
MouseInputSource::invalidPressure, target, target, now, pos, now, 0, false); | |||
if (me.mods.isAnyMouseButtonDown()) | |||
mouseListeners.callChecked (checker, &MouseListener::mouseDrag, me); | |||
@@ -25,6 +25,7 @@ | |||
MouseEvent::MouseEvent (MouseInputSource inputSource, | |||
Point<float> pos, | |||
ModifierKeys modKeys, | |||
float force, | |||
Component* const eventComp, | |||
Component* const originator, | |||
Time time, | |||
@@ -36,6 +37,7 @@ MouseEvent::MouseEvent (MouseInputSource inputSource, | |||
x (roundToInt (pos.x)), | |||
y (roundToInt (pos.y)), | |||
mods (modKeys), | |||
pressure (force), | |||
eventComponent (eventComp), | |||
originalComponent (originator), | |||
eventTime (time), | |||
@@ -57,22 +59,22 @@ MouseEvent MouseEvent::getEventRelativeTo (Component* const otherComponent) cons | |||
jassert (otherComponent != nullptr); | |||
return MouseEvent (source, otherComponent->getLocalPoint (eventComponent, position), | |||
mods, otherComponent, originalComponent, eventTime, | |||
mods, pressure, otherComponent, originalComponent, eventTime, | |||
otherComponent->getLocalPoint (eventComponent, mouseDownPos), | |||
mouseDownTime, numberOfClicks, wasMovedSinceMouseDown != 0); | |||
} | |||
MouseEvent MouseEvent::withNewPosition (Point<float> newPosition) const noexcept | |||
{ | |||
return MouseEvent (source, newPosition, mods, eventComponent, originalComponent, | |||
eventTime, mouseDownPos, mouseDownTime, | |||
return MouseEvent (source, newPosition, mods, pressure, eventComponent, | |||
originalComponent, eventTime, mouseDownPos, mouseDownTime, | |||
numberOfClicks, wasMovedSinceMouseDown != 0); | |||
} | |||
MouseEvent MouseEvent::withNewPosition (Point<int> newPosition) const noexcept | |||
{ | |||
return MouseEvent (source, newPosition.toFloat(), mods, eventComponent, originalComponent, | |||
eventTime, mouseDownPos, mouseDownTime, | |||
return MouseEvent (source, newPosition.toFloat(), mods, pressure, eventComponent, | |||
originalComponent, eventTime, mouseDownPos, mouseDownTime, | |||
numberOfClicks, wasMovedSinceMouseDown != 0); | |||
} | |||
@@ -112,6 +114,8 @@ int MouseEvent::getScreenY() const { return getScre | |||
int MouseEvent::getMouseDownScreenX() const { return getMouseDownScreenPosition().x; } | |||
int MouseEvent::getMouseDownScreenY() const { return getMouseDownScreenPosition().y; } | |||
bool MouseEvent::isPressureValid() const noexcept { return pressure > 0.0f && pressure < 1.0f; } | |||
//============================================================================== | |||
static int doubleClickTimeOutMs = 400; | |||
@@ -44,6 +44,9 @@ public: | |||
@param source the source that's invoking the event | |||
@param position the position of the mouse, relative to the component that is passed-in | |||
@param modifiers the key modifiers at the time of the event | |||
@param pressure the pressure of the touch or stylus, in the range 0 to 1. Devices that | |||
do not support force information may return 0.0, 1.0, or a negative value, | |||
depending on the platform | |||
@param eventComponent the component that the mouse event applies to | |||
@param originator the component that originally received the event | |||
@param eventTime the time the event happened | |||
@@ -59,6 +62,7 @@ public: | |||
MouseEvent (MouseInputSource source, | |||
Point<float> position, | |||
ModifierKeys modifiers, | |||
float pressure, | |||
Component* eventComponent, | |||
Component* originator, | |||
Time eventTime, | |||
@@ -109,6 +113,13 @@ public: | |||
*/ | |||
const ModifierKeys mods; | |||
/** The pressure of the touch or stylus for this event. | |||
The range is 0 (soft) to 1 (hard). | |||
If the input device doesn't provide any pressure data, it may return a negative | |||
value here, or 0.0 or 1.0, depending on the platform. | |||
*/ | |||
float pressure; | |||
/** The component that this event applies to. | |||
This is usually the component that the mouse was over at the time, but for mouse-drag | |||
@@ -224,6 +235,9 @@ public: | |||
*/ | |||
int getLengthOfMousePress() const noexcept; | |||
/** Returns true if the pressure value for this event is meaningful. */ | |||
bool isPressureValid() const noexcept; | |||
//============================================================================== | |||
/** The position of the mouse when the event occurred. | |||
@@ -27,7 +27,7 @@ class MouseInputSourceInternal : private AsyncUpdater | |||
public: | |||
//============================================================================== | |||
MouseInputSourceInternal (const int i, const bool isMouse) | |||
: index (i), isMouseDevice (isMouse), | |||
: index (i), isMouseDevice (isMouse), pressure (0.0f), | |||
isUnboundedMouseModeOn (false), isCursorVisibleUntilOffscreen (false), | |||
lastPeer (nullptr), currentCursorHandle (nullptr), | |||
mouseEventCounter (0), mouseMovedSignificantlySincePressed (false) | |||
@@ -40,17 +40,17 @@ public: | |||
return buttonState.isAnyMouseButtonDown(); | |||
} | |||
Component* getComponentUnderMouse() const | |||
Component* getComponentUnderMouse() const noexcept | |||
{ | |||
return componentUnderMouse.get(); | |||
} | |||
ModifierKeys getCurrentModifiers() const | |||
ModifierKeys getCurrentModifiers() const noexcept | |||
{ | |||
return ModifierKeys::getCurrentModifiers().withoutMouseButtons().withFlags (buttonState.getRawFlags()); | |||
} | |||
ComponentPeer* getPeer() | |||
ComponentPeer* getPeer() noexcept | |||
{ | |||
if (! ComponentPeer::isValidPeer (lastPeer)) | |||
lastPeer = nullptr; | |||
@@ -102,6 +102,8 @@ public: | |||
MouseInputSource::setRawMousePosition (ScalingHelpers::scaledScreenPosToUnscaled (p)); | |||
} | |||
bool isPressureValid() const noexcept { return pressure > 0.0f && pressure < 1.0f; } | |||
//============================================================================== | |||
#if JUCE_DUMP_MOUSE_EVENTS | |||
#define JUCE_MOUSE_EVENT_DBG(desc) DBG ("Mouse " << desc << " #" << index \ | |||
@@ -132,13 +134,13 @@ public: | |||
void sendMouseDown (Component& comp, Point<float> screenPos, Time time) | |||
{ | |||
JUCE_MOUSE_EVENT_DBG ("down") | |||
comp.internalMouseDown (MouseInputSource (this), screenPosToLocalPos (comp, screenPos), time); | |||
comp.internalMouseDown (MouseInputSource (this), screenPosToLocalPos (comp, screenPos), time, pressure); | |||
} | |||
void sendMouseDrag (Component& comp, Point<float> screenPos, Time time) | |||
{ | |||
JUCE_MOUSE_EVENT_DBG ("drag") | |||
comp.internalMouseDrag (MouseInputSource (this), screenPosToLocalPos (comp, screenPos), time); | |||
comp.internalMouseDrag (MouseInputSource (this), screenPosToLocalPos (comp, screenPos), time, pressure); | |||
} | |||
void sendMouseUp (Component& comp, Point<float> screenPos, Time time, const ModifierKeys oldMods) | |||
@@ -287,15 +289,18 @@ public: | |||
} | |||
//============================================================================== | |||
void handleEvent (ComponentPeer& newPeer, Point<float> positionWithinPeer, Time time, const ModifierKeys newMods) | |||
void handleEvent (ComponentPeer& newPeer, Point<float> positionWithinPeer, Time time, | |||
const ModifierKeys newMods, float newPressure) | |||
{ | |||
lastTime = time; | |||
const bool pressureChanged = (pressure != newPressure); | |||
pressure = newPressure; | |||
++mouseEventCounter; | |||
const Point<float> screenPos (newPeer.localToGlobal (positionWithinPeer)); | |||
if (isDragging() && newMods.isAnyMouseButtonDown()) | |||
{ | |||
setScreenPos (screenPos, time, false); | |||
setScreenPos (screenPos, time, pressureChanged); | |||
} | |||
else | |||
{ | |||
@@ -307,8 +312,9 @@ public: | |||
return; // some modal events have been dispatched, so the current event is now out-of-date | |||
peer = getPeer(); | |||
if (peer != nullptr) | |||
setScreenPos (screenPos, time, false); | |||
setScreenPos (screenPos, time, pressureChanged); | |||
} | |||
} | |||
} | |||
@@ -470,6 +476,7 @@ public: | |||
const bool isMouseDevice; | |||
Point<float> lastScreenPos, unboundedMouseOffset; // NB: these are unscaled coords | |||
ModifierKeys buttonState; | |||
float pressure; | |||
bool isUnboundedMouseModeOn, isCursorVisibleUntilOffscreen; | |||
@@ -542,14 +549,16 @@ MouseInputSource& MouseInputSource::operator= (const MouseInputSource& other) no | |||
return *this; | |||
} | |||
bool MouseInputSource::isMouse() const { return pimpl->isMouseDevice; } | |||
bool MouseInputSource::isTouch() const { return ! isMouse(); } | |||
bool MouseInputSource::canHover() const { return isMouse(); } | |||
bool MouseInputSource::hasMouseWheel() const { return isMouse(); } | |||
int MouseInputSource::getIndex() const { return pimpl->index; } | |||
bool MouseInputSource::isDragging() const { return pimpl->isDragging(); } | |||
Point<float> MouseInputSource::getScreenPosition() const { return pimpl->getScreenPosition(); } | |||
ModifierKeys MouseInputSource::getCurrentModifiers() const { return pimpl->getCurrentModifiers(); } | |||
bool MouseInputSource::isMouse() const noexcept { return pimpl->isMouseDevice; } | |||
bool MouseInputSource::isTouch() const noexcept { return ! isMouse(); } | |||
bool MouseInputSource::canHover() const noexcept { return isMouse(); } | |||
bool MouseInputSource::hasMouseWheel() const noexcept { return isMouse(); } | |||
int MouseInputSource::getIndex() const noexcept { return pimpl->index; } | |||
bool MouseInputSource::isDragging() const noexcept { return pimpl->isDragging(); } | |||
Point<float> MouseInputSource::getScreenPosition() const noexcept { return pimpl->getScreenPosition(); } | |||
ModifierKeys MouseInputSource::getCurrentModifiers() const noexcept { return pimpl->getCurrentModifiers(); } | |||
float MouseInputSource::getCurrentPressure() const noexcept { return pimpl->pressure; } | |||
bool MouseInputSource::isPressureValid() const noexcept { return pimpl->isPressureValid(); } | |||
Component* MouseInputSource::getComponentUnderMouse() const { return pimpl->getComponentUnderMouse(); } | |||
void MouseInputSource::triggerFakeMove() const { pimpl->triggerFakeMove(); } | |||
int MouseInputSource::getNumberOfMultipleClicks() const noexcept { return pimpl->getNumberOfMultipleClicks(); } | |||
@@ -567,9 +576,9 @@ void MouseInputSource::revealCursor() { pimpl | |||
void MouseInputSource::forceMouseCursorUpdate() { pimpl->revealCursor (true); } | |||
void MouseInputSource::setScreenPosition (Point<float> p) { pimpl->setScreenPosition (p); } | |||
void MouseInputSource::handleEvent (ComponentPeer& peer, Point<float> pos, int64 time, ModifierKeys mods) | |||
void MouseInputSource::handleEvent (ComponentPeer& peer, Point<float> pos, int64 time, ModifierKeys mods, float pressure) | |||
{ | |||
pimpl->handleEvent (peer, pos, Time (time), mods.withOnlyMouseButtons()); | |||
pimpl->handleEvent (peer, pos, Time (time), mods.withOnlyMouseButtons(), pressure); | |||
} | |||
void MouseInputSource::handleWheel (ComponentPeer& peer, Point<float> pos, int64 time, const MouseWheelDetails& wheel) | |||
@@ -582,6 +591,8 @@ void MouseInputSource::handleMagnifyGesture (ComponentPeer& peer, Point<float> p | |||
pimpl->handleMagnifyGesture (peer, pos, Time (time), scaleFactor); | |||
} | |||
const float MouseInputSource::invalidPressure = 0.0f; | |||
//============================================================================== | |||
struct MouseInputSource::SourceList : public Timer | |||
{ | |||
@@ -60,18 +60,18 @@ public: | |||
//============================================================================== | |||
/** Returns true if this object represents a normal desk-based mouse device. */ | |||
bool isMouse() const; | |||
bool isMouse() const noexcept; | |||
/** Returns true if this object represents a source of touch events - i.e. a finger or stylus. */ | |||
bool isTouch() const; | |||
bool isTouch() const noexcept; | |||
/** Returns true if this source has an on-screen pointer that can hover over | |||
items without clicking them. | |||
*/ | |||
bool canHover() const; | |||
bool canHover() const noexcept; | |||
/** Returns true if this source may have a scroll wheel. */ | |||
bool hasMouseWheel() const; | |||
bool hasMouseWheel() const noexcept; | |||
/** Returns this source's index in the global list of possible sources. | |||
If the system only has a single mouse, there will only be a single MouseInputSource | |||
@@ -82,18 +82,28 @@ public: | |||
number 0, and then if a second touch happens while the first is still down, it | |||
will have index 1, etc. | |||
*/ | |||
int getIndex() const; | |||
int getIndex() const noexcept; | |||
/** Returns true if this device is currently being pressed. */ | |||
bool isDragging() const; | |||
bool isDragging() const noexcept; | |||
/** Returns the last-known screen position of this source. */ | |||
Point<float> getScreenPosition() const; | |||
Point<float> getScreenPosition() const noexcept; | |||
/** Returns a set of modifiers that indicate which buttons are currently | |||
held down on this device. | |||
*/ | |||
ModifierKeys getCurrentModifiers() const; | |||
ModifierKeys getCurrentModifiers() const noexcept; | |||
/** Returns the device's current touch or pen pressure. | |||
The range is 0 (soft) to 1 (hard). | |||
If the input device doesn't provide any pressure data, it may return a negative | |||
value here, or 0.0 or 1.0, depending on the platform. | |||
*/ | |||
float getCurrentPressure() const noexcept; | |||
/** Returns true if the current pressure value is meaningful. */ | |||
bool isPressureValid() const noexcept; | |||
/** Returns the component that was last known to be under this pointer. */ | |||
Component* getComponentUnderMouse() const; | |||
@@ -164,6 +174,11 @@ public: | |||
/** Attempts to set this mouse pointer's screen position. */ | |||
void setScreenPosition (Point<float> newPosition); | |||
/** A default value for pressure, which is used when a device doesn't support it, or for | |||
mouse-moves, mouse-ups, etc. | |||
*/ | |||
static const float invalidPressure; | |||
private: | |||
//============================================================================== | |||
friend class ComponentPeer; | |||
@@ -174,7 +189,7 @@ private: | |||
struct SourceList; | |||
explicit MouseInputSource (MouseInputSourceInternal*) noexcept; | |||
void handleEvent (ComponentPeer&, Point<float>, int64 time, ModifierKeys); | |||
void handleEvent (ComponentPeer&, Point<float>, int64 time, ModifierKeys, float); | |||
void handleWheel (ComponentPeer&, Point<float>, int64 time, const MouseWheelDetails&); | |||
void handleMagnifyGesture (ComponentPeer&, Point<float>, int64 time, float scaleFactor); | |||
@@ -332,7 +332,7 @@ public: | |||
lastMousePos = pos; | |||
// this forces a mouse-enter/up event, in case for some reason we didn't get a mouse-up before. | |||
handleMouseEvent (index, pos, currentModifiers.withoutMouseButtons(), time); | |||
handleMouseEvent (index, pos, currentModifiers.withoutMouseButtons(), MouseInputSource::invalidPressure, time); | |||
if (isValidPeer (this)) | |||
handleMouseDragCallback (index, sysPos, time); | |||
@@ -346,8 +346,8 @@ public: | |||
jassert (index < 64); | |||
touchesDown = (touchesDown | (1 << (index & 63))); | |||
currentModifiers = currentModifiers.withoutMouseButtons().withFlags (ModifierKeys::leftButtonModifier); | |||
handleMouseEvent (index, pos, currentModifiers.withoutMouseButtons() | |||
.withFlags (ModifierKeys::leftButtonModifier), time); | |||
handleMouseEvent (index, pos, currentModifiers.withoutMouseButtons().withFlags (ModifierKeys::leftButtonModifier), | |||
MouseInputSource::invalidPressure, time); | |||
} | |||
void handleMouseUpCallback (int index, Point<float> pos, int64 time) | |||
@@ -361,7 +361,7 @@ public: | |||
if (touchesDown == 0) | |||
currentModifiers = currentModifiers.withoutMouseButtons(); | |||
handleMouseEvent (index, pos, currentModifiers.withoutMouseButtons(), time); | |||
handleMouseEvent (index, pos, currentModifiers.withoutMouseButtons(), MouseInputSource::invalidPressure, time); | |||
} | |||
void handleKeyDownCallback (int k, int kc) | |||
@@ -767,7 +767,11 @@ void UIViewComponentPeer::handleTouches (UIEvent* event, const bool isDown, cons | |||
{ | |||
UITouch* touch = [touches objectAtIndex: i]; | |||
#if defined (__IPHONE_9_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_9_0 | |||
if ([touch phase] == UITouchPhaseStationary && touch.maximumPossibleForce <= 0) | |||
#else | |||
if ([touch phase] == UITouchPhaseStationary) | |||
#endif | |||
continue; | |||
CGPoint p = [touch locationInView: view]; | |||
@@ -788,7 +792,9 @@ void UIViewComponentPeer::handleTouches (UIEvent* event, const bool isDown, cons | |||
modsToSend = currentModifiers; | |||
// this forces a mouse-enter/up event, in case for some reason we didn't get a mouse-up before. | |||
handleMouseEvent (touchIndex, pos, modsToSend.withoutMouseButtons(), time); | |||
handleMouseEvent (touchIndex, pos, modsToSend.withoutMouseButtons(), | |||
MouseInputSource::invalidPressure, time); | |||
if (! isValidPeer (this)) // (in case this component was deleted by the event) | |||
return; | |||
} | |||
@@ -810,13 +816,24 @@ void UIViewComponentPeer::handleTouches (UIEvent* event, const bool isDown, cons | |||
modsToSend = currentModifiers = currentModifiers.withoutMouseButtons(); | |||
} | |||
handleMouseEvent (touchIndex, pos, modsToSend, time); | |||
float pressure = MouseInputSource::invalidPressure; | |||
#if defined (__IPHONE_9_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_9_0 | |||
if (touch.maximumPossibleForce > 0) | |||
// NB: other devices return 0 or 1.0 if pressure is unknown, so we'll clip our value to a believable range: | |||
pressure = jlimit (0.0001f, 0.9999f, (float) (touch.force / touch.maximumPossibleForce)); | |||
#endif | |||
handleMouseEvent (touchIndex, pos, modsToSend, pressure, time); | |||
if (! isValidPeer (this)) // (in case this component was deleted by the event) | |||
return; | |||
if (isUp || isCancel) | |||
{ | |||
handleMouseEvent (touchIndex, Point<float> (-1.0f, -1.0f), modsToSend, time); | |||
handleMouseEvent (touchIndex, Point<float> (-1.0f, -1.0f), | |||
modsToSend, MouseInputSource::invalidPressure, time); | |||
if (! isValidPeer (this)) | |||
return; | |||
} | |||
@@ -2215,7 +2215,8 @@ public: | |||
{ | |||
currentModifiers = currentModifiers.withFlags (buttonModifierFlag); | |||
toFront (true); | |||
handleMouseEvent (0, getMousePos (buttonPressEvent), currentModifiers, getEventTime (buttonPressEvent)); | |||
handleMouseEvent (0, getMousePos (buttonPressEvent), currentModifiers, | |||
MouseInputSource::invalidPressure, getEventTime (buttonPressEvent)); | |||
} | |||
void handleButtonPressEvent (const XButtonPressedEvent& buttonPressEvent) | |||
@@ -2253,7 +2254,8 @@ public: | |||
if (dragState.dragging) | |||
handleExternalDragButtonReleaseEvent(); | |||
handleMouseEvent (0, getMousePos (buttonRelEvent), currentModifiers, getEventTime (buttonRelEvent)); | |||
handleMouseEvent (0, getMousePos (buttonRelEvent), currentModifiers, | |||
MouseInputSource::invalidPressure, getEventTime (buttonRelEvent)); | |||
clearLastMousePos(); | |||
} | |||
@@ -2267,7 +2269,8 @@ public: | |||
if (dragState.dragging) | |||
handleExternalDragMotionNotify(); | |||
handleMouseEvent (0, getMousePos (movedEvent), currentModifiers, getEventTime (movedEvent)); | |||
handleMouseEvent (0, getMousePos (movedEvent), currentModifiers, | |||
MouseInputSource::invalidPressure, getEventTime (movedEvent)); | |||
} | |||
void handleEnterNotifyEvent (const XEnterWindowEvent& enterEvent) | |||
@@ -2280,7 +2283,8 @@ public: | |||
if (! currentModifiers.isAnyMouseButtonDown()) | |||
{ | |||
updateKeyModifiers ((int) enterEvent.state); | |||
handleMouseEvent (0, getMousePos (enterEvent), currentModifiers, getEventTime (enterEvent)); | |||
handleMouseEvent (0, getMousePos (enterEvent), currentModifiers, | |||
MouseInputSource::invalidPressure, getEventTime (enterEvent)); | |||
} | |||
} | |||
@@ -2293,7 +2297,8 @@ public: | |||
|| leaveEvent.mode == NotifyUngrab) | |||
{ | |||
updateKeyModifiers ((int) leaveEvent.state); | |||
handleMouseEvent (0, getMousePos (leaveEvent), currentModifiers, getEventTime (leaveEvent)); | |||
handleMouseEvent (0, getMousePos (leaveEvent), currentModifiers, | |||
MouseInputSource::invalidPressure, getEventTime (leaveEvent)); | |||
} | |||
} | |||
@@ -587,7 +587,8 @@ public: | |||
sendMouseEvent (ev); | |||
else | |||
// moved into another window which overlaps this one, so trigger an exit | |||
handleMouseEvent (0, Point<float> (-1.0f, -1.0f), currentModifiers, getMouseTime (ev)); | |||
handleMouseEvent (0, Point<float> (-1.0f, -1.0f), currentModifiers, | |||
getMousePressure (ev), getMouseTime (ev)); | |||
showArrowCursorIfNeeded(); | |||
} | |||
@@ -678,7 +679,8 @@ public: | |||
void sendMouseEvent (NSEvent* ev) | |||
{ | |||
updateModifiers (ev); | |||
handleMouseEvent (0, getMousePos (ev, view), currentModifiers, getMouseTime (ev)); | |||
handleMouseEvent (0, getMousePos (ev, view), currentModifiers, | |||
getMousePressure (ev), getMouseTime (ev)); | |||
} | |||
bool handleKeyEvent (NSEvent* ev, bool isKeyDown) | |||
@@ -1080,10 +1082,15 @@ public: | |||
return keyCode; | |||
} | |||
static int64 getMouseTime (NSEvent* e) | |||
static int64 getMouseTime (NSEvent* e) noexcept | |||
{ | |||
return (Time::currentTimeMillis() - Time::getMillisecondCounter()) | |||
+ (int64) ([e timestamp] * 1000.0); | |||
+ (int64) ([e timestamp] * 1000.0); | |||
} | |||
static float getMousePressure (NSEvent* e) noexcept | |||
{ | |||
return (float) e.pressure; | |||
} | |||
static Point<float> getMousePos (NSEvent* e, NSView* view) | |||
@@ -1663,9 +1663,9 @@ private: | |||
} | |||
//============================================================================== | |||
void doMouseEvent (Point<float> position) | |||
void doMouseEvent (Point<float> position, float pressure) | |||
{ | |||
handleMouseEvent (0, position, currentModifiers, getMouseEventTime()); | |||
handleMouseEvent (0, position, currentModifiers, pressure, getMouseEventTime()); | |||
} | |||
StringArray getAvailableRenderingEngines() override | |||
@@ -1760,7 +1760,7 @@ private: | |||
if (now >= lastMouseTime + minTimeBetweenMouses) | |||
{ | |||
lastMouseTime = now; | |||
doMouseEvent (position); | |||
doMouseEvent (position, MouseInputSource::invalidPressure); | |||
} | |||
} | |||
@@ -1780,7 +1780,7 @@ private: | |||
updateModifiersFromWParam (wParam); | |||
isDragging = true; | |||
doMouseEvent (position); | |||
doMouseEvent (position, MouseInputSource::invalidPressure); | |||
} | |||
} | |||
@@ -1801,7 +1801,7 @@ private: | |||
// NB: under some circumstances (e.g. double-clicking a native title bar), a mouse-up can | |||
// arrive without a mouse-down, so in that case we need to avoid sending a message. | |||
if (wasDragging) | |||
doMouseEvent (position); | |||
doMouseEvent (position, MouseInputSource::invalidPressure); | |||
} | |||
void doCaptureChanged() | |||
@@ -1821,7 +1821,7 @@ private: | |||
void doMouseExit() | |||
{ | |||
isMouseOver = false; | |||
doMouseEvent (getCurrentMousePos()); | |||
doMouseEvent (getCurrentMousePos(), MouseInputSource::invalidPressure); | |||
} | |||
ComponentPeer* findPeerUnderMouse (Point<float>& localPos) | |||
@@ -1925,6 +1925,7 @@ private: | |||
const int64 time = getMouseEventTime(); | |||
const Point<float> pos (globalToLocal (Point<float> (static_cast<float> (TOUCH_COORD_TO_PIXEL (touch.x)), | |||
static_cast<float> (TOUCH_COORD_TO_PIXEL (touch.y))))); | |||
const float pressure = MouseInputSource::invalidPressure; | |||
ModifierKeys modsToSend (currentModifiers); | |||
if (isDown) | |||
@@ -1932,9 +1933,10 @@ private: | |||
currentModifiers = currentModifiers.withoutMouseButtons().withFlags (ModifierKeys::leftButtonModifier); | |||
modsToSend = currentModifiers; | |||
// this forces a mouse-enter/up event, in case for some reason we didn't get a mouse-up before. | |||
handleMouseEvent (touchIndex, pos.toFloat(), modsToSend.withoutMouseButtons(), time); | |||
if (! isValidPeer (this)) // (in case this component was deleted by the event) | |||
// this forces a mouse-enter/up event, in case for some reason we didn't get a mouse-up before. | |||
handleMouseEvent (touchIndex, pos.toFloat(), modsToSend.withoutMouseButtons(), pressure, time); | |||
if (! isValidPeer (this)) // (in case this component was deleted by the event) | |||
return false; | |||
} | |||
else if (isUp) | |||
@@ -1956,13 +1958,15 @@ private: | |||
currentModifiers = currentModifiers.withoutMouseButtons(); | |||
} | |||
handleMouseEvent (touchIndex, pos.toFloat(), modsToSend, time); | |||
handleMouseEvent (touchIndex, pos.toFloat(), modsToSend, pressure, time); | |||
if (! isValidPeer (this)) // (in case this component was deleted by the event) | |||
return false; | |||
if (isUp || isCancel) | |||
{ | |||
handleMouseEvent (touchIndex, Point<float> (-10.0f, -10.0f), currentModifiers, time); | |||
handleMouseEvent (touchIndex, Point<float> (-10.0f, -10.0f), currentModifiers, pressure, time); | |||
if (! isValidPeer (this)) | |||
return false; | |||
} | |||
@@ -2248,7 +2252,7 @@ private: | |||
if (contains (pos.roundToInt(), false)) | |||
{ | |||
doMouseEvent (pos); | |||
doMouseEvent (pos, MouseInputSource::invalidPressure); | |||
if (! isValidPeer (this)) | |||
return true; | |||
@@ -85,10 +85,10 @@ bool ComponentPeer::isKioskMode() const | |||
} | |||
//============================================================================== | |||
void ComponentPeer::handleMouseEvent (int touchIndex, Point<float> pos, ModifierKeys newMods, int64 time) | |||
void ComponentPeer::handleMouseEvent (int touchIndex, Point<float> pos, ModifierKeys newMods, float newPressure, int64 time) | |||
{ | |||
if (MouseInputSource* mouse = Desktop::getInstance().mouseSources->getOrCreateMouseInputSource (touchIndex)) | |||
MouseInputSource (*mouse).handleEvent (*this, pos, time, newMods); | |||
MouseInputSource (*mouse).handleEvent (*this, pos, time, newMods, newPressure); | |||
} | |||
void ComponentPeer::handleMouseWheel (int touchIndex, Point<float> pos, int64 time, const MouseWheelDetails& wheel) | |||
@@ -306,7 +306,7 @@ public: | |||
virtual void setAlpha (float newAlpha) = 0; | |||
//============================================================================== | |||
void handleMouseEvent (int touchIndex, Point<float> positionWithinPeer, ModifierKeys newMods, int64 time); | |||
void handleMouseEvent (int touchIndex, Point<float> positionWithinPeer, ModifierKeys newMods, float pressure, int64 time); | |||
void handleMouseWheel (int touchIndex, Point<float> positionWithinPeer, int64 time, const MouseWheelDetails&); | |||
void handleMagnifyGesture (int touchIndex, Point<float> positionWithinPeer, int64 time, float scaleFactor); | |||
@@ -104,6 +104,7 @@ public: | |||
const Time now (Time::getCurrentTime()); | |||
MouseInputSource mouseSource = Desktop::getInstance().getMainMouseSource(); | |||
const float pressure = (float) e.pressure; | |||
if (isLeft || isRight) // Only mouse up is sent by the OS, so simulate a down/up | |||
{ | |||
@@ -113,17 +114,17 @@ public: | |||
owner.mouseDown (MouseEvent (mouseSource, Point<float>(), | |||
eventMods.withFlags (isLeft ? ModifierKeys::leftButtonModifier | |||
: ModifierKeys::rightButtonModifier), | |||
&owner, &owner, now, | |||
pressure, &owner, &owner, now, | |||
Point<float>(), now, 1, false)); | |||
owner.mouseUp (MouseEvent (mouseSource, Point<float>(), eventMods.withoutMouseButtons(), | |||
&owner, &owner, now, | |||
pressure, &owner, &owner, now, | |||
Point<float>(), now, 1, false)); | |||
} | |||
else if (type == NSMouseMoved) | |||
{ | |||
owner.mouseMove (MouseEvent (mouseSource, Point<float>(), eventMods, | |||
&owner, &owner, now, | |||
pressure, &owner, &owner, now, | |||
Point<float>(), now, 1, false)); | |||
} | |||
} | |||
@@ -189,6 +189,7 @@ namespace ActiveXHelpers | |||
peer->handleMouseEvent (0, Point<int> (GET_X_LPARAM (lParam) + activeXRect.left - peerRect.left, | |||
GET_Y_LPARAM (lParam) + activeXRect.top - peerRect.top).toFloat(), | |||
ModifierKeys::getCurrentModifiersRealtime(), | |||
MouseInputSource::invalidPressure, | |||
getMouseEventTime()); | |||
break; | |||
@@ -111,8 +111,8 @@ public: | |||
const Time eventTime (getMouseEventTime()); | |||
const MouseEvent e (Desktop::getInstance().getMainMouseSource(), | |||
Point<float>(), eventMods, &owner, &owner, eventTime, | |||
Point<float>(), eventTime, 1, false); | |||
Point<float>(), eventMods, MouseInputSource::invalidPressure, | |||
&owner, &owner, eventTime, Point<float>(), eventTime, 1, false); | |||
if (lParam == WM_LBUTTONDOWN || lParam == WM_RBUTTONDOWN) | |||
{ | |||