Compare commits
	
		
			35 Commits
		
	
	
		
			gnome-3-26
			...
			3.16.4
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					02484cf66f | ||
| 
						 | 
					2c1f2fce40 | ||
| 
						 | 
					b449ae4ce1 | ||
| 
						 | 
					9ed5dc758f | ||
| 
						 | 
					f90834e2cf | ||
| 
						 | 
					916070cc72 | ||
| 
						 | 
					a54b1261d3 | ||
| 
						 | 
					c77e482b60 | ||
| 
						 | 
					9cc80497a2 | ||
| 
						 | 
					833c6e2263 | ||
| 
						 | 
					f4d9153e5f | ||
| 
						 | 
					55fd05ea58 | ||
| 
						 | 
					0765963adf | ||
| 
						 | 
					42634d4454 | ||
| 
						 | 
					f60c33b5af | ||
| 
						 | 
					20b6004507 | ||
| 
						 | 
					3fb1135cb7 | ||
| 
						 | 
					4a69a2a632 | ||
| 
						 | 
					351f444f9d | ||
| 
						 | 
					67f2e507e8 | ||
| 
						 | 
					aa19281dd3 | ||
| 
						 | 
					843c9b308c | ||
| 
						 | 
					21d95cf6d8 | ||
| 
						 | 
					e4e5e5a67f | ||
| 
						 | 
					b507461c0f | ||
| 
						 | 
					676a87eac6 | ||
| 
						 | 
					33eb82a5f5 | ||
| 
						 | 
					68d1832075 | ||
| 
						 | 
					83bc703744 | ||
| 
						 | 
					5b6380d394 | ||
| 
						 | 
					7f0ed14f02 | ||
| 
						 | 
					7bdd69892b | ||
| 
						 | 
					c99da71e96 | ||
| 
						 | 
					f7e243108d | ||
| 
						 | 
					0d6420df51 | 
							
								
								
									
										43
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								NEWS
									
									
									
									
									
								
							@@ -1,3 +1,46 @@
 | 
			
		||||
3.16.4
 | 
			
		||||
======
 | 
			
		||||
* Misc. crash fixes [Peter, Marek, Florian; #750816, #751884, #756642]
 | 
			
		||||
* Fix glitch with some fullscreen apps [Rui; #753020]
 | 
			
		||||
* Fix screen update issue with NVidia driver [Aaron, Rui; #728464]
 | 
			
		||||
* Misc. bug fixes [Florian, Ting-Wei, Colin; #753156, #753380, #756649, #752047]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Marek Chalupa, Peter Hutterer, Ting-Wei Lan, Rui Matos, Florian Müllner,
 | 
			
		||||
  Aaron Plattner, Jasper St. Pierre, Colin Walters
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
  Pedro Albuquerque [pt], Sveinn í Felli [is]
 | 
			
		||||
 | 
			
		||||
3.16.3
 | 
			
		||||
======
 | 
			
		||||
* Fix kill dialog not showing when first PING fails [Rui; #749076]
 | 
			
		||||
* wayland: Reset idle time appropriately [Rui; #749711, #749994]
 | 
			
		||||
* Fix crash when trying to focus a hidden window [Florian; #751715]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Rui Matos, Florian Müllner, Jasper St. Pierre
 | 
			
		||||
 | 
			
		||||
Translations:
 | 
			
		||||
  Bernd Homuth [de]
 | 
			
		||||
 | 
			
		||||
3.16.2
 | 
			
		||||
======
 | 
			
		||||
* Fix scroll button setting [Ondrej; #747967]
 | 
			
		||||
* Don't reset idle time for non-hardware events [Rui; #748541]
 | 
			
		||||
* Honor default value for click method setting [Rui; #746290]
 | 
			
		||||
* Misc. bug fixes [Rui; #748478]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Carlos Garnacho, Ondrej Holy, Rui Matos
 | 
			
		||||
 | 
			
		||||
3.16.1.1
 | 
			
		||||
========
 | 
			
		||||
* Prevent a crash when switching VTs or adding input devices [Carlos; #747886]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Carlos Garnacho
 | 
			
		||||
 | 
			
		||||
3.16.1
 | 
			
		||||
======
 | 
			
		||||
* Add function to refresh all background instances [Rui; #739178]
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@ AC_PREREQ(2.62)
 | 
			
		||||
 | 
			
		||||
m4_define([mutter_major_version], [3])
 | 
			
		||||
m4_define([mutter_minor_version], [16])
 | 
			
		||||
m4_define([mutter_micro_version], [1])
 | 
			
		||||
m4_define([mutter_micro_version], [4])
 | 
			
		||||
 | 
			
		||||
m4_define([mutter_version],
 | 
			
		||||
          [mutter_major_version.mutter_minor_version.mutter_micro_version])
 | 
			
		||||
@@ -332,6 +332,11 @@ fi
 | 
			
		||||
 | 
			
		||||
GTK_DOC_CHECK([1.15], [--flavour no-tmpl])
 | 
			
		||||
 | 
			
		||||
AC_CHECK_DECL([GL_EXT_x11_sync_object],
 | 
			
		||||
              [],
 | 
			
		||||
              [AC_MSG_ERROR([GL_EXT_x11_sync_object definition not found, please update your GL headers])],
 | 
			
		||||
              [#include <GL/glx.h>])
 | 
			
		||||
 | 
			
		||||
#### Warnings (last since -Werror can disturb other tests)
 | 
			
		||||
 | 
			
		||||
# Stay command-line compatible with the gnome-common configure option. Here
 | 
			
		||||
 
 | 
			
		||||
@@ -139,6 +139,8 @@ libmutter_la_SOURCES =				\
 | 
			
		||||
	compositor/meta-surface-actor.h		\
 | 
			
		||||
	compositor/meta-surface-actor-x11.c	\
 | 
			
		||||
	compositor/meta-surface-actor-x11.h	\
 | 
			
		||||
	compositor/meta-sync-ring.c		\
 | 
			
		||||
	compositor/meta-sync-ring.h		\
 | 
			
		||||
	compositor/meta-texture-rectangle.c	\
 | 
			
		||||
	compositor/meta-texture-rectangle.h	\
 | 
			
		||||
	compositor/meta-texture-tower.c		\
 | 
			
		||||
 
 | 
			
		||||
@@ -209,6 +209,10 @@ update_touchpad_left_handed (MetaInputSettings  *input_settings,
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
  gboolean enabled = FALSE;
 | 
			
		||||
 | 
			
		||||
  if (device &&
 | 
			
		||||
      clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  priv = meta_input_settings_get_instance_private (input_settings);
 | 
			
		||||
  input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
 | 
			
		||||
  handedness = g_settings_get_enum (priv->touchpad_settings, "left-handed");
 | 
			
		||||
@@ -230,7 +234,6 @@ update_touchpad_left_handed (MetaInputSettings  *input_settings,
 | 
			
		||||
 | 
			
		||||
  if (device)
 | 
			
		||||
    {
 | 
			
		||||
      g_assert (clutter_input_device_get_device_type (device) == CLUTTER_TOUCHPAD_DEVICE);
 | 
			
		||||
      settings_device_set_bool_setting (input_settings, device,
 | 
			
		||||
                                        input_settings_class->set_left_handed,
 | 
			
		||||
                                        enabled);
 | 
			
		||||
@@ -251,13 +254,16 @@ update_mouse_left_handed (MetaInputSettings  *input_settings,
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
  gboolean enabled;
 | 
			
		||||
 | 
			
		||||
  if (device &&
 | 
			
		||||
      clutter_input_device_get_device_type (device) != CLUTTER_POINTER_DEVICE)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  priv = meta_input_settings_get_instance_private (input_settings);
 | 
			
		||||
  input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
 | 
			
		||||
  enabled = g_settings_get_boolean (priv->mouse_settings, "left-handed");
 | 
			
		||||
 | 
			
		||||
  if (device)
 | 
			
		||||
    {
 | 
			
		||||
      g_assert (clutter_input_device_get_device_type (device) == CLUTTER_POINTER_DEVICE);
 | 
			
		||||
      settings_device_set_bool_setting (input_settings, device,
 | 
			
		||||
                                        input_settings_class->set_left_handed,
 | 
			
		||||
                                        enabled);
 | 
			
		||||
@@ -366,6 +372,10 @@ update_touchpad_tap_enabled (MetaInputSettings  *input_settings,
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
  gboolean enabled;
 | 
			
		||||
 | 
			
		||||
  if (device &&
 | 
			
		||||
      clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  priv = meta_input_settings_get_instance_private (input_settings);
 | 
			
		||||
  input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
 | 
			
		||||
  enabled = g_settings_get_boolean (priv->touchpad_settings, "tap-to-click");
 | 
			
		||||
@@ -392,6 +402,10 @@ update_touchpad_scroll_method (MetaInputSettings *input_settings,
 | 
			
		||||
  GDesktopTouchpadScrollMethod method;
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
 | 
			
		||||
  if (device &&
 | 
			
		||||
      clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  priv = meta_input_settings_get_instance_private (input_settings);
 | 
			
		||||
  input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
 | 
			
		||||
  method = g_settings_get_enum (priv->touchpad_settings, "scroll-method");
 | 
			
		||||
@@ -418,6 +432,10 @@ update_touchpad_click_method (MetaInputSettings *input_settings,
 | 
			
		||||
  GDesktopTouchpadScrollMethod method;
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
 | 
			
		||||
  if (device &&
 | 
			
		||||
      clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  priv = meta_input_settings_get_instance_private (input_settings);
 | 
			
		||||
  input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
 | 
			
		||||
  method = g_settings_get_enum (priv->touchpad_settings, "click-method");
 | 
			
		||||
@@ -444,6 +462,10 @@ update_touchpad_send_events (MetaInputSettings  *input_settings,
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
  GDesktopDeviceSendEvents mode;
 | 
			
		||||
 | 
			
		||||
  if (device &&
 | 
			
		||||
      clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  priv = meta_input_settings_get_instance_private (input_settings);
 | 
			
		||||
  input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
 | 
			
		||||
  mode = g_settings_get_enum (priv->touchpad_settings, "send-events");
 | 
			
		||||
@@ -486,13 +508,16 @@ update_trackball_scroll_button (MetaInputSettings  *input_settings,
 | 
			
		||||
  MetaInputSettingsPrivate *priv;
 | 
			
		||||
  guint button;
 | 
			
		||||
 | 
			
		||||
  if (device && !device_is_trackball (device))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  priv = meta_input_settings_get_instance_private (input_settings);
 | 
			
		||||
  input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
 | 
			
		||||
  /* This key is 'i' in the schema but it also specifies a minimum
 | 
			
		||||
   * range of 0 so the cast here is safe. */
 | 
			
		||||
  button = (guint) g_settings_get_int (priv->trackball_settings, "scroll-wheel-emulation-button");
 | 
			
		||||
 | 
			
		||||
  if (device && device_is_trackball (device))
 | 
			
		||||
  if (device)
 | 
			
		||||
    {
 | 
			
		||||
      input_settings_class->set_scroll_button (input_settings, device, button);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,7 @@
 | 
			
		||||
 | 
			
		||||
#include <meta/main.h>
 | 
			
		||||
#include <clutter/evdev/clutter-evdev.h>
 | 
			
		||||
#include <libupower-glib/upower.h>
 | 
			
		||||
 | 
			
		||||
#include "meta-barrier-native.h"
 | 
			
		||||
#include "meta-idle-monitor-native.h"
 | 
			
		||||
@@ -39,10 +40,11 @@
 | 
			
		||||
struct _MetaBackendNativePrivate
 | 
			
		||||
{
 | 
			
		||||
  MetaLauncher *launcher;
 | 
			
		||||
 | 
			
		||||
  MetaBarrierManagerNative *barrier_manager;
 | 
			
		||||
 | 
			
		||||
  GSettings *keyboard_settings;
 | 
			
		||||
  UpClient *up_client;
 | 
			
		||||
  guint sleep_signal_id;
 | 
			
		||||
  GCancellable *cancellable;
 | 
			
		||||
  GDBusConnection *system_bus;
 | 
			
		||||
};
 | 
			
		||||
typedef struct _MetaBackendNativePrivate MetaBackendNativePrivate;
 | 
			
		||||
 | 
			
		||||
@@ -56,9 +58,69 @@ meta_backend_native_finalize (GObject *object)
 | 
			
		||||
 | 
			
		||||
  meta_launcher_free (priv->launcher);
 | 
			
		||||
 | 
			
		||||
  g_object_unref (priv->up_client);
 | 
			
		||||
  if (priv->sleep_signal_id)
 | 
			
		||||
    g_dbus_connection_signal_unsubscribe (priv->system_bus, priv->sleep_signal_id);
 | 
			
		||||
  g_cancellable_cancel (priv->cancellable);
 | 
			
		||||
  g_clear_object (&priv->cancellable);
 | 
			
		||||
  g_clear_object (&priv->system_bus);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_backend_native_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
prepare_for_sleep_cb (GDBusConnection *connection,
 | 
			
		||||
                      const gchar     *sender_name,
 | 
			
		||||
                      const gchar     *object_path,
 | 
			
		||||
                      const gchar     *interface_name,
 | 
			
		||||
                      const gchar     *signal_name,
 | 
			
		||||
                      GVariant        *parameters,
 | 
			
		||||
                      gpointer         user_data)
 | 
			
		||||
{
 | 
			
		||||
  gboolean suspending;
 | 
			
		||||
  g_variant_get (parameters, "(b)", &suspending);
 | 
			
		||||
  if (suspending)
 | 
			
		||||
    return;
 | 
			
		||||
  meta_idle_monitor_native_reset_idletime (meta_idle_monitor_get_core ());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
system_bus_gotten_cb (GObject      *object,
 | 
			
		||||
                      GAsyncResult *res,
 | 
			
		||||
                      gpointer      user_data)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackendNativePrivate *priv;
 | 
			
		||||
  GDBusConnection *bus;
 | 
			
		||||
 | 
			
		||||
  bus = g_bus_get_finish (res, NULL);
 | 
			
		||||
  if (!bus)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  priv = meta_backend_native_get_instance_private (META_BACKEND_NATIVE (user_data));
 | 
			
		||||
  priv->system_bus = bus;
 | 
			
		||||
  priv->sleep_signal_id = g_dbus_connection_signal_subscribe (priv->system_bus,
 | 
			
		||||
                                                              "org.freedesktop.login1",
 | 
			
		||||
                                                              "org.freedesktop.login1.Manager",
 | 
			
		||||
                                                              "PrepareForSleep",
 | 
			
		||||
                                                              "/org/freedesktop/login1",
 | 
			
		||||
                                                              NULL,
 | 
			
		||||
                                                              G_DBUS_SIGNAL_FLAGS_NONE,
 | 
			
		||||
                                                              prepare_for_sleep_cb,
 | 
			
		||||
                                                              NULL,
 | 
			
		||||
                                                              NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
lid_is_closed_changed_cb (UpClient   *client,
 | 
			
		||||
                          GParamSpec *pspec,
 | 
			
		||||
                          gpointer    user_data)
 | 
			
		||||
{
 | 
			
		||||
  if (up_client_get_lid_is_closed (client))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  meta_idle_monitor_native_reset_idletime (meta_idle_monitor_get_core ());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
constrain_to_barriers (ClutterInputDevice *device,
 | 
			
		||||
                       guint32             time,
 | 
			
		||||
@@ -270,6 +332,16 @@ meta_backend_native_init (MetaBackendNative *native)
 | 
			
		||||
  priv->launcher = meta_launcher_new ();
 | 
			
		||||
 | 
			
		||||
  priv->barrier_manager = meta_barrier_manager_native_new ();
 | 
			
		||||
 | 
			
		||||
  priv->up_client = up_client_new ();
 | 
			
		||||
  g_signal_connect (priv->up_client, "notify::lid-is-closed",
 | 
			
		||||
                    G_CALLBACK (lid_is_closed_changed_cb), NULL);
 | 
			
		||||
 | 
			
		||||
  priv->cancellable = g_cancellable_new ();
 | 
			
		||||
  g_bus_get (G_BUS_TYPE_SYSTEM,
 | 
			
		||||
             priv->cancellable,
 | 
			
		||||
             system_bus_gotten_cb,
 | 
			
		||||
             native);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
 
 | 
			
		||||
@@ -43,6 +43,7 @@
 | 
			
		||||
 | 
			
		||||
#include "backends/meta-backend-private.h"
 | 
			
		||||
#include "meta-cursor-renderer-native.h"
 | 
			
		||||
#include "meta-idle-monitor-native.h"
 | 
			
		||||
 | 
			
		||||
struct _MetaLauncher
 | 
			
		||||
{
 | 
			
		||||
@@ -110,6 +111,7 @@ session_unpause (void)
 | 
			
		||||
 | 
			
		||||
    clutter_actor_queue_redraw (stage);
 | 
			
		||||
    meta_cursor_renderer_native_force_update (META_CURSOR_RENDERER_NATIVE (renderer));
 | 
			
		||||
    meta_idle_monitor_native_reset_idletime (meta_idle_monitor_get_core ());
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -141,7 +141,15 @@ translate_crossing_event (MetaBackendX11 *x11,
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  enter_event->event = meta_backend_x11_get_xwindow (x11);
 | 
			
		||||
  Window stage_window = meta_backend_x11_get_xwindow (x11);
 | 
			
		||||
  if (enter_event->event != stage_window)
 | 
			
		||||
    {
 | 
			
		||||
      /* See above for the rationale for this... */
 | 
			
		||||
      g_assert (!meta_is_wayland_compositor ());
 | 
			
		||||
      enter_event->event = meta_backend_x11_get_xwindow (x11);
 | 
			
		||||
      enter_event->event_x = enter_event->root_x;
 | 
			
		||||
      enter_event->event_y = enter_event->root_y;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,7 @@
 | 
			
		||||
#include "meta-backend-x11.h"
 | 
			
		||||
#include "meta-input-settings-x11.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <gdk/gdkx.h>
 | 
			
		||||
#include <X11/Xatom.h>
 | 
			
		||||
#include <X11/extensions/XInput2.h>
 | 
			
		||||
@@ -35,6 +36,38 @@
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (MetaInputSettingsX11, meta_input_settings_x11, META_TYPE_INPUT_SETTINGS)
 | 
			
		||||
 | 
			
		||||
static void *
 | 
			
		||||
get_property (ClutterInputDevice *device,
 | 
			
		||||
              const gchar        *property,
 | 
			
		||||
              Atom                type,
 | 
			
		||||
              int                 format,
 | 
			
		||||
              gulong              nitems)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackend *backend = meta_get_backend ();
 | 
			
		||||
  Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
 | 
			
		||||
  gulong nitems_ret, bytes_after_ret;
 | 
			
		||||
  int rc, device_id, format_ret;
 | 
			
		||||
  Atom property_atom, type_ret;
 | 
			
		||||
  guchar *data_ret = NULL;
 | 
			
		||||
 | 
			
		||||
  property_atom = XInternAtom (xdisplay, property, False);
 | 
			
		||||
  device_id = clutter_input_device_get_device_id (device);
 | 
			
		||||
 | 
			
		||||
  rc = XIGetProperty (xdisplay, device_id, property_atom,
 | 
			
		||||
                      0, 10, False, type, &type_ret, &format_ret,
 | 
			
		||||
                      &nitems_ret, &bytes_after_ret, &data_ret);
 | 
			
		||||
  if (rc == Success && type_ret == type && format_ret == format && nitems_ret >= nitems)
 | 
			
		||||
    {
 | 
			
		||||
      if (nitems_ret > nitems)
 | 
			
		||||
        g_warning ("Property '%s' for device '%s' returned %lu items, expected %lu",
 | 
			
		||||
                   property, clutter_input_device_get_device_name (device), nitems_ret, nitems);
 | 
			
		||||
      return data_ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_XFree (data_ret);
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
change_property (ClutterInputDevice *device,
 | 
			
		||||
                 const gchar        *property,
 | 
			
		||||
@@ -45,23 +78,20 @@ change_property (ClutterInputDevice *device,
 | 
			
		||||
{
 | 
			
		||||
  MetaBackend *backend = meta_get_backend ();
 | 
			
		||||
  Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
 | 
			
		||||
  gulong nitems_ret, bytes_after_ret;
 | 
			
		||||
  int rc, device_id, format_ret;
 | 
			
		||||
  Atom property_atom, type_ret;
 | 
			
		||||
  int device_id;
 | 
			
		||||
  Atom property_atom;
 | 
			
		||||
  guchar *data_ret;
 | 
			
		||||
 | 
			
		||||
  property_atom = XInternAtom (xdisplay, property, False);
 | 
			
		||||
  device_id = clutter_input_device_get_device_id (device);
 | 
			
		||||
 | 
			
		||||
  rc = XIGetProperty (xdisplay, device_id, property_atom,
 | 
			
		||||
                      0, 0, False, type, &type_ret, &format_ret,
 | 
			
		||||
                      &nitems_ret, &bytes_after_ret, &data_ret);
 | 
			
		||||
  data_ret = get_property (device, property, type, format, nitems);
 | 
			
		||||
  if (!data_ret)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  XIChangeProperty (xdisplay, device_id, property_atom, type,
 | 
			
		||||
                    format, XIPropModeReplace, data, nitems);
 | 
			
		||||
  meta_XFree (data_ret);
 | 
			
		||||
 | 
			
		||||
  if (rc == Success && type_ret == type && format_ret == format)
 | 
			
		||||
    XIChangeProperty (xdisplay, device_id, property_atom, type,
 | 
			
		||||
                      format, XIPropModeReplace, data, nitems);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -70,6 +100,12 @@ meta_input_settings_x11_set_send_events (MetaInputSettings        *settings,
 | 
			
		||||
                                         GDesktopDeviceSendEvents  mode)
 | 
			
		||||
{
 | 
			
		||||
  guchar values[2] = { 0 }; /* disabled, disabled-on-external-mouse */
 | 
			
		||||
  guchar *available;
 | 
			
		||||
 | 
			
		||||
  available = get_property (device, "libinput Send Events Modes Available",
 | 
			
		||||
                            XA_INTEGER, 8, 2);
 | 
			
		||||
  if (!available)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  switch (mode)
 | 
			
		||||
    {
 | 
			
		||||
@@ -83,8 +119,14 @@ meta_input_settings_x11_set_send_events (MetaInputSettings        *settings,
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  change_property (device, "libinput Send Events Mode Enabled",
 | 
			
		||||
                   XA_INTEGER, 8, &values, 2);
 | 
			
		||||
  if ((values[0] && !available[0]) || (values[1] && !available[1]))
 | 
			
		||||
    g_warning ("Device '%s' does not support sendevents mode %d\n",
 | 
			
		||||
               clutter_input_device_get_device_name (device), mode);
 | 
			
		||||
  else
 | 
			
		||||
    change_property (device, "libinput Send Events Mode Enabled",
 | 
			
		||||
                     XA_INTEGER, 8, &values, 2);
 | 
			
		||||
 | 
			
		||||
  meta_XFree (available);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -156,6 +198,12 @@ meta_input_settings_x11_set_scroll_method (MetaInputSettings            *setting
 | 
			
		||||
                                           GDesktopTouchpadScrollMethod  mode)
 | 
			
		||||
{
 | 
			
		||||
  guchar values[3] = { 0 }; /* 2fg, edge, button. The last value is unused */
 | 
			
		||||
  guchar *available;
 | 
			
		||||
 | 
			
		||||
  available = get_property (device, "libinput Scroll Methods Available",
 | 
			
		||||
                            XA_INTEGER, 8, 3);
 | 
			
		||||
  if (!available)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  switch (mode)
 | 
			
		||||
    {
 | 
			
		||||
@@ -171,8 +219,14 @@ meta_input_settings_x11_set_scroll_method (MetaInputSettings            *setting
 | 
			
		||||
      g_assert_not_reached ();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  change_property (device, "libinput Scroll Method Enabled",
 | 
			
		||||
                   XA_INTEGER, 8, &values, 3);
 | 
			
		||||
  if ((values[0] && !available[0]) || (values[1] && !available[1]))
 | 
			
		||||
    g_warning ("Device '%s' does not support scroll mode %d\n",
 | 
			
		||||
               clutter_input_device_get_device_name (device), mode);
 | 
			
		||||
  else
 | 
			
		||||
    change_property (device, "libinput Scroll Method Enabled",
 | 
			
		||||
                     XA_INTEGER, 8, &values, 3);
 | 
			
		||||
 | 
			
		||||
  meta_XFree (available);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -180,7 +234,7 @@ meta_input_settings_x11_set_scroll_button (MetaInputSettings  *settings,
 | 
			
		||||
                                           ClutterInputDevice *device,
 | 
			
		||||
                                           guint               button)
 | 
			
		||||
{
 | 
			
		||||
  change_property (device, "libinput Scroll Method Enabled",
 | 
			
		||||
  change_property (device, "libinput Button Scrolling Button",
 | 
			
		||||
                   XA_INTEGER, 32, &button, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -190,16 +244,28 @@ meta_input_settings_x11_set_click_method (MetaInputSettings           *settings,
 | 
			
		||||
                                          GDesktopTouchpadClickMethod  mode)
 | 
			
		||||
{
 | 
			
		||||
  guchar values[2] = { 0 }; /* buttonareas, clickfinger */
 | 
			
		||||
  guchar *defaults, *available;
 | 
			
		||||
 | 
			
		||||
  available = get_property (device, "libinput Click Methods Available",
 | 
			
		||||
                            XA_INTEGER, 8, 2);
 | 
			
		||||
  if (!available)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  switch (mode)
 | 
			
		||||
    {
 | 
			
		||||
    case G_DESKTOP_TOUCHPAD_CLICK_METHOD_DEFAULT:
 | 
			
		||||
      defaults = get_property (device, "libinput Click Method Enabled Default",
 | 
			
		||||
                               XA_INTEGER, 8, 2);
 | 
			
		||||
      if (!defaults)
 | 
			
		||||
        break;
 | 
			
		||||
      memcpy (values, defaults, 2);
 | 
			
		||||
      meta_XFree (defaults);
 | 
			
		||||
      break;
 | 
			
		||||
    case G_DESKTOP_TOUCHPAD_CLICK_METHOD_NONE:
 | 
			
		||||
      break;
 | 
			
		||||
    case G_DESKTOP_TOUCHPAD_CLICK_METHOD_AREAS:
 | 
			
		||||
      values[0] = 1;
 | 
			
		||||
      break;
 | 
			
		||||
    case G_DESKTOP_TOUCHPAD_CLICK_METHOD_DEFAULT:
 | 
			
		||||
      /* XXX: We can't be much smarter yet, x11 doesn't expose default settings */
 | 
			
		||||
    case G_DESKTOP_TOUCHPAD_CLICK_METHOD_FINGERS:
 | 
			
		||||
      values[1] = 1;
 | 
			
		||||
      break;
 | 
			
		||||
@@ -208,8 +274,14 @@ meta_input_settings_x11_set_click_method (MetaInputSettings           *settings,
 | 
			
		||||
      return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  change_property (device, "libinput Click Method Enabled",
 | 
			
		||||
                   XA_INTEGER, 8, &values, 2);
 | 
			
		||||
  if ((values[0] && !available[0]) || (values[1] && !available[1]))
 | 
			
		||||
    g_warning ("Device '%s' does not support click method %d\n",
 | 
			
		||||
               clutter_input_device_get_device_name (device), mode);
 | 
			
		||||
  else
 | 
			
		||||
    change_property (device, "libinput Click Method Enabled",
 | 
			
		||||
                     XA_INTEGER, 8, &values, 2);
 | 
			
		||||
 | 
			
		||||
  meta_XFree(available);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,8 @@ struct _MetaCompositor
 | 
			
		||||
{
 | 
			
		||||
  MetaDisplay    *display;
 | 
			
		||||
 | 
			
		||||
  guint           repaint_func_id;
 | 
			
		||||
  guint           pre_paint_func_id;
 | 
			
		||||
  guint           post_paint_func_id;
 | 
			
		||||
 | 
			
		||||
  gint64          server_time_query_time;
 | 
			
		||||
  gint64          server_time_offset;
 | 
			
		||||
@@ -40,6 +41,7 @@ struct _MetaCompositor
 | 
			
		||||
  MetaPluginManager *plugin_mgr;
 | 
			
		||||
 | 
			
		||||
  gboolean frame_has_updated_xsurfaces;
 | 
			
		||||
  gboolean have_x11_sync_object;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Wait 2ms after vblank before starting to draw next frame */
 | 
			
		||||
 
 | 
			
		||||
@@ -79,6 +79,7 @@
 | 
			
		||||
#include "frame.h"
 | 
			
		||||
#include <X11/extensions/shape.h>
 | 
			
		||||
#include <X11/extensions/Xcomposite.h>
 | 
			
		||||
#include "meta-sync-ring.h"
 | 
			
		||||
 | 
			
		||||
#include "backends/x11/meta-backend-x11.h"
 | 
			
		||||
 | 
			
		||||
@@ -125,7 +126,11 @@ meta_switch_workspace_completed (MetaCompositor *compositor)
 | 
			
		||||
void
 | 
			
		||||
meta_compositor_destroy (MetaCompositor *compositor)
 | 
			
		||||
{
 | 
			
		||||
  clutter_threads_remove_repaint_func (compositor->repaint_func_id);
 | 
			
		||||
  clutter_threads_remove_repaint_func (compositor->pre_paint_func_id);
 | 
			
		||||
  clutter_threads_remove_repaint_func (compositor->post_paint_func_id);
 | 
			
		||||
 | 
			
		||||
  if (compositor->have_x11_sync_object)
 | 
			
		||||
    meta_sync_ring_destroy ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -468,13 +473,11 @@ meta_compositor_manage (MetaCompositor *compositor)
 | 
			
		||||
  MetaDisplay *display = compositor->display;
 | 
			
		||||
  Display *xdisplay = display->xdisplay;
 | 
			
		||||
  MetaScreen *screen = display->screen;
 | 
			
		||||
  MetaBackend *backend = meta_get_backend ();
 | 
			
		||||
 | 
			
		||||
  meta_screen_set_cm_selection (display->screen);
 | 
			
		||||
 | 
			
		||||
  {
 | 
			
		||||
    MetaBackend *backend = meta_get_backend ();
 | 
			
		||||
    compositor->stage = meta_backend_get_stage (backend);
 | 
			
		||||
  }
 | 
			
		||||
  compositor->stage = meta_backend_get_stage (backend);
 | 
			
		||||
 | 
			
		||||
  /* We use connect_after() here to accomodate code in GNOME Shell that,
 | 
			
		||||
   * when benchmarking drawing performance, connects to ::after-paint
 | 
			
		||||
@@ -510,7 +513,7 @@ meta_compositor_manage (MetaCompositor *compositor)
 | 
			
		||||
 | 
			
		||||
      compositor->output = screen->composite_overlay_window;
 | 
			
		||||
 | 
			
		||||
      xwin = meta_backend_x11_get_xwindow (META_BACKEND_X11 (meta_get_backend ()));
 | 
			
		||||
      xwin = meta_backend_x11_get_xwindow (META_BACKEND_X11 (backend));
 | 
			
		||||
 | 
			
		||||
      XReparentWindow (xdisplay, xwin, compositor->output, 0, 0);
 | 
			
		||||
 | 
			
		||||
@@ -530,6 +533,8 @@ meta_compositor_manage (MetaCompositor *compositor)
 | 
			
		||||
       * contents until we show the stage.
 | 
			
		||||
       */
 | 
			
		||||
      XMapWindow (xdisplay, compositor->output);
 | 
			
		||||
 | 
			
		||||
      compositor->have_x11_sync_object = meta_sync_ring_init (xdisplay);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  redirect_windows (display->screen);
 | 
			
		||||
@@ -731,6 +736,9 @@ meta_compositor_process_event (MetaCompositor *compositor,
 | 
			
		||||
        process_damage (compositor, (XDamageNotifyEvent *) event, window);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (compositor->have_x11_sync_object)
 | 
			
		||||
    meta_sync_ring_handle_event (event);
 | 
			
		||||
 | 
			
		||||
  /* Clutter needs to know about MapNotify events otherwise it will
 | 
			
		||||
     think the stage is invisible */
 | 
			
		||||
  if (!meta_is_wayland_compositor () && event->type == MapNotify)
 | 
			
		||||
@@ -1044,11 +1052,12 @@ frame_callback (CoglOnscreen  *onscreen,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
pre_paint_windows (MetaCompositor *compositor)
 | 
			
		||||
static gboolean
 | 
			
		||||
meta_pre_paint_func (gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  GList *l;
 | 
			
		||||
  MetaWindowActor *top_window;
 | 
			
		||||
  MetaCompositor *compositor = data;
 | 
			
		||||
 | 
			
		||||
  if (compositor->onscreen == NULL)
 | 
			
		||||
    {
 | 
			
		||||
@@ -1060,7 +1069,7 @@ pre_paint_windows (MetaCompositor *compositor)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (compositor->windows == NULL)
 | 
			
		||||
    return;
 | 
			
		||||
    return TRUE;
 | 
			
		||||
 | 
			
		||||
  top_window = g_list_last (compositor->windows)->data;
 | 
			
		||||
 | 
			
		||||
@@ -1077,10 +1086,12 @@ pre_paint_windows (MetaCompositor *compositor)
 | 
			
		||||
    {
 | 
			
		||||
      /* We need to make sure that any X drawing that happens before
 | 
			
		||||
       * the XDamageSubtract() for each window above is visible to
 | 
			
		||||
       * subsequent GL rendering; the only standardized way to do this
 | 
			
		||||
       * is EXT_x11_sync_object, which isn't yet widely available. For
 | 
			
		||||
       * now, we count on details of Xorg and the open source drivers,
 | 
			
		||||
       * and hope for the best otherwise.
 | 
			
		||||
       * subsequent GL rendering; the standardized way to do this is
 | 
			
		||||
       * GL_EXT_X11_sync_object. Since this isn't implemented yet in
 | 
			
		||||
       * mesa, we also have a path that relies on the implementation
 | 
			
		||||
       * of the open source drivers.
 | 
			
		||||
       *
 | 
			
		||||
       * Anything else, we just hope for the best.
 | 
			
		||||
       *
 | 
			
		||||
       * Xorg and open source driver specifics:
 | 
			
		||||
       *
 | 
			
		||||
@@ -1095,17 +1106,28 @@ pre_paint_windows (MetaCompositor *compositor)
 | 
			
		||||
       * round trip request at this point is sufficient to flush the
 | 
			
		||||
       * GLX buffers.
 | 
			
		||||
       */
 | 
			
		||||
      XSync (compositor->display->xdisplay, False);
 | 
			
		||||
 | 
			
		||||
      compositor->frame_has_updated_xsurfaces = FALSE;
 | 
			
		||||
      if (compositor->have_x11_sync_object)
 | 
			
		||||
        compositor->have_x11_sync_object = meta_sync_ring_insert_wait ();
 | 
			
		||||
      else
 | 
			
		||||
        XSync (compositor->display->xdisplay, False);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
meta_repaint_func (gpointer data)
 | 
			
		||||
meta_post_paint_func (gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  MetaCompositor *compositor = data;
 | 
			
		||||
  pre_paint_windows (compositor);
 | 
			
		||||
 | 
			
		||||
  if (compositor->frame_has_updated_xsurfaces)
 | 
			
		||||
    {
 | 
			
		||||
      if (compositor->have_x11_sync_object)
 | 
			
		||||
        compositor->have_x11_sync_object = meta_sync_ring_after_frame ();
 | 
			
		||||
 | 
			
		||||
      compositor->frame_has_updated_xsurfaces = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1140,10 +1162,16 @@ meta_compositor_new (MetaDisplay *display)
 | 
			
		||||
                    G_CALLBACK (on_shadow_factory_changed),
 | 
			
		||||
                    compositor);
 | 
			
		||||
 | 
			
		||||
  compositor->repaint_func_id = clutter_threads_add_repaint_func (meta_repaint_func,
 | 
			
		||||
                                                                  compositor,
 | 
			
		||||
                                                                  NULL);
 | 
			
		||||
 | 
			
		||||
  compositor->pre_paint_func_id =
 | 
			
		||||
    clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_PRE_PAINT,
 | 
			
		||||
                                           meta_pre_paint_func,
 | 
			
		||||
                                           compositor,
 | 
			
		||||
                                           NULL);
 | 
			
		||||
  compositor->post_paint_func_id =
 | 
			
		||||
    clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT,
 | 
			
		||||
                                           meta_post_paint_func,
 | 
			
		||||
                                           compositor,
 | 
			
		||||
                                           NULL);
 | 
			
		||||
  return compositor;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,9 @@
 | 
			
		||||
ClutterActor *meta_shaped_texture_new (void);
 | 
			
		||||
void meta_shaped_texture_set_texture (MetaShapedTexture *stex,
 | 
			
		||||
                                      CoglTexture       *texture);
 | 
			
		||||
void meta_shaped_texture_set_fallback_size (MetaShapedTexture *stex,
 | 
			
		||||
                                            guint              fallback_width,
 | 
			
		||||
                                            guint              fallback_height);
 | 
			
		||||
gboolean meta_shaped_texture_is_obscured (MetaShapedTexture *self);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -86,6 +86,7 @@ struct _MetaShapedTexturePrivate
 | 
			
		||||
  cairo_region_t *unobscured_region;
 | 
			
		||||
 | 
			
		||||
  guint tex_width, tex_height;
 | 
			
		||||
  guint fallback_width, fallback_height;
 | 
			
		||||
 | 
			
		||||
  guint create_mipmaps : 1;
 | 
			
		||||
};
 | 
			
		||||
@@ -136,7 +137,20 @@ set_unobscured_region (MetaShapedTexture *self,
 | 
			
		||||
  g_clear_pointer (&priv->unobscured_region, (GDestroyNotify) cairo_region_destroy);
 | 
			
		||||
  if (unobscured_region)
 | 
			
		||||
    {
 | 
			
		||||
      cairo_rectangle_int_t bounds = { 0, 0, priv->tex_width, priv->tex_height };
 | 
			
		||||
      guint width, height;
 | 
			
		||||
 | 
			
		||||
      if (priv->texture)
 | 
			
		||||
        {
 | 
			
		||||
          width = priv->tex_width;
 | 
			
		||||
          height = priv->tex_height;
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          width = priv->fallback_width;
 | 
			
		||||
          height = priv->fallback_height;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      cairo_rectangle_int_t bounds = { 0, 0, width, height };
 | 
			
		||||
      priv->unobscured_region = cairo_region_copy (unobscured_region);
 | 
			
		||||
      cairo_region_intersect_rectangle (priv->unobscured_region, &bounds);
 | 
			
		||||
    }
 | 
			
		||||
@@ -499,16 +513,21 @@ meta_shaped_texture_get_preferred_width (ClutterActor *self,
 | 
			
		||||
                                         gfloat       *natural_width_p)
 | 
			
		||||
{
 | 
			
		||||
  MetaShapedTexturePrivate *priv;
 | 
			
		||||
  guint width;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (META_IS_SHAPED_TEXTURE (self));
 | 
			
		||||
 | 
			
		||||
  priv = META_SHAPED_TEXTURE (self)->priv;
 | 
			
		||||
 | 
			
		||||
  if (min_width_p)
 | 
			
		||||
    *min_width_p = priv->tex_width;
 | 
			
		||||
  if (priv->texture)
 | 
			
		||||
    width = priv->tex_width;
 | 
			
		||||
  else
 | 
			
		||||
    width = priv->fallback_width;
 | 
			
		||||
 | 
			
		||||
  if (min_width_p)
 | 
			
		||||
    *min_width_p = width;
 | 
			
		||||
  if (natural_width_p)
 | 
			
		||||
    *natural_width_p = priv->tex_width;
 | 
			
		||||
    *natural_width_p = width;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -518,16 +537,21 @@ meta_shaped_texture_get_preferred_height (ClutterActor *self,
 | 
			
		||||
                                          gfloat       *natural_height_p)
 | 
			
		||||
{
 | 
			
		||||
  MetaShapedTexturePrivate *priv;
 | 
			
		||||
  guint height;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (META_IS_SHAPED_TEXTURE (self));
 | 
			
		||||
 | 
			
		||||
  priv = META_SHAPED_TEXTURE (self)->priv;
 | 
			
		||||
 | 
			
		||||
  if (min_height_p)
 | 
			
		||||
    *min_height_p = priv->tex_height;
 | 
			
		||||
  if (priv->texture)
 | 
			
		||||
    height = priv->tex_height;
 | 
			
		||||
  else
 | 
			
		||||
    height = priv->fallback_height;
 | 
			
		||||
 | 
			
		||||
  if (min_height_p)
 | 
			
		||||
    *min_height_p = height;
 | 
			
		||||
  if (natural_height_p)
 | 
			
		||||
    *natural_height_p = priv->tex_height;
 | 
			
		||||
    *natural_height_p = height;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static cairo_region_t *
 | 
			
		||||
@@ -860,6 +884,17 @@ meta_shaped_texture_get_image (MetaShapedTexture     *stex,
 | 
			
		||||
  return surface;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_shaped_texture_set_fallback_size (MetaShapedTexture *self,
 | 
			
		||||
                                       guint              fallback_width,
 | 
			
		||||
                                       guint              fallback_height)
 | 
			
		||||
{
 | 
			
		||||
  MetaShapedTexturePrivate *priv = self->priv;
 | 
			
		||||
 | 
			
		||||
  priv->fallback_width = fallback_width;
 | 
			
		||||
  priv->fallback_height = fallback_height;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_shaped_texture_cull_out (MetaCullable   *cullable,
 | 
			
		||||
                              cairo_region_t *unobscured_region,
 | 
			
		||||
 
 | 
			
		||||
@@ -416,6 +416,7 @@ meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self,
 | 
			
		||||
                                 int width, int height)
 | 
			
		||||
{
 | 
			
		||||
  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
 | 
			
		||||
  MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
 | 
			
		||||
 | 
			
		||||
  if (priv->last_width == width &&
 | 
			
		||||
      priv->last_height == height)
 | 
			
		||||
@@ -424,4 +425,5 @@ meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self,
 | 
			
		||||
  priv->size_changed = TRUE;
 | 
			
		||||
  priv->last_width = width;
 | 
			
		||||
  priv->last_height = height;
 | 
			
		||||
  meta_shaped_texture_set_fallback_size (stex, width, height);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										592
									
								
								src/compositor/meta-sync-ring.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										592
									
								
								src/compositor/meta-sync-ring.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,592 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This is based on an original C++ implementation for compiz that
 | 
			
		||||
 * carries the following copyright notice:
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright © 2011 NVIDIA Corporation
 | 
			
		||||
 *
 | 
			
		||||
 * Permission to use, copy, modify, distribute, and sell this software
 | 
			
		||||
 * and its documentation for any purpose is hereby granted without
 | 
			
		||||
 * fee, provided that the above copyright notice appear in all copies
 | 
			
		||||
 * and that both that copyright notice and this permission notice
 | 
			
		||||
 * appear in supporting documentation, and that the name of NVIDIA
 | 
			
		||||
 * Corporation not be used in advertising or publicity pertaining to
 | 
			
		||||
 * distribution of the software without specific, written prior
 | 
			
		||||
 * permission.  NVIDIA Corporation makes no representations about the
 | 
			
		||||
 * suitability of this software for any purpose. It is provided "as
 | 
			
		||||
 * is" without express or implied warranty.
 | 
			
		||||
 *
 | 
			
		||||
 * NVIDIA CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
 | 
			
		||||
 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
 | 
			
		||||
 * FITNESS, IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY
 | 
			
		||||
 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
			
		||||
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
 | 
			
		||||
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 | 
			
		||||
 * SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 * Authors: James Jones <jajones@nvidia.com>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include <GL/gl.h>
 | 
			
		||||
#include <GL/glx.h>
 | 
			
		||||
#include <X11/extensions/sync.h>
 | 
			
		||||
 | 
			
		||||
#include <cogl/cogl.h>
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
 | 
			
		||||
#include <meta/util.h>
 | 
			
		||||
 | 
			
		||||
#include "meta-sync-ring.h"
 | 
			
		||||
 | 
			
		||||
/* Theory of operation:
 | 
			
		||||
 *
 | 
			
		||||
 * We use a ring of NUM_SYNCS fence objects. On each frame we advance
 | 
			
		||||
 * to the next fence in the ring. For each fence we do:
 | 
			
		||||
 *
 | 
			
		||||
 * 1. fence is XSyncTriggerFence()'d and glWaitSync()'d
 | 
			
		||||
 * 2. NUM_SYNCS / 2 frames later, fence should be triggered
 | 
			
		||||
 * 3. fence is XSyncResetFence()'d
 | 
			
		||||
 * 4. NUM_SYNCS / 2 frames later, fence should be reset
 | 
			
		||||
 * 5. go back to 1 and re-use fence
 | 
			
		||||
 *
 | 
			
		||||
 * glClientWaitSync() and XAlarms are used in steps 2 and 4,
 | 
			
		||||
 * respectively, to double-check the expectections.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define NUM_SYNCS 10
 | 
			
		||||
#define MAX_SYNC_WAIT_TIME (1 * 1000 * 1000 * 1000) /* one sec */
 | 
			
		||||
#define MAX_REBOOT_ATTEMPTS 2
 | 
			
		||||
 | 
			
		||||
typedef enum
 | 
			
		||||
{
 | 
			
		||||
  META_SYNC_STATE_READY,
 | 
			
		||||
  META_SYNC_STATE_WAITING,
 | 
			
		||||
  META_SYNC_STATE_DONE,
 | 
			
		||||
  META_SYNC_STATE_RESET_PENDING,
 | 
			
		||||
} MetaSyncState;
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  Display *xdisplay;
 | 
			
		||||
 | 
			
		||||
  XSyncFence xfence;
 | 
			
		||||
  GLsync gl_x11_sync;
 | 
			
		||||
  GLsync gpu_fence;
 | 
			
		||||
 | 
			
		||||
  XSyncCounter xcounter;
 | 
			
		||||
  XSyncAlarm xalarm;
 | 
			
		||||
  XSyncValue next_counter_value;
 | 
			
		||||
 | 
			
		||||
  MetaSyncState state;
 | 
			
		||||
} MetaSync;
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  Display *xdisplay;
 | 
			
		||||
  int xsync_event_base;
 | 
			
		||||
  int xsync_error_base;
 | 
			
		||||
 | 
			
		||||
  GHashTable *alarm_to_sync;
 | 
			
		||||
 | 
			
		||||
  MetaSync *syncs_array[NUM_SYNCS];
 | 
			
		||||
  guint current_sync_idx;
 | 
			
		||||
  MetaSync *current_sync;
 | 
			
		||||
  guint warmup_syncs;
 | 
			
		||||
 | 
			
		||||
  guint reboots;
 | 
			
		||||
} MetaSyncRing;
 | 
			
		||||
 | 
			
		||||
static MetaSyncRing meta_sync_ring = { 0 };
 | 
			
		||||
 | 
			
		||||
static XSyncValue SYNC_VALUE_ZERO;
 | 
			
		||||
static XSyncValue SYNC_VALUE_ONE;
 | 
			
		||||
 | 
			
		||||
static const char*      (*meta_gl_get_string) (GLenum name);
 | 
			
		||||
static void             (*meta_gl_get_integerv) (GLenum  pname,
 | 
			
		||||
                                                 GLint  *params);
 | 
			
		||||
static const char*      (*meta_gl_get_stringi) (GLenum name,
 | 
			
		||||
                                                GLuint index);
 | 
			
		||||
static void             (*meta_gl_delete_sync) (GLsync sync);
 | 
			
		||||
static GLenum           (*meta_gl_client_wait_sync) (GLsync sync,
 | 
			
		||||
                                                     GLbitfield flags,
 | 
			
		||||
                                                     GLuint64 timeout);
 | 
			
		||||
static void             (*meta_gl_wait_sync) (GLsync sync,
 | 
			
		||||
                                              GLbitfield flags,
 | 
			
		||||
                                              GLuint64 timeout);
 | 
			
		||||
static GLsync           (*meta_gl_import_sync) (GLenum external_sync_type,
 | 
			
		||||
                                                GLintptr external_sync,
 | 
			
		||||
                                                GLbitfield flags);
 | 
			
		||||
static GLsync           (*meta_gl_fence_sync) (GLenum condition,
 | 
			
		||||
                                               GLbitfield flags);
 | 
			
		||||
 | 
			
		||||
static MetaSyncRing *
 | 
			
		||||
meta_sync_ring_get (void)
 | 
			
		||||
{
 | 
			
		||||
  if (meta_sync_ring.reboots > MAX_REBOOT_ATTEMPTS)
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
  return &meta_sync_ring;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
load_gl_symbol (const char  *name,
 | 
			
		||||
                void       **func)
 | 
			
		||||
{
 | 
			
		||||
  *func = cogl_get_proc_address (name);
 | 
			
		||||
  if (!*func)
 | 
			
		||||
    {
 | 
			
		||||
      meta_verbose ("MetaSyncRing: failed to resolve required GL symbol \"%s\"\n", name);
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
check_gl_extensions (void)
 | 
			
		||||
{
 | 
			
		||||
  ClutterBackend *backend;
 | 
			
		||||
  CoglContext *cogl_context;
 | 
			
		||||
  CoglDisplay *cogl_display;
 | 
			
		||||
  CoglRenderer *cogl_renderer;
 | 
			
		||||
 | 
			
		||||
  backend = clutter_get_default_backend ();
 | 
			
		||||
  cogl_context = clutter_backend_get_cogl_context (backend);
 | 
			
		||||
  cogl_display = cogl_context_get_display (cogl_context);
 | 
			
		||||
  cogl_renderer = cogl_display_get_renderer (cogl_display);
 | 
			
		||||
 | 
			
		||||
  switch (cogl_renderer_get_driver (cogl_renderer))
 | 
			
		||||
    {
 | 
			
		||||
    case COGL_DRIVER_GL3:
 | 
			
		||||
      {
 | 
			
		||||
        int num_extensions, i;
 | 
			
		||||
        gboolean arb_sync = FALSE;
 | 
			
		||||
        gboolean x11_sync_object = FALSE;
 | 
			
		||||
 | 
			
		||||
        meta_gl_get_integerv (GL_NUM_EXTENSIONS, &num_extensions);
 | 
			
		||||
 | 
			
		||||
        for (i = 0; i < num_extensions; ++i)
 | 
			
		||||
          {
 | 
			
		||||
            const char *ext = meta_gl_get_stringi (GL_EXTENSIONS, i);
 | 
			
		||||
 | 
			
		||||
            if (g_strcmp0 ("GL_ARB_sync", ext) == 0)
 | 
			
		||||
              arb_sync = TRUE;
 | 
			
		||||
            else if (g_strcmp0 ("GL_EXT_x11_sync_object", ext) == 0)
 | 
			
		||||
              x11_sync_object = TRUE;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
        return arb_sync && x11_sync_object;
 | 
			
		||||
      }
 | 
			
		||||
    case COGL_DRIVER_GL:
 | 
			
		||||
      {
 | 
			
		||||
        const char *extensions = meta_gl_get_string (GL_EXTENSIONS);
 | 
			
		||||
        return (extensions != NULL &&
 | 
			
		||||
                strstr (extensions, "GL_ARB_sync") != NULL &&
 | 
			
		||||
                strstr (extensions, "GL_EXT_x11_sync_object") != NULL);
 | 
			
		||||
      }
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
load_required_symbols (void)
 | 
			
		||||
{
 | 
			
		||||
  static gboolean success = FALSE;
 | 
			
		||||
 | 
			
		||||
  if (success)
 | 
			
		||||
    return TRUE;
 | 
			
		||||
 | 
			
		||||
  /* We don't link against libGL directly because cogl may want to
 | 
			
		||||
   * use something else. This assumes that cogl has been initialized
 | 
			
		||||
   * and dynamically loaded libGL at this point.
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  if (!load_gl_symbol ("glGetString", (void **) &meta_gl_get_string))
 | 
			
		||||
    goto out;
 | 
			
		||||
  if (!load_gl_symbol ("glGetIntegerv", (void **) &meta_gl_get_integerv))
 | 
			
		||||
    goto out;
 | 
			
		||||
  if (!load_gl_symbol ("glGetStringi", (void **) &meta_gl_get_stringi))
 | 
			
		||||
    goto out;
 | 
			
		||||
 | 
			
		||||
  if (!check_gl_extensions ())
 | 
			
		||||
    {
 | 
			
		||||
      meta_verbose ("MetaSyncRing: couldn't find required GL extensions\n");
 | 
			
		||||
      goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (!load_gl_symbol ("glDeleteSync", (void **) &meta_gl_delete_sync))
 | 
			
		||||
    goto out;
 | 
			
		||||
  if (!load_gl_symbol ("glClientWaitSync", (void **) &meta_gl_client_wait_sync))
 | 
			
		||||
    goto out;
 | 
			
		||||
  if (!load_gl_symbol ("glWaitSync", (void **) &meta_gl_wait_sync))
 | 
			
		||||
    goto out;
 | 
			
		||||
  if (!load_gl_symbol ("glImportSyncEXT", (void **) &meta_gl_import_sync))
 | 
			
		||||
    goto out;
 | 
			
		||||
  if (!load_gl_symbol ("glFenceSync", (void **) &meta_gl_fence_sync))
 | 
			
		||||
    goto out;
 | 
			
		||||
 | 
			
		||||
  success = TRUE;
 | 
			
		||||
 out:
 | 
			
		||||
  return success;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_sync_insert (MetaSync *self)
 | 
			
		||||
{
 | 
			
		||||
  g_return_if_fail (self->state == META_SYNC_STATE_READY);
 | 
			
		||||
 | 
			
		||||
  XSyncTriggerFence (self->xdisplay, self->xfence);
 | 
			
		||||
  XFlush (self->xdisplay);
 | 
			
		||||
 | 
			
		||||
  meta_gl_wait_sync (self->gl_x11_sync, 0, GL_TIMEOUT_IGNORED);
 | 
			
		||||
  self->gpu_fence = meta_gl_fence_sync (GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
 | 
			
		||||
 | 
			
		||||
  self->state = META_SYNC_STATE_WAITING;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GLenum
 | 
			
		||||
meta_sync_check_update_finished (MetaSync *self,
 | 
			
		||||
                                 GLuint64  timeout)
 | 
			
		||||
{
 | 
			
		||||
  GLenum status = GL_WAIT_FAILED;
 | 
			
		||||
 | 
			
		||||
  switch (self->state)
 | 
			
		||||
    {
 | 
			
		||||
    case META_SYNC_STATE_DONE:
 | 
			
		||||
      status = GL_ALREADY_SIGNALED;
 | 
			
		||||
      break;
 | 
			
		||||
    case META_SYNC_STATE_WAITING:
 | 
			
		||||
      status = meta_gl_client_wait_sync (self->gpu_fence, 0, timeout);
 | 
			
		||||
      if (status == GL_ALREADY_SIGNALED || status == GL_CONDITION_SATISFIED)
 | 
			
		||||
        {
 | 
			
		||||
          self->state = META_SYNC_STATE_DONE;
 | 
			
		||||
          meta_gl_delete_sync (self->gpu_fence);
 | 
			
		||||
          self->gpu_fence = 0;
 | 
			
		||||
        }
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_warn_if_fail (status != GL_WAIT_FAILED);
 | 
			
		||||
 | 
			
		||||
  return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_sync_reset (MetaSync *self)
 | 
			
		||||
{
 | 
			
		||||
  XSyncAlarmAttributes attrs;
 | 
			
		||||
  int overflow;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (self->state == META_SYNC_STATE_DONE);
 | 
			
		||||
 | 
			
		||||
  XSyncResetFence (self->xdisplay, self->xfence);
 | 
			
		||||
 | 
			
		||||
  attrs.trigger.wait_value = self->next_counter_value;
 | 
			
		||||
 | 
			
		||||
  XSyncChangeAlarm (self->xdisplay, self->xalarm, XSyncCAValue, &attrs);
 | 
			
		||||
  XSyncSetCounter (self->xdisplay, self->xcounter, self->next_counter_value);
 | 
			
		||||
 | 
			
		||||
  XSyncValueAdd (&self->next_counter_value,
 | 
			
		||||
                 self->next_counter_value,
 | 
			
		||||
                 SYNC_VALUE_ONE,
 | 
			
		||||
                 &overflow);
 | 
			
		||||
 | 
			
		||||
  self->state = META_SYNC_STATE_RESET_PENDING;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_sync_handle_event (MetaSync              *self,
 | 
			
		||||
                        XSyncAlarmNotifyEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  g_return_if_fail (event->alarm == self->xalarm);
 | 
			
		||||
  g_return_if_fail (self->state == META_SYNC_STATE_RESET_PENDING);
 | 
			
		||||
 | 
			
		||||
  self->state = META_SYNC_STATE_READY;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaSync *
 | 
			
		||||
meta_sync_new (Display *xdisplay)
 | 
			
		||||
{
 | 
			
		||||
  MetaSync *self;
 | 
			
		||||
  XSyncAlarmAttributes attrs;
 | 
			
		||||
 | 
			
		||||
  self = g_malloc0 (sizeof (MetaSync));
 | 
			
		||||
 | 
			
		||||
  self->xdisplay = xdisplay;
 | 
			
		||||
 | 
			
		||||
  self->xfence = XSyncCreateFence (xdisplay, DefaultRootWindow (xdisplay), FALSE);
 | 
			
		||||
  self->gl_x11_sync = 0;
 | 
			
		||||
  self->gpu_fence = 0;
 | 
			
		||||
 | 
			
		||||
  self->xcounter = XSyncCreateCounter (xdisplay, SYNC_VALUE_ZERO);
 | 
			
		||||
 | 
			
		||||
  attrs.trigger.counter = self->xcounter;
 | 
			
		||||
  attrs.trigger.value_type = XSyncAbsolute;
 | 
			
		||||
  attrs.trigger.wait_value = SYNC_VALUE_ONE;
 | 
			
		||||
  attrs.trigger.test_type = XSyncPositiveTransition;
 | 
			
		||||
  attrs.events = TRUE;
 | 
			
		||||
  self->xalarm = XSyncCreateAlarm (xdisplay,
 | 
			
		||||
                                   XSyncCACounter |
 | 
			
		||||
                                   XSyncCAValueType |
 | 
			
		||||
                                   XSyncCAValue |
 | 
			
		||||
                                   XSyncCATestType |
 | 
			
		||||
                                   XSyncCAEvents,
 | 
			
		||||
                                   &attrs);
 | 
			
		||||
 | 
			
		||||
  XSyncIntToValue (&self->next_counter_value, 1);
 | 
			
		||||
 | 
			
		||||
  self->state = META_SYNC_STATE_READY;
 | 
			
		||||
 | 
			
		||||
  return self;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_sync_import (MetaSync *self)
 | 
			
		||||
{
 | 
			
		||||
  g_return_if_fail (self->gl_x11_sync == 0);
 | 
			
		||||
  self->gl_x11_sync = meta_gl_import_sync (GL_SYNC_X11_FENCE_EXT, self->xfence, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static Bool
 | 
			
		||||
alarm_event_predicate (Display  *dpy,
 | 
			
		||||
                       XEvent   *event,
 | 
			
		||||
                       XPointer  data)
 | 
			
		||||
{
 | 
			
		||||
  MetaSyncRing *ring = meta_sync_ring_get ();
 | 
			
		||||
 | 
			
		||||
  if (!ring)
 | 
			
		||||
    return False;
 | 
			
		||||
 | 
			
		||||
  if (event->type == ring->xsync_event_base + XSyncAlarmNotify)
 | 
			
		||||
    {
 | 
			
		||||
      if (((MetaSync *) data)->xalarm == ((XSyncAlarmNotifyEvent *) event)->alarm)
 | 
			
		||||
        return True;
 | 
			
		||||
    }
 | 
			
		||||
  return False;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_sync_free (MetaSync *self)
 | 
			
		||||
{
 | 
			
		||||
  /* When our assumptions don't hold, something has gone wrong but we
 | 
			
		||||
   * don't know what, so we reboot the ring. While doing that, we
 | 
			
		||||
   * trigger fences before deleting them to try to get ourselves out
 | 
			
		||||
   * of a potentially stuck GPU state.
 | 
			
		||||
   */
 | 
			
		||||
  switch (self->state)
 | 
			
		||||
    {
 | 
			
		||||
    case META_SYNC_STATE_WAITING:
 | 
			
		||||
      meta_gl_delete_sync (self->gpu_fence);
 | 
			
		||||
      break;
 | 
			
		||||
    case META_SYNC_STATE_DONE:
 | 
			
		||||
      /* nothing to do */
 | 
			
		||||
      break;
 | 
			
		||||
    case META_SYNC_STATE_RESET_PENDING:
 | 
			
		||||
      {
 | 
			
		||||
        XEvent event;
 | 
			
		||||
        XIfEvent (self->xdisplay, &event, alarm_event_predicate, (XPointer) self);
 | 
			
		||||
        meta_sync_handle_event (self, (XSyncAlarmNotifyEvent *) &event);
 | 
			
		||||
      }
 | 
			
		||||
      /* fall through */
 | 
			
		||||
    case META_SYNC_STATE_READY:
 | 
			
		||||
      XSyncTriggerFence (self->xdisplay, self->xfence);
 | 
			
		||||
      XFlush (self->xdisplay);
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_gl_delete_sync (self->gl_x11_sync);
 | 
			
		||||
  XSyncDestroyFence (self->xdisplay, self->xfence);
 | 
			
		||||
  XSyncDestroyCounter (self->xdisplay, self->xcounter);
 | 
			
		||||
  XSyncDestroyAlarm (self->xdisplay, self->xalarm);
 | 
			
		||||
 | 
			
		||||
  g_free (self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_sync_ring_init (Display *xdisplay)
 | 
			
		||||
{
 | 
			
		||||
  gint major, minor;
 | 
			
		||||
  guint i;
 | 
			
		||||
  MetaSyncRing *ring = meta_sync_ring_get ();
 | 
			
		||||
 | 
			
		||||
  if (!ring)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (xdisplay != NULL, FALSE);
 | 
			
		||||
  g_return_val_if_fail (ring->xdisplay == NULL, FALSE);
 | 
			
		||||
 | 
			
		||||
  if (!load_required_symbols ())
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  if (!XSyncQueryExtension (xdisplay, &ring->xsync_event_base, &ring->xsync_error_base) ||
 | 
			
		||||
      !XSyncInitialize (xdisplay, &major, &minor))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  XSyncIntToValue (&SYNC_VALUE_ZERO, 0);
 | 
			
		||||
  XSyncIntToValue (&SYNC_VALUE_ONE, 1);
 | 
			
		||||
 | 
			
		||||
  ring->xdisplay = xdisplay;
 | 
			
		||||
 | 
			
		||||
  ring->alarm_to_sync = g_hash_table_new (NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < NUM_SYNCS; ++i)
 | 
			
		||||
    {
 | 
			
		||||
      MetaSync *sync = meta_sync_new (ring->xdisplay);
 | 
			
		||||
      ring->syncs_array[i] = sync;
 | 
			
		||||
      g_hash_table_replace (ring->alarm_to_sync, (gpointer) sync->xalarm, sync);
 | 
			
		||||
    }
 | 
			
		||||
  /* Since the connection we create the X fences on isn't the same as
 | 
			
		||||
   * the one used for the GLX context, we need to XSync() here to
 | 
			
		||||
   * ensure glImportSync() succeeds. */
 | 
			
		||||
  XSync (xdisplay, False);
 | 
			
		||||
  for (i = 0; i < NUM_SYNCS; ++i)
 | 
			
		||||
    meta_sync_import (ring->syncs_array[i]);
 | 
			
		||||
 | 
			
		||||
  ring->current_sync_idx = 0;
 | 
			
		||||
  ring->current_sync = ring->syncs_array[0];
 | 
			
		||||
  ring->warmup_syncs = 0;
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_sync_ring_destroy (void)
 | 
			
		||||
{
 | 
			
		||||
  guint i;
 | 
			
		||||
  MetaSyncRing *ring = meta_sync_ring_get ();
 | 
			
		||||
 | 
			
		||||
  if (!ring)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (ring->xdisplay != NULL);
 | 
			
		||||
 | 
			
		||||
  ring->current_sync_idx = 0;
 | 
			
		||||
  ring->current_sync = NULL;
 | 
			
		||||
  ring->warmup_syncs = 0;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < NUM_SYNCS; ++i)
 | 
			
		||||
    meta_sync_free (ring->syncs_array[i]);
 | 
			
		||||
 | 
			
		||||
  g_hash_table_destroy (ring->alarm_to_sync);
 | 
			
		||||
 | 
			
		||||
  ring->xsync_event_base = 0;
 | 
			
		||||
  ring->xsync_error_base = 0;
 | 
			
		||||
  ring->xdisplay = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
meta_sync_ring_reboot (Display *xdisplay)
 | 
			
		||||
{
 | 
			
		||||
  MetaSyncRing *ring = meta_sync_ring_get ();
 | 
			
		||||
 | 
			
		||||
  if (!ring)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  meta_sync_ring_destroy ();
 | 
			
		||||
 | 
			
		||||
  ring->reboots += 1;
 | 
			
		||||
 | 
			
		||||
  if (!meta_sync_ring_get ())
 | 
			
		||||
    {
 | 
			
		||||
      meta_warning ("MetaSyncRing: Too many reboots -- disabling\n");
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return meta_sync_ring_init (xdisplay);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_sync_ring_after_frame (void)
 | 
			
		||||
{
 | 
			
		||||
  MetaSyncRing *ring = meta_sync_ring_get ();
 | 
			
		||||
 | 
			
		||||
  if (!ring)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (ring->xdisplay != NULL, FALSE);
 | 
			
		||||
 | 
			
		||||
  if (ring->warmup_syncs >= NUM_SYNCS / 2)
 | 
			
		||||
    {
 | 
			
		||||
      guint reset_sync_idx = (ring->current_sync_idx + NUM_SYNCS - (NUM_SYNCS / 2)) % NUM_SYNCS;
 | 
			
		||||
      MetaSync *sync_to_reset = ring->syncs_array[reset_sync_idx];
 | 
			
		||||
 | 
			
		||||
      GLenum status = meta_sync_check_update_finished (sync_to_reset, 0);
 | 
			
		||||
      if (status == GL_TIMEOUT_EXPIRED)
 | 
			
		||||
        {
 | 
			
		||||
          meta_warning ("MetaSyncRing: We should never wait for a sync -- add more syncs?\n");
 | 
			
		||||
          status = meta_sync_check_update_finished (sync_to_reset, MAX_SYNC_WAIT_TIME);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (status != GL_ALREADY_SIGNALED && status != GL_CONDITION_SATISFIED)
 | 
			
		||||
        {
 | 
			
		||||
          meta_warning ("MetaSyncRing: Timed out waiting for sync object.\n");
 | 
			
		||||
          return meta_sync_ring_reboot (ring->xdisplay);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      meta_sync_reset (sync_to_reset);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      ring->warmup_syncs += 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  ring->current_sync_idx += 1;
 | 
			
		||||
  ring->current_sync_idx %= NUM_SYNCS;
 | 
			
		||||
 | 
			
		||||
  ring->current_sync = ring->syncs_array[ring->current_sync_idx];
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_sync_ring_insert_wait (void)
 | 
			
		||||
{
 | 
			
		||||
  MetaSyncRing *ring = meta_sync_ring_get ();
 | 
			
		||||
 | 
			
		||||
  if (!ring)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  g_return_val_if_fail (ring->xdisplay != NULL, FALSE);
 | 
			
		||||
 | 
			
		||||
  if (ring->current_sync->state != META_SYNC_STATE_READY)
 | 
			
		||||
    {
 | 
			
		||||
      meta_warning ("MetaSyncRing: Sync object is not ready -- were events handled properly?\n");
 | 
			
		||||
      if (!meta_sync_ring_reboot (ring->xdisplay))
 | 
			
		||||
        return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_sync_insert (ring->current_sync);
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_sync_ring_handle_event (XEvent *xevent)
 | 
			
		||||
{
 | 
			
		||||
  XSyncAlarmNotifyEvent *event;
 | 
			
		||||
  MetaSync *sync;
 | 
			
		||||
  MetaSyncRing *ring = meta_sync_ring_get ();
 | 
			
		||||
 | 
			
		||||
  if (!ring)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  g_return_if_fail (ring->xdisplay != NULL);
 | 
			
		||||
 | 
			
		||||
  if (xevent->type != (ring->xsync_event_base + XSyncAlarmNotify))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  event = (XSyncAlarmNotifyEvent *) xevent;
 | 
			
		||||
 | 
			
		||||
  sync = g_hash_table_lookup (ring->alarm_to_sync, (gpointer) event->alarm);
 | 
			
		||||
  if (sync)
 | 
			
		||||
    meta_sync_handle_event (sync, event);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										14
									
								
								src/compositor/meta-sync-ring.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/compositor/meta-sync-ring.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
#ifndef _META_SYNC_RING_H_
 | 
			
		||||
#define _META_SYNC_RING_H_
 | 
			
		||||
 | 
			
		||||
#include <glib.h>
 | 
			
		||||
 | 
			
		||||
#include <X11/Xlib.h>
 | 
			
		||||
 | 
			
		||||
gboolean meta_sync_ring_init (Display *dpy);
 | 
			
		||||
void meta_sync_ring_destroy (void);
 | 
			
		||||
gboolean meta_sync_ring_after_frame (void);
 | 
			
		||||
gboolean meta_sync_ring_insert_wait (void);
 | 
			
		||||
void meta_sync_ring_handle_event (XEvent *event);
 | 
			
		||||
 | 
			
		||||
#endif  /* _META_SYNC_RING_H_ */
 | 
			
		||||
@@ -493,11 +493,10 @@ place_window_if_needed(MetaWindow     *window,
 | 
			
		||||
  if (window->placed || did_placement)
 | 
			
		||||
    {
 | 
			
		||||
      if (window->maximize_horizontally_after_placement ||
 | 
			
		||||
          window->maximize_vertically_after_placement   ||
 | 
			
		||||
          window->fullscreen_after_placement)
 | 
			
		||||
          window->maximize_vertically_after_placement)
 | 
			
		||||
        {
 | 
			
		||||
          /* define a sane saved_rect so that the user can unmaximize or
 | 
			
		||||
           * make unfullscreen to something reasonable.
 | 
			
		||||
          /* define a sane saved_rect so that the user can unmaximize to
 | 
			
		||||
           * something reasonable.
 | 
			
		||||
           */
 | 
			
		||||
          if (info->current.width >= info->work_area_monitor.width)
 | 
			
		||||
            {
 | 
			
		||||
@@ -525,15 +524,6 @@ place_window_if_needed(MetaWindow     *window,
 | 
			
		||||
                (window->maximize_vertically_after_placement ?
 | 
			
		||||
                 META_MAXIMIZE_VERTICAL : 0), &info->current);
 | 
			
		||||
 | 
			
		||||
          if (window->fullscreen_after_placement)
 | 
			
		||||
            {
 | 
			
		||||
              window->saved_rect = info->current;
 | 
			
		||||
              window->fullscreen = TRUE;
 | 
			
		||||
              window->fullscreen_after_placement = FALSE;
 | 
			
		||||
 | 
			
		||||
              g_object_notify (G_OBJECT (window), "fullscreen");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          window->maximize_horizontally_after_placement = FALSE;
 | 
			
		||||
          window->maximize_vertically_after_placement = FALSE;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -160,12 +160,7 @@ void
 | 
			
		||||
meta_window_set_alive (MetaWindow *window,
 | 
			
		||||
                       gboolean    is_alive)
 | 
			
		||||
{
 | 
			
		||||
  if (window->is_alive == is_alive)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  window->is_alive = is_alive;
 | 
			
		||||
 | 
			
		||||
  if (window->is_alive)
 | 
			
		||||
  if (is_alive)
 | 
			
		||||
    kill_delete_dialog (window);
 | 
			
		||||
  else
 | 
			
		||||
    show_delete_dialog (window, CurrentTime);
 | 
			
		||||
 
 | 
			
		||||
@@ -93,6 +93,15 @@ handle_idletime_for_event (const ClutterEvent *event)
 | 
			
		||||
      if (device == NULL)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
      if (event->any.flags & CLUTTER_EVENT_FLAG_SYNTHETIC ||
 | 
			
		||||
          event->type == CLUTTER_ENTER ||
 | 
			
		||||
          event->type == CLUTTER_LEAVE ||
 | 
			
		||||
          event->type == CLUTTER_STAGE_STATE ||
 | 
			
		||||
          event->type == CLUTTER_DESTROY_NOTIFY ||
 | 
			
		||||
          event->type == CLUTTER_CLIENT_MESSAGE ||
 | 
			
		||||
          event->type == CLUTTER_DELETE)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
      device_id = clutter_input_device_get_device_id (device);
 | 
			
		||||
 | 
			
		||||
      core_monitor = meta_idle_monitor_get_core ();
 | 
			
		||||
@@ -192,6 +201,7 @@ meta_display_handle_event (MetaDisplay        *display,
 | 
			
		||||
    {
 | 
			
		||||
      MetaCursorTracker *tracker = meta_cursor_tracker_get_for_screen (NULL);
 | 
			
		||||
      meta_cursor_tracker_update_position (tracker, event->motion.x, event->motion.y);
 | 
			
		||||
      display->monitor_cache_invalidated = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  handle_idletime_for_event (event);
 | 
			
		||||
 
 | 
			
		||||
@@ -1273,16 +1273,13 @@ get_default_focus_window (MetaStack     *stack,
 | 
			
		||||
      if (window->unmaps_pending > 0)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (window->minimized)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (window->unmanaging)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (!(window->input || window->take_focus))
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (workspace != NULL && !meta_window_located_on_workspace (window, workspace))
 | 
			
		||||
      if (!meta_window_should_be_showing (window))
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (must_be_at_point && !window_contains_point (window, root_x, root_y))
 | 
			
		||||
 
 | 
			
		||||
@@ -175,9 +175,6 @@ struct _MetaWindow
 | 
			
		||||
  /* Whether the window is marked as urgent */
 | 
			
		||||
  guint urgent : 1;
 | 
			
		||||
 | 
			
		||||
  /* Whether we have to fullscreen after placement */
 | 
			
		||||
  guint fullscreen_after_placement : 1;
 | 
			
		||||
 | 
			
		||||
  /* Area to cover when in fullscreen mode.  If _NET_WM_FULLSCREEN_MONITORS has
 | 
			
		||||
   * 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
 | 
			
		||||
@@ -434,7 +431,6 @@ struct _MetaWindow
 | 
			
		||||
 | 
			
		||||
  /* Managed by delete.c */
 | 
			
		||||
  int dialog_pid;
 | 
			
		||||
  guint is_alive : 1;
 | 
			
		||||
 | 
			
		||||
  /* maintained by group.c */
 | 
			
		||||
  MetaGroup *group;
 | 
			
		||||
 
 | 
			
		||||
@@ -873,7 +873,6 @@ _meta_window_shared_new (MetaDisplay         *display,
 | 
			
		||||
  window->maximize_vertically_after_placement = FALSE;
 | 
			
		||||
  window->minimize_after_placement = FALSE;
 | 
			
		||||
  window->fullscreen = FALSE;
 | 
			
		||||
  window->fullscreen_after_placement = FALSE;
 | 
			
		||||
  window->fullscreen_monitors[0] = -1;
 | 
			
		||||
  window->require_fully_onscreen = TRUE;
 | 
			
		||||
  window->require_on_single_monitor = TRUE;
 | 
			
		||||
@@ -6401,7 +6400,7 @@ find_ancestor_func (MetaWindow *window,
 | 
			
		||||
 * so by traversing the @transient's ancestors until it either locates @window
 | 
			
		||||
 * or reaches an ancestor that is not transient.
 | 
			
		||||
 *
 | 
			
		||||
 * Return Value: (transfer none): %TRUE if window is an ancestor of transient.
 | 
			
		||||
 * Return Value: %TRUE if window is an ancestor of transient.
 | 
			
		||||
 */
 | 
			
		||||
gboolean
 | 
			
		||||
meta_window_is_ancestor_of_transient (MetaWindow *window,
 | 
			
		||||
@@ -7139,7 +7138,7 @@ meta_window_get_transient_for (MetaWindow *window)
 | 
			
		||||
 * Returns pid of the process that created this window, if known (obtained from
 | 
			
		||||
 * the _NET_WM_PID property).
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: (transfer none): the pid, or -1 if not known.
 | 
			
		||||
 * Return value: the pid, or -1 if not known.
 | 
			
		||||
 */
 | 
			
		||||
int
 | 
			
		||||
meta_window_get_pid (MetaWindow *window)
 | 
			
		||||
 
 | 
			
		||||
@@ -1053,6 +1053,11 @@ meta_frame_left_click_event (MetaUIFrame *frame,
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return TRUE;
 | 
			
		||||
    case META_FRAME_CONTROL_NONE:
 | 
			
		||||
      /* We can get this for example when trying to resize window
 | 
			
		||||
       * that cannot be resized (e. g. it is maximized and the theme
 | 
			
		||||
       * currently used has borders for maximized windows), see #751884 */
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    default:
 | 
			
		||||
      g_assert_not_reached ();
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -115,7 +115,7 @@ struct _MetaFrameGeometry
 | 
			
		||||
 | 
			
		||||
  /* used for a memset hack */
 | 
			
		||||
#define ADDRESS_OF_BUTTON_RECTS(fgeom) (((char*)(fgeom)) + G_STRUCT_OFFSET (MetaFrameGeometry, close_rect))
 | 
			
		||||
#define LENGTH_OF_BUTTON_RECTS (G_STRUCT_OFFSET (MetaFrameGeometry, unstick_rect) + sizeof (GdkRectangle) - G_STRUCT_OFFSET (MetaFrameGeometry, close_rect))
 | 
			
		||||
#define LENGTH_OF_BUTTON_RECTS (G_STRUCT_OFFSET (MetaFrameGeometry, unstick_rect) + sizeof (MetaButtonSpace) - G_STRUCT_OFFSET (MetaFrameGeometry, close_rect))
 | 
			
		||||
 | 
			
		||||
  /* The button rects (if changed adjust memset hack) */
 | 
			
		||||
  MetaButtonSpace close_rect;
 | 
			
		||||
 
 | 
			
		||||
@@ -371,7 +371,7 @@ static void
 | 
			
		||||
destroy_data_device_icon (struct wl_listener *listener, void *data)
 | 
			
		||||
{
 | 
			
		||||
  MetaWaylandDragGrab *drag_grab =
 | 
			
		||||
    wl_container_of (listener, drag_grab, drag_data_source_listener);
 | 
			
		||||
    wl_container_of (listener, drag_grab, drag_icon_listener);
 | 
			
		||||
 | 
			
		||||
  drag_grab->drag_surface = NULL;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -690,7 +690,8 @@ meta_spew_event_print (MetaDisplay *display,
 | 
			
		||||
static gboolean
 | 
			
		||||
handle_window_focus_event (MetaDisplay  *display,
 | 
			
		||||
                           MetaWindow   *window,
 | 
			
		||||
                           XIEnterEvent *event)
 | 
			
		||||
                           XIEnterEvent *event,
 | 
			
		||||
                           unsigned long serial)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindow *focus_window;
 | 
			
		||||
#ifdef WITH_VERBOSE_MODE
 | 
			
		||||
@@ -725,7 +726,7 @@ handle_window_focus_event (MetaDisplay  *display,
 | 
			
		||||
              event->event, window_type,
 | 
			
		||||
              meta_event_mode_to_string (event->mode),
 | 
			
		||||
              meta_event_detail_to_string (event->mode),
 | 
			
		||||
              event->serial);
 | 
			
		||||
              serial);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  /* FIXME our pointer tracking is broken; see how
 | 
			
		||||
@@ -769,7 +770,7 @@ handle_window_focus_event (MetaDisplay  *display,
 | 
			
		||||
  if (event->evtype == XI_FocusIn)
 | 
			
		||||
    {
 | 
			
		||||
      display->server_focus_window = event->event;
 | 
			
		||||
      display->server_focus_serial = event->serial;
 | 
			
		||||
      display->server_focus_serial = serial;
 | 
			
		||||
      focus_window = window;
 | 
			
		||||
    }
 | 
			
		||||
  else if (event->evtype == XI_FocusOut)
 | 
			
		||||
@@ -783,7 +784,7 @@ handle_window_focus_event (MetaDisplay  *display,
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      display->server_focus_window = None;
 | 
			
		||||
      display->server_focus_serial = event->serial;
 | 
			
		||||
      display->server_focus_serial = serial;
 | 
			
		||||
      focus_window = NULL;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
@@ -828,8 +829,9 @@ crossing_serial_is_ignored (MetaDisplay  *display,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
handle_input_xevent (MetaDisplay *display,
 | 
			
		||||
                     XIEvent     *input_event)
 | 
			
		||||
handle_input_xevent (MetaDisplay  *display,
 | 
			
		||||
                     XIEvent      *input_event,
 | 
			
		||||
                     unsigned long serial)
 | 
			
		||||
{
 | 
			
		||||
  XIEnterEvent *enter_event = (XIEnterEvent *) input_event;
 | 
			
		||||
  Window modified;
 | 
			
		||||
@@ -866,7 +868,7 @@ handle_input_xevent (MetaDisplay *display,
 | 
			
		||||
      /* Check if we've entered a window; do this even if window->has_focus to
 | 
			
		||||
       * avoid races.
 | 
			
		||||
       */
 | 
			
		||||
      if (window && !crossing_serial_is_ignored (display, input_event->serial) &&
 | 
			
		||||
      if (window && !crossing_serial_is_ignored (display, serial) &&
 | 
			
		||||
          enter_event->mode != XINotifyGrab &&
 | 
			
		||||
          enter_event->mode != XINotifyUngrab &&
 | 
			
		||||
          enter_event->detail != XINotifyInferior &&
 | 
			
		||||
@@ -891,7 +893,7 @@ handle_input_xevent (MetaDisplay *display,
 | 
			
		||||
      break;
 | 
			
		||||
    case XI_FocusIn:
 | 
			
		||||
    case XI_FocusOut:
 | 
			
		||||
      if (handle_window_focus_event (display, window, enter_event) &&
 | 
			
		||||
      if (handle_window_focus_event (display, window, enter_event, serial) &&
 | 
			
		||||
          enter_event->event == enter_event->root)
 | 
			
		||||
        {
 | 
			
		||||
          if (enter_event->evtype == XI_FocusIn &&
 | 
			
		||||
@@ -1726,7 +1728,7 @@ meta_display_handle_xevent (MetaDisplay *display,
 | 
			
		||||
    }
 | 
			
		||||
#endif /* HAVE_XI23 */
 | 
			
		||||
 | 
			
		||||
  if (handle_input_xevent (display, input_event))
 | 
			
		||||
  if (handle_input_xevent (display, input_event, event->xany.serial))
 | 
			
		||||
    {
 | 
			
		||||
      bypass_gtk = bypass_compositor = TRUE;
 | 
			
		||||
      goto out;
 | 
			
		||||
 
 | 
			
		||||
@@ -946,7 +946,15 @@ save_state (void)
 | 
			
		||||
 | 
			
		||||
          /* Sticky */
 | 
			
		||||
          if (window->on_all_workspaces_requested)
 | 
			
		||||
            fputs ("    <sticky/>\n", outfile);
 | 
			
		||||
            {
 | 
			
		||||
              fputs ("    <sticky/>\n", outfile);
 | 
			
		||||
            } else {
 | 
			
		||||
              int n;
 | 
			
		||||
              n = meta_workspace_index (window->workspace);
 | 
			
		||||
              fprintf (outfile,
 | 
			
		||||
                       "    <workspace index=\"%d\"/>\n", n);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
          /* Minimized */
 | 
			
		||||
          if (window->minimized)
 | 
			
		||||
@@ -963,14 +971,6 @@ save_state (void)
 | 
			
		||||
                       window->saved_rect.height);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          /* Workspaces we're on */
 | 
			
		||||
          {
 | 
			
		||||
            int n;
 | 
			
		||||
            n = meta_workspace_index (window->workspace);
 | 
			
		||||
            fprintf (outfile,
 | 
			
		||||
                     "    <workspace index=\"%d\"/>\n", n);
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          /* Gravity */
 | 
			
		||||
          {
 | 
			
		||||
            int x, y, w, h;
 | 
			
		||||
 
 | 
			
		||||
@@ -810,7 +810,10 @@ reload_net_wm_state (MetaWindow    *window,
 | 
			
		||||
      else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_SKIP_PAGER)
 | 
			
		||||
        priv->wm_state_skip_pager = TRUE;
 | 
			
		||||
      else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_FULLSCREEN)
 | 
			
		||||
        window->fullscreen_after_placement = TRUE;
 | 
			
		||||
        {
 | 
			
		||||
          window->fullscreen = TRUE;
 | 
			
		||||
          g_object_notify (G_OBJECT (window), "fullscreen");
 | 
			
		||||
        }
 | 
			
		||||
      else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_ABOVE)
 | 
			
		||||
        window->wm_state_above = TRUE;
 | 
			
		||||
      else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_BELOW)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user