зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to m-c.
This commit is contained in:
Коммит
26f2a85534
|
@ -5,3 +5,4 @@ support-files = head.js
|
|||
[browser_first_download_panel.js]
|
||||
skip-if = os == "linux" # Bug 949434
|
||||
[browser_overflow_anchor.js]
|
||||
skip-if = os == "linux" # Bug 952422
|
||||
|
|
|
@ -5180,18 +5180,15 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
|
|||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case WM_MOUSEACTIVATE:
|
||||
if (mWindowType == eWindowType_popup) {
|
||||
// a popup with a parent owner should not be activated when clicked
|
||||
// but should still allow the mouse event to be fired, so the return
|
||||
// value is set to MA_NOACTIVATE. But if the owner isn't the frontmost
|
||||
// window, just use default processing so that the window is activated.
|
||||
HWND owner = ::GetWindow(mWnd, GW_OWNER);
|
||||
if (owner && owner == ::GetForegroundWindow()) {
|
||||
*aRetValue = MA_NOACTIVATE;
|
||||
result = true;
|
||||
}
|
||||
// A popup with a parent owner should not be activated when clicked but
|
||||
// should still allow the mouse event to be fired, so the return value
|
||||
// is set to MA_NOACTIVATE. But if the owner isn't the frontmost window,
|
||||
// just use default processing so that the window is activated.
|
||||
if (IsPopup() && IsOwnerForegroundWindow()) {
|
||||
*aRetValue = MA_NOACTIVATE;
|
||||
result = true;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -7259,15 +7256,11 @@ static bool IsDifferentThreadWindow(HWND aWnd)
|
|||
return ::GetCurrentThreadId() != ::GetWindowThreadProcessId(aWnd, nullptr);
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
nsWindow::EventIsInsideWindow(UINT Msg, nsWindow* aWindow)
|
||||
nsWindow::EventIsInsideWindow(nsWindow* aWindow)
|
||||
{
|
||||
RECT r;
|
||||
|
||||
if (Msg == WM_ACTIVATEAPP)
|
||||
// don't care about activation/deactivation
|
||||
return false;
|
||||
|
||||
::GetWindowRect(aWindow->mWnd, &r);
|
||||
DWORD pos = ::GetMessagePos();
|
||||
POINT mp;
|
||||
|
@ -7275,141 +7268,178 @@ nsWindow::EventIsInsideWindow(UINT Msg, nsWindow* aWindow)
|
|||
mp.y = GET_Y_LPARAM(pos);
|
||||
|
||||
// was the event inside this window?
|
||||
return (bool) PtInRect(&r, mp);
|
||||
return static_cast<bool>(::PtInRect(&r, mp));
|
||||
}
|
||||
|
||||
// Handle events that may cause a popup (combobox, XPMenu, etc) to need to rollup.
|
||||
// static
|
||||
bool
|
||||
nsWindow::DealWithPopups(HWND inWnd, UINT inMsg, WPARAM inWParam, LPARAM inLParam, LRESULT* outResult)
|
||||
nsWindow::GetPopupsToRollup(nsIRollupListener* aRollupListener,
|
||||
uint32_t* aPopupsToRollup)
|
||||
{
|
||||
NS_ASSERTION(outResult, "Bad outResult");
|
||||
// If we're dealing with menus, we probably have submenus and we don't want
|
||||
// to rollup some of them if the click is in a parent menu of the current
|
||||
// submenu.
|
||||
*aPopupsToRollup = UINT32_MAX;
|
||||
nsAutoTArray<nsIWidget*, 5> widgetChain;
|
||||
uint32_t sameTypeCount =
|
||||
aRollupListener->GetSubmenuWidgetChain(&widgetChain);
|
||||
for (uint32_t i = 0; i < widgetChain.Length(); ++i) {
|
||||
nsIWidget* widget = widgetChain[i];
|
||||
if (EventIsInsideWindow(static_cast<nsWindow*>(widget))) {
|
||||
// Don't roll up if the mouse event occurred within a menu of the
|
||||
// same type. If the mouse event occurred in a menu higher than that,
|
||||
// roll up, but pass the number of popups to Rollup so that only those
|
||||
// of the same type close up.
|
||||
if (i < sameTypeCount) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*outResult = MA_NOACTIVATE;
|
||||
*aPopupsToRollup = sameTypeCount;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!::IsWindowVisible(inWnd))
|
||||
// static
|
||||
bool
|
||||
nsWindow::DealWithPopups(HWND aWnd, UINT aMessage,
|
||||
WPARAM aWParam, LPARAM aLParam, LRESULT* aResult)
|
||||
{
|
||||
NS_ASSERTION(aResult, "Bad outResult");
|
||||
|
||||
// XXX Why do we use the return value of WM_MOUSEACTIVATE for all messages?
|
||||
*aResult = MA_NOACTIVATE;
|
||||
|
||||
if (!::IsWindowVisible(aWnd)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsIRollupListener* rollupListener = nsBaseWidget::GetActiveRollupListener();
|
||||
NS_ENSURE_TRUE(rollupListener, false);
|
||||
nsCOMPtr<nsIWidget> rollupWidget = rollupListener->GetRollupWidget();
|
||||
if (!rollupWidget)
|
||||
|
||||
nsCOMPtr<nsIWidget> popup = rollupListener->GetRollupWidget();
|
||||
if (!popup) {
|
||||
return false;
|
||||
}
|
||||
|
||||
inMsg = WinUtils::GetNativeMessage(inMsg);
|
||||
if (inMsg == WM_LBUTTONDOWN || inMsg == WM_RBUTTONDOWN || inMsg == WM_MBUTTONDOWN ||
|
||||
inMsg == WM_MOUSEWHEEL || inMsg == WM_MOUSEHWHEEL || inMsg == WM_ACTIVATE ||
|
||||
(inMsg == WM_KILLFOCUS && IsDifferentThreadWindow((HWND)inWParam)) ||
|
||||
inMsg == WM_NCRBUTTONDOWN ||
|
||||
inMsg == WM_MOVING ||
|
||||
inMsg == WM_SIZING ||
|
||||
inMsg == WM_NCLBUTTONDOWN ||
|
||||
inMsg == WM_NCMBUTTONDOWN ||
|
||||
inMsg == WM_MOUSEACTIVATE ||
|
||||
inMsg == WM_ACTIVATEAPP ||
|
||||
inMsg == WM_MENUSELECT) {
|
||||
// Rollup if the event is outside the popup.
|
||||
bool rollup = !nsWindow::EventIsInsideWindow(inMsg, (nsWindow*)(rollupWidget.get()));
|
||||
uint32_t popupsToRollup = UINT32_MAX;
|
||||
|
||||
if (rollup && (inMsg == WM_MOUSEWHEEL || inMsg == WM_MOUSEHWHEEL)) {
|
||||
rollup = rollupListener->ShouldRollupOnMouseWheelEvent();
|
||||
*outResult = MA_ACTIVATE;
|
||||
}
|
||||
nsWindow* popupWindow = static_cast<nsWindow*>(popup.get());
|
||||
UINT nativeMessage = WinUtils::GetNativeMessage(aMessage);
|
||||
switch (nativeMessage) {
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_RBUTTONDOWN:
|
||||
case WM_MBUTTONDOWN:
|
||||
case WM_NCLBUTTONDOWN:
|
||||
case WM_NCRBUTTONDOWN:
|
||||
case WM_NCMBUTTONDOWN:
|
||||
if (!EventIsInsideWindow(popupWindow) &&
|
||||
GetPopupsToRollup(rollupListener, &popupsToRollup)) {
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
|
||||
// If we're dealing with menus, we probably have submenus and we don't
|
||||
// want to rollup if the click is in a parent menu of the current submenu.
|
||||
uint32_t popupsToRollup = UINT32_MAX;
|
||||
if (rollup) {
|
||||
nsAutoTArray<nsIWidget*, 5> widgetChain;
|
||||
uint32_t sameTypeCount = rollupListener->GetSubmenuWidgetChain(&widgetChain);
|
||||
for ( uint32_t i = 0; i < widgetChain.Length(); ++i ) {
|
||||
nsIWidget* widget = widgetChain[i];
|
||||
if ( nsWindow::EventIsInsideWindow(inMsg, (nsWindow*)widget) ) {
|
||||
// don't roll up if the mouse event occurred within a menu of the
|
||||
// same type. If the mouse event occurred in a menu higher than
|
||||
// that, roll up, but pass the number of popups to Rollup so
|
||||
// that only those of the same type close up.
|
||||
if (i < sameTypeCount) {
|
||||
rollup = false;
|
||||
} else {
|
||||
popupsToRollup = sameTypeCount;
|
||||
}
|
||||
case WM_MOUSEWHEEL:
|
||||
case WM_MOUSEHWHEEL:
|
||||
// We need to check if the popup thinks that it should cause closing
|
||||
// itself when mouse wheel events are fired outside the rollup widget.
|
||||
if (!EventIsInsideWindow(popupWindow)) {
|
||||
*aResult = MA_ACTIVATE;
|
||||
if (rollupListener->ShouldRollupOnMouseWheelEvent() &&
|
||||
GetPopupsToRollup(rollupListener, &popupsToRollup)) {
|
||||
break;
|
||||
}
|
||||
} // foreach parent menu widget
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
case WM_ACTIVATEAPP:
|
||||
break;
|
||||
|
||||
case WM_ACTIVATE:
|
||||
// XXX Why do we need to check the message pos?
|
||||
if (!EventIsInsideWindow(popupWindow) &&
|
||||
GetPopupsToRollup(rollupListener, &popupsToRollup)) {
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
|
||||
case WM_MOUSEACTIVATE:
|
||||
// XXX Why do we need to check the message pos?
|
||||
if (!EventIsInsideWindow(popupWindow) &&
|
||||
GetPopupsToRollup(rollupListener, &popupsToRollup)) {
|
||||
// WM_MOUSEACTIVATE may be caused by moving the mouse (e.g., X-mouse
|
||||
// of TweakUI is enabled. Then, check if the popup should be rolled up
|
||||
// with rollup listener. If not, just consume the message.
|
||||
if (HIWORD(aLParam) == WM_MOUSEMOVE &&
|
||||
!rollupListener->ShouldRollupOnMouseActivate()) {
|
||||
return true;
|
||||
}
|
||||
// Otherwise, it should be handled by wndproc.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (inMsg == WM_MOUSEACTIVATE) {
|
||||
// Prevent the click inside the popup from causing a change in window
|
||||
// activation. Since the popup is shown non-activated, we need to eat
|
||||
// any requests to activate the window while it is displayed. Windows
|
||||
// will automatically activate the popup on the mousedown otherwise.
|
||||
if (!rollup) {
|
||||
return true;
|
||||
} else {
|
||||
UINT uMsg = HIWORD(inLParam);
|
||||
if (uMsg == WM_MOUSEMOVE) {
|
||||
// WM_MOUSEACTIVATE cause by moving the mouse - X-mouse (eg. TweakUI)
|
||||
// must be enabled in Windows.
|
||||
rollup = rollupListener->ShouldRollupOnMouseActivate();
|
||||
if (!rollup) {
|
||||
return true;
|
||||
}
|
||||
// activation. Since the popup is shown non-activated, we need to eat any
|
||||
// requests to activate the window while it is displayed. Windows will
|
||||
// automatically activate the popup on the mousedown otherwise.
|
||||
return true;
|
||||
|
||||
case WM_KILLFOCUS:
|
||||
// If focus moves to other window created in different process/thread,
|
||||
// e.g., a plugin window, popups should be rolled up.
|
||||
if (IsDifferentThreadWindow(reinterpret_cast<HWND>(aWParam))) {
|
||||
// XXX Why do we need to check the message pos?
|
||||
if (!EventIsInsideWindow(popupWindow) &&
|
||||
GetPopupsToRollup(rollupListener, &popupsToRollup)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// if we've still determined that we should still rollup everything, do it.
|
||||
else if (rollup) {
|
||||
// only need to deal with the last rollup for left mouse down events.
|
||||
NS_ASSERTION(!mLastRollup, "mLastRollup is null");
|
||||
return false;
|
||||
|
||||
bool consumeRollupEvent;
|
||||
if (inMsg == WM_LBUTTONDOWN) {
|
||||
POINT pt;
|
||||
pt.x = GET_X_LPARAM(inLParam);
|
||||
pt.y = GET_Y_LPARAM(inLParam);
|
||||
::ClientToScreen(inWnd, &pt);
|
||||
nsIntPoint pos(pt.x, pt.y);
|
||||
|
||||
consumeRollupEvent = rollupListener->Rollup(popupsToRollup, &pos, &mLastRollup);
|
||||
NS_IF_ADDREF(mLastRollup);
|
||||
}
|
||||
else {
|
||||
consumeRollupEvent = rollupListener->Rollup(popupsToRollup, nullptr, nullptr);
|
||||
case WM_MOVING:
|
||||
case WM_SIZING:
|
||||
case WM_MENUSELECT:
|
||||
// XXX Why do we need to check the message pos?
|
||||
if (!EventIsInsideWindow(popupWindow) &&
|
||||
GetPopupsToRollup(rollupListener, &popupsToRollup)) {
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
|
||||
// Tell hook to stop processing messages
|
||||
sProcessHook = false;
|
||||
sRollupMsgId = 0;
|
||||
sRollupMsgWnd = nullptr;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
// return TRUE tells Windows that the event is consumed,
|
||||
// false allows the event to be dispatched
|
||||
//
|
||||
// So if we are NOT supposed to be consuming events, let it go through
|
||||
if (consumeRollupEvent && inMsg != WM_RBUTTONDOWN) {
|
||||
*outResult = MA_ACTIVATE;
|
||||
// Only need to deal with the last rollup for left mouse down events.
|
||||
NS_ASSERTION(!mLastRollup, "mLastRollup is null");
|
||||
|
||||
// However, don't activate panels
|
||||
if (inMsg == WM_MOUSEACTIVATE) {
|
||||
nsWindow* activateWindow = WinUtils::GetNSWindowPtr(inWnd);
|
||||
if (activateWindow) {
|
||||
nsWindowType wintype;
|
||||
activateWindow->GetWindowType(wintype);
|
||||
if (wintype == eWindowType_popup && activateWindow->PopupType() == ePopupTypePanel) {
|
||||
*outResult = popupsToRollup != UINT32_MAX ? MA_NOACTIVATEANDEAT : MA_NOACTIVATE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// if we are only rolling up some popups, don't activate and don't let
|
||||
// the event go through. This prevents clicks menus higher in the
|
||||
// chain from opening when a context menu is open
|
||||
if (popupsToRollup != UINT32_MAX && inMsg == WM_MOUSEACTIVATE) {
|
||||
*outResult = MA_NOACTIVATEANDEAT;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} // if event that might trigger a popup to rollup
|
||||
bool consumeRollupEvent;
|
||||
if (nativeMessage == WM_LBUTTONDOWN) {
|
||||
POINT pt;
|
||||
pt.x = GET_X_LPARAM(aLParam);
|
||||
pt.y = GET_Y_LPARAM(aLParam);
|
||||
::ClientToScreen(aWnd, &pt);
|
||||
nsIntPoint pos(pt.x, pt.y);
|
||||
|
||||
consumeRollupEvent =
|
||||
rollupListener->Rollup(popupsToRollup, &pos, &mLastRollup);
|
||||
NS_IF_ADDREF(mLastRollup);
|
||||
} else {
|
||||
consumeRollupEvent =
|
||||
rollupListener->Rollup(popupsToRollup, nullptr, nullptr);
|
||||
}
|
||||
|
||||
// Tell hook to stop processing messages
|
||||
sProcessHook = false;
|
||||
sRollupMsgId = 0;
|
||||
sRollupMsgWnd = nullptr;
|
||||
|
||||
// If we are NOT supposed to be consuming events, let it go through
|
||||
if (consumeRollupEvent && nativeMessage != WM_RBUTTONDOWN) {
|
||||
*aResult = MA_ACTIVATE;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -337,6 +337,20 @@ protected:
|
|||
return mTransparencyMode == eTransparencyGlass ||
|
||||
mTransparencyMode == eTransparencyBorderlessGlass;
|
||||
}
|
||||
HWND GetOwnerWnd() const
|
||||
{
|
||||
return ::GetWindow(mWnd, GW_OWNER);
|
||||
}
|
||||
bool IsOwnerForegroundWindow() const
|
||||
{
|
||||
HWND owner = GetOwnerWnd();
|
||||
return owner && owner == ::GetForegroundWindow();
|
||||
}
|
||||
bool IsPopup() const
|
||||
{
|
||||
return mWindowType == eWindowType_popup;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Event processing helpers
|
||||
|
@ -358,7 +372,7 @@ protected:
|
|||
bool *aEventDispatched);
|
||||
LRESULT ProcessKeyDownMessage(const MSG &aMsg,
|
||||
bool *aEventDispatched);
|
||||
static bool EventIsInsideWindow(UINT Msg, nsWindow* aWindow);
|
||||
static bool EventIsInsideWindow(nsWindow* aWindow);
|
||||
// Convert nsEventStatus value to a windows boolean
|
||||
static bool ConvertStatus(nsEventStatus aStatus);
|
||||
static void PostSleepWakeNotification(const bool aIsSleepMode);
|
||||
|
@ -405,6 +419,8 @@ protected:
|
|||
static void ScheduleHookTimer(HWND aWnd, UINT aMsgId);
|
||||
static void RegisterSpecialDropdownHooks();
|
||||
static void UnregisterSpecialDropdownHooks();
|
||||
static bool GetPopupsToRollup(nsIRollupListener* aRollupListener,
|
||||
uint32_t* aPopupsToRollup);
|
||||
static bool DealWithPopups(HWND inWnd, UINT inMsg, WPARAM inWParam, LPARAM inLParam, LRESULT* outResult);
|
||||
|
||||
/**
|
||||
|
|
Загрузка…
Ссылка в новой задаче