MacUpdater: Initial implementation

This commit is contained in:
spycrab
2019-02-06 20:50:09 +01:00
parent 9e2406e7be
commit 80f4181f60
11 changed files with 1233 additions and 0 deletions
+4
View File
@@ -11,3 +11,7 @@ add_subdirectory(VideoBackends)
if(ENABLE_QT)
add_subdirectory(DolphinQt)
endif()
if (APPLE)
add_subdirectory(MacUpdater)
endif()
+9
View File
@@ -0,0 +1,9 @@
// Copyright 2019 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#import <Cocoa/Cocoa.h>
@interface AppDelegate : NSObject <NSApplicationDelegate>
@end
File diff suppressed because it is too large Load Diff
+63
View File
@@ -0,0 +1,63 @@
set(STORYBOARDS Main.storyboard)
set(SOURCES
main.m
AppDelegate.h
AppDelegate.mm
ViewController.h
ViewController.m
UI.h
UI.mm
${STORYBOARDS}
)
add_executable(MacUpdater ${SOURCES})
set(MacUpdater_NAME "Dolphin Updater")
set_target_properties(MacUpdater PROPERTIES
MACOSX_BUNDLE true
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in
OUTPUT_NAME ${MacUpdater_NAME})
target_compile_options(MacUpdater PRIVATE -x objective-c++)
# Copy icon into the bundle
target_sources(MacUpdater PRIVATE "${CMAKE_SOURCE_DIR}/Data/Dolphin.icns")
set_source_files_properties("${CMAKE_SOURCE_DIR}/Data/Dolphin.icns" PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
target_link_libraries(MacUpdater PRIVATE
"-framework Cocoa"
"-framework AppKit"
"-framework CoreData"
"-framework Foundation"
uicommon
mbedtls
z
ed25519
)
# Compile storyboards (Adapted from https://gitlab.kitware.com/cmake/community/wikis/doc/tutorials/OSX-InterfaceBuilderFiles)
# Make sure we can find the 'ibtool' program. If we can NOT find it we
# skip generation of this project
find_program(IBTOOL ibtool HINTS "/usr/bin" "${OSX_DEVELOPER_ROOT}/usr/bin")
if (${IBTOOL} STREQUAL "IBTOOL-NOTFOUND")
message(SEND_ERROR "ibtool can not be found and is needed to compile the .storyboard files. It should have been installed with
the Apple developer tools. The default system paths were searched in addition to ${OSX_DEVELOPER_ROOT}/usr/bin")
endif()
foreach(sb ${STORYBOARDS})
set(MacUpdater_BIN_DIR ${CMAKE_BINARY_DIR}/Binaries)
if (CMAKE_GENERATOR STREQUAL Xcode)
string(APPEND MacUpdater_BIN_DIR "/\${CONFIGURATION}")
endif()
add_custom_command(TARGET MacUpdater POST_BUILD
COMMAND ${IBTOOL} --errors --warnings --notices --output-format human-readable-text
--compile ${MacUpdater_BIN_DIR}/${MacUpdater_NAME}.app/Contents/Resources/${sb}c
${CMAKE_CURRENT_SOURCE_DIR}/${sb}
COMMENT "Compiling Storyboard ${sb}...")
endforeach()
+32
View File
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${MacUpdater_NAME}</string>
<key>CFBundleIconFile</key>
<string>Dolphin.icns</string>
<key>CFBundleIdentifier</key>
<string>com.dolphinteam.dolphin-updater</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>Updater</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>10.9</string>
<key>NSHumanReadableCopyright</key>
<string>Licensed under GPL version 2 or later (GPLv2+)</string>
<key>NSMainStoryboardFile</key>
<string>Main</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>
+109
View File
@@ -0,0 +1,109 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
<dependencies>
<deployment version="101000" identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14460.31"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Application-->
<scene sceneID="JPo-4y-FX3">
<objects>
<application id="hnw-xV-0zn" sceneMemberID="viewController">
<menu key="mainMenu" title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
<items>
<menuItem title="Updater" id="1Xt-HY-uBw">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Updater" systemMenu="apple" id="uQy-DD-JDr">
<items>
<menuItem title="About Updater" id="5kV-Vb-QxS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontStandardAboutPanel:" target="Ady-hI-5gd" id="Exp-CZ-Vem"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
<menuItem title="Quit Updater" keyEquivalent="q" id="4sb-4s-VLi">
<connections>
<action selector="terminate:" target="Ady-hI-5gd" id="Te7-pn-YzF"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
<connections>
<outlet property="delegate" destination="Voe-Tx-rLC" id="PrD-fu-P6m"/>
</connections>
</application>
<customObject id="Voe-Tx-rLC" customClass="AppDelegate"/>
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
<customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="75" y="0.0"/>
</scene>
<!--Window Controller-->
<scene sceneID="R2V-B0-nI4">
<objects>
<windowController id="B8D-0N-5wS" sceneMemberID="viewController">
<window key="window" title="Dolphin Updater" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" titlebarAppearsTransparent="YES" id="IQv-IB-iLA">
<windowStyleMask key="styleMask" titled="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="480" height="270"/>
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/>
<connections>
<outlet property="delegate" destination="B8D-0N-5wS" id="98r-iN-zZc"/>
</connections>
</window>
<connections>
<segue destination="XfG-lQ-9wD" kind="relationship" relationship="window.shadowedContentViewController" id="cq2-FE-JQM"/>
</connections>
</windowController>
<customObject id="Oky-zY-oP4" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="75" y="250"/>
</scene>
<!--View Controller-->
<scene sceneID="hIz-AP-VOD">
<objects>
<viewController id="XfG-lQ-9wD" customClass="ViewController" sceneMemberID="viewController">
<view key="view" wantsLayer="YES" id="m2S-Jp-Qdl">
<rect key="frame" x="0.0" y="0.0" width="480" height="120"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<progressIndicator identifier="progressTotal" wantsLayer="YES" fixedFrame="YES" maxValue="100" style="bar" translatesAutoresizingMaskIntoConstraints="NO" id="oLS-AW-V72">
<rect key="frame" x="20" y="81" width="440" height="20"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
</progressIndicator>
<progressIndicator identifier="progressCurrent" wantsLayer="YES" fixedFrame="YES" maxValue="100" indeterminate="YES" style="bar" translatesAutoresizingMaskIntoConstraints="NO" id="mni-rL-166">
<rect key="frame" x="20" y="39" width="440" height="20"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
</progressIndicator>
<textField identifier="labelProgress" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="r87-pn-Exw" userLabel="Label">
<rect key="frame" x="18" y="15" width="444" height="17"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Initializing..." id="FBK-Tz-5cA">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<action selector="progressLabel:" target="XfG-lQ-9wD" id="PDs-H5-idS"/>
</connections>
</textField>
</subviews>
</view>
<connections>
<outlet property="foo" destination="r87-pn-Exw" id="i76-Sg-K3o"/>
<outlet property="labelProgress" destination="r87-pn-Exw" id="v6b-r7-3lR"/>
<outlet property="progressCurrent" destination="mni-rL-166" id="A3C-wp-83j"/>
<outlet property="progressTotal" destination="oLS-AW-V72" id="pwo-CZ-XyN"/>
</connections>
</viewController>
<customObject id="rPt-NT-nkU" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="75" y="647"/>
</scene>
</scenes>
</document>
+24
View File
@@ -0,0 +1,24 @@
// Copyright 2019 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <string>
namespace UI
{
void Error(const std::string& text);
void SetVisible(bool visible);
void SetDescription(const std::string& text);
void SetTotalMarquee(bool marquee);
void ResetTotalProgress();
void SetTotalProgress(int current, int total);
void SetCurrentMarquee(bool marquee);
void ResetCurrentProgress();
void SetCurrentProgress(int current, int total);
} // namespace UI
+103
View File
@@ -0,0 +1,103 @@
// Copyright 2019 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "MacUpdater/UI.h"
#include "MacUpdater/ViewController.h"
#include <Cocoa/Cocoa.h>
#include <functional>
// When we call from the main thread, we are not allowed to use
// dispatch_sync(dispatch_get_main_queue() as it will cause crashes) To prevent this check if we're
// already on the main thread first
void run_on_main(std::function<void()> fnc)
{
if (![NSThread isMainThread])
dispatch_sync(dispatch_get_main_queue(), ^{
fnc();
});
else
fnc();
}
NSWindow* GetWindow()
{
return [[[NSApplication sharedApplication] windows] objectAtIndex:0];
}
ViewController* GetView()
{
return (ViewController*)GetWindow().contentViewController;
}
void UI::Error(const std::string& text)
{
run_on_main([&] {
NSAlert* alert = [[[NSAlert alloc] init] autorelease];
[alert setMessageText:@"Fatal error"];
[alert
setInformativeText:[NSString stringWithCString:text.c_str() encoding:NSUTF8StringEncoding]];
[alert setAlertStyle:NSAlertStyleCritical];
[alert beginSheetModalForWindow:GetWindow()
completionHandler:^(NSModalResponse) {
[NSApp performSelector:@selector(terminate:) withObject:nil afterDelay:0.0];
}];
});
}
void UI::SetVisible(bool visible)
{
run_on_main([&] {
if (visible)
{
[NSApp unhide:nil];
[NSApp activateIgnoringOtherApps:YES];
}
else
{
[NSApp hide:nil];
}
});
}
void UI::SetDescription(const std::string& text)
{
run_on_main([&] {
[GetView()
SetDescription:[NSString stringWithCString:text.c_str() encoding:NSUTF8StringEncoding]];
});
}
void UI::SetTotalMarquee(bool marquee)
{
run_on_main([marquee] { [GetView() SetTotalMarquee:marquee]; });
}
void UI::SetCurrentMarquee(bool marquee)
{
run_on_main([&] { [GetView() SetCurrentMarquee:marquee]; });
}
void UI::ResetTotalProgress()
{
run_on_main([] { SetTotalProgress(0, 1); });
}
void UI::ResetCurrentProgress()
{
run_on_main([] { SetCurrentProgress(0, 1); });
}
void UI::SetCurrentProgress(int current, int total)
{
run_on_main([&] { [GetView() SetCurrentProgress:(double)current total:(double)total]; });
}
void UI::SetTotalProgress(int current, int total)
{
run_on_main([&] { [GetView() SetTotalProgress:(double)current total:(double)total]; });
}
+21
View File
@@ -0,0 +1,21 @@
// Copyright 2019 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#import <Cocoa/Cocoa.h>
@interface ViewController : NSViewController
@property(assign) IBOutlet NSProgressIndicator* progressCurrent;
@property(assign) IBOutlet NSProgressIndicator* progressTotal;
@property(assign) IBOutlet NSTextField* labelProgress;
- (void)SetDescription:(NSString*)string;
- (void)SetTotalMarquee:(bool)marquee;
- (void)SetCurrentMarquee:(bool)marquee;
- (void)SetTotalProgress:(double)current total:(double)total;
- (void)SetCurrentProgress:(double)current total:(double)total;
@end
+52
View File
@@ -0,0 +1,52 @@
// Copyright 2019 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#import "ViewController.h"
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSWindow* window = [[self view] window];
[window setLevel:kCGMainMenuWindowLevel - 1];
[window setCollectionBehavior:NSWindowCollectionBehaviorStationary |
NSWindowCollectionBehaviorCanJoinAllSpaces |
NSWindowCollectionBehaviorFullScreenAuxiliary];
}
- (void)SetDescription:(NSString*)string
{
[_labelProgress setStringValue:string];
}
- (void)SetTotalMarquee:(bool)marquee
{
[_progressTotal setIndeterminate:marquee];
}
- (void)SetCurrentMarquee:(bool)marquee
{
[_progressCurrent setIndeterminate:marquee];
}
- (void)SetTotalProgress:(double)current total:(double)total
{
[_progressTotal setMaxValue:total];
[_progressTotal setDoubleValue:current];
}
- (void)SetCurrentProgress:(double)current total:(double)total
{
[_progressCurrent setMaxValue:total];
[_progressCurrent setDoubleValue:current];
}
- (void)setRepresentedObject:(id)representedObject
{
[super setRepresentedObject:representedObject];
}
@end
+22
View File
@@ -0,0 +1,22 @@
// Copyright 2019 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <Cocoa/Cocoa.h>
int main(int argc, const char** argv)
{
if (argc == 1)
{
NSAlert* alert = [[[NSAlert alloc] init] autorelease];
[alert setMessageText:@"This updater is not meant to be launched directly."];
[alert setAlertStyle:NSAlertStyleWarning];
[alert setInformativeText:@"Configure Auto-Update in Dolphin's settings instead."];
[alert runModal];
return 1;
}
return NSApplicationMain(argc, argv);
}