mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 00:50:22 +00:00
Ladybird/AppKit: Port TaskManager window to Swift
This is just a direct port of the Objective-C++ code to Swift 6. A future patch should probably update it to actually use SwiftUI.
This commit is contained in:
parent
4066ce2c7e
commit
68ce5f8290
Notes:
github-actions[bot]
2024-07-21 21:56:43 +00:00
Author: https://github.com/ADKaster Commit: https://github.com/LadybirdBrowser/ladybird/commit/68ce5f8290c Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/726
14 changed files with 313 additions and 15 deletions
2
.github/actions/setup/action.yml
vendored
2
.github/actions/setup/action.yml
vendored
|
@ -50,7 +50,7 @@ runs:
|
|||
shell: bash
|
||||
run: |
|
||||
set -e
|
||||
sudo xcode-select --switch /Applications/Xcode_15.4.app
|
||||
sudo xcode-select --switch /Applications/Xcode_16.0.app
|
||||
brew update
|
||||
brew install autoconf autoconf-archive automake coreutils bash ffmpeg ninja wabt ccache unzip qt llvm@18 nasm
|
||||
|
||||
|
|
10
.github/workflows/lagom-template.yml
vendored
10
.github/workflows/lagom-template.yml
vendored
|
@ -138,6 +138,16 @@ jobs:
|
|||
working-directory: ${{ github.workspace }}/Build
|
||||
run: cmake --build .
|
||||
|
||||
- name: Enable the AppKit chrome with Swift files
|
||||
if: ${{ inputs.os_name == 'macOS' && inputs.fuzzer == 'NO_FUZZ' }}
|
||||
working-directory: ${{ github.workspace }}
|
||||
run: cmake -B Build -DENABLE_QT=OFF -DENABLE_SWIFT=ON
|
||||
|
||||
- name: Build the AppKit chrome with Swift files
|
||||
if: ${{ inputs.os_name == 'macOS' && inputs.fuzzer == 'NO_FUZZ' }}
|
||||
working-directory: ${{ github.workspace }}/Build
|
||||
run: cmake --build .
|
||||
|
||||
- name: Save Caches
|
||||
uses: ./.github/actions/cache-save
|
||||
with:
|
||||
|
|
|
@ -36,15 +36,20 @@ include(lagom_install_options)
|
|||
if (ENABLE_ADDRESS_SANITIZER)
|
||||
add_cxx_compile_options(-fsanitize=address -fno-omit-frame-pointer)
|
||||
add_cxx_link_options(-fsanitize=address)
|
||||
add_swift_compile_options(-sanitize=address)
|
||||
add_swift_link_options(-sanitize=address)
|
||||
endif()
|
||||
|
||||
if (ENABLE_MEMORY_SANITIZER)
|
||||
add_cxx_compile_options(-fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer)
|
||||
add_cxx_link_options(-fsanitize=memory -fsanitize-memory-track-origins)
|
||||
add_swift_compile_options(-sanitize=memory)
|
||||
add_swift_link_options(-sanitize=memory)
|
||||
endif()
|
||||
|
||||
if (ENABLE_UNDEFINED_SANITIZER)
|
||||
add_cxx_compile_options(-fsanitize=undefined -fno-omit-frame-pointer)
|
||||
add_swift_compile_options(-sanitize=address)
|
||||
if (UNDEFINED_BEHAVIOR_IS_FATAL)
|
||||
add_cxx_compile_options(-fno-sanitize-recover=undefined)
|
||||
endif()
|
||||
|
@ -52,6 +57,7 @@ if (ENABLE_UNDEFINED_SANITIZER)
|
|||
add_cxx_compile_options(-fno-sanitize=function)
|
||||
endif()
|
||||
add_cxx_link_options(-fsanitize=undefined)
|
||||
add_swift_link_options(-sanitize=address)
|
||||
endif()
|
||||
|
||||
if (HAIKU)
|
||||
|
|
|
@ -11,7 +11,16 @@
|
|||
#import <UI/LadybirdWebView.h>
|
||||
#import <UI/Tab.h>
|
||||
#import <UI/TabController.h>
|
||||
|
||||
#if defined(LADYBIRD_USE_SWIFT)
|
||||
// FIXME: Report this codegen error to Apple
|
||||
# define StyleMask NSWindowStyleMask
|
||||
# import <Ladybird-Swift.h>
|
||||
# undef StyleMask
|
||||
#else
|
||||
# import <UI/TaskManagerController.h>
|
||||
#endif
|
||||
|
||||
#import <Utilities/Conversions.h>
|
||||
|
||||
#if !__has_feature(objc_arc)
|
||||
|
@ -237,7 +246,7 @@
|
|||
return;
|
||||
}
|
||||
|
||||
self.task_manager_controller = [[TaskManagerController alloc] init:self];
|
||||
self.task_manager_controller = [[TaskManagerController alloc] initWithDelegate:self];
|
||||
[self.task_manager_controller showWindow:nil];
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
add_executable(ladybird MACOSX_BUNDLE
|
||||
add_library(ladybird_impl STATIC
|
||||
${LADYBIRD_SOURCES}
|
||||
main.mm
|
||||
Application/Application.mm
|
||||
Application/ApplicationBridge.cpp
|
||||
Application/ApplicationDelegate.mm
|
||||
|
@ -14,14 +13,52 @@ add_executable(ladybird MACOSX_BUNDLE
|
|||
UI/SearchPanel.mm
|
||||
UI/Tab.mm
|
||||
UI/TabController.mm
|
||||
UI/TaskManager.mm
|
||||
UI/TaskManagerController.mm
|
||||
Utilities/Conversions.mm
|
||||
)
|
||||
target_include_directories(ladybird PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(ladybird PRIVATE "-framework Cocoa -framework UniformTypeIdentifiers" LibUnicode)
|
||||
target_compile_options(ladybird PRIVATE
|
||||
-fobjc-arc
|
||||
-Wno-deprecated-anon-enum-enum-conversion # Required for CGImageCreate
|
||||
target_include_directories(ladybird_impl PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
|
||||
|
||||
target_compile_options(ladybird_impl PRIVATE "SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xcc -std=c++23 -cxx-interoperability-mode=default>")
|
||||
target_compile_options(ladybird_impl PUBLIC
|
||||
$<$<COMPILE_LANGUAGE:CXX>:-fobjc-arc>
|
||||
$<$<COMPILE_LANGUAGE:CXX>:-Wno-deprecated-anon-enum-enum-conversion> # Required for CGImageCreate
|
||||
)
|
||||
target_compile_features(ladybird_impl PUBLIC cxx_std_23)
|
||||
|
||||
if (ENABLE_SWIFT)
|
||||
enable_language(Swift)
|
||||
if (CMAKE_Swift_COMPILER_VERSION VERSION_LESS 6.0)
|
||||
message(FATAL_ERROR
|
||||
"Swift 6.0 or newer is required to parse AK C++ headers in C++23 mode"
|
||||
)
|
||||
endif()
|
||||
if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
message(FATAL_ERROR
|
||||
"Swift files must use Clang that was bundled with swiftc"
|
||||
)
|
||||
endif()
|
||||
include(../cmake/GenerateSwiftHeader.cmake)
|
||||
|
||||
target_sources(ladybird_impl PRIVATE
|
||||
UI/TaskManager.swift
|
||||
UI/TaskManagerController.swift
|
||||
)
|
||||
target_compile_definitions(ladybird_impl PUBLIC LADYBIRD_USE_SWIFT)
|
||||
set_target_properties(ladybird_impl PROPERTIES Swift_MODULE_NAME "SwiftLadybird")
|
||||
|
||||
get_target_property(LADYBIRD_NATIVE_DIRS ladybird_impl INCLUDE_DIRECTORIES)
|
||||
_swift_generate_cxx_header(ladybird_impl "Ladybird-Swift.h"
|
||||
SEARCH_PATHS ${LADYBIRD_NATIVE_DIRS}
|
||||
)
|
||||
else()
|
||||
target_sources(ladybird_impl PRIVATE
|
||||
UI/TaskManager.mm
|
||||
UI/TaskManagerController.mm
|
||||
)
|
||||
endif()
|
||||
|
||||
add_executable(ladybird MACOSX_BUNDLE
|
||||
main.mm
|
||||
)
|
||||
target_link_libraries(ladybird PRIVATE "-framework Cocoa -framework UniformTypeIdentifiers" LibUnicode ladybird_impl)
|
||||
|
||||
create_ladybird_bundle(ladybird)
|
||||
|
|
64
Ladybird/AppKit/UI/TaskManager.swift
Normal file
64
Ladybird/AppKit/UI/TaskManager.swift
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Tim Flynn <trflynn89@serenityos.org>
|
||||
* Copyright (c) 2024, Andrew Kaster <akaster@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import Ladybird.WebView
|
||||
import Ladybird.WebViewApplication
|
||||
import SwiftUI
|
||||
|
||||
public class TaskManager: NSWindow {
|
||||
|
||||
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)
|
||||
|
||||
self.timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] timer in
|
||||
if let strong_self = self {
|
||||
strong_self.updateStatistics()
|
||||
}
|
||||
}
|
||||
|
||||
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.title = "Task Manager"
|
||||
self.setIsVisible(true)
|
||||
|
||||
self.updateStatistics()
|
||||
}
|
||||
|
||||
func updateStatistics() {
|
||||
WebView.Application.the().update_process_statistics();
|
||||
self.web_view.loadHTML(WebView.Application.the().generate_process_statistics_html().__bytes_as_string_viewUnsafe());
|
||||
}
|
||||
}
|
|
@ -16,6 +16,6 @@
|
|||
|
||||
@interface TaskManagerController : NSWindowController
|
||||
|
||||
- (instancetype)init:(id<TaskManagerDelegate>)delegate;
|
||||
- (instancetype)initWithDelegate:(id<TaskManagerDelegate>)delegate;
|
||||
|
||||
@end
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
@implementation TaskManagerController
|
||||
|
||||
- (instancetype)init:(id<TaskManagerDelegate>)delegate
|
||||
- (instancetype)initWithDelegate:(id<TaskManagerDelegate>)delegate
|
||||
{
|
||||
if (self = [super init]) {
|
||||
self.delegate = delegate;
|
||||
|
|
50
Ladybird/AppKit/UI/TaskManagerController.swift
Normal file
50
Ladybird/AppKit/UI/TaskManagerController.swift
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Tim Flynn <trflynn89@serenityos.org>
|
||||
* Copyright (c) 2024, Andrew Kaster <akaster@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
@objc
|
||||
public protocol TaskManagerDelegate where Self: NSObject {
|
||||
func onTaskManagerClosed()
|
||||
}
|
||||
|
||||
public class TaskManagerController: NSWindowController, NSWindowDelegate {
|
||||
|
||||
private weak var delegate: TaskManagerDelegate?
|
||||
|
||||
@objc
|
||||
public convenience init(delegate: TaskManagerDelegate) {
|
||||
self.init()
|
||||
self.delegate = delegate
|
||||
}
|
||||
|
||||
@IBAction public override func showWindow(_ sender: Any?) {
|
||||
self.window = TaskManager.init()
|
||||
self.window!.delegate = self
|
||||
self.window!.makeKeyAndOrderFront(sender)
|
||||
}
|
||||
|
||||
public func windowWillClose(_ sender: Notification) {
|
||||
self.delegate?.onTaskManagerClosed()
|
||||
}
|
||||
|
||||
public func windowDidResize(_ sender: Notification) {
|
||||
guard self.window != nil else { return }
|
||||
if !self.window!.inLiveResize {
|
||||
self.taskManager().web_view.handleResize()
|
||||
}
|
||||
}
|
||||
|
||||
public func windowDidChangeBackingProperties(_ sender: Notification) {
|
||||
self.taskManager().web_view.handleDevicePixelRatioChange()
|
||||
}
|
||||
|
||||
private func taskManager() -> TaskManager {
|
||||
return self.window as! TaskManager
|
||||
}
|
||||
}
|
14
Ladybird/AppKit/module.modulemap
Normal file
14
Ladybird/AppKit/module.modulemap
Normal file
|
@ -0,0 +1,14 @@
|
|||
module Ladybird [system] {
|
||||
requires cplusplus
|
||||
requires objc_arc
|
||||
|
||||
explicit module WebView {
|
||||
header "UI/LadybirdWebView.h"
|
||||
export *
|
||||
}
|
||||
|
||||
explicit module WebViewApplication {
|
||||
header "../../Userland/Libraries/LibWebView/Application.h"
|
||||
export *
|
||||
}
|
||||
}
|
85
Ladybird/cmake/GenerateSwiftHeader.cmake
Normal file
85
Ladybird/cmake/GenerateSwiftHeader.cmake
Normal file
|
@ -0,0 +1,85 @@
|
|||
# This source file is part of the Swift open source project
|
||||
#
|
||||
# Copyright (c) 2023 Apple Inc. and the Swift project authors.
|
||||
# Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
#
|
||||
# See https://swift.org/LICENSE.txt for license information
|
||||
|
||||
|
||||
# Generate the bridging header from Swift to C++
|
||||
#
|
||||
# target: the name of the target to generate headers for.
|
||||
# This target must build swift source files.
|
||||
# header: the name of the header file to generate.
|
||||
#
|
||||
# NOTE: This logic will eventually be unstreamed into CMake.
|
||||
function(_swift_generate_cxx_header target header)
|
||||
if(NOT TARGET ${target})
|
||||
message(FATAL_ERROR "Target ${target} not defined.")
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED CMAKE_Swift_COMPILER)
|
||||
message(WARNING "Swift not enabled in project. Cannot generate headers for Swift files.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
cmake_parse_arguments(ARG "" "" "SEARCH_PATHS;MODULE_NAME;CXX_STD_VERSION" ${ARGN})
|
||||
|
||||
if(NOT ARG_MODULE_NAME)
|
||||
set(target_module_name $<TARGET_PROPERTY:${target},Swift_MODULE_NAME>)
|
||||
set(ARG_MODULE_NAME $<IF:$<BOOL:${target_module_name}>,${target_module_name},${target}>)
|
||||
endif()
|
||||
|
||||
if(ARG_SEARCH_PATHS)
|
||||
list(TRANSFORM ARG_SEARCH_PATHS PREPEND "-I")
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
set(SDK_FLAGS "-sdk" "${CMAKE_OSX_SYSROOT}")
|
||||
elseif(WIN32)
|
||||
set(SDK_FLAGS "-sdk" "$ENV{SDKROOT}")
|
||||
elseif(DEFINED ${CMAKE_SYSROOT})
|
||||
set(SDK_FLAGS "-sdk" "${CMAKE_SYSROOT}")
|
||||
endif()
|
||||
|
||||
cmake_path(APPEND CMAKE_CURRENT_BINARY_DIR include
|
||||
OUTPUT_VARIABLE base_path)
|
||||
|
||||
cmake_path(APPEND base_path ${header}
|
||||
OUTPUT_VARIABLE header_path)
|
||||
|
||||
if (NOT ARG_CXX_STD_VERSION)
|
||||
set(ARG_CXX_STD_VERSION "14")
|
||||
get_target_property(CxxFeatures ${target} COMPILE_FEATURES)
|
||||
list(FILTER CxxFeatures INCLUDE REGEX "cxx_std_[0-9]+$")
|
||||
if (NOT "${CxxFeatures}" STREQUAL "")
|
||||
string(SUBSTRING ${CxxFeatures} 8 2 ARG_CXX_STD_VERSION)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CXX_STD_FLAGS -Xcc -std=c++${ARG_CXX_STD_VERSION})
|
||||
|
||||
set(_AllSources $<TARGET_PROPERTY:${target},SOURCES>)
|
||||
set(_SwiftSources $<FILTER:${_AllSources},INCLUDE,\\.swift$>)
|
||||
add_custom_command(OUTPUT ${header_path}
|
||||
DEPENDS ${_SwiftSources}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMAND
|
||||
${CMAKE_Swift_COMPILER} -frontend -typecheck
|
||||
${ARG_SEARCH_PATHS}
|
||||
${_SwiftSources}
|
||||
${SDK_FLAGS}
|
||||
${CXX_STD_FLAGS}
|
||||
-module-name "${ARG_MODULE_NAME}"
|
||||
-cxx-interoperability-mode=default
|
||||
-emit-clang-header-path ${header_path}
|
||||
COMMENT
|
||||
"Generating '${header_path}'"
|
||||
COMMAND_EXPAND_LISTS)
|
||||
|
||||
# Added to public interface for dependees to find.
|
||||
target_include_directories(${target} PUBLIC $<BUILD_INTERFACE:${base_path}>)
|
||||
# Added to the target to ensure target rebuilds if header changes and is used
|
||||
# by sources in the target.
|
||||
target_sources(${target} PRIVATE ${header_path})
|
||||
endfunction()
|
|
@ -21,6 +21,22 @@ macro(add_cxx_link_options)
|
|||
add_link_options($<$<LINK_LANGUAGE:C,CXX>:${args}>)
|
||||
endmacro()
|
||||
|
||||
macro(add_swift_compile_options)
|
||||
set(args "")
|
||||
foreach(arg ${ARGN})
|
||||
string(APPEND args ${arg}$<SEMICOLON>)
|
||||
endforeach()
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:Swift>:${args}>)
|
||||
endmacro()
|
||||
|
||||
macro(add_swift_link_options)
|
||||
set(args "")
|
||||
foreach(arg ${ARGN})
|
||||
string(APPEND args ${arg}$<SEMICOLON>)
|
||||
endforeach()
|
||||
add_link_options($<$<LINK_LANGUAGE:Swift>:${args}>)
|
||||
endmacro()
|
||||
|
||||
if (MSVC)
|
||||
add_cxx_compile_options(/W4)
|
||||
# do not warn about unused function
|
||||
|
|
|
@ -28,3 +28,4 @@ serenity_option(ENABLE_CLANG_PLUGINS OFF CACHE BOOL "Enable building with the Cl
|
|||
serenity_option(ENABLE_CLANG_PLUGINS_INVALID_FUNCTION_MEMBERS OFF CACHE BOOL "Enable detecting invalid function types as members of GC-allocated objects")
|
||||
|
||||
serenity_option(ENABLE_GUI_TARGETS ON CACHE BOOL "Enable building GUI targets")
|
||||
serenity_option(ENABLE_SWIFT OFF CACHE BOOL "Enable building Swift files")
|
||||
|
|
|
@ -10,6 +10,12 @@
|
|||
#include <LibWebView/Process.h>
|
||||
#include <LibWebView/ProcessManager.h>
|
||||
|
||||
#ifdef __swift__
|
||||
# include <swift/bridging>
|
||||
#else
|
||||
# define SWIFT_IMMORTAL_REFERENCE
|
||||
#endif
|
||||
|
||||
namespace WebView {
|
||||
|
||||
class Application {
|
||||
|
@ -46,6 +52,6 @@ private:
|
|||
Core::EventLoop m_event_loop;
|
||||
ProcessManager m_process_manager;
|
||||
bool m_in_shutdown { false };
|
||||
};
|
||||
} SWIFT_IMMORTAL_REFERENCE;
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue