UI/AppKit: Do not place the WebView inside a scroll view

Now that scrolling and rendering scrollbars is handled entirely in the
WebContent process, there's no reason to place the WebView inside scroll
views.
This commit is contained in:
Timothy Flynn 2024-11-07 12:26:42 -05:00 committed by Andreas Kling
parent 44443689f2
commit 43ed03145d
Notes: github-actions[bot] 2024-11-07 21:54:17 +00:00
12 changed files with 43 additions and 119 deletions

View file

@ -14,7 +14,7 @@
namespace Ladybird {
Web::MouseEvent ns_event_to_mouse_event(Web::MouseEvent::Type, NSEvent*, NSView*, NSScrollView*, Web::UIEvents::MouseButton);
Web::MouseEvent ns_event_to_mouse_event(Web::MouseEvent::Type, NSEvent*, NSView*, Web::UIEvents::MouseButton);
Web::DragEvent ns_event_to_drag_event(Web::DragEvent::Type, id<NSDraggingInfo>, NSView*);
Vector<URL::URL> drag_event_url_list(Web::DragEvent const&);

View file

@ -40,7 +40,7 @@ static Web::UIEvents::KeyModifier ns_modifiers_to_key_modifiers(NSEventModifierF
return static_cast<Web::UIEvents::KeyModifier>(modifiers);
}
Web::MouseEvent ns_event_to_mouse_event(Web::MouseEvent::Type type, NSEvent* event, NSView* view, NSScrollView* scroll_view, Web::UIEvents::MouseButton button)
Web::MouseEvent ns_event_to_mouse_event(Web::MouseEvent::Type type, NSEvent* event, NSView* view, Web::UIEvents::MouseButton button)
{
auto position = [view convertPoint:event.locationInWindow fromView:nil];
auto device_position = ns_point_to_gfx_point(position).to_type<Web::DevicePixels>();
@ -62,8 +62,10 @@ Web::MouseEvent ns_event_to_mouse_event(Web::MouseEvent::Type type, NSEvent* eve
CGFloat delta_y = -[event scrollingDeltaY];
if (![event hasPreciseScrollingDeltas]) {
delta_x *= scroll_view.horizontalLineScroll;
delta_y *= scroll_view.verticalLineScroll;
static constexpr CGFloat imprecise_scroll_multiplier = 24;
delta_x *= imprecise_scroll_multiplier;
delta_y *= imprecise_scroll_multiplier;
}
wheel_delta_x = static_cast<int>(delta_x);

View file

@ -129,7 +129,7 @@ static constexpr NSInteger CONTEXT_MENU_DELETE_COOKIE_TAG = 4;
[NSMenu popUpContextMenu:strong_self.cookie_context_menu withEvent:event forView:strong_self.web_view];
};
[self setContentView:self.web_view.enclosingScrollView];
[self setContentView:self.web_view];
[self setTitle:@"Inspector"];
[self setIsVisible:YES];
}

View file

@ -48,7 +48,7 @@
@end
@interface LadybirdWebView : NSClipView <NSMenuDelegate>
@interface LadybirdWebView : NSView <NSMenuDelegate>
- (instancetype)init:(id<LadybirdWebViewObserver>)observer;
- (instancetype)initAsChild:(id<LadybirdWebViewObserver>)observer
@ -70,7 +70,6 @@
- (void)handleResize;
- (void)handleDevicePixelRatioChange;
- (void)handleScroll;
- (void)handleVisibility:(BOOL)is_visible;
- (void)setPreferredColorScheme:(Web::CSS::PreferredColorScheme)color_scheme;

View file

@ -196,20 +196,14 @@ struct HideCursor {
- (void)handleResize
{
[self updateViewportRect:Ladybird::WebViewBridge::ForResize::Yes];
[self updateViewportRect];
[self updateStatusLabelPosition];
}
- (void)handleDevicePixelRatioChange
{
m_web_view_bridge->set_device_pixel_ratio([[self window] backingScaleFactor]);
[self updateViewportRect:Ladybird::WebViewBridge::ForResize::Yes];
[self updateStatusLabelPosition];
}
- (void)handleScroll
{
[self updateViewportRect:Ladybird::WebViewBridge::ForResize::No];
[self updateViewportRect];
[self updateStatusLabelPosition];
}
@ -295,27 +289,10 @@ static void copy_data_to_clipboard(StringView data, NSPasteboardType pasteboard_
[pasteBoard setData:ns_data forType:pasteboard_type];
}
- (void)updateViewportRect:(Ladybird::WebViewBridge::ForResize)for_resize
- (void)updateViewportRect
{
auto content_rect = [self frame];
auto document_rect = [[self documentView] frame];
auto device_pixel_ratio = m_web_view_bridge->device_pixel_ratio();
auto position = [&](auto content_size, auto document_size, auto scroll) {
return max(0, (document_size - content_size) * device_pixel_ratio * scroll);
};
auto horizontal_scroll = [[[self scrollView] horizontalScroller] floatValue];
auto vertical_scroll = [[[self scrollView] verticalScroller] floatValue];
auto ns_viewport_rect = NSMakeRect(
position(content_rect.size.width, document_rect.size.width, horizontal_scroll),
position(content_rect.size.height, document_rect.size.height, vertical_scroll),
content_rect.size.width,
content_rect.size.height);
auto viewport_rect = Ladybird::ns_rect_to_gfx_rect(ns_viewport_rect);
m_web_view_bridge->set_viewport_rect(viewport_rect, for_resize);
auto viewport_rect = Ladybird::ns_rect_to_gfx_rect([self frame]);
m_web_view_bridge->set_viewport_rect(viewport_rect);
}
- (void)updateStatusLabelPosition
@ -339,15 +316,6 @@ static void copy_data_to_clipboard(StringView data, NSPasteboardType pasteboard_
// By default, capturing self will copy a strong reference to self in ARC.
__weak LadybirdWebView* weak_self = self;
m_web_view_bridge->on_did_layout = [weak_self](auto content_size) {
LadybirdWebView* self = weak_self;
if (self == nil) {
return;
}
auto inverse_device_pixel_ratio = m_web_view_bridge->inverse_device_pixel_ratio();
[[self documentView] setFrameSize:NSMakeSize(content_size.width() * inverse_device_pixel_ratio, content_size.height() * inverse_device_pixel_ratio)];
};
m_web_view_bridge->on_ready_to_paint = [weak_self]() {
LadybirdWebView* self = weak_self;
if (self == nil) {
@ -573,7 +541,7 @@ static void copy_data_to_clipboard(StringView data, NSPasteboardType pasteboard_
if (self == nil) {
return;
}
[self updateViewportRect:Ladybird::WebViewBridge::ForResize::Yes];
[self updateViewportRect];
};
m_web_view_bridge->on_request_tooltip_override = [weak_self](auto, auto const& tooltip) {
@ -1080,7 +1048,7 @@ static void copy_data_to_clipboard(StringView data, NSPasteboardType pasteboard_
if (self == nil) {
return;
}
self.backgroundColor = Ladybird::gfx_color_to_ns_color(color);
self.layer.backgroundColor = [Ladybird::gfx_color_to_ns_color(color) CGColor];
};
m_web_view_bridge->on_find_in_page = [weak_self](auto current_match_index, auto const& total_match_count) {
@ -1138,11 +1106,6 @@ static void copy_data_to_clipboard(StringView data, NSPasteboardType pasteboard_
m_web_view_bridge->color_picker_update(Ladybird::ns_color_to_gfx_color([NSColorPanel sharedColorPanel].color), Web::HTML::ColorPickerUpdateState::Closed);
}
- (NSScrollView*)scrollView
{
return (NSScrollView*)[self superview];
}
- (void)copy:(id)sender
{
copy_data_to_clipboard(m_web_view_bridge->selected_text(), NSPasteboardTypeString);
@ -1584,13 +1547,13 @@ static void copy_data_to_clipboard(StringView data, NSPasteboardType pasteboard_
- (void)mouseMoved:(NSEvent*)event
{
auto mouse_event = Ladybird::ns_event_to_mouse_event(Web::MouseEvent::Type::MouseMove, event, self, [self scrollView], Web::UIEvents::MouseButton::None);
auto mouse_event = Ladybird::ns_event_to_mouse_event(Web::MouseEvent::Type::MouseMove, event, self, Web::UIEvents::MouseButton::None);
m_web_view_bridge->enqueue_input_event(move(mouse_event));
}
- (void)scrollWheel:(NSEvent*)event
{
auto mouse_event = Ladybird::ns_event_to_mouse_event(Web::MouseEvent::Type::MouseWheel, event, self, [self scrollView], Web::UIEvents::MouseButton::Middle);
auto mouse_event = Ladybird::ns_event_to_mouse_event(Web::MouseEvent::Type::MouseWheel, event, self, Web::UIEvents::MouseButton::Middle);
m_web_view_bridge->enqueue_input_event(move(mouse_event));
}
@ -1598,19 +1561,19 @@ static void copy_data_to_clipboard(StringView data, NSPasteboardType pasteboard_
{
[[self window] makeFirstResponder:self];
auto mouse_event = Ladybird::ns_event_to_mouse_event(Web::MouseEvent::Type::MouseDown, event, self, [self scrollView], Web::UIEvents::MouseButton::Primary);
auto mouse_event = Ladybird::ns_event_to_mouse_event(Web::MouseEvent::Type::MouseDown, event, self, Web::UIEvents::MouseButton::Primary);
m_web_view_bridge->enqueue_input_event(move(mouse_event));
}
- (void)mouseUp:(NSEvent*)event
{
auto mouse_event = Ladybird::ns_event_to_mouse_event(Web::MouseEvent::Type::MouseUp, event, self, [self scrollView], Web::UIEvents::MouseButton::Primary);
auto mouse_event = Ladybird::ns_event_to_mouse_event(Web::MouseEvent::Type::MouseUp, event, self, Web::UIEvents::MouseButton::Primary);
m_web_view_bridge->enqueue_input_event(move(mouse_event));
}
- (void)mouseDragged:(NSEvent*)event
{
auto mouse_event = Ladybird::ns_event_to_mouse_event(Web::MouseEvent::Type::MouseMove, event, self, [self scrollView], Web::UIEvents::MouseButton::Primary);
auto mouse_event = Ladybird::ns_event_to_mouse_event(Web::MouseEvent::Type::MouseMove, event, self, Web::UIEvents::MouseButton::Primary);
m_web_view_bridge->enqueue_input_event(move(mouse_event));
}
@ -1618,19 +1581,19 @@ static void copy_data_to_clipboard(StringView data, NSPasteboardType pasteboard_
{
[[self window] makeFirstResponder:self];
auto mouse_event = Ladybird::ns_event_to_mouse_event(Web::MouseEvent::Type::MouseDown, event, self, [self scrollView], Web::UIEvents::MouseButton::Secondary);
auto mouse_event = Ladybird::ns_event_to_mouse_event(Web::MouseEvent::Type::MouseDown, event, self, Web::UIEvents::MouseButton::Secondary);
m_web_view_bridge->enqueue_input_event(move(mouse_event));
}
- (void)rightMouseUp:(NSEvent*)event
{
auto mouse_event = Ladybird::ns_event_to_mouse_event(Web::MouseEvent::Type::MouseUp, event, self, [self scrollView], Web::UIEvents::MouseButton::Secondary);
auto mouse_event = Ladybird::ns_event_to_mouse_event(Web::MouseEvent::Type::MouseUp, event, self, Web::UIEvents::MouseButton::Secondary);
m_web_view_bridge->enqueue_input_event(move(mouse_event));
}
- (void)rightMouseDragged:(NSEvent*)event
{
auto mouse_event = Ladybird::ns_event_to_mouse_event(Web::MouseEvent::Type::MouseMove, event, self, [self scrollView], Web::UIEvents::MouseButton::Secondary);
auto mouse_event = Ladybird::ns_event_to_mouse_event(Web::MouseEvent::Type::MouseMove, event, self, Web::UIEvents::MouseButton::Secondary);
m_web_view_bridge->enqueue_input_event(move(mouse_event));
}
@ -1641,7 +1604,7 @@ static void copy_data_to_clipboard(StringView data, NSPasteboardType pasteboard_
[[self window] makeFirstResponder:self];
auto mouse_event = Ladybird::ns_event_to_mouse_event(Web::MouseEvent::Type::MouseDown, event, self, [self scrollView], Web::UIEvents::MouseButton::Middle);
auto mouse_event = Ladybird::ns_event_to_mouse_event(Web::MouseEvent::Type::MouseDown, event, self, Web::UIEvents::MouseButton::Middle);
m_web_view_bridge->enqueue_input_event(move(mouse_event));
}
@ -1650,7 +1613,7 @@ static void copy_data_to_clipboard(StringView data, NSPasteboardType pasteboard_
if (event.buttonNumber != 2)
return;
auto mouse_event = Ladybird::ns_event_to_mouse_event(Web::MouseEvent::Type::MouseUp, event, self, [self scrollView], Web::UIEvents::MouseButton::Middle);
auto mouse_event = Ladybird::ns_event_to_mouse_event(Web::MouseEvent::Type::MouseUp, event, self, Web::UIEvents::MouseButton::Middle);
m_web_view_bridge->enqueue_input_event(move(mouse_event));
}
@ -1659,7 +1622,7 @@ static void copy_data_to_clipboard(StringView data, NSPasteboardType pasteboard_
if (event.buttonNumber != 2)
return;
auto mouse_event = Ladybird::ns_event_to_mouse_event(Web::MouseEvent::Type::MouseMove, event, self, [self scrollView], Web::UIEvents::MouseButton::Middle);
auto mouse_event = Ladybird::ns_event_to_mouse_event(Web::MouseEvent::Type::MouseMove, event, self, Web::UIEvents::MouseButton::Middle);
m_web_view_bridge->enqueue_input_event(move(mouse_event));
}

View file

@ -51,16 +51,12 @@ void WebViewBridge::set_system_visibility_state(bool is_visible)
client().async_set_system_visibility_state(m_client_state.page_index, is_visible);
}
void WebViewBridge::set_viewport_rect(Gfx::IntRect viewport_rect, ForResize for_resize)
void WebViewBridge::set_viewport_rect(Gfx::IntRect viewport_rect)
{
viewport_rect.set_size(scale_for_device(viewport_rect.size(), m_device_pixel_ratio));
m_viewport_size = viewport_rect.size();
client().async_set_viewport_size(m_client_state.page_index, m_viewport_size.to_type<Web::DevicePixels>());
if (for_resize == ForResize::Yes) {
handle_resize();
}
handle_resize();
}
void WebViewBridge::update_palette()

View file

@ -32,12 +32,7 @@ public:
float inverse_device_pixel_ratio() const { return 1.0f / m_device_pixel_ratio; }
void set_system_visibility_state(bool is_visible);
enum class ForResize {
Yes,
No,
};
void set_viewport_rect(Gfx::IntRect, ForResize = ForResize::No);
void set_viewport_rect(Gfx::IntRect);
void update_palette();
void set_preferred_color_scheme(Web::CSS::PreferredColorScheme);

View file

@ -28,36 +28,16 @@
if (self) {
self.web_view = web_view;
if (self.web_view == nil)
self.web_view = [[LadybirdWebView alloc] init:nil];
[self.web_view setPostsBoundsChangedNotifications:YES];
auto* scroll_view = [[NSScrollView alloc] init];
[scroll_view setHasVerticalScroller:NO];
[scroll_view setHasHorizontalScroller:NO];
[scroll_view setLineScroll:24];
[scroll_view setContentView:self.web_view];
[scroll_view setDocumentView:[[NSView alloc] init]];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(onContentScroll:)
name:NSViewBoundsDidChangeNotification
object:[scroll_view contentView]];
[self.web_view setClipsToBounds:YES];
}
return self;
}
#pragma mark - Private methods
- (void)onContentScroll:(NSNotification*)notification
{
[self.web_view handleScroll];
}
#pragma mark - NSWindow
- (void)setIsVisible:(BOOL)flag

View file

@ -95,7 +95,7 @@ static constexpr CGFloat const WINDOW_HEIGHT = 800;
auto* stack_view = [NSStackView stackViewWithViews:@[
self.search_panel,
self.web_view.enclosingScrollView,
self.web_view,
]];
[stack_view setOrientation:NSUserInterfaceLayoutOrientationVertical];

View file

@ -46,7 +46,7 @@ static constexpr CGFloat const WINDOW_HEIGHT = 400;
[strong_self updateStatistics];
});
[self setContentView:self.web_view.enclosingScrollView];
[self setContentView:self.web_view];
[self setTitle:@"Task Manager"];
[self setIsVisible:YES];

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2024, Tim Flynn <trflynn89@serenityos.org>
* Copyright (c) 2024, Tim Flynn <trflynn89@ladybird.org>
* Copyright (c) 2024, Andrew Kaster <akaster@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
@ -8,30 +8,23 @@
import Foundation
import Ladybird.WebView
import Ladybird.WebViewApplication
import Ladybird.WebViewWindow
import SwiftUI
public class TaskManager: NSWindow {
public class TaskManager: LadybirdWebViewWindow {
private let WINDOW_WIDTH: CGFloat = 600
private let WINDOW_HEIGHT: CGFloat = 400
var web_view: LadybirdWebView
private var timer: Timer?
init() {
let tab_rect = NSApplication.shared.keyWindow!.frame
let position_x = tab_rect.origin.x + (tab_rect.size.width - WINDOW_WIDTH) / 2
let position_y = tab_rect.origin.y + (tab_rect.size.height - WINDOW_HEIGHT) / 2
let window_rect = NSMakeRect(position_x, position_y, WINDOW_WIDTH, WINDOW_HEIGHT)
let style_mask = NSWindow.StyleMask.init(arrayLiteral: [
NSWindow.StyleMask.titled, NSWindow.StyleMask.closable, NSWindow.StyleMask.miniaturizable,
NSWindow.StyleMask.resizable,
])
self.web_view = LadybirdWebView.init(nil)
super.init(contentRect: window_rect, styleMask: style_mask, backing: NSWindow.BackingStoreType.buffered, defer: false)
super.init(webView: nil, windowRect: window_rect)
self.timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] timer in
if let strong_self = self {
@ -39,16 +32,7 @@ public class TaskManager: NSWindow {
}
}
self.web_view.postsBoundsChangedNotifications = true
let scroll_view = NSScrollView()
scroll_view.hasVerticalScroller = true
scroll_view.hasHorizontalScroller = true
scroll_view.lineScroll = 24
scroll_view.contentView = self.web_view
scroll_view.documentView = NSView()
self.contentView = scroll_view
self.contentView = self.web_view
self.title = "Task Manager"
self.setIsVisible(true)

View file

@ -7,6 +7,11 @@ module Ladybird [system] {
export *
}
explicit module WebViewWindow {
header "UI/LadybirdWebViewWindow.h"
export *
}
explicit module WebViewApplication {
header "../../Userland/Libraries/LibWebView/Application.h"
export *