Bug 665315 - OOPP Contextmenu loses messages; r=jmathies

This commit is contained in:
Andrei Kurushin 2011-07-27 14:17:50 +02:00
Родитель bd43cc1726
Коммит 1f1b6b4402
5 изменённых файлов: 46 добавлений и 10 удалений

Просмотреть файл

@ -60,6 +60,7 @@ using mozilla::gfx::SharedDIBSurface;
#include "gfxAlphaRecovery.h"
#include "mozilla/ipc/SyncChannel.h"
#include "mozilla/AutoRestore.h"
using mozilla::ipc::ProcessChild;
using namespace mozilla::plugins;
@ -1547,14 +1548,8 @@ PluginInstanceChild::TrackPopupHookProc(HMENU hMenu,
// can act on the menu item selected.
bool isRetCmdCall = (uFlags & TPM_RETURNCMD);
// A little trick scrounged from chromium's code - set the focus
// to our surrogate parent so keyboard nav events go to the menu.
HWND focusHwnd = SetFocus(surrogateHwnd);
DWORD res = sUser32TrackPopupMenuStub(hMenu, uFlags|TPM_RETURNCMD, x, y,
nReserved, surrogateHwnd, prcRect);
if (IsWindow(focusHwnd)) {
SetFocus(focusHwnd);
}
if (!isRetCmdCall && res) {
SendMessage(hWnd, WM_COMMAND, MAKEWPARAM(res, 0), 0);
@ -1620,6 +1615,8 @@ PluginInstanceChild::WinlessHandleEvent(NPEvent& event)
// Events that might generate nested event dispatch loops need
// special handling during delivery.
int16_t handled;
HWND focusHwnd = NULL;
// TrackPopupMenu will fail if the parent window is not associated with
// our ui thread. So we hook TrackPopupMenu so we can hand in a surrogate
@ -1628,12 +1625,23 @@ PluginInstanceChild::WinlessHandleEvent(NPEvent& event)
(event.event == WM_RBUTTONDOWN || // flash
event.event == WM_RBUTTONUP)) { // silverlight
sWinlessPopupSurrogateHWND = mWinlessPopupSurrogateHWND;
// A little trick scrounged from chromium's code - set the focus
// to our surrogate parent so keyboard nav events go to the menu.
focusHwnd = SetFocus(mWinlessPopupSurrogateHWND);
}
MessageLoop* loop = MessageLoop::current();
AutoRestore<bool> modalLoop(loop->os_modal_loop());
handled = mPluginIface->event(&mData, reinterpret_cast<void*>(&event));
sWinlessPopupSurrogateHWND = NULL;
if (IsWindow(focusHwnd)) {
SetFocus(focusHwnd);
}
return handled;
}

Просмотреть файл

@ -2289,12 +2289,13 @@ PluginModuleChild::NestedInputEventHook(int nCode, WPARAM wParam, LPARAM lParam)
PluginModuleChild* self = current();
PRUint32 len = self->mIncallPumpingStack.Length();
if (nCode >= 0 && len && !self->mIncallPumpingStack[len - 1]._spinning) {
MessageLoop* loop = MessageLoop::current();
self->SendProcessNativeEventsInRPCCall();
IncallFrame& f = self->mIncallPumpingStack[len - 1];
f._spinning = true;
MessageLoop* loop = MessageLoop::current();
f._savedNestableTasksAllowed = loop->NestableTasksAllowed();
loop->SetNestableTasksAllowed(true);
loop->set_os_modal_loop(true);
}
return CallNextHookEx(NULL, nCode, wParam, lParam);

Просмотреть файл

@ -92,6 +92,9 @@ MessageLoop::MessageLoop(Type type)
nestable_tasks_allowed_(true),
exception_restoration_(false),
state_(NULL),
#ifdef OS_WIN
os_modal_loop_(false),
#endif // OS_WIN
next_sequence_num_(0) {
DCHECK(!current()) << "should only have one message loop per thread";
lazy_tls_ptr.Pointer()->Set(this);

Просмотреть файл

@ -264,6 +264,16 @@ public:
exception_restoration_ = restore;
}
#if defined(OS_WIN)
void set_os_modal_loop(bool os_modal_loop) {
os_modal_loop_ = os_modal_loop;
}
bool & os_modal_loop() {
return os_modal_loop_;
}
#endif // OS_WIN
//----------------------------------------------------------------------------
protected:
struct RunState {
@ -424,6 +434,12 @@ public:
RunState* state_;
#if defined(OS_WIN)
// Should be set to true before calling Windows APIs like TrackPopupMenu, etc
// which enter a modal message loop.
bool os_modal_loop_;
#endif
// The next sequence number to use for delayed tasks.
int next_sequence_num_;

Просмотреть файл

@ -6,6 +6,7 @@
#include <math.h>
#include "base/message_loop.h"
#include "base/histogram.h"
#include "base/win_util.h"
@ -380,11 +381,18 @@ bool MessagePumpForUI::ProcessPumpReplacementMessage() {
// that the re-post of kMsgHaveWork may be asynchronous to this thread!!
MSG msg;
bool have_message = (0 != PeekMessage(&msg, NULL, 0, 0, PM_REMOVE));
if (have_message && msg.message == WM_NULL)
bool have_message = false;
if (MessageLoop::current()->os_modal_loop()) {
// We only peek out WM_PAINT and WM_TIMER here for reasons mentioned above.
have_message = PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE) ||
PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_REMOVE);
} else {
have_message = (0 != PeekMessage(&msg, NULL, 0, 0, PM_REMOVE));
if (have_message && msg.message == WM_NULL)
have_message = (0 != PeekMessage(&msg, NULL, 0, 0, PM_REMOVE));
}
DCHECK(!have_message || kMsgHaveWork != msg.message ||
msg.hwnd != message_hwnd_);