зеркало из https://github.com/mozilla/gecko-dev.git
Bug 953146 part.7 Don't allow other application to activate non-focusable popup r=jimm
This commit is contained in:
Родитель
7a3a090854
Коммит
03b49ec18b
|
@ -7301,6 +7301,25 @@ nsWindow::GetPopupsToRollup(nsIRollupListener* aRollupListener,
|
|||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
nsWindow::NeedsToHandleNCActivateDelayed(HWND aWnd)
|
||||
{
|
||||
// While popup is open, popup window might be activated by other application.
|
||||
// At this time, we need to take back focus to the previous window but it
|
||||
// causes flickering its nonclient area because WM_NCACTIVATE comes before
|
||||
// WM_ACTIVATE and we cannot know which window will take focus at receiving
|
||||
// WM_NCACTIVATE. Therefore, we need a hack for preventing the flickerling.
|
||||
//
|
||||
// If non-popup window receives WM_NCACTIVATE at deactivating, default
|
||||
// wndproc shouldn't handle it as deactivating. Instead, at receiving
|
||||
// WM_ACTIVIATE after that, WM_NCACTIVATE should be sent again manually.
|
||||
// This returns true if the window needs to handle WM_NCACTIVATE later.
|
||||
|
||||
nsWindow* window = WinUtils::GetNSWindowPtr(aWnd);
|
||||
return window && !window->IsPopup();
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
nsWindow::DealWithPopups(HWND aWnd, UINT aMessage,
|
||||
|
@ -7323,6 +7342,8 @@ nsWindow::DealWithPopups(HWND aWnd, UINT aMessage,
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool sSendingNCACTIVATE = false;
|
||||
static bool sPendingNCACTIVATE = false;
|
||||
uint32_t popupsToRollup = UINT32_MAX;
|
||||
|
||||
nsWindow* popupWindow = static_cast<nsWindow*>(popup.get());
|
||||
|
@ -7357,6 +7378,31 @@ nsWindow::DealWithPopups(HWND aWnd, UINT aMessage,
|
|||
break;
|
||||
|
||||
case WM_ACTIVATE:
|
||||
// NOTE: Don't handle WA_INACTIVE for preventing popup taking focus
|
||||
// because we cannot distinguish it's caused by mouse or not.
|
||||
if (LOWORD(aWParam) == WA_ACTIVE && aLParam) {
|
||||
nsWindow* window = WinUtils::GetNSWindowPtr(aWnd);
|
||||
if (window && window->IsPopup()) {
|
||||
// Cancel notifying widget listeners of deactivating the previous
|
||||
// active window (see WM_KILLFOCUS case in ProcessMessage()).
|
||||
sJustGotDeactivate = false;
|
||||
// Reactivate the window later.
|
||||
::PostMessageW(aWnd, MOZ_WM_REACTIVATE, aWParam, aLParam);
|
||||
return true;
|
||||
}
|
||||
} else if (sPendingNCACTIVATE && LOWORD(aWParam) == WA_INACTIVE &&
|
||||
NeedsToHandleNCActivateDelayed(aWnd)) {
|
||||
// If focus moves to non-popup widget or focusable popup, the window
|
||||
// needs to update its nonclient area.
|
||||
nsWindow* activeWindow =
|
||||
WinUtils::GetNSWindowPtr(reinterpret_cast<HWND>(aLParam));
|
||||
if (!activeWindow || !activeWindow->IsPopup()) {
|
||||
sSendingNCACTIVATE = true;
|
||||
::SendMessageW(aWnd, WM_NCACTIVATE, false, 0);
|
||||
sSendingNCACTIVATE = false;
|
||||
}
|
||||
sPendingNCACTIVATE = false;
|
||||
}
|
||||
// XXX Why do we need to check the message pos?
|
||||
if (!EventIsInsideWindow(popupWindow) &&
|
||||
GetPopupsToRollup(rollupListener, &popupsToRollup)) {
|
||||
|
@ -7364,6 +7410,27 @@ nsWindow::DealWithPopups(HWND aWnd, UINT aMessage,
|
|||
}
|
||||
return false;
|
||||
|
||||
case MOZ_WM_REACTIVATE:
|
||||
// The previous active window should take back focus.
|
||||
if (::IsWindow(reinterpret_cast<HWND>(aLParam))) {
|
||||
::SetForegroundWindow(reinterpret_cast<HWND>(aLParam));
|
||||
}
|
||||
return true;
|
||||
|
||||
case WM_NCACTIVATE:
|
||||
if (!aWParam && !sSendingNCACTIVATE &&
|
||||
NeedsToHandleNCActivateDelayed(aWnd)) {
|
||||
// Don't just consume WM_NCACTIVATE. It doesn't handle only the
|
||||
// nonclient area state change.
|
||||
::DefWindowProcW(aWnd, aMessage, TRUE, aLParam);
|
||||
// Accept the deactivating because it's necessary to receive following
|
||||
// WM_ACTIVATE.
|
||||
*aResult = TRUE;
|
||||
sPendingNCACTIVATE = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
case WM_MOUSEACTIVATE:
|
||||
// XXX Why do we need to check the message pos?
|
||||
if (!EventIsInsideWindow(popupWindow) &&
|
||||
|
|
|
@ -421,6 +421,7 @@ protected:
|
|||
static void UnregisterSpecialDropdownHooks();
|
||||
static bool GetPopupsToRollup(nsIRollupListener* aRollupListener,
|
||||
uint32_t* aPopupsToRollup);
|
||||
static bool NeedsToHandleNCActivateDelayed(HWND aWnd);
|
||||
static bool DealWithPopups(HWND inWnd, UINT inMsg, WPARAM inWParam, LPARAM inLParam, LRESULT* outResult);
|
||||
|
||||
/**
|
||||
|
|
|
@ -33,10 +33,13 @@
|
|||
#define MOZ_WM_HSCROLL (WM_APP+0x0313)
|
||||
#define MOZ_WM_MOUSEWHEEL_FIRST MOZ_WM_MOUSEVWHEEL
|
||||
#define MOZ_WM_MOUSEWHEEL_LAST MOZ_WM_HSCROLL
|
||||
// If a popup window is being activated, we try to reactivate the previous
|
||||
// window with this message.
|
||||
#define MOZ_WM_REACTIVATE (WM_APP+0x0314)
|
||||
|
||||
// Internal message for ensuring the file picker is visible on multi monitor
|
||||
// systems, and when the screen resolution changes.
|
||||
#define MOZ_WM_ENSUREVISIBLE (WM_APP + 14159)
|
||||
#define MOZ_WM_ENSUREVISIBLE (WM_APP+0x374F)
|
||||
|
||||
#ifndef SM_CXPADDEDBORDER
|
||||
#define SM_CXPADDEDBORDER 92
|
||||
|
|
Загрузка…
Ссылка в новой задаче