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