PlatformScreenGtk.cpp [plain text]
#include "config.h"
#include "PlatformScreen.h"
#include "FloatRect.h"
#include "FrameView.h"
#include "GtkVersioning.h"
#include "HostWindow.h"
#include "NotImplemented.h"
#include "Widget.h"
#include <cmath>
#include <gtk/gtk.h>
#include <wtf/HashMap.h>
#include <wtf/NeverDestroyed.h>
namespace WebCore {
static GtkWidget* getToplevel(GtkWidget* widget)
{
GtkWidget* toplevel = gtk_widget_get_toplevel(widget);
return gtk_widget_is_toplevel(toplevel) ? toplevel : 0;
}
static GdkVisual* getVisual(Widget* widget)
{
GtkWidget* container = widget ? GTK_WIDGET(widget->root()->hostWindow()->platformPageClient()) : 0;
if (!container) {
GdkScreen* screen = gdk_screen_get_default();
return screen ? gdk_screen_get_system_visual(screen) : 0;
}
if (!gtk_widget_get_realized(container))
container = getToplevel(container);
return container ? gdk_window_get_visual(gtk_widget_get_window(container)) : 0;
}
int screenDepth(Widget* widget)
{
GdkVisual* visual = getVisual(widget);
if (!visual)
return 24;
return gdk_visual_get_depth(visual);
}
int screenDepthPerComponent(Widget* widget)
{
GdkVisual* visual = getVisual(widget);
if (!visual)
return 8;
return gdk_visual_get_bits_per_rgb(visual);
}
bool screenIsMonochrome(Widget* widget)
{
return screenDepth(widget) < 2;
}
bool screenHasInvertedColors()
{
return false;
}
double screenDPI()
{
static const double defaultDpi = 96;
GdkScreen* screen = gdk_screen_get_default();
if (!screen)
return defaultDpi;
double dpi = gdk_screen_get_resolution(screen);
if (dpi != -1)
return dpi;
static double cachedDpi = 0;
if (cachedDpi)
return cachedDpi;
static const double millimetresPerInch = 25.4;
double diagonalInPixels = std::hypot(gdk_screen_get_width(screen), gdk_screen_get_height(screen));
double diagonalInInches = std::hypot(gdk_screen_get_width_mm(screen), gdk_screen_get_height_mm(screen)) / millimetresPerInch;
cachedDpi = diagonalInPixels / diagonalInInches;
return cachedDpi;
}
static WTF::HashMap<void*, Function<void()>>& screenDPIObserverHandlersMap()
{
static WTF::NeverDestroyed<WTF::HashMap<void*, Function<void()>>> handlersMap;
return handlersMap;
}
static void gtkXftDPIChangedCallback()
{
for (const auto& keyValuePair : screenDPIObserverHandlersMap())
keyValuePair.value();
}
void setScreenDPIObserverHandler(Function<void()>&& handler, void* context)
{
static GtkSettings* gtkSettings = gtk_settings_get_default();
static unsigned long gtkXftDpiChangedHandlerID = 0;
if (!gtkSettings)
return;
if (handler)
screenDPIObserverHandlersMap().set(context, WTFMove(handler));
else
screenDPIObserverHandlersMap().remove(context);
if (!screenDPIObserverHandlersMap().isEmpty()) {
if (!gtkXftDpiChangedHandlerID)
gtkXftDpiChangedHandlerID = g_signal_connect(gtkSettings, "notify::gtk-xft-dpi", G_CALLBACK(gtkXftDPIChangedCallback), nullptr);
} else if (gtkXftDpiChangedHandlerID) {
g_signal_handler_disconnect(gtkSettings, gtkXftDpiChangedHandlerID);
gtkXftDpiChangedHandlerID = 0;
}
}
static GdkScreen* getScreen(GtkWidget* widget)
{
return gtk_widget_has_screen(widget) ? gtk_widget_get_screen(widget) : gdk_screen_get_default();
}
FloatRect screenRect(Widget* widget)
{
GtkWidget* container = widget ? GTK_WIDGET(widget->root()->hostWindow()->platformPageClient()) : 0;
if (container)
container = getToplevel(container);
GdkScreen* screen = container ? getScreen(container) : gdk_screen_get_default();
if (!screen)
return FloatRect();
gint monitor = container ? gdk_screen_get_monitor_at_window(screen, gtk_widget_get_window(container)) : 0;
GdkRectangle geometry;
gdk_screen_get_monitor_geometry(screen, monitor, &geometry);
return FloatRect(geometry.x, geometry.y, geometry.width, geometry.height);
}
FloatRect screenAvailableRect(Widget* widget)
{
GtkWidget* container = widget ? GTK_WIDGET(widget->root()->hostWindow()->platformPageClient()) : 0;
if (container && !gtk_widget_get_realized(container))
return screenRect(widget);
GdkScreen* screen = container ? getScreen(container) : gdk_screen_get_default();
if (!screen)
return FloatRect();
gint monitor = container ? gdk_screen_get_monitor_at_window(screen, gtk_widget_get_window(container)) : 0;
GdkRectangle workArea;
gdk_screen_get_monitor_workarea(screen, monitor, &workArea);
return FloatRect(workArea.x, workArea.y, workArea.width, workArea.height);
}
bool screenSupportsExtendedColor(Widget*)
{
return false;
}
}