Line
Link Here
|
0 |
-- brackets-shell/appshell/cefclient_gtk.cpp |
0 |
++ brackets-shell/appshell/cefclient_gtk.cpp |
Lines 1-6
Link Here
|
1 |
// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights |
1 |
// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights |
2 |
// reserved. Use of this source code is governed by a BSD-style license that |
2 |
// reserved. Use of this source code is governed by a BSD-style license that |
3 |
// can be found in the LICENSE file. |
3 |
// can be found in the LICENSE file. |
|
|
4 |
|
5 |
#include <gdk/gdkx.h> |
4 |
|
6 |
|
5 |
#include "cefclient.h" |
7 |
#include "cefclient.h" |
6 |
#include <gtk/gtk.h> |
8 |
#include <gtk/gtk.h> |
Lines 18-64
Link Here
|
18 |
#include "client_switches.h" |
20 |
#include "client_switches.h" |
19 |
#include "appshell_node_process.h" |
21 |
#include "appshell_node_process.h" |
20 |
|
22 |
|
21 |
static std::string APPICONS[] = {"appshell32.png","appshell48.png","appshell128.png","appshell256.png"}; |
23 |
static std::string APPICONS[] = {"appshell32.png", "appshell48.png", "appshell128.png", "appshell256.png"}; |
22 |
char szWorkingDir[512]; // The current working directory |
24 |
char szWorkingDir[512]; // The current working directory |
23 |
std::string szInitialUrl; |
25 |
std::string szInitialUrl; |
24 |
std::string szRunningDir; |
26 |
std::string szRunningDir; |
25 |
int add_handler_id; |
27 |
int add_handler_id; |
26 |
bool isReallyClosing = false; |
28 |
bool isReallyClosing = false; |
27 |
|
29 |
|
|
|
30 |
static gint DEFAULT_SIZE_HEIGHT = 600; |
31 |
static gint DEFAULT_SIZE_WIDTH = 800; |
32 |
|
28 |
// The global ClientHandler reference. |
33 |
// The global ClientHandler reference. |
29 |
extern CefRefPtr<ClientHandler> g_handler; |
34 |
extern CefRefPtr<ClientHandler> g_handler; |
30 |
|
35 |
|
31 |
// Application startup time |
36 |
// Application startup time |
32 |
time_t g_appStartupTime; |
37 |
time_t g_appStartupTime; |
33 |
|
38 |
|
|
|
39 |
// Error handler for X11 |
40 |
|
41 |
int XErrorHandlerImpl(Display *display, XErrorEvent *event) { |
42 |
LOG(WARNING) |
43 |
<< "X error received: " |
44 |
<< "type " << event->type << ", " |
45 |
<< "serial " << event->serial << ", " |
46 |
<< "error_code " << static_cast<int> (event->error_code) << ", " |
47 |
<< "request_code " << static_cast<int> (event->request_code) << ", " |
48 |
<< "minor_code " << static_cast<int> (event->minor_code); |
49 |
return 0; |
50 |
} |
51 |
|
52 |
int XIOErrorHandlerImpl(Display *display) { |
53 |
return 0; |
54 |
} |
55 |
|
34 |
void destroy(void) { |
56 |
void destroy(void) { |
35 |
CefQuitMessageLoop(); |
57 |
if (isReallyClosing) { |
36 |
} |
58 |
CefQuitMessageLoop(); |
37 |
|
59 |
} |
38 |
void TerminationSignalHandler(int signatl) { |
60 |
} |
|
|
61 |
|
62 |
void TerminationSignalHandler(int signal) { |
63 |
isReallyClosing = true; |
39 |
destroy(); |
64 |
destroy(); |
40 |
} |
65 |
} |
41 |
void HandleAdd(GtkContainer *container, |
66 |
|
42 |
GtkWidget *widget, |
67 |
//void HandleAdd(GtkContainer *container, |
43 |
gpointer user_data) { |
68 |
// GtkWidget *widget, |
44 |
g_signal_handler_disconnect(container, add_handler_id); |
69 |
// gpointer user_data) { |
45 |
if(gtk_widget_get_can_focus(widget)) { |
70 |
// g_signal_handler_disconnect(container, add_handler_id); |
46 |
gtk_widget_grab_focus(widget); |
71 |
// if (gtk_widget_get_can_focus(widget)) { |
47 |
} |
72 |
// gtk_widget_grab_focus(widget); |
48 |
else { |
73 |
// } else { |
49 |
add_handler_id = g_signal_connect(G_OBJECT(widget), "add", |
74 |
// add_handler_id = g_signal_connect(G_OBJECT(widget), "add", |
50 |
G_CALLBACK(HandleAdd), NULL); |
75 |
// G_CALLBACK(HandleAdd), NULL); |
51 |
} |
76 |
// } |
52 |
} |
77 |
//} |
53 |
|
78 |
|
54 |
static gboolean HandleQuit(int signatl) { |
79 |
// TODO: this is not yet called to shutdown Brackets |
55 |
if (!isReallyClosing && g_handler.get() && g_handler->GetBrowserId()) { |
80 |
gboolean HandleQuit() { |
56 |
CefRefPtr<CommandCallback> callback = new CloseWindowCommandCallback(g_handler->GetBrowser()); |
81 |
|
|
|
82 |
if (!isReallyClosing && g_handler.get()) { |
83 |
g_handler->DispatchCloseToNextBrowser(); |
84 |
} |
85 |
else |
86 |
{ |
87 |
if(!g_handler.get() || !g_handler->HasWindows()) { |
88 |
CefQuitMessageLoop(); |
89 |
return FALSE; |
90 |
} |
91 |
} |
92 |
|
93 |
return TRUE; |
57 |
|
94 |
|
58 |
g_handler->SendJSCommand(g_handler->GetBrowser(), FILE_CLOSE_WINDOW, callback); |
|
|
59 |
return TRUE; |
60 |
} |
61 |
destroy(); |
62 |
} |
95 |
} |
63 |
|
96 |
|
64 |
bool FileExists(std::string path) { |
97 |
bool FileExists(std::string path) { |
Lines 68-89
Link Here
|
68 |
|
101 |
|
69 |
int GetInitialUrl() { |
102 |
int GetInitialUrl() { |
70 |
GtkWidget *dialog; |
103 |
GtkWidget *dialog; |
71 |
const char* dialog_title = "Please select the index.html file"; |
104 |
const char* dialog_title = "Please select the index.html file"; |
72 |
GtkFileChooserAction file_or_directory = GTK_FILE_CHOOSER_ACTION_OPEN ; |
105 |
GtkFileChooserAction file_or_directory = GTK_FILE_CHOOSER_ACTION_OPEN; |
73 |
dialog = gtk_file_chooser_dialog_new (dialog_title, |
106 |
dialog = gtk_file_chooser_dialog_new(dialog_title, |
74 |
NULL, |
107 |
NULL, |
75 |
file_or_directory, |
108 |
file_or_directory, |
76 |
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |
109 |
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |
77 |
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, |
110 |
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, |
78 |
NULL); |
111 |
NULL); |
79 |
|
112 |
|
80 |
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) |
113 |
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { |
81 |
{ |
114 |
szInitialUrl = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); |
82 |
szInitialUrl = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); |
115 |
gtk_widget_destroy(dialog); |
83 |
gtk_widget_destroy (dialog); |
116 |
return 0; |
84 |
return 0; |
117 |
} |
85 |
} |
118 |
return -1; |
86 |
return -1; |
|
|
87 |
} |
119 |
} |
88 |
|
120 |
|
89 |
// Global functions |
121 |
// Global functions |
Lines 93-109
Link Here
|
93 |
} |
125 |
} |
94 |
|
126 |
|
95 |
std::string AppGetRunningDirectory() { |
127 |
std::string AppGetRunningDirectory() { |
96 |
if(szRunningDir.length() > 0) |
128 |
if (szRunningDir.length() > 0) |
97 |
return szRunningDir; |
129 |
return szRunningDir; |
98 |
|
130 |
|
99 |
char buf[512]; |
131 |
char buf[512]; |
100 |
int len = readlink("/proc/self/exe", buf, 512); |
132 |
int len = readlink("/proc/self/exe", buf, 512); |
101 |
|
133 |
|
102 |
if(len < 0) |
134 |
if (len < 0) |
103 |
return AppGetWorkingDirectory(); //# Well, can't think of any real-world case where this would be happen |
135 |
return AppGetWorkingDirectory(); //# Well, can't think of any real-world case where this would be happen |
104 |
|
136 |
|
105 |
for(; len >= 0; len--){ |
137 |
for (; len >= 0; len--) { |
106 |
if(buf[len] == '/'){ |
138 |
if (buf[len] == '/') { |
107 |
buf[len] = '\0'; |
139 |
buf[len] = '\0'; |
108 |
szRunningDir.append(buf); |
140 |
szRunningDir.append(buf); |
109 |
return szRunningDir; |
141 |
return szRunningDir; |
Lines 118-124
Link Here
|
118 |
} |
150 |
} |
119 |
|
151 |
|
120 |
GtkWidget* AddMenuEntry(GtkWidget* menu_widget, const char* text, |
152 |
GtkWidget* AddMenuEntry(GtkWidget* menu_widget, const char* text, |
121 |
GCallback callback) { |
153 |
GCallback callback) { |
122 |
GtkWidget* entry = gtk_menu_item_new_with_label(text); |
154 |
GtkWidget* entry = gtk_menu_item_new_with_label(text); |
123 |
g_signal_connect(entry, "activate", callback, NULL); |
155 |
g_signal_connect(entry, "activate", callback, NULL); |
124 |
gtk_menu_shell_append(GTK_MENU_SHELL(menu_widget), entry); |
156 |
gtk_menu_shell_append(GTK_MENU_SHELL(menu_widget), entry); |
Lines 138-143
Link Here
|
138 |
return FALSE; |
170 |
return FALSE; |
139 |
} |
171 |
} |
140 |
|
172 |
|
|
|
173 |
gboolean WindowConfigure(GtkWindow* window, |
174 |
GdkEvent* event, |
175 |
gpointer data) { |
176 |
// Called when size, position or stack order changes. |
177 |
if (g_handler) { |
178 |
CefRefPtr<CefBrowser> browser = g_handler->GetBrowser(); |
179 |
if (browser) { |
180 |
// Notify the browser of move/resize events so that: |
181 |
// - Popup windows are displayed in the correct location and dismissed |
182 |
// when the window moves. |
183 |
// - Drag&drop areas are updated accordingly. |
184 |
browser->GetHost()->NotifyMoveOrResizeStarted(); |
185 |
} |
186 |
} |
187 |
|
188 |
return FALSE; // Don't stop this message. |
189 |
} |
190 |
|
191 |
void VboxSizeAllocated(GtkWidget* widget, |
192 |
GtkAllocation* allocation, |
193 |
void* data) { |
194 |
if (g_handler) { |
195 |
CefRefPtr<CefBrowser> browser = g_handler->GetBrowser(); |
196 |
if (browser && !browser->GetHost()->IsWindowRenderingDisabled()) { |
197 |
// Size the browser window to match the GTK widget. |
198 |
::Display* xdisplay = cef_get_xdisplay(); |
199 |
::Window xwindow = browser->GetHost()->GetWindowHandle(); |
200 |
XWindowChanges changes = {0}; |
201 |
|
202 |
// TODO: get the real value |
203 |
int g_menubar_height = 0; |
204 |
changes.width = allocation->width; |
205 |
changes.height = allocation->height - (g_menubar_height); |
206 |
changes.y = g_menubar_height; |
207 |
XConfigureWindow(xdisplay, xwindow, CWHeight | CWWidth | CWY, &changes); |
208 |
} |
209 |
} |
210 |
} |
211 |
|
212 |
gboolean WindowFocusIn(GtkWidget* widget, |
213 |
GdkEventFocus* event, |
214 |
gpointer user_data) { |
215 |
if (g_handler && event->in) { |
216 |
CefRefPtr<CefBrowser> browser = g_handler->GetBrowser(); |
217 |
if (browser) { |
218 |
if (browser->GetHost()->IsWindowRenderingDisabled()) { |
219 |
// Give focus to the off-screen browser. |
220 |
browser->GetHost()->SendFocusEvent(true); |
221 |
} else { |
222 |
// Give focus to the browser window. |
223 |
browser->GetHost()->SetFocus(true); |
224 |
return TRUE; |
225 |
} |
226 |
} |
227 |
} |
228 |
|
229 |
return FALSE; |
230 |
} |
231 |
|
141 |
int main(int argc, char* argv[]) { |
232 |
int main(int argc, char* argv[]) { |
142 |
CefMainArgs main_args(argc, argv); |
233 |
CefMainArgs main_args(argc, argv); |
143 |
|
234 |
|
Lines 155-164
Link Here
|
155 |
if (!getcwd(szWorkingDir, sizeof (szWorkingDir))) |
246 |
if (!getcwd(szWorkingDir, sizeof (szWorkingDir))) |
156 |
return -1; |
247 |
return -1; |
157 |
|
248 |
|
158 |
GtkWidget* window; |
|
|
159 |
|
160 |
// Parse command line arguments. |
249 |
// Parse command line arguments. |
161 |
AppInitCommandLine(argc, argv); |
250 |
AppInitCommandLine(argc, argv); |
|
|
251 |
|
252 |
// Install xlib error handlers so that the application won't be terminated |
253 |
// on non-fatal errors. |
254 |
XSetErrorHandler(XErrorHandlerImpl); |
255 |
XSetIOErrorHandler(XIOErrorHandlerImpl); |
162 |
|
256 |
|
163 |
CefSettings settings; |
257 |
CefSettings settings; |
164 |
|
258 |
|
Lines 171-189
Link Here
|
171 |
if (CefString(&settings.cache_path).length() == 0) { |
265 |
if (CefString(&settings.cache_path).length() == 0) { |
172 |
CefString(&settings.cache_path) = AppGetCachePath(); |
266 |
CefString(&settings.cache_path) = AppGetCachePath(); |
173 |
} |
267 |
} |
174 |
|
268 |
|
175 |
CefRefPtr<CefCommandLine> cmdLine = AppGetCommandLine(); |
269 |
CefRefPtr<CefCommandLine> cmdLine = AppGetCommandLine(); |
176 |
|
270 |
|
177 |
if (cmdLine->HasSwitch(cefclient::kStartupPath)) { |
271 |
if (cmdLine->HasSwitch(cefclient::kStartupPath)) { |
178 |
szInitialUrl = cmdLine->GetSwitchValue(cefclient::kStartupPath); |
272 |
szInitialUrl = cmdLine->GetSwitchValue(cefclient::kStartupPath); |
179 |
} else { |
273 |
} else { |
180 |
szInitialUrl = AppGetRunningDirectory(); |
274 |
szInitialUrl = AppGetRunningDirectory(); |
181 |
szInitialUrl.append("/dev/src/index.html"); |
275 |
szInitialUrl.append("/dev/src/index.html"); |
182 |
|
276 |
|
183 |
if (!FileExists(szInitialUrl)) { |
277 |
if (!FileExists(szInitialUrl)) { |
184 |
szInitialUrl = AppGetRunningDirectory(); |
278 |
szInitialUrl = AppGetRunningDirectory(); |
185 |
szInitialUrl.append("/www/index.html"); |
279 |
szInitialUrl.append("/www/index.html"); |
186 |
|
280 |
|
187 |
if (!FileExists(szInitialUrl)) { |
281 |
if (!FileExists(szInitialUrl)) { |
188 |
if (GetInitialUrl() < 0) |
282 |
if (GetInitialUrl() < 0) |
189 |
return 0; |
283 |
return 0; |
Lines 191-222
Link Here
|
191 |
} |
285 |
} |
192 |
} |
286 |
} |
193 |
|
287 |
|
|
|
288 |
// Start the node server process |
289 |
startNodeProcess(); |
290 |
|
194 |
// Initialize CEF. |
291 |
// Initialize CEF. |
195 |
CefInitialize(main_args, settings, app.get(), NULL); |
292 |
CefInitialize(main_args, settings, app.get(), NULL); |
196 |
|
293 |
|
197 |
// Set window icon |
294 |
// Set window icon |
198 |
std::vector<std::string> icons(APPICONS, APPICONS + sizeof(APPICONS) / sizeof(APPICONS[0]) ); |
295 |
std::vector<std::string> icons(APPICONS, APPICONS + sizeof (APPICONS) / sizeof (APPICONS[0])); |
199 |
GList *list = NULL; |
296 |
GList *list = NULL; |
200 |
for (int i = 0; i < icons.size(); ++i) { |
297 |
for (int i = 0; i < icons.size(); ++i) { |
201 |
std::string path = icons[i]; |
298 |
std::string path = icons[i]; |
202 |
|
299 |
|
203 |
GdkPixbuf *icon = gdk_pixbuf_new_from_file(path.c_str(), NULL); |
300 |
GdkPixbuf *icon = gdk_pixbuf_new_from_file(path.c_str(), NULL); |
204 |
if (!icon) |
301 |
if (!icon) |
205 |
continue; |
302 |
continue; |
206 |
|
303 |
|
207 |
list = g_list_append(list, icon); |
304 |
list = g_list_append(list, icon); |
208 |
} |
305 |
} |
209 |
|
306 |
|
210 |
window = gtk_window_new(GTK_WINDOW_TOPLEVEL); |
307 |
GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL); |
211 |
gtk_window_set_default_size(GTK_WINDOW(window), 800, 600); |
308 |
gtk_window_set_default_size(GTK_WINDOW(window), DEFAULT_SIZE_WIDTH, DEFAULT_SIZE_HEIGHT); |
212 |
|
309 |
|
213 |
gtk_window_set_icon_list(GTK_WINDOW(window), list); |
310 |
gtk_window_set_icon_list(GTK_WINDOW(window), list); |
214 |
|
311 |
|
215 |
// Free icon list |
312 |
// Free icon list |
216 |
g_list_foreach(list, (GFunc) g_object_unref, NULL); |
313 |
g_list_foreach(list, (GFunc) g_object_unref, NULL); |
217 |
g_list_free(list); |
314 |
g_list_free(list); |
218 |
|
315 |
|
219 |
GtkWidget* vbox = gtk_vbox_new(FALSE, 0); |
316 |
GtkWidget* vbox = gtk_vbox_new(FALSE, 0); |
|
|
317 |
g_signal_connect(vbox, "size-allocate", |
318 |
G_CALLBACK(VboxSizeAllocated), NULL); |
319 |
gtk_container_add(GTK_CONTAINER(window), vbox); |
220 |
|
320 |
|
221 |
GtkWidget* menuBar = gtk_menu_bar_new(); |
321 |
GtkWidget* menuBar = gtk_menu_bar_new(); |
222 |
// GtkWidget* debug_menu = CreateMenu(menuBar, "Tests"); |
322 |
// GtkWidget* debug_menu = CreateMenu(menuBar, "Tests"); |
Lines 225-242
Link Here
|
225 |
|
325 |
|
226 |
gtk_box_pack_start(GTK_BOX(vbox), menuBar, FALSE, FALSE, 0); |
326 |
gtk_box_pack_start(GTK_BOX(vbox), menuBar, FALSE, FALSE, 0); |
227 |
|
327 |
|
|
|
328 |
// setup all event listener to handle focus, resizing, destruction |
329 |
g_signal_connect(G_OBJECT(window), "configure-event", |
330 |
G_CALLBACK(WindowConfigure), NULL); |
331 |
g_signal_connect(G_OBJECT(window), "focus-in-event", |
332 |
G_CALLBACK(WindowFocusIn), NULL); |
228 |
g_signal_connect(G_OBJECT(window), "delete_event", |
333 |
g_signal_connect(G_OBJECT(window), "delete_event", |
229 |
G_CALLBACK(HandleQuit), NULL); |
334 |
G_CALLBACK(HandleQuit), NULL); |
230 |
g_signal_connect(G_OBJECT(window), "destroy", |
335 |
g_signal_connect(G_OBJECT(window), "destroy", |
231 |
G_CALLBACK(gtk_widget_destroyed), &window); |
336 |
G_CALLBACK(destroy), window); |
232 |
add_handler_id = g_signal_connect(G_OBJECT(window), "add", |
337 |
|
233 |
G_CALLBACK(HandleAdd), NULL); |
338 |
// add_handler_id = g_signal_connect(G_OBJECT(window), "add", |
234 |
// g_signal_connect(G_OBJECT(window), "destroy", |
339 |
// G_CALLBACK(HandleAdd), NULL); |
235 |
// G_CALLBACK(destroy), NULL); |
|
|
236 |
|
340 |
|
237 |
// Create the handler. |
341 |
// Create the handler. |
238 |
g_handler = new ClientHandler(); |
342 |
g_handler = new ClientHandler(); |
239 |
g_handler->SetMainHwnd(vbox); |
343 |
g_handler->SetMainHwnd(vbox); |
|
|
344 |
// g_handler->SetMainHwnd(window); |
240 |
|
345 |
|
241 |
// Create the browser view. |
346 |
// Create the browser view. |
242 |
CefWindowInfo window_info; |
347 |
CefWindowInfo window_info; |
Lines 244-265
Link Here
|
244 |
|
349 |
|
245 |
browserSettings.web_security = STATE_DISABLED; |
350 |
browserSettings.web_security = STATE_DISABLED; |
246 |
|
351 |
|
247 |
window_info.SetAsChild(vbox); |
352 |
// show the window |
248 |
|
353 |
gtk_widget_show_all(GTK_WIDGET(window)); |
|
|
354 |
|
355 |
window_info.SetAsChild(GDK_WINDOW_XID(gtk_widget_get_window(window)), |
356 |
CefRect(0, 0, DEFAULT_SIZE_WIDTH, DEFAULT_SIZE_HEIGHT)); |
357 |
|
358 |
// Create the browser window |
249 |
CefBrowserHost::CreateBrowser( |
359 |
CefBrowserHost::CreateBrowser( |
250 |
window_info, |
360 |
window_info, |
251 |
static_cast<CefRefPtr<CefClient> >(g_handler), |
361 |
g_handler.get(), |
252 |
"file://"+szInitialUrl, browserSettings, NULL); |
362 |
"file://" + szInitialUrl, browserSettings, NULL); |
253 |
|
|
|
254 |
gtk_container_add(GTK_CONTAINER(window), vbox); |
255 |
gtk_widget_show_all(GTK_WIDGET(window)); |
256 |
|
363 |
|
257 |
// Install an signal handler so we clean up after ourselves. |
364 |
// Install an signal handler so we clean up after ourselves. |
258 |
signal(SIGINT, TerminationSignalHandler); |
365 |
signal(SIGINT, TerminationSignalHandler); |
259 |
signal(SIGTERM, TerminationSignalHandler); |
366 |
signal(SIGTERM, TerminationSignalHandler); |
260 |
|
|
|
261 |
// Start the node server process |
262 |
startNodeProcess(); |
263 |
|
367 |
|
264 |
CefRunMessageLoop(); |
368 |
CefRunMessageLoop(); |
265 |
|
369 |
|
Lines 277-279
Link Here
|
277 |
// TODO |
381 |
// TODO |
278 |
return CefString(""); |
382 |
return CefString(""); |
279 |
} |
383 |
} |
|
|
384 |
|