Bug 416771 - Allow window.focus() to switch tabs. r=NeilDeakin,dao CLOSED TREE

Differential Revision: https://phabricator.services.mozilla.com/D31643

--HG--
extra : source : 5acccb49a66840b5c2266edfb7a8953878a2a040
extra : histedit_source : 33a19d54114ef5eda00aefb1c997d6dbcfb40501
This commit is contained in:
Emilio Cobos Álvarez 2019-05-22 17:21:29 +00:00
parent e34a09a25c
commit 300ed443b9
6 changed files with 53 additions and 42 deletions

View File

@ -30,6 +30,7 @@ window._gBrowser = {
}
window.addEventListener("sizemodechange", this);
window.addEventListener("occlusionstatechange", this);
window.addEventListener("framefocusrequested", this);
this._setupInitialBrowserAndTab();
@ -4298,6 +4299,18 @@ window._gBrowser = {
case "keypress":
this._handleKeyPressEventMac(aEvent);
break;
case "framefocusrequested": {
let tab = this.getTabForBrowser(aEvent.target);
if (!tab || tab == this.selectedTab) {
// Let the focus manager try to do its thing by not calling
// preventDefault(). It will still raise the window if appropriate.
break;
}
this.selectedTab = tab;
window.focus();
aEvent.preventDefault();
break;
}
case "sizemodechange":
case "occlusionstatechange":
if (aEvent.target == window && !this._switcher) {
@ -4508,6 +4521,7 @@ window._gBrowser = {
}
window.removeEventListener("sizemodechange", this);
window.removeEventListener("occlusionstatechange", this);
window.removeEventListener("framefocusrequested", this);
if (gMultiProcessBrowser) {
let messageManager = window.getGroupMessageManager("browsers");

View File

@ -4176,6 +4176,32 @@ nsresult nsContentUtils::DispatchFocusChromeEvent(nsPIDOMWindowOuter* aWindow) {
CanBubble::eYes, Cancelable::eYes);
}
void nsContentUtils::RequestFrameFocus(Element& aFrameElement, bool aCanRaise) {
RefPtr<Element> target = &aFrameElement;
bool defaultAction = true;
if (aCanRaise) {
DispatchEventOnlyToChrome(target->OwnerDoc(), target,
NS_LITERAL_STRING("framefocusrequested"),
CanBubble::eYes, Cancelable::eYes,
&defaultAction);
}
if (!defaultAction) {
return;
}
nsCOMPtr<nsIFocusManager> fm = nsFocusManager::GetFocusManager();
if (!fm) {
return;
}
uint32_t flags = nsIFocusManager::FLAG_NOSCROLL;
if (aCanRaise) {
flags |= nsIFocusManager::FLAG_RAISE;
}
fm->SetFocus(target, flags);
}
nsresult nsContentUtils::DispatchEventOnlyToChrome(
Document* aDoc, nsISupports* aTarget, const nsAString& aEventName,
CanBubble aCanBubble, Cancelable aCancelable, bool* aDefaultAction) {

View File

@ -1520,6 +1520,12 @@ class nsContentUtils {
*/
static nsresult DispatchFocusChromeEvent(nsPIDOMWindowOuter* aWindow);
/**
* Helper to dispatch a "framefocusrequested" event to chrome, which will only
* bring the window to the foreground and switch tabs if aCanRaise is true.
*/
static void RequestFrameFocus(Element& aFrameElement, bool aCanRaise);
/**
* This method creates and dispatches a trusted event.
* If aTarget is not a chrome object, the nearest chrome object in the

View File

@ -4866,14 +4866,7 @@ void nsGlobalWindowOuter::FocusOuter() {
}
nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(mDocShell);
bool isVisible = false;
if (baseWin) {
baseWin->GetVisibility(&isVisible);
}
if (!isVisible) {
// A hidden tab is being focused, ignore this call.
if (!baseWin) {
return;
}
@ -4932,14 +4925,8 @@ void nsGlobalWindowOuter::FocusOuter() {
return;
}
RefPtr<Element> frame = parentdoc->FindContentForSubDocument(mDoc);
if (frame) {
uint32_t flags = nsIFocusManager::FLAG_NOSCROLL;
if (canFocus) flags |= nsIFocusManager::FLAG_RAISE;
DebugOnly<nsresult> rv = fm->SetFocus(frame, flags);
MOZ_ASSERT(NS_SUCCEEDED(rv),
"SetFocus only fails if the first argument is null, "
"but we pass an element");
if (Element* frame = parentdoc->FindContentForSubDocument(mDoc)) {
nsContentUtils::RequestFrameFocus(*frame, canFocus);
}
return;
}

View File

@ -159,22 +159,11 @@ IPCResult BrowserBridgeChild::RecvSetLayersId(
mozilla::ipc::IPCResult BrowserBridgeChild::RecvRequestFocus(
const bool& aCanRaise) {
// Adapted from BrowserParent
nsCOMPtr<nsIFocusManager> fm = nsFocusManager::GetFocusManager();
if (!fm) {
return IPC_OK();
}
RefPtr<Element> owner = mFrameLoader->GetOwnerContent();
if (!owner) {
return IPC_OK();
}
uint32_t flags = nsIFocusManager::FLAG_NOSCROLL;
if (aCanRaise) {
flags |= nsIFocusManager::FLAG_RAISE;
}
fm->SetFocus(owner, flags);
nsContentUtils::RequestFrameFocus(*owner, aCanRaise);
return IPC_OK();
}
@ -187,8 +176,7 @@ mozilla::ipc::IPCResult BrowserBridgeChild::RecvMoveFocus(
}
RefPtr<Element> owner = mFrameLoader->GetOwnerContent();
if (!owner || !owner->OwnerDoc()) {
if (!owner) {
return IPC_OK();
}

View File

@ -2121,26 +2121,16 @@ mozilla::ipc::IPCResult BrowserParent::RecvOnWindowedPluginKeyEvent(
mozilla::ipc::IPCResult BrowserParent::RecvRequestFocus(const bool& aCanRaise) {
LOGBROWSERFOCUS(("RecvRequestFocus %p, aCanRaise: %d", this, aCanRaise));
BrowserBridgeParent* bridgeParent = GetBrowserBridgeParent();
if (bridgeParent) {
if (BrowserBridgeParent* bridgeParent = GetBrowserBridgeParent()) {
mozilla::Unused << bridgeParent->SendRequestFocus(aCanRaise);
return IPC_OK();
}
nsCOMPtr<nsIFocusManager> fm = nsFocusManager::GetFocusManager();
if (!fm) {
return IPC_OK();
}
if (!mFrameElement) {
return IPC_OK();
}
uint32_t flags = nsIFocusManager::FLAG_NOSCROLL;
if (aCanRaise) flags |= nsIFocusManager::FLAG_RAISE;
RefPtr<Element> element = mFrameElement;
fm->SetFocus(element, flags);
nsContentUtils::RequestFrameFocus(*mFrameElement, aCanRaise);
return IPC_OK();
}