| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/gtk/browser_window_gtk.h" | 5 #include "chrome/browser/gtk/browser_window_gtk.h" |
| 6 | 6 |
| 7 #include <gdk/gdkkeysyms.h> | 7 #include <gdk/gdkkeysyms.h> |
| 8 | 8 |
| 9 #include "base/base_paths_linux.h" | 9 #include "base/base_paths_linux.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 browser_win->OnBoundsChanged(bounds); | 60 browser_win->OnBoundsChanged(bounds); |
| 61 return FALSE; | 61 return FALSE; |
| 62 } | 62 } |
| 63 | 63 |
| 64 gboolean MainWindowStateChanged(GtkWindow* window, GdkEventWindowState* event, | 64 gboolean MainWindowStateChanged(GtkWindow* window, GdkEventWindowState* event, |
| 65 BrowserWindowGtk* browser_win) { | 65 BrowserWindowGtk* browser_win) { |
| 66 browser_win->OnStateChanged(event->new_window_state); | 66 browser_win->OnStateChanged(event->new_window_state); |
| 67 return FALSE; | 67 return FALSE; |
| 68 } | 68 } |
| 69 | 69 |
| 70 // Callback for the delete event. This event is fired when the user tries to |
| 71 // close the window (e.g., clicking on the X in the window manager title bar). |
| 72 gboolean MainWindowDeleteEvent(GtkWidget* widget, GdkEvent* event, |
| 73 BrowserWindowGtk* window) { |
| 74 window->Close(); |
| 75 |
| 76 // Return true to prevent the gtk window from being destroyed. Close will |
| 77 // destroy it for us. |
| 78 return TRUE; |
| 79 } |
| 80 |
| 81 void MainWindowDestroy(GtkWidget* widget, BrowserWindowGtk* window) { |
| 82 // BUG 8712. When we gtk_widget_destroy() in Close(), this will emit the |
| 83 // signal right away, and we will be here (while Close() is still in the |
| 84 // call stack). In order to not reenter Close(), and to also follow the |
| 85 // expectations of BrowserList, we should run the BrowserWindowGtk destructor |
| 86 // not now, but after the run loop goes back to process messages. Otherwise |
| 87 // we will remove ourself from BrowserList while it's being iterated. |
| 88 // Additionally, now that we know the window is gone, we need to make sure to |
| 89 // set window_ to NULL, otherwise we will try to close the window again when |
| 90 // we call Close() in the destructor. |
| 91 MessageLoop::current()->DeleteSoon(FROM_HERE, window); |
| 92 } |
| 93 |
| 70 // Using gtk_window_get_position/size creates a race condition, so only use | 94 // Using gtk_window_get_position/size creates a race condition, so only use |
| 71 // this to get the initial bounds. After window creation, we pick up the | 95 // this to get the initial bounds. After window creation, we pick up the |
| 72 // normal bounds by connecting to the configure-event signal. | 96 // normal bounds by connecting to the configure-event signal. |
| 73 gfx::Rect GetInitialWindowBounds(GtkWindow* window) { | 97 gfx::Rect GetInitialWindowBounds(GtkWindow* window) { |
| 74 gint x, y, width, height; | 98 gint x, y, width, height; |
| 75 gtk_window_get_position(window, &x, &y); | 99 gtk_window_get_position(window, &x, &y); |
| 76 gtk_window_get_size(window, &width, &height); | 100 gtk_window_get_size(window, &width, &height); |
| 77 return gfx::Rect(x, y, width, height); | 101 return gfx::Rect(x, y, width, height); |
| 78 } | 102 } |
| 79 | 103 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 108 } // namespace | 132 } // namespace |
| 109 | 133 |
| 110 // TODO(estade): Break up this constructor into helper functions to improve | 134 // TODO(estade): Break up this constructor into helper functions to improve |
| 111 // readability. | 135 // readability. |
| 112 BrowserWindowGtk::BrowserWindowGtk(Browser* browser) | 136 BrowserWindowGtk::BrowserWindowGtk(Browser* browser) |
| 113 : browser_(browser), | 137 : browser_(browser), |
| 114 // TODO(port): make this a pref. | 138 // TODO(port): make this a pref. |
| 115 custom_frame_(false) { | 139 custom_frame_(false) { |
| 116 window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL)); | 140 window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL)); |
| 117 gtk_window_set_default_size(window_, 640, 480); | 141 gtk_window_set_default_size(window_, 640, 480); |
| 142 g_signal_connect(window_, "delete-event", |
| 143 G_CALLBACK(MainWindowDeleteEvent), this); |
| 118 g_signal_connect(window_, "destroy", | 144 g_signal_connect(window_, "destroy", |
| 119 G_CALLBACK(OnWindowDestroyed), this); | 145 G_CALLBACK(MainWindowDestroy), this); |
| 120 g_signal_connect(window_, "configure-event", | 146 g_signal_connect(window_, "configure-event", |
| 121 G_CALLBACK(MainWindowConfigured), this); | 147 G_CALLBACK(MainWindowConfigured), this); |
| 122 g_signal_connect(window_, "window-state-event", | 148 g_signal_connect(window_, "window-state-event", |
| 123 G_CALLBACK(MainWindowStateChanged), this); | 149 G_CALLBACK(MainWindowStateChanged), this); |
| 124 g_signal_connect(window_, "key-press-event", | 150 g_signal_connect(window_, "key-press-event", |
| 125 G_CALLBACK(OnKeyPress), NULL); | 151 G_CALLBACK(OnKeyPress), NULL); |
| 126 ConnectAccelerators(); | 152 ConnectAccelerators(); |
| 127 bounds_ = GetInitialWindowBounds(window_); | 153 bounds_ = GetInitialWindowBounds(window_); |
| 128 | 154 |
| 129 GdkPixbuf* images[9] = { | 155 GdkPixbuf* images[9] = { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 167 | 193 |
| 168 status_bubble_.reset(new StatusBubbleGtk(window_)); | 194 status_bubble_.reset(new StatusBubbleGtk(window_)); |
| 169 | 195 |
| 170 gtk_container_add(GTK_CONTAINER(window_), vbox_); | 196 gtk_container_add(GTK_CONTAINER(window_), vbox_); |
| 171 gtk_widget_show(vbox_); | 197 gtk_widget_show(vbox_); |
| 172 browser_->tabstrip_model()->AddObserver(this); | 198 browser_->tabstrip_model()->AddObserver(this); |
| 173 } | 199 } |
| 174 | 200 |
| 175 BrowserWindowGtk::~BrowserWindowGtk() { | 201 BrowserWindowGtk::~BrowserWindowGtk() { |
| 176 browser_->tabstrip_model()->RemoveObserver(this); | 202 browser_->tabstrip_model()->RemoveObserver(this); |
| 177 | |
| 178 Close(); | |
| 179 } | 203 } |
| 180 | 204 |
| 181 gboolean BrowserWindowGtk::OnContentAreaExpose(GtkWidget* widget, | 205 gboolean BrowserWindowGtk::OnContentAreaExpose(GtkWidget* widget, |
| 182 GdkEventExpose* e, | 206 GdkEventExpose* e, |
| 183 BrowserWindowGtk* window) { | 207 BrowserWindowGtk* window) { |
| 184 if (window->custom_frame_) { | 208 if (window->custom_frame_) { |
| 185 NOTIMPLEMENTED() << " needs custom drawing for the custom frame."; | 209 NOTIMPLEMENTED() << " needs custom drawing for the custom frame."; |
| 186 return FALSE; | 210 return FALSE; |
| 187 } | 211 } |
| 188 | 212 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 222 gint x = static_cast<gint>(bounds.x()); | 246 gint x = static_cast<gint>(bounds.x()); |
| 223 gint y = static_cast<gint>(bounds.y()); | 247 gint y = static_cast<gint>(bounds.y()); |
| 224 gint width = static_cast<gint>(bounds.width()); | 248 gint width = static_cast<gint>(bounds.width()); |
| 225 gint height = static_cast<gint>(bounds.height()); | 249 gint height = static_cast<gint>(bounds.height()); |
| 226 | 250 |
| 227 gtk_window_move(window_, x, y); | 251 gtk_window_move(window_, x, y); |
| 228 gtk_window_resize(window_, width, height); | 252 gtk_window_resize(window_, width, height); |
| 229 } | 253 } |
| 230 | 254 |
| 231 void BrowserWindowGtk::Close() { | 255 void BrowserWindowGtk::Close() { |
| 256 // TODO(tc): There's a lot missing here that's in the windows shutdown code |
| 257 // path. This method should try to close (see BrowserView::CanClose), |
| 258 // although it may not succeed (e.g., if the page has an unload handler). |
| 259 // Currently we just go ahead and close. |
| 260 |
| 232 // TODO(tc): Once the tab strip model is hooked up, this call can be removed. | 261 // TODO(tc): Once the tab strip model is hooked up, this call can be removed. |
| 233 // It should get called by TabDetachedAt when the window is being closed, but | 262 // It should get called by TabDetachedAt when the window is being closed, but |
| 234 // we don't have a TabStripModel yet. | 263 // we don't have a TabStripModel yet. |
| 235 find_bar_controller_->ChangeWebContents(NULL); | 264 find_bar_controller_->ChangeWebContents(NULL); |
| 236 | 265 |
| 237 if (!window_) | |
| 238 return; | |
| 239 | |
| 240 GtkWidget* window = GTK_WIDGET(window_); | 266 GtkWidget* window = GTK_WIDGET(window_); |
| 241 // To help catch bugs in any event handlers that might get fired during the | 267 // To help catch bugs in any event handlers that might get fired during the |
| 242 // destruction, set window_ to NULL before any handlers will run. | 268 // destruction, set window_ to NULL before any handlers will run. |
| 243 window_ = NULL; | 269 window_ = NULL; |
| 244 gtk_widget_destroy(window); | 270 gtk_widget_destroy(window); |
| 245 } | 271 } |
| 246 | 272 |
| 247 void BrowserWindowGtk::Activate() { | 273 void BrowserWindowGtk::Activate() { |
| 248 gtk_window_present(window_); | 274 gtk_window_present(window_); |
| 249 } | 275 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 269 | 295 |
| 270 StatusBubble* BrowserWindowGtk::GetStatusBubble() { | 296 StatusBubble* BrowserWindowGtk::GetStatusBubble() { |
| 271 return status_bubble_.get(); | 297 return status_bubble_.get(); |
| 272 } | 298 } |
| 273 | 299 |
| 274 void BrowserWindowGtk::SelectedTabToolbarSizeChanged(bool is_animating) { | 300 void BrowserWindowGtk::SelectedTabToolbarSizeChanged(bool is_animating) { |
| 275 NOTIMPLEMENTED(); | 301 NOTIMPLEMENTED(); |
| 276 } | 302 } |
| 277 | 303 |
| 278 void BrowserWindowGtk::UpdateTitleBar() { | 304 void BrowserWindowGtk::UpdateTitleBar() { |
| 279 if (!window_) | |
| 280 return; | |
| 281 | |
| 282 std::wstring title = browser_->GetCurrentPageTitle(); | 305 std::wstring title = browser_->GetCurrentPageTitle(); |
| 283 gtk_window_set_title(window_, WideToUTF8(title).c_str()); | 306 gtk_window_set_title(window_, WideToUTF8(title).c_str()); |
| 284 if (browser_->SupportsWindowFeature(Browser::FEATURE_TITLEBAR)) { | 307 if (browser_->SupportsWindowFeature(Browser::FEATURE_TITLEBAR)) { |
| 285 // If we're showing a title bar, we should update the app icon. | 308 // If we're showing a title bar, we should update the app icon. |
| 286 NOTIMPLEMENTED(); | 309 NOTIMPLEMENTED(); |
| 287 } | 310 } |
| 288 } | 311 } |
| 289 | 312 |
| 290 void BrowserWindowGtk::UpdateLoadingAnimations(bool should_animate) { | 313 void BrowserWindowGtk::UpdateLoadingAnimations(bool should_animate) { |
| 291 NOTIMPLEMENTED(); | 314 NOTIMPLEMENTED(); |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 if (custom_frame_) { | 497 if (custom_frame_) { |
| 475 gtk_container_set_border_width(GTK_CONTAINER(vbox_), 2); | 498 gtk_container_set_border_width(GTK_CONTAINER(vbox_), 2); |
| 476 // TODO(port): all the crazy blue title bar, etc. | 499 // TODO(port): all the crazy blue title bar, etc. |
| 477 NOTIMPLEMENTED(); | 500 NOTIMPLEMENTED(); |
| 478 } else { | 501 } else { |
| 479 gtk_container_set_border_width(GTK_CONTAINER(vbox_), 0); | 502 gtk_container_set_border_width(GTK_CONTAINER(vbox_), 0); |
| 480 } | 503 } |
| 481 } | 504 } |
| 482 | 505 |
| 483 // static | 506 // static |
| 484 gboolean BrowserWindowGtk::OnWindowDestroyed(GtkWidget* window, | |
| 485 BrowserWindowGtk* browser_win) { | |
| 486 // BUG 8712. When we gtk_widget_destroy() in Close(), this will emit the | |
| 487 // signal right away, and we will be here (while Close() is still in the | |
| 488 // call stack). In order to not reenter Close(), and to also follow the | |
| 489 // expectations of BrowserList, we should run the BrowserWindowGtk destructor | |
| 490 // not now, but after the run loop goes back to process messages. Otherwise | |
| 491 // we will remove ourself from BrowserList while it's being iterated. | |
| 492 // Additionally, now that we know the window is gone, we need to make sure to | |
| 493 // set window_ to NULL, otherwise we will try to close the window again when | |
| 494 // we call Close() in the destructor. | |
| 495 browser_win->window_ = NULL; | |
| 496 MessageLoop::current()->DeleteSoon(FROM_HERE, browser_win); | |
| 497 return FALSE; // Don't stop this message. | |
| 498 } | |
| 499 | |
| 500 // static | |
| 501 gboolean BrowserWindowGtk::OnAccelerator(GtkAccelGroup* accel_group, | 507 gboolean BrowserWindowGtk::OnAccelerator(GtkAccelGroup* accel_group, |
| 502 GObject* acceleratable, | 508 GObject* acceleratable, |
| 503 guint keyval, | 509 guint keyval, |
| 504 GdkModifierType modifier, | 510 GdkModifierType modifier, |
| 505 BrowserWindowGtk* browser_window) { | 511 BrowserWindowGtk* browser_window) { |
| 506 browser_window->browser_->ExecuteCommand(GetCommandFromKeyval(keyval)); | 512 browser_window->browser_->ExecuteCommand(GetCommandFromKeyval(keyval)); |
| 507 return TRUE; | 513 return TRUE; |
| 508 } | 514 } |
| OLD | NEW |