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