--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javauis/lcdui_akn/javalcdui/javasrc/javax/microedition/lcdui/Toolkit.java Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,745 @@
+/*
+* Copyright (c) 1999 - 2004 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+package javax.microedition.lcdui;
+
+import java.util.Hashtable;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.io.IOException;
+import java.io.InputStream;
+
+import com.nokia.mj.impl.rt.legacy.LegacyRtPort;
+import com.nokia.mj.impl.rt.legacy.LegacySupport;
+import com.nokia.mj.impl.rt.legacy.MIDEventServer;
+import com.nokia.mj.impl.rt.legacy.NativeError;
+import com.nokia.mj.impl.rt.legacy.ToolkitObserver;
+
+import com.nokia.mj.impl.rt.support.ApplicationUtils;
+import com.nokia.mj.impl.rt.support.ApplicationInfo;
+import com.nokia.mj.impl.rt.support.Finalizer;
+import com.nokia.mj.impl.rt.support.ShutdownListener;
+import com.nokia.mj.impl.utils.Logger;
+
+final class Toolkit
+{
+ static
+ {
+ com.nokia.mj.impl.rt.support.Jvm.loadSystemLibrary("javalcdui");
+ DirectGraphicsInvoker.createInvoker();
+ FreeSizeFontInvoker.createInvoker();
+ LcduiPropertyInvoker.createInvoker();
+ CanvasGraphicsItemPainterInvoker.createInvoker();
+ }
+
+ private Finalizer mFinalizer = new Finalizer()
+ {
+ public void finalizeImpl()
+ {
+ doFinalize();
+ }
+ };
+ //
+ private static final String SERVER_NAME = "javax.microedition.lcdui";
+ private static final String DEFAULT_MIDLET_NAME = "MIDlet ";
+ private static final int DEFAULT_MIDLET_UID = 0x101F9515;
+
+ // NGA specific change.
+ // Java side doesn't support native (c++) style macro flags and
+ // that is why Toolkit & ToolkitInvoker have been harnessed to substitutes
+ // NGA flag & its index
+ static final int FLAG_NONE = 0;
+ static final int FLAG_NGA_INDEX = 0;
+ static final int FLAG_NGA = 1 << FLAG_NGA_INDEX;
+ // Defines total flag count. Must be keep up to date.
+ private static final int FLAG_COUNT = 1;
+
+ private static final String RESOURCE_OR_PLUGIN_NOT_FOUND =
+ "Cannot find lcdui dll, or lcdgr dll or lcdui resource file";
+
+ //
+ private static int iServerCount;
+
+ private ToolkitInvoker iInvoker;
+ private Object iDestroySync = new Object();
+ private static final int HANDLE_UNINITIALIZED = -0xfffffe;
+ private int iHandle = HANDLE_UNINITIALIZED;
+ private Device iDevice;
+ private Display iDisplay;
+ private Image iIcon;
+ private MIDEventServer iEventServer;
+ private Hashtable iFontCache;
+ Buffer iBuffer;
+ private Object iCallbackLock;
+
+ private Vector iObservers;
+ private boolean iStartingInBackground = false;
+ protected Vector tmpDisplayables; //temporary Vector of created Displayables
+ protected boolean activated = false; //events are dispatched only if Toolkit is active, see Toolkit.start()
+
+ // NGA specific change
+ private int iFlags = FLAG_NONE;
+
+ // Splash screen specific
+ private boolean iFirstPaint = true;
+
+ //
+ // Event source : must keep in sync with TSourceType in lcdui.h
+ //
+ private static final int ITEM = 3;
+ private static final int DISPLAYABLE = 4;
+ private static final int MIDLET = 5;
+ private static final int SERIAL = 6; // deprecated
+ private static final int CANVAS_GRAPHICS_ITEM_PAINTER = 7;
+
+ //
+ // Event type : must keep in sync with TEventType in lcdui.h
+ //
+ static final int EVENT_PAINT = 10;
+ static final int EVENT_KEY_PRESSED = 11;
+ static final int EVENT_KEY_RELEASED = 12;
+ static final int EVENT_KEY_REPEATED = 13;
+ static final int EVENT_POINTER_PRESSED = 14;
+ static final int EVENT_POINTER_RELEASED = 15;
+ static final int EVENT_POINTER_DRAGGED = 16;
+ static final int EVENT_SIZE_CHANGED = 17;
+
+ static final int EVENT_EXIT_REQUESTED = 18;
+ static final int EVENT_FOREGROUND = 19;
+ static final int EVENT_BACKGROUND = 20;
+ static final int EVENT_PAUSE_REQUESTED = 21;
+ static final int EVENT_START_REQUESTED = 22;
+ static final int EVENT_DESTROY_REQUESTED = 23;
+ static final int EVENT_COMMAND = 24;
+ static final int EVENT_VISIBLE = 25;
+ static final int EVENT_TRAVERSE = 26;
+ static final int EVENT_SET_CURRENT = 29;
+ static final int EVENT_SERIAL = 30;
+
+ static final int EVET_CANVAS_GRAPHICS_ITEM_REPAINT = 31;
+
+ // IMPLICIT EVENT TYPES
+ static final int EVENT_DISMISS = 0; // ALERT
+ static final int EVENT_ITEM_CHANGED = 0; // ITEM(S)
+ static final int EVENT_SELECT = 0; // LIST
+
+ //
+ // Op codes for syncing to screen
+ // These must be kept in sync with MMIDCanvas::TDrawOp
+ //
+ private static final int SYNC = 0;
+ private static final int SYNC_RECT = 1;
+
+ // NGA specific change.
+ // Op code indicating M3G content start
+ private static final int M3G_CONTENT_START = 2;
+
+ // Splash screen specific.
+ private static final int SYNC_FIRST_PAINT = 3;
+
+ Toolkit(ToolkitInvoker aInvoker)
+ {
+ iInvoker = aInvoker;
+ tmpDisplayables = new Vector();
+
+ iStartingInBackground = iInvoker.iStartInBackGround;
+
+ ApplicationUtils.getInstance().addShutdownListener(new ShutdownListener()
+ {
+ public final void shuttingDown()
+ {
+ dispose();
+ }
+ });
+
+ }
+
+ /**
+ * Initializes the Toolkit, if it is uninitialized.
+ */
+ private void ensureInitialized()
+ {
+ if (iEventServer == null)
+ {
+ initialize();
+ }
+ }
+
+ /**
+ * Initializes the Toolkit.
+ */
+ synchronized private void initialize()
+ {
+ if (iEventServer != null)
+ {
+ return;
+ }
+ /**
+ * get UI server instance number
+ */
+ final String serverNumber = getServerNumber();
+
+ /**
+ * create mangled server name
+ */
+ final String serverName = SERVER_NAME.concat(serverNumber);
+
+ ApplicationInfo appInfo = ApplicationInfo.getInstance();
+ String appName = appInfo.getLocalizedName();
+ if (null == appName)
+ {
+ appName = DEFAULT_MIDLET_NAME.concat(serverNumber);
+ }
+
+ int appUid = LegacyRtPort.getMidletUid();
+ if (appUid == 0)
+ {
+ appUid = DEFAULT_MIDLET_UID;
+ }
+
+ String appHome = appInfo.getRootPath();
+ if (appHome.endsWith("\\"))
+ {
+ appHome = appHome.substring(0, appHome.length() - 1);
+ }
+
+ /**
+ * Create native event server + thread. This will run until shutdown
+ * in Toolkit.dispose().
+ */
+ iEventServer = new UiEventServer(serverName, appUid);
+ iCallbackLock = new Object();
+
+ final Hashtable properties = iInvoker.iMidletArgs;
+ final String[] attributes = new String [properties.size() * 2];
+ int count = -1;
+ for (final Enumeration keys = properties.keys(); keys.hasMoreElements();)
+ {
+ final String key = (String)keys.nextElement();
+ attributes[++count] = key;
+ attributes[++count] = (String)properties.get(key);
+ }
+
+ final int server = iEventServer.getHandle();
+
+ // NGA specific change.
+ // Array that will be filled with native flag macros
+ int[] flags = new int[Toolkit.FLAG_COUNT];
+ iHandle = _create(server, appName, appUid, appHome, attributes, flags);
+ switch (iHandle)
+ {
+ case NativeError.KErrNotFound:
+ case NativeError.KErrPathNotFound:
+ throw new RuntimeException(RESOURCE_OR_PLUGIN_NOT_FOUND);
+ default:
+ checkHandle(iHandle); // leaves if error
+ break;
+ }
+ // NGA specific change.
+ // Update flags
+ if (flags[Toolkit.FLAG_NGA_INDEX] > 0)
+ {
+ this.iFlags |= Toolkit.FLAG_NGA;
+ }
+
+ iDevice = new Device(this);
+ iBuffer = new Buffer(this);
+ iFontCache = new Hashtable();
+
+ }
+
+ InputStream getResourceAsStream(String aResource)
+ throws
+ IOException
+ {
+ return getClass().getResourceAsStream(aResource);
+ }
+
+ synchronized void start(Display aDisplay)
+ {
+ ensureInitialized();
+ iDisplay = aDisplay;
+ NativeError.check(_activate(iHandle));
+ activated = true;
+ }
+
+ private static synchronized String getServerNumber()
+ {
+ return Integer.toString(++iServerCount);
+ }
+
+ /**
+ * NGA specific change.
+ * Check if flags are set.
+ * @param flags Flags indexes
+ * @return True if flags are on.
+ * @since S60 9.2
+ */
+ boolean checkFlags(int flags)
+ {
+ return ((iFlags & flags) > 0);
+ }
+
+ public boolean isClosed()
+ {
+ return ((iHandle != HANDLE_UNINITIALIZED) &&
+ (iHandle <= 0));
+ }
+
+ public int getHandle()
+ {
+ ensureInitialized();
+ if (isClosed())
+ {
+ throw new RuntimeException("Toolkit closed");
+ }
+ return iHandle;
+ }
+
+ static Toolkit getToolkit()
+ {
+ ToolkitInvoker invoker = (ToolkitInvoker)ToolkitInvoker.getToolkitInvoker();
+ return invoker.getCurrentToolkit();
+ }
+
+ final Device getDevice()
+ {
+ ensureInitialized();
+ return iDevice;
+ }
+
+ final Display getDisplay()
+ {
+ ensureInitialized();
+ return iDisplay;
+ }
+
+ final Object getCallbackLock()
+ {
+ ensureInitialized();
+ return iCallbackLock;
+ }
+
+ final Hashtable getFontCache()
+ {
+ ensureInitialized();
+ return iFontCache;
+ }
+
+ final synchronized void addObserver(ToolkitObserver aObserver)
+ {
+ if (aObserver == null)
+ {
+ return;
+ }
+
+ if (iObservers == null)
+ {
+ iObservers = new Vector(2);
+ }
+
+ if (!iObservers.contains(aObserver))
+ {
+ iObservers.addElement(aObserver);
+ }
+ }
+
+ final synchronized void removeObserver(ToolkitObserver aObserver)
+ {
+ if ((iObservers != null) && (aObserver != null))
+ {
+ iObservers.removeElement(aObserver);
+ }
+ }
+
+ /**
+ * If toolkit is already disposed, then native object has already been deleted
+ * aHandle can be null if exception thrown in the object's constructor (where the handle
+ * is typically assigned
+ */
+ final synchronized void disposeObject(int aHandle)
+ {
+ ensureInitialized();
+
+ if (aHandle == 0)
+ {
+ Logger.LOG(Logger.EJavaUI, Logger.EInfo,
+ "disposeObject(" + aHandle + ") < ignoring NULL handle");
+ return;
+ }
+
+ if (iHandle <= 0)
+ {
+ Logger.LOG(Logger.EJavaUI, Logger.EInfo,
+ "disposeObject(" + aHandle + ") < : Toolkit already closed!");
+ return;
+ }
+
+ //
+ // Lock buffer for duration of dispose.
+ //
+ synchronized (iBuffer)
+ {
+ iBuffer.sync();
+ _disposeObject(iHandle, aHandle);
+ }
+
+ }
+
+ private void doFinalize()
+ {
+ if (mFinalizer != null)
+ {
+ registeredFinalize();
+ mFinalizer = null;
+ }
+ }
+
+ void registeredFinalize()
+ {
+ dispose();
+ }
+
+ final synchronized void dispose()
+ {
+ if ((iHandle == HANDLE_UNINITIALIZED) || (iHandle > 0))
+ {
+ //
+ // Notify observers that toolkit is being destroyed.
+ //
+ if (null != iObservers)
+ {
+ final int lastIndex = iObservers.size() -1;
+ for (int ii=lastIndex; ii>=0; ii--)
+ {
+ final ToolkitObserver observer = (ToolkitObserver)iObservers.elementAt(ii);
+ try
+ {
+ observer.destroyNotify();
+ }
+ catch (Exception ex)
+ {
+ Logger.ELOG(Logger.EJavaUI,
+ "exception thrown in destroyNotify: ", ex);
+ // close must complete otherwise could get panic, so ignore
+ // any exception thrown by observers.
+ }
+ }
+ }
+
+ iInvoker.removeToolkit();
+
+ if (null != iDisplay)
+ {
+ iDisplay.dispose();
+ iDisplay = null;
+ }
+
+ //
+ // Close the graphics buffer if present.
+ //
+ if (null != iBuffer)
+ {
+ synchronized (iBuffer)
+ {
+ iBuffer.close();
+ }
+ iBuffer = null;
+ }
+
+ if (iHandle > 0)
+ {
+ _dispose(iHandle);
+ iHandle = 0;
+ }
+
+ //
+ // Shutdown the ui event thread.
+ //
+ if (iEventServer != null)
+ {
+ iEventServer.shutdown();
+ }
+ }
+ }
+
+ /* deprecated */
+ private void handleAsyncEvent(Object aSource, int aResult)
+ {
+ ((AsyncCall)aSource).complete(aResult);
+ }
+
+ private boolean resetThread()
+ {
+ if (!isClosed())
+ {
+ return true;
+ }
+ return false;
+ }
+
+ private void handleItemEvent(Item aSource, int aEvent, int aParam0, int aParam1, int aParam2)
+ {
+ if (resetThread())
+ {
+ aSource.handleEvent(aEvent, aParam0, aParam1, aParam2);
+ }
+ }
+
+ private void handleDisplayableEvent(Displayable aSource, int aEvent, int aParam0, int aParam1, int aParam2)
+ {
+ synchronized (iDestroySync)
+ {
+ //S60 Modification ==>
+ try
+ {
+ if (resetThread())
+ {
+ aSource.handleEvent(aEvent, aParam0, aParam1);
+ }
+ }
+ catch (Throwable t)
+ {
+ String className = t.getClass().getName();
+ int index = className.lastIndexOf('.');
+ if (index != -1)
+ {
+ className = className.substring(index + 1, className.length());
+ }
+ String errStr= "Exception in handleDisplayableEvent. Reason: "+className+
+ "\n event is : "+aEvent+
+ "\n source is : "+aSource+"\n p0 is : "+aParam0+
+ "\n p1 is : "+aParam1+"\n p2 is : "+aParam2;
+ Logger.ELOG(Logger.EJavaUI,errStr, t);
+
+ //Removing Displayable if is exception thrown
+ if (tmpDisplayables.contains(this))
+ {
+ tmpDisplayables.removeElement(this);
+ }
+ }
+ }
+ }
+
+ private void handleDisplayEvent(Toolkit aToolkit, int aEvent, int aParam0, int aParam1, int aParam2)
+ {
+ synchronized (iDestroySync)
+ {
+ if (resetThread())
+ {
+ switch (aEvent)
+ {
+ case EVENT_EXIT_REQUESTED:
+ ApplicationUtils.getInstance().notifyExitCmd();
+ break;
+ case EVENT_DESTROY_REQUESTED:
+ ApplicationUtils.getInstance().notifyExitCmd();
+ break;
+ case EVENT_PAUSE_REQUESTED:
+ ApplicationUtils.getInstance().pauseApplication();
+ break;
+ case EVENT_START_REQUESTED:
+ ApplicationUtils.getInstance().resumeApplication();
+ break;
+ case EVENT_FOREGROUND:
+ iDisplay.handleForeground(true);
+ break;
+ case EVENT_BACKGROUND:
+ iDisplay.handleForeground(false);
+ break;
+ case EVENT_SET_CURRENT:
+ iDisplay.switchCurrent();
+ break;
+ case EVENT_SERIAL:
+ iDisplay.processSerialEvents();
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+ }
+ }
+
+ private void handleCanvasGraphicsItemPainterEvent(CanvasGraphicsItemPainter aSource, int aEvent, int aParam0, int aParam1, int aParam2)
+ {
+ if (resetThread())
+ {
+ aSource.handleEvent(aEvent, aParam0, aParam1);
+ }
+ }
+
+ synchronized void setForeground(boolean aForeground)
+ {
+ if (iStartingInBackground)
+ {
+ NativeError.check(_setForeground(getHandle(), false));
+ iStartingInBackground = false;
+ }
+ else
+ {
+ NativeError.check(_setForeground(getHandle(), aForeground));
+ }
+ }
+
+ /**
+ * blocks until all drawing complete
+ */
+ void sync()
+ {
+ ensureInitialized();
+ synchronized (iBuffer)
+ {
+ iBuffer.sync();
+ }
+ }
+
+ /*
+ * NGA specific change.
+ * Adds m3g content start op code to buffer,
+ * if Graphics's target is Canvas.
+ * The buffer is synchronized in any case.
+ * @param aGraphics Graphics instance
+ * @see ToolkitInvoker#toolkitSync(Object, Object)
+ * @since S60 9.2
+ */
+ void sync(Object aObject)
+ {
+ ensureInitialized();
+ Graphics graphics = (Graphics)aObject;
+ if (checkFlags(FLAG_NGA) &&
+ graphics != null &&
+ graphics.iTarget instanceof Canvas)
+ {
+ Canvas canvas = (Canvas)graphics.iTarget;
+ canvas.setM3GContent(true);
+ synchronized (iBuffer)
+ {
+ iBuffer.write(canvas.getContentHandle(), M3G_CONTENT_START);
+ iBuffer.sync();
+ }
+ }
+ else
+ {
+ sync();
+ }
+ }
+
+ /**
+ * Write buffer command which when processed will draw to screen.
+ * Used by Canvas and CustomItem.
+ */
+ void sync(int aDrawable)
+ {
+ ensureInitialized();
+ synchronized (iBuffer)
+ {
+ iBuffer.write(aDrawable, SYNC);
+ iBuffer.sync();
+ }
+ }
+
+ /**
+ * Write buffer command which when processed will draw to screen.
+ * Used by Canvas and CustomItem.
+ */
+ void sync(int aDrawable, int aX, int aY, int aW, int aH)
+ {
+ ensureInitialized();
+ synchronized (iBuffer)
+ {
+ final int x2=aX+aW;
+ final int y2=aY+aH;
+ iBuffer.write(aDrawable, SYNC_RECT, aX, aY, x2, y2);
+ iBuffer.sync();
+
+ if (iFirstPaint)
+ {
+ iFirstPaint = false;
+ iBuffer.write(aDrawable, SYNC_FIRST_PAINT);
+ iBuffer.sync();
+ }
+ }
+ }
+
+ /**
+ JSR 135 Support
+ */
+ final int getEventServerHandle()
+ {
+ ensureInitialized();
+ return iEventServer.getHandle();
+ }
+
+ void postEvent(int aEvent)
+ {
+ NativeError.check(_postEvent(getHandle(), 0, MIDLET, aEvent));
+ }
+
+ void postEvent(Item aItem, int aEvent)
+ {
+ NativeError.check(_postEvent(getHandle(), aItem.getHandle(), ITEM, aEvent));
+ }
+
+ void postEvent(Displayable aDisplayable, int aEvent)
+ {
+ NativeError.check(_postEvent(getHandle(), aDisplayable.getContainerHandle(), DISPLAYABLE, aEvent));
+ }
+
+ void postEvent(CanvasGraphicsItemPainter aCanvasGraphicsItem, int aEvent)
+ {
+ NativeError.check(_postEvent(getHandle(), aCanvasGraphicsItem.getHandle(), CANVAS_GRAPHICS_ITEM_PAINTER, aEvent));
+ }
+
+ static int checkHandle(int aHandle)
+ {
+ if (NativeError.check(aHandle) == 0)
+ {
+ throw new OutOfMemoryError();
+ }
+ return aHandle;
+ }
+
+ /**
+ * NGA specific change.
+ * Create native peer on server thread reference by aContext.
+ * @param aFlags The array that is filled according to native
+ * side's macro definitions
+ */
+ native int _create(
+ int aContext,String aName, int aUid, String aHomeDir, String[] aAttributes, int[] aFlags);
+
+ /**
+ * Open toolkit - enable events.
+ */
+ native int _activate(int aToolkit);
+
+ /**
+ * Delete toolkit - invalidates handle so no remaining threads must be
+ * holding the toolkit handle.
+ */
+ native void _dispose(int aToolkit);
+
+ /**
+ * Deletion native UI object with handle aObject
+ */
+ native void _disposeObject(int aToolkit,int aObject);
+
+ native int _postEvent(int aToolkit, int aSource, int aType, int aEvent);
+ native int _setCurrent(int aToolkit,int aDisplayable);
+ native int _setForeground(int aToolkit, boolean aForeground);
+}