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