Compare commits
41 Commits
dcvviewer
...
wip/nields
Author | SHA1 | Date | |
---|---|---|---|
eb2405f0f4 | |||
a2c545c321 | |||
3cd8f3b7dc | |||
033ce2d956 | |||
2b47e89405 | |||
80d11287eb | |||
f869e4d54b | |||
c1059df7f9 | |||
e3d3df985f | |||
86ff3dfb3c | |||
7e0d185120 | |||
61c173b777 | |||
f99cd18254 | |||
0405786573 | |||
b016ff29f6 | |||
3f2e86f67c | |||
0aa4a526c6 | |||
85c2aef4bc | |||
76664ef891 | |||
b1ea768949 | |||
ea9d8a895b | |||
38432da328 | |||
430f354cd9 | |||
1cf4279745 | |||
7713006f5b | |||
465e13128b | |||
86de79cfc5 | |||
1d77641f0b | |||
2f217109aa | |||
5e0523cc8b | |||
dbe6e01e12 | |||
103c469cc9 | |||
ef074ea510 | |||
39bac6eabd | |||
0200f4fcd9 | |||
439afb3f19 | |||
b01edc22f3 | |||
e8bca5052a | |||
468882ecec | |||
be3c89d823 | |||
7719e33e68 |
@ -35,15 +35,17 @@ test-mutter:
|
||||
variables:
|
||||
XDG_RUNTIME_DIR: "$CI_PROJECT_DIR/runtime-dir"
|
||||
GSETTINGS_SCHEMA_DIR: "$CI_PROJECT_DIR/build/data"
|
||||
G_SLICE: "always-malloc"
|
||||
MALLOC_CHECK_: "3"
|
||||
NO_AT_BRIDGE: "1"
|
||||
MALLOC_PERTURB_: "123"
|
||||
script:
|
||||
- dconf update
|
||||
- mkdir -m 700 $XDG_RUNTIME_DIR
|
||||
- glib-compile-schemas $GSETTINGS_SCHEMA_DIR
|
||||
- >
|
||||
env MALLOC_PERTURB_="$((RANDOM % 256 + 1))"
|
||||
dbus-run-session -- xvfb-run -s '+iglx -noreset'
|
||||
meson test -C build --no-rebuild -t 10 --verbose --no-stdsplit --wrap catchsegv
|
||||
meson test -C build --no-rebuild -t 10 --verbose --no-stdsplit --print-errorlogs --wrap catchsegv
|
||||
only:
|
||||
- merge_requests
|
||||
- /^.*$/
|
||||
|
15
NEWS
15
NEWS
@ -1,3 +1,18 @@
|
||||
3.33.2
|
||||
======
|
||||
* Fix rendering lag on Xorg [Daniel; !520, !281]
|
||||
* Misc. bug fixes and cleanups [Carlos, Marco, Jonas D., Florian, Niels,
|
||||
Daniel, Benjamin, Jonas Å., Ignacio, Vasilis; #598, !576, !547, !578,
|
||||
!583, !582, !469, !524, !119, !571, !584, !585, !586, #425]
|
||||
|
||||
Contributors:
|
||||
Jonas Ådahl, Benjamin Berg, Jonas Dreßler, Carlos Garnacho, Niels De Graef,
|
||||
Vasilis Liaskovitis, Florian Müllner, Ignacio Casal Quinteiro,
|
||||
Marco Trevisan (Treviño), Daniel van Vugt
|
||||
|
||||
Translators:
|
||||
Daniel Mustieles [es]
|
||||
|
||||
3.33.1
|
||||
======
|
||||
* Remove unused APIs and outdated driver support
|
||||
|
@ -1975,6 +1975,7 @@ selection_paint (ClutterText *self,
|
||||
else
|
||||
{
|
||||
/* Paint selection background first */
|
||||
CoglPipeline *color_pipeline = cogl_pipeline_copy (default_color_pipeline);
|
||||
PangoLayout *layout = clutter_text_get_layout (self);
|
||||
CoglPath *selection_path = cogl_path_new ();
|
||||
CoglColor cogl_color = { 0, };
|
||||
@ -1987,11 +1988,19 @@ selection_paint (ClutterText *self,
|
||||
else
|
||||
color = &priv->text_color;
|
||||
|
||||
cogl_color_init_from_4ub (&cogl_color,
|
||||
color->red,
|
||||
color->green,
|
||||
color->blue,
|
||||
paint_opacity * color->alpha / 255);
|
||||
cogl_color_premultiply (&cogl_color);
|
||||
cogl_pipeline_set_color (color_pipeline, &cogl_color);
|
||||
|
||||
clutter_text_foreach_selection_rectangle_prescaled (self,
|
||||
add_selection_rectangle_to_path,
|
||||
selection_path);
|
||||
|
||||
cogl_path_fill (selection_path);
|
||||
cogl_framebuffer_fill_path (fb, color_pipeline, selection_path);
|
||||
|
||||
/* Paint selected text */
|
||||
cogl_framebuffer_push_path_clip (fb, selection_path);
|
||||
|
@ -114,11 +114,12 @@ test_destroy_destroy (ClutterActor *self)
|
||||
test->tex = NULL;
|
||||
}
|
||||
|
||||
g_list_free_full (test->children, (GDestroyNotify) clutter_actor_destroy);
|
||||
test->children = NULL;
|
||||
g_assert_nonnull (test->children);
|
||||
|
||||
if (CLUTTER_ACTOR_CLASS (test_destroy_parent_class)->destroy)
|
||||
CLUTTER_ACTOR_CLASS (test_destroy_parent_class)->destroy (self);
|
||||
|
||||
g_assert_null (test->children);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -460,9 +460,7 @@ cogl_path_fill (CoglPath *path);
|
||||
* use while filling a path.</note>
|
||||
*
|
||||
* Stability: unstable
|
||||
* Deprecated: 1.16: Use cogl_path_fill() instead
|
||||
*/
|
||||
COGL_DEPRECATED_FOR (cogl_path_fill)
|
||||
void
|
||||
cogl_framebuffer_fill_path (CoglFramebuffer *framebuffer,
|
||||
CoglPipeline *pipeline,
|
||||
@ -492,9 +490,7 @@ cogl_path_stroke (CoglPath *path);
|
||||
* regardless of the current transformation matrix.
|
||||
*
|
||||
* Stability: unstable
|
||||
* Deprecated: 1.16: Use cogl_path_stroke() instead
|
||||
*/
|
||||
COGL_DEPRECATED_FOR (cogl_path_stroke)
|
||||
void
|
||||
cogl_framebuffer_stroke_path (CoglFramebuffer *framebuffer,
|
||||
CoglPipeline *pipeline,
|
||||
@ -529,9 +525,7 @@ cogl_framebuffer_push_path_clip (CoglFramebuffer *framebuffer,
|
||||
*
|
||||
* Since: 1.8
|
||||
* Stability: Unstable
|
||||
* Deprecated: 1.16: Use cogl_framebuffer_push_path_clip() instead
|
||||
*/
|
||||
COGL_DEPRECATED_FOR (cogl_framebuffer_push_path_clip)
|
||||
void
|
||||
cogl_clip_push_from_path (CoglPath *path);
|
||||
|
||||
|
@ -1504,7 +1504,6 @@ cogl_framebuffer_push_path_clip (CoglFramebuffer *framebuffer,
|
||||
COGL_FRAMEBUFFER_STATE_CLIP;
|
||||
}
|
||||
|
||||
/* XXX: deprecated */
|
||||
void
|
||||
cogl_clip_push_from_path (CoglPath *path)
|
||||
{
|
||||
@ -1575,7 +1574,6 @@ _cogl_path_build_stroke_attribute_buffer (CoglPath *path)
|
||||
data->stroke_n_attributes = n_attributes;
|
||||
}
|
||||
|
||||
/* XXX: deprecated */
|
||||
void
|
||||
cogl_framebuffer_fill_path (CoglFramebuffer *framebuffer,
|
||||
CoglPipeline *pipeline,
|
||||
@ -1588,7 +1586,6 @@ cogl_framebuffer_fill_path (CoglFramebuffer *framebuffer,
|
||||
_cogl_path_fill_nodes (path, framebuffer, pipeline, 0 /* flags */);
|
||||
}
|
||||
|
||||
/* XXX: deprecated */
|
||||
void
|
||||
cogl_framebuffer_stroke_path (CoglFramebuffer *framebuffer,
|
||||
CoglPipeline *pipeline,
|
||||
|
@ -452,9 +452,6 @@ _cogl_pipeline_free (CoglPipeline *pipeline)
|
||||
_cogl_bitmask_destroy (&uniforms_state->changed_mask);
|
||||
}
|
||||
|
||||
if (pipeline->differences & COGL_PIPELINE_STATE_NEEDS_BIG_STATE)
|
||||
g_slice_free (CoglPipelineBigState, pipeline->big_state);
|
||||
|
||||
if (pipeline->differences & COGL_PIPELINE_STATE_LAYERS)
|
||||
g_list_free_full (pipeline->layer_differences, cogl_object_unref);
|
||||
|
||||
@ -464,6 +461,9 @@ _cogl_pipeline_free (CoglPipeline *pipeline)
|
||||
if (pipeline->differences & COGL_PIPELINE_STATE_FRAGMENT_SNIPPETS)
|
||||
_cogl_pipeline_snippet_list_free (&pipeline->big_state->fragment_snippets);
|
||||
|
||||
if (pipeline->differences & COGL_PIPELINE_STATE_NEEDS_BIG_STATE)
|
||||
g_slice_free (CoglPipelineBigState, pipeline->big_state);
|
||||
|
||||
g_list_free (pipeline->deprecated_get_layers_list);
|
||||
|
||||
recursively_free_layer_caches (pipeline);
|
||||
|
@ -29,6 +29,7 @@
|
||||
*/
|
||||
|
||||
#include "cogl-config.h"
|
||||
#include "cogl-defines.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
@ -308,3 +309,66 @@ cogl_pixel_format_to_string (CoglPixelFormat format)
|
||||
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
#ifdef COGL_HAS_LIBDRM
|
||||
|
||||
typedef struct _PixelFormatMap {
|
||||
uint32_t drm_format;
|
||||
CoglPixelFormat cogl_format;
|
||||
CoglTextureComponents cogl_components;
|
||||
} PixelFormatMap;
|
||||
|
||||
static const PixelFormatMap pixel_format_map[] = {
|
||||
/* DRM formats are defined as little-endian, not machine endian. */
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
{ DRM_FORMAT_RGB565, COGL_PIXEL_FORMAT_RGB_565, COGL_TEXTURE_COMPONENTS_RGB },
|
||||
{ DRM_FORMAT_ABGR8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
|
||||
{ DRM_FORMAT_XBGR8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
|
||||
{ DRM_FORMAT_ARGB8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
|
||||
{ DRM_FORMAT_XRGB8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
|
||||
{ DRM_FORMAT_BGRA8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
|
||||
{ DRM_FORMAT_BGRX8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
|
||||
{ DRM_FORMAT_RGBA8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
|
||||
{ DRM_FORMAT_RGBX8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
|
||||
#elif G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
/* DRM_FORMAT_RGB565 cannot be expressed. */
|
||||
{ DRM_FORMAT_ABGR8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
|
||||
{ DRM_FORMAT_XBGR8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
|
||||
{ DRM_FORMAT_ARGB8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
|
||||
{ DRM_FORMAT_XRGB8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
|
||||
{ DRM_FORMAT_BGRA8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
|
||||
{ DRM_FORMAT_BGRX8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
|
||||
{ DRM_FORMAT_RGBA8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
|
||||
{ DRM_FORMAT_RGBX8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
|
||||
#else
|
||||
#error "unexpected G_BYTE_ORDER"
|
||||
#endif
|
||||
};
|
||||
|
||||
gboolean
|
||||
cogl_pixel_format_from_drm_format (uint32_t drm_format,
|
||||
CoglPixelFormat *out_format,
|
||||
CoglTextureComponents *out_components)
|
||||
{
|
||||
const size_t n = G_N_ELEMENTS (pixel_format_map);
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
if (pixel_format_map[i].drm_format == drm_format)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == n)
|
||||
return FALSE;
|
||||
|
||||
if (out_format)
|
||||
*out_format = pixel_format_map[i].cogl_format;
|
||||
|
||||
if (out_components)
|
||||
*out_components = pixel_format_map[i].cogl_components;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -38,6 +38,10 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef COGL_HAS_LIBDRM
|
||||
#include <drm_fourcc.h>
|
||||
#endif
|
||||
|
||||
#include <cogl/cogl-defines.h>
|
||||
|
||||
#include <glib.h>
|
||||
@ -58,6 +62,9 @@ G_BEGIN_DECLS
|
||||
*
|
||||
* Other examples of factors that can influence the layout in memory are the
|
||||
* system's endianness.
|
||||
*
|
||||
* This file also contains methods to map Linux DRM 4CC codes to
|
||||
* CoglPixelFormats.
|
||||
*/
|
||||
|
||||
#define COGL_A_BIT (1 << 4)
|
||||
@ -295,6 +302,34 @@ _cogl_pixel_format_is_endian_dependant (CoglPixelFormat format);
|
||||
const char *
|
||||
cogl_pixel_format_to_string (CoglPixelFormat format);
|
||||
|
||||
#ifdef COGL_HAS_LIBDRM
|
||||
|
||||
/* added in libdrm 2.4.95 */
|
||||
#ifndef DRM_FORMAT_INVALID
|
||||
#define DRM_FORMAT_INVALID 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* cogl_pixel_format_from_drm_format:
|
||||
* @drm_format: The DRM 4CC code (as specified in drm_fourcc.h)
|
||||
* @out_format: (optional): The corresponding #CoglPixelFormat (if successful)
|
||||
* @out_components: (optional): The corresponding #CoglTextureComponents (if
|
||||
* sucessful)
|
||||
*
|
||||
* Does an internal lookup to find a #CoglPixelFormat that matches the given
|
||||
* DRM 4CC code. If no such format could be found, this function will return
|
||||
* %FALSE and the output parameters will stay untouched.
|
||||
*
|
||||
* Returns: %TRUE if a #CoglPixelFormat corresponding to the 4CC code exists,
|
||||
* %FALSE otherwise.
|
||||
*/
|
||||
gboolean
|
||||
cogl_pixel_format_from_drm_format (uint32_t drm_format,
|
||||
CoglPixelFormat *out_format,
|
||||
CoglTextureComponents *out_components);
|
||||
|
||||
#endif
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __COGL_PIXEL_FORMAT_H__ */
|
||||
|
@ -54,41 +54,27 @@ static char *_cogl_x11_display_name = NULL;
|
||||
static GList *_cogl_xlib_renderers = NULL;
|
||||
|
||||
static void
|
||||
destroy_xlib_renderer_data (void *user_data)
|
||||
_xlib_renderer_data_free (CoglXlibRenderer *data)
|
||||
{
|
||||
CoglXlibRenderer *data = user_data;
|
||||
|
||||
if (data->xvisinfo)
|
||||
XFree (data->xvisinfo);
|
||||
|
||||
g_slice_free (CoglXlibRenderer, user_data);
|
||||
g_slice_free (CoglXlibRenderer, data);
|
||||
}
|
||||
|
||||
CoglXlibRenderer *
|
||||
_cogl_xlib_renderer_get_data (CoglRenderer *renderer)
|
||||
{
|
||||
static CoglUserDataKey key;
|
||||
CoglXlibRenderer *data;
|
||||
|
||||
/* Constructs a CoglXlibRenderer struct on demand and attaches it to
|
||||
the object using user data. It's done this way instead of using a
|
||||
subclassing hierarchy in the winsys data because all EGL winsys's
|
||||
need the EGL winsys data but only one of them wants the Xlib
|
||||
data. */
|
||||
|
||||
data = cogl_object_get_user_data (COGL_OBJECT (renderer), &key);
|
||||
if (!renderer->custom_winsys_user_data)
|
||||
renderer->custom_winsys_user_data = g_slice_new0 (CoglXlibRenderer);
|
||||
|
||||
if (data == NULL)
|
||||
{
|
||||
data = g_slice_new0 (CoglXlibRenderer);
|
||||
|
||||
cogl_object_set_user_data (COGL_OBJECT (renderer),
|
||||
&key,
|
||||
data,
|
||||
destroy_xlib_renderer_data);
|
||||
}
|
||||
|
||||
return data;
|
||||
return renderer->custom_winsys_user_data;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -570,6 +556,8 @@ _cogl_xlib_renderer_disconnect (CoglRenderer *renderer)
|
||||
if (!renderer->foreign_xdpy && xlib_renderer->xdpy)
|
||||
XCloseDisplay (xlib_renderer->xdpy);
|
||||
|
||||
g_clear_pointer (&renderer->custom_winsys_user_data, _xlib_renderer_data_free);
|
||||
|
||||
unregister_xlib_renderer (renderer);
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,9 @@ cdata.set('COGL_HAS_X11', have_x11)
|
||||
cdata.set('COGL_HAS_X11_SUPPORT', have_x11)
|
||||
cdata.set('COGL_HAS_XLIB', have_x11)
|
||||
cdata.set('COGL_HAS_XLIB_SUPPORT', have_x11)
|
||||
if have_native_backend
|
||||
cdata.set('COGL_HAS_LIBDRM', libdrm_dep.found())
|
||||
endif
|
||||
|
||||
cogl_defines_h = configure_file(
|
||||
input: 'cogl-defines.h.meson',
|
||||
|
@ -1,5 +1,5 @@
|
||||
project('mutter', 'c',
|
||||
version: '3.33.1',
|
||||
version: '3.33.2',
|
||||
meson_version: '>= 0.50.0',
|
||||
license: 'GPLv2+'
|
||||
)
|
||||
|
@ -353,7 +353,7 @@ find_builtin_output (MetaInputMapper *mapper,
|
||||
return panel != NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
static void
|
||||
guess_candidates (MetaInputMapper *mapper,
|
||||
MetaMapperInputInfo *input,
|
||||
DeviceCandidates *info)
|
||||
@ -387,15 +387,7 @@ guess_candidates (MetaInputMapper *mapper,
|
||||
find_builtin_output (mapper, &info->candidates[META_MATCH_IS_BUILTIN]);
|
||||
}
|
||||
|
||||
if (best < N_OUTPUT_MATCHES)
|
||||
{
|
||||
info->best = best;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
info->best = best;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -408,8 +400,7 @@ mapping_helper_add (MappingHelper *helper,
|
||||
|
||||
info.input = input;
|
||||
|
||||
if (!guess_candidates (mapper, input, &info))
|
||||
return;
|
||||
guess_candidates (mapper, input, &info);
|
||||
|
||||
for (i = 0; i < helper->device_maps->len; i++)
|
||||
{
|
||||
|
@ -823,6 +823,7 @@ static void
|
||||
cursor_priv_free (MetaCursorNativePrivate *cursor_priv)
|
||||
{
|
||||
g_hash_table_destroy (cursor_priv->gpu_states);
|
||||
g_free (cursor_priv);
|
||||
}
|
||||
|
||||
static MetaCursorNativePrivate *
|
||||
|
@ -73,11 +73,6 @@
|
||||
#define EGL_DRM_MASTER_FD_EXT 0x333C
|
||||
#endif
|
||||
|
||||
/* added in libdrm 2.4.95 */
|
||||
#ifndef DRM_FORMAT_INVALID
|
||||
#define DRM_FORMAT_INVALID 0
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
@ -252,11 +247,6 @@ static void
|
||||
free_next_secondary_bo (MetaGpuKms *gpu_kms,
|
||||
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state);
|
||||
|
||||
static gboolean
|
||||
cogl_pixel_format_from_drm_format (uint32_t drm_format,
|
||||
CoglPixelFormat *out_format,
|
||||
CoglTextureComponents *out_components);
|
||||
|
||||
static MetaBackend *
|
||||
backend_from_renderer_native (MetaRendererNative *renderer_native)
|
||||
{
|
||||
@ -2126,65 +2116,6 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct _PixelFormatMap {
|
||||
uint32_t drm_format;
|
||||
CoglPixelFormat cogl_format;
|
||||
CoglTextureComponents cogl_components;
|
||||
} PixelFormatMap;
|
||||
|
||||
static const PixelFormatMap pixel_format_map[] = {
|
||||
/* DRM formats are defined as little-endian, not machine endian. */
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
{ DRM_FORMAT_RGB565, COGL_PIXEL_FORMAT_RGB_565, COGL_TEXTURE_COMPONENTS_RGB },
|
||||
{ DRM_FORMAT_ABGR8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
|
||||
{ DRM_FORMAT_XBGR8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
|
||||
{ DRM_FORMAT_ARGB8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
|
||||
{ DRM_FORMAT_XRGB8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
|
||||
{ DRM_FORMAT_BGRA8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
|
||||
{ DRM_FORMAT_BGRX8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
|
||||
{ DRM_FORMAT_RGBA8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
|
||||
{ DRM_FORMAT_RGBX8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
|
||||
#elif G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
/* DRM_FORMAT_RGB565 cannot be expressed. */
|
||||
{ DRM_FORMAT_ABGR8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
|
||||
{ DRM_FORMAT_XBGR8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
|
||||
{ DRM_FORMAT_ARGB8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
|
||||
{ DRM_FORMAT_XRGB8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
|
||||
{ DRM_FORMAT_BGRA8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
|
||||
{ DRM_FORMAT_BGRX8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
|
||||
{ DRM_FORMAT_RGBA8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
|
||||
{ DRM_FORMAT_RGBX8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
|
||||
#else
|
||||
#error "unexpected G_BYTE_ORDER"
|
||||
#endif
|
||||
};
|
||||
|
||||
static gboolean
|
||||
cogl_pixel_format_from_drm_format (uint32_t drm_format,
|
||||
CoglPixelFormat *out_format,
|
||||
CoglTextureComponents *out_components)
|
||||
{
|
||||
const size_t n = G_N_ELEMENTS (pixel_format_map);
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
if (pixel_format_map[i].drm_format == drm_format)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == n)
|
||||
return FALSE;
|
||||
|
||||
if (out_format)
|
||||
*out_format = pixel_format_map[i].cogl_format;
|
||||
|
||||
if (out_components)
|
||||
*out_components = pixel_format_map[i].cogl_components;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
copy_shared_framebuffer_cpu (CoglOnscreen *onscreen,
|
||||
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state,
|
||||
|
@ -357,7 +357,6 @@ handle_host_xevent (MetaBackend *backend,
|
||||
{
|
||||
switch (xkb_ev->any.xkb_type)
|
||||
{
|
||||
case XkbNewKeyboardNotify:
|
||||
case XkbMapNotify:
|
||||
keymap_changed (backend);
|
||||
break;
|
||||
|
@ -203,7 +203,7 @@ meta_renderer_x11_nested_create_view (MetaRenderer *renderer,
|
||||
height = logical_monitor->rect.height;
|
||||
}
|
||||
width = roundf (width * view_scale);
|
||||
height = roundf (width * view_scale);
|
||||
height = roundf (height * view_scale);
|
||||
|
||||
fake_onscreen = create_offscreen (cogl_context, width, height);
|
||||
|
||||
|
@ -692,11 +692,8 @@ meta_compositor_add_window (MetaCompositor *compositor,
|
||||
{
|
||||
MetaWindowActor *window_actor;
|
||||
ClutterActor *window_group;
|
||||
MetaDisplay *display = compositor->display;
|
||||
GType window_actor_type = G_TYPE_INVALID;
|
||||
|
||||
meta_x11_error_trap_push (display->x11_display);
|
||||
|
||||
switch (window->client_type)
|
||||
{
|
||||
case META_WINDOW_CLIENT_TYPE_X11:
|
||||
@ -724,8 +721,6 @@ meta_compositor_add_window (MetaCompositor *compositor,
|
||||
*/
|
||||
compositor->windows = g_list_append (compositor->windows, window_actor);
|
||||
sync_actor_stacking (compositor);
|
||||
|
||||
meta_x11_error_trap_pop (display->x11_display);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -55,17 +55,8 @@ meta_rectangle_free (MetaRectangle *rect)
|
||||
g_free (rect);
|
||||
}
|
||||
|
||||
GType
|
||||
meta_rectangle_get_type (void)
|
||||
{
|
||||
static GType type_id = 0;
|
||||
|
||||
if (!type_id)
|
||||
type_id = g_boxed_type_register_static (g_intern_static_string ("MetaRectangle"),
|
||||
(GBoxedCopyFunc) meta_rectangle_copy,
|
||||
(GBoxedFreeFunc) meta_rectangle_free);
|
||||
return type_id;
|
||||
}
|
||||
G_DEFINE_BOXED_TYPE (MetaRectangle, meta_rectangle,
|
||||
meta_rectangle_copy, meta_rectangle_free);
|
||||
|
||||
char*
|
||||
meta_rectangle_to_string (const MetaRectangle *rect,
|
||||
|
@ -140,14 +140,6 @@ struct _MetaDisplay
|
||||
*/
|
||||
guint allow_terminal_deactivation : 1;
|
||||
|
||||
/* If true, server->focus_serial refers to us changing the focus; in
|
||||
* this case, we can ignore focus events that have exactly focus_serial,
|
||||
* since we take care to make another request immediately afterwards.
|
||||
* But if focus is being changed by another client, we have to accept
|
||||
* multiple events with the same serial.
|
||||
*/
|
||||
guint focused_by_us : 1;
|
||||
|
||||
/*< private-ish >*/
|
||||
GHashTable *stamps;
|
||||
GHashTable *wayland_windows;
|
||||
@ -203,10 +195,6 @@ struct _MetaDisplay
|
||||
MetaEdgeResistanceData *grab_edge_resistance_data;
|
||||
unsigned int grab_last_user_action_was_snap;
|
||||
|
||||
/* we use property updates as sentinels for certain window focus events
|
||||
* to avoid some race conditions on EnterNotify events
|
||||
*/
|
||||
int sentinel_counter;
|
||||
int grab_resize_timeout_id;
|
||||
|
||||
MetaKeyBindingManager key_binding_manager;
|
||||
@ -363,10 +351,6 @@ gboolean meta_grab_op_is_resizing (MetaGrabOp op);
|
||||
gboolean meta_grab_op_is_mouse (MetaGrabOp op);
|
||||
gboolean meta_grab_op_is_keyboard (MetaGrabOp op);
|
||||
|
||||
void meta_display_increment_focus_sentinel (MetaDisplay *display);
|
||||
void meta_display_decrement_focus_sentinel (MetaDisplay *display);
|
||||
gboolean meta_display_focus_sentinel_clear (MetaDisplay *display);
|
||||
|
||||
void meta_display_queue_autoraise_callback (MetaDisplay *display,
|
||||
MetaWindow *window);
|
||||
void meta_display_remove_autoraise_callback (MetaDisplay *display);
|
||||
@ -379,10 +363,7 @@ gboolean meta_display_modifiers_accelerator_activate (MetaDisplay *display);
|
||||
|
||||
void meta_display_sync_wayland_input_focus (MetaDisplay *display);
|
||||
void meta_display_update_focus_window (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
Window xwindow,
|
||||
gulong serial,
|
||||
gboolean focused_by_us);
|
||||
MetaWindow *window);
|
||||
|
||||
void meta_display_sanity_check_timestamps (MetaDisplay *display,
|
||||
guint32 timestamp);
|
||||
@ -446,4 +427,8 @@ MetaWindow *meta_display_get_window_from_id (MetaDisplay *display,
|
||||
uint64_t window_id);
|
||||
uint64_t meta_display_generate_window_id (MetaDisplay *display);
|
||||
|
||||
gboolean meta_display_init_x11 (MetaDisplay *display,
|
||||
GError **error);
|
||||
void meta_display_shutdown_x11 (MetaDisplay *display);
|
||||
|
||||
#endif
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include "backends/meta-logical-monitor.h"
|
||||
#include "backends/meta-stage-private.h"
|
||||
#include "backends/x11/meta-backend-x11.h"
|
||||
#include "backends/x11/cm/meta-backend-x11-cm.h"
|
||||
#include "clutter/x11/clutter-x11.h"
|
||||
#include "core/bell.h"
|
||||
#include "core/boxes-private.h"
|
||||
@ -630,6 +631,39 @@ on_ui_scaling_factor_changed (MetaSettings *settings,
|
||||
meta_display_reload_cursor (display);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_display_init_x11 (MetaDisplay *display,
|
||||
GError **error)
|
||||
{
|
||||
MetaX11Display *x11_display;
|
||||
|
||||
g_assert (display->x11_display == NULL);
|
||||
|
||||
x11_display = meta_x11_display_new (display, error);
|
||||
if (!x11_display)
|
||||
return FALSE;
|
||||
|
||||
display->x11_display = x11_display;
|
||||
g_signal_emit (display, display_signals[X11_DISPLAY_OPENED], 0);
|
||||
meta_x11_display_create_guard_window (x11_display);
|
||||
|
||||
if (!display->display_opening)
|
||||
meta_display_manage_all_windows (display);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_display_shutdown_x11 (MetaDisplay *display)
|
||||
{
|
||||
if (!display->x11_display)
|
||||
return;
|
||||
|
||||
g_signal_emit (display, display_signals[X11_DISPLAY_CLOSING], 0);
|
||||
g_object_run_dispose (G_OBJECT (display->x11_display));
|
||||
g_clear_object (&display->x11_display);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_display_open:
|
||||
*
|
||||
@ -645,7 +679,6 @@ meta_display_open (void)
|
||||
{
|
||||
GError *error = NULL;
|
||||
MetaDisplay *display;
|
||||
MetaX11Display *x11_display;
|
||||
int i;
|
||||
guint32 timestamp;
|
||||
Window old_active_xwindow = None;
|
||||
@ -683,7 +716,6 @@ meta_display_open (void)
|
||||
}
|
||||
|
||||
display->current_time = META_CURRENT_TIME;
|
||||
display->sentinel_counter = 0;
|
||||
|
||||
display->grab_resize_timeout_id = 0;
|
||||
display->grab_have_keyboard = FALSE;
|
||||
@ -693,7 +725,7 @@ meta_display_open (void)
|
||||
display->grab_tile_mode = META_TILE_NONE;
|
||||
display->grab_tile_monitor_number = -1;
|
||||
|
||||
display->grab_edge_resistance_data = NULL;
|
||||
meta_display_cleanup_edges (display);
|
||||
|
||||
meta_display_init_keys (display);
|
||||
|
||||
@ -730,10 +762,8 @@ meta_display_open (void)
|
||||
|
||||
if (meta_should_autostart_x11_display ())
|
||||
{
|
||||
x11_display = meta_x11_display_new (display, &error);
|
||||
g_assert (x11_display != NULL); /* Required, for now */
|
||||
display->x11_display = x11_display;
|
||||
g_signal_emit (display, display_signals[X11_DISPLAY_OPENED], 0);
|
||||
if (!meta_display_init_x11 (display, &error))
|
||||
g_error ("Failed to start Xwayland: %s", error->message);
|
||||
|
||||
timestamp = display->x11_display->timestamp;
|
||||
}
|
||||
@ -779,10 +809,12 @@ meta_display_open (void)
|
||||
if (old_active_window)
|
||||
meta_window_focus (old_active_window, timestamp);
|
||||
else
|
||||
meta_x11_display_focus_the_no_focus_window (display->x11_display, timestamp);
|
||||
meta_display_unset_input_focus (display, timestamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_display_unset_input_focus (display, timestamp);
|
||||
}
|
||||
else if (display->x11_display)
|
||||
meta_x11_display_focus_the_no_focus_window (display->x11_display, timestamp);
|
||||
|
||||
meta_idle_monitor_init_dbus ();
|
||||
|
||||
@ -924,7 +956,7 @@ meta_display_close (MetaDisplay *display,
|
||||
|
||||
g_clear_object (&display->gesture_tracker);
|
||||
|
||||
g_clear_pointer (&display->stack, meta_stack_free);
|
||||
g_clear_object (&display->stack);
|
||||
g_clear_pointer (&display->stack_tracker,
|
||||
meta_stack_tracker_free);
|
||||
|
||||
@ -953,12 +985,7 @@ meta_display_close (MetaDisplay *display,
|
||||
if (display->compositor)
|
||||
meta_compositor_destroy (display->compositor);
|
||||
|
||||
if (display->x11_display)
|
||||
{
|
||||
g_signal_emit (display, display_signals[X11_DISPLAY_CLOSING], 0);
|
||||
g_object_run_dispose (G_OBJECT (display->x11_display));
|
||||
g_clear_object (&display->x11_display);
|
||||
}
|
||||
meta_display_shutdown_x11 (display);
|
||||
|
||||
meta_display_shutdown_keys (display);
|
||||
|
||||
@ -1238,16 +1265,9 @@ meta_display_sync_wayland_input_focus (MetaDisplay *display)
|
||||
|
||||
void
|
||||
meta_display_update_focus_window (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
Window xwindow,
|
||||
gulong serial,
|
||||
gboolean focused_by_us)
|
||||
MetaWindow *window)
|
||||
{
|
||||
display->x11_display->focus_serial = serial;
|
||||
display->focused_by_us = focused_by_us;
|
||||
|
||||
if (display->x11_display->focus_xwindow == xwindow &&
|
||||
display->focus_window == window)
|
||||
if (display->focus_window == window)
|
||||
return;
|
||||
|
||||
if (display->focus_window)
|
||||
@ -1264,28 +1284,25 @@ meta_display_update_focus_window (MetaDisplay *display,
|
||||
*/
|
||||
previous = display->focus_window;
|
||||
display->focus_window = NULL;
|
||||
display->x11_display->focus_xwindow = None;
|
||||
|
||||
meta_window_set_focused_internal (previous, FALSE);
|
||||
}
|
||||
|
||||
display->focus_window = window;
|
||||
display->x11_display->focus_xwindow = xwindow;
|
||||
|
||||
if (display->focus_window)
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS, "* Focus --> %s with serial %lu\n",
|
||||
display->focus_window->desc, serial);
|
||||
meta_topic (META_DEBUG_FOCUS, "* Focus --> %s\n",
|
||||
display->focus_window->desc);
|
||||
meta_window_set_focused_internal (display->focus_window, TRUE);
|
||||
}
|
||||
else
|
||||
meta_topic (META_DEBUG_FOCUS, "* Focus --> NULL with serial %lu\n", serial);
|
||||
meta_topic (META_DEBUG_FOCUS, "* Focus --> NULL\n");
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
meta_display_sync_wayland_input_focus (display);
|
||||
|
||||
g_object_notify (G_OBJECT (display), "focus-window");
|
||||
meta_x11_display_update_active_window_hint (display->x11_display);
|
||||
}
|
||||
|
||||
gboolean
|
||||
@ -1317,6 +1334,51 @@ meta_display_timestamp_too_old (MetaDisplay *display,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_display_set_input_focus (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
gboolean focus_frame,
|
||||
guint32 timestamp)
|
||||
{
|
||||
if (meta_display_timestamp_too_old (display, ×tamp))
|
||||
return;
|
||||
|
||||
if (display->x11_display)
|
||||
{
|
||||
MetaX11Display *x11_display = display->x11_display;
|
||||
Window xwindow;
|
||||
gulong serial;
|
||||
|
||||
meta_x11_error_trap_push (x11_display);
|
||||
|
||||
if (window)
|
||||
xwindow = focus_frame ? window->frame->xwindow : window->xwindow;
|
||||
else
|
||||
xwindow = x11_display->no_focus_window;
|
||||
|
||||
meta_x11_display_set_input_focus (x11_display, xwindow, timestamp);
|
||||
serial = XNextRequest (x11_display->xdisplay);
|
||||
|
||||
meta_x11_display_update_focus_window (x11_display, xwindow, serial, TRUE);
|
||||
|
||||
meta_x11_error_trap_pop (display->x11_display);
|
||||
}
|
||||
|
||||
meta_display_update_focus_window (display, window);
|
||||
|
||||
display->last_focus_time = timestamp;
|
||||
|
||||
if (window == NULL || window != display->autoraise_window)
|
||||
meta_display_remove_autoraise_callback (display);
|
||||
}
|
||||
|
||||
void
|
||||
meta_display_unset_input_focus (MetaDisplay *display,
|
||||
guint32 timestamp)
|
||||
{
|
||||
meta_display_set_input_focus (display, NULL, FALSE, timestamp);
|
||||
}
|
||||
|
||||
void
|
||||
meta_display_register_wayland_window (MetaDisplay *display,
|
||||
MetaWindow *window)
|
||||
@ -1678,14 +1740,17 @@ meta_display_begin_grab_op (MetaDisplay *display,
|
||||
if (pointer_already_grabbed)
|
||||
display->grab_have_pointer = TRUE;
|
||||
|
||||
/* Since grab operations often happen as a result of implicit
|
||||
* pointer operations on the display X11 connection, we need
|
||||
* to ungrab here to ensure that the backend's X11 can take
|
||||
* the device grab. */
|
||||
XIUngrabDevice (display->x11_display->xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
timestamp);
|
||||
XSync (display->x11_display->xdisplay, False);
|
||||
if (META_IS_BACKEND_X11 (meta_get_backend ()) && display->x11_display)
|
||||
{
|
||||
/* Since grab operations often happen as a result of implicit
|
||||
* pointer operations on the display X11 connection, we need
|
||||
* to ungrab here to ensure that the backend's X11 can take
|
||||
* the device grab. */
|
||||
XIUngrabDevice (display->x11_display->xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
timestamp);
|
||||
XSync (display->x11_display->xdisplay, False);
|
||||
}
|
||||
|
||||
if (meta_backend_grab_device (backend, META_VIRTUAL_CORE_POINTER_ID, timestamp))
|
||||
display->grab_have_pointer = TRUE;
|
||||
@ -2490,37 +2555,6 @@ prefs_changed_callback (MetaPreference pref,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_display_increment_focus_sentinel (MetaDisplay *display)
|
||||
{
|
||||
unsigned long data[1];
|
||||
|
||||
data[0] = meta_display_get_current_time (display);
|
||||
|
||||
XChangeProperty (display->x11_display->xdisplay,
|
||||
display->x11_display->xroot,
|
||||
display->x11_display->atom__MUTTER_SENTINEL,
|
||||
XA_CARDINAL,
|
||||
32, PropModeReplace, (guchar*) data, 1);
|
||||
|
||||
display->sentinel_counter += 1;
|
||||
}
|
||||
|
||||
void
|
||||
meta_display_decrement_focus_sentinel (MetaDisplay *display)
|
||||
{
|
||||
display->sentinel_counter -= 1;
|
||||
|
||||
if (display->sentinel_counter < 0)
|
||||
display->sentinel_counter = 0;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_display_focus_sentinel_clear (MetaDisplay *display)
|
||||
{
|
||||
return (display->sentinel_counter == 0);
|
||||
}
|
||||
|
||||
void
|
||||
meta_display_sanity_check_timestamps (MetaDisplay *display,
|
||||
guint32 timestamp)
|
||||
@ -2626,13 +2660,14 @@ meta_display_supports_extended_barriers (MetaDisplay *display)
|
||||
return TRUE;
|
||||
#endif
|
||||
|
||||
if (META_IS_BACKEND_X11 (meta_get_backend ()))
|
||||
if (META_IS_BACKEND_X11_CM (meta_get_backend ()))
|
||||
{
|
||||
return (META_X11_DISPLAY_HAS_XINPUT_23 (display->x11_display) &&
|
||||
!meta_is_wayland_compositor());
|
||||
if (meta_is_wayland_compositor())
|
||||
return FALSE;
|
||||
|
||||
return META_X11_DISPLAY_HAS_XINPUT_23 (display->x11_display);
|
||||
}
|
||||
|
||||
g_assert_not_reached ();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -606,22 +606,6 @@ meta_init (void)
|
||||
meta_fatal ("Can't specify both SM save file and SM client id\n");
|
||||
|
||||
meta_main_loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
/*
|
||||
* We need to make sure the first client connecting to the X server
|
||||
* (e.g. Xwayland started from meta_wayland_init() above) is a permanent one,
|
||||
* so prepare the GDK X11 connection now already. Without doing this, if
|
||||
* there are any functionality that relies on X11 after here before
|
||||
* meta_display_open(), the X server will terminate itself when such a client
|
||||
* disconnects before the permanent GDK client connects.
|
||||
*/
|
||||
if (meta_should_autostart_x11_display ())
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (!meta_x11_init_gdk_display (&error))
|
||||
g_error ("Failed to open X11 display: %s", error->message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -600,8 +600,6 @@ meta_workspace_manager_calc_workspace_layout (MetaWorkspaceManager *workspace_ma
|
||||
|
||||
grid = g_new (int, grid_area);
|
||||
|
||||
current_row = -1;
|
||||
current_col = -1;
|
||||
i = 0;
|
||||
|
||||
switch (workspace_manager->starting_corner)
|
||||
|
409
src/core/stack.c
409
src/core/stack.c
@ -29,18 +29,13 @@
|
||||
|
||||
#include "core/stack.h"
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#include "backends/meta-logical-monitor.h"
|
||||
#include "core/frame.h"
|
||||
#include "core/meta-workspace-manager-private.h"
|
||||
#include "core/window-private.h"
|
||||
#include "meta/group.h"
|
||||
#include "meta/meta-x11-errors.h"
|
||||
#include "meta/prefs.h"
|
||||
#include "meta/workspace.h"
|
||||
#include "x11/group-private.h"
|
||||
#include "x11/meta-x11-display-private.h"
|
||||
|
||||
#define WINDOW_HAS_TRANSIENT_TYPE(w) \
|
||||
(w->type == META_WINDOW_DIALOG || \
|
||||
@ -52,51 +47,141 @@
|
||||
#define WINDOW_TRANSIENT_FOR_WHOLE_GROUP(w) \
|
||||
(WINDOW_HAS_TRANSIENT_TYPE (w) && w->transient_for == NULL)
|
||||
|
||||
static void stack_sync_to_xserver (MetaStack *stack);
|
||||
static void meta_window_set_stack_position_no_sync (MetaWindow *window,
|
||||
int position);
|
||||
static void stack_do_window_deletions (MetaStack *stack);
|
||||
static void stack_do_window_additions (MetaStack *stack);
|
||||
static void stack_do_relayer (MetaStack *stack);
|
||||
static void stack_do_constrain (MetaStack *stack);
|
||||
static void stack_do_resort (MetaStack *stack);
|
||||
|
||||
static void stack_ensure_sorted (MetaStack *stack);
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_DISPLAY = 1,
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CHANGED,
|
||||
WINDOW_ADDED,
|
||||
WINDOW_REMOVED,
|
||||
N_SIGNALS
|
||||
};
|
||||
|
||||
static GParamSpec *pspecs[N_PROPS] = { 0 };
|
||||
static guint signals[N_SIGNALS] = { 0 };
|
||||
|
||||
G_DEFINE_TYPE (MetaStack, meta_stack, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
meta_stack_init (MetaStack *stack)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_stack_finalize (GObject *object)
|
||||
{
|
||||
MetaStack *stack = META_STACK (object);
|
||||
|
||||
g_list_free (stack->sorted);
|
||||
|
||||
G_OBJECT_CLASS (meta_stack_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_stack_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaStack *stack = META_STACK (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DISPLAY:
|
||||
stack->display = g_value_get_object (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_stack_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaStack *stack = META_STACK (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DISPLAY:
|
||||
g_value_set_object (value, stack->display);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_stack_class_init (MetaStackClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->set_property = meta_stack_set_property;
|
||||
object_class->get_property = meta_stack_get_property;
|
||||
object_class->finalize = meta_stack_finalize;
|
||||
|
||||
signals[CHANGED] =
|
||||
g_signal_new ("changed",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0, NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
signals[WINDOW_ADDED] =
|
||||
g_signal_new ("window-added",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0, NULL, NULL,
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 1, META_TYPE_WINDOW);
|
||||
signals[WINDOW_REMOVED] =
|
||||
g_signal_new ("window-removed",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0, NULL, NULL,
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 1, META_TYPE_WINDOW);
|
||||
|
||||
pspecs[PROP_DISPLAY] =
|
||||
g_param_spec_object ("display",
|
||||
"Display",
|
||||
"Display",
|
||||
META_TYPE_DISPLAY,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPS, pspecs);
|
||||
}
|
||||
|
||||
MetaStack *
|
||||
meta_stack_new (MetaDisplay *display)
|
||||
{
|
||||
MetaStack *stack;
|
||||
|
||||
stack = g_new (MetaStack, 1);
|
||||
|
||||
stack->display = display;
|
||||
stack->xwindows = g_array_new (FALSE, FALSE, sizeof (Window));
|
||||
|
||||
stack->sorted = NULL;
|
||||
stack->added = NULL;
|
||||
stack->removed = NULL;
|
||||
|
||||
stack->freeze_count = 0;
|
||||
stack->n_positions = 0;
|
||||
|
||||
stack->need_resort = FALSE;
|
||||
stack->need_relayer = FALSE;
|
||||
stack->need_constrain = FALSE;
|
||||
|
||||
return stack;
|
||||
return g_object_new (META_TYPE_STACK,
|
||||
"display", display,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void
|
||||
meta_stack_free (MetaStack *stack)
|
||||
static void
|
||||
meta_stack_changed (MetaStack *stack)
|
||||
{
|
||||
g_array_free (stack->xwindows, TRUE);
|
||||
/* Bail out if frozen */
|
||||
if (stack->freeze_count > 0)
|
||||
return;
|
||||
|
||||
g_list_free (stack->sorted);
|
||||
g_list_free (stack->added);
|
||||
g_list_free (stack->removed);
|
||||
|
||||
g_free (stack);
|
||||
stack_ensure_sorted (stack);
|
||||
g_signal_emit (stack, signals[CHANGED], 0);
|
||||
}
|
||||
|
||||
void
|
||||
@ -112,7 +197,12 @@ meta_stack_add (MetaStack *stack,
|
||||
if (meta_window_is_in_stack (window))
|
||||
meta_bug ("Window %s had stack position already\n", window->desc);
|
||||
|
||||
stack->added = g_list_prepend (stack->added, window);
|
||||
stack->sorted = g_list_prepend (stack->sorted, window);
|
||||
stack->need_resort = TRUE; /* may not be needed as we add to top */
|
||||
stack->need_constrain = TRUE;
|
||||
stack->need_relayer = TRUE;
|
||||
|
||||
g_signal_emit (stack, signals[WINDOW_ADDED], 0, window);
|
||||
|
||||
window->stack_position = stack->n_positions;
|
||||
stack->n_positions += 1;
|
||||
@ -120,7 +210,7 @@ meta_stack_add (MetaStack *stack,
|
||||
"Window %s has stack_position initialized to %d\n",
|
||||
window->desc, window->stack_position);
|
||||
|
||||
stack_sync_to_xserver (stack);
|
||||
meta_stack_changed (stack);
|
||||
meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace);
|
||||
}
|
||||
|
||||
@ -140,25 +230,11 @@ meta_stack_remove (MetaStack *stack,
|
||||
window->stack_position = -1;
|
||||
stack->n_positions -= 1;
|
||||
|
||||
/* We don't know if it's been moved from "added" to "stack" yet */
|
||||
stack->added = g_list_remove (stack->added, window);
|
||||
stack->sorted = g_list_remove (stack->sorted, window);
|
||||
|
||||
/* stack->removed is only used to update stack->xwindows */
|
||||
if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
{
|
||||
/* Remember the window ID to remove it from the stack array.
|
||||
* The macro is safe to use: Window is guaranteed to be 32 bits, and
|
||||
* GUINT_TO_POINTER says it only works on 32 bits.
|
||||
*/
|
||||
stack->removed = g_list_prepend (stack->removed,
|
||||
GUINT_TO_POINTER (window->xwindow));
|
||||
if (window->frame)
|
||||
stack->removed = g_list_prepend (stack->removed,
|
||||
GUINT_TO_POINTER (window->frame->xwindow));
|
||||
}
|
||||
g_signal_emit (stack, signals[WINDOW_REMOVED], 0, window);
|
||||
|
||||
stack_sync_to_xserver (stack);
|
||||
meta_stack_changed (stack);
|
||||
meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace);
|
||||
}
|
||||
|
||||
@ -169,7 +245,7 @@ meta_stack_update_layer (MetaStack *stack,
|
||||
MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
|
||||
stack->need_relayer = TRUE;
|
||||
|
||||
stack_sync_to_xserver (stack);
|
||||
meta_stack_changed (stack);
|
||||
meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace);
|
||||
}
|
||||
|
||||
@ -180,7 +256,7 @@ meta_stack_update_transient (MetaStack *stack,
|
||||
MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
|
||||
stack->need_constrain = TRUE;
|
||||
|
||||
stack_sync_to_xserver (stack);
|
||||
meta_stack_changed (stack);
|
||||
meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace);
|
||||
}
|
||||
|
||||
@ -210,7 +286,7 @@ meta_stack_raise (MetaStack *stack,
|
||||
|
||||
meta_window_set_stack_position_no_sync (window, max_stack_position);
|
||||
|
||||
stack_sync_to_xserver (stack);
|
||||
meta_stack_changed (stack);
|
||||
meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace);
|
||||
}
|
||||
|
||||
@ -239,7 +315,7 @@ meta_stack_lower (MetaStack *stack,
|
||||
|
||||
meta_window_set_stack_position_no_sync (window, min_stack_position);
|
||||
|
||||
stack_sync_to_xserver (stack);
|
||||
meta_stack_changed (stack);
|
||||
meta_stack_update_window_tile_matches (stack, workspace_manager->active_workspace);
|
||||
}
|
||||
|
||||
@ -255,7 +331,7 @@ meta_stack_thaw (MetaStack *stack)
|
||||
g_return_if_fail (stack->freeze_count > 0);
|
||||
|
||||
stack->freeze_count -= 1;
|
||||
stack_sync_to_xserver (stack);
|
||||
meta_stack_changed (stack);
|
||||
meta_stack_update_window_tile_matches (stack, NULL);
|
||||
}
|
||||
|
||||
@ -771,99 +847,6 @@ apply_constraints (Constraint **constraints,
|
||||
g_slist_free (heads);
|
||||
}
|
||||
|
||||
/**
|
||||
* stack_do_window_deletions:
|
||||
*
|
||||
* Go through "deleted" and take the matching windows
|
||||
* out of "windows".
|
||||
*/
|
||||
static void
|
||||
stack_do_window_deletions (MetaStack *stack)
|
||||
{
|
||||
/* Do removals before adds, with paranoid idea that we might re-add
|
||||
* the same window IDs.
|
||||
*/
|
||||
GList *tmp;
|
||||
int i;
|
||||
|
||||
tmp = stack->removed;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
Window xwindow;
|
||||
xwindow = GPOINTER_TO_UINT (tmp->data);
|
||||
|
||||
/* We go from the end figuring removals are more
|
||||
* likely to be recent.
|
||||
*/
|
||||
i = stack->xwindows->len;
|
||||
while (i > 0)
|
||||
{
|
||||
--i;
|
||||
|
||||
/* there's no guarantee we'll actually find windows to
|
||||
* remove, e.g. the same xwindow could have been
|
||||
* added/removed before we ever synced, and we put
|
||||
* both the window->xwindow and window->frame->xwindow
|
||||
* in the removal list.
|
||||
*/
|
||||
if (xwindow == g_array_index (stack->xwindows, Window, i))
|
||||
{
|
||||
g_array_remove_index (stack->xwindows, i);
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
|
||||
next:
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
g_list_free (stack->removed);
|
||||
stack->removed = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
stack_do_window_additions (MetaStack *stack)
|
||||
{
|
||||
GList *tmp;
|
||||
gint n_added;
|
||||
|
||||
n_added = g_list_length (stack->added);
|
||||
if (n_added > 0)
|
||||
{
|
||||
meta_topic (META_DEBUG_STACK,
|
||||
"Adding %d windows to sorted list\n",
|
||||
n_added);
|
||||
|
||||
/* stack->added has the most recent additions at the
|
||||
* front of the list, so we need to reverse it
|
||||
*/
|
||||
stack->added = g_list_reverse (stack->added);
|
||||
|
||||
tmp = stack->added;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MetaWindow *w;
|
||||
|
||||
w = tmp->data;
|
||||
|
||||
if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
g_array_append_val (stack->xwindows, w->xwindow);
|
||||
|
||||
/* add to the main list */
|
||||
stack->sorted = g_list_prepend (stack->sorted, w);
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
stack->need_resort = TRUE; /* may not be needed as we add to top */
|
||||
stack->need_constrain = TRUE;
|
||||
stack->need_relayer = TRUE;
|
||||
}
|
||||
|
||||
g_list_free (stack->added);
|
||||
stack->added = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* stack_do_relayer:
|
||||
*
|
||||
@ -981,131 +964,11 @@ stack_do_resort (MetaStack *stack)
|
||||
static void
|
||||
stack_ensure_sorted (MetaStack *stack)
|
||||
{
|
||||
stack_do_window_deletions (stack);
|
||||
stack_do_window_additions (stack);
|
||||
stack_do_relayer (stack);
|
||||
stack_do_constrain (stack);
|
||||
stack_do_resort (stack);
|
||||
}
|
||||
|
||||
/**
|
||||
* stack_sync_to_server:
|
||||
*
|
||||
* Order the windows on the X server to be the same as in our structure.
|
||||
* We do this using XRestackWindows if we don't know the previous order,
|
||||
* or XConfigureWindow on a few particular windows if we do and can figure
|
||||
* out the minimum set of changes. After that, we set __NET_CLIENT_LIST
|
||||
* and __NET_CLIENT_LIST_STACKING.
|
||||
*
|
||||
* FIXME: Now that we have a good view of the stacking order on the server
|
||||
* with MetaStackTracker it should be possible to do a simpler and better
|
||||
* job of computing the minimal set of stacking requests needed.
|
||||
*/
|
||||
static void
|
||||
stack_sync_to_xserver (MetaStack *stack)
|
||||
{
|
||||
GArray *x11_stacked;
|
||||
GArray *all_root_children_stacked; /* wayland OR x11 */
|
||||
GList *tmp;
|
||||
GArray *hidden_stack_ids;
|
||||
|
||||
/* Bail out if frozen */
|
||||
if (stack->freeze_count > 0)
|
||||
return;
|
||||
|
||||
meta_topic (META_DEBUG_STACK, "Syncing window stack to server\n");
|
||||
|
||||
stack_ensure_sorted (stack);
|
||||
|
||||
/* Create stacked xwindow arrays, in bottom-to-top order
|
||||
*/
|
||||
x11_stacked = g_array_new (FALSE, FALSE, sizeof (Window));
|
||||
|
||||
all_root_children_stacked = g_array_new (FALSE, FALSE, sizeof (guint64));
|
||||
hidden_stack_ids = g_array_new (FALSE, FALSE, sizeof (guint64));
|
||||
|
||||
meta_topic (META_DEBUG_STACK, "Bottom to top: ");
|
||||
meta_push_no_msg_prefix ();
|
||||
|
||||
for (tmp = g_list_last(stack->sorted); tmp != NULL; tmp = tmp->prev)
|
||||
{
|
||||
MetaWindow *w = tmp->data;
|
||||
guint64 top_level_window;
|
||||
guint64 stack_id;
|
||||
|
||||
if (w->unmanaging)
|
||||
continue;
|
||||
|
||||
meta_topic (META_DEBUG_STACK, "%u:%d - %s ",
|
||||
w->layer, w->stack_position, w->desc);
|
||||
|
||||
if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
g_array_append_val (x11_stacked, w->xwindow);
|
||||
|
||||
if (w->frame)
|
||||
top_level_window = w->frame->xwindow;
|
||||
else
|
||||
top_level_window = w->xwindow;
|
||||
|
||||
if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
stack_id = top_level_window;
|
||||
else
|
||||
stack_id = w->stamp;
|
||||
|
||||
/* We don't restack hidden windows along with the rest, though they are
|
||||
* reflected in the _NET hints. Hidden windows all get pushed below
|
||||
* the screens fullscreen guard_window. */
|
||||
if (w->hidden)
|
||||
{
|
||||
g_array_append_val (hidden_stack_ids, stack_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
g_array_append_val (all_root_children_stacked, stack_id);
|
||||
}
|
||||
|
||||
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. */
|
||||
guint64 guard_window_id = stack->display->x11_display->guard_window;
|
||||
g_array_append_val (hidden_stack_ids, guard_window_id);
|
||||
|
||||
/* Sync to server */
|
||||
|
||||
meta_topic (META_DEBUG_STACK, "Restacking %u windows\n",
|
||||
all_root_children_stacked->len);
|
||||
|
||||
meta_stack_tracker_restack_managed (stack->display->stack_tracker,
|
||||
(guint64 *)all_root_children_stacked->data,
|
||||
all_root_children_stacked->len);
|
||||
meta_stack_tracker_restack_at_bottom (stack->display->stack_tracker,
|
||||
(guint64 *)hidden_stack_ids->data,
|
||||
hidden_stack_ids->len);
|
||||
|
||||
/* Sync _NET_CLIENT_LIST and _NET_CLIENT_LIST_STACKING */
|
||||
|
||||
XChangeProperty (stack->display->x11_display->xdisplay,
|
||||
stack->display->x11_display->xroot,
|
||||
stack->display->x11_display->atom__NET_CLIENT_LIST,
|
||||
XA_WINDOW,
|
||||
32, PropModeReplace,
|
||||
(unsigned char *)stack->xwindows->data,
|
||||
stack->xwindows->len);
|
||||
XChangeProperty (stack->display->x11_display->xdisplay,
|
||||
stack->display->x11_display->xroot,
|
||||
stack->display->x11_display->atom__NET_CLIENT_LIST_STACKING,
|
||||
XA_WINDOW,
|
||||
32, PropModeReplace,
|
||||
(unsigned char *)x11_stacked->data,
|
||||
x11_stacked->len);
|
||||
|
||||
g_array_free (x11_stacked, TRUE);
|
||||
g_array_free (hidden_stack_ids, TRUE);
|
||||
g_array_free (all_root_children_stacked, TRUE);
|
||||
}
|
||||
|
||||
MetaWindow*
|
||||
meta_stack_get_top (MetaStack *stack)
|
||||
{
|
||||
@ -1415,7 +1278,7 @@ meta_stack_set_positions (MetaStack *stack,
|
||||
meta_topic (META_DEBUG_STACK,
|
||||
"Reset the stack positions of (nearly) all windows\n");
|
||||
|
||||
stack_sync_to_xserver (stack);
|
||||
meta_stack_changed (stack);
|
||||
meta_stack_update_window_tile_matches (stack, NULL);
|
||||
}
|
||||
|
||||
@ -1480,7 +1343,7 @@ meta_window_set_stack_position (MetaWindow *window,
|
||||
MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
|
||||
|
||||
meta_window_set_stack_position_no_sync (window, position);
|
||||
stack_sync_to_xserver (window->display->stack);
|
||||
meta_stack_changed (window->display->stack);
|
||||
meta_stack_update_window_tile_matches (window->display->stack,
|
||||
workspace_manager->active_workspace);
|
||||
}
|
||||
|
@ -51,38 +51,14 @@
|
||||
*/
|
||||
struct _MetaStack
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
/** The MetaDisplay containing this stack. */
|
||||
MetaDisplay *display;
|
||||
|
||||
/**
|
||||
* A sequence of all the Windows (X handles, not MetaWindows) of the windows
|
||||
* we manage, sorted in order. Suitable to be passed into _NET_CLIENT_LIST.
|
||||
*/
|
||||
GArray *xwindows;
|
||||
|
||||
/** The MetaWindows of the windows we manage, sorted in order. */
|
||||
GList *sorted;
|
||||
|
||||
/**
|
||||
* MetaWindows waiting to be added to the "sorted" and "windows" list, after
|
||||
* being added by meta_stack_add() and before being assimilated by
|
||||
* stack_ensure_sorted().
|
||||
*
|
||||
* The order of the elements in this list is not important; what is important
|
||||
* is the stack_position element of each window.
|
||||
*/
|
||||
GList *added;
|
||||
|
||||
/**
|
||||
* Windows (X handles, not MetaWindows) waiting to be removed from the
|
||||
* "windows" list, after being removed by meta_stack_remove() and before
|
||||
* being assimilated by stack_ensure_sorted(). (We already removed them
|
||||
* from the "sorted" list.)
|
||||
*
|
||||
* The order of the elements in this list is not important.
|
||||
*/
|
||||
GList *removed;
|
||||
|
||||
/**
|
||||
* If this is zero, the local stack oughtn't to be brought up to date with
|
||||
* the X server's stack, because it is in the middle of being updated.
|
||||
@ -121,6 +97,9 @@ struct _MetaStack
|
||||
unsigned int need_constrain : 1;
|
||||
};
|
||||
|
||||
#define META_TYPE_STACK (meta_stack_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (MetaStack, meta_stack, META, STACK, GObject)
|
||||
|
||||
/**
|
||||
* meta_stack_new:
|
||||
* @display: The MetaDisplay which will be the parent of this stack.
|
||||
@ -131,14 +110,6 @@ struct _MetaStack
|
||||
*/
|
||||
MetaStack *meta_stack_new (MetaDisplay *display);
|
||||
|
||||
/**
|
||||
* meta_stack_free:
|
||||
* @stack: The stack to destroy.
|
||||
*
|
||||
* Destroys and frees a MetaStack.
|
||||
*/
|
||||
void meta_stack_free (MetaStack *stack);
|
||||
|
||||
/**
|
||||
* meta_stack_add:
|
||||
* @stack: The stack to add it to
|
||||
|
@ -581,6 +581,9 @@ struct _MetaWindowClass
|
||||
gboolean (*is_stackable) (MetaWindow *window);
|
||||
gboolean (*can_ping) (MetaWindow *window);
|
||||
gboolean (*are_updates_frozen) (MetaWindow *window);
|
||||
|
||||
void (* map) (MetaWindow *window);
|
||||
void (* unmap) (MetaWindow *window);
|
||||
};
|
||||
|
||||
/* These differ from window->has_foo_func in that they consider
|
||||
|
@ -809,17 +809,10 @@ sync_client_window_mapped (MetaWindow *window)
|
||||
|
||||
window->mapped = should_be_mapped;
|
||||
|
||||
meta_x11_error_trap_push (window->display->x11_display);
|
||||
if (should_be_mapped)
|
||||
{
|
||||
XMapWindow (window->display->x11_display->xdisplay, window->xwindow);
|
||||
}
|
||||
if (window->mapped)
|
||||
META_WINDOW_GET_CLASS (window)->map (window);
|
||||
else
|
||||
{
|
||||
XUnmapWindow (window->display->x11_display->xdisplay, window->xwindow);
|
||||
window->unmaps_pending ++;
|
||||
}
|
||||
meta_x11_error_trap_pop (window->display->x11_display);
|
||||
META_WINDOW_GET_CLASS (window)->unmap (window);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -1939,9 +1932,10 @@ idle_calc_showing (gpointer data)
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MetaWindow *window = tmp->data;
|
||||
MetaDisplay *display = window->display;
|
||||
|
||||
if (!window->display->mouse_mode)
|
||||
meta_display_increment_focus_sentinel (window->display);
|
||||
if (display->x11_display && !display->mouse_mode)
|
||||
meta_x11_display_increment_focus_sentinel (display->x11_display);
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
@ -2411,6 +2405,7 @@ meta_window_show (MetaWindow *window)
|
||||
gboolean needs_stacking_adjustment;
|
||||
MetaWindow *focus_window;
|
||||
gboolean notify_demands_attention = FALSE;
|
||||
MetaDisplay *display = window->display;
|
||||
|
||||
meta_topic (META_DEBUG_WINDOW_STATE,
|
||||
"Showing window %s, shaded: %d iconic: %d placed: %d\n",
|
||||
@ -2577,7 +2572,7 @@ meta_window_show (MetaWindow *window)
|
||||
|
||||
meta_window_focus (window, timestamp);
|
||||
}
|
||||
else
|
||||
else if (display->x11_display)
|
||||
{
|
||||
/* Prevent EnterNotify events in sloppy/mouse focus from
|
||||
* erroneously focusing the window that had been denied
|
||||
@ -2585,7 +2580,7 @@ meta_window_show (MetaWindow *window)
|
||||
* ideas for a better way to accomplish the same thing, but
|
||||
* they're more involved so do it this way for now.
|
||||
*/
|
||||
meta_display_increment_focus_sentinel (window->display);
|
||||
meta_x11_display_increment_focus_sentinel (display->x11_display);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3812,13 +3807,13 @@ maybe_move_attached_window (MetaWindow *window,
|
||||
void *data)
|
||||
{
|
||||
if (window->hidden)
|
||||
return FALSE;
|
||||
return G_SOURCE_CONTINUE;
|
||||
|
||||
if (meta_window_is_attached_dialog (window) ||
|
||||
meta_window_get_placement_rule (window))
|
||||
meta_window_reposition (window);
|
||||
|
||||
return FALSE;
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -5378,50 +5373,6 @@ redraw_icon (MetaWindow *window)
|
||||
meta_frame_queue_draw (window->frame);
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
load_default_window_icon (int size)
|
||||
{
|
||||
GtkIconTheme *theme = gtk_icon_theme_get_default ();
|
||||
g_autoptr (GdkPixbuf) pixbuf = NULL;
|
||||
const char *icon_name;
|
||||
|
||||
if (gtk_icon_theme_has_icon (theme, META_DEFAULT_ICON_NAME))
|
||||
icon_name = META_DEFAULT_ICON_NAME;
|
||||
else
|
||||
icon_name = "image-missing";
|
||||
|
||||
pixbuf = gtk_icon_theme_load_icon (theme, icon_name, size, 0, NULL);
|
||||
return gdk_cairo_surface_create_from_pixbuf (pixbuf, 1, NULL);
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
get_default_window_icon (void)
|
||||
{
|
||||
static cairo_surface_t *default_icon = NULL;
|
||||
|
||||
if (default_icon == NULL)
|
||||
{
|
||||
default_icon = load_default_window_icon (META_ICON_WIDTH);
|
||||
g_assert (default_icon);
|
||||
}
|
||||
|
||||
return cairo_surface_reference (default_icon);
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
get_default_mini_icon (void)
|
||||
{
|
||||
static cairo_surface_t *default_icon = NULL;
|
||||
|
||||
if (default_icon == NULL)
|
||||
{
|
||||
default_icon = load_default_window_icon (META_MINI_ICON_WIDTH);
|
||||
g_assert (default_icon);
|
||||
}
|
||||
|
||||
return cairo_surface_reference (default_icon);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_update_icon_now (MetaWindow *window,
|
||||
gboolean force)
|
||||
@ -5438,17 +5389,11 @@ meta_window_update_icon_now (MetaWindow *window,
|
||||
{
|
||||
if (window->icon)
|
||||
cairo_surface_destroy (window->icon);
|
||||
if (icon)
|
||||
window->icon = icon;
|
||||
else
|
||||
window->icon = get_default_window_icon ();
|
||||
window->icon = icon;
|
||||
|
||||
if (window->mini_icon)
|
||||
cairo_surface_destroy (window->mini_icon);
|
||||
if (mini_icon)
|
||||
window->mini_icon = mini_icon;
|
||||
else
|
||||
window->mini_icon = get_default_mini_icon ();
|
||||
window->mini_icon = mini_icon;
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (window));
|
||||
g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_ICON]);
|
||||
@ -5457,9 +5402,6 @@ meta_window_update_icon_now (MetaWindow *window,
|
||||
|
||||
redraw_icon (window);
|
||||
}
|
||||
|
||||
g_assert (window->icon);
|
||||
g_assert (window->mini_icon);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -8146,8 +8088,7 @@ mouse_mode_focus (MetaWindow *window,
|
||||
"Unsetting focus from %s due to mouse entering "
|
||||
"the DESKTOP window\n",
|
||||
display->focus_window->desc);
|
||||
meta_x11_display_focus_the_no_focus_window (display->x11_display,
|
||||
timestamp);
|
||||
meta_display_unset_input_focus (display, timestamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1308,8 +1308,7 @@ meta_workspace_focus_default_window (MetaWorkspace *workspace,
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Setting focus to no_focus_window, since no valid "
|
||||
"window to focus found.\n");
|
||||
meta_x11_display_focus_the_no_focus_window (workspace->display->x11_display,
|
||||
timestamp);
|
||||
meta_display_unset_input_focus (workspace->display, timestamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1381,8 +1380,7 @@ focus_ancestor_or_top_window (MetaWorkspace *workspace,
|
||||
else
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS, "No MRU window to focus found; focusing no_focus_window.\n");
|
||||
meta_x11_display_focus_the_no_focus_window (workspace->display->x11_display,
|
||||
timestamp);
|
||||
meta_display_unset_input_focus (workspace->display, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -392,6 +392,8 @@ mutter_sources = [
|
||||
'x11/meta-x11-selection-input-stream-private.h',
|
||||
'x11/meta-x11-selection-output-stream.c',
|
||||
'x11/meta-x11-selection-output-stream-private.h',
|
||||
'x11/meta-x11-stack.c',
|
||||
'x11/meta-x11-stack-private.h',
|
||||
'x11/mutter-Xatomtype.h',
|
||||
'x11/session.c',
|
||||
'x11/session.h',
|
||||
|
@ -297,4 +297,13 @@ MetaSoundPlayer * meta_display_get_sound_player (MetaDisplay *display);
|
||||
META_EXPORT
|
||||
MetaSelection * meta_display_get_selection (MetaDisplay *display);
|
||||
|
||||
META_EXPORT
|
||||
void meta_display_set_input_focus (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
gboolean focus_frame,
|
||||
guint32 timestamp);
|
||||
META_EXPORT
|
||||
void meta_display_unset_input_focus (MetaDisplay *display,
|
||||
guint32 timestamp);
|
||||
|
||||
#endif
|
||||
|
@ -63,27 +63,4 @@ META_EXPORT
|
||||
gboolean meta_x11_display_xwindow_is_a_no_focus_window (MetaX11Display *x11_display,
|
||||
Window xwindow);
|
||||
|
||||
/* meta_x11_display_set_input_focus_window is like XSetInputFocus, except
|
||||
* that (a) it can't detect timestamps later than the current time,
|
||||
* since Mutter isn't part of the XServer, and thus gives erroneous
|
||||
* behavior in this circumstance (so don't do it), (b) it uses
|
||||
* display->last_focus_time since we don't have access to the true
|
||||
* Xserver one, (c) it makes use of display->user_time since checking
|
||||
* whether a window should be allowed to be focused should depend
|
||||
* on user_time events (see bug 167358, comment 15 in particular)
|
||||
*/
|
||||
META_EXPORT
|
||||
void meta_x11_display_set_input_focus_window (MetaX11Display *x11_display,
|
||||
MetaWindow *window,
|
||||
gboolean focus_frame,
|
||||
guint32 timestamp);
|
||||
|
||||
/* meta_x11_display_focus_the_no_focus_window is called when the
|
||||
* designated no_focus_window should be focused, but is otherwise the
|
||||
* same as meta_display_set_input_focus_window
|
||||
*/
|
||||
META_EXPORT
|
||||
void meta_x11_display_focus_the_no_focus_window (MetaX11Display *x11_display,
|
||||
guint32 timestamp);
|
||||
|
||||
#endif /* META_X11_DISPLAY_H */
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "wayland/meta-wayland.h"
|
||||
|
||||
#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
||||
#define FRAME_WARNING "Frame has assigned frame counter but no frame drawn time"
|
||||
|
||||
static gboolean
|
||||
run_tests (gpointer data)
|
||||
@ -40,6 +41,8 @@ run_tests (gpointer data)
|
||||
MetaSettings *settings = meta_backend_get_settings (backend);
|
||||
gboolean ret;
|
||||
|
||||
g_test_log_set_fatal_handler (NULL, NULL);
|
||||
|
||||
meta_settings_override_experimental_features (settings);
|
||||
|
||||
meta_settings_enable_experimental_feature (
|
||||
@ -53,6 +56,20 @@ run_tests (gpointer data)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ignore_frame_counter_warning (const gchar *log_domain,
|
||||
GLogLevelFlags log_level,
|
||||
const gchar *message,
|
||||
gpointer user_data)
|
||||
{
|
||||
if ((log_level & G_LOG_LEVEL_WARNING) &&
|
||||
g_strcmp0 (log_domain, "mutter") == 0 &&
|
||||
g_str_has_suffix (message, FRAME_WARNING))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_test_headless_start (void)
|
||||
{
|
||||
@ -193,6 +210,8 @@ main (int argc, char *argv[])
|
||||
meta_init ();
|
||||
meta_register_with_session ();
|
||||
|
||||
g_test_log_set_fatal_handler (ignore_frame_counter_warning, NULL);
|
||||
|
||||
g_idle_add (run_tests, NULL);
|
||||
|
||||
return meta_run ();
|
||||
|
@ -385,6 +385,9 @@ test_case_do (TestCase *test,
|
||||
argc == 3 ? argv[2] : NULL,
|
||||
NULL))
|
||||
return FALSE;
|
||||
|
||||
if (!test_client_wait (client, error))
|
||||
return FALSE;
|
||||
}
|
||||
else if (strcmp (argv[0], "set_parent") == 0 ||
|
||||
strcmp (argv[0], "set_parent_exported") == 0)
|
||||
|
@ -31,8 +31,6 @@
|
||||
#include "meta/prefs.h"
|
||||
#include "ui/frames.h"
|
||||
|
||||
#define DEBUG_FILL_STRUCT(s) memset ((s), 0xef, sizeof (*(s)))
|
||||
|
||||
static void scale_border (GtkBorder *border, double factor);
|
||||
|
||||
static MetaFrameLayout *
|
||||
@ -58,7 +56,6 @@ meta_frame_layout_free (MetaFrameLayout *layout)
|
||||
{
|
||||
g_return_if_fail (layout != NULL);
|
||||
|
||||
DEBUG_FILL_STRUCT (layout);
|
||||
g_free (layout);
|
||||
}
|
||||
|
||||
@ -967,7 +964,6 @@ meta_theme_free (MetaTheme *theme)
|
||||
if (theme->layouts[i])
|
||||
meta_frame_layout_free (theme->layouts[i]);
|
||||
|
||||
DEBUG_FILL_STRUCT (theme);
|
||||
g_free (theme);
|
||||
}
|
||||
|
||||
|
@ -43,10 +43,6 @@
|
||||
|
||||
#include "linux-dmabuf-unstable-v1-server-protocol.h"
|
||||
|
||||
#ifndef DRM_FORMAT_MOD_INVALID
|
||||
#define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1)
|
||||
#endif
|
||||
|
||||
#define META_WAYLAND_DMA_BUF_MAX_FDS 4
|
||||
|
||||
struct _MetaWaylandDmaBufBuffer
|
||||
@ -84,28 +80,15 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer,
|
||||
if (buffer->dma_buf.texture)
|
||||
return TRUE;
|
||||
|
||||
switch (dma_buf->drm_format)
|
||||
/*
|
||||
* NOTE: The cogl_format here is only used for texture color channel
|
||||
* swizzling as compared to COGL_PIXEL_FORMAT_ARGB. It is *not* used
|
||||
* for accessing the buffer memory. EGL will access the buffer
|
||||
* memory according to the DRM fourcc code. Cogl will not mmap
|
||||
* and access the buffer memory at all.
|
||||
*/
|
||||
if (!cogl_pixel_format_from_drm_format (dma_buf->drm_format, &cogl_format, NULL))
|
||||
{
|
||||
/*
|
||||
* NOTE: The cogl_format here is only used for texture color channel
|
||||
* swizzling as compared to COGL_PIXEL_FORMAT_ARGB. It is *not* used
|
||||
* for accessing the buffer memory. EGL will access the buffer
|
||||
* memory according to the DRM fourcc code. Cogl will not mmap
|
||||
* and access the buffer memory at all.
|
||||
*/
|
||||
case DRM_FORMAT_XRGB8888:
|
||||
cogl_format = COGL_PIXEL_FORMAT_RGB_888;
|
||||
break;
|
||||
case DRM_FORMAT_ARGB8888:
|
||||
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888_PRE;
|
||||
break;
|
||||
case DRM_FORMAT_ARGB2101010:
|
||||
cogl_format = COGL_PIXEL_FORMAT_ARGB_2101010_PRE;
|
||||
break;
|
||||
case DRM_FORMAT_RGB565:
|
||||
cogl_format = COGL_PIXEL_FORMAT_RGB_565;
|
||||
break;
|
||||
default:
|
||||
g_set_error (error, G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
"Unsupported buffer format %d", dma_buf->drm_format);
|
||||
|
@ -862,6 +862,19 @@ init_pointer_constraint (struct wl_resource *resource,
|
||||
return;
|
||||
}
|
||||
|
||||
switch (lifetime)
|
||||
{
|
||||
case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT:
|
||||
case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT:
|
||||
break;
|
||||
|
||||
default:
|
||||
wl_resource_post_error (resource,
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
"Invalid constraint lifetime");
|
||||
return;
|
||||
}
|
||||
|
||||
constraint = meta_wayland_pointer_constraint_new (surface, seat,
|
||||
region,
|
||||
lifetime,
|
||||
|
@ -48,6 +48,7 @@ typedef struct
|
||||
char *lock_file;
|
||||
int abstract_fd;
|
||||
int unix_fd;
|
||||
struct wl_display *wayland_display;
|
||||
struct wl_client *client;
|
||||
struct wl_resource *xserver_resource;
|
||||
char *display_name;
|
||||
|
@ -266,7 +266,7 @@ meta_wayland_seat_free (MetaWaylandSeat *seat)
|
||||
meta_wayland_gtk_text_input_destroy (seat->gtk_text_input);
|
||||
meta_wayland_text_input_destroy (seat->text_input);
|
||||
|
||||
g_slice_free (MetaWaylandSeat, seat);
|
||||
g_free (seat);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -142,10 +142,12 @@ meta_window_wayland_focus (MetaWindow *window,
|
||||
guint32 timestamp)
|
||||
{
|
||||
if (meta_window_is_focusable (window))
|
||||
meta_x11_display_set_input_focus_window (window->display->x11_display,
|
||||
window,
|
||||
FALSE,
|
||||
timestamp);
|
||||
{
|
||||
meta_display_set_input_focus (window->display,
|
||||
window,
|
||||
FALSE,
|
||||
timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -611,6 +613,16 @@ meta_window_wayland_are_updates_frozen (MetaWindow *window)
|
||||
return !wl_window->has_been_shown;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_wayland_map (MetaWindow *window)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_wayland_unmap (MetaWindow *window)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_wayland_class_init (MetaWindowWaylandClass *klass)
|
||||
{
|
||||
@ -634,6 +646,8 @@ meta_window_wayland_class_init (MetaWindowWaylandClass *klass)
|
||||
window_class->is_stackable = meta_window_wayland_is_stackable;
|
||||
window_class->can_ping = meta_window_wayland_can_ping;
|
||||
window_class->are_updates_frozen = meta_window_wayland_are_updates_frozen;
|
||||
window_class->map = meta_window_wayland_map;
|
||||
window_class->unmap = meta_window_wayland_unmap;
|
||||
}
|
||||
|
||||
MetaWindow *
|
||||
@ -641,7 +655,6 @@ meta_window_wayland_new (MetaDisplay *display,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
XWindowAttributes attrs = { 0 };
|
||||
MetaWindow *window;
|
||||
|
||||
/*
|
||||
* Set attributes used by _meta_window_shared_new, don't bother trying to fake
|
||||
@ -656,26 +669,13 @@ meta_window_wayland_new (MetaDisplay *display,
|
||||
attrs.map_state = IsUnmapped;
|
||||
attrs.override_redirect = False;
|
||||
|
||||
/* XXX: Note: In the Wayland case we currently still trap X errors while
|
||||
* creating a MetaWindow because we will still be making various redundant
|
||||
* X requests (passing a window xid of None) until we thoroughly audit all
|
||||
* the code to make sure it knows about non X based clients...
|
||||
*/
|
||||
meta_x11_error_trap_push (display->x11_display); /* Push a trap over all of window
|
||||
* creation, to reduce XSync() calls
|
||||
*/
|
||||
|
||||
window = _meta_window_shared_new (display,
|
||||
META_WINDOW_CLIENT_TYPE_WAYLAND,
|
||||
surface,
|
||||
None,
|
||||
WithdrawnState,
|
||||
META_COMP_EFFECT_CREATE,
|
||||
&attrs);
|
||||
|
||||
meta_x11_error_trap_pop (display->x11_display); /* pop the XSync()-reducing trap */
|
||||
|
||||
return window;
|
||||
return _meta_window_shared_new (display,
|
||||
META_WINDOW_CLIENT_TYPE_WAYLAND,
|
||||
surface,
|
||||
None,
|
||||
WithdrawnState,
|
||||
META_COMP_EFFECT_CREATE,
|
||||
&attrs);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -465,32 +465,27 @@ on_displayfd_ready (int fd,
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_xwayland_start (MetaXWaylandManager *manager,
|
||||
struct wl_display *wl_display)
|
||||
static gboolean
|
||||
meta_xwayland_init_xserver (MetaXWaylandManager *manager)
|
||||
{
|
||||
int xwayland_client_fd[2];
|
||||
int displayfd[2];
|
||||
gboolean started = FALSE;
|
||||
g_autoptr(GSubprocessLauncher) launcher = NULL;
|
||||
GSubprocessFlags flags;
|
||||
GError *error = NULL;
|
||||
|
||||
if (!choose_xdisplay (manager))
|
||||
goto out;
|
||||
|
||||
/* We want xwayland to be a wayland client so we make a socketpair to setup a
|
||||
* wayland protocol connection. */
|
||||
if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, xwayland_client_fd) < 0)
|
||||
{
|
||||
g_warning ("xwayland_client_fd socketpair failed\n");
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, displayfd) < 0)
|
||||
{
|
||||
g_warning ("displayfd socketpair failed\n");
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* xwayland, please. */
|
||||
@ -511,16 +506,10 @@ meta_xwayland_start (MetaXWaylandManager *manager,
|
||||
|
||||
g_subprocess_launcher_setenv (launcher, "WAYLAND_SOCKET", "3", TRUE);
|
||||
|
||||
/* Use the -terminate parameter to ensure that Xwayland exits cleanly
|
||||
* after the last client disconnects. Fortunately that includes the window
|
||||
* manager so it won't exit prematurely either. This ensures that Xwayland
|
||||
* won't try to reconnect and crash, leaving uninteresting core dumps. We do
|
||||
* want core dumps from Xwayland but only if a real bug occurs...
|
||||
*/
|
||||
manager->proc = g_subprocess_launcher_spawn (launcher, &error,
|
||||
XWAYLAND_PATH, manager->display_name,
|
||||
"-rootless",
|
||||
"-terminate",
|
||||
"-noreset",
|
||||
"-accessx",
|
||||
"-core",
|
||||
"-listen", "4",
|
||||
@ -530,14 +519,15 @@ meta_xwayland_start (MetaXWaylandManager *manager,
|
||||
if (!manager->proc)
|
||||
{
|
||||
g_error ("Failed to spawn Xwayland: %s", error->message);
|
||||
goto out;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
manager->xserver_died_cancellable = g_cancellable_new ();
|
||||
g_subprocess_wait_async (manager->proc, manager->xserver_died_cancellable,
|
||||
xserver_died, NULL);
|
||||
g_unix_fd_add (displayfd[0], G_IO_IN, on_displayfd_ready, manager);
|
||||
manager->client = wl_client_create (wl_display, xwayland_client_fd[0]);
|
||||
manager->client = wl_client_create (manager->wayland_display,
|
||||
xwayland_client_fd[0]);
|
||||
|
||||
/* We need to run a mainloop until we know xwayland has a binding
|
||||
* for our xserver interface at which point we can assume it's
|
||||
@ -545,15 +535,18 @@ meta_xwayland_start (MetaXWaylandManager *manager,
|
||||
manager->init_loop = g_main_loop_new (NULL, FALSE);
|
||||
g_main_loop_run (manager->init_loop);
|
||||
|
||||
started = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
out:
|
||||
if (!started)
|
||||
{
|
||||
unlink (manager->lock_file);
|
||||
g_clear_pointer (&manager->lock_file, g_free);
|
||||
}
|
||||
return started;
|
||||
gboolean
|
||||
meta_xwayland_start (MetaXWaylandManager *manager,
|
||||
struct wl_display *wl_display)
|
||||
{
|
||||
if (!choose_xdisplay (manager))
|
||||
return FALSE;
|
||||
|
||||
manager->wayland_display = wl_display;
|
||||
return meta_xwayland_init_xserver (manager);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -803,14 +803,15 @@ handle_window_focus_event (MetaX11Display *x11_display,
|
||||
* multiple focus events with the same serial.
|
||||
*/
|
||||
if (x11_display->server_focus_serial > x11_display->focus_serial ||
|
||||
(!display->focused_by_us &&
|
||||
(!x11_display->focused_by_us &&
|
||||
x11_display->server_focus_serial == x11_display->focus_serial))
|
||||
{
|
||||
meta_display_update_focus_window (display,
|
||||
focus_window,
|
||||
focus_window ? focus_window->xwindow : None,
|
||||
x11_display->server_focus_serial,
|
||||
FALSE);
|
||||
meta_display_update_focus_window (display, focus_window);
|
||||
meta_x11_display_update_focus_window (x11_display,
|
||||
focus_window ?
|
||||
focus_window->xwindow : None,
|
||||
x11_display->server_focus_serial,
|
||||
FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
@ -882,7 +883,7 @@ handle_input_xevent (MetaX11Display *x11_display,
|
||||
enter_event->mode != XINotifyGrab &&
|
||||
enter_event->mode != XINotifyUngrab &&
|
||||
enter_event->detail != XINotifyInferior &&
|
||||
meta_display_focus_sentinel_clear (display))
|
||||
meta_x11_display_focus_sentinel_clear (x11_display))
|
||||
{
|
||||
meta_window_handle_enter (window,
|
||||
enter_event->time,
|
||||
@ -1525,7 +1526,7 @@ handle_other_xevent (MetaX11Display *x11_display,
|
||||
if (event->xproperty.atom ==
|
||||
x11_display->atom__MUTTER_SENTINEL)
|
||||
{
|
||||
meta_display_decrement_focus_sentinel (display);
|
||||
meta_x11_display_decrement_focus_sentinel (x11_display);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1792,7 +1793,7 @@ meta_x11_display_handle_xevent (MetaX11Display *x11_display,
|
||||
if (META_IS_BACKEND_X11 (backend))
|
||||
meta_backend_x11_handle_event (META_BACKEND_X11 (backend), event);
|
||||
|
||||
if (display->focused_by_us &&
|
||||
if (x11_display->focused_by_us &&
|
||||
event->xany.serial > x11_display->focus_serial &&
|
||||
display->focus_window &&
|
||||
!window_has_xwindow (display->focus_window, x11_display->server_focus_window))
|
||||
@ -1801,10 +1802,11 @@ meta_x11_display_handle_xevent (MetaX11Display *x11_display,
|
||||
display->focus_window->desc);
|
||||
meta_display_update_focus_window (display,
|
||||
meta_x11_display_lookup_x_window (x11_display,
|
||||
x11_display->server_focus_window),
|
||||
x11_display->server_focus_window,
|
||||
x11_display->server_focus_serial,
|
||||
FALSE);
|
||||
x11_display->server_focus_window));
|
||||
meta_x11_display_update_focus_window (x11_display,
|
||||
x11_display->server_focus_window,
|
||||
x11_display->server_focus_serial,
|
||||
FALSE);
|
||||
}
|
||||
|
||||
if (event->xany.window == x11_display->xroot)
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "meta/types.h"
|
||||
#include "meta/meta-x11-display.h"
|
||||
#include "meta-startup-notification-x11.h"
|
||||
#include "meta-x11-stack-private.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
typedef struct _MetaGroupPropHooks MetaGroupPropHooks;
|
||||
@ -133,8 +134,21 @@ struct _MetaX11Display
|
||||
GList *output_streams;
|
||||
} selection;
|
||||
|
||||
/* If true, server->focus_serial refers to us changing the focus; in
|
||||
* this case, we can ignore focus events that have exactly focus_serial,
|
||||
* since we take care to make another request immediately afterwards.
|
||||
* But if focus is being changed by another client, we have to accept
|
||||
* multiple events with the same serial.
|
||||
*/
|
||||
guint focused_by_us : 1;
|
||||
|
||||
guint keys_grabbed : 1;
|
||||
|
||||
/* we use property updates as sentinels for certain window focus events
|
||||
* to avoid some race conditions on EnterNotify events
|
||||
*/
|
||||
int sentinel_counter;
|
||||
|
||||
int composite_event_base;
|
||||
int composite_error_base;
|
||||
int composite_major_version;
|
||||
@ -162,6 +176,7 @@ struct _MetaX11Display
|
||||
#define META_X11_DISPLAY_HAS_XINPUT_23(x11_display) ((x11_display)->have_xinput_23)
|
||||
|
||||
MetaX11StartupNotification *startup_notification;
|
||||
MetaX11Stack *x11_stack;
|
||||
};
|
||||
|
||||
MetaX11Display *meta_x11_display_new (MetaDisplay *display, GError **error);
|
||||
@ -222,4 +237,16 @@ MetaLogicalMonitor *meta_x11_display_xinerama_index_to_logical_monitor (MetaX11D
|
||||
void meta_x11_display_update_workspace_layout (MetaX11Display *x11_display);
|
||||
void meta_x11_display_update_workspace_names (MetaX11Display *x11_display);
|
||||
|
||||
void meta_x11_display_increment_focus_sentinel (MetaX11Display *x11_display);
|
||||
void meta_x11_display_decrement_focus_sentinel (MetaX11Display *x11_display);
|
||||
gboolean meta_x11_display_focus_sentinel_clear (MetaX11Display *x11_display);
|
||||
|
||||
void meta_x11_display_update_focus_window (MetaX11Display *x11_display,
|
||||
Window xwindow,
|
||||
gulong serial,
|
||||
gboolean focused_by_us);
|
||||
void meta_x11_display_set_input_focus (MetaX11Display *x11_display,
|
||||
Window xwindow,
|
||||
guint32 timestamp);
|
||||
|
||||
#endif /* META_X11_DISPLAY_PRIVATE_H */
|
||||
|
@ -95,6 +95,27 @@ static void unset_wm_check_hint (MetaX11Display *x11_display);
|
||||
static void prefs_changed_callback (MetaPreference pref,
|
||||
void *data);
|
||||
|
||||
static void
|
||||
meta_x11_display_unmanage_windows (MetaX11Display *x11_display)
|
||||
{
|
||||
GList *windows, *l;
|
||||
MetaWindow *window;
|
||||
|
||||
if (!x11_display->xids)
|
||||
return;
|
||||
|
||||
windows = g_hash_table_get_values (x11_display->xids);
|
||||
g_list_foreach (windows, (GFunc) g_object_ref, NULL);
|
||||
|
||||
for (l = windows; l; l = l->next)
|
||||
{
|
||||
window = l->data;
|
||||
if (!window->unmanaging)
|
||||
meta_window_unmanage (window, META_CURRENT_TIME);
|
||||
}
|
||||
g_list_free_full (windows, g_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_x11_display_dispose (GObject *object)
|
||||
{
|
||||
@ -107,6 +128,9 @@ meta_x11_display_dispose (GObject *object)
|
||||
meta_x11_display_ungrab_keys (x11_display);
|
||||
|
||||
meta_x11_selection_shutdown (x11_display);
|
||||
meta_x11_display_unmanage_windows (x11_display);
|
||||
|
||||
g_clear_object (&x11_display->x11_stack);
|
||||
|
||||
if (x11_display->ui)
|
||||
{
|
||||
@ -466,6 +490,13 @@ init_x11_bell (MetaX11Display *x11_display)
|
||||
&mask);
|
||||
}
|
||||
}
|
||||
|
||||
/* We are playing sounds using libcanberra support, we handle the
|
||||
* bell whether its an audible bell or a visible bell */
|
||||
XkbChangeEnabledControls (x11_display->xdisplay,
|
||||
XkbUseCoreKbd,
|
||||
XkbAudibleBellMask,
|
||||
0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -483,32 +514,6 @@ shutdown_x11_bell (MetaX11Display *x11_display)
|
||||
XkbAudibleBellMask);
|
||||
}
|
||||
|
||||
/*
|
||||
* Turns the bell to audible or visual. This tells X what to do, but
|
||||
* not Mutter; you will need to set the "visual bell" pref for that.
|
||||
*/
|
||||
static void
|
||||
set_x11_bell_is_audible (MetaX11Display *x11_display,
|
||||
gboolean is_audible)
|
||||
{
|
||||
/* When we are playing sounds using libcanberra support, we handle the
|
||||
* bell whether its an audible bell or a visible bell */
|
||||
gboolean enable_system_bell = FALSE;
|
||||
|
||||
XkbChangeEnabledControls (x11_display->xdisplay,
|
||||
XkbUseCoreKbd,
|
||||
XkbAudibleBellMask,
|
||||
enable_system_bell ? XkbAudibleBellMask : 0);
|
||||
}
|
||||
|
||||
static void
|
||||
on_is_audible_changed (MetaBell *bell,
|
||||
gboolean is_audible,
|
||||
MetaX11Display *x11_display)
|
||||
{
|
||||
set_x11_bell_is_audible (x11_display, is_audible);
|
||||
}
|
||||
|
||||
static void
|
||||
set_desktop_geometry_hint (MetaX11Display *x11_display)
|
||||
{
|
||||
@ -1086,6 +1091,9 @@ meta_x11_display_new (MetaDisplay *display, GError **error)
|
||||
};
|
||||
Atom atoms[G_N_ELEMENTS(atom_names)];
|
||||
|
||||
if (!meta_x11_init_gdk_display (error))
|
||||
return NULL;
|
||||
|
||||
g_assert (prepared_gdk_display);
|
||||
gdk_display = g_steal_pointer (&prepared_gdk_display);
|
||||
|
||||
@ -1270,6 +1278,7 @@ meta_x11_display_new (MetaDisplay *display, GError **error)
|
||||
set_desktop_geometry_hint (x11_display);
|
||||
|
||||
x11_display->ui = meta_ui_new (x11_display);
|
||||
x11_display->x11_stack = meta_x11_stack_new (x11_display);
|
||||
|
||||
x11_display->keys_grabbed = FALSE;
|
||||
meta_x11_display_grab_keys (x11_display);
|
||||
@ -1323,12 +1332,6 @@ meta_x11_display_new (MetaDisplay *display, GError **error)
|
||||
|
||||
init_x11_bell (x11_display);
|
||||
|
||||
g_signal_connect_object (display->bell, "is-audible-changed",
|
||||
G_CALLBACK (on_is_audible_changed),
|
||||
x11_display, 0);
|
||||
|
||||
set_x11_bell_is_audible (x11_display, meta_prefs_bell_is_audible ());
|
||||
|
||||
meta_x11_startup_notification_init (x11_display);
|
||||
meta_x11_selection_init (x11_display);
|
||||
|
||||
@ -1819,17 +1822,27 @@ meta_x11_display_update_active_window_hint (MetaX11Display *x11_display)
|
||||
meta_x11_error_trap_pop (x11_display);
|
||||
}
|
||||
|
||||
static void
|
||||
request_xserver_input_focus_change (MetaX11Display *x11_display,
|
||||
MetaWindow *meta_window,
|
||||
Window xwindow,
|
||||
guint32 timestamp)
|
||||
void
|
||||
meta_x11_display_update_focus_window (MetaX11Display *x11_display,
|
||||
Window xwindow,
|
||||
gulong serial,
|
||||
gboolean focused_by_us)
|
||||
{
|
||||
gulong serial;
|
||||
x11_display->focus_serial = serial;
|
||||
x11_display->focused_by_us = !!focused_by_us;
|
||||
|
||||
if (meta_display_timestamp_too_old (x11_display->display, ×tamp))
|
||||
if (x11_display->focus_xwindow == xwindow)
|
||||
return;
|
||||
|
||||
x11_display->focus_xwindow = xwindow;
|
||||
meta_x11_display_update_active_window_hint (x11_display);
|
||||
}
|
||||
|
||||
void
|
||||
meta_x11_display_set_input_focus (MetaX11Display *x11_display,
|
||||
Window xwindow,
|
||||
guint32 timestamp)
|
||||
{
|
||||
meta_x11_error_trap_push (x11_display);
|
||||
|
||||
/* In order for mutter to know that the focus request succeeded, we track
|
||||
@ -1842,8 +1855,6 @@ request_xserver_input_focus_change (MetaX11Display *x11_display,
|
||||
*/
|
||||
XGrabServer (x11_display->xdisplay);
|
||||
|
||||
serial = XNextRequest (x11_display->xdisplay);
|
||||
|
||||
XSetInputFocus (x11_display->xdisplay,
|
||||
xwindow,
|
||||
RevertToPointerRoot,
|
||||
@ -1857,30 +1868,7 @@ request_xserver_input_focus_change (MetaX11Display *x11_display,
|
||||
XUngrabServer (x11_display->xdisplay);
|
||||
XFlush (x11_display->xdisplay);
|
||||
|
||||
meta_display_update_focus_window (x11_display->display,
|
||||
meta_window,
|
||||
xwindow,
|
||||
serial,
|
||||
TRUE);
|
||||
|
||||
meta_x11_error_trap_pop (x11_display);
|
||||
|
||||
x11_display->display->last_focus_time = timestamp;
|
||||
|
||||
if (meta_window == NULL || meta_window != x11_display->display->autoraise_window)
|
||||
meta_display_remove_autoraise_callback (x11_display->display);
|
||||
}
|
||||
|
||||
void
|
||||
meta_x11_display_set_input_focus_window (MetaX11Display *x11_display,
|
||||
MetaWindow *window,
|
||||
gboolean focus_frame,
|
||||
guint32 timestamp)
|
||||
{
|
||||
request_xserver_input_focus_change (x11_display,
|
||||
window,
|
||||
focus_frame ? window->frame->xwindow : window->xwindow,
|
||||
timestamp);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1888,20 +1876,12 @@ meta_x11_display_set_input_focus_xwindow (MetaX11Display *x11_display,
|
||||
Window window,
|
||||
guint32 timestamp)
|
||||
{
|
||||
request_xserver_input_focus_change (x11_display,
|
||||
NULL,
|
||||
window,
|
||||
timestamp);
|
||||
}
|
||||
gulong serial;
|
||||
|
||||
void
|
||||
meta_x11_display_focus_the_no_focus_window (MetaX11Display *x11_display,
|
||||
guint32 timestamp)
|
||||
{
|
||||
request_xserver_input_focus_change (x11_display,
|
||||
NULL,
|
||||
x11_display->no_focus_window,
|
||||
timestamp);
|
||||
meta_display_unset_input_focus (x11_display->display, timestamp);
|
||||
serial = XNextRequest (x11_display->xdisplay);
|
||||
meta_x11_display_set_input_focus (x11_display, window, timestamp);
|
||||
meta_x11_display_update_focus_window (x11_display, window, serial, TRUE);
|
||||
}
|
||||
|
||||
static MetaX11DisplayLogicalMonitorData *
|
||||
@ -2177,3 +2157,34 @@ prefs_changed_callback (MetaPreference pref,
|
||||
set_workspace_names (x11_display);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_x11_display_increment_focus_sentinel (MetaX11Display *x11_display)
|
||||
{
|
||||
unsigned long data[1];
|
||||
|
||||
data[0] = meta_display_get_current_time (x11_display->display);
|
||||
|
||||
XChangeProperty (x11_display->xdisplay,
|
||||
x11_display->xroot,
|
||||
x11_display->atom__MUTTER_SENTINEL,
|
||||
XA_CARDINAL,
|
||||
32, PropModeReplace, (guchar*) data, 1);
|
||||
|
||||
x11_display->sentinel_counter += 1;
|
||||
}
|
||||
|
||||
void
|
||||
meta_x11_display_decrement_focus_sentinel (MetaX11Display *x11_display)
|
||||
{
|
||||
x11_display->sentinel_counter -= 1;
|
||||
|
||||
if (x11_display->sentinel_counter < 0)
|
||||
x11_display->sentinel_counter = 0;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_x11_display_focus_sentinel_clear (MetaX11Display *x11_display)
|
||||
{
|
||||
return (x11_display->sentinel_counter == 0);
|
||||
}
|
||||
|
33
src/x11/meta-x11-stack-private.h
Normal file
33
src/x11/meta-x11-stack-private.h
Normal file
@ -0,0 +1,33 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* Copyright (C) 2019 Red Hat, Inc
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef META_X11_STACK_H
|
||||
#define META_X11_STACK_H
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "meta/types.h"
|
||||
|
||||
#define META_TYPE_X11_STACK (meta_x11_stack_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (MetaX11Stack, meta_x11_stack, META, X11_STACK, GObject)
|
||||
|
||||
typedef struct _MetaX11Stack MetaX11Stack;
|
||||
|
||||
MetaX11Stack * meta_x11_stack_new (MetaX11Display *x11_display);
|
||||
|
||||
#endif /* META_X11_STACK_H */
|
413
src/x11/meta-x11-stack.c
Normal file
413
src/x11/meta-x11-stack.c
Normal file
@ -0,0 +1,413 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* Copyright (C) 2019 Red Hat, Inc
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "core/frame.h"
|
||||
#include "core/stack.h"
|
||||
#include "core/window-private.h"
|
||||
#include "x11/meta-x11-display-private.h"
|
||||
#include "x11/meta-x11-stack-private.h"
|
||||
|
||||
struct _MetaX11Stack
|
||||
{
|
||||
GObject parent;
|
||||
MetaX11Display *x11_display;
|
||||
|
||||
/*
|
||||
* A sequence of all the Windows (X handles, not MetaWindows) of the windows
|
||||
* we manage, sorted in order. Suitable to be passed into _NET_CLIENT_LIST.
|
||||
*/
|
||||
GArray *xwindows;
|
||||
|
||||
/*
|
||||
* MetaWindows waiting to be added to the xwindows list, after
|
||||
* being added to the MetaStack.
|
||||
*
|
||||
* The order of the elements in this list is not important; what is important
|
||||
* is the stack_position element of each window.
|
||||
*/
|
||||
GList *added;
|
||||
|
||||
/*
|
||||
* Windows (X handles, not MetaWindows) waiting to be removed from the
|
||||
* xwindows list, after being removed from the MetaStack.
|
||||
*
|
||||
* The order of the elements in this list is not important.
|
||||
*/
|
||||
GList *removed;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_DISPLAY = 1,
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
static GParamSpec *pspecs[N_PROPS] = { 0 };
|
||||
|
||||
G_DEFINE_TYPE (MetaX11Stack, meta_x11_stack, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
meta_x11_stack_init (MetaX11Stack *x11_stack)
|
||||
{
|
||||
x11_stack->xwindows = g_array_new (FALSE, FALSE, sizeof (Window));
|
||||
}
|
||||
|
||||
static void
|
||||
meta_x11_stack_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaX11Stack *x11_stack = META_X11_STACK (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DISPLAY:
|
||||
x11_stack->x11_display = g_value_get_object (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_x11_stack_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaX11Stack *x11_stack = META_X11_STACK (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DISPLAY:
|
||||
g_value_set_object (value, x11_stack->x11_display);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
stack_window_added_cb (MetaStack *stack,
|
||||
MetaWindow *window,
|
||||
MetaX11Stack *x11_stack)
|
||||
{
|
||||
if (window->client_type != META_WINDOW_CLIENT_TYPE_X11)
|
||||
return;
|
||||
|
||||
x11_stack->added = g_list_prepend (x11_stack->added, window);
|
||||
}
|
||||
|
||||
static void
|
||||
stack_window_removed_cb (MetaStack *stack,
|
||||
MetaWindow *window,
|
||||
MetaX11Stack *x11_stack)
|
||||
{
|
||||
if (window->client_type != META_WINDOW_CLIENT_TYPE_X11)
|
||||
return;
|
||||
|
||||
x11_stack->added = g_list_remove (x11_stack->added, window);
|
||||
|
||||
x11_stack->removed = g_list_prepend (x11_stack->removed,
|
||||
GUINT_TO_POINTER (window->xwindow));
|
||||
if (window->frame)
|
||||
{
|
||||
x11_stack->removed = g_list_prepend (x11_stack->removed,
|
||||
GUINT_TO_POINTER (window->frame->xwindow));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* stack_do_window_deletions:
|
||||
*
|
||||
* Go through "deleted" and take the matching windows
|
||||
* out of "windows".
|
||||
*/
|
||||
static void
|
||||
x11_stack_do_window_deletions (MetaX11Stack *x11_stack)
|
||||
{
|
||||
GList *tmp;
|
||||
int i;
|
||||
|
||||
tmp = x11_stack->removed;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
Window xwindow;
|
||||
xwindow = GPOINTER_TO_UINT (tmp->data);
|
||||
|
||||
/* We go from the end figuring removals are more
|
||||
* likely to be recent.
|
||||
*/
|
||||
i = x11_stack->xwindows->len;
|
||||
while (i > 0)
|
||||
{
|
||||
--i;
|
||||
|
||||
/* there's no guarantee we'll actually find windows to
|
||||
* remove, e.g. the same xwindow could have been
|
||||
* added/removed before we ever synced, and we put
|
||||
* both the window->xwindow and window->frame->xwindow
|
||||
* in the removal list.
|
||||
*/
|
||||
if (xwindow == g_array_index (x11_stack->xwindows, Window, i))
|
||||
{
|
||||
g_array_remove_index (x11_stack->xwindows, i);
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
|
||||
next:
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
g_clear_pointer (&x11_stack->removed, g_list_free);
|
||||
}
|
||||
|
||||
static void
|
||||
x11_stack_do_window_additions (MetaX11Stack *x11_stack)
|
||||
{
|
||||
GList *tmp;
|
||||
gint n_added;
|
||||
|
||||
n_added = g_list_length (x11_stack->added);
|
||||
if (n_added > 0)
|
||||
{
|
||||
meta_topic (META_DEBUG_STACK,
|
||||
"Adding %d windows to sorted list\n",
|
||||
n_added);
|
||||
|
||||
/* stack->added has the most recent additions at the
|
||||
* front of the list, so we need to reverse it
|
||||
*/
|
||||
x11_stack->added = g_list_reverse (x11_stack->added);
|
||||
|
||||
tmp = x11_stack->added;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MetaWindow *w;
|
||||
|
||||
w = tmp->data;
|
||||
g_array_append_val (x11_stack->xwindows, w->xwindow);
|
||||
tmp = tmp->next;
|
||||
}
|
||||
}
|
||||
|
||||
g_clear_pointer (&x11_stack->added, g_list_free);
|
||||
}
|
||||
|
||||
/**
|
||||
* x11_stack_sync_to_server:
|
||||
*
|
||||
* Order the windows on the X server to be the same as in our structure.
|
||||
* We do this using XRestackWindows if we don't know the previous order,
|
||||
* or XConfigureWindow on a few particular windows if we do and can figure
|
||||
* out the minimum set of changes. After that, we set __NET_CLIENT_LIST
|
||||
* and __NET_CLIENT_LIST_STACKING.
|
||||
*
|
||||
* FIXME: Now that we have a good view of the stacking order on the server
|
||||
* with MetaStackTracker it should be possible to do a simpler and better
|
||||
* job of computing the minimal set of stacking requests needed.
|
||||
*/
|
||||
static void
|
||||
x11_stack_sync_to_xserver (MetaX11Stack *x11_stack)
|
||||
{
|
||||
MetaX11Display *x11_display = x11_stack->x11_display;
|
||||
MetaStack *stack = x11_display->display->stack;
|
||||
GArray *x11_stacked;
|
||||
GArray *all_root_children_stacked; /* wayland OR x11 */
|
||||
GList *tmp;
|
||||
GArray *hidden_stack_ids;
|
||||
uint64_t guard_window_id;
|
||||
GList *sorted;
|
||||
|
||||
meta_topic (META_DEBUG_STACK, "Syncing window stack to server\n");
|
||||
|
||||
/* Create stacked xwindow arrays, in bottom-to-top order
|
||||
*/
|
||||
x11_stacked = g_array_new (FALSE, FALSE, sizeof (Window));
|
||||
|
||||
all_root_children_stacked = g_array_new (FALSE, FALSE, sizeof (guint64));
|
||||
hidden_stack_ids = g_array_new (FALSE, FALSE, sizeof (guint64));
|
||||
|
||||
meta_topic (META_DEBUG_STACK, "Bottom to top: ");
|
||||
meta_push_no_msg_prefix ();
|
||||
|
||||
sorted = meta_stack_list_windows (stack, NULL);
|
||||
|
||||
for (tmp = sorted; tmp; tmp = tmp->next)
|
||||
{
|
||||
MetaWindow *w = tmp->data;
|
||||
guint64 top_level_window;
|
||||
guint64 stack_id;
|
||||
|
||||
if (w->unmanaging)
|
||||
continue;
|
||||
|
||||
meta_topic (META_DEBUG_STACK, "%u:%d - %s ",
|
||||
w->layer, w->stack_position, w->desc);
|
||||
|
||||
if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
g_array_append_val (x11_stacked, w->xwindow);
|
||||
|
||||
if (w->frame)
|
||||
top_level_window = w->frame->xwindow;
|
||||
else
|
||||
top_level_window = w->xwindow;
|
||||
|
||||
if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
stack_id = top_level_window;
|
||||
else
|
||||
stack_id = w->stamp;
|
||||
|
||||
/* We don't restack hidden windows along with the rest, though they are
|
||||
* reflected in the _NET hints. Hidden windows all get pushed below
|
||||
* the screens fullscreen guard_window. */
|
||||
if (w->hidden)
|
||||
{
|
||||
g_array_append_val (hidden_stack_ids, stack_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
g_array_append_val (all_root_children_stacked, stack_id);
|
||||
}
|
||||
|
||||
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. */
|
||||
guard_window_id = x11_stack->x11_display->guard_window;
|
||||
g_array_append_val (hidden_stack_ids, guard_window_id);
|
||||
|
||||
/* Sync to server */
|
||||
|
||||
meta_topic (META_DEBUG_STACK, "Restacking %u windows\n",
|
||||
all_root_children_stacked->len);
|
||||
|
||||
meta_stack_tracker_restack_managed (x11_display->display->stack_tracker,
|
||||
(guint64 *)all_root_children_stacked->data,
|
||||
all_root_children_stacked->len);
|
||||
meta_stack_tracker_restack_at_bottom (x11_display->display->stack_tracker,
|
||||
(guint64 *)hidden_stack_ids->data,
|
||||
hidden_stack_ids->len);
|
||||
|
||||
/* Sync _NET_CLIENT_LIST and _NET_CLIENT_LIST_STACKING */
|
||||
|
||||
XChangeProperty (x11_stack->x11_display->xdisplay,
|
||||
x11_stack->x11_display->xroot,
|
||||
x11_stack->x11_display->atom__NET_CLIENT_LIST,
|
||||
XA_WINDOW,
|
||||
32, PropModeReplace,
|
||||
(unsigned char *) x11_stack->xwindows->data,
|
||||
x11_stack->xwindows->len);
|
||||
XChangeProperty (x11_stack->x11_display->xdisplay,
|
||||
x11_stack->x11_display->xroot,
|
||||
x11_stack->x11_display->atom__NET_CLIENT_LIST_STACKING,
|
||||
XA_WINDOW,
|
||||
32, PropModeReplace,
|
||||
(unsigned char *) x11_stacked->data,
|
||||
x11_stacked->len);
|
||||
|
||||
g_array_free (x11_stacked, TRUE);
|
||||
g_array_free (hidden_stack_ids, TRUE);
|
||||
g_array_free (all_root_children_stacked, TRUE);
|
||||
g_list_free (sorted);
|
||||
}
|
||||
|
||||
static void
|
||||
stack_changed_cb (MetaX11Stack *x11_stack)
|
||||
{
|
||||
/* Do removals before adds, with paranoid idea that we might re-add
|
||||
* the same window IDs.
|
||||
*/
|
||||
x11_stack_do_window_deletions (x11_stack);
|
||||
x11_stack_do_window_additions (x11_stack);
|
||||
x11_stack_sync_to_xserver (x11_stack);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_x11_stack_constructed (GObject *object)
|
||||
{
|
||||
MetaX11Stack *x11_stack = META_X11_STACK (object);
|
||||
MetaX11Display *x11_display = x11_stack->x11_display;
|
||||
|
||||
G_OBJECT_CLASS (meta_x11_stack_parent_class)->constructed (object);
|
||||
|
||||
g_signal_connect (x11_display->display->stack,
|
||||
"window-added",
|
||||
G_CALLBACK (stack_window_added_cb),
|
||||
x11_stack);
|
||||
g_signal_connect (x11_display->display->stack,
|
||||
"window-removed",
|
||||
G_CALLBACK (stack_window_removed_cb),
|
||||
x11_stack);
|
||||
g_signal_connect_swapped (x11_display->display->stack,
|
||||
"changed",
|
||||
G_CALLBACK (stack_changed_cb),
|
||||
x11_stack);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_x11_stack_finalize (GObject *object)
|
||||
{
|
||||
MetaX11Stack *x11_stack = META_X11_STACK (object);
|
||||
MetaX11Display *x11_display = x11_stack->x11_display;
|
||||
|
||||
if (x11_display->display && x11_display->display->stack)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_data (x11_display->display->stack,
|
||||
x11_stack);
|
||||
}
|
||||
|
||||
g_array_free (x11_stack->xwindows, TRUE);
|
||||
g_list_free (x11_stack->added);
|
||||
g_list_free (x11_stack->removed);
|
||||
|
||||
G_OBJECT_CLASS (meta_x11_stack_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_x11_stack_class_init (MetaX11StackClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->set_property = meta_x11_stack_set_property;
|
||||
object_class->get_property = meta_x11_stack_get_property;
|
||||
object_class->constructed = meta_x11_stack_constructed;
|
||||
object_class->finalize = meta_x11_stack_finalize;
|
||||
|
||||
pspecs[PROP_DISPLAY] =
|
||||
g_param_spec_object ("display",
|
||||
"Display",
|
||||
"Display",
|
||||
META_TYPE_X11_DISPLAY,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPS, pspecs);
|
||||
}
|
||||
|
||||
MetaX11Stack *
|
||||
meta_x11_stack_new (MetaX11Display *x11_display)
|
||||
{
|
||||
return g_object_new (META_TYPE_X11_STACK,
|
||||
"display", x11_display,
|
||||
NULL);
|
||||
}
|
@ -794,10 +794,10 @@ meta_window_x11_focus (MetaWindow *window,
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focusing frame of %s\n", window->desc);
|
||||
meta_x11_display_set_input_focus_window (window->display->x11_display,
|
||||
window,
|
||||
TRUE,
|
||||
timestamp);
|
||||
meta_display_set_input_focus (window->display,
|
||||
window,
|
||||
TRUE,
|
||||
timestamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -806,10 +806,10 @@ meta_window_x11_focus (MetaWindow *window,
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Setting input focus on %s since input = true\n",
|
||||
window->desc);
|
||||
meta_x11_display_set_input_focus_window (window->display->x11_display,
|
||||
window,
|
||||
FALSE,
|
||||
timestamp);
|
||||
meta_display_set_input_focus (window->display,
|
||||
window,
|
||||
FALSE,
|
||||
timestamp);
|
||||
}
|
||||
|
||||
if (priv->wm_take_focus)
|
||||
@ -832,8 +832,7 @@ meta_window_x11_focus (MetaWindow *window,
|
||||
*/
|
||||
if (window->display->focus_window != NULL &&
|
||||
window->display->focus_window->unmanaging)
|
||||
meta_x11_display_focus_the_no_focus_window (window->display->x11_display,
|
||||
timestamp);
|
||||
meta_display_unset_input_focus (window->display, timestamp);
|
||||
}
|
||||
|
||||
request_take_focus (window, timestamp);
|
||||
@ -1706,6 +1705,27 @@ meta_window_x11_are_updates_frozen (MetaWindow *window)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_x11_map (MetaWindow *window)
|
||||
{
|
||||
MetaX11Display *x11_display = window->display->x11_display;
|
||||
|
||||
meta_x11_error_trap_push (x11_display);
|
||||
XMapWindow (x11_display->xdisplay, window->xwindow);
|
||||
meta_x11_error_trap_pop (x11_display);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_x11_unmap (MetaWindow *window)
|
||||
{
|
||||
MetaX11Display *x11_display = window->display->x11_display;
|
||||
|
||||
meta_x11_error_trap_push (x11_display);
|
||||
XUnmapWindow (x11_display->xdisplay, window->xwindow);
|
||||
meta_x11_error_trap_pop (x11_display);
|
||||
window->unmaps_pending ++;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_x11_class_init (MetaWindowX11Class *klass)
|
||||
{
|
||||
@ -1733,6 +1753,8 @@ meta_window_x11_class_init (MetaWindowX11Class *klass)
|
||||
window_class->is_stackable = meta_window_x11_is_stackable;
|
||||
window_class->can_ping = meta_window_x11_can_ping;
|
||||
window_class->are_updates_frozen = meta_window_x11_are_updates_frozen;
|
||||
window_class->map = meta_window_x11_map;
|
||||
window_class->unmap = meta_window_x11_unmap;
|
||||
}
|
||||
|
||||
void
|
||||
|
Reference in New Issue
Block a user