 Chromium Code Reviews
 Chromium Code Reviews Issue 1267483003:
  Combine the WM_CHAR with WM_KEY* for key event flow.  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master
    
  
    Issue 1267483003:
  Combine the WM_CHAR with WM_KEY* for key event flow.  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master| OLD | NEW | 
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "stdafx.h" | 5 #include "stdafx.h" | 
| 6 #include <corewindow.h> | 6 #include <corewindow.h> | 
| 7 #include <shobjidl.h> | 7 #include <shobjidl.h> | 
| 8 | 8 | 
| 9 #include "base/base_switches.h" | |
| 10 #include "base/command_line.h" | |
| 9 #include "base/logging.h" | 11 #include "base/logging.h" | 
| 10 #include "base/profiler/scoped_tracker.h" | 12 #include "base/profiler/scoped_tracker.h" | 
| 11 #include "ui/gfx/geometry/safe_integer_conversions.h" | 13 #include "ui/gfx/geometry/safe_integer_conversions.h" | 
| 12 #include "ui/gfx/win/msg_util.h" | 14 #include "ui/gfx/win/msg_util.h" | 
| 13 | 15 | 
| 14 #pragma comment(lib, "shell32.lib") | 16 #pragma comment(lib, "shell32.lib") | 
| 15 | 17 | 
| 16 EXTERN_C IMAGE_DOS_HEADER __ImageBase; | 18 EXTERN_C IMAGE_DOS_HEADER __ImageBase; | 
| 17 // Even though we only create a single window, we need to keep this | 19 // Even though we only create a single window, we need to keep this | 
| 18 // count because of the hidden window used by the UI message loop of | 20 // count because of the hidden window used by the UI message loop of | 
| (...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 364 DISALLOW_COPY_AND_ASSIGN(MouseEvent); | 366 DISALLOW_COPY_AND_ASSIGN(MouseEvent); | 
| 365 }; | 367 }; | 
| 366 | 368 | 
| 367 // This class implements the winrt interfaces needed to support keyboard | 369 // This class implements the winrt interfaces needed to support keyboard | 
| 368 // character and system character messages. | 370 // character and system character messages. | 
| 369 class KeyEvent : public mswr::RuntimeClass< | 371 class KeyEvent : public mswr::RuntimeClass< | 
| 370 winui::Core::IKeyEventArgs, | 372 winui::Core::IKeyEventArgs, | 
| 371 winui::Core::ICharacterReceivedEventArgs, | 373 winui::Core::ICharacterReceivedEventArgs, | 
| 372 winui::Core::IAcceleratorKeyEventArgs> { | 374 winui::Core::IAcceleratorKeyEventArgs> { | 
| 373 public: | 375 public: | 
| 374 KeyEvent(const MSG& msg) | 376 KeyEvent(const MSG& msg, bool was_key) | 
| 375 : msg_(msg) {} | 377 : msg_(msg), was_key_(was_key) {} | 
| 376 | 378 | 
| 377 // IKeyEventArgs implementation. | 379 // IKeyEventArgs implementation. | 
| 378 HRESULT STDMETHODCALLTYPE | 380 HRESULT STDMETHODCALLTYPE | 
| 379 get_VirtualKey(winsys::VirtualKey* virtual_key) override { | 381 get_VirtualKey(winsys::VirtualKey* virtual_key) override { | 
| 380 *virtual_key = static_cast<winsys::VirtualKey>(msg_.wParam); | 382 *virtual_key = static_cast<winsys::VirtualKey>(msg_.wParam); | 
| 381 return S_OK; | 383 return S_OK; | 
| 382 } | 384 } | 
| 383 | 385 | 
| 384 HRESULT STDMETHODCALLTYPE | 386 HRESULT STDMETHODCALLTYPE | 
| 385 get_KeyStatus(winui::Core::CorePhysicalKeyStatus* key_status) override { | 387 get_KeyStatus(winui::Core::CorePhysicalKeyStatus* key_status) override { | 
| 386 // As per msdn documentation for the keyboard messages. | 388 // As per msdn documentation for the keyboard messages. | 
| 387 key_status->RepeatCount = msg_.lParam & 0x0000FFFF; | 389 key_status->RepeatCount = msg_.lParam & 0x0000FFFF; | 
| 388 key_status->ScanCode = (msg_.lParam >> 16) & 0x00FF; | 390 key_status->ScanCode = (msg_.lParam >> 16) & 0x00FF; | 
| 389 key_status->IsExtendedKey = (msg_.lParam & (1 << 24)); | 391 key_status->IsExtendedKey = (msg_.lParam & (1 << 24)); | 
| 390 key_status->IsMenuKeyDown = (msg_.lParam & (1 << 29)); | 392 key_status->IsMenuKeyDown = (msg_.lParam & (1 << 29)); | 
| 391 key_status->WasKeyDown = (msg_.lParam & (1 << 30)); | |
| 392 key_status->IsKeyReleased = (msg_.lParam & (1 << 31)); | 393 key_status->IsKeyReleased = (msg_.lParam & (1 << 31)); | 
| 394 key_status->WasKeyDown = was_key_; | |
| 393 return S_OK; | 395 return S_OK; | 
| 394 } | 396 } | 
| 395 | 397 | 
| 396 // ICharacterReceivedEventArgs implementation. | 398 // ICharacterReceivedEventArgs implementation. | 
| 397 HRESULT STDMETHODCALLTYPE get_KeyCode(uint32* key_code) override { | 399 HRESULT STDMETHODCALLTYPE get_KeyCode(uint32* key_code) override { | 
| 398 *key_code = msg_.wParam; | 400 *key_code = msg_.wParam; | 
| 399 return S_OK; | 401 return S_OK; | 
| 400 } | 402 } | 
| 401 | 403 | 
| 402 // IAcceleratorKeyEventArgs implementation. | 404 // IAcceleratorKeyEventArgs implementation. | 
| 403 HRESULT STDMETHODCALLTYPE | 405 HRESULT STDMETHODCALLTYPE | 
| 404 get_EventType(winui::Core::CoreAcceleratorKeyEventType* event_type) override { | 406 get_EventType(winui::Core::CoreAcceleratorKeyEventType* event_type) override { | 
| 405 if (msg_.message == WM_SYSKEYDOWN) { | 407 if (msg_.message == WM_SYSKEYDOWN) { | 
| 406 *event_type = winui::Core::CoreAcceleratorKeyEventType_SystemKeyDown; | 408 *event_type = winui::Core::CoreAcceleratorKeyEventType_SystemKeyDown; | 
| 407 } else if (msg_.message == WM_SYSKEYUP) { | 409 } else if (msg_.message == WM_SYSKEYUP) { | 
| 408 *event_type = winui::Core::CoreAcceleratorKeyEventType_SystemKeyUp; | 410 *event_type = winui::Core::CoreAcceleratorKeyEventType_SystemKeyUp; | 
| 409 } else if (msg_.message == WM_SYSCHAR) { | 411 } else if (msg_.message == WM_SYSCHAR) { | 
| 410 *event_type = winui::Core::CoreAcceleratorKeyEventType_SystemCharacter; | 412 *event_type = winui::Core::CoreAcceleratorKeyEventType_SystemCharacter; | 
| 411 } | 413 } | 
| 412 return S_OK; | 414 return S_OK; | 
| 413 } | 415 } | 
| 414 | 416 | 
| 415 private: | 417 private: | 
| 416 MSG msg_; | 418 MSG msg_; | 
| 419 bool was_key_; | |
| 417 }; | 420 }; | 
| 418 | 421 | 
| 419 // The following classes are the emulation of the WinRT system as exposed | 422 // The following classes are the emulation of the WinRT system as exposed | 
| 420 // to metro applications. There is one application (ICoreApplication) which | 423 // to metro applications. There is one application (ICoreApplication) which | 
| 421 // contains a series of Views (ICoreApplicationView) each one of them | 424 // contains a series of Views (ICoreApplicationView) each one of them | 
| 422 // containing a CoreWindow which represents a surface that can drawn to | 425 // containing a CoreWindow which represents a surface that can drawn to | 
| 423 // and that receives events. | 426 // and that receives events. | 
| 424 // | 427 // | 
| 425 // Here is the general dependency hierachy in terms of interfaces: | 428 // Here is the general dependency hierachy in terms of interfaces: | 
| 426 // | 429 // | 
| (...skipping 28 matching lines...) Expand all Loading... | |
| 455 | 458 | 
| 456 HRESULT STDMETHODCALLTYPE | 459 HRESULT STDMETHODCALLTYPE | 
| 457 ProcessEvents(winui::Core::CoreProcessEventsOption options) override { | 460 ProcessEvents(winui::Core::CoreProcessEventsOption options) override { | 
| 458 // We don't support the other message pump modes. So we basically enter a | 461 // We don't support the other message pump modes. So we basically enter a | 
| 459 // traditional message loop that we only exit a teardown. | 462 // traditional message loop that we only exit a teardown. | 
| 460 if (options != winui::Core::CoreProcessEventsOption_ProcessUntilQuit) | 463 if (options != winui::Core::CoreProcessEventsOption_ProcessUntilQuit) | 
| 461 return E_FAIL; | 464 return E_FAIL; | 
| 462 | 465 | 
| 463 MSG msg = {0}; | 466 MSG msg = {0}; | 
| 464 while((::GetMessage(&msg, NULL, 0, 0) != 0) && g_window_count > 0) { | 467 while((::GetMessage(&msg, NULL, 0, 0) != 0) && g_window_count > 0) { | 
| 468 ::TranslateMessage(&msg); | |
| 
yukawa
2015/08/19 06:17:53
Would it be possible to preserve the current behav
 
Shu Chen
2015/08/19 06:41:31
Done.
 | |
| 465 ProcessInputMessage(msg); | 469 ProcessInputMessage(msg); | 
| 466 ::TranslateMessage(&msg); | |
| 467 ::DispatchMessage(&msg); | 470 ::DispatchMessage(&msg); | 
| 468 } | 471 } | 
| 469 // TODO(cpu): figure what to do with msg.WParam which we would normally | 472 // TODO(cpu): figure what to do with msg.WParam which we would normally | 
| 470 // return here. | 473 // return here. | 
| 471 return S_OK; | 474 return S_OK; | 
| 472 } | 475 } | 
| 473 | 476 | 
| 474 HRESULT STDMETHODCALLTYPE | 477 HRESULT STDMETHODCALLTYPE | 
| 475 RunAsync(winui::Core::CoreDispatcherPriority priority, | 478 RunAsync(winui::Core::CoreDispatcherPriority priority, | 
| 476 winui::Core::IDispatchedHandler* agileCallback, | 479 winui::Core::IDispatchedHandler* agileCallback, | 
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 515 } else if ((msg.message >= WM_MOUSEFIRST) && | 518 } else if ((msg.message >= WM_MOUSEFIRST) && | 
| 516 (msg.message <= WM_MOUSELAST)) { | 519 (msg.message <= WM_MOUSELAST)) { | 
| 517 ret = input_handler_->HandleMouseMessage(msg); | 520 ret = input_handler_->HandleMouseMessage(msg); | 
| 518 } | 521 } | 
| 519 } | 522 } | 
| 520 return ret; | 523 return ret; | 
| 521 } | 524 } | 
| 522 | 525 | 
| 523 bool HandleSystemKeys(const MSG& msg) { | 526 bool HandleSystemKeys(const MSG& msg) { | 
| 524 mswr::ComPtr<winui::Core::IAcceleratorKeyEventArgs> event_args; | 527 mswr::ComPtr<winui::Core::IAcceleratorKeyEventArgs> event_args; | 
| 525 event_args = mswr::Make<KeyEvent>(msg); | 528 event_args = mswr::Make<KeyEvent>(msg, true); | 
| 526 accelerator_key_event_handler_->Invoke(this, event_args.Get()); | 529 accelerator_key_event_handler_->Invoke(this, event_args.Get()); | 
| 527 return true; | 530 return true; | 
| 528 } | 531 } | 
| 529 | 532 | 
| 530 InputHandler* input_handler_; | 533 InputHandler* input_handler_; | 
| 531 AcceleratorKeyEventHandler* accelerator_key_event_handler_; | 534 AcceleratorKeyEventHandler* accelerator_key_event_handler_; | 
| 532 }; | 535 }; | 
| 533 | 536 | 
| 534 class CoreWindowEmulation | 537 class CoreWindowEmulation | 
| 535 : public mswr::RuntimeClass< | 538 : public mswr::RuntimeClass< | 
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 906 | 909 | 
| 907 HRESULT STDMETHODCALLTYPE put_MessageHandled(boolean value) override { | 910 HRESULT STDMETHODCALLTYPE put_MessageHandled(boolean value) override { | 
| 908 return S_OK; | 911 return S_OK; | 
| 909 } | 912 } | 
| 910 | 913 | 
| 911 // InputHandler | 914 // InputHandler | 
| 912 bool HandleKeyboardMessage(const MSG& msg) override { | 915 bool HandleKeyboardMessage(const MSG& msg) override { | 
| 913 switch (msg.message) { | 916 switch (msg.message) { | 
| 914 case WM_KEYDOWN: | 917 case WM_KEYDOWN: | 
| 915 case WM_KEYUP: { | 918 case WM_KEYUP: { | 
| 919 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( | |
| 920 switches::kDisableMergeKeyCharEvents)) { | |
| 921 // Combines the WM_KEY* and WM_CHAR messages in the event processing | |
| 922 // flow which is necessary to let Chrome IME extension to process the | |
| 923 // key event and perform corresponding IME actions. | |
| 924 // Chrome IME extension may wants to consume certain key events based | |
| 925 // on the character information of WM_CHAR messages. Holding WM_KEY* | |
| 926 // messages until WM_CHAR is processed by the IME extension is not | |
| 927 // feasible because there is no way to know wether there will or not | |
| 928 // be a WM_CHAR following the WM_KEY*. | |
| 929 // Chrome never handles dead chars so it is safe to remove/ignore | |
| 930 // WM_*DEADCHAR messages. | |
| 931 MSG char_msg; | |
| 932 while (::PeekMessage(&char_msg, msg.hwnd, WM_CHAR, WM_DEADCHAR, | |
| 933 PM_REMOVE)) { | |
| 934 if (char_msg.message == WM_DEADCHAR) | |
| 935 continue; | |
| 936 mswr::ComPtr<winui::Core::ICharacterReceivedEventArgs> char_args; | |
| 937 char_args = mswr::Make<KeyEvent>(char_msg, true); | |
| 938 character_received_handler_->Invoke(this, char_args.Get()); | |
| 939 } | |
| 940 } | |
| 916 mswr::ComPtr<winui::Core::IKeyEventArgs> event_args; | 941 mswr::ComPtr<winui::Core::IKeyEventArgs> event_args; | 
| 917 event_args = mswr::Make<KeyEvent>(msg); | 942 event_args = mswr::Make<KeyEvent>(msg, true); | 
| 918 KeyEventHandler* handler = NULL; | 943 KeyEventHandler* handler = NULL; | 
| 919 if (msg.message == WM_KEYDOWN) { | 944 if (msg.message == WM_KEYDOWN) { | 
| 920 handler = key_down_handler_; | 945 handler = key_down_handler_; | 
| 921 } else { | 946 } else { | 
| 922 handler = key_up_handler_; | 947 handler = key_up_handler_; | 
| 923 } | 948 } | 
| 924 handler->Invoke(this, event_args.Get()); | 949 handler->Invoke(this, event_args.Get()); | 
| 925 break; | 950 break; | 
| 926 } | 951 } | 
| 927 | 952 | 
| 928 case WM_CHAR: | 953 case WM_CHAR: { | 
| 929 case WM_DEADCHAR: | |
| 930 case WM_UNICHAR: { | |
| 931 mswr::ComPtr<winui::Core::ICharacterReceivedEventArgs> event_args; | 954 mswr::ComPtr<winui::Core::ICharacterReceivedEventArgs> event_args; | 
| 932 event_args = mswr::Make<KeyEvent>(msg); | 955 event_args = mswr::Make<KeyEvent>(msg, false); | 
| 933 character_received_handler_->Invoke(this, event_args.Get()); | 956 character_received_handler_->Invoke(this, event_args.Get()); | 
| 934 break; | 957 break; | 
| 935 } | 958 } | 
| 936 | 959 | 
| 937 default: | 960 default: | 
| 938 return false; | 961 return false; | 
| 939 } | 962 } | 
| 940 return true; | 963 return true; | 
| 941 } | 964 } | 
| 942 | 965 | 
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1218 }; | 1241 }; | 
| 1219 | 1242 | 
| 1220 | 1243 | 
| 1221 mswr::ComPtr<winapp::Core::ICoreApplication> InitWindows7() { | 1244 mswr::ComPtr<winapp::Core::ICoreApplication> InitWindows7() { | 
| 1222 HRESULT hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); | 1245 HRESULT hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); | 
| 1223 if (FAILED(hr)) | 1246 if (FAILED(hr)) | 
| 1224 CHECK(false); | 1247 CHECK(false); | 
| 1225 return mswr::Make<CoreApplicationWin7Emulation>(); | 1248 return mswr::Make<CoreApplicationWin7Emulation>(); | 
| 1226 } | 1249 } | 
| 1227 | 1250 | 
| OLD | NEW |