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