blob: cdf8f2093500a7b17c415d242740d4e50ad5a9fd [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1996-1998 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25package sun.awt.motif;
26
27import java.awt.*;
28import java.awt.peer.*;
29
30public class MPopupMenuPeer extends MMenuPeer implements PopupMenuPeer {
31
32 static {
33 initIDs();
34 }
35
36 /* initialize the methodIDs of methods that may be accessed from C */
37 private native static void initIDs();
38
39 native void createMenu(MComponentPeer parent);
40
41 void createPopupMenu() {
42 if (MMenuItemPeer.getParent_NoClientCode(target) instanceof Component) {
43 Component parent = (Component)getParent_NoClientCode(target);
44 MComponentPeer parentPeer = (MComponentPeer) MToolkit.targetToPeer(parent);
45 if (parentPeer == null) {
46 // because the menu isn't a component (sigh) we first have to wait
47 // for a failure to map the peer which should only happen for a
48 // lightweight container, then find the actual native parent from
49 // that component.
50 parent = MToolkit.getNativeContainer(parent);
51 parentPeer = (MComponentPeer) MToolkit.targetToPeer(parent);
52 }
53 createMenu(parentPeer);
54 nativeCreated = true;
55 createItems((Menu)target);
56
57 } else {
58 throw new IllegalArgumentException("illegal popup menu container class");
59 }
60 }
61
62 void createItems(Menu target) {
63 int nitems = target.getItemCount();
64 MMenuPeer parent = (MMenuPeer)MToolkit.targetToPeer(target);
65 for (int i = 0 ; i < nitems ; i++) {
66 MenuItem mitem = target.getItem(i);
67 MMenuItemPeer mipeer = (MMenuItemPeer)MToolkit.targetToPeer(mitem);
68 mipeer.create(parent);
69 if (mitem instanceof Menu) {
70 createItems((Menu)mitem);
71 }
72 }
73 }
74
75 public MPopupMenuPeer(PopupMenu target) {
76 // Do NOT instantiate native widget until just before showing the
77 // menu, else right mouse click will cause display to lock up
78 // (because of passive grab in Motif)
79 //
80 this.target = target;
81 }
82
83 native void pShow(Event evt, int x, int y, MComponentPeer origin);
84
85 public void show(Event evt) {
86
87 if (!nativeCreated)
88 createPopupMenu();
89
90 Component origin = (Component)evt.target;
91 MComponentPeer peer = (MComponentPeer) MToolkit.targetToPeer(origin);
92 int x = evt.x;
93 int y = evt.y;
94 if (peer == null) {
95 // A failure to map the peer should only happen for a
96 // lightweight component, then find the actual native parent from
97 // that component. The event coorinates are going to have to be
98 Component nativeOrigin = MToolkit.getNativeContainer(origin);
99 peer = (MComponentPeer) MToolkit.targetToPeer(nativeOrigin);
100
101 // remove the event coordinates
102 for (Component c = origin; c != nativeOrigin;
103 c = MComponentPeer.getParent_NoClientCode(c)) {
104 Point p = c.getLocation();
105 x += p.x;
106 y += p.y;
107 }
108 }
109 pShow(evt, x, y, peer);
110 }
111
112 /**
113 * This is the callback function called on the Motif thread by
114 * Popup_popdownCB(Widget, XtPointer, XtPointer) in awt_PopupMenu.c.
115 */
116 // NOTE: This method may be called by privileged threads.
117 // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
118 private void destroyNativeWidgetAfterGettingTreeLock() {
119
120 MToolkit.executeOnEventHandlerThread(target, new Runnable() {
121 public void run() {
122
123 Object treeLock = new Button().getTreeLock();
124 synchronized (treeLock) {
125 destroyNativeWidget();
126 }
127 }
128 });
129 }
130
131 native void pDispose();
132} // class MPopupMenuPeer