diff --git a/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_Make.h b/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_Make.h index 458c47015d..1d6833c4cf 100644 --- a/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_Make.h +++ b/extras/Jucer (experimental)/Source/Project/jucer_ProjectExport_Make.h @@ -211,12 +211,19 @@ private: { const String buildDirName ("build"); const String intermediatesDirName (buildDirName + "/intermediate/" + config.getName().toString()); + String outputDir (buildDirName); + + if (config.getTargetBinaryRelativePath().toString().isNotEmpty()) + { + RelativePath binaryPath (config.getTargetBinaryRelativePath().toString(), RelativePath::projectFolder); + outputDir = binaryPath.rebased (project.getFile().getParentDirectory(), getTargetFolder(), RelativePath::buildTargetFolder).toUnixStyle(); + } out << "ifeq ($(CONFIG)," << escapeSpaces (config.getName().toString()) << ")" << newLine; out << " BINDIR := " << escapeSpaces (buildDirName) << newLine << " LIBDIR := " << escapeSpaces (buildDirName) << newLine << " OBJDIR := " << escapeSpaces (intermediatesDirName) << newLine - << " OUTDIR := " << escapeSpaces (buildDirName) << newLine; + << " OUTDIR := " << escapeSpaces (outputDir) << newLine; writeCppFlags (out, config); diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 5992ef0ea8..38836d588f 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -21666,7 +21666,7 @@ public: void setThumbnail (AudioThumbnail* thumb) { if (thumb != 0) - thumb->reset (buffer.getNumChannels(), writer->sampleRate); + thumb->reset (buffer.getNumChannels(), writer->getSampleRate()); const ScopedLock sl (thumbnailLock); thumbnailToUpdate = thumb; @@ -33165,7 +33165,7 @@ namespace } } -typedef AEffect* (*MainCall) (audioMasterCallback); +typedef AEffect* (VSTCALLBACK *MainCall) (audioMasterCallback); static VstIntPtr VSTCALLBACK audioMaster (AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt); @@ -42117,8 +42117,6 @@ void Component::internalMouseUp (MouseInputSource& source, const Point& rel { if (flags.mouseDownFlag) { - Desktop& desktop = Desktop::getInstance(); - flags.mouseDownFlag = false; BailOutChecker checker (this); @@ -42138,6 +42136,7 @@ void Component::internalMouseUp (MouseInputSource& source, const Point& rel if (checker.shouldBailOut()) return; + Desktop& desktop = Desktop::getInstance(); desktop.resetTimer(); desktop.mouseListeners.callChecked (checker, &MouseListener::mouseUp, me); @@ -42164,8 +42163,6 @@ void Component::internalMouseDrag (MouseInputSource& source, const Point& r { if (flags.mouseDownFlag) { - Desktop& desktop = Desktop::getInstance(); - flags.mouseOverFlag = reallyContains (relativePos, false); BailOutChecker checker (this); @@ -42182,6 +42179,7 @@ void Component::internalMouseDrag (MouseInputSource& source, const Point& r if (checker.shouldBailOut()) return; + Desktop& desktop = Desktop::getInstance(); desktop.resetTimer(); desktop.mouseListeners.callChecked (checker, &MouseListener::mouseDrag, me); @@ -51383,7 +51381,8 @@ void TableHeaderComponent::paint (Graphics& g) || dragOverlayComp == 0 || ! dragOverlayComp->isVisible())) { - g.saveState(); + Graphics::ScopedSaveState ss (g); + g.setOrigin (x, 0); g.reduceClipRegion (0, 0, ci->width, getHeight()); @@ -51391,8 +51390,6 @@ void TableHeaderComponent::paint (Graphics& g) ci->id == columnIdUnderMouse, ci->id == columnIdUnderMouse && isMouseButtonDown(), ci->propertyFlags); - - g.restoreState(); } x += ci->width; @@ -51807,11 +51804,11 @@ public: const int columnId = header.getColumnIdOfIndex (i, true); const Rectangle columnRect (header.getColumnPosition(i).withHeight (getHeight())); - g.saveState(); + Graphics::ScopedSaveState ss (g); + g.reduceClipRegion (columnRect); g.setOrigin (columnRect.getX(), 0); model->paintCell (g, row, columnId, columnRect.getWidth(), columnRect.getHeight(), isSelected); - g.restoreState(); } } } @@ -53771,12 +53768,6 @@ void TextEditor::insertTextAtCaret (const String& newText_) if (allowedCharacters.isNotEmpty()) newText = newText.retainCharacters (allowedCharacters); - if ((! returnKeyStartsNewLine) && newText == "\n") - { - returnPressed(); - return; - } - if (! isMultiLine()) newText = newText.replaceCharacters ("\r\n", " "); else @@ -54207,7 +54198,11 @@ bool TextEditor::keyPressed (const KeyPress& key) else if (key == KeyPress::returnKey) { newTransaction(); - insertTextAtCaret ("\n"); + + if (returnKeyStartsNewLine) + insertTextAtCaret ("\n"); + else + returnPressed(); } else if (key.isKeyCode (KeyPress::escapeKey)) { @@ -55772,13 +55767,12 @@ void ToolbarItemComponent::paintButton (Graphics& g, const bool over, const bool if (! contentArea.isEmpty()) { - g.saveState(); + Graphics::ScopedSaveState ss (g); + g.reduceClipRegion (contentArea); g.setOrigin (contentArea.getX(), contentArea.getY()); paintButtonArea (g, contentArea.getWidth(), contentArea.getHeight(), over, down); - - g.restoreState(); } } @@ -57310,14 +57304,12 @@ void TreeViewItem::paintRecursively (Graphics& g, int width) const int itemW = itemWidth < 0 ? width - indent : itemWidth; { - g.saveState(); + Graphics::ScopedSaveState ss (g); g.setOrigin (indent, 0); if (g.reduceClipRegion (drawsInLeftMargin ? -indent : 0, 0, drawsInLeftMargin ? itemW + indent : itemW, itemHeight)) paintItem (g, itemW, itemHeight); - - g.restoreState(); } g.setColour (ownerView->findColour (TreeView::linesColourId)); @@ -57369,15 +57361,14 @@ void TreeViewItem::paintRecursively (Graphics& g, int width) if (mightContainSubItems()) { - g.saveState(); + Graphics::ScopedSaveState ss (g); + g.setOrigin (depth * indentWidth, 0); g.reduceClipRegion (0, 0, indentWidth, itemHeight); paintOpenCloseButton (g, indentWidth, itemHeight, static_cast (ownerView->viewport->getViewedComponent()) ->isMouseOverButton (this)); - - g.restoreState(); } } @@ -57396,13 +57387,12 @@ void TreeViewItem::paintRecursively (Graphics& g, int width) if (relY + ti->totalHeight >= clip.getY()) { - g.saveState(); + Graphics::ScopedSaveState ss (g); + g.setOrigin (0, relY); if (g.reduceClipRegion (0, 0, width, ti->totalHeight)) ti->paintRecursively (g, width); - - g.restoreState(); } } } @@ -68388,7 +68378,8 @@ void MenuBarComponent::paint (Graphics& g) { for (int i = 0; i < menuNames.size(); ++i) { - g.saveState(); + Graphics::ScopedSaveState ss (g); + g.setOrigin (xPositions [i], 0); g.reduceClipRegion (0, 0, xPositions[i + 1] - xPositions[i], getHeight()); @@ -68401,8 +68392,6 @@ void MenuBarComponent::paint (Graphics& g) i == currentPopupIndex, isMouseOverBar, *this); - - g.restoreState(); } } } @@ -71178,13 +71167,12 @@ public: return 0; } - const Point getScreenPosition() + const Point getScreenPosition() const { - // This must only be called with the message manager locked! - jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); - - setScreenPos (MouseInputSource::getCurrentMousePosition(), Time::currentTimeMillis(), false); - return lastScreenPos + unboundedMouseOffset; + // This needs to return the live position if possible, but it mustn't update the lastScreenPos + // value, because that can cause continuity problems. + return unboundedMouseOffset + (isMouseDevice ? MouseInputSource::getCurrentMousePosition() + : lastScreenPos); } void sendMouseEnter (Component* const comp, const Point& screenPos, const int64 time) @@ -76371,10 +76359,6 @@ public: setSelectAllWhenFocused (true); } - ~AlertWindowTextEditor() - { - } - void returnPressed() { // pass these up the component hierarchy to be trigger the buttons @@ -77318,9 +77302,9 @@ void ComponentPeer::handlePaint (LowLevelGraphicsContext& contextToPaintTo) { Graphics g (&contextToPaintTo); -#if JUCE_ENABLE_REPAINT_DEBUGGING + #if JUCE_ENABLE_REPAINT_DEBUGGING g.saveState(); -#endif + #endif JUCE_TRY { @@ -77328,18 +77312,16 @@ void ComponentPeer::handlePaint (LowLevelGraphicsContext& contextToPaintTo) } JUCE_CATCH_EXCEPTION -#if JUCE_ENABLE_REPAINT_DEBUGGING + #if JUCE_ENABLE_REPAINT_DEBUGGING // enabling this code will fill all areas that get repainted with a colour overlay, to show // clearly when things are being repainted. - { - g.restoreState(); + g.restoreState(); - g.fillAll (Colour ((uint8) Random::getSystemRandom().nextInt (255), - (uint8) Random::getSystemRandom().nextInt (255), - (uint8) Random::getSystemRandom().nextInt (255), - (uint8) 0x50)); - } -#endif + g.fillAll (Colour ((uint8) Random::getSystemRandom().nextInt (255), + (uint8) Random::getSystemRandom().nextInt (255), + (uint8) Random::getSystemRandom().nextInt (255), + (uint8) 0x50)); + #endif /** If this fails, it's probably be because your CPU floating-point precision mode has been set to low.. This setting is sometimes changed by things like Direct3D, and can @@ -82523,6 +82505,17 @@ void Graphics::drawImageTransformed (const Image& imageToDraw, } } +Graphics::ScopedSaveState::ScopedSaveState (Graphics& g) + : context (g) +{ + context.saveState(); +} + +Graphics::ScopedSaveState::~ScopedSaveState() +{ + context.restoreState(); +} + END_JUCE_NAMESPACE /*** End of inlined file: juce_Graphics.cpp ***/ @@ -85673,7 +85666,8 @@ void Drawable::draw (Graphics& g, float opacity, const AffineTransform& transfor void Drawable::nonConstDraw (Graphics& g, float opacity, const AffineTransform& transform) { - g.saveState(); + Graphics::ScopedSaveState ss (g); + const float oldOpacity = getAlpha(); setAlpha (opacity); g.addTransform (AffineTransform::translation ((float) -originRelativeToComponent.getX(), @@ -85685,7 +85679,6 @@ void Drawable::nonConstDraw (Graphics& g, float opacity, const AffineTransform& paintEntireComponent (g, false); setAlpha (oldOpacity); - g.restoreState(); } void Drawable::drawAt (Graphics& g, float x, float y, float opacity) const @@ -252875,10 +252868,12 @@ public: const int rx = roundToInt (dx), ry = roundToInt (dy); const int rw = roundToInt (dw), rh = roundToInt (dh); - g.saveState(); - g.excludeClipRegion (Rectangle (rx, ry, rw, rh)); - g.fillAll (Colours::black); - g.restoreState(); + { + Graphics::ScopedSaveState ss (g); + + g.excludeClipRegion (Rectangle (rx, ry, rw, rh)); + g.fillAll (Colours::black); + } g.drawImage (activeImage, rx, ry, rw, rh, 0, 0, width, height); } diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 0b9bc76e96..88b985e429 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -64,7 +64,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 52 -#define JUCE_BUILDNUMBER 102 +#define JUCE_BUILDNUMBER 103 /** Current Juce version number. @@ -1198,12 +1198,14 @@ inline bool isPositiveAndBelow (Type valueToTest, Type upperLimit) throw() return Type() <= valueToTest && valueToTest < upperLimit; } +#if ! JUCE_VC6 template <> inline bool isPositiveAndBelow (const int valueToTest, const int upperLimit) throw() { jassert (upperLimit >= 0); // makes no sense to call this if the upper limit is itself below zero.. return static_cast (valueToTest) < static_cast (upperLimit); } +#endif /** Returns true if a value is at least zero, and also less than or equal to a specified upper limit. This is basically a quicker way to write: @@ -1217,12 +1219,14 @@ inline bool isPositiveAndNotGreaterThan (Type valueToTest, Type upperLimit) thro return Type() <= valueToTest && valueToTest <= upperLimit; } +#if ! JUCE_VC6 template <> inline bool isPositiveAndNotGreaterThan (const int valueToTest, const int upperLimit) throw() { jassert (upperLimit >= 0); // makes no sense to call this if the upper limit is itself below zero.. return static_cast (valueToTest) <= static_cast (upperLimit); } +#endif /** Handy function to swap two values over. */ @@ -25090,15 +25094,32 @@ public: bool isClipEmpty() const; /** Saves the current graphics state on an internal stack. - To restore the state, use restoreState(). + @see ScopedSaveState */ void saveState(); /** Restores a graphics state that was previously saved with saveState(). + @see ScopedSaveState */ void restoreState(); + /** Uses RAII to save and restore the state of a graphics context. + On construction, this calls Graphics::saveState(), and on destruction it calls + Graphics::restoreState() on the Graphics object that you supply. + */ + class ScopedSaveState + { + public: + ScopedSaveState (Graphics& g); + ~ScopedSaveState(); + + private: + Graphics& context; + + JUCE_DECLARE_NON_COPYABLE (ScopedSaveState); + }; + /** Begins rendering to an off-screen bitmap which will later be flattened onto the current context with the given opacity. diff --git a/src/audio/audio_file_formats/juce_AudioFormatWriter.cpp b/src/audio/audio_file_formats/juce_AudioFormatWriter.cpp index 110b7e3d9c..fee2d57216 100644 --- a/src/audio/audio_file_formats/juce_AudioFormatWriter.cpp +++ b/src/audio/audio_file_formats/juce_AudioFormatWriter.cpp @@ -264,7 +264,7 @@ public: void setThumbnail (AudioThumbnail* thumb) { if (thumb != 0) - thumb->reset (buffer.getNumChannels(), writer->sampleRate); + thumb->reset (buffer.getNumChannels(), writer->getSampleRate()); const ScopedLock sl (thumbnailLock); thumbnailToUpdate = thumb; diff --git a/src/audio/plugins/formats/juce_VSTPluginFormat.cpp b/src/audio/plugins/formats/juce_VSTPluginFormat.cpp index 37671c2f2c..394c4ae4aa 100644 --- a/src/audio/plugins/formats/juce_VSTPluginFormat.cpp +++ b/src/audio/plugins/formats/juce_VSTPluginFormat.cpp @@ -212,7 +212,7 @@ namespace } //============================================================================== -typedef AEffect* (*MainCall) (audioMasterCallback); +typedef AEffect* (VSTCALLBACK *MainCall) (audioMasterCallback); static VstIntPtr VSTCALLBACK audioMaster (AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt); diff --git a/src/core/juce_MathsFunctions.h b/src/core/juce_MathsFunctions.h index 5c7c2218db..1f68a4dffe 100644 --- a/src/core/juce_MathsFunctions.h +++ b/src/core/juce_MathsFunctions.h @@ -227,12 +227,14 @@ inline bool isPositiveAndBelow (Type valueToTest, Type upperLimit) throw() return Type() <= valueToTest && valueToTest < upperLimit; } +#if ! JUCE_VC6 template <> inline bool isPositiveAndBelow (const int valueToTest, const int upperLimit) throw() { jassert (upperLimit >= 0); // makes no sense to call this if the upper limit is itself below zero.. return static_cast (valueToTest) < static_cast (upperLimit); } +#endif /** Returns true if a value is at least zero, and also less than or equal to a specified upper limit. This is basically a quicker way to write: @@ -246,12 +248,14 @@ inline bool isPositiveAndNotGreaterThan (Type valueToTest, Type upperLimit) thro return Type() <= valueToTest && valueToTest <= upperLimit; } +#if ! JUCE_VC6 template <> inline bool isPositiveAndNotGreaterThan (const int valueToTest, const int upperLimit) throw() { jassert (upperLimit >= 0); // makes no sense to call this if the upper limit is itself below zero.. return static_cast (valueToTest) <= static_cast (upperLimit); } +#endif //============================================================================== /** Handy function to swap two values over. diff --git a/src/core/juce_StandardHeader.h b/src/core/juce_StandardHeader.h index f56f35f88c..5efc8d45b0 100644 --- a/src/core/juce_StandardHeader.h +++ b/src/core/juce_StandardHeader.h @@ -33,7 +33,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 52 -#define JUCE_BUILDNUMBER 102 +#define JUCE_BUILDNUMBER 103 /** Current Juce version number. diff --git a/src/gui/components/controls/juce_TableHeaderComponent.cpp b/src/gui/components/controls/juce_TableHeaderComponent.cpp index c8e939a8b2..a3162e81dc 100644 --- a/src/gui/components/controls/juce_TableHeaderComponent.cpp +++ b/src/gui/components/controls/juce_TableHeaderComponent.cpp @@ -543,7 +543,8 @@ void TableHeaderComponent::paint (Graphics& g) || dragOverlayComp == 0 || ! dragOverlayComp->isVisible())) { - g.saveState(); + Graphics::ScopedSaveState ss (g); + g.setOrigin (x, 0); g.reduceClipRegion (0, 0, ci->width, getHeight()); @@ -551,8 +552,6 @@ void TableHeaderComponent::paint (Graphics& g) ci->id == columnIdUnderMouse, ci->id == columnIdUnderMouse && isMouseButtonDown(), ci->propertyFlags); - - g.restoreState(); } x += ci->width; diff --git a/src/gui/components/controls/juce_TableListBox.cpp b/src/gui/components/controls/juce_TableListBox.cpp index a54fbe0909..8a7b85f789 100644 --- a/src/gui/components/controls/juce_TableListBox.cpp +++ b/src/gui/components/controls/juce_TableListBox.cpp @@ -63,11 +63,11 @@ public: const int columnId = header.getColumnIdOfIndex (i, true); const Rectangle columnRect (header.getColumnPosition(i).withHeight (getHeight())); - g.saveState(); + Graphics::ScopedSaveState ss (g); + g.reduceClipRegion (columnRect); g.setOrigin (columnRect.getX(), 0); model->paintCell (g, row, columnId, columnRect.getWidth(), columnRect.getHeight(), isSelected); - g.restoreState(); } } } diff --git a/src/gui/components/controls/juce_TextEditor.cpp b/src/gui/components/controls/juce_TextEditor.cpp index 755d8842d0..88da68300a 100644 --- a/src/gui/components/controls/juce_TextEditor.cpp +++ b/src/gui/components/controls/juce_TextEditor.cpp @@ -1602,12 +1602,6 @@ void TextEditor::insertTextAtCaret (const String& newText_) if (allowedCharacters.isNotEmpty()) newText = newText.retainCharacters (allowedCharacters); - if ((! returnKeyStartsNewLine) && newText == "\n") - { - returnPressed(); - return; - } - if (! isMultiLine()) newText = newText.replaceCharacters ("\r\n", " "); else @@ -2043,7 +2037,11 @@ bool TextEditor::keyPressed (const KeyPress& key) else if (key == KeyPress::returnKey) { newTransaction(); - insertTextAtCaret ("\n"); + + if (returnKeyStartsNewLine) + insertTextAtCaret ("\n"); + else + returnPressed(); } else if (key.isKeyCode (KeyPress::escapeKey)) { diff --git a/src/gui/components/controls/juce_ToolbarItemComponent.cpp b/src/gui/components/controls/juce_ToolbarItemComponent.cpp index 049ef37242..481c745106 100644 --- a/src/gui/components/controls/juce_ToolbarItemComponent.cpp +++ b/src/gui/components/controls/juce_ToolbarItemComponent.cpp @@ -205,13 +205,12 @@ void ToolbarItemComponent::paintButton (Graphics& g, const bool over, const bool if (! contentArea.isEmpty()) { - g.saveState(); + Graphics::ScopedSaveState ss (g); + g.reduceClipRegion (contentArea); g.setOrigin (contentArea.getX(), contentArea.getY()); paintButtonArea (g, contentArea.getWidth(), contentArea.getHeight(), over, down); - - g.restoreState(); } } diff --git a/src/gui/components/controls/juce_TreeView.cpp b/src/gui/components/controls/juce_TreeView.cpp index 7dc0cd0445..80cdfc4970 100644 --- a/src/gui/components/controls/juce_TreeView.cpp +++ b/src/gui/components/controls/juce_TreeView.cpp @@ -1437,14 +1437,12 @@ void TreeViewItem::paintRecursively (Graphics& g, int width) const int itemW = itemWidth < 0 ? width - indent : itemWidth; { - g.saveState(); + Graphics::ScopedSaveState ss (g); g.setOrigin (indent, 0); if (g.reduceClipRegion (drawsInLeftMargin ? -indent : 0, 0, drawsInLeftMargin ? itemW + indent : itemW, itemHeight)) paintItem (g, itemW, itemHeight); - - g.restoreState(); } g.setColour (ownerView->findColour (TreeView::linesColourId)); @@ -1497,15 +1495,14 @@ void TreeViewItem::paintRecursively (Graphics& g, int width) if (mightContainSubItems()) { - g.saveState(); + Graphics::ScopedSaveState ss (g); + g.setOrigin (depth * indentWidth, 0); g.reduceClipRegion (0, 0, indentWidth, itemHeight); paintOpenCloseButton (g, indentWidth, itemHeight, static_cast (ownerView->viewport->getViewedComponent()) ->isMouseOverButton (this)); - - g.restoreState(); } } @@ -1524,13 +1521,12 @@ void TreeViewItem::paintRecursively (Graphics& g, int width) if (relY + ti->totalHeight >= clip.getY()) { - g.saveState(); + Graphics::ScopedSaveState ss (g); + g.setOrigin (0, relY); if (g.reduceClipRegion (0, 0, width, ti->totalHeight)) ti->paintRecursively (g, width); - - g.restoreState(); } } } diff --git a/src/gui/components/juce_Component.cpp b/src/gui/components/juce_Component.cpp index c783fd04e7..f106d40fc1 100644 --- a/src/gui/components/juce_Component.cpp +++ b/src/gui/components/juce_Component.cpp @@ -2426,8 +2426,6 @@ void Component::internalMouseUp (MouseInputSource& source, const Point& rel { if (flags.mouseDownFlag) { - Desktop& desktop = Desktop::getInstance(); - flags.mouseDownFlag = false; BailOutChecker checker (this); @@ -2447,6 +2445,7 @@ void Component::internalMouseUp (MouseInputSource& source, const Point& rel if (checker.shouldBailOut()) return; + Desktop& desktop = Desktop::getInstance(); desktop.resetTimer(); desktop.mouseListeners.callChecked (checker, &MouseListener::mouseUp, me); @@ -2473,8 +2472,6 @@ void Component::internalMouseDrag (MouseInputSource& source, const Point& r { if (flags.mouseDownFlag) { - Desktop& desktop = Desktop::getInstance(); - flags.mouseOverFlag = reallyContains (relativePos, false); BailOutChecker checker (this); @@ -2491,6 +2488,7 @@ void Component::internalMouseDrag (MouseInputSource& source, const Point& r if (checker.shouldBailOut()) return; + Desktop& desktop = Desktop::getInstance(); desktop.resetTimer(); desktop.mouseListeners.callChecked (checker, &MouseListener::mouseDrag, me); diff --git a/src/gui/components/menus/juce_MenuBarComponent.cpp b/src/gui/components/menus/juce_MenuBarComponent.cpp index 8ad11151ab..02e6b93855 100644 --- a/src/gui/components/menus/juce_MenuBarComponent.cpp +++ b/src/gui/components/menus/juce_MenuBarComponent.cpp @@ -91,7 +91,8 @@ void MenuBarComponent::paint (Graphics& g) { for (int i = 0; i < menuNames.size(); ++i) { - g.saveState(); + Graphics::ScopedSaveState ss (g); + g.setOrigin (xPositions [i], 0); g.reduceClipRegion (0, 0, xPositions[i + 1] - xPositions[i], getHeight()); @@ -104,8 +105,6 @@ void MenuBarComponent::paint (Graphics& g) i == currentPopupIndex, isMouseOverBar, *this); - - g.restoreState(); } } } diff --git a/src/gui/components/mouse/juce_MouseInputSource.cpp b/src/gui/components/mouse/juce_MouseInputSource.cpp index 42033692e8..97dadd73d8 100644 --- a/src/gui/components/mouse/juce_MouseInputSource.cpp +++ b/src/gui/components/mouse/juce_MouseInputSource.cpp @@ -89,13 +89,12 @@ public: return 0; } - const Point getScreenPosition() + const Point getScreenPosition() const { - // This must only be called with the message manager locked! - jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); - - setScreenPos (MouseInputSource::getCurrentMousePosition(), Time::currentTimeMillis(), false); - return lastScreenPos + unboundedMouseOffset; + // This needs to return the live position if possible, but it mustn't update the lastScreenPos + // value, because that can cause continuity problems. + return unboundedMouseOffset + (isMouseDevice ? MouseInputSource::getCurrentMousePosition() + : lastScreenPos); } //============================================================================== diff --git a/src/gui/components/windows/juce_AlertWindow.cpp b/src/gui/components/windows/juce_AlertWindow.cpp index 1fdf509400..035754f68a 100644 --- a/src/gui/components/windows/juce_AlertWindow.cpp +++ b/src/gui/components/windows/juce_AlertWindow.cpp @@ -47,10 +47,6 @@ public: setSelectAllWhenFocused (true); } - ~AlertWindowTextEditor() - { - } - void returnPressed() { // pass these up the component hierarchy to be trigger the buttons diff --git a/src/gui/components/windows/juce_ComponentPeer.cpp b/src/gui/components/windows/juce_ComponentPeer.cpp index a11e29488c..a87cd3ba63 100644 --- a/src/gui/components/windows/juce_ComponentPeer.cpp +++ b/src/gui/components/windows/juce_ComponentPeer.cpp @@ -120,9 +120,9 @@ void ComponentPeer::handlePaint (LowLevelGraphicsContext& contextToPaintTo) { Graphics g (&contextToPaintTo); -#if JUCE_ENABLE_REPAINT_DEBUGGING + #if JUCE_ENABLE_REPAINT_DEBUGGING g.saveState(); -#endif + #endif JUCE_TRY { @@ -130,18 +130,16 @@ void ComponentPeer::handlePaint (LowLevelGraphicsContext& contextToPaintTo) } JUCE_CATCH_EXCEPTION -#if JUCE_ENABLE_REPAINT_DEBUGGING + #if JUCE_ENABLE_REPAINT_DEBUGGING // enabling this code will fill all areas that get repainted with a colour overlay, to show // clearly when things are being repainted. - { - g.restoreState(); + g.restoreState(); - g.fillAll (Colour ((uint8) Random::getSystemRandom().nextInt (255), - (uint8) Random::getSystemRandom().nextInt (255), - (uint8) Random::getSystemRandom().nextInt (255), - (uint8) 0x50)); - } -#endif + g.fillAll (Colour ((uint8) Random::getSystemRandom().nextInt (255), + (uint8) Random::getSystemRandom().nextInt (255), + (uint8) Random::getSystemRandom().nextInt (255), + (uint8) 0x50)); + #endif /** If this fails, it's probably be because your CPU floating-point precision mode has been set to low.. This setting is sometimes changed by things like Direct3D, and can diff --git a/src/gui/graphics/contexts/juce_Graphics.cpp b/src/gui/graphics/contexts/juce_Graphics.cpp index 23391747b7..6ce2580966 100644 --- a/src/gui/graphics/contexts/juce_Graphics.cpp +++ b/src/gui/graphics/contexts/juce_Graphics.cpp @@ -719,5 +719,17 @@ void Graphics::drawImageTransformed (const Image& imageToDraw, } } +//============================================================================== +Graphics::ScopedSaveState::ScopedSaveState (Graphics& g) + : context (g) +{ + context.saveState(); +} + +Graphics::ScopedSaveState::~ScopedSaveState() +{ + context.restoreState(); +} + END_JUCE_NAMESPACE diff --git a/src/gui/graphics/contexts/juce_Graphics.h b/src/gui/graphics/contexts/juce_Graphics.h index 3b2734e9bf..23dcd86d1a 100644 --- a/src/gui/graphics/contexts/juce_Graphics.h +++ b/src/gui/graphics/contexts/juce_Graphics.h @@ -603,16 +603,35 @@ public: /** Returns true if no drawing can be done because the clip region is zero. */ bool isClipEmpty() const; + //============================================================================== /** Saves the current graphics state on an internal stack. - To restore the state, use restoreState(). + @see ScopedSaveState */ void saveState(); /** Restores a graphics state that was previously saved with saveState(). + @see ScopedSaveState */ void restoreState(); + /** Uses RAII to save and restore the state of a graphics context. + On construction, this calls Graphics::saveState(), and on destruction it calls + Graphics::restoreState() on the Graphics object that you supply. + */ + class ScopedSaveState + { + public: + ScopedSaveState (Graphics& g); + ~ScopedSaveState(); + + private: + Graphics& context; + + JUCE_DECLARE_NON_COPYABLE (ScopedSaveState); + }; + + //============================================================================== /** Begins rendering to an off-screen bitmap which will later be flattened onto the current context with the given opacity. diff --git a/src/gui/graphics/drawables/juce_Drawable.cpp b/src/gui/graphics/drawables/juce_Drawable.cpp index 0f159de1ad..5b0e1fc602 100644 --- a/src/gui/graphics/drawables/juce_Drawable.cpp +++ b/src/gui/graphics/drawables/juce_Drawable.cpp @@ -58,7 +58,8 @@ void Drawable::draw (Graphics& g, float opacity, const AffineTransform& transfor void Drawable::nonConstDraw (Graphics& g, float opacity, const AffineTransform& transform) { - g.saveState(); + Graphics::ScopedSaveState ss (g); + const float oldOpacity = getAlpha(); setAlpha (opacity); g.addTransform (AffineTransform::translation ((float) -originRelativeToComponent.getX(), @@ -70,7 +71,6 @@ void Drawable::nonConstDraw (Graphics& g, float opacity, const AffineTransform& paintEntireComponent (g, false); setAlpha (oldOpacity); - g.restoreState(); } void Drawable::drawAt (Graphics& g, float x, float y, float opacity) const diff --git a/src/native/windows/juce_win32_CameraDevice.cpp b/src/native/windows/juce_win32_CameraDevice.cpp index a9c41e462b..50c750e98a 100644 --- a/src/native/windows/juce_win32_CameraDevice.cpp +++ b/src/native/windows/juce_win32_CameraDevice.cpp @@ -244,10 +244,12 @@ public: const int rx = roundToInt (dx), ry = roundToInt (dy); const int rw = roundToInt (dw), rh = roundToInt (dh); - g.saveState(); - g.excludeClipRegion (Rectangle (rx, ry, rw, rh)); - g.fillAll (Colours::black); - g.restoreState(); + { + Graphics::ScopedSaveState ss (g); + + g.excludeClipRegion (Rectangle (rx, ry, rw, rh)); + g.fillAll (Colours::black); + } g.drawImage (activeImage, rx, ry, rw, rh, 0, 0, width, height); }