|
From: <ls...@us...> - 2007-01-31 20:25:36
|
Revision: 3099
http://jnode.svn.sourceforge.net/jnode/?rev=3099&view=rev
Author: lsantha
Date: 2007-01-31 12:25:09 -0800 (Wed, 31 Jan 2007)
Log Message:
-----------
Classpath patches.
Modified Paths:
--------------
trunk/core/src/classpath/java/java/awt/Component.java
trunk/core/src/classpath/java/java/awt/Container.java
trunk/core/src/classpath/java/java/awt/ContainerOrderFocusTraversalPolicy.java
trunk/core/src/classpath/java/java/awt/EventDispatchThread.java
trunk/core/src/classpath/java/java/awt/EventQueue.java
trunk/core/src/classpath/java/java/awt/LightweightDispatcher.java
trunk/core/src/classpath/java/java/awt/Window.java
Modified: trunk/core/src/classpath/java/java/awt/Component.java
===================================================================
--- trunk/core/src/classpath/java/java/awt/Component.java 2007-01-31 19:02:43 UTC (rev 3098)
+++ trunk/core/src/classpath/java/java/awt/Component.java 2007-01-31 20:25:09 UTC (rev 3099)
@@ -1486,7 +1486,40 @@
}
}
- /**
+ /**
+ * Sends notification to interested listeners about resizing and/or moving
+ * the component. If this component has interested
+ * component listeners or the corresponding event mask enabled, then
+ * COMPONENT_MOVED and/or COMPONENT_RESIZED events are posted to the event
+ * queue.
+ *
+ * @param resized true if the component has been resized, false otherwise
+ * @param moved true if the component has been moved, false otherwise
+ */
+ void notifyReshape(boolean resized, boolean moved)
+ {
+ // Only post an event if this component actually has a listener
+ // or has this event explicitly enabled.
+ if (componentListener != null
+ || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0)
+ {
+ // Fire component event on this component.
+ if (moved)
+ {
+ ComponentEvent ce = new ComponentEvent(this,
+ ComponentEvent.COMPONENT_MOVED);
+ getToolkit().getSystemEventQueue().postEvent(ce);
+ }
+ if (resized)
+ {
+ ComponentEvent ce = new ComponentEvent(this,
+ ComponentEvent.COMPONENT_RESIZED);
+ getToolkit().getSystemEventQueue().postEvent(ce);
+ }
+ }
+ }
+
+ /**
* Sets the bounding rectangle for this component to the specified
* rectangle. Note that these coordinates are relative to the parent, not
* to the screen.
Modified: trunk/core/src/classpath/java/java/awt/Container.java
===================================================================
--- trunk/core/src/classpath/java/java/awt/Container.java 2007-01-31 19:02:43 UTC (rev 3098)
+++ trunk/core/src/classpath/java/java/awt/Container.java 2007-01-31 20:25:09 UTC (rev 3099)
@@ -1808,6 +1808,11 @@
}
}
+ /**
+ * Overridden to dispatch events to lightweight descendents.
+ *
+ * @param e the event to dispatch.
+ */
void dispatchEventImpl(AWTEvent e)
{
boolean dispatched =
@@ -1825,6 +1830,19 @@
}
/**
+ * This is called by the lightweight dispatcher to avoid recursivly
+ * calling into the lightweight dispatcher.
+ *
+ * @param e the event to dispatch
+ *
+ * @see LightweightDispatcher#redispatch(MouseEvent, Component, int)
+ */
+ void dispatchNoLightweight(AWTEvent e)
+ {
+ super.dispatchEventImpl(e);
+ }
+
+ /**
* Tests if this container has an interest in the given event id.
*
* @param eventId The event id to check.
@@ -1938,6 +1956,43 @@
parent.updateHierarchyListenerCount(type, delta);
}
+ /**
+ * Notifies interested listeners about resizing or moving the container.
+ * This performs the super behaviour (sending component events) and
+ * additionally notifies any hierarchy bounds listeners on child components.
+ *
+ * @param resized true if the component has been resized, false otherwise
+ * @param moved true if the component has been moved, false otherwise
+ */
+ void notifyReshape(boolean resized, boolean moved)
+ {
+ // Notify component listeners.
+ super.notifyReshape(resized, moved);
+
+ if (ncomponents > 0)
+ {
+ // Notify hierarchy bounds listeners.
+ if (resized)
+ {
+ for (int i = 0; i < getComponentCount(); i++)
+ {
+ Component child = getComponent(i);
+ child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_RESIZED,
+ this, parent, 0);
+ }
+ }
+ if (moved)
+ {
+ for (int i = 0; i < getComponentCount(); i++)
+ {
+ Component child = getComponent(i);
+ child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_MOVED,
+ this, parent, 0);
+ }
+ }
+ }
+ }
+
private void addNotifyContainerChildren()
{
synchronized (getTreeLock ())
Modified: trunk/core/src/classpath/java/java/awt/ContainerOrderFocusTraversalPolicy.java
===================================================================
--- trunk/core/src/classpath/java/java/awt/ContainerOrderFocusTraversalPolicy.java 2007-01-31 19:02:43 UTC (rev 3098)
+++ trunk/core/src/classpath/java/java/awt/ContainerOrderFocusTraversalPolicy.java 2007-01-31 20:25:09 UTC (rev 3099)
@@ -346,29 +346,31 @@
|| !root.isDisplayable ())
return null;
- if (root.visible && root.isDisplayable() && root.enabled
- && root.focusable)
+ if (accept(root))
return root;
- Component[] componentArray = root.getComponents ();
-
- for (int i = 0; i < componentArray.length; i++)
+ int ncomponents = root.getComponentCount();
+ for (int i = 0; i < ncomponents; i++)
{
- Component component = componentArray [i];
-
- if (component.visible && component.isDisplayable() && component.enabled
- && component.focusable)
- return component;
-
- if (component instanceof Container)
+ Component component = root.getComponent(i);
+ if (component instanceof Container
+ && !((Container) component).isFocusCycleRoot())
{
- Component result = getFirstComponent ((Container) component);
-
- if (result != null
- && (result.visible && result.isDisplayable() && result.enabled && result.focusable))
- return result;
+ Component first = null;
+ Container cont = (Container) component;
+ if (cont.isFocusTraversalPolicyProvider())
+ {
+ FocusTraversalPolicy childPol = cont.getFocusTraversalPolicy();
+ first = childPol.getFirstComponent(cont);
}
+ else
+ first = getFirstComponent(cont);
+ if (first != null)
+ return first;
}
+ else if (accept(component))
+ return component;
+ }
return null;
}
Modified: trunk/core/src/classpath/java/java/awt/EventDispatchThread.java
===================================================================
--- trunk/core/src/classpath/java/java/awt/EventDispatchThread.java 2007-01-31 19:02:43 UTC (rev 3098)
+++ trunk/core/src/classpath/java/java/awt/EventDispatchThread.java 2007-01-31 20:25:09 UTC (rev 3099)
@@ -73,6 +73,9 @@
// Ignore and use default.
}
setPriority(priority);
+
+ // Make sure that an event dispatch thread is never a daemon thread.
+ setDaemon(false);
}
public void run()
Modified: trunk/core/src/classpath/java/java/awt/EventQueue.java
===================================================================
--- trunk/core/src/classpath/java/java/awt/EventQueue.java 2007-01-31 19:02:43 UTC (rev 3098)
+++ trunk/core/src/classpath/java/java/awt/EventQueue.java 2007-01-31 20:25:09 UTC (rev 3099)
@@ -39,6 +39,7 @@
package java.awt;
import gnu.java.awt.LowPriorityEvent;
+import gnu.java.awt.peer.NativeEventLoopRunningEvent;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
@@ -114,6 +115,7 @@
private long lastWhen = System.currentTimeMillis();
private EventDispatchThread dispatchThread = new EventDispatchThread(this);
+ private boolean nativeLoopRunning = false;
private boolean shutdown = false;
// @vm-specific allow JNode access from VMAwtAPI
@@ -130,17 +132,19 @@
// This is the exact self-shutdown condition specified in J2SE:
// http://java.sun.com/j2se/1.4.2/docs/api/java/awt/doc-files/AWTThreadIssues.html
-
- // FIXME: check somewhere that the native queue is empty
- if (peekEvent() == null)
- {
- Frame[] frames = Frame.getFrames();
- for (int i = 0; i < frames.length; ++i)
- if (frames[i].isDisplayable())
- return false;
- return true;
- }
+
+ if (nativeLoopRunning)
return false;
+
+ if (peekEvent() != null)
+ return false;
+
+ Frame[] frames = Frame.getFrames();
+ for (int i = 0; i < frames.length; ++i)
+ if (frames[i].isDisplayable())
+ return false;
+
+ return true;
}
/**
@@ -169,22 +173,26 @@
return next.getNextEvent();
AWTEvent res = getNextEventImpl(true);
+
while (res == null)
{
- // We are not allowed to return null from this method, yet it
- // is possible that we actually have run out of native events
- // in the enclosing while() loop, and none of the native events
- // happened to cause AWT events. We therefore ought to check
- // the isShutdown() condition here, before risking a "native
- // wait". If we check it before entering this function we may
- // wait forever for events after the shutdown condition has
- // arisen.
+ if (isShutdown())
+ {
+ // Explicitly set dispathThread to null. If we don't do
+ // this, there is a race condition where dispatchThread
+ // can be != null even after the event dispatch thread has
+ // stopped running. If that happens, then the
+ // dispatchThread == null check in postEventImpl will
+ // fail, and a new event dispatch thread will not be
+ // created, leaving invokeAndWaits waiting indefinitely.
+ dispatchThread = null;
- if (isShutdown())
+ // Interrupt the event dispatch thread.
throw new InterruptedException();
+ }
wait();
- res = getNextEventImpl(true);
+ res = getNextEventImpl(true);
}
return res;
@@ -298,6 +306,12 @@
priority = LOW_PRIORITY;
// TODO: Maybe let Swing RepaintManager events also be processed with
// low priority.
+ if (evt instanceof NativeEventLoopRunningEvent)
+ {
+ nativeLoopRunning = ((NativeEventLoopRunningEvent) evt).isRunning();
+ notify();
+ return;
+ }
postEventImpl(evt, priority);
}
Modified: trunk/core/src/classpath/java/java/awt/LightweightDispatcher.java
===================================================================
--- trunk/core/src/classpath/java/java/awt/LightweightDispatcher.java 2007-01-31 19:02:43 UTC (rev 3098)
+++ trunk/core/src/classpath/java/java/awt/LightweightDispatcher.java 2007-01-31 20:25:09 UTC (rev 3099)
@@ -38,7 +38,10 @@
package java.awt;
+import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
+import java.awt.event.MouseWheelEvent;
+import java.awt.peer.LightweightPeer;
import java.util.WeakHashMap;
/**
@@ -49,7 +52,7 @@
*
* @author Roman Kennke (ke...@ai...)
*/
-class LightweightDispatcher
+final class LightweightDispatcher
{
/**
@@ -80,6 +83,11 @@
private Component lastTarget;
/**
+ * The current mouseEventTarget.
+ */
+ private Component mouseEventTarget;
+
+ /**
* Returns an instance of LightweightDispatcher for the current thread's
* thread group.
*
@@ -113,7 +121,7 @@
*
* @param event the event
*/
- public boolean dispatchEvent(AWTEvent event)
+ public boolean dispatchEvent(final AWTEvent event)
{
if (event instanceof MouseEvent && event.getSource() instanceof Window)
{
@@ -336,4 +344,138 @@
p.y -= offY;
return p;
}
+
+ /**
+ * Checks if the specified component would be interested in a mouse event.
+ *
+ * @param c the component to check
+ *
+ * @return <code>true</code> if the component has mouse listeners installed,
+ * <code>false</code> otherwise
+ */
+ private boolean isMouseListening(final Component c)
+ {
+ // Note: It is important to NOT check if the component is listening
+ // for a specific event (for instance, mouse motion events). The event
+ // gets dispatched to the component if the component is listening
+ // for ANY mouse event, even when the component is not listening for the
+ // specific type of event. There are applications that depend on this
+ // (sadly).
+ return c.mouseListener != null
+ || c.mouseMotionListener != null
+ || c.mouseWheelListener != null
+ || (c.eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0
+ || (c.eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0
+ || (c.eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0;
+ }
+
+ /**
+ * Tracks MOUSE_ENTERED and MOUSE_EXIT as well as MOUSE_MOVED and
+ * MOUSE_DRAGGED and creates synthetic MOUSE_ENTERED and MOUSE_EXITED for
+ * lightweight component.s
+ *
+ * @param target the current mouse event target
+ * @param ev the mouse event
+ */
+ private void trackEnterExit(final Component target, final MouseEvent ev)
+ {
+ int id = ev.getID();
+ if (target != lastTarget)
+ {
+ if (lastTarget != null)
+ redispatch(ev, lastTarget, MouseEvent.MOUSE_EXITED);
+ if (id == MouseEvent.MOUSE_EXITED)
+ ev.consume();
+ if (target != null)
+ redispatch(ev, target, MouseEvent.MOUSE_ENTERED);
+ if (id == MouseEvent.MOUSE_ENTERED)
+ ev.consume();
+ lastTarget = target;
+ }
+
+ }
+
+ /**
+ * Redispatches the specified mouse event to the specified target with the
+ * specified id.
+ *
+ * @param ev the mouse event
+ * @param target the new target
+ * @param id the new id
+ */
+ private void redispatch(MouseEvent ev, Component target, int id)
+ {
+ Component source = ev.getComponent();
+ if (target != null)
+ {
+ // Translate coordinates.
+ int x = ev.getX();
+ int y = ev.getY();
+ for (Component c = target; c != null && c != source; c = c.getParent())
+ {
+ x -= c.x;
+ y -= c.y;
+ }
+
+ // Retarget event.
+ MouseEvent retargeted;
+ if (id == MouseEvent.MOUSE_WHEEL)
+ {
+ MouseWheelEvent mwe = (MouseWheelEvent) ev;
+ retargeted = new MouseWheelEvent(target, id, ev.getWhen(),
+ ev.getModifiers()
+ | ev.getModifiersEx(), x, y,
+ ev.getClickCount(),
+ ev.isPopupTrigger(),
+ mwe.getScrollType(),
+ mwe.getScrollAmount(),
+ mwe.getWheelRotation());
+ }
+ else
+ {
+ retargeted = new MouseEvent(target, id, ev.getWhen(),
+ ev.getModifiers() | ev.getModifiersEx(),
+ x, y, ev.getClickCount(),
+ ev.isPopupTrigger(), ev.getButton());
+ }
+
+ if (target == source)
+ ((Container) target).dispatchNoLightweight(retargeted);
+ else
+ target.dispatchEvent(retargeted);
+ }
+ }
+
+ /**
+ * Determines if we are in the middle of a drag operation, that is, if
+ * any of the buttons is held down.
+ *
+ * @param ev the mouse event to check
+ *
+ * @return <code>true</code> if we are in the middle of a drag operation,
+ * <code>false</code> otherwise
+ */
+ private boolean isDragging(MouseEvent ev)
+ {
+ int mods = ev.getModifiersEx();
+ int id = ev.getID();
+ if (id == MouseEvent.MOUSE_PRESSED || id == MouseEvent.MOUSE_RELEASED)
+ {
+ switch (ev.getButton())
+ {
+ case MouseEvent.BUTTON1:
+ mods ^= InputEvent.BUTTON1_DOWN_MASK;
+ break;
+ case MouseEvent.BUTTON2:
+ mods ^= InputEvent.BUTTON2_DOWN_MASK;
+ break;
+ case MouseEvent.BUTTON3:
+ mods ^= InputEvent.BUTTON3_DOWN_MASK;
+ break;
+ }
+ }
+ return (mods & (InputEvent.BUTTON1_DOWN_MASK
+ | InputEvent.BUTTON2_DOWN_MASK
+ | InputEvent.BUTTON3_DOWN_MASK)) != 0;
+ }
}
Modified: trunk/core/src/classpath/java/java/awt/Window.java
===================================================================
--- trunk/core/src/classpath/java/java/awt/Window.java 2007-01-31 19:02:43 UTC (rev 3098)
+++ trunk/core/src/classpath/java/java/awt/Window.java 2007-01-31 20:25:09 UTC (rev 3099)
@@ -329,6 +329,15 @@
if (initialFocusOwner != null)
initialFocusOwner.requestFocusInWindow();
+ // Post WINDOW_OPENED from here.
+ if (windowListener != null
+ || (eventMask & AWTEvent.WINDOW_EVENT_MASK) != 0)
+ {
+ WindowEvent ev = new WindowEvent(this,
+ WindowEvent.WINDOW_OPENED);
+ Toolkit tk = Toolkit.getDefaultToolkit();
+ tk.getSystemEventQueue().postEvent(ev);
+ }
shown = true;
}
}
@@ -413,11 +422,8 @@
public void toFront()
{
if (peer != null)
- {
- WindowPeer wp = (WindowPeer) peer;
- wp.toFront();
+ ( (WindowPeer) peer ).toFront();
}
- }
/**
* Returns the toolkit used to create this window.
@@ -1146,6 +1152,47 @@
this.focusableWindowState = focusableWindowState;
}
+ /**
+ * Check whether this Container is a focus cycle root.
+ * Returns always <code>true</code> as Windows are the
+ * root of the focus cycle.
+ *
+ * @return Always <code>true</code>.
+ *
+ * @since 1.4
+ */
+ public final boolean isFocusCycleRoot()
+ {
+ return true;
+ }
+
+ /**
+ * Set whether or not this Container is the root of a focus
+ * traversal cycle. Windows are the root of the focus cycle
+ * and therefore this method does nothing.
+ *
+ * @param focusCycleRoot ignored.
+ *
+ * @since 1.4
+ */
+ public final void setFocusCycleRoot(boolean focusCycleRoot)
+ {
+ // calls to the method are ignored
+ }
+
+ /**
+ * Returns the root container that owns the focus cycle where this
+ * component resides. Windows have no ancestors and this method
+ * returns always <code>null</code>.
+ *
+ * @return Always <code>null</code>.
+ * @since 1.4
+ */
+ public final Container getFocusCycleRootAncestor()
+ {
+ return null;
+ }
+
// setBoundsCallback is needed so that when a user moves a window,
// the Window's location can be updated without calling the peer's
// setBounds method. When a user moves a window the peer window's
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|