diff --git a/Ladybird/AppKit/Application/ApplicationDelegate.mm b/Ladybird/AppKit/Application/ApplicationDelegate.mm index ccc5786b0e..dca160cf5b 100644 --- a/Ladybird/AppKit/Application/ApplicationDelegate.mm +++ b/Ladybird/AppKit/Application/ApplicationDelegate.mm @@ -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]; diff --git a/Ladybird/AppKit/UI/LadybirdWebView.h b/Ladybird/AppKit/UI/LadybirdWebView.h index 87e5b7adbd..7fd65edd8f 100644 --- a/Ladybird/AppKit/UI/LadybirdWebView.h +++ b/Ladybird/AppKit/UI/LadybirdWebView.h @@ -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; diff --git a/Ladybird/AppKit/UI/LadybirdWebView.mm b/Ladybird/AppKit/UI/LadybirdWebView.mm index ebb120cc7c..cf242bcdfa 100644 --- a/Ladybird/AppKit/UI/LadybirdWebView.mm +++ b/Ladybird/AppKit/UI/LadybirdWebView.mm @@ -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]; }; diff --git a/Ladybird/AppKit/UI/LadybirdWebViewBridge.cpp b/Ladybird/AppKit/UI/LadybirdWebViewBridge.cpp index 73059cfe94..a22e530a09 100644 --- a/Ladybird/AppKit/UI/LadybirdWebViewBridge.cpp +++ b/Ladybird/AppKit/UI/LadybirdWebViewBridge.cpp @@ -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() 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 diff --git a/Ladybird/AppKit/UI/LadybirdWebViewBridge.h b/Ladybird/AppKit/UI/LadybirdWebViewBridge.h index 337ba94a1c..1910651bd1 100644 --- a/Ladybird/AppKit/UI/LadybirdWebViewBridge.h +++ b/Ladybird/AppKit/UI/LadybirdWebViewBridge.h @@ -55,6 +55,8 @@ public: }; Optional paintable(); + Function on_zoom_level_changed; + private: WebViewBridge(Vector screen_rects, float device_pixel_ratio, Optional webdriver_content_ipc_path, Web::CSS::PreferredColorScheme); diff --git a/Ladybird/AppKit/UI/TabController.mm b/Ladybird/AppKit/UI/TabController.mm index c6bdc696a2..a43c57d6d8 100644 --- a/Ladybird/AppKit/UI/TabController.mm +++ b/Ladybird/AppKit/UI/TabController.mm @@ -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(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; }