1 /* 2 * Copyright (c) 2002, 2011, 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 package sun.awt.X11; 26 27 import java.awt.AWTEvent; 28 import java.awt.AWTException; 29 import java.awt.BufferCapabilities; 30 import java.awt.Color; 31 import java.awt.Component; 32 import java.awt.Container; 33 import java.awt.Cursor; 34 import java.awt.Dimension; 35 import java.awt.Font; 36 import java.awt.FontMetrics; 37 import java.awt.Graphics; 38 import java.awt.GraphicsConfiguration; 39 import java.awt.Image; 40 import java.awt.Insets; 41 import java.awt.KeyboardFocusManager; 42 import java.awt.Rectangle; 43 import java.awt.SystemColor; 44 import java.awt.Toolkit; 45 import java.awt.Window; 46 import java.awt.dnd.DropTarget; 47 import java.awt.dnd.peer.DropTargetPeer; 48 import java.awt.event.FocusEvent; 49 import java.awt.event.InputEvent; 50 import java.awt.event.InputMethodEvent; 51 import java.awt.event.KeyEvent; 52 import java.awt.event.MouseEvent; 53 import java.awt.event.MouseWheelEvent; 54 import java.awt.event.PaintEvent; 55 import java.awt.event.WindowEvent; 56 import java.awt.event.InvocationEvent; 57 import java.awt.image.ImageObserver; 58 import java.awt.image.ImageProducer; 59 import java.awt.image.VolatileImage; 60 import java.awt.peer.ComponentPeer; 61 import java.awt.peer.ContainerPeer; 62 import java.awt.peer.LightweightPeer; 63 import java.lang.reflect.*; 64 import java.security.*; 65 import java.util.Collection; 66 import java.util.HashSet; 67 import java.util.Set; 68 import java.util.Vector; 69 import sun.util.logging.PlatformLogger; 70 71 import sun.awt.*; 72 import sun.awt.event.IgnorePaintEvent; 73 import sun.awt.image.SunVolatileImage; 74 import sun.awt.image.ToolkitImage; 75 import sun.java2d.BackBufferCapsProvider; 76 import sun.java2d.pipe.Region; 77 78 public class XComponentPeer extends XWindow implements ComponentPeer, DropTargetPeer, 79 BackBufferCapsProvider 80 { 81 private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XComponentPeer"); 82 private static final PlatformLogger buffersLog = PlatformLogger.getLogger("sun.awt.X11.XComponentPeer.multibuffer"); 83 private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.awt.X11.focus.XComponentPeer"); 84 private static final PlatformLogger fontLog = PlatformLogger.getLogger("sun.awt.X11.font.XComponentPeer"); 85 private static final PlatformLogger enableLog = PlatformLogger.getLogger("sun.awt.X11.enable.XComponentPeer"); 86 private static final PlatformLogger shapeLog = PlatformLogger.getLogger("sun.awt.X11.shape.XComponentPeer"); 87 88 boolean paintPending = false; 89 boolean isLayouting = false; 90 boolean enabled; 91 92 // Actually used only by XDecoratedPeer 93 protected int boundsOperation; 94 95 Color foreground; 96 Color background; 97 98 // Colors calculated as on Motif using MotifColorUtilties. 99 // If you use these, call updateMotifColors() in the peer's Constructor and 100 // setBackground(). Examples are XCheckboxPeer and XButtonPeer. 101 Color darkShadow; 102 Color lightShadow; 103 Color selectColor; 104 105 Font font; 106 private long backBuffer = 0; 107 private VolatileImage xBackBuffer = null; 108 109 static Color[] systemColors; 110 111 XComponentPeer() { 112 } 113 114 XComponentPeer (XCreateWindowParams params) { 115 super(params); 116 } 117 118 XComponentPeer(Component target, long parentWindow, Rectangle bounds) { 119 super(target, parentWindow, bounds); 120 } 121 122 /** 123 * Standard peer constructor, with corresponding Component 124 */ 125 XComponentPeer(Component target) { 126 super(target); 127 } 128 129 130 void preInit(XCreateWindowParams params) { 131 super.preInit(params); 132 boundsOperation = DEFAULT_OPERATION; 133 } 134 void postInit(XCreateWindowParams params) { 135 super.postInit(params); 136 Color c; 137 Font f; 138 Cursor cursor; 139 140 pSetCursor(target.getCursor()); 141 142 foreground = target.getForeground(); 143 background = target.getBackground(); 144 font = target.getFont(); 145 146 if (isInitialReshape()) { 147 Rectangle r = target.getBounds(); 148 reshape(r.x, r.y, r.width, r.height); 149 } 150 151 enabled = target.isEnabled(); 152 153 // If any of our heavyweight ancestors are disable, we should be too 154 // See 6176875 for more information 155 Component comp = target; 156 while( !(comp == null || comp instanceof Window) ) { 157 comp = comp.getParent(); 158 if( comp != null && !comp.isEnabled() && !comp.isLightweight() ){ 159 setEnabled(false); 160 break; 161 } 162 } 163 enableLog.fine("Initial enable state: {0}", Boolean.valueOf(enabled)); 164 165 if (target.isVisible()) { 166 setVisible(true); 167 } 168 } 169 170 protected boolean isInitialReshape() { 171 return true; 172 } 173 174 public void reparent(ContainerPeer newNativeParent) { 175 XComponentPeer newPeer = (XComponentPeer)newNativeParent; 176 XToolkit.awtLock(); 177 try { 178 XlibWrapper.XReparentWindow(XToolkit.getDisplay(), getWindow(), newPeer.getContentWindow(), x, y); 179 parentWindow = newPeer; 180 } finally { 181 XToolkit.awtUnlock(); 182 } 183 } 184 public boolean isReparentSupported() { 185 return System.getProperty("sun.awt.X11.XComponentPeer.reparentNotSupported", "false").equals("false"); 186 } 187 188 public boolean isObscured() { 189 Container container = (target instanceof Container) ? 190 (Container)target : target.getParent(); 191 192 if (container == null) { 193 return true; 194 } 195 196 Container parent; 197 while ((parent = container.getParent()) != null) { 198 container = parent; 199 } 200 201 if (container instanceof Window) { 202 XWindowPeer wpeer = (XWindowPeer)(container.getPeer()); 203 if (wpeer != null) { 204 return (wpeer.winAttr.visibilityState != 205 wpeer.winAttr.AWT_UNOBSCURED); 206 } 207 } 208 return true; 209 } 210 211 public boolean canDetermineObscurity() { 212 return true; 213 } 214 215 /************************************************* 216 * FOCUS STUFF 217 *************************************************/ 218 219 /** 220 * Keeps the track of focused state of the _NATIVE_ window 221 */ 222 boolean bHasFocus = false; 223 224 /** 225 * Descendants should use this method to determine whether or not native window 226 * has focus. 227 */ 228 final public boolean hasFocus() { 229 return bHasFocus; 230 } 231 232 /** 233 * Called when component receives focus 234 */ 235 public void focusGained(FocusEvent e) { 236 focusLog.fine("{0}", e); 237 bHasFocus = true; 238 } 239 240 /** 241 * Called when component loses focus 242 */ 243 public void focusLost(FocusEvent e) { 244 focusLog.fine("{0}", e); 245 bHasFocus = false; 246 } 247 248 public boolean isFocusable() { 249 /* should be implemented by other sub-classes */ 250 return false; 251 } 252 253 private static Class seClass; 254 private static Constructor seCtor; 255 256 final static AWTEvent wrapInSequenced(AWTEvent event) { 257 try { 258 if (seClass == null) { 259 seClass = Class.forName("java.awt.SequencedEvent"); 260 } 261 262 if (seCtor == null) { 263 seCtor = (Constructor) AccessController.doPrivileged(new PrivilegedExceptionAction() { 264 public Object run() throws Exception { 265 Constructor ctor = seClass.getConstructor(new Class[] { AWTEvent.class }); 266 ctor.setAccessible(true); 267 return ctor; 268 } 269 }); 270 } 271 272 return (AWTEvent) seCtor.newInstance(new Object[] { event }); 273 } 274 catch (ClassNotFoundException e) { 275 throw new NoClassDefFoundError("java.awt.SequencedEvent."); 276 } 277 catch (PrivilegedActionException ex) { 278 throw new NoClassDefFoundError("java.awt.SequencedEvent."); 279 } 280 catch (InstantiationException e) { 281 assert false; 282 } 283 catch (IllegalAccessException e) { 284 assert false; 285 } 286 catch (InvocationTargetException e) { 287 assert false; 288 } 289 290 return null; 291 } 292 293 // TODO: consider moving it to KeyboardFocusManagerPeerImpl 294 final public boolean requestFocus(Component lightweightChild, boolean temporary, 295 boolean focusedWindowChangeAllowed, long time, 296 CausedFocusEvent.Cause cause) 297 { 298 if (XKeyboardFocusManagerPeer. 299 processSynchronousLightweightTransfer(target, lightweightChild, temporary, 300 focusedWindowChangeAllowed, time)) 301 { 302 return true; 303 } 304 305 int result = XKeyboardFocusManagerPeer. 306 shouldNativelyFocusHeavyweight(target, lightweightChild, 307 temporary, focusedWindowChangeAllowed, 308 time, cause); 309 310 switch (result) { 311 case XKeyboardFocusManagerPeer.SNFH_FAILURE: 312 return false; 313 case XKeyboardFocusManagerPeer.SNFH_SUCCESS_PROCEED: 314 // Currently we just generate focus events like we deal with lightweight instead of calling 315 // XSetInputFocus on native window 316 if (focusLog.isLoggable(PlatformLogger.FINER)) focusLog.finer("Proceeding with request to " + 317 lightweightChild + " in " + target); 318 /** 319 * The problems with requests in non-focused window arise because shouldNativelyFocusHeavyweight 320 * checks that native window is focused while appropriate WINDOW_GAINED_FOCUS has not yet 321 * been processed - it is in EventQueue. Thus, SNFH allows native request and stores request record 322 * in requests list - and it breaks our requests sequence as first record on WGF should be the last 323 * focus owner which had focus before WLF. So, we should not add request record for such requests 324 * but store this component in mostRecent - and return true as before for compatibility. 325 */ 326 Window parentWindow = SunToolkit.getContainingWindow(target); 327 if (parentWindow == null) { 328 return rejectFocusRequestHelper("WARNING: Parent window is null"); 329 } 330 XWindowPeer wpeer = (XWindowPeer)parentWindow.getPeer(); 331 if (wpeer == null) { 332 return rejectFocusRequestHelper("WARNING: Parent window's peer is null"); 333 } 334 /* 335 * Passing null 'actualFocusedWindow' as we don't want to restore focus on it 336 * when a component inside a Frame is requesting focus. 337 * See 6314575 for details. 338 */ 339 boolean res = wpeer.requestWindowFocus(null); 340 341 if (focusLog.isLoggable(PlatformLogger.FINER)) focusLog.finer("Requested window focus: " + res); 342 // If parent window can be made focused and has been made focused(synchronously) 343 // then we can proceed with children, otherwise we retreat. 344 if (!(res && parentWindow.isFocused())) { 345 return rejectFocusRequestHelper("Waiting for asynchronous processing of the request"); 346 } 347 return XKeyboardFocusManagerPeer.deliverFocus(lightweightChild, 348 (Component)target, 349 temporary, 350 focusedWindowChangeAllowed, 351 time, cause); 352 // Motif compatibility code 353 case XKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED: 354 // Either lightweight or excessive request - all events are generated. 355 return true; 356 } 357 return false; 358 } 359 360 private boolean rejectFocusRequestHelper(String logMsg) { 361 if (focusLog.isLoggable(PlatformLogger.FINER)) focusLog.finer(logMsg); 362 XKeyboardFocusManagerPeer.removeLastFocusRequest(target); 363 return false; 364 } 365 366 void handleJavaFocusEvent(AWTEvent e) { 367 if (focusLog.isLoggable(PlatformLogger.FINER)) focusLog.finer(e.toString()); 368 if (e.getID() == FocusEvent.FOCUS_GAINED) { 369 focusGained((FocusEvent)e); 370 } else { 371 focusLost((FocusEvent)e); 372 } 373 } 374 375 void handleJavaWindowFocusEvent(AWTEvent e) { 376 } 377 378 /************************************************* 379 * END OF FOCUS STUFF 380 *************************************************/ 381 382 383 384 public void setVisible(boolean b) { 385 xSetVisible(b); 386 } 387 388 public void hide() { 389 setVisible(false); 390 } 391 392 393 /** 394 * @see java.awt.peer.ComponentPeer 395 */ 396 public void setEnabled(boolean value) { 397 enableLog.fine("{0}ing {1}", (value?"Enabl":"Disabl"), this); 398 boolean repaintNeeded = (enabled != value); 399 enabled = value; 400 if (target instanceof Container) { 401 Component list[] = ((Container)target).getComponents(); 402 for (int i = 0; i < list.length; ++i) { 403 boolean childEnabled = list[i].isEnabled(); 404 ComponentPeer p = list[i].getPeer(); 405 if ( p != null ) { 406 p.setEnabled(value && childEnabled); 407 } 408 } 409 } 410 if (repaintNeeded) { 411 repaint(); 412 } 413 } 414 415 // 416 // public so aw/Window can call it 417 // 418 public boolean isEnabled() { 419 return enabled; 420 } 421 422 423 424 public void enable() { 425 setEnabled(true); 426 } 427 428 public void disable() { 429 setEnabled(false); 430 } 431 432 public void paint(Graphics g) { 433 } 434 public void repaint(long tm, int x, int y, int width, int height) { 435 repaint(); 436 } 437 438 439 public Graphics getGraphics() { 440 return getGraphics(surfaceData, getPeerForeground(), getPeerBackground(), getPeerFont()); 441 } 442 443 444 445 public void print(Graphics g) { 446 // clear rect here to emulate X clears rect before Expose 447 g.setColor(target.getBackground()); 448 g.fillRect(0, 0, target.getWidth(), target.getHeight()); 449 g.setColor(target.getForeground()); 450 // paint peer 451 paint(g); 452 // allow target to change the picture 453 target.print(g); 454 } 455 456 public void setBounds(int x, int y, int width, int height, int op) { 457 this.x = x; 458 this.y = y; 459 this.width = width; 460 this.height = height; 461 xSetBounds(x,y,width,height); 462 validateSurface(); 463 layout(); 464 } 465 466 public void reshape(int x, int y, int width, int height) { 467 setBounds(x, y, width, height, SET_BOUNDS); 468 } 469 470 public void coalescePaintEvent(PaintEvent e) { 471 Rectangle r = e.getUpdateRect(); 472 if (!(e instanceof IgnorePaintEvent)) { 473 paintArea.add(r, e.getID()); 474 } 475 if (true) { 476 switch(e.getID()) { 477 case PaintEvent.UPDATE: 478 if (log.isLoggable(PlatformLogger.FINER)) { 479 log.finer("XCP coalescePaintEvent : UPDATE : add : x = " + 480 r.x + ", y = " + r.y + ", width = " + r.width + ",height = " + r.height); 481 } 482 return; 483 case PaintEvent.PAINT: 484 if (log.isLoggable(PlatformLogger.FINER)) { 485 log.finer("XCP coalescePaintEvent : PAINT : add : x = " + 486 r.x + ", y = " + r.y + ", width = " + r.width + ",height = " + r.height); 487 } 488 return; 489 } 490 } 491 } 492 493 XWindowPeer getParentTopLevel() { 494 AWTAccessor.ComponentAccessor compAccessor = AWTAccessor.getComponentAccessor(); 495 Container parent = (target instanceof Container) ? ((Container)target) : (compAccessor.getParent(target)); 496 // Search for parent window 497 while (parent != null && !(parent instanceof Window)) { 498 parent = compAccessor.getParent(parent); 499 } 500 if (parent != null) { 501 return (XWindowPeer)compAccessor.getPeer(parent); 502 } else { 503 return null; 504 } 505 } 506 507 /* This method is intended to be over-ridden by peers to perform user interaction */ 508 void handleJavaMouseEvent(MouseEvent e) { 509 switch (e.getID()) { 510 case MouseEvent.MOUSE_PRESSED: 511 if (target == e.getSource() && 512 !target.isFocusOwner() && 513 XKeyboardFocusManagerPeer.shouldFocusOnClick(target)) 514 { 515 XWindowPeer parentXWindow = getParentTopLevel(); 516 Window parentWindow = ((Window)parentXWindow.getTarget()); 517 // Simple windows are non-focusable in X terms but focusable in Java terms. 518 // As X-non-focusable they don't receive any focus events - we should generate them 519 // by ourselfves. 520 // if (parentXWindow.isFocusableWindow() /*&& parentXWindow.isSimpleWindow()*/ && 521 // !(getCurrentNativeFocusedWindow() == parentWindow)) 522 // { 523 // setCurrentNativeFocusedWindow(parentWindow); 524 // WindowEvent wfg = new WindowEvent(parentWindow, WindowEvent.WINDOW_GAINED_FOCUS); 525 // parentWindow.dispatchEvent(wfg); 526 // } 527 XKeyboardFocusManagerPeer.requestFocusFor(target, CausedFocusEvent.Cause.MOUSE_EVENT); 528 } 529 break; 530 } 531 } 532 533 /* This method is intended to be over-ridden by peers to perform user interaction */ 534 void handleJavaKeyEvent(KeyEvent e) { 535 } 536 537 /* This method is intended to be over-ridden by peers to perform user interaction */ 538 void handleJavaMouseWheelEvent(MouseWheelEvent e) { 539 } 540 541 542 /* This method is intended to be over-ridden by peers to perform user interaction */ 543 void handleJavaInputMethodEvent(InputMethodEvent e) { 544 } 545 546 void handleF10JavaKeyEvent(KeyEvent e) { 547 if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_F10) { 548 XWindowPeer winPeer = this.getToplevelXWindow(); 549 if (winPeer instanceof XFramePeer) { 550 XMenuBarPeer mPeer = ((XFramePeer)winPeer).getMenubarPeer(); 551 if (mPeer != null) { 552 mPeer.handleF10KeyPress(e); 553 } 554 } 555 } 556 } 557 558 public void handleEvent(java.awt.AWTEvent e) { 559 if ((e instanceof InputEvent) && !((InputEvent)e).isConsumed() && target.isEnabled()) { 560 if (e instanceof MouseEvent) { 561 if (e instanceof MouseWheelEvent) { 562 handleJavaMouseWheelEvent((MouseWheelEvent) e); 563 } 564 else 565 handleJavaMouseEvent((MouseEvent) e); 566 } 567 else if (e instanceof KeyEvent) { 568 handleF10JavaKeyEvent((KeyEvent)e); 569 handleJavaKeyEvent((KeyEvent)e); 570 } 571 } 572 else if (e instanceof KeyEvent && !((InputEvent)e).isConsumed()) { 573 // even if target is disabled. 574 handleF10JavaKeyEvent((KeyEvent)e); 575 } 576 else if (e instanceof InputMethodEvent) { 577 handleJavaInputMethodEvent((InputMethodEvent) e); 578 } 579 580 int id = e.getID(); 581 582 switch(id) { 583 case PaintEvent.PAINT: 584 // Got native painting 585 paintPending = false; 586 // Fallthrough to next statement 587 case PaintEvent.UPDATE: 588 // Skip all painting while layouting and all UPDATEs 589 // while waiting for native paint 590 if (!isLayouting && !paintPending) { 591 paintArea.paint(target,false); 592 } 593 return; 594 case FocusEvent.FOCUS_LOST: 595 case FocusEvent.FOCUS_GAINED: 596 handleJavaFocusEvent(e); 597 break; 598 case WindowEvent.WINDOW_LOST_FOCUS: 599 case WindowEvent.WINDOW_GAINED_FOCUS: 600 handleJavaWindowFocusEvent(e); 601 break; 602 default: 603 break; 604 } 605 606 } 607 608 public void handleButtonPressRelease(XEvent xev) { 609 /* 610 * Fix for 6385277. 611 * We request focus on simple Window by click in order 612 * to make it behave like Frame/Dialog in this case and also to unify 613 * the behaviour with what we have on MS Windows. 614 * handleJavaMouseEvent() would be more suitable place to do this 615 * but we want Swing to have this functionality also. 616 */ 617 if (xev.get_type() == XConstants.ButtonPress) { 618 final XWindowPeer parentXWindow = getParentTopLevel(); 619 Window parentWindow = (Window)parentXWindow.getTarget(); 620 if (parentXWindow.isFocusableWindow() && parentXWindow.isSimpleWindow() && 621 XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow() != parentWindow) 622 { 623 postEvent(new InvocationEvent(parentWindow, new Runnable() { 624 public void run() { 625 // Request focus on the EDT of 'parentWindow' because 626 // XDecoratedPeer.requestWindowFocus() calls client code. 627 parentXWindow.requestXFocus(); 628 } 629 })); 630 } 631 } 632 super.handleButtonPressRelease(xev); 633 } 634 635 public Dimension getMinimumSize() { 636 return target.getSize(); 637 } 638 639 public Dimension getPreferredSize() { 640 return getMinimumSize(); 641 } 642 643 public void layout() {} 644 645 public java.awt.Toolkit getToolkit() { 646 return Toolkit.getDefaultToolkit(); 647 } 648 649 void updateMotifColors(Color bg) { 650 int red = bg.getRed(); 651 int green = bg.getGreen(); 652 int blue = bg.getBlue(); 653 654 darkShadow = new Color(MotifColorUtilities.calculateBottomShadowFromBackground(red,green,blue)); 655 lightShadow = new Color(MotifColorUtilities.calculateTopShadowFromBackground(red,green,blue)); 656 selectColor= new Color(MotifColorUtilities.calculateSelectFromBackground(red,green,blue)); 657 } 658 659 /* 660 * Draw a 3D rectangle using the Motif colors. 661 * "Normal" rectangles have shadows on the bottom. 662 * "Depressed" rectangles (such as pressed buttons) have shadows on the top, 663 * in which case true should be passed for topShadow. 664 */ 665 public void drawMotif3DRect(Graphics g, 666 int x, int y, int width, int height, 667 boolean topShadow) { 668 g.setColor(topShadow ? darkShadow : lightShadow); 669 g.drawLine(x, y, x+width, y); // top 670 g.drawLine(x, y+height, x, y); // left 671 672 g.setColor(topShadow ? lightShadow : darkShadow ); 673 g.drawLine(x+1, y+height, x+width, y+height); // bottom 674 g.drawLine(x+width, y+height, x+width, y+1); // right 675 } 676 677 public void setBackground(Color c) { 678 if (log.isLoggable(PlatformLogger.FINE)) log.fine("Set background to " + c); 679 synchronized (getStateLock()) { 680 background = c; 681 } 682 super.setBackground(c); 683 repaint(); 684 } 685 686 public void setForeground(Color c) { 687 if (log.isLoggable(PlatformLogger.FINE)) log.fine("Set foreground to " + c); 688 synchronized (getStateLock()) { 689 foreground = c; 690 } 691 repaint(); 692 } 693 694 /** 695 * Gets the font metrics for the specified font. 696 * @param font the font for which font metrics is to be 697 * obtained 698 * @return the font metrics for <code>font</code> 699 * @see #getFont 700 * @see #getPeer 701 * @see java.awt.peer.ComponentPeer#getFontMetrics(Font) 702 * @see Toolkit#getFontMetrics(Font) 703 * @since JDK1.0 704 */ 705 public FontMetrics getFontMetrics(Font font) { 706 if (fontLog.isLoggable(PlatformLogger.FINE)) fontLog.fine("Getting font metrics for " + font); 707 return sun.font.FontDesignMetrics.getMetrics(font); 708 } 709 710 public void setFont(Font f) { 711 synchronized (getStateLock()) { 712 if (f == null) { 713 f = XWindow.getDefaultFont(); 714 } 715 font = f; 716 } 717 // as it stands currently we dont need to do layout or repaint since 718 // layout is done in the Component upon setFont. 719 //layout(); 720 // target.repaint(); 721 //repaint()? 722 } 723 724 public Font getFont() { 725 return font; 726 } 727 728 public void updateCursorImmediately() { 729 XGlobalCursorManager.getCursorManager().updateCursorImmediately(); 730 } 731 732 public final void pSetCursor(Cursor cursor) { 733 this.pSetCursor(cursor, true); 734 } 735 736 /* 737 * The method changes the cursor. 738 * @param cursor - a new cursor to change to. 739 * @param ignoreSubComponents - if {@code true} is passed then 740 * the new cursor will be installed on window. 741 * if {@code false} is passed then 742 * subsequent components will try to handle 743 * this request and install their cursor. 744 */ 745 //ignoreSubComponents not used here 746 public void pSetCursor(Cursor cursor, boolean ignoreSubComponents) { 747 XToolkit.awtLock(); 748 try { 749 long xcursor = XGlobalCursorManager.getCursor(cursor); 750 751 XSetWindowAttributes xwa = new XSetWindowAttributes(); 752 xwa.set_cursor(xcursor); 753 754 long valuemask = XConstants.CWCursor; 755 756 XlibWrapper.XChangeWindowAttributes(XToolkit.getDisplay(),getWindow(),valuemask,xwa.pData); 757 XlibWrapper.XFlush(XToolkit.getDisplay()); 758 xwa.dispose(); 759 } finally { 760 XToolkit.awtUnlock(); 761 } 762 } 763 764 public Image createImage(ImageProducer producer) { 765 return new ToolkitImage(producer); 766 } 767 768 public Image createImage(int width, int height) { 769 return graphicsConfig.createAcceleratedImage(target, width, height); 770 } 771 772 public VolatileImage createVolatileImage(int width, int height) { 773 return new SunVolatileImage(target, width, height); 774 } 775 776 public boolean prepareImage(Image img, int w, int h, ImageObserver o) { 777 return getToolkit().prepareImage(img, w, h, o); 778 } 779 780 public int checkImage(Image img, int w, int h, ImageObserver o) { 781 return getToolkit().checkImage(img, w, h, o); 782 } 783 784 public Dimension preferredSize() { 785 return getPreferredSize(); 786 } 787 788 public Dimension minimumSize() { 789 return getMinimumSize(); 790 } 791 792 public Insets getInsets() { 793 return new Insets(0, 0, 0, 0); 794 } 795 796 public void beginValidate() { 797 } 798 799 public void endValidate() { 800 } 801 802 803 /** 804 * DEPRECATED: Replaced by getInsets(). 805 */ 806 807 public Insets insets() { 808 return getInsets(); 809 } 810 811 // Returns true if we are inside begin/endLayout and 812 // are waiting for native painting 813 public boolean isPaintPending() { 814 return paintPending && isLayouting; 815 } 816 817 public boolean handlesWheelScrolling() { 818 return false; 819 } 820 821 public void beginLayout() { 822 // Skip all painting till endLayout 823 isLayouting = true; 824 825 } 826 827 public void endLayout() { 828 if (!paintPending && !paintArea.isEmpty() 829 && !AWTAccessor.getComponentAccessor().getIgnoreRepaint(target)) 830 { 831 // if not waiting for native painting repaint damaged area 832 postEvent(new PaintEvent(target, PaintEvent.PAINT, 833 new Rectangle())); 834 } 835 isLayouting = false; 836 } 837 838 public Color getWinBackground() { 839 return getPeerBackground(); 840 } 841 842 static int[] getRGBvals(Color c) { 843 844 int rgbvals[] = new int[3]; 845 846 rgbvals[0] = c.getRed(); 847 rgbvals[1] = c.getGreen(); 848 rgbvals[2] = c.getBlue(); 849 850 return rgbvals; 851 } 852 853 static final int BACKGROUND_COLOR = 0; 854 static final int HIGHLIGHT_COLOR = 1; 855 static final int SHADOW_COLOR = 2; 856 static final int FOREGROUND_COLOR = 3; 857 858 public Color[] getGUIcolors() { 859 Color c[] = new Color[4]; 860 float backb, highb, shadowb, hue, saturation; 861 c[BACKGROUND_COLOR] = getWinBackground(); 862 if (c[BACKGROUND_COLOR] == null) { 863 c[BACKGROUND_COLOR] = super.getWinBackground(); 864 } 865 if (c[BACKGROUND_COLOR] == null) { 866 c[BACKGROUND_COLOR] = Color.lightGray; 867 } 868 869 int[] rgb = getRGBvals(c[BACKGROUND_COLOR]); 870 871 float[] hsb = Color.RGBtoHSB(rgb[0],rgb[1],rgb[2],null); 872 873 hue = hsb[0]; 874 saturation = hsb[1]; 875 backb = hsb[2]; 876 877 878 /* Calculate Highlight Brightness */ 879 880 highb = backb + 0.2f; 881 shadowb = backb - 0.4f; 882 if ((highb > 1.0) ) { 883 if ((1.0 - backb) < 0.05) { 884 highb = shadowb + 0.25f; 885 } else { 886 highb = 1.0f; 887 } 888 } else { 889 if (shadowb < 0.0) { 890 if ((backb - 0.0) < 0.25) { 891 highb = backb + 0.75f; 892 shadowb = highb - 0.2f; 893 } else { 894 shadowb = 0.0f; 895 } 896 } 897 } 898 c[HIGHLIGHT_COLOR] = Color.getHSBColor(hue,saturation,highb); 899 c[SHADOW_COLOR] = Color.getHSBColor(hue,saturation,shadowb); 900 901 902 /* 903 c[SHADOW_COLOR] = c[BACKGROUND_COLOR].darker(); 904 int r2 = c[SHADOW_COLOR].getRed(); 905 int g2 = c[SHADOW_COLOR].getGreen(); 906 int b2 = c[SHADOW_COLOR].getBlue(); 907 */ 908 909 c[FOREGROUND_COLOR] = getPeerForeground(); 910 if (c[FOREGROUND_COLOR] == null) { 911 c[FOREGROUND_COLOR] = Color.black; 912 } 913 /* 914 if ((c[BACKGROUND_COLOR].equals(c[HIGHLIGHT_COLOR])) 915 && (c[BACKGROUND_COLOR].equals(c[SHADOW_COLOR]))) { 916 c[SHADOW_COLOR] = new Color(c[BACKGROUND_COLOR].getRed() + 75, 917 c[BACKGROUND_COLOR].getGreen() + 75, 918 c[BACKGROUND_COLOR].getBlue() + 75); 919 c[HIGHLIGHT_COLOR] = c[SHADOW_COLOR].brighter(); 920 } else if (c[BACKGROUND_COLOR].equals(c[HIGHLIGHT_COLOR])) { 921 c[HIGHLIGHT_COLOR] = c[SHADOW_COLOR]; 922 c[SHADOW_COLOR] = c[SHADOW_COLOR].darker(); 923 } 924 */ 925 if (! isEnabled()) { 926 c[BACKGROUND_COLOR] = c[BACKGROUND_COLOR].darker(); 927 // Reduce the contrast 928 // Calculate the NTSC gray (NB: REC709 L* might be better!) 929 // for foreground and background; then multiply the foreground 930 // by the average lightness 931 932 933 Color tc = c[BACKGROUND_COLOR]; 934 int bg = tc.getRed() * 30 + tc.getGreen() * 59 + tc.getBlue() * 11; 935 936 tc = c[FOREGROUND_COLOR]; 937 int fg = tc.getRed() * 30 + tc.getGreen() * 59 + tc.getBlue() * 11; 938 939 float ave = (float) ((fg + bg) / 51000.0); 940 // 255 * 100 * 2 941 942 Color newForeground = new Color((int) (tc.getRed() * ave), 943 (int) (tc.getGreen() * ave), 944 (int) (tc.getBlue() * ave)); 945 946 if (newForeground.equals(c[FOREGROUND_COLOR])) { 947 // This probably means the foreground color is black or white 948 newForeground = new Color(ave, ave, ave); 949 } 950 c[FOREGROUND_COLOR] = newForeground; 951 952 } 953 954 955 return c; 956 } 957 958 /** 959 * Returns an array of Colors similar to getGUIcolors(), but using the 960 * System colors. This is useful if pieces of a Component (such as 961 * the integrated scrollbars of a List) should retain the System color 962 * instead of the background color set by Component.setBackground(). 963 */ 964 static Color[] getSystemColors() { 965 if (systemColors == null) { 966 systemColors = new Color[4]; 967 systemColors[BACKGROUND_COLOR] = SystemColor.window; 968 systemColors[HIGHLIGHT_COLOR] = SystemColor.controlLtHighlight; 969 systemColors[SHADOW_COLOR] = SystemColor.controlShadow; 970 systemColors[FOREGROUND_COLOR] = SystemColor.windowText; 971 } 972 return systemColors; 973 } 974 975 /** 976 * Draw a 3D oval. 977 */ 978 public void draw3DOval(Graphics g, Color colors[], 979 int x, int y, int w, int h, boolean raised) 980 { 981 Color c = g.getColor(); 982 g.setColor(raised ? colors[HIGHLIGHT_COLOR] : colors[SHADOW_COLOR]); 983 g.drawArc(x, y, w, h, 45, 180); 984 g.setColor(raised ? colors[SHADOW_COLOR] : colors[HIGHLIGHT_COLOR]); 985 g.drawArc(x, y, w, h, 225, 180); 986 g.setColor(c); 987 } 988 989 public void draw3DRect(Graphics g, Color colors[], 990 int x, int y, int width, int height, boolean raised) 991 { 992 Color c = g.getColor(); 993 g.setColor(raised ? colors[HIGHLIGHT_COLOR] : colors[SHADOW_COLOR]); 994 g.drawLine(x, y, x, y + height); 995 g.drawLine(x + 1, y, x + width - 1, y); 996 g.setColor(raised ? colors[SHADOW_COLOR] : colors[HIGHLIGHT_COLOR]); 997 g.drawLine(x + 1, y + height, x + width, y + height); 998 g.drawLine(x + width, y, x + width, y + height - 1); 999 g.setColor(c); 1000 } 1001 1002 /* 1003 * drawXXX() methods are used to print the native components by 1004 * rendering the Motif look ourselves. 1005 * ToDo(aim): needs to query native motif for more accurate color 1006 * information. 1007 */ 1008 void draw3DOval(Graphics g, Color bg, 1009 int x, int y, int w, int h, boolean raised) 1010 { 1011 Color c = g.getColor(); 1012 Color shadow = bg.darker(); 1013 Color highlight = bg.brighter(); 1014 1015 g.setColor(raised ? highlight : shadow); 1016 g.drawArc(x, y, w, h, 45, 180); 1017 g.setColor(raised ? shadow : highlight); 1018 g.drawArc(x, y, w, h, 225, 180); 1019 g.setColor(c); 1020 } 1021 1022 void draw3DRect(Graphics g, Color bg, 1023 int x, int y, int width, int height, 1024 boolean raised) { 1025 Color c = g.getColor(); 1026 Color shadow = bg.darker(); 1027 Color highlight = bg.brighter(); 1028 1029 g.setColor(raised ? highlight : shadow); 1030 g.drawLine(x, y, x, y + height); 1031 g.drawLine(x + 1, y, x + width - 1, y); 1032 g.setColor(raised ? shadow : highlight); 1033 g.drawLine(x + 1, y + height, x + width, y + height); 1034 g.drawLine(x + width, y, x + width, y + height - 1); 1035 g.setColor(c); 1036 } 1037 1038 void drawScrollbar(Graphics g, Color bg, int thickness, int length, 1039 int min, int max, int val, int vis, boolean horizontal) { 1040 Color c = g.getColor(); 1041 double f = (double)(length - 2*(thickness-1)) / Math.max(1, ((max - min) + vis)); 1042 int v1 = thickness + (int)(f * (val - min)); 1043 int v2 = (int)(f * vis); 1044 int w2 = thickness-4; 1045 int tpts_x[] = new int[3]; 1046 int tpts_y[] = new int[3]; 1047 1048 if (length < 3*w2 ) { 1049 v1 = v2 = 0; 1050 if (length < 2*w2 + 2) { 1051 w2 = (length-2)/2; 1052 } 1053 } else if (v2 < 7) { 1054 // enforce a minimum handle size 1055 v1 = Math.max(0, v1 - ((7 - v2)>>1)); 1056 v2 = 7; 1057 } 1058 1059 int ctr = thickness/2; 1060 int sbmin = ctr - w2/2; 1061 int sbmax = ctr + w2/2; 1062 1063 // paint the background slightly darker 1064 { 1065 Color d = new Color((int) (bg.getRed() * 0.85), 1066 (int) (bg.getGreen() * 0.85), 1067 (int) (bg.getBlue() * 0.85)); 1068 1069 g.setColor(d); 1070 if (horizontal) { 1071 g.fillRect(0, 0, length, thickness); 1072 } else { 1073 g.fillRect(0, 0, thickness, length); 1074 } 1075 } 1076 1077 // paint the thumb and arrows in the normal background color 1078 g.setColor(bg); 1079 if (v1 > 0) { 1080 if (horizontal) { 1081 g.fillRect(v1, 3, v2, thickness-3); 1082 } else { 1083 g.fillRect(3, v1, thickness-3, v2); 1084 } 1085 } 1086 1087 tpts_x[0] = ctr; tpts_y[0] = 2; 1088 tpts_x[1] = sbmin; tpts_y[1] = w2; 1089 tpts_x[2] = sbmax; tpts_y[2] = w2; 1090 if (horizontal) { 1091 g.fillPolygon(tpts_y, tpts_x, 3); 1092 } else { 1093 g.fillPolygon(tpts_x, tpts_y, 3); 1094 } 1095 1096 tpts_y[0] = length-2; 1097 tpts_y[1] = length-w2; 1098 tpts_y[2] = length-w2; 1099 if (horizontal) { 1100 g.fillPolygon(tpts_y, tpts_x, 3); 1101 } else { 1102 g.fillPolygon(tpts_x, tpts_y, 3); 1103 } 1104 1105 Color highlight = bg.brighter(); 1106 1107 // // // // draw the "highlighted" edges 1108 g.setColor(highlight); 1109 1110 // outline & arrows 1111 if (horizontal) { 1112 g.drawLine(1, thickness, length - 1, thickness); 1113 g.drawLine(length - 1, 1, length - 1, thickness); 1114 1115 // arrows 1116 g.drawLine(1, ctr, w2, sbmin); 1117 g.drawLine(length - w2, sbmin, length - w2, sbmax); 1118 g.drawLine(length - w2, sbmin, length - 2, ctr); 1119 1120 } else { 1121 g.drawLine(thickness, 1, thickness, length - 1); 1122 g.drawLine(1, length - 1, thickness, length - 1); 1123 1124 // arrows 1125 g.drawLine(ctr, 1, sbmin, w2); 1126 g.drawLine(sbmin, length - w2, sbmax, length - w2); 1127 g.drawLine(sbmin, length - w2, ctr, length - 2); 1128 } 1129 1130 // thumb 1131 if (v1 > 0) { 1132 if (horizontal) { 1133 g.drawLine(v1, 2, v1 + v2, 2); 1134 g.drawLine(v1, 2, v1, thickness-3); 1135 } else { 1136 g.drawLine(2, v1, 2, v1 + v2); 1137 g.drawLine(2, v1, thickness-3, v1); 1138 } 1139 } 1140 1141 Color shadow = bg.darker(); 1142 1143 // // // // draw the "shadowed" edges 1144 g.setColor(shadow); 1145 1146 // outline && arrows 1147 if (horizontal) { 1148 g.drawLine(0, 0, 0, thickness); 1149 g.drawLine(0, 0, length - 1, 0); 1150 1151 // arrows 1152 g.drawLine(w2, sbmin, w2, sbmax); 1153 g.drawLine(w2, sbmax, 1, ctr); 1154 g.drawLine(length-2, ctr, length-w2, sbmax); 1155 1156 } else { 1157 g.drawLine(0, 0, thickness, 0); 1158 g.drawLine(0, 0, 0, length - 1); 1159 1160 // arrows 1161 g.drawLine(sbmin, w2, sbmax, w2); 1162 g.drawLine(sbmax, w2, ctr, 1); 1163 g.drawLine(ctr, length-2, sbmax, length-w2); 1164 } 1165 1166 // thumb 1167 if (v1 > 0) { 1168 if (horizontal) { 1169 g.drawLine(v1 + v2, 2, v1 + v2, thickness-2); 1170 g.drawLine(v1, thickness-2, v1 + v2, thickness-2); 1171 } else { 1172 g.drawLine(2, v1 + v2, thickness-2, v1 + v2); 1173 g.drawLine(thickness-2, v1, thickness-2, v1 + v2); 1174 } 1175 } 1176 g.setColor(c); 1177 } 1178 1179 /** 1180 * The following multibuffering-related methods delegate to our 1181 * associated GraphicsConfig (X11 or GLX) to handle the appropriate 1182 * native windowing system specific actions. 1183 */ 1184 1185 private BufferCapabilities backBufferCaps; 1186 1187 public void createBuffers(int numBuffers, BufferCapabilities caps) 1188 throws AWTException 1189 { 1190 if (buffersLog.isLoggable(PlatformLogger.FINE)) { 1191 buffersLog.fine("createBuffers(" + numBuffers + ", " + caps + ")"); 1192 } 1193 // set the caps first, they're used when creating the bb 1194 backBufferCaps = caps; 1195 backBuffer = graphicsConfig.createBackBuffer(this, numBuffers, caps); 1196 xBackBuffer = graphicsConfig.createBackBufferImage(target, 1197 backBuffer); 1198 } 1199 1200 @Override 1201 public BufferCapabilities getBackBufferCaps() { 1202 return backBufferCaps; 1203 } 1204 1205 public void flip(int x1, int y1, int x2, int y2, 1206 BufferCapabilities.FlipContents flipAction) 1207 { 1208 if (buffersLog.isLoggable(PlatformLogger.FINE)) { 1209 buffersLog.fine("flip(" + flipAction + ")"); 1210 } 1211 if (backBuffer == 0) { 1212 throw new IllegalStateException("Buffers have not been created"); 1213 } 1214 graphicsConfig.flip(this, target, xBackBuffer, 1215 x1, y1, x2, y2, flipAction); 1216 } 1217 1218 public Image getBackBuffer() { 1219 if (buffersLog.isLoggable(PlatformLogger.FINE)) { 1220 buffersLog.fine("getBackBuffer()"); 1221 } 1222 if (backBuffer == 0) { 1223 throw new IllegalStateException("Buffers have not been created"); 1224 } 1225 return xBackBuffer; 1226 } 1227 1228 public void destroyBuffers() { 1229 if (buffersLog.isLoggable(PlatformLogger.FINE)) { 1230 buffersLog.fine("destroyBuffers()"); 1231 } 1232 graphicsConfig.destroyBackBuffer(backBuffer); 1233 backBuffer = 0; 1234 xBackBuffer = null; 1235 } 1236 1237 // End of multi-buffering 1238 1239 public void notifyTextComponentChange(boolean add){ 1240 Container parent = AWTAccessor.getComponentAccessor().getParent(target); 1241 while(!(parent == null || 1242 parent instanceof java.awt.Frame || 1243 parent instanceof java.awt.Dialog)) { 1244 parent = AWTAccessor.getComponentAccessor().getParent(parent); 1245 } 1246 1247 /* FIX ME - FIX ME need to implement InputMethods 1248 if (parent instanceof java.awt.Frame || 1249 parent instanceof java.awt.Dialog) { 1250 if (add) 1251 ((MInputMethodControl)parent.getPeer()).addTextComponent((MComponentPeer)this); 1252 else 1253 ((MInputMethodControl)parent.getPeer()).removeTextComponent((MComponentPeer)this); 1254 } 1255 */ 1256 } 1257 1258 /** 1259 * Returns true if this event is disabled and shouldn't be processed by window 1260 * Currently if target component is disabled the following event will be disabled on window: 1261 * ButtonPress, ButtonRelease, KeyPress, KeyRelease, EnterNotify, LeaveNotify, MotionNotify 1262 */ 1263 protected boolean isEventDisabled(XEvent e) { 1264 if (enableLog.isLoggable(PlatformLogger.FINEST)) { 1265 enableLog.finest("Component is {1}, checking for disabled event {0}", e, (isEnabled()?"enabled":"disable")); 1266 } 1267 if (!isEnabled()) { 1268 switch (e.get_type()) { 1269 case XConstants.ButtonPress: 1270 case XConstants.ButtonRelease: 1271 case XConstants.KeyPress: 1272 case XConstants.KeyRelease: 1273 case XConstants.EnterNotify: 1274 case XConstants.LeaveNotify: 1275 case XConstants.MotionNotify: 1276 if (enableLog.isLoggable(PlatformLogger.FINER)) { 1277 enableLog.finer("Event {0} is disable", e); 1278 } 1279 return true; 1280 } 1281 } 1282 switch(e.get_type()) { 1283 case XConstants.MapNotify: 1284 case XConstants.UnmapNotify: 1285 return true; 1286 } 1287 return super.isEventDisabled(e); 1288 } 1289 1290 Color getPeerBackground() { 1291 return background; 1292 } 1293 1294 Color getPeerForeground() { 1295 return foreground; 1296 } 1297 1298 Font getPeerFont() { 1299 return font; 1300 } 1301 1302 Dimension getPeerSize() { 1303 return new Dimension(width,height); 1304 } 1305 1306 public void setBoundsOperation(int operation) { 1307 synchronized(getStateLock()) { 1308 if (boundsOperation == DEFAULT_OPERATION) { 1309 boundsOperation = operation; 1310 } else if (operation == RESET_OPERATION) { 1311 boundsOperation = DEFAULT_OPERATION; 1312 } 1313 } 1314 } 1315 1316 static String operationToString(int operation) { 1317 switch (operation) { 1318 case SET_LOCATION: 1319 return "SET_LOCATION"; 1320 case SET_SIZE: 1321 return "SET_SIZE"; 1322 case SET_CLIENT_SIZE: 1323 return "SET_CLIENT_SIZE"; 1324 default: 1325 case SET_BOUNDS: 1326 return "SET_BOUNDS"; 1327 } 1328 } 1329 1330 /** 1331 * Lowers this component at the bottom of the above HW peer. If the above parameter 1332 * is null then the method places this component at the top of the Z-order. 1333 */ 1334 public void setZOrder(ComponentPeer above) { 1335 long aboveWindow = (above != null) ? ((XComponentPeer)above).getWindow() : 0; 1336 1337 XToolkit.awtLock(); 1338 try{ 1339 XlibWrapper.SetZOrder(XToolkit.getDisplay(), getWindow(), aboveWindow); 1340 }finally{ 1341 XToolkit.awtUnlock(); 1342 } 1343 } 1344 1345 private void addTree(Collection order, Set set, Container cont) { 1346 for (int i = 0; i < cont.getComponentCount(); i++) { 1347 Component comp = cont.getComponent(i); 1348 ComponentPeer peer = comp.getPeer(); 1349 if (peer instanceof XComponentPeer) { 1350 Long window = Long.valueOf(((XComponentPeer)peer).getWindow()); 1351 if (!set.contains(window)) { 1352 set.add(window); 1353 order.add(window); 1354 } 1355 } else if (comp instanceof Container) { 1356 // It is lightweight container, it might contain heavyweight components attached to this 1357 // peer 1358 addTree(order, set, (Container)comp); 1359 } 1360 } 1361 } 1362 1363 /****** DropTargetPeer implementation ********************/ 1364 1365 public void addDropTarget(DropTarget dt) { 1366 Component comp = target; 1367 while(!(comp == null || comp instanceof Window)) { 1368 comp = comp.getParent(); 1369 } 1370 1371 if (comp instanceof Window) { 1372 XWindowPeer wpeer = (XWindowPeer)(comp.getPeer()); 1373 if (wpeer != null) { 1374 wpeer.addDropTarget(); 1375 } 1376 } 1377 } 1378 1379 public void removeDropTarget(DropTarget dt) { 1380 Component comp = target; 1381 while(!(comp == null || comp instanceof Window)) { 1382 comp = comp.getParent(); 1383 } 1384 1385 if (comp instanceof Window) { 1386 XWindowPeer wpeer = (XWindowPeer)(comp.getPeer()); 1387 if (wpeer != null) { 1388 wpeer.removeDropTarget(); 1389 } 1390 } 1391 } 1392 1393 /** 1394 * Applies the shape to the X-window. 1395 * @since 1.7 1396 */ 1397 public void applyShape(Region shape) { 1398 if (XlibUtil.isShapingSupported()) { 1399 if (shapeLog.isLoggable(PlatformLogger.FINER)) { 1400 shapeLog.finer( 1401 "*** INFO: Setting shape: PEER: " + this 1402 + "; WINDOW: " + getWindow() 1403 + "; TARGET: " + target 1404 + "; SHAPE: " + shape); 1405 } 1406 XToolkit.awtLock(); 1407 try { 1408 if (shape != null) { 1409 XlibWrapper.SetRectangularShape( 1410 XToolkit.getDisplay(), 1411 getWindow(), 1412 shape.getLoX(), shape.getLoY(), 1413 shape.getHiX(), shape.getHiY(), 1414 (shape.isRectangular() ? null : shape) 1415 ); 1416 } else { 1417 XlibWrapper.SetRectangularShape( 1418 XToolkit.getDisplay(), 1419 getWindow(), 1420 0, 0, 1421 0, 0, 1422 null 1423 ); 1424 } 1425 } finally { 1426 XToolkit.awtUnlock(); 1427 } 1428 } else { 1429 if (shapeLog.isLoggable(PlatformLogger.FINER)) { 1430 shapeLog.finer("*** WARNING: Shaping is NOT supported!"); 1431 } 1432 } 1433 } 1434 1435 public boolean updateGraphicsData(GraphicsConfiguration gc) { 1436 int oldVisual = -1, newVisual = -1; 1437 1438 if (graphicsConfig != null) { 1439 oldVisual = graphicsConfig.getVisual(); 1440 } 1441 if (gc != null && gc instanceof X11GraphicsConfig) { 1442 newVisual = ((X11GraphicsConfig)gc).getVisual(); 1443 } 1444 1445 // If the new visual differs from the old one, the peer must be 1446 // recreated because X11 does not allow changing the visual on the fly. 1447 // So we even skip the initGraphicsConfiguration() call. 1448 // The initial assignment should happen though, hence the != -1 thing. 1449 if (oldVisual != -1 && oldVisual != newVisual) { 1450 return true; 1451 } 1452 1453 initGraphicsConfiguration(); 1454 doValidateSurface(); 1455 return false; 1456 } 1457 }