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