javauis/lcdui_qt/src/javax/microedition/lcdui/Canvas.java
changeset 26 dc7c549001d5
parent 23 98ccebc37403
child 35 85266cc22c7f
equal deleted inserted replaced
23:98ccebc37403 26:dc7c549001d5
    25 import org.eclipse.swt.events.*;
    25 import org.eclipse.swt.events.*;
    26 import org.eclipse.swt.widgets.*;
    26 import org.eclipse.swt.widgets.*;
    27 import org.eclipse.swt.widgets.Display;
    27 import org.eclipse.swt.widgets.Display;
    28 import org.eclipse.swt.graphics.*;
    28 import org.eclipse.swt.graphics.*;
    29 import org.eclipse.swt.internal.extension.CompositeExtension;
    29 import org.eclipse.swt.internal.extension.CompositeExtension;
       
    30 import org.eclipse.swt.internal.qt.graphics.WindowSurface;
       
    31 
    30 
    32 
    31 /**
    33 /**
    32  * The abstract <code>Canvas</code> class is designed to handle low-level
    34  * The abstract <code>Canvas</code> class is designed to handle low-level
    33  * graphical operations as well as low-level key and pointer events. Canvas is
    35  * graphical operations as well as low-level key and pointer events. Canvas is
    34  * derived from <code>Displayable</code> so the application can switch between
    36  * derived from <code>Displayable</code> so the application can switch between
   151         new CanvasShellPaintListener();
   153         new CanvasShellPaintListener();
   152 
   154 
   153     private CanvasShellMouseListener mouseListener =
   155     private CanvasShellMouseListener mouseListener =
   154         new CanvasShellMouseListener();
   156         new CanvasShellMouseListener();
   155 
   157 
   156     // Canvas Graphics object passed to paint(Graphics g).
   158     // Canvas Graphics object passed to paint(Graphics g)
   157     // Graphics has its own back-buffer for double buffering.
       
   158     private Graphics canvasGraphics;
   159     private Graphics canvasGraphics;
   159 
   160 
       
   161     // Graphics command buffer for this instance
       
   162 	CanvasBuffer graphicsBuffer;
       
   163 	
   160     //On Screen Keypad
   164     //On Screen Keypad
   161     //private Composite keypadComposite;
   165     //private Composite keypadComposite;
   162     private CanvasKeypad onScreenkeypad;
   166     private CanvasKeypad onScreenkeypad;
   163     private int oskHeight;
   167     private int oskHeight;
   164 
   168 
   165     // Vector of flags that a certain key was pressed but was not released.
   169     // Vector of flags that a certain key was pressed but was not released.
   166     // Used to implement keyRepeated since eSWT does not support
   170     // Used to implement keyRepeated since eSWT does not support
   167     // key repeat events.
   171     // key repeat events.
   168     private Vector keysPressed;
   172     private Vector keysPressed;
   169 
       
   170     // Canvas modes
       
   171     private static final int MODE_UNINITIALIZED = 0;
       
   172     private static final int MODE_NORMAL = 1;
       
   173     private static final int MODE_BUFFER_FLUSH = 2;
       
   174     private static final int MODE_GAME_BUFFER_FLUSH = 3;
       
   175     private int canvasMode = MODE_UNINITIALIZED;
       
   176 
   173 
   177     private boolean suppressGameKeys;
   174     private boolean suppressGameKeys;
   178     private boolean suppressDragEvent;
   175     private boolean suppressDragEvent;
   179     private boolean cleanupNeeded;
   176     private boolean cleanupNeeded;
   180     private Object cleanupLock;
   177     private Object cleanupLock;
   181     private boolean noBackground;
   178     private boolean noBackground;
   182     private int gameKeyState;
   179     private int gameKeyState;
   183 
   180 
   184     private Graphics gameBufferGraphics;
       
   185 
       
   186     // lock created by graphics object for serializing
       
   187     // flushing against graphics buffer writing
       
   188     private Object flushLock;
       
   189 
       
   190     private Timer timer = new Timer();
   181     private Timer timer = new Timer();
   191     private CanvasTimerTask timerTask;
   182     private CanvasTimerTask timerTask;
   192 
   183 
   193     private static final int DEFAULT_TIMEOUT = 500;
   184     private static final int DEFAULT_TIMEOUT = 500;
   194     private static final int DEFAULT_TWIPS = 200;
   185     private static final int DEFAULT_TWIPS = 200;
   215     {
   206     {
   216         super(null);
   207         super(null);
   217         repaintLock = new Object();
   208         repaintLock = new Object();
   218         cleanupLock = new Object();
   209         cleanupLock = new Object();
   219         construct();
   210         construct();
   220         canvasGraphics = new Graphics();
       
   221         canvasMode = MODE_UNINITIALIZED;
       
   222         keysPressed = new Vector();
   211         keysPressed = new Vector();
       
   212         graphicsBuffer = new CanvasBuffer(this, getContentComp());
   223     }
   213     }
   224 
   214 
   225     /* (non-Javadoc)
   215     /* (non-Javadoc)
   226      * @see Displayable#eswtConstructShell(int)
   216      * @see Displayable#eswtConstructShell(int)
   227      */
   217      */
   626     {
   616     {
   627         this.suppressGameKeys = suppressKeys;
   617         this.suppressGameKeys = suppressKeys;
   628     }
   618     }
   629 
   619 
   630     /**
   620     /**
   631      * Update game buffer graphics.
       
   632      */
       
   633     final void eswtUpdateGameBufferGraphics()
       
   634     {
       
   635         if(gameBufferGraphics == null)
       
   636         {
       
   637             gameBufferGraphics = new Graphics();
       
   638             gameBufferGraphics.initBuffered(this, 0, 0, getWidth(), getHeight());
       
   639             flushLock = gameBufferGraphics.getLock();
       
   640         }
       
   641     }
       
   642 
       
   643     /**
       
   644      * Get game canvas frame buffer graphics.
   621      * Get game canvas frame buffer graphics.
   645      */
   622      */
   646     final Graphics getGameBufferGraphics()
   623     final Graphics getGameBufferGraphics()
   647     {
   624     {
   648         ESWTUIThreadRunner.safeSyncExec(new Runnable()
   625         return graphicsBuffer.getGraphics();
   649         {
       
   650             public void run()
       
   651             {
       
   652                 eswtUpdateGameBufferGraphics();
       
   653             }
       
   654         });
       
   655         return gameBufferGraphics;
       
   656     }
   626     }
   657 
   627 
   658     CanvasKeypad getCanvasKeypad()
   628     CanvasKeypad getCanvasKeypad()
   659     {
   629     {
   660         return onScreenkeypad;
   630         return onScreenkeypad;
   694      * @param height
   664      * @param height
   695      */
   665      */
   696     void flushGameBuffer(final int x, final int y, final int width,
   666     void flushGameBuffer(final int x, final int y, final int width,
   697                          final int height)
   667                          final int height)
   698     {
   668     {
   699         synchronized(flushLock)
   669         synchronized(graphicsBuffer)
   700         {
   670         {
   701             ESWTUIThreadRunner.safeSyncExec(new Runnable()
   671             flushGraphicsBuffer(x, y, width, height);
   702             {
       
   703                 public void run()
       
   704                 {
       
   705                     canvasMode = MODE_GAME_BUFFER_FLUSH;
       
   706                     ((CompositeExtension)getContentComp()).redrawNow(x, y, width, height);
       
   707                     gameBufferGraphics.resetCommandBuffer();
       
   708                     canvasMode = MODE_NORMAL;
       
   709                 }
       
   710             });
       
   711         }
   672         }
   712     }
   673     }
   713 
   674 
   714     /**
   675     /**
   715      * Called by ShellListener when shell gets activated.
   676      * Called by ShellListener when shell gets activated.
   718     {
   679     {
   719         super.handleShellActivatedEvent();
   680         super.handleShellActivatedEvent();
   720 
   681 
   721         // reset the game key state
   682         // reset the game key state
   722         gameKeyState = 0;
   683         gameKeyState = 0;
   723         canvasMode = MODE_NORMAL;
   684 
   724         synchronized(cleanupLock)
   685         synchronized(cleanupLock)
   725         {
   686         {
   726             cleanupNeeded = true;
   687             cleanupNeeded = true;
   727         }
   688         }
   728 
   689 
   744      * UI thread calls
   705      * UI thread calls
   745      */
   706      */
   746     void eswtHandleResizeEvent(int width, int height)
   707     void eswtHandleResizeEvent(int width, int height)
   747     {
   708     {
   748         super.eswtHandleResizeEvent(width, height);
   709         super.eswtHandleResizeEvent(width, height);
   749         canvasMode = MODE_NORMAL;
   710         // update new bounds to graphicsBuffer
       
   711         synchronized(graphicsBuffer)
       
   712         {
       
   713             graphicsBuffer.setControlBounds(getContentComp());
       
   714         }
   750         synchronized(cleanupLock)
   715         synchronized(cleanupLock)
   751         {
   716         {
   752             cleanupNeeded = true;
   717             cleanupNeeded = true;
   753         }
   718         }
   754     }
   719     }
   757      * UI thread calls
   722      * UI thread calls
   758      */
   723      */
   759     void eswtHandleEvent(Event e)
   724     void eswtHandleEvent(Event e)
   760     {
   725     {
   761         super.eswtHandleEvent(e);
   726         super.eswtHandleEvent(e);
   762 
       
   763         if(e.type == SWT.KeyDown)
   727         if(e.type == SWT.KeyDown)
   764         {
   728         {
   765             doKeyPressed(e.keyCode);
   729             doKeyPressed(e.keyCode);
   766         }
   730         }
   767         else if(e.type == SWT.KeyUp)
   731         else if(e.type == SWT.KeyUp)
   768         {
   732         {
   769             doKeyReleased(e.keyCode);
   733             doKeyReleased(e.keyCode);
   770         }
   734         }
   771 
       
   772     }
   735     }
   773 
   736 
   774     /*
   737     /*
   775      * UI thread calls. Paint listener of the eSWT widget.
   738      * UI thread calls. Paint listener of the eSWT widget.
   776      */
   739      */
   777     class CanvasShellPaintListener implements PaintListener
   740     class CanvasShellPaintListener implements PaintListener
   778     {
   741     {
   779 
   742 
   780         public void paintControl(PaintEvent pe)
   743         public void paintControl(PaintEvent pe)
   781         {
   744         {
   782             switch(canvasMode)
   745             // Native toolkit is requesting an update of an area that has
   783             {
   746             // become invalid. Can't do anything here because the contents
   784             case MODE_BUFFER_FLUSH:
   747             // need to be queried from the MIDlet in another thread by
   785                 // Paint event initiated by us to paint the Canvas.
   748             // a paint callback. For this a paint callback event is posted.
   786                 doBufferFlush(pe, canvasGraphics);
   749             // For a moment the native toolkit thinks that the area has
   787                 break;
   750             // been validated when in truth it will be painted later after
   788             case MODE_GAME_BUFFER_FLUSH:
   751             // the paint callback has been executed.
   789                 // Paint event initiated by us to paint the GameCanvas.
   752             EventDispatcher eventDispatcher = EventDispatcher.instance();
   790                 doBufferFlush(pe, gameBufferGraphics);
   753             LCDUIEvent event = eventDispatcher.newEvent(
   791                 break;
   754                                    LCDUIEvent.CANVAS_PAINT_NATIVE_REQUEST,
   792             case MODE_NORMAL:
   755                                    javax.microedition.lcdui.Canvas.this);
   793                 // Native toolkit is requesting an update of an area that has
   756             event.x = pe.x;
   794                 // become invalid. Can't do anything here because the contents
   757             event.y = pe.y;
   795                 // need to be queried from the MIDlet in another thread by
   758             event.width = pe.width;
   796                 // a paint callback. For this a paint callback event is posted.
   759             event.height = pe.height;
   797                 // For a moment the native toolkit thinks that the area has
   760             event.widget = pe.widget;
   798                 // been validated when in truth it will be painted later after
   761             eventDispatcher.postEvent(event);
   799                 // the paint callback has been executed.
       
   800                 EventDispatcher eventDispatcher = EventDispatcher.instance();
       
   801                 LCDUIEvent event = eventDispatcher.newEvent(
       
   802                                        LCDUIEvent.CANVAS_PAINT_NATIVE_REQUEST,
       
   803                                        javax.microedition.lcdui.Canvas.this);
       
   804                 event.x = pe.x;
       
   805                 event.y = pe.y;
       
   806                 event.width = pe.width;
       
   807                 event.height = pe.height;
       
   808                 event.widget = pe.widget;
       
   809                 eventDispatcher.postEvent(event);
       
   810                 break;
       
   811             }
       
   812         }
   762         }
   813     }
   763     }
   814 
   764 
   815     /*
   765     /*
   816      * Dispatcher thread or the serviceRepaints()-thread calls.
   766      * Dispatcher thread or the serviceRepaints()-thread calls.
   896             {
   846             {
   897                 return;
   847                 return;
   898             }
   848             }
   899         }
   849         }
   900 
   850 
   901         // Prepare the GC's buffer if not done yet
   851         // Create instance of Graphics if not created yet
   902         if(canvasGraphics.getCommandBuffer() == null)
   852         if(canvasGraphics == null)
   903         {
   853         {
   904             canvasGraphics.initBuffered(this, event.x, event.y, event.width, event.height);
   854             canvasGraphics = graphicsBuffer.getGraphics();
   905         }
   855         }
   906 
   856 
   907         // Clean the background if dirty, buffer the operations.
   857         // Clean the background if dirty, buffer the operations.
   908         synchronized(cleanupLock)
   858         synchronized(cleanupLock)
   909         {
   859         {
   925         canvasGraphics.setClip(redrawNowX, redrawNowY, redrawNowW, redrawNowH);
   875         canvasGraphics.setClip(redrawNowX, redrawNowY, redrawNowW, redrawNowH);
   926 
   876 
   927         // The callback
   877         // The callback
   928         paint(canvasGraphics);
   878         paint(canvasGraphics);
   929 
   879 
   930         // Wait until the UI thread is available. Then in the UI thread
   880 
   931         // synchronously send a paint event.
   881         // Flush drawn graphics to display
       
   882         synchronized(graphicsBuffer)
       
   883         {
       
   884             flushGraphicsBuffer(redrawNowX, redrawNowY, redrawNowW, redrawNowH);
       
   885         }
       
   886     }
       
   887 
       
   888     private void flushGraphicsBuffer(final int redrawNowX, final int redrawNowY, final int redrawNowW, final int redrawNowH)
       
   889     {
   932         ESWTUIThreadRunner.safeSyncExec(new Runnable()
   890         ESWTUIThreadRunner.safeSyncExec(new Runnable()
   933         {
   891         {
   934             public void run()
   892             public void run()
   935             {
   893             {
   936                 if(event.widget.isDisposed())
   894                 graphicsBuffer.setupWindowSurface();
   937                 {
   895                 Rectangle rect = graphicsBuffer.toWindowCoordinates(redrawNowX, redrawNowY, redrawNowW, redrawNowH);
   938                     return;
   896                 graphicsBuffer.windowSurface.beginPaint(rect.x, rect.y, rect.width, rect.height);
   939                 }
   897                 graphicsBuffer.sync();
   940 
   898                 graphicsBuffer.windowSurface.endPaint();
   941                 canvasMode = MODE_BUFFER_FLUSH;
   899                 graphicsBuffer.windowSurface.flush();
   942 
       
   943                 ((CompositeExtension) event.widget)
       
   944                 .redrawNow(redrawNowX, redrawNowY, redrawNowW, redrawNowH);
       
   945                 canvasGraphics.resetCommandBuffer();
       
   946                 canvasMode = MODE_NORMAL;
       
   947             }
   900             }
   948 
   901 
   949         });
   902         });
   950     }
   903     }
   951 
   904 
   952     /*
   905     /*
   953      * UI thread calls to flush the command buffer of a graphics context.
   906      * UI thread calls to flush the command buffer of a graphics context.
   954      */
   907      */
   955     private final void doBufferFlush(PaintEvent event, Graphics graphics)
   908     private final void doBufferFlush(PaintEvent event, Graphics graphics)
   956     {
   909     {
   957         event.gc.getGCData().internalGc.render(graphics.getCommandBuffer());
   910         //  event.gc.getGCData().internalGc.render(graphics.getCommandBuffer());
   958     }
   911     }
   959 
   912 
   960     /*
   913     /*
   961      * UI thread calls.
   914      * UI thread calls.
   962      */
   915      */
  1262         repaintY2 = repaintY2 < h ? repaintY2 : h;
  1215         repaintY2 = repaintY2 < h ? repaintY2 : h;
  1263 
  1216 
  1264         return valid;
  1217         return valid;
  1265     }
  1218     }
  1266 
  1219 
       
  1220     /**
       
  1221      * Disposes this instance
       
  1222      * Called when finalizer is destroying this instance.
       
  1223      */
       
  1224     void dispose()
       
  1225     {
       
  1226         super.dispose();
       
  1227         ESWTUIThreadRunner.safeSyncExec(new Runnable()
       
  1228         {
       
  1229             public void run()
       
  1230             {
       
  1231                 if(graphicsBuffer != null)
       
  1232                 {
       
  1233                     graphicsBuffer.dispose();
       
  1234                     graphicsBuffer = null;
       
  1235                 }
       
  1236             }
       
  1237         });
       
  1238     }
       
  1239 
  1267     class CanvasTimerTask extends TimerTask
  1240     class CanvasTimerTask extends TimerTask
  1268     {
  1241     {
  1269 
  1242 
  1270         public void run()
  1243         public void run()
  1271         {
  1244         {