Home | History | Annotate | Download | only in inputmethodservice
      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  */
     34 class SoftInputWindow extends Dialog {
     35     final KeyEvent.DispatcherState mDispatcherState;
     36     private final Rect mBounds = new Rect();
     37 
     38     public void setToken(IBinder token) {
     39         WindowManager.LayoutParams lp = getWindow().getAttributes();
     40         lp.token = token;
     41         getWindow().setAttributes(lp);
     42     }
     43 
     44     /**
     45      * Create a SoftInputWindow that uses a custom style.
     46      *
     47      * @param context The Context in which the DockWindow should run. In
     48      *        particular, it uses the window manager and theme from this context
     49      *        to present its UI.
     50      * @param theme A style resource describing the theme to use for the window.
     51      *        See <a href="{@docRoot}reference/available-resources.html#stylesandthemes">Style
     52      *        and Theme Resources</a> for more information about defining and
     53      *        using styles. This theme is applied on top of the current theme in
     54      *        <var>context</var>. If 0, the default dialog theme will be used.
     55      */
     56     public SoftInputWindow(Context context, int theme,
     57             KeyEvent.DispatcherState dispatcherState) {
     58         super(context, theme);
     59         mDispatcherState = dispatcherState;
     60         initDockWindow();
     61     }
     62 
     63     @Override
     64     public void onWindowFocusChanged(boolean hasFocus) {
     65         super.onWindowFocusChanged(hasFocus);
     66         mDispatcherState.reset();
     67     }
     68 
     69     @Override
     70     public boolean dispatchTouchEvent(MotionEvent ev) {
     71         getWindow().getDecorView().getHitRect(mBounds);
     72 
     73         if (ev.isWithinBoundsNoHistory(mBounds.left, mBounds.top,
     74                 mBounds.right - 1, mBounds.bottom - 1)) {
     75             return super.dispatchTouchEvent(ev);
     76         } else {
     77             MotionEvent temp = ev.clampNoHistory(mBounds.left, mBounds.top,
     78                     mBounds.right - 1, mBounds.bottom - 1);
     79             boolean handled = super.dispatchTouchEvent(temp);
     80             temp.recycle();
     81             return handled;
     82         }
     83     }
     84 
     85     /**
     86      * Get the size of the DockWindow.
     87      *
     88      * @return If the DockWindow sticks to the top or bottom of the screen, the
     89      *         return value is the height of the DockWindow, and its width is
     90      *         equal to the width of the screen; If the DockWindow sticks to the
     91      *         left or right of the screen, the return value is the width of the
     92      *         DockWindow, and its height is equal to the height of the screen.
     93      */
     94     public int getSize() {
     95         WindowManager.LayoutParams lp = getWindow().getAttributes();
     96 
     97         if (lp.gravity == Gravity.TOP || lp.gravity == Gravity.BOTTOM) {
     98             return lp.height;
     99         } else {
    100             return lp.width;
    101         }
    102     }
    103 
    104     /**
    105      * Set the size of the DockWindow.
    106      *
    107      * @param size If the DockWindow sticks to the top or bottom of the screen,
    108      *        <var>size</var> is the height of the DockWindow, and its width is
    109      *        equal to the width of the screen; If the DockWindow sticks to the
    110      *        left or right of the screen, <var>size</var> is the width of the
    111      *        DockWindow, and its height is equal to the height of the screen.
    112      */
    113     public void setSize(int size) {
    114         WindowManager.LayoutParams lp = getWindow().getAttributes();
    115 
    116         if (lp.gravity == Gravity.TOP || lp.gravity == Gravity.BOTTOM) {
    117             lp.width = -1;
    118             lp.height = size;
    119         } else {
    120             lp.width = size;
    121             lp.height = -1;
    122         }
    123         getWindow().setAttributes(lp);
    124     }
    125 
    126     /**
    127      * Set which boundary of the screen the DockWindow sticks to.
    128      *
    129      * @param gravity The boundary of the screen to stick. See {#link
    130      *        android.view.Gravity.LEFT}, {#link android.view.Gravity.TOP},
    131      *        {#link android.view.Gravity.BOTTOM}, {#link
    132      *        android.view.Gravity.RIGHT}.
    133      */
    134     public void setGravity(int gravity) {
    135         WindowManager.LayoutParams lp = getWindow().getAttributes();
    136 
    137         boolean oldIsVertical = (lp.gravity == Gravity.TOP || lp.gravity == Gravity.BOTTOM);
    138 
    139         lp.gravity = gravity;
    140 
    141         boolean newIsVertical = (lp.gravity == Gravity.TOP || lp.gravity == Gravity.BOTTOM);
    142 
    143         if (oldIsVertical != newIsVertical) {
    144             int tmp = lp.width;
    145             lp.width = lp.height;
    146             lp.height = tmp;
    147             getWindow().setAttributes(lp);
    148         }
    149     }
    150 
    151     private void initDockWindow() {
    152         WindowManager.LayoutParams lp = getWindow().getAttributes();
    153 
    154         lp.type = WindowManager.LayoutParams.TYPE_INPUT_METHOD;
    155         lp.setTitle("InputMethod");
    156 
    157         lp.gravity = Gravity.BOTTOM;
    158         lp.width = -1;
    159         // Let the input method window's orientation follow sensor based rotation
    160         // Turn this off for now, it is very problematic.
    161         //lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
    162 
    163         getWindow().setAttributes(lp);
    164         getWindow().setFlags(
    165                 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
    166                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
    167                 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
    168                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
    169                 WindowManager.LayoutParams.FLAG_DIM_BEHIND);
    170     }
    171 }
    172