/src/compiler/android-ndk/src/org/libftk/app/FtkActivity.java

http://ftk.googlecode.com/ · Java · 892 lines · 428 code · 114 blank · 350 comment · 51 complexity · 81d1541615df6298f6b403b84d61b29b MD5 · raw file

  1. package org.libftk.app;
  2. import java.io.InputStream;
  3. import javax.microedition.khronos.egl.*;
  4. import android.app.*;
  5. import android.content.*;
  6. import android.view.*;
  7. import android.view.inputmethod.BaseInputConnection;
  8. import android.view.inputmethod.CompletionInfo;
  9. import android.view.inputmethod.EditorInfo;
  10. import android.view.inputmethod.ExtractedText;
  11. import android.view.inputmethod.ExtractedTextRequest;
  12. import android.view.inputmethod.InputConnection;
  13. import android.view.inputmethod.InputMethodManager;
  14. import android.os.*;
  15. import android.util.Log;
  16. import android.text.method.*;
  17. import android.text.*;
  18. import android.content.res.AssetFileDescriptor;
  19. import android.content.res.AssetManager;
  20. import android.content.res.Configuration;
  21. import android.graphics.Bitmap;
  22. import android.graphics.BitmapFactory;
  23. import android.graphics.Canvas;
  24. import android.graphics.Rect;
  25. public class FtkActivity extends Activity {
  26. private static final boolean DEBUG = true;
  27. private static final String TAG = "FtkActivity";
  28. private static FtkActivity mActivity;
  29. private static FtkView mView;
  30. private static AssetManager mAssetManager;
  31. public static Thread mThread;
  32. static {
  33. System.loadLibrary("ftkapp");
  34. }
  35. protected void onCreate(Bundle savedInstanceState) {
  36. super.onCreate(savedInstanceState);
  37. mActivity = this;
  38. Window window = getWindow();
  39. window.requestFeature(Window.FEATURE_NO_TITLE);
  40. //requestWindowFeature(Window.FEATURE_NO_TITLE);
  41. window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
  42. mAssetManager = getAssets();
  43. mView = new FtkView(this, getApplication());
  44. setContentView(mView);
  45. SurfaceHolder holder = mView.getHolder();
  46. holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
  47. //ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
  48. //ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
  49. //getRequestedOrientation();
  50. //setRequestedOrientation();
  51. //List<InputMethodInfo> imInfos = imm.getEnabledInputMethodList();
  52. //Iterator<InputMethodInfo> it = imInfos.iterator();
  53. //while (it.hasNext()) {
  54. // InputMethodInfo info = it.next();
  55. // Log.d("FtkActivity", "InputMethod: " + info.getPackageName()
  56. // + ", " + info.loadLabel(getPackageManager()));
  57. //}
  58. }
  59. //Events
  60. protected void onPause()
  61. {
  62. super.onPause();
  63. }
  64. protected void onResume()
  65. {
  66. super.onResume();
  67. }
  68. protected void onStop() {
  69. super.onStop();
  70. if (DEBUG) { Log.d(TAG, "onStop"); }
  71. }
  72. protected void onDestroy() {
  73. super.onDestroy();
  74. if (DEBUG) { Log.d(TAG, "onDestroy"); }
  75. nativeQuit();
  76. try {
  77. mThread.wait();
  78. } catch (Exception e) {
  79. Log.e(TAG, "stopping ftk thread: " + e);
  80. }
  81. mAssetManager.close();
  82. ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
  83. am.restartPackage(getPackageName());
  84. }
  85. public void onConfigurationChanged(Configuration newConfig) {
  86. if (DEBUG) { Log.d(TAG, "onConfigurationChanged"); }
  87. super.onConfigurationChanged(newConfig);
  88. if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
  89. Log.d(TAG, "ORIENTATION_LANDSCAPE");
  90. } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
  91. Log.d(TAG, "ORIENTATION_PORTRAIT");
  92. } else if (newConfig.orientation == Configuration.ORIENTATION_SQUARE) {
  93. Log.d(TAG, "ORIENTATION_SQUARE");
  94. }
  95. }
  96. public static native void nativeInit();
  97. public static native void nativeQuit();
  98. public static native void nativeSetScreenSize(int width, int height);
  99. public static native void nativeEnableRender();
  100. public static native void nativeDisableRender();
  101. public static native void onNativeKey(int action, int keyCode);
  102. public static native void onNativeCommitText(String text, int newCursorPosition);
  103. public static native void onNativeTouch(int action, float x, float y, float p);
  104. public static native void onNativeResize(int x, int y, int format);
  105. // Java functions called from C
  106. public static final AssetFileDescriptor getAssetFileDescriptor(String file) {
  107. if (DEBUG) { Log.d(TAG, "getAssetFileDescriptor: " + file); }
  108. try {
  109. return mAssetManager.openFd(file);
  110. } catch (Exception ex) {
  111. Log.e(TAG, ex.getMessage());
  112. }
  113. return null;
  114. }
  115. public static final Bitmap decodeImage(String file) {
  116. //if (DEBUG) { Log.d(TAG, "decodeImage: " + file); }
  117. InputStream is = null;
  118. try {
  119. is = mAssetManager.open(file);
  120. } catch (Exception ex) {
  121. Log.e(TAG, ex.getMessage());
  122. return null;
  123. }
  124. Bitmap bitmap = BitmapFactory.decodeStream(is);
  125. try {
  126. is.close();
  127. } catch (Exception ex) {
  128. Log.e(TAG, ex.getMessage());
  129. }
  130. is = null;
  131. return bitmap;
  132. }
  133. public static final void initEGL() {
  134. mView.initEGL();
  135. }
  136. public static final void createEGLSurface() {
  137. mView.createEGLSurface();
  138. }
  139. public static final void destroyEGLSurface() {
  140. mView.destroyEGLSurface();
  141. }
  142. public static final void flipEGL() {
  143. mView.flipEGL();
  144. }
  145. public static final void drawBitmap(int[] colors, int offset, int stride, int x, int y, int width, int height) {
  146. mView.drawBitmap(colors, offset, stride, x, y, width, height);
  147. }
  148. public static final void showKeyboard() {
  149. InputMethodManager imm = (InputMethodManager) mActivity.getSystemService(INPUT_METHOD_SERVICE);
  150. imm.showSoftInput(mView, 0);
  151. }
  152. public static final void hideKeyboard() {
  153. InputMethodManager imm = (InputMethodManager) mActivity.getSystemService(INPUT_METHOD_SERVICE);
  154. imm.hideSoftInputFromWindow(mView.getWindowToken(), 0);
  155. }
  156. public static final void showInputMethodPicker() {
  157. InputMethodManager imm = (InputMethodManager) mActivity.getSystemService(INPUT_METHOD_SERVICE);
  158. //imm.hideSoftInputFromWindow(mView.getWindowToken(), 0);
  159. imm.showInputMethodPicker();
  160. }
  161. }
  162. class FtkRunner implements Runnable {
  163. private static final boolean DEBUG = true;
  164. private static final String TAG = "FtkRunner";
  165. private FtkActivity mActivity;
  166. public FtkRunner(FtkActivity activity) {
  167. super();
  168. mActivity = activity;
  169. }
  170. public void run() {
  171. if (DEBUG) { Log.d(TAG, "thread run"); }
  172. FtkActivity.nativeInit();
  173. if (DEBUG) { Log.v(TAG, "thread exit"); }
  174. mActivity.finish();
  175. }
  176. }
  177. class FtkInputConnection extends BaseInputConnection {
  178. private static final boolean DEBUG = true;
  179. private static final String TAG = "FtkInputConnection";
  180. private final FtkView mView;
  181. public FtkInputConnection(FtkView view) {
  182. super(view, true);
  183. mView = view;
  184. }
  185. public Editable getEditable() {
  186. FtkView v = mView;
  187. if (v != null) {
  188. return v.getEditableText();
  189. }
  190. return null;
  191. }
  192. public boolean beginBatchEdit() {
  193. mView.beginBatchEdit();
  194. return true;
  195. }
  196. public boolean endBatchEdit() {
  197. mView.endBatchEdit();
  198. return true;
  199. }
  200. public boolean clearMetaKeyStates(int states) {
  201. final Editable content = getEditable();
  202. if (content == null) return false;
  203. KeyListener kl = mView.getKeyListener();
  204. if (kl != null) {
  205. try {
  206. kl.clearMetaKeyState(mView, content, states);
  207. } catch (AbstractMethodError e) {
  208. // This is an old listener that doesn't implement the
  209. // new method.
  210. }
  211. }
  212. return true;
  213. }
  214. public boolean commitCompletion(CompletionInfo text) {
  215. if (DEBUG) Log.v(TAG, "commitCompletion " + text);
  216. mView.beginBatchEdit();
  217. mView.onCommitCompletion(text);
  218. mView.endBatchEdit();
  219. return true;
  220. }
  221. public boolean performEditorAction(int actionCode) {
  222. if (DEBUG) Log.v(TAG, "performEditorAction " + actionCode);
  223. mView.onEditorAction(actionCode);
  224. return true;
  225. }
  226. public boolean performContextMenuAction(int id) {
  227. if (DEBUG) Log.v(TAG, "performContextMenuAction " + id);
  228. mView.beginBatchEdit();
  229. mView.onTextContextMenuItem(id);
  230. mView.endBatchEdit();
  231. return true;
  232. }
  233. public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
  234. if (mView != null) {
  235. ExtractedText et = new ExtractedText();
  236. if (mView.extractText(request, et)) {
  237. if ((flags&GET_EXTRACTED_TEXT_MONITOR) != 0) {
  238. mView.setExtracting(request);
  239. }
  240. return et;
  241. }
  242. }
  243. return null;
  244. }
  245. public boolean performPrivateCommand(String action, Bundle data) {
  246. mView.onPrivateIMECommand(action, data);
  247. return true;
  248. }
  249. @Override
  250. public boolean commitText(CharSequence text, int newCursorPosition) {
  251. if (DEBUG) Log.v(TAG, "commitText " + text);
  252. if (mView == null) {
  253. return super.commitText(text, newCursorPosition);
  254. }
  255. FtkActivity.onNativeCommitText(String.valueOf(text), newCursorPosition);
  256. boolean success = super.commitText(text, newCursorPosition);
  257. return success;
  258. }
  259. }
  260. class FtkView extends SurfaceView implements SurfaceHolder.Callback, View.OnKeyListener, View.OnTouchListener {
  261. private static final boolean DEBUG = true;
  262. private static final String TAG = "FtkView";
  263. private FtkActivity mActivity;
  264. private boolean mSurfaceValid = false;
  265. private EGLDisplay mEGLDisplay;
  266. private EGLConfig mEGLConfig;
  267. private EGLContext mEGLContext;
  268. private EGLSurface mEGLSurface;
  269. public FtkView(FtkActivity activity, Context context) {
  270. super(context);
  271. mActivity = activity;
  272. SurfaceHolder holder = getHolder();
  273. holder.addCallback(this);
  274. setFocusable(true);
  275. setFocusableInTouchMode(true);
  276. requestFocus();
  277. setOnKeyListener(this);
  278. setOnTouchListener(this);
  279. mText = "";
  280. }
  281. public void surfaceCreated(SurfaceHolder holder) {
  282. if (DEBUG) { Log.v(TAG, "surfaceCreated"); }
  283. if (FtkActivity.mThread != null) {
  284. mSurfaceValid = true;
  285. FtkActivity.nativeEnableRender();
  286. return;
  287. }
  288. int width = getWidth();
  289. int height = getHeight();
  290. FtkActivity.nativeSetScreenSize(width, height);
  291. FtkActivity.mThread = new Thread(new FtkRunner(mActivity), "ftk thread");
  292. FtkActivity.mThread.start();
  293. mSurfaceValid = true;
  294. FtkActivity.nativeEnableRender();
  295. }
  296. public void surfaceDestroyed(SurfaceHolder holder) {
  297. if (DEBUG) { Log.v(TAG, "surfaceDestroyed"); }
  298. mSurfaceValid = false;
  299. FtkActivity.nativeDisableRender();
  300. }
  301. public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
  302. if (DEBUG) { Log.d(TAG, "surfaceChanged"); }
  303. FtkActivity.onNativeResize(width, height, format);
  304. }
  305. // EGL functions
  306. public boolean initEGL() {
  307. if (DEBUG) { Log.d(TAG, "initEGL"); }
  308. try {
  309. EGL10 egl = (EGL10)EGLContext.getEGL();
  310. EGLDisplay dpy = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
  311. int[] version = new int[2];
  312. egl.eglInitialize(dpy, version);
  313. int[] configSpec = {
  314. EGL10.EGL_RED_SIZE, 5,
  315. EGL10.EGL_GREEN_SIZE, 6,
  316. EGL10.EGL_BLUE_SIZE, 5,
  317. EGL10.EGL_ALPHA_SIZE, EGL10.EGL_DONT_CARE,
  318. EGL10.EGL_DEPTH_SIZE, 16,
  319. EGL10.EGL_STENCIL_SIZE, EGL10.EGL_DONT_CARE,
  320. EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT,
  321. EGL10.EGL_NONE
  322. };
  323. EGLConfig[] configs = new EGLConfig[1];
  324. int[] num_config = new int[1];
  325. egl.eglChooseConfig(dpy, configSpec, configs, 1, num_config);
  326. EGLConfig config = configs[0];
  327. EGLContext ctx = egl.eglCreateContext(dpy, config, EGL10.EGL_NO_CONTEXT, null);
  328. mEGLDisplay = dpy;
  329. mEGLConfig = config;
  330. mEGLContext = ctx;
  331. } catch (Exception e) {
  332. Log.e(TAG, e + "");
  333. for(StackTraceElement s : e.getStackTrace()) {
  334. Log.e(TAG, s.toString());
  335. }
  336. }
  337. return true;
  338. }
  339. public void createEGLSurface() {
  340. if (DEBUG) { Log.d(TAG, "createEGLSurface"); }
  341. EGL10 egl = (EGL10)EGLContext.getEGL();
  342. //if (mEGLSurface != null) {
  343. // xxx
  344. //}
  345. EGLSurface surface = egl.eglCreateWindowSurface(mEGLDisplay, mEGLConfig, this, null);
  346. egl.eglMakeCurrent(mEGLDisplay, surface, surface, mEGLContext);
  347. mEGLSurface = surface;
  348. }
  349. public void destroyEGLSurface() {
  350. if (DEBUG) { Log.d(TAG, "destroyEGLSurface"); }
  351. //EGL10 egl = (EGL10)EGLContext.getEGL();
  352. if (mEGLSurface != null) {
  353. //egl.eglMakeCurrent(mEGLDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, mEGLContext);
  354. //egl.eglDestroySurface(mEGLDisplay, mEGLSurface);
  355. mEGLSurface = null;
  356. }
  357. }
  358. public void flipEGL() {
  359. if (!mSurfaceValid) {
  360. return;
  361. }
  362. try {
  363. EGL10 egl = (EGL10)EGLContext.getEGL();
  364. egl.eglWaitNative(EGL10.EGL_NATIVE_RENDERABLE, null);
  365. egl.eglWaitGL();
  366. egl.eglSwapBuffers(mEGLDisplay, mEGLSurface);
  367. } catch(Exception e) {
  368. Log.v("FTK", "flipEGL(): " + e);
  369. for(StackTraceElement s : e.getStackTrace()){
  370. Log.v("FTK", s.toString());
  371. }
  372. }
  373. }
  374. public void drawBitmap(int[] colors, int offset, int stride, int x, int y, int width, int height) {
  375. //if (DEBUG) { Log.d(TAG, "drawBitmap: " + x + "-" + y + " " + width + "-" + height); }
  376. SurfaceHolder holder = getHolder();
  377. if (holder == null) {
  378. return;
  379. }
  380. Rect rect = new Rect(x, y, x + width, y + height);
  381. Canvas canvas = holder.lockCanvas(rect);
  382. if (canvas == null) {
  383. return;
  384. }
  385. canvas.drawBitmap(colors, offset, stride, x, y, width, height, true, null);
  386. holder.unlockCanvasAndPost(canvas);
  387. }
  388. public boolean onKey(View v, int keyCode, KeyEvent event){
  389. FtkActivity.onNativeKey(event.getAction(), keyCode);
  390. return true;
  391. }
  392. public boolean onTouch(View v, MotionEvent event){
  393. FtkActivity.onNativeTouch(event.getAction(), event.getX(), event.getY(), event.getPressure());
  394. return true;
  395. }
  396. // input method
  397. /**
  398. * Interface definition for a callback to be invoked when an action is
  399. * performed on the editor.
  400. */
  401. public interface OnEditorActionListener {
  402. /**
  403. * Called when an action is being performed.
  404. *
  405. * @param v The view that was clicked.
  406. * @param actionId Identifier of the action. This will be either the
  407. * identifier you supplied, or {@link EditorInfo#IME_NULL
  408. * EditorInfo.IME_NULL} if being called due to the enter key
  409. * being pressed.
  410. * @param event If triggered by an enter key, this is the event;
  411. * otherwise, this is null.
  412. * @return Return true if you have consumed the action, else false.
  413. */
  414. boolean onEditorAction(FtkView v, int actionId, KeyEvent event);
  415. }
  416. class InputContentType {
  417. int imeOptions = EditorInfo.IME_NULL;
  418. String privateImeOptions;
  419. CharSequence imeActionLabel;
  420. int imeActionId;
  421. Bundle extras;
  422. OnEditorActionListener onEditorActionListener;
  423. boolean enterDown;
  424. }
  425. InputContentType mInputContentType;
  426. @Override public boolean onCheckIsTextEditor() {
  427. return true;
  428. }
  429. @Override public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
  430. return new FtkInputConnection(this);
  431. }
  432. /**
  433. * Called when an attached input method calls
  434. * {@link InputConnection#performEditorAction(int)
  435. * InputConnection.performEditorAction()}
  436. * for this text view. The default implementation will call your action
  437. * listener supplied to {@link #setOnEditorActionListener}, or perform
  438. * a standard operation for {@link EditorInfo#IME_ACTION_NEXT
  439. * EditorInfo.IME_ACTION_NEXT} or {@link EditorInfo#IME_ACTION_DONE
  440. * EditorInfo.IME_ACTION_DONE}.
  441. *
  442. * <p>For backwards compatibility, if no IME options have been set and the
  443. * text view would not normally advance focus on enter, then
  444. * the NEXT and DONE actions received here will be turned into an enter
  445. * key down/up pair to go through the normal key handling.
  446. *
  447. * @param actionCode The code of the action being performed.
  448. *
  449. * @see #setOnEditorActionListener
  450. */
  451. public void onEditorAction(int actionCode) {
  452. /*final InputContentType ict = mInputContentType;
  453. if (ict != null) {
  454. if (ict.onEditorActionListener != null) {
  455. if (ict.onEditorActionListener.onEditorAction(this,
  456. actionCode, null)) {
  457. return;
  458. }
  459. }
  460. // This is the handling for some default action.
  461. // Note that for backwards compatibility we don't do this
  462. // default handling if explicit ime options have not been given,
  463. // instead turning this into the normal enter key codes that an
  464. // app may be expecting.
  465. if (actionCode == EditorInfo.IME_ACTION_NEXT) {
  466. View v = focusSearch(FOCUS_DOWN);
  467. if (v != null) {
  468. if (!v.requestFocus(FOCUS_DOWN)) {
  469. throw new IllegalStateException("focus search returned a view " +
  470. "that wasn't able to take focus!");
  471. }
  472. }
  473. return;
  474. } else if (actionCode == EditorInfo.IME_ACTION_DONE) {
  475. FtkActivity activity = FtkActivity.mSingleton;
  476. InputMethodManager imm = (InputMethodManager) activity.getSystemService(FtkActivity.INPUT_METHOD_SERVICE);
  477. if (imm != null) {
  478. imm.hideSoftInputFromWindow(getWindowToken(), 0);
  479. }
  480. return;
  481. }
  482. }
  483. Handler h = getHandler();
  484. if (h != null) {
  485. long eventTime = SystemClock.uptimeMillis();
  486. h.sendMessage(h.obtainMessage(ViewRoot.DISPATCH_KEY_FROM_IME,
  487. new KeyEvent(eventTime, eventTime,
  488. KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER, 0, 0, 0, 0,
  489. KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE
  490. | KeyEvent.FLAG_EDITOR_ACTION)));
  491. h.sendMessage(h.obtainMessage(ViewRoot.DISPATCH_KEY_FROM_IME,
  492. new KeyEvent(SystemClock.uptimeMillis(), eventTime,
  493. KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER, 0, 0, 0, 0,
  494. KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE
  495. | KeyEvent.FLAG_EDITOR_ACTION)));
  496. }*/
  497. }
  498. /**
  499. * If this TextView contains editable content, extract a portion of it
  500. * based on the information in <var>request</var> in to <var>outText</var>.
  501. * @return Returns true if the text was successfully extracted, else false.
  502. */
  503. public boolean extractText(ExtractedTextRequest request,
  504. ExtractedText outText) {
  505. return extractTextInternal(request, EXTRACT_UNKNOWN, EXTRACT_UNKNOWN,
  506. EXTRACT_UNKNOWN, outText);
  507. }
  508. static final int EXTRACT_NOTHING = -2;
  509. static final int EXTRACT_UNKNOWN = -1;
  510. boolean extractTextInternal(ExtractedTextRequest request,
  511. int partialStartOffset, int partialEndOffset, int delta,
  512. ExtractedText outText) {
  513. /*final CharSequence content = mText;
  514. if (content != null) {
  515. if (partialStartOffset != EXTRACT_NOTHING) {
  516. final int N = content.length();
  517. if (partialStartOffset < 0) {
  518. outText.partialStartOffset = outText.partialEndOffset = -1;
  519. partialStartOffset = 0;
  520. partialEndOffset = N;
  521. } else {
  522. // Now use the delta to determine the actual amount of text
  523. // we need.
  524. partialEndOffset += delta;
  525. // Adjust offsets to ensure we contain full spans.
  526. if (content instanceof Spanned) {
  527. Spanned spanned = (Spanned)content;
  528. Object[] spans = spanned.getSpans(partialStartOffset,
  529. partialEndOffset, ParcelableSpan.class);
  530. int i = spans.length;
  531. while (i > 0) {
  532. i--;
  533. int j = spanned.getSpanStart(spans[i]);
  534. if (j < partialStartOffset) partialStartOffset = j;
  535. j = spanned.getSpanEnd(spans[i]);
  536. if (j > partialEndOffset) partialEndOffset = j;
  537. }
  538. }
  539. outText.partialStartOffset = partialStartOffset;
  540. outText.partialEndOffset = partialEndOffset - delta;
  541. if (partialStartOffset > N) {
  542. partialStartOffset = N;
  543. } else if (partialStartOffset < 0) {
  544. partialStartOffset = 0;
  545. }
  546. if (partialEndOffset > N) {
  547. partialEndOffset = N;
  548. } else if (partialEndOffset < 0) {
  549. partialEndOffset = 0;
  550. }
  551. }
  552. if ((request.flags&InputConnection.GET_TEXT_WITH_STYLES) != 0) {
  553. outText.text = content.subSequence(partialStartOffset,
  554. partialEndOffset);
  555. } else {
  556. outText.text = TextUtils.substring(content, partialStartOffset,
  557. partialEndOffset);
  558. }
  559. } else {
  560. outText.partialStartOffset = 0;
  561. outText.partialEndOffset = 0;
  562. outText.text = "";
  563. }
  564. outText.flags = 0;
  565. if (MetaKeyKeyListener.getMetaState(mText, MetaKeyKeyListener.META_SELECTING) != 0) {
  566. outText.flags |= ExtractedText.FLAG_SELECTING;
  567. }
  568. if (mSingleLine) {
  569. outText.flags |= ExtractedText.FLAG_SINGLE_LINE;
  570. }
  571. outText.startOffset = 0;
  572. outText.selectionStart = Selection.getSelectionStart(content);
  573. outText.selectionEnd = Selection.getSelectionEnd(content);
  574. return true;
  575. }*/
  576. return false;
  577. }
  578. /**
  579. * @hide
  580. */
  581. public void setExtracting(ExtractedTextRequest req) {
  582. /*if (mInputMethodState != null) {
  583. mInputMethodState.mExtracting = req;
  584. }*/
  585. }
  586. /**
  587. * Called by the framework in response to a private command from the
  588. * current method, provided by it calling
  589. * {@link InputConnection#performPrivateCommand
  590. * InputConnection.performPrivateCommand()}.
  591. *
  592. * @param action The action name of the command.
  593. * @param data Any additional data for the command. This may be null.
  594. * @return Return true if you handled the command, else false.
  595. */
  596. public boolean onPrivateIMECommand(String action, Bundle data) {
  597. return false;
  598. }
  599. /**
  600. * Return the text the TextView is displaying as an Editable object. If
  601. * the text is not editable, null is returned.
  602. *
  603. * @see #getText
  604. */
  605. public Editable getEditableText() {
  606. return (mText instanceof Editable) ? (Editable)mText : null;
  607. }
  608. /**
  609. * Called by the framework in response to a text completion from
  610. * the current input method, provided by it calling
  611. * {@link InputConnection#commitCompletion
  612. * InputConnection.commitCompletion()}. The default implementation does
  613. * nothing; text views that are supporting auto-completion should override
  614. * this to do their desired behavior.
  615. *
  616. * @param text The auto complete text the user has selected.
  617. */
  618. public void onCommitCompletion(CompletionInfo text) {
  619. if (DEBUG) Log.v(TAG, "onCommitCompletion " + text.getText());
  620. }
  621. /**
  622. * Called when a context menu option for the text view is selected. Currently
  623. * this will be one of: {@link android.R.id#selectAll},
  624. * {@link android.R.id#startSelectingText}, {@link android.R.id#stopSelectingText},
  625. * {@link android.R.id#cut}, {@link android.R.id#copy},
  626. * {@link android.R.id#paste}, {@link android.R.id#copyUrl},
  627. * or {@link android.R.id#switchInputMethod}.
  628. */
  629. public boolean onTextContextMenuItem(int id) {
  630. /*int selStart = getSelectionStart();
  631. int selEnd = getSelectionEnd();
  632. if (!isFocused()) {
  633. selStart = 0;
  634. selEnd = mText.length();
  635. }
  636. int min = Math.min(selStart, selEnd);
  637. int max = Math.max(selStart, selEnd);
  638. if (min < 0) {
  639. min = 0;
  640. }
  641. if (max < 0) {
  642. max = 0;
  643. }
  644. ClipboardManager clip = (ClipboardManager)getContext()
  645. .getSystemService(Context.CLIPBOARD_SERVICE);
  646. switch (id) {
  647. case ID_SELECT_ALL:
  648. Selection.setSelection((Spannable) mText, 0,
  649. mText.length());
  650. return true;
  651. case ID_START_SELECTING_TEXT:
  652. MetaKeyKeyListener.startSelecting(this, (Spannable) mText);
  653. return true;
  654. case ID_STOP_SELECTING_TEXT:
  655. MetaKeyKeyListener.stopSelecting(this, (Spannable) mText);
  656. Selection.setSelection((Spannable) mText, getSelectionEnd());
  657. return true;
  658. case ID_CUT:
  659. MetaKeyKeyListener.stopSelecting(this, (Spannable) mText);
  660. if (min == max) {
  661. min = 0;
  662. max = mText.length();
  663. }
  664. clip.setText(mTransformed.subSequence(min, max));
  665. ((Editable) mText).delete(min, max);
  666. return true;
  667. case ID_COPY:
  668. MetaKeyKeyListener.stopSelecting(this, (Spannable) mText);
  669. if (min == max) {
  670. min = 0;
  671. max = mText.length();
  672. }
  673. clip.setText(mTransformed.subSequence(min, max));
  674. return true;
  675. case ID_PASTE:
  676. MetaKeyKeyListener.stopSelecting(this, (Spannable) mText);
  677. CharSequence paste = clip.getText();
  678. if (paste != null) {
  679. Selection.setSelection((Spannable) mText, max);
  680. ((Editable) mText).replace(min, max, paste);
  681. }
  682. return true;
  683. case ID_COPY_URL:
  684. MetaKeyKeyListener.stopSelecting(this, (Spannable) mText);
  685. URLSpan[] urls = ((Spanned) mText).getSpans(min, max,
  686. URLSpan.class);
  687. if (urls.length == 1) {
  688. clip.setText(urls[0].getURL());
  689. }
  690. return true;
  691. case ID_SWITCH_INPUT_METHOD:
  692. InputMethodManager imm = InputMethodManager.peekInstance();
  693. if (imm != null) {
  694. imm.showInputMethodPicker();
  695. }
  696. return true;
  697. case ID_ADD_TO_DICTIONARY:
  698. String word = getWordForDictionary();
  699. if (word != null) {
  700. Intent i = new Intent("com.android.settings.USER_DICTIONARY_INSERT");
  701. i.putExtra("word", word);
  702. i.setFlags(i.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
  703. getContext().startActivity(i);
  704. }
  705. return true;
  706. }*/
  707. return false;
  708. }
  709. public void beginBatchEdit() {
  710. if (DEBUG) Log.v(TAG, "beginBatchEdit");
  711. /*final InputMethodState ims = mInputMethodState;
  712. if (ims != null) {
  713. int nesting = ++ims.mBatchEditNesting;
  714. if (nesting == 1) {
  715. ims.mCursorChanged = false;
  716. ims.mChangedDelta = 0;
  717. if (ims.mContentChanged) {
  718. // We already have a pending change from somewhere else,
  719. // so turn this into a full update.
  720. ims.mChangedStart = 0;
  721. ims.mChangedEnd = mText.length();
  722. } else {
  723. ims.mChangedStart = EXTRACT_UNKNOWN;
  724. ims.mChangedEnd = EXTRACT_UNKNOWN;
  725. ims.mContentChanged = false;
  726. }
  727. onBeginBatchEdit();
  728. }
  729. }*/
  730. }
  731. public void endBatchEdit() {
  732. if (DEBUG) Log.v(TAG, "endBatchEdit");
  733. /*final InputMethodState ims = mInputMethodState;
  734. if (ims != null) {
  735. int nesting = --ims.mBatchEditNesting;
  736. if (nesting == 0) {
  737. finishBatchEdit(ims);
  738. }
  739. }*/
  740. }
  741. /**
  742. * @return the current key listener for this TextView.
  743. * This will frequently be null for non-EditText TextViews.
  744. */
  745. public final KeyListener getKeyListener() {
  746. return mInput;
  747. }
  748. private CharSequence mText;
  749. private KeyListener mInput;
  750. }