From 3ab5ecb671a7ebdf3de13e4189720734cdb9a197 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Tue, 9 Apr 2024 22:35:20 -0400 Subject: [PATCH] Ladybird/AppKit: Implement a simple TaskManager window Unlike the Inspector window, this is owned by the ApplicationDelegate as there should be only a single task manager for the entire application. --- .../AppKit/Application/ApplicationDelegate.mm | 32 ++++++- Ladybird/AppKit/UI/TaskManager.h | 19 +++++ Ladybird/AppKit/UI/TaskManager.mm | 84 +++++++++++++++++++ Ladybird/AppKit/UI/TaskManagerController.h | 21 +++++ Ladybird/AppKit/UI/TaskManagerController.mm | 67 +++++++++++++++ Ladybird/CMakeLists.txt | 2 + Meta/gn/secondary/Ladybird/BUILD.gn | 2 + 7 files changed, 226 insertions(+), 1 deletion(-) create mode 100644 Ladybird/AppKit/UI/TaskManager.h create mode 100644 Ladybird/AppKit/UI/TaskManager.mm create mode 100644 Ladybird/AppKit/UI/TaskManagerController.h create mode 100644 Ladybird/AppKit/UI/TaskManagerController.mm diff --git a/Ladybird/AppKit/Application/ApplicationDelegate.mm b/Ladybird/AppKit/Application/ApplicationDelegate.mm index 046b07c4c67..d6c65befd0e 100644 --- a/Ladybird/AppKit/Application/ApplicationDelegate.mm +++ b/Ladybird/AppKit/Application/ApplicationDelegate.mm @@ -11,13 +11,14 @@ #import #import #import +#import #import #if !__has_feature(objc_arc) # error "This project requires ARC" #endif -@interface ApplicationDelegate () +@interface ApplicationDelegate () { Vector m_initial_urls; URL::URL m_new_tab_page_url; @@ -35,6 +36,8 @@ @property (nonatomic, strong) NSMutableArray* managed_tabs; +@property (nonatomic, strong) TaskManagerController* task_manager_controller; + - (NSMenuItem*)createApplicationMenu; - (NSMenuItem*)createFileMenu; - (NSMenuItem*)createEditMenu; @@ -119,6 +122,12 @@ - (void)removeTab:(TabController*)controller { [self.managed_tabs removeObject:controller]; + + if ([self.managed_tabs count] == 0u) { + if (self.task_manager_controller != nil) { + [self.task_manager_controller.window close]; + } + } } - (WebView::CookieJar&)cookieJar @@ -185,6 +194,17 @@ [current_window close]; } +- (void)openTaskManager:(id)sender +{ + if (self.task_manager_controller != nil) { + [self.task_manager_controller.window makeKeyAndOrderFront:sender]; + return; + } + + self.task_manager_controller = [[TaskManagerController alloc] init:self]; + [self.task_manager_controller showWindow:nil]; +} + - (void)openLocation:(id)sender { auto* current_tab = [NSApp keyWindow]; @@ -430,6 +450,9 @@ [submenu addItem:[[NSMenuItem alloc] initWithTitle:@"Open Inspector" action:@selector(openInspector:) keyEquivalent:@"I"]]; + [submenu addItem:[[NSMenuItem alloc] initWithTitle:@"Open Task Manager" + action:@selector(openTaskManager:) + keyEquivalent:@"M"]]; [menu setSubmenu:submenu]; return menu; @@ -586,4 +609,11 @@ return YES; } +#pragma mark - TaskManagerDelegate + +- (void)onTaskManagerClosed +{ + self.task_manager_controller = nil; +} + @end diff --git a/Ladybird/AppKit/UI/TaskManager.h b/Ladybird/AppKit/UI/TaskManager.h new file mode 100644 index 00000000000..5ab2a267c2b --- /dev/null +++ b/Ladybird/AppKit/UI/TaskManager.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2024, Tim Flynn + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#import + +@class LadybirdWebView; + +@interface TaskManager : NSWindow + +- (instancetype)init; + +@property (nonatomic, strong) LadybirdWebView* web_view; + +@end diff --git a/Ladybird/AppKit/UI/TaskManager.mm b/Ladybird/AppKit/UI/TaskManager.mm new file mode 100644 index 00000000000..2997c13c48e --- /dev/null +++ b/Ladybird/AppKit/UI/TaskManager.mm @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2024, Tim Flynn + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +#import +#import + +#if !__has_feature(objc_arc) +# error "This project requires ARC" +#endif + +static constexpr CGFloat const WINDOW_WIDTH = 400; +static constexpr CGFloat const WINDOW_HEIGHT = 300; + +@interface TaskManager () +{ + RefPtr m_update_timer; +} + +@end + +@implementation TaskManager + +- (instancetype)init +{ + auto tab_rect = [[NSApp keyWindow] frame]; + auto position_x = tab_rect.origin.x + (tab_rect.size.width - WINDOW_WIDTH) / 2; + auto position_y = tab_rect.origin.y + (tab_rect.size.height - WINDOW_HEIGHT) / 2; + + auto window_rect = NSMakeRect(position_x, position_y, WINDOW_WIDTH, WINDOW_HEIGHT); + auto style_mask = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable; + + self = [super initWithContentRect:window_rect + styleMask:style_mask + backing:NSBackingStoreBuffered + defer:NO]; + + if (self) { + self.web_view = [[LadybirdWebView alloc] init:nil]; + [self.web_view setPostsBoundsChangedNotifications:YES]; + + auto* scroll_view = [[NSScrollView alloc] init]; + [scroll_view setHasVerticalScroller:YES]; + [scroll_view setHasHorizontalScroller:YES]; + [scroll_view setLineScroll:24]; + + [scroll_view setContentView:self.web_view]; + [scroll_view setDocumentView:[[NSView alloc] init]]; + + __weak TaskManager* weak_self = self; + + m_update_timer = MUST(Core::Timer::create_repeating(1000, [weak_self] { + TaskManager* strong_self = weak_self; + if (strong_self == nil) { + return; + } + + [strong_self updateStatistics]; + })); + + [self setContentView:scroll_view]; + [self setTitle:@"Task Manager"]; + [self setIsVisible:YES]; + + [self updateStatistics]; + m_update_timer->start(); + } + + return self; +} + +- (void)updateStatistics +{ + WebView::ProcessManager::the().update_all_processes(); + [self.web_view loadHTML:WebView::ProcessManager::the().generate_html()]; +} + +@end diff --git a/Ladybird/AppKit/UI/TaskManagerController.h b/Ladybird/AppKit/UI/TaskManagerController.h new file mode 100644 index 00000000000..7ea8ddc00ba --- /dev/null +++ b/Ladybird/AppKit/UI/TaskManagerController.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024, Tim Flynn + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#import + +@protocol TaskManagerDelegate + +- (void)onTaskManagerClosed; + +@end + +@interface TaskManagerController : NSWindowController + +- (instancetype)init:(id)delegate; + +@end diff --git a/Ladybird/AppKit/UI/TaskManagerController.mm b/Ladybird/AppKit/UI/TaskManagerController.mm new file mode 100644 index 00000000000..45762cd97ef --- /dev/null +++ b/Ladybird/AppKit/UI/TaskManagerController.mm @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2024, Tim Flynn + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#import +#import +#import + +#if !__has_feature(objc_arc) +# error "This project requires ARC" +#endif + +@interface TaskManagerController () + +@property (nonatomic, weak) id delegate; + +@end + +@implementation TaskManagerController + +- (instancetype)init:(id)delegate +{ + if (self = [super init]) { + self.delegate = delegate; + } + + return self; +} + +#pragma mark - Private methods + +- (TaskManager*)taskManager +{ + return (TaskManager*)[self window]; +} + +#pragma mark - NSWindowController + +- (IBAction)showWindow:(id)sender +{ + self.window = [[TaskManager alloc] init]; + [self.window setDelegate:self]; + [self.window makeKeyAndOrderFront:sender]; +} + +#pragma mark - NSWindowDelegate + +- (void)windowWillClose:(NSNotification*)notification +{ + [self.delegate onTaskManagerClosed]; +} + +- (void)windowDidResize:(NSNotification*)notification +{ + if (![[self window] inLiveResize]) { + [[[self taskManager] web_view] handleResize]; + } +} + +- (void)windowDidChangeBackingProperties:(NSNotification*)notification +{ + [[[self taskManager] web_view] handleDevicePixelRatioChange]; +} + +@end diff --git a/Ladybird/CMakeLists.txt b/Ladybird/CMakeLists.txt index ae7a559e4e8..b30beadabb8 100644 --- a/Ladybird/CMakeLists.txt +++ b/Ladybird/CMakeLists.txt @@ -148,6 +148,8 @@ elseif (APPLE) AppKit/UI/Palette.mm AppKit/UI/Tab.mm AppKit/UI/TabController.mm + AppKit/UI/TaskManager.mm + AppKit/UI/TaskManagerController.mm AppKit/Utilities/Conversions.mm ) target_include_directories(ladybird PRIVATE AppKit) diff --git a/Meta/gn/secondary/Ladybird/BUILD.gn b/Meta/gn/secondary/Ladybird/BUILD.gn index b03476ce3be..91db137b947 100644 --- a/Meta/gn/secondary/Ladybird/BUILD.gn +++ b/Meta/gn/secondary/Ladybird/BUILD.gn @@ -123,6 +123,8 @@ executable("ladybird_executable") { "AppKit/UI/Palette.mm", "AppKit/UI/Tab.mm", "AppKit/UI/TabController.mm", + "AppKit/UI/TaskManager.mm", + "AppKit/UI/TaskManagerController.mm", "AppKit/Utilities/Conversions.mm", "AppKit/main.mm", ]