Bug 1322939 - Implement inert subtrees. r=smaug draft
authorTim Nguyen <ntim.bugs@gmail.com>
Sat, 14 Jan 2017 02:20:32 +0000
changeset 460912 93a1a5f4a9c19531d45d0cc20f76746cb8cd2b77
parent 460907 584a34f80d9d3ff741dd6b98b5a3bb5584e76dd0
child 542171 df5490bb1414e036bad256b779b4947455bcb2a2
push id41526
push userbmo:ntim.bugs@gmail.com
push dateSat, 14 Jan 2017 02:20:57 +0000
reviewerssmaug
bugs1322939
milestone53.0a1
Bug 1322939 - Implement inert subtrees. r=smaug MozReview-Commit-ID: 8qREtIZSGC9
dom/base/Element.cpp
dom/base/Element.h
dom/events/EventStates.h
layout/style/nsCSSPseudoClassList.h
layout/style/res/ua.css
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -190,21 +190,38 @@ Element::QueryInterface(REFNSIID aIID, v
     return NS_OK;
   }
 
   // Give the binding manager a chance to get an interface for this element.
   return OwnerDoc()->BindingManager()->GetBindingImplementation(this, aIID,
                                                                 aInstancePtr);
 }
 
+bool
+Element::IsInert() const
+{
+  nsDocument* doc = static_cast<nsDocument*>(GetUncomposedDoc());
+  if (doc->GetPendingDialogStack().IsEmpty()) {
+    return false;
+  }
+  Element* topMostElement = doc->PendingDialogStackTop();
+  return this != topMostElement &&
+         !nsContentUtils::ContentIsDescendantOf(this, topMostElement);
+}
+
 EventStates
 Element::IntrinsicState() const
 {
-  return IsEditable() ? NS_EVENT_STATE_MOZ_READWRITE :
-                        NS_EVENT_STATE_MOZ_READONLY;
+  EventStates state = IsEditable() && !IsInert()
+                      ? NS_EVENT_STATE_MOZ_READWRITE
+                      : NS_EVENT_STATE_MOZ_READONLY;
+  if (IsInert()) {
+    state |= NS_EVENT_STATE_INERT;
+  }
+  return state;
 }
 
 void
 Element::NotifyStateChange(EventStates aStates)
 {
   nsIDocument* doc = GetComposedDoc();
   if (doc) {
     nsAutoScriptBlocker scriptBlocker;
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -174,16 +174,21 @@ public:
   }
 
 #endif // MOZILLA_INTERNAL_API
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ELEMENT_IID)
 
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
 
+  /*
+   * Check if element is inert
+   */
+  bool IsInert() const;
+
   /**
    * Method to get the full state of this element.  See mozilla/EventStates.h
    * for the possible bits that could be set here.
    */
   EventStates State() const
   {
     // mState is maintained by having whoever might have changed it
     // call UpdateState() or one of the other mState mutators.
--- a/dom/events/EventStates.h
+++ b/dom/events/EventStates.h
@@ -269,18 +269,18 @@ private:
 // Content has focus and should show a ring.
 #define NS_EVENT_STATE_FOCUSRING     NS_DEFINE_EVENT_STATE_MACRO(30)
 // Content is a submit control and the form isn't valid.
 #define NS_EVENT_STATE_MOZ_SUBMITINVALID NS_DEFINE_EVENT_STATE_MACRO(31)
 // UI friendly version of :invalid pseudo-class.
 #define NS_EVENT_STATE_MOZ_UI_INVALID NS_DEFINE_EVENT_STATE_MACRO(32)
 // UI friendly version of :valid pseudo-class.
 #define NS_EVENT_STATE_MOZ_UI_VALID NS_DEFINE_EVENT_STATE_MACRO(33)
-// This bit is currently free.
-// #define NS_EVENT_STATE_?????????? NS_DEFINE_EVENT_STATE_MACRO(34)
+// Inert subtrees
+#define NS_EVENT_STATE_INERT NS_DEFINE_EVENT_STATE_MACRO(34)
 // Handler for click to play plugin
 #define NS_EVENT_STATE_TYPE_CLICK_TO_PLAY NS_DEFINE_EVENT_STATE_MACRO(35)
 // Content is in the optimum region.
 #define NS_EVENT_STATE_OPTIMUM NS_DEFINE_EVENT_STATE_MACRO(36)
 // Content is in the suboptimal region.
 #define NS_EVENT_STATE_SUB_OPTIMUM NS_DEFINE_EVENT_STATE_MACRO(37)
 // Content is in the sub-suboptimal region.
 #define NS_EVENT_STATE_SUB_SUB_OPTIMUM NS_DEFINE_EVENT_STATE_MACRO(38)
--- a/layout/style/nsCSSPseudoClassList.h
+++ b/layout/style/nsCSSPseudoClassList.h
@@ -160,16 +160,20 @@ CSS_STATE_PSEUDO_CLASS(enabled, ":enable
 CSS_STATE_PSEUDO_CLASS(focus, ":focus", 0, "", NS_EVENT_STATE_FOCUS)
 CSS_STATE_PSEUDO_CLASS(focusWithin, ":focus-within", 0, "", NS_EVENT_STATE_FOCUS_WITHIN)
 CSS_STATE_PSEUDO_CLASS(hover, ":hover", 0, "", NS_EVENT_STATE_HOVER)
 CSS_STATE_PSEUDO_CLASS(mozDragOver, ":-moz-drag-over", 0, "", NS_EVENT_STATE_DRAGOVER)
 CSS_STATE_PSEUDO_CLASS(target, ":target", 0, "", NS_EVENT_STATE_URLTARGET)
 CSS_STATE_PSEUDO_CLASS(indeterminate, ":indeterminate", 0, "",
                        NS_EVENT_STATE_INDETERMINATE)
 
+CSS_STATE_PSEUDO_CLASS(mozInert, ":-moz-inert",
+                       CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME, "",
+                       NS_EVENT_STATE_INERT)
+
 CSS_STATE_PSEUDO_CLASS(mozDevtoolsHighlighted, ":-moz-devtools-highlighted", 0, "",
                        NS_EVENT_STATE_DEVTOOLS_HIGHLIGHTED)
 CSS_STATE_PSEUDO_CLASS(mozStyleeditorTransitioning, ":-moz-styleeditor-transitioning", 0, "",
                        NS_EVENT_STATE_STYLEEDITOR_TRANSITIONING)
 
 // Matches the element which is being displayed full-screen, and
 // any containing frames.
 CSS_STATE_PSEUDO_CLASS(fullscreen, ":fullscreen",
--- a/layout/style/res/ua.css
+++ b/layout/style/res/ua.css
@@ -125,16 +125,25 @@
   cursor: pointer;
 }
 
 *|*:any-link:-moz-focusring {
   /* Don't specify the outline-color, we should always use initial value. */
   outline: 1px dotted;
 }
 
+/* Inert subtrees */
+*|*:-moz-inert {
+  pointer-events: none;
+  -moz-user-focus: none;
+  -moz-user-input: disabled;
+  -moz-user-modify: read-only;
+  -moz-user-select: none;
+}
+
 /* Miscellaneous */
 
 *|*::-moz-anonymous-block, *|*::-moz-cell-content {
   display: block !important;
   position: static !important;
   unicode-bidi: inherit;
   text-overflow: inherit;
   overflow-clip-box: inherit;