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