Compare commits

..

53 Commits

Author SHA1 Message Date
Cheng Zhao
96b23830cd Bump v0.11.10. 2014-04-11 21:02:22 +08:00
Cheng Zhao
b0b5d1b1b0 Do not use new clang flags. 2014-04-15 00:18:42 +08:00
Cheng Zhao
b994ae8174 mac: Always cancel application termination.
OS X's application termination doesn't work very well with C++ message
loops. Especially when we return NSTerminateLater for shouldTerminate,
it would be impossible for the C++ message loop to quit, because unless
we explictly let NSApp terminate the application, the message loop would
think the application is not terminated and will run forever.

The fix is to simply ignore the Cocoa's application termination request
and let the C++ message loop deal with it compeletey. But we had the
side effect that atom-shell would always cancel OS X's shutdown request,
this is also the approach chosen by Chromium.

Fixes #229.
Fixes atom/atom#1864.
2014-04-15 00:13:00 +08:00
Cheng Zhao
6f4aed83f0 Fix compiler warning in breakpad when using latest clang. 2014-04-14 23:54:36 +08:00
Cheng Zhao
d654afde5f Bump v0.11.9. 2014-04-11 10:44:41 +00:00
Cheng Zhao
5c5cf3c66e Fix a crash when destroying window. 2014-04-11 18:43:01 +08:00
Cheng Zhao
84d458687a mac: Avoid managing NSWindow by hand. 2014-04-11 12:47:22 +08:00
Cheng Zhao
2ab5d6e35a Remove unneeded accessor. 2014-04-11 12:45:48 +08:00
Cheng Zhao
d6079782d1 mac: InspectableWebContents should be destroyed before release NSWindow.
Fixes atom/atom#1841.
2014-04-11 12:32:42 +08:00
Cheng Zhao
e576d4c014 Fix app.exit compatibility. 2014-04-10 17:08:22 +08:00
Cheng Zhao
a16ea1fbf2 Bump v0.11.8. 2014-04-10 07:30:29 +00:00
Cheng Zhao
f0d9ee4ca9 Shutdown gracefully, fixes #227. 2014-04-10 15:22:17 +08:00
Cheng Zhao
538bd1116d Deprecate app.terminate API.
Users should use app.quit which can shutdown the application gracefuly.
2014-04-10 15:08:14 +08:00
Cheng Zhao
5ead4f655a Bump v0.11.7. 2014-04-08 06:50:40 +00:00
Cheng Zhao
b975d4c41f Detect unresponsive window when quitting.
Preivously this is disabled because quitting multiple windows could
bring up the unresponsive dialog, but since we now have increased the
unresponsive time limitto 5s, this is not needed anymore and could cause
confusions.

Fixes #17.
2014-04-08 14:24:44 +08:00
Cheng Zhao
cca0d8d583 📝 Add docs for executeJavaScriptInDevTools. 2014-04-08 12:52:42 +08:00
Cheng Zhao
d7a54cf3a6 Add API to execute javascript in devtools. 2014-04-08 12:50:12 +08:00
Cheng Zhao
a50d3bde5c gtk: Connect to window-state-event, fixes #226. 2014-04-08 09:32:44 +08:00
Cheng Zhao
7f496f1994 Bump v0.11.6. 2014-04-07 09:21:02 +00:00
Cheng Zhao
395eb067d1 mac: Do not destroy window immediately.
Fixes atom/atom#1841.
2014-04-07 17:20:08 +08:00
Cheng Zhao
98fcc93862 💄 Remove unsed constant. 2014-04-07 17:12:24 +08:00
Cheng Zhao
b21e5a6300 Fix capturePage under accelerated mode, fixes #223. 2014-04-07 15:43:15 +08:00
Cheng Zhao
ac11c95da6 Increase the closing time limit to 5s.
Fixes https://github.com/atom/atom/issues/1838.
2014-04-06 13:16:14 +08:00
Cheng Zhao
5bbf749693 gtk: Handle accelerators after renderer handled them.
The key-press signal captured the key events before renderer handles,
which violated the behavior on OS X and Windows.

Fixes #221.
2014-04-05 19:21:18 +08:00
Cheng Zhao
3d518c2105 gtk: Do not access clipboard in renderer process. 2014-04-05 14:49:59 +08:00
Cheng Zhao
839f875045 Merge pull request #225 from atom/devtools-menu
Enable context menu in devtools
2014-04-05 03:30:47 +00:00
Cheng Zhao
2369f6cc41 Don't build symbols in CI. 2014-04-05 11:05:51 +08:00
Cheng Zhao
ff88535cd5 💄 Fix cpplint warning build/include_what_you_use. 2014-04-05 11:00:35 +08:00
Cheng Zhao
7a38307d1f Use dialog API to override file chooser dialog in web inspector. 2014-04-05 10:24:46 +08:00
Cheng Zhao
877277d837 Enable writing files in devtools. 2014-04-05 09:22:25 +08:00
Cheng Zhao
d4e7fe3eb8 Correctly translate WebInspector menu to native menu. 2014-04-04 22:37:34 +08:00
Cheng Zhao
03e6d564d7 Make remote.getCurrentWindow work for devtools. 2014-04-04 22:28:47 +08:00
Cheng Zhao
f5fc26d8fc Enable getting a window according to its attached devtools. 2014-04-04 22:28:18 +08:00
Cheng Zhao
86ebd6e8e3 Allow sending ipc messages to devtools. 2014-04-04 22:05:43 +08:00
Cheng Zhao
a80fe40f56 Synchronous event should be bound to WebContents.
This allows us to reply to synchronous message for arbitrary
WebContents.
2014-04-04 22:04:42 +08:00
Cheng Zhao
b1f0c2d174 Override web inspector's context menu. 2014-04-03 20:54:42 +08:00
Cheng Zhao
ac794c8085 Enable intercepting devtools window. 2014-04-03 20:20:42 +08:00
Cheng Zhao
663ab8e0bf 💄 Fix cpplint warning. 2014-04-02 14:23:38 +08:00
Cheng Zhao
d2162bf9f4 Bump v0.11.5. 2014-04-02 09:59:21 +08:00
Cheng Zhao
b7a71b885e Make sure tags are pushed. 2014-04-02 09:58:56 +08:00
Cheng Zhao
9aefb9c2d3 Add /vendor/npm to gitignore. 2014-04-02 09:58:38 +08:00
Cheng Zhao
a3e1fa3350 gtk: Consider window frame in SetSize. 2014-03-29 16:07:44 +08:00
Cheng Zhao
bf6fb3872e gtk: Do some guess of window border size according to window manager. 2014-03-29 14:18:47 +08:00
Cheng Zhao
84307dd329 gtk: Fix crash when calling GetSize() for hidden window. 2014-03-29 14:08:25 +08:00
Cheng Zhao
c814803c94 💄 2014-03-28 09:42:37 +00:00
Cheng Zhao
61d54f0558 Make bootstrap script silent. 2014-03-28 09:36:35 +00:00
Cheng Zhao
9d0a11580f Fix calling apm for apm 0.37.0. 2014-03-28 09:30:15 +00:00
Cheng Zhao
7a6db019e8 Use lastes npm in CI. 2014-03-28 09:25:53 +00:00
Cheng Zhao
fdecf09d99 Upgrade to apm@0.37.0 2014-03-28 16:19:19 +08:00
Cheng Zhao
7e7f0888e5 gtk: Force size allocation in window, fixes #219. 2014-03-28 16:01:38 +08:00
Cheng Zhao
5a837f5850 gtk: Detect rare conditions when resizing. 2014-03-27 21:03:27 +08:00
Cheng Zhao
d3e6166de6 gtk: Should remove self from watcher list in destructor. 2014-03-27 18:05:28 +08:00
Cheng Zhao
c6f0968d17 gtk: Do not count menubar in work area size on Unity. 2014-03-27 17:55:28 +08:00
45 changed files with 590 additions and 225 deletions

1
.gitignore vendored
View File

@@ -5,6 +5,7 @@
/out/
/vendor/brightray/vendor/download/
/vendor/python_26/
/vendor/npm/
node_modules/
*.xcodeproj
*.swp

View File

@@ -32,6 +32,7 @@
'atom/common/api/lib/shell.coffee',
'atom/common/lib/init.coffee',
'atom/renderer/lib/init.coffee',
'atom/renderer/lib/inspector.coffee',
'atom/renderer/lib/override.coffee',
'atom/renderer/api/lib/ipc.coffee',
'atom/renderer/api/lib/remote.coffee',
@@ -93,6 +94,8 @@
'atom/browser/browser_observer.h',
'atom/browser/devtools_delegate.cc',
'atom/browser/devtools_delegate.h',
'atom/browser/devtools_web_contents_observer.cc',
'atom/browser/devtools_web_contents_observer.h',
'atom/browser/native_window.cc',
'atom/browser/native_window.h',
'atom/browser/native_window_gtk.cc',

View File

@@ -73,16 +73,6 @@ void App::Quit(const v8::FunctionCallbackInfo<v8::Value>& args) {
Browser::Get()->Quit();
}
// static
void App::Exit(const v8::FunctionCallbackInfo<v8::Value>& args) {
exit(args[0]->IntegerValue());
}
// static
void App::Terminate(const v8::FunctionCallbackInfo<v8::Value>& args) {
Browser::Get()->Terminate();
}
// static
void App::Focus(const v8::FunctionCallbackInfo<v8::Value>& args) {
Browser::Get()->Focus();
@@ -185,8 +175,6 @@ void App::Initialize(v8::Handle<v8::Object> target) {
t->SetClassName(v8::String::NewSymbol("Application"));
NODE_SET_PROTOTYPE_METHOD(t, "quit", Quit);
NODE_SET_PROTOTYPE_METHOD(t, "exit", Exit);
NODE_SET_PROTOTYPE_METHOD(t, "terminate", Terminate);
NODE_SET_PROTOTYPE_METHOD(t, "focus", Focus);
NODE_SET_PROTOTYPE_METHOD(t, "getVersion", GetVersion);
NODE_SET_PROTOTYPE_METHOD(t, "setVersion", SetVersion);

View File

@@ -39,8 +39,6 @@ class App : public EventEmitter,
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Quit(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Exit(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Terminate(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Focus(const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetVersion(const v8::FunctionCallbackInfo<v8::Value>& args);
static void SetVersion(const v8::FunctionCallbackInfo<v8::Value>& args);

View File

@@ -4,10 +4,10 @@
#include "atom/browser/api/atom_api_event.h"
#include "atom/browser/native_window.h"
#include "atom/common/api/api_messages.h"
#include "atom/common/v8/node_common.h"
#include "atom/common/v8/native_type_conversions.h"
#include "content/public/browser/web_contents.h"
namespace atom {
@@ -22,8 +22,6 @@ Event::Event()
}
Event::~Event() {
if (sender_ != NULL)
sender_->RemoveObserver(this);
}
// static
@@ -44,16 +42,17 @@ v8::Handle<v8::Object> Event::CreateV8Object() {
return t->NewInstance(0, NULL);
}
void Event::SetSenderAndMessage(NativeWindow* sender, IPC::Message* message) {
void Event::SetSenderAndMessage(content::WebContents* sender,
IPC::Message* message) {
DCHECK(!sender_);
DCHECK(!message_);
sender_ = sender;
message_ = message;
sender_->AddObserver(this);
Observe(sender);
}
void Event::OnWindowClosed() {
void Event::WebContentsDestroyed(content::WebContents* web_contents) {
sender_ = NULL;
message_ = NULL;
}

View File

@@ -5,11 +5,11 @@
#ifndef ATOM_BROWSER_API_ATOM_API_EVENT_H_
#define ATOM_BROWSER_API_ATOM_API_EVENT_H_
#include "atom/common/v8/scoped_persistent.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/strings/string16.h"
#include "atom/browser/native_window_observer.h"
#include "atom/common/v8/scoped_persistent.h"
#include "content/public/browser/web_contents_observer.h"
#include "vendor/node/src/node_object_wrap.h"
namespace IPC {
@@ -18,12 +18,10 @@ class Message;
namespace atom {
class NativeWindow;
namespace api {
class Event : public node::ObjectWrap,
public NativeWindowObserver {
public content::WebContentsObserver {
public:
virtual ~Event();
@@ -31,7 +29,7 @@ class Event : public node::ObjectWrap,
static v8::Handle<v8::Object> CreateV8Object();
// Pass the sender and message to be replied.
void SetSenderAndMessage(NativeWindow* sender, IPC::Message* message);
void SetSenderAndMessage(content::WebContents* sender, IPC::Message* message);
// Whether event.preventDefault() is called.
bool prevent_default() const { return prevent_default_; }
@@ -39,8 +37,8 @@ class Event : public node::ObjectWrap,
protected:
Event();
// NativeWindowObserver implementations:
virtual void OnWindowClosed() OVERRIDE;
// content::WebContentsObserver implementations:
virtual void WebContentsDestroyed(content::WebContents*) OVERRIDE;
private:
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
@@ -52,7 +50,7 @@ class Event : public node::ObjectWrap,
static ScopedPersistent<v8::Function> constructor_template_;
// Replyer for the synchronous messages.
NativeWindow* sender_;
content::WebContents* sender_;
IPC::Message* message_;
bool prevent_default_;

View File

@@ -503,6 +503,31 @@ void Window::IsCrashed(const v8::FunctionCallbackInfo<v8::Value>& args) {
args.GetReturnValue().Set(self->window_->GetWebContents()->IsCrashed());
}
// static
void Window::GetDevTools(const v8::FunctionCallbackInfo<v8::Value>& args) {
UNWRAP_WINDOW_AND_CHECK;
content::WebContents* web_contents = self->window_->GetDevToolsWebContents();
v8::Local<v8::Object> devtools = v8::Object::New();
devtools->Set(ToV8Value("processId"),
ToV8Value(web_contents->GetRenderProcessHost()->GetID()));
devtools->Set(ToV8Value("routingId"),
ToV8Value(web_contents->GetRoutingID()));
args.GetReturnValue().Set(devtools);
}
// static
void Window::ExecuteJavaScriptInDevTools(
const v8::FunctionCallbackInfo<v8::Value>& args) {
UNWRAP_WINDOW_AND_CHECK;
std::string code;
if (!FromV8Arguments(args, &code))
return node::ThrowTypeError("Bad argument");
self->window_->ExecuteJavaScriptInDevTools(code);
}
// static
void Window::LoadURL(const v8::FunctionCallbackInfo<v8::Value>& args) {
UNWRAP_WINDOW_AND_CHECK;
@@ -686,6 +711,10 @@ void Window::Initialize(v8::Handle<v8::Object> target) {
NODE_SET_PROTOTYPE_METHOD(t, "getProcessId", GetProcessID);
NODE_SET_PROTOTYPE_METHOD(t, "isCrashed", IsCrashed);
NODE_SET_PROTOTYPE_METHOD(t, "getDevTools", GetDevTools);
NODE_SET_PROTOTYPE_METHOD(
t, "executeJavaScriptInDevTools", ExecuteJavaScriptInDevTools);
NODE_SET_PROTOTYPE_METHOD(t, "loadUrl", LoadURL);
NODE_SET_PROTOTYPE_METHOD(t, "getUrl", GetURL);
NODE_SET_PROTOTYPE_METHOD(t, "canGoBack", CanGoBack);

View File

@@ -103,6 +103,11 @@ class Window : public EventEmitter,
static void GetProcessID(const v8::FunctionCallbackInfo<v8::Value>& args);
static void IsCrashed(const v8::FunctionCallbackInfo<v8::Value>& args);
// APIs for devtools.
static void GetDevTools(const v8::FunctionCallbackInfo<v8::Value>& args);
static void ExecuteJavaScriptInDevTools(
const v8::FunctionCallbackInfo<v8::Value>& args);
// APIs for NavigationController.
static void LoadURL(const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetURL(const v8::FunctionCallbackInfo<v8::Value>& args);

View File

@@ -57,7 +57,7 @@ void AtomBrowserBindings::OnRendererMessageSync(
int routing_id,
const string16& channel,
const base::ListValue& args,
NativeWindow* sender,
content::WebContents* sender,
IPC::Message* message) {
v8::Locker locker(node_isolate);
v8::HandleScope handle_scope(node_isolate);

View File

@@ -13,14 +13,16 @@ namespace base {
class ListValue;
}
namespace content {
class WebContents;
}
namespace IPC {
class Message;
}
namespace atom {
class NativeWindow;
class AtomBrowserBindings : public AtomBindings {
public:
AtomBrowserBindings();
@@ -37,7 +39,7 @@ class AtomBrowserBindings : public AtomBindings {
int routing_id,
const string16& channel,
const base::ListValue& args,
NativeWindow* sender,
content::WebContents* sender,
IPC::Message* message);
private:

View File

@@ -27,8 +27,10 @@ if process.platform is 'darwin'
setBadge: bindings.dockSetBadgeText
getBadge: bindings.dockGetBadgeText
# Support old event name.
# Be compatible with old API.
app.once 'ready', -> app.emit 'finish-launching'
app.terminate = app.quit
app.exit = process.exit
# Only one App object pemitted.
module.exports = app

View File

@@ -55,4 +55,11 @@ BrowserWindow.fromProcessIdAndRoutingId = (processId, routingId) ->
return window for window in windows when window.getProcessId() == processId and
window.getRoutingId() == routingId
BrowserWindow.fromDevTools = (processId, routingId) ->
windows = BrowserWindow.getAllWindows()
for window in windows
devtools = window.getDevTools()
return window if devtools.processId == processId and
devtools.routingId == routingId
module.exports = BrowserWindow

View File

@@ -31,7 +31,7 @@
} else {
// System started termination.
atom::Browser::Get()->Quit();
return NSTerminateLater;
return NSTerminateCancel;
}
}

View File

@@ -8,6 +8,7 @@
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/browser/window_list.h"
#include "base/message_loop/message_loop.h"
namespace atom {
@@ -30,11 +31,16 @@ void Browser::Quit() {
atom::WindowList* window_list = atom::WindowList::GetInstance();
if (window_list->size() == 0)
NotifyAndTerminate();
NotifyAndShutdown();
window_list->CloseAllWindows();
}
void Browser::Shutdown() {
is_quiting_ = true;
base::MessageLoop::current()->Quit();
}
std::string Browser::GetVersion() const {
if (version_override_.empty()) {
std::string version = GetExecutableFileVersion();
@@ -88,7 +94,7 @@ void Browser::DidFinishLaunching() {
FOR_EACH_OBSERVER(BrowserObserver, observers_, OnFinishLaunching());
}
void Browser::NotifyAndTerminate() {
void Browser::NotifyAndShutdown() {
bool prevent_default = false;
FOR_EACH_OBSERVER(BrowserObserver, observers_, OnWillQuit(&prevent_default));
@@ -97,22 +103,19 @@ void Browser::NotifyAndTerminate() {
return;
}
Terminate();
Shutdown();
}
void Browser::OnWindowCloseCancelled(NativeWindow* window) {
if (is_quiting_) {
if (is_quiting_)
// Once a beforeunload handler has prevented the closing, we think the quit
// is cancelled too.
is_quiting_ = false;
CancelQuit();
}
}
void Browser::OnWindowAllClosed() {
if (is_quiting_)
NotifyAndTerminate();
NotifyAndShutdown();
else
FOR_EACH_OBSERVER(BrowserObserver, observers_, OnWindowAllClosed());
}

View File

@@ -26,8 +26,8 @@ class Browser : public WindowListObserver {
// Try to close all windows and quit the application.
void Quit();
// Quit the application immediately without cleanup work.
void Terminate();
// Cleanup everything and shutdown the application gracefully.
void Shutdown();
// Focus the application.
void Focus();
@@ -88,11 +88,8 @@ class Browser : public WindowListObserver {
// Returns the name of application bundle or executable file.
std::string GetExecutableFileProductName() const;
// Send the will-quit message and then terminate the application.
void NotifyAndTerminate();
// Tell the system we have cancelled quiting.
void CancelQuit();
// Send the will-quit message and then shutdown the application.
void NotifyAndShutdown();
bool is_quiting_;

View File

@@ -12,11 +12,6 @@
namespace atom {
void Browser::Terminate() {
is_quiting_ = true;
exit(0);
}
void Browser::Focus() {
// Focus on the first visible window.
WindowList* list = WindowList::GetInstance();
@@ -37,8 +32,4 @@ std::string Browser::GetExecutableFileProductName() const {
return "Atom-Shell";
}
void Browser::CancelQuit() {
// No way to cancel quit on Linux.
}
} // namespace atom

View File

@@ -10,11 +10,6 @@
namespace atom {
void Browser::Terminate() {
is_quiting_ = true;
[[AtomApplication sharedApplication] terminate:nil];
}
void Browser::Focus() {
[[AtomApplication sharedApplication] activateIgnoringOtherApps:YES];
}
@@ -31,10 +26,6 @@ std::string Browser::GetExecutableFileProductName() const {
return base::SysNSStringToUTF8(version);
}
void Browser::CancelQuit() {
[[AtomApplication sharedApplication] replyToApplicationShouldTerminate:NO];
}
int Browser::DockBounce(BounceType type) {
return [[AtomApplication sharedApplication] requestUserAttention:type];
}

View File

@@ -33,11 +33,6 @@ BOOL CALLBACK WindowsEnumerationHandler(HWND hwnd, LPARAM param) {
} // namespace
void Browser::Terminate() {
is_quiting_ = true;
PostQuitMessage(0);
}
void Browser::Focus() {
// On Windows we just focus on the first window found for this process.
DWORD pid = GetCurrentProcessId();
@@ -66,8 +61,4 @@ std::string Browser::GetExecutableFileProductName() const {
return "Atom-Shell";
}
void Browser::CancelQuit() {
// TODO(zcbenz): Research on how to cancel shutdown in Windows.
}
} // namespace atom

View File

@@ -10,7 +10,7 @@ var menu = null;
// Quit when all windows are closed.
app.on('window-all-closed', function() {
app.terminate();
app.quit();
});
app.on('open-url', function(event, url) {

View File

@@ -0,0 +1,64 @@
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "atom/browser/devtools_web_contents_observer.h"
#include "atom/browser/api/atom_browser_bindings.h"
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/browser/native_window.h"
#include "atom/common/api/api_messages.h"
#include "base/logging.h"
#include "content/public/browser/render_process_host.h"
#include "ipc/ipc_message_macros.h"
namespace atom {
DevToolsWebContentsObserver::DevToolsWebContentsObserver(
NativeWindow* native_window,
content::WebContents* web_contents)
: content::WebContentsObserver(web_contents),
inspected_window_(native_window) {
DCHECK(native_window);
}
DevToolsWebContentsObserver::~DevToolsWebContentsObserver() {
}
bool DevToolsWebContentsObserver::OnMessageReceived(
const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(DevToolsWebContentsObserver, message)
IPC_MESSAGE_HANDLER(AtomViewHostMsg_Message, OnRendererMessage)
IPC_MESSAGE_HANDLER_DELAY_REPLY(AtomViewHostMsg_Message_Sync,
OnRendererMessageSync)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void DevToolsWebContentsObserver::OnRendererMessage(
const string16& channel,
const base::ListValue& args) {
AtomBrowserMainParts::Get()->atom_bindings()->OnRendererMessage(
web_contents()->GetRenderProcessHost()->GetID(),
web_contents()->GetRoutingID(),
channel,
args);
}
void DevToolsWebContentsObserver::OnRendererMessageSync(
const string16& channel,
const base::ListValue& args,
IPC::Message* reply_msg) {
AtomBrowserMainParts::Get()->atom_bindings()->OnRendererMessageSync(
web_contents()->GetRenderProcessHost()->GetID(),
web_contents()->GetRoutingID(),
channel,
args,
web_contents(),
reply_msg);
}
} // namespace atom

View File

@@ -0,0 +1,41 @@
// Copyright (c) 2014 GitHub, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_DEVTOOLS_WEB_CONTENTS_OBSERVER_H_
#define ATOM_BROWSER_DEVTOOLS_WEB_CONTENTS_OBSERVER_H_
#include "content/public/browser/web_contents_observer.h"
namespace base {
class ListValue;
}
namespace atom {
class NativeWindow;
class DevToolsWebContentsObserver : public content::WebContentsObserver {
public:
DevToolsWebContentsObserver(NativeWindow* native_window,
content::WebContents* web_contents);
virtual ~DevToolsWebContentsObserver();
protected:
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
void OnRendererMessage(const string16& channel,
const base::ListValue& args);
void OnRendererMessageSync(const string16& channel,
const base::ListValue& args,
IPC::Message* reply_msg);
private:
NativeWindow* inspected_window_;
DISALLOW_COPY_AND_ASSIGN(DevToolsWebContentsObserver);
};
} // namespace atom
#endif // ATOM_BROWSER_DEVTOOLS_WEB_CONTENTS_OBSERVER_H_

View File

@@ -98,6 +98,7 @@ ipc.on 'ATOM_BROWSER_CURRENT_WINDOW', (event, processId, routingId) ->
try
BrowserWindow = require 'browser-window'
window = BrowserWindow.fromProcessIdAndRoutingId processId, routingId
window = BrowserWindow.fromDevTools processId, routingId unless window?
event.returnValue = valueToMeta processId, routingId, window
catch e
event.returnValue = errorToMeta e

View File

@@ -8,20 +8,26 @@
#include <utility>
#include <vector>
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/prefs/pref_service.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "atom/browser/api/atom_browser_bindings.h"
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/browser/atom_javascript_dialog_manager.h"
#include "atom/browser/browser.h"
#include "atom/browser/devtools_delegate.h"
#include "atom/browser/devtools_web_contents_observer.h"
#include "atom/browser/ui/file_dialog.h"
#include "atom/browser/window_list.h"
#include "atom/common/api/api_messages.h"
#include "atom/common/atom_version.h"
#include "atom/common/options_switches.h"
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/json/json_writer.h"
#include "base/prefs/pref_service.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/invalidate_type.h"
#include "content/public/browser/navigation_entry.h"
@@ -33,9 +39,6 @@
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents_view.h"
#include "content/public/common/renderer_preferences.h"
#include "atom/common/api/api_messages.h"
#include "atom/common/atom_version.h"
#include "atom/common/options_switches.h"
#include "ipc/ipc_message_macros.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/point.h"
@@ -50,12 +53,6 @@ using content::NavigationEntry;
namespace atom {
namespace {
const char kDockSidePref[] = "brightray.devtools.dockside";
} // namespace
NativeWindow::NativeWindow(content::WebContents* web_contents,
base::DictionaryValue* options)
: content::WebContentsObserver(web_contents),
@@ -194,8 +191,12 @@ bool NativeWindow::HasModalDialog() {
void NativeWindow::OpenDevTools() {
if (devtools_window_) {
devtools_window_->Focus(true);
devtools_web_contents_observer_.reset(new DevToolsWebContentsObserver(
this, devtools_window_->GetWebContents()));
} else {
inspectable_web_contents()->ShowDevTools();
devtools_web_contents_observer_.reset(new DevToolsWebContentsObserver(
this, GetDevToolsWebContents()));
#if defined(OS_MACOSX)
// Temporary fix for flashing devtools, try removing this after upgraded to
// Chrome 32.
@@ -224,6 +225,11 @@ void NativeWindow::InspectElement(int x, int y) {
agent->InspectElement(x, y);
}
void NativeWindow::ExecuteJavaScriptInDevTools(const std::string& script) {
GetDevToolsWebContents()->GetRenderViewHost()->ExecuteJavascriptInWebFrame(
string16(), base::UTF8ToUTF16(script));
}
void NativeWindow::FocusOnWebView() {
GetWebContents()->GetRenderViewHost()->Focus();
}
@@ -264,12 +270,28 @@ base::ProcessHandle NativeWindow::GetRenderProcessHandle() {
void NativeWindow::CapturePage(const gfx::Rect& rect,
const CapturePageCallback& callback) {
content::RenderViewHost* render_view_host =
GetWebContents()->GetRenderViewHost();
content::RenderWidgetHostView* render_widget_host_view =
render_view_host->GetView();
if (!render_widget_host_view) {
callback.Run(std::vector<unsigned char>());
return;
}
gfx::Rect flipped_y_rect = rect;
flipped_y_rect.set_y(-rect.y());
gfx::Size size;
if (flipped_y_rect.IsEmpty())
size = render_widget_host_view->GetViewBounds().size();
else
size = flipped_y_rect.size();
GetWebContents()->GetRenderViewHost()->CopyFromBackingStore(
flipped_y_rect,
gfx::Size(),
size,
base::Bind(&NativeWindow::OnCapturePageDone,
weak_factory_.GetWeakPtr(),
callback));
@@ -288,12 +310,11 @@ void NativeWindow::CloseWebContents() {
content::WebContents* web_contents(GetWebContents());
// Assume the window is not responding if it doesn't cancel the close and is
// not closed in 2000ms, in this way we can quickly show the unresponsive
// not closed in 5000ms, in this way we can quickly show the unresponsive
// dialog when the window is busy executing some script withouth waiting for
// the unresponsive timeout.
if (!Browser::Get()->is_quiting() &&
window_unresposive_closure_.IsCancelled())
ScheduleUnresponsiveEvent(2000);
if (window_unresposive_closure_.IsCancelled())
ScheduleUnresponsiveEvent(5000);
if (web_contents->NeedToFireBeforeUnload())
web_contents->GetRenderViewHost()->FirePageBeforeUnload(false);
@@ -344,6 +365,10 @@ void NativeWindow::NotifyWindowBlur() {
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnWindowBlur());
}
void NativeWindow::DestroyWebContents() {
inspectable_web_contents_.reset();
}
// In atom-shell all reloads and navigations started by renderer process would
// be redirected to this method, so we can have precise control of how we
// would open the url (in our case, is to restart the renderer process). See
@@ -514,6 +539,41 @@ bool NativeWindow::DevToolsShow(std::string* dock_side) {
return false;
}
void NativeWindow::DevToolsSaveToFile(const std::string& url,
const std::string& content,
bool save_as) {
base::FilePath path;
PathsMap::iterator it = saved_files_.find(url);
if (it != saved_files_.end() && !save_as) {
path = it->second;
} else {
if (!file_dialog::ShowSaveDialog(this, url, base::FilePath(url), &path))
return;
}
saved_files_[url] = path;
file_util::WriteFile(path, content.data(), content.size());
// Notify devtools.
base::StringValue url_value(url);
CallDevToolsFunction("InspectorFrontendAPI.savedURL", &url_value);
// TODO(zcbenz): In later Chrome we need to call canceledSaveURL when the save
// failed.
}
void NativeWindow::DevToolsAppendToFile(const std::string& url,
const std::string& content) {
PathsMap::iterator it = saved_files_.find(url);
if (it == saved_files_.end())
return;
file_util::AppendToFile(it->second, content.data(), content.size());
// Notify devtools.
base::StringValue url_value(url);
CallDevToolsFunction("InspectorFrontendAPI.appendedToURL", &url_value);
}
void NativeWindow::ScheduleUnresponsiveEvent(int ms) {
window_unresposive_closure_.Reset(
base::Bind(&NativeWindow::NotifyWindowUnresponsive,
@@ -542,6 +602,27 @@ void NativeWindow::OnCapturePageDone(const CapturePageCallback& callback,
callback.Run(data);
}
void NativeWindow::CallDevToolsFunction(const std::string& function_name,
const base::Value* arg1,
const base::Value* arg2,
const base::Value* arg3) {
std::string params;
if (arg1) {
std::string json;
base::JSONWriter::Write(arg1, &json);
params.append(json);
if (arg2) {
base::JSONWriter::Write(arg2, &json);
params.append(", " + json);
if (arg3) {
base::JSONWriter::Write(arg3, &json);
params.append(", " + json);
}
}
}
ExecuteJavaScriptInDevTools(function_name + "(" + params + ");");
}
void NativeWindow::OnRendererMessage(const string16& channel,
const base::ListValue& args) {
AtomBrowserMainParts::Get()->atom_bindings()->OnRendererMessage(
@@ -559,7 +640,7 @@ void NativeWindow::OnRendererMessageSync(const string16& channel,
GetWebContents()->GetRoutingID(),
channel,
args,
this,
GetWebContents(),
reply_msg);
}

View File

@@ -5,6 +5,7 @@
#ifndef ATOM_BROWSER_NATIVE_WINDOW_H_
#define ATOM_BROWSER_NATIVE_WINDOW_H_
#include <map>
#include <string>
#include <vector>
@@ -41,14 +42,11 @@ class Rect;
class Size;
}
namespace IPC {
class Message;
}
namespace atom {
class AtomJavaScriptDialogManager;
class DevToolsDelegate;
class DevToolsWebContentsObserver;
struct DraggableRegion;
class NativeWindow : public brightray::DefaultWebContentsDelegate,
@@ -138,6 +136,7 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
virtual void CloseDevTools();
virtual bool IsDevToolsOpened();
virtual void InspectElement(int x, int y);
virtual void ExecuteJavaScriptInDevTools(const std::string& script);
virtual void FocusOnWebView();
virtual void BlurWebView();
@@ -197,6 +196,9 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
void NotifyWindowClosed();
void NotifyWindowBlur();
// Destroy the inspectable_web_contents.
void DestroyWebContents();
// Called when the window needs to update its draggable region.
virtual void UpdateDraggableRegions(
const std::vector<DraggableRegion>& regions) = 0;
@@ -240,6 +242,11 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
virtual bool DevToolsSetDockSide(const std::string& dock_side,
bool* succeed) OVERRIDE;
virtual bool DevToolsShow(std::string* dock_side) OVERRIDE;
virtual void DevToolsSaveToFile(const std::string& url,
const std::string& content,
bool save_as) OVERRIDE;
virtual void DevToolsAppendToFile(const std::string& url,
const std::string& content) OVERRIDE;
// Whether window has standard frame.
bool has_frame_;
@@ -254,6 +261,12 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
// Dispatch unresponsive event to observers.
void NotifyWindowUnresponsive();
// Call a function in devtools.
void CallDevToolsFunction(const std::string& function_name,
const base::Value* arg1 = NULL,
const base::Value* arg2 = NULL,
const base::Value* arg3 = NULL);
// Called when CapturePage has done.
void OnCapturePageDone(const CapturePageCallback& callback,
bool succeed,
@@ -288,11 +301,22 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
base::WeakPtrFactory<NativeWindow> weak_factory_;
base::WeakPtr<NativeWindow> devtools_window_;
scoped_ptr<DevToolsDelegate> devtools_delegate_;
// WebContentsObserver for the WebContents of devtools.
scoped_ptr<DevToolsWebContentsObserver> devtools_web_contents_observer_;
scoped_ptr<AtomJavaScriptDialogManager> dialog_manager_;
// Notice that inspectable_web_contents_ must be placed after dialog_manager_,
// so we can make sure inspectable_web_contents_ is destroyed before
// dialog_manager_, otherwise a crash would happen.
scoped_ptr<brightray::InspectableWebContents> inspectable_web_contents_;
// Maps url to file path, used by the file requests sent from devtools.
typedef std::map<std::string, base::FilePath> PathsMap;
PathsMap saved_files_;
DISALLOW_COPY_AND_ASSIGN(NativeWindow);
};

View File

@@ -7,10 +7,13 @@
#include <string>
#include <vector>
#include "base/values.h"
#include "chrome/browser/ui/gtk/gtk_window_util.h"
#include "atom/common/draggable_region.h"
#include "atom/common/options_switches.h"
#include "base/environment.h"
#include "base/nix/xdg_util.h"
#include "base/values.h"
#include "chrome/browser/ui/gtk/gtk_window_util.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
#include "content/public/common/renderer_preferences.h"
@@ -31,6 +34,26 @@ namespace {
// This matches the logic in the WebKit GTK port.
const double kGtkCursorBlinkCycleFactor = 2000.0;
// Substract window border's size from window size according to current window
// manager.
void SubstractBorderSize(int* width, int* height) {
scoped_ptr<base::Environment> env(base::Environment::Create());
base::nix::DesktopEnvironment de(base::nix::GetDesktopEnvironment(env.get()));
if (de == base::nix::DESKTOP_ENVIRONMENT_UNITY) {
*width -= 2;
*height -= 29;
} else if (de == base::nix::DESKTOP_ENVIRONMENT_GNOME) {
*width -= 2;
*height -= 33;
} else if (de == base::nix::DESKTOP_ENVIRONMENT_XFCE) {
*width -= 6;
*height -= 27;
} else {
*width -= 2;
*height -= 29;
}
}
} // namespace
NativeWindowGtk::NativeWindowGtk(content::WebContents* web_contents,
@@ -42,6 +65,7 @@ NativeWindowGtk::NativeWindowGtk(content::WebContents* web_contents,
is_always_on_top_(false),
is_active_(false),
suppress_window_raise_(false),
has_ever_been_shown_(false),
frame_cursor_(NULL) {
gtk_container_add(GTK_CONTAINER(window_), vbox_);
gtk_container_add(GTK_CONTAINER(vbox_),
@@ -50,7 +74,20 @@ NativeWindowGtk::NativeWindowGtk(content::WebContents* web_contents,
int width = 800, height = 600;
options->GetInteger(switches::kWidth, &width);
options->GetInteger(switches::kHeight, &height);
gtk_window_set_default_size(window_, width, height);
// Fixup the initial window size.
if (has_frame_)
SubstractBorderSize(&width, &height);
// Force a size allocation so the web page of hidden window can have correct
// value of $(window).width().
GtkAllocation size = { 0, 0, width, height };
gtk_widget_show_all(vbox_);
gtk_widget_size_allocate(GTK_WIDGET(window_), &size);
gtk_window_util::SetWindowSize(window_, gfx::Size(width, height));
// Create the underlying gdk window.
gtk_widget_realize(GTK_WIDGET(window_));
if (!icon_.IsEmpty())
gtk_window_set_icon(window_, icon_.ToGdkPixbuf());
@@ -68,8 +105,8 @@ NativeWindowGtk::NativeWindowGtk(content::WebContents* web_contents,
G_CALLBACK(OnWindowDeleteEventThunk), this);
g_signal_connect(window_, "focus-out-event",
G_CALLBACK(OnFocusOutThunk), this);
g_signal_connect(window_, "key-press-event",
G_CALLBACK(OnKeyPressThunk), this);
g_signal_connect(window_, "window-state-event",
G_CALLBACK(OnWindowStateThunk), this);
if (!has_frame_) {
gtk_window_set_decorated(window_, false);
@@ -84,6 +121,8 @@ NativeWindowGtk::NativeWindowGtk(content::WebContents* web_contents,
}
NativeWindowGtk::~NativeWindowGtk() {
ui::ActiveWindowWatcherX::RemoveObserver(this);
if (window_)
gtk_widget_destroy(GTK_WIDGET(window_));
}
@@ -99,7 +138,7 @@ void NativeWindowGtk::CloseImmediately() {
void NativeWindowGtk::Move(const gfx::Rect& pos) {
gtk_window_move(window_, pos.x(), pos.y());
gtk_window_resize(window_, pos.width(), pos.height());
SetSize(pos.size());
}
void NativeWindowGtk::Focus(bool focus) {
@@ -121,6 +160,7 @@ bool NativeWindowGtk::IsFocused() {
}
void NativeWindowGtk::Show() {
has_ever_been_shown_ = true;
gtk_widget_show_all(GTK_WIDGET(window_));
}
@@ -160,7 +200,13 @@ bool NativeWindowGtk::IsFullscreen() {
}
void NativeWindowGtk::SetSize(const gfx::Size& size) {
gtk_window_resize(window_, size.width(), size.height());
// When the window has not been mapped the window size does not include frame.
int width = size.width();
int height = size.height();
if (has_frame_ && !has_ever_been_shown_)
SubstractBorderSize(&width, &height);
gtk_window_util::SetWindowSize(window_, gfx::Size(width, height));
}
gfx::Size NativeWindowGtk::GetSize() {
@@ -298,6 +344,18 @@ void NativeWindowGtk::UpdateDraggableRegions(
}
}
void NativeWindowGtk::HandleKeyboardEvent(
content::WebContents*,
const content::NativeWebKeyboardEvent& event) {
if (event.type == WebKit::WebInputEvent::RawKeyDown) {
GdkEventKey* os_event = reinterpret_cast<GdkEventKey*>(event.os_event);
ui::Accelerator accelerator = ui::AcceleratorForGdkKeyCodeAndModifier(
os_event->keyval, static_cast<GdkModifierType>(os_event->state));
accelerator_util::TriggerAcceleratorTableCommand(&accelerator_table_,
accelerator);
}
}
void NativeWindowGtk::ActiveWindowChanged(GdkWindow* active_window) {
is_active_ = gtk_widget_get_window(GTK_WIDGET(window_)) == active_window;
}
@@ -460,13 +518,6 @@ gboolean NativeWindowGtk::OnButtonPress(GtkWidget* widget,
return FALSE;
}
gboolean NativeWindowGtk::OnKeyPress(GtkWidget* widget, GdkEventKey* event) {
ui::Accelerator accelerator = ui::AcceleratorForGdkKeyCodeAndModifier(
event->keyval, static_cast<GdkModifierType>(event->state));
return accelerator_util::TriggerAcceleratorTableCommand(
&accelerator_table_, accelerator) ? TRUE: FALSE;
}
// static
NativeWindow* NativeWindow::Create(content::WebContents* web_contents,
base::DictionaryValue* options) {

View File

@@ -71,6 +71,11 @@ class NativeWindowGtk : public NativeWindow,
virtual void UpdateDraggableRegions(
const std::vector<DraggableRegion>& regions) OVERRIDE;
// Overridden from content::WebContentsDelegate:
virtual void HandleKeyboardEvent(
content::WebContents*,
const content::NativeWebKeyboardEvent&) OVERRIDE;
// Overridden from ActiveWindowWatcherXObserver.
virtual void ActiveWindowChanged(GdkWindow* active_window) OVERRIDE;
@@ -101,9 +106,6 @@ class NativeWindowGtk : public NativeWindow,
CHROMEGTK_CALLBACK_1(NativeWindowGtk, gboolean, OnButtonPress,
GdkEventButton*);
// Key press event callback.
CHROMEGTK_CALLBACK_1(NativeWindowGtk, gboolean, OnKeyPress, GdkEventKey*);
GtkWindow* window_;
GtkWidget* vbox_;
@@ -125,6 +127,11 @@ class NativeWindowGtk : public NativeWindow,
// bar or window border. This is to work around a compiz bug.
bool suppress_window_raise_;
// True if the window has been visible for once, on Linux the window frame
// would // only be considered as part of the window untill the window has
// been shown, so we need it to correctly set the window size.
bool has_ever_been_shown_;
// The current window cursor. We set it to a resize cursor when over the
// custom frame border. We set it to NULL if we want the default cursor.
GdkCursor* frame_cursor_;

View File

@@ -7,6 +7,7 @@
#import <Cocoa/Cocoa.h>
#include "base/mac/scoped_nsobject.h"
#include "base/memory/scoped_ptr.h"
#include "atom/browser/native_window.h"
@@ -68,7 +69,6 @@ class NativeWindowMac : public NativeWindow {
// Clip web view to rounded corner.
void ClipWebView();
NSWindow*& window() { return window_; }
SkRegion* draggable_region() const { return draggable_region_.get(); }
protected:
@@ -87,7 +87,7 @@ class NativeWindowMac : public NativeWindow {
void UpdateDraggableRegionsForCustomDrag(
const std::vector<DraggableRegion>& regions);
NSWindow* window_;
base::scoped_nsobject<NSWindow> window_;
bool is_kiosk_;

View File

@@ -7,7 +7,6 @@
#include <string>
#include "base/mac/mac_util.h"
#include "base/mac/scoped_nsobject.h"
#include "base/strings/sys_string_conversions.h"
#include "base/values.h"
#import "atom/browser/ui/cocoa/event_processing_window.h"
@@ -66,7 +65,6 @@ static const CGFloat kAtomWindowCornerRadius = 4.0;
}
- (void)windowWillClose:(NSNotification*)notification {
shell_->window() = nil;
[self autorelease];
}
@@ -171,11 +169,14 @@ NativeWindowMac::NativeWindowMac(content::WebContents* web_contents,
defer:YES];
[atomWindow setShell:this];
window_ = atomWindow;
window_.reset(atomWindow);
AtomNSWindowDelegate* delegate =
[[AtomNSWindowDelegate alloc] initWithShell:this];
[window() setDelegate:delegate];
[window_ setDelegate:delegate];
// We will manage window's lifetime ourselves.
[window_ setReleasedWhenClosed:NO];
// Enable the NSView to accept first mouse event.
bool acceptsFirstMouse = false;
@@ -186,9 +187,9 @@ NativeWindowMac::NativeWindowMac(content::WebContents* web_contents,
bool fullscreen;
if (!(options->GetBoolean(switches::kFullscreen, &fullscreen) &&
!fullscreen)) {
NSUInteger collectionBehavior = [window() collectionBehavior];
NSUInteger collectionBehavior = [window_ collectionBehavior];
collectionBehavior |= NSWindowCollectionBehaviorFullScreenPrimary;
[window() setCollectionBehavior:collectionBehavior];
[window_ setCollectionBehavior:collectionBehavior];
}
NSView* view = inspectable_web_contents()->GetView()->GetNativeView();
@@ -198,17 +199,18 @@ NativeWindowMac::NativeWindowMac(content::WebContents* web_contents,
}
NativeWindowMac::~NativeWindowMac() {
if (window())
[window() release];
// Force InspectableWebContents to be destroyed before we destroy window,
// because it may still be observing the window at this time.
DestroyWebContents();
}
void NativeWindowMac::Close() {
[window() performClose:nil];
[window_ performClose:nil];
}
void NativeWindowMac::CloseImmediately() {
[window() orderOut:nil];
[window() close];
[window_ orderOut:nil];
[window_ close];
}
void NativeWindowMac::Move(const gfx::Rect& pos) {
@@ -220,7 +222,7 @@ void NativeWindowMac::Move(const gfx::Rect& pos) {
cocoa_bounds.origin.y =
NSHeight([screen frame]) - pos.height() - pos.y();
[window() setFrame:cocoa_bounds display:YES];
[window_ setFrame:cocoa_bounds display:YES];
}
void NativeWindowMac::Focus(bool focus) {
@@ -229,42 +231,42 @@ void NativeWindowMac::Focus(bool focus) {
if (focus) {
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
[window() makeKeyAndOrderFront:nil];
[window_ makeKeyAndOrderFront:nil];
} else {
[window() orderBack:nil];
[window_ orderBack:nil];
}
}
bool NativeWindowMac::IsFocused() {
return [window() isKeyWindow];
return [window_ isKeyWindow];
}
void NativeWindowMac::Show() {
[window() makeKeyAndOrderFront:nil];
[window_ makeKeyAndOrderFront:nil];
}
void NativeWindowMac::Hide() {
[window() orderOut:nil];
[window_ orderOut:nil];
}
bool NativeWindowMac::IsVisible() {
return [window() isVisible];
return [window_ isVisible];
}
void NativeWindowMac::Maximize() {
[window() zoom:nil];
[window_ zoom:nil];
}
void NativeWindowMac::Unmaximize() {
[window() zoom:nil];
[window_ zoom:nil];
}
void NativeWindowMac::Minimize() {
[window() miniaturize:nil];
[window_ miniaturize:nil];
}
void NativeWindowMac::Restore() {
[window() deminiaturize:nil];
[window_ deminiaturize:nil];
}
void NativeWindowMac::SetFullscreen(bool fullscreen) {
@@ -276,11 +278,11 @@ void NativeWindowMac::SetFullscreen(bool fullscreen) {
return;
}
[window() toggleFullScreen:nil];
[window_ toggleFullScreen:nil];
}
bool NativeWindowMac::IsFullscreen() {
return [window() styleMask] & NSFullScreenWindowMask;
return [window_ styleMask] & NSFullScreenWindowMask;
}
void NativeWindowMac::SetSize(const gfx::Size& size) {
@@ -289,7 +291,7 @@ void NativeWindowMac::SetSize(const gfx::Size& size) {
frame.size.width = size.width();
frame.size.height = size.height();
[window() setFrame:frame display:YES];
[window_ setFrame:frame display:YES];
}
gfx::Size NativeWindowMac::GetSize() {
@@ -299,54 +301,54 @@ gfx::Size NativeWindowMac::GetSize() {
void NativeWindowMac::SetMinimumSize(const gfx::Size& size) {
NSSize min_size = NSMakeSize(size.width(), size.height());
NSView* content = [window() contentView];
[window() setContentMinSize:[content convertSize:min_size toView:nil]];
NSView* content = [window_ contentView];
[window_ setContentMinSize:[content convertSize:min_size toView:nil]];
}
gfx::Size NativeWindowMac::GetMinimumSize() {
NSView* content = [window() contentView];
NSSize min_size = [content convertSize:[window() contentMinSize]
NSView* content = [window_ contentView];
NSSize min_size = [content convertSize:[window_ contentMinSize]
fromView:nil];
return gfx::Size(min_size.width, min_size.height);
}
void NativeWindowMac::SetMaximumSize(const gfx::Size& size) {
NSSize max_size = NSMakeSize(size.width(), size.height());
NSView* content = [window() contentView];
[window() setContentMaxSize:[content convertSize:max_size toView:nil]];
NSView* content = [window_ contentView];
[window_ setContentMaxSize:[content convertSize:max_size toView:nil]];
}
gfx::Size NativeWindowMac::GetMaximumSize() {
NSView* content = [window() contentView];
NSSize max_size = [content convertSize:[window() contentMaxSize]
NSView* content = [window_ contentView];
NSSize max_size = [content convertSize:[window_ contentMaxSize]
fromView:nil];
return gfx::Size(max_size.width, max_size.height);
}
void NativeWindowMac::SetResizable(bool resizable) {
if (resizable) {
[[window() standardWindowButton:NSWindowZoomButton] setEnabled:YES];
[window() setStyleMask:window().styleMask | NSResizableWindowMask];
[[window_ standardWindowButton:NSWindowZoomButton] setEnabled:YES];
[window_ setStyleMask:[window_ styleMask] | NSResizableWindowMask];
} else {
[[window() standardWindowButton:NSWindowZoomButton] setEnabled:NO];
[window() setStyleMask:window().styleMask ^ NSResizableWindowMask];
[[window_ standardWindowButton:NSWindowZoomButton] setEnabled:NO];
[window_ setStyleMask:[window_ styleMask] ^ NSResizableWindowMask];
}
}
bool NativeWindowMac::IsResizable() {
return [window() styleMask] & NSResizableWindowMask;
return [window_ styleMask] & NSResizableWindowMask;
}
void NativeWindowMac::SetAlwaysOnTop(bool top) {
[window() setLevel:(top ? NSFloatingWindowLevel : NSNormalWindowLevel)];
[window_ setLevel:(top ? NSFloatingWindowLevel : NSNormalWindowLevel)];
}
bool NativeWindowMac::IsAlwaysOnTop() {
return [window() level] == NSFloatingWindowLevel;
return [window_ level] == NSFloatingWindowLevel;
}
void NativeWindowMac::Center() {
[window() center];
[window_ center];
}
void NativeWindowMac::SetPosition(const gfx::Point& position) {
@@ -362,11 +364,11 @@ gfx::Point NativeWindowMac::GetPosition() {
}
void NativeWindowMac::SetTitle(const std::string& title) {
[window() setTitle:base::SysUTF8ToNSString(title)];
[window_ setTitle:base::SysUTF8ToNSString(title)];
}
std::string NativeWindowMac::GetTitle() {
return base::SysNSStringToUTF8([window() title]);
return base::SysNSStringToUTF8([window_ title]);
}
void NativeWindowMac::FlashFrame(bool flash) {
@@ -403,11 +405,11 @@ bool NativeWindowMac::IsKiosk() {
}
bool NativeWindowMac::HasModalDialog() {
return [window() attachedSheet] != nil;
return [window_ attachedSheet] != nil;
}
gfx::NativeWindow NativeWindowMac::GetNativeWindow() {
return window();
return window_;
}
bool NativeWindowMac::IsWithinDraggableRegion(NSPoint point) const {
@@ -423,15 +425,15 @@ bool NativeWindowMac::IsWithinDraggableRegion(NSPoint point) const {
void NativeWindowMac::HandleMouseEvent(NSEvent* event) {
NSPoint current_mouse_location =
[window() convertBaseToScreen:[event locationInWindow]];
[window_ convertBaseToScreen:[event locationInWindow]];
if ([event type] == NSLeftMouseDown) {
NSPoint frame_origin = [window() frame].origin;
NSPoint frame_origin = [window_ frame].origin;
last_mouse_offset_ = NSMakePoint(
frame_origin.x - current_mouse_location.x,
frame_origin.y - current_mouse_location.y);
} else if ([event type] == NSLeftMouseDragged) {
[window() setFrameOrigin:NSMakePoint(
[window_ setFrameOrigin:NSMakePoint(
current_mouse_location.x + last_mouse_offset_.x,
current_mouse_location.y + last_mouse_offset_.y)];
}
@@ -455,7 +457,7 @@ void NativeWindowMac::HandleKeyboardEvent(
return;
EventProcessingWindow* event_window =
static_cast<EventProcessingWindow*>(window());
static_cast<EventProcessingWindow*>(window_);
DCHECK([event_window isKindOfClass:[EventProcessingWindow class]]);
[event_window redispatchKeyEvent:event.os_event];
}
@@ -463,19 +465,19 @@ void NativeWindowMac::HandleKeyboardEvent(
void NativeWindowMac::InstallView() {
NSView* view = inspectable_web_contents()->GetView()->GetNativeView();
if (has_frame_) {
[view setFrame:[[window() contentView] bounds]];
[[window() contentView] addSubview:view];
[view setFrame:[[window_ contentView] bounds]];
[[window_ contentView] addSubview:view];
} else {
NSView* frameView = [[window() contentView] superview];
NSView* frameView = [[window_ contentView] superview];
[view setFrame:[frameView bounds]];
[frameView addSubview:view];
ClipWebView();
[[window() standardWindowButton:NSWindowZoomButton] setHidden:YES];
[[window() standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES];
[[window() standardWindowButton:NSWindowCloseButton] setHidden:YES];
[[window() standardWindowButton:NSWindowFullScreenButton] setHidden:YES];
[[window_ standardWindowButton:NSWindowZoomButton] setHidden:YES];
[[window_ standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES];
[[window_ standardWindowButton:NSWindowCloseButton] setHidden:YES];
[[window_ standardWindowButton:NSWindowFullScreenButton] setHidden:YES];
}
}

View File

@@ -11,7 +11,7 @@
<key>CFBundleIconFile</key>
<string>atom.icns</string>
<key>CFBundleVersion</key>
<string>0.11.4</string>
<string>0.11.10</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>

View File

@@ -50,8 +50,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,11,4,0
PRODUCTVERSION 0,11,4,0
FILEVERSION 0,11,10,0
PRODUCTVERSION 0,11,10,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -68,12 +68,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "GitHub, Inc."
VALUE "FileDescription", "Atom-Shell"
VALUE "FileVersion", "0.11.4"
VALUE "FileVersion", "0.11.10"
VALUE "InternalName", "atom.exe"
VALUE "LegalCopyright", "Copyright (C) 2013 GitHub, Inc. All rights reserved."
VALUE "OriginalFilename", "atom.exe"
VALUE "ProductName", "Atom-Shell"
VALUE "ProductVersion", "0.11.4"
VALUE "ProductVersion", "0.11.10"
END
END
BLOCK "VarFileInfo"

View File

@@ -11,6 +11,8 @@
#if defined(TOOLKIT_GTK)
#include "base/command_line.h"
#include "base/environment.h"
#include "base/nix/xdg_util.h"
#include "ui/gfx/gtk_util.h"
#endif
@@ -25,7 +27,23 @@ namespace api {
namespace {
v8::Handle<v8::Object> DisplayToV8Value(const gfx::Display& display) {
gfx::Display AdaptToWindowManager(const gfx::Display& display) {
gfx::Display changed(display);
#if defined(TOOLKIT_GTK)
scoped_ptr<base::Environment> env(base::Environment::Create());
base::nix::DesktopEnvironment de(base::nix::GetDesktopEnvironment(env.get()));
if (de == base::nix::DESKTOP_ENVIRONMENT_UNITY) {
// Unity's 24px global menu bar should not be included in the work area.
gfx::Rect rect(changed.work_area());
rect.set_height(rect.height() - 24);
changed.set_work_area(rect);
}
#endif
return changed;
}
v8::Handle<v8::Object> DisplayToV8Value(const gfx::Display& raw) {
gfx::Display display(AdaptToWindowManager(raw));
v8::Handle<v8::Object> obj = v8::Object::New();
obj->Set(ToV8Value("bounds"), ToV8Value(display.bounds()));
obj->Set(ToV8Value("workArea"), ToV8Value(display.work_area()));

View File

@@ -1 +1,6 @@
module.exports = process.atomBinding 'clipboard'
module.exports =
if process.platform is 'linux'
# On Linux we could not access clipboard in renderer process.
require('remote').process.atomBinding 'clipboard'
else
process.atomBinding 'clipboard'

View File

@@ -7,7 +7,7 @@
#define ATOM_MAJOR_VERSION 0
#define ATOM_MINOR_VERSION 11
#define ATOM_PATCH_VERSION 4
#define ATOM_PATCH_VERSION 10
#define ATOM_VERSION_IS_RELEASE 1

View File

@@ -28,9 +28,6 @@ const char* kSecurityManualEnableIframe = "manual-enable-iframe";
const char* kSecurityDisable = "disable";
const char* kSecurityEnableNodeIntegration = "enable-node-integration";
// Scheme used by devtools
const char* kChromeDevToolsScheme = "chrome-devtools";
} // namespace
AtomRendererClient::AtomRendererClient()
@@ -159,10 +156,6 @@ bool AtomRendererClient::ShouldFork(WebKit::WebFrame* frame,
bool AtomRendererClient::IsNodeBindingEnabled(WebKit::WebFrame* frame) {
if (node_integration_ == DISABLE)
return false;
// Do not pollute devtools.
else if (frame != NULL &&
GURL(frame->document().url()).SchemeIs(kChromeDevToolsScheme))
return false;
// Node integration is enabled in main frame unless explictly disabled.
else if (frame == main_frame_)
return true;

View File

@@ -1,4 +1,5 @@
path = require 'path'
url = require 'url'
Module = require 'module'
# Expose information of current process.
@@ -42,5 +43,9 @@ else
global.__filename = __filename
global.__dirname = __dirname
# Override default web functions.
require path.join(__dirname, 'override')
if location.protocol is 'chrome-devtools:'
# Override some inspector APIs.
require path.join(__dirname, 'inspector')
else
# Override default web functions.
require path.join(__dirname, 'override')

View File

@@ -0,0 +1,61 @@
window.onload = ->
# Use menu API to show context menu.
WebInspector.ContextMenu.prototype.show = ->
menuObject = @_buildDescriptor()
if menuObject.length
WebInspector._contextMenu = this
createMenu(menuObject, @_event)
@_event.consume()
# Use dialog API to override file chooser dialog.
WebInspector.createFileSelectorElement = (callback) ->
fileSelectorElement = document.createElement 'span'
fileSelectorElement.style.display = 'none'
fileSelectorElement.click = showFileChooserDialog.bind this, callback
return fileSelectorElement
convertToMenuTemplate = (items) ->
template = []
for item in items
do (item) ->
transformed =
if item.type is 'subMenu'
type: 'submenu'
label: item.label
enabled: item.enabled
submenu: convertToMenuTemplate item.subItems
else if item.type is 'separator'
type: 'separator'
else if item.type is 'checkbox'
type: 'checkbox'
label: item.label
enabled: item.enabled
checked: item.checked
else
type: 'normal'
label: item.label
enabled: item.enabled
if item.id?
transformed.click = -> WebInspector.contextMenuItemSelected item.id
template.push transformed
template
createMenu = (items, event) ->
remote = require 'remote'
Menu = remote.require 'menu'
menu = Menu.buildFromTemplate convertToMenuTemplate(items)
menu.popup remote.getCurrentWindow()
event.consume true
showFileChooserDialog = (callback) ->
remote = require 'remote'
dialog = remote.require 'dialog'
dialog.showOpenDialog remote.getCurrentWindow(), null, (files) ->
callback pathToHtml5FileObject(files[0]) if files?
pathToHtml5FileObject = (path) ->
fs = require 'fs'
blob = new Blob([fs.readFileSync(path)])
blob.name = path
blob

View File

@@ -113,6 +113,7 @@
'conditions': [
['OS=="mac"', {
'xcode_settings': {
'GCC_TREAT_WARNINGS_AS_ERRORS': 'NO',
'WARNING_CFLAGS': [
'-Wno-deprecated-declarations',
'-Wno-unused-private-field',

View File

@@ -334,6 +334,13 @@ Closes the developer tools.
Starts inspecting element at position (`x`, `y`).
### BrowserWindow.executeJavaScriptInDevTools(code)
* `code` String
Evaluate `code` in devtools to use
[InspectorFrontendAPI](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/devtools/front_end/InspectorFrontendAPI.js&q=InspectorFrontendAPI&sq=package:chromium&type=cs)
### BrowserWindow.focusOnWebView()
### BrowserWindow.blurWebView()

View File

@@ -1,6 +1,6 @@
{
"name": "atom-shell",
"version": "0.11.4",
"version": "0.11.10",
"devDependencies": {
"coffee-script": "~1.6.3",

View File

@@ -6,7 +6,7 @@ import subprocess
import sys
from lib.config import LIBCHROMIUMCONTENT_COMMIT, BASE_URL
from lib.util import scoped_cwd
from lib.util import execute, scoped_cwd
SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
@@ -41,25 +41,27 @@ def parse_args():
def update_submodules():
subprocess.check_call(['git', 'submodule', 'sync', '--quiet'])
subprocess.check_call(['git', 'submodule', 'update', '--init',
'--recursive'])
execute(['git', 'submodule', 'sync'])
execute(['git', 'submodule', 'update', '--init', '--recursive'])
def bootstrap_brightray(url):
bootstrap = os.path.join(VENDOR_DIR, 'brightray', 'script', 'bootstrap')
subprocess.check_call([sys.executable, bootstrap, '--commit',
LIBCHROMIUMCONTENT_COMMIT, url])
execute([sys.executable, bootstrap, '--commit', LIBCHROMIUMCONTENT_COMMIT,
url])
def update_apm():
## NB: Without this, subprocess incorrectly searches for npm.exe
npm_cmd = 'npm'
if sys.platform in ['win32', 'cygwin']:
npm_cmd += '.cmd'
npm = 'npm.cmd' if sys.platform == 'win32' else 'npm'
if os.environ.get('CI') == '1':
execute([npm, 'install', 'npm'])
npm = os.path.join(SOURCE_ROOT, 'node_modules', '.bin', 'npm')
if sys.platform == 'win32':
npm += '.cmd'
with scoped_cwd(os.path.join('vendor', 'apm')):
subprocess.check_call([npm_cmd, 'install', '.'])
execute([npm, 'install', '.'])
def update_node_modules():
@@ -70,16 +72,15 @@ def update_node_modules():
def update_node_modules_for_dir(dirname):
with scoped_cwd(dirname):
apm = os.path.join(SOURCE_ROOT, 'vendor', 'apm', 'bin', 'apm')
subprocess.check_call(['node', os.path.relpath(apm), 'install'])
if sys.platform in ['win32', 'cygwin']:
apm += '.cmd'
subprocess.check_call([apm, 'install'])
def update_win32_python():
with scoped_cwd(VENDOR_DIR):
if not os.path.exists('python_26'):
subprocess.check_call(['git', 'clone', PYTHON_26_URL])
else:
with scoped_cwd('python_26'):
subprocess.check_call(['git', 'pull', '--rebase', 'origin', 'master'])
execute(['git', 'clone', PYTHON_26_URL])
def touch_config_gypi():
@@ -92,7 +93,7 @@ def touch_config_gypi():
def update_atom_shell():
update = os.path.join(SOURCE_ROOT, 'script', 'update.py')
subprocess.check_call([sys.executable, update])
execute([sys.executable, update])
if __name__ == '__main__':

View File

@@ -2,10 +2,9 @@
import os
import re
import subprocess
import sys
from lib.util import get_atom_shell_version, scoped_cwd
from lib.util import execute, get_atom_shell_version, scoped_cwd
SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
@@ -126,13 +125,13 @@ def update_info_plist(version):
def tag_version(version):
subprocess.check_call(['git', 'commit', '-a', '-m',
'Bump v{0}.'.format(version)])
subprocess.check_call(['git', 'tag', 'v{0}'.format(version)])
execute(['git', 'commit', '-a', '-m', 'Bump v{0}.'.format(version)])
execute(['git', 'tag', 'v{0}'.format(version)])
def git_push():
subprocess.check_call(['git', 'push', '--follow-tags'])
execute(['git', 'push'])
execute(['git', 'push', '--tags'])
if __name__ == '__main__':

View File

@@ -27,7 +27,6 @@ def main():
run_script('coffeelint.py')
run_script('build.py')
run_script('test.py', ['--ci'])
run_script('create-dist.py')
def run_script(script, args=[]):

View File

@@ -38,7 +38,7 @@ process.on('uncaughtException', function(error) {
});
app.on('window-all-closed', function() {
app.terminate();
app.quit();
});
app.on('ready', function() {

2
vendor/apm vendored

Submodule vendor/apm updated: 90cd546860...2ce1206e67