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

Quelle  nsUserIdleServiceGTK.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:expandtab:shiftwidth=4:tabstop=4:
 */

/* 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 <gtk/gtk.h>

#include "nsUserIdleServiceGTK.h"
#include "nsDebug.h"
#include "prlink.h"
#include "mozilla/Logging.h"
#include "WidgetUtilsGtk.h"
#ifdef MOZ_X11
#  include <X11/Xlib.h>
#  include <X11/Xutil.h>
#  include <gdk/gdkx.h>
#endif
#ifdef MOZ_ENABLE_DBUS
#  include <gio/gio.h>
#  include "AsyncDBus.h"
#  include "WakeLockListener.h"
#  include "nsIObserverService.h"
#  include "mozilla/UniquePtrExtensions.h"
#endif

using mozilla::LogLevel;
static mozilla::LazyLogModule sIdleLog("nsIUserIdleService");

using namespace mozilla;
using namespace mozilla::widget;

#ifdef MOZ_X11
typedef struct {
  Window window;               // Screen saver window
  int state;                   // ScreenSaver(Off,On,Disabled)
  int kind;                    // ScreenSaver(Blanked,Internal,External)
  unsigned long til_or_since;  // milliseconds since/til screensaver kicks in
  unsigned long idle;          // milliseconds idle
  unsigned long event_mask;    // event stuff
} XScreenSaverInfo;

typedef bool (*_XScreenSaverQueryExtension_fn)(Display* dpy, int* event_base,
                                               int* error_base);
typedef XScreenSaverInfo* (*_XScreenSaverAllocInfo_fn)(void);
typedef void (*_XScreenSaverQueryInfo_fn)(Display* dpy, Drawable drw,
                                          XScreenSaverInfo* info);

class UserIdleServiceX11 : public UserIdleServiceImpl {
 public:
  bool PollIdleTime(uint32_t* aIdleTime) override {
    // Ask xscreensaver about idle time:
    *aIdleTime = 0;

    // We might not have a display (cf. in xpcshell)
    Display* dplay = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
    if (!dplay) {
      MOZ_LOG(sIdleLog, LogLevel::Warning, ("No display found!\n"));
      return false;
    }

    int event_base, error_base;
    if (mXSSQueryExtension(dplay, &event_base, &error_base)) {
      if (!mXssInfo) mXssInfo = mXSSAllocInfo();
      if (!mXssInfo) return false;
      mXSSQueryInfo(dplay, GDK_ROOT_WINDOW(), mXssInfo);
      *aIdleTime = mXssInfo->idle;
      MOZ_LOG(sIdleLog, LogLevel::Info,
              ("UserIdleServiceX11::PollIdleTime() %d\n", *aIdleTime));
      return true;
    }
    // If we get here, we couldn't get to XScreenSaver:
    MOZ_LOG(sIdleLog, LogLevel::Warning,
            ("XSSQueryExtension returned false!\n"));
    return false;
  }

  bool ProbeImplementation() override {
    MOZ_LOG(sIdleLog, LogLevel::Info,
            ("UserIdleServiceX11::UserIdleServiceX11()\n"));

    if (!mozilla::widget::GdkIsX11Display()) {
      return false;
    }

    // This will leak - See comments in ~UserIdleServiceX11().
    PRLibrary* xsslib = PR_LoadLibrary("libXss.so.1");
    if (!xsslib)  // ouch.
    {
      MOZ_LOG(sIdleLog, LogLevel::Warning, ("Failed to find libXss.so!\n"));
      return false;
    }

    mXSSQueryExtension = (_XScreenSaverQueryExtension_fn)PR_FindFunctionSymbol(
        xsslib, "XScreenSaverQueryExtension");
    mXSSAllocInfo = (_XScreenSaverAllocInfo_fn)PR_FindFunctionSymbol(
        xsslib, "XScreenSaverAllocInfo");
    mXSSQueryInfo = (_XScreenSaverQueryInfo_fn)PR_FindFunctionSymbol(
        xsslib, "XScreenSaverQueryInfo");

    if (!mXSSQueryExtension) {
      MOZ_LOG(sIdleLog, LogLevel::Warning,
              ("Failed to get XSSQueryExtension!\n"));
    }
    if (!mXSSAllocInfo) {
      MOZ_LOG(sIdleLog, LogLevel::Warning, ("Failed to get XSSAllocInfo!\n"));
    }
    if (!mXSSQueryInfo) {
      MOZ_LOG(sIdleLog, LogLevel::Warning, ("Failed to get XSSQueryInfo!\n"));
    }
    if (!mXSSQueryExtension || !mXSSAllocInfo || !mXSSQueryInfo) {
      // We're missing X11 symbols
      return false;
    }

    // UserIdleServiceX11 uses sync init, confirm it now.
    mUserIdleServiceGTK->AcceptServiceCallback();
    return true;
  }

  explicit UserIdleServiceX11(nsUserIdleServiceGTK* aUserIdleService)
      : UserIdleServiceImpl(aUserIdleService) {};

  ~UserIdleServiceX11() {
#  ifdef MOZ_X11
    if (mXssInfo) {
      XFree(mXssInfo);
    }
#  endif

// It is not safe to unload libXScrnSaver until each display is closed because
// the library registers callbacks through XESetCloseDisplay (Bug 397607).
// (Also the library and its functions are scoped for the file not the object.)
#  if 0
        if (xsslib) {
            PR_UnloadLibrary(xsslib);
            xsslib = nullptr;
        }
#  endif
  }

 private:
  XScreenSaverInfo* mXssInfo = nullptr;
  _XScreenSaverQueryExtension_fn mXSSQueryExtension = nullptr;
  _XScreenSaverAllocInfo_fn mXSSAllocInfo = nullptr;
  _XScreenSaverQueryInfo_fn mXSSQueryInfo = nullptr;
};
#endif

#ifdef MOZ_ENABLE_DBUS
class UserIdleServiceMutter : public UserIdleServiceImpl {
 public:
  bool PollIdleTime(uint32_t* aIdleTime) override {
    MOZ_LOG(sIdleLog, LogLevel::Info, ("PollIdleTime() request\n"));

    // We're not ready yet
    if (!mProxy) {
      return false;
    }

    if (!mPollInProgress) {
      mPollInProgress = true;
      DBusProxyCall(mProxy, "GetIdletime", nullptr, G_DBUS_CALL_FLAGS_NONE, -1,
                    mCancellable)
          ->Then(
              GetCurrentSerialEventTarget(), __func__,
              // It's safe to capture this as we use mCancellable to stop
              // listening.
              [this](RefPtr<GVariant>&& aResult) {
                if (!g_variant_is_of_type(aResult, G_VARIANT_TYPE_TUPLE) ||
                    g_variant_n_children(aResult) != 1) {
                  MOZ_LOG(sIdleLog, LogLevel::Info,
                          ("PollIdleTime() Unexpected params type: %s\n",
                           g_variant_get_type_string(aResult)));
                  mLastIdleTime = 0;
                  return;
                }
                RefPtr<GVariant> iTime =
                    dont_AddRef(g_variant_get_child_value(aResult, 0));
                if (!g_variant_is_of_type(iTime, G_VARIANT_TYPE_UINT64)) {
                  MOZ_LOG(sIdleLog, LogLevel::Info,
                          ("PollIdleTime() Unexpected params type: %s\n",
                           g_variant_get_type_string(aResult)));
                  mLastIdleTime = 0;
                  return;
                }
                uint64_t idleTime = g_variant_get_uint64(iTime);
                if (idleTime > std::numeric_limits<uint32_t>::max()) {
                  idleTime = std::numeric_limits<uint32_t>::max();
                }
                mLastIdleTime = idleTime;
                mPollInProgress = false;
                MOZ_LOG(sIdleLog, LogLevel::Info,
                        ("Async handler got %d\n", mLastIdleTime));
              },
              [this](GUniquePtr<GError>&& aError) {
                mPollInProgress = false;
                if (!IsCancelledGError(aError.get())) {
                  MOZ_LOG(
                      sIdleLog, LogLevel::Warning,
                      ("Failed to call GetIdletime(): %s\n", aError->message));
                  mUserIdleServiceGTK->RejectAndTryNextServiceCallback();
                }
              });
    }

    *aIdleTime = mLastIdleTime;
    MOZ_LOG(sIdleLog, LogLevel::Info,
            ("PollIdleTime() returns %d\n", *aIdleTime));
    return true;
  }

  bool ProbeImplementation() override {
    MOZ_LOG(sIdleLog, LogLevel::Info,
            ("UserIdleServiceMutter::UserIdleServiceMutter()\n"));

    mCancellable = dont_AddRef(g_cancellable_new());
    CreateDBusProxyForBus(
        G_BUS_TYPE_SESSION,
        GDBusProxyFlags(G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS |
                        G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES),
        nullptr, "org.gnome.Mutter.IdleMonitor",
        "/org/gnome/Mutter/IdleMonitor/Core""org.gnome.Mutter.IdleMonitor",
        mCancellable)
        ->Then(
            GetCurrentSerialEventTarget(), __func__,
            [this](RefPtr<GDBusProxy>&& aProxy) {
              mProxy = std::move(aProxy);
              mUserIdleServiceGTK->AcceptServiceCallback();
            },
            [this](GUniquePtr<GError>&& aError) {
              if (!IsCancelledGError(aError.get())) {
                mUserIdleServiceGTK->RejectAndTryNextServiceCallback();
              }
            });
    return true;
  }

  explicit UserIdleServiceMutter(nsUserIdleServiceGTK* aUserIdleService)
      : UserIdleServiceImpl(aUserIdleService) {};

  ~UserIdleServiceMutter() {
    if (mCancellable) {
      g_cancellable_cancel(mCancellable);
      mCancellable = nullptr;
    }
    mProxy = nullptr;
  }

 private:
  RefPtr<GDBusProxy> mProxy;
  RefPtr<GCancellable> mCancellable;
  uint32_t mLastIdleTime = 0;
  bool mPollInProgress = false;
};
#endif

void nsUserIdleServiceGTK::ProbeService() {
  MOZ_LOG(sIdleLog, LogLevel::Info,
          ("nsUserIdleServiceGTK::ProbeService() mIdleServiceType %d\n",
           mIdleServiceType));
  MOZ_ASSERT(!mIdleService);

  switch (mIdleServiceType) {
#ifdef MOZ_ENABLE_DBUS
    case IDLE_SERVICE_MUTTER:
      mIdleService = MakeUnique<UserIdleServiceMutter>(this);
      break;
#endif
#ifdef MOZ_X11
    case IDLE_SERVICE_XSCREENSAVER:
      mIdleService = MakeUnique<UserIdleServiceX11>(this);
      break;
#endif
    default:
      return;
  }

  if (!mIdleService->ProbeImplementation()) {
    RejectAndTryNextServiceCallback();
  }
}

void nsUserIdleServiceGTK::AcceptServiceCallback() {
  MOZ_LOG(sIdleLog, LogLevel::Info,
          ("nsUserIdleServiceGTK::AcceptServiceCallback() type %d\n",
           mIdleServiceType));
  mIdleServiceInitialized = true;
}

void nsUserIdleServiceGTK::RejectAndTryNextServiceCallback() {
  MOZ_LOG(sIdleLog, LogLevel::Info,
          ("nsUserIdleServiceGTK::RejectAndTryNextServiceCallback() type %d\n",
           mIdleServiceType));

  // Delete recent non-working service
  MOZ_ASSERT(mIdleService, "Nothing to reject?");
  mIdleService = nullptr;
  mIdleServiceInitialized = false;

  mIdleServiceType++;
  if (mIdleServiceType < IDLE_SERVICE_NONE) {
    MOZ_LOG(sIdleLog, LogLevel::Info,
            ("nsUserIdleServiceGTK try next idle service\n"));
    ProbeService();
  } else {
    MOZ_LOG(sIdleLog, LogLevel::Info, ("nsUserIdleServiceGTK failed\n"));
  }
}

bool nsUserIdleServiceGTK::PollIdleTime(uint32_t* aIdleTime) {
  if (!mIdleServiceInitialized) {
    return false;
  }
  return mIdleService->PollIdleTime(aIdleTime);
}

100%


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