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

Side by Side Diff: base/message_pump_win.cc

Issue 10826223: Replace PeekMessage for TSF awareness (Closed) Base URL: http://git.chromium.org/chromium/src.git@yukawa
Patch Set: sync Created 8 years, 3 months 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
« no previous file with comments | « base/message_pump_win.h ('k') | base/win/text_services_message_filter.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) 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 "base/message_pump_win.h" 5 #include "base/message_pump_win.h"
6 6
7 #include <math.h> 7 #include <math.h>
8 8
9 #include "base/debug/trace_event.h" 9 #include "base/debug/trace_event.h"
10 #include "base/message_loop.h" 10 #include "base/message_loop.h"
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 int delay = static_cast<int>(timeout); 88 int delay = static_cast<int>(timeout);
89 if (delay < 0) 89 if (delay < 0)
90 delay = 0; 90 delay = 0;
91 91
92 return delay; 92 return delay;
93 } 93 }
94 94
95 //----------------------------------------------------------------------------- 95 //-----------------------------------------------------------------------------
96 // MessagePumpForUI public: 96 // MessagePumpForUI public:
97 97
98 MessagePumpForUI::MessagePumpForUI() : instance_(NULL) { 98 MessagePumpForUI::MessagePumpForUI()
99 : instance_(NULL),
100 message_filter_(new MessageFilter) {
99 InitMessageWnd(); 101 InitMessageWnd();
100 } 102 }
101 103
102 MessagePumpForUI::~MessagePumpForUI() { 104 MessagePumpForUI::~MessagePumpForUI() {
103 DestroyWindow(message_hwnd_); 105 DestroyWindow(message_hwnd_);
104 UnregisterClass(kWndClass, instance_); 106 UnregisterClass(kWndClass, instance_);
105 } 107 }
106 108
107 void MessagePumpForUI::ScheduleWork() { 109 void MessagePumpForUI::ScheduleWork() {
108 if (InterlockedExchange(&have_work_, 1)) 110 if (InterlockedExchange(&have_work_, 1))
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 290
289 DWORD result; 291 DWORD result;
290 result = MsgWaitForMultipleObjectsEx(0, NULL, delay, QS_ALLINPUT, 292 result = MsgWaitForMultipleObjectsEx(0, NULL, delay, QS_ALLINPUT,
291 MWMO_INPUTAVAILABLE); 293 MWMO_INPUTAVAILABLE);
292 294
293 if (WAIT_OBJECT_0 == result) { 295 if (WAIT_OBJECT_0 == result) {
294 // A WM_* message is available. 296 // A WM_* message is available.
295 // If a parent child relationship exists between windows across threads 297 // If a parent child relationship exists between windows across threads
296 // then their thread inputs are implicitly attached. 298 // then their thread inputs are implicitly attached.
297 // This causes the MsgWaitForMultipleObjectsEx API to return indicating 299 // This causes the MsgWaitForMultipleObjectsEx API to return indicating
298 // that messages are ready for processing (specifically mouse messages 300 // that messages are ready for processing (Specifically, mouse messages
299 // intended for the child window. Occurs if the child window has capture) 301 // intended for the child window may appear if the child window has
300 // The subsequent PeekMessages call fails to return any messages thus 302 // capture).
303 // The subsequent PeekMessages call may fail to return any messages thus
301 // causing us to enter a tight loop at times. 304 // causing us to enter a tight loop at times.
302 // The WaitMessage call below is a workaround to give the child window 305 // The WaitMessage call below is a workaround to give the child window
303 // sometime to process its input messages. 306 // some time to process its input messages.
304 MSG msg = {0}; 307 MSG msg = {0};
305 DWORD queue_status = GetQueueStatus(QS_MOUSE); 308 DWORD queue_status = GetQueueStatus(QS_MOUSE);
306 if (HIWORD(queue_status) & QS_MOUSE && 309 if (HIWORD(queue_status) & QS_MOUSE &&
307 !PeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE)) { 310 !PeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE)) {
308 WaitMessage(); 311 WaitMessage();
309 } 312 }
310 return; 313 return;
311 } 314 }
312 315
313 DCHECK_NE(WAIT_FAILED, result) << GetLastError(); 316 DCHECK_NE(WAIT_FAILED, result) << GetLastError();
314 } 317 }
315 318
316 void MessagePumpForUI::HandleWorkMessage() { 319 void MessagePumpForUI::HandleWorkMessage() {
317 // If we are being called outside of the context of Run, then don't try to do 320 // If we are being called outside of the context of Run, then don't try to do
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
354 // If there are sent messages in the queue then PeekMessage internally 357 // If there are sent messages in the queue then PeekMessage internally
355 // dispatches the message and returns false. We return true in this 358 // dispatches the message and returns false. We return true in this
356 // case to ensure that the message loop peeks again instead of calling 359 // case to ensure that the message loop peeks again instead of calling
357 // MsgWaitForMultipleObjectsEx again. 360 // MsgWaitForMultipleObjectsEx again.
358 bool sent_messages_in_queue = false; 361 bool sent_messages_in_queue = false;
359 DWORD queue_status = GetQueueStatus(QS_SENDMESSAGE); 362 DWORD queue_status = GetQueueStatus(QS_SENDMESSAGE);
360 if (HIWORD(queue_status) & QS_SENDMESSAGE) 363 if (HIWORD(queue_status) & QS_SENDMESSAGE)
361 sent_messages_in_queue = true; 364 sent_messages_in_queue = true;
362 365
363 MSG msg; 366 MSG msg;
364 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 367 if (message_filter_->DoPeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
365 return ProcessMessageHelper(msg); 368 return ProcessMessageHelper(msg);
366 369
367 return sent_messages_in_queue; 370 return sent_messages_in_queue;
368 } 371 }
369 372
370 bool MessagePumpForUI::ProcessMessageHelper(const MSG& msg) { 373 bool MessagePumpForUI::ProcessMessageHelper(const MSG& msg) {
371 TRACE_EVENT1("base", "MessagePumpForUI::ProcessMessageHelper", 374 TRACE_EVENT1("base", "MessagePumpForUI::ProcessMessageHelper",
372 "message", msg.message); 375 "message", msg.message);
373 if (WM_QUIT == msg.message) { 376 if (WM_QUIT == msg.message) {
374 // Repost the QUIT message so that it will be retrieved by the primary 377 // Repost the QUIT message so that it will be retrieved by the primary
375 // GetMessage() loop. 378 // GetMessage() loop.
376 state_->should_quit = true; 379 state_->should_quit = true;
377 PostQuitMessage(static_cast<int>(msg.wParam)); 380 PostQuitMessage(static_cast<int>(msg.wParam));
378 return false; 381 return false;
379 } 382 }
380 383
381 // While running our main message pump, we discard kMsgHaveWork messages. 384 // While running our main message pump, we discard kMsgHaveWork messages.
382 if (msg.message == kMsgHaveWork && msg.hwnd == message_hwnd_) 385 if (msg.message == kMsgHaveWork && msg.hwnd == message_hwnd_)
383 return ProcessPumpReplacementMessage(); 386 return ProcessPumpReplacementMessage();
384 387
385 if (CallMsgFilter(const_cast<MSG*>(&msg), kMessageFilterCode)) 388 if (CallMsgFilter(const_cast<MSG*>(&msg), kMessageFilterCode))
386 return true; 389 return true;
387 390
388 WillProcessMessage(msg); 391 WillProcessMessage(msg);
389 392
390 if (state_->dispatcher) { 393 if (!message_filter_->ProcessMessage(msg)) {
391 if (!state_->dispatcher->Dispatch(msg)) 394 if (state_->dispatcher) {
392 state_->should_quit = true; 395 if (!state_->dispatcher->Dispatch(msg))
393 } else { 396 state_->should_quit = true;
394 TranslateMessage(&msg); 397 } else {
395 DispatchMessage(&msg); 398 TranslateMessage(&msg);
399 DispatchMessage(&msg);
400 }
396 } 401 }
397 402
398 DidProcessMessage(msg); 403 DidProcessMessage(msg);
399 return true; 404 return true;
400 } 405 }
401 406
402 bool MessagePumpForUI::ProcessPumpReplacementMessage() { 407 bool MessagePumpForUI::ProcessPumpReplacementMessage() {
403 // When we encounter a kMsgHaveWork message, this method is called to peek 408 // When we encounter a kMsgHaveWork message, this method is called to peek
404 // and process a replacement message, such as a WM_PAINT or WM_TIMER. The 409 // and process a replacement message, such as a WM_PAINT or WM_TIMER. The
405 // goal is to make the kMsgHaveWork as non-intrusive as possible, even though 410 // goal is to make the kMsgHaveWork as non-intrusive as possible, even though
406 // a continuous stream of such messages are posted. This method carefully 411 // a continuous stream of such messages are posted. This method carefully
407 // peeks a message while there is no chance for a kMsgHaveWork to be pending, 412 // peeks a message while there is no chance for a kMsgHaveWork to be pending,
408 // then resets the have_work_ flag (allowing a replacement kMsgHaveWork to 413 // then resets the have_work_ flag (allowing a replacement kMsgHaveWork to
409 // possibly be posted), and finally dispatches that peeked replacement. Note 414 // possibly be posted), and finally dispatches that peeked replacement. Note
410 // that the re-post of kMsgHaveWork may be asynchronous to this thread!! 415 // that the re-post of kMsgHaveWork may be asynchronous to this thread!!
411 416
412 bool have_message = false; 417 bool have_message = false;
413 MSG msg; 418 MSG msg;
414 // We should not process all window messages if we are in the context of an 419 // We should not process all window messages if we are in the context of an
415 // OS modal loop, i.e. in the context of a windows API call like MessageBox. 420 // OS modal loop, i.e. in the context of a windows API call like MessageBox.
416 // This is to ensure that these messages are peeked out by the OS modal loop. 421 // This is to ensure that these messages are peeked out by the OS modal loop.
417 if (MessageLoop::current()->os_modal_loop()) { 422 if (MessageLoop::current()->os_modal_loop()) {
418 // We only peek out WM_PAINT and WM_TIMER here for reasons mentioned above. 423 // We only peek out WM_PAINT and WM_TIMER here for reasons mentioned above.
419 have_message = PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE) || 424 have_message = PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE) ||
420 PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_REMOVE); 425 PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_REMOVE);
421 } else { 426 } else {
422 have_message = (0 != PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)); 427 have_message = !!message_filter_->DoPeekMessage(&msg, NULL, 0, 0,
428 PM_REMOVE);
423 } 429 }
424 430
425 DCHECK(!have_message || kMsgHaveWork != msg.message || 431 DCHECK(!have_message || kMsgHaveWork != msg.message ||
426 msg.hwnd != message_hwnd_); 432 msg.hwnd != message_hwnd_);
427 433
428 // Since we discarded a kMsgHaveWork message, we must update the flag. 434 // Since we discarded a kMsgHaveWork message, we must update the flag.
429 int old_have_work = InterlockedExchange(&have_work_, 0); 435 int old_have_work = InterlockedExchange(&have_work_, 0);
430 DCHECK(old_have_work); 436 DCHECK(old_have_work);
431 437
432 // We don't need a special time slice if we didn't have_message to process. 438 // We don't need a special time slice if we didn't have_message to process.
433 if (!have_message) 439 if (!have_message)
434 return false; 440 return false;
435 441
436 // Guarantee we'll get another time slice in the case where we go into native 442 // Guarantee we'll get another time slice in the case where we go into native
437 // windows code. This ScheduleWork() may hurt performance a tiny bit when 443 // windows code. This ScheduleWork() may hurt performance a tiny bit when
438 // tasks appear very infrequently, but when the event queue is busy, the 444 // tasks appear very infrequently, but when the event queue is busy, the
439 // kMsgHaveWork events get (percentage wise) rarer and rarer. 445 // kMsgHaveWork events get (percentage wise) rarer and rarer.
440 ScheduleWork(); 446 ScheduleWork();
441 return ProcessMessageHelper(msg); 447 return ProcessMessageHelper(msg);
442 } 448 }
443 449
450 void MessagePumpForUI::SetMessageFilter(
451 scoped_ptr<MessageFilter> message_filter) {
darin (slow to review) 2012/09/07 07:33:51 nit: indent by 4 spaces for line continuations
yoichio 2012/09/07 07:51:36 Done.
452 message_filter_ = message_filter.Pass();
453 }
454
444 //----------------------------------------------------------------------------- 455 //-----------------------------------------------------------------------------
445 // MessagePumpForIO public: 456 // MessagePumpForIO public:
446 457
447 MessagePumpForIO::MessagePumpForIO() { 458 MessagePumpForIO::MessagePumpForIO() {
448 port_.Set(CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1)); 459 port_.Set(CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1));
449 DCHECK(port_.IsValid()); 460 DCHECK(port_.IsValid());
450 } 461 }
451 462
452 void MessagePumpForIO::ScheduleWork() { 463 void MessagePumpForIO::ScheduleWork() {
453 if (InterlockedExchange(&have_work_, 1)) 464 if (InterlockedExchange(&have_work_, 1))
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
660 671
661 // static 672 // static
662 MessagePumpForIO::IOHandler* MessagePumpForIO::KeyToHandler( 673 MessagePumpForIO::IOHandler* MessagePumpForIO::KeyToHandler(
663 ULONG_PTR key, 674 ULONG_PTR key,
664 bool* has_valid_io_context) { 675 bool* has_valid_io_context) {
665 *has_valid_io_context = ((key & 1) == 0); 676 *has_valid_io_context = ((key & 1) == 0);
666 return reinterpret_cast<IOHandler*>(key & ~static_cast<ULONG_PTR>(1)); 677 return reinterpret_cast<IOHandler*>(key & ~static_cast<ULONG_PTR>(1));
667 } 678 }
668 679
669 } // namespace base 680 } // namespace base
OLDNEW
« no previous file with comments | « base/message_pump_win.h ('k') | base/win/text_services_message_filter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698