diff --git a/Gruntfile.js b/Gruntfile.js index 58beee565..61b57d255 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -329,7 +329,7 @@ module.exports = function (grunt) { "version" : cef_version }, "node": { - "version" : "6.11.0" + "version" : "6.14.0" }, "icu": { "url" : "http://s3.amazonaws.com/files.brackets.io/icu", diff --git a/appshell.gyp b/appshell.gyp index 366557118..c8d755205 100755 --- a/appshell.gyp +++ b/appshell.gyp @@ -533,6 +533,9 @@ '$(SDKROOT)/System/Library/Frameworks/ScriptingBridge.framework', '$(SDKROOT)/System/Library/Frameworks/Security.framework', '$(CONFIGURATION)/<(framework_name).framework/<(framework_name)', + 'deps/icu/lib/libicuuc.a', + 'deps/icu/lib/libicui18n.a', + 'deps/icu/lib/libicudata.a', ], }, 'sources': [ diff --git a/appshell/browser/root_window_gtk.cc b/appshell/browser/root_window_gtk.cc index 60f66302e..fb5f312b2 100644 --- a/appshell/browser/root_window_gtk.cc +++ b/appshell/browser/root_window_gtk.cc @@ -21,9 +21,14 @@ #include "appshell/browser/window_test.h" #include "appshell/common/client_switches.h" -// Brackets specific change. +// Brackets specific changes. #include "appshell/native_menu_model.h" #include "appshell/command_callbacks.h" +#include "appshell/appshell_helpers.h" + +#define DEFAULT_WINDOW_WIDTH 800 +#define DEFAULT_WINDOW_HEIGHT 600 +// End of Brackets specific changes. namespace client { @@ -31,23 +36,187 @@ namespace { const char kMenuIdKey[] = "menu_id"; -bool IsWindowMaximized(GtkWindow* window) { - GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window)); - gint state = gdk_window_get_state(gdk_window); - return (state & GDK_WINDOW_STATE_MAXIMIZED) ? true : false; +// Brackets specific changes. +gboolean IsWindowMaximized(GtkWindow* window) { + + if (window) { + GdkWindow* gdk_window = gtk_widget_get_window(GTK_WIDGET(window)); + if (gdk_window) { + gint state = gdk_window_get_state(gdk_window); + return (state & GDK_WINDOW_STATE_MAXIMIZED) ? TRUE : FALSE; + } + } else { + return FALSE; + } + } void MinimizeWindow(GtkWindow* window) { - // Unmaximize the window before minimizing so restore behaves correctly. - if (IsWindowMaximized(window)) - gtk_window_unmaximize(window); - gtk_window_iconify(window); + if (window) { + // Unmaximize the window before minimizing so restore behaves correctly. + if (IsWindowMaximized(window)) + gtk_window_unmaximize(window); + + gtk_window_iconify(window); + } } void MaximizeWindow(GtkWindow* window) { - gtk_window_maximize(window); + if (window) { + gtk_window_maximize(window); + } +} + +void SaveWindowState(GtkWindow* window) { + + if (!window) + return; + + gint left = 1; + gint top = 1; + gint width = DEFAULT_WINDOW_WIDTH; + gint height = DEFAULT_WINDOW_HEIGHT; + + // Try to center the window. + GdkScreen* screen = gdk_screen_get_default(); + if (screen) { + left = (gdk_screen_get_width(screen) - DEFAULT_WINDOW_WIDTH) / 2 ; + top = (gdk_screen_get_height(screen) - DEFAULT_WINDOW_HEIGHT) / 2 ; + } + + GKeyFile* key_file = g_key_file_new(); + GError* err = NULL; + gchar* filePath = NULL; + + if (key_file) { + filePath = g_strdup_printf("%s/%s", appshell::AppGetSupportDirectory().ToString().c_str(), "window.ini"); + gboolean maximized = IsWindowMaximized(window); + + // If window is not maximized, save current size and position + + if (!maximized) { + gtk_window_get_position(window, &left, &top); + gtk_window_get_size(window, &width, &height); + } else if (g_key_file_load_from_file(key_file, filePath, G_KEY_FILE_NONE, &err)) { + + // If maximized, load size and position from file + // to preserve last saved values + left = g_key_file_get_integer(key_file, "position", "left", &err); + if (!err) + top = g_key_file_get_integer(key_file, "position", "top", &err); + + if (!err) + width = g_key_file_get_integer(key_file, "size", "width", &err); + + if (!err) + height = g_key_file_get_integer(key_file, "size", "height", &err); + + // If any value can not be read, restore defaults + if (err) { + left = 1; + top = 1; + width = DEFAULT_WINDOW_WIDTH; + height = DEFAULT_WINDOW_HEIGHT; + g_error_free(err); + } + } + + // The values would always be written to file. + g_key_file_set_integer(key_file, "position", "left", left); + g_key_file_set_integer(key_file, "position", "top", top); + g_key_file_set_integer(key_file, "size", "width", width - 1); // DelayedResize() 1 pixel compensation + g_key_file_set_integer(key_file, "size", "height", height - 1); // DelayedResize() 1 pixel compensation + g_key_file_set_boolean(key_file, "state", "maximized", maximized); + + err = NULL; + g_key_file_save_to_file(key_file, filePath, &err); + + if (err) { + fprintf(stderr, "Err -> SaveWindowState(): could not write to `window.ini`. Error Description: %s\n", err->message); + } + } else { + fprintf(stderr, "Err -> SaveWindowState(): could not write to `window.ini`\n"); + } +} + +void LoadWindowState(GtkWindow* window) { + + if (!window) { + return; + } + + // Default values for the window state. + gint left = 1; + gint top = 1; + gint width = DEFAULT_WINDOW_WIDTH; + gint height = DEFAULT_WINDOW_HEIGHT; + + // Try to center the window. + GdkScreen* screen = gdk_screen_get_default(); + if (screen) { + left = (gdk_screen_get_width(screen) - DEFAULT_WINDOW_WIDTH) / 2 ; + top = (gdk_screen_get_height(screen) - DEFAULT_WINDOW_HEIGHT) / 2 ; + } + + gboolean maximized = false; + + GKeyFile* key_file = g_key_file_new(); + bool any_error = false; + GError* err = NULL; + gchar* filePath = g_strdup_printf("%s/%s", appshell::AppGetSupportDirectory().ToString().c_str(), "window.ini"); + + if (key_file && g_key_file_load_from_file(key_file, filePath, G_KEY_FILE_NONE, &err)) { + + left = g_key_file_get_integer(key_file, "position", "left", &err); + if (!err) + top = g_key_file_get_integer(key_file, "position", "top", &err); + + if (!err) + width = g_key_file_get_integer(key_file, "size", "width", &err); + + if (!err) + height = g_key_file_get_integer(key_file, "size", "height", &err); + + if (!err) + maximized = g_key_file_get_boolean(key_file, "state", "maximized", &err); + + // If any value can not be readed, set defaults again + if (err) { + left = 1; + top = 1; + width = DEFAULT_WINDOW_WIDTH; + height = DEFAULT_WINDOW_HEIGHT; + maximized = TRUE; + } + } else { + any_error = true; + } + + gtk_window_move(GTK_WINDOW(window), left, top); + gtk_window_set_default_size(GTK_WINDOW(window), width, height); + + if (maximized) + MaximizeWindow(window); + + if (err || any_error) { + + // The failure could be because the file may not have been present, + // or the file read itself failed. + // In either of the cases default to maximizing the window. + MaximizeWindow(window); + + if (err) { + if (err->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND){ + fprintf(stderr, "LoadWindowState(): Could not read %s. Error Description:%s.\n", filePath, err->message); + } + g_error_free(err); + } else { + fprintf(stderr, "LoadWindowState(): Could not read %s.\n", filePath); + } + } } +// End of Brackets specific changes. } // namespace @@ -197,6 +366,7 @@ void RootWindowGtk::Close(bool force) { REQUIRE_MAIN_THREAD(); if (window_) { + SaveWindowState(GTK_WINDOW(window_)); force_close_ = force; gtk_widget_destroy(window_); } @@ -242,18 +412,20 @@ void RootWindowGtk::CreateRootWindow(const CefBrowserSettings& settings) { // in the upper-left corner. Maybe there's a better default place to put it? int x = start_rect_.x; int y = start_rect_.y; - int width, height; + int width = start_rect_.width; + int height = start_rect_.height; + + window_ = gtk_window_new(GTK_WINDOW_TOPLEVEL); + + // Brackets specific change. if (start_rect_.IsEmpty()) { - // TODO(port): Also, maybe there's a better way to choose the default size. - width = 800; - height = 600; + LoadWindowState(GTK_WINDOW(window_)); } else { - width = start_rect_.width; - height = start_rect_.height; + gtk_window_move(GTK_WINDOW(window_), x, y); + gtk_window_set_default_size(GTK_WINDOW(window_), width, height); } + // End of Brackets specific change. - window_ = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_default_size(GTK_WINDOW(window_), width, height); g_signal_connect(G_OBJECT(window_), "focus-in-event", G_CALLBACK(&RootWindowGtk::WindowFocusIn), this); g_signal_connect(G_OBJECT(window_), "window-state-event", @@ -341,7 +513,7 @@ void RootWindowGtk::CreateRootWindow(const CefBrowserSettings& settings) { // Most window managers ignore requests for initial window positions (instead // using a user-defined placement algorithm) and honor requests after the // window has already been shown. - gtk_window_move(GTK_WINDOW(window_), x, y); + //gtk_window_move(GTK_WINDOW(window_), x, y); // Windowed browsers are parented to the X11 Window underlying the GtkWindow* // and must be sized manually. The OSR GTK widget, on the other hand, can be diff --git a/appshell/cefclient.cpp b/appshell/cefclient.cpp index 72777401b..a6bf5aca8 100644 --- a/appshell/cefclient.cpp +++ b/appshell/cefclient.cpp @@ -20,6 +20,10 @@ CefRefPtr g_handler; +#ifdef OS_WIN +bool g_force_enable_acc = false; +#endif + CefRefPtr AppGetBrowser() { if (!g_handler.get()) return NULL; @@ -32,6 +36,20 @@ CefWindowHandle AppGetMainHwnd() { return g_handler->GetMainHwnd(); } +// CefCommandLine::HasSwitch is unable to report the presense of switches, +// in the command line properly. This is a generic function that could be +// used to check for any particular switch, passed as a command line argument. +bool HasSwitch(CefRefPtr command_line , CefString& switch_name) +{ + if (command_line) { + ExtensionString cmdLine = command_line->GetCommandLineString(); + size_t idx = cmdLine.find(switch_name); + return idx > 0 && idx < cmdLine.length(); + } else { + return false; + } +} + // Returns the application settings based on command line arguments. void AppGetSettings(CefSettings& settings, CefRefPtr command_line) { DCHECK(command_line.get()); @@ -91,4 +109,16 @@ void AppGetSettings(CefSettings& settings, CefRefPtr command_lin // Set product version, which gets added to the User Agent string CefString(&settings.product_version) = versionStr; } + +#ifdef OS_WIN + // We disable renderer accessibility by default as it is known to cause performance + // issues. But if any one wants to enable it back, then we need to honor the flag. + + CefString force_acc_switch_name("--force-renderer-accessibility"); + CefString enable_acc_switch_name("--enable-renderer-accessibility"); + + if (HasSwitch(command_line, force_acc_switch_name) || HasSwitch(command_line, enable_acc_switch_name)) + g_force_enable_acc = true; +#endif + } diff --git a/appshell/client_app.cpp b/appshell/client_app.cpp index 828ac8084..82f9a3f7c 100644 --- a/appshell/client_app.cpp +++ b/appshell/client_app.cpp @@ -16,6 +16,10 @@ #include "appshell/appshell_extension_handler.h" #include "appshell/appshell_helpers.h" +#ifdef OS_WIN +extern bool g_force_enable_acc; +#endif + ClientApp::ClientApp() { CreateRenderDelegates(render_delegates_); } @@ -42,6 +46,27 @@ void ClientApp::OnContextCreated(CefRefPtr browser, (*it)->OnContextCreated(this, browser, frame, context); } +void ClientApp::OnBeforeCommandLineProcessing( + const CefString& process_type, + CefRefPtr command_line) +{ + #ifdef OS_WIN + // Check if the user wants to enable renderer accessibility + // and if not, then disable renderer accessibility. + if (!g_force_enable_acc) + command_line->AppendSwitch("disable-renderer-accessibility"); + #endif +} + +void ClientApp::OnBeforeChildProcessLaunch( + CefRefPtr command_line) +{ +#ifdef OS_WIN + if (!g_force_enable_acc) + command_line->AppendSwitch("disable-renderer-accessibility"); +#endif +} + void ClientApp::OnContextReleased(CefRefPtr browser, CefRefPtr frame, CefRefPtr context) { diff --git a/appshell/client_app.h b/appshell/client_app.h index f1a64940c..fa2da0212 100644 --- a/appshell/client_app.h +++ b/appshell/client_app.h @@ -102,6 +102,15 @@ class ClientApp : public CefApp, } virtual CefRefPtr GetRenderProcessHandler() OVERRIDE { return this; } + + virtual CefRefPtr GetBrowserProcessHandler() + OVERRIDE { return this; } + virtual void OnBeforeCommandLineProcessing( + const CefString& process_type, + CefRefPtr command_line); + + virtual void OnBeforeChildProcessLaunch( + CefRefPtr command_line); // CefRenderProcessHandler methods. virtual void OnWebKitInitialized() OVERRIDE; diff --git a/appshell/mac/Info.plist b/appshell/mac/Info.plist index e1b8ba96a..6cc3f9896 100644 --- a/appshell/mac/Info.plist +++ b/appshell/mac/Info.plist @@ -19,9 +19,9 @@ CFBundleSignature ???? CFBundleVersion - 1.13.0 + 1.14.0 CFBundleShortVersionString - 1.13.0 + 1.14.0 NSMainNibFile MainMenu NSPrincipalClass diff --git a/appshell/update_mac.mm b/appshell/update_mac.mm index 608ffc757..8a76f7f96 100644 --- a/appshell/update_mac.mm +++ b/appshell/update_mac.mm @@ -67,6 +67,7 @@ + (void) setParams:(NSMutableDictionary *)params { _params = params; } + // Runs a script, given the script path, and args array. int RunScript(NSString* launchPath, NSArray* argsArray, BOOL waitUntilExit) { @@ -172,9 +173,39 @@ + (void) RunAppUpdate{ else { int pid = [self getCurrentProcessID]; NSString* pidString = [NSString stringWithFormat:@"%d", pid]; - pArgs = [NSArray arrayWithObjects:shPath, scriptPath, @"-a", bracketsAppName, @"-b", installDir, @"-l", logFilePath, @"-m", mountPoint, @"-t", updateDir, @"-p", pidString, @"&", nil]; - - retval = RunScript(nohupPath, pArgs, false); + BOOL isAdmin = NO; + + NSString *installDirPath = installDir; + installDirPath = [installDirPath stringByAppendingString:@"/"]; + NSString *bracketsAppPath = installDirPath; + bracketsAppPath = [bracketsAppPath stringByAppendingString:bracketsAppName]; + + NSFileManager *fm = [NSFileManager defaultManager]; + if([fm isWritableFileAtPath:installDirPath] && [fm isWritableFileAtPath:bracketsAppPath] ) + { + isAdmin = YES; + } + + + /*Build the Apple Script String*/ + NSAppleEventDescriptor *returnDescriptor = NULL; + NSString * appleScriptString; + + appleScriptString = [NSString stringWithFormat:@"do shell script \"%@ %@ %@ -a %@ -b '%@' -l '%@' -m %@ -t '%@' -p %@ > /dev/null 2>&1 &\"", nohupPath, shPath, scriptPath, bracketsAppName, installDir, logFilePath, mountPoint, updateDir, pidString]; + + if(!isAdmin) { + appleScriptString = [appleScriptString stringByAppendingString:@" with administrator privileges"]; + } + + NSAppleScript *theScript = [[NSAppleScript alloc] initWithSource:appleScriptString]; + + NSDictionary *theError = nil; + + returnDescriptor = [theScript executeAndReturnError: &theError]; + if(returnDescriptor == NULL) { + NSString *logStr = @"ERROR: scriptexecution Failed error: BA_06"; + [logStr writeToFile:installStatusFilePath atomically:YES encoding:NSUTF8StringEncoding error:nil]; + } } } } diff --git a/appshell/version.rc b/appshell/version.rc index 4ebc3f98e..7b727e683 100644 --- a/appshell/version.rc +++ b/appshell/version.rc @@ -31,7 +31,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // VS_VERSION_INFO VERSIONINFO -FILEVERSION 1,13,0,0 +FILEVERSION 1,14,0,0 /* PRODUCTVERSION 1,0,0,0 */ FILEOS VOS__WINDOWS32 FILETYPE VFT_APP @@ -42,7 +42,7 @@ BEGIN BEGIN VALUE "CompanyName", "brackets.io\0" VALUE "FileDescription", "\0" - VALUE "FileVersion", "Release 1.13.0\0" + VALUE "FileVersion", "Release 1.14.0\0" VALUE "ProductName", APP_NAME "\0" VALUE "ProductVersion", "\0" VALUE "LegalCopyright", "(c) 2012 Adobe Systems, Inc.\0" diff --git a/appshell/version_linux.h b/appshell/version_linux.h index b0a133644..126e2ca9b 100644 --- a/appshell/version_linux.h +++ b/appshell/version_linux.h @@ -1 +1 @@ -#define APP_VERSION "1.13.0.0" +#define APP_VERSION "1.14.0.0" diff --git a/appshell_paths.gypi b/appshell_paths.gypi index 3b14692a1..b7937deae 100755 --- a/appshell_paths.gypi +++ b/appshell_paths.gypi @@ -194,12 +194,12 @@ 'appshell/client_handler.h', 'appshell/native_menu_model.cpp', 'appshell/native_menu_model.h', + 'appshell/update.h', + 'appshell/update.cpp', ], 'appshell_sources_common': [ 'appshell/cefclient.cpp', 'appshell/cefclient.h', - 'appshell/update.h', - 'appshell/update.cpp', '<@(appshell_sources_common_helper)', ], 'appshell_sources_common_linux': [ @@ -310,6 +310,7 @@ 'appshell/appshell_helpers_mac.mm', 'appshell/client_handler_mac.mm', 'appshell/process_helper_mac.cpp', + 'appshell/update_mac.mm', '<@(appshell_sources_common_helper)', '<@(appshell_sources_renderer)', ], diff --git a/installer/mac/buildInstaller.sh b/installer/mac/buildInstaller.sh index 7cfb4c72b..63a2ce1c3 100755 --- a/installer/mac/buildInstaller.sh +++ b/installer/mac/buildInstaller.sh @@ -2,7 +2,7 @@ # config releaseName="Brackets" -version="1.13" +version="1.14" dmgName="${releaseName} Release ${version}" format="bzip2" encryption="none" diff --git a/installer/mac/update.sh b/installer/mac/update.sh index 12228aae3..276f0a92e 100755 --- a/installer/mac/update.sh +++ b/installer/mac/update.sh @@ -172,6 +172,7 @@ function updateBrackets(){ printInfo "Unmounted the DMG and attempying to open Brackets ..." fi + rm -rf "$TEMP_DIR/$APP_NAME" open -a "$APP_DIR/$APP_NAME" exitStatus=$? if [ $exitStatus -ne 0 ] diff --git a/installer/win/brackets-win-install-build.xml b/installer/win/brackets-win-install-build.xml index 24a4f0320..2b4ee9454 100644 --- a/installer/win/brackets-win-install-build.xml +++ b/installer/win/brackets-win-install-build.xml @@ -12,7 +12,7 @@ default="build.mul"> - + diff --git a/package.json b/package.json index e8dbf740e..b4af707fe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "Brackets-Shell", - "version": "1.13.0-0", + "version": "1.14.0-0", "homepage": "http://brackets.io", "issues": { "url": "http://github.com/adobe/brackets-shell/issues"