1 /* QtComponentPeer.java --
2 Copyright (C) 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
38 package gnu
.java
.awt
.peer
.qt
;
40 import java
.awt
.AWTEvent
;
41 import java
.awt
.AWTException
;
42 import java
.awt
.BufferCapabilities
;
43 import java
.awt
.Component
;
44 import java
.awt
.Container
;
45 import java
.awt
.Color
;
46 import java
.awt
.Cursor
;
47 import java
.awt
.Dimension
;
49 import java
.awt
.FontMetrics
;
50 import java
.awt
.Image
;
51 import java
.awt
.Graphics
;
52 import java
.awt
.Graphics2D
;
53 import java
.awt
.GraphicsConfiguration
;
54 import java
.awt
.GraphicsDevice
;
55 import java
.awt
.KeyboardFocusManager
;
56 import java
.awt
.Point
;
57 import java
.awt
.Rectangle
;
58 import java
.awt
.Toolkit
;
59 import java
.awt
.Window
;
60 import java
.awt
.peer
.ComponentPeer
;
61 import java
.awt
.peer
.ContainerPeer
;
62 import java
.awt
.image
.ColorModel
;
63 import java
.awt
.image
.VolatileImage
;
64 import java
.awt
.image
.ImageObserver
;
65 import java
.awt
.image
.ImageProducer
;
66 import java
.awt
.event
.ComponentEvent
; // 100%
67 import java
.awt
.event
.FocusEvent
; // 100%
68 import java
.awt
.event
.InputEvent
; // (abstract)
69 import java
.awt
.event
.KeyEvent
; // 2/3
70 import java
.awt
.event
.MouseEvent
; // 70%?
71 import java
.awt
.event
.PaintEvent
; // Yup.
72 import java
.awt
.event
.WindowEvent
; // 2/ 12
73 import java
.util
.Timer
;
74 import java
.util
.TimerTask
;
76 public class QtComponentPeer
extends NativeWrapper
implements ComponentPeer
80 * Popup trigger button, may differ between platforms
82 protected static final int POPUP_TRIGGER
= 3;
85 * The toolkit which manufactured this peer.
87 protected QtToolkit toolkit
;
90 * The component which owns this peer.
95 * Classpath updates our eventMask.
97 private long eventMask
;
100 * if the thing has mouse motion listeners or not.
102 private boolean hasMotionListeners
;
105 * The component's double buffer for off-screen drawing.
107 protected QtImage backBuffer
;
109 protected long qtApp
;
111 private boolean settingUp
;
113 private boolean ignoreResize
= false;
115 QtComponentPeer( QtToolkit kit
, Component owner
)
119 qtApp
= QtToolkit
.guiThread
.QApplicationPointer
;
123 callInit(); // Calls the init method FROM THE MAIN THREAD.
126 wait(); // Wait for the thing to be created.
128 catch(InterruptedException e
)
133 hasMotionListeners
= false;
136 protected native void callInit();
139 * Init does the creation of native widgets, it is therefore
140 * called from the main thread. (the constructor waits for this to happen.)
142 protected void init()
146 protected void setup()
151 if (owner
instanceof javax
.swing
.JComponent
)
152 setBackground(owner
.getBackground());
154 owner
.setBackground(getNativeBackground());
156 if (owner
.getForeground() != null)
157 setForeground(owner
.getForeground());
159 setForeground( Color
.black
);
161 if (owner
.getCursor() != null)
162 if (owner
.getCursor().getType() != Cursor
.DEFAULT_CURSOR
)
163 setCursor(owner
.getCursor());
165 if (owner
.getFont() != null)
166 setFont(owner
.getFont());
168 setEnabled( owner
.isEnabled() );
173 setVisible( owner
.isVisible() );
174 QtToolkit
.repaintThread
.queueComponent(this);
179 native void QtUpdate();
180 native void QtUpdateArea( int x
, int y
, int w
, int h
);
181 private synchronized native void disposeNative();
182 private native void setGround( int r
, int g
, int b
, boolean isForeground
);
183 private native void setBoundsNative( int x
, int y
, int width
, int height
);
184 private native void setCursor( int ctype
);
185 private native Color
getNativeBackground();
186 private native void setFontNative( QtFontPeer fp
);
187 private native int whichScreen();
188 private native void reparentNative( QtContainerPeer parent
);
189 private native void getLocationOnScreenNative( Point p
);
191 private boolean drawableComponent()
193 return ((this instanceof QtContainerPeer
&&
194 !(this instanceof QtScrollPanePeer
)) ||
195 (this instanceof QtCanvasPeer
));
200 Rectangle r
= owner
.getBounds();
201 setBounds( r
.x
, r
.y
, r
.width
, r
.height
);
204 synchronized void updateBackBuffer(int width
, int height
)
206 if(width
<= 0 || height
<= 0)
209 if( !drawableComponent() && backBuffer
== null)
212 if( backBuffer
!= null )
214 if( width
< backBuffer
.width
&& height
< backBuffer
.height
)
216 backBuffer
.dispose();
218 backBuffer
= new QtImage(width
, height
);
222 // ************ Event methods *********************
225 * Window closing event
227 protected void closeEvent()
229 if (owner
instanceof Window
)
231 WindowEvent e
= new WindowEvent((Window
)owner
,
232 WindowEvent
.WINDOW_CLOSING
);
233 QtToolkit
.eventQueue
.postEvent(e
);
237 protected void enterEvent(int modifiers
, int x
, int y
, int dummy
)
239 MouseEvent e
= new MouseEvent(owner
,
240 MouseEvent
.MOUSE_ENTERED
,
241 System
.currentTimeMillis(),
242 (modifiers
& 0x2FF), x
, y
, 0, false);
243 QtToolkit
.eventQueue
.postEvent(e
);
246 protected void focusInEvent()
248 FocusEvent e
= new FocusEvent(owner
, FocusEvent
.FOCUS_GAINED
);
249 QtToolkit
.eventQueue
.postEvent(e
);
252 protected void focusOutEvent()
254 FocusEvent e
= new FocusEvent(owner
, FocusEvent
.FOCUS_LOST
);
255 QtToolkit
.eventQueue
.postEvent(e
);
258 protected void keyPressEvent(int modifiers
, int code
, int unicode
, int dummy
)
260 KeyboardFocusManager manager
= KeyboardFocusManager
.getCurrentKeyboardFocusManager ();
261 KeyEvent e
= new KeyEvent(owner
,
262 KeyEvent
.KEY_PRESSED
,
263 System
.currentTimeMillis(),
264 modifiers
, code
, (char)(unicode
& 0xFFFF),
265 KeyEvent
.KEY_LOCATION_UNKNOWN
);
266 if (!manager
.dispatchEvent (e
))
267 QtToolkit
.eventQueue
.postEvent(e
);
270 protected void keyReleaseEvent(int modifiers
, int code
, int unicode
, int dummy
)
272 KeyEvent e
= new KeyEvent(owner
,
273 KeyEvent
.KEY_RELEASED
,
274 System
.currentTimeMillis(),
275 modifiers
, code
, (char)(unicode
& 0xFFFF),
276 KeyEvent
.KEY_LOCATION_UNKNOWN
);
277 QtToolkit
.eventQueue
.postEvent(e
);
280 protected void leaveEvent(int modifiers
, int x
, int y
, int dummy
)
282 MouseEvent e
= new MouseEvent(owner
,
283 MouseEvent
.MOUSE_EXITED
,
284 System
.currentTimeMillis(),
285 (modifiers
& 0x2FF), x
, y
, 0, false);
286 QtToolkit
.eventQueue
.postEvent(e
);
289 // FIXME: Coalesce press-release events into clicks.
290 protected void mouseDoubleClickEvent( int modifiers
, int x
, int y
, int clickCount
)
292 if( (eventMask
& AWTEvent
.MOUSE_EVENT_MASK
) == 0 )
295 if((modifiers
& InputEvent
.BUTTON1_DOWN_MASK
) ==
296 InputEvent
.BUTTON1_DOWN_MASK
) button
= 1;
297 if((modifiers
& InputEvent
.BUTTON2_DOWN_MASK
) ==
298 InputEvent
.BUTTON2_DOWN_MASK
) button
= 2;
299 if((modifiers
& InputEvent
.BUTTON3_DOWN_MASK
) ==
300 InputEvent
.BUTTON3_DOWN_MASK
) button
= 3;
301 MouseEvent e
= new MouseEvent(owner
,
302 MouseEvent
.MOUSE_CLICKED
,
303 System
.currentTimeMillis(),
304 (modifiers
& 0x2FF), x
, y
, clickCount
,
306 QtToolkit
.eventQueue
.postEvent(e
);
309 protected void mouseMoveEvent( int modifiers
, int x
, int y
, int clickCount
)
311 if( (eventMask
& AWTEvent
.MOUSE_EVENT_MASK
) == 0 )
315 if((modifiers
& InputEvent
.BUTTON1_DOWN_MASK
) ==
316 InputEvent
.BUTTON1_DOWN_MASK
) button
= 1;
317 if((modifiers
& InputEvent
.BUTTON2_DOWN_MASK
) ==
318 InputEvent
.BUTTON2_DOWN_MASK
) button
= 2;
319 if((modifiers
& InputEvent
.BUTTON3_DOWN_MASK
) ==
320 InputEvent
.BUTTON3_DOWN_MASK
) button
= 3;
322 int type
= (button
!= 0) ?
323 MouseEvent
.MOUSE_DRAGGED
:MouseEvent
.MOUSE_MOVED
;
325 MouseEvent e
= new MouseEvent(owner
,
327 System
.currentTimeMillis(),
328 (modifiers
& 0x2FF), x
, y
, clickCount
,
330 QtToolkit
.eventQueue
.postEvent(e
);
333 protected void mousePressEvent( int modifiers
, int x
, int y
, int clickCount
)
335 if( (eventMask
& AWTEvent
.MOUSE_EVENT_MASK
) == 0 )
338 if((modifiers
& InputEvent
.BUTTON1_DOWN_MASK
) ==
339 InputEvent
.BUTTON1_DOWN_MASK
) button
= 1;
340 if((modifiers
& InputEvent
.BUTTON2_DOWN_MASK
) ==
341 InputEvent
.BUTTON2_DOWN_MASK
) button
= 2;
342 if((modifiers
& InputEvent
.BUTTON3_DOWN_MASK
) ==
343 InputEvent
.BUTTON3_DOWN_MASK
) button
= 3;
344 MouseEvent e
= new MouseEvent(owner
,
345 MouseEvent
.MOUSE_PRESSED
,
346 System
.currentTimeMillis(),
347 (modifiers
& 0x2FF), x
, y
, clickCount
,
348 ( button
== POPUP_TRIGGER
),
350 QtToolkit
.eventQueue
.postEvent(e
);
353 protected void mouseReleaseEvent( int modifiers
, int x
, int y
, int clickCount
)
355 if( (eventMask
& AWTEvent
.MOUSE_EVENT_MASK
) == 0 )
358 if((modifiers
& InputEvent
.BUTTON1_DOWN_MASK
) ==
359 InputEvent
.BUTTON1_DOWN_MASK
) button
= 1;
360 if((modifiers
& InputEvent
.BUTTON2_DOWN_MASK
) ==
361 InputEvent
.BUTTON2_DOWN_MASK
) button
= 2;
362 if((modifiers
& InputEvent
.BUTTON3_DOWN_MASK
) ==
363 InputEvent
.BUTTON3_DOWN_MASK
) button
= 3;
365 MouseEvent e
= new MouseEvent(owner
,
366 MouseEvent
.MOUSE_RELEASED
,
367 System
.currentTimeMillis(),
368 (modifiers
& 0x2FF), x
, y
, clickCount
,
370 QtToolkit
.eventQueue
.postEvent(e
);
373 protected void moveEvent(int x
, int y
, int oldx
, int oldy
)
377 // Since Component.setLocation calls back to setBounds,
378 // we need to ignore that.
380 owner
.setLocation( x
, y
);
381 ignoreResize
= false;
385 protected void resizeEvent(int oldWidth
, int oldHeight
,
386 int width
, int height
)
388 if(!(owner
instanceof Window
))
390 updateBackBuffer(width
, height
);
392 owner
.setSize(width
, height
);
393 ignoreResize
= false;
394 ComponentEvent e
= new ComponentEvent(owner
,
395 ComponentEvent
.COMPONENT_RESIZED
);
396 QtToolkit
.eventQueue
.postEvent(e
);
397 QtToolkit
.repaintThread
.queueComponent(this);
400 protected void showEvent()
402 if (owner
instanceof Window
)
404 WindowEvent e
= new WindowEvent((Window
)owner
,
405 WindowEvent
.WINDOW_OPENED
);
406 QtToolkit
.eventQueue
.postEvent(e
);
410 ComponentEvent e
= new ComponentEvent(owner
,
411 ComponentEvent
.COMPONENT_SHOWN
);
412 QtToolkit
.eventQueue
.postEvent(e
);
416 protected void hideEvent()
418 ComponentEvent e
= new ComponentEvent(owner
,
419 ComponentEvent
.COMPONENT_HIDDEN
);
420 QtToolkit
.eventQueue
.postEvent(e
);
423 // ************ Public methods *********************
425 /** Classpath-specific method */
426 public void setEventMask(long x
)
432 public boolean canDetermineObscurity()
437 public int checkImage(Image img
,
442 return toolkit
.checkImage(img
, w
, h
, o
);
445 public void createBuffers(int numBuffers
, BufferCapabilities caps
)
451 public Image
createImage(ImageProducer producer
)
453 return toolkit
.createImage(producer
);
456 public Image
createImage(int width
, int height
)
458 return new QtImage(width
, height
);
461 public void coalescePaintEvent(PaintEvent e
)
466 public VolatileImage
createVolatileImage(int w
, int h
)
468 return new QtVolatileImage( w
, h
);
471 public void destroyBuffers()
476 public void disable()
481 public void dispose()
484 if( backBuffer
!= null )
485 backBuffer
.dispose();
493 public void finalize()
498 public void flip(BufferCapabilities
.FlipContents contents
)
502 public Image
getBackBuffer()
507 public ColorModel
getColorModel()
509 return toolkit
.getColorModel();
512 public FontMetrics
getFontMetrics(Font font
)
514 return new QtFontMetrics( font
, getGraphics() );
517 public Graphics
getGraphics()
519 if( backBuffer
== null )
521 Rectangle r
= owner
.getBounds();
522 backBuffer
= new QtImage( r
.width
, r
.height
);
524 return backBuffer
.getDirectGraphics( this );
527 public GraphicsConfiguration
getGraphicsConfiguration()
529 int id
= whichScreen(); // get the ID of the screen the widget is on.
530 GraphicsDevice
[] devs
= QtToolkit
.graphicsEnv
.getScreenDevices();
531 return devs
[id
].getDefaultConfiguration();
534 public Point
getLocationOnScreen()
536 Point p
= new Point();
539 getLocationOnScreenNative( p
);
542 p
.wait(); // Wait for the thing to be created.
544 catch(InterruptedException e
)
551 private native void getSizeNative(Dimension d
, boolean preferred
);
553 private Dimension
getSize(boolean preferred
)
555 Dimension d
= new Dimension();
558 getSizeNative(d
, preferred
);
561 d
.wait(); // Wait for the thing to be created.
563 catch(InterruptedException e
)
570 public Dimension
getMinimumSize()
572 return getSize( false );
575 public Dimension
getPreferredSize()
577 return getSize( true );
580 public Toolkit
getToolkit()
585 public native boolean handlesWheelScrolling();
592 public native boolean isFocusable();
594 public boolean isFocusTraversable()
600 public native boolean isObscured();
602 public Dimension
minimumSize()
604 return getMinimumSize();
607 public Dimension
preferredSize()
609 return getPreferredSize();
612 public native void requestFocus();
614 public boolean requestFocus (Component source
, boolean bool1
,
615 boolean bool2
, long x
)
621 public void reshape(int x
,
626 setBounds( x
, y
, width
, height
);
629 public void setBackground(Color c
)
631 if(c
== null && !settingUp
)
633 setGround(c
.getRed(), c
.getGreen(), c
.getBlue(), false);
636 public void setBounds(int x
, int y
, int width
, int height
)
640 updateBackBuffer(width
, height
);
641 QtToolkit
.repaintThread
.queueComponent(this);
642 setBoundsNative(x
, y
, width
, height
);
645 public void setCursor(Cursor cursor
)
648 setCursor(cursor
.getType());
651 public native void setEnabled(boolean b
);
653 public void setFont(Font f
)
655 if( f
== null || f
.getPeer() == null)
656 throw new IllegalArgumentException("Null font.");
657 setFontNative( (QtFontPeer
)f
.getPeer() );
660 public void setForeground(Color c
)
662 if(c
== null && !settingUp
)
664 setGround(c
.getRed(), c
.getGreen(), c
.getBlue(), true);
667 public native void setVisible(boolean b
);
674 public void handleEvent (AWTEvent e
)
676 int eventID
= e
.getID();
681 case ComponentEvent
.COMPONENT_SHOWN
:
682 QtToolkit
.repaintThread
.queueComponent(this);
684 case PaintEvent
.PAINT
:
685 case PaintEvent
.UPDATE
:
686 r
= ((PaintEvent
)e
).getUpdateRect();
687 QtToolkit
.repaintThread
.queueComponent(this, r
.x
, r
.y
,
690 case KeyEvent
.KEY_PRESSED
:
692 case KeyEvent
.KEY_RELEASED
:
698 * paint() is called back from the native side in response to a native
701 public void paint(Graphics g
)
703 Rectangle r
= g
.getClipBounds();
705 if (backBuffer
!= null)
706 backBuffer
.drawPixelsScaledFlipped ((QtGraphics
) g
,
707 0, 0, 0, /* bg colors */
708 false, false, /* no flipping */
709 r
.x
, r
.y
, r
.width
, r
.height
,
710 r
.x
, r
.y
, r
.width
, r
.height
,
711 false ); /* no compositing */
714 public void paintBackBuffer() throws InterruptedException
716 if( backBuffer
!= null )
719 Graphics2D bbg
= (Graphics2D
)backBuffer
.getGraphics();
725 public void paintBackBuffer(int x
, int y
, int w
, int h
)
726 throws InterruptedException
728 if( backBuffer
!= null )
730 Graphics2D bbg
= (Graphics2D
)backBuffer
.getGraphics();
731 bbg
.setBackground( getNativeBackground() );
732 bbg
.clearRect(x
, y
, w
, h
);
733 bbg
.setClip(x
, y
, w
, h
);
739 public boolean prepareImage(Image img
,
744 return toolkit
.prepareImage(img
, w
, h
, o
);
747 public void print(Graphics g
)
753 * Schedules a timed repaint.
755 public void repaint(long tm
,
763 QtToolkit
.repaintThread
.queueComponent(this, x
, y
, w
, h
);
766 Timer t
= new Timer();
767 t
.schedule(new RepaintTimerTask(this, x
, y
, w
, h
), tm
);
771 * Update the cursor (note that setCursor is usually not called)
773 public void updateCursorImmediately()
775 if (owner
.getCursor() != null)
776 setCursor(owner
.getCursor().getType());
782 private class RepaintTimerTask
extends TimerTask
784 private int x
, y
, w
, h
;
785 private QtComponentPeer peer
;
786 RepaintTimerTask(QtComponentPeer peer
, int x
, int y
, int w
, int h
)
796 QtToolkit
.repaintThread
.queueComponent(peer
, x
, y
, w
, h
);
800 public native Rectangle
getBounds();
802 public void reparent(ContainerPeer parent
)
804 if(!(parent
instanceof QtContainerPeer
))
805 throw new IllegalArgumentException("Illegal peer.");
806 reparentNative((QtContainerPeer
)parent
);
809 public void setBounds(int x
, int y
, int width
, int height
, int z
)
811 // TODO Auto-generated method stub
815 public boolean isReparentSupported()
820 // What does this do, anyway?
823 // TODO Auto-generated method stub