@@ -397,11 +397,9 @@ public: | |||||
if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &isAlive)) && isAlive == 0) | if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &isAlive)) && isAlive == 0) | ||||
return; | return; | ||||
Float64 sr; | |||||
size = sizeof (sr); | |||||
pa.mSelector = kAudioDevicePropertyNominalSampleRate; | |||||
if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &sr))) | |||||
sampleRate = sr; | |||||
const double currentRate = getNominalSampleRate(); | |||||
if (currentRate > 0) | |||||
sampleRate = currentRate; | |||||
UInt32 framesPerBuf = (UInt32) bufferSize; | UInt32 framesPerBuf = (UInt32) bufferSize; | ||||
size = sizeof (framesPerBuf); | size = sizeof (framesPerBuf); | ||||
@@ -525,6 +523,30 @@ public: | |||||
} | } | ||||
} | } | ||||
double getNominalSampleRate() const | |||||
{ | |||||
AudioObjectPropertyAddress pa; | |||||
pa.mSelector = kAudioDevicePropertyNominalSampleRate; | |||||
pa.mScope = kAudioObjectPropertyScopeGlobal; | |||||
pa.mElement = kAudioObjectPropertyElementMaster; | |||||
Float64 sr = 0; | |||||
UInt32 size = (UInt32) sizeof (sr); | |||||
return OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &sr)) ? (double) sr : 0.0; | |||||
} | |||||
bool setNominalSampleRate (double newSampleRate) const | |||||
{ | |||||
if (std::abs (getNominalSampleRate() - newSampleRate) < 1.0) | |||||
return true; | |||||
AudioObjectPropertyAddress pa; | |||||
pa.mSelector = kAudioDevicePropertyNominalSampleRate; | |||||
pa.mScope = kAudioObjectPropertyScopeGlobal; | |||||
pa.mElement = kAudioObjectPropertyElementMaster; | |||||
Float64 sr = newSampleRate; | |||||
return OK (AudioObjectSetPropertyData (deviceID, &pa, 0, 0, sizeof (sr), &sr)); | |||||
} | |||||
//============================================================================== | //============================================================================== | ||||
String reopen (const BigInteger& inputChannels, | String reopen (const BigInteger& inputChannels, | ||||
const BigInteger& outputChannels, | const BigInteger& outputChannels, | ||||
@@ -549,25 +571,23 @@ public: | |||||
numInputChans = activeInputChans.countNumberOfSetBits(); | numInputChans = activeInputChans.countNumberOfSetBits(); | ||||
numOutputChans = activeOutputChans.countNumberOfSetBits(); | numOutputChans = activeOutputChans.countNumberOfSetBits(); | ||||
// set sample rate | |||||
AudioObjectPropertyAddress pa; | |||||
pa.mSelector = kAudioDevicePropertyNominalSampleRate; | |||||
pa.mScope = kAudioObjectPropertyScopeGlobal; | |||||
pa.mElement = kAudioObjectPropertyElementMaster; | |||||
Float64 sr = newSampleRate; | |||||
if (! OK (AudioObjectSetPropertyData (deviceID, &pa, 0, 0, sizeof (sr), &sr))) | |||||
if (! setNominalSampleRate (newSampleRate)) | |||||
{ | { | ||||
updateDetailsFromDevice(); | |||||
error = "Couldn't change sample rate"; | error = "Couldn't change sample rate"; | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
// change buffer size | // change buffer size | ||||
UInt32 framesPerBuf = (UInt32) bufferSizeSamples; | |||||
AudioObjectPropertyAddress pa; | |||||
pa.mSelector = kAudioDevicePropertyBufferFrameSize; | pa.mSelector = kAudioDevicePropertyBufferFrameSize; | ||||
pa.mScope = kAudioObjectPropertyScopeGlobal; | |||||
pa.mElement = kAudioObjectPropertyElementMaster; | |||||
UInt32 framesPerBuf = (UInt32) bufferSizeSamples; | |||||
if (! OK (AudioObjectSetPropertyData (deviceID, &pa, 0, 0, sizeof (framesPerBuf), &framesPerBuf))) | if (! OK (AudioObjectSetPropertyData (deviceID, &pa, 0, 0, sizeof (framesPerBuf), &framesPerBuf))) | ||||
{ | { | ||||
updateDetailsFromDevice(); | |||||
error = "Couldn't change buffer size"; | error = "Couldn't change buffer size"; | ||||
} | } | ||||
else | else | ||||
@@ -643,7 +643,7 @@ public: | |||||
if (metadataValues.size() > 0) | if (metadataValues.size() > 0) | ||||
{ | { | ||||
// The meta data should have been santised for the AIFF format. | |||||
// The meta data should have been sanitised for the AIFF format. | |||||
// If it was originally sourced from a WAV file the MetaDataSource | // If it was originally sourced from a WAV file the MetaDataSource | ||||
// key should be removed (or set to "AIFF") once this has been done | // key should be removed (or set to "AIFF") once this has been done | ||||
jassert (metadataValues.getValue ("MetaDataSource", "None") != "WAV"); | jassert (metadataValues.getValue ("MetaDataSource", "None") != "WAV"); | ||||
@@ -1024,7 +1024,7 @@ public: | |||||
if (metadataValues.size() > 0) | if (metadataValues.size() > 0) | ||||
{ | { | ||||
// The meta data should have been santised for the WAV format. | |||||
// The meta data should have been sanitised for the WAV format. | |||||
// If it was originally sourced from an AIFF file the MetaDataSource | // If it was originally sourced from an AIFF file the MetaDataSource | ||||
// key should be removed (or set to "WAV") once this has been done | // key should be removed (or set to "WAV") once this has been done | ||||
jassert (metadataValues.getValue ("MetaDataSource", "None") != "AIFF"); | jassert (metadataValues.getValue ("MetaDataSource", "None") != "AIFF"); | ||||
@@ -42,7 +42,7 @@ public: | |||||
bool fileMightContainThisPluginType (const String& fileOrIdentifier) override; | bool fileMightContainThisPluginType (const String& fileOrIdentifier) override; | ||||
String getNameOfPluginFromIdentifier (const String& fileOrIdentifier) override; | String getNameOfPluginFromIdentifier (const String& fileOrIdentifier) override; | ||||
bool pluginNeedsRescanning (const PluginDescription&) override; | bool pluginNeedsRescanning (const PluginDescription&) override; | ||||
StringArray searchPathsForPlugins (const FileSearchPath&, bool recursive); | |||||
StringArray searchPathsForPlugins (const FileSearchPath&, bool recursive) override; | |||||
bool doesPluginStillExist (const PluginDescription&) override; | bool doesPluginStillExist (const PluginDescription&) override; | ||||
FileSearchPath getDefaultLocationsToSearch() override; | FileSearchPath getDefaultLocationsToSearch() override; | ||||
bool canScanForPlugins() const override { return true; } | bool canScanForPlugins() const override { return true; } | ||||
@@ -840,9 +840,9 @@ public: | |||||
if (audioUnit != nullptr) | if (audioUnit != nullptr) | ||||
{ | { | ||||
UInt32 paramListSize = 0; | |||||
UInt32 dummy = 0, paramListSize = 0; | |||||
AudioUnitGetProperty (audioUnit, kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, | AudioUnitGetProperty (audioUnit, kAudioUnitProperty_ParameterList, kAudioUnitScope_Global, | ||||
0, 0, ¶mListSize); | |||||
0, &dummy, ¶mListSize); | |||||
if (paramListSize > 0) | if (paramListSize > 0) | ||||
{ | { | ||||
@@ -1145,7 +1145,7 @@ public: | |||||
} | } | ||||
//============================================================================== | //============================================================================== | ||||
int getNumParameters() { return effect != nullptr ? effect->numParams : 0; } | |||||
int getNumParameters() override { return effect != nullptr ? effect->numParams : 0; } | |||||
float getParameter (int index) override | float getParameter (int index) override | ||||
{ | { | ||||
@@ -49,7 +49,7 @@ public: | |||||
virtual int toInt (const ValueUnion&) const noexcept { return 0; } | virtual int toInt (const ValueUnion&) const noexcept { return 0; } | ||||
virtual int64 toInt64 (const ValueUnion&) const noexcept { return 0; } | virtual int64 toInt64 (const ValueUnion&) const noexcept { return 0; } | ||||
virtual double toDouble (const ValueUnion&) const noexcept { return 0; } | virtual double toDouble (const ValueUnion&) const noexcept { return 0; } | ||||
virtual String toString (const ValueUnion&) const { return String::empty; } | |||||
virtual String toString (const ValueUnion&) const { return String(); } | |||||
virtual bool toBool (const ValueUnion&) const noexcept { return false; } | virtual bool toBool (const ValueUnion&) const noexcept { return false; } | ||||
virtual ReferenceCountedObject* toObject (const ValueUnion&) const noexcept { return nullptr; } | virtual ReferenceCountedObject* toObject (const ValueUnion&) const noexcept { return nullptr; } | ||||
virtual Array<var>* toArray (const ValueUnion&) const noexcept { return nullptr; } | virtual Array<var>* toArray (const ValueUnion&) const noexcept { return nullptr; } | ||||
@@ -274,7 +274,7 @@ public: | |||||
} | } | ||||
String toString (const ValueUnion& data) const override { return "Object 0x" + String::toHexString ((int) (pointer_sized_int) data.objectValue); } | String toString (const ValueUnion& data) const override { return "Object 0x" + String::toHexString ((int) (pointer_sized_int) data.objectValue); } | ||||
bool toBool (const ValueUnion& data) const noexcept override { return data.objectValue != 0; } | |||||
bool toBool (const ValueUnion& data) const noexcept override { return data.objectValue != nullptr; } | |||||
ReferenceCountedObject* toObject (const ValueUnion& data) const noexcept override { return data.objectValue; } | ReferenceCountedObject* toObject (const ValueUnion& data) const noexcept override { return data.objectValue; } | ||||
bool isObject() const noexcept override { return true; } | bool isObject() const noexcept override { return true; } | ||||
@@ -992,7 +992,8 @@ double Expression::evaluate() const | |||||
double Expression::evaluate (const Expression::Scope& scope) const | double Expression::evaluate (const Expression::Scope& scope) const | ||||
{ | { | ||||
return term->resolve (scope, 0)->toDouble(); | |||||
String err; | |||||
return evaluate (scope, err); | |||||
} | } | ||||
double Expression::evaluate (const Scope& scope, String& evaluationError) const | double Expression::evaluate (const Scope& scope, String& evaluationError) const | ||||
@@ -1038,20 +1039,16 @@ Expression Expression::adjustedToGiveNewResult (const double targetValue, const | |||||
jassert (termToAdjust != nullptr); | jassert (termToAdjust != nullptr); | ||||
const Term* const parent = Helpers::findDestinationFor (newTerm, termToAdjust); | |||||
if (parent == nullptr) | |||||
if (const Term* parent = Helpers::findDestinationFor (newTerm, termToAdjust)) | |||||
{ | { | ||||
termToAdjust->value = targetValue; | |||||
if (const Helpers::TermPtr reverseTerm = parent->createTermToEvaluateInput (scope, termToAdjust, targetValue, newTerm)) | |||||
termToAdjust->value = Expression (reverseTerm).evaluate (scope); | |||||
else | |||||
return Expression (targetValue); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
const Helpers::TermPtr reverseTerm (parent->createTermToEvaluateInput (scope, termToAdjust, targetValue, newTerm)); | |||||
if (reverseTerm == nullptr) | |||||
return Expression (targetValue); | |||||
termToAdjust->value = reverseTerm->resolve (scope, 0)->toDouble(); | |||||
termToAdjust->value = targetValue; | |||||
} | } | ||||
return Expression (newTerm.release()); | return Expression (newTerm.release()); | ||||
@@ -429,7 +429,7 @@ String SystemStats::getFullUserName() | |||||
String SystemStats::getComputerName() | String SystemStats::getComputerName() | ||||
{ | { | ||||
TCHAR text [MAX_COMPUTERNAME_LENGTH + 1] = { 0 }; | |||||
TCHAR text[128] = { 0 }; | |||||
DWORD len = (DWORD) numElementsInArray (text) - 1; | DWORD len = (DWORD) numElementsInArray (text) - 1; | ||||
GetComputerName (text, &len); | GetComputerName (text, &len); | ||||
return String (text, len); | return String (text, len); | ||||
@@ -26,28 +26,44 @@ | |||||
============================================================================== | ============================================================================== | ||||
*/ | */ | ||||
MACAddress::MACAddress() | |||||
MACAddress::MACAddress() noexcept | |||||
{ | { | ||||
zeromem (address, sizeof (address)); | zeromem (address, sizeof (address)); | ||||
} | } | ||||
MACAddress::MACAddress (const MACAddress& other) | |||||
MACAddress::MACAddress (const MACAddress& other) noexcept | |||||
{ | { | ||||
memcpy (address, other.address, sizeof (address)); | memcpy (address, other.address, sizeof (address)); | ||||
} | } | ||||
MACAddress& MACAddress::operator= (const MACAddress& other) | |||||
MACAddress& MACAddress::operator= (const MACAddress& other) noexcept | |||||
{ | { | ||||
memcpy (address, other.address, sizeof (address)); | memcpy (address, other.address, sizeof (address)); | ||||
return *this; | return *this; | ||||
} | } | ||||
MACAddress::MACAddress (const uint8 bytes[6]) | |||||
MACAddress::MACAddress (const uint8 bytes[6]) noexcept | |||||
{ | { | ||||
memcpy (address, bytes, sizeof (address)); | memcpy (address, bytes, sizeof (address)); | ||||
} | } | ||||
MACAddress::MACAddress (StringRef addressString) | |||||
{ | |||||
MemoryBlock hex; | |||||
hex.loadFromHexString (addressString); | |||||
if (hex.getSize() == sizeof (address)) | |||||
memcpy (address, hex.getData(), sizeof (address)); | |||||
else | |||||
zeromem (address, sizeof (address)); | |||||
} | |||||
String MACAddress::toString() const | String MACAddress::toString() const | ||||
{ | |||||
return toString ("-"); | |||||
} | |||||
String MACAddress::toString (StringRef separator) const | |||||
{ | { | ||||
String s; | String s; | ||||
@@ -56,7 +72,7 @@ String MACAddress::toString() const | |||||
s << String::toHexString ((int) address[i]).paddedLeft ('0', 2); | s << String::toHexString ((int) address[i]).paddedLeft ('0', 2); | ||||
if (i < sizeof (address) - 1) | if (i < sizeof (address) - 1) | ||||
s << '-'; | |||||
s << separator; | |||||
} | } | ||||
return s; | return s; | ||||
@@ -43,16 +43,22 @@ public: | |||||
//============================================================================== | //============================================================================== | ||||
/** Creates a null address (00-00-00-00-00-00). */ | /** Creates a null address (00-00-00-00-00-00). */ | ||||
MACAddress(); | |||||
MACAddress() noexcept; | |||||
/** Creates a copy of another address. */ | /** Creates a copy of another address. */ | ||||
MACAddress (const MACAddress&); | |||||
MACAddress (const MACAddress&) noexcept; | |||||
/** Creates a copy of another address. */ | /** Creates a copy of another address. */ | ||||
MACAddress& operator= (const MACAddress&); | |||||
MACAddress& operator= (const MACAddress&) noexcept; | |||||
/** Creates an address from 6 bytes. */ | /** Creates an address from 6 bytes. */ | ||||
explicit MACAddress (const uint8 bytes[6]); | |||||
explicit MACAddress (const uint8 bytes[6]) noexcept; | |||||
/** Creates an address from a hex string. | |||||
If the string isn't a 6-byte hex value, this will just default-initialise | |||||
the object. | |||||
*/ | |||||
explicit MACAddress (StringRef address); | |||||
/** Returns a pointer to the 6 bytes that make up this address. */ | /** Returns a pointer to the 6 bytes that make up this address. */ | ||||
const uint8* getBytes() const noexcept { return address; } | const uint8* getBytes() const noexcept { return address; } | ||||
@@ -60,6 +66,9 @@ public: | |||||
/** Returns a dash-separated string in the form "11-22-33-44-55-66" */ | /** Returns a dash-separated string in the form "11-22-33-44-55-66" */ | ||||
String toString() const; | String toString() const; | ||||
/** Returns a hex string of this address, using a custom separator between each byte. */ | |||||
String toString (StringRef separator) const; | |||||
/** Returns the address in the lower 6 bytes of an int64. | /** Returns the address in the lower 6 bytes of an int64. | ||||
This uses a little-endian arrangement, with the first byte of the address being | This uses a little-endian arrangement, with the first byte of the address being | ||||
@@ -67,13 +67,18 @@ int MemoryInputStream::read (void* const buffer, const int howMany) | |||||
{ | { | ||||
jassert (buffer != nullptr && howMany >= 0); | jassert (buffer != nullptr && howMany >= 0); | ||||
const int num = jmin (howMany, (int) (dataSize - position)); | |||||
if (num <= 0) | |||||
if (howMany <= 0 || position >= dataSize) | |||||
return 0; | return 0; | ||||
memcpy (buffer, addBytesToPointer (data, position), (size_t) num); | |||||
position += (unsigned int) num; | |||||
return num; | |||||
const size_t num = jmin ((size_t) howMany, dataSize - position); | |||||
if (num > 0) | |||||
{ | |||||
memcpy (buffer, addBytesToPointer (data, position), num); | |||||
position += num; | |||||
} | |||||
return (int) num; | |||||
} | } | ||||
bool MemoryInputStream::isExhausted() | bool MemoryInputStream::isExhausted() | ||||
@@ -40,6 +40,10 @@ | |||||
When you create a Value with its default constructor, it acts as a wrapper around a | When you create a Value with its default constructor, it acts as a wrapper around a | ||||
simple var object, but by creating a Value that refers to a custom subclass of ValueSource, | simple var object, but by creating a Value that refers to a custom subclass of ValueSource, | ||||
you can map the Value onto any kind of underlying data. | you can map the Value onto any kind of underlying data. | ||||
Important note! The Value class is not thread-safe! If you're accessing one from | |||||
multiple threads, then you'll need to use your own synchronisation around any code | |||||
that accesses it. | |||||
*/ | */ | ||||
class JUCE_API Value | class JUCE_API Value | ||||
{ | { | ||||
@@ -222,20 +222,21 @@ namespace CoreTextTypeLayout | |||||
CFStringRef cfText = text.getText().toCFString(); | CFStringRef cfText = text.getText().toCFString(); | ||||
CFMutableAttributedStringRef attribString = CFAttributedStringCreateMutable (kCFAllocatorDefault, 0); | CFMutableAttributedStringRef attribString = CFAttributedStringCreateMutable (kCFAllocatorDefault, 0); | ||||
CFAttributedStringReplaceString (attribString, CFRangeMake(0, 0), cfText); | |||||
CFAttributedStringReplaceString (attribString, CFRangeMake (0, 0), cfText); | |||||
CFRelease (cfText); | CFRelease (cfText); | ||||
const int numCharacterAttributes = text.getNumAttributes(); | const int numCharacterAttributes = text.getNumAttributes(); | ||||
const CFIndex attribStringLen = CFAttributedStringGetLength (attribString); | |||||
for (int i = 0; i < numCharacterAttributes; ++i) | for (int i = 0; i < numCharacterAttributes; ++i) | ||||
{ | { | ||||
const AttributedString::Attribute& attr = *text.getAttribute (i); | const AttributedString::Attribute& attr = *text.getAttribute (i); | ||||
const int rangeStart = attr.range.getStart(); | |||||
if (attr.range.getStart() > CFAttributedStringGetLength (attribString)) | |||||
if (rangeStart >= attribStringLen) | |||||
continue; | continue; | ||||
Range<int> range (attr.range); | |||||
range.setEnd (jmin (range.getEnd(), (int) CFAttributedStringGetLength (attribString))); | |||||
CFRange range = CFRangeMake (rangeStart, jmin (attr.range.getEnd(), (int) attribStringLen) - rangeStart); | |||||
if (const Font* const f = attr.getFont()) | if (const Font* const f = attr.getFont()) | ||||
{ | { | ||||
@@ -243,8 +244,19 @@ namespace CoreTextTypeLayout | |||||
{ | { | ||||
ctFontRef = getFontWithPointSize (ctFontRef, f->getHeight() * getHeightToPointsFactor (ctFontRef)); | ctFontRef = getFontWithPointSize (ctFontRef, f->getHeight() * getHeightToPointsFactor (ctFontRef)); | ||||
CFAttributedStringSetAttribute (attribString, CFRangeMake (range.getStart(), range.getLength()), | |||||
kCTFontAttributeName, ctFontRef); | |||||
CFAttributedStringSetAttribute (attribString, range, kCTFontAttributeName, ctFontRef); | |||||
float extraKerning = f->getExtraKerningFactor(); | |||||
if (extraKerning != 0.0f) | |||||
{ | |||||
extraKerning *= f->getHeight(); | |||||
CFNumberRef numberRef = CFNumberCreate (0, kCFNumberFloatType, &extraKerning); | |||||
CFAttributedStringSetAttribute (attribString, range, kCTKernAttributeName, numberRef); | |||||
CFRelease (numberRef); | |||||
} | |||||
CFRelease (ctFontRef); | CFRelease (ctFontRef); | ||||
} | } | ||||
} | } | ||||
@@ -264,9 +276,7 @@ namespace CoreTextTypeLayout | |||||
col->getFloatAlpha()); | col->getFloatAlpha()); | ||||
#endif | #endif | ||||
CFAttributedStringSetAttribute (attribString, | |||||
CFRangeMake (range.getStart(), range.getLength()), | |||||
kCTForegroundColorAttributeName, colour); | |||||
CFAttributedStringSetAttribute (attribString, range, kCTForegroundColorAttributeName, colour); | |||||
CGColorRelease (colour); | CGColorRelease (colour); | ||||
} | } | ||||
} | } | ||||
@@ -51,10 +51,10 @@ public: | |||||
Remember that when the target component is resized, it'll need to move and | Remember that when the target component is resized, it'll need to move and | ||||
resize this component to keep it in place, as this won't happen automatically. | resize this component to keep it in place, as this won't happen automatically. | ||||
If the constrainer parameter is non-zero, then this object will be used to enforce | |||||
If a constrainer object is provided, then this object will be used to enforce | |||||
limits on the size and position that the component can be stretched to. Make sure | limits on the size and position that the component can be stretched to. Make sure | ||||
that the constrainer isn't deleted while still in use by this object. If you | that the constrainer isn't deleted while still in use by this object. If you | ||||
pass a zero in here, no limits will be put on the sizes it can be stretched to. | |||||
pass a nullptr in here, no limits will be put on the sizes it can be stretched to. | |||||
@see ComponentBoundsConstrainer | @see ComponentBoundsConstrainer | ||||
*/ | */ | ||||
@@ -131,7 +131,7 @@ public: | |||||
/** OSX ONLY - Sets the model that is currently being shown as the main | /** OSX ONLY - Sets the model that is currently being shown as the main | ||||
menu bar at the top of the screen on the Mac. | menu bar at the top of the screen on the Mac. | ||||
You can pass 0 to stop the current model being displayed. Be careful | |||||
You can pass nullptr to stop the current model being displayed. Be careful | |||||
not to delete a model while it is being used. | not to delete a model while it is being used. | ||||
An optional extra menu can be specified, containing items to add to the top of | An optional extra menu can be specified, containing items to add to the top of | ||||
@@ -39,6 +39,14 @@ | |||||
#define WM_APPCOMMAND 0x0319 | #define WM_APPCOMMAND 0x0319 | ||||
#endif | #endif | ||||
#ifndef MI_WP_SIGNATURE | |||||
#define MI_WP_SIGNATURE 0xFF515700 | |||||
#endif | |||||
#ifndef SIGNATURE_MASK | |||||
#define SIGNATURE_MASK 0xFFFFFF00 | |||||
#endif | |||||
extern void juce_repeatLastProcessPriority(); | extern void juce_repeatLastProcessPriority(); | ||||
extern void juce_checkCurrentlyFocusedTopLevelWindow(); // in juce_TopLevelWindow.cpp | extern void juce_checkCurrentlyFocusedTopLevelWindow(); // in juce_TopLevelWindow.cpp | ||||
extern bool juce_isRunningInWine(); | extern bool juce_isRunningInWine(); | ||||
@@ -1706,8 +1714,22 @@ private: | |||||
return 1000 / 60; // Throttling the incoming mouse-events seems to still be needed in XP.. | return 1000 / 60; // Throttling the incoming mouse-events seems to still be needed in XP.. | ||||
} | } | ||||
bool isTouchEvent() noexcept | |||||
{ | |||||
if (registerTouchWindow == nullptr) | |||||
return false; | |||||
LPARAM dw = GetMessageExtraInfo(); | |||||
// see https://msdn.microsoft.com/en-us/library/windows/desktop/ms703320(v=vs.85).aspx | |||||
return (dw & SIGNATURE_MASK) == MI_WP_SIGNATURE; | |||||
} | |||||
void doMouseMove (Point<float> position) | void doMouseMove (Point<float> position) | ||||
{ | { | ||||
// this will be handled by WM_TOUCH | |||||
if (isTouchEvent()) | |||||
return; | |||||
if (! isMouseOver) | if (! isMouseOver) | ||||
{ | { | ||||
isMouseOver = true; | isMouseOver = true; | ||||
@@ -1744,6 +1766,10 @@ private: | |||||
void doMouseDown (Point<float> position, const WPARAM wParam) | void doMouseDown (Point<float> position, const WPARAM wParam) | ||||
{ | { | ||||
// this will be handled by WM_TOUCH | |||||
if (isTouchEvent()) | |||||
return; | |||||
if (GetCapture() != hwnd) | if (GetCapture() != hwnd) | ||||
SetCapture (hwnd); | SetCapture (hwnd); | ||||
@@ -1760,6 +1786,10 @@ private: | |||||
void doMouseUp (Point<float> position, const WPARAM wParam) | void doMouseUp (Point<float> position, const WPARAM wParam) | ||||
{ | { | ||||
// this will be handled by WM_TOUCH | |||||
if (isTouchEvent()) | |||||
return; | |||||
updateModifiersFromWParam (wParam); | updateModifiersFromWParam (wParam); | ||||
const bool wasDragging = isDragging; | const bool wasDragging = isDragging; | ||||
isDragging = false; | isDragging = false; | ||||
@@ -1879,8 +1909,7 @@ private: | |||||
const DWORD flags = inputInfo[i].dwFlags; | const DWORD flags = inputInfo[i].dwFlags; | ||||
if ((flags & (TOUCHEVENTF_DOWN | TOUCHEVENTF_MOVE | TOUCHEVENTF_UP)) != 0) | if ((flags & (TOUCHEVENTF_DOWN | TOUCHEVENTF_MOVE | TOUCHEVENTF_UP)) != 0) | ||||
if (! handleTouchInput (inputInfo[i], (flags & TOUCHEVENTF_PRIMARY) != 0, | |||||
(flags & TOUCHEVENTF_DOWN) != 0, (flags & TOUCHEVENTF_UP) != 0)) | |||||
if (! handleTouchInput (inputInfo[i], (flags & TOUCHEVENTF_DOWN) != 0, (flags & TOUCHEVENTF_UP) != 0)) | |||||
return 0; // abandon method if this window was deleted by the callback | return 0; // abandon method if this window was deleted by the callback | ||||
} | } | ||||
} | } | ||||
@@ -1889,7 +1918,7 @@ private: | |||||
return 0; | return 0; | ||||
} | } | ||||
bool handleTouchInput (const TOUCHINPUT& touch, const bool isPrimary, const bool isDown, const bool isUp) | |||||
bool handleTouchInput (const TOUCHINPUT& touch, const bool isDown, const bool isUp) | |||||
{ | { | ||||
bool isCancel = false; | bool isCancel = false; | ||||
const int touchIndex = currentTouches.getIndexOfTouch (touch.dwID); | const int touchIndex = currentTouches.getIndexOfTouch (touch.dwID); | ||||
@@ -1903,13 +1932,10 @@ private: | |||||
currentModifiers = currentModifiers.withoutMouseButtons().withFlags (ModifierKeys::leftButtonModifier); | currentModifiers = currentModifiers.withoutMouseButtons().withFlags (ModifierKeys::leftButtonModifier); | ||||
modsToSend = currentModifiers; | modsToSend = currentModifiers; | ||||
if (! isPrimary) | |||||
{ | |||||
// 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) | |||||
return false; | |||||
} | |||||
// 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) | |||||
return false; | |||||
} | } | ||||
else if (isUp) | else if (isUp) | ||||
{ | { | ||||
@@ -1930,14 +1956,11 @@ private: | |||||
currentModifiers = currentModifiers.withoutMouseButtons(); | currentModifiers = currentModifiers.withoutMouseButtons(); | ||||
} | } | ||||
if (! isPrimary) | |||||
{ | |||||
handleMouseEvent (touchIndex, pos.toFloat(), modsToSend, time); | |||||
if (! isValidPeer (this)) // (in case this component was deleted by the event) | |||||
return false; | |||||
} | |||||
handleMouseEvent (touchIndex, pos.toFloat(), modsToSend, time); | |||||
if (! isValidPeer (this)) // (in case this component was deleted by the event) | |||||
return false; | |||||
if ((isUp || isCancel) && ! isPrimary) | |||||
if (isUp || isCancel) | |||||
{ | { | ||||
handleMouseEvent (touchIndex, Point<float> (-10.0f, -10.0f), currentModifiers, time); | handleMouseEvent (touchIndex, Point<float> (-10.0f, -10.0f), currentModifiers, time); | ||||
if (! isValidPeer (this)) | if (! isValidPeer (this)) | ||||
@@ -309,7 +309,7 @@ TextEditor* Label::createEditorComponent() | |||||
copyColourIfSpecified (*this, *ed, textWhenEditingColourId, TextEditor::textColourId); | copyColourIfSpecified (*this, *ed, textWhenEditingColourId, TextEditor::textColourId); | ||||
copyColourIfSpecified (*this, *ed, backgroundWhenEditingColourId, TextEditor::backgroundColourId); | copyColourIfSpecified (*this, *ed, backgroundWhenEditingColourId, TextEditor::backgroundColourId); | ||||
copyColourIfSpecified (*this, *ed, outlineWhenEditingColourId, TextEditor::outlineColourId); | |||||
copyColourIfSpecified (*this, *ed, outlineWhenEditingColourId, TextEditor::focusedOutlineColourId); | |||||
return ed; | return ed; | ||||
} | } | ||||
@@ -89,7 +89,7 @@ void AlertWindow::addButton (const String& name, | |||||
const KeyPress& shortcutKey1, | const KeyPress& shortcutKey1, | ||||
const KeyPress& shortcutKey2) | const KeyPress& shortcutKey2) | ||||
{ | { | ||||
TextButton* const b = new TextButton (name, String::empty); | |||||
TextButton* const b = new TextButton (name, String()); | |||||
buttons.add (b); | buttons.add (b); | ||||
b->setWantsKeyboardFocus (true); | b->setWantsKeyboardFocus (true); | ||||
@@ -143,9 +143,9 @@ void AlertWindow::addTextEditor (const String& name, | |||||
ed->setColour (TextEditor::outlineColourId, findColour (ComboBox::outlineColourId)); | ed->setColour (TextEditor::outlineColourId, findColour (ComboBox::outlineColourId)); | ||||
ed->setFont (getLookAndFeel().getAlertWindowMessageFont()); | ed->setFont (getLookAndFeel().getAlertWindowMessageFont()); | ||||
addAndMakeVisible (ed); | |||||
ed->setText (initialContents); | ed->setText (initialContents); | ||||
ed->setCaretPosition (initialContents.length()); | ed->setCaretPosition (initialContents.length()); | ||||
addAndMakeVisible (ed); | |||||
textboxNames.add (onScreenLabel); | textboxNames.add (onScreenLabel); | ||||
updateLayout (false); | updateLayout (false); | ||||
@@ -165,7 +165,7 @@ String AlertWindow::getTextEditorContents (const String& nameOfTextEditor) const | |||||
if (TextEditor* const t = getTextEditor (nameOfTextEditor)) | if (TextEditor* const t = getTextEditor (nameOfTextEditor)) | ||||
return t->getText(); | return t->getText(); | ||||
return String::empty; | |||||
return String(); | |||||
} | } | ||||
@@ -66,14 +66,14 @@ struct CppTokeniserFunctions | |||||
static const char* const keywords7Char[] = | static const char* const keywords7Char[] = | ||||
{ "nullptr", "alignas", "alignof", "default", "mutable", "private", | { "nullptr", "alignas", "alignof", "default", "mutable", "private", | ||||
"typedef", "virtual", "wchar_t", nullptr }; | |||||
"typedef", "virtual", "wchar_t", "__cdecl", "_Pragma", "uint8_t", nullptr }; | |||||
static const char* const keywordsOther[] = | static const char* const keywordsOther[] = | ||||
{ "char16_t", "char32_t", "const_cast", "constexpr", "continue", "decltype", "dynamic_cast", | { "char16_t", "char32_t", "const_cast", "constexpr", "continue", "decltype", "dynamic_cast", | ||||
"explicit", "namespace", "noexcept", "operator", "protected", "register", "reinterpret_cast", | "explicit", "namespace", "noexcept", "operator", "protected", "register", "reinterpret_cast", | ||||
"static_assert", "static_cast", "template", "thread_local", "typename", "unsigned", "volatile", | "static_assert", "static_cast", "template", "thread_local", "typename", "unsigned", "volatile", | ||||
"@class", "@dynamic", "@end", "@implementation", "@interface", "@public", "@private", | "@class", "@dynamic", "@end", "@implementation", "@interface", "@public", "@private", | ||||
"@protected", "@property", "@synthesize", nullptr }; | |||||
"@protected", "@property", "@synthesize", "__fastcall", "__stdcall", nullptr }; | |||||
const char* const* k; | const char* const* k; | ||||