mirror of
https://github.com/brl/mutter.git
synced 2024-11-25 17:40:40 -05:00
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
This commit is contained in:
parent
ba7c524a18
commit
eb023ff2c9
@ -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)
|
||||
{
|
||||
@ -239,6 +274,19 @@ meta_surface_actor_wayland_get_preferred_height (ClutterActor *self,
|
||||
*natural_height_p *= scale;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -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;
|
||||
|
@ -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__ */
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -39,6 +39,8 @@ typedef struct _MetaWaylandRegion MetaWaylandRegion;
|
||||
|
||||
typedef struct _MetaWaylandSurface MetaWaylandSurface;
|
||||
|
||||
typedef struct _MetaWaylandOutput MetaWaylandOutput;
|
||||
|
||||
typedef struct _MetaWaylandSerial MetaWaylandSerial;
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user