Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(231)

Side by Side Diff: content/browser/renderer_host/render_widget_host.cc

Issue 8727010: Send one WebKeyboardEvent to the RenderWidget at a time. Move keyboard (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « content/browser/renderer_host/render_widget_host.h ('k') | content/common/view_messages.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "content/browser/renderer_host/render_widget_host.h" 5 #include "content/browser/renderer_host/render_widget_host.h"
6 6
7 #include "base/auto_reset.h" 7 #include "base/auto_reset.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/debug/trace_event.h" 10 #include "base/debug/trace_event.h"
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 touch_move_pending_(false), 94 touch_move_pending_(false),
95 touch_event_is_queued_(false), 95 touch_event_is_queued_(false),
96 needs_repainting_on_restore_(false), 96 needs_repainting_on_restore_(false),
97 is_unresponsive_(false), 97 is_unresponsive_(false),
98 in_get_backing_store_(false), 98 in_get_backing_store_(false),
99 view_being_painted_(false), 99 view_being_painted_(false),
100 ignore_input_events_(false), 100 ignore_input_events_(false),
101 text_direction_updated_(false), 101 text_direction_updated_(false),
102 text_direction_(WebKit::WebTextDirectionLeftToRight), 102 text_direction_(WebKit::WebTextDirectionLeftToRight),
103 text_direction_canceled_(false), 103 text_direction_canceled_(false),
104 suppress_next_char_events_(false), 104 suppress_incoming_char_events_(false),
105 suppress_outgoing_char_events_(false),
105 pending_mouse_lock_request_(false), 106 pending_mouse_lock_request_(false),
106 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { 107 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
107 if (routing_id_ == MSG_ROUTING_NONE) 108 if (routing_id_ == MSG_ROUTING_NONE)
108 routing_id_ = process_->GetNextRoutingID(); 109 routing_id_ = process_->GetNextRoutingID();
109 110
110 process_->Attach(this, routing_id_); 111 process_->Attach(this, routing_id_);
111 // Because the widget initializes as is_hidden_ == false, 112 // Because the widget initializes as is_hidden_ == false,
112 // tell the process host that we're alive. 113 // tell the process host that we're alive.
113 process_->WidgetRestored(); 114 process_->WidgetRestored();
114 115
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after
567 next_mouse_move_->movementX += x; 568 next_mouse_move_->movementX += x;
568 next_mouse_move_->movementY += y; 569 next_mouse_move_->movementY += y;
569 } 570 }
570 return; 571 return;
571 } 572 }
572 mouse_move_pending_ = true; 573 mouse_move_pending_ = true;
573 } else if (mouse_event.type == WebInputEvent::MouseDown) { 574 } else if (mouse_event.type == WebInputEvent::MouseDown) {
574 OnUserGesture(); 575 OnUserGesture();
575 } 576 }
576 577
577 ForwardInputEvent(mouse_event, sizeof(WebMouseEvent), false); 578 ForwardInputEvent(mouse_event, sizeof(WebMouseEvent));
578 } 579 }
579 580
580 void RenderWidgetHost::OnMouseActivate() { 581 void RenderWidgetHost::OnMouseActivate() {
581 } 582 }
582 583
583 void RenderWidgetHost::ForwardWheelEvent( 584 void RenderWidgetHost::ForwardWheelEvent(
584 const WebMouseWheelEvent& wheel_event) { 585 const WebMouseWheelEvent& wheel_event) {
585 TRACE_EVENT0("renderer_host", "RenderWidgetHost::ForwardWheelEvent"); 586 TRACE_EVENT0("renderer_host", "RenderWidgetHost::ForwardWheelEvent");
586 if (ignore_input_events_ || process_->IgnoreInputEvents()) 587 if (ignore_input_events_ || process_->IgnoreInputEvents())
587 return; 588 return;
(...skipping 17 matching lines...) Expand all
605 last_wheel_event->timeStampSeconds = wheel_event.timeStampSeconds; 606 last_wheel_event->timeStampSeconds = wheel_event.timeStampSeconds;
606 } 607 }
607 return; 608 return;
608 } 609 }
609 mouse_wheel_pending_ = true; 610 mouse_wheel_pending_ = true;
610 current_wheel_event_ = wheel_event; 611 current_wheel_event_ = wheel_event;
611 612
612 HISTOGRAM_COUNTS_100("MPArch.RWH_WheelQueueSize", 613 HISTOGRAM_COUNTS_100("MPArch.RWH_WheelQueueSize",
613 coalesced_mouse_wheel_events_.size()); 614 coalesced_mouse_wheel_events_.size());
614 615
615 ForwardInputEvent(wheel_event, sizeof(WebMouseWheelEvent), false); 616 ForwardInputEvent(wheel_event, sizeof(WebMouseWheelEvent));
616 } 617 }
617 618
618 void RenderWidgetHost::ForwardGestureEvent( 619 void RenderWidgetHost::ForwardGestureEvent(
619 const WebKit::WebGestureEvent& gesture_event) { 620 const WebKit::WebGestureEvent& gesture_event) {
620 TRACE_EVENT0("renderer_host", "RenderWidgetHost::ForwardWheelEvent"); 621 TRACE_EVENT0("renderer_host", "RenderWidgetHost::ForwardWheelEvent");
621 if (ignore_input_events_ || process_->IgnoreInputEvents()) 622 if (ignore_input_events_ || process_->IgnoreInputEvents())
622 return; 623 return;
623 624
624 ForwardInputEvent(gesture_event, sizeof(WebGestureEvent), false); 625 ForwardInputEvent(gesture_event, sizeof(WebGestureEvent));
625 } 626 }
626 627
627 void RenderWidgetHost::ForwardKeyboardEvent( 628 void RenderWidgetHost::ForwardKeyboardEvent(
628 const NativeWebKeyboardEvent& key_event) { 629 const NativeWebKeyboardEvent& key_event) {
629 TRACE_EVENT0("renderer_host", "RenderWidgetHost::ForwardKeyboardEvent"); 630 TRACE_EVENT0("renderer_host", "RenderWidgetHost::ForwardKeyboardEvent");
630 if (ignore_input_events_ || process_->IgnoreInputEvents()) 631 if (ignore_input_events_ || process_->IgnoreInputEvents())
631 return; 632 return;
632 633
634 // Double check the type to make sure caller hasn't sent us nonsense that
635 // will mess up our key queue.
636 if (!WebInputEvent::isKeyboardEventType(key_event.type))
637 return;
638
633 if (key_event.type == WebKeyboardEvent::Char && 639 if (key_event.type == WebKeyboardEvent::Char &&
634 (key_event.windowsKeyCode == ui::VKEY_RETURN || 640 (key_event.windowsKeyCode == ui::VKEY_RETURN ||
635 key_event.windowsKeyCode == ui::VKEY_SPACE)) { 641 key_event.windowsKeyCode == ui::VKEY_SPACE)) {
636 OnUserGesture(); 642 OnUserGesture();
637 } 643 }
638 644
639 // Double check the type to make sure caller hasn't sent us nonsense that 645 if (suppress_incoming_char_events_) {
640 // will mess up our key queue. 646 // If the preceding RawKeyDown event was handled by the browser, then we
641 if (WebInputEvent::isKeyboardEventType(key_event.type)) { 647 // need to suppress all Char events generated by it. Please note that, one
642 if (suppress_next_char_events_) { 648 // RawKeyDown event may generate multiple Char events, so we can't reset
643 // If preceding RawKeyDown event was handled by the browser, then we need 649 // |suppress_incoming_char_events_| until we get a KeyUp or a RawKeyDown.
644 // suppress all Char events generated by it. Please note that, one 650 if (key_event.type == WebKeyboardEvent::Char)
645 // RawKeyDown event may generate multiple Char events, so we can't reset 651 return;
646 // |suppress_next_char_events_| until we get a KeyUp or a RawKeyDown. 652 // We get a KeyUp or a RawKeyDown event.
647 if (key_event.type == WebKeyboardEvent::Char) 653 suppress_incoming_char_events_ = false;
648 return; 654 }
649 // We get a KeyUp or a RawKeyDown event. 655
650 suppress_next_char_events_ = false; 656 bool is_keyboard_shortcut = false;
657 // Only pre-handle the key event if it's not handled by the input method.
658 if (!key_event.skip_in_browser) {
659 // We need to set |suppress_incoming_char_events_| to true if
660 // PreHandleKeyboardEvent() returns true, but |this| may already be
661 // destroyed at that time. So set |suppress_incoming_char_events_| true
662 // here, then revert it afterwards when necessary.
663 if (key_event.type == WebKeyboardEvent::RawKeyDown)
664 suppress_incoming_char_events_ = true;
665
666 // Tab switching/closing accelerators aren't sent to the renderer to avoid
667 // a hung/malicious renderer from interfering.
668 if (PreHandleKeyboardEvent(key_event, &is_keyboard_shortcut))
669 return;
670
671 if (key_event.type == WebKeyboardEvent::RawKeyDown)
672 suppress_incoming_char_events_ = false;
673 }
674
675 // Don't add this key to the queue if we have no way to send the message...
676 if (!process_->HasConnection())
677 return;
678
679 bool has_pending_key = !key_queue_.empty();
680
681 // We keep track of all pending keyboard events so that if any are not
682 // processed by the renderer, we have the ability to process them in the
683 // browser (via UnhandledKeyboardEvent). We also delay sending the next
684 // keyboard event until the previous has been ACK'd by the renderer.
685 key_queue_.push_back(Key(key_event, is_keyboard_shortcut));
686 HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size());
687
688 if (!has_pending_key)
689 ForwardNextKeyboardEvent();
690 }
691
692 void RenderWidgetHost::ForwardNextKeyboardEvent() {
693 while (!key_queue_.empty()) {
694 const Key& front_item = key_queue_.front();
695
696 if (suppress_outgoing_char_events_) {
697 if (front_item.event.type == WebInputEvent::Char) {
698 key_queue_.pop_front();
699 continue;
700 }
701 suppress_outgoing_char_events_ = false;
651 } 702 }
652 703
653 bool is_keyboard_shortcut = false; 704 // The renderer only cares about the platform-independent event data.
654 // Only pre-handle the key event if it's not handled by the input method. 705 ForwardInputEvent(front_item.event, sizeof(WebKeyboardEvent));
655 if (!key_event.skip_in_browser) { 706 break;
656 // We need to set |suppress_next_char_events_| to true if
657 // PreHandleKeyboardEvent() returns true, but |this| may already be
658 // destroyed at that time. So set |suppress_next_char_events_| true here,
659 // then revert it afterwards when necessary.
660 if (key_event.type == WebKeyboardEvent::RawKeyDown)
661 suppress_next_char_events_ = true;
662
663 // Tab switching/closing accelerators aren't sent to the renderer to avoid
664 // a hung/malicious renderer from interfering.
665 if (PreHandleKeyboardEvent(key_event, &is_keyboard_shortcut))
666 return;
667
668 if (key_event.type == WebKeyboardEvent::RawKeyDown)
669 suppress_next_char_events_ = false;
670 }
671
672 // Don't add this key to the queue if we have no way to send the message...
673 if (!process_->HasConnection())
674 return;
675
676 // Put all WebKeyboardEvent objects in a queue since we can't trust the
677 // renderer and we need to give something to the UnhandledInputEvent
678 // handler.
679 key_queue_.push_back(key_event);
680 HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size());
681
682 // Only forward the non-native portions of our event.
683 ForwardInputEvent(key_event, sizeof(WebKeyboardEvent),
684 is_keyboard_shortcut);
685 } 707 }
686 } 708 }
687 709
688 void RenderWidgetHost::ForwardInputEvent(const WebInputEvent& input_event, 710 void RenderWidgetHost::ForwardInputEvent(const WebInputEvent& input_event,
689 int event_size, 711 int event_size) {
690 bool is_keyboard_shortcut) {
691 TRACE_EVENT0("renderer_host", "RenderWidgetHost::ForwardInputEvent"); 712 TRACE_EVENT0("renderer_host", "RenderWidgetHost::ForwardInputEvent");
692 713
693 if (!process_->HasConnection()) 714 if (!process_->HasConnection())
694 return; 715 return;
695 716
696 DCHECK(!process_->IgnoreInputEvents()); 717 DCHECK(!process_->IgnoreInputEvents());
697 718
698 IPC::Message* message = new ViewMsg_HandleInputEvent(routing_id_); 719 IPC::Message* message = new ViewMsg_HandleInputEvent(routing_id_);
699 message->WriteData( 720 message->WriteData(
700 reinterpret_cast<const char*>(&input_event), event_size); 721 reinterpret_cast<const char*>(&input_event), event_size);
701 // |is_keyboard_shortcut| only makes sense for RawKeyDown events.
702 if (input_event.type == WebInputEvent::RawKeyDown)
703 message->WriteBool(is_keyboard_shortcut);
704 input_event_start_time_ = TimeTicks::Now(); 722 input_event_start_time_ = TimeTicks::Now();
705 Send(message); 723 Send(message);
706 724
707 // Any non-wheel input event cancels pending wheel events. 725 // Any non-wheel input event cancels pending wheel events.
708 if (input_event.type != WebInputEvent::MouseWheel) 726 if (input_event.type != WebInputEvent::MouseWheel)
709 coalesced_mouse_wheel_events_.clear(); 727 coalesced_mouse_wheel_events_.clear();
710 728
711 // Any input event cancels a pending mouse move event. Note that 729 // Any input event cancels a pending mouse move event. Note that
712 // |next_mouse_move_| possibly owns |input_event|, so don't use |input_event| 730 // |next_mouse_move_| possibly owns |input_event|, so don't use |input_event|
713 // after this line. 731 // after this line.
(...skipping 12 matching lines...) Expand all
726 touch_move_pending_) { 744 touch_move_pending_) {
727 touch_event_is_queued_ = true; 745 touch_event_is_queued_ = true;
728 queued_touch_event_ = touch_event; 746 queued_touch_event_ = touch_event;
729 return; 747 return;
730 } 748 }
731 749
732 if (touch_event.type == WebInputEvent::TouchMove) 750 if (touch_event.type == WebInputEvent::TouchMove)
733 touch_move_pending_ = true; 751 touch_move_pending_ = true;
734 else 752 else
735 touch_move_pending_ = false; 753 touch_move_pending_ = false;
736 ForwardInputEvent(touch_event, sizeof(WebKit::WebTouchEvent), false); 754 ForwardInputEvent(touch_event, sizeof(WebKit::WebTouchEvent));
737 } 755 }
738 756
739 void RenderWidgetHost::RendererExited(base::TerminationStatus status, 757 void RenderWidgetHost::RendererExited(base::TerminationStatus status,
740 int exit_code) { 758 int exit_code) {
741 // Clearing this flag causes us to re-create the renderer when recovering 759 // Clearing this flag causes us to re-create the renderer when recovering
742 // from a crashed renderer. 760 // from a crashed renderer.
743 renderer_initialized_ = false; 761 renderer_initialized_ = false;
744 762
745 // Must reset these to ensure that mouse move/wheel events work with a new 763 // Must reset these to ensure that mouse move/wheel events work with a new
746 // renderer. 764 // renderer.
747 mouse_move_pending_ = false; 765 mouse_move_pending_ = false;
748 next_mouse_move_.reset(); 766 next_mouse_move_.reset();
749 mouse_wheel_pending_ = false; 767 mouse_wheel_pending_ = false;
750 coalesced_mouse_wheel_events_.clear(); 768 coalesced_mouse_wheel_events_.clear();
751 touch_move_pending_ = false; 769 touch_move_pending_ = false;
752 touch_event_is_queued_ = false; 770 touch_event_is_queued_ = false;
753 771
754 // Must reset these to ensure that keyboard events work with a new renderer. 772 // Must reset these to ensure that keyboard events work with a new renderer.
755 key_queue_.clear(); 773 key_queue_.clear();
756 suppress_next_char_events_ = false; 774 suppress_incoming_char_events_ = false;
775 suppress_outgoing_char_events_ = false;
757 776
758 // Reset some fields in preparation for recovering from a crash. 777 // Reset some fields in preparation for recovering from a crash.
759 resize_ack_pending_ = false; 778 resize_ack_pending_ = false;
760 repaint_ack_pending_ = false; 779 repaint_ack_pending_ = false;
761 780
762 in_flight_size_.SetSize(0, 0); 781 in_flight_size_.SetSize(0, 0);
763 in_flight_reserved_rect_.SetRect(0, 0, 0, 0); 782 in_flight_reserved_rect_.SetRect(0, 0, 0, 0);
764 current_size_.SetSize(0, 0); 783 current_size_.SetSize(0, 0);
765 current_reserved_rect_.SetRect(0, 0, 0, 0); 784 current_reserved_rect_.SetRect(0, 0, 0, 0);
766 is_hidden_ = false; 785 is_hidden_ = false;
(...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after
1316 if (process_->HasConnection()) { 1335 if (process_->HasConnection()) {
1317 // Renderer accessibility wasn't enabled on process launch. Enable it now. 1336 // Renderer accessibility wasn't enabled on process launch. Enable it now.
1318 Send(new ViewMsg_EnableAccessibility(routing_id())); 1337 Send(new ViewMsg_EnableAccessibility(routing_id()));
1319 } 1338 }
1320 } 1339 }
1321 1340
1322 void RenderWidgetHost::ProcessKeyboardEventAck(int type, bool processed) { 1341 void RenderWidgetHost::ProcessKeyboardEventAck(int type, bool processed) {
1323 if (key_queue_.empty()) { 1342 if (key_queue_.empty()) {
1324 LOG(ERROR) << "Got a KeyEvent back from the renderer but we " 1343 LOG(ERROR) << "Got a KeyEvent back from the renderer but we "
1325 << "don't seem to have sent it to the renderer!"; 1344 << "don't seem to have sent it to the renderer!";
1326 } else if (key_queue_.front().type != type) { 1345 } else if (key_queue_.front().event.type != type) {
1327 LOG(ERROR) << "We seem to have a different key type sent from " 1346 LOG(ERROR) << "We seem to have a different key type sent from "
1328 << "the renderer. (" << key_queue_.front().type << " vs. " 1347 << "the renderer. (" << key_queue_.front().event.type << " vs. "
1329 << type << "). Ignoring event."; 1348 << type << "). Ignoring event.";
1330 1349
1331 // Something must be wrong. Clear the |key_queue_| and 1350 // Something must be wrong. Clear the |key_queue_| and
1332 // |suppress_next_char_events_| so that we can resume from the error. 1351 // |suppress_incoming_char_events_| so that we can resume from the error.
1333 key_queue_.clear(); 1352 key_queue_.clear();
1334 suppress_next_char_events_ = false; 1353 suppress_incoming_char_events_ = false;
1354 suppress_outgoing_char_events_ = false;
1335 } else { 1355 } else {
1336 NativeWebKeyboardEvent front_item = key_queue_.front(); 1356 Key front_item = key_queue_.front();
1337 key_queue_.pop_front(); 1357 key_queue_.pop_front();
1338 1358
1339 #if defined(OS_MACOSX) 1359 #if defined(OS_MACOSX)
1340 if (!is_hidden_ && view_->PostProcessEventForPluginIme(front_item)) 1360 if (!is_hidden_ && view_->PostProcessEventForPluginIme(front_item.event))
1341 return; 1361 return;
1342 #endif 1362 #endif
1343 1363
1364 // If this RawKeyDown event corresponds to a browser keyboard shortcut and
1365 // it's not processed by the renderer, then we need to suppress the
1366 // upcoming Char event.
1367 if (!processed && front_item.is_shortcut) {
1368 DCHECK(front_item.event.type == WebInputEvent::RawKeyDown);
1369 suppress_outgoing_char_events_ = true;
1370 }
1371
1372 ForwardNextKeyboardEvent();
1373
1344 // We only send unprocessed key event upwards if we are not hidden, 1374 // We only send unprocessed key event upwards if we are not hidden,
1345 // because the user has moved away from us and no longer expect any effect 1375 // because the user has moved away from us and no longer expect any effect
1346 // of this key event. 1376 // of this key event.
1347 if (!processed && !is_hidden_ && !front_item.skip_in_browser) { 1377 if (!processed && !is_hidden_ && !front_item.event.skip_in_browser) {
1348 UnhandledKeyboardEvent(front_item); 1378 UnhandledKeyboardEvent(front_item.event);
1349 1379
1350 // WARNING: This RenderWidgetHost can be deallocated at this point 1380 // WARNING: This RenderWidgetHost can be deallocated at this point
1351 // (i.e. in the case of Ctrl+W, where the call to 1381 // (i.e. in the case of Ctrl+W, where the call to
1352 // UnhandledKeyboardEvent destroys this RenderWidgetHost). 1382 // UnhandledKeyboardEvent destroys this RenderWidgetHost).
1353 } 1383 }
1354 } 1384 }
1355 } 1385 }
1356 1386
1357 void RenderWidgetHost::ActivateDeferredPluginHandles() { 1387 void RenderWidgetHost::ActivateDeferredPluginHandles() {
1358 #if !defined(USE_AURA) 1388 #if !defined(USE_AURA)
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
1487 } 1517 }
1488 1518
1489 // static 1519 // static
1490 void RenderWidgetHost::AcknowledgePostSubBuffer(int32 route_id, 1520 void RenderWidgetHost::AcknowledgePostSubBuffer(int32 route_id,
1491 int gpu_host_id) { 1521 int gpu_host_id) {
1492 GpuProcessHostUIShim* ui_shim = GpuProcessHostUIShim::FromID(gpu_host_id); 1522 GpuProcessHostUIShim* ui_shim = GpuProcessHostUIShim::FromID(gpu_host_id);
1493 if (ui_shim) 1523 if (ui_shim)
1494 ui_shim->Send(new AcceleratedSurfaceMsg_PostSubBufferACK(route_id)); 1524 ui_shim->Send(new AcceleratedSurfaceMsg_PostSubBufferACK(route_id));
1495 } 1525 }
1496 #endif 1526 #endif
OLDNEW
« no previous file with comments | « content/browser/renderer_host/render_widget_host.h ('k') | content/common/view_messages.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698