Bug 1767172 - Remove custom screen info handling from GfxInfo, use ScreenManager for that. r=jrmuizel,handyman,stransky

This removes a bunch of custom code from GfxInfo to obtain screen
information, and instead collects that screen information in
ScreenManager.

This, apart of removing duplicated code, has the extra benefit of
reporting multi-monitor information on GTK (and potentially in the
future reporting scale and refresh rate properly as well, I've kept the
telemetry as it was on that regard).

Differential Revision: https://phabricator.services.mozilla.com/D145178
This commit is contained in:
Emilio Cobos Álvarez 2022-05-05 15:07:03 +00:00
Родитель 0d0356d4a0
Коммит 9d430bf4ed
31 изменённых файлов: 285 добавлений и 836 удалений

Просмотреть файл

@ -135,11 +135,13 @@ struct ScreenDetails {
DesktopIntRect availRectDisplayPix;
int32_t pixelDepth;
int32_t colorDepth;
uint32_t refreshRate; // In Hz, or 0 if not known.
DesktopToLayoutDeviceScale contentsScaleFactor;
CSSToLayoutDeviceScale defaultCSSScaleFactor;
float dpi;
ScreenOrientation orientation;
uint16_t orientationAngle;
bool isPseudoDisplay;
};
struct DimensionInfo

Просмотреть файл

@ -121,7 +121,6 @@ class MockGfxInfo final : public nsIGfxInfo {
JS::MutableHandleValue _retval) override {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHOD RefreshMonitors(void) override { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD GetFailures(nsTArray<int32_t>& indices,
nsTArray<nsCString>& failures) override {
return NS_ERROR_NOT_IMPLEMENTED;
@ -229,15 +228,6 @@ class MockGfxInfo final : public nsIGfxInfo {
NS_IMETHOD GetIsGPU2Active(bool* aIsGPU2Active) override {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHOD GetDisplayInfo(nsTArray<nsString>& aDisplayInfo) override {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHOD GetDisplayWidth(nsTArray<uint32_t>& aDisplayWidth) override {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHOD GetDisplayHeight(nsTArray<uint32_t>& aDisplayHeight) override {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHOD GetDrmRenderDevice(nsACString& aDrmRenderDevice) override {
return NS_ERROR_NOT_IMPLEMENTED;
}

Просмотреть файл

@ -105,7 +105,8 @@
#include "nsServiceManagerUtils.h"
#include "nsTArray.h"
#include "nsIObserverService.h"
#include "nsIScreenManager.h"
#include "mozilla/widget/Screen.h"
#include "mozilla/widget/ScreenManager.h"
#include "MainThreadUtils.h"
#include "nsWeakReference.h"
@ -1033,19 +1034,19 @@ void gfxPlatform::ReportTelemetry() {
"GFX: Only allowed to be called from parent process.");
nsCOMPtr<nsIGfxInfo> gfxInfo = components::GfxInfo::Service();
nsTArray<uint32_t> displayWidths;
nsTArray<uint32_t> displayHeights;
gfxInfo->GetDisplayWidth(displayWidths);
gfxInfo->GetDisplayHeight(displayHeights);
uint32_t displayCount = displayWidths.Length();
uint32_t displayWidth = displayWidths.Length() > 0 ? displayWidths[0] : 0;
uint32_t displayHeight = displayHeights.Length() > 0 ? displayHeights[0] : 0;
Telemetry::ScalarSet(Telemetry::ScalarID::GFX_DISPLAY_COUNT, displayCount);
Telemetry::ScalarSet(Telemetry::ScalarID::GFX_DISPLAY_PRIMARY_HEIGHT,
displayHeight);
Telemetry::ScalarSet(Telemetry::ScalarID::GFX_DISPLAY_PRIMARY_WIDTH,
displayWidth);
{
auto& screenManager = widget::ScreenManager::GetSingleton();
const uint32_t screenCount = screenManager.CurrentScreenList().Length();
RefPtr<widget::Screen> primaryScreen = screenManager.GetPrimaryScreen();
const LayoutDeviceIntRect rect = primaryScreen->GetRect();
Telemetry::ScalarSet(Telemetry::ScalarID::GFX_DISPLAY_COUNT, screenCount);
Telemetry::ScalarSet(Telemetry::ScalarID::GFX_DISPLAY_PRIMARY_HEIGHT,
uint32_t(rect.Height()));
Telemetry::ScalarSet(Telemetry::ScalarID::GFX_DISPLAY_PRIMARY_WIDTH,
uint32_t(rect.Width()));
}
nsString adapterDesc;
gfxInfo->GetAdapterDescription(adapterDesc);
@ -3203,18 +3204,19 @@ void gfxPlatform::GetCMSSupportInfo(mozilla::widget::InfoObject& aObj) {
}
void gfxPlatform::GetDisplayInfo(mozilla::widget::InfoObject& aObj) {
nsCOMPtr<nsIGfxInfo> gfxInfo = components::GfxInfo::Service();
auto& screens = widget::ScreenManager::GetSingleton().CurrentScreenList();
aObj.DefineProperty("DisplayCount", screens.Length());
nsTArray<nsString> displayInfo;
auto rv = gfxInfo->GetDisplayInfo(displayInfo);
if (NS_SUCCEEDED(rv)) {
size_t displayCount = displayInfo.Length();
aObj.DefineProperty("DisplayCount", displayCount);
size_t i = 0;
for (auto& screen : screens) {
const LayoutDeviceIntRect rect = screen->GetRect();
nsPrintfCString value("%dx%d@%dHz scales:%f|%f", rect.width, rect.height,
screen->GetRefreshRate(),
screen->GetContentsScaleFactor(),
screen->GetDefaultCSSScaleFactor());
for (size_t i = 0; i < displayCount; i++) {
nsPrintfCString name("Display%zu", i);
aObj.DefineProperty(name.get(), displayInfo[i]);
}
aObj.DefineProperty(nsPrintfCString("Display%zu", i++).get(),
NS_ConvertUTF8toUTF16(value));
}
// Platform display info is only currently used for about:support and getting

Просмотреть файл

@ -661,32 +661,6 @@ static void get_xrandr_info(Display* dpy) {
Window root = RootWindow(dpy, DefaultScreen(dpy));
XRRProviderResources* pr = XRRGetProviderResources(dpy, root);
XRRScreenResources* res = XRRGetScreenResourcesCurrent(dpy, root);
RROutput primary = XRRGetOutputPrimary(dpy, root);
if (res->noutput != 0) {
bool foundCRTC = false;
for (int i = 0; i < res->noutput; i++) {
XRROutputInfo* outputInfo = XRRGetOutputInfo(dpy, res, res->outputs[i]);
if (!outputInfo->crtc) {
continue;
}
if (!foundCRTC) {
record_value("SCREEN_INFO\n");
foundCRTC = true;
}
XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(dpy, res, outputInfo->crtc);
record_value("%dx%d:%d;", crtcInfo->width, crtcInfo->height,
res->outputs[i] == primary ? 1 : 0);
}
if (foundCRTC) {
record_value("\n");
}
}
if (pr->nproviders != 0) {
record_value("DDX_DRIVER\n");
for (int i = 0; i < pr->nproviders; i++) {
@ -932,314 +906,6 @@ static void glxtest() {
#endif
#ifdef MOZ_WAYLAND
typedef void (*print_info_t)(void* info);
typedef void (*destroy_info_t)(void* info);
struct global_info {
struct wl_list link;
uint32_t id;
uint32_t version;
char* interface;
print_info_t print;
destroy_info_t destroy;
};
struct output_info {
struct global_info global;
struct wl_list global_link;
struct wl_output* output;
int32_t version;
int32_t scale;
};
struct xdg_output_v1_info {
struct wl_list link;
struct zxdg_output_v1* xdg_output;
struct output_info* output;
struct {
int32_t width, height;
} logical;
};
struct xdg_output_manager_v1_info {
struct global_info global;
struct zxdg_output_manager_v1* manager;
struct weston_info* info;
struct wl_list outputs;
};
struct weston_info {
struct wl_display* display;
struct wl_registry* registry;
struct wl_list infos;
bool roundtrip_needed;
struct wl_list outputs;
struct xdg_output_manager_v1_info* xdg_output_manager_v1_info;
};
static void init_global_info(struct weston_info* info,
struct global_info* global, uint32_t id,
const char* interface, uint32_t version) {
global->id = id;
global->version = version;
global->interface = strdup(interface);
wl_list_insert(info->infos.prev, &global->link);
}
static void print_output_info(void* data) {}
static void destroy_xdg_output_v1_info(struct xdg_output_v1_info* info) {
wl_list_remove(&info->link);
zxdg_output_v1_destroy(info->xdg_output);
free(info);
}
static int cmpOutputIds(const void* a, const void* b) {
return (((struct xdg_output_v1_info*)a)->output->global.id -
((struct xdg_output_v1_info*)b)->output->global.id);
}
static void print_xdg_output_manager_v1_info(void* data) {
struct xdg_output_manager_v1_info* info =
(struct xdg_output_manager_v1_info*)data;
struct xdg_output_v1_info* output;
int screen_count = wl_list_length(&info->outputs);
if (screen_count > 0) {
struct xdg_output_v1_info* infos = (struct xdg_output_v1_info*)calloc(
1, screen_count * sizeof(xdg_output_v1_info));
int pos = 0;
wl_list_for_each(output, &info->outputs, link) {
infos[pos] = *output;
pos++;
}
if (screen_count > 1) {
qsort(infos, screen_count, sizeof(struct xdg_output_v1_info),
cmpOutputIds);
}
record_value("SCREEN_INFO\n");
for (int i = 0; i < screen_count; i++) {
record_value("%dx%d:0;", infos[i].logical.width, infos[i].logical.height);
}
record_value("\n");
free(infos);
}
}
static void destroy_xdg_output_manager_v1_info(void* data) {
struct xdg_output_manager_v1_info* info =
(struct xdg_output_manager_v1_info*)data;
struct xdg_output_v1_info *output, *tmp;
zxdg_output_manager_v1_destroy(info->manager);
wl_list_for_each_safe(output, tmp, &info->outputs, link) {
destroy_xdg_output_v1_info(output);
}
}
static void handle_xdg_output_v1_logical_position(void* data,
struct zxdg_output_v1* output,
int32_t x, int32_t y) {}
static void handle_xdg_output_v1_logical_size(void* data,
struct zxdg_output_v1* output,
int32_t width, int32_t height) {
struct xdg_output_v1_info* xdg_output = (struct xdg_output_v1_info*)data;
xdg_output->logical.width = width;
xdg_output->logical.height = height;
}
static void handle_xdg_output_v1_done(void* data,
struct zxdg_output_v1* output) {}
static void handle_xdg_output_v1_name(void* data, struct zxdg_output_v1* output,
const char* name) {}
static void handle_xdg_output_v1_description(void* data,
struct zxdg_output_v1* output,
const char* description) {}
static const struct zxdg_output_v1_listener xdg_output_v1_listener = {
.logical_position = handle_xdg_output_v1_logical_position,
.logical_size = handle_xdg_output_v1_logical_size,
.done = handle_xdg_output_v1_done,
.name = handle_xdg_output_v1_name,
.description = handle_xdg_output_v1_description,
};
static void add_xdg_output_v1_info(
struct xdg_output_manager_v1_info* manager_info,
struct output_info* output) {
struct xdg_output_v1_info* xdg_output =
(struct xdg_output_v1_info*)calloc(1, sizeof *xdg_output);
wl_list_insert(&manager_info->outputs, &xdg_output->link);
xdg_output->xdg_output = zxdg_output_manager_v1_get_xdg_output(
manager_info->manager, output->output);
zxdg_output_v1_add_listener(xdg_output->xdg_output, &xdg_output_v1_listener,
xdg_output);
xdg_output->output = output;
manager_info->info->roundtrip_needed = true;
}
static void add_xdg_output_manager_v1_info(struct weston_info* info,
uint32_t id, uint32_t version) {
struct output_info* output;
struct xdg_output_manager_v1_info* manager =
(struct xdg_output_manager_v1_info*)calloc(1, sizeof *manager);
wl_list_init(&manager->outputs);
manager->info = info;
init_global_info(info, &manager->global, id,
zxdg_output_manager_v1_interface.name, version);
manager->global.print = print_xdg_output_manager_v1_info;
manager->global.destroy = destroy_xdg_output_manager_v1_info;
manager->manager = (struct zxdg_output_manager_v1*)wl_registry_bind(
info->registry, id, &zxdg_output_manager_v1_interface,
version > 2 ? 2 : version);
wl_list_for_each(output, &info->outputs, global_link) {
add_xdg_output_v1_info(manager, output);
}
info->xdg_output_manager_v1_info = manager;
}
static void output_handle_geometry(void* data, struct wl_output* wl_output,
int32_t x, int32_t y, int32_t physical_width,
int32_t physical_height, int32_t subpixel,
const char* make, const char* model,
int32_t output_transform) {}
static void output_handle_mode(void* data, struct wl_output* wl_output,
uint32_t flags, int32_t width, int32_t height,
int32_t refresh) {}
static void output_handle_done(void* data, struct wl_output* wl_output) {}
static void output_handle_scale(void* data, struct wl_output* wl_output,
int32_t scale) {
struct output_info* output = (struct output_info*)data;
output->scale = scale;
}
static const struct wl_output_listener output_listener = {
output_handle_geometry,
output_handle_mode,
output_handle_done,
output_handle_scale,
};
static void destroy_output_info(void* data) {
struct output_info* output = (struct output_info*)data;
wl_output_destroy(output->output);
}
static void add_output_info(struct weston_info* info, uint32_t id,
uint32_t version) {
struct output_info* output = (struct output_info*)calloc(1, sizeof *output);
init_global_info(info, &output->global, id, "wl_output", version);
output->global.print = print_output_info;
output->global.destroy = destroy_output_info;
output->version = MIN(version, 2);
output->scale = 1;
output->output = (struct wl_output*)wl_registry_bind(
info->registry, id, &wl_output_interface, output->version);
wl_output_add_listener(output->output, &output_listener, output);
info->roundtrip_needed = true;
wl_list_insert(&info->outputs, &output->global_link);
if (info->xdg_output_manager_v1_info) {
add_xdg_output_v1_info(info->xdg_output_manager_v1_info, output);
}
}
static void global_handler(void* data, struct wl_registry* registry,
uint32_t id, const char* interface,
uint32_t version) {
struct weston_info* info = (struct weston_info*)data;
if (!strcmp(interface, "wl_output")) {
add_output_info(info, id, version);
} else if (!strcmp(interface, zxdg_output_manager_v1_interface.name)) {
add_xdg_output_manager_v1_info(info, id, version);
}
}
static void global_remove_handler(void* data, struct wl_registry* registry,
uint32_t name) {}
static const struct wl_registry_listener registry_listener = {
global_handler, global_remove_handler};
static void print_infos(struct wl_list* infos) {
struct global_info* info;
wl_list_for_each(info, infos, link) { info->print(info); }
}
static void destroy_info(void* data) {
struct global_info* global = (struct global_info*)data;
global->destroy(data);
wl_list_remove(&global->link);
free(global->interface);
free(data);
}
static void destroy_infos(struct wl_list* infos) {
struct global_info *info, *tmp;
wl_list_for_each_safe(info, tmp, infos, link) { destroy_info(info); }
}
static void get_wayland_screen_info(struct wl_display* dpy) {
struct weston_info info = {0};
info.display = dpy;
info.xdg_output_manager_v1_info = NULL;
wl_list_init(&info.infos);
wl_list_init(&info.outputs);
info.registry = wl_display_get_registry(info.display);
wl_registry_add_listener(info.registry, &registry_listener, &info);
do {
info.roundtrip_needed = false;
wl_display_roundtrip(info.display);
} while (info.roundtrip_needed);
print_infos(&info.infos);
destroy_infos(&info.infos);
wl_registry_destroy(info.registry);
}
static void wayland_egltest() {
// NOTE: returns false to fall back to X11 when the Wayland socket doesn't
// exist but fails with record_error if something actually went wrong
@ -1252,7 +918,6 @@ static void wayland_egltest() {
if (!get_egl_status((EGLNativeDisplayType)dpy, true, false)) {
record_error("EGL test failed");
}
get_wayland_screen_info(dpy);
wl_display_disconnect(dpy);
record_value("TEST_TYPE\nEGL\n");

Просмотреть файл

@ -23,7 +23,6 @@
#include "mozilla/Observer.h"
#include "nsIObserver.h"
#include "nsIObserverService.h"
#include "nsIScreenManager.h"
#include "nsTArray.h"
#include "nsXULAppAPI.h"
#include "nsIXULAppInfo.h"
@ -34,6 +33,8 @@
#include "mozilla/gfx/GPUProcessManager.h"
#include "mozilla/gfx/Logging.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/widget/ScreenManager.h"
#include "mozilla/widget/Screen.h"
#include "gfxPlatform.h"
#include "gfxConfig.h"
@ -773,14 +774,7 @@ void GfxInfoBase::GetData() {
return;
}
nsCOMPtr<nsIScreenManager> manager =
do_GetService("@mozilla.org/gfx/screenmanager;1");
if (!manager) {
MOZ_ASSERT_UNREACHABLE("failed to get nsIScreenManager");
return;
}
manager->GetTotalScreenPixels(&mScreenPixels);
ScreenManager::GetSingleton().GetTotalScreenPixels(&mScreenPixels);
}
NS_IMETHODIMP
@ -1551,26 +1545,52 @@ void GfxInfoBase::RemoveCollector(GfxInfoCollectorBase* collector) {
}
}
nsresult GfxInfoBase::FindMonitors(JSContext* aCx, JS::HandleObject aOutArray) {
// If we have no platform specific implementation for detecting monitors, we
// can just get the screen size from gfxPlatform as the best guess.
if (!gfxPlatform::Initialized()) {
return NS_OK;
}
// If the screen size is empty, we are probably in xpcshell.
gfx::IntSize screenSize = gfxPlatform::GetPlatform()->GetScreenSize();
static void AppendMonitor(JSContext* aCx, widget::Screen& aScreen,
JS::HandleObject aOutArray, int32_t aIndex) {
JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
auto screenSize = aScreen.GetRect().Size();
JS::Rooted<JS::Value> screenWidth(aCx, JS::Int32Value(screenSize.width));
JS_SetProperty(aCx, obj, "screenWidth", screenWidth);
JS::Rooted<JS::Value> screenHeight(aCx, JS::Int32Value(screenSize.height));
JS_SetProperty(aCx, obj, "screenHeight", screenHeight);
// XXX Just preserving behavior since this is exposed to telemetry, but we
// could consider including this everywhere.
#ifdef XP_MACOSX
JS::Rooted<JS::Value> scale(
aCx, JS::NumberValue(aScreen.GetContentsScaleFactor()));
JS_SetProperty(aCx, obj, "scale", scale);
#endif
#ifdef XP_WIN
JS::Rooted<JS::Value> refreshRate(aCx,
JS::Int32Value(aScreen.GetRefreshRate()));
JS_SetProperty(aCx, obj, "refreshRate", refreshRate);
JS::Rooted<JS::Value> pseudoDisplay(
aCx, JS::BooleanValue(aScreen.GetIsPseudoDisplay()));
JS_SetProperty(aCx, obj, "pseudoDisplay", pseudoDisplay);
#endif
JS::Rooted<JS::Value> element(aCx, JS::ObjectValue(*obj));
JS_SetElement(aCx, aOutArray, 0, element);
JS_SetElement(aCx, aOutArray, aIndex, element);
}
nsresult GfxInfoBase::FindMonitors(JSContext* aCx, JS::HandleObject aOutArray) {
int32_t index = 0;
auto& sm = ScreenManager::GetSingleton();
for (auto& screen : sm.CurrentScreenList()) {
AppendMonitor(aCx, *screen, aOutArray, index++);
}
if (index == 0) {
// Ensure we return at least one monitor, this is needed for xpcshell.
RefPtr<Screen> screen = sm.GetPrimaryScreen();
AppendMonitor(aCx, *screen, aOutArray, index++);
}
return NS_OK;
}
@ -1588,9 +1608,6 @@ GfxInfoBase::GetMonitors(JSContext* aCx, JS::MutableHandleValue aResult) {
return NS_OK;
}
NS_IMETHODIMP
GfxInfoBase::RefreshMonitors() { return NS_ERROR_NOT_IMPLEMENTED; }
static inline bool SetJSPropertyString(JSContext* aCx,
JS::Handle<JSObject*> aObj,
const char* aProp, const char* aString) {
@ -1903,6 +1920,24 @@ GfxInfoBase::GetUsingGPUProcess(bool* aOutValue) {
return NS_OK;
}
NS_IMETHODIMP_(int32_t)
GfxInfoBase::GetMaxRefreshRate(bool* aMixed) {
if (aMixed) {
*aMixed = false;
}
int32_t maxRefreshRate = 0;
for (auto& screen : ScreenManager::GetSingleton().CurrentScreenList()) {
int32_t refreshRate = screen->GetRefreshRate();
if (aMixed && maxRefreshRate > 0 && maxRefreshRate != refreshRate) {
*aMixed = true;
}
maxRefreshRate = std::max(maxRefreshRate, refreshRate);
}
return maxRefreshRate > 0 ? maxRefreshRate : -1;
}
NS_IMETHODIMP
GfxInfoBase::ControlGPUProcessForXPCShell(bool aEnable, bool* _retval) {
gfxPlatform::GetPlatform();

Просмотреть файл

@ -56,7 +56,6 @@ class GfxInfoBase : public nsIGfxInfo,
NS_IMETHOD GetMonitors(JSContext* cx,
JS::MutableHandleValue _retval) override;
NS_IMETHOD RefreshMonitors() override;
NS_IMETHOD GetFailures(nsTArray<int32_t>& indices,
nsTArray<nsCString>& failures) override;
NS_IMETHOD_(void) LogFailure(const nsACString& failure) override;
@ -86,12 +85,7 @@ class GfxInfoBase : public nsIGfxInfo,
virtual nsresult Init();
NS_IMETHOD_(void) GetData() override;
NS_IMETHOD_(int32_t) GetMaxRefreshRate(bool* aMixed) override {
if (aMixed) {
*aMixed = false;
}
return -1;
}
NS_IMETHOD_(int32_t) GetMaxRefreshRate(bool* aMixed) override;
static void AddCollector(GfxInfoCollectorBase* collector);
static void RemoveCollector(GfxInfoCollectorBase* collector);

Просмотреть файл

@ -19,7 +19,7 @@ void InfoObject::DefineProperty(const char* name, int value) {
mOk = JS_DefineProperty(mCx, mObj, name, value, JSPROP_ENUMERATE);
}
void InfoObject::DefineProperty(const char* name, nsAString& value) {
void InfoObject::DefineProperty(const char* name, const nsAString& value) {
if (!mOk) return;
const nsString& flat = PromiseFlatString(value);

Просмотреть файл

@ -22,7 +22,7 @@ class MOZ_STACK_CLASS InfoObject {
public:
void DefineProperty(const char* name, int value);
void DefineProperty(const char* name, nsAString& value);
void DefineProperty(const char* name, const nsAString& value);
void DefineProperty(const char* name, const char* value);
private:

Просмотреть файл

@ -26,8 +26,9 @@ static hal::ScreenOrientation EffectiveOrientation(
Screen::Screen(LayoutDeviceIntRect aRect, LayoutDeviceIntRect aAvailRect,
uint32_t aPixelDepth, uint32_t aColorDepth,
DesktopToLayoutDeviceScale aContentsScale,
uint32_t aRefreshRate, DesktopToLayoutDeviceScale aContentsScale,
CSSToLayoutDeviceScale aDefaultCssScale, float aDPI,
IsPseudoDisplay aIsPseudoDisplay,
hal::ScreenOrientation aOrientation,
OrientationAngle aOrientationAngle)
: mRect(aRect),
@ -36,11 +37,13 @@ Screen::Screen(LayoutDeviceIntRect aRect, LayoutDeviceIntRect aAvailRect,
mAvailRectDisplayPix(RoundedToInt(aAvailRect / aContentsScale)),
mPixelDepth(aPixelDepth),
mColorDepth(aColorDepth),
mRefreshRate(aRefreshRate),
mContentsScale(aContentsScale),
mDefaultCssScale(aDefaultCssScale),
mDPI(aDPI),
mScreenOrientation(EffectiveOrientation(aOrientation, aRect)),
mOrientationAngle(aOrientationAngle) {}
mOrientationAngle(aOrientationAngle),
mIsPseudoDisplay(aIsPseudoDisplay == IsPseudoDisplay::Yes) {}
Screen::Screen(const dom::ScreenDetails& aScreen)
: mRect(aScreen.rect()),
@ -49,11 +52,13 @@ Screen::Screen(const dom::ScreenDetails& aScreen)
mAvailRectDisplayPix(aScreen.availRectDisplayPix()),
mPixelDepth(aScreen.pixelDepth()),
mColorDepth(aScreen.colorDepth()),
mRefreshRate(aScreen.refreshRate()),
mContentsScale(aScreen.contentsScaleFactor()),
mDefaultCssScale(aScreen.defaultCSSScaleFactor()),
mDPI(aScreen.dpi()),
mScreenOrientation(aScreen.orientation()),
mOrientationAngle(aScreen.orientationAngle()) {}
mOrientationAngle(aScreen.orientationAngle()),
mIsPseudoDisplay(aScreen.isPseudoDisplay()) {}
Screen::Screen(const Screen& aOther)
: mRect(aOther.mRect),
@ -62,17 +67,19 @@ Screen::Screen(const Screen& aOther)
mAvailRectDisplayPix(aOther.mAvailRectDisplayPix),
mPixelDepth(aOther.mPixelDepth),
mColorDepth(aOther.mColorDepth),
mRefreshRate(aOther.mRefreshRate),
mContentsScale(aOther.mContentsScale),
mDefaultCssScale(aOther.mDefaultCssScale),
mDPI(aOther.mDPI),
mScreenOrientation(aOther.mScreenOrientation),
mOrientationAngle(aOther.mOrientationAngle) {}
mOrientationAngle(aOther.mOrientationAngle),
mIsPseudoDisplay(aOther.mIsPseudoDisplay) {}
dom::ScreenDetails Screen::ToScreenDetails() const {
return dom::ScreenDetails(mRect, mRectDisplayPix, mAvailRect,
mAvailRectDisplayPix, mPixelDepth, mColorDepth,
mContentsScale, mDefaultCssScale, mDPI,
mScreenOrientation, mOrientationAngle);
return dom::ScreenDetails(
mRect, mRectDisplayPix, mAvailRect, mAvailRectDisplayPix, mPixelDepth,
mColorDepth, mRefreshRate, mContentsScale, mDefaultCssScale, mDPI,
mScreenOrientation, mOrientationAngle, mIsPseudoDisplay);
}
NS_IMETHODIMP
@ -138,4 +145,16 @@ Screen::GetDpi(float* aDPI) {
return NS_OK;
}
NS_IMETHODIMP
Screen::GetRefreshRate(int32_t* aRefreshRate) {
*aRefreshRate = mRefreshRate;
return NS_OK;
}
NS_IMETHODIMP
Screen::GetIsPseudoDisplay(bool* aIsPseudoDisplay) {
*aIsPseudoDisplay = mIsPseudoDisplay;
return NS_OK;
}
} // namespace mozilla::widget

Просмотреть файл

@ -25,11 +25,12 @@ class Screen final : public nsIScreen {
NS_DECL_NSISCREEN
using OrientationAngle = uint16_t;
enum class IsPseudoDisplay : bool { No, Yes };
Screen(LayoutDeviceIntRect aRect, LayoutDeviceIntRect aAvailRect,
uint32_t aPixelDepth, uint32_t aColorDepth,
uint32_t aPixelDepth, uint32_t aColorDepth, uint32_t aRefreshRate,
DesktopToLayoutDeviceScale aContentsScale,
CSSToLayoutDeviceScale aDefaultCssScale, float aDpi,
CSSToLayoutDeviceScale aDefaultCssScale, float aDpi, IsPseudoDisplay,
hal::ScreenOrientation = hal::ScreenOrientation::None,
OrientationAngle = 0);
explicit Screen(const dom::ScreenDetails& aScreenDetails);
@ -44,6 +45,15 @@ class Screen final : public nsIScreen {
float GetDPI() const { return mDPI; }
const LayoutDeviceIntRect& GetRect() const { return mRect; }
const LayoutDeviceIntRect& GetAvailRect() const { return mAvailRect; }
const DesktopToLayoutDeviceScale& GetContentsScaleFactor() const {
return mContentsScale;
}
const CSSToLayoutDeviceScale& GetDefaultCSSScaleFactor() const {
return mDefaultCssScale;
}
private:
virtual ~Screen() = default;
@ -53,11 +63,13 @@ class Screen final : public nsIScreen {
const DesktopIntRect mAvailRectDisplayPix;
const uint32_t mPixelDepth;
const uint32_t mColorDepth;
const uint32_t mRefreshRate;
const DesktopToLayoutDeviceScale mContentsScale;
const CSSToLayoutDeviceScale mDefaultCssScale;
const float mDPI;
const hal::ScreenOrientation mScreenOrientation;
const OrientationAngle mOrientationAngle;
const bool mIsPseudoDisplay;
};
} // namespace widget

Просмотреть файл

@ -129,9 +129,9 @@ ScreenManager::ScreenForRect(int32_t aX, int32_t aY, int32_t aWidth,
MOZ_LOG(sScreenLog, LogLevel::Warning,
("No screen available. This can happen in xpcshell."));
auto screen = MakeRefPtr<Screen>(
LayoutDeviceIntRect(), LayoutDeviceIntRect(), 0, 0,
LayoutDeviceIntRect(), LayoutDeviceIntRect(), 0, 0, 0,
DesktopToLayoutDeviceScale(), CSSToLayoutDeviceScale(), 96 /* dpi */,
hal::ScreenOrientation::None, 0);
Screen::IsPseudoDisplay::No, hal::ScreenOrientation::None, 0);
screen.forget(aOutScreen);
return NS_OK;
}
@ -215,10 +215,10 @@ 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, DesktopToLayoutDeviceScale(),
CSSToLayoutDeviceScale(), 96 /* dpi */,
hal::ScreenOrientation::None, 0);
return MakeAndAddRef<Screen>(
LayoutDeviceIntRect(), LayoutDeviceIntRect(), 0, 0, 0,
DesktopToLayoutDeviceScale(), CSSToLayoutDeviceScale(), 96 /* dpi */,
Screen::IsPseudoDisplay::No, hal::ScreenOrientation::None, 0);
}
return do_AddRef(mScreenList[0]);

Просмотреть файл

@ -44,6 +44,10 @@ class ScreenManager final : public nsIScreenManager {
void CopyScreensToRemote(mozilla::dom::ContentParent* aContentParent);
already_AddRefed<Screen> GetPrimaryScreen();
const nsTArray<RefPtr<Screen>>& CurrentScreenList() const {
return mScreenList;
}
private:
ScreenManager();
virtual ~ScreenManager();

Просмотреть файл

@ -227,12 +227,6 @@ void GfxInfo::EnsureInitialized() {
mGLStrings->Renderer().get(), mGLStrings->Version().get());
AddCrashReportAnnotations();
java::sdk::Rect::LocalRef screenrect = java::GeckoAppShell::GetScreenSize();
mScreenInfo.mScreenDimensions =
gfx::Rect(screenrect->Left(), screenrect->Top(), screenrect->Width(),
screenrect->Height());
mInitialized = true;
}
@ -358,29 +352,6 @@ GfxInfo::GetIsGPU2Active(bool* aIsGPU2Active) {
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
GfxInfo::GetDisplayInfo(nsTArray<nsString>& aDisplayInfo) {
EnsureInitialized();
nsString displayInfo;
displayInfo.AppendPrintf("%dx%d",
(int32_t)mScreenInfo.mScreenDimensions.width,
(int32_t)mScreenInfo.mScreenDimensions.height);
aDisplayInfo.AppendElement(displayInfo);
return NS_OK;
}
NS_IMETHODIMP
GfxInfo::GetDisplayWidth(nsTArray<uint32_t>& aDisplayWidth) {
aDisplayWidth.AppendElement((uint32_t)mScreenInfo.mScreenDimensions.width);
return NS_OK;
}
NS_IMETHODIMP
GfxInfo::GetDisplayHeight(nsTArray<uint32_t>& aDisplayHeight) {
aDisplayHeight.AppendElement((uint32_t)mScreenInfo.mScreenDimensions.height);
return NS_OK;
}
NS_IMETHODIMP
GfxInfo::GetDrmRenderDevice(nsACString& aDrmRenderDevice) {
return NS_ERROR_NOT_IMPLEMENTED;

Просмотреть файл

@ -57,9 +57,6 @@ class GfxInfo : public GfxInfoBase {
nsAString& aAdapterDriverVersion) override;
NS_IMETHOD GetAdapterDriverDate2(nsAString& aAdapterDriverDate) override;
NS_IMETHOD GetIsGPU2Active(bool* aIsGPU2Active) override;
NS_IMETHOD GetDisplayInfo(nsTArray<nsString>& aDisplayInfo) override;
NS_IMETHOD GetDisplayWidth(nsTArray<uint32_t>& aDisplayWidth) override;
NS_IMETHOD GetDisplayHeight(nsTArray<uint32_t>& aDisplayHeight) override;
NS_IMETHOD GetDrmRenderDevice(nsACString& aDrmRenderDevice) override;
using GfxInfoBase::GetFeatureStatus;
using GfxInfoBase::GetFeatureSuggestedDriverVersion;
@ -85,11 +82,6 @@ class GfxInfo : public GfxInfoBase {
OperatingSystem* aOS = nullptr) override;
virtual const nsTArray<GfxDriverInfo>& GetGfxDriverInfo() override;
private:
struct ScreenInfo {
gfx::Rect mScreenDimensions;
};
private:
void AddCrashReportAnnotations();
int32_t WebRtcHwVp8EncodeSupported();
@ -107,7 +99,6 @@ class GfxInfo : public GfxInfoBase {
nsCString mOSVersion;
uint32_t mOSVersionInteger;
int32_t mSDKVersion;
ScreenInfo mScreenInfo;
};
} // namespace widget

Просмотреть файл

@ -40,9 +40,10 @@ static already_AddRefed<Screen> MakePrimaryScreen() {
auto orientation =
hal::ScreenOrientation(java::GeckoAppShell::GetScreenOrientation());
uint16_t angle = java::GeckoAppShell::GetScreenAngle();
return MakeAndAddRef<Screen>(
bounds, bounds, depth, depth, DesktopToLayoutDeviceScale(density),
CSSToLayoutDeviceScale(1.0f), dpi, orientation, angle);
return MakeAndAddRef<Screen>(bounds, bounds, depth, depth, 0,
DesktopToLayoutDeviceScale(density),
CSSToLayoutDeviceScale(1.0f), dpi,
Screen::IsPseudoDisplay::No, orientation, angle);
}
ScreenHelperAndroid::ScreenHelperAndroid() {

Просмотреть файл

@ -50,9 +50,6 @@ class GfxInfo : public GfxInfoBase {
nsAString& aAdapterDriverVersion) override;
NS_IMETHOD GetAdapterDriverDate2(nsAString& aAdapterDriverDate) override;
NS_IMETHOD GetIsGPU2Active(bool* aIsGPU2Active) override;
NS_IMETHOD GetDisplayInfo(nsTArray<nsString>& aDisplayInfo) override;
NS_IMETHOD GetDisplayWidth(nsTArray<uint32_t>& aDisplayWidth) override;
NS_IMETHOD GetDisplayHeight(nsTArray<uint32_t>& aDisplayHeight) override;
NS_IMETHOD GetDrmRenderDevice(nsACString& aDrmRenderDevice) override;
using GfxInfoBase::GetFeatureStatus;
@ -67,8 +64,6 @@ class GfxInfo : public GfxInfoBase {
virtual uint32_t OperatingSystemVersion() override { return mOSXVersion; }
nsresult FindMonitors(JSContext* cx, JS::HandleObject array) override;
protected:
virtual ~GfxInfo() {}

Просмотреть файл

@ -358,41 +358,6 @@ GfxInfo::GetAdapterSubsysID(nsAString& aAdapterSubsysID) { return NS_ERROR_FAILU
NS_IMETHODIMP
GfxInfo::GetAdapterSubsysID2(nsAString& aAdapterSubsysID) { return NS_ERROR_FAILURE; }
/* readonly attribute Array<DOMString> displayInfo; */
NS_IMETHODIMP
GfxInfo::GetDisplayInfo(nsTArray<nsString>& aDisplayInfo) {
nsAutoreleasePool localPool;
for (NSScreen* screen in [NSScreen screens]) {
NSRect rect = [screen frame];
nsString desc;
desc.AppendPrintf("%dx%d scale:%f", (int32_t)rect.size.width, (int32_t)rect.size.height,
nsCocoaUtils::GetBackingScaleFactor(screen));
aDisplayInfo.AppendElement(desc);
}
return NS_OK;
}
NS_IMETHODIMP
GfxInfo::GetDisplayWidth(nsTArray<uint32_t>& aDisplayWidth) {
nsAutoreleasePool localPool;
for (NSScreen* screen in [NSScreen screens]) {
NSRect rect = [screen frame];
aDisplayWidth.AppendElement((uint32_t)rect.size.width);
}
return NS_OK;
}
NS_IMETHODIMP
GfxInfo::GetDisplayHeight(nsTArray<uint32_t>& aDisplayHeight) {
nsAutoreleasePool localPool;
for (NSScreen* screen in [NSScreen screens]) {
NSRect rect = [screen frame];
aDisplayHeight.AppendElement((uint32_t)rect.size.height);
}
return NS_OK;
}
NS_IMETHODIMP
GfxInfo::GetDrmRenderDevice(nsACString& aDrmRenderDevice) { return NS_ERROR_NOT_IMPLEMENTED; }
@ -504,32 +469,6 @@ nsresult GfxInfo::GetFeatureStatusImpl(int32_t aFeature, int32_t* aStatus,
aFailureId, &os);
}
nsresult GfxInfo::FindMonitors(JSContext* aCx, JS::HandleObject aOutArray) {
nsAutoreleasePool localPool;
// Getting the refresh rate is a little hard on OS X. We could use
// CVDisplayLinkGetNominalOutputVideoRefreshPeriod, but that's a little
// involved. Ideally we could query it from vsync. For now, we leave it out.
int32_t deviceCount = 0;
for (NSScreen* screen in [NSScreen screens]) {
NSRect rect = [screen frame];
JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
JS::Rooted<JS::Value> screenWidth(aCx, JS::Int32Value((int)rect.size.width));
JS_SetProperty(aCx, obj, "screenWidth", screenWidth);
JS::Rooted<JS::Value> screenHeight(aCx, JS::Int32Value((int)rect.size.height));
JS_SetProperty(aCx, obj, "screenHeight", screenHeight);
JS::Rooted<JS::Value> scale(aCx, JS::NumberValue(nsCocoaUtils::GetBackingScaleFactor(screen)));
JS_SetProperty(aCx, obj, "scale", scale);
JS::Rooted<JS::Value> element(aCx, JS::ObjectValue(*obj));
JS_SetElement(aCx, aOutArray, deviceCount++, element);
}
return NS_OK;
}
#ifdef DEBUG
// Implement nsIGfxInfoDebug

Просмотреть файл

@ -120,8 +120,12 @@ static already_AddRefed<Screen> MakeScreen(NSScreen* aScreen) {
rect.height, availRect.x, availRect.y, availRect.width, availRect.height, pixelDepth,
contentsScaleFactor.scale, defaultCssScaleFactor.scale, dpi));
RefPtr<Screen> screen = new Screen(rect, availRect, pixelDepth, pixelDepth, contentsScaleFactor,
defaultCssScaleFactor, dpi);
// Getting the refresh rate is a little hard on OS X. We could use
// CVDisplayLinkGetNominalOutputVideoRefreshPeriod, but that's a little
// involved. Ideally we could query it from vsync. For now, we leave it out.
RefPtr<Screen> screen =
new Screen(rect, availRect, pixelDepth, pixelDepth, 0, contentsScaleFactor,
defaultCssScaleFactor, dpi, Screen::IsPseudoDisplay::No);
return screen.forget();
NS_OBJC_END_TRY_BLOCK_RETURN(nullptr);

Просмотреть файл

@ -159,7 +159,6 @@ void GfxInfo::GetData() {
nsCString mesaAccelerated;
// Available if using a DRI-based libGL stack.
nsCString driDriver;
nsCString screenInfo;
nsCString adapterRam;
nsCString drmRenderDevice;
@ -202,8 +201,6 @@ void GfxInfo::GetData() {
stringToFill = &ddxDriver;
} else if (!strcmp(line, "DRI_DRIVER")) {
stringToFill = &driDriver;
} else if (!strcmp(line, "SCREEN_INFO")) {
stringToFill = &screenInfo;
} else if (!strcmp(line, "PCI_VENDOR_ID")) {
stringToFill = pciVendors.AppendElement();
} else if (!strcmp(line, "PCI_DEVICE_ID")) {
@ -340,24 +337,6 @@ void GfxInfo::GetData() {
NS_WARNING("Failed to detect GL vendor!");
}
if (!screenInfo.IsEmpty()) {
PRInt32 start = 0;
PRInt32 loc = screenInfo.Find(";", PR_FALSE, start);
while (loc != kNotFound) {
int isDefault = 0;
nsCString line(screenInfo.get() + start, loc - start);
ScreenInfo info{};
if (sscanf(line.get(), "%ux%u:%u", &info.mWidth, &info.mHeight,
&isDefault) == 3) {
info.mIsDefault = isDefault != 0;
mScreenInfo.AppendElement(info);
}
start = loc + 1;
loc = screenInfo.Find(";", PR_FALSE, start);
}
}
if (!adapterRam.IsEmpty()) {
mAdapterRAM = (uint32_t)atoi(adapterRam.get());
}
@ -1136,36 +1115,6 @@ GfxInfo::GetAdapterSubsysID2(nsAString& aAdapterSubsysID) {
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
GfxInfo::GetDisplayInfo(nsTArray<nsString>& aDisplayInfo) {
GetData();
for (auto screenInfo : mScreenInfo) {
nsString infoString;
infoString.AppendPrintf("%dx%d %s", screenInfo.mWidth, screenInfo.mHeight,
screenInfo.mIsDefault ? "default" : "");
aDisplayInfo.AppendElement(infoString);
}
return aDisplayInfo.IsEmpty() ? NS_ERROR_FAILURE : NS_OK;
}
NS_IMETHODIMP
GfxInfo::GetDisplayWidth(nsTArray<uint32_t>& aDisplayWidth) {
for (auto screenInfo : mScreenInfo) {
aDisplayWidth.AppendElement((uint32_t)screenInfo.mWidth);
}
return NS_OK;
}
NS_IMETHODIMP
GfxInfo::GetDisplayHeight(nsTArray<uint32_t>& aDisplayHeight) {
for (auto screenInfo : mScreenInfo) {
aDisplayHeight.AppendElement((uint32_t)screenInfo.mHeight);
}
return NS_OK;
}
NS_IMETHODIMP
GfxInfo::GetIsGPU2Active(bool* aIsGPU2Active) {
// This is never the case, as the active GPU should be the primary GPU.

Просмотреть файл

@ -48,9 +48,6 @@ class GfxInfo final : public GfxInfoBase {
nsAString& aAdapterDriverVersion) override;
NS_IMETHOD GetAdapterDriverDate2(nsAString& aAdapterDriverDate) override;
NS_IMETHOD GetIsGPU2Active(bool* aIsGPU2Active) override;
NS_IMETHOD GetDisplayInfo(nsTArray<nsString>& aDisplayInfo) override;
NS_IMETHOD GetDisplayWidth(nsTArray<uint32_t>& aDisplayWidth) override;
NS_IMETHOD GetDisplayHeight(nsTArray<uint32_t>& aDisplayHeight) override;
NS_IMETHOD GetDrmRenderDevice(nsACString& aDrmRenderDevice) override;
using GfxInfoBase::GetFeatureStatus;
using GfxInfoBase::GetFeatureSuggestedDriverVersion;

Просмотреть файл

@ -39,10 +39,23 @@ static LazyLogModule sScreenLog("WidgetScreen");
using GdkMonitor = struct _GdkMonitor;
static UniquePtr<ScreenGetter> gScreenGetter;
struct MonitorConfig {
int id = 0;
int x = 0;
int y = 0;
int width_mm = 0;
int height_mm = 0;
int width = 0;
int height = 0;
int scale = 0;
int refresh = 0;
explicit MonitorConfig(int aId) : id(aId) {}
};
static void monitors_changed(GdkScreen* aScreen, gpointer aClosure) {
LOG_SCREEN("Received monitors-changed event");
ScreenGetterGtk* self = static_cast<ScreenGetterGtk*>(aClosure);
auto* self = static_cast<ScreenGetterGtk*>(aClosure);
self->RefreshScreens();
}
@ -144,6 +157,25 @@ static already_AddRefed<Screen> MakeScreenGtk(GdkScreen* aScreen,
LayoutDeviceIntRect rect;
gint refreshRate = [&] {
// Since gtk 3.22
static auto s_gdk_display_get_monitor = (GdkMonitor * (*)(GdkDisplay*, int))
dlsym(RTLD_DEFAULT, "gdk_display_get_monitor");
static auto s_gdk_monitor_get_refresh_rate = (int (*)(GdkMonitor*))dlsym(
RTLD_DEFAULT, "gdk_monitor_get_refresh_rate");
if (!s_gdk_monitor_get_refresh_rate) {
return 0;
}
GdkMonitor* monitor =
s_gdk_display_get_monitor(gdk_display_get_default(), aMonitorNum);
if (!monitor) {
return 0;
}
// Convert to Hz.
return NSToIntRound(s_gdk_monitor_get_refresh_rate(monitor) / 1000.0f);
}();
GdkRectangle workarea;
gdk_screen_get_monitor_workarea(aScreen, aMonitorNum, &workarea);
LayoutDeviceIntRect availRect(workarea.x * geometryScaleFactor,
@ -183,11 +215,12 @@ static already_AddRefed<Screen> MakeScreenGtk(GdkScreen* aScreen,
LOG_SCREEN(
"New monitor %d size [%d,%d -> %d x %d] depth %d scale %f CssScale %f "
"DPI %f ]",
"DPI %f refresh %d ]",
aMonitorNum, rect.x, rect.y, rect.width, rect.height, pixelDepth,
contentsScale.scale, defaultCssScale.scale, dpi);
contentsScale.scale, defaultCssScale.scale, dpi, refreshRate);
return MakeAndAddRef<Screen>(rect, availRect, pixelDepth, pixelDepth,
contentsScale, defaultCssScale, dpi);
refreshRate, contentsScale, defaultCssScale, dpi,
Screen::IsPseudoDisplay::No);
}
void ScreenGetterGtk::RefreshScreens() {
@ -211,7 +244,7 @@ static void output_handle_geometry(void* data, struct wl_output* wl_output,
int physical_height, int subpixel,
const char* make, const char* model,
int32_t transform) {
MonitorConfig* monitor = (MonitorConfig*)data;
auto* monitor = static_cast<MonitorConfig*>(data);
LOG_SCREEN(
"wl_output: geometry position %d %d physical size %d %d, subpixel %d, "
"transform %d",
@ -229,7 +262,7 @@ static void output_handle_done(void* data, struct wl_output* wl_output) {
static void output_handle_scale(void* data, struct wl_output* wl_output,
int32_t scale) {
MonitorConfig* monitor = (MonitorConfig*)data;
auto* monitor = static_cast<MonitorConfig*>(data);
LOG_SCREEN("wl_output: scale %d", scale);
monitor->scale = scale;
}
@ -237,13 +270,13 @@ static void output_handle_scale(void* data, struct wl_output* wl_output,
static void output_handle_mode(void* data, struct wl_output* wl_output,
uint32_t flags, int width, int height,
int refresh) {
MonitorConfig* monitor = (MonitorConfig*)data;
auto* monitor = static_cast<MonitorConfig*>(data);
LOG_SCREEN("wl_output: mode output size %d x %d refresh %d", width, height,
refresh);
if ((flags & WL_OUTPUT_MODE_CURRENT) == 0) return;
monitor->refresh = NSToIntRound(refresh / 1000.0f);
monitor->width = width;
monitor->height = height;
}
@ -258,7 +291,7 @@ static const struct wl_output_listener output_listener = {
static void screen_registry_handler(void* data, wl_registry* registry,
uint32_t id, const char* interface,
uint32_t version) {
ScreenGetterWayland* getter = static_cast<ScreenGetterWayland*>(data);
auto* getter = static_cast<ScreenGetterWayland*>(data);
if (strcmp(interface, "wl_output") == 0 && version > 1) {
auto* output =
WaylandRegistryBind<wl_output>(registry, id, &wl_output_interface, 2);
@ -308,6 +341,8 @@ bool ScreenGetterWayland::RemoveMonitorConfig(int aId) {
return false;
}
ScreenGetterWayland::ScreenGetterWayland() = default;
ScreenGetterWayland::~ScreenGetterWayland() {
g_clear_pointer(&mRegistry, wl_registry_destroy);
}
@ -347,11 +382,12 @@ already_AddRefed<Screen> ScreenGetterWayland::MakeScreenWayland(gint aMonitor) {
LOG_SCREEN(
"Monitor %d [%d %d -> %d x %d depth %d content scale %f css scale %f "
"DPI %f]",
"DPI %f, refresh %d]",
aMonitor, rect.x, rect.y, rect.width, rect.height, pixelDepth,
contentsScale.scale, defaultCssScale.scale, dpi);
contentsScale.scale, defaultCssScale.scale, dpi, monitor->refresh);
return MakeAndAddRef<Screen>(rect, rect, pixelDepth, pixelDepth,
contentsScale, defaultCssScale, dpi);
monitor->refresh, contentsScale, defaultCssScale,
dpi, Screen::IsPseudoDisplay::No);
}
void ScreenGetterWayland::RefreshScreens() {
@ -405,7 +441,7 @@ int ScreenGetterWayland::GetMonitorForWindow(nsWindow* aWindow) {
// we can rely on Gtk work area start position to match wl_output.
if (mMonitors[i]->x == workArea.x && mMonitors[i]->y == workArea.y) {
LOG_SCREEN(" monitor %d values %d %d -> %d x %d", i, mMonitors[i]->x,
mMonitors[i]->y, mMonitors[i]->width, mMonitors[i]->height);
mMonitors[i]->y, mMonitors[i]->width, mMonitors[i]->height);
return i;
}
}

Просмотреть файл

@ -55,24 +55,12 @@ class ScreenGetterGtk : public ScreenGetter {
};
class ScreenGetterWayland;
struct MonitorConfig {
int id = 0;
int x = 0;
int y = 0;
int width_mm = 0;
int height_mm = 0;
int width = 0;
int height = 0;
int scale = 0;
explicit MonitorConfig(int aId) : id(aId){};
};
struct MonitorConfig;
#ifdef MOZ_WAYLAND
class ScreenGetterWayland : public ScreenGetter {
public:
ScreenGetterWayland() : mRegistry(){};
ScreenGetterWayland();
~ScreenGetterWayland();
void Init();
@ -91,7 +79,7 @@ class ScreenGetterWayland : public ScreenGetter {
bool MonitorUsesNonIntegerScale(int aMonitor);
private:
void* mRegistry;
void* mRegistry = nullptr;
// We use UniquePtr<> here to ensure that MonitorConfig is heap-allocated
// so it's not invalidated by any change to mMonitors that could happen in the
// meantime.

Просмотреть файл

@ -32,9 +32,9 @@ LayoutDeviceIntRect HeadlessScreenHelper::GetScreenRect() {
HeadlessScreenHelper::HeadlessScreenHelper() {
AutoTArray<RefPtr<Screen>, 1> screenList;
LayoutDeviceIntRect rect = GetScreenRect();
auto ret =
MakeRefPtr<Screen>(rect, rect, 24, 24, DesktopToLayoutDeviceScale(),
CSSToLayoutDeviceScale(), 96.0f);
auto ret = MakeRefPtr<Screen>(
rect, rect, 24, 24, 0, DesktopToLayoutDeviceScale(),
CSSToLayoutDeviceScale(), 96.0f, Screen::IsPseudoDisplay::No);
screenList.AppendElement(ret.forget());
ScreenManager::Refresh(std::move(screenList));
}

Просмотреть файл

@ -78,13 +78,6 @@ interface nsIGfxInfo : nsISupports
readonly attribute ACString drmRenderDevice;
/**
* Information about display devices
*/
readonly attribute Array<AString> displayInfo;
readonly attribute Array<unsigned long> displayWidth;
readonly attribute Array<unsigned long> displayHeight;
/**
* Returns an array of objects describing each monitor. Guaranteed properties
* are "screenWidth" and "screenHeight". This is only implemented on Desktop.
@ -96,8 +89,6 @@ interface nsIGfxInfo : nsISupports
[implicit_jscontext]
jsval getMonitors();
void refreshMonitors();
Array<ACString> getFailures(out Array<long> indices);
[noscript, notxpcom] void logFailure(in ACString failure);
@ -234,7 +225,7 @@ interface nsIGfxInfo : nsISupports
/**
* Maximum refresh rate among detected monitors. -1 if unknown. aMixed is set
* to true if we know there are multiple displays and they have different
* refresh rates, else false.
* refresh rates, else false. The returned value is in Hz.
*/
[noscript, notxpcom] long GetMaxRefreshRate(out boolean aMixed);

Просмотреть файл

@ -62,8 +62,8 @@ interface nsIScreen : nsISupports
}
%}
readonly attribute long pixelDepth;
readonly attribute long colorDepth;
[infallible] readonly attribute long pixelDepth;
[infallible] readonly attribute long colorDepth;
/**
* The number of device pixels per desktop pixel for this screen (for
@ -107,5 +107,9 @@ interface nsIScreen : nsISupports
/**
* The DPI of the screen.
*/
readonly attribute float dpi;
[infallible] readonly attribute float dpi;
/** The target screen refresh rate, in Hz, or 0 if unknown */
[infallible] readonly attribute long refreshRate;
[infallible] readonly attribute boolean isPseudoDisplay;
};

Просмотреть файл

@ -83,24 +83,6 @@ GfxInfo::GetHasBattery(bool* aHasBattery) {
return NS_OK;
}
int32_t GfxInfo::GetMaxRefreshRate(bool* aMixed) {
AssertNotWin32kLockdown();
int32_t maxRefreshRate = -1;
if (aMixed) {
*aMixed = false;
}
for (auto displayInfo : mDisplayInfo) {
int32_t refreshRate = int32_t(displayInfo.mRefreshRate);
if (aMixed && maxRefreshRate > 0 && maxRefreshRate != refreshRate) {
*aMixed = true;
}
maxRefreshRate = std::max(maxRefreshRate, refreshRate);
}
return maxRefreshRate;
}
NS_IMETHODIMP
GfxInfo::GetEmbeddedInFirefoxReality(bool* aEmbeddedInFirefoxReality) {
*aEmbeddedInFirefoxReality = gfxVars::FxREmbedded();
@ -882,9 +864,6 @@ nsresult GfxInfo::Init() {
}
}
// Get monitor information
RefreshMonitors();
const char* spoofedDriverVersionString =
PR_GetEnv("MOZ_GFX_SPOOF_DRIVER_VERSION");
if (spoofedDriverVersionString) {
@ -922,45 +901,6 @@ GfxInfo::GetAdapterDescription2(nsAString& aAdapterDescription) {
return NS_OK;
}
NS_IMETHODIMP
GfxInfo::RefreshMonitors() {
AssertNotWin32kLockdown();
mDisplayInfo.Clear();
for (int deviceIndex = 0;; deviceIndex++) {
DISPLAY_DEVICEW device;
device.cb = sizeof(device);
if (!::EnumDisplayDevicesW(nullptr, deviceIndex, &device, 0)) {
break;
}
if (!(device.StateFlags & DISPLAY_DEVICE_ACTIVE)) {
continue;
}
DEVMODEW mode;
mode.dmSize = sizeof(mode);
mode.dmDriverExtra = 0;
if (!::EnumDisplaySettingsW(device.DeviceName, ENUM_CURRENT_SETTINGS,
&mode)) {
continue;
}
DisplayInfo displayInfo;
displayInfo.mScreenWidth = mode.dmPelsWidth;
displayInfo.mScreenHeight = mode.dmPelsHeight;
displayInfo.mRefreshRate = mode.dmDisplayFrequency;
displayInfo.mIsPseudoDisplay =
!!(device.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER);
displayInfo.mDeviceString = device.DeviceString;
mDisplayInfo.AppendElement(displayInfo);
}
return NS_OK;
}
NS_IMETHODIMP
GfxInfo::GetAdapterRAM(uint32_t* aAdapterRAM) {
AssertNotWin32kLockdown();
@ -1126,43 +1066,6 @@ GfxInfo::GetIsGPU2Active(bool* aIsGPU2Active) {
return NS_OK;
}
NS_IMETHODIMP
GfxInfo::GetDisplayInfo(nsTArray<nsString>& aDisplayInfo) {
AssertNotWin32kLockdown();
for (auto displayInfo : mDisplayInfo) {
nsString value;
value.AppendPrintf("%dx%d@%dHz %s %s", displayInfo.mScreenWidth,
displayInfo.mScreenHeight, displayInfo.mRefreshRate,
displayInfo.mIsPseudoDisplay ? "Pseudo Display :" : ":",
NS_ConvertUTF16toUTF8(displayInfo.mDeviceString).get());
aDisplayInfo.AppendElement(value);
}
return NS_OK;
}
NS_IMETHODIMP
GfxInfo::GetDisplayWidth(nsTArray<uint32_t>& aDisplayWidth) {
AssertNotWin32kLockdown();
for (auto displayInfo : mDisplayInfo) {
aDisplayWidth.AppendElement((uint32_t)displayInfo.mScreenWidth);
}
return NS_OK;
}
NS_IMETHODIMP
GfxInfo::GetDisplayHeight(nsTArray<uint32_t>& aDisplayHeight) {
AssertNotWin32kLockdown();
for (auto displayInfo : mDisplayInfo) {
aDisplayHeight.AppendElement((uint32_t)displayInfo.mScreenHeight);
}
return NS_OK;
}
NS_IMETHODIMP
GfxInfo::GetDrmRenderDevice(nsACString& aDrmRenderDevice) {
return NS_ERROR_NOT_IMPLEMENTED;
@ -2060,35 +1963,6 @@ nsresult GfxInfo::GetFeatureStatusImpl(
aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, aFailureId, &os);
}
nsresult GfxInfo::FindMonitors(JSContext* aCx, JS::HandleObject aOutArray) {
AssertNotWin32kLockdown();
int deviceCount = 0;
for (auto displayInfo : mDisplayInfo) {
JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
JS::Rooted<JS::Value> screenWidth(aCx,
JS::Int32Value(displayInfo.mScreenWidth));
JS_SetProperty(aCx, obj, "screenWidth", screenWidth);
JS::Rooted<JS::Value> screenHeight(
aCx, JS::Int32Value(displayInfo.mScreenHeight));
JS_SetProperty(aCx, obj, "screenHeight", screenHeight);
JS::Rooted<JS::Value> refreshRate(aCx,
JS::Int32Value(displayInfo.mRefreshRate));
JS_SetProperty(aCx, obj, "refreshRate", refreshRate);
JS::Rooted<JS::Value> pseudoDisplay(
aCx, JS::BooleanValue(displayInfo.mIsPseudoDisplay));
JS_SetProperty(aCx, obj, "pseudoDisplay", pseudoDisplay);
JS::Rooted<JS::Value> element(aCx, JS::ObjectValue(*obj));
JS_SetElement(aCx, aOutArray, deviceCount++, element);
}
return NS_OK;
}
void GfxInfo::DescribeFeatures(JSContext* aCx, JS::Handle<JSObject*> aObj) {
// Add the platform neutral features
GfxInfoBase::DescribeFeatures(aCx, aObj);

Просмотреть файл

@ -52,33 +52,17 @@ class GfxInfo : public GfxInfoBase {
nsAString& aAdapterDriverVersion) override;
NS_IMETHOD GetAdapterDriverDate2(nsAString& aAdapterDriverDate) override;
NS_IMETHOD GetIsGPU2Active(bool* aIsGPU2Active) override;
NS_IMETHOD GetDisplayInfo(nsTArray<nsString>& aDisplayInfo) override;
NS_IMETHOD GetDisplayWidth(nsTArray<uint32_t>& aDisplayWidth) override;
NS_IMETHOD GetDisplayHeight(nsTArray<uint32_t>& aDisplayHeight) override;
NS_IMETHOD GetDrmRenderDevice(nsACString& aDrmRenderDevice) override;
NS_IMETHOD RefreshMonitors() override;
NS_IMETHOD_(int32_t) GetMaxRefreshRate(bool* aMixed) override;
uint32_t OperatingSystemVersion() override { return mWindowsVersion; }
uint32_t OperatingSystemBuild() override { return mWindowsBuildNumber; }
nsresult FindMonitors(JSContext* cx, JS::HandleObject array) override;
#ifdef DEBUG
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIGFXINFODEBUG
#endif
private:
struct DisplayInfo {
uint32_t mScreenWidth;
uint32_t mScreenHeight;
uint32_t mRefreshRate;
bool mIsPseudoDisplay;
nsString mDeviceString;
};
~GfxInfo() = default;
// Disallow copy/move
@ -110,7 +94,6 @@ class GfxInfo : public GfxInfoBase {
uint32_t mWindowsVersion = 0;
uint32_t mWindowsBuildNumber = 0;
uint32_t mActiveGPUIndex = 0; // This must be 0 or 1
nsTArray<DisplayInfo> mDisplayInfo;
bool mHasDualGPU = false;
bool mHasDriverVersionMismatch = false;
bool mHasBattery = false;

Просмотреть файл

@ -15,6 +15,65 @@ static mozilla::LazyLogModule sScreenLog("WidgetScreen");
namespace mozilla {
namespace widget {
static void GetDisplayInfo(const char16ptr_t aName,
hal::ScreenOrientation& aOrientation,
uint16_t& aAngle, bool& aIsPseudoDisplay,
uint32_t& aRefreshRate) {
DISPLAY_DEVICEW displayDevice = {.cb = sizeof(DISPLAY_DEVICEW)};
// XXX Is the pseudodisplay status really useful?
aIsPseudoDisplay =
EnumDisplayDevicesW(aName, 0, &displayDevice, 0) &&
(displayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER);
DEVMODEW mode = {.dmSize = sizeof(DEVMODEW)};
if (!EnumDisplaySettingsW(aName, ENUM_CURRENT_SETTINGS, &mode)) {
return;
}
MOZ_ASSERT(mode.dmFields & DM_DISPLAYORIENTATION);
aRefreshRate = mode.dmDisplayFrequency;
// conver to default/natural size
if (mode.dmDisplayOrientation == DMDO_90 ||
mode.dmDisplayOrientation == DMDO_270) {
DWORD temp = mode.dmPelsHeight;
mode.dmPelsHeight = mode.dmPelsWidth;
mode.dmPelsWidth = temp;
}
bool defaultIsLandscape = mode.dmPelsWidth >= mode.dmPelsHeight;
switch (mode.dmDisplayOrientation) {
case DMDO_DEFAULT:
aOrientation = defaultIsLandscape
? hal::ScreenOrientation::LandscapePrimary
: hal::ScreenOrientation::PortraitPrimary;
aAngle = 0;
break;
case DMDO_90:
aOrientation = defaultIsLandscape
? hal::ScreenOrientation::PortraitPrimary
: hal::ScreenOrientation::LandscapeSecondary;
aAngle = 270;
break;
case DMDO_180:
aOrientation = defaultIsLandscape
? hal::ScreenOrientation::LandscapeSecondary
: hal::ScreenOrientation::PortraitSecondary;
aAngle = 180;
break;
case DMDO_270:
aOrientation = defaultIsLandscape
? hal::ScreenOrientation::PortraitSecondary
: hal::ScreenOrientation::LandscapePrimary;
aAngle = 90;
break;
default:
MOZ_ASSERT_UNREACHABLE("Unexpected angle");
break;
}
}
BOOL CALLBACK CollectMonitors(HMONITOR aMon, HDC, LPRECT, LPARAM ioParam) {
auto screens = reinterpret_cast<nsTArray<RefPtr<Screen>>*>(ioParam);
BOOL success = FALSE;
@ -57,17 +116,22 @@ BOOL CALLBACK CollectMonitors(HMONITOR aMon, HDC, LPRECT, LPARAM ioParam) {
float dpi = WinUtils::MonitorDPI(aMon);
hal::ScreenOrientation orientation;
uint16_t angle;
WinUtils::GetDisplayOrientation(info.szDevice, orientation, angle);
auto orientation = hal::ScreenOrientation::None;
uint16_t angle = 0;
bool isPseudoDisplay = false;
uint32_t refreshRate = 0;
GetDisplayInfo(info.szDevice, orientation, angle, isPseudoDisplay,
refreshRate);
MOZ_LOG(sScreenLog, LogLevel::Debug,
("New screen [%s (%s) %d %f %f %f %d %d]", ToString(rect).c_str(),
ToString(availRect).c_str(), pixelDepth, contentsScaleFactor.scale,
defaultCssScaleFactor.scale, dpi, orientation, angle));
auto screen =
new Screen(rect, availRect, pixelDepth, pixelDepth, contentsScaleFactor,
defaultCssScaleFactor, dpi, orientation, angle);
("New screen [%s (%s) %d %u %f %f %f %d %d %d]",
ToString(rect).c_str(), ToString(availRect).c_str(), pixelDepth,
refreshRate, contentsScaleFactor.scale, defaultCssScaleFactor.scale,
dpi, isPseudoDisplay, orientation, angle));
auto screen = MakeRefPtr<Screen>(
rect, availRect, pixelDepth, pixelDepth, refreshRate, contentsScaleFactor,
defaultCssScaleFactor, dpi, Screen::IsPseudoDisplay(isPseudoDisplay),
orientation, angle);
if (info.dwFlags & MONITORINFOF_PRIMARY) {
// The primary monitor must be the first element of the screen list.
screens->InsertElementAt(0, std::move(screen));

Просмотреть файл

@ -2318,58 +2318,5 @@ void WinUtils::EnableWindowOcclusion(const bool aEnable) {
reinterpret_cast<LPARAM>(&aEnable));
}
void WinUtils::GetDisplayOrientation(const char16ptr_t aName,
hal::ScreenOrientation& aOrientation,
uint16_t& aAngle) {
aOrientation = hal::ScreenOrientation::None;
aAngle = 0;
DEVMODEW mode = {.dmSize = sizeof(DEVMODEW)};
if (!EnumDisplaySettingsW(aName, ENUM_CURRENT_SETTINGS, &mode)) {
return;
}
MOZ_ASSERT(mode.dmFields & DM_DISPLAYORIENTATION);
// conver to default/natural size
if (mode.dmDisplayOrientation == DMDO_90 ||
mode.dmDisplayOrientation == DMDO_270) {
DWORD temp = mode.dmPelsHeight;
mode.dmPelsHeight = mode.dmPelsWidth;
mode.dmPelsWidth = temp;
}
bool defaultIsLandscape = mode.dmPelsWidth >= mode.dmPelsHeight;
switch (mode.dmDisplayOrientation) {
case DMDO_DEFAULT:
aOrientation = defaultIsLandscape
? hal::ScreenOrientation::LandscapePrimary
: hal::ScreenOrientation::PortraitPrimary;
aAngle = 0;
break;
case DMDO_90:
aOrientation = defaultIsLandscape
? hal::ScreenOrientation::PortraitPrimary
: hal::ScreenOrientation::LandscapeSecondary;
aAngle = 270;
break;
case DMDO_180:
aOrientation = defaultIsLandscape
? hal::ScreenOrientation::LandscapeSecondary
: hal::ScreenOrientation::PortraitSecondary;
aAngle = 180;
break;
case DMDO_270:
aOrientation = defaultIsLandscape
? hal::ScreenOrientation::PortraitSecondary
: hal::ScreenOrientation::LandscapePrimary;
aAngle = 90;
break;
default:
MOZ_ASSERT_UNREACHABLE("Unexpected angle");
break;
}
return;
}
} // namespace widget
} // namespace mozilla

Просмотреть файл

@ -565,10 +565,6 @@ class WinUtils {
static void EnableWindowOcclusion(const bool aEnable);
static void GetDisplayOrientation(const char16ptr_t aName,
hal::ScreenOrientation& aOrientation,
uint16_t& aAngle);
private:
static WhitelistVec BuildWhitelist();

Просмотреть файл

@ -5940,10 +5940,6 @@ bool nsWindow::ProcessMessageInternal(UINT msg, WPARAM& wParam, LPARAM& lParam,
case WM_DISPLAYCHANGE: {
ScreenHelperWin::RefreshScreens();
nsCOMPtr<nsIGfxInfo> gfxInfo = components::GfxInfo::Service();
if (gfxInfo) {
gfxInfo->RefreshMonitors();
}
if (mWidgetListener) {
mWidgetListener->UIResolutionChanged();
}