diff --git a/build/linux/platform_specific_code/juce_linux_Windowing.cpp b/build/linux/platform_specific_code/juce_linux_Windowing.cpp index 02017e3d2a..9e65927deb 100644 --- a/build/linux/platform_specific_code/juce_linux_Windowing.cpp +++ b/build/linux/platform_specific_code/juce_linux_Windowing.cpp @@ -1067,8 +1067,7 @@ public: if (windowH != 0 && XGetWindowAttributes (display, windowH, &atts) - && atts.map_state == IsViewable - && ! isFocused()) + && atts.map_state == IsViewable) { XSetInputFocus (display, windowH, RevertToParent, CurrentTime); diff --git a/src/juce_appframework/gui/components/controls/juce_TextEditor.cpp b/src/juce_appframework/gui/components/controls/juce_TextEditor.cpp index 9fee7d5262..ebf5577f16 100644 --- a/src/juce_appframework/gui/components/controls/juce_TextEditor.cpp +++ b/src/juce_appframework/gui/components/controls/juce_TextEditor.cpp @@ -876,6 +876,8 @@ TextEditor::TextEditor (const String& name, wasFocused (false), caretFlashState (true), keepCursorOnScreen (true), + tabKeyUsed (false), + menuActive (false), cursorX (0), cursorY (0), cursorHeight (0), @@ -951,7 +953,7 @@ bool TextEditor::isMultiLine() const throw() return multiline; } -void TextEditor::setScrollbarsShown (bool enabled) +void TextEditor::setScrollbarsShown (bool enabled) throw() { scrollbarVisible = enabled; @@ -966,7 +968,7 @@ void TextEditor::setReadOnly (const bool shouldBeReadOnly) enablementChanged(); } -bool TextEditor::isReadOnly() const +bool TextEditor::isReadOnly() const throw() { return readOnly || ! isEnabled(); } @@ -976,28 +978,28 @@ void TextEditor::setReturnKeyStartsNewLine (const bool shouldStartNewLine) returnKeyStartsNewLine = shouldStartNewLine; } -bool TextEditor::getReturnKeyStartsNewLine() const +void TextEditor::setTabKeyUsedAsCharacter (const bool shouldTabKeyBeUsed) throw() { - return returnKeyStartsNewLine; + tabKeyUsed = shouldTabKeyBeUsed; } -void TextEditor::setPopupMenuEnabled (bool b) +void TextEditor::setPopupMenuEnabled (const bool b) throw() { popupMenuEnabled = b; } -void TextEditor::setSelectAllWhenFocused (bool b) +void TextEditor::setSelectAllWhenFocused (const bool b) throw() { selectAllTextWhenFocused = b; } //============================================================================== -const Font TextEditor::getFont() const +const Font TextEditor::getFont() const throw() { return currentFont; } -void TextEditor::setFont (const Font& newFont) +void TextEditor::setFont (const Font& newFont) throw() { currentFont = newFont; scrollToMakeSureCursorIsVisible(); @@ -1022,7 +1024,7 @@ void TextEditor::colourChanged() repaint(); } -void TextEditor::setCaretVisible (bool shouldCaretBeVisible) +void TextEditor::setCaretVisible (const bool shouldCaretBeVisible) throw() { caretVisible = shouldCaretBeVisible; @@ -1034,13 +1036,13 @@ void TextEditor::setCaretVisible (bool shouldCaretBeVisible) } void TextEditor::setInputRestrictions (const int maxLen, - const String& chars) + const String& chars) throw() { maxTextLength = jmax (0, maxLen); allowedCharacters = chars; } -void TextEditor::setTextToShowWhenEmpty (const String& text, const Colour& colourToUse) +void TextEditor::setTextToShowWhenEmpty (const String& text, const Colour& colourToUse) throw() { textToShowWhenEmpty = text; colourForTextWhenEmpty = colourToUse; @@ -1579,7 +1581,9 @@ void TextEditor::mouseDown (const MouseEvent& e) PopupMenu m; addPopupMenuItems (m); + menuActive = true; const int result = m.show(); + menuActive = false; if (result != 0) performPopupMenuAction (result); @@ -1837,8 +1841,8 @@ bool TextEditor::keyPressed (const KeyPress& key) escapePressed(); } else if (key.getTextCharacter() != 0 - && ! (isReadOnly() - || key.isKeyCode (KeyPress::tabKey))) + && (! isReadOnly()) + && (tabKeyUsed || ! key.isKeyCode (KeyPress::tabKey))) { if (! isReadOnly()) insertTextAtCursor (String::charToString (key.getTextCharacter())); diff --git a/src/juce_appframework/gui/components/controls/juce_TextEditor.h b/src/juce_appframework/gui/components/controls/juce_TextEditor.h index 70045449ed..9464a0d973 100644 --- a/src/juce_appframework/gui/components/controls/juce_TextEditor.h +++ b/src/juce_appframework/gui/components/controls/juce_TextEditor.h @@ -130,7 +130,20 @@ public: See setReturnKeyStartsNewLine() for more info. */ - bool getReturnKeyStartsNewLine() const; + bool getReturnKeyStartsNewLine() const throw() { return returnKeyStartsNewLine; } + + /** Indicates whether the tab key should be accepted and used to input a tab character, + or whether it gets ignored. + + By default the tab key is ignored, so that it can be used to switch keyboard focus + between components. + */ + void setTabKeyUsedAsCharacter (const bool shouldTabKeyBeUsed) throw(); + + /** Returns true if the tab key is being used for input. + @see setTabKeyUsedAsCharacter + */ + bool isTabKeyUsedAsCharacter() const throw() { return tabKeyUsed; } //============================================================================== /** Changes the editor to read-only mode. @@ -146,7 +159,7 @@ public: /** Returns true if the editor is in read-only mode. */ - bool isReadOnly() const; + bool isReadOnly() const throw(); //============================================================================== /** Makes the caret visible or invisible. @@ -155,7 +168,7 @@ public: @see setCaretColour, setCaretPosition */ - void setCaretVisible (bool shouldBeVisible); + void setCaretVisible (const bool shouldBeVisible) throw(); /** Returns true if the caret is enabled. @see setCaretVisible @@ -171,7 +184,7 @@ public: By default the scrollbar is enabled. */ - void setScrollbarsShown (bool shouldBeEnabled); + void setScrollbarsShown (bool shouldBeEnabled) throw(); /** Returns true if scrollbars are enabled. @see setScrollbarsShown @@ -204,13 +217,17 @@ l */ If enabled, right-clicking (or command-clicking on the Mac) will pop up a menu of options such as cut/copy/paste, undo/redo, etc. */ - void setPopupMenuEnabled (const bool menuEnabled); + void setPopupMenuEnabled (const bool menuEnabled) throw(); /** Returns true if the right-click menu is enabled. @see setPopupMenuEnabled */ bool isPopupMenuEnabled() const throw() { return popupMenuEnabled; } + /** Returns true if a popup-menu is currently being displayed. + */ + bool isPopupMenuCurrentlyActive() const throw() { return menuActive; } + //============================================================================== /** A set of colour IDs to use to change the colour of various aspects of the editor. @@ -256,7 +273,7 @@ l */ @see applyFontToAllText */ - void setFont (const Font& newFont); + void setFont (const Font& newFont) throw(); /** Applies a font to all the text in the editor. @@ -270,7 +287,7 @@ l */ @see setFont */ - const Font getFont() const; + const Font getFont() const throw(); //============================================================================== /** If set to true, focusing on the editor will highlight all its text. @@ -280,7 +297,7 @@ l */ This is useful for boxes where you expect the user to re-enter all the text when they focus on the component, rather than editing what's already there. */ - void setSelectAllWhenFocused (bool b); + void setSelectAllWhenFocused (const bool b) throw(); /** Sets limits on the characters that can be entered. @@ -290,7 +307,7 @@ l */ this string are allowed to be entered into the editor. */ void setInputRestrictions (const int maxTextLength, - const String& allowedCharacters = String::empty); + const String& allowedCharacters = String::empty) throw(); /** When the text editor is empty, it can be set to display a message. @@ -298,7 +315,7 @@ l */ string is only displayed, it's not taken to actually be the contents of the editor. */ - void setTextToShowWhenEmpty (const String& text, const Colour& colourToUse); + void setTextToShowWhenEmpty (const String& text, const Colour& colourToUse) throw(); //============================================================================== /** Changes the size of the scrollbars that are used. @@ -587,6 +604,8 @@ private: bool wasFocused : 1; bool caretFlashState : 1; bool keepCursorOnScreen : 1; + bool tabKeyUsed : 1; + bool menuActive : 1; UndoManager undoManager; float cursorX, cursorY, cursorHeight; diff --git a/src/juce_appframework/gui/components/juce_Component.cpp b/src/juce_appframework/gui/components/juce_Component.cpp index 31cd725582..7722e6db5c 100644 --- a/src/juce_appframework/gui/components/juce_Component.cpp +++ b/src/juce_appframework/gui/components/juce_Component.cpp @@ -60,9 +60,10 @@ static const int exitModalStateMessage = 0x7fff0002; //============================================================================== // these are also used by ComponentPeer -int64 juce_recentMouseDownTimes [4] = { 0, 0, 0, 0 }; -int juce_recentMouseDownX [4] = { 0, 0, 0, 0 }; -int juce_recentMouseDownY [4] = { 0, 0, 0, 0 }; +int64 juce_recentMouseDownTimes [4] = { 0, 0, 0, 0 }; +int juce_recentMouseDownX [4] = { 0, 0, 0, 0 }; +int juce_recentMouseDownY [4] = { 0, 0, 0, 0 }; +Component* juce_recentMouseDownComponent [4] = { 0, 0, 0, 0 }; int juce_LastMousePosX = 0; int juce_LastMousePosY = 0; int juce_MouseClickCounter = 0; @@ -77,12 +78,13 @@ static int countMouseClicks() throw() if (! juce_MouseHasMovedSignificantlySincePressed) ++numClicks; - for (int i = 1; i < 4; ++i) + for (int i = 1; i < numElementsInArray (juce_recentMouseDownTimes); ++i) { if (juce_recentMouseDownTimes[0] - juce_recentMouseDownTimes [i] < (int) (MouseEvent::getDoubleClickTimeout() * (1.0 + 0.25 * (i - 1))) && abs (juce_recentMouseDownX[0] - juce_recentMouseDownX[i]) < 8 - && abs (juce_recentMouseDownY[0] - juce_recentMouseDownY[i]) < 8) + && abs (juce_recentMouseDownY[0] - juce_recentMouseDownY[i]) < 8 + && juce_recentMouseDownComponent[0] == juce_recentMouseDownComponent [i]) { ++numClicks; } diff --git a/src/juce_appframework/gui/components/windows/juce_ComponentPeer.cpp b/src/juce_appframework/gui/components/windows/juce_ComponentPeer.cpp index 6c7d397b28..b9eccc5e82 100644 --- a/src/juce_appframework/gui/components/windows/juce_ComponentPeer.cpp +++ b/src/juce_appframework/gui/components/windows/juce_ComponentPeer.cpp @@ -51,6 +51,7 @@ BEGIN_JUCE_NAMESPACE extern int64 juce_recentMouseDownTimes[4]; extern int juce_recentMouseDownX [4]; extern int juce_recentMouseDownY [4]; +extern Component* juce_recentMouseDownComponent [4]; extern int juce_LastMousePosX; extern int juce_LastMousePosY; extern int juce_MouseClickCounter; @@ -224,16 +225,18 @@ void ComponentPeer::handleMouseDown (int x, int y, const int64 time) { // can't set these in the mouseDownInt() method, because it's re-entrant, so do it here.. - for (int i = 4; --i > 0;) + for (int i = numElementsInArray (juce_recentMouseDownTimes); --i > 0;) { juce_recentMouseDownTimes [i] = juce_recentMouseDownTimes [i - 1]; juce_recentMouseDownX [i] = juce_recentMouseDownX [i - 1]; juce_recentMouseDownY [i] = juce_recentMouseDownY [i - 1]; + juce_recentMouseDownComponent [i] = juce_recentMouseDownComponent [i - 1]; } juce_recentMouseDownTimes[0] = time; juce_recentMouseDownX[0] = x; juce_recentMouseDownY[0] = y; + juce_recentMouseDownComponent[0] = Component::componentUnderMouse; relativePositionToGlobal (juce_recentMouseDownX[0], juce_recentMouseDownY[0]); juce_MouseHasMovedSignificantlySincePressed = false;