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