Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/gfx/layers/apz/src/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 8 kB image not shown  

Quelle  FocusState.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */


#include "FocusState.h"

#include "mozilla/Logging.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/layers/APZThreadUtils.h"

static mozilla::LazyLogModule sApzFstLog("apz.focusstate");
#define FS_LOG(...) MOZ_LOG(sApzFstLog, LogLevel::Debug, (__VA_ARGS__))

namespace mozilla {
namespace layers {

FocusState::FocusState()
    : mMutex("FocusStateMutex"),
      mLastAPZProcessedEvent(1),
      mLastContentProcessedEvent(0),
      mFocusHasKeyEventListeners(false),
      mReceivedUpdate(false),
      mFocusLayersId{0},
      mFocusHorizontalTarget(ScrollableLayerGuid::NULL_SCROLL_ID),
      mFocusVerticalTarget(ScrollableLayerGuid::NULL_SCROLL_ID) {}

uint64_t FocusState::LastAPZProcessedEvent() const {
  APZThreadUtils::AssertOnControllerThread();
  MutexAutoLock lock(mMutex);

  return mLastAPZProcessedEvent;
}

bool FocusState::IsCurrent(const MutexAutoLock& aProofOfLock) const {
  FS_LOG("Checking IsCurrent() with cseq=%" PRIu64 ", aseq=%" PRIu64 "\n",
         mLastContentProcessedEvent, mLastAPZProcessedEvent);
  MOZ_ASSERT(mLastContentProcessedEvent <= mLastAPZProcessedEvent);
  return mLastContentProcessedEvent == mLastAPZProcessedEvent;
}

void FocusState::ReceiveFocusChangingEvent() {
  APZThreadUtils::AssertOnControllerThread();
  MutexAutoLock lock(mMutex);

  if (!mReceivedUpdate) {
    // In the initial state don't advance mLastAPZProcessedEvent because we
    // might blow away the information that we're in a freshly-restarted GPU
    // process. This information (i.e. that mLastAPZProcessedEvent == 1) needs
    // to be preserved until the first call to Update() which will then advance
    // mLastAPZProcessedEvent to match the content-side sequence number.
    return;
  }
  mLastAPZProcessedEvent += 1;
  FS_LOG("Focus changing event incremented aseq to %" PRIu64 ", (%p)\n",
         mLastAPZProcessedEvent, this);
}

void FocusState::Update(LayersId aRootLayerTreeId,
                        LayersId aOriginatingLayersId,
                        const FocusTarget& aState) {
  // This runs on the updater thread, it's not worth passing around extra raw
  // pointers just to assert it.

  MutexAutoLock lock(mMutex);

  FS_LOG("Update with rlt=%" PRIu64 ", olt=%" PRIu64 ", ft=(%s, %" PRIu64 ")\n",
         aRootLayerTreeId.mId, aOriginatingLayersId.mId, aState.Type(),
         aState.mSequenceNumber);
  mReceivedUpdate = true;

  // Update the focus tree with the latest target
  mFocusTree[aOriginatingLayersId] = aState;

  // Reset our internal state so we can recalculate it
  mFocusHasKeyEventListeners = false;
  mFocusLayersId = aRootLayerTreeId;
  mFocusHorizontalTarget = ScrollableLayerGuid::NULL_SCROLL_ID;
  mFocusVerticalTarget = ScrollableLayerGuid::NULL_SCROLL_ID;

  // To update the focus state for the entire APZCTreeManager, we need
  // to traverse the focus tree to find the current leaf which is the global
  // focus target we can use for async keyboard scrolling
  while (true) {
    auto currentNode = mFocusTree.find(mFocusLayersId);
    if (currentNode == mFocusTree.end()) {
      FS_LOG("Setting target to nil (cannot find lt=%" PRIu64 ")\n",
             mFocusLayersId.mId);
      return;
    }

    const FocusTarget& target = currentNode->second;

    // Accumulate event listener flags on the path to the focus target
    mFocusHasKeyEventListeners |= target.mFocusHasKeyEventListeners;

    // Match on the data stored in mData
    // The match functions return true or false depending on whether the
    // enclosing method, FocusState::Update, should return or continue to the
    // next iteration of the while loop, respectively.
    struct FocusTargetDataMatcher {
      FocusState& mFocusState;
      const uint64_t mSequenceNumber;

      bool operator()(const FocusTarget::NoFocusTarget& aNoFocusTarget) {
        FS_LOG("Setting target to nil (reached a nil target) with seq=%" PRIu64
               ", (%p)\n",
               mSequenceNumber, &mFocusState);

        // Mark what sequence number this target has for debugging purposes so
        // we can always accurately report on whether we are stale or not
        mFocusState.mLastContentProcessedEvent = mSequenceNumber;

        // If this focus state was just created and content has experienced more
        // events then us, then assume we were recreated and sync focus sequence
        // numbers.
        if (mFocusState.mLastAPZProcessedEvent == 1 &&
            mFocusState.mLastContentProcessedEvent >
                mFocusState.mLastAPZProcessedEvent) {
          mFocusState.mLastAPZProcessedEvent =
              mFocusState.mLastContentProcessedEvent;
        }
        return true;
      }

      bool operator()(const LayersId& aRefLayerId) {
        // Guard against infinite loops
        MOZ_ASSERT(mFocusState.mFocusLayersId != aRefLayerId);
        if (mFocusState.mFocusLayersId == aRefLayerId) {
          FS_LOG(
              "Setting target to nil (bailing out of infinite loop, lt=%" PRIu64
              ")\n",
              mFocusState.mFocusLayersId.mId);
          return true;
        }

        FS_LOG("Looking for target in lt=%" PRIu64 "\n", aRefLayerId.mId);

        // The focus target is in a child layer tree
        mFocusState.mFocusLayersId = aRefLayerId;
        return false;
      }

      bool operator()(const FocusTarget::ScrollTargets& aScrollTargets) {
        FS_LOG("Setting target to h=%" PRIu64 ", v=%" PRIu64
               ", and seq=%" PRIu64 "(%p)\n",
               aScrollTargets.mHorizontal, aScrollTargets.mVertical,
               mSequenceNumber, &mFocusState);

        // This is the global focus target
        mFocusState.mFocusHorizontalTarget = aScrollTargets.mHorizontal;
        mFocusState.mFocusVerticalTarget = aScrollTargets.mVertical;

        // Mark what sequence number this target has so we can determine whether
        // it is stale or not
        mFocusState.mLastContentProcessedEvent = mSequenceNumber;

        // If this focus state was just created and content has experienced more
        // events then us, then assume we were recreated and sync focus sequence
        // numbers.
        if (mFocusState.mLastAPZProcessedEvent == 1 &&
            mFocusState.mLastContentProcessedEvent >
                mFocusState.mLastAPZProcessedEvent) {
          mFocusState.mLastAPZProcessedEvent =
              mFocusState.mLastContentProcessedEvent;
        }
        return true;
      }
    };  // struct FocusTargetDataMatcher

    if (target.mData.match(
            FocusTargetDataMatcher{*this, target.mSequenceNumber})) {
      return;
    }
  }
}

void FocusState::RemoveFocusTarget(LayersId aLayersId) {
  // This runs on the updater thread, it's not worth passing around extra raw
  // pointers just to assert it.
  MutexAutoLock lock(mMutex);

  mFocusTree.erase(aLayersId);
}

Maybe<ScrollableLayerGuid> FocusState::GetHorizontalTarget() const {
  APZThreadUtils::AssertOnControllerThread();
  MutexAutoLock lock(mMutex);

  // There is not a scrollable layer to async scroll if
  //   1. We aren't current
  //   2. There are event listeners that could change the focus
  //   3. The target has not been layerized
  if (!IsCurrent(lock) || mFocusHasKeyEventListeners ||
      mFocusHorizontalTarget == ScrollableLayerGuid::NULL_SCROLL_ID) {
    return Nothing();
  }
  return Some(ScrollableLayerGuid(mFocusLayersId, 0, mFocusHorizontalTarget));
}

Maybe<ScrollableLayerGuid> FocusState::GetVerticalTarget() const {
  APZThreadUtils::AssertOnControllerThread();
  MutexAutoLock lock(mMutex);

  // There is not a scrollable layer to async scroll if:
  //   1. We aren't current
  //   2. There are event listeners that could change the focus
  //   3. The target has not been layerized
  if (!IsCurrent(lock) || mFocusHasKeyEventListeners ||
      mFocusVerticalTarget == ScrollableLayerGuid::NULL_SCROLL_ID) {
    return Nothing();
  }
  return Some(ScrollableLayerGuid(mFocusLayersId, 0, mFocusVerticalTarget));
}

bool FocusState::CanIgnoreKeyboardShortcutMisses() const {
  APZThreadUtils::AssertOnControllerThread();
  MutexAutoLock lock(mMutex);

  return IsCurrent(lock) && !mFocusHasKeyEventListeners;
}

void FocusState::Reset() {
  MutexAutoLock lock(mMutex);

  mLastAPZProcessedEvent = 1;
  mLastContentProcessedEvent = 0;
  mFocusHasKeyEventListeners = false;
  mReceivedUpdate = false;
  mFocusLayersId = {0};
  mFocusHorizontalTarget = ScrollableLayerGuid::NULL_SCROLL_ID;
  mFocusVerticalTarget = ScrollableLayerGuid::NULL_SCROLL_ID;
  mFocusTree = {};
}

}  // namespace layers
}  // namespace mozilla

Messung V0.5
C=81 H=97 G=89

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.