blob: d697fd34047c707b90141afc5d8cf5feb0aa4d83 [file] [log] [blame]
/*
* Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.windows;
import java.awt.*;
import java.awt.peer.*;
import java.awt.image.VolatileImage;
import sun.awt.RepaintArea;
import sun.awt.CausedFocusEvent;
import sun.awt.image.SunVolatileImage;
import sun.awt.image.ToolkitImage;
import java.awt.image.BufferedImage;
import java.awt.image.ImageProducer;
import java.awt.image.ImageObserver;
import java.awt.image.ColorModel;
import java.awt.event.PaintEvent;
import java.awt.event.InvocationEvent;
import java.awt.event.KeyEvent;
import java.awt.event.FocusEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.InputEvent;
import sun.awt.Win32GraphicsConfig;
import sun.awt.Win32GraphicsEnvironment;
import sun.java2d.InvalidPipeException;
import sun.java2d.SurfaceData;
import sun.java2d.ScreenUpdateManager;
import sun.java2d.d3d.D3DSurfaceData;
import sun.java2d.opengl.OGLSurfaceData;
import sun.java2d.pipe.Region;
import sun.awt.DisplayChangedListener;
import sun.awt.PaintEventDispatcher;
import sun.awt.SunToolkit;
import sun.awt.event.IgnorePaintEvent;
import java.awt.dnd.DropTarget;
import java.awt.dnd.peer.DropTargetPeer;
import sun.awt.AWTAccessor;
import sun.util.logging.PlatformLogger;
public abstract class WComponentPeer extends WObjectPeer
implements ComponentPeer, DropTargetPeer
{
/**
* Handle to native window
*/
protected volatile long hwnd;
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.windows.WComponentPeer");
private static final PlatformLogger shapeLog = PlatformLogger.getLogger("sun.awt.windows.shape.WComponentPeer");
private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.awt.windows.focus.WComponentPeer");
// ComponentPeer implementation
SurfaceData surfaceData;
private RepaintArea paintArea;
protected Win32GraphicsConfig winGraphicsConfig;
boolean isLayouting = false;
boolean paintPending = false;
int oldWidth = -1;
int oldHeight = -1;
private int numBackBuffers = 0;
private VolatileImage backBuffer = null;
private BufferCapabilities backBufferCaps = null;
// foreground, background and color are cached to avoid calling back
// into the Component.
private Color foreground;
private Color background;
private Font font;
public native boolean isObscured();
public boolean canDetermineObscurity() { return true; }
// DropTarget support
int nDropTargets;
long nativeDropTargetContext; // native pointer
public synchronized native void pShow();
public synchronized native void hide();
public synchronized native void enable();
public synchronized native void disable();
public long getHWnd() {
return hwnd;
}
/* New 1.1 API */
public native Point getLocationOnScreen();
/* New 1.1 API */
public void setVisible(boolean b) {
if (b) {
show();
} else {
hide();
}
}
public void show() {
Dimension s = ((Component)target).getSize();
oldHeight = s.height;
oldWidth = s.width;
pShow();
}
/* New 1.1 API */
public void setEnabled(boolean b) {
if (b) {
enable();
} else {
disable();
}
}
public int serialNum = 0;
private native void reshapeNoCheck(int x, int y, int width, int height);
/* New 1.1 API */
public void setBounds(int x, int y, int width, int height, int op) {
// Should set paintPending before reahape to prevent
// thread race between paint events
// Native components do redraw after resize
paintPending = (width != oldWidth) || (height != oldHeight);
if ( (op & NO_EMBEDDED_CHECK) != 0 ) {
reshapeNoCheck(x, y, width, height);
} else {
reshape(x, y, width, height);
}
if ((width != oldWidth) || (height != oldHeight)) {
// Only recreate surfaceData if this setBounds is called
// for a resize; a simple move should not trigger a recreation
try {
replaceSurfaceData();
} catch (InvalidPipeException e) {
// REMIND : what do we do if our surface creation failed?
}
oldWidth = width;
oldHeight = height;
}
serialNum++;
}
/*
* Called from native code (on Toolkit thread) in order to
* dynamically layout the Container during resizing
*/
void dynamicallyLayoutContainer() {
// If we got the WM_SIZING, this must be a Container, right?
// In fact, it must be the top-level Container.
if (log.isLoggable(PlatformLogger.FINE)) {
Container parent = WToolkit.getNativeContainer((Component)target);
if (parent != null) {
log.fine("Assertion (parent == null) failed");
}
}
final Container cont = (Container)target;
WToolkit.executeOnEventHandlerThread(cont, new Runnable() {
public void run() {
// Discarding old paint events doesn't seem to be necessary.
cont.invalidate();
cont.validate();
if (surfaceData instanceof D3DSurfaceData.D3DWindowSurfaceData ||
surfaceData instanceof OGLSurfaceData)
{
// When OGL or D3D is enabled, it is necessary to
// replace the SurfaceData for each dynamic layout
// request so that the viewport stays in sync
// with the window bounds.
try {
replaceSurfaceData();
} catch (InvalidPipeException e) {
// REMIND: this is unlikely to occur for OGL, but
// what do we do if surface creation fails?
}
}
// Forcing a paint here doesn't seem to be necessary.
// paintDamagedAreaImmediately();
}
});
}
/*
* Paints any portion of the component that needs updating
* before the call returns (similar to the Win32 API UpdateWindow)
*/
void paintDamagedAreaImmediately() {
// force Windows to send any pending WM_PAINT events so
// the damage area is updated on the Java side
updateWindow();
// make sure paint events are transferred to main event queue
// for coalescing
WToolkit.getWToolkit().flushPendingEvents();
// paint the damaged area
paintArea.paint(target, shouldClearRectBeforePaint());
}
native synchronized void updateWindow();
public void paint(Graphics g) {
((Component)target).paint(g);
}
public void repaint(long tm, int x, int y, int width, int height) {
}
private static final double BANDING_DIVISOR = 4.0;
private native int[] createPrintedPixels(int srcX, int srcY,
int srcW, int srcH,
int alpha);
public void print(Graphics g) {
Component comp = (Component)target;
// To conserve memory usage, we will band the image.
int totalW = comp.getWidth();
int totalH = comp.getHeight();
int hInc = (int)(totalH / BANDING_DIVISOR);
if (hInc == 0) {
hInc = totalH;
}
for (int startY = 0; startY < totalH; startY += hInc) {
int endY = startY + hInc - 1;
if (endY >= totalH) {
endY = totalH - 1;
}
int h = endY - startY + 1;
Color bgColor = comp.getBackground();
int[] pix = createPrintedPixels(0, startY, totalW, h,
bgColor == null ? 255 : bgColor.getAlpha());
if (pix != null) {
BufferedImage bim = new BufferedImage(totalW, h,
BufferedImage.TYPE_INT_ARGB);
bim.setRGB(0, 0, totalW, h, pix, 0, totalW);
g.drawImage(bim, 0, startY, null);
bim.flush();
}
}
comp.print(g);
}
public void coalescePaintEvent(PaintEvent e) {
Rectangle r = e.getUpdateRect();
if (!(e instanceof IgnorePaintEvent)) {
paintArea.add(r, e.getID());
}
if (log.isLoggable(PlatformLogger.FINEST)) {
switch(e.getID()) {
case PaintEvent.UPDATE:
log.finest("coalescePaintEvent: UPDATE: add: x = " +
r.x + ", y = " + r.y + ", width = " + r.width + ", height = " + r.height);
return;
case PaintEvent.PAINT:
log.finest("coalescePaintEvent: PAINT: add: x = " +
r.x + ", y = " + r.y + ", width = " + r.width + ", height = " + r.height);
return;
}
}
}
public synchronized native void reshape(int x, int y, int width, int height);
// returns true if the event has been handled and shouldn't be propagated
// though handleEvent method chain - e.g. WTextFieldPeer returns true
// on handling '\n' to prevent it from being passed to native code
public boolean handleJavaKeyEvent(KeyEvent e) { return false; }
public void handleJavaMouseEvent(MouseEvent e) {
switch (e.getID()) {
case MouseEvent.MOUSE_PRESSED:
// Note that Swing requests focus in its own mouse event handler.
if (target == e.getSource() &&
!((Component)target).isFocusOwner() &&
WKeyboardFocusManagerPeer.shouldFocusOnClick((Component)target))
{
WKeyboardFocusManagerPeer.requestFocusFor((Component)target,
CausedFocusEvent.Cause.MOUSE_EVENT);
}
break;
}
}
native void nativeHandleEvent(AWTEvent e);
public void handleEvent(AWTEvent e) {
int id = e.getID();
if ((e instanceof InputEvent) && !((InputEvent)e).isConsumed() &&
((Component)target).isEnabled())
{
if (e instanceof MouseEvent && !(e instanceof MouseWheelEvent)) {
handleJavaMouseEvent((MouseEvent) e);
} else if (e instanceof KeyEvent) {
if (handleJavaKeyEvent((KeyEvent)e)) {
return;
}
}
}
switch(id) {
case PaintEvent.PAINT:
// Got native painting
paintPending = false;
// Fallthrough to next statement
case PaintEvent.UPDATE:
// Skip all painting while layouting and all UPDATEs
// while waiting for native paint
if (!isLayouting && ! paintPending) {
paintArea.paint(target,shouldClearRectBeforePaint());
}
return;
case FocusEvent.FOCUS_LOST:
case FocusEvent.FOCUS_GAINED:
handleJavaFocusEvent((FocusEvent)e);
default:
break;
}
// Call the native code
nativeHandleEvent(e);
}
void handleJavaFocusEvent(FocusEvent fe) {
if (focusLog.isLoggable(PlatformLogger.FINER)) focusLog.finer(fe.toString());
setFocus(fe.getID() == FocusEvent.FOCUS_GAINED);
}
native void setFocus(boolean doSetFocus);
public Dimension getMinimumSize() {
return ((Component)target).getSize();
}
public Dimension getPreferredSize() {
return getMinimumSize();
}
// Do nothing for heavyweight implementation
public void layout() {}
public Rectangle getBounds() {
return ((Component)target).getBounds();
}
public boolean isFocusable() {
return false;
}
/*
* Return the GraphicsConfiguration associated with this peer, either
* the locally stored winGraphicsConfig, or that of the target Component.
*/
public GraphicsConfiguration getGraphicsConfiguration() {
if (winGraphicsConfig != null) {
return winGraphicsConfig;
}
else {
// we don't need a treelock here, since
// Component.getGraphicsConfiguration() gets it itself.
return ((Component)target).getGraphicsConfiguration();
}
}
public SurfaceData getSurfaceData() {
return surfaceData;
}
/**
* Creates new surfaceData object and invalidates the previous
* surfaceData object.
* Replacing the surface data should never lock on any resources which are
* required by other threads which may have them and may require
* the tree-lock.
* This is a degenerate version of replaceSurfaceData(numBackBuffers), so
* just call that version with our current numBackBuffers.
*/
public void replaceSurfaceData() {
replaceSurfaceData(this.numBackBuffers, this.backBufferCaps);
}
public void createScreenSurface(boolean isResize)
{
Win32GraphicsConfig gc = (Win32GraphicsConfig)getGraphicsConfiguration();
ScreenUpdateManager mgr = ScreenUpdateManager.getInstance();
surfaceData = mgr.createScreenSurface(gc, this, numBackBuffers, isResize);
}
/**
* Multi-buffer version of replaceSurfaceData. This version is called
* by createBuffers(), which needs to acquire the same locks in the same
* order, but also needs to perform additional functions inside the
* locks.
*/
public void replaceSurfaceData(int newNumBackBuffers,
BufferCapabilities caps)
{
SurfaceData oldData = null;
VolatileImage oldBB = null;
synchronized(((Component)target).getTreeLock()) {
synchronized(this) {
if (pData == 0) {
return;
}
numBackBuffers = newNumBackBuffers;
ScreenUpdateManager mgr = ScreenUpdateManager.getInstance();
oldData = surfaceData;
mgr.dropScreenSurface(oldData);
createScreenSurface(true);
if (oldData != null) {
oldData.invalidate();
}
oldBB = backBuffer;
if (numBackBuffers > 0) {
// set the caps first, they're used when creating the bb
backBufferCaps = caps;
Win32GraphicsConfig gc =
(Win32GraphicsConfig)getGraphicsConfiguration();
backBuffer = gc.createBackBuffer(this);
} else if (backBuffer != null) {
backBufferCaps = null;
backBuffer = null;
}
}
}
// it would be better to do this before we create new ones,
// but then we'd run into deadlock issues
if (oldData != null) {
oldData.flush();
// null out the old data to make it collected faster
oldData = null;
}
if (oldBB != null) {
oldBB.flush();
// null out the old data to make it collected faster
oldData = null;
}
}
public void replaceSurfaceDataLater() {
Runnable r = new Runnable() {
public void run() {
// Shouldn't do anything if object is disposed in meanwhile
// No need for sync as disposeAction in Window is performed
// on EDT
if (!isDisposed()) {
try {
replaceSurfaceData();
} catch (InvalidPipeException e) {
// REMIND : what do we do if our surface creation failed?
}
}
}
};
// Fix 6255371.
if (!PaintEventDispatcher.getPaintEventDispatcher().queueSurfaceDataReplacing((Component)target, r)) {
postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(), r));
}
}
public boolean updateGraphicsData(GraphicsConfiguration gc) {
winGraphicsConfig = (Win32GraphicsConfig)gc;
try {
replaceSurfaceData();
} catch (InvalidPipeException e) {
// REMIND : what do we do if our surface creation failed?
}
return false;
}
//This will return null for Components not yet added to a Container
public ColorModel getColorModel() {
GraphicsConfiguration gc = getGraphicsConfiguration();
if (gc != null) {
return gc.getColorModel();
}
else {
return null;
}
}
//This will return null for Components not yet added to a Container
public ColorModel getDeviceColorModel() {
Win32GraphicsConfig gc =
(Win32GraphicsConfig)getGraphicsConfiguration();
if (gc != null) {
return gc.getDeviceColorModel();
}
else {
return null;
}
}
//Returns null for Components not yet added to a Container
public ColorModel getColorModel(int transparency) {
// return WToolkit.config.getColorModel(transparency);
GraphicsConfiguration gc = getGraphicsConfiguration();
if (gc != null) {
return gc.getColorModel(transparency);
}
else {
return null;
}
}
public java.awt.Toolkit getToolkit() {
return Toolkit.getDefaultToolkit();
}
// fallback default font object
final static Font defaultFont = new Font(Font.DIALOG, Font.PLAIN, 12);
public Graphics getGraphics() {
if (isDisposed()) {
return null;
}
Component target = (Component)getTarget();
Window window = SunToolkit.getContainingWindow(target);
if (window != null && !window.isOpaque()) {
// Non-opaque windows do not support heavyweight children.
// Redirect all painting to the Window's Graphics instead.
// The caller is responsible for calling the
// WindowPeer.updateWindow() after painting has finished.
int x = 0, y = 0;
for (Component c = target; c != window; c = c.getParent()) {
x += c.getX();
y += c.getY();
}
Graphics g =
((WWindowPeer)window.getPeer()).getTranslucentGraphics();
g.translate(x, y);
g.clipRect(0, 0, target.getWidth(), target.getHeight());
return g;
}
SurfaceData surfaceData = this.surfaceData;
if (surfaceData != null) {
/* Fix for bug 4746122. Color and Font shouldn't be null */
Color bgColor = background;
if (bgColor == null) {
bgColor = SystemColor.window;
}
Color fgColor = foreground;
if (fgColor == null) {
fgColor = SystemColor.windowText;
}
Font font = this.font;
if (font == null) {
font = defaultFont;
}
ScreenUpdateManager mgr =
ScreenUpdateManager.getInstance();
return mgr.createGraphics(surfaceData, this, fgColor,
bgColor, font);
}
return null;
}
public FontMetrics getFontMetrics(Font font) {
return WFontMetrics.getFontMetrics(font);
}
private synchronized native void _dispose();
protected void disposeImpl() {
SurfaceData oldData = surfaceData;
surfaceData = null;
ScreenUpdateManager.getInstance().dropScreenSurface(oldData);
oldData.invalidate();
// remove from updater before calling targetDisposedPeer
WToolkit.targetDisposedPeer(target, this);
_dispose();
}
public synchronized void setForeground(Color c) {
foreground = c;
_setForeground(c.getRGB());
}
public synchronized void setBackground(Color c) {
background = c;
_setBackground(c.getRGB());
}
/**
* This method is intentionally not synchronized as it is called while
* holding other locks.
*
* @see sun.java2d.d3d.D3DScreenUpdateManager#validate(D3DWindowSurfaceData)
*/
public Color getBackgroundNoSync() {
return background;
}
public native void _setForeground(int rgb);
public native void _setBackground(int rgb);
public synchronized void setFont(Font f) {
font = f;
_setFont(f);
}
public synchronized native void _setFont(Font f);
public final void updateCursorImmediately() {
WGlobalCursorManager.getCursorManager().updateCursorImmediately();
}
// TODO: consider moving it to KeyboardFocusManagerPeerImpl
public boolean requestFocus(Component lightweightChild, boolean temporary,
boolean focusedWindowChangeAllowed, long time,
CausedFocusEvent.Cause cause)
{
if (WKeyboardFocusManagerPeer.
processSynchronousLightweightTransfer((Component)target, lightweightChild, temporary,
focusedWindowChangeAllowed, time))
{
return true;
}
int result = WKeyboardFocusManagerPeer
.shouldNativelyFocusHeavyweight((Component)target, lightweightChild,
temporary, focusedWindowChangeAllowed,
time, cause);
switch (result) {
case WKeyboardFocusManagerPeer.SNFH_FAILURE:
return false;
case WKeyboardFocusManagerPeer.SNFH_SUCCESS_PROCEED:
if (focusLog.isLoggable(PlatformLogger.FINER)) {
focusLog.finer("Proceeding with request to " + lightweightChild + " in " + target);
}
Window parentWindow = SunToolkit.getContainingWindow((Component)target);
if (parentWindow == null) {
return rejectFocusRequestHelper("WARNING: Parent window is null");
}
WWindowPeer wpeer = (WWindowPeer)parentWindow.getPeer();
if (wpeer == null) {
return rejectFocusRequestHelper("WARNING: Parent window's peer is null");
}
boolean res = wpeer.requestWindowFocus(cause);
if (focusLog.isLoggable(PlatformLogger.FINER)) focusLog.finer("Requested window focus: " + res);
// If parent window can be made focused and has been made focused(synchronously)
// then we can proceed with children, otherwise we retreat.
if (!(res && parentWindow.isFocused())) {
return rejectFocusRequestHelper("Waiting for asynchronous processing of the request");
}
return WKeyboardFocusManagerPeer.deliverFocus(lightweightChild,
(Component)target,
temporary,
focusedWindowChangeAllowed,
time, cause);
case WKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED:
// Either lightweight or excessive request - all events are generated.
return true;
}
return false;
}
private boolean rejectFocusRequestHelper(String logMsg) {
if (focusLog.isLoggable(PlatformLogger.FINER)) focusLog.finer(logMsg);
WKeyboardFocusManagerPeer.removeLastFocusRequest((Component)target);
return false;
}
public Image createImage(ImageProducer producer) {
return new ToolkitImage(producer);
}
public Image createImage(int width, int height) {
Win32GraphicsConfig gc =
(Win32GraphicsConfig)getGraphicsConfiguration();
return gc.createAcceleratedImage((Component)target, width, height);
}
public VolatileImage createVolatileImage(int width, int height) {
return new SunVolatileImage((Component)target, width, height);
}
public boolean prepareImage(Image img, int w, int h, ImageObserver o) {
return getToolkit().prepareImage(img, w, h, o);
}
public int checkImage(Image img, int w, int h, ImageObserver o) {
return getToolkit().checkImage(img, w, h, o);
}
// Object overrides
public String toString() {
return getClass().getName() + "[" + target + "]";
}
// Toolkit & peer internals
private int updateX1, updateY1, updateX2, updateY2;
WComponentPeer(Component target) {
this.target = target;
this.paintArea = new RepaintArea();
Container parent = WToolkit.getNativeContainer(target);
WComponentPeer parentPeer = (WComponentPeer) WToolkit.targetToPeer(parent);
create(parentPeer);
// fix for 5088782: check if window object is created successfully
checkCreation();
createScreenSurface(false);
initialize();
start(); // Initialize enable/disable state, turn on callbacks
}
abstract void create(WComponentPeer parent);
protected void checkCreation()
{
if ((hwnd == 0) || (pData == 0))
{
if (createError != null)
{
throw createError;
}
else
{
throw new InternalError("couldn't create component peer");
}
}
}
synchronized native void start();
void initialize() {
if (((Component)target).isVisible()) {
show(); // the wnd starts hidden
}
Color fg = ((Component)target).getForeground();
if (fg != null) {
setForeground(fg);
}
// Set background color in C++, to avoid inheriting a parent's color.
Font f = ((Component)target).getFont();
if (f != null) {
setFont(f);
}
if (! ((Component)target).isEnabled()) {
disable();
}
Rectangle r = ((Component)target).getBounds();
setBounds(r.x, r.y, r.width, r.height, SET_BOUNDS);
}
// Callbacks for window-system events to the frame
// Invoke a update() method call on the target
void handleRepaint(int x, int y, int w, int h) {
// Repaints are posted from updateClient now...
}
// Invoke a paint() method call on the target, after clearing the
// damaged area.
void handleExpose(int x, int y, int w, int h) {
// Bug ID 4081126 & 4129709 - can't do the clearRect() here,
// since it interferes with the java thread working in the
// same window on multi-processor NT machines.
postPaintIfNecessary(x, y, w, h);
}
/* Invoke a paint() method call on the target, without clearing the
* damaged area. This is normally called by a native control after
* it has painted itself.
*
* NOTE: This is called on the privileged toolkit thread. Do not
* call directly into user code using this thread!
*/
public void handlePaint(int x, int y, int w, int h) {
postPaintIfNecessary(x, y, w, h);
}
private void postPaintIfNecessary(int x, int y, int w, int h) {
if ( !AWTAccessor.getComponentAccessor().getIgnoreRepaint( (Component) target) ) {
PaintEvent event = PaintEventDispatcher.getPaintEventDispatcher().
createPaintEvent((Component)target, x, y, w, h);
if (event != null) {
postEvent(event);
}
}
}
/*
* Post an event. Queue it for execution by the callback thread.
*/
void postEvent(AWTEvent event) {
preprocessPostEvent(event);
WToolkit.postEvent(WToolkit.targetToAppContext(target), event);
}
void preprocessPostEvent(AWTEvent event) {}
// Routines to support deferred window positioning.
public void beginLayout() {
// Skip all painting till endLayout
isLayouting = true;
}
public void endLayout() {
if(!paintArea.isEmpty() && !paintPending &&
!((Component)target).getIgnoreRepaint()) {
// if not waiting for native painting repaint damaged area
postEvent(new PaintEvent((Component)target, PaintEvent.PAINT,
new Rectangle()));
}
isLayouting = false;
}
public native void beginValidate();
public native void endValidate();
/**
* DEPRECATED
*/
public Dimension minimumSize() {
return getMinimumSize();
}
/**
* DEPRECATED
*/
public Dimension preferredSize() {
return getPreferredSize();
}
/**
* register a DropTarget with this native peer
*/
public synchronized void addDropTarget(DropTarget dt) {
if (nDropTargets == 0) {
nativeDropTargetContext = addNativeDropTarget();
}
nDropTargets++;
}
/**
* unregister a DropTarget with this native peer
*/
public synchronized void removeDropTarget(DropTarget dt) {
nDropTargets--;
if (nDropTargets == 0) {
removeNativeDropTarget();
nativeDropTargetContext = 0;
}
}
/**
* add the native peer's AwtDropTarget COM object
* @return reference to AwtDropTarget object
*/
native long addNativeDropTarget();
/**
* remove the native peer's AwtDropTarget COM object
*/
native void removeNativeDropTarget();
native boolean nativeHandlesWheelScrolling();
public boolean handlesWheelScrolling() {
// should this be cached?
return nativeHandlesWheelScrolling();
}
// Returns true if we are inside begin/endLayout and
// are waiting for native painting
public boolean isPaintPending() {
return paintPending && isLayouting;
}
/**
* The following multibuffering-related methods delegate to our
* associated GraphicsConfig (Win or WGL) to handle the appropriate
* native windowing system specific actions.
*/
@Override
public void createBuffers(int numBuffers, BufferCapabilities caps)
throws AWTException
{
Win32GraphicsConfig gc =
(Win32GraphicsConfig)getGraphicsConfiguration();
gc.assertOperationSupported((Component)target, numBuffers, caps);
// Re-create the primary surface with the new number of back buffers
try {
replaceSurfaceData(numBuffers - 1, caps);
} catch (InvalidPipeException e) {
throw new AWTException(e.getMessage());
}
}
@Override
public void destroyBuffers() {
replaceSurfaceData(0, null);
}
@Override
public void flip(int x1, int y1, int x2, int y2,
BufferCapabilities.FlipContents flipAction)
{
VolatileImage backBuffer = this.backBuffer;
if (backBuffer == null) {
throw new IllegalStateException("Buffers have not been created");
}
Win32GraphicsConfig gc =
(Win32GraphicsConfig)getGraphicsConfiguration();
gc.flip(this, (Component)target, backBuffer, x1, y1, x2, y2, flipAction);
}
@Override
public synchronized Image getBackBuffer() {
Image backBuffer = this.backBuffer;
if (backBuffer == null) {
throw new IllegalStateException("Buffers have not been created");
}
return backBuffer;
}
public BufferCapabilities getBackBufferCaps() {
return backBufferCaps;
}
public int getBackBuffersNum() {
return numBackBuffers;
}
/* override and return false on components that DO NOT require
a clearRect() before painting (i.e. native components) */
public boolean shouldClearRectBeforePaint() {
return true;
}
native void pSetParent(ComponentPeer newNativeParent);
/**
* @see java.awt.peer.ComponentPeer#reparent
*/
public void reparent(ContainerPeer newNativeParent) {
pSetParent(newNativeParent);
}
/**
* @see java.awt.peer.ComponentPeer#isReparentSupported
*/
public boolean isReparentSupported() {
return true;
}
public void setBoundsOperation(int operation) {
}
/**
* Returns whether this component is capable of being hw accelerated.
* More specifically, whether rendering to this component or a
* BufferStrategy's back-buffer for this component can be hw accelerated.
*
* Conditions which could prevent hw acceleration include the toplevel
* window containing this component being
* {@link GraphicsDevice.WindowTranslucency#PERPIXEL_TRANSLUCENT
* PERPIXEL_TRANSLUCENT}.
*
* @return {@code true} if this component is capable of being hw
* accelerated, {@code false} otherwise
* @see GraphicsDevice.WindowTranslucency#PERPIXEL_TRANSLUCENT
*/
public boolean isAccelCapable() {
boolean isTranslucent =
SunToolkit.isContainingTopLevelTranslucent((Component)target);
// D3D/OGL and translucent windows interacted poorly in Windows XP;
// these problems are no longer present in Vista
return !isTranslucent || Win32GraphicsEnvironment.isVistaOS();
}
native void setRectangularShape(int lox, int loy, int hix, int hiy,
Region region);
// REMIND: Temp workaround for issues with using HW acceleration
// in the browser on Vista when DWM is enabled.
// @return true if the toplevel container is not an EmbeddedFrame or
// if this EmbeddedFrame is acceleration capable, false otherwise
private static final boolean isContainingTopLevelAccelCapable(Component c) {
while (c != null && !(c instanceof WEmbeddedFrame)) {
c = c.getParent();
}
if (c == null) {
return true;
}
return ((WEmbeddedFramePeer)c.getPeer()).isAccelCapable();
}
/**
* Applies the shape to the native component window.
* @since 1.7
*/
public void applyShape(Region shape) {
if (shapeLog.isLoggable(PlatformLogger.FINER)) {
shapeLog.finer(
"*** INFO: Setting shape: PEER: " + this
+ "; TARGET: " + target
+ "; SHAPE: " + shape);
}
if (shape != null) {
setRectangularShape(shape.getLoX(), shape.getLoY(), shape.getHiX(), shape.getHiY(),
(shape.isRectangular() ? null : shape));
} else {
setRectangularShape(0, 0, 0, 0, null);
}
}
/**
* Lowers this component at the bottom of the above component. If the above parameter
* is null then the method places this component at the top of the Z-order.
*/
public void setZOrder(ComponentPeer above) {
long aboveHWND = (above != null) ? ((WComponentPeer)above).getHWnd() : 0;
setZOrder(aboveHWND);
}
private native void setZOrder(long above);
}