Skip to content

Commit 7242348

Browse files
committed
[UnifiedPDF] [macOS] Switching from continuous to discrete mode will display the page(s) that are at the top of the window, even if barely visible
https://bugs.webkit.org/show_bug.cgi?id=286193 rdar://137608841 Reviewed by Tim Horton. When switching between display modes, we need to decide an anchor point to maintain the PDF document's view position post factum. We have been using the top left (plugin space) as said anchor point, but when switching out from a continuous display mode, the anchor point often happens to be in the sliver of the previous page showing in the plugin space, so after the transition, we end up landing on a previous page. This patch addresses this logic error by instead adopting Preview's (and PDFLayerController's) behavior of anchoring around the origin (top left) of the page visible in the center of the plugin. To facilitate these changes, we introduce a couple of helper methods, namely `anchorPointForDocument()` and `pageIndexForCurrentView()`. These helpers allow both the presentation controller instances to use shared logic for `pdfPositionForCurrentView()`, so we devirtualize it. Note that we don't use this new anchoring behavior for layout updates with autoscaling behavior activated, since we still want to unconditionally anchor around the plugin's top-left in that use case. * LayoutTests/pdf/two-pages-continuous-to-discrete-expected.html: Address some flakiness. * Source/WebKit/WebProcess/Plugins/PDF/UnifiedPDF/PDFDiscretePresentationController.h: * Source/WebKit/WebProcess/Plugins/PDF/UnifiedPDF/PDFDiscretePresentationController.mm: (WebKit::PDFDiscretePresentationController::pageIndexForCurrentView const): (WebKit::PDFDiscretePresentationController::pdfPositionForCurrentView const): Deleted. * Source/WebKit/WebProcess/Plugins/PDF/UnifiedPDF/PDFPresentationController.h: * Source/WebKit/WebProcess/Plugins/PDF/UnifiedPDF/PDFPresentationController.mm: (WebKit::PDFPresentationController::pdfPositionForCurrentView const): (WebKit::PDFPresentationController::anchorPointForDocument const): * Source/WebKit/WebProcess/Plugins/PDF/UnifiedPDF/PDFScrollingPresentationController.h: * Source/WebKit/WebProcess/Plugins/PDF/UnifiedPDF/PDFScrollingPresentationController.mm: (WebKit::PDFScrollingPresentationController::pageIndexForCurrentView const): (WebKit::PDFScrollingPresentationController::pdfPositionForCurrentView const): Deleted. * Source/WebKit/WebProcess/Plugins/PDF/UnifiedPDF/UnifiedPDFPlugin.mm: (WebKit::UnifiedPDFPlugin::updateLayout): (WebKit::UnifiedPDFPlugin::setDisplayModeAndUpdateLayout): * Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: * Tools/TestWebKitAPI/Tests/WebKitCocoa/UnifiedPDFTests.mm: (TestWebKitAPI::UnifiedPDFWithKeyboardScrolling::synchronouslyLoadPDFDocument): (TestWebKitAPI::UnifiedPDFWithKeyboardScrolling::scrollDown): (TestWebKitAPI::UnifiedPDFWithKeyboardScrolling::scrollRight): (TestWebKitAPI::UnifiedPDFWithKeyboardScrolling::pressKey): (TestWebKitAPI::TEST_F(UnifiedPDFWithKeyboardScrolling, KeyboardScrollingInSinglePageMode)): (TestWebKitAPI::TEST_F(UnifiedPDFWithKeyboardScrolling, DisplayModeTransitionLandingPage)): Introduce a UnifiedPDFWithKeyboardScrolling text fixture class, which takes the keyboard scrolling technique from the existing API test - KeyboardScrollingInSinglePageMode - and exposes it as convenient `scroll[Down|Right]()` utilities. This fixture class is used to introduce a new API test `DisplayModeTransitionLandingPage`. * Tools/TestWebKitAPI/Tests/WebKitCocoa/multiple-pages-colored.pdf: Added. Canonical link: https://commits.webkit.org/289212@main
1 parent a77d7d4 commit 7242348

11 files changed

+125
-58
lines changed

LayoutTests/pdf/two-pages-continuous-to-discrete-expected.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
testRunner.waitUntilDone();
1515
window.internals.registerPDFTest(async () => {
1616
internals.setPDFDisplayModeForTesting(pluginElement, "TwoUpDiscrete");
17-
await UIHelper.renderingUpdate();
17+
await UIHelper.ensureStablePresentationUpdate();
1818
testRunner.notifyDone();
1919
}, pluginElement);
2020
});

Source/WebKit/WebProcess/Plugins/PDF/UnifiedPDF/PDFDiscretePresentationController.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ class PDFDiscretePresentationController final : public PDFPresentationController
144144

145145
void applyWheelEventDelta(FloatSize);
146146

147-
std::optional<VisiblePDFPosition> pdfPositionForCurrentView(bool preservePosition) const override;
147+
std::optional<PDFDocumentLayout::PageIndex> pageIndexForCurrentView(DocumentAnchorPoint) const override;
148148
void restorePDFPosition(const VisiblePDFPosition&) override;
149149

150150
void ensurePageIsVisible(PDFDocumentLayout::PageIndex) override;

Source/WebKit/WebProcess/Plugins/PDF/UnifiedPDF/PDFDiscretePresentationController.mm

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,25 +1354,11 @@ static float elasticDeltaForTimeDelta(float initialPosition, float initialVeloci
13541354

13551355
#pragma mark -
13561356

1357-
auto PDFDiscretePresentationController::pdfPositionForCurrentView(bool preservePosition) const -> std::optional<VisiblePDFPosition>
1357+
std::optional<PDFDocumentLayout::PageIndex> PDFDiscretePresentationController::pageIndexForCurrentView(DocumentAnchorPoint) const
13581358
{
1359-
if (!preservePosition)
1360-
return { };
1361-
1362-
auto& documentLayout = m_plugin->documentLayout();
1363-
if (!documentLayout.hasLaidOutPDFDocument())
1364-
return { };
1365-
1366-
auto visibleRow = this->visibleRow();
1367-
if (!visibleRow)
1368-
return { };
1369-
1370-
auto pageIndex = visibleRow->pages[0];
1371-
auto pageBounds = documentLayout.layoutBoundsForPageAtIndex(pageIndex);
1372-
auto topLeftInDocumentSpace = m_plugin->convertDown(UnifiedPDFPlugin::CoordinateSpace::Plugin, UnifiedPDFPlugin::CoordinateSpace::PDFDocumentLayout, FloatPoint { });
1373-
auto pagePoint = documentLayout.documentToPDFPage(FloatPoint { pageBounds.center().x(), topLeftInDocumentSpace.y() }, pageIndex);
1374-
1375-
return VisiblePDFPosition { pageIndex, pagePoint };
1359+
return visibleRow().transform([](const auto& row) {
1360+
return row.pages[0];
1361+
});
13761362
}
13771363

13781364
void PDFDiscretePresentationController::restorePDFPosition(const VisiblePDFPosition& info)

Source/WebKit/WebProcess/Plugins/PDF/UnifiedPDF/PDFPresentationController.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,9 @@ class PDFPresentationController : public ThreadSafeRefCountedAndCanMakeThreadSaf
9999
WebCore::FloatPoint pagePoint;
100100
};
101101

102-
virtual std::optional<VisiblePDFPosition> pdfPositionForCurrentView(bool preservePosition = true) const = 0;
102+
enum class DocumentAnchorPoint : uint8_t { TopLeft, Center };
103+
std::optional<VisiblePDFPosition> pdfPositionForCurrentView(DocumentAnchorPoint, bool preservePosition = true) const;
104+
virtual std::optional<PDFDocumentLayout::PageIndex> pageIndexForCurrentView(DocumentAnchorPoint) const = 0;
103105
virtual void restorePDFPosition(const VisiblePDFPosition&) = 0;
104106

105107
virtual void ensurePageIsVisible(PDFDocumentLayout::PageIndex) = 0;
@@ -137,9 +139,10 @@ class PDFPresentationController : public ThreadSafeRefCountedAndCanMakeThreadSaf
137139
RefPtr<AsyncPDFRenderer> asyncRendererIfExists() const;
138140
void clearAsyncRenderer();
139141

142+
WebCore::FloatPoint anchorPointForDocument(DocumentAnchorPoint) const;
143+
140144
Ref<UnifiedPDFPlugin> m_plugin;
141145
RefPtr<AsyncPDFRenderer> m_asyncRenderer;
142-
143146
};
144147

145148
} // namespace WebKit

Source/WebKit/WebProcess/Plugins/PDF/UnifiedPDF/PDFPresentationController.mm

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "PDFKitSPI.h"
3434
#include "PDFScrollingPresentationController.h"
3535
#include <WebCore/GraphicsLayer.h>
36+
#include <wtf/CheckedRef.h>
3637
#include <wtf/TZoneMallocInlines.h>
3738

3839
namespace WebKit {
@@ -236,6 +237,44 @@
236237
return { };
237238
}
238239

240+
auto PDFPresentationController::pdfPositionForCurrentView(DocumentAnchorPoint anchorPoint, bool preservePosition) const -> std::optional<VisiblePDFPosition>
241+
{
242+
if (!preservePosition)
243+
return { };
244+
245+
auto& documentLayout = m_plugin->documentLayout();
246+
if (!documentLayout.hasLaidOutPDFDocument())
247+
return { };
248+
249+
auto maybePageIndex = pageIndexForCurrentView(anchorPoint);
250+
if (!maybePageIndex)
251+
return { };
252+
253+
auto pageIndex = *maybePageIndex;
254+
auto pageBounds = documentLayout.layoutBoundsForPageAtIndex(pageIndex);
255+
auto topLeftInDocumentSpace = m_plugin->convertDown(UnifiedPDFPlugin::CoordinateSpace::Plugin, UnifiedPDFPlugin::CoordinateSpace::PDFDocumentLayout, FloatPoint { });
256+
auto pagePoint = documentLayout.documentToPDFPage(FloatPoint { pageBounds.center().x(), topLeftInDocumentSpace.y() }, pageIndex);
257+
258+
LOG_WITH_STREAM(PDF, stream << "PDFPresentationController::pdfPositionForCurrentView - point " << pagePoint << " in page " << pageIndex << " with anchor point " << std::to_underlying(anchorPoint));
259+
260+
return VisiblePDFPosition { pageIndex, pagePoint };
261+
}
262+
263+
FloatPoint PDFPresentationController::anchorPointForDocument(DocumentAnchorPoint anchorPoint) const
264+
{
265+
auto anchorPointInPluginSpace = [anchorPoint, checkedPlugin = CheckedRef { m_plugin.get() }] -> FloatPoint {
266+
switch (anchorPoint) {
267+
case DocumentAnchorPoint::TopLeft:
268+
return { };
269+
case DocumentAnchorPoint::Center:
270+
return flooredIntPoint(checkedPlugin->size() / 2);
271+
}
272+
ASSERT_NOT_REACHED();
273+
return { };
274+
}();
275+
return m_plugin->convertDown(UnifiedPDFPlugin::CoordinateSpace::Plugin, UnifiedPDFPlugin::CoordinateSpace::PDFDocumentLayout, anchorPointInPluginSpace);
276+
}
277+
239278
} // namespace WebKit
240279

241280
#endif // ENABLE(UNIFIED_PDF)

Source/WebKit/WebProcess/Plugins/PDF/UnifiedPDF/PDFScrollingPresentationController.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ class PDFScrollingPresentationController final : public PDFPresentationControlle
7474
CheckedPtr<WebCore::KeyboardScrollingAnimator> checkedKeyboardScrollingAnimator() const;
7575
#endif
7676

77-
std::optional<VisiblePDFPosition> pdfPositionForCurrentView(bool preservePosition) const override;
77+
std::optional<PDFDocumentLayout::PageIndex> pageIndexForCurrentView(DocumentAnchorPoint) const override;
7878
void restorePDFPosition(const VisiblePDFPosition&) override;
7979

8080
void ensurePageIsVisible(PDFDocumentLayout::PageIndex) override { }

Source/WebKit/WebProcess/Plugins/PDF/UnifiedPDF/PDFScrollingPresentationController.mm

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -335,22 +335,9 @@
335335

336336
#pragma mark -
337337

338-
auto PDFScrollingPresentationController::pdfPositionForCurrentView(bool preservePosition) const -> std::optional<VisiblePDFPosition>
338+
std::optional<PDFDocumentLayout::PageIndex> PDFScrollingPresentationController::pageIndexForCurrentView(DocumentAnchorPoint anchorPoint) const
339339
{
340-
if (!preservePosition)
341-
return { };
342-
343-
auto& documentLayout = m_plugin->documentLayout();
344-
345-
if (!documentLayout.hasLaidOutPDFDocument())
346-
return { };
347-
348-
auto topLeftInDocumentSpace = m_plugin->convertDown(UnifiedPDFPlugin::CoordinateSpace::Plugin, UnifiedPDFPlugin::CoordinateSpace::PDFDocumentLayout, FloatPoint { });
349-
auto [pageIndex, pointInPDFPageSpace] = documentLayout.pageIndexAndPagePointForDocumentYOffset(topLeftInDocumentSpace.y());
350-
351-
LOG_WITH_STREAM(PDF, stream << "PDFScrollingPresentationController::pdfPositionForCurrentView - point " << pointInPDFPageSpace << " in page " << pageIndex);
352-
353-
return VisiblePDFPosition { pageIndex, pointInPDFPageSpace };
340+
return m_plugin->documentLayout().pageIndexAndPagePointForDocumentYOffset(anchorPointForDocument(anchorPoint).y()).first;
354341
}
355342

356343
void PDFScrollingPresentationController::restorePDFPosition(const VisiblePDFPosition& info)

Source/WebKit/WebProcess/Plugins/PDF/UnifiedPDF/UnifiedPDFPlugin.mm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,7 +1258,7 @@ static String mutationObserverNotificationString()
12581258
auto autoSizeMode = shouldUpdateAutoSizeScaleOverride.value_or(m_didLayoutWithValidDocument ? m_shouldUpdateAutoSizeScale : ShouldUpdateAutoSizeScale::Yes);
12591259

12601260
auto computeAnchoringInfo = [&] {
1261-
return m_presentationController->pdfPositionForCurrentView(shouldAdjustScale == AdjustScaleAfterLayout::Yes || autoSizeMode == ShouldUpdateAutoSizeScale::Yes);
1261+
return m_presentationController->pdfPositionForCurrentView(PDFPresentationController::DocumentAnchorPoint::TopLeft, shouldAdjustScale == AdjustScaleAfterLayout::Yes || autoSizeMode == ShouldUpdateAutoSizeScale::Yes);
12621262
};
12631263
auto anchoringInfo = computeAnchoringInfo();
12641264

@@ -3957,7 +3957,7 @@ static NSStringCompareOptions compareOptionsForFindOptions(WebCore::FindOptions
39573957
{
39583958
auto shouldAdjustPageScale = m_shouldUpdateAutoSizeScale == ShouldUpdateAutoSizeScale::Yes ? AdjustScaleAfterLayout::No : AdjustScaleAfterLayout::Yes;
39593959
bool didWantWheelEvents = m_presentationController->wantsWheelEvents();
3960-
auto anchoringInfo = m_presentationController->pdfPositionForCurrentView();
3960+
auto anchoringInfo = m_presentationController->pdfPositionForCurrentView(PDFPresentationController::DocumentAnchorPoint::Center);
39613961

39623962
setDisplayMode(mode);
39633963
{

Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@
140140
33DB57432CFD46700045C37C /* metalSpecTOC.pdf in Copy Resources */ = {isa = PBXBuildFile; fileRef = 33DB57422CFD46700045C37C /* metalSpecTOC.pdf */; };
141141
33DB57462CFD9D100045C37C /* WKWebViewForTestingImmediateActions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 33DB57452CFD9D100045C37C /* WKWebViewForTestingImmediateActions.mm */; };
142142
33DC89141419579F00747EF7 /* LoadCanceledNoServerRedirectCallback_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 33DC89131419579F00747EF7 /* LoadCanceledNoServerRedirectCallback_Bundle.cpp */; };
143+
33F734692D3B4ADB003B8704 /* multiple-pages-colored.pdf in Copy Resources */ = {isa = PBXBuildFile; fileRef = 33F734682D3B4ADB003B8704 /* multiple-pages-colored.pdf */; };
143144
3545E58927E2AD1300F1910E /* WritingModeTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3545E58827E2AD1200F1910E /* WritingModeTests.cpp */; };
144145
374B7A611DF371CF00ACCB6C /* BundleEditingDelegatePlugIn.mm in Sources */ = {isa = PBXBuildFile; fileRef = 374B7A5F1DF36EEE00ACCB6C /* BundleEditingDelegatePlugIn.mm */; };
145146
378E64771632655E00B6C676 /* InjectedBundleFrameHitTest_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 378E64751632655D00B6C676 /* InjectedBundleFrameHitTest_Bundle.cpp */; };
@@ -1913,6 +1914,7 @@
19131914
A17C47D42C98E5C20023F3C7 /* mso-list-on-h4.html in Copy Resources */,
19141915
A17C47D52C98E5C20023F3C7 /* mso-list.html in Copy Resources */,
19151916
A17C47D62C98E5C20023F3C7 /* multiple-images.html in Copy Resources */,
1917+
33F734692D3B4ADB003B8704 /* multiple-pages-colored.pdf in Copy Resources */,
19161918
A17C47D72C98E5C20023F3C7 /* multiple-pages.pdf in Copy Resources */,
19171919
A17C46D82C98E54B0023F3C7 /* navigation-client-default-crypto.html in Copy Resources */,
19181920
A17C47D82C98E5C20023F3C7 /* nested-frames.html in Copy Resources */,
@@ -2454,6 +2456,7 @@
24542456
33DC8910141953A300747EF7 /* LoadCanceledNoServerRedirectCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LoadCanceledNoServerRedirectCallback.cpp; sourceTree = "<group>"; };
24552457
33DC89131419579F00747EF7 /* LoadCanceledNoServerRedirectCallback_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LoadCanceledNoServerRedirectCallback_Bundle.cpp; sourceTree = "<group>"; };
24562458
33E79E05137B5FCE00E32D99 /* mouse-move-listener.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "mouse-move-listener.html"; sourceTree = "<group>"; };
2459+
33F734682D3B4ADB003B8704 /* multiple-pages-colored.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = "multiple-pages-colored.pdf"; sourceTree = "<group>"; };
24572460
33FFFC3A2CB9CCFB00248AC3 /* UnifiedPDFTestHelpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UnifiedPDFTestHelpers.h; sourceTree = "<group>"; };
24582461
33FFFC442CBA079500248AC3 /* UnifiedPDFTestHelpers.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = UnifiedPDFTestHelpers.mm; sourceTree = "<group>"; };
24592462
3545E58827E2AD1200F1910E /* WritingModeTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WritingModeTests.cpp; sourceTree = "<group>"; };
@@ -5286,6 +5289,7 @@
52865289
9BCD4119206D5ED7001D71BE /* mso-list-on-h4.html */,
52875290
9BF356CC202D44F200F71160 /* mso-list.html */,
52885291
F42F0811274497C8007E0D90 /* multiple-images.html */,
5292+
33F734682D3B4ADB003B8704 /* multiple-pages-colored.pdf */,
52895293
F4D2C66B2BCF9DE400DADC86 /* multiple-pages.pdf */,
52905294
F455DB8C2BAE37C100732E1B /* nested-frames.html */,
52915295
2E4838462169DD42002F4531 /* nested-lists.html */,

Tools/TestWebKitAPI/Tests/WebKitCocoa/UnifiedPDFTests.mm

Lines changed: 66 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -85,49 +85,97 @@ - (bool)navigationFinished
8585

8686
#if PLATFORM(MAC)
8787

88-
static constexpr unsigned short DownArrowKeyCode { 0x7D };
89-
static constexpr unsigned short RightArrowKeyCode { 0x7C };
88+
class UnifiedPDFWithKeyboardScrolling : public testing::Test {
89+
public:
90+
RetainPtr<TestWKWebView> webView;
91+
92+
void SetUp() final
93+
{
94+
webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 600, 600) configuration:configurationForWebViewTestingUnifiedPDF().get() addToWindow:YES]);
95+
[webView setForceWindowToBecomeKey:YES];
96+
}
9097

91-
UNIFIED_PDF_TEST(KeyboardScrollingInSinglePageMode)
92-
{
93-
auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 600, 600) configuration:configurationForWebViewTestingUnifiedPDF().get() addToWindow:YES]);
94-
[webView setForceWindowToBecomeKey:YES];
98+
void synchronouslyLoadPDFDocument(String documentName)
99+
{
100+
RetainPtr request = [NSURLRequest requestWithURL:[NSBundle.test_resourcesBundle URLForResource:documentName withExtension:@"pdf"]];
101+
[webView synchronouslyLoadRequest:request.get()];
102+
[[webView window] makeFirstResponder:webView.get()];
103+
[[webView window] makeKeyAndOrderFront:nil];
104+
[[webView window] orderFrontRegardless];
105+
[webView waitForNextPresentationUpdate];
106+
}
95107

96-
RetainPtr request = [NSURLRequest requestWithURL:[NSBundle.test_resourcesBundle URLForResource:@"multiple-pages" withExtension:@"pdf"]];
97-
[webView synchronouslyLoadRequest:request.get()];
98-
[[webView window] makeFirstResponder:webView.get()];
99-
[[webView window] makeKeyAndOrderFront:nil];
100-
[[webView window] orderFrontRegardless];
101-
[webView objectByEvaluatingJavaScript:@"internals.setPDFDisplayModeForTesting(document.querySelector('embed'), 'SinglePageDiscrete')"];
102-
[webView waitForNextPresentationUpdate];
103-
[webView setMagnification:2];
108+
void scrollDown(Seconds duration = 200_ms)
109+
{
110+
pressKey(NSDownArrowFunctionKey, DownArrowKeyCode, duration);
111+
}
104112

105-
auto pressKey = [&webView](auto key, unsigned short code, Seconds duration = 200_ms) {
113+
void scrollRight(Seconds duration = 200_ms)
114+
{
115+
pressKey(NSRightArrowFunctionKey, RightArrowKeyCode, duration);
116+
}
117+
118+
private:
119+
static constexpr unsigned short DownArrowKeyCode { 0x7D };
120+
static constexpr unsigned short RightArrowKeyCode { 0x7C };
121+
122+
void pressKey(auto key, unsigned short code, Seconds duration = 200_ms)
123+
{
106124
NSString *keyString = [NSString stringWithFormat:@"%C", static_cast<unichar>(key)];
107125
[webView sendKey:keyString code:code isDown:YES modifiers:0];
108126
Util::runFor(duration);
109127
[webView sendKey:keyString code:code isDown:NO modifiers:0];
110128
Util::runFor(50_ms);
111-
};
129+
}
130+
};
131+
132+
TEST_F(UnifiedPDFWithKeyboardScrolling, KeyboardScrollingInSinglePageMode)
133+
{
134+
if constexpr (!unifiedPDFForTestingEnabled)
135+
return;
136+
137+
synchronouslyLoadPDFDocument("multiple-pages"_s);
138+
139+
[webView objectByEvaluatingJavaScript:@"internals.setPDFDisplayModeForTesting(document.querySelector('embed'), 'SinglePageDiscrete')"];
140+
[webView waitForNextPresentationUpdate];
141+
[webView setMagnification:2];
112142

113143
auto colorsBeforeScrolling = [webView sampleColors];
114144
Vector<WebCore::Color> colorsAfterScrollingDown;
115145
while (true) {
116-
pressKey(NSDownArrowFunctionKey, DownArrowKeyCode);
146+
scrollDown();
117147
colorsAfterScrollingDown = [webView sampleColors];
118148
if (colorsBeforeScrolling != colorsAfterScrollingDown)
119149
break;
120150
}
121151

122152
Vector<WebCore::Color> colorsAfterScrollingRight;
123153
while (true) {
124-
pressKey(NSRightArrowFunctionKey, RightArrowKeyCode);
154+
scrollRight();
125155
colorsAfterScrollingRight = [webView sampleColors];
126156
if (colorsAfterScrollingDown != colorsAfterScrollingRight)
127157
break;
128158
}
129159
}
130160

161+
TEST_F(UnifiedPDFWithKeyboardScrolling, DisplayModeTransitionLandingPage)
162+
{
163+
if constexpr (!unifiedPDFForTestingEnabled)
164+
return;
165+
166+
synchronouslyLoadPDFDocument("multiple-pages-colored"_s);
167+
168+
auto colorsBefore = [webView sampleColors];
169+
170+
scrollDown(800_ms);
171+
[webView objectByEvaluatingJavaScript:@"internals.setPDFDisplayModeForTesting(document.querySelector('embed'), 'SinglePageDiscrete')"];
172+
[webView waitForNextPresentationUpdate];
173+
174+
auto colorsAfter = [webView sampleColors];
175+
176+
EXPECT_NE(colorsBefore, colorsAfter);
177+
}
178+
131179
UNIFIED_PDF_TEST(CopyEditingCommandOnEmptySelectionShouldNotCrash)
132180
{
133181
auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 600, 600) configuration:configurationForWebViewTestingUnifiedPDF().get() addToWindow:YES]);
Binary file not shown.

0 commit comments

Comments
 (0)