Compare commits

..

18 Commits

Author SHA1 Message Date
Jonas Ådahl
9b2ee14eb1 tests/stacking: Add test checking the initial size
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:13 +02:00
Jonas Ådahl
0a8286e008 tests/stacking: Add test for checking restored positions
Going maximized -> unmaximized should restore the previous position. The
same for untiling, or going from tiled, to maximized, to floating.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:13 +02:00
Jonas Ådahl
42fecdb60b tests/test-runner: Add 'move' and 'assert_position'
Make it possible for tests to move the windows, and check their
positions.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:13 +02:00
Jonas Ådahl
f84ec95d2f tests/restore-size: Also test that untiling restores correctly
Tiling, then untiling should restore to the size prior to tiling.

Tiling, maximizing, then unmaximizing should also restore to the size
prior to tiling.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:13 +02:00
Jonas Ådahl
4b4cf96de1 tests/test-runner: Add tile and untile commands
This allows test cases to tile windows to the right or left, and untile,
just as the keyboard shortcuts does.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:13 +02:00
Jonas Ådahl
c413dd9078 window: Set fall-back tile monitor if not set
When tiling, we want to set the tile monitor. To not have to do this
from the call site, make meta_window_tile() fall back to the current
monitor if nothing set it prior to the call.

This will make it more convenient for test cases that what to test
tiling.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:13 +02:00
Jonas Ådahl
95f3fe7bd5 window: Add meta_window_untile()
It does the same as the untile keyboard shortcut does, i.e. handles
going back to saved maximized state. It's split out to be able to be
tested by the stacking tests.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:13 +02:00
Jonas Ådahl
443dd146e1 tests/stacking: Test some maximize fullscreen interaction
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:13 +02:00
Jonas Ådahl
2d982b678e tests/test-client: Add 'fullscreen' and 'unfullscreen' commands
This needs some hand holding when calculating the "full" size of the
window, as the titlebar isn't actually shown.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:13 +02:00
Jonas Ådahl
7cf61a392d tests/stacking: Check that unmaximize to new size works
A client that set a new fallback size while being maximized should not
restore to the one prior to being maximized.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:12 +02:00
Jonas Ådahl
e190efb7af tests/stacking: Add test to verify we unmaximize correctly
The test tests that (for both X11 and Wayland) that:

 * The client unmaximizes after mapping maximized to a predictable size
 * That the client unmaximizes to the same size after toggling maximize

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:12 +02:00
Jonas Ådahl
711adcb36e tests/test-runner: Add a 'wait_reconfigure' command
This makes sure that a client has properly responded to a configure
event it itself triggered. In practice, this is just two 'wait'
commands, with a 'dispatch' in between, which is needed because a single
one does not reliably include the two way round trip happening when e.g.
responding to a unmaximize configure event triggered by a unmaximize
request.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:12 +02:00
Jonas Ådahl
b98ce96d09 tests/test-runner: Add 'assert_size' command
The 'assert_size' command checks that the size of the window, both
client side and compositor side, corresponds to an expected size set by
the test case.

The size comparison can only be done when the window is using 'csd', in
order for both the client and server to have the same amount of
understanding of the title bar. For ssd, the client cannot know how
large the title bar, thus cannot verify the full window size.

Sizes can be specified to mean the size of the monitor divided by a
number. This is that one can make sure a window is maximized or
fullscreened correctly.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:12 +02:00
Jonas Ådahl
b7ad1fb086 tests/test-client: Remove shadow from X11 test client CSS style
Gtk is quite buggy and "fluid" in how it handles the shadow margins for
windows under X11. The "size" of the window fluctuate between including and
excluding a shadow margin in a way that causes issues, as there are no
atomic update of any state going on.

In order to avoid running into those particular issues now, lets get rid
of shadows so the margins are always zero, when the client is using the
X11 backend.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:12 +02:00
Jonas Ådahl
d812cecc44 tests/test-client: Make 'resize' client command include the titlebar
To get some kind of consistency between what 'resize' means for the
compositor and the client, make the size correspond to the "frame rect"
of the window, i.e. the window geometry in the Wayland case, and the
window size including the titlebar in the X11 case.

This is so that the window size later can be reliably compared both in
the compositor and in the client using the same expected dimensions.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:12 +02:00
Jonas Ådahl
965d74355a tests/test-client: Add line breaks to warning messages
When toying with the test client to try to reproduce issues (e.g.
writing commands on stdin to create and manipulate windows), when you
write a command incorrectly you'll get a warning printed to standard
out. The problem, however, is that it doesn't include a line break in
the end, meaning when you type the correct command, it won't be on a new
line.

Fix this minor annoyance by adding line breaks to all warning messages.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:12 +02:00
Jonas Ådahl
92b1359d04 tests/test-runner: Plumb "resize" command
The test client could already understand the resize command, but they
could not be added to metatests as the command was not properly plumbed
via the test runner. Establish the plumbing for the resize command so
that resize tests can be added.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:12 +02:00
Jonas Ådahl
c25fa19208 tests/test-client: Add commands to maximize/unmaximize
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1171
2020-04-15 15:59:12 +02:00
54 changed files with 1218 additions and 1264 deletions

39
NEWS
View File

@@ -1,42 +1,3 @@
3.36.3
======
* Broadcast clipboard/primary offers [Carlos; !1262]
* Fix monitor screen cast on X11 [Jonas Å.; !1251]
* Implement touch-mode detecation for the X11 backend [Carlos; !1278]
* Drop external keyboard detection from touch-mode heuristics [Carlos; !1277]
* Fix leaked DMA buffers in screencasts [Jonas; !1283]
* Fixed crashes [Daniel, Carlos, Jonas D.; !1256, !1258, !1280]
Contributors:
Carlos Garnacho, Daniel van Vugt, Jonas Ådahl
3.36.2
======
* Sync timelines to hardware vsync [Daniel; !724]
* Fix screencasting non-maximized windows [Jonas; !1174]
* Make window-aliveness checks less aggressive [Jonas; !1182]
* Fix stylus coordinates when using screen rotation [Jonas T.; #1118]
* Preserve keyboard state on VT switch [Olivier; !1185]
* Fix trackball button scrolling [Phillip; #1120]
* Fix tiled monitor support [Jonas Å.; !1199]
* Fix various clipboard issues [Carlos; !1198, !1203, !1204, !1186, !1206]
* Synchronize shadows to server-side decorations [Olivier; !1214]
* Fix overview key on X11 when using multiple keyboard layouts [Olivier; !1219]
* Fix capturing with multiple stage views [Jonas Å.; !1222]
* Fixed crashes [Jonas D., Carlos; !1173, !1183]
* Misc. bug fixes and cleanups [Andre, Georges, Simon, Christian, Carlos, Marco,
Pekka, Laurent, Jonas D.; !1169, !1170, !1172, !1168, !1184, !1200, !1209,
#1074, !1208]
Contributors:
Marco Trevisan (Treviño), Laurent Bigonville, Jonas Dreßler, Olivier Fourdan,
Carlos Garnacho, Andre Moreira Magalhaes, Simon McVittie,
Georges Basile Stavracas Neto, Pekka Paalanen, Christian Rauch, Jonas Troeger,
Daniel van Vugt, Phillip Wood, Jonas Ådahl
Translators:
Dušan Kazik [sk], Christian Kirbach [de]
3.36.1
======
* Fix hardware cursor on GPU hotplpug [Pekka; !1097]

View File

@@ -2604,9 +2604,6 @@ clutter_actor_set_allocation_internal (ClutterActor *self,
gboolean retval;
ClutterActorBox old_alloc = { 0, };
g_return_val_if_fail (!isnan (box->x1) && !isnan (box->x2) &&
!isnan (box->y1) && !isnan (box->y2), FALSE);
obj = G_OBJECT (self);
g_object_freeze_notify (obj);
@@ -4197,9 +4194,7 @@ clutter_actor_continue_paint (ClutterActor *self,
clutter_paint_node_unref (dummy);
/* XXX:2.0 - Call the paint() virtual directly */
if (!(clutter_paint_context_get_paint_flags (paint_context) &
CLUTTER_PAINT_FLAG_NO_PAINT_SIGNAL) &&
g_signal_has_handler_pending (self, actor_signals[PAINT],
if (g_signal_has_handler_pending (self, actor_signals[PAINT],
0, TRUE))
g_signal_emit (self, actor_signals[PAINT], 0, paint_context);
else
@@ -10369,11 +10364,6 @@ clutter_actor_allocate (ClutterActor *self,
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

View File

@@ -30,7 +30,6 @@
#include "clutter-input-device-private.h"
#include "clutter-input-pointer-a11y-private.h"
#include "clutter-macros.h"
#include "clutter-paint-context-private.h"
#include "clutter-private.h"
#include "clutter-stage-private.h"
#include "clutter-stage-view.h"
@@ -49,23 +48,6 @@ void clutter_stage_capture_into (ClutterStage *stage,
cairo_rectangle_int_t *rect,
uint8_t *data);
CLUTTER_EXPORT
void clutter_stage_paint_to_framebuffer (ClutterStage *stage,
CoglFramebuffer *framebuffer,
const cairo_rectangle_int_t *rect,
float scale,
ClutterPaintFlag paint_flags);
CLUTTER_EXPORT
gboolean clutter_stage_paint_to_buffer (ClutterStage *stage,
const cairo_rectangle_int_t *rect,
float scale,
uint8_t *data,
int stride,
CoglPixelFormat format,
ClutterPaintFlag paint_flags,
GError **error);
CLUTTER_EXPORT
void clutter_stage_freeze_updates (ClutterStage *stage);

View File

@@ -20,22 +20,11 @@
#include "clutter-paint-context.h"
typedef enum _ClutterPaintFlag
{
CLUTTER_PAINT_FLAG_NONE = 0,
CLUTTER_PAINT_FLAG_NO_CURSORS = 1 << 0,
CLUTTER_PAINT_FLAG_NO_PAINT_SIGNAL = 1 << 0,
} ClutterPaintFlag;
ClutterPaintContext * clutter_paint_context_new_for_view (ClutterStageView *view,
const cairo_region_t *redraw_clip,
ClutterPaintFlag paint_flags);
const cairo_region_t *redraw_clip);
gboolean clutter_paint_context_is_drawing_off_stage (ClutterPaintContext *paint_context);
CoglFramebuffer * clutter_paint_context_get_base_framebuffer (ClutterPaintContext *paint_context);
CLUTTER_EXPORT
ClutterPaintFlag clutter_paint_context_get_paint_flags (ClutterPaintContext *paint_context);
#endif /* CLUTTER_PAINT_CONTEXT_PRIVATE_H */

View File

@@ -23,8 +23,6 @@ struct _ClutterPaintContext
{
grefcount ref_count;
ClutterPaintFlag paint_flags;
GList *framebuffers;
ClutterStageView *view;
@@ -38,8 +36,7 @@ G_DEFINE_BOXED_TYPE (ClutterPaintContext, clutter_paint_context,
ClutterPaintContext *
clutter_paint_context_new_for_view (ClutterStageView *view,
const cairo_region_t *redraw_clip,
ClutterPaintFlag paint_flags)
const cairo_region_t *redraw_clip)
{
ClutterPaintContext *paint_context;
CoglFramebuffer *framebuffer;
@@ -48,7 +45,6 @@ clutter_paint_context_new_for_view (ClutterStageView *view,
g_ref_count_init (&paint_context->ref_count);
paint_context->view = view;
paint_context->redraw_clip = cairo_region_copy (redraw_clip);
paint_context->paint_flags = paint_flags;
framebuffer = clutter_stage_view_get_framebuffer (view);
clutter_paint_context_push_framebuffer (paint_context, framebuffer);
@@ -66,8 +62,6 @@ clutter_paint_context_new_for_framebuffer (CoglFramebuffer *framebuffer)
paint_context = g_new0 (ClutterPaintContext, 1);
g_ref_count_init (&paint_context->ref_count);
paint_context->paint_flags = (CLUTTER_PAINT_FLAG_NO_CURSORS |
CLUTTER_PAINT_FLAG_NO_PAINT_SIGNAL);
clutter_paint_context_push_framebuffer (paint_context, framebuffer);
@@ -176,12 +170,3 @@ clutter_paint_context_is_drawing_off_stage (ClutterPaintContext *paint_context)
return !paint_context->view;
}
/**
* clutter_paint_context_get_paint_flags: (skip)
*/
ClutterPaintFlag
clutter_paint_context_get_paint_flags (ClutterPaintContext *paint_context)
{
return paint_context->paint_flags;
}

View File

@@ -682,6 +682,7 @@ 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

@@ -934,8 +934,7 @@ clutter_stage_do_paint_view (ClutterStage *stage,
ClutterPaintContext *paint_context;
cairo_rectangle_int_t clip_rect;
paint_context = clutter_paint_context_new_for_view (view, redraw_clip,
CLUTTER_PAINT_FLAG_NONE);
paint_context = clutter_paint_context_new_for_view (view, redraw_clip);
cairo_region_get_extents (redraw_clip, &clip_rect);
setup_view_for_pick_or_paint (stage, view, &clip_rect);
@@ -4473,100 +4472,6 @@ clutter_stage_get_capture_final_size (ClutterStage *stage,
return TRUE;
}
/**
* clutter_stage_paint_to_framebuffer: (skip)
*/
void
clutter_stage_paint_to_framebuffer (ClutterStage *stage,
CoglFramebuffer *framebuffer,
const cairo_rectangle_int_t *rect,
float scale,
ClutterPaintFlag paint_flags)
{
ClutterStagePrivate *priv = stage->priv;
ClutterPaintContext *paint_context;
cairo_region_t *redraw_clip;
redraw_clip = cairo_region_create_rectangle (rect);
paint_context = clutter_paint_context_new_for_framebuffer (framebuffer);
cairo_region_destroy (redraw_clip);
cogl_framebuffer_push_matrix (framebuffer);
cogl_framebuffer_set_projection_matrix (framebuffer, &priv->projection);
cogl_framebuffer_set_viewport (framebuffer,
-(rect->x * scale),
-(rect->y * scale),
priv->viewport[2] * scale,
priv->viewport[3] * scale);
clutter_actor_paint (CLUTTER_ACTOR (stage), paint_context);
cogl_framebuffer_pop_matrix (framebuffer);
clutter_paint_context_destroy (paint_context);
}
/**
* clutter_stage_paint_to_buffer: (skip)
*/
gboolean
clutter_stage_paint_to_buffer (ClutterStage *stage,
const cairo_rectangle_int_t *rect,
float scale,
uint8_t *data,
int stride,
CoglPixelFormat format,
ClutterPaintFlag paint_flags,
GError **error)
{
ClutterBackend *clutter_backend = clutter_get_default_backend ();
CoglContext *cogl_context =
clutter_backend_get_cogl_context (clutter_backend);
int texture_width, texture_height;
CoglTexture2D *texture;
CoglOffscreen *offscreen;
CoglFramebuffer *framebuffer;
CoglBitmap *bitmap;
texture_width = (int) ceilf (rect->width * scale);
texture_height = (int) ceilf (rect->height * scale);
texture = cogl_texture_2d_new_with_size (cogl_context,
texture_width,
texture_height);
if (!texture)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Failed to create %dx%d texture",
texture_width, texture_height);
return FALSE;
}
offscreen = cogl_offscreen_new_with_texture (COGL_TEXTURE (texture));
framebuffer = COGL_FRAMEBUFFER (offscreen);
cogl_object_unref (texture);
if (!cogl_framebuffer_allocate (framebuffer, error))
return FALSE;
clutter_stage_paint_to_framebuffer (stage, framebuffer,
rect, scale, paint_flags);
bitmap = cogl_bitmap_new_for_data (cogl_context,
texture_width, texture_height,
format,
stride,
data);
cogl_framebuffer_read_pixels_into_bitmap (framebuffer,
0, 0,
COGL_READ_PIXELS_COLOR_BUFFER,
bitmap);
cogl_object_unref (bitmap);
cogl_object_unref (framebuffer);
return TRUE;
}
static void
capture_view_into (ClutterStage *stage,
gboolean paint,
@@ -4575,17 +4480,50 @@ capture_view_into (ClutterStage *stage,
uint8_t *data,
int stride)
{
g_autoptr (GError) error = NULL;
CoglFramebuffer *framebuffer;
ClutterBackend *backend;
CoglContext *context;
CoglBitmap *bitmap;
cairo_rectangle_int_t view_layout;
float view_scale;
float texture_width;
float texture_height;
g_return_if_fail (CLUTTER_IS_STAGE (stage));
framebuffer = clutter_stage_view_get_framebuffer (view);
if (paint)
{
cairo_region_t *region;
_clutter_stage_maybe_setup_viewport (stage, view);
region = cairo_region_create_rectangle (rect);
clutter_stage_do_paint_view (stage, view, region);
cairo_region_destroy (region);
}
view_scale = clutter_stage_view_get_scale (view);
if (!clutter_stage_paint_to_buffer (stage, rect, view_scale, data, stride,
CLUTTER_CAIRO_FORMAT_ARGB32,
CLUTTER_PAINT_FLAG_NO_CURSORS,
&error))
g_warning ("Failed to capture stage: %s", error->message);
texture_width = roundf (rect->width * view_scale);
texture_height = roundf (rect->height * view_scale);
backend = clutter_get_default_backend ();
context = clutter_backend_get_cogl_context (backend);
bitmap = cogl_bitmap_new_for_data (context,
texture_width, texture_height,
CLUTTER_CAIRO_FORMAT_ARGB32,
stride,
data);
clutter_stage_view_get_layout (view, &view_layout);
cogl_framebuffer_read_pixels_into_bitmap (framebuffer,
roundf ((rect->x - view_layout.x) * view_scale),
roundf ((rect->y - view_layout.y) * view_scale),
COGL_READ_PIXELS_COLOR_BUFFER,
bitmap);
cogl_object_unref (bitmap);
}
void

View File

@@ -403,11 +403,15 @@ static gboolean
swap_framebuffer (ClutterStageWindow *stage_window,
ClutterStageView *view,
cairo_region_t *swap_region,
gboolean swap_with_damage)
gboolean swap_with_damage,
cairo_region_t *queued_redraw_clip)
{
CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (view);
int *damage, n_rects, i;
if (G_UNLIKELY ((clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_DAMAGE_REGION)))
paint_damage_region (stage_window, view, swap_region, queued_redraw_clip);
n_rects = cairo_region_num_rectangles (swap_region);
damage = g_newa (int, n_rects * 4);
for (i = 0; i < n_rects; i++)
@@ -644,7 +648,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
gboolean swap_with_damage;
ClutterActor *wrapper;
cairo_region_t *redraw_clip;
cairo_region_t *queued_redraw_clip = NULL;
cairo_region_t *queued_redraw_clip;
cairo_region_t *fb_clip_region;
cairo_region_t *swap_region;
cairo_rectangle_int_t redraw_rect;
@@ -668,8 +672,6 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
has_buffer_age = cogl_is_onscreen (fb) && is_buffer_age_enabled ();
redraw_clip = clutter_stage_view_take_redraw_clip (view);
if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_DAMAGE_REGION))
queued_redraw_clip = cairo_region_copy (redraw_clip);
/* NB: a NULL redraw clip == full stage redraw */
if (!redraw_clip)
@@ -737,6 +739,8 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
redraw_clip = cairo_region_create_rectangle (&view_rect);
}
queued_redraw_clip = cairo_region_copy (redraw_clip);
if (may_use_clipped_redraw &&
G_LIKELY (!(clutter_paint_debug_flags & CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS)))
use_clipped_redraw = TRUE;
@@ -946,6 +950,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
}
g_clear_pointer (&redraw_clip, cairo_region_destroy);
g_clear_pointer (&queued_redraw_clip, cairo_region_destroy);
g_clear_pointer (&fb_clip_region, cairo_region_destroy);
if (do_swap_buffer)
@@ -966,17 +971,11 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
swap_region = transformed_swap_region;
}
if (queued_redraw_clip)
{
paint_damage_region (stage_window, view,
swap_region, queued_redraw_clip);
cairo_region_destroy (queued_redraw_clip);
}
res = swap_framebuffer (stage_window,
view,
swap_region,
swap_with_damage);
swap_with_damage,
queued_redraw_clip);
cairo_region_destroy (swap_region);
@@ -984,7 +983,6 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
}
else
{
g_clear_pointer (&queued_redraw_clip, cairo_region_destroy);
return FALSE;
}
}

View File

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

View File

@@ -13,8 +13,8 @@ msgid ""
msgstr ""
"Project-Id-Version: mutter master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n"
"POT-Creation-Date: 2020-03-30 20:11+0000\n"
"PO-Revision-Date: 2020-04-06 23:13+0200\n"
"POT-Creation-Date: 2019-08-06 00:49+0000\n"
"PO-Revision-Date: 2019-09-05 23:42+0200\n"
"Last-Translator: Christian Kirbach <christian.kirbach@gmail.com>\n"
"Language-Team: Deutsch <gnome-de@gnome.org>\n"
"Language: de\n"
@@ -22,7 +22,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 2.3\n"
"X-Generator: Poedit 2.2.1\n"
#: data/50-mutter-navigation.xml:6
msgid "Navigation"
@@ -435,33 +435,20 @@ msgstr "Zusatztaste zum Finden des Zeigers"
msgid "This key will initiate the “locate pointer” action."
msgstr "Diese Taste wird die Aktion »Zeiger finden« auslösen."
#: data/org.gnome.mutter.gschema.xml.in:142
msgid "Timeout for check-alive ping"
msgstr "Reaktionsschwellwert bei Kontaktkontrolle"
#: data/org.gnome.mutter.gschema.xml.in:143
msgid ""
"Number of milliseconds a client has to respond to a ping request in order to "
"not be detected as frozen. Using 0 will disable the alive check completely."
msgstr ""
"Zeit in Millisekunden, innerhalb welcher ein Client auf eine "
"Kontaktkontrolle antworten muss, um nicht als abgestürzt zu gelten. »0« "
"bedeutet, dass die Kontaktkontrolle ausgeschaltet wird."
#: data/org.gnome.mutter.gschema.xml.in:165
#: data/org.gnome.mutter.gschema.xml.in:155
msgid "Select window from tab popup"
msgstr "Fenster aus Tab-Anzeige auswählen"
#: data/org.gnome.mutter.gschema.xml.in:170
#: data/org.gnome.mutter.gschema.xml.in:160
msgid "Cancel tab popup"
msgstr "Tab-Anzeige abbrechen"
#: data/org.gnome.mutter.gschema.xml.in:175
#: data/org.gnome.mutter.gschema.xml.in:165
msgid "Switch monitor configurations"
msgstr "Bildschirmkonfigurationen wechseln"
# Ich denke nicht, dass »rotate« hier die Bildschirmdrehung meint, sondern eher eine Liste aus Konfigurationen rotiert (d.h. umgewälzt) wird.
#: data/org.gnome.mutter.gschema.xml.in:180
#: data/org.gnome.mutter.gschema.xml.in:170
msgid "Rotates the built-in monitor configuration"
msgstr "Wechselt die Konfiguration des eingebauten Bildschirms"
@@ -582,7 +569,7 @@ msgstr ""
#. TRANSLATORS: This string refers to a button that switches between
#. * different modes.
#.
#: src/backends/meta-input-settings.c:2631
#: src/backends/meta-input-settings.c:2531
#, c-format
msgid "Mode Switch (Group %d)"
msgstr "Moduswechsel (Gruppe %d)"
@@ -590,34 +577,34 @@ msgstr "Moduswechsel (Gruppe %d)"
#. TRANSLATORS: This string refers to an action, cycles drawing tablets'
#. * mapping through the available outputs.
#.
#: src/backends/meta-input-settings.c:2654
#: src/backends/meta-input-settings.c:2554
msgid "Switch monitor"
msgstr "Bildschirm wechseln"
#: src/backends/meta-input-settings.c:2656
#: src/backends/meta-input-settings.c:2556
msgid "Show on-screen help"
msgstr "Bildschirmhilfe anzeigen"
#: src/backends/meta-monitor.c:226
#: src/backends/meta-monitor.c:223
msgid "Built-in display"
msgstr "Eingebaute Anzeige"
#: src/backends/meta-monitor.c:255
#: src/backends/meta-monitor.c:252
msgid "Unknown"
msgstr "Unbekannt"
#: src/backends/meta-monitor.c:257
#: src/backends/meta-monitor.c:254
msgid "Unknown Display"
msgstr "Unbekannte Anzeige"
#: src/backends/meta-monitor.c:265
#: src/backends/meta-monitor.c:262
#, c-format
msgctxt ""
"This is a monitor vendor name, followed by a size in inches, like 'Dell 15\"'"
msgid "%s %s"
msgstr "%s %s"
#: src/backends/meta-monitor.c:273
#: src/backends/meta-monitor.c:270
#, c-format
msgctxt ""
"This is a monitor vendor name followed by product/model name where size in "
@@ -627,13 +614,13 @@ msgstr "%s %s"
# https://de.wikipedia.org/wiki/Composition-Manager
#. Translators: this string will appear in Sysprof
#: src/backends/meta-profiler.c:79
#: src/backends/meta-profiler.c:82
msgid "Compositor"
msgstr "Compositor"
#. This probably means that a non-WM compositor like xcompmgr is running;
#. * we have no way to get it to exit
#: src/compositor/compositor.c:533
#: src/compositor/compositor.c:510
#, c-format
msgid ""
"Another compositing manager is already running on screen %i on display “%s”."
@@ -645,47 +632,47 @@ msgstr ""
msgid "Bell event"
msgstr "Klangereignis"
#: src/core/main.c:190
#: src/core/main.c:185
msgid "Disable connection to session manager"
msgstr "Verbindung zur Sitzungsverwaltung deaktivieren"
#: src/core/main.c:196
#: src/core/main.c:191
msgid "Replace the running window manager"
msgstr "Den aktuellen Fensterverwalter ersetzen"
#: src/core/main.c:202
#: src/core/main.c:197
msgid "Specify session management ID"
msgstr "Kennung der Sitzungsverwaltung angeben"
#: src/core/main.c:207
#: src/core/main.c:202
msgid "X Display to use"
msgstr "Zu verwendende X-Anzeige"
#: src/core/main.c:213
#: src/core/main.c:208
msgid "Initialize session from savefile"
msgstr "Sitzung anhand gespeicherter Datei starten"
#: src/core/main.c:219
#: src/core/main.c:214
msgid "Make X calls synchronous"
msgstr "X-Aufrufe abgleichen"
#: src/core/main.c:226
#: src/core/main.c:221
msgid "Run as a wayland compositor"
msgstr "Als Wayland-Compositor ausführen"
#: src/core/main.c:232
#: src/core/main.c:227
msgid "Run as a nested compositor"
msgstr "Als eingebetteten Compositor ausführen"
#: src/core/main.c:238
#: src/core/main.c:233
msgid "Run wayland compositor without starting Xwayland"
msgstr "Wayland-Compositor ausführen, ohne Xwayland zu starten"
#: src/core/main.c:246
#: src/core/main.c:241
msgid "Run as a full display server, rather than nested"
msgstr "Als vollwertigen Display-Server verwenden (nicht eingebettet)"
#: src/core/main.c:252
#: src/core/main.c:247
msgid "Run with X11 backend"
msgstr "Mit X11-Backend ausführen"
@@ -741,21 +728,21 @@ msgstr "Version ausgeben"
msgid "Mutter plugin to use"
msgstr "Zu benutzendes Mutter-Plugin"
#: src/core/prefs.c:1911
#: src/core/prefs.c:1849
#, c-format
msgid "Workspace %d"
msgstr "Arbeitsfläche %d"
#: src/core/util.c:122
#: src/core/util.c:121
msgid "Mutter was compiled without support for verbose mode\n"
msgstr "Mutter wurde ohne Unterstützung für den redseligen Modus kompiliert\n"
#: src/wayland/meta-wayland-tablet-pad.c:568
#: src/wayland/meta-wayland-tablet-pad.c:567
#, c-format
msgid "Mode Switch: Mode %d"
msgstr "Moduswechsel: Modus %d"
#: src/x11/meta-x11-display.c:676
#: src/x11/meta-x11-display.c:671
#, c-format
msgid ""
"Display “%s” already has a window manager; try using the --replace option to "
@@ -764,21 +751,21 @@ msgstr ""
"Bildschirm »%s« hat bereits einen Fensterverwalter. Versuchen Sie die Option "
"»--replace«, um den aktuellen Fensterverwalter zu ersetzen."
#: src/x11/meta-x11-display.c:1089
#: src/x11/meta-x11-display.c:1032
msgid "Failed to initialize GDK\n"
msgstr "GDK konnte nicht initialisiert werden\n"
#: src/x11/meta-x11-display.c:1113
#: src/x11/meta-x11-display.c:1056
#, c-format
msgid "Failed to open X Window System display “%s”\n"
msgstr "X-Window-Systemanzeige »%s« konnte nicht geöffnet werden\n"
#: src/x11/meta-x11-display.c:1196
#: src/x11/meta-x11-display.c:1140
#, c-format
msgid "Screen %d on display “%s” is invalid\n"
msgstr "Bildschirm %d auf Anzeige »%s« ist ungültig\n"
#: src/x11/meta-x11-selection-input-stream.c:460
#: src/x11/meta-x11-selection-input-stream.c:445
#, c-format
msgid "Format %s not supported"
msgstr "Format %s wird nicht unterstützt"

View File

@@ -90,6 +90,7 @@ float meta_logical_monitor_get_scale (MetaLogicalMonitor *logical_monitor);
MetaMonitorTransform meta_logical_monitor_get_transform (MetaLogicalMonitor *logical_monitor);
META_EXPORT_TEST
MetaRectangle meta_logical_monitor_get_layout (MetaLogicalMonitor *logical_monitor);
META_EXPORT_TEST

View File

@@ -172,7 +172,6 @@ assign_monitor_crtc (MetaMonitor *monitor,
MetaCrtc *crtc;
MetaMonitorTransform transform;
MetaMonitorTransform crtc_transform;
MetaMonitorTransform crtc_hw_transform;
int crtc_x, crtc_y;
float x_offset, y_offset;
float scale = 0.0;
@@ -201,12 +200,10 @@ assign_monitor_crtc (MetaMonitor *monitor,
transform = data->logical_monitor_config->transform;
crtc_transform = meta_monitor_logical_to_crtc_transform (monitor, transform);
if (meta_monitor_manager_is_transform_handled (data->monitor_manager,
crtc,
crtc_transform))
crtc_hw_transform = crtc_transform;
else
crtc_hw_transform = META_MONITOR_TRANSFORM_NORMAL;
if (!meta_monitor_manager_is_transform_handled (data->monitor_manager,
crtc,
crtc_transform))
crtc_transform = META_MONITOR_TRANSFORM_NORMAL;
meta_monitor_calculate_crtc_pos (monitor, mode, output, crtc_transform,
&crtc_x, &crtc_y);
@@ -247,7 +244,7 @@ assign_monitor_crtc (MetaMonitor *monitor,
.crtc = crtc,
.mode = crtc_mode,
.layout = crtc_layout,
.transform = crtc_hw_transform,
.transform = crtc_transform,
.outputs = g_ptr_array_new ()
};
g_ptr_array_add (crtc_info->outputs, output);
@@ -446,35 +443,23 @@ MetaMonitorsConfigKey *
meta_create_monitors_config_key_for_current_state (MetaMonitorManager *monitor_manager)
{
MetaMonitorsConfigKey *config_key;
MetaMonitorSpec *laptop_monitor_spec;
GList *l;
GList *monitor_specs;
laptop_monitor_spec = NULL;
monitor_specs = NULL;
for (l = monitor_manager->monitors; l; l = l->next)
{
MetaMonitor *monitor = l->data;
MetaMonitorSpec *monitor_spec;
if (meta_monitor_is_laptop_panel (monitor))
{
laptop_monitor_spec = meta_monitor_get_spec (monitor);
if (is_lid_closed (monitor_manager))
continue;
}
if (meta_monitor_is_laptop_panel (monitor) &&
is_lid_closed (monitor_manager))
continue;
monitor_spec = meta_monitor_spec_clone (meta_monitor_get_spec (monitor));
monitor_specs = g_list_prepend (monitor_specs, monitor_spec);
}
if (!monitor_specs && laptop_monitor_spec)
{
monitor_specs =
g_list_prepend (NULL, meta_monitor_spec_clone (laptop_monitor_spec));
}
if (!monitor_specs)
return NULL;

View File

@@ -817,19 +817,19 @@ calculate_tile_coordinate (MetaMonitor *monitor,
case META_MONITOR_TRANSFORM_270:
case META_MONITOR_TRANSFORM_FLIPPED_270:
if (other_output->tile_info.loc_v_tile == output->tile_info.loc_v_tile &&
other_output->tile_info.loc_h_tile > output->tile_info.loc_h_tile)
other_output->tile_info.loc_h_tile < output->tile_info.loc_h_tile)
y += other_output->tile_info.tile_w;
if (other_output->tile_info.loc_h_tile == output->tile_info.loc_h_tile &&
other_output->tile_info.loc_v_tile > output->tile_info.loc_v_tile)
other_output->tile_info.loc_v_tile < output->tile_info.loc_v_tile)
x += other_output->tile_info.tile_h;
break;
case META_MONITOR_TRANSFORM_90:
case META_MONITOR_TRANSFORM_FLIPPED_90:
if (other_output->tile_info.loc_v_tile == output->tile_info.loc_v_tile &&
other_output->tile_info.loc_h_tile < output->tile_info.loc_h_tile)
other_output->tile_info.loc_h_tile > output->tile_info.loc_h_tile)
y += other_output->tile_info.tile_w;
if (other_output->tile_info.loc_h_tile == output->tile_info.loc_h_tile &&
other_output->tile_info.loc_v_tile < output->tile_info.loc_v_tile)
other_output->tile_info.loc_v_tile > output->tile_info.loc_v_tile)
x += other_output->tile_info.tile_h;
break;
}

View File

@@ -55,7 +55,6 @@ struct _MetaRemoteDesktopSession
MetaScreenCastSession *screen_cast_session;
gulong screen_cast_session_closed_handler_id;
guint started : 1;
ClutterVirtualInputDevice *virtual_pointer;
ClutterVirtualInputDevice *virtual_keyboard;
@@ -120,7 +119,7 @@ meta_remote_desktop_session_start (MetaRemoteDesktopSession *session,
ClutterBackend *backend = clutter_get_default_backend ();
ClutterSeat *seat = clutter_backend_get_default_seat (backend);
g_assert (!session->started);
g_assert (!session->virtual_pointer && !session->virtual_keyboard);
if (session->screen_cast_session)
{
@@ -136,7 +135,6 @@ meta_remote_desktop_session_start (MetaRemoteDesktopSession *session,
clutter_seat_create_virtual_device (seat, CLUTTER_TOUCHSCREEN_DEVICE);
init_remote_access_handle (session);
session->started = TRUE;
return TRUE;
}
@@ -147,8 +145,6 @@ meta_remote_desktop_session_close (MetaRemoteDesktopSession *session)
MetaDBusRemoteDesktopSession *skeleton =
META_DBUS_REMOTE_DESKTOP_SESSION (session);
session->started = FALSE;
if (session->screen_cast_session)
{
g_clear_signal_handler (&session->screen_cast_session_closed_handler_id,
@@ -253,37 +249,6 @@ check_permission (MetaRemoteDesktopSession *session,
g_dbus_method_invocation_get_sender (invocation)) == 0;
}
static gboolean
meta_remote_desktop_session_check_can_notify (MetaRemoteDesktopSession *session,
GDBusMethodInvocation *invocation)
{
if (!session->started)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Session not started");
return FALSE;
}
if (!check_permission (session, invocation))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Permission denied");
return FALSE;
}
if (!session->screen_cast_session)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"No screen cast active");
return FALSE;
}
return TRUE;
}
static gboolean
handle_start (MetaDBusRemoteDesktopSession *skeleton,
GDBusMethodInvocation *invocation)
@@ -291,14 +256,6 @@ handle_start (MetaDBusRemoteDesktopSession *skeleton,
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
GError *error = NULL;
if (session->started)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Already started");
return TRUE;
}
if (!check_permission (session, invocation))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
@@ -331,14 +288,6 @@ handle_stop (MetaDBusRemoteDesktopSession *skeleton,
{
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
if (!session->started)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Session not started");
return TRUE;
}
if (!check_permission (session, invocation))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
@@ -363,8 +312,13 @@ handle_notify_keyboard_keycode (MetaDBusRemoteDesktopSession *skeleton,
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
ClutterKeyState state;
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
return TRUE;
if (!check_permission (session, invocation))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Permission denied");
return TRUE;
}
if (pressed)
state = CLUTTER_KEY_STATE_PRESSED;
@@ -390,8 +344,13 @@ handle_notify_keyboard_keysym (MetaDBusRemoteDesktopSession *skeleton,
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
ClutterKeyState state;
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
return TRUE;
if (!check_permission (session, invocation))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Permission denied");
return TRUE;
}
if (pressed)
state = CLUTTER_KEY_STATE_PRESSED;
@@ -439,8 +398,13 @@ handle_notify_pointer_button (MetaDBusRemoteDesktopSession *skeleton,
uint32_t button;
ClutterButtonState state;
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
return TRUE;
if (!check_permission (session, invocation))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Permission denied");
return TRUE;
}
button = translate_to_clutter_button (button_code);
@@ -470,8 +434,13 @@ handle_notify_pointer_axis (MetaDBusRemoteDesktopSession *skeleton,
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
ClutterScrollFinishFlags finish_flags = CLUTTER_SCROLL_FINISHED_NONE;
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
return TRUE;
if (!check_permission (session, invocation))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Permission denied");
return TRUE;
}
if (flags & META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_FINISH)
{
@@ -518,8 +487,13 @@ handle_notify_pointer_axis_discrete (MetaDBusRemoteDesktopSession *skeleton,
ClutterScrollDirection direction;
int step_count;
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
return TRUE;
if (!check_permission (session, invocation))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Permission denied");
return TRUE;
}
if (axis > 1)
{
@@ -564,8 +538,13 @@ handle_notify_pointer_motion_relative (MetaDBusRemoteDesktopSession *skeleton,
{
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
return TRUE;
if (!check_permission (session, invocation))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Permission denied");
return TRUE;
}
clutter_virtual_input_device_notify_relative_motion (session->virtual_pointer,
CLUTTER_CURRENT_TIME,
@@ -588,8 +567,21 @@ handle_notify_pointer_motion_absolute (MetaDBusRemoteDesktopSession *skeleton,
MetaScreenCastStream *stream;
double abs_x, abs_y;
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
return TRUE;
if (!check_permission (session, invocation))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Permission denied");
return TRUE;
}
if (!session->screen_cast_session)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"No screen cast active");
return TRUE;
}
stream = meta_screen_cast_session_get_stream (session->screen_cast_session,
stream_path);
@@ -625,8 +617,21 @@ handle_notify_touch_down (MetaDBusRemoteDesktopSession *skeleton,
MetaScreenCastStream *stream;
double abs_x, abs_y;
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
return TRUE;
if (!check_permission (session, invocation))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Permission denied");
return TRUE;
}
if (!session->screen_cast_session)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"No screen cast active");
return TRUE;
}
stream = meta_screen_cast_session_get_stream (session->screen_cast_session,
stream_path);
@@ -663,8 +668,21 @@ handle_notify_touch_motion (MetaDBusRemoteDesktopSession *skeleton,
MetaScreenCastStream *stream;
double abs_x, abs_y;
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
return TRUE;
if (!check_permission (session, invocation))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Permission denied");
return TRUE;
}
if (!session->screen_cast_session)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"No screen cast active");
return TRUE;
}
stream = meta_screen_cast_session_get_stream (session->screen_cast_session,
stream_path);
@@ -696,8 +714,13 @@ handle_notify_touch_up (MetaDBusRemoteDesktopSession *skeleton,
{
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
return TRUE;
if (!check_permission (session, invocation))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Permission denied");
return TRUE;
}
clutter_virtual_input_device_notify_touch_up (session->virtual_touchscreen,
CLUTTER_CURRENT_TIME,

View File

@@ -160,12 +160,14 @@ meta_renderer_real_rebuild_views (MetaRenderer *renderer)
}
void
meta_renderer_add_view (MetaRenderer *renderer,
MetaRendererView *view)
meta_renderer_set_legacy_view (MetaRenderer *renderer,
MetaRendererView *legacy_view)
{
MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer);
priv->views = g_list_append (priv->views, view);
g_assert (!priv->views);
priv->views = g_list_append (priv->views, legacy_view);
}
/**

View File

@@ -54,8 +54,8 @@ CoglRenderer * meta_renderer_create_cogl_renderer (MetaRenderer *renderer);
void meta_renderer_rebuild_views (MetaRenderer *renderer);
void meta_renderer_add_view (MetaRenderer *renderer,
MetaRendererView *view);
void meta_renderer_set_legacy_view (MetaRenderer *renderer,
MetaRendererView *legacy_view);
META_EXPORT_TEST
GList * meta_renderer_get_views (MetaRenderer *renderer);

View File

@@ -115,10 +115,9 @@ meta_screen_cast_monitor_stream_src_get_specs (MetaScreenCastStreamSrc *src,
}
static void
stage_painted (MetaStage *stage,
ClutterStageView *view,
ClutterPaintContext *paint_context,
gpointer user_data)
stage_painted (MetaStage *stage,
ClutterStageView *view,
gpointer user_data)
{
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (user_data);

View File

@@ -68,7 +68,6 @@ typedef struct _MetaPipeWireSource
{
GSource base;
MetaScreenCastStreamSrc *src;
struct pw_loop *pipewire_loop;
} MetaPipeWireSource;
@@ -82,7 +81,6 @@ typedef struct _MetaScreenCastStreamSrcPrivate
struct spa_hook pipewire_core_listener;
gboolean is_enabled;
gboolean emit_closed_after_dispatch;
struct pw_stream *pipewire_stream;
struct spa_hook pipewire_stream_listener;
@@ -447,8 +445,7 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src)
uint64_t now_us;
now_us = g_get_monotonic_time ();
if (priv->video_format.max_framerate.num > 0 &&
priv->last_frame_timestamp_us != 0 &&
if (priv->last_frame_timestamp_us != 0 &&
(now_us - priv->last_frame_timestamp_us <
((1000000 * priv->video_format.max_framerate.denom) /
priv->video_format.max_framerate.num)))
@@ -542,6 +539,12 @@ meta_screen_cast_stream_src_disable (MetaScreenCastStreamSrc *src)
priv->is_enabled = FALSE;
}
static void
meta_screen_cast_stream_src_notify_closed (MetaScreenCastStreamSrc *src)
{
g_signal_emit (src, signals[CLOSED], 0);
}
static void
on_stream_state_changed (void *data,
enum pw_stream_state old,
@@ -556,9 +559,7 @@ on_stream_state_changed (void *data,
{
case PW_STREAM_STATE_ERROR:
g_warning ("pipewire stream error: %s", error_message);
if (meta_screen_cast_stream_src_is_enabled (src))
meta_screen_cast_stream_src_disable (src);
priv->emit_closed_after_dispatch = TRUE;
meta_screen_cast_stream_src_notify_closed (src);
break;
case PW_STREAM_STATE_PAUSED:
if (priv->node_id == SPA_ID_INVALID && priv->pipewire_stream)
@@ -826,17 +827,11 @@ on_core_error (void *data,
const char *message)
{
MetaScreenCastStreamSrc *src = data;
MetaScreenCastStreamSrcPrivate *priv =
meta_screen_cast_stream_src_get_instance_private (src);
g_warning ("pipewire remote error: id:%u %s", id, message);
if (id == PW_ID_CORE && res == -EPIPE)
{
if (meta_screen_cast_stream_src_is_enabled (src))
meta_screen_cast_stream_src_disable (src);
priv->emit_closed_after_dispatch = TRUE;
}
meta_screen_cast_stream_src_notify_closed (src);
}
static gboolean
@@ -853,18 +848,12 @@ pipewire_loop_source_dispatch (GSource *source,
gpointer user_data)
{
MetaPipeWireSource *pipewire_source = (MetaPipeWireSource *) source;
MetaScreenCastStreamSrc *src = pipewire_source->src;
MetaScreenCastStreamSrcPrivate *priv =
meta_screen_cast_stream_src_get_instance_private (src);
int result;
result = pw_loop_iterate (pipewire_source->pipewire_loop, 0);
if (result < 0)
g_warning ("pipewire_loop_iterate failed: %s", spa_strerror (result));
if (priv->emit_closed_after_dispatch)
g_signal_emit (src, signals[CLOSED], 0);
return TRUE;
}
@@ -886,14 +875,13 @@ static GSourceFuncs pipewire_source_funcs =
};
static MetaPipeWireSource *
create_pipewire_source (MetaScreenCastStreamSrc *src)
create_pipewire_source (void)
{
MetaPipeWireSource *pipewire_source;
pipewire_source =
(MetaPipeWireSource *) g_source_new (&pipewire_source_funcs,
sizeof (MetaPipeWireSource));
pipewire_source->src = src;
pipewire_source->pipewire_loop = pw_loop_new (NULL);
if (!pipewire_source->pipewire_loop)
{
@@ -925,7 +913,7 @@ meta_screen_cast_stream_src_initable_init (GInitable *initable,
MetaScreenCastStreamSrcPrivate *priv =
meta_screen_cast_stream_src_get_instance_private (src);
priv->pipewire_source = create_pipewire_source (src);
priv->pipewire_source = create_pipewire_source ();
if (!priv->pipewire_source)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
@@ -987,8 +975,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->pipewire_stream, pw_stream_destroy);
g_clear_pointer (&priv->dmabuf_handles, g_hash_table_destroy);
g_clear_pointer (&priv->pipewire_stream, pw_stream_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

@@ -38,10 +38,9 @@ typedef enum
META_STAGE_WATCH_AFTER_PAINT,
} MetaStageWatchPhase;
typedef void (* MetaStageWatchFunc) (MetaStage *stage,
ClutterStageView *view,
ClutterPaintContext *paint_context,
gpointer user_data);
typedef void (* MetaStageWatchFunc) (MetaStage *stage,
ClutterStageView *view,
gpointer user_data);
ClutterActor *meta_stage_new (MetaBackend *backend);

View File

@@ -65,6 +65,7 @@ struct _MetaStage
ClutterStage parent;
GPtrArray *watchers[N_WATCH_MODES];
ClutterStageView *current_view;
GList *overlays;
gboolean is_active;
@@ -168,7 +169,6 @@ meta_stage_finalize (GObject *object)
static void
notify_watchers_for_mode (MetaStage *stage,
ClutterStageView *view,
ClutterPaintContext *paint_context,
MetaStageWatchPhase watch_phase)
{
GPtrArray *watchers;
@@ -183,7 +183,7 @@ notify_watchers_for_mode (MetaStage *stage,
if (watch->view && view != watch->view)
continue;
watch->callback (stage, view, paint_context, watch->user_data);
watch->callback (stage, view, watch->user_data);
}
}
@@ -192,34 +192,20 @@ meta_stage_paint (ClutterActor *actor,
ClutterPaintContext *paint_context)
{
MetaStage *stage = META_STAGE (actor);
ClutterStageView *view;
GList *l;
CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor, paint_context);
view = clutter_paint_context_get_stage_view (paint_context);
if (view)
{
notify_watchers_for_mode (stage, view, paint_context,
META_STAGE_WATCH_AFTER_ACTOR_PAINT);
}
notify_watchers_for_mode (stage, stage->current_view,
META_STAGE_WATCH_AFTER_ACTOR_PAINT);
if (!(clutter_paint_context_get_paint_flags (paint_context) &
CLUTTER_PAINT_FLAG_NO_PAINT_SIGNAL))
g_signal_emit (stage, signals[ACTORS_PAINTED], 0);
g_signal_emit (stage, signals[ACTORS_PAINTED], 0);
if (!(clutter_paint_context_get_paint_flags (paint_context) &
CLUTTER_PAINT_FLAG_NO_CURSORS))
{
for (l = stage->overlays; l; l = l->next)
meta_overlay_paint (l->data, paint_context);
}
for (l = stage->overlays; l; l = l->next)
meta_overlay_paint (l->data, paint_context);
if (view)
{
notify_watchers_for_mode (stage, view, paint_context,
META_STAGE_WATCH_AFTER_OVERLAY_PAINT);
}
notify_watchers_for_mode (stage, stage->current_view,
META_STAGE_WATCH_AFTER_OVERLAY_PAINT);
}
static void
@@ -229,14 +215,13 @@ meta_stage_paint_view (ClutterStage *stage,
{
MetaStage *meta_stage = META_STAGE (stage);
notify_watchers_for_mode (meta_stage, view, NULL,
META_STAGE_WATCH_BEFORE_PAINT);
notify_watchers_for_mode (meta_stage, view, META_STAGE_WATCH_BEFORE_PAINT);
meta_stage->current_view = view;
CLUTTER_STAGE_CLASS (meta_stage_parent_class)->paint_view (stage, view,
redraw_clip);
notify_watchers_for_mode (meta_stage, view, NULL,
META_STAGE_WATCH_AFTER_PAINT);
notify_watchers_for_mode (meta_stage, view, META_STAGE_WATCH_AFTER_PAINT);
}
static void

View File

@@ -407,14 +407,13 @@ update_monitor_crtc_cursor (MetaMonitor *monitor,
else
scale = 1.0;
transform = meta_logical_monitor_get_transform (data->in_logical_monitor);
transform = meta_monitor_logical_to_crtc_transform (monitor, transform);
meta_monitor_calculate_crtc_pos (monitor, monitor_mode,
monitor_crtc_mode->output,
transform,
META_MONITOR_TRANSFORM_NORMAL,
&crtc_x, &crtc_y);
transform = meta_logical_monitor_get_transform (data->in_logical_monitor);
transform = meta_monitor_logical_to_crtc_transform (monitor, transform);
if (meta_monitor_transform_is_rotated (transform))
{
crtc_width = monitor_crtc_mode->crtc_mode->height;

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2019 Red Hat
* Copyright (C) 2019-2020 DisplayLink (UK) Ltd.
* Copyright (C) 2019 DisplayLink (UK) Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -660,9 +660,6 @@ process_page_flip (MetaKmsImpl *impl,
meta_kms_page_flip_data_ref (page_flip_data));
}
if (ret != 0)
meta_kms_page_flip_data_unref (page_flip_data);
if (ret == -EBUSY)
{
CachedModeSet *cached_mode_set;

View File

@@ -1,6 +1,5 @@
/*
* Copyright (C) 2018 Red Hat
* Copyright 2020 DisplayLink (UK) Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -384,7 +383,6 @@ meta_kms_add_source_in_impl (MetaKms *kms,
simple_impl_source->kms = kms;
g_source_set_callback (source, func, user_data, user_data_destroy);
g_source_set_ready_time (source, 0);
g_source_attach (source, g_main_context_get_thread_default ());
return source;

View File

@@ -3037,7 +3037,6 @@ meta_renderer_native_create_view (MetaRenderer *renderer,
float scale;
int onscreen_width;
int onscreen_height;
MetaRectangle view_layout;
MetaRendererView *view;
GError *error = NULL;
@@ -3109,11 +3108,8 @@ meta_renderer_native_create_view (MetaRenderer *renderer,
else
scale = 1.0;
meta_rectangle_from_graphene_rect (&crtc->config->layout,
META_ROUNDING_STRATEGY_ROUND,
&view_layout);
view = g_object_new (META_TYPE_RENDERER_VIEW,
"layout", &view_layout,
"layout", &logical_monitor->rect,
"scale", scale,
"framebuffer", onscreen,
"offscreen", offscreen,

View File

@@ -1380,6 +1380,35 @@ 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)
{
@@ -1392,10 +1421,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), assume touch-mode.
* (eg. kiosk machines), check availability of external keyboards.
*/
else
touch_mode = TRUE;
touch_mode = !seat->has_external_keyboard;
if (seat->touch_mode != touch_mode)
{
@@ -1436,7 +1465,12 @@ evdev_add_device (MetaSeatNative *seat,
g_signal_emit_by_name (seat, "device-added", device);
if (type == CLUTTER_TOUCHSCREEN_DEVICE)
if (type == CLUTTER_KEYBOARD_DEVICE)
{
seat->has_external_keyboard = has_external_keyboard (seat);
check_touch_mode = TRUE;
}
else if (type == CLUTTER_TOUCHSCREEN_DEVICE)
{
seat->has_touchscreen = TRUE;
check_touch_mode = TRUE;
@@ -1469,7 +1503,12 @@ evdev_remove_device (MetaSeatNative *seat,
device_type = clutter_input_device_get_device_type (device);
if (device_type == CLUTTER_TOUCHSCREEN_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)
{
seat->has_touchscreen = has_touchscreen (seat);
update_touch_mode (seat);
@@ -2514,6 +2553,7 @@ 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,6 +120,7 @@ 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

@@ -24,75 +24,14 @@
#include "backends/x11/cm/meta-renderer-x11-cm.h"
#include "backends/meta-renderer-view.h"
struct _MetaRendererX11Cm
{
MetaRendererX11 parent;
MetaRendererView *screen_view;
};
G_DEFINE_TYPE (MetaRendererX11Cm, meta_renderer_x11_cm,
META_TYPE_RENDERER_X11)
void
meta_renderer_x11_cm_ensure_screen_view (MetaRendererX11Cm *renderer_x11_cm,
int width,
int height)
{
cairo_rectangle_int_t view_layout;
if (renderer_x11_cm->screen_view)
return;
view_layout = (cairo_rectangle_int_t) {
.width = width,
.height = height,
};
renderer_x11_cm->screen_view = g_object_new (META_TYPE_RENDERER_VIEW,
"layout", &view_layout,
NULL);
meta_renderer_add_view (META_RENDERER (renderer_x11_cm),
renderer_x11_cm->screen_view);
}
void
meta_renderer_x11_cm_resize (MetaRendererX11Cm *renderer_x11_cm,
int width,
int height)
{
cairo_rectangle_int_t view_layout;
view_layout = (cairo_rectangle_int_t) {
.width = width,
.height = height,
};
g_object_set (G_OBJECT (renderer_x11_cm->screen_view),
"layout", &view_layout,
NULL);
}
void
meta_renderer_x11_cm_set_onscreen (MetaRendererX11Cm *renderer_x11_cm,
CoglOnscreen *onscreen)
{
g_object_set (G_OBJECT (renderer_x11_cm->screen_view),
"framebuffer", onscreen,
NULL);
}
static void
meta_renderer_x11_cm_rebuild_views (MetaRenderer *renderer)
{
MetaRendererX11Cm *renderer_x11_cm = META_RENDERER_X11_CM (renderer);
g_return_if_fail (!meta_renderer_get_views (renderer));
meta_renderer_add_view (renderer, renderer_x11_cm->screen_view);
}
static void
meta_renderer_x11_cm_init (MetaRendererX11Cm *renderer_x11_cm)
{
@@ -101,7 +40,4 @@ meta_renderer_x11_cm_init (MetaRendererX11Cm *renderer_x11_cm)
static void
meta_renderer_x11_cm_class_init (MetaRendererX11CmClass *klass)
{
MetaRendererClass *renderer_class = META_RENDERER_CLASS (klass);
renderer_class->rebuild_views = meta_renderer_x11_cm_rebuild_views;
}

View File

@@ -30,15 +30,4 @@ G_DECLARE_FINAL_TYPE (MetaRendererX11Cm, meta_renderer_x11_cm,
META, RENDERER_X11_CM,
MetaRendererX11)
void meta_renderer_x11_cm_ensure_screen_view (MetaRendererX11Cm *renderer_x11_cm,
int width,
int height);
void meta_renderer_x11_cm_resize (MetaRendererX11Cm *renderer_x11_cm,
int width,
int height);
void meta_renderer_x11_cm_set_onscreen (MetaRendererX11Cm *renderer_x11_cm,
CoglOnscreen *onscreen);
#endif /* META_RENDERER_X11_CM_H */

View File

@@ -855,7 +855,6 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
static void
meta_backend_x11_init (MetaBackendX11 *x11)
{
XInitThreads ();
}
Display *

View File

@@ -38,10 +38,7 @@ enum
PROP_OPCODE,
PROP_POINTER_ID,
PROP_KEYBOARD_ID,
N_PROPS,
/* This property is overridden */
PROP_TOUCH_MODE,
N_PROPS
};
struct _MetaSeatX11
@@ -57,8 +54,6 @@ struct _MetaSeatX11
int pointer_id;
int keyboard_id;
int opcode;
guint has_touchscreens : 1;
guint touch_mode : 1;
};
static GParamSpec *props[N_PROPS] = { 0 };
@@ -610,20 +605,6 @@ 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,
@@ -654,8 +635,6 @@ 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
{
@@ -684,38 +663,18 @@ 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)
@@ -736,12 +695,6 @@ 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
@@ -1319,7 +1272,6 @@ 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);
}
@@ -1344,9 +1296,6 @@ 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);
}
@@ -1598,9 +1547,6 @@ 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

@@ -26,17 +26,15 @@
#include <unistd.h>
#endif
#include "backends/x11/cm/meta-backend-x11-cm.h"
#include "backends/x11/cm/meta-renderer-x11-cm.h"
#include "backends/x11/meta-backend-x11.h"
#include "backends/x11/meta-seat-x11.h"
#include "backends/x11/meta-stage-x11.h"
#include "clutter/clutter-mutter.h"
#include "clutter/x11/clutter-x11.h"
#include "clutter/x11/clutter-backend-x11.h"
#include "cogl/cogl.h"
#include "core/display-private.h"
#include "meta/meta-x11-errors.h"
#include "meta-backend-x11.h"
#include "meta-seat-x11.h"
#include "meta-stage-x11.h"
#define STAGE_X11_IS_MAPPED(s) ((((MetaStageX11 *) (s))->wm_state & STAGE_X11_WITHDRAWN) == 0)
@@ -289,6 +287,8 @@ meta_stage_x11_unrealize (ClutterStageWindow *stage_window)
clutter_stage_window_parent_iface->unrealize (stage_window);
g_list_free (stage_x11->legacy_views);
g_clear_object (&stage_x11->legacy_view);
g_clear_pointer (&stage_x11->onscreen, cogl_object_unref);
}
@@ -330,13 +330,10 @@ meta_stage_x11_realize (ClutterStageWindow *stage_window)
stage_cogl,
NULL);
if (META_IS_BACKEND_X11_CM (stage_x11->backend))
{
MetaRenderer *renderer = meta_backend_get_renderer (stage_x11->backend);
MetaRendererX11Cm *renderer_x11_cm = META_RENDERER_X11_CM (renderer);
meta_renderer_x11_cm_set_onscreen (renderer_x11_cm, stage_x11->onscreen);
}
if (stage_x11->legacy_view)
g_object_set (G_OBJECT (stage_x11->legacy_view),
"framebuffer", stage_x11->onscreen,
NULL);
/* We just created a window of the size of the actor. No need to fix
the size of the stage, just update it. */
@@ -525,13 +522,34 @@ meta_stage_x11_can_clip_redraws (ClutterStageWindow *stage_window)
return stage_x11->clipped_redraws_cool_off == 0;
}
static void
ensure_legacy_view (ClutterStageWindow *stage_window)
{
MetaStageX11 *stage_x11 = META_STAGE_X11 (stage_window);
cairo_rectangle_int_t view_layout;
CoglFramebuffer *framebuffer;
if (stage_x11->legacy_view)
return;
_clutter_stage_window_get_geometry (stage_window, &view_layout);
framebuffer = COGL_FRAMEBUFFER (stage_x11->onscreen);
stage_x11->legacy_view = g_object_new (CLUTTER_TYPE_STAGE_VIEW_COGL,
"layout", &view_layout,
"framebuffer", framebuffer,
NULL);
stage_x11->legacy_views = g_list_append (stage_x11->legacy_views,
stage_x11->legacy_view);
}
static GList *
meta_stage_x11_get_views (ClutterStageWindow *stage_window)
{
MetaStageX11 *stage_x11 = META_STAGE_X11 (stage_window);
MetaRenderer *renderer = meta_backend_get_renderer (stage_x11->backend);
return meta_renderer_get_views (renderer);
ensure_legacy_view (stage_window);
return stage_x11->legacy_views;
}
static int64_t
@@ -563,9 +581,6 @@ meta_stage_x11_class_init (MetaStageX11Class *klass)
static void
meta_stage_x11_init (MetaStageX11 *stage)
{
MetaRenderer *renderer;
MetaRendererX11Cm *renderer_x11_cm;
stage->xwin = None;
stage->xwin_width = 640;
stage->xwin_height = 480;
@@ -576,19 +591,6 @@ meta_stage_x11_init (MetaStageX11 *stage)
stage->accept_focus = TRUE;
stage->title = NULL;
stage->backend = meta_get_backend ();
g_assert (stage->backend);
if (META_IS_BACKEND_X11_CM (stage->backend))
{
renderer = meta_backend_get_renderer (stage->backend);
renderer_x11_cm = META_RENDERER_X11_CM (renderer);
meta_renderer_x11_cm_ensure_screen_view (renderer_x11_cm,
stage->xwin_width,
stage->xwin_height);
}
}
static void
@@ -776,16 +778,16 @@ meta_stage_x11_translate_event (MetaStageX11 *stage_x11,
* X11 compositing manager, we need to reset the legacy
* stage view, now that it has a new size.
*/
if (META_IS_BACKEND_X11_CM (stage_x11->backend))
if (stage_x11->legacy_view)
{
MetaBackend *backend = stage_x11->backend;
MetaRenderer *renderer = meta_backend_get_renderer (backend);
MetaRendererX11Cm *renderer_x11_cm =
META_RENDERER_X11_CM (renderer);
cairo_rectangle_int_t view_layout = {
.width = stage_width,
.height = stage_height
};
meta_renderer_x11_cm_resize (renderer_x11_cm,
stage_width,
stage_height);
g_object_set (G_OBJECT (stage_x11->legacy_view),
"layout", &view_layout,
NULL);
}
}
}

View File

@@ -25,7 +25,6 @@
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include "backends/meta-backend-private.h"
#include "clutter/clutter-mutter.h"
#include "clutter/x11/clutter-x11.h"
@@ -52,13 +51,14 @@ struct _MetaStageX11
{
ClutterStageCogl parent_instance;
MetaBackend *backend;
CoglOnscreen *onscreen;
Window xwin;
gint xwin_width;
gint xwin_height; /* FIXME target_width / height */
ClutterStageView *legacy_view;
GList *legacy_views;
CoglFrameClosure *frame_closure;
gchar *title;

View File

@@ -167,8 +167,7 @@ meta_renderer_x11_nested_ensure_legacy_view (MetaRendererX11Nested *renderer_x11
"framebuffer", COGL_FRAMEBUFFER (fake_onscreen),
NULL);
g_assert (!meta_renderer_get_views (renderer));
meta_renderer_add_view (renderer, legacy_view);
meta_renderer_set_legacy_view (renderer, legacy_view);
}
static MetaRendererView *

View File

@@ -63,6 +63,7 @@
#include "clutter/clutter-mutter.h"
#include "cogl/cogl.h"
#include "compositor/meta-window-actor-x11.h"
#include "compositor/meta-window-actor-wayland.h"
#include "compositor/meta-window-actor-private.h"
#include "compositor/meta-window-group-private.h"
#include "core/display-private.h"
@@ -81,7 +82,6 @@
#include "x11/meta-x11-display-private.h"
#ifdef HAVE_WAYLAND
#include "compositor/meta-window-actor-wayland.h"
#include "wayland/meta-wayland-private.h"
#endif

View File

@@ -85,8 +85,6 @@ struct _MetaWindowActorX11
cairo_region_t *shape_region;
/* The region we should clip to when painting the shadow */
cairo_region_t *shadow_clip;
/* The frame region */
cairo_region_t *frame_bounds;
/* Extracted size-invariant shape used for shadows */
MetaWindowShape *shadow_shape;
@@ -704,8 +702,11 @@ set_clip_region_beneath (MetaWindowActorX11 *actor_x11,
if (clip_shadow_under_window (actor_x11))
{
if (actor_x11->frame_bounds)
cairo_region_subtract (actor_x11->shadow_clip, actor_x11->frame_bounds);
cairo_region_t *frame_bounds;
frame_bounds = meta_window_get_frame_bounds (window);
if (frame_bounds)
cairo_region_subtract (actor_x11->shadow_clip, frame_bounds);
}
}
else
@@ -1125,17 +1126,6 @@ update_opaque_region (MetaWindowActorX11 *actor_x11)
cairo_region_destroy (opaque_region);
}
static void
update_frame_bounds (MetaWindowActorX11 *actor_x11)
{
MetaWindow *window =
meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11));
g_clear_pointer (&actor_x11->frame_bounds, cairo_region_destroy);
actor_x11->frame_bounds =
cairo_region_copy (meta_window_get_frame_bounds (window));
}
static void
update_regions (MetaWindowActorX11 *actor_x11)
{
@@ -1207,7 +1197,6 @@ handle_updates (MetaWindowActorX11 *actor_x11)
if (!meta_surface_actor_is_visible (surface))
return;
update_frame_bounds (actor_x11);
check_needs_reshape (actor_x11);
check_needs_shadow (actor_x11);
}
@@ -1261,13 +1250,15 @@ meta_window_actor_x11_paint (ClutterActor *actor,
*/
if (!clip && clip_shadow_under_window (actor_x11))
{
cairo_region_t *frame_bounds;
cairo_rectangle_int_t bounds;
get_shadow_bounds (actor_x11, appears_focused, &bounds);
clip = cairo_region_create_rectangle (&bounds);
if (actor_x11->frame_bounds)
cairo_region_subtract (clip, actor_x11->frame_bounds);
frame_bounds = meta_window_get_frame_bounds (window);
if (frame_bounds)
cairo_region_subtract (clip, frame_bounds);
}
framebuffer = clutter_paint_context_get_framebuffer (paint_context);
@@ -1554,7 +1545,6 @@ meta_window_actor_x11_dispose (GObject *object)
g_clear_pointer (&actor_x11->shape_region, cairo_region_destroy);
g_clear_pointer (&actor_x11->shadow_clip, cairo_region_destroy);
g_clear_pointer (&actor_x11->frame_bounds, cairo_region_destroy);
g_clear_pointer (&actor_x11->shadow_class, g_free);
g_clear_pointer (&actor_x11->focused_shadow, meta_shadow_unref);

View File

@@ -2129,7 +2129,7 @@ process_special_modifier_key (MetaDisplay *display,
return TRUE;
}
else if (event->type == CLUTTER_KEY_PRESS &&
((event->modifier_state & ~(IGNORED_MODIFIERS)) & CLUTTER_MODIFIER_MASK) == 0 &&
(event->modifier_state & ~(IGNORED_MODIFIERS)) == 0 &&
resolved_key_combo_has_keycode (resolved_key_combo,
event->hardware_keycode))
{
@@ -3302,15 +3302,7 @@ handle_toggle_tiled (MetaDisplay *display,
if ((META_WINDOW_TILED_LEFT (window) && mode == META_TILE_LEFT) ||
(META_WINDOW_TILED_RIGHT (window) && mode == META_TILE_RIGHT))
{
window->tile_monitor_number = window->saved_maximize ? window->monitor->number
: -1;
window->tile_mode = window->saved_maximize ? META_TILE_MAXIMIZED
: META_TILE_NONE;
if (window->saved_maximize)
meta_window_maximize (window, META_MAXIMIZE_BOTH);
else
meta_window_unmaximize (window, META_MAXIMIZE_BOTH);
meta_window_untile (window);
}
else if (meta_window_can_tile_side_by_side (window))
{

View File

@@ -1,32 +0,0 @@
/*
* Copyright (C) 2020 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:
* Carlos Garnacho <carlosg@gnome.org>
*/
#ifndef META_SELECTION_PRIVATE_H
#define META_SELECTION_PRIVATE_H
#include "meta/meta-selection.h"
MetaSelectionSource *
meta_selection_get_current_owner (MetaSelection *selection,
MetaSelectionType selection_type);
#endif /* META_SELECTION_PRIVATE_H */

View File

@@ -21,7 +21,6 @@
#include "config.h"
#include "core/meta-selection-private.h"
#include "meta/meta-selection.h"
typedef struct TransferRequest TransferRequest;
@@ -51,9 +50,6 @@ static guint signals[N_SIGNALS] = { 0 };
G_DEFINE_TYPE (MetaSelection, meta_selection, G_TYPE_OBJECT)
static void read_selection_source_async (GTask *task,
TransferRequest *request);
static void
meta_selection_dispose (GObject *object)
{
@@ -220,7 +216,6 @@ write_cb (GOutputStream *stream,
GAsyncResult *result,
GTask *task)
{
TransferRequest *request;
GError *error = NULL;
g_output_stream_write_bytes_finish (stream, result, &error);
@@ -231,17 +226,8 @@ write_cb (GOutputStream *stream,
return;
}
request = g_task_get_task_data (task);
if (request->len > 0)
{
read_selection_source_async (task, request);
}
else
{
g_task_return_boolean (task, TRUE);
g_object_unref (task);
}
g_task_return_boolean (task, TRUE);
g_object_unref (task);
}
static void
@@ -260,26 +246,8 @@ read_cb (GInputStream *stream,
g_object_unref (task);
return;
}
else if (g_bytes_get_size (bytes) == 0)
{
g_task_return_boolean (task, TRUE);
g_object_unref (task);
return;
}
request = g_task_get_task_data (task);
if (request->len < g_bytes_get_size (bytes))
{
GBytes *copy;
/* Trim content */
copy = g_bytes_new_from_bytes (bytes, 0, request->len);
g_bytes_unref (bytes);
bytes = copy;
}
request->len -= g_bytes_get_size (bytes);
g_output_stream_write_bytes_async (request->ostream,
bytes,
G_PRIORITY_DEFAULT,
@@ -289,18 +257,6 @@ read_cb (GInputStream *stream,
g_bytes_unref (bytes);
}
static void
read_selection_source_async (GTask *task,
TransferRequest *request)
{
g_input_stream_read_bytes_async (request->istream,
(gsize) request->len,
G_PRIORITY_DEFAULT,
g_task_get_cancellable (task),
(GAsyncReadyCallback) read_cb,
task);
}
static void
source_read_cb (MetaSelectionSource *source,
GAsyncResult *result,
@@ -334,7 +290,12 @@ source_read_cb (MetaSelectionSource *source,
}
else
{
read_selection_source_async (task, request);
g_input_stream_read_bytes_async (request->istream,
(gsize) request->len,
G_PRIORITY_DEFAULT,
g_task_get_cancellable (task),
(GAsyncReadyCallback) read_cb,
task);
}
}
@@ -403,13 +364,3 @@ meta_selection_transfer_finish (MetaSelection *selection,
return g_task_propagate_boolean (G_TASK (result), error);
}
MetaSelectionSource *
meta_selection_get_current_owner (MetaSelection *selection,
MetaSelectionType selection_type)
{
g_return_val_if_fail (META_IS_SELECTION (selection), NULL);
g_return_val_if_fail (selection_type < META_N_SELECTION_TYPES, NULL);
return selection->owners[selection_type];
}

View File

@@ -656,6 +656,9 @@ void meta_window_unmanage (MetaWindow *window,
void meta_window_unmanage_on_idle (MetaWindow *window);
void meta_window_queue (MetaWindow *window,
guint queuebits);
META_EXPORT_TEST
void meta_window_untile (MetaWindow *window);
META_EXPORT_TEST
void meta_window_tile (MetaWindow *window,
MetaTileMode mode);

View File

@@ -3148,6 +3148,22 @@ update_edge_constraints (MetaWindow *window)
}
}
void
meta_window_untile (MetaWindow *window)
{
window->tile_monitor_number =
window->saved_maximize ? window->monitor->number
: -1;
window->tile_mode =
window->saved_maximize ? META_TILE_MAXIMIZED
: META_TILE_NONE;
if (window->saved_maximize)
meta_window_maximize (window, META_MAXIMIZE_BOTH);
else
meta_window_unmaximize (window, META_MAXIMIZE_BOTH);
}
void
meta_window_tile (MetaWindow *window,
MetaTileMode tile_mode)
@@ -3164,6 +3180,10 @@ meta_window_tile (MetaWindow *window,
window->tile_monitor_number = -1;
return;
}
else
{
window->tile_monitor_number = window->monitor->number;
}
if (window->tile_mode == META_TILE_MAXIMIZED)
directions = META_MAXIMIZE_BOTH;

View File

@@ -141,6 +141,11 @@ stacking_tests = [
'override-redirect',
'set-override-redirect-parent',
'set-parent-exported',
'restore-size',
'unmaximize-new-size',
'fullscreen-maximize',
'restore-position',
'default-size',
]
foreach stacking_test: stacking_tests

View File

@@ -1,23 +0,0 @@
<monitors version="2">
<configuration>
<logicalmonitor>
<x>0</x>
<y>0</y>
<primary>yes</primary>
<scale>2</scale>
<monitor>
<monitorspec>
<connector>eDP-1</connector>
<vendor>MetaProduct's Inc.</vendor>
<product>MetaMonitor</product>
<serial>0x123456</serial>
</monitorspec>
<mode>
<width>1920</width>
<height>1080</height>
<rate>60.000495910644531</rate>
</mode>
</monitor>
</logicalmonitor>
</configuration>
</monitors>

View File

@@ -2868,116 +2868,6 @@ meta_test_monitor_lid_closed_with_hotplugged_external (void)
check_monitor_configuration (&test_case);
}
static void
meta_test_monitor_lid_scaled_closed_opened (void)
{
MonitorTestCase test_case = {
.setup = {
.modes = {
{
.width = 1920,
.height = 1080,
.refresh_rate = 60.000495910644531
}
},
.n_modes = 1,
.outputs = {
{
.crtc = 0,
.modes = { 0 },
.n_modes = 1,
.preferred_mode = 0,
.possible_crtcs = { 0 },
.n_possible_crtcs = 1,
.width_mm = 222,
.height_mm = 125,
.is_laptop_panel = TRUE
},
},
.n_outputs = 1,
.crtcs = {
{
.current_mode = 0
},
},
.n_crtcs = 1
},
.expect = {
.monitors = {
{
.outputs = { 0 },
.n_outputs = 1,
.modes = {
{
.width = 1920,
.height = 1080,
.refresh_rate = 60.000495910644531,
.crtc_modes = {
{
.output = 0,
.crtc_mode = 0
}
}
}
},
.n_modes = 1,
.current_mode = 0,
.width_mm = 222,
.height_mm = 125,
}
},
.n_monitors = 1,
.logical_monitors = {
{
.monitors = { 0 },
.n_monitors = 1,
.layout = { .x = 0, .y = 0, .width = 960, .height = 540 },
.scale = 2
}
},
.n_logical_monitors = 1,
.primary_logical_monitor = 0,
.n_outputs = 1,
.crtcs = {
{
.current_mode = 0,
}
},
.n_crtcs = 1,
.n_tiled_monitors = 0,
.screen_width = 960,
.screen_height = 540
}
};
MetaMonitorTestSetup *test_setup;
MetaBackend *backend = meta_get_backend ();
MetaMonitorManager *monitor_manager =
meta_backend_get_monitor_manager (backend);
if (!meta_is_stage_views_enabled ())
{
g_test_skip ("Not using stage views");
return;
}
test_setup = create_monitor_test_setup (&test_case,
MONITOR_TEST_FLAG_NONE);
set_custom_monitor_config ("lid-scale.xml");
emulate_hotplug (test_setup);
check_monitor_configuration (&test_case);
meta_backend_test_set_is_lid_closed (META_BACKEND_TEST (backend), TRUE);
meta_monitor_manager_lid_is_closed_changed (monitor_manager);
check_monitor_configuration (&test_case);
meta_backend_test_set_is_lid_closed (META_BACKEND_TEST (backend), FALSE);
meta_monitor_manager_lid_is_closed_changed (monitor_manager);
check_monitor_configuration (&test_case);
}
static void
meta_test_monitor_no_outputs (void)
{
@@ -4938,13 +4828,12 @@ meta_test_monitor_custom_second_rotated_tiled_config (void)
.current_mode = 1,
.transform = META_MONITOR_TRANSFORM_90,
.x = 1024,
.y = 0,
.y = 400,
},
{
.current_mode = 1,
.transform = META_MONITOR_TRANSFORM_90,
.x = 1024,
.y = 400,
}
},
.n_crtcs = 3,
@@ -4970,198 +4859,6 @@ meta_test_monitor_custom_second_rotated_tiled_config (void)
check_monitor_configuration (&test_case);
}
static void
meta_test_monitor_custom_second_rotated_nonnative_tiled_config (void)
{
MonitorTestCase test_case = {
.setup = {
.modes = {
{
.width = 1024,
.height = 768,
.refresh_rate = 60.000495910644531
},
{
.width = 400,
.height = 600,
.refresh_rate = 60.000495910644531
}
},
.n_modes = 2,
.outputs = {
{
.crtc = 0,
.modes = { 0 },
.n_modes = 1,
.preferred_mode = 0,
.possible_crtcs = { 0 },
.n_possible_crtcs = 1,
.width_mm = 222,
.height_mm = 125,
},
{
.crtc = -1,
.modes = { 1 },
.n_modes = 1,
.preferred_mode = 1,
.possible_crtcs = { 1, 2 },
.n_possible_crtcs = 2,
.width_mm = 222,
.height_mm = 125,
.tile_info = {
.group_id = 1,
.max_h_tiles = 2,
.max_v_tiles = 1,
.loc_h_tile = 0,
.loc_v_tile = 0,
.tile_w = 400,
.tile_h = 600
}
},
{
.crtc = -1,
.modes = { 1 },
.n_modes = 1,
.preferred_mode = 1,
.possible_crtcs = { 1, 2 },
.n_possible_crtcs = 2,
.width_mm = 222,
.height_mm = 125,
.tile_info = {
.group_id = 1,
.max_h_tiles = 2,
.max_v_tiles = 1,
.loc_h_tile = 1,
.loc_v_tile = 0,
.tile_w = 400,
.tile_h = 600
}
}
},
.n_outputs = 3,
.crtcs = {
{
.current_mode = -1
},
{
.current_mode = -1
},
{
.current_mode = -1
}
},
.n_crtcs = 3
},
.expect = {
.monitors = {
{
.outputs = { 0 },
.n_outputs = 1,
.modes = {
{
.width = 1024,
.height = 768,
.refresh_rate = 60.000495910644531,
.crtc_modes = {
{
.output = 0,
.crtc_mode = 0
}
}
}
},
.n_modes = 1,
.current_mode = 0,
.width_mm = 222,
.height_mm = 125,
},
{
.outputs = { 1, 2 },
.n_outputs = 2,
.modes = {
{
.width = 800,
.height = 600,
.refresh_rate = 60.000495910644531,
.crtc_modes = {
{
.output = 1,
.crtc_mode = 1,
},
{
.output = 2,
.crtc_mode = 1,
}
}
}
},
.n_modes = 1,
.current_mode = 0,
.width_mm = 222,
.height_mm = 125,
}
},
.n_monitors = 2,
.logical_monitors = {
{
.monitors = { 0 },
.n_monitors = 1,
.layout = { .x = 0, .y = 256, .width = 1024, .height = 768 },
.scale = 1
},
{
.monitors = { 1 },
.n_monitors = 1,
.layout = { .x = 1024, .y = 0, .width = 600, .height = 800 },
.scale = 1,
.transform = META_MONITOR_TRANSFORM_90
}
},
.n_logical_monitors = 2,
.primary_logical_monitor = 0,
.n_outputs = 3,
.crtcs = {
{
.current_mode = 0,
.y = 256,
},
{
.current_mode = 1,
.transform = META_MONITOR_TRANSFORM_NORMAL,
.x = 1024,
.y = 0,
},
{
.current_mode = 1,
.transform = META_MONITOR_TRANSFORM_NORMAL,
.x = 1024,
.y = 400,
}
},
.n_crtcs = 3,
.n_tiled_monitors = 1,
.screen_width = 1024 + 600,
.screen_height = 1024
}
};
MetaMonitorTestSetup *test_setup;
MetaBackend *backend = meta_get_backend ();
MetaMonitorManager *monitor_manager =
meta_backend_get_monitor_manager (backend);
MetaMonitorManagerTest *monitor_manager_test =
META_MONITOR_MANAGER_TEST (monitor_manager);
meta_monitor_manager_test_set_handles_transforms (monitor_manager_test,
FALSE);
test_setup = create_monitor_test_setup (&test_case,
MONITOR_TEST_FLAG_NONE);
set_custom_monitor_config ("second-rotated-tiled.xml");
emulate_hotplug (test_setup);
check_monitor_configuration (&test_case);
}
static void
meta_test_monitor_custom_second_rotated_nonnative_config (void)
{
@@ -6361,8 +6058,6 @@ init_monitor_tests (void)
meta_test_monitor_lid_closed_no_external);
add_monitor_test ("/backends/monitor/lid-closed-with-hotplugged-external",
meta_test_monitor_lid_closed_with_hotplugged_external);
add_monitor_test ("/backends/monitor/lid-scaled-closed-opened",
meta_test_monitor_lid_scaled_closed_opened);
add_monitor_test ("/backends/monitor/no-outputs",
meta_test_monitor_no_outputs);
add_monitor_test ("/backends/monitor/underscanning-config",
@@ -6398,8 +6093,6 @@ init_monitor_tests (void)
meta_test_monitor_custom_second_rotated_config);
add_monitor_test ("/backends/monitor/custom/second-rotated-tiled-config",
meta_test_monitor_custom_second_rotated_tiled_config);
add_monitor_test ("/backends/monitor/custom/second-rotated-nonnative-tiled-config",
meta_test_monitor_custom_second_rotated_nonnative_tiled_config);
add_monitor_test ("/backends/monitor/custom/second-rotated-nonnative-config",
meta_test_monitor_custom_second_rotated_nonnative_config);
add_monitor_test ("/backends/monitor/custom/interlaced-config",

View File

@@ -0,0 +1,36 @@
new_client x x11
create x/1 csd
resize x/1 300 400
show x/1
wait
assert_size x/1 300 400
resize x/1 200 300
wait
assert_size x/1 200 300
hide x/1
show x/1
wait
assert_size x/1 200 300
new_client w wayland
create w/1 csd
resize w/1 300 400
show w/1
wait
assert_size w/1 300 400
resize w/1 200 300
wait_reconfigure
assert_size w/1 200 300
hide w/1
show w/1
wait_reconfigure
assert_size w/1 200 300

View File

@@ -0,0 +1,73 @@
# Tests that the following works, both on Wayland and X11
# 1. Create a window with a known size
# 2. Maxmize window results in maximized size
# 3. Fullscreen window results in fullscreen size
# 4. Unfullscreen window results in maximized size
# 5. Unmaximize window results in original size
# 6. Toggling fullscreen ends up with original size
new_client w wayland
create w/1 csd
resize w/1 500 400
show w/1
wait
assert_size w/1 500 400
maximize w/1
wait_reconfigure
assert_size w/1 MONITOR_WIDTH MONITOR_HEIGHT
fullscreen w/1
wait_reconfigure
assert_size w/1 MONITOR_WIDTH MONITOR_HEIGHT
unfullscreen w/1
wait_reconfigure
assert_size w/1 MONITOR_WIDTH MONITOR_HEIGHT
unmaximize w/1
wait_reconfigure
assert_size w/1 500 400
fullscreen w/1
wait_reconfigure
assert_size w/1 MONITOR_WIDTH MONITOR_HEIGHT
unfullscreen w/1
wait_reconfigure
assert_size w/1 500 400
new_client x x11
create x/1 csd
resize x/1 500 400
show x/1
wait
assert_size x/1 500 400
maximize x/1
wait_reconfigure
assert_size x/1 MONITOR_WIDTH MONITOR_HEIGHT
fullscreen x/1
wait_reconfigure
assert_size x/1 MONITOR_WIDTH MONITOR_HEIGHT
unfullscreen x/1
wait_reconfigure
assert_size x/1 MONITOR_WIDTH MONITOR_HEIGHT
unmaximize x/1
wait_reconfigure
assert_size x/1 500 400
fullscreen x/1
wait_reconfigure
assert_size x/1 MONITOR_WIDTH MONITOR_HEIGHT
unfullscreen x/1
wait_reconfigure
assert_size x/1 500 400

View File

@@ -0,0 +1,73 @@
# X11
new_client x x11
create x/1 csd
show x/1
move x/1 100 100
assert_position x/1 100 100
maximize x/1
wait_reconfigure
assert_position x/1 0 0
unmaximize x/1
wait_reconfigure
assert_position x/1 100 100
tile x/1 left
wait
assert_position x/1 0 0
untile x/1
wait
assert_position x/1 100 100
tile x/1 left
wait
assert_position x/1 0 0
maximize x/1
wait_reconfigure
assert_position x/1 0 0
unmaximize x/1
wait_reconfigure
assert_position x/1 100 100
# Wayland
new_client w wayland
create w/1 csd
show w/1
move w/1 100 100
assert_position w/1 100 100
maximize w/1
wait_reconfigure
assert_position w/1 0 0
unmaximize w/1
wait_reconfigure
assert_position w/1 100 100
tile w/1 left
wait_reconfigure
assert_position w/1 0 0
untile w/1
wait
assert_position w/1 100 100
tile w/1 left
wait
assert_position w/1 0 0
maximize w/1
wait_reconfigure
assert_position w/1 0 0
unmaximize w/1
wait_reconfigure
assert_position w/1 100 100

View File

@@ -0,0 +1,93 @@
# Check that X11 clients restore to their right size after unmaximize
# or untile
new_client x x11
create x/1 csd
resize x/1 500 400
maximize x/1
show x/1
wait
assert_size x/1 MONITOR_WIDTH MONITOR_HEIGHT
unmaximize x/1
wait
assert_size x/1 500 400
resize x/1 300 200
maximize x/1
wait
unmaximize x/1
wait
assert_size x/1 300 200
tile x/1 right
wait
assert_size x/1 MONITOR_WIDTH/2 MONITOR_HEIGHT
untile x/1
wait
assert_size x/1 300 200
tile x/1 left
wait
assert_size x/1 MONITOR_WIDTH/2 MONITOR_HEIGHT
maximize x/1
wait_reconfigure
assert_size x/1 MONITOR_WIDTH MONITOR_HEIGHT
unmaximize x/1
wait_reconfigure
assert_size x/1 300 200
# Check that Wayland clients restore to their right size after unmaximize
# or untile
new_client w wayland
create w/1 csd
resize w/1 150 300
maximize w/1
show w/1
wait
assert_size w/1 MONITOR_WIDTH MONITOR_HEIGHT
unmaximize w/1
wait_reconfigure
assert_size w/1 150 300
resize w/1 300 200
maximize w/1
wait
unmaximize w/1
wait_reconfigure
assert_size w/1 300 200
tile w/1 right
wait
assert_size w/1 MONITOR_WIDTH/2 MONITOR_HEIGHT
untile w/1
wait
assert_size w/1 300 200
tile w/1 left
wait
assert_size w/1 MONITOR_WIDTH/2 MONITOR_HEIGHT
maximize w/1
wait_reconfigure
assert_size w/1 MONITOR_WIDTH MONITOR_HEIGHT
unmaximize w/1
wait_reconfigure
assert_size w/1 300 200

View File

@@ -0,0 +1,22 @@
# This is only tested on Wayland since it's broken on X11
new_client w wayland
create w/1 csd
resize w/1 500 400
show w/1
wait
assert_size w/1 500 400
maximize w/1
wait_reconfigure
assert_size w/1 MONITOR_WIDTH MONITOR_HEIGHT
resize w/1 300 500
wait_reconfigure
assert_size w/1 MONITOR_WIDTH MONITOR_HEIGHT
unmaximize w/1
wait_reconfigure
assert_size w/1 300 500

View File

@@ -48,7 +48,7 @@ window_export_handle_cb (GdkWindow *window,
if (!gdk_wayland_window_set_transient_for_exported (gdk_window,
(gchar *) handle_str))
g_print ("Fail to set transient_for exported window handle %s", handle_str);
g_print ("Fail to set transient_for exported window handle %s\n", handle_str);
gdk_window_set_modal_hint (gdk_window, TRUE);
}
@@ -57,7 +57,7 @@ lookup_window (const char *window_id)
{
GtkWidget *window = g_hash_table_lookup (windows, window_id);
if (!window)
g_print ("Window %s doesn't exist", window_id);
g_print ("Window %s doesn't exist\n", window_id);
return window;
}
@@ -242,6 +242,23 @@ handle_take_focus (GtkWidget *window,
}
}
static int
calculate_titlebar_height (GtkWindow *window)
{
GtkWidget *titlebar;
GdkWindow *gdk_window;
gdk_window = gtk_widget_get_window (GTK_WIDGET (window));
if (gdk_window_get_state (gdk_window) & GDK_WINDOW_STATE_FULLSCREEN)
return 0;
titlebar = gtk_window_get_titlebar (window);
if (!titlebar)
return 0;
return gtk_widget_get_allocated_height (titlebar);
}
static void
process_line (const char *line)
{
@@ -251,14 +268,14 @@ process_line (const char *line)
if (!g_shell_parse_argv (line, &argc, &argv, &error))
{
g_print ("error parsing command: %s", error->message);
g_print ("error parsing command: %s\n", error->message);
g_error_free (error);
return;
}
if (argc < 1)
{
g_print ("Empty command");
g_print ("Empty command\n");
goto out;
}
@@ -268,13 +285,13 @@ process_line (const char *line)
if (argc < 2)
{
g_print ("usage: create <id> [override|csd]");
g_print ("usage: create <id> [override|csd]\n");
goto out;
}
if (g_hash_table_lookup (windows, argv[1]))
{
g_print ("window %s already exists", argv[1]);
g_print ("window %s already exists\n", argv[1]);
goto out;
}
@@ -290,7 +307,7 @@ process_line (const char *line)
if (override && csd)
{
g_print ("override and csd keywords are exclusie");
g_print ("override and csd keywords are exclusive\n");
goto out;
}
@@ -334,21 +351,21 @@ process_line (const char *line)
{
if (argc != 3)
{
g_print ("usage: set_parent <window-id> <parent-id>");
g_print ("usage: set_parent <window-id> <parent-id>\n");
goto out;
}
GtkWidget *window = lookup_window (argv[1]);
if (!window)
{
g_print ("unknown window %s", argv[1]);
g_print ("unknown window %s\n", argv[1]);
goto out;
}
GtkWidget *parent_window = lookup_window (argv[2]);
if (!parent_window)
{
g_print ("unknown parent window %s", argv[2]);
g_print ("unknown parent window %s\n", argv[2]);
goto out;
}
@@ -359,21 +376,21 @@ process_line (const char *line)
{
if (argc != 3)
{
g_print ("usage: set_parent_exported <window-id> <parent-id>");
g_print ("usage: set_parent_exported <window-id> <parent-id>\n");
goto out;
}
GtkWidget *window = lookup_window (argv[1]);
if (!window)
{
g_print ("unknown window %s", argv[1]);
g_print ("unknown window %s\n", argv[1]);
goto out;
}
GtkWidget *parent_window = lookup_window (argv[2]);
if (!parent_window)
{
g_print ("unknown parent window %s", argv[2]);
g_print ("unknown parent window %s\n", argv[2]);
goto out;
}
@@ -382,27 +399,27 @@ process_line (const char *line)
window_export_handle_cb,
window,
NULL))
g_print ("Fail to export handle for window id %s", argv[2]);
g_print ("Fail to export handle for window id %s\n", argv[2]);
}
else if (strcmp (argv[0], "accept_focus") == 0)
{
if (argc != 3)
{
g_print ("usage: %s <window-id> [true|false]", argv[0]);
g_print ("usage: %s <window-id> [true|false]\n", argv[0]);
goto out;
}
GtkWidget *window = lookup_window (argv[1]);
if (!window)
{
g_print ("unknown window %s", argv[1]);
g_print ("unknown window %s\n", argv[1]);
goto out;
}
if (!wayland &&
window_has_x11_event_handler (window, handle_take_focus))
{
g_print ("Impossible to use %s for windows accepting take focus",
g_print ("Impossible to use %s for windows accepting take focus\n",
argv[1]);
goto out;
}
@@ -414,26 +431,26 @@ process_line (const char *line)
{
if (argc != 3)
{
g_print ("usage: %s <window-id> [true|false]", argv[0]);
g_print ("usage: %s <window-id> [true|false]\n", argv[0]);
goto out;
}
GtkWidget *window = lookup_window (argv[1]);
if (!window)
{
g_print ("unknown window %s", argv[1]);
g_print ("unknown window %s\n", argv[1]);
goto out;
}
if (wayland)
{
g_print ("%s not supported under wayland", argv[0]);
g_print ("%s not supported under wayland\n", argv[0]);
goto out;
}
if (window_has_x11_event_handler (window, handle_take_focus))
{
g_print ("Impossible to change %s for windows accepting take focus",
g_print ("Impossible to change %s for windows accepting take focus\n",
argv[1]);
goto out;
}
@@ -473,32 +490,32 @@ process_line (const char *line)
{
if (argc != 3)
{
g_print ("usage: %s <window-id> [true|false]", argv[0]);
g_print ("usage: %s <window-id> [true|false]\n", argv[0]);
goto out;
}
GtkWidget *window = lookup_window (argv[1]);
if (!window)
{
g_print ("unknown window %s", argv[1]);
g_print ("unknown window %s\n", argv[1]);
goto out;
}
if (wayland)
{
g_print ("%s not supported under wayland", argv[0]);
g_print ("%s not supported under wayland\n", argv[0]);
goto out;
}
if (gtk_window_get_accept_focus (GTK_WINDOW (window)))
{
g_print ("%s not supported for input windows", argv[0]);
g_print ("%s not supported for input windows\n", argv[0]);
goto out;
}
if (!g_object_get_qdata (G_OBJECT (window), can_take_focus_quark))
{
g_print ("%s not supported for windows with no WM_TAKE_FOCUS set",
g_print ("%s not supported for windows with no WM_TAKE_FOCUS set\n",
argv[0]);
goto out;
}
@@ -512,7 +529,7 @@ process_line (const char *line)
{
if (argc != 2)
{
g_print ("usage: show <id>");
g_print ("usage: show <id>\n");
goto out;
}
@@ -527,7 +544,7 @@ process_line (const char *line)
{
if (argc != 2)
{
g_print ("usage: hide <id>");
g_print ("usage: hide <id>\n");
goto out;
}
@@ -541,7 +558,7 @@ process_line (const char *line)
{
if (argc != 2)
{
g_print ("usage: activate <id>");
g_print ("usage: activate <id>\n");
goto out;
}
@@ -555,7 +572,7 @@ process_line (const char *line)
{
if (argc != 4)
{
g_print ("usage: resize <id> <width> <height>");
g_print ("usage: resize <id> <width> <height>\n");
goto out;
}
@@ -565,13 +582,16 @@ process_line (const char *line)
int width = atoi (argv[2]);
int height = atoi (argv[3]);
gtk_window_resize (GTK_WINDOW (window), width, height);
int titlebar_height = calculate_titlebar_height (GTK_WINDOW (window));
gtk_window_resize (GTK_WINDOW (window),
width,
height - titlebar_height);
}
else if (strcmp (argv[0], "raise") == 0)
{
if (argc != 2)
{
g_print ("usage: raise <id>");
g_print ("usage: raise <id>\n");
goto out;
}
@@ -585,7 +605,7 @@ process_line (const char *line)
{
if (argc != 2)
{
g_print ("usage: lower <id>");
g_print ("usage: lower <id>\n");
goto out;
}
@@ -599,7 +619,7 @@ process_line (const char *line)
{
if (argc != 2)
{
g_print ("usage: destroy <id>");
g_print ("usage: destroy <id>\n");
goto out;
}
@@ -614,7 +634,7 @@ process_line (const char *line)
{
if (argc != 1)
{
g_print ("usage: destroy_all");
g_print ("usage: destroy_all\n");
goto out;
}
@@ -631,7 +651,7 @@ process_line (const char *line)
{
if (argc != 1)
{
g_print ("usage: sync");
g_print ("usage: sync\n");
goto out;
}
@@ -644,13 +664,13 @@ process_line (const char *line)
if (argc != 3)
{
g_print ("usage: set_counter <counter> <value>");
g_print ("usage: set_counter <counter> <value>\n");
goto out;
}
if (wayland)
{
g_print ("usage: set_counter can only be used for X11");
g_print ("usage: set_counter can only be used for X11\n");
goto out;
}
@@ -666,7 +686,7 @@ process_line (const char *line)
{
if (argc != 2)
{
g_print ("usage: minimize <id>");
g_print ("usage: minimize <id>\n");
goto out;
}
@@ -680,7 +700,7 @@ process_line (const char *line)
{
if (argc != 2)
{
g_print ("usage: unminimize <id>");
g_print ("usage: unminimize <id>\n");
goto out;
}
@@ -690,9 +710,95 @@ process_line (const char *line)
gtk_window_deiconify (GTK_WINDOW (window));
}
else if (strcmp (argv[0], "maximize") == 0)
{
if (argc != 2)
{
g_print ("usage: maximize <id>\n");
goto out;
}
GtkWidget *window = lookup_window (argv[1]);
if (!window)
goto out;
gtk_window_maximize (GTK_WINDOW (window));
}
else if (strcmp (argv[0], "unmaximize") == 0)
{
if (argc != 2)
{
g_print ("usage: unmaximize <id>\n");
goto out;
}
GtkWidget *window = lookup_window (argv[1]);
if (!window)
goto out;
gtk_window_unmaximize (GTK_WINDOW (window));
}
else if (strcmp (argv[0], "fullscreen") == 0)
{
if (argc != 2)
{
g_print ("usage: fullscreen <id>\n");
goto out;
}
GtkWidget *window = lookup_window (argv[1]);
if (!window)
goto out;
gtk_window_fullscreen (GTK_WINDOW (window));
}
else if (strcmp (argv[0], "unfullscreen") == 0)
{
if (argc != 2)
{
g_print ("usage: unfullscreen <id>\n");
goto out;
}
GtkWidget *window = lookup_window (argv[1]);
if (!window)
goto out;
gtk_window_unfullscreen (GTK_WINDOW (window));
}
else if (strcmp (argv[0], "assert_size") == 0)
{
int expected_width;
int expected_height;
int width;
int height;
if (argc != 4)
{
g_print ("usage: assert_size <id> <width> <height>\n");
goto out;
}
GtkWidget *window = lookup_window (argv[1]);
if (!window)
goto out;
gtk_window_get_size (GTK_WINDOW (window), &width, &height);
height += calculate_titlebar_height (GTK_WINDOW (window));
expected_width = atoi (argv[2]);
expected_height = atoi (argv[3]);
if (expected_width != width || expected_height != height)
{
g_print ("Expected size %dx%d didn't match actual size %dx%d\n",
expected_width, expected_height,
width, height);
goto out;
}
}
else
{
g_print ("Unknown command %s", argv[0]);
g_print ("Unknown command %s\n", argv[0]);
goto out;
}
@@ -770,6 +876,32 @@ main(int argc, char **argv)
gtk_init (NULL, NULL);
if (!wayland)
{
GdkScreen *screen;
GtkCssProvider *provider;
screen = gdk_screen_get_default ();
provider = gtk_css_provider_new ();
static const char *no_decoration_css =
"decoration {"
" border-radius: 0 0 0 0;"
" border-width: 0;"
" box-shadow: 0 0 0 0 rgba(0, 0, 0, 0), 0 0 0 0 rgba(0, 0, 0, 0);"
" margin: 0px;"
"}";
if (!gtk_css_provider_load_from_data (provider,
no_decoration_css,
strlen (no_decoration_css),
&error))
{
g_printerr ("%s", error->message);
return 1;
}
gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
}
windows = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, NULL);
event_source_quark = g_quark_from_static_string ("event-source");

View File

@@ -291,6 +291,30 @@ test_case_assert_focused (TestCase *test,
return *error == NULL;
}
static gboolean
test_case_assert_size (TestCase *test,
MetaWindow *window,
int expected_width,
int expected_height,
GError **error)
{
MetaRectangle frame_rect;
meta_window_get_frame_rect (window, &frame_rect);
if (frame_rect.width != expected_width ||
frame_rect.height != expected_height)
{
g_set_error (error, TEST_RUNNER_ERROR, TEST_RUNNER_ERROR_ASSERTION_FAILED,
"Expected size %dx%d didn't match actual size %dx%d",
expected_width, expected_height,
frame_rect.width, frame_rect.height);
return FALSE;
}
return TRUE;
}
static gboolean
test_case_check_xserver_stacking (TestCase *test,
GError **error)
@@ -344,6 +368,55 @@ test_case_check_xserver_stacking (TestCase *test,
return *error == NULL;
}
static int
maybe_divide (const char *str,
int value)
{
if (strstr (str, "/") == str)
{
int divisor;
str += 1;
divisor = atoi (str);
value /= divisor;
}
return value;
}
static int
parse_window_size (const char *size_str)
{
MetaBackend *backend = meta_get_backend ();
MetaMonitorManager *monitor_manager =
meta_backend_get_monitor_manager (backend);
MetaLogicalMonitor *logical_monitor =
meta_monitor_manager_get_logical_monitors (monitor_manager)->data;
MetaRectangle logical_monitor_layout =
meta_logical_monitor_get_layout (logical_monitor);
int value;
if (strstr (size_str, "MONITOR_WIDTH") == size_str)
{
value = logical_monitor_layout.width;
size_str += strlen ("MONITOR_WIDTH");
value = maybe_divide (size_str, value);
}
else if (strstr (size_str, "MONITOR_HEIGHT") == size_str)
{
value = logical_monitor_layout.height;
size_str += strlen ("MONITOR_HEIGHT");
value = maybe_divide (size_str, value);
}
else
{
value = atoi (size_str);
}
return value;
}
static gboolean
test_case_do (TestCase *test,
int argc,
@@ -504,12 +577,96 @@ test_case_do (TestCase *test,
test_client_wait_for_window_shown (client, window);
}
else if (strcmp (argv[0], "resize") == 0)
{
if (argc != 4)
BAD_COMMAND("usage: %s <client-id>/<window-id> width height", argv[0]);
TestClient *client;
const char *window_id;
if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error))
return FALSE;
if (!test_client_do (client, error, argv[0], window_id,
argv[2], argv[3], NULL))
return FALSE;
}
else if (strcmp (argv[0], "move") == 0)
{
if (argc != 4)
BAD_COMMAND("usage: %s <client-id>/<window-id> x y", argv[0]);
TestClient *client;
const char *window_id;
if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error))
return FALSE;
MetaWindow *window = test_client_find_window (client, window_id, error);
if (!window)
return FALSE;
meta_window_move_frame (window, TRUE, atoi (argv[2]), atoi (argv[3]));
}
else if (strcmp (argv[0], "tile") == 0)
{
if (argc != 3)
BAD_COMMAND("usage: %s <client-id>/<window-id> [right|left]", argv[0]);
TestClient *client;
const char *window_id;
if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error))
return FALSE;
MetaWindow *window = test_client_find_window (client, window_id, error);
if (!window)
return FALSE;
MetaTileMode tile_mode;
if (strcmp (argv[2], "right") == 0)
{
tile_mode = META_TILE_RIGHT;
}
else if (strcmp (argv[2], "left") == 0)
{
tile_mode = META_TILE_LEFT;
}
else
{
g_set_error (error,
TEST_RUNNER_ERROR,
TEST_RUNNER_ERROR_ASSERTION_FAILED,
"Invalid tile mode '%s'", argv[2]);
return FALSE;
}
meta_window_tile (window, tile_mode);
}
else if (strcmp (argv[0], "untile") == 0)
{
if (argc != 2)
BAD_COMMAND("usage: %s <client-id>/<window-id>", argv[0]);
TestClient *client;
const char *window_id;
if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error))
return FALSE;
MetaWindow *window = test_client_find_window (client, window_id, error);
if (!window)
return FALSE;
meta_window_untile (window);
}
else if (strcmp (argv[0], "hide") == 0 ||
strcmp (argv[0], "activate") == 0 ||
strcmp (argv[0], "raise") == 0 ||
strcmp (argv[0], "lower") == 0 ||
strcmp (argv[0], "minimize") == 0 ||
strcmp (argv[0], "unminimize") == 0 ||
strcmp (argv[0], "maximize") == 0 ||
strcmp (argv[0], "unmaximize") == 0 ||
strcmp (argv[0], "fullscreen") == 0 ||
strcmp (argv[0], "unfullscreen") == 0 ||
strcmp (argv[0], "destroy") == 0)
{
if (argc != 2)
@@ -547,6 +704,24 @@ test_case_do (TestCase *test,
if (!test_case_wait (test, error))
return FALSE;
}
else if (strcmp (argv[0], "wait_reconfigure") == 0)
{
if (argc != 1)
BAD_COMMAND("usage: %s", argv[0]);
/*
* Wait twice, so that we
* 1) First wait for any requests to configure has been made
* 2) Then wait for the new configuration has been applied
*/
if (!test_case_wait (test, error))
return FALSE;
if (!test_case_dispatch (test, error))
return FALSE;
if (!test_case_wait (test, error))
return FALSE;
}
else if (strcmp (argv[0], "dispatch") == 0)
{
if (argc != 1)
@@ -582,6 +757,80 @@ test_case_do (TestCase *test,
if (!test_case_assert_focused (test, argv[1], error))
return FALSE;
}
else if (strcmp (argv[0], "assert_size") == 0)
{
if (argc != 4)
{
BAD_COMMAND("usage: %s <client-id>/<window-id> <width> <height>",
argv[0]);
}
TestClient *client;
const char *window_id;
if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error))
return FALSE;
MetaWindow *window = test_client_find_window (client, window_id, error);
if (!window)
return FALSE;
if (meta_window_get_frame (window))
{
g_set_error (error,
TEST_RUNNER_ERROR,
TEST_RUNNER_ERROR_ASSERTION_FAILED,
"Can only assert size of CSD window");
return FALSE;
}
int width = parse_window_size (argv[2]);
int height = parse_window_size (argv[3]);
g_autofree char *width_str = g_strdup_printf ("%d", width);
g_autofree char *height_str = g_strdup_printf ("%d", height);
if (!test_client_do (client, error, argv[0],
window_id,
width_str,
height_str,
NULL))
return FALSE;
if (!test_case_assert_size (test, window,
width, height,
error))
return FALSE;
}
else if (strcmp (argv[0], "assert_position") == 0)
{
if (argc != 4)
{
BAD_COMMAND("usage: %s <client-id>/<window-id> <x> <y>",
argv[0]);
}
TestClient *client;
const char *window_id;
if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error))
return FALSE;
MetaWindow *window = test_client_find_window (client, window_id, error);
if (!window)
return FALSE;
MetaRectangle frame_rect;
meta_window_get_frame_rect (window, &frame_rect);
int x = atoi (argv[2]);
int y = atoi (argv[3]);
if (frame_rect.x != x || frame_rect.y != y)
{
g_set_error (error,
TEST_RUNNER_ERROR,
TEST_RUNNER_ERROR_ASSERTION_FAILED,
"Expected window position (%d, %d) doesn't match (%d, %d)",
x, y, frame_rect.x, frame_rect.y);
return FALSE;
}
}
else
{
BAD_COMMAND("Unknown command %s", argv[0]);

View File

@@ -108,30 +108,6 @@ static struct wl_resource * create_and_send_primary_offer (MetaWaylandDataDevi
struct wl_resource *target);
static struct wl_resource * meta_wayland_data_source_get_resource (MetaWaylandDataSource *source);
static void
move_resources (struct wl_list *destination,
struct wl_list *source)
{
wl_list_insert_list (destination, source);
wl_list_init (source);
}
static void
move_resources_for_client (struct wl_list *destination,
struct wl_list *source,
struct wl_client *client)
{
struct wl_resource *resource, *tmp;
wl_resource_for_each_safe (resource, tmp, source)
{
if (wl_resource_get_client (resource) == client)
{
wl_list_remove (wl_resource_get_link (resource));
wl_list_insert (destination, wl_resource_get_link (resource));
}
}
}
static void
unbind_resource (struct wl_resource *resource)
{
@@ -925,12 +901,6 @@ meta_wayland_drag_grab_set_focus (MetaWaylandDragGrab *drag_grab,
client = wl_resource_get_client (surface->resource);
data_device_resource = wl_resource_find_for_client (&seat->data_device.resource_list, client);
if (!data_device_resource)
{
data_device_resource =
wl_resource_find_for_client (&seat->data_device.focus_resource_list,
client);
}
if (source && data_device_resource)
offer = create_and_send_dnd_offer (source, data_device_resource);
@@ -1374,8 +1344,20 @@ static void
selection_data_source_destroyed (gpointer data, GObject *object_was_here)
{
MetaWaylandDataDevice *data_device = data;
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
struct wl_resource *data_device_resource;
struct wl_client *focus_client = NULL;
data_device->selection_data_source = NULL;
focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard);
if (focus_client)
{
data_device_resource = wl_resource_find_for_client (&data_device->resource_list, focus_client);
if (data_device_resource)
wl_data_device_send_selection (data_device_resource, NULL);
}
unset_selection_source (data_device, META_SELECTION_CLIPBOARD);
}
@@ -1410,7 +1392,8 @@ meta_wayland_source_cancel (MetaWaylandDataSource *source)
if (!priv->resource)
return;
wl_data_source_send_cancelled (priv->resource);
if (wl_resource_get_version(priv->resource) >= WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION)
wl_data_source_send_cancelled (priv->resource);
}
static void
@@ -1431,12 +1414,11 @@ meta_wayland_source_drop_performed (MetaWaylandDataSource *source)
MetaWaylandDataSourcePrivate *priv =
meta_wayland_data_source_get_instance_private (source);
priv->drop_performed = TRUE;
if (wl_resource_get_version (priv->resource) >=
WL_DATA_SOURCE_DND_DROP_PERFORMED_SINCE_VERSION)
{
priv->drop_performed = TRUE;
wl_data_source_send_dnd_drop_performed (priv->resource);
}
wl_data_source_send_dnd_drop_performed (priv->resource);
}
static void
@@ -1677,6 +1659,8 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
guint32 serial)
{
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
struct wl_resource *data_device_resource;
struct wl_client *focus_client;
MetaSelectionSource *selection_source;
if (data_device->selection_data_source &&
@@ -1685,6 +1669,7 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
if (data_device->selection_data_source)
{
meta_wayland_data_source_cancel (data_device->selection_data_source);
g_object_weak_unref (G_OBJECT (data_device->selection_data_source),
selection_data_source_destroyed,
data_device);
@@ -1711,6 +1696,18 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
set_selection_source (data_device, META_SELECTION_CLIPBOARD,
selection_source);
g_object_unref (selection_source);
focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard);
if (focus_client)
{
data_device_resource = wl_resource_find_for_client (&data_device->resource_list, focus_client);
if (data_device_resource)
{
struct wl_resource *offer;
offer = create_and_send_clipboard_offer (data_device, data_device_resource);
wl_data_device_send_selection (data_device_resource, offer);
}
}
}
static void
@@ -1761,8 +1758,21 @@ primary_source_destroyed (gpointer data,
GObject *object_was_here)
{
MetaWaylandDataDevice *data_device = data;
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
struct wl_client *focus_client = NULL;
data_device->primary_data_source = NULL;
focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard);
if (focus_client)
{
struct wl_resource *data_device_resource;
data_device_resource = wl_resource_find_for_client (&data_device->primary_resource_list, focus_client);
if (data_device_resource)
gtk_primary_selection_device_send_selection (data_device_resource, NULL);
}
unset_selection_source (data_device, META_SELECTION_PRIMARY);
}
@@ -1772,6 +1782,8 @@ meta_wayland_data_device_set_primary (MetaWaylandDataDevice *data_device,
guint32 serial)
{
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
struct wl_resource *data_device_resource;
struct wl_client *focus_client;
MetaSelectionSource *selection_source;
g_assert (!source || META_IS_WAYLAND_DATA_SOURCE_PRIMARY (source));
@@ -1782,6 +1794,7 @@ meta_wayland_data_device_set_primary (MetaWaylandDataDevice *data_device,
if (data_device->primary_data_source)
{
meta_wayland_data_source_cancel (data_device->primary_data_source);
g_object_weak_unref (G_OBJECT (data_device->primary_data_source),
primary_source_destroyed,
data_device);
@@ -1807,6 +1820,18 @@ meta_wayland_data_device_set_primary (MetaWaylandDataDevice *data_device,
set_selection_source (data_device, META_SELECTION_PRIMARY,
selection_source);
g_object_unref (selection_source);
focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard);
if (focus_client)
{
data_device_resource = wl_resource_find_for_client (&data_device->primary_resource_list, focus_client);
if (data_device_resource)
{
struct wl_resource *offer;
offer = create_and_send_primary_offer (data_device, data_device_resource);
gtk_primary_selection_device_send_selection (data_device_resource, offer);
}
}
}
static void
@@ -1871,7 +1896,10 @@ owner_changed_cb (MetaSelection *selection,
if (selection_type == META_SELECTION_PRIMARY)
{
wl_resource_for_each (data_device_resource, &data_device->primary_focus_resource_list)
data_device_resource =
wl_resource_find_for_client (&data_device->primary_resource_list,
focus_client);
if (data_device_resource)
{
struct wl_resource *offer = NULL;
@@ -1887,7 +1915,10 @@ owner_changed_cb (MetaSelection *selection,
}
else if (selection_type == META_SELECTION_CLIPBOARD)
{
wl_resource_for_each (data_device_resource, &data_device->focus_resource_list)
data_device_resource =
wl_resource_find_for_client (&data_device->resource_list, focus_client);
if (data_device_resource)
{
struct wl_resource *offer = NULL;
@@ -2022,9 +2053,7 @@ void
meta_wayland_data_device_init (MetaWaylandDataDevice *data_device)
{
wl_list_init (&data_device->resource_list);
wl_list_init (&data_device->focus_resource_list);
wl_list_init (&data_device->primary_resource_list);
wl_list_init (&data_device->primary_focus_resource_list);
}
static struct wl_resource *
@@ -2106,34 +2135,22 @@ meta_wayland_data_device_set_keyboard_focus (MetaWaylandDataDevice *data_device)
return;
data_device->focus_client = focus_client;
move_resources (&data_device->resource_list,
&data_device->focus_resource_list);
move_resources (&data_device->primary_resource_list,
&data_device->primary_focus_resource_list);
if (!focus_client)
return;
move_resources_for_client (&data_device->focus_resource_list,
&data_device->resource_list,
focus_client);
wl_resource_for_each (data_device_resource, &data_device->focus_resource_list)
data_device_resource = wl_resource_find_for_client (&data_device->resource_list, focus_client);
if (data_device_resource)
{
struct wl_resource *offer;
offer = create_and_send_clipboard_offer (data_device, data_device_resource);
wl_data_device_send_selection (data_device_resource, offer);
}
move_resources_for_client (&data_device->primary_focus_resource_list,
&data_device->primary_resource_list,
focus_client);
wl_resource_for_each (data_device_resource, &data_device->primary_focus_resource_list)
data_device_resource = wl_resource_find_for_client (&data_device->primary_resource_list, focus_client);
if (data_device_resource)
{
struct wl_resource *offer;
offer = create_and_send_primary_offer (data_device, data_device_resource);
gtk_primary_selection_device_send_selection (data_device_resource, offer);
}

View File

@@ -63,9 +63,7 @@ struct _MetaWaylandDataDevice
MetaWaylandDataSource *primary_data_source;
struct wl_listener selection_data_source_listener;
struct wl_list resource_list;
struct wl_list focus_resource_list;
struct wl_list primary_resource_list;
struct wl_list primary_focus_resource_list;
MetaWaylandDragGrab *current_grab;
struct wl_client *focus_client;

View File

@@ -60,8 +60,6 @@ G_DEFINE_TYPE_WITH_PRIVATE (MetaX11SelectionOutputStream,
meta_x11_selection_output_stream,
G_TYPE_OUTPUT_STREAM);
static size_t get_element_size (int format);
static void
meta_x11_selection_output_stream_notify_selection (MetaX11SelectionOutputStream *stream)
{
@@ -99,9 +97,6 @@ meta_x11_selection_output_stream_can_flush (MetaX11SelectionOutputStream *stream
if (priv->delete_pending)
return FALSE;
if (!g_output_stream_is_closing (G_OUTPUT_STREAM (stream)) &&
priv->data->len < get_element_size (priv->format))
return FALSE;
return TRUE;
}
@@ -115,7 +110,7 @@ get_max_request_size (MetaX11Display *display)
if (size <= 0)
size = XMaxRequestSize (display->xdisplay);
return (size - 100) * 4;
return size - 100;
}
static gboolean
@@ -125,12 +120,7 @@ meta_x11_selection_output_stream_needs_flush_unlocked (MetaX11SelectionOutputStr
meta_x11_selection_output_stream_get_instance_private (stream);
if (priv->data->len == 0)
{
if (priv->incr)
return g_output_stream_is_closing (G_OUTPUT_STREAM (stream));
else
return FALSE;
}
return FALSE;
if (g_output_stream_is_closing (G_OUTPUT_STREAM (stream)))
return TRUE;
@@ -203,8 +193,7 @@ meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *st
MetaX11SelectionOutputStreamPrivate *priv =
meta_x11_selection_output_stream_get_instance_private (stream);
Display *xdisplay;
size_t element_size, n_elements, max_size;
gboolean first_chunk = FALSE;
size_t element_size, n_elements;
int error_code;
g_assert (!priv->delete_pending);
@@ -218,12 +207,8 @@ meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *st
element_size = get_element_size (priv->format);
n_elements = priv->data->len / element_size;
max_size = get_max_request_size (priv->x11_display);
if (!priv->incr)
first_chunk = TRUE;
if (!priv->incr && priv->data->len > max_size)
if (!g_output_stream_is_closing (G_OUTPUT_STREAM (stream)))
{
XWindowAttributes attrs;
@@ -239,22 +224,14 @@ meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *st
XChangeProperty (xdisplay,
priv->xwindow,
priv->xproperty,
XInternAtom (priv->x11_display->xdisplay, "INCR", False),
XInternAtom (priv->x11_display->xdisplay, "INCR", True),
32,
PropModeReplace,
(guchar *) &(long) { n_elements },
1);
priv->delete_pending = TRUE;
}
else
{
size_t copy_n_elements;
if (priv->incr && priv->data->len > 0)
priv->delete_pending = TRUE;
copy_n_elements = MIN (n_elements, max_size / element_size);
XChangeProperty (xdisplay,
priv->xwindow,
priv->xproperty,
@@ -262,13 +239,15 @@ meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *st
priv->format,
PropModeReplace,
priv->data->data,
copy_n_elements);
g_byte_array_remove_range (priv->data, 0, copy_n_elements * element_size);
n_elements);
g_byte_array_remove_range (priv->data, 0, n_elements * element_size);
if (priv->data->len < element_size)
priv->flush_requested = FALSE;
}
if (first_chunk)
meta_x11_selection_output_stream_notify_selection (stream);
meta_x11_selection_output_stream_notify_selection (stream);
priv->delete_pending = TRUE;
g_cond_broadcast (&priv->cond);
g_mutex_unlock (&priv->mutex);
@@ -278,26 +257,19 @@ meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *st
{
char error_str[100];
priv->flush_requested = FALSE;
priv->delete_pending = FALSE;
XGetErrorText (xdisplay, error_code, error_str, sizeof (error_str));
g_task_return_new_error (priv->pending_task,
G_IO_ERROR,
G_IO_ERROR_BROKEN_PIPE,
"Failed to flush selection output stream: %s",
error_str);
g_clear_object (&priv->pending_task);
priv->pipe_error = TRUE;
if (priv->pending_task)
{
XGetErrorText (xdisplay, error_code, error_str, sizeof (error_str));
g_task_return_new_error (priv->pending_task,
G_IO_ERROR,
G_IO_ERROR_BROKEN_PIPE,
"Failed to flush selection output stream: %s",
error_str);
g_clear_object (&priv->pending_task);
}
}
else if (priv->pending_task && priv->data->len == 0 && !priv->delete_pending)
else if (priv->pending_task)
{
size_t result;
priv->flush_requested = FALSE;
result = GPOINTER_TO_SIZE (g_task_get_task_data (priv->pending_task));
g_task_return_int (priv->pending_task, result);
g_clear_object (&priv->pending_task);
@@ -309,17 +281,12 @@ meta_x11_selection_output_stream_invoke_flush (gpointer data)
{
MetaX11SelectionOutputStream *stream =
META_X11_SELECTION_OUTPUT_STREAM (data);
MetaX11SelectionOutputStreamPrivate *priv =
meta_x11_selection_output_stream_get_instance_private (stream);
if (meta_x11_selection_output_stream_needs_flush (stream) &&
meta_x11_selection_output_stream_can_flush (stream))
meta_x11_selection_output_stream_perform_flush (stream);
if (priv->delete_pending || priv->data->len > 0)
return G_SOURCE_CONTINUE;
else
return G_SOURCE_REMOVE;
return G_SOURCE_REMOVE;
}
static gssize
@@ -387,11 +354,16 @@ meta_x11_selection_output_stream_write_async (GOutputStream *output_stream
g_object_unref (task);
return;
}
else if (!meta_x11_selection_output_stream_can_flush (stream))
{
g_assert (priv->pending_task == NULL);
priv->pending_task = task;
g_task_set_task_data (task, GSIZE_TO_POINTER (count), NULL);
return;
}
else
{
if (meta_x11_selection_output_stream_can_flush (stream))
meta_x11_selection_output_stream_perform_flush (stream);
meta_x11_selection_output_stream_perform_flush (stream);
g_task_return_int (task, count);
g_object_unref (task);
return;
@@ -419,7 +391,7 @@ meta_x11_selection_output_request_flush (MetaX11SelectionOutputStream *stream)
g_mutex_lock (&priv->mutex);
if (priv->data->len > 0)
if (priv->data->len >= get_element_size (priv->format))
priv->flush_requested = TRUE;
needs_flush = meta_x11_selection_output_stream_needs_flush_unlocked (stream);
@@ -494,9 +466,10 @@ meta_x11_selection_output_stream_flush_async (GOutputStream *output_stream
}
}
g_assert (priv->pending_task == NULL);
priv->pending_task = task;
meta_x11_selection_output_stream_perform_flush (stream);
g_task_return_boolean (task, TRUE);
g_object_unref (task);
return;
}
static gboolean

View File

@@ -23,8 +23,6 @@
#include <gdk/gdkx.h>
#include "core/meta-selection-private.h"
#include "meta/meta-selection-source-memory.h"
#include "x11/meta-selection-source-x11-private.h"
#include "x11/meta-x11-selection-output-stream-private.h"
#include "x11/meta-x11-selection-private.h"
@@ -32,13 +30,6 @@
#define UTF8_STRING_MIMETYPE "text/plain;charset=utf-8"
#define STRING_MIMETYPE "text/plain"
/* Set an arbitrary (although generous) threshold to determine whether a
* XFixesSelectionNotify corresponds to a XSetSelectionOwner from another
* client. The selection timestamp is not updated if the owner client is
* closed.
*/
#define SELECTION_CLEARED_BY_CLIENT(e) (e->timestamp - e->selection_timestamp < 50)
static gboolean
atom_to_selection_type (Display *xdisplay,
Atom selection,
@@ -305,8 +296,8 @@ source_new_cb (GObject *object,
source = meta_selection_source_x11_new_finish (res, &error);
if (source)
{
g_set_object (&x11_display->selection.owners[selection_type], source);
meta_selection_set_owner (selection, selection_type, source);
g_set_object (&x11_display->selection.owners[selection_type], source);
g_object_unref (source);
}
else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
@@ -340,27 +331,16 @@ meta_x11_selection_handle_xfixes_selection_notify (MetaX11Display *x11_display,
x11_display->selection.cancellables[selection_type] = g_cancellable_new ();
if (event->owner == None && x11_display->selection.owners[selection_type])
if (event->owner == None)
{
if (SELECTION_CLEARED_BY_CLIENT (event))
{
MetaSelectionSource *source;
/* Replace with an empty owner */
source = g_object_new (META_TYPE_SELECTION_SOURCE_MEMORY, NULL);
g_set_object (&x11_display->selection.owners[selection_type], source);
meta_selection_set_owner (selection, selection_type, source);
g_object_unref (source);
}
else
if (x11_display->selection.owners[selection_type])
{
/* An X client went away, clear the selection */
meta_selection_unset_owner (selection, selection_type,
x11_display->selection.owners[selection_type]);
g_clear_object (&x11_display->selection.owners[selection_type]);
}
}
else if (event->owner != None && event->owner != x11_display->selection.xwindow)
else if (event->owner != x11_display->selection.xwindow)
{
SourceNewData *data;
@@ -394,13 +374,14 @@ meta_x11_selection_handle_event (MetaX11Display *x11_display,
}
static void
notify_selection_owner (MetaX11Display *x11_display,
MetaSelectionType selection_type,
MetaSelectionSource *new_owner)
owner_changed_cb (MetaSelection *selection,
MetaSelectionType selection_type,
MetaSelectionSource *new_owner,
MetaX11Display *x11_display)
{
Display *xdisplay = x11_display->xdisplay;
if (new_owner && new_owner != x11_display->selection.owners[selection_type])
if (new_owner && !META_IS_SELECTION_SOURCE_X11 (new_owner))
{
if (x11_display->selection.cancellables[selection_type])
{
@@ -423,7 +404,6 @@ meta_x11_selection_init (MetaX11Display *x11_display)
{
XSetWindowAttributes attributes = { 0 };
MetaDisplay *display = meta_get_display ();
MetaSelection *selection;
guint mask, i;
attributes.event_mask = PropertyChangeMask | SubstructureNotifyMask;
@@ -444,24 +424,18 @@ meta_x11_selection_init (MetaX11Display *x11_display)
XFixesSelectionWindowDestroyNotifyMask |
XFixesSelectionClientCloseNotifyMask;
selection = meta_display_get_selection (display);
for (i = 0; i < META_N_SELECTION_TYPES; i++)
{
MetaSelectionSource *owner;
XFixesSelectSelectionInput (x11_display->xdisplay,
x11_display->selection.xwindow,
selection_to_atom (i, x11_display->xdisplay),
mask);
owner = meta_selection_get_current_owner (selection, i);
notify_selection_owner (x11_display, i, owner);
}
g_signal_connect_swapped (selection,
"owner-changed",
G_CALLBACK (notify_selection_owner),
x11_display);
g_signal_connect (meta_display_get_selection (display),
"owner-changed",
G_CALLBACK (owner_changed_cb),
x11_display);
}
void
@@ -471,7 +445,7 @@ meta_x11_selection_shutdown (MetaX11Display *x11_display)
guint i;
g_signal_handlers_disconnect_by_func (meta_display_get_selection (display),
notify_selection_owner,
owner_changed_cb,
x11_display);
for (i = 0; i < META_N_SELECTION_TYPES; i++)