Skip to content

Commit 592d745

Browse files
committedAug 30, 2019
Merge
2 parents a0b4b14 + a1aa38a commit 592d745

File tree

10 files changed

+330
-17
lines changed

10 files changed

+330
-17
lines changed
 

‎.hgtags

+2
Original file line numberDiff line numberDiff line change
@@ -539,3 +539,5 @@ c8cde739aa8e3745e5c7686661d196f9d980a8c7 13+7
539539
c91a28ed4845c265cd3d3340755e018da5e10698 13+10
540540
030420e44e748f392b07f6f9c5ee0ae4b582fe56 13+11
541541
e21afe5aabed9f81fdcc7fe061536e2c13d19456 13+12
542+
dde636c6219c01c7d640f04acd92a344d6f9f421 13+13
543+
6425e1f958fcad3bc17299880c167306273207dd 13+14

‎modules/javafx.controls/src/main/java/com/sun/javafx/scene/control/skin/Utils.java

+8
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
import javafx.scene.text.HitInfo;
6161

6262
import java.text.Bidi;
63+
import java.util.List;
6364
import java.util.Locale;
6465
import java.util.function.Consumer;
6566

@@ -693,6 +694,10 @@ public static void addMnemonics(ContextMenu popup, Scene scene) {
693694
}
694695

695696
public static void addMnemonics(ContextMenu popup, Scene scene, boolean initialState) {
697+
addMnemonics(popup, scene, initialState, null);
698+
}
699+
700+
public static void addMnemonics(ContextMenu popup, Scene scene, boolean initialState, List<Mnemonic> into) {
696701

697702
if (!com.sun.javafx.PlatformUtil.isMac()) {
698703

@@ -713,6 +718,9 @@ public static void addMnemonics(ContextMenu popup, Scene scene, boolean initialS
713718
Mnemonic myMnemonic = new Mnemonic(cmContent.getLabelAt(i), mnemonicKeyCombo);
714719
scene.addMnemonic(myMnemonic);
715720
NodeHelper.setShowMnemonics(cmContent.getLabelAt(i), initialState);
721+
if (into != null) {
722+
into.add(myMnemonic);
723+
}
716724
}
717725
}
718726
}

‎modules/javafx.controls/src/main/java/javafx/scene/control/skin/MenuButtonSkinBase.java

+12-2
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,21 @@
3434
import javafx.collections.ListChangeListener;
3535
import javafx.event.ActionEvent;
3636
import javafx.scene.Node;
37+
import javafx.scene.Scene;
3738
import javafx.scene.control.ContextMenu;
3839
import javafx.scene.control.MenuButton;
3940
import javafx.scene.control.MenuItem;
4041
import javafx.scene.control.Skin;
4142
import javafx.scene.control.SkinBase;
43+
import javafx.scene.input.Mnemonic;
4244
import javafx.scene.input.MouseEvent;
4345
import javafx.scene.layout.Region;
4446
import javafx.scene.layout.StackPane;
4547
import com.sun.javafx.scene.control.behavior.MenuButtonBehaviorBase;
4648

49+
import java.util.ArrayList;
50+
import java.util.List;
51+
4752
/**
4853
* Base class for MenuButtonSkin and SplitMenuButtonSkin. It consists of the
4954
* label, the arrowButton with its arrow shape, and the popup.
@@ -168,6 +173,7 @@ public MenuButtonSkinBase(final C control) {
168173
label.setMnemonicParsing(getSkinnable().isMnemonicParsing());
169174
getSkinnable().requestLayout();
170175
});
176+
List<Mnemonic> mnemonics = new ArrayList<>();
171177
registerChangeListener(popup.showingProperty(), e -> {
172178
if (!popup.isShowing() && getSkinnable().isShowing()) {
173179
// Popup was dismissed. Maybe user clicked outside or typed ESCAPE.
@@ -176,7 +182,8 @@ public MenuButtonSkinBase(final C control) {
176182
}
177183

178184
if (popup.isShowing()) {
179-
Utils.addMnemonics(popup, getSkinnable().getScene(), NodeHelper.isShowMnemonics(getSkinnable()));
185+
boolean showMnemonics = NodeHelper.isShowMnemonics(getSkinnable());
186+
Utils.addMnemonics(popup, getSkinnable().getScene(), showMnemonics, mnemonics);
180187
} else {
181188
// we wrap this in a runLater so that mnemonics are not removed
182189
// before all key events are fired (because KEY_PRESSED might have
@@ -185,7 +192,10 @@ public MenuButtonSkinBase(final C control) {
185192
// through the mnemonics code (especially in case they should be
186193
// consumed to prevent them being used elsewhere).
187194
// See JBS-8090026 for more detail.
188-
Platform.runLater(() -> Utils.removeMnemonics(popup, getSkinnable().getScene()));
195+
Scene scene = getSkinnable().getScene();
196+
List<Mnemonic> mnemonicsToRemove = new ArrayList<>(mnemonics);
197+
mnemonics.clear();
198+
Platform.runLater(() -> mnemonicsToRemove.forEach(scene::removeMnemonic));
189199
}
190200
});
191201
}

‎modules/javafx.graphics/src/main/java/com/sun/javafx/tk/quantum/WindowStage.java

+1-6
Original file line numberDiff line numberDiff line change
@@ -895,12 +895,7 @@ protected void setPlatformEnabled(boolean enabled) {
895895
if (platformWindow != null) {
896896
platformWindow.setEnabled(enabled);
897897
}
898-
if (enabled) {
899-
// Check if window is really enabled - to handle nested case
900-
if (platformWindow != null && platformWindow.isEnabled()) {
901-
requestToFront();
902-
}
903-
} else {
898+
if (!enabled) {
904899
removeActiveWindow(this);
905900
}
906901
}

‎modules/javafx.graphics/src/main/java/javafx/scene/image/PixelBuffer.java

+9-7
Original file line numberDiff line numberDiff line change
@@ -189,15 +189,17 @@ public void updateBuffer(Callback<PixelBuffer<T>, Rectangle2D> callback) {
189189
Toolkit.getToolkit().checkFxUserThread();
190190
Objects.requireNonNull(callback, "callback must not be null.");
191191
Rectangle2D rect2D = callback.call(this);
192-
Rectangle rect = null;
193192
if (rect2D != null) {
194-
int x1 = (int) Math.floor(rect2D.getMinX());
195-
int y1 = (int) Math.floor(rect2D.getMinY());
196-
int x2 = (int) Math.ceil(rect2D.getMaxX());
197-
int y2 = (int) Math.ceil(rect2D.getMaxY());
198-
rect = new Rectangle(x1, y1, x2 - x1, y2 - y1);
193+
if (rect2D.getWidth() > 0 && rect2D.getHeight() > 0) {
194+
int x1 = (int) Math.floor(rect2D.getMinX());
195+
int y1 = (int) Math.floor(rect2D.getMinY());
196+
int x2 = (int) Math.ceil(rect2D.getMaxX());
197+
int y2 = (int) Math.ceil(rect2D.getMaxY());
198+
bufferDirty(new Rectangle(x1, y1, x2 - x1, y2 - y1));
199+
}
200+
} else {
201+
bufferDirty(null);
199202
}
200-
bufferDirty(rect);
201203
}
202204

203205
private void bufferDirty(Rectangle rect) {

‎modules/javafx.graphics/src/test/java/test/javafx/scene/image/PixelBufferTest.java

+11
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,17 @@ public void testUpdatePixelBufferPartialBufferUpdate() {
133133
pixelBuffer.updateBuffer(callback);
134134
}
135135

136+
@Test
137+
public void testUpdatePixelBufferEmptyBufferUpdate() {
138+
// This test verifies that an empty dirty region does not cause any exception
139+
PixelBuffer<ByteBuffer> pixelBuffer = new PixelBuffer<>(WIDTH, HEIGHT, BYTE_BUFFER, BYTE_BGRA_PRE_PF);
140+
Callback<PixelBuffer<ByteBuffer>, Rectangle2D> callback = pixBuf -> {
141+
// Assuming no pixels were modified.
142+
return Rectangle2D.EMPTY;
143+
};
144+
pixelBuffer.updateBuffer(callback);
145+
}
146+
136147
@Test
137148
public void testUpdatePixelBufferCallbackNull() {
138149
try {

‎modules/javafx.web/src/main/native/Source/WebKitLegacy/java/WebCoreSupport/WebPage.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "EditorClientJava.h"
3939
#include "FrameLoaderClientJava.h"
4040
#include "InspectorClientJava.h"
41+
#include "PageStorageSessionProvider.h"
4142
#include "PlatformStrategiesJava.h"
4243
#include "ProgressTrackerClientJava.h"
4344
#include "VisitedLinkStoreJava.h"
@@ -59,6 +60,7 @@
5960
#include <WebCore/Chrome.h>
6061
#include <WebCore/ContextMenu.h>
6162
#include <WebCore/ContextMenuController.h>
63+
#include <WebCore/CookieJar.h>
6264
#include <WebCore/DeprecatedGlobalSettings.h>
6365
#include <WebCore/Document.h>
6466
#include <WebCore/DragController.h>
@@ -875,7 +877,8 @@ JNIEXPORT jlong JNICALL Java_com_sun_webkit_WebPage_twkCreatePage
875877
//utaTODO: history agent implementation
876878

877879
auto pc = pageConfigurationWithEmptyClients();
878-
880+
auto pageStorageSessionProvider = PageStorageSessionProvider::create();
881+
pc.cookieJar = CookieJar::create(pageStorageSessionProvider.copyRef());
879882
pc.chromeClient = new ChromeClientJava(jlself);
880883
pc.contextMenuClient = new ContextMenuClientJava(jlself);
881884
pc.editorClient = makeUniqueRef<EditorClientJava>(jlself);
@@ -889,10 +892,10 @@ JNIEXPORT jlong JNICALL Java_com_sun_webkit_WebPage_twkCreatePage
889892
pc.progressTrackerClient = new ProgressTrackerClientJava(jlself);
890893

891894
pc.backForwardClient = BackForwardList::create();
892-
893895
auto page = std::make_unique<Page>(WTFMove(pc));
894896
// Associate PageSupplementJava instance which has WebPage java object.
895897
page->provideSupplement(PageSupplementJava::supplementName(), std::make_unique<PageSupplementJava>(self));
898+
pageStorageSessionProvider->setPage(*page);
896899
#if ENABLE(GEOLOCATION)
897900
WebCore::provideGeolocationTo(page.get(), *new GeolocationClientMock());
898901
#endif

‎modules/javafx.web/src/test/java/test/javafx/scene/web/MiscellaneousTest.java

+10
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,16 @@ public void call(long createdTime, long interval, int index) {
227227
}
228228
}
229229

230+
@Test public void testCookieEnabled() {
231+
final WebEngine webEngine = createWebEngine();
232+
submit(() -> {
233+
final JSObject window = (JSObject) webEngine.executeScript("window");
234+
assertNotNull(window);
235+
webEngine.executeScript("var cookieEnabled = navigator.cookieEnabled");
236+
assertTrue((Boolean)window.getMember("cookieEnabled"));
237+
});
238+
}
239+
230240
// This test case will be removed once we implement Websql feature.
231241
@Test public void testWebSQLUndefined() {
232242
final WebEngine webEngine = createWebEngine();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/*
2+
* Copyright (c) 2019, 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+
26+
package test.javafx.scene.control;
27+
28+
import javafx.application.Application;
29+
import javafx.application.Platform;
30+
import javafx.scene.Scene;
31+
import javafx.scene.control.Menu;
32+
import javafx.scene.control.MenuBar;
33+
import javafx.scene.control.MenuItem;
34+
import javafx.stage.Stage;
35+
import javafx.stage.WindowEvent;
36+
import org.junit.AfterClass;
37+
import org.junit.Assert;
38+
import org.junit.BeforeClass;
39+
import org.junit.Test;
40+
import test.util.Util;
41+
42+
import java.io.ByteArrayOutputStream;
43+
import java.io.PrintStream;
44+
import java.util.concurrent.CountDownLatch;
45+
import java.util.concurrent.TimeUnit;
46+
47+
public class MenuButtonSkinBaseNPETest {
48+
static CountDownLatch startupLatch;
49+
static Menu menu;
50+
static MenuBar menuBar;
51+
52+
public static void main(String[] args) throws Exception {
53+
initFX();
54+
try {
55+
var test = new MenuButtonSkinBaseNPETest();
56+
test.testMenuButtonNPE();
57+
} catch (Throwable e) {
58+
e.printStackTrace();
59+
} finally {
60+
tearDown();
61+
}
62+
}
63+
64+
@Test
65+
public void testMenuButtonNPE() throws Exception {
66+
PrintStream defaultErrorStream = System.err;
67+
ByteArrayOutputStream out = new ByteArrayOutputStream();
68+
System.setErr(new PrintStream(out, true));
69+
Thread.sleep(1000);
70+
Util.runAndWait(() -> {
71+
menu.hide();
72+
menuBar.getMenus().clear();
73+
});
74+
Thread.sleep(100);
75+
System.setErr(defaultErrorStream);
76+
Assert.assertEquals("No error should be thrown", "", out.toString());
77+
}
78+
79+
public static class TestApp extends Application {
80+
81+
@Override
82+
public void start(Stage primaryStage) throws Exception {
83+
menu = new Menu("Menu", null, new MenuItem("Press '_a'"));
84+
menuBar = new MenuBar(menu);
85+
Scene scene = new Scene(menuBar);
86+
primaryStage.addEventHandler(WindowEvent.WINDOW_SHOWN, event -> startupLatch.countDown());
87+
primaryStage.setScene(scene);
88+
primaryStage.show();
89+
menu.show();
90+
}
91+
}
92+
93+
@BeforeClass
94+
public static void initFX() throws Exception {
95+
startupLatch = new CountDownLatch(1);
96+
new Thread(() -> Application.launch(TestApp.class, (String[])null)).start();
97+
Assert.assertTrue("Timeout waiting for FX runtime to start",
98+
startupLatch.await(15, TimeUnit.SECONDS));
99+
}
100+
101+
@AfterClass
102+
public static void tearDown() {
103+
Platform.exit();
104+
}
105+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
/*
2+
* Copyright (c) 2019, 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+
26+
package test.javafx.scene.image;
27+
28+
import java.awt.Color;
29+
import java.awt.Graphics2D;
30+
import java.awt.image.BufferedImage;
31+
import java.awt.image.DataBuffer;
32+
import java.awt.image.DataBufferInt;
33+
import java.io.ByteArrayOutputStream;
34+
import java.io.PrintStream;
35+
import java.nio.IntBuffer;
36+
import java.util.concurrent.CountDownLatch;
37+
import java.util.concurrent.TimeUnit;
38+
39+
import org.junit.AfterClass;
40+
import org.junit.Assert;
41+
import org.junit.Before;
42+
import org.junit.BeforeClass;
43+
import org.junit.Test;
44+
45+
import javafx.application.Application;
46+
import javafx.application.Platform;
47+
import javafx.geometry.Rectangle2D;
48+
import javafx.scene.Scene;
49+
import javafx.scene.image.ImageView;
50+
import javafx.scene.image.PixelBuffer;
51+
import javafx.scene.image.PixelFormat;
52+
import javafx.scene.image.WritableImage;
53+
import javafx.scene.layout.StackPane;
54+
import javafx.stage.Stage;
55+
import javafx.stage.WindowEvent;
56+
import test.util.Util;
57+
58+
/**
59+
* This test verifies the fix for JDK-8229890.
60+
* This test ensures that the callback provided to the {@link javafx.scene.image.PixelBuffer#updateBuffer()}
61+
* method may return {@link javafx.geometry.Rectangle2D.Empty} in order to
62+
* indicate that no update is necessary and no exception is thrown.
63+
*/
64+
public class WritableImageFromBufferTest {
65+
66+
static CountDownLatch startupLatch;
67+
68+
private static final int IMG_WIDTH = 600;
69+
private static final int IMG_HEIGHT = 400;
70+
71+
private PixelBuffer<IntBuffer> pixelBuffer;
72+
private Graphics2D g2d;
73+
private WritableImage fxImage;
74+
75+
private static Scene scene;
76+
77+
public static class TestApp extends Application {
78+
@Override
79+
public void start(Stage primaryStage) throws Exception {
80+
scene = new Scene(new StackPane(), IMG_WIDTH, IMG_HEIGHT);
81+
primaryStage.addEventHandler(WindowEvent.WINDOW_SHOWN, event -> startupLatch.countDown());
82+
primaryStage.setScene(scene);
83+
primaryStage.show();
84+
}
85+
}
86+
87+
@Before
88+
public void setUp() throws Exception {
89+
BufferedImage awtImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, BufferedImage.TYPE_INT_ARGB_PRE);
90+
g2d = (Graphics2D) awtImage.getGraphics();
91+
92+
DataBuffer db = awtImage.getRaster().getDataBuffer();
93+
DataBufferInt dbi = (DataBufferInt) db;
94+
int[] rawInts = dbi.getData();
95+
IntBuffer ib = IntBuffer.wrap(rawInts);
96+
97+
PixelFormat<IntBuffer> pixelFormat = PixelFormat.getIntArgbPreInstance();
98+
pixelBuffer = new PixelBuffer<>(IMG_WIDTH, IMG_HEIGHT, ib, pixelFormat);
99+
fxImage = new WritableImage(pixelBuffer);
100+
}
101+
102+
@Test
103+
public void test() throws InterruptedException {
104+
PrintStream defaultErrorStream = System.err;
105+
ByteArrayOutputStream out = new ByteArrayOutputStream();
106+
System.setErr(new PrintStream(out, true));
107+
108+
Thread.sleep(1000);
109+
Util.runAndWait(() -> {
110+
StackPane root = (StackPane)scene.getRoot();
111+
root.getChildren().add(new ImageView(fxImage));
112+
requestFullUpdate();
113+
});
114+
Thread.sleep(100);
115+
Util.runAndWait(() -> {
116+
requestEmptyUpdate(); // This will fail without the fix.
117+
});
118+
Thread.sleep(100);
119+
Util.runAndWait(() -> {
120+
requestPartialUpdate();
121+
});
122+
Thread.sleep(100);
123+
124+
System.setErr(defaultErrorStream);
125+
Assert.assertEquals("No error should be thrown", "", out.toString());
126+
}
127+
128+
private void requestFullUpdate() {
129+
// This call should work before and after the fix.
130+
pixelBuffer.updateBuffer(pb -> {
131+
g2d.setBackground(Color.decode("#FF0000"));
132+
g2d.clearRect(0, 0, IMG_WIDTH, IMG_HEIGHT);
133+
return null;
134+
});
135+
}
136+
137+
private void requestEmptyUpdate() {
138+
// This call should fail without the fix and pass after the fix.
139+
pixelBuffer.updateBuffer(pb -> {
140+
// Nothing to do.
141+
return Rectangle2D.EMPTY;
142+
});
143+
}
144+
145+
private void requestPartialUpdate() {
146+
// This call should work before and after the fix.
147+
pixelBuffer.updateBuffer(pb -> {
148+
g2d.setBackground(Color.decode("#0000FF"));
149+
g2d.clearRect(0, 0, IMG_WIDTH / 2, IMG_HEIGHT);
150+
return new Rectangle2D(0, 0, IMG_WIDTH / 2, IMG_HEIGHT);
151+
});
152+
}
153+
154+
@BeforeClass
155+
public static void initFX() throws Exception {
156+
startupLatch = new CountDownLatch(1);
157+
new Thread(() -> Application.launch(TestApp.class, (String[])null)).start();
158+
Assert.assertTrue("Timeout waiting for FX runtime to start",
159+
startupLatch.await(15, TimeUnit.SECONDS));
160+
}
161+
162+
@AfterClass
163+
public static void tearDown() {
164+
Platform.exit();
165+
}
166+
167+
}

0 commit comments

Comments
 (0)
Please sign in to comment.