2015-05-03 22:32:37 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2012-05-21 15:12:37 +04:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2011-06-18 04:08:32 +04:00
|
|
|
#include "mozilla/dom/TabParent.h"
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
#include "nsFocusManager.h"
|
|
|
|
|
2015-04-24 03:08:00 +03:00
|
|
|
#include "AccessibleCaretEventHub.h"
|
2018-01-26 18:48:26 +03:00
|
|
|
#include "ChildIterator.h"
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
#include "nsIInterfaceRequestorUtils.h"
|
|
|
|
#include "nsGkAtoms.h"
|
2017-03-10 03:34:00 +03:00
|
|
|
#include "nsGlobalWindow.h"
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
#include "nsContentUtils.h"
|
2018-01-26 18:47:44 +03:00
|
|
|
#include "nsDocument.h"
|
2017-07-04 11:20:46 +03:00
|
|
|
#include "nsIContentParent.h"
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
#include "nsPIDOMWindow.h"
|
2015-07-13 13:07:49 +03:00
|
|
|
#include "nsIDOMChromeWindow.h"
|
2011-05-15 14:07:28 +04:00
|
|
|
#include "nsIDOMDocument.h"
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
#include "nsIDOMRange.h"
|
|
|
|
#include "nsIHTMLDocument.h"
|
|
|
|
#include "nsIDocShell.h"
|
|
|
|
#include "nsIDocShellTreeOwner.h"
|
2016-06-09 13:42:21 +03:00
|
|
|
#include "nsIFormControl.h"
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
#include "nsLayoutUtils.h"
|
|
|
|
#include "nsIPresShell.h"
|
2012-10-15 22:35:50 +04:00
|
|
|
#include "nsFrameTraversal.h"
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
#include "nsIWebNavigation.h"
|
|
|
|
#include "nsCaret.h"
|
|
|
|
#include "nsIBaseWindow.h"
|
2014-12-09 17:31:33 +03:00
|
|
|
#include "nsIXULWindow.h"
|
2013-01-05 07:12:24 +04:00
|
|
|
#include "nsViewManager.h"
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
#include "nsFrameSelection.h"
|
2014-04-10 20:09:40 +04:00
|
|
|
#include "mozilla/dom/Selection.h"
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
#include "nsXULPopupManager.h"
|
2015-07-13 13:07:49 +03:00
|
|
|
#include "nsMenuPopupFrame.h"
|
2010-04-24 14:40:48 +04:00
|
|
|
#include "nsIScriptObjectPrincipal.h"
|
|
|
|
#include "nsIPrincipal.h"
|
2012-06-06 11:40:02 +04:00
|
|
|
#include "nsIObserverService.h"
|
2013-08-15 22:17:48 +04:00
|
|
|
#include "nsIObjectFrame.h"
|
2013-08-20 02:55:18 +04:00
|
|
|
#include "nsBindingManager.h"
|
2013-10-01 01:26:04 +04:00
|
|
|
#include "nsStyleCoord.h"
|
2015-02-06 19:26:29 +03:00
|
|
|
#include "TabChild.h"
|
2015-07-13 13:07:49 +03:00
|
|
|
#include "nsFrameLoader.h"
|
2016-05-24 00:27:00 +03:00
|
|
|
#include "nsNumberControlFrame.h"
|
2017-03-10 03:34:00 +03:00
|
|
|
#include "nsNetUtil.h"
|
2018-01-30 07:10:51 +03:00
|
|
|
#include "nsRange.h"
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2013-09-25 15:21:20 +04:00
|
|
|
#include "mozilla/ContentEvents.h"
|
2012-06-06 11:40:02 +04:00
|
|
|
#include "mozilla/dom/Element.h"
|
2016-06-09 13:42:21 +03:00
|
|
|
#include "mozilla/dom/HTMLInputElement.h"
|
2018-01-26 18:48:26 +03:00
|
|
|
#include "mozilla/dom/HTMLSlotElement.h"
|
2018-03-29 01:01:47 +03:00
|
|
|
#include "mozilla/dom/Text.h"
|
2014-03-18 08:48:21 +04:00
|
|
|
#include "mozilla/EventDispatcher.h"
|
2014-04-01 08:09:23 +04:00
|
|
|
#include "mozilla/EventStateManager.h"
|
2014-04-03 08:18:36 +04:00
|
|
|
#include "mozilla/EventStates.h"
|
2017-08-07 08:55:58 +03:00
|
|
|
#include "mozilla/HTMLEditor.h"
|
2014-03-08 05:20:07 +04:00
|
|
|
#include "mozilla/IMEStateManager.h"
|
2012-06-06 11:40:02 +04:00
|
|
|
#include "mozilla/LookAndFeel.h"
|
|
|
|
#include "mozilla/Preferences.h"
|
2013-09-24 01:30:40 +04:00
|
|
|
#include "mozilla/Services.h"
|
2016-08-23 07:09:32 +03:00
|
|
|
#include "mozilla/Unused.h"
|
2013-01-15 16:22:03 +04:00
|
|
|
#include <algorithm>
|
2012-06-06 11:40:02 +04:00
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
#ifdef MOZ_XUL
|
|
|
|
#include "nsIDOMXULMenuListElement.h"
|
|
|
|
#endif
|
|
|
|
|
2011-09-28 05:46:11 +04:00
|
|
|
#ifdef ACCESSIBILITY
|
|
|
|
#include "nsAccessibilityService.h"
|
|
|
|
#endif
|
|
|
|
|
2013-08-15 22:17:48 +04:00
|
|
|
#ifndef XP_MACOSX
|
|
|
|
#include "nsIScriptError.h"
|
|
|
|
#endif
|
|
|
|
|
2011-05-25 10:31:59 +04:00
|
|
|
using namespace mozilla;
|
2010-04-30 17:12:05 +04:00
|
|
|
using namespace mozilla::dom;
|
2011-11-27 15:51:52 +04:00
|
|
|
using namespace mozilla::widget;
|
2010-04-30 17:12:05 +04:00
|
|
|
|
2012-07-31 04:43:28 +04:00
|
|
|
// Two types of focus pr logging are available:
|
|
|
|
// 'Focus' for normal focus manager calls
|
|
|
|
// 'FocusNavigation' for tab and document navigation
|
2015-11-23 22:09:25 +03:00
|
|
|
LazyLogModule gFocusLog("Focus");
|
|
|
|
LazyLogModule gFocusNavigationLog("FocusNavigation");
|
2012-07-31 04:43:28 +04:00
|
|
|
|
2015-06-04 01:25:57 +03:00
|
|
|
#define LOGFOCUS(args) MOZ_LOG(gFocusLog, mozilla::LogLevel::Debug, args)
|
|
|
|
#define LOGFOCUSNAVIGATION(args) MOZ_LOG(gFocusNavigationLog, mozilla::LogLevel::Debug, args)
|
2012-07-31 04:43:28 +04:00
|
|
|
|
|
|
|
#define LOGTAG(log, format, content) \
|
2015-06-04 01:25:57 +03:00
|
|
|
if (MOZ_LOG_TEST(log, LogLevel::Debug)) { \
|
2012-09-02 06:35:17 +04:00
|
|
|
nsAutoCString tag(NS_LITERAL_CSTRING("(none)")); \
|
2012-07-31 04:43:28 +04:00
|
|
|
if (content) { \
|
2015-03-03 14:09:00 +03:00
|
|
|
content->NodeInfo()->NameAtom()->ToUTF8String(tag); \
|
2012-07-31 04:43:28 +04:00
|
|
|
} \
|
2015-06-04 01:25:57 +03:00
|
|
|
MOZ_LOG(log, LogLevel::Debug, (format, tag.get())); \
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
2012-07-31 04:43:28 +04:00
|
|
|
#define LOGCONTENT(format, content) LOGTAG(gFocusLog, format, content)
|
|
|
|
#define LOGCONTENTNAVIGATION(format, content) LOGTAG(gFocusNavigationLog, format, content)
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
struct nsDelayedBlurOrFocusEvent
|
|
|
|
{
|
2015-08-26 15:56:59 +03:00
|
|
|
nsDelayedBlurOrFocusEvent(EventMessage aEventMessage,
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsIPresShell* aPresShell,
|
|
|
|
nsIDocument* aDocument,
|
2016-03-30 01:53:00 +03:00
|
|
|
EventTarget* aTarget,
|
|
|
|
EventTarget* aRelatedTarget)
|
2015-08-26 15:56:59 +03:00
|
|
|
: mPresShell(aPresShell)
|
|
|
|
, mDocument(aDocument)
|
|
|
|
, mTarget(aTarget)
|
|
|
|
, mEventMessage(aEventMessage)
|
2016-03-30 01:53:00 +03:00
|
|
|
, mRelatedTarget(aRelatedTarget)
|
2015-08-26 15:56:59 +03:00
|
|
|
{
|
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
nsDelayedBlurOrFocusEvent(const nsDelayedBlurOrFocusEvent& aOther)
|
2015-08-26 15:56:59 +03:00
|
|
|
: mPresShell(aOther.mPresShell)
|
|
|
|
, mDocument(aOther.mDocument)
|
|
|
|
, mTarget(aOther.mTarget)
|
|
|
|
, mEventMessage(aOther.mEventMessage)
|
|
|
|
{
|
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
nsCOMPtr<nsIPresShell> mPresShell;
|
|
|
|
nsCOMPtr<nsIDocument> mDocument;
|
2013-04-20 02:18:32 +04:00
|
|
|
nsCOMPtr<EventTarget> mTarget;
|
2015-08-26 15:56:59 +03:00
|
|
|
EventMessage mEventMessage;
|
2016-03-30 01:53:00 +03:00
|
|
|
nsCOMPtr<EventTarget> mRelatedTarget;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
};
|
|
|
|
|
2014-09-03 18:52:05 +04:00
|
|
|
inline void ImplCycleCollectionUnlink(nsDelayedBlurOrFocusEvent& aField)
|
|
|
|
{
|
|
|
|
aField.mPresShell = nullptr;
|
|
|
|
aField.mDocument = nullptr;
|
|
|
|
aField.mTarget = nullptr;
|
2016-03-30 01:53:00 +03:00
|
|
|
aField.mRelatedTarget = nullptr;
|
2014-09-03 18:52:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void
|
|
|
|
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
|
|
|
|
nsDelayedBlurOrFocusEvent& aField,
|
|
|
|
const char* aName,
|
|
|
|
uint32_t aFlags = 0)
|
|
|
|
{
|
|
|
|
CycleCollectionNoteChild(aCallback, aField.mPresShell.get(), aName, aFlags);
|
|
|
|
CycleCollectionNoteChild(aCallback, aField.mDocument.get(), aName, aFlags);
|
|
|
|
CycleCollectionNoteChild(aCallback, aField.mTarget.get(), aName, aFlags);
|
2016-03-30 01:53:00 +03:00
|
|
|
CycleCollectionNoteChild(aCallback, aField.mRelatedTarget.get(), aName, aFlags);
|
2014-09-03 18:52:05 +04:00
|
|
|
}
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFocusManager)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIFocusManager)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
|
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIFocusManager)
|
|
|
|
NS_INTERFACE_MAP_END
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFocusManager)
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFocusManager)
|
|
|
|
|
2014-04-25 20:49:00 +04:00
|
|
|
NS_IMPL_CYCLE_COLLECTION(nsFocusManager,
|
|
|
|
mActiveWindow,
|
|
|
|
mFocusedWindow,
|
2018-04-26 22:28:31 +03:00
|
|
|
mFocusedElement,
|
2014-04-25 20:49:00 +04:00
|
|
|
mFirstBlurEvent,
|
|
|
|
mFirstFocusEvent,
|
2014-09-03 18:52:05 +04:00
|
|
|
mWindowBeingLowered,
|
|
|
|
mDelayedBlurFocusEvents,
|
|
|
|
mMouseButtonEventHandlingDocument)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
nsFocusManager* nsFocusManager::sInstance = nullptr;
|
2011-09-29 10:19:26 +04:00
|
|
|
bool nsFocusManager::sMouseFocusesFormControl = false;
|
2012-01-13 16:42:18 +04:00
|
|
|
bool nsFocusManager::sTestMode = false;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2011-05-29 03:39:27 +04:00
|
|
|
static const char* kObservedPrefs[] = {
|
|
|
|
"accessibility.browsewithcaret",
|
|
|
|
"accessibility.tabfocus_applies_to_xul",
|
|
|
|
"accessibility.mouse_focuses_formcontrol",
|
2012-01-13 16:42:18 +04:00
|
|
|
"focusmanager.testmode",
|
2013-10-28 18:04:12 +04:00
|
|
|
nullptr
|
2011-05-29 03:39:27 +04:00
|
|
|
};
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsFocusManager::nsFocusManager()
|
2017-05-19 23:20:48 +03:00
|
|
|
: mEventHandlingNeedsFlush(false)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{ }
|
|
|
|
|
|
|
|
nsFocusManager::~nsFocusManager()
|
|
|
|
{
|
2011-05-29 03:39:27 +04:00
|
|
|
Preferences::RemoveObservers(this, kObservedPrefs);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2010-12-18 00:48:00 +03:00
|
|
|
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
|
|
|
if (obs) {
|
|
|
|
obs->RemoveObserver(this, "xpcom-shutdown");
|
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
nsresult
|
|
|
|
nsFocusManager::Init()
|
|
|
|
{
|
|
|
|
nsFocusManager* fm = new nsFocusManager();
|
|
|
|
NS_ADDREF(fm);
|
|
|
|
sInstance = fm;
|
|
|
|
|
|
|
|
nsIContent::sTabFocusModelAppliesToXUL =
|
2011-05-25 10:31:59 +04:00
|
|
|
Preferences::GetBool("accessibility.tabfocus_applies_to_xul",
|
|
|
|
nsIContent::sTabFocusModelAppliesToXUL);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2010-08-09 20:15:47 +04:00
|
|
|
sMouseFocusesFormControl =
|
2011-09-29 10:19:26 +04:00
|
|
|
Preferences::GetBool("accessibility.mouse_focuses_formcontrol", false);
|
2010-08-09 20:15:47 +04:00
|
|
|
|
2012-01-13 16:42:18 +04:00
|
|
|
sTestMode = Preferences::GetBool("focusmanager.testmode", false);
|
|
|
|
|
2011-05-29 03:39:27 +04:00
|
|
|
Preferences::AddWeakObservers(fm, kObservedPrefs);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2010-12-18 00:48:00 +03:00
|
|
|
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
|
|
|
if (obs) {
|
2011-10-17 18:59:28 +04:00
|
|
|
obs->AddObserver(fm, "xpcom-shutdown", true);
|
2010-12-18 00:48:00 +03:00
|
|
|
}
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
void
|
|
|
|
nsFocusManager::Shutdown()
|
|
|
|
{
|
|
|
|
NS_IF_RELEASE(sInstance);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFocusManager::Observe(nsISupports *aSubject,
|
|
|
|
const char *aTopic,
|
2014-01-04 19:02:17 +04:00
|
|
|
const char16_t *aData)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
|
|
|
if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
|
2010-12-18 00:48:00 +03:00
|
|
|
nsDependentString data(aData);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (data.EqualsLiteral("accessibility.browsewithcaret")) {
|
2013-05-22 07:28:43 +04:00
|
|
|
UpdateCaretForCaretBrowsingMode();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
else if (data.EqualsLiteral("accessibility.tabfocus_applies_to_xul")) {
|
|
|
|
nsIContent::sTabFocusModelAppliesToXUL =
|
2011-05-25 10:31:59 +04:00
|
|
|
Preferences::GetBool("accessibility.tabfocus_applies_to_xul",
|
|
|
|
nsIContent::sTabFocusModelAppliesToXUL);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
2010-08-09 20:15:47 +04:00
|
|
|
else if (data.EqualsLiteral("accessibility.mouse_focuses_formcontrol")) {
|
|
|
|
sMouseFocusesFormControl =
|
2011-05-25 10:31:59 +04:00
|
|
|
Preferences::GetBool("accessibility.mouse_focuses_formcontrol",
|
2011-09-29 10:19:26 +04:00
|
|
|
false);
|
2010-08-09 20:15:47 +04:00
|
|
|
}
|
2012-01-13 16:42:18 +04:00
|
|
|
else if (data.EqualsLiteral("focusmanager.testmode")) {
|
|
|
|
sTestMode = Preferences::GetBool("focusmanager.testmode", false);
|
|
|
|
}
|
2010-12-18 00:48:00 +03:00
|
|
|
} else if (!nsCRT::strcmp(aTopic, "xpcom-shutdown")) {
|
2012-07-30 18:20:58 +04:00
|
|
|
mActiveWindow = nullptr;
|
|
|
|
mFocusedWindow = nullptr;
|
2018-04-26 22:28:31 +03:00
|
|
|
mFocusedElement = nullptr;
|
2012-07-30 18:20:58 +04:00
|
|
|
mFirstBlurEvent = nullptr;
|
|
|
|
mFirstFocusEvent = nullptr;
|
|
|
|
mWindowBeingLowered = nullptr;
|
2011-06-18 13:12:13 +04:00
|
|
|
mDelayedBlurFocusEvents.Clear();
|
2014-06-18 10:13:00 +04:00
|
|
|
mMouseButtonEventHandlingDocument = nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2017-07-06 15:00:35 +03:00
|
|
|
// given a frame content node, retrieve the nsIDOMWindow displayed in it
|
2016-01-30 20:05:36 +03:00
|
|
|
static nsPIDOMWindowOuter*
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
GetContentWindow(nsIContent* aContent)
|
|
|
|
{
|
2014-08-06 03:23:02 +04:00
|
|
|
nsIDocument* doc = aContent->GetComposedDoc();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (doc) {
|
|
|
|
nsIDocument* subdoc = doc->GetSubDocumentFor(aContent);
|
|
|
|
if (subdoc)
|
|
|
|
return subdoc->GetWindow();
|
|
|
|
}
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
2017-08-03 22:07:14 +03:00
|
|
|
bool
|
|
|
|
nsFocusManager::IsFocused(nsIContent* aContent)
|
|
|
|
{
|
2018-04-26 22:28:31 +03:00
|
|
|
if (!aContent || !mFocusedElement) {
|
2017-08-03 22:07:14 +03:00
|
|
|
return false;
|
|
|
|
}
|
2018-04-26 22:28:31 +03:00
|
|
|
return aContent == mFocusedElement;
|
2017-08-03 22:07:14 +03:00
|
|
|
}
|
|
|
|
|
2017-07-06 15:00:35 +03:00
|
|
|
// get the current window for the given content node
|
2016-01-30 20:05:36 +03:00
|
|
|
static nsPIDOMWindowOuter*
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
GetCurrentWindow(nsIContent* aContent)
|
|
|
|
{
|
2014-08-06 03:23:02 +04:00
|
|
|
nsIDocument* doc = aContent->GetComposedDoc();
|
2012-07-30 18:20:58 +04:00
|
|
|
return doc ? doc->GetWindow() : nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
2018-04-26 17:37:47 +03:00
|
|
|
Element*
|
2017-09-07 16:54:49 +03:00
|
|
|
nsFocusManager::GetFocusedDescendant(nsPIDOMWindowOuter* aWindow,
|
|
|
|
SearchRange aSearchRange,
|
2016-01-30 20:05:36 +03:00
|
|
|
nsPIDOMWindowOuter** aFocusedWindow)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
NS_ENSURE_TRUE(aWindow, nullptr);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
*aFocusedWindow = nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2018-04-26 22:28:31 +03:00
|
|
|
Element* currentElement = nullptr;
|
2016-01-30 20:05:36 +03:00
|
|
|
nsPIDOMWindowOuter* window = aWindow;
|
2017-09-07 16:54:49 +03:00
|
|
|
for (;;) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
*aFocusedWindow = window;
|
2018-04-26 22:28:31 +03:00
|
|
|
currentElement = window->GetFocusedElement();
|
|
|
|
if (!currentElement || aSearchRange == eOnlyCurrentWindow) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
break;
|
2017-09-07 16:54:49 +03:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2018-04-26 22:28:31 +03:00
|
|
|
window = GetContentWindow(currentElement);
|
2017-09-07 16:54:49 +03:00
|
|
|
if (!window) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aSearchRange == eIncludeAllDescendants) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(aSearchRange == eIncludeVisibleDescendants);
|
|
|
|
|
|
|
|
// If the child window doesn't have PresShell, it means the window is
|
|
|
|
// invisible.
|
|
|
|
nsIDocShell* docShell = window->GetDocShell();
|
|
|
|
if (!docShell) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
nsIPresShell* presShell = docShell->GetPresShell();
|
|
|
|
if (!presShell) {
|
|
|
|
break;
|
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IF_ADDREF(*aFocusedWindow);
|
|
|
|
|
2018-04-26 22:28:31 +03:00
|
|
|
return currentElement;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
2018-04-26 17:37:47 +03:00
|
|
|
Element*
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsFocusManager::GetRedirectedFocus(nsIContent* aContent)
|
|
|
|
{
|
2016-05-24 00:27:00 +03:00
|
|
|
// For input number, redirect focus to our anonymous text control.
|
|
|
|
if (aContent->IsHTMLElement(nsGkAtoms::input)) {
|
|
|
|
bool typeIsNumber =
|
2017-04-01 05:49:00 +03:00
|
|
|
static_cast<dom::HTMLInputElement*>(aContent)->ControlType() ==
|
2016-05-24 00:27:00 +03:00
|
|
|
NS_FORM_INPUT_NUMBER;
|
|
|
|
|
|
|
|
if (typeIsNumber) {
|
|
|
|
nsNumberControlFrame* numberControlFrame =
|
|
|
|
do_QueryFrame(aContent->GetPrimaryFrame());
|
|
|
|
|
|
|
|
if (numberControlFrame) {
|
|
|
|
HTMLInputElement* textControl =
|
|
|
|
numberControlFrame->GetAnonTextControl();
|
2018-04-26 17:37:47 +03:00
|
|
|
return textControl;
|
2016-05-24 00:27:00 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
#ifdef MOZ_XUL
|
2015-03-03 14:08:59 +03:00
|
|
|
if (aContent->IsXULElement()) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsCOMPtr<nsIDOMNode> inputField;
|
|
|
|
|
2018-04-27 01:15:10 +03:00
|
|
|
if (aContent->IsXULElement(nsGkAtoms::textbox)) {
|
|
|
|
return aContent->OwnerDoc()->
|
|
|
|
GetAnonymousElementByAttribute(aContent, nsGkAtoms::anonid, NS_LITERAL_STRING("input"));
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
nsCOMPtr<nsIDOMXULMenuListElement> menulist = do_QueryInterface(aContent);
|
|
|
|
if (menulist) {
|
|
|
|
menulist->GetInputField(getter_AddRefs(inputField));
|
|
|
|
}
|
2015-03-03 14:09:00 +03:00
|
|
|
else if (aContent->IsXULElement(nsGkAtoms::scale)) {
|
2014-08-06 03:23:02 +04:00
|
|
|
nsCOMPtr<nsIDocument> doc = aContent->GetComposedDoc();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (!doc)
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2013-05-02 02:50:08 +04:00
|
|
|
nsINodeList* children = doc->BindingManager()->GetAnonymousNodesFor(aContent);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (children) {
|
2012-10-13 16:50:24 +04:00
|
|
|
nsIContent* child = children->Item(0);
|
2015-03-03 14:09:00 +03:00
|
|
|
if (child && child->IsXULElement(nsGkAtoms::slider))
|
2018-04-26 17:37:47 +03:00
|
|
|
return child->AsElement();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (inputField) {
|
2018-04-26 17:37:47 +03:00
|
|
|
nsCOMPtr<Element> retval = do_QueryInterface(inputField);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
2011-04-20 16:47:40 +04:00
|
|
|
// static
|
2011-11-27 15:51:52 +04:00
|
|
|
InputContextAction::Cause
|
2012-08-22 19:56:38 +04:00
|
|
|
nsFocusManager::GetFocusMoveActionCause(uint32_t aFlags)
|
2011-04-20 16:47:40 +04:00
|
|
|
{
|
2015-11-12 19:36:19 +03:00
|
|
|
if (aFlags & nsIFocusManager::FLAG_BYTOUCH) {
|
|
|
|
return InputContextAction::CAUSE_TOUCH;
|
|
|
|
} else if (aFlags & nsIFocusManager::FLAG_BYMOUSE) {
|
2011-11-27 15:51:52 +04:00
|
|
|
return InputContextAction::CAUSE_MOUSE;
|
2011-04-20 16:47:40 +04:00
|
|
|
} else if (aFlags & nsIFocusManager::FLAG_BYKEY) {
|
2011-11-27 15:51:52 +04:00
|
|
|
return InputContextAction::CAUSE_KEY;
|
2011-04-20 16:47:40 +04:00
|
|
|
}
|
2011-11-27 15:51:52 +04:00
|
|
|
return InputContextAction::CAUSE_UNKNOWN;
|
2011-04-20 16:47:40 +04:00
|
|
|
}
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
NS_IMETHODIMP
|
2016-01-30 20:05:36 +03:00
|
|
|
nsFocusManager::GetActiveWindow(mozIDOMWindowProxy** aWindow)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
|
|
|
NS_IF_ADDREF(*aWindow = mActiveWindow);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2016-01-30 20:05:36 +03:00
|
|
|
nsFocusManager::SetActiveWindow(mozIDOMWindowProxy* aWindow)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
2016-01-30 20:05:36 +03:00
|
|
|
NS_ENSURE_STATE(aWindow);
|
2017-07-06 15:00:35 +03:00
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// only top-level windows can be made active
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> piWindow = nsPIDOMWindowOuter::From(aWindow);
|
|
|
|
NS_ENSURE_TRUE(piWindow == piWindow->GetPrivateRoot(), NS_ERROR_INVALID_ARG);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
RaiseWindow(piWindow);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2016-01-30 20:05:36 +03:00
|
|
|
nsFocusManager::GetFocusedWindow(mozIDOMWindowProxy** aFocusedWindow)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
|
|
|
NS_IF_ADDREF(*aFocusedWindow = mFocusedWindow);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
NS_IMETHODIMP nsFocusManager::SetFocusedWindow(mozIDOMWindowProxy* aWindowToFocus)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
2012-07-31 04:43:28 +04:00
|
|
|
LOGFOCUS(("<<SetFocusedWindow begin>>"));
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> windowToFocus = nsPIDOMWindowOuter::From(aWindowToFocus);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
NS_ENSURE_TRUE(windowToFocus, NS_ERROR_FAILURE);
|
|
|
|
|
|
|
|
windowToFocus = windowToFocus->GetOuterWindow();
|
|
|
|
|
2014-01-24 01:14:29 +04:00
|
|
|
nsCOMPtr<Element> frameElement = windowToFocus->GetFrameElementInternal();
|
|
|
|
if (frameElement) {
|
2010-11-16 00:12:50 +03:00
|
|
|
// pass false for aFocusChanged so that the caret does not get updated
|
|
|
|
// and scrolling does not occur.
|
2014-01-24 01:14:29 +04:00
|
|
|
SetFocusInner(frameElement, 0, false, true);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
// this is a top-level window. If the window has a child frame focused,
|
|
|
|
// clear the focus. Otherwise, focus should already be in this frame, or
|
|
|
|
// already cleared. This ensures that focus will be in this frame and not
|
|
|
|
// in a child.
|
2018-04-26 22:28:30 +03:00
|
|
|
nsIContent* content = windowToFocus->GetFocusedElement();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (content) {
|
2016-01-30 20:05:36 +03:00
|
|
|
if (nsCOMPtr<nsPIDOMWindowOuter> childWindow = GetContentWindow(content))
|
2010-04-21 18:53:42 +04:00
|
|
|
ClearFocus(windowToFocus);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> rootWindow = windowToFocus->GetPrivateRoot();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (rootWindow)
|
|
|
|
RaiseWindow(rootWindow);
|
|
|
|
|
2012-07-31 04:43:28 +04:00
|
|
|
LOGFOCUS(("<<SetFocusedWindow end>>"));
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2018-04-27 06:35:19 +03:00
|
|
|
nsFocusManager::GetFocusedElement(Element** aFocusedElement)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
2018-04-27 06:35:19 +03:00
|
|
|
RefPtr<Element> focusedElement = mFocusedElement;
|
|
|
|
focusedElement.forget(aFocusedElement);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2016-01-30 20:05:36 +03:00
|
|
|
nsFocusManager::GetLastFocusMethod(mozIDOMWindowProxy* aWindow, uint32_t* aLastFocusMethod)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
|
|
|
// the focus method is stored on the inner window
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> window;
|
|
|
|
if (aWindow) {
|
|
|
|
window = nsPIDOMWindowOuter::From(aWindow);
|
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (!window)
|
|
|
|
window = mFocusedWindow;
|
|
|
|
|
|
|
|
*aLastFocusMethod = window ? window->GetFocusMethod() : 0;
|
|
|
|
|
|
|
|
NS_ASSERTION((*aLastFocusMethod & FOCUSMETHOD_MASK) == *aLastFocusMethod,
|
|
|
|
"invalid focus method");
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2018-04-26 17:37:46 +03:00
|
|
|
nsFocusManager::SetFocus(Element* aElement, uint32_t aFlags)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
2012-07-31 04:43:28 +04:00
|
|
|
LOGFOCUS(("<<SetFocus begin>>"));
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2018-04-26 17:37:46 +03:00
|
|
|
NS_ENSURE_ARG(aElement);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2018-04-26 17:37:46 +03:00
|
|
|
SetFocusInner(aElement, aFlags, true, true);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2012-07-31 04:43:28 +04:00
|
|
|
LOGFOCUS(("<<SetFocus end>>"));
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-11-10 20:20:47 +04:00
|
|
|
NS_IMETHODIMP
|
2018-04-26 17:37:47 +03:00
|
|
|
nsFocusManager::ElementIsFocusable(Element* aElement, uint32_t aFlags,
|
2011-11-10 20:20:47 +04:00
|
|
|
bool* aIsFocusable)
|
|
|
|
{
|
|
|
|
NS_ENSURE_TRUE(aElement, NS_ERROR_INVALID_ARG);
|
|
|
|
|
2018-04-26 17:37:47 +03:00
|
|
|
*aIsFocusable = CheckIfFocusable(aElement, aFlags) != nullptr;
|
2011-11-10 20:20:47 +04:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
NS_IMETHODIMP
|
2018-04-26 17:37:47 +03:00
|
|
|
nsFocusManager::MoveFocus(mozIDOMWindowProxy* aWindow, Element* aStartElement,
|
|
|
|
uint32_t aType, uint32_t aFlags, Element** aElement)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
*aElement = nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2012-07-31 04:43:28 +04:00
|
|
|
LOGFOCUS(("<<MoveFocus begin Type: %d Flags: %x>>", aType, aFlags));
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2015-06-04 01:25:57 +03:00
|
|
|
if (MOZ_LOG_TEST(gFocusLog, LogLevel::Debug) && mFocusedWindow) {
|
2012-07-31 04:43:28 +04:00
|
|
|
nsIDocument* doc = mFocusedWindow->GetExtantDoc();
|
|
|
|
if (doc && doc->GetDocumentURI()) {
|
2016-08-26 09:02:31 +03:00
|
|
|
LOGFOCUS((" Focused Window: %p %s",
|
|
|
|
mFocusedWindow.get(),
|
|
|
|
doc->GetDocumentURI()->GetSpecOrDefault().get()));
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
}
|
2012-07-31 04:43:28 +04:00
|
|
|
|
2018-04-26 22:28:31 +03:00
|
|
|
LOGCONTENT(" Current Focus: %s", mFocusedElement.get());
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2009-08-26 20:19:41 +04:00
|
|
|
// use FLAG_BYMOVEFOCUS when switching focus with MoveFocus unless one of
|
|
|
|
// the other focus methods is already set, or we're just moving to the root
|
|
|
|
// or caret position.
|
|
|
|
if (aType != MOVEFOCUS_ROOT && aType != MOVEFOCUS_CARET &&
|
|
|
|
(aFlags & FOCUSMETHOD_MASK) == 0) {
|
|
|
|
aFlags |= FLAG_BYMOVEFOCUS;
|
|
|
|
}
|
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> window;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (aStartElement) {
|
2018-04-26 17:37:47 +03:00
|
|
|
window = GetCurrentWindow(aStartElement);
|
2017-05-03 13:41:24 +03:00
|
|
|
} else {
|
2016-01-30 20:05:36 +03:00
|
|
|
window = aWindow ? nsPIDOMWindowOuter::From(aWindow) : mFocusedWindow.get();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
|
|
|
|
|
2012-02-13 23:24:28 +04:00
|
|
|
bool noParentTraversal = aFlags & FLAG_NOPARENTFRAME;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsCOMPtr<nsIContent> newFocus;
|
2018-04-26 17:37:47 +03:00
|
|
|
nsresult rv = DetermineElementToMoveFocus(window, aStartElement, aType, noParentTraversal,
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
getter_AddRefs(newFocus));
|
2015-07-13 13:07:49 +03:00
|
|
|
if (rv == NS_SUCCESS_DOM_NO_OPERATION) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2012-07-31 04:43:28 +04:00
|
|
|
LOGCONTENTNAVIGATION("Element to be focused: %s", newFocus.get());
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2018-04-26 17:37:47 +03:00
|
|
|
if (newFocus && newFocus->IsElement()) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// for caret movement, pass false for the aFocusChanged argument,
|
|
|
|
// otherwise the caret will end up moving to the focus position. This
|
|
|
|
// would be a problem because the caret would move to the beginning of the
|
|
|
|
// focused link making it impossible to navigate the caret over a link.
|
2018-04-26 17:37:47 +03:00
|
|
|
SetFocusInner(newFocus->AsElement(), aFlags, aType != MOVEFOCUS_CARET,
|
|
|
|
true);
|
2018-04-26 17:37:47 +03:00
|
|
|
*aElement = do_AddRef(newFocus->AsElement()).take();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
else if (aType == MOVEFOCUS_ROOT || aType == MOVEFOCUS_CARET) {
|
|
|
|
// no content was found, so clear the focus for these two types.
|
|
|
|
ClearFocus(window);
|
|
|
|
}
|
|
|
|
|
2012-07-31 04:43:28 +04:00
|
|
|
LOGFOCUS(("<<MoveFocus end>>"));
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2016-01-30 20:05:36 +03:00
|
|
|
nsFocusManager::ClearFocus(mozIDOMWindowProxy* aWindow)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
2012-07-31 04:43:28 +04:00
|
|
|
LOGFOCUS(("<<ClearFocus begin>>"));
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
// if the window to clear is the focused window or an ancestor of the
|
|
|
|
// focused window, then blur the existing focused content. Otherwise, the
|
|
|
|
// focus is somewhere else so just update the current node.
|
2016-01-30 20:05:36 +03:00
|
|
|
NS_ENSURE_TRUE(aWindow, NS_ERROR_INVALID_ARG);
|
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> window = nsPIDOMWindowOuter::From(aWindow);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
if (IsSameOrAncestor(window, mFocusedWindow)) {
|
2011-09-29 10:19:26 +04:00
|
|
|
bool isAncestor = (window != mFocusedWindow);
|
2012-07-30 18:20:58 +04:00
|
|
|
if (Blur(window, nullptr, isAncestor, true)) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// if we are clearing the focus on an ancestor of the focused window,
|
|
|
|
// the ancestor will become the new focused window, so focus it
|
|
|
|
if (isAncestor)
|
2012-07-30 18:20:58 +04:00
|
|
|
Focus(window, nullptr, 0, true, false, false, true);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2018-04-26 22:28:30 +03:00
|
|
|
window->SetFocusedElement(nullptr);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
2012-07-31 04:43:28 +04:00
|
|
|
LOGFOCUS(("<<ClearFocus end>>"));
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2016-01-30 20:05:36 +03:00
|
|
|
nsFocusManager::GetFocusedElementForWindow(mozIDOMWindowProxy* aWindow,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aDeep,
|
2016-01-30 20:05:36 +03:00
|
|
|
mozIDOMWindowProxy** aFocusedWindow,
|
2018-04-27 06:35:19 +03:00
|
|
|
Element** aElement)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
*aElement = nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (aFocusedWindow)
|
2012-07-30 18:20:58 +04:00
|
|
|
*aFocusedWindow = nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
NS_ENSURE_TRUE(aWindow, NS_ERROR_INVALID_ARG);
|
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> window = nsPIDOMWindowOuter::From(aWindow);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
|
2018-04-27 06:35:19 +03:00
|
|
|
RefPtr<Element> focusedElement =
|
2017-09-07 16:54:49 +03:00
|
|
|
GetFocusedDescendant(window,
|
|
|
|
aDeep ? nsFocusManager::eIncludeAllDescendants :
|
|
|
|
nsFocusManager::eOnlyCurrentWindow,
|
|
|
|
getter_AddRefs(focusedWindow));
|
2018-04-27 06:35:19 +03:00
|
|
|
|
|
|
|
focusedElement.forget(aElement);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
if (aFocusedWindow)
|
|
|
|
NS_IF_ADDREF(*aFocusedWindow = focusedWindow);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2016-01-30 20:05:36 +03:00
|
|
|
nsFocusManager::MoveCaretToFocus(mozIDOMWindowProxy* aWindow)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIWebNavigation> webnav = do_GetInterface(aWindow);
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> dsti = do_QueryInterface(webnav);
|
|
|
|
if (dsti) {
|
2014-01-20 11:58:26 +04:00
|
|
|
if (dsti->ItemType() != nsIDocShellTreeItem::typeChrome) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(dsti);
|
|
|
|
NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
|
|
|
|
|
2013-02-14 02:39:30 +04:00
|
|
|
// don't move the caret for editable documents
|
|
|
|
bool isEditable;
|
|
|
|
docShell->GetEditable(&isEditable);
|
|
|
|
if (isEditable)
|
|
|
|
return NS_OK;
|
|
|
|
|
2012-12-29 05:56:42 +04:00
|
|
|
nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
|
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> window = nsPIDOMWindowOuter::From(aWindow);
|
2018-04-26 22:28:30 +03:00
|
|
|
nsCOMPtr<nsIContent> content = window->GetFocusedElement();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (content)
|
|
|
|
MoveCaretToFocus(presShell, content);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2016-01-30 20:05:36 +03:00
|
|
|
nsFocusManager::WindowRaised(mozIDOMWindowProxy* aWindow)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
2016-01-30 20:05:36 +03:00
|
|
|
NS_ENSURE_TRUE(aWindow, NS_ERROR_INVALID_ARG);
|
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> window = nsPIDOMWindowOuter::From(aWindow);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2015-06-04 01:25:57 +03:00
|
|
|
if (MOZ_LOG_TEST(gFocusLog, LogLevel::Debug)) {
|
2012-07-31 04:43:28 +04:00
|
|
|
LOGFOCUS(("Window %p Raised [Currently: %p %p]", aWindow, mActiveWindow.get(), mFocusedWindow.get()));
|
|
|
|
nsIDocument* doc = window->GetExtantDoc();
|
|
|
|
if (doc && doc->GetDocumentURI()) {
|
2016-08-26 09:02:31 +03:00
|
|
|
LOGFOCUS((" Raised Window: %p %s", aWindow,
|
|
|
|
doc->GetDocumentURI()->GetSpecOrDefault().get()));
|
2012-07-31 04:43:28 +04:00
|
|
|
}
|
|
|
|
if (mActiveWindow) {
|
|
|
|
doc = mActiveWindow->GetExtantDoc();
|
|
|
|
if (doc && doc->GetDocumentURI()) {
|
2016-08-26 09:02:31 +03:00
|
|
|
LOGFOCUS((" Active Window: %p %s", mActiveWindow.get(),
|
|
|
|
doc->GetDocumentURI()->GetSpecOrDefault().get()));
|
2012-07-31 04:43:28 +04:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mActiveWindow == window) {
|
|
|
|
// The window is already active, so there is no need to focus anything,
|
|
|
|
// but make sure that the right widget is focused. This is a special case
|
|
|
|
// for Windows because when restoring a minimized window, a second
|
|
|
|
// activation will occur and the top-level widget could be focused instead
|
|
|
|
// of the child we want. We solve this by calling SetFocus to ensure that
|
|
|
|
// what the focus manager thinks should be the current widget is actually
|
|
|
|
// focused.
|
|
|
|
EnsureCurrentWidgetFocused();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// lower the existing window, if any. This shouldn't happen usually.
|
|
|
|
if (mActiveWindow)
|
|
|
|
WindowLowered(mActiveWindow);
|
|
|
|
|
2014-01-10 06:03:47 +04:00
|
|
|
nsCOMPtr<nsIDocShellTreeItem> docShellAsItem = window->GetDocShell();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// If there's no docShellAsItem, this window must have been closed,
|
|
|
|
// in that case there is no tree owner.
|
|
|
|
NS_ENSURE_TRUE(docShellAsItem, NS_OK);
|
|
|
|
|
|
|
|
// set this as the active window
|
|
|
|
mActiveWindow = window;
|
|
|
|
|
|
|
|
// ensure that the window is enabled and visible
|
|
|
|
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
|
|
|
|
docShellAsItem->GetTreeOwner(getter_AddRefs(treeOwner));
|
|
|
|
nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(treeOwner);
|
|
|
|
if (baseWindow) {
|
2011-09-29 10:19:26 +04:00
|
|
|
bool isEnabled = true;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (NS_SUCCEEDED(baseWindow->GetEnabled(&isEnabled)) && !isEnabled) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2013-07-05 20:05:26 +04:00
|
|
|
if (!sTestMode) {
|
|
|
|
baseWindow->SetVisibility(true);
|
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
2014-11-27 16:28:26 +03:00
|
|
|
// If this is a parent or single process window, send the activate event.
|
|
|
|
// Events for child process windows will be sent when ParentActivated
|
|
|
|
// is called.
|
2015-07-04 04:29:00 +03:00
|
|
|
if (XRE_IsParentProcess()) {
|
2014-11-27 16:28:26 +03:00
|
|
|
ActivateOrDeactivate(window, true);
|
|
|
|
}
|
2009-10-29 22:11:00 +03:00
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// retrieve the last focused element within the window that was raised
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> currentWindow;
|
2018-04-26 17:37:47 +03:00
|
|
|
RefPtr<Element> currentFocus =
|
2017-09-07 16:54:49 +03:00
|
|
|
GetFocusedDescendant(window, eIncludeAllDescendants,
|
|
|
|
getter_AddRefs(currentWindow));
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
NS_ASSERTION(currentWindow, "window raised with no window current");
|
|
|
|
if (!currentWindow)
|
|
|
|
return NS_OK;
|
|
|
|
|
2014-12-09 17:31:33 +03:00
|
|
|
// If there is no nsIXULWindow, then this is an embedded or child process window.
|
|
|
|
// Pass false for aWindowRaised so that commands get updated.
|
|
|
|
nsCOMPtr<nsIXULWindow> xulWin(do_GetInterface(baseWindow));
|
|
|
|
Focus(currentWindow, currentFocus, 0, true, false, xulWin != nullptr, true);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2016-01-30 20:05:36 +03:00
|
|
|
nsFocusManager::WindowLowered(mozIDOMWindowProxy* aWindow)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
2016-01-30 20:05:36 +03:00
|
|
|
NS_ENSURE_TRUE(aWindow, NS_ERROR_INVALID_ARG);
|
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> window = nsPIDOMWindowOuter::From(aWindow);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2015-06-04 01:25:57 +03:00
|
|
|
if (MOZ_LOG_TEST(gFocusLog, LogLevel::Debug)) {
|
2012-07-31 04:43:28 +04:00
|
|
|
LOGFOCUS(("Window %p Lowered [Currently: %p %p]", aWindow, mActiveWindow.get(), mFocusedWindow.get()));
|
|
|
|
nsIDocument* doc = window->GetExtantDoc();
|
|
|
|
if (doc && doc->GetDocumentURI()) {
|
2016-08-26 09:02:31 +03:00
|
|
|
LOGFOCUS((" Lowered Window: %s",
|
|
|
|
doc->GetDocumentURI()->GetSpecOrDefault().get()));
|
2012-07-31 04:43:28 +04:00
|
|
|
}
|
|
|
|
if (mActiveWindow) {
|
|
|
|
doc = mActiveWindow->GetExtantDoc();
|
|
|
|
if (doc && doc->GetDocumentURI()) {
|
2016-08-26 09:02:31 +03:00
|
|
|
LOGFOCUS((" Active Window: %s",
|
|
|
|
doc->GetDocumentURI()->GetSpecOrDefault().get()));
|
2012-07-31 04:43:28 +04:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mActiveWindow != window)
|
|
|
|
return NS_OK;
|
|
|
|
|
2010-02-20 19:06:58 +03:00
|
|
|
// clear the mouse capture as the active window has changed
|
2012-07-30 18:20:58 +04:00
|
|
|
nsIPresShell::SetCapturingContent(nullptr, 0);
|
2010-02-20 19:06:58 +03:00
|
|
|
|
2015-07-15 21:55:18 +03:00
|
|
|
// In addition, reset the drag state to ensure that we are no longer in
|
|
|
|
// drag-select mode.
|
|
|
|
if (mFocusedWindow) {
|
|
|
|
nsCOMPtr<nsIDocShell> docShell = mFocusedWindow->GetDocShell();
|
|
|
|
if (docShell) {
|
|
|
|
nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
|
|
|
|
if (presShell) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsFrameSelection> frameSelection = presShell->FrameSelection();
|
2015-07-15 21:55:18 +03:00
|
|
|
frameSelection->SetDragState(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-27 16:28:26 +03:00
|
|
|
// If this is a parent or single process window, send the deactivate event.
|
|
|
|
// Events for child process windows will be sent when ParentActivated
|
|
|
|
// is called.
|
2015-07-04 04:29:00 +03:00
|
|
|
if (XRE_IsParentProcess()) {
|
2014-11-27 16:28:26 +03:00
|
|
|
ActivateOrDeactivate(window, false);
|
|
|
|
}
|
2009-10-29 22:11:00 +03:00
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// keep track of the window being lowered, so that attempts to raise the
|
|
|
|
// window can be prevented until we return. Otherwise, focus can get into
|
|
|
|
// an unusual state.
|
|
|
|
mWindowBeingLowered = mActiveWindow;
|
2012-07-30 18:20:58 +04:00
|
|
|
mActiveWindow = nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
if (mFocusedWindow)
|
2012-07-30 18:20:58 +04:00
|
|
|
Blur(nullptr, nullptr, true, true);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
mWindowBeingLowered = nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-04-27 13:58:58 +04:00
|
|
|
nsresult
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsFocusManager::ContentRemoved(nsIDocument* aDocument, nsIContent* aContent)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG(aDocument);
|
|
|
|
NS_ENSURE_ARG(aContent);
|
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
nsPIDOMWindowOuter *window = aDocument->GetWindow();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (!window)
|
|
|
|
return NS_OK;
|
|
|
|
|
2018-01-15 09:42:47 +03:00
|
|
|
// if the content is currently focused in the window, or is an
|
|
|
|
// shadow-including inclusive ancestor of the currently focused element,
|
|
|
|
// reset the focus within that window.
|
2018-04-26 22:28:30 +03:00
|
|
|
nsIContent* content = window->GetFocusedElement();
|
2018-01-15 09:42:47 +03:00
|
|
|
if (content && nsContentUtils::ContentIsHostIncludingDescendantOf(content, aContent)) {
|
2011-09-29 10:19:26 +04:00
|
|
|
bool shouldShowFocusRing = window->ShouldShowFocusRing();
|
2018-04-26 22:28:30 +03:00
|
|
|
window->SetFocusedElement(nullptr);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
// if this window is currently focused, clear the global focused
|
|
|
|
// element as well, but don't fire any events.
|
2009-07-29 18:36:03 +04:00
|
|
|
if (window == mFocusedWindow) {
|
2018-04-26 22:28:31 +03:00
|
|
|
mFocusedElement = nullptr;
|
2014-09-10 03:27:56 +04:00
|
|
|
} else {
|
2009-07-29 18:36:03 +04:00
|
|
|
// Check if the node that was focused is an iframe or similar by looking
|
|
|
|
// if it has a subdocument. This would indicate that this focused iframe
|
|
|
|
// and its descendants will be going away. We will need to move the
|
|
|
|
// focus somewhere else, so just clear the focus in the toplevel window
|
|
|
|
// so that no element is focused.
|
|
|
|
nsIDocument* subdoc = aDocument->GetSubDocumentFor(content);
|
|
|
|
if (subdoc) {
|
2014-01-10 06:03:47 +04:00
|
|
|
nsCOMPtr<nsIDocShell> docShell = subdoc->GetDocShell();
|
|
|
|
if (docShell) {
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> childWindow = docShell->GetWindow();
|
2014-01-10 06:03:47 +04:00
|
|
|
if (childWindow && IsSameOrAncestor(childWindow, mFocusedWindow)) {
|
|
|
|
ClearFocus(mActiveWindow);
|
|
|
|
}
|
2009-07-29 18:36:03 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-06-01 05:46:56 +04:00
|
|
|
|
2014-09-10 03:27:56 +04:00
|
|
|
// Notify the editor in case we removed its ancestor limiter.
|
|
|
|
if (content->IsEditable()) {
|
|
|
|
nsCOMPtr<nsIDocShell> docShell = aDocument->GetDocShell();
|
|
|
|
if (docShell) {
|
2017-08-07 08:55:58 +03:00
|
|
|
RefPtr<HTMLEditor> htmlEditor = docShell->GetHTMLEditor();
|
|
|
|
if (htmlEditor) {
|
|
|
|
RefPtr<Selection> selection = htmlEditor->GetSelection();
|
|
|
|
if (selection && selection->GetFrameSelection() &&
|
|
|
|
content == selection->GetFrameSelection()->GetAncestorLimiter()) {
|
|
|
|
htmlEditor->FinalizeSelection();
|
2014-09-10 03:27:56 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-03 13:41:24 +03:00
|
|
|
NotifyFocusStateChange(content, nullptr, shouldShowFocusRing, false);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2016-01-30 20:05:36 +03:00
|
|
|
nsFocusManager::WindowShown(mozIDOMWindowProxy* aWindow, bool aNeedsFocus)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
2016-01-30 20:05:36 +03:00
|
|
|
NS_ENSURE_TRUE(aWindow, NS_ERROR_INVALID_ARG);
|
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> window = nsPIDOMWindowOuter::From(aWindow);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2015-06-04 01:25:57 +03:00
|
|
|
if (MOZ_LOG_TEST(gFocusLog, LogLevel::Debug)) {
|
2012-07-31 04:43:28 +04:00
|
|
|
LOGFOCUS(("Window %p Shown [Currently: %p %p]", window.get(), mActiveWindow.get(), mFocusedWindow.get()));
|
|
|
|
nsIDocument* doc = window->GetExtantDoc();
|
|
|
|
if (doc && doc->GetDocumentURI()) {
|
2016-08-26 09:02:31 +03:00
|
|
|
LOGFOCUS(("Shown Window: %s",
|
|
|
|
doc->GetDocumentURI()->GetSpecOrDefault().get()));
|
2012-07-31 04:43:28 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (mFocusedWindow) {
|
|
|
|
doc = mFocusedWindow->GetExtantDoc();
|
|
|
|
if (doc && doc->GetDocumentURI()) {
|
2016-08-26 09:02:31 +03:00
|
|
|
LOGFOCUS((" Focused Window: %s",
|
|
|
|
doc->GetDocumentURI()->GetSpecOrDefault().get()));
|
2012-07-31 04:43:28 +04:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-16 22:18:38 +03:00
|
|
|
if (nsIDocShell* docShell = window->GetDocShell()) {
|
|
|
|
if (nsCOMPtr<nsITabChild> child = docShell->GetTabChild()) {
|
|
|
|
bool active = static_cast<TabChild*>(child.get())->ParentIsActive();
|
|
|
|
ActivateOrDeactivate(window, active);
|
|
|
|
}
|
2015-02-06 19:26:29 +03:00
|
|
|
}
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (mFocusedWindow != window)
|
|
|
|
return NS_OK;
|
|
|
|
|
2009-10-16 18:32:05 +04:00
|
|
|
if (aNeedsFocus) {
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> currentWindow;
|
2018-04-26 17:37:47 +03:00
|
|
|
RefPtr<Element> currentFocus =
|
2017-09-07 16:54:49 +03:00
|
|
|
GetFocusedDescendant(window, eIncludeAllDescendants,
|
|
|
|
getter_AddRefs(currentWindow));
|
2009-10-16 18:32:05 +04:00
|
|
|
if (currentWindow)
|
2011-10-17 18:59:28 +04:00
|
|
|
Focus(currentWindow, currentFocus, 0, true, false, false, true);
|
2009-10-16 18:32:05 +04:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Sometimes, an element in a window can be focused before the window is
|
|
|
|
// visible, which would mean that the widget may not be properly focused.
|
|
|
|
// When the window becomes visible, make sure the right widget is focused.
|
|
|
|
EnsureCurrentWidgetFocused();
|
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2016-01-30 20:05:36 +03:00
|
|
|
nsFocusManager::WindowHidden(mozIDOMWindowProxy* aWindow)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
|
|
|
// if there is no window or it is not the same or an ancestor of the
|
|
|
|
// currently focused window, just return, as the current focus will not
|
|
|
|
// be affected.
|
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
NS_ENSURE_TRUE(aWindow, NS_ERROR_INVALID_ARG);
|
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> window = nsPIDOMWindowOuter::From(aWindow);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2015-06-04 01:25:57 +03:00
|
|
|
if (MOZ_LOG_TEST(gFocusLog, LogLevel::Debug)) {
|
2012-07-31 04:43:28 +04:00
|
|
|
LOGFOCUS(("Window %p Hidden [Currently: %p %p]", window.get(), mActiveWindow.get(), mFocusedWindow.get()));
|
2012-09-02 06:35:17 +04:00
|
|
|
nsAutoCString spec;
|
2012-07-31 04:43:28 +04:00
|
|
|
nsIDocument* doc = window->GetExtantDoc();
|
|
|
|
if (doc && doc->GetDocumentURI()) {
|
2016-08-26 09:02:31 +03:00
|
|
|
LOGFOCUS((" Hide Window: %s",
|
|
|
|
doc->GetDocumentURI()->GetSpecOrDefault().get()));
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
2012-07-31 04:43:28 +04:00
|
|
|
if (mFocusedWindow) {
|
|
|
|
doc = mFocusedWindow->GetExtantDoc();
|
|
|
|
if (doc && doc->GetDocumentURI()) {
|
2016-08-26 09:02:31 +03:00
|
|
|
LOGFOCUS((" Focused Window: %s",
|
|
|
|
doc->GetDocumentURI()->GetSpecOrDefault().get()));
|
2012-07-31 04:43:28 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mActiveWindow) {
|
|
|
|
doc = mActiveWindow->GetExtantDoc();
|
|
|
|
if (doc && doc->GetDocumentURI()) {
|
2016-08-26 09:02:31 +03:00
|
|
|
LOGFOCUS((" Active Window: %s",
|
|
|
|
doc->GetDocumentURI()->GetSpecOrDefault().get()));
|
2012-07-31 04:43:28 +04:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!IsSameOrAncestor(window, mFocusedWindow))
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
// at this point, we know that the window being hidden is either the focused
|
|
|
|
// window, or an ancestor of the focused window. Either way, the focus is no
|
|
|
|
// longer valid, so it needs to be updated.
|
|
|
|
|
2018-04-26 22:28:31 +03:00
|
|
|
RefPtr<Element> oldFocusedElement = mFocusedElement.forget();
|
2011-03-29 07:32:11 +04:00
|
|
|
|
2012-06-23 05:13:56 +04:00
|
|
|
nsCOMPtr<nsIDocShell> focusedDocShell = mFocusedWindow->GetDocShell();
|
2012-12-29 05:56:42 +04:00
|
|
|
nsCOMPtr<nsIPresShell> presShell = focusedDocShell->GetPresShell();
|
2012-06-23 05:13:56 +04:00
|
|
|
|
2018-04-26 22:28:31 +03:00
|
|
|
if (oldFocusedElement && oldFocusedElement->IsInComposedDoc()) {
|
|
|
|
NotifyFocusStateChange(oldFocusedElement,
|
2017-05-03 13:41:24 +03:00
|
|
|
nullptr,
|
2011-06-01 05:46:56 +04:00
|
|
|
mFocusedWindow->ShouldShowFocusRing(),
|
2011-10-17 18:59:28 +04:00
|
|
|
false);
|
2014-07-28 03:21:00 +04:00
|
|
|
window->UpdateCommands(NS_LITERAL_STRING("focus"), nullptr, 0);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2012-06-23 05:13:56 +04:00
|
|
|
if (presShell) {
|
2015-09-02 09:08:00 +03:00
|
|
|
SendFocusOrBlurEvent(eBlur, presShell,
|
2018-04-26 22:28:31 +03:00
|
|
|
oldFocusedElement->GetComposedDoc(),
|
|
|
|
oldFocusedElement, 1, false);
|
2012-06-23 05:13:56 +04:00
|
|
|
}
|
|
|
|
}
|
2012-06-03 20:05:00 +04:00
|
|
|
|
2012-10-26 04:49:13 +04:00
|
|
|
nsPresContext* focusedPresContext =
|
|
|
|
presShell ? presShell->GetPresContext() : nullptr;
|
2014-03-08 05:20:07 +04:00
|
|
|
IMEStateManager::OnChangeFocus(focusedPresContext, nullptr,
|
|
|
|
GetFocusMoveActionCause(0));
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (presShell) {
|
2012-07-30 18:20:58 +04:00
|
|
|
SetCaretVisible(presShell, false, nullptr);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// if the docshell being hidden is being destroyed, then we want to move
|
|
|
|
// focus somewhere else. Call ClearFocus on the toplevel window, which
|
|
|
|
// will have the effect of clearing the focus and moving the focused window
|
|
|
|
// to the toplevel window. But if the window isn't being destroyed, we are
|
|
|
|
// likely just loading a new document in it, so we want to maintain the
|
|
|
|
// focused window so that the new document gets properly focused.
|
|
|
|
nsCOMPtr<nsIDocShell> docShellBeingHidden = window->GetDocShell();
|
2016-02-05 22:22:31 +03:00
|
|
|
bool beingDestroyed = !docShellBeingHidden;
|
|
|
|
if (docShellBeingHidden) {
|
|
|
|
docShellBeingHidden->IsBeingDestroyed(&beingDestroyed);
|
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (beingDestroyed) {
|
|
|
|
// There is usually no need to do anything if a toplevel window is going
|
|
|
|
// away, as we assume that WindowLowered will be called. However, this may
|
|
|
|
// not happen if nsIAppStartup::eForceQuit is used to quit, and can cause
|
|
|
|
// a leak. So if the active window is being destroyed, call WindowLowered
|
|
|
|
// directly.
|
|
|
|
if (mActiveWindow == mFocusedWindow || mActiveWindow == window)
|
|
|
|
WindowLowered(mActiveWindow);
|
|
|
|
else
|
|
|
|
ClearFocus(mActiveWindow);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if the window being hidden is an ancestor of the focused window, adjust
|
|
|
|
// the focused window so that it points to the one being hidden. This
|
|
|
|
// ensures that the focused window isn't in a chain of frames that doesn't
|
|
|
|
// exist any more.
|
|
|
|
if (window != mFocusedWindow) {
|
2014-01-10 06:03:47 +04:00
|
|
|
nsCOMPtr<nsIDocShellTreeItem> dsti =
|
|
|
|
mFocusedWindow ? mFocusedWindow->GetDocShell() : nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (dsti) {
|
2009-06-23 04:40:55 +04:00
|
|
|
nsCOMPtr<nsIDocShellTreeItem> parentDsti;
|
|
|
|
dsti->GetParent(getter_AddRefs(parentDsti));
|
2014-01-10 06:03:47 +04:00
|
|
|
if (parentDsti) {
|
2016-01-30 20:05:36 +03:00
|
|
|
if (nsCOMPtr<nsPIDOMWindowOuter> parentWindow = parentDsti->GetWindow())
|
2018-04-26 22:28:30 +03:00
|
|
|
parentWindow->SetFocusedElement(nullptr);
|
2014-01-10 06:03:47 +04:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
2013-03-24 14:32:44 +04:00
|
|
|
SetFocusedWindowInternal(window);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFocusManager::FireDelayedEvents(nsIDocument* aDocument)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG(aDocument);
|
|
|
|
|
|
|
|
// fire any delayed focus and blur events in the same order that they were added
|
2013-12-18 04:12:33 +04:00
|
|
|
for (uint32_t i = 0; i < mDelayedBlurFocusEvents.Length(); i++) {
|
|
|
|
if (mDelayedBlurFocusEvents[i].mDocument == aDocument) {
|
|
|
|
if (!aDocument->GetInnerWindow() ||
|
|
|
|
!aDocument->GetInnerWindow()->IsCurrentInnerWindow()) {
|
|
|
|
// If the document was navigated away from or is defunct, don't bother
|
|
|
|
// firing events on it. Note the symmetry between this condition and
|
|
|
|
// the similar one in nsDocument.cpp:FireOrClearDelayedEvents.
|
|
|
|
mDelayedBlurFocusEvents.RemoveElementAt(i);
|
|
|
|
--i;
|
|
|
|
} else if (!aDocument->EventHandlingSuppressed()) {
|
2015-08-26 15:56:59 +03:00
|
|
|
EventMessage message = mDelayedBlurFocusEvents[i].mEventMessage;
|
2013-12-18 04:12:33 +04:00
|
|
|
nsCOMPtr<EventTarget> target = mDelayedBlurFocusEvents[i].mTarget;
|
|
|
|
nsCOMPtr<nsIPresShell> presShell = mDelayedBlurFocusEvents[i].mPresShell;
|
2016-03-30 01:53:00 +03:00
|
|
|
nsCOMPtr<EventTarget> relatedTarget = mDelayedBlurFocusEvents[i].mRelatedTarget;
|
2013-12-18 04:12:33 +04:00
|
|
|
mDelayedBlurFocusEvents.RemoveElementAt(i);
|
2017-04-30 20:00:11 +03:00
|
|
|
|
|
|
|
FireFocusOrBlurEvent(message, presShell, target, false, false,
|
|
|
|
relatedTarget);
|
2013-12-18 04:12:33 +04:00
|
|
|
--i;
|
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-11-16 00:12:50 +03:00
|
|
|
NS_IMETHODIMP
|
2018-04-26 17:37:46 +03:00
|
|
|
nsFocusManager::FocusPlugin(Element* aPlugin)
|
2010-11-16 00:12:50 +03:00
|
|
|
{
|
2018-04-26 17:37:46 +03:00
|
|
|
NS_ENSURE_ARG(aPlugin);
|
|
|
|
SetFocusInner(aPlugin, 0, true, false);
|
2010-11-16 00:12:50 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2014-11-27 16:28:26 +03:00
|
|
|
NS_IMETHODIMP
|
2016-01-30 20:05:36 +03:00
|
|
|
nsFocusManager::ParentActivated(mozIDOMWindowProxy* aWindow, bool aActive)
|
2014-11-27 16:28:26 +03:00
|
|
|
{
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> window = nsPIDOMWindowOuter::From(aWindow);
|
2014-11-27 16:28:26 +03:00
|
|
|
NS_ENSURE_TRUE(window, NS_ERROR_INVALID_ARG);
|
|
|
|
|
|
|
|
ActivateOrDeactivate(window, aActive);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-06-01 05:46:56 +04:00
|
|
|
/* static */
|
|
|
|
void
|
|
|
|
nsFocusManager::NotifyFocusStateChange(nsIContent* aContent,
|
2017-05-03 13:41:24 +03:00
|
|
|
nsIContent* aContentToFocus,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aWindowShouldShowFocusRing,
|
|
|
|
bool aGettingFocus)
|
2011-06-01 05:46:56 +04:00
|
|
|
{
|
2017-05-03 13:41:24 +03:00
|
|
|
MOZ_ASSERT_IF(aContentToFocus, !aGettingFocus);
|
2011-06-01 05:46:56 +04:00
|
|
|
if (!aContent->IsElement()) {
|
|
|
|
return;
|
|
|
|
}
|
2017-05-03 13:41:24 +03:00
|
|
|
|
|
|
|
nsIContent* commonAncestor = nullptr;
|
|
|
|
if (aContentToFocus && aContentToFocus->IsElement()) {
|
|
|
|
commonAncestor =
|
|
|
|
nsContentUtils::GetCommonFlattenedTreeAncestor(aContent, aContentToFocus);
|
|
|
|
}
|
|
|
|
|
2014-04-03 08:18:36 +04:00
|
|
|
EventStates eventState = NS_EVENT_STATE_FOCUS;
|
2013-04-21 14:30:11 +04:00
|
|
|
if (aWindowShouldShowFocusRing) {
|
2011-06-01 05:46:56 +04:00
|
|
|
eventState |= NS_EVENT_STATE_FOCUSRING;
|
|
|
|
}
|
2016-09-09 01:12:00 +03:00
|
|
|
|
2011-06-01 05:46:56 +04:00
|
|
|
if (aGettingFocus) {
|
|
|
|
aContent->AsElement()->AddStates(eventState);
|
|
|
|
} else {
|
|
|
|
aContent->AsElement()->RemoveStates(eventState);
|
|
|
|
}
|
2016-09-09 01:12:00 +03:00
|
|
|
|
2017-05-03 13:41:24 +03:00
|
|
|
for (nsIContent* content = aContent;
|
|
|
|
content && content != commonAncestor;
|
|
|
|
content = content->GetFlattenedTreeParent()) {
|
|
|
|
if (!content->IsElement()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
Element* element = content->AsElement();
|
2016-09-09 01:12:00 +03:00
|
|
|
if (aGettingFocus) {
|
2017-05-03 13:41:24 +03:00
|
|
|
if (element->State().HasState(NS_EVENT_STATE_FOCUS_WITHIN)) {
|
|
|
|
break;
|
|
|
|
}
|
2016-09-09 01:12:00 +03:00
|
|
|
element->AddStates(NS_EVENT_STATE_FOCUS_WITHIN);
|
|
|
|
} else {
|
|
|
|
element->RemoveStates(NS_EVENT_STATE_FOCUS_WITHIN);
|
|
|
|
}
|
|
|
|
}
|
2011-06-01 05:46:56 +04:00
|
|
|
}
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// static
|
|
|
|
void
|
|
|
|
nsFocusManager::EnsureCurrentWidgetFocused()
|
|
|
|
{
|
2012-01-13 16:42:18 +04:00
|
|
|
if (!mFocusedWindow || sTestMode)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
return;
|
|
|
|
|
|
|
|
// get the main child widget for the focused window and ensure that the
|
|
|
|
// platform knows that this widget is focused.
|
|
|
|
nsCOMPtr<nsIDocShell> docShell = mFocusedWindow->GetDocShell();
|
|
|
|
if (docShell) {
|
2012-12-29 05:56:42 +04:00
|
|
|
nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (presShell) {
|
2013-01-05 07:12:24 +04:00
|
|
|
nsViewManager* vm = presShell->GetViewManager();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (vm) {
|
|
|
|
nsCOMPtr<nsIWidget> widget;
|
2009-07-22 04:45:05 +04:00
|
|
|
vm->GetRootWidget(getter_AddRefs(widget));
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (widget)
|
2011-10-17 18:59:28 +04:00
|
|
|
widget->SetFocus(false);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-11 15:56:42 +03:00
|
|
|
bool
|
2014-11-27 16:28:26 +03:00
|
|
|
ActivateOrDeactivateChild(TabParent* aParent, void* aArg)
|
|
|
|
{
|
|
|
|
bool active = static_cast<bool>(aArg);
|
2017-08-23 12:02:57 +03:00
|
|
|
Unused << aParent->SendParentActivated(active);
|
2016-05-11 15:56:42 +03:00
|
|
|
return false;
|
2014-11-27 16:28:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2016-01-30 20:05:36 +03:00
|
|
|
nsFocusManager::ActivateOrDeactivate(nsPIDOMWindowOuter* aWindow, bool aActive)
|
2014-11-27 16:28:26 +03:00
|
|
|
{
|
|
|
|
if (!aWindow) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Inform the DOM window that it has activated or deactivated, so that
|
|
|
|
// the active attribute is updated on the window.
|
|
|
|
aWindow->ActivateOrDeactivate(aActive);
|
|
|
|
|
|
|
|
// Send the activate event.
|
2015-07-31 23:23:15 +03:00
|
|
|
if (aWindow->GetExtantDoc()) {
|
|
|
|
nsContentUtils::DispatchEventOnlyToChrome(aWindow->GetExtantDoc(),
|
2016-01-30 20:05:36 +03:00
|
|
|
aWindow->GetCurrentInnerWindow(),
|
2015-07-31 23:23:15 +03:00
|
|
|
aActive ?
|
|
|
|
NS_LITERAL_STRING("activate") :
|
|
|
|
NS_LITERAL_STRING("deactivate"),
|
|
|
|
true, true, nullptr);
|
|
|
|
}
|
2014-11-27 16:28:26 +03:00
|
|
|
|
|
|
|
// Look for any remote child frames, iterate over them and send the activation notification.
|
|
|
|
nsContentUtils::CallOnAllRemoteChildren(aWindow, ActivateOrDeactivateChild,
|
|
|
|
(void *)aActive);
|
|
|
|
}
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
void
|
2018-04-26 17:37:47 +03:00
|
|
|
nsFocusManager::SetFocusInner(Element* aNewContent, int32_t aFlags,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aFocusChanged, bool aAdjustWidget)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
|
|
|
// if the element is not focusable, just return and leave the focus as is
|
2018-04-26 22:28:31 +03:00
|
|
|
RefPtr<Element> elementToFocus = CheckIfFocusable(aNewContent, aFlags);
|
|
|
|
if (!elementToFocus) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
return;
|
2018-04-26 22:28:31 +03:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
// check if the element to focus is a frame (iframe) containing a child
|
|
|
|
// document. Frames are never directly focused; instead focusing a frame
|
|
|
|
// means focus what is inside the frame. To do this, the descendant content
|
|
|
|
// within the frame is retrieved and that will be focused instead.
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> newWindow;
|
2018-04-26 22:28:31 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> subWindow = GetContentWindow(elementToFocus);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (subWindow) {
|
2018-04-26 22:28:31 +03:00
|
|
|
elementToFocus = GetFocusedDescendant(subWindow, eIncludeAllDescendants,
|
2017-09-07 16:54:49 +03:00
|
|
|
getter_AddRefs(newWindow));
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// since a window is being refocused, clear aFocusChanged so that the
|
|
|
|
// caret position isn't updated.
|
2011-10-17 18:59:28 +04:00
|
|
|
aFocusChanged = false;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// unless it was set above, retrieve the window for the element to focus
|
2018-04-26 22:28:31 +03:00
|
|
|
if (!newWindow) {
|
|
|
|
newWindow = GetCurrentWindow(elementToFocus);
|
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
// if the element is already focused, just return. Note that this happens
|
|
|
|
// after the frame check above so that we compare the element that will be
|
|
|
|
// focused rather than the frame it is in.
|
2018-04-26 22:28:31 +03:00
|
|
|
if (!newWindow ||
|
|
|
|
(newWindow == mFocusedWindow && elementToFocus == mFocusedElement)) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
return;
|
2018-04-26 22:28:31 +03:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
// don't allow focus to be placed in docshells or descendants of docshells
|
2009-07-13 15:55:56 +04:00
|
|
|
// that are being destroyed. Also, ensure that the page hasn't been
|
|
|
|
// unloaded. The prevents content from being refocused during an unload event.
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsCOMPtr<nsIDocShell> newDocShell = newWindow->GetDocShell();
|
|
|
|
nsCOMPtr<nsIDocShell> docShell = newDocShell;
|
|
|
|
while (docShell) {
|
2011-09-29 10:19:26 +04:00
|
|
|
bool inUnload;
|
2009-07-13 15:55:56 +04:00
|
|
|
docShell->GetIsInUnload(&inUnload);
|
|
|
|
if (inUnload)
|
|
|
|
return;
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool beingDestroyed;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
docShell->IsBeingDestroyed(&beingDestroyed);
|
|
|
|
if (beingDestroyed)
|
|
|
|
return;
|
|
|
|
|
2009-06-23 04:40:55 +04:00
|
|
|
nsCOMPtr<nsIDocShellTreeItem> parentDsti;
|
2013-02-13 02:02:51 +04:00
|
|
|
docShell->GetParent(getter_AddRefs(parentDsti));
|
2009-06-23 04:40:55 +04:00
|
|
|
docShell = do_QueryInterface(parentDsti);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
2017-07-06 15:00:35 +03:00
|
|
|
// if the new element is in the same window as the currently focused element
|
2011-09-29 10:19:26 +04:00
|
|
|
bool isElementInFocusedWindow = (mFocusedWindow == newWindow);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2010-04-24 14:40:48 +04:00
|
|
|
if (!isElementInFocusedWindow && mFocusedWindow && newWindow &&
|
|
|
|
nsContentUtils::IsHandlingKeyBoardEvent()) {
|
|
|
|
nsCOMPtr<nsIScriptObjectPrincipal> focused =
|
|
|
|
do_QueryInterface(mFocusedWindow);
|
|
|
|
nsCOMPtr<nsIScriptObjectPrincipal> newFocus =
|
|
|
|
do_QueryInterface(newWindow);
|
|
|
|
nsIPrincipal* focusedPrincipal = focused->GetPrincipal();
|
|
|
|
nsIPrincipal* newPrincipal = newFocus->GetPrincipal();
|
|
|
|
if (!focusedPrincipal || !newPrincipal) {
|
|
|
|
return;
|
|
|
|
}
|
2011-09-29 10:19:26 +04:00
|
|
|
bool subsumes = false;
|
2010-04-24 14:40:48 +04:00
|
|
|
focusedPrincipal->Subsumes(newPrincipal, &subsumes);
|
2014-09-25 13:04:45 +04:00
|
|
|
if (!subsumes && !nsContentUtils::LegacyIsCallerChromeOrNativeCode()) {
|
2010-04-24 14:40:48 +04:00
|
|
|
NS_WARNING("Not allowed to focus the new window!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// to check if the new element is in the active window, compare the
|
|
|
|
// new root docshell for the new element with the active window's docshell.
|
2011-09-29 10:19:26 +04:00
|
|
|
bool isElementInActiveWindow = false;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2014-01-10 06:03:47 +04:00
|
|
|
nsCOMPtr<nsIDocShellTreeItem> dsti = newWindow->GetDocShell();
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> newRootWindow;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (dsti) {
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> root;
|
|
|
|
dsti->GetRootTreeItem(getter_AddRefs(root));
|
2014-01-10 06:03:47 +04:00
|
|
|
newRootWindow = root ? root->GetWindow() : nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
isElementInActiveWindow = (mActiveWindow && newRootWindow == mActiveWindow);
|
|
|
|
}
|
|
|
|
|
2013-02-28 03:28:27 +04:00
|
|
|
// Exit fullscreen if we're focusing a windowed plugin on a non-MacOSX
|
2011-12-16 01:42:36 +04:00
|
|
|
// system. We don't control event dispatch to windowed plugins on non-MacOSX,
|
2013-02-28 03:28:27 +04:00
|
|
|
// so we can't display the "Press ESC to leave fullscreen mode" warning on
|
|
|
|
// key input if a windowed plugin is focused, so just exit fullscreen
|
2011-12-16 01:42:36 +04:00
|
|
|
// to guard against phishing.
|
|
|
|
#ifndef XP_MACOSX
|
2018-04-26 22:28:31 +03:00
|
|
|
if (elementToFocus &&
|
2016-02-24 03:40:08 +03:00
|
|
|
nsContentUtils::
|
2018-04-26 22:28:31 +03:00
|
|
|
GetRootDocument(elementToFocus->OwnerDoc())->GetFullscreenElement() &&
|
|
|
|
nsContentUtils::HasPluginWithUncontrolledEventDispatch(elementToFocus)) {
|
2011-12-16 01:42:36 +04:00
|
|
|
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
2013-08-21 23:28:26 +04:00
|
|
|
NS_LITERAL_CSTRING("DOM"),
|
2018-04-26 22:28:31 +03:00
|
|
|
elementToFocus->OwnerDoc(),
|
2011-12-16 01:42:36 +04:00
|
|
|
nsContentUtils::eDOM_PROPERTIES,
|
2016-02-17 03:47:11 +03:00
|
|
|
"FocusedWindowedPluginWhileFullscreen");
|
2018-04-26 22:28:31 +03:00
|
|
|
nsIDocument::AsyncExitFullscreen(elementToFocus->OwnerDoc());
|
2011-12-16 01:42:36 +04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// if the FLAG_NOSWITCHFRAME flag is used, only allow the focus to be
|
|
|
|
// shifted away from the current element if the new shell to focus is
|
|
|
|
// the same or an ancestor shell of the currently focused shell.
|
2011-09-29 10:19:26 +04:00
|
|
|
bool allowFrameSwitch = !(aFlags & FLAG_NOSWITCHFRAME) ||
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
IsSameOrAncestor(newWindow, mFocusedWindow);
|
|
|
|
|
|
|
|
// if the element is in the active window, frame switching is allowed and
|
|
|
|
// the content is in a visible window, fire blur and focus events.
|
2011-09-29 10:19:26 +04:00
|
|
|
bool sendFocusEvent =
|
2009-12-12 08:17:40 +03:00
|
|
|
isElementInActiveWindow && allowFrameSwitch && IsWindowVisible(newWindow);
|
|
|
|
|
|
|
|
// When the following conditions are true:
|
|
|
|
// * an element has focus
|
|
|
|
// * isn't called by trusted event (i.e., called by untrusted event or by js)
|
|
|
|
// * the focus is moved to another document's element
|
|
|
|
// we need to check the permission.
|
2018-04-26 22:28:31 +03:00
|
|
|
if (sendFocusEvent && mFocusedElement && !nsContentUtils::LegacyIsCallerNativeCode() &&
|
|
|
|
mFocusedElement->OwnerDoc() != aNewContent->OwnerDoc()) {
|
2009-12-12 08:17:40 +03:00
|
|
|
// If the caller cannot access the current focused node, the caller should
|
|
|
|
// not be able to steal focus from it. E.g., When the current focused node
|
|
|
|
// is in chrome, any web contents should not be able to steal the focus.
|
2018-04-26 22:28:31 +03:00
|
|
|
nsCOMPtr<nsIDOMNode> domNode(do_QueryInterface(mFocusedElement));
|
2009-12-12 08:17:40 +03:00
|
|
|
sendFocusEvent = nsContentUtils::CanCallerAccess(domNode);
|
2014-06-18 10:13:00 +04:00
|
|
|
if (!sendFocusEvent && mMouseButtonEventHandlingDocument) {
|
|
|
|
// However, while mouse button event is handling, the handling document's
|
2010-11-06 08:04:11 +03:00
|
|
|
// script should be able to steal focus.
|
2014-06-18 10:13:00 +04:00
|
|
|
domNode = do_QueryInterface(mMouseButtonEventHandlingDocument);
|
2010-11-06 08:04:11 +03:00
|
|
|
sendFocusEvent = nsContentUtils::CanCallerAccess(domNode);
|
|
|
|
}
|
2009-12-12 08:17:40 +03:00
|
|
|
}
|
|
|
|
|
2018-04-26 22:28:31 +03:00
|
|
|
LOGCONTENT("Shift Focus: %s", elementToFocus.get());
|
2012-07-31 04:43:28 +04:00
|
|
|
LOGFOCUS((" Flags: %x Current Window: %p New Window: %p Current Element: %p",
|
2018-04-26 22:28:31 +03:00
|
|
|
aFlags, mFocusedWindow.get(), newWindow.get(), mFocusedElement.get()));
|
2012-07-31 04:43:28 +04:00
|
|
|
LOGFOCUS((" In Active Window: %d In Focused Window: %d SendFocus: %d",
|
|
|
|
isElementInActiveWindow, isElementInFocusedWindow, sendFocusEvent));
|
|
|
|
|
2009-12-12 08:17:40 +03:00
|
|
|
if (sendFocusEvent) {
|
2018-04-26 22:28:31 +03:00
|
|
|
RefPtr<Element> oldFocusedElement = mFocusedElement;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// return if blurring fails or the focus changes during the blur
|
|
|
|
if (mFocusedWindow) {
|
|
|
|
// if the focus is being moved to another element in the same document,
|
|
|
|
// or to a descendant, pass the existing window to Blur so that the
|
|
|
|
// current node in the existing window is cleared. If moving to a
|
|
|
|
// window elsewhere, we want to maintain the current node in the
|
|
|
|
// window but still blur it.
|
2011-09-29 10:19:26 +04:00
|
|
|
bool currentIsSameOrAncestor = IsSameOrAncestor(mFocusedWindow, newWindow);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// find the common ancestor of the currently focused window and the new
|
|
|
|
// window. The ancestor will need to have its currently focused node
|
|
|
|
// cleared once the document has been blurred. Otherwise, we'll be in a
|
|
|
|
// state where a document is blurred yet the chain of windows above it
|
|
|
|
// still points to that document.
|
|
|
|
// For instance, in the following frame tree:
|
|
|
|
// A
|
|
|
|
// B C
|
|
|
|
// D
|
|
|
|
// D is focused and we want to focus C. Once D has been blurred, we need
|
|
|
|
// to clear out the focus in A, otherwise A would still maintain that B
|
|
|
|
// was focused, and B that D was focused.
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> commonAncestor;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (!isElementInFocusedWindow)
|
|
|
|
commonAncestor = GetCommonAncestor(newWindow, mFocusedWindow);
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
if (!Blur(currentIsSameOrAncestor ? mFocusedWindow.get() : nullptr,
|
2016-03-30 01:53:00 +03:00
|
|
|
commonAncestor, !isElementInFocusedWindow, aAdjustWidget,
|
2018-04-26 22:28:31 +03:00
|
|
|
elementToFocus)) {
|
2009-06-21 04:04:04 +04:00
|
|
|
return;
|
2018-04-26 22:28:31 +03:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
2018-04-26 22:28:31 +03:00
|
|
|
Focus(newWindow, elementToFocus, aFlags, !isElementInFocusedWindow,
|
|
|
|
aFocusChanged, false, aAdjustWidget, oldFocusedElement);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
else {
|
2009-12-12 08:17:40 +03:00
|
|
|
// otherwise, for inactive windows and when the caller cannot steal the
|
|
|
|
// focus, update the node in the window, and raise the window if desired.
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (allowFrameSwitch)
|
2011-10-17 18:59:28 +04:00
|
|
|
AdjustWindowFocus(newWindow, true);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
// set the focus node and method as needed
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t focusMethod = aFocusChanged ? aFlags & FOCUSMETHODANDRING_MASK :
|
2010-04-21 18:53:42 +04:00
|
|
|
newWindow->GetFocusMethod() | (aFlags & FLAG_SHOWRING);
|
2018-04-26 22:28:31 +03:00
|
|
|
newWindow->SetFocusedElement(elementToFocus, focusMethod);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (aFocusChanged) {
|
|
|
|
nsCOMPtr<nsIDocShell> docShell = newWindow->GetDocShell();
|
|
|
|
|
2012-12-29 05:56:42 +04:00
|
|
|
nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
|
2015-09-27 19:37:20 +03:00
|
|
|
if (presShell && presShell->DidInitialize())
|
2018-04-26 22:28:31 +03:00
|
|
|
ScrollIntoView(presShell, elementToFocus, aFlags);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// update the commands even when inactive so that the attributes for that
|
|
|
|
// window are up to date.
|
|
|
|
if (allowFrameSwitch)
|
2014-07-28 03:21:00 +04:00
|
|
|
newWindow->UpdateCommands(NS_LITERAL_STRING("focus"), nullptr, 0);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
if (aFlags & FLAG_RAISE)
|
|
|
|
RaiseWindow(newRootWindow);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2016-01-30 20:05:36 +03:00
|
|
|
nsFocusManager::IsSameOrAncestor(nsPIDOMWindowOuter* aPossibleAncestor,
|
|
|
|
nsPIDOMWindowOuter* aWindow)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
2014-01-10 06:03:47 +04:00
|
|
|
if (!aWindow || !aPossibleAncestor) {
|
|
|
|
return false;
|
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2014-01-10 06:03:47 +04:00
|
|
|
nsCOMPtr<nsIDocShellTreeItem> ancestordsti = aPossibleAncestor->GetDocShell();
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> dsti = aWindow->GetDocShell();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
while (dsti) {
|
|
|
|
if (dsti == ancestordsti)
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2009-06-23 04:40:55 +04:00
|
|
|
nsCOMPtr<nsIDocShellTreeItem> parentDsti;
|
|
|
|
dsti->GetParent(getter_AddRefs(parentDsti));
|
|
|
|
dsti.swap(parentDsti);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
already_AddRefed<nsPIDOMWindowOuter>
|
|
|
|
nsFocusManager::GetCommonAncestor(nsPIDOMWindowOuter* aWindow1,
|
|
|
|
nsPIDOMWindowOuter* aWindow2)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
2014-01-10 06:03:47 +04:00
|
|
|
NS_ENSURE_TRUE(aWindow1 && aWindow2, nullptr);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> dsti1 = aWindow1->GetDocShell();
|
2012-07-30 18:20:58 +04:00
|
|
|
NS_ENSURE_TRUE(dsti1, nullptr);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2014-01-10 06:03:47 +04:00
|
|
|
nsCOMPtr<nsIDocShellTreeItem> dsti2 = aWindow2->GetDocShell();
|
2012-07-30 18:20:58 +04:00
|
|
|
NS_ENSURE_TRUE(dsti2, nullptr);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2016-02-02 18:36:30 +03:00
|
|
|
AutoTArray<nsIDocShellTreeItem*, 30> parents1, parents2;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
do {
|
|
|
|
parents1.AppendElement(dsti1);
|
2009-06-23 04:40:55 +04:00
|
|
|
nsCOMPtr<nsIDocShellTreeItem> parentDsti1;
|
|
|
|
dsti1->GetParent(getter_AddRefs(parentDsti1));
|
|
|
|
dsti1.swap(parentDsti1);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
} while (dsti1);
|
|
|
|
do {
|
|
|
|
parents2.AppendElement(dsti2);
|
2009-06-23 04:40:55 +04:00
|
|
|
nsCOMPtr<nsIDocShellTreeItem> parentDsti2;
|
|
|
|
dsti2->GetParent(getter_AddRefs(parentDsti2));
|
|
|
|
dsti2.swap(parentDsti2);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
} while (dsti2);
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t pos1 = parents1.Length();
|
|
|
|
uint32_t pos2 = parents2.Length();
|
2012-07-30 18:20:58 +04:00
|
|
|
nsIDocShellTreeItem* parent = nullptr;
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t len;
|
2013-01-15 16:22:03 +04:00
|
|
|
for (len = std::min(pos1, pos2); len > 0; --len) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsIDocShellTreeItem* child1 = parents1.ElementAt(--pos1);
|
|
|
|
nsIDocShellTreeItem* child2 = parents2.ElementAt(--pos2);
|
|
|
|
if (child1 != child2) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
parent = child1;
|
|
|
|
}
|
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> window = parent ? parent->GetWindow() : nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
return window.forget();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2016-01-30 20:05:36 +03:00
|
|
|
nsFocusManager::AdjustWindowFocus(nsPIDOMWindowOuter* aWindow,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aCheckPermission)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
2011-09-29 10:19:26 +04:00
|
|
|
bool isVisible = IsWindowVisible(aWindow);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> window(aWindow);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
while (window) {
|
|
|
|
// get the containing <iframe> or equivalent element so that it can be
|
|
|
|
// focused below.
|
2014-01-24 01:14:29 +04:00
|
|
|
nsCOMPtr<Element> frameElement = window->GetFrameElementInternal();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2014-01-10 06:03:47 +04:00
|
|
|
nsCOMPtr<nsIDocShellTreeItem> dsti = window->GetDocShell();
|
2017-07-06 15:00:35 +03:00
|
|
|
if (!dsti)
|
2009-06-23 04:40:55 +04:00
|
|
|
return;
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> parentDsti;
|
|
|
|
dsti->GetParent(getter_AddRefs(parentDsti));
|
2014-01-10 06:03:47 +04:00
|
|
|
if (!parentDsti) {
|
|
|
|
return;
|
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2014-01-10 06:03:47 +04:00
|
|
|
window = parentDsti->GetWindow();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (window) {
|
|
|
|
// if the parent window is visible but aWindow was not, then we have
|
|
|
|
// likely moved up and out from a hidden tab to the browser window, or a
|
|
|
|
// similar such arrangement. Stop adjusting the current nodes.
|
|
|
|
if (IsWindowVisible(window) != isVisible)
|
|
|
|
break;
|
|
|
|
|
2009-12-12 08:17:40 +03:00
|
|
|
// When aCheckPermission is true, we should check whether the caller can
|
|
|
|
// access the window or not. If it cannot access, we should stop the
|
|
|
|
// adjusting.
|
2014-09-25 13:04:45 +04:00
|
|
|
if (aCheckPermission && !nsContentUtils::LegacyIsCallerNativeCode() &&
|
2016-01-30 20:05:36 +03:00
|
|
|
!nsContentUtils::CanCallerAccess(window->GetCurrentInnerWindow())) {
|
2009-12-12 08:17:40 +03:00
|
|
|
break;
|
2014-09-25 13:04:45 +04:00
|
|
|
}
|
2009-12-12 08:17:40 +03:00
|
|
|
|
2018-04-26 22:28:30 +03:00
|
|
|
window->SetFocusedElement(frameElement);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2016-01-30 20:05:36 +03:00
|
|
|
nsFocusManager::IsWindowVisible(nsPIDOMWindowOuter* aWindow)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
2013-12-23 18:24:36 +04:00
|
|
|
if (!aWindow || aWindow->IsFrozen())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Check if the inner window is frozen as well. This can happen when a focus change
|
|
|
|
// occurs while restoring a previous page.
|
2016-01-30 20:05:36 +03:00
|
|
|
nsPIDOMWindowInner* innerWindow = aWindow->GetCurrentInnerWindow();
|
2013-12-23 18:24:36 +04:00
|
|
|
if (!innerWindow || innerWindow->IsFrozen())
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell();
|
|
|
|
nsCOMPtr<nsIBaseWindow> baseWin(do_QueryInterface(docShell));
|
|
|
|
if (!baseWin)
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool visible = false;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
baseWin->GetVisibility(&visible);
|
|
|
|
return visible;
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2010-04-21 17:13:08 +04:00
|
|
|
nsFocusManager::IsNonFocusableRoot(nsIContent* aContent)
|
|
|
|
{
|
2018-04-28 22:50:58 +03:00
|
|
|
MOZ_ASSERT(aContent, "aContent must not be NULL");
|
|
|
|
MOZ_ASSERT(aContent->IsInComposedDoc(), "aContent must be in a document");
|
2010-04-21 17:13:08 +04:00
|
|
|
|
|
|
|
// If aContent is in designMode, the root element is not focusable.
|
|
|
|
// NOTE: in designMode, most elements are not focusable, just the document is
|
|
|
|
// focusable.
|
|
|
|
// Also, if aContent is not editable but it isn't in designMode, it's not
|
|
|
|
// focusable.
|
2013-11-20 02:21:16 +04:00
|
|
|
// And in userfocusignored context nothing is focusable.
|
2014-08-06 03:23:02 +04:00
|
|
|
nsIDocument* doc = aContent->GetComposedDoc();
|
2010-04-21 17:13:08 +04:00
|
|
|
NS_ASSERTION(doc, "aContent must have current document");
|
2010-04-30 17:12:05 +04:00
|
|
|
return aContent == doc->GetRootElement() &&
|
2013-11-20 02:21:16 +04:00
|
|
|
(doc->HasFlag(NODE_IS_EDITABLE) || !aContent->IsEditable() ||
|
|
|
|
nsContentUtils::IsUserFocusIgnored(aContent));
|
2010-04-21 17:13:08 +04:00
|
|
|
}
|
|
|
|
|
2018-04-26 17:37:47 +03:00
|
|
|
Element*
|
2018-04-26 22:28:31 +03:00
|
|
|
nsFocusManager::CheckIfFocusable(Element* aElement, uint32_t aFlags)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
2018-04-26 22:28:31 +03:00
|
|
|
if (!aElement)
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2016-05-24 00:27:00 +03:00
|
|
|
// this is a special case for some XUL elements or input number, where an
|
|
|
|
// anonymous child is actually focusable and not the element itself.
|
2018-04-26 22:28:31 +03:00
|
|
|
RefPtr<Element> redirectedFocus = GetRedirectedFocus(aElement);
|
2018-04-26 17:37:47 +03:00
|
|
|
if (redirectedFocus) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
return CheckIfFocusable(redirectedFocus, aFlags);
|
2018-04-26 17:37:47 +03:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2018-04-26 22:28:31 +03:00
|
|
|
nsCOMPtr<nsIDocument> doc = aElement->GetComposedDoc();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// can't focus elements that are not in documents
|
2012-07-31 04:43:28 +04:00
|
|
|
if (!doc) {
|
2018-04-26 22:28:31 +03:00
|
|
|
LOGCONTENT("Cannot focus %s because content not in document", aElement)
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2012-07-31 04:43:28 +04:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2017-07-04 06:36:24 +03:00
|
|
|
// Make sure that our frames are up to date while ensuring the presshell is
|
2018-01-09 00:35:00 +03:00
|
|
|
// also initialized in case we come from a script calling focus() early.
|
2017-05-19 23:20:48 +03:00
|
|
|
mEventHandlingNeedsFlush = false;
|
2017-07-04 06:36:24 +03:00
|
|
|
doc->FlushPendingNotifications(FlushType::EnsurePresShellInitAndFrames);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2010-06-25 17:59:57 +04:00
|
|
|
nsIPresShell *shell = doc->GetShell();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (!shell)
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2013-11-20 02:21:16 +04:00
|
|
|
// the root content can always be focused,
|
|
|
|
// except in userfocusignored context.
|
2018-04-26 22:28:31 +03:00
|
|
|
if (aElement == doc->GetRootElement()) {
|
|
|
|
return nsContentUtils::IsUserFocusIgnored(aElement) ? nullptr : aElement;
|
2018-04-26 17:37:47 +03:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
// cannot focus content in print preview mode. Only the root can be focused.
|
|
|
|
nsPresContext* presContext = shell->GetPresContext();
|
2012-07-31 04:43:28 +04:00
|
|
|
if (presContext && presContext->Type() == nsPresContext::eContext_PrintPreview) {
|
2018-04-26 22:28:31 +03:00
|
|
|
LOGCONTENT("Cannot focus %s while in print preview", aElement)
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2012-07-31 04:43:28 +04:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2018-04-26 22:28:31 +03:00
|
|
|
nsIFrame* frame = aElement->GetPrimaryFrame();
|
2012-07-31 04:43:28 +04:00
|
|
|
if (!frame) {
|
2018-04-26 22:28:31 +03:00
|
|
|
LOGCONTENT("Cannot focus %s as it has no frame", aElement)
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2012-07-31 04:43:28 +04:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2018-04-26 22:28:31 +03:00
|
|
|
if (aElement->IsHTMLElement(nsGkAtoms::area)) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// HTML areas do not have their own frame, and the img frame we get from
|
2009-12-25 00:20:06 +03:00
|
|
|
// GetPrimaryFrame() is not relevant as to whether it is focusable or
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// not, so we have to do all the relevant checks manually for them.
|
2011-10-27 03:57:55 +04:00
|
|
|
return frame->IsVisibleConsideringAncestors() &&
|
2018-04-26 22:28:31 +03:00
|
|
|
aElement->IsFocusable() ? aElement : nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// if this is a child frame content node, check if it is visible and
|
|
|
|
// call the content node's IsFocusable method instead of the frame's
|
|
|
|
// IsFocusable method. This skips checking the style system and ensures that
|
|
|
|
// offscreen browsers can still be focused.
|
2018-04-26 22:28:31 +03:00
|
|
|
nsIDocument* subdoc = doc->GetSubDocumentFor(aElement);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (subdoc && IsWindowVisible(subdoc->GetWindow())) {
|
2013-02-17 01:51:02 +04:00
|
|
|
const nsStyleUserInterface* ui = frame->StyleUserInterface();
|
2016-07-25 09:26:40 +03:00
|
|
|
int32_t tabIndex = (ui->mUserFocus == StyleUserFocus::Ignore ||
|
2016-09-03 21:46:58 +03:00
|
|
|
ui->mUserFocus == StyleUserFocus::None) ? -1 : 0;
|
2018-04-26 22:28:31 +03:00
|
|
|
return aElement->IsFocusable(&tabIndex, aFlags & FLAG_BYMOUSE) ? aElement : nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2018-04-26 22:28:31 +03:00
|
|
|
return frame->IsFocusable(nullptr, aFlags & FLAG_BYMOUSE) ? aElement : nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2016-01-30 20:05:36 +03:00
|
|
|
nsFocusManager::Blur(nsPIDOMWindowOuter* aWindowToClear,
|
|
|
|
nsPIDOMWindowOuter* aAncestorWindowToFocus,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aIsLeavingDocument,
|
2016-03-30 01:53:00 +03:00
|
|
|
bool aAdjustWidgets,
|
|
|
|
nsIContent* aContentToFocus)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
2012-07-31 04:43:28 +04:00
|
|
|
LOGFOCUS(("<<Blur begin>>"));
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// hold a reference to the focused content, which may be null
|
2018-04-26 22:28:31 +03:00
|
|
|
RefPtr<Element> element = mFocusedElement;
|
|
|
|
if (element) {
|
|
|
|
if (!element->IsInComposedDoc()) {
|
|
|
|
mFocusedElement = nullptr;
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2009-06-21 04:04:04 +04:00
|
|
|
}
|
2018-04-26 22:28:31 +03:00
|
|
|
if (element == mFirstBlurEvent)
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2009-06-21 04:04:04 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// hold a reference to the focused window
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> window = mFocusedWindow;
|
2009-06-21 04:04:04 +04:00
|
|
|
if (!window) {
|
2018-04-26 22:28:31 +03:00
|
|
|
mFocusedElement = nullptr;
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2009-06-21 04:04:04 +04:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShell> docShell = window->GetDocShell();
|
2009-06-21 04:04:04 +04:00
|
|
|
if (!docShell) {
|
2018-04-26 22:28:31 +03:00
|
|
|
mFocusedElement = nullptr;
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2009-06-21 04:04:04 +04:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
// Keep a ref to presShell since dispatching the DOM event may cause
|
|
|
|
// the document to be destroyed.
|
2012-12-29 05:56:42 +04:00
|
|
|
nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
|
2009-06-21 04:04:04 +04:00
|
|
|
if (!presShell) {
|
2018-04-26 22:28:31 +03:00
|
|
|
mFocusedElement = nullptr;
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2009-06-21 04:04:04 +04:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool clearFirstBlurEvent = false;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (!mFirstBlurEvent) {
|
2018-04-26 22:28:31 +03:00
|
|
|
mFirstBlurEvent = element;
|
2011-10-17 18:59:28 +04:00
|
|
|
clearFirstBlurEvent = true;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
2012-10-26 04:49:13 +04:00
|
|
|
nsPresContext* focusedPresContext =
|
|
|
|
mActiveWindow ? presShell->GetPresContext() : nullptr;
|
2014-03-08 05:20:07 +04:00
|
|
|
IMEStateManager::OnChangeFocus(focusedPresContext, nullptr,
|
|
|
|
GetFocusMoveActionCause(0));
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
// now adjust the actual focus, by clearing the fields in the focus manager
|
|
|
|
// and in the window.
|
2018-04-26 22:28:31 +03:00
|
|
|
mFocusedElement = nullptr;
|
2011-09-29 10:19:26 +04:00
|
|
|
bool shouldShowFocusRing = window->ShouldShowFocusRing();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (aWindowToClear)
|
2018-04-26 22:28:30 +03:00
|
|
|
aWindowToClear->SetFocusedElement(nullptr);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2018-04-26 22:28:31 +03:00
|
|
|
LOGCONTENT("Element %s has been blurred", element.get());
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2010-04-21 17:13:08 +04:00
|
|
|
// Don't fire blur event on the root content which isn't editable.
|
2011-09-29 10:19:26 +04:00
|
|
|
bool sendBlurEvent =
|
2018-04-26 22:28:31 +03:00
|
|
|
element && element->IsInComposedDoc() && !IsNonFocusableRoot(element);
|
|
|
|
if (element) {
|
2010-04-21 17:13:08 +04:00
|
|
|
if (sendBlurEvent) {
|
2018-04-26 22:28:31 +03:00
|
|
|
NotifyFocusStateChange(element,
|
2017-05-03 13:41:24 +03:00
|
|
|
aContentToFocus,
|
|
|
|
shouldShowFocusRing,
|
|
|
|
false);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
2011-06-18 04:08:32 +04:00
|
|
|
// if an object/plug-in/remote browser is being blurred, move the system focus
|
|
|
|
// to the parent window, otherwise events will still get fired at the plugin.
|
2009-06-16 22:34:13 +04:00
|
|
|
// But don't do this if we are blurring due to the window being lowered,
|
|
|
|
// otherwise, the parent window can get raised again.
|
2011-06-18 04:08:32 +04:00
|
|
|
if (mActiveWindow) {
|
2018-04-26 22:28:31 +03:00
|
|
|
nsIFrame* contentFrame = element->GetPrimaryFrame();
|
2009-06-16 22:34:13 +04:00
|
|
|
nsIObjectFrame* objectFrame = do_QueryFrame(contentFrame);
|
2012-01-13 16:42:18 +04:00
|
|
|
if (aAdjustWidgets && objectFrame && !sTestMode) {
|
2015-07-09 17:48:57 +03:00
|
|
|
if (XRE_IsContentProcess()) {
|
|
|
|
// set focus to the top level window via the chrome process.
|
2016-03-16 22:18:38 +03:00
|
|
|
nsCOMPtr<nsITabChild> tabChild = docShell->GetTabChild();
|
2015-07-09 17:48:57 +03:00
|
|
|
if (tabChild) {
|
|
|
|
static_cast<TabChild*>(tabChild.get())->SendDispatchFocusToTopLevelWindow();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// note that the presshell's widget is being retrieved here, not the one
|
|
|
|
// for the object frame.
|
|
|
|
nsViewManager* vm = presShell->GetViewManager();
|
|
|
|
if (vm) {
|
|
|
|
nsCOMPtr<nsIWidget> widget;
|
|
|
|
vm->GetRootWidget(getter_AddRefs(widget));
|
|
|
|
if (widget) {
|
|
|
|
// set focus to the top level window but don't raise it.
|
|
|
|
widget->SetFocus(false);
|
|
|
|
}
|
|
|
|
}
|
2009-06-16 22:34:13 +04:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
2014-09-20 00:44:08 +04:00
|
|
|
}
|
2011-06-18 04:08:32 +04:00
|
|
|
|
|
|
|
// if the object being blurred is a remote browser, deactivate remote content
|
2018-04-26 22:28:31 +03:00
|
|
|
if (TabParent* remote = TabParent::GetFrom(element)) {
|
2014-09-20 00:44:08 +04:00
|
|
|
remote->Deactivate();
|
|
|
|
LOGFOCUS(("Remote browser deactivated"));
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool result = true;
|
2010-04-21 17:13:08 +04:00
|
|
|
if (sendBlurEvent) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// if there is an active window, update commands. If there isn't an active
|
|
|
|
// window, then this was a blur caused by the active window being lowered,
|
|
|
|
// so there is no need to update the commands
|
|
|
|
if (mActiveWindow)
|
2014-07-28 03:21:00 +04:00
|
|
|
window->UpdateCommands(NS_LITERAL_STRING("focus"), nullptr, 0);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2015-09-02 09:08:00 +03:00
|
|
|
SendFocusOrBlurEvent(eBlur, presShell,
|
2018-04-26 22:28:31 +03:00
|
|
|
element->GetComposedDoc(), element, 1,
|
2016-03-30 01:53:00 +03:00
|
|
|
false, false, aContentToFocus);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// if we are leaving the document or the window was lowered, make the caret
|
|
|
|
// invisible.
|
2014-12-19 00:50:00 +03:00
|
|
|
if (aIsLeavingDocument || !mActiveWindow) {
|
2012-07-30 18:20:58 +04:00
|
|
|
SetCaretVisible(presShell, false, nullptr);
|
2014-12-19 00:50:00 +03:00
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<AccessibleCaretEventHub> eventHub = presShell->GetAccessibleCaretEventHub();
|
2015-04-24 03:08:00 +03:00
|
|
|
if (eventHub) {
|
|
|
|
eventHub->NotifyBlur(aIsLeavingDocument || !mActiveWindow);
|
2015-01-05 03:15:00 +03:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
// at this point, it is expected that this window will be still be
|
2018-04-26 22:28:31 +03:00
|
|
|
// focused, but the focused element will be null, as it was cleared before
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// the event. If this isn't the case, then something else was focused during
|
|
|
|
// the blur event above and we should just return. However, if
|
|
|
|
// aIsLeavingDocument is set, a new document is desired, so make sure to
|
|
|
|
// blur the document and window.
|
|
|
|
if (mFocusedWindow != window ||
|
2018-04-26 22:28:31 +03:00
|
|
|
(mFocusedElement != nullptr && !aIsLeavingDocument)) {
|
2011-10-17 18:59:28 +04:00
|
|
|
result = false;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
else if (aIsLeavingDocument) {
|
2011-10-17 18:59:28 +04:00
|
|
|
window->TakeFocus(false, 0);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
// clear the focus so that the ancestor frame hierarchy is in the correct
|
|
|
|
// state. Pass true because aAncestorWindowToFocus is thought to be
|
|
|
|
// focused at this point.
|
|
|
|
if (aAncestorWindowToFocus)
|
2018-04-26 22:28:30 +03:00
|
|
|
aAncestorWindowToFocus->SetFocusedElement(nullptr, 0, true);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2013-03-24 14:32:44 +04:00
|
|
|
SetFocusedWindowInternal(nullptr);
|
2018-04-26 22:28:31 +03:00
|
|
|
mFocusedElement = nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
// pass 1 for the focus method when calling SendFocusOrBlurEvent just so
|
2009-06-22 23:49:10 +04:00
|
|
|
// that the check is made for suppressed documents. Check to ensure that
|
|
|
|
// the document isn't null in case someone closed it during the blur above
|
2012-07-31 04:43:28 +04:00
|
|
|
nsIDocument* doc = window->GetExtantDoc();
|
2009-06-22 23:49:10 +04:00
|
|
|
if (doc)
|
2015-09-02 09:08:00 +03:00
|
|
|
SendFocusOrBlurEvent(eBlur, presShell, doc, doc, 1, false);
|
2012-07-30 18:20:58 +04:00
|
|
|
if (mFocusedWindow == nullptr)
|
2016-01-30 20:05:36 +03:00
|
|
|
SendFocusOrBlurEvent(eBlur, presShell, doc,
|
|
|
|
window->GetCurrentInnerWindow(), 1, false);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
// check if a different window was focused
|
2012-07-30 18:20:58 +04:00
|
|
|
result = (mFocusedWindow == nullptr && mActiveWindow);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
else if (mActiveWindow) {
|
|
|
|
// Otherwise, the blur of the element without blurring the document
|
2010-05-13 16:19:50 +04:00
|
|
|
// occurred normally. Call UpdateCaret to redisplay the caret at the right
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// location within the document. This is needed to ensure that the caret
|
|
|
|
// used for caret browsing is made visible again when an input field is
|
|
|
|
// blurred.
|
2012-07-30 18:20:58 +04:00
|
|
|
UpdateCaret(false, true, nullptr);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (clearFirstBlurEvent)
|
2012-07-30 18:20:58 +04:00
|
|
|
mFirstBlurEvent = nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2016-01-30 20:05:36 +03:00
|
|
|
nsFocusManager::Focus(nsPIDOMWindowOuter* aWindow,
|
2018-04-26 22:28:31 +03:00
|
|
|
Element* aElement,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t aFlags,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aIsNewDocument,
|
|
|
|
bool aFocusChanged,
|
|
|
|
bool aWindowRaised,
|
2016-03-30 01:53:00 +03:00
|
|
|
bool aAdjustWidgets,
|
|
|
|
nsIContent* aContentLostFocus)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
2012-07-31 04:43:28 +04:00
|
|
|
LOGFOCUS(("<<Focus begin>>"));
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (!aWindow)
|
|
|
|
return;
|
|
|
|
|
2018-04-26 22:28:31 +03:00
|
|
|
if (aElement && (aElement == mFirstFocusEvent || aElement == mFirstBlurEvent))
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
return;
|
|
|
|
|
|
|
|
// Keep a reference to the presShell since dispatching the DOM event may
|
|
|
|
// cause the document to be destroyed.
|
|
|
|
nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell();
|
2009-06-22 23:49:10 +04:00
|
|
|
if (!docShell)
|
|
|
|
return;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2012-12-29 05:56:42 +04:00
|
|
|
nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (!presShell)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// If the focus actually changed, set the focus method (mouse, keyboard, etc).
|
|
|
|
// Otherwise, just get the current focus method and use that. This ensures
|
|
|
|
// that the method is set during the document and window focus events.
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t focusMethod = aFocusChanged ? aFlags & FOCUSMETHODANDRING_MASK :
|
2010-04-21 18:53:42 +04:00
|
|
|
aWindow->GetFocusMethod() | (aFlags & FLAG_SHOWRING);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
if (!IsWindowVisible(aWindow)) {
|
|
|
|
// if the window isn't visible, for instance because it is a hidden tab,
|
|
|
|
// update the current focus and scroll it into view but don't do anything else
|
2018-04-26 22:28:31 +03:00
|
|
|
if (CheckIfFocusable(aElement, aFlags)) {
|
|
|
|
aWindow->SetFocusedElement(aElement, focusMethod);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (aFocusChanged)
|
2018-04-26 22:28:31 +03:00
|
|
|
ScrollIntoView(presShell, aElement, aFlags);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool clearFirstFocusEvent = false;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (!mFirstFocusEvent) {
|
2018-04-26 22:28:31 +03:00
|
|
|
mFirstFocusEvent = aElement;
|
2011-10-17 18:59:28 +04:00
|
|
|
clearFirstFocusEvent = true;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
2018-04-26 22:28:31 +03:00
|
|
|
LOGCONTENT("Element %s has been focused", aElement);
|
2012-07-31 04:43:28 +04:00
|
|
|
|
2015-06-04 01:25:57 +03:00
|
|
|
if (MOZ_LOG_TEST(gFocusLog, LogLevel::Debug)) {
|
2012-07-31 04:43:28 +04:00
|
|
|
nsIDocument* docm = aWindow->GetExtantDoc();
|
|
|
|
if (docm) {
|
|
|
|
LOGCONTENT(" from %s", docm->GetRootElement());
|
|
|
|
}
|
|
|
|
LOGFOCUS((" [Newdoc: %d FocusChanged: %d Raised: %d Flags: %x]",
|
|
|
|
aIsNewDocument, aFocusChanged, aWindowRaised, aFlags));
|
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2010-08-02 17:34:54 +04:00
|
|
|
if (aIsNewDocument) {
|
|
|
|
// if this is a new document, update the parent chain of frames so that
|
|
|
|
// focus can be traversed from the top level down to the newly focused
|
|
|
|
// window.
|
2011-10-17 18:59:28 +04:00
|
|
|
AdjustWindowFocus(aWindow, false);
|
2010-08-02 17:34:54 +04:00
|
|
|
}
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// indicate that the window has taken focus.
|
2011-10-17 18:59:28 +04:00
|
|
|
if (aWindow->TakeFocus(true, focusMethod))
|
|
|
|
aIsNewDocument = true;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2013-03-24 14:32:44 +04:00
|
|
|
SetFocusedWindowInternal(aWindow);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2010-11-16 00:12:50 +03:00
|
|
|
// Update the system focus by focusing the root widget. But avoid this
|
2018-04-26 22:28:31 +03:00
|
|
|
// if 1) aAdjustWidgets is false or 2) aElement is a plugin that has its
|
2010-11-16 00:12:50 +03:00
|
|
|
// own widget and is either already focused or is about to be focused.
|
|
|
|
nsCOMPtr<nsIWidget> objectFrameWidget;
|
2018-04-26 22:28:31 +03:00
|
|
|
if (aElement) {
|
|
|
|
nsIFrame* contentFrame = aElement->GetPrimaryFrame();
|
2010-11-16 00:12:50 +03:00
|
|
|
nsIObjectFrame* objectFrame = do_QueryFrame(contentFrame);
|
|
|
|
if (objectFrame)
|
|
|
|
objectFrameWidget = objectFrame->GetWidget();
|
|
|
|
}
|
2012-01-13 16:42:18 +04:00
|
|
|
if (aAdjustWidgets && !objectFrameWidget && !sTestMode) {
|
2013-01-05 07:12:24 +04:00
|
|
|
nsViewManager* vm = presShell->GetViewManager();
|
2010-11-16 00:12:50 +03:00
|
|
|
if (vm) {
|
|
|
|
nsCOMPtr<nsIWidget> widget;
|
|
|
|
vm->GetRootWidget(getter_AddRefs(widget));
|
|
|
|
if (widget)
|
2011-10-17 18:59:28 +04:00
|
|
|
widget->SetFocus(false);
|
2010-11-16 00:12:50 +03:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// if switching to a new document, first fire the focus event on the
|
|
|
|
// document and then the window.
|
|
|
|
if (aIsNewDocument) {
|
2012-07-31 04:43:28 +04:00
|
|
|
nsIDocument* doc = aWindow->GetExtantDoc();
|
2014-03-08 05:20:07 +04:00
|
|
|
// The focus change should be notified to IMEStateManager from here if
|
2018-04-26 22:28:31 +03:00
|
|
|
// the focused element is a designMode editor since any content won't
|
2013-02-01 22:02:17 +04:00
|
|
|
// receive focus event.
|
|
|
|
if (doc && doc->HasFlag(NODE_IS_EDITABLE)) {
|
2014-03-08 05:20:07 +04:00
|
|
|
IMEStateManager::OnChangeFocus(presShell->GetPresContext(), nullptr,
|
|
|
|
GetFocusMoveActionCause(aFlags));
|
2013-02-01 22:02:17 +04:00
|
|
|
}
|
2018-04-26 22:28:31 +03:00
|
|
|
if (doc) {
|
2015-09-02 09:08:00 +03:00
|
|
|
SendFocusOrBlurEvent(eFocus, presShell, doc,
|
2009-10-01 21:53:10 +04:00
|
|
|
doc, aFlags & FOCUSMETHOD_MASK, aWindowRaised);
|
2018-04-26 22:28:31 +03:00
|
|
|
}
|
|
|
|
if (mFocusedWindow == aWindow && mFocusedElement == nullptr) {
|
2015-09-02 09:08:00 +03:00
|
|
|
SendFocusOrBlurEvent(eFocus, presShell, doc,
|
2016-01-30 20:05:36 +03:00
|
|
|
aWindow->GetCurrentInnerWindow(),
|
|
|
|
aFlags & FOCUSMETHOD_MASK, aWindowRaised);
|
2018-04-26 22:28:31 +03:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// check to ensure that the element is still focusable, and that nothing
|
|
|
|
// else was focused during the events above.
|
2018-04-26 22:28:31 +03:00
|
|
|
if (CheckIfFocusable(aElement, aFlags) &&
|
|
|
|
mFocusedWindow == aWindow && mFocusedElement == nullptr) {
|
|
|
|
mFocusedElement = aElement;
|
2010-10-18 22:12:18 +04:00
|
|
|
|
2018-04-26 22:28:30 +03:00
|
|
|
nsIContent* focusedNode = aWindow->GetFocusedElement();
|
2018-04-26 22:28:31 +03:00
|
|
|
bool isRefocus = focusedNode && focusedNode->IsEqualNode(aElement);
|
2010-10-18 22:12:18 +04:00
|
|
|
|
2018-04-26 22:28:31 +03:00
|
|
|
aWindow->SetFocusedElement(aElement, focusMethod);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2017-01-09 19:03:52 +03:00
|
|
|
// if the focused element changed, scroll it into view
|
2018-04-26 22:28:31 +03:00
|
|
|
if (aElement && aFocusChanged) {
|
|
|
|
ScrollIntoView(presShell, aElement, aFlags);
|
2017-01-09 19:03:52 +03:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool sendFocusEvent =
|
2018-04-26 22:28:31 +03:00
|
|
|
aElement && aElement->IsInComposedDoc() && !IsNonFocusableRoot(aElement);
|
2011-03-29 07:32:11 +04:00
|
|
|
nsPresContext* presContext = presShell->GetPresContext();
|
2010-04-21 17:13:08 +04:00
|
|
|
if (sendFocusEvent) {
|
2018-04-26 22:28:31 +03:00
|
|
|
NotifyFocusStateChange(aElement,
|
2017-05-03 13:41:24 +03:00
|
|
|
nullptr,
|
|
|
|
aWindow->ShouldShowFocusRing(),
|
|
|
|
true);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2011-06-18 04:08:32 +04:00
|
|
|
// if this is an object/plug-in/remote browser, focus its widget. Note that we might
|
2009-12-25 00:20:06 +03:00
|
|
|
// no longer be in the same document, due to the events we fired above when
|
|
|
|
// aIsNewDocument.
|
2018-04-26 22:28:31 +03:00
|
|
|
if (presShell->GetDocument() == aElement->GetComposedDoc()) {
|
2012-01-13 16:42:18 +04:00
|
|
|
if (aAdjustWidgets && objectFrameWidget && !sTestMode)
|
2011-10-17 18:59:28 +04:00
|
|
|
objectFrameWidget->SetFocus(false);
|
2011-06-18 04:08:32 +04:00
|
|
|
|
|
|
|
// if the object being focused is a remote browser, activate remote content
|
2018-04-26 22:28:31 +03:00
|
|
|
if (TabParent* remote = TabParent::GetFrom(aElement)) {
|
2011-06-18 04:08:32 +04:00
|
|
|
remote->Activate();
|
2012-07-31 04:43:28 +04:00
|
|
|
LOGFOCUS(("Remote browser activated"));
|
2011-06-18 04:08:32 +04:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
2018-04-26 22:28:31 +03:00
|
|
|
IMEStateManager::OnChangeFocus(presContext, aElement,
|
2014-03-08 05:20:07 +04:00
|
|
|
GetFocusMoveActionCause(aFlags));
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
// as long as this focus wasn't because a window was raised, update the
|
|
|
|
// commands
|
|
|
|
// XXXndeakin P2 someone could adjust the focus during the update
|
|
|
|
if (!aWindowRaised)
|
2014-07-28 03:21:00 +04:00
|
|
|
aWindow->UpdateCommands(NS_LITERAL_STRING("focus"), nullptr, 0);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2015-09-02 09:08:00 +03:00
|
|
|
SendFocusOrBlurEvent(eFocus, presShell,
|
2018-04-26 22:28:31 +03:00
|
|
|
aElement->GetComposedDoc(),
|
|
|
|
aElement, aFlags & FOCUSMETHOD_MASK,
|
2016-03-30 01:53:00 +03:00
|
|
|
aWindowRaised, isRefocus, aContentLostFocus);
|
2010-04-21 17:13:08 +04:00
|
|
|
} else {
|
2014-03-08 05:20:07 +04:00
|
|
|
IMEStateManager::OnChangeFocus(presContext, nullptr,
|
|
|
|
GetFocusMoveActionCause(aFlags));
|
2010-04-21 17:13:08 +04:00
|
|
|
if (!aWindowRaised) {
|
2014-07-28 03:21:00 +04:00
|
|
|
aWindow->UpdateCommands(NS_LITERAL_STRING("focus"), nullptr, 0);
|
2010-04-21 17:13:08 +04:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2010-11-16 00:12:50 +03:00
|
|
|
// If the window focus event (fired above when aIsNewDocument) caused
|
|
|
|
// the plugin not to be focusable, update the system focus by focusing
|
|
|
|
// the root widget.
|
|
|
|
if (aAdjustWidgets && objectFrameWidget &&
|
2018-04-26 22:28:31 +03:00
|
|
|
mFocusedWindow == aWindow && mFocusedElement == nullptr &&
|
2012-01-13 16:42:18 +04:00
|
|
|
!sTestMode) {
|
2013-01-05 07:12:24 +04:00
|
|
|
nsViewManager* vm = presShell->GetViewManager();
|
2010-11-16 00:12:50 +03:00
|
|
|
if (vm) {
|
|
|
|
nsCOMPtr<nsIWidget> widget;
|
|
|
|
vm->GetRootWidget(getter_AddRefs(widget));
|
|
|
|
if (widget)
|
2011-10-17 18:59:28 +04:00
|
|
|
widget->SetFocus(false);
|
2010-11-16 00:12:50 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-26 22:28:31 +03:00
|
|
|
if (!mFocusedElement) {
|
|
|
|
// When there is no focused element, IMEStateManager needs to adjust IME
|
2015-04-08 05:50:12 +03:00
|
|
|
// enabled state with the document.
|
|
|
|
nsPresContext* presContext = presShell->GetPresContext();
|
|
|
|
IMEStateManager::OnChangeFocus(presContext, nullptr,
|
|
|
|
GetFocusMoveActionCause(aFlags));
|
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
if (!aWindowRaised)
|
2014-07-28 03:21:00 +04:00
|
|
|
aWindow->UpdateCommands(NS_LITERAL_STRING("focus"), nullptr, 0);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// update the caret visibility and position to match the newly focused
|
|
|
|
// element. However, don't update the position if this was a focus due to a
|
|
|
|
// mouse click as the selection code would already have moved the caret as
|
|
|
|
// needed. If this is a different document than was focused before, also
|
|
|
|
// update the caret's visibility. If this is the same document, the caret
|
|
|
|
// visibility should be the same as before so there is no need to update it.
|
2018-04-26 22:28:31 +03:00
|
|
|
if (mFocusedElement == aElement)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
UpdateCaret(aFocusChanged && !(aFlags & FLAG_BYMOUSE), aIsNewDocument,
|
2018-04-26 22:28:31 +03:00
|
|
|
mFocusedElement);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
if (clearFirstFocusEvent)
|
2012-07-30 18:20:58 +04:00
|
|
|
mFirstFocusEvent = nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
2016-04-26 03:23:21 +03:00
|
|
|
class FocusBlurEvent : public Runnable
|
2009-12-18 22:27:57 +03:00
|
|
|
{
|
|
|
|
public:
|
2017-06-12 22:34:10 +03:00
|
|
|
FocusBlurEvent(nsISupports* aTarget,
|
|
|
|
EventMessage aEventMessage,
|
|
|
|
nsPresContext* aContext,
|
|
|
|
bool aWindowRaised,
|
|
|
|
bool aIsRefocus,
|
|
|
|
EventTarget* aRelatedTarget)
|
|
|
|
: mozilla::Runnable("FocusBlurEvent")
|
|
|
|
, mTarget(aTarget)
|
2015-08-26 15:56:59 +03:00
|
|
|
, mContext(aContext)
|
|
|
|
, mEventMessage(aEventMessage)
|
|
|
|
, mWindowRaised(aWindowRaised)
|
|
|
|
, mIsRefocus(aIsRefocus)
|
2016-03-30 01:53:00 +03:00
|
|
|
, mRelatedTarget(aRelatedTarget)
|
2015-08-26 15:56:59 +03:00
|
|
|
{
|
|
|
|
}
|
2009-12-18 22:27:57 +03:00
|
|
|
|
2016-08-08 05:18:10 +03:00
|
|
|
NS_IMETHOD Run() override
|
2009-12-18 22:27:57 +03:00
|
|
|
{
|
2015-08-26 15:56:59 +03:00
|
|
|
InternalFocusEvent event(true, mEventMessage);
|
2012-12-16 05:26:03 +04:00
|
|
|
event.mFlags.mBubbles = false;
|
2015-10-12 20:48:49 +03:00
|
|
|
event.mFlags.mCancelable = false;
|
2016-03-27 08:44:57 +03:00
|
|
|
event.mFromRaise = mWindowRaised;
|
2016-03-27 08:46:07 +03:00
|
|
|
event.mIsRefocus = mIsRefocus;
|
2016-03-30 01:53:00 +03:00
|
|
|
event.mRelatedTarget = mRelatedTarget;
|
2014-03-18 08:48:21 +04:00
|
|
|
return EventDispatcher::Dispatch(mTarget, mContext, &event);
|
2009-12-18 22:27:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsISupports> mTarget;
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsPresContext> mContext;
|
2015-08-26 15:56:59 +03:00
|
|
|
EventMessage mEventMessage;
|
2011-09-29 10:19:26 +04:00
|
|
|
bool mWindowRaised;
|
|
|
|
bool mIsRefocus;
|
2016-03-30 01:53:00 +03:00
|
|
|
nsCOMPtr<EventTarget> mRelatedTarget;
|
2009-12-18 22:27:57 +03:00
|
|
|
};
|
|
|
|
|
2016-10-07 04:39:53 +03:00
|
|
|
class FocusInOutEvent : public Runnable
|
|
|
|
{
|
|
|
|
public:
|
2017-06-12 22:34:10 +03:00
|
|
|
FocusInOutEvent(nsISupports* aTarget,
|
|
|
|
EventMessage aEventMessage,
|
|
|
|
nsPresContext* aContext,
|
|
|
|
nsPIDOMWindowOuter* aOriginalFocusedWindow,
|
|
|
|
nsIContent* aOriginalFocusedContent,
|
|
|
|
EventTarget* aRelatedTarget)
|
|
|
|
: mozilla::Runnable("FocusInOutEvent")
|
|
|
|
, mTarget(aTarget)
|
2016-10-07 04:39:53 +03:00
|
|
|
, mContext(aContext)
|
|
|
|
, mEventMessage(aEventMessage)
|
|
|
|
, mOriginalFocusedWindow(aOriginalFocusedWindow)
|
|
|
|
, mOriginalFocusedContent(aOriginalFocusedContent)
|
|
|
|
, mRelatedTarget(aRelatedTarget)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHOD Run() override
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIContent> originalWindowFocus = mOriginalFocusedWindow ?
|
2018-04-26 22:28:30 +03:00
|
|
|
mOriginalFocusedWindow->GetFocusedElement() :
|
2016-10-07 04:39:53 +03:00
|
|
|
nullptr;
|
|
|
|
// Blink does not check that focus is the same after blur, but WebKit does.
|
|
|
|
// Opt to follow Blink's behavior (see bug 687787).
|
|
|
|
if (mEventMessage == eFocusOut ||
|
|
|
|
originalWindowFocus == mOriginalFocusedContent) {
|
|
|
|
InternalFocusEvent event(true, mEventMessage);
|
|
|
|
event.mFlags.mBubbles = true;
|
|
|
|
event.mFlags.mCancelable = false;
|
|
|
|
event.mRelatedTarget = mRelatedTarget;
|
|
|
|
return EventDispatcher::Dispatch(mTarget, mContext, &event);
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsISupports> mTarget;
|
|
|
|
RefPtr<nsPresContext> mContext;
|
|
|
|
EventMessage mEventMessage;
|
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> mOriginalFocusedWindow;
|
|
|
|
nsCOMPtr<nsIContent> mOriginalFocusedContent;
|
|
|
|
nsCOMPtr<EventTarget> mRelatedTarget;
|
|
|
|
};
|
|
|
|
|
2016-03-30 01:53:00 +03:00
|
|
|
static nsIDocument*
|
|
|
|
GetDocumentHelper(EventTarget* aTarget)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsINode> node = do_QueryInterface(aTarget);
|
|
|
|
if (!node) {
|
|
|
|
nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(aTarget);
|
|
|
|
return win ? win->GetExtantDoc() : nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return node->OwnerDoc();
|
|
|
|
}
|
|
|
|
|
2017-04-30 20:00:11 +03:00
|
|
|
void nsFocusManager::FireFocusInOrOutEvent(EventMessage aEventMessage,
|
2016-10-07 04:39:53 +03:00
|
|
|
nsIPresShell* aPresShell,
|
|
|
|
nsISupports* aTarget,
|
|
|
|
nsPIDOMWindowOuter* aCurrentFocusedWindow,
|
|
|
|
nsIContent* aCurrentFocusedContent,
|
|
|
|
EventTarget* aRelatedTarget)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(aEventMessage == eFocusIn || aEventMessage == eFocusOut,
|
2017-04-30 20:00:11 +03:00
|
|
|
"Wrong event type for FireFocusInOrOutEvent");
|
2016-10-07 04:39:53 +03:00
|
|
|
|
|
|
|
nsContentUtils::AddScriptRunner(
|
|
|
|
new FocusInOutEvent(
|
|
|
|
aTarget,
|
|
|
|
aEventMessage,
|
|
|
|
aPresShell->GetPresContext(),
|
|
|
|
aCurrentFocusedWindow,
|
|
|
|
aCurrentFocusedContent,
|
|
|
|
aRelatedTarget));
|
|
|
|
}
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
void
|
2015-08-26 15:56:59 +03:00
|
|
|
nsFocusManager::SendFocusOrBlurEvent(EventMessage aEventMessage,
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsIPresShell* aPresShell,
|
|
|
|
nsIDocument* aDocument,
|
|
|
|
nsISupports* aTarget,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t aFocusMethod,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aWindowRaised,
|
2016-03-30 01:53:00 +03:00
|
|
|
bool aIsRefocus,
|
|
|
|
EventTarget* aRelatedTarget)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
2015-09-02 09:08:00 +03:00
|
|
|
NS_ASSERTION(aEventMessage == eFocus || aEventMessage == eBlur,
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
"Wrong event type for SendFocusOrBlurEvent");
|
|
|
|
|
2013-04-20 02:18:32 +04:00
|
|
|
nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
|
2016-03-30 01:53:00 +03:00
|
|
|
nsCOMPtr<nsIDocument> eventTargetDoc = GetDocumentHelper(eventTarget);
|
|
|
|
nsCOMPtr<nsIDocument> relatedTargetDoc = GetDocumentHelper(aRelatedTarget);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2016-03-30 01:53:00 +03:00
|
|
|
// set aRelatedTarget to null if it's not in the same document as eventTarget
|
|
|
|
if (eventTargetDoc != relatedTargetDoc) {
|
|
|
|
aRelatedTarget = nullptr;
|
2013-11-20 02:21:16 +04:00
|
|
|
}
|
2016-03-30 01:53:00 +03:00
|
|
|
|
|
|
|
bool dontDispatchEvent =
|
|
|
|
eventTargetDoc && nsContentUtils::IsUserFocusIgnored(eventTargetDoc);
|
2013-11-20 02:21:16 +04:00
|
|
|
|
2017-02-03 13:16:00 +03:00
|
|
|
if (!dontDispatchEvent && aDocument && aDocument->EventHandlingSuppressed()) {
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t i = mDelayedBlurFocusEvents.Length(); i > 0; --i) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// if this event was already queued, remove it and append it to the end
|
2015-08-26 15:56:59 +03:00
|
|
|
if (mDelayedBlurFocusEvents[i - 1].mEventMessage == aEventMessage &&
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
mDelayedBlurFocusEvents[i - 1].mPresShell == aPresShell &&
|
|
|
|
mDelayedBlurFocusEvents[i - 1].mDocument == aDocument &&
|
2016-03-30 01:53:00 +03:00
|
|
|
mDelayedBlurFocusEvents[i - 1].mTarget == eventTarget &&
|
|
|
|
mDelayedBlurFocusEvents[i - 1].mRelatedTarget == aRelatedTarget) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
mDelayedBlurFocusEvents.RemoveElementAt(i - 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mDelayedBlurFocusEvents.AppendElement(
|
2015-08-26 15:56:59 +03:00
|
|
|
nsDelayedBlurOrFocusEvent(aEventMessage, aPresShell,
|
2016-03-30 01:53:00 +03:00
|
|
|
aDocument, eventTarget, aRelatedTarget));
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-04-30 20:00:11 +03:00
|
|
|
// If mDelayedBlurFocusEvents queue is not empty, check if there are events
|
|
|
|
// that belongs to this doc, if yes, fire them first.
|
|
|
|
if (aDocument && !aDocument->EventHandlingSuppressed() &&
|
|
|
|
mDelayedBlurFocusEvents.Length()) {
|
|
|
|
FireDelayedEvents(aDocument);
|
|
|
|
}
|
|
|
|
|
|
|
|
FireFocusOrBlurEvent(aEventMessage, aPresShell, aTarget, aWindowRaised,
|
|
|
|
aIsRefocus, aRelatedTarget);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsFocusManager::FireFocusOrBlurEvent(EventMessage aEventMessage,
|
|
|
|
nsIPresShell* aPresShell,
|
|
|
|
nsISupports* aTarget,
|
|
|
|
bool aWindowRaised,
|
|
|
|
bool aIsRefocus,
|
|
|
|
EventTarget* aRelatedTarget)
|
|
|
|
{
|
|
|
|
nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
|
|
|
|
nsCOMPtr<nsIDocument> eventTargetDoc = GetDocumentHelper(eventTarget);
|
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> currentWindow = mFocusedWindow;
|
|
|
|
nsCOMPtr<nsPIDOMWindowInner> targetWindow = do_QueryInterface(aTarget);
|
|
|
|
nsCOMPtr<nsIDocument> targetDocument = do_QueryInterface(aTarget);
|
|
|
|
nsCOMPtr<nsIContent> currentFocusedContent = currentWindow ?
|
2018-04-26 22:28:30 +03:00
|
|
|
currentWindow->GetFocusedElement() : nullptr;
|
2017-04-30 20:00:11 +03:00
|
|
|
|
|
|
|
bool dontDispatchEvent =
|
|
|
|
eventTargetDoc && nsContentUtils::IsUserFocusIgnored(eventTargetDoc);
|
|
|
|
|
2011-09-28 05:46:11 +04:00
|
|
|
#ifdef ACCESSIBILITY
|
|
|
|
nsAccessibilityService* accService = GetAccService();
|
|
|
|
if (accService) {
|
2015-09-02 09:08:00 +03:00
|
|
|
if (aEventMessage == eFocus) {
|
2011-09-28 05:46:11 +04:00
|
|
|
accService->NotifyOfDOMFocus(aTarget);
|
2015-08-26 15:56:59 +03:00
|
|
|
} else {
|
2011-09-28 05:46:11 +04:00
|
|
|
accService->NotifyOfDOMBlur(aTarget);
|
2015-08-26 15:56:59 +03:00
|
|
|
}
|
2011-09-28 05:46:11 +04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-11-20 02:21:16 +04:00
|
|
|
if (!dontDispatchEvent) {
|
|
|
|
nsContentUtils::AddScriptRunner(
|
2015-08-26 15:56:59 +03:00
|
|
|
new FocusBlurEvent(aTarget, aEventMessage, aPresShell->GetPresContext(),
|
2016-03-30 01:53:00 +03:00
|
|
|
aWindowRaised, aIsRefocus, aRelatedTarget));
|
2016-10-07 04:39:53 +03:00
|
|
|
|
|
|
|
// Check that the target is not a window or document before firing
|
|
|
|
// focusin/focusout. Other browsers do not fire focusin/focusout on window,
|
|
|
|
// despite being required in the spec, so follow their behavior.
|
|
|
|
//
|
|
|
|
// As for document, we should not even fire focus/blur, but until then, we
|
|
|
|
// need this check. targetDocument should be removed once bug 1228802 is
|
|
|
|
// resolved.
|
|
|
|
if (!targetWindow && !targetDocument) {
|
|
|
|
EventMessage focusInOrOutMessage = aEventMessage == eFocus ? eFocusIn : eFocusOut;
|
2017-04-30 20:00:11 +03:00
|
|
|
FireFocusInOrOutEvent(focusInOrOutMessage, aPresShell, aTarget,
|
2016-10-07 04:39:53 +03:00
|
|
|
currentWindow, currentFocusedContent, aRelatedTarget);
|
|
|
|
}
|
2013-11-20 02:21:16 +04:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsFocusManager::ScrollIntoView(nsIPresShell* aPresShell,
|
|
|
|
nsIContent* aContent,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t aFlags)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
|
|
|
// if the noscroll flag isn't set, scroll the newly focused element into view
|
|
|
|
if (!(aFlags & FLAG_NOSCROLL))
|
|
|
|
aPresShell->ScrollContentIntoView(aContent,
|
2012-03-20 06:09:50 +04:00
|
|
|
nsIPresShell::ScrollAxis(
|
|
|
|
nsIPresShell::SCROLL_MINIMUM,
|
|
|
|
nsIPresShell::SCROLL_IF_NOT_VISIBLE),
|
|
|
|
nsIPresShell::ScrollAxis(
|
|
|
|
nsIPresShell::SCROLL_MINIMUM,
|
|
|
|
nsIPresShell::SCROLL_IF_NOT_VISIBLE),
|
2010-10-28 20:01:37 +04:00
|
|
|
nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2016-01-30 20:05:36 +03:00
|
|
|
nsFocusManager::RaiseWindow(nsPIDOMWindowOuter* aWindow)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
|
|
|
// don't raise windows that are already raised or are in the process of
|
|
|
|
// being lowered
|
2009-07-13 15:55:56 +04:00
|
|
|
if (!aWindow || aWindow == mActiveWindow || aWindow == mWindowBeingLowered)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
return;
|
|
|
|
|
2012-01-13 16:42:18 +04:00
|
|
|
if (sTestMode) {
|
|
|
|
// In test mode, emulate the existing window being lowered and the new
|
2017-01-31 02:42:02 +03:00
|
|
|
// window being raised. This happens in a separate runnable to avoid
|
|
|
|
// touching multiple windows in the current runnable.
|
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> active(mActiveWindow);
|
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> window(aWindow);
|
|
|
|
RefPtr<nsFocusManager> self(this);
|
2017-06-12 22:34:10 +03:00
|
|
|
NS_DispatchToCurrentThread(NS_NewRunnableFunction(
|
|
|
|
"nsFocusManager::RaiseWindow", [self, active, window]() -> void {
|
2017-01-31 02:42:02 +03:00
|
|
|
if (active) {
|
|
|
|
self->WindowLowered(active);
|
|
|
|
}
|
|
|
|
self->WindowRaised(window);
|
|
|
|
}));
|
2012-01-13 16:42:18 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-02-11 02:57:01 +04:00
|
|
|
#if defined(XP_WIN)
|
2009-07-13 15:55:56 +04:00
|
|
|
// Windows would rather we focus the child widget, otherwise, the toplevel
|
|
|
|
// widget will always end up being focused. Fortunately, focusing the child
|
|
|
|
// widget will also have the effect of raising the window this widget is in.
|
|
|
|
// But on other platforms, we can just focus the toplevel widget to raise
|
|
|
|
// the window.
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> childWindow;
|
2017-09-07 16:54:49 +03:00
|
|
|
GetFocusedDescendant(aWindow, eIncludeAllDescendants,
|
|
|
|
getter_AddRefs(childWindow));
|
2009-07-13 15:55:56 +04:00
|
|
|
if (!childWindow)
|
|
|
|
childWindow = aWindow;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell();
|
|
|
|
if (!docShell)
|
|
|
|
return;
|
|
|
|
|
2012-12-29 05:56:42 +04:00
|
|
|
nsCOMPtr<nsIPresShell> presShell = docShell->GetPresShell();
|
2009-07-13 15:55:56 +04:00
|
|
|
if (!presShell)
|
|
|
|
return;
|
|
|
|
|
2013-01-05 07:12:24 +04:00
|
|
|
nsViewManager* vm = presShell->GetViewManager();
|
2009-07-13 15:55:56 +04:00
|
|
|
if (vm) {
|
|
|
|
nsCOMPtr<nsIWidget> widget;
|
2009-07-22 04:45:05 +04:00
|
|
|
vm->GetRootWidget(getter_AddRefs(widget));
|
2009-07-13 15:55:56 +04:00
|
|
|
if (widget)
|
2011-10-17 18:59:28 +04:00
|
|
|
widget->SetFocus(true);
|
2009-07-13 15:55:56 +04:00
|
|
|
}
|
|
|
|
#else
|
2014-01-10 06:03:47 +04:00
|
|
|
nsCOMPtr<nsIBaseWindow> treeOwnerAsWin =
|
|
|
|
do_QueryInterface(aWindow->GetDocShell());
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (treeOwnerAsWin) {
|
|
|
|
nsCOMPtr<nsIWidget> widget;
|
|
|
|
treeOwnerAsWin->GetMainWidget(getter_AddRefs(widget));
|
|
|
|
if (widget)
|
2011-10-17 18:59:28 +04:00
|
|
|
widget->SetFocus(true);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
2009-07-13 15:55:56 +04:00
|
|
|
#endif
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
2013-05-22 07:28:43 +04:00
|
|
|
void
|
|
|
|
nsFocusManager::UpdateCaretForCaretBrowsingMode()
|
|
|
|
{
|
2018-04-26 22:28:31 +03:00
|
|
|
UpdateCaret(false, true, mFocusedElement);
|
2013-05-22 07:28:43 +04:00
|
|
|
}
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
void
|
2011-09-29 10:19:26 +04:00
|
|
|
nsFocusManager::UpdateCaret(bool aMoveCaretToFocus,
|
|
|
|
bool aUpdateVisibility,
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsIContent* aContent)
|
|
|
|
{
|
2012-07-31 04:43:28 +04:00
|
|
|
LOGFOCUS(("Update Caret: %d %d", aMoveCaretToFocus, aUpdateVisibility));
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
if (!mFocusedWindow)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// this is called when a document is focused or when the caretbrowsing
|
|
|
|
// preference is changed
|
|
|
|
nsCOMPtr<nsIDocShell> focusedDocShell = mFocusedWindow->GetDocShell();
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> dsti = do_QueryInterface(focusedDocShell);
|
|
|
|
if (!dsti)
|
|
|
|
return;
|
|
|
|
|
2014-01-20 11:58:26 +04:00
|
|
|
if (dsti->ItemType() == nsIDocShellTreeItem::typeChrome) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
return; // Never browse with caret in chrome
|
2014-01-20 11:58:26 +04:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool browseWithCaret =
|
2011-05-25 10:31:59 +04:00
|
|
|
Preferences::GetBool("accessibility.browsewithcaret");
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2012-12-29 05:56:42 +04:00
|
|
|
nsCOMPtr<nsIPresShell> presShell = focusedDocShell->GetPresShell();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (!presShell)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// If this is an editable document which isn't contentEditable, or a
|
|
|
|
// contentEditable document and the node to focus is contentEditable,
|
|
|
|
// return, so that we don't mess with caret visibility.
|
2011-09-29 10:19:26 +04:00
|
|
|
bool isEditable = false;
|
2013-02-14 02:39:30 +04:00
|
|
|
focusedDocShell->GetEditable(&isEditable);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2013-02-14 02:39:30 +04:00
|
|
|
if (isEditable) {
|
|
|
|
nsCOMPtr<nsIHTMLDocument> doc =
|
|
|
|
do_QueryInterface(presShell->GetDocument());
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2013-02-14 02:39:30 +04:00
|
|
|
bool isContentEditableDoc =
|
|
|
|
doc && doc->GetEditingState() == nsIHTMLDocument::eContentEditable;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2013-02-14 02:39:30 +04:00
|
|
|
bool isFocusEditable =
|
|
|
|
aContent && aContent->HasFlag(NODE_IS_EDITABLE);
|
|
|
|
if (!isContentEditableDoc || isFocusEditable)
|
|
|
|
return;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!isEditable && aMoveCaretToFocus)
|
|
|
|
MoveCaretToFocus(presShell, aContent);
|
|
|
|
|
|
|
|
if (!aUpdateVisibility)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// XXXndeakin this doesn't seem right. It should be checking for this only
|
|
|
|
// on the nearest ancestor frame which is a chrome frame. But this is
|
|
|
|
// what the existing code does, so just leave it for now.
|
|
|
|
if (!browseWithCaret) {
|
2014-01-24 01:14:29 +04:00
|
|
|
nsCOMPtr<Element> docElement =
|
|
|
|
mFocusedWindow->GetFrameElementInternal();
|
|
|
|
if (docElement)
|
|
|
|
browseWithCaret = docElement->AttrValueIs(kNameSpaceID_None,
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsGkAtoms::showcaret,
|
|
|
|
NS_LITERAL_STRING("true"),
|
|
|
|
eCaseMatters);
|
|
|
|
}
|
|
|
|
|
|
|
|
SetCaretVisible(presShell, browseWithCaret, aContent);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsFocusManager::MoveCaretToFocus(nsIPresShell* aPresShell, nsIContent* aContent)
|
|
|
|
{
|
2018-01-30 07:10:51 +03:00
|
|
|
nsCOMPtr<nsIDocument> doc = aPresShell->GetDocument();
|
|
|
|
if (doc) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsFrameSelection> frameSelection = aPresShell->FrameSelection();
|
2018-03-27 07:35:22 +03:00
|
|
|
RefPtr<Selection> domSelection =
|
2016-06-09 12:35:22 +03:00
|
|
|
frameSelection->GetSelection(SelectionType::eNormal);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (domSelection) {
|
|
|
|
// First clear the selection. This way, if there is no currently focused
|
|
|
|
// content, the selection will just be cleared.
|
2018-03-27 07:35:23 +03:00
|
|
|
domSelection->RemoveAllRanges(IgnoreErrors());
|
2018-01-30 07:10:51 +03:00
|
|
|
if (aContent) {
|
|
|
|
ErrorResult rv;
|
|
|
|
RefPtr<nsRange> newRange = doc->CreateRange(rv);
|
|
|
|
if (NS_WARN_IF(rv.Failed())) {
|
|
|
|
rv.SuppressException();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the range to the start of the currently focused node
|
|
|
|
// Make sure it's collapsed
|
2018-02-01 22:21:14 +03:00
|
|
|
newRange->SelectNodeContents(*aContent, IgnoreErrors());
|
2018-01-30 07:10:51 +03:00
|
|
|
|
|
|
|
if (!aContent->GetFirstChild() ||
|
|
|
|
aContent->IsNodeOfType(nsINode::eHTML_FORM_CONTROL)) {
|
|
|
|
// If current focus node is a leaf, set range to before the
|
|
|
|
// node by using the parent as a container.
|
|
|
|
// This prevents it from appearing as selected.
|
2018-02-01 22:21:14 +03:00
|
|
|
newRange->SetStartBefore(*aContent, IgnoreErrors());
|
|
|
|
newRange->SetEndBefore(*aContent, IgnoreErrors());
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
2018-03-27 07:35:22 +03:00
|
|
|
domSelection->AddRange(*newRange, IgnoreErrors());
|
2018-01-30 07:10:51 +03:00
|
|
|
domSelection->CollapseToStart();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsFocusManager::SetCaretVisible(nsIPresShell* aPresShell,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aVisible,
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsIContent* aContent)
|
|
|
|
{
|
|
|
|
// When browsing with caret, make sure caret is visible after new focus
|
|
|
|
// Return early if there is no caret. This can happen for the testcase
|
|
|
|
// for bug 308025 where a window is closed in a blur handler.
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsCaret> caret = aPresShell->GetCaret();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (!caret)
|
|
|
|
return NS_OK;
|
|
|
|
|
2014-08-06 09:19:29 +04:00
|
|
|
bool caretVisible = caret->IsVisible();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (!aVisible && !caretVisible)
|
|
|
|
return NS_OK;
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsFrameSelection> frameSelection;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (aContent) {
|
2014-08-06 03:23:02 +04:00
|
|
|
NS_ASSERTION(aContent->GetComposedDoc() == aPresShell->GetDocument(),
|
2009-12-25 00:20:06 +03:00
|
|
|
"Wrong document?");
|
|
|
|
nsIFrame *focusFrame = aContent->GetPrimaryFrame();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (focusFrame)
|
|
|
|
frameSelection = focusFrame->GetFrameSelection();
|
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsFrameSelection> docFrameSelection = aPresShell->FrameSelection();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
if (docFrameSelection && caret &&
|
|
|
|
(frameSelection == docFrameSelection || !aContent)) {
|
2016-06-11 05:06:37 +03:00
|
|
|
nsISelection* domSelection =
|
2016-06-09 12:35:22 +03:00
|
|
|
docFrameSelection->GetSelection(SelectionType::eNormal);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (domSelection) {
|
2014-06-03 11:08:54 +04:00
|
|
|
nsCOMPtr<nsISelectionController> selCon(do_QueryInterface(aPresShell));
|
|
|
|
if (!selCon) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2010-12-02 00:38:21 +03:00
|
|
|
// First, hide the caret to prevent attempting to show it in SetCaretDOMSelection
|
2014-06-03 11:08:54 +04:00
|
|
|
selCon->SetCaretEnabled(false);
|
2010-12-02 00:38:21 +03:00
|
|
|
|
2013-05-22 07:28:43 +04:00
|
|
|
// Caret must blink on non-editable elements
|
|
|
|
caret->SetIgnoreUserModify(true);
|
2010-12-02 00:38:21 +03:00
|
|
|
// Tell the caret which selection to use
|
2014-08-06 09:19:27 +04:00
|
|
|
caret->SetSelection(domSelection);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
// In content, we need to set the caret. The only special case is edit
|
|
|
|
// fields, which have a different frame selection from the document.
|
|
|
|
// They will take care of making the caret visible themselves.
|
|
|
|
|
2013-05-22 07:28:43 +04:00
|
|
|
selCon->SetCaretReadOnly(false);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
selCon->SetCaretEnabled(aVisible);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsFocusManager::GetSelectionLocation(nsIDocument* aDocument,
|
|
|
|
nsIPresShell* aPresShell,
|
|
|
|
nsIContent **aStartContent,
|
|
|
|
nsIContent **aEndContent)
|
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
*aStartContent = *aEndContent = nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsPresContext* presContext = aPresShell->GetPresContext();
|
|
|
|
NS_ASSERTION(presContext, "mPresContent is null!!");
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsFrameSelection> frameSelection = aPresShell->FrameSelection();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2018-03-27 07:35:21 +03:00
|
|
|
RefPtr<Selection> domSelection;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (frameSelection) {
|
2016-06-09 12:35:22 +03:00
|
|
|
domSelection = frameSelection->GetSelection(SelectionType::eNormal);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool isCollapsed = false;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsCOMPtr<nsIContent> startContent, endContent;
|
2017-07-19 16:49:52 +03:00
|
|
|
uint32_t startOffset = 0;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (domSelection) {
|
2018-03-27 07:35:21 +03:00
|
|
|
isCollapsed = domSelection->IsCollapsed();
|
|
|
|
RefPtr<nsRange> domRange = domSelection->GetRangeAt(0);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (domRange) {
|
2018-03-27 07:35:21 +03:00
|
|
|
nsCOMPtr<nsINode> startNode = domRange->GetStartContainer();
|
|
|
|
nsCOMPtr<nsINode> endNode = domRange->GetEndContainer();
|
|
|
|
startOffset = domRange->StartOffset();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
nsIContent *childContent = nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
startContent = do_QueryInterface(startNode);
|
2010-04-30 17:12:06 +04:00
|
|
|
if (startContent && startContent->IsElement()) {
|
2018-01-03 15:59:54 +03:00
|
|
|
childContent = startContent->GetChildAt_Deprecated(startOffset);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (childContent) {
|
|
|
|
startContent = childContent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
endContent = do_QueryInterface(endNode);
|
2010-04-30 17:12:06 +04:00
|
|
|
if (endContent && endContent->IsElement()) {
|
2018-03-27 07:35:21 +03:00
|
|
|
uint32_t endOffset = domRange->EndOffset();
|
2018-01-03 15:59:54 +03:00
|
|
|
childContent = endContent->GetChildAt_Deprecated(endOffset);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (childContent) {
|
|
|
|
endContent = childContent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2018-03-27 07:35:21 +03:00
|
|
|
return NS_ERROR_INVALID_ARG;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
nsIFrame *startFrame = nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (startContent) {
|
2009-12-25 00:20:06 +03:00
|
|
|
startFrame = startContent->GetPrimaryFrame();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (isCollapsed) {
|
|
|
|
// Next check to see if our caret is at the very end of a node
|
|
|
|
// If so, the caret is actually sitting in front of the next
|
|
|
|
// logical frame's primary node - so for this case we need to
|
|
|
|
// change caretContent to that node.
|
|
|
|
|
2018-01-30 07:10:53 +03:00
|
|
|
if (startContent->NodeType() == nsINode::TEXT_NODE) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsAutoString nodeValue;
|
2018-03-29 01:01:47 +03:00
|
|
|
startContent->GetAsText()->AppendTextTo(nodeValue);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool isFormControl =
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
startContent->IsNodeOfType(nsINode::eHTML_FORM_CONTROL);
|
|
|
|
|
2017-07-19 16:49:52 +03:00
|
|
|
if (nodeValue.Length() == startOffset && !isFormControl &&
|
2010-04-30 17:12:05 +04:00
|
|
|
startContent != aDocument->GetRootElement()) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// Yes, indeed we were at the end of the last node
|
2012-10-15 22:35:50 +04:00
|
|
|
nsCOMPtr<nsIFrameEnumerator> frameTraversal;
|
|
|
|
nsresult rv = NS_NewFrameTraversal(getter_AddRefs(frameTraversal),
|
|
|
|
presContext, startFrame,
|
|
|
|
eLeaf,
|
|
|
|
false, // aVisual
|
|
|
|
false, // aLockInScrollView
|
2015-07-13 13:07:49 +03:00
|
|
|
true, // aFollowOOFs
|
2018-01-26 18:47:44 +03:00
|
|
|
false, // aSkipPopupChecks
|
|
|
|
false // aSkipShadow
|
2012-10-15 22:35:50 +04:00
|
|
|
);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
nsIFrame *newCaretFrame = nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsCOMPtr<nsIContent> newCaretContent = startContent;
|
2011-09-29 10:19:26 +04:00
|
|
|
bool endOfSelectionInStartNode(startContent == endContent);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
do {
|
|
|
|
// Continue getting the next frame until the primary content for the frame
|
|
|
|
// we are on changes - we don't want to be stuck in the same place
|
2012-10-15 22:35:50 +04:00
|
|
|
frameTraversal->Next();
|
|
|
|
newCaretFrame = static_cast<nsIFrame*>(frameTraversal->CurrentItem());
|
2012-07-30 18:20:58 +04:00
|
|
|
if (nullptr == newCaretFrame)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
break;
|
2012-08-06 07:00:55 +04:00
|
|
|
newCaretContent = newCaretFrame->GetContent();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
} while (!newCaretContent || newCaretContent == startContent);
|
|
|
|
|
|
|
|
if (newCaretFrame && newCaretContent) {
|
|
|
|
// If the caret is exactly at the same position of the new frame,
|
|
|
|
// then we can use the newCaretFrame and newCaretContent for our position
|
|
|
|
nsRect caretRect;
|
2014-08-06 09:19:26 +04:00
|
|
|
nsIFrame *frame = nsCaret::GetGeometry(domSelection, &caretRect);
|
2010-03-15 01:52:07 +03:00
|
|
|
if (frame) {
|
2010-07-02 23:11:04 +04:00
|
|
|
nsPoint caretWidgetOffset;
|
|
|
|
nsIWidget *widget = frame->GetNearestWidget(caretWidgetOffset);
|
|
|
|
caretRect.MoveBy(caretWidgetOffset);
|
2010-03-15 01:52:07 +03:00
|
|
|
nsPoint newCaretOffset;
|
2010-07-02 23:11:04 +04:00
|
|
|
nsIWidget *newCaretWidget = newCaretFrame->GetNearestWidget(newCaretOffset);
|
2018-02-19 23:15:23 +03:00
|
|
|
if (widget == newCaretWidget && caretRect.y == newCaretOffset.y &&
|
|
|
|
caretRect.x == newCaretOffset.x) {
|
2010-03-15 01:52:07 +03:00
|
|
|
// The caret is at the start of the new element.
|
|
|
|
startFrame = newCaretFrame;
|
|
|
|
startContent = newCaretContent;
|
|
|
|
if (endOfSelectionInStartNode) {
|
|
|
|
endContent = newCaretContent; // Ensure end of selection is not before start
|
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*aStartContent = startContent;
|
|
|
|
*aEndContent = endContent;
|
|
|
|
NS_IF_ADDREF(*aStartContent);
|
|
|
|
NS_IF_ADDREF(*aEndContent);
|
|
|
|
|
2018-03-27 07:35:21 +03:00
|
|
|
return NS_OK;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2016-01-30 20:05:36 +03:00
|
|
|
nsFocusManager::DetermineElementToMoveFocus(nsPIDOMWindowOuter* aWindow,
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsIContent* aStartContent,
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t aType, bool aNoParentTraversal,
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsIContent** aNextContent)
|
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
*aNextContent = nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2015-07-13 13:07:49 +03:00
|
|
|
// True if we are navigating by document (F6/Shift+F6) or false if we are
|
|
|
|
// navigating by element (Tab/Shift+Tab).
|
|
|
|
bool forDocumentNavigation = false;
|
|
|
|
|
|
|
|
// This is used for document navigation only. It will be set to true if we
|
|
|
|
// start navigating from a starting point. If this starting point is near the
|
|
|
|
// end of the document (for example, an element on a statusbar), and there
|
|
|
|
// are no child documents or panels before the end of the document, then we
|
|
|
|
// will need to ensure that we don't consider the root chrome window when we
|
|
|
|
// loop around and instead find the next child document/panel, as focus is
|
|
|
|
// already in that window. This flag will be cleared once we navigate into
|
|
|
|
// another document.
|
|
|
|
bool mayFocusRoot = (aStartContent != nullptr);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
nsCOMPtr<nsIContent> startContent = aStartContent;
|
2012-02-24 01:02:33 +04:00
|
|
|
if (!startContent && aType != MOVEFOCUS_CARET) {
|
|
|
|
if (aType == MOVEFOCUS_FORWARDDOC || aType == MOVEFOCUS_BACKWARDDOC) {
|
|
|
|
// When moving between documents, make sure to get the right
|
|
|
|
// starting content in a descendant.
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
|
2017-09-07 16:54:49 +03:00
|
|
|
startContent = GetFocusedDescendant(aWindow, eIncludeAllDescendants,
|
|
|
|
getter_AddRefs(focusedWindow));
|
2012-02-24 01:02:33 +04:00
|
|
|
}
|
2015-09-29 21:49:34 +03:00
|
|
|
else if (aType != MOVEFOCUS_LASTDOC) {
|
|
|
|
// Otherwise, start at the focused node. If MOVEFOCUS_LASTDOC is used,
|
|
|
|
// then we are document-navigating backwards from chrome to the content
|
|
|
|
// process, and we don't want to use this so that we start from the end
|
|
|
|
// of the document.
|
2018-04-26 22:28:30 +03:00
|
|
|
startContent = aWindow->GetFocusedElement();
|
2012-02-24 01:02:33 +04:00
|
|
|
}
|
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
nsCOMPtr<nsIDocument> doc;
|
|
|
|
if (startContent)
|
2014-08-06 03:23:02 +04:00
|
|
|
doc = startContent->GetComposedDoc();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
else
|
2012-07-31 04:43:28 +04:00
|
|
|
doc = aWindow->GetExtantDoc();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (!doc)
|
|
|
|
return NS_OK;
|
|
|
|
|
2011-09-09 06:27:12 +04:00
|
|
|
LookAndFeel::GetInt(LookAndFeel::eIntID_TabFocusModel,
|
|
|
|
&nsIContent::sTabFocusModel);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2015-07-13 13:07:49 +03:00
|
|
|
// These types are for document navigation using F6.
|
|
|
|
if (aType == MOVEFOCUS_FORWARDDOC || aType == MOVEFOCUS_BACKWARDDOC ||
|
|
|
|
aType == MOVEFOCUS_FIRSTDOC || aType == MOVEFOCUS_LASTDOC) {
|
|
|
|
forDocumentNavigation = true;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
2015-07-13 13:07:49 +03:00
|
|
|
|
|
|
|
// If moving to the root or first document, find the root element and return.
|
|
|
|
if (aType == MOVEFOCUS_ROOT || aType == MOVEFOCUS_FIRSTDOC) {
|
|
|
|
NS_IF_ADDREF(*aNextContent = GetRootForFocus(aWindow, doc, false, false));
|
|
|
|
if (!*aNextContent && aType == MOVEFOCUS_FIRSTDOC) {
|
|
|
|
// When looking for the first document, if the root wasn't focusable,
|
|
|
|
// find the next focusable document.
|
|
|
|
aType = MOVEFOCUS_FORWARDDOC;
|
|
|
|
} else {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
2015-07-13 13:07:49 +03:00
|
|
|
|
2017-12-07 21:13:50 +03:00
|
|
|
Element* rootContent = doc->GetRootElement();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
NS_ENSURE_TRUE(rootContent, NS_OK);
|
|
|
|
|
2017-12-07 21:13:50 +03:00
|
|
|
nsIPresShell* presShell = doc->GetShell();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
NS_ENSURE_TRUE(presShell, NS_OK);
|
|
|
|
|
|
|
|
if (aType == MOVEFOCUS_FIRST) {
|
|
|
|
if (!aStartContent)
|
|
|
|
startContent = rootContent;
|
|
|
|
return GetNextTabbableContent(presShell, startContent,
|
2012-07-30 18:20:58 +04:00
|
|
|
nullptr, startContent,
|
2015-07-13 13:07:49 +03:00
|
|
|
true, 1, false, false, aNextContent);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
if (aType == MOVEFOCUS_LAST) {
|
|
|
|
if (!aStartContent)
|
|
|
|
startContent = rootContent;
|
|
|
|
return GetNextTabbableContent(presShell, startContent,
|
2012-07-30 18:20:58 +04:00
|
|
|
nullptr, startContent,
|
2015-07-13 13:07:49 +03:00
|
|
|
false, 0, false, false, aNextContent);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
2015-07-13 13:07:49 +03:00
|
|
|
bool forward = (aType == MOVEFOCUS_FORWARD ||
|
|
|
|
aType == MOVEFOCUS_FORWARDDOC ||
|
|
|
|
aType == MOVEFOCUS_CARET);
|
2011-09-29 10:19:26 +04:00
|
|
|
bool doNavigation = true;
|
|
|
|
bool ignoreTabIndex = false;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// when a popup is open, we want to ensure that tab navigation occurs only
|
|
|
|
// within the most recently opened panel. If a popup is open, its frame will
|
|
|
|
// be stored in popupFrame.
|
2012-07-30 18:20:58 +04:00
|
|
|
nsIFrame* popupFrame = nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t tabIndex = forward ? 1 : 0;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (startContent) {
|
2009-12-25 00:20:06 +03:00
|
|
|
nsIFrame* frame = startContent->GetPrimaryFrame();
|
2015-03-03 14:09:00 +03:00
|
|
|
if (startContent->IsHTMLElement(nsGkAtoms::area))
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
startContent->IsFocusable(&tabIndex);
|
|
|
|
else if (frame)
|
|
|
|
frame->IsFocusable(&tabIndex, 0);
|
2009-11-20 15:09:33 +03:00
|
|
|
else
|
|
|
|
startContent->IsFocusable(&tabIndex);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
// if the current element isn't tabbable, ignore the tabindex and just
|
|
|
|
// look for the next element. The root content won't have a tabindex
|
|
|
|
// so just treat this as the beginning of the tab order.
|
|
|
|
if (tabIndex < 0) {
|
|
|
|
tabIndex = 1;
|
|
|
|
if (startContent != rootContent)
|
2011-10-17 18:59:28 +04:00
|
|
|
ignoreTabIndex = true;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// check if the focus is currently inside a popup. Elements such as the
|
|
|
|
// autocomplete widget use the noautofocus attribute to allow the focus to
|
|
|
|
// remain outside the popup when it is opened.
|
|
|
|
if (frame) {
|
2017-04-30 18:30:08 +03:00
|
|
|
popupFrame =
|
2017-05-01 20:32:52 +03:00
|
|
|
nsLayoutUtils::GetClosestFrameOfType(frame, LayoutFrameType::MenuPopup);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
2015-07-13 13:07:49 +03:00
|
|
|
if (popupFrame && !forDocumentNavigation) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// Don't navigate outside of a popup, so pretend that the
|
|
|
|
// root content is the popup itself
|
2017-12-07 21:13:50 +03:00
|
|
|
rootContent = popupFrame->GetContent()->AsElement();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
NS_ASSERTION(rootContent, "Popup frame doesn't have a content node");
|
|
|
|
}
|
2010-04-21 17:13:08 +04:00
|
|
|
else if (!forward) {
|
|
|
|
// If focus moves backward and when current focused node is root
|
|
|
|
// content or <body> element which is editable by contenteditable
|
|
|
|
// attribute, focus should move to its parent document.
|
|
|
|
if (startContent == rootContent) {
|
2011-10-17 18:59:28 +04:00
|
|
|
doNavigation = false;
|
2010-04-21 17:13:08 +04:00
|
|
|
} else {
|
2014-08-06 03:23:02 +04:00
|
|
|
nsIDocument* doc = startContent->GetComposedDoc();
|
2010-04-21 17:13:08 +04:00
|
|
|
if (startContent ==
|
|
|
|
nsLayoutUtils::GetEditableRootContentByContentEditable(doc)) {
|
2011-10-17 18:59:28 +04:00
|
|
|
doNavigation = false;
|
2010-04-21 17:13:08 +04:00
|
|
|
}
|
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
#ifdef MOZ_XUL
|
2012-05-30 11:39:17 +04:00
|
|
|
if (aType != MOVEFOCUS_CARET) {
|
|
|
|
// if there is no focus, yet a panel is open, focus the first item in
|
|
|
|
// the panel
|
|
|
|
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
|
|
|
if (pm)
|
|
|
|
popupFrame = pm->GetTopPopup(ePopupTypePanel);
|
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
#endif
|
|
|
|
if (popupFrame) {
|
2015-07-13 13:07:49 +03:00
|
|
|
// When there is a popup open, and no starting content, start the search
|
|
|
|
// at the topmost popup.
|
|
|
|
startContent = popupFrame->GetContent();
|
|
|
|
NS_ASSERTION(startContent, "Popup frame doesn't have a content node");
|
|
|
|
// Unless we are searching for documents, set the root content to the
|
|
|
|
// popup as well, so that we don't tab-navigate outside the popup.
|
|
|
|
// When navigating by documents, we start at the popup but can navigate
|
|
|
|
// outside of it to look for other panels and documents.
|
|
|
|
if (!forDocumentNavigation) {
|
2017-12-07 21:13:50 +03:00
|
|
|
rootContent = startContent->AsElement();
|
2015-07-13 13:07:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
doc = startContent ? startContent->GetComposedDoc() : nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Otherwise, for content shells, start from the location of the caret.
|
2015-07-13 13:07:49 +03:00
|
|
|
nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell();
|
|
|
|
if (docShell && docShell->ItemType() != nsIDocShellTreeItem::typeChrome) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsCOMPtr<nsIContent> endSelectionContent;
|
|
|
|
GetSelectionLocation(doc, presShell,
|
|
|
|
getter_AddRefs(startContent),
|
|
|
|
getter_AddRefs(endSelectionContent));
|
|
|
|
// If the selection is on the rootContent, then there is no selection
|
|
|
|
if (startContent == rootContent) {
|
2012-07-30 18:20:58 +04:00
|
|
|
startContent = nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
2010-02-23 21:16:19 +03:00
|
|
|
if (aType == MOVEFOCUS_CARET) {
|
|
|
|
// GetFocusInSelection finds a focusable link near the caret.
|
|
|
|
// If there is no start content though, don't do this to avoid
|
|
|
|
// focusing something unexpected.
|
|
|
|
if (startContent) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
GetFocusInSelection(aWindow, startContent,
|
|
|
|
endSelectionContent, aNextContent);
|
|
|
|
}
|
2010-02-23 21:16:19 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2009-11-20 15:09:33 +03:00
|
|
|
|
2010-02-23 21:16:19 +03:00
|
|
|
if (startContent) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// when starting from a selection, we always want to find the next or
|
|
|
|
// previous element in the document. So the tabindex on elements
|
|
|
|
// should be ignored.
|
2011-10-17 18:59:28 +04:00
|
|
|
ignoreTabIndex = true;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!startContent) {
|
|
|
|
// otherwise, just use the root content as the starting point
|
|
|
|
startContent = rootContent;
|
|
|
|
NS_ENSURE_TRUE(startContent, NS_OK);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-13 13:07:50 +03:00
|
|
|
// Check if the starting content is the same as the content assigned to the
|
|
|
|
// retargetdocumentfocus attribute. Is so, we don't want to start searching
|
|
|
|
// from there but instead from the beginning of the document. Otherwise, the
|
|
|
|
// content that appears before the retargetdocumentfocus element will never
|
|
|
|
// get checked as it will be skipped when the focus is retargetted to it.
|
|
|
|
if (forDocumentNavigation && doc->IsXULDocument()) {
|
|
|
|
nsAutoString retarget;
|
|
|
|
|
|
|
|
if (rootContent->GetAttr(kNameSpaceID_None,
|
|
|
|
nsGkAtoms::retargetdocumentfocus, retarget)) {
|
|
|
|
nsIContent* retargetElement = doc->GetElementById(retarget);
|
|
|
|
// The common case here is the urlbar where focus is on the anonymous
|
|
|
|
// input inside the textbox, but the retargetdocumentfocus attribute
|
|
|
|
// refers to the textbox. The Contains check will return false and the
|
|
|
|
// ContentIsDescendantOf check will return true in this case.
|
|
|
|
if (retargetElement && (retargetElement == startContent ||
|
|
|
|
(!retargetElement->Contains(startContent) &&
|
|
|
|
nsContentUtils::ContentIsDescendantOf(startContent, retargetElement)))) {
|
|
|
|
startContent = rootContent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
NS_ASSERTION(startContent, "starting content not set");
|
|
|
|
|
|
|
|
// keep a reference to the starting content. If we find that again, it means
|
|
|
|
// we've iterated around completely and we don't want to adjust the focus.
|
|
|
|
// The skipOriginalContentCheck will be set to true only for the first time
|
|
|
|
// GetNextTabbableContent is called. This ensures that we don't break out
|
|
|
|
// when nothing is focused to start with. Specifically,
|
|
|
|
// GetNextTabbableContent first checks the root content -- which happens to
|
|
|
|
// be the same as the start content -- when nothing is focused and tabbing
|
|
|
|
// forward. Without skipOriginalContentCheck set to true, we'd end up
|
|
|
|
// returning right away and focusing nothing. Luckily, GetNextTabbableContent
|
|
|
|
// will never wrap around on its own, and can only return the original
|
|
|
|
// content when it is called a second time or later.
|
2011-09-29 10:19:26 +04:00
|
|
|
bool skipOriginalContentCheck = true;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsIContent* originalStartContent = startContent;
|
|
|
|
|
2012-07-31 04:43:28 +04:00
|
|
|
LOGCONTENTNAVIGATION("Focus Navigation Start Content %s", startContent.get());
|
2015-07-13 13:07:49 +03:00
|
|
|
LOGFOCUSNAVIGATION((" Forward: %d Tabindex: %d Ignore: %d DocNav: %d",
|
|
|
|
forward, tabIndex, ignoreTabIndex, forDocumentNavigation));
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
while (doc) {
|
|
|
|
if (doNavigation) {
|
|
|
|
nsCOMPtr<nsIContent> nextFocus;
|
|
|
|
nsresult rv = GetNextTabbableContent(presShell, rootContent,
|
2012-07-30 18:20:58 +04:00
|
|
|
skipOriginalContentCheck ? nullptr : originalStartContent,
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
startContent, forward,
|
|
|
|
tabIndex, ignoreTabIndex,
|
2015-07-13 13:07:49 +03:00
|
|
|
forDocumentNavigation,
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
getter_AddRefs(nextFocus));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2015-07-13 13:07:49 +03:00
|
|
|
if (rv == NS_SUCCESS_DOM_NO_OPERATION) {
|
|
|
|
// Navigation was redirected to a child process, so just return.
|
|
|
|
return NS_OK;
|
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
// found a content node to focus.
|
|
|
|
if (nextFocus) {
|
2012-07-31 04:43:28 +04:00
|
|
|
LOGCONTENTNAVIGATION("Next Content: %s", nextFocus.get());
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// as long as the found node was not the same as the starting node,
|
2015-07-13 13:07:49 +03:00
|
|
|
// set it as the return value. For document navigation, we can return
|
|
|
|
// the same element in case there is only one content node that could
|
2017-07-06 15:00:35 +03:00
|
|
|
// be returned, for example, in a child process document.
|
2015-07-13 13:07:49 +03:00
|
|
|
if (nextFocus != originalStartContent || forDocumentNavigation) {
|
2015-03-31 17:03:49 +03:00
|
|
|
nextFocus.forget(aNextContent);
|
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2015-07-13 13:07:49 +03:00
|
|
|
if (popupFrame && !forDocumentNavigation) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// in a popup, so start again from the beginning of the popup. However,
|
|
|
|
// if we already started at the beginning, then there isn't anything to
|
|
|
|
// focus, so just return
|
|
|
|
if (startContent != rootContent) {
|
|
|
|
startContent = rootContent;
|
|
|
|
tabIndex = forward ? 1 : 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
doNavigation = true;
|
2015-07-13 13:07:49 +03:00
|
|
|
skipOriginalContentCheck = forDocumentNavigation;
|
2011-10-17 18:59:28 +04:00
|
|
|
ignoreTabIndex = false;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2012-02-13 23:24:28 +04:00
|
|
|
if (aNoParentTraversal) {
|
2013-10-08 18:49:55 +04:00
|
|
|
if (startContent == rootContent)
|
|
|
|
return NS_OK;
|
|
|
|
|
2012-02-13 23:24:28 +04:00
|
|
|
startContent = rootContent;
|
|
|
|
tabIndex = forward ? 1 : 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2015-07-13 13:07:49 +03:00
|
|
|
// Reached the beginning or end of the document. Next, navigate up to the
|
|
|
|
// parent document and try again.
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> piWindow = doc->GetWindow();
|
2015-07-13 13:07:49 +03:00
|
|
|
NS_ENSURE_TRUE(piWindow, NS_ERROR_FAILURE);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2015-07-13 13:07:49 +03:00
|
|
|
nsCOMPtr<nsIDocShell> docShell = piWindow->GetDocShell();
|
|
|
|
NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2015-07-13 13:07:49 +03:00
|
|
|
// Get the frame element this window is inside and, from that, get the
|
|
|
|
// parent document and presshell. If there is no enclosing frame element,
|
|
|
|
// then this is a top-level, embedded or remote window.
|
|
|
|
startContent = piWindow->GetFrameElementInternal();
|
|
|
|
if (startContent) {
|
|
|
|
doc = startContent->GetComposedDoc();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
|
|
|
|
|
2015-07-13 13:07:49 +03:00
|
|
|
rootContent = doc->GetRootElement();
|
2010-06-25 17:59:57 +04:00
|
|
|
presShell = doc->GetShell();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2015-07-13 13:07:49 +03:00
|
|
|
// We can focus the root element now that we have moved to another document.
|
|
|
|
mayFocusRoot = true;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2015-07-13 13:07:49 +03:00
|
|
|
nsIFrame* frame = startContent->GetPrimaryFrame();
|
|
|
|
if (!frame) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2015-07-13 13:07:49 +03:00
|
|
|
frame->IsFocusable(&tabIndex, 0);
|
|
|
|
if (tabIndex < 0) {
|
|
|
|
tabIndex = 1;
|
|
|
|
ignoreTabIndex = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if the frame is inside a popup, make sure to scan only within the
|
|
|
|
// popup. This handles the situation of tabbing amongst elements
|
|
|
|
// inside an iframe which is itself inside a popup. Otherwise,
|
|
|
|
// navigation would move outside the popup when tabbing outside the
|
|
|
|
// iframe.
|
|
|
|
if (!forDocumentNavigation) {
|
2017-05-01 20:32:52 +03:00
|
|
|
popupFrame = nsLayoutUtils::GetClosestFrameOfType(
|
|
|
|
frame, LayoutFrameType::MenuPopup);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (popupFrame) {
|
2017-12-07 21:13:50 +03:00
|
|
|
rootContent = popupFrame->GetContent()->AsElement();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
NS_ASSERTION(rootContent, "Popup frame doesn't have a content node");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2015-07-13 13:07:49 +03:00
|
|
|
// There is no parent, so call the tree owner. This will tell the
|
|
|
|
// embedder or parent process that it should take the focus.
|
2011-09-29 10:19:26 +04:00
|
|
|
bool tookFocus;
|
2015-07-13 13:07:49 +03:00
|
|
|
docShell->TabToTreeOwner(forward, forDocumentNavigation, &tookFocus);
|
2018-04-26 22:28:31 +03:00
|
|
|
// If the tree owner took the focus, blur the current element.
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (tookFocus) {
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> window = docShell->GetWindow();
|
2018-04-26 22:28:31 +03:00
|
|
|
if (window->GetFocusedElement() == mFocusedElement)
|
2012-07-30 18:20:58 +04:00
|
|
|
Blur(mFocusedWindow, nullptr, true, true);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
else
|
2018-04-26 22:28:30 +03:00
|
|
|
window->SetFocusedElement(nullptr);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2015-07-13 13:07:49 +03:00
|
|
|
// If we have reached the end of the top-level document, focus the
|
|
|
|
// first element in the top-level document. This should always happen
|
|
|
|
// when navigating by document forwards but when navigating backwards,
|
|
|
|
// only do this if we started in another document or within a popup frame.
|
|
|
|
// If the focus started in this window outside a popup however, we should
|
|
|
|
// continue by looping around to the end again.
|
|
|
|
if (forDocumentNavigation && (forward || mayFocusRoot || popupFrame)) {
|
|
|
|
// HTML content documents can have their root element focused (a focus
|
|
|
|
// ring appears around the entire content area frame). This root
|
|
|
|
// appears in the tab order before all of the elements in the document.
|
|
|
|
// Chrome documents however cannot be focused directly, so instead we
|
|
|
|
// focus the first focusable element within the window.
|
|
|
|
// For example, the urlbar.
|
2017-12-07 21:13:50 +03:00
|
|
|
Element* root = GetRootForFocus(piWindow, doc, true, true);
|
2015-07-13 13:07:49 +03:00
|
|
|
return FocusFirst(root, aNextContent);
|
|
|
|
}
|
|
|
|
|
2015-12-02 17:34:42 +03:00
|
|
|
// Once we have hit the top-level and have iterated to the end again, we
|
|
|
|
// just want to break out next time we hit this spot to prevent infinite
|
|
|
|
// iteration.
|
|
|
|
mayFocusRoot = true;
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// reset the tab index and start again from the beginning or end
|
|
|
|
startContent = rootContent;
|
|
|
|
tabIndex = forward ? 1 : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// wrapped all the way around and didn't find anything to move the focus
|
|
|
|
// to, so just break out
|
|
|
|
if (startContent == originalStartContent)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2018-01-26 18:48:26 +03:00
|
|
|
// Helper class to iterate contents in scope by traversing flattened tree
|
|
|
|
// in tree order
|
|
|
|
class MOZ_STACK_CLASS ScopedContentTraversal
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ScopedContentTraversal(nsIContent* aStartContent, nsIContent* aOwner)
|
|
|
|
: mCurrent(aStartContent)
|
|
|
|
, mOwner(aOwner)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(aStartContent);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Next();
|
|
|
|
void Prev();
|
|
|
|
|
|
|
|
void Reset()
|
|
|
|
{
|
|
|
|
SetCurrent(mOwner);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIContent* GetCurrent()
|
|
|
|
{
|
|
|
|
return mCurrent;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
void SetCurrent(nsIContent* aContent)
|
|
|
|
{
|
|
|
|
mCurrent = aContent;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIContent* mCurrent;
|
|
|
|
nsIContent* mOwner;
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
ScopedContentTraversal::Next()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mCurrent);
|
|
|
|
|
|
|
|
// Get mCurrent's first child if it's in the same scope.
|
|
|
|
if (!(mCurrent->GetShadowRoot() || mCurrent->IsHTMLElement(nsGkAtoms::slot)) ||
|
|
|
|
mCurrent == mOwner) {
|
|
|
|
FlattenedChildIterator iter(mCurrent);
|
|
|
|
nsIContent* child = iter.GetNextChild();
|
|
|
|
if (child) {
|
|
|
|
SetCurrent(child);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If mOwner has no children, END traversal
|
|
|
|
if (mCurrent == mOwner) {
|
|
|
|
SetCurrent(nullptr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIContent* current = mCurrent;
|
|
|
|
while (1) {
|
|
|
|
// Create parent's iterator and move to current
|
|
|
|
nsIContent* parent = current->GetFlattenedTreeParent();
|
|
|
|
FlattenedChildIterator parentIter(parent);
|
|
|
|
parentIter.Seek(current);
|
|
|
|
|
|
|
|
// Get next sibling of current
|
|
|
|
nsIContent* next = parentIter.GetNextChild();
|
|
|
|
if (next) {
|
|
|
|
SetCurrent(next);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If no next sibling and parent is mOwner, END traversal
|
|
|
|
if (parent == mOwner) {
|
|
|
|
SetCurrent(nullptr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
current = parent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ScopedContentTraversal::Prev()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mCurrent);
|
|
|
|
|
|
|
|
nsIContent* parent;
|
|
|
|
nsIContent* last;
|
|
|
|
if (mCurrent == mOwner) {
|
|
|
|
// Get last child of mOwner
|
|
|
|
FlattenedChildIterator ownerIter(mOwner, false /* aStartAtBeginning */);
|
|
|
|
last = ownerIter.GetPreviousChild();
|
|
|
|
|
|
|
|
parent = last;
|
|
|
|
} else {
|
|
|
|
// Create parent's iterator and move to mCurrent
|
|
|
|
parent = mCurrent->GetFlattenedTreeParent();
|
|
|
|
FlattenedChildIterator parentIter(parent);
|
|
|
|
parentIter.Seek(mCurrent);
|
|
|
|
|
|
|
|
// Get previous sibling
|
|
|
|
last = parentIter.GetPreviousChild();
|
|
|
|
}
|
|
|
|
|
|
|
|
while (last) {
|
|
|
|
parent = last;
|
|
|
|
if (parent->GetShadowRoot() ||
|
|
|
|
parent->IsHTMLElement(nsGkAtoms::slot)) {
|
|
|
|
// Skip contents in other scopes
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find last child
|
|
|
|
FlattenedChildIterator iter(parent, false /* aStartAtBeginning */);
|
|
|
|
last = iter.GetPreviousChild();
|
|
|
|
}
|
|
|
|
|
|
|
|
// If parent is mOwner and no previous sibling remains, END traversal
|
|
|
|
SetCurrent(parent == mOwner ? nullptr : parent);
|
|
|
|
}
|
|
|
|
|
2018-01-26 18:49:06 +03:00
|
|
|
nsIContent*
|
|
|
|
nsFocusManager::FindOwner(nsIContent* aContent)
|
|
|
|
{
|
|
|
|
nsIContent* currentContent = aContent;
|
|
|
|
while (currentContent) {
|
|
|
|
nsIContent* parent = currentContent->GetFlattenedTreeParent();
|
|
|
|
if (!parent) {
|
|
|
|
// Document root
|
|
|
|
nsIDocument* doc = currentContent->GetUncomposedDoc();
|
|
|
|
if (doc && doc->GetRootElement() == currentContent) {
|
|
|
|
return currentContent;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Shadow host / Slot
|
|
|
|
if (IsHostOrSlot(parent)) {
|
|
|
|
return parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
currentContent = parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
nsFocusManager::IsHostOrSlot(nsIContent* aContent)
|
|
|
|
{
|
|
|
|
return aContent->GetShadowRoot() || // shadow host
|
|
|
|
aContent->IsHTMLElement(nsGkAtoms::slot); // slot
|
|
|
|
}
|
|
|
|
|
2018-04-22 14:25:38 +03:00
|
|
|
int32_t
|
|
|
|
nsFocusManager::HostOrSlotTabIndexValue(nsIContent* aContent)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(IsHostOrSlot(aContent));
|
|
|
|
|
|
|
|
const nsAttrValue* attrVal =
|
|
|
|
aContent->AsElement()->GetParsedAttr(nsGkAtoms::tabindex);
|
|
|
|
if (!attrVal) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (attrVal->Type() == nsAttrValue::eInteger) {
|
|
|
|
return attrVal->GetIntegerValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2018-01-26 18:49:06 +03:00
|
|
|
nsIContent*
|
|
|
|
nsFocusManager::GetNextTabbableContentInScope(nsIContent* aOwner,
|
|
|
|
nsIContent* aStartContent,
|
2018-04-28 16:07:06 +03:00
|
|
|
nsIContent* aOriginalStartContent,
|
2018-01-26 18:49:06 +03:00
|
|
|
bool aForward,
|
|
|
|
int32_t aCurrentTabIndex,
|
|
|
|
bool aIgnoreTabIndex,
|
2018-04-28 16:07:06 +03:00
|
|
|
bool aForDocumentNavigation,
|
2018-01-26 18:49:06 +03:00
|
|
|
bool aSkipOwner)
|
|
|
|
{
|
|
|
|
// Return shadow host at first for forward navigation if its tabindex
|
|
|
|
// is non-negative
|
|
|
|
bool skipOwner = aSkipOwner || !aOwner->GetShadowRoot();
|
|
|
|
if (!skipOwner && (aForward && aOwner == aStartContent)) {
|
|
|
|
int32_t tabIndex = 0;
|
|
|
|
aOwner->IsFocusable(&tabIndex);
|
|
|
|
if (tabIndex >= 0) {
|
|
|
|
return aOwner;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Iterate contents in scope
|
|
|
|
//
|
|
|
|
ScopedContentTraversal contentTraversal(aStartContent, aOwner);
|
|
|
|
nsCOMPtr<nsIContent> iterContent;
|
2018-04-27 12:37:43 +03:00
|
|
|
nsIContent* firstNonChromeOnly = aStartContent->IsInNativeAnonymousSubtree() ?
|
|
|
|
aStartContent->FindFirstNonChromeOnlyAccessContent() : nullptr;
|
2018-01-26 18:49:06 +03:00
|
|
|
while (1) {
|
|
|
|
// Iterate tab index to find corresponding contents in scope
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
// Iterate remaining contents in scope to find next content to focus
|
|
|
|
|
|
|
|
// Get next content
|
|
|
|
aForward ? contentTraversal.Next() : contentTraversal.Prev();
|
|
|
|
iterContent = contentTraversal.GetCurrent();
|
2018-04-27 12:37:43 +03:00
|
|
|
|
|
|
|
if (firstNonChromeOnly && firstNonChromeOnly == iterContent) {
|
|
|
|
// We just broke out from the native anonynous content, so move
|
|
|
|
// to the previous/next node of the native anonymous owner.
|
|
|
|
if (aForward) {
|
|
|
|
contentTraversal.Next();
|
|
|
|
} else {
|
|
|
|
contentTraversal.Prev();
|
|
|
|
}
|
|
|
|
iterContent = contentTraversal.GetCurrent();
|
|
|
|
}
|
2018-01-26 18:49:06 +03:00
|
|
|
if (!iterContent) {
|
|
|
|
// Reach the end
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2018-04-27 12:37:43 +03:00
|
|
|
// Get the tab index of the next element. For NAC we rely on frames.
|
|
|
|
//XXXsmaug we should probably use frames also for Shadow DOM and special
|
|
|
|
// case only display:contents elements.
|
2018-01-26 18:49:06 +03:00
|
|
|
int32_t tabIndex = 0;
|
2018-04-27 12:37:43 +03:00
|
|
|
if (iterContent->IsInNativeAnonymousSubtree() &&
|
|
|
|
iterContent->GetPrimaryFrame()) {
|
|
|
|
iterContent->GetPrimaryFrame()->IsFocusable(&tabIndex);
|
|
|
|
} else {
|
|
|
|
iterContent->IsFocusable(&tabIndex);
|
|
|
|
}
|
2018-01-26 18:49:06 +03:00
|
|
|
if (tabIndex < 0 || !(aIgnoreTabIndex || tabIndex == aCurrentTabIndex)) {
|
2018-04-27 12:37:43 +03:00
|
|
|
// If the element has native anonymous content, we may need to
|
|
|
|
// focus some NAC element, even if the element itself isn't focusable.
|
|
|
|
// This happens for example with <input type="date">.
|
|
|
|
// So, try to find NAC and then traverse the frame tree to find elements
|
|
|
|
// to focus.
|
|
|
|
nsIFrame* possibleAnonOwnerFrame = iterContent->GetPrimaryFrame();
|
|
|
|
nsIAnonymousContentCreator* anonCreator =
|
|
|
|
do_QueryFrame(possibleAnonOwnerFrame);
|
|
|
|
if (anonCreator && !iterContent->IsInNativeAnonymousSubtree()) {
|
|
|
|
nsIFrame* frame = nullptr;
|
|
|
|
// Find the first or last frame in tree order so that
|
|
|
|
// we can scope frame traversing to NAC.
|
|
|
|
if (aForward) {
|
|
|
|
frame = possibleAnonOwnerFrame->PrincipalChildList().FirstChild();
|
|
|
|
} else {
|
|
|
|
frame = possibleAnonOwnerFrame->PrincipalChildList().LastChild();
|
|
|
|
nsIFrame* last = frame;
|
|
|
|
while (last) {
|
|
|
|
frame = last;
|
|
|
|
last = frame->PrincipalChildList().LastChild();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
nsCOMPtr<nsIFrameEnumerator> frameTraversal;
|
|
|
|
nsresult rv = NS_NewFrameTraversal(getter_AddRefs(frameTraversal),
|
|
|
|
iterContent->OwnerDoc()->
|
|
|
|
GetShell()->GetPresContext(),
|
|
|
|
frame,
|
|
|
|
ePreOrder,
|
|
|
|
false, // aVisual
|
|
|
|
false, // aLockInScrollView
|
|
|
|
true, // aFollowOOFs
|
|
|
|
true, // aSkipPopupChecks
|
|
|
|
false // aSkipShadow
|
|
|
|
);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
nsIFrame* frame =
|
|
|
|
static_cast<nsIFrame*>(frameTraversal->CurrentItem());
|
|
|
|
while (frame) {
|
|
|
|
int32_t tabIndex;
|
|
|
|
frame->IsFocusable(&tabIndex, 0);
|
|
|
|
if (tabIndex >= 0 &&
|
|
|
|
(aIgnoreTabIndex || aCurrentTabIndex == tabIndex)) {
|
|
|
|
return frame->GetContent();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aForward) {
|
|
|
|
frameTraversal->Next();
|
|
|
|
} else {
|
|
|
|
frameTraversal->Prev();
|
|
|
|
}
|
|
|
|
frame = static_cast<nsIFrame*>(frameTraversal->CurrentItem());
|
|
|
|
if (frame == possibleAnonOwnerFrame) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-26 18:49:06 +03:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!IsHostOrSlot(iterContent)) {
|
2018-04-28 16:07:06 +03:00
|
|
|
nsCOMPtr<nsIContent> elementInFrame;
|
|
|
|
bool checkSubDocument = true;
|
|
|
|
if (aForDocumentNavigation &&
|
|
|
|
TryDocumentNavigation(iterContent, &checkSubDocument,
|
|
|
|
getter_AddRefs(elementInFrame))) {
|
|
|
|
return elementInFrame;
|
|
|
|
}
|
|
|
|
if (!checkSubDocument) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (TryToMoveFocusToSubDocument(iterContent, aOriginalStartContent,
|
|
|
|
aForward, aForDocumentNavigation,
|
|
|
|
getter_AddRefs(elementInFrame))) {
|
|
|
|
return elementInFrame;
|
|
|
|
}
|
|
|
|
|
2018-01-26 18:49:06 +03:00
|
|
|
// Found content to focus
|
|
|
|
return iterContent;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Search in scope owned by iterContent
|
|
|
|
nsIContent* contentToFocus =
|
2018-04-28 16:07:06 +03:00
|
|
|
GetNextTabbableContentInScope(iterContent, iterContent,
|
|
|
|
aOriginalStartContent, aForward,
|
2018-01-26 18:49:06 +03:00
|
|
|
aForward ? 1 : 0, aIgnoreTabIndex,
|
2018-04-28 16:07:06 +03:00
|
|
|
aForDocumentNavigation,
|
2018-01-26 18:49:06 +03:00
|
|
|
false /* aSkipOwner */);
|
|
|
|
if (contentToFocus) {
|
|
|
|
return contentToFocus;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// If already at lowest priority tab (0), end search completely.
|
|
|
|
// A bit counterintuitive but true, tabindex order goes 1, 2, ... 32767, 0
|
|
|
|
if (aCurrentTabIndex == (aForward ? 0 : 1)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Continue looking for next highest priority tabindex
|
|
|
|
aCurrentTabIndex = GetNextTabIndex(aOwner, aCurrentTabIndex, aForward);
|
|
|
|
contentTraversal.Reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return shadow host at last for backward navigation if its tabindex
|
|
|
|
// is non-negative
|
|
|
|
if (!skipOwner && !aForward) {
|
|
|
|
int32_t tabIndex = 0;
|
|
|
|
aOwner->IsFocusable(&tabIndex);
|
|
|
|
if (tabIndex >= 0) {
|
|
|
|
return aOwner;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIContent*
|
|
|
|
nsFocusManager::GetNextTabbableContentInAncestorScopes(
|
|
|
|
nsIContent** aStartContent,
|
2018-04-28 16:07:06 +03:00
|
|
|
nsIContent* aOriginalStartContent,
|
2018-01-26 18:49:06 +03:00
|
|
|
bool aForward,
|
|
|
|
int32_t* aCurrentTabIndex,
|
2018-04-28 16:07:06 +03:00
|
|
|
bool aIgnoreTabIndex,
|
|
|
|
bool aForDocumentNavigation)
|
2018-01-26 18:49:06 +03:00
|
|
|
{
|
|
|
|
nsIContent* startContent = *aStartContent;
|
|
|
|
while (1) {
|
|
|
|
nsIContent* owner = FindOwner(startContent);
|
|
|
|
MOZ_ASSERT(owner, "focus navigation scope owner not in document");
|
|
|
|
|
|
|
|
int32_t tabIndex = 0;
|
|
|
|
startContent->IsFocusable(&tabIndex);
|
|
|
|
nsIContent* contentToFocus =
|
2018-04-28 16:07:06 +03:00
|
|
|
GetNextTabbableContentInScope(owner, startContent, aOriginalStartContent,
|
|
|
|
aForward, tabIndex, aIgnoreTabIndex,
|
|
|
|
aForDocumentNavigation,
|
2018-01-26 18:49:06 +03:00
|
|
|
false /* aSkipOwner */);
|
|
|
|
if (contentToFocus) {
|
|
|
|
return contentToFocus;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If not found in shadow DOM, search from the shadow host in light DOM
|
|
|
|
if (!owner->IsInShadowTree()) {
|
|
|
|
MOZ_ASSERT(owner->GetShadowRoot());
|
|
|
|
|
|
|
|
*aStartContent = owner;
|
2018-04-22 14:25:38 +03:00
|
|
|
*aCurrentTabIndex = HostOrSlotTabIndexValue(owner);
|
2018-01-26 18:49:06 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
startContent = owner;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsresult
|
|
|
|
nsFocusManager::GetNextTabbableContent(nsIPresShell* aPresShell,
|
|
|
|
nsIContent* aRootContent,
|
|
|
|
nsIContent* aOriginalStartContent,
|
|
|
|
nsIContent* aStartContent,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aForward,
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t aCurrentTabIndex,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aIgnoreTabIndex,
|
2015-07-13 13:07:49 +03:00
|
|
|
bool aForDocumentNavigation,
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsIContent** aResultContent)
|
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
*aResultContent = nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2009-11-20 15:09:33 +03:00
|
|
|
nsCOMPtr<nsIContent> startContent = aStartContent;
|
|
|
|
if (!startContent)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
return NS_OK;
|
|
|
|
|
2012-07-31 04:43:28 +04:00
|
|
|
LOGCONTENTNAVIGATION("GetNextTabbable: %s", aStartContent);
|
|
|
|
LOGFOCUSNAVIGATION((" tabindex: %d", aCurrentTabIndex));
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2018-01-26 18:49:06 +03:00
|
|
|
if (nsDocument::IsShadowDOMEnabled(aRootContent)) {
|
|
|
|
// If aStartContent is a shadow host or slot in forward navigation,
|
|
|
|
// search in scope owned by aStartContent
|
|
|
|
if (aForward && IsHostOrSlot(aStartContent)) {
|
|
|
|
nsIContent* contentToFocus =
|
2018-04-28 16:07:06 +03:00
|
|
|
GetNextTabbableContentInScope(aStartContent, aStartContent,
|
|
|
|
aOriginalStartContent, aForward,
|
2018-01-26 18:49:06 +03:00
|
|
|
aForward ? 1 : 0, aIgnoreTabIndex,
|
2018-04-28 16:07:06 +03:00
|
|
|
aForDocumentNavigation,
|
2018-01-26 18:49:06 +03:00
|
|
|
true /* aSkipOwner */);
|
|
|
|
if (contentToFocus) {
|
|
|
|
NS_ADDREF(*aResultContent = contentToFocus);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If aStartContent is not in scope owned by aRootContent
|
|
|
|
// (e.g., aStartContent is already in shadow DOM),
|
|
|
|
// search from scope including aStartContent
|
|
|
|
if (aRootContent != FindOwner(aStartContent)) {
|
|
|
|
nsIContent* contentToFocus =
|
2018-04-28 16:07:06 +03:00
|
|
|
GetNextTabbableContentInAncestorScopes(&aStartContent,
|
|
|
|
aOriginalStartContent,
|
|
|
|
aForward,
|
2018-01-26 18:49:06 +03:00
|
|
|
&aCurrentTabIndex,
|
2018-04-28 16:07:06 +03:00
|
|
|
aIgnoreTabIndex,
|
|
|
|
aForDocumentNavigation);
|
2018-01-26 18:49:06 +03:00
|
|
|
if (contentToFocus) {
|
|
|
|
NS_ADDREF(*aResultContent = contentToFocus);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we reach here, it means no next tabbable content in shadow DOM.
|
|
|
|
// We need to continue searching in light DOM, starting at the shadow host
|
|
|
|
// in light DOM (updated aStartContent) and its tabindex
|
|
|
|
// (updated aCurrentTabIndex).
|
|
|
|
}
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsPresContext* presContext = aPresShell->GetPresContext();
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool getNextFrame = true;
|
2009-11-20 15:09:33 +03:00
|
|
|
nsCOMPtr<nsIContent> iterStartContent = aStartContent;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
while (1) {
|
2009-12-25 00:20:06 +03:00
|
|
|
nsIFrame* startFrame = iterStartContent->GetPrimaryFrame();
|
2009-11-20 15:09:33 +03:00
|
|
|
// if there is no frame, look for another content node that has a frame
|
|
|
|
if (!startFrame) {
|
|
|
|
// if the root content doesn't have a frame, just return
|
|
|
|
if (iterStartContent == aRootContent)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
return NS_OK;
|
2009-11-20 15:09:33 +03:00
|
|
|
|
|
|
|
// look for the next or previous content node in tree order
|
2011-04-12 06:46:59 +04:00
|
|
|
iterStartContent = aForward ? iterStartContent->GetNextNode() : iterStartContent->GetPreviousContent();
|
|
|
|
// we've already skipped over the initial focused content, so we
|
|
|
|
// don't want to traverse frames.
|
2011-10-17 18:59:28 +04:00
|
|
|
getNextFrame = false;
|
2011-04-12 06:46:59 +04:00
|
|
|
if (iterStartContent)
|
|
|
|
continue;
|
2009-11-20 15:09:33 +03:00
|
|
|
|
|
|
|
// otherwise, as a last attempt, just look at the root content
|
|
|
|
iterStartContent = aRootContent;
|
|
|
|
continue;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
2015-07-13 13:07:49 +03:00
|
|
|
// For tab navigation, pass false for aSkipPopupChecks so that we don't
|
|
|
|
// iterate into or out of a popup. For document naviation pass true to
|
|
|
|
// ignore these boundaries.
|
2012-10-15 22:35:50 +04:00
|
|
|
nsCOMPtr<nsIFrameEnumerator> frameTraversal;
|
|
|
|
nsresult rv = NS_NewFrameTraversal(getter_AddRefs(frameTraversal),
|
|
|
|
presContext, startFrame,
|
|
|
|
ePreOrder,
|
|
|
|
false, // aVisual
|
|
|
|
false, // aLockInScrollView
|
2015-07-13 13:07:49 +03:00
|
|
|
true, // aFollowOOFs
|
2018-01-26 18:47:44 +03:00
|
|
|
aForDocumentNavigation, // aSkipPopupChecks
|
|
|
|
nsDocument::IsShadowDOMEnabled(aRootContent) // aSkipShadow
|
2012-10-15 22:35:50 +04:00
|
|
|
);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2009-11-20 15:09:33 +03:00
|
|
|
if (iterStartContent == aRootContent) {
|
2010-04-21 17:13:08 +04:00
|
|
|
if (!aForward) {
|
2012-10-15 22:35:50 +04:00
|
|
|
frameTraversal->Last();
|
2010-04-21 17:13:08 +04:00
|
|
|
} else if (aRootContent->IsFocusable()) {
|
2012-10-15 22:35:50 +04:00
|
|
|
frameTraversal->Next();
|
2010-04-21 17:13:08 +04:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
2009-11-20 15:09:33 +03:00
|
|
|
else if (getNextFrame &&
|
2015-03-03 14:09:00 +03:00
|
|
|
(!iterStartContent ||
|
|
|
|
!iterStartContent->IsHTMLElement(nsGkAtoms::area))) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// Need to do special check in case we're in an imagemap which has multiple
|
|
|
|
// content nodes per frame, so don't skip over the starting frame.
|
|
|
|
if (aForward)
|
2012-10-15 22:35:50 +04:00
|
|
|
frameTraversal->Next();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
else
|
2012-10-15 22:35:50 +04:00
|
|
|
frameTraversal->Prev();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Walk frames to find something tabbable matching mCurrentTabIndex
|
2012-10-15 22:35:50 +04:00
|
|
|
nsIFrame* frame = static_cast<nsIFrame*>(frameTraversal->CurrentItem());
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
while (frame) {
|
2015-07-13 13:07:49 +03:00
|
|
|
nsIContent* currentContent = frame->GetContent();
|
|
|
|
|
|
|
|
// For document navigation, check if this element is an open panel. Since
|
|
|
|
// panels aren't focusable (tabIndex would be -1), we'll just assume that
|
|
|
|
// for document navigation, the tabIndex is 0.
|
|
|
|
if (aForDocumentNavigation && currentContent && (aCurrentTabIndex == 0) &&
|
|
|
|
currentContent->IsXULElement(nsGkAtoms::panel)) {
|
|
|
|
nsMenuPopupFrame* popupFrame = do_QueryFrame(frame);
|
|
|
|
// Check if the panel is open. Closed panels are ignored since you can't
|
|
|
|
// focus anything in them.
|
|
|
|
if (popupFrame && popupFrame->IsOpen()) {
|
|
|
|
// When moving backward, skip the popup we started in otherwise it
|
|
|
|
// will be selected again.
|
|
|
|
bool validPopup = true;
|
|
|
|
if (!aForward) {
|
|
|
|
nsIContent* content = aStartContent;
|
|
|
|
while (content) {
|
|
|
|
if (content == currentContent) {
|
|
|
|
validPopup = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
content = content->GetParent();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (validPopup) {
|
|
|
|
// Since a panel isn't focusable itself, find the first focusable
|
|
|
|
// content within the popup. If there isn't any focusable content
|
|
|
|
// in the popup, skip this popup and continue iterating through the
|
|
|
|
// frames. We pass the panel itself (currentContent) as the starting
|
|
|
|
// and root content, so that we only find content within the panel.
|
|
|
|
// Note also that we pass false for aForDocumentNavigation since we
|
|
|
|
// want to locate the first content, not the first document.
|
|
|
|
rv = GetNextTabbableContent(aPresShell, currentContent,
|
|
|
|
nullptr, currentContent,
|
|
|
|
true, 1, false, false,
|
|
|
|
aResultContent);
|
|
|
|
if (NS_SUCCEEDED(rv) && *aResultContent) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-22 14:25:38 +03:00
|
|
|
// As of now, 2018/04/12, sequential focus navigation is still
|
|
|
|
// in the obsolete Shadow DOM specification.
|
|
|
|
// http://w3c.github.io/webcomponents/spec/shadow/#sequential-focus-navigation
|
|
|
|
// "if ELEMENT is focusable, a shadow host, or a slot element,
|
|
|
|
// append ELEMENT to NAVIGATION-ORDER."
|
|
|
|
// and later in "For each element ELEMENT in NAVIGATION-ORDER: "
|
|
|
|
// hosts and slots are handled before other elements.
|
|
|
|
if (currentContent && nsDocument::IsShadowDOMEnabled(currentContent) &&
|
|
|
|
IsHostOrSlot(currentContent)) {
|
|
|
|
int32_t tabIndex = HostOrSlotTabIndexValue(currentContent);
|
|
|
|
if (tabIndex >= 0 &&
|
|
|
|
(aIgnoreTabIndex || aCurrentTabIndex == tabIndex)) {
|
|
|
|
nsIContent* contentToFocus =
|
2018-04-28 16:07:06 +03:00
|
|
|
GetNextTabbableContentInScope(currentContent, currentContent,
|
|
|
|
aOriginalStartContent, aForward,
|
2018-04-22 14:25:38 +03:00
|
|
|
aForward ? 1 : 0, aIgnoreTabIndex,
|
2018-04-28 16:07:06 +03:00
|
|
|
aForDocumentNavigation,
|
2018-04-22 14:25:38 +03:00
|
|
|
true /* aSkipOwner */);
|
|
|
|
if (contentToFocus) {
|
|
|
|
NS_ADDREF(*aResultContent = contentToFocus);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// TabIndex not set defaults to 0 for form elements, anchors and other
|
|
|
|
// elements that are normally focusable. Tabindex defaults to -1
|
|
|
|
// for elements that are not normally focusable.
|
|
|
|
// The returned computed tabindex from IsFocusable() is as follows:
|
|
|
|
// < 0 not tabbable at all
|
|
|
|
// == 0 in normal tab order (last after positive tabindexed items)
|
|
|
|
// > 0 can be tabbed to in the order specified by this value
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t tabIndex;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
frame->IsFocusable(&tabIndex, 0);
|
|
|
|
|
2012-07-31 04:43:28 +04:00
|
|
|
LOGCONTENTNAVIGATION("Next Tabbable %s:", frame->GetContent());
|
|
|
|
LOGFOCUSNAVIGATION((" with tabindex: %d expected: %d", tabIndex, aCurrentTabIndex));
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
if (tabIndex >= 0) {
|
|
|
|
NS_ASSERTION(currentContent, "IsFocusable set a tabindex for a frame with no content");
|
2015-07-13 13:07:49 +03:00
|
|
|
if (!aForDocumentNavigation &&
|
|
|
|
currentContent->IsHTMLElement(nsGkAtoms::img) &&
|
2017-12-07 21:13:50 +03:00
|
|
|
currentContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::usemap)) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// This is an image with a map. Image map areas are not traversed by
|
|
|
|
// nsIFrameTraversal so look for the next or previous area element.
|
|
|
|
nsIContent *areaContent =
|
|
|
|
GetNextTabbableMapArea(aForward, aCurrentTabIndex,
|
2017-12-07 21:13:50 +03:00
|
|
|
currentContent->AsElement(), iterStartContent);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (areaContent) {
|
|
|
|
NS_ADDREF(*aResultContent = areaContent);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (aIgnoreTabIndex || aCurrentTabIndex == tabIndex) {
|
|
|
|
// break out if we've wrapped around to the start again.
|
|
|
|
if (aOriginalStartContent && currentContent == aOriginalStartContent) {
|
|
|
|
NS_ADDREF(*aResultContent = currentContent);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2015-07-23 17:04:15 +03:00
|
|
|
// If this is a remote child browser, call NavigateDocument to have
|
|
|
|
// the child process continue the navigation. Return a special error
|
|
|
|
// code to have the caller return early. If the child ends up not
|
|
|
|
// being focusable in some way, the child process will call back
|
|
|
|
// into document navigation again by calling MoveFocus.
|
|
|
|
TabParent* remote = TabParent::GetFrom(currentContent);
|
|
|
|
if (remote) {
|
|
|
|
remote->NavigateByKey(aForward, aForDocumentNavigation);
|
|
|
|
return NS_SUCCESS_DOM_NO_OPERATION;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Next, for document navigation, check if this a non-remote child document.
|
2015-07-13 13:07:49 +03:00
|
|
|
bool checkSubDocument = true;
|
2018-04-28 16:07:06 +03:00
|
|
|
if (aForDocumentNavigation &&
|
|
|
|
TryDocumentNavigation(currentContent, &checkSubDocument,
|
|
|
|
aResultContent)) {
|
|
|
|
return NS_OK;
|
2015-07-13 13:07:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (checkSubDocument) {
|
|
|
|
// found a node with a matching tab index. Check if it is a child
|
|
|
|
// frame. If so, navigate into the child frame instead.
|
2018-04-28 16:07:06 +03:00
|
|
|
if (TryToMoveFocusToSubDocument(currentContent,
|
|
|
|
aOriginalStartContent,
|
|
|
|
aForward, aForDocumentNavigation,
|
|
|
|
aResultContent)) {
|
|
|
|
MOZ_ASSERT(*aResultContent);
|
|
|
|
return NS_OK;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
2015-07-13 13:07:49 +03:00
|
|
|
// otherwise, use this as the next content node to tab to, unless
|
|
|
|
// this was the element we started on. This would happen for
|
|
|
|
// instance on an element with child frames, where frame navigation
|
|
|
|
// could return the original element again. In that case, just skip
|
|
|
|
// it. Also, if the next content node is the root content, then
|
|
|
|
// return it. This latter case would happen only if someone made a
|
|
|
|
// popup focusable.
|
|
|
|
// Also, when going backwards, check to ensure that the focus
|
|
|
|
// wouldn't be redirected. Otherwise, for example, when an input in
|
|
|
|
// a textbox is focused, the enclosing textbox would be found and
|
|
|
|
// the same inner input would be returned again.
|
|
|
|
else if (currentContent == aRootContent ||
|
|
|
|
(currentContent != startContent &&
|
|
|
|
(aForward || !GetRedirectedFocus(currentContent)))) {
|
2018-01-26 18:49:06 +03:00
|
|
|
|
|
|
|
if (nsDocument::IsShadowDOMEnabled(aRootContent)) {
|
|
|
|
// If currentContent is a shadow host in backward
|
|
|
|
// navigation, search in scope owned by currentContent
|
|
|
|
if (!aForward && currentContent->GetShadowRoot()) {
|
|
|
|
nsIContent* contentToFocus =
|
|
|
|
GetNextTabbableContentInScope(currentContent,
|
|
|
|
currentContent,
|
2018-04-28 16:07:06 +03:00
|
|
|
aOriginalStartContent,
|
2018-01-26 18:49:06 +03:00
|
|
|
aForward, aForward ? 1 : 0,
|
|
|
|
aIgnoreTabIndex,
|
2018-04-28 16:07:06 +03:00
|
|
|
aForDocumentNavigation,
|
2018-01-26 18:49:06 +03:00
|
|
|
true /* aSkipOwner */);
|
|
|
|
if (contentToFocus) {
|
|
|
|
NS_ADDREF(*aResultContent = contentToFocus);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-13 13:07:49 +03:00
|
|
|
NS_ADDREF(*aResultContent = currentContent);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (aOriginalStartContent && currentContent == aOriginalStartContent) {
|
|
|
|
// not focusable, so return if we have wrapped around to the original
|
|
|
|
// content. This is necessary in case the original starting content was
|
|
|
|
// not focusable.
|
|
|
|
NS_ADDREF(*aResultContent = currentContent);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Move to the next or previous frame, but ignore continuation frames
|
|
|
|
// since only the first frame should be involved in focusability.
|
|
|
|
// Otherwise, a loop will occur in the following example:
|
|
|
|
// <span tabindex="1">...<a/><a/>...</span>
|
|
|
|
// where the text wraps onto multiple lines. Tabbing from the second
|
|
|
|
// link can find one of the span's continuation frames between the link
|
|
|
|
// and the end of the span, and the span would end up getting focused
|
|
|
|
// again.
|
|
|
|
do {
|
|
|
|
if (aForward)
|
2012-10-15 22:35:50 +04:00
|
|
|
frameTraversal->Next();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
else
|
2012-10-15 22:35:50 +04:00
|
|
|
frameTraversal->Prev();
|
|
|
|
frame = static_cast<nsIFrame*>(frameTraversal->CurrentItem());
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
} while (frame && frame->GetPrevContinuation());
|
|
|
|
}
|
|
|
|
|
|
|
|
// If already at lowest priority tab (0), end search completely.
|
|
|
|
// A bit counterintuitive but true, tabindex order goes 1, 2, ... 32767, 0
|
|
|
|
if (aCurrentTabIndex == (aForward ? 0 : 1)) {
|
|
|
|
// if going backwards, the canvas should be focused once the beginning
|
2015-07-13 13:07:49 +03:00
|
|
|
// has been reached, so get the root element.
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (!aForward) {
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> window = GetCurrentWindow(aRootContent);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
|
2015-07-13 13:07:49 +03:00
|
|
|
|
2017-12-07 21:13:50 +03:00
|
|
|
RefPtr<Element> docRoot =
|
2015-07-13 13:07:49 +03:00
|
|
|
GetRootForFocus(window, aRootContent->GetComposedDoc(), false, true);
|
|
|
|
FocusFirst(docRoot, aResultContent);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// continue looking for next highest priority tabindex
|
|
|
|
aCurrentTabIndex = GetNextTabIndex(aRootContent, aCurrentTabIndex, aForward);
|
2009-11-20 15:09:33 +03:00
|
|
|
startContent = iterStartContent = aRootContent;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2018-04-28 16:07:06 +03:00
|
|
|
bool
|
|
|
|
nsFocusManager::TryDocumentNavigation(nsIContent* aCurrentContent,
|
|
|
|
bool* aCheckSubDocument,
|
|
|
|
nsIContent** aResultContent)
|
|
|
|
{
|
|
|
|
*aCheckSubDocument = true;
|
|
|
|
Element* docRoot = GetRootForChildDocument(aCurrentContent);
|
|
|
|
if (docRoot) {
|
|
|
|
// If GetRootForChildDocument returned something then call
|
|
|
|
// FocusFirst to find the root or first element to focus within
|
|
|
|
// the child document. If this is a frameset though, skip this and
|
|
|
|
// fall through to normal tab navigation to iterate into
|
|
|
|
// the frameset's frames and locate the first focusable frame.
|
|
|
|
if (!docRoot->IsHTMLElement(nsGkAtoms::frameset)) {
|
|
|
|
*aCheckSubDocument = false;
|
|
|
|
Unused << FocusFirst(docRoot, aResultContent);
|
|
|
|
return *aResultContent != nullptr;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Set aCheckSubDocument to false, as this was neither a frame
|
|
|
|
// type element or a child document that was focusable.
|
|
|
|
*aCheckSubDocument = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
nsFocusManager::TryToMoveFocusToSubDocument(nsIContent* aCurrentContent,
|
|
|
|
nsIContent* aOriginalStartContent,
|
|
|
|
bool aForward,
|
|
|
|
bool aForDocumentNavigation,
|
|
|
|
nsIContent** aResultContent)
|
|
|
|
{
|
|
|
|
nsIDocument* doc = aCurrentContent->GetComposedDoc();
|
|
|
|
NS_ASSERTION(doc, "content not in document");
|
|
|
|
nsIDocument* subdoc = doc->GetSubDocumentFor(aCurrentContent);
|
|
|
|
if (subdoc && !subdoc->EventHandlingSuppressed()) {
|
|
|
|
if (aForward) {
|
|
|
|
// when tabbing forward into a frame, return the root
|
|
|
|
// frame so that the canvas becomes focused.
|
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> subframe = subdoc->GetWindow();
|
|
|
|
if (subframe) {
|
|
|
|
*aResultContent = GetRootForFocus(subframe, subdoc, false, true);
|
|
|
|
if (*aResultContent) {
|
|
|
|
NS_ADDREF(*aResultContent);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Element* rootElement = subdoc->GetRootElement();
|
|
|
|
nsIPresShell* subShell = subdoc->GetShell();
|
|
|
|
if (rootElement && subShell) {
|
|
|
|
nsresult rv = GetNextTabbableContent(subShell, rootElement,
|
|
|
|
aOriginalStartContent, rootElement,
|
|
|
|
aForward, (aForward ? 1 : 0),
|
|
|
|
false, aForDocumentNavigation,
|
|
|
|
aResultContent);
|
|
|
|
NS_ENSURE_SUCCESS(rv, false);
|
|
|
|
if (*aResultContent) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsIContent*
|
2011-09-29 10:19:26 +04:00
|
|
|
nsFocusManager::GetNextTabbableMapArea(bool aForward,
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t aCurrentTabIndex,
|
2017-12-07 21:13:50 +03:00
|
|
|
Element* aImageContent,
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsIContent* aStartContent)
|
|
|
|
{
|
|
|
|
nsAutoString useMap;
|
|
|
|
aImageContent->GetAttr(kNameSpaceID_None, nsGkAtoms::usemap, useMap);
|
|
|
|
|
2014-08-06 03:23:02 +04:00
|
|
|
nsCOMPtr<nsIDocument> doc = aImageContent->GetComposedDoc();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (doc) {
|
2011-05-30 15:00:00 +04:00
|
|
|
nsCOMPtr<nsIContent> mapContent = doc->FindImageMap(useMap);
|
|
|
|
if (!mapContent)
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t count = mapContent->GetChildCount();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// First see if the the start content is in this map
|
|
|
|
|
2018-01-23 16:30:18 +03:00
|
|
|
int32_t index = mapContent->ComputeIndexOf(aStartContent);
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t tabIndex;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (index < 0 || (aStartContent->IsFocusable(&tabIndex) &&
|
|
|
|
tabIndex != aCurrentTabIndex)) {
|
|
|
|
// If aStartContent is in this map we must start iterating past it.
|
|
|
|
// We skip the case where aStartContent has tabindex == aStartContent
|
|
|
|
// since the next tab ordered element might be before it
|
|
|
|
// (or after for backwards) in the child list.
|
2012-08-22 19:56:38 +04:00
|
|
|
index = aForward ? -1 : (int32_t)count;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
2018-01-03 15:59:54 +03:00
|
|
|
// GetChildAt_Deprecated will return nullptr if our index < 0 or index >=
|
|
|
|
// count
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsCOMPtr<nsIContent> areaContent;
|
2018-01-03 15:59:54 +03:00
|
|
|
while ((areaContent = mapContent->GetChildAt_Deprecated(aForward ? ++index : --index)) != nullptr) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (areaContent->IsFocusable(&tabIndex) && tabIndex == aCurrentTabIndex) {
|
|
|
|
return areaContent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsFocusManager::GetNextTabIndex(nsIContent* aParent,
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t aCurrentTabIndex,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aForward)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t tabIndex, childTabIndex;
|
2018-01-26 18:48:26 +03:00
|
|
|
FlattenedChildIterator iter(aParent);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
if (aForward) {
|
|
|
|
tabIndex = 0;
|
2018-01-26 18:48:26 +03:00
|
|
|
for (nsIContent* child = iter.GetNextChild();
|
2012-01-25 11:50:07 +04:00
|
|
|
child;
|
2018-01-26 18:48:26 +03:00
|
|
|
child = iter.GetNextChild()) {
|
|
|
|
// Skip child's descendants if child is a shadow host or slot, as they are
|
2018-01-26 18:47:44 +03:00
|
|
|
// in the focus navigation scope owned by child's shadow root
|
2018-01-26 18:48:26 +03:00
|
|
|
if (!(nsDocument::IsShadowDOMEnabled(aParent) && IsHostOrSlot(child))) {
|
2018-01-26 18:47:44 +03:00
|
|
|
childTabIndex = GetNextTabIndex(child, aCurrentTabIndex, aForward);
|
|
|
|
if (childTabIndex > aCurrentTabIndex && childTabIndex != tabIndex) {
|
|
|
|
tabIndex = (tabIndex == 0 || childTabIndex < tabIndex) ? childTabIndex : tabIndex;
|
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoString tabIndexStr;
|
2017-12-07 21:13:50 +03:00
|
|
|
if (child->IsElement()) {
|
|
|
|
child->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::tabindex, tabIndexStr);
|
|
|
|
}
|
2012-07-27 17:59:29 +04:00
|
|
|
nsresult ec;
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t val = tabIndexStr.ToInteger(&ec);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (NS_SUCCEEDED (ec) && val > aCurrentTabIndex && val != tabIndex) {
|
|
|
|
tabIndex = (tabIndex == 0 || val < tabIndex) ? val : tabIndex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else { /* !aForward */
|
|
|
|
tabIndex = 1;
|
2018-01-26 18:48:26 +03:00
|
|
|
for (nsIContent* child = iter.GetNextChild();
|
2012-01-25 11:50:07 +04:00
|
|
|
child;
|
2018-01-26 18:48:26 +03:00
|
|
|
child = iter.GetNextChild()) {
|
|
|
|
// Skip child's descendants if child is a shadow host or slot, as they are
|
2018-01-26 18:47:44 +03:00
|
|
|
// in the focus navigation scope owned by child's shadow root
|
2018-01-26 18:48:26 +03:00
|
|
|
if (!(nsDocument::IsShadowDOMEnabled(aParent) && IsHostOrSlot(child))) {
|
2018-01-26 18:47:44 +03:00
|
|
|
childTabIndex = GetNextTabIndex(child, aCurrentTabIndex, aForward);
|
|
|
|
if ((aCurrentTabIndex == 0 && childTabIndex > tabIndex) ||
|
|
|
|
(childTabIndex < aCurrentTabIndex && childTabIndex > tabIndex)) {
|
|
|
|
tabIndex = childTabIndex;
|
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoString tabIndexStr;
|
2017-12-07 21:13:50 +03:00
|
|
|
if (child->IsElement()) {
|
|
|
|
child->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::tabindex, tabIndexStr);
|
|
|
|
}
|
2012-07-27 17:59:29 +04:00
|
|
|
nsresult ec;
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t val = tabIndexStr.ToInteger(&ec);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (NS_SUCCEEDED (ec)) {
|
|
|
|
if ((aCurrentTabIndex == 0 && val > tabIndex) ||
|
|
|
|
(val < aCurrentTabIndex && val > tabIndex) ) {
|
|
|
|
tabIndex = val;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return tabIndex;
|
|
|
|
}
|
|
|
|
|
2015-07-13 13:07:49 +03:00
|
|
|
nsresult
|
2017-12-07 21:13:50 +03:00
|
|
|
nsFocusManager::FocusFirst(Element* aRootElement, nsIContent** aNextContent)
|
2015-07-13 13:07:49 +03:00
|
|
|
{
|
2017-12-07 21:13:50 +03:00
|
|
|
if (!aRootElement) {
|
2015-07-13 13:07:49 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2017-12-07 21:13:50 +03:00
|
|
|
nsIDocument* doc = aRootElement->GetComposedDoc();
|
2015-07-13 13:07:49 +03:00
|
|
|
if (doc) {
|
2015-07-13 13:07:50 +03:00
|
|
|
if (doc->IsXULDocument()) {
|
|
|
|
// If the redirectdocumentfocus attribute is set, redirect the focus to a
|
|
|
|
// specific element. This is primarily used to retarget the focus to the
|
|
|
|
// urlbar during document navigation.
|
|
|
|
nsAutoString retarget;
|
|
|
|
|
2017-12-07 21:13:50 +03:00
|
|
|
if (aRootElement->GetAttr(kNameSpaceID_None,
|
2015-07-13 13:07:50 +03:00
|
|
|
nsGkAtoms::retargetdocumentfocus, retarget)) {
|
2017-03-25 04:01:19 +03:00
|
|
|
nsCOMPtr<Element> element = doc->GetElementById(retarget);
|
2015-07-13 13:07:50 +03:00
|
|
|
nsCOMPtr<nsIContent> retargetElement =
|
2017-03-25 04:01:19 +03:00
|
|
|
CheckIfFocusable(element, 0);
|
2015-07-13 13:07:50 +03:00
|
|
|
if (retargetElement) {
|
|
|
|
retargetElement.forget(aNextContent);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-13 13:07:49 +03:00
|
|
|
nsCOMPtr<nsIDocShell> docShell = doc->GetDocShell();
|
|
|
|
if (docShell->ItemType() == nsIDocShellTreeItem::typeChrome) {
|
|
|
|
// If the found content is in a chrome shell, navigate forward one
|
|
|
|
// tabbable item so that the first item is focused. Note that we
|
|
|
|
// always go forward and not back here.
|
|
|
|
nsIPresShell* presShell = doc->GetShell();
|
|
|
|
if (presShell) {
|
2017-12-07 21:13:50 +03:00
|
|
|
return GetNextTabbableContent(presShell, aRootElement,
|
|
|
|
nullptr, aRootElement,
|
2015-07-13 13:07:49 +03:00
|
|
|
true, 1, false, false,
|
|
|
|
aNextContent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-07 21:13:50 +03:00
|
|
|
NS_ADDREF(*aNextContent = aRootElement);
|
2015-07-13 13:07:49 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2017-12-07 21:13:50 +03:00
|
|
|
Element*
|
2016-01-30 20:05:36 +03:00
|
|
|
nsFocusManager::GetRootForFocus(nsPIDOMWindowOuter* aWindow,
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsIDocument* aDocument,
|
2015-07-13 13:07:49 +03:00
|
|
|
bool aForDocumentNavigation,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aCheckVisibility)
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
{
|
2015-07-13 13:07:49 +03:00
|
|
|
if (!aForDocumentNavigation) {
|
2013-02-13 02:02:51 +04:00
|
|
|
nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell();
|
2014-01-20 11:58:26 +04:00
|
|
|
if (docShell->ItemType() == nsIDocShellTreeItem::typeChrome) {
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2014-01-20 11:58:26 +04:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (aCheckVisibility && !IsWindowVisible(aWindow))
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2015-07-13 13:07:49 +03:00
|
|
|
// If the body is contenteditable, use the editor's root element rather than
|
|
|
|
// the actual root element.
|
2017-12-07 21:13:50 +03:00
|
|
|
RefPtr<Element> rootElement =
|
2015-07-13 13:07:49 +03:00
|
|
|
nsLayoutUtils::GetEditableRootContentByContentEditable(aDocument);
|
|
|
|
if (!rootElement || !rootElement->GetPrimaryFrame()) {
|
|
|
|
rootElement = aDocument->GetRootElement();
|
|
|
|
if (!rootElement) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2012-01-25 11:50:07 +04:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2012-01-25 11:50:07 +04:00
|
|
|
if (aCheckVisibility && !rootElement->GetPrimaryFrame()) {
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2012-01-25 11:50:07 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Finally, check if this is a frameset
|
|
|
|
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(aDocument);
|
2015-07-13 13:07:49 +03:00
|
|
|
if (htmlDoc) {
|
2017-12-07 21:13:50 +03:00
|
|
|
Element* htmlChild = aDocument->GetHtmlChildElement(nsGkAtoms::frameset);
|
2015-07-13 13:07:49 +03:00
|
|
|
if (htmlChild) {
|
|
|
|
// In document navigation mode, return the frameset so that navigation
|
|
|
|
// descends into the child frames.
|
|
|
|
return aForDocumentNavigation ? htmlChild : nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-13 13:07:49 +03:00
|
|
|
return rootElement;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
2017-12-07 21:13:50 +03:00
|
|
|
Element*
|
2015-07-13 13:07:49 +03:00
|
|
|
nsFocusManager::GetRootForChildDocument(nsIContent* aContent)
|
|
|
|
{
|
|
|
|
// Check for elements that represent child documents, that is, browsers,
|
|
|
|
// editors or frames from a frameset. We don't include iframes since we
|
|
|
|
// consider them to be an integral part of the same window or page.
|
|
|
|
if (!aContent ||
|
|
|
|
!(aContent->IsXULElement(nsGkAtoms::browser) ||
|
|
|
|
aContent->IsXULElement(nsGkAtoms::editor) ||
|
|
|
|
aContent->IsHTMLElement(nsGkAtoms::frame))) {
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2012-02-24 01:02:33 +04:00
|
|
|
}
|
|
|
|
|
2015-07-13 13:07:49 +03:00
|
|
|
nsIDocument* doc = aContent->GetComposedDoc();
|
|
|
|
if (!doc) {
|
|
|
|
return nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
2012-02-24 01:02:33 +04:00
|
|
|
|
2015-07-13 13:07:49 +03:00
|
|
|
nsIDocument* subdoc = doc->GetSubDocumentFor(aContent);
|
|
|
|
if (!subdoc || subdoc->EventHandlingSuppressed()) {
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2015-07-13 13:07:49 +03:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> window = subdoc->GetWindow();
|
2015-07-13 13:07:49 +03:00
|
|
|
return GetRootForFocus(window, subdoc, true, true);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2016-01-30 20:05:36 +03:00
|
|
|
nsFocusManager::GetFocusInSelection(nsPIDOMWindowOuter* aWindow,
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsIContent* aStartSelection,
|
|
|
|
nsIContent* aEndSelection,
|
|
|
|
nsIContent** aFocusedContent)
|
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
*aFocusedContent = nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
nsCOMPtr<nsIContent> testContent = aStartSelection;
|
|
|
|
nsCOMPtr<nsIContent> nextTestContent = aEndSelection;
|
|
|
|
|
2018-04-26 22:28:30 +03:00
|
|
|
nsCOMPtr<nsIContent> currentFocus = aWindow->GetFocusedElement();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
// We now have the correct start node in selectionContent!
|
|
|
|
// Search for focusable elements, starting with selectionContent
|
|
|
|
|
|
|
|
// Method #1: Keep going up while we look - an ancestor might be focusable
|
|
|
|
// We could end the loop earlier, such as when we're no longer
|
2009-12-25 00:20:06 +03:00
|
|
|
// in the same frame, by comparing selectionContent->GetPrimaryFrame()
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
// with a variable holding the starting selectionContent
|
|
|
|
while (testContent) {
|
|
|
|
// Keep testing while selectionContent is equal to something,
|
|
|
|
// eventually we'll run out of ancestors
|
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
if (testContent == currentFocus ||
|
|
|
|
testContent->IsLink(getter_AddRefs(uri))) {
|
2015-03-31 17:03:49 +03:00
|
|
|
testContent.forget(aFocusedContent);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the parent
|
|
|
|
testContent = testContent->GetParent();
|
|
|
|
|
|
|
|
if (!testContent) {
|
|
|
|
// We run this loop again, checking the ancestor chain of the selection's end point
|
|
|
|
testContent = nextTestContent;
|
2012-07-30 18:20:58 +04:00
|
|
|
nextTestContent = nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// We couldn't find an anchor that was an ancestor of the selection start
|
|
|
|
// Method #2: look for anchor in selection's primary range (depth first search)
|
|
|
|
|
2018-01-30 07:10:51 +03:00
|
|
|
nsCOMPtr<nsIContent> selectionNode = aStartSelection;
|
|
|
|
nsCOMPtr<nsIContent> endSelectionNode = aEndSelection;
|
|
|
|
nsCOMPtr<nsIContent> testNode;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
do {
|
2018-01-30 07:10:51 +03:00
|
|
|
testContent = selectionNode;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
// We're looking for any focusable link that could be part of the
|
|
|
|
// main document's selection.
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
|
|
if (testContent == currentFocus ||
|
|
|
|
testContent->IsLink(getter_AddRefs(uri))) {
|
2015-03-31 17:03:49 +03:00
|
|
|
testContent.forget(aFocusedContent);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-01-30 07:10:51 +03:00
|
|
|
nsIContent* testNode = selectionNode->GetFirstChild();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (testNode) {
|
|
|
|
selectionNode = testNode;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (selectionNode == endSelectionNode)
|
|
|
|
break;
|
2018-01-30 07:10:51 +03:00
|
|
|
testNode = selectionNode->GetNextSibling();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (testNode) {
|
|
|
|
selectionNode = testNode;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
2018-01-30 07:10:51 +03:00
|
|
|
// GetParent is OK here, instead of GetParentNode, because the only case
|
|
|
|
// where the latter returns something different from the former is when
|
|
|
|
// GetParentNode is the document. But in that case we would simply get
|
|
|
|
// null for selectionNode when setting it to testNode->GetNextSibling()
|
|
|
|
// (because a document has no next sibling). And then the next iteration
|
|
|
|
// of this loop would get null for GetParentNode anyway, and break out of
|
|
|
|
// all the loops.
|
|
|
|
testNode = selectionNode->GetParent();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (!testNode || testNode == endSelectionNode) {
|
2012-07-30 18:20:58 +04:00
|
|
|
selectionNode = nullptr;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
break;
|
|
|
|
}
|
2018-01-30 07:10:51 +03:00
|
|
|
selectionNode = testNode->GetNextSibling();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (selectionNode)
|
|
|
|
break;
|
|
|
|
selectionNode = testNode;
|
2011-10-17 18:59:28 +04:00
|
|
|
} while (true);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
|
|
|
while (selectionNode && selectionNode != endSelectionNode);
|
|
|
|
}
|
|
|
|
|
2016-04-26 03:23:21 +03:00
|
|
|
class PointerUnlocker : public Runnable
|
2013-03-24 14:32:44 +04:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
PointerUnlocker()
|
2017-06-12 22:34:10 +03:00
|
|
|
: mozilla::Runnable("PointerUnlocker")
|
2013-03-24 14:32:44 +04:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(!PointerUnlocker::sActiveUnlocker);
|
|
|
|
PointerUnlocker::sActiveUnlocker = this;
|
|
|
|
}
|
|
|
|
|
|
|
|
~PointerUnlocker()
|
|
|
|
{
|
|
|
|
if (PointerUnlocker::sActiveUnlocker == this) {
|
|
|
|
PointerUnlocker::sActiveUnlocker = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-08 05:18:10 +03:00
|
|
|
NS_IMETHOD Run() override
|
2013-03-24 14:32:44 +04:00
|
|
|
{
|
|
|
|
if (PointerUnlocker::sActiveUnlocker == this) {
|
|
|
|
PointerUnlocker::sActiveUnlocker = nullptr;
|
|
|
|
}
|
|
|
|
NS_ENSURE_STATE(nsFocusManager::GetFocusManager());
|
2016-01-30 20:05:36 +03:00
|
|
|
nsPIDOMWindowOuter* focused =
|
2013-03-24 14:32:44 +04:00
|
|
|
nsFocusManager::GetFocusManager()->GetFocusedWindow();
|
|
|
|
nsCOMPtr<nsIDocument> pointerLockedDoc =
|
2014-04-01 08:09:23 +04:00
|
|
|
do_QueryReferent(EventStateManager::sPointerLockedDoc);
|
2013-03-24 14:32:44 +04:00
|
|
|
if (pointerLockedDoc &&
|
|
|
|
!nsContentUtils::IsInPointerLockContext(focused)) {
|
|
|
|
nsIDocument::UnlockPointer();
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PointerUnlocker* sActiveUnlocker;
|
|
|
|
};
|
|
|
|
|
|
|
|
PointerUnlocker*
|
|
|
|
PointerUnlocker::sActiveUnlocker = nullptr;
|
|
|
|
|
|
|
|
void
|
2016-01-30 20:05:36 +03:00
|
|
|
nsFocusManager::SetFocusedWindowInternal(nsPIDOMWindowOuter* aWindow)
|
2013-03-24 14:32:44 +04:00
|
|
|
{
|
|
|
|
if (!PointerUnlocker::sActiveUnlocker &&
|
|
|
|
nsContentUtils::IsInPointerLockContext(mFocusedWindow) &&
|
|
|
|
!nsContentUtils::IsInPointerLockContext(aWindow)) {
|
|
|
|
nsCOMPtr<nsIRunnable> runnable = new PointerUnlocker();
|
|
|
|
NS_DispatchToCurrentThread(runnable);
|
|
|
|
}
|
2017-03-01 06:12:27 +03:00
|
|
|
|
|
|
|
// Update the last focus time on any affected documents
|
|
|
|
if (aWindow && aWindow != mFocusedWindow) {
|
|
|
|
const TimeStamp now(TimeStamp::Now());
|
|
|
|
for (nsIDocument* doc = aWindow->GetExtantDoc();
|
|
|
|
doc;
|
|
|
|
doc = doc->GetParentDocument()) {
|
|
|
|
doc->SetLastFocusTime(now);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-24 14:32:44 +04:00
|
|
|
mFocusedWindow = aWindow;
|
|
|
|
}
|
|
|
|
|
2013-11-24 23:35:34 +04:00
|
|
|
void
|
|
|
|
nsFocusManager::MarkUncollectableForCCGeneration(uint32_t aGeneration)
|
|
|
|
{
|
|
|
|
if (!sInstance) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sInstance->mActiveWindow) {
|
|
|
|
sInstance->mActiveWindow->
|
|
|
|
MarkUncollectableForCCGeneration(aGeneration);
|
|
|
|
}
|
|
|
|
if (sInstance->mFocusedWindow) {
|
|
|
|
sInstance->mFocusedWindow->
|
|
|
|
MarkUncollectableForCCGeneration(aGeneration);
|
|
|
|
}
|
|
|
|
if (sInstance->mWindowBeingLowered) {
|
|
|
|
sInstance->mWindowBeingLowered->
|
|
|
|
MarkUncollectableForCCGeneration(aGeneration);
|
|
|
|
}
|
2018-04-26 22:28:31 +03:00
|
|
|
if (sInstance->mFocusedElement) {
|
|
|
|
sInstance->mFocusedElement->OwnerDoc()->
|
2013-11-24 23:35:34 +04:00
|
|
|
MarkUncollectableForCCGeneration(aGeneration);
|
|
|
|
}
|
|
|
|
if (sInstance->mFirstBlurEvent) {
|
|
|
|
sInstance->mFirstBlurEvent->OwnerDoc()->
|
|
|
|
MarkUncollectableForCCGeneration(aGeneration);
|
|
|
|
}
|
|
|
|
if (sInstance->mFirstFocusEvent) {
|
|
|
|
sInstance->mFirstFocusEvent->OwnerDoc()->
|
|
|
|
MarkUncollectableForCCGeneration(aGeneration);
|
|
|
|
}
|
2014-06-18 10:13:00 +04:00
|
|
|
if (sInstance->mMouseButtonEventHandlingDocument) {
|
|
|
|
sInstance->mMouseButtonEventHandlingDocument->
|
2013-11-24 23:35:34 +04:00
|
|
|
MarkUncollectableForCCGeneration(aGeneration);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-23 14:34:06 +03:00
|
|
|
bool
|
|
|
|
nsFocusManager::CanSkipFocus(nsIContent* aContent)
|
|
|
|
{
|
2017-05-23 14:37:15 +03:00
|
|
|
if (!aContent ||
|
|
|
|
nsContentUtils::IsChromeDoc(aContent->OwnerDoc())) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-04-26 22:28:31 +03:00
|
|
|
if (mFocusedElement == aContent) {
|
2017-05-23 14:37:15 +03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIDocShell* ds = aContent->OwnerDoc()->GetDocShell();
|
|
|
|
if (!ds) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> root;
|
|
|
|
ds->GetRootTreeItem(getter_AddRefs(root));
|
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> newRootWindow =
|
|
|
|
root ? root->GetWindow() : nullptr;
|
|
|
|
if (mActiveWindow != newRootWindow) {
|
|
|
|
nsPIDOMWindowOuter* outerWindow = aContent->OwnerDoc()->GetWindow();
|
2018-04-26 22:28:30 +03:00
|
|
|
if (outerWindow && outerWindow->GetFocusedElement() == aContent) {
|
2017-05-23 14:37:15 +03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2017-05-23 14:34:06 +03:00
|
|
|
}
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsresult
|
|
|
|
NS_NewFocusManager(nsIFocusManager** aResult)
|
|
|
|
{
|
|
|
|
NS_IF_ADDREF(*aResult = nsFocusManager::GetFocusManager());
|
|
|
|
return NS_OK;
|
|
|
|
}
|