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 |