| 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 #include <X11/XF86keysym.h> | 8 #include <X11/XF86keysym.h> |
| 9 | 9 |
| 10 #include <string> | 10 #include <string> |
| 11 | 11 |
| 12 #include "app/gfx/color_utils.h" | 12 #include "app/gfx/color_utils.h" |
| 13 #include "app/gfx/gtk_util.h" | 13 #include "app/gfx/gtk_util.h" |
| 14 #include "app/l10n_util.h" | 14 #include "app/l10n_util.h" |
| 15 #include "app/resource_bundle.h" | 15 #include "app/resource_bundle.h" |
| 16 #include "app/theme_provider.h" | 16 #include "app/theme_provider.h" |
| 17 #include "base/base_paths.h" | 17 #include "base/base_paths.h" |
| 18 #include "base/command_line.h" | 18 #include "base/command_line.h" |
| 19 #include "base/gfx/rect.h" | 19 #include "base/gfx/rect.h" |
| 20 #include "base/keyboard_codes.h" |
| 20 #include "base/logging.h" | 21 #include "base/logging.h" |
| 21 #include "base/message_loop.h" | 22 #include "base/message_loop.h" |
| 22 #include "base/path_service.h" | 23 #include "base/path_service.h" |
| 23 #include "base/scoped_ptr.h" | 24 #include "base/scoped_ptr.h" |
| 24 #include "base/string_util.h" | 25 #include "base/string_util.h" |
| 25 #include "base/time.h" | 26 #include "base/time.h" |
| 26 #include "chrome/app/chrome_dll_resource.h" | 27 #include "chrome/app/chrome_dll_resource.h" |
| 27 #include "chrome/browser/app_modal_dialog_queue.h" | 28 #include "chrome/browser/app_modal_dialog_queue.h" |
| 28 #include "chrome/browser/autocomplete/autocomplete_edit_view.h" | 29 #include "chrome/browser/autocomplete/autocomplete_edit_view.h" |
| 29 #include "chrome/browser/bookmarks/bookmark_utils.h" | 30 #include "chrome/browser/bookmarks/bookmark_utils.h" |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 { XF86XK_Go, IDC_FOCUS_LOCATION, GdkModifierType(0) }, | 198 { XF86XK_Go, IDC_FOCUS_LOCATION, GdkModifierType(0) }, |
| 198 | 199 |
| 199 // Tab/window controls. | 200 // Tab/window controls. |
| 200 { GDK_Page_Down, IDC_SELECT_NEXT_TAB, GDK_CONTROL_MASK }, | 201 { GDK_Page_Down, IDC_SELECT_NEXT_TAB, GDK_CONTROL_MASK }, |
| 201 { GDK_Page_Up, IDC_SELECT_PREVIOUS_TAB, GDK_CONTROL_MASK }, | 202 { GDK_Page_Up, IDC_SELECT_PREVIOUS_TAB, GDK_CONTROL_MASK }, |
| 202 { GDK_Page_Down, IDC_MOVE_TAB_NEXT, | 203 { GDK_Page_Down, IDC_MOVE_TAB_NEXT, |
| 203 GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, | 204 GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, |
| 204 { GDK_Page_Up, IDC_MOVE_TAB_PREVIOUS, | 205 { GDK_Page_Up, IDC_MOVE_TAB_PREVIOUS, |
| 205 GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, | 206 GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, |
| 206 { GDK_Page_Up, IDC_SELECT_PREVIOUS_TAB, GDK_CONTROL_MASK }, | 207 { GDK_Page_Up, IDC_SELECT_PREVIOUS_TAB, GDK_CONTROL_MASK }, |
| 207 { GDK_t, IDC_NEW_TAB, GDK_CONTROL_MASK }, | |
| 208 { GDK_n, IDC_NEW_WINDOW, GDK_CONTROL_MASK }, | |
| 209 { GDK_n, IDC_NEW_INCOGNITO_WINDOW, | |
| 210 GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, | |
| 211 { GDK_w, IDC_CLOSE_TAB, GDK_CONTROL_MASK }, | 208 { GDK_w, IDC_CLOSE_TAB, GDK_CONTROL_MASK }, |
| 212 { GDK_t, IDC_RESTORE_TAB, | 209 { GDK_t, IDC_RESTORE_TAB, |
| 213 GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, | 210 GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, |
| 214 | 211 |
| 215 { GDK_1, IDC_SELECT_TAB_0, GDK_CONTROL_MASK }, | 212 { GDK_1, IDC_SELECT_TAB_0, GDK_CONTROL_MASK }, |
| 216 { GDK_2, IDC_SELECT_TAB_1, GDK_CONTROL_MASK }, | 213 { GDK_2, IDC_SELECT_TAB_1, GDK_CONTROL_MASK }, |
| 217 { GDK_3, IDC_SELECT_TAB_2, GDK_CONTROL_MASK }, | 214 { GDK_3, IDC_SELECT_TAB_2, GDK_CONTROL_MASK }, |
| 218 { GDK_4, IDC_SELECT_TAB_3, GDK_CONTROL_MASK }, | 215 { GDK_4, IDC_SELECT_TAB_3, GDK_CONTROL_MASK }, |
| 219 { GDK_5, IDC_SELECT_TAB_4, GDK_CONTROL_MASK }, | 216 { GDK_5, IDC_SELECT_TAB_4, GDK_CONTROL_MASK }, |
| 220 { GDK_6, IDC_SELECT_TAB_5, GDK_CONTROL_MASK }, | 217 { GDK_6, IDC_SELECT_TAB_5, GDK_CONTROL_MASK }, |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 { GDK_f, IDC_FULLSCREEN, | 307 { GDK_f, IDC_FULLSCREEN, |
| 311 GdkModifierType(GDK_CONTROL_MASK | GDK_MOD1_MASK) }, | 308 GdkModifierType(GDK_CONTROL_MASK | GDK_MOD1_MASK) }, |
| 312 { GDK_Delete, IDC_TASK_MANAGER, | 309 { GDK_Delete, IDC_TASK_MANAGER, |
| 313 GdkModifierType(GDK_CONTROL_MASK | GDK_MOD1_MASK) }, | 310 GdkModifierType(GDK_CONTROL_MASK | GDK_MOD1_MASK) }, |
| 314 { GDK_comma, IDC_CONTROL_PANEL, GdkModifierType(GDK_CONTROL_MASK) }, | 311 { GDK_comma, IDC_CONTROL_PANEL, GdkModifierType(GDK_CONTROL_MASK) }, |
| 315 #endif | 312 #endif |
| 316 }; | 313 }; |
| 317 | 314 |
| 318 #if defined(OS_CHROMEOS) | 315 #if defined(OS_CHROMEOS) |
| 319 | 316 |
| 320 namespace { | |
| 321 | |
| 322 // This draws the spacer below the tab strip when we're using the compact | 317 // This draws the spacer below the tab strip when we're using the compact |
| 323 // location bar (i.e. no location bar). This basically duplicates the painting | 318 // location bar (i.e. no location bar). This basically duplicates the painting |
| 324 // that the tab strip would have done for this region so that it blends | 319 // that the tab strip would have done for this region so that it blends |
| 325 // nicely in with the bottom of the tabs. | 320 // nicely in with the bottom of the tabs. |
| 326 gboolean OnCompactNavSpacerExpose(GtkWidget* widget, | 321 gboolean OnCompactNavSpacerExpose(GtkWidget* widget, |
| 327 GdkEventExpose* e, | 322 GdkEventExpose* e, |
| 328 BrowserWindowGtk* window) { | 323 BrowserWindowGtk* window) { |
| 329 cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(widget->window)); | 324 cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(widget->window)); |
| 330 cairo_rectangle(cr, e->area.x, e->area.y, e->area.width, e->area.height); | 325 cairo_rectangle(cr, e->area.x, e->area.y, e->area.width, e->area.height); |
| 331 cairo_clip(cr); | 326 cairo_clip(cr); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 345 tabstrip_origin.x(), | 340 tabstrip_origin.x(), |
| 346 tabstrip_origin.y(), | 341 tabstrip_origin.y(), |
| 347 e->area.x + e->area.width - tabstrip_origin.x(), | 342 e->area.x + e->area.width - tabstrip_origin.x(), |
| 348 e->area.y + e->area.height - tabstrip_origin.y()); | 343 e->area.y + e->area.height - tabstrip_origin.y()); |
| 349 cairo_fill(cr); | 344 cairo_fill(cr); |
| 350 cairo_destroy(cr); | 345 cairo_destroy(cr); |
| 351 | 346 |
| 352 return FALSE; | 347 return FALSE; |
| 353 } | 348 } |
| 354 | 349 |
| 355 } // namespace | |
| 356 | |
| 357 // Callback from GTK when the user clicks the main menu button. | 350 // Callback from GTK when the user clicks the main menu button. |
| 358 static void OnMainMenuButtonClicked(GtkWidget* widget, | 351 static void OnMainMenuButtonClicked(GtkWidget* widget, |
| 359 BrowserWindowGtk* browser) { | 352 BrowserWindowGtk* browser) { |
| 360 chromeos::MainMenu::Show(browser->browser()); | 353 chromeos::MainMenu::Show(browser->browser()); |
| 361 } | 354 } |
| 362 | 355 |
| 363 #endif // OS_CHROMEOS | 356 #endif // OS_CHROMEOS |
| 364 | 357 |
| 365 int GetCommandId(guint accel_key, GdkModifierType modifier) { | 358 // Get the command ids of the key combinations that are not valid gtk |
| 366 // Bug 9806: If capslock is on, we will get a capital letter as accel_key. | 359 // accelerators. |
| 367 accel_key = gdk_keyval_to_lower(accel_key); | 360 int GetCustomCommandId(GdkEventKey* event) { |
| 368 // Filter modifier to only include accelerator modifiers. | 361 // Filter modifier to only include accelerator modifiers. |
| 369 modifier = static_cast<GdkModifierType>( | 362 guint modifier = event->state & gtk_accelerator_get_default_mod_mask(); |
| 370 modifier & gtk_accelerator_get_default_mod_mask()); | 363 switch (event->keyval) { |
| 371 for (size_t i = 0; i < arraysize(kAcceleratorMap); ++i) { | |
| 372 if (kAcceleratorMap[i].keyval == accel_key && | |
| 373 kAcceleratorMap[i].modifier_type == modifier) | |
| 374 return kAcceleratorMap[i].command_id; | |
| 375 } | |
| 376 | |
| 377 return -1; | |
| 378 } | |
| 379 | |
| 380 int GetCustomCommandId(guint keyval, GdkModifierType modifier) { | |
| 381 // Filter modifier to only include accelerator modifiers. | |
| 382 modifier = static_cast<GdkModifierType>( | |
| 383 modifier & gtk_accelerator_get_default_mod_mask()); | |
| 384 | |
| 385 switch (keyval) { | |
| 386 // Gtk doesn't allow GDK_Tab or GDK_ISO_Left_Tab to be an accelerator (see | 364 // Gtk doesn't allow GDK_Tab or GDK_ISO_Left_Tab to be an accelerator (see |
| 387 // gtk_accelerator_valid), so we need to handle these accelerators | 365 // gtk_accelerator_valid), so we need to handle these accelerators |
| 388 // manually. | 366 // manually. |
| 389 // Some X clients (e.g. cygwin, NX client, etc.) also send GDK_KP_Tab when | 367 // Some X clients (e.g. cygwin, NX client, etc.) also send GDK_KP_Tab when |
| 390 // typing a tab key. We should also handle GDK_KP_Tab for such X clients as | 368 // typing a tab key. We should also handle GDK_KP_Tab for such X clients as |
| 391 // Firefox does. | 369 // Firefox does. |
| 392 case GDK_Tab: | 370 case GDK_Tab: |
| 393 case GDK_ISO_Left_Tab: | 371 case GDK_ISO_Left_Tab: |
| 394 case GDK_KP_Tab: | 372 case GDK_KP_Tab: |
| 395 if (GDK_CONTROL_MASK == modifier) { | 373 if (GDK_CONTROL_MASK == modifier) { |
| 396 return IDC_SELECT_NEXT_TAB; | 374 return IDC_SELECT_NEXT_TAB; |
| 397 } else if ((GDK_CONTROL_MASK | GDK_SHIFT_MASK) == modifier) { | 375 } else if ((GDK_CONTROL_MASK | GDK_SHIFT_MASK) == modifier) { |
| 398 return IDC_SELECT_PREVIOUS_TAB; | 376 return IDC_SELECT_PREVIOUS_TAB; |
| 399 } | 377 } |
| 400 break; | 378 break; |
| 401 | 379 |
| 402 default: | 380 default: |
| 403 break; | 381 break; |
| 404 } | 382 } |
| 405 return -1; | 383 return -1; |
| 406 } | 384 } |
| 407 | 385 |
| 408 // An event handler for key press events. We need to special case key | 386 // Get the command ids of the accelerators that we don't want the native widget |
| 409 // combinations that are not valid gtk accelerators. This function returns | 387 // to be able to override. |
| 410 // TRUE if it can handle the key press. | 388 int GetPreHandleCommandId(GdkEventKey* event) { |
| 411 gboolean HandleCustomAccelerator(guint keyval, GdkModifierType modifier, | |
| 412 Browser* browser) { | |
| 413 int command = GetCustomCommandId(keyval, modifier); | |
| 414 if (command == -1) | |
| 415 return FALSE; | |
| 416 | |
| 417 browser->ExecuteCommand(command); | |
| 418 return TRUE; | |
| 419 } | |
| 420 | |
| 421 // Handle accelerators that we don't want the native widget to be able to | |
| 422 // override. | |
| 423 gboolean PreHandleAccelerator(guint keyval, GdkModifierType modifier, | |
| 424 Browser* browser) { | |
| 425 // Filter modifier to only include accelerator modifiers. | 389 // Filter modifier to only include accelerator modifiers. |
| 426 modifier = static_cast<GdkModifierType>( | 390 guint modifier = event->state & gtk_accelerator_get_default_mod_mask(); |
| 427 modifier & gtk_accelerator_get_default_mod_mask()); | 391 switch (event->keyval) { |
| 428 switch (keyval) { | |
| 429 case GDK_Page_Down: | 392 case GDK_Page_Down: |
| 430 if (GDK_CONTROL_MASK == modifier) { | 393 if (GDK_CONTROL_MASK == modifier) { |
| 431 browser->ExecuteCommand(IDC_SELECT_NEXT_TAB); | 394 return IDC_SELECT_NEXT_TAB; |
| 432 return TRUE; | |
| 433 } else if ((GDK_CONTROL_MASK | GDK_SHIFT_MASK) == modifier) { | 395 } else if ((GDK_CONTROL_MASK | GDK_SHIFT_MASK) == modifier) { |
| 434 browser->ExecuteCommand(IDC_MOVE_TAB_NEXT); | 396 return IDC_MOVE_TAB_NEXT; |
| 435 return TRUE; | |
| 436 } | 397 } |
| 437 break; | 398 break; |
| 438 | 399 |
| 439 case GDK_Page_Up: | 400 case GDK_Page_Up: |
| 440 if (GDK_CONTROL_MASK == modifier) { | 401 if (GDK_CONTROL_MASK == modifier) { |
| 441 browser->ExecuteCommand(IDC_SELECT_PREVIOUS_TAB); | 402 return IDC_SELECT_PREVIOUS_TAB; |
| 442 return TRUE; | |
| 443 } else if ((GDK_CONTROL_MASK | GDK_SHIFT_MASK) == modifier) { | 403 } else if ((GDK_CONTROL_MASK | GDK_SHIFT_MASK) == modifier) { |
| 444 browser->ExecuteCommand(IDC_MOVE_TAB_PREVIOUS); | 404 return IDC_MOVE_TAB_PREVIOUS; |
| 445 return TRUE; | |
| 446 } | 405 } |
| 447 break; | 406 break; |
| 448 | 407 |
| 449 default: | 408 default: |
| 450 break; | 409 break; |
| 451 } | 410 } |
| 452 return FALSE; | 411 return -1; |
| 453 } | |
| 454 | |
| 455 // Let the focused widget have first crack at the key event so we don't | |
| 456 // override their accelerators. | |
| 457 gboolean OnKeyPress(GtkWindow* window, GdkEventKey* event, Browser* browser) { | |
| 458 // If a widget besides the native view is focused, we have to try to handle | |
| 459 // the custom accelerators before letting it handle them. | |
| 460 TabContents* current_tab_contents = | |
| 461 browser->tabstrip_model()->GetSelectedTabContents(); | |
| 462 // The current tab might not have a render view if it crashed. | |
| 463 if (!current_tab_contents || !current_tab_contents->GetContentNativeView() || | |
| 464 !gtk_widget_is_focus(current_tab_contents->GetContentNativeView())) { | |
| 465 if (HandleCustomAccelerator(event->keyval, | |
| 466 GdkModifierType(event->state), browser) || | |
| 467 PreHandleAccelerator(event->keyval, | |
| 468 GdkModifierType(event->state), browser)) { | |
| 469 return TRUE; | |
| 470 } | |
| 471 | |
| 472 // Propagate the key event to child widget first, so we don't override their | |
| 473 // accelerators. | |
| 474 if (!gtk_window_propagate_key_event(window, event)) { | |
| 475 if (!gtk_window_activate_key(window, event)) { | |
| 476 gtk_bindings_activate_event(GTK_OBJECT(window), event); | |
| 477 } | |
| 478 } | |
| 479 } else { | |
| 480 bool rv = gtk_window_propagate_key_event(window, event); | |
| 481 DCHECK(rv); | |
| 482 } | |
| 483 | |
| 484 // Prevents the default handler from handling this event. | |
| 485 return TRUE; | |
| 486 } | 412 } |
| 487 | 413 |
| 488 GdkCursorType GdkWindowEdgeToGdkCursorType(GdkWindowEdge edge) { | 414 GdkCursorType GdkWindowEdgeToGdkCursorType(GdkWindowEdge edge) { |
| 489 switch (edge) { | 415 switch (edge) { |
| 490 case GDK_WINDOW_EDGE_NORTH_WEST: | 416 case GDK_WINDOW_EDGE_NORTH_WEST: |
| 491 return GDK_TOP_LEFT_CORNER; | 417 return GDK_TOP_LEFT_CORNER; |
| 492 case GDK_WINDOW_EDGE_NORTH: | 418 case GDK_WINDOW_EDGE_NORTH: |
| 493 return GDK_TOP_SIDE; | 419 return GDK_TOP_SIDE; |
| 494 case GDK_WINDOW_EDGE_NORTH_EAST: | 420 case GDK_WINDOW_EDGE_NORTH_EAST: |
| 495 return GDK_TOP_RIGHT_CORNER; | 421 return GDK_TOP_RIGHT_CORNER; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 521 GdkScreen* screen = gdk_screen_get_default(); | 447 GdkScreen* screen = gdk_screen_get_default(); |
| 522 if (width == gdk_screen_get_width(screen) && | 448 if (width == gdk_screen_get_width(screen) && |
| 523 height == gdk_screen_get_height(screen)) { | 449 height == gdk_screen_get_height(screen)) { |
| 524 // Adjust the height so we don't trigger the WM feature. | 450 // Adjust the height so we don't trigger the WM feature. |
| 525 gtk_window_resize(window, width, height - 1); | 451 gtk_window_resize(window, width, height - 1); |
| 526 } else { | 452 } else { |
| 527 gtk_window_resize(window, width, height); | 453 gtk_window_resize(window, width, height); |
| 528 } | 454 } |
| 529 } | 455 } |
| 530 | 456 |
| 457 GQuark GetBrowserWindowQuarkKey() { |
| 458 static GQuark quark = g_quark_from_static_string(kBrowserWindowKey); |
| 459 return quark; |
| 460 } |
| 461 |
| 462 // Checks if a reserved accelerator key should be processed immediately, rather |
| 463 // than being sent to the renderer first. |
| 464 bool ShouldExecuteReservedCommandImmediately( |
| 465 const NativeWebKeyboardEvent& event, int command_id) { |
| 466 // IDC_EXIT is now only bound to Ctrl+Shift+q, so we should always execute it |
| 467 // immediately. |
| 468 if (command_id == IDC_EXIT) |
| 469 return true; |
| 470 |
| 471 // Keys like Ctrl+w, Ctrl+n, etc. should always be sent to the renderer first, |
| 472 // otherwise some web apps or the Emacs key bindings may not work correctly. |
| 473 int vkey = event.windowsKeyCode; |
| 474 if ((vkey >= base::VKEY_0 && vkey <= base::VKEY_9) || |
| 475 (vkey >= base::VKEY_A && vkey <= base::VKEY_Z)) |
| 476 return false; |
| 477 |
| 478 // All other reserved accelerators should be processed immediately. |
| 479 return true; |
| 480 } |
| 481 |
| 531 } // namespace | 482 } // namespace |
| 532 | 483 |
| 533 std::map<XID, GtkWindow*> BrowserWindowGtk::xid_map_; | 484 std::map<XID, GtkWindow*> BrowserWindowGtk::xid_map_; |
| 534 | 485 |
| 535 #if defined(OS_CHROMEOS) | 486 #if defined(OS_CHROMEOS) |
| 536 // Default to using the regular window style. | 487 // Default to using the regular window style. |
| 537 bool BrowserWindowGtk::next_window_should_use_compact_nav_ = false; | 488 bool BrowserWindowGtk::next_window_should_use_compact_nav_ = false; |
| 538 #endif | 489 #endif |
| 539 | 490 |
| 540 BrowserWindowGtk::BrowserWindowGtk(Browser* browser) | 491 BrowserWindowGtk::BrowserWindowGtk(Browser* browser) |
| 541 : browser_(browser), | 492 : browser_(browser), |
| 542 state_(GDK_WINDOW_STATE_WITHDRAWN), | 493 state_(GDK_WINDOW_STATE_WITHDRAWN), |
| 543 #if defined(OS_CHROMEOS) | 494 #if defined(OS_CHROMEOS) |
| 544 drag_active_(false), | 495 drag_active_(false), |
| 545 panel_controller_(NULL), | 496 panel_controller_(NULL), |
| 546 compact_navigation_bar_(NULL), | 497 compact_navigation_bar_(NULL), |
| 547 status_area_(NULL), | 498 status_area_(NULL), |
| 548 main_menu_button_(NULL), | 499 main_menu_button_(NULL), |
| 549 compact_navbar_hbox_(NULL), | 500 compact_navbar_hbox_(NULL), |
| 550 #endif | 501 #endif |
| 551 frame_cursor_(NULL), | 502 frame_cursor_(NULL), |
| 552 is_active_(true), | 503 is_active_(true), |
| 553 last_click_time_(0), | 504 last_click_time_(0), |
| 554 maximize_after_show_(false), | 505 maximize_after_show_(false), |
| 555 accel_group_(NULL) { | 506 accel_group_(NULL) { |
| 556 use_custom_frame_pref_.Init(prefs::kUseCustomChromeFrame, | 507 use_custom_frame_pref_.Init(prefs::kUseCustomChromeFrame, |
| 557 browser_->profile()->GetPrefs(), this); | 508 browser_->profile()->GetPrefs(), this); |
| 558 | 509 |
| 559 window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL)); | 510 window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL)); |
| 560 g_object_set_data(G_OBJECT(window_), kBrowserWindowKey, this); | 511 g_object_set_qdata(G_OBJECT(window_), GetBrowserWindowQuarkKey(), this); |
| 561 gtk_widget_add_events(GTK_WIDGET(window_), GDK_BUTTON_PRESS_MASK | | 512 gtk_widget_add_events(GTK_WIDGET(window_), GDK_BUTTON_PRESS_MASK | |
| 562 GDK_POINTER_MOTION_MASK); | 513 GDK_POINTER_MOTION_MASK); |
| 563 | 514 |
| 564 // Add this window to its own unique window group to allow for | 515 // Add this window to its own unique window group to allow for |
| 565 // window-to-parent modality. | 516 // window-to-parent modality. |
| 566 gtk_window_group_add_window(gtk_window_group_new(), window_); | 517 gtk_window_group_add_window(gtk_window_group_new(), window_); |
| 567 g_object_unref(gtk_window_get_group(window_)); | 518 g_object_unref(gtk_window_get_group(window_)); |
| 568 | 519 |
| 569 // For popups, we initialize widgets then set the window geometry, because | 520 // For popups, we initialize widgets then set the window geometry, because |
| 570 // popups need the widgets inited before they can set the window size | 521 // popups need the widgets inited before they can set the window size |
| (...skipping 23 matching lines...) Expand all Loading... |
| 594 ActiveWindowWatcherX::RemoveObserver(this); | 545 ActiveWindowWatcherX::RemoveObserver(this); |
| 595 | 546 |
| 596 browser_->tabstrip_model()->RemoveObserver(this); | 547 browser_->tabstrip_model()->RemoveObserver(this); |
| 597 | 548 |
| 598 if (frame_cursor_) { | 549 if (frame_cursor_) { |
| 599 gdk_cursor_unref(frame_cursor_); | 550 gdk_cursor_unref(frame_cursor_); |
| 600 frame_cursor_ = NULL; | 551 frame_cursor_ = NULL; |
| 601 } | 552 } |
| 602 } | 553 } |
| 603 | 554 |
| 604 bool BrowserWindowGtk::HandleKeyboardEvent(GdkEventKey* event) { | |
| 605 // Handles a key event in following sequence: | |
| 606 // 1. Our special key accelerators, such as ctrl-tab, etc. | |
| 607 // 2. Gtk mnemonics and accelerators. | |
| 608 // This sequence matches the default key press handler of GtkWindow. | |
| 609 // | |
| 610 // It's not necessary to care about the keyboard layout, as | |
| 611 // gtk_window_activate_key() takes care of it automatically. | |
| 612 if (!HandleCustomAccelerator(event->keyval, GdkModifierType(event->state), | |
| 613 browser_.get())) { | |
| 614 return gtk_window_activate_key(window_, event); | |
| 615 } | |
| 616 return true; | |
| 617 } | |
| 618 | |
| 619 gboolean BrowserWindowGtk::OnCustomFrameExpose(GtkWidget* widget, | 555 gboolean BrowserWindowGtk::OnCustomFrameExpose(GtkWidget* widget, |
| 620 GdkEventExpose* event, | 556 GdkEventExpose* event, |
| 621 BrowserWindowGtk* window) { | 557 BrowserWindowGtk* window) { |
| 622 GtkThemeProvider* theme_provider = GtkThemeProvider::GetFrom( | 558 GtkThemeProvider* theme_provider = GtkThemeProvider::GetFrom( |
| 623 window->browser()->profile()); | 559 window->browser()->profile()); |
| 624 | 560 |
| 625 // Draw the default background. | 561 // Draw the default background. |
| 626 cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(widget->window)); | 562 cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(widget->window)); |
| 627 cairo_rectangle(cr, event->area.x, event->area.y, event->area.width, | 563 cairo_rectangle(cr, event->area.x, event->area.y, event->area.width, |
| 628 event->area.height); | 564 event->area.height); |
| (...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1202 // (Alt+e). We connect the accelerator directly to the widget in | 1138 // (Alt+e). We connect the accelerator directly to the widget in |
| 1203 // BrowserToolbarGtk. | 1139 // BrowserToolbarGtk. |
| 1204 } | 1140 } |
| 1205 | 1141 |
| 1206 void BrowserWindowGtk::ShowAppMenu() { | 1142 void BrowserWindowGtk::ShowAppMenu() { |
| 1207 // On Windows, this is used to show the page menu for a keyboard accelerator | 1143 // On Windows, this is used to show the page menu for a keyboard accelerator |
| 1208 // (Alt+f). We connect the accelerator directly to the widget in | 1144 // (Alt+f). We connect the accelerator directly to the widget in |
| 1209 // BrowserToolbarGtk. | 1145 // BrowserToolbarGtk. |
| 1210 } | 1146 } |
| 1211 | 1147 |
| 1212 int BrowserWindowGtk::GetCommandId(const NativeWebKeyboardEvent& event) { | 1148 bool BrowserWindowGtk::PreHandleKeyboardEvent( |
| 1213 if (!event.os_event) | 1149 const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut) { |
| 1214 return -1; | 1150 GdkEventKey* os_event = event.os_event; |
| 1215 | 1151 |
| 1216 guint keyval = event.os_event->keyval; | 1152 if (!os_event || event.type != WebKit::WebInputEvent::RawKeyDown) |
| 1217 GdkModifierType modifier = GdkModifierType(event.os_event->state); | 1153 return false; |
| 1218 int command = ::GetCommandId(keyval, modifier); | 1154 |
| 1219 if (command == -1) | 1155 // We first find out the browser command associated to the |event|. |
| 1220 command = GetCustomCommandId(keyval, modifier); | 1156 // Then if the command is a reserved one, and should be processed immediately |
| 1221 return command; | 1157 // according to the |event|, the command will be executed immediately. |
| 1158 // Otherwise we just set |*is_keyboard_shortcut| properly and return false. |
| 1159 |
| 1160 // First check if it's a custom accelerator. |
| 1161 int id = GetCustomCommandId(os_event); |
| 1162 |
| 1163 // Then check if it's a predefined accelerator bound to the window. |
| 1164 if (id == -1) { |
| 1165 // This piece of code is based on the fact that calling |
| 1166 // gtk_window_activate_key() method against |window_| may only trigger a |
| 1167 // browser command execution, by matching either a global accelerator |
| 1168 // defined in above |kAcceleratorMap| or the accelerator key of a menu |
| 1169 // item defined in chrome/browser/gtk/standard_menus.cc. |
| 1170 // |
| 1171 // Here we need to retrieve the command id (if any) associated to the |
| 1172 // keyboard event. Instead of looking up the command id in above |
| 1173 // |kAcceleratorMap| table by ourselves, we block the command execution of |
| 1174 // the |browser_| object then send the keyboard event to the |window_| by |
| 1175 // calling gtk_window_activate_key() method, as if we are activating an |
| 1176 // accelerator key. Then we can retrieve the command id from the |
| 1177 // |browser_| object. |
| 1178 // |
| 1179 // Pros of this approach: |
| 1180 // 1. We can handle accelerators defined not only in above |
| 1181 // |kAcceleratorMap| table, but also those in standard_menus.cc. |
| 1182 // 2. We don't need to care about keyboard layout problem, as |
| 1183 // gtk_window_activate_key() method handles it for us. |
| 1184 // |
| 1185 // Cons: |
| 1186 // 1. The logic is a little complicated. |
| 1187 // 2. We should be careful not to introduce any accelerators that trigger |
| 1188 // customized code instead of browser commands. |
| 1189 browser_->SetBlockCommandExecution(true); |
| 1190 gtk_window_activate_key(window_, os_event); |
| 1191 // We don't need to care about the WindowOpenDisposition value, |
| 1192 // because all commands executed in this path use the default value. |
| 1193 id = browser_->GetLastBlockedCommand(NULL); |
| 1194 browser_->SetBlockCommandExecution(false); |
| 1195 } |
| 1196 |
| 1197 if (id == -1) |
| 1198 return false; |
| 1199 |
| 1200 if (browser_->IsReservedCommand(id) && |
| 1201 ShouldExecuteReservedCommandImmediately(event, id)) { |
| 1202 // Executing the command may cause |this| object to be destroyed. |
| 1203 return ExecuteBrowserCommand(id); |
| 1204 } |
| 1205 |
| 1206 // The |event| is a keyboard shortcut. |
| 1207 DCHECK(is_keyboard_shortcut != NULL); |
| 1208 *is_keyboard_shortcut = true; |
| 1209 |
| 1210 return false; |
| 1211 } |
| 1212 |
| 1213 void BrowserWindowGtk::HandleKeyboardEvent( |
| 1214 const NativeWebKeyboardEvent& event) { |
| 1215 GdkEventKey* os_event = event.os_event; |
| 1216 |
| 1217 if (!os_event || event.type != WebKit::WebInputEvent::RawKeyDown) |
| 1218 return; |
| 1219 |
| 1220 // Handles a key event in following sequence: |
| 1221 // 1. Our special key accelerators, such as ctrl-tab, etc. |
| 1222 // 2. Gtk accelerators. |
| 1223 // This sequence matches the default key press handler of GtkWindow. |
| 1224 // |
| 1225 // It's not necessary to care about the keyboard layout, as |
| 1226 // gtk_window_activate_key() takes care of it automatically. |
| 1227 int id = GetCustomCommandId(os_event); |
| 1228 if (id != -1) |
| 1229 ExecuteBrowserCommand(id); |
| 1230 else |
| 1231 gtk_window_activate_key(window_, os_event); |
| 1222 } | 1232 } |
| 1223 | 1233 |
| 1224 void BrowserWindowGtk::ShowCreateShortcutsDialog(TabContents* tab_contents) { | 1234 void BrowserWindowGtk::ShowCreateShortcutsDialog(TabContents* tab_contents) { |
| 1225 SkBitmap bitmap; | 1235 SkBitmap bitmap; |
| 1226 if (tab_contents->FavIconIsValid()) | 1236 if (tab_contents->FavIconIsValid()) |
| 1227 bitmap = tab_contents->GetFavIcon(); | 1237 bitmap = tab_contents->GetFavIcon(); |
| 1228 CreateApplicationShortcutsDialogGtk::Show(window_, | 1238 CreateApplicationShortcutsDialogGtk::Show(window_, |
| 1229 tab_contents->GetURL(), | 1239 tab_contents->GetURL(), |
| 1230 tab_contents->GetTitle(), | 1240 tab_contents->GetTitle(), |
| 1231 bitmap); | 1241 bitmap); |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1537 gdk_cursor_unref(frame_cursor_); | 1547 gdk_cursor_unref(frame_cursor_); |
| 1538 frame_cursor_ = NULL; | 1548 frame_cursor_ = NULL; |
| 1539 gdk_window_set_cursor(GTK_WIDGET(window_)->window, NULL); | 1549 gdk_window_set_cursor(GTK_WIDGET(window_)->window, NULL); |
| 1540 } | 1550 } |
| 1541 | 1551 |
| 1542 // static | 1552 // static |
| 1543 BrowserWindowGtk* BrowserWindowGtk::GetBrowserWindowForNativeWindow( | 1553 BrowserWindowGtk* BrowserWindowGtk::GetBrowserWindowForNativeWindow( |
| 1544 gfx::NativeWindow window) { | 1554 gfx::NativeWindow window) { |
| 1545 if (window) { | 1555 if (window) { |
| 1546 return static_cast<BrowserWindowGtk*>( | 1556 return static_cast<BrowserWindowGtk*>( |
| 1547 g_object_get_data(G_OBJECT(window), kBrowserWindowKey)); | 1557 g_object_get_qdata(G_OBJECT(window), GetBrowserWindowQuarkKey())); |
| 1548 } | 1558 } |
| 1549 | 1559 |
| 1550 return NULL; | 1560 return NULL; |
| 1551 } | 1561 } |
| 1552 | 1562 |
| 1553 // static | 1563 // static |
| 1554 GtkWindow* BrowserWindowGtk::GetBrowserWindowForXID(XID xid) { | 1564 GtkWindow* BrowserWindowGtk::GetBrowserWindowForXID(XID xid) { |
| 1555 std::map<XID, GtkWindow*>::iterator iter = | 1565 std::map<XID, GtkWindow*>::iterator iter = |
| 1556 BrowserWindowGtk::xid_map_.find(xid); | 1566 BrowserWindowGtk::xid_map_.find(xid); |
| 1557 return (iter != BrowserWindowGtk::xid_map_.end()) ? iter->second : NULL; | 1567 return (iter != BrowserWindowGtk::xid_map_.end()) ? iter->second : NULL; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1621 G_CALLBACK(MainWindowDestroy), this); | 1631 G_CALLBACK(MainWindowDestroy), this); |
| 1622 g_signal_connect(window_, "configure-event", | 1632 g_signal_connect(window_, "configure-event", |
| 1623 G_CALLBACK(MainWindowConfigured), this); | 1633 G_CALLBACK(MainWindowConfigured), this); |
| 1624 g_signal_connect(window_, "window-state-event", | 1634 g_signal_connect(window_, "window-state-event", |
| 1625 G_CALLBACK(MainWindowStateChanged), this); | 1635 G_CALLBACK(MainWindowStateChanged), this); |
| 1626 g_signal_connect(window_, "map", | 1636 g_signal_connect(window_, "map", |
| 1627 G_CALLBACK(MainWindowMapped), this); | 1637 G_CALLBACK(MainWindowMapped), this); |
| 1628 g_signal_connect(window_, "unmap", | 1638 g_signal_connect(window_, "unmap", |
| 1629 G_CALLBACK(MainWindowUnMapped), this); | 1639 G_CALLBACK(MainWindowUnMapped), this); |
| 1630 g_signal_connect(window_, "key-press-event", | 1640 g_signal_connect(window_, "key-press-event", |
| 1631 G_CALLBACK(OnKeyPress), browser_.get()); | 1641 G_CALLBACK(OnKeyPress), this); |
| 1632 g_signal_connect(window_, "motion-notify-event", | 1642 g_signal_connect(window_, "motion-notify-event", |
| 1633 G_CALLBACK(OnMouseMoveEvent), this); | 1643 G_CALLBACK(OnMouseMoveEvent), this); |
| 1634 g_signal_connect(window_, "button-press-event", | 1644 g_signal_connect(window_, "button-press-event", |
| 1635 G_CALLBACK(OnButtonPressEvent), this); | 1645 G_CALLBACK(OnButtonPressEvent), this); |
| 1636 g_signal_connect(window_, "focus-in-event", | 1646 g_signal_connect(window_, "focus-in-event", |
| 1637 G_CALLBACK(OnFocusIn), this); | 1647 G_CALLBACK(OnFocusIn), this); |
| 1638 g_signal_connect(window_, "focus-out-event", | 1648 g_signal_connect(window_, "focus-out-event", |
| 1639 G_CALLBACK(OnFocusOut), this); | 1649 G_CALLBACK(OnFocusOut), this); |
| 1640 } | 1650 } |
| 1641 | 1651 |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1939 void BrowserWindowGtk::ConnectAccelerators() { | 1949 void BrowserWindowGtk::ConnectAccelerators() { |
| 1940 accel_group_ = gtk_accel_group_new(); | 1950 accel_group_ = gtk_accel_group_new(); |
| 1941 gtk_window_add_accel_group(window_, accel_group_); | 1951 gtk_window_add_accel_group(window_, accel_group_); |
| 1942 | 1952 |
| 1943 for (size_t i = 0; i < arraysize(kAcceleratorMap); ++i) { | 1953 for (size_t i = 0; i < arraysize(kAcceleratorMap); ++i) { |
| 1944 gtk_accel_group_connect( | 1954 gtk_accel_group_connect( |
| 1945 accel_group_, | 1955 accel_group_, |
| 1946 kAcceleratorMap[i].keyval, | 1956 kAcceleratorMap[i].keyval, |
| 1947 kAcceleratorMap[i].modifier_type, | 1957 kAcceleratorMap[i].modifier_type, |
| 1948 GtkAccelFlags(0), | 1958 GtkAccelFlags(0), |
| 1949 g_cclosure_new(G_CALLBACK(OnGtkAccelerator), this, NULL)); | 1959 g_cclosure_new(G_CALLBACK(OnGtkAccelerator), |
| 1960 GINT_TO_POINTER(kAcceleratorMap[i].command_id), NULL)); |
| 1950 } | 1961 } |
| 1951 } | 1962 } |
| 1952 | 1963 |
| 1953 void BrowserWindowGtk::UpdateCustomFrame() { | 1964 void BrowserWindowGtk::UpdateCustomFrame() { |
| 1954 gtk_window_set_decorated(window_, !UseCustomFrame()); | 1965 gtk_window_set_decorated(window_, !UseCustomFrame()); |
| 1955 titlebar_->UpdateCustomFrame(UseCustomFrame() && !IsFullscreen()); | 1966 titlebar_->UpdateCustomFrame(UseCustomFrame() && !IsFullscreen()); |
| 1956 UpdateWindowShape(bounds_.width(), bounds_.height()); | 1967 UpdateWindowShape(bounds_.width(), bounds_.height()); |
| 1957 } | 1968 } |
| 1958 | 1969 |
| 1959 void BrowserWindowGtk::SaveWindowPosition() { | 1970 void BrowserWindowGtk::SaveWindowPosition() { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1988 window_preferences->SetInteger(L"work_area_top", work_area.y()); | 1999 window_preferences->SetInteger(L"work_area_top", work_area.y()); |
| 1989 window_preferences->SetInteger(L"work_area_right", work_area.right()); | 2000 window_preferences->SetInteger(L"work_area_right", work_area.right()); |
| 1990 window_preferences->SetInteger(L"work_area_bottom", work_area.bottom()); | 2001 window_preferences->SetInteger(L"work_area_bottom", work_area.bottom()); |
| 1991 } | 2002 } |
| 1992 | 2003 |
| 1993 // static | 2004 // static |
| 1994 gboolean BrowserWindowGtk::OnGtkAccelerator(GtkAccelGroup* accel_group, | 2005 gboolean BrowserWindowGtk::OnGtkAccelerator(GtkAccelGroup* accel_group, |
| 1995 GObject* acceleratable, | 2006 GObject* acceleratable, |
| 1996 guint keyval, | 2007 guint keyval, |
| 1997 GdkModifierType modifier, | 2008 GdkModifierType modifier, |
| 1998 BrowserWindowGtk* browser_window) { | 2009 void* user_data) { |
| 1999 int command_id = ::GetCommandId(keyval, modifier); | 2010 int command_id = GPOINTER_TO_INT(user_data); |
| 2000 DCHECK_NE(command_id, -1); | 2011 BrowserWindowGtk* browser_window = |
| 2001 browser_window->ExecuteBrowserCommand(command_id); | 2012 GetBrowserWindowForNativeWindow(GTK_WINDOW(acceleratable)); |
| 2013 DCHECK(browser_window != NULL); |
| 2014 return browser_window->ExecuteBrowserCommand(command_id); |
| 2015 } |
| 2002 | 2016 |
| 2017 // static |
| 2018 // Let the focused widget have first crack at the key event so we don't |
| 2019 // override their accelerators. |
| 2020 gboolean BrowserWindowGtk::OnKeyPress( |
| 2021 GtkWidget* widget, GdkEventKey* event, BrowserWindowGtk* window) { |
| 2022 // If a widget besides the native view is focused, we have to try to handle |
| 2023 // the custom accelerators before letting it handle them. |
| 2024 TabContents* current_tab_contents = |
| 2025 window->browser()->tabstrip_model()->GetSelectedTabContents(); |
| 2026 // The current tab might not have a render view if it crashed. |
| 2027 if (!current_tab_contents || !current_tab_contents->GetContentNativeView() || |
| 2028 !gtk_widget_is_focus(current_tab_contents->GetContentNativeView())) { |
| 2029 int command_id = GetCustomCommandId(event); |
| 2030 if (command_id == -1) |
| 2031 command_id = GetPreHandleCommandId(event); |
| 2032 |
| 2033 if (command_id != -1 && window->ExecuteBrowserCommand(command_id)) |
| 2034 return TRUE; |
| 2035 |
| 2036 // Propagate the key event to child widget first, so we don't override their |
| 2037 // accelerators. |
| 2038 if (!gtk_window_propagate_key_event(GTK_WINDOW(widget), event)) { |
| 2039 if (!gtk_window_activate_key(GTK_WINDOW(widget), event)) { |
| 2040 gtk_bindings_activate_event(GTK_OBJECT(widget), event); |
| 2041 } |
| 2042 } |
| 2043 } else { |
| 2044 bool rv = gtk_window_propagate_key_event(GTK_WINDOW(widget), event); |
| 2045 DCHECK(rv); |
| 2046 } |
| 2047 |
| 2048 // Prevents the default handler from handling this event. |
| 2003 return TRUE; | 2049 return TRUE; |
| 2004 } | 2050 } |
| 2005 | 2051 |
| 2006 // static | 2052 // static |
| 2007 gboolean BrowserWindowGtk::OnMouseMoveEvent(GtkWidget* widget, | 2053 gboolean BrowserWindowGtk::OnMouseMoveEvent(GtkWidget* widget, |
| 2008 GdkEventMotion* event, BrowserWindowGtk* browser) { | 2054 GdkEventMotion* event, BrowserWindowGtk* window) { |
| 2009 // This method is used to update the mouse cursor when over the edge of the | 2055 // This method is used to update the mouse cursor when over the edge of the |
| 2010 // custom frame. If the custom frame is off or we're over some other widget, | 2056 // custom frame. If the custom frame is off or we're over some other widget, |
| 2011 // do nothing. | 2057 // do nothing. |
| 2012 if (!browser->UseCustomFrame() || event->window != widget->window) { | 2058 if (!window->UseCustomFrame() || event->window != widget->window) { |
| 2013 // Reset the cursor. | 2059 // Reset the cursor. |
| 2014 if (browser->frame_cursor_) { | 2060 if (window->frame_cursor_) { |
| 2015 gdk_cursor_unref(browser->frame_cursor_); | 2061 gdk_cursor_unref(window->frame_cursor_); |
| 2016 browser->frame_cursor_ = NULL; | 2062 window->frame_cursor_ = NULL; |
| 2017 gdk_window_set_cursor(GTK_WIDGET(browser->window_)->window, NULL); | 2063 gdk_window_set_cursor(GTK_WIDGET(window->window_)->window, NULL); |
| 2018 } | 2064 } |
| 2019 return FALSE; | 2065 return FALSE; |
| 2020 } | 2066 } |
| 2021 | 2067 |
| 2022 // Update the cursor if we're on the custom frame border. | 2068 // Update the cursor if we're on the custom frame border. |
| 2023 GdkWindowEdge edge; | 2069 GdkWindowEdge edge; |
| 2024 bool has_hit_edge = browser->GetWindowEdge(static_cast<int>(event->x), | 2070 bool has_hit_edge = window->GetWindowEdge(static_cast<int>(event->x), |
| 2025 static_cast<int>(event->y), &edge); | 2071 static_cast<int>(event->y), &edge); |
| 2026 GdkCursorType new_cursor = GDK_LAST_CURSOR; | 2072 GdkCursorType new_cursor = GDK_LAST_CURSOR; |
| 2027 if (has_hit_edge) | 2073 if (has_hit_edge) |
| 2028 new_cursor = GdkWindowEdgeToGdkCursorType(edge); | 2074 new_cursor = GdkWindowEdgeToGdkCursorType(edge); |
| 2029 | 2075 |
| 2030 GdkCursorType last_cursor = GDK_LAST_CURSOR; | 2076 GdkCursorType last_cursor = GDK_LAST_CURSOR; |
| 2031 if (browser->frame_cursor_) | 2077 if (window->frame_cursor_) |
| 2032 last_cursor = browser->frame_cursor_->type; | 2078 last_cursor = window->frame_cursor_->type; |
| 2033 | 2079 |
| 2034 if (last_cursor != new_cursor) { | 2080 if (last_cursor != new_cursor) { |
| 2035 if (browser->frame_cursor_) { | 2081 if (window->frame_cursor_) { |
| 2036 gdk_cursor_unref(browser->frame_cursor_); | 2082 gdk_cursor_unref(window->frame_cursor_); |
| 2037 browser->frame_cursor_ = NULL; | 2083 window->frame_cursor_ = NULL; |
| 2038 } | 2084 } |
| 2039 if (has_hit_edge) { | 2085 if (has_hit_edge) { |
| 2040 browser->frame_cursor_ = gtk_util::GetCursor(new_cursor); | 2086 window->frame_cursor_ = gtk_util::GetCursor(new_cursor); |
| 2041 gdk_window_set_cursor(GTK_WIDGET(browser->window_)->window, | 2087 gdk_window_set_cursor(GTK_WIDGET(window->window_)->window, |
| 2042 browser->frame_cursor_); | 2088 window->frame_cursor_); |
| 2043 } else { | 2089 } else { |
| 2044 gdk_window_set_cursor(GTK_WIDGET(browser->window_)->window, NULL); | 2090 gdk_window_set_cursor(GTK_WIDGET(window->window_)->window, NULL); |
| 2045 } | 2091 } |
| 2046 } | 2092 } |
| 2047 return FALSE; | 2093 return FALSE; |
| 2048 } | 2094 } |
| 2049 | 2095 |
| 2050 // static | 2096 // static |
| 2051 gboolean BrowserWindowGtk::OnButtonPressEvent(GtkWidget* widget, | 2097 gboolean BrowserWindowGtk::OnButtonPressEvent(GtkWidget* widget, |
| 2052 GdkEventButton* event, BrowserWindowGtk* browser) { | 2098 GdkEventButton* event, BrowserWindowGtk* window) { |
| 2053 // Handle back/forward. | 2099 // Handle back/forward. |
| 2054 // TODO(jhawkins): Investigate the possibility of the button numbers being | 2100 // TODO(jhawkins): Investigate the possibility of the button numbers being |
| 2055 // different for other mice. | 2101 // different for other mice. |
| 2056 if (event->button == 8) { | 2102 if (event->button == 8) { |
| 2057 browser->browser_->GoBack(CURRENT_TAB); | 2103 window->browser_->GoBack(CURRENT_TAB); |
| 2058 return TRUE; | 2104 return TRUE; |
| 2059 } else if (event->button == 9) { | 2105 } else if (event->button == 9) { |
| 2060 browser->browser_->GoForward(CURRENT_TAB); | 2106 window->browser_->GoForward(CURRENT_TAB); |
| 2061 return TRUE; | 2107 return TRUE; |
| 2062 } | 2108 } |
| 2063 | 2109 |
| 2064 // Handle left, middle and right clicks. In particular, we care about clicks | 2110 // Handle left, middle and right clicks. In particular, we care about clicks |
| 2065 // in the custom frame border and clicks in the titlebar. | 2111 // in the custom frame border and clicks in the titlebar. |
| 2066 | 2112 |
| 2067 // Make the button press coordinate relative to the browser window. | 2113 // Make the button press coordinate relative to the browser window. |
| 2068 int win_x, win_y; | 2114 int win_x, win_y; |
| 2069 gdk_window_get_origin(GTK_WIDGET(browser->window_)->window, &win_x, &win_y); | 2115 gdk_window_get_origin(GTK_WIDGET(window->window_)->window, &win_x, &win_y); |
| 2070 | 2116 |
| 2071 GdkWindowEdge edge; | 2117 GdkWindowEdge edge; |
| 2072 gfx::Point point(static_cast<int>(event->x_root - win_x), | 2118 gfx::Point point(static_cast<int>(event->x_root - win_x), |
| 2073 static_cast<int>(event->y_root - win_y)); | 2119 static_cast<int>(event->y_root - win_y)); |
| 2074 bool has_hit_edge = browser->GetWindowEdge(point.x(), point.y(), &edge); | 2120 bool has_hit_edge = window->GetWindowEdge(point.x(), point.y(), &edge); |
| 2075 | 2121 |
| 2076 // Ignore clicks that are in/below the browser toolbar. | 2122 // Ignore clicks that are in/below the browser toolbar. |
| 2077 GtkWidget* toolbar = browser->toolbar_->widget(); | 2123 GtkWidget* toolbar = window->toolbar_->widget(); |
| 2078 if (!GTK_WIDGET_VISIBLE(toolbar)) { | 2124 if (!GTK_WIDGET_VISIBLE(toolbar)) { |
| 2079 // If the toolbar is not showing, use the location of web contents as the | 2125 // If the toolbar is not showing, use the location of web contents as the |
| 2080 // boundary of where to ignore clicks. | 2126 // boundary of where to ignore clicks. |
| 2081 toolbar = browser->render_area_vbox_; | 2127 toolbar = window->render_area_vbox_; |
| 2082 } | 2128 } |
| 2083 gint toolbar_y; | 2129 gint toolbar_y; |
| 2084 gtk_widget_get_pointer(toolbar, NULL, &toolbar_y); | 2130 gtk_widget_get_pointer(toolbar, NULL, &toolbar_y); |
| 2085 bool has_hit_titlebar = !browser->IsFullscreen() && (toolbar_y < 0) | 2131 bool has_hit_titlebar = !window->IsFullscreen() && (toolbar_y < 0) |
| 2086 && !has_hit_edge; | 2132 && !has_hit_edge; |
| 2087 if (event->button == 1) { | 2133 if (event->button == 1) { |
| 2088 if (GDK_BUTTON_PRESS == event->type) { | 2134 if (GDK_BUTTON_PRESS == event->type) { |
| 2089 guint32 last_click_time = browser->last_click_time_; | 2135 guint32 last_click_time = window->last_click_time_; |
| 2090 gfx::Point last_click_position = browser->last_click_position_; | 2136 gfx::Point last_click_position = window->last_click_position_; |
| 2091 browser->last_click_time_ = event->time; | 2137 window->last_click_time_ = event->time; |
| 2092 browser->last_click_position_ = gfx::Point(static_cast<int>(event->x), | 2138 window->last_click_position_ = gfx::Point(static_cast<int>(event->x), |
| 2093 static_cast<int>(event->y)); | 2139 static_cast<int>(event->y)); |
| 2094 | 2140 |
| 2095 // Raise the window after a click on either the titlebar or the border to | 2141 // Raise the window after a click on either the titlebar or the border to |
| 2096 // match the behavior of most window managers. | 2142 // match the behavior of most window managers. |
| 2097 if (has_hit_titlebar || has_hit_edge) | 2143 if (has_hit_titlebar || has_hit_edge) |
| 2098 gdk_window_raise(GTK_WIDGET(browser->window_)->window); | 2144 gdk_window_raise(GTK_WIDGET(window->window_)->window); |
| 2099 | 2145 |
| 2100 if (has_hit_titlebar) { | 2146 if (has_hit_titlebar) { |
| 2101 // We want to start a move when the user single clicks, but not start a | 2147 // We want to start a move when the user single clicks, but not start a |
| 2102 // move when the user double clicks. However, a double click sends the | 2148 // move when the user double clicks. However, a double click sends the |
| 2103 // following GDK events: GDK_BUTTON_PRESS, GDK_BUTTON_RELEASE, | 2149 // following GDK events: GDK_BUTTON_PRESS, GDK_BUTTON_RELEASE, |
| 2104 // GDK_BUTTON_PRESS, GDK_2BUTTON_PRESS, GDK_BUTTON_RELEASE. If we | 2150 // GDK_BUTTON_PRESS, GDK_2BUTTON_PRESS, GDK_BUTTON_RELEASE. If we |
| 2105 // start a gtk_window_begin_move_drag on the second GDK_BUTTON_PRESS, | 2151 // start a gtk_window_begin_move_drag on the second GDK_BUTTON_PRESS, |
| 2106 // the call to gtk_window_maximize fails. To work around this, we | 2152 // the call to gtk_window_maximize fails. To work around this, we |
| 2107 // keep track of the last click and if it's going to be a double click, | 2153 // keep track of the last click and if it's going to be a double click, |
| 2108 // we don't call gtk_window_begin_move_drag. | 2154 // we don't call gtk_window_begin_move_drag. |
| 2109 static GtkSettings* settings = gtk_settings_get_default(); | 2155 static GtkSettings* settings = gtk_settings_get_default(); |
| 2110 gint double_click_time = 250; | 2156 gint double_click_time = 250; |
| 2111 gint double_click_distance = 5; | 2157 gint double_click_distance = 5; |
| 2112 g_object_get(G_OBJECT(settings), | 2158 g_object_get(G_OBJECT(settings), |
| 2113 "gtk-double-click-time", &double_click_time, | 2159 "gtk-double-click-time", &double_click_time, |
| 2114 "gtk-double-click-distance", &double_click_distance, | 2160 "gtk-double-click-distance", &double_click_distance, |
| 2115 NULL); | 2161 NULL); |
| 2116 | 2162 |
| 2117 guint32 click_time = event->time - last_click_time; | 2163 guint32 click_time = event->time - last_click_time; |
| 2118 int click_move_x = static_cast<int>(event->x - last_click_position.x()); | 2164 int click_move_x = static_cast<int>(event->x - last_click_position.x()); |
| 2119 int click_move_y = static_cast<int>(event->y - last_click_position.y()); | 2165 int click_move_y = static_cast<int>(event->y - last_click_position.y()); |
| 2120 | 2166 |
| 2121 if (click_time > static_cast<guint32>(double_click_time) || | 2167 if (click_time > static_cast<guint32>(double_click_time) || |
| 2122 click_move_x > double_click_distance || | 2168 click_move_x > double_click_distance || |
| 2123 click_move_y > double_click_distance) { | 2169 click_move_y > double_click_distance) { |
| 2124 gtk_window_begin_move_drag(browser->window_, event->button, | 2170 gtk_window_begin_move_drag(window->window_, event->button, |
| 2125 static_cast<gint>(event->x_root), | 2171 static_cast<gint>(event->x_root), |
| 2126 static_cast<gint>(event->y_root), | 2172 static_cast<gint>(event->y_root), |
| 2127 event->time); | 2173 event->time); |
| 2128 return TRUE; | 2174 return TRUE; |
| 2129 } | 2175 } |
| 2130 } else if (has_hit_edge) { | 2176 } else if (has_hit_edge) { |
| 2131 gtk_window_begin_resize_drag(browser->window_, edge, event->button, | 2177 gtk_window_begin_resize_drag(window->window_, edge, event->button, |
| 2132 static_cast<gint>(event->x_root), | 2178 static_cast<gint>(event->x_root), |
| 2133 static_cast<gint>(event->y_root), | 2179 static_cast<gint>(event->y_root), |
| 2134 event->time); | 2180 event->time); |
| 2135 return TRUE; | 2181 return TRUE; |
| 2136 } | 2182 } |
| 2137 } else if (GDK_2BUTTON_PRESS == event->type) { | 2183 } else if (GDK_2BUTTON_PRESS == event->type) { |
| 2138 if (has_hit_titlebar) { | 2184 if (has_hit_titlebar) { |
| 2139 // Maximize/restore on double click. | 2185 // Maximize/restore on double click. |
| 2140 if (browser->IsMaximized()) { | 2186 if (window->IsMaximized()) { |
| 2141 browser->UnMaximize(); | 2187 window->UnMaximize(); |
| 2142 } else { | 2188 } else { |
| 2143 gtk_window_maximize(browser->window_); | 2189 gtk_window_maximize(window->window_); |
| 2144 } | 2190 } |
| 2145 return TRUE; | 2191 return TRUE; |
| 2146 } | 2192 } |
| 2147 } | 2193 } |
| 2148 } else if (event->button == 2) { | 2194 } else if (event->button == 2) { |
| 2149 if (has_hit_titlebar || has_hit_edge) { | 2195 if (has_hit_titlebar || has_hit_edge) { |
| 2150 gdk_window_lower(GTK_WIDGET(browser->window_)->window); | 2196 gdk_window_lower(GTK_WIDGET(window->window_)->window); |
| 2151 } | 2197 } |
| 2152 return TRUE; | 2198 return TRUE; |
| 2153 } else if (event->button == 3) { | 2199 } else if (event->button == 3) { |
| 2154 if (has_hit_titlebar) { | 2200 if (has_hit_titlebar) { |
| 2155 browser->titlebar_->ShowContextMenu(); | 2201 window->titlebar_->ShowContextMenu(); |
| 2156 return TRUE; | 2202 return TRUE; |
| 2157 } | 2203 } |
| 2158 } | 2204 } |
| 2159 | 2205 |
| 2160 return FALSE; // Continue to propagate the event. | 2206 return FALSE; // Continue to propagate the event. |
| 2161 } | 2207 } |
| 2162 | 2208 |
| 2163 // static | 2209 // static |
| 2164 void BrowserWindowGtk::MainWindowMapped(GtkWidget* widget, | 2210 void BrowserWindowGtk::MainWindowMapped(GtkWidget* widget, |
| 2165 BrowserWindowGtk* window) { | 2211 BrowserWindowGtk* window) { |
| 2166 // Map the X Window ID of the window to our window. | 2212 // Map the X Window ID of the window to our window. |
| 2167 XID xid = x11_util::GetX11WindowFromGtkWidget(widget); | 2213 XID xid = x11_util::GetX11WindowFromGtkWidget(widget); |
| 2168 BrowserWindowGtk::xid_map_.insert( | 2214 BrowserWindowGtk::xid_map_.insert( |
| 2169 std::pair<XID, GtkWindow*>(xid, GTK_WINDOW(widget))); | 2215 std::pair<XID, GtkWindow*>(xid, GTK_WINDOW(widget))); |
| 2170 } | 2216 } |
| 2171 | 2217 |
| 2172 // static | 2218 // static |
| 2173 void BrowserWindowGtk::MainWindowUnMapped(GtkWidget* widget, | 2219 void BrowserWindowGtk::MainWindowUnMapped(GtkWidget* widget, |
| 2174 BrowserWindowGtk* window) { | 2220 BrowserWindowGtk* window) { |
| 2175 // Unmap the X Window ID. | 2221 // Unmap the X Window ID. |
| 2176 XID xid = x11_util::GetX11WindowFromGtkWidget(widget); | 2222 XID xid = x11_util::GetX11WindowFromGtkWidget(widget); |
| 2177 BrowserWindowGtk::xid_map_.erase(xid); | 2223 BrowserWindowGtk::xid_map_.erase(xid); |
| 2178 } | 2224 } |
| 2179 | 2225 |
| 2180 // static | 2226 // static |
| 2181 gboolean BrowserWindowGtk::OnFocusIn(GtkWidget* widget, | 2227 gboolean BrowserWindowGtk::OnFocusIn(GtkWidget* widget, |
| 2182 GdkEventFocus* event, | 2228 GdkEventFocus* event, |
| 2183 BrowserWindowGtk* browser) { | 2229 BrowserWindowGtk* window) { |
| 2184 BrowserList::SetLastActive(browser->browser_.get()); | 2230 BrowserList::SetLastActive(window->browser_.get()); |
| 2185 #if defined(OS_CHROMEOS) | 2231 #if defined(OS_CHROMEOS) |
| 2186 if (browser->panel_controller_) { | 2232 if (window->panel_controller_) { |
| 2187 browser->panel_controller_->OnFocusIn(); | 2233 window->panel_controller_->OnFocusIn(); |
| 2188 } | 2234 } |
| 2189 #endif | 2235 #endif |
| 2190 return FALSE; | 2236 return FALSE; |
| 2191 } | 2237 } |
| 2192 | 2238 |
| 2193 // static | 2239 // static |
| 2194 gboolean BrowserWindowGtk::OnFocusOut(GtkWidget* widget, | 2240 gboolean BrowserWindowGtk::OnFocusOut(GtkWidget* widget, |
| 2195 GdkEventFocus* event, | 2241 GdkEventFocus* event, |
| 2196 BrowserWindowGtk* browser) { | 2242 BrowserWindowGtk* window) { |
| 2197 #if defined(OS_CHROMEOS) | 2243 #if defined(OS_CHROMEOS) |
| 2198 if (browser->panel_controller_) { | 2244 if (window->panel_controller_) { |
| 2199 browser->panel_controller_->OnFocusOut(); | 2245 window->panel_controller_->OnFocusOut(); |
| 2200 } | 2246 } |
| 2201 #endif | 2247 #endif |
| 2202 return FALSE; | 2248 return FALSE; |
| 2203 } | 2249 } |
| 2204 | 2250 |
| 2205 void BrowserWindowGtk::ExecuteBrowserCommand(int id) { | 2251 bool BrowserWindowGtk::ExecuteBrowserCommand(int id) { |
| 2206 if (browser_->command_updater()->IsCommandEnabled(id)) | 2252 if (browser_->command_updater()->IsCommandEnabled(id)) { |
| 2207 browser_->ExecuteCommand(id); | 2253 browser_->ExecuteCommand(id); |
| 2254 return true; |
| 2255 } |
| 2256 return false; |
| 2208 } | 2257 } |
| 2209 | 2258 |
| 2210 void BrowserWindowGtk::ShowSupportedWindowFeatures() { | 2259 void BrowserWindowGtk::ShowSupportedWindowFeatures() { |
| 2211 if (IsTabStripSupported()) | 2260 if (IsTabStripSupported()) |
| 2212 tabstrip_->Show(); | 2261 tabstrip_->Show(); |
| 2213 | 2262 |
| 2214 if (IsToolbarSupported()) | 2263 if (IsToolbarSupported()) |
| 2215 toolbar_->Show(); | 2264 toolbar_->Show(); |
| 2216 | 2265 |
| 2217 if (IsBookmarkBarSupported()) | 2266 if (IsBookmarkBarSupported()) |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2350 // are taken from the WMs' source code. | 2399 // are taken from the WMs' source code. |
| 2351 return (wm_name == "Blackbox" || | 2400 return (wm_name == "Blackbox" || |
| 2352 wm_name == "compiz" || | 2401 wm_name == "compiz" || |
| 2353 wm_name == "e16" || // Enlightenment DR16 | 2402 wm_name == "e16" || // Enlightenment DR16 |
| 2354 wm_name == "KWin" || | 2403 wm_name == "KWin" || |
| 2355 wm_name == "Metacity" || | 2404 wm_name == "Metacity" || |
| 2356 wm_name == "Mutter" || | 2405 wm_name == "Mutter" || |
| 2357 wm_name == "Openbox" || | 2406 wm_name == "Openbox" || |
| 2358 wm_name == "Xfwm4"); | 2407 wm_name == "Xfwm4"); |
| 2359 } | 2408 } |
| OLD | NEW |