Compare commits
	
		
			33 Commits
		
	
	
		
			wip/hadess
			...
			wip/displa
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					78b41e542b | ||
| 
						 | 
					13557b39d0 | ||
| 
						 | 
					39aecd2dde | ||
| 
						 | 
					c564515ef6 | ||
| 
						 | 
					d7b2ea37b1 | ||
| 
						 | 
					0a1e0fe132 | ||
| 
						 | 
					1a0513ea61 | ||
| 
						 | 
					028fa6cd4e | ||
| 
						 | 
					194b11186c | ||
| 
						 | 
					40f064abc3 | ||
| 
						 | 
					27b8716795 | ||
| 
						 | 
					50b44d0445 | ||
| 
						 | 
					c74d40ac41 | ||
| 
						 | 
					c21f7d43bd | ||
| 
						 | 
					80e0b4aac9 | ||
| 
						 | 
					12cd4c216b | ||
| 
						 | 
					91d193e5e8 | ||
| 
						 | 
					f82f3ef67b | ||
| 
						 | 
					6125b3fa7e | ||
| 
						 | 
					169780346b | ||
| 
						 | 
					9b255f9292 | ||
| 
						 | 
					60e11fbae3 | ||
| 
						 | 
					355f0258b1 | ||
| 
						 | 
					09984bb56d | ||
| 
						 | 
					f48ddb3683 | ||
| 
						 | 
					9ac92336c9 | ||
| 
						 | 
					2bc5e89a5e | ||
| 
						 | 
					a413bc106f | ||
| 
						 | 
					b04ac57f02 | ||
| 
						 | 
					c3a08ee589 | ||
| 
						 | 
					1fdb161f54 | ||
| 
						 | 
					f3d1653f13 | ||
| 
						 | 
					3093b5c95d | 
@@ -75,6 +75,8 @@ MUTTER_PC_MODULES="
 | 
			
		||||
   xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
 | 
			
		||||
   $CLUTTER_PACKAGE >= 1.14.3
 | 
			
		||||
   cogl-1.0 >= 1.13.3
 | 
			
		||||
   upower-glib > 0.9.11
 | 
			
		||||
   gnome-desktop-3.0
 | 
			
		||||
"
 | 
			
		||||
 | 
			
		||||
GLIB_GSETTINGS
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@ INCLUDES=								\
 | 
			
		||||
	-DMUTTER_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\"		\
 | 
			
		||||
	-DMUTTER_PKGDATADIR=\"$(pkgdatadir)\"				\
 | 
			
		||||
	-DMUTTER_DATADIR=\"$(datadir)\"					\
 | 
			
		||||
	-DG_LOG_DOMAIN=\"mutter\"					\
 | 
			
		||||
	-DG_LOG_DOMAIN=\"Mutter\"					\
 | 
			
		||||
	-DSN_API_NOT_YET_FROZEN=1					\
 | 
			
		||||
	-DMUTTER_MAJOR_VERSION=$(MUTTER_MAJOR_VERSION)			\
 | 
			
		||||
	-DMUTTER_MINOR_VERSION=$(MUTTER_MINOR_VERSION)			\
 | 
			
		||||
@@ -30,6 +30,7 @@ INCLUDES=								\
 | 
			
		||||
	-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\"
 | 
			
		||||
 | 
			
		||||
mutter_built_sources = \
 | 
			
		||||
	$(dbus_xrandr_built_sources)	\
 | 
			
		||||
	mutter-enum-types.h \
 | 
			
		||||
	mutter-enum-types.c
 | 
			
		||||
 | 
			
		||||
@@ -94,6 +95,8 @@ libmutter_la_SOURCES =				\
 | 
			
		||||
	ui/draw-workspace.h			\
 | 
			
		||||
	core/edge-resistance.c			\
 | 
			
		||||
	core/edge-resistance.h			\
 | 
			
		||||
	core/edid-parse.c			\
 | 
			
		||||
	core/edid.h				\
 | 
			
		||||
	core/errors.c				\
 | 
			
		||||
	meta/errors.h				\
 | 
			
		||||
	core/frame.c				\
 | 
			
		||||
@@ -110,6 +113,11 @@ libmutter_la_SOURCES =				\
 | 
			
		||||
	core/keybindings.c			\
 | 
			
		||||
	core/keybindings-private.h		\
 | 
			
		||||
	core/main.c				\
 | 
			
		||||
	core/meta-xrandr-shared.h		\
 | 
			
		||||
	core/monitor.c				\
 | 
			
		||||
	core/monitor-config.c			\
 | 
			
		||||
	core/monitor-private.h			\
 | 
			
		||||
	core/monitor-xrandr.c			\
 | 
			
		||||
	core/mutter-Xatomtype.h			\
 | 
			
		||||
	core/place.c				\
 | 
			
		||||
	core/place.h				\
 | 
			
		||||
@@ -323,3 +331,12 @@ mutter-enum-types.c: stamp-mutter-enum-types.h mutter-enum-types.c.in
 | 
			
		||||
	  $(libmutterinclude_base_headers) ) >> xgen-tetc && \
 | 
			
		||||
	cp xgen-tetc mutter-enum-types.c && \
 | 
			
		||||
	rm -f xgen-tetc
 | 
			
		||||
 | 
			
		||||
dbus_xrandr_built_sources = meta-dbus-xrandr.c meta-dbus-xrandr.h
 | 
			
		||||
 | 
			
		||||
$(dbus_xrandr_built_sources) : Makefile.am xrandr.xml
 | 
			
		||||
	$(AM_V_GEN)gdbus-codegen								\
 | 
			
		||||
		--interface-prefix org.gnome.Mutter					\
 | 
			
		||||
		--c-namespace MetaDBus							\
 | 
			
		||||
		--generate-c-code meta-dbus-xrandr					\
 | 
			
		||||
		xrandr.xml
 | 
			
		||||
 
 | 
			
		||||
@@ -73,13 +73,12 @@ void
 | 
			
		||||
meta_background_group_set_visible_region (MetaBackgroundGroup *self,
 | 
			
		||||
                                          cairo_region_t      *region)
 | 
			
		||||
{
 | 
			
		||||
  GList *children, *l;
 | 
			
		||||
  ClutterActorIter iter;
 | 
			
		||||
  ClutterActor *actor;
 | 
			
		||||
 | 
			
		||||
  children = clutter_actor_get_children (CLUTTER_ACTOR (self));
 | 
			
		||||
  for (l = children; l; l = l->next)
 | 
			
		||||
  clutter_actor_iter_init (&iter, CLUTTER_ACTOR (self));
 | 
			
		||||
  while (clutter_actor_iter_next (&iter, &actor))
 | 
			
		||||
    {
 | 
			
		||||
      ClutterActor *actor = l->data;
 | 
			
		||||
 | 
			
		||||
      if (META_IS_BACKGROUND_ACTOR (actor))
 | 
			
		||||
        {
 | 
			
		||||
          meta_background_actor_set_visible_region (META_BACKGROUND_ACTOR (actor), region);
 | 
			
		||||
@@ -96,7 +95,6 @@ meta_background_group_set_visible_region (MetaBackgroundGroup *self,
 | 
			
		||||
          cairo_region_translate (region, x, y);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  g_list_free (children);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ClutterActor *
 | 
			
		||||
 
 | 
			
		||||
@@ -85,12 +85,20 @@ meta_plugin_manager_load (const gchar       *plugin_name)
 | 
			
		||||
  g_free (path);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_confirm_display_change (MetaMonitorManager *monitors,
 | 
			
		||||
                           MetaPluginManager  *plugin_mgr)
 | 
			
		||||
{
 | 
			
		||||
  meta_plugin_manager_confirm_display_change (plugin_mgr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaPluginManager *
 | 
			
		||||
meta_plugin_manager_new (MetaScreen *screen)
 | 
			
		||||
{
 | 
			
		||||
  MetaPluginManager *plugin_mgr;
 | 
			
		||||
  MetaPluginClass *klass;
 | 
			
		||||
  MetaPlugin *plugin;
 | 
			
		||||
  MetaMonitorManager *monitors;
 | 
			
		||||
 | 
			
		||||
  plugin_mgr = g_new0 (MetaPluginManager, 1);
 | 
			
		||||
  plugin_mgr->screen = screen;
 | 
			
		||||
@@ -101,6 +109,10 @@ meta_plugin_manager_new (MetaScreen *screen)
 | 
			
		||||
  if (klass->start)
 | 
			
		||||
    klass->start (plugin);
 | 
			
		||||
 | 
			
		||||
  monitors = meta_monitor_manager_get ();
 | 
			
		||||
  g_signal_connect (monitors, "confirm-display-change",
 | 
			
		||||
                    G_CALLBACK (on_confirm_display_change), plugin_mgr);
 | 
			
		||||
 | 
			
		||||
  return plugin_mgr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -320,3 +332,15 @@ meta_plugin_manager_xevent_filter (MetaPluginManager *plugin_mgr,
 | 
			
		||||
  else
 | 
			
		||||
    return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_plugin_manager_confirm_display_change (MetaPluginManager *plugin_mgr)
 | 
			
		||||
{
 | 
			
		||||
  MetaPlugin *plugin = plugin_mgr->plugin;
 | 
			
		||||
  MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
 | 
			
		||||
 | 
			
		||||
  if (klass->confirm_display_change)
 | 
			
		||||
    return klass->confirm_display_change (plugin);
 | 
			
		||||
  else
 | 
			
		||||
    return meta_plugin_complete_display_change (plugin, TRUE);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -73,4 +73,6 @@ gboolean meta_plugin_manager_filter_keybinding (MetaPluginManager  *mgr,
 | 
			
		||||
gboolean meta_plugin_manager_xevent_filter (MetaPluginManager *mgr,
 | 
			
		||||
                                            XEvent            *xev);
 | 
			
		||||
 | 
			
		||||
void     meta_plugin_manager_confirm_display_change (MetaPluginManager *mgr);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -41,6 +41,7 @@
 | 
			
		||||
 | 
			
		||||
#include "compositor-private.h"
 | 
			
		||||
#include "meta-window-actor-private.h"
 | 
			
		||||
#include "monitor-private.h"
 | 
			
		||||
 | 
			
		||||
G_DEFINE_ABSTRACT_TYPE (MetaPlugin, meta_plugin, G_TYPE_OBJECT);
 | 
			
		||||
 | 
			
		||||
@@ -338,3 +339,13 @@ meta_plugin_get_screen (MetaPlugin *plugin)
 | 
			
		||||
 | 
			
		||||
  return priv->screen;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_plugin_complete_display_change (MetaPlugin *plugin,
 | 
			
		||||
                                     gboolean    ok)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManager *manager;
 | 
			
		||||
 | 
			
		||||
  manager = meta_monitor_manager_get ();
 | 
			
		||||
  meta_monitor_manager_confirm_configuration (manager, ok);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -369,10 +369,10 @@ meta_window_actor_constructed (GObject *object)
 | 
			
		||||
       */
 | 
			
		||||
      g_object_ref (priv->actor);
 | 
			
		||||
 | 
			
		||||
      g_signal_connect (window, "notify::decorated",
 | 
			
		||||
                        G_CALLBACK (window_decorated_notify), self);
 | 
			
		||||
      g_signal_connect (window, "notify::appears-focused",
 | 
			
		||||
                        G_CALLBACK (window_appears_focused_notify), self);
 | 
			
		||||
      g_signal_connect_object (window, "notify::decorated",
 | 
			
		||||
                               G_CALLBACK (window_decorated_notify), self, 0);
 | 
			
		||||
      g_signal_connect_object (window, "notify::appears-focused",
 | 
			
		||||
                               G_CALLBACK (window_appears_focused_notify), self, 0);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,8 @@
 | 
			
		||||
#include <meta/meta-plugin.h>
 | 
			
		||||
#include <meta/window.h>
 | 
			
		||||
#include <meta/util.h>
 | 
			
		||||
#include <meta/meta-background-group.h>
 | 
			
		||||
#include <meta/meta-background-actor.h>
 | 
			
		||||
 | 
			
		||||
#include <libintl.h>
 | 
			
		||||
#define _(x) dgettext (GETTEXT_PACKAGE, x)
 | 
			
		||||
@@ -98,6 +100,8 @@ static void kill_window_effects   (MetaPlugin      *plugin,
 | 
			
		||||
                                   MetaWindowActor *actor);
 | 
			
		||||
static void kill_switch_workspace (MetaPlugin      *plugin);
 | 
			
		||||
 | 
			
		||||
static void confirm_display_change (MetaPlugin *plugin);
 | 
			
		||||
 | 
			
		||||
static const MetaPluginInfo * plugin_info (MetaPlugin *plugin);
 | 
			
		||||
 | 
			
		||||
META_PLUGIN_DECLARE(MetaDefaultPlugin, meta_default_plugin);
 | 
			
		||||
@@ -113,6 +117,8 @@ struct _MetaDefaultPluginPrivate
 | 
			
		||||
  ClutterActor          *desktop1;
 | 
			
		||||
  ClutterActor          *desktop2;
 | 
			
		||||
 | 
			
		||||
  ClutterActor          *background_group;
 | 
			
		||||
 | 
			
		||||
  MetaPluginInfo         info;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -203,6 +209,7 @@ meta_default_plugin_class_init (MetaDefaultPluginClass *klass)
 | 
			
		||||
  plugin_class->plugin_info      = plugin_info;
 | 
			
		||||
  plugin_class->kill_window_effects   = kill_window_effects;
 | 
			
		||||
  plugin_class->kill_switch_workspace = kill_switch_workspace;
 | 
			
		||||
  plugin_class->confirm_display_change = confirm_display_change;
 | 
			
		||||
 | 
			
		||||
  g_type_class_add_private (gobject_class, sizeof (MetaDefaultPluginPrivate));
 | 
			
		||||
}
 | 
			
		||||
@@ -299,9 +306,58 @@ show_stage (MetaPlugin *plugin)
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_monitors_changed (MetaScreen *screen,
 | 
			
		||||
                     MetaPlugin *plugin)
 | 
			
		||||
{
 | 
			
		||||
  MetaDefaultPlugin *self = META_DEFAULT_PLUGIN (plugin);
 | 
			
		||||
  int i, n;
 | 
			
		||||
 | 
			
		||||
  clutter_actor_destroy_all_children (self->priv->background_group);
 | 
			
		||||
 | 
			
		||||
  n = meta_screen_get_n_monitors (screen);
 | 
			
		||||
  for (i = 0; i < n; i++)
 | 
			
		||||
    {
 | 
			
		||||
      MetaRectangle rect;
 | 
			
		||||
      ClutterActor *background;
 | 
			
		||||
      ClutterColor color;
 | 
			
		||||
 | 
			
		||||
      meta_screen_get_monitor_geometry (screen, i, &rect);
 | 
			
		||||
 | 
			
		||||
      background = meta_background_actor_new ();
 | 
			
		||||
 | 
			
		||||
      clutter_actor_set_position (background, rect.x, rect.y);
 | 
			
		||||
      clutter_actor_set_size (background, rect.width, rect.height);
 | 
			
		||||
 | 
			
		||||
      /* Don't use rand() here, mesa calls srand() internally when
 | 
			
		||||
         parsing the driconf XML, but it's nice if the colors are
 | 
			
		||||
         reproducible.
 | 
			
		||||
      */
 | 
			
		||||
      clutter_color_init (&color,
 | 
			
		||||
                          g_random_int () % 255,
 | 
			
		||||
                          g_random_int () % 255,
 | 
			
		||||
                          g_random_int () % 255,
 | 
			
		||||
                          255);
 | 
			
		||||
      clutter_actor_set_background_color (background, &color);
 | 
			
		||||
 | 
			
		||||
      clutter_actor_add_child (self->priv->background_group, background);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
start (MetaPlugin *plugin)
 | 
			
		||||
{
 | 
			
		||||
  MetaDefaultPlugin *self = META_DEFAULT_PLUGIN (plugin);
 | 
			
		||||
  MetaScreen *screen = meta_plugin_get_screen (plugin);
 | 
			
		||||
 | 
			
		||||
  self->priv->background_group = meta_background_group_new ();
 | 
			
		||||
  clutter_actor_insert_child_below (meta_get_window_group_for_screen (screen),
 | 
			
		||||
                                    self->priv->background_group, NULL);
 | 
			
		||||
 | 
			
		||||
  g_signal_connect (screen, "monitors-changed",
 | 
			
		||||
                    G_CALLBACK (on_monitors_changed), plugin);
 | 
			
		||||
  on_monitors_changed (screen, plugin);
 | 
			
		||||
 | 
			
		||||
  meta_later_add (META_LATER_BEFORE_REDRAW,
 | 
			
		||||
                  (GSourceFunc) show_stage,
 | 
			
		||||
                  plugin,
 | 
			
		||||
@@ -782,3 +838,33 @@ plugin_info (MetaPlugin *plugin)
 | 
			
		||||
 | 
			
		||||
  return &priv->info;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_dialog_closed (GPid     pid,
 | 
			
		||||
                  gint     status,
 | 
			
		||||
                  gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
  MetaPlugin *plugin = user_data;
 | 
			
		||||
  gboolean ok;
 | 
			
		||||
 | 
			
		||||
  ok = g_spawn_check_exit_status (status, NULL);
 | 
			
		||||
  meta_plugin_complete_display_change (plugin, ok);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
confirm_display_change (MetaPlugin *plugin)
 | 
			
		||||
{
 | 
			
		||||
  GPid pid;
 | 
			
		||||
 | 
			
		||||
  pid = meta_show_dialog ("--question",
 | 
			
		||||
                          "Does the display look OK?",
 | 
			
		||||
                          "20",
 | 
			
		||||
                          NULL,
 | 
			
		||||
                          "_Keep This Configuration",
 | 
			
		||||
                          "_Restore Previous Configuration",
 | 
			
		||||
                          "preferences-desktop-display",
 | 
			
		||||
                          0,
 | 
			
		||||
                          NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  g_child_watch_add (pid, on_dialog_closed, plugin);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2146,6 +2146,7 @@ event_callback (XEvent   *event,
 | 
			
		||||
  gboolean bypass_compositor;
 | 
			
		||||
  gboolean filter_out_event;
 | 
			
		||||
  XIEvent *input_event;
 | 
			
		||||
  MetaMonitorManager *monitor;
 | 
			
		||||
 | 
			
		||||
  display = data;
 | 
			
		||||
  
 | 
			
		||||
@@ -2157,6 +2158,14 @@ event_callback (XEvent   *event,
 | 
			
		||||
#ifdef HAVE_STARTUP_NOTIFICATION
 | 
			
		||||
  sn_display_process_event (display->sn_display, event);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  /* Intercept XRandR events early and don't attempt any
 | 
			
		||||
     processing for them. We still let them through to Gdk though,
 | 
			
		||||
     so it can update its own internal state.
 | 
			
		||||
  */
 | 
			
		||||
  monitor = meta_monitor_manager_get ();
 | 
			
		||||
  if (meta_monitor_manager_handle_xevent (monitor, event))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
  
 | 
			
		||||
  bypass_compositor = FALSE;
 | 
			
		||||
  filter_out_event = FALSE;
 | 
			
		||||
@@ -2822,32 +2831,10 @@ event_callback (XEvent   *event,
 | 
			
		||||
                meta_stack_tracker_configure_event (screen->stack_tracker,
 | 
			
		||||
                                                    &event->xconfigure);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          if (window && window->override_redirect)
 | 
			
		||||
            meta_window_configure_notify (window, &event->xconfigure);
 | 
			
		||||
          else
 | 
			
		||||
            /* Handle screen resize */
 | 
			
		||||
            {
 | 
			
		||||
              MetaScreen *screen;
 | 
			
		||||
 | 
			
		||||
              screen = meta_display_screen_for_root (display,
 | 
			
		||||
                                                     event->xconfigure.window);
 | 
			
		||||
 | 
			
		||||
              if (screen != NULL)
 | 
			
		||||
                {
 | 
			
		||||
#ifdef HAVE_RANDR
 | 
			
		||||
                  /* do the resize the official way */
 | 
			
		||||
                  XRRUpdateConfiguration (event);
 | 
			
		||||
#else
 | 
			
		||||
                  /* poke around in Xlib */
 | 
			
		||||
                  screen->xscreen->width   = event->xconfigure.width;
 | 
			
		||||
                  screen->xscreen->height  = event->xconfigure.height;
 | 
			
		||||
#endif
 | 
			
		||||
	      
 | 
			
		||||
                  meta_screen_resize (screen, 
 | 
			
		||||
                                      event->xconfigure.width,
 | 
			
		||||
                                      event->xconfigure.height);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
          break;
 | 
			
		||||
        case ConfigureRequest:
 | 
			
		||||
          /* This comment and code is found in both twm and fvwm */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										540
									
								
								src/core/edid-parse.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										540
									
								
								src/core/edid-parse.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,540 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 2007 Red Hat, Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a
 | 
			
		||||
 * copy of this software and associated documentation files (the "Software"),
 | 
			
		||||
 * to deal in the Software without restriction, including without limitation
 | 
			
		||||
 * on the rights to use, copy, modify, merge, publish, distribute, sub
 | 
			
		||||
 * license, and/or sell copies of the Software, and to permit persons to whom
 | 
			
		||||
 * the Software is furnished to do so, subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice (including the next
 | 
			
		||||
 * paragraph) shall be included in all copies or substantial portions of the
 | 
			
		||||
 * Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
 | 
			
		||||
 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
			
		||||
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
			
		||||
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Author: Soren Sandmann <sandmann@redhat.com> */
 | 
			
		||||
 | 
			
		||||
#include "edid.h"
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
#include <glib.h>
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
get_bit (int in, int bit)
 | 
			
		||||
{
 | 
			
		||||
    return (in & (1 << bit)) >> bit;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
get_bits (int in, int begin, int end)
 | 
			
		||||
{
 | 
			
		||||
    int mask = (1 << (end - begin + 1)) - 1;
 | 
			
		||||
    
 | 
			
		||||
    return (in >> begin) & mask;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
decode_header (const uchar *edid)
 | 
			
		||||
{
 | 
			
		||||
    if (memcmp (edid, "\x00\xff\xff\xff\xff\xff\xff\x00", 8) == 0)
 | 
			
		||||
	return TRUE;
 | 
			
		||||
    return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
decode_vendor_and_product_identification (const uchar *edid, MonitorInfo *info)
 | 
			
		||||
{
 | 
			
		||||
    int is_model_year;
 | 
			
		||||
    
 | 
			
		||||
    /* Manufacturer Code */
 | 
			
		||||
    info->manufacturer_code[0]  = get_bits (edid[0x08], 2, 6);
 | 
			
		||||
    info->manufacturer_code[1]  = get_bits (edid[0x08], 0, 1) << 3;
 | 
			
		||||
    info->manufacturer_code[1] |= get_bits (edid[0x09], 5, 7);
 | 
			
		||||
    info->manufacturer_code[2]  = get_bits (edid[0x09], 0, 4);
 | 
			
		||||
    info->manufacturer_code[3]  = '\0';
 | 
			
		||||
    
 | 
			
		||||
    info->manufacturer_code[0] += 'A' - 1;
 | 
			
		||||
    info->manufacturer_code[1] += 'A' - 1;
 | 
			
		||||
    info->manufacturer_code[2] += 'A' - 1;
 | 
			
		||||
 | 
			
		||||
    /* Product Code */
 | 
			
		||||
    info->product_code = edid[0x0b] << 8 | edid[0x0a];
 | 
			
		||||
 | 
			
		||||
    /* Serial Number */
 | 
			
		||||
    info->serial_number =
 | 
			
		||||
	edid[0x0c] | edid[0x0d] << 8 | edid[0x0e] << 16 | edid[0x0f] << 24;
 | 
			
		||||
 | 
			
		||||
    /* Week and Year */
 | 
			
		||||
    is_model_year = FALSE;
 | 
			
		||||
    switch (edid[0x10])
 | 
			
		||||
    {
 | 
			
		||||
    case 0x00:
 | 
			
		||||
	info->production_week = -1;
 | 
			
		||||
	break;
 | 
			
		||||
 | 
			
		||||
    case 0xff:
 | 
			
		||||
	info->production_week = -1;
 | 
			
		||||
	is_model_year = TRUE;
 | 
			
		||||
	break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
	info->production_week = edid[0x10];
 | 
			
		||||
	break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (is_model_year)
 | 
			
		||||
    {
 | 
			
		||||
	info->production_year = -1;
 | 
			
		||||
	info->model_year = 1990 + edid[0x11];
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
	info->production_year = 1990 + edid[0x11];
 | 
			
		||||
	info->model_year = -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
decode_edid_version (const uchar *edid, MonitorInfo *info)
 | 
			
		||||
{
 | 
			
		||||
    info->major_version = edid[0x12];
 | 
			
		||||
    info->minor_version = edid[0x13];
 | 
			
		||||
 | 
			
		||||
    return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
decode_display_parameters (const uchar *edid, MonitorInfo *info)
 | 
			
		||||
{
 | 
			
		||||
    /* Digital vs Analog */
 | 
			
		||||
    info->is_digital = get_bit (edid[0x14], 7);
 | 
			
		||||
 | 
			
		||||
    if (info->is_digital)
 | 
			
		||||
    {
 | 
			
		||||
	int bits;
 | 
			
		||||
	
 | 
			
		||||
	static const int bit_depth[8] =
 | 
			
		||||
	{
 | 
			
		||||
	    -1, 6, 8, 10, 12, 14, 16, -1
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	static const Interface interfaces[6] =
 | 
			
		||||
	{
 | 
			
		||||
	    UNDEFINED, DVI, HDMI_A, HDMI_B, MDDI, DISPLAY_PORT
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	bits = get_bits (edid[0x14], 4, 6);
 | 
			
		||||
	info->connector.digital.bits_per_primary = bit_depth[bits];
 | 
			
		||||
 | 
			
		||||
	bits = get_bits (edid[0x14], 0, 3);
 | 
			
		||||
	
 | 
			
		||||
	if (bits <= 5)
 | 
			
		||||
	    info->connector.digital.interface = interfaces[bits];
 | 
			
		||||
	else
 | 
			
		||||
	    info->connector.digital.interface = UNDEFINED;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
	int bits = get_bits (edid[0x14], 5, 6);
 | 
			
		||||
	
 | 
			
		||||
	static const double levels[][3] =
 | 
			
		||||
	{
 | 
			
		||||
	    { 0.7,   0.3,    1.0 },
 | 
			
		||||
	    { 0.714, 0.286,  1.0 },
 | 
			
		||||
	    { 1.0,   0.4,    1.4 },
 | 
			
		||||
	    { 0.7,   0.0,    0.7 },
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	info->connector.analog.video_signal_level = levels[bits][0];
 | 
			
		||||
	info->connector.analog.sync_signal_level = levels[bits][1];
 | 
			
		||||
	info->connector.analog.total_signal_level = levels[bits][2];
 | 
			
		||||
 | 
			
		||||
	info->connector.analog.blank_to_black = get_bit (edid[0x14], 4);
 | 
			
		||||
 | 
			
		||||
	info->connector.analog.separate_hv_sync = get_bit (edid[0x14], 3);
 | 
			
		||||
	info->connector.analog.composite_sync_on_h = get_bit (edid[0x14], 2);
 | 
			
		||||
	info->connector.analog.composite_sync_on_green = get_bit (edid[0x14], 1);
 | 
			
		||||
 | 
			
		||||
	info->connector.analog.serration_on_vsync = get_bit (edid[0x14], 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Screen Size / Aspect Ratio */
 | 
			
		||||
    if (edid[0x15] == 0 && edid[0x16] == 0)
 | 
			
		||||
    {
 | 
			
		||||
	info->width_mm = -1;
 | 
			
		||||
	info->height_mm = -1;
 | 
			
		||||
	info->aspect_ratio = -1.0;
 | 
			
		||||
    }
 | 
			
		||||
    else if (edid[0x16] == 0)
 | 
			
		||||
    {
 | 
			
		||||
	info->width_mm = -1;
 | 
			
		||||
	info->height_mm = -1; 
 | 
			
		||||
	info->aspect_ratio = 100.0 / (edid[0x15] + 99);
 | 
			
		||||
    }
 | 
			
		||||
    else if (edid[0x15] == 0)
 | 
			
		||||
    {
 | 
			
		||||
	info->width_mm = -1;
 | 
			
		||||
	info->height_mm = -1;
 | 
			
		||||
	info->aspect_ratio = 100.0 / (edid[0x16] + 99);
 | 
			
		||||
	info->aspect_ratio = 1/info->aspect_ratio; /* portrait */
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
	info->width_mm = 10 * edid[0x15];
 | 
			
		||||
	info->height_mm = 10 * edid[0x16];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Gamma */
 | 
			
		||||
    if (edid[0x17] == 0xFF)
 | 
			
		||||
	info->gamma = -1.0;
 | 
			
		||||
    else
 | 
			
		||||
	info->gamma = (edid[0x17] + 100.0) / 100.0;
 | 
			
		||||
 | 
			
		||||
    /* Features */
 | 
			
		||||
    info->standby = get_bit (edid[0x18], 7);
 | 
			
		||||
    info->suspend = get_bit (edid[0x18], 6);
 | 
			
		||||
    info->active_off = get_bit (edid[0x18], 5);
 | 
			
		||||
 | 
			
		||||
    if (info->is_digital)
 | 
			
		||||
    {
 | 
			
		||||
	info->connector.digital.rgb444 = TRUE;
 | 
			
		||||
	if (get_bit (edid[0x18], 3))
 | 
			
		||||
	    info->connector.digital.ycrcb444 = 1;
 | 
			
		||||
	if (get_bit (edid[0x18], 4))
 | 
			
		||||
	    info->connector.digital.ycrcb422 = 1;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
	int bits = get_bits (edid[0x18], 3, 4);
 | 
			
		||||
	ColorType color_type[4] =
 | 
			
		||||
	{
 | 
			
		||||
	    MONOCHROME, RGB, OTHER_COLOR, UNDEFINED_COLOR
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	info->connector.analog.color_type = color_type[bits];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    info->srgb_is_standard = get_bit (edid[0x18], 2);
 | 
			
		||||
 | 
			
		||||
    /* In 1.3 this is called "has preferred timing" */
 | 
			
		||||
    info->preferred_timing_includes_native = get_bit (edid[0x18], 1);
 | 
			
		||||
 | 
			
		||||
    /* FIXME: In 1.3 this indicates whether the monitor accepts GTF */
 | 
			
		||||
    info->continuous_frequency = get_bit (edid[0x18], 0);
 | 
			
		||||
    return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static double
 | 
			
		||||
decode_fraction (int high, int low)
 | 
			
		||||
{
 | 
			
		||||
    double result = 0.0;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    high = (high << 2) | low;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < 10; ++i)
 | 
			
		||||
	result += get_bit (high, i) * pow (2, i - 10);
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
decode_color_characteristics (const uchar *edid, MonitorInfo *info)
 | 
			
		||||
{
 | 
			
		||||
    info->red_x = decode_fraction (edid[0x1b], get_bits (edid[0x19], 6, 7));
 | 
			
		||||
    info->red_y = decode_fraction (edid[0x1c], get_bits (edid[0x19], 5, 4));
 | 
			
		||||
    info->green_x = decode_fraction (edid[0x1d], get_bits (edid[0x19], 2, 3));
 | 
			
		||||
    info->green_y = decode_fraction (edid[0x1e], get_bits (edid[0x19], 0, 1));
 | 
			
		||||
    info->blue_x = decode_fraction (edid[0x1f], get_bits (edid[0x1a], 6, 7));
 | 
			
		||||
    info->blue_y = decode_fraction (edid[0x20], get_bits (edid[0x1a], 4, 5));
 | 
			
		||||
    info->white_x = decode_fraction (edid[0x21], get_bits (edid[0x1a], 2, 3));
 | 
			
		||||
    info->white_y = decode_fraction (edid[0x22], get_bits (edid[0x1a], 0, 1));
 | 
			
		||||
 | 
			
		||||
    return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
decode_established_timings (const uchar *edid, MonitorInfo *info)
 | 
			
		||||
{
 | 
			
		||||
    static const Timing established[][8] = 
 | 
			
		||||
    {
 | 
			
		||||
	{
 | 
			
		||||
	    { 800, 600, 60 },
 | 
			
		||||
	    { 800, 600, 56 },
 | 
			
		||||
	    { 640, 480, 75 },
 | 
			
		||||
	    { 640, 480, 72 },
 | 
			
		||||
	    { 640, 480, 67 },
 | 
			
		||||
	    { 640, 480, 60 },
 | 
			
		||||
	    { 720, 400, 88 },
 | 
			
		||||
	    { 720, 400, 70 }
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
	    { 1280, 1024, 75 },
 | 
			
		||||
	    { 1024, 768, 75 },
 | 
			
		||||
	    { 1024, 768, 70 },
 | 
			
		||||
	    { 1024, 768, 60 },
 | 
			
		||||
	    { 1024, 768, 87 },
 | 
			
		||||
	    { 832, 624, 75 },
 | 
			
		||||
	    { 800, 600, 75 },
 | 
			
		||||
	    { 800, 600, 72 }
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
	    { 0, 0, 0 },
 | 
			
		||||
	    { 0, 0, 0 },
 | 
			
		||||
	    { 0, 0, 0 },
 | 
			
		||||
	    { 0, 0, 0 },
 | 
			
		||||
	    { 0, 0, 0 },
 | 
			
		||||
	    { 0, 0, 0 },
 | 
			
		||||
	    { 0, 0, 0 },
 | 
			
		||||
	    { 1152, 870, 75 }
 | 
			
		||||
	},
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    int i, j, idx;
 | 
			
		||||
 | 
			
		||||
    idx = 0;
 | 
			
		||||
    for (i = 0; i < 3; ++i)
 | 
			
		||||
    {
 | 
			
		||||
	for (j = 0; j < 8; ++j)
 | 
			
		||||
	{
 | 
			
		||||
	    int byte = edid[0x23 + i];
 | 
			
		||||
 | 
			
		||||
	    if (get_bit (byte, j) && established[i][j].frequency != 0)
 | 
			
		||||
		info->established[idx++] = established[i][j];
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
    return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
decode_standard_timings (const uchar *edid, MonitorInfo *info)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
    
 | 
			
		||||
    for (i = 0; i < 8; i++)
 | 
			
		||||
    {
 | 
			
		||||
	int first = edid[0x26 + 2 * i];
 | 
			
		||||
	int second = edid[0x27 + 2 * i];
 | 
			
		||||
 | 
			
		||||
	if (first != 0x01 && second != 0x01)
 | 
			
		||||
	{
 | 
			
		||||
	    int w = 8 * (first + 31);
 | 
			
		||||
	    int h = 0;
 | 
			
		||||
 | 
			
		||||
	    switch (get_bits (second, 6, 7))
 | 
			
		||||
	    {
 | 
			
		||||
	    case 0x00: h = (w / 16) * 10; break;
 | 
			
		||||
	    case 0x01: h = (w / 4) * 3; break;
 | 
			
		||||
	    case 0x02: h = (w / 5) * 4; break;
 | 
			
		||||
	    case 0x03: h = (w / 16) * 9; break;
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
	    info->standard[i].width = w;
 | 
			
		||||
	    info->standard[i].height = h;
 | 
			
		||||
	    info->standard[i].frequency = get_bits (second, 0, 5) + 60;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
decode_lf_string (const uchar *s, int n_chars, char *result)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
    for (i = 0; i < n_chars; ++i)
 | 
			
		||||
    {
 | 
			
		||||
	if (s[i] == 0x0a)
 | 
			
		||||
	{
 | 
			
		||||
	    *result++ = '\0';
 | 
			
		||||
	    break;
 | 
			
		||||
	}
 | 
			
		||||
	else if (s[i] == 0x00)
 | 
			
		||||
	{
 | 
			
		||||
	    /* Convert embedded 0's to spaces */
 | 
			
		||||
	    *result++ = ' ';
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
	    *result++ = s[i];
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
decode_display_descriptor (const uchar *desc,
 | 
			
		||||
			   MonitorInfo *info)
 | 
			
		||||
{
 | 
			
		||||
    switch (desc[0x03])
 | 
			
		||||
    {
 | 
			
		||||
    case 0xFC:
 | 
			
		||||
	decode_lf_string (desc + 5, 13, info->dsc_product_name);
 | 
			
		||||
	break;
 | 
			
		||||
    case 0xFF:
 | 
			
		||||
	decode_lf_string (desc + 5, 13, info->dsc_serial_number);
 | 
			
		||||
	break;
 | 
			
		||||
    case 0xFE:
 | 
			
		||||
	decode_lf_string (desc + 5, 13, info->dsc_string);
 | 
			
		||||
	break;
 | 
			
		||||
    case 0xFD:
 | 
			
		||||
	/* Range Limits */
 | 
			
		||||
	break;
 | 
			
		||||
    case 0xFB:
 | 
			
		||||
	/* Color Point */
 | 
			
		||||
	break;
 | 
			
		||||
    case 0xFA:
 | 
			
		||||
	/* Timing Identifications */
 | 
			
		||||
	break;
 | 
			
		||||
    case 0xF9:
 | 
			
		||||
	/* Color Management */
 | 
			
		||||
	break;
 | 
			
		||||
    case 0xF8:
 | 
			
		||||
	/* Timing Codes */
 | 
			
		||||
	break;
 | 
			
		||||
    case 0xF7:
 | 
			
		||||
	/* Established Timings */
 | 
			
		||||
	break;
 | 
			
		||||
    case 0x10:
 | 
			
		||||
	break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
decode_detailed_timing (const uchar *timing,
 | 
			
		||||
			DetailedTiming *detailed)
 | 
			
		||||
{
 | 
			
		||||
    int bits;
 | 
			
		||||
    StereoType stereo[] =
 | 
			
		||||
    {
 | 
			
		||||
	NO_STEREO, NO_STEREO, FIELD_RIGHT, FIELD_LEFT,
 | 
			
		||||
	TWO_WAY_RIGHT_ON_EVEN, TWO_WAY_LEFT_ON_EVEN,
 | 
			
		||||
	FOUR_WAY_INTERLEAVED, SIDE_BY_SIDE
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    detailed->pixel_clock = (timing[0x00] | timing[0x01] << 8) * 10000;
 | 
			
		||||
    detailed->h_addr = timing[0x02] | ((timing[0x04] & 0xf0) << 4);
 | 
			
		||||
    detailed->h_blank = timing[0x03] | ((timing[0x04] & 0x0f) << 8);
 | 
			
		||||
    detailed->v_addr = timing[0x05] | ((timing[0x07] & 0xf0) << 4);
 | 
			
		||||
    detailed->v_blank = timing[0x06] | ((timing[0x07] & 0x0f) << 8);
 | 
			
		||||
    detailed->h_front_porch = timing[0x08] | get_bits (timing[0x0b], 6, 7) << 8;
 | 
			
		||||
    detailed->h_sync = timing[0x09] | get_bits (timing[0x0b], 4, 5) << 8;
 | 
			
		||||
    detailed->v_front_porch =
 | 
			
		||||
	get_bits (timing[0x0a], 4, 7) | get_bits (timing[0x0b], 2, 3) << 4;
 | 
			
		||||
    detailed->v_sync =
 | 
			
		||||
	get_bits (timing[0x0a], 0, 3) | get_bits (timing[0x0b], 0, 1) << 4;
 | 
			
		||||
    detailed->width_mm =  timing[0x0c] | get_bits (timing[0x0e], 4, 7) << 8;
 | 
			
		||||
    detailed->height_mm = timing[0x0d] | get_bits (timing[0x0e], 0, 3) << 8;
 | 
			
		||||
    detailed->right_border = timing[0x0f];
 | 
			
		||||
    detailed->top_border = timing[0x10];
 | 
			
		||||
 | 
			
		||||
    detailed->interlaced = get_bit (timing[0x11], 7);
 | 
			
		||||
 | 
			
		||||
    /* Stereo */
 | 
			
		||||
    bits = get_bits (timing[0x11], 5, 6) << 1 | get_bit (timing[0x11], 0);
 | 
			
		||||
    detailed->stereo = stereo[bits];
 | 
			
		||||
 | 
			
		||||
    /* Sync */
 | 
			
		||||
    bits = timing[0x11];
 | 
			
		||||
 | 
			
		||||
    detailed->digital_sync = get_bit (bits, 4);
 | 
			
		||||
    if (detailed->digital_sync)
 | 
			
		||||
    {
 | 
			
		||||
	detailed->connector.digital.composite = !get_bit (bits, 3);
 | 
			
		||||
 | 
			
		||||
	if (detailed->connector.digital.composite)
 | 
			
		||||
	{
 | 
			
		||||
	    detailed->connector.digital.serrations = get_bit (bits, 2);
 | 
			
		||||
	    detailed->connector.digital.negative_vsync = FALSE;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
	    detailed->connector.digital.serrations = FALSE;
 | 
			
		||||
	    detailed->connector.digital.negative_vsync = !get_bit (bits, 2);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	detailed->connector.digital.negative_hsync = !get_bit (bits, 0);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
	detailed->connector.analog.bipolar = get_bit (bits, 3);
 | 
			
		||||
	detailed->connector.analog.serrations = get_bit (bits, 2);
 | 
			
		||||
	detailed->connector.analog.sync_on_green = !get_bit (bits, 1);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
decode_descriptors (const uchar *edid, MonitorInfo *info)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
    int timing_idx;
 | 
			
		||||
    
 | 
			
		||||
    timing_idx = 0;
 | 
			
		||||
    
 | 
			
		||||
    for (i = 0; i < 4; ++i)
 | 
			
		||||
    {
 | 
			
		||||
	int index = 0x36 + i * 18;
 | 
			
		||||
 | 
			
		||||
	if (edid[index + 0] == 0x00 && edid[index + 1] == 0x00)
 | 
			
		||||
	{
 | 
			
		||||
	    decode_display_descriptor (edid + index, info);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
	    decode_detailed_timing (
 | 
			
		||||
		edid + index, &(info->detailed_timings[timing_idx++]));
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    info->n_detailed_timings = timing_idx;
 | 
			
		||||
 | 
			
		||||
    return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
decode_check_sum (const uchar *edid,
 | 
			
		||||
		  MonitorInfo *info)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
    uchar check = 0;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < 128; ++i)
 | 
			
		||||
	check += edid[i];
 | 
			
		||||
 | 
			
		||||
    info->checksum = check;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MonitorInfo *
 | 
			
		||||
decode_edid (const uchar *edid)
 | 
			
		||||
{
 | 
			
		||||
    MonitorInfo *info = g_new0 (MonitorInfo, 1);
 | 
			
		||||
 | 
			
		||||
    decode_check_sum (edid, info);
 | 
			
		||||
    
 | 
			
		||||
    if (decode_header (edid)
 | 
			
		||||
	&& decode_vendor_and_product_identification (edid, info)
 | 
			
		||||
	&& decode_edid_version (edid, info)
 | 
			
		||||
	&& decode_display_parameters (edid, info)
 | 
			
		||||
	&& decode_color_characteristics (edid, info)
 | 
			
		||||
	&& decode_established_timings (edid, info)
 | 
			
		||||
	&& decode_standard_timings (edid, info)
 | 
			
		||||
	&& decode_descriptors (edid, info))
 | 
			
		||||
    {
 | 
			
		||||
	return info;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
	g_free (info);
 | 
			
		||||
	return NULL;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										195
									
								
								src/core/edid.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										195
									
								
								src/core/edid.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,195 @@
 | 
			
		||||
/* edid.h
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2007, 2008, Red Hat, Inc.
 | 
			
		||||
 * 
 | 
			
		||||
 * This file is part of the Gnome Library.
 | 
			
		||||
 * 
 | 
			
		||||
 * The Gnome 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.
 | 
			
		||||
 *
 | 
			
		||||
 * The Gnome 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 the Gnome Library; see the file COPYING.LIB.  If not,
 | 
			
		||||
 * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 | 
			
		||||
 * Boston, MA 02110-1301, USA.
 | 
			
		||||
 * 
 | 
			
		||||
 * Author: Soren Sandmann <sandmann@redhat.com>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef EDID_H
 | 
			
		||||
#define EDID_H
 | 
			
		||||
 | 
			
		||||
typedef unsigned char uchar;
 | 
			
		||||
typedef struct MonitorInfo MonitorInfo;
 | 
			
		||||
typedef struct Timing Timing;
 | 
			
		||||
typedef struct DetailedTiming DetailedTiming;
 | 
			
		||||
 | 
			
		||||
typedef enum
 | 
			
		||||
{
 | 
			
		||||
    UNDEFINED,
 | 
			
		||||
    DVI,
 | 
			
		||||
    HDMI_A,
 | 
			
		||||
    HDMI_B,
 | 
			
		||||
    MDDI,
 | 
			
		||||
    DISPLAY_PORT
 | 
			
		||||
} Interface;
 | 
			
		||||
 | 
			
		||||
typedef enum
 | 
			
		||||
{
 | 
			
		||||
    UNDEFINED_COLOR,
 | 
			
		||||
    MONOCHROME,
 | 
			
		||||
    RGB,
 | 
			
		||||
    OTHER_COLOR
 | 
			
		||||
} ColorType;
 | 
			
		||||
 | 
			
		||||
typedef enum
 | 
			
		||||
{
 | 
			
		||||
    NO_STEREO,
 | 
			
		||||
    FIELD_RIGHT,
 | 
			
		||||
    FIELD_LEFT,
 | 
			
		||||
    TWO_WAY_RIGHT_ON_EVEN,
 | 
			
		||||
    TWO_WAY_LEFT_ON_EVEN,
 | 
			
		||||
    FOUR_WAY_INTERLEAVED,
 | 
			
		||||
    SIDE_BY_SIDE
 | 
			
		||||
} StereoType;
 | 
			
		||||
 | 
			
		||||
struct Timing
 | 
			
		||||
{
 | 
			
		||||
    int width;
 | 
			
		||||
    int height;
 | 
			
		||||
    int frequency;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct DetailedTiming
 | 
			
		||||
{
 | 
			
		||||
    int		pixel_clock;
 | 
			
		||||
    int		h_addr;
 | 
			
		||||
    int		h_blank;
 | 
			
		||||
    int		h_sync;
 | 
			
		||||
    int		h_front_porch;
 | 
			
		||||
    int		v_addr;
 | 
			
		||||
    int		v_blank;
 | 
			
		||||
    int		v_sync;
 | 
			
		||||
    int		v_front_porch;
 | 
			
		||||
    int		width_mm;
 | 
			
		||||
    int		height_mm;
 | 
			
		||||
    int		right_border;
 | 
			
		||||
    int		top_border;
 | 
			
		||||
    int		interlaced;
 | 
			
		||||
    StereoType	stereo;
 | 
			
		||||
 | 
			
		||||
    int		digital_sync;
 | 
			
		||||
    union
 | 
			
		||||
    {
 | 
			
		||||
	struct
 | 
			
		||||
	{
 | 
			
		||||
	    int bipolar;
 | 
			
		||||
	    int serrations;
 | 
			
		||||
	    int sync_on_green;
 | 
			
		||||
	} analog;
 | 
			
		||||
 | 
			
		||||
	struct
 | 
			
		||||
	{
 | 
			
		||||
	    int composite;
 | 
			
		||||
	    int serrations;
 | 
			
		||||
	    int negative_vsync;
 | 
			
		||||
	    int negative_hsync;
 | 
			
		||||
	} digital;
 | 
			
		||||
    } connector;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct MonitorInfo
 | 
			
		||||
{
 | 
			
		||||
    int			checksum;
 | 
			
		||||
    char		manufacturer_code[4];
 | 
			
		||||
    int			product_code;
 | 
			
		||||
    unsigned int	serial_number;
 | 
			
		||||
    
 | 
			
		||||
    int			production_week;	/* -1 if not specified */
 | 
			
		||||
    int			production_year;	/* -1 if not specified */
 | 
			
		||||
    int			model_year;		/* -1 if not specified */
 | 
			
		||||
 | 
			
		||||
    int			major_version;
 | 
			
		||||
    int			minor_version;
 | 
			
		||||
 | 
			
		||||
    int			is_digital;
 | 
			
		||||
    
 | 
			
		||||
    union
 | 
			
		||||
    {
 | 
			
		||||
	struct
 | 
			
		||||
	{
 | 
			
		||||
	    int		bits_per_primary;
 | 
			
		||||
	    Interface	interface;
 | 
			
		||||
	    int		rgb444;
 | 
			
		||||
	    int		ycrcb444;
 | 
			
		||||
	    int		ycrcb422;
 | 
			
		||||
	} digital;
 | 
			
		||||
 | 
			
		||||
	struct
 | 
			
		||||
	{
 | 
			
		||||
	    double	video_signal_level;
 | 
			
		||||
	    double	sync_signal_level;
 | 
			
		||||
	    double	total_signal_level;
 | 
			
		||||
 | 
			
		||||
	    int		blank_to_black;
 | 
			
		||||
 | 
			
		||||
	    int		separate_hv_sync;
 | 
			
		||||
	    int		composite_sync_on_h;
 | 
			
		||||
	    int		composite_sync_on_green;
 | 
			
		||||
	    int		serration_on_vsync;
 | 
			
		||||
	    ColorType	color_type;
 | 
			
		||||
	} analog;
 | 
			
		||||
    } connector;
 | 
			
		||||
 | 
			
		||||
    int			width_mm;		/* -1 if not specified */
 | 
			
		||||
    int			height_mm;		/* -1 if not specified */
 | 
			
		||||
    double		aspect_ratio;		/* -1.0 if not specififed */
 | 
			
		||||
 | 
			
		||||
    double		gamma;			/* -1.0 if not specified */
 | 
			
		||||
 | 
			
		||||
    int			standby;
 | 
			
		||||
    int			suspend;
 | 
			
		||||
    int			active_off;
 | 
			
		||||
 | 
			
		||||
    int			srgb_is_standard;
 | 
			
		||||
    int			preferred_timing_includes_native;
 | 
			
		||||
    int			continuous_frequency;
 | 
			
		||||
 | 
			
		||||
    double		red_x;
 | 
			
		||||
    double		red_y;
 | 
			
		||||
    double		green_x;
 | 
			
		||||
    double		green_y;
 | 
			
		||||
    double		blue_x;
 | 
			
		||||
    double		blue_y;
 | 
			
		||||
    double		white_x;
 | 
			
		||||
    double		white_y;
 | 
			
		||||
 | 
			
		||||
    Timing		established[24];	/* Terminated by 0x0x0 */
 | 
			
		||||
    Timing		standard[8];
 | 
			
		||||
    
 | 
			
		||||
    int			n_detailed_timings;
 | 
			
		||||
    DetailedTiming	detailed_timings[4];	/* If monitor has a preferred
 | 
			
		||||
						 * mode, it is the first one
 | 
			
		||||
						 * (whether it has, is
 | 
			
		||||
						 * determined by the 
 | 
			
		||||
						 * preferred_timing_includes
 | 
			
		||||
						 * bit.
 | 
			
		||||
						 */
 | 
			
		||||
 | 
			
		||||
    /* Optional product description */
 | 
			
		||||
    char		dsc_serial_number[14];
 | 
			
		||||
    char		dsc_product_name[14];
 | 
			
		||||
    char		dsc_string[14];		/* Unspecified ASCII data */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
MonitorInfo *decode_edid (const uchar *data);
 | 
			
		||||
char *make_display_name (const MonitorInfo *info);
 | 
			
		||||
char *make_display_size_string (int width_mm, int height_mm);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										108
									
								
								src/core/main.c
									
									
									
									
									
								
							
							
						
						
									
										108
									
								
								src/core/main.c
									
									
									
									
									
								
							@@ -56,6 +56,7 @@
 | 
			
		||||
#include <meta/prefs.h>
 | 
			
		||||
#include <meta/compositor.h>
 | 
			
		||||
 | 
			
		||||
#include <glib-unix.h>
 | 
			
		||||
#include <glib-object.h>
 | 
			
		||||
#include <gdk/gdkx.h>
 | 
			
		||||
 | 
			
		||||
@@ -93,26 +94,6 @@ static GMainLoop *meta_main_loop = NULL;
 | 
			
		||||
static void prefs_changed_callback (MetaPreference pref,
 | 
			
		||||
                                    gpointer       data);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * log_handler:
 | 
			
		||||
 * @log_domain: the domain the error occurred in (we ignore this)
 | 
			
		||||
 * @log_level: the log level so that we can filter out less
 | 
			
		||||
 *             important messages
 | 
			
		||||
 * @message: the message to log
 | 
			
		||||
 * @user_data: arbitrary data (we ignore this)
 | 
			
		||||
 *
 | 
			
		||||
 * Prints log messages. If Mutter was compiled with backtrace support,
 | 
			
		||||
 * also prints a backtrace (see meta_print_backtrace()).
 | 
			
		||||
 */
 | 
			
		||||
static void
 | 
			
		||||
log_handler (const gchar   *log_domain,
 | 
			
		||||
             GLogLevelFlags log_level,
 | 
			
		||||
             const gchar   *message,
 | 
			
		||||
             gpointer       user_data)
 | 
			
		||||
{
 | 
			
		||||
  meta_warning ("Log level %d: %s\n", log_level, message);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * meta_print_compilation_info:
 | 
			
		||||
 *
 | 
			
		||||
@@ -348,23 +329,8 @@ meta_finalize (void)
 | 
			
		||||
                        CurrentTime); /* I doubt correct timestamps matter here */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int sigterm_pipe_fds[2] = { -1, -1 };
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
sigterm_handler (int signum)
 | 
			
		||||
{
 | 
			
		||||
  if (sigterm_pipe_fds[1] >= 0)
 | 
			
		||||
    {
 | 
			
		||||
      int G_GNUC_UNUSED dummy;
 | 
			
		||||
 | 
			
		||||
      dummy = write (sigterm_pipe_fds[1], "", 1);
 | 
			
		||||
      close (sigterm_pipe_fds[1]);
 | 
			
		||||
      sigterm_pipe_fds[1] = -1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
on_sigterm (void)
 | 
			
		||||
on_sigterm (gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
  meta_quit (META_EXIT_SUCCESS);
 | 
			
		||||
  return FALSE;
 | 
			
		||||
@@ -381,8 +347,7 @@ meta_init (void)
 | 
			
		||||
{
 | 
			
		||||
  struct sigaction act;
 | 
			
		||||
  sigset_t empty_mask;
 | 
			
		||||
  GIOChannel *channel;
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  sigemptyset (&empty_mask);
 | 
			
		||||
  act.sa_handler = SIG_IGN;
 | 
			
		||||
  act.sa_mask    = empty_mask;
 | 
			
		||||
@@ -396,20 +361,9 @@ meta_init (void)
 | 
			
		||||
                g_strerror (errno));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  if (pipe (sigterm_pipe_fds) != 0)
 | 
			
		||||
    g_printerr ("Failed to create SIGTERM pipe: %s\n",
 | 
			
		||||
                g_strerror (errno));
 | 
			
		||||
  g_unix_signal_add (SIGTERM, on_sigterm, NULL);
 | 
			
		||||
 | 
			
		||||
  channel = g_io_channel_unix_new (sigterm_pipe_fds[0]);
 | 
			
		||||
  g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL);
 | 
			
		||||
  g_io_add_watch (channel, G_IO_IN, (GIOFunc) on_sigterm, NULL);
 | 
			
		||||
  g_io_channel_set_close_on_unref (channel, TRUE);
 | 
			
		||||
  g_io_channel_unref (channel);
 | 
			
		||||
 | 
			
		||||
  act.sa_handler = &sigterm_handler;
 | 
			
		||||
  if (sigaction (SIGTERM, &act, NULL) < 0)
 | 
			
		||||
    g_printerr ("Failed to register SIGTERM handler: %s\n",
 | 
			
		||||
		g_strerror (errno));
 | 
			
		||||
  meta_debug_init ();
 | 
			
		||||
 | 
			
		||||
  if (g_getenv ("MUTTER_VERBOSE"))
 | 
			
		||||
    meta_set_verbose (TRUE);
 | 
			
		||||
@@ -496,63 +450,25 @@ meta_register_with_session (void)
 | 
			
		||||
int
 | 
			
		||||
meta_run (void)
 | 
			
		||||
{
 | 
			
		||||
  const gchar *log_domains[] = {
 | 
			
		||||
    NULL, G_LOG_DOMAIN, "Gtk", "Gdk", "GLib",
 | 
			
		||||
    "Pango", "GLib-GObject", "GThread"
 | 
			
		||||
  };
 | 
			
		||||
  guint i;
 | 
			
		||||
 | 
			
		||||
  /* Load prefs */
 | 
			
		||||
  meta_prefs_init ();
 | 
			
		||||
  meta_prefs_add_listener (prefs_changed_callback, NULL);
 | 
			
		||||
 | 
			
		||||
  for (i=0; i<G_N_ELEMENTS(log_domains); i++)
 | 
			
		||||
    g_log_set_handler (log_domains[i],
 | 
			
		||||
                       G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
 | 
			
		||||
                       log_handler, NULL);
 | 
			
		||||
 | 
			
		||||
  if (g_getenv ("MUTTER_G_FATAL_WARNINGS") != NULL)
 | 
			
		||||
    g_log_set_always_fatal (G_LOG_LEVEL_MASK);
 | 
			
		||||
  
 | 
			
		||||
  meta_ui_set_current_theme (meta_prefs_get_theme ());
 | 
			
		||||
 | 
			
		||||
  /* Try to find some theme that'll work if the theme preference
 | 
			
		||||
   * doesn't exist.  First try Simple (the default theme) then just
 | 
			
		||||
   * try anything in the themes directory.
 | 
			
		||||
  /* If the theme preference does not exists, fallback to
 | 
			
		||||
   * Adwaita (the default theme), or abort if that doesn't
 | 
			
		||||
   * exists.
 | 
			
		||||
   */
 | 
			
		||||
  if (!meta_ui_have_a_theme ())
 | 
			
		||||
    meta_ui_set_current_theme ("Simple");
 | 
			
		||||
  
 | 
			
		||||
    meta_ui_set_current_theme ("Adwaita");
 | 
			
		||||
 | 
			
		||||
  if (!meta_ui_have_a_theme ())
 | 
			
		||||
    {
 | 
			
		||||
      const char *dir_entry = NULL;
 | 
			
		||||
      GError *err = NULL;
 | 
			
		||||
      GDir   *themes_dir = NULL;
 | 
			
		||||
      
 | 
			
		||||
      if (!(themes_dir = g_dir_open (MUTTER_DATADIR"/themes", 0, &err)))
 | 
			
		||||
        {
 | 
			
		||||
          meta_fatal (_("Failed to scan themes directory: %s\n"), err->message);
 | 
			
		||||
          g_error_free (err);
 | 
			
		||||
        } 
 | 
			
		||||
      else 
 | 
			
		||||
        {
 | 
			
		||||
          while (((dir_entry = g_dir_read_name (themes_dir)) != NULL) && 
 | 
			
		||||
                 (!meta_ui_have_a_theme ()))
 | 
			
		||||
            {
 | 
			
		||||
              meta_ui_set_current_theme (dir_entry);
 | 
			
		||||
            }
 | 
			
		||||
          
 | 
			
		||||
          g_dir_close (themes_dir);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  
 | 
			
		||||
  if (!meta_ui_have_a_theme ())
 | 
			
		||||
    meta_fatal (_("Could not find a theme! Be sure %s exists and contains the usual themes.\n"),
 | 
			
		||||
                MUTTER_DATADIR"/themes");
 | 
			
		||||
    meta_fatal ("Adwaita theme missing, please install the gnome-themes-standard package");
 | 
			
		||||
 | 
			
		||||
  if (!meta_display_open ())
 | 
			
		||||
    meta_exit (META_EXIT_ERROR);
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  g_main_loop_run (meta_main_loop);
 | 
			
		||||
 | 
			
		||||
  meta_finalize ();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										40
									
								
								src/core/meta-xrandr-shared.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/core/meta-xrandr-shared.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
/* 
 | 
			
		||||
 * Copyright (C) 2013 Red Hat Inc.
 | 
			
		||||
 * 
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License as
 | 
			
		||||
 * published by the Free Software Foundation; either version 2 of the
 | 
			
		||||
 * License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program 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
 | 
			
		||||
 * General Public License for more details.
 | 
			
		||||
 * 
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 | 
			
		||||
 * 02111-1307, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* This file is shared between mutter (src/core/meta-xrandr-shared.h)
 | 
			
		||||
   and gnome-desktop (libgnome-desktop/meta-xrandr-shared.h).
 | 
			
		||||
 | 
			
		||||
   The canonical place for all changes is mutter.
 | 
			
		||||
 | 
			
		||||
   There should be no includes in this file.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef META_XRANDR_SHARED_H
 | 
			
		||||
#define META_XRANDR_SHARED_H
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
  META_POWER_SAVE_UNKNOWN = -1,
 | 
			
		||||
  META_POWER_SAVE_ON = 0,
 | 
			
		||||
  META_POWER_SAVE_STANDBY,
 | 
			
		||||
  META_POWER_SAVE_SUSPEND,
 | 
			
		||||
  META_POWER_SAVE_OFF,
 | 
			
		||||
} MetaPowerSave;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										1771
									
								
								src/core/monitor-config.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1771
									
								
								src/core/monitor-config.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										390
									
								
								src/core/monitor-private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										390
									
								
								src/core/monitor-private.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,390 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \file screen-private.h  Handling of monitor configuration
 | 
			
		||||
 *
 | 
			
		||||
 * Managing multiple monitors
 | 
			
		||||
 * This file contains structures and functions that handle
 | 
			
		||||
 * multiple monitors, including reading the current configuration
 | 
			
		||||
 * and available hardware, and applying it.
 | 
			
		||||
 *
 | 
			
		||||
 * This interface is private to mutter, API users should look
 | 
			
		||||
 * at MetaScreen instead.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* 
 | 
			
		||||
 * Copyright (C) 2001 Havoc Pennington
 | 
			
		||||
 * Copyright (C) 2003 Rob Adams
 | 
			
		||||
 * Copyright (C) 2004-2006 Elijah Newren
 | 
			
		||||
 * Copyright (C) 2013 Red Hat Inc.
 | 
			
		||||
 * 
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License as
 | 
			
		||||
 * published by the Free Software Foundation; either version 2 of the
 | 
			
		||||
 * License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program 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
 | 
			
		||||
 * General Public License for more details.
 | 
			
		||||
 * 
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 | 
			
		||||
 * 02111-1307, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef META_MONITOR_PRIVATE_H
 | 
			
		||||
#define META_MONITOR_PRIVATE_H
 | 
			
		||||
 | 
			
		||||
#include <cogl/cogl.h>
 | 
			
		||||
#include <libgnome-desktop/gnome-pnp-ids.h>
 | 
			
		||||
 | 
			
		||||
#include "display-private.h"
 | 
			
		||||
#include <meta/screen.h>
 | 
			
		||||
#include "stack-tracker.h"
 | 
			
		||||
#include "ui.h"
 | 
			
		||||
#ifdef HAVE_WAYLAND
 | 
			
		||||
#include <wayland-server.h>
 | 
			
		||||
#endif
 | 
			
		||||
#include "meta-xrandr-shared.h"
 | 
			
		||||
 | 
			
		||||
#include "meta-dbus-xrandr.h"
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaMonitorManagerClass    MetaMonitorManagerClass;
 | 
			
		||||
typedef struct _MetaMonitorManager         MetaMonitorManager;
 | 
			
		||||
typedef struct _MetaMonitorConfigClass    MetaMonitorConfigClass;
 | 
			
		||||
typedef struct _MetaMonitorConfig         MetaMonitorConfig;
 | 
			
		||||
 | 
			
		||||
#ifndef HAVE_WAYLAND
 | 
			
		||||
enum wl_output_transform {
 | 
			
		||||
  WL_OUTPUT_TRANSFORM_NORMAL,
 | 
			
		||||
  WL_OUTPUT_TRANSFORM_90,
 | 
			
		||||
  WL_OUTPUT_TRANSFORM_180,
 | 
			
		||||
  WL_OUTPUT_TRANSFORM_270,
 | 
			
		||||
  WL_OUTPUT_TRANSFORM_FLIPPED,
 | 
			
		||||
  WL_OUTPUT_TRANSFORM_FLIPPED_90,
 | 
			
		||||
  WL_OUTPUT_TRANSFORM_FLIPPED_180,
 | 
			
		||||
  WL_OUTPUT_TRANSFORM_FLIPPED_270
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaOutput MetaOutput;
 | 
			
		||||
typedef struct _MetaCRTC MetaCRTC;
 | 
			
		||||
typedef struct _MetaMonitorMode MetaMonitorMode;
 | 
			
		||||
typedef struct _MetaMonitorInfo MetaMonitorInfo;
 | 
			
		||||
typedef struct _MetaCRTCInfo MetaCRTCInfo;
 | 
			
		||||
typedef struct _MetaOutputInfo MetaOutputInfo;
 | 
			
		||||
 | 
			
		||||
struct _MetaOutput
 | 
			
		||||
{
 | 
			
		||||
  /* The CRTC driving this output, NULL if the output is not enabled */
 | 
			
		||||
  MetaCRTC *crtc;
 | 
			
		||||
  /* The low-level ID of this output, used to apply back configuration */
 | 
			
		||||
  glong output_id;
 | 
			
		||||
  char *name;
 | 
			
		||||
  char *vendor;
 | 
			
		||||
  char *product;
 | 
			
		||||
  char *serial;
 | 
			
		||||
  int width_mm;
 | 
			
		||||
  int height_mm;
 | 
			
		||||
  CoglSubpixelOrder subpixel_order;
 | 
			
		||||
 | 
			
		||||
  MetaMonitorMode *preferred_mode;
 | 
			
		||||
  MetaMonitorMode **modes;
 | 
			
		||||
  unsigned int n_modes;
 | 
			
		||||
 | 
			
		||||
  MetaCRTC **possible_crtcs;
 | 
			
		||||
  unsigned int n_possible_crtcs;
 | 
			
		||||
 | 
			
		||||
  MetaOutput **possible_clones;
 | 
			
		||||
  unsigned int n_possible_clones;
 | 
			
		||||
 | 
			
		||||
  int backlight;
 | 
			
		||||
  int backlight_min;
 | 
			
		||||
  int backlight_max;
 | 
			
		||||
 | 
			
		||||
  /* Used when changing configuration */
 | 
			
		||||
  gboolean dirty;
 | 
			
		||||
 | 
			
		||||
  /* The low-level bits used to build the high-level info
 | 
			
		||||
     in MetaMonitorInfo
 | 
			
		||||
 | 
			
		||||
     XXX: flags maybe?
 | 
			
		||||
     There is a lot of code that uses MonitorInfo->is_primary,
 | 
			
		||||
     but nobody uses MetaOutput yet
 | 
			
		||||
  */
 | 
			
		||||
  gboolean is_primary;
 | 
			
		||||
  gboolean is_presentation;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaCRTC
 | 
			
		||||
{
 | 
			
		||||
  glong crtc_id;
 | 
			
		||||
  MetaRectangle rect;
 | 
			
		||||
  MetaMonitorMode *current_mode;
 | 
			
		||||
  enum wl_output_transform transform;
 | 
			
		||||
  unsigned int all_transforms;
 | 
			
		||||
 | 
			
		||||
  /* Only used to build the logical configuration
 | 
			
		||||
     from the HW one
 | 
			
		||||
  */
 | 
			
		||||
  MetaMonitorInfo *logical_monitor;
 | 
			
		||||
 | 
			
		||||
  /* Used when changing configuration */
 | 
			
		||||
  gboolean dirty;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaMonitorMode
 | 
			
		||||
{
 | 
			
		||||
  /* The low-level ID of this mode, used to apply back configuration */
 | 
			
		||||
  glong mode_id;
 | 
			
		||||
 | 
			
		||||
  int width;
 | 
			
		||||
  int height;
 | 
			
		||||
  float refresh_rate;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * MetaMonitorInfo:
 | 
			
		||||
 *
 | 
			
		||||
 * A structure with high-level information about monitors.
 | 
			
		||||
 * This corresponds to a subset of the compositor coordinate space.
 | 
			
		||||
 * Clones are only reported once, irrespective of the way
 | 
			
		||||
 * they're implemented (two CRTCs configured for the same
 | 
			
		||||
 * coordinates or one CRTCs driving two outputs). Inactive CRTCs
 | 
			
		||||
 * are ignored, and so are disabled outputs.
 | 
			
		||||
 */
 | 
			
		||||
struct _MetaMonitorInfo
 | 
			
		||||
{
 | 
			
		||||
  int number;
 | 
			
		||||
  int xinerama_index;
 | 
			
		||||
  MetaRectangle rect;
 | 
			
		||||
  gboolean is_primary;
 | 
			
		||||
  gboolean is_presentation; /* XXX: not yet used */
 | 
			
		||||
  gboolean in_fullscreen;
 | 
			
		||||
 | 
			
		||||
  /* The primary or first output for this monitor, 0 if we can't figure out.
 | 
			
		||||
     It can be matched to an output_id of a MetaOutput.
 | 
			
		||||
 | 
			
		||||
     This is used as an opaque token on reconfiguration when switching from
 | 
			
		||||
     clone to extened, to decide on what output the windows should go next
 | 
			
		||||
     (it's an attempt to keep windows on the same monitor, and preferably on
 | 
			
		||||
     the primary one).
 | 
			
		||||
  */
 | 
			
		||||
  glong output_id;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * MetaCRTCInfo:
 | 
			
		||||
 * This represents the writable part of a CRTC, as deserialized from DBus
 | 
			
		||||
 * or built by MetaMonitorConfig
 | 
			
		||||
 *
 | 
			
		||||
 * Note: differently from the other structures in this file, MetaCRTCInfo
 | 
			
		||||
 * is handled by pointer. This is to accomodate the usage in MetaMonitorConfig
 | 
			
		||||
 */
 | 
			
		||||
struct _MetaCRTCInfo {
 | 
			
		||||
  MetaCRTC                 *crtc;
 | 
			
		||||
  MetaMonitorMode          *mode;
 | 
			
		||||
  int                       x;
 | 
			
		||||
  int                       y;
 | 
			
		||||
  enum wl_output_transform  transform;
 | 
			
		||||
  GPtrArray                *outputs;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * MetaOutputInfo:
 | 
			
		||||
 * this is the same as MetaOutputInfo, but for CRTCs
 | 
			
		||||
 */
 | 
			
		||||
struct _MetaOutputInfo {
 | 
			
		||||
  MetaOutput  *output;
 | 
			
		||||
  gboolean     is_primary;
 | 
			
		||||
  gboolean     is_presentation;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_MONITOR_MANAGER            (meta_monitor_manager_get_type ())
 | 
			
		||||
#define META_MONITOR_MANAGER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER, MetaMonitorManager))
 | 
			
		||||
#define META_MONITOR_MANAGER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_MONITOR_MANAGER, MetaMonitorManagerClass))
 | 
			
		||||
#define META_IS_MONITOR_MANAGER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER))
 | 
			
		||||
#define META_IS_MONITOR_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_MONITOR_MANAGER))
 | 
			
		||||
#define META_MONITOR_MANAGER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_MONITOR_MANAGER, MetaMonitorManagerClass))
 | 
			
		||||
 | 
			
		||||
struct _MetaMonitorManager
 | 
			
		||||
{
 | 
			
		||||
  MetaDBusDisplayConfigSkeleton parent_instance;
 | 
			
		||||
 | 
			
		||||
  /* XXX: this structure is very badly
 | 
			
		||||
     packed, but I like the logical organization
 | 
			
		||||
     of fields */
 | 
			
		||||
 | 
			
		||||
  gboolean in_init;
 | 
			
		||||
  unsigned int serial;
 | 
			
		||||
 | 
			
		||||
  MetaPowerSave power_save_mode;
 | 
			
		||||
 | 
			
		||||
  int max_screen_width;
 | 
			
		||||
  int max_screen_height;
 | 
			
		||||
  int screen_width;
 | 
			
		||||
  int screen_height;
 | 
			
		||||
 | 
			
		||||
  /* Outputs refer to physical screens,
 | 
			
		||||
     CRTCs refer to stuff that can drive outputs
 | 
			
		||||
     (like encoders, but less tied to the HW),
 | 
			
		||||
     while monitor_infos refer to logical ones.
 | 
			
		||||
 | 
			
		||||
     See also the comment in monitor-private.h
 | 
			
		||||
  */
 | 
			
		||||
  MetaOutput *outputs;
 | 
			
		||||
  unsigned int n_outputs;
 | 
			
		||||
 | 
			
		||||
  MetaMonitorMode *modes;
 | 
			
		||||
  unsigned int n_modes;
 | 
			
		||||
 | 
			
		||||
  MetaCRTC *crtcs;
 | 
			
		||||
  unsigned int n_crtcs;
 | 
			
		||||
 | 
			
		||||
  MetaMonitorInfo *monitor_infos;
 | 
			
		||||
  unsigned int n_monitor_infos;
 | 
			
		||||
  int primary_monitor_index;
 | 
			
		||||
 | 
			
		||||
  int dbus_name_id;
 | 
			
		||||
 | 
			
		||||
  int persistent_timeout_id;
 | 
			
		||||
  MetaMonitorConfig *config;
 | 
			
		||||
 | 
			
		||||
  GnomePnpIds *pnp_ids;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaMonitorManagerClass
 | 
			
		||||
{
 | 
			
		||||
  MetaDBusDisplayConfigSkeletonClass parent_class;
 | 
			
		||||
 | 
			
		||||
  void (*read_current) (MetaMonitorManager *);
 | 
			
		||||
 | 
			
		||||
  char* (*get_edid_file) (MetaMonitorManager *,
 | 
			
		||||
                          MetaOutput         *);
 | 
			
		||||
  GBytes* (*read_edid) (MetaMonitorManager *,
 | 
			
		||||
                        MetaOutput         *);
 | 
			
		||||
 | 
			
		||||
  void (*apply_configuration) (MetaMonitorManager  *,
 | 
			
		||||
                               MetaCRTCInfo       **,
 | 
			
		||||
                               unsigned int         ,
 | 
			
		||||
                               MetaOutputInfo     **,
 | 
			
		||||
                               unsigned int);
 | 
			
		||||
 | 
			
		||||
  void (*set_power_save_mode) (MetaMonitorManager *,
 | 
			
		||||
                               MetaPowerSave);
 | 
			
		||||
 | 
			
		||||
  void (*change_backlight) (MetaMonitorManager *,
 | 
			
		||||
                            MetaOutput         *,
 | 
			
		||||
                            int);
 | 
			
		||||
 | 
			
		||||
  void (*get_crtc_gamma) (MetaMonitorManager  *,
 | 
			
		||||
                          MetaCRTC            *,
 | 
			
		||||
                          gsize               *,
 | 
			
		||||
                          unsigned short     **,
 | 
			
		||||
                          unsigned short     **,
 | 
			
		||||
                          unsigned short     **);
 | 
			
		||||
  void (*set_crtc_gamma) (MetaMonitorManager *,
 | 
			
		||||
                          MetaCRTC           *,
 | 
			
		||||
                          gsize               ,
 | 
			
		||||
                          unsigned short     *,
 | 
			
		||||
                          unsigned short     *,
 | 
			
		||||
                          unsigned short     *);
 | 
			
		||||
 | 
			
		||||
  gboolean (*handle_xevent) (MetaMonitorManager *,
 | 
			
		||||
                             XEvent             *);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GType meta_monitor_manager_get_type (void);
 | 
			
		||||
 | 
			
		||||
void                meta_monitor_manager_initialize (void);
 | 
			
		||||
MetaMonitorManager *meta_monitor_manager_get  (void);
 | 
			
		||||
 | 
			
		||||
MetaMonitorInfo    *meta_monitor_manager_get_monitor_infos (MetaMonitorManager *manager,
 | 
			
		||||
							    unsigned int       *n_infos);
 | 
			
		||||
 | 
			
		||||
MetaOutput         *meta_monitor_manager_get_outputs       (MetaMonitorManager *manager,
 | 
			
		||||
							    unsigned int       *n_outputs);
 | 
			
		||||
 | 
			
		||||
void                meta_monitor_manager_get_resources     (MetaMonitorManager  *manager,
 | 
			
		||||
                                                            MetaMonitorMode    **modes,
 | 
			
		||||
                                                            unsigned int        *n_modes,
 | 
			
		||||
                                                            MetaCRTC           **crtcs,
 | 
			
		||||
                                                            unsigned int        *n_crtcs,
 | 
			
		||||
                                                            MetaOutput         **outputs,
 | 
			
		||||
                                                            unsigned int        *n_outputs);
 | 
			
		||||
 | 
			
		||||
int                 meta_monitor_manager_get_primary_index (MetaMonitorManager *manager);
 | 
			
		||||
 | 
			
		||||
gboolean            meta_monitor_manager_handle_xevent     (MetaMonitorManager *manager,
 | 
			
		||||
                                                            XEvent             *event);
 | 
			
		||||
 | 
			
		||||
void                meta_monitor_manager_get_screen_size   (MetaMonitorManager *manager,
 | 
			
		||||
                                                            int                *width,
 | 
			
		||||
                                                            int                *height);
 | 
			
		||||
 | 
			
		||||
void                meta_monitor_manager_get_screen_limits (MetaMonitorManager *manager,
 | 
			
		||||
                                                            int                *width,
 | 
			
		||||
                                                            int                *height);
 | 
			
		||||
 | 
			
		||||
void                meta_monitor_manager_apply_configuration (MetaMonitorManager  *manager,
 | 
			
		||||
                                                              MetaCRTCInfo       **crtcs,
 | 
			
		||||
                                                              unsigned int         n_crtcs,
 | 
			
		||||
                                                              MetaOutputInfo     **outputs,
 | 
			
		||||
                                                              unsigned int         n_outputs);
 | 
			
		||||
 | 
			
		||||
void                meta_monitor_manager_confirm_configuration (MetaMonitorManager *manager,
 | 
			
		||||
                                                                gboolean            ok);
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_MONITOR_MANAGER_XRANDR            (meta_monitor_manager_xrandr_get_type ())
 | 
			
		||||
#define META_MONITOR_MANAGER_XRANDR(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandr))
 | 
			
		||||
#define META_MONITOR_MANAGER_XRANDR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandrClass))
 | 
			
		||||
#define META_IS_MONITOR_MANAGER_XRANDR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER_XRANDR))
 | 
			
		||||
#define META_IS_MONITOR_MANAGER_XRANDR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_MONITOR_MANAGER_XRANDR))
 | 
			
		||||
#define META_MONITOR_MANAGER_XRANDR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandrClass))
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaMonitorManagerXrandrClass    MetaMonitorManagerXrandrClass;
 | 
			
		||||
typedef struct _MetaMonitorManagerXrandr         MetaMonitorManagerXrandr;
 | 
			
		||||
 | 
			
		||||
GType meta_monitor_manager_xrandr_get_type (void);
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_MONITOR_CONFIG            (meta_monitor_config_get_type ())
 | 
			
		||||
#define META_MONITOR_CONFIG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfig))
 | 
			
		||||
#define META_MONITOR_CONFIG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_MONITOR_CONFIG, MetaMonitorConfigClass))
 | 
			
		||||
#define META_IS_MONITOR_CONFIG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_CONFIG))
 | 
			
		||||
#define META_IS_MONITOR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_MONITOR_CONFIG))
 | 
			
		||||
#define META_MONITOR_CONFIG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_MONITOR_CONFIG, MetaMonitorConfigClass))
 | 
			
		||||
 | 
			
		||||
GType meta_monitor_config_get_type (void) G_GNUC_CONST;
 | 
			
		||||
 | 
			
		||||
MetaMonitorConfig *meta_monitor_config_new (void);
 | 
			
		||||
 | 
			
		||||
gboolean           meta_monitor_config_match_current (MetaMonitorConfig  *config,
 | 
			
		||||
                                                      MetaMonitorManager *manager);
 | 
			
		||||
 | 
			
		||||
gboolean           meta_monitor_config_apply_stored (MetaMonitorConfig  *config,
 | 
			
		||||
                                                     MetaMonitorManager *manager);
 | 
			
		||||
 | 
			
		||||
void               meta_monitor_config_make_default (MetaMonitorConfig  *config,
 | 
			
		||||
                                                     MetaMonitorManager *manager);
 | 
			
		||||
 | 
			
		||||
void               meta_monitor_config_update_current (MetaMonitorConfig  *config,
 | 
			
		||||
                                                       MetaMonitorManager *manager);
 | 
			
		||||
void               meta_monitor_config_make_persistent (MetaMonitorConfig *config);
 | 
			
		||||
 | 
			
		||||
void               meta_monitor_config_restore_previous (MetaMonitorConfig  *config,
 | 
			
		||||
                                                         MetaMonitorManager *manager);
 | 
			
		||||
 | 
			
		||||
void               meta_crtc_info_free   (MetaCRTCInfo   *info);
 | 
			
		||||
void               meta_output_info_free (MetaOutputInfo *info);
 | 
			
		||||
 | 
			
		||||
/* Returns true if transform causes width and height to be inverted
 | 
			
		||||
   This is true for the odd transforms in the enum */
 | 
			
		||||
static inline gboolean
 | 
			
		||||
meta_monitor_transform_is_rotated (enum wl_output_transform transform)
 | 
			
		||||
{
 | 
			
		||||
  return (transform % 2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										938
									
								
								src/core/monitor-xrandr.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										938
									
								
								src/core/monitor-xrandr.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,938 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
/* 
 | 
			
		||||
 * Copyright (C) 2001, 2002 Havoc Pennington
 | 
			
		||||
 * Copyright (C) 2002, 2003 Red Hat Inc.
 | 
			
		||||
 * Some ICCCM manager selection code derived from fvwm2,
 | 
			
		||||
 * Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team
 | 
			
		||||
 * Copyright (C) 2003 Rob Adams
 | 
			
		||||
 * Copyright (C) 2004-2006 Elijah Newren
 | 
			
		||||
 * Copyright (C) 2013 Red Hat Inc.
 | 
			
		||||
 * 
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License as
 | 
			
		||||
 * published by the Free Software Foundation; either version 2 of the
 | 
			
		||||
 * License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program 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
 | 
			
		||||
 * General Public License for more details.
 | 
			
		||||
 * 
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 | 
			
		||||
 * 02111-1307, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
 | 
			
		||||
#include <X11/Xatom.h>
 | 
			
		||||
#include <X11/extensions/Xrandr.h>
 | 
			
		||||
#include <X11/extensions/dpms.h>
 | 
			
		||||
 | 
			
		||||
#include <meta/main.h>
 | 
			
		||||
#include <meta/errors.h>
 | 
			
		||||
#include "monitor-private.h"
 | 
			
		||||
 | 
			
		||||
#include "edid.h"
 | 
			
		||||
 | 
			
		||||
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
 | 
			
		||||
 | 
			
		||||
/* Look for DPI_FALLBACK in:
 | 
			
		||||
 * http://git.gnome.org/browse/gnome-settings-daemon/tree/plugins/xsettings/gsd-xsettings-manager.c
 | 
			
		||||
 * for the reasoning */
 | 
			
		||||
#define DPI_FALLBACK 96.0
 | 
			
		||||
 | 
			
		||||
struct _MetaMonitorManagerXrandr
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManager parent_instance;
 | 
			
		||||
 | 
			
		||||
  Display *xdisplay;
 | 
			
		||||
  XRRScreenResources *resources;
 | 
			
		||||
  int time;
 | 
			
		||||
  int rr_event_base;
 | 
			
		||||
  int rr_error_base;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaMonitorManagerXrandrClass
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerClass parent_class;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (MetaMonitorManagerXrandr, meta_monitor_manager_xrandr, META_TYPE_MONITOR_MANAGER);
 | 
			
		||||
 | 
			
		||||
static enum wl_output_transform
 | 
			
		||||
wl_transform_from_xrandr (Rotation rotation)
 | 
			
		||||
{
 | 
			
		||||
  static const enum wl_output_transform y_reflected_map[4] = {
 | 
			
		||||
    WL_OUTPUT_TRANSFORM_FLIPPED_180,
 | 
			
		||||
    WL_OUTPUT_TRANSFORM_FLIPPED_90,
 | 
			
		||||
    WL_OUTPUT_TRANSFORM_FLIPPED,
 | 
			
		||||
    WL_OUTPUT_TRANSFORM_FLIPPED_270
 | 
			
		||||
  };
 | 
			
		||||
  enum wl_output_transform ret;
 | 
			
		||||
 | 
			
		||||
  switch (rotation & 0x7F)
 | 
			
		||||
    {
 | 
			
		||||
    default:
 | 
			
		||||
    case RR_Rotate_0:
 | 
			
		||||
      ret = WL_OUTPUT_TRANSFORM_NORMAL;
 | 
			
		||||
      break;
 | 
			
		||||
    case RR_Rotate_90:
 | 
			
		||||
      ret = WL_OUTPUT_TRANSFORM_90;
 | 
			
		||||
      break;
 | 
			
		||||
    case RR_Rotate_180:
 | 
			
		||||
      ret = WL_OUTPUT_TRANSFORM_180;
 | 
			
		||||
      break;
 | 
			
		||||
    case RR_Rotate_270:
 | 
			
		||||
      ret = WL_OUTPUT_TRANSFORM_270;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (rotation & RR_Reflect_X)
 | 
			
		||||
    return ret + 4;
 | 
			
		||||
  else if (rotation & RR_Reflect_Y)
 | 
			
		||||
    return y_reflected_map[ret];
 | 
			
		||||
  else
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define ALL_ROTATIONS (RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270)
 | 
			
		||||
 | 
			
		||||
static unsigned int
 | 
			
		||||
wl_transform_from_xrandr_all (Rotation rotation)
 | 
			
		||||
{
 | 
			
		||||
  unsigned ret;
 | 
			
		||||
 | 
			
		||||
  /* Handle the common cases first (none or all) */
 | 
			
		||||
  if (rotation == 0 || rotation == RR_Rotate_0)
 | 
			
		||||
    return (1 << WL_OUTPUT_TRANSFORM_NORMAL);
 | 
			
		||||
 | 
			
		||||
  /* All rotations and one reflection -> all of them by composition */
 | 
			
		||||
  if ((rotation & ALL_ROTATIONS) &&
 | 
			
		||||
      ((rotation & RR_Reflect_X) || (rotation & RR_Reflect_Y)))
 | 
			
		||||
    return ALL_WL_TRANSFORMS;
 | 
			
		||||
 | 
			
		||||
  ret = 1 << WL_OUTPUT_TRANSFORM_NORMAL;
 | 
			
		||||
  if (rotation & RR_Rotate_90)
 | 
			
		||||
    ret |= 1 << WL_OUTPUT_TRANSFORM_90;
 | 
			
		||||
  if (rotation & RR_Rotate_180)
 | 
			
		||||
    ret |= 1 << WL_OUTPUT_TRANSFORM_180;
 | 
			
		||||
  if (rotation & RR_Rotate_270)
 | 
			
		||||
    ret |= 1 << WL_OUTPUT_TRANSFORM_270;
 | 
			
		||||
  if (rotation & (RR_Rotate_0 | RR_Reflect_X))
 | 
			
		||||
    ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED;
 | 
			
		||||
  if (rotation & (RR_Rotate_90 | RR_Reflect_X))
 | 
			
		||||
    ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_90;
 | 
			
		||||
  if (rotation & (RR_Rotate_180 | RR_Reflect_X))
 | 
			
		||||
    ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_180;
 | 
			
		||||
  if (rotation & (RR_Rotate_270 | RR_Reflect_X))
 | 
			
		||||
    ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_270;
 | 
			
		||||
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
                                MetaOutput               *output)
 | 
			
		||||
{
 | 
			
		||||
  MetaDisplay *display = meta_get_display ();
 | 
			
		||||
  gboolean value;
 | 
			
		||||
  Atom actual_type;
 | 
			
		||||
  int actual_format;
 | 
			
		||||
  unsigned long nitems, bytes_after;
 | 
			
		||||
  unsigned char *buffer;
 | 
			
		||||
 | 
			
		||||
  XRRGetOutputProperty (manager_xrandr->xdisplay,
 | 
			
		||||
                        (XID)output->output_id,
 | 
			
		||||
                        display->atom__MUTTER_PRESENTATION_OUTPUT,
 | 
			
		||||
                        0, G_MAXLONG, False, False, XA_CARDINAL,
 | 
			
		||||
                        &actual_type, &actual_format,
 | 
			
		||||
                        &nitems, &bytes_after, &buffer);
 | 
			
		||||
 | 
			
		||||
  if (actual_type != XA_CARDINAL || actual_format != 32 ||
 | 
			
		||||
      nitems < 1)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  value = ((int*)buffer)[0];
 | 
			
		||||
 | 
			
		||||
  XFree (buffer);
 | 
			
		||||
  return value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
normalize_backlight (MetaOutput *output,
 | 
			
		||||
                     int         hw_value)
 | 
			
		||||
{
 | 
			
		||||
  return round((double)(hw_value - output->backlight_min) /
 | 
			
		||||
               (output->backlight_max - output->backlight_min) * 100.0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
                             MetaOutput               *output)
 | 
			
		||||
{
 | 
			
		||||
  MetaDisplay *display = meta_get_display ();
 | 
			
		||||
  gboolean value;
 | 
			
		||||
  Atom actual_type;
 | 
			
		||||
  int actual_format;
 | 
			
		||||
  unsigned long nitems, bytes_after;
 | 
			
		||||
  unsigned char *buffer;
 | 
			
		||||
 | 
			
		||||
  XRRGetOutputProperty (manager_xrandr->xdisplay,
 | 
			
		||||
                        (XID)output->output_id,
 | 
			
		||||
                        display->atom_BACKLIGHT,
 | 
			
		||||
                        0, G_MAXLONG, False, False, XA_INTEGER,
 | 
			
		||||
                        &actual_type, &actual_format,
 | 
			
		||||
                        &nitems, &bytes_after, &buffer);
 | 
			
		||||
 | 
			
		||||
  if (actual_type != XA_INTEGER || actual_format != 32 ||
 | 
			
		||||
      nitems < 1)
 | 
			
		||||
    return -1;
 | 
			
		||||
 | 
			
		||||
  value = ((int*)buffer)[0];
 | 
			
		||||
 | 
			
		||||
  XFree (buffer);
 | 
			
		||||
  return normalize_backlight (output, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
output_get_backlight_limits_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
                                    MetaOutput               *output)
 | 
			
		||||
{
 | 
			
		||||
  MetaDisplay *display = meta_get_display ();
 | 
			
		||||
  XRRPropertyInfo *info;
 | 
			
		||||
 | 
			
		||||
  meta_error_trap_push (display);
 | 
			
		||||
  info = XRRQueryOutputProperty (manager_xrandr->xdisplay,
 | 
			
		||||
                                 (XID)output->output_id,
 | 
			
		||||
                                 display->atom_BACKLIGHT);
 | 
			
		||||
  meta_error_trap_pop (display);
 | 
			
		||||
 | 
			
		||||
  if (info == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      meta_verbose ("could not get output property for %s\n", output->name);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (!info->range || info->num_values != 2)
 | 
			
		||||
    {
 | 
			
		||||
      meta_verbose ("backlight %s was not range\n", output->name);
 | 
			
		||||
      goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  output->backlight_min = info->values[0];
 | 
			
		||||
  output->backlight_max = info->values[1];
 | 
			
		||||
 | 
			
		||||
out:
 | 
			
		||||
  XFree (info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
compare_outputs (const void *one,
 | 
			
		||||
                 const void *two)
 | 
			
		||||
{
 | 
			
		||||
  const MetaOutput *o_one = one, *o_two = two;
 | 
			
		||||
 | 
			
		||||
  return strcmp (o_one->name, o_two->name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static guint8 *
 | 
			
		||||
get_edid_property (Display  *dpy,
 | 
			
		||||
                   RROutput  output,
 | 
			
		||||
                   Atom      atom,
 | 
			
		||||
                   gsize    *len)
 | 
			
		||||
{
 | 
			
		||||
  unsigned char *prop;
 | 
			
		||||
  int actual_format;
 | 
			
		||||
  unsigned long nitems, bytes_after;
 | 
			
		||||
  Atom actual_type;
 | 
			
		||||
  guint8 *result;
 | 
			
		||||
 | 
			
		||||
  XRRGetOutputProperty (dpy, output, atom,
 | 
			
		||||
                        0, 100, False, False,
 | 
			
		||||
                        AnyPropertyType,
 | 
			
		||||
                        &actual_type, &actual_format,
 | 
			
		||||
                        &nitems, &bytes_after, &prop);
 | 
			
		||||
 | 
			
		||||
  if (actual_type == XA_INTEGER && actual_format == 8)
 | 
			
		||||
    {
 | 
			
		||||
      result = g_memdup (prop, nitems);
 | 
			
		||||
      if (len)
 | 
			
		||||
        *len = nitems;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      result = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  XFree (prop);
 | 
			
		||||
    
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GBytes *
 | 
			
		||||
read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
                  XID                       output_id)
 | 
			
		||||
{
 | 
			
		||||
  Atom edid_atom;
 | 
			
		||||
  guint8 *result;
 | 
			
		||||
  gsize len;
 | 
			
		||||
 | 
			
		||||
  edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID", FALSE);
 | 
			
		||||
  result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
 | 
			
		||||
 | 
			
		||||
  if (!result)
 | 
			
		||||
    {
 | 
			
		||||
      edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID_DATA", FALSE);
 | 
			
		||||
      result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (!result)
 | 
			
		||||
    {
 | 
			
		||||
      edid_atom = XInternAtom (manager_xrandr->xdisplay, "XFree86_DDC_EDID1_RAWDATA", FALSE);
 | 
			
		||||
      result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (result)
 | 
			
		||||
    {
 | 
			
		||||
      if (len > 0 && len % 128 == 0)
 | 
			
		||||
        return g_bytes_new_take (result, len);
 | 
			
		||||
      else
 | 
			
		||||
        g_free (result);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
 | 
			
		||||
  XRRScreenResources *resources;
 | 
			
		||||
  RROutput primary_output;
 | 
			
		||||
  unsigned int i, j, k;
 | 
			
		||||
  unsigned int n_actual_outputs;
 | 
			
		||||
  int min_width, min_height;
 | 
			
		||||
  Screen *screen;
 | 
			
		||||
  BOOL dpms_capable, dpms_enabled;
 | 
			
		||||
  CARD16 dpms_state;
 | 
			
		||||
 | 
			
		||||
  if (manager_xrandr->resources)
 | 
			
		||||
    XRRFreeScreenResources (manager_xrandr->resources);
 | 
			
		||||
  manager_xrandr->resources = NULL;
 | 
			
		||||
 | 
			
		||||
  meta_error_trap_push (meta_get_display ());
 | 
			
		||||
  dpms_capable = DPMSCapable (manager_xrandr->xdisplay);
 | 
			
		||||
  meta_error_trap_pop (meta_get_display ());
 | 
			
		||||
 | 
			
		||||
  if (dpms_capable &&
 | 
			
		||||
      DPMSInfo (manager_xrandr->xdisplay, &dpms_state, &dpms_enabled) &&
 | 
			
		||||
      dpms_enabled)
 | 
			
		||||
    {
 | 
			
		||||
      switch (dpms_state)
 | 
			
		||||
	{
 | 
			
		||||
	case DPMSModeOn:
 | 
			
		||||
	  manager->power_save_mode = META_POWER_SAVE_ON;
 | 
			
		||||
	case DPMSModeStandby:
 | 
			
		||||
	  manager->power_save_mode = META_POWER_SAVE_STANDBY;
 | 
			
		||||
	case DPMSModeSuspend:
 | 
			
		||||
	  manager->power_save_mode = META_POWER_SAVE_SUSPEND;
 | 
			
		||||
	case DPMSModeOff:
 | 
			
		||||
	  manager->power_save_mode = META_POWER_SAVE_OFF;
 | 
			
		||||
	default:
 | 
			
		||||
	  manager->power_save_mode = META_POWER_SAVE_UNKNOWN;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      manager->power_save_mode = META_POWER_SAVE_UNKNOWN;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  XRRGetScreenSizeRange (manager_xrandr->xdisplay, DefaultRootWindow (manager_xrandr->xdisplay),
 | 
			
		||||
			 &min_width,
 | 
			
		||||
			 &min_height,
 | 
			
		||||
			 &manager->max_screen_width,
 | 
			
		||||
			 &manager->max_screen_height);
 | 
			
		||||
 | 
			
		||||
  screen = ScreenOfDisplay (manager_xrandr->xdisplay,
 | 
			
		||||
			    DefaultScreen (manager_xrandr->xdisplay));
 | 
			
		||||
  /* This is updated because we called RRUpdateConfiguration below */
 | 
			
		||||
  manager->screen_width = WidthOfScreen (screen);
 | 
			
		||||
  manager->screen_height = HeightOfScreen (screen);
 | 
			
		||||
 | 
			
		||||
  resources = XRRGetScreenResourcesCurrent (manager_xrandr->xdisplay,
 | 
			
		||||
					    DefaultRootWindow (manager_xrandr->xdisplay));
 | 
			
		||||
  if (!resources)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  manager_xrandr->resources = resources;
 | 
			
		||||
  manager_xrandr->time = resources->configTimestamp;
 | 
			
		||||
  manager->n_outputs = resources->noutput;
 | 
			
		||||
  manager->n_crtcs = resources->ncrtc;
 | 
			
		||||
  manager->n_modes = resources->nmode;
 | 
			
		||||
  manager->outputs = g_new0 (MetaOutput, manager->n_outputs);
 | 
			
		||||
  manager->modes = g_new0 (MetaMonitorMode, manager->n_modes);
 | 
			
		||||
  manager->crtcs = g_new0 (MetaCRTC, manager->n_crtcs);
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < (unsigned)resources->nmode; i++)
 | 
			
		||||
    {
 | 
			
		||||
      XRRModeInfo *xmode = &resources->modes[i];
 | 
			
		||||
      MetaMonitorMode *mode;
 | 
			
		||||
 | 
			
		||||
      mode = &manager->modes[i];
 | 
			
		||||
 | 
			
		||||
      mode->mode_id = xmode->id;
 | 
			
		||||
      mode->width = xmode->width;
 | 
			
		||||
      mode->height = xmode->height;
 | 
			
		||||
      mode->refresh_rate = (xmode->dotClock /
 | 
			
		||||
			    ((float)xmode->hTotal * xmode->vTotal));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < (unsigned)resources->ncrtc; i++)
 | 
			
		||||
    {
 | 
			
		||||
      XRRCrtcInfo *crtc;
 | 
			
		||||
      MetaCRTC *meta_crtc;
 | 
			
		||||
 | 
			
		||||
      crtc = XRRGetCrtcInfo (manager_xrandr->xdisplay, resources, resources->crtcs[i]);
 | 
			
		||||
 | 
			
		||||
      meta_crtc = &manager->crtcs[i];
 | 
			
		||||
 | 
			
		||||
      meta_crtc->crtc_id = resources->crtcs[i];
 | 
			
		||||
      meta_crtc->rect.x = crtc->x;
 | 
			
		||||
      meta_crtc->rect.y = crtc->y;
 | 
			
		||||
      meta_crtc->rect.width = crtc->width;
 | 
			
		||||
      meta_crtc->rect.height = crtc->height;
 | 
			
		||||
      meta_crtc->dirty = FALSE;
 | 
			
		||||
      meta_crtc->transform = wl_transform_from_xrandr (crtc->rotation);
 | 
			
		||||
      meta_crtc->all_transforms = wl_transform_from_xrandr_all (crtc->rotations);
 | 
			
		||||
 | 
			
		||||
      for (j = 0; j < (unsigned)resources->nmode; j++)
 | 
			
		||||
	{
 | 
			
		||||
	  if (resources->modes[j].id == crtc->mode)
 | 
			
		||||
	    {
 | 
			
		||||
	      meta_crtc->current_mode = &manager->modes[j];
 | 
			
		||||
	      break;
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
      XRRFreeCrtcInfo (crtc);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  primary_output = XRRGetOutputPrimary (manager_xrandr->xdisplay,
 | 
			
		||||
					DefaultRootWindow (manager_xrandr->xdisplay));
 | 
			
		||||
 | 
			
		||||
  n_actual_outputs = 0;
 | 
			
		||||
  for (i = 0; i < (unsigned)resources->noutput; i++)
 | 
			
		||||
    {
 | 
			
		||||
      XRROutputInfo *output;
 | 
			
		||||
      MetaOutput *meta_output;
 | 
			
		||||
 | 
			
		||||
      output = XRRGetOutputInfo (manager_xrandr->xdisplay, resources, resources->outputs[i]);
 | 
			
		||||
 | 
			
		||||
      meta_output = &manager->outputs[n_actual_outputs];
 | 
			
		||||
 | 
			
		||||
      if (output->connection != RR_Disconnected)
 | 
			
		||||
	{
 | 
			
		||||
          GBytes *edid;
 | 
			
		||||
          MonitorInfo *parsed_edid;
 | 
			
		||||
 | 
			
		||||
	  meta_output->output_id = resources->outputs[i];
 | 
			
		||||
	  meta_output->name = g_strdup (output->name);
 | 
			
		||||
 | 
			
		||||
          edid = read_output_edid (manager_xrandr, meta_output->output_id);
 | 
			
		||||
          if (edid)
 | 
			
		||||
            {
 | 
			
		||||
              gsize len;
 | 
			
		||||
 | 
			
		||||
              parsed_edid = decode_edid (g_bytes_get_data (edid, &len));
 | 
			
		||||
              if (parsed_edid)
 | 
			
		||||
                {
 | 
			
		||||
                  meta_output->vendor = g_strndup (parsed_edid->manufacturer_code, 4);
 | 
			
		||||
                  meta_output->product = g_strndup (parsed_edid->dsc_product_name, 14);
 | 
			
		||||
                  meta_output->serial = g_strndup (parsed_edid->dsc_serial_number, 14);
 | 
			
		||||
 | 
			
		||||
                  g_free (parsed_edid);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
              g_bytes_unref (edid);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          if (!meta_output->vendor)
 | 
			
		||||
            {
 | 
			
		||||
              meta_output->vendor = g_strdup ("unknown");
 | 
			
		||||
              meta_output->product = g_strdup ("unknown");
 | 
			
		||||
              meta_output->serial = g_strdup ("unknown");
 | 
			
		||||
            }
 | 
			
		||||
	  meta_output->width_mm = output->mm_width;
 | 
			
		||||
	  meta_output->height_mm = output->mm_height;
 | 
			
		||||
	  meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
 | 
			
		||||
 | 
			
		||||
	  meta_output->n_modes = output->nmode;
 | 
			
		||||
	  meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
 | 
			
		||||
	  for (j = 0; j < meta_output->n_modes; j++)
 | 
			
		||||
	    {
 | 
			
		||||
	      for (k = 0; k < manager->n_modes; k++)
 | 
			
		||||
		{
 | 
			
		||||
		  if (output->modes[j] == (XID)manager->modes[k].mode_id)
 | 
			
		||||
		    {
 | 
			
		||||
		      meta_output->modes[j] = &manager->modes[k];
 | 
			
		||||
		      break;
 | 
			
		||||
		    }
 | 
			
		||||
		}
 | 
			
		||||
	    }
 | 
			
		||||
	  meta_output->preferred_mode = meta_output->modes[0];
 | 
			
		||||
 | 
			
		||||
	  meta_output->n_possible_crtcs = output->ncrtc;
 | 
			
		||||
	  meta_output->possible_crtcs = g_new0 (MetaCRTC *, meta_output->n_possible_crtcs);
 | 
			
		||||
	  for (j = 0; j < (unsigned)output->ncrtc; j++)
 | 
			
		||||
	    {
 | 
			
		||||
	      for (k = 0; k < manager->n_crtcs; k++)
 | 
			
		||||
		{
 | 
			
		||||
		  if ((XID)manager->crtcs[k].crtc_id == output->crtcs[j])
 | 
			
		||||
		    {
 | 
			
		||||
		      meta_output->possible_crtcs[j] = &manager->crtcs[k];
 | 
			
		||||
		      break;
 | 
			
		||||
		    }
 | 
			
		||||
		}
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
	  meta_output->crtc = NULL;
 | 
			
		||||
	  for (j = 0; j < manager->n_crtcs; j++)
 | 
			
		||||
	    {
 | 
			
		||||
	      if ((XID)manager->crtcs[j].crtc_id == output->crtc)
 | 
			
		||||
		{
 | 
			
		||||
		  meta_output->crtc = &manager->crtcs[j];
 | 
			
		||||
		  break;
 | 
			
		||||
		}
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
	  meta_output->n_possible_clones = output->nclone;
 | 
			
		||||
	  meta_output->possible_clones = g_new0 (MetaOutput *, meta_output->n_possible_clones);
 | 
			
		||||
	  /* We can build the list of clones now, because we don't have the list of outputs
 | 
			
		||||
	     yet, so temporarily set the pointers to the bare XIDs, and then we'll fix them
 | 
			
		||||
	     in a second pass
 | 
			
		||||
	  */
 | 
			
		||||
	  for (j = 0; j < (unsigned)output->nclone; j++)
 | 
			
		||||
	    {
 | 
			
		||||
	      meta_output->possible_clones = GINT_TO_POINTER (output->clones[j]);
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
	  meta_output->is_primary = ((XID)meta_output->output_id == primary_output);
 | 
			
		||||
	  meta_output->is_presentation = output_get_presentation_xrandr (manager_xrandr, meta_output);
 | 
			
		||||
	  output_get_backlight_limits_xrandr (manager_xrandr, meta_output);
 | 
			
		||||
 | 
			
		||||
	  if (!(meta_output->backlight_min == 0 && meta_output->backlight_max == 0))
 | 
			
		||||
	    meta_output->backlight = output_get_backlight_xrandr (manager_xrandr, meta_output);
 | 
			
		||||
	  else
 | 
			
		||||
	    meta_output->backlight = -1;
 | 
			
		||||
 | 
			
		||||
	  n_actual_outputs++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
      XRRFreeOutputInfo (output);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  manager->n_outputs = n_actual_outputs;
 | 
			
		||||
 | 
			
		||||
  /* Sort the outputs for easier handling in MetaMonitorConfig */
 | 
			
		||||
  qsort (manager->outputs, manager->n_outputs, sizeof (MetaOutput), compare_outputs);
 | 
			
		||||
 | 
			
		||||
  /* Now fix the clones */
 | 
			
		||||
  for (i = 0; i < manager->n_outputs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      MetaOutput *meta_output;
 | 
			
		||||
 | 
			
		||||
      meta_output = &manager->outputs[i];
 | 
			
		||||
 | 
			
		||||
      for (j = 0; j < meta_output->n_possible_clones; j++)
 | 
			
		||||
	{
 | 
			
		||||
	  RROutput clone = GPOINTER_TO_INT (meta_output->possible_clones[j]);
 | 
			
		||||
 | 
			
		||||
	  for (k = 0; k < manager->n_outputs; k++)
 | 
			
		||||
	    {
 | 
			
		||||
	      if (clone == (XID)manager->outputs[k].output_id)
 | 
			
		||||
		{
 | 
			
		||||
		  meta_output->possible_clones[j] = &manager->outputs[k];
 | 
			
		||||
		  break;
 | 
			
		||||
		}
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GBytes *
 | 
			
		||||
meta_monitor_manager_xrandr_read_edid (MetaMonitorManager *manager,
 | 
			
		||||
                                       MetaOutput         *output)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
 | 
			
		||||
 | 
			
		||||
  return read_output_edid (manager_xrandr, output->output_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_xrandr_set_power_save_mode (MetaMonitorManager *manager,
 | 
			
		||||
						 MetaPowerSave       mode)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
 | 
			
		||||
  CARD16 state;
 | 
			
		||||
 | 
			
		||||
  switch (mode) {
 | 
			
		||||
  case META_POWER_SAVE_ON:
 | 
			
		||||
    state = DPMSModeOn;
 | 
			
		||||
    break;
 | 
			
		||||
  case META_POWER_SAVE_STANDBY:
 | 
			
		||||
    state = DPMSModeStandby;
 | 
			
		||||
    break;
 | 
			
		||||
  case META_POWER_SAVE_SUSPEND:
 | 
			
		||||
    state = DPMSModeSuspend;
 | 
			
		||||
    break;
 | 
			
		||||
  case META_POWER_SAVE_OFF:
 | 
			
		||||
    state = DPMSModeOff;
 | 
			
		||||
    break;
 | 
			
		||||
  default:
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  meta_error_trap_push (meta_get_display ());
 | 
			
		||||
  DPMSForceLevel (manager_xrandr->xdisplay, state);
 | 
			
		||||
  DPMSSetTimeouts (manager_xrandr->xdisplay, 0, 0, 0);
 | 
			
		||||
  meta_error_trap_pop (meta_get_display ());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Rotation
 | 
			
		||||
wl_transform_to_xrandr (enum wl_output_transform transform)
 | 
			
		||||
{
 | 
			
		||||
  switch (transform)
 | 
			
		||||
    {
 | 
			
		||||
    case WL_OUTPUT_TRANSFORM_NORMAL:
 | 
			
		||||
      return RR_Rotate_0;
 | 
			
		||||
    case WL_OUTPUT_TRANSFORM_90:
 | 
			
		||||
      return RR_Rotate_90;
 | 
			
		||||
    case WL_OUTPUT_TRANSFORM_180:
 | 
			
		||||
      return RR_Rotate_180;
 | 
			
		||||
    case WL_OUTPUT_TRANSFORM_270:
 | 
			
		||||
      return RR_Rotate_270;
 | 
			
		||||
    case WL_OUTPUT_TRANSFORM_FLIPPED:
 | 
			
		||||
      return RR_Reflect_X | RR_Rotate_0;
 | 
			
		||||
    case WL_OUTPUT_TRANSFORM_FLIPPED_90:
 | 
			
		||||
      return RR_Reflect_X | RR_Rotate_90;
 | 
			
		||||
    case WL_OUTPUT_TRANSFORM_FLIPPED_180:
 | 
			
		||||
      return RR_Reflect_X | RR_Rotate_180;
 | 
			
		||||
    case WL_OUTPUT_TRANSFORM_FLIPPED_270:
 | 
			
		||||
      return RR_Reflect_X | RR_Rotate_270;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_assert_not_reached ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
output_set_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
 | 
			
		||||
                                MetaOutput               *output,
 | 
			
		||||
                                gboolean                  presentation)
 | 
			
		||||
{
 | 
			
		||||
  MetaDisplay *display = meta_get_display ();
 | 
			
		||||
  int value = presentation;
 | 
			
		||||
 | 
			
		||||
  XRRChangeOutputProperty (manager_xrandr->xdisplay,
 | 
			
		||||
                           (XID)output->output_id,
 | 
			
		||||
                           display->atom__MUTTER_PRESENTATION_OUTPUT,
 | 
			
		||||
                           XA_CARDINAL, 32, PropModeReplace,
 | 
			
		||||
                           (unsigned char*) &value, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
 | 
			
		||||
						 MetaCRTCInfo       **crtcs,
 | 
			
		||||
						 unsigned int         n_crtcs,
 | 
			
		||||
						 MetaOutputInfo     **outputs,
 | 
			
		||||
						 unsigned int         n_outputs)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
 | 
			
		||||
  unsigned i;
 | 
			
		||||
  int width, height, width_mm, height_mm;
 | 
			
		||||
 | 
			
		||||
  meta_display_grab (meta_get_display ());
 | 
			
		||||
 | 
			
		||||
  /* First compute the new size of the screen (framebuffer) */
 | 
			
		||||
  width = 0; height = 0;
 | 
			
		||||
  for (i = 0; i < n_crtcs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      MetaCRTCInfo *crtc_info = crtcs[i];
 | 
			
		||||
      MetaCRTC *crtc = crtc_info->crtc;
 | 
			
		||||
      crtc->dirty = TRUE;
 | 
			
		||||
 | 
			
		||||
      if (crtc_info->mode == NULL)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (meta_monitor_transform_is_rotated (crtc_info->transform))
 | 
			
		||||
        {
 | 
			
		||||
          width = MAX (width, crtc_info->x + crtc_info->mode->height);
 | 
			
		||||
          height = MAX (height, crtc_info->y + crtc_info->mode->width);
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          width = MAX (width, crtc_info->x + crtc_info->mode->width);
 | 
			
		||||
          height = MAX (height, crtc_info->y + crtc_info->mode->height);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* Second disable all newly disabled CRTCs, or CRTCs that in the previous
 | 
			
		||||
     configuration would be outside the new framebuffer (otherwise X complains
 | 
			
		||||
     loudly when resizing)
 | 
			
		||||
     CRTC will be enabled again after resizing the FB
 | 
			
		||||
  */
 | 
			
		||||
  for (i = 0; i < n_crtcs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      MetaCRTCInfo *crtc_info = crtcs[i];
 | 
			
		||||
      MetaCRTC *crtc = crtc_info->crtc;
 | 
			
		||||
 | 
			
		||||
      if (crtc_info->mode == NULL ||
 | 
			
		||||
          crtc->rect.x + crtc->rect.width > width ||
 | 
			
		||||
          crtc->rect.y + crtc->rect.height > height)
 | 
			
		||||
        {
 | 
			
		||||
          XRRSetCrtcConfig (manager_xrandr->xdisplay,
 | 
			
		||||
                            manager_xrandr->resources,
 | 
			
		||||
                            (XID)crtc->crtc_id,
 | 
			
		||||
                            manager_xrandr->time,
 | 
			
		||||
                            0, 0,
 | 
			
		||||
                            None,
 | 
			
		||||
                            RR_Rotate_0,
 | 
			
		||||
                            NULL, 0);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* Disable CRTCs not mentioned in the list */
 | 
			
		||||
  for (i = 0; i < manager->n_crtcs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      MetaCRTC *crtc = &manager->crtcs[i];
 | 
			
		||||
 | 
			
		||||
      if (crtc->dirty)
 | 
			
		||||
        {
 | 
			
		||||
          crtc->dirty = FALSE;
 | 
			
		||||
          continue;
 | 
			
		||||
        }
 | 
			
		||||
      if (crtc->current_mode == NULL)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      XRRSetCrtcConfig (manager_xrandr->xdisplay,
 | 
			
		||||
                        manager_xrandr->resources,
 | 
			
		||||
                        (XID)crtc->crtc_id,
 | 
			
		||||
                        manager_xrandr->time,
 | 
			
		||||
                        0, 0,
 | 
			
		||||
                        None,
 | 
			
		||||
                        RR_Rotate_0,
 | 
			
		||||
                        NULL, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_assert (width > 0 && height > 0);
 | 
			
		||||
  /* The 'physical size' of an X screen is meaningless if that screen
 | 
			
		||||
   * can consist of many monitors. So just pick a size that make the
 | 
			
		||||
   * dpi 96.
 | 
			
		||||
   *
 | 
			
		||||
   * Firefox and Evince apparently believe what X tells them.
 | 
			
		||||
   */
 | 
			
		||||
  width_mm = (width / DPI_FALLBACK) * 25.4 + 0.5;
 | 
			
		||||
  height_mm = (height / DPI_FALLBACK) * 25.4 + 0.5;
 | 
			
		||||
  meta_error_trap_push (meta_get_display ());
 | 
			
		||||
  XRRSetScreenSize (manager_xrandr->xdisplay, DefaultRootWindow (manager_xrandr->xdisplay),
 | 
			
		||||
                    width, height, width_mm, height_mm);
 | 
			
		||||
  meta_error_trap_pop (meta_get_display ());
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < n_crtcs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      MetaCRTCInfo *crtc_info = crtcs[i];
 | 
			
		||||
      MetaCRTC *crtc = crtc_info->crtc;
 | 
			
		||||
 | 
			
		||||
      if (crtc_info->mode != NULL)
 | 
			
		||||
        {
 | 
			
		||||
          MetaMonitorMode *mode;
 | 
			
		||||
          XID *outputs;
 | 
			
		||||
          int j, n_outputs;
 | 
			
		||||
          Status ok;
 | 
			
		||||
 | 
			
		||||
          mode = crtc_info->mode;
 | 
			
		||||
 | 
			
		||||
          n_outputs = crtc_info->outputs->len;
 | 
			
		||||
          outputs = g_new (XID, n_outputs);
 | 
			
		||||
 | 
			
		||||
          for (j = 0; j < n_outputs; j++)
 | 
			
		||||
            outputs[j] = ((MetaOutput**)crtc_info->outputs->pdata)[j]->output_id;
 | 
			
		||||
 | 
			
		||||
          meta_error_trap_push (meta_get_display ());
 | 
			
		||||
          ok = XRRSetCrtcConfig (manager_xrandr->xdisplay,
 | 
			
		||||
                                 manager_xrandr->resources,
 | 
			
		||||
                                 (XID)crtc->crtc_id,
 | 
			
		||||
                                 manager_xrandr->time,
 | 
			
		||||
                                 crtc_info->x, crtc_info->y,
 | 
			
		||||
                                 (XID)mode->mode_id,
 | 
			
		||||
                                 wl_transform_to_xrandr (crtc_info->transform),
 | 
			
		||||
                                 outputs, n_outputs);
 | 
			
		||||
          meta_error_trap_pop (meta_get_display ());
 | 
			
		||||
 | 
			
		||||
          if (ok != Success)
 | 
			
		||||
            meta_warning ("Configuring CRTC %d with mode %d (%d x %d @ %f) at position %d, %d and transfrom %u failed\n",
 | 
			
		||||
                          (unsigned)(crtc->crtc_id), (unsigned)(mode->mode_id),
 | 
			
		||||
                          mode->width, mode->height, (float)mode->refresh_rate,
 | 
			
		||||
                          crtc_info->x, crtc_info->y, crtc_info->transform);
 | 
			
		||||
 | 
			
		||||
          g_free (outputs);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < n_outputs; i++)
 | 
			
		||||
    {
 | 
			
		||||
      MetaOutputInfo *output_info = outputs[i];
 | 
			
		||||
 | 
			
		||||
      if (output_info->is_primary)
 | 
			
		||||
        {
 | 
			
		||||
          XRRSetOutputPrimary (manager_xrandr->xdisplay,
 | 
			
		||||
                               DefaultRootWindow (manager_xrandr->xdisplay),
 | 
			
		||||
                               (XID)output_info->output->output_id);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      output_set_presentation_xrandr (manager_xrandr,
 | 
			
		||||
                                      output_info->output,
 | 
			
		||||
                                      output_info->is_presentation);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_display_ungrab (meta_get_display ());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_xrandr_change_backlight (MetaMonitorManager *manager,
 | 
			
		||||
					      MetaOutput         *output,
 | 
			
		||||
					      gint                value)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
 | 
			
		||||
  MetaDisplay *display = meta_get_display ();
 | 
			
		||||
  int hw_value;
 | 
			
		||||
 | 
			
		||||
  hw_value = round((double)value / 100.0 * output->backlight_max + output->backlight_min);
 | 
			
		||||
 | 
			
		||||
  meta_error_trap_push (display);
 | 
			
		||||
  XRRChangeOutputProperty (manager_xrandr->xdisplay,
 | 
			
		||||
                           (XID)output->output_id,
 | 
			
		||||
                           display->atom_BACKLIGHT,
 | 
			
		||||
                           XA_INTEGER, 32, PropModeReplace,
 | 
			
		||||
                           (unsigned char *) &hw_value, 1);
 | 
			
		||||
  meta_error_trap_pop (display);
 | 
			
		||||
 | 
			
		||||
  /* We're not selecting for property notifies, so update the value immediately */
 | 
			
		||||
  output->backlight = normalize_backlight (output, hw_value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_xrandr_get_crtc_gamma (MetaMonitorManager  *manager,
 | 
			
		||||
					    MetaCRTC            *crtc,
 | 
			
		||||
					    gsize               *size,
 | 
			
		||||
					    unsigned short     **red,
 | 
			
		||||
					    unsigned short     **green,
 | 
			
		||||
					    unsigned short     **blue)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
 | 
			
		||||
  XRRCrtcGamma *gamma;
 | 
			
		||||
 | 
			
		||||
  gamma = XRRGetCrtcGamma (manager_xrandr->xdisplay, (XID)crtc->crtc_id);
 | 
			
		||||
 | 
			
		||||
  *size = gamma->size;
 | 
			
		||||
  *red = g_memdup (gamma->red, sizeof (unsigned short) * gamma->size);
 | 
			
		||||
  *green = g_memdup (gamma->green, sizeof (unsigned short) * gamma->size);
 | 
			
		||||
  *blue = g_memdup (gamma->blue, sizeof (unsigned short) * gamma->size);
 | 
			
		||||
 | 
			
		||||
  XRRFreeGamma (gamma);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_xrandr_set_crtc_gamma (MetaMonitorManager *manager,
 | 
			
		||||
					    MetaCRTC           *crtc,
 | 
			
		||||
					    gsize               size,
 | 
			
		||||
					    unsigned short     *red,
 | 
			
		||||
					    unsigned short     *green,
 | 
			
		||||
					    unsigned short     *blue)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
 | 
			
		||||
  XRRCrtcGamma gamma;
 | 
			
		||||
 | 
			
		||||
  gamma.size = size;
 | 
			
		||||
  gamma.red = red;
 | 
			
		||||
  gamma.green = green;
 | 
			
		||||
  gamma.blue = blue;
 | 
			
		||||
 | 
			
		||||
  XRRSetCrtcGamma (manager_xrandr->xdisplay, (XID)crtc->crtc_id, &gamma);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager,
 | 
			
		||||
					   XEvent             *event)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
 | 
			
		||||
 | 
			
		||||
  if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  XRRUpdateConfiguration (event);
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
 | 
			
		||||
{
 | 
			
		||||
  MetaDisplay *display = meta_get_display ();
 | 
			
		||||
 | 
			
		||||
  manager_xrandr->xdisplay = display->xdisplay;
 | 
			
		||||
 | 
			
		||||
  if (!XRRQueryExtension (manager_xrandr->xdisplay,
 | 
			
		||||
			  &manager_xrandr->rr_event_base,
 | 
			
		||||
			  &manager_xrandr->rr_error_base))
 | 
			
		||||
    {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      /* We only use ScreenChangeNotify, but GDK uses the others,
 | 
			
		||||
	 and we don't want to step on its toes */
 | 
			
		||||
      XRRSelectInput (manager_xrandr->xdisplay,
 | 
			
		||||
		      DefaultRootWindow (manager_xrandr->xdisplay),
 | 
			
		||||
		      RRScreenChangeNotifyMask
 | 
			
		||||
		      | RRCrtcChangeNotifyMask
 | 
			
		||||
		      | RROutputPropertyNotifyMask);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_xrandr_finalize (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (object);
 | 
			
		||||
 | 
			
		||||
  if (manager_xrandr->resources)
 | 
			
		||||
    XRRFreeScreenResources (manager_xrandr->resources);
 | 
			
		||||
  manager_xrandr->resources = NULL;
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
 | 
			
		||||
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  object_class->finalize = meta_monitor_manager_xrandr_finalize;
 | 
			
		||||
 | 
			
		||||
  manager_class->read_current = meta_monitor_manager_xrandr_read_current;
 | 
			
		||||
  manager_class->read_edid = meta_monitor_manager_xrandr_read_edid;
 | 
			
		||||
  manager_class->apply_configuration = meta_monitor_manager_xrandr_apply_configuration;
 | 
			
		||||
  manager_class->set_power_save_mode = meta_monitor_manager_xrandr_set_power_save_mode;
 | 
			
		||||
  manager_class->change_backlight = meta_monitor_manager_xrandr_change_backlight;
 | 
			
		||||
  manager_class->get_crtc_gamma = meta_monitor_manager_xrandr_get_crtc_gamma;
 | 
			
		||||
  manager_class->set_crtc_gamma = meta_monitor_manager_xrandr_set_crtc_gamma;
 | 
			
		||||
  manager_class->handle_xevent = meta_monitor_manager_xrandr_handle_xevent;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1553
									
								
								src/core/monitor.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1553
									
								
								src/core/monitor.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -38,17 +38,7 @@
 | 
			
		||||
#include <X11/Xutil.h>
 | 
			
		||||
#include "stack-tracker.h"
 | 
			
		||||
#include "ui.h"
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaMonitorInfo MetaMonitorInfo;
 | 
			
		||||
 | 
			
		||||
struct _MetaMonitorInfo
 | 
			
		||||
{
 | 
			
		||||
  int number;
 | 
			
		||||
  MetaRectangle rect;
 | 
			
		||||
  gboolean is_primary;
 | 
			
		||||
  gboolean in_fullscreen;
 | 
			
		||||
  XID output; /* The primary or first output for this crtc, None if no xrandr */
 | 
			
		||||
};
 | 
			
		||||
#include "monitor-private.h"
 | 
			
		||||
 | 
			
		||||
typedef void (* MetaScreenWindowFunc) (MetaScreen *screen, MetaWindow *window,
 | 
			
		||||
                                       gpointer user_data);
 | 
			
		||||
@@ -100,10 +90,11 @@ struct _MetaScreen
 | 
			
		||||
  Window wm_sn_selection_window;
 | 
			
		||||
  Atom wm_sn_atom;
 | 
			
		||||
  guint32 wm_sn_timestamp;
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  MetaMonitorInfo *monitor_infos;
 | 
			
		||||
  int primary_monitor_index;
 | 
			
		||||
  int n_monitor_infos;
 | 
			
		||||
  int primary_monitor_index;
 | 
			
		||||
  gboolean has_xinerama_indices;
 | 
			
		||||
 | 
			
		||||
  /* Cache the current monitor */
 | 
			
		||||
  int last_monitor_index;
 | 
			
		||||
@@ -231,10 +222,6 @@ void meta_screen_calc_workspace_layout (MetaScreen          *screen,
 | 
			
		||||
                                        MetaWorkspaceLayout *layout);
 | 
			
		||||
void meta_screen_free_workspace_layout (MetaWorkspaceLayout *layout);
 | 
			
		||||
 | 
			
		||||
void meta_screen_resize (MetaScreen *screen,
 | 
			
		||||
                         int         width,
 | 
			
		||||
                         int         height);
 | 
			
		||||
 | 
			
		||||
void     meta_screen_minimize_all_on_active_workspace_except (MetaScreen *screen,
 | 
			
		||||
                                                              MetaWindow *keep);
 | 
			
		||||
 | 
			
		||||
@@ -257,4 +244,9 @@ void     meta_screen_workspace_switched (MetaScreen         *screen,
 | 
			
		||||
 | 
			
		||||
void meta_screen_set_active_workspace_hint (MetaScreen *screen);
 | 
			
		||||
 | 
			
		||||
int meta_screen_xinerama_index_to_monitor_index (MetaScreen *screen,
 | 
			
		||||
                                                 int         index);
 | 
			
		||||
int meta_screen_monitor_index_to_xinerama_index (MetaScreen *screen,
 | 
			
		||||
                                                 int         index);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -48,10 +48,6 @@
 | 
			
		||||
 | 
			
		||||
#include <X11/extensions/Xinerama.h>
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_RANDR
 | 
			
		||||
#include <X11/extensions/Xrandr.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <X11/Xatom.h>
 | 
			
		||||
#include <locale.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
@@ -76,6 +72,9 @@ static void meta_screen_sn_event   (SnMonitorEvent *event,
 | 
			
		||||
                                    void           *user_data);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void on_monitors_changed (MetaMonitorManager *manager,
 | 
			
		||||
                                 MetaScreen         *screen);
 | 
			
		||||
 | 
			
		||||
enum
 | 
			
		||||
{
 | 
			
		||||
  PROP_N_WORKSPACES = 1,
 | 
			
		||||
@@ -350,250 +349,93 @@ set_wm_icon_size_hint (MetaScreen *screen)
 | 
			
		||||
#undef N_VALS
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* The list of monitors reported by the windowing system might include
 | 
			
		||||
 * mirrored monitors with identical bounds. Since mirrored monitors
 | 
			
		||||
 * shouldn't be treated as separate monitors for most purposes, we
 | 
			
		||||
 * filter them out here. (We ignore the possibility of partially
 | 
			
		||||
 * overlapping monitors because they are rare and it's hard to come
 | 
			
		||||
 * up with any sensible interpretation.)
 | 
			
		||||
 */
 | 
			
		||||
static void
 | 
			
		||||
filter_mirrored_monitors (MetaScreen *screen)
 | 
			
		||||
meta_screen_ensure_xinerama_indices (MetaScreen *screen)
 | 
			
		||||
{
 | 
			
		||||
  int i, j;
 | 
			
		||||
  XineramaScreenInfo *infos;
 | 
			
		||||
  int n_infos, i, j;
 | 
			
		||||
 | 
			
		||||
  /* Currently always true and simplifies things */
 | 
			
		||||
  g_assert (screen->primary_monitor_index == 0);
 | 
			
		||||
  if (screen->has_xinerama_indices)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  for (i = 1; i < screen->n_monitor_infos; i++)
 | 
			
		||||
  screen->has_xinerama_indices = TRUE;
 | 
			
		||||
 | 
			
		||||
  if (!XineramaIsActive (screen->display->xdisplay))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  infos = XineramaQueryScreens (screen->display->xdisplay, &n_infos);
 | 
			
		||||
  if (n_infos <= 0 || infos == NULL)
 | 
			
		||||
    {
 | 
			
		||||
      /* In case we've filtered previous monitors */
 | 
			
		||||
      screen->monitor_infos[i].number = i;
 | 
			
		||||
      meta_XFree (infos);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
      for (j = 0; j < i; j++)
 | 
			
		||||
  for (i = 0; i < screen->n_monitor_infos; ++i)
 | 
			
		||||
    {
 | 
			
		||||
      for (j = 0; j < n_infos; ++j)
 | 
			
		||||
        {
 | 
			
		||||
          if (meta_rectangle_equal (&screen->monitor_infos[i].rect,
 | 
			
		||||
                                    &screen->monitor_infos[j].rect))
 | 
			
		||||
            {
 | 
			
		||||
              memmove (&screen->monitor_infos[i],
 | 
			
		||||
                       &screen->monitor_infos[i + 1],
 | 
			
		||||
                       (screen->n_monitor_infos - i - 1) * sizeof (MetaMonitorInfo));
 | 
			
		||||
              screen->n_monitor_infos--;
 | 
			
		||||
              i--;
 | 
			
		||||
 | 
			
		||||
              continue;
 | 
			
		||||
            }
 | 
			
		||||
          if (screen->monitor_infos[i].rect.x == infos[j].x_org &&
 | 
			
		||||
	      screen->monitor_infos[i].rect.y == infos[j].y_org &&
 | 
			
		||||
	      screen->monitor_infos[i].rect.width == infos[j].width &&
 | 
			
		||||
	      screen->monitor_infos[i].rect.height == infos[j].height)
 | 
			
		||||
            screen->monitor_infos[i].xinerama_index = j;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_XFree (infos);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_RANDR
 | 
			
		||||
static MetaMonitorInfo *
 | 
			
		||||
find_monitor_with_rect (MetaScreen *screen, int x, int y, int w, int h)
 | 
			
		||||
int
 | 
			
		||||
meta_screen_monitor_index_to_xinerama_index (MetaScreen *screen,
 | 
			
		||||
                                             int         index)
 | 
			
		||||
{
 | 
			
		||||
  meta_screen_ensure_xinerama_indices (screen);
 | 
			
		||||
 | 
			
		||||
  return screen->monitor_infos[index].xinerama_index;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
meta_screen_xinerama_index_to_monitor_index (MetaScreen *screen,
 | 
			
		||||
                                             int         index)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitorInfo *info;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  meta_screen_ensure_xinerama_indices (screen);
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < screen->n_monitor_infos; i++)
 | 
			
		||||
    {
 | 
			
		||||
      info = &screen->monitor_infos[i];
 | 
			
		||||
      if (x == info->rect.x &&
 | 
			
		||||
          y == info->rect.y &&
 | 
			
		||||
          w == info->rect.width &&
 | 
			
		||||
          h == info->rect.height)
 | 
			
		||||
        return info;
 | 
			
		||||
    }
 | 
			
		||||
  return NULL;
 | 
			
		||||
    if (screen->monitor_infos[i].xinerama_index == index)
 | 
			
		||||
      return i;
 | 
			
		||||
 | 
			
		||||
  return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* In the case of multiple outputs of a single crtc (mirroring), we consider one of the
 | 
			
		||||
 * outputs the "main". This is the one we consider "owning" the windows, so if
 | 
			
		||||
 * the mirroring is changed to a dual monitor setup then the windows are moved to the
 | 
			
		||||
 * crtc that now has that main output. If one of the outputs is the primary that is
 | 
			
		||||
 * always the main, otherwise we just use the first.
 | 
			
		||||
 */
 | 
			
		||||
static XID
 | 
			
		||||
find_main_output_for_crtc (MetaScreen *screen, XRRScreenResources *resources, XRRCrtcInfo *crtc)
 | 
			
		||||
{
 | 
			
		||||
  XRROutputInfo *output;
 | 
			
		||||
  RROutput primary_output;
 | 
			
		||||
  int i;
 | 
			
		||||
  XID res;
 | 
			
		||||
 | 
			
		||||
  primary_output = XRRGetOutputPrimary (screen->display->xdisplay, screen->xroot);
 | 
			
		||||
 | 
			
		||||
  res = None;
 | 
			
		||||
  for (i = 0; i < crtc->noutput; i++)
 | 
			
		||||
    {
 | 
			
		||||
      output = XRRGetOutputInfo (screen->display->xdisplay, resources, crtc->outputs[i]);
 | 
			
		||||
      if (output->connection != RR_Disconnected &&
 | 
			
		||||
          (res == None || crtc->outputs[i] == primary_output))
 | 
			
		||||
        res = crtc->outputs[i];
 | 
			
		||||
      XRRFreeOutputInfo (output);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
reload_monitor_infos (MetaScreen *screen)
 | 
			
		||||
{
 | 
			
		||||
  MetaDisplay *display;
 | 
			
		||||
  GList *tmp;
 | 
			
		||||
  MetaMonitorManager *manager;
 | 
			
		||||
 | 
			
		||||
  {
 | 
			
		||||
    GList *tmp;
 | 
			
		||||
  tmp = screen->workspaces;
 | 
			
		||||
  while (tmp != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      MetaWorkspace *space = tmp->data;
 | 
			
		||||
 | 
			
		||||
    tmp = screen->workspaces;
 | 
			
		||||
    while (tmp != NULL)
 | 
			
		||||
      {
 | 
			
		||||
        MetaWorkspace *space = tmp->data;
 | 
			
		||||
      meta_workspace_invalidate_work_area (space);
 | 
			
		||||
      
 | 
			
		||||
      tmp = tmp->next;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        meta_workspace_invalidate_work_area (space);
 | 
			
		||||
        
 | 
			
		||||
        tmp = tmp->next;
 | 
			
		||||
      }
 | 
			
		||||
  }
 | 
			
		||||
  /* Any previous screen->monitor_infos or screen->outputs is freed by the caller */
 | 
			
		||||
 | 
			
		||||
  display = screen->display;
 | 
			
		||||
 | 
			
		||||
  /* Any previous screen->monitor_infos is freed by the caller */
 | 
			
		||||
 | 
			
		||||
  screen->monitor_infos = NULL;
 | 
			
		||||
  screen->n_monitor_infos = 0;
 | 
			
		||||
  screen->last_monitor_index = 0;
 | 
			
		||||
 | 
			
		||||
  /* Xinerama doesn't have a concept of primary monitor, however XRandR
 | 
			
		||||
   * does. However, the XRandR xinerama compat code always sorts the
 | 
			
		||||
   * primary output first, so we rely on that here. We could use the
 | 
			
		||||
   * native XRandR calls instead of xinerama, but that would be
 | 
			
		||||
   * slightly problematic for _NET_WM_FULLSCREEN_MONITORS support, as
 | 
			
		||||
   * that is defined in terms of xinerama monitor indexes.
 | 
			
		||||
   * So, since we don't need anything in xrandr except the primary
 | 
			
		||||
   * we can keep using xinerama and use the first monitor as the
 | 
			
		||||
   * primary.
 | 
			
		||||
   */
 | 
			
		||||
  screen->primary_monitor_index = 0;
 | 
			
		||||
 | 
			
		||||
  screen->has_xinerama_indices = FALSE;
 | 
			
		||||
  screen->display->monitor_cache_invalidated = TRUE;
 | 
			
		||||
 | 
			
		||||
  if (g_getenv ("MUTTER_DEBUG_XINERAMA"))
 | 
			
		||||
    {
 | 
			
		||||
      meta_topic (META_DEBUG_XINERAMA,
 | 
			
		||||
                  "Pretending a single monitor has two Xinerama screens\n");
 | 
			
		||||
  manager = meta_monitor_manager_get ();
 | 
			
		||||
 | 
			
		||||
      screen->monitor_infos = g_new0 (MetaMonitorInfo, 2);
 | 
			
		||||
      screen->n_monitor_infos = 2;
 | 
			
		||||
 | 
			
		||||
      screen->monitor_infos[0].number = 0;
 | 
			
		||||
      screen->monitor_infos[0].rect = screen->rect;
 | 
			
		||||
      screen->monitor_infos[0].rect.width = screen->rect.width / 2;
 | 
			
		||||
      screen->monitor_infos[0].in_fullscreen = -1;
 | 
			
		||||
 | 
			
		||||
      screen->monitor_infos[1].number = 1;
 | 
			
		||||
      screen->monitor_infos[1].rect = screen->rect;
 | 
			
		||||
      screen->monitor_infos[1].rect.x = screen->rect.width / 2;
 | 
			
		||||
      screen->monitor_infos[1].rect.width = screen->rect.width / 2;
 | 
			
		||||
      screen->monitor_infos[0].in_fullscreen = -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (screen->n_monitor_infos == 0 &&
 | 
			
		||||
      XineramaIsActive (display->xdisplay))
 | 
			
		||||
    {
 | 
			
		||||
      XineramaScreenInfo *infos;
 | 
			
		||||
      int n_infos;
 | 
			
		||||
      int i;
 | 
			
		||||
      
 | 
			
		||||
      n_infos = 0;
 | 
			
		||||
      infos = XineramaQueryScreens (display->xdisplay, &n_infos);
 | 
			
		||||
 | 
			
		||||
      meta_topic (META_DEBUG_XINERAMA,
 | 
			
		||||
                  "Found %d Xinerama screens on display %s\n",
 | 
			
		||||
                  n_infos, display->name);
 | 
			
		||||
 | 
			
		||||
      if (n_infos > 0)
 | 
			
		||||
        {
 | 
			
		||||
          screen->monitor_infos = g_new0 (MetaMonitorInfo, n_infos);
 | 
			
		||||
          screen->n_monitor_infos = n_infos;
 | 
			
		||||
          
 | 
			
		||||
          i = 0;
 | 
			
		||||
          while (i < n_infos)
 | 
			
		||||
            {
 | 
			
		||||
              screen->monitor_infos[i].number = infos[i].screen_number;
 | 
			
		||||
              screen->monitor_infos[i].rect.x = infos[i].x_org;
 | 
			
		||||
              screen->monitor_infos[i].rect.y = infos[i].y_org;
 | 
			
		||||
              screen->monitor_infos[i].rect.width = infos[i].width;
 | 
			
		||||
              screen->monitor_infos[i].rect.height = infos[i].height;
 | 
			
		||||
              screen->monitor_infos[i].in_fullscreen = -1;
 | 
			
		||||
 | 
			
		||||
              meta_topic (META_DEBUG_XINERAMA,
 | 
			
		||||
                          "Monitor %d is %d,%d %d x %d\n",
 | 
			
		||||
                          screen->monitor_infos[i].number,
 | 
			
		||||
                          screen->monitor_infos[i].rect.x,
 | 
			
		||||
                          screen->monitor_infos[i].rect.y,
 | 
			
		||||
                          screen->monitor_infos[i].rect.width,
 | 
			
		||||
                          screen->monitor_infos[i].rect.height);
 | 
			
		||||
              
 | 
			
		||||
              ++i;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
      
 | 
			
		||||
      meta_XFree (infos);
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_RANDR
 | 
			
		||||
      {
 | 
			
		||||
        XRRScreenResources *resources;
 | 
			
		||||
 | 
			
		||||
        resources = XRRGetScreenResourcesCurrent (display->xdisplay, screen->xroot);
 | 
			
		||||
        if (resources)
 | 
			
		||||
          {
 | 
			
		||||
            for (i = 0; i < resources->ncrtc; i++)
 | 
			
		||||
              {
 | 
			
		||||
                XRRCrtcInfo *crtc;
 | 
			
		||||
                MetaMonitorInfo *info;
 | 
			
		||||
 | 
			
		||||
                crtc = XRRGetCrtcInfo (display->xdisplay, resources, resources->crtcs[i]);
 | 
			
		||||
                info = find_monitor_with_rect (screen, crtc->x, crtc->y, (int)crtc->width, (int)crtc->height);
 | 
			
		||||
                if (info)
 | 
			
		||||
                  info->output = find_main_output_for_crtc (screen, resources, crtc);
 | 
			
		||||
 | 
			
		||||
                XRRFreeCrtcInfo (crtc);
 | 
			
		||||
              }
 | 
			
		||||
            XRRFreeScreenResources (resources);
 | 
			
		||||
          }
 | 
			
		||||
      }
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
  else if (screen->n_monitor_infos > 0)
 | 
			
		||||
    {
 | 
			
		||||
      meta_topic (META_DEBUG_XINERAMA,
 | 
			
		||||
                  "No Xinerama extension or Xinerama inactive on display %s\n",
 | 
			
		||||
                  display->name);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* If no Xinerama, fill in the single screen info so
 | 
			
		||||
   * we can use the field unconditionally
 | 
			
		||||
   */
 | 
			
		||||
  if (screen->n_monitor_infos == 0)
 | 
			
		||||
    {
 | 
			
		||||
      meta_topic (META_DEBUG_XINERAMA,
 | 
			
		||||
                  "No Xinerama screens, using default screen info\n");
 | 
			
		||||
          
 | 
			
		||||
      screen->monitor_infos = g_new0 (MetaMonitorInfo, 1);
 | 
			
		||||
      screen->n_monitor_infos = 1;
 | 
			
		||||
          
 | 
			
		||||
      screen->monitor_infos[0].number = 0;
 | 
			
		||||
      screen->monitor_infos[0].rect = screen->rect;
 | 
			
		||||
      screen->monitor_infos[0].in_fullscreen = -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  filter_mirrored_monitors (screen);
 | 
			
		||||
 | 
			
		||||
  screen->monitor_infos[screen->primary_monitor_index].is_primary = TRUE;
 | 
			
		||||
 | 
			
		||||
  g_assert (screen->n_monitor_infos > 0);
 | 
			
		||||
  g_assert (screen->monitor_infos != NULL);
 | 
			
		||||
  screen->monitor_infos = meta_monitor_manager_get_monitor_infos (manager,
 | 
			
		||||
                                                                  (unsigned*)&screen->n_monitor_infos);
 | 
			
		||||
  screen->primary_monitor_index = meta_monitor_manager_get_primary_index (manager);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* The guard window allows us to leave minimized windows mapped so
 | 
			
		||||
@@ -668,6 +510,7 @@ meta_screen_new (MetaDisplay *display,
 | 
			
		||||
  char buf[128];
 | 
			
		||||
  guint32 manager_timestamp;
 | 
			
		||||
  gulong current_workspace;
 | 
			
		||||
  MetaMonitorManager *manager;
 | 
			
		||||
  
 | 
			
		||||
  replace_current_wm = meta_get_replace_current_wm ();
 | 
			
		||||
  
 | 
			
		||||
@@ -826,8 +669,17 @@ meta_screen_new (MetaDisplay *display,
 | 
			
		||||
  screen->xscreen = ScreenOfDisplay (xdisplay, number);
 | 
			
		||||
  screen->xroot = xroot;
 | 
			
		||||
  screen->rect.x = screen->rect.y = 0;
 | 
			
		||||
  screen->rect.width = WidthOfScreen (screen->xscreen);
 | 
			
		||||
  screen->rect.height = HeightOfScreen (screen->xscreen);
 | 
			
		||||
  
 | 
			
		||||
  meta_monitor_manager_initialize ();
 | 
			
		||||
 | 
			
		||||
  manager = meta_monitor_manager_get ();
 | 
			
		||||
  g_signal_connect (manager, "monitors-changed",
 | 
			
		||||
                    G_CALLBACK (on_monitors_changed), screen);
 | 
			
		||||
 | 
			
		||||
  meta_monitor_manager_get_screen_size (manager,
 | 
			
		||||
                                        &screen->rect.width,
 | 
			
		||||
                                        &screen->rect.height);
 | 
			
		||||
 | 
			
		||||
  screen->current_cursor = -1; /* invalid/unset */
 | 
			
		||||
  screen->default_xvisual = DefaultVisualOfScreen (screen->xscreen);
 | 
			
		||||
  screen->default_depth = DefaultDepthOfScreen (screen->xscreen);
 | 
			
		||||
@@ -852,10 +704,6 @@ meta_screen_new (MetaDisplay *display,
 | 
			
		||||
  screen->compositor_data = NULL;
 | 
			
		||||
  screen->guard_window = None;
 | 
			
		||||
 | 
			
		||||
  screen->monitor_infos = NULL;
 | 
			
		||||
  screen->n_monitor_infos = 0;
 | 
			
		||||
  screen->last_monitor_index = 0;  
 | 
			
		||||
  
 | 
			
		||||
  reload_monitor_infos (screen);
 | 
			
		||||
  
 | 
			
		||||
  meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
 | 
			
		||||
@@ -941,7 +789,7 @@ meta_screen_new (MetaDisplay *display,
 | 
			
		||||
 | 
			
		||||
  meta_verbose ("Added screen %d ('%s') root 0x%lx\n",
 | 
			
		||||
                screen->number, screen->screen_name, screen->xroot);
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  return screen;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -2997,19 +2845,15 @@ meta_screen_resize_func (MetaScreen *screen,
 | 
			
		||||
  meta_window_recalc_features (window);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_screen_resize (MetaScreen *screen,
 | 
			
		||||
                    int         width,
 | 
			
		||||
                    int         height)
 | 
			
		||||
static void
 | 
			
		||||
on_monitors_changed (MetaMonitorManager *manager,
 | 
			
		||||
                     MetaScreen         *screen)
 | 
			
		||||
{
 | 
			
		||||
  GSList *windows, *tmp;
 | 
			
		||||
  MetaMonitorInfo *old_monitor_infos;
 | 
			
		||||
  GSList *tmp, *windows;
 | 
			
		||||
 | 
			
		||||
  screen->rect.width = width;
 | 
			
		||||
  screen->rect.height = height;
 | 
			
		||||
 | 
			
		||||
  /* Save the old monitor infos, so they stay valid during the update */
 | 
			
		||||
  old_monitor_infos = screen->monitor_infos;
 | 
			
		||||
  meta_monitor_manager_get_screen_size (manager,
 | 
			
		||||
                                        &screen->rect.width,
 | 
			
		||||
                                        &screen->rect.height);
 | 
			
		||||
 | 
			
		||||
  reload_monitor_infos (screen);
 | 
			
		||||
  set_desktop_geometry_hint (screen);
 | 
			
		||||
@@ -3021,8 +2865,8 @@ meta_screen_resize (MetaScreen *screen,
 | 
			
		||||
 | 
			
		||||
      changes.x = 0;
 | 
			
		||||
      changes.y = 0;
 | 
			
		||||
      changes.width = width;
 | 
			
		||||
      changes.height = height;
 | 
			
		||||
      changes.width = screen->rect.width;
 | 
			
		||||
      changes.height = screen->rect.height;
 | 
			
		||||
 | 
			
		||||
      XConfigureWindow(screen->display->xdisplay,
 | 
			
		||||
                       screen->guard_window,
 | 
			
		||||
@@ -3032,7 +2876,8 @@ meta_screen_resize (MetaScreen *screen,
 | 
			
		||||
 | 
			
		||||
  if (screen->display->compositor)
 | 
			
		||||
    meta_compositor_sync_screen_size (screen->display->compositor,
 | 
			
		||||
				      screen, width, height);
 | 
			
		||||
				      screen,
 | 
			
		||||
                                      screen->rect.width, screen->rect.height);
 | 
			
		||||
 | 
			
		||||
  /* Queue a resize on all the windows */
 | 
			
		||||
  meta_screen_foreach_window (screen, meta_screen_resize_func, 0);
 | 
			
		||||
@@ -3048,7 +2893,6 @@ meta_screen_resize (MetaScreen *screen,
 | 
			
		||||
        meta_window_update_for_monitors_changed (window);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_free (old_monitor_infos);
 | 
			
		||||
  g_slist_free (windows);
 | 
			
		||||
 | 
			
		||||
  meta_screen_queue_check_fullscreen (screen);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										133
									
								
								src/core/util.c
									
									
									
									
									
								
							
							
						
						
									
										133
									
								
								src/core/util.c
									
									
									
									
									
								
							@@ -332,6 +332,8 @@ topic_name (MetaDebugTopic topic)
 | 
			
		||||
      return "COMPOSITOR";
 | 
			
		||||
    case META_DEBUG_EDGE_RESISTANCE:
 | 
			
		||||
      return "EDGE_RESISTANCE";
 | 
			
		||||
    case META_DEBUG_DBUS:
 | 
			
		||||
      return "DBUS";
 | 
			
		||||
    case META_DEBUG_VERBOSE:
 | 
			
		||||
      return "VERBOSE";
 | 
			
		||||
    }
 | 
			
		||||
@@ -389,91 +391,100 @@ meta_topic_real (MetaDebugTopic topic,
 | 
			
		||||
}
 | 
			
		||||
#endif /* WITH_VERBOSE_MODE */
 | 
			
		||||
 | 
			
		||||
#ifdef WITH_VERBOSE_MODE
 | 
			
		||||
static void
 | 
			
		||||
logfile_log_handler (const gchar *log_domain,
 | 
			
		||||
                     GLogLevelFlags log_level,
 | 
			
		||||
                     const gchar *message,
 | 
			
		||||
                     gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
  switch (log_level & G_LOG_LEVEL_MASK) {
 | 
			
		||||
  case G_LOG_LEVEL_ERROR:
 | 
			
		||||
    utf8_fputs ("ERROR: ", logfile);
 | 
			
		||||
    break;
 | 
			
		||||
 | 
			
		||||
  case G_LOG_LEVEL_CRITICAL:
 | 
			
		||||
    utf8_fputs ("CRITICAL: ", logfile);
 | 
			
		||||
    break;
 | 
			
		||||
 | 
			
		||||
  case G_LOG_LEVEL_WARNING:
 | 
			
		||||
    utf8_fputs ("WARNING: ", logfile);
 | 
			
		||||
    break;
 | 
			
		||||
 | 
			
		||||
  default:
 | 
			
		||||
    /* the other levels don't go through
 | 
			
		||||
       g_log, they go directly to the log file */
 | 
			
		||||
    ;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  utf8_fputs (message, logfile);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_debug_init (void)
 | 
			
		||||
{
 | 
			
		||||
  ensure_logfile ();
 | 
			
		||||
 | 
			
		||||
  if (logfile)
 | 
			
		||||
    g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MASK,
 | 
			
		||||
                       logfile_log_handler, NULL);
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
void
 | 
			
		||||
meta_debug_init (void)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_bug (const char *format, ...)
 | 
			
		||||
{
 | 
			
		||||
  char *stripped;
 | 
			
		||||
  va_list args;
 | 
			
		||||
  gchar *str;
 | 
			
		||||
  FILE *out;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (format != NULL);
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  stripped = g_strstrip (g_strdup (format));
 | 
			
		||||
 | 
			
		||||
  va_start (args, format);
 | 
			
		||||
  str = g_strdup_vprintf (format, args);
 | 
			
		||||
  g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, stripped, args);
 | 
			
		||||
  va_end (args);
 | 
			
		||||
 | 
			
		||||
#ifdef WITH_VERBOSE_MODE
 | 
			
		||||
  out = logfile ? logfile : stderr;
 | 
			
		||||
#else
 | 
			
		||||
  out = stderr;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  if (no_prefix == 0)
 | 
			
		||||
    utf8_fputs (_("Bug in window manager: "), out);
 | 
			
		||||
  utf8_fputs (str, out);
 | 
			
		||||
 | 
			
		||||
  fflush (out);
 | 
			
		||||
  
 | 
			
		||||
  g_free (str);
 | 
			
		||||
  
 | 
			
		||||
  /* stop us in a debugger */
 | 
			
		||||
  abort ();
 | 
			
		||||
  g_free (stripped);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_warning (const char *format, ...)
 | 
			
		||||
{
 | 
			
		||||
  char *stripped;
 | 
			
		||||
  va_list args;
 | 
			
		||||
  gchar *str;
 | 
			
		||||
  FILE *out;
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (format != NULL);
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  stripped = g_strstrip (g_strdup (format));
 | 
			
		||||
 | 
			
		||||
  va_start (args, format);
 | 
			
		||||
  str = g_strdup_vprintf (format, args);
 | 
			
		||||
  g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, stripped, args);
 | 
			
		||||
  va_end (args);
 | 
			
		||||
 | 
			
		||||
#ifdef WITH_VERBOSE_MODE
 | 
			
		||||
  out = logfile ? logfile : stderr;
 | 
			
		||||
#else
 | 
			
		||||
  out = stderr;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  if (no_prefix == 0)
 | 
			
		||||
    utf8_fputs (_("Window manager warning: "), out);
 | 
			
		||||
  utf8_fputs (str, out);
 | 
			
		||||
 | 
			
		||||
  fflush (out);
 | 
			
		||||
  
 | 
			
		||||
  g_free (str);
 | 
			
		||||
  g_free (stripped);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_fatal (const char *format, ...)
 | 
			
		||||
{
 | 
			
		||||
  char *stripped;
 | 
			
		||||
  va_list args;
 | 
			
		||||
  gchar *str;
 | 
			
		||||
  FILE *out;
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (format != NULL);
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  stripped = g_strstrip (g_strdup (format));
 | 
			
		||||
 | 
			
		||||
  va_start (args, format);
 | 
			
		||||
  str = g_strdup_vprintf (format, args);
 | 
			
		||||
  g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, stripped, args);
 | 
			
		||||
  va_end (args);
 | 
			
		||||
 | 
			
		||||
#ifdef WITH_VERBOSE_MODE
 | 
			
		||||
  out = logfile ? logfile : stderr;
 | 
			
		||||
#else
 | 
			
		||||
  out = stderr;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  if (no_prefix == 0)
 | 
			
		||||
    utf8_fputs (_("Window manager error: "), out);
 | 
			
		||||
  utf8_fputs (str, out);
 | 
			
		||||
 | 
			
		||||
  fflush (out);
 | 
			
		||||
  
 | 
			
		||||
  g_free (str);
 | 
			
		||||
  g_free (stripped);
 | 
			
		||||
 | 
			
		||||
  meta_exit (META_EXIT_ERROR);
 | 
			
		||||
}
 | 
			
		||||
@@ -495,7 +506,6 @@ meta_pop_no_msg_prefix (void)
 | 
			
		||||
void
 | 
			
		||||
meta_exit (MetaExitCode code)
 | 
			
		||||
{
 | 
			
		||||
  
 | 
			
		||||
  exit (code);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -637,8 +647,13 @@ meta_show_dialog (const char *type,
 | 
			
		||||
 | 
			
		||||
  append_argument (args, "zenity");
 | 
			
		||||
  append_argument (args, type);
 | 
			
		||||
  append_argument (args, "--display");
 | 
			
		||||
  append_argument (args, display);
 | 
			
		||||
 | 
			
		||||
  if (display)
 | 
			
		||||
    {
 | 
			
		||||
      append_argument (args, "--display");
 | 
			
		||||
      append_argument (args, display);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  append_argument (args, "--class");
 | 
			
		||||
  append_argument (args, "mutter-dialog");
 | 
			
		||||
  append_argument (args, "--title");
 | 
			
		||||
 
 | 
			
		||||
@@ -165,7 +165,7 @@ struct _MetaWindow
 | 
			
		||||
   * been overridden (via a client message), the window will cover the union of
 | 
			
		||||
   * these monitors.  If not, this is the single monitor which the window's
 | 
			
		||||
   * origin is on. */
 | 
			
		||||
  long fullscreen_monitors[4];
 | 
			
		||||
  gint fullscreen_monitors[4];
 | 
			
		||||
  
 | 
			
		||||
  /* Whether we're trying to constrain the window to be fully onscreen */
 | 
			
		||||
  guint require_fully_onscreen : 1;
 | 
			
		||||
 
 | 
			
		||||
@@ -2108,10 +2108,14 @@ set_net_wm_state (MetaWindow *window)
 | 
			
		||||
 | 
			
		||||
  if (window->fullscreen)
 | 
			
		||||
    {
 | 
			
		||||
      data[0] = window->fullscreen_monitors[0];
 | 
			
		||||
      data[1] = window->fullscreen_monitors[1];
 | 
			
		||||
      data[2] = window->fullscreen_monitors[2];
 | 
			
		||||
      data[3] = window->fullscreen_monitors[3];
 | 
			
		||||
      data[0] = meta_screen_monitor_index_to_xinerama_index (window->screen,
 | 
			
		||||
                                                             window->fullscreen_monitors[0]);
 | 
			
		||||
      data[1] = meta_screen_monitor_index_to_xinerama_index (window->screen,
 | 
			
		||||
                                                             window->fullscreen_monitors[1]);
 | 
			
		||||
      data[2] = meta_screen_monitor_index_to_xinerama_index (window->screen,
 | 
			
		||||
                                                             window->fullscreen_monitors[2]);
 | 
			
		||||
      data[3] = meta_screen_monitor_index_to_xinerama_index (window->screen,
 | 
			
		||||
                                                             window->fullscreen_monitors[3]);
 | 
			
		||||
 | 
			
		||||
      meta_verbose ("Setting _NET_WM_FULLSCREEN_MONITORS\n");
 | 
			
		||||
      meta_error_trap_push (window->display);
 | 
			
		||||
@@ -4785,7 +4789,8 @@ meta_window_update_for_monitors_changed (MetaWindow *window)
 | 
			
		||||
    {
 | 
			
		||||
      MetaMonitorInfo *info = &window->screen->monitor_infos[i];
 | 
			
		||||
 | 
			
		||||
      if (info->output == old->output)
 | 
			
		||||
      if (info->output_id != 0 &&
 | 
			
		||||
          info->output_id == old->output_id)
 | 
			
		||||
        {
 | 
			
		||||
          new = info;
 | 
			
		||||
          break;
 | 
			
		||||
@@ -7130,10 +7135,14 @@ meta_window_client_message (MetaWindow *window,
 | 
			
		||||
      meta_verbose ("_NET_WM_FULLSCREEN_MONITORS request for window '%s'\n",
 | 
			
		||||
                    window->desc);
 | 
			
		||||
 | 
			
		||||
      top = event->xclient.data.l[0];
 | 
			
		||||
      bottom = event->xclient.data.l[1];
 | 
			
		||||
      left = event->xclient.data.l[2];
 | 
			
		||||
      right = event->xclient.data.l[3];
 | 
			
		||||
      top = meta_screen_xinerama_index_to_monitor_index (window->screen,
 | 
			
		||||
                                                         event->xclient.data.l[0]);
 | 
			
		||||
      bottom = meta_screen_xinerama_index_to_monitor_index (window->screen,
 | 
			
		||||
                                                            event->xclient.data.l[1]);
 | 
			
		||||
      left = meta_screen_xinerama_index_to_monitor_index (window->screen,
 | 
			
		||||
                                                          event->xclient.data.l[2]);
 | 
			
		||||
      right = meta_screen_xinerama_index_to_monitor_index (window->screen,
 | 
			
		||||
                                                           event->xclient.data.l[3]);
 | 
			
		||||
      /* source_indication = event->xclient.data.l[4]; */
 | 
			
		||||
 | 
			
		||||
      meta_window_update_fullscreen_monitors (window, top, bottom, left, right);
 | 
			
		||||
 
 | 
			
		||||
@@ -72,6 +72,7 @@ item(_MUTTER_TIMESTAMP_PING)
 | 
			
		||||
item(_MUTTER_FOCUS_SET)
 | 
			
		||||
item(_MUTTER_SENTINEL)
 | 
			
		||||
item(_MUTTER_VERSION)
 | 
			
		||||
item(_MUTTER_PRESENTATION_OUTPUT)
 | 
			
		||||
item(WM_CLIENT_MACHINE)
 | 
			
		||||
item(MANAGER)
 | 
			
		||||
item(TARGETS)
 | 
			
		||||
@@ -79,6 +80,7 @@ item(MULTIPLE)
 | 
			
		||||
item(TIMESTAMP)
 | 
			
		||||
item(VERSION)
 | 
			
		||||
item(ATOM_PAIR)
 | 
			
		||||
item(BACKLIGHT)
 | 
			
		||||
 | 
			
		||||
/* Oddities: These are used, and we need atoms for them,
 | 
			
		||||
 * but when we need all _NET_WM hints (i.e. when we're making
 | 
			
		||||
 
 | 
			
		||||
@@ -205,6 +205,21 @@ struct _MetaPluginClass
 | 
			
		||||
  gboolean (*keybinding_filter) (MetaPlugin     *plugin,
 | 
			
		||||
                                 MetaKeyBinding *binding);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * MetaPluginClass::confirm_display_config:
 | 
			
		||||
   * @plugin: a #MetaPlugin
 | 
			
		||||
   *
 | 
			
		||||
   * Virtual function called when the display configuration changes.
 | 
			
		||||
   * The common way to implement this function is to show some form
 | 
			
		||||
   * of modal dialog that should ask the user if everything was ok.
 | 
			
		||||
   *
 | 
			
		||||
   * When confirmed by the user, the plugin must call meta_plugin_complete_display_change()
 | 
			
		||||
   * to make the configuration permanent. If that function is not
 | 
			
		||||
   * called within the timeout, the previous configuration will be
 | 
			
		||||
   * reapplied.
 | 
			
		||||
   */
 | 
			
		||||
  void (*confirm_display_change) (MetaPlugin *plugin);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * MetaPluginClass::plugin_info:
 | 
			
		||||
   * @plugin: a #MetaPlugin
 | 
			
		||||
@@ -214,6 +229,7 @@ struct _MetaPluginClass
 | 
			
		||||
   * Returns: a #MetaPluginInfo.
 | 
			
		||||
   */
 | 
			
		||||
  const MetaPluginInfo * (*plugin_info) (MetaPlugin *plugin);
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -360,6 +376,10 @@ void
 | 
			
		||||
meta_plugin_destroy_completed (MetaPlugin      *plugin,
 | 
			
		||||
                               MetaWindowActor *actor);
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_plugin_complete_display_change (MetaPlugin *plugin,
 | 
			
		||||
                                     gboolean    ok);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * MetaModalOptions:
 | 
			
		||||
 * @META_MODAL_POINTER_ALREADY_GRABBED: if set the pointer is already
 | 
			
		||||
 
 | 
			
		||||
@@ -100,7 +100,8 @@ typedef enum
 | 
			
		||||
  META_DEBUG_RESIZING        = 1 << 18,
 | 
			
		||||
  META_DEBUG_SHAPES          = 1 << 19,
 | 
			
		||||
  META_DEBUG_COMPOSITOR      = 1 << 20,
 | 
			
		||||
  META_DEBUG_EDGE_RESISTANCE = 1 << 21
 | 
			
		||||
  META_DEBUG_EDGE_RESISTANCE = 1 << 21,
 | 
			
		||||
  META_DEBUG_DBUS            = 1 << 22
 | 
			
		||||
} MetaDebugTopic;
 | 
			
		||||
 | 
			
		||||
void meta_topic_real      (MetaDebugTopic topic,
 | 
			
		||||
@@ -109,6 +110,8 @@ void meta_topic_real      (MetaDebugTopic topic,
 | 
			
		||||
void meta_add_verbose_topic    (MetaDebugTopic topic);
 | 
			
		||||
void meta_remove_verbose_topic (MetaDebugTopic topic);
 | 
			
		||||
 | 
			
		||||
void meta_debug_init      (void);
 | 
			
		||||
 | 
			
		||||
void meta_push_no_msg_prefix (void);
 | 
			
		||||
void meta_pop_no_msg_prefix  (void);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										281
									
								
								src/xrandr.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										281
									
								
								src/xrandr.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,281 @@
 | 
			
		||||
<!DOCTYPE node PUBLIC
 | 
			
		||||
'-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'
 | 
			
		||||
'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>
 | 
			
		||||
<node>
 | 
			
		||||
  <!--
 | 
			
		||||
      org.gnome.Mutter.DisplayConfig:
 | 
			
		||||
      @short_description: display configuration interface
 | 
			
		||||
 | 
			
		||||
      This interface is used by mutter and gnome-settings-daemon
 | 
			
		||||
      to apply multiple monitor configuration.
 | 
			
		||||
  -->
 | 
			
		||||
 | 
			
		||||
  <interface name="org.gnome.Mutter.DisplayConfig">
 | 
			
		||||
 | 
			
		||||
    <!--
 | 
			
		||||
        GetResources:
 | 
			
		||||
	@serial: configuration serial
 | 
			
		||||
	@crtcs: available CRTCs
 | 
			
		||||
	@outputs: available outputs
 | 
			
		||||
	@modes: available modes
 | 
			
		||||
	@max_screen_width:
 | 
			
		||||
	@max_screen_height:
 | 
			
		||||
 | 
			
		||||
        Retrieves the current layout of the hardware.
 | 
			
		||||
 | 
			
		||||
        @serial is an unique identifier representing the current state
 | 
			
		||||
        of the screen. It must be passed back to ApplyConfiguration()
 | 
			
		||||
	and will be increased for every configuration change (so that
 | 
			
		||||
	mutter can detect that the new configuration is based on old
 | 
			
		||||
	state).
 | 
			
		||||
 | 
			
		||||
	A CRTC (CRT controller) is a logical monitor, ie a portion
 | 
			
		||||
	of the compositor coordinate space. It might correspond
 | 
			
		||||
	to multiple monitors, when in clone mode, but not that
 | 
			
		||||
	it is possible to implement clone mode also by setting different
 | 
			
		||||
	CRTCs to the same coordinates.
 | 
			
		||||
 | 
			
		||||
	The number of CRTCs represent the maximum number of monitors
 | 
			
		||||
	that can be set to expand and it is a HW constraint; if more
 | 
			
		||||
	monitors are connected,	then necessarily some will clone. This
 | 
			
		||||
	is complementary to the concept of the encoder (not exposed in
 | 
			
		||||
	the API), which groups outputs that necessarily will show the
 | 
			
		||||
	same image (again a HW constraint).
 | 
			
		||||
 | 
			
		||||
	A CRTC is represented by a DBus structure with the following
 | 
			
		||||
	layout:
 | 
			
		||||
	* u ID: the ID in the API of this CRTC
 | 
			
		||||
	* x winsys_id: the low-level ID of this CRTC (which might
 | 
			
		||||
	               be a XID, a KMS handle or something entirely
 | 
			
		||||
		       different)
 | 
			
		||||
	* i x, y, width, height: the geometry of this CRTC
 | 
			
		||||
	                         (might be invalid if the CRTC is not in
 | 
			
		||||
				 use)
 | 
			
		||||
	* i current_mode: the current mode of the CRTC, or -1 if this
 | 
			
		||||
	                  CRTC is not used
 | 
			
		||||
			  Note: the size of the mode will always correspond
 | 
			
		||||
			  to the width and height of the CRTC
 | 
			
		||||
	* u current_transform: the current transform (espressed according
 | 
			
		||||
	                       to the wayland protocol)
 | 
			
		||||
	* au transforms: all possible transforms
 | 
			
		||||
	* a{sv} properties: other high-level properties that affect this
 | 
			
		||||
	                    CRTC; they are not necessarily reflected in
 | 
			
		||||
			    the hardware.
 | 
			
		||||
			    No property is specified in this version of the API.
 | 
			
		||||
 | 
			
		||||
        Note: all geometry information refers to the untransformed
 | 
			
		||||
	display.
 | 
			
		||||
 | 
			
		||||
	An output represents a physical screen, connected somewhere to
 | 
			
		||||
	the computer. Floating connectors are not exposed in the API.
 | 
			
		||||
	An output is a DBus struct with the following fields:
 | 
			
		||||
	* u ID: the ID in the API
 | 
			
		||||
	* x winsys_id: the low-level ID of this output (XID or KMS handle)
 | 
			
		||||
	* i current_crtc: the CRTC that is currently driving this output,
 | 
			
		||||
	                  or -1 if the output is disabled
 | 
			
		||||
	* au possible_crtcs: all CRTCs that can control this output
 | 
			
		||||
	* s name: the name of the connector to which the output is attached
 | 
			
		||||
	          (like VGA1 or HDMI)
 | 
			
		||||
	* au modes: valid modes for this output
 | 
			
		||||
	* au clones: valid clones for this output, ie other outputs that
 | 
			
		||||
	             can be assigned the same CRTC as this one; if you
 | 
			
		||||
	             want to mirror two outputs that don't have each other
 | 
			
		||||
	             in the clone list, you must configure two different
 | 
			
		||||
	             CRTCs for the same geometry
 | 
			
		||||
	* a{sv} properties: other high-level properties that affect this
 | 
			
		||||
	                    output; they are not necessarily reflected in
 | 
			
		||||
			    the hardware.
 | 
			
		||||
			    Known properties:
 | 
			
		||||
                            - "vendor" (s): (readonly) the human readable name
 | 
			
		||||
                                            of the manufacturer
 | 
			
		||||
                            - "product" (s): (readonly) the human readable name
 | 
			
		||||
                                             of the display model
 | 
			
		||||
                            - "serial" (s): (readonly) the serial number of this
 | 
			
		||||
                                            particular hardware part
 | 
			
		||||
			    - "display-name" (s): (readonly) a human readable name
 | 
			
		||||
			                          of this output, to be shown in the UI
 | 
			
		||||
	                    - "backlight" (i): (readonly, use the specific interface)
 | 
			
		||||
                                               the backlight value as a percentage
 | 
			
		||||
                                               (-1 if not supported)
 | 
			
		||||
			    - "primary" (b): whether this output is primary
 | 
			
		||||
			                     or not
 | 
			
		||||
			    - "presentation" (b): whether this output is
 | 
			
		||||
			                          for presentation only
 | 
			
		||||
			    Note: properties might be ignored if not consistenly
 | 
			
		||||
			    applied to all outputs in the same clone group. In
 | 
			
		||||
			    general, it's expected that presentation or primary
 | 
			
		||||
			    outputs will not be cloned.
 | 
			
		||||
 | 
			
		||||
        A mode represents a set of parameters that are applied to
 | 
			
		||||
	each output, such as resolution and refresh rate. It is a separate
 | 
			
		||||
	object so that it can be referenced by CRTCs and outputs.
 | 
			
		||||
	Multiple outputs in the same CRTCs must all have the same mode.
 | 
			
		||||
	A mode is exposed as:
 | 
			
		||||
	* u ID: the ID in the API
 | 
			
		||||
	* x winsys_id: the low-level ID of this mode
 | 
			
		||||
	* u width, height: the resolution
 | 
			
		||||
	* d frequency: refresh rate
 | 
			
		||||
 | 
			
		||||
        Output and modes are read-only objects (except for output properties),
 | 
			
		||||
	they can change only in accordance to HW changes (such as hotplugging
 | 
			
		||||
	a monitor), while CRTCs can be changed with ApplyConfiguration().
 | 
			
		||||
 | 
			
		||||
        XXX: actually, if you insist enough, you can add new modes
 | 
			
		||||
	through xrandr command line or the KMS API, overriding what the
 | 
			
		||||
	kernel driver and the EDID say.
 | 
			
		||||
	Usually, it only matters with old cards with broken drivers, or
 | 
			
		||||
	old monitors with broken EDIDs, but it happens more often with
 | 
			
		||||
	projectors (if for example the kernel driver doesn't add the
 | 
			
		||||
	640x480 - 800x600 - 1024x768 default modes). Probably something
 | 
			
		||||
	that we need to handle in mutter anyway.
 | 
			
		||||
    -->
 | 
			
		||||
    <method name="GetResources">
 | 
			
		||||
      <arg name="serial" direction="out" type="u" />
 | 
			
		||||
      <arg name="crtcs" direction="out" type="a(uxiiiiiuaua{sv})" />
 | 
			
		||||
      <arg name="outputs" direction="out" type="a(uxiausauaua{sv})" />
 | 
			
		||||
      <arg name="modes" direction="out" type="a(uxuud)" />
 | 
			
		||||
      <arg name="max_screen_width" direction="out" type="i" />
 | 
			
		||||
      <arg name="max_screen_height" direction="out" type="i" />
 | 
			
		||||
    </method>
 | 
			
		||||
 | 
			
		||||
    <!--
 | 
			
		||||
        ApplyConfiguration:
 | 
			
		||||
	@serial: configuration serial
 | 
			
		||||
	@persistent: whether this configuration should be saved on disk
 | 
			
		||||
	@crtcs: new data for CRTCs
 | 
			
		||||
	@outputs: new data for outputs
 | 
			
		||||
 | 
			
		||||
	Applies the requested configuration changes.
 | 
			
		||||
 | 
			
		||||
	@serial must match the serial from the last GetResources() call,
 | 
			
		||||
	or org.freedesktop.DBus.AccessDenied will be generated.
 | 
			
		||||
 | 
			
		||||
	If @persistent is true, mutter will attempt to replicate this
 | 
			
		||||
	configuration the next time this HW layout appears.
 | 
			
		||||
 | 
			
		||||
	@crtcs represents the new logical configuration, as a list
 | 
			
		||||
	of structures containing:
 | 
			
		||||
	- u ID: the API ID from the corresponding GetResources() call
 | 
			
		||||
	- i new_mode: the API ID of the new mode to configure the CRTC
 | 
			
		||||
	              with, or -1 if the CRTC should be disabled
 | 
			
		||||
        - i x, y: the new coordinates of the top left corner
 | 
			
		||||
	          the geometry will be completed with the size information
 | 
			
		||||
		  from @new_mode
 | 
			
		||||
        - u transform: the desired transform
 | 
			
		||||
	- au outputs: the API ID of outputs that should be assigned to
 | 
			
		||||
	              this CRTC
 | 
			
		||||
        - a{sv} properties: properties whose value should be changed
 | 
			
		||||
 | 
			
		||||
	Note: CRTCs not referenced in the array will be	disabled.
 | 
			
		||||
 | 
			
		||||
	@outputs represent the output property changes as:
 | 
			
		||||
	- u ID: the API ID of the output to change
 | 
			
		||||
	- a{sv} properties: properties whose value should be changed
 | 
			
		||||
 | 
			
		||||
	Note: both for CRTCs and outputs, properties not included in
 | 
			
		||||
	the dictionary will not be changed.
 | 
			
		||||
 | 
			
		||||
	Note: unrecognized properties will have no effect, but if the
 | 
			
		||||
	configuration change succeeds the property will be reported
 | 
			
		||||
	by the next GetResources() call, and if @persistent is true,
 | 
			
		||||
	it will also be saved to disk.
 | 
			
		||||
 | 
			
		||||
	If the configuration is invalid according to the previous
 | 
			
		||||
	GetResources() call, for example because a CRTC references
 | 
			
		||||
	an output it cannot drive, or not all outputs support the
 | 
			
		||||
	chosen mode, the error org.freedesktop.DBus.InvalidArgs will
 | 
			
		||||
	be generated.
 | 
			
		||||
 | 
			
		||||
	If the configuration cannot be applied for any other reason
 | 
			
		||||
	(eg. the screen size would exceed texture limits), the error
 | 
			
		||||
	org.freedesktop.DBus.Error.LimitsExceeded will be generated.
 | 
			
		||||
    -->
 | 
			
		||||
    <method name="ApplyConfiguration">
 | 
			
		||||
      <arg name="serial" direction="in" type="u" />
 | 
			
		||||
      <arg name="persistent" direction="in" type="b" />
 | 
			
		||||
      <arg name="crtcs" direction="in" type="a(uiiiuaua{sv})" />
 | 
			
		||||
      <arg name="outputs" direction="in" type="a(ua{sv})" />
 | 
			
		||||
    </method>
 | 
			
		||||
 | 
			
		||||
    <!--
 | 
			
		||||
        ChangeBacklight:
 | 
			
		||||
	@serial: configuration serial
 | 
			
		||||
	@output: the API id of the output
 | 
			
		||||
	@value: the new backlight value
 | 
			
		||||
 | 
			
		||||
	Changes the backlight of @output to @value, which is
 | 
			
		||||
	expressed as a percentage and rounded to the HW limits.
 | 
			
		||||
    -->
 | 
			
		||||
    <method name="ChangeBacklight">
 | 
			
		||||
      <arg name="serial" direction="in" type="u" />
 | 
			
		||||
      <arg name="output" direction="in" type="u" />
 | 
			
		||||
      <arg name="value" direction="in" type="i" />
 | 
			
		||||
    </method>
 | 
			
		||||
 | 
			
		||||
    <!--
 | 
			
		||||
        GetCrtcGamma:
 | 
			
		||||
	@serial: configuration serial
 | 
			
		||||
	@crtc: API id of the crtc
 | 
			
		||||
	@red: red gamma ramp
 | 
			
		||||
	@green: green gamma ramp
 | 
			
		||||
	@blue: blue gamma ramp
 | 
			
		||||
 | 
			
		||||
	Requests the current gamma ramps of @crtc.
 | 
			
		||||
    -->
 | 
			
		||||
    <method name="GetCrtcGamma">
 | 
			
		||||
      <arg name="serial" direction="in" type="u" />
 | 
			
		||||
      <arg name="crtc" direction="in" type="u" />
 | 
			
		||||
      <arg name="red" direction="out" type="aq" />
 | 
			
		||||
      <arg name="green" direction="out" type="aq" />
 | 
			
		||||
      <arg name="blue" direction="out" type="aq" />
 | 
			
		||||
    </method>
 | 
			
		||||
 | 
			
		||||
    <!--
 | 
			
		||||
        SetCrtcGamma:
 | 
			
		||||
	@serial: configuration serial
 | 
			
		||||
	@crtc: API id of the crtc
 | 
			
		||||
	@red: red gamma ramp
 | 
			
		||||
	@green: green gamma ramp
 | 
			
		||||
	@blue: blue gamma ramp
 | 
			
		||||
 | 
			
		||||
	Changes the gamma ramps of @crtc.
 | 
			
		||||
    -->
 | 
			
		||||
    <method name="SetCrtcGamma">
 | 
			
		||||
      <arg name="serial" direction="in" type="u" />
 | 
			
		||||
      <arg name="crtc" direction="in" type="u" />
 | 
			
		||||
      <arg name="red" direction="in" type="aq" />
 | 
			
		||||
      <arg name="green" direction="in" type="aq" />
 | 
			
		||||
      <arg name="blue" direction="in" type="aq" />
 | 
			
		||||
    </method>
 | 
			
		||||
 | 
			
		||||
    <!--
 | 
			
		||||
        PowerSaveMode:
 | 
			
		||||
 | 
			
		||||
	Contains the current power saving mode for the screen, and
 | 
			
		||||
	allows changing it.
 | 
			
		||||
 | 
			
		||||
        Possible values:
 | 
			
		||||
	- 0: on
 | 
			
		||||
	- 1: standby
 | 
			
		||||
	- 2: suspend
 | 
			
		||||
	- 3: off
 | 
			
		||||
	- -1: unknown (unsupported)
 | 
			
		||||
 | 
			
		||||
        A client should not attempt to change the powersave mode
 | 
			
		||||
	from -1 (unknown) to any other value, and viceversa.
 | 
			
		||||
	Note that the actual effects of the different values
 | 
			
		||||
	depend on the hardware and the kernel driver in use, and
 | 
			
		||||
	it's perfectly possible that all values different than on
 | 
			
		||||
	have the same effect.
 | 
			
		||||
	Also, setting the PowerSaveMode to 3 (off) may or may
 | 
			
		||||
	not have the same effect as disabling all outputs by
 | 
			
		||||
	setting no CRTC on them with ApplyConfiguration(), and
 | 
			
		||||
	may or may not cause a configuration change.
 | 
			
		||||
 | 
			
		||||
        Also note that this property might become out of date
 | 
			
		||||
	if changed through different means (for example using the
 | 
			
		||||
	XRandR interface directly).
 | 
			
		||||
    -->
 | 
			
		||||
    <property name="PowerSaveMode" type="i" access="readwrite" />
 | 
			
		||||
  </interface>
 | 
			
		||||
</node>
 | 
			
		||||
		Reference in New Issue
	
	Block a user