| @@ -399,16 +399,21 @@ public final class JuceDemo extends Activity | |||||
| private native void handleKeyDown (long host, int keycode, int textchar); | private native void handleKeyDown (long host, int keycode, int textchar); | ||||
| private native void handleKeyUp (long host, int keycode, int textchar); | private native void handleKeyUp (long host, int keycode, int textchar); | ||||
| public void showKeyboard (boolean shouldShow) | |||||
| public void showKeyboard (String type) | |||||
| { | { | ||||
| InputMethodManager imm = (InputMethodManager) getSystemService (Context.INPUT_METHOD_SERVICE); | InputMethodManager imm = (InputMethodManager) getSystemService (Context.INPUT_METHOD_SERVICE); | ||||
| if (imm != null) | if (imm != null) | ||||
| { | { | ||||
| if (shouldShow) | |||||
| imm.showSoftInput (this, InputMethodManager.SHOW_FORCED); | |||||
| if (! type.isEmpty()) | |||||
| { | |||||
| imm.showSoftInput (this, android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT); | |||||
| imm.setInputMethod (getWindowToken(), type); | |||||
| } | |||||
| else | else | ||||
| { | |||||
| imm.hideSoftInputFromWindow (getWindowToken(), 0); | imm.hideSoftInputFromWindow (getWindowToken(), 0); | ||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -399,16 +399,21 @@ public final class JuceAppActivity extends Activity | |||||
| private native void handleKeyDown (long host, int keycode, int textchar); | private native void handleKeyDown (long host, int keycode, int textchar); | ||||
| private native void handleKeyUp (long host, int keycode, int textchar); | private native void handleKeyUp (long host, int keycode, int textchar); | ||||
| public void showKeyboard (boolean shouldShow) | |||||
| public void showKeyboard (String type) | |||||
| { | { | ||||
| InputMethodManager imm = (InputMethodManager) getSystemService (Context.INPUT_METHOD_SERVICE); | InputMethodManager imm = (InputMethodManager) getSystemService (Context.INPUT_METHOD_SERVICE); | ||||
| if (imm != null) | if (imm != null) | ||||
| { | { | ||||
| if (shouldShow) | |||||
| imm.showSoftInput (this, InputMethodManager.SHOW_FORCED); | |||||
| if (! type.isEmpty()) | |||||
| { | |||||
| imm.showSoftInput (this, android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT); | |||||
| imm.setInputMethod (getWindowToken(), type); | |||||
| } | |||||
| else | else | ||||
| { | |||||
| imm.hideSoftInputFromWindow (getWindowToken(), 0); | imm.hideSoftInputFromWindow (getWindowToken(), 0); | ||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -71,6 +71,23 @@ public: | |||||
| /** Returns the position of the caret, relative to the component's origin. */ | /** Returns the position of the caret, relative to the component's origin. */ | ||||
| virtual Rectangle<int> getCaretRectangle() = 0; | virtual Rectangle<int> getCaretRectangle() = 0; | ||||
| /** A set of possible on-screen keyboard types, for use in the | |||||
| getKeyboardType() method. | |||||
| */ | |||||
| enum VirtualKeyboardType | |||||
| { | |||||
| textKeyboard = 0, | |||||
| numericKeyboard, | |||||
| urlKeyboard, | |||||
| emailAddressKeyboard, | |||||
| phoneNumberKeyboard | |||||
| }; | |||||
| /** Returns the target's preference for the type of keyboard that would be most appropriate. | |||||
| This may be ignored, depending on the capabilities of the OS. | |||||
| */ | |||||
| virtual VirtualKeyboardType getKeyboardType() { return textKeyboard; } | |||||
| }; | }; | ||||
| @@ -91,7 +91,7 @@ DECLARE_JNI_CLASS (CanvasMinimal, "android/graphics/Canvas"); | |||||
| METHOD (hasFocus, "hasFocus", "()Z") \ | METHOD (hasFocus, "hasFocus", "()Z") \ | ||||
| METHOD (invalidate, "invalidate", "(IIII)V") \ | METHOD (invalidate, "invalidate", "(IIII)V") \ | ||||
| METHOD (containsPoint, "containsPoint", "(II)Z") \ | METHOD (containsPoint, "containsPoint", "(II)Z") \ | ||||
| METHOD (showKeyboard, "showKeyboard", "(Z)V") \ | |||||
| METHOD (showKeyboard, "showKeyboard", "(Ljava/lang/String;)V") \ | |||||
| METHOD (createGLView, "createGLView", "()L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$OpenGLView;") \ | METHOD (createGLView, "createGLView", "()L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$OpenGLView;") \ | ||||
| DECLARE_JNI_CLASS (ComponentPeerView, JUCE_ANDROID_ACTIVITY_CLASSPATH "$ComponentPeerView"); | DECLARE_JNI_CLASS (ComponentPeerView, JUCE_ANDROID_ACTIVITY_CLASSPATH "$ComponentPeerView"); | ||||
| @@ -378,14 +378,30 @@ public: | |||||
| handleFocusLoss(); | handleFocusLoss(); | ||||
| } | } | ||||
| void textInputRequired (const Point<int>&) override | |||||
| static const char* getVirtualKeyboardType (TextInputTarget::VirtualKeyboardType type) noexcept | |||||
| { | { | ||||
| view.callVoidMethod (ComponentPeerView.showKeyboard, true); | |||||
| switch (type) | |||||
| { | |||||
| case TextInputTarget::textKeyboard: return "text"; | |||||
| case TextInputTarget::numericKeyboard: return "number"; | |||||
| case TextInputTarget::urlKeyboard: return "textUri"; | |||||
| case TextInputTarget::emailAddressKeyboard: return "textEmailAddress"; | |||||
| case TextInputTarget::phoneNumberKeyboard: return "phone"; | |||||
| default: jassertfalse; break; | |||||
| } | |||||
| return "text"; | |||||
| } | |||||
| void textInputRequired (Point<int>, TextInputTarget& target) override | |||||
| { | |||||
| view.callVoidMethod (ComponentPeerView.showKeyboard, | |||||
| javaString (getVirtualKeyboardType (target.getKeyboardType())).get()); | |||||
| } | } | ||||
| void dismissPendingTextInput() override | void dismissPendingTextInput() override | ||||
| { | { | ||||
| view.callVoidMethod (ComponentPeerView.showKeyboard, false); | |||||
| view.callVoidMethod (ComponentPeerView.showKeyboard, javaString ("").get()); | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -168,7 +168,7 @@ public: | |||||
| void viewFocusLoss(); | void viewFocusLoss(); | ||||
| bool isFocused() const override; | bool isFocused() const override; | ||||
| void grabFocus() override; | void grabFocus() override; | ||||
| void textInputRequired (const Point<int>&) override; | |||||
| void textInputRequired (Point<int>, TextInputTarget&) override; | |||||
| BOOL textViewReplaceCharacters (Range<int>, const String&); | BOOL textViewReplaceCharacters (Range<int>, const String&); | ||||
| void updateHiddenTextContent (TextInputTarget*); | void updateHiddenTextContent (TextInputTarget*); | ||||
| @@ -702,10 +702,7 @@ void UIViewComponentPeer::toFront (bool makeActiveWindow) | |||||
| void UIViewComponentPeer::toBehind (ComponentPeer* other) | void UIViewComponentPeer::toBehind (ComponentPeer* other) | ||||
| { | { | ||||
| UIViewComponentPeer* const otherPeer = dynamic_cast <UIViewComponentPeer*> (other); | |||||
| jassert (otherPeer != nullptr); // wrong type of window? | |||||
| if (otherPeer != nullptr) | |||||
| if (UIViewComponentPeer* const otherPeer = dynamic_cast<UIViewComponentPeer*> (other)) | |||||
| { | { | ||||
| if (isSharedWindow) | if (isSharedWindow) | ||||
| { | { | ||||
| @@ -716,6 +713,10 @@ void UIViewComponentPeer::toBehind (ComponentPeer* other) | |||||
| // don't know how to do this | // don't know how to do this | ||||
| } | } | ||||
| } | } | ||||
| else | |||||
| { | |||||
| jassertfalse; // wrong type of window? | |||||
| } | |||||
| } | } | ||||
| void UIViewComponentPeer::setIcon (const Image& /*newIcon*/) | void UIViewComponentPeer::setIcon (const Image& /*newIcon*/) | ||||
| @@ -828,12 +829,28 @@ void UIViewComponentPeer::grabFocus() | |||||
| } | } | ||||
| } | } | ||||
| void UIViewComponentPeer::textInputRequired (const Point<int>&) | |||||
| void UIViewComponentPeer::textInputRequired (Point<int>, TextInputTarget&) | |||||
| { | |||||
| } | |||||
| static UIKeyboardType getUIKeyboardType (TextInputTarget::VirtualKeyboardType type) noexcept | |||||
| { | { | ||||
| switch (type) | |||||
| { | |||||
| case TextInputTarget::textKeyboard: return UIKeyboardTypeAlphabet; | |||||
| case TextInputTarget::numericKeyboard: return UIKeyboardTypeNumbersAndPunctuation; | |||||
| case TextInputTarget::urlKeyboard: return UIKeyboardTypeURL; | |||||
| case TextInputTarget::emailAddressKeyboard: return UIKeyboardTypeEmailAddress; | |||||
| case TextInputTarget::phoneNumberKeyboard: return UIKeyboardTypePhonePad; | |||||
| default: jassertfalse; break; | |||||
| } | |||||
| return UIKeyboardTypeDefault; | |||||
| } | } | ||||
| void UIViewComponentPeer::updateHiddenTextContent (TextInputTarget* target) | void UIViewComponentPeer::updateHiddenTextContent (TextInputTarget* target) | ||||
| { | { | ||||
| view->hiddenTextView.keyboardType = getUIKeyboardType (target->getKeyboardType()); | |||||
| view->hiddenTextView.text = juceStringToNS (target->getTextInRange (Range<int> (0, target->getHighlightedRegion().getStart()))); | view->hiddenTextView.text = juceStringToNS (target->getTextInRange (Range<int> (0, target->getHighlightedRegion().getStart()))); | ||||
| view->hiddenTextView.selectedRange = NSMakeRange (target->getHighlightedRegion().getStart(), 0); | view->hiddenTextView.selectedRange = NSMakeRange (target->getHighlightedRegion().getStart(), 0); | ||||
| } | } | ||||
| @@ -1217,7 +1217,7 @@ public: | |||||
| } | } | ||||
| } | } | ||||
| void textInputRequired (const Point<int>&) override {} | |||||
| void textInputRequired (Point<int>, TextInputTarget&) override {} | |||||
| void repaint (const Rectangle<int>& area) override | void repaint (const Rectangle<int>& area) override | ||||
| { | { | ||||
| @@ -1151,7 +1151,7 @@ public: | |||||
| } | } | ||||
| } | } | ||||
| void textInputRequired (const Point<int>&) override {} | |||||
| void textInputRequired (Point<int>, TextInputTarget&) override {} | |||||
| //============================================================================== | //============================================================================== | ||||
| void repaint (const Rectangle<int>& area) override | void repaint (const Rectangle<int>& area) override | ||||
| @@ -877,7 +877,7 @@ public: | |||||
| shouldDeactivateTitleBar = oldDeactivate; | shouldDeactivateTitleBar = oldDeactivate; | ||||
| } | } | ||||
| void textInputRequired (const Point<int>&) override | |||||
| void textInputRequired (Point<int>, TextInputTarget&) override | |||||
| { | { | ||||
| if (! hasCreatedCaret) | if (! hasCreatedCaret) | ||||
| { | { | ||||
| @@ -2059,7 +2059,7 @@ void TextEditor::focusGained (FocusChangeType) | |||||
| if (ComponentPeer* const peer = getPeer()) | if (ComponentPeer* const peer = getPeer()) | ||||
| if (! isReadOnly()) | if (! isReadOnly()) | ||||
| peer->textInputRequired (peer->globalToLocal (getScreenPosition())); | |||||
| peer->textInputRequired (peer->globalToLocal (getScreenPosition()), *this); | |||||
| } | } | ||||
| void TextEditor::focusLost (FocusChangeType) | void TextEditor::focusLost (FocusChangeType) | ||||
| @@ -276,7 +276,7 @@ public: | |||||
| This may cause things like a virtual on-screen keyboard to appear, depending | This may cause things like a virtual on-screen keyboard to appear, depending | ||||
| on the OS. | on the OS. | ||||
| */ | */ | ||||
| virtual void textInputRequired (const Point<int>& position) = 0; | |||||
| virtual void textInputRequired (Point<int> position, TextInputTarget&) = 0; | |||||
| /** If there's some kind of OS input-method in progress, this should dismiss it. */ | /** If there's some kind of OS input-method in progress, this should dismiss it. */ | ||||
| virtual void dismissPendingTextInput(); | virtual void dismissPendingTextInput(); | ||||