1 /* 2 * Copyright (C) 2007-2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 17 package android.inputmethodservice; 18 19 import android.app.Dialog; 20 import android.content.Context; 21 import android.graphics.Rect; 22 import android.os.IBinder; 23 import android.view.Gravity; 24 import android.view.KeyEvent; 25 import android.view.MotionEvent; 26 import android.view.WindowManager; 27 28 /** 29 * A SoftInputWindow is a Dialog that is intended to be used for a top-level input 30 * method window. It will be displayed along the edge of the screen, moving 31 * the application user interface away from it so that the focused item is 32 * always visible. 33 * @hide 34 */ 35 public class SoftInputWindow extends Dialog { 36 final String mName; 37 final Callback mCallback; 38 final KeyEvent.Callback mKeyEventCallback; 39 final KeyEvent.DispatcherState mDispatcherState; 40 final int mWindowType; 41 final int mGravity; 42 final boolean mTakesFocus; 43 private final Rect mBounds = new Rect(); 44 45 public interface Callback { onBackPressed()46 public void onBackPressed(); 47 } 48 setToken(IBinder token)49 public void setToken(IBinder token) { 50 WindowManager.LayoutParams lp = getWindow().getAttributes(); 51 lp.token = token; 52 getWindow().setAttributes(lp); 53 } 54 55 /** 56 * Create a SoftInputWindow that uses a custom style. 57 * 58 * @param context The Context in which the DockWindow should run. In 59 * particular, it uses the window manager and theme from this context 60 * to present its UI. 61 * @param theme A style resource describing the theme to use for the window. 62 * See <a href="{@docRoot}reference/available-resources.html#stylesandthemes">Style 63 * and Theme Resources</a> for more information about defining and 64 * using styles. This theme is applied on top of the current theme in 65 * <var>context</var>. If 0, the default dialog theme will be used. 66 */ SoftInputWindow(Context context, String name, int theme, Callback callback, KeyEvent.Callback keyEventCallback, KeyEvent.DispatcherState dispatcherState, int windowType, int gravity, boolean takesFocus)67 public SoftInputWindow(Context context, String name, int theme, Callback callback, 68 KeyEvent.Callback keyEventCallback, KeyEvent.DispatcherState dispatcherState, 69 int windowType, int gravity, boolean takesFocus) { 70 super(context, theme); 71 mName = name; 72 mCallback = callback; 73 mKeyEventCallback = keyEventCallback; 74 mDispatcherState = dispatcherState; 75 mWindowType = windowType; 76 mGravity = gravity; 77 mTakesFocus = takesFocus; 78 initDockWindow(); 79 } 80 81 @Override onWindowFocusChanged(boolean hasFocus)82 public void onWindowFocusChanged(boolean hasFocus) { 83 super.onWindowFocusChanged(hasFocus); 84 mDispatcherState.reset(); 85 } 86 87 @Override dispatchTouchEvent(MotionEvent ev)88 public boolean dispatchTouchEvent(MotionEvent ev) { 89 getWindow().getDecorView().getHitRect(mBounds); 90 91 if (ev.isWithinBoundsNoHistory(mBounds.left, mBounds.top, 92 mBounds.right - 1, mBounds.bottom - 1)) { 93 return super.dispatchTouchEvent(ev); 94 } else { 95 MotionEvent temp = ev.clampNoHistory(mBounds.left, mBounds.top, 96 mBounds.right - 1, mBounds.bottom - 1); 97 boolean handled = super.dispatchTouchEvent(temp); 98 temp.recycle(); 99 return handled; 100 } 101 } 102 103 /** 104 * Set which boundary of the screen the DockWindow sticks to. 105 * 106 * @param gravity The boundary of the screen to stick. See {#link 107 * android.view.Gravity.LEFT}, {#link android.view.Gravity.TOP}, 108 * {#link android.view.Gravity.BOTTOM}, {#link 109 * android.view.Gravity.RIGHT}. 110 */ setGravity(int gravity)111 public void setGravity(int gravity) { 112 WindowManager.LayoutParams lp = getWindow().getAttributes(); 113 lp.gravity = gravity; 114 updateWidthHeight(lp); 115 getWindow().setAttributes(lp); 116 } 117 getGravity()118 public int getGravity() { 119 return getWindow().getAttributes().gravity; 120 } 121 updateWidthHeight(WindowManager.LayoutParams lp)122 private void updateWidthHeight(WindowManager.LayoutParams lp) { 123 if (lp.gravity == Gravity.TOP || lp.gravity == Gravity.BOTTOM) { 124 lp.width = WindowManager.LayoutParams.MATCH_PARENT; 125 lp.height = WindowManager.LayoutParams.WRAP_CONTENT; 126 } else { 127 lp.width = WindowManager.LayoutParams.WRAP_CONTENT; 128 lp.height = WindowManager.LayoutParams.MATCH_PARENT; 129 } 130 } 131 onKeyDown(int keyCode, KeyEvent event)132 public boolean onKeyDown(int keyCode, KeyEvent event) { 133 if (mKeyEventCallback != null && mKeyEventCallback.onKeyDown(keyCode, event)) { 134 return true; 135 } 136 return super.onKeyDown(keyCode, event); 137 } 138 onKeyLongPress(int keyCode, KeyEvent event)139 public boolean onKeyLongPress(int keyCode, KeyEvent event) { 140 if (mKeyEventCallback != null && mKeyEventCallback.onKeyLongPress(keyCode, event)) { 141 return true; 142 } 143 return super.onKeyLongPress(keyCode, event); 144 } 145 onKeyUp(int keyCode, KeyEvent event)146 public boolean onKeyUp(int keyCode, KeyEvent event) { 147 if (mKeyEventCallback != null && mKeyEventCallback.onKeyUp(keyCode, event)) { 148 return true; 149 } 150 return super.onKeyUp(keyCode, event); 151 } 152 onKeyMultiple(int keyCode, int count, KeyEvent event)153 public boolean onKeyMultiple(int keyCode, int count, KeyEvent event) { 154 if (mKeyEventCallback != null && mKeyEventCallback.onKeyMultiple(keyCode, count, event)) { 155 return true; 156 } 157 return super.onKeyMultiple(keyCode, count, event); 158 } 159 onBackPressed()160 public void onBackPressed() { 161 if (mCallback != null) { 162 mCallback.onBackPressed(); 163 } else { 164 super.onBackPressed(); 165 } 166 } 167 initDockWindow()168 private void initDockWindow() { 169 WindowManager.LayoutParams lp = getWindow().getAttributes(); 170 171 lp.type = mWindowType; 172 lp.setTitle(mName); 173 174 lp.gravity = mGravity; 175 updateWidthHeight(lp); 176 177 getWindow().setAttributes(lp); 178 179 int windowSetFlags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; 180 int windowModFlags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | 181 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | 182 WindowManager.LayoutParams.FLAG_DIM_BEHIND; 183 184 if (!mTakesFocus) { 185 windowSetFlags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 186 } else { 187 windowSetFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; 188 windowModFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; 189 } 190 191 getWindow().setFlags(windowSetFlags, windowModFlags); 192 } 193 } 194