1 /* 2 * Copyright (c) 2003, 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 26 package sun.awt.X11; 27 28 import java.awt.*; 29 import sun.awt.*; 30 import java.util.*; 31 import sun.util.logging.PlatformLogger; 32 33 public class XBaseWindow { 34 private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XBaseWindow"); 35 private static final PlatformLogger insLog = PlatformLogger.getLogger("sun.awt.X11.insets.XBaseWindow"); 36 private static final PlatformLogger eventLog = PlatformLogger.getLogger("sun.awt.X11.event.XBaseWindow"); 37 private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.awt.X11.focus.XBaseWindow"); 38 private static final PlatformLogger grabLog = PlatformLogger.getLogger("sun.awt.X11.grab.XBaseWindow"); 39 40 public static final String 41 PARENT_WINDOW = "parent window", // parent window, Long 42 BOUNDS = "bounds", // bounds of the window, Rectangle 43 OVERRIDE_REDIRECT = "overrideRedirect", // override_redirect setting, Boolean 44 EVENT_MASK = "event mask", // event mask, Integer 45 VALUE_MASK = "value mask", // value mask, Long 46 BORDER_PIXEL = "border pixel", // border pixel value, Integer 47 COLORMAP = "color map", // color map, Long 48 DEPTH = "visual depth", // depth, Integer 49 VISUAL_CLASS = "visual class", // visual class, Integer 50 VISUAL = "visual", // visual, Long 51 EMBEDDED = "embedded", // is embedded?, Boolean 52 DELAYED = "delayed", // is creation delayed?, Boolean 53 PARENT = "parent", // parent peer 54 BACKGROUND_PIXMAP = "pixmap", // background pixmap 55 VISIBLE = "visible", // whether it is visible by default 56 SAVE_UNDER = "save under", // save content under this window 57 BACKING_STORE = "backing store", // enables double buffering 58 BIT_GRAVITY = "bit gravity"; // copy old content on geometry change 59 private XCreateWindowParams delayedParams; 60 61 Set<Long> children = new HashSet<Long>(); 62 long window; 63 boolean visible; 64 boolean mapped; 65 boolean embedded; 66 Rectangle maxBounds; 67 volatile XBaseWindow parentWindow; 68 69 private boolean disposed; 70 71 private long screen; 72 private XSizeHints hints; 73 private XWMHints wmHints; 74 75 static final int MIN_SIZE = 1; 76 static final int DEF_LOCATION = 1; 77 78 private static XAtom wm_client_leader; 79 80 static enum InitialiseState { 81 INITIALISING, 82 INITIALISED, 83 FAILED_INITIALISATION 84 }; 85 86 private InitialiseState initialising; 87 88 int x; 89 int y; 90 int width; 91 int height; 92 awtLock()93 void awtLock() { 94 XToolkit.awtLock(); 95 } 96 awtUnlock()97 void awtUnlock() { 98 XToolkit.awtUnlock(); 99 } 100 awtLockNotifyAll()101 void awtLockNotifyAll() { 102 XToolkit.awtLockNotifyAll(); 103 } 104 awtLockWait()105 void awtLockWait() throws InterruptedException { 106 XToolkit.awtLockWait(); 107 } 108 109 // To prevent errors from overriding obsolete methods init(long parentWindow, Rectangle bounds)110 protected final void init(long parentWindow, Rectangle bounds) {} preInit()111 protected final void preInit() {} postInit()112 protected final void postInit() {} 113 114 // internal lock for synchronizing state changes and paint calls, initialized in preInit. 115 // the order with other locks: AWTLock -> stateLock 116 static class StateLock { } 117 protected StateLock state_lock; 118 119 /** 120 * Called for delayed inits during construction 121 */ instantPreInit(XCreateWindowParams params)122 void instantPreInit(XCreateWindowParams params) { 123 state_lock = new StateLock(); 124 } 125 126 /** 127 * Called before window creation, descendants should override to initialize the data, 128 * initialize params. 129 */ preInit(XCreateWindowParams params)130 void preInit(XCreateWindowParams params) { 131 state_lock = new StateLock(); 132 embedded = Boolean.TRUE.equals(params.get(EMBEDDED)); 133 visible = Boolean.TRUE.equals(params.get(VISIBLE)); 134 135 Object parent = params.get(PARENT); 136 if (parent instanceof XBaseWindow) { 137 parentWindow = (XBaseWindow)parent; 138 } else { 139 Long parentWindowID = (Long)params.get(PARENT_WINDOW); 140 if (parentWindowID != null) { 141 parentWindow = XToolkit.windowToXWindow(parentWindowID); 142 } 143 } 144 145 Long eventMask = (Long)params.get(EVENT_MASK); 146 if (eventMask != null) { 147 long mask = eventMask.longValue(); 148 mask |= XConstants.SubstructureNotifyMask; 149 params.put(EVENT_MASK, mask); 150 } 151 152 screen = -1; 153 } 154 155 /** 156 * Called after window creation, descendants should override to initialize Window 157 * with class-specific values and perform post-initialization actions. 158 */ postInit(XCreateWindowParams params)159 void postInit(XCreateWindowParams params) { 160 if (log.isLoggable(PlatformLogger.Level.FINE)) { 161 log.fine("WM name is " + getWMName()); 162 } 163 updateWMName(); 164 165 // Set WM_CLIENT_LEADER property 166 initClientLeader(); 167 } 168 169 /** 170 * Creates window using parameters {@code params} 171 * If params contain flag DELAYED doesn't do anything. 172 * Note: Descendants can call this method to create the window 173 * at the time different to instance construction. 174 */ init(XCreateWindowParams params)175 protected final void init(XCreateWindowParams params) { 176 awtLock(); 177 initialising = InitialiseState.INITIALISING; 178 awtUnlock(); 179 180 try { 181 if (!Boolean.TRUE.equals(params.get(DELAYED))) { 182 preInit(params); 183 create(params); 184 postInit(params); 185 } else { 186 instantPreInit(params); 187 delayedParams = params; 188 } 189 awtLock(); 190 initialising = InitialiseState.INITIALISED; 191 awtLockNotifyAll(); 192 awtUnlock(); 193 } catch (RuntimeException re) { 194 awtLock(); 195 initialising = InitialiseState.FAILED_INITIALISATION; 196 awtLockNotifyAll(); 197 awtUnlock(); 198 throw re; 199 } catch (Throwable t) { 200 log.warning("Exception during peer initialization", t); 201 awtLock(); 202 initialising = InitialiseState.FAILED_INITIALISATION; 203 awtLockNotifyAll(); 204 awtUnlock(); 205 } 206 } 207 checkInitialised()208 public boolean checkInitialised() { 209 awtLock(); 210 try { 211 switch (initialising) { 212 case INITIALISED: 213 return true; 214 case INITIALISING: 215 try { 216 while (initialising != InitialiseState.INITIALISED) { 217 awtLockWait(); 218 } 219 } catch (InterruptedException ie) { 220 return false; 221 } 222 return true; 223 case FAILED_INITIALISATION: 224 return false; 225 default: 226 return false; 227 } 228 } finally { 229 awtUnlock(); 230 } 231 } 232 233 /* 234 * Creates an invisible InputOnly window without an associated Component. 235 */ XBaseWindow()236 XBaseWindow() { 237 this(new XCreateWindowParams()); 238 } 239 240 /** 241 * Creates normal child window 242 */ XBaseWindow(long parentWindow, Rectangle bounds)243 XBaseWindow(long parentWindow, Rectangle bounds) { 244 this(new XCreateWindowParams(new Object[] { 245 BOUNDS, bounds, 246 PARENT_WINDOW, Long.valueOf(parentWindow)})); 247 } 248 249 /** 250 * Creates top-level window 251 */ XBaseWindow(Rectangle bounds)252 XBaseWindow(Rectangle bounds) { 253 this(new XCreateWindowParams(new Object[] { 254 BOUNDS, bounds 255 })); 256 } 257 XBaseWindow(XCreateWindowParams params)258 public XBaseWindow (XCreateWindowParams params) { 259 init(params); 260 } 261 262 /* This create is used by the XEmbeddedFramePeer since it has to create the window 263 as a child of the netscape window. This netscape window is passed in as wid */ XBaseWindow(long parentWindow)264 XBaseWindow(long parentWindow) { 265 this(new XCreateWindowParams(new Object[] { 266 PARENT_WINDOW, Long.valueOf(parentWindow), 267 EMBEDDED, Boolean.TRUE 268 })); 269 } 270 271 /** 272 * Verifies that all required parameters are set. If not, sets them to default values. 273 * Verifies values of critical parameters, adjust their values when needed. 274 * @throws IllegalArgumentException if params is null 275 */ checkParams(XCreateWindowParams params)276 protected void checkParams(XCreateWindowParams params) { 277 if (params == null) { 278 throw new IllegalArgumentException("Window creation parameters are null"); 279 } 280 params.putIfNull(PARENT_WINDOW, Long.valueOf(XToolkit.getDefaultRootWindow())); 281 params.putIfNull(BOUNDS, new Rectangle(DEF_LOCATION, DEF_LOCATION, MIN_SIZE, MIN_SIZE)); 282 params.putIfNull(DEPTH, Integer.valueOf((int)XConstants.CopyFromParent)); 283 params.putIfNull(VISUAL, Long.valueOf(XConstants.CopyFromParent)); 284 params.putIfNull(VISUAL_CLASS, Integer.valueOf(XConstants.InputOnly)); 285 params.putIfNull(VALUE_MASK, Long.valueOf(XConstants.CWEventMask)); 286 Rectangle bounds = (Rectangle)params.get(BOUNDS); 287 bounds.width = Math.max(MIN_SIZE, bounds.width); 288 bounds.height = Math.max(MIN_SIZE, bounds.height); 289 290 Long eventMaskObj = (Long)params.get(EVENT_MASK); 291 long eventMask = eventMaskObj != null ? eventMaskObj.longValue() : 0; 292 // We use our own synthetic grab see XAwtState.getGrabWindow() 293 // (see X vol. 1, 8.3.3.2) 294 eventMask |= XConstants.PropertyChangeMask | XConstants.OwnerGrabButtonMask; 295 params.put(EVENT_MASK, Long.valueOf(eventMask)); 296 } 297 298 /** 299 * Returns scale factor of the window. It is used to convert native 300 * coordinates to local and vice verse. 301 */ getScale()302 protected int getScale() { 303 return 1; 304 } 305 scaleUp(int x)306 protected int scaleUp(int x) { 307 return x; 308 } 309 scaleDown(int x)310 protected int scaleDown(int x) { 311 return x; 312 } 313 314 /** 315 * Creates window with parameters specified by {@code params} 316 * @see #init 317 */ create(XCreateWindowParams params)318 private void create(XCreateWindowParams params) { 319 XToolkit.awtLock(); 320 try { 321 XSetWindowAttributes xattr = new XSetWindowAttributes(); 322 try { 323 checkParams(params); 324 325 long value_mask = ((Long)params.get(VALUE_MASK)).longValue(); 326 327 Long eventMask = (Long)params.get(EVENT_MASK); 328 xattr.set_event_mask(eventMask.longValue()); 329 value_mask |= XConstants.CWEventMask; 330 331 Long border_pixel = (Long)params.get(BORDER_PIXEL); 332 if (border_pixel != null) { 333 xattr.set_border_pixel(border_pixel.longValue()); 334 value_mask |= XConstants.CWBorderPixel; 335 } 336 337 Long colormap = (Long)params.get(COLORMAP); 338 if (colormap != null) { 339 xattr.set_colormap(colormap.longValue()); 340 value_mask |= XConstants.CWColormap; 341 } 342 Long background_pixmap = (Long)params.get(BACKGROUND_PIXMAP); 343 if (background_pixmap != null) { 344 xattr.set_background_pixmap(background_pixmap.longValue()); 345 value_mask |= XConstants.CWBackPixmap; 346 } 347 348 Long parentWindow = (Long)params.get(PARENT_WINDOW); 349 Rectangle bounds = (Rectangle)params.get(BOUNDS); 350 Integer depth = (Integer)params.get(DEPTH); 351 Integer visual_class = (Integer)params.get(VISUAL_CLASS); 352 Long visual = (Long)params.get(VISUAL); 353 Boolean overrideRedirect = (Boolean)params.get(OVERRIDE_REDIRECT); 354 if (overrideRedirect != null) { 355 xattr.set_override_redirect(overrideRedirect.booleanValue()); 356 value_mask |= XConstants.CWOverrideRedirect; 357 } 358 359 Boolean saveUnder = (Boolean)params.get(SAVE_UNDER); 360 if (saveUnder != null) { 361 xattr.set_save_under(saveUnder.booleanValue()); 362 value_mask |= XConstants.CWSaveUnder; 363 } 364 365 Integer backingStore = (Integer)params.get(BACKING_STORE); 366 if (backingStore != null) { 367 xattr.set_backing_store(backingStore.intValue()); 368 value_mask |= XConstants.CWBackingStore; 369 } 370 371 Integer bitGravity = (Integer)params.get(BIT_GRAVITY); 372 if (bitGravity != null) { 373 xattr.set_bit_gravity(bitGravity.intValue()); 374 value_mask |= XConstants.CWBitGravity; 375 } 376 377 if (log.isLoggable(PlatformLogger.Level.FINE)) { 378 log.fine("Creating window for " + this + " with the following attributes: \n" + params); 379 } 380 window = XlibWrapper.XCreateWindow(XToolkit.getDisplay(), 381 parentWindow.longValue(), 382 scaleUp(bounds.x), 383 scaleUp(bounds.y), 384 scaleUp(bounds.width), 385 scaleUp(bounds.height), 386 0, // border 387 depth.intValue(), // depth 388 visual_class.intValue(), // class 389 visual.longValue(), // visual 390 value_mask, // value mask 391 xattr.pData); // attributes 392 393 if (window == 0) { 394 throw new IllegalStateException("Couldn't create window because of wrong parameters. Run with NOISY_AWT to see details"); 395 } 396 XToolkit.addToWinMap(window, this); 397 } finally { 398 xattr.dispose(); 399 } 400 } finally { 401 XToolkit.awtUnlock(); 402 } 403 } 404 getDelayedParams()405 public XCreateWindowParams getDelayedParams() { 406 return delayedParams; 407 } 408 getWMName()409 protected String getWMName() { 410 return XToolkit.getCorrectXIDString(getClass().getName()); 411 } 412 initClientLeader()413 protected void initClientLeader() { 414 XToolkit.awtLock(); 415 try { 416 if (wm_client_leader == null) { 417 wm_client_leader = XAtom.get("WM_CLIENT_LEADER"); 418 } 419 wm_client_leader.setWindowProperty(this, getXAWTRootWindow()); 420 } finally { 421 XToolkit.awtUnlock(); 422 } 423 } 424 getXAWTRootWindow()425 static XRootWindow getXAWTRootWindow() { 426 return XRootWindow.getInstance(); 427 } 428 destroy()429 void destroy() { 430 XToolkit.awtLock(); 431 try { 432 if (hints != null) { 433 XlibWrapper.XFree(hints.pData); 434 hints = null; 435 } 436 XToolkit.removeFromWinMap(getWindow(), this); 437 XlibWrapper.XDestroyWindow(XToolkit.getDisplay(), getWindow()); 438 if (XPropertyCache.isCachingSupported()) { 439 XPropertyCache.clearCache(window); 440 } 441 window = -1; 442 if( !isDisposed() ) { 443 setDisposed( true ); 444 } 445 446 XAwtState.getGrabWindow(); // Magic - getGrabWindow clear state if grabbing window is disposed of. 447 } finally { 448 XToolkit.awtUnlock(); 449 } 450 } 451 flush()452 void flush() { 453 XToolkit.awtLock(); 454 try { 455 XlibWrapper.XFlush(XToolkit.getDisplay()); 456 } finally { 457 XToolkit.awtUnlock(); 458 } 459 } 460 461 /** 462 * Helper function to set W 463 */ setWMHints(XWMHints hints)464 public final void setWMHints(XWMHints hints) { 465 XToolkit.awtLock(); 466 try { 467 XlibWrapper.XSetWMHints(XToolkit.getDisplay(), getWindow(), hints.pData); 468 } finally { 469 XToolkit.awtUnlock(); 470 } 471 } 472 getWMHints()473 public XWMHints getWMHints() { 474 if (wmHints == null) { 475 wmHints = new XWMHints(XlibWrapper.XAllocWMHints()); 476 // XlibWrapper.XGetWMHints(XToolkit.getDisplay(), 477 // getWindow(), 478 // wmHints.pData); 479 } 480 return wmHints; 481 } 482 483 484 /* 485 * Call this method under AWTLock. 486 * The lock should be acquired untill all operations with XSizeHints are completed. 487 */ getHints()488 public XSizeHints getHints() { 489 if (hints == null) { 490 long p_hints = XlibWrapper.XAllocSizeHints(); 491 hints = new XSizeHints(p_hints); 492 // XlibWrapper.XGetWMNormalHints(XToolkit.getDisplay(), getWindow(), p_hints, XlibWrapper.larg1); 493 // TODO: Shouldn't we listen for WM updates on this property? 494 } 495 return hints; 496 } 497 setSizeHints(long flags, int x, int y, int width, int height)498 public void setSizeHints(long flags, int x, int y, int width, int height) { 499 if (insLog.isLoggable(PlatformLogger.Level.FINER)) { 500 insLog.finer("Setting hints, flags " + XlibWrapper.hintsToString(flags)); 501 } 502 XToolkit.awtLock(); 503 try { 504 XSizeHints hints = getHints(); 505 // Note: if PPosition is not set in flags this means that 506 // we want to reset PPosition in hints. This is necessary 507 // for locationByPlatform functionality 508 if ((flags & XUtilConstants.PPosition) != 0) { 509 hints.set_x(scaleUp(x)); 510 hints.set_y(scaleUp(y)); 511 } 512 if ((flags & XUtilConstants.PSize) != 0) { 513 hints.set_width(scaleUp(width)); 514 hints.set_height(scaleUp(height)); 515 } else if ((hints.get_flags() & XUtilConstants.PSize) != 0) { 516 flags |= XUtilConstants.PSize; 517 } 518 if ((flags & XUtilConstants.PMinSize) != 0) { 519 hints.set_min_width(scaleUp(width)); 520 hints.set_min_height(scaleUp(height)); 521 } else if ((hints.get_flags() & XUtilConstants.PMinSize) != 0) { 522 flags |= XUtilConstants.PMinSize; 523 //Fix for 4320050: Minimum size for java.awt.Frame is not being enforced. 524 //We don't need to reset minimum size if it's already set 525 } 526 if ((flags & XUtilConstants.PMaxSize) != 0) { 527 if (maxBounds != null) { 528 if (maxBounds.width != Integer.MAX_VALUE) { 529 hints.set_max_width(scaleUp(maxBounds.width)); 530 } else { 531 hints.set_max_width(XToolkit.getMaxWindowWidthInPixels()); 532 } 533 if (maxBounds.height != Integer.MAX_VALUE) { 534 hints.set_max_height(scaleUp(maxBounds.height)); 535 } else { 536 hints.set_max_height(XToolkit.getMaxWindowHeightInPixels()); 537 } 538 } else { 539 hints.set_max_width(scaleUp(width)); 540 hints.set_max_height(scaleUp(height)); 541 } 542 } else if ((hints.get_flags() & XUtilConstants.PMaxSize) != 0) { 543 flags |= XUtilConstants.PMaxSize; 544 if (maxBounds != null) { 545 if (maxBounds.width != Integer.MAX_VALUE) { 546 hints.set_max_width(scaleUp(maxBounds.width)); 547 } else { 548 hints.set_max_width(XToolkit.getMaxWindowWidthInPixels()); 549 } 550 if (maxBounds.height != Integer.MAX_VALUE) { 551 hints.set_max_height(scaleUp(maxBounds.height)); 552 } else { 553 hints.set_max_height(XToolkit.getMaxWindowHeightInPixels()); 554 } 555 } else { 556 // Leave intact 557 } 558 } 559 flags |= XUtilConstants.PWinGravity; 560 hints.set_flags(flags); 561 hints.set_win_gravity(XConstants.NorthWestGravity); 562 if (insLog.isLoggable(PlatformLogger.Level.FINER)) { 563 insLog.finer("Setting hints, resulted flags " + XlibWrapper.hintsToString(flags) + 564 ", values " + hints); 565 } 566 XlibWrapper.XSetWMNormalHints(XToolkit.getDisplay(), getWindow(), hints.pData); 567 } finally { 568 XToolkit.awtUnlock(); 569 } 570 } 571 isMinSizeSet()572 public boolean isMinSizeSet() { 573 XSizeHints hints = getHints(); 574 long flags = hints.get_flags(); 575 return ((flags & XUtilConstants.PMinSize) == XUtilConstants.PMinSize); 576 } 577 578 /** 579 * This lock object can be used to protect instance data from concurrent access 580 * by two threads. If both state lock and AWT lock are taken, AWT Lock should be taken first. 581 */ getStateLock()582 Object getStateLock() { 583 return state_lock; 584 } 585 getWindow()586 public long getWindow() { 587 return window; 588 } getContentWindow()589 public long getContentWindow() { 590 return window; 591 } 592 getContentXWindow()593 public XBaseWindow getContentXWindow() { 594 return XToolkit.windowToXWindow(getContentWindow()); 595 } 596 getBounds()597 public Rectangle getBounds() { 598 return new Rectangle(x, y, width, height); 599 } getSize()600 public Dimension getSize() { 601 return new Dimension(width, height); 602 } 603 604 toFront()605 public void toFront() { 606 XToolkit.awtLock(); 607 try { 608 XlibWrapper.XRaiseWindow(XToolkit.getDisplay(), getWindow()); 609 } finally { 610 XToolkit.awtUnlock(); 611 } 612 } xRequestFocus(long time)613 public void xRequestFocus(long time) { 614 XToolkit.awtLock(); 615 try { 616 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { 617 focusLog.finer("XSetInputFocus on " + Long.toHexString(getWindow()) + " with time " + time); 618 } 619 XlibWrapper.XSetInputFocus2(XToolkit.getDisplay(), getWindow(), time); 620 } finally { 621 XToolkit.awtUnlock(); 622 } 623 } xRequestFocus()624 public void xRequestFocus() { 625 XToolkit.awtLock(); 626 try { 627 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { 628 focusLog.finer("XSetInputFocus on " + Long.toHexString(getWindow())); 629 } 630 XlibWrapper.XSetInputFocus(XToolkit.getDisplay(), getWindow()); 631 } finally { 632 XToolkit.awtUnlock(); 633 } 634 } 635 xGetInputFocus()636 public static long xGetInputFocus() { 637 XToolkit.awtLock(); 638 try { 639 return XlibWrapper.XGetInputFocus(XToolkit.getDisplay()); 640 } finally { 641 XToolkit.awtUnlock(); 642 } 643 } 644 xSetVisible(boolean visible)645 public void xSetVisible(boolean visible) { 646 if (log.isLoggable(PlatformLogger.Level.FINE)) { 647 log.fine("Setting visible on " + this + " to " + visible); 648 } 649 XToolkit.awtLock(); 650 try { 651 this.visible = visible; 652 if (visible) { 653 XlibWrapper.XMapWindow(XToolkit.getDisplay(), getWindow()); 654 } 655 else { 656 XlibWrapper.XUnmapWindow(XToolkit.getDisplay(), getWindow()); 657 } 658 XlibWrapper.XFlush(XToolkit.getDisplay()); 659 } finally { 660 XToolkit.awtUnlock(); 661 } 662 } 663 isMapped()664 boolean isMapped() { 665 return mapped; 666 } 667 updateWMName()668 void updateWMName() { 669 String name = getWMName(); 670 XToolkit.awtLock(); 671 try { 672 if (name == null) { 673 name = " "; 674 } 675 XAtom nameAtom = XAtom.get(XAtom.XA_WM_NAME); 676 nameAtom.setProperty(getWindow(), name); 677 XAtom netNameAtom = XAtom.get("_NET_WM_NAME"); 678 netNameAtom.setPropertyUTF8(getWindow(), name); 679 } finally { 680 XToolkit.awtUnlock(); 681 } 682 } setWMClass(String[] cl)683 void setWMClass(String[] cl) { 684 if (cl.length != 2) { 685 throw new IllegalArgumentException("WM_CLASS_NAME consists of exactly two strings"); 686 } 687 XToolkit.awtLock(); 688 try { 689 XAtom xa = XAtom.get(XAtom.XA_WM_CLASS); 690 xa.setProperty8(getWindow(), cl[0] + '\0' + cl[1] + '\0'); 691 } finally { 692 XToolkit.awtUnlock(); 693 } 694 } 695 isVisible()696 boolean isVisible() { 697 return visible; 698 } 699 getScreenOfWindow(long window)700 static long getScreenOfWindow(long window) { 701 XToolkit.awtLock(); 702 try { 703 return XlibWrapper.getScreenOfWindow(XToolkit.getDisplay(), window); 704 } finally { 705 XToolkit.awtUnlock(); 706 } 707 } getScreenNumber()708 long getScreenNumber() { 709 XToolkit.awtLock(); 710 try { 711 return XlibWrapper.XScreenNumberOfScreen(getScreen()); 712 } finally { 713 XToolkit.awtUnlock(); 714 } 715 } 716 getScreen()717 long getScreen() { 718 if (screen == -1) { // Not initialized 719 screen = getScreenOfWindow(window); 720 } 721 return screen; 722 } 723 xSetBounds(Rectangle bounds)724 public void xSetBounds(Rectangle bounds) { 725 xSetBounds(bounds.x, bounds.y, bounds.width, bounds.height); 726 } 727 xSetBounds(int x, int y, int width, int height)728 public void xSetBounds(int x, int y, int width, int height) { 729 if (getWindow() == 0) { 730 insLog.warning("Attempt to resize uncreated window"); 731 throw new IllegalStateException("Attempt to resize uncreated window"); 732 } 733 if (insLog.isLoggable(PlatformLogger.Level.FINE)) { 734 insLog.fine("Setting bounds on " + this + " to (" + x + ", " + y + "), " + width + "x" + height); 735 } 736 width = Math.max(MIN_SIZE, width); 737 height = Math.max(MIN_SIZE, height); 738 XToolkit.awtLock(); 739 try { 740 XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), getWindow(), 741 scaleUp(x), scaleUp(y), 742 scaleUp(width), scaleUp(height)); 743 } finally { 744 XToolkit.awtUnlock(); 745 } 746 } 747 748 /** 749 * Translate coordinates from one window into another. Optimized 750 * for XAWT - uses cached data when possible. Preferable over 751 * pure XTranslateCoordinates. 752 * @return coordinates relative to dst, or null if error happened 753 */ toOtherWindow(long src, long dst, int x, int y)754 static Point toOtherWindow(long src, long dst, int x, int y) { 755 Point rpt = new Point(0, 0); 756 757 // Check if both windows belong to XAWT - then no X calls are necessary 758 759 XBaseWindow srcPeer = XToolkit.windowToXWindow(src); 760 XBaseWindow dstPeer = XToolkit.windowToXWindow(dst); 761 762 if (srcPeer != null && dstPeer != null) { 763 // (x, y) is relative to src 764 rpt.x = x + srcPeer.getAbsoluteX() - dstPeer.getAbsoluteX(); 765 rpt.y = y + srcPeer.getAbsoluteY() - dstPeer.getAbsoluteY(); 766 } else if (dstPeer != null && XlibUtil.isRoot(src, dstPeer.getScreenNumber())) { 767 // from root into peer 768 rpt.x = x - dstPeer.getAbsoluteX(); 769 rpt.y = y - dstPeer.getAbsoluteY(); 770 } else if (srcPeer != null && XlibUtil.isRoot(dst, srcPeer.getScreenNumber())) { 771 // from peer into root 772 rpt.x = x + srcPeer.getAbsoluteX(); 773 rpt.y = y + srcPeer.getAbsoluteY(); 774 } else { 775 int scale = srcPeer == null ? 1 : srcPeer.getScale(); 776 rpt = XlibUtil.translateCoordinates(src, dst, new Point(x, y), scale); 777 } 778 return rpt; 779 } 780 781 /* 782 * Convert to global coordinates. 783 */ toGlobal(Rectangle rec)784 Rectangle toGlobal(Rectangle rec) { 785 Point p = toGlobal(rec.getLocation()); 786 Rectangle newRec = new Rectangle(rec); 787 if (p != null) { 788 newRec.setLocation(p); 789 } 790 return newRec; 791 } 792 toGlobal(Point pt)793 Point toGlobal(Point pt) { 794 Point p = toGlobal(pt.x, pt.y); 795 if (p != null) { 796 return p; 797 } else { 798 return new Point(pt); 799 } 800 } 801 toGlobal(int x, int y)802 Point toGlobal(int x, int y) { 803 long root; 804 XToolkit.awtLock(); 805 try { 806 root = XlibWrapper.RootWindow(XToolkit.getDisplay(), 807 getScreenNumber()); 808 } finally { 809 XToolkit.awtUnlock(); 810 } 811 Point p = toOtherWindow(getContentWindow(), root, x, y); 812 if (p != null) { 813 return p; 814 } else { 815 return new Point(x, y); 816 } 817 } 818 819 /* 820 * Convert to local coordinates. 821 */ toLocal(Point pt)822 Point toLocal(Point pt) { 823 Point p = toLocal(pt.x, pt.y); 824 if (p != null) { 825 return p; 826 } else { 827 return new Point(pt); 828 } 829 } 830 toLocal(int x, int y)831 Point toLocal(int x, int y) { 832 long root; 833 XToolkit.awtLock(); 834 try { 835 root = XlibWrapper.RootWindow(XToolkit.getDisplay(), 836 getScreenNumber()); 837 } finally { 838 XToolkit.awtUnlock(); 839 } 840 Point p = toOtherWindow(root, getContentWindow(), x, y); 841 if (p != null) { 842 return p; 843 } else { 844 return new Point(x, y); 845 } 846 } 847 848 /** 849 * We should always grab both keyboard and pointer to control event flow 850 * on popups. This also simplifies synthetic grab implementation. 851 * The active grab overrides activated automatic grab. 852 */ grabInput()853 public boolean grabInput() { 854 if (grabLog.isLoggable(PlatformLogger.Level.FINE)) { 855 grabLog.fine("Grab input on {0}", this); 856 } 857 858 XToolkit.awtLock(); 859 try { 860 if (XAwtState.getGrabWindow() == this && 861 XAwtState.isManualGrab()) 862 { 863 grabLog.fine(" Already Grabbed"); 864 return true; 865 } 866 //6273031: PIT. Choice drop down does not close once it is right clicked to show a popup menu 867 //remember previous window having grab and if it's not null ungrab it. 868 XBaseWindow prevGrabWindow = XAwtState.getGrabWindow(); 869 final int eventMask = (int) (XConstants.ButtonPressMask | XConstants.ButtonReleaseMask 870 | XConstants.EnterWindowMask | XConstants.LeaveWindowMask | XConstants.PointerMotionMask 871 | XConstants.ButtonMotionMask); 872 final int ownerEvents = 1; 873 874 875 //6714678: IDE (Netbeans, Eclipse, JDeveloper) Debugger hangs 876 //process on Linux 877 //The user must pass the sun.awt.disablegrab property to disable 878 //taking grabs. This prevents hanging of the GUI when a breakpoint 879 //is hit while a popup window taking the grab is open. 880 if (!XToolkit.getSunAwtDisableGrab()) { 881 int ptrGrab = XlibWrapper.XGrabPointer(XToolkit.getDisplay(), 882 getContentWindow(), ownerEvents, eventMask, XConstants.GrabModeAsync, 883 XConstants.GrabModeAsync, XConstants.None, (XWM.isMotif() ? XToolkit.arrowCursor : XConstants.None), 884 XConstants.CurrentTime); 885 // Check grab results to be consistent with X server grab 886 if (ptrGrab != XConstants.GrabSuccess) { 887 XlibWrapper.XUngrabPointer(XToolkit.getDisplay(), XConstants.CurrentTime); 888 XAwtState.setGrabWindow(null); 889 grabLog.fine(" Grab Failure - mouse"); 890 return false; 891 } 892 893 int keyGrab = XlibWrapper.XGrabKeyboard(XToolkit.getDisplay(), 894 getContentWindow(), ownerEvents, XConstants.GrabModeAsync, XConstants.GrabModeAsync, 895 XConstants.CurrentTime); 896 if (keyGrab != XConstants.GrabSuccess) { 897 XlibWrapper.XUngrabPointer(XToolkit.getDisplay(), XConstants.CurrentTime); 898 XlibWrapper.XUngrabKeyboard(XToolkit.getDisplay(), XConstants.CurrentTime); 899 XAwtState.setGrabWindow(null); 900 grabLog.fine(" Grab Failure - keyboard"); 901 return false; 902 } 903 } 904 if (prevGrabWindow != null) { 905 prevGrabWindow.ungrabInputImpl(); 906 } 907 XAwtState.setGrabWindow(this); 908 grabLog.fine(" Grab - success"); 909 return true; 910 } finally { 911 XToolkit.awtUnlock(); 912 } 913 } 914 ungrabInput()915 static void ungrabInput() { 916 XToolkit.awtLock(); 917 try { 918 XBaseWindow grabWindow = XAwtState.getGrabWindow(); 919 if (grabLog.isLoggable(PlatformLogger.Level.FINE)) { 920 grabLog.fine("UnGrab input on {0}", grabWindow); 921 } 922 if (grabWindow != null) { 923 grabWindow.ungrabInputImpl(); 924 if (!XToolkit.getSunAwtDisableGrab()) { 925 XlibWrapper.XUngrabPointer(XToolkit.getDisplay(), XConstants.CurrentTime); 926 XlibWrapper.XUngrabKeyboard(XToolkit.getDisplay(), XConstants.CurrentTime); 927 } 928 XAwtState.setGrabWindow(null); 929 // we need to call XFlush() here to force ungrab 930 // see 6384219 for details 931 XlibWrapper.XFlush(XToolkit.getDisplay()); 932 } 933 } finally { 934 XToolkit.awtUnlock(); 935 } 936 } 937 938 // called from ungrabInput, used in popup windows to hide theirselfs in ungrabbing ungrabInputImpl()939 void ungrabInputImpl() { 940 } 941 checkSecurity()942 static void checkSecurity() { 943 if (XToolkit.isSecurityWarningEnabled() && XToolkit.isToolkitThread()) { 944 StackTraceElement[] stack = (new Throwable()).getStackTrace(); 945 log.warning(stack[1] + ": Security violation: calling user code on toolkit thread"); 946 } 947 } 948 getChildren()949 public Set<Long> getChildren() { 950 synchronized (getStateLock()) { 951 return new HashSet<Long>(children); 952 } 953 } 954 955 // -------------- Event handling ---------------- handleMapNotifyEvent(XEvent xev)956 public void handleMapNotifyEvent(XEvent xev) { 957 mapped = true; 958 } handleUnmapNotifyEvent(XEvent xev)959 public void handleUnmapNotifyEvent(XEvent xev) { 960 mapped = false; 961 } handleReparentNotifyEvent(XEvent xev)962 public void handleReparentNotifyEvent(XEvent xev) { 963 if (eventLog.isLoggable(PlatformLogger.Level.FINER)) { 964 XReparentEvent msg = xev.get_xreparent(); 965 eventLog.finer(msg.toString()); 966 } 967 } handlePropertyNotify(XEvent xev)968 public void handlePropertyNotify(XEvent xev) { 969 XPropertyEvent msg = xev.get_xproperty(); 970 if (XPropertyCache.isCachingSupported()) { 971 XPropertyCache.clearCache(window, XAtom.get(msg.get_atom())); 972 } 973 if (eventLog.isLoggable(PlatformLogger.Level.FINER)) { 974 eventLog.finer("{0}", msg); 975 } 976 } 977 handleDestroyNotify(XEvent xev)978 public void handleDestroyNotify(XEvent xev) { 979 XAnyEvent xany = xev.get_xany(); 980 if (xany.get_window() == getWindow()) { 981 XToolkit.removeFromWinMap(getWindow(), this); 982 if (XPropertyCache.isCachingSupported()) { 983 XPropertyCache.clearCache(getWindow()); 984 } 985 } 986 if (xany.get_window() != getWindow()) { 987 synchronized (getStateLock()) { 988 children.remove(xany.get_window()); 989 } 990 } 991 } 992 handleCreateNotify(XEvent xev)993 public void handleCreateNotify(XEvent xev) { 994 XAnyEvent xany = xev.get_xany(); 995 if (xany.get_window() != getWindow()) { 996 synchronized (getStateLock()) { 997 children.add(xany.get_window()); 998 } 999 } 1000 } 1001 handleClientMessage(XEvent xev)1002 public void handleClientMessage(XEvent xev) { 1003 if (eventLog.isLoggable(PlatformLogger.Level.FINER)) { 1004 XClientMessageEvent msg = xev.get_xclient(); 1005 eventLog.finer(msg.toString()); 1006 } 1007 } 1008 handleVisibilityEvent(XEvent xev)1009 public void handleVisibilityEvent(XEvent xev) { 1010 } handleKeyPress(XEvent xev)1011 public void handleKeyPress(XEvent xev) { 1012 } handleKeyRelease(XEvent xev)1013 public void handleKeyRelease(XEvent xev) { 1014 } handleExposeEvent(XEvent xev)1015 public void handleExposeEvent(XEvent xev) { 1016 } 1017 /** 1018 * Activate automatic grab on first ButtonPress, 1019 * deactivate on full mouse release 1020 */ handleButtonPressRelease(XEvent xev)1021 public void handleButtonPressRelease(XEvent xev) { 1022 XButtonEvent xbe = xev.get_xbutton(); 1023 /* 1024 * Ignore the buttons above 20 due to the bit limit for 1025 * InputEvent.BUTTON_DOWN_MASK. 1026 * One more bit is reserved for FIRST_HIGH_BIT. 1027 */ 1028 int theButton = xbe.get_button(); 1029 if (theButton > SunToolkit.MAX_BUTTONS_SUPPORTED) { 1030 return; 1031 } 1032 int buttonState = 0; 1033 buttonState = xbe.get_state() & XConstants.ALL_BUTTONS_MASK; 1034 1035 boolean isWheel = (theButton == XConstants.MouseWheelUp || 1036 theButton == XConstants.MouseWheelDown); 1037 1038 // don't give focus if it's just the mouse wheel turning 1039 if (!isWheel) { 1040 switch (xev.get_type()) { 1041 case XConstants.ButtonPress: 1042 if (buttonState == 0) { 1043 XWindowPeer parent = getToplevelXWindow(); 1044 // See 6385277, 6981400. 1045 if (parent != null && parent.isFocusableWindow()) { 1046 // A click in a client area drops the actual focused window retaining. 1047 parent.setActualFocusedWindow(null); 1048 parent.requestWindowFocus(xbe.get_time(), true); 1049 } 1050 XAwtState.setAutoGrabWindow(this); 1051 } 1052 break; 1053 case XConstants.ButtonRelease: 1054 if (isFullRelease(buttonState, xbe.get_button())) { 1055 XAwtState.setAutoGrabWindow(null); 1056 } 1057 break; 1058 } 1059 } 1060 } handleMotionNotify(XEvent xev)1061 public void handleMotionNotify(XEvent xev) { 1062 } handleXCrossingEvent(XEvent xev)1063 public void handleXCrossingEvent(XEvent xev) { 1064 } handleConfigureNotifyEvent(XEvent xev)1065 public void handleConfigureNotifyEvent(XEvent xev) { 1066 XConfigureEvent xe = xev.get_xconfigure(); 1067 if (insLog.isLoggable(PlatformLogger.Level.FINER)) { 1068 insLog.finer("Configure, {0}", xe); 1069 } 1070 1071 x = scaleDown(xe.get_x()); 1072 y = scaleDown(xe.get_y()); 1073 width = scaleDown(xe.get_width()); 1074 height = scaleDown(xe.get_height()); 1075 } 1076 /** 1077 * Checks ButtonRelease released all Mouse buttons 1078 */ isFullRelease(int buttonState, int button)1079 static boolean isFullRelease(int buttonState, int button) { 1080 final int buttonsNumber = XToolkit.getNumberOfButtonsForMask(); 1081 1082 if (button < 0 || button > buttonsNumber) { 1083 return buttonState == 0; 1084 } else { 1085 return buttonState == XlibUtil.getButtonMask(button); 1086 } 1087 } 1088 isGrabbedEvent(XEvent ev, XBaseWindow target)1089 static boolean isGrabbedEvent(XEvent ev, XBaseWindow target) { 1090 switch (ev.get_type()) { 1091 case XConstants.ButtonPress: 1092 case XConstants.ButtonRelease: 1093 case XConstants.MotionNotify: 1094 case XConstants.KeyPress: 1095 case XConstants.KeyRelease: 1096 return true; 1097 case XConstants.LeaveNotify: 1098 case XConstants.EnterNotify: 1099 // We shouldn't dispatch this events to the grabbed components (see 6317481) 1100 // But this logic is important if the grabbed component is top-level (see realSync) 1101 return (target instanceof XWindowPeer); 1102 default: 1103 return false; 1104 } 1105 } 1106 /** 1107 * Dispatches event to the grab Window or event source window depending 1108 * on whether the grab is active and on the event type 1109 */ dispatchToWindow(XEvent ev)1110 static void dispatchToWindow(XEvent ev) { 1111 XBaseWindow target = XAwtState.getGrabWindow(); 1112 if (target == null || !isGrabbedEvent(ev, target)) { 1113 target = XToolkit.windowToXWindow(ev.get_xany().get_window()); 1114 } 1115 if (target != null && target.checkInitialised()) { 1116 target.dispatchEvent(ev); 1117 } 1118 } 1119 dispatchEvent(XEvent xev)1120 public void dispatchEvent(XEvent xev) { 1121 if (eventLog.isLoggable(PlatformLogger.Level.FINEST)) { 1122 eventLog.finest(xev.toString()); 1123 } 1124 int type = xev.get_type(); 1125 1126 if (isDisposed()) { 1127 return; 1128 } 1129 1130 switch (type) 1131 { 1132 case XConstants.VisibilityNotify: 1133 handleVisibilityEvent(xev); 1134 break; 1135 case XConstants.ClientMessage: 1136 handleClientMessage(xev); 1137 break; 1138 case XConstants.Expose : 1139 case XConstants.GraphicsExpose : 1140 handleExposeEvent(xev); 1141 break; 1142 case XConstants.ButtonPress: 1143 case XConstants.ButtonRelease: 1144 handleButtonPressRelease(xev); 1145 break; 1146 1147 case XConstants.MotionNotify: 1148 handleMotionNotify(xev); 1149 break; 1150 case XConstants.KeyPress: 1151 handleKeyPress(xev); 1152 break; 1153 case XConstants.KeyRelease: 1154 handleKeyRelease(xev); 1155 break; 1156 case XConstants.EnterNotify: 1157 case XConstants.LeaveNotify: 1158 handleXCrossingEvent(xev); 1159 break; 1160 case XConstants.ConfigureNotify: 1161 handleConfigureNotifyEvent(xev); 1162 break; 1163 case XConstants.MapNotify: 1164 handleMapNotifyEvent(xev); 1165 break; 1166 case XConstants.UnmapNotify: 1167 handleUnmapNotifyEvent(xev); 1168 break; 1169 case XConstants.ReparentNotify: 1170 handleReparentNotifyEvent(xev); 1171 break; 1172 case XConstants.PropertyNotify: 1173 handlePropertyNotify(xev); 1174 break; 1175 case XConstants.DestroyNotify: 1176 handleDestroyNotify(xev); 1177 break; 1178 case XConstants.CreateNotify: 1179 handleCreateNotify(xev); 1180 break; 1181 } 1182 } isEventDisabled(XEvent e)1183 protected boolean isEventDisabled(XEvent e) { 1184 return false; 1185 } 1186 getX()1187 int getX() { 1188 return x; 1189 } 1190 getY()1191 int getY() { 1192 return y; 1193 } 1194 getWidth()1195 int getWidth() { 1196 return width; 1197 } 1198 getHeight()1199 int getHeight() { 1200 return height; 1201 } 1202 setDisposed(boolean d)1203 void setDisposed(boolean d) { 1204 disposed = d; 1205 } 1206 isDisposed()1207 boolean isDisposed() { 1208 return disposed; 1209 } 1210 getAbsoluteX()1211 public int getAbsoluteX() { 1212 XBaseWindow pw = getParentWindow(); 1213 if (pw != null) { 1214 return pw.getAbsoluteX() + getX(); 1215 } else { 1216 // Overridden for top-levels as their (x,y) is Java (x, y), not native location 1217 return getX(); 1218 } 1219 } 1220 getAbsoluteY()1221 public int getAbsoluteY() { 1222 XBaseWindow pw = getParentWindow(); 1223 if (pw != null) { 1224 return pw.getAbsoluteY() + getY(); 1225 } else { 1226 return getY(); 1227 } 1228 } 1229 getParentWindow()1230 public XBaseWindow getParentWindow() { 1231 return parentWindow; 1232 } 1233 getToplevelXWindow()1234 public XWindowPeer getToplevelXWindow() { 1235 XBaseWindow bw = this; 1236 while (bw != null && !(bw instanceof XWindowPeer)) { 1237 bw = bw.getParentWindow(); 1238 } 1239 return (XWindowPeer)bw; 1240 } toString()1241 public String toString() { 1242 return super.toString() + "(" + Long.toString(getWindow(), 16) + ")"; 1243 } 1244 1245 /** 1246 * Returns whether the given point is inside of the window. Coordinates are local. 1247 */ contains(int x, int y)1248 public boolean contains(int x, int y) { 1249 return x >= 0 && y >= 0 && x < getWidth() && y < getHeight(); 1250 } 1251 1252 /** 1253 * Returns whether the given point is inside of the window. Coordinates are global. 1254 */ containsGlobal(int x, int y)1255 public boolean containsGlobal(int x, int y) { 1256 return x >= getAbsoluteX() && y >= getAbsoluteY() && x < (getAbsoluteX()+getWidth()) && y < (getAbsoluteY()+getHeight()); 1257 } 1258 1259 } 1260