diff --git a/build/macosx/platform_specific_code/juce_mac_MessageManager.mm b/build/macosx/platform_specific_code/juce_mac_MessageManager.mm index 2e27766c60..f3c9d90f59 100644 --- a/build/macosx/platform_specific_code/juce_mac_MessageManager.mm +++ b/build/macosx/platform_specific_code/juce_mac_MessageManager.mm @@ -276,28 +276,70 @@ static bool isEventBlockedByModalComps (NSEvent* e) if (Component::getNumCurrentlyModalComponents() == 0) return false; - [[NSApp mainMenu] update]; NSWindow* const w = [e window]; if (w == 0 || [w worksWhenModal]) return false; + bool isKey = false, isInputAttempt = false; + + switch ([e type]) + { + case NSKeyDown: + case NSKeyUp: + isKey = isInputAttempt = true; + break; + + case NSLeftMouseDown: + case NSRightMouseDown: + case NSOtherMouseDown: + isInputAttempt = true; + break; + + case NSLeftMouseDragged: + case NSRightMouseDragged: + case NSLeftMouseUp: + case NSRightMouseUp: + case NSOtherMouseUp: + case NSOtherMouseDragged: + if (Component::getComponentUnderMouse() != 0) + return false; + break; + + case NSMouseMoved: + case NSMouseEntered: + case NSMouseExited: + case NSCursorUpdate: + case NSScrollWheel: + case NSTabletPoint: + case NSTabletProximity: + break; + + default: + return false; + } + for (int i = ComponentPeer::getNumPeers(); --i >= 0;) { ComponentPeer* const peer = ComponentPeer::getPeer (i); NSView* const compView = (NSView*) peer->getNativeHandle(); - if ([compView window] == w - && (NSPointInRect ([compView convertPoint: [e locationInWindow] fromView: nil], - [compView bounds]) - || peer->getComponent()->isMouseButtonDown())) + if ([compView window] == w) { - return false; + if (isKey) + { + if (compView == [w firstResponder]) + return false; + } + else + { + if (NSPointInRect ([compView convertPoint: [e locationInWindow] fromView: nil], + [compView bounds])) + return false; + } } } - if ([e type] == NSLeftMouseDown - || [e type] == NSRightMouseDown - || [e type] == NSOtherMouseDown) + if (isInputAttempt) { if (! [NSApp isActive]) [NSApp activateIgnoringOtherApps: YES]; @@ -330,7 +372,7 @@ bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) inMode: NSDefaultRunLoopMode dequeue: YES]; - if (! isEventBlockedByModalComps (e)) + if (e != 0 && ! isEventBlockedByModalComps (e)) [NSApp sendEvent: e]; } diff --git a/build/macosx/platform_specific_code/juce_mac_NSViewComponentPeer.mm b/build/macosx/platform_specific_code/juce_mac_NSViewComponentPeer.mm index a69af6cde2..3fe71d5ee4 100644 --- a/build/macosx/platform_specific_code/juce_mac_NSViewComponentPeer.mm +++ b/build/macosx/platform_specific_code/juce_mac_NSViewComponentPeer.mm @@ -1141,6 +1141,8 @@ void juce_HandleProcessFocusChange() if (Process::isForegroundProcess()) { currentlyFocusedPeer->handleFocusGain(); + + ComponentPeer::bringModalComponentToFront(); } else { @@ -1223,13 +1225,19 @@ bool NSViewComponentPeer::redirectKeyDown (NSEvent* ev) used = (isValidPeer (this) && handleKeyEvent (ev, false)) || used; } + // (If we're running modally, don't allow unused keystrokes to be passed + // along to other blocked views..) + if (Component::getCurrentlyModalComponent() != 0) + used = true; + return used; } bool NSViewComponentPeer::redirectKeyUp (NSEvent* ev) { updateKeysDown (ev, false); - return handleKeyEvent (ev, false); + return handleKeyEvent (ev, false) + || Component::getCurrentlyModalComponent() != 0; } void NSViewComponentPeer::redirectModKeyChange (NSEvent* ev) diff --git a/build/macosx/platform_specific_code/juce_mac_OpenGLComponent.mm b/build/macosx/platform_specific_code/juce_mac_OpenGLComponent.mm index 83620f1985..7dc1d2c7a3 100644 --- a/build/macosx/platform_specific_code/juce_mac_OpenGLComponent.mm +++ b/build/macosx/platform_specific_code/juce_mac_OpenGLComponent.mm @@ -164,6 +164,10 @@ public: renderContext = [[[NSOpenGLContext alloc] initWithFormat: format shareContext: sharedContext] autorelease]; + + const long swapInterval = 1; + [renderContext setValues: &swapInterval forParameter: NSOpenGLCPSwapInterval]; + [view setOpenGLContext: renderContext]; [renderContext setView: view]; diff --git a/build/win32/platform_specific_code/juce_win32_Windowing.cpp b/build/win32/platform_specific_code/juce_win32_Windowing.cpp index 0934ef2074..13218f80a1 100644 --- a/build/win32/platform_specific_code/juce_win32_Windowing.cpp +++ b/build/win32/platform_specific_code/juce_win32_Windowing.cpp @@ -1477,7 +1477,8 @@ private: sendModifierKeyChangeIfNeeded(); } - return handleKeyUpOrDown(); + return handleKeyUpOrDown() + || Component::getCurrentlyModalComponent() != 0; } bool doKeyDown (const WPARAM key) @@ -1563,6 +1564,9 @@ private: break; } + if (Component::getCurrentlyModalComponent() != 0) + used = true; + return used; } diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 0aca63be98..8b62bc41e5 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -39433,6 +39433,8 @@ void Component::exitModalState (const int returnValue) modalComponentStack.removeValue (this); flags.currentlyModalFlag = false; + + bringModalComponentToFront(); } else { @@ -39469,6 +39471,34 @@ Component* JUCE_CALLTYPE Component::getCurrentlyModalComponent (int index) throw return c->isValidComponent() ? c : 0; } +void Component::bringModalComponentToFront() +{ + ComponentPeer* lastOne = 0; + + for (int i = 0; i < getNumCurrentlyModalComponents(); ++i) + { + Component* const c = getCurrentlyModalComponent (i); + + if (c == 0) + break; + + ComponentPeer* peer = c->getPeer(); + + if (peer != 0 && peer != lastOne) + { + if (lastOne == 0) + { + peer->toFront (true); + peer->grabFocus(); + } + else + peer->toBehind (lastOne); + + lastOne = peer; + } + } +} + void Component::setBroughtToFrontOnMouseClick (const bool shouldBeBroughtToFront) throw() { flags.bringToFrontOnClickFlag = shouldBeBroughtToFront; @@ -40063,8 +40093,7 @@ void Component::removeComponentListener (ComponentListener* const listenerToRemo void Component::inputAttemptWhenModal() { - getTopLevelComponent()->toFront (true); - + bringModalComponentToFront(); getLookAndFeel().playAlertSound(); } @@ -40982,9 +41011,7 @@ void Component::internalBroughtToFront() Component* const cm = getCurrentlyModalComponent(); if (cm != 0 && cm->getTopLevelComponent() != getTopLevelComponent()) - { - cm->getTopLevelComponent()->toFront (true); - } + bringModalComponentToFront(); } } @@ -60913,7 +60940,7 @@ AlertWindow* LookAndFeel::createAlertWindow (const String& title, int numButtons, Component* associatedComponent) { - AlertWindow* aw = new AlertWindow (title, message, iconType); + AlertWindow* aw = new AlertWindow (title, message, iconType, associatedComponent); if (numButtons == 1) { @@ -73091,16 +73118,9 @@ void ComponentPeer::handleFocusGain() else { if (! component->isCurrentlyBlockedByAnotherModalComponent()) - { component->grabKeyboardFocus(); - } else - { - Component* const currentModalComp = Component::getCurrentlyModalComponent(); - - if (currentModalComp != 0) - currentModalComp->toFront (! currentModalComp->hasKeyboardFocus (true)); - } + Component::bringModalComponentToFront(); } } @@ -73257,6 +73277,11 @@ void ComponentPeer::handleUserClosingWindow() component->userTriedToCloseWindow(); } +void ComponentPeer::bringModalComponentToFront() +{ + Component::bringModalComponentToFront(); +} + void ComponentPeer::clearMaskedRegion() throw() { maskedRegion.clear(); @@ -244470,7 +244495,8 @@ private: sendModifierKeyChangeIfNeeded(); } - return handleKeyUpOrDown(); + return handleKeyUpOrDown() + || Component::getCurrentlyModalComponent() != 0; } bool doKeyDown (const WPARAM key) @@ -244556,6 +244582,9 @@ private: break; } + if (Component::getCurrentlyModalComponent() != 0) + used = true; + return used; } @@ -267916,6 +267945,8 @@ void juce_HandleProcessFocusChange() if (Process::isForegroundProcess()) { currentlyFocusedPeer->handleFocusGain(); + + ComponentPeer::bringModalComponentToFront(); } else { @@ -267998,13 +268029,19 @@ bool NSViewComponentPeer::redirectKeyDown (NSEvent* ev) used = (isValidPeer (this) && handleKeyEvent (ev, false)) || used; } + // (If we're running modally, don't allow unused keystrokes to be passed + // along to other blocked views..) + if (Component::getCurrentlyModalComponent() != 0) + used = true; + return used; } bool NSViewComponentPeer::redirectKeyUp (NSEvent* ev) { updateKeysDown (ev, false); - return handleKeyEvent (ev, false); + return handleKeyEvent (ev, false) + || Component::getCurrentlyModalComponent() != 0; } void NSViewComponentPeer::redirectModKeyChange (NSEvent* ev) @@ -268984,6 +269021,10 @@ public: renderContext = [[[NSOpenGLContext alloc] initWithFormat: format shareContext: sharedContext] autorelease]; + + const long swapInterval = 1; + [renderContext setValues: &swapInterval forParameter: NSOpenGLCPSwapInterval]; + [view setOpenGLContext: renderContext]; [renderContext setView: view]; @@ -270977,28 +271018,70 @@ static bool isEventBlockedByModalComps (NSEvent* e) if (Component::getNumCurrentlyModalComponents() == 0) return false; - [[NSApp mainMenu] update]; NSWindow* const w = [e window]; if (w == 0 || [w worksWhenModal]) return false; + bool isKey = false, isInputAttempt = false; + + switch ([e type]) + { + case NSKeyDown: + case NSKeyUp: + isKey = isInputAttempt = true; + break; + + case NSLeftMouseDown: + case NSRightMouseDown: + case NSOtherMouseDown: + isInputAttempt = true; + break; + + case NSLeftMouseDragged: + case NSRightMouseDragged: + case NSLeftMouseUp: + case NSRightMouseUp: + case NSOtherMouseUp: + case NSOtherMouseDragged: + if (Component::getComponentUnderMouse() != 0) + return false; + break; + + case NSMouseMoved: + case NSMouseEntered: + case NSMouseExited: + case NSCursorUpdate: + case NSScrollWheel: + case NSTabletPoint: + case NSTabletProximity: + break; + + default: + return false; + } + for (int i = ComponentPeer::getNumPeers(); --i >= 0;) { ComponentPeer* const peer = ComponentPeer::getPeer (i); NSView* const compView = (NSView*) peer->getNativeHandle(); - if ([compView window] == w - && (NSPointInRect ([compView convertPoint: [e locationInWindow] fromView: nil], - [compView bounds]) - || peer->getComponent()->isMouseButtonDown())) + if ([compView window] == w) { - return false; + if (isKey) + { + if (compView == [w firstResponder]) + return false; + } + else + { + if (NSPointInRect ([compView convertPoint: [e locationInWindow] fromView: nil], + [compView bounds])) + return false; + } } } - if ([e type] == NSLeftMouseDown - || [e type] == NSRightMouseDown - || [e type] == NSOtherMouseDown) + if (isInputAttempt) { if (! [NSApp isActive]) [NSApp activateIgnoringOtherApps: YES]; @@ -271031,7 +271114,7 @@ bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) inMode: NSDefaultRunLoopMode dequeue: YES]; - if (! isEventBlockedByModalComps (e)) + if (e != 0 && ! isEventBlockedByModalComps (e)) [NSApp sendEvent: e]; } diff --git a/juce_amalgamated.h b/juce_amalgamated.h index a70f1bb3f8..680dc65270 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -3561,12 +3561,14 @@ public: if (indexToChange < numUsed) { if (deleteOldElement) + { toDelete = this->elements [indexToChange]; - if (toDelete == newObject) - toDelete = 0; - else - this->elements [indexToChange] = const_cast (newObject); + if (toDelete == newObject) + toDelete = 0; + } + + this->elements [indexToChange] = const_cast (newObject); } else { @@ -20934,6 +20936,8 @@ public: */ static bool isValidPeer (const ComponentPeer* const peer) throw(); + static void bringModalComponentToFront(); + juce_UseDebuggingNewOperator protected: @@ -22963,6 +22967,7 @@ private: static void giveAwayFocus(); void sendEnablementChangeMessage(); static void* runModalLoopCallback (void*); + static void bringModalComponentToFront(); void subtractObscuredRegions (RectangleList& result, const int deltaX, const int deltaY, const Rectangle& clipRect, diff --git a/src/juce_appframework/gui/components/juce_Component.cpp b/src/juce_appframework/gui/components/juce_Component.cpp index 3138b637c4..3f85c591fa 100644 --- a/src/juce_appframework/gui/components/juce_Component.cpp +++ b/src/juce_appframework/gui/components/juce_Component.cpp @@ -1515,6 +1515,8 @@ void Component::exitModalState (const int returnValue) modalComponentStack.removeValue (this); flags.currentlyModalFlag = false; + + bringModalComponentToFront(); } else { @@ -1551,6 +1553,34 @@ Component* JUCE_CALLTYPE Component::getCurrentlyModalComponent (int index) throw return c->isValidComponent() ? c : 0; } +void Component::bringModalComponentToFront() +{ + ComponentPeer* lastOne = 0; + + for (int i = 0; i < getNumCurrentlyModalComponents(); ++i) + { + Component* const c = getCurrentlyModalComponent (i); + + if (c == 0) + break; + + ComponentPeer* peer = c->getPeer(); + + if (peer != 0 && peer != lastOne) + { + if (lastOne == 0) + { + peer->toFront (true); + peer->grabFocus(); + } + else + peer->toBehind (lastOne); + + lastOne = peer; + } + } +} + //============================================================================== void Component::setBroughtToFrontOnMouseClick (const bool shouldBeBroughtToFront) throw() { @@ -2157,8 +2187,7 @@ void Component::removeComponentListener (ComponentListener* const listenerToRemo //============================================================================== void Component::inputAttemptWhenModal() { - getTopLevelComponent()->toFront (true); - + bringModalComponentToFront(); getLookAndFeel().playAlertSound(); } @@ -3085,9 +3114,7 @@ void Component::internalBroughtToFront() Component* const cm = getCurrentlyModalComponent(); if (cm != 0 && cm->getTopLevelComponent() != getTopLevelComponent()) - { - cm->getTopLevelComponent()->toFront (true); - } + bringModalComponentToFront(); } } diff --git a/src/juce_appframework/gui/components/juce_Component.h b/src/juce_appframework/gui/components/juce_Component.h index 417611e27b..dfacf8a92a 100644 --- a/src/juce_appframework/gui/components/juce_Component.h +++ b/src/juce_appframework/gui/components/juce_Component.h @@ -2085,6 +2085,7 @@ private: static void giveAwayFocus(); void sendEnablementChangeMessage(); static void* runModalLoopCallback (void*); + static void bringModalComponentToFront(); void subtractObscuredRegions (RectangleList& result, const int deltaX, const int deltaY, const Rectangle& clipRect, diff --git a/src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.cpp b/src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.cpp index 3f1aa078ac..c518afd285 100644 --- a/src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.cpp +++ b/src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.cpp @@ -475,7 +475,7 @@ AlertWindow* LookAndFeel::createAlertWindow (const String& title, int numButtons, Component* associatedComponent) { - AlertWindow* aw = new AlertWindow (title, message, iconType); + AlertWindow* aw = new AlertWindow (title, message, iconType, associatedComponent); if (numButtons == 1) { diff --git a/src/juce_appframework/gui/components/windows/juce_ComponentPeer.cpp b/src/juce_appframework/gui/components/windows/juce_ComponentPeer.cpp index 8e347e3af3..9a00da1d9f 100644 --- a/src/juce_appframework/gui/components/windows/juce_ComponentPeer.cpp +++ b/src/juce_appframework/gui/components/windows/juce_ComponentPeer.cpp @@ -604,16 +604,9 @@ void ComponentPeer::handleFocusGain() else { if (! component->isCurrentlyBlockedByAnotherModalComponent()) - { component->grabKeyboardFocus(); - } else - { - Component* const currentModalComp = Component::getCurrentlyModalComponent(); - - if (currentModalComp != 0) - currentModalComp->toFront (! currentModalComp->hasKeyboardFocus (true)); - } + Component::bringModalComponentToFront(); } } @@ -772,6 +765,12 @@ void ComponentPeer::handleUserClosingWindow() component->userTriedToCloseWindow(); } +//============================================================================== +void ComponentPeer::bringModalComponentToFront() +{ + Component::bringModalComponentToFront(); +} + //============================================================================== void ComponentPeer::clearMaskedRegion() throw() { diff --git a/src/juce_appframework/gui/components/windows/juce_ComponentPeer.h b/src/juce_appframework/gui/components/windows/juce_ComponentPeer.h index b30c007180..92f9ee5414 100644 --- a/src/juce_appframework/gui/components/windows/juce_ComponentPeer.h +++ b/src/juce_appframework/gui/components/windows/juce_ComponentPeer.h @@ -356,6 +356,9 @@ public: */ static bool isValidPeer (const ComponentPeer* const peer) throw(); + //============================================================================== + static void bringModalComponentToFront(); + //============================================================================== juce_UseDebuggingNewOperator diff --git a/src/juce_core/containers/juce_OwnedArray.h b/src/juce_core/containers/juce_OwnedArray.h index 719e9fb071..fc6869b0a0 100644 --- a/src/juce_core/containers/juce_OwnedArray.h +++ b/src/juce_core/containers/juce_OwnedArray.h @@ -355,12 +355,14 @@ public: if (indexToChange < numUsed) { if (deleteOldElement) + { toDelete = this->elements [indexToChange]; - if (toDelete == newObject) - toDelete = 0; - else - this->elements [indexToChange] = const_cast (newObject); + if (toDelete == newObject) + toDelete = 0; + } + + this->elements [indexToChange] = const_cast (newObject); } else {