Compare commits
2 Commits
wip/surfac
...
wip/xdg-sh
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c9e225822c | ||
![]() |
1689de7015 |
@@ -275,113 +275,87 @@
|
||||
<arg name="output" type="object" interface="wl_output" allow-null="true"/>
|
||||
</request>
|
||||
|
||||
<event name="request_set_fullscreen">
|
||||
<description summary="server requests that the client set fullscreen">
|
||||
Event sent from the compositor to the client requesting that the client
|
||||
goes to a fullscreen state. It's the client job to call set_fullscreen
|
||||
and really trigger the fullscreen state.
|
||||
<enum name="state_type">
|
||||
<description summary="types of state on the surface">
|
||||
The different state values used on the surface. This is designed for
|
||||
state values like maximized, fullscreen. It is paired with the
|
||||
request_change_state event to ensure that both the client and the
|
||||
compositor setting the state can be synchronized.
|
||||
|
||||
States set in this way are double-buffered. They will get applied on
|
||||
the next commit.
|
||||
|
||||
Desktop environments may extend this enum by taking up a range of
|
||||
values and documenting the range they chose in this description.
|
||||
They are not required to document the values for the range that they
|
||||
chose. Ideally, any good extensions from a desktop environment should
|
||||
make its way into standardization into this enum.
|
||||
|
||||
The current reserved ranges are:
|
||||
|
||||
0x0000 - 0x0FFF: xdg-shell core values, documented below.
|
||||
0x1000 - 0x1FFF: GNOME
|
||||
</description>
|
||||
</event>
|
||||
<entry name="maximized" value="1" summary="the surface is maximized">
|
||||
A non-zero value indicates the surface is maximized. Otherwise,
|
||||
the surface is unmaximized.
|
||||
</entry>
|
||||
<entry name="fullscreen" value="2" summary="the surface is fullscreen">
|
||||
A non-zero value indicates the surface is fullscreen. Otherwise,
|
||||
the surface is not fullscreen.
|
||||
</entry>
|
||||
</enum>
|
||||
|
||||
<event name="request_unset_fullscreen">
|
||||
<description summary="server requests that the client unset fullscreen">
|
||||
Event sent from the compositor to the client requesting that the client
|
||||
leaves the fullscreen state. It's the client job to call
|
||||
unset_fullscreen and really leave the fullscreen state.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<request name="set_fullscreen">
|
||||
<description summary="set the surface state as fullscreen">
|
||||
Set the surface as fullscreen.
|
||||
|
||||
After this request, the compositor should send a configure event
|
||||
informing the output size.
|
||||
|
||||
This request informs the compositor that the next attached buffer
|
||||
committed will be in a fullscreen state. The buffer size should be the
|
||||
same size as the size informed in the configure event, if the client
|
||||
doesn't want to leave any empty area.
|
||||
|
||||
In other words: the next attached buffer after set_maximized is the new
|
||||
maximized buffer. And the surface will be positioned at the maximized
|
||||
position on commit.
|
||||
|
||||
A simple way to synchronize and wait for the correct configure event is
|
||||
to use a wl_display.sync request right after the set_fullscreen
|
||||
request. When the sync callback returns, the last configure event
|
||||
received just before it will be the correct one, and should contain the
|
||||
right size for the surface to maximize.
|
||||
|
||||
Setting one state won't unset another state. Use
|
||||
xdg_surface.unset_fullscreen for unsetting it.
|
||||
<request name="request_change_state">
|
||||
<description summary="client requests to change a surface's state">
|
||||
This asks the compositor to change the state. If the compositor wants
|
||||
to change the state, it will send a change_state event with the same
|
||||
state_type, value, and serial, and the event flow continues as if it
|
||||
it was initiated by the compositor.
|
||||
|
||||
If the compositor does not want to change the state, it will send a
|
||||
change_state to the client with the old value of the state.
|
||||
</description>
|
||||
<arg name="state_type" type="uint" summary="the state to set"/>
|
||||
<arg name="value" type="uint" summary="the value to change the state to"/>
|
||||
<arg name="serial" type="uint" summary="an event serial">
|
||||
This serial is so the client can know which change_state event corresponds
|
||||
to which request_change_state request it sent out.
|
||||
</arg>
|
||||
</request>
|
||||
|
||||
<request name="unset_fullscreen">
|
||||
<description summary="unset the surface state as fullscreen">
|
||||
Unset the surface fullscreen state.
|
||||
|
||||
Same negotiation as set_fullscreen must be used.
|
||||
<event name="change_state">
|
||||
<description summary="compositor wants to change a surface's state">
|
||||
This event tells the client to change a surface's state. The client
|
||||
should respond with an ack_change_state request to the compositor to
|
||||
guarantee that the compositor knows that the client has seen it.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<event name="request_set_maximized">
|
||||
<description summary="server requests that the client set maximized">
|
||||
Event sent from the compositor to the client requesting that the client
|
||||
goes to a maximized state. It's the client job to call set_maximized
|
||||
and really trigger the maximized state.
|
||||
</description>
|
||||
<arg name="state_type" type="uint" summary="the state to set"/>
|
||||
<arg name="value" type="uint" summary="the value to change the state to"/>
|
||||
<arg name="serial" type="uint" summary="a serial for the compositor's own tracking"/>
|
||||
</event>
|
||||
|
||||
<event name="request_unset_maximized">
|
||||
<description summary="server requests that the client unset maximized">
|
||||
Event sent from the compositor to the client requesting that the client
|
||||
leaves the maximized state. It's the client job to call unset_maximized
|
||||
and really leave the maximized state.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<request name="set_maximized">
|
||||
<description summary="set the surface state as maximized">
|
||||
Set the surface as maximized.
|
||||
|
||||
After this request, the compositor will send a configure event
|
||||
informing the output size minus panel and other MW decorations.
|
||||
|
||||
This request informs the compositor that the next attached buffer
|
||||
committed will be in a maximized state. The buffer size should be the
|
||||
same size as the size informed in the configure event, if the client
|
||||
doesn't want to leave any empty area.
|
||||
|
||||
In other words: the next attached buffer after set_maximized is the new
|
||||
maximized buffer. And the surface will be positioned at the maximized
|
||||
position on commit.
|
||||
|
||||
A simple way to synchronize and wait for the correct configure event is
|
||||
to use a wl_display.sync request right after the set_maximized request.
|
||||
When the sync callback returns, the last configure event received just
|
||||
before it will be the correct one, and should contain the right size
|
||||
for the surface to maximize.
|
||||
|
||||
Setting one state won't unset another state. Use
|
||||
xdg_surface.unset_maximized for unsetting it.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="unset_maximized">
|
||||
<description summary="unset the surface state as maximized">
|
||||
Unset the surface maximized state.
|
||||
|
||||
Same negotiation as set_maximized must be used.
|
||||
<request name="ack_change_state">
|
||||
<description summary="ack a change_state event">
|
||||
When a change_state event is received, a client should then ack it
|
||||
using the ack_change_state request to ensure that the compositor
|
||||
knows the client has seen the event.
|
||||
|
||||
By this point, the state is confirmed, and the next attach should
|
||||
contain the buffer drawn for the new state value.
|
||||
|
||||
The values here need to be the same as the values in the cooresponding
|
||||
change_state event.
|
||||
</description>
|
||||
<arg name="state_type" type="uint" summary="the state to set"/>
|
||||
<arg name="value" type="uint" summary="the value to change the state to"/>
|
||||
<arg name="serial" type="uint" summary="a serial to pass to change_state"/>
|
||||
</request>
|
||||
|
||||
<request name="set_minimized">
|
||||
<description summary="set the surface state as minimized">
|
||||
Set the surface minimized state.
|
||||
|
||||
Setting one state won't unset another state.
|
||||
<description summary="minimize the surface">
|
||||
Minimize the surface.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
|
@@ -80,10 +80,6 @@ libmutter_wayland_la_SOURCES = \
|
||||
compositor/meta-shaped-texture-private.h \
|
||||
compositor/meta-surface-actor.c \
|
||||
compositor/meta-surface-actor.h \
|
||||
compositor/meta-surface-actor-x11.c \
|
||||
compositor/meta-surface-actor-x11.h \
|
||||
compositor/meta-surface-actor-wayland.c \
|
||||
compositor/meta-surface-actor-wayland.h \
|
||||
compositor/meta-texture-rectangle.c \
|
||||
compositor/meta-texture-rectangle.h \
|
||||
compositor/meta-texture-tower.c \
|
||||
|
@@ -42,6 +42,8 @@
|
||||
static void meta_shaped_texture_dispose (GObject *object);
|
||||
|
||||
static void meta_shaped_texture_paint (ClutterActor *actor);
|
||||
static void meta_shaped_texture_pick (ClutterActor *actor,
|
||||
const ClutterColor *color);
|
||||
|
||||
static void meta_shaped_texture_get_preferred_width (ClutterActor *self,
|
||||
gfloat for_height,
|
||||
@@ -71,6 +73,8 @@ struct _MetaShapedTexturePrivate
|
||||
CoglTexture *texture;
|
||||
CoglTexture *mask_texture;
|
||||
|
||||
cairo_region_t *input_shape_region;
|
||||
|
||||
/* The region containing only fully opaque pixels */
|
||||
cairo_region_t *opaque_region;
|
||||
|
||||
@@ -94,6 +98,7 @@ meta_shaped_texture_class_init (MetaShapedTextureClass *klass)
|
||||
actor_class->get_preferred_width = meta_shaped_texture_get_preferred_width;
|
||||
actor_class->get_preferred_height = meta_shaped_texture_get_preferred_height;
|
||||
actor_class->paint = meta_shaped_texture_paint;
|
||||
actor_class->pick = meta_shaped_texture_pick;
|
||||
actor_class->get_paint_volume = meta_shaped_texture_get_paint_volume;
|
||||
|
||||
g_type_class_add_private (klass, sizeof (MetaShapedTexturePrivate));
|
||||
@@ -458,6 +463,71 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
||||
cairo_region_destroy (blended_region);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_pick (ClutterActor *actor,
|
||||
const ClutterColor *color)
|
||||
{
|
||||
MetaShapedTexture *stex = (MetaShapedTexture *) actor;
|
||||
MetaShapedTexturePrivate *priv = stex->priv;
|
||||
|
||||
if (!clutter_actor_should_pick_paint (actor) ||
|
||||
(priv->clip_region && cairo_region_is_empty (priv->clip_region)))
|
||||
return;
|
||||
|
||||
/* If there is no region then use the regular pick */
|
||||
if (priv->input_shape_region == NULL)
|
||||
CLUTTER_ACTOR_CLASS (meta_shaped_texture_parent_class)->pick (actor, color);
|
||||
else
|
||||
{
|
||||
int n_rects;
|
||||
float *rectangles;
|
||||
int i;
|
||||
CoglPipeline *pipeline;
|
||||
CoglContext *ctx;
|
||||
CoglFramebuffer *fb;
|
||||
CoglColor cogl_color;
|
||||
|
||||
/* Note: We don't bother trying to intersect the pick and clip regions
|
||||
* since needing to copy the region, do the intersection, and probably
|
||||
* increase the number of rectangles seems more likely to have a negative
|
||||
* effect.
|
||||
*
|
||||
* NB: Most of the time when just using rectangles for picking then
|
||||
* picking shouldn't involve any rendering, and minimizing the number of
|
||||
* rectangles has more benefit than reducing the area of the pick
|
||||
* region.
|
||||
*/
|
||||
|
||||
n_rects = cairo_region_num_rectangles (priv->input_shape_region);
|
||||
rectangles = g_alloca (sizeof (float) * 4 * n_rects);
|
||||
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
int pos = i * 4;
|
||||
|
||||
cairo_region_get_rectangle (priv->input_shape_region, i, &rect);
|
||||
|
||||
rectangles[pos] = rect.x;
|
||||
rectangles[pos + 1] = rect.y;
|
||||
rectangles[pos + 2] = rect.x + rect.width;
|
||||
rectangles[pos + 3] = rect.y + rect.height;
|
||||
}
|
||||
|
||||
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
fb = cogl_get_draw_framebuffer ();
|
||||
|
||||
cogl_color_init_from_4ub (&cogl_color, color->red, color->green, color->blue, color->alpha);
|
||||
|
||||
pipeline = cogl_pipeline_new (ctx);
|
||||
cogl_pipeline_set_color (pipeline, &cogl_color);
|
||||
|
||||
cogl_framebuffer_draw_rectangles (fb, pipeline,
|
||||
rectangles, n_rects);
|
||||
cogl_object_unref (pipeline);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_get_preferred_width (ClutterActor *self,
|
||||
gfloat for_height,
|
||||
@@ -694,6 +764,41 @@ meta_shaped_texture_get_texture (MetaShapedTexture *stex)
|
||||
return COGL_TEXTURE (stex->priv->texture);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_shaped_texture_set_input_shape_region:
|
||||
* @stex: a #MetaShapedTexture
|
||||
* @shape_region: the region of the texture that should respond to
|
||||
* input.
|
||||
*
|
||||
* Determines what region of the texture should accept input. For
|
||||
* X based windows this is defined by the ShapeInput region of the
|
||||
* window.
|
||||
*/
|
||||
void
|
||||
meta_shaped_texture_set_input_shape_region (MetaShapedTexture *stex,
|
||||
cairo_region_t *shape_region)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
if (priv->input_shape_region != NULL)
|
||||
{
|
||||
cairo_region_destroy (priv->input_shape_region);
|
||||
priv->input_shape_region = NULL;
|
||||
}
|
||||
|
||||
if (shape_region != NULL)
|
||||
{
|
||||
cairo_region_reference (shape_region);
|
||||
priv->input_shape_region = shape_region;
|
||||
}
|
||||
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_shaped_texture_set_opaque_region:
|
||||
* @stex: a #MetaShapedTexture
|
||||
|
@@ -1,153 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "meta-surface-actor-wayland.h"
|
||||
|
||||
#include <cogl/cogl-wayland-server.h>
|
||||
#include "meta-shaped-texture-private.h"
|
||||
|
||||
struct _MetaSurfaceActorWaylandPrivate
|
||||
{
|
||||
MetaWaylandSurface *surface;
|
||||
MetaWaylandBuffer *buffer;
|
||||
};
|
||||
typedef struct _MetaSurfaceActorWaylandPrivate MetaSurfaceActorWaylandPrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaSurfaceActorWayland, meta_surface_actor_wayland, META_TYPE_SURFACE_ACTOR)
|
||||
|
||||
static void
|
||||
meta_surface_actor_wayland_process_damage (MetaSurfaceActor *actor,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor);
|
||||
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
|
||||
|
||||
struct wl_resource *resource = priv->buffer->resource;
|
||||
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (resource);
|
||||
|
||||
if (shm_buffer)
|
||||
{
|
||||
CoglTexture2D *texture = COGL_TEXTURE_2D (priv->buffer->texture);
|
||||
cogl_wayland_texture_set_region_from_shm_buffer (texture, x, y, width, height, shm_buffer, x, y, 0, NULL);
|
||||
}
|
||||
|
||||
meta_surface_actor_update_area (META_SURFACE_ACTOR (self), x, y, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_wayland_pre_paint (MetaSurfaceActor *actor)
|
||||
{
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_surface_actor_wayland_is_argb32 (MetaSurfaceActor *actor)
|
||||
{
|
||||
/* XXX -- look at the SHM buffer format. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_surface_actor_wayland_is_visible (MetaSurfaceActor *actor)
|
||||
{
|
||||
/* TODO: ensure that the buffer isn't NULL, implement
|
||||
* wayland mapping semantics */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_surface_actor_wayland_should_unredirect (MetaSurfaceActor *actor)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_wayland_set_unredirected (MetaSurfaceActor *actor,
|
||||
gboolean unredirected)
|
||||
{
|
||||
/* Do nothing. In the future, we'll use KMS to set this
|
||||
* up as a hardware overlay or something. */
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_surface_actor_wayland_is_unredirected (MetaSurfaceActor *actor)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
|
||||
{
|
||||
MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass);
|
||||
|
||||
surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage;
|
||||
surface_actor_class->pre_paint = meta_surface_actor_wayland_pre_paint;
|
||||
surface_actor_class->is_argb32 = meta_surface_actor_wayland_is_argb32;
|
||||
surface_actor_class->is_visible = meta_surface_actor_wayland_is_visible;
|
||||
|
||||
surface_actor_class->should_unredirect = meta_surface_actor_wayland_should_unredirect;
|
||||
surface_actor_class->set_unredirected = meta_surface_actor_wayland_set_unredirected;
|
||||
surface_actor_class->is_unredirected = meta_surface_actor_wayland_is_unredirected;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_wayland_init (MetaSurfaceActorWayland *self)
|
||||
{
|
||||
}
|
||||
|
||||
MetaSurfaceActor *
|
||||
meta_surface_actor_wayland_new (MetaWaylandSurface *surface)
|
||||
{
|
||||
MetaSurfaceActorWayland *self = g_object_new (META_TYPE_SURFACE_ACTOR_WAYLAND, NULL);
|
||||
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
|
||||
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
priv->surface = surface;
|
||||
|
||||
return META_SURFACE_ACTOR (self);
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self,
|
||||
MetaWaylandBuffer *buffer)
|
||||
{
|
||||
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
|
||||
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
|
||||
|
||||
priv->buffer = buffer;
|
||||
|
||||
if (buffer)
|
||||
meta_shaped_texture_set_texture (stex, buffer->texture);
|
||||
else
|
||||
meta_shaped_texture_set_texture (stex, NULL);
|
||||
}
|
||||
|
||||
MetaWaylandSurface *
|
||||
meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self)
|
||||
{
|
||||
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
|
||||
return priv->surface;
|
||||
}
|
@@ -1,66 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#ifndef __META_SURFACE_ACTOR_WAYLAND_H__
|
||||
#define __META_SURFACE_ACTOR_WAYLAND_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "meta-surface-actor.h"
|
||||
|
||||
#include "meta-wayland-private.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define META_TYPE_SURFACE_ACTOR_WAYLAND (meta_surface_actor_wayland_get_type ())
|
||||
#define META_SURFACE_ACTOR_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWayland))
|
||||
#define META_SURFACE_ACTOR_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWaylandClass))
|
||||
#define META_IS_SURFACE_ACTOR_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SURFACE_ACTOR_WAYLAND))
|
||||
#define META_IS_SURFACE_ACTOR_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SURFACE_ACTOR_WAYLAND))
|
||||
#define META_SURFACE_ACTOR_WAYLAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWaylandClass))
|
||||
|
||||
typedef struct _MetaSurfaceActorWayland MetaSurfaceActorWayland;
|
||||
typedef struct _MetaSurfaceActorWaylandClass MetaSurfaceActorWaylandClass;
|
||||
|
||||
struct _MetaSurfaceActorWayland
|
||||
{
|
||||
MetaSurfaceActor parent;
|
||||
};
|
||||
|
||||
struct _MetaSurfaceActorWaylandClass
|
||||
{
|
||||
MetaSurfaceActorClass parent_class;
|
||||
};
|
||||
|
||||
GType meta_surface_actor_wayland_get_type (void);
|
||||
|
||||
MetaSurfaceActor * meta_surface_actor_wayland_new (MetaWaylandSurface *surface);
|
||||
MetaWaylandSurface * meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self);
|
||||
|
||||
void meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self,
|
||||
MetaWaylandBuffer *buffer);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __META_SURFACE_ACTOR_WAYLAND_H__ */
|
@@ -1,453 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Written by:
|
||||
* Owen Taylor <otaylor@redhat.com>
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "meta-surface-actor-x11.h"
|
||||
|
||||
#include <X11/extensions/Xcomposite.h>
|
||||
#include <X11/extensions/Xrender.h>
|
||||
#include <cogl/cogl-texture-pixmap-x11.h>
|
||||
|
||||
#include <meta/errors.h>
|
||||
#include "window-private.h"
|
||||
#include "meta-shaped-texture-private.h"
|
||||
#include "meta-cullable.h"
|
||||
|
||||
struct _MetaSurfaceActorX11Private
|
||||
{
|
||||
MetaWindow *window;
|
||||
|
||||
MetaDisplay *display;
|
||||
|
||||
CoglTexture *texture;
|
||||
Pixmap pixmap;
|
||||
Damage damage;
|
||||
|
||||
int last_width;
|
||||
int last_height;
|
||||
|
||||
/* This is used to detect fullscreen windows that need to be unredirected */
|
||||
guint full_damage_frames_count;
|
||||
guint does_full_damage : 1;
|
||||
|
||||
/* Other state... */
|
||||
guint argb32 : 1;
|
||||
guint received_damage : 1;
|
||||
guint size_changed : 1;
|
||||
|
||||
guint unredirected : 1;
|
||||
};
|
||||
typedef struct _MetaSurfaceActorX11Private MetaSurfaceActorX11Private;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaSurfaceActorX11, meta_surface_actor_x11, META_TYPE_SURFACE_ACTOR)
|
||||
|
||||
static void
|
||||
free_damage (MetaSurfaceActorX11 *self)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
MetaDisplay *display = priv->display;
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
|
||||
if (priv->damage == None)
|
||||
return;
|
||||
|
||||
meta_error_trap_push (display);
|
||||
XDamageDestroy (xdisplay, priv->damage);
|
||||
priv->damage = None;
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
static void
|
||||
detach_pixmap (MetaSurfaceActorX11 *self)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
MetaDisplay *display = priv->display;
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
|
||||
|
||||
if (priv->pixmap == None)
|
||||
return;
|
||||
|
||||
/* Get rid of all references to the pixmap before freeing it; it's unclear whether
|
||||
* you are supposed to be able to free a GLXPixmap after freeing the underlying
|
||||
* pixmap, but it certainly doesn't work with current DRI/Mesa
|
||||
*/
|
||||
meta_shaped_texture_set_texture (stex, NULL);
|
||||
cogl_flush ();
|
||||
|
||||
meta_error_trap_push (display);
|
||||
XFreePixmap (xdisplay, priv->pixmap);
|
||||
priv->pixmap = None;
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
cogl_object_unref (priv->texture);
|
||||
priv->texture = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
set_pixmap (MetaSurfaceActorX11 *self,
|
||||
Pixmap pixmap)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
|
||||
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
|
||||
CoglTexture *texture;
|
||||
|
||||
g_assert (priv->pixmap == None);
|
||||
priv->pixmap = pixmap;
|
||||
|
||||
texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, priv->pixmap, FALSE, NULL));
|
||||
|
||||
if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture))))
|
||||
g_warning ("NOTE: Not using GLX TFP!\n");
|
||||
|
||||
priv->texture = texture;
|
||||
meta_shaped_texture_set_texture (stex, texture);
|
||||
}
|
||||
|
||||
static void
|
||||
update_pixmap (MetaSurfaceActorX11 *self)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
MetaDisplay *display = priv->display;
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
|
||||
if (priv->size_changed)
|
||||
{
|
||||
detach_pixmap (self);
|
||||
priv->size_changed = FALSE;
|
||||
}
|
||||
|
||||
if (priv->pixmap == None)
|
||||
{
|
||||
Pixmap new_pixmap;
|
||||
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
|
||||
|
||||
meta_error_trap_push (display);
|
||||
new_pixmap = XCompositeNameWindowPixmap (xdisplay, xwindow);
|
||||
|
||||
if (meta_error_trap_pop_with_return (display) != Success)
|
||||
{
|
||||
/* Probably a BadMatch if the window isn't viewable; we could
|
||||
* GrabServer/GetWindowAttributes/NameWindowPixmap/UngrabServer/Sync
|
||||
* to avoid this, but there's no reason to take two round trips
|
||||
* when one will do. (We need that Sync if we want to handle failures
|
||||
* for any reason other than !viewable. That's unlikely, but maybe
|
||||
* we'll BadAlloc or something.)
|
||||
*/
|
||||
new_pixmap = None;
|
||||
}
|
||||
|
||||
if (new_pixmap == None)
|
||||
{
|
||||
meta_verbose ("Unable to get named pixmap for %s\n",
|
||||
meta_window_get_description (priv->window));
|
||||
return;
|
||||
}
|
||||
|
||||
set_pixmap (self, new_pixmap);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_visible (MetaSurfaceActorX11 *self)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
return (priv->pixmap != None) && !priv->unredirected;
|
||||
}
|
||||
|
||||
static void
|
||||
damage_area (MetaSurfaceActorX11 *self,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
|
||||
if (!is_visible (self))
|
||||
return;
|
||||
|
||||
cogl_texture_pixmap_x11_update_area (priv->texture, x, y, width, height);
|
||||
meta_surface_actor_update_area (META_SURFACE_ACTOR (self), x, y, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
|
||||
priv->received_damage = TRUE;
|
||||
|
||||
if (meta_window_is_fullscreen (priv->window) && !priv->unredirected && !priv->does_full_damage)
|
||||
{
|
||||
MetaRectangle window_rect;
|
||||
meta_window_get_frame_rect (priv->window, &window_rect);
|
||||
|
||||
if (window_rect.x == x &&
|
||||
window_rect.y == y &&
|
||||
window_rect.width == width &&
|
||||
window_rect.height == height)
|
||||
priv->full_damage_frames_count++;
|
||||
else
|
||||
priv->full_damage_frames_count = 0;
|
||||
|
||||
if (priv->full_damage_frames_count >= 100)
|
||||
priv->does_full_damage = TRUE;
|
||||
}
|
||||
|
||||
/* Drop damage event for unredirected windows */
|
||||
if (priv->unredirected)
|
||||
return;
|
||||
|
||||
damage_area (self, x, y, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_x11_pre_paint (MetaSurfaceActor *actor)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
MetaDisplay *display = priv->display;
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
|
||||
if (priv->received_damage)
|
||||
{
|
||||
meta_error_trap_push (display);
|
||||
XDamageSubtract (xdisplay, priv->damage, None, None);
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
/* We need to make sure that any X drawing that happens before the
|
||||
* XDamageSubtract() above is visible to subsequent GL rendering;
|
||||
* the only standardized way to do this is EXT_x11_sync_object,
|
||||
* which isn't yet widely available. For now, we count on details
|
||||
* of Xorg and the open source drivers, and hope for the best
|
||||
* otherwise.
|
||||
*
|
||||
* Xorg and open source driver specifics:
|
||||
*
|
||||
* The X server makes sure to flush drawing to the kernel before
|
||||
* sending out damage events, but since we use DamageReportBoundingBox
|
||||
* there may be drawing between the last damage event and the
|
||||
* XDamageSubtract() that needs to be flushed as well.
|
||||
*
|
||||
* Xorg always makes sure that drawing is flushed to the kernel
|
||||
* before writing events or responses to the client, so any round trip
|
||||
* request at this point is sufficient to flush the GLX buffers.
|
||||
*/
|
||||
XSync (xdisplay, False);
|
||||
|
||||
priv->received_damage = FALSE;
|
||||
}
|
||||
|
||||
update_pixmap (self);
|
||||
}
|
||||
|
||||
static void
|
||||
update_is_argb32 (MetaSurfaceActorX11 *self)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
MetaDisplay *display = priv->display;
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
|
||||
XRenderPictFormat *format;
|
||||
format = XRenderFindVisualFormat (xdisplay, priv->window->xvisual);
|
||||
|
||||
priv->argb32 = (format && format->type == PictTypeDirect && format->direct.alphaMask);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_surface_actor_x11_is_argb32 (MetaSurfaceActor *actor)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
|
||||
return priv->argb32;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_surface_actor_x11_is_visible (MetaSurfaceActor *actor)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
|
||||
return is_visible (self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_surface_actor_x11_should_unredirect (MetaSurfaceActor *actor)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
|
||||
MetaWindow *window = priv->window;
|
||||
|
||||
if (meta_window_requested_dont_bypass_compositor (window))
|
||||
return FALSE;
|
||||
|
||||
if (window->opacity != 0xFF)
|
||||
return FALSE;
|
||||
|
||||
if (window->shape_region != NULL)
|
||||
return FALSE;
|
||||
|
||||
if (priv->argb32 && !meta_window_requested_bypass_compositor (window))
|
||||
return FALSE;
|
||||
|
||||
if (!meta_window_is_monitor_sized (window))
|
||||
return FALSE;
|
||||
|
||||
if (meta_window_requested_bypass_compositor (window))
|
||||
return TRUE;
|
||||
|
||||
if (meta_window_is_override_redirect (window))
|
||||
return TRUE;
|
||||
|
||||
if (priv->does_full_damage)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
sync_unredirected (MetaSurfaceActorX11 *self)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
MetaDisplay *display = priv->display;
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
|
||||
|
||||
meta_error_trap_push (display);
|
||||
|
||||
if (priv->unredirected)
|
||||
{
|
||||
detach_pixmap (self);
|
||||
XCompositeUnredirectWindow (xdisplay, xwindow, CompositeRedirectManual);
|
||||
}
|
||||
else
|
||||
{
|
||||
XCompositeRedirectWindow (xdisplay, xwindow, CompositeRedirectManual);
|
||||
}
|
||||
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_x11_set_unredirected (MetaSurfaceActor *actor,
|
||||
gboolean unredirected)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
|
||||
if (priv->unredirected == unredirected)
|
||||
return;
|
||||
|
||||
priv->unredirected = unredirected;
|
||||
sync_unredirected (self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_surface_actor_x11_is_unredirected (MetaSurfaceActor *actor)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
|
||||
return priv->unredirected;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_x11_dispose (GObject *object)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (object);
|
||||
|
||||
detach_pixmap (self);
|
||||
free_damage (self);
|
||||
|
||||
G_OBJECT_CLASS (meta_surface_actor_x11_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_x11_class_init (MetaSurfaceActorX11Class *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass);
|
||||
|
||||
object_class->dispose = meta_surface_actor_x11_dispose;
|
||||
|
||||
surface_actor_class->process_damage = meta_surface_actor_x11_process_damage;
|
||||
surface_actor_class->pre_paint = meta_surface_actor_x11_pre_paint;
|
||||
surface_actor_class->is_argb32 = meta_surface_actor_x11_is_argb32;
|
||||
surface_actor_class->is_visible = meta_surface_actor_x11_is_visible;
|
||||
|
||||
surface_actor_class->should_unredirect = meta_surface_actor_x11_should_unredirect;
|
||||
surface_actor_class->set_unredirected = meta_surface_actor_x11_set_unredirected;
|
||||
surface_actor_class->is_unredirected = meta_surface_actor_x11_is_unredirected;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_x11_init (MetaSurfaceActorX11 *self)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
|
||||
priv->last_width = -1;
|
||||
priv->last_height = -1;
|
||||
}
|
||||
|
||||
MetaSurfaceActor *
|
||||
meta_surface_actor_x11_new (MetaWindow *window)
|
||||
{
|
||||
MetaSurfaceActorX11 *self = g_object_new (META_TYPE_SURFACE_ACTOR_X11, NULL);
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
MetaDisplay *display = meta_window_get_display (window);
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
Window xwindow = meta_window_get_toplevel_xwindow (window);
|
||||
|
||||
g_assert (!meta_is_wayland_compositor ());
|
||||
|
||||
priv->window = window;
|
||||
priv->display = display;
|
||||
|
||||
priv->damage = XDamageCreate (xdisplay, xwindow, XDamageReportBoundingBox);
|
||||
update_is_argb32 (self);
|
||||
|
||||
priv->unredirected = FALSE;
|
||||
sync_unredirected (self);
|
||||
|
||||
return META_SURFACE_ACTOR (self);
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self,
|
||||
int width, int height)
|
||||
{
|
||||
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
|
||||
|
||||
if (priv->last_width == width &&
|
||||
priv->last_height == height)
|
||||
return;
|
||||
|
||||
priv->size_changed = TRUE;
|
||||
priv->last_width = width;
|
||||
priv->last_height = height;
|
||||
}
|
@@ -1,69 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Written by:
|
||||
* Owen Taylor <otaylor@redhat.com>
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#ifndef __META_SURFACE_ACTOR_X11_H__
|
||||
#define __META_SURFACE_ACTOR_X11_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "meta-surface-actor.h"
|
||||
|
||||
#include <X11/extensions/Xdamage.h>
|
||||
|
||||
#include <meta/display.h>
|
||||
#include <meta/window.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define META_TYPE_SURFACE_ACTOR_X11 (meta_surface_actor_x11_get_type ())
|
||||
#define META_SURFACE_ACTOR_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11))
|
||||
#define META_SURFACE_ACTOR_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11Class))
|
||||
#define META_IS_SURFACE_ACTOR_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SURFACE_ACTOR_X11))
|
||||
#define META_IS_SURFACE_ACTOR_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SURFACE_ACTOR_X11))
|
||||
#define META_SURFACE_ACTOR_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11Class))
|
||||
|
||||
typedef struct _MetaSurfaceActorX11 MetaSurfaceActorX11;
|
||||
typedef struct _MetaSurfaceActorX11Class MetaSurfaceActorX11Class;
|
||||
|
||||
struct _MetaSurfaceActorX11
|
||||
{
|
||||
MetaSurfaceActor parent;
|
||||
};
|
||||
|
||||
struct _MetaSurfaceActorX11Class
|
||||
{
|
||||
MetaSurfaceActorClass parent_class;
|
||||
};
|
||||
|
||||
GType meta_surface_actor_x11_get_type (void);
|
||||
|
||||
MetaSurfaceActor * meta_surface_actor_x11_new (MetaWindow *window);
|
||||
|
||||
void meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self,
|
||||
int width, int height);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __META_SURFACE_ACTOR_X11_H__ */
|
@@ -10,30 +10,26 @@
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "meta-surface-actor.h"
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <cogl/cogl-wayland-server.h>
|
||||
#include <cogl/cogl-texture-pixmap-x11.h>
|
||||
#include <meta/meta-shaped-texture.h>
|
||||
#include "meta-surface-actor.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-cullable.h"
|
||||
|
||||
#include "meta-shaped-texture-private.h"
|
||||
|
||||
struct _MetaSurfaceActorPrivate
|
||||
{
|
||||
MetaShapedTexture *texture;
|
||||
|
||||
cairo_region_t *input_region;
|
||||
|
||||
/* Freeze/thaw accounting */
|
||||
guint freeze_count;
|
||||
guint needs_damage_all : 1;
|
||||
MetaWaylandBuffer *buffer;
|
||||
};
|
||||
|
||||
static void cullable_iface_init (MetaCullableInterface *iface);
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaSurfaceActor, meta_surface_actor, CLUTTER_TYPE_ACTOR,
|
||||
G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
|
||||
G_DEFINE_TYPE_WITH_CODE (MetaSurfaceActor, meta_surface_actor, CLUTTER_TYPE_ACTOR,
|
||||
G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor *self,
|
||||
@@ -43,77 +39,9 @@ meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor *self,
|
||||
return meta_shaped_texture_get_unobscured_bounds (priv->texture, unobscured_bounds);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_pick (ClutterActor *actor,
|
||||
const ClutterColor *color)
|
||||
{
|
||||
MetaSurfaceActor *self = META_SURFACE_ACTOR (actor);
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
|
||||
if (!clutter_actor_should_pick_paint (actor))
|
||||
return;
|
||||
|
||||
/* If there is no region then use the regular pick */
|
||||
if (priv->input_region == NULL)
|
||||
CLUTTER_ACTOR_CLASS (meta_surface_actor_parent_class)->pick (actor, color);
|
||||
else
|
||||
{
|
||||
int n_rects;
|
||||
float *rectangles;
|
||||
int i;
|
||||
CoglPipeline *pipeline;
|
||||
CoglContext *ctx;
|
||||
CoglFramebuffer *fb;
|
||||
CoglColor cogl_color;
|
||||
|
||||
n_rects = cairo_region_num_rectangles (priv->input_region);
|
||||
rectangles = g_alloca (sizeof (float) * 4 * n_rects);
|
||||
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
int pos = i * 4;
|
||||
|
||||
cairo_region_get_rectangle (priv->input_region, i, &rect);
|
||||
|
||||
rectangles[pos + 0] = rect.x;
|
||||
rectangles[pos + 1] = rect.y;
|
||||
rectangles[pos + 2] = rect.x + rect.width;
|
||||
rectangles[pos + 3] = rect.y + rect.height;
|
||||
}
|
||||
|
||||
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
fb = cogl_get_draw_framebuffer ();
|
||||
|
||||
cogl_color_init_from_4ub (&cogl_color, color->red, color->green, color->blue, color->alpha);
|
||||
|
||||
pipeline = cogl_pipeline_new (ctx);
|
||||
cogl_pipeline_set_color (pipeline, &cogl_color);
|
||||
cogl_framebuffer_draw_rectangles (fb, pipeline, rectangles, n_rects);
|
||||
cogl_object_unref (pipeline);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_dispose (GObject *object)
|
||||
{
|
||||
MetaSurfaceActor *self = META_SURFACE_ACTOR (object);
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
|
||||
g_clear_pointer (&priv->input_region, cairo_region_destroy);
|
||||
|
||||
G_OBJECT_CLASS (meta_surface_actor_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_class_init (MetaSurfaceActorClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
|
||||
object_class->dispose = meta_surface_actor_dispose;
|
||||
actor_class->pick = meta_surface_actor_pick;
|
||||
|
||||
g_type_class_add_private (klass, sizeof (MetaSurfaceActorPrivate));
|
||||
}
|
||||
|
||||
@@ -164,11 +92,50 @@ meta_surface_actor_get_texture (MetaSurfaceActor *self)
|
||||
return self->priv->texture;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_update_area (MetaSurfaceActor *self,
|
||||
int x, int y, int width, int height)
|
||||
static void
|
||||
update_area (MetaSurfaceActor *self,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
struct wl_resource *resource = priv->buffer->resource;
|
||||
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (resource);
|
||||
|
||||
if (shm_buffer)
|
||||
{
|
||||
CoglTexture2D *texture = COGL_TEXTURE_2D (priv->buffer->texture);
|
||||
cogl_wayland_texture_set_region_from_shm_buffer (texture, x, y, width, height, shm_buffer, x, y, 0, NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CoglTexturePixmapX11 *texture = COGL_TEXTURE_PIXMAP_X11 (meta_shaped_texture_get_texture (priv->texture));
|
||||
cogl_texture_pixmap_x11_update_area (texture, x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_damage_all (MetaSurfaceActor *self)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
CoglTexture *texture = meta_shaped_texture_get_texture (priv->texture);
|
||||
|
||||
update_area (self, 0, 0, cogl_texture_get_width (texture), cogl_texture_get_height (texture));
|
||||
return meta_shaped_texture_update_area (priv->texture, 0, 0, cogl_texture_get_width (texture), cogl_texture_get_height (texture));
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_damage_area (MetaSurfaceActor *self,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
|
||||
update_area (self, x, y, width, height);
|
||||
return meta_shaped_texture_update_area (priv->texture, x, y, width, height);
|
||||
}
|
||||
|
||||
@@ -179,19 +146,33 @@ meta_surface_actor_is_obscured (MetaSurfaceActor *self)
|
||||
return meta_shaped_texture_is_obscured (priv->texture);
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_attach_wayland_buffer (MetaSurfaceActor *self,
|
||||
MetaWaylandBuffer *buffer)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
priv->buffer = buffer;
|
||||
|
||||
if (buffer)
|
||||
meta_shaped_texture_set_texture (priv->texture, buffer->texture);
|
||||
else
|
||||
meta_shaped_texture_set_texture (priv->texture, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_set_texture (MetaSurfaceActor *self,
|
||||
CoglTexture *texture)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
meta_shaped_texture_set_texture (priv->texture, texture);
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_set_input_region (MetaSurfaceActor *self,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
|
||||
if (priv->input_region)
|
||||
cairo_region_destroy (priv->input_region);
|
||||
|
||||
if (region)
|
||||
priv->input_region = cairo_region_reference (region);
|
||||
else
|
||||
priv->input_region = NULL;
|
||||
meta_shaped_texture_set_input_shape_region (priv->texture, region);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -202,114 +183,8 @@ meta_surface_actor_set_opaque_region (MetaSurfaceActor *self,
|
||||
meta_shaped_texture_set_opaque_region (priv->texture, region);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_frozen (MetaSurfaceActor *self)
|
||||
MetaSurfaceActor *
|
||||
meta_surface_actor_new (void)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
return (priv->freeze_count > 0);
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_process_damage (MetaSurfaceActor *self,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
|
||||
if (is_frozen (self))
|
||||
{
|
||||
/* The window is frozen due to an effect in progress: we ignore damage
|
||||
* here on the off chance that this will stop the corresponding
|
||||
* texture_from_pixmap from being update.
|
||||
*
|
||||
* needs_damage_all tracks that some unknown damage happened while the
|
||||
* window was frozen so that when the window becomes unfrozen we can
|
||||
* issue a full window update to cover any lost damage.
|
||||
*
|
||||
* It should be noted that this is an unreliable mechanism since it's
|
||||
* quite likely that drivers will aim to provide a zero-copy
|
||||
* implementation of the texture_from_pixmap extension and in those cases
|
||||
* any drawing done to the window is always immediately reflected in the
|
||||
* texture regardless of damage event handling.
|
||||
*/
|
||||
priv->needs_damage_all = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
META_SURFACE_ACTOR_GET_CLASS (self)->process_damage (self, x, y, width, height);
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_pre_paint (MetaSurfaceActor *self)
|
||||
{
|
||||
META_SURFACE_ACTOR_GET_CLASS (self)->pre_paint (self);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_is_argb32 (MetaSurfaceActor *self)
|
||||
{
|
||||
return META_SURFACE_ACTOR_GET_CLASS (self)->is_argb32 (self);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_is_visible (MetaSurfaceActor *self)
|
||||
{
|
||||
return META_SURFACE_ACTOR_GET_CLASS (self)->is_visible (self);
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_freeze (MetaSurfaceActor *self)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
|
||||
priv->freeze_count ++;
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_thaw (MetaSurfaceActor *self)
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv = self->priv;
|
||||
|
||||
if (priv->freeze_count == 0)
|
||||
{
|
||||
g_critical ("Error in freeze/thaw accounting.");
|
||||
return;
|
||||
}
|
||||
|
||||
priv->freeze_count --;
|
||||
|
||||
/* Since we ignore damage events while a window is frozen for certain effects
|
||||
* we may need to issue an update_area() covering the whole pixmap if we
|
||||
* don't know what real damage has happened. */
|
||||
if (priv->needs_damage_all)
|
||||
{
|
||||
meta_surface_actor_process_damage (self, 0, 0,
|
||||
clutter_actor_get_width (CLUTTER_ACTOR (priv->texture)),
|
||||
clutter_actor_get_height (CLUTTER_ACTOR (priv->texture)));
|
||||
priv->needs_damage_all = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_is_frozen (MetaSurfaceActor *self)
|
||||
{
|
||||
return is_frozen (self);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_should_unredirect (MetaSurfaceActor *self)
|
||||
{
|
||||
return META_SURFACE_ACTOR_GET_CLASS (self)->should_unredirect (self);
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_set_unredirected (MetaSurfaceActor *self,
|
||||
gboolean unredirected)
|
||||
{
|
||||
META_SURFACE_ACTOR_GET_CLASS (self)->set_unredirected (self, unredirected);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_surface_actor_is_unredirected (MetaSurfaceActor *self)
|
||||
{
|
||||
return META_SURFACE_ACTOR_GET_CLASS (self)->is_unredirected (self);
|
||||
return g_object_new (META_TYPE_SURFACE_ACTOR, NULL);
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@
|
||||
#include <config.h>
|
||||
|
||||
#include <meta/meta-shaped-texture.h>
|
||||
#include "meta-wayland-types.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@@ -24,17 +25,6 @@ struct _MetaSurfaceActorClass
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterActorClass parent_class;
|
||||
|
||||
void (* process_damage) (MetaSurfaceActor *actor,
|
||||
int x, int y, int width, int height);
|
||||
void (* pre_paint) (MetaSurfaceActor *actor);
|
||||
gboolean (* is_argb32) (MetaSurfaceActor *actor);
|
||||
gboolean (* is_visible) (MetaSurfaceActor *actor);
|
||||
|
||||
gboolean (* should_unredirect) (MetaSurfaceActor *actor);
|
||||
void (* set_unredirected) (MetaSurfaceActor *actor,
|
||||
gboolean unredirected);
|
||||
gboolean (* is_unredirected) (MetaSurfaceActor *actor);
|
||||
};
|
||||
|
||||
struct _MetaSurfaceActor
|
||||
@@ -46,38 +36,33 @@ struct _MetaSurfaceActor
|
||||
|
||||
GType meta_surface_actor_get_type (void);
|
||||
|
||||
MetaSurfaceActor *meta_surface_actor_new (void);
|
||||
|
||||
cairo_surface_t *meta_surface_actor_get_image (MetaSurfaceActor *self,
|
||||
cairo_rectangle_int_t *clip);
|
||||
|
||||
MetaShapedTexture *meta_surface_actor_get_texture (MetaSurfaceActor *self);
|
||||
|
||||
gboolean meta_surface_actor_damage_all (MetaSurfaceActor *self);
|
||||
gboolean meta_surface_actor_damage_area (MetaSurfaceActor *self,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
gboolean meta_surface_actor_is_obscured (MetaSurfaceActor *self);
|
||||
gboolean meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor *self,
|
||||
cairo_rectangle_int_t *unobscured_bounds);
|
||||
|
||||
void meta_surface_actor_set_texture (MetaSurfaceActor *self,
|
||||
CoglTexture *texture);
|
||||
void meta_surface_actor_attach_wayland_buffer (MetaSurfaceActor *self,
|
||||
MetaWaylandBuffer *buffer);
|
||||
void meta_surface_actor_set_input_region (MetaSurfaceActor *self,
|
||||
cairo_region_t *region);
|
||||
void meta_surface_actor_set_opaque_region (MetaSurfaceActor *self,
|
||||
cairo_region_t *region);
|
||||
|
||||
gboolean meta_surface_actor_update_area (MetaSurfaceActor *actor,
|
||||
int x, int y, int width, int height);
|
||||
|
||||
void meta_surface_actor_process_damage (MetaSurfaceActor *actor,
|
||||
int x, int y, int width, int height);
|
||||
void meta_surface_actor_pre_paint (MetaSurfaceActor *actor);
|
||||
gboolean meta_surface_actor_is_argb32 (MetaSurfaceActor *actor);
|
||||
gboolean meta_surface_actor_is_visible (MetaSurfaceActor *actor);
|
||||
|
||||
void meta_surface_actor_freeze (MetaSurfaceActor *actor);
|
||||
void meta_surface_actor_thaw (MetaSurfaceActor *actor);
|
||||
gboolean meta_surface_actor_is_frozen (MetaSurfaceActor *actor);
|
||||
|
||||
gboolean meta_surface_actor_should_unredirect (MetaSurfaceActor *actor);
|
||||
void meta_surface_actor_set_unredirected (MetaSurfaceActor *actor,
|
||||
gboolean unredirected);
|
||||
gboolean meta_surface_actor_is_unredirected (MetaSurfaceActor *actor);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* META_SURFACE_ACTOR_PRIVATE_H */
|
||||
|
@@ -10,6 +10,10 @@
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <X11/extensions/Xcomposite.h>
|
||||
#include <X11/extensions/Xdamage.h>
|
||||
#include <X11/extensions/Xrender.h>
|
||||
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
#include <cogl/cogl-texture-pixmap-x11.h>
|
||||
#include <gdk/gdk.h> /* for gdk_rectangle_union() */
|
||||
@@ -26,15 +30,13 @@
|
||||
#include "meta-shaped-texture-private.h"
|
||||
#include "meta-shadow-factory-private.h"
|
||||
#include "meta-window-actor-private.h"
|
||||
#include "meta-surface-actor.h"
|
||||
#include "meta-texture-rectangle.h"
|
||||
#include "region-utils.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "monitor-private.h"
|
||||
#include "meta-cullable.h"
|
||||
|
||||
#include "meta-surface-actor.h"
|
||||
#include "meta-surface-actor-x11.h"
|
||||
|
||||
struct _MetaWindowActorPrivate
|
||||
{
|
||||
MetaWindow *window;
|
||||
@@ -61,12 +63,18 @@ struct _MetaWindowActorPrivate
|
||||
/* The region we should clip to when painting the shadow */
|
||||
cairo_region_t *shadow_clip;
|
||||
|
||||
guint send_frame_messages_timer;
|
||||
gint64 frame_drawn_time;
|
||||
|
||||
/* Extracted size-invariant shape used for shadows */
|
||||
MetaWindowShape *shadow_shape;
|
||||
char * shadow_class;
|
||||
|
||||
guint send_frame_messages_timer;
|
||||
gint64 frame_drawn_time;
|
||||
gint last_width;
|
||||
gint last_height;
|
||||
|
||||
gint freeze_count;
|
||||
|
||||
char * shadow_class;
|
||||
|
||||
/*
|
||||
* These need to be counters rather than flags, since more plugins
|
||||
@@ -82,7 +90,11 @@ struct _MetaWindowActorPrivate
|
||||
/* List of FrameData for recent frames */
|
||||
GList *frames;
|
||||
|
||||
Pixmap back_pixmap; /* Not used in wayland compositor mode */
|
||||
Damage damage; /* Not used in wayland compositor mode */
|
||||
|
||||
guint visible : 1;
|
||||
guint argb32 : 1;
|
||||
guint disposed : 1;
|
||||
guint redecorating : 1;
|
||||
|
||||
@@ -99,7 +111,24 @@ struct _MetaWindowActorPrivate
|
||||
|
||||
guint no_shadow : 1;
|
||||
|
||||
|
||||
/*
|
||||
* None of these are used in wayland compositor mode...
|
||||
*/
|
||||
|
||||
guint needs_damage_all : 1;
|
||||
guint received_x11_damage : 1;
|
||||
|
||||
guint needs_pixmap : 1;
|
||||
|
||||
guint x11_size_changed : 1;
|
||||
guint updates_frozen : 1;
|
||||
|
||||
guint unredirected : 1;
|
||||
|
||||
/* This is used to detect fullscreen windows that need to be unredirected */
|
||||
guint full_damage_frames_count;
|
||||
guint does_full_damage : 1;
|
||||
};
|
||||
|
||||
typedef struct _FrameData FrameData;
|
||||
@@ -136,6 +165,7 @@ static gboolean meta_window_actor_get_paint_volume (ClutterActor *actor,
|
||||
ClutterPaintVolume *volume);
|
||||
|
||||
|
||||
static void meta_window_actor_detach_x11_pixmap (MetaWindowActor *self);
|
||||
static gboolean meta_window_actor_has_shadow (MetaWindowActor *self);
|
||||
|
||||
static void meta_window_actor_handle_updates (MetaWindowActor *self);
|
||||
@@ -226,6 +256,9 @@ window_decorated_notify (MetaWindow *mw,
|
||||
{
|
||||
MetaWindowActor *self = META_WINDOW_ACTOR (data);
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
MetaScreen *screen = priv->screen;
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
|
||||
/*
|
||||
* Basically, we have to reconstruct the the internals of this object
|
||||
@@ -233,6 +266,23 @@ window_decorated_notify (MetaWindow *mw,
|
||||
*/
|
||||
priv->redecorating = TRUE;
|
||||
|
||||
if (!meta_is_wayland_compositor ())
|
||||
{
|
||||
meta_window_actor_detach_x11_pixmap (self);
|
||||
|
||||
/*
|
||||
* First of all, clean up any resources we are currently using and will
|
||||
* be replacing.
|
||||
*/
|
||||
if (priv->damage != None)
|
||||
{
|
||||
meta_error_trap_push (display);
|
||||
XDamageDestroy (xdisplay, priv->damage);
|
||||
meta_error_trap_pop (display);
|
||||
priv->damage = None;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Recreate the contents.
|
||||
*/
|
||||
@@ -257,52 +307,13 @@ surface_allocation_changed_notify (ClutterActor *actor,
|
||||
meta_window_actor_update_shape (self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_argb32 (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
return meta_surface_actor_is_argb32 (priv->surface);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_non_opaque (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
MetaWindow *window = priv->window;
|
||||
|
||||
return is_argb32 (self) || (window->opacity != 0xFF);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_frozen (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
return meta_surface_actor_is_frozen (priv->surface);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_actor_freeze (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
meta_surface_actor_freeze (priv->surface);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_actor_thaw (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
|
||||
meta_surface_actor_thaw (priv->surface);
|
||||
|
||||
if (is_frozen (self))
|
||||
return;
|
||||
|
||||
/* We sometimes ignore moves and resizes on frozen windows */
|
||||
meta_window_actor_sync_actor_geometry (self, FALSE);
|
||||
|
||||
/* We do this now since we might be going right back into the
|
||||
* frozen state */
|
||||
meta_window_actor_handle_updates (self);
|
||||
return priv->argb32 || (window->opacity != 0xFF);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -311,15 +322,38 @@ meta_window_actor_constructed (GObject *object)
|
||||
MetaWindowActor *self = META_WINDOW_ACTOR (object);
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
MetaWindow *window = priv->window;
|
||||
Window xwindow = meta_window_get_toplevel_xwindow (window);
|
||||
MetaScreen *screen = meta_window_get_screen (window);
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
|
||||
priv->screen = window->screen;
|
||||
priv->screen = screen;
|
||||
|
||||
if (!meta_is_wayland_compositor ())
|
||||
priv->damage = XDamageCreate (xdisplay, xwindow,
|
||||
XDamageReportBoundingBox);
|
||||
|
||||
if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
{
|
||||
XRenderPictFormat *format;
|
||||
|
||||
format = XRenderFindVisualFormat (xdisplay, window->xvisual);
|
||||
|
||||
if (format && format->type == PictTypeDirect && format->direct.alphaMask)
|
||||
priv->argb32 = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* XXX: parse shm formats to determine argb32 */
|
||||
priv->argb32 = TRUE;
|
||||
}
|
||||
|
||||
if (!priv->surface)
|
||||
{
|
||||
if (window->surface)
|
||||
priv->surface = window->surface->surface_actor;
|
||||
else
|
||||
priv->surface = meta_surface_actor_x11_new (window);
|
||||
priv->surface = meta_surface_actor_new ();
|
||||
g_object_ref_sink (priv->surface);
|
||||
|
||||
clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->surface));
|
||||
@@ -342,6 +376,8 @@ meta_window_actor_dispose (GObject *object)
|
||||
MetaWindowActor *self = META_WINDOW_ACTOR (object);
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
MetaScreen *screen;
|
||||
MetaDisplay *display;
|
||||
Display *xdisplay;
|
||||
MetaCompScreen *info;
|
||||
|
||||
if (priv->disposed)
|
||||
@@ -352,6 +388,9 @@ meta_window_actor_dispose (GObject *object)
|
||||
screen = priv->screen;
|
||||
info = meta_screen_get_compositor_data (screen);
|
||||
|
||||
if (!meta_is_wayland_compositor ())
|
||||
meta_window_actor_detach_x11_pixmap (self);
|
||||
|
||||
if (priv->send_frame_messages_timer != 0)
|
||||
{
|
||||
g_source_remove (priv->send_frame_messages_timer);
|
||||
@@ -366,6 +405,18 @@ meta_window_actor_dispose (GObject *object)
|
||||
g_clear_pointer (&priv->unfocused_shadow, meta_shadow_unref);
|
||||
g_clear_pointer (&priv->shadow_shape, meta_window_shape_unref);
|
||||
|
||||
if (!meta_is_wayland_compositor () && priv->damage != None)
|
||||
{
|
||||
display = meta_screen_get_display (screen);
|
||||
xdisplay = meta_display_get_xdisplay (display);
|
||||
|
||||
meta_error_trap_push (display);
|
||||
XDamageDestroy (xdisplay, priv->damage);
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
priv->damage = None;
|
||||
}
|
||||
|
||||
info->windows = g_list_remove (info->windows, (gconstpointer) self);
|
||||
|
||||
g_clear_object (&priv->window);
|
||||
@@ -776,6 +827,13 @@ meta_window_actor_is_destroyed (MetaWindowActor *self)
|
||||
return self->priv->disposed;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_actor_freeze (MetaWindowActor *self)
|
||||
{
|
||||
if (!meta_is_wayland_compositor ())
|
||||
self->priv->freeze_count++;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
send_frame_messages_timeout (gpointer data)
|
||||
{
|
||||
@@ -830,6 +888,55 @@ queue_send_frame_messages_timeout (MetaWindowActor *self)
|
||||
priv->send_frame_messages_timer = g_timeout_add_full (META_PRIORITY_REDRAW, offset, send_frame_messages_timeout, self, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_actor_damage_all (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
gboolean redraw_queued;
|
||||
|
||||
if (!priv->needs_damage_all)
|
||||
return;
|
||||
|
||||
if (priv->needs_pixmap)
|
||||
return;
|
||||
|
||||
redraw_queued = meta_surface_actor_damage_all (priv->surface);
|
||||
priv->repaint_scheduled = priv->repaint_scheduled || redraw_queued;
|
||||
priv->needs_damage_all = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_actor_thaw (MetaWindowActor *self)
|
||||
{
|
||||
if (!meta_is_wayland_compositor ())
|
||||
{
|
||||
self->priv->freeze_count--;
|
||||
|
||||
if (G_UNLIKELY (self->priv->freeze_count < 0))
|
||||
{
|
||||
g_warning ("Error in freeze/thaw accounting.");
|
||||
self->priv->freeze_count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->priv->freeze_count)
|
||||
return;
|
||||
|
||||
/* We sometimes ignore moves and resizes on frozen windows */
|
||||
meta_window_actor_sync_actor_geometry (self, FALSE);
|
||||
|
||||
/* We do this now since we might be going right back into the
|
||||
* frozen state */
|
||||
meta_window_actor_handle_updates (self);
|
||||
|
||||
/* Since we ignore damage events while a window is frozen for certain effects
|
||||
* we may need to issue an update_area() covering the whole pixmap if we
|
||||
* don't know what real damage has happened. */
|
||||
if (self->priv->needs_damage_all)
|
||||
meta_window_actor_damage_all (self);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
|
||||
gboolean no_delay_frame)
|
||||
@@ -884,6 +991,33 @@ meta_window_actor_effect_in_progress (MetaWindowActor *self)
|
||||
self->priv->destroy_in_progress);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_frozen (MetaWindowActor *self)
|
||||
{
|
||||
return self->priv->freeze_count ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_actor_queue_create_x11_pixmap (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
|
||||
priv->needs_pixmap = TRUE;
|
||||
|
||||
if (is_frozen (self))
|
||||
return;
|
||||
|
||||
/* This will cause the compositor paint function to be run
|
||||
* if the actor is visible or a clone of the actor is visible.
|
||||
* if the actor isn't visible in any way, then we don't
|
||||
* need to repair the window anyways, and can wait until
|
||||
* the stage is redrawn for some other reason
|
||||
*
|
||||
* The compositor paint function repairs all windows.
|
||||
*/
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (priv->surface));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_freeze_thaw_effect (gulong event)
|
||||
{
|
||||
@@ -964,6 +1098,12 @@ meta_window_actor_after_effects (MetaWindowActor *self)
|
||||
|
||||
meta_window_actor_sync_visibility (self);
|
||||
meta_window_actor_sync_actor_geometry (self, FALSE);
|
||||
|
||||
if (!meta_is_wayland_compositor ())
|
||||
{
|
||||
if (priv->needs_pixmap)
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (priv->surface));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1038,19 +1178,95 @@ meta_window_actor_effect_completed (MetaWindowActor *self,
|
||||
meta_window_actor_after_effects (self);
|
||||
}
|
||||
|
||||
/* Called to drop our reference to a window backing pixmap that we
|
||||
* previously obtained with XCompositeNameWindowPixmap. We do this
|
||||
* when the window is unmapped or when we want to update to a new
|
||||
* pixmap for a new size.
|
||||
*/
|
||||
static void
|
||||
meta_window_actor_detach_x11_pixmap (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
MetaScreen *screen = priv->screen;
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
|
||||
if (!priv->back_pixmap)
|
||||
return;
|
||||
|
||||
/* Get rid of all references to the pixmap before freeing it; it's unclear whether
|
||||
* you are supposed to be able to free a GLXPixmap after freeing the underlying
|
||||
* pixmap, but it certainly doesn't work with current DRI/Mesa
|
||||
*/
|
||||
meta_surface_actor_set_texture (priv->surface, NULL);
|
||||
cogl_flush();
|
||||
|
||||
XFreePixmap (xdisplay, priv->back_pixmap);
|
||||
priv->back_pixmap = None;
|
||||
|
||||
meta_window_actor_queue_create_x11_pixmap (self);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_window_actor_should_unredirect (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindow *metaWindow = meta_window_actor_get_meta_window (self);
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
return meta_surface_actor_should_unredirect (priv->surface);
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
return FALSE;
|
||||
|
||||
if (meta_window_requested_dont_bypass_compositor (metaWindow))
|
||||
return FALSE;
|
||||
|
||||
if (metaWindow->opacity != 0xFF)
|
||||
return FALSE;
|
||||
|
||||
if (metaWindow->shape_region != NULL)
|
||||
return FALSE;
|
||||
|
||||
if (priv->argb32 && !meta_window_requested_bypass_compositor (metaWindow))
|
||||
return FALSE;
|
||||
|
||||
if (!meta_window_is_monitor_sized (metaWindow))
|
||||
return FALSE;
|
||||
|
||||
if (meta_window_requested_bypass_compositor (metaWindow))
|
||||
return TRUE;
|
||||
|
||||
if (meta_window_is_override_redirect (metaWindow))
|
||||
return TRUE;
|
||||
|
||||
if (priv->does_full_damage)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_actor_set_unredirected (MetaWindowActor *self,
|
||||
gboolean unredirected)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
meta_surface_actor_set_unredirected (priv->surface, unredirected);
|
||||
MetaWindow *metaWindow = meta_window_actor_get_meta_window (self);
|
||||
MetaDisplay *display = meta_window_get_display (metaWindow);
|
||||
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
Window xwin = meta_window_get_toplevel_xwindow (metaWindow);
|
||||
|
||||
meta_error_trap_push (display);
|
||||
|
||||
if (unredirected)
|
||||
{
|
||||
XCompositeUnredirectWindow (xdisplay, xwin, CompositeRedirectManual);
|
||||
}
|
||||
else
|
||||
{
|
||||
XCompositeRedirectWindow (xdisplay, xwin, CompositeRedirectManual);
|
||||
meta_window_actor_detach_x11_pixmap (self);
|
||||
}
|
||||
|
||||
self->priv->unredirected = unredirected;
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1110,11 +1326,19 @@ meta_window_actor_sync_actor_geometry (MetaWindowActor *self,
|
||||
|
||||
meta_window_get_input_rect (priv->window, &window_rect);
|
||||
|
||||
/* When running as a Wayland compositor we catch size changes when new
|
||||
* buffers are attached */
|
||||
if (META_IS_SURFACE_ACTOR_X11 (priv->surface))
|
||||
meta_surface_actor_x11_set_size (META_SURFACE_ACTOR_X11 (priv->surface),
|
||||
window_rect.width, window_rect.height);
|
||||
/* When running as a display server we catch size changes when new
|
||||
buffers are attached */
|
||||
if (!meta_is_wayland_compositor ())
|
||||
{
|
||||
if (priv->last_width != window_rect.width ||
|
||||
priv->last_height != window_rect.height)
|
||||
{
|
||||
priv->x11_size_changed = TRUE;
|
||||
|
||||
priv->last_width = window_rect.width;
|
||||
priv->last_height = window_rect.height;
|
||||
}
|
||||
}
|
||||
|
||||
/* Normally we want freezing a window to also freeze its position; this allows
|
||||
* windows to atomically move and resize together, either under app control,
|
||||
@@ -1126,6 +1350,15 @@ meta_window_actor_sync_actor_geometry (MetaWindowActor *self,
|
||||
if (is_frozen (self) && !did_placement)
|
||||
return;
|
||||
|
||||
if (!meta_is_wayland_compositor ())
|
||||
{
|
||||
if (priv->x11_size_changed)
|
||||
{
|
||||
meta_window_actor_queue_create_x11_pixmap (self);
|
||||
meta_window_actor_update_shape (self);
|
||||
}
|
||||
}
|
||||
|
||||
if (meta_window_actor_effect_in_progress (self))
|
||||
return;
|
||||
|
||||
@@ -1191,6 +1424,7 @@ meta_window_actor_hide (MetaWindowActor *self,
|
||||
g_return_if_fail (priv->visible);
|
||||
|
||||
priv->visible = FALSE;
|
||||
clutter_actor_set_reactive (CLUTTER_ACTOR (self), FALSE);
|
||||
|
||||
/* If a plugin is animating a workspace transition, we have to
|
||||
* hold off on hiding the window, and do it after the workspace
|
||||
@@ -1292,13 +1526,22 @@ meta_window_actor_new (MetaWindow *window)
|
||||
|
||||
priv = self->priv;
|
||||
|
||||
meta_window_actor_set_updates_frozen (self, meta_window_updates_are_frozen (priv->window));
|
||||
if (!meta_is_wayland_compositor ())
|
||||
{
|
||||
priv->last_width = -1;
|
||||
priv->last_height = -1;
|
||||
|
||||
/* If a window doesn't start off with updates frozen, we should
|
||||
* we should send a _NET_WM_FRAME_DRAWN immediately after the first drawn.
|
||||
*/
|
||||
if (priv->window->extended_sync_request_counter && !priv->updates_frozen)
|
||||
meta_window_actor_queue_frame_drawn (self, FALSE);
|
||||
meta_window_actor_queue_create_x11_pixmap (self);
|
||||
|
||||
meta_window_actor_set_updates_frozen (self,
|
||||
meta_window_updates_are_frozen (priv->window));
|
||||
|
||||
/* If a window doesn't start off with updates frozen, we should
|
||||
* we should send a _NET_WM_FRAME_DRAWN immediately after the first drawn.
|
||||
*/
|
||||
if (priv->window->extended_sync_request_counter && !priv->updates_frozen)
|
||||
meta_window_actor_queue_frame_drawn (self, FALSE);
|
||||
}
|
||||
|
||||
meta_window_actor_sync_actor_geometry (self, priv->window->placed);
|
||||
|
||||
@@ -1314,6 +1557,8 @@ meta_window_actor_new (MetaWindow *window)
|
||||
|
||||
clutter_actor_hide (CLUTTER_ACTOR (self));
|
||||
|
||||
clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE);
|
||||
|
||||
/* Initial position in the stack is arbitrary; stacking will be synced
|
||||
* before we first paint.
|
||||
*/
|
||||
@@ -1407,7 +1652,13 @@ meta_window_actor_cull_out (MetaCullable *cullable,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
MetaWindowActor *self = META_WINDOW_ACTOR (cullable);
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
|
||||
/* Don't do any culling for the unredirected window */
|
||||
if (priv->unredirected)
|
||||
return;
|
||||
|
||||
meta_cullable_cull_out_children (cullable, unobscured_region, clip_region);
|
||||
meta_window_actor_set_clip_region_beneath (self, clip_region);
|
||||
}
|
||||
|
||||
@@ -1429,6 +1680,74 @@ cullable_iface_init (MetaCullableInterface *iface)
|
||||
iface->reset_culling = meta_window_actor_reset_culling;
|
||||
}
|
||||
|
||||
/* When running as a wayland compositor we don't make requests for
|
||||
* replacement pixmaps when resizing windows, we will instead be
|
||||
* asked to attach replacement buffers by the clients. */
|
||||
static void
|
||||
check_needs_x11_pixmap (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
MetaScreen *screen = priv->screen;
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
|
||||
|
||||
if (!priv->needs_pixmap)
|
||||
return;
|
||||
|
||||
if (xwindow == meta_screen_get_xroot (screen) ||
|
||||
xwindow == clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage)))
|
||||
return;
|
||||
|
||||
if (priv->x11_size_changed)
|
||||
{
|
||||
meta_window_actor_detach_x11_pixmap (self);
|
||||
priv->x11_size_changed = FALSE;
|
||||
}
|
||||
|
||||
meta_error_trap_push (display);
|
||||
|
||||
if (priv->back_pixmap == None)
|
||||
{
|
||||
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
CoglTexture *texture;
|
||||
|
||||
meta_error_trap_push (display);
|
||||
|
||||
priv->back_pixmap = XCompositeNameWindowPixmap (xdisplay, xwindow);
|
||||
|
||||
if (meta_error_trap_pop_with_return (display) != Success)
|
||||
{
|
||||
/* Probably a BadMatch if the window isn't viewable; we could
|
||||
* GrabServer/GetWindowAttributes/NameWindowPixmap/UngrabServer/Sync
|
||||
* to avoid this, but there's no reason to take two round trips
|
||||
* when one will do. (We need that Sync if we want to handle failures
|
||||
* for any reason other than !viewable. That's unlikely, but maybe
|
||||
* we'll BadAlloc or something.)
|
||||
*/
|
||||
priv->back_pixmap = None;
|
||||
}
|
||||
|
||||
if (priv->back_pixmap == None)
|
||||
{
|
||||
meta_verbose ("Unable to get named pixmap for %p\n", self);
|
||||
goto out;
|
||||
}
|
||||
|
||||
texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, priv->back_pixmap, FALSE, NULL));
|
||||
if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture))))
|
||||
g_warning ("NOTE: Not using GLX TFP!\n");
|
||||
|
||||
meta_surface_actor_set_texture (META_SURFACE_ACTOR (priv->surface), texture);
|
||||
}
|
||||
|
||||
priv->needs_pixmap = FALSE;
|
||||
|
||||
out:
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
static void
|
||||
check_needs_shadow (MetaWindowActor *self)
|
||||
{
|
||||
@@ -1496,12 +1815,61 @@ meta_window_actor_process_x11_damage (MetaWindowActor *self,
|
||||
XDamageNotifyEvent *event)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (priv->screen);
|
||||
gboolean redraw_queued;
|
||||
|
||||
meta_surface_actor_process_damage (priv->surface,
|
||||
event->area.x,
|
||||
event->area.y,
|
||||
event->area.width,
|
||||
event->area.height);
|
||||
priv->received_x11_damage = TRUE;
|
||||
|
||||
if (meta_window_is_fullscreen (priv->window) && g_list_last (info->windows)->data == self && !priv->unredirected)
|
||||
{
|
||||
MetaRectangle window_rect;
|
||||
meta_window_get_frame_rect (priv->window, &window_rect);
|
||||
|
||||
if (window_rect.x == event->area.x &&
|
||||
window_rect.y == event->area.y &&
|
||||
window_rect.width == event->area.width &&
|
||||
window_rect.height == event->area.height)
|
||||
priv->full_damage_frames_count++;
|
||||
else
|
||||
priv->full_damage_frames_count = 0;
|
||||
|
||||
if (priv->full_damage_frames_count >= 100)
|
||||
priv->does_full_damage = TRUE;
|
||||
}
|
||||
|
||||
/* Drop damage event for unredirected windows */
|
||||
if (priv->unredirected)
|
||||
return;
|
||||
|
||||
if (is_frozen (self))
|
||||
{
|
||||
/* The window is frozen due to an effect in progress: we ignore damage
|
||||
* here on the off chance that this will stop the corresponding
|
||||
* texture_from_pixmap from being update.
|
||||
*
|
||||
* needs_damage_all tracks that some unknown damage happened while the
|
||||
* window was frozen so that when the window becomes unfrozen we can
|
||||
* issue a full window update to cover any lost damage.
|
||||
*
|
||||
* It should be noted that this is an unreliable mechanism since it's
|
||||
* quite likely that drivers will aim to provide a zero-copy
|
||||
* implementation of the texture_from_pixmap extension and in those cases
|
||||
* any drawing done to the window is always immediately reflected in the
|
||||
* texture regardless of damage event handling.
|
||||
*/
|
||||
priv->needs_damage_all = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (priv->needs_pixmap)
|
||||
return;
|
||||
|
||||
redraw_queued = meta_surface_actor_damage_area (priv->surface,
|
||||
event->area.x,
|
||||
event->area.y,
|
||||
event->area.width,
|
||||
event->area.height);
|
||||
priv->repaint_scheduled = priv->repaint_scheduled || redraw_queued;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1729,9 +2097,8 @@ meta_window_actor_update_opaque_region (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
cairo_region_t *opaque_region;
|
||||
gboolean argb32 = is_argb32 (self);
|
||||
|
||||
if (argb32 && priv->window->opaque_region != NULL)
|
||||
if (priv->argb32 && priv->window->opaque_region != NULL)
|
||||
{
|
||||
MetaFrameBorders borders;
|
||||
|
||||
@@ -1751,7 +2118,7 @@ meta_window_actor_update_opaque_region (MetaWindowActor *self)
|
||||
cairo_region_translate (opaque_region, borders.total.left, borders.total.top);
|
||||
cairo_region_intersect (opaque_region, priv->shape_region);
|
||||
}
|
||||
else if (argb32)
|
||||
else if (priv->argb32)
|
||||
opaque_region = NULL;
|
||||
else
|
||||
opaque_region = cairo_region_reference (priv->shape_region);
|
||||
@@ -1808,6 +2175,9 @@ static void
|
||||
meta_window_actor_handle_updates (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
MetaScreen *screen = priv->screen;
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
|
||||
if (is_frozen (self))
|
||||
{
|
||||
@@ -1816,13 +2186,45 @@ meta_window_actor_handle_updates (MetaWindowActor *self)
|
||||
return;
|
||||
}
|
||||
|
||||
if (meta_surface_actor_is_unredirected (priv->surface))
|
||||
return;
|
||||
if (!meta_is_wayland_compositor ())
|
||||
{
|
||||
if (priv->unredirected)
|
||||
{
|
||||
/* Nothing to do here until/if the window gets redirected again */
|
||||
return;
|
||||
}
|
||||
|
||||
meta_surface_actor_pre_paint (priv->surface);
|
||||
if (priv->received_x11_damage)
|
||||
{
|
||||
meta_error_trap_push (display);
|
||||
XDamageSubtract (xdisplay, priv->damage, None, None);
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
if (!meta_surface_actor_is_visible (priv->surface))
|
||||
return;
|
||||
/* We need to make sure that any X drawing that happens before the
|
||||
* XDamageSubtract() above is visible to subsequent GL rendering;
|
||||
* the only standardized way to do this is EXT_x11_sync_object,
|
||||
* which isn't yet widely available. For now, we count on details
|
||||
* of Xorg and the open source drivers, and hope for the best
|
||||
* otherwise.
|
||||
*
|
||||
* Xorg and open source driver specifics:
|
||||
*
|
||||
* The X server makes sure to flush drawing to the kernel before
|
||||
* sending out damage events, but since we use DamageReportBoundingBox
|
||||
* there may be drawing between the last damage event and the
|
||||
* XDamageSubtract() that needs to be flushed as well.
|
||||
*
|
||||
* Xorg always makes sure that drawing is flushed to the kernel
|
||||
* before writing events or responses to the client, so any round trip
|
||||
* request at this point is sufficient to flush the GLX buffers.
|
||||
*/
|
||||
XSync (xdisplay, False);
|
||||
|
||||
priv->received_x11_damage = FALSE;
|
||||
}
|
||||
|
||||
check_needs_x11_pixmap (self);
|
||||
}
|
||||
|
||||
check_needs_reshape (self);
|
||||
check_needs_shadow (self);
|
||||
@@ -2011,16 +2413,20 @@ void
|
||||
meta_window_actor_set_updates_frozen (MetaWindowActor *self,
|
||||
gboolean updates_frozen)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
|
||||
updates_frozen = updates_frozen != FALSE;
|
||||
|
||||
if (priv->updates_frozen != updates_frozen)
|
||||
/* On wayland we shouldn't need to ever freeze updates... */
|
||||
if (!meta_is_wayland_compositor ())
|
||||
{
|
||||
priv->updates_frozen = updates_frozen;
|
||||
if (updates_frozen)
|
||||
meta_window_actor_freeze (self);
|
||||
else
|
||||
meta_window_actor_thaw (self);
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
|
||||
updates_frozen = updates_frozen != FALSE;
|
||||
|
||||
if (priv->updates_frozen != updates_frozen)
|
||||
{
|
||||
priv->updates_frozen = updates_frozen;
|
||||
if (updates_frozen)
|
||||
meta_window_actor_freeze (self);
|
||||
else
|
||||
meta_window_actor_thaw (self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -164,6 +164,19 @@ meta_window_group_paint (ClutterActor *actor)
|
||||
paint_y_offset = paint_y_origin - actor_y_origin;
|
||||
cairo_region_translate (clip_region, -paint_x_offset, -paint_y_offset);
|
||||
|
||||
if (!meta_is_wayland_compositor ())
|
||||
{
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (window_group->screen);
|
||||
if (info->unredirected_window != NULL)
|
||||
{
|
||||
cairo_rectangle_int_t unredirected_rect;
|
||||
|
||||
meta_window_get_frame_rect (info->unredirected_window, (MetaRectangle *)&unredirected_rect);
|
||||
cairo_region_subtract_rectangle (unobscured_region, &unredirected_rect);
|
||||
cairo_region_subtract_rectangle (clip_region, &unredirected_rect);
|
||||
}
|
||||
}
|
||||
|
||||
meta_cullable_cull_out (META_CULLABLE (window_group), unobscured_region, clip_region);
|
||||
|
||||
cairo_region_destroy (unobscured_region);
|
||||
|
@@ -73,7 +73,6 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "meta-xwayland-private.h"
|
||||
#include "meta-surface-actor-wayland.h"
|
||||
|
||||
#define GRAB_OP_IS_WINDOW_SWITCH(g) \
|
||||
(g == META_GRAB_OP_KEYBOARD_TABBING_NORMAL || \
|
||||
@@ -1683,12 +1682,8 @@ get_window_for_event (MetaDisplay *display,
|
||||
return display->grab_window;
|
||||
|
||||
source = clutter_event_get_source (event);
|
||||
if (META_IS_SURFACE_ACTOR_WAYLAND (source))
|
||||
{
|
||||
MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (META_SURFACE_ACTOR_WAYLAND (source));
|
||||
g_assert (surface != NULL);
|
||||
return surface->window;
|
||||
}
|
||||
if (META_IS_WINDOW_ACTOR (source))
|
||||
return meta_window_actor_get_meta_window (META_WINDOW_ACTOR (source));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -4985,7 +4980,7 @@ meta_display_ping_window (MetaWindow *window,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!window->can_ping)
|
||||
if (!window->net_wm_ping)
|
||||
{
|
||||
if (ping_reply_func)
|
||||
(* ping_reply_func) (window, timestamp, user_data);
|
||||
|
@@ -343,8 +343,7 @@ meta_select_display (char *display_arg)
|
||||
else
|
||||
display_name = g_getenv ("MUTTER_DISPLAY");
|
||||
|
||||
if (display_name)
|
||||
g_setenv ("DISPLAY", display_name, TRUE);
|
||||
g_setenv ("DISPLAY", display_name, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -238,7 +238,7 @@ struct _MetaWindow
|
||||
/* These are the flags from WM_PROTOCOLS */
|
||||
guint take_focus : 1;
|
||||
guint delete_window : 1;
|
||||
guint can_ping : 1;
|
||||
guint net_wm_ping : 1;
|
||||
/* Globally active / No input */
|
||||
guint input : 1;
|
||||
|
||||
|
@@ -1407,7 +1407,7 @@ reload_wm_protocols (MetaWindow *window,
|
||||
|
||||
window->take_focus = FALSE;
|
||||
window->delete_window = FALSE;
|
||||
window->can_ping = FALSE;
|
||||
window->net_wm_ping = FALSE;
|
||||
|
||||
if (value->type == META_PROP_VALUE_INVALID)
|
||||
return;
|
||||
@@ -1423,7 +1423,7 @@ reload_wm_protocols (MetaWindow *window,
|
||||
window->delete_window = TRUE;
|
||||
else if (value->v.atom_list.atoms[i] ==
|
||||
window->display->atom__NET_WM_PING)
|
||||
window->can_ping = TRUE;
|
||||
window->net_wm_ping = TRUE;
|
||||
++i;
|
||||
}
|
||||
|
||||
|
@@ -874,7 +874,7 @@ _meta_window_shared_new (MetaDisplay *display,
|
||||
window->user_time_window = None;
|
||||
window->take_focus = FALSE;
|
||||
window->delete_window = FALSE;
|
||||
window->can_ping = FALSE;
|
||||
window->net_wm_ping = FALSE;
|
||||
window->input = TRUE;
|
||||
window->calc_placement = FALSE;
|
||||
window->shaken_loose = FALSE;
|
||||
@@ -1320,7 +1320,6 @@ meta_window_wayland_new (MetaDisplay *display,
|
||||
WithdrawnState,
|
||||
META_COMP_EFFECT_CREATE,
|
||||
&attrs);
|
||||
window->can_ping = TRUE;
|
||||
|
||||
meta_error_trap_pop (display); /* pop the XSync()-reducing trap */
|
||||
|
||||
@@ -3117,6 +3116,9 @@ meta_window_maximize_internal (MetaWindow *window,
|
||||
meta_window_recalc_features (window);
|
||||
set_net_wm_state (window);
|
||||
|
||||
if (window->surface && window->maximized_horizontally && window->maximized_vertically)
|
||||
meta_wayland_surface_send_maximized (window->surface);
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (window));
|
||||
g_object_notify (G_OBJECT (window), "maximized-horizontally");
|
||||
g_object_notify (G_OBJECT (window), "maximized-vertically");
|
||||
@@ -3602,10 +3604,13 @@ meta_window_unmaximize_internal (MetaWindow *window,
|
||||
set_net_wm_state (window);
|
||||
}
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (window));
|
||||
g_object_notify (G_OBJECT (window), "maximized-horizontally");
|
||||
g_object_notify (G_OBJECT (window), "maximized-vertically");
|
||||
g_object_thaw_notify (G_OBJECT (window));
|
||||
if (window->surface && !window->maximized_horizontally && !window->maximized_vertically)
|
||||
meta_wayland_surface_send_unmaximized (window->surface);
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (window));
|
||||
g_object_notify (G_OBJECT (window), "maximized-horizontally");
|
||||
g_object_notify (G_OBJECT (window), "maximized-vertically");
|
||||
g_object_thaw_notify (G_OBJECT (window));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -3708,6 +3713,9 @@ meta_window_make_fullscreen_internal (MetaWindow *window)
|
||||
/* For the auto-minimize feature, if we fail to get focus */
|
||||
meta_screen_queue_check_fullscreen (window->screen);
|
||||
|
||||
if (window->surface)
|
||||
meta_wayland_surface_send_fullscreened (window->surface);
|
||||
|
||||
g_object_notify (G_OBJECT (window), "fullscreen");
|
||||
}
|
||||
}
|
||||
@@ -3764,6 +3772,9 @@ meta_window_unmake_fullscreen (MetaWindow *window)
|
||||
|
||||
meta_window_update_layer (window);
|
||||
|
||||
if (window->surface)
|
||||
meta_wayland_surface_send_unfullscreened (window->surface);
|
||||
|
||||
g_object_notify (G_OBJECT (window), "fullscreen");
|
||||
}
|
||||
}
|
||||
@@ -6360,14 +6371,6 @@ meta_window_appears_focused_changed (MetaWindow *window)
|
||||
|
||||
if (window->frame)
|
||||
meta_frame_queue_draw (window->frame);
|
||||
|
||||
if (window->surface)
|
||||
{
|
||||
if (meta_window_appears_focused (window))
|
||||
meta_wayland_surface_activated (window->surface);
|
||||
else
|
||||
meta_wayland_surface_deactivated (window->surface);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -75,6 +75,9 @@ CoglTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex);
|
||||
|
||||
void meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex,
|
||||
CoglTexture *mask_texture);
|
||||
void meta_shaped_texture_set_input_shape_region (MetaShapedTexture *stex,
|
||||
cairo_region_t *shape_region);
|
||||
|
||||
void meta_shaped_texture_set_opaque_region (MetaShapedTexture *stex,
|
||||
cairo_region_t *opaque_region);
|
||||
|
||||
|
@@ -60,6 +60,14 @@
|
||||
|
||||
#include "meta-wayland-private.h"
|
||||
|
||||
static MetaWaylandSeat *
|
||||
meta_wayland_keyboard_get_seat (MetaWaylandKeyboard *keyboard)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_container_of (keyboard, seat, keyboard);
|
||||
|
||||
return seat;
|
||||
}
|
||||
|
||||
static int
|
||||
create_anonymous_file (off_t size,
|
||||
GError **error)
|
||||
@@ -283,11 +291,28 @@ default_grab_modifiers (MetaWaylandKeyboardGrab *grab, uint32_t serial,
|
||||
uint32_t mods_locked, uint32_t group)
|
||||
{
|
||||
MetaWaylandKeyboard *keyboard = grab->keyboard;
|
||||
MetaWaylandSeat *seat = meta_wayland_keyboard_get_seat (keyboard);
|
||||
MetaWaylandPointer *pointer = &seat->pointer;
|
||||
struct wl_resource *resource, *pr;
|
||||
|
||||
if (keyboard->focus_resource)
|
||||
resource = keyboard->focus_resource;
|
||||
if (!resource)
|
||||
return;
|
||||
|
||||
wl_keyboard_send_modifiers (resource, serial, mods_depressed,
|
||||
mods_latched, mods_locked, group);
|
||||
|
||||
if (pointer && pointer->focus_surface && pointer->focus_surface != keyboard->focus_surface)
|
||||
{
|
||||
wl_keyboard_send_modifiers (keyboard->focus_resource, serial, mods_depressed,
|
||||
mods_latched, mods_locked, group);
|
||||
pr = find_resource_for_surface (&keyboard->resource_list, pointer->focus_surface);
|
||||
if (pr)
|
||||
{
|
||||
wl_keyboard_send_modifiers (pr, serial,
|
||||
mods_depressed,
|
||||
mods_latched,
|
||||
mods_locked,
|
||||
group);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,65 +527,72 @@ void
|
||||
meta_wayland_keyboard_set_focus (MetaWaylandKeyboard *keyboard,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
uint32_t serial;
|
||||
|
||||
if (keyboard->focus_surface == surface && keyboard->focus_resource != NULL)
|
||||
return;
|
||||
|
||||
if (keyboard->focus_surface != NULL)
|
||||
resource = keyboard->focus_resource;
|
||||
if (resource)
|
||||
{
|
||||
if (keyboard->focus_resource)
|
||||
if (keyboard->focus_surface->resource)
|
||||
{
|
||||
if (keyboard->focus_surface->resource)
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (keyboard->focus_resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
uint32_t serial = wl_display_next_serial (display);
|
||||
wl_keyboard_send_leave (keyboard->focus_resource, serial, keyboard->focus_surface->resource);
|
||||
}
|
||||
struct wl_client *client = wl_resource_get_client (resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
serial = wl_display_next_serial (display);
|
||||
wl_keyboard_send_leave (resource, serial, keyboard->focus_surface->resource);
|
||||
|
||||
wl_list_remove (&keyboard->focus_resource_listener.link);
|
||||
keyboard->focus_resource = NULL;
|
||||
meta_wayland_surface_deactivated (keyboard->focus_surface);
|
||||
}
|
||||
|
||||
wl_list_remove (&keyboard->focus_resource_listener.link);
|
||||
wl_list_remove (&keyboard->focus_surface_listener.link);
|
||||
|
||||
keyboard->focus_resource = NULL;
|
||||
keyboard->focus_surface = NULL;
|
||||
}
|
||||
|
||||
if (surface != NULL)
|
||||
resource = find_resource_for_surface (&keyboard->resource_list, surface);
|
||||
if (resource)
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
|
||||
serial = wl_display_next_serial (display);
|
||||
|
||||
/* If we're in a modal grab, the client is focused but doesn't see
|
||||
modifiers or pressed keys (and fix that up when we exit the modal) */
|
||||
if (keyboard->grab->interface == &modal_grab)
|
||||
{
|
||||
struct wl_array empty;
|
||||
wl_array_init (&empty);
|
||||
|
||||
wl_keyboard_send_modifiers (resource, serial,
|
||||
0, 0, 0, 0);
|
||||
wl_keyboard_send_enter (resource, serial, surface->resource,
|
||||
&empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
wl_keyboard_send_modifiers (resource, serial,
|
||||
keyboard->modifier_state.mods_depressed,
|
||||
keyboard->modifier_state.mods_latched,
|
||||
keyboard->modifier_state.mods_locked,
|
||||
keyboard->modifier_state.group);
|
||||
wl_keyboard_send_enter (resource, serial, surface->resource,
|
||||
&keyboard->keys);
|
||||
}
|
||||
|
||||
meta_wayland_surface_activated (surface);
|
||||
|
||||
keyboard->focus_resource = resource;
|
||||
keyboard->focus_surface = surface;
|
||||
|
||||
wl_resource_add_destroy_listener (keyboard->focus_resource, &keyboard->focus_resource_listener);
|
||||
wl_resource_add_destroy_listener (keyboard->focus_surface->resource, &keyboard->focus_surface_listener);
|
||||
|
||||
keyboard->focus_resource = find_resource_for_surface (&keyboard->resource_list, surface);
|
||||
if (keyboard->focus_resource)
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (keyboard->focus_resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
uint32_t serial = wl_display_next_serial (display);
|
||||
|
||||
/* If we're in a modal grab, the client is focused but doesn't see
|
||||
modifiers or pressed keys (and fix that up when we exit the modal) */
|
||||
if (keyboard->grab->interface == &modal_grab)
|
||||
{
|
||||
struct wl_array empty;
|
||||
wl_array_init (&empty);
|
||||
|
||||
wl_keyboard_send_modifiers (keyboard->focus_resource, serial, 0, 0, 0, 0);
|
||||
wl_keyboard_send_enter (keyboard->focus_resource, serial, keyboard->focus_surface->resource, &empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
wl_keyboard_send_modifiers (keyboard->focus_resource, serial,
|
||||
keyboard->modifier_state.mods_depressed,
|
||||
keyboard->modifier_state.mods_latched,
|
||||
keyboard->modifier_state.mods_locked,
|
||||
keyboard->modifier_state.group);
|
||||
wl_keyboard_send_enter (keyboard->focus_resource, serial, keyboard->focus_surface->resource,
|
||||
&keyboard->keys);
|
||||
}
|
||||
|
||||
wl_resource_add_destroy_listener (keyboard->focus_resource, &keyboard->focus_resource_listener);
|
||||
keyboard->focus_serial = serial;
|
||||
}
|
||||
keyboard->focus_serial = serial;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -55,6 +55,14 @@
|
||||
|
||||
static void meta_wayland_pointer_end_popup_grab (MetaWaylandPointer *pointer);
|
||||
|
||||
static MetaWaylandSeat *
|
||||
meta_wayland_pointer_get_seat (MetaWaylandPointer *pointer)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_container_of (pointer, seat, pointer);
|
||||
|
||||
return seat;
|
||||
}
|
||||
|
||||
static void
|
||||
release_focus (MetaWaylandPointer *pointer)
|
||||
{
|
||||
@@ -323,57 +331,70 @@ void
|
||||
meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
MetaWaylandSeat *seat = meta_wayland_pointer_get_seat (pointer);
|
||||
MetaWaylandKeyboard *kbd = &seat->keyboard;
|
||||
struct wl_resource *resource, *kr;
|
||||
uint32_t serial;
|
||||
|
||||
if (pointer->focus_surface == surface && pointer->focus_resource != NULL)
|
||||
return;
|
||||
|
||||
if (pointer->focus_surface)
|
||||
resource = pointer->focus_resource;
|
||||
if (resource)
|
||||
{
|
||||
if (pointer->focus_resource)
|
||||
if (pointer->focus_surface->resource)
|
||||
{
|
||||
if (pointer->focus_surface->resource)
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (pointer->focus_resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
uint32_t serial = wl_display_next_serial (display);
|
||||
wl_pointer_send_leave (pointer->focus_resource, serial, pointer->focus_surface->resource);
|
||||
}
|
||||
|
||||
wl_list_remove (&pointer->focus_resource_listener.link);
|
||||
pointer->focus_resource = NULL;
|
||||
struct wl_client *client = wl_resource_get_client (resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
serial = wl_display_next_serial (display);
|
||||
wl_pointer_send_leave (resource, serial, pointer->focus_surface->resource);
|
||||
}
|
||||
|
||||
wl_list_remove (&pointer->focus_surface_listener.link);
|
||||
wl_list_remove (&pointer->focus_resource_listener.link);
|
||||
|
||||
pointer->focus_surface = NULL;
|
||||
pointer->focus_resource = NULL;
|
||||
}
|
||||
|
||||
if (surface != NULL)
|
||||
resource = find_resource_for_surface (&pointer->resource_list, surface);
|
||||
if (resource)
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
wl_fixed_t sx, sy;
|
||||
|
||||
serial = wl_display_next_serial (display);
|
||||
|
||||
if (kbd)
|
||||
{
|
||||
kr = find_resource_for_surface (&kbd->resource_list, surface);
|
||||
if (kr)
|
||||
{
|
||||
wl_keyboard_send_modifiers (kr,
|
||||
serial,
|
||||
kbd->modifier_state.mods_depressed,
|
||||
kbd->modifier_state.mods_latched,
|
||||
kbd->modifier_state.mods_locked,
|
||||
kbd->modifier_state.group);
|
||||
}
|
||||
}
|
||||
|
||||
meta_wayland_pointer_get_relative_coordinates (pointer, surface, &sx, &sy);
|
||||
meta_window_handle_enter (surface->window,
|
||||
/* XXX -- can we reliably get a timestamp for setting focus? */
|
||||
clutter_get_current_event_time (),
|
||||
wl_fixed_to_int (pointer->x),
|
||||
wl_fixed_to_int (pointer->y));
|
||||
wl_pointer_send_enter (resource, serial, surface->resource, sx, sy);
|
||||
|
||||
pointer->focus_resource = resource;
|
||||
pointer->focus_surface = surface;
|
||||
|
||||
wl_resource_add_destroy_listener (pointer->focus_resource, &pointer->focus_resource_listener);
|
||||
wl_resource_add_destroy_listener (pointer->focus_surface->resource, &pointer->focus_surface_listener);
|
||||
|
||||
pointer->focus_resource = find_resource_for_surface (&pointer->resource_list, surface);
|
||||
if (pointer->focus_resource)
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (pointer->focus_resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
uint32_t serial = wl_display_next_serial (display);
|
||||
|
||||
meta_window_handle_enter (pointer->focus_surface->window,
|
||||
/* XXX -- can we reliably get a timestamp for setting focus? */
|
||||
clutter_get_current_event_time (),
|
||||
wl_fixed_to_int (pointer->x),
|
||||
wl_fixed_to_int (pointer->y));
|
||||
|
||||
{
|
||||
wl_fixed_t sx, sy;
|
||||
|
||||
meta_wayland_pointer_get_relative_coordinates (pointer, pointer->focus_surface, &sx, &sy);
|
||||
wl_pointer_send_enter (pointer->focus_resource, serial, pointer->focus_surface->resource, sx, sy);
|
||||
}
|
||||
|
||||
wl_resource_add_destroy_listener (pointer->focus_resource, &pointer->focus_resource_listener);
|
||||
pointer->focus_serial = serial;
|
||||
}
|
||||
pointer->focus_serial = serial;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -38,7 +38,6 @@
|
||||
#include "meta-shaped-texture-private.h"
|
||||
#include "meta-wayland-stage.h"
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
#include "meta-surface-actor-wayland.h"
|
||||
|
||||
#define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int (10)
|
||||
|
||||
@@ -421,8 +420,13 @@ meta_wayland_seat_repick (MetaWaylandSeat *seat,
|
||||
else
|
||||
seat->current_stage = NULL;
|
||||
|
||||
if (META_IS_SURFACE_ACTOR_WAYLAND (actor))
|
||||
surface = meta_surface_actor_wayland_get_surface (META_SURFACE_ACTOR_WAYLAND (actor));
|
||||
if (META_IS_WINDOW_ACTOR (actor))
|
||||
{
|
||||
MetaWindow *window =
|
||||
meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor));
|
||||
|
||||
surface = window->surface;
|
||||
}
|
||||
|
||||
pointer->current = surface;
|
||||
if (surface != pointer->focus_surface)
|
||||
|
@@ -44,11 +44,11 @@
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-xwayland-private.h"
|
||||
#include "meta-wayland-stage.h"
|
||||
#include "meta-surface-actor.h"
|
||||
#include "meta-wayland-seat.h"
|
||||
#include "meta-wayland-keyboard.h"
|
||||
#include "meta-wayland-pointer.h"
|
||||
#include "meta-wayland-data-device.h"
|
||||
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
#include "display-private.h"
|
||||
#include "window-private.h"
|
||||
@@ -58,9 +58,6 @@
|
||||
#include "meta-idle-monitor-private.h"
|
||||
#include "monitor-private.h"
|
||||
|
||||
#include "meta-surface-actor.h"
|
||||
#include "meta-surface-actor-wayland.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE,
|
||||
@@ -117,8 +114,8 @@ surface_process_damage (MetaWaylandSurface *surface,
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
meta_surface_actor_process_damage (surface->surface_actor,
|
||||
rect.x, rect.y, rect.width, rect.height);
|
||||
meta_surface_actor_damage_area (surface->surface_actor,
|
||||
rect.x, rect.y, rect.width, rect.height);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,6 +273,8 @@ ensure_buffer_texture (MetaWaylandBuffer *buffer)
|
||||
}
|
||||
|
||||
buffer->texture = texture;
|
||||
buffer->width = cogl_texture_get_width (texture);
|
||||
buffer->height = cogl_texture_get_height (texture);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -298,7 +297,7 @@ actor_surface_commit (MetaWaylandSurface *surface,
|
||||
if (buffer_changed)
|
||||
{
|
||||
ensure_buffer_texture (buffer);
|
||||
meta_surface_actor_wayland_set_buffer (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor), buffer);
|
||||
meta_surface_actor_attach_wayland_buffer (surface_actor, buffer);
|
||||
}
|
||||
|
||||
surface_process_damage (surface, pending->damage);
|
||||
@@ -325,11 +324,11 @@ toplevel_surface_commit (MetaWaylandSurface *surface,
|
||||
/* We resize X based surfaces according to X events */
|
||||
if (buffer != NULL && window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
|
||||
{
|
||||
int new_width, new_height;
|
||||
|
||||
new_width = cogl_texture_get_width (buffer->texture);
|
||||
new_height = cogl_texture_get_height (buffer->texture);
|
||||
int new_width;
|
||||
int new_height;
|
||||
|
||||
new_width = surface->buffer->width;
|
||||
new_height = surface->buffer->height;
|
||||
if (new_width != window->rect.width ||
|
||||
new_height != window->rect.height ||
|
||||
pending->dx != 0 ||
|
||||
@@ -340,22 +339,6 @@ toplevel_surface_commit (MetaWaylandSurface *surface,
|
||||
|
||||
if (pending->frame_extents_changed)
|
||||
meta_window_set_custom_frame_extents (surface->window, &pending->frame_extents);
|
||||
|
||||
if (pending->maximized.changed)
|
||||
{
|
||||
if (pending->maximized.value)
|
||||
meta_window_maximize (surface->window, META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
|
||||
else
|
||||
meta_window_unmaximize (surface->window, META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
|
||||
}
|
||||
|
||||
if (pending->fullscreen.changed)
|
||||
{
|
||||
if (pending->fullscreen.value)
|
||||
meta_window_make_fullscreen (surface->window);
|
||||
else
|
||||
meta_window_unmake_fullscreen (surface->window);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -381,8 +364,6 @@ double_buffered_state_init (MetaWaylandDoubleBufferedState *state)
|
||||
wl_list_init (&state->frame_callback_list);
|
||||
|
||||
state->frame_extents_changed = FALSE;
|
||||
state->maximized.changed = FALSE;
|
||||
state->fullscreen.changed = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -597,14 +578,11 @@ meta_wayland_surface_window_unmanaged (MetaWaylandSurface *surface)
|
||||
static void
|
||||
destroy_window (MetaWaylandSurface *surface)
|
||||
{
|
||||
if (surface->window)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
guint32 timestamp = meta_display_get_current_time_roundtrip (display);
|
||||
|
||||
meta_window_unmanage (surface->window, timestamp);
|
||||
}
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
guint32 timestamp = meta_display_get_current_time_roundtrip (display);
|
||||
|
||||
g_assert (surface->window != NULL);
|
||||
meta_window_unmanage (surface->window, timestamp);
|
||||
g_assert (surface->window == NULL);
|
||||
}
|
||||
|
||||
@@ -614,17 +592,18 @@ wl_surface_destructor (struct wl_resource *resource)
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandCompositor *compositor = surface->compositor;
|
||||
|
||||
/* If we still have a window at the time of destruction, that means that
|
||||
* the client is disconnecting, as the resources are destroyed in a random
|
||||
* order. Simply destroy the window in this case. */
|
||||
if (surface->window)
|
||||
destroy_window (surface);
|
||||
/* At the time when the wl_surface is destroyed, we should
|
||||
* no longer have a window, unless we're an XWayland window
|
||||
* in which case we received the wl_surface.destroy before
|
||||
* the UnmapNotify/DestroyNotify. */
|
||||
g_assert (surface->window == NULL || surface->window->client_type == META_WINDOW_CLIENT_TYPE_X11);
|
||||
|
||||
compositor->surfaces = g_list_remove (compositor->surfaces, surface);
|
||||
|
||||
surface_set_buffer (surface, NULL);
|
||||
double_buffered_state_destroy (&surface->pending);
|
||||
|
||||
clutter_actor_destroy (CLUTTER_ACTOR (surface->surface_actor));
|
||||
g_object_unref (surface->surface_actor);
|
||||
|
||||
if (surface->resource)
|
||||
@@ -648,8 +627,7 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
|
||||
wl_resource_set_implementation (surface->resource, &meta_wayland_surface_interface, surface, wl_surface_destructor);
|
||||
|
||||
surface->buffer_destroy_listener.notify = surface_handle_buffer_destroy;
|
||||
surface->surface_actor = g_object_ref_sink (meta_surface_actor_wayland_new (surface));
|
||||
clutter_actor_set_reactive (CLUTTER_ACTOR (surface->surface_actor), TRUE);
|
||||
surface->surface_actor = g_object_ref_sink (meta_surface_actor_new ());
|
||||
|
||||
double_buffered_state_init (&surface->pending);
|
||||
|
||||
@@ -891,47 +869,45 @@ xdg_surface_set_output (struct wl_client *client,
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_surface_set_fullscreen (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
xdg_surface_request_change_state (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
uint32_t state_type,
|
||||
uint32_t value,
|
||||
uint32_t serial)
|
||||
{
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
|
||||
surface->pending.fullscreen.changed = TRUE;
|
||||
surface->pending.fullscreen.value = TRUE;
|
||||
surface->state_changed_serial = serial;
|
||||
|
||||
switch (state_type)
|
||||
{
|
||||
case XDG_SURFACE_STATE_TYPE_MAXIMIZED:
|
||||
if (value)
|
||||
meta_window_maximize (surface->window, META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
|
||||
else
|
||||
meta_window_unmaximize (surface->window, META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL);
|
||||
break;
|
||||
case XDG_SURFACE_STATE_TYPE_FULLSCREEN:
|
||||
if (value)
|
||||
meta_window_make_fullscreen (surface->window);
|
||||
else
|
||||
meta_window_unmake_fullscreen (surface->window);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_surface_unset_fullscreen (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
xdg_surface_ack_change_state (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
uint32_t state_type,
|
||||
uint32_t value,
|
||||
uint32_t serial)
|
||||
{
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
|
||||
surface->pending.fullscreen.changed = TRUE;
|
||||
surface->pending.fullscreen.value = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_surface_set_maximized (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
|
||||
surface->pending.maximized.changed = TRUE;
|
||||
surface->pending.maximized.value = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_surface_unset_maximized (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurfaceExtension *xdg_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = wl_container_of (xdg_surface, surface, xdg_surface);
|
||||
|
||||
surface->pending.maximized.changed = TRUE;
|
||||
surface->pending.maximized.value = FALSE;
|
||||
/* Do nothing for now. In the future, we'd imagine that
|
||||
* we'd ignore attaches when we have a state pending that
|
||||
* we haven't had the client ACK'd, to prevent a race
|
||||
* condition when we have an in-flight attach when the
|
||||
* client gets the new state. */
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -953,10 +929,8 @@ static const struct xdg_surface_interface meta_wayland_xdg_surface_interface = {
|
||||
xdg_surface_move,
|
||||
xdg_surface_resize,
|
||||
xdg_surface_set_output,
|
||||
xdg_surface_set_fullscreen,
|
||||
xdg_surface_unset_fullscreen,
|
||||
xdg_surface_set_maximized,
|
||||
xdg_surface_unset_maximized,
|
||||
xdg_surface_request_change_state,
|
||||
xdg_surface_ack_change_state,
|
||||
xdg_surface_set_minimized,
|
||||
};
|
||||
|
||||
@@ -1019,10 +993,13 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
|
||||
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
|
||||
MetaWaylandSurface *parent_surf = wl_resource_get_user_data (parent_resource);
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
||||
MetaRectangle parent_rect;
|
||||
|
||||
if (parent_surf == NULL || parent_surf->window == NULL)
|
||||
return;
|
||||
|
||||
meta_window_get_rect (parent_surf->window, &parent_rect);
|
||||
|
||||
if (!create_surface_extension (&surface->xdg_popup, client, surface_resource, resource, id,
|
||||
META_XDG_POPUP_VERSION,
|
||||
&xdg_popup_interface,
|
||||
@@ -1036,8 +1013,8 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
|
||||
}
|
||||
|
||||
surface->window = meta_window_wayland_new (meta_get_display (), surface);
|
||||
surface->window->rect.x = parent_surf->window->rect.x + x;
|
||||
surface->window->rect.y = parent_surf->window->rect.y + y;
|
||||
surface->window->rect.x = parent_rect.x + x;
|
||||
surface->window->rect.y = parent_rect.y + y;
|
||||
surface->window->showing_for_first_time = FALSE;
|
||||
surface->window->placed = TRUE;
|
||||
meta_window_set_transient_for (surface->window, parent_surf->window);
|
||||
@@ -1511,6 +1488,55 @@ meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
|
||||
new_width, new_height);
|
||||
}
|
||||
|
||||
static void
|
||||
send_change_state (MetaWaylandSurface *surface,
|
||||
uint32_t state_type,
|
||||
uint32_t value)
|
||||
{
|
||||
if (surface->xdg_surface.resource)
|
||||
{
|
||||
uint32_t serial;
|
||||
|
||||
if (surface->state_changed_serial != 0)
|
||||
{
|
||||
serial = surface->state_changed_serial;
|
||||
surface->state_changed_serial = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (surface->xdg_surface.resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
serial = wl_display_next_serial (display);
|
||||
}
|
||||
|
||||
xdg_surface_send_change_state (surface->xdg_surface.resource, state_type, value, serial);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_surface_send_maximized (MetaWaylandSurface *surface)
|
||||
{
|
||||
send_change_state (surface, XDG_SURFACE_STATE_TYPE_MAXIMIZED, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_surface_send_unmaximized (MetaWaylandSurface *surface)
|
||||
{
|
||||
send_change_state (surface, XDG_SURFACE_STATE_TYPE_MAXIMIZED, FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_surface_send_fullscreened (MetaWaylandSurface *surface)
|
||||
{
|
||||
send_change_state (surface, XDG_SURFACE_STATE_TYPE_FULLSCREEN, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_surface_send_unfullscreened (MetaWaylandSurface *surface)
|
||||
{
|
||||
send_change_state (surface, XDG_SURFACE_STATE_TYPE_FULLSCREEN, FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_surface_activated (MetaWaylandSurface *surface)
|
||||
{
|
||||
|
@@ -38,15 +38,10 @@ struct _MetaWaylandBuffer
|
||||
struct wl_listener destroy_listener;
|
||||
|
||||
CoglTexture *texture;
|
||||
int32_t width, height;
|
||||
uint32_t ref_count;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
guint changed : 1;
|
||||
guint value : 1;
|
||||
} MetaWaylandStateFlag;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* wl_surface.attach */
|
||||
@@ -67,9 +62,6 @@ typedef struct
|
||||
|
||||
gboolean frame_extents_changed;
|
||||
GtkBorder frame_extents;
|
||||
|
||||
MetaWaylandStateFlag fullscreen;
|
||||
MetaWaylandStateFlag maximized;
|
||||
} MetaWaylandDoubleBufferedState;
|
||||
|
||||
typedef struct
|
||||
@@ -107,6 +99,8 @@ struct _MetaWaylandSurface
|
||||
GSList *pending_placement_ops;
|
||||
} sub;
|
||||
|
||||
uint32_t state_changed_serial;
|
||||
|
||||
/* All the pending state, that wl_surface.commit will apply. */
|
||||
MetaWaylandDoubleBufferedState pending;
|
||||
};
|
||||
@@ -123,6 +117,10 @@ void meta_wayland_surface_window_unmanaged (MetaWaylandSurface *s
|
||||
void meta_wayland_surface_configure_notify (MetaWaylandSurface *surface,
|
||||
int width,
|
||||
int height);
|
||||
void meta_wayland_surface_send_maximized (MetaWaylandSurface *surface);
|
||||
void meta_wayland_surface_send_unmaximized (MetaWaylandSurface *surface);
|
||||
void meta_wayland_surface_send_fullscreened (MetaWaylandSurface *surface);
|
||||
void meta_wayland_surface_send_unfullscreened (MetaWaylandSurface *surface);
|
||||
|
||||
void meta_wayland_surface_activated (MetaWaylandSurface *surface);
|
||||
void meta_wayland_surface_deactivated (MetaWaylandSurface *surface);
|
||||
|
Reference in New Issue
Block a user