/* * @(#)ComponentXWindow.java 1.19 06/10/10 * * Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. * */ package java.awt; import java.awt.event.*; /** The X window used by a component to get mouse events from the X server. This winow represents an InputOnly window in X (an invisible window that can be used to select and receive events). @version 1.15, 08/19/02 @author Nicholas Allen*/ class ComponentXWindow { static { // Make sure the toolkit has been loaded. This is necessary to ensure the // libx11awt is loaded and initialized. Toolkit.getDefaultToolkit(); } ComponentXWindow (Component component) { this.component = component; create(); setBackground(component.getBackground()); setCursor(component.cursor); } /** Sets the background for this x window. As this is an InputOnly X window we don't do anything but sub classes need to override this if the X window is an InputOutput X window. */ void setBackground(Color c) {} /** Creates the component's X window. */ void create() { isDelegateWindow = component.delegateSource != null || component.parent.xwindow.isDelegateWindow; // If this is the top level delegate's x window (eg a JButton's) then create it as a child // of the delegate source's (ie the Button's) x window this.windowID = create((component.delegateSource != null) ? component.delegateSource.xwindow.windowID : component.parent.xwindow.windowID); } /** Creates the window given its parent. The window should be initially unmapped and the size can be anything as this is set later by the setBounds method. */ private native int create(int parent); /** Destroys the X window. */ native void dispose(); /** Gets the location of the X window on the screen. */ native Point getLocationOnScreen(); void setCursor(Cursor cursor) { setCursorNative(cursor != null ? cursor.type : Cursor.DEFAULT_CURSOR); } native void setCursorNative(int type); void setBounds(int x, int y, int width, int height) { // X does not allow window of width or height of 0 so if the component has these // dimensions then we unmap the XWindow. if (width == 0 || height == 0) { unmap(); zeroSize = true; } else { // If this is a top level delegate's x window then it is a child of the delegate // source's x window and so we always position it a 0,0. if (component.delegateSource != null) { x = 0; y = 0; } else { ComponentXWindow parent = component.parent.xwindow; if (parent instanceof WindowXWindow) { x -= ((WindowXWindow) parent).leftBorder; y -= ((WindowXWindow) parent).topBorder; } } setBoundsNative(x, y, width, height); zeroSize = false; // Because the X window could have been unmapped by setting the size to 0 // we remap it again if the component is showing. if (component.visible) map(); } } /** Sets the bounds for this X window using XMoveResizeWindow xlib function. Note that this function should not be called with a width or height of zero as X will generate errors. */ native void setBoundsNative(int x, int y, int width, int height); /** Sets the event mask for the X window using the supplied event mask (see AWTEvent). This lets the X server know what kinds of events we are interested in. */ native void setMouseEventMask(long mask); /** Maps the X window. This will only map the window if the size is non zero for both the width and height. */ void map() { if (!zeroSize) mapNative(); } /** Maps the X window using XMapWindow xlib function. */ native void mapNative(); /** Unmaps the X window using the XUnmapWindow xlib function. */ native void unmap(); /** Called when a mouse button event is received from the X server for this X window. Posts required AWTEvents into the Java event queue for processing. This method will determine the click count. */ void postMouseButtonEvent(int id, long when, int modifiers, int x, int y) { if (id == MouseEvent.MOUSE_PRESSED) { if (x == lastClickX && y == lastClickY && when - lastClickTime <= 200) clickCount++; else clickCount = 1; lastClickX = x; lastClickY = y; lastClickModifiers = modifiers; } boolean popupTrigger = (id == MouseEvent.MOUSE_PRESSED && (modifiers & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK); postMouseEvent(new MouseEvent (component, id, when, modifiers, x, y, clickCount, popupTrigger)); if (id == MouseEvent.MOUSE_RELEASED && lastClickX == x && lastClickY == y && lastClickModifiers == modifiers) { postMouseEvent(new MouseEvent (component, MouseEvent.MOUSE_CLICKED, when, modifiers, x, y, clickCount, popupTrigger)); lastClickTime = when; } } /** Called when a mouse motion event is received from the X server for this X window. Posts required AWTEvents into the Java event queue for processing. */ void postMouseEvent(int id, long when, int modifiers, int x, int y) { postMouseEvent(new MouseEvent (component, id, when, modifiers, x, y, 0, false)); } private void postMouseEvent(MouseEvent e) { // Check to see if the mouse event should be propogated to the delegate source if this // is a delegate x window. For example, as the events will come in directly to a JButton // through its X window it is necessary to send the event to the Button as well. if (isDelegateWindow) { int x = e.getX(), y = e.getY(); MouseEvent e2; Component c = component; // Find delegate source and translate to its coordinates while (c.delegateSource == null) { x += c.x; y += c.y; c = c.parent; } Toolkit.getEventQueue().postEvent(new MouseEvent (c.delegateSource, e.id, e.getWhen(), e.getModifiers(), x, y, e.getClickCount(), e.isPopupTrigger())); } Toolkit.getEventQueue().postEvent(e); } /** The component this X window is for. */ Component component; /** The native X Window id. */ int windowID; /** true if size is set to zero in either width or height. This is necessary as X doesn't allow 0 size windows. */ boolean zeroSize = true; /** The time the last mouse click event ocurred at. */ private long lastClickTime; /** The click count used for mouse events. */ private int clickCount = 1; /** Position of last mouse click. */ private int lastClickX, lastClickY; /** Modifiers used the last time the mouse was clicked. */ private int lastClickModifiers; /** true if this x window is an x window for a delegate component (eg a JButton) or one of it's child windows. This is used to determine if we need to propogate mouse events to the delegate source (eg the Button). */ private boolean isDelegateWindow; }