1 /* 2 * Copyright (c) 1996, 2010, 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.windows; 26 27 import java.awt.*; 28 import java.awt.peer.*; 29 import java.awt.image.VolatileImage; 30 import sun.awt.RepaintArea; 31 import sun.awt.CausedFocusEvent; 32 import sun.awt.image.SunVolatileImage; 33 import sun.awt.image.ToolkitImage; 34 import java.awt.image.BufferedImage; 35 import java.awt.image.ImageProducer; 36 import java.awt.image.ImageObserver; 37 import java.awt.image.ColorModel; 38 import java.awt.event.PaintEvent; 39 import java.awt.event.InvocationEvent; 40 import java.awt.event.KeyEvent; 41 import java.awt.event.FocusEvent; 42 import java.awt.event.MouseEvent; 43 import java.awt.event.MouseWheelEvent; 44 import java.awt.event.InputEvent; 45 import sun.awt.Win32GraphicsConfig; 46 import sun.awt.Win32GraphicsEnvironment; 47 import sun.java2d.InvalidPipeException; 48 import sun.java2d.SurfaceData; 49 import sun.java2d.ScreenUpdateManager; 50 import sun.java2d.d3d.D3DSurfaceData; 51 import sun.java2d.opengl.OGLSurfaceData; 52 import sun.java2d.pipe.Region; 53 import sun.awt.DisplayChangedListener; 54 import sun.awt.PaintEventDispatcher; 55 import sun.awt.SunToolkit; 56 import sun.awt.event.IgnorePaintEvent; 57 58 import java.awt.dnd.DropTarget; 59 import java.awt.dnd.peer.DropTargetPeer; 60 import sun.awt.AWTAccessor; 61 62 import sun.util.logging.PlatformLogger; 63 64 public abstract class WComponentPeer extends WObjectPeer 65 implements ComponentPeer, DropTargetPeer 66 { 67 /** 68 * Handle to native window 69 */ 70 protected volatile long hwnd; 71 72 private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.windows.WComponentPeer"); 73 private static final PlatformLogger shapeLog = PlatformLogger.getLogger("sun.awt.windows.shape.WComponentPeer"); 74 private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.awt.windows.focus.WComponentPeer"); 75 76 // ComponentPeer implementation 77 SurfaceData surfaceData; 78 79 private RepaintArea paintArea; 80 81 protected Win32GraphicsConfig winGraphicsConfig; 82 83 boolean isLayouting = false; 84 boolean paintPending = false; 85 int oldWidth = -1; 86 int oldHeight = -1; 87 private int numBackBuffers = 0; 88 private VolatileImage backBuffer = null; 89 private BufferCapabilities backBufferCaps = null; 90 91 // foreground, background and color are cached to avoid calling back 92 // into the Component. 93 private Color foreground; 94 private Color background; 95 private Font font; 96 97 public native boolean isObscured(); 98 public boolean canDetermineObscurity() { return true; } 99 100 // DropTarget support 101 102 int nDropTargets; 103 long nativeDropTargetContext; // native pointer 104 105 public synchronized native void pShow(); 106 public synchronized native void hide(); 107 public synchronized native void enable(); 108 public synchronized native void disable(); 109 110 public long getHWnd() { 111 return hwnd; 112 } 113 114 /* New 1.1 API */ 115 public native Point getLocationOnScreen(); 116 117 /* New 1.1 API */ 118 public void setVisible(boolean b) { 119 if (b) { 120 show(); 121 } else { 122 hide(); 123 } 124 } 125 126 public void show() { 127 Dimension s = ((Component)target).getSize(); 128 oldHeight = s.height; 129 oldWidth = s.width; 130 pShow(); 131 } 132 133 /* New 1.1 API */ 134 public void setEnabled(boolean b) { 135 if (b) { 136 enable(); 137 } else { 138 disable(); 139 } 140 } 141 142 public int serialNum = 0; 143 144 private native void reshapeNoCheck(int x, int y, int width, int height); 145 146 /* New 1.1 API */ 147 public void setBounds(int x, int y, int width, int height, int op) { 148 // Should set paintPending before reahape to prevent 149 // thread race between paint events 150 // Native components do redraw after resize 151 paintPending = (width != oldWidth) || (height != oldHeight); 152 153 if ( (op & NO_EMBEDDED_CHECK) != 0 ) { 154 reshapeNoCheck(x, y, width, height); 155 } else { 156 reshape(x, y, width, height); 157 } 158 if ((width != oldWidth) || (height != oldHeight)) { 159 // Only recreate surfaceData if this setBounds is called 160 // for a resize; a simple move should not trigger a recreation 161 try { 162 replaceSurfaceData(); 163 } catch (InvalidPipeException e) { 164 // REMIND : what do we do if our surface creation failed? 165 } 166 oldWidth = width; 167 oldHeight = height; 168 } 169 170 serialNum++; 171 } 172 173 /* 174 * Called from native code (on Toolkit thread) in order to 175 * dynamically layout the Container during resizing 176 */ 177 void dynamicallyLayoutContainer() { 178 // If we got the WM_SIZING, this must be a Container, right? 179 // In fact, it must be the top-level Container. 180 if (log.isLoggable(PlatformLogger.Level.FINE)) { 181 Container parent = WToolkit.getNativeContainer((Component)target); 182 if (parent != null) { 183 log.fine("Assertion (parent == null) failed"); 184 } 185 } 186 final Container cont = (Container)target; 187 188 WToolkit.executeOnEventHandlerThread(cont, new Runnable() { 189 public void run() { 190 // Discarding old paint events doesn't seem to be necessary. 191 cont.invalidate(); 192 cont.validate(); 193 194 if (surfaceData instanceof D3DSurfaceData.D3DWindowSurfaceData || 195 surfaceData instanceof OGLSurfaceData) 196 { 197 // When OGL or D3D is enabled, it is necessary to 198 // replace the SurfaceData for each dynamic layout 199 // request so that the viewport stays in sync 200 // with the window bounds. 201 try { 202 replaceSurfaceData(); 203 } catch (InvalidPipeException e) { 204 // REMIND: this is unlikely to occur for OGL, but 205 // what do we do if surface creation fails? 206 } 207 } 208 209 // Forcing a paint here doesn't seem to be necessary. 210 // paintDamagedAreaImmediately(); 211 } 212 }); 213 } 214 215 /* 216 * Paints any portion of the component that needs updating 217 * before the call returns (similar to the Win32 API UpdateWindow) 218 */ 219 void paintDamagedAreaImmediately() { 220 // force Windows to send any pending WM_PAINT events so 221 // the damage area is updated on the Java side 222 updateWindow(); 223 // make sure paint events are transferred to main event queue 224 // for coalescing 225 SunToolkit.flushPendingEvents(); 226 // paint the damaged area 227 paintArea.paint(target, shouldClearRectBeforePaint()); 228 } 229 230 native synchronized void updateWindow(); 231 232 public void paint(Graphics g) { 233 ((Component)target).paint(g); 234 } 235 236 public void repaint(long tm, int x, int y, int width, int height) { 237 } 238 239 private static final double BANDING_DIVISOR = 4.0; 240 private native int[] createPrintedPixels(int srcX, int srcY, 241 int srcW, int srcH, 242 int alpha); 243 public void print(Graphics g) { 244 245 Component comp = (Component)target; 246 247 // To conserve memory usage, we will band the image. 248 249 int totalW = comp.getWidth(); 250 int totalH = comp.getHeight(); 251 252 int hInc = (int)(totalH / BANDING_DIVISOR); 253 if (hInc == 0) { 254 hInc = totalH; 255 } 256 257 for (int startY = 0; startY < totalH; startY += hInc) { 258 int endY = startY + hInc - 1; 259 if (endY >= totalH) { 260 endY = totalH - 1; 261 } 262 int h = endY - startY + 1; 263 264 Color bgColor = comp.getBackground(); 265 int[] pix = createPrintedPixels(0, startY, totalW, h, 266 bgColor == null ? 255 : bgColor.getAlpha()); 267 if (pix != null) { 268 BufferedImage bim = new BufferedImage(totalW, h, 269 BufferedImage.TYPE_INT_ARGB); 270 bim.setRGB(0, 0, totalW, h, pix, 0, totalW); 271 g.drawImage(bim, 0, startY, null); 272 bim.flush(); 273 } 274 } 275 276 comp.print(g); 277 } 278 279 public void coalescePaintEvent(PaintEvent e) { 280 Rectangle r = e.getUpdateRect(); 281 if (!(e instanceof IgnorePaintEvent)) { 282 paintArea.add(r, e.getID()); 283 } 284 285 if (log.isLoggable(PlatformLogger.Level.FINEST)) { 286 switch(e.getID()) { 287 case PaintEvent.UPDATE: 288 log.finest("coalescePaintEvent: UPDATE: add: x = " + 289 r.x + ", y = " + r.y + ", width = " + r.width + ", height = " + r.height); 290 return; 291 case PaintEvent.PAINT: 292 log.finest("coalescePaintEvent: PAINT: add: x = " + 293 r.x + ", y = " + r.y + ", width = " + r.width + ", height = " + r.height); 294 return; 295 } 296 } 297 } 298 299 public synchronized native void reshape(int x, int y, int width, int height); 300 301 // returns true if the event has been handled and shouldn't be propagated 302 // though handleEvent method chain - e.g. WTextFieldPeer returns true 303 // on handling '\n' to prevent it from being passed to native code 304 public boolean handleJavaKeyEvent(KeyEvent e) { return false; } 305 306 public void handleJavaMouseEvent(MouseEvent e) { 307 switch (e.getID()) { 308 case MouseEvent.MOUSE_PRESSED: 309 // Note that Swing requests focus in its own mouse event handler. 310 if (target == e.getSource() && 311 !((Component)target).isFocusOwner() && 312 WKeyboardFocusManagerPeer.shouldFocusOnClick((Component)target)) 313 { 314 WKeyboardFocusManagerPeer.requestFocusFor((Component)target, 315 CausedFocusEvent.Cause.MOUSE_EVENT); 316 } 317 break; 318 } 319 } 320 321 native void nativeHandleEvent(AWTEvent e); 322 323 @SuppressWarnings("fallthrough") 324 public void handleEvent(AWTEvent e) { 325 int id = e.getID(); 326 327 if ((e instanceof InputEvent) && !((InputEvent)e).isConsumed() && 328 ((Component)target).isEnabled()) 329 { 330 if (e instanceof MouseEvent && !(e instanceof MouseWheelEvent)) { 331 handleJavaMouseEvent((MouseEvent) e); 332 } else if (e instanceof KeyEvent) { 333 if (handleJavaKeyEvent((KeyEvent)e)) { 334 return; 335 } 336 } 337 } 338 339 switch(id) { 340 case PaintEvent.PAINT: 341 // Got native painting 342 paintPending = false; 343 // Fallthrough to next statement 344 case PaintEvent.UPDATE: 345 // Skip all painting while layouting and all UPDATEs 346 // while waiting for native paint 347 if (!isLayouting && ! paintPending) { 348 paintArea.paint(target,shouldClearRectBeforePaint()); 349 } 350 return; 351 case FocusEvent.FOCUS_LOST: 352 case FocusEvent.FOCUS_GAINED: 353 handleJavaFocusEvent((FocusEvent)e); 354 default: 355 break; 356 } 357 358 // Call the native code 359 nativeHandleEvent(e); 360 } 361 362 void handleJavaFocusEvent(FocusEvent fe) { 363 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { 364 focusLog.finer(fe.toString()); 365 } 366 setFocus(fe.getID() == FocusEvent.FOCUS_GAINED); 367 } 368 369 native void setFocus(boolean doSetFocus); 370 371 public Dimension getMinimumSize() { 372 return ((Component)target).getSize(); 373 } 374 375 public Dimension getPreferredSize() { 376 return getMinimumSize(); 377 } 378 379 // Do nothing for heavyweight implementation 380 public void layout() {} 381 382 public Rectangle getBounds() { 383 return ((Component)target).getBounds(); 384 } 385 386 public boolean isFocusable() { 387 return false; 388 } 389 390 /* 391 * Return the GraphicsConfiguration associated with this peer, either 392 * the locally stored winGraphicsConfig, or that of the target Component. 393 */ 394 public GraphicsConfiguration getGraphicsConfiguration() { 395 if (winGraphicsConfig != null) { 396 return winGraphicsConfig; 397 } 398 else { 399 // we don't need a treelock here, since 400 // Component.getGraphicsConfiguration() gets it itself. 401 return ((Component)target).getGraphicsConfiguration(); 402 } 403 } 404 405 public SurfaceData getSurfaceData() { 406 return surfaceData; 407 } 408 409 /** 410 * Creates new surfaceData object and invalidates the previous 411 * surfaceData object. 412 * Replacing the surface data should never lock on any resources which are 413 * required by other threads which may have them and may require 414 * the tree-lock. 415 * This is a degenerate version of replaceSurfaceData(numBackBuffers), so 416 * just call that version with our current numBackBuffers. 417 */ 418 public void replaceSurfaceData() { 419 replaceSurfaceData(this.numBackBuffers, this.backBufferCaps); 420 } 421 422 public void createScreenSurface(boolean isResize) 423 { 424 Win32GraphicsConfig gc = (Win32GraphicsConfig)getGraphicsConfiguration(); 425 ScreenUpdateManager mgr = ScreenUpdateManager.getInstance(); 426 427 surfaceData = mgr.createScreenSurface(gc, this, numBackBuffers, isResize); 428 } 429 430 431 /** 432 * Multi-buffer version of replaceSurfaceData. This version is called 433 * by createBuffers(), which needs to acquire the same locks in the same 434 * order, but also needs to perform additional functions inside the 435 * locks. 436 */ 437 public void replaceSurfaceData(int newNumBackBuffers, 438 BufferCapabilities caps) 439 { 440 SurfaceData oldData = null; 441 VolatileImage oldBB = null; 442 synchronized(((Component)target).getTreeLock()) { 443 synchronized(this) { 444 if (pData == 0) { 445 return; 446 } 447 numBackBuffers = newNumBackBuffers; 448 ScreenUpdateManager mgr = ScreenUpdateManager.getInstance(); 449 oldData = surfaceData; 450 mgr.dropScreenSurface(oldData); 451 createScreenSurface(true); 452 if (oldData != null) { 453 oldData.invalidate(); 454 } 455 456 oldBB = backBuffer; 457 if (numBackBuffers > 0) { 458 // set the caps first, they're used when creating the bb 459 backBufferCaps = caps; 460 Win32GraphicsConfig gc = 461 (Win32GraphicsConfig)getGraphicsConfiguration(); 462 backBuffer = gc.createBackBuffer(this); 463 } else if (backBuffer != null) { 464 backBufferCaps = null; 465 backBuffer = null; 466 } 467 } 468 } 469 // it would be better to do this before we create new ones, 470 // but then we'd run into deadlock issues 471 if (oldData != null) { 472 oldData.flush(); 473 // null out the old data to make it collected faster 474 oldData = null; 475 } 476 if (oldBB != null) { 477 oldBB.flush(); 478 // null out the old data to make it collected faster 479 oldData = null; 480 } 481 } 482 483 public void replaceSurfaceDataLater() { 484 Runnable r = new Runnable() { 485 public void run() { 486 // Shouldn't do anything if object is disposed in meanwhile 487 // No need for sync as disposeAction in Window is performed 488 // on EDT 489 if (!isDisposed()) { 490 try { 491 replaceSurfaceData(); 492 } catch (InvalidPipeException e) { 493 // REMIND : what do we do if our surface creation failed? 494 } 495 } 496 } 497 }; 498 Component c = (Component)target; 499 // Fix 6255371. 500 if (!PaintEventDispatcher.getPaintEventDispatcher().queueSurfaceDataReplacing(c, r)) { 501 postEvent(new InvocationEvent(c, r)); 502 } 503 } 504 505 public boolean updateGraphicsData(GraphicsConfiguration gc) { 506 winGraphicsConfig = (Win32GraphicsConfig)gc; 507 try { 508 replaceSurfaceData(); 509 } catch (InvalidPipeException e) { 510 // REMIND : what do we do if our surface creation failed? 511 } 512 return false; 513 } 514 515 //This will return null for Components not yet added to a Container 516 public ColorModel getColorModel() { 517 GraphicsConfiguration gc = getGraphicsConfiguration(); 518 if (gc != null) { 519 return gc.getColorModel(); 520 } 521 else { 522 return null; 523 } 524 } 525 526 //This will return null for Components not yet added to a Container 527 public ColorModel getDeviceColorModel() { 528 Win32GraphicsConfig gc = 529 (Win32GraphicsConfig)getGraphicsConfiguration(); 530 if (gc != null) { 531 return gc.getDeviceColorModel(); 532 } 533 else { 534 return null; 535 } 536 } 537 538 //Returns null for Components not yet added to a Container 539 public ColorModel getColorModel(int transparency) { 540 // return WToolkit.config.getColorModel(transparency); 541 GraphicsConfiguration gc = getGraphicsConfiguration(); 542 if (gc != null) { 543 return gc.getColorModel(transparency); 544 } 545 else { 546 return null; 547 } 548 } 549 public java.awt.Toolkit getToolkit() { 550 return Toolkit.getDefaultToolkit(); 551 } 552 553 // fallback default font object 554 final static Font defaultFont = new Font(Font.DIALOG, Font.PLAIN, 12); 555 556 @SuppressWarnings("deprecation") 557 public Graphics getGraphics() { 558 if (isDisposed()) { 559 return null; 560 } 561 562 Component target = (Component)getTarget(); 563 Window window = SunToolkit.getContainingWindow(target); 564 if (window != null) { 565 Graphics g = 566 ((WWindowPeer)window.getPeer()).getTranslucentGraphics(); 567 // getTranslucentGraphics() returns non-null value for non-opaque windows only 568 if (g != null) { 569 // Non-opaque windows do not support heavyweight children. 570 // Redirect all painting to the Window's Graphics instead. 571 // The caller is responsible for calling the 572 // WindowPeer.updateWindow() after painting has finished. 573 int x = 0, y = 0; 574 for (Component c = target; c != window; c = c.getParent()) { 575 x += c.getX(); 576 y += c.getY(); 577 } 578 579 g.translate(x, y); 580 g.clipRect(0, 0, target.getWidth(), target.getHeight()); 581 582 return g; 583 } 584 } 585 586 SurfaceData surfaceData = this.surfaceData; 587 if (surfaceData != null) { 588 /* Fix for bug 4746122. Color and Font shouldn't be null */ 589 Color bgColor = background; 590 if (bgColor == null) { 591 bgColor = SystemColor.window; 592 } 593 Color fgColor = foreground; 594 if (fgColor == null) { 595 fgColor = SystemColor.windowText; 596 } 597 Font font = this.font; 598 if (font == null) { 599 font = defaultFont; 600 } 601 ScreenUpdateManager mgr = 602 ScreenUpdateManager.getInstance(); 603 return mgr.createGraphics(surfaceData, this, fgColor, 604 bgColor, font); 605 } 606 return null; 607 } 608 public FontMetrics getFontMetrics(Font font) { 609 return WFontMetrics.getFontMetrics(font); 610 } 611 612 private synchronized native void _dispose(); 613 protected void disposeImpl() { 614 SurfaceData oldData = surfaceData; 615 surfaceData = null; 616 ScreenUpdateManager.getInstance().dropScreenSurface(oldData); 617 oldData.invalidate(); 618 // remove from updater before calling targetDisposedPeer 619 WToolkit.targetDisposedPeer(target, this); 620 _dispose(); 621 } 622 623 public void disposeLater() { 624 postEvent(new InvocationEvent(target, new Runnable() { 625 public void run() { 626 dispose(); 627 } 628 })); 629 } 630 631 public synchronized void setForeground(Color c) { 632 foreground = c; 633 _setForeground(c.getRGB()); 634 } 635 636 public synchronized void setBackground(Color c) { 637 background = c; 638 _setBackground(c.getRGB()); 639 } 640 641 /** 642 * This method is intentionally not synchronized as it is called while 643 * holding other locks. 644 * 645 * @see sun.java2d.d3d.D3DScreenUpdateManager#validate(D3DWindowSurfaceData) 646 */ 647 public Color getBackgroundNoSync() { 648 return background; 649 } 650 651 public native void _setForeground(int rgb); 652 public native void _setBackground(int rgb); 653 654 public synchronized void setFont(Font f) { 655 font = f; 656 _setFont(f); 657 } 658 public synchronized native void _setFont(Font f); 659 public final void updateCursorImmediately() { 660 WGlobalCursorManager.getCursorManager().updateCursorImmediately(); 661 } 662 663 // TODO: consider moving it to KeyboardFocusManagerPeerImpl 664 @SuppressWarnings("deprecation") 665 public boolean requestFocus(Component lightweightChild, boolean temporary, 666 boolean focusedWindowChangeAllowed, long time, 667 CausedFocusEvent.Cause cause) 668 { 669 if (WKeyboardFocusManagerPeer. 670 processSynchronousLightweightTransfer((Component)target, lightweightChild, temporary, 671 focusedWindowChangeAllowed, time)) 672 { 673 return true; 674 } 675 676 int result = WKeyboardFocusManagerPeer 677 .shouldNativelyFocusHeavyweight((Component)target, lightweightChild, 678 temporary, focusedWindowChangeAllowed, 679 time, cause); 680 681 switch (result) { 682 case WKeyboardFocusManagerPeer.SNFH_FAILURE: 683 return false; 684 case WKeyboardFocusManagerPeer.SNFH_SUCCESS_PROCEED: 685 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { 686 focusLog.finer("Proceeding with request to " + lightweightChild + " in " + target); 687 } 688 Window parentWindow = SunToolkit.getContainingWindow((Component)target); 689 if (parentWindow == null) { 690 return rejectFocusRequestHelper("WARNING: Parent window is null"); 691 } 692 WWindowPeer wpeer = (WWindowPeer)parentWindow.getPeer(); 693 if (wpeer == null) { 694 return rejectFocusRequestHelper("WARNING: Parent window's peer is null"); 695 } 696 boolean res = wpeer.requestWindowFocus(cause); 697 698 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { 699 focusLog.finer("Requested window focus: " + res); 700 } 701 // If parent window can be made focused and has been made focused(synchronously) 702 // then we can proceed with children, otherwise we retreat. 703 if (!(res && parentWindow.isFocused())) { 704 return rejectFocusRequestHelper("Waiting for asynchronous processing of the request"); 705 } 706 return WKeyboardFocusManagerPeer.deliverFocus(lightweightChild, 707 (Component)target, 708 temporary, 709 focusedWindowChangeAllowed, 710 time, cause); 711 712 case WKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED: 713 // Either lightweight or excessive request - all events are generated. 714 return true; 715 } 716 return false; 717 } 718 719 private boolean rejectFocusRequestHelper(String logMsg) { 720 if (focusLog.isLoggable(PlatformLogger.Level.FINER)) { 721 focusLog.finer(logMsg); 722 } 723 WKeyboardFocusManagerPeer.removeLastFocusRequest((Component)target); 724 return false; 725 } 726 727 public Image createImage(ImageProducer producer) { 728 return new ToolkitImage(producer); 729 } 730 731 public Image createImage(int width, int height) { 732 Win32GraphicsConfig gc = 733 (Win32GraphicsConfig)getGraphicsConfiguration(); 734 return gc.createAcceleratedImage((Component)target, width, height); 735 } 736 737 public VolatileImage createVolatileImage(int width, int height) { 738 return new SunVolatileImage((Component)target, width, height); 739 } 740 741 public boolean prepareImage(Image img, int w, int h, ImageObserver o) { 742 return getToolkit().prepareImage(img, w, h, o); 743 } 744 745 public int checkImage(Image img, int w, int h, ImageObserver o) { 746 return getToolkit().checkImage(img, w, h, o); 747 } 748 749 // Object overrides 750 751 public String toString() { 752 return getClass().getName() + "[" + target + "]"; 753 } 754 755 // Toolkit & peer internals 756 757 private int updateX1, updateY1, updateX2, updateY2; 758 759 WComponentPeer(Component target) { 760 this.target = target; 761 this.paintArea = new RepaintArea(); 762 create(getNativeParent()); 763 // fix for 5088782: check if window object is created successfully 764 checkCreation(); 765 766 createScreenSurface(false); 767 initialize(); 768 start(); // Initialize enable/disable state, turn on callbacks 769 } 770 abstract void create(WComponentPeer parent); 771 772 /** 773 * Gets the native parent of this peer. We use the term "parent" explicitly, 774 * because we override the method in top-level window peer implementations. 775 * 776 * @return the parent container/owner of this peer. 777 */ 778 WComponentPeer getNativeParent() { 779 Container parent = SunToolkit.getNativeContainer((Component) target); 780 return (WComponentPeer) WToolkit.targetToPeer(parent); 781 } 782 783 protected void checkCreation() 784 { 785 if ((hwnd == 0) || (pData == 0)) 786 { 787 if (createError != null) 788 { 789 throw createError; 790 } 791 else 792 { 793 throw new InternalError("couldn't create component peer"); 794 } 795 } 796 } 797 798 synchronized native void start(); 799 800 void initialize() { 801 if (((Component)target).isVisible()) { 802 show(); // the wnd starts hidden 803 } 804 Color fg = ((Component)target).getForeground(); 805 if (fg != null) { 806 setForeground(fg); 807 } 808 // Set background color in C++, to avoid inheriting a parent's color. 809 Font f = ((Component)target).getFont(); 810 if (f != null) { 811 setFont(f); 812 } 813 if (! ((Component)target).isEnabled()) { 814 disable(); 815 } 816 Rectangle r = ((Component)target).getBounds(); 817 setBounds(r.x, r.y, r.width, r.height, SET_BOUNDS); 818 } 819 820 // Callbacks for window-system events to the frame 821 822 // Invoke a update() method call on the target 823 void handleRepaint(int x, int y, int w, int h) { 824 // Repaints are posted from updateClient now... 825 } 826 827 // Invoke a paint() method call on the target, after clearing the 828 // damaged area. 829 void handleExpose(int x, int y, int w, int h) { 830 // Bug ID 4081126 & 4129709 - can't do the clearRect() here, 831 // since it interferes with the java thread working in the 832 // same window on multi-processor NT machines. 833 834 postPaintIfNecessary(x, y, w, h); 835 } 836 837 /* Invoke a paint() method call on the target, without clearing the 838 * damaged area. This is normally called by a native control after 839 * it has painted itself. 840 * 841 * NOTE: This is called on the privileged toolkit thread. Do not 842 * call directly into user code using this thread! 843 */ 844 public void handlePaint(int x, int y, int w, int h) { 845 postPaintIfNecessary(x, y, w, h); 846 } 847 848 private void postPaintIfNecessary(int x, int y, int w, int h) { 849 if ( !AWTAccessor.getComponentAccessor().getIgnoreRepaint( (Component) target) ) { 850 PaintEvent event = PaintEventDispatcher.getPaintEventDispatcher(). 851 createPaintEvent((Component)target, x, y, w, h); 852 if (event != null) { 853 postEvent(event); 854 } 855 } 856 } 857 858 /* 859 * Post an event. Queue it for execution by the callback thread. 860 */ 861 void postEvent(AWTEvent event) { 862 preprocessPostEvent(event); 863 WToolkit.postEvent(WToolkit.targetToAppContext(target), event); 864 } 865 866 void preprocessPostEvent(AWTEvent event) {} 867 868 // Routines to support deferred window positioning. 869 public void beginLayout() { 870 // Skip all painting till endLayout 871 isLayouting = true; 872 } 873 874 public void endLayout() { 875 if(!paintArea.isEmpty() && !paintPending && 876 !((Component)target).getIgnoreRepaint()) { 877 // if not waiting for native painting repaint damaged area 878 postEvent(new PaintEvent((Component)target, PaintEvent.PAINT, 879 new Rectangle())); 880 } 881 isLayouting = false; 882 } 883 884 public native void beginValidate(); 885 public native void endValidate(); 886 887 /** 888 * DEPRECATED 889 */ 890 public Dimension minimumSize() { 891 return getMinimumSize(); 892 } 893 894 /** 895 * DEPRECATED 896 */ 897 public Dimension preferredSize() { 898 return getPreferredSize(); 899 } 900 901 /** 902 * register a DropTarget with this native peer 903 */ 904 905 public synchronized void addDropTarget(DropTarget dt) { 906 if (nDropTargets == 0) { 907 nativeDropTargetContext = addNativeDropTarget(); 908 } 909 nDropTargets++; 910 } 911 912 /** 913 * unregister a DropTarget with this native peer 914 */ 915 916 public synchronized void removeDropTarget(DropTarget dt) { 917 nDropTargets--; 918 if (nDropTargets == 0) { 919 removeNativeDropTarget(); 920 nativeDropTargetContext = 0; 921 } 922 } 923 924 /** 925 * add the native peer's AwtDropTarget COM object 926 * @return reference to AwtDropTarget object 927 */ 928 929 native long addNativeDropTarget(); 930 931 /** 932 * remove the native peer's AwtDropTarget COM object 933 */ 934 935 native void removeNativeDropTarget(); 936 native boolean nativeHandlesWheelScrolling(); 937 938 public boolean handlesWheelScrolling() { 939 // should this be cached? 940 return nativeHandlesWheelScrolling(); 941 } 942 943 // Returns true if we are inside begin/endLayout and 944 // are waiting for native painting 945 public boolean isPaintPending() { 946 return paintPending && isLayouting; 947 } 948 949 /** 950 * The following multibuffering-related methods delegate to our 951 * associated GraphicsConfig (Win or WGL) to handle the appropriate 952 * native windowing system specific actions. 953 */ 954 955 @Override 956 public void createBuffers(int numBuffers, BufferCapabilities caps) 957 throws AWTException 958 { 959 Win32GraphicsConfig gc = 960 (Win32GraphicsConfig)getGraphicsConfiguration(); 961 gc.assertOperationSupported((Component)target, numBuffers, caps); 962 963 // Re-create the primary surface with the new number of back buffers 964 try { 965 replaceSurfaceData(numBuffers - 1, caps); 966 } catch (InvalidPipeException e) { 967 throw new AWTException(e.getMessage()); 968 } 969 } 970 971 @Override 972 public void destroyBuffers() { 973 replaceSurfaceData(0, null); 974 } 975 976 @Override 977 public void flip(int x1, int y1, int x2, int y2, 978 BufferCapabilities.FlipContents flipAction) 979 { 980 VolatileImage backBuffer = this.backBuffer; 981 if (backBuffer == null) { 982 throw new IllegalStateException("Buffers have not been created"); 983 } 984 Win32GraphicsConfig gc = 985 (Win32GraphicsConfig)getGraphicsConfiguration(); 986 gc.flip(this, (Component)target, backBuffer, x1, y1, x2, y2, flipAction); 987 } 988 989 @Override 990 public synchronized Image getBackBuffer() { 991 Image backBuffer = this.backBuffer; 992 if (backBuffer == null) { 993 throw new IllegalStateException("Buffers have not been created"); 994 } 995 return backBuffer; 996 } 997 public BufferCapabilities getBackBufferCaps() { 998 return backBufferCaps; 999 } 1000 public int getBackBuffersNum() { 1001 return numBackBuffers; 1002 } 1003 1004 /* override and return false on components that DO NOT require 1005 a clearRect() before painting (i.e. native components) */ 1006 public boolean shouldClearRectBeforePaint() { 1007 return true; 1008 } 1009 1010 native void pSetParent(ComponentPeer newNativeParent); 1011 1012 /** 1013 * @see java.awt.peer.ComponentPeer#reparent 1014 */ 1015 public void reparent(ContainerPeer newNativeParent) { 1016 pSetParent(newNativeParent); 1017 } 1018 1019 /** 1020 * @see java.awt.peer.ComponentPeer#isReparentSupported 1021 */ 1022 public boolean isReparentSupported() { 1023 return true; 1024 } 1025 1026 public void setBoundsOperation(int operation) { 1027 } 1028 1029 private volatile boolean isAccelCapable = true; 1030 1031 /** 1032 * Returns whether this component is capable of being hw accelerated. 1033 * More specifically, whether rendering to this component or a 1034 * BufferStrategy's back-buffer for this component can be hw accelerated. 1035 * 1036 * Conditions which could prevent hw acceleration include the toplevel 1037 * window containing this component being 1038 * {@link GraphicsDevice.WindowTranslucency#PERPIXEL_TRANSLUCENT 1039 * PERPIXEL_TRANSLUCENT}. 1040 * 1041 * Another condition is if Xor paint mode was detected when rendering 1042 * to an on-screen accelerated surface associated with this peer. 1043 * in this case both on- and off-screen acceleration for this peer is 1044 * disabled. 1045 * 1046 * @return {@code true} if this component is capable of being hw 1047 * accelerated, {@code false} otherwise 1048 * @see GraphicsDevice.WindowTranslucency#PERPIXEL_TRANSLUCENT 1049 */ 1050 public boolean isAccelCapable() { 1051 if (!isAccelCapable || 1052 !isContainingTopLevelAccelCapable((Component)target)) 1053 { 1054 return false; 1055 } 1056 1057 boolean isTranslucent = 1058 SunToolkit.isContainingTopLevelTranslucent((Component)target); 1059 // D3D/OGL and translucent windows interacted poorly in Windows XP; 1060 // these problems are no longer present in Vista 1061 return !isTranslucent || Win32GraphicsEnvironment.isVistaOS(); 1062 } 1063 1064 /** 1065 * Disables acceleration for this peer. 1066 */ 1067 public void disableAcceleration() { 1068 isAccelCapable = false; 1069 } 1070 1071 1072 native void setRectangularShape(int lox, int loy, int hix, int hiy, 1073 Region region); 1074 1075 1076 // REMIND: Temp workaround for issues with using HW acceleration 1077 // in the browser on Vista when DWM is enabled. 1078 // @return true if the toplevel container is not an EmbeddedFrame or 1079 // if this EmbeddedFrame is acceleration capable, false otherwise 1080 @SuppressWarnings("deprecation") 1081 private static final boolean isContainingTopLevelAccelCapable(Component c) { 1082 while (c != null && !(c instanceof WEmbeddedFrame)) { 1083 c = c.getParent(); 1084 } 1085 if (c == null) { 1086 return true; 1087 } 1088 return ((WEmbeddedFramePeer)c.getPeer()).isAccelCapable(); 1089 } 1090 1091 /** 1092 * Applies the shape to the native component window. 1093 * @since 1.7 1094 */ 1095 @SuppressWarnings("deprecation") 1096 public void applyShape(Region shape) { 1097 if (shapeLog.isLoggable(PlatformLogger.Level.FINER)) { 1098 shapeLog.finer("*** INFO: Setting shape: PEER: " + this 1099 + "; TARGET: " + target 1100 + "; SHAPE: " + shape); 1101 } 1102 1103 if (shape != null) { 1104 setRectangularShape(shape.getLoX(), shape.getLoY(), shape.getHiX(), shape.getHiY(), 1105 (shape.isRectangular() ? null : shape)); 1106 } else { 1107 setRectangularShape(0, 0, 0, 0, null); 1108 } 1109 } 1110 1111 /** 1112 * Lowers this component at the bottom of the above component. If the above parameter 1113 * is null then the method places this component at the top of the Z-order. 1114 */ 1115 public void setZOrder(ComponentPeer above) { 1116 long aboveHWND = (above != null) ? ((WComponentPeer)above).getHWnd() : 0; 1117 1118 setZOrder(aboveHWND); 1119 } 1120 1121 private native void setZOrder(long above); 1122 }