Compare commits
	
		
			70 Commits
		
	
	
		
			wip/nields
			...
			cherry-pic
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					b51d32a812 | ||
| 
						 | 
					3288edf677 | ||
| 
						 | 
					fe1616668e | ||
| 
						 | 
					7d01aec48d | ||
| 
						 | 
					a41d84db00 | ||
| 
						 | 
					e73b321c2e | ||
| 
						 | 
					b6dc2052c3 | ||
| 
						 | 
					72965aaaf0 | ||
| 
						 | 
					2a6782dc10 | ||
| 
						 | 
					5142c8c7e7 | ||
| 
						 | 
					abc7ad8e9f | ||
| 
						 | 
					1a3f9a3323 | ||
| 
						 | 
					235c35182b | ||
| 
						 | 
					e4661d7870 | ||
| 
						 | 
					9d4c7e4e75 | ||
| 
						 | 
					47131b1dad | ||
| 
						 | 
					51c0130645 | ||
| 
						 | 
					2dd9fc17c1 | ||
| 
						 | 
					c7a38c3139 | ||
| 
						 | 
					7d52be0229 | ||
| 
						 | 
					41303bc01b | ||
| 
						 | 
					0d188c3898 | ||
| 
						 | 
					28eff93143 | ||
| 
						 | 
					b380aa72aa | ||
| 
						 | 
					920dc9e5a1 | ||
| 
						 | 
					32f02010ae | ||
| 
						 | 
					889c56c776 | ||
| 
						 | 
					67a4cd898e | ||
| 
						 | 
					43d6c0ea61 | ||
| 
						 | 
					2872bb1f2a | ||
| 
						 | 
					1c00cd5ca3 | ||
| 
						 | 
					2919a7f25f | ||
| 
						 | 
					ca0d56a3a4 | ||
| 
						 | 
					a89baa44ab | ||
| 
						 | 
					7076a48bcf | ||
| 
						 | 
					1b439c42d1 | ||
| 
						 | 
					928a40f328 | ||
| 
						 | 
					59397266ed | ||
| 
						 | 
					d0147591b3 | ||
| 
						 | 
					25c7e52ada | ||
| 
						 | 
					99d766c044 | ||
| 
						 | 
					fcd4c816c4 | ||
| 
						 | 
					2a63a47d5a | ||
| 
						 | 
					c80e2c9ae5 | ||
| 
						 | 
					d3d5eb8e1b | ||
| 
						 | 
					4837cec89f | ||
| 
						 | 
					32329e6c00 | ||
| 
						 | 
					89261be556 | ||
| 
						 | 
					e3e76d658b | ||
| 
						 | 
					34644b2133 | ||
| 
						 | 
					7da4e8cf14 | ||
| 
						 | 
					23c3f8bb18 | ||
| 
						 | 
					60866e0f85 | ||
| 
						 | 
					45c02645f3 | ||
| 
						 | 
					e515e37a7e | ||
| 
						 | 
					957f4ec69d | ||
| 
						 | 
					a98eb107be | ||
| 
						 | 
					1851fa2bd0 | ||
| 
						 | 
					de7d7bbf3d | ||
| 
						 | 
					7ac551cd05 | ||
| 
						 | 
					8696a79477 | ||
| 
						 | 
					b2f9de98d0 | ||
| 
						 | 
					2da2489da5 | ||
| 
						 | 
					31779404f0 | ||
| 
						 | 
					b096c0ac33 | ||
| 
						 | 
					44a7f74dcd | ||
| 
						 | 
					3832c6b607 | ||
| 
						 | 
					14b7e79d3c | ||
| 
						 | 
					e99b0b9368 | ||
| 
						 | 
					de294f34bb | 
							
								
								
									
										32
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								NEWS
									
									
									
									
									
								
							@@ -1,3 +1,35 @@
 | 
			
		||||
3.28.2
 | 
			
		||||
======
 | 
			
		||||
* Take inhibitors into account for monitoring idle [Bastien; #705942]
 | 
			
		||||
* Fix window animations on wayland [Georges; #780292]
 | 
			
		||||
* Misc. bug fixes [Mario, Jonas, Olivier, Florian; gnome-shell#157, #130,
 | 
			
		||||
  #21, #124, !96, #138, !102, #781471]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Jonas Ådahl, Olivier Fourdan, Carlos Garnacho, Florian Müllner,
 | 
			
		||||
  Georges Basile Stavracas Neto, Bastien Nocera, Mario Sanchez Prada,
 | 
			
		||||
  Ray Strode, Marco Trevisan (Treviño)
 | 
			
		||||
 | 
			
		||||
3.28.1
 | 
			
		||||
======
 | 
			
		||||
* Fix various input-method regressions [Carlos; #65, #74, #66]
 | 
			
		||||
* Fix wayland build on FreeBSD [Ting-Wei; #792280, #792717]
 | 
			
		||||
* Fix swapped colors in screenshots (again) [Carlos; #72]
 | 
			
		||||
* Allow building with elogind [Rasmus; !46]
 | 
			
		||||
* Consider display rotation for cursor [Olivier; #85]
 | 
			
		||||
* Fall back to non-modifier GBM surfaces [Daniel; #84]
 | 
			
		||||
* Disable KMS modifiers by default [Jonas; #81]
 | 
			
		||||
* Misc bug fixes [handsome-feng; !45]
 | 
			
		||||
 | 
			
		||||
Contributors:
 | 
			
		||||
  Jonas Ådahl, Olivier Fourdan, Carlos Garnacho, handsome-feng, Yussuf Khalil,
 | 
			
		||||
  Ting-Wei Lan, Aleksandr Mezin, Alberts Muktupāvels,
 | 
			
		||||
  Georges Basile Stavracas Neto, Benjamin Otte, Daniel Stone, Rasmus Thomsen,
 | 
			
		||||
  Marco Trevisan (Treviño), Daniel van Vugt
 | 
			
		||||
 | 
			
		||||
Translators:
 | 
			
		||||
  Emin Tufan Çetin [tr], Dušan Kazik [sk], Matej Urbančič [sl]
 | 
			
		||||
 | 
			
		||||
3.28.0
 | 
			
		||||
======
 | 
			
		||||
* Fix xdg-foreign regression [Carlos; #63]
 | 
			
		||||
 
 | 
			
		||||
@@ -692,7 +692,7 @@ Cally_@LIBMUTTER_API_VERSION@_gir_CFLAGS = $(AM_CPPFLAGS) $(CLUTTER_CFLAGS)
 | 
			
		||||
Cally_@LIBMUTTER_API_VERSION@_gir_SCANNERFLAGS = \
 | 
			
		||||
	--warn-all \
 | 
			
		||||
	--c-include='cally/cally.h' \
 | 
			
		||||
	--pkg-export=mutter-cally-@LIBMUTTER_API_VERSION@ \
 | 
			
		||||
	--pkg-export=mutter-clutter-@LIBMUTTER_API_VERSION@ \
 | 
			
		||||
	--include-uninstalled=$(top_builddir)/clutter/Clutter-@LIBMUTTER_API_VERSION@.gir
 | 
			
		||||
 | 
			
		||||
INTROSPECTION_GIRS += Cally-@LIBMUTTER_API_VERSION@.gir
 | 
			
		||||
 
 | 
			
		||||
@@ -353,6 +353,7 @@ clutter_input_method_notify_key_event (ClutterInputMethod *im,
 | 
			
		||||
      copy = clutter_event_copy (event);
 | 
			
		||||
      clutter_event_set_flags (copy, clutter_event_get_flags (event) |
 | 
			
		||||
                               CLUTTER_EVENT_FLAG_INPUT_METHOD);
 | 
			
		||||
      clutter_event_set_source_device (copy, clutter_event_get_device (copy));
 | 
			
		||||
      clutter_event_put (copy);
 | 
			
		||||
      clutter_event_free (copy);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -2830,6 +2830,10 @@ clutter_text_key_focus_in (ClutterActor *actor)
 | 
			
		||||
  if (method && priv->editable)
 | 
			
		||||
    {
 | 
			
		||||
      clutter_input_method_focus_in (method, priv->input_focus);
 | 
			
		||||
      clutter_input_focus_set_content_purpose (priv->input_focus,
 | 
			
		||||
					       priv->input_purpose);
 | 
			
		||||
      clutter_input_focus_set_content_hints (priv->input_focus,
 | 
			
		||||
					     priv->input_hints);
 | 
			
		||||
      update_cursor_location (CLUTTER_TEXT (actor));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -4511,6 +4515,27 @@ buffer_deleted_text (ClutterTextBuffer *buffer,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
clutter_text_queue_redraw_or_relayout (ClutterText *self)
 | 
			
		||||
{
 | 
			
		||||
  ClutterActor *actor = CLUTTER_ACTOR (self);
 | 
			
		||||
  gfloat preferred_width;
 | 
			
		||||
  gfloat preferred_height;
 | 
			
		||||
 | 
			
		||||
  clutter_text_dirty_cache (self);
 | 
			
		||||
 | 
			
		||||
  /* we're using our private implementations here to avoid the caching done by ClutterActor */
 | 
			
		||||
  clutter_text_get_preferred_width (actor, -1, NULL, &preferred_width);
 | 
			
		||||
  clutter_text_get_preferred_height (actor, preferred_width, NULL, &preferred_height);
 | 
			
		||||
 | 
			
		||||
  if (clutter_actor_has_allocation (actor) &&
 | 
			
		||||
      (fabsf (preferred_width - clutter_actor_get_width (actor)) > 0.001 ||
 | 
			
		||||
       fabsf (preferred_height - clutter_actor_get_height (actor)) > 0.001))
 | 
			
		||||
    clutter_actor_queue_relayout (actor);
 | 
			
		||||
  else
 | 
			
		||||
    clutter_text_queue_redraw (actor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
buffer_notify_text (ClutterTextBuffer *buffer,
 | 
			
		||||
                    GParamSpec        *spec,
 | 
			
		||||
@@ -4518,9 +4543,7 @@ buffer_notify_text (ClutterTextBuffer *buffer,
 | 
			
		||||
{
 | 
			
		||||
  g_object_freeze_notify (G_OBJECT (self));
 | 
			
		||||
 | 
			
		||||
  clutter_text_dirty_cache (self);
 | 
			
		||||
 | 
			
		||||
  clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
 | 
			
		||||
  clutter_text_queue_redraw_or_relayout (self);
 | 
			
		||||
 | 
			
		||||
  g_signal_emit (self, text_signals[TEXT_CHANGED], 0);
 | 
			
		||||
  g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_TEXT]);
 | 
			
		||||
@@ -4872,8 +4895,7 @@ clutter_text_set_cursor_visible (ClutterText *self,
 | 
			
		||||
    {
 | 
			
		||||
      priv->cursor_visible = cursor_visible;
 | 
			
		||||
 | 
			
		||||
      clutter_text_dirty_cache (self);
 | 
			
		||||
      clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
 | 
			
		||||
      clutter_text_queue_redraw_or_relayout (self);
 | 
			
		||||
 | 
			
		||||
      g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_CURSOR_VISIBLE]);
 | 
			
		||||
    }
 | 
			
		||||
@@ -5774,9 +5796,7 @@ clutter_text_set_line_alignment (ClutterText    *self,
 | 
			
		||||
    {
 | 
			
		||||
      priv->alignment = alignment;
 | 
			
		||||
 | 
			
		||||
      clutter_text_dirty_cache (self);
 | 
			
		||||
 | 
			
		||||
      clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
 | 
			
		||||
      clutter_text_queue_redraw_or_relayout (self);
 | 
			
		||||
 | 
			
		||||
      g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_LINE_ALIGNMENT]);
 | 
			
		||||
    }
 | 
			
		||||
@@ -5831,9 +5851,7 @@ clutter_text_set_use_markup (ClutterText *self,
 | 
			
		||||
  if (setting)
 | 
			
		||||
    clutter_text_set_markup_internal (self, text);
 | 
			
		||||
 | 
			
		||||
  clutter_text_dirty_cache (self);
 | 
			
		||||
 | 
			
		||||
  clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
 | 
			
		||||
  clutter_text_queue_redraw_or_relayout (self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -5880,9 +5898,7 @@ clutter_text_set_justify (ClutterText *self,
 | 
			
		||||
    {
 | 
			
		||||
      priv->justify = justify;
 | 
			
		||||
 | 
			
		||||
      clutter_text_dirty_cache (self);
 | 
			
		||||
 | 
			
		||||
      clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
 | 
			
		||||
      clutter_text_queue_redraw_or_relayout (self);
 | 
			
		||||
 | 
			
		||||
      g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_JUSTIFY]);
 | 
			
		||||
    }
 | 
			
		||||
@@ -6449,8 +6465,7 @@ clutter_text_set_preedit_string (ClutterText   *self,
 | 
			
		||||
      priv->preedit_set = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  clutter_text_dirty_cache (self);
 | 
			
		||||
  clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
 | 
			
		||||
  clutter_text_queue_redraw_or_relayout (self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -6512,7 +6527,9 @@ clutter_text_set_input_hints (ClutterText                  *self,
 | 
			
		||||
  g_return_if_fail (CLUTTER_IS_TEXT (self));
 | 
			
		||||
 | 
			
		||||
  self->priv->input_hints = hints;
 | 
			
		||||
  clutter_input_focus_set_content_hints (self->priv->input_focus, hints);
 | 
			
		||||
 | 
			
		||||
  if (clutter_input_focus_is_focused (self->priv->input_focus))
 | 
			
		||||
    clutter_input_focus_set_content_hints (self->priv->input_focus, hints);
 | 
			
		||||
  g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_INPUT_HINTS]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -6531,7 +6548,9 @@ clutter_text_set_input_purpose (ClutterText                *self,
 | 
			
		||||
  g_return_if_fail (CLUTTER_IS_TEXT (self));
 | 
			
		||||
 | 
			
		||||
  self->priv->input_purpose = purpose;
 | 
			
		||||
  clutter_input_focus_set_content_purpose (self->priv->input_focus, purpose);
 | 
			
		||||
 | 
			
		||||
  if (clutter_input_focus_is_focused (self->priv->input_focus))
 | 
			
		||||
    clutter_input_focus_set_content_purpose (self->priv->input_focus, purpose);
 | 
			
		||||
  g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_INPUT_PURPOSE]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -793,10 +793,12 @@ evdev_add_device (ClutterDeviceManagerEvdev *manager_evdev,
 | 
			
		||||
      if (priv->main_seat->libinput_seat == NULL)
 | 
			
		||||
        seat = priv->main_seat;
 | 
			
		||||
      else
 | 
			
		||||
        seat = clutter_seat_evdev_new (manager_evdev);
 | 
			
		||||
        {
 | 
			
		||||
          seat = clutter_seat_evdev_new (manager_evdev);
 | 
			
		||||
          priv->seats = g_slist_append (priv->seats, seat);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      clutter_seat_evdev_set_libinput_seat (seat, libinput_seat);
 | 
			
		||||
      priv->seats = g_slist_append (priv->seats, seat);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  device = _clutter_input_device_evdev_new (manager, seat, libinput_device);
 | 
			
		||||
@@ -919,7 +921,6 @@ clutter_device_manager_evdev_get_device (ClutterDeviceManager *manager,
 | 
			
		||||
  ClutterDeviceManagerEvdev *manager_evdev;
 | 
			
		||||
  ClutterDeviceManagerEvdevPrivate *priv;
 | 
			
		||||
  GSList *l;
 | 
			
		||||
  GSList *device_it;
 | 
			
		||||
 | 
			
		||||
  manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
 | 
			
		||||
  priv = manager_evdev->priv;
 | 
			
		||||
@@ -927,14 +928,10 @@ clutter_device_manager_evdev_get_device (ClutterDeviceManager *manager,
 | 
			
		||||
  for (l = priv->seats; l; l = l->next)
 | 
			
		||||
    {
 | 
			
		||||
      ClutterSeatEvdev *seat = l->data;
 | 
			
		||||
      ClutterInputDevice *device = clutter_seat_evdev_get_device (seat, id);
 | 
			
		||||
 | 
			
		||||
      for (device_it = seat->devices; device_it; device_it = device_it->next)
 | 
			
		||||
        {
 | 
			
		||||
          ClutterInputDevice *device = device_it->data;
 | 
			
		||||
 | 
			
		||||
          if (clutter_input_device_get_device_id (device) == id)
 | 
			
		||||
            return device;
 | 
			
		||||
        }
 | 
			
		||||
      if (device)
 | 
			
		||||
        return device;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return NULL;
 | 
			
		||||
@@ -1967,6 +1964,7 @@ clutter_device_manager_evdev_constructed (GObject *gobject)
 | 
			
		||||
  xkb_context_unref (ctx);
 | 
			
		||||
 | 
			
		||||
  priv->main_seat = clutter_seat_evdev_new (manager_evdev);
 | 
			
		||||
  priv->seats = g_slist_append (priv->seats, priv->main_seat);
 | 
			
		||||
 | 
			
		||||
  dispatch_libinput (manager_evdev);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -433,6 +433,8 @@ key_event_is_modifier (ClutterEvent *event)
 | 
			
		||||
    case XKB_KEY_Super_R:
 | 
			
		||||
    case XKB_KEY_Hyper_L:
 | 
			
		||||
    case XKB_KEY_Hyper_R:
 | 
			
		||||
    case XKB_KEY_Caps_Lock:
 | 
			
		||||
    case XKB_KEY_Shift_Lock:
 | 
			
		||||
      return TRUE;
 | 
			
		||||
    default:
 | 
			
		||||
      return FALSE;
 | 
			
		||||
@@ -584,6 +586,12 @@ handle_stickykeys_press (ClutterEvent            *event,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  depressed_mods = xkb_state_serialize_mods (seat->xkb, XKB_STATE_MODS_DEPRESSED);
 | 
			
		||||
  /* Ignore the lock modifier mask, that one cannot be sticky, yet the
 | 
			
		||||
   * CAPS_LOCK key itself counts as a modifier as it might be remapped
 | 
			
		||||
   * to some other modifier which can be sticky.
 | 
			
		||||
   */
 | 
			
		||||
  depressed_mods &= ~CLUTTER_LOCK_MASK;
 | 
			
		||||
 | 
			
		||||
  new_latched_mask = device->stickykeys_latched_mask;
 | 
			
		||||
  new_locked_mask = device->stickykeys_locked_mask;
 | 
			
		||||
 | 
			
		||||
@@ -1122,6 +1130,10 @@ clutter_input_device_evdev_process_kbd_a11y_event (ClutterEvent               *e
 | 
			
		||||
{
 | 
			
		||||
  ClutterInputDeviceEvdev *device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (device);
 | 
			
		||||
 | 
			
		||||
  /* Ignore key events injected from IM */
 | 
			
		||||
  if (event->key.flags & CLUTTER_EVENT_FLAG_INPUT_METHOD)
 | 
			
		||||
    goto emit_event;
 | 
			
		||||
 | 
			
		||||
  if (!device_evdev->a11y_flags & CLUTTER_A11Y_KEYBOARD_ENABLED)
 | 
			
		||||
    goto emit_event;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -858,6 +858,24 @@ clutter_seat_evdev_free (ClutterSeatEvdev *seat)
 | 
			
		||||
  g_free (seat);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ClutterInputDevice *
 | 
			
		||||
clutter_seat_evdev_get_device (ClutterSeatEvdev *seat,
 | 
			
		||||
                               gint              id)
 | 
			
		||||
{
 | 
			
		||||
  ClutterInputDevice *device;
 | 
			
		||||
  GSList *l;
 | 
			
		||||
 | 
			
		||||
  for (l = seat->devices; l; l = l->next)
 | 
			
		||||
    {
 | 
			
		||||
      device = l->data;
 | 
			
		||||
 | 
			
		||||
      if (clutter_input_device_get_device_id (device) == id)
 | 
			
		||||
        return device;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
clutter_seat_evdev_set_stage (ClutterSeatEvdev *seat,
 | 
			
		||||
                              ClutterStage     *stage)
 | 
			
		||||
 
 | 
			
		||||
@@ -139,6 +139,9 @@ void clutter_seat_evdev_set_libinput_seat (ClutterSeatEvdev     *seat,
 | 
			
		||||
 | 
			
		||||
void clutter_seat_evdev_sync_leds (ClutterSeatEvdev *seat);
 | 
			
		||||
 | 
			
		||||
ClutterInputDevice * clutter_seat_evdev_get_device (ClutterSeatEvdev *seat,
 | 
			
		||||
                                                    gint              id);
 | 
			
		||||
 | 
			
		||||
ClutterTouchState * clutter_seat_evdev_acquire_touch_state (ClutterSeatEvdev *seat,
 | 
			
		||||
                                                            int               device_slot);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -452,7 +452,7 @@ libmutter_cogl_@LIBMUTTER_API_VERSION@_la_LDFLAGS = \
 | 
			
		||||
	-avoid-version \
 | 
			
		||||
	-export-dynamic \
 | 
			
		||||
	-rpath $(mutterlibdir) \
 | 
			
		||||
	-export-symbols-regex "^(cogl|_cogl_debug_flags|_cogl_atlas_new|_cogl_atlas_add_reorganize_callback|_cogl_atlas_reserve_space|_cogl_callback|_cogl_util_get_eye_planes_for_screen_poly|_cogl_atlas_texture_remove_reorganize_callback|_cogl_atlas_texture_add_reorganize_callback|_cogl_texture_get_format|_cogl_texture_foreach_sub_texture_in_region|_cogl_texture_set_region|_cogl_profile_trace_message|_cogl_context_get_default|_cogl_framebuffer_get_stencil_bits|_cogl_clip_stack_push_rectangle|_cogl_framebuffer_get_modelview_stack|_cogl_object_default_unref|_cogl_pipeline_foreach_layer_internal|_cogl_clip_stack_push_primitive|_cogl_buffer_unmap_for_fill_or_fallback|_cogl_framebuffer_draw_primitive|_cogl_debug_instances|_cogl_framebuffer_get_projection_stack|_cogl_pipeline_layer_get_texture|_cogl_buffer_map_for_fill_or_fallback|_cogl_texture_can_hardware_repeat|_cogl_pipeline_prune_to_n_layers|_cogl_primitive_draw|test_|unit_test_|_cogl_winsys_glx_get_vtable|_cogl_winsys_egl_xlib_get_vtable|_cogl_winsys_egl_get_vtable|_cogl_closure_disconnect|_cogl_onscreen_notify_complete|_cogl_onscreen_notify_frame_sync|_cogl_winsys_egl_renderer_connect_common|_cogl_winsys_error_quark|_cogl_set_error|_cogl_poll_renderer_add_fd|_cogl_poll_renderer_add_idle|_cogl_framebuffer_winsys_update_size|_cogl_winsys_egl_make_current|_cogl_pixel_format_get_bytes_per_pixel).*"
 | 
			
		||||
	-export-symbols-regex "^(cogl|_cogl_debug_flags|_cogl_atlas_new|_cogl_atlas_add_reorganize_callback|_cogl_atlas_reserve_space|_cogl_callback|_cogl_util_get_eye_planes_for_screen_poly|_cogl_atlas_texture_remove_reorganize_callback|_cogl_atlas_texture_add_reorganize_callback|_cogl_texture_get_format|_cogl_texture_foreach_sub_texture_in_region|_cogl_texture_set_region|_cogl_profile_trace_message|_cogl_context_get_default|_cogl_framebuffer_get_stencil_bits|_cogl_clip_stack_push_rectangle|_cogl_framebuffer_get_modelview_stack|_cogl_object_default_unref|_cogl_pipeline_foreach_layer_internal|_cogl_clip_stack_push_primitive|_cogl_buffer_unmap_for_fill_or_fallback|_cogl_framebuffer_draw_primitive|_cogl_debug_instances|_cogl_framebuffer_get_projection_stack|_cogl_pipeline_layer_get_texture|_cogl_buffer_map_for_fill_or_fallback|_cogl_texture_can_hardware_repeat|_cogl_pipeline_prune_to_n_layers|_cogl_primitive_draw|test_|unit_test_|_cogl_winsys_glx_get_vtable|_cogl_winsys_egl_xlib_get_vtable|_cogl_winsys_egl_get_vtable|_cogl_closure_disconnect|_cogl_onscreen_notify_complete|_cogl_onscreen_notify_frame_sync|_cogl_winsys_egl_renderer_connect_common|_cogl_winsys_error_quark|_cogl_set_error|_cogl_poll_renderer_add_fd|_cogl_poll_renderer_add_idle|_cogl_framebuffer_winsys_update_size|_cogl_winsys_egl_make_current|_cogl_winsys_egl_ensure_current|_cogl_pixel_format_get_bytes_per_pixel).*"
 | 
			
		||||
 | 
			
		||||
libmutter_cogl_@LIBMUTTER_API_VERSION@_la_SOURCES = $(cogl_sources_c)
 | 
			
		||||
nodist_libmutter_cogl_@LIBMUTTER_API_VERSION@_la_SOURCES = $(BUILT_SOURCES)
 | 
			
		||||
 
 | 
			
		||||
@@ -109,7 +109,11 @@ _cogl_object_default_unref (void *object)
 | 
			
		||||
void
 | 
			
		||||
cogl_object_unref (void *obj)
 | 
			
		||||
{
 | 
			
		||||
  void (* unref_func) (void *) = ((CoglObject *) obj)->klass->virt_unref;
 | 
			
		||||
  void (* unref_func) (void *);
 | 
			
		||||
 | 
			
		||||
  _COGL_RETURN_IF_FAIL (obj != NULL);
 | 
			
		||||
 | 
			
		||||
  unref_func = ((CoglObject *) obj)->klass->virt_unref;
 | 
			
		||||
  unref_func (obj);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1412,22 +1412,12 @@ _cogl_framebuffer_gl_read_pixels_into_bitmap (CoglFramebuffer *framebuffer,
 | 
			
		||||
  if (!cogl_is_offscreen (framebuffer))
 | 
			
		||||
    y = framebuffer_height - y - height;
 | 
			
		||||
 | 
			
		||||
  required_format = ctx->driver_vtable->pixel_format_to_gl (ctx,
 | 
			
		||||
                                                            format,
 | 
			
		||||
                                                            &gl_intformat,
 | 
			
		||||
                                                            &gl_format,
 | 
			
		||||
                                                            &gl_type);
 | 
			
		||||
#if HAVE_COGL_GL
 | 
			
		||||
  /* As we are reading pixels, we want to consider the bitmap according to
 | 
			
		||||
   * its real pixel format, not the swizzled channels we pretend face to the
 | 
			
		||||
   * pipeline.
 | 
			
		||||
   */
 | 
			
		||||
  if ((ctx->driver == COGL_DRIVER_GL || ctx->driver == COGL_DRIVER_GL3) &&
 | 
			
		||||
      (format == COGL_PIXEL_FORMAT_BGRA_8888 ||
 | 
			
		||||
       format == COGL_PIXEL_FORMAT_BGRA_8888_PRE) &&
 | 
			
		||||
      _cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_TEXTURE_SWIZZLE))
 | 
			
		||||
    gl_format = GL_BGRA;
 | 
			
		||||
#endif
 | 
			
		||||
  required_format = ctx->driver_vtable->pixel_format_to_gl_with_target (ctx,
 | 
			
		||||
                                                                        framebuffer->internal_format,
 | 
			
		||||
                                                                        format,
 | 
			
		||||
                                                                        &gl_intformat,
 | 
			
		||||
                                                                        &gl_format,
 | 
			
		||||
                                                                        &gl_type);
 | 
			
		||||
 | 
			
		||||
  /* NB: All offscreen rendering is done upside down so there is no need
 | 
			
		||||
   * to flip in this case... */
 | 
			
		||||
 
 | 
			
		||||
@@ -181,6 +181,9 @@ _cogl_winsys_egl_make_current (CoglDisplay *display,
 | 
			
		||||
                               EGLSurface read,
 | 
			
		||||
                               EGLContext context);
 | 
			
		||||
 | 
			
		||||
EGLBoolean
 | 
			
		||||
_cogl_winsys_egl_ensure_current (CoglDisplay *display);
 | 
			
		||||
 | 
			
		||||
#ifdef EGL_KHR_image_base
 | 
			
		||||
EGLImageKHR
 | 
			
		||||
_cogl_egl_create_image (CoglContext *ctx,
 | 
			
		||||
 
 | 
			
		||||
@@ -309,6 +309,18 @@ _cogl_winsys_egl_make_current (CoglDisplay *display,
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
EGLBoolean
 | 
			
		||||
_cogl_winsys_egl_ensure_current (CoglDisplay *display)
 | 
			
		||||
{
 | 
			
		||||
  CoglDisplayEGL *egl_display = display->winsys;
 | 
			
		||||
  CoglRendererEGL *egl_renderer = display->renderer->winsys;
 | 
			
		||||
 | 
			
		||||
  return eglMakeCurrent (egl_renderer->edpy,
 | 
			
		||||
                         egl_display->current_draw_surface,
 | 
			
		||||
                         egl_display->current_read_surface,
 | 
			
		||||
                         egl_display->current_context);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
cleanup_context (CoglDisplay *display)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								configure.ac
									
									
									
									
									
								
							@@ -2,7 +2,7 @@ AC_PREREQ(2.62)
 | 
			
		||||
 | 
			
		||||
m4_define([mutter_major_version], [3])
 | 
			
		||||
m4_define([mutter_minor_version], [28])
 | 
			
		||||
m4_define([mutter_micro_version], [0])
 | 
			
		||||
m4_define([mutter_micro_version], [2])
 | 
			
		||||
 | 
			
		||||
m4_define([mutter_version],
 | 
			
		||||
          [mutter_major_version.mutter_minor_version.mutter_micro_version])
 | 
			
		||||
@@ -262,7 +262,19 @@ AC_SUBST(XWAYLAND_PATH)
 | 
			
		||||
 | 
			
		||||
PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
 | 
			
		||||
 | 
			
		||||
MUTTER_NATIVE_BACKEND_MODULES="libdrm >= 2.4.83 libsystemd libinput >= 1.4 gudev-1.0 gbm >= 17.1"
 | 
			
		||||
PKG_CHECK_MODULES(ELOGIND, [libelogind], [have_elogind=yes], [have_elogind=no])
 | 
			
		||||
 | 
			
		||||
if test x$have_elogind = xyes; then
 | 
			
		||||
     logind_provider="libelogind"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
PKG_CHECK_MODULES(SYSTEMD, [libsystemd], [have_systemd=yes], [have_systemd=no])
 | 
			
		||||
 | 
			
		||||
if test x$have_systemd = xyes -o -z "$logind_provider"; then
 | 
			
		||||
     logind_provider="libsystemd"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
MUTTER_NATIVE_BACKEND_MODULES="libdrm $logind_provider libinput >= 1.4 gudev-1.0 gbm >= 10.3"
 | 
			
		||||
 | 
			
		||||
AC_ARG_ENABLE(native-backend,
 | 
			
		||||
  AS_HELP_STRING([--disable-native-backend], [disable mutter native (KMS) backend]),,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										23
									
								
								po/sl.po
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								po/sl.po
									
									
									
									
									
								
							@@ -10,8 +10,8 @@ msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: mutter master\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n"
 | 
			
		||||
"POT-Creation-Date: 2018-03-05 19:32+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2018-03-06 22:02+0100\n"
 | 
			
		||||
"POT-Creation-Date: 2018-04-03 20:43+0000\n"
 | 
			
		||||
"PO-Revision-Date: 2018-04-09 20:28+0200\n"
 | 
			
		||||
"Last-Translator: Matej Urbančič <mateju@svn.gnome.org>\n"
 | 
			
		||||
"Language-Team: Slovenian GNOME Translation Team <gnome-si@googlegroups.com>\n"
 | 
			
		||||
"Language: sl_SI\n"
 | 
			
		||||
@@ -21,7 +21,7 @@ msgstr ""
 | 
			
		||||
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n"
 | 
			
		||||
"%100==4 ? 3 : 0);\n"
 | 
			
		||||
"X-Poedit-SourceCharset: utf-8\n"
 | 
			
		||||
"X-Generator: Poedit 2.0.4\n"
 | 
			
		||||
"X-Generator: Poedit 2.0.6\n"
 | 
			
		||||
 | 
			
		||||
#: data/50-mutter-navigation.xml:6
 | 
			
		||||
msgid "Navigation"
 | 
			
		||||
@@ -481,7 +481,7 @@ msgstr "Ponovno omogoči tipkovne bližnjice"
 | 
			
		||||
 | 
			
		||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:64
 | 
			
		||||
msgid "Allow grabs with Xwayland"
 | 
			
		||||
msgstr ""
 | 
			
		||||
msgstr "Dovoli zajemanje z XWayland"
 | 
			
		||||
 | 
			
		||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:65
 | 
			
		||||
msgid ""
 | 
			
		||||
@@ -491,10 +491,14 @@ msgid ""
 | 
			
		||||
"window or be among the applications white-listed in key “xwayland-grab-"
 | 
			
		||||
"access-rules”."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Upošteva zajeme s tipkovnico, ki jih sprožijo programi X11, zagnani v okolju "
 | 
			
		||||
"Xwayland. Če naj se programski zajem upošteva, mora odjemalec ali poslati "
 | 
			
		||||
"specifično sporočilo X11 na korensko okno ali pa mora biti zaveden na "
 | 
			
		||||
"seznamu programov v ključu »xwayland-garb-access-rules«."
 | 
			
		||||
 | 
			
		||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:77
 | 
			
		||||
msgid "Xwayland applications allowed to issue keyboard grabs"
 | 
			
		||||
msgstr ""
 | 
			
		||||
msgstr "Program XWayland ima dovoljenje za zajemanje s tipkovnico"
 | 
			
		||||
 | 
			
		||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:78
 | 
			
		||||
msgid ""
 | 
			
		||||
@@ -509,6 +513,15 @@ msgid ""
 | 
			
		||||
"using the specific keyboard shortcut defined by the keybinding key “restore-"
 | 
			
		||||
"shortcuts”."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Seznam imen ali razredov virov oken X11, ki lahko sprožijo zajeme v okolju "
 | 
			
		||||
"Xwayland. Ime oziroma razred vira podanega okna X11 je mogoče pridobiti z "
 | 
			
		||||
"ukazom »xprop WM_CLASS«. Uporaba pomožnih znakov » * « in » ? « je podprta. "
 | 
			
		||||
"Vrednosti, ki se začnejo z znakom » ! « so uvrščeni na črni seznam. Ta "
 | 
			
		||||
"seznam je obravnavan prednostno pred belim seznamom in prekliče zajeme na "
 | 
			
		||||
"seznamu sistema. Privzeti seznam vključuje ključ: "
 | 
			
		||||
"»@XWAYLAND_GRAB_DEFAULT_ACCESS_RULES@« Uporabniki lahko prekinejo obstoječi "
 | 
			
		||||
"zajem z uporabo posebne tipkovne bližnjice, določene s tipkovnim ključem "
 | 
			
		||||
"»restore-shortcuts«."
 | 
			
		||||
 | 
			
		||||
#. TRANSLATORS: This string refers to a button that switches between
 | 
			
		||||
#. * different modes.
 | 
			
		||||
 
 | 
			
		||||
@@ -153,7 +153,7 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES =	\
 | 
			
		||||
	backends/meta-pointer-constraint.h	\
 | 
			
		||||
	backends/meta-settings.c		\
 | 
			
		||||
	backends/meta-settings-private.h	\
 | 
			
		||||
	backends/meta-stage.h			\
 | 
			
		||||
	backends/meta-stage-private.h		\
 | 
			
		||||
	backends/meta-stage.c			\
 | 
			
		||||
	backends/meta-renderer.c		\
 | 
			
		||||
	backends/meta-renderer.h		\
 | 
			
		||||
@@ -161,6 +161,7 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES =	\
 | 
			
		||||
	backends/meta-renderer-view.h		\
 | 
			
		||||
	backends/edid-parse.c			\
 | 
			
		||||
	backends/edid.h				\
 | 
			
		||||
	backends/gsm-inhibitor-flag.h		\
 | 
			
		||||
	backends/x11/meta-backend-x11.c			\
 | 
			
		||||
	backends/x11/meta-backend-x11.h			\
 | 
			
		||||
	backends/x11/meta-barrier-x11.c			\
 | 
			
		||||
@@ -183,8 +184,6 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES =	\
 | 
			
		||||
	backends/x11/nested/meta-cursor-renderer-x11-nested.h		\
 | 
			
		||||
	backends/x11/nested/meta-renderer-x11-nested.c	\
 | 
			
		||||
	backends/x11/nested/meta-renderer-x11-nested.h	\
 | 
			
		||||
	backends/x11/meta-idle-monitor-xsync.c		\
 | 
			
		||||
	backends/x11/meta-idle-monitor-xsync.h		\
 | 
			
		||||
	backends/x11/meta-input-settings-x11.c		\
 | 
			
		||||
	backends/x11/meta-input-settings-x11.h		\
 | 
			
		||||
	backends/x11/meta-monitor-manager-xrandr.c	\
 | 
			
		||||
@@ -247,7 +246,7 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES =	\
 | 
			
		||||
	compositor/meta-window-actor.c		\
 | 
			
		||||
	compositor/meta-window-actor-private.h	\
 | 
			
		||||
	compositor/meta-window-group.c		\
 | 
			
		||||
	compositor/meta-window-group.h		\
 | 
			
		||||
	compositor/meta-window-group-private.h	\
 | 
			
		||||
	compositor/meta-window-shape.c		\
 | 
			
		||||
	compositor/region-utils.c		\
 | 
			
		||||
	compositor/region-utils.h		\
 | 
			
		||||
@@ -487,8 +486,6 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES +=		\
 | 
			
		||||
	backends/native/meta-default-modes.h		\
 | 
			
		||||
	backends/native/meta-gpu-kms.c			\
 | 
			
		||||
	backends/native/meta-gpu-kms.h			\
 | 
			
		||||
	backends/native/meta-idle-monitor-native.c	\
 | 
			
		||||
	backends/native/meta-idle-monitor-native.h	\
 | 
			
		||||
	backends/native/meta-input-settings-native.c	\
 | 
			
		||||
	backends/native/meta-input-settings-native.h	\
 | 
			
		||||
	backends/native/meta-monitor-manager-kms.c	\
 | 
			
		||||
@@ -546,7 +543,9 @@ libmutterinclude_headers =			\
 | 
			
		||||
	meta/meta-settings.h			\
 | 
			
		||||
	meta/meta-shaped-texture.h		\
 | 
			
		||||
	meta/meta-shadow-factory.h		\
 | 
			
		||||
	meta/meta-stage.h			\
 | 
			
		||||
	meta/meta-window-actor.h		\
 | 
			
		||||
	meta/meta-window-group.h		\
 | 
			
		||||
	meta/meta-window-shape.h		\
 | 
			
		||||
	meta/prefs.h				\
 | 
			
		||||
	meta/screen.h				\
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										36
									
								
								src/backends/gsm-inhibitor-flag.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/backends/gsm-inhibitor-flag.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2008 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
 | 
			
		||||
 * Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __GSM_INHIBITOR_FLAG_H__
 | 
			
		||||
#define __GSM_INHIBITOR_FLAG_H__
 | 
			
		||||
 | 
			
		||||
#include <glib-object.h>
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
        GSM_INHIBITOR_FLAG_LOGOUT      = 1 << 0,
 | 
			
		||||
        GSM_INHIBITOR_FLAG_SWITCH_USER = 1 << 1,
 | 
			
		||||
        GSM_INHIBITOR_FLAG_SUSPEND     = 1 << 2,
 | 
			
		||||
        GSM_INHIBITOR_FLAG_IDLE        = 1 << 3,
 | 
			
		||||
        GSM_INHIBITOR_FLAG_AUTOMOUNT   = 1 << 4
 | 
			
		||||
} GsmInhibitorFlag;
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* __GSM_INHIBITOR_FLAG_H__ */
 | 
			
		||||
@@ -59,8 +59,6 @@ struct _MetaBackendClass
 | 
			
		||||
 | 
			
		||||
  void (* post_init) (MetaBackend *backend);
 | 
			
		||||
 | 
			
		||||
  MetaIdleMonitor * (* create_idle_monitor) (MetaBackend *backend,
 | 
			
		||||
                                             int          device_id);
 | 
			
		||||
  MetaMonitorManager * (* create_monitor_manager) (MetaBackend *backend,
 | 
			
		||||
                                                   GError     **error);
 | 
			
		||||
  MetaCursorRenderer * (* create_cursor_renderer) (MetaBackend *backend);
 | 
			
		||||
 
 | 
			
		||||
@@ -34,7 +34,7 @@
 | 
			
		||||
#include "meta-input-settings-private.h"
 | 
			
		||||
#include "backends/x11/meta-backend-x11.h"
 | 
			
		||||
#include "meta-cursor-tracker-private.h"
 | 
			
		||||
#include "meta-stage.h"
 | 
			
		||||
#include "meta-stage-private.h"
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_REMOTE_DESKTOP
 | 
			
		||||
#include "backends/meta-dbus-session-watcher.h"
 | 
			
		||||
@@ -110,6 +110,11 @@ struct _MetaBackendPrivate
 | 
			
		||||
 | 
			
		||||
  MetaPointerConstraint *client_pointer_constraint;
 | 
			
		||||
  MetaDnd *dnd;
 | 
			
		||||
 | 
			
		||||
  UpClient *up_client;
 | 
			
		||||
  guint sleep_signal_id;
 | 
			
		||||
  GCancellable *cancellable;
 | 
			
		||||
  GDBusConnection *system_bus;
 | 
			
		||||
};
 | 
			
		||||
typedef struct _MetaBackendPrivate MetaBackendPrivate;
 | 
			
		||||
 | 
			
		||||
@@ -136,6 +141,13 @@ meta_backend_finalize (GObject *object)
 | 
			
		||||
  g_clear_object (&priv->dbus_session_watcher);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  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);
 | 
			
		||||
 | 
			
		||||
  if (priv->device_update_idle_id)
 | 
			
		||||
    g_source_remove (priv->device_update_idle_id);
 | 
			
		||||
 | 
			
		||||
@@ -158,7 +170,7 @@ meta_backend_sync_screen_size (MetaBackend *backend)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
center_pointer (MetaBackend *backend)
 | 
			
		||||
reset_pointer_position (MetaBackend *backend)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
 | 
			
		||||
  MetaMonitorManager *monitor_manager = priv->monitor_manager;
 | 
			
		||||
@@ -167,9 +179,11 @@ center_pointer (MetaBackend *backend)
 | 
			
		||||
  primary =
 | 
			
		||||
    meta_monitor_manager_get_primary_logical_monitor (monitor_manager);
 | 
			
		||||
 | 
			
		||||
  /* Move the pointer out of the way to avoid hovering over reactive
 | 
			
		||||
   * elements (e.g. users list at login) causing undesired behaviour. */
 | 
			
		||||
  meta_backend_warp_pointer (backend,
 | 
			
		||||
                             primary->rect.x + primary->rect.width / 2,
 | 
			
		||||
                             primary->rect.y + primary->rect.height / 2);
 | 
			
		||||
                             primary->rect.x + primary->rect.width * 0.9,
 | 
			
		||||
                             primary->rect.y + primary->rect.height * 0.9);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -192,7 +206,7 @@ meta_backend_monitors_changed (MetaBackend *backend)
 | 
			
		||||
           !priv->is_pointer_position_initialized) &&
 | 
			
		||||
          !meta_monitor_manager_is_headless (monitor_manager))
 | 
			
		||||
        {
 | 
			
		||||
          center_pointer (backend);
 | 
			
		||||
          reset_pointer_position (backend);
 | 
			
		||||
          priv->is_pointer_position_initialized = TRUE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -222,7 +236,9 @@ static MetaIdleMonitor *
 | 
			
		||||
meta_backend_create_idle_monitor (MetaBackend *backend,
 | 
			
		||||
                                  int          device_id)
 | 
			
		||||
{
 | 
			
		||||
  return META_BACKEND_GET_CLASS (backend)->create_idle_monitor (backend, device_id);
 | 
			
		||||
  return g_object_new (META_TYPE_IDLE_MONITOR,
 | 
			
		||||
                       "device-id", device_id,
 | 
			
		||||
                       NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -465,7 +481,7 @@ meta_backend_real_post_init (MetaBackend *backend)
 | 
			
		||||
 | 
			
		||||
  if (!meta_monitor_manager_is_headless (priv->monitor_manager))
 | 
			
		||||
    {
 | 
			
		||||
      center_pointer (backend);
 | 
			
		||||
      reset_pointer_position (backend);
 | 
			
		||||
      priv->is_pointer_position_initialized = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -590,6 +606,61 @@ meta_backend_create_renderer (MetaBackend *backend,
 | 
			
		||||
  return META_BACKEND_GET_CLASS (backend)->create_renderer (backend, error);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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_reset_idletime (meta_idle_monitor_get_core ());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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_reset_idletime (meta_idle_monitor_get_core ());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
system_bus_gotten_cb (GObject      *object,
 | 
			
		||||
                      GAsyncResult *res,
 | 
			
		||||
                      gpointer      user_data)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackendPrivate *priv;
 | 
			
		||||
  GDBusConnection *bus;
 | 
			
		||||
 | 
			
		||||
  bus = g_bus_get_finish (res, NULL);
 | 
			
		||||
  if (!bus)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  priv = meta_backend_get_instance_private (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 gboolean
 | 
			
		||||
meta_backend_initable_init (GInitable     *initable,
 | 
			
		||||
                            GCancellable  *cancellable,
 | 
			
		||||
@@ -619,6 +690,16 @@ meta_backend_initable_init (GInitable     *initable,
 | 
			
		||||
 | 
			
		||||
  priv->dnd = g_object_new (META_TYPE_DND, NULL);
 | 
			
		||||
 | 
			
		||||
  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,
 | 
			
		||||
             backend);
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,7 @@
 | 
			
		||||
#include <cogl/cogl.h>
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
 | 
			
		||||
#include "meta-stage.h"
 | 
			
		||||
#include "meta-stage-private.h"
 | 
			
		||||
 | 
			
		||||
struct _MetaCursorRendererPrivate
 | 
			
		||||
{
 | 
			
		||||
@@ -264,6 +264,18 @@ meta_cursor_renderer_set_position (MetaCursorRenderer *renderer,
 | 
			
		||||
  update_cursor (renderer, priv->displayed_cursor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ClutterPoint
 | 
			
		||||
meta_cursor_renderer_get_position (MetaCursorRenderer *renderer)
 | 
			
		||||
{
 | 
			
		||||
  MetaCursorRendererPrivate *priv =
 | 
			
		||||
    meta_cursor_renderer_get_instance_private (renderer);
 | 
			
		||||
 | 
			
		||||
  return (ClutterPoint) {
 | 
			
		||||
    .x = priv->current_x,
 | 
			
		||||
    .y = priv->current_y
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaCursorSprite *
 | 
			
		||||
meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -62,6 +62,7 @@ void meta_cursor_renderer_set_cursor (MetaCursorRenderer *renderer,
 | 
			
		||||
void meta_cursor_renderer_set_position (MetaCursorRenderer *renderer,
 | 
			
		||||
                                        float               x,
 | 
			
		||||
                                        float               y);
 | 
			
		||||
ClutterPoint meta_cursor_renderer_get_position (MetaCursorRenderer *renderer);
 | 
			
		||||
void meta_cursor_renderer_force_update (MetaCursorRenderer *renderer);
 | 
			
		||||
 | 
			
		||||
MetaCursorSprite * meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer);
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,7 @@
 | 
			
		||||
 | 
			
		||||
#include "meta-idle-monitor-dbus.h"
 | 
			
		||||
#include <meta/meta-idle-monitor.h>
 | 
			
		||||
#include <backends/meta-idle-monitor-private.h>
 | 
			
		||||
#include "meta-dbus-idle-monitor.h"
 | 
			
		||||
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
@@ -43,6 +44,26 @@ handle_get_idletime (MetaDBusIdleMonitor   *skeleton,
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
handle_reset_idletime (MetaDBusIdleMonitor   *skeleton,
 | 
			
		||||
                       GDBusMethodInvocation *invocation,
 | 
			
		||||
                       MetaIdleMonitor       *monitor)
 | 
			
		||||
{
 | 
			
		||||
  if (!g_getenv ("MUTTER_DEBUG_RESET_IDLETIME"))
 | 
			
		||||
    {
 | 
			
		||||
      g_dbus_method_invocation_return_error_literal (invocation,
 | 
			
		||||
                                                     G_DBUS_ERROR,
 | 
			
		||||
                                                     G_DBUS_ERROR_UNKNOWN_METHOD,
 | 
			
		||||
                                                     "No such method");
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_idle_monitor_reset_idletime (meta_idle_monitor_get_core ());
 | 
			
		||||
  meta_dbus_idle_monitor_complete_reset_idletime (skeleton, invocation);
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  MetaDBusIdleMonitor *dbus_monitor;
 | 
			
		||||
  MetaIdleMonitor *monitor;
 | 
			
		||||
@@ -173,6 +194,8 @@ create_monitor_skeleton (GDBusObjectManagerServer *manager,
 | 
			
		||||
                           G_CALLBACK (handle_add_user_active_watch), monitor, 0);
 | 
			
		||||
  g_signal_connect_object (skeleton, "handle-remove-watch",
 | 
			
		||||
                           G_CALLBACK (handle_remove_watch), monitor, 0);
 | 
			
		||||
  g_signal_connect_object (skeleton, "handle-reset-idletime",
 | 
			
		||||
                           G_CALLBACK (handle_reset_idletime), monitor, 0);
 | 
			
		||||
  g_signal_connect_object (skeleton, "handle-get-idletime",
 | 
			
		||||
                           G_CALLBACK (handle_get_idletime), monitor, 0);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -26,9 +26,6 @@
 | 
			
		||||
#include <meta/meta-idle-monitor.h>
 | 
			
		||||
#include "display-private.h"
 | 
			
		||||
 | 
			
		||||
#include <X11/Xlib.h>
 | 
			
		||||
#include <X11/extensions/sync.h>
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitor          *monitor;
 | 
			
		||||
@@ -38,28 +35,26 @@ typedef struct
 | 
			
		||||
  GDestroyNotify            notify;
 | 
			
		||||
  guint64                   timeout_msec;
 | 
			
		||||
  int                       idle_source_id;
 | 
			
		||||
  GSource                  *timeout_source;
 | 
			
		||||
} MetaIdleMonitorWatch;
 | 
			
		||||
 | 
			
		||||
struct _MetaIdleMonitor
 | 
			
		||||
{
 | 
			
		||||
  GObject parent_instance;
 | 
			
		||||
 | 
			
		||||
  GDBusProxy *session_proxy;
 | 
			
		||||
  gboolean inhibited;
 | 
			
		||||
  GHashTable *watches;
 | 
			
		||||
  int device_id;
 | 
			
		||||
  guint64 last_event_time;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaIdleMonitorClass
 | 
			
		||||
{
 | 
			
		||||
  GObjectClass parent_class;
 | 
			
		||||
 | 
			
		||||
  gint64 (*get_idletime) (MetaIdleMonitor *monitor);
 | 
			
		||||
  MetaIdleMonitorWatch * (*make_watch) (MetaIdleMonitor           *monitor,
 | 
			
		||||
                                        guint64                    timeout_msec,
 | 
			
		||||
                                        MetaIdleMonitorWatchFunc   callback,
 | 
			
		||||
                                        gpointer                   user_data,
 | 
			
		||||
                                        GDestroyNotify             notify);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void _meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch);
 | 
			
		||||
void meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor);
 | 
			
		||||
 | 
			
		||||
#endif /* META_IDLE_MONITOR_PRIVATE_H */
 | 
			
		||||
 
 | 
			
		||||
@@ -36,6 +36,7 @@
 | 
			
		||||
#include <meta/util.h>
 | 
			
		||||
#include <meta/main.h>
 | 
			
		||||
#include <meta/meta-idle-monitor.h>
 | 
			
		||||
#include "gsm-inhibitor-flag.h"
 | 
			
		||||
#include "meta-idle-monitor-private.h"
 | 
			
		||||
#include "meta-idle-monitor-dbus.h"
 | 
			
		||||
#include "meta-backend-private.h"
 | 
			
		||||
@@ -87,6 +88,7 @@ meta_idle_monitor_dispose (GObject *object)
 | 
			
		||||
  MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
 | 
			
		||||
 | 
			
		||||
  g_clear_pointer (&monitor->watches, g_hash_table_destroy);
 | 
			
		||||
  g_clear_object (&monitor->session_proxy);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_idle_monitor_parent_class)->dispose (object);
 | 
			
		||||
}
 | 
			
		||||
@@ -151,9 +153,117 @@ meta_idle_monitor_class_init (MetaIdleMonitorClass *klass)
 | 
			
		||||
  g_object_class_install_property (object_class, PROP_DEVICE_ID, obj_props[PROP_DEVICE_ID]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
free_watch (gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) data;
 | 
			
		||||
  MetaIdleMonitor *monitor = watch->monitor;
 | 
			
		||||
 | 
			
		||||
  g_object_ref (monitor);
 | 
			
		||||
 | 
			
		||||
  if (watch->idle_source_id)
 | 
			
		||||
    {
 | 
			
		||||
      g_source_remove (watch->idle_source_id);
 | 
			
		||||
      watch->idle_source_id = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (watch->notify != NULL)
 | 
			
		||||
    watch->notify (watch->user_data);
 | 
			
		||||
 | 
			
		||||
  if (watch->timeout_source != NULL)
 | 
			
		||||
    g_source_destroy (watch->timeout_source);
 | 
			
		||||
 | 
			
		||||
  g_object_unref (monitor);
 | 
			
		||||
  g_slice_free (MetaIdleMonitorWatch, watch);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
update_inhibited_watch (gpointer key,
 | 
			
		||||
                        gpointer value,
 | 
			
		||||
                        gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitor *monitor = user_data;
 | 
			
		||||
  MetaIdleMonitorWatch *watch = value;
 | 
			
		||||
 | 
			
		||||
  if (!watch->timeout_source)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  if (monitor->inhibited)
 | 
			
		||||
    {
 | 
			
		||||
      g_source_set_ready_time (watch->timeout_source, -1);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      g_source_set_ready_time (watch->timeout_source,
 | 
			
		||||
                               monitor->last_event_time +
 | 
			
		||||
                               watch->timeout_msec * 1000);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
update_inhibited (MetaIdleMonitor *monitor,
 | 
			
		||||
                  gboolean         inhibited)
 | 
			
		||||
{
 | 
			
		||||
  if (inhibited == monitor->inhibited)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  g_hash_table_foreach (monitor->watches,
 | 
			
		||||
                        update_inhibited_watch,
 | 
			
		||||
                        monitor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_idle_monitor_inhibited_actions_changed (GDBusProxy  *session,
 | 
			
		||||
                                             GVariant    *changed,
 | 
			
		||||
                                             char       **invalidated,
 | 
			
		||||
                                             gpointer     user_data)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitor *monitor = user_data;
 | 
			
		||||
  GVariant *v;
 | 
			
		||||
 | 
			
		||||
  v = g_variant_lookup_value (changed, "InhibitedActions", G_VARIANT_TYPE_UINT32);
 | 
			
		||||
  if (v)
 | 
			
		||||
    {
 | 
			
		||||
      gboolean inhibited;
 | 
			
		||||
 | 
			
		||||
      inhibited = g_variant_get_uint32 (v) & GSM_INHIBITOR_FLAG_IDLE;
 | 
			
		||||
      g_variant_unref (v);
 | 
			
		||||
 | 
			
		||||
      if (!inhibited)
 | 
			
		||||
        monitor->last_event_time = g_get_monotonic_time ();
 | 
			
		||||
      update_inhibited (monitor, inhibited);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_idle_monitor_init (MetaIdleMonitor *monitor)
 | 
			
		||||
{
 | 
			
		||||
  GVariant *v;
 | 
			
		||||
 | 
			
		||||
  monitor->watches = g_hash_table_new_full (NULL, NULL, NULL, free_watch);
 | 
			
		||||
  monitor->last_event_time = g_get_monotonic_time ();
 | 
			
		||||
 | 
			
		||||
  /* Monitor inhibitors */
 | 
			
		||||
  monitor->session_proxy =
 | 
			
		||||
    g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
 | 
			
		||||
                                   G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
 | 
			
		||||
                                   NULL,
 | 
			
		||||
                                   "org.gnome.SessionManager",
 | 
			
		||||
                                   "/org/gnome/SessionManager",
 | 
			
		||||
                                   "org.gnome.SessionManager",
 | 
			
		||||
                                   NULL,
 | 
			
		||||
                                   NULL);
 | 
			
		||||
  if (!monitor->session_proxy)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  g_signal_connect (monitor->session_proxy, "g-properties-changed",
 | 
			
		||||
                    G_CALLBACK (meta_idle_monitor_inhibited_actions_changed),
 | 
			
		||||
                    monitor);
 | 
			
		||||
 | 
			
		||||
  v = g_dbus_proxy_get_cached_property (monitor->session_proxy,
 | 
			
		||||
                                        "InhibitedActions");
 | 
			
		||||
  monitor->inhibited = g_variant_get_uint32 (v) & GSM_INHIBITOR_FLAG_IDLE;
 | 
			
		||||
  g_variant_unref (v);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -185,6 +295,36 @@ meta_idle_monitor_get_for_device (int device_id)
 | 
			
		||||
  return meta_backend_get_idle_monitor (backend, device_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static guint32
 | 
			
		||||
get_next_watch_serial (void)
 | 
			
		||||
{
 | 
			
		||||
  static guint32 serial = 0;
 | 
			
		||||
 | 
			
		||||
  g_atomic_int_inc (&serial);
 | 
			
		||||
 | 
			
		||||
  return serial;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
idle_monitor_dispatch_timeout (GSource     *source,
 | 
			
		||||
                               GSourceFunc  callback,
 | 
			
		||||
                               gpointer     user_data)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) user_data;
 | 
			
		||||
 | 
			
		||||
  _meta_idle_monitor_watch_fire (watch);
 | 
			
		||||
  g_source_set_ready_time (watch->timeout_source, -1);
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GSourceFuncs idle_monitor_source_funcs = {
 | 
			
		||||
  .prepare = NULL,
 | 
			
		||||
  .check = NULL,
 | 
			
		||||
  .dispatch = idle_monitor_dispatch_timeout,
 | 
			
		||||
  .finalize = NULL,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static MetaIdleMonitorWatch *
 | 
			
		||||
make_watch (MetaIdleMonitor           *monitor,
 | 
			
		||||
            guint64                    timeout_msec,
 | 
			
		||||
@@ -194,11 +334,32 @@ make_watch (MetaIdleMonitor           *monitor,
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitorWatch *watch;
 | 
			
		||||
 | 
			
		||||
  watch = META_IDLE_MONITOR_GET_CLASS (monitor)->make_watch (monitor,
 | 
			
		||||
                                                             timeout_msec,
 | 
			
		||||
                                                             callback,
 | 
			
		||||
                                                             user_data,
 | 
			
		||||
                                                             notify);
 | 
			
		||||
  watch = g_slice_new0 (MetaIdleMonitorWatch);
 | 
			
		||||
 | 
			
		||||
  watch->monitor = monitor;
 | 
			
		||||
  watch->id = get_next_watch_serial ();
 | 
			
		||||
  watch->callback = callback;
 | 
			
		||||
  watch->user_data = user_data;
 | 
			
		||||
  watch->notify = notify;
 | 
			
		||||
  watch->timeout_msec = timeout_msec;
 | 
			
		||||
 | 
			
		||||
  if (timeout_msec != 0)
 | 
			
		||||
    {
 | 
			
		||||
      GSource *source = g_source_new (&idle_monitor_source_funcs,
 | 
			
		||||
                                      sizeof (GSource));
 | 
			
		||||
 | 
			
		||||
      g_source_set_callback (source, NULL, watch, NULL);
 | 
			
		||||
      if (!monitor->inhibited)
 | 
			
		||||
        {
 | 
			
		||||
          g_source_set_ready_time (source,
 | 
			
		||||
                                   monitor->last_event_time +
 | 
			
		||||
                                   timeout_msec * 1000);
 | 
			
		||||
        }
 | 
			
		||||
      g_source_attach (source, NULL);
 | 
			
		||||
      g_source_unref (source);
 | 
			
		||||
 | 
			
		||||
      watch->timeout_source = source;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_hash_table_insert (monitor->watches,
 | 
			
		||||
                       GUINT_TO_POINTER (watch->id),
 | 
			
		||||
@@ -314,5 +475,39 @@ meta_idle_monitor_remove_watch (MetaIdleMonitor *monitor,
 | 
			
		||||
gint64
 | 
			
		||||
meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor)
 | 
			
		||||
{
 | 
			
		||||
  return META_IDLE_MONITOR_GET_CLASS (monitor)->get_idletime (monitor);
 | 
			
		||||
  return (g_get_monotonic_time () - monitor->last_event_time) / 1000;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor)
 | 
			
		||||
{
 | 
			
		||||
  GList *node, *watch_ids;
 | 
			
		||||
 | 
			
		||||
  monitor->last_event_time = g_get_monotonic_time ();
 | 
			
		||||
 | 
			
		||||
  watch_ids = g_hash_table_get_keys (monitor->watches);
 | 
			
		||||
 | 
			
		||||
  for (node = watch_ids; node != NULL; node = node->next)
 | 
			
		||||
    {
 | 
			
		||||
      guint watch_id = GPOINTER_TO_UINT (node->data);
 | 
			
		||||
      MetaIdleMonitorWatch *watch;
 | 
			
		||||
 | 
			
		||||
      watch = g_hash_table_lookup (monitor->watches,
 | 
			
		||||
                                   GUINT_TO_POINTER (watch_id));
 | 
			
		||||
      if (!watch)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (watch->timeout_msec == 0)
 | 
			
		||||
        {
 | 
			
		||||
          _meta_idle_monitor_watch_fire ((MetaIdleMonitorWatch *) watch);
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          g_source_set_ready_time (watch->timeout_source,
 | 
			
		||||
                                   monitor->last_event_time +
 | 
			
		||||
                                   watch->timeout_msec * 1000);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_list_free (watch_ids);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1088,7 +1088,7 @@ meta_input_settings_changed_cb (GSettings  *settings,
 | 
			
		||||
        update_device_natural_scroll (input_settings, NULL);
 | 
			
		||||
      else if (strcmp (key, "tap-to-click") == 0)
 | 
			
		||||
        update_touchpad_tap_enabled (input_settings, NULL);
 | 
			
		||||
      else if (strcmp (key, "tap-and_drag") == 0)
 | 
			
		||||
      else if (strcmp (key, "tap-and-drag") == 0)
 | 
			
		||||
        update_touchpad_tap_and_drag_enabled (input_settings, NULL);
 | 
			
		||||
      else if (strcmp(key, "disable-while-typing") == 0)
 | 
			
		||||
        update_touchpad_disable_while_typing (input_settings, NULL);
 | 
			
		||||
 
 | 
			
		||||
@@ -100,11 +100,12 @@ static MetaMonitorTransform
 | 
			
		||||
derive_monitor_transform (MetaMonitor *monitor)
 | 
			
		||||
{
 | 
			
		||||
  MetaOutput *main_output;
 | 
			
		||||
  MetaMonitorTransform transform;
 | 
			
		||||
 | 
			
		||||
  main_output = meta_monitor_get_main_output (monitor);
 | 
			
		||||
  transform = meta_output_get_assigned_crtc (main_output)->transform;
 | 
			
		||||
 | 
			
		||||
  return meta_monitor_crtc_to_logical_transform (monitor,
 | 
			
		||||
                                                 main_output->crtc->transform);
 | 
			
		||||
  return meta_monitor_crtc_to_logical_transform (monitor, transform);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaLogicalMonitor *
 | 
			
		||||
@@ -145,7 +146,7 @@ meta_logical_monitor_add_monitor (MetaLogicalMonitor *logical_monitor,
 | 
			
		||||
 | 
			
		||||
  is_presentation = logical_monitor->is_presentation;
 | 
			
		||||
  logical_monitor->monitors = g_list_append (logical_monitor->monitors,
 | 
			
		||||
                                             monitor);
 | 
			
		||||
                                             g_object_ref (monitor));
 | 
			
		||||
 | 
			
		||||
  for (l = logical_monitor->monitors; l; l = l->next)
 | 
			
		||||
    {
 | 
			
		||||
@@ -157,10 +158,12 @@ meta_logical_monitor_add_monitor (MetaLogicalMonitor *logical_monitor,
 | 
			
		||||
      for (l_output = outputs; l_output; l_output = l_output->next)
 | 
			
		||||
        {
 | 
			
		||||
          MetaOutput *output = l_output->data;
 | 
			
		||||
          MetaCrtc *crtc;
 | 
			
		||||
 | 
			
		||||
          is_presentation = is_presentation && output->is_presentation;
 | 
			
		||||
          if (output->crtc)
 | 
			
		||||
            output->crtc->logical_monitor = logical_monitor;
 | 
			
		||||
          crtc = meta_output_get_assigned_crtc (output);
 | 
			
		||||
          if (crtc)
 | 
			
		||||
            crtc->logical_monitor = logical_monitor;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -220,7 +223,7 @@ foreach_crtc (MetaMonitor         *monitor,
 | 
			
		||||
  ForeachCrtcData *data = user_data;
 | 
			
		||||
 | 
			
		||||
  data->func (data->logical_monitor,
 | 
			
		||||
              monitor_crtc_mode->output->crtc,
 | 
			
		||||
              meta_output_get_assigned_crtc (monitor_crtc_mode->output),
 | 
			
		||||
              data->user_data);
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
@@ -254,13 +257,17 @@ meta_logical_monitor_init (MetaLogicalMonitor *logical_monitor)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_logical_monitor_finalize (GObject *object)
 | 
			
		||||
meta_logical_monitor_dispose (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  MetaLogicalMonitor *logical_monitor = META_LOGICAL_MONITOR (object);
 | 
			
		||||
 | 
			
		||||
  g_list_free (logical_monitor->monitors);
 | 
			
		||||
  if (logical_monitor->monitors)
 | 
			
		||||
    {
 | 
			
		||||
      g_list_free_full (logical_monitor->monitors, g_object_unref);
 | 
			
		||||
      logical_monitor->monitors = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_logical_monitor_parent_class)->finalize (object);
 | 
			
		||||
  G_OBJECT_CLASS (meta_logical_monitor_parent_class)->dispose (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -268,7 +275,7 @@ meta_logical_monitor_class_init (MetaLogicalMonitorClass *klass)
 | 
			
		||||
{
 | 
			
		||||
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  object_class->finalize = meta_logical_monitor_finalize;
 | 
			
		||||
  object_class->dispose = meta_logical_monitor_dispose;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
 
 | 
			
		||||
@@ -486,7 +486,7 @@ apply_crtc_assignments (MetaMonitorManager *manager,
 | 
			
		||||
              output = ((MetaOutput**)crtc_info->outputs->pdata)[j];
 | 
			
		||||
 | 
			
		||||
              output->is_dirty = TRUE;
 | 
			
		||||
              output->crtc = crtc;
 | 
			
		||||
              meta_output_assign_crtc (output, crtc);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -531,7 +531,7 @@ apply_crtc_assignments (MetaMonitorManager *manager,
 | 
			
		||||
          continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      output->crtc = NULL;
 | 
			
		||||
      meta_output_unassign_crtc (output);
 | 
			
		||||
      output->is_primary = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -89,6 +89,9 @@ static gboolean
 | 
			
		||||
meta_monitor_manager_is_config_complete (MetaMonitorManager *manager,
 | 
			
		||||
                                         MetaMonitorsConfig *config);
 | 
			
		||||
 | 
			
		||||
static MetaMonitor *
 | 
			
		||||
meta_monitor_manager_get_active_monitor (MetaMonitorManager *manager);
 | 
			
		||||
 | 
			
		||||
MetaBackend *
 | 
			
		||||
meta_monitor_manager_get_backend (MetaMonitorManager *manager)
 | 
			
		||||
{
 | 
			
		||||
@@ -198,13 +201,17 @@ calculate_monitor_scale (MetaMonitorManager *manager,
 | 
			
		||||
static float
 | 
			
		||||
derive_calculated_global_scale (MetaMonitorManager *manager)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitor *primary_monitor;
 | 
			
		||||
  MetaMonitor *monitor = NULL;
 | 
			
		||||
 | 
			
		||||
  primary_monitor = meta_monitor_manager_get_primary_monitor (manager);
 | 
			
		||||
  if (!primary_monitor)
 | 
			
		||||
  monitor = meta_monitor_manager_get_primary_monitor (manager);
 | 
			
		||||
 | 
			
		||||
  if (!monitor || !meta_monitor_is_active (monitor))
 | 
			
		||||
    monitor = meta_monitor_manager_get_active_monitor (manager);
 | 
			
		||||
 | 
			
		||||
  if (!monitor)
 | 
			
		||||
    return 1.0;
 | 
			
		||||
 | 
			
		||||
  return calculate_monitor_scale (manager, primary_monitor);
 | 
			
		||||
  return calculate_monitor_scale (manager, monitor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static float
 | 
			
		||||
@@ -578,8 +585,6 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
 | 
			
		||||
                                                       &error))
 | 
			
		||||
        {
 | 
			
		||||
          g_clear_object (&config);
 | 
			
		||||
          g_warning ("Failed to use linear monitor configuration: %s",
 | 
			
		||||
                     error->message);
 | 
			
		||||
          g_clear_error (&error);
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
@@ -597,8 +602,6 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager)
 | 
			
		||||
                                                       &error))
 | 
			
		||||
        {
 | 
			
		||||
          g_clear_object (&config);
 | 
			
		||||
          g_warning ("Failed to use fallback monitor configuration: %s",
 | 
			
		||||
                 error->message);
 | 
			
		||||
          g_clear_error (&error);
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
@@ -1032,12 +1035,13 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
 | 
			
		||||
                             NULL /* properties */);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  for (l = combined_outputs; l; l = l->next)
 | 
			
		||||
  for (l = combined_outputs, i = 0; l; l = l->next, i++)
 | 
			
		||||
    {
 | 
			
		||||
      MetaOutput *output = l->data;
 | 
			
		||||
      GVariantBuilder crtcs, modes, clones, properties;
 | 
			
		||||
      GBytes *edid;
 | 
			
		||||
      char *edid_file;
 | 
			
		||||
      MetaCrtc *crtc;
 | 
			
		||||
      int crtc_index;
 | 
			
		||||
 | 
			
		||||
      g_variant_builder_init (&crtcs, G_VARIANT_TYPE ("au"));
 | 
			
		||||
@@ -1131,8 +1135,8 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
 | 
			
		||||
                                                output->tile_info.tile_h));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      crtc_index = output->crtc ? g_list_index (combined_crtcs, output->crtc)
 | 
			
		||||
                                : -1;
 | 
			
		||||
      crtc = meta_output_get_assigned_crtc (output);
 | 
			
		||||
      crtc_index = crtc ? g_list_index (combined_crtcs, crtc) : -1;
 | 
			
		||||
      g_variant_builder_add (&output_builder, "(uxiausauaua{sv})",
 | 
			
		||||
                             i, /* ID */
 | 
			
		||||
                             (gint64)output->winsys_id,
 | 
			
		||||
@@ -2382,6 +2386,12 @@ meta_monitor_manager_get_laptop_panel (MetaMonitorManager *manager)
 | 
			
		||||
  return find_monitor (manager, meta_monitor_is_laptop_panel);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaMonitor *
 | 
			
		||||
meta_monitor_manager_get_active_monitor (MetaMonitorManager *manager)
 | 
			
		||||
{
 | 
			
		||||
  return find_monitor (manager, meta_monitor_is_active);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaMonitor *
 | 
			
		||||
meta_monitor_manager_get_monitor_from_connector (MetaMonitorManager *manager,
 | 
			
		||||
                                                 const char         *connector)
 | 
			
		||||
@@ -2894,11 +2904,7 @@ meta_monitor_manager_get_monitor_for_connector (MetaMonitorManager *manager,
 | 
			
		||||
 | 
			
		||||
      if (meta_monitor_is_active (monitor) &&
 | 
			
		||||
          g_str_equal (connector, meta_monitor_get_connector (monitor)))
 | 
			
		||||
        {
 | 
			
		||||
          MetaOutput *main_output = meta_monitor_get_main_output (monitor);
 | 
			
		||||
 | 
			
		||||
          return main_output->crtc->logical_monitor->number;
 | 
			
		||||
        }
 | 
			
		||||
        return meta_monitor_get_logical_monitor (monitor)->number;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return -1;
 | 
			
		||||
 
 | 
			
		||||
@@ -204,10 +204,12 @@ gboolean
 | 
			
		||||
meta_monitor_is_active (MetaMonitor *monitor)
 | 
			
		||||
{
 | 
			
		||||
  MetaOutput *output;
 | 
			
		||||
  MetaCrtc *crtc;
 | 
			
		||||
 | 
			
		||||
  output = meta_monitor_get_main_output (monitor);
 | 
			
		||||
  crtc = meta_output_get_assigned_crtc (output);
 | 
			
		||||
 | 
			
		||||
  return output->crtc && output->crtc->current_mode;
 | 
			
		||||
  return crtc && crtc->current_mode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
@@ -385,6 +387,21 @@ meta_monitor_crtc_to_logical_transform (MetaMonitor          *monitor,
 | 
			
		||||
  return new_transform;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_dispose (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitor *monitor = META_MONITOR (object);
 | 
			
		||||
  MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
 | 
			
		||||
 | 
			
		||||
  if (priv->outputs)
 | 
			
		||||
    {
 | 
			
		||||
      g_list_free_full (priv->outputs, g_object_unref);
 | 
			
		||||
      priv->outputs = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_monitor_parent_class)->dispose (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_monitor_finalize (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
@@ -393,7 +410,6 @@ meta_monitor_finalize (GObject *object)
 | 
			
		||||
 | 
			
		||||
  g_hash_table_destroy (priv->mode_ids);
 | 
			
		||||
  g_list_free_full (priv->modes, (GDestroyNotify) meta_monitor_mode_free);
 | 
			
		||||
  g_clear_pointer (&priv->outputs, g_list_free);
 | 
			
		||||
  meta_monitor_spec_free (priv->spec);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_monitor_parent_class)->finalize (object);
 | 
			
		||||
@@ -412,6 +428,7 @@ meta_monitor_class_init (MetaMonitorClass *klass)
 | 
			
		||||
{
 | 
			
		||||
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  object_class->dispose = meta_monitor_dispose;
 | 
			
		||||
  object_class->finalize = meta_monitor_finalize;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -493,6 +510,7 @@ meta_monitor_normal_generate_modes (MetaMonitorNormal *monitor_normal)
 | 
			
		||||
  for (i = 0; i < output->n_modes; i++)
 | 
			
		||||
    {
 | 
			
		||||
      MetaCrtcMode *crtc_mode = output->modes[i];
 | 
			
		||||
      MetaCrtc *crtc;
 | 
			
		||||
      MetaMonitorMode *mode;
 | 
			
		||||
      gboolean replace;
 | 
			
		||||
 | 
			
		||||
@@ -526,7 +544,9 @@ meta_monitor_normal_generate_modes (MetaMonitorNormal *monitor_normal)
 | 
			
		||||
 | 
			
		||||
      if (crtc_mode == output->preferred_mode)
 | 
			
		||||
        monitor_priv->preferred_mode = mode;
 | 
			
		||||
      if (output->crtc && crtc_mode == output->crtc->current_mode)
 | 
			
		||||
 | 
			
		||||
      crtc = meta_output_get_assigned_crtc (output);
 | 
			
		||||
      if (crtc && crtc_mode == crtc->current_mode)
 | 
			
		||||
        monitor_priv->current_mode = mode;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -545,7 +565,7 @@ meta_monitor_normal_new (MetaGpu    *gpu,
 | 
			
		||||
 | 
			
		||||
  monitor_priv->gpu = gpu;
 | 
			
		||||
 | 
			
		||||
  monitor_priv->outputs = g_list_append (NULL, output);
 | 
			
		||||
  monitor_priv->outputs = g_list_append (NULL, g_object_ref (output));
 | 
			
		||||
  monitor_priv->winsys_id = output->winsys_id;
 | 
			
		||||
  meta_monitor_generate_spec (monitor);
 | 
			
		||||
 | 
			
		||||
@@ -568,13 +588,15 @@ meta_monitor_normal_derive_layout (MetaMonitor   *monitor,
 | 
			
		||||
                                   MetaRectangle *layout)
 | 
			
		||||
{
 | 
			
		||||
  MetaOutput *output;
 | 
			
		||||
  MetaCrtc *crtc;
 | 
			
		||||
 | 
			
		||||
  output = meta_monitor_get_main_output (monitor);
 | 
			
		||||
  crtc = meta_output_get_assigned_crtc (output);
 | 
			
		||||
  *layout = (MetaRectangle) {
 | 
			
		||||
    .x = output->crtc->rect.x,
 | 
			
		||||
    .y = output->crtc->rect.y,
 | 
			
		||||
    .width = output->crtc->rect.width,
 | 
			
		||||
    .height = output->crtc->rect.height
 | 
			
		||||
    .x = crtc->rect.x,
 | 
			
		||||
    .y = crtc->rect.y,
 | 
			
		||||
    .width = crtc->rect.width,
 | 
			
		||||
    .height = crtc->rect.height
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -658,7 +680,8 @@ add_tiled_monitor_outputs (MetaGpu          *gpu,
 | 
			
		||||
      g_warn_if_fail (output->subpixel_order ==
 | 
			
		||||
                      monitor_tiled->origin_output->subpixel_order);
 | 
			
		||||
 | 
			
		||||
      monitor_priv->outputs = g_list_append (monitor_priv->outputs, output);
 | 
			
		||||
      monitor_priv->outputs = g_list_append (monitor_priv->outputs,
 | 
			
		||||
                                             g_object_ref (output));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -764,12 +787,13 @@ is_monitor_mode_assigned (MetaMonitor     *monitor,
 | 
			
		||||
    {
 | 
			
		||||
      MetaOutput *output = l->data;
 | 
			
		||||
      MetaMonitorCrtcMode *monitor_crtc_mode = &mode->crtc_modes[i];
 | 
			
		||||
      MetaCrtc *crtc;
 | 
			
		||||
 | 
			
		||||
      crtc = meta_output_get_assigned_crtc (output);
 | 
			
		||||
      if (monitor_crtc_mode->crtc_mode &&
 | 
			
		||||
          (!output->crtc ||
 | 
			
		||||
           output->crtc->current_mode != monitor_crtc_mode->crtc_mode))
 | 
			
		||||
          (!crtc || crtc->current_mode != monitor_crtc_mode->crtc_mode))
 | 
			
		||||
        return FALSE;
 | 
			
		||||
      else if (!monitor_crtc_mode->crtc_mode && output->crtc)
 | 
			
		||||
      else if (!monitor_crtc_mode->crtc_mode && crtc)
 | 
			
		||||
        return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1217,14 +1241,16 @@ meta_monitor_tiled_derive_layout (MetaMonitor   *monitor,
 | 
			
		||||
  for (l = monitor_priv->outputs; l; l = l->next)
 | 
			
		||||
    {
 | 
			
		||||
      MetaOutput *output = l->data;
 | 
			
		||||
      MetaCrtc *crtc;
 | 
			
		||||
 | 
			
		||||
      if (!output->crtc)
 | 
			
		||||
      crtc = meta_output_get_assigned_crtc (output);
 | 
			
		||||
      if (!crtc)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      min_x = MIN (output->crtc->rect.x, min_x);
 | 
			
		||||
      min_y = MIN (output->crtc->rect.y, min_y);
 | 
			
		||||
      max_x = MAX (output->crtc->rect.x + output->crtc->rect.width, max_x);
 | 
			
		||||
      max_y = MAX (output->crtc->rect.y + output->crtc->rect.height, max_y);
 | 
			
		||||
      min_x = MIN (crtc->rect.x, min_x);
 | 
			
		||||
      min_y = MIN (crtc->rect.y, min_y);
 | 
			
		||||
      max_x = MAX (crtc->rect.x + crtc->rect.width, max_x);
 | 
			
		||||
      max_y = MAX (crtc->rect.y + crtc->rect.height, max_y);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  *layout = (MetaRectangle) {
 | 
			
		||||
@@ -1318,10 +1344,14 @@ meta_monitor_get_spec (MetaMonitor *monitor)
 | 
			
		||||
MetaLogicalMonitor *
 | 
			
		||||
meta_monitor_get_logical_monitor (MetaMonitor *monitor)
 | 
			
		||||
{
 | 
			
		||||
  MetaOutput *output = meta_monitor_get_main_output (monitor);
 | 
			
		||||
  MetaOutput *output;
 | 
			
		||||
  MetaCrtc *crtc;
 | 
			
		||||
 | 
			
		||||
  if (output->crtc)
 | 
			
		||||
    return output->crtc->logical_monitor;
 | 
			
		||||
  output = meta_monitor_get_main_output (monitor);
 | 
			
		||||
  crtc = meta_output_get_assigned_crtc (output);
 | 
			
		||||
 | 
			
		||||
  if (crtc)
 | 
			
		||||
    return crtc->logical_monitor;
 | 
			
		||||
  else
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,13 @@
 | 
			
		||||
 | 
			
		||||
#include "backends/meta-output.h"
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (MetaOutput, meta_output, G_TYPE_OBJECT)
 | 
			
		||||
typedef struct _MetaOutputPrivate
 | 
			
		||||
{
 | 
			
		||||
  /* The CRTC driving this output, NULL if the output is not enabled */
 | 
			
		||||
  MetaCrtc *crtc;
 | 
			
		||||
} MetaOutputPrivate;
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaOutput, meta_output, G_TYPE_OBJECT)
 | 
			
		||||
 | 
			
		||||
MetaGpu *
 | 
			
		||||
meta_output_get_gpu (MetaOutput *output)
 | 
			
		||||
@@ -29,6 +35,44 @@ meta_output_get_gpu (MetaOutput *output)
 | 
			
		||||
  return output->gpu;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_output_assign_crtc (MetaOutput *output,
 | 
			
		||||
                         MetaCrtc   *crtc)
 | 
			
		||||
{
 | 
			
		||||
  MetaOutputPrivate *priv = meta_output_get_instance_private (output);
 | 
			
		||||
 | 
			
		||||
  g_assert (crtc);
 | 
			
		||||
 | 
			
		||||
  g_set_object (&priv->crtc, crtc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_output_unassign_crtc (MetaOutput *output)
 | 
			
		||||
{
 | 
			
		||||
  MetaOutputPrivate *priv = meta_output_get_instance_private (output);
 | 
			
		||||
 | 
			
		||||
  g_clear_object (&priv->crtc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaCrtc *
 | 
			
		||||
meta_output_get_assigned_crtc (MetaOutput *output)
 | 
			
		||||
{
 | 
			
		||||
  MetaOutputPrivate *priv = meta_output_get_instance_private (output);
 | 
			
		||||
 | 
			
		||||
  return priv->crtc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_output_dispose (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  MetaOutput *output = META_OUTPUT (object);
 | 
			
		||||
  MetaOutputPrivate *priv = meta_output_get_instance_private (output);
 | 
			
		||||
 | 
			
		||||
  g_clear_object (&priv->crtc);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_output_parent_class)->dispose (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_output_finalize (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
@@ -58,5 +102,6 @@ meta_output_class_init (MetaOutputClass *klass)
 | 
			
		||||
{
 | 
			
		||||
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  object_class->dispose = meta_output_dispose;
 | 
			
		||||
  object_class->finalize = meta_output_finalize;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -64,9 +64,6 @@ struct _MetaOutput
 | 
			
		||||
 | 
			
		||||
  MetaGpu *gpu;
 | 
			
		||||
 | 
			
		||||
  /* 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 winsys_id;
 | 
			
		||||
  char *name;
 | 
			
		||||
@@ -122,4 +119,11 @@ G_DECLARE_FINAL_TYPE (MetaOutput, meta_output, META, OUTPUT, GObject)
 | 
			
		||||
 | 
			
		||||
MetaGpu * meta_output_get_gpu (MetaOutput *output);
 | 
			
		||||
 | 
			
		||||
void meta_output_assign_crtc (MetaOutput *output,
 | 
			
		||||
                              MetaCrtc   *crtc);
 | 
			
		||||
 | 
			
		||||
void meta_output_unassign_crtc (MetaOutput *output);
 | 
			
		||||
 | 
			
		||||
MetaCrtc * meta_output_get_assigned_crtc (MetaOutput *output);
 | 
			
		||||
 | 
			
		||||
#endif /* META_OUTPUT_H */
 | 
			
		||||
 
 | 
			
		||||
@@ -153,6 +153,11 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  buffer = pw_stream_peek_buffer (priv->pipewire_stream, buffer_id);
 | 
			
		||||
  if (!buffer)
 | 
			
		||||
    {
 | 
			
		||||
      g_warning ("Failed to peek at PipeWire buffer");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (buffer->datas[0].type == priv->pipewire_type->data.MemFd)
 | 
			
		||||
    {
 | 
			
		||||
@@ -327,10 +332,18 @@ create_pipewire_stream (MetaScreenCastStreamSrc  *src,
 | 
			
		||||
  struct spa_fraction max_framerate;
 | 
			
		||||
  struct spa_fraction min_framerate;
 | 
			
		||||
  const struct spa_pod *params[1];
 | 
			
		||||
  int result;
 | 
			
		||||
 | 
			
		||||
  pipewire_stream = pw_stream_new (priv->pipewire_remote,
 | 
			
		||||
                                   "meta-screen-cast-src",
 | 
			
		||||
                                   NULL);
 | 
			
		||||
  if (!pipewire_stream)
 | 
			
		||||
    {
 | 
			
		||||
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
 | 
			
		||||
                   "Failed to create PipeWire stream: %s",
 | 
			
		||||
                   strerror (errno));
 | 
			
		||||
      return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_screen_cast_stream_src_get_specs (src, &width, &height, &frame_rate);
 | 
			
		||||
  frame_rate_fraction = meta_fraction_from_double (frame_rate);
 | 
			
		||||
@@ -347,23 +360,24 @@ create_pipewire_stream (MetaScreenCastStreamSrc  *src,
 | 
			
		||||
    ":", spa_type->format_video.format, "I", spa_type->video_format.BGRx,
 | 
			
		||||
    ":", spa_type->format_video.size, "R", &SPA_RECTANGLE (width, height),
 | 
			
		||||
    ":", spa_type->format_video.framerate, "F", &SPA_FRACTION (0, 1),
 | 
			
		||||
    ":", spa_type->format_video.max_framerate, "Fr", &max_framerate,
 | 
			
		||||
                                                     PROP_RANGE (&min_framerate,
 | 
			
		||||
                                                                 &max_framerate));
 | 
			
		||||
    ":", spa_type->format_video.max_framerate, "Fru", &max_framerate,
 | 
			
		||||
                                                      PROP_RANGE (&min_framerate,
 | 
			
		||||
                                                                  &max_framerate));
 | 
			
		||||
 | 
			
		||||
  pw_stream_add_listener (pipewire_stream,
 | 
			
		||||
                          &priv->pipewire_stream_listener,
 | 
			
		||||
                          &stream_events,
 | 
			
		||||
                          src);
 | 
			
		||||
 | 
			
		||||
  if (pw_stream_connect (pipewire_stream,
 | 
			
		||||
                         PW_DIRECTION_OUTPUT,
 | 
			
		||||
                         NULL,
 | 
			
		||||
                         PW_STREAM_FLAG_NONE,
 | 
			
		||||
                         params, G_N_ELEMENTS (¶ms)) != 0)
 | 
			
		||||
  result = pw_stream_connect (pipewire_stream,
 | 
			
		||||
                              PW_DIRECTION_OUTPUT,
 | 
			
		||||
                              NULL,
 | 
			
		||||
                              PW_STREAM_FLAG_NONE,
 | 
			
		||||
                              params, G_N_ELEMENTS (params));
 | 
			
		||||
  if (result != 0)
 | 
			
		||||
    {
 | 
			
		||||
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
 | 
			
		||||
                   "Could not connect");
 | 
			
		||||
                   "Could not connect: %s", spa_strerror (result));
 | 
			
		||||
      return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -466,6 +480,12 @@ create_pipewire_source (void)
 | 
			
		||||
    (MetaPipeWireSource *) g_source_new (&pipewire_source_funcs,
 | 
			
		||||
                                         sizeof (MetaPipeWireSource));
 | 
			
		||||
  pipewire_source->pipewire_loop = pw_loop_new (NULL);
 | 
			
		||||
  if (!pipewire_source->pipewire_loop)
 | 
			
		||||
    {
 | 
			
		||||
      g_source_destroy ((GSource *) pipewire_source);
 | 
			
		||||
      return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_source_add_unix_fd (&pipewire_source->base,
 | 
			
		||||
                        pw_loop_get_fd (pipewire_source->pipewire_loop),
 | 
			
		||||
                        G_IO_IN | G_IO_ERR);
 | 
			
		||||
@@ -491,6 +511,13 @@ meta_screen_cast_stream_src_initable_init (GInitable     *initable,
 | 
			
		||||
    meta_screen_cast_stream_src_get_instance_private (src);
 | 
			
		||||
 | 
			
		||||
  priv->pipewire_source = create_pipewire_source ();
 | 
			
		||||
  if (!priv->pipewire_source)
 | 
			
		||||
    {
 | 
			
		||||
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
 | 
			
		||||
                   "Failed to create PipeWire source");
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  priv->pipewire_core = pw_core_new (priv->pipewire_source->pipewire_loop,
 | 
			
		||||
                                     NULL);
 | 
			
		||||
  if (!priv->pipewire_core)
 | 
			
		||||
 
 | 
			
		||||
@@ -33,6 +33,7 @@ typedef enum _MetaExperimentalFeature
 | 
			
		||||
  META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER = (1 << 0),
 | 
			
		||||
  META_EXPERIMENTAL_FEATURE_SCREEN_CAST = (1 << 1),
 | 
			
		||||
  META_EXPERIMENTAL_FEATURE_REMOTE_DESKTOP  = (1 << 2),
 | 
			
		||||
  META_EXPERIMENTAL_FEATURE_KMS_MODIFIERS = (1 << 3),
 | 
			
		||||
} MetaExperimentalFeature;
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_SETTINGS (meta_settings_get_type ())
 | 
			
		||||
 
 | 
			
		||||
@@ -267,6 +267,8 @@ experimental_features_handler (GVariant *features_variant,
 | 
			
		||||
        features |= META_EXPERIMENTAL_FEATURE_SCREEN_CAST;
 | 
			
		||||
      else if (g_str_equal (feature, "remote-desktop"))
 | 
			
		||||
        features |= META_EXPERIMENTAL_FEATURE_REMOTE_DESKTOP;
 | 
			
		||||
      else if (g_str_equal (feature, "kms-modifiers"))
 | 
			
		||||
        features |= META_EXPERIMENTAL_FEATURE_KMS_MODIFIERS;
 | 
			
		||||
      else
 | 
			
		||||
        g_info ("Unknown experimental feature '%s'\n", feature);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -17,39 +17,23 @@
 | 
			
		||||
 * 02111-1307, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef META_STAGE_H
 | 
			
		||||
#define META_STAGE_H
 | 
			
		||||
#ifndef META_STAGE_PRIVATE_H
 | 
			
		||||
#define META_STAGE_PRIVATE_H
 | 
			
		||||
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
#include <meta/meta-stage.h>
 | 
			
		||||
 | 
			
		||||
#include "meta-cursor.h"
 | 
			
		||||
#include <meta/boxes.h>
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_STAGE            (meta_stage_get_type ())
 | 
			
		||||
#define META_STAGE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_STAGE, MetaStage))
 | 
			
		||||
#define META_STAGE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_STAGE, MetaStageClass))
 | 
			
		||||
#define META_IS_STAGE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_STAGE))
 | 
			
		||||
#define META_IS_STAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_STAGE))
 | 
			
		||||
#define META_STAGE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_STAGE, MetaStageClass))
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaStage      MetaStage;
 | 
			
		||||
typedef struct _MetaStageClass MetaStageClass;
 | 
			
		||||
typedef struct _MetaOverlay    MetaOverlay;
 | 
			
		||||
 | 
			
		||||
struct _MetaStageClass
 | 
			
		||||
{
 | 
			
		||||
  ClutterStageClass parent_class;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaStage
 | 
			
		||||
{
 | 
			
		||||
  ClutterStage parent;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GType             meta_stage_get_type                (void) G_GNUC_CONST;
 | 
			
		||||
 | 
			
		||||
ClutterActor     *meta_stage_new                     (void);
 | 
			
		||||
 | 
			
		||||
MetaOverlay      *meta_stage_create_cursor_overlay   (MetaStage   *stage);
 | 
			
		||||
@@ -68,4 +52,4 @@ void meta_stage_update_view_layout (MetaStage *stage);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* META_STAGE_H */
 | 
			
		||||
#endif /* META_STAGE_PRIVATE_H */
 | 
			
		||||
@@ -22,7 +22,7 @@
 | 
			
		||||
 | 
			
		||||
#include <config.h>
 | 
			
		||||
 | 
			
		||||
#include "meta-stage.h"
 | 
			
		||||
#include "meta-stage-private.h"
 | 
			
		||||
 | 
			
		||||
#include <meta/meta-backend.h>
 | 
			
		||||
#include <meta/meta-monitor-manager.h>
 | 
			
		||||
 
 | 
			
		||||
@@ -35,15 +35,15 @@
 | 
			
		||||
#include "clutter/evdev/clutter-evdev.h"
 | 
			
		||||
#include "meta-barrier-native.h"
 | 
			
		||||
#include "meta-border.h"
 | 
			
		||||
#include "meta-idle-monitor-native.h"
 | 
			
		||||
#include "meta-monitor-manager-kms.h"
 | 
			
		||||
#include "meta-cursor-renderer-native.h"
 | 
			
		||||
#include "meta-launcher.h"
 | 
			
		||||
#include "backends/meta-cursor-tracker-private.h"
 | 
			
		||||
#include "backends/meta-idle-monitor-private.h"
 | 
			
		||||
#include "backends/meta-logical-monitor.h"
 | 
			
		||||
#include "backends/meta-monitor-manager-private.h"
 | 
			
		||||
#include "backends/meta-pointer-constraint.h"
 | 
			
		||||
#include "backends/meta-stage.h"
 | 
			
		||||
#include "backends/meta-stage-private.h"
 | 
			
		||||
#include "backends/native/meta-clutter-backend-native.h"
 | 
			
		||||
#include "backends/native/meta-input-settings-native.h"
 | 
			
		||||
#include "backends/native/meta-renderer-native.h"
 | 
			
		||||
@@ -60,10 +60,6 @@ struct _MetaBackendNativePrivate
 | 
			
		||||
{
 | 
			
		||||
  MetaLauncher *launcher;
 | 
			
		||||
  MetaBarrierManagerNative *barrier_manager;
 | 
			
		||||
  UpClient *up_client;
 | 
			
		||||
  guint sleep_signal_id;
 | 
			
		||||
  GCancellable *cancellable;
 | 
			
		||||
  GDBusConnection *system_bus;
 | 
			
		||||
};
 | 
			
		||||
typedef struct _MetaBackendNativePrivate MetaBackendNativePrivate;
 | 
			
		||||
 | 
			
		||||
@@ -85,69 +81,9 @@ 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,
 | 
			
		||||
@@ -398,15 +334,6 @@ meta_backend_native_post_init (MetaBackend *backend)
 | 
			
		||||
                                            meta_backend_get_monitor_manager (backend));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaIdleMonitor *
 | 
			
		||||
meta_backend_native_create_idle_monitor (MetaBackend *backend,
 | 
			
		||||
                                         int          device_id)
 | 
			
		||||
{
 | 
			
		||||
  return g_object_new (META_TYPE_IDLE_MONITOR_NATIVE,
 | 
			
		||||
                       "device-id", device_id,
 | 
			
		||||
                       NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaMonitorManager *
 | 
			
		||||
meta_backend_native_create_monitor_manager (MetaBackend *backend,
 | 
			
		||||
                                            GError     **error)
 | 
			
		||||
@@ -604,7 +531,6 @@ meta_backend_native_class_init (MetaBackendNativeClass *klass)
 | 
			
		||||
 | 
			
		||||
  backend_class->post_init = meta_backend_native_post_init;
 | 
			
		||||
 | 
			
		||||
  backend_class->create_idle_monitor = meta_backend_native_create_idle_monitor;
 | 
			
		||||
  backend_class->create_monitor_manager = meta_backend_native_create_monitor_manager;
 | 
			
		||||
  backend_class->create_cursor_renderer = meta_backend_native_create_cursor_renderer;
 | 
			
		||||
  backend_class->create_renderer = meta_backend_native_create_renderer;
 | 
			
		||||
@@ -637,16 +563,6 @@ meta_backend_native_init (MetaBackendNative *native)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaLauncher *
 | 
			
		||||
@@ -747,5 +663,5 @@ void meta_backend_native_resume (MetaBackendNative *native)
 | 
			
		||||
  meta_cursor_renderer_native_force_update (cursor_renderer_native);
 | 
			
		||||
 | 
			
		||||
  idle_monitor = meta_backend_get_idle_monitor (backend, 0);
 | 
			
		||||
  meta_idle_monitor_native_reset_idletime (idle_monitor);
 | 
			
		||||
  meta_idle_monitor_reset_idletime (idle_monitor);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -291,9 +291,12 @@ update_monitor_crtc_cursor (MetaMonitor         *monitor,
 | 
			
		||||
    data->in_cursor_renderer_native;
 | 
			
		||||
  MetaCursorRendererNativePrivate *priv =
 | 
			
		||||
    meta_cursor_renderer_native_get_instance_private (cursor_renderer_native);
 | 
			
		||||
  MetaCrtc *crtc;
 | 
			
		||||
  MetaMonitorTransform transform;
 | 
			
		||||
  ClutterRect scaled_crtc_rect;
 | 
			
		||||
  float scale;
 | 
			
		||||
  int crtc_x, crtc_y;
 | 
			
		||||
  int crtc_width, crtc_height;
 | 
			
		||||
 | 
			
		||||
  if (meta_is_stage_views_scaled ())
 | 
			
		||||
    scale = meta_logical_monitor_get_scale (data->in_logical_monitor);
 | 
			
		||||
@@ -305,17 +308,31 @@ update_monitor_crtc_cursor (MetaMonitor         *monitor,
 | 
			
		||||
                                   META_MONITOR_TRANSFORM_NORMAL,
 | 
			
		||||
                                   &crtc_x, &crtc_y);
 | 
			
		||||
 | 
			
		||||
  transform = meta_logical_monitor_get_transform (data->in_logical_monitor);
 | 
			
		||||
  if (meta_monitor_transform_is_rotated (transform))
 | 
			
		||||
    {
 | 
			
		||||
      crtc_width = monitor_crtc_mode->crtc_mode->height;
 | 
			
		||||
      crtc_height = monitor_crtc_mode->crtc_mode->width;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      crtc_width = monitor_crtc_mode->crtc_mode->width;
 | 
			
		||||
      crtc_height = monitor_crtc_mode->crtc_mode->height;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  scaled_crtc_rect = (ClutterRect) {
 | 
			
		||||
    .origin = {
 | 
			
		||||
      .x = crtc_x / scale,
 | 
			
		||||
      .y = crtc_y / scale
 | 
			
		||||
    },
 | 
			
		||||
    .size = {
 | 
			
		||||
      .width = monitor_crtc_mode->crtc_mode->width / scale,
 | 
			
		||||
      .height = monitor_crtc_mode->crtc_mode->height / scale
 | 
			
		||||
      .width = crtc_width / scale,
 | 
			
		||||
      .height = crtc_height / scale
 | 
			
		||||
    },
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  crtc = meta_output_get_assigned_crtc (monitor_crtc_mode->output);
 | 
			
		||||
 | 
			
		||||
  if (priv->has_hw_cursor &&
 | 
			
		||||
      clutter_rect_intersection (&scaled_crtc_rect,
 | 
			
		||||
                                 &data->in_local_cursor_rect,
 | 
			
		||||
@@ -326,7 +343,7 @@ update_monitor_crtc_cursor (MetaMonitor         *monitor,
 | 
			
		||||
      float crtc_cursor_x, crtc_cursor_y;
 | 
			
		||||
 | 
			
		||||
      set_crtc_cursor (data->in_cursor_renderer_native,
 | 
			
		||||
                       monitor_crtc_mode->output->crtc,
 | 
			
		||||
                       crtc,
 | 
			
		||||
                       data->in_cursor_sprite);
 | 
			
		||||
 | 
			
		||||
      gpu_kms = META_GPU_KMS (meta_monitor_get_gpu (monitor));
 | 
			
		||||
@@ -336,7 +353,7 @@ update_monitor_crtc_cursor (MetaMonitor         *monitor,
 | 
			
		||||
      crtc_cursor_y = (data->in_local_cursor_rect.origin.y -
 | 
			
		||||
                       scaled_crtc_rect.origin.y) * scale;
 | 
			
		||||
      drmModeMoveCursor (kms_fd,
 | 
			
		||||
                         monitor_crtc_mode->output->crtc->crtc_id,
 | 
			
		||||
                         crtc->crtc_id,
 | 
			
		||||
                         roundf (crtc_cursor_x),
 | 
			
		||||
                         roundf (crtc_cursor_y));
 | 
			
		||||
 | 
			
		||||
@@ -344,8 +361,7 @@ update_monitor_crtc_cursor (MetaMonitor         *monitor,
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      set_crtc_cursor (data->in_cursor_renderer_native,
 | 
			
		||||
                       monitor_crtc_mode->output->crtc, NULL);
 | 
			
		||||
      set_crtc_cursor (data->in_cursor_renderer_native, crtc, NULL);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
 
 | 
			
		||||
@@ -64,6 +64,7 @@ struct _MetaGpuKms
 | 
			
		||||
  gboolean page_flips_not_supported;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
G_DEFINE_QUARK (MetaGpuKmsError, meta_gpu_kms_error)
 | 
			
		||||
G_DEFINE_TYPE (MetaGpuKms, meta_gpu_kms, META_TYPE_GPU)
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
@@ -104,8 +105,10 @@ get_crtc_drm_connectors (MetaGpu       *gpu,
 | 
			
		||||
  for (l = meta_gpu_get_outputs (gpu); l; l = l->next)
 | 
			
		||||
    {
 | 
			
		||||
      MetaOutput *output = l->data;
 | 
			
		||||
      MetaCrtc *assigned_crtc;
 | 
			
		||||
 | 
			
		||||
      if (output->crtc == crtc)
 | 
			
		||||
      assigned_crtc = meta_output_get_assigned_crtc (output);
 | 
			
		||||
      if (assigned_crtc == crtc)
 | 
			
		||||
        g_array_append_val (connectors_array, output->winsys_id);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -185,8 +188,10 @@ meta_gpu_kms_is_crtc_active (MetaGpuKms *gpu_kms,
 | 
			
		||||
  for (l = meta_gpu_get_outputs (gpu); l; l = l->next)
 | 
			
		||||
    {
 | 
			
		||||
      MetaOutput *output = l->data;
 | 
			
		||||
      MetaCrtc *assigned_crtc;
 | 
			
		||||
 | 
			
		||||
      if (output->crtc == crtc)
 | 
			
		||||
      assigned_crtc = meta_output_get_assigned_crtc (output);
 | 
			
		||||
      if (assigned_crtc == crtc)
 | 
			
		||||
        {
 | 
			
		||||
          connected_crtc_found = TRUE;
 | 
			
		||||
          break;
 | 
			
		||||
@@ -751,6 +756,8 @@ meta_gpu_kms_read_current (MetaGpu  *gpu,
 | 
			
		||||
     are freed by the platform-independent layer. */
 | 
			
		||||
  free_resources (gpu_kms);
 | 
			
		||||
 | 
			
		||||
  g_assert (resources.resources->count_connectors > 0);
 | 
			
		||||
 | 
			
		||||
  init_connectors (gpu_kms, resources.resources);
 | 
			
		||||
  init_modes (gpu_kms, resources.resources);
 | 
			
		||||
  init_crtcs (gpu_kms, &resources);
 | 
			
		||||
@@ -774,11 +781,39 @@ meta_gpu_kms_new (MetaMonitorManagerKms  *monitor_manager_kms,
 | 
			
		||||
  GSource *source;
 | 
			
		||||
  MetaKmsSource *kms_source;
 | 
			
		||||
  MetaGpuKms *gpu_kms;
 | 
			
		||||
  drmModeRes *drm_resources;
 | 
			
		||||
  guint n_connectors;
 | 
			
		||||
  int kms_fd;
 | 
			
		||||
 | 
			
		||||
  kms_fd = meta_launcher_open_restricted (launcher, kms_file_path, error);
 | 
			
		||||
  if (kms_fd == -1)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
    return NULL;
 | 
			
		||||
 | 
			
		||||
  /* Some GPUs might have no connectors, for example dedicated GPUs on PRIME (hybrid) laptops.
 | 
			
		||||
   * These GPUs cannot render anything on separate screens, and they are aggressively switched
 | 
			
		||||
   * off by the kernel.
 | 
			
		||||
   *
 | 
			
		||||
   * If we add these PRIME GPUs to the GPU list anyway, Mutter keeps awakening the secondary GPU,
 | 
			
		||||
   * and doing this causes a considerable stuttering. These GPUs are usually put to sleep again
 | 
			
		||||
   * after ~2s without a workload.
 | 
			
		||||
   *
 | 
			
		||||
   * For now, to avoid this situation, only create the MetaGpuKms when the GPU has any connectors.
 | 
			
		||||
   */
 | 
			
		||||
  drm_resources = drmModeGetResources (kms_fd);
 | 
			
		||||
 | 
			
		||||
  n_connectors = drm_resources->count_connectors;
 | 
			
		||||
 | 
			
		||||
  drmModeFreeResources (drm_resources);
 | 
			
		||||
 | 
			
		||||
  if (n_connectors == 0)
 | 
			
		||||
    {
 | 
			
		||||
      g_set_error (error,
 | 
			
		||||
                   META_GPU_KMS_ERROR,
 | 
			
		||||
                   META_GPU_KMS_ERROR_NO_CONNECTORS,
 | 
			
		||||
                   "No connectors available in this GPU. This is probably a dedicated GPU in a hybrid setup.");
 | 
			
		||||
      meta_launcher_close_restricted (launcher, kms_fd);
 | 
			
		||||
      return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  gpu_kms = g_object_new (META_TYPE_GPU_KMS,
 | 
			
		||||
                          "monitor-manager", monitor_manager_kms,
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,14 @@
 | 
			
		||||
#include "backends/meta-gpu.h"
 | 
			
		||||
#include "backends/native/meta-monitor-manager-kms.h"
 | 
			
		||||
 | 
			
		||||
typedef enum
 | 
			
		||||
{
 | 
			
		||||
  META_GPU_KMS_ERROR_NO_CONNECTORS,
 | 
			
		||||
} MetaGpuKmsError;
 | 
			
		||||
 | 
			
		||||
#define META_GPU_KMS_ERROR (meta_gpu_kms_error_quark ())
 | 
			
		||||
GQuark meta_gpu_kms_error_quark (void);
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_GPU_KMS (meta_gpu_kms_get_type ())
 | 
			
		||||
G_DECLARE_FINAL_TYPE (MetaGpuKms, meta_gpu_kms, META, GPU_KMS, MetaGpu)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,200 +0,0 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 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, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 * Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
 | 
			
		||||
 *         from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include "meta-idle-monitor-native.h"
 | 
			
		||||
#include "meta-idle-monitor-private.h"
 | 
			
		||||
 | 
			
		||||
#include <meta/util.h>
 | 
			
		||||
#include "display-private.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
struct _MetaIdleMonitorNative
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitor parent;
 | 
			
		||||
 | 
			
		||||
  guint64 last_event_time;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaIdleMonitorNativeClass
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitorClass parent_class;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  MetaIdleMonitorWatch base;
 | 
			
		||||
 | 
			
		||||
  GSource *timeout_source;
 | 
			
		||||
} MetaIdleMonitorWatchNative;
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (MetaIdleMonitorNative, meta_idle_monitor_native, META_TYPE_IDLE_MONITOR)
 | 
			
		||||
 | 
			
		||||
static gint64
 | 
			
		||||
meta_idle_monitor_native_get_idletime (MetaIdleMonitor *monitor)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitorNative *monitor_native = META_IDLE_MONITOR_NATIVE (monitor);
 | 
			
		||||
 | 
			
		||||
  return (g_get_monotonic_time () - monitor_native->last_event_time) / 1000;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static guint32
 | 
			
		||||
get_next_watch_serial (void)
 | 
			
		||||
{
 | 
			
		||||
  static guint32 serial = 0;
 | 
			
		||||
  g_atomic_int_inc (&serial);
 | 
			
		||||
  return serial;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
native_dispatch_timeout (GSource     *source,
 | 
			
		||||
                         GSourceFunc  callback,
 | 
			
		||||
                         gpointer     user_data)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitorWatchNative *watch_native = user_data;
 | 
			
		||||
  MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_native;
 | 
			
		||||
 | 
			
		||||
  _meta_idle_monitor_watch_fire (watch);
 | 
			
		||||
  g_source_set_ready_time (watch_native->timeout_source, -1);
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static GSourceFuncs native_source_funcs = {
 | 
			
		||||
  NULL, /* prepare */
 | 
			
		||||
  NULL, /* check */
 | 
			
		||||
  native_dispatch_timeout,
 | 
			
		||||
  NULL, /* finalize */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
free_watch (gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitorWatchNative *watch_native = data;
 | 
			
		||||
  MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_native;
 | 
			
		||||
  MetaIdleMonitor *monitor = watch->monitor;
 | 
			
		||||
 | 
			
		||||
  g_object_ref (monitor);
 | 
			
		||||
 | 
			
		||||
  if (watch->idle_source_id)
 | 
			
		||||
    {
 | 
			
		||||
      g_source_remove (watch->idle_source_id);
 | 
			
		||||
      watch->idle_source_id = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (watch->notify != NULL)
 | 
			
		||||
    watch->notify (watch->user_data);
 | 
			
		||||
 | 
			
		||||
  if (watch_native->timeout_source != NULL)
 | 
			
		||||
    g_source_destroy (watch_native->timeout_source);
 | 
			
		||||
 | 
			
		||||
  g_object_unref (monitor);
 | 
			
		||||
  g_slice_free (MetaIdleMonitorWatchNative, watch_native);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaIdleMonitorWatch *
 | 
			
		||||
meta_idle_monitor_native_make_watch (MetaIdleMonitor           *monitor,
 | 
			
		||||
                                     guint64                    timeout_msec,
 | 
			
		||||
                                     MetaIdleMonitorWatchFunc   callback,
 | 
			
		||||
                                     gpointer                   user_data,
 | 
			
		||||
                                     GDestroyNotify             notify)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitorWatchNative *watch_native;
 | 
			
		||||
  MetaIdleMonitorWatch *watch;
 | 
			
		||||
  MetaIdleMonitorNative *monitor_native = META_IDLE_MONITOR_NATIVE (monitor);
 | 
			
		||||
 | 
			
		||||
  watch_native = g_slice_new0 (MetaIdleMonitorWatchNative);
 | 
			
		||||
  watch = (MetaIdleMonitorWatch *) watch_native;
 | 
			
		||||
 | 
			
		||||
  watch->monitor = monitor;
 | 
			
		||||
  watch->id = get_next_watch_serial ();
 | 
			
		||||
  watch->callback = callback;
 | 
			
		||||
  watch->user_data = user_data;
 | 
			
		||||
  watch->notify = notify;
 | 
			
		||||
  watch->timeout_msec = timeout_msec;
 | 
			
		||||
 | 
			
		||||
  if (timeout_msec != 0)
 | 
			
		||||
    {
 | 
			
		||||
      GSource *source = g_source_new (&native_source_funcs, sizeof (GSource));
 | 
			
		||||
 | 
			
		||||
      g_source_set_callback (source, NULL, watch, NULL);
 | 
			
		||||
      g_source_set_ready_time (source, monitor_native->last_event_time + timeout_msec * 1000);
 | 
			
		||||
      g_source_attach (source, NULL);
 | 
			
		||||
      g_source_unref (source);
 | 
			
		||||
 | 
			
		||||
      watch_native->timeout_source = source;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return watch;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_idle_monitor_native_class_init (MetaIdleMonitorNativeClass *klass)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitorClass *idle_monitor_class = META_IDLE_MONITOR_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  idle_monitor_class->get_idletime = meta_idle_monitor_native_get_idletime;
 | 
			
		||||
  idle_monitor_class->make_watch = meta_idle_monitor_native_make_watch;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_idle_monitor_native_init (MetaIdleMonitorNative *monitor_native)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitor *monitor = META_IDLE_MONITOR (monitor_native);
 | 
			
		||||
 | 
			
		||||
  monitor->watches = g_hash_table_new_full (NULL, NULL, NULL, free_watch);
 | 
			
		||||
  monitor_native->last_event_time = g_get_monotonic_time ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_idle_monitor_native_reset_idletime (MetaIdleMonitor *monitor)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitorNative *monitor_native = META_IDLE_MONITOR_NATIVE (monitor);
 | 
			
		||||
  GList *node, *watch_ids;
 | 
			
		||||
 | 
			
		||||
  monitor_native->last_event_time = g_get_monotonic_time ();
 | 
			
		||||
 | 
			
		||||
  watch_ids = g_hash_table_get_keys (monitor->watches);
 | 
			
		||||
 | 
			
		||||
  for (node = watch_ids; node != NULL; node = node->next)
 | 
			
		||||
    {
 | 
			
		||||
      guint watch_id = GPOINTER_TO_UINT (node->data);
 | 
			
		||||
      MetaIdleMonitorWatchNative *watch;
 | 
			
		||||
 | 
			
		||||
      watch = g_hash_table_lookup (monitor->watches, GUINT_TO_POINTER (watch_id));
 | 
			
		||||
      if (!watch)
 | 
			
		||||
        continue;
 | 
			
		||||
 | 
			
		||||
      if (watch->base.timeout_msec == 0)
 | 
			
		||||
        {
 | 
			
		||||
          _meta_idle_monitor_watch_fire ((MetaIdleMonitorWatch *) watch);
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          g_source_set_ready_time (watch->timeout_source,
 | 
			
		||||
                                   monitor_native->last_event_time +
 | 
			
		||||
                                   watch->base.timeout_msec * 1000);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_list_free (watch_ids);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,43 +0,0 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 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, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 * Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
 | 
			
		||||
 *         from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef META_IDLE_MONITOR_NATIVE_H
 | 
			
		||||
#define META_IDLE_MONITOR_NATIVE_H
 | 
			
		||||
 | 
			
		||||
#include <glib-object.h>
 | 
			
		||||
#include <meta/meta-idle-monitor.h>
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_IDLE_MONITOR_NATIVE            (meta_idle_monitor_native_get_type ())
 | 
			
		||||
#define META_IDLE_MONITOR_NATIVE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_IDLE_MONITOR_NATIVE, MetaIdleMonitorNative))
 | 
			
		||||
#define META_IDLE_MONITOR_NATIVE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_IDLE_MONITOR_NATIVE, MetaIdleMonitorNativeClass))
 | 
			
		||||
#define META_IS_IDLE_MONITOR_NATIVE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_IDLE_MONITOR_NATIVE))
 | 
			
		||||
#define META_IS_IDLE_MONITOR_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_IDLE_MONITOR_NATIVE))
 | 
			
		||||
#define META_IDLE_MONITOR_NATIVE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_IDLE_MONITOR_NATIVE, MetaIdleMonitorNativeClass))
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaIdleMonitorNative        MetaIdleMonitorNative;
 | 
			
		||||
typedef struct _MetaIdleMonitorNativeClass   MetaIdleMonitorNativeClass;
 | 
			
		||||
 | 
			
		||||
GType meta_idle_monitor_native_get_type (void);
 | 
			
		||||
 | 
			
		||||
void meta_idle_monitor_native_reset_idletime (MetaIdleMonitor *monitor);
 | 
			
		||||
 | 
			
		||||
#endif /* META_IDLE_MONITOR_NATIVE_H */
 | 
			
		||||
@@ -44,7 +44,6 @@
 | 
			
		||||
#include "backends/meta-backend-private.h"
 | 
			
		||||
#include "backends/native/meta-backend-native.h"
 | 
			
		||||
#include "meta-cursor-renderer-native.h"
 | 
			
		||||
#include "meta-idle-monitor-native.h"
 | 
			
		||||
#include "meta-renderer-native.h"
 | 
			
		||||
 | 
			
		||||
struct _MetaLauncher
 | 
			
		||||
 
 | 
			
		||||
@@ -188,7 +188,7 @@ apply_crtc_assignments (MetaMonitorManager *manager,
 | 
			
		||||
              MetaOutput *output = g_ptr_array_index (crtc_info->outputs, j);
 | 
			
		||||
 | 
			
		||||
              output->is_dirty = TRUE;
 | 
			
		||||
              output->crtc = crtc;
 | 
			
		||||
              meta_output_assign_crtc (output, crtc);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -249,7 +249,7 @@ apply_crtc_assignments (MetaMonitorManager *manager,
 | 
			
		||||
              continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          output->crtc = NULL;
 | 
			
		||||
          meta_output_unassign_crtc (output);
 | 
			
		||||
          output->is_primary = FALSE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -674,16 +674,19 @@ meta_monitor_manager_kms_initable_init (GInitable    *initable,
 | 
			
		||||
  gpu_paths = get_gpu_paths (manager_kms, GPU_TYPE_SECONDARY, primary_gpu_path);
 | 
			
		||||
  for (l = gpu_paths; l; l = l->next)
 | 
			
		||||
    {
 | 
			
		||||
      GError *secondary_error = NULL;
 | 
			
		||||
      g_autoptr (GError) secondary_error = NULL;
 | 
			
		||||
      char *gpu_path = l->data;
 | 
			
		||||
      MetaGpuKms *gpu_kms;
 | 
			
		||||
 | 
			
		||||
      gpu_kms = meta_gpu_kms_new (manager_kms, gpu_path, &secondary_error);
 | 
			
		||||
      if (!gpu_kms)
 | 
			
		||||
        {
 | 
			
		||||
          g_warning ("Failed to open secondary gpu '%s': %s",
 | 
			
		||||
                     gpu_path, secondary_error->message);
 | 
			
		||||
          g_error_free (secondary_error);
 | 
			
		||||
          if (g_error_matches (secondary_error, META_GPU_KMS_ERROR, META_GPU_KMS_ERROR_NO_CONNECTORS))
 | 
			
		||||
            g_message ("Ignoring GPU %s due to the lack of connectors", gpu_path);
 | 
			
		||||
          else
 | 
			
		||||
            g_warning ("Failed to open secondary gpu '%s': %s", gpu_path, secondary_error->message);
 | 
			
		||||
 | 
			
		||||
          continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      meta_monitor_manager_add_gpu (META_MONITOR_MANAGER (manager_kms),
 | 
			
		||||
 
 | 
			
		||||
@@ -64,11 +64,13 @@ typedef struct _MetaOutputKms
 | 
			
		||||
void
 | 
			
		||||
meta_output_kms_set_underscan (MetaOutput *output)
 | 
			
		||||
{
 | 
			
		||||
  if (!output->crtc)
 | 
			
		||||
  MetaCrtc *crtc;
 | 
			
		||||
 | 
			
		||||
  crtc = meta_output_get_assigned_crtc (output);
 | 
			
		||||
  if (!crtc)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  meta_crtc_kms_set_underscan (output->crtc,
 | 
			
		||||
                               output->is_underscanning);
 | 
			
		||||
  meta_crtc_kms_set_underscan (crtc, output->is_underscanning);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -600,14 +602,14 @@ meta_create_kms_output (MetaGpuKms        *gpu_kms,
 | 
			
		||||
 | 
			
		||||
          if (crtc->crtc_id == output_kms->current_encoder->crtc_id)
 | 
			
		||||
            {
 | 
			
		||||
              output->crtc = crtc;
 | 
			
		||||
              meta_output_assign_crtc (output, crtc);
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      output->crtc = NULL;
 | 
			
		||||
      meta_output_unassign_crtc (output);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (old_output)
 | 
			
		||||
 
 | 
			
		||||
@@ -193,6 +193,8 @@ struct _MetaRendererNative
 | 
			
		||||
  MetaMonitorManagerKms *monitor_manager_kms;
 | 
			
		||||
  MetaGles3 *gles3;
 | 
			
		||||
 | 
			
		||||
  gboolean use_modifiers;
 | 
			
		||||
 | 
			
		||||
  GHashTable *gpu_datas;
 | 
			
		||||
 | 
			
		||||
  CoglClosure *swap_notify_idle;
 | 
			
		||||
@@ -1586,6 +1588,7 @@ gbm_get_next_fb_id (MetaGpuKms         *gpu_kms,
 | 
			
		||||
                    struct gbm_bo     **out_next_bo,
 | 
			
		||||
                    uint32_t           *out_next_fb_id)
 | 
			
		||||
{
 | 
			
		||||
  MetaRendererNative *renderer_native = meta_renderer_native_from_gpu (gpu_kms);
 | 
			
		||||
  struct gbm_bo *next_bo;
 | 
			
		||||
  uint32_t next_fb_id;
 | 
			
		||||
  int kms_fd;
 | 
			
		||||
@@ -1598,6 +1601,12 @@ gbm_get_next_fb_id (MetaGpuKms         *gpu_kms,
 | 
			
		||||
  /* Now we need to set the CRTC to whatever is the front buffer */
 | 
			
		||||
  next_bo = gbm_surface_lock_front_buffer (gbm_surface);
 | 
			
		||||
 | 
			
		||||
  if (!next_bo)
 | 
			
		||||
    {
 | 
			
		||||
      g_error ("Impossible to lock surface front buffer: %m");
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < gbm_bo_get_plane_count (next_bo); i++)
 | 
			
		||||
    {
 | 
			
		||||
      strides[i] = gbm_bo_get_stride_for_plane (next_bo, i);
 | 
			
		||||
@@ -1608,7 +1617,8 @@ gbm_get_next_fb_id (MetaGpuKms         *gpu_kms,
 | 
			
		||||
 | 
			
		||||
  kms_fd = meta_gpu_kms_get_fd (gpu_kms);
 | 
			
		||||
 | 
			
		||||
  if (modifiers[0] != DRM_FORMAT_MOD_INVALID)
 | 
			
		||||
  if (renderer_native->use_modifiers &&
 | 
			
		||||
      modifiers[0] != DRM_FORMAT_MOD_INVALID)
 | 
			
		||||
    {
 | 
			
		||||
      if (drmModeAddFB2WithModifiers (kms_fd,
 | 
			
		||||
                                      gbm_bo_get_width (next_bo),
 | 
			
		||||
@@ -1854,18 +1864,18 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
 | 
			
		||||
  frame_info = g_queue_peek_tail (&onscreen->pending_frame_infos);
 | 
			
		||||
  frame_info->global_frame_counter = renderer_native->frame_counter;
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * Wait for the flip callback before continuing, as we might have started the
 | 
			
		||||
   * animation earlier due to the animation being driven by some other monitor.
 | 
			
		||||
   */
 | 
			
		||||
  wait_for_pending_flips (onscreen);
 | 
			
		||||
 | 
			
		||||
  update_secondary_gpu_state_pre_swap_buffers (onscreen);
 | 
			
		||||
 | 
			
		||||
  parent_vtable->onscreen_swap_buffers_with_damage (onscreen,
 | 
			
		||||
                                                    rectangles,
 | 
			
		||||
                                                    n_rectangles);
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * Wait for the flip callback before continuing, as we might have started the
 | 
			
		||||
   * animation earlier due to the animation being driven by some other monitor.
 | 
			
		||||
   */
 | 
			
		||||
  wait_for_pending_flips (onscreen);
 | 
			
		||||
 | 
			
		||||
  renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native,
 | 
			
		||||
                                                         render_gpu);
 | 
			
		||||
  switch (renderer_gpu_data->mode)
 | 
			
		||||
@@ -1907,12 +1917,7 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
 | 
			
		||||
   * context.
 | 
			
		||||
   */
 | 
			
		||||
  if (egl_context_changed)
 | 
			
		||||
    {
 | 
			
		||||
      _cogl_winsys_egl_make_current (cogl_display,
 | 
			
		||||
                                     EGL_NO_SURFACE,
 | 
			
		||||
                                     EGL_NO_SURFACE,
 | 
			
		||||
                                     EGL_NO_CONTEXT);
 | 
			
		||||
    }
 | 
			
		||||
    _cogl_winsys_egl_ensure_current (cogl_display);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
@@ -1996,7 +2001,7 @@ meta_renderer_native_create_surface_gbm (CoglOnscreen        *onscreen,
 | 
			
		||||
  CoglRenderer *cogl_renderer = cogl_display->renderer;
 | 
			
		||||
  CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys;
 | 
			
		||||
  MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform;
 | 
			
		||||
  struct gbm_surface *new_gbm_surface;
 | 
			
		||||
  struct gbm_surface *new_gbm_surface = NULL;
 | 
			
		||||
  EGLNativeWindowType egl_native_window;
 | 
			
		||||
  EGLSurface new_egl_surface;
 | 
			
		||||
  uint32_t format = GBM_FORMAT_XRGB8888;
 | 
			
		||||
@@ -2006,7 +2011,10 @@ meta_renderer_native_create_surface_gbm (CoglOnscreen        *onscreen,
 | 
			
		||||
    meta_renderer_native_get_gpu_data (renderer_native,
 | 
			
		||||
                                       onscreen_native->render_gpu);
 | 
			
		||||
 | 
			
		||||
  modifiers = get_supported_modifiers (onscreen, format);
 | 
			
		||||
  if (renderer_native->use_modifiers)
 | 
			
		||||
    modifiers = get_supported_modifiers (onscreen, format);
 | 
			
		||||
  else
 | 
			
		||||
    modifiers = NULL;
 | 
			
		||||
 | 
			
		||||
  if (modifiers)
 | 
			
		||||
    {
 | 
			
		||||
@@ -2017,7 +2025,8 @@ meta_renderer_native_create_surface_gbm (CoglOnscreen        *onscreen,
 | 
			
		||||
                                           modifiers->len);
 | 
			
		||||
      g_array_free (modifiers, TRUE);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
 | 
			
		||||
  if (!new_gbm_surface)
 | 
			
		||||
    {
 | 
			
		||||
      uint32_t flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
 | 
			
		||||
 | 
			
		||||
@@ -2080,6 +2089,7 @@ meta_renderer_native_create_surface_egl_device (CoglOnscreen       *onscreen,
 | 
			
		||||
  EGLDisplay egl_display = renderer_gpu_data->egl_display;
 | 
			
		||||
  MetaMonitor *monitor;
 | 
			
		||||
  MetaOutput *output;
 | 
			
		||||
  MetaCrtc *crtc;
 | 
			
		||||
  EGLConfig egl_config;
 | 
			
		||||
  EGLStreamKHR egl_stream;
 | 
			
		||||
  EGLSurface egl_surface;
 | 
			
		||||
@@ -2103,6 +2113,7 @@ meta_renderer_native_create_surface_egl_device (CoglOnscreen       *onscreen,
 | 
			
		||||
 | 
			
		||||
  monitor = meta_logical_monitor_get_monitors (logical_monitor)->data;
 | 
			
		||||
  output = meta_monitor_get_main_output (monitor);
 | 
			
		||||
  crtc = meta_output_get_assigned_crtc (output);
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * An "logical_monitor" may have multiple outputs/crtcs in case its tiled,
 | 
			
		||||
@@ -2110,7 +2121,7 @@ meta_renderer_native_create_surface_egl_device (CoglOnscreen       *onscreen,
 | 
			
		||||
   * lets pass the first one.
 | 
			
		||||
   */
 | 
			
		||||
  output_attribs[0] = EGL_DRM_CRTC_EXT;
 | 
			
		||||
  output_attribs[1] = output->crtc->crtc_id;
 | 
			
		||||
  output_attribs[1] = crtc->crtc_id;
 | 
			
		||||
  output_attribs[2] = EGL_NONE;
 | 
			
		||||
 | 
			
		||||
  if (!meta_egl_get_output_layers (egl, egl_display,
 | 
			
		||||
@@ -2708,12 +2719,10 @@ calculate_view_transform (MetaMonitorManager *monitor_manager,
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitor *main_monitor;
 | 
			
		||||
  MetaOutput *main_output;
 | 
			
		||||
  MetaMonitorTransform crtc_transform;
 | 
			
		||||
  MetaCrtc *crtc;
 | 
			
		||||
  main_monitor = meta_logical_monitor_get_monitors (logical_monitor)->data;
 | 
			
		||||
  main_output = meta_monitor_get_main_output (main_monitor);
 | 
			
		||||
  crtc_transform =
 | 
			
		||||
    meta_monitor_logical_to_crtc_transform (main_monitor,
 | 
			
		||||
                                            logical_monitor->transform);
 | 
			
		||||
  crtc = meta_output_get_assigned_crtc (main_output);
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * Pick any monitor and output and check; all CRTCs of a logical monitor will
 | 
			
		||||
@@ -2721,11 +2730,11 @@ calculate_view_transform (MetaMonitorManager *monitor_manager,
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  if (meta_monitor_manager_is_transform_handled (monitor_manager,
 | 
			
		||||
                                                 main_output->crtc,
 | 
			
		||||
                                                 crtc_transform))
 | 
			
		||||
                                                 crtc,
 | 
			
		||||
                                                 crtc->transform))
 | 
			
		||||
    return META_MONITOR_TRANSFORM_NORMAL;
 | 
			
		||||
  else
 | 
			
		||||
    return crtc_transform;
 | 
			
		||||
    return crtc->transform;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaRendererView *
 | 
			
		||||
@@ -3389,6 +3398,22 @@ meta_renderer_native_finalize (GObject *object)
 | 
			
		||||
  G_OBJECT_CLASS (meta_renderer_native_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_renderer_native_constructed (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  MetaRendererNative *renderer_native = META_RENDERER_NATIVE (object);
 | 
			
		||||
  MetaMonitorManager *monitor_manager =
 | 
			
		||||
    META_MONITOR_MANAGER (renderer_native->monitor_manager_kms);
 | 
			
		||||
  MetaBackend *backend = meta_monitor_manager_get_backend (monitor_manager);
 | 
			
		||||
  MetaSettings *settings = meta_backend_get_settings (backend);
 | 
			
		||||
 | 
			
		||||
  if (meta_settings_is_experimental_feature_enabled (
 | 
			
		||||
        settings, META_EXPERIMENTAL_FEATURE_KMS_MODIFIERS))
 | 
			
		||||
    renderer_native->use_modifiers = TRUE;
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_renderer_native_parent_class)->constructed (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_renderer_native_init (MetaRendererNative *renderer_native)
 | 
			
		||||
{
 | 
			
		||||
@@ -3407,6 +3432,7 @@ meta_renderer_native_class_init (MetaRendererNativeClass *klass)
 | 
			
		||||
  object_class->get_property = meta_renderer_native_get_property;
 | 
			
		||||
  object_class->set_property = meta_renderer_native_set_property;
 | 
			
		||||
  object_class->finalize = meta_renderer_native_finalize;
 | 
			
		||||
  object_class->constructed = meta_renderer_native_constructed;
 | 
			
		||||
 | 
			
		||||
  renderer_class->create_cogl_renderer = meta_renderer_native_create_cogl_renderer;
 | 
			
		||||
  renderer_class->create_view = meta_renderer_native_create_view;
 | 
			
		||||
 
 | 
			
		||||
@@ -37,8 +37,7 @@
 | 
			
		||||
#include <X11/Xlib-xcb.h>
 | 
			
		||||
#include <xkbcommon/xkbcommon-x11.h>
 | 
			
		||||
 | 
			
		||||
#include "meta-idle-monitor-xsync.h"
 | 
			
		||||
#include "backends/meta-stage.h"
 | 
			
		||||
#include "backends/meta-stage-private.h"
 | 
			
		||||
#include "backends/x11/meta-clutter-backend-x11.h"
 | 
			
		||||
#include "backends/x11/meta-renderer-x11.h"
 | 
			
		||||
#include "meta/meta-cursor-tracker.h"
 | 
			
		||||
@@ -47,6 +46,7 @@
 | 
			
		||||
#include "display-private.h"
 | 
			
		||||
#include "compositor/compositor-private.h"
 | 
			
		||||
#include "backends/meta-dnd-private.h"
 | 
			
		||||
#include "backends/meta-idle-monitor-private.h"
 | 
			
		||||
 | 
			
		||||
struct _MetaBackendX11Private
 | 
			
		||||
{
 | 
			
		||||
@@ -57,6 +57,8 @@ struct _MetaBackendX11Private
 | 
			
		||||
 | 
			
		||||
  int xsync_event_base;
 | 
			
		||||
  int xsync_error_base;
 | 
			
		||||
  XSyncAlarm user_active_alarm;
 | 
			
		||||
  XSyncCounter counter;
 | 
			
		||||
 | 
			
		||||
  int xinput_opcode;
 | 
			
		||||
  int xinput_event_base;
 | 
			
		||||
@@ -83,13 +85,77 @@ G_DEFINE_TYPE_WITH_CODE (MetaBackendX11, meta_backend_x11, META_TYPE_BACKEND,
 | 
			
		||||
                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
 | 
			
		||||
                                                initable_iface_init));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
handle_alarm_notify (MetaBackend *backend,
 | 
			
		||||
                     XEvent      *event)
 | 
			
		||||
uint64_to_xsync_value (uint64_t    value,
 | 
			
		||||
                       XSyncValue *xsync_value)
 | 
			
		||||
{
 | 
			
		||||
  meta_backend_foreach_device_monitor (backend,
 | 
			
		||||
                                       (GFunc) meta_idle_monitor_xsync_handle_xevent,
 | 
			
		||||
                                       event);
 | 
			
		||||
  XSyncIntsToValue (xsync_value, value & 0xffffffff, value >> 32);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static XSyncAlarm
 | 
			
		||||
xsync_user_active_alarm_set (MetaBackendX11Private *priv)
 | 
			
		||||
{
 | 
			
		||||
  XSyncAlarmAttributes attr;
 | 
			
		||||
  XSyncValue delta;
 | 
			
		||||
  unsigned long flags;
 | 
			
		||||
 | 
			
		||||
  flags = (XSyncCACounter | XSyncCAValueType | XSyncCATestType |
 | 
			
		||||
           XSyncCAValue | XSyncCADelta | XSyncCAEvents);
 | 
			
		||||
 | 
			
		||||
  XSyncIntToValue (&delta, 0);
 | 
			
		||||
  attr.trigger.counter = priv->counter;
 | 
			
		||||
  attr.trigger.value_type = XSyncAbsolute;
 | 
			
		||||
  attr.delta = delta;
 | 
			
		||||
  attr.events = TRUE;
 | 
			
		||||
 | 
			
		||||
  uint64_to_xsync_value (1, &attr.trigger.wait_value);
 | 
			
		||||
 | 
			
		||||
  attr.trigger.test_type = XSyncNegativeTransition;
 | 
			
		||||
  return XSyncCreateAlarm (priv->xdisplay, flags, &attr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static XSyncCounter
 | 
			
		||||
find_idletime_counter (MetaBackendX11Private *priv)
 | 
			
		||||
{
 | 
			
		||||
  int i;
 | 
			
		||||
  int n_counters;
 | 
			
		||||
  XSyncSystemCounter *counters;
 | 
			
		||||
  XSyncCounter counter = None;
 | 
			
		||||
 | 
			
		||||
  counters = XSyncListSystemCounters (priv->xdisplay, &n_counters);
 | 
			
		||||
  for (i = 0; i < n_counters; i++)
 | 
			
		||||
    {
 | 
			
		||||
      if (g_strcmp0 (counters[i].name, "IDLETIME") == 0)
 | 
			
		||||
        {
 | 
			
		||||
          counter = counters[i].counter;
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  XSyncFreeSystemCounterList (counters);
 | 
			
		||||
 | 
			
		||||
  return counter;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
handle_alarm_notify (MetaBackend           *backend,
 | 
			
		||||
                     XSyncAlarmNotifyEvent *alarm_event)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
 | 
			
		||||
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
 | 
			
		||||
  MetaIdleMonitor *idle_monitor;
 | 
			
		||||
  XSyncAlarmAttributes attr;
 | 
			
		||||
 | 
			
		||||
  if (alarm_event->state != XSyncAlarmActive ||
 | 
			
		||||
      alarm_event->alarm != priv->user_active_alarm)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  attr.events = TRUE;
 | 
			
		||||
  XSyncChangeAlarm (priv->xdisplay, priv->user_active_alarm,
 | 
			
		||||
                    XSyncCAEvents, &attr);
 | 
			
		||||
 | 
			
		||||
  idle_monitor = meta_backend_get_idle_monitor (backend, 0);
 | 
			
		||||
  meta_idle_monitor_reset_idletime (idle_monitor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@@ -275,7 +341,7 @@ handle_host_xevent (MetaBackend *backend,
 | 
			
		||||
                    bypass_clutter);
 | 
			
		||||
 | 
			
		||||
  if (event->type == (priv->xsync_event_base + XSyncAlarmNotify))
 | 
			
		||||
    handle_alarm_notify (backend, event);
 | 
			
		||||
    handle_alarm_notify (backend, (XSyncAlarmNotifyEvent *) event);
 | 
			
		||||
 | 
			
		||||
  if (event->type == priv->xkb_event_base)
 | 
			
		||||
    {
 | 
			
		||||
@@ -423,6 +489,12 @@ meta_backend_x11_post_init (MetaBackend *backend)
 | 
			
		||||
      !XSyncInitialize (priv->xdisplay, &major, &minor))
 | 
			
		||||
    meta_fatal ("Could not initialize XSync");
 | 
			
		||||
 | 
			
		||||
  priv->counter = find_idletime_counter (priv);
 | 
			
		||||
  if (priv->counter == None)
 | 
			
		||||
    meta_fatal ("Could not initialize XSync counter");
 | 
			
		||||
 | 
			
		||||
  priv->user_active_alarm = xsync_user_active_alarm_set (priv);
 | 
			
		||||
 | 
			
		||||
  if (XQueryExtension (priv->xdisplay,
 | 
			
		||||
                       "XInputExtension",
 | 
			
		||||
                       &priv->xinput_opcode,
 | 
			
		||||
@@ -464,15 +536,6 @@ meta_backend_x11_create_clutter_backend (MetaBackend *backend)
 | 
			
		||||
  return g_object_new (META_TYPE_CLUTTER_BACKEND_X11, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaIdleMonitor *
 | 
			
		||||
meta_backend_x11_create_idle_monitor (MetaBackend *backend,
 | 
			
		||||
                                      int          device_id)
 | 
			
		||||
{
 | 
			
		||||
  return g_object_new (META_TYPE_IDLE_MONITOR_XSYNC,
 | 
			
		||||
                       "device-id", device_id,
 | 
			
		||||
                       NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
meta_backend_x11_grab_device (MetaBackend *backend,
 | 
			
		||||
                              int          device_id,
 | 
			
		||||
@@ -679,14 +742,30 @@ initable_iface_init (GInitableIface *initable_iface)
 | 
			
		||||
  initable_iface->init = meta_backend_x11_initable_init;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_backend_x11_finalize (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackendX11 *x11 = META_BACKEND_X11 (object);
 | 
			
		||||
  MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
 | 
			
		||||
 | 
			
		||||
  if (priv->user_active_alarm != None)
 | 
			
		||||
    {
 | 
			
		||||
      XSyncDestroyAlarm (priv->xdisplay, priv->user_active_alarm);
 | 
			
		||||
      priv->user_active_alarm = None;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_backend_x11_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_backend_x11_class_init (MetaBackendX11Class *klass)
 | 
			
		||||
{
 | 
			
		||||
  MetaBackendClass *backend_class = META_BACKEND_CLASS (klass);
 | 
			
		||||
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  object_class->finalize = meta_backend_x11_finalize;
 | 
			
		||||
  backend_class->create_clutter_backend = meta_backend_x11_create_clutter_backend;
 | 
			
		||||
  backend_class->post_init = meta_backend_x11_post_init;
 | 
			
		||||
  backend_class->create_idle_monitor = meta_backend_x11_create_idle_monitor;
 | 
			
		||||
  backend_class->grab_device = meta_backend_x11_grab_device;
 | 
			
		||||
  backend_class->ungrab_device = meta_backend_x11_ungrab_device;
 | 
			
		||||
  backend_class->warp_pointer = meta_backend_x11_warp_pointer;
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,7 @@
 | 
			
		||||
#include <X11/extensions/Xfixes.h>
 | 
			
		||||
 | 
			
		||||
#include "meta-backend-x11.h"
 | 
			
		||||
#include "meta-stage.h"
 | 
			
		||||
#include "meta-stage-private.h"
 | 
			
		||||
 | 
			
		||||
struct _MetaCursorRendererX11Private
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -1,373 +0,0 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 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, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 * Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
 | 
			
		||||
 *         from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include "meta-idle-monitor-xsync.h"
 | 
			
		||||
#include "meta-idle-monitor-private.h"
 | 
			
		||||
 | 
			
		||||
#include "meta-backend-x11.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
struct _MetaIdleMonitorXSync
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitor parent;
 | 
			
		||||
 | 
			
		||||
  GHashTable  *alarms;
 | 
			
		||||
  Display     *display;
 | 
			
		||||
  XSyncCounter counter;
 | 
			
		||||
  XSyncAlarm   user_active_alarm;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaIdleMonitorXSyncClass
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitorClass parent_class;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  MetaIdleMonitorWatch base;
 | 
			
		||||
 | 
			
		||||
  XSyncAlarm xalarm;
 | 
			
		||||
} MetaIdleMonitorWatchXSync;
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (MetaIdleMonitorXSync, meta_idle_monitor_xsync, META_TYPE_IDLE_MONITOR)
 | 
			
		||||
 | 
			
		||||
static gint64
 | 
			
		||||
_xsyncvalue_to_int64 (XSyncValue value)
 | 
			
		||||
{
 | 
			
		||||
  return ((guint64) XSyncValueHigh32 (value)) << 32
 | 
			
		||||
    | (guint64) XSyncValueLow32 (value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define GUINT64_TO_XSYNCVALUE(value, ret) XSyncIntsToValue (ret, (value) & 0xFFFFFFFF, ((guint64)(value)) >> 32)
 | 
			
		||||
 | 
			
		||||
static XSyncAlarm
 | 
			
		||||
_xsync_alarm_set (MetaIdleMonitorXSync	*monitor_xsync,
 | 
			
		||||
		  XSyncTestType          test_type,
 | 
			
		||||
		  guint64                interval,
 | 
			
		||||
		  gboolean               want_events)
 | 
			
		||||
{
 | 
			
		||||
  XSyncAlarmAttributes attr;
 | 
			
		||||
  XSyncValue	     delta;
 | 
			
		||||
  guint		     flags;
 | 
			
		||||
 | 
			
		||||
  flags = XSyncCACounter | XSyncCAValueType | XSyncCATestType |
 | 
			
		||||
    XSyncCAValue | XSyncCADelta | XSyncCAEvents;
 | 
			
		||||
 | 
			
		||||
  XSyncIntToValue (&delta, 0);
 | 
			
		||||
  attr.trigger.counter = monitor_xsync->counter;
 | 
			
		||||
  attr.trigger.value_type = XSyncAbsolute;
 | 
			
		||||
  attr.delta = delta;
 | 
			
		||||
  attr.events = want_events;
 | 
			
		||||
 | 
			
		||||
  GUINT64_TO_XSYNCVALUE (interval, &attr.trigger.wait_value);
 | 
			
		||||
  attr.trigger.test_type = test_type;
 | 
			
		||||
  return XSyncCreateAlarm (monitor_xsync->display, flags, &attr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
ensure_alarm_rescheduled (Display    *dpy,
 | 
			
		||||
			  XSyncAlarm  alarm)
 | 
			
		||||
{
 | 
			
		||||
  XSyncAlarmAttributes attr;
 | 
			
		||||
 | 
			
		||||
  /* Some versions of Xorg have an issue where alarms aren't
 | 
			
		||||
   * always rescheduled. Calling XSyncChangeAlarm, even
 | 
			
		||||
   * without any attributes, will reschedule the alarm. */
 | 
			
		||||
  XSyncChangeAlarm (dpy, alarm, 0, &attr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
set_alarm_enabled (Display    *dpy,
 | 
			
		||||
		   XSyncAlarm  alarm,
 | 
			
		||||
		   gboolean    enabled)
 | 
			
		||||
{
 | 
			
		||||
  XSyncAlarmAttributes attr;
 | 
			
		||||
  attr.events = enabled;
 | 
			
		||||
  XSyncChangeAlarm (dpy, alarm, XSyncCAEvents, &attr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char *
 | 
			
		||||
counter_name_for_device (int device_id)
 | 
			
		||||
{
 | 
			
		||||
  if (device_id > 0)
 | 
			
		||||
    return g_strdup_printf ("DEVICEIDLETIME %d", device_id);
 | 
			
		||||
 | 
			
		||||
  return g_strdup ("IDLETIME");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static XSyncCounter
 | 
			
		||||
find_idletime_counter (MetaIdleMonitorXSync *monitor_xsync)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitor *monitor = META_IDLE_MONITOR (monitor_xsync);
 | 
			
		||||
  int		      i;
 | 
			
		||||
  int		      ncounters;
 | 
			
		||||
  XSyncSystemCounter *counters;
 | 
			
		||||
  XSyncCounter        counter = None;
 | 
			
		||||
  char               *counter_name;
 | 
			
		||||
 | 
			
		||||
  counter_name = counter_name_for_device (monitor->device_id);
 | 
			
		||||
  counters = XSyncListSystemCounters (monitor_xsync->display, &ncounters);
 | 
			
		||||
  for (i = 0; i < ncounters; i++)
 | 
			
		||||
    {
 | 
			
		||||
      if (counters[i].name != NULL && strcmp (counters[i].name, counter_name) == 0)
 | 
			
		||||
        {
 | 
			
		||||
          counter = counters[i].counter;
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  XSyncFreeSystemCounterList (counters);
 | 
			
		||||
  g_free (counter_name);
 | 
			
		||||
 | 
			
		||||
  return counter;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
init_xsync (MetaIdleMonitorXSync *monitor_xsync)
 | 
			
		||||
{
 | 
			
		||||
  monitor_xsync->counter = find_idletime_counter (monitor_xsync);
 | 
			
		||||
  /* IDLETIME counter not found? */
 | 
			
		||||
  if (monitor_xsync->counter == None)
 | 
			
		||||
    {
 | 
			
		||||
      g_warning ("IDLETIME counter not found\n");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  monitor_xsync->user_active_alarm = _xsync_alarm_set (monitor_xsync, XSyncNegativeTransition, 1, FALSE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_idle_monitor_xsync_dispose (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (object);
 | 
			
		||||
 | 
			
		||||
  if (monitor_xsync->user_active_alarm != None)
 | 
			
		||||
    {
 | 
			
		||||
      XSyncDestroyAlarm (monitor_xsync->display, monitor_xsync->user_active_alarm);
 | 
			
		||||
      monitor_xsync->user_active_alarm = None;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_clear_pointer (&monitor_xsync->alarms, g_hash_table_destroy);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_idle_monitor_xsync_parent_class)->dispose (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_idle_monitor_xsync_constructed (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (object);
 | 
			
		||||
  MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
 | 
			
		||||
 | 
			
		||||
  monitor_xsync->display = meta_backend_x11_get_xdisplay (backend);
 | 
			
		||||
  init_xsync (monitor_xsync);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (meta_idle_monitor_xsync_parent_class)->constructed (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gint64
 | 
			
		||||
meta_idle_monitor_xsync_get_idletime (MetaIdleMonitor *monitor)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (monitor);
 | 
			
		||||
  XSyncValue value;
 | 
			
		||||
 | 
			
		||||
  if (!XSyncQueryCounter (monitor_xsync->display, monitor_xsync->counter, &value))
 | 
			
		||||
    return -1;
 | 
			
		||||
 | 
			
		||||
  return _xsyncvalue_to_int64 (value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
fire_watch_idle (gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitorWatch *watch = data;
 | 
			
		||||
 | 
			
		||||
  watch->idle_source_id = 0;
 | 
			
		||||
  _meta_idle_monitor_watch_fire (watch);
 | 
			
		||||
 | 
			
		||||
  return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static guint32
 | 
			
		||||
get_next_watch_serial (void)
 | 
			
		||||
{
 | 
			
		||||
  static guint32 serial = 0;
 | 
			
		||||
  g_atomic_int_inc (&serial);
 | 
			
		||||
  return serial;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
free_watch (gpointer data)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitorWatchXSync *watch_xsync = data;
 | 
			
		||||
  MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_xsync;
 | 
			
		||||
  MetaIdleMonitor *monitor = watch->monitor;
 | 
			
		||||
  MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (monitor);
 | 
			
		||||
 | 
			
		||||
  g_object_ref (monitor);
 | 
			
		||||
 | 
			
		||||
  if (watch->idle_source_id)
 | 
			
		||||
    {
 | 
			
		||||
      g_source_remove (watch->idle_source_id);
 | 
			
		||||
      watch->idle_source_id = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (watch->notify != NULL)
 | 
			
		||||
    watch->notify (watch->user_data);
 | 
			
		||||
 | 
			
		||||
  if (watch_xsync->xalarm != monitor_xsync->user_active_alarm &&
 | 
			
		||||
      watch_xsync->xalarm != None)
 | 
			
		||||
    {
 | 
			
		||||
      XSyncDestroyAlarm (monitor_xsync->display, watch_xsync->xalarm);
 | 
			
		||||
      g_hash_table_remove (monitor_xsync->alarms, (gpointer) watch_xsync->xalarm);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_object_unref (monitor);
 | 
			
		||||
  g_slice_free (MetaIdleMonitorWatchXSync, watch_xsync);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaIdleMonitorWatch *
 | 
			
		||||
meta_idle_monitor_xsync_make_watch (MetaIdleMonitor           *monitor,
 | 
			
		||||
                                    guint64                    timeout_msec,
 | 
			
		||||
                                    MetaIdleMonitorWatchFunc   callback,
 | 
			
		||||
                                    gpointer                   user_data,
 | 
			
		||||
                                    GDestroyNotify             notify)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (monitor);
 | 
			
		||||
  MetaIdleMonitorWatchXSync *watch_xsync;
 | 
			
		||||
  MetaIdleMonitorWatch *watch;
 | 
			
		||||
 | 
			
		||||
  watch_xsync = g_slice_new0 (MetaIdleMonitorWatchXSync);
 | 
			
		||||
  watch = (MetaIdleMonitorWatch *) watch_xsync;
 | 
			
		||||
 | 
			
		||||
  watch->monitor = monitor;
 | 
			
		||||
  watch->id = get_next_watch_serial ();
 | 
			
		||||
  watch->callback = callback;
 | 
			
		||||
  watch->user_data = user_data;
 | 
			
		||||
  watch->notify = notify;
 | 
			
		||||
  watch->timeout_msec = timeout_msec;
 | 
			
		||||
 | 
			
		||||
  if (monitor_xsync->user_active_alarm != None)
 | 
			
		||||
    {
 | 
			
		||||
      if (timeout_msec != 0)
 | 
			
		||||
        {
 | 
			
		||||
          watch_xsync->xalarm = _xsync_alarm_set (monitor_xsync, XSyncPositiveTransition, timeout_msec, TRUE);
 | 
			
		||||
 | 
			
		||||
          g_hash_table_add (monitor_xsync->alarms, (gpointer) watch_xsync->xalarm);
 | 
			
		||||
 | 
			
		||||
          if (meta_idle_monitor_get_idletime (monitor) > (gint64)timeout_msec)
 | 
			
		||||
            {
 | 
			
		||||
              watch->idle_source_id = g_idle_add (fire_watch_idle, watch);
 | 
			
		||||
              g_source_set_name_by_id (watch->idle_source_id, "[mutter] fire_watch_idle");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          watch_xsync->xalarm = monitor_xsync->user_active_alarm;
 | 
			
		||||
 | 
			
		||||
          set_alarm_enabled (monitor_xsync->display, monitor_xsync->user_active_alarm, TRUE);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return watch;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_idle_monitor_xsync_class_init (MetaIdleMonitorXSyncClass *klass)
 | 
			
		||||
{
 | 
			
		||||
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
  MetaIdleMonitorClass *idle_monitor_class = META_IDLE_MONITOR_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  object_class->dispose = meta_idle_monitor_xsync_dispose;
 | 
			
		||||
  object_class->constructed = meta_idle_monitor_xsync_constructed;
 | 
			
		||||
 | 
			
		||||
  idle_monitor_class->get_idletime = meta_idle_monitor_xsync_get_idletime;
 | 
			
		||||
  idle_monitor_class->make_watch = meta_idle_monitor_xsync_make_watch;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
meta_idle_monitor_xsync_init (MetaIdleMonitorXSync *monitor_xsync)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitor *monitor = META_IDLE_MONITOR (monitor_xsync);
 | 
			
		||||
 | 
			
		||||
  monitor->watches = g_hash_table_new_full (NULL, NULL, NULL, free_watch);
 | 
			
		||||
  monitor_xsync->alarms = g_hash_table_new (NULL, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
check_x11_watches (MetaIdleMonitor *monitor,
 | 
			
		||||
                   XSyncAlarm       alarm)
 | 
			
		||||
{
 | 
			
		||||
  GList *node, *watch_ids;
 | 
			
		||||
 | 
			
		||||
  /* we get the keys and do explicit look ups in case
 | 
			
		||||
   * an early iteration of the loop ends up leading
 | 
			
		||||
   * to watches from later iterations getting invalidated
 | 
			
		||||
   */
 | 
			
		||||
  watch_ids = g_hash_table_get_keys (monitor->watches);
 | 
			
		||||
 | 
			
		||||
  for (node = watch_ids; node != NULL; node = node->next)
 | 
			
		||||
    {
 | 
			
		||||
      guint watch_id = GPOINTER_TO_UINT (node->data);
 | 
			
		||||
      MetaIdleMonitorWatchXSync *watch;
 | 
			
		||||
 | 
			
		||||
      watch = g_hash_table_lookup (monitor->watches, GUINT_TO_POINTER (watch_id));
 | 
			
		||||
 | 
			
		||||
      if (watch && watch->xalarm == alarm)
 | 
			
		||||
        _meta_idle_monitor_watch_fire ((MetaIdleMonitorWatch *) watch);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_list_free (watch_ids);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_idle_monitor_xsync_handle_xevent (MetaIdleMonitor       *monitor,
 | 
			
		||||
                                       XSyncAlarmNotifyEvent *alarm_event)
 | 
			
		||||
{
 | 
			
		||||
  MetaIdleMonitorXSync *monitor_xsync = META_IDLE_MONITOR_XSYNC (monitor);
 | 
			
		||||
  XSyncAlarm alarm;
 | 
			
		||||
  gboolean has_alarm;
 | 
			
		||||
 | 
			
		||||
  if (alarm_event->state != XSyncAlarmActive)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  alarm = alarm_event->alarm;
 | 
			
		||||
 | 
			
		||||
  has_alarm = FALSE;
 | 
			
		||||
 | 
			
		||||
  if (alarm == monitor_xsync->user_active_alarm)
 | 
			
		||||
    {
 | 
			
		||||
      set_alarm_enabled (monitor_xsync->display,
 | 
			
		||||
                         alarm,
 | 
			
		||||
                         FALSE);
 | 
			
		||||
      has_alarm = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
  else if (g_hash_table_contains (monitor_xsync->alarms, (gpointer) alarm))
 | 
			
		||||
    {
 | 
			
		||||
      ensure_alarm_rescheduled (monitor_xsync->display,
 | 
			
		||||
                                alarm);
 | 
			
		||||
      has_alarm = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (has_alarm)
 | 
			
		||||
    check_x11_watches (monitor, alarm);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,47 +0,0 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright 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, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 * Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
 | 
			
		||||
 *         from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef META_IDLE_MONITOR_XSYNC_H
 | 
			
		||||
#define META_IDLE_MONITOR_XSYNC_H
 | 
			
		||||
 | 
			
		||||
#include <glib-object.h>
 | 
			
		||||
#include <meta/meta-idle-monitor.h>
 | 
			
		||||
 | 
			
		||||
#include <X11/Xlib.h>
 | 
			
		||||
#include <X11/extensions/sync.h>
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_IDLE_MONITOR_XSYNC            (meta_idle_monitor_xsync_get_type ())
 | 
			
		||||
#define META_IDLE_MONITOR_XSYNC(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_IDLE_MONITOR_XSYNC, MetaIdleMonitorXSync))
 | 
			
		||||
#define META_IDLE_MONITOR_XSYNC_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  META_TYPE_IDLE_MONITOR_XSYNC, MetaIdleMonitorXSyncClass))
 | 
			
		||||
#define META_IS_IDLE_MONITOR_XSYNC(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_IDLE_MONITOR_XSYNC))
 | 
			
		||||
#define META_IS_IDLE_MONITOR_XSYNC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  META_TYPE_IDLE_MONITOR_XSYNC))
 | 
			
		||||
#define META_IDLE_MONITOR_XSYNC_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  META_TYPE_IDLE_MONITOR_XSYNC, MetaIdleMonitorXSyncClass))
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaIdleMonitorXSync        MetaIdleMonitorXSync;
 | 
			
		||||
typedef struct _MetaIdleMonitorXSyncClass   MetaIdleMonitorXSyncClass;
 | 
			
		||||
 | 
			
		||||
GType meta_idle_monitor_xsync_get_type (void);
 | 
			
		||||
 | 
			
		||||
void meta_idle_monitor_xsync_handle_xevent (MetaIdleMonitor       *monitor,
 | 
			
		||||
                                            XSyncAlarmNotifyEvent *xevent);
 | 
			
		||||
 | 
			
		||||
#endif /* META_IDLE_MONITOR_XSYNC_H */
 | 
			
		||||
@@ -225,8 +225,10 @@ is_crtc_assignment_changed (MetaCrtc      *crtc,
 | 
			
		||||
      for (j = 0; j < crtc_info->outputs->len; j++)
 | 
			
		||||
        {
 | 
			
		||||
          MetaOutput *output = ((MetaOutput**) crtc_info->outputs->pdata)[j];
 | 
			
		||||
          MetaCrtc *assigned_crtc;
 | 
			
		||||
 | 
			
		||||
          if (output->crtc != crtc)
 | 
			
		||||
          assigned_crtc = meta_output_get_assigned_crtc (output);
 | 
			
		||||
          if (assigned_crtc != crtc)
 | 
			
		||||
            return TRUE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -243,6 +245,7 @@ is_output_assignment_changed (MetaOutput      *output,
 | 
			
		||||
                              MetaOutputInfo **output_infos,
 | 
			
		||||
                              unsigned int     n_output_infos)
 | 
			
		||||
{
 | 
			
		||||
  MetaCrtc *assigned_crtc;
 | 
			
		||||
  gboolean output_is_found = FALSE;
 | 
			
		||||
  unsigned int i;
 | 
			
		||||
 | 
			
		||||
@@ -265,8 +268,10 @@ is_output_assignment_changed (MetaOutput      *output,
 | 
			
		||||
      output_is_found = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  assigned_crtc = meta_output_get_assigned_crtc (output);
 | 
			
		||||
 | 
			
		||||
  if (!output_is_found)
 | 
			
		||||
    return output->crtc != NULL;
 | 
			
		||||
    return assigned_crtc != NULL;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < n_crtc_infos; i++)
 | 
			
		||||
    {
 | 
			
		||||
@@ -279,7 +284,7 @@ is_output_assignment_changed (MetaOutput      *output,
 | 
			
		||||
            ((MetaOutput**) crtc_info->outputs->pdata)[j];
 | 
			
		||||
 | 
			
		||||
          if (crtc_info_output == output &&
 | 
			
		||||
              crtc_info->crtc == output->crtc)
 | 
			
		||||
              crtc_info->crtc == assigned_crtc)
 | 
			
		||||
            return FALSE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -455,7 +460,7 @@ apply_crtc_assignments (MetaMonitorManager *manager,
 | 
			
		||||
              output = ((MetaOutput**)crtc_info->outputs->pdata)[j];
 | 
			
		||||
 | 
			
		||||
              output->is_dirty = TRUE;
 | 
			
		||||
              output->crtc = crtc;
 | 
			
		||||
              meta_output_assign_crtc (output, crtc);
 | 
			
		||||
 | 
			
		||||
              output_ids[j] = output->winsys_id;
 | 
			
		||||
            }
 | 
			
		||||
@@ -521,7 +526,7 @@ apply_crtc_assignments (MetaMonitorManager *manager,
 | 
			
		||||
          continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      output->crtc = NULL;
 | 
			
		||||
      meta_output_unassign_crtc (output);
 | 
			
		||||
      output->is_primary = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -97,10 +97,13 @@ output_set_underscanning_xrandr (MetaOutput *output,
 | 
			
		||||
   * make the border configurable. */
 | 
			
		||||
  if (underscanning)
 | 
			
		||||
    {
 | 
			
		||||
      MetaCrtc *crtc;
 | 
			
		||||
      uint32_t border_value;
 | 
			
		||||
 | 
			
		||||
      crtc = meta_output_get_assigned_crtc (output);
 | 
			
		||||
 | 
			
		||||
      prop = XInternAtom (xdisplay, "underscan hborder", False);
 | 
			
		||||
      border_value = output->crtc->current_mode->width * 0.05;
 | 
			
		||||
      border_value = crtc->current_mode->width * 0.05;
 | 
			
		||||
 | 
			
		||||
      xcb_randr_change_output_property (XGetXCBConnection (xdisplay),
 | 
			
		||||
                                        (XID) output->winsys_id,
 | 
			
		||||
@@ -109,7 +112,7 @@ output_set_underscanning_xrandr (MetaOutput *output,
 | 
			
		||||
                                        1, &border_value);
 | 
			
		||||
 | 
			
		||||
      prop = XInternAtom (xdisplay, "underscan vborder", False);
 | 
			
		||||
      border_value = output->crtc->current_mode->height * 0.05;
 | 
			
		||||
      border_value = crtc->current_mode->height * 0.05;
 | 
			
		||||
 | 
			
		||||
      xcb_randr_change_output_property (XGetXCBConnection (xdisplay),
 | 
			
		||||
                                        (XID) output->winsys_id,
 | 
			
		||||
@@ -737,14 +740,14 @@ output_get_crtcs (MetaOutput    *output,
 | 
			
		||||
    }
 | 
			
		||||
  output->n_possible_crtcs = n_actual_crtcs;
 | 
			
		||||
 | 
			
		||||
  output->crtc = NULL;
 | 
			
		||||
  meta_output_unassign_crtc (output);
 | 
			
		||||
  for (l = meta_gpu_get_crtcs (gpu); l; l = l->next)
 | 
			
		||||
    {
 | 
			
		||||
      MetaCrtc *crtc = l->data;
 | 
			
		||||
 | 
			
		||||
      if ((XID) crtc->crtc_id == xrandr_output->crtc)
 | 
			
		||||
        {
 | 
			
		||||
          output->crtc = crtc;
 | 
			
		||||
          meta_output_assign_crtc (output, crtc);
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -113,7 +113,7 @@ draw_crtc (MetaMonitor         *monitor,
 | 
			
		||||
  CoglTexture *texture = data->texture;
 | 
			
		||||
  MetaLogicalMonitor *logical_monitor = data->logical_monitor;
 | 
			
		||||
  MetaOutput *output = monitor_crtc_mode->output;
 | 
			
		||||
  MetaCrtc *crtc = output->crtc;
 | 
			
		||||
  MetaCrtc *crtc;
 | 
			
		||||
  MetaRendererView *renderer_view = META_RENDERER_VIEW (data->view);
 | 
			
		||||
  MetaMonitorTransform view_transform;
 | 
			
		||||
  MetaMonitorTransform layout_transform = META_MONITOR_TRANSFORM_NORMAL;
 | 
			
		||||
@@ -129,6 +129,8 @@ draw_crtc (MetaMonitor         *monitor,
 | 
			
		||||
  texture_width = cogl_texture_get_width (texture);
 | 
			
		||||
  texture_height = cogl_texture_get_height (texture);
 | 
			
		||||
 | 
			
		||||
  crtc = meta_output_get_assigned_crtc (output);
 | 
			
		||||
 | 
			
		||||
  clutter_stage_view_get_layout (data->view, &view_layout);
 | 
			
		||||
  sample_x = crtc->rect.x - view_layout.x;
 | 
			
		||||
  sample_y = crtc->rect.y - view_layout.y;
 | 
			
		||||
 
 | 
			
		||||
@@ -50,24 +50,22 @@ calculate_view_transform (MetaMonitorManager *monitor_manager,
 | 
			
		||||
{
 | 
			
		||||
  MetaMonitor *main_monitor;
 | 
			
		||||
  MetaOutput *main_output;
 | 
			
		||||
  MetaMonitorTransform crtc_transform;
 | 
			
		||||
  MetaCrtc *crtc;
 | 
			
		||||
 | 
			
		||||
  main_monitor = meta_logical_monitor_get_monitors (logical_monitor)->data;
 | 
			
		||||
  main_output = meta_monitor_get_main_output (main_monitor);
 | 
			
		||||
  crtc_transform =
 | 
			
		||||
    meta_monitor_logical_to_crtc_transform (main_monitor,
 | 
			
		||||
                                            logical_monitor->transform);
 | 
			
		||||
 | 
			
		||||
  crtc = meta_output_get_assigned_crtc (main_output);
 | 
			
		||||
  /*
 | 
			
		||||
   * Pick any monitor and output and check; all CRTCs of a logical monitor will
 | 
			
		||||
   * always have the same transform assigned to them.
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  if (meta_monitor_manager_is_transform_handled (monitor_manager,
 | 
			
		||||
                                                 main_output->crtc,
 | 
			
		||||
                                                 crtc_transform))
 | 
			
		||||
                                                 crtc,
 | 
			
		||||
                                                 crtc->transform))
 | 
			
		||||
    return META_MONITOR_TRANSFORM_NORMAL;
 | 
			
		||||
  else
 | 
			
		||||
    return crtc_transform;
 | 
			
		||||
    return crtc->transform;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaRendererView *
 | 
			
		||||
 
 | 
			
		||||
@@ -67,7 +67,7 @@
 | 
			
		||||
#include <meta/meta-background-group.h>
 | 
			
		||||
#include <meta/meta-shadow-factory.h>
 | 
			
		||||
#include "meta-window-actor-private.h"
 | 
			
		||||
#include "meta-window-group.h"
 | 
			
		||||
#include "meta-window-group-private.h"
 | 
			
		||||
#include "window-private.h" /* to check window->hidden */
 | 
			
		||||
#include "display-private.h" /* for meta_display_lookup_x_window() and meta_display_cancel_touch() */
 | 
			
		||||
#include "util-private.h"
 | 
			
		||||
 
 | 
			
		||||
@@ -58,5 +58,6 @@ void meta_window_actor_effect_completed (MetaWindowActor  *actor,
 | 
			
		||||
 | 
			
		||||
MetaSurfaceActor *meta_window_actor_get_surface (MetaWindowActor *self);
 | 
			
		||||
void meta_window_actor_update_surface (MetaWindowActor *self);
 | 
			
		||||
MetaWindowActor *meta_window_actor_from_window (MetaWindow *window);
 | 
			
		||||
 | 
			
		||||
#endif /* META_WINDOW_ACTOR_PRIVATE_H */
 | 
			
		||||
 
 | 
			
		||||
@@ -142,6 +142,8 @@ struct _FrameData
 | 
			
		||||
enum
 | 
			
		||||
{
 | 
			
		||||
  FIRST_FRAME,
 | 
			
		||||
  EFFECTS_COMPLETED,
 | 
			
		||||
 | 
			
		||||
  LAST_SIGNAL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -238,6 +240,21 @@ meta_window_actor_class_init (MetaWindowActorClass *klass)
 | 
			
		||||
                  NULL, NULL, NULL,
 | 
			
		||||
                  G_TYPE_NONE, 0);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * MetaWindowActor::effects-completed:
 | 
			
		||||
   * @actor: the #MetaWindowActor instance
 | 
			
		||||
   *
 | 
			
		||||
   * The ::effects-completed signal will be emitted once all pending compositor
 | 
			
		||||
   * effects are completed.
 | 
			
		||||
   */
 | 
			
		||||
  signals[EFFECTS_COMPLETED] =
 | 
			
		||||
    g_signal_new ("effects-completed",
 | 
			
		||||
                  G_TYPE_FROM_CLASS (object_class),
 | 
			
		||||
                  G_SIGNAL_RUN_LAST,
 | 
			
		||||
                  0,
 | 
			
		||||
                  NULL, NULL, NULL,
 | 
			
		||||
                  G_TYPE_NONE, 0);
 | 
			
		||||
 | 
			
		||||
  pspec = g_param_spec_object ("meta-window",
 | 
			
		||||
                               "MetaWindow",
 | 
			
		||||
                               "The displayed MetaWindow",
 | 
			
		||||
@@ -1131,6 +1148,7 @@ meta_window_actor_after_effects (MetaWindowActor *self)
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  g_signal_emit (self, signals[EFFECTS_COMPLETED], 0);
 | 
			
		||||
  meta_window_actor_sync_visibility (self);
 | 
			
		||||
  meta_window_actor_sync_actor_geometry (self, FALSE);
 | 
			
		||||
}
 | 
			
		||||
@@ -2157,3 +2175,9 @@ meta_window_actor_sync_updates_frozen (MetaWindowActor *self)
 | 
			
		||||
 | 
			
		||||
  meta_window_actor_set_updates_frozen (self, meta_window_updates_are_frozen (window));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetaWindowActor *
 | 
			
		||||
meta_window_actor_from_window (MetaWindow *window)
 | 
			
		||||
{
 | 
			
		||||
  return META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										24
									
								
								src/compositor/meta-window-group-private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/compositor/meta-window-group-private.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
#ifndef META_WINDOW_GROUP_PRIVATE_H
 | 
			
		||||
#define META_WINDOW_GROUP_PRIVATE_H
 | 
			
		||||
 | 
			
		||||
#include <meta/meta-window-group.h>
 | 
			
		||||
 | 
			
		||||
#include <meta/screen.h>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * MetaWindowGroup:
 | 
			
		||||
 *
 | 
			
		||||
 * This class is a subclass of ClutterActor with special handling for
 | 
			
		||||
 * #MetaCullable when painting children. It uses code similar to
 | 
			
		||||
 * meta_cullable_cull_out_children(), but also has additional special
 | 
			
		||||
 * cases for the undirected window, and similar.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaWindowGroupPrivate MetaWindowGroupPrivate;
 | 
			
		||||
 | 
			
		||||
ClutterActor *meta_window_group_new (MetaScreen *screen);
 | 
			
		||||
 | 
			
		||||
#endif /* META_WINDOW_GROUP_PRIVATE_H */
 | 
			
		||||
@@ -10,7 +10,7 @@
 | 
			
		||||
#include "clutter-utils.h"
 | 
			
		||||
#include "compositor-private.h"
 | 
			
		||||
#include "meta-window-actor-private.h"
 | 
			
		||||
#include "meta-window-group.h"
 | 
			
		||||
#include "meta-window-group-private.h"
 | 
			
		||||
#include "window-private.h"
 | 
			
		||||
#include "meta-cullable.h"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,37 +0,0 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
#ifndef META_WINDOW_GROUP_H
 | 
			
		||||
#define META_WINDOW_GROUP_H
 | 
			
		||||
 | 
			
		||||
#include <clutter/clutter.h>
 | 
			
		||||
 | 
			
		||||
#include <meta/screen.h>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * MetaWindowGroup:
 | 
			
		||||
 *
 | 
			
		||||
 * This class is a subclass of ClutterActor with special handling for
 | 
			
		||||
 * #MetaCullable when painting children. It uses code similar to
 | 
			
		||||
 * meta_cullable_cull_out_children(), but also has additional special
 | 
			
		||||
 * cases for the undirected window, and similar.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_WINDOW_GROUP            (meta_window_group_get_type ())
 | 
			
		||||
#define META_WINDOW_GROUP(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_WINDOW_GROUP, MetaWindowGroup))
 | 
			
		||||
#define META_WINDOW_GROUP_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_WINDOW_GROUP, MetaWindowGroupClass))
 | 
			
		||||
#define META_IS_WINDOW_GROUP(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_WINDOW_GROUP))
 | 
			
		||||
#define META_IS_WINDOW_GROUP_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_WINDOW_GROUP))
 | 
			
		||||
#define META_WINDOW_GROUP_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_WINDOW_GROUP, MetaWindowGroupClass))
 | 
			
		||||
 | 
			
		||||
typedef struct _MetaWindowGroup        MetaWindowGroup;
 | 
			
		||||
typedef struct _MetaWindowGroupClass   MetaWindowGroupClass;
 | 
			
		||||
typedef struct _MetaWindowGroupPrivate MetaWindowGroupPrivate;
 | 
			
		||||
 | 
			
		||||
GType meta_window_group_get_type (void);
 | 
			
		||||
 | 
			
		||||
ClutterActor *meta_window_group_new (MetaScreen *screen);
 | 
			
		||||
 | 
			
		||||
gboolean meta_window_group_actor_is_untransformed (ClutterActor *actor,
 | 
			
		||||
                                                   int          *x_origin,
 | 
			
		||||
                                                   int          *y_origin);
 | 
			
		||||
#endif /* META_WINDOW_GROUP_H */
 | 
			
		||||
@@ -886,7 +886,8 @@ constrain_modal_dialog (MetaWindow         *window,
 | 
			
		||||
  MetaRectangle child_rect, parent_rect;
 | 
			
		||||
  gboolean constraint_already_satisfied;
 | 
			
		||||
 | 
			
		||||
  if (!meta_window_is_attached_dialog (window) ||
 | 
			
		||||
  if (!parent ||
 | 
			
		||||
      !meta_window_is_attached_dialog (window) ||
 | 
			
		||||
      meta_window_get_placement_rule (window))
 | 
			
		||||
    return TRUE;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -53,7 +53,7 @@
 | 
			
		||||
#include "backends/meta-logical-monitor.h"
 | 
			
		||||
#include "backends/native/meta-backend-native.h"
 | 
			
		||||
#include "backends/x11/meta-backend-x11.h"
 | 
			
		||||
#include "backends/meta-stage.h"
 | 
			
		||||
#include "backends/meta-stage-private.h"
 | 
			
		||||
#include "backends/meta-input-settings-private.h"
 | 
			
		||||
#include <clutter/x11/clutter-x11.h>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -32,9 +32,10 @@
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_NATIVE_BACKEND
 | 
			
		||||
#include "backends/native/meta-backend-native.h"
 | 
			
		||||
#include "backends/native/meta-idle-monitor-native.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "backends/meta-idle-monitor-private.h"
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_WAYLAND
 | 
			
		||||
#include "wayland/meta-wayland-private.h"
 | 
			
		||||
#endif
 | 
			
		||||
@@ -92,46 +93,38 @@ get_window_for_event (MetaDisplay        *display,
 | 
			
		||||
static void
 | 
			
		||||
handle_idletime_for_event (const ClutterEvent *event)
 | 
			
		||||
{
 | 
			
		||||
#ifdef HAVE_NATIVE_BACKEND
 | 
			
		||||
  /* This is handled by XSync under X11. */
 | 
			
		||||
  MetaBackend *backend = meta_get_backend ();
 | 
			
		||||
  ClutterInputDevice *device, *source_device;
 | 
			
		||||
  MetaIdleMonitor *core_monitor, *device_monitor;
 | 
			
		||||
  int device_id;
 | 
			
		||||
 | 
			
		||||
  if (META_IS_BACKEND_NATIVE (backend))
 | 
			
		||||
  device = clutter_event_get_device (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 ();
 | 
			
		||||
  device_monitor = meta_idle_monitor_get_for_device (device_id);
 | 
			
		||||
 | 
			
		||||
  meta_idle_monitor_reset_idletime (core_monitor);
 | 
			
		||||
  meta_idle_monitor_reset_idletime (device_monitor);
 | 
			
		||||
 | 
			
		||||
  source_device = clutter_event_get_source_device (event);
 | 
			
		||||
  if (source_device != device)
 | 
			
		||||
    {
 | 
			
		||||
      ClutterInputDevice *device, *source_device;
 | 
			
		||||
      MetaIdleMonitor *core_monitor, *device_monitor;
 | 
			
		||||
      int device_id;
 | 
			
		||||
 | 
			
		||||
      device = clutter_event_get_device (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 ();
 | 
			
		||||
      device_monitor = meta_idle_monitor_get_for_device (device_id);
 | 
			
		||||
 | 
			
		||||
      meta_idle_monitor_native_reset_idletime (core_monitor);
 | 
			
		||||
      meta_idle_monitor_native_reset_idletime (device_monitor);
 | 
			
		||||
 | 
			
		||||
      source_device = clutter_event_get_source_device (event);
 | 
			
		||||
      if (source_device != device)
 | 
			
		||||
        {
 | 
			
		||||
          device_id = clutter_input_device_get_device_id (device);
 | 
			
		||||
          device_monitor = meta_idle_monitor_get_for_device (device_id);
 | 
			
		||||
          meta_idle_monitor_native_reset_idletime (device_monitor);
 | 
			
		||||
        }
 | 
			
		||||
      meta_idle_monitor_reset_idletime (device_monitor);
 | 
			
		||||
    }
 | 
			
		||||
#endif /* HAVE_NATIVE_BACKEND */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
 
 | 
			
		||||
@@ -81,6 +81,7 @@ typedef enum
 | 
			
		||||
  META_MOVE_RESIZE_STATE_CHANGED = 1 << 5,
 | 
			
		||||
  META_MOVE_RESIZE_UNMAXIMIZE = 1 << 6,
 | 
			
		||||
  META_MOVE_RESIZE_FORCE_MOVE = 1 << 7,
 | 
			
		||||
  META_MOVE_RESIZE_WAYLAND_STATE_CHANGED = 1 << 8,
 | 
			
		||||
} MetaMoveResizeFlags;
 | 
			
		||||
 | 
			
		||||
typedef enum
 | 
			
		||||
@@ -88,6 +89,7 @@ typedef enum
 | 
			
		||||
  META_MOVE_RESIZE_RESULT_MOVED               = 1 << 0,
 | 
			
		||||
  META_MOVE_RESIZE_RESULT_RESIZED             = 1 << 1,
 | 
			
		||||
  META_MOVE_RESIZE_RESULT_FRAME_SHAPE_CHANGED = 1 << 2,
 | 
			
		||||
  META_MOVE_RESIZE_RESULT_STATE_CHANGED       = 1 << 3,
 | 
			
		||||
} MetaMoveResizeResultFlags;
 | 
			
		||||
 | 
			
		||||
typedef enum
 | 
			
		||||
 
 | 
			
		||||
@@ -3997,7 +3997,7 @@ meta_window_move_resize_internal (MetaWindow          *window,
 | 
			
		||||
 | 
			
		||||
  if ((moved_or_resized ||
 | 
			
		||||
       did_placement ||
 | 
			
		||||
       (flags & META_MOVE_RESIZE_STATE_CHANGED) != 0) &&
 | 
			
		||||
       (result & META_MOVE_RESIZE_RESULT_STATE_CHANGED) != 0) &&
 | 
			
		||||
      window->known_to_compositor)
 | 
			
		||||
    {
 | 
			
		||||
      meta_compositor_sync_window_geometry (window->display->compositor,
 | 
			
		||||
@@ -5268,7 +5268,7 @@ static cairo_surface_t *
 | 
			
		||||
load_default_window_icon (int size)
 | 
			
		||||
{
 | 
			
		||||
  GtkIconTheme *theme = gtk_icon_theme_get_default ();
 | 
			
		||||
  GdkPixbuf *pixbuf;
 | 
			
		||||
  g_autoptr (GdkPixbuf) pixbuf = NULL;
 | 
			
		||||
  const char *icon_name;
 | 
			
		||||
 | 
			
		||||
  if (gtk_icon_theme_has_icon (theme, META_DEFAULT_ICON_NAME))
 | 
			
		||||
 
 | 
			
		||||
@@ -54,4 +54,7 @@ MetaMonitorSwitchConfigType meta_monitor_manager_get_switch_config (MetaMonitorM
 | 
			
		||||
 | 
			
		||||
gint meta_monitor_manager_get_display_configuration_timeout (void);
 | 
			
		||||
 | 
			
		||||
/* Re-declaration of parent type for introspection */
 | 
			
		||||
GType meta_dbus_display_config_skeleton_get_type (void) G_GNUC_CONST;
 | 
			
		||||
 | 
			
		||||
#endif /* META_MONITOR_MANAGER_H */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										32
									
								
								src/meta/meta-stage.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/meta/meta-stage.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2012 Intel Corporation
 | 
			
		||||
 *
 | 
			
		||||
 * 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_STAGE_H
 | 
			
		||||
#define META_STAGE_H
 | 
			
		||||
 | 
			
		||||
#include "clutter/clutter.h"
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_STAGE (meta_stage_get_type ())
 | 
			
		||||
G_DECLARE_FINAL_TYPE (MetaStage, meta_stage, META, STAGE, ClutterStage)
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* META_STAGE_H */
 | 
			
		||||
							
								
								
									
										11
									
								
								src/meta/meta-window-group.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/meta/meta-window-group.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
#ifndef META_WINDOW_GROUP_H
 | 
			
		||||
#define META_WINDOW_GROUP_H
 | 
			
		||||
 | 
			
		||||
#include "clutter/clutter.h"
 | 
			
		||||
 | 
			
		||||
#define META_TYPE_WINDOW_GROUP (meta_window_group_get_type())
 | 
			
		||||
G_DECLARE_FINAL_TYPE (MetaWindowGroup, meta_window_group, META, WINDOW_GROUP, ClutterActor)
 | 
			
		||||
 | 
			
		||||
#endif /* META_WINDOW_GROUP_H */
 | 
			
		||||
@@ -28,6 +28,8 @@
 | 
			
		||||
      <arg name="id" direction="in" type="u" />
 | 
			
		||||
    </method>
 | 
			
		||||
 | 
			
		||||
    <method name="ResetIdletime"/>
 | 
			
		||||
 | 
			
		||||
    <signal name="WatchFired">
 | 
			
		||||
      <arg name="id" direction="out" type="u" />
 | 
			
		||||
    </signal>
 | 
			
		||||
 
 | 
			
		||||
@@ -209,7 +209,7 @@ apply_crtc_assignments (MetaMonitorManager *manager,
 | 
			
		||||
              output = ((MetaOutput**)crtc_info->outputs->pdata)[j];
 | 
			
		||||
 | 
			
		||||
              output->is_dirty = TRUE;
 | 
			
		||||
              output->crtc = crtc;
 | 
			
		||||
              meta_output_assign_crtc (output, crtc);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -255,7 +255,7 @@ apply_crtc_assignments (MetaMonitorManager *manager,
 | 
			
		||||
          continue;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      output->crtc = NULL;
 | 
			
		||||
      meta_output_unassign_crtc (output);
 | 
			
		||||
      output->is_primary = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -449,22 +449,24 @@ check_current_monitor_mode (MetaMonitor         *monitor,
 | 
			
		||||
  CheckMonitorModeData *data = user_data;
 | 
			
		||||
  MetaMonitorManager *monitor_manager = data->monitor_manager;
 | 
			
		||||
  MetaOutput *output;
 | 
			
		||||
  MetaCrtc *crtc;
 | 
			
		||||
 | 
			
		||||
  output = output_from_winsys_id (monitor_manager,
 | 
			
		||||
                                  data->expect_crtc_mode_iter->output);
 | 
			
		||||
  crtc = meta_output_get_assigned_crtc (output);
 | 
			
		||||
 | 
			
		||||
  if (data->expect_crtc_mode_iter->crtc_mode == -1)
 | 
			
		||||
    {
 | 
			
		||||
      g_assert_null (output->crtc);
 | 
			
		||||
      g_assert_null (crtc);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      MetaLogicalMonitor *logical_monitor;
 | 
			
		||||
 | 
			
		||||
      g_assert_nonnull (output->crtc);
 | 
			
		||||
      g_assert (monitor_crtc_mode->crtc_mode == output->crtc->current_mode);
 | 
			
		||||
      g_assert_nonnull (crtc);
 | 
			
		||||
      g_assert (monitor_crtc_mode->crtc_mode == crtc->current_mode);
 | 
			
		||||
 | 
			
		||||
      logical_monitor = output->crtc->logical_monitor;
 | 
			
		||||
      logical_monitor = crtc->logical_monitor;
 | 
			
		||||
      g_assert_nonnull (logical_monitor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -553,6 +555,7 @@ check_logical_monitor (MonitorTestCase               *test_case,
 | 
			
		||||
      for (l_output = outputs; l_output; l_output = l_output->next)
 | 
			
		||||
        {
 | 
			
		||||
          MetaOutput *output = l_output->data;
 | 
			
		||||
          MetaCrtc *crtc;
 | 
			
		||||
 | 
			
		||||
          if (output->is_primary)
 | 
			
		||||
            {
 | 
			
		||||
@@ -560,8 +563,8 @@ check_logical_monitor (MonitorTestCase               *test_case,
 | 
			
		||||
              primary_output = output;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          g_assert (!output->crtc ||
 | 
			
		||||
                    output->crtc->logical_monitor == logical_monitor);
 | 
			
		||||
          crtc = meta_output_get_assigned_crtc (output);
 | 
			
		||||
          g_assert (!crtc || crtc->logical_monitor == logical_monitor);
 | 
			
		||||
          g_assert_cmpint (logical_monitor->is_presentation,
 | 
			
		||||
                           ==,
 | 
			
		||||
                           output->is_presentation);
 | 
			
		||||
@@ -983,7 +986,8 @@ create_monitor_test_setup (MonitorTestCase *test_case,
 | 
			
		||||
 | 
			
		||||
      output = g_object_new (META_TYPE_OUTPUT, NULL);
 | 
			
		||||
 | 
			
		||||
      output->crtc = crtc;
 | 
			
		||||
      if (crtc)
 | 
			
		||||
        meta_output_assign_crtc (output, crtc);
 | 
			
		||||
      output->winsys_id = i;
 | 
			
		||||
      output->name = (is_laptop_panel ? g_strdup_printf ("eDP-%d",
 | 
			
		||||
                                                  ++n_laptop_panels)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										283
									
								
								src/ui/frames.c
									
									
									
									
									
								
							
							
						
						
									
										283
									
								
								src/ui/frames.c
									
									
									
									
									
								
							@@ -71,6 +71,14 @@ static MetaFrameControl get_control  (MetaUIFrame       *frame,
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (MetaFrames, meta_frames, GTK_TYPE_WINDOW);
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
  META_ACTION_CLICK,
 | 
			
		||||
  META_ACTION_RIGHT_CLICK,
 | 
			
		||||
  META_ACTION_MIDDLE_CLICK,
 | 
			
		||||
  META_ACTION_DOUBLE_CLICK,
 | 
			
		||||
  META_ACTION_IGNORE
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static GObject *
 | 
			
		||||
meta_frames_constructor (GType                  gtype,
 | 
			
		||||
                         guint                  n_properties,
 | 
			
		||||
@@ -742,17 +750,25 @@ redraw_control (MetaUIFrame *frame,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
meta_frame_titlebar_event (MetaUIFrame *frame,
 | 
			
		||||
                           ClutterButtonEvent *event,
 | 
			
		||||
                           int action)
 | 
			
		||||
meta_frame_titlebar_event (MetaUIFrame        *frame,
 | 
			
		||||
                           const ClutterEvent *event,
 | 
			
		||||
                           int                 action)
 | 
			
		||||
{
 | 
			
		||||
  MetaFrameFlags flags;
 | 
			
		||||
  Display *display;
 | 
			
		||||
  uint32_t evtime;
 | 
			
		||||
  float x, y;
 | 
			
		||||
 | 
			
		||||
  g_assert (event->type == CLUTTER_BUTTON_PRESS ||
 | 
			
		||||
            event->type == CLUTTER_TOUCH_BEGIN);
 | 
			
		||||
 | 
			
		||||
  display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 | 
			
		||||
 | 
			
		||||
  flags = meta_frame_get_flags (frame->meta_window->frame);
 | 
			
		||||
 | 
			
		||||
  evtime = clutter_event_get_time (event);
 | 
			
		||||
  clutter_event_get_coords (event, &x, &y);
 | 
			
		||||
 | 
			
		||||
  switch (action)
 | 
			
		||||
    {
 | 
			
		||||
    case G_DESKTOP_TITLEBAR_ACTION_TOGGLE_SHADE:
 | 
			
		||||
@@ -760,9 +776,9 @@ meta_frame_titlebar_event (MetaUIFrame *frame,
 | 
			
		||||
        if (flags & META_FRAME_ALLOWS_SHADE)
 | 
			
		||||
          {
 | 
			
		||||
            if (flags & META_FRAME_SHADED)
 | 
			
		||||
              meta_window_unshade (frame->meta_window, event->time);
 | 
			
		||||
              meta_window_unshade (frame->meta_window, evtime);
 | 
			
		||||
            else
 | 
			
		||||
              meta_window_shade (frame->meta_window, event->time);
 | 
			
		||||
              meta_window_shade (frame->meta_window, evtime);
 | 
			
		||||
          }
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
@@ -808,16 +824,14 @@ meta_frame_titlebar_event (MetaUIFrame *frame,
 | 
			
		||||
    case G_DESKTOP_TITLEBAR_ACTION_LOWER:
 | 
			
		||||
      meta_core_user_lower_and_unfocus (display,
 | 
			
		||||
                                        frame->xwindow,
 | 
			
		||||
                                        event->time);
 | 
			
		||||
                                        evtime);
 | 
			
		||||
      break;
 | 
			
		||||
 | 
			
		||||
    case G_DESKTOP_TITLEBAR_ACTION_MENU:
 | 
			
		||||
      meta_core_show_window_menu (display,
 | 
			
		||||
                                  frame->xwindow,
 | 
			
		||||
                                  META_WINDOW_MENU_WM,
 | 
			
		||||
                                  event->x,
 | 
			
		||||
                                  event->y,
 | 
			
		||||
                                  event->time);
 | 
			
		||||
                                  x, y, evtime);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -825,8 +839,8 @@ meta_frame_titlebar_event (MetaUIFrame *frame,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
meta_frame_double_click_event (MetaUIFrame  *frame,
 | 
			
		||||
                               ClutterButtonEvent *event)
 | 
			
		||||
meta_frame_double_click_event (MetaUIFrame        *frame,
 | 
			
		||||
                               const ClutterEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  int action = meta_prefs_get_action_double_click_titlebar ();
 | 
			
		||||
 | 
			
		||||
@@ -839,7 +853,8 @@ meta_frame_middle_click_event (MetaUIFrame *frame,
 | 
			
		||||
{
 | 
			
		||||
  int action = meta_prefs_get_action_middle_click_titlebar();
 | 
			
		||||
 | 
			
		||||
  return meta_frame_titlebar_event (frame, event, action);
 | 
			
		||||
  return meta_frame_titlebar_event (frame, (const ClutterEvent *) event,
 | 
			
		||||
                                    action);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
@@ -848,7 +863,8 @@ meta_frame_right_click_event (MetaUIFrame *frame,
 | 
			
		||||
{
 | 
			
		||||
  int action = meta_prefs_get_action_right_click_titlebar();
 | 
			
		||||
 | 
			
		||||
  return meta_frame_titlebar_event (frame, event, action);
 | 
			
		||||
  return meta_frame_titlebar_event (frame, (const ClutterEvent *) event,
 | 
			
		||||
                                    action);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
@@ -879,6 +895,8 @@ meta_frames_try_grab_op (MetaUIFrame *frame,
 | 
			
		||||
      frames->grab_x = grab_x;
 | 
			
		||||
      frames->grab_y = grab_y;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    frames->grab_touch = NULL;
 | 
			
		||||
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
@@ -889,6 +907,7 @@ meta_frames_retry_grab_op (MetaFrames *frames,
 | 
			
		||||
{
 | 
			
		||||
  Display *display;
 | 
			
		||||
  MetaGrabOp op;
 | 
			
		||||
  gboolean ret;
 | 
			
		||||
 | 
			
		||||
  if (frames->current_grab_op == META_GRAB_OP_NONE)
 | 
			
		||||
    return TRUE;
 | 
			
		||||
@@ -897,16 +916,20 @@ meta_frames_retry_grab_op (MetaFrames *frames,
 | 
			
		||||
  frames->current_grab_op = META_GRAB_OP_NONE;
 | 
			
		||||
  display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 | 
			
		||||
 | 
			
		||||
  return meta_core_begin_grab_op (display,
 | 
			
		||||
                                  frames->grab_frame->xwindow,
 | 
			
		||||
                                  op,
 | 
			
		||||
                                  FALSE,
 | 
			
		||||
                                  TRUE,
 | 
			
		||||
                                  frames->grab_frame->grab_button,
 | 
			
		||||
                                  0,
 | 
			
		||||
                                  time,
 | 
			
		||||
                                  frames->grab_x,
 | 
			
		||||
                                  frames->grab_y);
 | 
			
		||||
  ret = meta_core_begin_grab_op (display,
 | 
			
		||||
                                 frames->grab_frame->xwindow,
 | 
			
		||||
                                 op,
 | 
			
		||||
                                 FALSE,
 | 
			
		||||
                                 TRUE,
 | 
			
		||||
                                 frames->grab_frame->grab_button,
 | 
			
		||||
                                 0,
 | 
			
		||||
                                 time,
 | 
			
		||||
                                 frames->grab_x,
 | 
			
		||||
                                 frames->grab_y);
 | 
			
		||||
  if (ret)
 | 
			
		||||
    frames->grab_touch = NULL;
 | 
			
		||||
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static MetaGrabOp
 | 
			
		||||
@@ -935,12 +958,65 @@ grab_op_from_resize_control (MetaFrameControl control)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static guint
 | 
			
		||||
get_action (const ClutterEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  if (event->type == CLUTTER_BUTTON_PRESS ||
 | 
			
		||||
      event->type == CLUTTER_BUTTON_RELEASE)
 | 
			
		||||
    {
 | 
			
		||||
      switch (event->button.button)
 | 
			
		||||
        {
 | 
			
		||||
        case CLUTTER_BUTTON_PRIMARY:
 | 
			
		||||
          if (clutter_event_get_click_count (event) == 2)
 | 
			
		||||
            return META_ACTION_DOUBLE_CLICK;
 | 
			
		||||
          else
 | 
			
		||||
            return META_ACTION_CLICK;
 | 
			
		||||
        case CLUTTER_BUTTON_SECONDARY:
 | 
			
		||||
          return META_ACTION_RIGHT_CLICK;
 | 
			
		||||
        case CLUTTER_BUTTON_MIDDLE:
 | 
			
		||||
          return META_ACTION_MIDDLE_CLICK;
 | 
			
		||||
        default:
 | 
			
		||||
          meta_verbose ("No action triggered for button %u %s\n",
 | 
			
		||||
                        event->button.button,
 | 
			
		||||
                        (event->type == CLUTTER_BUTTON_PRESS) ? "press" : "release");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  else if (event->type == CLUTTER_TOUCH_BEGIN ||
 | 
			
		||||
           event->type == CLUTTER_TOUCH_UPDATE ||
 | 
			
		||||
           event->type == CLUTTER_TOUCH_END)
 | 
			
		||||
    {
 | 
			
		||||
      return META_ACTION_CLICK;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return META_ACTION_IGNORE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t
 | 
			
		||||
get_button_number (const ClutterEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  if (event->type == CLUTTER_TOUCH_BEGIN ||
 | 
			
		||||
      event->type == CLUTTER_TOUCH_UPDATE ||
 | 
			
		||||
      event->type == CLUTTER_TOUCH_END)
 | 
			
		||||
    return -1;
 | 
			
		||||
  else if (event->type == CLUTTER_BUTTON_PRESS ||
 | 
			
		||||
           event->type == CLUTTER_BUTTON_RELEASE)
 | 
			
		||||
    return clutter_event_get_button (event);
 | 
			
		||||
 | 
			
		||||
  g_assert_not_reached ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
meta_frame_left_click_event (MetaUIFrame *frame,
 | 
			
		||||
                             ClutterButtonEvent *event)
 | 
			
		||||
meta_frame_left_click_event (MetaUIFrame        *frame,
 | 
			
		||||
                             const ClutterEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  Display *display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 | 
			
		||||
  MetaFrameControl control = get_control (frame, event->x, event->y);
 | 
			
		||||
  MetaFrameControl control;
 | 
			
		||||
  guint32 evtime;
 | 
			
		||||
  gfloat x, y;
 | 
			
		||||
 | 
			
		||||
  evtime = clutter_event_get_time (event);
 | 
			
		||||
  clutter_event_get_coords (event, &x, &y);
 | 
			
		||||
  control = get_control (frame, x, y);
 | 
			
		||||
 | 
			
		||||
  switch (control)
 | 
			
		||||
    {
 | 
			
		||||
@@ -950,7 +1026,7 @@ meta_frame_left_click_event (MetaUIFrame *frame,
 | 
			
		||||
    case META_FRAME_CONTROL_DELETE:
 | 
			
		||||
    case META_FRAME_CONTROL_MENU:
 | 
			
		||||
    case META_FRAME_CONTROL_APPMENU:
 | 
			
		||||
      frame->grab_button = event->button;
 | 
			
		||||
      frame->grab_button = get_button_number (event);
 | 
			
		||||
      frame->button_state = META_BUTTON_STATE_PRESSED;
 | 
			
		||||
      frame->prelit_control = control;
 | 
			
		||||
      redraw_control (frame, control);
 | 
			
		||||
@@ -987,13 +1063,12 @@ meta_frame_left_click_event (MetaUIFrame *frame,
 | 
			
		||||
                                               frame->xwindow,
 | 
			
		||||
                                               menu,
 | 
			
		||||
                                               &root_rect,
 | 
			
		||||
                                               event->time);
 | 
			
		||||
                                               evtime);
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
        {
 | 
			
		||||
          meta_frames_try_grab_op (frame, META_GRAB_OP_FRAME_BUTTON,
 | 
			
		||||
                                   event->x, event->y,
 | 
			
		||||
                                   event->time);
 | 
			
		||||
                                   x, y, evtime);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      return TRUE;
 | 
			
		||||
@@ -1007,8 +1082,7 @@ meta_frame_left_click_event (MetaUIFrame *frame,
 | 
			
		||||
    case META_FRAME_CONTROL_RESIZE_W:
 | 
			
		||||
      meta_frames_try_grab_op (frame,
 | 
			
		||||
                               grab_op_from_resize_control (control),
 | 
			
		||||
                               event->x, event->y,
 | 
			
		||||
                               event->time);
 | 
			
		||||
                               x, y, evtime);
 | 
			
		||||
 | 
			
		||||
      return TRUE;
 | 
			
		||||
    case META_FRAME_CONTROL_TITLE:
 | 
			
		||||
@@ -1019,8 +1093,7 @@ meta_frame_left_click_event (MetaUIFrame *frame,
 | 
			
		||||
          {
 | 
			
		||||
            meta_frames_try_grab_op (frame,
 | 
			
		||||
                                     META_GRAB_OP_MOVING,
 | 
			
		||||
                                     event->x, event->y,
 | 
			
		||||
                                     event->time);
 | 
			
		||||
                                     x, y, evtime);
 | 
			
		||||
          }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
@@ -1036,21 +1109,31 @@ meta_frame_left_click_event (MetaUIFrame *frame,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
handle_button_press_event (MetaUIFrame *frame,
 | 
			
		||||
                           ClutterButtonEvent *event)
 | 
			
		||||
handle_press_event (MetaUIFrame        *frame,
 | 
			
		||||
                    const ClutterEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  MetaFrameControl control;
 | 
			
		||||
  Display *display;
 | 
			
		||||
  uint32_t evtime, action;
 | 
			
		||||
  float x, y;
 | 
			
		||||
 | 
			
		||||
  g_assert (event->type == CLUTTER_BUTTON_PRESS ||
 | 
			
		||||
            event->type == CLUTTER_TOUCH_BEGIN);
 | 
			
		||||
 | 
			
		||||
  action = get_action (event);
 | 
			
		||||
  if (action == META_ACTION_IGNORE)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 | 
			
		||||
 | 
			
		||||
  control = get_control (frame, event->x, event->y);
 | 
			
		||||
 | 
			
		||||
  evtime = clutter_event_get_time (event);
 | 
			
		||||
  clutter_event_get_coords (event, &x, &y);
 | 
			
		||||
  control = get_control (frame, x, y);
 | 
			
		||||
  /* don't do the rest of this if on client area */
 | 
			
		||||
  if (control == META_FRAME_CONTROL_CLIENT_AREA)
 | 
			
		||||
    return FALSE; /* not on the frame, just passed through from client */
 | 
			
		||||
 | 
			
		||||
  if (event->button == 1 &&
 | 
			
		||||
  if (action == META_ACTION_CLICK &&
 | 
			
		||||
      !(control == META_FRAME_CONTROL_MINIMIZE ||
 | 
			
		||||
        control == META_FRAME_CONTROL_DELETE ||
 | 
			
		||||
        control == META_FRAME_CONTROL_MAXIMIZE))
 | 
			
		||||
@@ -1058,52 +1141,60 @@ handle_button_press_event (MetaUIFrame *frame,
 | 
			
		||||
      meta_topic (META_DEBUG_FOCUS,
 | 
			
		||||
                  "Focusing window with frame 0x%lx due to button 1 press\n",
 | 
			
		||||
                  frame->xwindow);
 | 
			
		||||
      meta_window_focus (frame->meta_window, event->time);
 | 
			
		||||
      meta_window_focus (frame->meta_window, evtime);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  /* We want to shade even if we have a GrabOp, since we'll have a move grab
 | 
			
		||||
   * if we double click the titlebar.
 | 
			
		||||
   */
 | 
			
		||||
  if (control == META_FRAME_CONTROL_TITLE &&
 | 
			
		||||
      event->button == 1 &&
 | 
			
		||||
      event->click_count == 2)
 | 
			
		||||
      action == META_ACTION_DOUBLE_CLICK)
 | 
			
		||||
    {
 | 
			
		||||
      meta_core_end_grab_op (display, event->time);
 | 
			
		||||
      meta_core_end_grab_op (display, evtime);
 | 
			
		||||
      return meta_frame_double_click_event (frame, event);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (meta_core_get_grab_op (display) != META_GRAB_OP_NONE)
 | 
			
		||||
    return FALSE; /* already up to something */
 | 
			
		||||
 | 
			
		||||
  frame->grab_button = event->button;
 | 
			
		||||
  frame->grab_button = get_button_number (event);
 | 
			
		||||
 | 
			
		||||
  switch (event->button)
 | 
			
		||||
  switch (action)
 | 
			
		||||
    {
 | 
			
		||||
    case 1:
 | 
			
		||||
    case META_ACTION_CLICK:
 | 
			
		||||
      return meta_frame_left_click_event (frame, event);
 | 
			
		||||
    case 2:
 | 
			
		||||
      return meta_frame_middle_click_event (frame, event);
 | 
			
		||||
    case 3:
 | 
			
		||||
      return meta_frame_right_click_event (frame, event);
 | 
			
		||||
    case META_ACTION_MIDDLE_CLICK:
 | 
			
		||||
      return meta_frame_middle_click_event (frame, (ClutterButtonEvent *) event);
 | 
			
		||||
    case META_ACTION_RIGHT_CLICK:
 | 
			
		||||
      return meta_frame_right_click_event (frame, (ClutterButtonEvent *) event);
 | 
			
		||||
    default:
 | 
			
		||||
      return FALSE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
handle_button_release_event (MetaUIFrame *frame,
 | 
			
		||||
                             ClutterButtonEvent *event)
 | 
			
		||||
handle_release_event (MetaUIFrame        *frame,
 | 
			
		||||
                      const ClutterEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  Display *display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 | 
			
		||||
  guint32 evtime, button;
 | 
			
		||||
  gfloat x, y;
 | 
			
		||||
 | 
			
		||||
  g_assert (event->type == CLUTTER_BUTTON_RELEASE ||
 | 
			
		||||
            event->type == CLUTTER_TOUCH_END);
 | 
			
		||||
 | 
			
		||||
  evtime = clutter_event_get_time (event);
 | 
			
		||||
  clutter_event_get_coords (event, &x, &y);
 | 
			
		||||
  button = get_button_number (event);
 | 
			
		||||
 | 
			
		||||
  frame->frames->current_grab_op = META_GRAB_OP_NONE;
 | 
			
		||||
  meta_core_end_grab_op (display, event->time);
 | 
			
		||||
  meta_core_end_grab_op (display, evtime);
 | 
			
		||||
 | 
			
		||||
  /* We only handle the releases we handled the presses for (things
 | 
			
		||||
   * involving frame controls). Window ops that don't require a
 | 
			
		||||
   * frame are handled in the Xlib part of the code, display.c/window.c
 | 
			
		||||
   */
 | 
			
		||||
  if (((int) event->button) == frame->grab_button &&
 | 
			
		||||
  if (((int) button) == frame->grab_button &&
 | 
			
		||||
      frame->button_state == META_BUTTON_STATE_PRESSED)
 | 
			
		||||
    {
 | 
			
		||||
      switch (frame->prelit_control)
 | 
			
		||||
@@ -1113,7 +1204,7 @@ handle_button_release_event (MetaUIFrame *frame,
 | 
			
		||||
          break;
 | 
			
		||||
        case META_FRAME_CONTROL_MAXIMIZE:
 | 
			
		||||
          /* Focus the window on the maximize */
 | 
			
		||||
          meta_window_focus (frame->meta_window, event->time);
 | 
			
		||||
          meta_window_focus (frame->meta_window, evtime);
 | 
			
		||||
          if (meta_prefs_get_raise_on_click ())
 | 
			
		||||
            meta_window_raise (frame->meta_window);
 | 
			
		||||
          meta_window_maximize (frame->meta_window, META_MAXIMIZE_BOTH);
 | 
			
		||||
@@ -1124,7 +1215,7 @@ handle_button_release_event (MetaUIFrame *frame,
 | 
			
		||||
          meta_window_unmaximize (frame->meta_window, META_MAXIMIZE_BOTH);
 | 
			
		||||
          break;
 | 
			
		||||
        case META_FRAME_CONTROL_DELETE:
 | 
			
		||||
          meta_window_delete (frame->meta_window, event->time);
 | 
			
		||||
          meta_window_delete (frame->meta_window, evtime);
 | 
			
		||||
          break;
 | 
			
		||||
        default:
 | 
			
		||||
          break;
 | 
			
		||||
@@ -1135,7 +1226,7 @@ handle_button_release_event (MetaUIFrame *frame,
 | 
			
		||||
       * prelit so to let the user know that it can now be pressed.
 | 
			
		||||
       * :)
 | 
			
		||||
       */
 | 
			
		||||
      MetaFrameControl control = get_control (frame, event->x, event->y);
 | 
			
		||||
      MetaFrameControl control = get_control (frame, x, y);
 | 
			
		||||
      meta_ui_frame_update_prelit_control (frame, control);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1236,13 +1327,22 @@ meta_ui_frame_update_prelit_control (MetaUIFrame     *frame,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
handle_motion_notify_event (MetaUIFrame *frame,
 | 
			
		||||
                            ClutterMotionEvent *event)
 | 
			
		||||
handle_motion_event (MetaUIFrame        *frame,
 | 
			
		||||
                     const ClutterEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  MetaFrames *frames = frame->frames;
 | 
			
		||||
  MetaFrameControl control;
 | 
			
		||||
  ClutterModifierType modifiers;
 | 
			
		||||
  guint32 evtime;
 | 
			
		||||
  gfloat x, y;
 | 
			
		||||
 | 
			
		||||
  control = get_control (frame, event->x, event->y);
 | 
			
		||||
  g_assert (event->type == CLUTTER_MOTION ||
 | 
			
		||||
            event->type == CLUTTER_TOUCH_UPDATE);
 | 
			
		||||
 | 
			
		||||
  modifiers = clutter_event_get_state (event);
 | 
			
		||||
  evtime = clutter_event_get_time (event);
 | 
			
		||||
  clutter_event_get_coords (event, &x, &y);
 | 
			
		||||
  control = get_control (frame, x, y);
 | 
			
		||||
 | 
			
		||||
  if (frame->button_state == META_BUTTON_STATE_PRESSED)
 | 
			
		||||
    {
 | 
			
		||||
@@ -1260,9 +1360,11 @@ handle_motion_notify_event (MetaUIFrame *frame,
 | 
			
		||||
      meta_ui_frame_update_prelit_control (frame, control);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if ((event->modifier_state & CLUTTER_BUTTON1_MASK) &&
 | 
			
		||||
      frames->current_grab_op != META_GRAB_OP_NONE)
 | 
			
		||||
    meta_frames_retry_grab_op (frames, event->time);
 | 
			
		||||
  if (frames->current_grab_op != META_GRAB_OP_NONE &&
 | 
			
		||||
      (event->type == CLUTTER_TOUCH_UPDATE ||
 | 
			
		||||
       (event->type == CLUTTER_MOTION &&
 | 
			
		||||
        (modifiers & CLUTTER_BUTTON1_MASK))))
 | 
			
		||||
    meta_frames_retry_grab_op (frames, evtime);
 | 
			
		||||
 | 
			
		||||
  return TRUE;
 | 
			
		||||
}
 | 
			
		||||
@@ -1330,7 +1432,9 @@ meta_ui_frame_get_mask (MetaUIFrame *frame,
 | 
			
		||||
  MetaFrameBorders borders;
 | 
			
		||||
  MetaFrameFlags flags;
 | 
			
		||||
  MetaRectangle frame_rect;
 | 
			
		||||
  int scale = meta_theme_get_window_scaling_factor ();
 | 
			
		||||
  cairo_surface_t *surface;
 | 
			
		||||
  double xscale, yscale;
 | 
			
		||||
  int scale;
 | 
			
		||||
 | 
			
		||||
  meta_window_get_frame_rect (frame->meta_window, &frame_rect);
 | 
			
		||||
 | 
			
		||||
@@ -1340,7 +1444,11 @@ meta_ui_frame_get_mask (MetaUIFrame *frame,
 | 
			
		||||
  meta_ui_frame_get_borders (frame, &borders);
 | 
			
		||||
 | 
			
		||||
  /* See comment in meta_frame_layout_draw_with_style() for details on HiDPI handling */
 | 
			
		||||
  cairo_scale (cr, scale, scale);
 | 
			
		||||
  scale = meta_theme_get_window_scaling_factor ();
 | 
			
		||||
  surface = cairo_get_target (cr);
 | 
			
		||||
  cairo_surface_get_device_scale (surface, &xscale, &yscale);
 | 
			
		||||
  cairo_surface_set_device_scale (surface, scale, scale);
 | 
			
		||||
 | 
			
		||||
  gtk_render_background (frame->style_info->styles[META_STYLE_ELEMENT_FRAME], cr,
 | 
			
		||||
                         borders.invisible.left / scale,
 | 
			
		||||
                         borders.invisible.top / scale,
 | 
			
		||||
@@ -1349,6 +1457,8 @@ meta_ui_frame_get_mask (MetaUIFrame *frame,
 | 
			
		||||
                         borders.invisible.left / scale,
 | 
			
		||||
                         borders.invisible.top / scale,
 | 
			
		||||
                         frame_rect.width / scale, borders.total.top / scale);
 | 
			
		||||
 | 
			
		||||
  cairo_surface_set_device_scale (surface, xscale, yscale);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* XXX -- this is disgusting. Find a better approach here.
 | 
			
		||||
@@ -1508,14 +1618,51 @@ gboolean
 | 
			
		||||
meta_ui_frame_handle_event (MetaUIFrame *frame,
 | 
			
		||||
                            const ClutterEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  if (event->type == CLUTTER_TOUCH_BEGIN ||
 | 
			
		||||
      event->type == CLUTTER_TOUCH_UPDATE ||
 | 
			
		||||
      event->type == CLUTTER_TOUCH_END)
 | 
			
		||||
    {
 | 
			
		||||
      ClutterEventSequence *sequence;
 | 
			
		||||
      MetaFrames *frames = frame->frames;
 | 
			
		||||
 | 
			
		||||
      /* In X11, mutter sets up passive touch grabs which basically
 | 
			
		||||
       * means we handle those events twice (once through the passive
 | 
			
		||||
       * grab, and then through XISelectEvents).
 | 
			
		||||
       *
 | 
			
		||||
       * Receiving touch events here means we are going through the
 | 
			
		||||
       * former, but passive grabs are exclusively for gesture
 | 
			
		||||
       * recognition purposes.
 | 
			
		||||
       *
 | 
			
		||||
       * We do actually want this to happen though the regular event
 | 
			
		||||
       * selection paths to avoid breaking internal state, which means
 | 
			
		||||
       * we will get pointer events, because we don't select for XI_Touch*.
 | 
			
		||||
       */
 | 
			
		||||
      if (!meta_is_wayland_compositor ())
 | 
			
		||||
        return FALSE;
 | 
			
		||||
 | 
			
		||||
      sequence = clutter_event_get_event_sequence (event);
 | 
			
		||||
 | 
			
		||||
      /* Lock onto a single touch */
 | 
			
		||||
      if (frames->grab_touch && frames->grab_touch != sequence)
 | 
			
		||||
        return FALSE;
 | 
			
		||||
 | 
			
		||||
      if (event->type == CLUTTER_TOUCH_BEGIN)
 | 
			
		||||
        frames->grab_touch = sequence;
 | 
			
		||||
      else if (event->type == CLUTTER_TOUCH_END)
 | 
			
		||||
        frames->grab_touch = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  switch (event->any.type)
 | 
			
		||||
    {
 | 
			
		||||
    case CLUTTER_BUTTON_PRESS:
 | 
			
		||||
      return handle_button_press_event (frame, (ClutterButtonEvent *) event);
 | 
			
		||||
    case CLUTTER_TOUCH_BEGIN:
 | 
			
		||||
      return handle_press_event (frame, event);
 | 
			
		||||
    case CLUTTER_BUTTON_RELEASE:
 | 
			
		||||
      return handle_button_release_event (frame, (ClutterButtonEvent *) event);
 | 
			
		||||
    case CLUTTER_TOUCH_END:
 | 
			
		||||
      return handle_release_event (frame, event);
 | 
			
		||||
    case CLUTTER_MOTION:
 | 
			
		||||
      return handle_motion_notify_event (frame, (ClutterMotionEvent *) event);
 | 
			
		||||
    case CLUTTER_TOUCH_UPDATE:
 | 
			
		||||
      return handle_motion_event (frame, event);
 | 
			
		||||
    case CLUTTER_ENTER:
 | 
			
		||||
      return handle_enter_notify_event (frame, (ClutterCrossingEvent *) event);
 | 
			
		||||
    case CLUTTER_LEAVE:
 | 
			
		||||
 
 | 
			
		||||
@@ -99,6 +99,8 @@ struct _MetaFrames
 | 
			
		||||
  guint grab_button;
 | 
			
		||||
  gdouble grab_x;
 | 
			
		||||
  gdouble grab_y;
 | 
			
		||||
 | 
			
		||||
  ClutterEventSequence *grab_touch;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _MetaFramesClass
 | 
			
		||||
 
 | 
			
		||||
@@ -580,7 +580,7 @@ meta_frame_layout_calc_geometry (MetaFrameLayout        *layout,
 | 
			
		||||
      x = rect->visible.x - layout->button_margin.left * scale;
 | 
			
		||||
 | 
			
		||||
      if (i > 0)
 | 
			
		||||
        x -= layout->titlebar_spacing;
 | 
			
		||||
        x -= layout->titlebar_spacing * scale;
 | 
			
		||||
 | 
			
		||||
      --i;
 | 
			
		||||
    }
 | 
			
		||||
@@ -712,6 +712,8 @@ get_class_from_button_type (MetaButtonType type)
 | 
			
		||||
      return "maximize";
 | 
			
		||||
    case META_BUTTON_TYPE_MINIMIZE:
 | 
			
		||||
      return "minimize";
 | 
			
		||||
    case META_BUTTON_TYPE_APPMENU:
 | 
			
		||||
      return "appmenu";
 | 
			
		||||
    default:
 | 
			
		||||
      return NULL;
 | 
			
		||||
    }
 | 
			
		||||
@@ -734,7 +736,9 @@ meta_frame_layout_draw_with_style (MetaFrameLayout         *layout,
 | 
			
		||||
  GdkRectangle titlebar_rect;
 | 
			
		||||
  GdkRectangle button_rect;
 | 
			
		||||
  const MetaFrameBorders *borders;
 | 
			
		||||
  int scale = meta_theme_get_window_scaling_factor ();
 | 
			
		||||
  cairo_surface_t *frame_surface;
 | 
			
		||||
  double xscale, yscale;
 | 
			
		||||
  int scale;
 | 
			
		||||
 | 
			
		||||
  /* We opt out of GTK+/Clutter's HiDPI handling, so we have to do the scaling
 | 
			
		||||
   * ourselves; the nitty-gritty is a bit confusing, so here is an overview:
 | 
			
		||||
@@ -746,8 +750,14 @@ meta_frame_layout_draw_with_style (MetaFrameLayout         *layout,
 | 
			
		||||
   *  - for drawing, we scale the canvas to have GTK+ render elements (borders,
 | 
			
		||||
   *    radii, ...) at the correct scale - as a result, we have to "unscale"
 | 
			
		||||
   *    the geometry again to not apply the scaling twice
 | 
			
		||||
   *  - As per commit e36b629c GTK expects the device scale to be set and match
 | 
			
		||||
   *    the final scaling or the surface caching won't take this in account
 | 
			
		||||
   *    breaking -gtk-scaled items.
 | 
			
		||||
   */
 | 
			
		||||
  cairo_scale (cr, scale, scale);
 | 
			
		||||
  scale = meta_theme_get_window_scaling_factor ();
 | 
			
		||||
  frame_surface = cairo_get_target (cr);
 | 
			
		||||
  cairo_surface_get_device_scale (frame_surface, &xscale, &yscale);
 | 
			
		||||
  cairo_surface_set_device_scale (frame_surface, scale, scale);
 | 
			
		||||
 | 
			
		||||
  borders = &fgeom->borders;
 | 
			
		||||
 | 
			
		||||
@@ -903,6 +913,8 @@ meta_frame_layout_draw_with_style (MetaFrameLayout         *layout,
 | 
			
		||||
        gtk_style_context_remove_class (style, button_class);
 | 
			
		||||
      gtk_style_context_set_state (style, state);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  cairo_surface_set_device_scale (frame_surface, xscale, yscale);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 
 | 
			
		||||
@@ -600,6 +600,10 @@ meta_wayland_zxdg_toplevel_v6_commit (MetaWaylandSurfaceRole  *surface_role,
 | 
			
		||||
    meta_wayland_surface_role_get_surface (surface_role);
 | 
			
		||||
  MetaWindow *window = surface->window;
 | 
			
		||||
  MetaRectangle window_geometry;
 | 
			
		||||
  MetaRectangle old_geometry;
 | 
			
		||||
  gboolean geometry_changed;
 | 
			
		||||
 | 
			
		||||
  old_geometry = xdg_surface_priv->geometry;
 | 
			
		||||
 | 
			
		||||
  surface_role_class =
 | 
			
		||||
    META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_zxdg_toplevel_v6_parent_class);
 | 
			
		||||
@@ -618,7 +622,9 @@ meta_wayland_zxdg_toplevel_v6_commit (MetaWaylandSurfaceRole  *surface_role,
 | 
			
		||||
  if (!window)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  if (pending->has_new_geometry)
 | 
			
		||||
  geometry_changed = !meta_rectangle_equal (&old_geometry, &xdg_surface_priv->geometry);
 | 
			
		||||
 | 
			
		||||
  if (geometry_changed || meta_window_wayland_needs_move_resize (window))
 | 
			
		||||
    {
 | 
			
		||||
      window_geometry =
 | 
			
		||||
        meta_wayland_zxdg_surface_v6_get_window_geometry (xdg_surface);
 | 
			
		||||
 
 | 
			
		||||
@@ -325,7 +325,8 @@ void
 | 
			
		||||
meta_wayland_seat_update (MetaWaylandSeat    *seat,
 | 
			
		||||
                          const ClutterEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  if (!event_from_supported_hardware_device (seat, event) &&
 | 
			
		||||
  if (!(clutter_event_get_flags (event) & CLUTTER_EVENT_FLAG_INPUT_METHOD) &&
 | 
			
		||||
      !event_from_supported_hardware_device (seat, event) &&
 | 
			
		||||
      !event_is_synthesized_crossing (event))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
@@ -363,7 +364,8 @@ gboolean
 | 
			
		||||
meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
 | 
			
		||||
                                const ClutterEvent *event)
 | 
			
		||||
{
 | 
			
		||||
  if (!event_from_supported_hardware_device (seat, event))
 | 
			
		||||
  if (!(clutter_event_get_flags (event) & CLUTTER_EVENT_FLAG_INPUT_METHOD) &&
 | 
			
		||||
      !event_from_supported_hardware_device (seat, event))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  switch (event->type)
 | 
			
		||||
 
 | 
			
		||||
@@ -195,14 +195,15 @@ cursor_surface_role_is_on_logical_monitor (MetaWaylandSurfaceRole *role,
 | 
			
		||||
    META_WAYLAND_SURFACE_ROLE_CURSOR (surface->role);
 | 
			
		||||
  MetaWaylandSurfaceRoleCursorPrivate *priv =
 | 
			
		||||
    meta_wayland_surface_role_cursor_get_instance_private (cursor_role);
 | 
			
		||||
  ClutterRect rect;
 | 
			
		||||
  ClutterPoint point;
 | 
			
		||||
  ClutterRect logical_monitor_rect;
 | 
			
		||||
 | 
			
		||||
  rect = meta_cursor_renderer_calculate_rect (priv->cursor_renderer,
 | 
			
		||||
                                              priv->cursor_sprite);
 | 
			
		||||
  logical_monitor_rect =
 | 
			
		||||
    meta_rectangle_to_clutter_rect (&logical_monitor->rect);
 | 
			
		||||
  return clutter_rect_intersection (&rect, &logical_monitor_rect, NULL);
 | 
			
		||||
 | 
			
		||||
  point = meta_cursor_renderer_get_position (priv->cursor_renderer);
 | 
			
		||||
 | 
			
		||||
  return clutter_rect_contains_point (&logical_monitor_rect, &point);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
 
 | 
			
		||||
@@ -54,6 +54,7 @@
 | 
			
		||||
 | 
			
		||||
#include "compositor/region-utils.h"
 | 
			
		||||
#include "compositor/meta-shaped-texture-private.h"
 | 
			
		||||
#include "compositor/meta-window-actor-private.h"
 | 
			
		||||
 | 
			
		||||
#include "meta-surface-actor.h"
 | 
			
		||||
#include "meta-surface-actor-wayland.h"
 | 
			
		||||
@@ -142,6 +143,9 @@ surface_actor_position_notify (MetaSurfaceActorWayland *surface_actor,
 | 
			
		||||
static void
 | 
			
		||||
window_position_changed (MetaWindow         *window,
 | 
			
		||||
                         MetaWaylandSurface *surface);
 | 
			
		||||
static void
 | 
			
		||||
window_actor_effects_completed (MetaWindowActor    *window_actor,
 | 
			
		||||
                                MetaWaylandSurface *surface);
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
role_assignment_valist_to_properties (GType       role_type,
 | 
			
		||||
@@ -392,6 +396,7 @@ pending_state_init (MetaWaylandPendingState *state)
 | 
			
		||||
{
 | 
			
		||||
  state->newly_attached = FALSE;
 | 
			
		||||
  state->buffer = NULL;
 | 
			
		||||
  state->buffer_destroy_handler_id = 0;
 | 
			
		||||
  state->dx = 0;
 | 
			
		||||
  state->dy = 0;
 | 
			
		||||
  state->scale = 0;
 | 
			
		||||
@@ -421,8 +426,11 @@ pending_state_destroy (MetaWaylandPendingState *state)
 | 
			
		||||
  g_clear_pointer (&state->opaque_region, cairo_region_destroy);
 | 
			
		||||
 | 
			
		||||
  if (state->buffer)
 | 
			
		||||
    g_signal_handler_disconnect (state->buffer,
 | 
			
		||||
                                 state->buffer_destroy_handler_id);
 | 
			
		||||
    {
 | 
			
		||||
      g_signal_handler_disconnect (state->buffer,
 | 
			
		||||
                                   state->buffer_destroy_handler_id);
 | 
			
		||||
      state->buffer_destroy_handler_id = 0;
 | 
			
		||||
    }
 | 
			
		||||
  wl_list_for_each_safe (cb, next, &state->frame_callback_list, link)
 | 
			
		||||
    wl_resource_destroy (cb->resource);
 | 
			
		||||
}
 | 
			
		||||
@@ -435,36 +443,84 @@ pending_state_reset (MetaWaylandPendingState *state)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
move_pending_state (MetaWaylandPendingState *from,
 | 
			
		||||
                    MetaWaylandPendingState *to)
 | 
			
		||||
merge_pending_state (MetaWaylandPendingState *from,
 | 
			
		||||
                     MetaWaylandPendingState *to)
 | 
			
		||||
{
 | 
			
		||||
  if (from->buffer)
 | 
			
		||||
    g_signal_handler_disconnect (from->buffer, from->buffer_destroy_handler_id);
 | 
			
		||||
  if (from->newly_attached)
 | 
			
		||||
    {
 | 
			
		||||
      if (to->buffer)
 | 
			
		||||
        {
 | 
			
		||||
          g_signal_handler_disconnect (to->buffer,
 | 
			
		||||
                                       to->buffer_destroy_handler_id);
 | 
			
		||||
          to->buffer_destroy_handler_id = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
  to->newly_attached = from->newly_attached;
 | 
			
		||||
  to->buffer = from->buffer;
 | 
			
		||||
  to->dx = from->dx;
 | 
			
		||||
  to->dy = from->dy;
 | 
			
		||||
  to->scale = from->scale;
 | 
			
		||||
  to->surface_damage = from->surface_damage;
 | 
			
		||||
  to->buffer_damage = from->buffer_damage;
 | 
			
		||||
  to->input_region = from->input_region;
 | 
			
		||||
  to->input_region_set = from->input_region_set;
 | 
			
		||||
  to->opaque_region = from->opaque_region;
 | 
			
		||||
  to->opaque_region_set = from->opaque_region_set;
 | 
			
		||||
  to->new_geometry = from->new_geometry;
 | 
			
		||||
  to->has_new_geometry = from->has_new_geometry;
 | 
			
		||||
  to->has_new_min_size = from->has_new_min_size;
 | 
			
		||||
  to->new_min_width = from->new_min_width;
 | 
			
		||||
  to->new_min_height = from->new_min_height;
 | 
			
		||||
  to->has_new_max_size = from->has_new_max_size;
 | 
			
		||||
  to->new_max_width = from->new_max_width;
 | 
			
		||||
  to->new_max_height = from->new_max_height;
 | 
			
		||||
      if (from->buffer)
 | 
			
		||||
        {
 | 
			
		||||
          g_signal_handler_disconnect (from->buffer,
 | 
			
		||||
                                       from->buffer_destroy_handler_id);
 | 
			
		||||
          from->buffer_destroy_handler_id = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      to->newly_attached = TRUE;
 | 
			
		||||
      to->buffer = from->buffer;
 | 
			
		||||
      to->dx = from->dx;
 | 
			
		||||
      to->dy = from->dy;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  wl_list_init (&to->frame_callback_list);
 | 
			
		||||
  wl_list_insert_list (&to->frame_callback_list, &from->frame_callback_list);
 | 
			
		||||
 | 
			
		||||
  if (to->buffer)
 | 
			
		||||
  cairo_region_union (to->surface_damage, from->surface_damage);
 | 
			
		||||
  cairo_region_union (to->buffer_damage, from->buffer_damage);
 | 
			
		||||
  cairo_region_destroy (from->surface_damage);
 | 
			
		||||
  cairo_region_destroy (from->buffer_damage);
 | 
			
		||||
 | 
			
		||||
  if (from->input_region_set)
 | 
			
		||||
    {
 | 
			
		||||
      if (to->input_region)
 | 
			
		||||
        cairo_region_union (to->input_region, from->input_region);
 | 
			
		||||
      else
 | 
			
		||||
        to->input_region = cairo_region_reference (from->input_region);
 | 
			
		||||
 | 
			
		||||
      to->input_region_set = TRUE;
 | 
			
		||||
      cairo_region_destroy (from->input_region);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (from->opaque_region_set)
 | 
			
		||||
    {
 | 
			
		||||
      if (to->opaque_region)
 | 
			
		||||
        cairo_region_union (to->opaque_region, from->opaque_region);
 | 
			
		||||
      else
 | 
			
		||||
        to->opaque_region = cairo_region_reference (from->opaque_region);
 | 
			
		||||
 | 
			
		||||
      to->opaque_region_set = TRUE;
 | 
			
		||||
      cairo_region_destroy (from->opaque_region);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (from->has_new_geometry)
 | 
			
		||||
    {
 | 
			
		||||
      to->new_geometry = from->new_geometry;
 | 
			
		||||
      to->has_new_geometry = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (from->has_new_min_size)
 | 
			
		||||
    {
 | 
			
		||||
      to->new_min_width = from->new_min_width;
 | 
			
		||||
      to->new_min_height = from->new_min_height;
 | 
			
		||||
      to->has_new_min_size = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (from->has_new_max_size)
 | 
			
		||||
    {
 | 
			
		||||
      to->new_max_width = from->new_max_width;
 | 
			
		||||
      to->new_max_height = from->new_max_height;
 | 
			
		||||
      to->has_new_max_size = TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (from->scale > 0)
 | 
			
		||||
    to->scale = from->scale;
 | 
			
		||||
 | 
			
		||||
  if (to->buffer && to->buffer_destroy_handler_id == 0)
 | 
			
		||||
    {
 | 
			
		||||
      to->buffer_destroy_handler_id =
 | 
			
		||||
        g_signal_connect (to->buffer, "resource-destroyed",
 | 
			
		||||
@@ -528,7 +584,10 @@ meta_wayland_surface_is_effectively_synchronized (MetaWaylandSurface *surface)
 | 
			
		||||
        {
 | 
			
		||||
          MetaWaylandSurface *parent = surface->sub.parent;
 | 
			
		||||
 | 
			
		||||
          return meta_wayland_surface_is_effectively_synchronized (parent);
 | 
			
		||||
          if (parent)
 | 
			
		||||
            return meta_wayland_surface_is_effectively_synchronized (parent);
 | 
			
		||||
 | 
			
		||||
          return TRUE;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -712,7 +771,7 @@ meta_wayland_surface_commit (MetaWaylandSurface *surface)
 | 
			
		||||
   *     surface is in effective desynchronized mode.
 | 
			
		||||
   */
 | 
			
		||||
  if (meta_wayland_surface_is_effectively_synchronized (surface))
 | 
			
		||||
    move_pending_state (surface->pending, surface->sub.pending);
 | 
			
		||||
    merge_pending_state (surface->pending, surface->sub.pending);
 | 
			
		||||
  else
 | 
			
		||||
    meta_wayland_surface_apply_pending_state (surface, surface->pending);
 | 
			
		||||
}
 | 
			
		||||
@@ -1083,6 +1142,9 @@ meta_wayland_surface_set_window (MetaWaylandSurface *surface,
 | 
			
		||||
      g_signal_handlers_disconnect_by_func (surface->window,
 | 
			
		||||
                                            window_position_changed,
 | 
			
		||||
                                            surface);
 | 
			
		||||
      g_signal_handlers_disconnect_by_func (meta_window_actor_from_window (surface->window),
 | 
			
		||||
                                            window_actor_effects_completed,
 | 
			
		||||
                                            surface);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  surface->window = window;
 | 
			
		||||
@@ -1099,6 +1161,10 @@ meta_wayland_surface_set_window (MetaWaylandSurface *surface,
 | 
			
		||||
                               "position-changed",
 | 
			
		||||
                               G_CALLBACK (window_position_changed),
 | 
			
		||||
                               surface, 0);
 | 
			
		||||
      g_signal_connect_object (meta_window_actor_from_window (window),
 | 
			
		||||
                               "effects-completed",
 | 
			
		||||
                               G_CALLBACK (window_actor_effects_completed),
 | 
			
		||||
                               surface, 0);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1200,6 +1266,13 @@ window_position_changed (MetaWindow         *window,
 | 
			
		||||
  meta_wayland_surface_update_outputs_recursively (surface);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
window_actor_effects_completed (MetaWindowActor    *window_actor,
 | 
			
		||||
                                MetaWaylandSurface *surface)
 | 
			
		||||
{
 | 
			
		||||
  meta_wayland_surface_update_outputs_recursively (surface);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
meta_wayland_surface_create_surface_actor (MetaWaylandSurface *surface)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -120,8 +120,6 @@ meta_wayland_text_input_focus_commit_text (ClutterInputFocus *focus,
 | 
			
		||||
      gtk_text_input_send_preedit_string (resource, NULL, 0);
 | 
			
		||||
      gtk_text_input_send_commit_string (resource, text);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  clutter_input_focus_reset (focus);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
 
 | 
			
		||||
@@ -252,10 +252,8 @@ is_valid_child (MetaWaylandSurface *surface)
 | 
			
		||||
  if (!surface->role)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  if (!META_IS_WAYLAND_XDG_SURFACE (surface->role))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  if (!META_IS_WAYLAND_ZXDG_SURFACE_V6 (surface->role))
 | 
			
		||||
  if (!META_IS_WAYLAND_XDG_TOPLEVEL (surface->role) &&
 | 
			
		||||
      !META_IS_WAYLAND_ZXDG_TOPLEVEL_V6 (surface->role))
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  if (!surface->window)
 | 
			
		||||
@@ -384,7 +382,7 @@ xdg_importer_import (struct wl_client   *client,
 | 
			
		||||
      (!META_IS_WAYLAND_XDG_SURFACE (exported->surface->role) &&
 | 
			
		||||
       !META_IS_WAYLAND_ZXDG_SURFACE_V6 (exported->surface->role)))
 | 
			
		||||
    {
 | 
			
		||||
      zxdg_imported_v1_send_destroyed (resource);
 | 
			
		||||
      zxdg_imported_v1_send_destroyed (xdg_imported_resource);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -621,6 +621,8 @@ meta_wayland_xdg_toplevel_commit (MetaWaylandSurfaceRole  *surface_role,
 | 
			
		||||
    meta_wayland_surface_role_get_surface (surface_role);
 | 
			
		||||
  MetaWindow *window;
 | 
			
		||||
  MetaRectangle window_geometry;
 | 
			
		||||
  MetaRectangle old_geometry;
 | 
			
		||||
  gboolean geometry_changed;
 | 
			
		||||
 | 
			
		||||
  if (!surface->buffer_ref.buffer && xdg_surface_priv->first_buffer_attached)
 | 
			
		||||
    {
 | 
			
		||||
@@ -629,6 +631,7 @@ meta_wayland_xdg_toplevel_commit (MetaWaylandSurfaceRole  *surface_role,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  window = surface->window;
 | 
			
		||||
  old_geometry = xdg_surface_priv->geometry;
 | 
			
		||||
 | 
			
		||||
  surface_role_class =
 | 
			
		||||
    META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_xdg_toplevel_parent_class);
 | 
			
		||||
@@ -643,7 +646,9 @@ meta_wayland_xdg_toplevel_commit (MetaWaylandSurfaceRole  *surface_role,
 | 
			
		||||
  if (!pending->newly_attached)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  if (pending->has_new_geometry)
 | 
			
		||||
  geometry_changed = !meta_rectangle_equal (&old_geometry, &xdg_surface_priv->geometry);
 | 
			
		||||
 | 
			
		||||
  if (geometry_changed || meta_window_wayland_needs_move_resize (window))
 | 
			
		||||
    {
 | 
			
		||||
      window_geometry = meta_wayland_xdg_surface_get_window_geometry (xdg_surface);
 | 
			
		||||
      meta_window_wayland_move_resize (window,
 | 
			
		||||
 
 | 
			
		||||
@@ -48,6 +48,7 @@ struct _MetaWindowWayland
 | 
			
		||||
  int geometry_scale;
 | 
			
		||||
 | 
			
		||||
  MetaWaylandSerial pending_configure_serial;
 | 
			
		||||
  gboolean has_pending_state_change;
 | 
			
		||||
  gboolean has_pending_move;
 | 
			
		||||
  int pending_move_x;
 | 
			
		||||
  int pending_move_y;
 | 
			
		||||
@@ -324,6 +325,9 @@ meta_window_wayland_move_resize_internal (MetaWindow                *window,
 | 
			
		||||
          window->buffer_rect.x = new_buffer_x;
 | 
			
		||||
          window->buffer_rect.y = new_buffer_y;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (flags & META_MOVE_RESIZE_WAYLAND_STATE_CHANGED)
 | 
			
		||||
        *result |= META_MOVE_RESIZE_RESULT_STATE_CHANGED;
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
@@ -336,6 +340,8 @@ meta_window_wayland_move_resize_internal (MetaWindow                *window,
 | 
			
		||||
          wl_window->pending_move_x = new_x;
 | 
			
		||||
          wl_window->pending_move_y = new_y;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      wl_window->has_pending_state_change = (flags & META_MOVE_RESIZE_STATE_CHANGED) != 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -629,12 +635,9 @@ meta_window_wayland_new (MetaDisplay        *display,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
should_do_pending_move (MetaWindowWayland *wl_window,
 | 
			
		||||
                        MetaWaylandSerial *acked_configure_serial)
 | 
			
		||||
is_pending_ack_configure (MetaWindowWayland *wl_window,
 | 
			
		||||
                          MetaWaylandSerial *acked_configure_serial)
 | 
			
		||||
{
 | 
			
		||||
  if (!wl_window->has_pending_move)
 | 
			
		||||
    return FALSE;
 | 
			
		||||
 | 
			
		||||
  if (wl_window->pending_configure_serial.set)
 | 
			
		||||
    {
 | 
			
		||||
      /* If we're waiting for a configure and this isn't an ACK for
 | 
			
		||||
@@ -677,6 +680,7 @@ meta_window_wayland_move_resize (MetaWindow        *window,
 | 
			
		||||
  int gravity;
 | 
			
		||||
  MetaRectangle rect;
 | 
			
		||||
  MetaMoveResizeFlags flags;
 | 
			
		||||
  gboolean pending_ack_configure;
 | 
			
		||||
 | 
			
		||||
  /* new_geom is in the logical pixel coordinate space, but MetaWindow wants its
 | 
			
		||||
   * rects to represent what in turn will end up on the stage, i.e. we need to
 | 
			
		||||
@@ -700,10 +704,12 @@ meta_window_wayland_move_resize (MetaWindow        *window,
 | 
			
		||||
 | 
			
		||||
  flags = META_MOVE_RESIZE_WAYLAND_RESIZE;
 | 
			
		||||
 | 
			
		||||
  pending_ack_configure = is_pending_ack_configure (wl_window, acked_configure_serial);
 | 
			
		||||
 | 
			
		||||
  /* x/y are ignored when we're doing interactive resizing */
 | 
			
		||||
  if (!meta_grab_op_is_resizing (window->display->grab_op))
 | 
			
		||||
    {
 | 
			
		||||
      if (wl_window->has_pending_move && should_do_pending_move (wl_window, acked_configure_serial))
 | 
			
		||||
      if (wl_window->has_pending_move && pending_ack_configure)
 | 
			
		||||
        {
 | 
			
		||||
          rect.x = wl_window->pending_move_x;
 | 
			
		||||
          rect.y = wl_window->pending_move_y;
 | 
			
		||||
@@ -724,6 +730,12 @@ meta_window_wayland_move_resize (MetaWindow        *window,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (wl_window->has_pending_state_change && pending_ack_configure)
 | 
			
		||||
    {
 | 
			
		||||
      flags |= META_MOVE_RESIZE_WAYLAND_STATE_CHANGED;
 | 
			
		||||
      wl_window->has_pending_state_change = FALSE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  wl_window->pending_configure_serial.set = FALSE;
 | 
			
		||||
 | 
			
		||||
  rect.width = new_geom.width;
 | 
			
		||||
@@ -903,3 +915,10 @@ meta_window_wayland_get_max_size (MetaWindow *window,
 | 
			
		||||
  scale_size (width, height, scale);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
meta_window_wayland_needs_move_resize (MetaWindow *window)
 | 
			
		||||
{
 | 
			
		||||
  MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window);
 | 
			
		||||
 | 
			
		||||
  return wl_window->has_pending_state_change || wl_window->has_pending_move;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -78,5 +78,6 @@ void meta_window_wayland_get_max_size (MetaWindow *window,
 | 
			
		||||
                                       int        *width,
 | 
			
		||||
                                       int        *height);
 | 
			
		||||
 | 
			
		||||
gboolean meta_window_wayland_needs_move_resize (MetaWindow *window);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,8 @@
 | 
			
		||||
#include "meta-xwayland.h"
 | 
			
		||||
#include "meta-xwayland-private.h"
 | 
			
		||||
 | 
			
		||||
#include <meta/main.h>
 | 
			
		||||
 | 
			
		||||
#include <glib.h>
 | 
			
		||||
#include <glib-unix.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
@@ -393,30 +395,34 @@ xserver_died (GObject      *source,
 | 
			
		||||
              gpointer      user_data)
 | 
			
		||||
{
 | 
			
		||||
  GSubprocess *proc = G_SUBPROCESS (source);
 | 
			
		||||
  GError *error = NULL;
 | 
			
		||||
  g_autoptr (GError) error = NULL;
 | 
			
		||||
 | 
			
		||||
  if (!g_subprocess_wait_finish (proc, result, &error))
 | 
			
		||||
    {
 | 
			
		||||
      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
 | 
			
		||||
        g_error ("Failed to finish waiting for Xwayland: %s", error->message);
 | 
			
		||||
      g_clear_error (&error);
 | 
			
		||||
      if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
      g_warning ("Failed to finish waiting for Xwayland: %s", error->message);
 | 
			
		||||
    }
 | 
			
		||||
  else if (!g_subprocess_get_successful (proc))
 | 
			
		||||
    g_error ("X Wayland crashed; aborting");
 | 
			
		||||
    g_warning ("X Wayland crashed; exiting");
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      /* For now we simply abort if we see the server exit.
 | 
			
		||||
       *
 | 
			
		||||
       * In the future X will only be loaded lazily for legacy X support
 | 
			
		||||
       * but for now it's a hard requirement. */
 | 
			
		||||
      g_error ("Spurious exit of X Wayland server");
 | 
			
		||||
      g_warning ("Spurious exit of X Wayland server");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  meta_exit (META_EXIT_ERROR);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
x_io_error (Display *display)
 | 
			
		||||
{
 | 
			
		||||
  g_error ("Connection to xwayland lost");
 | 
			
		||||
  g_warning ("Connection to xwayland lost");
 | 
			
		||||
  meta_exit (META_EXIT_ERROR);
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1282,6 +1282,8 @@ meta_window_x11_move_resize_internal (MetaWindow                *window,
 | 
			
		||||
    *result |= META_MOVE_RESIZE_RESULT_MOVED;
 | 
			
		||||
  if (need_resize_client || need_resize_frame)
 | 
			
		||||
    *result |= META_MOVE_RESIZE_RESULT_RESIZED;
 | 
			
		||||
  if (flags & META_MOVE_RESIZE_STATE_CHANGED)
 | 
			
		||||
    *result |= META_MOVE_RESIZE_RESULT_STATE_CHANGED;
 | 
			
		||||
 | 
			
		||||
  update_gtk_edge_constraints (window);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user