001: /*
002: * Copyright 1996-1998 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025: package sun.awt.motif;
026:
027: import java.awt.*;
028: import java.awt.peer.*;
029:
030: public class MPopupMenuPeer extends MMenuPeer implements PopupMenuPeer {
031:
032: static {
033: initIDs();
034: }
035:
036: /* initialize the methodIDs of methods that may be accessed from C */
037: private native static void initIDs();
038:
039: native void createMenu(MComponentPeer parent);
040:
041: void createPopupMenu() {
042: if (MMenuItemPeer.getParent_NoClientCode(target) instanceof Component) {
043: Component parent = (Component) getParent_NoClientCode(target);
044: MComponentPeer parentPeer = (MComponentPeer) MToolkit
045: .targetToPeer(parent);
046: if (parentPeer == null) {
047: // because the menu isn't a component (sigh) we first have to wait
048: // for a failure to map the peer which should only happen for a
049: // lightweight container, then find the actual native parent from
050: // that component.
051: parent = MToolkit.getNativeContainer(parent);
052: parentPeer = (MComponentPeer) MToolkit
053: .targetToPeer(parent);
054: }
055: createMenu(parentPeer);
056: nativeCreated = true;
057: createItems((Menu) target);
058:
059: } else {
060: throw new IllegalArgumentException(
061: "illegal popup menu container class");
062: }
063: }
064:
065: void createItems(Menu target) {
066: int nitems = target.getItemCount();
067: MMenuPeer parent = (MMenuPeer) MToolkit.targetToPeer(target);
068: for (int i = 0; i < nitems; i++) {
069: MenuItem mitem = target.getItem(i);
070: MMenuItemPeer mipeer = (MMenuItemPeer) MToolkit
071: .targetToPeer(mitem);
072: mipeer.create(parent);
073: if (mitem instanceof Menu) {
074: createItems((Menu) mitem);
075: }
076: }
077: }
078:
079: public MPopupMenuPeer(PopupMenu target) {
080: // Do NOT instantiate native widget until just before showing the
081: // menu, else right mouse click will cause display to lock up
082: // (because of passive grab in Motif)
083: //
084: this .target = target;
085: }
086:
087: native void pShow(Event evt, int x, int y, MComponentPeer origin);
088:
089: public void show(Event evt) {
090:
091: if (!nativeCreated)
092: createPopupMenu();
093:
094: Component origin = (Component) evt.target;
095: MComponentPeer peer = (MComponentPeer) MToolkit
096: .targetToPeer(origin);
097: int x = evt.x;
098: int y = evt.y;
099: if (peer == null) {
100: // A failure to map the peer should only happen for a
101: // lightweight component, then find the actual native parent from
102: // that component. The event coorinates are going to have to be
103: Component nativeOrigin = MToolkit
104: .getNativeContainer(origin);
105: peer = (MComponentPeer) MToolkit.targetToPeer(nativeOrigin);
106:
107: // remove the event coordinates
108: for (Component c = origin; c != nativeOrigin; c = MComponentPeer
109: .getParent_NoClientCode(c)) {
110: Point p = c.getLocation();
111: x += p.x;
112: y += p.y;
113: }
114: }
115: pShow(evt, x, y, peer);
116: }
117:
118: /**
119: * This is the callback function called on the Motif thread by
120: * Popup_popdownCB(Widget, XtPointer, XtPointer) in awt_PopupMenu.c.
121: */
122: // NOTE: This method may be called by privileged threads.
123: // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
124: private void destroyNativeWidgetAfterGettingTreeLock() {
125:
126: MToolkit.executeOnEventHandlerThread(target, new Runnable() {
127: public void run() {
128:
129: Object treeLock = new Button().getTreeLock();
130: synchronized (treeLock) {
131: destroyNativeWidget();
132: }
133: }
134: });
135: }
136:
137: native void pDispose();
138: } // class MPopupMenuPeer
|