1 /* 2 * Copyright (c) 2002, 2017, 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 * DEPRECATED: Replaced by setEnabled(boolean). 103 * @see java.awt.peer.MenuItemPeer 104 */ 105 public void enable() { 106 setEnabled( true ); 107 } 108 109 /** 110 * DEPRECATED: Replaced by setEnabled(boolean). 111 * @see java.awt.peer.MenuItemPeer 112 */ 113 public void disable() { 114 setEnabled( false ); 115 } 116 117 /* 118 * From MenuPeer 119 */ 120 /** 121 * addSeparator routines are not used 122 * in peers. Shared code invokes addItem("-") 123 * for adding separators 124 */ 125 public void addSeparator() { 126 if (log.isLoggable(PlatformLogger.Level.FINER)) { 127 log.finer("addSeparator is not implemented"); 128 } 129 } 130 131 /* 132 * From PopupMenuPeer 133 */ 134 @SuppressWarnings("deprecation") 135 public void show(Event e) { 136 target = (Component)e.target; 137 // Get menus from the target. 138 Vector<MenuItem> targetItemVector = getMenuTargetItems(); 139 if (targetItemVector != null) { 140 reloadItems(targetItemVector); 141 //Fix for 6287092: JCK15a: api/java_awt/interactive/event/EventTests.html#EventTest0015 fails, mustang 142 Point tl = target.getLocationOnScreen(); 143 Point pt = new Point(tl.x + e.x, tl.y + e.y); 144 //Fixed 6266513: Incorrect key handling in XAWT popup menu 145 //No item should be selected when showing popup menu 146 if (!ensureCreated()) { 147 return; 148 } 149 Dimension dim = getDesiredSize(); 150 //Fix for 6267162: PIT: Popup Menu gets hidden below the screen when opened 151 //near the periphery of the screen, XToolkit 152 Rectangle bounds = getWindowBounds(pt, dim); 153 reshape(bounds); 154 xSetVisible(true); 155 toFront(); 156 selectItem(null, false); 157 grabInput(); 158 } 159 } 160 161 /************************************************ 162 * 163 * Access to target's fields 164 * 165 ************************************************/ 166 167 //Fix for 6267144: PIT: Popup menu label is not shown, XToolkit 168 Font getTargetFont() { 169 if (popupMenuTarget == null) { 170 return XWindow.getDefaultFont(); 171 } 172 return AWTAccessor.getMenuComponentAccessor() 173 .getFont_NoClientCode(popupMenuTarget); 174 } 175 176 //Fix for 6267144: PIT: Popup menu label is not shown, XToolkit 177 String getTargetLabel() { 178 if (target == null) { 179 return ""; 180 } 181 return AWTAccessor.getMenuItemAccessor().getLabel(popupMenuTarget); 182 } 183 184 //Fix for 6184485: Popup menu is not disabled on XToolkit even when calling setEnabled (false) 185 boolean isTargetEnabled() { 186 if (popupMenuTarget == null) { 187 return false; 188 } 189 return AWTAccessor.getMenuItemAccessor().isEnabled(popupMenuTarget); 190 } 191 192 Vector<MenuItem> getMenuTargetItems() { 193 if (popupMenuTarget == null) { 194 return null; 195 } 196 return AWTAccessor.getMenuAccessor().getItems(popupMenuTarget); 197 } 198 199 /************************************************ 200 * 201 * Utility functions 202 * 203 ************************************************/ 204 205 //Fix for 6267162: PIT: Popup Menu gets hidden below the screen when opened 206 //near the periphery of the screen, XToolkit 207 208 /** 209 * Calculates placement of popup menu window 210 * given origin in global coordinates and 211 * size of menu window. Returns suggested 212 * rectangle for menu window in global coordinates 213 * @param origin the origin point specified in show() 214 * function converted to global coordinates 215 * @param windowSize the desired size of menu's window 216 */ 217 protected Rectangle getWindowBounds(Point origin, Dimension windowSize) { 218 Rectangle globalBounds = new Rectangle(origin.x, origin.y, 0, 0); 219 Rectangle screenBounds = getCurrentGraphicsConfiguration().getBounds(); 220 Rectangle res; 221 res = fitWindowRight(globalBounds, windowSize, screenBounds); 222 if (res != null) { 223 return res; 224 } 225 res = fitWindowLeft(globalBounds, windowSize, screenBounds); 226 if (res != null) { 227 return res; 228 } 229 res = fitWindowBelow(globalBounds, windowSize, screenBounds); 230 if (res != null) { 231 return res; 232 } 233 res = fitWindowAbove(globalBounds, windowSize, screenBounds); 234 if (res != null) { 235 return res; 236 } 237 return fitWindowToScreen(windowSize, screenBounds); 238 } 239 240 /************************************************ 241 * 242 * Overriden XMenuWindow caption-painting functions 243 * Necessary to fix 6267144: PIT: Popup menu label is not shown, XToolkit 244 * 245 ************************************************/ 246 /** 247 * Returns height of menu window's caption. 248 * Can be overriden for popup menus and tear-off menus 249 */ 250 protected Dimension getCaptionSize() { 251 String s = getTargetLabel(); 252 if (s.equals("")) { 253 return null; 254 } 255 Graphics g = getGraphics(); 256 if (g == null) { 257 return null; 258 } 259 try { 260 g.setFont(getTargetFont()); 261 FontMetrics fm = g.getFontMetrics(); 262 String str = getTargetLabel(); 263 int width = fm.stringWidth(str); 264 int height = CAPTION_MARGIN_TOP + fm.getHeight() + CAPTION_SEPARATOR_HEIGHT; 265 Dimension textDimension = new Dimension(width, height); 266 return textDimension; 267 } finally { 268 g.dispose(); 269 } 270 } 271 272 /** 273 * Paints menu window's caption. 274 * Can be overriden for popup menus and tear-off menus. 275 * Default implementation does nothing 276 */ 277 protected void paintCaption(Graphics g, Rectangle rect) { 278 String s = getTargetLabel(); 279 if (s.equals("")) { 280 return; 281 } 282 g.setFont(getTargetFont()); 283 FontMetrics fm = g.getFontMetrics(); 284 String str = getTargetLabel(); 285 int width = fm.stringWidth(str); 286 int textx = rect.x + (rect.width - width) / 2; 287 int texty = rect.y + CAPTION_MARGIN_TOP + fm.getAscent(); 288 int sepy = rect.y + rect.height - CAPTION_SEPARATOR_HEIGHT / 2; 289 g.setColor(isTargetEnabled() ? getForegroundColor() : getDisabledColor()); 290 g.drawString(s, textx, texty); 291 draw3DRect(g, rect.x, sepy, rect.width, 2, false); 292 } 293 294 /************************************************ 295 * 296 * Overriden XBaseMenuWindow functions 297 * 298 ************************************************/ 299 protected void doDispose() { 300 super.doDispose(); 301 XToolkit.targetDisposedPeer(popupMenuTarget, this); 302 } 303 304 protected void handleEvent(AWTEvent event) { 305 switch(event.getID()) { 306 case MouseEvent.MOUSE_PRESSED: 307 case MouseEvent.MOUSE_RELEASED: 308 case MouseEvent.MOUSE_CLICKED: 309 case MouseEvent.MOUSE_MOVED: 310 case MouseEvent.MOUSE_ENTERED: 311 case MouseEvent.MOUSE_EXITED: 312 case MouseEvent.MOUSE_DRAGGED: 313 doHandleJavaMouseEvent((MouseEvent)event); 314 break; 315 case KeyEvent.KEY_PRESSED: 316 case KeyEvent.KEY_RELEASED: 317 doHandleJavaKeyEvent((KeyEvent)event); 318 break; 319 default: 320 super.handleEvent(event); 321 break; 322 } 323 } 324 325 /************************************************ 326 * 327 * Overriden XWindow general-purpose functions 328 * 329 ************************************************/ 330 void ungrabInputImpl() { 331 hide(); 332 } 333 334 /************************************************ 335 * 336 * Overriden XWindow keyboard processing 337 * 338 ************************************************/ 339 340 /* 341 * In previous version keys were handled in handleKeyPress. 342 * Now we override this function do disable F10 explicit 343 * processing. All processing is done using KeyEvent. 344 */ 345 public void handleKeyPress(XEvent xev) { 346 XKeyEvent xkey = xev.get_xkey(); 347 if (log.isLoggable(PlatformLogger.Level.FINE)) { 348 log.fine(xkey.toString()); 349 } 350 if (isEventDisabled(xev)) { 351 return; 352 } 353 final Component currentSource = getEventSource(); 354 handleKeyPress(xkey); 355 } 356 357 } --- EOF ---