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

Quelle  ScreenManager.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 "ScreenManager.h"

#include "mozilla/ClearOnShutdown.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/DOMTypes.h"
#include "mozilla/Logging.h"
#include "mozilla/StaticPtr.h"
#ifdef MOZ_WAYLAND
#  include "mozilla/WidgetUtilsGtk.h"
#endif /* MOZ_WAYLAND */

static mozilla::LazyLogModule sScreenLog("WidgetScreen");

namespace mozilla::widget {

NS_IMPL_ISUPPORTS(ScreenManager, nsIScreenManager)

ScreenManager::ScreenManager() = default;

ScreenManager::~ScreenManager() = default;

static StaticRefPtr<ScreenManager> sSingleton;

ScreenManager& ScreenManager::GetSingleton() {
  if (!sSingleton) {
    sSingleton = new ScreenManager();
    ClearOnShutdown(&sSingleton);
  }
  return *sSingleton;
}

already_AddRefed<ScreenManager> ScreenManager::GetAddRefedSingleton() {
  RefPtr<ScreenManager> sm = &GetSingleton();
  return sm.forget();
}

void ScreenManager::SetHelper(UniquePtr<Helper> aHelper) {
  mHelper = std::move(aHelper);
}

// static
void ScreenManager::Refresh(nsTArray<RefPtr<Screen>>&& aScreens) {
  if (PastShutdownPhase(ShutdownPhase::XPCOMShutdown)) {
    // We don't refresh screen data if starting XPCOM shutdown path.
    // GetSingleton returns invalid data since it is freed.
    return;
  }
  MOZ_LOG(sScreenLog, LogLevel::Debug, ("Refresh screens"));
  GetSingleton().RefreshInternal(std::move(aScreens));
}

void ScreenManager::Refresh(nsTArray<mozilla::dom::ScreenDetails>&& aScreens) {
  MOZ_LOG(sScreenLog, LogLevel::Debug, ("Refresh screens from IPC"));

  AutoTArray<RefPtr<Screen>, 4> screens;
  for (auto& screen : aScreens) {
    screens.AppendElement(new Screen(screen));
  }
  RefreshInternal(std::move(screens));
}

void ScreenManager::RefreshInternal(nsTArray<RefPtr<Screen>>&& aScreens) {
  mScreenList = std::move(aScreens);

  CopyScreensToAllRemotesIfIsParent();
  if (nsCOMPtr<nsIObserverService> s = services::GetObserverService()) {
    s->NotifyObservers(nullptr, "screen-information-changed", nullptr);
  }
}

template <class Range>
void ScreenManager::CopyScreensToRemoteRange(Range aRemoteRange) {
  AutoTArray<dom::ScreenDetails, 4> screens;
  for (auto& screen : mScreenList) {
    screens.AppendElement(screen->ToScreenDetails());
  }
  for (auto cp : aRemoteRange) {
    MOZ_LOG(sScreenLog, LogLevel::Debug,
            ("Send screens to [Pid %d]", cp->Pid()));
    if (!cp->SendRefreshScreens(screens)) {
      MOZ_LOG(sScreenLog, LogLevel::Error,
              ("SendRefreshScreens to [Pid %d] failed", cp->Pid()));
    }
  }
}

void ScreenManager::CopyScreensToRemote(dom::ContentParent* aContentParent) {
  MOZ_ASSERT(aContentParent);
  MOZ_ASSERT(XRE_IsParentProcess());

  auto range = {aContentParent};
  CopyScreensToRemoteRange(range);
}

void ScreenManager::CopyScreensToAllRemotesIfIsParent() {
  if (XRE_IsContentProcess()) {
    return;
  }

  MOZ_LOG(sScreenLog, LogLevel::Debug, ("Refreshing all ContentParents"));

  CopyScreensToRemoteRange(
      dom::ContentParent::AllProcesses(dom::ContentParent::eLive));
}

// Returns the screen that contains the rectangle. If the rect overlaps
// multiple screens, it picks the screen with the greatest area of intersection.
//
// The coordinates are in desktop pixels.
//
NS_IMETHODIMP
ScreenManager::ScreenForRect(int32_t aX, int32_t aY, int32_t aWidth,
                             int32_t aHeight, nsIScreen** aOutScreen) {
  DesktopIntRect rect(aX, aY, aWidth, aHeight);
  nsCOMPtr<nsIScreen> screen = ScreenForRect(rect);
  screen.forget(aOutScreen);
  return NS_OK;
}

already_AddRefed<Screen> ScreenManager::ScreenForRect(
    const DesktopIntRect& aRect) {
#if defined(MOZ_WAYLAND) && defined(MOZ_LOGGING)
  static bool inWayland = GdkIsWaylandDisplay();
  if (inWayland) {
    MOZ_LOG(sScreenLog, LogLevel::Warning,
            ("Getting screen in wayland, primary display will be returned."));
  }
#endif

  if (mScreenList.IsEmpty()) {
    MOZ_LOG(sScreenLog, LogLevel::Warning,
            ("No screen available. This can happen in xpcshell."));
    auto screen = MakeRefPtr<Screen>(
        LayoutDeviceIntRect(), LayoutDeviceIntRect(), 0, 0, 0,
        DesktopToLayoutDeviceScale(), CSSToLayoutDeviceScale(), 96 /* dpi */,
        Screen::IsPseudoDisplay::No, Screen::IsHDR::No,
        hal::ScreenOrientation::None, 0);
    return screen.forget();
  }

  // Optimize for the common case. If the number of screens is only
  // one then just return the primary screen.
  if (mScreenList.Length() == 1) {
    return GetPrimaryScreen();
  }

  // which screen should we return?
  Screen* which = mScreenList[0].get();

  // walk the list of screens and find the one that has the most
  // surface area.
  uint32_t area = 0;
  for (auto& screen : mScreenList) {
    int32_t x, y, width, height;
    x = y = width = height = 0;
    screen->GetRectDisplayPix(&x, &y, &width, &height);
    // calculate the surface area
    DesktopIntRect screenRect(x, y, width, height);
    screenRect.IntersectRect(screenRect, aRect);
    uint32_t tempArea = screenRect.Area();
    if (tempArea > area) {
      which = screen.get();
      area = tempArea;
    }
  }

  // If the rect intersects one or more screen,
  // return the screen that has the largest intersection.
  if (area > 0) {
    RefPtr<Screen> ret = which;
    return ret.forget();
  }

  // If the rect does not intersect a screen, find
  // a screen that is nearest to the rect.
  uint32_t distance = UINT32_MAX;
  for (auto& screen : mScreenList) {
    int32_t x, y, width, height;
    x = y = width = height = 0;
    screen->GetRectDisplayPix(&x, &y, &width, &height);

    uint32_t distanceX = 0;
    if (aRect.x > (x + width)) {
      distanceX = aRect.x - (x + width);
    } else if (aRect.XMost() < x) {
      distanceX = x - aRect.XMost();
    }

    uint32_t distanceY = 0;
    if (aRect.y > (y + height)) {
      distanceY = aRect.y - (y + height);
    } else if (aRect.YMost() < y) {
      distanceY = y - aRect.YMost();
    }

    uint32_t tempDistance = distanceX * distanceX + distanceY * distanceY;
    if (tempDistance < distance) {
      which = screen.get();
      distance = tempDistance;
      if (distance == 0) {
        break;
      }
    }
  }

  RefPtr<Screen> ret = which;
  return ret.forget();
}

// The screen with the menubar/taskbar. This shouldn't be needed very
// often.
//
already_AddRefed<Screen> ScreenManager::GetPrimaryScreen() {
  if (mScreenList.IsEmpty()) {
    MOZ_LOG(sScreenLog, LogLevel::Warning,
            ("No screen available. This can happen in xpcshell."));
    return MakeAndAddRef<Screen>(LayoutDeviceIntRect(), LayoutDeviceIntRect(),
                                 0, 0, 0, DesktopToLayoutDeviceScale(),
                                 CSSToLayoutDeviceScale(), 96 /* dpi */,
                                 Screen::IsPseudoDisplay::No, Screen::IsHDR::No,
                                 hal::ScreenOrientation::None, 0);
  }

  return do_AddRef(mScreenList[0]);
}

NS_IMETHODIMP
ScreenManager::GetPrimaryScreen(nsIScreen** aPrimaryScreen) {
  nsCOMPtr<nsIScreen> screen = GetPrimaryScreen();
  screen.forget(aPrimaryScreen);
  return NS_OK;
}

NS_IMETHODIMP
ScreenManager::GetTotalScreenPixels(int64_t* aTotalScreenPixels) {
  MOZ_ASSERT(aTotalScreenPixels);

  if (mScreenList.IsEmpty()) {
    MOZ_LOG(sScreenLog, LogLevel::Warning,
            ("No screen available. This can happen in xpcshell."));
    *aTotalScreenPixels = 0;
    return NS_OK;
  }

  int64_t pixels = 0;
  for (auto& screen : mScreenList) {
    int32_t x, y, width, height;
    x = y = width = height = 0;
    screen->GetRect(&x, &y, &width, &height);
    pixels += width * height;
  }

  *aTotalScreenPixels = pixels;
  return NS_OK;
}

}  // namespace mozilla::widget

83%


¤ Dauer der Verarbeitung: 0.28 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 ist noch experimentell.