Compare commits

...

16 Commits

Author SHA1 Message Date
f61d4b4e70 Bump version to 3.37.2
Update NEWS.
2020-06-03 01:11:15 +02:00
dcb42d3b25 clutter/actor: Sanity check new allocations
Apparently some shell extensions are setting invalid NaN allocations,
leading to weird crashes like
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/1849.

Even though an implementation error like this probably deserves a crash,
those can be hard to debug since the crash can happen anywhere the
allocation is being used later. So let Clutter be the good guy and
prevent implementations from setting invalid allocations by
sanity-checking the ClutterActorBoxes using g_return_if_fail.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/1849

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1280
2020-06-02 20:53:12 +00:00
59a2bff8e2 cogl tests: Normally skip tests that are not expected to succeed
If a test is not expected to succeed, then running it could be considered
to be a waste of resources, particularly if the failure might manifest
as an indefinite hang (see cogl!11), or if the test is likely to dump core
and trigger "expensive" crash-reporting mechanisms like systemd-coredump,
corekeeper, abrt or apport.

Skip the tests that are expected to fail. They can still be requested via
an environment variable, which can be set after fixing a bug to check which
tests are now passing.

Originally cogl!15, adapted for mutter's fork of cogl to use gboolean
instead of CoglBool.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1272

Signed-off-by: Simon McVittie <smcv@debian.org>
2020-06-02 20:15:26 +00:00
720360b07a clutter/actor: Don't allocate actors if only the absolute origin changed
For actors which don't have needs_allocation set to TRUE and where the
new allocation wouldn't be different from the old one, the allocate()
vfunc doesn't have to be called. We still did this in case a parent
actor was moved though (so the absolute origin changed), because we
needed to propagate the ABSOLUTE_ORIGIN_CHANGED allocation flag down to
all actors.

Since that flag is now removed and got replaced with a private property,
we can simply notify the children about the absolute allocation change
using the existing infrastructure and safely stop allocating children at
this point.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1247
2020-06-02 19:44:42 +00:00
9b39e37fee clutter/actor: Notify hidden actors about absolute allocation changes
With commit 0eab73dc2e we introduced an optimization of not doing
allocations for actors which are hidden. This broke the propagation of
absolute origin changes to hidden actors, so if an actor is moved while
its child is hidden, the child will not get
priv->needs_compute_resource_scale set to TRUE, which means the resource
scale won't be updated when the child gets mapped and shown again.

Since we now have priv->absolute_origin_changed, we can simply check
whether that is TRUE for our parent before bailing out of
clutter_actor_allocate() and if it is, notify the whole hidden sub-tree
about the absolute origin change.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1247
2020-06-02 19:44:42 +00:00
38104755a2 clutter/stage: Make set_viewport() a static method
Since clutter_stage_set_viewport() is only used inside clutter-stage.c
anyway, we can make it a static method. Also we can remove the x and y
arguments from it since they're always set to 0 anyway.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1247
2020-06-02 19:44:42 +00:00
7abf0f1e2d clutter/stage: Set viewport without getting the last allocation
When getting the last allocation using
clutter_actor_get_allocation_box(), Clutter will do an immediate
relayout of the stage in case an actor has an invalid allocation. Since
the allocation is always invalid when the allocate() vfunc is called,
clutter_stage_allocate() always forces another allocation cycle.

To fix that, stop comparing the old allocation to the new one to find
out whether the viewport changed, but instead use the existing check in
_clutter_stage_set_viewport() and implement the behavior of rounding the
viewport to the nearest int using roundf() (which should behave just as
CLUTTER_NEARBYINT()) since we're passing around floats anyway.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1247
2020-06-02 19:44:42 +00:00
0a37c32a72 clutter/actor: Update absolute_origin_changed inside set_allocation()
When manipulating the allocation of a ClutterActor from an allocate()
vfunc override, clutter_actor_set_allocation() is used to let Clutter
know about the changes.

If the actors allocation or its absolute origin did not change before
that, this can also affect the actors absolute_origin_changed property
used by the children to detect changes to their absolute position.

So fix this bug (which luckily didn't seem to affect us so far) and set
priv->absolute_origin_changed to TRUE in case the origin changes inside
clutter_actor_set_allocation_internal(). Since this function is always
called when our allocation changes, we no longer need to update
absolute_origin_changed in clutter_actor_allocate() now.

Since a change to the absolute origin always affects the resource scale,
too, we also need to move that check from clutter_actor_allocate() here
to make sure we update the resource scale.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1247
2020-06-02 19:44:42 +00:00
9f121a211d clutter/actor: Always reset absolute_origin_changed after relayout
Since the introduction of the shallow relayout functionality it's
possible to start an allocation cycle at any point in the tree, not only
at the stage. Now when starting an allocation at an actor that's not the
stage, we'd still look at the absolute_origin_changed property of this
actors parent, which might still be set to TRUE from the parents last
allocation.

So avoid using the parents absolute_origin_changed property from the
last allocation in case a shallow relayout is being done and always
reset the absolute_origin_changed property to FALSE after the allocation
cycle.

This broke with the removal of the ABSOLUTE_ORIGIN_CHANGED
ClutterAllocationFlag that was done in commit dc8e5c7f.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1247
2020-06-02 19:44:42 +00:00
c823b5ddba renderer-native: Don't leak DMA buffer CoglFramebuffer
When we created the DMA buffer backed CoglFramebuffer, we handed it over
to CoglDmaBufHandle which took its own reference. What we failed to do
was to release our own reference to it, effectively leaking it.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1283
2020-06-02 18:39:27 +02:00
97175f8fa1 screen-cast-src: Destroy hash dmabuf table after stream
The stream will clean up the buffers, so let it do that before we
destroy them under its feet. Note that it'll only do this after the
following PipeWire commit:

    commit fbaa4ddedd84afdffca16f090dcc4b0db8ccfc29
    Author: Wim Taymans <wtaymans@redhat.com>
    Date:   Mon Jun 1 15:36:09 2020 +0200

        stream: allow NULL param and 0 buffers in disconnect

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1283
2020-06-02 18:39:23 +02:00
c5b1bdc0fe tests/stacking/restore-position: Always use wait_reconfigure
wait_reconfigure ensures that the whole configure back and forth
completes before continuing. Doing this after every state change ensures
that we always end up with the expected state, thus fixes flakyness of
the restore-position stacking test.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1279
2020-05-29 14:47:10 +00:00
f8e2234ce5 backends/native: Drop external keyboard detection for ::touch-mode
This cannot be made to work reliably. Some factoids:

- Internal devices may be connected via USB.
- The ACPI spec provides the _PLD (Physical location of device) hook to
  determine how is an USB device connected, with an anecdotal success
  rate. Internal devices may be seen as external and vice-versa, there is
  also an "unknown" value that is widely used.
- There may be non-USB keyboards, the old "AT Translated Set 2 Keyboard"
  interface does not change on hotplugging.
- Libinput has an internal series of quirks to classify keyboards as
  internal of external, also with an "unknown" value.

These heuristics are kinda hopeless to get right by our own hand. Drop
this external keyboard detection in the hope that there will be something
more deterministic to rely on in the future (e.g. the libinput quirks
made available to us directly or indirectly).

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2378
Related: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2353

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1277
2020-05-29 14:37:21 +00:00
38bbd9593b backends/x11: Implement ClutterSeat::touch-mode for the X11 backend
This only checks touchscreen availability as we have no access to
tablet-mode switch events as we do on the native backend.

Fixes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1242

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1278
2020-05-29 12:39:59 +00:00
a3cc62c285 cogl tests: Force defined behaviour for 24-bit left-shifts
When r is 128 or more, running tests compiled with the undefined behaviour
sanitizer (ubsan) reports:

test-utils.c:312:45: runtime error: left shift of 128 by 24 places cannot be represented in type 'int'

which indeed it cannot. Force the type to be unsigned 32-bit so that we
get defined behaviour.

Similarly, in test-atlas-migration, the left-shifted guint8 is promoted
to int, which again does not have enough non-sign bits available to
left-shift a value >= 128 by 24 bits. Again, force the shift to be done
in unsigned 32-bit space.

This was originally cogl!22, but applies equally to mutter's fork of cogl.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1271

Signed-off-by: Simon McVittie <smcv@debian.org>
2020-05-27 21:26:49 +00:00
c3bf10d19a cogl test-premult: Don't free texture data until CoglBitmap is freed
According to the cogl_bitmap_new_for_data documentation, the data is not
copied, so the application must keep the buffer alive for the lifetime
of the CoglBitmap. Freeing it too early led to a use-after-free in the
cogl unit tests. With that fixed, the test passes, so remove the known
failure annotation.

This AddressSanitizer trace is from the original cogl, but the bug and
fix apply equally to mutter's fork of cogl:

==6223==ERROR: AddressSanitizer: heap-use-after-free on address 0x62100001a500 at pc 0x7f3e2d4e7f4e bp 0x7ffcd9c41f30 sp 0x7ffcd9c416e0
READ of size 4096 at 0x62100001a500 thread T0
    #0 0x7f3e2d4e7f4d  (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x96f4d)
    #1 0x7f3e260c7f6b in util_copy_box ../src/gallium/auxiliary/util/u_surface.c:131
    #2 0x7f3e268c6c10 in u_default_texture_subdata ../src/gallium/auxiliary/util/u_transfer.c:67
    #3 0x7f3e26486459 in st_TexSubImage ../src/mesa/state_tracker/st_cb_texture.c:1480
    #4 0x7f3e26487029 in st_TexImage ../src/mesa/state_tracker/st_cb_texture.c:1709
    #5 0x7f3e26487029 in st_TexImage ../src/mesa/state_tracker/st_cb_texture.c:1691
    #6 0x7f3e2644bdba in teximage ../src/mesa/main/teximage.c:3105
    #7 0x7f3e2644bdba in teximage_err ../src/mesa/main/teximage.c:3132
    #8 0x7f3e2644d84f in _mesa_TexImage2D ../src/mesa/main/teximage.c:3170
    #9 0x7f3e2cd1f7df in _cogl_texture_driver_upload_to_gl driver/gl/gl/cogl-texture-driver-gl.c:347
    #10 0x7f3e2ccd441b in allocate_from_bitmap driver/gl/cogl-texture-2d-gl.c:255
    #11 0x7f3e2ccd441b in _cogl_texture_2d_gl_allocate driver/gl/cogl-texture-2d-gl.c:462
    #12 0x7f3e2ce3a6c0 in cogl_texture_allocate cogl/cogl-texture.c:1398
    #13 0x7f3e2ce3e116 in _cogl_texture_pre_paint cogl/cogl-texture.c:359
    #14 0x7f3e2cdee177 in _cogl_pipeline_layer_pre_paint cogl/cogl-pipeline-layer.c:864
    #15 0x7f3e2cd574af in _cogl_rectangles_validate_layer_cb cogl/cogl-primitives.c:542
    #16 0x7f3e2cdd742f in cogl_pipeline_foreach_layer cogl/cogl-pipeline.c:735
    #17 0x7f3e2cd5c8b0 in _cogl_framebuffer_draw_multitextured_rectangles cogl/cogl-primitives.c:658
    #18 0x7f3e2cd60152 in cogl_rectangle cogl/cogl-primitives.c:858
    #19 0x5570a71ed6a0 in check_texture tests/conform/test-premult.c:103
    #20 0x5570a71ed946 in test_premult tests/conform/test-premult.c:159
    #21 0x5570a71df0d6 in main tests/conform/test-conform-main.c:58
    #22 0x7f3e2bcd809a in __libc_start_main ../csu/libc-start.c:308
    #23 0x5570a71e0869 in _start (/home/smcv/src/debian/cogl/tests/conform/.libs/test-conformance+0x33869)

0x62100001a500 is located 0 bytes inside of 4096-byte region [0x62100001a500,0x62100001b500)
freed by thread T0 here:
    #0 0x7f3e2d5581d7 in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x1071d7)
    #1 0x5570a71ed58b in make_texture tests/conform/test-premult.c:69

previously allocated by thread T0 here:
    #0 0x7f3e2d558588 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.5+0x107588)
    #1 0x7f3e2d384500 in g_malloc ../../../glib/gmem.c:99

This was originally cogl!12.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1274

Signed-off-by: Simon McVittie <smcv@debian.org>
2020-05-27 15:50:36 +01:00
18 changed files with 232 additions and 145 deletions

27
NEWS
View File

@ -1,3 +1,30 @@
3.37.2
======
* Fix move-to-center keybinding with multiple monitors [Sergey; #1073]
* Fix stuck buttons when a virtual device is destroyed [Carlos; !1239]
* Use workarea when centering new windows [Akatsuki; #964]
* Limit mipmap levels when rendering background [Daniel; !1003]
* Broadcast clipboard/primary offers [Carlos; !1253]
* Support primary-selection protocol from wayland-protocols [Carlos; !1255]
* Fix monitor screen cast on X11 [Jonas Å.; !1251]
* Support a "blank" cursor type [Florian; !1244]
* Improve stage view damage tracking [Jonas Å.; !1237]
* Implement touch-mode detecation for the X11 backend [Carlos; !1278]
* Drop external keyboard detection from touch-mode heuristics [Carlos; !1277]
* Optimize actor allocations [Jonas D.; !1247]
* Fixed crashes [Daniel, Carlos, Jonas Å., Jonas D.; !1256, !1258, !1217, !1280]
* Misc. bug fixes and cleanups [Christian, Jonas D., Olivier, Ting-Wei,
Jonas Å., Marco, Corentin, Daniel, Robert, Niels, Florian, Simon; !1231,
!1228, !1238, !1229, !1192, !1236, !1171, !1134, #1126, !1234, !1230, !1210,
!1242, !1243, !1252, !1113, !1232, !1259, !1245, !1265, !1180, !1261, !788,
!1264, !1235, !1218, !1150, !1274, !1271, !1279, !1283, !1272]
Contributors:
Marco Trevisan (Treviño), Akatsuki, Jonas Dreßler, Olivier Fourdan,
Carlos Garnacho, Niels De Graef, Ting-Wei Lan, Robert Mader, Simon McVittie,
Florian Müllner, Corentin Noël, Christian Rauch, Daniel van Vugt,
Sergey Zigachev, Jonas Ådahl
3.37.1
======
* Fix screencasting non-maximized windows [Jonas Å.; !1174]

View File

@ -2560,6 +2560,22 @@ clutter_actor_notify_if_geometry_changed (ClutterActor *self,
g_object_thaw_notify (obj);
}
static void
absolute_allocation_changed (ClutterActor *actor)
{
actor->priv->needs_compute_resource_scale = TRUE;
}
static ClutterActorTraverseVisitFlags
absolute_allocation_changed_cb (ClutterActor *actor,
int depth,
gpointer user_data)
{
absolute_allocation_changed (actor);
return CLUTTER_ACTOR_TRAVERSE_VISIT_CONTINUE;
}
/*< private >
* clutter_actor_set_allocation_internal:
* @self: a #ClutterActor
@ -2585,6 +2601,9 @@ clutter_actor_set_allocation_internal (ClutterActor *self,
gboolean x1_changed, y1_changed, x2_changed, y2_changed;
ClutterActorBox old_alloc = { 0, };
g_return_if_fail (!isnan (box->x1) && !isnan (box->x2) &&
!isnan (box->y1) && !isnan (box->y2));
obj = G_OBJECT (self);
g_object_freeze_notify (obj);
@ -2603,6 +2622,11 @@ clutter_actor_set_allocation_internal (ClutterActor *self,
priv->needs_height_request = FALSE;
priv->needs_allocation = FALSE;
priv->absolute_origin_changed |= x1_changed || y1_changed;
if (priv->absolute_origin_changed || x2_changed || y2_changed)
absolute_allocation_changed (self);
if (x1_changed ||
y1_changed ||
x2_changed ||
@ -10094,7 +10118,6 @@ clutter_actor_allocate (ClutterActor *self,
{
ClutterActorBox old_allocation, real_allocation;
gboolean origin_changed, size_changed;
gboolean stage_allocation_changed;
ClutterActorPrivate *priv;
g_return_if_fail (CLUTTER_IS_ACTOR (self));
@ -10106,14 +10129,34 @@ clutter_actor_allocate (ClutterActor *self,
return;
}
if (!clutter_actor_is_visible (self))
return;
priv = self->priv;
priv->absolute_origin_changed = priv->parent
? priv->parent->priv->absolute_origin_changed
: FALSE;
if (!CLUTTER_ACTOR_IS_VISIBLE (self))
{
if (priv->absolute_origin_changed)
{
_clutter_actor_traverse (self,
CLUTTER_ACTOR_TRAVERSE_DEPTH_FIRST,
absolute_allocation_changed_cb,
NULL,
NULL);
}
goto out;
}
old_allocation = priv->allocation;
real_allocation = *box;
g_return_if_fail (!isnan (real_allocation.x1) &&
!isnan (real_allocation.x2) &&
!isnan (real_allocation.y1) &&
!isnan (real_allocation.y2));
/* constraints are allowed to modify the allocation only here; we do
* this prior to all the other checks so that we can bail out if the
* allocation did not change
@ -10142,49 +10185,46 @@ clutter_actor_allocate (ClutterActor *self,
size_changed = (real_allocation.x2 != old_allocation.x2 ||
real_allocation.y2 != old_allocation.y2);
priv->absolute_origin_changed = priv->parent
? priv->parent->priv->absolute_origin_changed
: FALSE;
priv->absolute_origin_changed |= origin_changed;
stage_allocation_changed = priv->absolute_origin_changed || size_changed;
/* If we get an allocation "out of the blue"
* (we did not queue relayout), then we want to
* ignore it. But if we have needs_allocation set,
* we want to guarantee that allocate() virtual
* method is always called, i.e. that queue_relayout()
* always results in an allocate() invocation on
* an actor.
/* When needs_allocation is set but we didn't move nor resize, we still
* want to call the allocate() vfunc because a child probably called
* queue_relayout() and needs a new allocation.
*
* The optimization here is to avoid re-allocating
* actors that did not queue relayout and were
* not moved.
* In case needs_allocation isn't set and we didn't move nor resize, we
* can safely stop allocating, but we need to notify the sub-tree in case
* our absolute origin changed.
*/
if (!priv->needs_allocation && !stage_allocation_changed)
if (!priv->needs_allocation && !origin_changed && !size_changed)
{
if (priv->absolute_origin_changed)
{
_clutter_actor_traverse (self,
CLUTTER_ACTOR_TRAVERSE_DEPTH_FIRST,
absolute_allocation_changed_cb,
NULL,
NULL);
}
CLUTTER_NOTE (LAYOUT, "No allocation needed");
return;
goto out;
}
if (CLUTTER_ACTOR_IS_MAPPED (self))
self->priv->needs_paint_volume_update = TRUE;
if (stage_allocation_changed)
priv->needs_compute_resource_scale = TRUE;
if (!stage_allocation_changed)
if (!origin_changed && !size_changed)
{
/* If the actor didn't move but needs_allocation is set, we just
* need to allocate the children */
* need to allocate the children (see comment above) */
clutter_actor_allocate_internal (self, &real_allocation);
return;
goto out;
}
_clutter_actor_create_transition (self, obj_props[PROP_ALLOCATION],
&priv->allocation,
&real_allocation);
out:
priv->absolute_origin_changed = FALSE;
}
/**

View File

@ -682,7 +682,6 @@ clutter_seat_warp_pointer (ClutterSeat *seat,
* requirements are fulfilled:
*
* - A touchscreen is available
* - No external keyboard is attached to the device
* - A tablet mode switch, if present, is enabled
*
* Returns: %TRUE if the device is a tablet that doesn't have an external

View File

@ -50,11 +50,6 @@ ClutterStageWindow *_clutter_stage_get_window (ClutterStage
void _clutter_stage_get_projection_matrix (ClutterStage *stage,
CoglMatrix *projection);
void _clutter_stage_dirty_projection (ClutterStage *stage);
void _clutter_stage_set_viewport (ClutterStage *stage,
float x,
float y,
float width,
float height);
void _clutter_stage_get_viewport (ClutterStage *stage,
float *x,
float *y,

View File

@ -189,6 +189,9 @@ static void capture_view_into (ClutterStage *stage,
uint8_t *data,
int stride);
static void clutter_stage_update_view_perspective (ClutterStage *stage);
static void clutter_stage_set_viewport (ClutterStage *stage,
float width,
float height);
static void clutter_container_iface_init (ClutterContainerIface *iface);
@ -619,7 +622,6 @@ clutter_stage_allocate (ClutterActor *self,
{
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
ClutterActorBox alloc = CLUTTER_ACTOR_BOX_INIT_ZERO;
float old_width, old_height;
float new_width, new_height;
float width, height;
cairo_rectangle_int_t window_size;
@ -628,10 +630,6 @@ clutter_stage_allocate (ClutterActor *self,
if (priv->impl == NULL)
return;
/* our old allocation */
clutter_actor_get_allocation_box (self, &alloc);
clutter_actor_box_get_size (&alloc, &old_width, &old_height);
/* the current allocation */
clutter_actor_box_get_size (box, &width, &height);
@ -719,27 +717,11 @@ clutter_stage_allocate (ClutterActor *self,
&override);
}
/* reset the viewport if the allocation effectively changed */
/* set the viewport to the new allocation */
clutter_actor_get_allocation_box (self, &alloc);
clutter_actor_box_get_size (&alloc, &new_width, &new_height);
if (CLUTTER_NEARBYINT (old_width) != CLUTTER_NEARBYINT (new_width) ||
CLUTTER_NEARBYINT (old_height) != CLUTTER_NEARBYINT (new_height))
{
int real_width = CLUTTER_NEARBYINT (new_width);
int real_height = CLUTTER_NEARBYINT (new_height);
_clutter_stage_set_viewport (CLUTTER_STAGE (self),
0, 0,
real_width,
real_height);
/* Note: we don't assume that set_viewport will queue a full redraw
* since it may bail-out early if something preemptively set the
* viewport before the stage was really allocated its new size.
*/
queue_full_redraw (CLUTTER_STAGE (self));
}
clutter_stage_set_viewport (CLUTTER_STAGE (self), new_width, new_height);
}
typedef struct _Vector4
@ -2257,10 +2239,7 @@ clutter_stage_init (ClutterStage *self)
g_signal_connect (self, "notify::min-height",
G_CALLBACK (clutter_stage_notify_min_size), NULL);
_clutter_stage_set_viewport (self,
0, 0,
geom.width,
geom.height);
clutter_stage_set_viewport (self, geom.width, geom.height);
priv->paint_volume_stack =
g_array_new (FALSE, FALSE, sizeof (ClutterPaintVolume));
@ -2447,8 +2426,6 @@ _clutter_stage_dirty_projection (ClutterStage *stage)
/*
* clutter_stage_set_viewport:
* @stage: A #ClutterStage
* @x: The X postition to render the stage at, in window coordinates
* @y: The Y position to render the stage at, in window coordinates
* @width: The width to render the stage at, in window coordinates
* @height: The height to render the stage at, in window coordinates
*
@ -2481,19 +2458,22 @@ _clutter_stage_dirty_projection (ClutterStage *stage)
*
* Since: 1.6
*/
void
_clutter_stage_set_viewport (ClutterStage *stage,
float x,
float y,
float width,
float height)
static void
clutter_stage_set_viewport (ClutterStage *stage,
float width,
float height)
{
ClutterStagePrivate *priv;
float x, y;
g_return_if_fail (CLUTTER_IS_STAGE (stage));
priv = stage->priv;
x = 0.f;
y = 0.f;
width = roundf (width);
height = roundf (height);
if (x == priv->viewport[0] &&
y == priv->viewport[1] &&

View File

@ -77,7 +77,7 @@ is_boolean_env_set (const char *variable)
return ret;
}
void
gboolean
test_utils_init (TestFlags requirement_flags,
TestFlags known_failure_flags)
{
@ -156,6 +156,8 @@ test_utils_init (TestFlags requirement_flags,
g_print ("WARNING: Missing required feature[s] for this test\n");
else if (known_failure)
g_print ("WARNING: Test is known to fail\n");
return (!missing_requirement && !known_failure);
}
void
@ -250,7 +252,17 @@ void
test_utils_check_pixel_rgb (CoglFramebuffer *test_fb,
int x, int y, int r, int g, int b)
{
test_utils_check_pixel (test_fb, x, y, (r << 24) | (g << 16) | (b << 8));
g_return_if_fail (r >= 0);
g_return_if_fail (g >= 0);
g_return_if_fail (b >= 0);
g_return_if_fail (r <= 0xFF);
g_return_if_fail (g <= 0xFF);
g_return_if_fail (b <= 0xFF);
test_utils_check_pixel (test_fb, x, y,
(((guint32) r) << 24) |
(((guint32) g) << 16) |
(((guint32) b) << 8));
}
void

View File

@ -68,7 +68,7 @@ typedef enum
extern CoglContext *test_ctx;
extern CoglFramebuffer *test_fb;
void
gboolean
test_utils_init (TestFlags requirement_flags,
TestFlags known_failure_flags);

View File

@ -99,9 +99,9 @@ verify_texture (CoglTexture *texture, int size)
};
test_utils_compare_pixel (p,
(real_color.red << 24) |
(real_color.green << 16) |
(real_color.blue << 8) |
(((guint32) real_color.red) << 24) |
(((guint32) real_color.green) << 16) |
(((guint32) real_color.blue) << 8) |
opacity);
g_assert_cmpint (p[3], ==, opacity);

View File

@ -15,10 +15,17 @@
G_STMT_START { \
if (strcmp (#FUNC, argv[1]) == 0) \
{ \
test_utils_init (REQUIREMENTS, KNOWN_FAIL_REQUIREMENTS); \
FUNC (); \
test_utils_fini (); \
exit (0); \
if (test_utils_init (REQUIREMENTS, KNOWN_FAIL_REQUIREMENTS) \
|| g_getenv ("COGL_TEST_TRY_EVERYTHING") != NULL) \
{ \
FUNC (); \
test_utils_fini (); \
exit (0); \
} \
else \
{ \
exit (1); \
} \
} \
} G_STMT_END
@ -55,7 +62,7 @@ main (int argc, char **argv)
ADD_TEST (test_pipeline_user_matrix, 0, 0);
ADD_TEST (test_blend_strings, 0, 0);
ADD_TEST (test_blend, 0, 0);
ADD_TEST (test_premult, 0, TEST_KNOWN_FAILURE);
ADD_TEST (test_premult, 0, 0);
UNPORTED_TEST (test_readpixels);
ADD_TEST (test_depth_test, 0, 0);
ADD_TEST (test_backface_culling, 0, TEST_REQUIREMENT_NPOT);

View File

@ -50,6 +50,7 @@ make_texture (uint32_t color,
CoglPixelFormat src_format,
MakeTextureFlags flags)
{
static CoglUserDataKey bitmap_free_key;
CoglTexture2D *tex_2d;
guchar *tex_data = gen_tex_data (color);
CoglBitmap *bmp = cogl_bitmap_new_for_data (test_ctx,
@ -58,6 +59,10 @@ make_texture (uint32_t color,
src_format,
QUAD_WIDTH * 4,
tex_data);
cogl_object_set_user_data (COGL_OBJECT (bmp),
&bitmap_free_key,
tex_data,
g_free);
tex_2d = cogl_texture_2d_new_from_bitmap (bmp);
@ -67,7 +72,6 @@ make_texture (uint32_t color,
cogl_texture_set_premultiplied (tex_2d, FALSE);
cogl_object_unref (bmp);
g_free (tex_data);
return tex_2d;
}

View File

@ -36,10 +36,16 @@ main (int argc, char **argv)
return 1;
}
test_utils_init (unit_test->requirement_flags,
unit_test->known_failure_flags);
unit_test->run ();
test_utils_fini ();
return 0;
if (test_utils_init (unit_test->requirement_flags,
unit_test->known_failure_flags)
|| g_getenv ("COGL_TEST_TRY_EVERYTHING") != NULL)
{
unit_test->run ();
test_utils_fini ();
return 0;
}
else
{
return 1;
}
}

View File

@ -1,5 +1,5 @@
project('mutter', 'c',
version: '3.37.1',
version: '3.37.2',
meson_version: '>= 0.50.0',
license: 'GPLv2+'
)

View File

@ -996,8 +996,8 @@ meta_screen_cast_stream_src_finalize (GObject *object)
if (meta_screen_cast_stream_src_is_enabled (src))
meta_screen_cast_stream_src_disable (src);
g_clear_pointer (&priv->dmabuf_handles, g_hash_table_destroy);
g_clear_pointer (&priv->pipewire_stream, pw_stream_destroy);
g_clear_pointer (&priv->dmabuf_handles, g_hash_table_destroy);
g_clear_pointer (&priv->pipewire_core, pw_core_disconnect);
g_clear_pointer (&priv->pipewire_context, pw_context_destroy);
g_source_destroy (&priv->pipewire_source->base);

View File

@ -2168,6 +2168,7 @@ meta_renderer_native_create_dma_buf (CoglRenderer *cogl_renderer,
case META_RENDERER_NATIVE_MODE_GBM:
{
CoglFramebuffer *dmabuf_fb;
CoglDmaBufHandle *dmabuf_handle;
struct gbm_bo *new_bo;
int stride;
int offset;
@ -2210,10 +2211,13 @@ meta_renderer_native_create_dma_buf (CoglRenderer *cogl_renderer,
if (!dmabuf_fb)
return NULL;
return cogl_dma_buf_handle_new (dmabuf_fb, dmabuf_fd,
width, height, stride, offset, bpp,
new_bo,
(GDestroyNotify) gbm_bo_destroy);
dmabuf_handle =
cogl_dma_buf_handle_new (dmabuf_fb, dmabuf_fd,
width, height, stride, offset, bpp,
new_bo,
(GDestroyNotify) gbm_bo_destroy);
cogl_object_unref (dmabuf_fb);
return dmabuf_handle;
}
break;
#ifdef HAVE_EGL_DEVICE

View File

@ -1380,35 +1380,6 @@ has_touchscreen (MetaSeatNative *seat)
return FALSE;
}
static gboolean
has_external_keyboard (MetaSeatNative *seat)
{
GList *devices, *l;
gboolean has_external = FALSE;
devices = g_udev_client_query_by_subsystem (seat->udev_client, "input");
for (l = devices; l; l = l->next)
{
if (!g_udev_device_has_property (l->data, "ID_INPUT_KEYBOARD"))
continue;
/* May be "hid" or something else, we don't care. This property
* will not be present in virtual "AT Translated Set 2 keyboard"
* devices.
*/
if (!g_udev_device_has_property (l->data, "ID_TYPE"))
break;
has_external = TRUE;
break;
}
g_list_free_full (devices, g_object_unref);
return has_external;
}
static void
update_touch_mode (MetaSeatNative *seat)
{
@ -1421,10 +1392,10 @@ update_touch_mode (MetaSeatNative *seat)
else if (seat->has_tablet_switch && !seat->tablet_mode_switch_state)
touch_mode = FALSE;
/* If tablet mode is enabled, or if there is no tablet mode switch
* (eg. kiosk machines), check availability of external keyboards.
* (eg. kiosk machines), assume touch-mode.
*/
else
touch_mode = !seat->has_external_keyboard;
touch_mode = TRUE;
if (seat->touch_mode != touch_mode)
{
@ -1465,12 +1436,7 @@ evdev_add_device (MetaSeatNative *seat,
g_signal_emit_by_name (seat, "device-added", device);
if (type == CLUTTER_KEYBOARD_DEVICE)
{
seat->has_external_keyboard = has_external_keyboard (seat);
check_touch_mode = TRUE;
}
else if (type == CLUTTER_TOUCHSCREEN_DEVICE)
if (type == CLUTTER_TOUCHSCREEN_DEVICE)
{
seat->has_touchscreen = TRUE;
check_touch_mode = TRUE;
@ -1503,12 +1469,7 @@ evdev_remove_device (MetaSeatNative *seat,
device_type = clutter_input_device_get_device_type (device);
if (device_type == CLUTTER_KEYBOARD_DEVICE)
{
seat->has_external_keyboard = has_external_keyboard (seat);
update_touch_mode (seat);
}
else if (device_type == CLUTTER_TOUCHSCREEN_DEVICE)
if (device_type == CLUTTER_TOUCHSCREEN_DEVICE)
{
seat->has_touchscreen = has_touchscreen (seat);
update_touch_mode (seat);
@ -2553,7 +2514,6 @@ meta_seat_native_constructed (GObject *object)
xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_SCROLL);
}
seat->has_external_keyboard = has_external_keyboard (seat);
seat->has_touchscreen = has_touchscreen (seat);
update_touch_mode (seat);

View File

@ -120,7 +120,6 @@ struct _MetaSeatNative
GUdevClient *udev_client;
guint tablet_mode_switch_state : 1;
guint has_external_keyboard : 1;
guint has_touchscreen : 1;
guint has_tablet_switch : 1;
guint touch_mode : 1;

View File

@ -38,7 +38,10 @@ enum
PROP_OPCODE,
PROP_POINTER_ID,
PROP_KEYBOARD_ID,
N_PROPS
N_PROPS,
/* This property is overridden */
PROP_TOUCH_MODE,
};
struct _MetaSeatX11
@ -54,6 +57,8 @@ struct _MetaSeatX11
int pointer_id;
int keyboard_id;
int opcode;
guint has_touchscreens : 1;
guint touch_mode : 1;
};
static GParamSpec *props[N_PROPS] = { 0 };
@ -605,6 +610,20 @@ pad_passive_button_grab (ClutterInputDevice *device)
g_free (xi_event_mask.mask);
}
static void
update_touch_mode (MetaSeatX11 *seat_x11)
{
gboolean touch_mode;
touch_mode = seat_x11->has_touchscreens;
if (seat_x11->touch_mode == touch_mode)
return;
seat_x11->touch_mode = touch_mode;
g_object_notify (G_OBJECT (seat_x11), "touch-mode");
}
static ClutterInputDevice *
add_device (MetaSeatX11 *seat_x11,
ClutterBackend *backend,
@ -635,6 +654,8 @@ add_device (MetaSeatX11 *seat_x11,
info->attachment == seat_x11->keyboard_id))
{
seat_x11->devices = g_list_prepend (seat_x11->devices, device);
seat_x11->has_touchscreens |=
clutter_input_device_get_device_type (device) == CLUTTER_TOUCHSCREEN_DEVICE;
}
else
{
@ -663,18 +684,38 @@ add_device (MetaSeatX11 *seat_x11,
}
}
update_touch_mode (seat_x11);
return device;
}
static gboolean
has_touchscreens (MetaSeatX11 *seat_x11)
{
GList *l;
for (l = seat_x11->devices; l; l = l->next)
{
if (clutter_input_device_get_device_type (l->data) == CLUTTER_TOUCHSCREEN_DEVICE)
return TRUE;
}
return FALSE;
}
static void
remove_device (MetaSeatX11 *seat_x11,
int device_id)
{
ClutterInputDevice *device;
gboolean check_touchscreens = FALSE;
device = g_hash_table_lookup (seat_x11->devices_by_id,
GINT_TO_POINTER (device_id));
if (clutter_input_device_get_device_type (device) == CLUTTER_TOUCHSCREEN_DEVICE)
check_touchscreens = TRUE;
if (device != NULL)
{
if (seat_x11->core_pointer == device)
@ -695,6 +736,12 @@ remove_device (MetaSeatX11 *seat_x11,
g_hash_table_remove (seat_x11->devices_by_id,
GINT_TO_POINTER (device_id));
}
if (check_touchscreens)
{
seat_x11->has_touchscreens = has_touchscreens (seat_x11);
update_touch_mode (seat_x11);
}
}
static void
@ -1272,6 +1319,7 @@ meta_seat_x11_set_property (GObject *object,
case PROP_KEYBOARD_ID:
seat_x11->keyboard_id = g_value_get_int (value);
break;
case PROP_TOUCH_MODE:
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@ -1296,6 +1344,9 @@ meta_seat_x11_get_property (GObject *object,
case PROP_KEYBOARD_ID:
g_value_set_int (value, seat_x11->keyboard_id);
break;
case PROP_TOUCH_MODE:
g_value_set_boolean (value, seat_x11->touch_mode);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@ -1547,6 +1598,9 @@ meta_seat_x11_class_init (MetaSeatX11Class *klass)
G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_properties (object_class, N_PROPS, props);
g_object_class_override_property (object_class, PROP_TOUCH_MODE,
"touch-mode");
}
static void

View File

@ -16,11 +16,11 @@ wait_reconfigure
assert_position x/1 100 100
tile x/1 left
wait
wait_reconfigure
assert_position x/1 0 0
untile x/1
wait
wait_reconfigure
assert_position x/1 100 100
tile x/1 left
@ -57,11 +57,11 @@ wait_reconfigure
assert_position w/1 0 0
untile w/1
wait
wait_reconfigure
assert_position w/1 100 100
tile w/1 left
wait
wait_reconfigure
assert_position w/1 0 0
maximize w/1