blob: cdf8f2093500a7b17c415d242740d4e50ad5a9fd [file] [log] [blame]
/*
* Copyright 1996-1998 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code 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 in the LICENSE file that
* accompanied this code).
*
* 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 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.awt.motif;
import java.awt.*;
import java.awt.peer.*;
public class MPopupMenuPeer extends MMenuPeer implements PopupMenuPeer {
static {
initIDs();
}
/* initialize the methodIDs of methods that may be accessed from C */
private native static void initIDs();
native void createMenu(MComponentPeer parent);
void createPopupMenu() {
if (MMenuItemPeer.getParent_NoClientCode(target) instanceof Component) {
Component parent = (Component)getParent_NoClientCode(target);
MComponentPeer parentPeer = (MComponentPeer) MToolkit.targetToPeer(parent);
if (parentPeer == null) {
// because the menu isn't a component (sigh) we first have to wait
// for a failure to map the peer which should only happen for a
// lightweight container, then find the actual native parent from
// that component.
parent = MToolkit.getNativeContainer(parent);
parentPeer = (MComponentPeer) MToolkit.targetToPeer(parent);
}
createMenu(parentPeer);
nativeCreated = true;
createItems((Menu)target);
} else {
throw new IllegalArgumentException("illegal popup menu container class");
}
}
void createItems(Menu target) {
int nitems = target.getItemCount();
MMenuPeer parent = (MMenuPeer)MToolkit.targetToPeer(target);
for (int i = 0 ; i < nitems ; i++) {
MenuItem mitem = target.getItem(i);
MMenuItemPeer mipeer = (MMenuItemPeer)MToolkit.targetToPeer(mitem);
mipeer.create(parent);
if (mitem instanceof Menu) {
createItems((Menu)mitem);
}
}
}
public MPopupMenuPeer(PopupMenu target) {
// Do NOT instantiate native widget until just before showing the
// menu, else right mouse click will cause display to lock up
// (because of passive grab in Motif)
//
this.target = target;
}
native void pShow(Event evt, int x, int y, MComponentPeer origin);
public void show(Event evt) {
if (!nativeCreated)
createPopupMenu();
Component origin = (Component)evt.target;
MComponentPeer peer = (MComponentPeer) MToolkit.targetToPeer(origin);
int x = evt.x;
int y = evt.y;
if (peer == null) {
// A failure to map the peer should only happen for a
// lightweight component, then find the actual native parent from
// that component. The event coorinates are going to have to be
Component nativeOrigin = MToolkit.getNativeContainer(origin);
peer = (MComponentPeer) MToolkit.targetToPeer(nativeOrigin);
// remove the event coordinates
for (Component c = origin; c != nativeOrigin;
c = MComponentPeer.getParent_NoClientCode(c)) {
Point p = c.getLocation();
x += p.x;
y += p.y;
}
}
pShow(evt, x, y, peer);
}
/**
* This is the callback function called on the Motif thread by
* Popup_popdownCB(Widget, XtPointer, XtPointer) in awt_PopupMenu.c.
*/
// NOTE: This method may be called by privileged threads.
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
private void destroyNativeWidgetAfterGettingTreeLock() {
MToolkit.executeOnEventHandlerThread(target, new Runnable() {
public void run() {
Object treeLock = new Button().getTreeLock();
synchronized (treeLock) {
destroyNativeWidget();
}
}
});
}
native void pDispose();
} // class MPopupMenuPeer