clang-format objc files (#12673)
This commit is contained in:
parent
94236bf4eb
commit
12a57ff1c2
54 changed files with 1298 additions and 1033 deletions
|
@ -24,7 +24,7 @@ int AtomMain(int argc, char* argv[]) {
|
|||
}
|
||||
|
||||
#ifdef ENABLE_RUN_AS_NODE
|
||||
int AtomInitializeICUandStartNode(int argc, char *argv[]) {
|
||||
int AtomInitializeICUandStartNode(int argc, char* argv[]) {
|
||||
base::AtExitManager atexit_manager;
|
||||
base::mac::ScopedNSAutoreleasePool pool;
|
||||
base::mac::SetOverrideFrameworkBundlePath(
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
int main(int argc, char* argv[]) {
|
||||
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
|
||||
NSArray* pathComponents = [[[NSBundle mainBundle] bundlePath] pathComponents];
|
||||
pathComponents = [pathComponents subarrayWithRange:NSMakeRange(0, [pathComponents count] - 4)];
|
||||
pathComponents = [pathComponents
|
||||
subarrayWithRange:NSMakeRange(0, [pathComponents count] - 4)];
|
||||
NSString* path = [NSString pathWithComponents:pathComponents];
|
||||
[[NSWorkspace sharedWorkspace] launchApplication:path];
|
||||
[pool drain];
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
|
||||
#include "atom/app/atom_main_delegate.h"
|
||||
|
||||
#include "base/mac/bundle_locations.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/mac/bundle_locations.h"
|
||||
#include "base/mac/foundation_util.h"
|
||||
#include "base/mac/scoped_nsautorelease_pool.h"
|
||||
#include "base/path_service.h"
|
||||
|
@ -20,16 +20,17 @@ namespace atom {
|
|||
namespace {
|
||||
|
||||
base::FilePath GetFrameworksPath() {
|
||||
return brightray::MainApplicationBundlePath().Append("Contents")
|
||||
.Append("Frameworks");
|
||||
return brightray::MainApplicationBundlePath()
|
||||
.Append("Contents")
|
||||
.Append("Frameworks");
|
||||
}
|
||||
|
||||
base::FilePath GetHelperAppPath(const base::FilePath& frameworks_path,
|
||||
const std::string& name) {
|
||||
return frameworks_path.Append(name + " Helper.app")
|
||||
.Append("Contents")
|
||||
.Append("MacOS")
|
||||
.Append(name + " Helper");
|
||||
.Append("Contents")
|
||||
.Append("MacOS")
|
||||
.Append(name + " Helper");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -41,11 +42,11 @@ void AtomMainDelegate::OverrideFrameworkBundlePath() {
|
|||
|
||||
void AtomMainDelegate::OverrideChildProcessPath() {
|
||||
base::FilePath frameworks_path = GetFrameworksPath();
|
||||
base::FilePath helper_path = GetHelperAppPath(frameworks_path,
|
||||
ATOM_PRODUCT_NAME);
|
||||
base::FilePath helper_path =
|
||||
GetHelperAppPath(frameworks_path, ATOM_PRODUCT_NAME);
|
||||
if (!base::PathExists(helper_path))
|
||||
helper_path = GetHelperAppPath(frameworks_path,
|
||||
brightray::GetApplicationName());
|
||||
helper_path =
|
||||
GetHelperAppPath(frameworks_path, brightray::GetApplicationName());
|
||||
if (!base::PathExists(helper_path))
|
||||
LOG(FATAL) << "Unable to find helper app";
|
||||
PathService::Override(content::CHILD_PROCESS_EXE, helper_path);
|
||||
|
|
|
@ -19,23 +19,27 @@ void OnStopAccessingSecurityScopedResource(NSURL* bookmarkUrl) {
|
|||
}
|
||||
|
||||
// Get base64 encoded NSData, create a bookmark for it and start accessing it.
|
||||
base::Callback<void ()> App::StartAccessingSecurityScopedResource(mate::Arguments* args) {
|
||||
base::Callback<void()> App::StartAccessingSecurityScopedResource(
|
||||
mate::Arguments* args) {
|
||||
std::string data;
|
||||
args->GetNext(&data);
|
||||
NSString *base64str = base::SysUTF8ToNSString(data);
|
||||
NSData *bookmarkData = [[NSData alloc] initWithBase64EncodedString: base64str options: 0];
|
||||
NSString* base64str = base::SysUTF8ToNSString(data);
|
||||
NSData* bookmarkData =
|
||||
[[NSData alloc] initWithBase64EncodedString:base64str options:0];
|
||||
|
||||
// Create bookmarkUrl from NSData.
|
||||
BOOL isStale = false;
|
||||
NSError *error = nil;
|
||||
NSURL *bookmarkUrl = [NSURL URLByResolvingBookmarkData: bookmarkData
|
||||
options: NSURLBookmarkResolutionWithSecurityScope
|
||||
relativeToURL: nil
|
||||
bookmarkDataIsStale: &isStale
|
||||
error: &error];
|
||||
NSError* error = nil;
|
||||
NSURL* bookmarkUrl =
|
||||
[NSURL URLByResolvingBookmarkData:bookmarkData
|
||||
options:NSURLBookmarkResolutionWithSecurityScope
|
||||
relativeToURL:nil
|
||||
bookmarkDataIsStale:&isStale
|
||||
error:&error];
|
||||
|
||||
if (error != nil) {
|
||||
NSString *err = [NSString stringWithFormat: @"NSError: %@ %@", error, [error userInfo]];
|
||||
NSString* err =
|
||||
[NSString stringWithFormat:@"NSError: %@ %@", error, [error userInfo]];
|
||||
args->ThrowError(base::SysNSStringToUTF8(err));
|
||||
}
|
||||
|
||||
|
@ -54,6 +58,6 @@ base::Callback<void ()> App::StartAccessingSecurityScopedResource(mate::Argument
|
|||
return base::Bind(&OnStopAccessingSecurityScopedResource, bookmarkUrl);
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
} // namespace atom
|
||||
|
||||
} // namespace api
|
||||
} // namespace api
|
||||
|
|
|
@ -38,7 +38,9 @@ namespace {
|
|||
// Return a vector of non-draggable regions that fill a window of size
|
||||
// |width| by |height|, but leave gaps where the window should be draggable.
|
||||
std::vector<gfx::Rect> CalculateNonDraggableRegions(
|
||||
std::unique_ptr<SkRegion> draggable, int width, int height) {
|
||||
std::unique_ptr<SkRegion> draggable,
|
||||
int width,
|
||||
int height) {
|
||||
std::vector<gfx::Rect> result;
|
||||
std::unique_ptr<SkRegion> non_draggable(new SkRegion);
|
||||
non_draggable->op(0, 0, width, height, SkRegion::kUnion_Op);
|
||||
|
|
|
@ -2,18 +2,18 @@
|
|||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#import "atom/browser/api/atom_api_screen.h"
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "atom/browser/api/atom_api_screen.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
//TODO(codebytere): deprecated; remove in 3.0
|
||||
// TODO(codebytere): deprecated; remove in 3.0
|
||||
int Screen::getMenuBarHeight() {
|
||||
return [[NSApp mainMenu] menuBarHeight];
|
||||
}
|
||||
|
||||
}// namespace api
|
||||
} // namespace api
|
||||
|
||||
}// namespace atom
|
||||
} // namespace atom
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include "atom/browser/mac/dict_util.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
#include "base/values.h"
|
||||
#include "net/base/mac/url_conversions.h"
|
||||
|
@ -28,27 +28,32 @@ std::map<int, id> g_id_map;
|
|||
|
||||
} // namespace
|
||||
|
||||
void SystemPreferences::PostNotification(const std::string& name,
|
||||
void SystemPreferences::PostNotification(
|
||||
const std::string& name,
|
||||
const base::DictionaryValue& user_info) {
|
||||
DoPostNotification(name, user_info, kNSDistributedNotificationCenter);
|
||||
}
|
||||
|
||||
int SystemPreferences::SubscribeNotification(
|
||||
const std::string& name, const NotificationCallback& callback) {
|
||||
return DoSubscribeNotification(name, callback, kNSDistributedNotificationCenter);
|
||||
const std::string& name,
|
||||
const NotificationCallback& callback) {
|
||||
return DoSubscribeNotification(name, callback,
|
||||
kNSDistributedNotificationCenter);
|
||||
}
|
||||
|
||||
void SystemPreferences::UnsubscribeNotification(int request_id) {
|
||||
DoUnsubscribeNotification(request_id, kNSDistributedNotificationCenter);
|
||||
}
|
||||
|
||||
void SystemPreferences::PostLocalNotification(const std::string& name,
|
||||
void SystemPreferences::PostLocalNotification(
|
||||
const std::string& name,
|
||||
const base::DictionaryValue& user_info) {
|
||||
DoPostNotification(name, user_info, kNSNotificationCenter);
|
||||
}
|
||||
|
||||
int SystemPreferences::SubscribeLocalNotification(
|
||||
const std::string& name, const NotificationCallback& callback) {
|
||||
const std::string& name,
|
||||
const NotificationCallback& callback) {
|
||||
return DoSubscribeNotification(name, callback, kNSNotificationCenter);
|
||||
}
|
||||
|
||||
|
@ -56,89 +61,102 @@ void SystemPreferences::UnsubscribeLocalNotification(int request_id) {
|
|||
DoUnsubscribeNotification(request_id, kNSNotificationCenter);
|
||||
}
|
||||
|
||||
void SystemPreferences::PostWorkspaceNotification(const std::string& name,
|
||||
void SystemPreferences::PostWorkspaceNotification(
|
||||
const std::string& name,
|
||||
const base::DictionaryValue& user_info) {
|
||||
DoPostNotification(name, user_info, kNSWorkspaceNotificationCenter);
|
||||
}
|
||||
|
||||
int SystemPreferences::SubscribeWorkspaceNotification(
|
||||
const std::string& name, const NotificationCallback& callback) {
|
||||
return DoSubscribeNotification(name, callback, kNSWorkspaceNotificationCenter);
|
||||
const std::string& name,
|
||||
const NotificationCallback& callback) {
|
||||
return DoSubscribeNotification(name, callback,
|
||||
kNSWorkspaceNotificationCenter);
|
||||
}
|
||||
|
||||
void SystemPreferences::UnsubscribeWorkspaceNotification(int request_id) {
|
||||
DoUnsubscribeNotification(request_id, kNSWorkspaceNotificationCenter);
|
||||
}
|
||||
|
||||
void SystemPreferences::DoPostNotification(const std::string& name,
|
||||
const base::DictionaryValue& user_info, NotificationCenterKind kind) {
|
||||
void SystemPreferences::DoPostNotification(
|
||||
const std::string& name,
|
||||
const base::DictionaryValue& user_info,
|
||||
NotificationCenterKind kind) {
|
||||
NSNotificationCenter* center;
|
||||
switch (kind) {
|
||||
case kNSDistributedNotificationCenter:
|
||||
center = [NSDistributedNotificationCenter defaultCenter]; break;
|
||||
case kNSNotificationCenter:
|
||||
center = [NSNotificationCenter defaultCenter]; break;
|
||||
case kNSWorkspaceNotificationCenter:
|
||||
center = [[NSWorkspace sharedWorkspace] notificationCenter]; break;
|
||||
case kNSDistributedNotificationCenter:
|
||||
center = [NSDistributedNotificationCenter defaultCenter];
|
||||
break;
|
||||
case kNSNotificationCenter:
|
||||
center = [NSNotificationCenter defaultCenter];
|
||||
break;
|
||||
case kNSWorkspaceNotificationCenter:
|
||||
center = [[NSWorkspace sharedWorkspace] notificationCenter];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
[center
|
||||
postNotificationName:base::SysUTF8ToNSString(name)
|
||||
object:nil
|
||||
userInfo:DictionaryValueToNSDictionary(user_info)
|
||||
];
|
||||
[center postNotificationName:base::SysUTF8ToNSString(name)
|
||||
object:nil
|
||||
userInfo:DictionaryValueToNSDictionary(user_info)];
|
||||
}
|
||||
|
||||
int SystemPreferences::DoSubscribeNotification(const std::string& name,
|
||||
const NotificationCallback& callback, NotificationCenterKind kind) {
|
||||
int SystemPreferences::DoSubscribeNotification(
|
||||
const std::string& name,
|
||||
const NotificationCallback& callback,
|
||||
NotificationCenterKind kind) {
|
||||
int request_id = g_next_id++;
|
||||
__block NotificationCallback copied_callback = callback;
|
||||
NSNotificationCenter* center;
|
||||
switch (kind) {
|
||||
case kNSDistributedNotificationCenter:
|
||||
center = [NSDistributedNotificationCenter defaultCenter]; break;
|
||||
case kNSNotificationCenter:
|
||||
center = [NSNotificationCenter defaultCenter]; break;
|
||||
case kNSWorkspaceNotificationCenter:
|
||||
center = [[NSWorkspace sharedWorkspace] notificationCenter]; break;
|
||||
case kNSDistributedNotificationCenter:
|
||||
center = [NSDistributedNotificationCenter defaultCenter];
|
||||
break;
|
||||
case kNSNotificationCenter:
|
||||
center = [NSNotificationCenter defaultCenter];
|
||||
break;
|
||||
case kNSWorkspaceNotificationCenter:
|
||||
center = [[NSWorkspace sharedWorkspace] notificationCenter];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
g_id_map[request_id] = [center
|
||||
addObserverForName:base::SysUTF8ToNSString(name)
|
||||
object:nil
|
||||
queue:nil
|
||||
usingBlock:^(NSNotification* notification) {
|
||||
std::unique_ptr<base::DictionaryValue> user_info =
|
||||
NSDictionaryToDictionaryValue(notification.userInfo);
|
||||
if (user_info) {
|
||||
copied_callback.Run(
|
||||
base::SysNSStringToUTF8(notification.name),
|
||||
*user_info);
|
||||
} else {
|
||||
copied_callback.Run(
|
||||
base::SysNSStringToUTF8(notification.name),
|
||||
base::DictionaryValue());
|
||||
}
|
||||
}
|
||||
];
|
||||
addObserverForName:base::SysUTF8ToNSString(name)
|
||||
object:nil
|
||||
queue:nil
|
||||
usingBlock:^(NSNotification* notification) {
|
||||
std::unique_ptr<base::DictionaryValue> user_info =
|
||||
NSDictionaryToDictionaryValue(notification.userInfo);
|
||||
if (user_info) {
|
||||
copied_callback.Run(
|
||||
base::SysNSStringToUTF8(notification.name), *user_info);
|
||||
} else {
|
||||
copied_callback.Run(
|
||||
base::SysNSStringToUTF8(notification.name),
|
||||
base::DictionaryValue());
|
||||
}
|
||||
}];
|
||||
return request_id;
|
||||
}
|
||||
|
||||
void SystemPreferences::DoUnsubscribeNotification(int request_id, NotificationCenterKind kind) {
|
||||
void SystemPreferences::DoUnsubscribeNotification(int request_id,
|
||||
NotificationCenterKind kind) {
|
||||
auto iter = g_id_map.find(request_id);
|
||||
if (iter != g_id_map.end()) {
|
||||
id observer = iter->second;
|
||||
NSNotificationCenter* center;
|
||||
switch (kind) {
|
||||
case kNSDistributedNotificationCenter:
|
||||
center = [NSDistributedNotificationCenter defaultCenter]; break;
|
||||
case kNSNotificationCenter:
|
||||
center = [NSNotificationCenter defaultCenter]; break;
|
||||
case kNSWorkspaceNotificationCenter:
|
||||
center = [[NSWorkspace sharedWorkspace] notificationCenter]; break;
|
||||
case kNSDistributedNotificationCenter:
|
||||
center = [NSDistributedNotificationCenter defaultCenter];
|
||||
break;
|
||||
case kNSNotificationCenter:
|
||||
center = [NSNotificationCenter defaultCenter];
|
||||
break;
|
||||
case kNSWorkspaceNotificationCenter:
|
||||
center = [[NSWorkspace sharedWorkspace] notificationCenter];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -148,12 +166,13 @@ void SystemPreferences::DoUnsubscribeNotification(int request_id, NotificationCe
|
|||
}
|
||||
|
||||
v8::Local<v8::Value> SystemPreferences::GetUserDefault(
|
||||
const std::string& name, const std::string& type) {
|
||||
const std::string& name,
|
||||
const std::string& type) {
|
||||
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
|
||||
NSString* key = base::SysUTF8ToNSString(name);
|
||||
if (type == "string") {
|
||||
return mate::StringToV8(isolate(),
|
||||
base::SysNSStringToUTF8([defaults stringForKey:key]));
|
||||
return mate::StringToV8(
|
||||
isolate(), base::SysNSStringToUTF8([defaults stringForKey:key]));
|
||||
} else if (type == "boolean") {
|
||||
return v8::Boolean::New(isolate(), [defaults boolForKey:key]);
|
||||
} else if (type == "float") {
|
||||
|
@ -164,7 +183,7 @@ v8::Local<v8::Value> SystemPreferences::GetUserDefault(
|
|||
return v8::Number::New(isolate(), [defaults doubleForKey:key]);
|
||||
} else if (type == "url") {
|
||||
return mate::ConvertToV8(isolate(),
|
||||
net::GURLWithNSURL([defaults URLForKey:key]));
|
||||
net::GURLWithNSURL([defaults URLForKey:key]));
|
||||
} else if (type == "array") {
|
||||
std::unique_ptr<base::ListValue> list =
|
||||
NSArrayToListValue([defaults arrayForKey:key]);
|
||||
|
@ -185,7 +204,7 @@ v8::Local<v8::Value> SystemPreferences::GetUserDefault(
|
|||
void SystemPreferences::RegisterDefaults(mate::Arguments* args) {
|
||||
base::DictionaryValue value;
|
||||
|
||||
if(!args->GetNext(&value)) {
|
||||
if (!args->GetNext(&value)) {
|
||||
args->ThrowError("Invalid userDefault data provided");
|
||||
} else {
|
||||
@try {
|
||||
|
|
|
@ -12,7 +12,8 @@ namespace api {
|
|||
|
||||
bool WebContents::IsFocused() const {
|
||||
auto* view = web_contents()->GetRenderWidgetHostView();
|
||||
if (!view) return false;
|
||||
if (!view)
|
||||
return false;
|
||||
|
||||
if (GetType() != BACKGROUND_PAGE) {
|
||||
auto window = [web_contents()->GetNativeView() window];
|
||||
|
|
|
@ -25,7 +25,8 @@ void AtomBrowserMainParts::PreMainMessageLoopStart() {
|
|||
// Prevent Cocoa from turning command-line arguments into
|
||||
// |-application:openFiles:|, since we already handle them directly.
|
||||
[[NSUserDefaults standardUserDefaults]
|
||||
setObject:@"NO" forKey:@"NSTreatUnknownArgumentsAsOpen"];
|
||||
setObject:@"NO"
|
||||
forKey:@"NSTreatUnknownArgumentsAsOpen"];
|
||||
}
|
||||
|
||||
void AtomBrowserMainParts::FreeAppDelegate() {
|
||||
|
|
|
@ -4,16 +4,16 @@
|
|||
|
||||
#include "atom/browser/auto_updater.h"
|
||||
|
||||
#import <ReactiveCocoa/NSObject+RACPropertySubscribing.h>
|
||||
#import <ReactiveCocoa/RACCommand.h>
|
||||
#import <ReactiveCocoa/RACSignal.h>
|
||||
#import <ReactiveCocoa/NSObject+RACPropertySubscribing.h>
|
||||
#import <Squirrel/Squirrel.h>
|
||||
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/common/native_mate_converters/value_converter.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/time/time.h"
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
#include "base/time/time.h"
|
||||
#include "native_mate/converter.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
|
@ -31,7 +31,7 @@ namespace {
|
|||
bool g_update_available = false;
|
||||
std::string update_url_ = "";
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
std::string AutoUpdater::GetFeedURL() {
|
||||
return update_url_;
|
||||
|
@ -45,7 +45,9 @@ void AutoUpdater::SetFeedURL(mate::Arguments* args) {
|
|||
std::string serverType = "default";
|
||||
if (args->GetNext(&opts)) {
|
||||
if (!opts.Get("url", &feed)) {
|
||||
args->ThrowError("Expected options object to contain a 'url' string property in setFeedUrl call");
|
||||
args->ThrowError(
|
||||
"Expected options object to contain a 'url' string property in "
|
||||
"setFeedUrl call");
|
||||
return;
|
||||
}
|
||||
opts.Get("headers", &requestHeaders);
|
||||
|
@ -57,10 +59,11 @@ void AutoUpdater::SetFeedURL(mate::Arguments* args) {
|
|||
} else if (args->GetNext(&feed)) {
|
||||
args->GetNext(&requestHeaders);
|
||||
} else {
|
||||
args->ThrowError("Expected an options object with a 'url' property to be provided");
|
||||
args->ThrowError(
|
||||
"Expected an options object with a 'url' property to be provided");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Delegate* delegate = GetDelegate();
|
||||
if (!delegate)
|
||||
return;
|
||||
|
@ -72,7 +75,7 @@ void AutoUpdater::SetFeedURL(mate::Arguments* args) {
|
|||
|
||||
for (const auto& it : requestHeaders) {
|
||||
[urlRequest setValue:base::SysUTF8ToNSString(it.second)
|
||||
forHTTPHeaderField:base::SysUTF8ToNSString(it.first)];
|
||||
forHTTPHeaderField:base::SysUTF8ToNSString(it.first)];
|
||||
}
|
||||
|
||||
if (g_updater)
|
||||
|
@ -81,8 +84,10 @@ void AutoUpdater::SetFeedURL(mate::Arguments* args) {
|
|||
// Initialize the SQRLUpdater.
|
||||
@try {
|
||||
if (serverType == "json") {
|
||||
NSString* nsAppVersion = base::SysUTF8ToNSString(atom::Browser::Get()->GetVersion());
|
||||
g_updater = [[SQRLUpdater alloc] initWithUpdateRequest:urlRequest forVersion:nsAppVersion];
|
||||
NSString* nsAppVersion =
|
||||
base::SysUTF8ToNSString(atom::Browser::Get()->GetVersion());
|
||||
g_updater = [[SQRLUpdater alloc] initWithUpdateRequest:urlRequest
|
||||
forVersion:nsAppVersion];
|
||||
} else {
|
||||
// default
|
||||
g_updater = [[SQRLUpdater alloc] initWithUpdateRequest:urlRequest];
|
||||
|
@ -93,16 +98,16 @@ void AutoUpdater::SetFeedURL(mate::Arguments* args) {
|
|||
}
|
||||
|
||||
[[g_updater rac_valuesForKeyPath:@"state" observer:g_updater]
|
||||
subscribeNext:^(NSNumber *stateNumber) {
|
||||
int state = [stateNumber integerValue];
|
||||
// Dispatching the event on main thread.
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (state == SQRLUpdaterStateCheckingForUpdate)
|
||||
delegate->OnCheckingForUpdate();
|
||||
else if (state == SQRLUpdaterStateDownloadingUpdate)
|
||||
delegate->OnUpdateAvailable();
|
||||
});
|
||||
}];
|
||||
subscribeNext:^(NSNumber* stateNumber) {
|
||||
int state = [stateNumber integerValue];
|
||||
// Dispatching the event on main thread.
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (state == SQRLUpdaterStateCheckingForUpdate)
|
||||
delegate->OnCheckingForUpdate();
|
||||
else if (state == SQRLUpdaterStateDownloadingUpdate)
|
||||
delegate->OnUpdateAvailable();
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -111,32 +116,32 @@ void AutoUpdater::CheckForUpdates() {
|
|||
if (!delegate)
|
||||
return;
|
||||
|
||||
[[[[g_updater.checkForUpdatesCommand
|
||||
execute:nil]
|
||||
[[[[g_updater.checkForUpdatesCommand execute:nil]
|
||||
// Send a `nil` after everything...
|
||||
concat:[RACSignal return:nil]]
|
||||
// But only take the first value. If an update is sent, we'll get that.
|
||||
// Otherwise, we'll get our inserted `nil` value.
|
||||
take:1]
|
||||
subscribeNext:^(SQRLDownloadedUpdate *downloadedUpdate) {
|
||||
subscribeNext:^(SQRLDownloadedUpdate* downloadedUpdate) {
|
||||
if (downloadedUpdate) {
|
||||
g_update_available = true;
|
||||
SQRLUpdate* update = downloadedUpdate.update;
|
||||
// There is a new update that has been downloaded.
|
||||
delegate->OnUpdateDownloaded(
|
||||
base::SysNSStringToUTF8(update.releaseNotes),
|
||||
base::SysNSStringToUTF8(update.releaseName),
|
||||
base::Time::FromDoubleT(update.releaseDate.timeIntervalSince1970),
|
||||
base::SysNSStringToUTF8(update.updateURL.absoluteString));
|
||||
base::SysNSStringToUTF8(update.releaseNotes),
|
||||
base::SysNSStringToUTF8(update.releaseName),
|
||||
base::Time::FromDoubleT(update.releaseDate.timeIntervalSince1970),
|
||||
base::SysNSStringToUTF8(update.updateURL.absoluteString));
|
||||
} else {
|
||||
g_update_available = false;
|
||||
// When the completed event is sent with no update, then we know there
|
||||
// is no update available.
|
||||
delegate->OnUpdateNotAvailable();
|
||||
}
|
||||
} error:^(NSError *error) {
|
||||
NSMutableString *failureString =
|
||||
[NSMutableString stringWithString:error.localizedDescription];
|
||||
}
|
||||
error:^(NSError* error) {
|
||||
NSMutableString* failureString =
|
||||
[NSMutableString stringWithString:error.localizedDescription];
|
||||
if (error.localizedFailureReason) {
|
||||
[failureString appendString:@": "];
|
||||
[failureString appendString:error.localizedFailureReason];
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
|
||||
#include "atom/browser/browser.h"
|
||||
|
||||
#include "atom/common/platform_util.h"
|
||||
#include "atom/browser/mac/atom_application.h"
|
||||
#include "atom/browser/mac/atom_application_delegate.h"
|
||||
#include "atom/browser/mac/dict_util.h"
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/window_list.h"
|
||||
#include "atom/common/platform_util.h"
|
||||
#include "base/mac/bundle_locations.h"
|
||||
#include "base/mac/foundation_util.h"
|
||||
#include "base/mac/mac_util.h"
|
||||
|
@ -71,9 +71,9 @@ bool Browser::RemoveAsDefaultProtocolClient(const std::string& protocol,
|
|||
// Apple's defaults first, so we'll use the first option that isn't our bundle
|
||||
CFStringRef other = nil;
|
||||
for (CFIndex i = 0; i < CFArrayGetCount(bundleList); ++i) {
|
||||
other = base::mac::CFCast<CFStringRef>(CFArrayGetValueAtIndex(bundleList,
|
||||
i));
|
||||
if (![identifier isEqualToString: (__bridge NSString *)other]) {
|
||||
other =
|
||||
base::mac::CFCast<CFStringRef>(CFArrayGetValueAtIndex(bundleList, i));
|
||||
if (![identifier isEqualToString:(__bridge NSString*)other]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -92,9 +92,8 @@ bool Browser::SetAsDefaultProtocolClient(const std::string& protocol,
|
|||
return false;
|
||||
|
||||
NSString* protocol_ns = [NSString stringWithUTF8String:protocol.c_str()];
|
||||
OSStatus return_code =
|
||||
LSSetDefaultHandlerForURLScheme(base::mac::NSToCFCast(protocol_ns),
|
||||
base::mac::NSToCFCast(identifier));
|
||||
OSStatus return_code = LSSetDefaultHandlerForURLScheme(
|
||||
base::mac::NSToCFCast(protocol_ns), base::mac::NSToCFCast(identifier));
|
||||
return return_code == noErr;
|
||||
}
|
||||
|
||||
|
@ -111,20 +110,18 @@ bool Browser::IsDefaultProtocolClient(const std::string& protocol,
|
|||
|
||||
CFStringRef bundle =
|
||||
LSCopyDefaultHandlerForURLScheme(base::mac::NSToCFCast(protocol_ns));
|
||||
NSString* bundleId = static_cast<NSString*>(
|
||||
base::mac::CFTypeRefToNSObjectAutorelease(bundle));
|
||||
NSString* bundleId =
|
||||
static_cast<NSString*>(base::mac::CFTypeRefToNSObjectAutorelease(bundle));
|
||||
if (!bundleId)
|
||||
return false;
|
||||
|
||||
// Ensure the comparison is case-insensitive
|
||||
// as LS does not persist the case of the bundle id.
|
||||
NSComparisonResult result =
|
||||
[bundleId caseInsensitiveCompare:identifier];
|
||||
NSComparisonResult result = [bundleId caseInsensitiveCompare:identifier];
|
||||
return result == NSOrderedSame;
|
||||
}
|
||||
|
||||
void Browser::SetAppUserModelID(const base::string16& name) {
|
||||
}
|
||||
void Browser::SetAppUserModelID(const base::string16& name) {}
|
||||
|
||||
bool Browser::SetBadgeCount(int count) {
|
||||
DockSetBadgeText(count != 0 ? base::IntToString(count) : "");
|
||||
|
@ -206,8 +203,8 @@ Browser::LoginItemSettings Browser::GetLoginItemSettings(
|
|||
#if defined(MAS_BUILD)
|
||||
settings.open_at_login = platform_util::GetLoginItemEnabled();
|
||||
#else
|
||||
settings.open_at_login = base::mac::CheckLoginItemStatus(
|
||||
&settings.open_as_hidden);
|
||||
settings.open_at_login =
|
||||
base::mac::CheckLoginItemStatus(&settings.open_as_hidden);
|
||||
settings.restore_state = base::mac::WasLaunchedAsLoginItemRestoreState();
|
||||
settings.opened_at_login = base::mac::WasLaunchedAsLoginOrResumeItem();
|
||||
settings.opened_as_hidden = base::mac::WasLaunchedAsHiddenLoginItem();
|
||||
|
@ -244,18 +241,18 @@ void Browser::DockCancelBounce(int request_id) {
|
|||
}
|
||||
|
||||
void Browser::DockSetBadgeText(const std::string& label) {
|
||||
NSDockTile *tile = [[AtomApplication sharedApplication] dockTile];
|
||||
NSDockTile* tile = [[AtomApplication sharedApplication] dockTile];
|
||||
[tile setBadgeLabel:base::SysUTF8ToNSString(label)];
|
||||
}
|
||||
|
||||
void Browser::DockDownloadFinished(const std::string& filePath) {
|
||||
[[NSDistributedNotificationCenter defaultCenter]
|
||||
postNotificationName: @"com.apple.DownloadFileFinished"
|
||||
object: base::SysUTF8ToNSString(filePath)];
|
||||
postNotificationName:@"com.apple.DownloadFileFinished"
|
||||
object:base::SysUTF8ToNSString(filePath)];
|
||||
}
|
||||
|
||||
std::string Browser::DockGetBadgeText() {
|
||||
NSDockTile *tile = [[AtomApplication sharedApplication] dockTile];
|
||||
NSDockTile* tile = [[AtomApplication sharedApplication] dockTile];
|
||||
return base::SysNSStringToUTF8([tile badgeLabel]);
|
||||
}
|
||||
|
||||
|
@ -263,19 +260,20 @@ void Browser::DockHide() {
|
|||
for (auto* const& window : WindowList::GetWindows())
|
||||
[window->GetNativeWindow() setCanHide:NO];
|
||||
|
||||
ProcessSerialNumber psn = { 0, kCurrentProcess };
|
||||
ProcessSerialNumber psn = {0, kCurrentProcess};
|
||||
TransformProcessType(&psn, kProcessTransformToUIElementApplication);
|
||||
}
|
||||
|
||||
bool Browser::DockIsVisible() {
|
||||
// Because DockShow has a slight delay this may not be true immediately
|
||||
// after that call.
|
||||
return ([[NSRunningApplication currentApplication] activationPolicy] == NSApplicationActivationPolicyRegular);
|
||||
return ([[NSRunningApplication currentApplication] activationPolicy] ==
|
||||
NSApplicationActivationPolicyRegular);
|
||||
}
|
||||
|
||||
void Browser::DockShow() {
|
||||
BOOL active = [[NSRunningApplication currentApplication] isActive];
|
||||
ProcessSerialNumber psn = { 0, kCurrentProcess };
|
||||
ProcessSerialNumber psn = {0, kCurrentProcess};
|
||||
if (active) {
|
||||
// Workaround buggy behavior of TransformProcessType.
|
||||
// http://stackoverflow.com/questions/7596643/
|
||||
|
@ -300,7 +298,8 @@ void Browser::DockShow() {
|
|||
}
|
||||
|
||||
void Browser::DockSetMenu(AtomMenuModel* model) {
|
||||
AtomApplicationDelegate* delegate = (AtomApplicationDelegate*)[NSApp delegate];
|
||||
AtomApplicationDelegate* delegate =
|
||||
(AtomApplicationDelegate*)[NSApp delegate];
|
||||
[delegate setApplicationDockMenu:model];
|
||||
}
|
||||
|
||||
|
@ -329,8 +328,7 @@ void Browser::SetAboutPanelOptions(const base::DictionaryValue& options) {
|
|||
about_panel_options_.Clear();
|
||||
|
||||
// Upper case option keys for orderFrontStandardAboutPanelWithOptions format
|
||||
for (base::DictionaryValue::Iterator iter(options);
|
||||
!iter.IsAtEnd();
|
||||
for (base::DictionaryValue::Iterator iter(options); !iter.IsAtEnd();
|
||||
iter.Advance()) {
|
||||
std::string key = iter.key();
|
||||
std::string value;
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
|
||||
#import "atom/browser/mac/atom_application.h"
|
||||
|
||||
#include "atom/browser/browser.h"
|
||||
#import "atom/browser/mac/atom_application_delegate.h"
|
||||
#include "atom/browser/mac/dict_util.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "base/auto_reset.h"
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
#include "content/public/browser/browser_accessibility_state.h"
|
||||
|
@ -92,23 +92,28 @@ inline void dispatch_sync_main(dispatch_block_t block) {
|
|||
[handoffLock_ unlock];
|
||||
}
|
||||
|
||||
- (void)userActivityWillSave:(NSUserActivity *)userActivity API_AVAILABLE(macosx(10.10)) {
|
||||
- (void)userActivityWillSave:(NSUserActivity*)userActivity
|
||||
API_AVAILABLE(macosx(10.10)) {
|
||||
__block BOOL shouldWait = NO;
|
||||
dispatch_sync_main(^{
|
||||
std::string activity_type(base::SysNSStringToUTF8(userActivity.activityType));
|
||||
std::string activity_type(
|
||||
base::SysNSStringToUTF8(userActivity.activityType));
|
||||
std::unique_ptr<base::DictionaryValue> user_info =
|
||||
atom::NSDictionaryToDictionaryValue(userActivity.userInfo);
|
||||
atom::NSDictionaryToDictionaryValue(userActivity.userInfo);
|
||||
|
||||
atom::Browser* browser = atom::Browser::Get();
|
||||
shouldWait = browser->UpdateUserActivityState(activity_type, *user_info) ? YES : NO;
|
||||
shouldWait =
|
||||
browser->UpdateUserActivityState(activity_type, *user_info) ? YES : NO;
|
||||
});
|
||||
|
||||
if (shouldWait) {
|
||||
[handoffLock_ lock];
|
||||
updateReceived_ = NO;
|
||||
while (!updateReceived_) {
|
||||
BOOL isSignaled = [handoffLock_ waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
|
||||
if (!isSignaled) break;
|
||||
BOOL isSignaled =
|
||||
[handoffLock_ waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
|
||||
if (!isSignaled)
|
||||
break;
|
||||
}
|
||||
[handoffLock_ unlock];
|
||||
}
|
||||
|
@ -116,11 +121,13 @@ inline void dispatch_sync_main(dispatch_block_t block) {
|
|||
[userActivity setNeedsSave:YES];
|
||||
}
|
||||
|
||||
- (void)userActivityWasContinued:(NSUserActivity *)userActivity API_AVAILABLE(macosx(10.10)) {
|
||||
- (void)userActivityWasContinued:(NSUserActivity*)userActivity
|
||||
API_AVAILABLE(macosx(10.10)) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
std::string activity_type(base::SysNSStringToUTF8(userActivity.activityType));
|
||||
std::string activity_type(
|
||||
base::SysNSStringToUTF8(userActivity.activityType));
|
||||
std::unique_ptr<base::DictionaryValue> user_info =
|
||||
atom::NSDictionaryToDictionaryValue(userActivity.userInfo);
|
||||
atom::NSDictionaryToDictionaryValue(userActivity.userInfo);
|
||||
|
||||
atom::Browser* browser = atom::Browser::Get();
|
||||
browser->UserActivityWasContinued(activity_type, *user_info);
|
||||
|
@ -140,27 +147,26 @@ inline void dispatch_sync_main(dispatch_block_t block) {
|
|||
|
||||
- (void)handleURLEvent:(NSAppleEventDescriptor*)event
|
||||
withReplyEvent:(NSAppleEventDescriptor*)replyEvent {
|
||||
NSString* url = [
|
||||
[event paramDescriptorForKeyword:keyDirectObject] stringValue];
|
||||
NSString* url =
|
||||
[[event paramDescriptorForKeyword:keyDirectObject] stringValue];
|
||||
atom::Browser::Get()->OpenURL(base::SysNSStringToUTF8(url));
|
||||
}
|
||||
|
||||
- (bool)voiceOverEnabled {
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
|
||||
[defaults addSuiteNamed:@"com.apple.universalaccess"];
|
||||
[defaults synchronize];
|
||||
|
||||
return [defaults boolForKey:@"voiceOverOnOffKey"];
|
||||
}
|
||||
|
||||
- (void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute {
|
||||
- (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute {
|
||||
// Undocumented attribute that VoiceOver happens to set while running.
|
||||
// Chromium uses this too, even though it's not exactly right.
|
||||
if ([attribute isEqualToString:@"AXEnhancedUserInterface"]) {
|
||||
bool enableAccessibility = ([self voiceOverEnabled] && [value boolValue]);
|
||||
[self updateAccessibilityEnabled:enableAccessibility];
|
||||
}
|
||||
else if ([attribute isEqualToString:@"AXManualAccessibility"]) {
|
||||
} else if ([attribute isEqualToString:@"AXManualAccessibility"]) {
|
||||
[self updateAccessibilityEnabled:[value boolValue]];
|
||||
}
|
||||
return [super accessibilitySetValue:value forAttribute:attribute];
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
#import "atom/browser/mac/atom_application_delegate.h"
|
||||
|
||||
#import "atom/browser/mac/atom_application.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#import "atom/browser/mac/atom_application.h"
|
||||
#include "atom/browser/mac/dict_util.h"
|
||||
#include "base/allocator/allocator_shim.h"
|
||||
#include "base/allocator/features.h"
|
||||
|
@ -46,20 +46,24 @@ static base::mac::ScopedObjCClassSwizzler* g_swizzle_imk_input_session;
|
|||
|
||||
- (void)applicationWillFinishLaunching:(NSNotification*)notify {
|
||||
// Don't add the "Enter Full Screen" menu item automatically.
|
||||
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"NSFullScreenMenuItemEverywhere"];
|
||||
[[NSUserDefaults standardUserDefaults]
|
||||
setBool:NO
|
||||
forKey:@"NSFullScreenMenuItemEverywhere"];
|
||||
|
||||
atom::Browser::Get()->WillFinishLaunching();
|
||||
}
|
||||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification*)notify {
|
||||
NSUserNotification *user_notification = [notify userInfo][(id)@"NSApplicationLaunchUserNotificationKey"];
|
||||
NSUserNotification* user_notification =
|
||||
[notify userInfo][(id) @"NSApplicationLaunchUserNotificationKey"];
|
||||
|
||||
if (user_notification.userInfo != nil) {
|
||||
std::unique_ptr<base::DictionaryValue> launch_info =
|
||||
atom::NSDictionaryToDictionaryValue(user_notification.userInfo);
|
||||
atom::NSDictionaryToDictionaryValue(user_notification.userInfo);
|
||||
atom::Browser::Get()->DidFinishLaunching(*launch_info);
|
||||
} else {
|
||||
std::unique_ptr<base::DictionaryValue> empty_info(new base::DictionaryValue);
|
||||
std::unique_ptr<base::DictionaryValue> empty_info(
|
||||
new base::DictionaryValue);
|
||||
atom::Browser::Get()->DidFinishLaunching(*empty_info);
|
||||
}
|
||||
|
||||
|
@ -81,8 +85,7 @@ static base::mac::ScopedObjCClassSwizzler* g_swizzle_imk_input_session;
|
|||
return nil;
|
||||
}
|
||||
|
||||
- (BOOL)application:(NSApplication*)sender
|
||||
openFile:(NSString*)filename {
|
||||
- (BOOL)application:(NSApplication*)sender openFile:(NSString*)filename {
|
||||
std::string filename_str(base::SysNSStringToUTF8(filename));
|
||||
return atom::Browser::Get()->OpenFile(filename_str) ? YES : NO;
|
||||
}
|
||||
|
@ -94,13 +97,14 @@ static base::mac::ScopedObjCClassSwizzler* g_swizzle_imk_input_session;
|
|||
return flag;
|
||||
}
|
||||
|
||||
- (BOOL)application:(NSApplication*)sender
|
||||
continueUserActivity:(NSUserActivity*)userActivity
|
||||
restorationHandler:(void (^)(NSArray*restorableObjects))restorationHandler
|
||||
API_AVAILABLE(macosx(10.10)) {
|
||||
- (BOOL)application:(NSApplication*)sender
|
||||
continueUserActivity:(NSUserActivity*)userActivity
|
||||
restorationHandler:
|
||||
(void (^)(NSArray* restorableObjects))restorationHandler
|
||||
API_AVAILABLE(macosx(10.10)) {
|
||||
std::string activity_type(base::SysNSStringToUTF8(userActivity.activityType));
|
||||
std::unique_ptr<base::DictionaryValue> user_info =
|
||||
atom::NSDictionaryToDictionaryValue(userActivity.userInfo);
|
||||
atom::NSDictionaryToDictionaryValue(userActivity.userInfo);
|
||||
if (!user_info)
|
||||
return NO;
|
||||
|
||||
|
@ -108,16 +112,20 @@ continueUserActivity:(NSUserActivity*)userActivity
|
|||
return browser->ContinueUserActivity(activity_type, *user_info) ? YES : NO;
|
||||
}
|
||||
|
||||
- (BOOL)application:(NSApplication*)application willContinueUserActivityWithType:(NSString*)userActivityType {
|
||||
- (BOOL)application:(NSApplication*)application
|
||||
willContinueUserActivityWithType:(NSString*)userActivityType {
|
||||
std::string activity_type(base::SysNSStringToUTF8(userActivityType));
|
||||
|
||||
atom::Browser* browser = atom::Browser::Get();
|
||||
return browser->WillContinueUserActivity(activity_type) ? YES : NO;
|
||||
}
|
||||
|
||||
- (void)application:(NSApplication*)application didFailToContinueUserActivityWithType:(NSString*)userActivityType error:(NSError*)error {
|
||||
- (void)application:(NSApplication*)application
|
||||
didFailToContinueUserActivityWithType:(NSString*)userActivityType
|
||||
error:(NSError*)error {
|
||||
std::string activity_type(base::SysNSStringToUTF8(userActivityType));
|
||||
std::string error_message(base::SysNSStringToUTF8([error localizedDescription]));
|
||||
std::string error_message(
|
||||
base::SysNSStringToUTF8([error localizedDescription]));
|
||||
|
||||
atom::Browser* browser = atom::Browser::Get();
|
||||
browser->DidFailToContinueUserActivity(activity_type, error_message);
|
||||
|
|
|
@ -61,14 +61,14 @@ std::unique_ptr<base::ListValue> NSArrayToListValue(NSArray* arr) {
|
|||
return result;
|
||||
}
|
||||
|
||||
NSDictionary* DictionaryValueToNSDictionary(const base::DictionaryValue& value) {
|
||||
NSDictionary* DictionaryValueToNSDictionary(
|
||||
const base::DictionaryValue& value) {
|
||||
std::string json;
|
||||
if (!base::JSONWriter::Write(value, &json))
|
||||
return nil;
|
||||
NSData* jsonData = [NSData dataWithBytes:json.c_str() length:json.length()];
|
||||
id obj = [NSJSONSerialization JSONObjectWithData:jsonData
|
||||
options:0
|
||||
error:nil];
|
||||
id obj =
|
||||
[NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil];
|
||||
if (![obj isKindOfClass:[NSDictionary class]])
|
||||
return nil;
|
||||
return obj;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
// --------------------------------- Interface --------------------------------
|
||||
|
||||
@interface InAppPurchase : NSObject<SKProductsRequestDelegate> {
|
||||
@interface InAppPurchase : NSObject <SKProductsRequestDelegate> {
|
||||
@private
|
||||
in_app_purchase::InAppPurchaseCallback callback_;
|
||||
NSInteger quantity_;
|
||||
|
|
|
@ -22,7 +22,7 @@ using InAppTransactionCallback = base::RepeatingCallback<void(
|
|||
|
||||
} // namespace
|
||||
|
||||
@interface InAppTransactionObserver : NSObject<SKPaymentTransactionObserver> {
|
||||
@interface InAppTransactionObserver : NSObject <SKPaymentTransactionObserver> {
|
||||
@private
|
||||
InAppTransactionCallback callback_;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
// --------------------------------- Interface --------------------------------
|
||||
|
||||
@interface InAppPurchaseProduct : NSObject<SKProductsRequestDelegate> {
|
||||
@interface InAppPurchaseProduct : NSObject <SKProductsRequestDelegate> {
|
||||
@private
|
||||
in_app_purchase::InAppPurchaseProductsCallback callback_;
|
||||
}
|
||||
|
|
|
@ -15,36 +15,33 @@ const NSAutoresizingMaskOptions kDefaultAutoResizingMask =
|
|||
|
||||
@interface DragRegionView : NSView
|
||||
|
||||
@property (assign) NSPoint initialLocation;
|
||||
@property(assign) NSPoint initialLocation;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSWindow ()
|
||||
- (void)performWindowDragWithEvent:(NSEvent *)event;
|
||||
- (void)performWindowDragWithEvent:(NSEvent*)event;
|
||||
@end
|
||||
|
||||
@implementation DragRegionView
|
||||
|
||||
@synthesize initialLocation;
|
||||
|
||||
- (BOOL)mouseDownCanMoveWindow
|
||||
{
|
||||
- (BOOL)mouseDownCanMoveWindow {
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSView *)hitTest:(NSPoint)aPoint
|
||||
{
|
||||
// Pass-through events that don't hit one of the exclusion zones
|
||||
for (NSView *exlusion_zones in [self subviews]) {
|
||||
if ([exlusion_zones hitTest:aPoint])
|
||||
return nil;
|
||||
}
|
||||
- (NSView*)hitTest:(NSPoint)aPoint {
|
||||
// Pass-through events that don't hit one of the exclusion zones
|
||||
for (NSView* exlusion_zones in [self subviews]) {
|
||||
if ([exlusion_zones hitTest:aPoint])
|
||||
return nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)mouseDown:(NSEvent *)event
|
||||
{
|
||||
- (void)mouseDown:(NSEvent*)event {
|
||||
if ([self.window respondsToSelector:@selector(performWindowDragWithEvent)]) {
|
||||
// According to Google, using performWindowDragWithEvent:
|
||||
// does not generate a NSWindowWillMoveNotification. Hence post one.
|
||||
|
@ -65,8 +62,7 @@ const NSAutoresizingMaskOptions kDefaultAutoResizingMask =
|
|||
self.initialLocation = [event locationInWindow];
|
||||
}
|
||||
|
||||
- (void)mouseDragged:(NSEvent *)theEvent
|
||||
{
|
||||
- (void)mouseDragged:(NSEvent*)theEvent {
|
||||
if ([self.window respondsToSelector:@selector(performWindowDragWithEvent)]) {
|
||||
return;
|
||||
}
|
||||
|
@ -86,27 +82,27 @@ const NSAutoresizingMaskOptions kDefaultAutoResizingMask =
|
|||
newOrigin.x = currentLocation.x - self.initialLocation.x;
|
||||
newOrigin.y = currentLocation.y - self.initialLocation.y;
|
||||
|
||||
BOOL inMenuBar = (newOrigin.y + windowSize.height) > (screenFrame.origin.y + screenSize.height);
|
||||
BOOL inMenuBar = (newOrigin.y + windowSize.height) >
|
||||
(screenFrame.origin.y + screenSize.height);
|
||||
BOOL screenAboveMainScreen = false;
|
||||
|
||||
if (inMenuBar) {
|
||||
for (NSScreen *screen in [NSScreen screens]) {
|
||||
for (NSScreen* screen in [NSScreen screens]) {
|
||||
NSRect currentScreenFrame = [screen frame];
|
||||
BOOL isHigher = currentScreenFrame.origin.y > screenFrame.origin.y;
|
||||
|
||||
// If there's another screen that is generally above the current screen,
|
||||
// we'll draw a new rectangle that is just above the current screen. If the
|
||||
// "higher" screen intersects with this rectangle, we'll allow drawing above
|
||||
// the menubar.
|
||||
// we'll draw a new rectangle that is just above the current screen. If
|
||||
// the "higher" screen intersects with this rectangle, we'll allow drawing
|
||||
// above the menubar.
|
||||
if (isHigher) {
|
||||
NSRect aboveScreenRect = NSMakeRect(
|
||||
screenFrame.origin.x,
|
||||
screenFrame.origin.y + screenFrame.size.height - 10,
|
||||
screenFrame.size.width,
|
||||
200
|
||||
);
|
||||
NSRect aboveScreenRect =
|
||||
NSMakeRect(screenFrame.origin.x,
|
||||
screenFrame.origin.y + screenFrame.size.height - 10,
|
||||
screenFrame.size.width, 200);
|
||||
|
||||
BOOL screenAboveIntersects = NSIntersectsRect(currentScreenFrame, aboveScreenRect);
|
||||
BOOL screenAboveIntersects =
|
||||
NSIntersectsRect(currentScreenFrame, aboveScreenRect);
|
||||
|
||||
if (screenAboveIntersects) {
|
||||
screenAboveMainScreen = true;
|
||||
|
@ -118,7 +114,8 @@ const NSAutoresizingMaskOptions kDefaultAutoResizingMask =
|
|||
|
||||
// Don't let window get dragged up under the menu bar
|
||||
if (inMenuBar && !screenAboveMainScreen) {
|
||||
newOrigin.y = screenFrame.origin.y + (screenFrame.size.height - windowFrame.size.height);
|
||||
newOrigin.y = screenFrame.origin.y +
|
||||
(screenFrame.size.height - windowFrame.size.height);
|
||||
}
|
||||
|
||||
// Move the window to the new location
|
||||
|
|
|
@ -150,9 +150,7 @@
|
|||
|
||||
#if !defined(AVAILABLE_MAC_OS_X_VERSION_10_12_AND_LATER)
|
||||
|
||||
enum {
|
||||
NSWindowTabbingModeDisallowed = 2
|
||||
};
|
||||
enum { NSWindowTabbingModeDisallowed = 2 };
|
||||
|
||||
@interface NSWindow (SierraSDK)
|
||||
- (void)setTabbingMode:(NSInteger)mode;
|
||||
|
@ -178,7 +176,9 @@ enum {
|
|||
// Draw edges of rounded rect.
|
||||
NSRect rect = NSInsetRect([self bounds], 1.0, 1.0);
|
||||
CGFloat radius = rect.size.height / 2;
|
||||
NSBezierPath* bezier_path = [NSBezierPath bezierPathWithRoundedRect:rect xRadius:radius yRadius:radius];
|
||||
NSBezierPath* bezier_path = [NSBezierPath bezierPathWithRoundedRect:rect
|
||||
xRadius:radius
|
||||
yRadius:radius];
|
||||
[bezier_path setLineWidth:2.0];
|
||||
[[NSColor grayColor] set];
|
||||
[bezier_path stroke];
|
||||
|
@ -186,12 +186,15 @@ enum {
|
|||
// Fill the rounded rect.
|
||||
rect = NSInsetRect(rect, 2.0, 2.0);
|
||||
radius = rect.size.height / 2;
|
||||
bezier_path = [NSBezierPath bezierPathWithRoundedRect:rect xRadius:radius yRadius:radius];
|
||||
bezier_path = [NSBezierPath bezierPathWithRoundedRect:rect
|
||||
xRadius:radius
|
||||
yRadius:radius];
|
||||
[bezier_path setLineWidth:1.0];
|
||||
[bezier_path addClip];
|
||||
|
||||
// Calculate the progress width.
|
||||
rect.size.width = floor(rect.size.width * ([self doubleValue] / [self maxValue]));
|
||||
rect.size.width =
|
||||
floor(rect.size.width * ([self doubleValue] / [self maxValue]));
|
||||
|
||||
// Fill the progress bar with color blue.
|
||||
[[NSColor colorWithSRGBRed:0.2 green:0.6 blue:1 alpha:1] set];
|
||||
|
@ -202,9 +205,10 @@ enum {
|
|||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
template <>
|
||||
struct Converter<atom::NativeWindowMac::TitleBarStyle> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Handle<v8::Value> val,
|
||||
atom::NativeWindowMac::TitleBarStyle* out) {
|
||||
std::string title_bar_style;
|
||||
if (!ConvertFromV8(isolate, val, &title_bar_style))
|
||||
|
@ -244,10 +248,8 @@ NativeWindowMac::NativeWindowMac(const mate::Dictionary& options,
|
|||
|
||||
NSRect main_screen_rect = [[[NSScreen screens] firstObject] frame];
|
||||
NSRect cocoa_bounds = NSMakeRect(
|
||||
round((NSWidth(main_screen_rect) - width) / 2) ,
|
||||
round((NSHeight(main_screen_rect) - height) / 2),
|
||||
width,
|
||||
height);
|
||||
round((NSWidth(main_screen_rect) - width) / 2),
|
||||
round((NSHeight(main_screen_rect) - height) / 2), width, height);
|
||||
|
||||
bool resizable = true;
|
||||
options.Get(options::kResizable, &resizable);
|
||||
|
@ -301,11 +303,10 @@ NativeWindowMac::NativeWindowMac(const mate::Dictionary& options,
|
|||
styleMask |= NSResizableWindowMask;
|
||||
}
|
||||
|
||||
window_.reset([[AtomNSWindow alloc]
|
||||
initWithContentRect:cocoa_bounds
|
||||
styleMask:styleMask
|
||||
backing:NSBackingStoreBuffered
|
||||
defer:YES]);
|
||||
window_.reset([[AtomNSWindow alloc] initWithContentRect:cocoa_bounds
|
||||
styleMask:styleMask
|
||||
backing:NSBackingStoreBuffered
|
||||
defer:YES]);
|
||||
[window_ setShell:this];
|
||||
[window_ setEnableLargerThanScreen:enable_larger_than_screen()];
|
||||
|
||||
|
@ -325,10 +326,9 @@ NativeWindowMac::NativeWindowMac(const mate::Dictionary& options,
|
|||
if (windowType == "desktop") {
|
||||
[window_ setLevel:kCGDesktopWindowLevel - 1];
|
||||
[window_ setDisableKeyOrMainWindow:YES];
|
||||
[window_ setCollectionBehavior:
|
||||
(NSWindowCollectionBehaviorCanJoinAllSpaces |
|
||||
NSWindowCollectionBehaviorStationary |
|
||||
NSWindowCollectionBehaviorIgnoresCycle)];
|
||||
[window_ setCollectionBehavior:(NSWindowCollectionBehaviorCanJoinAllSpaces |
|
||||
NSWindowCollectionBehaviorStationary |
|
||||
NSWindowCollectionBehaviorIgnoresCycle)];
|
||||
}
|
||||
|
||||
bool focusable;
|
||||
|
@ -405,22 +405,28 @@ NativeWindowMac::NativeWindowMac(const mate::Dictionary& options,
|
|||
// Use an NSEvent monitor to listen for the wheel event.
|
||||
BOOL __block began = NO;
|
||||
wheel_event_monitor_ = [NSEvent
|
||||
addLocalMonitorForEventsMatchingMask:NSScrollWheelMask
|
||||
handler:^(NSEvent* event) {
|
||||
if ([[event window] windowNumber] != [window_ windowNumber])
|
||||
return event;
|
||||
addLocalMonitorForEventsMatchingMask:NSScrollWheelMask
|
||||
handler:^(NSEvent* event) {
|
||||
if ([[event window] windowNumber] !=
|
||||
[window_ windowNumber])
|
||||
return event;
|
||||
|
||||
if (!began && (([event phase] == NSEventPhaseMayBegin) ||
|
||||
([event phase] == NSEventPhaseBegan))) {
|
||||
this->NotifyWindowScrollTouchBegin();
|
||||
began = YES;
|
||||
} else if (began && (([event phase] == NSEventPhaseEnded) ||
|
||||
([event phase] == NSEventPhaseCancelled))) {
|
||||
this->NotifyWindowScrollTouchEnd();
|
||||
began = NO;
|
||||
}
|
||||
return event;
|
||||
}];
|
||||
if (!began && (([event phase] ==
|
||||
NSEventPhaseMayBegin) ||
|
||||
([event phase] ==
|
||||
NSEventPhaseBegan))) {
|
||||
this->NotifyWindowScrollTouchBegin();
|
||||
began = YES;
|
||||
} else if (began &&
|
||||
(([event phase] ==
|
||||
NSEventPhaseEnded) ||
|
||||
([event phase] ==
|
||||
NSEventPhaseCancelled))) {
|
||||
this->NotifyWindowScrollTouchEnd();
|
||||
began = NO;
|
||||
}
|
||||
return event;
|
||||
}];
|
||||
|
||||
// Set maximizable state last to ensure zoom button does not get reset
|
||||
// by calls to other APIs.
|
||||
|
@ -439,9 +445,9 @@ void NativeWindowMac::SetContentView(
|
|||
content_view_ = web_contents->GetView()->GetNativeView();
|
||||
[content_view_ setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
||||
|
||||
// Make sure the bottom corner is rounded for non-modal windows: http://crbug.com/396264.
|
||||
// But do not enable it on OS X 10.9 for transparent window, otherwise a
|
||||
// semi-transparent frame would show.
|
||||
// Make sure the bottom corner is rounded for non-modal windows:
|
||||
// http://crbug.com/396264. But do not enable it on OS X 10.9 for transparent
|
||||
// window, otherwise a semi-transparent frame would show.
|
||||
if (!(transparent() && base::mac::IsOS10_9()) && !is_modal())
|
||||
[[window_ contentView] setWantsLayer:YES];
|
||||
|
||||
|
@ -541,7 +547,8 @@ void NativeWindowMac::Show() {
|
|||
if (is_modal() && parent()) {
|
||||
if ([window_ sheetParent] == nil)
|
||||
[parent()->GetNativeWindow() beginSheet:window_
|
||||
completionHandler:^(NSModalResponse) {}];
|
||||
completionHandler:^(NSModalResponse){
|
||||
}];
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -588,12 +595,13 @@ bool NativeWindowMac::IsEnabled() {
|
|||
|
||||
void NativeWindowMac::SetEnabled(bool enable) {
|
||||
if (enable) {
|
||||
[window_ beginSheet: window_ completionHandler:^(NSModalResponse returnCode) {
|
||||
NSLog(@"modal enabled");
|
||||
return;
|
||||
}];
|
||||
[window_ beginSheet:window_
|
||||
completionHandler:^(NSModalResponse returnCode) {
|
||||
NSLog(@"modal enabled");
|
||||
return;
|
||||
}];
|
||||
} else {
|
||||
[window_ endSheet: [window_ attachedSheet]];
|
||||
[window_ endSheet:[window_ attachedSheet]];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -662,8 +670,7 @@ void NativeWindowMac::SetBounds(const gfx::Rect& bounds, bool animate) {
|
|||
NSRect cocoa_bounds = NSMakeRect(bounds.x(), 0, size.width(), size.height());
|
||||
// Flip coordinates based on the primary screen.
|
||||
NSScreen* screen = [[NSScreen screens] firstObject];
|
||||
cocoa_bounds.origin.y =
|
||||
NSHeight([screen frame]) - size.height() - bounds.y();
|
||||
cocoa_bounds.origin.y = NSHeight([screen frame]) - size.height() - bounds.y();
|
||||
|
||||
[window_ setFrame:cocoa_bounds display:YES animate:animate];
|
||||
}
|
||||
|
@ -702,7 +709,7 @@ void NativeWindowMac::SetContentSizeConstraints(
|
|||
NativeWindow::SetContentSizeConstraints(size_constraints);
|
||||
}
|
||||
|
||||
void NativeWindowMac::MoveTop(){
|
||||
void NativeWindowMac::MoveTop() {
|
||||
[window_ orderWindow:NSWindowAbove relativeTo:0];
|
||||
}
|
||||
void NativeWindowMac::SetResizable(bool resizable) {
|
||||
|
@ -763,11 +770,11 @@ bool NativeWindowMac::IsMaximizable() {
|
|||
}
|
||||
|
||||
void NativeWindowMac::SetFullScreenable(bool fullscreenable) {
|
||||
SetCollectionBehavior(
|
||||
fullscreenable, NSWindowCollectionBehaviorFullScreenPrimary);
|
||||
SetCollectionBehavior(fullscreenable,
|
||||
NSWindowCollectionBehaviorFullScreenPrimary);
|
||||
// On EL Capitan this flag is required to hide fullscreen button.
|
||||
SetCollectionBehavior(
|
||||
!fullscreenable, NSWindowCollectionBehaviorFullScreenAuxiliary);
|
||||
SetCollectionBehavior(!fullscreenable,
|
||||
NSWindowCollectionBehaviorFullScreenAuxiliary);
|
||||
}
|
||||
|
||||
bool NativeWindowMac::IsFullScreenable() {
|
||||
|
@ -783,8 +790,10 @@ bool NativeWindowMac::IsClosable() {
|
|||
return [window_ styleMask] & NSClosableWindowMask;
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetAlwaysOnTop(bool top, const std::string& level,
|
||||
int relativeLevel, std::string* error) {
|
||||
void NativeWindowMac::SetAlwaysOnTop(bool top,
|
||||
const std::string& level,
|
||||
int relativeLevel,
|
||||
std::string* error) {
|
||||
int windowLevel = NSNormalWindowLevel;
|
||||
CGWindowLevel maxWindowLevel = CGWindowLevelForKey(kCGMaximumWindowLevelKey);
|
||||
CGWindowLevel minWindowLevel = CGWindowLevelForKey(kCGMinimumWindowLevelKey);
|
||||
|
@ -814,9 +823,9 @@ void NativeWindowMac::SetAlwaysOnTop(bool top, const std::string& level,
|
|||
if (newLevel >= minWindowLevel && newLevel <= maxWindowLevel) {
|
||||
[window_ setLevel:newLevel];
|
||||
} else {
|
||||
*error = std::string([[NSString stringWithFormat:
|
||||
@"relativeLevel must be between %d and %d", minWindowLevel,
|
||||
maxWindowLevel] UTF8String]);
|
||||
*error = std::string([
|
||||
[NSString stringWithFormat:@"relativeLevel must be between %d and %d",
|
||||
minWindowLevel, maxWindowLevel] UTF8String]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -843,7 +852,8 @@ void NativeWindowMac::SetTitle(const std::string& title) {
|
|||
}
|
||||
|
||||
std::string NativeWindowMac::GetTitle() {
|
||||
return base::SysNSStringToUTF8([window_ title]);;
|
||||
return base::SysNSStringToUTF8([window_ title]);
|
||||
;
|
||||
}
|
||||
|
||||
void NativeWindowMac::FlashFrame(bool flash) {
|
||||
|
@ -855,8 +865,7 @@ void NativeWindowMac::FlashFrame(bool flash) {
|
|||
}
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetSkipTaskbar(bool skip) {
|
||||
}
|
||||
void NativeWindowMac::SetSkipTaskbar(bool skip) {}
|
||||
|
||||
void NativeWindowMac::SetSimpleFullScreen(bool simple_fullscreen) {
|
||||
NSWindow* window = GetNativeWindow();
|
||||
|
@ -870,7 +879,8 @@ void NativeWindowMac::SetSimpleFullScreen(bool simple_fullscreen) {
|
|||
simple_fullscreen_options_ = [NSApp currentSystemPresentationOptions];
|
||||
simple_fullscreen_mask_ = [window styleMask];
|
||||
|
||||
// We can simulate the pre-Lion fullscreen by auto-hiding the dock and menu bar
|
||||
// We can simulate the pre-Lion fullscreen by auto-hiding the dock and menu
|
||||
// bar
|
||||
NSApplicationPresentationOptions options =
|
||||
NSApplicationPresentationAutoHideDock +
|
||||
NSApplicationPresentationAutoHideMenuBar;
|
||||
|
@ -881,12 +891,13 @@ void NativeWindowMac::SetSimpleFullScreen(bool simple_fullscreen) {
|
|||
|
||||
NSRect fullscreenFrame = [window.screen frame];
|
||||
|
||||
if ( !fullscreen_window_title() ) {
|
||||
if (!fullscreen_window_title()) {
|
||||
// Hide the titlebar
|
||||
SetStyleMask(false, NSTitledWindowMask);
|
||||
|
||||
// Resize the window to accomodate the _entire_ screen size
|
||||
fullscreenFrame.size.height -= [[[NSApplication sharedApplication] mainMenu] menuBarHeight];
|
||||
fullscreenFrame.size.height -=
|
||||
[[[NSApplication sharedApplication] mainMenu] menuBarHeight];
|
||||
} else {
|
||||
// No need to hide the title, but we should still hide the window buttons
|
||||
[[window standardWindowButton:NSWindowZoomButton] setHidden:YES];
|
||||
|
@ -894,7 +905,7 @@ void NativeWindowMac::SetSimpleFullScreen(bool simple_fullscreen) {
|
|||
[[window standardWindowButton:NSWindowCloseButton] setHidden:YES];
|
||||
}
|
||||
|
||||
[window setFrame:fullscreenFrame display: YES animate: YES];
|
||||
[window setFrame:fullscreenFrame display:YES animate:YES];
|
||||
|
||||
// Fullscreen windows can't be resized, minimized, maximized, or moved
|
||||
SetMinimizable(false);
|
||||
|
@ -904,7 +915,7 @@ void NativeWindowMac::SetSimpleFullScreen(bool simple_fullscreen) {
|
|||
} else if (!simple_fullscreen && is_simple_fullscreen_) {
|
||||
is_simple_fullscreen_ = false;
|
||||
|
||||
if ( !fullscreen_window_title() ) {
|
||||
if (!fullscreen_window_title()) {
|
||||
// Restore the titlebar
|
||||
SetStyleMask(true, NSTitledWindowMask);
|
||||
} else {
|
||||
|
@ -914,7 +925,7 @@ void NativeWindowMac::SetSimpleFullScreen(bool simple_fullscreen) {
|
|||
[[window standardWindowButton:NSWindowCloseButton] setHidden:NO];
|
||||
}
|
||||
|
||||
[window setFrame:original_frame_ display: YES animate: YES];
|
||||
[window setFrame:original_frame_ display:YES animate:YES];
|
||||
|
||||
[NSApp setPresentationOptions:simple_fullscreen_options_];
|
||||
|
||||
|
@ -946,10 +957,12 @@ void NativeWindowMac::SetKiosk(bool kiosk) {
|
|||
[NSApp setPresentationOptions:options];
|
||||
is_kiosk_ = true;
|
||||
was_fullscreen_ = IsFullscreen();
|
||||
if (!was_fullscreen_) SetFullScreen(true);
|
||||
if (!was_fullscreen_)
|
||||
SetFullScreen(true);
|
||||
} else if (!kiosk && is_kiosk_) {
|
||||
is_kiosk_ = false;
|
||||
if (!was_fullscreen_) SetFullScreen(false);
|
||||
if (!was_fullscreen_)
|
||||
SetFullScreen(false);
|
||||
[NSApp setPresentationOptions:kiosk_options_];
|
||||
}
|
||||
}
|
||||
|
@ -1007,8 +1020,8 @@ void NativeWindowMac::SetIgnoreMouseEvents(bool ignore, bool forward) {
|
|||
}
|
||||
|
||||
void NativeWindowMac::SetContentProtection(bool enable) {
|
||||
[window_ setSharingType:enable ? NSWindowSharingNone
|
||||
: NSWindowSharingReadOnly];
|
||||
[window_
|
||||
setSharingType:enable ? NSWindowSharingNone : NSWindowSharingReadOnly];
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetBrowserView(NativeBrowserView* view) {
|
||||
|
@ -1046,10 +1059,12 @@ gfx::AcceleratedWidget NativeWindowMac::GetAcceleratedWidget() const {
|
|||
return [window_ contentView];
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetProgressBar(double progress, const NativeWindow::ProgressState state) {
|
||||
void NativeWindowMac::SetProgressBar(double progress,
|
||||
const NativeWindow::ProgressState state) {
|
||||
NSDockTile* dock_tile = [NSApp dockTile];
|
||||
|
||||
// For the first time API invoked, we need to create a ContentView in DockTile.
|
||||
// For the first time API invoked, we need to create a ContentView in
|
||||
// DockTile.
|
||||
if (dock_tile.contentView == nullptr) {
|
||||
NSImageView* image_view = [[NSImageView alloc] init];
|
||||
[image_view setImage:[NSApp applicationIconImage]];
|
||||
|
@ -1068,9 +1083,8 @@ void NativeWindowMac::SetProgressBar(double progress, const NativeWindow::Progre
|
|||
[dock_tile.contentView addSubview:progress_indicator];
|
||||
}
|
||||
|
||||
NSProgressIndicator* progress_indicator =
|
||||
static_cast<NSProgressIndicator*>([[[dock_tile contentView] subviews]
|
||||
objectAtIndex:0]);
|
||||
NSProgressIndicator* progress_indicator = static_cast<NSProgressIndicator*>(
|
||||
[[[dock_tile contentView] subviews] objectAtIndex:0]);
|
||||
if (progress < 0) {
|
||||
[progress_indicator setHidden:YES];
|
||||
} else if (progress > 1) {
|
||||
|
@ -1085,8 +1099,7 @@ void NativeWindowMac::SetProgressBar(double progress, const NativeWindow::Progre
|
|||
}
|
||||
|
||||
void NativeWindowMac::SetOverlayIcon(const gfx::Image& overlay,
|
||||
const std::string& description) {
|
||||
}
|
||||
const std::string& description) {}
|
||||
|
||||
void NativeWindowMac::SetVisibleOnAllWorkspaces(bool visible) {
|
||||
SetCollectionBehavior(visible, NSWindowCollectionBehaviorCanJoinAllSpaces);
|
||||
|
@ -1150,7 +1163,8 @@ void NativeWindowMac::SetVibrancy(const std::string& type) {
|
|||
[window_ setBackgroundColor:background_color_before_vibrancy_];
|
||||
[window_ setTitlebarAppearsTransparent:transparency_before_vibrancy_];
|
||||
}
|
||||
if (vibrant_view == nil) return;
|
||||
if (vibrant_view == nil)
|
||||
return;
|
||||
|
||||
[vibrant_view removeFromSuperview];
|
||||
[window_ setVibrantView:nil];
|
||||
|
@ -1171,10 +1185,11 @@ void NativeWindowMac::SetVibrancy(const std::string& type) {
|
|||
NSVisualEffectView* effect_view = (NSVisualEffectView*)vibrant_view;
|
||||
if (effect_view == nil) {
|
||||
effect_view = [[[NSVisualEffectView alloc]
|
||||
initWithFrame: [[window_ contentView] bounds]] autorelease];
|
||||
initWithFrame:[[window_ contentView] bounds]] autorelease];
|
||||
[window_ setVibrantView:(NSView*)effect_view];
|
||||
|
||||
[effect_view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
||||
[effect_view
|
||||
setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
||||
[effect_view setBlendingMode:NSVisualEffectBlendingModeBehindWindow];
|
||||
[effect_view setState:NSVisualEffectStateActive];
|
||||
[[window_ contentView] addSubview:effect_view
|
||||
|
@ -1274,7 +1289,8 @@ gfx::Rect NativeWindowMac::WindowBoundsToContentBounds(
|
|||
}
|
||||
}
|
||||
|
||||
void NativeWindowMac::InternalSetParentWindow(NativeWindow* parent, bool attach) {
|
||||
void NativeWindowMac::InternalSetParentWindow(NativeWindow* parent,
|
||||
bool attach) {
|
||||
if (is_modal())
|
||||
return;
|
||||
|
||||
|
|
|
@ -12,9 +12,8 @@
|
|||
|
||||
namespace atom {
|
||||
|
||||
class MacHelper :
|
||||
public content::BrowserCompositorMacClient,
|
||||
public ui::AcceleratedWidgetMacNSView {
|
||||
class MacHelper : public content::BrowserCompositorMacClient,
|
||||
public ui::AcceleratedWidgetMacNSView {
|
||||
public:
|
||||
explicit MacHelper(OffScreenRenderWidgetHostView* view) : view_(view) {
|
||||
[this->AcceleratedWidgetGetNSView() setWantsLayer:YES];
|
||||
|
@ -53,13 +52,13 @@ class MacHelper :
|
|||
}
|
||||
|
||||
void AcceleratedWidgetGetVSyncParameters(
|
||||
base::TimeTicks* timebase, base::TimeDelta* interval) const override {
|
||||
base::TimeTicks* timebase,
|
||||
base::TimeDelta* interval) const override {
|
||||
*timebase = base::TimeTicks();
|
||||
*interval = base::TimeDelta();
|
||||
}
|
||||
|
||||
void AcceleratedWidgetSwapCompleted() override {
|
||||
}
|
||||
void AcceleratedWidgetSwapCompleted() override {}
|
||||
|
||||
private:
|
||||
OffScreenRenderWidgetHostView* view_;
|
||||
|
@ -74,30 +73,25 @@ OffScreenRenderWidgetHostView::GetAcceleratedWidgetMac() const {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::SetActive(bool active) {
|
||||
}
|
||||
void OffScreenRenderWidgetHostView::SetActive(bool active) {}
|
||||
|
||||
void OffScreenRenderWidgetHostView::ShowDefinitionForSelection() {
|
||||
}
|
||||
void OffScreenRenderWidgetHostView::ShowDefinitionForSelection() {}
|
||||
|
||||
bool OffScreenRenderWidgetHostView::SupportsSpeech() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::SpeakSelection() {
|
||||
}
|
||||
void OffScreenRenderWidgetHostView::SpeakSelection() {}
|
||||
|
||||
bool OffScreenRenderWidgetHostView::IsSpeaking() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void OffScreenRenderWidgetHostView::StopSpeaking() {
|
||||
}
|
||||
void OffScreenRenderWidgetHostView::StopSpeaking() {}
|
||||
|
||||
void OffScreenRenderWidgetHostView::SelectionChanged(
|
||||
const base::string16& text,
|
||||
size_t offset,
|
||||
const gfx::Range& range) {
|
||||
void OffScreenRenderWidgetHostView::SelectionChanged(const base::string16& text,
|
||||
size_t offset,
|
||||
const gfx::Range& range) {
|
||||
if (range.is_empty() || text.empty()) {
|
||||
selected_text_.clear();
|
||||
} else {
|
||||
|
@ -141,4 +135,4 @@ OffScreenRenderWidgetHostView::GetDelegatedFrameHost() const {
|
|||
return browser_compositor_->GetDelegatedFrameHost();
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
} // namespace atom
|
||||
|
|
|
@ -16,12 +16,12 @@
|
|||
NSMutableParagraphStyle* paragraphStyle =
|
||||
[[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease];
|
||||
[paragraphStyle setAlignment:NSCenterTextAlignment];
|
||||
NSDictionary* attributes = [NSDictionary
|
||||
dictionaryWithObject:paragraphStyle
|
||||
forKey:NSParagraphStyleAttributeName];
|
||||
NSDictionary* attributes =
|
||||
[NSDictionary dictionaryWithObject:paragraphStyle
|
||||
forKey:NSParagraphStyleAttributeName];
|
||||
NSAttributedString* text =
|
||||
[[[NSAttributedString alloc] initWithString:str
|
||||
attributes:attributes] autorelease];
|
||||
[[[NSAttributedString alloc] initWithString:str attributes:attributes]
|
||||
autorelease];
|
||||
NSRect frame = NSMakeRect(0, (self.frame.size.height - text.size.height) / 2,
|
||||
self.frame.size.width, text.size.height);
|
||||
[str drawInRect:frame withAttributes:attributes];
|
||||
|
|
|
@ -14,16 +14,13 @@ void SetPlatformAccelerator(ui::Accelerator* accelerator) {
|
|||
unichar character;
|
||||
unichar characterIgnoringModifiers;
|
||||
|
||||
NSUInteger modifiers =
|
||||
(accelerator->IsCtrlDown() ? NSControlKeyMask : 0) |
|
||||
(accelerator->IsCmdDown() ? NSCommandKeyMask : 0) |
|
||||
(accelerator->IsAltDown() ? NSAlternateKeyMask : 0) |
|
||||
(accelerator->IsShiftDown() ? NSShiftKeyMask : 0);
|
||||
NSUInteger modifiers = (accelerator->IsCtrlDown() ? NSControlKeyMask : 0) |
|
||||
(accelerator->IsCmdDown() ? NSCommandKeyMask : 0) |
|
||||
(accelerator->IsAltDown() ? NSAlternateKeyMask : 0) |
|
||||
(accelerator->IsShiftDown() ? NSShiftKeyMask : 0);
|
||||
|
||||
ui::MacKeyCodeForWindowsKeyCode(accelerator->key_code(),
|
||||
modifiers,
|
||||
&character,
|
||||
&characterIgnoringModifiers);
|
||||
ui::MacKeyCodeForWindowsKeyCode(accelerator->key_code(), modifiers,
|
||||
&character, &characterIgnoringModifiers);
|
||||
|
||||
if (character != characterIgnoringModifiers) {
|
||||
if (isdigit(characterIgnoringModifiers)) {
|
||||
|
|
|
@ -24,14 +24,14 @@
|
|||
}
|
||||
|
||||
- (id)initWithCallback:(const certificate_trust::ShowTrustCallback&)callback
|
||||
panel:(SFCertificateTrustPanel*)panel
|
||||
cert:(const scoped_refptr<net::X509Certificate>&)cert
|
||||
trust:(SecTrustRef)trust
|
||||
certChain:(CFArrayRef)certChain
|
||||
secPolicy:(SecPolicyRef)secPolicy;
|
||||
panel:(SFCertificateTrustPanel*)panel
|
||||
cert:(const scoped_refptr<net::X509Certificate>&)cert
|
||||
trust:(SecTrustRef)trust
|
||||
certChain:(CFArrayRef)certChain
|
||||
secPolicy:(SecPolicyRef)secPolicy;
|
||||
|
||||
- (void)panelDidEnd:(NSWindow*)sheet
|
||||
returnCode:(int)returnCode
|
||||
returnCode:(int)returnCode
|
||||
contextInfo:(void*)contextInfo;
|
||||
|
||||
@end
|
||||
|
@ -48,11 +48,11 @@
|
|||
}
|
||||
|
||||
- (id)initWithCallback:(const certificate_trust::ShowTrustCallback&)callback
|
||||
panel:(SFCertificateTrustPanel*)panel
|
||||
cert:(const scoped_refptr<net::X509Certificate>&)cert
|
||||
trust:(SecTrustRef)trust
|
||||
certChain:(CFArrayRef)certChain
|
||||
secPolicy:(SecPolicyRef)secPolicy {
|
||||
panel:(SFCertificateTrustPanel*)panel
|
||||
cert:(const scoped_refptr<net::X509Certificate>&)cert
|
||||
trust:(SecTrustRef)trust
|
||||
certChain:(CFArrayRef)certChain
|
||||
secPolicy:(SecPolicyRef)secPolicy {
|
||||
if ((self = [super init])) {
|
||||
callback_ = callback;
|
||||
panel_ = panel;
|
||||
|
@ -66,7 +66,7 @@
|
|||
}
|
||||
|
||||
- (void)panelDidEnd:(NSWindow*)sheet
|
||||
returnCode:(int)returnCode
|
||||
returnCode:(int)returnCode
|
||||
contextInfo:(void*)contextInfo {
|
||||
auto* cert_db = net::CertDatabase::GetInstance();
|
||||
// This forces Chromium to reload the certificate since it might be trusted
|
||||
|
@ -92,24 +92,22 @@ void ShowCertificateTrust(atom::NativeWindow* parent_window,
|
|||
SecTrustRef trust = nullptr;
|
||||
SecTrustCreateWithCertificates(cert_chain, sec_policy, &trust);
|
||||
|
||||
NSWindow* window = parent_window ?
|
||||
parent_window->GetNativeWindow() :
|
||||
nil;
|
||||
NSWindow* window = parent_window ? parent_window->GetNativeWindow() : nil;
|
||||
auto msg = base::SysUTF8ToNSString(message);
|
||||
|
||||
auto panel = [[SFCertificateTrustPanel alloc] init];
|
||||
auto delegate = [[TrustDelegate alloc] initWithCallback:callback
|
||||
panel:panel
|
||||
cert:cert
|
||||
trust:trust
|
||||
certChain:cert_chain
|
||||
secPolicy:sec_policy];
|
||||
panel:panel
|
||||
cert:cert
|
||||
trust:trust
|
||||
certChain:cert_chain
|
||||
secPolicy:sec_policy];
|
||||
[panel beginSheetForWindow:window
|
||||
modalDelegate:delegate
|
||||
didEndSelector:@selector(panelDidEnd:returnCode:contextInfo:)
|
||||
contextInfo:nil
|
||||
trust:trust
|
||||
message:msg];
|
||||
modalDelegate:delegate
|
||||
didEndSelector:@selector(panelDidEnd:returnCode:contextInfo:)
|
||||
contextInfo:nil
|
||||
trust:trust
|
||||
message:msg];
|
||||
}
|
||||
|
||||
} // namespace certificate_trust
|
||||
|
|
|
@ -14,11 +14,11 @@
|
|||
|
||||
if (inColorString) {
|
||||
NSScanner* scanner = [NSScanner scannerWithString:inColorString];
|
||||
(void) [scanner scanHexInt:&colorCode]; // ignore error
|
||||
(void)[scanner scanHexInt:&colorCode]; // ignore error
|
||||
}
|
||||
redByte = (unsigned char)(colorCode >> 16);
|
||||
greenByte = (unsigned char)(colorCode >> 8);
|
||||
blueByte = (unsigned char)(colorCode); // masks off high bits
|
||||
blueByte = (unsigned char)(colorCode); // masks off high bits
|
||||
|
||||
return [NSColor colorWithCalibratedRed:(CGFloat)redByte / 0xff
|
||||
green:(CGFloat)greenByte / 0xff
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/ui/cocoa/NSString+ANSI.h"
|
||||
#include "atom/browser/ui/cocoa/NSColor+Hex.h"
|
||||
#include "atom/browser/ui/cocoa/NSString+ANSI.h"
|
||||
#include "base/mac/scoped_nsobject.h"
|
||||
|
||||
@implementation NSMutableDictionary (ANSI)
|
||||
|
@ -22,7 +22,8 @@
|
|||
case 0:
|
||||
[self removeAllObjects];
|
||||
// remove italic and bold from font here
|
||||
if (font) self[NSFontAttributeName] = font;
|
||||
if (font)
|
||||
self[NSFontAttributeName] = font;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
@ -30,34 +31,42 @@
|
|||
bold = (code == 1);
|
||||
break;
|
||||
|
||||
// case 3: italic
|
||||
// case 23: italic off
|
||||
// case 4: underlined
|
||||
// case 24: underlined off
|
||||
// case 3: italic
|
||||
// case 23: italic off
|
||||
// case 4: underlined
|
||||
// case 24: underlined off
|
||||
|
||||
case 30:
|
||||
self[NSForegroundColorAttributeName] = [NSColor colorWithHexColorString:bold ? @"7f7f7f" : @"000000"];
|
||||
self[NSForegroundColorAttributeName] =
|
||||
[NSColor colorWithHexColorString:bold ? @"7f7f7f" : @"000000"];
|
||||
break;
|
||||
case 31:
|
||||
self[NSForegroundColorAttributeName] = [NSColor colorWithHexColorString:bold ? @"cd0000" : @"ff0000"];
|
||||
self[NSForegroundColorAttributeName] =
|
||||
[NSColor colorWithHexColorString:bold ? @"cd0000" : @"ff0000"];
|
||||
break;
|
||||
case 32:
|
||||
self[NSForegroundColorAttributeName] = [NSColor colorWithHexColorString:bold ? @"00cd00" : @"00ff00"];
|
||||
self[NSForegroundColorAttributeName] =
|
||||
[NSColor colorWithHexColorString:bold ? @"00cd00" : @"00ff00"];
|
||||
break;
|
||||
case 33:
|
||||
self[NSForegroundColorAttributeName] = [NSColor colorWithHexColorString:bold ? @"cdcd00" : @"ffff00"];
|
||||
self[NSForegroundColorAttributeName] =
|
||||
[NSColor colorWithHexColorString:bold ? @"cdcd00" : @"ffff00"];
|
||||
break;
|
||||
case 34:
|
||||
self[NSForegroundColorAttributeName] = [NSColor colorWithHexColorString:bold ? @"0000ee" : @"5c5cff"];
|
||||
self[NSForegroundColorAttributeName] =
|
||||
[NSColor colorWithHexColorString:bold ? @"0000ee" : @"5c5cff"];
|
||||
break;
|
||||
case 35:
|
||||
self[NSForegroundColorAttributeName] = [NSColor colorWithHexColorString:bold ? @"cd00cd" : @"ff00ff"];
|
||||
self[NSForegroundColorAttributeName] =
|
||||
[NSColor colorWithHexColorString:bold ? @"cd00cd" : @"ff00ff"];
|
||||
break;
|
||||
case 36:
|
||||
self[NSForegroundColorAttributeName] = [NSColor colorWithHexColorString:bold ? @"00cdcd" : @"00ffff"];
|
||||
self[NSForegroundColorAttributeName] =
|
||||
[NSColor colorWithHexColorString:bold ? @"00cdcd" : @"00ffff"];
|
||||
break;
|
||||
case 37:
|
||||
self[NSForegroundColorAttributeName] = [NSColor colorWithHexColorString:bold ? @"e5e5e5" : @"ffffff"];
|
||||
self[NSForegroundColorAttributeName] =
|
||||
[NSColor colorWithHexColorString:bold ? @"e5e5e5" : @"ffffff"];
|
||||
break;
|
||||
|
||||
case 39:
|
||||
|
@ -65,28 +74,36 @@
|
|||
break;
|
||||
|
||||
case 40:
|
||||
self[NSBackgroundColorAttributeName] = [NSColor colorWithHexColorString:@"7f7f7f"];
|
||||
self[NSBackgroundColorAttributeName] =
|
||||
[NSColor colorWithHexColorString:@"7f7f7f"];
|
||||
break;
|
||||
case 41:
|
||||
self[NSBackgroundColorAttributeName] = [NSColor colorWithHexColorString:@"cd0000"];
|
||||
self[NSBackgroundColorAttributeName] =
|
||||
[NSColor colorWithHexColorString:@"cd0000"];
|
||||
break;
|
||||
case 42:
|
||||
self[NSBackgroundColorAttributeName] = [NSColor colorWithHexColorString:@"00cd00"];
|
||||
self[NSBackgroundColorAttributeName] =
|
||||
[NSColor colorWithHexColorString:@"00cd00"];
|
||||
break;
|
||||
case 43:
|
||||
self[NSBackgroundColorAttributeName] = [NSColor colorWithHexColorString:@"cdcd00"];
|
||||
self[NSBackgroundColorAttributeName] =
|
||||
[NSColor colorWithHexColorString:@"cdcd00"];
|
||||
break;
|
||||
case 44:
|
||||
self[NSBackgroundColorAttributeName] = [NSColor colorWithHexColorString:@"0000ee"];
|
||||
self[NSBackgroundColorAttributeName] =
|
||||
[NSColor colorWithHexColorString:@"0000ee"];
|
||||
break;
|
||||
case 45:
|
||||
self[NSBackgroundColorAttributeName] = [NSColor colorWithHexColorString:@"cd00cd"];
|
||||
self[NSBackgroundColorAttributeName] =
|
||||
[NSColor colorWithHexColorString:@"cd00cd"];
|
||||
break;
|
||||
case 46:
|
||||
self[NSBackgroundColorAttributeName] = [NSColor colorWithHexColorString:@"00cdcd"];
|
||||
self[NSBackgroundColorAttributeName] =
|
||||
[NSColor colorWithHexColorString:@"00cdcd"];
|
||||
break;
|
||||
case 47:
|
||||
self[NSBackgroundColorAttributeName] = [NSColor colorWithHexColorString:@"e5e5e5"];
|
||||
self[NSBackgroundColorAttributeName] =
|
||||
[NSColor colorWithHexColorString:@"e5e5e5"];
|
||||
break;
|
||||
|
||||
case 49:
|
||||
|
@ -119,7 +136,8 @@
|
|||
initWithString:parts.firstObject
|
||||
attributes:nil] autorelease]];
|
||||
|
||||
for (NSString* part in [parts subarrayWithRange:NSMakeRange(1, parts.count - 1)]) {
|
||||
for (NSString* part in
|
||||
[parts subarrayWithRange:NSMakeRange(1, parts.count - 1)]) {
|
||||
if (part.length == 0)
|
||||
continue;
|
||||
|
||||
|
@ -127,16 +145,18 @@
|
|||
NSString* text = sequence.lastObject;
|
||||
|
||||
if (sequence.count < 2) {
|
||||
[result appendAttributedString:[[[NSAttributedString alloc]
|
||||
initWithString:text
|
||||
attributes:attributes] autorelease]];
|
||||
[result
|
||||
appendAttributedString:[[[NSAttributedString alloc]
|
||||
initWithString:text
|
||||
attributes:attributes] autorelease]];
|
||||
} else if (sequence.count >= 2) {
|
||||
text = [[sequence subarrayWithRange:NSMakeRange(1, sequence.count - 1)]
|
||||
componentsJoinedByString:@"m"];
|
||||
componentsJoinedByString:@"m"];
|
||||
[attributes modifyAttributesForANSICodes:sequence[0]];
|
||||
[result appendAttributedString:[[[NSAttributedString alloc]
|
||||
initWithString:text
|
||||
attributes:attributes] autorelease]];
|
||||
[result
|
||||
appendAttributedString:[[[NSAttributedString alloc]
|
||||
initWithString:text
|
||||
attributes:attributes] autorelease]];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
#import <Security/Security.h>
|
||||
#import <dlfcn.h>
|
||||
#import <sys/param.h>
|
||||
#import <sys/mount.h>
|
||||
#import <sys/param.h>
|
||||
|
||||
#import "atom/browser/browser.h"
|
||||
|
||||
|
@ -24,22 +24,29 @@ bool AtomBundleMover::Move(mate::Arguments* args) {
|
|||
NSString* bundlePath = [[NSBundle mainBundle] bundlePath];
|
||||
|
||||
// Skip if the application is already in the Applications folder
|
||||
if (IsInApplicationsFolder(bundlePath)) return true;
|
||||
if (IsInApplicationsFolder(bundlePath))
|
||||
return true;
|
||||
|
||||
NSFileManager* fileManager = [NSFileManager defaultManager];
|
||||
|
||||
NSString* diskImageDevice = ContainingDiskImageDevice(bundlePath);
|
||||
|
||||
NSString *applicationsDirectory = [[NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSLocalDomainMask, true) lastObject] stringByResolvingSymlinksInPath];
|
||||
NSString *bundleName = [bundlePath lastPathComponent];
|
||||
NSString *destinationPath = [applicationsDirectory stringByAppendingPathComponent:bundleName];
|
||||
NSString* applicationsDirectory = [[NSSearchPathForDirectoriesInDomains(
|
||||
NSApplicationDirectory, NSLocalDomainMask, true) lastObject]
|
||||
stringByResolvingSymlinksInPath];
|
||||
NSString* bundleName = [bundlePath lastPathComponent];
|
||||
NSString* destinationPath =
|
||||
[applicationsDirectory stringByAppendingPathComponent:bundleName];
|
||||
|
||||
// Check if we can write to the applications directory
|
||||
// and then make sure that if the app already exists we can overwrite it
|
||||
bool needAuthorization = ![fileManager isWritableFileAtPath:applicationsDirectory]
|
||||
| ([fileManager fileExistsAtPath:destinationPath] && ![fileManager isWritableFileAtPath:destinationPath]);
|
||||
bool needAuthorization =
|
||||
![fileManager isWritableFileAtPath:applicationsDirectory] |
|
||||
([fileManager fileExistsAtPath:destinationPath] &&
|
||||
![fileManager isWritableFileAtPath:destinationPath]);
|
||||
|
||||
// Activate app -- work-around for focus issues related to "scary file from internet" OS dialog.
|
||||
// Activate app -- work-around for focus issues related to "scary file from
|
||||
// internet" OS dialog.
|
||||
if (![NSApp isActive]) {
|
||||
[NSApp activateIgnoringOtherApps:true];
|
||||
}
|
||||
|
@ -48,14 +55,15 @@ bool AtomBundleMover::Move(mate::Arguments* args) {
|
|||
if (needAuthorization) {
|
||||
bool authorizationCanceled;
|
||||
|
||||
if (!AuthorizedInstall(bundlePath, destinationPath, &authorizationCanceled)) {
|
||||
if (!AuthorizedInstall(bundlePath, destinationPath,
|
||||
&authorizationCanceled)) {
|
||||
if (authorizationCanceled) {
|
||||
// User rejected the authorization request
|
||||
args->ThrowError("User rejected the authorization request");
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
args->ThrowError("Failed to copy to applications directory even with authorization");
|
||||
} else {
|
||||
args->ThrowError(
|
||||
"Failed to copy to applications directory even with authorization");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -65,11 +73,16 @@ bool AtomBundleMover::Move(mate::Arguments* args) {
|
|||
// But first, make sure that it's not running
|
||||
if (IsApplicationAtPathRunning(destinationPath)) {
|
||||
// Give the running app focus and terminate myself
|
||||
[[NSTask launchedTaskWithLaunchPath:@"/usr/bin/open" arguments:[NSArray arrayWithObject:destinationPath]] waitUntilExit];
|
||||
[[NSTask
|
||||
launchedTaskWithLaunchPath:@"/usr/bin/open"
|
||||
arguments:[NSArray
|
||||
arrayWithObject:destinationPath]]
|
||||
waitUntilExit];
|
||||
atom::Browser::Get()->Quit();
|
||||
return true;
|
||||
} else {
|
||||
if (!Trash([applicationsDirectory stringByAppendingPathComponent:bundleName])) {
|
||||
if (!Trash([applicationsDirectory
|
||||
stringByAppendingPathComponent:bundleName])) {
|
||||
args->ThrowError("Failed to delete existing application");
|
||||
return false;
|
||||
}
|
||||
|
@ -77,15 +90,17 @@ bool AtomBundleMover::Move(mate::Arguments* args) {
|
|||
}
|
||||
|
||||
if (!CopyBundle(bundlePath, destinationPath)) {
|
||||
args->ThrowError("Failed to copy current bundle to the applications folder");
|
||||
args->ThrowError(
|
||||
"Failed to copy current bundle to the applications folder");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Trash the original app. It's okay if this fails.
|
||||
// NOTE: This final delete does not work if the source bundle is in a network mounted volume.
|
||||
// Calling rm or file manager's delete method doesn't work either. It's unlikely to happen
|
||||
// but it'd be great if someone could fix this.
|
||||
// NOTE: This final delete does not work if the source bundle is in a network
|
||||
// mounted volume.
|
||||
// Calling rm or file manager's delete method doesn't work either. It's
|
||||
// unlikely to happen but it'd be great if someone could fix this.
|
||||
if (diskImageDevice == nil && !DeleteOrTrash(bundlePath)) {
|
||||
// Could not delete original but we just don't care
|
||||
}
|
||||
|
@ -93,11 +108,15 @@ bool AtomBundleMover::Move(mate::Arguments* args) {
|
|||
// Relaunch.
|
||||
Relaunch(destinationPath);
|
||||
|
||||
// Launched from within a disk image? -- unmount (if no files are open after 5 seconds,
|
||||
// otherwise leave it mounted).
|
||||
// Launched from within a disk image? -- unmount (if no files are open after 5
|
||||
// seconds, otherwise leave it mounted).
|
||||
if (diskImageDevice) {
|
||||
NSString *script = [NSString stringWithFormat:@"(/bin/sleep 5 && /usr/bin/hdiutil detach %@) &", ShellQuotedString(diskImageDevice)];
|
||||
[NSTask launchedTaskWithLaunchPath:@"/bin/sh" arguments:[NSArray arrayWithObjects:@"-c", script, nil]];
|
||||
NSString* script = [NSString
|
||||
stringWithFormat:@"(/bin/sleep 5 && /usr/bin/hdiutil detach %@) &",
|
||||
ShellQuotedString(diskImageDevice)];
|
||||
[NSTask launchedTaskWithLaunchPath:@"/bin/sh"
|
||||
arguments:[NSArray arrayWithObjects:@"-c", script,
|
||||
nil]];
|
||||
}
|
||||
|
||||
atom::Browser::Get()->Quit();
|
||||
|
@ -106,18 +125,22 @@ bool AtomBundleMover::Move(mate::Arguments* args) {
|
|||
}
|
||||
|
||||
bool AtomBundleMover::IsCurrentAppInApplicationsFolder() {
|
||||
return IsInApplicationsFolder([[NSBundle mainBundle] bundlePath]);
|
||||
return IsInApplicationsFolder([[NSBundle mainBundle] bundlePath]);
|
||||
}
|
||||
|
||||
bool AtomBundleMover::IsInApplicationsFolder(NSString* bundlePath) {
|
||||
// Check all the normal Application directories
|
||||
NSArray* applicationDirs = NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSAllDomainsMask, true);
|
||||
NSArray* applicationDirs = NSSearchPathForDirectoriesInDomains(
|
||||
NSApplicationDirectory, NSAllDomainsMask, true);
|
||||
for (NSString* appDir in applicationDirs) {
|
||||
if ([bundlePath hasPrefix:appDir]) return true;
|
||||
if ([bundlePath hasPrefix:appDir])
|
||||
return true;
|
||||
}
|
||||
|
||||
// Also, handle the case that the user has some other Application directory (perhaps on a separate data partition).
|
||||
if ([[bundlePath pathComponents] containsObject:@"Applications"]) return true;
|
||||
// Also, handle the case that the user has some other Application directory
|
||||
// (perhaps on a separate data partition).
|
||||
if ([[bundlePath pathComponents] containsObject:@"Applications"])
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -126,43 +149,61 @@ NSString* AtomBundleMover::ContainingDiskImageDevice(NSString* bundlePath) {
|
|||
NSString* containingPath = [bundlePath stringByDeletingLastPathComponent];
|
||||
|
||||
struct statfs fs;
|
||||
if (statfs([containingPath fileSystemRepresentation], &fs) || (fs.f_flags & MNT_ROOTFS))
|
||||
if (statfs([containingPath fileSystemRepresentation], &fs) ||
|
||||
(fs.f_flags & MNT_ROOTFS))
|
||||
return nil;
|
||||
|
||||
NSString *device = [[NSFileManager defaultManager] stringWithFileSystemRepresentation:fs.f_mntfromname length:strlen(fs.f_mntfromname)];
|
||||
NSString* device = [[NSFileManager defaultManager]
|
||||
stringWithFileSystemRepresentation:fs.f_mntfromname
|
||||
length:strlen(fs.f_mntfromname)];
|
||||
|
||||
NSTask *hdiutil = [[[NSTask alloc] init] autorelease];
|
||||
NSTask* hdiutil = [[[NSTask alloc] init] autorelease];
|
||||
[hdiutil setLaunchPath:@"/usr/bin/hdiutil"];
|
||||
[hdiutil setArguments:[NSArray arrayWithObjects:@"info", @"-plist", nil]];
|
||||
[hdiutil setStandardOutput:[NSPipe pipe]];
|
||||
[hdiutil launch];
|
||||
[hdiutil waitUntilExit];
|
||||
|
||||
NSData *data = [[[hdiutil standardOutput] fileHandleForReading] readDataToEndOfFile];
|
||||
NSData* data =
|
||||
[[[hdiutil standardOutput] fileHandleForReading] readDataToEndOfFile];
|
||||
|
||||
NSDictionary *info = nil;
|
||||
NSDictionary* info = nil;
|
||||
if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_5) {
|
||||
info = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListImmutable format:NULL error:NULL];
|
||||
info = [NSPropertyListSerialization
|
||||
propertyListWithData:data
|
||||
options:NSPropertyListImmutable
|
||||
format:NULL
|
||||
error:NULL];
|
||||
} else {
|
||||
info = [NSPropertyListSerialization propertyListFromData:data mutabilityOption:NSPropertyListImmutable format:NULL errorDescription:NULL];
|
||||
info = [NSPropertyListSerialization
|
||||
propertyListFromData:data
|
||||
mutabilityOption:NSPropertyListImmutable
|
||||
format:NULL
|
||||
errorDescription:NULL];
|
||||
}
|
||||
|
||||
if (![info isKindOfClass:[NSDictionary class]]) return nil;
|
||||
if (![info isKindOfClass:[NSDictionary class]])
|
||||
return nil;
|
||||
|
||||
NSArray *images = (NSArray *)[info objectForKey:@"images"];
|
||||
if (![images isKindOfClass:[NSArray class]]) return nil;
|
||||
NSArray* images = (NSArray*)[info objectForKey:@"images"];
|
||||
if (![images isKindOfClass:[NSArray class]])
|
||||
return nil;
|
||||
|
||||
for (NSDictionary *image in images) {
|
||||
if (![image isKindOfClass:[NSDictionary class]]) return nil;
|
||||
for (NSDictionary* image in images) {
|
||||
if (![image isKindOfClass:[NSDictionary class]])
|
||||
return nil;
|
||||
|
||||
id systemEntities = [image objectForKey:@"system-entities"];
|
||||
if (![systemEntities isKindOfClass:[NSArray class]]) return nil;
|
||||
if (![systemEntities isKindOfClass:[NSArray class]])
|
||||
return nil;
|
||||
|
||||
for (NSDictionary *systemEntity in systemEntities) {
|
||||
if (![systemEntity isKindOfClass:[NSDictionary class]]) return nil;
|
||||
for (NSDictionary* systemEntity in systemEntities) {
|
||||
if (![systemEntity isKindOfClass:[NSDictionary class]])
|
||||
return nil;
|
||||
|
||||
NSString *devEntry = [systemEntity objectForKey:@"dev-entry"];
|
||||
if (![devEntry isKindOfClass:[NSString class]]) return nil;
|
||||
NSString* devEntry = [systemEntity objectForKey:@"dev-entry"];
|
||||
if (![devEntry isKindOfClass:[NSString class]])
|
||||
return nil;
|
||||
|
||||
if ([devEntry isEqualToString:device])
|
||||
return device;
|
||||
|
@ -172,72 +213,99 @@ NSString* AtomBundleMover::ContainingDiskImageDevice(NSString* bundlePath) {
|
|||
return nil;
|
||||
}
|
||||
|
||||
bool AtomBundleMover::AuthorizedInstall(NSString* srcPath, NSString* dstPath, bool* canceled) {
|
||||
if (canceled) *canceled = false;
|
||||
bool AtomBundleMover::AuthorizedInstall(NSString* srcPath,
|
||||
NSString* dstPath,
|
||||
bool* canceled) {
|
||||
if (canceled)
|
||||
*canceled = false;
|
||||
|
||||
// Make sure that the destination path is an app bundle. We're essentially running 'sudo rm -rf'
|
||||
// so we really don't want to screw this up.
|
||||
if (![[dstPath pathExtension] isEqualToString:@"app"]) return false;
|
||||
// Make sure that the destination path is an app bundle. We're essentially
|
||||
// running 'sudo rm -rf' so we really don't want to screw this up.
|
||||
if (![[dstPath pathExtension] isEqualToString:@"app"])
|
||||
return false;
|
||||
|
||||
// Do some more checks
|
||||
if ([[dstPath stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] length] == 0) return false;
|
||||
if ([[srcPath stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] length] == 0) return false;
|
||||
if ([[dstPath stringByTrimmingCharactersInSet:[NSCharacterSet
|
||||
whitespaceCharacterSet]]
|
||||
length] == 0)
|
||||
return false;
|
||||
if ([[srcPath stringByTrimmingCharactersInSet:[NSCharacterSet
|
||||
whitespaceCharacterSet]]
|
||||
length] == 0)
|
||||
return false;
|
||||
|
||||
int pid, status;
|
||||
AuthorizationRef myAuthorizationRef;
|
||||
|
||||
// Get the authorization
|
||||
OSStatus err = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &myAuthorizationRef);
|
||||
if (err != errAuthorizationSuccess) return false;
|
||||
OSStatus err =
|
||||
AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment,
|
||||
kAuthorizationFlagDefaults, &myAuthorizationRef);
|
||||
if (err != errAuthorizationSuccess)
|
||||
return false;
|
||||
|
||||
AuthorizationItem myItems = {kAuthorizationRightExecute, 0, NULL, 0};
|
||||
AuthorizationRights myRights = {1, &myItems};
|
||||
AuthorizationFlags myFlags = (AuthorizationFlags)(kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights | kAuthorizationFlagPreAuthorize);
|
||||
AuthorizationFlags myFlags = (AuthorizationFlags)(
|
||||
kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights |
|
||||
kAuthorizationFlagPreAuthorize);
|
||||
|
||||
err = AuthorizationCopyRights(myAuthorizationRef, &myRights, NULL, myFlags, NULL);
|
||||
err = AuthorizationCopyRights(myAuthorizationRef, &myRights, NULL, myFlags,
|
||||
NULL);
|
||||
if (err != errAuthorizationSuccess) {
|
||||
if (err == errAuthorizationCanceled && canceled)
|
||||
*canceled = true;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
static OSStatus (*security_AuthorizationExecuteWithPrivileges)(AuthorizationRef authorization, const char *pathToTool,
|
||||
AuthorizationFlags options, char * const *arguments,
|
||||
FILE **communicationsPipe) = NULL;
|
||||
static OSStatus (*security_AuthorizationExecuteWithPrivileges)(
|
||||
AuthorizationRef authorization, const char* pathToTool,
|
||||
AuthorizationFlags options, char* const* arguments,
|
||||
FILE** communicationsPipe) = NULL;
|
||||
if (!security_AuthorizationExecuteWithPrivileges) {
|
||||
// On 10.7, AuthorizationExecuteWithPrivileges is deprecated. We want to still use it since there's no
|
||||
// good alternative (without requiring code signing). We'll look up the function through dyld and fail
|
||||
// if it is no longer accessible. If Apple removes the function entirely this will fail gracefully. If
|
||||
// they keep the function and throw some sort of exception, this won't fail gracefully, but that's a
|
||||
// risk we'll have to take for now.
|
||||
security_AuthorizationExecuteWithPrivileges = (OSStatus (*)(AuthorizationRef, const char*,
|
||||
AuthorizationFlags, char* const*,
|
||||
FILE **)) dlsym(RTLD_DEFAULT, "AuthorizationExecuteWithPrivileges");
|
||||
// On 10.7, AuthorizationExecuteWithPrivileges is deprecated. We want to
|
||||
// still use it since there's no good alternative (without requiring code
|
||||
// signing). We'll look up the function through dyld and fail if it is no
|
||||
// longer accessible. If Apple removes the function entirely this will fail
|
||||
// gracefully. If they keep the function and throw some sort of exception,
|
||||
// this won't fail gracefully, but that's a risk we'll have to take for now.
|
||||
security_AuthorizationExecuteWithPrivileges = (OSStatus(*)(
|
||||
AuthorizationRef, const char*, AuthorizationFlags, char* const*,
|
||||
FILE**))dlsym(RTLD_DEFAULT, "AuthorizationExecuteWithPrivileges");
|
||||
}
|
||||
if (!security_AuthorizationExecuteWithPrivileges) goto fail;
|
||||
if (!security_AuthorizationExecuteWithPrivileges)
|
||||
goto fail;
|
||||
|
||||
// Delete the destination
|
||||
{
|
||||
char rf[] = "-rf";
|
||||
char *args[] = {rf, (char *)[dstPath fileSystemRepresentation], NULL};
|
||||
err = security_AuthorizationExecuteWithPrivileges(myAuthorizationRef, "/bin/rm", kAuthorizationFlagDefaults, args, NULL);
|
||||
if (err != errAuthorizationSuccess) goto fail;
|
||||
char* args[] = {rf, (char*)[dstPath fileSystemRepresentation], NULL};
|
||||
err = security_AuthorizationExecuteWithPrivileges(
|
||||
myAuthorizationRef, "/bin/rm", kAuthorizationFlagDefaults, args, NULL);
|
||||
if (err != errAuthorizationSuccess)
|
||||
goto fail;
|
||||
|
||||
// Wait until it's done
|
||||
pid = wait(&status);
|
||||
if (pid == -1 || !WIFEXITED(status)) goto fail; // We don't care about exit status as the destination most likely does not exist
|
||||
if (pid == -1 || !WIFEXITED(status))
|
||||
goto fail; // We don't care about exit status as the destination most
|
||||
// likely does not exist
|
||||
}
|
||||
|
||||
// Copy
|
||||
{
|
||||
char pR[] = "-pR";
|
||||
char *args[] = {pR, (char *)[srcPath fileSystemRepresentation], (char *)[dstPath fileSystemRepresentation], NULL};
|
||||
err = security_AuthorizationExecuteWithPrivileges(myAuthorizationRef, "/bin/cp", kAuthorizationFlagDefaults, args, NULL);
|
||||
if (err != errAuthorizationSuccess) goto fail;
|
||||
char* args[] = {pR, (char*)[srcPath fileSystemRepresentation],
|
||||
(char*)[dstPath fileSystemRepresentation], NULL};
|
||||
err = security_AuthorizationExecuteWithPrivileges(
|
||||
myAuthorizationRef, "/bin/cp", kAuthorizationFlagDefaults, args, NULL);
|
||||
if (err != errAuthorizationSuccess)
|
||||
goto fail;
|
||||
|
||||
// Wait until it's done
|
||||
pid = wait(&status);
|
||||
if (pid == -1 || !WIFEXITED(status) || WEXITSTATUS(status)) goto fail;
|
||||
if (pid == -1 || !WIFEXITED(status) || WEXITSTATUS(status))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
AuthorizationFree(myAuthorizationRef, kAuthorizationFlagDefaults);
|
||||
|
@ -254,14 +322,16 @@ bool AtomBundleMover::CopyBundle(NSString* srcPath, NSString* dstPath) {
|
|||
|
||||
if ([fileManager copyItemAtPath:srcPath toPath:dstPath error:&error]) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
NSString* AtomBundleMover::ShellQuotedString(NSString* string) {
|
||||
return [NSString stringWithFormat:@"'%@'", [string stringByReplacingOccurrencesOfString:@"'" withString:@"'\\''"]];
|
||||
return [NSString
|
||||
stringWithFormat:@"'%@'",
|
||||
[string stringByReplacingOccurrencesOfString:@"'"
|
||||
withString:@"'\\''"]];
|
||||
}
|
||||
|
||||
void AtomBundleMover::Relaunch(NSString* destinationPath) {
|
||||
|
@ -276,18 +346,28 @@ void AtomBundleMover::Relaunch(NSString* destinationPath) {
|
|||
|
||||
// Before we launch the new app, clear xattr:com.apple.quarantine to avoid
|
||||
// duplicate "scary file from the internet" dialog.
|
||||
preOpenCmd = [NSString stringWithFormat:@"/usr/bin/xattr -d -r com.apple.quarantine %@", quotedDestinationPath];
|
||||
preOpenCmd = [NSString
|
||||
stringWithFormat:@"/usr/bin/xattr -d -r com.apple.quarantine %@",
|
||||
quotedDestinationPath];
|
||||
|
||||
NSString* script = [NSString stringWithFormat:@"(while /bin/kill -0 %d >&/dev/null; do /bin/sleep 0.1; done; %@; /usr/bin/open %@) &", pid, preOpenCmd, quotedDestinationPath];
|
||||
NSString* script =
|
||||
[NSString stringWithFormat:
|
||||
@"(while /bin/kill -0 %d >&/dev/null; do /bin/sleep 0.1; "
|
||||
@"done; %@; /usr/bin/open %@) &",
|
||||
pid, preOpenCmd, quotedDestinationPath];
|
||||
|
||||
[NSTask launchedTaskWithLaunchPath:@"/bin/sh" arguments:[NSArray arrayWithObjects:@"-c", script, nil]];
|
||||
[NSTask
|
||||
launchedTaskWithLaunchPath:@"/bin/sh"
|
||||
arguments:[NSArray arrayWithObjects:@"-c", script, nil]];
|
||||
}
|
||||
|
||||
bool AtomBundleMover::IsApplicationAtPathRunning(NSString* bundlePath) {
|
||||
bundlePath = [bundlePath stringByStandardizingPath];
|
||||
|
||||
for (NSRunningApplication *runningApplication in [[NSWorkspace sharedWorkspace] runningApplications]) {
|
||||
NSString* runningAppBundlePath = [[[runningApplication bundleURL] path] stringByStandardizingPath];
|
||||
for (NSRunningApplication* runningApplication in
|
||||
[[NSWorkspace sharedWorkspace] runningApplications]) {
|
||||
NSString* runningAppBundlePath =
|
||||
[[[runningApplication bundleURL] path] stringByStandardizingPath];
|
||||
if ([runningAppBundlePath isEqualToString:bundlePath]) {
|
||||
return true;
|
||||
}
|
||||
|
@ -299,29 +379,41 @@ bool AtomBundleMover::Trash(NSString* path) {
|
|||
bool result = false;
|
||||
|
||||
if (floor(NSAppKitVersionNumber) >= NSAppKitVersionNumber10_8) {
|
||||
result = [[NSFileManager defaultManager] trashItemAtURL:[NSURL fileURLWithPath:path] resultingItemURL:NULL error:NULL];
|
||||
result = [[NSFileManager defaultManager]
|
||||
trashItemAtURL:[NSURL fileURLWithPath:path]
|
||||
resultingItemURL:NULL
|
||||
error:NULL];
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
result = [[NSWorkspace sharedWorkspace] performFileOperation:NSWorkspaceRecycleOperation
|
||||
source:[path stringByDeletingLastPathComponent]
|
||||
destination:@""
|
||||
files:[NSArray arrayWithObject:[path lastPathComponent]]
|
||||
tag:NULL];
|
||||
result = [[NSWorkspace sharedWorkspace]
|
||||
performFileOperation:NSWorkspaceRecycleOperation
|
||||
source:[path stringByDeletingLastPathComponent]
|
||||
destination:@""
|
||||
files:[NSArray arrayWithObject:[path lastPathComponent]]
|
||||
tag:NULL];
|
||||
}
|
||||
|
||||
|
||||
// As a last resort try trashing with AppleScript.
|
||||
// This allows us to trash the app in macOS Sierra even when the app is running inside
|
||||
// an app translocation image.
|
||||
// This allows us to trash the app in macOS Sierra even when the app is
|
||||
// running inside an app translocation image.
|
||||
if (!result) {
|
||||
NSAppleScript* appleScript = [[[NSAppleScript alloc] initWithSource:
|
||||
[NSString stringWithFormat:@"\
|
||||
set theFile to POSIX file \"%@\" \n\
|
||||
tell application \"Finder\" \n\
|
||||
NSAppleScript* appleScript = [[[NSAppleScript alloc]
|
||||
initWithSource:
|
||||
[NSString
|
||||
stringWithFormat:
|
||||
@"\
|
||||
set theFile to POSIX file \"%@\" "
|
||||
@"\n\
|
||||
tell application \"Finder\" "
|
||||
@"\n\
|
||||
move theFile to trash \n\
|
||||
end tell", path]] autorelease];
|
||||
"
|
||||
@" end tell",
|
||||
path]] autorelease];
|
||||
NSDictionary* errorDict = nil;
|
||||
NSAppleEventDescriptor* scriptResult = [appleScript executeAndReturnError:&errorDict];
|
||||
NSAppleEventDescriptor* scriptResult =
|
||||
[appleScript executeAndReturnError:&errorDict];
|
||||
result = (scriptResult != nil);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,35 +25,35 @@ struct Role {
|
|||
const char* role;
|
||||
};
|
||||
Role kRolesMap[] = {
|
||||
{ @selector(orderFrontStandardAboutPanel:), "about" },
|
||||
{ @selector(hide:), "hide" },
|
||||
{ @selector(hideOtherApplications:), "hideothers" },
|
||||
{ @selector(unhideAllApplications:), "unhide" },
|
||||
{ @selector(arrangeInFront:), "front" },
|
||||
{ @selector(undo:), "undo" },
|
||||
{ @selector(redo:), "redo" },
|
||||
{ @selector(cut:), "cut" },
|
||||
{ @selector(copy:), "copy" },
|
||||
{ @selector(paste:), "paste" },
|
||||
{ @selector(delete:), "delete" },
|
||||
{ @selector(pasteAndMatchStyle:), "pasteandmatchstyle" },
|
||||
{ @selector(selectAll:), "selectall" },
|
||||
{ @selector(startSpeaking:), "startspeaking" },
|
||||
{ @selector(stopSpeaking:), "stopspeaking" },
|
||||
{ @selector(performMiniaturize:), "minimize" },
|
||||
{ @selector(performClose:), "close" },
|
||||
{ @selector(performZoom:), "zoom" },
|
||||
{ @selector(terminate:), "quit" },
|
||||
// ↓ is intentionally not `toggleFullScreen`. The macOS full screen menu item behaves weird.
|
||||
// If we use `toggleFullScreen`, then the menu item will use the default label, and not take
|
||||
// the one provided.
|
||||
{ @selector(toggleFullScreenMode:), "togglefullscreen" },
|
||||
{ @selector(toggleTabBar:), "toggletabbar" },
|
||||
{ @selector(selectNextTab:), "selectnexttab" },
|
||||
{ @selector(selectPreviousTab:), "selectprevioustab" },
|
||||
{ @selector(mergeAllWindows:), "mergeallwindows" },
|
||||
{ @selector(moveTabToNewWindow:), "movetabtonewwindow" },
|
||||
{ @selector(clearRecentDocuments:), "clearrecentdocuments" },
|
||||
{@selector(orderFrontStandardAboutPanel:), "about"},
|
||||
{@selector(hide:), "hide"},
|
||||
{@selector(hideOtherApplications:), "hideothers"},
|
||||
{@selector(unhideAllApplications:), "unhide"},
|
||||
{@selector(arrangeInFront:), "front"},
|
||||
{@selector(undo:), "undo"},
|
||||
{@selector(redo:), "redo"},
|
||||
{@selector(cut:), "cut"},
|
||||
{@selector(copy:), "copy"},
|
||||
{@selector(paste:), "paste"},
|
||||
{@selector(delete:), "delete"},
|
||||
{@selector(pasteAndMatchStyle:), "pasteandmatchstyle"},
|
||||
{@selector(selectAll:), "selectall"},
|
||||
{@selector(startSpeaking:), "startspeaking"},
|
||||
{@selector(stopSpeaking:), "stopspeaking"},
|
||||
{@selector(performMiniaturize:), "minimize"},
|
||||
{@selector(performClose:), "close"},
|
||||
{@selector(performZoom:), "zoom"},
|
||||
{@selector(terminate:), "quit"},
|
||||
// ↓ is intentionally not `toggleFullScreen`. The macOS full screen menu
|
||||
// item behaves weird. If we use `toggleFullScreen`, then the menu item will
|
||||
// use the default label, and not take the one provided.
|
||||
{@selector(toggleFullScreenMode:), "togglefullscreen"},
|
||||
{@selector(toggleTabBar:), "toggletabbar"},
|
||||
{@selector(selectNextTab:), "selectnexttab"},
|
||||
{@selector(selectPreviousTab:), "selectprevioustab"},
|
||||
{@selector(mergeAllWindows:), "mergeallwindows"},
|
||||
{@selector(moveTabToNewWindow:), "movetabtonewwindow"},
|
||||
{@selector(clearRecentDocuments:), "clearrecentdocuments"},
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
@ -68,7 +68,8 @@ static base::scoped_nsobject<NSMenu> recentDocumentsMenuSwap_;
|
|||
|
||||
@synthesize model = model_;
|
||||
|
||||
- (id)initWithModel:(atom::AtomMenuModel*)model useDefaultAccelerator:(BOOL)use {
|
||||
- (id)initWithModel:(atom::AtomMenuModel*)model
|
||||
useDefaultAccelerator:(BOOL)use {
|
||||
if ((self = [super init])) {
|
||||
model_ = model;
|
||||
isMenuOpen_ = NO;
|
||||
|
@ -100,10 +101,9 @@ static base::scoped_nsobject<NSMenu> recentDocumentsMenuSwap_;
|
|||
|
||||
if (!recentDocumentsMenuItem_) {
|
||||
// Locate & retain the recent documents menu item
|
||||
recentDocumentsMenuItem_.reset([[[[[NSApp mainMenu]
|
||||
itemWithTitle:@"Electron"] submenu]
|
||||
itemWithTitle:@"Open Recent"]
|
||||
retain]);
|
||||
recentDocumentsMenuItem_.reset(
|
||||
[[[[[NSApp mainMenu] itemWithTitle:@"Electron"] submenu]
|
||||
itemWithTitle:@"Open Recent"] retain]);
|
||||
}
|
||||
|
||||
model_ = model;
|
||||
|
@ -146,15 +146,13 @@ static base::scoped_nsobject<NSMenu> recentDocumentsMenuSwap_;
|
|||
// Adds a separator item at the given index. As the separator doesn't need
|
||||
// anything from the model, this method doesn't need the model index as the
|
||||
// other method below does.
|
||||
- (void)addSeparatorToMenu:(NSMenu*)menu
|
||||
atIndex:(int)index {
|
||||
- (void)addSeparatorToMenu:(NSMenu*)menu atIndex:(int)index {
|
||||
NSMenuItem* separator = [NSMenuItem separatorItem];
|
||||
[menu insertItem:separator atIndex:index];
|
||||
}
|
||||
|
||||
// Empties the source menu items to the destination.
|
||||
- (void)moveMenuItems:(NSMenu*)source
|
||||
to:(NSMenu*)destination {
|
||||
- (void)moveMenuItems:(NSMenu*)source to:(NSMenu*)destination {
|
||||
const long count = [source numberOfItems];
|
||||
for (long index = 0; index < count; index++) {
|
||||
NSMenuItem* removedItem = [[[source itemAtIndex:0] retain] autorelease];
|
||||
|
@ -166,12 +164,11 @@ static base::scoped_nsobject<NSMenu> recentDocumentsMenuSwap_;
|
|||
// Replaces the item's submenu instance with the singleton recent documents
|
||||
// menu. Previously replaced menu items will be recovered.
|
||||
- (void)replaceSubmenuShowingRecentDocuments:(NSMenuItem*)item {
|
||||
NSMenu* recentDocumentsMenu = [[[recentDocumentsMenuItem_ submenu]
|
||||
retain] autorelease];
|
||||
NSMenu* recentDocumentsMenu =
|
||||
[[[recentDocumentsMenuItem_ submenu] retain] autorelease];
|
||||
|
||||
// Remove menu items in recent documents back to swap menu
|
||||
[self moveMenuItems:recentDocumentsMenu
|
||||
to:recentDocumentsMenuSwap_];
|
||||
[self moveMenuItems:recentDocumentsMenu to:recentDocumentsMenuSwap_];
|
||||
// Swap back the submenu
|
||||
[recentDocumentsMenuItem_ setSubmenu:recentDocumentsMenuSwap_];
|
||||
|
||||
|
@ -179,8 +176,7 @@ static base::scoped_nsobject<NSMenu> recentDocumentsMenuSwap_;
|
|||
recentDocumentsMenuSwap_.reset([[item submenu] retain]);
|
||||
|
||||
// Repopulate with items from the submenu to be replaced
|
||||
[self moveMenuItems:recentDocumentsMenuSwap_
|
||||
to:recentDocumentsMenu];
|
||||
[self moveMenuItems:recentDocumentsMenuSwap_ to:recentDocumentsMenu];
|
||||
// Update the submenu's title
|
||||
[recentDocumentsMenu setTitle:[recentDocumentsMenuSwap_ title]];
|
||||
// Replace submenu
|
||||
|
@ -198,10 +194,10 @@ static base::scoped_nsobject<NSMenu> recentDocumentsMenuSwap_;
|
|||
base::string16 label16 = model->GetLabelAt(index);
|
||||
NSString* label = l10n_util::FixUpWindowsStyleLabel(label16);
|
||||
|
||||
base::scoped_nsobject<NSMenuItem> item(
|
||||
[[NSMenuItem alloc] initWithTitle:label
|
||||
action:@selector(itemSelected:)
|
||||
keyEquivalent:@""]);
|
||||
base::scoped_nsobject<NSMenuItem> item([[NSMenuItem alloc]
|
||||
initWithTitle:label
|
||||
action:@selector(itemSelected:)
|
||||
keyEquivalent:@""]);
|
||||
|
||||
// If the menu item has an icon, set it.
|
||||
gfx::Image icon;
|
||||
|
@ -214,8 +210,8 @@ static base::scoped_nsobject<NSMenu> recentDocumentsMenuSwap_;
|
|||
// Recursively build a submenu from the sub-model at this index.
|
||||
[item setTarget:nil];
|
||||
[item setAction:nil];
|
||||
atom::AtomMenuModel* submenuModel = static_cast<atom::AtomMenuModel*>(
|
||||
model->GetSubmenuModelAt(index));
|
||||
atom::AtomMenuModel* submenuModel =
|
||||
static_cast<atom::AtomMenuModel*>(model->GetSubmenuModelAt(index));
|
||||
NSMenu* submenu = [self menuFromModel:submenuModel];
|
||||
[submenu setTitle:[item title]];
|
||||
[item setSubmenu:submenu];
|
||||
|
@ -239,15 +235,15 @@ static base::scoped_nsobject<NSMenu> recentDocumentsMenuSwap_;
|
|||
NSValue* modelObject = [NSValue valueWithPointer:model];
|
||||
[item setRepresentedObject:modelObject]; // Retains |modelObject|.
|
||||
ui::Accelerator accelerator;
|
||||
if (model->GetAcceleratorAtWithParams(
|
||||
index, useDefaultAccelerator_, &accelerator)) {
|
||||
if (model->GetAcceleratorAtWithParams(index, useDefaultAccelerator_,
|
||||
&accelerator)) {
|
||||
const ui::PlatformAcceleratorCocoa* platformAccelerator =
|
||||
static_cast<const ui::PlatformAcceleratorCocoa*>(
|
||||
accelerator.platform_accelerator());
|
||||
if (platformAccelerator) {
|
||||
[item setKeyEquivalent:platformAccelerator->characters()];
|
||||
[item setKeyEquivalentModifierMask:
|
||||
platformAccelerator->modifier_mask()];
|
||||
[item
|
||||
setKeyEquivalentModifierMask:platformAccelerator->modifier_mask()];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -275,9 +271,8 @@ static base::scoped_nsobject<NSMenu> recentDocumentsMenuSwap_;
|
|||
return NO;
|
||||
|
||||
NSInteger modelIndex = [item tag];
|
||||
atom::AtomMenuModel* model =
|
||||
static_cast<atom::AtomMenuModel*>(
|
||||
[[(id)item representedObject] pointerValue]);
|
||||
atom::AtomMenuModel* model = static_cast<atom::AtomMenuModel*>(
|
||||
[[(id)item representedObject] pointerValue]);
|
||||
DCHECK(model);
|
||||
if (model) {
|
||||
BOOL checked = model->IsItemCheckedAt(modelIndex);
|
||||
|
@ -303,9 +298,8 @@ static base::scoped_nsobject<NSMenu> recentDocumentsMenuSwap_;
|
|||
// item chosen.
|
||||
- (void)itemSelected:(id)sender {
|
||||
NSInteger modelIndex = [sender tag];
|
||||
atom::AtomMenuModel* model =
|
||||
static_cast<atom::AtomMenuModel*>(
|
||||
[[sender representedObject] pointerValue]);
|
||||
atom::AtomMenuModel* model = static_cast<atom::AtomMenuModel*>(
|
||||
[[sender representedObject] pointerValue]);
|
||||
DCHECK(model);
|
||||
if (model) {
|
||||
NSEvent* event = [NSApp currentEvent];
|
||||
|
@ -338,8 +332,8 @@ static base::scoped_nsobject<NSMenu> recentDocumentsMenuSwap_;
|
|||
if (isMenuOpen_) {
|
||||
isMenuOpen_ = NO;
|
||||
model_->MenuWillClose();
|
||||
// Post async task so that itemSelected runs before the close callback
|
||||
// deletes the controller from the map which deallocates it
|
||||
// Post async task so that itemSelected runs before the close callback
|
||||
// deletes the controller from the map which deallocates it
|
||||
if (!closeCallback.is_null()) {
|
||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, closeCallback);
|
||||
}
|
||||
|
|
|
@ -8,11 +8,9 @@ namespace atom {
|
|||
|
||||
AtomNativeWidgetMac::AtomNativeWidgetMac(
|
||||
views::internal::NativeWidgetDelegate* delegate)
|
||||
: views::NativeWidgetMac(delegate) {
|
||||
}
|
||||
: views::NativeWidgetMac(delegate) {}
|
||||
|
||||
AtomNativeWidgetMac::~AtomNativeWidgetMac() {
|
||||
}
|
||||
AtomNativeWidgetMac::~AtomNativeWidgetMac() {}
|
||||
|
||||
NativeWidgetMacNSWindow* AtomNativeWidgetMac::CreateNSWindow(
|
||||
const views::Widget::InitParams& params) {
|
||||
|
|
|
@ -36,7 +36,7 @@ bool ScopedDisableResize::disable_resize_ = false;
|
|||
|
||||
// NSWindow overrides.
|
||||
|
||||
- (void)swipeWithEvent:(NSEvent *)event {
|
||||
- (void)swipeWithEvent:(NSEvent*)event {
|
||||
if (event.deltaY == 1.0) {
|
||||
shell_->NotifyWindowSwipe("up");
|
||||
} else if (event.deltaX == -1.0) {
|
||||
|
@ -78,12 +78,11 @@ bool ScopedDisableResize::disable_resize_ = false;
|
|||
// * when VoiceOver is enabled, the full accessibility tree is used.
|
||||
// Without removing the title and with VO disabled, the TTS would always read
|
||||
// the window title instead of using Cmd+C to get the selected text.
|
||||
NSPredicate *predicate = [NSPredicate predicateWithFormat:
|
||||
@"(self isKindOfClass: %@) OR (self.className == %@)",
|
||||
[NSButtonCell class],
|
||||
@"RenderWidgetHostViewCocoa"];
|
||||
NSPredicate* predicate = [NSPredicate
|
||||
predicateWithFormat:@"(self isKindOfClass: %@) OR (self.className == %@)",
|
||||
[NSButtonCell class], @"RenderWidgetHostViewCocoa"];
|
||||
|
||||
NSArray *children = [super accessibilityAttributeValue:attribute];
|
||||
NSArray* children = [super accessibilityAttributeValue:attribute];
|
||||
return [children filteredArrayUsingPredicate:predicate];
|
||||
}
|
||||
|
||||
|
@ -97,7 +96,8 @@ bool ScopedDisableResize::disable_resize_ = false;
|
|||
|
||||
- (void)enableWindowButtonsOffset {
|
||||
auto closeButton = [self standardWindowButton:NSWindowCloseButton];
|
||||
auto miniaturizeButton = [self standardWindowButton:NSWindowMiniaturizeButton];
|
||||
auto miniaturizeButton =
|
||||
[self standardWindowButton:NSWindowMiniaturizeButton];
|
||||
auto zoomButton = [self standardWindowButton:NSWindowZoomButton];
|
||||
|
||||
[closeButton setPostsFrameChangedNotifications:YES];
|
||||
|
@ -105,7 +105,7 @@ bool ScopedDisableResize::disable_resize_ = false;
|
|||
[zoomButton setPostsFrameChangedNotifications:YES];
|
||||
|
||||
windowButtonsInterButtonSpacing_ =
|
||||
NSMinX([miniaturizeButton frame]) - NSMaxX([closeButton frame]);
|
||||
NSMinX([miniaturizeButton frame]) - NSMaxX([closeButton frame]);
|
||||
|
||||
auto center = [NSNotificationCenter defaultCenter];
|
||||
|
||||
|
@ -126,39 +126,34 @@ bool ScopedDisableResize::disable_resize_ = false;
|
|||
}
|
||||
|
||||
- (void)adjustCloseButton:(NSNotification*)notification {
|
||||
[self adjustButton:[notification object]
|
||||
ofKind:NSWindowCloseButton];
|
||||
[self adjustButton:[notification object] ofKind:NSWindowCloseButton];
|
||||
}
|
||||
|
||||
- (void)adjustMiniaturizeButton:(NSNotification*)notification {
|
||||
[self adjustButton:[notification object]
|
||||
ofKind:NSWindowMiniaturizeButton];
|
||||
[self adjustButton:[notification object] ofKind:NSWindowMiniaturizeButton];
|
||||
}
|
||||
|
||||
- (void)adjustZoomButton:(NSNotification*)notification {
|
||||
[self adjustButton:[notification object]
|
||||
ofKind:NSWindowZoomButton];
|
||||
[self adjustButton:[notification object] ofKind:NSWindowZoomButton];
|
||||
}
|
||||
|
||||
- (void)adjustButton:(NSButton*)button
|
||||
ofKind:(NSWindowButton)kind {
|
||||
- (void)adjustButton:(NSButton*)button ofKind:(NSWindowButton)kind {
|
||||
NSRect buttonFrame = [button frame];
|
||||
NSRect frameViewBounds = [[self frameView] bounds];
|
||||
NSPoint offset = self.windowButtonsOffset;
|
||||
|
||||
buttonFrame.origin = NSMakePoint(
|
||||
offset.x,
|
||||
(NSHeight(frameViewBounds) - NSHeight(buttonFrame) - offset.y));
|
||||
offset.x, (NSHeight(frameViewBounds) - NSHeight(buttonFrame) - offset.y));
|
||||
|
||||
switch (kind) {
|
||||
case NSWindowZoomButton:
|
||||
buttonFrame.origin.x += NSWidth(
|
||||
[[self standardWindowButton:NSWindowMiniaturizeButton] frame]);
|
||||
[[self standardWindowButton:NSWindowMiniaturizeButton] frame]);
|
||||
buttonFrame.origin.x += windowButtonsInterButtonSpacing_;
|
||||
// fallthrough
|
||||
case NSWindowMiniaturizeButton:
|
||||
buttonFrame.origin.x += NSWidth(
|
||||
[[self standardWindowButton:NSWindowCloseButton] frame]);
|
||||
buttonFrame.origin.x +=
|
||||
NSWidth([[self standardWindowButton:NSWindowCloseButton] frame]);
|
||||
buttonFrame.origin.x += windowButtonsInterButtonSpacing_;
|
||||
// fallthrough
|
||||
default:
|
||||
|
@ -194,7 +189,8 @@ bool ScopedDisableResize::disable_resize_ = false;
|
|||
// Custom window button methods
|
||||
|
||||
- (void)performClose:(id)sender {
|
||||
if (shell_->title_bar_style() == atom::NativeWindowMac::CUSTOM_BUTTONS_ON_HOVER)
|
||||
if (shell_->title_bar_style() ==
|
||||
atom::NativeWindowMac::CUSTOM_BUTTONS_ON_HOVER)
|
||||
[[self delegate] windowShouldClose:self];
|
||||
else
|
||||
[super performClose:sender];
|
||||
|
@ -204,11 +200,12 @@ bool ScopedDisableResize::disable_resize_ = false;
|
|||
if (shell_->simple_fullscreen())
|
||||
shell_->SetSimpleFullScreen(!shell_->IsSimpleFullScreen());
|
||||
else
|
||||
[super toggleFullScreen:sender];
|
||||
[super toggleFullScreen:sender];
|
||||
}
|
||||
|
||||
- (void)performMiniaturize:(id)sender {
|
||||
if (shell_->title_bar_style() == atom::NativeWindowMac::CUSTOM_BUTTONS_ON_HOVER)
|
||||
if (shell_->title_bar_style() ==
|
||||
atom::NativeWindowMac::CUSTOM_BUTTONS_ON_HOVER)
|
||||
[self miniaturize:self];
|
||||
else
|
||||
[super performMiniaturize:sender];
|
||||
|
|
|
@ -23,19 +23,20 @@
|
|||
|
||||
#pragma mark - NSWindowDelegate
|
||||
|
||||
- (void)windowDidChangeOcclusionState:(NSNotification *)notification {
|
||||
- (void)windowDidChangeOcclusionState:(NSNotification*)notification {
|
||||
// notification.object is the window that changed its state.
|
||||
// It's safe to use self.window instead if you don't assign one delegate to many windows
|
||||
NSWindow *window = notification.object;
|
||||
// It's safe to use self.window instead if you don't assign one delegate to
|
||||
// many windows
|
||||
NSWindow* window = notification.object;
|
||||
|
||||
// check occlusion binary flag
|
||||
if (window.occlusionState & NSWindowOcclusionStateVisible) {
|
||||
// The app is visible
|
||||
shell_->NotifyWindowShow();
|
||||
} else {
|
||||
// The app is not visible
|
||||
shell_->NotifyWindowHide();
|
||||
}
|
||||
if (window.occlusionState & NSWindowOcclusionStateVisible) {
|
||||
// The app is visible
|
||||
shell_->NotifyWindowShow();
|
||||
} else {
|
||||
// The app is not visible
|
||||
shell_->NotifyWindowHide();
|
||||
}
|
||||
}
|
||||
|
||||
// Called when the user clicks the zoom button or selects it from the Window
|
||||
|
@ -55,8 +56,8 @@
|
|||
|
||||
// Never shrink from the current size on zoom.
|
||||
NSRect window_frame = [window frame];
|
||||
CGFloat zoomed_width = std::max(static_cast<CGFloat>(preferred_width),
|
||||
NSWidth(window_frame));
|
||||
CGFloat zoomed_width =
|
||||
std::max(static_cast<CGFloat>(preferred_width), NSWidth(window_frame));
|
||||
|
||||
// |frame| determines our maximum extents. We need to set the origin of the
|
||||
// frame -- and only move it left if necessary.
|
||||
|
@ -117,7 +118,8 @@
|
|||
|
||||
- (void)windowWillMiniaturize:(NSNotification*)notification {
|
||||
NSWindow* window = shell_->GetNativeWindow();
|
||||
// store the current status window level to be restored in windowDidDeminiaturize
|
||||
// store the current status window level to be restored in
|
||||
// windowDidDeminiaturize
|
||||
level_ = [window level];
|
||||
[window setLevel:NSNormalWindowLevel];
|
||||
}
|
||||
|
@ -177,16 +179,16 @@
|
|||
[window setTitleVisibility:NSWindowTitleVisible];
|
||||
}
|
||||
|
||||
// Restore the native toolbar immediately after entering fullscreen, if we do
|
||||
// this before leaving fullscreen, traffic light buttons will be jumping.
|
||||
// Restore the native toolbar immediately after entering fullscreen, if we
|
||||
// do this before leaving fullscreen, traffic light buttons will be jumping.
|
||||
if (shell_->title_bar_style() == atom::NativeWindowMac::HIDDEN_INSET) {
|
||||
base::scoped_nsobject<NSToolbar> toolbar(
|
||||
[[NSToolbar alloc] initWithIdentifier:@"titlebarStylingToolbar"]);
|
||||
[toolbar setShowsBaselineSeparator:NO];
|
||||
[window setToolbar:toolbar];
|
||||
|
||||
// Set window style to hide the toolbar, otherwise the toolbar will show in
|
||||
// fullscreen mode.
|
||||
// Set window style to hide the toolbar, otherwise the toolbar will show
|
||||
// in fullscreen mode.
|
||||
shell_->SetStyleMask(true, NSFullSizeContentViewWindowMask);
|
||||
}
|
||||
}
|
||||
|
@ -229,7 +231,8 @@
|
|||
}
|
||||
|
||||
- (NSRect)window:(NSWindow*)window
|
||||
willPositionSheet:(NSWindow*)sheet usingRect:(NSRect)rect {
|
||||
willPositionSheet:(NSWindow*)sheet
|
||||
usingRect:(NSRect)rect {
|
||||
NSView* view = window.contentView;
|
||||
|
||||
rect.origin.x = shell_->GetSheetOffsetX();
|
||||
|
@ -237,11 +240,11 @@
|
|||
return rect;
|
||||
}
|
||||
|
||||
- (void)windowWillBeginSheet:(NSNotification *)notification {
|
||||
- (void)windowWillBeginSheet:(NSNotification*)notification {
|
||||
shell_->NotifyWindowSheetBegin();
|
||||
}
|
||||
|
||||
- (void)windowDidEndSheet:(NSNotification *)notification {
|
||||
- (void)windowDidEndSheet:(NSNotification*)notification {
|
||||
shell_->NotifyWindowSheetEnd();
|
||||
}
|
||||
|
||||
|
@ -253,7 +256,8 @@
|
|||
#pragma mark - NSTouchBarDelegate
|
||||
|
||||
- (NSTouchBarItem*)touchBar:(NSTouchBar*)touchBar
|
||||
makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier API_AVAILABLE(macosx(10.12.2)) {
|
||||
makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier
|
||||
API_AVAILABLE(macosx(10.12.2)) {
|
||||
if (touchBar && shell_->touch_bar())
|
||||
return [shell_->touch_bar() makeItemForIdentifier:identifier];
|
||||
else
|
||||
|
@ -266,8 +270,8 @@
|
|||
return 1;
|
||||
}
|
||||
|
||||
- (id <QLPreviewItem>)previewPanel:(QLPreviewPanel*)panel
|
||||
previewItemAtIndex:(NSInteger)index {
|
||||
- (id<QLPreviewItem>)previewPanel:(QLPreviewPanel*)panel
|
||||
previewItemAtIndex:(NSInteger)index {
|
||||
return shell_->preview_item();
|
||||
}
|
||||
|
||||
|
|
|
@ -12,21 +12,30 @@
|
|||
|
||||
@implementation AtomTouchBar
|
||||
|
||||
static NSTouchBarItemIdentifier ButtonIdentifier = @"com.electron.touchbar.button.";
|
||||
static NSTouchBarItemIdentifier ColorPickerIdentifier = @"com.electron.touchbar.colorpicker.";
|
||||
static NSTouchBarItemIdentifier GroupIdentifier = @"com.electron.touchbar.group.";
|
||||
static NSTouchBarItemIdentifier LabelIdentifier = @"com.electron.touchbar.label.";
|
||||
static NSTouchBarItemIdentifier PopoverIdentifier = @"com.electron.touchbar.popover.";
|
||||
static NSTouchBarItemIdentifier SliderIdentifier = @"com.electron.touchbar.slider.";
|
||||
static NSTouchBarItemIdentifier SegmentedControlIdentifier = @"com.electron.touchbar.segmentedcontrol.";
|
||||
static NSTouchBarItemIdentifier ScrubberIdentifier = @"com.electron.touchbar.scrubber.";
|
||||
static NSTouchBarItemIdentifier ButtonIdentifier =
|
||||
@"com.electron.touchbar.button.";
|
||||
static NSTouchBarItemIdentifier ColorPickerIdentifier =
|
||||
@"com.electron.touchbar.colorpicker.";
|
||||
static NSTouchBarItemIdentifier GroupIdentifier =
|
||||
@"com.electron.touchbar.group.";
|
||||
static NSTouchBarItemIdentifier LabelIdentifier =
|
||||
@"com.electron.touchbar.label.";
|
||||
static NSTouchBarItemIdentifier PopoverIdentifier =
|
||||
@"com.electron.touchbar.popover.";
|
||||
static NSTouchBarItemIdentifier SliderIdentifier =
|
||||
@"com.electron.touchbar.slider.";
|
||||
static NSTouchBarItemIdentifier SegmentedControlIdentifier =
|
||||
@"com.electron.touchbar.segmentedcontrol.";
|
||||
static NSTouchBarItemIdentifier ScrubberIdentifier =
|
||||
@"com.electron.touchbar.scrubber.";
|
||||
|
||||
static NSString* const TextScrubberItemIdentifier = @"scrubber.text.item";
|
||||
static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
||||
|
||||
- (id)initWithDelegate:(id<NSTouchBarDelegate>)delegate
|
||||
window:(atom::NativeWindow*)window
|
||||
settings:(const std::vector<mate::PersistentDictionary>&)settings {
|
||||
settings:
|
||||
(const std::vector<mate::PersistentDictionary>&)settings {
|
||||
if ((self = [super init])) {
|
||||
delegate_ = delegate;
|
||||
window_ = window;
|
||||
|
@ -36,7 +45,8 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
}
|
||||
|
||||
- (NSTouchBar*)makeTouchBar {
|
||||
NSMutableArray* identifiers = [self identifiersFromSettings:ordered_settings_];
|
||||
NSMutableArray* identifiers =
|
||||
[self identifiersFromSettings:ordered_settings_];
|
||||
return [self touchBarFromItemIdentifiers:identifiers];
|
||||
}
|
||||
|
||||
|
@ -48,7 +58,8 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
return bar.autorelease();
|
||||
}
|
||||
|
||||
- (NSMutableArray*)identifiersFromSettings:(const std::vector<mate::PersistentDictionary>&)dicts {
|
||||
- (NSMutableArray*)identifiersFromSettings:
|
||||
(const std::vector<mate::PersistentDictionary>&)dicts {
|
||||
NSMutableArray* identifiers = [NSMutableArray array];
|
||||
|
||||
if (@available(macOS 10.12.2, *)) {
|
||||
|
@ -93,7 +104,8 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
item_id = [self idFromIdentifier:identifier withPrefix:LabelIdentifier];
|
||||
return [self makeLabelForID:item_id withIdentifier:identifier];
|
||||
} else if ([identifier hasPrefix:ColorPickerIdentifier]) {
|
||||
item_id = [self idFromIdentifier:identifier withPrefix:ColorPickerIdentifier];
|
||||
item_id =
|
||||
[self idFromIdentifier:identifier withPrefix:ColorPickerIdentifier];
|
||||
return [self makeColorPickerForID:item_id withIdentifier:identifier];
|
||||
} else if ([identifier hasPrefix:SliderIdentifier]) {
|
||||
item_id = [self idFromIdentifier:identifier withPrefix:SliderIdentifier];
|
||||
|
@ -105,7 +117,8 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
item_id = [self idFromIdentifier:identifier withPrefix:GroupIdentifier];
|
||||
return [self makeGroupForID:item_id withIdentifier:identifier];
|
||||
} else if ([identifier hasPrefix:SegmentedControlIdentifier]) {
|
||||
item_id = [self idFromIdentifier:identifier withPrefix:SegmentedControlIdentifier];
|
||||
item_id = [self idFromIdentifier:identifier
|
||||
withPrefix:SegmentedControlIdentifier];
|
||||
return [self makeSegmentedControlForID:item_id withIdentifier:identifier];
|
||||
} else if ([identifier hasPrefix:ScrubberIdentifier]) {
|
||||
item_id = [self idFromIdentifier:identifier withPrefix:ScrubberIdentifier];
|
||||
|
@ -119,9 +132,10 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
id:(NSTouchBarItemIdentifier)identifier
|
||||
withType:(const std::string&)item_type
|
||||
withSettings:(const mate::PersistentDictionary&)settings
|
||||
API_AVAILABLE(macosx(10.12.2)) {
|
||||
API_AVAILABLE(macosx(10.12.2)) {
|
||||
NSTouchBarItem* item = [touchBar itemForIdentifier:identifier];
|
||||
if (!item) return;
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
if (item_type == "button") {
|
||||
[self updateButton:(NSCustomTouchBarItem*)item withSettings:settings];
|
||||
|
@ -135,7 +149,8 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
} else if (item_type == "popover") {
|
||||
[self updatePopover:(NSPopoverTouchBarItem*)item withSettings:settings];
|
||||
} else if (item_type == "segmented_control") {
|
||||
[self updateSegmentedControl:(NSCustomTouchBarItem*)item withSettings:settings];
|
||||
[self updateSegmentedControl:(NSCustomTouchBarItem*)item
|
||||
withSettings:settings];
|
||||
} else if (item_type == "scrubber") {
|
||||
[self updateScrubber:(NSCustomTouchBarItem*)item withSettings:settings];
|
||||
} else if (item_type == "group") {
|
||||
|
@ -143,12 +158,16 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
}
|
||||
}
|
||||
|
||||
- (void)addNonDefaultTouchBarItems:(const std::vector<mate::PersistentDictionary>&)items {
|
||||
- (void)addNonDefaultTouchBarItems:
|
||||
(const std::vector<mate::PersistentDictionary>&)items {
|
||||
[self identifiersFromSettings:items];
|
||||
}
|
||||
|
||||
- (void)setEscapeTouchBarItem:(const mate::PersistentDictionary&)item forTouchBar:(NSTouchBar*)touchBar {
|
||||
if (![touchBar respondsToSelector:@selector(escapeKeyReplacementItemIdentifier)]) return;
|
||||
- (void)setEscapeTouchBarItem:(const mate::PersistentDictionary&)item
|
||||
forTouchBar:(NSTouchBar*)touchBar {
|
||||
if (![touchBar
|
||||
respondsToSelector:@selector(escapeKeyReplacementItemIdentifier)])
|
||||
return;
|
||||
std::string type;
|
||||
std::string item_id;
|
||||
NSTouchBarItemIdentifier identifier = nil;
|
||||
|
@ -156,7 +175,7 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
identifier = [self identifierFromID:item_id type:type];
|
||||
}
|
||||
if (identifier) {
|
||||
[self addNonDefaultTouchBarItems:{ item }];
|
||||
[self addNonDefaultTouchBarItems:{item}];
|
||||
touchBar.escapeKeyReplacementItemIdentifier = identifier;
|
||||
} else {
|
||||
touchBar.escapeKeyReplacementItemIdentifier = nil;
|
||||
|
@ -165,14 +184,16 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
|
||||
- (void)refreshTouchBarItem:(NSTouchBar*)touchBar
|
||||
id:(const std::string&)item_id {
|
||||
if (![self hasItemWithID:item_id]) return;
|
||||
if (![self hasItemWithID:item_id])
|
||||
return;
|
||||
|
||||
mate::PersistentDictionary settings = settings_[item_id];
|
||||
std::string item_type;
|
||||
settings.Get("type", &item_type);
|
||||
|
||||
auto identifier = [self identifierFromID:item_id type:item_type];
|
||||
if (!identifier) return;
|
||||
if (!identifier)
|
||||
return;
|
||||
|
||||
std::vector<mate::Dictionary> parents;
|
||||
settings.Get("_parents", &parents);
|
||||
|
@ -182,18 +203,19 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
if (!parent.Get("type", &parent_type) || !parent.Get("id", &parent_id))
|
||||
continue;
|
||||
auto parentIdentifier = [self identifierFromID:parent_id type:parent_type];
|
||||
if (!parentIdentifier) continue;
|
||||
if (!parentIdentifier)
|
||||
continue;
|
||||
|
||||
if (parent_type == "popover") {
|
||||
NSPopoverTouchBarItem* popoverItem =
|
||||
[touchBar itemForIdentifier:parentIdentifier];
|
||||
[touchBar itemForIdentifier:parentIdentifier];
|
||||
[self refreshTouchBarItem:popoverItem.popoverTouchBar
|
||||
id:identifier
|
||||
withType:item_type
|
||||
withSettings:settings];
|
||||
id:identifier
|
||||
withType:item_type
|
||||
withSettings:settings];
|
||||
} else if (parent_type == "group") {
|
||||
NSGroupTouchBarItem* groupItem =
|
||||
[touchBar itemForIdentifier:parentIdentifier];
|
||||
[touchBar itemForIdentifier:parentIdentifier];
|
||||
[self refreshTouchBarItem:groupItem.groupTouchBar
|
||||
id:identifier
|
||||
withType:item_type
|
||||
|
@ -208,15 +230,16 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
}
|
||||
|
||||
- (void)buttonAction:(id)sender {
|
||||
NSString* item_id = [NSString stringWithFormat:@"%ld", ((NSButton*)sender).tag];
|
||||
NSString* item_id =
|
||||
[NSString stringWithFormat:@"%ld", ((NSButton*)sender).tag];
|
||||
window_->NotifyTouchBarItemInteraction([item_id UTF8String],
|
||||
base::DictionaryValue());
|
||||
}
|
||||
|
||||
- (void)colorPickerAction:(id)sender {
|
||||
NSString* identifier = ((NSColorPickerTouchBarItem*)sender).identifier;
|
||||
NSString* item_id = [self idFromIdentifier:identifier
|
||||
withPrefix:ColorPickerIdentifier];
|
||||
NSString* item_id =
|
||||
[self idFromIdentifier:identifier withPrefix:ColorPickerIdentifier];
|
||||
NSColor* color = ((NSColorPickerTouchBarItem*)sender).color;
|
||||
std::string hex_color = atom::ToRGBHex(skia::NSDeviceColorToSkColor(color));
|
||||
base::DictionaryValue details;
|
||||
|
@ -226,8 +249,8 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
|
||||
- (void)sliderAction:(id)sender {
|
||||
NSString* identifier = ((NSSliderTouchBarItem*)sender).identifier;
|
||||
NSString* item_id = [self idFromIdentifier:identifier
|
||||
withPrefix:SliderIdentifier];
|
||||
NSString* item_id =
|
||||
[self idFromIdentifier:identifier withPrefix:SliderIdentifier];
|
||||
base::DictionaryValue details;
|
||||
details.SetInteger("value",
|
||||
[((NSSliderTouchBarItem*)sender).slider intValue]);
|
||||
|
@ -235,31 +258,41 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
}
|
||||
|
||||
- (NSString*)idFromIdentifier:(NSString*)identifier
|
||||
withPrefix:(NSString*)prefix {
|
||||
withPrefix:(NSString*)prefix {
|
||||
return [identifier substringFromIndex:[prefix length]];
|
||||
}
|
||||
|
||||
- (void)segmentedControlAction:(id)sender {
|
||||
NSString* item_id = [NSString stringWithFormat:@"%ld", ((NSSegmentedControl*)sender).tag];
|
||||
NSString* item_id =
|
||||
[NSString stringWithFormat:@"%ld", ((NSSegmentedControl*)sender).tag];
|
||||
base::DictionaryValue details;
|
||||
details.SetInteger("selectedIndex", ((NSSegmentedControl*)sender).selectedSegment);
|
||||
details.SetBoolean("isSelected", [((NSSegmentedControl*)sender) isSelectedForSegment:((NSSegmentedControl*)sender).selectedSegment]);
|
||||
window_->NotifyTouchBarItemInteraction([item_id UTF8String],
|
||||
details);
|
||||
details.SetInteger("selectedIndex",
|
||||
((NSSegmentedControl*)sender).selectedSegment);
|
||||
details.SetBoolean(
|
||||
"isSelected",
|
||||
[((NSSegmentedControl*)sender)
|
||||
isSelectedForSegment:((NSSegmentedControl*)sender).selectedSegment]);
|
||||
window_->NotifyTouchBarItemInteraction([item_id UTF8String], details);
|
||||
}
|
||||
|
||||
- (void)scrubber:(NSScrubber*)scrubber didSelectItemAtIndex:(NSInteger)selectedIndex API_AVAILABLE(macosx(10.12.2)) {
|
||||
- (void)scrubber:(NSScrubber*)scrubber
|
||||
didSelectItemAtIndex:(NSInteger)selectedIndex
|
||||
API_AVAILABLE(macosx(10.12.2)) {
|
||||
base::DictionaryValue details;
|
||||
details.SetInteger("selectedIndex", selectedIndex);
|
||||
details.SetString("type", "select");
|
||||
window_->NotifyTouchBarItemInteraction([scrubber.identifier UTF8String], details);
|
||||
window_->NotifyTouchBarItemInteraction([scrubber.identifier UTF8String],
|
||||
details);
|
||||
}
|
||||
|
||||
- (void)scrubber:(NSScrubber*)scrubber didHighlightItemAtIndex:(NSInteger)highlightedIndex API_AVAILABLE(macosx(10.12.2)) {
|
||||
- (void)scrubber:(NSScrubber*)scrubber
|
||||
didHighlightItemAtIndex:(NSInteger)highlightedIndex
|
||||
API_AVAILABLE(macosx(10.12.2)) {
|
||||
base::DictionaryValue details;
|
||||
details.SetInteger("highlightedIndex", highlightedIndex);
|
||||
details.SetString("type", "highlight");
|
||||
window_->NotifyTouchBarItemInteraction([scrubber.identifier UTF8String], details);
|
||||
window_->NotifyTouchBarItemInteraction([scrubber.identifier UTF8String],
|
||||
details);
|
||||
}
|
||||
|
||||
- (NSTouchBarItemIdentifier)identifierFromID:(const std::string&)item_id
|
||||
|
@ -300,7 +333,8 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
- (NSTouchBarItem*)makeButtonForID:(NSString*)id
|
||||
withIdentifier:(NSString*)identifier {
|
||||
std::string s_id([id UTF8String]);
|
||||
if (![self hasItemWithID:s_id]) return nil;
|
||||
if (![self hasItemWithID:s_id])
|
||||
return nil;
|
||||
|
||||
mate::PersistentDictionary settings = settings_[s_id];
|
||||
base::scoped_nsobject<NSCustomTouchBarItem> item([[NSClassFromString(
|
||||
|
@ -346,7 +380,8 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
- (NSTouchBarItem*)makeLabelForID:(NSString*)id
|
||||
withIdentifier:(NSString*)identifier {
|
||||
std::string s_id([id UTF8String]);
|
||||
if (![self hasItemWithID:s_id]) return nil;
|
||||
if (![self hasItemWithID:s_id])
|
||||
return nil;
|
||||
|
||||
mate::PersistentDictionary settings = settings_[s_id];
|
||||
base::scoped_nsobject<NSCustomTouchBarItem> item([[NSClassFromString(
|
||||
|
@ -375,11 +410,12 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
- (NSTouchBarItem*)makeColorPickerForID:(NSString*)id
|
||||
withIdentifier:(NSString*)identifier {
|
||||
std::string s_id([id UTF8String]);
|
||||
if (![self hasItemWithID:s_id]) return nil;
|
||||
if (![self hasItemWithID:s_id])
|
||||
return nil;
|
||||
|
||||
mate::PersistentDictionary settings = settings_[s_id];
|
||||
base::scoped_nsobject<NSColorPickerTouchBarItem> item([[NSClassFromString(
|
||||
@"NSColorPickerTouchBarItem") alloc] initWithIdentifier:identifier]);
|
||||
@"NSColorPickerTouchBarItem") alloc] initWithIdentifier:identifier]);
|
||||
[item setTarget:self];
|
||||
[item setAction:@selector(colorPickerAction:)];
|
||||
[self updateColorPicker:item withSettings:settings];
|
||||
|
@ -390,13 +426,14 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
withSettings:(const mate::PersistentDictionary&)settings {
|
||||
std::vector<std::string> colors;
|
||||
if (settings.Get("availableColors", &colors) && !colors.empty()) {
|
||||
NSColorList* color_list = [[[NSColorList alloc] initWithName:@""] autorelease];
|
||||
NSColorList* color_list =
|
||||
[[[NSColorList alloc] initWithName:@""] autorelease];
|
||||
for (size_t i = 0; i < colors.size(); ++i) {
|
||||
[color_list insertColor:[self colorFromHexColorString:colors[i]]
|
||||
key:base::SysUTF8ToNSString(colors[i])
|
||||
atIndex:i];
|
||||
}
|
||||
item.colorList = color_list;
|
||||
item.colorList = color_list;
|
||||
}
|
||||
|
||||
std::string selectedColor;
|
||||
|
@ -408,7 +445,8 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
- (NSTouchBarItem*)makeSliderForID:(NSString*)id
|
||||
withIdentifier:(NSString*)identifier {
|
||||
std::string s_id([id UTF8String]);
|
||||
if (![self hasItemWithID:s_id]) return nil;
|
||||
if (![self hasItemWithID:s_id])
|
||||
return nil;
|
||||
|
||||
mate::PersistentDictionary settings = settings_[s_id];
|
||||
base::scoped_nsobject<NSSliderTouchBarItem> item([[NSClassFromString(
|
||||
|
@ -440,7 +478,8 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
- (NSTouchBarItem*)makePopoverForID:(NSString*)id
|
||||
withIdentifier:(NSString*)identifier {
|
||||
std::string s_id([id UTF8String]);
|
||||
if (![self hasItemWithID:s_id]) return nil;
|
||||
if (![self hasItemWithID:s_id])
|
||||
return nil;
|
||||
|
||||
mate::PersistentDictionary settings = settings_[s_id];
|
||||
base::scoped_nsobject<NSPopoverTouchBarItem> item([[NSClassFromString(
|
||||
|
@ -467,59 +506,72 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
mate::PersistentDictionary child;
|
||||
std::vector<mate::PersistentDictionary> items;
|
||||
if (settings.Get("child", &child) && child.Get("ordereredItems", &items)) {
|
||||
item.popoverTouchBar = [self touchBarFromItemIdentifiers:[self identifiersFromSettings:items]];
|
||||
item.popoverTouchBar =
|
||||
[self touchBarFromItemIdentifiers:[self identifiersFromSettings:items]];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSTouchBarItem*)makeGroupForID:(NSString*)id
|
||||
withIdentifier:(NSString*)identifier {
|
||||
std::string s_id([id UTF8String]);
|
||||
if (![self hasItemWithID:s_id]) return nil;
|
||||
if (![self hasItemWithID:s_id])
|
||||
return nil;
|
||||
mate::PersistentDictionary settings = settings_[s_id];
|
||||
|
||||
mate::PersistentDictionary child;
|
||||
if (!settings.Get("child", &child)) return nil;
|
||||
if (!settings.Get("child", &child))
|
||||
return nil;
|
||||
std::vector<mate::PersistentDictionary> items;
|
||||
if (!child.Get("ordereredItems", &items)) return nil;
|
||||
if (!child.Get("ordereredItems", &items))
|
||||
return nil;
|
||||
|
||||
NSMutableArray* generatedItems = [NSMutableArray array];
|
||||
NSMutableArray* identifiers = [self identifiersFromSettings:items];
|
||||
for (NSUInteger i = 0; i < [identifiers count]; ++i) {
|
||||
if ([identifiers objectAtIndex:i] != NSTouchBarItemIdentifierOtherItemsProxy) {
|
||||
NSTouchBarItem* generatedItem = [self makeItemForIdentifier:[identifiers objectAtIndex:i]];
|
||||
if ([identifiers objectAtIndex:i] !=
|
||||
NSTouchBarItemIdentifierOtherItemsProxy) {
|
||||
NSTouchBarItem* generatedItem =
|
||||
[self makeItemForIdentifier:[identifiers objectAtIndex:i]];
|
||||
if (generatedItem) {
|
||||
[generatedItems addObject:generatedItem];
|
||||
}
|
||||
}
|
||||
}
|
||||
return [NSClassFromString(@"NSGroupTouchBarItem") groupItemWithIdentifier:identifier
|
||||
items:generatedItems];
|
||||
return [NSClassFromString(@"NSGroupTouchBarItem")
|
||||
groupItemWithIdentifier:identifier
|
||||
items:generatedItems];
|
||||
}
|
||||
|
||||
- (void)updateGroup:(NSGroupTouchBarItem*)item
|
||||
withSettings:(const mate::PersistentDictionary&)settings API_AVAILABLE(macosx(10.12.2)) {
|
||||
|
||||
withSettings:(const mate::PersistentDictionary&)settings
|
||||
API_AVAILABLE(macosx(10.12.2)) {
|
||||
mate::PersistentDictionary child;
|
||||
if (!settings.Get("child", &child)) return;
|
||||
if (!settings.Get("child", &child))
|
||||
return;
|
||||
std::vector<mate::PersistentDictionary> items;
|
||||
if (!child.Get("ordereredItems", &items)) return;
|
||||
if (!child.Get("ordereredItems", &items))
|
||||
return;
|
||||
|
||||
item.groupTouchBar = [self touchBarFromItemIdentifiers:[self identifiersFromSettings:items]];
|
||||
item.groupTouchBar =
|
||||
[self touchBarFromItemIdentifiers:[self identifiersFromSettings:items]];
|
||||
}
|
||||
|
||||
- (NSTouchBarItem*)makeSegmentedControlForID:(NSString*)id
|
||||
withIdentifier:(NSString*)identifier API_AVAILABLE(macosx(10.12.2)) {
|
||||
withIdentifier:(NSString*)identifier
|
||||
API_AVAILABLE(macosx(10.12.2)) {
|
||||
std::string s_id([id UTF8String]);
|
||||
if (![self hasItemWithID:s_id]) return nil;
|
||||
if (![self hasItemWithID:s_id])
|
||||
return nil;
|
||||
|
||||
mate::PersistentDictionary settings = settings_[s_id];
|
||||
base::scoped_nsobject<NSCustomTouchBarItem> item([[NSClassFromString(
|
||||
@"NSCustomTouchBarItem") alloc] initWithIdentifier:identifier]);
|
||||
|
||||
NSSegmentedControl* control = [NSSegmentedControl segmentedControlWithLabels:[NSMutableArray array]
|
||||
trackingMode:NSSegmentSwitchTrackingSelectOne
|
||||
target:self
|
||||
action:@selector(segmentedControlAction:)];
|
||||
NSSegmentedControl* control = [NSSegmentedControl
|
||||
segmentedControlWithLabels:[NSMutableArray array]
|
||||
trackingMode:NSSegmentSwitchTrackingSelectOne
|
||||
target:self
|
||||
action:@selector(segmentedControlAction:)];
|
||||
control.tag = [id floatValue];
|
||||
[item setView:control];
|
||||
|
||||
|
@ -528,8 +580,8 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
}
|
||||
|
||||
- (void)updateSegmentedControl:(NSCustomTouchBarItem*)item
|
||||
withSettings:(const mate::PersistentDictionary&)settings API_AVAILABLE(macosx(10.12.2)) {
|
||||
|
||||
withSettings:(const mate::PersistentDictionary&)settings
|
||||
API_AVAILABLE(macosx(10.12.2)) {
|
||||
NSSegmentedControl* control = item.view;
|
||||
|
||||
std::string segmentStyle;
|
||||
|
@ -585,18 +637,23 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
}
|
||||
|
||||
- (NSTouchBarItem*)makeScrubberForID:(NSString*)id
|
||||
withIdentifier:(NSString*)identifier API_AVAILABLE(macosx(10.12.2)) {
|
||||
withIdentifier:(NSString*)identifier
|
||||
API_AVAILABLE(macosx(10.12.2)) {
|
||||
std::string s_id([id UTF8String]);
|
||||
if (![self hasItemWithID:s_id]) return nil;
|
||||
if (![self hasItemWithID:s_id])
|
||||
return nil;
|
||||
|
||||
mate::PersistentDictionary settings = settings_[s_id];
|
||||
base::scoped_nsobject<NSCustomTouchBarItem> item([[NSClassFromString(
|
||||
@"NSCustomTouchBarItem") alloc] initWithIdentifier:identifier]);
|
||||
|
||||
NSScrubber* scrubber = [[[NSClassFromString(@"NSScrubber") alloc] initWithFrame:NSZeroRect] autorelease];
|
||||
NSScrubber* scrubber = [[[NSClassFromString(@"NSScrubber") alloc]
|
||||
initWithFrame:NSZeroRect] autorelease];
|
||||
|
||||
[scrubber registerClass:NSClassFromString(@"NSScrubberTextItemView") forItemIdentifier:TextScrubberItemIdentifier];
|
||||
[scrubber registerClass:NSClassFromString(@"NSScrubberImageItemView") forItemIdentifier:ImageScrubberItemIdentifier];
|
||||
[scrubber registerClass:NSClassFromString(@"NSScrubberTextItemView")
|
||||
forItemIdentifier:TextScrubberItemIdentifier];
|
||||
[scrubber registerClass:NSClassFromString(@"NSScrubberImageItemView")
|
||||
forItemIdentifier:ImageScrubberItemIdentifier];
|
||||
|
||||
scrubber.delegate = self;
|
||||
scrubber.dataSource = self;
|
||||
|
@ -609,7 +666,8 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
}
|
||||
|
||||
- (void)updateScrubber:(NSCustomTouchBarItem*)item
|
||||
withSettings:(const mate::PersistentDictionary&)settings API_AVAILABLE(macosx(10.12.2)) {
|
||||
withSettings:(const mate::PersistentDictionary&)settings
|
||||
API_AVAILABLE(macosx(10.12.2)) {
|
||||
NSScrubber* scrubber = item.view;
|
||||
|
||||
bool showsArrowButtons = false;
|
||||
|
@ -622,17 +680,21 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
settings.Get("overlayStyle", &overlayStyle);
|
||||
|
||||
if (selectedStyle == "outline") {
|
||||
scrubber.selectionBackgroundStyle = [NSClassFromString(@"NSScrubberSelectionStyle") outlineOverlayStyle];
|
||||
scrubber.selectionBackgroundStyle =
|
||||
[NSClassFromString(@"NSScrubberSelectionStyle") outlineOverlayStyle];
|
||||
} else if (selectedStyle == "background") {
|
||||
scrubber.selectionBackgroundStyle = [NSClassFromString(@"NSScrubberSelectionStyle") roundedBackgroundStyle];
|
||||
scrubber.selectionBackgroundStyle =
|
||||
[NSClassFromString(@"NSScrubberSelectionStyle") roundedBackgroundStyle];
|
||||
} else {
|
||||
scrubber.selectionBackgroundStyle = nil;
|
||||
}
|
||||
|
||||
if (overlayStyle == "outline") {
|
||||
scrubber.selectionOverlayStyle = [NSClassFromString(@"NSScrubberSelectionStyle") outlineOverlayStyle];
|
||||
scrubber.selectionOverlayStyle =
|
||||
[NSClassFromString(@"NSScrubberSelectionStyle") outlineOverlayStyle];
|
||||
} else if (overlayStyle == "background") {
|
||||
scrubber.selectionOverlayStyle = [NSClassFromString(@"NSScrubberSelectionStyle") roundedBackgroundStyle];
|
||||
scrubber.selectionOverlayStyle =
|
||||
[NSClassFromString(@"NSScrubberSelectionStyle") roundedBackgroundStyle];
|
||||
} else {
|
||||
scrubber.selectionOverlayStyle = nil;
|
||||
}
|
||||
|
@ -652,9 +714,11 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
[scrubber reloadData];
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfItemsForScrubber:(NSScrubber*)scrubber API_AVAILABLE(macosx(10.12.2)) {
|
||||
- (NSInteger)numberOfItemsForScrubber:(NSScrubber*)scrubber
|
||||
API_AVAILABLE(macosx(10.12.2)) {
|
||||
std::string s_id([[scrubber identifier] UTF8String]);
|
||||
if (![self hasItemWithID:s_id]) return 0;
|
||||
if (![self hasItemWithID:s_id])
|
||||
return 0;
|
||||
|
||||
mate::PersistentDictionary settings = settings_[s_id];
|
||||
std::vector<mate::PersistentDictionary> items;
|
||||
|
@ -663,15 +727,19 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
}
|
||||
|
||||
- (NSScrubberItemView*)scrubber:(NSScrubber*)scrubber
|
||||
viewForItemAtIndex:(NSInteger)index API_AVAILABLE(macosx(10.12.2)) {
|
||||
viewForItemAtIndex:(NSInteger)index
|
||||
API_AVAILABLE(macosx(10.12.2)) {
|
||||
std::string s_id([[scrubber identifier] UTF8String]);
|
||||
if (![self hasItemWithID:s_id]) return nil;
|
||||
if (![self hasItemWithID:s_id])
|
||||
return nil;
|
||||
|
||||
mate::PersistentDictionary settings = settings_[s_id];
|
||||
std::vector<mate::PersistentDictionary> items;
|
||||
if (!settings.Get("items", &items)) return nil;
|
||||
if (!settings.Get("items", &items))
|
||||
return nil;
|
||||
|
||||
if (index >= static_cast<NSInteger>(items.size())) return nil;
|
||||
if (index >= static_cast<NSInteger>(items.size()))
|
||||
return nil;
|
||||
|
||||
mate::PersistentDictionary item = items[index];
|
||||
|
||||
|
@ -679,13 +747,14 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
std::string title;
|
||||
|
||||
if (item.Get("label", &title)) {
|
||||
NSScrubberTextItemView* view = [scrubber makeItemWithIdentifier:TextScrubberItemIdentifier
|
||||
owner:self];
|
||||
NSScrubberTextItemView* view =
|
||||
[scrubber makeItemWithIdentifier:TextScrubberItemIdentifier owner:self];
|
||||
view.title = base::SysUTF8ToNSString(title);
|
||||
itemView = view;
|
||||
} else {
|
||||
NSScrubberImageItemView* view = [scrubber makeItemWithIdentifier:ImageScrubberItemIdentifier
|
||||
owner:self];
|
||||
NSScrubberImageItemView* view =
|
||||
[scrubber makeItemWithIdentifier:ImageScrubberItemIdentifier
|
||||
owner:self];
|
||||
gfx::Image image;
|
||||
if (item.Get("icon", &image)) {
|
||||
view.image = image.AsNSImage();
|
||||
|
@ -696,30 +765,38 @@ static NSString* const ImageScrubberItemIdentifier = @"scrubber.image.item";
|
|||
return itemView;
|
||||
}
|
||||
|
||||
- (NSSize)scrubber:(NSScrubber *)scrubber layout:(NSScrubberFlowLayout *)layout sizeForItemAtIndex:(NSInteger)itemIndex
|
||||
API_AVAILABLE(macosx(10.12.2)) {
|
||||
- (NSSize)scrubber:(NSScrubber*)scrubber
|
||||
layout:(NSScrubberFlowLayout*)layout
|
||||
sizeForItemAtIndex:(NSInteger)itemIndex API_AVAILABLE(macosx(10.12.2)) {
|
||||
NSInteger width = 50;
|
||||
NSInteger height = 30;
|
||||
NSInteger margin = 15;
|
||||
NSSize defaultSize = NSMakeSize(width, height);
|
||||
|
||||
std::string s_id([[scrubber identifier] UTF8String]);
|
||||
if (![self hasItemWithID:s_id]) return defaultSize;
|
||||
if (![self hasItemWithID:s_id])
|
||||
return defaultSize;
|
||||
|
||||
mate::PersistentDictionary settings = settings_[s_id];
|
||||
std::vector<mate::PersistentDictionary> items;
|
||||
if (!settings.Get("items", &items)) return defaultSize;
|
||||
if (!settings.Get("items", &items))
|
||||
return defaultSize;
|
||||
|
||||
if (itemIndex >= static_cast<NSInteger>(items.size())) return defaultSize;
|
||||
if (itemIndex >= static_cast<NSInteger>(items.size()))
|
||||
return defaultSize;
|
||||
|
||||
mate::PersistentDictionary item = items[itemIndex];
|
||||
std::string title;
|
||||
|
||||
if (item.Get("label", &title)) {
|
||||
NSSize size = NSMakeSize(CGFLOAT_MAX, CGFLOAT_MAX);
|
||||
NSRect textRect = [base::SysUTF8ToNSString(title) boundingRectWithSize:size
|
||||
options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
|
||||
attributes:@{ NSFontAttributeName: [NSFont systemFontOfSize:0]}];
|
||||
NSRect textRect = [base::SysUTF8ToNSString(title)
|
||||
boundingRectWithSize:size
|
||||
options:NSStringDrawingUsesLineFragmentOrigin |
|
||||
NSStringDrawingUsesFontLeading
|
||||
attributes:@{
|
||||
NSFontAttributeName : [NSFont systemFontOfSize:0]
|
||||
}];
|
||||
|
||||
width = textRect.size.width + margin;
|
||||
} else {
|
||||
|
|
|
@ -9,11 +9,9 @@
|
|||
|
||||
namespace atom {
|
||||
|
||||
ViewsDelegateMac::ViewsDelegateMac() {
|
||||
}
|
||||
ViewsDelegateMac::ViewsDelegateMac() {}
|
||||
|
||||
ViewsDelegateMac::~ViewsDelegateMac() {
|
||||
}
|
||||
ViewsDelegateMac::~ViewsDelegateMac() {}
|
||||
|
||||
void ViewsDelegateMac::OnBeforeWidgetInit(
|
||||
views::Widget::InitParams* params,
|
||||
|
|
|
@ -63,7 +63,8 @@
|
|||
@implementation AtomAccessoryView
|
||||
|
||||
- (void)dealloc {
|
||||
auto* popupButton = static_cast<NSPopUpButton*>([[self subviews] objectAtIndex: 1]);
|
||||
auto* popupButton =
|
||||
static_cast<NSPopUpButton*>([[self subviews] objectAtIndex:1]);
|
||||
[[popupButton target] release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
@ -88,7 +89,8 @@ void SetAllowedFileTypes(NSSavePanel* dialog, const Filters& filters) {
|
|||
base::SysUTF8ToCFStringRef(filter.first));
|
||||
[filter_names addObject:base::mac::CFToNSCast(name_cf.get())];
|
||||
for (const std::string& ext : filter.second) {
|
||||
base::ScopedCFTypeRef<CFStringRef> ext_cf(base::SysUTF8ToCFStringRef(ext));
|
||||
base::ScopedCFTypeRef<CFStringRef> ext_cf(
|
||||
base::SysUTF8ToCFStringRef(ext));
|
||||
[file_type_set addObject:base::mac::CFToNSCast(ext_cf.get())];
|
||||
}
|
||||
[file_types_list addObject:[file_type_set allObjects]];
|
||||
|
@ -121,10 +123,12 @@ void SetAllowedFileTypes(NSSavePanel* dialog, const Filters& filters) {
|
|||
[label setBezeled:NO];
|
||||
[label setDrawsBackground:NO];
|
||||
|
||||
NSPopUpButton* popupButton = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(50.0, 2, 140, 22.0)
|
||||
pullsDown:NO];
|
||||
PopUpButtonHandler* popUpButtonHandler = [[PopUpButtonHandler alloc] initWithPanel:dialog
|
||||
andTypesList:file_types_list];
|
||||
NSPopUpButton* popupButton =
|
||||
[[NSPopUpButton alloc] initWithFrame:NSMakeRect(50.0, 2, 140, 22.0)
|
||||
pullsDown:NO];
|
||||
PopUpButtonHandler* popUpButtonHandler =
|
||||
[[PopUpButtonHandler alloc] initWithPanel:dialog
|
||||
andTypesList:file_types_list];
|
||||
[popupButton addItemsWithTitles:filter_names];
|
||||
[popupButton setTarget:popUpButtonHandler];
|
||||
[popupButton setAction:@selector(selectFormat:)];
|
||||
|
@ -135,8 +139,7 @@ void SetAllowedFileTypes(NSSavePanel* dialog, const Filters& filters) {
|
|||
[dialog setAccessoryView:[accessoryView autorelease]];
|
||||
}
|
||||
|
||||
void SetupDialog(NSSavePanel* dialog,
|
||||
const DialogSettings& settings) {
|
||||
void SetupDialog(NSSavePanel* dialog, const DialogSettings& settings) {
|
||||
if (!settings.title.empty())
|
||||
[dialog setTitle:base::SysUTF8ToNSString(settings.title)];
|
||||
|
||||
|
@ -147,7 +150,8 @@ void SetupDialog(NSSavePanel* dialog,
|
|||
[dialog setMessage:base::SysUTF8ToNSString(settings.message)];
|
||||
|
||||
if (!settings.name_field_label.empty())
|
||||
[dialog setNameFieldLabel:base::SysUTF8ToNSString(settings.name_field_label)];
|
||||
[dialog
|
||||
setNameFieldLabel:base::SysUTF8ToNSString(settings.name_field_label)];
|
||||
|
||||
[dialog setShowsTagField:settings.shows_tag_field];
|
||||
|
||||
|
@ -213,9 +217,9 @@ int RunModalDialog(NSSavePanel* dialog, const DialogSettings& settings) {
|
|||
|
||||
[dialog beginSheetModalForWindow:window
|
||||
completionHandler:^(NSInteger c) {
|
||||
chosen = c;
|
||||
[NSApp stopModal];
|
||||
}];
|
||||
chosen = c;
|
||||
[NSApp stopModal];
|
||||
}];
|
||||
[NSApp runModalForWindow:window];
|
||||
}
|
||||
|
||||
|
@ -225,23 +229,25 @@ int RunModalDialog(NSSavePanel* dialog, const DialogSettings& settings) {
|
|||
// Create bookmark data and serialise it into a base64 string.
|
||||
std::string GetBookmarkDataFromNSURL(NSURL* url) {
|
||||
// Create the file if it doesn't exist (necessary for NSSavePanel options).
|
||||
NSFileManager *defaultManager = [NSFileManager defaultManager];
|
||||
if (![defaultManager fileExistsAtPath: [url path]]) {
|
||||
[defaultManager createFileAtPath: [url path] contents: nil attributes: nil];
|
||||
NSFileManager* defaultManager = [NSFileManager defaultManager];
|
||||
if (![defaultManager fileExistsAtPath:[url path]]) {
|
||||
[defaultManager createFileAtPath:[url path] contents:nil attributes:nil];
|
||||
}
|
||||
|
||||
NSError *error = nil;
|
||||
NSData *bookmarkData = [url bookmarkDataWithOptions: NSURLBookmarkCreationWithSecurityScope
|
||||
includingResourceValuesForKeys: nil
|
||||
relativeToURL: nil
|
||||
error: &error];
|
||||
NSError* error = nil;
|
||||
NSData* bookmarkData =
|
||||
[url bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope
|
||||
includingResourceValuesForKeys:nil
|
||||
relativeToURL:nil
|
||||
error:&error];
|
||||
if (error != nil) {
|
||||
// Send back an empty string if there was an error.
|
||||
return "";
|
||||
} else {
|
||||
// Encode NSData in base64 then convert to NSString.
|
||||
NSString *base64data = [[NSString alloc] initWithData: [bookmarkData base64EncodedDataWithOptions: 0]
|
||||
encoding: NSUTF8StringEncoding];
|
||||
NSString* base64data = [[NSString alloc]
|
||||
initWithData:[bookmarkData base64EncodedDataWithOptions:0]
|
||||
encoding:NSUTF8StringEncoding];
|
||||
return base::SysNSStringToUTF8(base64data);
|
||||
}
|
||||
}
|
||||
|
@ -280,30 +286,31 @@ bool ShowOpenDialog(const DialogSettings& settings,
|
|||
return true;
|
||||
}
|
||||
|
||||
void OpenDialogCompletion(int chosen, NSOpenPanel* dialog,
|
||||
void OpenDialogCompletion(int chosen,
|
||||
NSOpenPanel* dialog,
|
||||
const DialogSettings& settings,
|
||||
const OpenDialogCallback& callback) {
|
||||
if (chosen == NSFileHandlingPanelCancelButton) {
|
||||
#if defined(MAS_BUILD)
|
||||
callback.Run(false, std::vector<base::FilePath>(),
|
||||
std::vector<std::string>());
|
||||
#else
|
||||
callback.Run(false, std::vector<base::FilePath>());
|
||||
#endif
|
||||
#if defined(MAS_BUILD)
|
||||
callback.Run(false, std::vector<base::FilePath>(),
|
||||
std::vector<std::string>());
|
||||
#else
|
||||
callback.Run(false, std::vector<base::FilePath>());
|
||||
#endif
|
||||
} else {
|
||||
std::vector<base::FilePath> paths;
|
||||
#if defined(MAS_BUILD)
|
||||
std::vector<std::string> bookmarks;
|
||||
if (settings.security_scoped_bookmarks) {
|
||||
ReadDialogPathsWithBookmarks(dialog, &paths, &bookmarks);
|
||||
} else {
|
||||
ReadDialogPaths(dialog, &paths);
|
||||
}
|
||||
callback.Run(true, paths, bookmarks);
|
||||
#else
|
||||
#if defined(MAS_BUILD)
|
||||
std::vector<std::string> bookmarks;
|
||||
if (settings.security_scoped_bookmarks) {
|
||||
ReadDialogPathsWithBookmarks(dialog, &paths, &bookmarks);
|
||||
} else {
|
||||
ReadDialogPaths(dialog, &paths);
|
||||
callback.Run(true, paths);
|
||||
#endif
|
||||
}
|
||||
callback.Run(true, paths, bookmarks);
|
||||
#else
|
||||
ReadDialogPaths(dialog, &paths);
|
||||
callback.Run(true, paths);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -327,13 +334,12 @@ void ShowOpenDialog(const DialogSettings& settings,
|
|||
NSWindow* window = settings.parent_window->GetNativeWindow();
|
||||
[dialog beginSheetModalForWindow:window
|
||||
completionHandler:^(NSInteger chosen) {
|
||||
OpenDialogCompletion(chosen, dialog, settings, callback);
|
||||
}];
|
||||
OpenDialogCompletion(chosen, dialog, settings, callback);
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
bool ShowSaveDialog(const DialogSettings& settings,
|
||||
base::FilePath* path) {
|
||||
bool ShowSaveDialog(const DialogSettings& settings, base::FilePath* path) {
|
||||
DCHECK(path);
|
||||
NSSavePanel* dialog = [NSSavePanel savePanel];
|
||||
|
||||
|
@ -347,26 +353,27 @@ bool ShowSaveDialog(const DialogSettings& settings,
|
|||
return true;
|
||||
}
|
||||
|
||||
void SaveDialogCompletion(int chosen, NSSavePanel* dialog,
|
||||
void SaveDialogCompletion(int chosen,
|
||||
NSSavePanel* dialog,
|
||||
const DialogSettings& settings,
|
||||
const SaveDialogCallback& callback) {
|
||||
if (chosen == NSFileHandlingPanelCancelButton) {
|
||||
#if defined(MAS_BUILD)
|
||||
callback.Run(false, base::FilePath(), "");
|
||||
#else
|
||||
callback.Run(false, base::FilePath());
|
||||
#endif
|
||||
#if defined(MAS_BUILD)
|
||||
callback.Run(false, base::FilePath(), "");
|
||||
#else
|
||||
callback.Run(false, base::FilePath());
|
||||
#endif
|
||||
} else {
|
||||
std::string path = base::SysNSStringToUTF8([[dialog URL] path]);
|
||||
#if defined(MAS_BUILD)
|
||||
std::string bookmark;
|
||||
if (settings.security_scoped_bookmarks) {
|
||||
bookmark = GetBookmarkDataFromNSURL([dialog URL]);
|
||||
}
|
||||
callback.Run(true, base::FilePath(path), bookmark);
|
||||
#else
|
||||
callback.Run(true, base::FilePath(path));
|
||||
#endif
|
||||
#if defined(MAS_BUILD)
|
||||
std::string bookmark;
|
||||
if (settings.security_scoped_bookmarks) {
|
||||
bookmark = GetBookmarkDataFromNSURL([dialog URL]);
|
||||
}
|
||||
callback.Run(true, base::FilePath(path), bookmark);
|
||||
#else
|
||||
callback.Run(true, base::FilePath(path));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -388,8 +395,8 @@ void ShowSaveDialog(const DialogSettings& settings,
|
|||
NSWindow* window = settings.parent_window->GetNativeWindow();
|
||||
[dialog beginSheetModalForWindow:window
|
||||
completionHandler:^(NSInteger chosen) {
|
||||
SaveDialogCompletion(chosen, dialog, settings, callback);
|
||||
}];
|
||||
SaveDialogCompletion(chosen, dialog, settings, callback);
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -141,9 +141,9 @@ int ShowMessageBox(NativeWindow* parent_window,
|
|||
const std::string& message,
|
||||
const std::string& detail,
|
||||
const gfx::ImageSkia& icon) {
|
||||
NSAlert* alert = CreateNSAlert(parent_window, type, buttons, default_id,
|
||||
cancel_id, title, message, detail, "", false,
|
||||
icon);
|
||||
NSAlert* alert =
|
||||
CreateNSAlert(parent_window, type, buttons, default_id, cancel_id, title,
|
||||
message, detail, "", false, icon);
|
||||
|
||||
// Use runModal for synchronous alert without parent, since we don't have a
|
||||
// window to wait for.
|
||||
|
@ -194,10 +194,11 @@ void ShowMessageBox(NativeWindow* parent_window,
|
|||
callEndModal:false];
|
||||
|
||||
NSWindow* window = parent_window ? parent_window->GetNativeWindow() : nil;
|
||||
[alert beginSheetModalForWindow:window
|
||||
modalDelegate:delegate
|
||||
[alert
|
||||
beginSheetModalForWindow:window
|
||||
modalDelegate:delegate
|
||||
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:)
|
||||
contextInfo:nil];
|
||||
contextInfo:nil];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
|
||||
#include "atom/browser/ui/tray_icon_cocoa.h"
|
||||
|
||||
#include "atom/browser/ui/cocoa/atom_menu_controller.h"
|
||||
#include "atom/browser/ui/cocoa/NSString+ANSI.h"
|
||||
#include "atom/browser/ui/cocoa/atom_menu_controller.h"
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
#include "ui/display/screen.h"
|
||||
#include "ui/events/cocoa/cocoa_event_utils.h"
|
||||
#include "ui/gfx/image/image.h"
|
||||
#include "ui/gfx/mac/coordinate_conversion.h"
|
||||
#include "ui/display/screen.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -22,8 +22,8 @@ const CGFloat kVerticalTitleMargin = 2;
|
|||
} // namespace
|
||||
|
||||
@interface StatusItemView : NSView {
|
||||
atom::TrayIconCocoa* trayIcon_; // weak
|
||||
AtomMenuController* menuController_; // weak
|
||||
atom::TrayIconCocoa* trayIcon_; // weak
|
||||
AtomMenuController* menuController_; // weak
|
||||
atom::TrayIcon::HighlightMode highlight_mode_;
|
||||
BOOL forceHighlight_;
|
||||
BOOL inMouseEventSequence_;
|
||||
|
@ -47,24 +47,26 @@ const CGFloat kVerticalTitleMargin = 2;
|
|||
forceHighlight_ = NO;
|
||||
inMouseEventSequence_ = NO;
|
||||
|
||||
if ((self = [super initWithFrame: CGRectZero])) {
|
||||
[self registerForDraggedTypes: @[
|
||||
if ((self = [super initWithFrame:CGRectZero])) {
|
||||
[self registerForDraggedTypes:@[
|
||||
NSFilenamesPboardType,
|
||||
NSStringPboardType,
|
||||
]];
|
||||
|
||||
// Create the status item.
|
||||
NSStatusItem * item = [[NSStatusBar systemStatusBar]
|
||||
statusItemWithLength:NSVariableStatusItemLength];
|
||||
NSStatusItem* item = [[NSStatusBar systemStatusBar]
|
||||
statusItemWithLength:NSVariableStatusItemLength];
|
||||
statusItem_.reset([item retain]);
|
||||
[statusItem_ setView:self];
|
||||
// Finalize setup by sizing our views
|
||||
[self updateDimensions];
|
||||
|
||||
// Add NSTrackingArea for listening to mouseEnter, mouseExit, and mouseMove events
|
||||
// Add NSTrackingArea for listening to mouseEnter, mouseExit, and mouseMove
|
||||
// events
|
||||
trackingArea_.reset([[NSTrackingArea alloc]
|
||||
initWithRect:[self bounds]
|
||||
options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveAlways
|
||||
options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved |
|
||||
NSTrackingActiveAlways
|
||||
owner:self
|
||||
userInfo:nil]);
|
||||
[self addTrackingArea:trackingArea_];
|
||||
|
@ -73,8 +75,8 @@ const CGFloat kVerticalTitleMargin = 2;
|
|||
}
|
||||
|
||||
- (void)updateDimensions {
|
||||
NSStatusBar * bar = [NSStatusBar systemStatusBar];
|
||||
[self setFrame: NSMakeRect(0, 0, [self fullWidth], [bar thickness])];
|
||||
NSStatusBar* bar = [NSStatusBar systemStatusBar];
|
||||
[self setFrame:NSMakeRect(0, 0, [self fullWidth], [bar thickness])];
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
|
@ -110,25 +112,23 @@ const CGFloat kVerticalTitleMargin = 2;
|
|||
if ([image isTemplate] == YES) {
|
||||
NSImage* imageWithColor = [[image copy] autorelease];
|
||||
[imageWithColor lockFocus];
|
||||
[[self colorWithHighlight: [self isHighlighted]] set];
|
||||
CGRect imageBounds = CGRectMake(0,0, image.size.width, image.size.height);
|
||||
[[self colorWithHighlight:[self isHighlighted]] set];
|
||||
CGRect imageBounds = CGRectMake(0, 0, image.size.width, image.size.height);
|
||||
NSRectFillUsingOperation(imageBounds, NSCompositeSourceAtop);
|
||||
[imageWithColor unlockFocus];
|
||||
image = imageWithColor;
|
||||
}
|
||||
|
||||
// Draw the image
|
||||
[image drawInRect: CGRectMake(
|
||||
roundf(([self iconWidth] - image.size.width) / 2),
|
||||
roundf((thickness - image.size.height) / 2),
|
||||
image.size.width,
|
||||
image.size.height
|
||||
)];
|
||||
[image
|
||||
drawInRect:CGRectMake(roundf(([self iconWidth] - image.size.width) / 2),
|
||||
roundf((thickness - image.size.height) / 2),
|
||||
image.size.width, image.size.height)];
|
||||
|
||||
if (title_) {
|
||||
// Draw title.
|
||||
NSRect titleDrawRect = NSMakeRect(
|
||||
[self iconWidth], -kVerticalTitleMargin, [self titleWidth], thickness);
|
||||
NSRect titleDrawRect = NSMakeRect([self iconWidth], -kVerticalTitleMargin,
|
||||
[self titleWidth], thickness);
|
||||
[attributedTitle_ drawInRect:titleDrawRect];
|
||||
}
|
||||
}
|
||||
|
@ -139,7 +139,6 @@ const CGFloat kVerticalTitleMargin = 2;
|
|||
return mode && [mode isEqualToString:@"Dark"];
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)isHighlighted {
|
||||
BOOL highlight = [self shouldHighlight];
|
||||
return highlight | [self isDarkMode];
|
||||
|
@ -184,9 +183,11 @@ const CGFloat kVerticalTitleMargin = 2;
|
|||
}
|
||||
|
||||
- (NSColor*)colorWithHighlight:(BOOL)highlight {
|
||||
return highlight ?
|
||||
[NSColor whiteColor] :
|
||||
[NSColor colorWithRed:0.265625 green:0.25390625 blue:0.234375 alpha:1.0];
|
||||
return highlight ? [NSColor whiteColor]
|
||||
: [NSColor colorWithRed:0.265625
|
||||
green:0.25390625
|
||||
blue:0.234375
|
||||
alpha:1.0];
|
||||
}
|
||||
|
||||
- (void)setImage:(NSImage*)image {
|
||||
|
@ -215,11 +216,9 @@ const CGFloat kVerticalTitleMargin = 2;
|
|||
[self updateDimensions];
|
||||
}
|
||||
|
||||
|
||||
- (void)updateAttributedTitle {
|
||||
NSDictionary* attributes = @{
|
||||
NSFontAttributeName:[NSFont menuBarFontOfSize:0]
|
||||
};
|
||||
NSDictionary* attributes =
|
||||
@{NSFontAttributeName : [NSFont menuBarFontOfSize:0]};
|
||||
|
||||
if (ANSI_) {
|
||||
NSCharacterSet* whites = [NSCharacterSet whitespaceCharacterSet];
|
||||
|
@ -231,20 +230,20 @@ const CGFloat kVerticalTitleMargin = 2;
|
|||
}
|
||||
|
||||
// check title_ being nil
|
||||
NSString *title = @"";
|
||||
NSString* title = @"";
|
||||
if (title_)
|
||||
title = title_;
|
||||
|
||||
attributedTitle_.reset([[NSMutableAttributedString alloc]
|
||||
initWithString:title
|
||||
attributes:attributes]);
|
||||
initWithString:title
|
||||
attributes:attributes]);
|
||||
|
||||
//NSFontAttributeName:[NSFont menuBarFontOfSize:0],
|
||||
//NSForegroundColorAttributeName:[self colorWithHighlight: highlight]
|
||||
// NSFontAttributeName:[NSFont menuBarFontOfSize:0],
|
||||
// NSForegroundColorAttributeName:[self colorWithHighlight: highlight]
|
||||
[attributedTitle_ addAttributes:attributes
|
||||
range:NSMakeRange(0, [attributedTitle_ length])];
|
||||
[attributedTitle_ addAttribute:NSForegroundColorAttributeName
|
||||
value:[self colorWithHighlight: [self isHighlighted]]
|
||||
value:[self colorWithHighlight:[self isHighlighted]]
|
||||
range:NSMakeRange(0, [attributedTitle_ length])];
|
||||
}
|
||||
|
||||
|
@ -259,10 +258,10 @@ const CGFloat kVerticalTitleMargin = 2;
|
|||
|
||||
- (void)mouseUp:(NSEvent*)event {
|
||||
if (!inMouseEventSequence_) {
|
||||
// If the menu is showing, when user clicked the tray icon, the `mouseDown`
|
||||
// event will be dissmissed, we need to close the menu at this time.
|
||||
[self setNeedsDisplay:YES];
|
||||
return;
|
||||
// If the menu is showing, when user clicked the tray icon, the `mouseDown`
|
||||
// event will be dissmissed, we need to close the menu at this time.
|
||||
[self setNeedsDisplay:YES];
|
||||
return;
|
||||
}
|
||||
inMouseEventSequence_ = NO;
|
||||
|
||||
|
@ -299,9 +298,9 @@ const CGFloat kVerticalTitleMargin = 2;
|
|||
- (void)popUpContextMenu:(atom::AtomMenuModel*)menu_model {
|
||||
// Show a custom menu.
|
||||
if (menu_model) {
|
||||
base::scoped_nsobject<AtomMenuController> menuController(
|
||||
[[AtomMenuController alloc] initWithModel:menu_model
|
||||
useDefaultAccelerator:NO]);
|
||||
base::scoped_nsobject<AtomMenuController> menuController([
|
||||
[AtomMenuController alloc] initWithModel:menu_model
|
||||
useDefaultAccelerator:NO]);
|
||||
forceHighlight_ = YES; // Should highlight when showing menu.
|
||||
[self setNeedsDisplay:YES];
|
||||
[statusItem_ popUpStatusItemMenu:[menuController menu]];
|
||||
|
@ -326,7 +325,7 @@ const CGFloat kVerticalTitleMargin = 2;
|
|||
ui::EventFlagsFromModifiers([event modifierFlags]));
|
||||
}
|
||||
|
||||
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender {
|
||||
- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender {
|
||||
trayIcon_->NotifyDragEntered();
|
||||
return NSDragOperationCopy;
|
||||
}
|
||||
|
@ -349,11 +348,11 @@ const CGFloat kVerticalTitleMargin = 2;
|
|||
ui::EventFlagsFromModifiers([event modifierFlags]));
|
||||
}
|
||||
|
||||
- (void)draggingExited:(id <NSDraggingInfo>)sender {
|
||||
- (void)draggingExited:(id<NSDraggingInfo>)sender {
|
||||
trayIcon_->NotifyDragExited();
|
||||
}
|
||||
|
||||
- (void)draggingEnded:(id <NSDraggingInfo>)sender {
|
||||
- (void)draggingEnded:(id<NSDraggingInfo>)sender {
|
||||
trayIcon_->NotifyDragEnded();
|
||||
|
||||
if (NSPointInRect([sender draggingLocation], self.frame)) {
|
||||
|
@ -361,7 +360,7 @@ const CGFloat kVerticalTitleMargin = 2;
|
|||
}
|
||||
}
|
||||
|
||||
- (BOOL)handleDrop:(id <NSDraggingInfo>)sender {
|
||||
- (BOOL)handleDrop:(id<NSDraggingInfo>)sender {
|
||||
NSPasteboard* pboard = [sender draggingPasteboard];
|
||||
|
||||
if ([[pboard types] containsObject:NSFilenamesPboardType]) {
|
||||
|
@ -380,11 +379,11 @@ const CGFloat kVerticalTitleMargin = 2;
|
|||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender {
|
||||
- (BOOL)prepareForDragOperation:(id<NSDraggingInfo>)sender {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender {
|
||||
- (BOOL)performDragOperation:(id<NSDraggingInfo>)sender {
|
||||
[self handleDrop:sender];
|
||||
return YES;
|
||||
}
|
||||
|
@ -405,8 +404,7 @@ const CGFloat kVerticalTitleMargin = 2;
|
|||
|
||||
namespace atom {
|
||||
|
||||
TrayIconCocoa::TrayIconCocoa() : menu_model_(nullptr) {
|
||||
}
|
||||
TrayIconCocoa::TrayIconCocoa() : menu_model_(nullptr) {}
|
||||
|
||||
TrayIconCocoa::~TrayIconCocoa() {
|
||||
[status_item_view_ removeItem];
|
||||
|
@ -419,8 +417,7 @@ void TrayIconCocoa::SetImage(const gfx::Image& image) {
|
|||
[status_item_view_ setImage:image.AsNSImage()];
|
||||
} else {
|
||||
status_item_view_.reset(
|
||||
[[StatusItemView alloc] initWithImage:image.AsNSImage()
|
||||
icon:this]);
|
||||
[[StatusItemView alloc] initWithImage:image.AsNSImage() icon:this]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,16 +20,19 @@ NSData* bufferFromNSImage(NSImage* image) {
|
|||
CGImageRef ref = [image CGImageForProposedRect:nil context:nil hints:nil];
|
||||
NSBitmapImageRep* rep = [[NSBitmapImageRep alloc] initWithCGImage:ref];
|
||||
[rep setSize:[image size]];
|
||||
return [rep representationUsingType:NSPNGFileType properties:[[NSDictionary alloc] init]];
|
||||
return [rep representationUsingType:NSPNGFileType
|
||||
properties:[[NSDictionary alloc] init]];
|
||||
}
|
||||
|
||||
double safeShift(double in, double def) {
|
||||
if (in >= 0 || in <= 1 || in == def) return in;
|
||||
if (in >= 0 || in <= 1 || in == def)
|
||||
return in;
|
||||
return def;
|
||||
}
|
||||
|
||||
mate::Handle<NativeImage> NativeImage::CreateFromNamedImage(
|
||||
mate::Arguments* args, const std::string& name) {
|
||||
mate::Arguments* args,
|
||||
const std::string& name) {
|
||||
@autoreleasepool {
|
||||
std::vector<double> hsl_shift;
|
||||
NSImage* image = [NSImage imageNamed:base::SysUTF8ToNSString(name)];
|
||||
|
@ -41,18 +44,19 @@ mate::Handle<NativeImage> NativeImage::CreateFromNamedImage(
|
|||
|
||||
if (args->GetNext(&hsl_shift) && hsl_shift.size() == 3) {
|
||||
gfx::Image gfx_image = gfx::Image::CreateFrom1xPNGBytes(
|
||||
reinterpret_cast<const unsigned char*>((char *) [png_data bytes]), [png_data length]);
|
||||
color_utils::HSL shift = {
|
||||
safeShift(hsl_shift[0], -1),
|
||||
safeShift(hsl_shift[1], 0.5),
|
||||
safeShift(hsl_shift[2], 0.5)
|
||||
};
|
||||
png_data = bufferFromNSImage(gfx::Image(
|
||||
gfx::ImageSkiaOperations::CreateHSLShiftedImage(
|
||||
gfx_image.AsImageSkia(), shift)).CopyNSImage());
|
||||
reinterpret_cast<const unsigned char*>((char*)[png_data bytes]),
|
||||
[png_data length]);
|
||||
color_utils::HSL shift = {safeShift(hsl_shift[0], -1),
|
||||
safeShift(hsl_shift[1], 0.5),
|
||||
safeShift(hsl_shift[2], 0.5)};
|
||||
png_data = bufferFromNSImage(
|
||||
gfx::Image(gfx::ImageSkiaOperations::CreateHSLShiftedImage(
|
||||
gfx_image.AsImageSkia(), shift))
|
||||
.CopyNSImage());
|
||||
}
|
||||
|
||||
return CreateFromPNG(args->isolate(), (char *) [png_data bytes], [png_data length]);
|
||||
return CreateFromPNG(args->isolate(), (char*)[png_data bytes],
|
||||
[png_data length]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,11 +20,9 @@
|
|||
|
||||
namespace crash_reporter {
|
||||
|
||||
CrashReporterMac::CrashReporterMac() {
|
||||
}
|
||||
CrashReporterMac::CrashReporterMac() {}
|
||||
|
||||
CrashReporterMac::~CrashReporterMac() {
|
||||
}
|
||||
CrashReporterMac::~CrashReporterMac() {}
|
||||
|
||||
void CrashReporterMac::InitBreakpad(const std::string& product_name,
|
||||
const std::string& version,
|
||||
|
@ -45,17 +43,13 @@ void CrashReporterMac::InitBreakpad(const std::string& product_name,
|
|||
framework_bundle_path.Append("Resources").Append("crashpad_handler");
|
||||
|
||||
std::vector<std::string> args = {
|
||||
"--no-rate-limit",
|
||||
"--no-upload-gzip", // not all servers accept gzip
|
||||
"--no-rate-limit",
|
||||
"--no-upload-gzip", // not all servers accept gzip
|
||||
};
|
||||
|
||||
crashpad::CrashpadClient crashpad_client;
|
||||
crashpad_client.StartHandler(handler_path, crashes_dir, crashes_dir,
|
||||
submit_url,
|
||||
StringMap(),
|
||||
args,
|
||||
true,
|
||||
false);
|
||||
submit_url, StringMap(), args, true, false);
|
||||
} // @autoreleasepool
|
||||
}
|
||||
|
||||
|
@ -73,12 +67,11 @@ void CrashReporterMac::InitBreakpad(const std::string& product_name,
|
|||
SetCrashKeyValue("process_type", is_browser_ ? "browser" : "renderer");
|
||||
SetCrashKeyValue("ver", version);
|
||||
|
||||
for (const auto& upload_parameter: upload_parameters_) {
|
||||
for (const auto& upload_parameter : upload_parameters_) {
|
||||
SetCrashKeyValue(upload_parameter.first, upload_parameter.second);
|
||||
}
|
||||
if (is_browser_) {
|
||||
database_ =
|
||||
crashpad::CrashReportDatabase::Initialize(crashes_dir);
|
||||
database_ = crashpad::CrashReportDatabase::Initialize(crashes_dir);
|
||||
SetUploadToServer(upload_to_server);
|
||||
}
|
||||
}
|
||||
|
@ -126,9 +119,10 @@ std::map<std::string, std::string> CrashReporterMac::GetParameters() const {
|
|||
if (simple_string_dictionary_) {
|
||||
std::map<std::string, std::string> ret;
|
||||
crashpad::SimpleStringDictionary::Iterator iter(*simple_string_dictionary_);
|
||||
for(;;) {
|
||||
for (;;) {
|
||||
auto* const entry = iter.Next();
|
||||
if (!entry) break;
|
||||
if (!entry)
|
||||
break;
|
||||
ret[entry->key] = entry->value;
|
||||
}
|
||||
return ret;
|
||||
|
@ -148,7 +142,7 @@ CrashReporterMac::GetUploadedReports(const base::FilePath& crashes_dir) {
|
|||
}
|
||||
// Load crashpad database.
|
||||
std::unique_ptr<crashpad::CrashReportDatabase> database =
|
||||
crashpad::CrashReportDatabase::Initialize(crashes_dir);
|
||||
crashpad::CrashReportDatabase::Initialize(crashes_dir);
|
||||
DCHECK(database);
|
||||
|
||||
std::vector<crashpad::CrashReportDatabase::Report> completed_reports;
|
||||
|
@ -168,7 +162,9 @@ CrashReporterMac::GetUploadedReports(const base::FilePath& crashes_dir) {
|
|||
}
|
||||
|
||||
auto sort_by_time = [](const UploadReportResult& a,
|
||||
const UploadReportResult& b) {return a.first >= b.first;};
|
||||
const UploadReportResult& b) {
|
||||
return a.first >= b.first;
|
||||
};
|
||||
std::sort(uploaded_reports.begin(), uploaded_reports.end(), sort_by_time);
|
||||
return uploaded_reports;
|
||||
}
|
||||
|
|
|
@ -75,9 +75,7 @@ std::string MessageForOSStatus(OSStatus status, const char* default_message) {
|
|||
std::string OpenURL(NSURL* ns_url, bool activate) {
|
||||
CFURLRef openingApp = nullptr;
|
||||
OSStatus status = LSGetApplicationForURL(base::mac::NSToCFCast(ns_url),
|
||||
kLSRolesAll,
|
||||
nullptr,
|
||||
&openingApp);
|
||||
kLSRolesAll, nullptr, &openingApp);
|
||||
if (status != noErr)
|
||||
return MessageForOSStatus(status, "Failed to open");
|
||||
|
||||
|
@ -87,12 +85,11 @@ std::string OpenURL(NSURL* ns_url, bool activate) {
|
|||
if (!activate)
|
||||
launchOptions |= NSWorkspaceLaunchWithoutActivation;
|
||||
|
||||
bool opened = [[NSWorkspace sharedWorkspace]
|
||||
openURLs:@[ns_url]
|
||||
withAppBundleIdentifier:nil
|
||||
options:launchOptions
|
||||
additionalEventParamDescriptor:nil
|
||||
launchIdentifiers:nil];
|
||||
bool opened = [[NSWorkspace sharedWorkspace] openURLs:@[ ns_url ]
|
||||
withAppBundleIdentifier:nil
|
||||
options:launchOptions
|
||||
additionalEventParamDescriptor:nil
|
||||
launchIdentifiers:nil];
|
||||
if (!opened)
|
||||
return "Failed to open URL";
|
||||
|
||||
|
@ -100,7 +97,8 @@ std::string OpenURL(NSURL* ns_url, bool activate) {
|
|||
}
|
||||
|
||||
NSString* GetLoginHelperBundleIdentifier() {
|
||||
return [[[NSBundle mainBundle] bundleIdentifier] stringByAppendingString:@".loginhelper"];
|
||||
return [[[NSBundle mainBundle] bundleIdentifier]
|
||||
stringByAppendingString:@".loginhelper"];
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -135,10 +133,10 @@ bool OpenItem(const base::FilePath& full_path) {
|
|||
const NSWorkspaceLaunchOptions launch_options =
|
||||
NSWorkspaceLaunchAsync | NSWorkspaceLaunchWithErrorPresentation;
|
||||
return [[NSWorkspace sharedWorkspace] openURLs:@[ url ]
|
||||
withAppBundleIdentifier:nil
|
||||
options:launch_options
|
||||
additionalEventParamDescriptor:nil
|
||||
launchIdentifiers:NULL];
|
||||
withAppBundleIdentifier:nil
|
||||
options:launch_options
|
||||
additionalEventParamDescriptor:nil
|
||||
launchIdentifiers:NULL];
|
||||
}
|
||||
|
||||
bool OpenExternal(const GURL& url, bool activate) {
|
||||
|
@ -149,7 +147,8 @@ bool OpenExternal(const GURL& url, bool activate) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void OpenExternal(const GURL& url, bool activate,
|
||||
void OpenExternal(const GURL& url,
|
||||
bool activate,
|
||||
const OpenExternalCallback& callback) {
|
||||
NSURL* ns_url = net::NSURLWithGURL(url);
|
||||
if (!ns_url) {
|
||||
|
@ -158,20 +157,21 @@ void OpenExternal(const GURL& url, bool activate,
|
|||
}
|
||||
|
||||
__block OpenExternalCallback c = callback;
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
__block std::string error = OpenURL(ns_url, activate);
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
c.Run(error);
|
||||
});
|
||||
});
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
|
||||
^{
|
||||
__block std::string error = OpenURL(ns_url, activate);
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
c.Run(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
bool MoveItemToTrash(const base::FilePath& full_path) {
|
||||
NSString* path_string = base::SysUTF8ToNSString(full_path.value());
|
||||
BOOL status = [[NSFileManager defaultManager]
|
||||
trashItemAtURL:[NSURL fileURLWithPath:path_string]
|
||||
resultingItemURL:nil
|
||||
error:nil];
|
||||
trashItemAtURL:[NSURL fileURLWithPath:path_string]
|
||||
resultingItemURL:nil
|
||||
error:nil];
|
||||
if (!path_string || !status)
|
||||
LOG(WARNING) << "NSWorkspace failed to move file " << full_path.value()
|
||||
<< " to trash";
|
||||
|
@ -201,7 +201,7 @@ bool GetLoginItemEnabled() {
|
|||
|
||||
void SetLoginItemEnabled(bool enabled) {
|
||||
NSString* identifier = GetLoginHelperBundleIdentifier();
|
||||
SMLoginItemSetEnabled((__bridge CFStringRef) identifier, enabled);
|
||||
SMLoginItemSetEnabled((__bridge CFStringRef)identifier, enabled);
|
||||
}
|
||||
|
||||
} // namespace platform_util
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
#import "brightray/browser/browser_main_parts.h"
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
#import "base/logging.h"
|
||||
#import "base/mac/bundle_locations.h"
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
namespace brightray {
|
||||
|
||||
void BrowserMainParts::OverrideAppLogsPath() {
|
||||
base::FilePath path;
|
||||
NSString* bundleName = [[[NSBundle mainBundle] infoDictionary]
|
||||
objectForKey:@"CFBundleName"];
|
||||
NSString* logsPath = [NSString stringWithFormat:@"Library/Logs/%@",bundleName];
|
||||
NSString* libraryPath = [NSHomeDirectory() stringByAppendingPathComponent:logsPath];
|
||||
NSString* bundleName =
|
||||
[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
|
||||
NSString* logsPath =
|
||||
[NSString stringWithFormat:@"Library/Logs/%@", bundleName];
|
||||
NSString* libraryPath =
|
||||
[NSHomeDirectory() stringByAppendingPathComponent:logsPath];
|
||||
|
||||
PathService::Override(DIR_APP_LOGS, base::FilePath([libraryPath UTF8String]));
|
||||
}
|
||||
|
@ -20,11 +22,13 @@ void BrowserMainParts::OverrideAppLogsPath() {
|
|||
void BrowserMainParts::InitializeMainNib() {
|
||||
auto infoDictionary = base::mac::OuterBundle().infoDictionary;
|
||||
|
||||
auto principalClass = NSClassFromString([infoDictionary objectForKey:@"NSPrincipalClass"]);
|
||||
auto principalClass =
|
||||
NSClassFromString([infoDictionary objectForKey:@"NSPrincipalClass"]);
|
||||
auto application = [principalClass sharedApplication];
|
||||
|
||||
NSString *mainNibName = [infoDictionary objectForKey:@"NSMainNibFile"];
|
||||
auto mainNib = [[NSNib alloc] initWithNibNamed:mainNibName bundle:base::mac::FrameworkBundle()];
|
||||
NSString* mainNibName = [infoDictionary objectForKey:@"NSMainNibFile"];
|
||||
auto mainNib = [[NSNib alloc] initWithNibNamed:mainNibName
|
||||
bundle:base::mac::FrameworkBundle()];
|
||||
[mainNib instantiateWithOwner:application topLevelObjects:nil];
|
||||
[mainNib release];
|
||||
}
|
||||
|
|
|
@ -9,14 +9,16 @@
|
|||
|
||||
namespace brightray {
|
||||
|
||||
InspectableWebContentsView* CreateInspectableContentsView(InspectableWebContentsImpl* inspectable_web_contents) {
|
||||
InspectableWebContentsView* CreateInspectableContentsView(
|
||||
InspectableWebContentsImpl* inspectable_web_contents) {
|
||||
return new InspectableWebContentsViewMac(inspectable_web_contents);
|
||||
}
|
||||
|
||||
InspectableWebContentsViewMac::InspectableWebContentsViewMac(InspectableWebContentsImpl* inspectable_web_contents)
|
||||
InspectableWebContentsViewMac::InspectableWebContentsViewMac(
|
||||
InspectableWebContentsImpl* inspectable_web_contents)
|
||||
: inspectable_web_contents_(inspectable_web_contents),
|
||||
view_([[BRYInspectableWebContentsView alloc] initWithInspectableWebContentsViewMac:this]) {
|
||||
}
|
||||
view_([[BRYInspectableWebContentsView alloc]
|
||||
initWithInspectableWebContentsViewMac:this]) {}
|
||||
|
||||
InspectableWebContentsViewMac::~InspectableWebContentsViewMac() {
|
||||
[view_ removeObservers];
|
||||
|
@ -48,7 +50,7 @@ void InspectableWebContentsViewMac::SetIsDocked(bool docked) {
|
|||
}
|
||||
|
||||
void InspectableWebContentsViewMac::SetContentsResizingStrategy(
|
||||
const DevToolsContentsResizingStrategy& strategy) {
|
||||
const DevToolsContentsResizingStrategy& strategy) {
|
||||
[view_ setContentsResizingStrategy:strategy];
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
|
||||
@implementation BRYInspectableWebContentsView
|
||||
|
||||
- (instancetype)initWithInspectableWebContentsViewMac:(InspectableWebContentsViewMac*)view {
|
||||
- (instancetype)initWithInspectableWebContentsViewMac:
|
||||
(InspectableWebContentsViewMac*)view {
|
||||
self = [super init];
|
||||
if (!self)
|
||||
return nil;
|
||||
|
@ -20,18 +21,19 @@
|
|||
devtools_is_first_responder_ = NO;
|
||||
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver:self
|
||||
selector:@selector(viewDidBecomeFirstResponder:)
|
||||
name:kViewDidBecomeFirstResponder
|
||||
object:nil];
|
||||
addObserver:self
|
||||
selector:@selector(viewDidBecomeFirstResponder:)
|
||||
name:kViewDidBecomeFirstResponder
|
||||
object:nil];
|
||||
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver:self
|
||||
selector:@selector(parentWindowBecameMain:)
|
||||
name:NSWindowDidBecomeMainNotification
|
||||
object:nil];
|
||||
addObserver:self
|
||||
selector:@selector(parentWindowBecameMain:)
|
||||
name:NSWindowDidBecomeMainNotification
|
||||
object:nil];
|
||||
|
||||
auto* contents = inspectableWebContentsView_->inspectable_web_contents()->GetWebContents();
|
||||
auto* contents =
|
||||
inspectableWebContentsView_->inspectable_web_contents()->GetWebContents();
|
||||
auto contentsView = contents->GetNativeView();
|
||||
[contentsView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
||||
[self addSubview:contentsView];
|
||||
|
@ -63,9 +65,11 @@
|
|||
if (visible == devtools_visible_)
|
||||
return;
|
||||
|
||||
auto* inspectable_web_contents = inspectableWebContentsView_->inspectable_web_contents();
|
||||
auto* inspectable_web_contents =
|
||||
inspectableWebContentsView_->inspectable_web_contents();
|
||||
auto* webContents = inspectable_web_contents->GetWebContents();
|
||||
auto* devToolsWebContents = inspectable_web_contents->GetDevToolsWebContents();
|
||||
auto* devToolsWebContents =
|
||||
inspectable_web_contents->GetDevToolsWebContents();
|
||||
auto devToolsView = devToolsWebContents->GetNativeView();
|
||||
|
||||
if (visible && devtools_docked_) {
|
||||
|
@ -120,8 +124,10 @@
|
|||
// Switch to new state.
|
||||
devtools_docked_ = docked;
|
||||
if (!docked) {
|
||||
auto* inspectable_web_contents = inspectableWebContentsView_->inspectable_web_contents();
|
||||
auto* devToolsWebContents = inspectable_web_contents->GetDevToolsWebContents();
|
||||
auto* inspectable_web_contents =
|
||||
inspectableWebContentsView_->inspectable_web_contents();
|
||||
auto* devToolsWebContents =
|
||||
inspectable_web_contents->GetDevToolsWebContents();
|
||||
auto devToolsView = devToolsWebContents->GetNativeView();
|
||||
|
||||
auto styleMask = NSTitledWindowMask | NSClosableWindowMask |
|
||||
|
@ -137,7 +143,8 @@
|
|||
[devtools_window_ setFrameAutosaveName:@"brightray.devtools"];
|
||||
[devtools_window_ setTitle:@"Developer Tools"];
|
||||
[devtools_window_ setReleasedWhenClosed:NO];
|
||||
[devtools_window_ setAutorecalculatesContentBorderThickness:NO forEdge:NSMaxYEdge];
|
||||
[devtools_window_ setAutorecalculatesContentBorderThickness:NO
|
||||
forEdge:NSMaxYEdge];
|
||||
[devtools_window_ setContentBorderThickness:24 forEdge:NSMaxYEdge];
|
||||
|
||||
NSView* contentView = [devtools_window_ contentView];
|
||||
|
@ -149,7 +156,8 @@
|
|||
[self setDevToolsVisible:YES];
|
||||
}
|
||||
|
||||
- (void)setContentsResizingStrategy:(const DevToolsContentsResizingStrategy&)strategy {
|
||||
- (void)setContentsResizingStrategy:
|
||||
(const DevToolsContentsResizingStrategy&)strategy {
|
||||
strategy_.CopyFrom(strategy);
|
||||
[self adjustSubviews];
|
||||
}
|
||||
|
@ -184,7 +192,8 @@
|
|||
}
|
||||
|
||||
- (void)viewDidBecomeFirstResponder:(NSNotification*)notification {
|
||||
auto* inspectable_web_contents = inspectableWebContentsView_->inspectable_web_contents();
|
||||
auto* inspectable_web_contents =
|
||||
inspectableWebContentsView_->inspectable_web_contents();
|
||||
if (!inspectable_web_contents)
|
||||
return;
|
||||
auto* webContents = inspectable_web_contents->GetWebContents();
|
||||
|
@ -196,7 +205,8 @@
|
|||
return;
|
||||
}
|
||||
|
||||
auto* devToolsWebContents = inspectable_web_contents->GetDevToolsWebContents();
|
||||
auto* devToolsWebContents =
|
||||
inspectable_web_contents->GetDevToolsWebContents();
|
||||
if (!devToolsWebContents)
|
||||
return;
|
||||
auto devToolsView = devToolsWebContents->GetNativeView();
|
||||
|
@ -209,7 +219,8 @@
|
|||
|
||||
- (void)parentWindowBecameMain:(NSNotification*)notification {
|
||||
NSWindow* parentWindow = [notification object];
|
||||
if ([self window] == parentWindow && devtools_docked_ && devtools_is_first_responder_)
|
||||
if ([self window] == parentWindow && devtools_docked_ &&
|
||||
devtools_is_first_responder_)
|
||||
[self notifyDevToolsFocused];
|
||||
}
|
||||
|
||||
|
@ -221,7 +232,8 @@
|
|||
|
||||
- (void)windowDidBecomeMain:(NSNotification*)notification {
|
||||
content::WebContents* web_contents =
|
||||
inspectableWebContentsView_->inspectable_web_contents()->GetDevToolsWebContents();
|
||||
inspectableWebContentsView_->inspectable_web_contents()
|
||||
->GetDevToolsWebContents();
|
||||
if (!web_contents)
|
||||
return;
|
||||
|
||||
|
@ -236,7 +248,8 @@
|
|||
|
||||
- (void)windowDidResignMain:(NSNotification*)notification {
|
||||
content::WebContents* web_contents =
|
||||
inspectableWebContentsView_->inspectable_web_contents()->GetDevToolsWebContents();
|
||||
inspectableWebContentsView_->inspectable_web_contents()
|
||||
->GetDevToolsWebContents();
|
||||
if (!web_contents)
|
||||
return;
|
||||
|
||||
|
|
|
@ -17,8 +17,7 @@ int g_identifier_ = 1;
|
|||
|
||||
CocoaNotification::CocoaNotification(NotificationDelegate* delegate,
|
||||
NotificationPresenter* presenter)
|
||||
: Notification(delegate, presenter) {
|
||||
}
|
||||
: Notification(delegate, presenter) {}
|
||||
|
||||
CocoaNotification::~CocoaNotification() {
|
||||
if (notification_)
|
||||
|
@ -29,7 +28,8 @@ CocoaNotification::~CocoaNotification() {
|
|||
void CocoaNotification::Show(const NotificationOptions& options) {
|
||||
notification_.reset([[NSUserNotification alloc] init]);
|
||||
|
||||
NSString* identifier = [NSString stringWithFormat:@"ElectronNotification%d", g_identifier_++];
|
||||
NSString* identifier =
|
||||
[NSString stringWithFormat:@"ElectronNotification%d", g_identifier_++];
|
||||
|
||||
[notification_ setTitle:base::SysUTF16ToNSString(options.title)];
|
||||
[notification_ setSubtitle:base::SysUTF16ToNSString(options.subtitle)];
|
||||
|
@ -58,23 +58,28 @@ void CocoaNotification::Show(const NotificationOptions& options) {
|
|||
|
||||
int i = 0;
|
||||
action_index_ = UINT_MAX;
|
||||
NSMutableArray* additionalActions = [[[NSMutableArray alloc] init] autorelease];
|
||||
NSMutableArray* additionalActions =
|
||||
[[[NSMutableArray alloc] init] autorelease];
|
||||
for (const auto& action : options.actions) {
|
||||
if (action.type == base::ASCIIToUTF16("button")) {
|
||||
if (action_index_ == UINT_MAX) {
|
||||
// First button observed is the displayed action
|
||||
[notification_ setHasActionButton:true];
|
||||
[notification_ setActionButtonTitle:base::SysUTF16ToNSString(action.text)];
|
||||
[notification_
|
||||
setActionButtonTitle:base::SysUTF16ToNSString(action.text)];
|
||||
action_index_ = i;
|
||||
} else {
|
||||
// All of the rest are appended to the list of additional actions
|
||||
NSString* actionIdentifier = [NSString stringWithFormat:@"%@Action%d", identifier, i];
|
||||
NSString* actionIdentifier =
|
||||
[NSString stringWithFormat:@"%@Action%d", identifier, i];
|
||||
if (@available(macOS 10.10, *)) {
|
||||
NSUserNotificationAction* notificationAction =
|
||||
[NSUserNotificationAction actionWithIdentifier:actionIdentifier
|
||||
title:base::SysUTF16ToNSString(action.text)];
|
||||
[NSUserNotificationAction
|
||||
actionWithIdentifier:actionIdentifier
|
||||
title:base::SysUTF16ToNSString(action.text)];
|
||||
[additionalActions addObject:notificationAction];
|
||||
additional_action_indices_.insert(std::make_pair(base::SysNSStringToUTF8(actionIdentifier), i));
|
||||
additional_action_indices_.insert(
|
||||
std::make_pair(base::SysNSStringToUTF8(actionIdentifier), i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -88,12 +93,14 @@ void CocoaNotification::Show(const NotificationOptions& options) {
|
|||
}
|
||||
|
||||
if (options.has_reply) {
|
||||
[notification_ setResponsePlaceholder:base::SysUTF16ToNSString(options.reply_placeholder)];
|
||||
[notification_ setResponsePlaceholder:base::SysUTF16ToNSString(
|
||||
options.reply_placeholder)];
|
||||
[notification_ setHasReplyButton:true];
|
||||
}
|
||||
|
||||
if (!options.close_button_text.empty()) {
|
||||
[notification_ setOtherButtonTitle:base::SysUTF16ToNSString(options.close_button_text)];
|
||||
[notification_ setOtherButtonTitle:base::SysUTF16ToNSString(
|
||||
options.close_button_text)];
|
||||
}
|
||||
|
||||
[NSUserNotificationCenter.defaultUserNotificationCenter
|
||||
|
@ -131,7 +138,8 @@ void CocoaNotification::NotificationActivated() {
|
|||
this->LogAction("button clicked");
|
||||
}
|
||||
|
||||
void CocoaNotification::NotificationActivated(NSUserNotificationAction* action) {
|
||||
void CocoaNotification::NotificationActivated(
|
||||
NSUserNotificationAction* action) {
|
||||
if (delegate()) {
|
||||
unsigned index = action_index_;
|
||||
std::string identifier = base::SysNSStringToUTF8(action.identifier);
|
||||
|
@ -151,7 +159,8 @@ void CocoaNotification::NotificationActivated(NSUserNotificationAction* action)
|
|||
void CocoaNotification::LogAction(const char* action) {
|
||||
if (getenv("ELECTRON_DEBUG_NOTIFICATIONS")) {
|
||||
NSString* identifier = [notification_ valueForKey:@"identifier"];
|
||||
LOG(INFO) << "Notification " << action << " (" << [identifier UTF8String] << ")";
|
||||
LOG(INFO) << "Notification " << action << " (" << [identifier UTF8String]
|
||||
<< ")";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
return NO;
|
||||
else
|
||||
return [super performKeyEquivalent:event];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)redispatchKeyEvent:(NSEvent*)event {
|
||||
NSEventType eventType = [event type];
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
|
||||
@implementation NotificationCenterDelegate
|
||||
|
||||
- (instancetype)initWithPresenter:(brightray::NotificationPresenterMac*)presenter {
|
||||
- (instancetype)initWithPresenter:
|
||||
(brightray::NotificationPresenterMac*)presenter {
|
||||
self = [super init];
|
||||
if (!self)
|
||||
return nil;
|
||||
|
@ -26,25 +27,32 @@
|
|||
}
|
||||
|
||||
- (void)userNotificationCenter:(NSUserNotificationCenter*)center
|
||||
didActivateNotification:(NSUserNotification *)notif {
|
||||
didActivateNotification:(NSUserNotification*)notif {
|
||||
auto* notification = presenter_->GetNotification(notif);
|
||||
|
||||
if (getenv("ELECTRON_DEBUG_NOTIFICATIONS")) {
|
||||
LOG(INFO) << "Notification activated (" << [notif.identifier UTF8String] << ")";
|
||||
LOG(INFO) << "Notification activated (" << [notif.identifier UTF8String]
|
||||
<< ")";
|
||||
}
|
||||
|
||||
if (notification) {
|
||||
// Ref: https://developer.apple.com/documentation/foundation/nsusernotificationactivationtype?language=objc
|
||||
if (notif.activationType == NSUserNotificationActivationTypeContentsClicked) {
|
||||
// Ref:
|
||||
// https://developer.apple.com/documentation/foundation/nsusernotificationactivationtype?language=objc
|
||||
if (notif.activationType ==
|
||||
NSUserNotificationActivationTypeContentsClicked) {
|
||||
notification->NotificationClicked();
|
||||
} else if (notif.activationType == NSUserNotificationActivationTypeActionButtonClicked) {
|
||||
} else if (notif.activationType ==
|
||||
NSUserNotificationActivationTypeActionButtonClicked) {
|
||||
notification->NotificationActivated();
|
||||
} else if (notif.activationType == NSUserNotificationActivationTypeReplied) {
|
||||
} else if (notif.activationType ==
|
||||
NSUserNotificationActivationTypeReplied) {
|
||||
notification->NotificationReplied([notif.response.string UTF8String]);
|
||||
} else {
|
||||
if (@available(macOS 10.10, *)) {
|
||||
if (notif.activationType == NSUserNotificationActivationTypeAdditionalActionClicked) {
|
||||
notification->NotificationActivated([notif additionalActivationAction]);
|
||||
if (notif.activationType ==
|
||||
NSUserNotificationActivationTypeAdditionalActionClicked) {
|
||||
notification->NotificationActivated(
|
||||
[notif additionalActivationAction]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,12 +19,13 @@ CocoaNotification* NotificationPresenterMac::GetNotification(
|
|||
for (Notification* notification : notifications()) {
|
||||
auto* native_notification = static_cast<CocoaNotification*>(notification);
|
||||
if ([native_notification->notification().identifier
|
||||
isEqual:ns_notification.identifier])
|
||||
isEqual:ns_notification.identifier])
|
||||
return native_notification;
|
||||
}
|
||||
|
||||
if (getenv("ELECTRON_DEBUG_NOTIFICATIONS")) {
|
||||
LOG(INFO) << "Could not find notification for " << [ns_notification.identifier UTF8String];
|
||||
LOG(INFO) << "Could not find notification for "
|
||||
<< [ns_notification.identifier UTF8String];
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
|
|
@ -9,7 +9,8 @@ namespace brightray {
|
|||
namespace {
|
||||
|
||||
std::string ApplicationInfoDictionaryValue(NSString* key) {
|
||||
return base::SysNSStringToUTF8([MainApplicationBundle().infoDictionary objectForKey:key]);
|
||||
return base::SysNSStringToUTF8(
|
||||
[MainApplicationBundle().infoDictionary objectForKey:key]);
|
||||
}
|
||||
|
||||
std::string ApplicationInfoDictionaryValue(CFStringRef key) {
|
||||
|
|
|
@ -17,7 +17,8 @@ namespace {
|
|||
|
||||
bool HasMainProcessKey() {
|
||||
NSDictionary* info_dictionary = [base::mac::MainBundle() infoDictionary];
|
||||
return [[info_dictionary objectForKey:@"ElectronMainProcess"] boolValue] != NO;
|
||||
return
|
||||
[[info_dictionary objectForKey:@"ElectronMainProcess"] boolValue] != NO;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -48,7 +49,8 @@ base::FilePath MainApplicationBundlePath() {
|
|||
}
|
||||
|
||||
NSBundle* MainApplicationBundle() {
|
||||
return [NSBundle bundleWithPath:base::mac::FilePathToNSString(MainApplicationBundlePath())];
|
||||
return [NSBundle bundleWithPath:base::mac::FilePathToNSString(
|
||||
MainApplicationBundlePath())];
|
||||
}
|
||||
|
||||
} // namespace brightray
|
||||
|
|
|
@ -43,16 +43,18 @@ void LoadCommonResources() {
|
|||
}
|
||||
|
||||
void MainDelegate::OverrideFrameworkBundlePath() {
|
||||
base::FilePath helper_path = GetFrameworksPath().Append(GetApplicationName() + " Framework.framework");
|
||||
base::FilePath helper_path =
|
||||
GetFrameworksPath().Append(GetApplicationName() + " Framework.framework");
|
||||
|
||||
base::mac::SetOverrideFrameworkBundlePath(helper_path);
|
||||
}
|
||||
|
||||
void MainDelegate::OverrideChildProcessPath() {
|
||||
base::FilePath helper_path = GetFrameworksPath().Append(GetApplicationName() + " Helper.app")
|
||||
.Append("Contents")
|
||||
.Append("MacOS")
|
||||
.Append(GetApplicationName() + " Helper");
|
||||
base::FilePath helper_path = GetFrameworksPath()
|
||||
.Append(GetApplicationName() + " Helper.app")
|
||||
.Append("Contents")
|
||||
.Append("MacOS")
|
||||
.Append(GetApplicationName() + " Helper");
|
||||
|
||||
PathService::Override(content::CHILD_PROCESS_EXE, helper_path);
|
||||
}
|
||||
|
|
|
@ -62,8 +62,7 @@ namespace extensions {
|
|||
// static
|
||||
GlobalShortcutListener* GlobalShortcutListener::GetInstance() {
|
||||
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
||||
static GlobalShortcutListenerMac* instance =
|
||||
new GlobalShortcutListenerMac();
|
||||
static GlobalShortcutListenerMac* instance = new GlobalShortcutListenerMac();
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
@ -126,8 +125,8 @@ void GlobalShortcutListenerMac::OnHotKeyEvent(EventHotKeyID hot_key_id) {
|
|||
bool GlobalShortcutListenerMac::OnMediaOrVolumeKeyEvent(
|
||||
int media_or_volume_key_code) {
|
||||
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
||||
ui::KeyboardCode key_code = MediaOrVolumeKeyCodeToKeyboardCode(
|
||||
media_or_volume_key_code);
|
||||
ui::KeyboardCode key_code =
|
||||
MediaOrVolumeKeyCodeToKeyboardCode(media_or_volume_key_code);
|
||||
// Create an accelerator corresponding to the keyCode.
|
||||
ui::Accelerator accelerator(key_code, 0);
|
||||
// Look for a match with a bound hot_key.
|
||||
|
@ -181,8 +180,8 @@ void GlobalShortcutListenerMac::UnregisterAcceleratorImpl(
|
|||
accelerator_ids_.erase(accelerator);
|
||||
|
||||
if (IsMediaOrVolumeKey(accelerator)) {
|
||||
// If we unregistered a media/volume key, and now no media/volume keys are registered,
|
||||
// stop the media/volume key tap.
|
||||
// If we unregistered a media/volume key, and now no media/volume keys are
|
||||
// registered, stop the media/volume key tap.
|
||||
if (!IsAnyMediaOrVolumeKeyRegistered())
|
||||
StopWatchingMediaOrVolumeKeys();
|
||||
} else {
|
||||
|
@ -195,7 +194,8 @@ void GlobalShortcutListenerMac::UnregisterAcceleratorImpl(
|
|||
}
|
||||
|
||||
bool GlobalShortcutListenerMac::RegisterHotKey(
|
||||
const ui::Accelerator& accelerator, KeyId hot_key_id) {
|
||||
const ui::Accelerator& accelerator,
|
||||
KeyId hot_key_id) {
|
||||
EventHotKeyID event_hot_key_id;
|
||||
|
||||
// Signature uniquely identifies the application that owns this hot_key.
|
||||
|
@ -209,13 +209,14 @@ bool GlobalShortcutListenerMac::RegisterHotKey(
|
|||
modifiers |= (accelerator.IsAltDown() ? optionKey : 0);
|
||||
modifiers |= (accelerator.IsCmdDown() ? cmdKey : 0);
|
||||
|
||||
int key_code = ui::MacKeyCodeForWindowsKeyCode(accelerator.key_code(), 0,
|
||||
NULL, NULL);
|
||||
int key_code =
|
||||
ui::MacKeyCodeForWindowsKeyCode(accelerator.key_code(), 0, NULL, NULL);
|
||||
|
||||
// Register the event hot key.
|
||||
EventHotKeyRef hot_key_ref;
|
||||
OSStatus status = RegisterEventHotKey(key_code, modifiers, event_hot_key_id,
|
||||
GetApplicationEventTarget(), 0, &hot_key_ref);
|
||||
OSStatus status =
|
||||
RegisterEventHotKey(key_code, modifiers, event_hot_key_id,
|
||||
GetApplicationEventTarget(), 0, &hot_key_ref);
|
||||
if (status != noErr)
|
||||
return false;
|
||||
|
||||
|
@ -243,31 +244,28 @@ void GlobalShortcutListenerMac::StartWatchingMediaOrVolumeKeys() {
|
|||
DCHECK(event_tap_source_ == NULL);
|
||||
|
||||
// Add an event tap to intercept the system defined media/volume key events.
|
||||
event_tap_ = CGEventTapCreate(kCGSessionEventTap,
|
||||
kCGHeadInsertEventTap,
|
||||
kCGEventTapOptionDefault,
|
||||
CGEventMaskBit(NX_SYSDEFINED),
|
||||
EventTapCallback,
|
||||
this);
|
||||
event_tap_ = CGEventTapCreate(
|
||||
kCGSessionEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault,
|
||||
CGEventMaskBit(NX_SYSDEFINED), EventTapCallback, this);
|
||||
if (event_tap_ == NULL) {
|
||||
LOG(ERROR) << "Error: failed to create event tap.";
|
||||
return;
|
||||
}
|
||||
|
||||
event_tap_source_ = CFMachPortCreateRunLoopSource(kCFAllocatorSystemDefault,
|
||||
event_tap_, 0);
|
||||
event_tap_source_ =
|
||||
CFMachPortCreateRunLoopSource(kCFAllocatorSystemDefault, event_tap_, 0);
|
||||
if (event_tap_source_ == NULL) {
|
||||
LOG(ERROR) << "Error: failed to create new run loop source.";
|
||||
return;
|
||||
}
|
||||
|
||||
CFRunLoopAddSource(CFRunLoopGetCurrent(), event_tap_source_,
|
||||
kCFRunLoopCommonModes);
|
||||
kCFRunLoopCommonModes);
|
||||
}
|
||||
|
||||
void GlobalShortcutListenerMac::StopWatchingMediaOrVolumeKeys() {
|
||||
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), event_tap_source_,
|
||||
kCFRunLoopCommonModes);
|
||||
kCFRunLoopCommonModes);
|
||||
// Ensure both event tap and source are initialized.
|
||||
DCHECK(event_tap_ != NULL);
|
||||
DCHECK(event_tap_source_ != NULL);
|
||||
|
@ -288,8 +286,8 @@ void GlobalShortcutListenerMac::StartWatchingHotKeys() {
|
|||
EventTypeSpec event_type;
|
||||
event_type.eventClass = kEventClassKeyboard;
|
||||
event_type.eventKind = kEventHotKeyPressed;
|
||||
InstallApplicationEventHandler(
|
||||
hot_key_function, 1, &event_type, this, &event_handler_);
|
||||
InstallApplicationEventHandler(hot_key_function, 1, &event_type, this,
|
||||
&event_handler_);
|
||||
}
|
||||
|
||||
void GlobalShortcutListenerMac::StopWatchingHotKeys() {
|
||||
|
@ -323,8 +321,10 @@ bool GlobalShortcutListenerMac::IsAnyHotKeyRegistered() {
|
|||
// Returning event causes the event to propagate to other applications.
|
||||
// Returning NULL prevents the event from propagating.
|
||||
// static
|
||||
CGEventRef GlobalShortcutListenerMac::EventTapCallback(
|
||||
CGEventTapProxy proxy, CGEventType type, CGEventRef event, void* refcon) {
|
||||
CGEventRef GlobalShortcutListenerMac::EventTapCallback(CGEventTapProxy proxy,
|
||||
CGEventType type,
|
||||
CGEventRef event,
|
||||
void* refcon) {
|
||||
GlobalShortcutListenerMac* shortcut_listener =
|
||||
static_cast<GlobalShortcutListenerMac*>(refcon);
|
||||
|
||||
|
@ -341,8 +341,7 @@ CGEventRef GlobalShortcutListenerMac::EventTapCallback(
|
|||
}
|
||||
|
||||
// Ignore events that are not system defined media/volume keys.
|
||||
if (type != NX_SYSDEFINED ||
|
||||
[ns_event type] != NSSystemDefined ||
|
||||
if (type != NX_SYSDEFINED || [ns_event type] != NSSystemDefined ||
|
||||
[ns_event subtype] != kSystemDefinedEventMediaAndVolumeKeysSubtype) {
|
||||
return event;
|
||||
}
|
||||
|
@ -354,10 +353,8 @@ CGEventRef GlobalShortcutListenerMac::EventTapCallback(
|
|||
int key_code = (data1 & 0xFFFF0000) >> 16;
|
||||
if (key_code != NX_KEYTYPE_PLAY && key_code != NX_KEYTYPE_NEXT &&
|
||||
key_code != NX_KEYTYPE_PREVIOUS && key_code != NX_KEYTYPE_FAST &&
|
||||
key_code != NX_KEYTYPE_REWIND &&
|
||||
key_code != NX_KEYTYPE_SOUND_UP &&
|
||||
key_code != NX_KEYTYPE_SOUND_DOWN &&
|
||||
key_code != NX_KEYTYPE_MUTE) {
|
||||
key_code != NX_KEYTYPE_REWIND && key_code != NX_KEYTYPE_SOUND_UP &&
|
||||
key_code != NX_KEYTYPE_SOUND_DOWN && key_code != NX_KEYTYPE_MUTE) {
|
||||
return event;
|
||||
}
|
||||
|
||||
|
@ -381,11 +378,14 @@ CGEventRef GlobalShortcutListenerMac::EventTapCallback(
|
|||
|
||||
// static
|
||||
OSStatus GlobalShortcutListenerMac::HotKeyHandler(
|
||||
EventHandlerCallRef next_handler, EventRef event, void* user_data) {
|
||||
EventHandlerCallRef next_handler,
|
||||
EventRef event,
|
||||
void* user_data) {
|
||||
// Extract the hotkey from the event.
|
||||
EventHotKeyID hot_key_id;
|
||||
OSStatus result = GetEventParameter(event, kEventParamDirectObject,
|
||||
typeEventHotKeyID, NULL, sizeof(hot_key_id), NULL, &hot_key_id);
|
||||
OSStatus result =
|
||||
GetEventParameter(event, kEventParamDirectObject, typeEventHotKeyID, NULL,
|
||||
sizeof(hot_key_id), NULL, &hot_key_id);
|
||||
if (result != noErr)
|
||||
return result;
|
||||
|
||||
|
|
|
@ -30,8 +30,7 @@ int64_t MonitorFinder::GetMonitor() {
|
|||
}
|
||||
|
||||
content::BrowserThread::PostTask(
|
||||
content::BrowserThread::UI,
|
||||
FROM_HERE,
|
||||
content::BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(&MonitorFinder::FetchMonitorFromWidget, this));
|
||||
return display_id_;
|
||||
}
|
||||
|
|
|
@ -49,16 +49,13 @@ class TtsPlatformImplMac;
|
|||
|
||||
class TtsPlatformImplMac : public TtsPlatformImpl {
|
||||
public:
|
||||
bool PlatformImplAvailable() override {
|
||||
return true;
|
||||
}
|
||||
bool PlatformImplAvailable() override { return true; }
|
||||
|
||||
bool Speak(
|
||||
int utterance_id,
|
||||
const std::string& utterance,
|
||||
const std::string& lang,
|
||||
const VoiceData& voice,
|
||||
const UtteranceContinuousParameters& params) override;
|
||||
bool Speak(int utterance_id,
|
||||
const std::string& utterance,
|
||||
const std::string& lang,
|
||||
const VoiceData& voice,
|
||||
const UtteranceContinuousParameters& params) override;
|
||||
|
||||
bool StopSpeaking() override;
|
||||
|
||||
|
@ -101,12 +98,11 @@ TtsPlatformImpl* TtsPlatformImpl::GetInstance() {
|
|||
return TtsPlatformImplMac::GetInstance();
|
||||
}
|
||||
|
||||
bool TtsPlatformImplMac::Speak(
|
||||
int utterance_id,
|
||||
const std::string& utterance,
|
||||
const std::string& lang,
|
||||
const VoiceData& voice,
|
||||
const UtteranceContinuousParameters& params) {
|
||||
bool TtsPlatformImplMac::Speak(int utterance_id,
|
||||
const std::string& utterance,
|
||||
const std::string& lang,
|
||||
const VoiceData& voice,
|
||||
const UtteranceContinuousParameters& params) {
|
||||
// TODO: convert SSML to SAPI xml. http://crbug.com/88072
|
||||
utterance_ = utterance;
|
||||
paused_ = false;
|
||||
|
@ -119,9 +115,8 @@ bool TtsPlatformImplMac::Speak(
|
|||
// apply to the current utterance or a previous utterance. In
|
||||
// experimentation, the overhead of constructing and destructing a
|
||||
// NSSpeechSynthesizer is minimal.
|
||||
speech_synthesizer_.reset(
|
||||
[[SingleUseSpeechSynthesizer alloc]
|
||||
initWithUtterance:utterance_nsstring]);
|
||||
speech_synthesizer_.reset([[SingleUseSpeechSynthesizer alloc]
|
||||
initWithUtterance:utterance_nsstring]);
|
||||
[speech_synthesizer_ setDelegate:delegate_];
|
||||
|
||||
if (!voice.native_voice_identifier.empty()) {
|
||||
|
@ -136,9 +131,9 @@ bool TtsPlatformImplMac::Speak(
|
|||
|
||||
if (params.rate >= 0.0) {
|
||||
// The TTS api defines rate via words per minute. Let 200 be the default.
|
||||
[speech_synthesizer_
|
||||
setObject:[NSNumber numberWithInt:params.rate * 200]
|
||||
forProperty:NSSpeechRateProperty error:nil];
|
||||
[speech_synthesizer_ setObject:[NSNumber numberWithInt:params.rate * 200]
|
||||
forProperty:NSSpeechRateProperty
|
||||
error:nil];
|
||||
}
|
||||
|
||||
if (params.pitch >= 0.0) {
|
||||
|
@ -150,15 +145,15 @@ bool TtsPlatformImplMac::Speak(
|
|||
error:&errorCode];
|
||||
int defaultPitch = defaultPitchObj ? [defaultPitchObj intValue] : 48;
|
||||
int newPitch = static_cast<int>(defaultPitch * (0.5 * params.pitch + 0.5));
|
||||
[speech_synthesizer_
|
||||
setObject:[NSNumber numberWithInt:newPitch]
|
||||
forProperty:NSSpeechPitchBaseProperty error:nil];
|
||||
[speech_synthesizer_ setObject:[NSNumber numberWithInt:newPitch]
|
||||
forProperty:NSSpeechPitchBaseProperty
|
||||
error:nil];
|
||||
}
|
||||
|
||||
if (params.volume >= 0.0) {
|
||||
[speech_synthesizer_
|
||||
setObject: [NSNumber numberWithFloat:params.volume]
|
||||
forProperty:NSSpeechVolumeProperty error:nil];
|
||||
[speech_synthesizer_ setObject:[NSNumber numberWithFloat:params.volume]
|
||||
forProperty:NSSpeechVolumeProperty
|
||||
error:nil];
|
||||
}
|
||||
|
||||
bool success = [speech_synthesizer_ startSpeakingRetainedUtterance];
|
||||
|
@ -182,8 +177,8 @@ void TtsPlatformImplMac::Pause() {
|
|||
if (speech_synthesizer_.get() && utterance_id_ && !paused_) {
|
||||
[speech_synthesizer_ pauseSpeakingAtBoundary:NSSpeechImmediateBoundary];
|
||||
paused_ = true;
|
||||
TtsController::GetInstance()->OnTtsEvent(
|
||||
utterance_id_, TTS_EVENT_PAUSE, last_char_index_, "");
|
||||
TtsController::GetInstance()->OnTtsEvent(utterance_id_, TTS_EVENT_PAUSE,
|
||||
last_char_index_, "");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,8 +186,8 @@ void TtsPlatformImplMac::Resume() {
|
|||
if (speech_synthesizer_.get() && utterance_id_ && paused_) {
|
||||
[speech_synthesizer_ continueSpeaking];
|
||||
paused_ = false;
|
||||
TtsController::GetInstance()->OnTtsEvent(
|
||||
utterance_id_, TTS_EVENT_RESUME, last_char_index_, "");
|
||||
TtsController::GetInstance()->OnTtsEvent(utterance_id_, TTS_EVENT_RESUME,
|
||||
last_char_index_, "");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -260,11 +255,10 @@ void TtsPlatformImplMac::GetVoices(std::vector<VoiceData>* outVoices) {
|
|||
}
|
||||
}
|
||||
|
||||
void TtsPlatformImplMac::OnSpeechEvent(
|
||||
NSSpeechSynthesizer* sender,
|
||||
TtsEventType event_type,
|
||||
int char_index,
|
||||
const std::string& error_message) {
|
||||
void TtsPlatformImplMac::OnSpeechEvent(NSSpeechSynthesizer* sender,
|
||||
TtsEventType event_type,
|
||||
int char_index,
|
||||
const std::string& error_message) {
|
||||
// Don't send events from an utterance that's already completed.
|
||||
// This depends on the fact that we construct a new NSSpeechSynthesizer
|
||||
// each time we call Speak.
|
||||
|
@ -274,8 +268,7 @@ void TtsPlatformImplMac::OnSpeechEvent(
|
|||
if (event_type == TTS_EVENT_END)
|
||||
char_index = utterance_.size();
|
||||
TtsController* controller = TtsController::GetInstance();
|
||||
controller->OnTtsEvent(
|
||||
utterance_id_, event_type, char_index, error_message);
|
||||
controller->OnTtsEvent(utterance_id_, event_type, char_index, error_message);
|
||||
last_char_index_ = char_index;
|
||||
}
|
||||
|
||||
|
@ -286,8 +279,7 @@ TtsPlatformImplMac::TtsPlatformImplMac() {
|
|||
delegate_.reset([[ChromeTtsDelegate alloc] initWithPlatformImplMac:this]);
|
||||
}
|
||||
|
||||
TtsPlatformImplMac::~TtsPlatformImplMac() {
|
||||
}
|
||||
TtsPlatformImplMac::~TtsPlatformImplMac() {}
|
||||
|
||||
// static
|
||||
TtsPlatformImplMac* TtsPlatformImplMac::GetInstance() {
|
||||
|
@ -311,17 +303,17 @@ TtsPlatformImplMac* TtsPlatformImplMac::GetInstance() {
|
|||
- (void)speechSynthesizer:(NSSpeechSynthesizer*)sender
|
||||
willSpeakWord:(NSRange)character_range
|
||||
ofString:(NSString*)string {
|
||||
ttsImplMac_->OnSpeechEvent(sender, TTS_EVENT_WORD,
|
||||
character_range.location, "");
|
||||
ttsImplMac_->OnSpeechEvent(sender, TTS_EVENT_WORD, character_range.location,
|
||||
"");
|
||||
}
|
||||
|
||||
- (void)speechSynthesizer:(NSSpeechSynthesizer*)sender
|
||||
didEncounterErrorAtIndex:(NSUInteger)character_index
|
||||
ofString:(NSString*)string
|
||||
message:(NSString*)message {
|
||||
didEncounterErrorAtIndex:(NSUInteger)character_index
|
||||
ofString:(NSString*)string
|
||||
message:(NSString*)message {
|
||||
std::string message_utf8 = base::SysNSStringToUTF8(message);
|
||||
ttsImplMac_->OnSpeechEvent(sender, TTS_EVENT_ERROR, character_index,
|
||||
message_utf8);
|
||||
message_utf8);
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -15,7 +15,7 @@ class ColorChooserMac;
|
|||
|
||||
// A Listener class to act as a event target for NSColorPanel and send
|
||||
// the results to the C++ class, ColorChooserMac.
|
||||
@interface ColorPanelCocoa : NSObject<NSWindowDelegate> {
|
||||
@interface ColorPanelCocoa : NSObject <NSWindowDelegate> {
|
||||
@private
|
||||
// We don't call DidChooseColor if the change wasn't caused by the user
|
||||
// interacting with the panel.
|
||||
|
@ -65,8 +65,7 @@ ColorChooserMac* ColorChooserMac::Open(content::WebContents* web_contents,
|
|||
if (current_color_chooser_)
|
||||
current_color_chooser_->End();
|
||||
DCHECK(!current_color_chooser_);
|
||||
current_color_chooser_ =
|
||||
new ColorChooserMac(web_contents, initial_color);
|
||||
current_color_chooser_ = new ColorChooserMac(web_contents, initial_color);
|
||||
return current_color_chooser_;
|
||||
}
|
||||
|
||||
|
@ -97,7 +96,7 @@ void ColorChooserMac::End() {
|
|||
DCHECK(current_color_chooser_ == this);
|
||||
current_color_chooser_ = NULL;
|
||||
if (web_contents_)
|
||||
web_contents_->DidEndColorChooser();
|
||||
web_contents_->DidEndColorChooser();
|
||||
}
|
||||
|
||||
void ColorChooserMac::SetSelectedColor(SkColor color) {
|
||||
|
|
|
@ -235,8 +235,8 @@ NSBundle* OuterAppBundle() {
|
|||
|
||||
bool GetUserDataDirectoryForBrowserBundle(NSBundle* bundle,
|
||||
base::FilePath* result) {
|
||||
std::unique_ptr<char, base::FreeDeleter>
|
||||
product_dir_name(ProductDirNameForBundle(bundle));
|
||||
std::unique_ptr<char, base::FreeDeleter> product_dir_name(
|
||||
ProductDirNameForBundle(bundle));
|
||||
return GetDefaultUserDataDirectoryForProduct(product_dir_name.get(), result);
|
||||
}
|
||||
|
||||
|
|
|
@ -56,8 +56,8 @@ bool PrintWebViewHelper::RenderPreviewPage(
|
|||
std::unique_ptr<PdfMetafileSkia> draft_metafile;
|
||||
PdfMetafileSkia* initial_render_metafile = print_preview_context_.metafile();
|
||||
|
||||
bool render_to_draft = print_preview_context_.IsModifiable() &&
|
||||
is_print_ready_metafile_sent_;
|
||||
bool render_to_draft =
|
||||
print_preview_context_.IsModifiable() && is_print_ready_metafile_sent_;
|
||||
|
||||
if (render_to_draft) {
|
||||
draft_metafile.reset(new PdfMetafileSkia(SkiaDocumentType::PDF));
|
||||
|
@ -69,8 +69,8 @@ bool PrintWebViewHelper::RenderPreviewPage(
|
|||
gfx::Size page_size;
|
||||
RenderPage(printParams, page_number, print_preview_context_.prepared_frame(),
|
||||
true, initial_render_metafile, &page_size, NULL);
|
||||
print_preview_context_.RenderedPreviewPage(
|
||||
base::TimeTicks::Now() - begin_time);
|
||||
print_preview_context_.RenderedPreviewPage(base::TimeTicks::Now() -
|
||||
begin_time);
|
||||
|
||||
if (draft_metafile.get()) {
|
||||
draft_metafile->FinishDocument();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue