Skip to content

Commit 10956f6

Browse files
committed
- paste support for android
1 parent 35e56d3 commit 10956f6

2 files changed

Lines changed: 136 additions & 9 deletions

File tree

core/pen/source/android/os.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -816,4 +816,45 @@ namespace pen
816816
return PEN_ERR_OK;
817817
}
818818

819+
Str os_get_clipboard_string()
820+
{
821+
auto env = get_jni_env();
822+
if(env)
823+
{
824+
jmethodID method = env->GetMethodID(s_android_context.m_activity_class, "getClipboardString", "()Ljava/lang/String;");
825+
auto result = (jstring)env->CallObjectMethod(s_android_context.m_activity_object, method);
826+
827+
const char* result_cstr = env->GetStringUTFChars(result, nullptr);
828+
Str return_result = result_cstr;
829+
830+
env->ReleaseStringUTFChars(result, result_cstr);
831+
832+
return return_result;
833+
}
834+
835+
return "";
836+
}
837+
838+
void os_clear_clipboard_string()
839+
{
840+
auto env = get_jni_env();
841+
if(env)
842+
{
843+
jmethodID method = env->GetMethodID(s_android_context.m_activity_class, "clearClipboardString", "()V");
844+
env->CallVoidMethod(s_android_context.m_activity_object, method);
845+
}
846+
}
847+
848+
void os_enable_paste_popup(bool enable)
849+
{
850+
auto env = get_jni_env();
851+
if(env)
852+
{
853+
jboolean jenable = enable;
854+
855+
jmethodID method = env->GetMethodID(s_android_context.m_activity_class, "enablePaste", "(Z)V");
856+
env->CallVoidMethod(s_android_context.m_activity_object, method, jenable);
857+
}
858+
}
859+
819860
} // namespace pen

core/template/android/activity/pen_activity.java

Lines changed: 95 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,11 @@
1414
import android.content.Intent;
1515
import android.content.SharedPreferences;
1616
import android.content.res.AssetManager;
17+
import android.content.ClipboardManager;
18+
import android.content.ClipData;
1719

18-
import android.graphics.SurfaceTexture;
1920
import android.graphics.Canvas;
2021

21-
import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
22-
import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
23-
import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
24-
import static android.view.View.SYSTEM_UI_FLAG_LOW_PROFILE;
25-
2622
import android.view.KeyEvent;
2723
import android.view.Surface;
2824
import android.view.SurfaceHolder;
@@ -32,18 +28,22 @@
3228
import android.view.inputmethod.InputMethodManager;
3329
import android.view.WindowManager;
3430
import android.view.inputmethod.EditorInfo;
31+
import android.view.MenuItem;
32+
import android.view.ViewGroup;
3533

3634
import androidx.security.crypto.EncryptedSharedPreferences;
3735
import androidx.security.crypto.MasterKey;
3836

37+
import android.widget.FrameLayout;
38+
import android.widget.PopupMenu;
3939
import android.widget.EditText;
4040
import android.text.InputType;
4141

4242
import org.fmod.FMOD;
4343

4444
// new graphics api agnostic implementation of android surface to support native egl
45-
class SurfaceWrapper extends SurfaceView implements SurfaceHolder.Callback {
46-
45+
class SurfaceWrapper extends SurfaceView implements SurfaceHolder.Callback
46+
{
4747
public static native void surface_created(Surface surface, int window_width, int window_height, int display_width, int display_height, int orientation, long app_ptr);
4848
public static native void surface_changed(int width, int height);
4949
public static native void render(SurfaceWrapper caller);
@@ -147,10 +147,11 @@ public boolean onTouchEvent(MotionEvent event)
147147
break;
148148
}
149149

150-
return true;
150+
return super.onTouchEvent(event);
151151
}
152152
}
153153

154+
154155
public class pen_activity extends Activity {
155156
public static native void register_asset_manager(AssetManager asset_manager);
156157
public static native void set_persistent_data_dir(String persistent_data_dir);
@@ -167,6 +168,54 @@ public class pen_activity extends Activity {
167168
private SharedPreferences m_sharedPrefs;
168169
private boolean m_canUseSharedPrefs;
169170

171+
public String clipboard_string = "";
172+
public boolean paste_enabled = false;
173+
final float[] lastTouch = new float[2];
174+
175+
private void showPastePopup(View parent, int x, int y) {
176+
177+
// Create a temporary anchor view at the touch point
178+
View anchor = new View(parent.getContext());
179+
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(1, 1);
180+
params.leftMargin = x;
181+
params.topMargin = y;
182+
183+
ViewGroup root = (ViewGroup) parent.getRootView();
184+
root.addView(anchor, params);
185+
186+
PopupMenu popup = new PopupMenu(parent.getContext(), anchor);
187+
popup.getMenu().add("Paste");
188+
189+
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
190+
@Override
191+
public boolean onMenuItemClick(MenuItem item) {
192+
193+
ClipboardManager clipboard =
194+
(ClipboardManager) parent.getContext()
195+
.getSystemService(Context.CLIPBOARD_SERVICE);
196+
197+
if (clipboard != null && clipboard.hasPrimaryClip()) {
198+
CharSequence text =
199+
clipboard.getPrimaryClip().getItemAt(0).getText();
200+
if (text != null) {
201+
clipboard_string = text.toString();
202+
}
203+
}
204+
205+
return true;
206+
}
207+
});
208+
209+
popup.setOnDismissListener(new PopupMenu.OnDismissListener() {
210+
@Override
211+
public void onDismiss(PopupMenu menu) {
212+
root.removeView(anchor);
213+
}
214+
});
215+
216+
popup.show();
217+
}
218+
170219
public int getStatusBarHeight() {
171220
int result = 0;
172221
int resourceId = this.getResources().getIdentifier("status_bar_height", "dimen", "android");
@@ -225,6 +274,28 @@ protected void onCreate(Bundle arg0) {
225274
// setup view / surface
226275
m_surfaceView = new SurfaceWrapper(this);
227276

277+
// paste menu on long click
278+
m_surfaceView.setLongClickable(true);
279+
280+
m_surfaceView.setOnTouchListener(new View.OnTouchListener() {
281+
@Override
282+
public boolean onTouch(View v, MotionEvent event) {
283+
if (event.getAction() == MotionEvent.ACTION_DOWN) {
284+
lastTouch[0] = event.getX();
285+
lastTouch[1] = event.getY();
286+
}
287+
return false; // IMPORTANT: do not block long-press detection
288+
}
289+
});
290+
291+
m_surfaceView.setOnLongClickListener(new View.OnLongClickListener() {
292+
@Override
293+
public boolean onLongClick(View v) {
294+
showPastePopup(v, (int)lastTouch[0], (int)lastTouch[1]);
295+
return true;
296+
}
297+
});
298+
228299
DisplayMetrics metrics = new DisplayMetrics();
229300
getWindowManager().getDefaultDisplay().getMetrics(metrics);
230301

@@ -373,4 +444,19 @@ public void triggerVibration()
373444
vibrator.cancel();
374445
vibrator.vibrate(effect);
375446
}
447+
448+
public void enablePaste(boolean enable)
449+
{
450+
paste_enabled = enable;
451+
}
452+
453+
public String getClipboardString()
454+
{
455+
return clipboard_string;
456+
}
457+
458+
void clearClipboardString()
459+
{
460+
clipboard_string = "";
461+
}
376462
}

0 commit comments

Comments
 (0)