001: /*
002: * @(#)GWindowPeer.java 1.24 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package sun.awt.gtk;
029:
030: import sun.awt.peer.WindowPeer;
031: import java.awt.*;
032: import java.awt.event.*;
033:
034: /**
035: * GWindowPeer.java
036: *
037: * @author Nicholas Allen
038: */
039:
040: class GWindowPeer extends GPanelPeer implements WindowPeer {
041: private static native void initIDs();
042:
043: private static int defaultLeftBorder = 0;
044: private static int defaultRightBorder = 0;
045: private static int defaultTopBorder = 0;
046: private static int defaultBottomBorder = 0;
047:
048: static {
049: initIDs();
050: }
051:
052: GWindowPeer(GToolkit toolkit, Window target) {
053: super (toolkit, target);
054:
055: Window owner = (Window) target.getParent();
056:
057: if (owner != null) {
058: GWindowPeer ownerPeer = (GWindowPeer) GToolkit
059: .getComponentPeer(owner);
060:
061: if (ownerPeer != null)
062: setOwner(ownerPeer);
063: }
064:
065: if (!initializedBorders) {
066: initBorders();
067: initializedBorders = true;
068: }
069:
070: insets = calculateInsets();
071: currentFocusComponent = target;
072: }
073:
074: protected native void create();
075:
076: public native void toFront();
077:
078: public native void toBack();
079:
080: public native void setResizable(boolean resizeable);
081:
082: /** This is overridden to set the bounds on the window manager's frame. */
083:
084: public void setBounds(int x, int y, int w, int h) {
085: if (!initializedBorders) {
086: initBorders();
087: initializedBorders = true;
088: }
089:
090: setBoundsNative(x, y,
091: Math.max(w - leftBorder - rightBorder, 0), Math.max(h
092: - topBorder - bottomBorder, 0));
093: }
094:
095: /** Sets the bounds for the X window for this widget. */
096:
097: protected native void setBoundsNative(int x, int y, int w, int h);
098:
099: public Graphics getGraphics() {
100: Graphics g = super .getGraphics();
101:
102: if (g != null)
103: g.translate(-leftBorder, -topBorder);
104:
105: return g;
106: }
107:
108: /** This is necessary to make sure the window manager's X window is in the correct place
109: after showing the window. It's not very elegant but it seems to be the only way to get
110: the right size and position of the actual outer frame under Gtk with any window manager. */
111:
112: public void show() {
113: super .show();
114: Rectangle bounds = target.getBounds();
115: setBounds(bounds.x, bounds.y, bounds.width, bounds.height);
116: }
117:
118: public Point getLocationOnScreen() {
119: Point point = super .getLocationOnScreen();
120: point.x -= leftBorder;
121: point.y -= topBorder;
122: return point;
123: }
124:
125: void postPaintEvent(int x, int y, int width, int height) {
126: super .postPaintEvent(x + leftBorder, y + topBorder, width,
127: height);
128: }
129:
130: void postMouseEvent(int id, long when, int modifiers, int x, int y,
131: int clickCount, boolean popupTrigger, int nativeEvent) {
132: super .postMouseEvent(id, when, modifiers, x + leftBorder, y
133: + topBorder, clickCount, popupTrigger, nativeEvent);
134: }
135:
136: /**
137: * Called to inform the Frame that its size has changed and it
138: * should layout its children.
139: */
140:
141: private void postResizedEvent() {
142: GToolkit.postEvent(new ComponentEvent(target,
143: ComponentEvent.COMPONENT_RESIZED));
144: }
145:
146: private void postMovedEvent() {
147: GToolkit.postEvent(new ComponentEvent(target,
148: ComponentEvent.COMPONENT_MOVED));
149: }
150:
151: /** Posts the required window event to the queue. */
152:
153: protected void postWindowEvent(int type) {
154:
155: // Gtk does not post focus events when the window becomes activated/deactivated so
156: // it is necessary to do this here.
157:
158: if (type == WindowEvent.WINDOW_ACTIVATED) {
159: if (!postedActivatedEvent) {
160: GToolkit.postEvent(new WindowEvent((Window) target,
161: type));
162: GToolkit
163: .postEvent(new FocusEvent(
164: currentFocusComponent,
165: FocusEvent.FOCUS_GAINED));
166: postedActivatedEvent = true;
167: }
168: }
169:
170: else if (type == WindowEvent.WINDOW_DEACTIVATED) {
171: if (postedActivatedEvent) {
172: GToolkit.postEvent(new WindowEvent((Window) target,
173: type));
174: GToolkit.postEvent(new FocusEvent(
175: currentFocusComponent, FocusEvent.FOCUS_LOST,
176: true));
177: postedActivatedEvent = false;
178: }
179: }
180:
181: else
182: GToolkit.postEvent(new WindowEvent((Window) target, type));
183: }
184:
185: /** This has been overridden because calling gtk_widget_grab_focus on a window does not take
186: focus away from a component. We have to explicity set the focus component to NULL using
187: gtk_window_set_focus. */
188:
189: public native void requestFocus();
190:
191: /** Called by the native code when the focus has moved from one component to another
192: inside this window. Note that this may be called even when the window is not activated
193: so we can't always post focus gained events to the current focus component. If no component
194: has the focus in this window then this method is called with this window as the new focus
195: component. */
196:
197: private void focusChanged(GComponentPeer newFocusPeer) {
198:
199: Component newFocusComponent = newFocusPeer.target;
200:
201: if (newFocusComponent != currentFocusComponent) {
202:
203: GToolkit.postEvent(new FocusEvent(currentFocusComponent,
204: FocusEvent.FOCUS_LOST));
205:
206: if (postedActivatedEvent) {
207: GToolkit.postEvent(new FocusEvent(newFocusComponent,
208: FocusEvent.FOCUS_GAINED));
209: }
210:
211: currentFocusComponent = newFocusComponent;
212: }
213: }
214:
215: private void updateInsets() {
216: insets = calculateInsets();
217: }
218:
219: /** Calculates the insets using any values appropriate (such as borders). */
220:
221: Insets calculateInsets() {
222: return new Insets(topBorder, leftBorder, bottomBorder,
223: rightBorder);
224: }
225:
226: /** Sets up border values to some sensible values for this window. */
227:
228: void initBorders() {
229: topBorder = defaultTopBorder;
230: leftBorder = defaultLeftBorder;
231: bottomBorder = defaultBottomBorder;
232: rightBorder = defaultRightBorder;
233: }
234:
235: /** Sets the default border values to be used for future windows. */
236:
237: void setDefaultBorders(int top, int left, int bottom, int right) {
238: defaultTopBorder = top;
239: defaultLeftBorder = left;
240: defaultBottomBorder = bottom;
241: defaultRightBorder = right;
242: }
243:
244: private native void setOwner(GWindowPeer owner);
245:
246: int getOriginX() {
247: return -leftBorder;
248: }
249:
250: int getOriginY() {
251: return -topBorder;
252: }
253:
254: int topBorder, leftBorder, bottomBorder, rightBorder;
255:
256: /** The currently focused component in this window. This will be the window itself if
257: no component inside the window has focus but it is never null. */
258:
259: private Component currentFocusComponent;
260:
261: /** Determines if a WINDOW_ACTIVATED event has been posted to the queue without a
262: WINDOW_DEACTIVATED. This is necessary because when the focus changes in the window
263: we need to post a focus gained permanent on the new component only if this window has
264: been activated.
265: @see #focusChanged */
266:
267: private boolean postedActivatedEvent;
268: private boolean initializedBorders;
269: }
|