001: /*
002: * @(#)ComponentXWindow.java 1.19 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 java.awt;
029:
030: import java.awt.event.*;
031:
032: /** The X window used by a component to get mouse events from the X server. This winow represents an InputOnly
033: window in X (an invisible window that can be used to select and receive events).
034: @version 1.15, 08/19/02
035: @author Nicholas Allen*/
036:
037: class ComponentXWindow {
038: static {
039: // Make sure the toolkit has been loaded. This is necessary to ensure the
040: // libx11awt is loaded and initialized.
041:
042: Toolkit.getDefaultToolkit();
043: }
044:
045: ComponentXWindow(Component component) {
046: this .component = component;
047: create();
048: setBackground(component.getBackground());
049: setCursor(component.cursor);
050: }
051:
052: /** Sets the background for this x window. As this is an InputOnly X window we don't do anything
053: but sub classes need to override this if the X window is an InputOutput X window. */
054:
055: void setBackground(Color c) {
056: }
057:
058: /** Creates the component's X window. */
059:
060: void create() {
061: isDelegateWindow = component.delegateSource != null
062: || component.parent.xwindow.isDelegateWindow;
063: // If this is the top level delegate's x window (eg a JButton's) then create it as a child
064: // of the delegate source's (ie the Button's) x window
065:
066: this .windowID = create((component.delegateSource != null) ? component.delegateSource.xwindow.windowID
067: : component.parent.xwindow.windowID);
068: }
069:
070: /** Creates the window given its parent. The window should be initially unmapped and the
071: size can be anything as this is set later by the setBounds method. */
072:
073: private native int create(int parent);
074:
075: /** Destroys the X window. */
076:
077: native void dispose();
078:
079: /** Gets the location of the X window on the screen. */
080:
081: native Point getLocationOnScreen();
082:
083: void setCursor(Cursor cursor) {
084: setCursorNative(cursor != null ? cursor.type
085: : Cursor.DEFAULT_CURSOR);
086: }
087:
088: native void setCursorNative(int type);
089:
090: void setBounds(int x, int y, int width, int height) {
091: // X does not allow window of width or height of 0 so if the component has these
092: // dimensions then we unmap the XWindow.
093:
094: if (width == 0 || height == 0) {
095: unmap();
096: zeroSize = true;
097: } else {
098: // If this is a top level delegate's x window then it is a child of the delegate
099: // source's x window and so we always position it a 0,0.
100:
101: if (component.delegateSource != null) {
102: x = 0;
103: y = 0;
104: } else {
105: ComponentXWindow parent = component.parent.xwindow;
106: if (parent instanceof WindowXWindow) {
107: x -= ((WindowXWindow) parent).leftBorder;
108: y -= ((WindowXWindow) parent).topBorder;
109: }
110: }
111: setBoundsNative(x, y, width, height);
112: zeroSize = false;
113: // Because the X window could have been unmapped by setting the size to 0
114: // we remap it again if the component is showing.
115:
116: if (component.visible)
117: map();
118: }
119: }
120:
121: /** Sets the bounds for this X window using XMoveResizeWindow xlib function. Note that
122: this function should not be called with a width or height of zero as X will generate errors. */
123:
124: native void setBoundsNative(int x, int y, int width, int height);
125:
126: /** Sets the event mask for the X window using the supplied event mask (see AWTEvent).
127: This lets the X server know what kinds of events we are interested in. */
128:
129: native void setMouseEventMask(long mask);
130:
131: /** Maps the X window. This will only map the window if the size is non zero for
132: both the width and height. */
133:
134: void map() {
135: if (!zeroSize)
136: mapNative();
137: }
138:
139: /** Maps the X window using XMapWindow xlib function. */
140:
141: native void mapNative();
142:
143: /** Unmaps the X window using the XUnmapWindow xlib function. */
144:
145: native void unmap();
146:
147: /** Called when a mouse button event is received from the X server for this X window.
148: Posts required AWTEvents into the Java event queue for processing. This method will
149: determine the click count. */
150:
151: void postMouseButtonEvent(int id, long when, int modifiers, int x,
152: int y) {
153: if (id == MouseEvent.MOUSE_PRESSED) {
154: if (x == lastClickX && y == lastClickY
155: && when - lastClickTime <= 200)
156: clickCount++;
157: else
158: clickCount = 1;
159: lastClickX = x;
160: lastClickY = y;
161: lastClickModifiers = modifiers;
162: }
163: boolean popupTrigger = (id == MouseEvent.MOUSE_PRESSED && (modifiers & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK);
164: postMouseEvent(new MouseEvent(component, id, when, modifiers,
165: x, y, clickCount, popupTrigger));
166: if (id == MouseEvent.MOUSE_RELEASED && lastClickX == x
167: && lastClickY == y && lastClickModifiers == modifiers) {
168: postMouseEvent(new MouseEvent(component,
169: MouseEvent.MOUSE_CLICKED, when, modifiers, x, y,
170: clickCount, popupTrigger));
171: lastClickTime = when;
172: }
173: }
174:
175: /** Called when a mouse motion event is received from the X server for this X window.
176: Posts required AWTEvents into the Java event queue for processing. */
177:
178: void postMouseEvent(int id, long when, int modifiers, int x, int y) {
179: postMouseEvent(new MouseEvent(component, id, when, modifiers,
180: x, y, 0, false));
181: }
182:
183: private void postMouseEvent(MouseEvent e) {
184: // Check to see if the mouse event should be propogated to the delegate source if this
185: // is a delegate x window. For example, as the events will come in directly to a JButton
186: // through its X window it is necessary to send the event to the Button as well.
187:
188: if (isDelegateWindow) {
189: int x = e.getX(), y = e.getY();
190: MouseEvent e2;
191: Component c = component;
192: // Find delegate source and translate to its coordinates
193:
194: while (c.delegateSource == null) {
195: x += c.x;
196: y += c.y;
197: c = c.parent;
198: }
199: Toolkit.getEventQueue().postEvent(
200: new MouseEvent(c.delegateSource, e.id, e.getWhen(),
201: e.getModifiers(), x, y, e.getClickCount(),
202: e.isPopupTrigger()));
203: }
204: Toolkit.getEventQueue().postEvent(e);
205: }
206:
207: /** The component this X window is for. */
208:
209: Component component;
210: /** The native X Window id. */
211:
212: int windowID;
213: /** true if size is set to zero in either width or height. This is necessary
214: as X doesn't allow 0 size windows. */
215:
216: boolean zeroSize = true;
217: /** The time the last mouse click event ocurred at. */
218:
219: private long lastClickTime;
220: /** The click count used for mouse events. */
221:
222: private int clickCount = 1;
223: /** Position of last mouse click. */
224:
225: private int lastClickX, lastClickY;
226: /** Modifiers used the last time the mouse was clicked. */
227:
228: private int lastClickModifiers;
229: /** true if this x window is an x window for a delegate component (eg a JButton) or one of
230: it's child windows. This is used to determine if we need to propogate mouse events to
231: the delegate source (eg the Button). */
232:
233: private boolean isDelegateWindow;
234: }
|