diff options
Diffstat (limited to 'libjava/gnu/awt/LightweightRedirector.java')
-rw-r--r-- | libjava/gnu/awt/LightweightRedirector.java | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/libjava/gnu/awt/LightweightRedirector.java b/libjava/gnu/awt/LightweightRedirector.java new file mode 100644 index 000000000..41dc12427 --- /dev/null +++ b/libjava/gnu/awt/LightweightRedirector.java @@ -0,0 +1,183 @@ +/* Copyright (C) 2000 Free Software Foundation + + This file is part of libgcj. + +This software is copyrighted work licensed under the terms of the +Libgcj License. Please consult the file "LIBGCJ_LICENSE" for +details. */ + +package gnu.awt; + +import java.awt.AWTEvent; +import java.awt.AWTError; +import java.awt.Component; +import java.awt.Container; +import java.awt.event.MouseEvent; +import java.awt.event.InputEvent; + +/** + * Encapsulates the logic required to dispatch events to the correct + * component in a component tree that may contain lightweight + * components. Toolkits typically only identify heavyweight components + * as the source of events. This class redirects the events to the + * appropriate lightweight children of the heavyweight component. + */ +public class LightweightRedirector +{ + final static int LAST_BUTTON_NUMBER = 3; + + /* We sacrifice one array element to allow the button number to + match the index of this array. */ + Component[] releaseTargets = new Component[LAST_BUTTON_NUMBER+1]; + + /** + * + * Modifies or replaces the given event with an event that has been + * properly redirected. State of button presses are kept so that + * button releases can be redirected to the same component as the + * button press. It is required that all events are sent through + * this method in chronological order. + */ + public AWTEvent redirect(AWTEvent event) + { + if (event instanceof MouseEvent) + return redirectMouse((MouseEvent) event); + + /* In case we don't know how to redirect the event, simply return + the event unchanged. */ + return event; + } + + MouseEvent redirectMouse(MouseEvent event) + { + int button = getButtonNumber(event); + int id = event.getID(); + + Component heavySource = (Component) event.getSource(); + Component source = heavySource; + int x = event.getX(); + int y = event.getY(); + + if (id == MouseEvent.MOUSE_RELEASED) + { + Component target = releaseTargets[button]; + + if (target != null) + { + releaseTargets[button] = null; + source = target; + + Component child = source; + while (child != heavySource) + { + x -= child.getX(); + y -= child.getY(); + child = child.getParent(); + if (child == null) + System.err.println("warning, orphaned release target"); + } + } + } + else + { + /* Find real component, and adjust source, x and y + accordingly. */ + + while (true) + { + Component parent = source; + + Component child = parent.getComponentAt(x, y); + + if (parent == child) + break; + + // maybe ignoring would be better? + if (child == null) + { + String msg = "delivered event not within component. " + + "Heavyweight source was " + heavySource + ". " + + "Component was " + parent; + throw new AWTError(msg); + } + if (child.isLightweight()) + { + // descend down to child + source = child; + x -= child.getX(); + y -= child.getY(); + } + else + { + System.err.println("warning: event delivered to wrong " + + "heavyweight component. Was " + + "delivered to " + source + ". " + + "Should have been delivered to " + + child + ". Maybe the native window " + + "system is bubbling events up the " + + "containment hierarchy."); + break; + } + } + + /* ensure that the release event is delivered to the same + component as the press event. For most toolkits this is + only necessary for lightweight components, since the + underlying windowing system takes care of its heavyweight + components. */ + if (id == MouseEvent.MOUSE_PRESSED) + releaseTargets[button] = source; + } + + + if (source == heavySource) + return event; // no change in event + + // print warning for heavyweights + /* this warning can safely be removed if a toolkit that + needs heavyweight redirection support is ever created. */ + if (!source.isLightweight()) + System.err.println("warning: redirecting to heavyweight"); + + MouseEvent redirected = new MouseEvent(source, event.getID(), + event.getWhen(), + event.getModifiersEx(), + x, y, + event.getClickCount(), + event.isPopupTrigger()); + + return redirected; + } + + /** + * Identifies the button number for an input event. + * + * @returns the button number, or 0 if no button modifier was set + * for the event. + */ + int getButtonNumber(InputEvent event) + { + int modifiers = event.getModifiersEx(); + + modifiers &= + InputEvent.BUTTON1_DOWN_MASK | + InputEvent.BUTTON2_DOWN_MASK | + InputEvent.BUTTON3_DOWN_MASK; + + switch (modifiers) + { + case InputEvent.BUTTON1_DOWN_MASK: + return 1; + case InputEvent.BUTTON2_DOWN_MASK: + return 2; + case InputEvent.BUTTON3_DOWN_MASK: + return 3; + case 0: + return 0; + + default: + System.err.println("FIXME: multibutton event"); + return 0; + } + } +} |