1 /* GtkWindowPeer.java -- Implements WindowPeer with GTK
2 Copyright (C) 1998, 1999, 2002, 2005, 2006 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. */
39 package gnu.java.awt.peer.gtk;
41 import gnu.java.awt.ComponentReshapeEvent;
43 import java.awt.Component;
45 import java.awt.Frame;
46 import java.awt.Graphics;
47 import java.awt.KeyboardFocusManager;
48 import java.awt.Rectangle;
49 import java.awt.Window;
50 import java.awt.event.ComponentEvent;
51 import java.awt.event.FocusEvent;
52 import java.awt.event.PaintEvent;
53 import java.awt.event.WindowEvent;
54 import java.awt.peer.WindowPeer;
56 public class GtkWindowPeer extends GtkContainerPeer
59 protected static final int GDK_WINDOW_TYPE_HINT_NORMAL = 0;
60 protected static final int GDK_WINDOW_TYPE_HINT_DIALOG = 1;
61 protected static final int GDK_WINDOW_TYPE_HINT_MENU = 2;
62 protected static final int GDK_WINDOW_TYPE_HINT_TOOLBAR = 3;
63 protected static final int GDK_WINDOW_TYPE_HINT_SPLASHSCREEN = 4;
64 protected static final int GDK_WINDOW_TYPE_HINT_UTILITY = 5;
65 protected static final int GDK_WINDOW_TYPE_HINT_DOCK = 6;
66 protected static final int GDK_WINDOW_TYPE_HINT_DESKTOP = 7;
68 protected int windowState = Frame.NORMAL;
70 // Cached awt window component location, width and height.
71 private int x, y, width, height;
73 native void gtkWindowSetTitle (String title);
74 native void gtkWindowSetResizable (boolean resizable);
75 native void gtkWindowSetModal (boolean modal);
76 native void gtkWindowSetAlwaysOnTop ( boolean alwaysOnTop );
77 native boolean gtkWindowHasFocus();
78 native void realize ();
83 GtkMainThread.destroyWindow();
86 /** Returns the cached width of the AWT window component. */
92 /** Returns the cached width of the AWT window component. */
98 /** Returns the cached width of the AWT window component. */
104 /** Returns the cached height of the AWT window component. */
110 native void create (int type, boolean decorated, GtkWindowPeer parent);
112 void create (int type, boolean decorated)
114 Window window = (Window) awtComponent;
115 GtkWindowPeer parent_peer = null;
116 Component parent = awtComponent.getParent();
117 x = awtComponent.getX();
118 y = awtComponent.getY();
119 height = awtComponent.getHeight();
120 width = awtComponent.getWidth();
122 if (!window.isFocusableWindow())
123 type = GDK_WINDOW_TYPE_HINT_MENU;
126 parent_peer = (GtkWindowPeer) awtComponent.getParent().getPeer();
128 create (type, decorated, parent_peer);
133 // Create a normal undecorated window.
134 create (GDK_WINDOW_TYPE_HINT_NORMAL, false);
139 setVisible (awtComponent.isVisible ());
140 setEnabled (awtComponent.isEnabled ());
143 void setVisibleAndEnabled ()
147 public native void setVisibleNative (boolean b);
148 public native void setVisibleNativeUnlocked (boolean b);
150 native void connectSignals ();
152 public GtkWindowPeer (Window window)
155 // Set reasonable font for the window.
156 window.setFont(new Font("Dialog", Font.PLAIN, 12));
159 public native void toBack();
160 public native void toFront();
162 native void nativeSetBounds (int x, int y, int width, int height);
163 native void nativeSetBoundsUnlocked (int x, int y, int width, int height);
164 native void nativeSetLocation (int x, int y);
165 native void nativeSetLocationUnlocked (int x, int y);
168 protected void setLocation (int x, int y)
170 nativeSetLocation (x, y);
173 public void setBounds (int x, int y, int width, int height)
177 || width != getWidth()
178 || height != getHeight())
183 this.height = height;
185 nativeSetBounds (x, y,
186 width - insets.left - insets.right,
187 height - insets.top - insets.bottom);
191 public void setTitle (String title)
193 gtkWindowSetTitle (title);
196 // Called from setResizable
197 protected native void setSize (int width, int height);
200 * Needed by both GtkFramePeer and GtkDialogPeer subclasses, so
201 * implemented here. But never actually called on a GtkWindowPeer
204 public void setResizable (boolean resizable)
206 // Call setSize; otherwise when resizable is changed from true to
207 // false the window will shrink to the dimensions it had before it
209 x = awtComponent.getX();
210 y = awtComponent.getY();
211 width = awtComponent.getWidth();
212 height = awtComponent.getHeight();
213 setSize (width - insets.left - insets.right,
214 height - insets.top - insets.bottom);
215 gtkWindowSetResizable (resizable);
218 protected void postInsetsChangedEvent (int top, int left,
219 int bottom, int right)
223 insets.bottom = bottom;
224 insets.right = right;
227 // called back by native side: window_configure_cb
228 // only called from GTK thread
229 protected void postConfigureEvent (int x, int y, int width, int height)
231 int frame_x = x - insets.left;
232 int frame_y = y - insets.top;
233 int frame_width = width + insets.left + insets.right;
234 int frame_height = height + insets.top + insets.bottom;
236 // Update the component's knowledge about the size.
237 // Important: Please look at the big comment in ComponentReshapeEvent
238 // to learn why we did it this way. If you change this code, make
239 // sure that the peer->AWT bounds update still works.
240 // (for instance: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29448 )
242 // We do this befor we post the ComponentEvent, because (in Window)
243 // we invalidate() / revalidate() when a ComponentEvent is seen,
244 // and the AWT must already know about the new size then.
245 if (frame_x != this.x || frame_y != this.y || frame_width != this.width
246 || frame_height != this.height)
248 ComponentReshapeEvent ev = new ComponentReshapeEvent(awtComponent,
253 awtComponent.dispatchEvent(ev);
256 if (frame_width != getWidth()
257 || frame_height != getHeight())
259 this.width = frame_width;
260 this.height = frame_height;
261 q().postEvent(new ComponentEvent(awtComponent,
262 ComponentEvent.COMPONENT_RESIZED));
265 if (frame_x != getX()
266 || frame_y != getY())
270 q().postEvent(new ComponentEvent(awtComponent,
271 ComponentEvent.COMPONENT_MOVED));
278 x = awtComponent.getX();
279 y = awtComponent.getY();
280 width = awtComponent.getWidth();
281 height = awtComponent.getHeight();
286 void postWindowEvent (int id, Window opposite, int newState)
288 if (id == WindowEvent.WINDOW_STATE_CHANGED)
290 if (windowState != newState)
292 // Post old styleWindowEvent with WINDOW_ICONIFIED or
293 // WINDOW_DEICONIFIED if appropriate.
294 if ((windowState & Frame.ICONIFIED) != 0
295 && (newState & Frame.ICONIFIED) == 0)
296 q().postEvent(new WindowEvent((Window) awtComponent,
297 WindowEvent.WINDOW_DEICONIFIED,
299 else if ((windowState & Frame.ICONIFIED) == 0
300 && (newState & Frame.ICONIFIED) != 0)
301 q().postEvent(new WindowEvent((Window) awtComponent,
302 WindowEvent.WINDOW_ICONIFIED,
304 // Post new-style WindowStateEvent.
305 q().postEvent (new WindowEvent ((Window) awtComponent, id,
306 opposite, windowState, newState));
307 windowState = newState;
311 q().postEvent (new WindowEvent ((Window) awtComponent, id, opposite));
315 * Update the always-on-top status of the native window.
317 public void updateAlwaysOnTop()
319 gtkWindowSetAlwaysOnTop( ((Window)awtComponent).isAlwaysOnTop() );
322 protected void postExposeEvent (int x, int y, int width, int height)
324 // Translate GTK co-ordinates, which do not include a window
325 // frame's insets, to AWT co-ordinates, which do include a window
326 // frame's insets. GtkWindowPeer should always have all-zero
327 // insets but GtkFramePeer and GtkDialogPeer insets will be
329 q().postEvent (new PaintEvent (awtComponent, PaintEvent.PAINT,
330 new Rectangle (x + insets.left,
335 public boolean requestWindowFocus()
337 // TODO Auto-generated method stub
341 public boolean requestFocus (Component request, boolean temporary,
342 boolean allowWindowFocus, long time)
344 assert request == awtComponent || isLightweightDescendant(request);
345 boolean retval = false;
346 if (gtkWindowHasFocus())
348 KeyboardFocusManager kfm =
349 KeyboardFocusManager.getCurrentKeyboardFocusManager();
350 Component currentFocus = kfm.getFocusOwner();
351 if (currentFocus == request)
352 // Nothing to do in this trivial case.
356 // Requested component is a lightweight descendant of this one
357 // or the actual heavyweight.
358 // Since this (native) component is already focused, we simply
359 // change the actual focus and be done.
360 postFocusEvent(FocusEvent.FOCUS_GAINED, temporary);
366 if (allowWindowFocus)
368 retval = requestWindowFocus();
374 public Graphics getGraphics ()
376 Graphics g = super.getGraphics ();
377 // Translate AWT co-ordinates, which include a window frame's
378 // insets, to GTK co-ordinates, which do not include a window
379 // frame's insets. GtkWindowPeer should always have all-zero
380 // insets but GtkFramePeer and GtkDialogPeer insets will be
382 g.translate (-insets.left, -insets.top);
386 protected void postMouseEvent(int id, long when, int mods, int x, int y,
387 int clickCount, boolean popupTrigger)
389 // Translate AWT co-ordinates, which include a window frame's
390 // insets, to GTK co-ordinates, which do not include a window
391 // frame's insets. GtkWindowPeer should always have all-zero
392 // insets but GtkFramePeer and GtkDialogPeer insets will be
394 super.postMouseEvent (id, when, mods,
395 x + insets.left, y + insets.top,
396 clickCount, popupTrigger);
399 // We override this to keep it in sync with our internal
401 public Rectangle getBounds()
403 return new Rectangle(x, y, width, height);