/* * * * Copyright 1990-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. */ package javax.microedition.lcdui; /* import javax.microedition.lcdui.KeyConverter; */ import javax.microedition.lcdui.game.GameCanvas; import com.sun.midp.lcdui.EventConstants; import com.sun.midp.lcdui.GameMap; import com.sun.midp.lcdui.GameCanvasLFImpl; import com.sun.midp.log.Logging; import com.sun.midp.log.LogChannels; import com.sun.midp.configurator.Constants; /** * The look and feel implementation of <code>Displayable</code> based * on platform widget. */ abstract class DisplayableLFImpl implements DisplayableLF { /** Static initializer. */ static { initialize0(); } /** * Native class initializer. */ private static native void initialize0(); /** * Creates <code>DisplayableLF</code> for the passed in * <code>Displayable</code>. * * @param d the <code>Displayable</code> object associated with this * look & feel. */ DisplayableLFImpl(Displayable d) { owner = d; width = Display.WIDTH; height = Display.HEIGHT; } /** * Native finalizer to delete native resources. */ private native void finalize(); // ************************************************************ // public methods - DisplayableLF interface implementation // ************************************************************ /** * Implement public API isShown(). * * @return true if current <code>DisplayableLF</code> is interactive * with user. */ public boolean lIsShown() { return (currentDisplay != null) && currentDisplay.isShown(this); } /** * Get the width in pixels this <code>Displayable</code> is using. * * @return width of the area available to the application */ public int lGetWidth() { return width; } /** * Get the height in pixels this <code>Displayable</code> is using. * * @return height of the area available to the application */ public int lGetHeight() { return height; } /** * Notifies <code>Displayable</code>'s look & feel object of * a title change. * * SYNC NOTE: The caller of this method handles synchronization. * * @param oldTitle the old title, or <code>null</code> for no title * @param newTitle the new title, or <code>null</code> for no title */ public void lSetTitle(String oldTitle, String newTitle) { // No updates are necessary if we are in a full screen mode if (owner.isInFullScreenMode) { return; } // No update needed if title string is the same object if (oldTitle == newTitle) { return; } // No update needed if title strings have same content if (oldTitle != null && newTitle != null && oldTitle.equals(newTitle)) { return; } // Update only if we have native resource created if (nativeId != INVALID_NATIVE_ID) { setTitle0(nativeId, newTitle); } } /** * Notifies <code>Displayable</code>'s look & feel object of * a ticker change. * * SYNC NOTE: The caller of this method handles synchronization. * * @param oldTicker the old ticker, or <code>null</code> for no ticker * @param newTicker the new ticker, or <code>null</code> for no ticker */ public void lSetTicker(Ticker oldTicker, Ticker newTicker) { // This method will not be called if oldTicker and // newTicker are the same (that includes both being null) if (owner.ticker != null) { owner.ticker.tickerLF.lSetOwner(this); } updateNativeTicker(oldTicker, newTicker); } /** * Notifies look & feel object of a command addition * to the <code>Displayable</code>. * * SYNC NOTE: The caller of this method handles synchronization. * * @param cmd the command that was added * @param i the index of the added command in * <code>Displayable.commands[]</code> array */ public void lAddCommand(Command cmd, int i) { updateCommandSet(); } /** * Notifies look &s; feel object of a command removal * from the <code>Displayable</code>. * * SYNC NOTE: The caller of this method handles synchronization. * * @param cmd the command that was removed * @param i the index of the removed command in * <code>Displayable.commands[]</code> array */ public void lRemoveCommand(Command cmd, int i) { updateCommandSet(); } /** * Updates command set if this <code>Displayable</code> is visible. * * SYNC NOTE: Caller must hold LCDUILock around this call. */ public void updateCommandSet() { if (state == SHOWN && currentDisplay != null) { currentDisplay.updateCommandSet(); } } /** * Return the <code>Display</code> instance in which the LF is * currently shown. * * @return the <code>Display</code> instance in which the LF is shown. * <code>Null</code> if not shown. */ public Display lGetCurrentDisplay() { return currentDisplay; } /** * Called to get the key mask of all the keys that were pressed. * Implement an interface function for <code>CanvasLF</code> only. * * @return keyMask The key mask of all the keys that were pressed. */ public int uGetKeyMask() { synchronized (Display.LCDUILock) { // don't release currently pressed keys int savedMaskCopy = stickyKeyMask | currentKeyMask; stickyKeyMask = 0; return savedMaskCopy; } } /** * Set the display instance the <code>Displayable</code> is associated * with. * Caller should hold LCDUILock around this call. * * @param d <code>Display</code> instance in which this * <code>DisplayableLF</code> is visible. * <code>null</code> if this <code>DisplayableLF</code> is * no longer visible. */ public void lSetDisplay(Display d) { // ASSERT(d == null || currentDisplay == null) currentDisplay = d; } /** * Return the associated Displayable object. * * SYNC NOTE: Since the <code>Displayable</code> and * <code>DisplayableLFImpl</code> has 1-to-1 mapping, this function * can be called from in or outside of LCDUILock. * * @return the public model object this LF is associated with. */ public Displayable lGetDisplayable() { return owner; } /** * Notifies look & feel object of a full screen mode change. * * @param mode <code>true</code>, if canvas should be displayed * without title, ticker, etc.; <code>false</code> otherwise */ public void uSetFullScreenMode(boolean mode) { boolean requestRepaint = false; synchronized (Display.LCDUILock) { if (lIsShown()) { // currentDisplay is not null when lIsShown is true currentDisplay.lSetFullScreen(mode); if (mode) { setTicker(null); } else if (owner.ticker != null) { setTicker(owner.ticker); } updateCommandSet(); requestRepaint = true; } } if (currentDisplay != null) { // This may call into app code, so do it outside LCDUILock uCallSizeChanged(currentDisplay.width, currentDisplay.height); } else { uCallSizeChanged(Display.WIDTH, Display.HEIGHT); } // app's sizeChanged has to be called before repaint synchronized (Display.LCDUILock) { if (requestRepaint) { lRequestPaint(); } } } /** * Prepare to show this LF on physical screen. * This function will set correct screen mode screen mode * then call lCallShow. */ public void uCallShow() { boolean copyDefferedSizeChange; synchronized (Display.LCDUILock) { // Assure correct screen mode currentDisplay.lSetFullScreen(owner.isInFullScreenMode); // display dimentions may change as the resulr of lSetFullScreen width = currentDisplay.width; height = currentDisplay.height; if (owner.isInFullScreenMode) { setTicker(null); } else if (owner.ticker != null) { setTicker(owner.ticker); } copyDefferedSizeChange = defferedSizeChange; defferedSizeChange = false; } if (copyDefferedSizeChange) { synchronized (Display.calloutLock) { try { owner.sizeChanged(width, height); } catch (Throwable t) { Display.handleThrowable(t); } } } synchronized (Display.LCDUILock) { // Do the internal show preparation lCallShow(); if (pendingInvalidate || copyDefferedSizeChange) { lRequestInvalidate(); } } } /** * Prepare to show this LF on physical screen. This is the * internal version of showNotify() function as defined in MIDP spec. * It is called immediately prior to this LF being made visible * on the display. The LF should load any resource that is * needed, layout. App's paint() should NOT be called in this function. * Instead, it should be in the uCallPaint() that will be called on this * LF shortly after. * * This function sets this DisplayableLF to SHOWN state. */ void lCallShow() { // This will suppress drags, repeats and ups until a // corresponding down is seen. sawPointerPress = sawKeyPress = false; if (state != SHOWN) { // Create native resource first // since the title and ticker may depend on it createNativeResource(); } // Start to paint the ticker updateNativeTicker(null, owner.ticker); // set mapping between GameCanvas and DisplayAccess // set Game key event flag based on value passed in // GameCanvas constructor. if (owner instanceof GameCanvas) { GameMap.registerDisplayAccess(owner, currentDisplay.accessor); stickyKeyMask = currentKeyMask = 0; } else { // set the keymask to -1 when // the displayable is not a GameCanvas. stickyKeyMask = currentKeyMask = -1; } state = SHOWN; } // lCallShow() /** * Get the current vertical scroll position. * * @return int The vertical scroll position on a scale of 0-100 */ public int getVerticalScrollPosition() { // SYNC NOTE: return of atomic value return 0; } /** * Get the current vertical scroll proportion. * * @return ing The vertical scroll proportion on a scale of 0-100 */ public int getVerticalScrollProportion() { // SYNC NOTE: return of atomic value return 100; } /** * Remove this <code>Displayable</code> from physical screen. * This function calls lCallHide after holding LCDUILock * and sets this DisplayableLF to HIDDEN state. */ public void uCallHide() { synchronized (Display.LCDUILock) { // Delete native resources and update ticker lCallHide(); // set state state = HIDDEN; } } /** * Some "system modal dialog" takes over physical screen * buffer and user input now or foreground is lost. * This function calls lCallHide after holding LCDUILock * and sets this DisplayableLF to FROZEN state. */ public void uCallFreeze() { synchronized (Display.LCDUILock) { // Delete native resources and update ticker lCallHide(); // set state state = FROZEN; } } /** * Remove this <code>Displayable</code> from physical screen. * The <code>Displayable</code> should unload any resource that * was allocated. It is not required to clean the physical screen * before this function returns. */ void lCallHide() { if (state == SHOWN) { updateNativeTicker(owner.ticker, null); } // Delete native resources deleteNativeResource(); } /** * Called by the event handler to perform an invalidation of this * <code>Displayable</code>. * Subclass should override to perform re-layout. * Default implementation does nothing. */ public void uCallInvalidate() { synchronized (Display.LCDUILock) { pendingInvalidate = false; } } /** * This method is used in repaint, in order to determine the translation * of the draw coordinates. * * @return <code>true</code>, if the scroll responsibility is on * the native platform. * <code>false</code>, if the scroll is done at Java level. */ public boolean uIsScrollNative() { // only native form overrides this and returns true return false; } // ************************************************************ // package private methods // ************************************************************ /** * Create native resource. * Instance variable {@link #nativeId nativeId} must be set * to the id of the new resource. */ abstract void createNativeResource(); /** * Delete native resource. * Instance variable {@link #nativeId nativeId} is reset * to {@link #INVALID_NATIVE_ID INVALID_NATIVE_ID}. */ void deleteNativeResource() { if (nativeId != INVALID_NATIVE_ID) { deleteNativeResource0(nativeId); nativeId = INVALID_NATIVE_ID; } } /** * Package private equivalent of sizeChanged(). * * @param w the new width * @param h the new height * */ public void uCallSizeChanged(int w, int h) { boolean copyDefferedSizeChange; synchronized (Display.LCDUILock) { if (owner instanceof GameCanvas) { GameCanvasLFImpl gameCanvasLF = GameMap.getGameCanvasImpl((GameCanvas)owner); if (gameCanvasLF != null) { gameCanvasLF.lCallSizeChanged(w, h); } } // If there is no Display, or if this Displayable is not // currently visible, we simply record the fact that the // size has changed defferedSizeChange = (state != SHOWN); copyDefferedSizeChange = defferedSizeChange; /* * sizeChangeOccurred is a boolean which (when true) indicates * that sizeChanged() will be called at a later time. So, if it * is false after calling super(), we go ahead and notify the * Canvas now, rather than later */ width = w; height = h; if (!defferedSizeChange) { lRequestInvalidate(); } } if (!copyDefferedSizeChange) { synchronized (Display.calloutLock) { try { owner.sizeChanged(w, h); } catch (Throwable t) { Display.handleThrowable(t); } } } } /** * This method notify displayable to scroll its content * * @param scrollType scrollType * @param thumbPosition */ public void uCallScrollContent(int scrollType, int thumbPosition) { // by default nothing to do } /** * <code>Display</code> calls this method on it's current * <code>Displayable</code>. * <code>Displayable</code> uses this opportunity to do necessary stuff * on the graphics context, this includes, paint Ticker, paint Title * and translate as necessary. * * <p>The target Object of this repaint may be some Object * initially set by this <code>Displayable</code> when the repaint was * requested - allowing this <code>Displayable</code> to know exactly * which Object it needs to call to service this repaint, * rather than potentially querying all of its Objects to * determine the one(s) which need painting. * * SYNC NOTE: The caller of this method handles synchronization. * * @param g the graphics context to paint into. * @param target the target Object of this repaint */ public void uCallPaint(Graphics g, Object target) { // Made obsolete by dsShow, where native title is shown already } /** * Handle a raw key event from <code>Display</code>. * * @param type type of event, defined in <code>EventConstants</code> * @param keyCode code of the key event */ public void uCallKeyEvent(int type, int keyCode) { int eventType = -1; synchronized (Display.LCDUILock) { switch (type) { case EventConstants.PRESSED: sawKeyPress = true; eventType = 0; break; case EventConstants.RELEASED: if (sawKeyPress) { eventType = 1; } break; case EventConstants.REPEATED: if (sawKeyPress) { eventType = 2; } break; } // used later by getKeyMask() if (currentKeyMask > -1 && eventType != -1) { if (eventType == 1) { releaseKeyMask(keyCode); } else { // set the mask on key press, repeat or type. // don't set the mask when a key was released. setKeyMask(keyCode); } } } // synchronized // SYNC NOTE: Since we may call into application code, // we do so outside of LCDUILock switch (eventType) { case -1: return; case 0: uCallKeyPressed(keyCode); break; case 1: uCallKeyReleased(keyCode); break; case 2: uCallKeyRepeated(keyCode); break; default: /* * TBD: * * Originally severity level was "ERROR". * But it was reduced to INFO because * a). it do not harm to the system * b). some cases, * Displayable processes KEY_PRESS events * (when in system menu) & cleans all related status flag, * while following KEY_REPEAT & KEY_RELEASE event pairs * are not processed in the same way and therefore * this eror messae was printed or them. * * As a temporary solution it was decided to disable messages * insead of additional event filtering. */ if (Logging.REPORT_LEVEL <= Logging.INFORMATION) { Logging.report(Logging.INFORMATION, LogChannels.LC_HIGHUI, "DisplayableLFImpl: uCallKeyEvent," + "type=" +type+ " keyCode=" +keyCode); } break; } } // end of dsKeyEvent() /** * Set status of screen rotation * @param newStatus * @return */ public boolean uSetRotatedStatus(boolean newStatus) { synchronized (Display.LCDUILock) { if (newStatus == owner.isRotated) { return false; } else { owner.isRotated = newStatus; return true; } } } /** * Handle a key press. * * @param keyCode The key that was pressed */ void uCallKeyPressed(int keyCode) { } /** * Handle a repeated key press. * * @param keyCode The key that was pressed */ void uCallKeyRepeated(int keyCode) { } /** * Handle a key release. * * @param keyCode The key that was released */ void uCallKeyReleased(int keyCode) { } /** * Called from the event delivery loop when a pointer event is seen. * * @param type kind of pointer event * @param x x-coordinate of pointer event * @param y y-coordinate of pointer event */ public void uCallPointerEvent(int type, int x, int y) { int eventType = -1; synchronized (Display.LCDUILock) { switch (type) { case EventConstants.PRESSED: sawPointerPress = true; eventType = 0; break; case EventConstants.RELEASED: if (sawPointerPress) { eventType = 1; } break; case EventConstants.DRAGGED: if (sawPointerPress) { eventType = 2; } break; } } // synchronized // SYNC NOTE: Since we may call into application code, // we do so outside of LCDUILock switch (eventType) { case -1: return; case 0: uCallPointerPressed(x, y); break; case 1: uCallPointerReleased(x, y); break; case 2: uCallPointerDragged(x, y); break; default: // this is an error break; } } // uCallPointerEvent() /** * Handle a pointer press event. * * @param x The x coordinate of the press * @param y The y coordinate of the press */ void uCallPointerPressed(int x, int y) { } /** * Handle a pointer drag event. * * @param x The x coordinate of the drag * @param y The y coordinate of the drag */ void uCallPointerDragged(int x, int y) { } /** * Handle a pointer release event. * * @param x The x coordinate of the release * @param y The y coordinate of the release */ void uCallPointerReleased(int x, int y) { } /** * Called to commit any pending user interaction for the current item. */ public void lCommitPendingInteraction() { } /** * Repaint this <code>Displayable</code>. * * @param x The x coordinate of the region to repaint * @param y The y coordinate of the region to repaint * @param width The width of the region to repaint * @param height The height of the region to repaint * @param target an optional paint target to receive the paint request * when it returns via uCallPaint() */ void lRequestPaint(int x, int y, int width, int height, Object target) { if (lIsShown()) { // Note: Display will not let anyone but the current // Displayable schedule repaints currentDisplay.repaintImpl(this, x, y, width, height, target); } } /** * Repaints this <code>Displayable</code>. * This is the same as calling * repaint(0, 0, width, height, null) */ void lRequestPaint() { lRequestPaint(0, 0, width, height, null); } /** * Request to paint all of this Displayable (without holding a lock). */ void uRequestPaint() { synchronized (Display.LCDUILock) { lRequestPaint(); } } /** * Repaint the whole <code>Displayable</code>. */ void lRequestPaintContents() { lRequestPaint(0, 0, width, height, null); } /** * Called to schedule an "invalidate" for this <code>Displayable</code>. * Invalidation is caused by things like size changes, content changes, * or spontaneous traversal within the <code>Item</code>. * * SYNC NOTE: Caller must hold LCDUILock around this call. */ void lRequestInvalidate() { pendingInvalidate = true; if (state == SHOWN && currentDisplay != null) { currentDisplay.invalidate(); } } // ************************************************************ // private methods // ************************************************************ /** * Updates the ticker. * * @param oldTicker the old ticker, or <code>null</code> for no ticker * @param newTicker the new ticker, or <code>null</code> for no ticker */ private void updateNativeTicker(Ticker oldTicker, Ticker newTicker) { // CASES: // 1. Had an invisible non-null ticker, setting a null ticker // - We need to set the new ticker. There's no need to re-layout // or start the new ticker // 2. Had an invisible non-null ticker, setting a non-null ticker // - We need to set the new ticker. There's no need to re-layout // or start the new ticker // 3. Had a visible non-null ticker, setting a null ticker // - We need to set the new ticker and re-layout. There's no // need to start the new ticker. // 4. Had a null ticker, setting a visible non-null ticker // - We need to set the new ticker, re-layout, and // start up the new ticker // 5. Had a visible non-null ticker, setting a non-null ticker // - We need to set the new ticker. There's no need to re-layout if ((owner.isInFullScreenMode) || ((oldTicker == null) && (newTicker == null))) { return; } else { setTicker(newTicker); } } /** * Set the ticker. * * @param t the new ticker to be set */ private void setTicker(Ticker t) { if (nativeId != INVALID_NATIVE_ID) { setTicker0(nativeId, (t == null) ? null : t.displayedMessage); } } /** * Notification that the ticker has changed. * This method is called from <code>TickerLFImpl</code>. * * @param t the ticker associated with the TickerLFImpl */ void tickerTextChanged(Ticker t) { if (owner.ticker != t) { return; } setTicker(t); } /** * Called to set key mask of all the keys that were pressed. * * @param keyCode The key code to set the key mask. */ private void setKeyMask(int keyCode) { /* // Shouldn't run into this case. if (paintSuspended || !hasForeground) { return; } */ // set the mask of keys pressed switch (KeyConverter.getGameAction(keyCode)) { case Canvas.UP: stickyKeyMask = stickyKeyMask | GameCanvas.UP_PRESSED; currentKeyMask = currentKeyMask | GameCanvas.UP_PRESSED; break; case Canvas.DOWN: stickyKeyMask = stickyKeyMask | GameCanvas.DOWN_PRESSED; currentKeyMask = currentKeyMask | GameCanvas.DOWN_PRESSED; break; case Canvas.LEFT: stickyKeyMask = stickyKeyMask | GameCanvas.LEFT_PRESSED; currentKeyMask = currentKeyMask | GameCanvas.LEFT_PRESSED; break; case Canvas.RIGHT: stickyKeyMask = stickyKeyMask | GameCanvas.RIGHT_PRESSED; currentKeyMask = currentKeyMask | GameCanvas.RIGHT_PRESSED; break; case Canvas.FIRE: stickyKeyMask = stickyKeyMask | GameCanvas.FIRE_PRESSED; currentKeyMask = currentKeyMask | GameCanvas.FIRE_PRESSED; break; case Canvas.GAME_A: stickyKeyMask = stickyKeyMask | GameCanvas.GAME_A_PRESSED; currentKeyMask = currentKeyMask | GameCanvas.GAME_A_PRESSED; break; case Canvas.GAME_B: stickyKeyMask = stickyKeyMask | GameCanvas.GAME_B_PRESSED; currentKeyMask = currentKeyMask | GameCanvas.GAME_B_PRESSED; break; case Canvas.GAME_C: stickyKeyMask = stickyKeyMask | GameCanvas.GAME_C_PRESSED; currentKeyMask = currentKeyMask | GameCanvas.GAME_C_PRESSED; break; case Canvas.GAME_D: stickyKeyMask = stickyKeyMask | GameCanvas.GAME_D_PRESSED; currentKeyMask = currentKeyMask | GameCanvas.GAME_D_PRESSED; } } /** * Called to release key mask of all the keys that were release. * * @param keyCode The key code to release the key mask. */ private void releaseKeyMask(int keyCode) { /* // Leave this case to dsHide and dsFreeze() if (paintSuspended || !hasForeground) { currentKeyMask = 0; return; } */ // set the mask of keys pressed switch (KeyConverter.getGameAction(keyCode)) { case Canvas.UP: currentKeyMask = currentKeyMask & ~ GameCanvas.UP_PRESSED; break; case Canvas.DOWN: currentKeyMask = currentKeyMask & ~ GameCanvas.DOWN_PRESSED; break; case Canvas.LEFT: currentKeyMask = currentKeyMask & ~ GameCanvas.LEFT_PRESSED; break; case Canvas.RIGHT: currentKeyMask = currentKeyMask & ~ GameCanvas.RIGHT_PRESSED; break; case Canvas.FIRE: currentKeyMask = currentKeyMask & ~ GameCanvas.FIRE_PRESSED; break; case Canvas.GAME_A: currentKeyMask = currentKeyMask & ~ GameCanvas.GAME_A_PRESSED; break; case Canvas.GAME_B: currentKeyMask = currentKeyMask & ~ GameCanvas.GAME_B_PRESSED; break; case Canvas.GAME_C: currentKeyMask = currentKeyMask & ~ GameCanvas.GAME_C_PRESSED; break; case Canvas.GAME_D: currentKeyMask = currentKeyMask & ~ GameCanvas.GAME_D_PRESSED; } } // ************************************************************ // public member variables - NOT ALLOWED in this class // ************************************************************ // ************************************************************ // protected member variables - NOT ALLOWED in this class // ************************************************************ // ************************************************************ // package private member variables // ************************************************************ /** * The current <code>Display</code> object. */ Display currentDisplay; /** * Width and height available to the <code>Displayable</code>. */ int width, height; /** * <code>True</code>, indicates that before being painted, this * <code>Displayable</code> should be notified that its size has * changed via uCallSizeChanged(). */ boolean defferedSizeChange = true; /** * The owner of this view. */ Displayable owner; /** * The <code>MidpDisplayable*</code> of this <code>Displayable</code> * while visible. * <code>INVALID_NATIVE_ID</code> if no native resource has been created. */ int nativeId = INVALID_NATIVE_ID; /** * Version number of this LF's data model. * Should be updated when public data model has changed and * be passed to native peer if visible. Native peer tags * all its native events with this version to prevent user * actions on obsolete copy of the data in native. */ int modelVersion; // = 0 // ************************************************************ // private member variables // ************************************************************ // No events will be delivered while these are false. // This is our attempt at avoiding spurious up events. /** * <code>True</code>, if a pointer press is in progress. */ boolean sawPointerPress; /** * <code>True</code>, if a key press is in progress. */ boolean sawKeyPress; /** current state of DisplayableLF (HIDDEN, SHOWN, or FROZEN) */ int state; // = HIDDEN (0) /** * Stores key code of the current key pressed at least once. */ // caters to the GameCanvas.getKeyStats() latching behavior. // This latched state is cleared when getKeyStats() is called. private int stickyKeyMask; /** * Stores key code of the current key is currently down. */ // sets the key to 1 when the key is currently down private int currentKeyMask; /** * Used to indicate the invalidate is needed */ boolean pendingInvalidate; // ************************************************************ // Static initializer, constructor // ************************************************************ /** * Used as an index into the viewport[], for the x origin. */ final static int X = 0; /** * Used as an index into the viewport[], for the y origin. */ final static int Y = 1; /** * Used as an index into the viewport[], for the width. */ final static int WIDTH = 2; /** * Used as an index into the viewport[], for the height. */ final static int HEIGHT = 3; /** * Uninitialized native resource id value. */ final static int INVALID_NATIVE_ID = 0; /** hidden state of DisplayableLF */ final static int HIDDEN = 0; /** shown state of DisplayableLF */ final static int SHOWN = 1; /** frozen state of DisplayableLF */ final static int FROZEN = 2; // ************************************************************ // Native methods // *********************************************************** /** * Free the native resource of this <code>Displayable</code> and hide * it from display. * * @param nativeId native resource id * * @exception OutOfMemoryException - if out of native resource */ private native void deleteNativeResource0(int nativeId); /** * Change the title of native resource. * * @param nativeId native resource id (<code>MidpDisplayable *</code>) * @param title New title string. Can be <code>null</code>. */ private static native void setTitle0(int nativeId, String title); /** * Set text of the native ticker. * * @param nativeId native resource id. * @param text text used. Null if the ticker should stop. */ private static native void setTicker0(int nativeId, String text); } // DisplayableLFImpl