Merge pull request #12 from electron/master

update as upstream
This commit is contained in:
Heilig Benedek 2016-07-06 14:12:24 +02:00 committed by GitHub
commit 74120493fd
147 changed files with 2605 additions and 1221 deletions

View file

@ -463,10 +463,11 @@ void App::DisableHardwareAcceleration(mate::Arguments* args) {
void App::ImportCertificate(
const base::DictionaryValue& options,
const net::CompletionCallback& callback) {
auto browser_context = AtomBrowserMainParts::Get()->browser_context();
auto browser_context = brightray::BrowserContext::From("", false);
if (!certificate_manager_model_) {
std::unique_ptr<base::DictionaryValue> copy = options.CreateDeepCopy();
CertificateManagerModel::Create(browser_context,
CertificateManagerModel::Create(
browser_context.get(),
base::Bind(&App::OnCertificateManagerModelCreated,
base::Unretained(this),
base::Passed(&copy),
@ -519,6 +520,8 @@ void App::BuildPrototype(
base::Bind(&Browser::SetAsDefaultProtocolClient, browser))
.SetMethod("removeAsDefaultProtocolClient",
base::Bind(&Browser::RemoveAsDefaultProtocolClient, browser))
.SetMethod("setBadgeCount", base::Bind(&Browser::SetBadgeCount, browser))
.SetMethod("getBadgeCount", base::Bind(&Browser::GetBadgeCount, browser))
#if defined(OS_MACOSX)
.SetMethod("hide", base::Bind(&Browser::Hide, browser))
.SetMethod("show", base::Bind(&Browser::Show, browser))
@ -528,8 +531,11 @@ void App::BuildPrototype(
base::Bind(&Browser::GetCurrentActivityType, browser))
#endif
#if defined(OS_WIN)
.SetMethod("setUserTasks",
base::Bind(&Browser::SetUserTasks, browser))
.SetMethod("setUserTasks", base::Bind(&Browser::SetUserTasks, browser))
#endif
#if defined(OS_LINUX)
.SetMethod("isUnityRunning",
base::Bind(&Browser::IsUnityRunning, browser))
#endif
.SetMethod("setPath", &App::SetPath)
.SetMethod("getPath", &App::GetPath)

View file

@ -30,7 +30,7 @@ struct Converter<atom::api::Cookies::Error> {
if (val == atom::api::Cookies::SUCCESS)
return v8::Null(isolate);
else
return v8::Exception::Error(StringToV8(isolate, "failed"));
return v8::Exception::Error(StringToV8(isolate, "Setting cookie failed"));
}
};

View file

@ -61,8 +61,10 @@ bool Menu::GetAcceleratorForCommandId(int command_id,
return mate::ConvertFromV8(isolate(), val, accelerator);
}
void Menu::ExecuteCommand(int command_id, int event_flags) {
execute_command_.Run(command_id);
void Menu::ExecuteCommand(int command_id, int flags) {
execute_command_.Run(
mate::internal::CreateEventFromFlags(isolate(), flags),
command_id);
}
void Menu::MenuWillShow(ui::SimpleMenuModel* source) {

View file

@ -90,7 +90,7 @@ class Menu : public mate::TrackableObject<Menu>,
base::Callback<bool(int)> is_enabled_;
base::Callback<bool(int)> is_visible_;
base::Callback<v8::Local<v8::Value>(int)> get_accelerator_;
base::Callback<void(int)> execute_command_;
base::Callback<void(v8::Local<v8::Value>, int)> execute_command_;
base::Callback<void()> menu_will_show_;
DISALLOW_COPY_AND_ASSIGN(Menu);

View file

@ -41,8 +41,10 @@
#include "net/http/http_auth_preferences.h"
#include "net/proxy/proxy_service.h"
#include "net/proxy/proxy_config_service_fixed.h"
#include "net/url_request/static_http_user_agent_settings.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "ui/base/l10n/l10n_util.h"
using content::BrowserThread;
using content::StoragePartition;
@ -93,6 +95,15 @@ uint32_t GetQuotaMask(const std::vector<std::string>& quota_types) {
return quota_mask;
}
void SetUserAgentInIO(scoped_refptr<net::URLRequestContextGetter> getter,
const std::string& accept_lang,
const std::string& user_agent) {
getter->GetURLRequestContext()->set_http_user_agent_settings(
new net::StaticHttpUserAgentSettings(
net::HttpUtil::GenerateAcceptLanguageHeader(accept_lang),
user_agent));
}
} // namespace
namespace mate {
@ -455,6 +466,23 @@ void Session::AllowNTLMCredentialsForDomains(const std::string& domains) {
domains));
}
void Session::SetUserAgent(const std::string& user_agent,
mate::Arguments* args) {
browser_context_->SetUserAgent(user_agent);
std::string accept_lang = l10n_util::GetApplicationLocale("");
args->GetNext(&accept_lang);
auto getter = browser_context_->GetRequestContext();
getter->GetNetworkTaskRunner()->PostTask(
FROM_HERE,
base::Bind(&SetUserAgentInIO, getter, accept_lang, user_agent));
}
std::string Session::GetUserAgent() {
return browser_context_->GetUserAgent();
}
v8::Local<v8::Value> Session::Cookies(v8::Isolate* isolate) {
if (cookies_.IsEmpty()) {
auto handle = atom::api::Cookies::Create(isolate, browser_context());
@ -520,6 +548,8 @@ void Session::BuildPrototype(v8::Isolate* isolate,
.SetMethod("clearHostResolverCache", &Session::ClearHostResolverCache)
.SetMethod("allowNTLMCredentialsForDomains",
&Session::AllowNTLMCredentialsForDomains)
.SetMethod("setUserAgent", &Session::SetUserAgent)
.SetMethod("getUserAgent", &Session::GetUserAgent)
.SetProperty("cookies", &Session::Cookies)
.SetProperty("protocol", &Session::Protocol)
.SetProperty("webRequest", &Session::WebRequest);

View file

@ -57,15 +57,7 @@ class Session: public mate::TrackableObject<Session>,
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype);
protected:
Session(v8::Isolate* isolate, AtomBrowserContext* browser_context);
~Session();
// content::DownloadManager::Observer:
void OnDownloadCreated(content::DownloadManager* manager,
content::DownloadItem* item) override;
private:
// Methods.
void ResolveProxy(const GURL& url, ResolveProxyCallback callback);
template<CacheAction action>
void DoCacheAction(const net::CompletionCallback& callback);
@ -80,10 +72,21 @@ class Session: public mate::TrackableObject<Session>,
mate::Arguments* args);
void ClearHostResolverCache(mate::Arguments* args);
void AllowNTLMCredentialsForDomains(const std::string& domains);
void SetUserAgent(const std::string& user_agent, mate::Arguments* args);
std::string GetUserAgent();
v8::Local<v8::Value> Cookies(v8::Isolate* isolate);
v8::Local<v8::Value> Protocol(v8::Isolate* isolate);
v8::Local<v8::Value> WebRequest(v8::Isolate* isolate);
protected:
Session(v8::Isolate* isolate, AtomBrowserContext* browser_context);
~Session();
// content::DownloadManager::Observer:
void OnDownloadCreated(content::DownloadManager* manager,
content::DownloadItem* item) override;
private:
// Cached object.
v8::Global<v8::Value> cookies_;
v8::Global<v8::Value> protocol_;

View file

@ -53,6 +53,10 @@ void SystemPreferences::BuildPrototype(
&SystemPreferences::SubscribeNotification)
.SetMethod("unsubscribeNotification",
&SystemPreferences::UnsubscribeNotification)
.SetMethod("subscribeLocalNotification",
&SystemPreferences::SubscribeLocalNotification)
.SetMethod("unsubscribeLocalNotification",
&SystemPreferences::UnsubscribeLocalNotification)
.SetMethod("getUserDefault", &SystemPreferences::GetUserDefault)
#endif
.SetMethod("isDarkMode", &SystemPreferences::IsDarkMode);

View file

@ -26,17 +26,18 @@ class SystemPreferences : public mate::EventEmitter<SystemPreferences> {
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype);
#if defined(OS_MACOSX)
using NotificationCallback = base::Callback<
void(const std::string&, const base::DictionaryValue&)>;
#endif
#if defined(OS_WIN)
bool IsAeroGlassEnabled();
#elif defined(OS_MACOSX)
using NotificationCallback = base::Callback<
void(const std::string&, const base::DictionaryValue&)>;
int SubscribeNotification(const std::string& name,
const NotificationCallback& callback);
void UnsubscribeNotification(int id);
int SubscribeLocalNotification(const std::string& name,
const NotificationCallback& callback);
void UnsubscribeLocalNotification(int request_id);
v8::Local<v8::Value> GetUserDefault(const std::string& name,
const std::string& type);
#endif
@ -46,6 +47,13 @@ class SystemPreferences : public mate::EventEmitter<SystemPreferences> {
explicit SystemPreferences(v8::Isolate* isolate);
~SystemPreferences() override;
#if defined(OS_MACOSX)
int DoSubscribeNotification(const std::string& name,
const NotificationCallback& callback,
bool is_local);
void DoUnsubscribeNotification(int request_id, bool is_local);
#endif
private:
DISALLOW_COPY_AND_ASSIGN(SystemPreferences);
};

View file

@ -30,34 +30,59 @@ std::map<int, id> g_id_map;
int SystemPreferences::SubscribeNotification(
const std::string& name, const NotificationCallback& callback) {
return DoSubscribeNotification(name, callback, false);
}
void SystemPreferences::UnsubscribeNotification(int request_id) {
DoUnsubscribeNotification(request_id, false);
}
int SystemPreferences::SubscribeLocalNotification(
const std::string& name, const NotificationCallback& callback) {
return DoSubscribeNotification(name, callback, true);
}
void SystemPreferences::UnsubscribeLocalNotification(int request_id) {
DoUnsubscribeNotification(request_id, true);
}
int SystemPreferences::DoSubscribeNotification(const std::string& name,
const NotificationCallback& callback, bool is_local) {
int request_id = g_next_id++;
__block NotificationCallback copied_callback = callback;
g_id_map[request_id] = [[NSDistributedNotificationCenter defaultCenter]
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());
}
NSNotificationCenter* center = is_local ?
[NSNotificationCenter defaultCenter] :
[NSDistributedNotificationCenter defaultCenter];
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());
}
}
];
return request_id;
}
void SystemPreferences::UnsubscribeNotification(int request_id) {
void SystemPreferences::DoUnsubscribeNotification(int request_id, bool is_local) {
auto iter = g_id_map.find(request_id);
if (iter != g_id_map.end()) {
id observer = iter->second;
[[NSDistributedNotificationCenter defaultCenter] removeObserver:observer];
NSNotificationCenter* center = is_local ?
[NSNotificationCenter defaultCenter] :
[NSDistributedNotificationCenter defaultCenter];
[center removeObserver:observer];
g_id_map.erase(iter);
}
}

View file

@ -16,7 +16,6 @@
#include "atom/common/node_includes.h"
#include "native_mate/constructor.h"
#include "native_mate/dictionary.h"
#include "ui/events/event_constants.h"
#include "ui/gfx/image/image.h"
namespace atom {
@ -44,24 +43,15 @@ mate::WrappableBase* Tray::New(v8::Isolate* isolate,
}
void Tray::OnClicked(const gfx::Rect& bounds, int modifiers) {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
EmitCustomEvent("click",
ModifiersToObject(isolate(), modifiers), bounds);
EmitWithFlags("click", modifiers, bounds);
}
void Tray::OnDoubleClicked(const gfx::Rect& bounds, int modifiers) {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
EmitCustomEvent("double-click",
ModifiersToObject(isolate(), modifiers), bounds);
EmitWithFlags("double-click", modifiers, bounds);
}
void Tray::OnRightClicked(const gfx::Rect& bounds, int modifiers) {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
EmitCustomEvent("right-click",
ModifiersToObject(isolate(), modifiers), bounds);
EmitWithFlags("right-click", modifiers, bounds);
}
void Tray::OnBalloonShow() {
@ -159,14 +149,8 @@ void Tray::SetContextMenu(v8::Isolate* isolate, mate::Handle<Menu> menu) {
tray_icon_->SetContextMenu(menu->model());
}
v8::Local<v8::Object> Tray::ModifiersToObject(v8::Isolate* isolate,
int modifiers) {
mate::Dictionary obj(isolate, v8::Object::New(isolate));
obj.Set("shiftKey", static_cast<bool>(modifiers & ui::EF_SHIFT_DOWN));
obj.Set("ctrlKey", static_cast<bool>(modifiers & ui::EF_CONTROL_DOWN));
obj.Set("altKey", static_cast<bool>(modifiers & ui::EF_ALT_DOWN));
obj.Set("metaKey", static_cast<bool>(modifiers & ui::EF_COMMAND_DOWN));
return obj.GetHandle();
gfx::Rect Tray::GetBounds() {
return tray_icon_->GetBounds();
}
// static
@ -181,7 +165,8 @@ void Tray::BuildPrototype(v8::Isolate* isolate,
.SetMethod("setHighlightMode", &Tray::SetHighlightMode)
.SetMethod("displayBalloon", &Tray::DisplayBalloon)
.SetMethod("popUpContextMenu", &Tray::PopUpContextMenu)
.SetMethod("setContextMenu", &Tray::SetContextMenu);
.SetMethod("setContextMenu", &Tray::SetContextMenu)
.SetMethod("getBounds", &Tray::GetBounds);
}
} // namespace api

View file

@ -65,10 +65,9 @@ class Tray : public mate::TrackableObject<Tray>,
void DisplayBalloon(mate::Arguments* args, const mate::Dictionary& options);
void PopUpContextMenu(mate::Arguments* args);
void SetContextMenu(v8::Isolate* isolate, mate::Handle<Menu> menu);
gfx::Rect GetBounds();
private:
v8::Local<v8::Object> ModifiersToObject(v8::Isolate* isolate, int modifiers);
v8::Global<v8::Object> menu_;
std::unique_ptr<TrayIcon> tray_icon_;

View file

@ -17,6 +17,7 @@
#include "atom/browser/lib/bluetooth_chooser.h"
#include "atom/browser/native_window.h"
#include "atom/browser/net/atom_network_delegate.h"
#include "atom/browser/ui/drag_util.h"
#include "atom/browser/web_contents_permission_helper.h"
#include "atom/browser/web_contents_preferences.h"
#include "atom/browser/web_view_guest_delegate.h"
@ -61,11 +62,9 @@
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/static_http_user_agent_settings.h"
#include "net/url_request/url_request_context.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "third_party/WebKit/public/web/WebFindOptions.h"
#include "ui/base/l10n/l10n_util.h"
#include "atom/common/node_includes.h"
@ -76,15 +75,6 @@ struct PrintSettings {
bool print_background;
};
void SetUserAgentInIO(scoped_refptr<net::URLRequestContextGetter> getter,
std::string accept_lang,
std::string user_agent) {
getter->GetURLRequestContext()->set_http_user_agent_settings(
new net::StaticHttpUserAgentSettings(
net::HttpUtil::GenerateAcceptLanguageHeader(accept_lang),
user_agent));
}
} // namespace
namespace mate {
@ -618,7 +608,10 @@ void WebContents::DidFailProvisionalLoad(
bool was_ignored_by_handler) {
bool is_main_frame = !render_frame_host->GetParent();
Emit("did-fail-provisional-load", code, description, url, is_main_frame);
Emit("did-fail-load", code, description, url, is_main_frame);
// Do not emit "did-fail-load" for canceled requests.
if (code != net::ERR_ABORTED)
Emit("did-fail-load", code, description, url, is_main_frame);
}
void WebContents::DidFailLoad(content::RenderFrameHost* render_frame_host,
@ -811,7 +804,7 @@ void WebContents::LoadURL(const GURL& url, const mate::Dictionary& options) {
std::string user_agent;
if (options.Get("userAgent", &user_agent))
SetUserAgent(user_agent);
web_contents()->SetUserAgentOverride(user_agent);
std::string extra_headers;
if (options.Get("extraHeaders", &extra_headers))
@ -898,14 +891,9 @@ bool WebContents::IsCrashed() const {
return web_contents()->IsCrashed();
}
void WebContents::SetUserAgent(const std::string& user_agent) {
void WebContents::SetUserAgent(const std::string& user_agent,
mate::Arguments* args) {
web_contents()->SetUserAgentOverride(user_agent);
scoped_refptr<net::URLRequestContextGetter> getter =
web_contents()->GetBrowserContext()->GetRequestContext();
auto accept_lang = l10n_util::GetApplicationLocale("");
getter->GetNetworkTaskRunner()->PostTask(FROM_HERE,
base::Bind(&SetUserAgentInIO, getter, accept_lang, user_agent));
}
std::string WebContents::GetUserAgent() {
@ -1194,15 +1182,14 @@ void WebContents::SendInputEvent(v8::Isolate* isolate,
isolate, "Invalid event object")));
}
void WebContents::BeginFrameSubscription(
mate::Arguments* args) {
FrameSubscriber::FrameCaptureCallback callback;
void WebContents::BeginFrameSubscription(mate::Arguments* args) {
bool only_dirty = false;
FrameSubscriber::FrameCaptureCallback callback;
args->GetNext(&only_dirty);
if (!args->GetNext(&callback)) {
args->GetNext(&only_dirty);
if (!args->GetNext(&callback))
args->ThrowTypeError("'callback' must be defined");
args->ThrowError();
return;
}
const auto view = web_contents()->GetRenderWidgetHostView();
@ -1219,6 +1206,35 @@ void WebContents::EndFrameSubscription() {
view->EndFrameSubscription();
}
void WebContents::StartDrag(const mate::Dictionary& item,
mate::Arguments* args) {
base::FilePath file;
std::vector<base::FilePath> files;
if (!item.Get("files", &files) && item.Get("file", &file)) {
files.push_back(file);
}
mate::Handle<NativeImage> icon;
if (!item.Get("icon", &icon) && !file.empty()) {
// TODO(zcbenz): Set default icon from file.
}
// Error checking.
if (icon.IsEmpty()) {
args->ThrowError("icon must be set");
return;
}
// Start dragging.
if (!files.empty()) {
base::MessageLoop::ScopedNestableTaskAllower allow(
base::MessageLoop::current());
DragFileItems(files, icon->image(), web_contents()->GetNativeView());
} else {
args->ThrowError("There is nothing to drag");
}
}
void WebContents::OnCursorChange(const content::WebCursor& cursor) {
content::WebCursor::CursorInfo info;
cursor.GetCursorInfo(&info);
@ -1338,6 +1354,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
.SetMethod("beginFrameSubscription",
&WebContents::BeginFrameSubscription)
.SetMethod("endFrameSubscription", &WebContents::EndFrameSubscription)
.SetMethod("startDrag", &WebContents::StartDrag)
.SetMethod("setSize", &WebContents::SetSize)
.SetMethod("isGuest", &WebContents::IsGuest)
.SetMethod("getType", &WebContents::GetType)

View file

@ -81,7 +81,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
void GoForward();
void GoToOffset(int offset);
bool IsCrashed() const;
void SetUserAgent(const std::string& user_agent);
void SetUserAgent(const std::string& user_agent, mate::Arguments* args);
std::string GetUserAgent();
void InsertCSS(const std::string& css);
bool SavePage(const base::FilePath& full_file_path,
@ -142,6 +142,9 @@ class WebContents : public mate::TrackableObject<WebContents>,
void BeginFrameSubscription(mate::Arguments* args);
void EndFrameSubscription();
// Dragging native items.
void StartDrag(const mate::Dictionary& item, mate::Arguments* args);
// Methods for creating <webview>.
void SetSize(const SetSizeParams& params);
bool IsGuest() const;

View file

@ -106,9 +106,6 @@ Window::Window(v8::Isolate* isolate, const mate::Dictionary& options) {
options,
parent.IsEmpty() ? nullptr : parent->window_.get()));
web_contents->SetOwnerWindow(window_.get());
window_->InitFromOptions(options);
window_->AddObserver(this);
AttachAsUserData(window_.get());
#if defined(TOOLKIT_VIEWS)
// Sets the window icon.
@ -116,6 +113,10 @@ Window::Window(v8::Isolate* isolate, const mate::Dictionary& options) {
if (options.Get(options::kIcon, &icon))
SetIcon(icon);
#endif
window_->InitFromOptions(options);
window_->AddObserver(this);
AttachAsUserData(window_.get());
}
Window::~Window() {
@ -572,6 +573,10 @@ void Window::SetIgnoreMouseEvents(bool ignore) {
return window_->SetIgnoreMouseEvents(ignore);
}
void Window::SetContentProtection(bool enable) {
return window_->SetContentProtection(enable);
}
void Window::SetFocusable(bool focusable) {
return window_->SetFocusable(focusable);
}
@ -833,6 +838,7 @@ void Window::BuildPrototype(v8::Isolate* isolate,
.SetMethod("setDocumentEdited", &Window::SetDocumentEdited)
.SetMethod("isDocumentEdited", &Window::IsDocumentEdited)
.SetMethod("setIgnoreMouseEvents", &Window::SetIgnoreMouseEvents)
.SetMethod("setContentProtection", &Window::SetContentProtection)
.SetMethod("setFocusable", &Window::SetFocusable)
.SetMethod("focusOnWebView", &Window::FocusOnWebView)
.SetMethod("blurWebView", &Window::BlurWebView)

View file

@ -153,6 +153,7 @@ class Window : public mate::TrackableObject<Window>,
void SetDocumentEdited(bool edited);
bool IsDocumentEdited();
void SetIgnoreMouseEvents(bool ignore);
void SetContentProtection(bool enable);
void SetFocusable(bool focusable);
void CapturePage(mate::Arguments* args);
void SetProgressBar(double progress);

View file

@ -8,6 +8,7 @@
#include "native_mate/arguments.h"
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
#include "ui/events/event_constants.h"
namespace mate {
@ -65,6 +66,15 @@ v8::Local<v8::Object> CreateCustomEvent(
return event;
}
v8::Local<v8::Object> CreateEventFromFlags(v8::Isolate* isolate, int flags) {
mate::Dictionary obj = mate::Dictionary::CreateEmpty(isolate);
obj.Set("shiftKey", static_cast<bool>(flags & ui::EF_SHIFT_DOWN));
obj.Set("ctrlKey", static_cast<bool>(flags & ui::EF_CONTROL_DOWN));
obj.Set("altKey", static_cast<bool>(flags & ui::EF_ALT_DOWN));
obj.Set("metaKey", static_cast<bool>(flags & ui::EF_COMMAND_DOWN));
return obj.GetHandle();
}
} // namespace internal
} // namespace mate

View file

@ -30,6 +30,7 @@ v8::Local<v8::Object> CreateCustomEvent(
v8::Isolate* isolate,
v8::Local<v8::Object> object,
v8::Local<v8::Object> event);
v8::Local<v8::Object> CreateEventFromFlags(v8::Isolate* isolate, int flags);
} // namespace internal
@ -54,6 +55,16 @@ class EventEmitter : public Wrappable<T> {
internal::CreateCustomEvent(isolate(), GetWrapper(), event), args...);
}
// this.emit(name, new Event(flags), args...);
template<typename... Args>
bool EmitWithFlags(const base::StringPiece& name,
int flags,
const Args&... args) {
return EmitCustomEvent(
name,
internal::CreateEventFromFlags(isolate(), flags), args...);
}
// this.emit(name, new Event(), args...);
template<typename... Args>
bool Emit(const base::StringPiece& name, const Args&... args) {

View file

@ -5,8 +5,8 @@
#include "atom/browser/api/frame_subscriber.h"
#include "base/bind.h"
#include "atom/common/node_includes.h"
#include "atom/common/native_mate_converters/gfx_converter.h"
#include "atom/common/node_includes.h"
#include "content/public/browser/render_widget_host.h"
#include <iostream>
@ -31,8 +31,11 @@ FrameSubscriber::FrameSubscriber(v8::Isolate* isolate,
content::RenderWidgetHostView* view,
const FrameCaptureCallback& callback,
bool only_dirty)
: isolate_(isolate), view_(view), callback_(callback),
only_dirty_(only_dirty), weak_factory_(this) {
: isolate_(isolate),
view_(view),
callback_(callback),
only_dirty_(only_dirty),
weak_factory_(this) {
}
bool FrameSubscriber::ShouldCaptureFrame(
@ -87,8 +90,9 @@ void FrameSubscriber::ReadbackResultAsBitmap(
}
void FrameSubscriber::OnFrameDelivered(const FrameCaptureCallback& callback,
const gfx::Rect& damage_rect, const SkBitmap& bitmap,
content::ReadbackResponse response) {
const gfx::Rect& damage_rect,
const SkBitmap& bitmap,
content::ReadbackResponse response) {
if (response != content::ReadbackResponse::READBACK_SUCCESS)
return;
@ -106,7 +110,7 @@ void FrameSubscriber::OnFrameDelivered(const FrameCaptureCallback& callback,
rgb_arr_size);
v8::Local<v8::Value> damage =
mate::Converter<gfx::Rect>::ToV8(isolate_, damage_rect);
mate::Converter<gfx::Rect>::ToV8(isolate_, damage_rect);
callback_.Run(buffer.ToLocalChecked(), damage);
}

View file

@ -35,7 +35,7 @@ class FrameSubscriberRenderWidgetHostView
class FrameSubscriber : public content::RenderWidgetHostViewFrameSubscriber {
public:
using FrameCaptureCallback =
base::Callback<void(v8::Local<v8::Value>, v8::Local<v8::Value>)>;
base::Callback<void(v8::Local<v8::Value>, v8::Local<v8::Value>)>;
FrameSubscriber(v8::Isolate* isolate,
content::RenderWidgetHostView* view,
@ -52,8 +52,9 @@ class FrameSubscriber : public content::RenderWidgetHostViewFrameSubscriber {
std::unique_ptr<cc::CopyOutputResult> result);
void OnFrameDelivered(const FrameCaptureCallback& callback,
const gfx::Rect& damage_rect, const SkBitmap& bitmap,
content::ReadbackResponse response);
const gfx::Rect& damage_rect,
const SkBitmap& bitmap,
content::ReadbackResponse response);
v8::Isolate* isolate_;
content::RenderWidgetHostView* view_;

View file

@ -7,8 +7,8 @@
#include <utility>
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/common/google_api_key.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/geolocation_provider.h"
namespace atom {
@ -25,6 +25,7 @@ const char* kGeolocationProviderURL =
} // namespace
AtomAccessTokenStore::AtomAccessTokenStore() {
LOG(ERROR) << "AtomAccessTokenStore";
content::GeolocationProvider::GetInstance()->UserDidOptIntoLocationServices();
}
@ -33,21 +34,35 @@ AtomAccessTokenStore::~AtomAccessTokenStore() {
void AtomAccessTokenStore::LoadAccessTokens(
const LoadAccessTokensCallback& callback) {
AccessTokenMap access_token_map;
// Equivelent to access_token_map[kGeolocationProviderURL].
// Somehow base::string16 is causing compilation errors when used in a pair
// of std::map on Linux, this can work around it.
std::pair<GURL, base::string16> token_pair;
token_pair.first = GURL(kGeolocationProviderURL);
access_token_map.insert(token_pair);
auto browser_context = AtomBrowserMainParts::Get()->browser_context();
callback.Run(access_token_map, browser_context->url_request_context_getter());
content::BrowserThread::PostTaskAndReply(
content::BrowserThread::UI,
FROM_HERE,
base::Bind(&AtomAccessTokenStore::GetRequestContextOnUIThread, this),
base::Bind(&AtomAccessTokenStore::RespondOnOriginatingThread,
this, callback));
}
void AtomAccessTokenStore::SaveAccessToken(const GURL& server_url,
const base::string16& access_token) {
}
void AtomAccessTokenStore::GetRequestContextOnUIThread() {
auto browser_context = brightray::BrowserContext::From("", false);
request_context_getter_ = browser_context->GetRequestContext();
}
void AtomAccessTokenStore::RespondOnOriginatingThread(
const LoadAccessTokensCallback& callback) {
// Equivelent to access_token_map[kGeolocationProviderURL].
// Somehow base::string16 is causing compilation errors when used in a pair
// of std::map on Linux, this can work around it.
AccessTokenMap access_token_map;
std::pair<GURL, base::string16> token_pair;
token_pair.first = GURL(kGeolocationProviderURL);
access_token_map.insert(token_pair);
callback.Run(access_token_map, request_context_getter_.get());
request_context_getter_ = nullptr;
}
} // namespace atom

View file

@ -9,12 +9,10 @@
namespace atom {
class AtomBrowserContext;
class AtomAccessTokenStore : public content::AccessTokenStore {
public:
AtomAccessTokenStore();
virtual ~AtomAccessTokenStore();
~AtomAccessTokenStore();
// content::AccessTokenStore:
void LoadAccessTokens(
@ -23,6 +21,11 @@ class AtomAccessTokenStore : public content::AccessTokenStore {
const base::string16& access_token) override;
private:
void GetRequestContextOnUIThread();
void RespondOnOriginatingThread(const LoadAccessTokensCallback& callback);
scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
DISALLOW_COPY_AND_ASSIGN(AtomAccessTokenStore);
};

View file

@ -287,20 +287,21 @@ brightray::BrowserMainParts* AtomBrowserClient::OverrideCreateBrowserMainParts(
void AtomBrowserClient::WebNotificationAllowed(
int render_process_id,
const base::Callback<void(bool)>& callback) {
const base::Callback<void(bool, bool)>& callback) {
content::WebContents* web_contents =
WebContentsPreferences::GetWebContentsFromProcessID(render_process_id);
if (!web_contents) {
callback.Run(false);
callback.Run(false, false);
return;
}
auto permission_helper =
WebContentsPermissionHelper::FromWebContents(web_contents);
if (!permission_helper) {
callback.Run(false);
callback.Run(false, false);
return;
}
permission_helper->RequestWebNotificationPermission(callback);
permission_helper->RequestWebNotificationPermission(
base::Bind(callback, web_contents->IsAudioMuted()));
}
void AtomBrowserClient::RenderProcessHostDestroyed(

View file

@ -100,7 +100,7 @@ class AtomBrowserClient : public brightray::BrowserClient,
const content::MainFunctionParams&) override;
void WebNotificationAllowed(
int render_process_id,
const base::Callback<void(bool)>& callback) override;
const base::Callback<void(bool, bool)>& callback) override;
// content::RenderProcessHostObserver:
void RenderProcessHostDestroyed(content::RenderProcessHost* host) override;

View file

@ -68,16 +68,7 @@ AtomBrowserContext::AtomBrowserContext(const std::string& partition,
: brightray::BrowserContext(partition, in_memory),
cert_verifier_(new AtomCertVerifier),
network_delegate_(new AtomNetworkDelegate) {
}
AtomBrowserContext::~AtomBrowserContext() {
}
net::NetworkDelegate* AtomBrowserContext::CreateNetworkDelegate() {
return network_delegate_;
}
std::string AtomBrowserContext::GetUserAgent() {
// Construct user agent string.
Browser* browser = Browser::Get();
std::string name = RemoveWhitespace(browser->GetName());
std::string user_agent;
@ -91,7 +82,22 @@ std::string AtomBrowserContext::GetUserAgent() {
browser->GetVersion().c_str(),
CHROME_VERSION_STRING);
}
return content::BuildUserAgentFromProduct(user_agent);
user_agent_ = content::BuildUserAgentFromProduct(user_agent);
}
AtomBrowserContext::~AtomBrowserContext() {
}
void AtomBrowserContext::SetUserAgent(const std::string& user_agent) {
user_agent_ = user_agent;
}
net::NetworkDelegate* AtomBrowserContext::CreateNetworkDelegate() {
return network_delegate_;
}
std::string AtomBrowserContext::GetUserAgent() {
return user_agent_;
}
std::unique_ptr<net::URLRequestJobFactory>

View file

@ -22,6 +22,8 @@ class AtomBrowserContext : public brightray::BrowserContext {
AtomBrowserContext(const std::string& partition, bool in_memory);
~AtomBrowserContext() override;
void SetUserAgent(const std::string& user_agent);
// brightray::URLRequestContextGetter::Delegate:
net::NetworkDelegate* CreateNetworkDelegate() override;
std::string GetUserAgent() override;
@ -47,6 +49,7 @@ class AtomBrowserContext : public brightray::BrowserContext {
std::unique_ptr<AtomDownloadManagerDelegate> download_manager_delegate_;
std::unique_ptr<WebViewManager> guest_manager_;
std::unique_ptr<AtomPermissionManager> permission_manager_;
std::string user_agent_;
// Managed by brightray::BrowserContext.
AtomCertVerifier* cert_verifier_;

View file

@ -124,6 +124,8 @@ void AtomBrowserMainParts::PostEarlyInitialization() {
}
void AtomBrowserMainParts::PreMainMessageLoopRun() {
js_env_->OnMessageLoopCreated();
// Run user's main script before most things get initialized, so we can have
// a chance to setup everything.
node_bindings_->PrepareMessageLoop();
@ -169,6 +171,8 @@ void AtomBrowserMainParts::PostMainMessageLoopStart() {
void AtomBrowserMainParts::PostMainMessageLoopRun() {
brightray::BrowserMainParts::PostMainMessageLoopRun();
js_env_->OnMessageLoopDestroying();
#if defined(OS_MACOSX)
FreeAppDelegate();
#endif

View file

@ -118,6 +118,10 @@ void Browser::SetName(const std::string& name) {
name_override_ = name;
}
int Browser::GetBadgeCount() {
return badge_count_;
}
bool Browser::OpenFile(const std::string& file_path) {
bool prevent_default = false;
FOR_EACH_OBSERVER(BrowserObserver,

View file

@ -87,6 +87,10 @@ class Browser : public WindowListObserver {
// Query the current state of default handler for a protocol.
bool IsDefaultProtocolClient(const std::string& protocol);
// Set/Get the badge count.
bool SetBadgeCount(int count);
int GetBadgeCount();
#if defined(OS_MACOSX)
// Hide the application.
void Hide();
@ -149,7 +153,12 @@ class Browser : public WindowListObserver {
// one from app's name.
// The returned string managed by Browser, and should not be modified.
PCWSTR GetAppUserModelID();
#endif
#endif // defined(OS_WIN)
#if defined(OS_LINUX)
// Whether Unity launcher is running.
bool IsUnityRunning();
#endif // defined(OS_LINUX)
// Tell the application to open a file.
bool OpenFile(const std::string& file_path);
@ -216,6 +225,8 @@ class Browser : public WindowListObserver {
std::string version_override_;
std::string name_override_;
int badge_count_ = 0;
#if defined(OS_WIN)
base::string16 app_user_model_id_;
#endif

View file

@ -10,6 +10,7 @@
#include "atom/browser/window_list.h"
#include "atom/common/atom_version.h"
#include "brightray/common/application_info.h"
#include "chrome/browser/ui/libgtk2ui/unity_service.h"
namespace atom {
@ -46,6 +47,16 @@ bool Browser::IsDefaultProtocolClient(const std::string& protocol) {
return false;
}
bool Browser::SetBadgeCount(int count) {
if (IsUnityRunning()) {
unity::SetDownloadCount(count);
badge_count_ = count;
return true;
} else {
return false;
}
}
std::string Browser::GetExecutableFileVersion() const {
return brightray::GetApplicationVersion();
}
@ -54,4 +65,8 @@ std::string Browser::GetExecutableFileProductName() const {
return brightray::GetApplicationName();
}
bool Browser::IsUnityRunning() {
return unity::IsRunning();
}
} // namespace atom

View file

@ -11,6 +11,7 @@
#include "atom/browser/window_list.h"
#include "base/mac/bundle_locations.h"
#include "base/mac/foundation_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/sys_string_conversions.h"
#include "brightray/common/application_info.h"
#include "net/base/mac/url_conversions.h"
@ -114,6 +115,12 @@ bool Browser::IsDefaultProtocolClient(const std::string& protocol) {
void Browser::SetAppUserModelID(const base::string16& name) {
}
bool Browser::SetBadgeCount(int count) {
DockSetBadgeText(count != 0 ? base::IntToString(count) : "");
badge_count_ = count;
return true;
}
void Browser::SetUserActivity(const std::string& type,
const base::DictionaryValue& user_info,
mate::Arguments* args) {

View file

@ -269,6 +269,10 @@ bool Browser::IsDefaultProtocolClient(const std::string& protocol) {
}
}
bool Browser::SetBadgeCount(int count) {
return false;
}
PCWSTR Browser::GetAppUserModelID() {
if (app_user_model_id_.empty()) {
SetAppUserModelID(base::ReplaceStringPlaceholders(

View file

@ -7,6 +7,7 @@
#include <string>
#include "base/command_line.h"
#include "base/message_loop/message_loop.h"
#include "content/public/common/content_switches.h"
#include "gin/array_buffer.h"
#include "gin/v8_initializer.h"
@ -23,6 +24,14 @@ JavascriptEnvironment::JavascriptEnvironment()
context_scope_(v8::Local<v8::Context>::New(isolate_, context_)) {
}
void JavascriptEnvironment::OnMessageLoopCreated() {
isolate_holder_.AddRunMicrotasksObserver();
}
void JavascriptEnvironment::OnMessageLoopDestroying() {
isolate_holder_.RemoveRunMicrotasksObserver();
}
bool JavascriptEnvironment::Initialize() {
auto cmd = base::CommandLine::ForCurrentProcess();
if (cmd->HasSwitch("debug-brk")) {

View file

@ -14,6 +14,9 @@ class JavascriptEnvironment {
public:
JavascriptEnvironment();
void OnMessageLoopCreated();
void OnMessageLoopDestroying();
v8::Isolate* isolate() const { return isolate_; }
v8::Local<v8::Context> context() const {
return v8::Local<v8::Context>::New(isolate_, context_);

View file

@ -157,6 +157,7 @@ class NativeWindow : public base::SupportsUserData,
virtual void SetDocumentEdited(bool edited);
virtual bool IsDocumentEdited();
virtual void SetIgnoreMouseEvents(bool ignore) = 0;
virtual void SetContentProtection(bool enable) = 0;
virtual void SetFocusable(bool focusable);
virtual void SetMenu(ui::MenuModel* menu);
virtual bool HasModalDialog();

View file

@ -79,6 +79,7 @@ class NativeWindowMac : public NativeWindow {
void SetDocumentEdited(bool edited) override;
bool IsDocumentEdited() override;
void SetIgnoreMouseEvents(bool ignore) override;
void SetContentProtection(bool enable) override;
bool HasModalDialog() override;
void SetParentWindow(NativeWindow* parent) override;
gfx::NativeWindow GetNativeWindow() override;

View file

@ -70,6 +70,7 @@ bool ScopedDisableResize::disable_resize_ = false;
@interface AtomNSWindowDelegate : NSObject<NSWindowDelegate> {
@private
atom::NativeWindowMac* shell_;
bool is_zooming_;
}
- (id)initWithShell:(atom::NativeWindowMac*)shell;
@end
@ -79,6 +80,7 @@ bool ScopedDisableResize::disable_resize_ = false;
- (id)initWithShell:(atom::NativeWindowMac*)shell {
if ((self = [super init])) {
shell_ = shell;
is_zooming_ = false;
}
return self;
}
@ -172,16 +174,20 @@ bool ScopedDisableResize::disable_resize_ = false;
}
- (BOOL)windowShouldZoom:(NSWindow*)window toFrame:(NSRect)newFrame {
// Cocoa doen't have concept of maximize/unmaximize, so wee need to emulate
// them by calculating size change when zooming.
if (newFrame.size.width < [window frame].size.width ||
newFrame.size.height < [window frame].size.height)
shell_->NotifyWindowUnmaximize();
else
shell_->NotifyWindowMaximize();
is_zooming_ = true;
return YES;
}
- (void)windowDidEndLiveResize:(NSNotification*)notification {
if (is_zooming_) {
if (shell_->IsMaximized())
shell_->NotifyWindowMaximize();
else
shell_->NotifyWindowUnmaximize();
is_zooming_ = false;
}
}
- (void)windowWillEnterFullScreen:(NSNotification*)notification {
// Hide the native toolbar before entering fullscreen, so there is no visual
// artifacts.
@ -199,6 +205,7 @@ bool ScopedDisableResize::disable_resize_ = false;
// have to set one, because title bar is visible here.
NSWindow* window = shell_->GetNativeWindow();
if ((shell_->transparent() || !shell_->has_frame()) &&
base::mac::IsOSYosemiteOrLater() &&
// FIXME(zcbenz): Showing titlebar for hiddenInset window is weird under
// fullscreen mode.
shell_->title_bar_style() != atom::NativeWindowMac::HIDDEN_INSET) {
@ -223,6 +230,7 @@ bool ScopedDisableResize::disable_resize_ = false;
// Restore the titlebar visibility.
NSWindow* window = shell_->GetNativeWindow();
if ((shell_->transparent() || !shell_->has_frame()) &&
base::mac::IsOSYosemiteOrLater() &&
shell_->title_bar_style() != atom::NativeWindowMac::HIDDEN_INSET) {
[window setTitleVisibility:NSWindowTitleHidden];
}
@ -526,8 +534,10 @@ NativeWindowMac::NativeWindowMac(
[window_ setDisableKeyOrMainWindow:YES];
if (transparent() || !has_frame()) {
// Don't show title bar.
[window_ setTitleVisibility:NSWindowTitleHidden];
if (base::mac::IsOSYosemiteOrLater()) {
// Don't show title bar.
[window_ setTitleVisibility:NSWindowTitleHidden];
}
// Remove non-transparent corners, see http://git.io/vfonD.
[window_ setOpaque:NO];
}
@ -852,6 +862,11 @@ void NativeWindowMac::Center() {
}
void NativeWindowMac::SetTitle(const std::string& title) {
// For macOS <= 10.9, the setTitleVisibility API is not available, we have
// to avoid calling setTitle for frameless window.
if (!base::mac::IsOSYosemiteOrLater() && (transparent() || !has_frame()))
return;
[window_ setTitle:base::SysUTF8ToNSString(title)];
}
@ -935,6 +950,11 @@ void NativeWindowMac::SetIgnoreMouseEvents(bool ignore) {
[window_ setIgnoresMouseEvents:ignore];
}
void NativeWindowMac::SetContentProtection(bool enable) {
[window_ setSharingType:enable ? NSWindowSharingNone
: NSWindowSharingReadOnly];
}
bool NativeWindowMac::HasModalDialog() {
return [window_ attachedSheet] != nil;
}

View file

@ -752,6 +752,13 @@ void NativeWindowViews::SetIgnoreMouseEvents(bool ignore) {
#endif
}
void NativeWindowViews::SetContentProtection(bool enable) {
#if defined(OS_WIN)
DWORD affinity = enable ? WDA_MONITOR : WDA_NONE;
::SetWindowDisplayAffinity(GetAcceleratedWidget(), affinity);
#endif
}
void NativeWindowViews::SetFocusable(bool focusable) {
#if defined(OS_WIN)
LONG ex_style = ::GetWindowLong(GetAcceleratedWidget(), GWL_EXSTYLE);

View file

@ -97,6 +97,7 @@ class NativeWindowViews : public NativeWindow,
void SetHasShadow(bool has_shadow) override;
bool HasShadow() override;
void SetIgnoreMouseEvents(bool ignore) override;
void SetContentProtection(bool enable) override;
void SetFocusable(bool focusable) override;
void SetMenu(ui::MenuModel* menu_model) override;
void SetParentWindow(NativeWindow* parent) override;

View file

@ -17,9 +17,9 @@
<key>CFBundleIconFile</key>
<string>electron.icns</string>
<key>CFBundleVersion</key>
<string>1.2.3</string>
<string>1.2.6</string>
<key>CFBundleShortVersionString</key>
<string>1.2.3</string>
<string>1.2.6</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.developer-tools</string>
<key>LSMinimumSystemVersion</key>

View file

@ -56,8 +56,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,2,3,0
PRODUCTVERSION 1,2,3,0
FILEVERSION 1,2,6,0
PRODUCTVERSION 1,2,6,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -74,12 +74,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "GitHub, Inc."
VALUE "FileDescription", "Electron"
VALUE "FileVersion", "1.2.3"
VALUE "FileVersion", "1.2.6"
VALUE "InternalName", "electron.exe"
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
VALUE "OriginalFilename", "electron.exe"
VALUE "ProductName", "Electron"
VALUE "ProductVersion", "1.2.3"
VALUE "ProductVersion", "1.2.6"
VALUE "SquirrelAwareVersion", "1"
END
END

View file

@ -29,6 +29,10 @@ void SetPlatformAccelerator(ui::Accelerator* accelerator) {
modifiers ^= NSShiftKeyMask;
}
if (character == NSDeleteFunctionKey) {
character = NSDeleteCharacter;
}
NSString* characters =
[[[NSString alloc] initWithCharacters:&character length:1] autorelease];

View file

@ -17,12 +17,14 @@ AtomMenuModel::~AtomMenuModel() {
}
void AtomMenuModel::SetRole(int index, const base::string16& role) {
roles_[index] = role;
int command_id = GetCommandIdAt(index);
roles_[command_id] = role;
}
base::string16 AtomMenuModel::GetRoleAt(int index) {
if (ContainsKey(roles_, index))
return roles_[index];
int command_id = GetCommandIdAt(index);
if (ContainsKey(roles_, command_id))
return roles_[command_id];
else
return base::string16();
}

View file

@ -42,7 +42,7 @@ class AtomMenuModel : public ui::SimpleMenuModel {
private:
Delegate* delegate_; // weak ref.
std::map<int, base::string16> roles_;
std::map<int, base::string16> roles_; // command id -> role
base::ObserverList<Observer> observers_;
DISALLOW_COPY_AND_ASSIGN(AtomMenuModel);

View file

@ -38,6 +38,8 @@ Role kRolesMap[] = {
{ @selector(performMiniaturize:), "minimize" },
{ @selector(performClose:), "close" },
{ @selector(performZoom:), "zoom" },
{ @selector(terminate:), "quit" },
{ @selector(toggleFullScreen:), "togglefullscreen" },
};
} // namespace

View file

@ -0,0 +1,24 @@
// Copyright (c) 2016 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_UI_DRAG_UTIL_H_
#define ATOM_BROWSER_UI_DRAG_UTIL_H_
#include <vector>
#include "ui/gfx/image/image.h"
namespace base {
class FilePath;
}
namespace atom {
void DragFileItems(const std::vector<base::FilePath>& files,
const gfx::Image& icon,
gfx::NativeView view);
} // namespace atom
#endif // ATOM_BROWSER_UI_DRAG_UTIL_H_

View file

@ -0,0 +1,58 @@
// Copyright (c) 2016 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#import <Cocoa/Cocoa.h>
#include "atom/browser/ui/drag_util.h"
#include "base/files/file_path.h"
#include "base/strings/sys_string_conversions.h"
namespace atom {
namespace {
// Write information about the file being dragged to the pasteboard.
void AddFilesToPasteboard(NSPasteboard* pasteboard,
const std::vector<base::FilePath>& files) {
NSMutableArray* fileList = [NSMutableArray array];
for (const base::FilePath& file : files)
[fileList addObject:base::SysUTF8ToNSString(file.value())];
[pasteboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType]
owner:nil];
[pasteboard setPropertyList:fileList forType:NSFilenamesPboardType];
}
} // namespace
void DragFileItems(const std::vector<base::FilePath>& files,
const gfx::Image& icon,
gfx::NativeView view) {
NSPasteboard* pasteboard = [NSPasteboard pasteboardWithName:NSDragPboard];
AddFilesToPasteboard(pasteboard, files);
// Synthesize a drag event, since we don't have access to the actual event
// that initiated a drag (possibly consumed by the Web UI, for example).
NSPoint position = [[view window] mouseLocationOutsideOfEventStream];
NSTimeInterval eventTime = [[NSApp currentEvent] timestamp];
NSEvent* dragEvent = [NSEvent mouseEventWithType:NSLeftMouseDragged
location:position
modifierFlags:NSLeftMouseDraggedMask
timestamp:eventTime
windowNumber:[[view window] windowNumber]
context:nil
eventNumber:0
clickCount:1
pressure:1.0];
// Run the drag operation.
[[view window] dragImage:icon.ToNSImage()
at:position
offset:NSZeroSize
event:dragEvent
pasteboard:pasteboard
source:view
slideBack:YES];
}
} // namespace atom

View file

@ -0,0 +1,48 @@
// Copyright (c) 2016 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/ui/drag_util.h"
#include "ui/aura/window.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/drag_utils.h"
#include "ui/base/dragdrop/file_info.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/screen.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/public/drag_drop_client.h"
namespace atom {
void DragFileItems(const std::vector<base::FilePath>& files,
const gfx::Image& icon,
gfx::NativeView view) {
// Set up our OLE machinery
ui::OSExchangeData data;
drag_utils::CreateDragImageForFile(files[0], icon.AsImageSkia(), &data);
std::vector<ui::FileInfo> file_infos;
for (const base::FilePath& file : files) {
file_infos.push_back(ui::FileInfo(file, base::FilePath()));
}
data.SetFilenames(file_infos);
aura::Window* root_window = view->GetRootWindow();
if (!root_window || !aura::client::GetDragDropClient(root_window))
return;
gfx::Point location = gfx::Screen::GetScreen()->GetCursorScreenPoint();
// TODO(varunjain): Properly determine and send DRAG_EVENT_SOURCE below.
aura::client::GetDragDropClient(root_window)->StartDragAndDrop(
data,
root_window,
view,
location,
ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_LINK,
ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
}
} // namespace atom

View file

@ -4,7 +4,7 @@
#include "atom/browser/ui/file_dialog.h"
#include "atom/browser/native_window.h"
#include "atom/browser/native_window_views.h"
#include "base/callback.h"
#include "base/files/file_util.h"
#include "base/strings/string_util.h"
@ -40,7 +40,8 @@ class FileChooserDialog {
const std::string& button_label,
const base::FilePath& default_path,
const Filters& filters)
: dialog_scope_(parent_window),
: parent_(static_cast<atom::NativeWindowViews*>(parent_window)),
dialog_scope_(parent_window),
filters_(filters) {
const char* confirm_text = GTK_STOCK_OK;
@ -58,9 +59,10 @@ class FileChooserDialog {
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
confirm_text, GTK_RESPONSE_ACCEPT,
NULL);
if (parent_window) {
gfx::NativeWindow window = parent_window->GetNativeWindow();
libgtk2ui::SetGtkTransientForAura(dialog_, window);
if (parent_) {
parent_->SetEnabled(false);
libgtk2ui::SetGtkTransientForAura(dialog_, parent_->GetNativeWindow());
gtk_window_set_modal(GTK_WINDOW(dialog_), TRUE);
}
if (action == GTK_FILE_CHOOSER_ACTION_SAVE)
@ -69,8 +71,6 @@ class FileChooserDialog {
if (action != GTK_FILE_CHOOSER_ACTION_OPEN)
gtk_file_chooser_set_create_folders(GTK_FILE_CHOOSER(dialog_), TRUE);
gtk_window_set_modal(GTK_WINDOW(dialog_), TRUE);
if (!default_path.empty()) {
if (base::DirectoryExists(default_path)) {
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog_),
@ -89,6 +89,8 @@ class FileChooserDialog {
virtual ~FileChooserDialog() {
gtk_widget_destroy(dialog_);
if (parent_)
parent_->SetEnabled(true);
}
void RunAsynchronous() {
@ -143,6 +145,7 @@ class FileChooserDialog {
void AddFilters(const Filters& filters);
base::FilePath AddExtensionForFilename(const gchar* filename) const;
atom::NativeWindowViews* parent_;
atom::NativeWindow::DialogScope dialog_scope_;
GtkWidget* dialog_;
@ -208,7 +211,9 @@ base::FilePath FileChooserDialog::AddExtensionForFilename(
const auto& extensions = filters_[i].second;
for (const auto& extension : extensions) {
if (extension == "*" || path.MatchesExtension("." + extension))
if (extension == "*" ||
base::EndsWith(path.value(), "." + extension,
base::CompareCase::INSENSITIVE_ASCII))
return path;
}

View file

@ -5,7 +5,7 @@
#include "atom/browser/ui/message_box.h"
#include "atom/browser/browser.h"
#include "atom/browser/native_window.h"
#include "atom/browser/native_window_views.h"
#include "base/callback.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@ -36,7 +36,8 @@ class GtkMessageBox {
const std::string& detail,
const gfx::ImageSkia& icon)
: dialog_scope_(parent_window),
cancel_id_(cancel_id) {
cancel_id_(cancel_id),
parent_(static_cast<NativeWindowViews*>(parent_window)) {
// Create dialog.
dialog_ = gtk_message_dialog_new(
nullptr, // parent
@ -75,14 +76,17 @@ class GtkMessageBox {
}
// Parent window.
if (parent_window) {
gfx::NativeWindow window = parent_window->GetNativeWindow();
libgtk2ui::SetGtkTransientForAura(dialog_, window);
if (parent_) {
parent_->SetEnabled(false);
libgtk2ui::SetGtkTransientForAura(dialog_, parent_->GetNativeWindow());
gtk_window_set_modal(GTK_WINDOW(dialog_), TRUE);
}
}
~GtkMessageBox() {
gtk_widget_destroy(dialog_);
if (parent_)
parent_->SetEnabled(true);
}
GtkMessageType GetMessageType(MessageBoxType type) {
@ -123,7 +127,6 @@ class GtkMessageBox {
}
int RunSynchronous() {
gtk_window_set_modal(GTK_WINDOW(dialog_), TRUE);
Show();
int response = gtk_dialog_run(GTK_DIALOG(dialog_));
if (response < 0)
@ -149,6 +152,7 @@ class GtkMessageBox {
// The id to return when the dialog is closed without pressing buttons.
int cancel_id_;
NativeWindowViews* parent_;
GtkWidget* dialog_;
MessageBoxCallback callback_;

View file

@ -30,6 +30,10 @@ void TrayIcon::PopUpContextMenu(const gfx::Point& pos,
ui::SimpleMenuModel* menu_model) {
}
gfx::Rect TrayIcon::GetBounds() {
return gfx::Rect();
}
void TrayIcon::NotifyClicked(const gfx::Rect& bounds, int modifiers) {
FOR_EACH_OBSERVER(TrayIconObserver, observers_, OnClicked(bounds, modifiers));
}

View file

@ -60,8 +60,12 @@ class TrayIcon {
// Set the context menu for this icon.
virtual void SetContextMenu(ui::SimpleMenuModel* menu_model) = 0;
// Returns the bounds of tray icon.
virtual gfx::Rect GetBounds();
void AddObserver(TrayIconObserver* obs) { observers_.AddObserver(obs); }
void RemoveObserver(TrayIconObserver* obs) { observers_.RemoveObserver(obs); }
void NotifyClicked(const gfx::Rect& = gfx::Rect(), int modifiers = 0);
void NotifyDoubleClicked(const gfx::Rect& = gfx::Rect(), int modifiers = 0);
void NotifyBalloonShow();

View file

@ -32,6 +32,7 @@ class TrayIconCocoa : public TrayIcon,
void PopUpContextMenu(const gfx::Point& pos,
ui::SimpleMenuModel* menu_model) override;
void SetContextMenu(ui::SimpleMenuModel* menu_model) override;
gfx::Rect GetBounds() override;
protected:
// AtomMenuModel::Observer:

View file

@ -8,6 +8,7 @@
#include "base/strings/sys_string_conversions.h"
#include "ui/events/cocoa/cocoa_event_utils.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/mac/coordinate_conversion.h"
#include "ui/gfx/screen.h"
namespace {
@ -236,13 +237,13 @@ const CGFloat kVerticalTitleMargin = 2;
// Single click event.
if (event.clickCount == 1)
trayIcon_->NotifyClicked(
[self getBoundsFromEvent:event],
gfx::ScreenRectFromNSRect(event.window.frame),
ui::EventFlagsFromModifiers([event modifierFlags]));
// Double click event.
if (event.clickCount == 2)
trayIcon_->NotifyDoubleClicked(
[self getBoundsFromEvent:event],
gfx::ScreenRectFromNSRect(event.window.frame),
ui::EventFlagsFromModifiers([event modifierFlags]));
[self setNeedsDisplay:YES];
@ -262,7 +263,7 @@ const CGFloat kVerticalTitleMargin = 2;
}
if (menuController_ && ![menuController_ isMenuOpen]) {
// Redraw the dray icon to show highlight if it is enabled.
// Redraw the tray icon to show highlight if it is enabled.
[self setNeedsDisplay:YES];
[statusItem_ popUpStatusItemMenu:[menuController_ menu]];
// The popUpStatusItemMenu returns only after the showing menu is closed.
@ -273,7 +274,7 @@ const CGFloat kVerticalTitleMargin = 2;
- (void)rightMouseUp:(NSEvent*)event {
trayIcon_->NotifyRightClicked(
[self getBoundsFromEvent:event],
gfx::ScreenRectFromNSRect(event.window.frame),
ui::EventFlagsFromModifiers([event modifierFlags]));
}
@ -324,13 +325,6 @@ const CGFloat kVerticalTitleMargin = 2;
return isHighlightEnable_ && (inMouseEventSequence_ || isMenuOpen);
}
- (gfx::Rect)getBoundsFromEvent:(NSEvent*)event {
NSRect frame = event.window.frame;
gfx::Rect bounds(frame.origin.x, 0, NSWidth(frame), NSHeight(frame));
NSScreen* screen = [[NSScreen screens] objectAtIndex:0];
bounds.set_y(NSHeight([screen frame]) - NSMaxY(frame));
return bounds;
}
@end
namespace atom {
@ -386,6 +380,15 @@ void TrayIconCocoa::SetContextMenu(ui::SimpleMenuModel* menu_model) {
[status_item_view_ setMenuController:menu_.get()];
}
gfx::Rect TrayIconCocoa::GetBounds() {
auto bounds = gfx::ScreenRectFromNSRect([status_item_view_ window].frame);
// Calling [window frame] immediately after the view gets created will have
// negative |y| sometimes.
if (bounds.y() < 0)
bounds.set_y(0);
return bounds;
}
void TrayIconCocoa::MenuClosed() {
[status_item_view_ setNeedsDisplay:YES];
}

View file

@ -50,14 +50,7 @@ void GetMenuBarColor(SkColor* enabled, SkColor* disabled, SkColor* highlight,
MenuBar::MenuBar()
: background_color_(kDefaultColor),
menu_model_(NULL) {
#if defined(OS_WIN)
background_color_ = color_utils::GetSysSkColor(COLOR_MENUBAR);
#elif defined(USE_X11)
GetMenuBarColor(&enabled_color_, &disabled_color_, &highlight_color_,
&hover_color_, &background_color_);
#endif
set_background(views::Background::CreateSolidBackground(background_color_));
UpdateMenuBarColor();
SetLayoutManager(new views::BoxLayout(
views::BoxLayout::kHorizontal, 0, 0, 0));
}
@ -152,11 +145,27 @@ void MenuBar::OnMenuButtonClicked(views::MenuButton* source,
int id = source->tag();
ui::MenuModel::ItemType type = menu_model_->GetTypeAt(id);
if (type != ui::MenuModel::TYPE_SUBMENU)
if (type != ui::MenuModel::TYPE_SUBMENU) {
menu_model_->ActivatedAt(id, 0);
return;
}
MenuDelegate menu_delegate(this);
menu_delegate.RunMenu(menu_model_->GetSubmenuModelAt(id), source);
}
void MenuBar::OnNativeThemeChanged(const ui::NativeTheme* theme) {
UpdateMenuBarColor();
}
void MenuBar::UpdateMenuBarColor() {
#if defined(OS_WIN)
background_color_ = color_utils::GetSysSkColor(COLOR_MENUBAR);
#elif defined(USE_X11)
GetMenuBarColor(&enabled_color_, &disabled_color_, &highlight_color_,
&hover_color_, &background_color_);
#endif
set_background(views::Background::CreateSolidBackground(background_color_));
}
} // namespace atom

View file

@ -60,9 +60,11 @@ class MenuBar : public views::View,
void OnMenuButtonClicked(views::MenuButton* source,
const gfx::Point& point,
const ui::Event* event) override;
void OnNativeThemeChanged(const ui::NativeTheme* theme) override;
private:
void UpdateMenuBarColor();
SkColor background_color_;
#if defined(USE_X11)

View file

@ -13,6 +13,7 @@
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/win/dpi.h"
#include "ui/views/controls/menu/menu_runner.h"
namespace atom {
@ -48,26 +49,19 @@ NotifyIcon::~NotifyIcon() {
void NotifyIcon::HandleClickEvent(int modifiers,
bool left_mouse_click,
bool double_button_click) {
NOTIFYICONIDENTIFIER icon_id;
memset(&icon_id, 0, sizeof(NOTIFYICONIDENTIFIER));
icon_id.uID = icon_id_;
icon_id.hWnd = window_;
icon_id.cbSize = sizeof(NOTIFYICONIDENTIFIER);
RECT rect = { 0 };
Shell_NotifyIconGetRect(&icon_id, &rect);
gfx::Rect bounds = GetBounds();
if (left_mouse_click) {
if (double_button_click) // double left click
NotifyDoubleClicked(gfx::Rect(rect), modifiers);
NotifyDoubleClicked(bounds, modifiers);
else // single left click
NotifyClicked(gfx::Rect(rect), modifiers);
NotifyClicked(bounds, modifiers);
return;
} else if (!double_button_click) { // single right click
if (menu_model_)
PopUpContextMenu(gfx::Point(), menu_model_);
else
NotifyRightClicked(gfx::Rect(rect), modifiers);
NotifyRightClicked(bounds, modifiers);
}
}
@ -140,8 +134,9 @@ void NotifyIcon::DisplayBalloon(HICON icon,
void NotifyIcon::PopUpContextMenu(const gfx::Point& pos,
ui::SimpleMenuModel* menu_model) {
// Returns if context menu isn't set.
if (!menu_model)
if (menu_model == nullptr && menu_model_ == nullptr)
return;
// Set our window as the foreground window, so the context menu closes when
// we click away from it.
if (!SetForegroundWindow(window_))
@ -153,7 +148,7 @@ void NotifyIcon::PopUpContextMenu(const gfx::Point& pos,
rect.set_origin(gfx::Screen::GetScreen()->GetCursorScreenPoint());
views::MenuRunner menu_runner(
menu_model,
menu_model != nullptr ? menu_model : menu_model_,
views::MenuRunner::CONTEXT_MENU | views::MenuRunner::HAS_MNEMONICS);
ignore_result(menu_runner.RunMenuAt(
NULL, NULL, rect, views::MENU_ANCHOR_TOPLEFT, ui::MENU_SOURCE_MOUSE));
@ -163,6 +158,18 @@ void NotifyIcon::SetContextMenu(ui::SimpleMenuModel* menu_model) {
menu_model_ = menu_model;
}
gfx::Rect NotifyIcon::GetBounds() {
NOTIFYICONIDENTIFIER icon_id;
memset(&icon_id, 0, sizeof(NOTIFYICONIDENTIFIER));
icon_id.uID = icon_id_;
icon_id.hWnd = window_;
icon_id.cbSize = sizeof(NOTIFYICONIDENTIFIER);
RECT rect = { 0 };
Shell_NotifyIconGetRect(&icon_id, &rect);
return gfx::win::ScreenToDIPRect(gfx::Rect(rect));
}
void NotifyIcon::InitIconData(NOTIFYICONDATA* icon_data) {
memset(icon_data, 0, sizeof(NOTIFYICONDATA));
icon_data->cbSize = sizeof(NOTIFYICONDATA);

View file

@ -54,6 +54,7 @@ class NotifyIcon : public TrayIcon {
void PopUpContextMenu(const gfx::Point& pos,
ui::SimpleMenuModel* menu_model) override;
void SetContextMenu(ui::SimpleMenuModel* menu_model) override;
gfx::Rect GetBounds() override;
private:
void InitIconData(NOTIFYICONDATA* icon_data);