[mutter] wayland: Send wl_surface.enter and wl_surface.leave
- From: Jonas Ådahl <jadahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] wayland: Send wl_surface.enter and wl_surface.leave
- Date: Wed, 15 Jul 2015 07:02:34 +0000 (UTC)
commit eb023ff2c9dc7dd92e3a7c232995083e6bdcbb48
Author: Jonas Ådahl <jadahl gmail com>
Date: Tue Feb 3 15:49:52 2015 +0800
wayland: Send wl_surface.enter and wl_surface.leave
Whenever a MetaSurfaceActor is painted, update the list of what outputs
the surface is being drawed upon. Since we do this on paint, we
effectively avoids this whenever the surface is not drawn, for example
being minimized, on a non-active workspace, or simply outside of the
damage region of a frame.
DND icons and cursors are not affected by this patch, since they are not
drawn as MetaSurfaceActors. If a MetaSurfaceActor or a parent is cloned,
then we'll check the position of the original actor again when the clone is
drawn, which is slightly expensive, but harmless. If the MetaShapedTexture
instead is cloned, as GNOME Shell does in many cases, then these clones
will not cause duplicate position checks.
https://bugzilla.gnome.org/show_bug.cgi?id=744453
src/compositor/meta-surface-actor-wayland.c | 49 ++++++++++++
src/compositor/meta-surface-actor-wayland.h | 5 +
src/wayland/meta-wayland-outputs.c | 16 ++++
src/wayland/meta-wayland-outputs.h | 1 -
src/wayland/meta-wayland-surface.c | 113 +++++++++++++++++++++++++++
src/wayland/meta-wayland-surface.h | 3 +
src/wayland/meta-wayland-types.h | 2 +
7 files changed, 188 insertions(+), 1 deletions(-)
---
diff --git a/src/compositor/meta-surface-actor-wayland.c b/src/compositor/meta-surface-actor-wayland.c
index 67bc42e..865e041 100644
--- a/src/compositor/meta-surface-actor-wayland.c
+++ b/src/compositor/meta-surface-actor-wayland.c
@@ -26,6 +26,7 @@
#include "meta-surface-actor-wayland.h"
+#include <math.h>
#include <cogl/cogl-wayland-server.h>
#include "meta-shaped-texture-private.h"
@@ -195,6 +196,40 @@ meta_surface_actor_wayland_sync_state_recursive (MetaSurfaceActorWayland *self)
}
}
+gboolean
+meta_surface_actor_wayland_is_on_monitor (MetaSurfaceActorWayland *self,
+ MetaMonitorInfo *monitor)
+{
+ float x, y, width, height;
+ cairo_rectangle_int_t actor_rect;
+ cairo_region_t *region;
+ gboolean is_on_monitor;
+
+ clutter_actor_get_transformed_position (CLUTTER_ACTOR (self), &x, &y);
+ clutter_actor_get_transformed_size (CLUTTER_ACTOR (self), &width, &height);
+
+ actor_rect.x = (int)roundf (x);
+ actor_rect.y = (int)roundf (y);
+ actor_rect.width = (int)roundf (x + width) - actor_rect.x;
+ actor_rect.height = (int)roundf (y + height) - actor_rect.y;
+
+ /* Calculate the scaled surface actor region. */
+ region = cairo_region_create_rectangle (&actor_rect);
+
+ cairo_region_intersect_rectangle (region,
+ &((cairo_rectangle_int_t) {
+ .x = monitor->rect.x,
+ .y = monitor->rect.y,
+ .width = monitor->rect.width,
+ .height = monitor->rect.height,
+ }));
+
+ is_on_monitor = !cairo_region_is_empty (region);
+ cairo_region_destroy (region);
+
+ return is_on_monitor;
+}
+
static MetaWindow *
meta_surface_actor_wayland_get_window (MetaSurfaceActor *actor)
{
@@ -240,6 +275,19 @@ meta_surface_actor_wayland_get_preferred_height (ClutterActor *self,
}
static void
+meta_surface_actor_wayland_paint (ClutterActor *actor)
+{
+ MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor);
+ MetaSurfaceActorWaylandPrivate *priv =
+ meta_surface_actor_wayland_get_instance_private (self);
+
+ if (priv->surface)
+ meta_wayland_surface_update_outputs (priv->surface);
+
+ CLUTTER_ACTOR_CLASS (meta_surface_actor_wayland_parent_class)->paint (actor);
+}
+
+static void
meta_surface_actor_wayland_dispose (GObject *object)
{
MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (object);
@@ -258,6 +306,7 @@ meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
actor_class->get_preferred_width = meta_surface_actor_wayland_get_preferred_width;
actor_class->get_preferred_height = meta_surface_actor_wayland_get_preferred_height;
+ actor_class->paint = meta_surface_actor_wayland_paint;
surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage;
surface_actor_class->pre_paint = meta_surface_actor_wayland_pre_paint;
diff --git a/src/compositor/meta-surface-actor-wayland.h b/src/compositor/meta-surface-actor-wayland.h
index 7071cdb..443bacc 100644
--- a/src/compositor/meta-surface-actor-wayland.h
+++ b/src/compositor/meta-surface-actor-wayland.h
@@ -31,6 +31,8 @@
#include "wayland/meta-wayland.h"
+#include "backends/meta-monitor-manager-private.h"
+
G_BEGIN_DECLS
#define META_TYPE_SURFACE_ACTOR_WAYLAND (meta_surface_actor_wayland_get_type ())
@@ -68,6 +70,9 @@ void meta_surface_actor_wayland_sync_state (MetaSurfaceActorWayland *self);
void meta_surface_actor_wayland_sync_state_recursive (MetaSurfaceActorWayland *self);
+gboolean meta_surface_actor_wayland_is_on_monitor (MetaSurfaceActorWayland *self,
+ MetaMonitorInfo *monitor);
+
G_END_DECLS
#endif /* __META_SURFACE_ACTOR_WAYLAND_H__ */
diff --git a/src/wayland/meta-wayland-outputs.c b/src/wayland/meta-wayland-outputs.c
index 6c59303..bdd1c68 100644
--- a/src/wayland/meta-wayland-outputs.c
+++ b/src/wayland/meta-wayland-outputs.c
@@ -31,6 +31,14 @@
#include <string.h>
+enum {
+ OUTPUT_DESTROYED,
+
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
G_DEFINE_TYPE (MetaWaylandOutput, meta_wayland_output, G_TYPE_OBJECT)
static void
@@ -102,6 +110,7 @@ wayland_output_destroy_notify (gpointer data)
{
MetaWaylandOutput *wayland_output = data;
+ g_signal_emit (wayland_output, signals[OUTPUT_DESTROYED], 0);
g_object_unref (wayland_output);
}
@@ -243,6 +252,13 @@ meta_wayland_output_class_init (MetaWaylandOutputClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_wayland_output_finalize;
+
+ signals[OUTPUT_DESTROYED] = g_signal_new ("output-destroyed",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
}
void
diff --git a/src/wayland/meta-wayland-outputs.h b/src/wayland/meta-wayland-outputs.h
index 94a739d..2c0f28d 100644
--- a/src/wayland/meta-wayland-outputs.h
+++ b/src/wayland/meta-wayland-outputs.h
@@ -35,7 +35,6 @@
#define META_IS_WAYLAND_OUTPUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_WAYLAND_OUTPUT))
#define META_WAYLAND_OUTPUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_WAYLAND_OUTPUT,
MetaWaylandOutputClass))
-typedef struct _MetaWaylandOutput MetaWaylandOutput;
typedef struct _MetaWaylandOutputClass MetaWaylandOutputClass;
struct _MetaWaylandOutput
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index 565d061..2817ba6 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -42,6 +42,7 @@
#include "meta-wayland-pointer.h"
#include "meta-wayland-popup.h"
#include "meta-wayland-data-device.h"
+#include "meta-wayland-outputs.h"
#include "meta-cursor-tracker-private.h"
#include "display-private.h"
@@ -773,6 +774,114 @@ sync_drag_dest_funcs (MetaWaylandSurface *surface)
surface->dnd.funcs = meta_wayland_data_device_get_drag_dest_funcs ();
}
+static void
+surface_entered_output (MetaWaylandSurface *surface,
+ MetaWaylandOutput *wayland_output)
+{
+ GList *iter;
+ struct wl_resource *resource;
+
+ for (iter = wayland_output->resources; iter != NULL; iter = iter->next)
+ {
+ resource = iter->data;
+
+ if (wl_resource_get_client (resource) !=
+ wl_resource_get_client (surface->resource))
+ continue;
+
+ wl_surface_send_enter (surface->resource, resource);
+ }
+}
+
+static void
+surface_left_output (MetaWaylandSurface *surface,
+ MetaWaylandOutput *wayland_output)
+{
+ GList *iter;
+ struct wl_resource *resource;
+
+ for (iter = wayland_output->resources; iter != NULL; iter = iter->next)
+ {
+ resource = iter->data;
+
+ if (wl_resource_get_client (resource) !=
+ wl_resource_get_client (surface->resource))
+ continue;
+
+ wl_surface_send_leave (surface->resource, resource);
+ }
+}
+
+static void
+set_surface_is_on_output (MetaWaylandSurface *surface,
+ MetaWaylandOutput *wayland_output,
+ gboolean is_on_output);
+
+static void
+surface_handle_output_destroy (MetaWaylandOutput *wayland_output,
+ GParamSpec *pspec,
+ MetaWaylandSurface *surface)
+{
+ set_surface_is_on_output (surface, wayland_output, FALSE);
+}
+
+static void
+set_surface_is_on_output (MetaWaylandSurface *surface,
+ MetaWaylandOutput *wayland_output,
+ gboolean is_on_output)
+{
+ gboolean was_on_output = g_hash_table_contains (surface->outputs,
+ wayland_output);
+
+ if (!was_on_output && is_on_output)
+ {
+ g_signal_connect (wayland_output, "output-destroyed",
+ G_CALLBACK (surface_handle_output_destroy),
+ surface);
+ g_hash_table_add (surface->outputs, wayland_output);
+ surface_entered_output (surface, wayland_output);
+ }
+ else if (was_on_output && !is_on_output)
+ {
+ g_hash_table_remove (surface->outputs, wayland_output);
+ g_signal_handlers_disconnect_by_func (
+ wayland_output, (gpointer)surface_handle_output_destroy, surface);
+ surface_left_output (surface, wayland_output);
+ }
+}
+
+static void
+update_surface_output_state (gpointer key, gpointer value, gpointer user_data)
+{
+ MetaWaylandOutput *wayland_output = value;
+ MetaWaylandSurface *surface = user_data;
+ MetaSurfaceActorWayland *actor =
+ META_SURFACE_ACTOR_WAYLAND (surface->surface_actor);
+ MetaMonitorInfo *monitor;
+ gboolean is_on_output;
+
+ monitor = wayland_output->monitor_info;
+ if (!monitor)
+ {
+ set_surface_is_on_output (surface, wayland_output, FALSE);
+ return;
+ }
+
+ is_on_output = meta_surface_actor_wayland_is_on_monitor (actor, monitor);
+ set_surface_is_on_output (surface, wayland_output, is_on_output);
+}
+
+void
+meta_wayland_surface_update_outputs (MetaWaylandSurface *surface)
+{
+ if (!surface->compositor)
+ return;
+
+ g_hash_table_foreach (surface->compositor->outputs,
+ update_surface_output_state,
+ surface);
+}
+
void
meta_wayland_surface_set_window (MetaWaylandSurface *surface,
MetaWindow *window)
@@ -809,6 +918,8 @@ wl_surface_destructor (struct wl_resource *resource)
meta_wayland_compositor_destroy_frame_callbacks (compositor, surface);
+ g_hash_table_unref (surface->outputs);
+
if (surface->resource)
wl_resource_set_user_data (surface->resource, NULL);
@@ -847,6 +958,8 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
sync_drag_dest_funcs (surface);
+ surface->outputs = g_hash_table_new (NULL, NULL);
+
pending_state_init (&surface->pending);
return surface;
}
diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h
index 66206b9..e29cf93 100644
--- a/src/wayland/meta-wayland-surface.h
+++ b/src/wayland/meta-wayland-surface.h
@@ -100,6 +100,7 @@ struct _MetaWaylandSurface
int scale;
int32_t offset_x, offset_y;
GList *subsurfaces;
+ GHashTable *outputs;
struct {
const MetaWaylandDragDestFuncs *funcs;
@@ -187,4 +188,6 @@ void meta_wayland_surface_drag_dest_motion (MetaWaylandSurface
void meta_wayland_surface_drag_dest_focus_out (MetaWaylandSurface *surface);
void meta_wayland_surface_drag_dest_drop (MetaWaylandSurface *surface);
+void meta_wayland_surface_update_outputs (MetaWaylandSurface *surface);
+
#endif
diff --git a/src/wayland/meta-wayland-types.h b/src/wayland/meta-wayland-types.h
index 637af77..6b134e6 100644
--- a/src/wayland/meta-wayland-types.h
+++ b/src/wayland/meta-wayland-types.h
@@ -39,6 +39,8 @@ typedef struct _MetaWaylandRegion MetaWaylandRegion;
typedef struct _MetaWaylandSurface MetaWaylandSurface;
+typedef struct _MetaWaylandOutput MetaWaylandOutput;
+
typedef struct _MetaWaylandSerial MetaWaylandSerial;
#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]