Skip to content

Commit 426697f

Browse files
committed
[[ Bug 21467 ]] Implement mobileSetKeyboardDisplay
This patch implements a new command `mobileSetKeyboardDisplay` and function `mobileGetKeyboardDisplay` to govern the behavior of the keyboard on mobile to pan the view up if necessary so the focused object is visible.
1 parent afcc655 commit 426697f

File tree

15 files changed

+372
-8
lines changed

15 files changed

+372
-8
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
Name: mobileSetKeyboardDisplay
2+
3+
Type: command
4+
5+
Syntax: mobileSetKeyboardDisplay <mode>
6+
7+
Summary:
8+
Configures the mode in which the keyboard is displayed
9+
10+
Introduced: 9.5
11+
12+
OS: ios, android
13+
14+
Platforms: mobile
15+
16+
Example:
17+
mobileSetKeyboardDisplay "pan"
18+
19+
Example:
20+
mobileSetKeyboardDisplay "over"
21+
22+
Parameters:
23+
mode (enum):
24+
The mode of keyboard display to use. One of:
25+
26+
- "over": Display the keyboard over the current stack rect. Over is the default
27+
keyboard display mode
28+
- "pan": Pan the stack up so that the rect of the foucused object will be
29+
visible above the keyboard
30+
31+
Description:
32+
Use the <mobileSetKeyboardDisplay> command to configure the move of
33+
keyboard display.
34+
35+
The <mobileSetKeyboardDisplay> setting takes affect the next time the keyboard is
36+
shown. It does not affect the current keyboard, if it is being displayed.
37+
38+
References: keyboardDeactivated (message), keyboardActivated (message),
39+
mobileGetKeyboardDisplay (function)
40+
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
Name: mobileGetKeyboardDisplay
2+
3+
Type: function
4+
5+
Syntax: mobileSetKeyboardDisplay()
6+
7+
Summary:
8+
Get the mode in which the keyboard is displayed
9+
10+
Introduced: 9.5
11+
12+
OS: ios, android
13+
14+
Platforms: mobile
15+
16+
Example:
17+
on keyboardActivated
18+
if mobileGetKeyboardDisplay() is "over" then
19+
layoutUI
20+
end if
21+
end keyboardActivated
22+
23+
Returns (enum):
24+
The mode of keyboard display to use. One of:
25+
26+
- "over": Display the keyboard over the current stack rect
27+
- "pan": Pan the stack up so that the rect of the foucused object will be
28+
visible above the keyboard
29+
30+
Description:
31+
Use the <mobileSetKeyboardDisplay> command to configure the move of
32+
keyboard display.
33+
34+
References: keyboardDeactivated (message), keyboardActivated (message),
35+
mobileSetKeyboardDisplay (command)
36+

docs/notes/bugfix-21467.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# New mobileSetKeyboardDisplay and mobileGetKeyboardDisplay handlers
2+
3+
A new command `mobileSetKeyboardDisplay` has been added to support a `pan` mode
4+
where the view is panned up if the currently focused field control is not visible
5+
when the keyboard is shown. Use `mobileGetKeyboardDisplay` to get the current
6+
mode. There are two modes supported:
7+
8+
- `over` - the default where the keyboard displays over the stack
9+
- `pan` - the view is panned up the minimum amount required to ensure the
10+
foucused field is visible.

engine/src/exec-misc.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,10 +224,28 @@ void MCMiscSetKeyboardReturnKey(MCExecContext& ctxt, intenum_t p_keyboard_return
224224
{
225225
if (MCSystemSetKeyboardReturnKey(p_keyboard_return_key))
226226
return;
227+
228+
ctxt.Throw();
229+
}
230+
231+
static intenum_t s_current_keyboard_display = 0;
232+
233+
void MCMiscExecSetKeyboardDisplay(MCExecContext& ctxt, intenum_t p_mode)
234+
{
235+
if (MCSystemSetKeyboardDisplay(p_mode))
236+
{
237+
s_current_keyboard_display = p_mode;
238+
return;
239+
}
227240

228241
ctxt.Throw();
229242
}
230243

244+
void MCMiscExecGetKeyboardDisplay(MCExecContext& ctxt, intenum_t& r_mode)
245+
{
246+
r_mode = s_current_keyboard_display;
247+
}
248+
231249
void MCMiscGetPreferredLanguages(MCExecContext& ctxt, MCStringRef& r_languages)
232250
{
233251
if (MCSystemGetPreferredLanguages(r_languages))

engine/src/exec.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4019,6 +4019,8 @@ void MCMiscExecHideStatusBar(MCExecContext& ctxt);
40194019

40204020
void MCMiscSetKeyboardType(MCExecContext& ctxt, intenum_t p_keyboard_type);
40214021
void MCMiscSetKeyboardReturnKey(MCExecContext& ctxt, intenum_t p_keyboard_return_key);
4022+
void MCMiscExecSetKeyboardDisplay(MCExecContext& ctxt, intenum_t p_mode);
4023+
void MCMiscExecGetKeyboardDisplay(MCExecContext& ctxt, intenum_t& r_mode);
40224024

40234025
void MCMiscGetPreferredLanguages(MCExecContext& ctxt, MCStringRef& r_preferred_languages);
40244026
void MCMiscGetCurrentLocale(MCExecContext& ctxt, MCStringRef& r_current_locale);

engine/src/java/com/runrev/android/Engine.java

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,41 @@ public void showKeyboard()
609609

610610
// HH-2017-01-18: [[ Bug 18058 ]] Fix keyboard not show in landscape orientation
611611
imm.showSoftInput(this, InputMethodManager.SHOW_FORCED);
612-
}
612+
}
613+
614+
@Override
615+
public void getFocusedRect(Rect r_rect)
616+
{
617+
Rect t_rect = doGetFocusedRect();
618+
619+
if (t_rect == null)
620+
{
621+
super.getFocusedRect(r_rect);
622+
}
623+
else
624+
{
625+
r_rect.set(t_rect);
626+
}
627+
}
628+
629+
private static final int KEYBOARD_DISPLAY_OVER = 0;
630+
private static final int KEYBOARD_DISPLAY_PAN = 1;
631+
632+
public void setKeyboardDisplay(int p_mode)
633+
{
634+
if (p_mode == KEYBOARD_DISPLAY_PAN)
635+
{
636+
getActivity()
637+
.getWindow()
638+
.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
639+
}
640+
else if (p_mode == KEYBOARD_DISPLAY_OVER)
641+
{
642+
getActivity()
643+
.getWindow()
644+
.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
645+
}
646+
}
613647

614648
public void hideKeyboard()
615649
{
@@ -3833,6 +3867,8 @@ public static native void doPurchaseStateChanged(boolean verified, int purchaseS
38333867
public static native void doReconfigure(int x, int y, int w, int h, Bitmap bitmap);
38343868

38353869
public static native String doGetCustomPropertyValue(String set, String property);
3870+
3871+
public static native Rect doGetFocusedRect();
38363872

38373873
// MW-2013-08-07: [[ ExternalsApiV5 ]] Native wrapper around MCScreenDC::wait
38383874
// used by runActivity() API.

engine/src/mblandroiddc.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2013,6 +2013,7 @@ extern "C" JNIEXPORT void JNICALL Java_com_runrev_android_Engine_doMediaDone(JNI
20132013
extern "C" JNIEXPORT void JNICALL Java_com_runrev_android_Engine_doMediaCanceled(JNIEnv *env, jobject object) __attribute__((visibility("default")));
20142014
extern "C" JNIEXPORT void JNICALL Java_com_runrev_android_Engine_doKeyboardShown(JNIEnv *env, jobject object, int height) __attribute__((visibility("default")));
20152015
extern "C" JNIEXPORT void JNICALL Java_com_runrev_android_Engine_doKeyboardHidden(JNIEnv *env, jobject object) __attribute__((visibility("default")));
2016+
extern "C" JNIEXPORT jobject JNICALL Java_com_runrev_android_Engine_doGetFocusedRect(JNIEnv *env, jobject object) __attribute__((visibility("default")));
20162017

20172018
JNIEXPORT void JNICALL Java_com_runrev_android_Engine_doCreate(JNIEnv *env, jobject object, jobject activity, jobject container, jobject view)
20182019
{
@@ -3085,6 +3086,58 @@ JNIEXPORT jstring JNICALL Java_com_runrev_android_Engine_doGetCustomPropertyValu
30853086

30863087
////////////////////////////////////////////////////////////////////////////////
30873088

3089+
JNIEXPORT jobject JNICALL Java_com_runrev_android_Engine_doGetFocusedRect(JNIEnv *env, jobject object)
3090+
{
3091+
MCObject *t_object = nullptr;
3092+
if (MCactivefield.IsValid())
3093+
{
3094+
t_object = MCactivefield;
3095+
}
3096+
3097+
if (t_object == nullptr)
3098+
{
3099+
t_object = MCdefaultstackptr->getcard()->getkfocused();
3100+
}
3101+
3102+
if (t_object == nullptr)
3103+
{
3104+
t_object = MCdefaultstackptr->getcard();
3105+
}
3106+
3107+
if (t_object == nullptr)
3108+
{
3109+
return nullptr;
3110+
}
3111+
3112+
MCRectangle t_object_rect = t_object -> getrect();
3113+
MCGAffineTransform t_transform = MCdefaultstackptr->getdevicetransform();
3114+
3115+
MCRectangle t_transformed_object_rect =
3116+
MCRectangleGetTransformedBounds(t_object_rect, t_transform);
3117+
3118+
jclass t_class = env->FindClass("android/graphics/Rect");
3119+
if (t_class == nullptr)
3120+
{
3121+
return nullptr;
3122+
}
3123+
3124+
jmethodID t_constructor = env->GetMethodID(t_class, "<init>", "(IIII)V");
3125+
if (t_constructor == nullptr)
3126+
{
3127+
return nullptr;
3128+
}
3129+
jobject t_rect = env->NewObject(t_class,
3130+
t_constructor,
3131+
t_transformed_object_rect.x,
3132+
t_transformed_object_rect.y,
3133+
t_transformed_object_rect.x + t_transformed_object_rect.width,
3134+
t_transformed_object_rect.y + t_transformed_object_rect.height);
3135+
3136+
return t_rect;
3137+
}
3138+
3139+
////////////////////////////////////////////////////////////////////////////////
3140+
30883141
void MCAndroidInitEngine()
30893142
{
30903143
MCAndroidEngineCall("onAppLaunched", "v", nil);

engine/src/mblandroidmisc.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,13 @@ bool MCSystemSetKeyboardReturnKey(intenum_t p_type)
707707
return false;
708708
}
709709

710+
711+
bool MCSystemSetKeyboardDisplay(intenum_t p_type)
712+
{
713+
MCAndroidEngineRemoteCall("setKeyboardDisplay", "vi", nullptr, p_type);
714+
return true;
715+
}
716+
710717
// SN-2014-12-18: [[ Bug 13860 ]] Parameter added in case it's a filename, not raw data, in the DataRef
711718
bool MCSystemExportImageToAlbum(MCStringRef& r_save_result, MCDataRef p_raw_data, MCStringRef p_file_name, MCStringRef p_file_extension, bool p_is_raw_data)
712719
{

engine/src/mblhandlers.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3057,6 +3057,62 @@ Exec_stat MCHandleSetKeyboardReturnKey (void *context, MCParameter *p_parameters
30573057
return ES_ERROR;
30583058
}
30593059

3060+
static const char *s_keyboard_display_names[] =
3061+
{
3062+
"over", "pan", nil
3063+
};
3064+
3065+
3066+
Exec_stat MCHandleSetKeyboardDisplay(void *context, MCParameter *p_parameters)
3067+
{
3068+
MCExecContext ctxt(nil, nil, nil);
3069+
ctxt.SetTheResultToEmpty();
3070+
3071+
MCAutoStringRef t_mode_string;
3072+
if (!MCParseParameters(p_parameters, "x", &(&t_mode_string)))
3073+
{
3074+
return ES_ERROR;
3075+
}
3076+
3077+
bool t_success = true;
3078+
3079+
intenum_t t_mode = 0;
3080+
for (uint32_t i = 0; s_keyboard_display_names[i] != nil; i++)
3081+
{
3082+
if (MCStringIsEqualToCString(*t_mode_string, s_keyboard_display_names[i], kMCCompareCaseless))
3083+
{
3084+
t_mode = i;
3085+
break;
3086+
}
3087+
}
3088+
3089+
MCMiscExecSetKeyboardDisplay(ctxt, t_mode);
3090+
3091+
if (!ctxt.HasError())
3092+
{
3093+
return ES_NORMAL;
3094+
}
3095+
3096+
return ES_ERROR;
3097+
}
3098+
3099+
Exec_stat MCHandleGetKeyboardDisplay(void *context, MCParameter *p_parameters)
3100+
{
3101+
MCExecContext ctxt(nil, nil, nil);
3102+
ctxt.SetTheResultToEmpty();
3103+
3104+
intenum_t t_mode;
3105+
MCMiscExecGetKeyboardDisplay(ctxt, t_mode);
3106+
3107+
if (!ctxt.HasError())
3108+
{
3109+
ctxt.SetTheResultToStaticCString(s_keyboard_display_names[t_mode]);
3110+
return ES_NORMAL;
3111+
}
3112+
3113+
return ES_ERROR;
3114+
}
3115+
30603116
Exec_stat MCHandlePreferredLanguages(void *context, MCParameter* p_parameters)
30613117
{
30623118
MCExecContext ctxt(nil, nil, nil);
@@ -4783,6 +4839,9 @@ static const MCPlatformMessageSpec s_platform_messages[] =
47834839
{false, "mobileEnableNFCDispatch", MCHandleEnableNFCDispatch, nil},
47844840
{false, "mobileDisableNFCDispatch", MCHandleDisableNFCDispatch, nil},
47854841

4842+
{false, "mobileSetKeyboardDisplay", MCHandleSetKeyboardDisplay, nil},
4843+
{false, "mobileGetKeyboardDisplay", MCHandleGetKeyboardDisplay, nil},
4844+
47864845
{nil, nil, nil}
47874846
};
47884847

engine/src/mbliphoneapp.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ enum MCIPhoneApplicationStatus
6767
kMCIPhoneApplicationStatusShutdown,
6868
};
6969

70+
enum MCIPhoneKeyboardDisplayMode
71+
{
72+
kMCIPhoneKeyboardDisplayModeOver,
73+
kMCIPhoneKeyboardDisplayModePan,
74+
};
75+
7076
@interface MCIPhoneApplication : NSObject <UIApplicationDelegate>
7177
{
7278
// The actual application object (remember this object is only a delegate!).
@@ -132,6 +138,8 @@ enum MCIPhoneApplicationStatus
132138
bool m_pending_launch_url;
133139
// We need to know if the application is active before we can send a message
134140
bool m_did_become_active;
141+
142+
MCIPhoneKeyboardDisplayMode m_keyboard_display;
135143
}
136144

137145
//////////
@@ -227,6 +235,8 @@ enum MCIPhoneApplicationStatus
227235
- (void)configureKeyboardType: (UIKeyboardType)newKeyboardType;
228236
// Configure the type of return key.
229237
- (void)configureReturnKeyType: (UIReturnKeyType)newReturnKeyType;
238+
// Configure the keyboard display.
239+
- (void)configureKeyboardDisplay: (MCIPhoneKeyboardDisplayMode)p_mode;
230240

231241
// Get the set of allowed orientations.
232242
- (uint32_t)allowedOrientations;
@@ -393,6 +403,7 @@ void MCIPhoneSwitchViewToOpenGL(void);
393403
UIKeyboardType MCIPhoneGetKeyboardType(void);
394404
void MCIPhoneSetKeyboardType(UIKeyboardType type);
395405
void MCIPhoneSetReturnKeyType(UIReturnKeyType type);
406+
void MCIPhoneSetKeyboardDisplay(MCIPhoneKeyboardDisplayMode p_mode);
396407
UIInterfaceOrientation MCIPhoneGetOrientation(void);
397408
bool MCIPhoneIsEmbedded(void);
398409
void MCIPhoneBreakWait(void);

0 commit comments

Comments
 (0)