Bug 1554850 - handle fractional DPI change on Linux. r=karlt

On Linux, Firefox is listening on notify::scale-factor to detect DPI
change. However, scale-factor is an int and on the lower-end side of
the DPI scale, some devices are using fractional scale factors encoded
into Xft/DPI setting. Changing from ×1 to ×1.5 scale is therefore
undetected.

The proposed change is two-folds:

 - remove use of a cached sDPI value and rely on GTK being the cache

 - listening on notify::gtk-xft-dpi to trigger a DPI change

What is missing:

 - performance evaluation of not caching sDPI (on a 10s session
   loading 2 pages, there is an "overhead" of 6ms on my setup, nothing
   visible from my point of view)

 - when changing Xft/DPI and scale, the change is done twice, this
   seems harmless

Differential Revision: https://phabricator.services.mozilla.com/D92095
This commit is contained in:
Vincent Bernat 2020-10-13 02:47:27 +00:00
Родитель 803b368879
Коммит 10ae6bfc55
3 изменённых файлов: 23 добавлений и 17 удалений

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

@ -245,22 +245,15 @@ gfxPlatformFontList* gfxPlatformGtk::CreatePlatformFontList() {
return nullptr;
}
// FIXME(emilio, bug 1554850): This should be invalidated somehow, right now
// requires a restart.
static int32_t sDPI = 0;
int32_t gfxPlatformGtk::GetFontScaleDPI() {
if (MOZ_UNLIKELY(!sDPI)) {
// Make sure init is run so we have a resolution
GdkScreen* screen = gdk_screen_get_default();
gtk_settings_get_for_screen(screen);
sDPI = int32_t(round(gdk_screen_get_resolution(screen)));
if (sDPI <= 0) {
// Fall back to something sane
sDPI = 96;
}
GdkScreen* screen = gdk_screen_get_default();
gtk_settings_get_for_screen(screen);
int32_t dpi = int32_t(round(gdk_screen_get_resolution(screen)));
if (dpi <= 0) {
// Fall back to something sane
dpi = 96;
}
return sDPI;
return dpi;
}
double gfxPlatformGtk::GetFontScaleFactor() {

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

@ -218,6 +218,8 @@ static gboolean window_state_event_cb(GtkWidget* widget,
GdkEventWindowState* event);
static void settings_changed_cb(GtkSettings* settings, GParamSpec* pspec,
nsWindow* data);
static void settings_xft_dpi_changed_cb(GtkSettings* settings,
GParamSpec* pspec, nsWindow* data);
static void check_resize_cb(GtkContainer* container, gpointer user_data);
static void screen_composited_changed_cb(GdkScreen* screen, gpointer user_data);
static void widget_composited_changed_cb(GtkWidget* widget, gpointer user_data);
@ -715,8 +717,7 @@ void nsWindow::Destroy() {
ClearCachedResources();
g_signal_handlers_disconnect_by_func(
gtk_settings_get_default(), FuncToGpointer(settings_changed_cb), this);
g_signal_handlers_disconnect_by_data(gtk_settings_get_default(), this);
nsIRollupListener* rollupListener = nsBaseWidget::GetActiveRollupListener();
if (rollupListener) {
@ -4690,6 +4691,8 @@ nsresult nsWindow::Create(nsIWidget* aParent, nsNativeWidget aNativeParent,
G_CALLBACK(settings_changed_cb), this);
g_signal_connect_after(default_settings, "notify::gtk-decoration-layout",
G_CALLBACK(settings_changed_cb), this);
g_signal_connect_after(default_settings, "notify::gtk-xft-dpi",
G_CALLBACK(settings_xft_dpi_changed_cb), this);
}
if (mContainer) {
@ -6821,6 +6824,16 @@ static void settings_changed_cb(GtkSettings* settings, GParamSpec* pspec,
window->ThemeChanged();
}
static void settings_xft_dpi_changed_cb(GtkSettings* gtk_settings,
GParamSpec* pspec, nsWindow* data) {
RefPtr<nsWindow> window = data;
window->OnDPIChanged();
// Even though the window size in screen pixels has not changed,
// nsViewManager stores the dimensions in app units.
// DispatchResized() updates those.
window->DispatchResized();
}
static void check_resize_cb(GtkContainer* container, gpointer user_data) {
RefPtr<nsWindow> window = get_window_for_gtk_widget(GTK_WIDGET(container));
if (!window) {

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

@ -271,6 +271,7 @@ class nsWindow final : public nsBaseWidget {
void OnCheckResize(void);
void OnCompositedChanged(void);
void OnScaleChanged(GtkAllocation* aAllocation);
void DispatchResized();
#ifdef MOZ_X11
Window mOldFocusWindow;
@ -429,7 +430,6 @@ class nsWindow final : public nsBaseWidget {
// event handling code
void DispatchActivateEvent(void);
void DispatchDeactivateEvent(void);
void DispatchResized();
void MaybeDispatchResized();
virtual void RegisterTouchWindow() override;