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