Compare commits
67 Commits
3.13.92
...
wip/dnd-su
Author | SHA1 | Date | |
---|---|---|---|
![]() |
410b37bc53 | ||
![]() |
6dfdc6d6ec | ||
![]() |
869d12c36d | ||
![]() |
827e0c23c5 | ||
![]() |
9efd96be7b | ||
![]() |
102d1e62a2 | ||
![]() |
aba81603b9 | ||
![]() |
10c6056ce0 | ||
![]() |
79fdbbfe1a | ||
![]() |
572727e6e8 | ||
![]() |
1dbc9e868f | ||
![]() |
a181ea3cde | ||
![]() |
78477dd56a | ||
![]() |
30cc4e1d0a | ||
![]() |
4b83b031bc | ||
![]() |
40a85e0e99 | ||
![]() |
dfde1ff327 | ||
![]() |
92b7daab61 | ||
![]() |
b735571688 | ||
![]() |
5e249ad5eb | ||
![]() |
21bffe4aef | ||
![]() |
68283df4d9 | ||
![]() |
4f3de2ce39 | ||
![]() |
9f8b641472 | ||
![]() |
a9a21c801c | ||
![]() |
482a97466d | ||
![]() |
4e14bb9df3 | ||
![]() |
df90545258 | ||
![]() |
c954f9cc24 | ||
![]() |
d06b39d13c | ||
![]() |
f3595ebd08 | ||
![]() |
1e1ca47ec1 | ||
![]() |
2eec11b445 | ||
![]() |
8ff4597201 | ||
![]() |
d5f2468d88 | ||
![]() |
488dd0b402 | ||
![]() |
6565bca210 | ||
![]() |
60c22b6236 | ||
![]() |
d3111a9f07 | ||
![]() |
cdfb301200 | ||
![]() |
371560c2b6 | ||
![]() |
7616881afa | ||
![]() |
74c37d49c4 | ||
![]() |
d3142b92f0 | ||
![]() |
ae2afa7c5e | ||
![]() |
4a71621fbc | ||
![]() |
565b9d73d5 | ||
![]() |
90bd02ff4d | ||
![]() |
73ca0efaeb | ||
![]() |
790269db95 | ||
![]() |
cb82bd8afa | ||
![]() |
b1e06ed110 | ||
![]() |
fabe66e65f | ||
![]() |
4a965a37d1 | ||
![]() |
302ff7b95a | ||
![]() |
e2e241340c | ||
![]() |
461aea47dd | ||
![]() |
d87093fe29 | ||
![]() |
0cde7879d6 | ||
![]() |
89ffcee7ca | ||
![]() |
1250afef7b | ||
![]() |
3a577edaa7 | ||
![]() |
48dfde2073 | ||
![]() |
4a41d415f8 | ||
![]() |
1fb7ca398d | ||
![]() |
2b79935fd8 | ||
![]() |
e3c915350e |
14
NEWS
14
NEWS
@@ -1,3 +1,17 @@
|
||||
3.14.0
|
||||
======
|
||||
* Fix placement of popup windows on wayland [Jasper; #736812]
|
||||
* Only increment serial once per event [Jasper; #736840]
|
||||
* Fix window positioning regression with non-GTK+ toolkits [Owen; #736719]
|
||||
|
||||
Contributors:
|
||||
Jasper St. Pierre, Owen W. Taylor
|
||||
|
||||
Translations:
|
||||
Saibal Ray [bn_IN], Dušan Kazik [sk], Manoj Kumar Giri [or],
|
||||
Christian Kirbach [de], Ask H. Larsen [da], YunQiang Su [zh_CN],
|
||||
Bernd Homuth [de], Shankar Prasad [kn], Petr Kovar [cs], Rajesh Ranjan [hi]
|
||||
|
||||
3.13.92
|
||||
=======
|
||||
* Rewrite background code [Owen; #735637, #736568]
|
||||
|
@@ -1,8 +1,8 @@
|
||||
AC_PREREQ(2.62)
|
||||
|
||||
m4_define([mutter_major_version], [3])
|
||||
m4_define([mutter_minor_version], [13])
|
||||
m4_define([mutter_micro_version], [92])
|
||||
m4_define([mutter_minor_version], [14])
|
||||
m4_define([mutter_micro_version], [0])
|
||||
|
||||
m4_define([mutter_version],
|
||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||
@@ -79,7 +79,7 @@ MUTTER_PC_MODULES="
|
||||
$CLUTTER_PACKAGE >= 1.19.5
|
||||
clutter-egl-1.0
|
||||
cogl-1.0 >= 1.17.1
|
||||
gbm
|
||||
gbm >= 10.3
|
||||
upower-glib >= 0.99.0
|
||||
gnome-desktop-3.0
|
||||
xcomposite >= 0.2
|
||||
|
2679
po/bn_IN.po
2679
po/bn_IN.po
File diff suppressed because it is too large
Load Diff
1300
po/sr@latin.po
1300
po/sr@latin.po
File diff suppressed because it is too large
Load Diff
1306
po/zh_CN.po
1306
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,7 @@ stackingdir = $(pkgdatadir)/tests/stacking
|
||||
dist_stacking_DATA = \
|
||||
tests/stacking/basic-x11.metatest \
|
||||
tests/stacking/basic-wayland.metatest \
|
||||
tests/stacking/minimized.metatest \
|
||||
tests/stacking/mixed-windows.metatest \
|
||||
tests/stacking/override-redirect.metatest
|
||||
|
||||
|
@@ -35,13 +35,21 @@
|
||||
|
||||
#include "meta-stage.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CoglTexture *texture;
|
||||
MetaRectangle current_rect;
|
||||
int current_x, current_y;
|
||||
} MetaCursorLayer;
|
||||
|
||||
struct _MetaCursorRendererPrivate
|
||||
{
|
||||
int current_x, current_y;
|
||||
MetaRectangle current_rect;
|
||||
MetaCursorLayer core_layer;
|
||||
MetaCursorLayer dnd_layer;
|
||||
|
||||
MetaCursorReference *displayed_cursor;
|
||||
gboolean handled_by_backend;
|
||||
int dnd_surface_offset_x, dnd_surface_offset_y;
|
||||
gboolean cursor_handled_by_backend;
|
||||
};
|
||||
typedef struct _MetaCursorRendererPrivate MetaCursorRendererPrivate;
|
||||
|
||||
@@ -59,12 +67,19 @@ queue_redraw (MetaCursorRenderer *renderer)
|
||||
if (!stage)
|
||||
return;
|
||||
|
||||
if (priv->displayed_cursor && !priv->handled_by_backend)
|
||||
texture = meta_cursor_reference_get_cogl_texture (priv->displayed_cursor, NULL, NULL);
|
||||
/* Pointer cursor */
|
||||
if (!priv->cursor_handled_by_backend)
|
||||
texture = priv->core_layer.texture;
|
||||
else
|
||||
texture = NULL;
|
||||
|
||||
meta_stage_set_cursor (META_STAGE (stage), texture, &priv->current_rect);
|
||||
meta_stage_set_cursor (META_STAGE (stage), texture,
|
||||
&priv->core_layer.current_rect);
|
||||
|
||||
/* DnD surface */
|
||||
meta_stage_set_dnd_surface (META_STAGE (stage),
|
||||
priv->dnd_layer.texture,
|
||||
&priv->dnd_layer.current_rect);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -85,46 +100,76 @@ meta_cursor_renderer_init (MetaCursorRenderer *renderer)
|
||||
}
|
||||
|
||||
static void
|
||||
update_cursor (MetaCursorRenderer *renderer)
|
||||
update_layer (MetaCursorRenderer *renderer,
|
||||
MetaCursorLayer *layer,
|
||||
CoglTexture *texture,
|
||||
int offset_x,
|
||||
int offset_y)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
gboolean handled_by_backend;
|
||||
gboolean should_redraw = FALSE;
|
||||
layer->texture = texture;
|
||||
|
||||
if (priv->displayed_cursor)
|
||||
if (layer->texture)
|
||||
{
|
||||
CoglTexture *texture;
|
||||
int hot_x, hot_y;
|
||||
|
||||
texture = meta_cursor_reference_get_cogl_texture (priv->displayed_cursor, &hot_x, &hot_y);
|
||||
|
||||
priv->current_rect.x = priv->current_x - hot_x;
|
||||
priv->current_rect.y = priv->current_y - hot_y;
|
||||
priv->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (texture));
|
||||
priv->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (texture));
|
||||
layer->current_rect.x = layer->current_x + offset_x;
|
||||
layer->current_rect.y = layer->current_y + offset_y;
|
||||
layer->current_rect.width = cogl_texture_get_width (layer->texture);
|
||||
layer->current_rect.height = cogl_texture_get_height (layer->texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->current_rect.x = 0;
|
||||
priv->current_rect.y = 0;
|
||||
priv->current_rect.width = 0;
|
||||
priv->current_rect.height = 0;
|
||||
layer->current_rect.x = 0;
|
||||
layer->current_rect.y = 0;
|
||||
layer->current_rect.width = 0;
|
||||
layer->current_rect.height = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
emit_update_cursor (MetaCursorRenderer *renderer,
|
||||
gboolean force)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
gboolean handled_by_backend, should_redraw = FALSE;
|
||||
|
||||
handled_by_backend = META_CURSOR_RENDERER_GET_CLASS (renderer)->update_cursor (renderer);
|
||||
if (handled_by_backend != priv->handled_by_backend)
|
||||
|
||||
if (handled_by_backend != priv->cursor_handled_by_backend)
|
||||
{
|
||||
priv->handled_by_backend = handled_by_backend;
|
||||
priv->cursor_handled_by_backend = handled_by_backend;
|
||||
should_redraw = TRUE;
|
||||
}
|
||||
|
||||
if (!handled_by_backend)
|
||||
if (force || !handled_by_backend || priv->dnd_layer.texture)
|
||||
should_redraw = TRUE;
|
||||
|
||||
if (should_redraw)
|
||||
queue_redraw (renderer);
|
||||
}
|
||||
|
||||
static void
|
||||
update_cursor (MetaCursorRenderer *renderer)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
CoglTexture *texture;
|
||||
int hot_x, hot_y;
|
||||
|
||||
/* Cursor layer */
|
||||
if (priv->displayed_cursor)
|
||||
{
|
||||
texture = meta_cursor_reference_get_cogl_texture (priv->displayed_cursor,
|
||||
&hot_x, &hot_y);
|
||||
}
|
||||
else
|
||||
{
|
||||
texture = NULL;
|
||||
hot_x = 0;
|
||||
hot_y = 0;
|
||||
}
|
||||
|
||||
update_layer (renderer, &priv->core_layer, texture, -hot_x, -hot_y);
|
||||
emit_update_cursor (renderer, FALSE);
|
||||
}
|
||||
|
||||
MetaCursorRenderer *
|
||||
meta_cursor_renderer_new (void)
|
||||
{
|
||||
@@ -144,6 +189,23 @@ meta_cursor_renderer_set_cursor (MetaCursorRenderer *renderer,
|
||||
update_cursor (renderer);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_renderer_set_dnd_surface (MetaCursorRenderer *renderer,
|
||||
CoglTexture *texture,
|
||||
int offset_x,
|
||||
int offset_y)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
priv->dnd_surface_offset_x = offset_x;
|
||||
priv->dnd_surface_offset_y = offset_y;
|
||||
|
||||
update_layer (renderer, &priv->dnd_layer, texture, offset_x, offset_y);
|
||||
emit_update_cursor (renderer, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_renderer_set_position (MetaCursorRenderer *renderer,
|
||||
int x, int y)
|
||||
@@ -152,12 +214,46 @@ meta_cursor_renderer_set_position (MetaCursorRenderer *renderer,
|
||||
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
priv->current_x = x;
|
||||
priv->current_y = y;
|
||||
priv->core_layer.current_x = x;
|
||||
priv->core_layer.current_y = y;
|
||||
|
||||
update_cursor (renderer);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_renderer_set_dnd_surface_position (MetaCursorRenderer *renderer,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
priv->dnd_layer.current_x = x;
|
||||
priv->dnd_layer.current_y = y;
|
||||
|
||||
update_layer (renderer, &priv->dnd_layer, priv->dnd_layer.texture,
|
||||
priv->dnd_surface_offset_x, priv->dnd_surface_offset_y);
|
||||
emit_update_cursor (renderer, FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_renderer_dnd_failed (MetaCursorRenderer *renderer,
|
||||
int dest_x,
|
||||
int dest_y)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
ClutterActor *stage = meta_backend_get_stage (backend);
|
||||
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
if (priv->dnd_layer.texture)
|
||||
meta_stage_dnd_failed (META_STAGE (stage),
|
||||
dest_x + priv->dnd_surface_offset_x,
|
||||
dest_y + priv->dnd_surface_offset_y);
|
||||
}
|
||||
|
||||
MetaCursorReference *
|
||||
meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer)
|
||||
{
|
||||
@@ -171,5 +267,5 @@ meta_cursor_renderer_get_rect (MetaCursorRenderer *renderer)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
|
||||
return &priv->current_rect;
|
||||
return &priv->core_layer.current_rect;
|
||||
}
|
||||
|
@@ -67,4 +67,14 @@ void meta_cursor_renderer_set_position (MetaCursorRenderer *renderer,
|
||||
MetaCursorReference * meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer);
|
||||
const MetaRectangle * meta_cursor_renderer_get_rect (MetaCursorRenderer *renderer);
|
||||
|
||||
void meta_cursor_renderer_set_dnd_surface (MetaCursorRenderer *renderer,
|
||||
CoglTexture *texture,
|
||||
int offset_x,
|
||||
int offset_y);
|
||||
void meta_cursor_renderer_set_dnd_surface_position (MetaCursorRenderer *renderer,
|
||||
int x, int y);
|
||||
|
||||
void meta_cursor_renderer_dnd_failed (MetaCursorRenderer *renderer,
|
||||
int dest_x, int dest_y);
|
||||
|
||||
#endif /* META_CURSOR_RENDERER_H */
|
||||
|
@@ -62,10 +62,20 @@ void meta_cursor_tracker_set_window_cursor (MetaCursorTracker *tracker,
|
||||
void meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker);
|
||||
void meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
|
||||
MetaCursorReference *cursor);
|
||||
void meta_cursor_tracker_set_dnd_surface (MetaCursorTracker *tracker,
|
||||
CoglTexture *texture,
|
||||
int offset_x,
|
||||
int offset_y);
|
||||
|
||||
void meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
|
||||
int new_x,
|
||||
int new_y);
|
||||
void meta_cursor_tracker_update_dnd_surface_position (MetaCursorTracker *tracker,
|
||||
int new_x,
|
||||
int new_y);
|
||||
void meta_cursor_tracker_dnd_failed (MetaCursorTracker *tracker,
|
||||
int dest_x,
|
||||
int dest_y);
|
||||
|
||||
MetaCursorReference * meta_cursor_tracker_get_displayed_cursor (MetaCursorTracker *tracker);
|
||||
|
||||
|
@@ -358,6 +358,28 @@ meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
|
||||
sync_cursor (tracker);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_set_dnd_surface (MetaCursorTracker *tracker,
|
||||
CoglTexture *texture,
|
||||
int offset_x,
|
||||
int offset_y)
|
||||
{
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
meta_cursor_renderer_set_dnd_surface (tracker->renderer, texture,
|
||||
offset_x, offset_y);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_dnd_failed (MetaCursorTracker *tracker,
|
||||
int dest_x,
|
||||
int dest_y)
|
||||
{
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
meta_cursor_renderer_dnd_failed (tracker->renderer, dest_x, dest_y);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
|
||||
int new_x,
|
||||
@@ -368,6 +390,17 @@ meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
|
||||
meta_cursor_renderer_set_position (tracker->renderer, new_x, new_y);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_update_dnd_surface_position (MetaCursorTracker *tracker,
|
||||
int new_x,
|
||||
int new_y)
|
||||
{
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
meta_cursor_renderer_set_dnd_surface_position (tracker->renderer,
|
||||
new_x, new_y);
|
||||
}
|
||||
|
||||
static void
|
||||
get_pointer_position_gdk (int *x,
|
||||
int *y,
|
||||
|
@@ -139,35 +139,56 @@ load_cursor_on_client (MetaCursor cursor)
|
||||
meta_prefs_get_cursor_size ());
|
||||
}
|
||||
|
||||
static void
|
||||
get_hardware_cursor_size (uint64_t *cursor_width, uint64_t *cursor_height)
|
||||
{
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
MetaBackend *meta_backend = meta_get_backend ();
|
||||
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend);
|
||||
|
||||
if (META_IS_CURSOR_RENDERER_NATIVE (renderer))
|
||||
{
|
||||
meta_cursor_renderer_native_get_cursor_size (META_CURSOR_RENDERER_NATIVE (renderer), cursor_width, cursor_height);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm,
|
||||
MetaCursorImage *image,
|
||||
uint8_t *pixels,
|
||||
int width,
|
||||
int height,
|
||||
uint width,
|
||||
uint height,
|
||||
int rowstride,
|
||||
uint32_t gbm_format)
|
||||
{
|
||||
if (width > 64 || height > 64)
|
||||
uint64_t cursor_width, cursor_height;
|
||||
get_hardware_cursor_size (&cursor_width, &cursor_height);
|
||||
|
||||
if (width > cursor_width || height > cursor_height)
|
||||
{
|
||||
meta_warning ("Invalid theme cursor size (must be at most 64x64)\n");
|
||||
meta_warning ("Invalid theme cursor size (must be at most %ux%u)\n",
|
||||
(unsigned int)cursor_width, (unsigned int)cursor_height);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gbm_device_is_format_supported (gbm, gbm_format,
|
||||
GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE))
|
||||
GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE))
|
||||
{
|
||||
uint8_t buf[4 * 64 * 64];
|
||||
int i;
|
||||
uint8_t buf[4 * cursor_width * cursor_height];
|
||||
uint i;
|
||||
|
||||
image->bo = gbm_bo_create (gbm, 64, 64,
|
||||
gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
|
||||
image->bo = gbm_bo_create (gbm, cursor_width, cursor_height,
|
||||
gbm_format, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
|
||||
|
||||
memset (buf, 0, sizeof(buf));
|
||||
for (i = 0; i < height; i++)
|
||||
memcpy (buf + i * 4 * 64, pixels + i * rowstride, width * 4);
|
||||
memcpy (buf + i * 4 * cursor_width, pixels + i * rowstride, width * 4);
|
||||
|
||||
gbm_bo_write (image->bo, buf, 64 * 64 * 4);
|
||||
gbm_bo_write (image->bo, buf, cursor_width * cursor_height * 4);
|
||||
}
|
||||
else
|
||||
meta_warning ("HW cursor for format %d not supported\n", gbm_format);
|
||||
@@ -191,7 +212,7 @@ static void
|
||||
meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image,
|
||||
XcursorImage *xc_image)
|
||||
{
|
||||
int width, height, rowstride;
|
||||
uint width, height, rowstride;
|
||||
CoglPixelFormat cogl_format;
|
||||
uint32_t gbm_format;
|
||||
ClutterBackend *clutter_backend;
|
||||
@@ -262,7 +283,8 @@ meta_cursor_image_load_from_buffer (MetaCursorImage *image,
|
||||
CoglContext *cogl_context;
|
||||
struct wl_shm_buffer *shm_buffer;
|
||||
uint32_t gbm_format;
|
||||
int width, height;
|
||||
uint64_t cursor_width, cursor_height;
|
||||
uint width, height;
|
||||
|
||||
image->hot_x = hot_x;
|
||||
image->hot_y = hot_y;
|
||||
@@ -313,22 +335,23 @@ meta_cursor_image_load_from_buffer (MetaCursorImage *image,
|
||||
}
|
||||
else
|
||||
{
|
||||
/* HW cursors must be 64x64, but 64x64 is huge, and no cursor theme actually uses
|
||||
that, so themed cursors must be padded with transparent pixels to fill the
|
||||
overlay. This is trivial if we have CPU access to the data, but it's not
|
||||
possible if the buffer is in GPU memory (and possibly tiled too), so if we
|
||||
don't get the right size, we fallback to GL.
|
||||
*/
|
||||
if (width != 64 || height != 64)
|
||||
{
|
||||
meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (gbm)
|
||||
{
|
||||
image->bo = gbm_bo_import (gbm, GBM_BO_IMPORT_WL_BUFFER,
|
||||
buffer, GBM_BO_USE_CURSOR_64X64);
|
||||
/* HW cursors have a predefined size (at least 64x64), which usually is bigger than cursor theme
|
||||
size, so themed cursors must be padded with transparent pixels to fill the
|
||||
overlay. This is trivial if we have CPU access to the data, but it's not
|
||||
possible if the buffer is in GPU memory (and possibly tiled too), so if we
|
||||
don't get the right size, we fallback to GL.
|
||||
*/
|
||||
get_hardware_cursor_size (&cursor_width, &cursor_height);
|
||||
|
||||
if (width != cursor_width || height != cursor_height)
|
||||
{
|
||||
meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
|
||||
return;
|
||||
}
|
||||
|
||||
image->bo = gbm_bo_import (gbm, GBM_BO_IMPORT_WL_BUFFER, buffer, GBM_BO_USE_CURSOR);
|
||||
if (!image->bo)
|
||||
meta_warning ("Importing HW cursor from wl_buffer failed\n");
|
||||
}
|
||||
|
@@ -44,12 +44,6 @@ enum {
|
||||
SIGNALS_LAST
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_POWER_SAVE_MODE,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static int signals[SIGNALS_LAST];
|
||||
|
||||
static void meta_monitor_manager_display_config_init (MetaDBusDisplayConfigIface *iface);
|
||||
@@ -167,11 +161,39 @@ make_logical_config (MetaMonitorManager *manager)
|
||||
manager->monitor_infos = (void*)g_array_free (monitor_infos, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
power_save_mode_changed (MetaMonitorManager *manager,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaMonitorManagerClass *klass;
|
||||
int mode = meta_dbus_display_config_get_power_save_mode (META_DBUS_DISPLAY_CONFIG (manager));
|
||||
|
||||
if (mode == META_POWER_SAVE_UNSUPPORTED)
|
||||
return;
|
||||
|
||||
/* If DPMS is unsupported, force the property back. */
|
||||
if (manager->power_save_mode == META_POWER_SAVE_UNSUPPORTED)
|
||||
{
|
||||
meta_dbus_display_config_set_power_save_mode (META_DBUS_DISPLAY_CONFIG (manager), META_POWER_SAVE_UNSUPPORTED);
|
||||
return;
|
||||
}
|
||||
|
||||
klass = META_MONITOR_MANAGER_GET_CLASS (manager);
|
||||
if (klass->set_power_save_mode)
|
||||
klass->set_power_save_mode (manager, mode);
|
||||
|
||||
manager->power_save_mode = mode;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_constructed (GObject *object)
|
||||
{
|
||||
MetaMonitorManager *manager = META_MONITOR_MANAGER (object);
|
||||
|
||||
g_signal_connect_object (manager, "notify::power-save-mode",
|
||||
G_CALLBACK (power_save_mode_changed), manager, 0);
|
||||
|
||||
manager->in_init = TRUE;
|
||||
|
||||
manager->config = meta_monitor_config_new ();
|
||||
@@ -214,23 +236,6 @@ meta_monitor_manager_constructed (GObject *object)
|
||||
manager->in_init = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_set_power_save_mode (MetaMonitorManager *manager,
|
||||
MetaPowerSave mode)
|
||||
{
|
||||
MetaMonitorManagerClass *klass;
|
||||
|
||||
if (manager->power_save_mode == META_POWER_SAVE_UNSUPPORTED ||
|
||||
mode == META_POWER_SAVE_UNSUPPORTED)
|
||||
return;
|
||||
|
||||
klass = META_MONITOR_MANAGER_GET_CLASS (manager);
|
||||
if (klass->set_power_save_mode)
|
||||
klass->set_power_save_mode (manager, mode);
|
||||
|
||||
manager->power_save_mode = mode;
|
||||
}
|
||||
|
||||
void
|
||||
meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
|
||||
int n_old_outputs)
|
||||
@@ -298,44 +303,6 @@ meta_monitor_manager_dispose (GObject *object)
|
||||
G_OBJECT_CLASS (meta_monitor_manager_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaMonitorManager *self = META_MONITOR_MANAGER (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_POWER_SAVE_MODE:
|
||||
meta_monitor_manager_set_power_save_mode (self, g_value_get_int (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaMonitorManager *self = META_MONITOR_MANAGER (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_POWER_SAVE_MODE:
|
||||
g_value_set_int (value, self->power_save_mode);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
meta_monitor_manager_real_read_edid (MetaMonitorManager *manager,
|
||||
MetaOutput *output)
|
||||
@@ -356,8 +323,6 @@ meta_monitor_manager_class_init (MetaMonitorManagerClass *klass)
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->constructed = meta_monitor_manager_constructed;
|
||||
object_class->get_property = meta_monitor_manager_get_property;
|
||||
object_class->set_property = meta_monitor_manager_set_property;
|
||||
object_class->dispose = meta_monitor_manager_dispose;
|
||||
object_class->finalize = meta_monitor_manager_finalize;
|
||||
|
||||
@@ -371,8 +336,6 @@ meta_monitor_manager_class_init (MetaMonitorManagerClass *klass)
|
||||
0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
g_object_class_override_property (object_class, PROP_POWER_SAVE_MODE, "power-save-mode");
|
||||
}
|
||||
|
||||
static const double known_diagonals[] = {
|
||||
|
@@ -28,6 +28,8 @@
|
||||
#include <meta/meta-backend.h>
|
||||
#include <meta/util.h>
|
||||
|
||||
#define DRAG_FAILED_MSECS 500
|
||||
|
||||
typedef struct {
|
||||
gboolean enabled;
|
||||
|
||||
@@ -39,8 +41,20 @@ typedef struct {
|
||||
gboolean previous_is_valid;
|
||||
} MetaOverlay;
|
||||
|
||||
typedef struct {
|
||||
MetaStage *stage;
|
||||
MetaOverlay overlay;
|
||||
ClutterTimeline *timeline;
|
||||
int orig_x;
|
||||
int orig_y;
|
||||
int dest_x;
|
||||
int dest_y;
|
||||
} MetaDragFailedAnimation;
|
||||
|
||||
struct _MetaStagePrivate {
|
||||
MetaOverlay dnd_overlay;
|
||||
MetaOverlay cursor_overlay;
|
||||
GList *drag_failed_animations;
|
||||
};
|
||||
typedef struct _MetaStagePrivate MetaStagePrivate;
|
||||
|
||||
@@ -54,6 +68,15 @@ meta_overlay_init (MetaOverlay *overlay)
|
||||
overlay->pipeline = cogl_pipeline_new (ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_overlay_copy (MetaOverlay *src,
|
||||
MetaOverlay *dst)
|
||||
{
|
||||
*dst = *src;
|
||||
dst->pipeline = cogl_pipeline_copy (src->pipeline);
|
||||
dst->texture = src->texture;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_overlay_free (MetaOverlay *overlay)
|
||||
{
|
||||
@@ -112,6 +135,7 @@ meta_stage_finalize (GObject *object)
|
||||
MetaStage *stage = META_STAGE (object);
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
meta_overlay_free (&priv->dnd_overlay);
|
||||
meta_overlay_free (&priv->cursor_overlay);
|
||||
}
|
||||
|
||||
@@ -120,9 +144,18 @@ meta_stage_paint (ClutterActor *actor)
|
||||
{
|
||||
MetaStage *stage = META_STAGE (actor);
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
MetaDragFailedAnimation *animation;
|
||||
GList *l;
|
||||
|
||||
CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor);
|
||||
|
||||
for (l = priv->drag_failed_animations; l; l = l->next)
|
||||
{
|
||||
animation = l->data;
|
||||
meta_overlay_paint (&animation->overlay);
|
||||
}
|
||||
|
||||
meta_overlay_paint (&priv->dnd_overlay);
|
||||
meta_overlay_paint (&priv->cursor_overlay);
|
||||
}
|
||||
|
||||
@@ -142,6 +175,7 @@ meta_stage_init (MetaStage *stage)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
meta_overlay_init (&priv->dnd_overlay);
|
||||
meta_overlay_init (&priv->cursor_overlay);
|
||||
|
||||
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), FALSE);
|
||||
@@ -183,6 +217,19 @@ queue_redraw_for_overlay (MetaStage *stage,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_stage_set_dnd_surface (MetaStage *stage,
|
||||
CoglTexture *texture,
|
||||
MetaRectangle *rect)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
meta_overlay_set (&priv->dnd_overlay, texture, rect);
|
||||
queue_redraw_for_overlay (stage, &priv->dnd_overlay);
|
||||
}
|
||||
|
||||
void
|
||||
meta_stage_set_cursor (MetaStage *stage,
|
||||
CoglTexture *texture,
|
||||
@@ -195,3 +242,84 @@ meta_stage_set_cursor (MetaStage *stage,
|
||||
meta_overlay_set (&priv->cursor_overlay, texture, rect);
|
||||
queue_redraw_for_overlay (stage, &priv->cursor_overlay);
|
||||
}
|
||||
|
||||
static void
|
||||
drag_failed_animation_frame_cb (ClutterTimeline *timeline,
|
||||
guint pos,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaDragFailedAnimation *data = user_data;
|
||||
gdouble progress = clutter_timeline_get_progress (timeline);
|
||||
CoglColor color;
|
||||
|
||||
cogl_color_init_from_4f (&color, 0, 0, 0, 1 - progress);
|
||||
cogl_pipeline_set_layer_combine_constant (data->overlay.pipeline, 0, &color);
|
||||
|
||||
data->overlay.current_rect.x = data->orig_x + ((data->dest_x - data->orig_x) * progress);
|
||||
data->overlay.current_rect.y = data->orig_y + ((data->dest_y - data->orig_y) * progress);
|
||||
queue_redraw_for_overlay (data->stage, &data->overlay);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_drag_failed_animation_free (MetaDragFailedAnimation *data)
|
||||
{
|
||||
MetaStage *stage = data->stage;
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
|
||||
priv->drag_failed_animations =
|
||||
g_list_remove (priv->drag_failed_animations, data);
|
||||
|
||||
g_object_unref (data->timeline);
|
||||
meta_overlay_free (&data->overlay);
|
||||
g_slice_free (MetaDragFailedAnimation, data);
|
||||
}
|
||||
|
||||
static MetaDragFailedAnimation *
|
||||
meta_drag_failed_animation_new (MetaStage *stage,
|
||||
int dest_x,
|
||||
int dest_y)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
MetaDragFailedAnimation *data;
|
||||
|
||||
data = g_slice_new0 (MetaDragFailedAnimation);
|
||||
data->stage = stage;
|
||||
data->orig_x = priv->dnd_overlay.current_rect.x;
|
||||
data->orig_y = priv->dnd_overlay.current_rect.y;
|
||||
data->dest_x = dest_x;
|
||||
data->dest_y = dest_y;
|
||||
|
||||
meta_overlay_copy (&priv->dnd_overlay, &data->overlay);
|
||||
|
||||
data->timeline = clutter_timeline_new (DRAG_FAILED_MSECS);
|
||||
clutter_timeline_set_progress_mode (data->timeline, CLUTTER_EASE_OUT_CUBIC);
|
||||
g_signal_connect (data->timeline, "new-frame",
|
||||
G_CALLBACK (drag_failed_animation_frame_cb), data);
|
||||
g_signal_connect_swapped (data->timeline, "completed",
|
||||
G_CALLBACK (meta_drag_failed_animation_free), data);
|
||||
|
||||
priv->drag_failed_animations =
|
||||
g_list_prepend (priv->drag_failed_animations, data);
|
||||
|
||||
cogl_pipeline_set_layer_combine (data->overlay.pipeline, 0,
|
||||
"RGBA = MODULATE (TEXTURE, CONSTANT[A])",
|
||||
NULL);
|
||||
return data;
|
||||
}
|
||||
|
||||
void
|
||||
meta_stage_dnd_failed (MetaStage *stage,
|
||||
int dest_x,
|
||||
int dest_y)
|
||||
{
|
||||
MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
|
||||
MetaDragFailedAnimation *data;
|
||||
|
||||
g_assert (meta_is_wayland_compositor ());
|
||||
|
||||
if (!priv->dnd_overlay.enabled)
|
||||
return;
|
||||
|
||||
data = meta_drag_failed_animation_new (stage, dest_x, dest_y);
|
||||
clutter_timeline_start (data->timeline);
|
||||
}
|
||||
|
@@ -51,9 +51,18 @@ GType meta_stage_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterActor *meta_stage_new (void);
|
||||
|
||||
void meta_stage_set_dnd_surface (MetaStage *stage,
|
||||
CoglTexture *texture,
|
||||
MetaRectangle *rect);
|
||||
|
||||
void meta_stage_set_cursor (MetaStage *stage,
|
||||
CoglTexture *texture,
|
||||
MetaRectangle *rect);
|
||||
|
||||
void meta_stage_dnd_failed (MetaStage *stage,
|
||||
int dest_x,
|
||||
int dest_y);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* META_STAGE_H */
|
||||
|
@@ -27,16 +27,27 @@
|
||||
#include "meta-cursor-renderer-native.h"
|
||||
|
||||
#include <gbm.h>
|
||||
#include <xf86drm.h>
|
||||
|
||||
#include "meta-cursor-private.h"
|
||||
#include "meta-monitor-manager.h"
|
||||
|
||||
#ifndef DRM_CAP_CURSOR_WIDTH
|
||||
#define DRM_CAP_CURSOR_WIDTH 0x8
|
||||
#endif
|
||||
#ifndef DRM_CAP_CURSOR_HEIGHT
|
||||
#define DRM_CAP_CURSOR_HEIGHT 0x9
|
||||
#endif
|
||||
|
||||
struct _MetaCursorRendererNativePrivate
|
||||
{
|
||||
gboolean has_hw_cursor;
|
||||
|
||||
int drm_fd;
|
||||
struct gbm_device *gbm;
|
||||
|
||||
uint64_t cursor_width;
|
||||
uint64_t cursor_height;
|
||||
};
|
||||
typedef struct _MetaCursorRendererNativePrivate MetaCursorRendererNativePrivate;
|
||||
|
||||
@@ -71,17 +82,13 @@ set_crtc_cursor (MetaCursorRendererNative *native,
|
||||
{
|
||||
struct gbm_bo *bo;
|
||||
union gbm_bo_handle handle;
|
||||
int width, height;
|
||||
int hot_x, hot_y;
|
||||
|
||||
bo = meta_cursor_reference_get_gbm_bo (cursor, &hot_x, &hot_y);
|
||||
|
||||
handle = gbm_bo_get_handle (bo);
|
||||
width = gbm_bo_get_width (bo);
|
||||
height = gbm_bo_get_height (bo);
|
||||
|
||||
drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, handle.u32,
|
||||
width, height, hot_x, hot_y);
|
||||
priv->cursor_width, priv->cursor_height, hot_x, hot_y);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -186,6 +193,19 @@ meta_cursor_renderer_native_init (MetaCursorRendererNative *native)
|
||||
CoglRenderer *cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (ctx));
|
||||
priv->drm_fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
|
||||
priv->gbm = gbm_create_device (priv->drm_fd);
|
||||
|
||||
uint64_t width, height;
|
||||
if (drmGetCap (priv->drm_fd, DRM_CAP_CURSOR_WIDTH, &width) == 0 &&
|
||||
drmGetCap (priv->drm_fd, DRM_CAP_CURSOR_HEIGHT, &height) == 0)
|
||||
{
|
||||
priv->cursor_width = width;
|
||||
priv->cursor_height = height;
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->cursor_width = 64;
|
||||
priv->cursor_height = 64;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -198,6 +218,16 @@ meta_cursor_renderer_native_get_gbm_device (MetaCursorRendererNative *native)
|
||||
return priv->gbm;
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_renderer_native_get_cursor_size (MetaCursorRendererNative *native,
|
||||
uint64_t *width, uint64_t *height)
|
||||
{
|
||||
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
|
||||
|
||||
*width = priv->cursor_width;
|
||||
*height = priv->cursor_height;
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_renderer_native_force_update (MetaCursorRendererNative *native)
|
||||
{
|
||||
|
@@ -50,6 +50,7 @@ struct _MetaCursorRendererNativeClass
|
||||
GType meta_cursor_renderer_native_get_type (void) G_GNUC_CONST;
|
||||
|
||||
struct gbm_device * meta_cursor_renderer_native_get_gbm_device (MetaCursorRendererNative *renderer);
|
||||
void meta_cursor_renderer_native_get_cursor_size (MetaCursorRendererNative *native, uint64_t *width, uint64_t *height);
|
||||
void meta_cursor_renderer_native_force_update (MetaCursorRendererNative *renderer);
|
||||
|
||||
#endif /* META_CURSOR_RENDERER_NATIVE_H */
|
||||
|
@@ -144,7 +144,7 @@ static gboolean
|
||||
output_get_boolean_property (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output, const char *propname)
|
||||
{
|
||||
gboolean value;
|
||||
gboolean value = FALSE;
|
||||
Atom atom, actual_type;
|
||||
int actual_format;
|
||||
unsigned long nitems, bytes_after;
|
||||
@@ -158,12 +158,12 @@ output_get_boolean_property (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
&actual_type, &actual_format,
|
||||
&nitems, &bytes_after, &buffer);
|
||||
|
||||
if (actual_type != XA_CARDINAL || actual_format != 32 ||
|
||||
nitems < 1)
|
||||
return FALSE;
|
||||
if (actual_type != XA_CARDINAL || actual_format != 32 || nitems < 1)
|
||||
goto out;
|
||||
|
||||
value = ((int*)buffer)[0];
|
||||
|
||||
out:
|
||||
XFree (buffer);
|
||||
return value;
|
||||
}
|
||||
@@ -187,7 +187,7 @@ static int
|
||||
output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
MetaOutput *output)
|
||||
{
|
||||
gboolean value;
|
||||
int value = -1;
|
||||
Atom atom, actual_type;
|
||||
int actual_format;
|
||||
unsigned long nitems, bytes_after;
|
||||
@@ -201,14 +201,17 @@ output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
&actual_type, &actual_format,
|
||||
&nitems, &bytes_after, &buffer);
|
||||
|
||||
if (actual_type != XA_INTEGER || actual_format != 32 ||
|
||||
nitems < 1)
|
||||
return -1;
|
||||
if (actual_type != XA_INTEGER || actual_format != 32 || nitems < 1)
|
||||
goto out;
|
||||
|
||||
value = ((int*)buffer)[0];
|
||||
|
||||
out:
|
||||
XFree (buffer);
|
||||
return normalize_backlight (output, value);
|
||||
if (value > 0)
|
||||
return normalize_backlight (output, value);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -185,6 +185,9 @@ file_loaded (GObject *source_object,
|
||||
image->texture = texture;
|
||||
|
||||
out:
|
||||
if (pixbuf != NULL)
|
||||
g_object_unref (pixbuf);
|
||||
|
||||
image->loaded = TRUE;
|
||||
g_signal_emit (image, signals[LOADED], 0);
|
||||
}
|
||||
|
@@ -612,9 +612,14 @@ update_onscreen_requirements (MetaWindow *window,
|
||||
*/
|
||||
if (window->frame && window->decorated)
|
||||
{
|
||||
MetaRectangle titlebar_rect;
|
||||
MetaRectangle titlebar_rect, frame_rect;
|
||||
|
||||
meta_window_get_titlebar_rect (window, &titlebar_rect);
|
||||
meta_window_get_frame_rect (window, &frame_rect);
|
||||
|
||||
/* translate into screen coordinates */
|
||||
titlebar_rect.x = frame_rect.x;
|
||||
titlebar_rect.y = frame_rect.y;
|
||||
|
||||
old = window->require_titlebar_visible;
|
||||
window->require_titlebar_visible =
|
||||
|
@@ -57,6 +57,7 @@ typedef struct MetaEdgeResistanceData MetaEdgeResistanceData;
|
||||
typedef enum {
|
||||
META_LIST_DEFAULT = 0, /* normal windows */
|
||||
META_LIST_INCLUDE_OVERRIDE_REDIRECT = 1 << 0, /* normal and O-R */
|
||||
META_LIST_SORTED = 1 << 1, /* sort list by mru */
|
||||
} MetaListWindowsFlags;
|
||||
|
||||
#define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
|
||||
|
@@ -150,6 +150,9 @@ static void update_cursor_theme (void);
|
||||
static void prefs_changed_callback (MetaPreference pref,
|
||||
void *data);
|
||||
|
||||
static int mru_cmp (gconstpointer a,
|
||||
gconstpointer b);
|
||||
|
||||
static void
|
||||
meta_display_get_property(GObject *object,
|
||||
guint prop_id,
|
||||
@@ -1061,6 +1064,9 @@ meta_display_list_windows (MetaDisplay *display,
|
||||
tmp = next;
|
||||
}
|
||||
|
||||
if (flags & META_LIST_SORTED)
|
||||
winlist = g_slist_sort (winlist, mru_cmp);
|
||||
|
||||
return winlist;
|
||||
}
|
||||
|
||||
|
@@ -101,6 +101,8 @@ typedef struct
|
||||
MetaKeyCombo *iso_next_group_combos;
|
||||
int n_iso_next_group_combos;
|
||||
|
||||
xkb_level_index_t keymap_num_levels;
|
||||
|
||||
/* Alt+click button grabs */
|
||||
ClutterModifierType window_grab_modifiers;
|
||||
} MetaKeyBindingManager;
|
||||
|
@@ -40,7 +40,11 @@
|
||||
#include <meta/prefs.h>
|
||||
#include "meta-accel-parse.h"
|
||||
|
||||
#ifdef __linux__
|
||||
#include <linux/input.h>
|
||||
#elif !defined KEY_GRAVE
|
||||
#define KEY_GRAVE 0x29 /* assume the use of xf86-input-keyboard */
|
||||
#endif
|
||||
|
||||
#include "backends/x11/meta-backend-x11.h"
|
||||
#include "x11/window-x11.h"
|
||||
@@ -236,29 +240,19 @@ reload_modmap (MetaKeyBindingManager *keys)
|
||||
|
||||
static gboolean
|
||||
is_keycode_for_keysym (struct xkb_keymap *keymap,
|
||||
xkb_layout_index_t layout,
|
||||
xkb_level_index_t level,
|
||||
xkb_keycode_t keycode,
|
||||
xkb_keysym_t keysym)
|
||||
{
|
||||
xkb_layout_index_t num_layouts, i;
|
||||
const xkb_keysym_t *syms;
|
||||
int num_syms, k;
|
||||
|
||||
num_layouts = xkb_keymap_num_layouts_for_key (keymap, keycode);
|
||||
for (i = 0; i < num_layouts; i++)
|
||||
num_syms = xkb_keymap_key_get_syms_by_level (keymap, keycode, layout, level, &syms);
|
||||
for (k = 0; k < num_syms; k++)
|
||||
{
|
||||
xkb_level_index_t num_levels, j;
|
||||
|
||||
num_levels = xkb_keymap_num_levels_for_key (keymap, keycode, i);
|
||||
for (j = 0; j < num_levels; j++)
|
||||
{
|
||||
const xkb_keysym_t *syms;
|
||||
int num_syms, k;
|
||||
|
||||
num_syms = xkb_keymap_key_get_syms_by_level (keymap, keycode, i, j, &syms);
|
||||
for (k = 0; k < num_syms; k++)
|
||||
{
|
||||
if (syms[k] == keysym)
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
if (syms[k] == keysym)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
@@ -268,6 +262,8 @@ typedef struct
|
||||
{
|
||||
GArray *keycodes;
|
||||
xkb_keysym_t keysym;
|
||||
xkb_layout_index_t layout;
|
||||
xkb_level_index_t level;
|
||||
} FindKeysymData;
|
||||
|
||||
static void
|
||||
@@ -278,8 +274,10 @@ get_keycodes_for_keysym_iter (struct xkb_keymap *keymap,
|
||||
FindKeysymData *search_data = data;
|
||||
GArray *keycodes = search_data->keycodes;
|
||||
xkb_keysym_t keysym = search_data->keysym;
|
||||
xkb_layout_index_t layout = search_data->layout;
|
||||
xkb_level_index_t level = search_data->level;
|
||||
|
||||
if (is_keycode_for_keysym (keymap, keycode, keysym))
|
||||
if (is_keycode_for_keysym (keymap, layout, level, keycode, keysym))
|
||||
g_array_append_val (keycodes, keycode);
|
||||
}
|
||||
|
||||
@@ -307,8 +305,15 @@ get_keycodes_for_keysym (MetaKeyBindingManager *keys,
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
struct xkb_keymap *keymap = meta_backend_get_keymap (backend);
|
||||
FindKeysymData search_data = { retval, keysym };
|
||||
xkb_keymap_key_for_each (keymap, get_keycodes_for_keysym_iter, &search_data);
|
||||
xkb_layout_index_t i;
|
||||
xkb_level_index_t j;
|
||||
|
||||
for (i = 0; i < xkb_keymap_num_layouts (keymap); i++)
|
||||
for (j = 0; j < keys->keymap_num_levels; j++)
|
||||
{
|
||||
FindKeysymData search_data = { retval, keysym, i, j };
|
||||
xkb_keymap_key_for_each (keymap, get_keycodes_for_keysym_iter, &search_data);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -319,7 +324,7 @@ get_keycodes_for_keysym (MetaKeyBindingManager *keys,
|
||||
|
||||
static guint
|
||||
get_first_keycode_for_keysym (MetaKeyBindingManager *keys,
|
||||
guint keysym)
|
||||
guint keysym)
|
||||
{
|
||||
int *keycodes;
|
||||
int n_keycodes;
|
||||
@@ -336,6 +341,32 @@ get_first_keycode_for_keysym (MetaKeyBindingManager *keys,
|
||||
return keycode;
|
||||
}
|
||||
|
||||
static void
|
||||
determine_keymap_num_levels_iter (struct xkb_keymap *keymap,
|
||||
xkb_keycode_t keycode,
|
||||
void *data)
|
||||
{
|
||||
xkb_level_index_t *num_levels = data;
|
||||
xkb_layout_index_t i;
|
||||
|
||||
for (i = 0; i < xkb_keymap_num_layouts_for_key (keymap, keycode); i++)
|
||||
{
|
||||
xkb_level_index_t level = xkb_keymap_num_levels_for_key (keymap, keycode, i);
|
||||
if (level > *num_levels)
|
||||
*num_levels = level;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
determine_keymap_num_levels (MetaKeyBindingManager *keys)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
struct xkb_keymap *keymap = meta_backend_get_keymap (backend);
|
||||
|
||||
keys->keymap_num_levels = 0;
|
||||
xkb_keymap_key_for_each (keymap, determine_keymap_num_levels_iter, &keys->keymap_num_levels);
|
||||
}
|
||||
|
||||
static void
|
||||
reload_iso_next_group_combos (MetaKeyBindingManager *keys)
|
||||
{
|
||||
@@ -484,6 +515,8 @@ reload_keycodes (MetaKeyBindingManager *keys)
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"Reloading keycodes for binding tables\n");
|
||||
|
||||
determine_keymap_num_levels (keys);
|
||||
|
||||
if (keys->overlay_key_combo.keysym != 0)
|
||||
{
|
||||
keys->overlay_key_combo.keycode =
|
||||
|
@@ -1187,7 +1187,6 @@ settings_changed (GSettings *settings,
|
||||
{
|
||||
/* Unknown preference type. This quite likely simply isn't
|
||||
* a preference we track changes to. */
|
||||
return;
|
||||
}
|
||||
|
||||
g_variant_unref (value);
|
||||
|
@@ -1056,10 +1056,6 @@ stack_sync_to_xserver (MetaStack *stack)
|
||||
all_root_children_stacked = g_array_new (FALSE, FALSE, sizeof (guint64));
|
||||
x11_hidden_stack_ids = g_array_new (FALSE, FALSE, sizeof (guint64));
|
||||
|
||||
/* The screen guard window sits above all hidden windows and acts as
|
||||
* a barrier to input reaching these windows. */
|
||||
g_array_append_val (x11_hidden_stack_ids, stack->screen->guard_window);
|
||||
|
||||
meta_topic (META_DEBUG_STACK, "Top to bottom: ");
|
||||
meta_push_no_msg_prefix ();
|
||||
|
||||
@@ -1107,6 +1103,10 @@ stack_sync_to_xserver (MetaStack *stack)
|
||||
meta_topic (META_DEBUG_STACK, "\n");
|
||||
meta_pop_no_msg_prefix ();
|
||||
|
||||
/* The screen guard window sits above all hidden windows and acts as
|
||||
* a barrier to input reaching these windows. */
|
||||
g_array_append_val (x11_hidden_stack_ids, stack->screen->guard_window);
|
||||
|
||||
/* Sync to server */
|
||||
|
||||
meta_topic (META_DEBUG_STACK, "Restacking %u windows\n",
|
||||
|
@@ -653,9 +653,6 @@ void meta_window_set_transient_for (MetaWindow *window,
|
||||
void meta_window_set_opacity (MetaWindow *window,
|
||||
guint8 opacity);
|
||||
|
||||
void meta_window_set_custom_frame_extents (MetaWindow *window,
|
||||
GtkBorder *extents);
|
||||
|
||||
void meta_window_handle_enter (MetaWindow *window,
|
||||
guint32 timestamp,
|
||||
guint root_x,
|
||||
|
@@ -1062,8 +1062,8 @@ _meta_window_shared_new (MetaDisplay *display,
|
||||
|
||||
if (window->initial_workspace_set)
|
||||
{
|
||||
gboolean on_all_workspaces;
|
||||
MetaWorkspace *workspace;
|
||||
gboolean on_all_workspaces = window->on_all_workspaces;
|
||||
MetaWorkspace *workspace = NULL;
|
||||
|
||||
if (window->initial_workspace == (int) 0xFFFFFFFF)
|
||||
{
|
||||
@@ -1077,15 +1077,13 @@ _meta_window_shared_new (MetaDisplay *display,
|
||||
window->on_all_workspaces_requested = TRUE;
|
||||
|
||||
on_all_workspaces = TRUE;
|
||||
workspace = NULL;
|
||||
}
|
||||
else
|
||||
else if (!on_all_workspaces)
|
||||
{
|
||||
meta_topic (META_DEBUG_PLACEMENT,
|
||||
"Window %s is initially on space %d\n",
|
||||
window->desc, window->initial_workspace);
|
||||
|
||||
on_all_workspaces = FALSE;
|
||||
workspace = meta_screen_get_workspace_by_index (window->screen,
|
||||
window->initial_workspace);
|
||||
}
|
||||
@@ -1099,9 +1097,9 @@ _meta_window_shared_new (MetaDisplay *display,
|
||||
* but appear on other workspaces. override-redirect windows are part
|
||||
* of no workspace.
|
||||
*/
|
||||
if (!window->override_redirect)
|
||||
if (!window->override_redirect && window->workspace == NULL)
|
||||
{
|
||||
if (window->workspace == NULL && window->transient_for != NULL)
|
||||
if (window->transient_for != NULL)
|
||||
{
|
||||
meta_topic (META_DEBUG_PLACEMENT,
|
||||
"Putting window %s on same workspace as parent %s\n",
|
||||
@@ -1112,7 +1110,15 @@ _meta_window_shared_new (MetaDisplay *display,
|
||||
window->transient_for->workspace);
|
||||
}
|
||||
|
||||
if (window->workspace == NULL)
|
||||
if (window->on_all_workspaces)
|
||||
{
|
||||
meta_topic (META_DEBUG_PLACEMENT,
|
||||
"Putting window %s on all workspaces\n",
|
||||
window->desc);
|
||||
|
||||
set_workspace_state (window, TRUE, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_topic (META_DEBUG_PLACEMENT,
|
||||
"Putting window %s on active workspace\n",
|
||||
@@ -2089,7 +2095,7 @@ windows_overlap (const MetaWindow *w1, const MetaWindow *w2)
|
||||
static gboolean
|
||||
window_would_be_covered (const MetaWindow *newbie)
|
||||
{
|
||||
MetaWorkspace *workspace = newbie->workspace;
|
||||
MetaWorkspace *workspace = meta_window_get_workspace ((MetaWindow *)newbie);
|
||||
GList *tmp, *windows;
|
||||
|
||||
windows = meta_workspace_list_windows (workspace);
|
||||
@@ -4291,7 +4297,7 @@ meta_window_focus (MetaWindow *window,
|
||||
* - workspace->windows is a list of windows that is located on
|
||||
* that workspace.
|
||||
*
|
||||
* - If the window is on_all_workspaces, then then
|
||||
* - If the window is on_all_workspaces, then
|
||||
* window->workspace == NULL, but workspace->windows contains
|
||||
* the window.
|
||||
*/
|
||||
@@ -4313,7 +4319,8 @@ set_workspace_state (MetaWindow *window,
|
||||
g_return_if_fail ((window->constructing && on_all_workspaces) || window->unmanaging);
|
||||
|
||||
if (on_all_workspaces == window->on_all_workspaces &&
|
||||
workspace == window->workspace)
|
||||
workspace == window->workspace &&
|
||||
!window->constructing)
|
||||
return;
|
||||
|
||||
if (window->workspace)
|
||||
@@ -5385,7 +5392,7 @@ meta_window_shove_titlebar_onscreen (MetaWindow *window)
|
||||
gboolean
|
||||
meta_window_titlebar_is_onscreen (MetaWindow *window)
|
||||
{
|
||||
MetaRectangle titlebar_rect;
|
||||
MetaRectangle titlebar_rect, frame_rect;
|
||||
GList *onscreen_region;
|
||||
gboolean is_onscreen;
|
||||
|
||||
@@ -5400,6 +5407,11 @@ meta_window_titlebar_is_onscreen (MetaWindow *window)
|
||||
/* Get the rectangle corresponding to the titlebar */
|
||||
meta_window_get_titlebar_rect (window, &titlebar_rect);
|
||||
|
||||
/* Translate into screen coordinates */
|
||||
meta_window_get_frame_rect (window, &frame_rect);
|
||||
titlebar_rect.x = frame_rect.x;
|
||||
titlebar_rect.y = frame_rect.y;
|
||||
|
||||
/* Run through the spanning rectangles for the screen and see if one of
|
||||
* them overlaps with the titlebar sufficiently to consider it onscreen.
|
||||
*/
|
||||
@@ -6719,7 +6731,7 @@ meta_window_set_demands_attention (MetaWindow *window)
|
||||
other_window = stack->data;
|
||||
stack = stack->next;
|
||||
|
||||
if (meta_window_located_on_workspace (other_window, window->workspace))
|
||||
if (meta_window_located_on_workspace (other_window, workspace))
|
||||
{
|
||||
meta_window_get_frame_rect (other_window, &other_rect);
|
||||
|
||||
@@ -7887,24 +7899,6 @@ meta_window_handle_ungrabbed_event (MetaWindow *window,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_set_custom_frame_extents (MetaWindow *window,
|
||||
GtkBorder *extents)
|
||||
{
|
||||
if (extents)
|
||||
{
|
||||
window->has_custom_frame_extents = TRUE;
|
||||
window->custom_frame_extents = *extents;
|
||||
}
|
||||
else
|
||||
{
|
||||
window->has_custom_frame_extents = FALSE;
|
||||
memset (&window->custom_frame_extents, 0, sizeof (window->custom_frame_extents));
|
||||
}
|
||||
|
||||
meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_window_can_maximize (MetaWindow *window)
|
||||
{
|
||||
|
@@ -170,6 +170,7 @@ MetaWorkspace*
|
||||
meta_workspace_new (MetaScreen *screen)
|
||||
{
|
||||
MetaWorkspace *workspace;
|
||||
GSList *windows, *l;
|
||||
|
||||
workspace = g_object_new (META_TYPE_WORKSPACE, NULL);
|
||||
|
||||
@@ -179,6 +180,13 @@ meta_workspace_new (MetaScreen *screen)
|
||||
workspace->windows = NULL;
|
||||
workspace->mru_list = NULL;
|
||||
|
||||
/* make sure sticky windows are in our mru_list */
|
||||
windows = meta_display_list_windows (screen->display, META_LIST_SORTED);
|
||||
for (l = windows; l; l = l->next)
|
||||
if (meta_window_located_on_workspace (l->data, workspace))
|
||||
meta_workspace_add_window (workspace, l->data);
|
||||
g_slist_free (windows);
|
||||
|
||||
workspace->work_areas_invalid = TRUE;
|
||||
workspace->work_area_monitor = NULL;
|
||||
workspace->work_area_screen.x = 0;
|
||||
@@ -358,7 +366,7 @@ meta_workspace_relocate_windows (MetaWorkspace *workspace,
|
||||
{
|
||||
MetaWindow *window = l->data;
|
||||
|
||||
if (!window->override_redirect)
|
||||
if (!window->on_all_workspaces)
|
||||
meta_window_change_workspace (window, new_home);
|
||||
}
|
||||
|
||||
|
@@ -28,7 +28,7 @@
|
||||
#define META_TYPE_WORKSPACE (meta_workspace_get_type ())
|
||||
#define META_WORKSPACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_WORKSPACE, MetaWorkspace))
|
||||
#define META_WORKSPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_WORKSPACE, MetaWorkspaceClass))
|
||||
#define META_IS_WORKSPACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_WORKSPACE_TYPE))
|
||||
#define META_IS_WORKSPACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_WORKSPACE))
|
||||
#define META_IS_WORKSPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_WORKSPACE))
|
||||
#define META_WORKSPACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_WORKSPACE, MetaWorkspaceClass))
|
||||
|
||||
|
@@ -71,6 +71,11 @@ lower <client-id>/<window-id>
|
||||
for Wayland clients. (It's also considered discouraged, but supported, for
|
||||
non-override-redirect X11 clients.)
|
||||
|
||||
minimize <client-id>/<window-id>
|
||||
unminimize <client-id>/<window-id>
|
||||
Ask the client to minimize or unminimize the given window ID. This older
|
||||
term for this operation is "iconify".
|
||||
|
||||
destroy <client-id>/<window-id>
|
||||
Destroy the given window
|
||||
|
||||
@@ -80,7 +85,10 @@ wait
|
||||
|
||||
assert_stacking <client-id>/<window-id> <client-id>/<window-id> ...
|
||||
Assert that the list of client windows known to Mutter is as given and in
|
||||
the given order, bottom to top.
|
||||
the given order, bottom to top. The character '|' can be present in the
|
||||
list of windows to indicate the guard window that separates hidden and
|
||||
visible windows. If '|' isn't present, the guard window is asserted to
|
||||
be below all client windows.
|
||||
|
||||
This function also queries the X server stack and verifies that Mutter's
|
||||
expectation of the X server stack matches reality.
|
||||
|
18
src/tests/stacking/minimized.metatest
Normal file
18
src/tests/stacking/minimized.metatest
Normal file
@@ -0,0 +1,18 @@
|
||||
new_client 1 x11
|
||||
create 1/1
|
||||
show 1/1
|
||||
create 1/2
|
||||
show 1/2
|
||||
wait
|
||||
assert_stacking 1/1 1/2
|
||||
|
||||
minimize 1/2
|
||||
wait
|
||||
assert_stacking 1/2 | 1/1
|
||||
|
||||
# unminimize doesn't work for GTK+ currently, because GTK+ expects
|
||||
# to be able to de-iconify with MapWindow, but the window is already
|
||||
# mapped.
|
||||
activate 1/2
|
||||
wait
|
||||
assert_stacking 1/1 1/2
|
@@ -12,7 +12,7 @@ assert_stacking 1/1 1/2
|
||||
|
||||
lower 1/2
|
||||
wait
|
||||
assert_stacking 1/2 1/1
|
||||
assert_stacking 1/2 | 1/1
|
||||
|
||||
raise 1/2
|
||||
wait
|
||||
|
@@ -263,6 +263,34 @@ process_line (const char *line)
|
||||
XSyncSetCounter (gdk_x11_display_get_xdisplay (gdk_display_get_default ()),
|
||||
counter, sync_value);
|
||||
}
|
||||
else if (strcmp (argv[0], "minimize") == 0)
|
||||
{
|
||||
if (argc != 2)
|
||||
{
|
||||
g_print ("usage: minimize <id>");
|
||||
goto out;
|
||||
}
|
||||
|
||||
GtkWidget *window = lookup_window (argv[1]);
|
||||
if (!window)
|
||||
goto out;
|
||||
|
||||
gtk_window_iconify (GTK_WINDOW (window));
|
||||
}
|
||||
else if (strcmp (argv[0], "unminimize") == 0)
|
||||
{
|
||||
if (argc != 2)
|
||||
{
|
||||
g_print ("usage: unminimize <id>");
|
||||
goto out;
|
||||
}
|
||||
|
||||
GtkWidget *window = lookup_window (argv[1]);
|
||||
if (!window)
|
||||
goto out;
|
||||
|
||||
gtk_window_deiconify (GTK_WINDOW (window));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_print ("Unknown command %s", argv[0]);
|
||||
|
@@ -413,6 +413,7 @@ typedef struct {
|
||||
AsyncWaiter *waiter;
|
||||
guint log_handler_id;
|
||||
GString *warning_messages;
|
||||
GMainLoop *loop;
|
||||
} TestCase;
|
||||
|
||||
static gboolean
|
||||
@@ -483,10 +484,21 @@ test_case_new (void)
|
||||
|
||||
test->clients = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
test->waiter = async_waiter_new ();
|
||||
test->loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
return test;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
test_case_before_redraw (gpointer data)
|
||||
{
|
||||
TestCase *test = data;
|
||||
|
||||
g_main_loop_quit (test->loop);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
test_case_wait (TestCase *test,
|
||||
GError **error)
|
||||
@@ -494,11 +506,30 @@ test_case_wait (TestCase *test,
|
||||
GHashTableIter iter;
|
||||
gpointer key, value;
|
||||
|
||||
/* First have each client set a XSync counter, and wait until
|
||||
* we receive the resulting event - so we know we've received
|
||||
* everything that the client have sent us.
|
||||
*/
|
||||
g_hash_table_iter_init (&iter, test->clients);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
||||
if (!test_client_wait (value, error))
|
||||
return FALSE;
|
||||
|
||||
/* Then wait until we've done any outstanding queued up work.
|
||||
* Though we add this as BEFORE_REDRAW, the iteration that runs the
|
||||
* BEFORE_REDRAW idles will proceed on and do the redraw, so we're
|
||||
* waiting until after *all* frame processing.
|
||||
*/
|
||||
meta_later_add (META_LATER_BEFORE_REDRAW,
|
||||
test_case_before_redraw,
|
||||
test,
|
||||
NULL);
|
||||
g_main_loop_run (test->loop);
|
||||
|
||||
/* Then set an XSync counter ourselves and and wait until
|
||||
* we receive the resulting event - this makes sure that we've
|
||||
* received back any X events we generated.
|
||||
*/
|
||||
async_waiter_set_and_wait (test->waiter);
|
||||
return TRUE;
|
||||
}
|
||||
@@ -579,6 +610,13 @@ test_case_assert_stacking (TestCase *test,
|
||||
else
|
||||
g_string_append_printf (stack_string, "(%s)", window->title);
|
||||
}
|
||||
else if (windows[i] == display->screen->guard_window)
|
||||
{
|
||||
if (stack_string->len > 0)
|
||||
g_string_append_c (stack_string, ' ');
|
||||
|
||||
g_string_append_c (stack_string, '|');
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < n_expected_windows; i++)
|
||||
@@ -589,6 +627,16 @@ test_case_assert_stacking (TestCase *test,
|
||||
g_string_append (expected_string, expected_windows[i]);
|
||||
}
|
||||
|
||||
/* Don't require '| ' as a prefix if there are no hidden windows - we
|
||||
* remove the prefix from the actual string instead of adding it to the
|
||||
* expected string for clarity of the error message
|
||||
*/
|
||||
if (index (expected_string->str, '|') == NULL && stack_string->str[0] == '|')
|
||||
{
|
||||
g_string_erase (stack_string,
|
||||
0, stack_string->str[1] == ' ' ? 2 : 1);
|
||||
}
|
||||
|
||||
if (strcmp (expected_string->str, stack_string->str) != 0)
|
||||
{
|
||||
g_set_error (error, TEST_RUNNER_ERROR, TEST_RUNNER_ERROR_ASSERTION_FAILED,
|
||||
@@ -725,6 +773,8 @@ test_case_do (TestCase *test,
|
||||
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], "destroy") == 0)
|
||||
{
|
||||
if (argc != 2)
|
||||
@@ -766,6 +816,7 @@ test_case_do (TestCase *test,
|
||||
{
|
||||
if (!test_case_assert_stacking (test, argv + 1, argc - 1, error))
|
||||
return FALSE;
|
||||
|
||||
if (!test_case_check_xserver_stacking (test, error))
|
||||
return FALSE;
|
||||
}
|
||||
|
@@ -34,6 +34,7 @@
|
||||
#include "meta-wayland-seat.h"
|
||||
#include "meta-wayland-pointer.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -46,6 +47,7 @@ struct _MetaWaylandDataSource
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
struct wl_array mime_types;
|
||||
gboolean has_target;
|
||||
};
|
||||
|
||||
static void
|
||||
@@ -67,7 +69,10 @@ data_offer_accept (struct wl_client *client,
|
||||
* this be a wl_data_device request? */
|
||||
|
||||
if (offer->source)
|
||||
wl_data_source_send_target (offer->source->resource, mime_type);
|
||||
{
|
||||
wl_data_source_send_target (offer->source->resource, mime_type);
|
||||
offer->source->has_target = mime_type != NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -162,7 +167,7 @@ static struct wl_data_source_interface data_source_interface = {
|
||||
data_source_destroy
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
struct _MetaWaylandDragGrab {
|
||||
MetaWaylandPointerGrab generic;
|
||||
|
||||
MetaWaylandSeat *seat;
|
||||
@@ -177,7 +182,12 @@ typedef struct {
|
||||
|
||||
MetaWaylandDataSource *drag_data_source;
|
||||
struct wl_listener drag_data_source_listener;
|
||||
} MetaWaylandDragGrab;
|
||||
|
||||
MetaWaylandSurface *drag_origin;
|
||||
struct wl_listener drag_origin_listener;
|
||||
|
||||
int drag_start_x, drag_start_y;
|
||||
};
|
||||
|
||||
static void
|
||||
destroy_drag_focus (struct wl_listener *listener, void *data)
|
||||
@@ -202,6 +212,8 @@ drag_grab_focus (MetaWaylandPointerGrab *grab,
|
||||
if (drag_grab->drag_focus == surface)
|
||||
return;
|
||||
|
||||
meta_wayland_pointer_set_focus (&seat->pointer, surface, FALSE);
|
||||
|
||||
if (drag_grab->drag_focus_data_device)
|
||||
{
|
||||
wl_data_device_send_leave (drag_grab->drag_focus_data_device);
|
||||
@@ -241,6 +253,40 @@ drag_grab_focus (MetaWaylandPointerGrab *grab,
|
||||
wl_resource_add_destroy_listener (data_device_resource, &drag_grab->drag_focus_listener);
|
||||
}
|
||||
|
||||
static void
|
||||
drag_grab_update_dnd_surface_position (MetaWaylandDragGrab *drag_grab)
|
||||
{
|
||||
MetaWaylandSeat *seat = drag_grab->seat;
|
||||
ClutterPoint pos;
|
||||
|
||||
clutter_input_device_get_coords (seat->pointer.device, NULL, &pos);
|
||||
meta_cursor_tracker_update_dnd_surface_position (seat->pointer.cursor_tracker,
|
||||
(int) pos.x, (int) pos.y);
|
||||
}
|
||||
|
||||
static void
|
||||
drag_grab_update_dnd_surface (MetaWaylandDragGrab *drag_grab)
|
||||
{
|
||||
MetaWaylandSurface *surface = drag_grab->drag_surface;
|
||||
MetaWaylandSeat *seat = drag_grab->seat;
|
||||
CoglTexture *texture = NULL;
|
||||
int offset_x, offset_y;
|
||||
|
||||
if (surface)
|
||||
{
|
||||
if (surface->buffer)
|
||||
texture = surface->buffer->texture;
|
||||
|
||||
offset_x = surface->offset_x;
|
||||
offset_y = surface->offset_y;
|
||||
}
|
||||
else
|
||||
offset_x = offset_y = 0;
|
||||
|
||||
meta_cursor_tracker_set_dnd_surface (seat->pointer.cursor_tracker,
|
||||
texture, offset_x, offset_y);
|
||||
}
|
||||
|
||||
static void
|
||||
drag_grab_motion (MetaWaylandPointerGrab *grab,
|
||||
const ClutterEvent *event)
|
||||
@@ -248,6 +294,8 @@ drag_grab_motion (MetaWaylandPointerGrab *grab,
|
||||
MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab;
|
||||
wl_fixed_t sx, sy;
|
||||
|
||||
drag_grab_update_dnd_surface_position (drag_grab);
|
||||
|
||||
if (drag_grab->drag_focus_data_device)
|
||||
{
|
||||
meta_wayland_pointer_get_relative_coordinates (grab->pointer,
|
||||
@@ -259,9 +307,38 @@ drag_grab_motion (MetaWaylandPointerGrab *grab,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
data_device_dnd_failed (MetaWaylandDragGrab *drag_grab)
|
||||
{
|
||||
MetaWaylandSurface *surface = drag_grab->drag_origin;
|
||||
MetaWaylandSeat *seat = drag_grab->seat;
|
||||
ClutterPoint dest;
|
||||
|
||||
if (drag_grab->drag_origin &&
|
||||
!meta_window_is_hidden (surface->window))
|
||||
{
|
||||
/* Find out the snap back position */
|
||||
clutter_actor_get_transformed_position (CLUTTER_ACTOR (meta_surface_actor_get_texture (surface->surface_actor)),
|
||||
&dest.x, &dest.y);
|
||||
dest.x += drag_grab->drag_start_x;
|
||||
dest.y += drag_grab->drag_start_y;
|
||||
}
|
||||
else
|
||||
clutter_input_device_get_coords (seat->pointer.device, NULL, &dest);
|
||||
|
||||
meta_cursor_tracker_dnd_failed (seat->pointer.cursor_tracker,
|
||||
dest.x, dest.y);
|
||||
}
|
||||
|
||||
static void
|
||||
data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab)
|
||||
{
|
||||
if (drag_grab->drag_origin)
|
||||
{
|
||||
drag_grab->drag_origin = NULL;
|
||||
wl_list_remove (&drag_grab->drag_origin_listener.link);
|
||||
}
|
||||
|
||||
if (drag_grab->drag_surface)
|
||||
{
|
||||
drag_grab->drag_surface = NULL;
|
||||
@@ -269,9 +346,15 @@ data_device_end_drag_grab (MetaWaylandDragGrab *drag_grab)
|
||||
}
|
||||
|
||||
if (drag_grab->drag_data_source)
|
||||
wl_list_remove (&drag_grab->drag_data_source_listener.link);
|
||||
{
|
||||
drag_grab->drag_data_source->has_target = FALSE;
|
||||
wl_list_remove (&drag_grab->drag_data_source_listener.link);
|
||||
}
|
||||
|
||||
drag_grab->seat->data_device.current_grab = NULL;
|
||||
|
||||
drag_grab_focus (&drag_grab->generic, NULL);
|
||||
drag_grab_update_dnd_surface (drag_grab);
|
||||
|
||||
meta_wayland_pointer_end_grab (drag_grab->generic.pointer);
|
||||
g_slice_free (MetaWaylandDragGrab, drag_grab);
|
||||
@@ -285,10 +368,15 @@ drag_grab_button (MetaWaylandPointerGrab *grab,
|
||||
MetaWaylandSeat *seat = drag_grab->seat;
|
||||
ClutterEventType event_type = clutter_event_type (event);
|
||||
|
||||
if (drag_grab->drag_focus_data_device &&
|
||||
drag_grab->generic.pointer->grab_button == clutter_event_get_button (event) &&
|
||||
if (drag_grab->generic.pointer->grab_button == clutter_event_get_button (event) &&
|
||||
event_type == CLUTTER_BUTTON_RELEASE)
|
||||
wl_data_device_send_drop (drag_grab->drag_focus_data_device);
|
||||
{
|
||||
if (drag_grab->drag_focus_data_device &&
|
||||
drag_grab->drag_data_source->has_target)
|
||||
wl_data_device_send_drop (drag_grab->drag_focus_data_device);
|
||||
else
|
||||
data_device_dnd_failed (drag_grab);
|
||||
}
|
||||
|
||||
if (seat->pointer.button_count == 0 &&
|
||||
event_type == CLUTTER_BUTTON_RELEASE)
|
||||
@@ -301,6 +389,16 @@ static const MetaWaylandPointerGrabInterface drag_grab_interface = {
|
||||
drag_grab_button,
|
||||
};
|
||||
|
||||
static void
|
||||
destroy_data_device_origin (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandDragGrab *drag_grab =
|
||||
wl_container_of (listener, drag_grab, drag_origin_listener);
|
||||
|
||||
drag_grab->drag_origin = NULL;
|
||||
data_device_end_drag_grab (drag_grab);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_data_device_source (struct wl_listener *listener, void *data)
|
||||
{
|
||||
@@ -318,6 +416,7 @@ destroy_data_device_icon (struct wl_listener *listener, void *data)
|
||||
wl_container_of (listener, drag_grab, drag_data_source_listener);
|
||||
|
||||
drag_grab->drag_surface = NULL;
|
||||
drag_grab_update_dnd_surface (drag_grab);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -329,20 +428,29 @@ data_device_start_drag (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandDataDevice *data_device = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
|
||||
MetaWaylandSurface *surface = NULL;
|
||||
MetaWaylandDragGrab *drag_grab;
|
||||
ClutterPoint pos;
|
||||
|
||||
if ((seat->pointer.button_count == 0 ||
|
||||
seat->pointer.grab_serial != serial ||
|
||||
!seat->pointer.focus_surface ||
|
||||
seat->pointer.focus_surface != wl_resource_get_user_data (origin_resource)))
|
||||
if (origin_resource)
|
||||
surface = wl_resource_get_user_data (origin_resource);
|
||||
|
||||
if (!surface)
|
||||
return;
|
||||
|
||||
if (seat->pointer.button_count == 0 ||
|
||||
seat->pointer.grab_serial != serial ||
|
||||
!seat->pointer.focus_surface ||
|
||||
seat->pointer.focus_surface != surface)
|
||||
return;
|
||||
|
||||
/* FIXME: Check that the data source type array isn't empty. */
|
||||
|
||||
if (seat->pointer.grab != &seat->pointer.default_grab)
|
||||
if (data_device->current_grab ||
|
||||
seat->pointer.grab != &seat->pointer.default_grab)
|
||||
return;
|
||||
|
||||
drag_grab = g_slice_new0 (MetaWaylandDragGrab);
|
||||
data_device->current_grab = drag_grab = g_slice_new0 (MetaWaylandDragGrab);
|
||||
|
||||
drag_grab->generic.interface = &drag_grab_interface;
|
||||
drag_grab->generic.pointer = &seat->pointer;
|
||||
@@ -350,6 +458,17 @@ data_device_start_drag (struct wl_client *client,
|
||||
drag_grab->drag_client = client;
|
||||
drag_grab->seat = seat;
|
||||
|
||||
drag_grab->drag_origin = surface;
|
||||
drag_grab->drag_origin_listener.notify = destroy_data_device_origin;
|
||||
wl_resource_add_destroy_listener (origin_resource,
|
||||
&drag_grab->drag_origin_listener);
|
||||
|
||||
clutter_input_device_get_coords (seat->pointer.device, NULL, &pos);
|
||||
clutter_actor_transform_stage_point (CLUTTER_ACTOR (meta_surface_actor_get_texture (surface->surface_actor)),
|
||||
pos.x, pos.y, &pos.x, &pos.y);
|
||||
drag_grab->drag_start_x = pos.x;
|
||||
drag_grab->drag_start_y = pos.y;
|
||||
|
||||
if (source_resource)
|
||||
{
|
||||
drag_grab->drag_data_source = wl_resource_get_user_data (source_resource);
|
||||
@@ -366,8 +485,10 @@ data_device_start_drag (struct wl_client *client,
|
||||
&drag_grab->drag_icon_listener);
|
||||
}
|
||||
|
||||
meta_wayland_pointer_set_focus (&seat->pointer, NULL);
|
||||
meta_wayland_pointer_set_focus (&seat->pointer, NULL, TRUE);
|
||||
meta_wayland_pointer_start_grab (&seat->pointer, (MetaWaylandPointerGrab*)drag_grab);
|
||||
drag_grab_update_dnd_surface_position (drag_grab);
|
||||
drag_grab_update_dnd_surface (drag_grab);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -551,3 +672,18 @@ meta_wayland_data_device_set_keyboard_focus (MetaWaylandDataDevice *data_device)
|
||||
wl_data_device_send_selection (data_device_resource, offer);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_data_device_is_dnd_surface (MetaWaylandDataDevice *data_device,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
return data_device->current_grab &&
|
||||
data_device->current_grab->drag_surface == surface;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_device_update_dnd_surface (MetaWaylandDataDevice *data_device)
|
||||
{
|
||||
if (data_device->current_grab)
|
||||
drag_grab_update_dnd_surface (data_device->current_grab);
|
||||
}
|
||||
|
@@ -27,12 +27,15 @@
|
||||
|
||||
#include "meta-wayland-types.h"
|
||||
|
||||
typedef struct _MetaWaylandDragGrab MetaWaylandDragGrab;
|
||||
|
||||
struct _MetaWaylandDataDevice
|
||||
{
|
||||
uint32_t selection_serial;
|
||||
MetaWaylandDataSource *selection_data_source;
|
||||
struct wl_listener selection_data_source_listener;
|
||||
struct wl_list resource_list;
|
||||
MetaWaylandDragGrab *current_grab;
|
||||
};
|
||||
|
||||
void meta_wayland_data_device_manager_init (MetaWaylandCompositor *compositor);
|
||||
@@ -41,4 +44,8 @@ void meta_wayland_data_device_init (MetaWaylandDataDevice *data_device);
|
||||
|
||||
void meta_wayland_data_device_set_keyboard_focus (MetaWaylandDataDevice *data_device);
|
||||
|
||||
gboolean meta_wayland_data_device_is_dnd_surface (MetaWaylandDataDevice *data_device,
|
||||
MetaWaylandSurface *surface);
|
||||
void meta_wayland_data_device_update_dnd_surface (MetaWaylandDataDevice *data_device);
|
||||
|
||||
#endif /* META_WAYLAND_DATA_DEVICE_H */
|
||||
|
@@ -273,14 +273,19 @@ notify_modifiers (MetaWaylandKeyboard *keyboard)
|
||||
state = keyboard->xkb_info.state;
|
||||
|
||||
l = &keyboard->focus_resource_list;
|
||||
wl_resource_for_each (resource, l)
|
||||
if (!wl_list_empty (l))
|
||||
{
|
||||
wl_keyboard_send_modifiers (resource,
|
||||
wl_display_next_serial (keyboard->display),
|
||||
xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED),
|
||||
xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED),
|
||||
xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED),
|
||||
xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE));
|
||||
uint32_t serial = wl_display_next_serial (keyboard->display);
|
||||
|
||||
wl_resource_for_each (resource, l)
|
||||
{
|
||||
wl_keyboard_send_modifiers (resource,
|
||||
serial,
|
||||
xkb_state_serialize_mods (state, XKB_STATE_MODS_DEPRESSED),
|
||||
xkb_state_serialize_mods (state, XKB_STATE_MODS_LATCHED),
|
||||
xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED),
|
||||
xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -95,7 +95,7 @@ pointer_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandPointer *pointer = wl_container_of (listener, pointer, focus_surface_listener);
|
||||
|
||||
meta_wayland_pointer_set_focus (pointer, NULL);
|
||||
meta_wayland_pointer_set_focus (pointer, NULL, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -107,7 +107,7 @@ default_grab_focus (MetaWaylandPointerGrab *grab,
|
||||
if (pointer->button_count > 0)
|
||||
return;
|
||||
|
||||
meta_wayland_pointer_set_focus (pointer, surface);
|
||||
meta_wayland_pointer_set_focus (pointer, surface, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -142,7 +142,7 @@ default_grab_button (MetaWaylandPointerGrab *grab,
|
||||
event_type = clutter_event_type (event);
|
||||
|
||||
l = &grab->pointer->focus_resource_list;
|
||||
wl_resource_for_each(resource, l)
|
||||
if (!wl_list_empty (l))
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (pointer->focus_surface->resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
@@ -168,13 +168,17 @@ default_grab_button (MetaWaylandPointerGrab *grab,
|
||||
}
|
||||
|
||||
serial = wl_display_next_serial (display);
|
||||
wl_pointer_send_button (resource, serial,
|
||||
clutter_event_get_time (event), button,
|
||||
event_type == CLUTTER_BUTTON_PRESS ? 1 : 0);
|
||||
|
||||
wl_resource_for_each(resource, l)
|
||||
{
|
||||
wl_pointer_send_button (resource, serial,
|
||||
clutter_event_get_time (event), button,
|
||||
event_type == CLUTTER_BUTTON_PRESS ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (pointer->button_count == 0 && event_type == CLUTTER_BUTTON_RELEASE)
|
||||
meta_wayland_pointer_set_focus (pointer, pointer->current);
|
||||
meta_wayland_pointer_set_focus (pointer, pointer->current, TRUE);
|
||||
}
|
||||
|
||||
static const MetaWaylandPointerGrabInterface default_pointer_grab_interface = {
|
||||
@@ -214,7 +218,7 @@ meta_wayland_pointer_init (MetaWaylandPointer *pointer,
|
||||
void
|
||||
meta_wayland_pointer_release (MetaWaylandPointer *pointer)
|
||||
{
|
||||
meta_wayland_pointer_set_focus (pointer, NULL);
|
||||
meta_wayland_pointer_set_focus (pointer, NULL, TRUE);
|
||||
set_cursor_surface (pointer, NULL);
|
||||
|
||||
pointer->display = NULL;
|
||||
@@ -476,7 +480,8 @@ broadcast_focus (MetaWaylandPointer *pointer,
|
||||
|
||||
void
|
||||
meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
|
||||
MetaWaylandSurface *surface)
|
||||
MetaWaylandSurface *surface,
|
||||
gboolean emit_crossing)
|
||||
{
|
||||
if (pointer->display == NULL)
|
||||
return;
|
||||
@@ -496,9 +501,12 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
uint32_t serial = wl_display_next_serial (display);
|
||||
|
||||
wl_resource_for_each (resource, l)
|
||||
if (emit_crossing)
|
||||
{
|
||||
wl_pointer_send_leave (resource, serial, pointer->focus_surface->resource);
|
||||
wl_resource_for_each (resource, l)
|
||||
{
|
||||
wl_pointer_send_leave (resource, serial, pointer->focus_surface->resource);
|
||||
}
|
||||
}
|
||||
|
||||
move_resources (&pointer->resource_list, &pointer->focus_resource_list);
|
||||
@@ -529,7 +537,7 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
|
||||
wl_resource_get_client (pointer->focus_surface->resource));
|
||||
|
||||
l = &pointer->focus_resource_list;
|
||||
if (!wl_list_empty (l))
|
||||
if (emit_crossing && !wl_list_empty (l))
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (pointer->focus_surface->resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
@@ -591,9 +599,9 @@ popup_grab_focus (MetaWaylandPointerGrab *grab,
|
||||
/* Popup grabs are in owner-events mode (ie, events for the same client
|
||||
are reported as normal) */
|
||||
if (surface && wl_resource_get_client (surface->resource) == popup_grab->grab_client)
|
||||
meta_wayland_pointer_set_focus (grab->pointer, surface);
|
||||
meta_wayland_pointer_set_focus (grab->pointer, surface, TRUE);
|
||||
else
|
||||
meta_wayland_pointer_set_focus (grab->pointer, NULL);
|
||||
meta_wayland_pointer_set_focus (grab->pointer, NULL, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -86,7 +86,8 @@ gboolean meta_wayland_pointer_handle_event (MetaWaylandPointer *pointer,
|
||||
const ClutterEvent *event);
|
||||
|
||||
void meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
|
||||
MetaWaylandSurface *surface);
|
||||
MetaWaylandSurface *surface,
|
||||
gboolean emit_crossing);
|
||||
|
||||
void meta_wayland_pointer_start_grab (MetaWaylandPointer *pointer,
|
||||
MetaWaylandPointerGrab *grab);
|
||||
|
@@ -175,6 +175,13 @@ cursor_surface_commit (MetaWaylandSurface *surface,
|
||||
meta_wayland_seat_update_cursor_surface (surface->compositor->seat);
|
||||
}
|
||||
|
||||
static void
|
||||
dnd_surface_commit (MetaWaylandSurface *surface,
|
||||
MetaWaylandPendingState *pending)
|
||||
{
|
||||
meta_wayland_data_device_update_dnd_surface (&surface->compositor->seat->data_device);
|
||||
}
|
||||
|
||||
static void
|
||||
calculate_surface_window_geometry (MetaWaylandSurface *surface,
|
||||
MetaRectangle *total_geometry,
|
||||
@@ -429,6 +436,9 @@ commit_pending_state (MetaWaylandSurface *surface,
|
||||
if (!cairo_region_is_empty (pending->damage))
|
||||
surface_process_damage (surface, pending->damage);
|
||||
|
||||
surface->offset_x += pending->dx;
|
||||
surface->offset_y += pending->dy;
|
||||
|
||||
if (pending->opaque_region)
|
||||
{
|
||||
pending->opaque_region = scale_region (pending->opaque_region, surface->scale);
|
||||
@@ -442,6 +452,8 @@ commit_pending_state (MetaWaylandSurface *surface,
|
||||
|
||||
if (surface == compositor->seat->pointer.cursor_surface)
|
||||
cursor_surface_commit (surface, pending);
|
||||
else if (meta_wayland_data_device_is_dnd_surface (&compositor->seat->data_device, surface))
|
||||
dnd_surface_commit (surface, pending);
|
||||
else if (surface->window)
|
||||
toplevel_surface_commit (surface, pending);
|
||||
else if (surface->subsurface.resource)
|
||||
@@ -1441,12 +1453,15 @@ bind_gtk_shell (struct wl_client *client,
|
||||
guint32 id)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
uint32_t capabilities = 0;
|
||||
|
||||
resource = wl_resource_create (client, >k_shell_interface, version, id);
|
||||
wl_resource_set_implementation (resource, &meta_wayland_gtk_shell_interface, data, NULL);
|
||||
|
||||
/* FIXME: ask the plugin */
|
||||
gtk_shell_send_capabilities (resource, GTK_SHELL_CAPABILITY_GLOBAL_APP_MENU);
|
||||
if (!meta_prefs_get_show_fallback_app_menu ())
|
||||
capabilities = GTK_SHELL_CAPABILITY_GLOBAL_APP_MENU;
|
||||
|
||||
gtk_shell_send_capabilities (resource, capabilities);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -115,6 +115,8 @@ struct _MetaWaylandSurface
|
||||
GSList *pending_placement_ops;
|
||||
} sub;
|
||||
|
||||
int32_t offset_x, offset_y;
|
||||
|
||||
gboolean has_set_geometry;
|
||||
|
||||
/* All the pending state that wl_surface.commit will apply. */
|
||||
|
@@ -188,21 +188,20 @@ meta_window_wayland_move_resize_internal (MetaWindow *window,
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If we get a 0x0 size, this means that we're trying to resize
|
||||
* a surface that doesn't have any buffer attached. This can happen
|
||||
* when a client requests an xdg surface before bringing it up.
|
||||
* The constrained_rect will be 1x1 because of how our constraints
|
||||
* code works, and sending that to the window would cause it to
|
||||
* redraw itself, so just don't send anything. Pretend like this
|
||||
* move_resize never happened.
|
||||
*/
|
||||
if (unconstrained_rect.width == 0 &&
|
||||
unconstrained_rect.height == 0)
|
||||
return;
|
||||
|
||||
if (constrained_rect.width != window->rect.width ||
|
||||
constrained_rect.height != window->rect.height)
|
||||
{
|
||||
/* If we get a 0x0 size, this means that we're trying to resize
|
||||
* a surface that doesn't have any buffer attached. This can happen
|
||||
* when a client requests an xdg surface before bringing it up.
|
||||
* The constrained_rect will be 1x1 because of how our constraints
|
||||
* code works, and sending that to the window would cause it to
|
||||
* redraw itself, so just don't send anything.
|
||||
*/
|
||||
if (unconstrained_rect.width == 0 &&
|
||||
unconstrained_rect.height == 0)
|
||||
return;
|
||||
|
||||
meta_wayland_surface_configure_notify (window->surface,
|
||||
constrained_rect.width,
|
||||
constrained_rect.height,
|
||||
|
@@ -338,6 +338,52 @@ reload_icon_geometry (MetaWindow *window,
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_border_equal (GtkBorder *a,
|
||||
GtkBorder *b)
|
||||
{
|
||||
return (a->left == b->left &&
|
||||
a->right == b->right &&
|
||||
a->top == b->top &&
|
||||
a->bottom == b->bottom);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_set_custom_frame_extents (MetaWindow *window,
|
||||
GtkBorder *extents,
|
||||
gboolean is_initial)
|
||||
{
|
||||
if (extents)
|
||||
{
|
||||
if (window->has_custom_frame_extents && gtk_border_equal (&window->custom_frame_extents, extents))
|
||||
return;
|
||||
|
||||
window->has_custom_frame_extents = TRUE;
|
||||
window->custom_frame_extents = *extents;
|
||||
|
||||
/* If we're setting the frame extents on map, then this is telling
|
||||
* us to adjust our understanding of the frame rect to match what
|
||||
* GTK+ thinks it is. Future changes to the frame extents should
|
||||
* trigger a resize and send a ConfigureRequest to the application.
|
||||
*/
|
||||
if (is_initial)
|
||||
{
|
||||
meta_window_client_rect_to_frame_rect (window, &window->rect, &window->rect);
|
||||
meta_window_client_rect_to_frame_rect (window, &window->unconstrained_rect, &window->unconstrained_rect);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!window->has_custom_frame_extents)
|
||||
return;
|
||||
|
||||
window->has_custom_frame_extents = FALSE;
|
||||
memset (&window->custom_frame_extents, 0, sizeof (window->custom_frame_extents));
|
||||
}
|
||||
|
||||
meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
|
||||
}
|
||||
|
||||
static void
|
||||
reload_gtk_frame_extents (MetaWindow *window,
|
||||
MetaPropValue *value,
|
||||
@@ -357,16 +403,13 @@ reload_gtk_frame_extents (MetaWindow *window,
|
||||
extents.right = (int)value->v.cardinal_list.cardinals[1];
|
||||
extents.top = (int)value->v.cardinal_list.cardinals[2];
|
||||
extents.bottom = (int)value->v.cardinal_list.cardinals[3];
|
||||
meta_window_set_custom_frame_extents (window, &extents);
|
||||
meta_window_set_custom_frame_extents (window, &extents, initial);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_window_set_custom_frame_extents (window, NULL);
|
||||
meta_window_set_custom_frame_extents (window, NULL, initial);
|
||||
}
|
||||
|
||||
if (!initial)
|
||||
meta_window_queue(window, META_QUEUE_MOVE_RESIZE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -214,8 +214,29 @@ send_configure_notify (MetaWindow *window)
|
||||
event.xconfigure.display = window->display->xdisplay;
|
||||
event.xconfigure.event = window->xwindow;
|
||||
event.xconfigure.window = window->xwindow;
|
||||
event.xconfigure.x = window->rect.x - priv->border_width;
|
||||
event.xconfigure.y = window->rect.y - priv->border_width;
|
||||
event.xconfigure.x = priv->client_rect.x - priv->border_width;
|
||||
event.xconfigure.y = priv->client_rect.y - priv->border_width;
|
||||
if (window->frame)
|
||||
{
|
||||
if (window->withdrawn)
|
||||
{
|
||||
MetaFrameBorders borders;
|
||||
/* We reparent the client window and put it to the position
|
||||
* where the visible top-left of the frame window currently is.
|
||||
*/
|
||||
|
||||
meta_frame_calc_borders (window->frame, &borders);
|
||||
|
||||
event.xconfigure.x = window->frame->rect.x + borders.invisible.left;
|
||||
event.xconfigure.y = window->frame->rect.y + borders.invisible.top;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Need to be in root window coordinates */
|
||||
event.xconfigure.x += window->frame->rect.x;
|
||||
event.xconfigure.y += window->frame->rect.y;
|
||||
}
|
||||
}
|
||||
event.xconfigure.width = priv->client_rect.width;
|
||||
event.xconfigure.height = priv->client_rect.height;
|
||||
event.xconfigure.border_width = priv->border_width; /* requested not actual */
|
||||
@@ -249,6 +270,17 @@ adjust_for_gravity (MetaWindow *window,
|
||||
int frame_width, frame_height;
|
||||
MetaFrameBorders borders;
|
||||
|
||||
/* We're computing position to pass to window_move, which is
|
||||
* the position of the client window (StaticGravity basically)
|
||||
*
|
||||
* (see WM spec description of gravity computation, but note that
|
||||
* their formulas assume we're honoring the border width, rather
|
||||
* than compensating for having turned it off)
|
||||
*/
|
||||
|
||||
if (gravity == StaticGravity)
|
||||
return;
|
||||
|
||||
if (coords_assume_border)
|
||||
bw = priv->border_width;
|
||||
else
|
||||
@@ -261,14 +293,6 @@ adjust_for_gravity (MetaWindow *window,
|
||||
frame_width = child_x + rect->width + borders.visible.right;
|
||||
frame_height = child_y + rect->height + borders.visible.bottom;
|
||||
|
||||
/* We're computing position to pass to window_move, which is
|
||||
* the position of the client window (StaticGravity basically)
|
||||
*
|
||||
* (see WM spec description of gravity computation, but note that
|
||||
* their formulas assume we're honoring the border width, rather
|
||||
* than compensating for having turned it off)
|
||||
*/
|
||||
|
||||
/* Calculate the the reference point, which is the corner of the
|
||||
* outer window specified by the gravity. So, NorthEastGravity
|
||||
* would have the reference point as the top-right corner of the
|
||||
|
Reference in New Issue
Block a user