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

Quelle  nsWindowLoggedMessages.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 <windef.h>
#include <winuser.h>
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/Likely.h"
#include "mozilla/StaticPrefs_storage.h"
#include "mozilla/StaticPrefs_widget.h"
#include "nsWindowLoggedMessages.h"
#include "nsWindow.h"
#include "WinUtils.h"
#include <map>
#include <algorithm>

namespace mozilla::widget {

// NCCALCSIZE_PARAMS and WINDOWPOS are relatively large structures, so store
// them as a pointer to save memory
using NcCalcSizeVariantData =
    Variant<UniquePtr<std::pair<NCCALCSIZE_PARAMS, WINDOWPOS>>, RECT>;
// to save memory, hold the raw data and only convert to string
// when requested
using MessageSpecificData =
    Variant<std::pair<WPARAM, LPARAM>,  // WM_SIZE, WM_MOVE
            WINDOWPOS,  // WM_WINDOWPOSCHANGING, WM_WINDOWPOSCHANGED
            std::pair<WPARAM, RECT>,      // WM_SIZING, WM_DPICHANGED, WM_MOVING
            std::pair<WPARAM, nsString>,  // WM_SETTINGCHANGE
            std::pair<bool, NcCalcSizeVariantData>,  // WM_NCCALCSIZE
            MINMAXINFO                               // WM_GETMINMAXINFO
            >;

struct WindowMessageData {
  long mEventCounter;
  bool mIsPreEvent;
  MessageSpecificData mSpecificData;
  mozilla::Maybe<bool> mResult;
  LRESULT mRetValue;
  WindowMessageData(long eventCounter, bool isPreEvent,
                    MessageSpecificData&& specificData,
                    mozilla::Maybe<bool> result, LRESULT retValue)
      : mEventCounter(eventCounter),
        mIsPreEvent(isPreEvent),
        mSpecificData(std::move(specificData)),
        mResult(result),
        mRetValue(retValue) {}
  // Disallow copy constructor/operator since MessageSpecificData has a
  // UniquePtr
  WindowMessageData(const WindowMessageData&) = delete;
  WindowMessageData& operator=(const WindowMessageData&) = delete;
  WindowMessageData(WindowMessageData&&) = default;
  WindowMessageData& operator=(WindowMessageData&&) = default;
};

struct WindowMessageDataSortKey {
  long mEventCounter;
  bool mIsPreEvent;
  explicit WindowMessageDataSortKey(const WindowMessageData& data)
      : mEventCounter(data.mEventCounter), mIsPreEvent(data.mIsPreEvent) {}
  bool operator<(const WindowMessageDataSortKey& other) const {
    if (mEventCounter < other.mEventCounter) {
      return true;
    }
    if (other.mEventCounter < mEventCounter) {
      return false;
    }
    if (mIsPreEvent && !other.mIsPreEvent) {
      return true;
    }
    if (other.mIsPreEvent && !mIsPreEvent) {
      return false;
    }
    // they're equal
    return false;
  }
};

struct CircularMessageBuffer {
  // Only used when the vector is at its maximum size
  size_t mNextFreeIndex = 0;
  std::vector<WindowMessageData> mMessages;
};
using WindowMessageMap = std::map<HWND, std::map<UINT, CircularMessageBuffer>>;

static WindowMessageMap* GetStaticMessageBuffer() {
  MOZ_ASSERT(NS_IsMainThread());
  static StaticAutoPtr<WindowMessageMap> gWindowMessages;
  static bool gWindowMessagesShutdown = false;

  if (MOZ_LIKELY(gWindowMessages)) {
    return gWindowMessages.get();
  }
  if (gWindowMessagesShutdown) {
    return nullptr;
  }

  gWindowMessages = new WindowMessageMap();

  RunOnShutdown([]() {
    MOZ_ASSERT(NS_IsMainThread());
    gWindowMessages = nullptr;
    gWindowMessagesShutdown = true;
  });

  return gWindowMessages.get();
}

static HWND GetHwndFromWidget(nsIWidget* windowWidget) {
  nsWindow* window = static_cast<nsWindow*>(windowWidget);
  return window->GetWindowHandle();
}

MessageSpecificData MakeMessageSpecificData(UINT event, WPARAM wParam,
                                            LPARAM lParam) {
  // Since we store this data for every message we log, make sure it's of a
  // reasonable size. Keep in mind we're storing up to 10 (number of message
  // types)
  // * 6 (default number of messages per type to keep) of these messages per
  // window.
  static_assert(sizeof(MessageSpecificData) <= 48);
  switch (event) {
    case WM_SIZE:
    case WM_MOVE:
      return MessageSpecificData(std::make_pair(wParam, lParam));
    case WM_WINDOWPOSCHANGING:
    case WM_WINDOWPOSCHANGED: {
      LPWINDOWPOS windowPosPtr = reinterpret_cast<LPWINDOWPOS>(lParam);
      WINDOWPOS windowPos = *windowPosPtr;
      return MessageSpecificData(std::move(windowPos));
    }
    case WM_SIZING:
    case WM_DPICHANGED:
    case WM_MOVING: {
      LPRECT rectPtr = reinterpret_cast<LPRECT>(lParam);
      RECT rect = *rectPtr;
      return MessageSpecificData(std::make_pair(wParam, std::move(rect)));
    }
    case WM_SETTINGCHANGE: {
      LPCWSTR wideStrPtr = reinterpret_cast<LPCWSTR>(lParam);
      nsString str(wideStrPtr);
      return MessageSpecificData(std::make_pair(wParam, std::move(str)));
    }
    case WM_NCCALCSIZE: {
      bool shouldIndicateValidArea = wParam == TRUE;
      if (shouldIndicateValidArea) {
        LPNCCALCSIZE_PARAMS ncCalcSizeParamsPtr =
            reinterpret_cast<LPNCCALCSIZE_PARAMS>(lParam);
        NCCALCSIZE_PARAMS ncCalcSizeParams = *ncCalcSizeParamsPtr;
        WINDOWPOS windowPos = *ncCalcSizeParams.lppos;
        UniquePtr<std::pair<NCCALCSIZE_PARAMS, WINDOWPOS>> ncCalcSizeData =
            MakeUnique<std::pair<NCCALCSIZE_PARAMS, WINDOWPOS>>(
                std::pair(std::move(ncCalcSizeParams), std::move(windowPos)));
        return MessageSpecificData(
            std::make_pair(shouldIndicateValidArea,
                           NcCalcSizeVariantData(std::move(ncCalcSizeData))));
      } else {
        LPRECT rectPtr = reinterpret_cast<LPRECT>(lParam);
        RECT rect = *rectPtr;
        return MessageSpecificData(std::make_pair(
            shouldIndicateValidArea, NcCalcSizeVariantData(std::move(rect))));
      }
    }
    case WM_GETMINMAXINFO: {
      PMINMAXINFO minMaxInfoPtr = reinterpret_cast<PMINMAXINFO>(lParam);
      MINMAXINFO minMaxInfo = *minMaxInfoPtr;
      return MessageSpecificData(std::move(minMaxInfo));
    }
    default:
      MOZ_ASSERT_UNREACHABLE(
          "Unhandled message type in MakeMessageSpecificData");
      return MessageSpecificData(std::make_pair(wParam, lParam));
  }
}

void AppendFriendlyMessageSpecificData(nsCString& str, UINT event,
                                       bool isPreEvent,
                                       const MessageSpecificData& data) {
  switch (event) {
    case WM_SIZE: {
      const auto& params = data.as<std::pair<WPARAM, LPARAM>>();
      nsAutoCString tempStr =
          WmSizeParamInfo(params.first, params.second, isPreEvent);
      str.AppendASCII(tempStr);
      break;
    }
    case WM_MOVE: {
      const auto& params = data.as<std::pair<WPARAM, LPARAM>>();
      XLowWordYHighWordParamInfo(str, params.second, "upperLeft", isPreEvent);
      break;
    }
    case WM_WINDOWPOSCHANGING:
    case WM_WINDOWPOSCHANGED: {
      const auto& params = data.as<WINDOWPOS>();
      WindowPosParamInfo(str, reinterpret_cast<uint64_t>(¶ms),
                         "newSizeAndPos", isPreEvent);
      break;
    }
    case WM_SIZING: {
      const auto& params = data.as<std::pair<WPARAM, RECT>>();
      WindowEdgeParamInfo(str, params.first, "edge", isPreEvent);
      str.AppendASCII(" ");
      RectParamInfo(str, reinterpret_cast<uint64_t>(¶ms.second), "rect",
                    isPreEvent);
      break;
    }
    case WM_DPICHANGED: {
      const auto& params = data.as<std::pair<WPARAM, RECT>>();
      XLowWordYHighWordParamInfo(str, params.first, "newDPI", isPreEvent);
      str.AppendASCII(" ");
      RectParamInfo(str, reinterpret_cast<uint64_t>(¶ms.second),
                    "suggestedSizeAndPos", isPreEvent);
      break;
    }
    case WM_MOVING: {
      const auto& params = data.as<std::pair<WPARAM, RECT>>();
      RectParamInfo(str, reinterpret_cast<uint64_t>(¶ms.second), "rect",
                    isPreEvent);
      break;
    }
    case WM_SETTINGCHANGE: {
      const auto& params = data.as<std::pair<WPARAM, nsString>>();
      UiActionParamInfo(str, params.first, "uiAction", isPreEvent);
      str.AppendASCII(" ");
      WideStringParamInfo(
          str,
          reinterpret_cast<uint64_t>((const wchar_t*)(params.second.Data())),
          "paramChanged", isPreEvent);
      break;
    }
    case WM_NCCALCSIZE: {
      const auto& params = data.as<std::pair<bool, NcCalcSizeVariantData>>();
      bool shouldIndicateValidArea = params.first;
      if (shouldIndicateValidArea) {
        const auto& validAreaParams =
            params.second
                .as<UniquePtr<std::pair<NCCALCSIZE_PARAMS, WINDOWPOS>>>();
        // Make pointer point to the cached data
        validAreaParams->first.lppos = &validAreaParams->second;
        nsAutoCString tempStr = WmNcCalcSizeParamInfo(
            TRUEreinterpret_cast<uint64_t>(&validAreaParams->first),
            isPreEvent);
        str.AppendASCII(tempStr);
      } else {
        RECT rect = params.second.as<RECT>();
        nsAutoCString tempStr = WmNcCalcSizeParamInfo(
            FALSEreinterpret_cast<uint64_t>(&rect), isPreEvent);
        str.AppendASCII(tempStr);
      }
      break;
    }
    case WM_GETMINMAXINFO: {
      const auto& params = data.as<MINMAXINFO>();
      MinMaxInfoParamInfo(str, reinterpret_cast<uint64_t>(¶ms), "",
                          isPreEvent);
      break;
    }
    default:
      MOZ_ASSERT(false,
                 "Unhandled message type in AppendFriendlyMessageSpecificData");
      str.AppendASCII("???");
  }
}

nsCString MakeFriendlyMessage(UINT event, bool isPreEvent, long eventCounter,
                              const MessageSpecificData& data,
                              mozilla::Maybe<bool> result, LRESULT retValue) {
  nsCString str;
  const char* eventName = mozilla::widget::WinUtils::WinEventToEventName(event);
  MOZ_ASSERT(eventName, "Unknown event name in MakeFriendlyMessage");
  eventName = eventName ? eventName : "(unknown)";
  str.AppendPrintf("%6ld %04x (%s) - ", eventCounter, event, eventName);
  AppendFriendlyMessageSpecificData(str, event, isPreEvent, data);
  const char* resultMsg =
      result.isSome() ? (result.value() ? "true" : "false") : "initial call";
  str.AppendPrintf(" 0x%08llX (%s)",
                   result.isSome() ? static_cast<uint64_t>(retValue) : 0,
                   resultMsg);
  return str;
}

void WindowClosed(HWND hwnd) {
  if (auto* msgs = GetStaticMessageBuffer()) {
    msgs->erase(hwnd);
  }
}

void LogWindowMessage(HWND hwnd, UINT event, bool isPreEvent, long eventCounter,
                      WPARAM wParam, LPARAM lParam, mozilla::Maybe<bool> result,
                      LRESULT retValue) {
  auto* messageBuf = GetStaticMessageBuffer();
  if (!messageBuf) return;
  auto& hwndMessages = (*messageBuf)[hwnd];
  auto& hwndWindowMessages = hwndMessages[event];
  WindowMessageData messageData = {
      eventCounter, isPreEvent, MakeMessageSpecificData(event, wParam, lParam),
      result, retValue};
  uint32_t numberOfMessagesToKeep =
      StaticPrefs::widget_windows_messages_to_log();
  if (hwndWindowMessages.mMessages.size() < numberOfMessagesToKeep) {
    // haven't reached limit yet
    hwndWindowMessages.mMessages.push_back(std::move(messageData));
  } else {
    hwndWindowMessages.mMessages[hwndWindowMessages.mNextFreeIndex] =
        std::move(messageData);
  }
  hwndWindowMessages.mNextFreeIndex =
      (hwndWindowMessages.mNextFreeIndex + 1) % numberOfMessagesToKeep;
}

void GetLatestWindowMessages(nsIWidget* windowWidget,
                             nsTArray<nsCString>& messages) {
  auto* messageBuf = GetStaticMessageBuffer();
  if (!messageBuf) return;
  HWND hwnd = GetHwndFromWidget(windowWidget);
  const auto& rawMessages = (*messageBuf)[hwnd];
  nsTArray<std::pair<WindowMessageDataSortKey, nsCString>>
      sortKeyAndMessageArray;
  sortKeyAndMessageArray.SetCapacity(
      rawMessages.size() * StaticPrefs::widget_windows_messages_to_log());
  for (const auto& eventAndMessage : rawMessages) {
    for (const auto& messageData : eventAndMessage.second.mMessages) {
      nsCString message = MakeFriendlyMessage(
          eventAndMessage.first, messageData.mIsPreEvent,
          messageData.mEventCounter, messageData.mSpecificData,
          messageData.mResult, messageData.mRetValue);
      WindowMessageDataSortKey sortKey(messageData);
      sortKeyAndMessageArray.AppendElement(
          std::make_pair(sortKey, std::move(message)));
    }
  }
  std::sort(sortKeyAndMessageArray.begin(), sortKeyAndMessageArray.end());
  messages.SetCapacity(sortKeyAndMessageArray.Length());
  for (std::pair<WindowMessageDataSortKey, nsCString>& entry :
       sortKeyAndMessageArray) {
    messages.AppendElement(std::move(entry.second));
  }
}
}  // namespace mozilla::widget

97%


¤ Dauer der Verarbeitung: 0.14 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.