Browse Source

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.
Timothy Flynn 1 year ago
parent
commit
3ab5ecb671

+ 31 - 1
Ladybird/AppKit/Application/ApplicationDelegate.mm

@@ -11,13 +11,14 @@
 #import <UI/LadybirdWebView.h>
 #import <UI/LadybirdWebView.h>
 #import <UI/Tab.h>
 #import <UI/Tab.h>
 #import <UI/TabController.h>
 #import <UI/TabController.h>
+#import <UI/TaskManagerController.h>
 #import <Utilities/Conversions.h>
 #import <Utilities/Conversions.h>
 
 
 #if !__has_feature(objc_arc)
 #if !__has_feature(objc_arc)
 #    error "This project requires ARC"
 #    error "This project requires ARC"
 #endif
 #endif
 
 
-@interface ApplicationDelegate ()
+@interface ApplicationDelegate () <TaskManagerDelegate>
 {
 {
     Vector<URL::URL> m_initial_urls;
     Vector<URL::URL> m_initial_urls;
     URL::URL m_new_tab_page_url;
     URL::URL m_new_tab_page_url;
@@ -35,6 +36,8 @@
 
 
 @property (nonatomic, strong) NSMutableArray<TabController*>* managed_tabs;
 @property (nonatomic, strong) NSMutableArray<TabController*>* managed_tabs;
 
 
+@property (nonatomic, strong) TaskManagerController* task_manager_controller;
+
 - (NSMenuItem*)createApplicationMenu;
 - (NSMenuItem*)createApplicationMenu;
 - (NSMenuItem*)createFileMenu;
 - (NSMenuItem*)createFileMenu;
 - (NSMenuItem*)createEditMenu;
 - (NSMenuItem*)createEditMenu;
@@ -119,6 +122,12 @@
 - (void)removeTab:(TabController*)controller
 - (void)removeTab:(TabController*)controller
 {
 {
     [self.managed_tabs removeObject: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
 - (WebView::CookieJar&)cookieJar
@@ -185,6 +194,17 @@
     [current_window close];
     [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
 - (void)openLocation:(id)sender
 {
 {
     auto* current_tab = [NSApp keyWindow];
     auto* current_tab = [NSApp keyWindow];
@@ -430,6 +450,9 @@
     [submenu addItem:[[NSMenuItem alloc] initWithTitle:@"Open Inspector"
     [submenu addItem:[[NSMenuItem alloc] initWithTitle:@"Open Inspector"
                                                 action:@selector(openInspector:)
                                                 action:@selector(openInspector:)
                                          keyEquivalent:@"I"]];
                                          keyEquivalent:@"I"]];
+    [submenu addItem:[[NSMenuItem alloc] initWithTitle:@"Open Task Manager"
+                                                action:@selector(openTaskManager:)
+                                         keyEquivalent:@"M"]];
 
 
     [menu setSubmenu:submenu];
     [menu setSubmenu:submenu];
     return menu;
     return menu;
@@ -586,4 +609,11 @@
     return YES;
     return YES;
 }
 }
 
 
+#pragma mark - TaskManagerDelegate
+
+- (void)onTaskManagerClosed
+{
+    self.task_manager_controller = nil;
+}
+
 @end
 @end

+ 19 - 0
Ladybird/AppKit/UI/TaskManager.h

@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2024, Tim Flynn <trflynn89@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#import <System/Cocoa.h>
+
+@class LadybirdWebView;
+
+@interface TaskManager : NSWindow
+
+- (instancetype)init;
+
+@property (nonatomic, strong) LadybirdWebView* web_view;
+
+@end

+ 84 - 0
Ladybird/AppKit/UI/TaskManager.mm

@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2024, Tim Flynn <trflynn89@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <AK/String.h>
+#include <LibCore/Timer.h>
+#include <LibWebView/ProcessManager.h>
+
+#import <UI/LadybirdWebView.h>
+#import <UI/TaskManager.h>
+
+#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<Core::Timer> 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

+ 21 - 0
Ladybird/AppKit/UI/TaskManagerController.h

@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2024, Tim Flynn <trflynn89@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#import <System/Cocoa.h>
+
+@protocol TaskManagerDelegate <NSObject>
+
+- (void)onTaskManagerClosed;
+
+@end
+
+@interface TaskManagerController : NSWindowController
+
+- (instancetype)init:(id<TaskManagerDelegate>)delegate;
+
+@end

+ 67 - 0
Ladybird/AppKit/UI/TaskManagerController.mm

@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2024, Tim Flynn <trflynn89@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#import <UI/LadybirdWebView.h>
+#import <UI/TaskManager.h>
+#import <UI/TaskManagerController.h>
+
+#if !__has_feature(objc_arc)
+#    error "This project requires ARC"
+#endif
+
+@interface TaskManagerController () <NSWindowDelegate>
+
+@property (nonatomic, weak) id<TaskManagerDelegate> delegate;
+
+@end
+
+@implementation TaskManagerController
+
+- (instancetype)init:(id<TaskManagerDelegate>)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

+ 2 - 0
Ladybird/CMakeLists.txt

@@ -148,6 +148,8 @@ elseif (APPLE)
         AppKit/UI/Palette.mm
         AppKit/UI/Palette.mm
         AppKit/UI/Tab.mm
         AppKit/UI/Tab.mm
         AppKit/UI/TabController.mm
         AppKit/UI/TabController.mm
+        AppKit/UI/TaskManager.mm
+        AppKit/UI/TaskManagerController.mm
         AppKit/Utilities/Conversions.mm
         AppKit/Utilities/Conversions.mm
     )
     )
     target_include_directories(ladybird PRIVATE AppKit)
     target_include_directories(ladybird PRIVATE AppKit)

+ 2 - 0
Meta/gn/secondary/Ladybird/BUILD.gn

@@ -123,6 +123,8 @@ executable("ladybird_executable") {
       "AppKit/UI/Palette.mm",
       "AppKit/UI/Palette.mm",
       "AppKit/UI/Tab.mm",
       "AppKit/UI/Tab.mm",
       "AppKit/UI/TabController.mm",
       "AppKit/UI/TabController.mm",
+      "AppKit/UI/TaskManager.mm",
+      "AppKit/UI/TaskManagerController.mm",
       "AppKit/Utilities/Conversions.mm",
       "AppKit/Utilities/Conversions.mm",
       "AppKit/main.mm",
       "AppKit/main.mm",
     ]
     ]