forked from AuroraMiddleware/gtk
f68cf698fc
The gtk_shell protocol used some half baked unstable protocol semantics that worked by only allowing binding the exact version of the interface. This hack is a bit too confusing and it makes it impossible to do any compatible changes without breaking things. So, instead rename it to include a number in the interface names. This way we can add requests and events without causing compatibility issues, and we can later remove requests and events by bumping the number in the interface names. https://bugzilla.gnome.org/show_bug.cgi?id=763001
1251 lines
36 KiB
C
1251 lines
36 KiB
C
/*
|
|
* Copyright © 2010 Intel Corporation
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <glib.h>
|
|
#include <gio/gio.h>
|
|
#include "gdkscreenprivate.h"
|
|
#include "gdkvisualprivate.h"
|
|
#include "gdkdisplay.h"
|
|
#include "gdkdisplay-wayland.h"
|
|
#include "gdkwayland.h"
|
|
#include "gdkprivate-wayland.h"
|
|
|
|
#include "wm-button-layout-translation.h"
|
|
|
|
typedef struct _GdkWaylandScreen GdkWaylandScreen;
|
|
typedef struct _GdkWaylandScreenClass GdkWaylandScreenClass;
|
|
|
|
#define GDK_TYPE_WAYLAND_SCREEN (_gdk_wayland_screen_get_type ())
|
|
#define GDK_WAYLAND_SCREEN(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WAYLAND_SCREEN, GdkWaylandScreen))
|
|
#define GDK_WAYLAND_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WAYLAND_SCREEN, GdkWaylandScreenClass))
|
|
#define GDK_IS_WAYLAND_SCREEN(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_SCREEN))
|
|
#define GDK_IS_WAYLAND_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WAYLAND_SCREEN))
|
|
#define GDK_WAYLAND_SCREEN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WAYLAND_SCREEN, GdkWaylandScreenClass))
|
|
|
|
typedef struct {
|
|
gboolean antialias;
|
|
gboolean hinting;
|
|
gint dpi;
|
|
const gchar *rgba;
|
|
const gchar *hintstyle;
|
|
} GsdXftSettings;
|
|
|
|
typedef struct _GdkWaylandMonitor GdkWaylandMonitor;
|
|
|
|
struct _GdkWaylandScreen
|
|
{
|
|
GdkScreen parent_instance;
|
|
|
|
GdkDisplay *display;
|
|
GdkWindow *root_window;
|
|
|
|
int width, height;
|
|
int width_mm, height_mm;
|
|
|
|
/* Visual Part */
|
|
GdkVisual *visual;
|
|
|
|
/* Xinerama/RandR 1.2 */
|
|
GPtrArray *monitors;
|
|
gint primary_monitor;
|
|
|
|
GHashTable *settings;
|
|
GsdXftSettings xft_settings;
|
|
|
|
guint32 shell_capabilities;
|
|
};
|
|
|
|
struct _GdkWaylandScreenClass
|
|
{
|
|
GdkScreenClass parent_class;
|
|
|
|
void (* window_manager_changed) (GdkWaylandScreen *screen_wayland);
|
|
};
|
|
|
|
#define OUTPUT_VERSION_WITH_DONE 2
|
|
|
|
struct _GdkWaylandMonitor
|
|
{
|
|
GdkWaylandScreen *screen;
|
|
guint32 id;
|
|
guint32 version;
|
|
struct wl_output *output;
|
|
GdkRectangle geometry;
|
|
int width_mm;
|
|
int height_mm;
|
|
char * output_name;
|
|
char * manufacturer;
|
|
int refresh_rate;
|
|
gint scale;
|
|
};
|
|
|
|
GType _gdk_wayland_screen_get_type (void);
|
|
|
|
G_DEFINE_TYPE (GdkWaylandScreen, _gdk_wayland_screen, GDK_TYPE_SCREEN)
|
|
|
|
static void
|
|
free_monitor (gpointer data)
|
|
{
|
|
GdkWaylandMonitor *monitor = data;
|
|
|
|
if (monitor == NULL)
|
|
return;
|
|
|
|
wl_output_destroy (monitor->output);
|
|
g_free (monitor->output_name);
|
|
g_free (monitor->manufacturer);
|
|
|
|
g_free (monitor);
|
|
}
|
|
|
|
static void
|
|
deinit_multihead (GdkScreen *screen)
|
|
{
|
|
GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
|
|
|
|
g_ptr_array_free (screen_wayland->monitors, TRUE);
|
|
|
|
screen_wayland->monitors = NULL;
|
|
}
|
|
|
|
static void
|
|
init_multihead (GdkScreen *screen)
|
|
{
|
|
GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
|
|
|
|
screen_wayland->monitors = g_ptr_array_new_with_free_func (free_monitor);
|
|
screen_wayland->primary_monitor = 0;
|
|
}
|
|
|
|
static void
|
|
gdk_wayland_screen_dispose (GObject *object)
|
|
{
|
|
GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (object);
|
|
|
|
if (screen_wayland->root_window)
|
|
_gdk_window_destroy (screen_wayland->root_window, FALSE);
|
|
|
|
G_OBJECT_CLASS (_gdk_wayland_screen_parent_class)->dispose (object);
|
|
}
|
|
|
|
static void
|
|
gdk_wayland_screen_finalize (GObject *object)
|
|
{
|
|
GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (object);
|
|
|
|
if (screen_wayland->root_window)
|
|
g_object_unref (screen_wayland->root_window);
|
|
|
|
g_object_unref (screen_wayland->visual);
|
|
|
|
deinit_multihead (GDK_SCREEN (object));
|
|
|
|
g_hash_table_destroy (screen_wayland->settings);
|
|
|
|
G_OBJECT_CLASS (_gdk_wayland_screen_parent_class)->finalize (object);
|
|
}
|
|
|
|
static GdkDisplay *
|
|
gdk_wayland_screen_get_display (GdkScreen *screen)
|
|
{
|
|
return GDK_WAYLAND_SCREEN (screen)->display;
|
|
}
|
|
|
|
static gint
|
|
gdk_wayland_screen_get_width (GdkScreen *screen)
|
|
{
|
|
return GDK_WAYLAND_SCREEN (screen)->width;
|
|
}
|
|
|
|
static gint
|
|
gdk_wayland_screen_get_height (GdkScreen *screen)
|
|
{
|
|
return GDK_WAYLAND_SCREEN (screen)->height;
|
|
}
|
|
|
|
static gint
|
|
gdk_wayland_screen_get_width_mm (GdkScreen *screen)
|
|
{
|
|
return GDK_WAYLAND_SCREEN (screen)->width_mm;
|
|
}
|
|
|
|
static gint
|
|
gdk_wayland_screen_get_height_mm (GdkScreen *screen)
|
|
{
|
|
return GDK_WAYLAND_SCREEN (screen)->height_mm;
|
|
}
|
|
|
|
static gint
|
|
gdk_wayland_screen_get_number (GdkScreen *screen)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static GdkWindow *
|
|
gdk_wayland_screen_get_root_window (GdkScreen *screen)
|
|
{
|
|
return GDK_WAYLAND_SCREEN (screen)->root_window;
|
|
}
|
|
|
|
static gint
|
|
gdk_wayland_screen_get_n_monitors (GdkScreen *screen)
|
|
{
|
|
return GDK_WAYLAND_SCREEN (screen)->monitors->len;
|
|
}
|
|
|
|
static gint
|
|
gdk_wayland_screen_get_primary_monitor (GdkScreen *screen)
|
|
{
|
|
return GDK_WAYLAND_SCREEN (screen)->primary_monitor;
|
|
}
|
|
|
|
static gint
|
|
gdk_wayland_screen_get_monitor_width_mm (GdkScreen *screen,
|
|
gint monitor_num)
|
|
{
|
|
GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
|
|
GdkWaylandMonitor *monitor;
|
|
|
|
monitor = g_ptr_array_index (screen_wayland->monitors, monitor_num);
|
|
|
|
return monitor->width_mm;
|
|
}
|
|
|
|
static gint
|
|
gdk_wayland_screen_get_monitor_height_mm (GdkScreen *screen,
|
|
gint monitor_num)
|
|
{
|
|
GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
|
|
GdkWaylandMonitor *monitor;
|
|
|
|
monitor = g_ptr_array_index (screen_wayland->monitors, monitor_num);
|
|
|
|
return monitor->height_mm;
|
|
}
|
|
|
|
static gchar *
|
|
gdk_wayland_screen_get_monitor_plug_name (GdkScreen *screen,
|
|
gint monitor_num)
|
|
{
|
|
GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
|
|
GdkWaylandMonitor *monitor;
|
|
|
|
monitor = g_ptr_array_index (screen_wayland->monitors, monitor_num);
|
|
|
|
return g_strdup (monitor->output_name);
|
|
}
|
|
|
|
static void
|
|
gdk_wayland_screen_get_monitor_geometry (GdkScreen *screen,
|
|
gint monitor_num,
|
|
GdkRectangle *dest)
|
|
{
|
|
GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
|
|
GdkWaylandMonitor *monitor;
|
|
|
|
monitor = g_ptr_array_index (screen_wayland->monitors, monitor_num);
|
|
|
|
if (dest)
|
|
*dest = monitor->geometry;
|
|
}
|
|
|
|
static gint
|
|
gdk_wayland_screen_get_monitor_scale_factor (GdkScreen *screen,
|
|
gint monitor_num)
|
|
{
|
|
GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
|
|
GdkWaylandMonitor *monitor;
|
|
|
|
monitor = g_ptr_array_index (screen_wayland->monitors, monitor_num);
|
|
|
|
return monitor->scale;
|
|
}
|
|
|
|
static GdkVisual *
|
|
gdk_wayland_screen_get_system_visual (GdkScreen * screen)
|
|
{
|
|
return (GdkVisual *) GDK_WAYLAND_SCREEN (screen)->visual;
|
|
}
|
|
|
|
static GdkVisual *
|
|
gdk_wayland_screen_get_rgba_visual (GdkScreen *screen)
|
|
{
|
|
return (GdkVisual *) GDK_WAYLAND_SCREEN (screen)->visual;
|
|
}
|
|
|
|
static gboolean
|
|
gdk_wayland_screen_is_composited (GdkScreen *screen)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
static gchar *
|
|
gdk_wayland_screen_make_display_name (GdkScreen *screen)
|
|
{
|
|
const gchar *name;
|
|
|
|
name = g_getenv ("WAYLAND_DISPLAY");
|
|
if (name == NULL)
|
|
name = "wayland-0";
|
|
|
|
return g_strdup (name);
|
|
}
|
|
|
|
static GdkWindow *
|
|
gdk_wayland_screen_get_active_window (GdkScreen *screen)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static GList *
|
|
gdk_wayland_screen_get_window_stack (GdkScreen *screen)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
gdk_wayland_screen_broadcast_client_message (GdkScreen *screen,
|
|
GdkEvent *event)
|
|
{
|
|
}
|
|
|
|
static void
|
|
notify_setting (GdkScreen *screen,
|
|
const gchar *setting)
|
|
{
|
|
GdkEvent event;
|
|
|
|
event.type = GDK_SETTING;
|
|
event.setting.window = gdk_screen_get_root_window (screen);
|
|
event.setting.send_event = FALSE;
|
|
event.setting.action = GDK_SETTING_ACTION_CHANGED;
|
|
event.setting.name = (gchar *)setting;
|
|
gdk_event_put (&event);
|
|
}
|
|
|
|
typedef enum
|
|
{
|
|
GSD_FONT_ANTIALIASING_MODE_NONE,
|
|
GSD_FONT_ANTIALIASING_MODE_GRAYSCALE,
|
|
GSD_FONT_ANTIALIASING_MODE_RGBA
|
|
} GsdFontAntialiasingMode;
|
|
|
|
typedef enum
|
|
{
|
|
GSD_FONT_HINTING_NONE,
|
|
GSD_FONT_HINTING_SLIGHT,
|
|
GSD_FONT_HINTING_MEDIUM,
|
|
GSD_FONT_HINTING_FULL
|
|
} GsdFontHinting;
|
|
|
|
typedef enum
|
|
{
|
|
GSD_FONT_RGBA_ORDER_RGBA,
|
|
GSD_FONT_RGBA_ORDER_RGB,
|
|
GSD_FONT_RGBA_ORDER_BGR,
|
|
GSD_FONT_RGBA_ORDER_VRGB,
|
|
GSD_FONT_RGBA_ORDER_VBGR
|
|
} GsdFontRgbaOrder;
|
|
|
|
static gdouble
|
|
get_dpi_from_gsettings (GdkWaylandScreen *screen_wayland)
|
|
{
|
|
GSettings *settings;
|
|
gdouble factor;
|
|
|
|
settings = g_hash_table_lookup (screen_wayland->settings,
|
|
"org.gnome.desktop.interface");
|
|
if (settings != NULL)
|
|
factor = g_settings_get_double (settings, "text-scaling-factor");
|
|
else
|
|
factor = 1.0;
|
|
|
|
return 96.0 * factor;
|
|
}
|
|
|
|
static void
|
|
update_xft_settings (GdkScreen *screen)
|
|
{
|
|
GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
|
|
GSettings *settings;
|
|
GsdFontAntialiasingMode antialiasing;
|
|
GsdFontHinting hinting;
|
|
GsdFontRgbaOrder order;
|
|
gboolean use_rgba = FALSE;
|
|
GsdXftSettings xft_settings;
|
|
|
|
settings = g_hash_table_lookup (screen_wayland->settings, "org.gnome.settings-daemon.plugins.xsettings");
|
|
|
|
if (settings)
|
|
{
|
|
antialiasing = g_settings_get_enum (settings, "antialiasing");
|
|
hinting = g_settings_get_enum (settings, "hinting");
|
|
order = g_settings_get_enum (settings, "rgba-order");
|
|
}
|
|
else
|
|
{
|
|
antialiasing = GSD_FONT_ANTIALIASING_MODE_GRAYSCALE;
|
|
hinting = GSD_FONT_HINTING_MEDIUM;
|
|
order = GSD_FONT_RGBA_ORDER_RGB;
|
|
}
|
|
|
|
xft_settings.antialias = (antialiasing != GSD_FONT_ANTIALIASING_MODE_NONE);
|
|
xft_settings.hinting = (hinting != GSD_FONT_HINTING_NONE);
|
|
xft_settings.dpi = get_dpi_from_gsettings (screen_wayland) * 1024; /* Xft wants 1/1024ths of an inch */
|
|
xft_settings.rgba = "rgb";
|
|
xft_settings.hintstyle = "hintfull";
|
|
|
|
switch (hinting)
|
|
{
|
|
case GSD_FONT_HINTING_NONE:
|
|
xft_settings.hintstyle = "hintnone";
|
|
break;
|
|
case GSD_FONT_HINTING_SLIGHT:
|
|
xft_settings.hintstyle = "hintslight";
|
|
break;
|
|
case GSD_FONT_HINTING_MEDIUM:
|
|
xft_settings.hintstyle = "hintmedium";
|
|
break;
|
|
case GSD_FONT_HINTING_FULL:
|
|
xft_settings.hintstyle = "hintfull";
|
|
break;
|
|
}
|
|
|
|
switch (order)
|
|
{
|
|
case GSD_FONT_RGBA_ORDER_RGBA:
|
|
xft_settings.rgba = "rgba";
|
|
break;
|
|
case GSD_FONT_RGBA_ORDER_RGB:
|
|
xft_settings.rgba = "rgb";
|
|
break;
|
|
case GSD_FONT_RGBA_ORDER_BGR:
|
|
xft_settings.rgba = "bgr";
|
|
break;
|
|
case GSD_FONT_RGBA_ORDER_VRGB:
|
|
xft_settings.rgba = "vrgb";
|
|
break;
|
|
case GSD_FONT_RGBA_ORDER_VBGR:
|
|
xft_settings.rgba = "vbgr";
|
|
break;
|
|
}
|
|
|
|
switch (antialiasing)
|
|
{
|
|
case GSD_FONT_ANTIALIASING_MODE_NONE:
|
|
xft_settings.antialias = FALSE;
|
|
break;
|
|
case GSD_FONT_ANTIALIASING_MODE_GRAYSCALE:
|
|
xft_settings.antialias = TRUE;
|
|
break;
|
|
case GSD_FONT_ANTIALIASING_MODE_RGBA:
|
|
xft_settings.antialias = TRUE;
|
|
use_rgba = TRUE;
|
|
}
|
|
|
|
if (!use_rgba)
|
|
xft_settings.rgba = "none";
|
|
|
|
if (screen_wayland->xft_settings.antialias != xft_settings.antialias)
|
|
{
|
|
screen_wayland->xft_settings.antialias = xft_settings.antialias;
|
|
notify_setting (screen, "gtk-xft-antialias");
|
|
}
|
|
|
|
if (screen_wayland->xft_settings.hinting != xft_settings.hinting)
|
|
{
|
|
screen_wayland->xft_settings.hinting = xft_settings.hinting;
|
|
notify_setting (screen, "gtk-xft-hinting");
|
|
}
|
|
|
|
if (screen_wayland->xft_settings.hintstyle != xft_settings.hintstyle)
|
|
{
|
|
screen_wayland->xft_settings.hintstyle = xft_settings.hintstyle;
|
|
notify_setting (screen, "gtk-xft-hintstyle");
|
|
}
|
|
|
|
if (screen_wayland->xft_settings.rgba != xft_settings.rgba)
|
|
{
|
|
screen_wayland->xft_settings.rgba = xft_settings.rgba;
|
|
notify_setting (screen, "gtk-xft-rgba");
|
|
}
|
|
|
|
if (screen_wayland->xft_settings.dpi != xft_settings.dpi)
|
|
{
|
|
double dpi = xft_settings.dpi / 1024.;
|
|
const char *scale_env;
|
|
double scale;
|
|
|
|
screen_wayland->xft_settings.dpi = xft_settings.dpi;
|
|
|
|
scale_env = g_getenv ("GDK_DPI_SCALE");
|
|
if (scale_env)
|
|
{
|
|
scale = g_ascii_strtod (scale_env, NULL);
|
|
if (scale != 0 && dpi > 0)
|
|
dpi *= scale;
|
|
}
|
|
|
|
_gdk_screen_set_resolution (screen, dpi);
|
|
|
|
notify_setting (screen, "gtk-xft-dpi");
|
|
}
|
|
}
|
|
|
|
#define WM_SETTINGS_SCHEMA "org.gnome.desktop.wm.preferences"
|
|
#define CLASSIC_WM_SETTINGS_SCHEMA "org.gnome.shell.extensions.classic-overrides"
|
|
|
|
typedef struct _TranslationEntry TranslationEntry;
|
|
struct _TranslationEntry {
|
|
const gchar *schema;
|
|
const gchar *key;
|
|
const gchar *setting;
|
|
GType type;
|
|
union {
|
|
const gchar *s;
|
|
gint i;
|
|
gboolean b;
|
|
} fallback;
|
|
};
|
|
|
|
static TranslationEntry translations[] = {
|
|
{ "org.gnome.desktop.interface", "gtk-theme", "gtk-theme-name" , G_TYPE_STRING, { .s = "Adwaita" } },
|
|
{ "org.gnome.desktop.interface", "icon-theme", "gtk-icon-theme-name", G_TYPE_STRING, { .s = "gnome" } },
|
|
{ "org.gnome.desktop.interface", "cursor-theme", "gtk-cursor-theme-name", G_TYPE_STRING, { .s = "Adwaita" } },
|
|
{ "org.gnome.desktop.interface", "cursor-size", "gtk-cursor-theme-size", G_TYPE_INT, { .i = 32 } },
|
|
{ "org.gnome.desktop.interface", "font-name", "gtk-font-name", G_TYPE_STRING, { .s = "Cantarell 11" } },
|
|
{ "org.gnome.desktop.interface", "cursor-blink", "gtk-cursor-blink", G_TYPE_BOOLEAN, { .b = TRUE } },
|
|
{ "org.gnome.desktop.interface", "cursor-blink-time", "gtk-cursor-blink-time", G_TYPE_INT, { .i = 1200 } },
|
|
{ "org.gnome.desktop.interface", "cursor-blink-timeout", "gtk-cursor-blink-timeout", G_TYPE_INT, { .i = 3600 } },
|
|
{ "org.gnome.desktop.interface", "gtk-im-module", "gtk-im-module", G_TYPE_STRING, { .s = "simple" } },
|
|
{ "org.gnome.desktop.interface", "enable-animations", "gtk-enable-animations", G_TYPE_BOOLEAN, { .b = TRUE } },
|
|
{ "org.gnome.settings-daemon.peripherals.mouse", "double-click", "gtk-double-click-time", G_TYPE_INT, { .i = 400 } },
|
|
{ "org.gnome.settings-daemon.peripherals.mouse", "drag-threshold", "gtk-dnd-drag-threshold", G_TYPE_INT, {.i = 8 } },
|
|
{ "org.gnome.desktop.sound", "theme-name", "gtk-sound-theme-name", G_TYPE_STRING, { .s = "freedesktop" } },
|
|
{ "org.gnome.desktop.sound", "event-sounds", "gtk-enable-event-sounds", G_TYPE_BOOLEAN, { .b = TRUE } },
|
|
{ "org.gnome.desktop.sound", "input-feedback-sounds", "gtk-enable-input-feedback-sounds", G_TYPE_BOOLEAN, { . b = FALSE } },
|
|
{ "org.gnome.desktop.privacy", "recent-files-max-age", "gtk-recent-files-max-age", G_TYPE_INT, { .i = 30 } },
|
|
{ "org.gnome.desktop.privacy", "remember-recent-files", "gtk-recent-files-enabled", G_TYPE_BOOLEAN, { .b = TRUE } },
|
|
{ WM_SETTINGS_SCHEMA, "button-layout", "gtk-decoration-layout", G_TYPE_STRING, { .s = "menu:close" } },
|
|
{ CLASSIC_WM_SETTINGS_SCHEMA, "button-layout", "gtk-decoration-layout", G_TYPE_STRING, { .s = "menu:close" } },
|
|
{ "org.gnome.settings-daemon.plugins.xsettings", "antialiasing", "gtk-xft-antialias", G_TYPE_NONE, { .i = 0 } },
|
|
{ "org.gnome.settings-daemon.plugins.xsettings", "hinting", "gtk-xft-hinting", G_TYPE_NONE, { .i = 0 } },
|
|
{ "org.gnome.settings-daemon.plugins.xsettings", "hinting", "gtk-xft-hintstyle", G_TYPE_NONE, { .i = 0 } },
|
|
{ "org.gnome.settings-daemon.plugins.xsettings", "rgba-order", "gtk-xft-rgba", G_TYPE_NONE, { .i = 0 } },
|
|
{ "org.gnome.desktop.interface", "text-scaling-factor", "gtk-xft-dpi" , G_TYPE_NONE, { .i = 0 } },
|
|
{ "org.gnome.desktop.wm.preferences", "action-double-click-titlebar", "gtk-titlebar-double-click", G_TYPE_STRING, { .s = "toggle-maximize" } },
|
|
{ "org.gnome.desktop.wm.preferences", "action-middle-click-titlebar", "gtk-titlebar-middle-click", G_TYPE_STRING, { .s = "none" } },
|
|
{ "org.gnome.desktop.wm.preferences", "action-right-click-titlebar", "gtk-titlebar-right-click", G_TYPE_STRING, { .s = "menu" } },
|
|
{ "org.gnome.desktop.a11y", "always-show-text-caret", "gtk-keynav-use-caret", G_TYPE_BOOLEAN, { .b = FALSE } }
|
|
};
|
|
|
|
static TranslationEntry *
|
|
find_translation_entry_by_key (GSettings *settings,
|
|
const gchar *key)
|
|
{
|
|
guint i;
|
|
gchar *schema;
|
|
|
|
g_object_get (settings, "schema", &schema, NULL);
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (translations); i++)
|
|
{
|
|
if (g_str_equal (schema, translations[i].schema) &&
|
|
g_str_equal (key, translations[i].key))
|
|
{
|
|
g_free (schema);
|
|
return &translations[i];
|
|
}
|
|
}
|
|
|
|
g_free (schema);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static TranslationEntry *
|
|
find_translation_entry_by_setting (const gchar *setting)
|
|
{
|
|
guint i;
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (translations); i++)
|
|
{
|
|
if (g_str_equal (setting, translations[i].setting))
|
|
return &translations[i];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
settings_changed (GSettings *settings,
|
|
const gchar *key,
|
|
GdkScreen *screen)
|
|
{
|
|
TranslationEntry *entry;
|
|
|
|
entry = find_translation_entry_by_key (settings, key);
|
|
|
|
if (entry != NULL)
|
|
{
|
|
if (entry->type != G_TYPE_NONE)
|
|
notify_setting (screen, entry->setting);
|
|
else
|
|
update_xft_settings (screen);
|
|
}
|
|
}
|
|
|
|
static void
|
|
init_settings (GdkScreen *screen)
|
|
{
|
|
GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
|
|
GSettingsSchemaSource *source;
|
|
GSettingsSchema *schema;
|
|
GSettings *settings;
|
|
gint i;
|
|
|
|
screen_wayland->settings = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
|
|
|
|
source = g_settings_schema_source_get_default ();
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (translations); i++)
|
|
{
|
|
if (g_hash_table_lookup (screen_wayland->settings, (gpointer)translations[i].schema) != NULL)
|
|
continue;
|
|
|
|
schema = g_settings_schema_source_lookup (source, translations[i].schema, TRUE);
|
|
if (schema != NULL)
|
|
{
|
|
settings = g_settings_new_full (schema, NULL, NULL);
|
|
g_signal_connect (settings, "changed",
|
|
G_CALLBACK (settings_changed), screen);
|
|
g_hash_table_insert (screen_wayland->settings, (gpointer)translations[i].schema, settings);
|
|
g_settings_schema_unref (schema);
|
|
}
|
|
}
|
|
|
|
update_xft_settings (screen);
|
|
}
|
|
|
|
static void
|
|
gtk_shell_handle_capabilities (void *data,
|
|
struct gtk_shell1 *shell,
|
|
uint32_t capabilities)
|
|
{
|
|
GdkScreen *screen = data;
|
|
GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (data);
|
|
|
|
screen_wayland->shell_capabilities = capabilities;
|
|
|
|
notify_setting (screen, "gtk-shell-shows-app-menu");
|
|
notify_setting (screen, "gtk-shell-shows-menubar");
|
|
notify_setting (screen, "gtk-shell-shows-desktop");
|
|
}
|
|
|
|
struct gtk_shell1_listener gdk_screen_gtk_shell_listener = {
|
|
gtk_shell_handle_capabilities
|
|
};
|
|
|
|
void
|
|
_gdk_wayland_screen_set_has_gtk_shell (GdkScreen *screen)
|
|
{
|
|
GdkWaylandDisplay *wayland_display = GDK_WAYLAND_DISPLAY (GDK_WAYLAND_SCREEN (screen)->display);
|
|
|
|
gtk_shell1_add_listener (wayland_display->gtk_shell,
|
|
&gdk_screen_gtk_shell_listener,
|
|
screen);
|
|
}
|
|
|
|
static void
|
|
set_value_from_entry (GdkScreen *screen,
|
|
TranslationEntry *entry,
|
|
GValue *value)
|
|
{
|
|
GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
|
|
GSettings *settings;
|
|
|
|
settings = (GSettings *)g_hash_table_lookup (screen_wayland->settings, entry->schema);
|
|
switch (entry->type)
|
|
{
|
|
case G_TYPE_STRING:
|
|
if (settings)
|
|
{
|
|
gchar *s;
|
|
s = g_settings_get_string (settings, entry->key);
|
|
g_value_set_string (value, s);
|
|
g_free (s);
|
|
}
|
|
else
|
|
{
|
|
g_value_set_static_string (value, entry->fallback.s);
|
|
}
|
|
break;
|
|
case G_TYPE_INT:
|
|
g_value_set_int (value, settings != NULL
|
|
? g_settings_get_int (settings, entry->key)
|
|
: entry->fallback.i);
|
|
break;
|
|
case G_TYPE_BOOLEAN:
|
|
g_value_set_boolean (value, settings != NULL
|
|
? g_settings_get_boolean (settings, entry->key)
|
|
: entry->fallback.b);
|
|
break;
|
|
case G_TYPE_NONE:
|
|
if (g_str_equal (entry->setting, "gtk-xft-antialias"))
|
|
g_value_set_int (value, screen_wayland->xft_settings.antialias);
|
|
else if (g_str_equal (entry->setting, "gtk-xft-hinting"))
|
|
g_value_set_int (value, screen_wayland->xft_settings.hinting);
|
|
else if (g_str_equal (entry->setting, "gtk-xft-hintstyle"))
|
|
g_value_set_static_string (value, screen_wayland->xft_settings.hintstyle);
|
|
else if (g_str_equal (entry->setting, "gtk-xft-rgba"))
|
|
g_value_set_static_string (value, screen_wayland->xft_settings.rgba);
|
|
else if (g_str_equal (entry->setting, "gtk-xft-dpi"))
|
|
g_value_set_int (value, screen_wayland->xft_settings.dpi);
|
|
else
|
|
g_assert_not_reached ();
|
|
break;
|
|
default:
|
|
g_assert_not_reached ();
|
|
}
|
|
}
|
|
|
|
static void
|
|
set_decoration_layout_from_entry (GdkScreen *screen,
|
|
TranslationEntry *entry,
|
|
GValue *value)
|
|
{
|
|
GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
|
|
GSettings *settings = NULL;
|
|
const char *session;
|
|
|
|
/* Hack: until we get session-dependent defaults in GSettings,
|
|
* swap out the usual schema for the "classic" one when
|
|
* running in classic mode
|
|
*/
|
|
session = g_getenv ("XDG_CURRENT_DESKTOP");
|
|
if (session && strstr (session, "GNOME-Classic"))
|
|
settings = (GSettings *)g_hash_table_lookup (screen_wayland->settings, CLASSIC_WM_SETTINGS_SCHEMA);
|
|
|
|
if (settings == NULL)
|
|
settings = (GSettings *)g_hash_table_lookup (screen_wayland->settings, WM_SETTINGS_SCHEMA);
|
|
|
|
if (settings)
|
|
{
|
|
gchar *s = g_settings_get_string (settings, entry->key);
|
|
|
|
translate_wm_button_layout_to_gtk (s);
|
|
g_value_set_string (value, s);
|
|
|
|
g_free (s);
|
|
}
|
|
else
|
|
{
|
|
g_value_set_static_string (value, entry->fallback.s);
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
set_capability_setting (GdkScreen *screen,
|
|
GValue *value,
|
|
enum gtk_shell1_capability test)
|
|
{
|
|
GdkWaylandScreen *wayland_screen = GDK_WAYLAND_SCREEN (screen);
|
|
|
|
g_value_set_boolean (value, (wayland_screen->shell_capabilities & test) == test);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
gdk_wayland_screen_get_setting (GdkScreen *screen,
|
|
const gchar *name,
|
|
GValue *value)
|
|
{
|
|
TranslationEntry *entry;
|
|
|
|
g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
|
|
|
|
entry = find_translation_entry_by_setting (name);
|
|
if (entry != NULL)
|
|
{
|
|
if (strcmp (name, "gtk-decoration-layout") == 0)
|
|
set_decoration_layout_from_entry (screen, entry, value);
|
|
else
|
|
set_value_from_entry (screen, entry, value);
|
|
return TRUE;
|
|
}
|
|
|
|
if (strcmp (name, "gtk-shell-shows-app-menu") == 0)
|
|
return set_capability_setting (screen, value,
|
|
GTK_SHELL1_CAPABILITY_GLOBAL_APP_MENU);
|
|
|
|
if (strcmp (name, "gtk-shell-shows-menubar") == 0)
|
|
return set_capability_setting (screen, value,
|
|
GTK_SHELL1_CAPABILITY_GLOBAL_MENU_BAR);
|
|
|
|
if (strcmp (name, "gtk-shell-shows-desktop") == 0)
|
|
return set_capability_setting (screen, value,
|
|
GTK_SHELL1_CAPABILITY_DESKTOP_ICONS);
|
|
|
|
if (strcmp (name, "gtk-dialogs-use-header") == 0)
|
|
{
|
|
g_value_set_boolean (value, TRUE);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
typedef struct _GdkWaylandVisual GdkWaylandVisual;
|
|
typedef struct _GdkWaylandVisualClass GdkWaylandVisualClass;
|
|
|
|
struct _GdkWaylandVisual
|
|
{
|
|
GdkVisual visual;
|
|
};
|
|
|
|
struct _GdkWaylandVisualClass
|
|
{
|
|
GdkVisualClass parent_class;
|
|
};
|
|
|
|
GType _gdk_wayland_visual_get_type (void);
|
|
|
|
G_DEFINE_TYPE (GdkWaylandVisual, _gdk_wayland_visual, GDK_TYPE_VISUAL)
|
|
|
|
static void
|
|
_gdk_wayland_visual_class_init (GdkWaylandVisualClass *klass)
|
|
{
|
|
}
|
|
|
|
static void
|
|
_gdk_wayland_visual_init (GdkWaylandVisual *visual)
|
|
{
|
|
}
|
|
|
|
static gint
|
|
gdk_wayland_screen_visual_get_best_depth (GdkScreen *screen)
|
|
{
|
|
return 32;
|
|
}
|
|
|
|
static GdkVisualType
|
|
gdk_wayland_screen_visual_get_best_type (GdkScreen *screen)
|
|
{
|
|
return GDK_VISUAL_TRUE_COLOR;
|
|
}
|
|
|
|
static GdkVisual*
|
|
gdk_wayland_screen_visual_get_best (GdkScreen *screen)
|
|
{
|
|
return GDK_WAYLAND_SCREEN (screen)->visual;
|
|
}
|
|
|
|
static GdkVisual*
|
|
gdk_wayland_screen_visual_get_best_with_depth (GdkScreen *screen,
|
|
gint depth)
|
|
{
|
|
return GDK_WAYLAND_SCREEN (screen)->visual;
|
|
}
|
|
|
|
static GdkVisual*
|
|
gdk_wayland_screen_visual_get_best_with_type (GdkScreen *screen,
|
|
GdkVisualType visual_type)
|
|
{
|
|
return GDK_WAYLAND_SCREEN (screen)->visual;
|
|
}
|
|
|
|
static GdkVisual*
|
|
gdk_wayland_screen_visual_get_best_with_both (GdkScreen *screen,
|
|
gint depth,
|
|
GdkVisualType visual_type)
|
|
{
|
|
return GDK_WAYLAND_SCREEN (screen)->visual;
|
|
}
|
|
|
|
static void
|
|
gdk_wayland_screen_query_depths (GdkScreen *screen,
|
|
gint **depths,
|
|
gint *count)
|
|
{
|
|
static gint static_depths[] = { 32 };
|
|
|
|
*count = G_N_ELEMENTS(static_depths);
|
|
*depths = static_depths;
|
|
}
|
|
|
|
static void
|
|
gdk_wayland_screen_query_visual_types (GdkScreen *screen,
|
|
GdkVisualType **visual_types,
|
|
gint *count)
|
|
{
|
|
static GdkVisualType static_visual_types[] = { GDK_VISUAL_TRUE_COLOR };
|
|
|
|
*count = G_N_ELEMENTS(static_visual_types);
|
|
*visual_types = static_visual_types;
|
|
}
|
|
|
|
static GList *
|
|
gdk_wayland_screen_list_visuals (GdkScreen *screen)
|
|
{
|
|
GList *list;
|
|
GdkWaylandScreen *screen_wayland;
|
|
|
|
g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
|
|
screen_wayland = GDK_WAYLAND_SCREEN (screen);
|
|
|
|
list = g_list_append (NULL, screen_wayland->visual);
|
|
|
|
return list;
|
|
}
|
|
|
|
#define GDK_TYPE_WAYLAND_VISUAL (_gdk_wayland_visual_get_type ())
|
|
#define GDK_WAYLAND_VISUAL(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WAYLAND_VISUAL, GdkWaylandVisual))
|
|
|
|
static GdkVisual *
|
|
gdk_wayland_visual_new (GdkScreen *screen)
|
|
{
|
|
GdkVisual *visual;
|
|
|
|
visual = g_object_new (GDK_TYPE_WAYLAND_VISUAL, NULL);
|
|
visual->screen = GDK_SCREEN (screen);
|
|
visual->type = GDK_VISUAL_TRUE_COLOR;
|
|
visual->depth = 32;
|
|
visual->bits_per_rgb = 8;
|
|
|
|
return visual;
|
|
}
|
|
|
|
GdkScreen *
|
|
_gdk_wayland_screen_new (GdkDisplay *display)
|
|
{
|
|
GdkScreen *screen;
|
|
GdkWaylandScreen *screen_wayland;
|
|
|
|
screen = g_object_new (GDK_TYPE_WAYLAND_SCREEN, NULL);
|
|
|
|
screen_wayland = GDK_WAYLAND_SCREEN (screen);
|
|
screen_wayland->display = display;
|
|
screen_wayland->width = 0;
|
|
screen_wayland->height = 0;
|
|
|
|
screen_wayland->visual = gdk_wayland_visual_new (screen);
|
|
|
|
init_multihead (screen);
|
|
|
|
screen_wayland->root_window =
|
|
_gdk_wayland_screen_create_root_window (screen,
|
|
screen_wayland->width,
|
|
screen_wayland->height);
|
|
|
|
init_settings (screen);
|
|
|
|
return screen;
|
|
}
|
|
|
|
static void
|
|
_gdk_wayland_screen_class_init (GdkWaylandScreenClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
GdkScreenClass *screen_class = GDK_SCREEN_CLASS (klass);
|
|
|
|
object_class->dispose = gdk_wayland_screen_dispose;
|
|
object_class->finalize = gdk_wayland_screen_finalize;
|
|
|
|
screen_class->get_display = gdk_wayland_screen_get_display;
|
|
screen_class->get_width = gdk_wayland_screen_get_width;
|
|
screen_class->get_height = gdk_wayland_screen_get_height;
|
|
screen_class->get_width_mm = gdk_wayland_screen_get_width_mm;
|
|
screen_class->get_height_mm = gdk_wayland_screen_get_height_mm;
|
|
screen_class->get_number = gdk_wayland_screen_get_number;
|
|
screen_class->get_root_window = gdk_wayland_screen_get_root_window;
|
|
screen_class->get_n_monitors = gdk_wayland_screen_get_n_monitors;
|
|
screen_class->get_primary_monitor = gdk_wayland_screen_get_primary_monitor;
|
|
screen_class->get_monitor_width_mm = gdk_wayland_screen_get_monitor_width_mm;
|
|
screen_class->get_monitor_height_mm = gdk_wayland_screen_get_monitor_height_mm;
|
|
screen_class->get_monitor_plug_name = gdk_wayland_screen_get_monitor_plug_name;
|
|
screen_class->get_monitor_geometry = gdk_wayland_screen_get_monitor_geometry;
|
|
screen_class->get_monitor_workarea = gdk_wayland_screen_get_monitor_geometry;
|
|
screen_class->get_monitor_scale_factor = gdk_wayland_screen_get_monitor_scale_factor;
|
|
screen_class->get_system_visual = gdk_wayland_screen_get_system_visual;
|
|
screen_class->get_rgba_visual = gdk_wayland_screen_get_rgba_visual;
|
|
screen_class->is_composited = gdk_wayland_screen_is_composited;
|
|
screen_class->make_display_name = gdk_wayland_screen_make_display_name;
|
|
screen_class->get_active_window = gdk_wayland_screen_get_active_window;
|
|
screen_class->get_window_stack = gdk_wayland_screen_get_window_stack;
|
|
screen_class->broadcast_client_message = gdk_wayland_screen_broadcast_client_message;
|
|
screen_class->get_setting = gdk_wayland_screen_get_setting;
|
|
screen_class->visual_get_best_depth = gdk_wayland_screen_visual_get_best_depth;
|
|
screen_class->visual_get_best_type = gdk_wayland_screen_visual_get_best_type;
|
|
screen_class->visual_get_best = gdk_wayland_screen_visual_get_best;
|
|
screen_class->visual_get_best_with_depth = gdk_wayland_screen_visual_get_best_with_depth;
|
|
screen_class->visual_get_best_with_type = gdk_wayland_screen_visual_get_best_with_type;
|
|
screen_class->visual_get_best_with_both = gdk_wayland_screen_visual_get_best_with_both;
|
|
screen_class->query_depths = gdk_wayland_screen_query_depths;
|
|
screen_class->query_visual_types = gdk_wayland_screen_query_visual_types;
|
|
screen_class->list_visuals = gdk_wayland_screen_list_visuals;
|
|
}
|
|
|
|
static void
|
|
_gdk_wayland_screen_init (GdkWaylandScreen *screen_wayland)
|
|
{
|
|
}
|
|
|
|
static void
|
|
update_screen_size (GdkWaylandScreen *screen_wayland)
|
|
{
|
|
gboolean emit_changed = FALSE;
|
|
gint width, height;
|
|
gint width_mm, height_mm;
|
|
gint i;
|
|
|
|
width = height = 0;
|
|
width_mm = height_mm = 0;
|
|
for (i = 0; i < screen_wayland->monitors->len; i++)
|
|
{
|
|
GdkWaylandMonitor *monitor = screen_wayland->monitors->pdata[i];
|
|
|
|
/* XXX: Largely assuming here that monitor areas
|
|
* are contiguous and never overlap.
|
|
*/
|
|
if (monitor->geometry.x > 0)
|
|
width_mm += monitor->width_mm;
|
|
else
|
|
width_mm = MAX (width_mm, monitor->width_mm);
|
|
|
|
if (monitor->geometry.y > 0)
|
|
height_mm += monitor->height_mm;
|
|
else
|
|
height_mm = MAX (height_mm, monitor->height_mm);
|
|
|
|
width = MAX (width, monitor->geometry.x + monitor->geometry.width);
|
|
height = MAX (height, monitor->geometry.y + monitor->geometry.height);
|
|
}
|
|
|
|
if (screen_wayland->width_mm != width_mm ||
|
|
screen_wayland->height_mm != height_mm)
|
|
{
|
|
emit_changed = TRUE;
|
|
screen_wayland->width_mm = width_mm;
|
|
screen_wayland->height_mm = height_mm;
|
|
}
|
|
|
|
if (screen_wayland->width != width ||
|
|
screen_wayland->height != height)
|
|
{
|
|
emit_changed = TRUE;
|
|
screen_wayland->width = width;
|
|
screen_wayland->height = height;
|
|
}
|
|
|
|
if (emit_changed)
|
|
g_signal_emit_by_name (screen_wayland, "size-changed");
|
|
}
|
|
|
|
static void
|
|
output_handle_geometry (void *data,
|
|
struct wl_output *wl_output,
|
|
int x,
|
|
int y,
|
|
int physical_width,
|
|
int physical_height,
|
|
int subpixel,
|
|
const char *make,
|
|
const char *model,
|
|
int32_t transform)
|
|
{
|
|
GdkWaylandMonitor *monitor = (GdkWaylandMonitor *)data;
|
|
|
|
GDK_NOTE (MISC,
|
|
g_message ("handle geometry output %d, position %d %d, phys. size %d %d, manufacturer %s, model %s",
|
|
monitor->id, x, y, physical_width, physical_height, make, model));
|
|
|
|
monitor->geometry.x = x;
|
|
monitor->geometry.y = y;
|
|
|
|
monitor->width_mm = physical_width;
|
|
monitor->height_mm = physical_height;
|
|
|
|
monitor->manufacturer = g_strdup (make);
|
|
monitor->output_name = g_strdup (model);
|
|
|
|
if (monitor->geometry.width != 0 && monitor->version < OUTPUT_VERSION_WITH_DONE)
|
|
{
|
|
g_signal_emit_by_name (monitor->screen, "monitors-changed");
|
|
update_screen_size (monitor->screen);
|
|
}
|
|
}
|
|
|
|
static void
|
|
output_handle_done (void *data,
|
|
struct wl_output *wl_output)
|
|
{
|
|
GdkWaylandMonitor *monitor = (GdkWaylandMonitor *)data;
|
|
|
|
GDK_NOTE (MISC,
|
|
g_message ("handle done output %d", monitor->id));
|
|
|
|
g_signal_emit_by_name (monitor->screen, "monitors-changed");
|
|
update_screen_size (monitor->screen);
|
|
}
|
|
|
|
static void
|
|
output_handle_scale (void *data,
|
|
struct wl_output *wl_output,
|
|
int32_t scale)
|
|
{
|
|
GdkWaylandMonitor *monitor = (GdkWaylandMonitor *)data;
|
|
|
|
GDK_NOTE (MISC,
|
|
g_message ("handle scale output %d, scale %d", monitor->id, scale));
|
|
|
|
monitor->scale = scale;
|
|
|
|
if (monitor->geometry.width != 0 && monitor->version < OUTPUT_VERSION_WITH_DONE)
|
|
g_signal_emit_by_name (monitor->screen, "monitors-changed");
|
|
}
|
|
|
|
static void
|
|
output_handle_mode (void *data,
|
|
struct wl_output *wl_output,
|
|
uint32_t flags,
|
|
int width,
|
|
int height,
|
|
int refresh)
|
|
{
|
|
GdkWaylandMonitor *monitor = (GdkWaylandMonitor *)data;
|
|
|
|
GDK_NOTE (MISC,
|
|
g_message ("handle mode output %d, size %d %d, rate %d",
|
|
monitor->id, width, height, refresh));
|
|
|
|
if ((flags & WL_OUTPUT_MODE_CURRENT) == 0)
|
|
return;
|
|
|
|
monitor->geometry.width = width;
|
|
monitor->geometry.height = height;
|
|
monitor->refresh_rate = refresh;
|
|
|
|
if (monitor->geometry.width != 0 && monitor->version < OUTPUT_VERSION_WITH_DONE)
|
|
{
|
|
g_signal_emit_by_name (monitor->screen, "monitors-changed");
|
|
update_screen_size (monitor->screen);
|
|
}
|
|
}
|
|
|
|
static const struct wl_output_listener output_listener =
|
|
{
|
|
output_handle_geometry,
|
|
output_handle_mode,
|
|
output_handle_done,
|
|
output_handle_scale,
|
|
};
|
|
|
|
void
|
|
_gdk_wayland_screen_add_output (GdkScreen *screen,
|
|
guint32 id,
|
|
struct wl_output *output,
|
|
guint32 version)
|
|
{
|
|
GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
|
|
GdkWaylandMonitor *monitor;
|
|
|
|
monitor = g_new0 (GdkWaylandMonitor, 1);
|
|
|
|
monitor->id = id;
|
|
monitor->output = output;
|
|
monitor->version = version;
|
|
monitor->screen = screen_wayland;
|
|
monitor->scale = 1;
|
|
|
|
g_ptr_array_add (screen_wayland->monitors, monitor);
|
|
|
|
wl_output_add_listener (output, &output_listener, monitor);
|
|
}
|
|
|
|
struct wl_output *
|
|
_gdk_wayland_screen_get_wl_output (GdkScreen *screen,
|
|
gint monitor_num)
|
|
{
|
|
GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
|
|
GdkWaylandMonitor *monitor = g_ptr_array_index (screen_wayland->monitors, monitor_num);
|
|
return monitor->output;
|
|
}
|
|
|
|
void
|
|
_gdk_wayland_screen_remove_output (GdkScreen *screen,
|
|
guint32 id)
|
|
{
|
|
GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
|
|
int i;
|
|
|
|
for (i = 0; i < screen_wayland->monitors->len; i++)
|
|
{
|
|
GdkWaylandMonitor *monitor = screen_wayland->monitors->pdata[i];
|
|
|
|
if (monitor->id == id)
|
|
{
|
|
g_ptr_array_remove (screen_wayland->monitors, monitor);
|
|
|
|
g_signal_emit_by_name (screen_wayland, "monitors-changed");
|
|
update_screen_size (screen_wayland);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
int
|
|
_gdk_wayland_screen_get_output_refresh_rate (GdkScreen *screen,
|
|
struct wl_output *output)
|
|
{
|
|
GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
|
|
int i;
|
|
|
|
for (i = 0; i < screen_wayland->monitors->len; i++)
|
|
{
|
|
GdkWaylandMonitor *monitor = screen_wayland->monitors->pdata[i];
|
|
|
|
if (monitor->output == output)
|
|
return monitor->refresh_rate;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
guint32
|
|
_gdk_wayland_screen_get_output_scale (GdkScreen *screen,
|
|
struct wl_output *output)
|
|
{
|
|
GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
|
|
int i;
|
|
|
|
for (i = 0; i < screen_wayland->monitors->len; i++)
|
|
{
|
|
GdkWaylandMonitor *monitor = screen_wayland->monitors->pdata[i];
|
|
|
|
if (monitor->output == output)
|
|
return monitor->scale;
|
|
}
|
|
|
|
return 0;
|
|
}
|