gfx/layers/apz/util/ActiveElementManager.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "ActiveElementManager.h"
     7 #include "mozilla/EventStates.h"
     8 #include "mozilla/Preferences.h"
     9 #include "mozilla/Services.h"
    10 #include "inIDOMUtils.h"
    11 #include "nsIDOMDocument.h"
    12 #include "nsIDOMElement.h"
    13 #include "nsIDOMEventTarget.h"
    14 #include "base/message_loop.h"
    15 #include "base/task.h"
    17 namespace mozilla {
    18 namespace layers {
    20 static int32_t sActivationDelayMs = 100;
    21 static bool sActivationDelayMsSet = false;
    23 ActiveElementManager::ActiveElementManager()
    24   : mDomUtils(services::GetInDOMUtils()),
    25     mCanBePan(false),
    26     mCanBePanSet(false),
    27     mSetActiveTask(nullptr)
    28 {
    29   if (!sActivationDelayMsSet) {
    30     Preferences::AddIntVarCache(&sActivationDelayMs,
    31                                 "ui.touch_activation.delay_ms",
    32                                 sActivationDelayMs);
    33     sActivationDelayMsSet = true;
    34   }
    35 }
    37 ActiveElementManager::~ActiveElementManager() {}
    39 void
    40 ActiveElementManager::SetTargetElement(nsIDOMEventTarget* aTarget)
    41 {
    42   if (mTarget) {
    43     // Multiple fingers on screen (since HandleTouchEnd clears mTarget).
    44     CancelTask();
    45     ResetActive();
    46     mTarget = nullptr;
    47     return;
    48   }
    50   mTarget = do_QueryInterface(aTarget);
    51   TriggerElementActivation();
    52 }
    54 void
    55 ActiveElementManager::HandleTouchStart(bool aCanBePan)
    56 {
    57   mCanBePan = aCanBePan;
    58   mCanBePanSet = true;
    59   TriggerElementActivation();
    60 }
    62 void
    63 ActiveElementManager::TriggerElementActivation()
    64 {
    65   // Both HandleTouchStart() and SetTargetElement() call this. They can be
    66   // called in either order. One will set mCanBePanSet, and the other, mTarget.
    67   // We want to actually trigger the activation once both are set.
    68   if (!(mTarget && mCanBePanSet)) {
    69     return;
    70   }
    72   // If the touch cannot be a pan, make mTarget :active right away.
    73   // Otherwise, wait a bit to see if the user will pan or not.
    74   if (!mCanBePan) {
    75     SetActive(mTarget);
    76   } else {
    77     mSetActiveTask = NewRunnableMethod(
    78         this, &ActiveElementManager::SetActiveTask, mTarget);
    79     MessageLoop::current()->PostDelayedTask(
    80         FROM_HERE, mSetActiveTask, sActivationDelayMs);
    81   }
    82 }
    84 void
    85 ActiveElementManager::HandlePanStart()
    86 {
    87   // The user started to pan, so we don't want mTarget to be :active.
    88   // Make it not :active, and clear any pending task to make it :active.
    89   CancelTask();
    90   ResetActive();
    91 }
    93 void
    94 ActiveElementManager::HandleTouchEnd(bool aWasClick)
    95 {
    96   // If the touch was a click, make mTarget :active right away.
    97   // nsEventStateManager will reset the active element when processing
    98   // the mouse-down event generated by the click.
    99   CancelTask();
   100   if (aWasClick) {
   101     SetActive(mTarget);
   102   }
   104   // Clear mTarget for next touch.
   105   mTarget = nullptr;
   106 }
   108 void
   109 ActiveElementManager::SetActive(nsIDOMElement* aTarget)
   110 {
   111   if (mDomUtils) {
   112     mDomUtils->SetContentState(aTarget, NS_EVENT_STATE_ACTIVE.GetInternalValue());;
   113   }
   114 }
   116 void
   117 ActiveElementManager::ResetActive()
   118 {
   119   // Clear the :active flag from mTarget by setting it on the document root.
   120   if (mTarget) {
   121     nsCOMPtr<nsIDOMDocument> doc;
   122     mTarget->GetOwnerDocument(getter_AddRefs(doc));
   123     if (doc) {
   124       nsCOMPtr<nsIDOMElement> root;
   125       doc->GetDocumentElement(getter_AddRefs(root));
   126       if (root) {
   127         SetActive(root);
   128       }
   129     }
   130   }
   131 }
   133 void
   134 ActiveElementManager::SetActiveTask(nsIDOMElement* aTarget)
   135 {
   136   // This gets called from mSetActiveTask's Run() method. The message loop
   137   // deletes the task right after running it, so we need to null out
   138   // mSetActiveTask to make sure we're not left with a dangling pointer.
   139   mSetActiveTask = nullptr;
   140   SetActive(aTarget);
   141 }
   143 void
   144 ActiveElementManager::CancelTask()
   145 {
   146   if (mSetActiveTask) {
   147     mSetActiveTask->Cancel();
   148     mSetActiveTask = nullptr;
   149   }
   150 }
   152 }
   153 }

mercurial