Skip to content
Snippets Groups Projects
Commit 67f98e74 authored by Guido Gunther's avatar Guido Gunther :zzz:
Browse files

monitor-manager: Implement org.gnome.Mutter.DisplayConfig {Set,Get}CrtcGamma

This allows GNOME's redshift to work. Since wlroots gamma protocol
doesn't allow to read the gamma ramps fake empty ramps of the right
size. All users only use it to determin the gamma table's size.

Fixes #13
parent 9c679cc0
No related branches found
No related tags found
No related merge requests found
...@@ -22,6 +22,7 @@ phosh_resources = gnome.compile_resources( ...@@ -22,6 +22,7 @@ phosh_resources = gnome.compile_resources(
wl_protos = [ wl_protos = [
'/'.join([wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml']), '/'.join([wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml']),
'../protocol/gamma-control.xml',
'../protocol/idle.xml', '../protocol/idle.xml',
'../protocol/phosh-private.xml', '../protocol/phosh-private.xml',
'../protocol/wlr-input-inhibitor-unstable-v1.xml', '../protocol/wlr-input-inhibitor-unstable-v1.xml',
......
...@@ -10,8 +10,13 @@ ...@@ -10,8 +10,13 @@
#include "monitor-manager.h" #include "monitor-manager.h"
#include "monitor/monitor.h" #include "monitor/monitor.h"
#include "gamma-control-client-protocol.h"
#include "phosh.h"
#include <gdk/gdkwayland.h> #include <gdk/gdkwayland.h>
static void phosh_monitor_manager_display_config_init ( static void phosh_monitor_manager_display_config_init (
PhoshDisplayDbusOrgGnomeMutterDisplayConfigIface *iface); PhoshDisplayDbusOrgGnomeMutterDisplayConfigIface *iface);
...@@ -135,6 +140,7 @@ phosh_monitor_manager_handle_get_resources ( ...@@ -135,6 +140,7 @@ phosh_monitor_manager_handle_get_resources (
return TRUE; return TRUE;
} }
static gboolean static gboolean
phosh_monitor_manager_handle_change_backlight ( phosh_monitor_manager_handle_change_backlight (
PhoshDisplayDbusOrgGnomeMutterDisplayConfig *skeleton, PhoshDisplayDbusOrgGnomeMutterDisplayConfig *skeleton,
...@@ -148,6 +154,52 @@ phosh_monitor_manager_handle_change_backlight ( ...@@ -148,6 +154,52 @@ phosh_monitor_manager_handle_change_backlight (
} }
struct get_wl_gamma_callback_data {
PhoshDisplayDbusOrgGnomeMutterDisplayConfig *skeleton;
GDBusMethodInvocation *invocation;
};
static void handle_wl_gamma_size(void *data, struct gamma_control *gamma_control,
uint32_t size) {
struct get_wl_gamma_callback_data *gamma_callback_data = data;
GBytes *red_bytes, *green_bytes, *blue_bytes;
GVariant *red_v, *green_v, *blue_v;
/* All known clients using libgnome-desktop's
gnome_rr_crtc_get_gamma only do so to get the size of the gamma
table. So don't bother getting the real table since this is not
supported by wlroots: https://github.com/swaywm/wlroots/pull/1059.
Return an empty table instead.
*/
size *= sizeof(unsigned short);
red_bytes = g_bytes_new_take (g_malloc0 (size), size);
green_bytes = g_bytes_new_take (g_malloc0 (size), size);
blue_bytes = g_bytes_new_take (g_malloc0 (size), size);
red_v = g_variant_new_from_bytes (G_VARIANT_TYPE ("aq"), red_bytes, TRUE);
green_v = g_variant_new_from_bytes (G_VARIANT_TYPE ("aq"), green_bytes, TRUE);
blue_v = g_variant_new_from_bytes (G_VARIANT_TYPE ("aq"), blue_bytes, TRUE);
phosh_display_dbus_org_gnome_mutter_display_config_complete_get_crtc_gamma (
gamma_callback_data->skeleton,
gamma_callback_data->invocation,
red_v, green_v, blue_v);
g_bytes_unref (red_bytes);
g_bytes_unref (green_bytes);
g_bytes_unref (blue_bytes);
g_free (gamma_callback_data);
gamma_control_destroy (gamma_control);
}
static const struct
gamma_control_listener gamma_control_listener = {
.gamma_size = handle_wl_gamma_size,
};
static gboolean static gboolean
phosh_monitor_manager_handle_get_crtc_gamma ( phosh_monitor_manager_handle_get_crtc_gamma (
PhoshDisplayDbusOrgGnomeMutterDisplayConfig *skeleton, PhoshDisplayDbusOrgGnomeMutterDisplayConfig *skeleton,
...@@ -155,8 +207,47 @@ phosh_monitor_manager_handle_get_crtc_gamma ( ...@@ -155,8 +207,47 @@ phosh_monitor_manager_handle_get_crtc_gamma (
guint serial, guint serial,
guint crtc_id) guint crtc_id)
{ {
g_debug ("Unimplemented DBus call %s\n", __func__); PhoshMonitorManager *self = PHOSH_MONITOR_MANAGER (skeleton);
return FALSE; PhoshMonitor *monitor;
struct gamma_control *gamma_control;
struct gamma_control_manager *gamma_control_manager;
struct get_wl_gamma_callback_data *data;;
g_debug ("DBus call %s for crtc %d, serial %d\n", __func__, crtc_id, serial);
if (serial != self->serial) {
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"The requested configuration is based on stale information");
return TRUE;
}
if (crtc_id >= self->monitors->len) {
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS,
"Invalid crtc id %d", crtc_id);
return TRUE;
}
gamma_control_manager = phosh_shell_get_wl_gamma_control_manager ();
if (gamma_control_manager == NULL) {
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_NOT_SUPPORTED,
"gamma control not supported");
return TRUE;
}
data = g_new0 (struct get_wl_gamma_callback_data, 1);
data->skeleton = skeleton;
data->invocation = invocation;
monitor = g_ptr_array_index (self->monitors, crtc_id);
gamma_control = gamma_control_manager_get_gamma_control (
gamma_control_manager,
monitor->wl_output);
gamma_control_add_listener (gamma_control, &gamma_control_listener, data);
return TRUE;
} }
...@@ -170,8 +261,87 @@ phosh_monitor_manager_handle_set_crtc_gamma ( ...@@ -170,8 +261,87 @@ phosh_monitor_manager_handle_set_crtc_gamma (
GVariant *green_v, GVariant *green_v,
GVariant *blue_v) GVariant *blue_v)
{ {
g_debug ("Unimplemented DBus call %s\n", __func__); PhoshMonitorManager *self = PHOSH_MONITOR_MANAGER (skeleton);
return FALSE; PhoshMonitor *monitor;
unsigned short *red, *green, *blue;
GBytes *red_bytes, *green_bytes, *blue_bytes;
gsize size, dummy;
struct gamma_control_manager *gamma_control_manager;
struct gamma_control *gamma_control;
struct wl_array wl_red, wl_green, wl_blue;
g_debug ("DBus call %s for crtc %d, serial %d\n", __func__, crtc_id, serial);
if (serial != self->serial) {
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"The requested configuration is based on stale information");
return TRUE;
}
if (crtc_id >= self->monitors->len) {
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS,
"Invalid crtc id");
return TRUE;
}
gamma_control_manager = phosh_shell_get_wl_gamma_control_manager ();
if (!gamma_control_manager) {
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_NOT_SUPPORTED,
"gamma control not supported");
return TRUE;
}
monitor = g_ptr_array_index (self->monitors, crtc_id);
red_bytes = g_variant_get_data_as_bytes (red_v);
green_bytes = g_variant_get_data_as_bytes (green_v);
blue_bytes = g_variant_get_data_as_bytes (blue_v);
size = g_bytes_get_size (red_bytes);
if (size != g_bytes_get_size (blue_bytes) || size != g_bytes_get_size (green_bytes)) {
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_NOT_SUPPORTED,
"gamma for each color must have same size");
goto err;
}
red = (unsigned short*) g_bytes_get_data (red_bytes, &dummy);
green = (unsigned short*) g_bytes_get_data (green_bytes, &dummy);
blue = (unsigned short*) g_bytes_get_data (blue_bytes, &dummy);
wl_array_init (&wl_red);
wl_array_init (&wl_green);
wl_array_init (&wl_blue);
wl_array_add (&wl_red, size);
wl_array_add (&wl_green, size);
wl_array_add (&wl_blue, size);
memcpy(wl_red.data, red, size);
memcpy(wl_green.data, green, size);
memcpy(wl_blue.data, blue, size);
gamma_control = gamma_control_manager_get_gamma_control (
gamma_control_manager,
monitor->wl_output);
gamma_control_set_gamma(gamma_control, &wl_red, &wl_green, &wl_blue);
gamma_control_destroy (gamma_control);
phosh_display_dbus_org_gnome_mutter_display_config_complete_set_crtc_gamma (
skeleton,
invocation);
wl_array_release (&wl_red);
wl_array_release (&wl_green);
wl_array_release (&wl_blue);
err:
g_bytes_unref (red_bytes);
g_bytes_unref (green_bytes);
g_bytes_unref (blue_bytes);
return TRUE;
} }
#define MODE_FORMAT "(siiddada{sv})" #define MODE_FORMAT "(siiddada{sv})"
......
...@@ -13,9 +13,11 @@ ...@@ -13,9 +13,11 @@
G_DECLARE_FINAL_TYPE (PhoshMonitorManager, phosh_monitor_manager, PHOSH, MONITOR_MANAGER, G_DECLARE_FINAL_TYPE (PhoshMonitorManager, phosh_monitor_manager, PHOSH, MONITOR_MANAGER,
PhoshDisplayDbusOrgGnomeMutterDisplayConfigSkeleton) PhoshDisplayDbusOrgGnomeMutterDisplayConfigSkeleton)
PhoshMonitorManager * phosh_monitor_manager_new (void); PhoshMonitorManager * phosh_monitor_manager_new (void);
void phosh_monitor_manager_add_monitor (PhoshMonitorManager *self, void phosh_monitor_manager_add_monitor (PhoshMonitorManager *self,
PhoshMonitor *monitor); PhoshMonitor *monitor);
PhoshMonitor * phosh_monitor_manager_get_monitor (PhoshMonitorManager *self, PhoshMonitor * phosh_monitor_manager_get_monitor (PhoshMonitorManager *self,
guint monitor); guint monitor);
guint phosh_monitor_manager_get_num_monitors (PhoshMonitorManager *self); guint phosh_monitor_manager_get_num_monitors (PhoshMonitorManager *self);
void phosh_monitor_manager_set_gamma_control_manager (PhoshMonitorManager *self,
gpointer *gamma);
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#include "wlr-input-inhibitor-unstable-v1-client-protocol.h" #include "wlr-input-inhibitor-unstable-v1-client-protocol.h"
#include "wlr-layer-shell-unstable-v1-client-protocol.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h"
#include "xdg-shell-client-protocol.h" #include "xdg-shell-client-protocol.h"
#include "gamma-control-client-protocol.h"
#include "phosh.h" #include "phosh.h"
#include "monitor/monitor.h" /* FIXME: move upwards? */ #include "monitor/monitor.h" /* FIXME: move upwards? */
...@@ -70,6 +70,7 @@ typedef struct ...@@ -70,6 +70,7 @@ typedef struct
struct org_kde_kwin_idle *idle_manager; struct org_kde_kwin_idle *idle_manager;
struct zwlr_input_inhibit_manager_v1 *input_inhibit_manager; struct zwlr_input_inhibit_manager_v1 *input_inhibit_manager;
struct zwlr_input_inhibitor_v1 *input_inhibitor; struct zwlr_input_inhibitor_v1 *input_inhibitor;
struct gamma_control_manager *gamma_control_manager;
struct wl_seat *wl_seat; struct wl_seat *wl_seat;
struct xdg_wm_base *xdg_wm_base; struct xdg_wm_base *xdg_wm_base;
...@@ -653,24 +654,36 @@ registry_handle_global (void *data, ...@@ -653,24 +654,36 @@ registry_handle_global (void *data,
PhoshShellPrivate *priv = phosh_shell_get_instance_private (self); PhoshShellPrivate *priv = phosh_shell_get_instance_private (self);
struct wl_output *output; struct wl_output *output;
if (!strcmp (interface, "phosh_private")) { if (!strcmp (interface, "phosh_private")) {
priv->mshell = wl_registry_bind (registry, name, priv->mshell = wl_registry_bind (
&phosh_private_interface, 1); registry,
name,
&phosh_private_interface,
1);
} else if (!strcmp (interface, zwlr_layer_shell_v1_interface.name)) { } else if (!strcmp (interface, zwlr_layer_shell_v1_interface.name)) {
priv->layer_shell = wl_registry_bind (registry, name, priv->layer_shell = wl_registry_bind (
&zwlr_layer_shell_v1_interface, 1); registry,
name,
&zwlr_layer_shell_v1_interface,
1);
} else if (!strcmp (interface, "wl_output")) { } else if (!strcmp (interface, "wl_output")) {
output = wl_registry_bind (registry, name, output = wl_registry_bind (
&wl_output_interface, 1); registry,
phosh_monitor_manager_add_monitor (priv->monitor_manager, name,
phosh_monitor_new_from_wl_output(output)); &wl_output_interface, 1);
phosh_monitor_manager_add_monitor (
priv->monitor_manager,
phosh_monitor_new_from_wl_output(output));
} else if (!strcmp (interface, "org_kde_kwin_idle")) { } else if (!strcmp (interface, "org_kde_kwin_idle")) {
priv->idle_manager = wl_registry_bind (registry, priv->idle_manager = wl_registry_bind (
name, registry,
&org_kde_kwin_idle_interface, 1); name,
&org_kde_kwin_idle_interface,
1);
} else if (!strcmp(interface, "wl_seat")) { } else if (!strcmp(interface, "wl_seat")) {
priv->wl_seat = wl_registry_bind(registry, name, &wl_seat_interface, 1); priv->wl_seat = wl_registry_bind(
registry, name, &wl_seat_interface,
1);
} else if (!strcmp(interface, zwlr_input_inhibit_manager_v1_interface.name)) { } else if (!strcmp(interface, zwlr_input_inhibit_manager_v1_interface.name)) {
priv->input_inhibit_manager = wl_registry_bind( priv->input_inhibit_manager = wl_registry_bind(
registry, registry,
...@@ -678,7 +691,17 @@ registry_handle_global (void *data, ...@@ -678,7 +691,17 @@ registry_handle_global (void *data,
&zwlr_input_inhibit_manager_v1_interface, &zwlr_input_inhibit_manager_v1_interface,
1); 1);
} else if (!strcmp(interface, xdg_wm_base_interface.name)) { } else if (!strcmp(interface, xdg_wm_base_interface.name)) {
priv->xdg_wm_base = wl_registry_bind(registry, name, &xdg_wm_base_interface, 1); priv->xdg_wm_base = wl_registry_bind(
registry,
name,
&xdg_wm_base_interface,
1);
} else if (!strcmp(interface, gamma_control_manager_interface.name)) {
priv->gamma_control_manager = wl_registry_bind(
registry,
name,
&gamma_control_manager_interface,
1);
} }
} }
...@@ -768,7 +791,7 @@ phosh_shell_constructed (GObject *object) ...@@ -768,7 +791,7 @@ phosh_shell_constructed (GObject *object)
{ {
PhoshShell *self = PHOSH_SHELL (object); PhoshShell *self = PHOSH_SHELL (object);
PhoshShellPrivate *priv = phosh_shell_get_instance_private (self); PhoshShellPrivate *priv = phosh_shell_get_instance_private (self);
guint num_mon;; guint num_mon;
G_OBJECT_CLASS (phosh_shell_parent_class)->constructed (object); G_OBJECT_CLASS (phosh_shell_parent_class)->constructed (object);
...@@ -788,26 +811,34 @@ phosh_shell_constructed (GObject *object) ...@@ -788,26 +811,34 @@ phosh_shell_constructed (GObject *object)
/* Wait until we have been notified about the compositor, /* Wait until we have been notified about the compositor,
* shell, and shell helper objects */ * shell, and shell helper objects */
num_mon = phosh_monitor_manager_get_num_monitors (priv->monitor_manager); num_mon = phosh_monitor_manager_get_num_monitors (priv->monitor_manager);
if (!num_mon || !priv->layer_shell || !priv->idle_manager || if (!num_mon ||
!priv->input_inhibit_manager || !priv->mshell || !priv->xdg_wm_base) !priv->layer_shell ||
!priv->idle_manager ||
!priv->input_inhibit_manager ||
!priv->mshell ||
!priv->xdg_wm_base ||
!priv->gamma_control_manager)
wl_display_roundtrip (priv->display); wl_display_roundtrip (priv->display);
num_mon = phosh_monitor_manager_get_num_monitors (priv->monitor_manager); num_mon = phosh_monitor_manager_get_num_monitors (priv->monitor_manager);
if (!num_mon || !priv->layer_shell || !priv->idle_manager || if (!num_mon ||
!priv->input_inhibit_manager || !priv->xdg_wm_base) { !priv->layer_shell ||
!priv->idle_manager ||
!priv->input_inhibit_manager ||
!priv->xdg_wm_base ||
!priv->gamma_control_manager) {
g_error ("Could not find needed globals\n" g_error ("Could not find needed globals\n"
"outputs: %d, layer_shell: %p, seat: %p, " "outputs: %d, layer_shell: %p, seat: %p, "
"inhibit: %p, xdg_wm: %p\n", "inhibit: %p, xdg_wm: %p, gamma %p\n",
num_mon, priv->layer_shell, priv->idle_manager, num_mon, priv->layer_shell, priv->idle_manager,
priv->input_inhibit_manager, priv->xdg_wm_base); priv->input_inhibit_manager, priv->xdg_wm_base,
priv->gamma_control_manager);
} }
if (!priv->mshell) { if (!priv->mshell) {
g_info ("Could not find phosh global, disabling some features\n"); g_info ("Could not find phosh global, disabling some features\n");
} }
gtk_icon_theme_add_resource_path (gtk_icon_theme_get_default (), gtk_icon_theme_add_resource_path (gtk_icon_theme_get_default (),
"/sm/puri/phosh/icons"); "/sm/puri/phosh/icons");
env_setup (); env_setup ();
css_setup (self); css_setup (self);
panel_create (self); panel_create (self);
...@@ -884,6 +915,14 @@ phosh_shell_get_wl_layer_shell () ...@@ -884,6 +915,14 @@ phosh_shell_get_wl_layer_shell ()
} }
gpointer
phosh_shell_get_wl_gamma_control_manager ()
{
PhoshShellPrivate *priv = phosh_shell_get_instance_private (_phosh);
return priv->gamma_control_manager;
}
PhoshMonitor * PhoshMonitor *
phosh_shell_get_primary_monitor () phosh_shell_get_primary_monitor ()
{ {
......
...@@ -31,4 +31,5 @@ PhoshMonitor *phosh_shell_get_primary_monitor (); ...@@ -31,4 +31,5 @@ PhoshMonitor *phosh_shell_get_primary_monitor ();
/* Phosh keeps track of the wayland globals */ /* Phosh keeps track of the wayland globals */
gpointer phosh_shell_get_wl_layer_shell (); gpointer phosh_shell_get_wl_layer_shell ();
gpointer phosh_shell_get_wl_gamma_control_manager ();
#endif /* PHOSH_H */ #endif /* PHOSH_H */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment