@@ -412,7 +412,7 @@ void JUCE_CALLTYPE FloatVectorOperations::copy (double* dest, const double* src, | |||
void JUCE_CALLTYPE FloatVectorOperations::copyWithMultiply (float* dest, const float* src, float multiplier, int num) noexcept | |||
{ | |||
#if JUCE_USE_VDSP_FRAMEWORK | |||
vDSP_vsmul (src, 1, &multiplier, dest, 1, num); | |||
vDSP_vsmul (src, 1, &multiplier, dest, 1, (vDSP_Length) num); | |||
#else | |||
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] * multiplier, Mode::mul (mult, s), | |||
JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST, | |||
@@ -423,7 +423,7 @@ void JUCE_CALLTYPE FloatVectorOperations::copyWithMultiply (float* dest, const f | |||
void JUCE_CALLTYPE FloatVectorOperations::copyWithMultiply (double* dest, const double* src, double multiplier, int num) noexcept | |||
{ | |||
#if JUCE_USE_VDSP_FRAMEWORK | |||
vDSP_vsmulD (src, 1, &multiplier, dest, 1, num); | |||
vDSP_vsmulD (src, 1, &multiplier, dest, 1, (vDSP_Length) num); | |||
#else | |||
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] * multiplier, Mode::mul (mult, s), | |||
JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST, | |||
@@ -446,7 +446,7 @@ void JUCE_CALLTYPE FloatVectorOperations::add (double* dest, double amount, int | |||
void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, const float* src, int num) noexcept | |||
{ | |||
#if JUCE_USE_VDSP_FRAMEWORK | |||
vDSP_vadd (src, 1, dest, 1, dest, 1, num); | |||
vDSP_vadd (src, 1, dest, 1, dest, 1, (vDSP_Length) num); | |||
#else | |||
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] += src[i], Mode::add (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST, ) | |||
#endif | |||
@@ -455,7 +455,7 @@ void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, const float* src, in | |||
void JUCE_CALLTYPE FloatVectorOperations::add (double* dest, const double* src, int num) noexcept | |||
{ | |||
#if JUCE_USE_VDSP_FRAMEWORK | |||
vDSP_vaddD (src, 1, dest, 1, dest, 1, num); | |||
vDSP_vaddD (src, 1, dest, 1, dest, 1, (vDSP_Length) num); | |||
#else | |||
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] += src[i], Mode::add (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST, ) | |||
#endif | |||
@@ -464,7 +464,7 @@ void JUCE_CALLTYPE FloatVectorOperations::add (double* dest, const double* src, | |||
void JUCE_CALLTYPE FloatVectorOperations::subtract (float* dest, const float* src, int num) noexcept | |||
{ | |||
#if JUCE_USE_VDSP_FRAMEWORK | |||
vDSP_vsub (src, 1, dest, 1, dest, 1, num); | |||
vDSP_vsub (src, 1, dest, 1, dest, 1, (vDSP_Length) num); | |||
#else | |||
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] -= src[i], Mode::sub (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST, ) | |||
#endif | |||
@@ -473,7 +473,7 @@ void JUCE_CALLTYPE FloatVectorOperations::subtract (float* dest, const float* sr | |||
void JUCE_CALLTYPE FloatVectorOperations::subtract (double* dest, const double* src, int num) noexcept | |||
{ | |||
#if JUCE_USE_VDSP_FRAMEWORK | |||
vDSP_vsubD (src, 1, dest, 1, dest, 1, num); | |||
vDSP_vsubD (src, 1, dest, 1, dest, 1, (vDSP_Length) num); | |||
#else | |||
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] -= src[i], Mode::sub (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST, ) | |||
#endif | |||
@@ -496,7 +496,7 @@ void JUCE_CALLTYPE FloatVectorOperations::addWithMultiply (double* dest, const d | |||
void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, const float* src, int num) noexcept | |||
{ | |||
#if JUCE_USE_VDSP_FRAMEWORK | |||
vDSP_vmul (src, 1, dest, 1, dest, 1, num); | |||
vDSP_vmul (src, 1, dest, 1, dest, 1, (vDSP_Length) num); | |||
#else | |||
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] *= src[i], Mode::mul (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST, ) | |||
#endif | |||
@@ -505,7 +505,7 @@ void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, const float* sr | |||
void JUCE_CALLTYPE FloatVectorOperations::multiply (double* dest, const double* src, int num) noexcept | |||
{ | |||
#if JUCE_USE_VDSP_FRAMEWORK | |||
vDSP_vmulD (src, 1, dest, 1, dest, 1, num); | |||
vDSP_vmulD (src, 1, dest, 1, dest, 1, (vDSP_Length) num); | |||
#else | |||
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] *= src[i], Mode::mul (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST, ) | |||
#endif | |||
@@ -514,7 +514,7 @@ void JUCE_CALLTYPE FloatVectorOperations::multiply (double* dest, const double* | |||
void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, float multiplier, int num) noexcept | |||
{ | |||
#if JUCE_USE_VDSP_FRAMEWORK | |||
vDSP_vsmul (dest, 1, &multiplier, dest, 1, num); | |||
vDSP_vsmul (dest, 1, &multiplier, dest, 1, (vDSP_Length) num); | |||
#else | |||
JUCE_PERFORM_VEC_OP_DEST (dest[i] *= multiplier, Mode::mul (d, mult), JUCE_LOAD_DEST, | |||
const Mode::ParallelType mult = Mode::load1 (multiplier);) | |||
@@ -524,7 +524,7 @@ void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, float multiplie | |||
void JUCE_CALLTYPE FloatVectorOperations::multiply (double* dest, double multiplier, int num) noexcept | |||
{ | |||
#if JUCE_USE_VDSP_FRAMEWORK | |||
vDSP_vsmulD (dest, 1, &multiplier, dest, 1, num); | |||
vDSP_vsmulD (dest, 1, &multiplier, dest, 1, (vDSP_Length) num); | |||
#else | |||
JUCE_PERFORM_VEC_OP_DEST (dest[i] *= multiplier, Mode::mul (d, mult), JUCE_LOAD_DEST, | |||
const Mode::ParallelType mult = Mode::load1 (multiplier);) | |||
@@ -643,8 +643,8 @@ public: | |||
const int range = random.nextBool() ? 500 : 10; | |||
const int num = random.nextInt (range) + 1; | |||
HeapBlock<ValueType> buffer1 (num + 16), buffer2 (num + 16); | |||
HeapBlock<int> buffer3 (num + 16); | |||
HeapBlock<ValueType> buffer1 ((size_t) num + 16), buffer2 ((size_t) num + 16); | |||
HeapBlock<int> buffer3 ((size_t) num + 16); | |||
#if JUCE_ARM | |||
ValueType* const data1 = buffer1; | |||
@@ -210,7 +210,7 @@ bool MidiBuffer::Iterator::getNextEvent (const uint8* &midiData, int& numBytes, | |||
const int itemSize = MidiBufferHelpers::getEventDataSize (data); | |||
numBytes = itemSize; | |||
midiData = data + sizeof (int32) + sizeof (uint16); | |||
data += sizeof (int32) + sizeof (uint16) + itemSize; | |||
data += sizeof (int32) + sizeof (uint16) + (size_t) itemSize; | |||
return true; | |||
} | |||
@@ -223,7 +223,7 @@ bool MidiBuffer::Iterator::getNextEvent (MidiMessage& result, int& samplePositio | |||
samplePosition = MidiBufferHelpers::getEventTime (data); | |||
const int itemSize = MidiBufferHelpers::getEventDataSize (data); | |||
result = MidiMessage (data + sizeof (int32) + sizeof (uint16), itemSize, samplePosition); | |||
data += sizeof (int32) + sizeof (uint16) + itemSize; | |||
data += sizeof (int32) + sizeof (uint16) + (size_t) itemSize; | |||
return true; | |||
} |
@@ -129,7 +129,7 @@ MidiMessage::MidiMessage (const MidiMessage& other) | |||
{ | |||
if (other.allocatedData != nullptr) | |||
{ | |||
allocatedData.malloc (size); | |||
allocatedData.malloc ((size_t) size); | |||
memcpy (allocatedData, other.allocatedData, (size_t) size); | |||
} | |||
else | |||
@@ -143,7 +143,7 @@ MidiMessage::MidiMessage (const MidiMessage& other, const double newTimeStamp) | |||
{ | |||
if (other.allocatedData != nullptr) | |||
{ | |||
allocatedData.malloc (size); | |||
allocatedData.malloc ((size_t) size); | |||
memcpy (allocatedData, other.allocatedData, (size_t) size); | |||
} | |||
else | |||
@@ -255,7 +255,7 @@ MidiMessage& MidiMessage::operator= (const MidiMessage& other) | |||
if (other.allocatedData != nullptr) | |||
{ | |||
allocatedData.malloc (size); | |||
allocatedData.malloc ((size_t) size); | |||
memcpy (allocatedData, other.allocatedData, (size_t) size); | |||
} | |||
else | |||
@@ -297,7 +297,7 @@ uint8* MidiMessage::allocateSpace (int bytes) | |||
{ | |||
if (bytes > 4) | |||
{ | |||
allocatedData.malloc (bytes); | |||
allocatedData.malloc ((size_t) bytes); | |||
return allocatedData; | |||
} | |||
@@ -47,23 +47,28 @@ void ResamplingAudioSource::setResamplingRatio (const double samplesInPerOutputS | |||
ratio = jmax (0.0, samplesInPerOutputSample); | |||
} | |||
void ResamplingAudioSource::prepareToPlay (int samplesPerBlockExpected, | |||
double sampleRate) | |||
void ResamplingAudioSource::prepareToPlay (int samplesPerBlockExpected, double sampleRate) | |||
{ | |||
const SpinLock::ScopedLockType sl (ratioLock); | |||
input->prepareToPlay (samplesPerBlockExpected, sampleRate); | |||
buffer.setSize (numChannels, roundToInt (samplesPerBlockExpected * ratio) + 32); | |||
buffer.clear(); | |||
sampsInBuffer = 0; | |||
bufferPos = 0; | |||
subSampleOffset = 0.0; | |||
filterStates.calloc ((size_t) numChannels); | |||
srcBuffers.calloc ((size_t) numChannels); | |||
destBuffers.calloc ((size_t) numChannels); | |||
createLowPass (ratio); | |||
flushBuffers(); | |||
} | |||
void ResamplingAudioSource::flushBuffers() | |||
{ | |||
buffer.clear(); | |||
bufferPos = 0; | |||
sampsInBuffer = 0; | |||
subSampleOffset = 0.0; | |||
resetFilters(); | |||
} | |||
@@ -66,6 +66,9 @@ public: | |||
*/ | |||
double getResamplingRatio() const noexcept { return ratio; } | |||
/** Clears any buffers and filters that the resampler is using. */ | |||
void flushBuffers(); | |||
//============================================================================== | |||
void prepareToPlay (int samplesPerBlockExpected, double sampleRate) override; | |||
void releaseResources() override; | |||
@@ -233,7 +233,7 @@ public: | |||
size = sizeof (nameNSString); | |||
pa.mSelector = kAudioObjectPropertyElementName; | |||
pa.mElement = chanNum + 1; | |||
pa.mElement = (AudioObjectPropertyElement) chanNum + 1; | |||
if (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &nameNSString) == noErr) | |||
{ | |||
@@ -394,7 +394,7 @@ public: | |||
if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &sr))) | |||
sampleRate = sr; | |||
UInt32 framesPerBuf = bufferSize; | |||
UInt32 framesPerBuf = (UInt32) bufferSize; | |||
size = sizeof (framesPerBuf); | |||
pa.mSelector = kAudioDevicePropertyBufferFrameSize; | |||
AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &framesPerBuf); | |||
@@ -182,6 +182,10 @@ void AudioTransportSource::setNextReadPosition (int64 newPosition) | |||
newPosition = (int64) (newPosition * sourceSampleRate / sampleRate); | |||
positionableSource->setNextReadPosition (newPosition); | |||
if (resamplerSource != nullptr) | |||
resamplerSource->flushBuffers(); | |||
inputStreamEOF = false; | |||
} | |||
} | |||
@@ -162,7 +162,7 @@ void AudioFormatReader::read (AudioSampleBuffer* buffer, | |||
} | |||
else | |||
{ | |||
HeapBlock<int*> chans (numTargetChannels); | |||
HeapBlock<int*> chans ((size_t) numTargetChannels); | |||
readChannels (*this, chans, buffer, startSample, numSamples, readerStartSample, numTargetChannels); | |||
} | |||
@@ -972,16 +972,11 @@ private: | |||
for (int i = 0; i < parameters.size(); ++i) | |||
{ | |||
const ParamInfo& p = *parameters.getUnchecked(i); | |||
AudioUnitParameter paramToAdd; | |||
paramToAdd.mAudioUnit = audioUnit; | |||
paramToAdd.mParameterID = p.paramID; | |||
paramToAdd.mScope = kAudioUnitScope_Global; | |||
paramToAdd.mElement = 0; | |||
AudioUnitEvent event; | |||
event.mArgument.mParameter = paramToAdd; | |||
event.mArgument.mParameter.mAudioUnit = audioUnit; | |||
event.mArgument.mParameter.mParameterID = parameters.getUnchecked(i)->paramID; | |||
event.mArgument.mParameter.mScope = kAudioUnitScope_Global; | |||
event.mArgument.mParameter.mElement = 0; | |||
event.mEventType = kAudioUnitEvent_ParameterValueChange; | |||
AUEventListenerAddEventType (eventListenerRef, nullptr, &event); | |||
@@ -992,6 +987,16 @@ private: | |||
event.mEventType = kAudioUnitEvent_EndParameterChangeGesture; | |||
AUEventListenerAddEventType (eventListenerRef, nullptr, &event); | |||
} | |||
// Add a listener for program changes | |||
AudioUnitEvent event; | |||
event.mArgument.mProperty.mAudioUnit = audioUnit; | |||
event.mArgument.mProperty.mPropertyID = kAudioUnitProperty_PresentPreset; | |||
event.mArgument.mProperty.mScope = kAudioUnitScope_Global; | |||
event.mArgument.mProperty.mElement = 0; | |||
event.mEventType = kAudioUnitEvent_PropertyChange; | |||
AUEventListenerAddEventType (eventListenerRef, nullptr, &event); | |||
} | |||
} | |||
@@ -1022,6 +1027,7 @@ private: | |||
break; | |||
default: | |||
sendAllParametersChangedEvents(); | |||
break; | |||
} | |||
} | |||
@@ -112,27 +112,24 @@ struct AutoResizingNSViewComponentWithParent : public AutoResizingNSViewCompone | |||
setView (v); | |||
[v release]; | |||
startTimer (100); | |||
startTimer (30); | |||
} | |||
void timerCallback() override | |||
NSView* getChildView() const | |||
{ | |||
if (NSView* parent = (NSView*) getView()) | |||
{ | |||
if ([[parent subviews] count] > 0) | |||
{ | |||
if (NSView* child = [[parent subviews] objectAtIndex: 0]) | |||
{ | |||
NSRect f = [parent frame]; | |||
NSSize newSize = [child frame].size; | |||
if (f.size.width != newSize.width || f.size.height != newSize.height) | |||
{ | |||
f.size = newSize; | |||
[parent setFrame: f]; | |||
} | |||
} | |||
} | |||
return [[parent subviews] objectAtIndex: 0]; | |||
return nil; | |||
} | |||
void timerCallback() override | |||
{ | |||
if (NSView* child = getChildView()) | |||
{ | |||
stopTimer(); | |||
setView (child); | |||
} | |||
} | |||
}; | |||
@@ -289,9 +289,9 @@ public: | |||
filter will return an empty buffer, but won't block the audio thread like it would | |||
do if you use the getCallbackLock() critical section to synchronise access. | |||
If you're going to use this, your processBlock() method must call isSuspended() and | |||
check whether it's suspended or not. If it is, then it should skip doing any real | |||
processing, either emitting silence or passing the input through unchanged. | |||
Any code that calls processBlock() should call isSuspended() before doing so, and | |||
if the processor is suspended, it should avoid the call and emit silence or | |||
whatever is appropriate. | |||
@see getCallbackLock | |||
*/ | |||
@@ -396,7 +396,6 @@ private: | |||
Array<void*> renderingOps; | |||
friend class AudioGraphIOProcessor; | |||
friend class CarlaPluginInstance; | |||
AudioSampleBuffer* currentAudioInputBuffer; | |||
AudioSampleBuffer currentAudioOutputBuffer; | |||
MidiBuffer* currentMidiInputBuffer; | |||
@@ -72,7 +72,7 @@ public: | |||
const ScopedLockType lock (other.getLock()); | |||
numUsed = other.size(); | |||
data.setAllocatedSize (numUsed); | |||
memcpy (data.elements, other.getRawDataPointer(), numUsed * sizeof (ObjectClass*)); | |||
memcpy (data.elements, other.getRawDataPointer(), (size_t) numUsed * sizeof (ObjectClass*)); | |||
for (int i = numUsed; --i >= 0;) | |||
if (ObjectClass* o = data.elements[i]) | |||
@@ -543,14 +543,14 @@ struct JavascriptEngine::RootObject : public DynamicObject | |||
struct DivideOp : public BinaryOperator | |||
{ | |||
DivideOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::divide) {} | |||
var getWithDoubles (double a, double b) const override { return a / b; } | |||
var getWithInts (int64 a, int64 b) const override { return a / b; } | |||
var getWithDoubles (double a, double b) const override { return b != 0 ? a / b : std::numeric_limits<double>::infinity(); } | |||
var getWithInts (int64 a, int64 b) const override { return b != 0 ? var (a / b) : var (std::numeric_limits<double>::infinity()); } | |||
}; | |||
struct ModuloOp : public BinaryOperator | |||
{ | |||
ModuloOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::modulo) {} | |||
var getWithInts (int64 a, int64 b) const override { return a % b; } | |||
var getWithInts (int64 a, int64 b) const override { return b != 0 ? var (a % b) : var (std::numeric_limits<double>::infinity()); } | |||
}; | |||
struct BitwiseOrOp : public BinaryOperator | |||
@@ -843,7 +843,7 @@ struct JavascriptEngine::RootObject : public DynamicObject | |||
String::CharPointerType end (p); | |||
while (isIdentifierBody (*++end)) {} | |||
const size_t len = end - p; | |||
const size_t len = (size_t) (end - p); | |||
#define JUCE_JS_COMPARE_KEYWORD(name, str) if (len == sizeof (str) - 1 && matchToken (TokenTypes::name, len)) return TokenTypes::name; | |||
JUCE_JS_KEYWORDS (JUCE_JS_COMPARE_KEYWORD) | |||
@@ -311,37 +311,24 @@ void BigInteger::negate() noexcept | |||
#pragma intrinsic (_BitScanReverse) | |||
#endif | |||
namespace BitFunctions | |||
{ | |||
inline int countBitsInInt32 (uint32 n) noexcept | |||
{ | |||
n -= ((n >> 1) & 0x55555555); | |||
n = (((n >> 2) & 0x33333333) + (n & 0x33333333)); | |||
n = (((n >> 4) + n) & 0x0f0f0f0f); | |||
n += (n >> 8); | |||
n += (n >> 16); | |||
return (int) (n & 0x3f); | |||
} | |||
inline int highestBitInInt (uint32 n) noexcept | |||
{ | |||
jassert (n != 0); // (the built-in functions may not work for n = 0) | |||
#if JUCE_GCC | |||
return 31 - __builtin_clz (n); | |||
#elif JUCE_USE_INTRINSICS | |||
unsigned long highest; | |||
_BitScanReverse (&highest, n); | |||
return (int) highest; | |||
#else | |||
n |= (n >> 1); | |||
n |= (n >> 2); | |||
n |= (n >> 4); | |||
n |= (n >> 8); | |||
n |= (n >> 16); | |||
return countBitsInInt32 (n >> 1); | |||
#endif | |||
} | |||
inline static int highestBitInInt (uint32 n) noexcept | |||
{ | |||
jassert (n != 0); // (the built-in functions may not work for n = 0) | |||
#if JUCE_GCC | |||
return 31 - __builtin_clz (n); | |||
#elif JUCE_USE_INTRINSICS | |||
unsigned long highest; | |||
_BitScanReverse (&highest, n); | |||
return (int) highest; | |||
#else | |||
n |= (n >> 1); | |||
n |= (n >> 2); | |||
n |= (n >> 4); | |||
n |= (n >> 8); | |||
n |= (n >> 16); | |||
return countBitsInInt32 (n >> 1); | |||
#endif | |||
} | |||
int BigInteger::countNumberOfSetBits() const noexcept | |||
@@ -349,7 +336,7 @@ int BigInteger::countNumberOfSetBits() const noexcept | |||
int total = 0; | |||
for (int i = (int) bitToIndex (highestBit) + 1; --i >= 0;) | |||
total += BitFunctions::countBitsInInt32 (values[i]); | |||
total += countNumberOfBits (values[i]); | |||
return total; | |||
} | |||
@@ -361,7 +348,7 @@ int BigInteger::getHighestBit() const noexcept | |||
const uint32 n = values[i]; | |||
if (n != 0) | |||
return BitFunctions::highestBitInInt (n) + (i << 5); | |||
return highestBitInInt (n) + (i << 5); | |||
} | |||
return -1; | |||
@@ -443,6 +443,23 @@ inline int nextPowerOfTwo (int n) noexcept | |||
return n + 1; | |||
} | |||
/** Returns the number of bits in a 32-bit integer. */ | |||
inline int countNumberOfBits (uint32 n) noexcept | |||
{ | |||
n -= ((n >> 1) & 0x55555555); | |||
n = (((n >> 2) & 0x33333333) + (n & 0x33333333)); | |||
n = (((n >> 4) + n) & 0x0f0f0f0f); | |||
n += (n >> 8); | |||
n += (n >> 16); | |||
return (int) (n & 0x3f); | |||
} | |||
/** Returns the number of bits in a 64-bit integer. */ | |||
inline int countNumberOfBits (uint64 n) noexcept | |||
{ | |||
return countNumberOfBits ((uint32) n) + countNumberOfBits ((uint32) (n >> 32)); | |||
} | |||
/** Performs a modulo operation, but can cope with the dividend being negative. | |||
The divisor must be greater than zero. | |||
*/ | |||
@@ -362,6 +362,12 @@ private: | |||
extern ThreadLocalJNIEnvHolder threadLocalJNIEnvHolder; | |||
struct AndroidThreadScope | |||
{ | |||
AndroidThreadScope() { threadLocalJNIEnvHolder.attach(); } | |||
~AndroidThreadScope() { threadLocalJNIEnvHolder.detach(); } | |||
}; | |||
//============================================================================== | |||
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ | |||
METHOD (createNewView, "createNewView", "(ZJ)L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$ComponentPeerView;") \ | |||
@@ -849,12 +849,6 @@ extern "C" void* threadEntryProc (void* userData) | |||
JUCE_AUTORELEASEPOOL | |||
{ | |||
#if JUCE_ANDROID | |||
struct AndroidThreadScope | |||
{ | |||
AndroidThreadScope() { threadLocalJNIEnvHolder.attach(); } | |||
~AndroidThreadScope() { threadLocalJNIEnvHolder.detach(); } | |||
}; | |||
const AndroidThreadScope androidEnv; | |||
#endif | |||
@@ -1169,15 +1163,23 @@ struct HighResolutionTimer::Pimpl | |||
{ | |||
if (periodMs != newPeriod) | |||
{ | |||
stop(); | |||
periodMs = newPeriod; | |||
if (thread != pthread_self()) | |||
{ | |||
stop(); | |||
shouldStop = false; | |||
periodMs = newPeriod; | |||
shouldStop = false; | |||
if (pthread_create (&thread, nullptr, timerThread, this) == 0) | |||
setThreadToRealtime (thread, (uint64) newPeriod); | |||
if (pthread_create (&thread, nullptr, timerThread, this) == 0) | |||
setThreadToRealtime (thread, (uint64) newPeriod); | |||
else | |||
jassertfalse; | |||
} | |||
else | |||
jassertfalse; | |||
{ | |||
periodMs = newPeriod; | |||
shouldStop = false; | |||
} | |||
} | |||
} | |||
@@ -1201,7 +1203,9 @@ private: | |||
static void* timerThread (void* param) | |||
{ | |||
#if ! JUCE_ANDROID | |||
#if JUCE_ANDROID | |||
const AndroidThreadScope androidEnv; | |||
#else | |||
int dummy; | |||
pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &dummy); | |||
#endif | |||
@@ -1212,12 +1216,19 @@ private: | |||
void timerThread() | |||
{ | |||
Clock clock (periodMs); | |||
int lastPeriod = periodMs; | |||
Clock clock (lastPeriod); | |||
while (! shouldStop) | |||
{ | |||
clock.wait(); | |||
owner.hiResTimerCallback(); | |||
if (lastPeriod != periodMs) | |||
{ | |||
lastPeriod = periodMs; | |||
clock = Clock (lastPeriod); | |||
} | |||
} | |||
periodMs = 0; | |||
@@ -29,8 +29,7 @@ | |||
#ifndef JUCE_WIN32_COMSMARTPTR_H_INCLUDED | |||
#define JUCE_WIN32_COMSMARTPTR_H_INCLUDED | |||
// FIXME | |||
#if 1 //! (defined (_MSC_VER) || defined (__uuidof)) | |||
#if ! (defined (_MSC_VER) || defined (__uuidof)) | |||
template<typename Type> struct UUIDGetter { static CLSID get() { jassertfalse; return CLSID(); } }; | |||
#define __uuidof(x) UUIDGetter<x>::get() | |||
#endif | |||
@@ -259,7 +259,8 @@ private: | |||
{ | |||
const TCHAR* mimeTypes[] = { _T("*/*"), nullptr }; | |||
DWORD flags = INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_COOKIES; | |||
DWORD flags = INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_COOKIES | |||
| INTERNET_FLAG_NO_AUTO_REDIRECT | SECURITY_SET_MASK; | |||
if (address.startsWithIgnoreCase ("https:")) | |||
flags |= INTERNET_FLAG_SECURE; // (this flag only seems necessary if the OS is running IE6 - | |||
@@ -270,6 +271,8 @@ private: | |||
if (request != 0) | |||
{ | |||
setSecurityFlags(); | |||
INTERNET_BUFFERS buffers = { 0 }; | |||
buffers.dwStructSize = sizeof (INTERNET_BUFFERS); | |||
buffers.lpcszHeader = headers.toWideCharPointer(); | |||
@@ -313,6 +316,14 @@ private: | |||
close(); | |||
} | |||
void setSecurityFlags() | |||
{ | |||
DWORD dwFlags = 0, dwBuffLen = sizeof (DWORD); | |||
InternetQueryOption (request, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, &dwBuffLen); | |||
dwFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_SET_MASK; | |||
InternetSetOption (request, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof (dwFlags)); | |||
} | |||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream) | |||
}; | |||
@@ -253,9 +253,23 @@ public: | |||
HiResCounterHandler() | |||
: hiResTicksOffset (0) | |||
{ | |||
const MMRESULT res = timeBeginPeriod (1); | |||
// This macro allows you to override the default timer-period | |||
// used on Windows. By default this is set to 1, because that has | |||
// always been the value used in JUCE apps, and changing it could | |||
// affect the behaviour of existing code, but you may wish to make | |||
// it larger (or set it to 0 to use the system default) to make your | |||
// app less demanding on the CPU. | |||
// For more info, see win32 documentation about the timeBeginPeriod | |||
// function. | |||
#ifndef JUCE_WIN32_TIMER_PERIOD | |||
#define JUCE_WIN32_TIMER_PERIOD 1 | |||
#endif | |||
#if JUCE_WIN32_TIMER_PERIOD > 0 | |||
const MMRESULT res = timeBeginPeriod (JUCE_WIN32_TIMER_PERIOD); | |||
(void) res; | |||
jassert (res == TIMERR_NOERROR); | |||
#endif | |||
LARGE_INTEGER f; | |||
QueryPerformanceFrequency (&f); | |||
@@ -378,7 +378,7 @@ void StreamingSocket::close() | |||
{ | |||
// need to do this to interrupt the accept() function.. | |||
StreamingSocket temp; | |||
temp.connect ("localhost", portNumber, 1000); | |||
temp.connect (IPAddress::local().toString(), portNumber, 1000); | |||
} | |||
} | |||
@@ -60,7 +60,7 @@ MemoryInputStream::~MemoryInputStream() | |||
int64 MemoryInputStream::getTotalLength() | |||
{ | |||
return dataSize; | |||
return (int64) dataSize; | |||
} | |||
int MemoryInputStream::read (void* const buffer, const int howMany) | |||
@@ -89,7 +89,7 @@ bool MemoryInputStream::setPosition (const int64 pos) | |||
int64 MemoryInputStream::getPosition() | |||
{ | |||
return position; | |||
return (int64) position; | |||
} | |||
@@ -114,7 +114,7 @@ public: | |||
void flush(); | |||
bool write (const void*, size_t) override; | |||
int64 getPosition() override { return position; } | |||
int64 getPosition() override { return (int64) position; } | |||
bool setPosition (int64) override; | |||
int writeFromInputStream (InputStream&, int64 maxNumBytesToWrite) override; | |||
bool writeRepeatedByte (uint8 byte, size_t numTimesToRepeat) override; | |||
@@ -36,7 +36,7 @@ | |||
*/ | |||
#define JUCE_MAJOR_VERSION 3 | |||
#define JUCE_MINOR_VERSION 0 | |||
#define JUCE_BUILDNUMBER 6 | |||
#define JUCE_BUILDNUMBER 7 | |||
/** Current Juce version number. | |||
@@ -97,7 +97,7 @@ String SystemStats::getStackBacktrace() | |||
{ | |||
String result; | |||
#if JUCE_ANDROID || JUCE_MINGW || JUCE_HAIKU || JUCE_MAC | |||
#if JUCE_ANDROID || JUCE_MINGW || JUCE_HAIKU | |||
jassertfalse; // sorry, not implemented yet! | |||
#elif JUCE_WINDOWS | |||
@@ -558,7 +558,7 @@ struct HashGenerator | |||
Type result = Type(); | |||
while (! t.isEmpty()) | |||
result = multiplier * result + t.getAndAdvance(); | |||
result = ((Type) multiplier) * result + (Type) t.getAndAdvance(); | |||
return result; | |||
} | |||
@@ -167,7 +167,7 @@ public: | |||
typedef CharPointer_UTF32 CharPointerType; | |||
#elif (JUCE_STRING_UTF_TYPE == 16) | |||
typedef CharPointer_UTF16 CharPointerType; | |||
#elif (JUCE_STRING_UTF_TYPE == 8) | |||
#elif (DOXYGEN || JUCE_STRING_UTF_TYPE == 8) | |||
typedef CharPointer_UTF8 CharPointerType; | |||
#else | |||
#error "You must set the value of JUCE_STRING_UTF_TYPE to be either 8, 16, or 32!" | |||
@@ -135,7 +135,7 @@ public: | |||
char buffer [30]; | |||
if (inputStream != nullptr | |||
&& inputStream->setPosition (zei.streamOffset) | |||
&& inputStream->setPosition ((int64) zei.streamOffset) | |||
&& inputStream->read (buffer, 30) == 30 | |||
&& ByteOrder::littleEndianInt (buffer) == 0x04034b50) | |||
{ | |||
@@ -154,7 +154,7 @@ public: | |||
int64 getTotalLength() | |||
{ | |||
return zipEntryHolder.compressedSize; | |||
return (int64) zipEntryHolder.compressedSize; | |||
} | |||
int read (void* buffer, int howMany) | |||
@@ -162,7 +162,7 @@ public: | |||
if (headerSize <= 0) | |||
return 0; | |||
howMany = (int) jmin ((int64) howMany, (int64) (zipEntryHolder.compressedSize - pos)); | |||
howMany = (int) jmin ((int64) howMany, ((int64) zipEntryHolder.compressedSize) - pos); | |||
if (inputStream == nullptr) | |||
return 0; | |||
@@ -172,12 +172,12 @@ public: | |||
if (inputStream == file.inputStream) | |||
{ | |||
const ScopedLock sl (file.lock); | |||
inputStream->setPosition (pos + zipEntryHolder.streamOffset + headerSize); | |||
inputStream->setPosition (pos + (int64) zipEntryHolder.streamOffset + headerSize); | |||
num = inputStream->read (buffer, howMany); | |||
} | |||
else | |||
{ | |||
inputStream->setPosition (pos + zipEntryHolder.streamOffset + headerSize); | |||
inputStream->setPosition (pos + (int64) zipEntryHolder.streamOffset + headerSize); | |||
num = inputStream->read (buffer, howMany); | |||
} | |||
@@ -147,9 +147,9 @@ public: | |||
The listener is added to this specific Value object, and not to the shared | |||
object that it refers to. When this object is deleted, all the listeners will | |||
be lost, even if other references to the same Value still exist. So when you're | |||
adding a listener, make sure that you add it to a ValueTree instance that will last | |||
adding a listener, make sure that you add it to a Value instance that will last | |||
for as long as you need the listener. In general, you'd never want to add a listener | |||
to a local stack-based ValueTree, but more likely to one that's a member variable. | |||
to a local stack-based Value, but more likely to one that's a member variable. | |||
@see removeListener | |||
*/ | |||
@@ -61,7 +61,9 @@ AsyncUpdater::~AsyncUpdater() | |||
void AsyncUpdater::triggerAsyncUpdate() | |||
{ | |||
if (activeMessage->shouldDeliver.compareAndSetBool (1, 0)) | |||
activeMessage->post(); | |||
if (! activeMessage->post()) | |||
cancelPendingUpdate(); // if the message queue fails, this avoids getting | |||
// trapped waiting for the message to arrive | |||
} | |||
void AsyncUpdater::cancelPendingUpdate() noexcept | |||
@@ -69,11 +69,9 @@ bool InterprocessConnection::connectToSocket (const String& hostName, | |||
thread->startThread(); | |||
return true; | |||
} | |||
else | |||
{ | |||
socket = nullptr; | |||
return false; | |||
} | |||
socket = nullptr; | |||
return false; | |||
} | |||
bool InterprocessConnection::connectToPipe (const String& pipeName, const int timeoutMs) | |||
@@ -143,41 +141,43 @@ bool InterprocessConnection::isConnected() const | |||
String InterprocessConnection::getConnectedHostName() const | |||
{ | |||
if (pipe != nullptr) | |||
return "localhost"; | |||
if (socket != nullptr) | |||
{ | |||
if (! socket->isLocal()) | |||
return socket->getHostName(); | |||
const ScopedLock sl (pipeAndSocketLock); | |||
if (pipe == nullptr && socket == nullptr) | |||
return String(); | |||
return "localhost"; | |||
if (socket != nullptr && ! socket->isLocal()) | |||
return socket->getHostName(); | |||
} | |||
return String(); | |||
return IPAddress::local().toString(); | |||
} | |||
//============================================================================== | |||
bool InterprocessConnection::sendMessage (const MemoryBlock& message) | |||
{ | |||
uint32 messageHeader[2]; | |||
messageHeader [0] = ByteOrder::swapIfBigEndian (magicMessageHeader); | |||
messageHeader [1] = ByteOrder::swapIfBigEndian ((uint32) message.getSize()); | |||
uint32 messageHeader[2] = { ByteOrder::swapIfBigEndian (magicMessageHeader), | |||
ByteOrder::swapIfBigEndian ((uint32) message.getSize()) }; | |||
MemoryBlock messageData (sizeof (messageHeader) + message.getSize()); | |||
messageData.copyFrom (messageHeader, 0, sizeof (messageHeader)); | |||
messageData.copyFrom (message.getData(), sizeof (messageHeader), message.getSize()); | |||
int bytesWritten = 0; | |||
return writeData (messageData.getData(), (int) messageData.getSize()) == (int) messageData.getSize(); | |||
} | |||
int InterprocessConnection::writeData (void* data, int dataSize) | |||
{ | |||
const ScopedLock sl (pipeAndSocketLock); | |||
if (socket != nullptr) | |||
bytesWritten = socket->write (messageData.getData(), (int) messageData.getSize()); | |||
else if (pipe != nullptr) | |||
bytesWritten = pipe->write (messageData.getData(), (int) messageData.getSize(), pipeReceiveMessageTimeout); | |||
return socket->write (data, dataSize); | |||
if (pipe != nullptr) | |||
return pipe->write (data, dataSize, pipeReceiveMessageTimeout); | |||
return bytesWritten == (int) messageData.getSize(); | |||
return 0; | |||
} | |||
//============================================================================== | |||
@@ -201,6 +201,7 @@ private: | |||
friend struct ContainerDeletePolicy<ConnectionThread>; | |||
ScopedPointer<ConnectionThread> thread; | |||
void runThread(); | |||
int writeData (void*, int); | |||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (InterprocessConnection) | |||
}; | |||
@@ -138,7 +138,7 @@ String JUCEApplicationBase::getCommandLineParameters() { return String( | |||
#else | |||
#if JUCE_WINDOWS | |||
#if JUCE_WINDOWS && ! defined (_CONSOLE) | |||
String JUCE_CALLTYPE JUCEApplicationBase::getCommandLineParameters() | |||
{ | |||
@@ -171,8 +171,13 @@ StringArray JUCE_CALLTYPE JUCEApplicationBase::getCommandLineParameterArray() | |||
extern void initialiseNSApplication(); | |||
#endif | |||
extern const char* const* juce_argv; // declared in juce_core | |||
extern int juce_argc; | |||
#if JUCE_WINDOWS | |||
const char* const* juce_argv = nullptr; | |||
int juce_argc = 0; | |||
#else | |||
extern const char* const* juce_argv; // declared in juce_core | |||
extern int juce_argc; | |||
#endif | |||
String JUCEApplicationBase::getCommandLineParameters() | |||
{ | |||
@@ -92,18 +92,12 @@ public: | |||
juce::JUCEApplicationBase* juce_CreateApplication() { return new AppClass(); } | |||
#else | |||
#if JUCE_WINDOWS | |||
#if defined (WINAPI) || defined (_WINDOWS_) || defined(JUCE_MINGW) | |||
#define JUCE_MAIN_FUNCTION int __stdcall WinMain (HINSTANCE, HINSTANCE, const LPSTR, int) | |||
#elif defined (_UNICODE) | |||
#define JUCE_MAIN_FUNCTION int __stdcall WinMain (void*, void*, const wchar_t*, int) | |||
#else | |||
#define JUCE_MAIN_FUNCTION int __stdcall WinMain (void*, void*, const char*, int) | |||
#endif | |||
#define JUCE_MAIN_FUNCTION_ARGS | |||
#if JUCE_WINDOWS && ! defined (_CONSOLE) | |||
#define JUCE_MAIN_FUNCTION int __stdcall WinMain (struct HINSTANCE__*, struct HINSTANCE__*, char*, int) | |||
#define JUCE_MAIN_FUNCTION_ARGS | |||
#else | |||
#define JUCE_MAIN_FUNCTION int main (int argc, char* argv[]) | |||
#define JUCE_MAIN_FUNCTION_ARGS argc, (const char**) argv | |||
#define JUCE_MAIN_FUNCTION int main (int argc, char* argv[]) | |||
#define JUCE_MAIN_FUNCTION_ARGS argc, (const char**) argv | |||
#endif | |||
#define START_JUCE_APPLICATION(AppClass) \ | |||
@@ -66,12 +66,17 @@ void MessageManager::deleteInstance() | |||
} | |||
//============================================================================== | |||
void MessageManager::MessageBase::post() | |||
bool MessageManager::MessageBase::post() | |||
{ | |||
MessageManager* const mm = MessageManager::instance; | |||
if (mm == nullptr || mm->quitMessagePosted || ! postMessageToSystemQueue (this)) | |||
{ | |||
Ptr deleter (this); // (this will delete messages that were just created with a 0 ref count) | |||
return false; | |||
} | |||
return true; | |||
} | |||
//============================================================================== | |||
@@ -158,9 +163,15 @@ void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* cons | |||
jassert (! currentThreadHasLockedMessageManager()); | |||
const ReferenceCountedObjectPtr<AsyncFunctionCallback> message (new AsyncFunctionCallback (func, parameter)); | |||
message->post(); | |||
message->finished.wait(); | |||
return message->result; | |||
if (message->post()) | |||
{ | |||
message->finished.wait(); | |||
return message->result; | |||
} | |||
jassertfalse; // the OS message queue failed to send the message! | |||
return nullptr; | |||
} | |||
//============================================================================== | |||
@@ -275,7 +286,9 @@ bool MessageManagerLock::attemptLock (Thread* const threadToCheck, ThreadPoolJob | |||
} | |||
blockingMessage = new BlockingMessage(); | |||
blockingMessage->post(); | |||
if (! blockingMessage->post()) | |||
return false; | |||
while (! blockingMessage->lockedEvent.wait (20)) | |||
{ | |||
@@ -170,7 +170,7 @@ public: | |||
virtual ~MessageBase() {} | |||
virtual void messageCallback() = 0; | |||
void post(); | |||
bool post(); | |||
typedef ReferenceCountedObjectPtr<MessageBase> Ptr; | |||
@@ -1182,11 +1182,25 @@ void Component::setBounds (const int x, const int y, int w, int h) | |||
cachedImage->invalidateAll(); | |||
} | |||
flags.isMoveCallbackPending = wasMoved; | |||
flags.isResizeCallbackPending = wasResized; | |||
if (flags.hasHeavyweightPeerFlag) | |||
if (ComponentPeer* const peer = getPeer()) | |||
peer->updateBounds(); | |||
sendMovedResizedMessages (wasMoved, wasResized); | |||
sendMovedResizedMessagesIfPending(); | |||
} | |||
} | |||
void Component::sendMovedResizedMessagesIfPending() | |||
{ | |||
if (flags.isMoveCallbackPending || flags.isResizeCallbackPending) | |||
{ | |||
sendMovedResizedMessages (flags.isMoveCallbackPending, flags.isResizeCallbackPending); | |||
flags.isMoveCallbackPending = false; | |||
flags.isResizeCallbackPending = false; | |||
} | |||
} | |||
@@ -2047,6 +2061,11 @@ void Component::paintComponentAndChildren (Graphics& g) | |||
void Component::paintEntireComponent (Graphics& g, const bool ignoreAlphaLevel) | |||
{ | |||
// If sizing a top-level-window and the OS paint message is delivered synchronously | |||
// before resized() is called, then we'll invoke the callback here, to make sure | |||
// the components inside have had a chance to sort their sizes out.. | |||
sendMovedResizedMessagesIfPending(); | |||
#if JUCE_DEBUG | |||
flags.isInsidePaintCall = true; | |||
#endif | |||
@@ -2306,6 +2306,8 @@ private: | |||
bool childCompFocusedFlag : 1; | |||
bool dontClipGraphicsFlag : 1; | |||
bool mouseDownWasBlocked : 1; | |||
bool isMoveCallbackPending : 1; | |||
bool isResizeCallbackPending : 1; | |||
#if JUCE_DEBUG | |||
bool isInsidePaintCall : 1; | |||
#endif | |||
@@ -2344,6 +2346,7 @@ private: | |||
void paintComponentAndChildren (Graphics&); | |||
void paintWithinParentContext (Graphics&); | |||
void sendMovedResizedMessages (bool wasMoved, bool wasResized); | |||
void sendMovedResizedMessagesIfPending(); | |||
void repaintParent(); | |||
void sendFakeMouseMove() const; | |||
void takeKeyboardFocus (const FocusChangeType); | |||
@@ -287,7 +287,7 @@ void TabbedButtonBar::setTabName (const int tabIndex, const String& newName) | |||
} | |||
} | |||
void TabbedButtonBar::removeTab (const int tabIndex) | |||
void TabbedButtonBar::removeTab (const int tabIndex, const bool animate) | |||
{ | |||
const int oldIndex = currentTabIndex; | |||
if (tabIndex == currentTabIndex) | |||
@@ -296,7 +296,7 @@ void TabbedButtonBar::removeTab (const int tabIndex) | |||
tabs.remove (tabIndex); | |||
setCurrentTabIndex (oldIndex); | |||
resized(); | |||
updateTabPositions (animate); | |||
} | |||
void TabbedButtonBar::moveTab (const int currentIndex, const int newIndex, const bool animate) | |||
@@ -212,7 +212,7 @@ public: | |||
void setTabName (int tabIndex, const String& newName); | |||
/** Gets rid of one of the tabs. */ | |||
void removeTab (int tabIndex); | |||
void removeTab (int tabIndex, bool animate = false); | |||
/** Moves a tab to a new index in the list. | |||
Pass -1 as the index to move it to the end of the list. | |||
@@ -346,15 +346,15 @@ void Viewport::mouseWheelMove (const MouseEvent& e, const MouseWheelDetails& whe | |||
Component::mouseWheelMove (e, wheel); | |||
} | |||
static float rescaleMouseWheelDistance (float distance, int singleStepSize) noexcept | |||
static int rescaleMouseWheelDistance (float distance, int singleStepSize) noexcept | |||
{ | |||
if (distance == 0) | |||
return 0; | |||
distance *= 14.0f * singleStepSize; | |||
return distance < 0 ? jmin (distance, -1.0f) | |||
: jmax (distance, 1.0f); | |||
return roundToInt (distance < 0 ? jmin (distance, -1.0f) | |||
: jmax (distance, 1.0f)); | |||
} | |||
bool Viewport::useMouseWheelMoveIfNeeded (const MouseEvent& e, const MouseWheelDetails& wheel) | |||
@@ -366,26 +366,23 @@ bool Viewport::useMouseWheelMoveIfNeeded (const MouseEvent& e, const MouseWheelD | |||
if (canScrollHorz || canScrollVert) | |||
{ | |||
float wheelIncrementX = rescaleMouseWheelDistance (wheel.deltaX, singleStepX); | |||
float wheelIncrementY = rescaleMouseWheelDistance (wheel.deltaY, singleStepY); | |||
const int deltaX = rescaleMouseWheelDistance (wheel.deltaX, singleStepX); | |||
const int deltaY = rescaleMouseWheelDistance (wheel.deltaY, singleStepY); | |||
Point<int> pos (getViewPosition()); | |||
if (wheelIncrementX != 0 && wheelIncrementY != 0 && canScrollHorz && canScrollVert) | |||
if (deltaX != 0 && deltaY != 0 && canScrollHorz && canScrollVert) | |||
{ | |||
pos.setX (pos.x - roundToInt (wheelIncrementX)); | |||
pos.setY (pos.y - roundToInt (wheelIncrementY)); | |||
pos.x -= deltaX; | |||
pos.y -= deltaY; | |||
} | |||
else if (canScrollHorz && (wheelIncrementX != 0 || e.mods.isShiftDown() || ! canScrollVert)) | |||
else if (canScrollHorz && (deltaX != 0 || e.mods.isShiftDown() || ! canScrollVert)) | |||
{ | |||
if (wheelIncrementX == 0 && ! canScrollVert) | |||
wheelIncrementX = wheelIncrementY; | |||
pos.setX (pos.x - roundToInt (wheelIncrementX)); | |||
pos.x -= deltaX != 0 ? deltaX : deltaY; | |||
} | |||
else if (canScrollVert && wheelIncrementY != 0) | |||
else if (canScrollVert && deltaY != 0) | |||
{ | |||
pos.setY (pos.y - roundToInt (wheelIncrementY)); | |||
pos.y -= deltaY; | |||
} | |||
if (pos != getViewPosition()) | |||
@@ -2357,6 +2357,10 @@ void LookAndFeel_V2::drawCallOutBoxBackground (CallOutBox& box, Graphics& g, | |||
g.strokePath (path, PathStrokeType (2.0f)); | |||
} | |||
int LookAndFeel_V2::getCallOutBoxBorderSize (const CallOutBox&) | |||
{ | |||
return 20; | |||
} | |||
//============================================================================== | |||
AttributedString LookAndFeel_V2::createFileChooserHeaderText (const String& title, | |||
@@ -285,6 +285,7 @@ public: | |||
//============================================================================== | |||
void drawCallOutBoxBackground (CallOutBox&, Graphics&, const Path& path, Image& cachedImage) override; | |||
int getCallOutBoxBorderSize (const CallOutBox&) override; | |||
//============================================================================== | |||
void drawLevelMeter (Graphics&, int width, int height, float level) override; | |||
@@ -274,7 +274,7 @@ public: | |||
sendMouseDrag (*current, newScreenPos + unboundedMouseOffset, time); | |||
if (isUnboundedMouseModeOn) | |||
handleUnboundedDrag (current); | |||
handleUnboundedDrag (*current); | |||
} | |||
else | |||
{ | |||
@@ -399,7 +399,8 @@ public: | |||
{ | |||
// when released, return the mouse to within the component's bounds | |||
if (Component* current = getComponentUnderMouse()) | |||
setScreenPosition (current->getScreenBounds().toFloat().getConstrainedPoint (lastScreenPos)); | |||
setScreenPosition (current->getScreenBounds().toFloat() | |||
.getConstrainedPoint (ScalingHelpers::unscaledScreenPosToScaled (lastScreenPos))); | |||
} | |||
isUnboundedMouseModeOn = enable; | |||
@@ -409,21 +410,22 @@ public: | |||
} | |||
} | |||
void handleUnboundedDrag (Component* current) | |||
void handleUnboundedDrag (Component& current) | |||
{ | |||
const Rectangle<float> screenArea (current->getParentMonitorArea().expanded (-2, -2).toFloat()); | |||
const Rectangle<float> componentScreenBounds | |||
= ScalingHelpers::scaledScreenPosToUnscaled (current.getParentMonitorArea().reduced (2, 2).toFloat()); | |||
if (! screenArea.contains (lastScreenPos)) | |||
if (! componentScreenBounds.contains (lastScreenPos)) | |||
{ | |||
const Point<float> componentCentre (current->getScreenBounds().toFloat().getCentre()); | |||
unboundedMouseOffset += (lastScreenPos - componentCentre); | |||
const Point<float> componentCentre (current.getScreenBounds().toFloat().getCentre()); | |||
unboundedMouseOffset += (lastScreenPos - ScalingHelpers::scaledScreenPosToUnscaled (componentCentre)); | |||
setScreenPosition (componentCentre); | |||
} | |||
else if (isCursorVisibleUntilOffscreen | |||
&& (! unboundedMouseOffset.isOrigin()) | |||
&& screenArea.contains (lastScreenPos + unboundedMouseOffset)) | |||
&& componentScreenBounds.contains (lastScreenPos + unboundedMouseOffset)) | |||
{ | |||
setScreenPosition (lastScreenPos + unboundedMouseOffset); | |||
MouseInputSource::setRawMousePosition (lastScreenPos + unboundedMouseOffset); | |||
unboundedMouseOffset = Point<float>(); | |||
} | |||
} | |||
@@ -462,10 +464,9 @@ public: | |||
//============================================================================== | |||
const int index; | |||
const bool isMouseDevice; | |||
Point<float> lastScreenPos; | |||
Point<float> lastScreenPos, unboundedMouseOffset; // NB: these are unscaled coords | |||
ModifierKeys buttonState; | |||
Point<float> unboundedMouseOffset; | |||
bool isUnboundedMouseModeOn, isCursorVisibleUntilOffscreen; | |||
private: | |||
@@ -487,8 +488,8 @@ private: | |||
bool canBePartOfMultipleClickWith (const RecentMouseDown& other, const int maxTimeBetweenMs) const | |||
{ | |||
return time - other.time < RelativeTime::milliseconds (maxTimeBetweenMs) | |||
&& abs (position.x - other.position.x) < 8 | |||
&& abs (position.y - other.position.y) < 8 | |||
&& std::abs (position.x - other.position.x) < 8 | |||
&& std::abs (position.y - other.position.y) < 8 | |||
&& buttons == other.buttons | |||
&& peerID == other.peerID; | |||
} | |||
@@ -42,99 +42,134 @@ bool FileChooser::isPlatformDialogAvailable() | |||
#endif | |||
} | |||
void FileChooser::showPlatformDialog (Array<File>& results, | |||
const String& title, | |||
const File& file, | |||
const String& filters, | |||
bool isDirectory, | |||
bool /* selectsFiles */, | |||
bool isSave, | |||
bool /* warnAboutOverwritingExistingFiles */, | |||
bool selectMultipleFiles, | |||
FilePreviewComponent* /* previewComponent */) | |||
static uint64 getTopWindowID() noexcept | |||
{ | |||
String separator; | |||
StringArray args; | |||
if (TopLevelWindow* top = TopLevelWindow::getActiveTopLevelWindow()) | |||
return (uint64) (pointer_sized_uint) top->getWindowHandle(); | |||
const File previousWorkingDirectory (File::getCurrentWorkingDirectory()); | |||
const bool isKdeFullSession = SystemStats::getEnvironmentVariable ("KDE_FULL_SESSION", String::empty) | |||
.equalsIgnoreCase ("true"); | |||
return 0; | |||
} | |||
if (exeIsAvailable ("kdialog") && (isKdeFullSession || ! exeIsAvailable ("zenity"))) | |||
{ | |||
// use kdialog for KDE sessions or if zenity is missing | |||
args.add ("kdialog"); | |||
static bool isKdeFullSession() | |||
{ | |||
return SystemStats::getEnvironmentVariable ("KDE_FULL_SESSION", String()) | |||
.equalsIgnoreCase ("true"); | |||
} | |||
if (title.isNotEmpty()) | |||
args.add ("--title=" + title); | |||
static void addKDialogArgs (StringArray& args, String& separator, | |||
const String& title, const File& file, const String& filters, | |||
bool isDirectory, bool isSave, bool selectMultipleFiles) | |||
{ | |||
args.add ("kdialog"); | |||
if (selectMultipleFiles) | |||
{ | |||
separator = "\n"; | |||
args.add ("--multiple"); | |||
args.add ("--separate-output"); | |||
args.add ("--getopenfilename"); | |||
} | |||
else | |||
{ | |||
if (isSave) args.add ("--getsavefilename"); | |||
else if (isDirectory) args.add ("--getexistingdirectory"); | |||
else args.add ("--getopenfilename"); | |||
} | |||
if (title.isNotEmpty()) | |||
args.add ("--title=" + title); | |||
String startPath; | |||
if (selectMultipleFiles) | |||
{ | |||
separator = "\n"; | |||
args.add ("--multiple"); | |||
args.add ("--separate-output"); | |||
args.add ("--getopenfilename"); | |||
} | |||
else | |||
{ | |||
if (isSave) args.add ("--getsavefilename"); | |||
else if (isDirectory) args.add ("--getexistingdirectory"); | |||
else args.add ("--getopenfilename"); | |||
} | |||
if (file.exists()) | |||
{ | |||
startPath = file.getFullPathName(); | |||
} | |||
else if (file.getParentDirectory().exists()) | |||
{ | |||
startPath = file.getParentDirectory().getFullPathName(); | |||
} | |||
else | |||
{ | |||
startPath = File::getSpecialLocation (File::userHomeDirectory).getFullPathName(); | |||
if (uint64 topWindowID = getTopWindowID()) | |||
{ | |||
args.add ("--attach"); | |||
args.add (String (topWindowID)); | |||
} | |||
if (isSave) | |||
startPath += "/" + file.getFileName(); | |||
} | |||
File startPath; | |||
args.add (startPath); | |||
args.add (filters.replaceCharacter (';', ' ')); | |||
if (file.exists()) | |||
{ | |||
startPath = file; | |||
} | |||
else if (file.getParentDirectory().exists()) | |||
{ | |||
startPath = file.getParentDirectory(); | |||
} | |||
else | |||
{ | |||
// zenity | |||
args.add ("zenity"); | |||
args.add ("--file-selection"); | |||
startPath = File::getSpecialLocation (File::userHomeDirectory); | |||
if (title.isNotEmpty()) | |||
args.add ("--title=" + title); | |||
if (isSave) | |||
startPath = startPath.getChildFile (file.getFileName()); | |||
} | |||
if (selectMultipleFiles) | |||
{ | |||
separator = ":"; | |||
args.add ("--multiple"); | |||
args.add ("--separator=" + separator); | |||
} | |||
else | |||
{ | |||
if (isDirectory) args.add ("--directory"); | |||
if (isSave) args.add ("--save"); | |||
} | |||
args.add (startPath.getFullPathName()); | |||
args.add (filters.replaceCharacter (';', ' ')); | |||
} | |||
static void addZenityArgs (StringArray& args, String& separator, | |||
const String& title, const File& file, const String& filters, | |||
bool isDirectory, bool isSave, bool selectMultipleFiles) | |||
{ | |||
args.add ("zenity"); | |||
args.add ("--file-selection"); | |||
if (title.isNotEmpty()) | |||
args.add ("--title=" + title); | |||
if (file.isDirectory()) | |||
file.setAsCurrentWorkingDirectory(); | |||
else if (file.getParentDirectory().exists()) | |||
file.getParentDirectory().setAsCurrentWorkingDirectory(); | |||
else | |||
File::getSpecialLocation (File::userHomeDirectory).setAsCurrentWorkingDirectory(); | |||
if (selectMultipleFiles) | |||
{ | |||
separator = ":"; | |||
args.add ("--multiple"); | |||
args.add ("--separator=" + separator); | |||
} | |||
else | |||
{ | |||
if (isDirectory) args.add ("--directory"); | |||
if (isSave) args.add ("--save"); | |||
} | |||
if (filters.isNotEmpty() && filters != "*" && filters != "*.*") | |||
{ | |||
args.add ("--file-filter"); | |||
args.add (filters.replaceCharacter (';', ' ')); | |||
if (! file.getFileName().isEmpty()) | |||
args.add ("--filename=" + file.getFileName()); | |||
args.add ("--file-filter"); | |||
args.add ("All files | *"); | |||
} | |||
if (file.isDirectory()) | |||
file.setAsCurrentWorkingDirectory(); | |||
else if (file.getParentDirectory().exists()) | |||
file.getParentDirectory().setAsCurrentWorkingDirectory(); | |||
else | |||
File::getSpecialLocation (File::userHomeDirectory).setAsCurrentWorkingDirectory(); | |||
if (! file.getFileName().isEmpty()) | |||
args.add ("--filename=" + file.getFileName()); | |||
// supplying the window ID of the topmost window makes sure that Zenity pops up.. | |||
if (uint64 topWindowID = getTopWindowID()) | |||
setenv ("WINDOWID", String (topWindowID).toRawUTF8(), true); | |||
} | |||
void FileChooser::showPlatformDialog (Array<File>& results, | |||
const String& title, const File& file, const String& filters, | |||
bool isDirectory, bool /* selectsFiles */, | |||
bool isSave, bool /* warnAboutOverwritingExistingFiles */, | |||
bool selectMultipleFiles, FilePreviewComponent*) | |||
{ | |||
const File previousWorkingDirectory (File::getCurrentWorkingDirectory()); | |||
StringArray args; | |||
String separator; | |||
// use kdialog for KDE sessions or if zenity is missing | |||
if (exeIsAvailable ("kdialog") && (isKdeFullSession() || ! exeIsAvailable ("zenity"))) | |||
addKDialogArgs (args, separator, title, file, filters, isDirectory, isSave, selectMultipleFiles); | |||
else | |||
addZenityArgs (args, separator, title, file, filters, isDirectory, isSave, selectMultipleFiles); | |||
args.add ("2>/dev/null"); // (to avoid logging info ending up in the results) | |||
ChildProcess child; | |||
@@ -33,17 +33,18 @@ struct Atoms | |||
{ | |||
Atoms() | |||
{ | |||
Protocols = getIfExists ("WM_PROTOCOLS"); | |||
ProtocolList [TAKE_FOCUS] = getIfExists ("WM_TAKE_FOCUS"); | |||
ProtocolList [DELETE_WINDOW] = getIfExists ("WM_DELETE_WINDOW"); | |||
ProtocolList [PING] = getIfExists ("_NET_WM_PING"); | |||
ChangeState = getIfExists ("WM_CHANGE_STATE"); | |||
State = getIfExists ("WM_STATE"); | |||
UserTime = getCreating ("_NET_WM_USER_TIME"); | |||
ActiveWin = getCreating ("_NET_ACTIVE_WINDOW"); | |||
Pid = getCreating ("_NET_WM_PID"); | |||
WindowType = getIfExists ("_NET_WM_WINDOW_TYPE"); | |||
WindowState = getIfExists ("_NET_WM_STATE"); | |||
protocols = getIfExists ("WM_PROTOCOLS"); | |||
protocolList [TAKE_FOCUS] = getIfExists ("WM_TAKE_FOCUS"); | |||
protocolList [DELETE_WINDOW] = getIfExists ("WM_DELETE_WINDOW"); | |||
protocolList [PING] = getIfExists ("_NET_WM_PING"); | |||
changeState = getIfExists ("WM_CHANGE_STATE"); | |||
state = getIfExists ("WM_STATE"); | |||
userTime = getCreating ("_NET_WM_USER_TIME"); | |||
activeWin = getCreating ("_NET_ACTIVE_WINDOW"); | |||
pid = getCreating ("_NET_WM_PID"); | |||
windowType = getIfExists ("_NET_WM_WINDOW_TYPE"); | |||
windowState = getIfExists ("_NET_WM_STATE"); | |||
compositingManager = getCreating ("_NET_WM_CM_S0"); | |||
XdndAware = getCreating ("XdndAware"); | |||
XdndEnter = getCreating ("XdndEnter"); | |||
@@ -88,8 +89,8 @@ struct Atoms | |||
PING = 2 | |||
}; | |||
Atom Protocols, ProtocolList[3], ChangeState, State, UserTime, | |||
ActiveWin, Pid, WindowType, WindowState, | |||
Atom protocols, protocolList[3], changeState, state, userTime, | |||
activeWin, pid, windowType, windowState, compositingManager, | |||
XdndAware, XdndEnter, XdndLeave, XdndPosition, XdndStatus, | |||
XdndDrop, XdndFinished, XdndSelection, XdndTypeList, XdndActionList, | |||
XdndActionDescription, XdndActionCopy, XdndActionPrivate, | |||
@@ -314,6 +315,11 @@ namespace XRender | |||
return xRenderQueryVersion != nullptr; | |||
} | |||
static bool hasCompositingWindowManager() | |||
{ | |||
return XGetSelectionOwner (display, Atoms::get().compositingManager) != 0; | |||
} | |||
static XRenderPictFormat* findPictureFormat() | |||
{ | |||
ScopedXLock xlock; | |||
@@ -915,7 +921,7 @@ public: | |||
clientMsg.window = windowH; | |||
clientMsg.type = ClientMessage; | |||
clientMsg.format = 32; | |||
clientMsg.message_type = Atoms::get().WindowState; | |||
clientMsg.message_type = Atoms::get().windowState; | |||
clientMsg.data.l[0] = 0; // Remove | |||
clientMsg.data.l[1] = fs; | |||
clientMsg.data.l[2] = 0; | |||
@@ -1002,7 +1008,7 @@ public: | |||
clientMsg.window = windowH; | |||
clientMsg.type = ClientMessage; | |||
clientMsg.format = 32; | |||
clientMsg.message_type = Atoms::get().ChangeState; | |||
clientMsg.message_type = Atoms::get().changeState; | |||
clientMsg.data.l[0] = IconicState; | |||
ScopedXLock xlock; | |||
@@ -1018,10 +1024,10 @@ public: | |||
{ | |||
ScopedXLock xlock; | |||
const Atoms& atoms = Atoms::get(); | |||
GetXProperty prop (windowH, atoms.State, 0, 64, false, atoms.State); | |||
GetXProperty prop (windowH, atoms.state, 0, 64, false, atoms.state); | |||
return prop.success | |||
&& prop.actualType == atoms.State | |||
&& prop.actualType == atoms.state | |||
&& prop.actualFormat == 32 | |||
&& prop.numItems > 0 | |||
&& ((unsigned long*) prop.data)[0] == IconicState; | |||
@@ -1152,7 +1158,7 @@ public: | |||
ev.xclient.type = ClientMessage; | |||
ev.xclient.serial = 0; | |||
ev.xclient.send_event = True; | |||
ev.xclient.message_type = Atoms::get().ActiveWin; | |||
ev.xclient.message_type = Atoms::get().activeWin; | |||
ev.xclient.window = windowH; | |||
ev.xclient.format = 32; | |||
ev.xclient.data.l[0] = 2; | |||
@@ -1178,10 +1184,7 @@ public: | |||
void toBehind (ComponentPeer* other) override | |||
{ | |||
LinuxComponentPeer* const otherPeer = dynamic_cast <LinuxComponentPeer*> (other); | |||
jassert (otherPeer != nullptr); // wrong type of window? | |||
if (otherPeer != nullptr) | |||
if (LinuxComponentPeer* const otherPeer = dynamic_cast<LinuxComponentPeer*> (other)) | |||
{ | |||
setMinimised (false); | |||
@@ -1190,6 +1193,8 @@ public: | |||
ScopedXLock xlock; | |||
XRestackWindows (display, newStack, 2); | |||
} | |||
else | |||
jassertfalse; // wrong type of window? | |||
} | |||
bool isFocused() const override | |||
@@ -1221,7 +1226,7 @@ public: | |||
void repaint (const Rectangle<int>& area) override | |||
{ | |||
repainter->repaint (area.getIntersection (component.getLocalBounds())); | |||
repainter->repaint (area.getIntersection (bounds.withZeroOrigin())); | |||
} | |||
void performAnyPendingRepaintsNow() override | |||
@@ -1699,11 +1704,11 @@ public: | |||
{ | |||
const Atoms& atoms = Atoms::get(); | |||
if (clientMsg.message_type == atoms.Protocols && clientMsg.format == 32) | |||
if (clientMsg.message_type == atoms.protocols && clientMsg.format == 32) | |||
{ | |||
const Atom atom = (Atom) clientMsg.data.l[0]; | |||
if (atom == atoms.ProtocolList [Atoms::PING]) | |||
if (atom == atoms.protocolList [Atoms::PING]) | |||
{ | |||
Window root = RootWindow (display, DefaultScreen (display)); | |||
@@ -1712,7 +1717,7 @@ public: | |||
XSendEvent (display, root, False, NoEventMask, &event); | |||
XFlush (display); | |||
} | |||
else if (atom == atoms.ProtocolList [Atoms::TAKE_FOCUS]) | |||
else if (atom == atoms.protocolList [Atoms::TAKE_FOCUS]) | |||
{ | |||
if ((getStyleFlags() & juce::ComponentPeer::windowIgnoresKeyPresses) == 0) | |||
{ | |||
@@ -1727,7 +1732,7 @@ public: | |||
} | |||
} | |||
} | |||
else if (atom == atoms.ProtocolList [Atoms::DELETE_WINDOW]) | |||
else if (atom == atoms.protocolList [Atoms::DELETE_WINDOW]) | |||
{ | |||
handleUserClosingWindow(); | |||
} | |||
@@ -2168,7 +2173,7 @@ private: | |||
netHints[1] = Atoms::getIfExists ("_KDE_NET_WM_WINDOW_TYPE_OVERRIDE"); | |||
xchangeProperty (windowH, Atoms::get().WindowType, XA_ATOM, 32, &netHints, 2); | |||
xchangeProperty (windowH, Atoms::get().windowType, XA_ATOM, 32, &netHints, 2); | |||
int numHints = 0; | |||
@@ -2179,7 +2184,7 @@ private: | |||
netHints [numHints++] = Atoms::getIfExists ("_NET_WM_STATE_ABOVE"); | |||
if (numHints > 0) | |||
xchangeProperty (windowH, Atoms::get().WindowState, XA_ATOM, 32, &netHints, numHints); | |||
xchangeProperty (windowH, Atoms::get().windowState, XA_ATOM, 32, &netHints, numHints); | |||
} | |||
void createWindow (Window parentToAddTo) | |||
@@ -2256,10 +2261,10 @@ private: | |||
// Associate the PID, allowing to be shut down when something goes wrong | |||
unsigned long pid = getpid(); | |||
xchangeProperty (windowH, atoms.Pid, XA_CARDINAL, 32, &pid, 1); | |||
xchangeProperty (windowH, atoms.pid, XA_CARDINAL, 32, &pid, 1); | |||
// Set window manager protocols | |||
xchangeProperty (windowH, atoms.Protocols, XA_ATOM, 32, atoms.ProtocolList, 2); | |||
xchangeProperty (windowH, atoms.protocols, XA_ATOM, 32, atoms.protocolList, 2); | |||
// Set drag and drop flags | |||
xchangeProperty (windowH, atoms.XdndTypeList, XA_ATOM, 32, atoms.allowedMimeTypes, numElementsInArray (atoms.allowedMimeTypes)); | |||
@@ -2316,7 +2321,7 @@ private: | |||
long getUserTime() const | |||
{ | |||
GetXProperty prop (windowH, Atoms::get().UserTime, 0, 65536, false, XA_CARDINAL); | |||
GetXProperty prop (windowH, Atoms::get().userTime, 0, 65536, false, XA_CARDINAL); | |||
return prop.success ? *(long*) prop.data : 0; | |||
} | |||
@@ -3116,11 +3121,17 @@ bool MouseInputSource::SourceList::addSource() | |||
bool Desktop::canUseSemiTransparentWindows() noexcept | |||
{ | |||
int matchedDepth = 0; | |||
const int desiredDepth = 32; | |||
#if JUCE_USE_XRENDER | |||
if (XRender::hasCompositingWindowManager()) | |||
{ | |||
int matchedDepth = 0, desiredDepth = 32; | |||
return Visuals::findVisualFormat (desiredDepth, matchedDepth) != 0 | |||
&& (matchedDepth == desiredDepth); | |||
return Visuals::findVisualFormat (desiredDepth, matchedDepth) != 0 | |||
&& matchedDepth == desiredDepth; | |||
} | |||
#endif | |||
return false; | |||
} | |||
Point<float> MouseInputSource::getCurrentRawMousePosition() | |||
@@ -3366,7 +3377,7 @@ void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType ty | |||
void MouseCursor::showInWindow (ComponentPeer* peer) const | |||
{ | |||
if (LinuxComponentPeer* const lp = dynamic_cast <LinuxComponentPeer*> (peer)) | |||
if (LinuxComponentPeer* const lp = dynamic_cast<LinuxComponentPeer*> (peer)) | |||
lp->showMouseCursor ((Cursor) getHandle()); | |||
} | |||
@@ -3390,7 +3401,7 @@ bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray& fi | |||
if (MouseInputSource* draggingSource = Desktop::getInstance().getDraggingMouseSource(0)) | |||
if (Component* sourceComp = draggingSource->getComponentUnderMouse()) | |||
if (LinuxComponentPeer* const lp = dynamic_cast <LinuxComponentPeer*> (sourceComp->getPeer())) | |||
if (LinuxComponentPeer* const lp = dynamic_cast<LinuxComponentPeer*> (sourceComp->getPeer())) | |||
return lp->externalDragFileInit (files, canMoveFiles); | |||
// This method must be called in response to a component's mouseDown or mouseDrag event! | |||
@@ -3405,7 +3416,7 @@ bool DragAndDropContainer::performExternalDragDropOfText (const String& text) | |||
if (MouseInputSource* draggingSource = Desktop::getInstance().getDraggingMouseSource(0)) | |||
if (Component* sourceComp = draggingSource->getComponentUnderMouse()) | |||
if (LinuxComponentPeer* const lp = dynamic_cast <LinuxComponentPeer*> (sourceComp->getPeer())) | |||
if (LinuxComponentPeer* const lp = dynamic_cast<LinuxComponentPeer*> (sourceComp->getPeer())) | |||
return lp->externalDragTextInit (text); | |||
// This method must be called in response to a component's mouseDown or mouseDrag event! | |||
@@ -390,16 +390,36 @@ public: | |||
return ComponentPeer::isKioskMode(); | |||
} | |||
static bool isWindowAtPoint (NSWindow* w, NSPoint screenPoint) | |||
{ | |||
#if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 | |||
if ([NSWindow respondsToSelector: @selector (windowNumberAtPoint:belowWindowWithWindowNumber:)]) | |||
return [NSWindow windowNumberAtPoint: screenPoint belowWindowWithWindowNumber: 0] == [w windowNumber]; | |||
#endif | |||
return true; | |||
} | |||
bool contains (Point<int> localPos, bool trueIfInAChildWindow) const override | |||
{ | |||
NSRect frameRect = [view frame]; | |||
NSRect viewFrame = [view frame]; | |||
if (! (isPositiveAndBelow (localPos.getX(), (int) frameRect.size.width) | |||
&& isPositiveAndBelow (localPos.getY(), (int) frameRect.size.height))) | |||
if (! (isPositiveAndBelow (localPos.getX(), (int) viewFrame.size.width) | |||
&& isPositiveAndBelow (localPos.getY(), (int) viewFrame.size.height))) | |||
return false; | |||
NSView* v = [view hitTest: NSMakePoint (frameRect.origin.x + localPos.getX(), | |||
frameRect.origin.y + frameRect.size.height - localPos.getY())]; | |||
if (NSWindow* const viewWindow = [view window]) | |||
{ | |||
const NSRect windowFrame = [viewWindow frame]; | |||
const NSPoint screenPoint = NSMakePoint (windowFrame.origin.x + localPos.getX(), | |||
windowFrame.origin.y + windowFrame.size.height - localPos.getY()); | |||
if (! isWindowAtPoint (viewWindow, screenPoint)) | |||
return false; | |||
} | |||
NSView* v = [view hitTest: NSMakePoint (viewFrame.origin.x + localPos.getX(), | |||
viewFrame.origin.y + viewFrame.size.height - localPos.getY())]; | |||
return trueIfInAChildWindow ? (v != nil) | |||
: (v == view); | |||
@@ -553,19 +573,11 @@ public: | |||
{ | |||
currentModifiers = currentModifiers.withoutMouseButtons(); | |||
#if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 | |||
if ([NSWindow respondsToSelector: @selector (windowNumberAtPoint:belowWindowWithWindowNumber:)] | |||
&& [NSWindow windowNumberAtPoint: [[ev window] convertBaseToScreen: [ev locationInWindow]] | |||
belowWindowWithWindowNumber: 0] != [window windowNumber]) | |||
{ | |||
if (isWindowAtPoint ([ev window], [[ev window] convertBaseToScreen: [ev locationInWindow]])) | |||
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)); | |||
} | |||
else | |||
#endif | |||
{ | |||
sendMouseEvent (ev); | |||
} | |||
showArrowCursorIfNeeded(); | |||
} | |||
@@ -1013,7 +1025,7 @@ public: | |||
static Point<float> getMousePos (NSEvent* e, NSView* view) | |||
{ | |||
NSPoint p = [view convertPoint: [e locationInWindow] fromView: nil]; | |||
return Point<float> (p.x, [view frame].size.height - p.y); | |||
return Point<float> ((float) p.x, (float) ([view frame].size.height - p.y)); | |||
} | |||
static int getModifierForButtonNumber (const NSInteger num) | |||
@@ -214,7 +214,7 @@ Point<float> MouseInputSource::getCurrentRawMousePosition() | |||
JUCE_AUTORELEASEPOOL | |||
{ | |||
const NSPoint p ([NSEvent mouseLocation]); | |||
return Point<float> (p.x, getMainScreenHeight() - p.y); | |||
return Point<float> ((float) p.x, (float) (getMainScreenHeight() - p.y)); | |||
} | |||
} | |||
@@ -81,8 +81,9 @@ public: | |||
bool isDynamic() const; | |||
/** Returns a string which represents this point. | |||
This returns a comma-separated list of coordinates, in the order left, top, right, bottom. For details of | |||
the string syntax used by the coordinates, see the RelativeCoordinate constructor notes. | |||
This returns a comma-separated list of coordinates, in the order left, top, right, bottom. | |||
If you're using this to position a Component, then see the notes for | |||
Component::setBounds (const RelativeRectangle&) for details of the syntax used. | |||
The string that is returned can be passed to the RelativeRectangle constructor to recreate the rectangle. | |||
*/ | |||
String toString() const; | |||
@@ -289,11 +289,22 @@ bool Label::isBeingEdited() const noexcept | |||
return editor != nullptr; | |||
} | |||
static void copyColourIfSpecified (Label& l, TextEditor& ed, int colourID, int targetColourID) | |||
{ | |||
if (l.isColourSpecified (colourID) || l.getLookAndFeel().isColourSpecified (colourID)) | |||
ed.setColour (targetColourID, l.findColour (colourID)); | |||
} | |||
TextEditor* Label::createEditorComponent() | |||
{ | |||
TextEditor* const ed = new TextEditor (getName()); | |||
ed->applyFontToAllText (getLookAndFeel().getLabelFont (*this)); | |||
copyAllExplicitColoursTo (*ed); | |||
copyColourIfSpecified (*this, *ed, textWhenEditingColourId, TextEditor::textColourId); | |||
copyColourIfSpecified (*this, *ed, backgroundWhenEditingColourId, TextEditor::backgroundColourId); | |||
copyColourIfSpecified (*this, *ed, outlineWhenEditingColourId, TextEditor::outlineColourId); | |||
return ed; | |||
} | |||
@@ -101,10 +101,13 @@ public: | |||
*/ | |||
enum ColourIds | |||
{ | |||
backgroundColourId = 0x1000280, /**< The background colour to fill the label with. */ | |||
textColourId = 0x1000281, /**< The colour for the text. */ | |||
outlineColourId = 0x1000282 /**< An optional colour to use to draw a border around the label. | |||
Leave this transparent to not have an outline. */ | |||
backgroundColourId = 0x1000280, /**< The background colour to fill the label with. */ | |||
textColourId = 0x1000281, /**< The colour for the text. */ | |||
outlineColourId = 0x1000282, /**< An optional colour to use to draw a border around the label. | |||
Leave this transparent to not have an outline. */ | |||
backgroundWhenEditingColourId = 0x1000283, /**< The background colour when the label is being edited. */ | |||
textWhenEditingColourId = 0x1000284, /**< The colour for the text when the label is being edited. */ | |||
outlineWhenEditingColourId = 0x1000285 /**< An optional border colour when the label is being edited. */ | |||
}; | |||
//============================================================================== | |||
@@ -667,7 +667,7 @@ public: | |||
if (isTwoValue || isThreeValue) | |||
{ | |||
const float mousePos = (float) (isVertical() ? e.y : e.x); | |||
const float mousePos = isVertical() ? e.position.y : e.position.x; | |||
const float normalPosDistance = std::abs (getLinearSliderPos (currentValue.getValue()) - mousePos); | |||
const float minPosDistance = std::abs (getLinearSliderPos (valueMin.getValue()) - 0.1f - mousePos); | |||
@@ -689,10 +689,10 @@ public: | |||
//============================================================================== | |||
void handleRotaryDrag (const MouseEvent& e) | |||
{ | |||
const int dx = e.x - sliderRect.getCentreX(); | |||
const int dy = e.y - sliderRect.getCentreY(); | |||
const float dx = e.position.x - sliderRect.getCentreX(); | |||
const float dy = e.position.y - sliderRect.getCentreY(); | |||
if (dx * dx + dy * dy > 25) | |||
if (dx * dx + dy * dy > 25.0f) | |||
{ | |||
double angle = std::atan2 ((double) dx, (double) -dy); | |||
while (angle < 0.0) | |||
@@ -736,7 +736,7 @@ public: | |||
void handleAbsoluteDrag (const MouseEvent& e) | |||
{ | |||
const int mousePos = (isHorizontal() || style == RotaryHorizontalDrag) ? e.x : e.y; | |||
const float mousePos = (isHorizontal() || style == RotaryHorizontalDrag) ? e.position.x : e.position.y; | |||
double newPos = (mousePos - sliderRegionStart) / (double) sliderRegionSize; | |||
if (style == RotaryHorizontalDrag | |||
@@ -781,7 +781,7 @@ public: | |||
void handleVelocityDrag (const MouseEvent& e) | |||
{ | |||
const float mouseDiff = style == RotaryHorizontalVerticalDrag | |||
? (e.x - mousePosWhenLastDragged.x) + (mousePosWhenLastDragged.y - e.y) | |||
? (e.position.x - mousePosWhenLastDragged.x) + (mousePosWhenLastDragged.y - e.position.y) | |||
: (isHorizontal() | |||
|| style == RotaryHorizontalDrag | |||
|| (style == IncDecButtons && incDecDragDirectionIsHorizontal())) | |||
@@ -789,7 +789,7 @@ public: | |||
: e.position.y - mousePosWhenLastDragged.y; | |||
const double maxSpeed = jmax (200, sliderRegionSize); | |||
double speed = jlimit (0.0, maxSpeed, (double) abs (mouseDiff)); | |||
double speed = jlimit (0.0, maxSpeed, (double) std::abs (mouseDiff)); | |||
if (speed != 0) | |||
{ | |||
@@ -981,29 +981,45 @@ public: | |||
} | |||
} | |||
double getMouseWheelDelta (double value, double wheelAmount) | |||
{ | |||
if (style == IncDecButtons) | |||
return interval * wheelAmount; | |||
const double proportionDelta = wheelAmount * 0.15f; | |||
const double currentPos = owner.valueToProportionOfLength (value); | |||
return owner.proportionOfLengthToValue (jlimit (0.0, 1.0, currentPos + proportionDelta)) - value; | |||
} | |||
bool mouseWheelMove (const MouseEvent& e, const MouseWheelDetails& wheel) | |||
{ | |||
if (scrollWheelEnabled | |||
&& style != TwoValueHorizontal | |||
&& style != TwoValueVertical) | |||
{ | |||
if (maximum > minimum && ! e.mods.isAnyMouseButtonDown()) | |||
// sometimes duplicate wheel events seem to be sent, so since we're going to | |||
// bump the value by a minimum of the interval, avoid doing this twice.. | |||
if (e.eventTime != lastMouseWheelTime) | |||
{ | |||
if (valueBox != nullptr) | |||
valueBox->hideEditor (false); | |||
lastMouseWheelTime = e.eventTime; | |||
if (maximum > minimum && ! e.mods.isAnyMouseButtonDown()) | |||
{ | |||
if (valueBox != nullptr) | |||
valueBox->hideEditor (false); | |||
const double value = (double) currentValue.getValue(); | |||
const double proportionDelta = (wheel.deltaX != 0 ? -wheel.deltaX : wheel.deltaY) | |||
* (wheel.isReversed ? -0.15f : 0.15f); | |||
const double currentPos = owner.valueToProportionOfLength (value); | |||
const double newValue = owner.proportionOfLengthToValue (jlimit (0.0, 1.0, currentPos + proportionDelta)); | |||
const double value = (double) currentValue.getValue(); | |||
const double delta = getMouseWheelDelta (value, (wheel.deltaX != 0 ? -wheel.deltaX : wheel.deltaY) | |||
* (wheel.isReversed ? -1.0f : 1.0f)); | |||
double delta = (newValue != value) ? jmax (std::abs (newValue - value), interval) : 0; | |||
if (value > newValue) | |||
delta = -delta; | |||
if (delta != 0) | |||
{ | |||
const double newValue = value + jmax (interval, std::abs (delta)) * (delta < 0 ? -1.0 : 1.0); | |||
DragInProgress drag (*this); | |||
setValue (owner.snapValue (value + delta, notDragging), sendNotificationSync); | |||
DragInProgress drag (*this); | |||
setValue (owner.snapValue (newValue, notDragging), sendNotificationSync); | |||
} | |||
} | |||
} | |||
return true; | |||
@@ -1236,6 +1252,7 @@ public: | |||
int sliderRegionStart, sliderRegionSize; | |||
int sliderBeingDragged; | |||
int pixelsForFullDragExtent; | |||
Time lastMouseWheelTime; | |||
Rectangle<int> sliderRect; | |||
ScopedPointer<DragInProgress> currentDrag; | |||
@@ -91,7 +91,7 @@ void CallOutBox::setArrowSize (const float newSize) | |||
int CallOutBox::getBorderSize() const noexcept | |||
{ | |||
return jmax (20, (int) arrowSize); | |||
return jmax (getLookAndFeel().getCallOutBoxBorderSize (*this), (int) arrowSize); | |||
} | |||
void CallOutBox::paint (Graphics& g) | |||
@@ -130,6 +130,7 @@ public: | |||
virtual ~LookAndFeelMethods() {} | |||
virtual void drawCallOutBoxBackground (CallOutBox&, Graphics&, const Path&, Image& cachedImage) = 0; | |||
virtual int getCallOutBoxBorderSize (const CallOutBox&) = 0; | |||
}; | |||
//============================================================================== | |||
@@ -117,8 +117,8 @@ LivePropertyEditorBase::LivePropertyEditorBase (LiveValueBase& v, CodeDocument& | |||
name.setFont (13.0f); | |||
name.setText (v.name, dontSendNotification); | |||
valueEditor.setMultiLine (true); | |||
valueEditor.setReturnKeyStartsNewLine (true); | |||
valueEditor.setMultiLine (v.isString()); | |||
valueEditor.setReturnKeyStartsNewLine (v.isString()); | |||
valueEditor.setText (v.getStringValue (wasHex), dontSendNotification); | |||
valueEditor.addListener (this); | |||
sourceEditor.setReadOnly (true); | |||
@@ -381,7 +381,7 @@ struct ColourEditorComp : public Component, | |||
Colour getColour() const | |||
{ | |||
return Colour ((int) parseInt (editor.value.getStringValue (false))); | |||
return Colour ((uint32) parseInt (editor.value.getStringValue (false))); | |||
} | |||
void paint (Graphics& g) override | |||
@@ -53,7 +53,7 @@ namespace LiveConstantEditor | |||
inline void setFromString (double& v, const String& s) { v = parseDouble (s); } | |||
inline void setFromString (float& v, const String& s) { v = (float) parseDouble (s); } | |||
inline void setFromString (String& v, const String& s) { v = s; } | |||
inline void setFromString (Colour& v, const String& s) { v = Colour ((int) parseInt (s)); } | |||
inline void setFromString (Colour& v, const String& s) { v = Colour ((uint32) parseInt (s)); } | |||
template <typename Type> | |||
inline String getAsString (const Type& v, bool) { return String (v); } | |||
@@ -67,6 +67,9 @@ namespace LiveConstantEditor | |||
inline String getAsString (uint64 v, bool preferHex) { return intToString ((int64) v, preferHex); } | |||
inline String getAsString (Colour v, bool) { return intToString ((int) v.getARGB(), true); } | |||
template <typename Type> struct isStringType { enum { value = 0 }; }; | |||
template <> struct isStringType<String> { enum { value = 1 }; }; | |||
template <typename Type> | |||
inline String getAsCode (Type& v, bool preferHex) { return getAsString (v, preferHex); } | |||
inline String getAsCode (Colour v, bool) { return "Colour (0x" + String::toHexString ((int) v.getARGB()).paddedLeft ('0', 8) + ")"; } | |||
@@ -90,6 +93,7 @@ namespace LiveConstantEditor | |||
virtual String getCodeValue (bool preferHex) const = 0; | |||
virtual void setStringValue (const String&) = 0; | |||
virtual String getOriginalStringValue (bool preferHex) const = 0; | |||
virtual bool isString() const = 0; | |||
String name, sourceFile; | |||
int sourceLine; | |||
@@ -175,6 +179,7 @@ namespace LiveConstantEditor | |||
String getCodeValue (bool preferHex) const override { return getAsCode (value, preferHex); } | |||
String getOriginalStringValue (bool preferHex) const override { return getAsString (originalValue, preferHex); } | |||
void setStringValue (const String& s) override { setFromString (value, s); } | |||
bool isString() const override { return isStringType<Type>::value; } | |||
Type value, originalValue; | |||