1 /*
2 * Copyright (c) 2002, 2018, Oracle and/or its affiliates. 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package sun.awt.X11;
26
27 import java.awt.*;
28 import java.awt.peer.*;
29 import java.awt.event.*;
30
31 import java.util.Vector;
32 import sun.awt.AWTAccessor;
33 import sun.util.logging.PlatformLogger;
34
35 public class XPopupMenuPeer extends XMenuWindow implements PopupMenuPeer {
36
37 /************************************************
38 *
39 * Data members
40 *
41 ************************************************/
42 private static PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XBaseMenuWindow");
43
44 /*
45 * Primary members
46 */
47 private XComponentPeer componentPeer;
48 private PopupMenu popupMenuTarget;
49
50 /*
51 * If mouse button is clicked on item showing submenu
52 * we have to hide its submenu.
53 * This member saves the submenu under cursor
54 * Only if it's showing
55 */
56 private XMenuPeer showingMousePressedSubmenu = null;
57
58 /*
59 * Painting constants
60 */
61 private static final int CAPTION_MARGIN_TOP = 4;
62 private static final int CAPTION_SEPARATOR_HEIGHT = 6;
63
64 /************************************************
65 *
66 * Construction
67 *
68 ************************************************/
69 XPopupMenuPeer(PopupMenu target) {
70 super(null);
71 this.popupMenuTarget = target;
72 }
73
74 /************************************************
75 *
76 * Implementation of interface methods
77 *
78 ************************************************/
79 /*
80 * From MenuComponentPeer
81 */
82 public void setFont(Font f) {
83 resetMapping();
84 setItemsFont(f);
85 postPaintEvent();
86 }
87
88 /*
89 * From MenuItemPeer
90 */
91 public void setLabel(String label) {
92 resetMapping();
93 postPaintEvent();
94 }
95
96
97 public void setEnabled(boolean enabled) {
98 postPaintEvent();
99 }
100
101 /*
102 * From MenuPeer
103 */
104 /**
105 * addSeparator routines are not used
106 * in peers. Shared code invokes addItem("-")
107 * for adding separators
108 */
109 public void addSeparator() {
110 if (log.isLoggable(PlatformLogger.Level.FINER)) {
111 log.finer("addSeparator is not implemented");
112 }
113 }
114
115 /*
116 * From PopupMenuPeer
117 */
118 @SuppressWarnings("deprecation")
119 public void show(Event e) {
120 target = (Component)e.target;
121 // Get menus from the target.
122 Vector<MenuItem> targetItemVector = getMenuTargetItems();
123 if (targetItemVector != null) {
124 reloadItems(targetItemVector);
125 //Fix for 6287092: JCK15a: api/java_awt/interactive/event/EventTests.html#EventTest0015 fails, mustang
126 Point tl = target.getLocationOnScreen();
127 Point pt = new Point(tl.x + e.x, tl.y + e.y);
128 //Fixed 6266513: Incorrect key handling in XAWT popup menu
129 //No item should be selected when showing popup menu
130 if (!ensureCreated()) {
131 return;
132 }
133 Dimension dim = getDesiredSize();
134 //Fix for 6267162: PIT: Popup Menu gets hidden below the screen when opened
135 //near the periphery of the screen, XToolkit
136 Rectangle bounds = getWindowBounds(pt, dim);
137 reshape(bounds);
138 xSetVisible(true);
139 toFront();
140 selectItem(null, false);
141 grabInput();
142 }
143 }
144
145 /************************************************
146 *
147 * Access to target's fields
148 *
149 ************************************************/
150
151 //Fix for 6267144: PIT: Popup menu label is not shown, XToolkit
152 Font getTargetFont() {
153 if (popupMenuTarget == null) {
154 return XWindow.getDefaultFont();
155 }
156 return AWTAccessor.getMenuComponentAccessor()
157 .getFont_NoClientCode(popupMenuTarget);
158 }
159
160 //Fix for 6267144: PIT: Popup menu label is not shown, XToolkit
161 String getTargetLabel() {
162 if (target == null) {
163 return "";
164 }
165 return AWTAccessor.getMenuItemAccessor().getLabel(popupMenuTarget);
166 }
167
168 //Fix for 6184485: Popup menu is not disabled on XToolkit even when calling setEnabled (false)
169 boolean isTargetEnabled() {
170 if (popupMenuTarget == null) {
171 return false;
172 }
173 return AWTAccessor.getMenuItemAccessor().isEnabled(popupMenuTarget);
174 }
175
176 Vector<MenuItem> getMenuTargetItems() {
177 if (popupMenuTarget == null) {
178 return null;
179 }
180 return AWTAccessor.getMenuAccessor().getItems(popupMenuTarget);
181 }
182
183 /************************************************
184 *
185 * Utility functions
186 *
187 ************************************************/
188
189 //Fix for 6267162: PIT: Popup Menu gets hidden below the screen when opened
190 //near the periphery of the screen, XToolkit
191
192 /**
193 * Calculates placement of popup menu window
194 * given origin in global coordinates and
195 * size of menu window. Returns suggested
196 * rectangle for menu window in global coordinates
197 * @param origin the origin point specified in show()
198 * function converted to global coordinates
199 * @param windowSize the desired size of menu's window
200 */
201 protected Rectangle getWindowBounds(Point origin, Dimension windowSize) {
202 Rectangle globalBounds = new Rectangle(origin.x, origin.y, 0, 0);
203 Rectangle screenBounds = getCurrentGraphicsConfiguration().getBounds();
204 Rectangle res;
205 res = fitWindowRight(globalBounds, windowSize, screenBounds);
206 if (res != null) {
207 return res;
208 }
209 res = fitWindowLeft(globalBounds, windowSize, screenBounds);
210 if (res != null) {
211 return res;
212 }
213 res = fitWindowBelow(globalBounds, windowSize, screenBounds);
214 if (res != null) {
215 return res;
216 }
217 res = fitWindowAbove(globalBounds, windowSize, screenBounds);
218 if (res != null) {
219 return res;
220 }
221 return fitWindowToScreen(windowSize, screenBounds);
222 }
223
224 /************************************************
225 *
226 * Overriden XMenuWindow caption-painting functions
227 * Necessary to fix 6267144: PIT: Popup menu label is not shown, XToolkit
228 *
229 ************************************************/
230 /**
231 * Returns height of menu window's caption.
232 * Can be overriden for popup menus and tear-off menus
233 */
234 protected Dimension getCaptionSize() {
235 String s = getTargetLabel();
236 if (s.equals("")) {
237 return null;
238 }
239 Graphics g = getGraphics();
240 if (g == null) {
241 return null;
242 }
243 try {
244 g.setFont(getTargetFont());
245 FontMetrics fm = g.getFontMetrics();
246 String str = getTargetLabel();
247 int width = fm.stringWidth(str);
248 int height = CAPTION_MARGIN_TOP + fm.getHeight() + CAPTION_SEPARATOR_HEIGHT;
249 Dimension textDimension = new Dimension(width, height);
250 return textDimension;
251 } finally {
252 g.dispose();
253 }
254 }
255
256 /**
257 * Paints menu window's caption.
258 * Can be overriden for popup menus and tear-off menus.
259 * Default implementation does nothing
260 */
261 protected void paintCaption(Graphics g, Rectangle rect) {
262 String s = getTargetLabel();
263 if (s.equals("")) {
264 return;
265 }
266 g.setFont(getTargetFont());
267 FontMetrics fm = g.getFontMetrics();
268 String str = getTargetLabel();
269 int width = fm.stringWidth(str);
270 int textx = rect.x + (rect.width - width) / 2;
271 int texty = rect.y + CAPTION_MARGIN_TOP + fm.getAscent();
272 int sepy = rect.y + rect.height - CAPTION_SEPARATOR_HEIGHT / 2;
273 g.setColor(isTargetEnabled() ? getForegroundColor() : getDisabledColor());
274 g.drawString(s, textx, texty);
275 draw3DRect(g, rect.x, sepy, rect.width, 2, false);
276 }
277
278 /************************************************
279 *
280 * Overriden XBaseMenuWindow functions
281 *
282 ************************************************/
283 protected void doDispose() {
284 super.doDispose();
285 XToolkit.targetDisposedPeer(popupMenuTarget, this);
286 }
287
288 protected void handleEvent(AWTEvent event) {
289 switch(event.getID()) {
290 case MouseEvent.MOUSE_PRESSED:
291 case MouseEvent.MOUSE_RELEASED:
292 case MouseEvent.MOUSE_CLICKED:
293 case MouseEvent.MOUSE_MOVED:
294 case MouseEvent.MOUSE_ENTERED:
295 case MouseEvent.MOUSE_EXITED:
296 case MouseEvent.MOUSE_DRAGGED:
297 doHandleJavaMouseEvent((MouseEvent)event);
298 break;
299 case KeyEvent.KEY_PRESSED:
300 case KeyEvent.KEY_RELEASED:
301 doHandleJavaKeyEvent((KeyEvent)event);
302 break;
303 default:
304 super.handleEvent(event);
305 break;
306 }
307 }
308
309 /************************************************
310 *
311 * Overriden XWindow general-purpose functions
312 *
313 ************************************************/
314 void ungrabInputImpl() {
315 hide();
316 }
317
318 /************************************************
319 *
320 * Overriden XWindow keyboard processing
321 *
322 ************************************************/
323
324 /*
325 * In previous version keys were handled in handleKeyPress.
326 * Now we override this function do disable F10 explicit
327 * processing. All processing is done using KeyEvent.
328 */
329 public void handleKeyPress(XEvent xev) {
330 XKeyEvent xkey = xev.get_xkey();
331 if (log.isLoggable(PlatformLogger.Level.FINE)) {
332 log.fine(xkey.toString());
333 }
334 if (isEventDisabled(xev)) {
335 return;
336 }
337 final Component currentSource = getEventSource();
338 handleKeyPress(xkey);
339 }
340
341 }
--- EOF ---