Ladybird: Implement content zooming in the AppKit chrome

This lets the user zoom in and out on a web page using the View menu or
keyboard shortcuts. This does not implement zooming with ctrl+scroll.

In the future, it'd be nice to embed the zoom level display inside the
location toolbar. But to do that, we will need to invent our own custom
search field and all of the UI classes (controller, cell, etc.) to draw
the field. So for now, this places the zoom level display to the right
of the location toolbar.
This commit is contained in:
Timothy Flynn 2023-10-07 17:21:00 -04:00 committed by Andreas Kling
parent af7b4609b6
commit 9d31fc3ea3
6 changed files with 105 additions and 1 deletions

View file

@ -303,7 +303,24 @@
keyEquivalent:@""];
[color_scheme_menu_item setSubmenu:color_scheme_menu];
auto* zoom_menu = [[NSMenu alloc] init];
[zoom_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Zoom In"
action:@selector(zoomIn:)
keyEquivalent:@"+"]];
[zoom_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Zoom Out"
action:@selector(zoomOut:)
keyEquivalent:@"-"]];
[zoom_menu addItem:[[NSMenuItem alloc] initWithTitle:@"Actual Size"
action:@selector(resetZoom:)
keyEquivalent:@"0"]];
auto* zoom_menu_item = [[NSMenuItem alloc] initWithTitle:@"Zoom"
action:nil
keyEquivalent:@""];
[zoom_menu_item setSubmenu:zoom_menu];
[submenu addItem:color_scheme_menu_item];
[submenu addItem:zoom_menu_item];
[submenu addItem:[NSMenuItem separatorItem]];
[menu setSubmenu:submenu];

View file

@ -54,6 +54,11 @@
- (void)setPreferredColorScheme:(Web::CSS::PreferredColorScheme)color_scheme;
- (void)zoomIn;
- (void)zoomOut;
- (void)resetZoom;
- (float)zoomLevel;
- (void)debugRequest:(DeprecatedString const&)request argument:(DeprecatedString const&)argument;
- (void)viewSource;

View file

@ -149,6 +149,26 @@ struct HideCursor {
m_web_view_bridge->set_system_visibility_state(is_visible);
}
- (void)zoomIn
{
m_web_view_bridge->zoom_in();
}
- (void)zoomOut
{
m_web_view_bridge->zoom_out();
}
- (void)resetZoom
{
m_web_view_bridge->reset_zoom();
}
- (float)zoomLevel
{
return m_web_view_bridge->zoom_level();
}
- (void)setPreferredColorScheme:(Web::CSS::PreferredColorScheme)color_scheme
{
m_web_view_bridge->set_preferred_color_scheme(color_scheme);
@ -344,6 +364,10 @@ struct HideCursor {
}
};
m_web_view_bridge->on_zoom_level_changed = [self]() {
[self updateViewportRect:Ladybird::WebViewBridge::ForResize::Yes];
};
m_web_view_bridge->on_navigate_back = [self]() {
[self.observer onNavigateBack];
};

View file

@ -70,7 +70,7 @@ WebViewBridge::~WebViewBridge() = default;
void WebViewBridge::set_device_pixel_ratio(float device_pixel_ratio)
{
m_device_pixel_ratio = device_pixel_ratio;
client().async_set_device_pixels_per_css_pixel(device_pixel_ratio);
client().async_set_device_pixels_per_css_pixel(m_device_pixel_ratio * m_zoom_level);
}
void WebViewBridge::set_system_visibility_state(bool is_visible)
@ -158,6 +158,10 @@ Optional<WebViewBridge::Paintable> WebViewBridge::paintable()
void WebViewBridge::update_zoom()
{
client().async_set_device_pixels_per_css_pixel(m_device_pixel_ratio * m_zoom_level);
if (on_zoom_level_changed)
on_zoom_level_changed();
}
Gfx::IntRect WebViewBridge::viewport_rect() const

View file

@ -55,6 +55,8 @@ public:
};
Optional<Paintable> paintable();
Function<void()> on_zoom_level_changed;
private:
WebViewBridge(Vector<Gfx::IntRect> screen_rects, float device_pixel_ratio, Optional<StringView> webdriver_content_ipc_path, Web::CSS::PreferredColorScheme);

View file

@ -24,6 +24,7 @@ static NSString* const TOOLBAR_NAVIGATE_BACK_IDENTIFIER = @"ToolbarNavigateBackI
static NSString* const TOOLBAR_NAVIGATE_FORWARD_IDENTIFIER = @"ToolbarNavigateForwardIdentifier";
static NSString* const TOOLBAR_RELOAD_IDENTIFIER = @"ToolbarReloadIdentifier";
static NSString* const TOOLBAR_LOCATION_IDENTIFIER = @"ToolbarLocationIdentifier";
static NSString* const TOOLBAR_ZOOM_IDENTIFIER = @"ToolbarZoomIdentifier";
static NSString* const TOOLBAR_NEW_TAB_IDENTIFIER = @"ToolbarNewTabIdentifier";
static NSString* const TOOLBAR_TAB_OVERVIEW_IDENTIFIER = @"ToolbarTabOverviewIdentifer";
@ -49,6 +50,7 @@ enum class IsHistoryNavigation {
@property (nonatomic, strong) NSToolbarItem* navigate_forward_toolbar_item;
@property (nonatomic, strong) NSToolbarItem* reload_toolbar_item;
@property (nonatomic, strong) NSToolbarItem* location_toolbar_item;
@property (nonatomic, strong) NSToolbarItem* zoom_toolbar_item;
@property (nonatomic, strong) NSToolbarItem* new_tab_toolbar_item;
@property (nonatomic, strong) NSToolbarItem* tab_overview_toolbar_item;
@ -63,6 +65,7 @@ enum class IsHistoryNavigation {
@synthesize navigate_forward_toolbar_item = _navigate_forward_toolbar_item;
@synthesize reload_toolbar_item = _reload_toolbar_item;
@synthesize location_toolbar_item = _location_toolbar_item;
@synthesize zoom_toolbar_item = _zoom_toolbar_item;
@synthesize new_tab_toolbar_item = _new_tab_toolbar_item;
@synthesize tab_overview_toolbar_item = _tab_overview_toolbar_item;
@ -119,6 +122,24 @@ enum class IsHistoryNavigation {
m_history.update_title(m_title);
}
- (void)zoomIn:(id)sender
{
[[[self tab] web_view] zoomIn];
[self updateZoomButton];
}
- (void)zoomOut:(id)sender
{
[[[self tab] web_view] zoomOut];
[self updateZoomButton];
}
- (void)resetZoom:(id)sender
{
[[[self tab] web_view] resetZoom];
[self updateZoomButton];
}
- (void)navigateBack:(id)sender
{
if (!m_history.can_go_back()) {
@ -221,6 +242,17 @@ enum class IsHistoryNavigation {
self.tab.titlebarAppearsTransparent = YES;
}
- (void)updateZoomButton
{
auto zoom_level = [[[self tab] web_view] zoomLevel];
auto* zoom_level_text = [NSString stringWithFormat:@"%d%%", round_to<int>(zoom_level * 100.0f)];
[self.zoom_toolbar_item setTitle:zoom_level_text];
auto zoom_button_hidden = zoom_level == 1.0 ? YES : NO;
[[self.zoom_toolbar_item view] setHidden:zoom_button_hidden];
}
- (void)dumpDOMTree:(id)sender
{
[self debugRequest:"dump-dom-tree" argument:""];
@ -392,6 +424,22 @@ enum class IsHistoryNavigation {
return _location_toolbar_item;
}
- (NSToolbarItem*)zoom_toolbar_item
{
if (!_zoom_toolbar_item) {
auto* button = [NSButton buttonWithTitle:@"100%"
target:self
action:@selector(resetZoom:)];
[button setToolTip:@"Reset zoom level"];
[button setHidden:YES];
_zoom_toolbar_item = [[NSToolbarItem alloc] initWithItemIdentifier:TOOLBAR_ZOOM_IDENTIFIER];
[_zoom_toolbar_item setView:button];
}
return _zoom_toolbar_item;
}
- (NSToolbarItem*)new_tab_toolbar_item
{
if (!_new_tab_toolbar_item) {
@ -429,6 +477,7 @@ enum class IsHistoryNavigation {
NSToolbarFlexibleSpaceItemIdentifier,
TOOLBAR_RELOAD_IDENTIFIER,
TOOLBAR_LOCATION_IDENTIFIER,
TOOLBAR_ZOOM_IDENTIFIER,
NSToolbarFlexibleSpaceItemIdentifier,
TOOLBAR_NEW_TAB_IDENTIFIER,
TOOLBAR_TAB_OVERVIEW_IDENTIFIER,
@ -518,6 +567,9 @@ enum class IsHistoryNavigation {
if ([identifier isEqual:TOOLBAR_LOCATION_IDENTIFIER]) {
return self.location_toolbar_item;
}
if ([identifier isEqual:TOOLBAR_ZOOM_IDENTIFIER]) {
return self.zoom_toolbar_item;
}
if ([identifier isEqual:TOOLBAR_NEW_TAB_IDENTIFIER]) {
return self.new_tab_toolbar_item;
}