7198229: Painting during resizing of the frame should be more smooth
Reviewed-by: anthony, denis, skovatch
diff --git a/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java
index 4b9123d..72a5d0c 100644
--- a/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java
+++ b/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java
@@ -622,29 +622,21 @@
}
/**
- * Called by the delegate when any part of the window should be repainted.
+ * Called by the {@code PlatformWindow} when any part of the window should
+ * be repainted.
*/
- public void notifyExpose(final int x, final int y, final int w, final int h) {
- // TODO: there's a serious problem with Swing here: it handles
- // the exposition internally, so SwingPaintEventDispatcher always
- // return null from createPaintEvent(). However, we flush the
- // back buffer here unconditionally, so some flickering may appear.
- // A possible solution is to split postPaintEvent() into two parts,
- // and override that part which is only called after if
- // createPaintEvent() returned non-null value and flush the buffer
- // from the overridden method
- flushOnscreenGraphics();
- repaintPeer(new Rectangle(x, y, w, h));
+ public final void notifyExpose(final Rectangle r) {
+ repaintPeer(r);
}
/**
- * Called by the delegate when this window is moved/resized by user.
- * There's no notifyReshape() in LWComponentPeer as the only
+ * Called by the {@code PlatformWindow} when this window is moved/resized by
+ * user. There's no notifyReshape() in LWComponentPeer as the only
* components which could be resized by user are top-level windows.
*/
public final void notifyReshape(int x, int y, int w, int h) {
- boolean moved = false;
- boolean resized = false;
+ final boolean moved;
+ final boolean resized;
synchronized (getStateLock()) {
moved = (x != sysX) || (y != sysY);
resized = (w != sysW) || (h != sysH);
@@ -668,12 +660,13 @@
flushOnscreenGraphics();
}
- // Third, COMPONENT_MOVED/COMPONENT_RESIZED events
+ // Third, COMPONENT_MOVED/COMPONENT_RESIZED/PAINT events
if (moved) {
handleMove(x, y, true);
}
if (resized) {
- handleResize(w, h,true);
+ handleResize(w, h, true);
+ repaintPeer();
}
}
diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java
index ebae30c..ea6e03a 100644
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java
@@ -244,12 +244,11 @@
event.getCharactersIgnoringModifiers(), event.getKeyCode(), true);
}
+ /**
+ * Called by the native delegate in layer backed view mode or in the simple
+ * NSView mode. See NSView.drawRect().
+ */
private void deliverWindowDidExposeEvent() {
- Rectangle r = peer.getBounds();
- peer.notifyExpose(0, 0, r.width, r.height);
- }
-
- private void deliverWindowDidExposeEvent(float x, float y, float w, float h) {
- peer.notifyExpose((int)x, (int)y, (int)w, (int)h);
+ peer.notifyExpose(peer.getSize());
}
}
diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java
index d00071f..f357a61 100644
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java
@@ -46,7 +46,7 @@
import com.apple.laf.ClientPropertyApplicator.Property;
import com.sun.awt.AWTUtilities;
-public class CPlatformWindow extends CFRetainedResource implements PlatformWindow {
+public final class CPlatformWindow extends CFRetainedResource implements PlatformWindow {
private native long nativeCreateNSWindow(long nsViewPtr, long styleBits, double x, double y, double w, double h);
private static native void nativeSetNSWindowStyleBits(long nsWindowPtr, int mask, int data);
private static native void nativeSetNSWindowMenuBar(long nsWindowPtr, long menuBarPtr);
@@ -195,7 +195,7 @@
// In order to keep it up-to-date we will update them on
// 1) setting native bounds via nativeSetBounds() call
// 2) getting notification from the native level via deliverMoveResizeEvent()
- private Rectangle nativeBounds;
+ private Rectangle nativeBounds = new Rectangle(0, 0, 0, 0);
private volatile boolean isFullScreenMode = false;
private Window target;
@@ -869,6 +869,12 @@
}
}
+ private void flushBuffers() {
+ if (isVisible() && !nativeBounds.isEmpty()) {
+ LWCToolkit.getLWCToolkit().flushPendingEventsOnAppkit(target);
+ }
+ }
+
/*************************************************************
* Callbacks from the AWTWindow and AWTView objc classes.
*************************************************************/
@@ -886,10 +892,16 @@
// move/resize notifications contain a bounds smaller than
// the whole screen and therefore we ignore the native notifications
// and the content view itself creates correct synthetic notifications
- if (isFullScreenMode) return;
+ if (isFullScreenMode) {
+ return;
+ }
+ final Rectangle oldB = nativeBounds;
nativeBounds = new Rectangle(x, y, width, height);
peer.notifyReshape(x, y, width, height);
+ if (!oldB.getSize().equals(nativeBounds.getSize()) ) {
+ flushBuffers();
+ }
//TODO validateSurface already called from notifyReshape
validateSurface();
}
diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java
index 97d4c32..65e1ff0 100644
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java
@@ -160,6 +160,10 @@
});
}
+ public static LWCToolkit getLWCToolkit() {
+ return (LWCToolkit)Toolkit.getDefaultToolkit();
+ }
+
@Override
protected PlatformWindow createPlatformWindow(PeerType peerType) {
if (peerType == PeerType.EMBEDDED_FRAME) {
@@ -420,7 +424,6 @@
return BUTTONS;
}
-
@Override
public boolean isTraySupported() {
return true;
@@ -502,6 +505,22 @@
synchronized(ret) { return ret[0]; }
}
+ /**
+ * Just a wrapper for LWCToolkit.invokeAndWait. Posts an empty event to the
+ * appropriate event queue and waits for it to finish.
+ */
+ public static void flushPendingEventsOnAppkit(final Component component) {
+ try {
+ invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ }
+ }, component);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
// Kicks an event over to the appropriate eventqueue and waits for it to finish
// To avoid deadlocking, we manually run the NSRunLoop while waiting
// Any selector invoked using ThreadUtilities performOnMainThread will be processed in doAWTRunLoop
diff --git a/jdk/src/macosx/native/sun/awt/AWTView.m b/jdk/src/macosx/native/sun/awt/AWTView.m
index c6bc108..454f0c6 100644
--- a/jdk/src/macosx/native/sun/awt/AWTView.m
+++ b/jdk/src/macosx/native/sun/awt/AWTView.m
@@ -85,11 +85,14 @@
if (windowLayer != nil) {
self.cglLayer = windowLayer;
+ //Layer hosting view
+ [self setLayer: cglLayer];
[self setWantsLayer: YES];
- [self.layer addSublayer: (CALayer *)cglLayer];
- [self setLayerContentsRedrawPolicy: NSViewLayerContentsRedrawDuringViewResize];
- [self setLayerContentsPlacement: NSViewLayerContentsPlacementTopLeft];
- [self setAutoresizingMask: NSViewHeightSizable | NSViewWidthSizable];
+ //Layer backed view
+ //[self.layer addSublayer: (CALayer *)cglLayer];
+ //[self setLayerContentsRedrawPolicy: NSViewLayerContentsRedrawDuringViewResize];
+ //[self setLayerContentsPlacement: NSViewLayerContentsPlacementTopLeft];
+ //[self setAutoresizingMask: NSViewHeightSizable | NSViewWidthSizable];
#ifdef REMOTELAYER
CGLLayer *parentLayer = (CGLLayer*)self.cglLayer;
diff --git a/jdk/src/macosx/native/sun/java2d/opengl/CGLLayer.m b/jdk/src/macosx/native/sun/java2d/opengl/CGLLayer.m
index 978fbe2..6683898 100644
--- a/jdk/src/macosx/native/sun/java2d/opengl/CGLLayer.m
+++ b/jdk/src/macosx/native/sun/java2d/opengl/CGLLayer.m
@@ -57,9 +57,10 @@
// NOTE: async=YES means that the layer is re-cached periodically
self.asynchronous = FALSE;
- self.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
self.contentsGravity = kCAGravityTopLeft;
- self.needsDisplayOnBoundsChange = YES;
+ //Layer backed view
+ //self.needsDisplayOnBoundsChange = YES;
+ //self.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
textureID = 0; // texture will be created by rendering pipe
target = 0;
@@ -109,6 +110,10 @@
glDisable(target);
}
+-(BOOL)canDrawInCGLContext:(CGLContextObj)glContext pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp{
+ return textureID == 0 ? NO : YES;
+}
+
-(void)drawInCGLContext:(CGLContextObj)glContext pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp
{
AWT_ASSERT_APPKIT_THREAD;