Skip to content

Commit edf90c9

Browse files
committed
[API][Mac] gui.Window can catch the 'close' event.
1 parent c9f77ea commit edf90c9

9 files changed

Lines changed: 73 additions & 29 deletions

File tree

src/api/window/window.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ Window::Window(int id,
3232
: Base(id, dispatcher_host, option),
3333
shell_(content::Shell::FromRenderViewHost(dispatcher_host->
3434
render_view_host())) {
35+
// Set ID for Shell
36+
shell_->set_id(id);
3537
}
3638

3739
Window::~Window() {
@@ -41,6 +43,10 @@ void Window::Call(const std::string& method,
4143
const base::ListValue& arguments) {
4244
if (method == "Show") {
4345
shell_->Show();
46+
} else if (method == "Close") {
47+
bool force = false;
48+
arguments.GetBoolean(0, &force);
49+
shell_->Close(force);
4450
} else if (method == "Hide") {
4551
shell_->Hide();
4652
} else if (method == "Maximize") {

src/api/window/window.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,8 @@ Window.prototype.hide = function() {
9393
nw.callObjectMethod(this, 'Hide', []);
9494
}
9595

96-
Window.prototype.close = function() {
97-
window.close();
96+
Window.prototype.close = function(force) {
97+
nw.callObjectMethod(this, 'Close', [ Boolean(force) ]);
9898
}
9999

100100
Window.prototype.maximize = function() {
@@ -113,6 +113,17 @@ Window.prototype.restore = function() {
113113
nw.callObjectMethod(this, 'Restore', []);
114114
}
115115

116+
Window.prototype.handleEvent = function(ev) {
117+
// If no one is listening to 'close' then close directly
118+
if (ev == 'close' && this.listeners(ev).length == 0) {
119+
this.close(true);
120+
return;
121+
}
122+
123+
// Emit generate event handler
124+
exports.Base.prototype.handleEvent.apply(this, arguments);
125+
}
126+
116127
exports.Window = {
117128
get: function() {
118129
if (nwDispatcher.windowInstance == null) {

src/shell.cc

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "content/public/browser/notification_types.h"
3737
#include "content/public/browser/render_view_host.h"
3838
#include "content/public/browser/web_contents.h"
39+
#include "content/nw/src/api/api_messages.h"
3940
#include "content/nw/src/browser/file_select_helper.h"
4041
#include "content/nw/src/browser/shell_devtools_delegate.h"
4142
#include "content/nw/src/browser/shell_javascript_dialog_creator.h"
@@ -55,6 +56,8 @@ bool Shell::quit_message_loop_ = true;
5556
Shell::Shell(WebContents* web_contents, base::DictionaryValue* manifest)
5657
: window_(NULL),
5758
url_edit_view_(NULL),
59+
force_close_(false),
60+
id_(-1),
5861
window_manifest_(manifest),
5962
is_show_devtools_(false),
6063
is_toolbar_open_(true),
@@ -94,6 +97,12 @@ Shell::~Shell() {
9497
MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure());
9598
}
9699

100+
void Shell::SendEvent(const std::string& event) {
101+
base::ListValue args;
102+
web_contents()->GetRenderViewHost()->Send(new ShellViewMsg_Object_On_Event(
103+
web_contents()->GetRoutingID(), id(), event, args));
104+
}
105+
97106
Shell* Shell::CreateShell(WebContents* web_contents,
98107
base::DictionaryValue* manifest) {
99108
int width = 700;
@@ -106,10 +115,9 @@ Shell* Shell::CreateShell(WebContents* web_contents,
106115

107116
shell->web_contents_.reset(web_contents);
108117
web_contents->SetDelegate(shell);
109-
110118
shell->PlatformSetContents();
111-
112119
shell->PlatformResizeSubViews();
120+
113121
return shell;
114122
}
115123

@@ -211,6 +219,7 @@ void Shell::ShowDevTools() {
211219
WebContents::Create(web_contents()->GetBrowserContext(),
212220
NULL, MSG_ROUTING_NONE, NULL),
213221
&manifest);
222+
shell->force_close_ = true;
214223
shell->LoadURL(url);
215224
}
216225

src/shell.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class Shell : public WebContentsDelegate,
6464
void Reload();
6565
void Stop();
6666
void UpdateNavigationControls();
67-
void Close();
67+
void Close(bool force = false);
6868
void Move(const gfx::Rect& pos);
6969
void ShowDevTools();
7070
void Focus(bool focus);
@@ -75,6 +75,9 @@ class Shell : public WebContentsDelegate,
7575
void Minimize();
7676
void Restore();
7777

78+
// Send an event to renderer.
79+
void SendEvent(const std::string& event);
80+
7881
// Do one time initialization at application startup.
7982
static void PlatformInitialize();
8083

@@ -99,6 +102,10 @@ class Shell : public WebContentsDelegate,
99102
WebContents* web_contents() const { return web_contents_.get(); }
100103
gfx::NativeWindow window() { return window_; }
101104

105+
bool force_close() { return force_close_; }
106+
void set_id(int id) { id_ = id; }
107+
int id() const { return id_; }
108+
102109
#if defined(OS_MACOSX)
103110
// Public to be called by an ObjC bridge object.
104111
void ActionPerformed(int control);
@@ -220,6 +227,12 @@ class Shell : public WebContentsDelegate,
220227
// Notification manager
221228
NotificationRegistrar registrar_;
222229

230+
// Flag to indicate we will force closing
231+
bool force_close_ = false;
232+
233+
// ID of corresponding js object.
234+
int id_;
235+
223236
// Window manifest
224237
base::DictionaryValue* window_manifest_;
225238
bool is_show_devtools_;

src/shell_gtk.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ GtkWidget* CreateMenuBar(Shell* shell) {
7474

7575
} // namespace
7676

77-
void Shell::Close() {
77+
void Shell::Close(bool force) {
7878
gtk_widget_destroy(GTK_WIDGET(window_));
7979
}
8080

src/shell_mac.mm

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,11 @@ - (id)initWithShell:(content::Shell*)shell {
7373
// before we go deleting objects. By returning YES, we allow the window to be
7474
// removed from the screen.
7575
- (BOOL)windowShouldClose:(id)window {
76+
if (shell_->id() > 0 && !shell_->force_close()) {
77+
shell_->SendEvent("close");
78+
return NO;
79+
}
80+
7681
[window autorelease];
7782

7883
// Clean ourselves up and do the work after clearing the stack of anything
@@ -152,7 +157,9 @@ void MakeShellButton(NSRect* rect,
152157

153158
namespace content {
154159

155-
void Shell::Close() {
160+
void Shell::Close(bool force) {
161+
if (!force_close_)
162+
force_close_ = force;
156163
[window_ performClose:nil];
157164
}
158165

src/shell_win.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ namespace content {
5050

5151
HINSTANCE Shell::instance_handle_;
5252

53-
void Shell::Close() {
53+
void Shell::Close(bool force) {
5454
DestroyWindow(window_);
5555
}
5656

tests/window/index.html

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@
55
<script>
66
var gui = require('nw.gui');
77
var win = gui.Window.from(
8-
window.open('popup.html', '_blank', 'screenX=100,screenY=100,width=400,height=300')
8+
window.open('popup.html', '_blank', 'screenX=100,screenY=100,width=200,height=300')
99
);
1010
</script>
11-
<br/>
1211
<button onclick="win.focus()">Focus</button>
1312
<br/>
1413
<button onclick="win.blur()">Blur</button>
@@ -24,5 +23,9 @@
2423
<button onclick="win.minimize()">Minimize</button>
2524
<br/>
2625
<button onclick="win.restore()">Restore</button>
26+
<br/>
27+
<button onclick="win.close()">Close</button>
28+
<br/>
29+
<button onclick="win.close(true)">Force Close</button>
2730
</body>
2831
</html>

tests/window/popup.html

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,21 @@
11
<html>
22
<head>
33
<meta http-equiv="content-type" content="text/html; charset=utf-8">
4-
<title>新窗口</title>
4+
<title>New Window</title>
55
</head>
66
<body>
7-
This is the popup window<br/>
8-
<script>
9-
document.write('node ' + process.version);
10-
document.write('<br/>window.opener.testwindow == ' + window.opener.testwindow);
11-
document.write('<br/>global.testglobal == ' + global.testglobal);
12-
// window.Test = "Popup window value";
13-
// setTimeout(function() {
14-
// window.moveTo(0, 0);
15-
// setInterval(function() {
16-
// window.moveBy(10, 10);
17-
// window.resizeBy(10, 10);
18-
// }, 1000);
19-
// }, 1000);
20-
</script>
21-
<br/>
22-
<button onclick="window.blur()">Blur Me</button>
23-
<br/>
24-
<button onclick="window.opener.focus()">Focus Parent</button>
7+
This is the popup window<br/>
8+
<script>
9+
var enable = false;
10+
var gui = require('nw.gui');
11+
var win = gui.Window.get();
12+
win.on('close', function() {
13+
if (enable)
14+
this.close(true);
15+
else
16+
console.log('This window can not be closed.');
17+
});
18+
</script>
19+
<button onclick="javascript:enable = true;">Enable to be closed</button>
2520
</body>
2621
</html>

0 commit comments

Comments
 (0)