Compare commits
59 Commits
dcvviewer
...
gnome-3-32
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c2e12b3434 | ||
![]() |
002299fbef | ||
![]() |
f0b7cf4d91 | ||
![]() |
ad4dbefbc0 | ||
![]() |
5a486f5b6b | ||
![]() |
bb5c7b97ba | ||
![]() |
b7f1588119 | ||
![]() |
88e492cac0 | ||
![]() |
ed03ce53b2 | ||
![]() |
ccab0f470d | ||
![]() |
61691bacc8 | ||
![]() |
63f3f5d59f | ||
![]() |
80869e0737 | ||
![]() |
763092a4b6 | ||
![]() |
e50cdda4ff | ||
![]() |
c50df14311 | ||
![]() |
194d93efd8 | ||
![]() |
947da2c5d5 | ||
![]() |
0a8fbbe5cc | ||
![]() |
001076339a | ||
![]() |
0d570f2dd3 | ||
![]() |
c5fb1d1975 | ||
![]() |
83ce89ef59 | ||
![]() |
da3195288b | ||
![]() |
8b986cd065 | ||
![]() |
5efb11acad | ||
![]() |
2db94e2e40 | ||
![]() |
866d6780c9 | ||
![]() |
9009f8d48f | ||
![]() |
3d9771b25a | ||
![]() |
1be5a57ade | ||
![]() |
afcea966c0 | ||
![]() |
9c079a5261 | ||
![]() |
d56bd28f64 | ||
![]() |
225d18761a | ||
![]() |
e0922bffea | ||
![]() |
8307c0f7ab | ||
![]() |
cded69da61 | ||
![]() |
a3a97621be | ||
![]() |
8b79c83ad5 | ||
![]() |
2ce4a20c8e | ||
![]() |
fb03e198e5 | ||
![]() |
07c9cd498d | ||
![]() |
e716f9d143 | ||
![]() |
13a1624c10 | ||
![]() |
30d6e3abe2 | ||
![]() |
18e44bb64c | ||
![]() |
15803b9558 | ||
![]() |
3fdc651179 | ||
![]() |
189f71f5d1 | ||
![]() |
0a3cddeecf | ||
![]() |
ee92e4fe13 | ||
![]() |
6933ce0976 | ||
![]() |
f9d6627fe0 | ||
![]() |
668c44e66b | ||
![]() |
3495a43810 | ||
![]() |
9a795d3d0f | ||
![]() |
abc3fdcc65 | ||
![]() |
4705a31049 |
11
NEWS
11
NEWS
@@ -1,3 +1,14 @@
|
|||||||
|
3.32.2
|
||||||
|
======
|
||||||
|
* Disable mouse keys with Numlock on [Olivier; #530]
|
||||||
|
* Fix crash when restarting on X11 [Marco; #576]
|
||||||
|
* Fix mapping of touchscreens that don't report dimensions [Carlos; #581]
|
||||||
|
* Fix spurious idle signals that prevent session unblank [Jonas; !543]
|
||||||
|
* Misc. bug fixes and cleanups [Olivier, Marco, Carlos; !552, !557, #586]
|
||||||
|
|
||||||
|
Contributors:
|
||||||
|
Jonas Ådahl, Olivier Fourdan, Carlos Garnacho, Marco Trevisan (Treviño)
|
||||||
|
|
||||||
3.32.1
|
3.32.1
|
||||||
======
|
======
|
||||||
* Fix fallback app menu on wayland [Florian; #493]
|
* Fix fallback app menu on wayland [Florian; #493]
|
||||||
|
@@ -1975,6 +1975,7 @@ selection_paint (ClutterText *self,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Paint selection background first */
|
/* Paint selection background first */
|
||||||
|
CoglPipeline *color_pipeline = cogl_pipeline_copy (default_color_pipeline);
|
||||||
PangoLayout *layout = clutter_text_get_layout (self);
|
PangoLayout *layout = clutter_text_get_layout (self);
|
||||||
CoglPath *selection_path = cogl_path_new ();
|
CoglPath *selection_path = cogl_path_new ();
|
||||||
CoglColor cogl_color = { 0, };
|
CoglColor cogl_color = { 0, };
|
||||||
@@ -1987,11 +1988,19 @@ selection_paint (ClutterText *self,
|
|||||||
else
|
else
|
||||||
color = &priv->text_color;
|
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,
|
clutter_text_foreach_selection_rectangle_prescaled (self,
|
||||||
add_selection_rectangle_to_path,
|
add_selection_rectangle_to_path,
|
||||||
selection_path);
|
selection_path);
|
||||||
|
|
||||||
cogl_path_fill (selection_path);
|
cogl_framebuffer_fill_path (fb, color_pipeline, selection_path);
|
||||||
|
|
||||||
/* Paint selected text */
|
/* Paint selected text */
|
||||||
cogl_framebuffer_push_path_clip (fb, selection_path);
|
cogl_framebuffer_push_path_clip (fb, selection_path);
|
||||||
|
@@ -855,6 +855,14 @@ emulate_pointer_motion (ClutterInputDeviceEvdev *device,
|
|||||||
clutter_virtual_input_device_notify_relative_motion (device->mousekeys_virtual_device,
|
clutter_virtual_input_device_notify_relative_motion (device->mousekeys_virtual_device,
|
||||||
time_us, dx_motion, dy_motion);
|
time_us, dx_motion, dy_motion);
|
||||||
}
|
}
|
||||||
|
static gboolean
|
||||||
|
is_numlock_active (ClutterInputDeviceEvdev *device)
|
||||||
|
{
|
||||||
|
ClutterSeatEvdev *seat = device->seat;
|
||||||
|
return xkb_state_mod_name_is_active (seat->xkb,
|
||||||
|
"Mod2",
|
||||||
|
XKB_STATE_MODS_LOCKED);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
enable_mousekeys (ClutterInputDeviceEvdev *device)
|
enable_mousekeys (ClutterInputDeviceEvdev *device)
|
||||||
@@ -1013,6 +1021,10 @@ handle_mousekeys_press (ClutterEvent *event,
|
|||||||
if (!(event->key.flags & CLUTTER_EVENT_FLAG_SYNTHETIC))
|
if (!(event->key.flags & CLUTTER_EVENT_FLAG_SYNTHETIC))
|
||||||
stop_mousekeys_move (device);
|
stop_mousekeys_move (device);
|
||||||
|
|
||||||
|
/* Do not handle mousekeys if NumLock is ON */
|
||||||
|
if (is_numlock_active (device))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
/* Button selection */
|
/* Button selection */
|
||||||
switch (event->key.keyval)
|
switch (event->key.keyval)
|
||||||
{
|
{
|
||||||
@@ -1084,6 +1096,10 @@ static gboolean
|
|||||||
handle_mousekeys_release (ClutterEvent *event,
|
handle_mousekeys_release (ClutterEvent *event,
|
||||||
ClutterInputDeviceEvdev *device)
|
ClutterInputDeviceEvdev *device)
|
||||||
{
|
{
|
||||||
|
/* Do not handle mousekeys if NumLock is ON */
|
||||||
|
if (is_numlock_active (device))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
switch (event->key.keyval)
|
switch (event->key.keyval)
|
||||||
{
|
{
|
||||||
case XKB_KEY_KP_0:
|
case XKB_KEY_KP_0:
|
||||||
|
@@ -54,6 +54,7 @@
|
|||||||
#include "clutter-main.h"
|
#include "clutter-main.h"
|
||||||
#include "clutter-private.h"
|
#include "clutter-private.h"
|
||||||
#include "clutter-settings-private.h"
|
#include "clutter-settings-private.h"
|
||||||
|
#include "clutter-xkb-a11y-x11.h"
|
||||||
|
|
||||||
G_DEFINE_TYPE (ClutterBackendX11, clutter_backend_x11, CLUTTER_TYPE_BACKEND)
|
G_DEFINE_TYPE (ClutterBackendX11, clutter_backend_x11, CLUTTER_TYPE_BACKEND)
|
||||||
|
|
||||||
@@ -276,6 +277,20 @@ clutter_backend_x11_create_device_manager (ClutterBackendX11 *backend_x11)
|
|||||||
_clutter_backend_add_event_translator (backend, translator);
|
_clutter_backend_add_event_translator (backend, translator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_keymap_state_change (ClutterKeymapX11 *keymap_x11,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
ClutterDeviceManager *device_manager = CLUTTER_DEVICE_MANAGER (data);
|
||||||
|
ClutterKbdA11ySettings kbd_a11y_settings;
|
||||||
|
|
||||||
|
/* On keymaps state change, just reapply the current settings, it'll
|
||||||
|
* take care of enabling/disabling mousekeys based on NumLock state.
|
||||||
|
*/
|
||||||
|
clutter_device_manager_get_kbd_a11y_settings (device_manager, &kbd_a11y_settings);
|
||||||
|
clutter_device_manager_x11_apply_kbd_a11y_settings (device_manager, &kbd_a11y_settings);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_backend_x11_create_keymap (ClutterBackendX11 *backend_x11)
|
clutter_backend_x11_create_keymap (ClutterBackendX11 *backend_x11)
|
||||||
{
|
{
|
||||||
@@ -292,6 +307,11 @@ clutter_backend_x11_create_keymap (ClutterBackendX11 *backend_x11)
|
|||||||
backend = CLUTTER_BACKEND (backend_x11);
|
backend = CLUTTER_BACKEND (backend_x11);
|
||||||
translator = CLUTTER_EVENT_TRANSLATOR (backend_x11->keymap);
|
translator = CLUTTER_EVENT_TRANSLATOR (backend_x11->keymap);
|
||||||
_clutter_backend_add_event_translator (backend, translator);
|
_clutter_backend_add_event_translator (backend, translator);
|
||||||
|
|
||||||
|
g_signal_connect (backend_x11->keymap,
|
||||||
|
"state-changed",
|
||||||
|
G_CALLBACK (on_keymap_state_change),
|
||||||
|
backend->device_manager);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -241,7 +241,12 @@ clutter_device_manager_x11_apply_kbd_a11y_settings (ClutterDeviceManager *devi
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* mouse keys */
|
/* mouse keys */
|
||||||
if (set_xkb_ctrl (desc, kbd_a11y_settings->controls,
|
if (clutter_keymap_get_num_lock_state (CLUTTER_KEYMAP (backend_x11->keymap)))
|
||||||
|
{
|
||||||
|
/* Disable mousekeys when NumLock is ON */
|
||||||
|
desc->ctrls->enabled_ctrls &= ~(XkbMouseKeysMask | XkbMouseKeysAccelMask);
|
||||||
|
}
|
||||||
|
else if (set_xkb_ctrl (desc, kbd_a11y_settings->controls,
|
||||||
CLUTTER_A11Y_MOUSE_KEYS_ENABLED, XkbMouseKeysMask | XkbMouseKeysAccelMask))
|
CLUTTER_A11Y_MOUSE_KEYS_ENABLED, XkbMouseKeysMask | XkbMouseKeysAccelMask))
|
||||||
{
|
{
|
||||||
gint mk_max_speed;
|
gint mk_max_speed;
|
||||||
|
@@ -460,9 +460,7 @@ cogl_path_fill (CoglPath *path);
|
|||||||
* use while filling a path.</note>
|
* use while filling a path.</note>
|
||||||
*
|
*
|
||||||
* Stability: unstable
|
* Stability: unstable
|
||||||
* Deprecated: 1.16: Use cogl_path_fill() instead
|
|
||||||
*/
|
*/
|
||||||
COGL_DEPRECATED_FOR (cogl_path_fill)
|
|
||||||
void
|
void
|
||||||
cogl_framebuffer_fill_path (CoglFramebuffer *framebuffer,
|
cogl_framebuffer_fill_path (CoglFramebuffer *framebuffer,
|
||||||
CoglPipeline *pipeline,
|
CoglPipeline *pipeline,
|
||||||
@@ -492,9 +490,7 @@ cogl_path_stroke (CoglPath *path);
|
|||||||
* regardless of the current transformation matrix.
|
* regardless of the current transformation matrix.
|
||||||
*
|
*
|
||||||
* Stability: unstable
|
* Stability: unstable
|
||||||
* Deprecated: 1.16: Use cogl_path_stroke() instead
|
|
||||||
*/
|
*/
|
||||||
COGL_DEPRECATED_FOR (cogl_path_stroke)
|
|
||||||
void
|
void
|
||||||
cogl_framebuffer_stroke_path (CoglFramebuffer *framebuffer,
|
cogl_framebuffer_stroke_path (CoglFramebuffer *framebuffer,
|
||||||
CoglPipeline *pipeline,
|
CoglPipeline *pipeline,
|
||||||
@@ -529,9 +525,7 @@ cogl_framebuffer_push_path_clip (CoglFramebuffer *framebuffer,
|
|||||||
*
|
*
|
||||||
* Since: 1.8
|
* Since: 1.8
|
||||||
* Stability: Unstable
|
* Stability: Unstable
|
||||||
* Deprecated: 1.16: Use cogl_framebuffer_push_path_clip() instead
|
|
||||||
*/
|
*/
|
||||||
COGL_DEPRECATED_FOR (cogl_framebuffer_push_path_clip)
|
|
||||||
void
|
void
|
||||||
cogl_clip_push_from_path (CoglPath *path);
|
cogl_clip_push_from_path (CoglPath *path);
|
||||||
|
|
||||||
|
@@ -1504,7 +1504,6 @@ cogl_framebuffer_push_path_clip (CoglFramebuffer *framebuffer,
|
|||||||
COGL_FRAMEBUFFER_STATE_CLIP;
|
COGL_FRAMEBUFFER_STATE_CLIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX: deprecated */
|
|
||||||
void
|
void
|
||||||
cogl_clip_push_from_path (CoglPath *path)
|
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;
|
data->stroke_n_attributes = n_attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX: deprecated */
|
|
||||||
void
|
void
|
||||||
cogl_framebuffer_fill_path (CoglFramebuffer *framebuffer,
|
cogl_framebuffer_fill_path (CoglFramebuffer *framebuffer,
|
||||||
CoglPipeline *pipeline,
|
CoglPipeline *pipeline,
|
||||||
@@ -1588,7 +1586,6 @@ cogl_framebuffer_fill_path (CoglFramebuffer *framebuffer,
|
|||||||
_cogl_path_fill_nodes (path, framebuffer, pipeline, 0 /* flags */);
|
_cogl_path_fill_nodes (path, framebuffer, pipeline, 0 /* flags */);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX: deprecated */
|
|
||||||
void
|
void
|
||||||
cogl_framebuffer_stroke_path (CoglFramebuffer *framebuffer,
|
cogl_framebuffer_stroke_path (CoglFramebuffer *framebuffer,
|
||||||
CoglPipeline *pipeline,
|
CoglPipeline *pipeline,
|
||||||
|
@@ -455,9 +455,6 @@ _cogl_pipeline_free (CoglPipeline *pipeline)
|
|||||||
_cogl_bitmask_destroy (&uniforms_state->changed_mask);
|
_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)
|
if (pipeline->differences & COGL_PIPELINE_STATE_LAYERS)
|
||||||
{
|
{
|
||||||
g_list_foreach (pipeline->layer_differences,
|
g_list_foreach (pipeline->layer_differences,
|
||||||
@@ -471,6 +468,9 @@ _cogl_pipeline_free (CoglPipeline *pipeline)
|
|||||||
if (pipeline->differences & COGL_PIPELINE_STATE_FRAGMENT_SNIPPETS)
|
if (pipeline->differences & COGL_PIPELINE_STATE_FRAGMENT_SNIPPETS)
|
||||||
_cogl_pipeline_snippet_list_free (&pipeline->big_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);
|
g_list_free (pipeline->deprecated_get_layers_list);
|
||||||
|
|
||||||
recursively_free_layer_caches (pipeline);
|
recursively_free_layer_caches (pipeline);
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
project('mutter', 'c',
|
project('mutter', 'c',
|
||||||
version: '3.32.1',
|
version: '3.32.2',
|
||||||
meson_version: '>= 0.48.0',
|
meson_version: '>= 0.50.0',
|
||||||
license: 'GPLv2+'
|
license: 'GPLv2+'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
12
po/de.po
12
po/de.po
@@ -13,9 +13,9 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: mutter master\n"
|
"Project-Id-Version: mutter master\n"
|
||||||
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n"
|
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n"
|
||||||
"POT-Creation-Date: 2019-02-04 17:52+0000\n"
|
"POT-Creation-Date: 2019-08-06 00:49+0000\n"
|
||||||
"PO-Revision-Date: 2019-02-26 20:43+0100\n"
|
"PO-Revision-Date: 2019-09-05 23:42+0200\n"
|
||||||
"Last-Translator: Tim Sabsch <tim@sabsch.com>\n"
|
"Last-Translator: Christian Kirbach <christian.kirbach@gmail.com>\n"
|
||||||
"Language-Team: Deutsch <gnome-de@gnome.org>\n"
|
"Language-Team: Deutsch <gnome-de@gnome.org>\n"
|
||||||
"Language: de\n"
|
"Language: de\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
@@ -152,13 +152,15 @@ msgstr "Zur Arbeitsfläche 4 wechseln"
|
|||||||
msgid "Switch to last workspace"
|
msgid "Switch to last workspace"
|
||||||
msgstr "Zur letzten Arbeitsfläche wechseln"
|
msgstr "Zur letzten Arbeitsfläche wechseln"
|
||||||
|
|
||||||
|
# Wechsel der Arbeitsfläche. Es wird nichts verschoben.
|
||||||
#: data/50-mutter-navigation.xml:123
|
#: data/50-mutter-navigation.xml:123
|
||||||
msgid "Move to workspace above"
|
msgid "Move to workspace above"
|
||||||
msgstr "Auf Arbeitsfläche darüber verschieben"
|
msgstr "Zur Arbeitsfläche darüber wechseln"
|
||||||
|
|
||||||
|
# Wechsel der Arbeitsfläche. Es wird nichts verschoben.
|
||||||
#: data/50-mutter-navigation.xml:126
|
#: data/50-mutter-navigation.xml:126
|
||||||
msgid "Move to workspace below"
|
msgid "Move to workspace below"
|
||||||
msgstr "Auf Arbeitsfläche darunter verschieben"
|
msgstr "Zur Arbeitsfläche darunter wechseln"
|
||||||
|
|
||||||
#: data/50-mutter-system.xml:6 data/50-mutter-wayland.xml:6
|
#: data/50-mutter-system.xml:6 data/50-mutter-wayland.xml:6
|
||||||
msgid "System"
|
msgid "System"
|
||||||
|
@@ -49,6 +49,14 @@
|
|||||||
#define DEFAULT_XKB_RULES_FILE "evdev"
|
#define DEFAULT_XKB_RULES_FILE "evdev"
|
||||||
#define DEFAULT_XKB_MODEL "pc105+inet"
|
#define DEFAULT_XKB_MODEL "pc105+inet"
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
META_SEQUENCE_NONE,
|
||||||
|
META_SEQUENCE_ACCEPTED,
|
||||||
|
META_SEQUENCE_REJECTED,
|
||||||
|
META_SEQUENCE_PENDING_END
|
||||||
|
} MetaSequenceState;
|
||||||
|
|
||||||
struct _MetaBackendClass
|
struct _MetaBackendClass
|
||||||
{
|
{
|
||||||
GObjectClass parent_class;
|
GObjectClass parent_class;
|
||||||
@@ -71,6 +79,10 @@ struct _MetaBackendClass
|
|||||||
int device_id,
|
int device_id,
|
||||||
uint32_t timestamp);
|
uint32_t timestamp);
|
||||||
|
|
||||||
|
void (* finish_touch_sequence) (MetaBackend *backend,
|
||||||
|
ClutterEventSequence *sequence,
|
||||||
|
MetaSequenceState state);
|
||||||
|
|
||||||
void (* warp_pointer) (MetaBackend *backend,
|
void (* warp_pointer) (MetaBackend *backend,
|
||||||
int x,
|
int x,
|
||||||
int y);
|
int y);
|
||||||
@@ -135,6 +147,10 @@ gboolean meta_backend_ungrab_device (MetaBackend *backend,
|
|||||||
int device_id,
|
int device_id,
|
||||||
uint32_t timestamp);
|
uint32_t timestamp);
|
||||||
|
|
||||||
|
void meta_backend_finish_touch_sequence (MetaBackend *backend,
|
||||||
|
ClutterEventSequence *sequence,
|
||||||
|
MetaSequenceState state);
|
||||||
|
|
||||||
void meta_backend_warp_pointer (MetaBackend *backend,
|
void meta_backend_warp_pointer (MetaBackend *backend,
|
||||||
int x,
|
int x,
|
||||||
int y);
|
int y);
|
||||||
|
@@ -1007,6 +1007,20 @@ meta_backend_ungrab_device (MetaBackend *backend,
|
|||||||
return META_BACKEND_GET_CLASS (backend)->ungrab_device (backend, device_id, timestamp);
|
return META_BACKEND_GET_CLASS (backend)->ungrab_device (backend, device_id, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* meta_backend_finish_touch_sequence: (skip)
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
meta_backend_finish_touch_sequence (MetaBackend *backend,
|
||||||
|
ClutterEventSequence *sequence,
|
||||||
|
MetaSequenceState state)
|
||||||
|
{
|
||||||
|
if (META_BACKEND_GET_CLASS (backend)->finish_touch_sequence)
|
||||||
|
META_BACKEND_GET_CLASS (backend)->finish_touch_sequence (backend,
|
||||||
|
sequence,
|
||||||
|
state);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* meta_backend_warp_pointer: (skip)
|
* meta_backend_warp_pointer: (skip)
|
||||||
*/
|
*/
|
||||||
|
@@ -207,6 +207,8 @@ update_inhibited (MetaIdleMonitor *monitor,
|
|||||||
if (inhibited == monitor->inhibited)
|
if (inhibited == monitor->inhibited)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
monitor->inhibited = inhibited;
|
||||||
|
|
||||||
g_hash_table_foreach (monitor->watches,
|
g_hash_table_foreach (monitor->watches,
|
||||||
update_inhibited_watch,
|
update_inhibited_watch,
|
||||||
monitor);
|
monitor);
|
||||||
@@ -316,11 +318,18 @@ idle_monitor_dispatch_timeout (GSource *source,
|
|||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) user_data;
|
MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) user_data;
|
||||||
|
int64_t now;
|
||||||
|
int64_t ready_time;
|
||||||
|
|
||||||
|
now = g_source_get_time (source);
|
||||||
|
ready_time = g_source_get_ready_time (source);
|
||||||
|
if (ready_time > now)
|
||||||
|
return G_SOURCE_CONTINUE;
|
||||||
|
|
||||||
_meta_idle_monitor_watch_fire (watch);
|
_meta_idle_monitor_watch_fire (watch);
|
||||||
g_source_set_ready_time (watch->timeout_source, -1);
|
g_source_set_ready_time (watch->timeout_source, -1);
|
||||||
|
|
||||||
return TRUE;
|
return G_SOURCE_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GSourceFuncs idle_monitor_source_funcs = {
|
static GSourceFuncs idle_monitor_source_funcs = {
|
||||||
@@ -506,6 +515,12 @@ meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor)
|
|||||||
{
|
{
|
||||||
_meta_idle_monitor_watch_fire ((MetaIdleMonitorWatch *) watch);
|
_meta_idle_monitor_watch_fire ((MetaIdleMonitorWatch *) watch);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (monitor->inhibited)
|
||||||
|
{
|
||||||
|
g_source_set_ready_time (watch->timeout_source, -1);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_source_set_ready_time (watch->timeout_source,
|
g_source_set_ready_time (watch->timeout_source,
|
||||||
@@ -513,6 +528,7 @@ meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor)
|
|||||||
watch->timeout_msec * 1000);
|
watch->timeout_msec * 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
g_list_free (watch_ids);
|
g_list_free (watch_ids);
|
||||||
}
|
}
|
||||||
|
@@ -381,7 +381,7 @@ guess_candidates (MetaInputMapper *mapper,
|
|||||||
info->candidates[META_MATCH_SIZE] = matched_monitor;
|
info->candidates[META_MATCH_SIZE] = matched_monitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input->builtin)
|
if (input->builtin || best == N_OUTPUT_MATCHES)
|
||||||
{
|
{
|
||||||
best = MIN (best, META_MATCH_IS_BUILTIN);
|
best = MIN (best, META_MATCH_IS_BUILTIN);
|
||||||
find_builtin_output (mapper, &info->candidates[META_MATCH_IS_BUILTIN]);
|
find_builtin_output (mapper, &info->candidates[META_MATCH_IS_BUILTIN]);
|
||||||
|
@@ -1216,7 +1216,7 @@ load_keyboard_a11y_settings (MetaInputSettings *input_settings,
|
|||||||
ClutterInputDevice *device)
|
ClutterInputDevice *device)
|
||||||
{
|
{
|
||||||
MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (input_settings);
|
MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (input_settings);
|
||||||
ClutterKbdA11ySettings kbd_a11y_settings;
|
ClutterKbdA11ySettings kbd_a11y_settings = { 0 };
|
||||||
ClutterInputDevice *core_keyboard;
|
ClutterInputDevice *core_keyboard;
|
||||||
guint i;
|
guint i;
|
||||||
|
|
||||||
|
@@ -90,6 +90,12 @@ meta_renderer_create_view (MetaRenderer *renderer,
|
|||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
meta_renderer_rebuild_views (MetaRenderer *renderer)
|
meta_renderer_rebuild_views (MetaRenderer *renderer)
|
||||||
|
{
|
||||||
|
return META_RENDERER_GET_CLASS (renderer)->rebuild_views (renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_renderer_real_rebuild_views (MetaRenderer *renderer)
|
||||||
{
|
{
|
||||||
MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer);
|
MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer);
|
||||||
MetaBackend *backend = meta_get_backend ();
|
MetaBackend *backend = meta_get_backend ();
|
||||||
@@ -181,4 +187,6 @@ meta_renderer_class_init (MetaRendererClass *klass)
|
|||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
object_class->finalize = meta_renderer_finalize;
|
object_class->finalize = meta_renderer_finalize;
|
||||||
|
|
||||||
|
klass->rebuild_views = meta_renderer_real_rebuild_views;
|
||||||
}
|
}
|
||||||
|
@@ -43,6 +43,7 @@ struct _MetaRendererClass
|
|||||||
CoglRenderer * (* create_cogl_renderer) (MetaRenderer *renderer);
|
CoglRenderer * (* create_cogl_renderer) (MetaRenderer *renderer);
|
||||||
MetaRendererView * (* create_view) (MetaRenderer *renderer,
|
MetaRendererView * (* create_view) (MetaRenderer *renderer,
|
||||||
MetaLogicalMonitor *logical_monitor);
|
MetaLogicalMonitor *logical_monitor);
|
||||||
|
void (* rebuild_views) (MetaRenderer *renderer);
|
||||||
};
|
};
|
||||||
|
|
||||||
CoglRenderer * meta_renderer_create_cogl_renderer (MetaRenderer *renderer);
|
CoglRenderer * meta_renderer_create_cogl_renderer (MetaRenderer *renderer);
|
||||||
|
@@ -368,12 +368,8 @@ parse_transforms (MetaCrtc *crtc,
|
|||||||
|
|
||||||
if (strcmp (prop->enums[i].name, "rotate-0") == 0)
|
if (strcmp (prop->enums[i].name, "rotate-0") == 0)
|
||||||
transform = META_MONITOR_TRANSFORM_NORMAL;
|
transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||||
else if (strcmp (prop->enums[i].name, "rotate-90") == 0)
|
|
||||||
transform = META_MONITOR_TRANSFORM_90;
|
|
||||||
else if (strcmp (prop->enums[i].name, "rotate-180") == 0)
|
else if (strcmp (prop->enums[i].name, "rotate-180") == 0)
|
||||||
transform = META_MONITOR_TRANSFORM_180;
|
transform = META_MONITOR_TRANSFORM_180;
|
||||||
else if (strcmp (prop->enums[i].name, "rotate-270") == 0)
|
|
||||||
transform = META_MONITOR_TRANSFORM_270;
|
|
||||||
|
|
||||||
if (transform != -1)
|
if (transform != -1)
|
||||||
{
|
{
|
||||||
|
@@ -823,6 +823,7 @@ static void
|
|||||||
cursor_priv_free (MetaCursorNativePrivate *cursor_priv)
|
cursor_priv_free (MetaCursorNativePrivate *cursor_priv)
|
||||||
{
|
{
|
||||||
g_hash_table_destroy (cursor_priv->gpu_states);
|
g_hash_table_destroy (cursor_priv->gpu_states);
|
||||||
|
g_free (cursor_priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static MetaCursorNativePrivate *
|
static MetaCursorNativePrivate *
|
||||||
|
@@ -258,6 +258,9 @@ cogl_pixel_format_from_drm_format (uint32_t drm_format,
|
|||||||
CoglPixelFormat *out_format,
|
CoglPixelFormat *out_format,
|
||||||
CoglTextureComponents *out_components);
|
CoglTextureComponents *out_components);
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native);
|
||||||
|
|
||||||
static MetaBackend *
|
static MetaBackend *
|
||||||
backend_from_renderer_native (MetaRendererNative *renderer_native)
|
backend_from_renderer_native (MetaRendererNative *renderer_native)
|
||||||
{
|
{
|
||||||
@@ -1277,7 +1280,7 @@ meta_renderer_native_egl_context_created (CoglDisplay *cogl_display,
|
|||||||
cogl_display_egl->dummy_surface,
|
cogl_display_egl->dummy_surface,
|
||||||
cogl_display_egl->egl_context))
|
cogl_display_egl->egl_context))
|
||||||
{
|
{
|
||||||
_cogl_set_error (error, COGL_WINSYS_ERROR,
|
g_set_error (error, COGL_WINSYS_ERROR,
|
||||||
COGL_WINSYS_ERROR_CREATE_CONTEXT,
|
COGL_WINSYS_ERROR_CREATE_CONTEXT,
|
||||||
"Failed to make context current");
|
"Failed to make context current");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@@ -3035,11 +3038,53 @@ meta_onscreen_native_allocate (CoglOnscreen *onscreen,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
destroy_egl_surface (CoglOnscreen *onscreen)
|
||||||
|
{
|
||||||
|
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
|
||||||
|
|
||||||
|
if (onscreen_egl->egl_surface != EGL_NO_SURFACE)
|
||||||
|
{
|
||||||
|
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
|
||||||
|
MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native);
|
||||||
|
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
|
||||||
|
CoglContext *cogl_context = framebuffer->context;
|
||||||
|
CoglRenderer *cogl_renderer = cogl_context->display->renderer;
|
||||||
|
CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys;
|
||||||
|
|
||||||
|
meta_egl_destroy_surface (egl,
|
||||||
|
cogl_renderer_egl->edpy,
|
||||||
|
onscreen_egl->egl_surface,
|
||||||
|
NULL);
|
||||||
|
onscreen_egl->egl_surface = EGL_NO_SURFACE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
discard_onscreen_page_flip_retries (MetaOnscreenNative *onscreen_native)
|
||||||
|
{
|
||||||
|
g_list_free_full (onscreen_native->pending_page_flip_retries,
|
||||||
|
(GDestroyNotify) retry_page_flip_data_free);
|
||||||
|
onscreen_native->pending_page_flip_retries = NULL;
|
||||||
|
|
||||||
|
if (onscreen_native->retry_page_flips_source)
|
||||||
|
{
|
||||||
|
MetaBackend *backend =
|
||||||
|
backend_from_renderer_native (onscreen_native->renderer_native);
|
||||||
|
|
||||||
|
meta_backend_thaw_updates (backend);
|
||||||
|
g_clear_pointer (&onscreen_native->retry_page_flips_source,
|
||||||
|
g_source_destroy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_renderer_native_release_onscreen (CoglOnscreen *onscreen)
|
meta_renderer_native_release_onscreen (CoglOnscreen *onscreen)
|
||||||
{
|
{
|
||||||
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
|
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
|
||||||
CoglContext *cogl_context = framebuffer->context;
|
CoglContext *cogl_context = framebuffer->context;
|
||||||
|
CoglDisplay *cogl_display = cogl_context_get_display (cogl_context);
|
||||||
|
CoglDisplayEGL *cogl_display_egl = cogl_display->winsys;
|
||||||
CoglRenderer *cogl_renderer = cogl_context->display->renderer;
|
CoglRenderer *cogl_renderer = cogl_context->display->renderer;
|
||||||
CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys;
|
CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys;
|
||||||
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
|
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
|
||||||
@@ -3052,28 +3097,18 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen)
|
|||||||
|
|
||||||
onscreen_native = onscreen_egl->platform;
|
onscreen_native = onscreen_egl->platform;
|
||||||
|
|
||||||
g_list_free_full (onscreen_native->pending_page_flip_retries,
|
if (onscreen_egl->egl_surface != EGL_NO_SURFACE &&
|
||||||
(GDestroyNotify) retry_page_flip_data_free);
|
(cogl_display_egl->current_draw_surface == onscreen_egl->egl_surface ||
|
||||||
if (onscreen_native->retry_page_flips_source)
|
cogl_display_egl->current_read_surface == onscreen_egl->egl_surface))
|
||||||
{
|
{
|
||||||
MetaBackend *backend =
|
if (!_cogl_winsys_egl_make_current (cogl_display,
|
||||||
backend_from_renderer_native (onscreen_native->renderer_native);
|
cogl_display_egl->dummy_surface,
|
||||||
|
cogl_display_egl->dummy_surface,
|
||||||
meta_backend_thaw_updates (backend);
|
cogl_display_egl->egl_context))
|
||||||
g_clear_pointer (&onscreen_native->retry_page_flips_source,
|
g_warning ("Failed to clear current context");
|
||||||
g_source_destroy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onscreen_egl->egl_surface != EGL_NO_SURFACE)
|
discard_onscreen_page_flip_retries (onscreen_native);
|
||||||
{
|
|
||||||
MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native);
|
|
||||||
|
|
||||||
meta_egl_destroy_surface (egl,
|
|
||||||
cogl_renderer_egl->edpy,
|
|
||||||
onscreen_egl->egl_surface,
|
|
||||||
NULL);
|
|
||||||
onscreen_egl->egl_surface = EGL_NO_SURFACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderer_gpu_data =
|
renderer_gpu_data =
|
||||||
meta_renderer_native_get_gpu_data (onscreen_native->renderer_native,
|
meta_renderer_native_get_gpu_data (onscreen_native->renderer_native,
|
||||||
@@ -3087,6 +3122,8 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen)
|
|||||||
|
|
||||||
free_current_bo (onscreen);
|
free_current_bo (onscreen);
|
||||||
|
|
||||||
|
destroy_egl_surface (onscreen);
|
||||||
|
|
||||||
if (onscreen_native->gbm.surface)
|
if (onscreen_native->gbm.surface)
|
||||||
{
|
{
|
||||||
gbm_surface_destroy (onscreen_native->gbm.surface);
|
gbm_surface_destroy (onscreen_native->gbm.surface);
|
||||||
@@ -3097,6 +3134,9 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen)
|
|||||||
case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
|
case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
|
||||||
release_dumb_fb (&onscreen_native->egl.dumb_fb,
|
release_dumb_fb (&onscreen_native->egl.dumb_fb,
|
||||||
onscreen_native->render_gpu);
|
onscreen_native->render_gpu);
|
||||||
|
|
||||||
|
destroy_egl_surface (onscreen);
|
||||||
|
|
||||||
if (onscreen_native->egl.stream != EGL_NO_STREAM_KHR)
|
if (onscreen_native->egl.stream != EGL_NO_STREAM_KHR)
|
||||||
{
|
{
|
||||||
MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native);
|
MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native);
|
||||||
@@ -3157,7 +3197,7 @@ meta_renderer_native_supports_mirroring (MetaRendererNative *renderer_native)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native)
|
meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native)
|
||||||
{
|
{
|
||||||
MetaRenderer *renderer = META_RENDERER (renderer_native);
|
MetaRenderer *renderer = META_RENDERER (renderer_native);
|
||||||
@@ -3523,6 +3563,37 @@ meta_renderer_native_create_view (MetaRenderer *renderer,
|
|||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
discard_page_flip_retries (MetaRenderer *renderer)
|
||||||
|
{
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
for (l = meta_renderer_get_views (renderer); l; l = l->next)
|
||||||
|
{
|
||||||
|
ClutterStageView *stage_view = l->data;
|
||||||
|
CoglFramebuffer *framebuffer =
|
||||||
|
clutter_stage_view_get_onscreen (stage_view);
|
||||||
|
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
|
||||||
|
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
|
||||||
|
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
|
||||||
|
|
||||||
|
discard_onscreen_page_flip_retries (onscreen_native);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_renderer_native_rebuild_views (MetaRenderer *renderer)
|
||||||
|
{
|
||||||
|
MetaRendererClass *parent_renderer_class =
|
||||||
|
META_RENDERER_CLASS (meta_renderer_native_parent_class);
|
||||||
|
|
||||||
|
discard_page_flip_retries (renderer);
|
||||||
|
|
||||||
|
parent_renderer_class->rebuild_views (renderer);
|
||||||
|
|
||||||
|
meta_renderer_native_queue_modes_reset (META_RENDERER_NATIVE (renderer));
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_renderer_native_finish_frame (MetaRendererNative *renderer_native)
|
meta_renderer_native_finish_frame (MetaRendererNative *renderer_native)
|
||||||
{
|
{
|
||||||
@@ -4038,6 +4109,7 @@ create_renderer_gpu_data_egl_device (MetaRendererNative *renderer_native,
|
|||||||
G_IO_ERROR_FAILED,
|
G_IO_ERROR_FAILED,
|
||||||
"Missing EGL extensions required for EGLDevice renderer: %s",
|
"Missing EGL extensions required for EGLDevice renderer: %s",
|
||||||
missing_extensions_str);
|
missing_extensions_str);
|
||||||
|
meta_egl_terminate (egl, egl_display, NULL);
|
||||||
g_free (missing_extensions_str);
|
g_free (missing_extensions_str);
|
||||||
g_free (missing_extensions);
|
g_free (missing_extensions);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -4320,6 +4392,7 @@ meta_renderer_native_class_init (MetaRendererNativeClass *klass)
|
|||||||
|
|
||||||
renderer_class->create_cogl_renderer = meta_renderer_native_create_cogl_renderer;
|
renderer_class->create_cogl_renderer = meta_renderer_native_create_cogl_renderer;
|
||||||
renderer_class->create_view = meta_renderer_native_create_view;
|
renderer_class->create_view = meta_renderer_native_create_view;
|
||||||
|
renderer_class->rebuild_views = meta_renderer_native_rebuild_views;
|
||||||
|
|
||||||
obj_props[PROP_MONITOR_MANAGER] =
|
obj_props[PROP_MONITOR_MANAGER] =
|
||||||
g_param_spec_object ("monitor-manager",
|
g_param_spec_object ("monitor-manager",
|
||||||
|
@@ -53,20 +53,6 @@ struct gbm_device * meta_gbm_device_from_gpu (MetaGpuKms *gpu_kms);
|
|||||||
|
|
||||||
gboolean meta_renderer_native_supports_mirroring (MetaRendererNative *renderer_native);
|
gboolean meta_renderer_native_supports_mirroring (MetaRendererNative *renderer_native);
|
||||||
|
|
||||||
void meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native);
|
|
||||||
|
|
||||||
gboolean meta_renderer_native_set_legacy_view_size (MetaRendererNative *renderer_native,
|
|
||||||
MetaRendererView *view,
|
|
||||||
int width,
|
|
||||||
int height,
|
|
||||||
GError **error);
|
|
||||||
|
|
||||||
void meta_renderer_native_set_ignore_crtc (MetaRendererNative *renderer_native,
|
|
||||||
uint32_t id,
|
|
||||||
gboolean ignore);
|
|
||||||
|
|
||||||
MetaRendererView * meta_renderer_native_create_legacy_view (MetaRendererNative *renderer_native);
|
|
||||||
|
|
||||||
void meta_renderer_native_finish_frame (MetaRendererNative *renderer_native);
|
void meta_renderer_native_finish_frame (MetaRendererNative *renderer_native);
|
||||||
|
|
||||||
int64_t meta_renderer_native_get_frame_counter (MetaRendererNative *renderer_native);
|
int64_t meta_renderer_native_get_frame_counter (MetaRendererNative *renderer_native);
|
||||||
|
@@ -140,7 +140,6 @@ meta_stage_native_rebuild_views (MetaStageNative *stage_native)
|
|||||||
ClutterActor *stage = meta_backend_get_stage (backend);
|
ClutterActor *stage = meta_backend_get_stage (backend);
|
||||||
|
|
||||||
meta_renderer_rebuild_views (renderer);
|
meta_renderer_rebuild_views (renderer);
|
||||||
meta_renderer_native_queue_modes_reset (META_RENDERER_NATIVE (renderer));
|
|
||||||
clutter_stage_update_resource_scales (CLUTTER_STAGE (stage));
|
clutter_stage_update_resource_scales (CLUTTER_STAGE (stage));
|
||||||
ensure_frame_callbacks (stage_native);
|
ensure_frame_callbacks (stage_native);
|
||||||
}
|
}
|
||||||
|
@@ -66,6 +66,10 @@ struct _MetaBackendX11Private
|
|||||||
XSyncAlarm user_active_alarm;
|
XSyncAlarm user_active_alarm;
|
||||||
XSyncCounter counter;
|
XSyncCounter counter;
|
||||||
|
|
||||||
|
int current_touch_replay_sync_serial;
|
||||||
|
int pending_touch_replay_sync_serial;
|
||||||
|
Atom touch_replay_sync_atom;
|
||||||
|
|
||||||
int xinput_opcode;
|
int xinput_opcode;
|
||||||
int xinput_event_base;
|
int xinput_event_base;
|
||||||
int xinput_error_base;
|
int xinput_error_base;
|
||||||
@@ -174,6 +178,26 @@ meta_backend_x11_translate_device_event (MetaBackendX11 *x11,
|
|||||||
backend_x11_class->translate_device_event (x11, device_event);
|
backend_x11_class->translate_device_event (x11, device_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
maybe_translate_touch_replay_pointer_event (MetaBackendX11 *x11,
|
||||||
|
XIDeviceEvent *device_event)
|
||||||
|
{
|
||||||
|
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||||
|
|
||||||
|
if (!device_event->send_event &&
|
||||||
|
device_event->time != META_CURRENT_TIME &&
|
||||||
|
priv->current_touch_replay_sync_serial !=
|
||||||
|
priv->pending_touch_replay_sync_serial &&
|
||||||
|
XSERVER_TIME_IS_BEFORE (device_event->time, priv->latest_evtime))
|
||||||
|
{
|
||||||
|
/* Emulated pointer events received after XIRejectTouch is received
|
||||||
|
* on a passive touch grab will contain older timestamps, update those
|
||||||
|
* so we dont get InvalidTime at grabs.
|
||||||
|
*/
|
||||||
|
device_event->time = priv->latest_evtime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
translate_device_event (MetaBackendX11 *x11,
|
translate_device_event (MetaBackendX11 *x11,
|
||||||
XIDeviceEvent *device_event)
|
XIDeviceEvent *device_event)
|
||||||
@@ -183,20 +207,8 @@ translate_device_event (MetaBackendX11 *x11,
|
|||||||
meta_backend_x11_translate_device_event (x11, device_event);
|
meta_backend_x11_translate_device_event (x11, device_event);
|
||||||
|
|
||||||
if (!device_event->send_event && device_event->time != META_CURRENT_TIME)
|
if (!device_event->send_event && device_event->time != META_CURRENT_TIME)
|
||||||
{
|
|
||||||
if (XSERVER_TIME_IS_BEFORE (device_event->time, priv->latest_evtime))
|
|
||||||
{
|
|
||||||
/* Emulated pointer events received after XIRejectTouch is received
|
|
||||||
* on a passive touch grab will contain older timestamps, update those
|
|
||||||
* so we dont get InvalidTime at grabs.
|
|
||||||
*/
|
|
||||||
device_event->time = priv->latest_evtime;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update the internal latest evtime, for any possible later use */
|
|
||||||
priv->latest_evtime = device_event->time;
|
priv->latest_evtime = device_event->time;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_backend_x11_translate_crossing_event (MetaBackendX11 *x11,
|
meta_backend_x11_translate_crossing_event (MetaBackendX11 *x11,
|
||||||
@@ -260,6 +272,9 @@ maybe_spoof_event_as_stage_event (MetaBackendX11 *x11,
|
|||||||
case XI_Motion:
|
case XI_Motion:
|
||||||
case XI_ButtonPress:
|
case XI_ButtonPress:
|
||||||
case XI_ButtonRelease:
|
case XI_ButtonRelease:
|
||||||
|
maybe_translate_touch_replay_pointer_event (x11,
|
||||||
|
(XIDeviceEvent *) input_event);
|
||||||
|
/* Intentional fall-through */
|
||||||
case XI_KeyPress:
|
case XI_KeyPress:
|
||||||
case XI_KeyRelease:
|
case XI_KeyRelease:
|
||||||
case XI_TouchBegin:
|
case XI_TouchBegin:
|
||||||
@@ -327,6 +342,17 @@ handle_host_xevent (MetaBackend *backend,
|
|||||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||||
gboolean bypass_clutter = FALSE;
|
gboolean bypass_clutter = FALSE;
|
||||||
|
|
||||||
|
switch (event->type)
|
||||||
|
{
|
||||||
|
case ClientMessage:
|
||||||
|
if (event->xclient.window == meta_backend_x11_get_xwindow (x11) &&
|
||||||
|
event->xclient.message_type == priv->touch_replay_sync_atom)
|
||||||
|
priv->current_touch_replay_sync_serial = event->xclient.data.l[0];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
XGetEventData (priv->xdisplay, &event->xcookie);
|
XGetEventData (priv->xdisplay, &event->xcookie);
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -534,6 +560,10 @@ meta_backend_x11_post_init (MetaBackend *backend)
|
|||||||
monitor_manager = meta_backend_get_monitor_manager (backend);
|
monitor_manager = meta_backend_get_monitor_manager (backend);
|
||||||
g_signal_connect (monitor_manager, "monitors-changed-internal",
|
g_signal_connect (monitor_manager, "monitors-changed-internal",
|
||||||
G_CALLBACK (on_monitors_changed), backend);
|
G_CALLBACK (on_monitors_changed), backend);
|
||||||
|
|
||||||
|
priv->touch_replay_sync_atom = XInternAtom (priv->xdisplay,
|
||||||
|
"_MUTTER_TOUCH_SEQUENCE_SYNC",
|
||||||
|
False);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ClutterBackend *
|
static ClutterBackend *
|
||||||
@@ -591,6 +621,43 @@ meta_backend_x11_ungrab_device (MetaBackend *backend,
|
|||||||
return (ret == Success);
|
return (ret == Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_backend_x11_finish_touch_sequence (MetaBackend *backend,
|
||||||
|
ClutterEventSequence *sequence,
|
||||||
|
MetaSequenceState state)
|
||||||
|
{
|
||||||
|
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||||
|
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||||
|
int event_mode;
|
||||||
|
|
||||||
|
if (state == META_SEQUENCE_ACCEPTED)
|
||||||
|
event_mode = XIAcceptTouch;
|
||||||
|
else if (state == META_SEQUENCE_REJECTED)
|
||||||
|
event_mode = XIRejectTouch;
|
||||||
|
else
|
||||||
|
g_return_if_reached ();
|
||||||
|
|
||||||
|
XIAllowTouchEvents (priv->xdisplay,
|
||||||
|
META_VIRTUAL_CORE_POINTER_ID,
|
||||||
|
clutter_x11_event_sequence_get_touch_detail (sequence),
|
||||||
|
DefaultRootWindow (priv->xdisplay), event_mode);
|
||||||
|
|
||||||
|
if (state == META_SEQUENCE_REJECTED)
|
||||||
|
{
|
||||||
|
XClientMessageEvent ev;
|
||||||
|
|
||||||
|
ev = (XClientMessageEvent) {
|
||||||
|
.type = ClientMessage,
|
||||||
|
.window = meta_backend_x11_get_xwindow (x11),
|
||||||
|
.message_type = priv->touch_replay_sync_atom,
|
||||||
|
.format = 32,
|
||||||
|
.data.l[0] = ++priv->pending_touch_replay_sync_serial,
|
||||||
|
};
|
||||||
|
XSendEvent (priv->xdisplay, meta_backend_x11_get_xwindow (x11),
|
||||||
|
False, 0, (XEvent *) &ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_backend_x11_warp_pointer (MetaBackend *backend,
|
meta_backend_x11_warp_pointer (MetaBackend *backend,
|
||||||
int x,
|
int x,
|
||||||
@@ -776,6 +843,7 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
|
|||||||
backend_class->post_init = meta_backend_x11_post_init;
|
backend_class->post_init = meta_backend_x11_post_init;
|
||||||
backend_class->grab_device = meta_backend_x11_grab_device;
|
backend_class->grab_device = meta_backend_x11_grab_device;
|
||||||
backend_class->ungrab_device = meta_backend_x11_ungrab_device;
|
backend_class->ungrab_device = meta_backend_x11_ungrab_device;
|
||||||
|
backend_class->finish_touch_sequence = meta_backend_x11_finish_touch_sequence;
|
||||||
backend_class->warp_pointer = meta_backend_x11_warp_pointer;
|
backend_class->warp_pointer = meta_backend_x11_warp_pointer;
|
||||||
backend_class->get_current_logical_monitor = meta_backend_x11_get_current_logical_monitor;
|
backend_class->get_current_logical_monitor = meta_backend_x11_get_current_logical_monitor;
|
||||||
backend_class->get_keymap = meta_backend_x11_get_keymap;
|
backend_class->get_keymap = meta_backend_x11_get_keymap;
|
||||||
|
@@ -18,6 +18,9 @@ struct _MetaCompositor
|
|||||||
guint pre_paint_func_id;
|
guint pre_paint_func_id;
|
||||||
guint post_paint_func_id;
|
guint post_paint_func_id;
|
||||||
|
|
||||||
|
guint stage_presented_id;
|
||||||
|
guint stage_after_paint_id;
|
||||||
|
|
||||||
gint64 server_time_query_time;
|
gint64 server_time_query_time;
|
||||||
gint64 server_time_offset;
|
gint64 server_time_offset;
|
||||||
|
|
||||||
|
@@ -92,6 +92,10 @@ on_presented (ClutterStage *stage,
|
|||||||
ClutterFrameInfo *frame_info,
|
ClutterFrameInfo *frame_info,
|
||||||
MetaCompositor *compositor);
|
MetaCompositor *compositor);
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_top_window_actor_destroyed (MetaWindowActor *window_actor,
|
||||||
|
MetaCompositor *compositor);
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
is_modal (MetaDisplay *display)
|
is_modal (MetaDisplay *display)
|
||||||
{
|
{
|
||||||
@@ -131,9 +135,31 @@ meta_switch_workspace_completed (MetaCompositor *compositor)
|
|||||||
void
|
void
|
||||||
meta_compositor_destroy (MetaCompositor *compositor)
|
meta_compositor_destroy (MetaCompositor *compositor)
|
||||||
{
|
{
|
||||||
|
g_signal_handler_disconnect (compositor->stage,
|
||||||
|
compositor->stage_after_paint_id);
|
||||||
|
g_signal_handler_disconnect (compositor->stage,
|
||||||
|
compositor->stage_presented_id);
|
||||||
|
|
||||||
|
compositor->stage_after_paint_id = 0;
|
||||||
|
compositor->stage_presented_id = 0;
|
||||||
|
compositor->stage = NULL;
|
||||||
|
|
||||||
clutter_threads_remove_repaint_func (compositor->pre_paint_func_id);
|
clutter_threads_remove_repaint_func (compositor->pre_paint_func_id);
|
||||||
clutter_threads_remove_repaint_func (compositor->post_paint_func_id);
|
clutter_threads_remove_repaint_func (compositor->post_paint_func_id);
|
||||||
|
|
||||||
|
if (compositor->top_window_actor)
|
||||||
|
{
|
||||||
|
g_signal_handlers_disconnect_by_func (compositor->top_window_actor,
|
||||||
|
on_top_window_actor_destroyed,
|
||||||
|
compositor);
|
||||||
|
compositor->top_window_actor = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_pointer (&compositor->window_group, clutter_actor_destroy);
|
||||||
|
g_clear_pointer (&compositor->top_window_group, clutter_actor_destroy);
|
||||||
|
g_clear_pointer (&compositor->feedback_group, clutter_actor_destroy);
|
||||||
|
g_clear_pointer (&compositor->windows, g_list_free);
|
||||||
|
|
||||||
if (compositor->have_x11_sync_object)
|
if (compositor->have_x11_sync_object)
|
||||||
meta_sync_ring_destroy ();
|
meta_sync_ring_destroy ();
|
||||||
}
|
}
|
||||||
@@ -503,6 +529,7 @@ meta_compositor_manage (MetaCompositor *compositor)
|
|||||||
|
|
||||||
compositor->stage = meta_backend_get_stage (backend);
|
compositor->stage = meta_backend_get_stage (backend);
|
||||||
|
|
||||||
|
compositor->stage_presented_id =
|
||||||
g_signal_connect (compositor->stage, "presented",
|
g_signal_connect (compositor->stage, "presented",
|
||||||
G_CALLBACK (on_presented),
|
G_CALLBACK (on_presented),
|
||||||
compositor);
|
compositor);
|
||||||
@@ -515,7 +542,8 @@ meta_compositor_manage (MetaCompositor *compositor)
|
|||||||
* connections to ::after-paint, connect() vs. connect_after() doesn't
|
* connections to ::after-paint, connect() vs. connect_after() doesn't
|
||||||
* matter.
|
* matter.
|
||||||
*/
|
*/
|
||||||
g_signal_connect_after (CLUTTER_STAGE (compositor->stage), "after-paint",
|
compositor->stage_after_paint_id =
|
||||||
|
g_signal_connect_after (compositor->stage, "after-paint",
|
||||||
G_CALLBACK (after_stage_paint), compositor);
|
G_CALLBACK (after_stage_paint), compositor);
|
||||||
|
|
||||||
clutter_stage_set_sync_delay (CLUTTER_STAGE (compositor->stage), META_SYNC_DELAY);
|
clutter_stage_set_sync_delay (CLUTTER_STAGE (compositor->stage), META_SYNC_DELAY);
|
||||||
|
@@ -252,12 +252,11 @@ static void
|
|||||||
set_file (MetaBackground *self,
|
set_file (MetaBackground *self,
|
||||||
GFile **filep,
|
GFile **filep,
|
||||||
MetaBackgroundImage **imagep,
|
MetaBackgroundImage **imagep,
|
||||||
GFile *file)
|
GFile *file,
|
||||||
|
gboolean force_reload)
|
||||||
{
|
{
|
||||||
if (!file_equal0 (*filep, file))
|
if (force_reload || !file_equal0 (*filep, file))
|
||||||
{
|
{
|
||||||
g_clear_object (filep);
|
|
||||||
|
|
||||||
if (*imagep)
|
if (*imagep)
|
||||||
{
|
{
|
||||||
g_signal_handlers_disconnect_by_func (*imagep,
|
g_signal_handlers_disconnect_by_func (*imagep,
|
||||||
@@ -267,11 +266,12 @@ set_file (MetaBackground *self,
|
|||||||
*imagep = NULL;
|
*imagep = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_set_object (filep, file);
|
||||||
|
|
||||||
if (file)
|
if (file)
|
||||||
{
|
{
|
||||||
MetaBackgroundImageCache *cache = meta_background_image_cache_get_default ();
|
MetaBackgroundImageCache *cache = meta_background_image_cache_get_default ();
|
||||||
|
|
||||||
*filep = g_object_ref (file);
|
|
||||||
*imagep = meta_background_image_cache_load (cache, file);
|
*imagep = meta_background_image_cache_load (cache, file);
|
||||||
g_signal_connect (*imagep, "loaded",
|
g_signal_connect (*imagep, "loaded",
|
||||||
G_CALLBACK (on_background_loaded), self);
|
G_CALLBACK (on_background_loaded), self);
|
||||||
@@ -279,6 +279,32 @@ set_file (MetaBackground *self,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_gl_video_memory_purged (MetaBackground *self)
|
||||||
|
{
|
||||||
|
MetaBackgroundImageCache *cache = meta_background_image_cache_get_default ();
|
||||||
|
|
||||||
|
/* The GPU memory that just got invalidated is the texture inside
|
||||||
|
* self->background_image1,2 and/or its mipmaps. However, to save memory the
|
||||||
|
* original pixbuf isn't kept in RAM so we can't do a simple re-upload. The
|
||||||
|
* only copy of the image was the one in texture memory that got invalidated.
|
||||||
|
* So we need to do a full reload from disk.
|
||||||
|
*/
|
||||||
|
if (self->file1)
|
||||||
|
{
|
||||||
|
meta_background_image_cache_purge (cache, self->file1);
|
||||||
|
set_file (self, &self->file1, &self->background_image1, self->file1, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self->file2)
|
||||||
|
{
|
||||||
|
meta_background_image_cache_purge (cache, self->file2);
|
||||||
|
set_file (self, &self->file2, &self->background_image2, self->file2, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
mark_changed (self);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_background_dispose (GObject *object)
|
meta_background_dispose (GObject *object)
|
||||||
{
|
{
|
||||||
@@ -287,8 +313,8 @@ meta_background_dispose (GObject *object)
|
|||||||
free_color_texture (self);
|
free_color_texture (self);
|
||||||
free_wallpaper_texture (self);
|
free_wallpaper_texture (self);
|
||||||
|
|
||||||
set_file (self, &self->file1, &self->background_image1, NULL);
|
set_file (self, &self->file1, &self->background_image1, NULL, FALSE);
|
||||||
set_file (self, &self->file2, &self->background_image2, NULL);
|
set_file (self, &self->file2, &self->background_image2, NULL, FALSE);
|
||||||
|
|
||||||
set_display (self, NULL);
|
set_display (self, NULL);
|
||||||
|
|
||||||
@@ -312,7 +338,7 @@ meta_background_constructed (GObject *object)
|
|||||||
G_OBJECT_CLASS (meta_background_parent_class)->constructed (object);
|
G_OBJECT_CLASS (meta_background_parent_class)->constructed (object);
|
||||||
|
|
||||||
g_signal_connect_object (self->display, "gl-video-memory-purged",
|
g_signal_connect_object (self->display, "gl-video-memory-purged",
|
||||||
G_CALLBACK (mark_changed), object, G_CONNECT_SWAPPED);
|
G_CALLBACK (on_gl_video_memory_purged), object, G_CONNECT_SWAPPED);
|
||||||
|
|
||||||
g_signal_connect_object (monitor_manager, "monitors-changed",
|
g_signal_connect_object (monitor_manager, "monitors-changed",
|
||||||
G_CALLBACK (on_monitors_changed), self,
|
G_CALLBACK (on_monitors_changed), self,
|
||||||
@@ -937,8 +963,8 @@ meta_background_set_blend (MetaBackground *self,
|
|||||||
g_return_if_fail (META_IS_BACKGROUND (self));
|
g_return_if_fail (META_IS_BACKGROUND (self));
|
||||||
g_return_if_fail (blend_factor >= 0.0 && blend_factor <= 1.0);
|
g_return_if_fail (blend_factor >= 0.0 && blend_factor <= 1.0);
|
||||||
|
|
||||||
set_file (self, &self->file1, &self->background_image1, file1);
|
set_file (self, &self->file1, &self->background_image1, file1, FALSE);
|
||||||
set_file (self, &self->file2, &self->background_image2, file2);
|
set_file (self, &self->file2, &self->background_image2, file2, FALSE);
|
||||||
|
|
||||||
self->blend_factor = blend_factor;
|
self->blend_factor = blend_factor;
|
||||||
self->style = style;
|
self->style = style;
|
||||||
|
@@ -32,6 +32,7 @@
|
|||||||
#include "cogl/winsys/cogl-texture-pixmap-x11.h"
|
#include "cogl/winsys/cogl-texture-pixmap-x11.h"
|
||||||
#include "compositor/meta-cullable.h"
|
#include "compositor/meta-cullable.h"
|
||||||
#include "compositor/meta-shaped-texture-private.h"
|
#include "compositor/meta-shaped-texture-private.h"
|
||||||
|
#include "compositor/meta-window-actor-private.h"
|
||||||
#include "core/window-private.h"
|
#include "core/window-private.h"
|
||||||
#include "meta/meta-x11-errors.h"
|
#include "meta/meta-x11-errors.h"
|
||||||
#include "x11/meta-x11-display-private.h"
|
#include "x11/meta-x11-display-private.h"
|
||||||
@@ -71,11 +72,13 @@ static void
|
|||||||
free_damage (MetaSurfaceActorX11 *self)
|
free_damage (MetaSurfaceActorX11 *self)
|
||||||
{
|
{
|
||||||
MetaDisplay *display = self->display;
|
MetaDisplay *display = self->display;
|
||||||
Display *xdisplay = meta_x11_display_get_xdisplay (display->x11_display);
|
Display *xdisplay;
|
||||||
|
|
||||||
if (self->damage == None)
|
if (self->damage == None)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
xdisplay = meta_x11_display_get_xdisplay (display->x11_display);
|
||||||
|
|
||||||
meta_x11_error_trap_push (display->x11_display);
|
meta_x11_error_trap_push (display->x11_display);
|
||||||
XDamageDestroy (xdisplay, self->damage);
|
XDamageDestroy (xdisplay, self->damage);
|
||||||
self->damage = None;
|
self->damage = None;
|
||||||
@@ -86,12 +89,14 @@ static void
|
|||||||
detach_pixmap (MetaSurfaceActorX11 *self)
|
detach_pixmap (MetaSurfaceActorX11 *self)
|
||||||
{
|
{
|
||||||
MetaDisplay *display = self->display;
|
MetaDisplay *display = self->display;
|
||||||
Display *xdisplay = meta_x11_display_get_xdisplay (display->x11_display);
|
|
||||||
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
|
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
|
||||||
|
Display *xdisplay;
|
||||||
|
|
||||||
if (self->pixmap == None)
|
if (self->pixmap == None)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
xdisplay = meta_x11_display_get_xdisplay (display->x11_display);
|
||||||
|
|
||||||
/* Get rid of all references to the pixmap before freeing it; it's unclear whether
|
/* Get rid of all references to the pixmap before freeing it; it's unclear whether
|
||||||
* you are supposed to be able to free a GLXPixmap after freeing the underlying
|
* you are supposed to be able to free a GLXPixmap after freeing the underlying
|
||||||
* pixmap, but it certainly doesn't work with current DRI/Mesa
|
* pixmap, but it certainly doesn't work with current DRI/Mesa
|
||||||
@@ -343,13 +348,19 @@ meta_surface_actor_x11_is_unredirected (MetaSurfaceActor *actor)
|
|||||||
return self->unredirected;
|
return self->unredirected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
release_x11_resources (MetaSurfaceActorX11 *self)
|
||||||
|
{
|
||||||
|
detach_pixmap (self);
|
||||||
|
free_damage (self);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_surface_actor_x11_dispose (GObject *object)
|
meta_surface_actor_x11_dispose (GObject *object)
|
||||||
{
|
{
|
||||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (object);
|
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (object);
|
||||||
|
|
||||||
detach_pixmap (self);
|
release_x11_resources (self);
|
||||||
free_damage (self);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (meta_surface_actor_x11_parent_class)->dispose (object);
|
G_OBJECT_CLASS (meta_surface_actor_x11_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
@@ -403,8 +414,7 @@ window_decorated_notify (MetaWindow *window,
|
|||||||
{
|
{
|
||||||
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (user_data);
|
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (user_data);
|
||||||
|
|
||||||
detach_pixmap (self);
|
release_x11_resources (self);
|
||||||
free_damage (self);
|
|
||||||
create_damage (self);
|
create_damage (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -441,6 +451,10 @@ meta_surface_actor_x11_new (MetaWindow *window)
|
|||||||
g_signal_connect_object (self->window, "notify::decorated",
|
g_signal_connect_object (self->window, "notify::decorated",
|
||||||
G_CALLBACK (window_decorated_notify), self, 0);
|
G_CALLBACK (window_decorated_notify), self, 0);
|
||||||
|
|
||||||
|
g_signal_connect_object (meta_window_actor_from_window (window), "destroy",
|
||||||
|
G_CALLBACK (release_x11_resources), self,
|
||||||
|
G_CONNECT_SWAPPED);
|
||||||
|
|
||||||
self->unredirected = FALSE;
|
self->unredirected = FALSE;
|
||||||
sync_unredirected (self);
|
sync_unredirected (self);
|
||||||
|
|
||||||
|
@@ -52,8 +52,6 @@ typedef enum
|
|||||||
|
|
||||||
typedef struct _MetaWindowActorPrivate
|
typedef struct _MetaWindowActorPrivate
|
||||||
{
|
{
|
||||||
ClutterActor parent;
|
|
||||||
|
|
||||||
MetaWindow *window;
|
MetaWindow *window;
|
||||||
MetaCompositor *compositor;
|
MetaCompositor *compositor;
|
||||||
|
|
||||||
@@ -417,7 +415,7 @@ meta_window_actor_update_surface (MetaWindowActor *self)
|
|||||||
else
|
else
|
||||||
surface_actor = NULL;
|
surface_actor = NULL;
|
||||||
|
|
||||||
set_surface (self, surface_actor);
|
META_WINDOW_ACTOR_GET_CLASS (self)->set_surface_actor (self, surface_actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -430,6 +428,9 @@ meta_window_actor_constructed (GObject *object)
|
|||||||
|
|
||||||
priv->compositor = window->display->compositor;
|
priv->compositor = window->display->compositor;
|
||||||
|
|
||||||
|
/* Hang our compositor window state off the MetaWindow for fast retrieval */
|
||||||
|
meta_window_set_compositor_private (window, object);
|
||||||
|
|
||||||
meta_window_actor_update_surface (self);
|
meta_window_actor_update_surface (self);
|
||||||
|
|
||||||
meta_window_actor_update_opacity (self);
|
meta_window_actor_update_opacity (self);
|
||||||
@@ -446,9 +447,6 @@ meta_window_actor_constructed (GObject *object)
|
|||||||
priv->first_frame_state = DRAWING_FIRST_FRAME;
|
priv->first_frame_state = DRAWING_FIRST_FRAME;
|
||||||
|
|
||||||
meta_window_actor_sync_actor_geometry (self, priv->window->placed);
|
meta_window_actor_sync_actor_geometry (self, priv->window->placed);
|
||||||
|
|
||||||
/* Hang our compositor window state off the MetaWindow for fast retrieval */
|
|
||||||
meta_window_set_compositor_private (window, object);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -476,7 +474,7 @@ meta_window_actor_dispose (GObject *object)
|
|||||||
|
|
||||||
g_clear_object (&priv->window);
|
g_clear_object (&priv->window);
|
||||||
|
|
||||||
set_surface (self, NULL);
|
META_WINDOW_ACTOR_GET_CLASS (self)->set_surface_actor (self, NULL);
|
||||||
|
|
||||||
G_OBJECT_CLASS (meta_window_actor_parent_class)->dispose (object);
|
G_OBJECT_CLASS (meta_window_actor_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
|
@@ -42,6 +42,7 @@
|
|||||||
#include <X11/extensions/Xdamage.h>
|
#include <X11/extensions/Xdamage.h>
|
||||||
#include <X11/extensions/Xfixes.h>
|
#include <X11/extensions/Xfixes.h>
|
||||||
|
|
||||||
|
#include "backends/meta-backend-private.h"
|
||||||
#include "backends/meta-cursor-sprite-xcursor.h"
|
#include "backends/meta-cursor-sprite-xcursor.h"
|
||||||
#include "backends/meta-cursor-tracker-private.h"
|
#include "backends/meta-cursor-tracker-private.h"
|
||||||
#include "backends/meta-idle-monitor-dbus.h"
|
#include "backends/meta-idle-monitor-dbus.h"
|
||||||
@@ -598,27 +599,23 @@ gesture_tracker_state_changed (MetaGestureTracker *tracker,
|
|||||||
MetaSequenceState state,
|
MetaSequenceState state,
|
||||||
MetaDisplay *display)
|
MetaDisplay *display)
|
||||||
{
|
{
|
||||||
if (meta_is_wayland_compositor ())
|
switch (state)
|
||||||
{
|
{
|
||||||
if (state == META_SEQUENCE_ACCEPTED)
|
case META_SEQUENCE_NONE:
|
||||||
meta_display_cancel_touch (display);
|
case META_SEQUENCE_PENDING_END:
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
|
|
||||||
int event_mode;
|
|
||||||
|
|
||||||
if (state == META_SEQUENCE_ACCEPTED)
|
|
||||||
event_mode = XIAcceptTouch;
|
|
||||||
else if (state == META_SEQUENCE_REJECTED)
|
|
||||||
event_mode = XIRejectTouch;
|
|
||||||
else
|
|
||||||
return;
|
return;
|
||||||
|
case META_SEQUENCE_ACCEPTED:
|
||||||
|
meta_display_cancel_touch (display);
|
||||||
|
|
||||||
XIAllowTouchEvents (meta_backend_x11_get_xdisplay (backend),
|
/* Intentional fall-through */
|
||||||
META_VIRTUAL_CORE_POINTER_ID,
|
case META_SEQUENCE_REJECTED:
|
||||||
clutter_x11_event_sequence_get_touch_detail (sequence),
|
{
|
||||||
DefaultRootWindow (display->x11_display->xdisplay), event_mode);
|
MetaBackend *backend;
|
||||||
|
|
||||||
|
backend = meta_get_backend ();
|
||||||
|
meta_backend_finish_touch_sequence (backend, sequence, state);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -920,10 +917,6 @@ meta_display_close (MetaDisplay *display,
|
|||||||
|
|
||||||
g_clear_object (&display->gesture_tracker);
|
g_clear_object (&display->gesture_tracker);
|
||||||
|
|
||||||
g_clear_pointer (&display->stack, meta_stack_free);
|
|
||||||
g_clear_pointer (&display->stack_tracker,
|
|
||||||
meta_stack_tracker_free);
|
|
||||||
|
|
||||||
if (display->focus_timeout_id)
|
if (display->focus_timeout_id)
|
||||||
g_source_remove (display->focus_timeout_id);
|
g_source_remove (display->focus_timeout_id);
|
||||||
display->focus_timeout_id = 0;
|
display->focus_timeout_id = 0;
|
||||||
@@ -940,12 +933,6 @@ meta_display_close (MetaDisplay *display,
|
|||||||
/* Stop caring about events */
|
/* Stop caring about events */
|
||||||
meta_display_free_events (display);
|
meta_display_free_events (display);
|
||||||
|
|
||||||
/* Must be after all calls to meta_window_unmanage() since they
|
|
||||||
* unregister windows
|
|
||||||
*/
|
|
||||||
g_hash_table_destroy (display->wayland_windows);
|
|
||||||
g_hash_table_destroy (display->stamps);
|
|
||||||
|
|
||||||
if (display->compositor)
|
if (display->compositor)
|
||||||
meta_compositor_destroy (display->compositor);
|
meta_compositor_destroy (display->compositor);
|
||||||
|
|
||||||
@@ -956,6 +943,16 @@ meta_display_close (MetaDisplay *display,
|
|||||||
g_clear_object (&display->x11_display);
|
g_clear_object (&display->x11_display);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Must be after all calls to meta_window_unmanage() since they
|
||||||
|
* unregister windows
|
||||||
|
*/
|
||||||
|
g_hash_table_destroy (display->wayland_windows);
|
||||||
|
g_hash_table_destroy (display->stamps);
|
||||||
|
|
||||||
|
g_clear_pointer (&display->stack, meta_stack_free);
|
||||||
|
g_clear_pointer (&display->stack_tracker,
|
||||||
|
meta_stack_tracker_free);
|
||||||
|
|
||||||
meta_display_shutdown_keys (display);
|
meta_display_shutdown_keys (display);
|
||||||
|
|
||||||
g_clear_object (&display->bell);
|
g_clear_object (&display->bell);
|
||||||
|
@@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "backends/meta-backend-private.h"
|
||||||
#include "clutter/clutter.h"
|
#include "clutter/clutter.h"
|
||||||
#include "meta/window.h"
|
#include "meta/window.h"
|
||||||
|
|
||||||
@@ -39,14 +40,6 @@
|
|||||||
typedef struct _MetaGestureTracker MetaGestureTracker;
|
typedef struct _MetaGestureTracker MetaGestureTracker;
|
||||||
typedef struct _MetaGestureTrackerClass MetaGestureTrackerClass;
|
typedef struct _MetaGestureTrackerClass MetaGestureTrackerClass;
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
META_SEQUENCE_NONE,
|
|
||||||
META_SEQUENCE_ACCEPTED,
|
|
||||||
META_SEQUENCE_REJECTED,
|
|
||||||
META_SEQUENCE_PENDING_END
|
|
||||||
} MetaSequenceState;
|
|
||||||
|
|
||||||
struct _MetaGestureTracker
|
struct _MetaGestureTracker
|
||||||
{
|
{
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
|
@@ -110,13 +110,24 @@ static void
|
|||||||
meta_launch_context_constructed (GObject *object)
|
meta_launch_context_constructed (GObject *object)
|
||||||
{
|
{
|
||||||
MetaLaunchContext *context = META_LAUNCH_CONTEXT (object);
|
MetaLaunchContext *context = META_LAUNCH_CONTEXT (object);
|
||||||
|
const char *x11_display, *wayland_display;
|
||||||
|
|
||||||
G_OBJECT_CLASS (meta_launch_context_parent_class)->constructed (object);
|
G_OBJECT_CLASS (meta_launch_context_parent_class)->constructed (object);
|
||||||
|
|
||||||
|
x11_display = getenv ("DISPLAY");
|
||||||
|
wayland_display = getenv ("WAYLAND_DISPLAY");
|
||||||
|
|
||||||
|
if (x11_display)
|
||||||
|
{
|
||||||
g_app_launch_context_setenv (G_APP_LAUNCH_CONTEXT (context),
|
g_app_launch_context_setenv (G_APP_LAUNCH_CONTEXT (context),
|
||||||
"DISPLAY", getenv ("DISPLAY"));
|
"DISPLAY", x11_display);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wayland_display)
|
||||||
|
{
|
||||||
g_app_launch_context_setenv (G_APP_LAUNCH_CONTEXT (context),
|
g_app_launch_context_setenv (G_APP_LAUNCH_CONTEXT (context),
|
||||||
"WAYLAND_DISPLAY", getenv ("WAYLAND_DISPLAY"));
|
"WAYLAND_DISPLAY", wayland_display);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gchar *
|
static gchar *
|
||||||
|
@@ -1194,6 +1194,27 @@ window_contains_point (MetaWindow *window,
|
|||||||
return POINT_IN_RECT (root_x, root_y, rect);
|
return POINT_IN_RECT (root_x, root_y, rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
window_can_get_default_focus (MetaWindow *window)
|
||||||
|
{
|
||||||
|
if (window->unmaps_pending > 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (window->unmanaging)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!meta_window_is_focusable (window))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!meta_window_should_be_showing (window))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (window->type == META_WINDOW_DOCK)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static MetaWindow*
|
static MetaWindow*
|
||||||
get_default_focus_window (MetaStack *stack,
|
get_default_focus_window (MetaStack *stack,
|
||||||
MetaWorkspace *workspace,
|
MetaWorkspace *workspace,
|
||||||
@@ -1221,24 +1242,12 @@ get_default_focus_window (MetaStack *stack,
|
|||||||
if (window == not_this_one)
|
if (window == not_this_one)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (window->unmaps_pending > 0)
|
if (!window_can_get_default_focus (window))
|
||||||
continue;
|
|
||||||
|
|
||||||
if (window->unmanaging)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!meta_window_is_focusable (window))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!meta_window_should_be_showing (window))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (must_be_at_point && !window_contains_point (window, root_x, root_y))
|
if (must_be_at_point && !window_contains_point (window, root_x, root_y))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (window->type == META_WINDOW_DOCK)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1293,6 +1302,26 @@ meta_stack_list_windows (MetaStack *stack,
|
|||||||
return workspace_windows;
|
return workspace_windows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GList *
|
||||||
|
meta_stack_get_default_focus_candidates (MetaStack *stack,
|
||||||
|
MetaWorkspace *workspace)
|
||||||
|
{
|
||||||
|
GList *windows = meta_stack_list_windows (stack, workspace);
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
for (l = windows; l;)
|
||||||
|
{
|
||||||
|
GList *next = l->next;
|
||||||
|
|
||||||
|
if (!window_can_get_default_focus (l->data))
|
||||||
|
windows = g_list_delete_link (windows, l);
|
||||||
|
|
||||||
|
l = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return windows;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
meta_stack_windows_cmp (MetaStack *stack,
|
meta_stack_windows_cmp (MetaStack *stack,
|
||||||
MetaWindow *window_a,
|
MetaWindow *window_a,
|
||||||
|
@@ -337,6 +337,21 @@ MetaWindow* meta_stack_get_default_focus_window_at_point (MetaStack *stack,
|
|||||||
int root_x,
|
int root_x,
|
||||||
int root_y);
|
int root_y);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* meta_stack_get_default_focus_candidates:
|
||||||
|
* @stack: The stack to examine.
|
||||||
|
* @workspace: If not %NULL, only windows on this workspace will be
|
||||||
|
* returned; otherwise all windows in the stack will be
|
||||||
|
* returned.
|
||||||
|
*
|
||||||
|
* Returns all the focus candidate windows in the stack, in order.
|
||||||
|
*
|
||||||
|
* Returns: (transfer container) (element-type Meta.Window):
|
||||||
|
* A #GList of #MetaWindow, in stacking order, honouring layers.
|
||||||
|
*/
|
||||||
|
GList * meta_stack_get_default_focus_candidates (MetaStack *stack,
|
||||||
|
MetaWorkspace *workspace);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* meta_stack_list_windows:
|
* meta_stack_list_windows:
|
||||||
* @stack: The stack to examine.
|
* @stack: The stack to examine.
|
||||||
|
@@ -3683,6 +3683,13 @@ meta_window_activate_full (MetaWindow *window,
|
|||||||
{
|
{
|
||||||
MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
|
MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
|
||||||
gboolean allow_workspace_switch;
|
gboolean allow_workspace_switch;
|
||||||
|
|
||||||
|
if (window->unmanaging)
|
||||||
|
{
|
||||||
|
g_warning ("Trying to activate unmanaged window '%s'", window->desc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
meta_topic (META_DEBUG_FOCUS,
|
meta_topic (META_DEBUG_FOCUS,
|
||||||
"_NET_ACTIVE_WINDOW message sent for %s at time %u "
|
"_NET_ACTIVE_WINDOW message sent for %s at time %u "
|
||||||
"by client type %u.\n",
|
"by client type %u.\n",
|
||||||
@@ -8562,6 +8569,8 @@ meta_window_shortcuts_inhibited (MetaWindow *window,
|
|||||||
gboolean
|
gboolean
|
||||||
meta_window_is_focusable (MetaWindow *window)
|
meta_window_is_focusable (MetaWindow *window)
|
||||||
{
|
{
|
||||||
|
g_return_val_if_fail (!window->unmanaging, FALSE);
|
||||||
|
|
||||||
return META_WINDOW_GET_CLASS (window)->is_focusable (window);
|
return META_WINDOW_GET_CLASS (window)->is_focusable (window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -85,6 +85,12 @@ typedef struct _MetaWorkspaceLogicalMonitorData
|
|||||||
MetaRectangle logical_monitor_work_area;
|
MetaRectangle logical_monitor_work_area;
|
||||||
} MetaWorkspaceLogicalMonitorData;
|
} MetaWorkspaceLogicalMonitorData;
|
||||||
|
|
||||||
|
typedef struct _MetaWorkspaceFocusableAncestorData
|
||||||
|
{
|
||||||
|
MetaWorkspace *workspace;
|
||||||
|
MetaWindow *out_window;
|
||||||
|
} MetaWorkspaceFocusableAncestorData;
|
||||||
|
|
||||||
static MetaWorkspaceLogicalMonitorData *
|
static MetaWorkspaceLogicalMonitorData *
|
||||||
meta_workspace_get_logical_monitor_data (MetaWorkspace *workspace,
|
meta_workspace_get_logical_monitor_data (MetaWorkspace *workspace,
|
||||||
MetaLogicalMonitor *logical_monitor)
|
MetaLogicalMonitor *logical_monitor)
|
||||||
@@ -1322,13 +1328,20 @@ meta_workspace_focus_default_window (MetaWorkspace *workspace,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
record_ancestor (MetaWindow *window,
|
find_focusable_ancestor (MetaWindow *window,
|
||||||
void *data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
MetaWindow **result = data;
|
MetaWorkspaceFocusableAncestorData *data = user_data;
|
||||||
|
|
||||||
*result = window;
|
if (!window->unmanaging && meta_window_is_focusable (window) &&
|
||||||
return FALSE; /* quit with the first ancestor we find */
|
meta_window_located_on_workspace (window, data->workspace) &&
|
||||||
|
meta_window_showing_on_its_workspace (window))
|
||||||
|
{
|
||||||
|
data->out_window = window;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Focus ancestor of not_this_one if there is one */
|
/* Focus ancestor of not_this_one if there is one */
|
||||||
@@ -1350,11 +1363,15 @@ focus_ancestor_or_top_window (MetaWorkspace *workspace,
|
|||||||
if (not_this_one)
|
if (not_this_one)
|
||||||
{
|
{
|
||||||
MetaWindow *ancestor;
|
MetaWindow *ancestor;
|
||||||
ancestor = NULL;
|
MetaWorkspaceFocusableAncestorData data;
|
||||||
meta_window_foreach_ancestor (not_this_one, record_ancestor, &ancestor);
|
|
||||||
if (ancestor != NULL &&
|
data = (MetaWorkspaceFocusableAncestorData) {
|
||||||
meta_window_located_on_workspace (ancestor, workspace) &&
|
.workspace = workspace,
|
||||||
meta_window_showing_on_its_workspace (ancestor))
|
};
|
||||||
|
meta_window_foreach_ancestor (not_this_one, find_focusable_ancestor, &data);
|
||||||
|
ancestor = data.out_window;
|
||||||
|
|
||||||
|
if (ancestor)
|
||||||
{
|
{
|
||||||
meta_topic (META_DEBUG_FOCUS,
|
meta_topic (META_DEBUG_FOCUS,
|
||||||
"Focusing %s, ancestor of %s\n",
|
"Focusing %s, ancestor of %s\n",
|
||||||
|
@@ -32,6 +32,7 @@
|
|||||||
#include "wayland/meta-wayland.h"
|
#include "wayland/meta-wayland.h"
|
||||||
|
|
||||||
#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
|
#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
|
static gboolean
|
||||||
run_tests (gpointer data)
|
run_tests (gpointer data)
|
||||||
@@ -40,6 +41,8 @@ run_tests (gpointer data)
|
|||||||
MetaSettings *settings = meta_backend_get_settings (backend);
|
MetaSettings *settings = meta_backend_get_settings (backend);
|
||||||
gboolean ret;
|
gboolean ret;
|
||||||
|
|
||||||
|
g_test_log_set_fatal_handler (NULL, NULL);
|
||||||
|
|
||||||
meta_settings_override_experimental_features (settings);
|
meta_settings_override_experimental_features (settings);
|
||||||
|
|
||||||
meta_settings_enable_experimental_feature (
|
meta_settings_enable_experimental_feature (
|
||||||
@@ -53,6 +56,20 @@ run_tests (gpointer data)
|
|||||||
return FALSE;
|
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
|
static void
|
||||||
meta_test_headless_start (void)
|
meta_test_headless_start (void)
|
||||||
{
|
{
|
||||||
@@ -193,6 +210,8 @@ main (int argc, char *argv[])
|
|||||||
meta_init ();
|
meta_init ();
|
||||||
meta_register_with_session ();
|
meta_register_with_session ();
|
||||||
|
|
||||||
|
g_test_log_set_fatal_handler (ignore_frame_counter_warning, NULL);
|
||||||
|
|
||||||
g_idle_add (run_tests, NULL);
|
g_idle_add (run_tests, NULL);
|
||||||
|
|
||||||
return meta_run ();
|
return meta_run ();
|
||||||
|
@@ -38,6 +38,7 @@ test_client = executable('mutter-test-client',
|
|||||||
dependencies: [
|
dependencies: [
|
||||||
gtk3_dep,
|
gtk3_dep,
|
||||||
gio_unix_dep,
|
gio_unix_dep,
|
||||||
|
x11_dep,
|
||||||
xext_dep,
|
xext_dep,
|
||||||
],
|
],
|
||||||
install: have_installed_tests,
|
install: have_installed_tests,
|
||||||
@@ -104,6 +105,13 @@ headless_start_test = executable('mutter-headless-start-test',
|
|||||||
stacking_tests = files([
|
stacking_tests = files([
|
||||||
'stacking/basic-x11.metatest',
|
'stacking/basic-x11.metatest',
|
||||||
'stacking/basic-wayland.metatest',
|
'stacking/basic-wayland.metatest',
|
||||||
|
'stacking/closed-transient-no-input-no-take-focus-parent.metatest',
|
||||||
|
'stacking/closed-transient-no-input-no-take-focus-parents.metatest',
|
||||||
|
'stacking/closed-transient-no-input-parent.metatest',
|
||||||
|
'stacking/closed-transient-no-input-parent-delayed-focus-default-cancelled.metatest',
|
||||||
|
'stacking/closed-transient-no-input-parents.metatest',
|
||||||
|
'stacking/closed-transient-no-input-parents-queued-default-focus-destroyed.metatest',
|
||||||
|
'stacking/closed-transient-only-take-focus-parents.metatest',
|
||||||
'stacking/minimized.metatest',
|
'stacking/minimized.metatest',
|
||||||
'stacking/mixed-windows.metatest',
|
'stacking/mixed-windows.metatest',
|
||||||
'stacking/set-parent.metatest',
|
'stacking/set-parent.metatest',
|
||||||
|
@@ -0,0 +1,23 @@
|
|||||||
|
new_client 1 x11
|
||||||
|
create 1/1
|
||||||
|
show 1/1
|
||||||
|
|
||||||
|
create 1/2 csd
|
||||||
|
set_parent 1/2 1
|
||||||
|
can_take_focus 1/2 false
|
||||||
|
accept_focus 1/2 false
|
||||||
|
show 1/2
|
||||||
|
|
||||||
|
create 1/3 csd
|
||||||
|
set_parent 1/3 2
|
||||||
|
show 1/3
|
||||||
|
|
||||||
|
wait
|
||||||
|
assert_focused 1/3
|
||||||
|
assert_stacking 1/1 1/2 1/3
|
||||||
|
|
||||||
|
destroy 1/3
|
||||||
|
|
||||||
|
wait
|
||||||
|
assert_focused 1/1
|
||||||
|
assert_stacking 1/1 1/2
|
@@ -0,0 +1,30 @@
|
|||||||
|
new_client 2 x11
|
||||||
|
create 2/1
|
||||||
|
show 2/1
|
||||||
|
wait
|
||||||
|
|
||||||
|
new_client 1 x11
|
||||||
|
create 1/1
|
||||||
|
accept_focus 1/1 false
|
||||||
|
can_take_focus 1/1 false
|
||||||
|
show 1/1
|
||||||
|
|
||||||
|
create 1/2 csd
|
||||||
|
set_parent 1/2 1
|
||||||
|
can_take_focus 1/2 false
|
||||||
|
accept_focus 1/2 false
|
||||||
|
show 1/2
|
||||||
|
|
||||||
|
create 1/3 csd
|
||||||
|
set_parent 1/3 2
|
||||||
|
show 1/3
|
||||||
|
|
||||||
|
wait
|
||||||
|
assert_focused 1/3
|
||||||
|
assert_stacking 2/1 1/1 1/2 1/3
|
||||||
|
|
||||||
|
destroy 1/3
|
||||||
|
|
||||||
|
wait
|
||||||
|
assert_stacking 1/1 1/2 2/1
|
||||||
|
assert_focused 2/1
|
@@ -0,0 +1,36 @@
|
|||||||
|
new_client 2 x11
|
||||||
|
create 2/1
|
||||||
|
show 2/1
|
||||||
|
|
||||||
|
new_client 1 x11
|
||||||
|
create 1/1
|
||||||
|
show 1/1
|
||||||
|
|
||||||
|
create 1/2 csd
|
||||||
|
set_parent 1/2 1
|
||||||
|
accept_focus 1/2 false
|
||||||
|
show 1/2
|
||||||
|
|
||||||
|
create 1/3 csd
|
||||||
|
set_parent 1/3 2
|
||||||
|
show 1/3
|
||||||
|
|
||||||
|
wait
|
||||||
|
assert_focused 1/3
|
||||||
|
assert_stacking 2/1 1/1 1/2 1/3
|
||||||
|
|
||||||
|
destroy 1/3
|
||||||
|
dispatch
|
||||||
|
|
||||||
|
assert_focused none
|
||||||
|
assert_stacking 2/1 1/1 1/2
|
||||||
|
|
||||||
|
activate 2/1
|
||||||
|
wait
|
||||||
|
|
||||||
|
assert_focused 2/1
|
||||||
|
assert_stacking 1/1 1/2 2/1
|
||||||
|
|
||||||
|
sleep 250
|
||||||
|
assert_focused 2/1
|
||||||
|
assert_stacking 1/1 1/2 2/1
|
30
src/tests/stacking/closed-transient-no-input-parent.metatest
Normal file
30
src/tests/stacking/closed-transient-no-input-parent.metatest
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
new_client 2 x11
|
||||||
|
create 2/1
|
||||||
|
show 2/1
|
||||||
|
|
||||||
|
new_client 1 x11
|
||||||
|
create 1/1
|
||||||
|
show 1/1
|
||||||
|
|
||||||
|
create 1/2 csd
|
||||||
|
set_parent 1/2 1
|
||||||
|
accept_focus 1/2 false
|
||||||
|
show 1/2
|
||||||
|
|
||||||
|
create 1/3 csd
|
||||||
|
set_parent 1/3 2
|
||||||
|
show 1/3
|
||||||
|
|
||||||
|
wait
|
||||||
|
assert_focused 1/3
|
||||||
|
assert_stacking 2/1 1/1 1/2 1/3
|
||||||
|
|
||||||
|
destroy 1/3
|
||||||
|
dispatch
|
||||||
|
|
||||||
|
assert_focused none
|
||||||
|
assert_stacking 2/1 1/1 1/2
|
||||||
|
|
||||||
|
sleep 150
|
||||||
|
assert_focused 1/1
|
||||||
|
assert_stacking 2/1 1/1 1/2
|
@@ -0,0 +1,43 @@
|
|||||||
|
new_client 0 x11
|
||||||
|
create 0/1
|
||||||
|
show 0/1
|
||||||
|
|
||||||
|
new_client 1 x11
|
||||||
|
create 1/1
|
||||||
|
show 1/1
|
||||||
|
|
||||||
|
create 1/2 csd
|
||||||
|
set_parent 1/2 1
|
||||||
|
accept_focus 1/2 false
|
||||||
|
show 1/2
|
||||||
|
|
||||||
|
create 1/3 csd
|
||||||
|
set_parent 1/3 2
|
||||||
|
accept_focus 1/3 false
|
||||||
|
show 1/3
|
||||||
|
|
||||||
|
create 1/4 csd
|
||||||
|
set_parent 1/4 3
|
||||||
|
accept_focus 1/4 false
|
||||||
|
show 1/4
|
||||||
|
|
||||||
|
create 1/5 csd
|
||||||
|
set_parent 1/5 3
|
||||||
|
show 1/5
|
||||||
|
|
||||||
|
wait
|
||||||
|
assert_focused 1/5
|
||||||
|
assert_stacking 0/1 1/1 1/2 1/3 1/4 1/5
|
||||||
|
|
||||||
|
destroy 1/5
|
||||||
|
dispatch
|
||||||
|
|
||||||
|
assert_focused none
|
||||||
|
assert_stacking 0/1 1/1 1/2 1/3 1/4
|
||||||
|
|
||||||
|
destroy 1/2
|
||||||
|
dispatch
|
||||||
|
|
||||||
|
sleep 450
|
||||||
|
assert_focused 1/1
|
||||||
|
assert_stacking 0/1 1/1 1/3 1/4
|
@@ -0,0 +1,46 @@
|
|||||||
|
new_client 0 x11
|
||||||
|
create 0/1
|
||||||
|
show 0/1
|
||||||
|
|
||||||
|
new_client 1 x11
|
||||||
|
create 1/1
|
||||||
|
show 1/1
|
||||||
|
|
||||||
|
create 1/2 csd
|
||||||
|
set_parent 1/2 1
|
||||||
|
accept_focus 1/2 false
|
||||||
|
show 1/2
|
||||||
|
|
||||||
|
create 1/3 csd
|
||||||
|
set_parent 1/3 2
|
||||||
|
accept_focus 1/3 false
|
||||||
|
show 1/3
|
||||||
|
|
||||||
|
create 1/4 csd
|
||||||
|
set_parent 1/4 3
|
||||||
|
accept_focus 1/4 false
|
||||||
|
show 1/4
|
||||||
|
|
||||||
|
create 1/5 csd
|
||||||
|
set_parent 1/5 3
|
||||||
|
show 1/5
|
||||||
|
|
||||||
|
wait
|
||||||
|
assert_focused 1/5
|
||||||
|
assert_stacking 0/1 1/1 1/2 1/3 1/4 1/5
|
||||||
|
|
||||||
|
destroy 1/5
|
||||||
|
dispatch
|
||||||
|
|
||||||
|
assert_focused none
|
||||||
|
assert_stacking 0/1 1/1 1/2 1/3 1/4
|
||||||
|
|
||||||
|
sleep 600
|
||||||
|
assert_focused 1/1
|
||||||
|
assert_stacking 0/1 1/1 1/2 1/3 1/4
|
||||||
|
|
||||||
|
destroy 1/3
|
||||||
|
wait
|
||||||
|
|
||||||
|
assert_focused 1/1
|
||||||
|
assert_stacking 0/1 1/1 1/2 1/4
|
@@ -0,0 +1,34 @@
|
|||||||
|
new_client 0 x11
|
||||||
|
create 0/1
|
||||||
|
show 0/1
|
||||||
|
|
||||||
|
new_client 1 x11
|
||||||
|
create 1/1
|
||||||
|
accept_focus 1/1 false
|
||||||
|
can_take_focus 1/1 true
|
||||||
|
accept_take_focus 1/1 true
|
||||||
|
show 1/1
|
||||||
|
|
||||||
|
create 1/2 csd
|
||||||
|
set_parent 1/2 1
|
||||||
|
accept_focus 1/2 false
|
||||||
|
can_take_focus 1/2 true
|
||||||
|
accept_take_focus 1/2 true
|
||||||
|
show 1/2
|
||||||
|
|
||||||
|
create 1/3
|
||||||
|
set_parent 1/3 2
|
||||||
|
show 1/3
|
||||||
|
|
||||||
|
assert_focused 1/3
|
||||||
|
assert_stacking 0/1 1/1 1/2 1/3
|
||||||
|
|
||||||
|
destroy 1/3
|
||||||
|
wait
|
||||||
|
|
||||||
|
assert_focused 1/2
|
||||||
|
assert_stacking 0/1 1/1 1/2
|
||||||
|
|
||||||
|
sleep 150
|
||||||
|
assert_focused 1/2
|
||||||
|
assert_stacking 0/1 1/1 1/2
|
@@ -31,6 +31,11 @@
|
|||||||
const char *client_id = "0";
|
const char *client_id = "0";
|
||||||
static gboolean wayland;
|
static gboolean wayland;
|
||||||
GHashTable *windows;
|
GHashTable *windows;
|
||||||
|
GQuark event_source_quark;
|
||||||
|
GQuark event_handlers_quark;
|
||||||
|
GQuark can_take_focus_quark;
|
||||||
|
|
||||||
|
typedef void (*XEventHandler) (GtkWidget *window, XEvent *event);
|
||||||
|
|
||||||
static void read_next_line (GDataInputStream *in);
|
static void read_next_line (GDataInputStream *in);
|
||||||
|
|
||||||
@@ -57,6 +62,186 @@ lookup_window (const char *window_id)
|
|||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GSource base;
|
||||||
|
GSource **self_ref;
|
||||||
|
GPollFD event_poll_fd;
|
||||||
|
Display *xdisplay;
|
||||||
|
} XClientEventSource;
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
x_event_source_prepare (GSource *source,
|
||||||
|
int *timeout)
|
||||||
|
{
|
||||||
|
XClientEventSource *x_source = (XClientEventSource *) source;
|
||||||
|
|
||||||
|
*timeout = -1;
|
||||||
|
|
||||||
|
return XPending (x_source->xdisplay);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
x_event_source_check (GSource *source)
|
||||||
|
{
|
||||||
|
XClientEventSource *x_source = (XClientEventSource *) source;
|
||||||
|
|
||||||
|
return XPending (x_source->xdisplay);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
x_event_source_dispatch (GSource *source,
|
||||||
|
GSourceFunc callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
XClientEventSource *x_source = (XClientEventSource *) source;
|
||||||
|
|
||||||
|
while (XPending (x_source->xdisplay))
|
||||||
|
{
|
||||||
|
GHashTableIter iter;
|
||||||
|
XEvent event;
|
||||||
|
gpointer value;
|
||||||
|
|
||||||
|
XNextEvent (x_source->xdisplay, &event);
|
||||||
|
|
||||||
|
g_hash_table_iter_init (&iter, windows);
|
||||||
|
while (g_hash_table_iter_next (&iter, NULL, &value))
|
||||||
|
{
|
||||||
|
GList *l;
|
||||||
|
GtkWidget *window = value;
|
||||||
|
GList *handlers =
|
||||||
|
g_object_get_qdata (G_OBJECT (window), event_handlers_quark);
|
||||||
|
|
||||||
|
for (l = handlers; l; l = l->next)
|
||||||
|
{
|
||||||
|
XEventHandler handler = l->data;
|
||||||
|
handler (window, &event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
x_event_source_finalize (GSource *source)
|
||||||
|
{
|
||||||
|
XClientEventSource *x_source = (XClientEventSource *) source;
|
||||||
|
|
||||||
|
*x_source->self_ref = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GSourceFuncs x_event_funcs = {
|
||||||
|
x_event_source_prepare,
|
||||||
|
x_event_source_check,
|
||||||
|
x_event_source_dispatch,
|
||||||
|
x_event_source_finalize,
|
||||||
|
};
|
||||||
|
|
||||||
|
static GSource*
|
||||||
|
ensure_xsource_handler (GdkDisplay *gdkdisplay)
|
||||||
|
{
|
||||||
|
static GSource *source = NULL;
|
||||||
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdkdisplay);
|
||||||
|
XClientEventSource *x_source;
|
||||||
|
|
||||||
|
if (source)
|
||||||
|
return g_source_ref (source);
|
||||||
|
|
||||||
|
source = g_source_new (&x_event_funcs, sizeof (XClientEventSource));
|
||||||
|
x_source = (XClientEventSource *) source;
|
||||||
|
x_source->self_ref = &source;
|
||||||
|
x_source->xdisplay = xdisplay;
|
||||||
|
x_source->event_poll_fd.fd = ConnectionNumber (xdisplay);
|
||||||
|
x_source->event_poll_fd.events = G_IO_IN;
|
||||||
|
g_source_add_poll (source, &x_source->event_poll_fd);
|
||||||
|
|
||||||
|
g_source_set_priority (source, GDK_PRIORITY_EVENTS - 1);
|
||||||
|
g_source_set_can_recurse (source, TRUE);
|
||||||
|
g_source_attach (source, NULL);
|
||||||
|
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
window_has_x11_event_handler (GtkWidget *window,
|
||||||
|
XEventHandler handler)
|
||||||
|
{
|
||||||
|
GList *handlers =
|
||||||
|
g_object_get_qdata (G_OBJECT (window), event_handlers_quark);
|
||||||
|
|
||||||
|
g_return_val_if_fail (handler, FALSE);
|
||||||
|
g_return_val_if_fail (!wayland, FALSE);
|
||||||
|
|
||||||
|
return g_list_find (handlers, handler) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
unref_and_maybe_destroy_gsource (GSource *source)
|
||||||
|
{
|
||||||
|
g_source_unref (source);
|
||||||
|
|
||||||
|
if (source->ref_count == 1)
|
||||||
|
g_source_destroy (source);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
window_add_x11_event_handler (GtkWidget *window,
|
||||||
|
XEventHandler handler)
|
||||||
|
{
|
||||||
|
GSource *source;
|
||||||
|
GList *handlers =
|
||||||
|
g_object_get_qdata (G_OBJECT (window), event_handlers_quark);
|
||||||
|
|
||||||
|
g_return_if_fail (!window_has_x11_event_handler (window, handler));
|
||||||
|
|
||||||
|
source = ensure_xsource_handler (gtk_widget_get_display (window));
|
||||||
|
g_object_set_qdata_full (G_OBJECT (window), event_source_quark, source,
|
||||||
|
(GDestroyNotify) unref_and_maybe_destroy_gsource);
|
||||||
|
|
||||||
|
handlers = g_list_append (handlers, handler);
|
||||||
|
g_object_set_qdata (G_OBJECT (window), event_handlers_quark, handlers);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
window_remove_x11_event_handler (GtkWidget *window,
|
||||||
|
XEventHandler handler)
|
||||||
|
{
|
||||||
|
GList *handlers =
|
||||||
|
g_object_get_qdata (G_OBJECT (window), event_handlers_quark);
|
||||||
|
|
||||||
|
g_return_if_fail (window_has_x11_event_handler (window, handler));
|
||||||
|
|
||||||
|
g_object_set_qdata (G_OBJECT (window), event_source_quark, NULL);
|
||||||
|
|
||||||
|
handlers = g_list_remove (handlers, handler);
|
||||||
|
g_object_set_qdata (G_OBJECT (window), event_handlers_quark, handlers);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_take_focus (GtkWidget *window,
|
||||||
|
XEvent *xevent)
|
||||||
|
{
|
||||||
|
GdkWindow *gdkwindow = gtk_widget_get_window (window);
|
||||||
|
GdkDisplay *display = gtk_widget_get_display (window);
|
||||||
|
Atom wm_protocols =
|
||||||
|
gdk_x11_get_xatom_by_name_for_display (display, "WM_PROTOCOLS");
|
||||||
|
Atom wm_take_focus =
|
||||||
|
gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
|
||||||
|
|
||||||
|
if (xevent->xany.type != ClientMessage ||
|
||||||
|
xevent->xany.window != GDK_WINDOW_XID (gdkwindow))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (xevent->xclient.message_type == wm_protocols &&
|
||||||
|
xevent->xclient.data.l[0] == wm_take_focus)
|
||||||
|
{
|
||||||
|
XSetInputFocus (xevent->xany.display,
|
||||||
|
GDK_WINDOW_XID (gdkwindow),
|
||||||
|
RevertToParent,
|
||||||
|
xevent->xclient.data.l[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
process_line (const char *line)
|
process_line (const char *line)
|
||||||
{
|
{
|
||||||
@@ -125,6 +310,9 @@ process_line (const char *line)
|
|||||||
gtk_window_set_title (GTK_WINDOW (window), title);
|
gtk_window_set_title (GTK_WINDOW (window), title);
|
||||||
g_free (title);
|
g_free (title);
|
||||||
|
|
||||||
|
g_object_set_qdata (G_OBJECT (window), can_take_focus_quark,
|
||||||
|
GUINT_TO_POINTER (TRUE));
|
||||||
|
|
||||||
gtk_widget_realize (window);
|
gtk_widget_realize (window);
|
||||||
|
|
||||||
if (!wayland)
|
if (!wayland)
|
||||||
@@ -196,6 +384,130 @@ process_line (const char *line)
|
|||||||
NULL))
|
NULL))
|
||||||
g_print ("Fail to export handle for window id %s", argv[2]);
|
g_print ("Fail to export handle for window id %s", argv[2]);
|
||||||
}
|
}
|
||||||
|
else if (strcmp (argv[0], "accept_focus") == 0)
|
||||||
|
{
|
||||||
|
if (argc != 3)
|
||||||
|
{
|
||||||
|
g_print ("usage: %s <window-id> [true|false]", argv[0]);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget *window = lookup_window (argv[1]);
|
||||||
|
if (!window)
|
||||||
|
{
|
||||||
|
g_print ("unknown window %s", argv[1]);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wayland &&
|
||||||
|
window_has_x11_event_handler (window, handle_take_focus))
|
||||||
|
{
|
||||||
|
g_print ("Impossible to use %s for windows accepting take focus",
|
||||||
|
argv[1]);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean enabled = g_ascii_strcasecmp (argv[2], "true") == 0;
|
||||||
|
gtk_window_set_accept_focus (GTK_WINDOW (window), enabled);
|
||||||
|
}
|
||||||
|
else if (strcmp (argv[0], "can_take_focus") == 0)
|
||||||
|
{
|
||||||
|
if (argc != 3)
|
||||||
|
{
|
||||||
|
g_print ("usage: %s <window-id> [true|false]", argv[0]);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget *window = lookup_window (argv[1]);
|
||||||
|
if (!window)
|
||||||
|
{
|
||||||
|
g_print ("unknown window %s", argv[1]);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wayland)
|
||||||
|
{
|
||||||
|
g_print ("%s not supported under wayland", argv[0]);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window_has_x11_event_handler (window, handle_take_focus))
|
||||||
|
{
|
||||||
|
g_print ("Impossible to change %s for windows accepting take focus",
|
||||||
|
argv[1]);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
GdkDisplay *display = gdk_display_get_default ();
|
||||||
|
GdkWindow *gdkwindow = gtk_widget_get_window (window);
|
||||||
|
Display *xdisplay = gdk_x11_display_get_xdisplay (display);
|
||||||
|
Window xwindow = GDK_WINDOW_XID (gdkwindow);
|
||||||
|
Atom wm_take_focus = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
|
||||||
|
gboolean add = g_ascii_strcasecmp(argv[2], "true") == 0;
|
||||||
|
Atom *protocols = NULL;
|
||||||
|
Atom *new_protocols;
|
||||||
|
int n_protocols = 0;
|
||||||
|
int i, n = 0;
|
||||||
|
|
||||||
|
gdk_display_sync (display);
|
||||||
|
XGetWMProtocols (xdisplay, xwindow, &protocols, &n_protocols);
|
||||||
|
new_protocols = g_new0 (Atom, n_protocols + (add ? 1 : 0));
|
||||||
|
|
||||||
|
for (i = 0; i < n_protocols; ++i)
|
||||||
|
{
|
||||||
|
if (protocols[i] != wm_take_focus)
|
||||||
|
new_protocols[n++] = protocols[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (add)
|
||||||
|
new_protocols[n++] = wm_take_focus;
|
||||||
|
|
||||||
|
XSetWMProtocols (xdisplay, xwindow, new_protocols, n);
|
||||||
|
g_object_set_qdata (G_OBJECT (window), can_take_focus_quark,
|
||||||
|
GUINT_TO_POINTER (add));
|
||||||
|
|
||||||
|
XFree (new_protocols);
|
||||||
|
XFree (protocols);
|
||||||
|
}
|
||||||
|
else if (strcmp (argv[0], "accept_take_focus") == 0)
|
||||||
|
{
|
||||||
|
if (argc != 3)
|
||||||
|
{
|
||||||
|
g_print ("usage: %s <window-id> [true|false]", argv[0]);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget *window = lookup_window (argv[1]);
|
||||||
|
if (!window)
|
||||||
|
{
|
||||||
|
g_print ("unknown window %s", argv[1]);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wayland)
|
||||||
|
{
|
||||||
|
g_print ("%s not supported under wayland", argv[0]);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gtk_window_get_accept_focus (GTK_WINDOW (window)))
|
||||||
|
{
|
||||||
|
g_print ("%s not supported for input windows", argv[0]);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_object_get_qdata (G_OBJECT (window), can_take_focus_quark))
|
||||||
|
{
|
||||||
|
g_print ("%s not supported for windows with no WM_TAKE_FOCUS set",
|
||||||
|
argv[0]);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_ascii_strcasecmp (argv[2], "true") == 0)
|
||||||
|
window_add_x11_event_handler (window, handle_take_focus);
|
||||||
|
else
|
||||||
|
window_remove_x11_event_handler (window, handle_take_focus);
|
||||||
|
}
|
||||||
else if (strcmp (argv[0], "show") == 0)
|
else if (strcmp (argv[0], "show") == 0)
|
||||||
{
|
{
|
||||||
if (argc != 2)
|
if (argc != 2)
|
||||||
@@ -460,6 +772,9 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
windows = g_hash_table_new_full (g_str_hash, g_str_equal,
|
windows = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||||
g_free, NULL);
|
g_free, NULL);
|
||||||
|
event_source_quark = g_quark_from_static_string ("event-source");
|
||||||
|
event_handlers_quark = g_quark_from_static_string ("event-handlers");
|
||||||
|
can_take_focus_quark = g_quark_from_static_string ("can-take-focus");
|
||||||
|
|
||||||
GInputStream *raw_in = g_unix_input_stream_new (0, FALSE);
|
GInputStream *raw_in = g_unix_input_stream_new (0, FALSE);
|
||||||
GDataInputStream *in = g_data_input_stream_new (raw_in);
|
GDataInputStream *in = g_data_input_stream_new (raw_in);
|
||||||
|
@@ -77,7 +77,7 @@ test_case_new (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
test_case_before_redraw (gpointer data)
|
test_case_loop_quit (gpointer data)
|
||||||
{
|
{
|
||||||
TestCase *test = data;
|
TestCase *test = data;
|
||||||
|
|
||||||
@@ -86,6 +86,24 @@ test_case_before_redraw (gpointer data)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
test_case_dispatch (TestCase *test,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
/* Wait until we've done any outstanding queued up work.
|
||||||
|
* Though we add this as BEFORE_REDRAW, the iteration that runs the
|
||||||
|
* BEFORE_REDRAW idles will proceed on and do the redraw, so we're
|
||||||
|
* waiting until after *all* frame processing.
|
||||||
|
*/
|
||||||
|
meta_later_add (META_LATER_BEFORE_REDRAW,
|
||||||
|
test_case_loop_quit,
|
||||||
|
test,
|
||||||
|
NULL);
|
||||||
|
g_main_loop_run (test->loop);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
test_case_wait (TestCase *test,
|
test_case_wait (TestCase *test,
|
||||||
GError **error)
|
GError **error)
|
||||||
@@ -102,16 +120,8 @@ test_case_wait (TestCase *test,
|
|||||||
if (!test_client_wait (value, error))
|
if (!test_client_wait (value, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* Then wait until we've done any outstanding queued up work.
|
/* Then wait until we've done any outstanding queued up work. */
|
||||||
* Though we add this as BEFORE_REDRAW, the iteration that runs the
|
test_case_dispatch (test, error);
|
||||||
* BEFORE_REDRAW idles will proceed on and do the redraw, so we're
|
|
||||||
* waiting until after *all* frame processing.
|
|
||||||
*/
|
|
||||||
meta_later_add (META_LATER_BEFORE_REDRAW,
|
|
||||||
test_case_before_redraw,
|
|
||||||
test,
|
|
||||||
NULL);
|
|
||||||
g_main_loop_run (test->loop);
|
|
||||||
|
|
||||||
/* Then set an XSync counter ourselves and and wait until
|
/* Then set an XSync counter ourselves and and wait until
|
||||||
* we receive the resulting event - this makes sure that we've
|
* we receive the resulting event - this makes sure that we've
|
||||||
@@ -121,6 +131,17 @@ test_case_wait (TestCase *test,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
test_case_sleep (TestCase *test,
|
||||||
|
guint32 interval,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_timeout_add_full (G_PRIORITY_LOW, interval, test_case_loop_quit, test, NULL);
|
||||||
|
g_main_loop_run (test->loop);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
#define BAD_COMMAND(...) \
|
#define BAD_COMMAND(...) \
|
||||||
G_STMT_START { \
|
G_STMT_START { \
|
||||||
g_set_error (error, \
|
g_set_error (error, \
|
||||||
@@ -237,6 +258,37 @@ test_case_assert_stacking (TestCase *test,
|
|||||||
return *error == NULL;
|
return *error == NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
test_case_assert_focused (TestCase *test,
|
||||||
|
const char *expected_window,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
MetaDisplay *display = meta_get_display ();
|
||||||
|
|
||||||
|
if (!display->focus_window)
|
||||||
|
{
|
||||||
|
if (g_strcmp0 (expected_window, "none") != 0)
|
||||||
|
{
|
||||||
|
g_set_error (error, TEST_RUNNER_ERROR, TEST_RUNNER_ERROR_ASSERTION_FAILED,
|
||||||
|
"focus: expected='%s', actual='none'", expected_window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const char *focused = display->focus_window->title;
|
||||||
|
|
||||||
|
if (g_str_has_prefix (focused, "test/"))
|
||||||
|
focused += 5;
|
||||||
|
|
||||||
|
if (g_strcmp0 (focused, expected_window) != 0)
|
||||||
|
g_set_error (error, TEST_RUNNER_ERROR, TEST_RUNNER_ERROR_ASSERTION_FAILED,
|
||||||
|
"focus: expected='%s', actual='%s'",
|
||||||
|
expected_window, focused);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *error == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
test_case_check_xserver_stacking (TestCase *test,
|
test_case_check_xserver_stacking (TestCase *test,
|
||||||
GError **error)
|
GError **error)
|
||||||
@@ -385,6 +437,9 @@ test_case_do (TestCase *test,
|
|||||||
argc == 3 ? argv[2] : NULL,
|
argc == 3 ? argv[2] : NULL,
|
||||||
NULL))
|
NULL))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
if (!test_client_wait (client, error))
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
else if (strcmp (argv[0], "set_parent") == 0 ||
|
else if (strcmp (argv[0], "set_parent") == 0 ||
|
||||||
strcmp (argv[0], "set_parent_exported") == 0)
|
strcmp (argv[0], "set_parent_exported") == 0)
|
||||||
@@ -398,6 +453,63 @@ test_case_do (TestCase *test,
|
|||||||
if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error))
|
if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
if (!test_client_do (client, error,
|
||||||
|
argv[0], window_id,
|
||||||
|
argv[2],
|
||||||
|
NULL))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else if (strcmp (argv[0], "accept_focus") == 0)
|
||||||
|
{
|
||||||
|
if (argc != 3 ||
|
||||||
|
(g_ascii_strcasecmp (argv[2], "true") != 0 &&
|
||||||
|
g_ascii_strcasecmp (argv[2], "false") != 0))
|
||||||
|
BAD_COMMAND("usage: %s <client-id>/<window-id> [true|false]",
|
||||||
|
argv[0]);
|
||||||
|
|
||||||
|
TestClient *client;
|
||||||
|
const char *window_id;
|
||||||
|
if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!test_client_do (client, error,
|
||||||
|
argv[0], window_id,
|
||||||
|
argv[2],
|
||||||
|
NULL))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else if (strcmp (argv[0], "can_take_focus") == 0)
|
||||||
|
{
|
||||||
|
if (argc != 3 ||
|
||||||
|
(g_ascii_strcasecmp (argv[2], "true") != 0 &&
|
||||||
|
g_ascii_strcasecmp (argv[2], "false") != 0))
|
||||||
|
BAD_COMMAND("usage: %s <client-id>/<window-id> [true|false]",
|
||||||
|
argv[0]);
|
||||||
|
|
||||||
|
TestClient *client;
|
||||||
|
const char *window_id;
|
||||||
|
if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!test_client_do (client, error,
|
||||||
|
argv[0], window_id,
|
||||||
|
argv[2],
|
||||||
|
NULL))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else if (strcmp (argv[0], "accept_take_focus") == 0)
|
||||||
|
{
|
||||||
|
if (argc != 3 ||
|
||||||
|
(g_ascii_strcasecmp (argv[2], "true") != 0 &&
|
||||||
|
g_ascii_strcasecmp (argv[2], "false") != 0))
|
||||||
|
BAD_COMMAND("usage: %s <client-id>/<window-id> [true|false]",
|
||||||
|
argv[0]);
|
||||||
|
|
||||||
|
TestClient *client;
|
||||||
|
const char *window_id;
|
||||||
|
if (!test_case_parse_window_id (test, argv[1], &client, &window_id, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (!test_client_do (client, error,
|
if (!test_client_do (client, error,
|
||||||
argv[0], window_id,
|
argv[0], window_id,
|
||||||
argv[2],
|
argv[2],
|
||||||
@@ -477,6 +589,28 @@ test_case_do (TestCase *test,
|
|||||||
if (!test_case_wait (test, error))
|
if (!test_case_wait (test, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
else if (strcmp (argv[0], "dispatch") == 0)
|
||||||
|
{
|
||||||
|
if (argc != 1)
|
||||||
|
BAD_COMMAND("usage: %s", argv[0]);
|
||||||
|
|
||||||
|
if (!test_case_dispatch (test, error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else if (strcmp (argv[0], "sleep") == 0)
|
||||||
|
{
|
||||||
|
guint64 interval;
|
||||||
|
|
||||||
|
if (argc != 2)
|
||||||
|
BAD_COMMAND("usage: %s <milliseconds>", argv[0]);
|
||||||
|
|
||||||
|
if (!g_ascii_string_to_unsigned (argv[1], 10, 0, G_MAXUINT32,
|
||||||
|
&interval, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!test_case_sleep (test, (guint32) interval, error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
else if (strcmp (argv[0], "assert_stacking") == 0)
|
else if (strcmp (argv[0], "assert_stacking") == 0)
|
||||||
{
|
{
|
||||||
if (!test_case_assert_stacking (test, argv + 1, argc - 1, error))
|
if (!test_case_assert_stacking (test, argv + 1, argc - 1, error))
|
||||||
@@ -485,6 +619,11 @@ test_case_do (TestCase *test,
|
|||||||
if (!test_case_check_xserver_stacking (test, error))
|
if (!test_case_check_xserver_stacking (test, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
else if (strcmp (argv[0], "assert_focused") == 0)
|
||||||
|
{
|
||||||
|
if (!test_case_assert_focused (test, argv[1], error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BAD_COMMAND("Unknown command %s", argv[0]);
|
BAD_COMMAND("Unknown command %s", argv[0]);
|
||||||
|
@@ -170,8 +170,9 @@ meta_wayland_cursor_surface_commit (MetaWaylandSurfaceRole *surface_role,
|
|||||||
wl_list_init (&pending->frame_callback_list);
|
wl_list_init (&pending->frame_callback_list);
|
||||||
|
|
||||||
if (pending->newly_attached &&
|
if (pending->newly_attached &&
|
||||||
(!cairo_region_is_empty (pending->surface_damage) ||
|
((!cairo_region_is_empty (pending->surface_damage) ||
|
||||||
!cairo_region_is_empty (pending->buffer_damage)))
|
!cairo_region_is_empty (pending->buffer_damage)) ||
|
||||||
|
!priv->buffer))
|
||||||
update_cursor_sprite_texture (META_WAYLAND_CURSOR_SURFACE (surface_role));
|
update_cursor_sprite_texture (META_WAYLAND_CURSOR_SURFACE (surface_role));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -266,7 +266,7 @@ meta_wayland_seat_free (MetaWaylandSeat *seat)
|
|||||||
meta_wayland_gtk_text_input_destroy (seat->gtk_text_input);
|
meta_wayland_gtk_text_input_destroy (seat->gtk_text_input);
|
||||||
meta_wayland_text_input_destroy (seat->text_input);
|
meta_wayland_text_input_destroy (seat->text_input);
|
||||||
|
|
||||||
g_slice_free (MetaWaylandSeat, seat);
|
g_free (seat);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@@ -737,6 +737,10 @@ meta_wayland_surface_apply_pending_state (MetaWaylandSurface *surface,
|
|||||||
g_clear_pointer (&snippet, cogl_object_unref);
|
g_clear_pointer (&snippet, cogl_object_unref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cogl_clear_object (&surface->texture);
|
||||||
|
}
|
||||||
|
|
||||||
/* If the newly attached buffer is going to be accessed directly without
|
/* If the newly attached buffer is going to be accessed directly without
|
||||||
* making a copy, such as an EGL buffer, mark it as in-use don't release
|
* making a copy, such as an EGL buffer, mark it as in-use don't release
|
||||||
|
@@ -50,6 +50,8 @@
|
|||||||
#include "x11/window-props.h"
|
#include "x11/window-props.h"
|
||||||
#include "x11/xprops.h"
|
#include "x11/xprops.h"
|
||||||
|
|
||||||
|
#define TAKE_FOCUS_FALLBACK_DELAY_MS 150
|
||||||
|
|
||||||
enum _MetaGtkEdgeConstraints
|
enum _MetaGtkEdgeConstraints
|
||||||
{
|
{
|
||||||
META_GTK_EDGE_CONSTRAINT_TOP_TILED = 1 << 0,
|
META_GTK_EDGE_CONSTRAINT_TOP_TILED = 1 << 0,
|
||||||
@@ -64,6 +66,11 @@ enum _MetaGtkEdgeConstraints
|
|||||||
|
|
||||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaWindowX11, meta_window_x11, META_TYPE_WINDOW)
|
G_DEFINE_TYPE_WITH_PRIVATE (MetaWindowX11, meta_window_x11, META_TYPE_WINDOW)
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_window_x11_maybe_focus_delayed (MetaWindow *window,
|
||||||
|
GQueue *other_focus_candidates,
|
||||||
|
guint32 timestamp);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_window_x11_init (MetaWindowX11 *window_x11)
|
meta_window_x11_init (MetaWindowX11 *window_x11)
|
||||||
{
|
{
|
||||||
@@ -776,6 +783,158 @@ request_take_focus (MetaWindow *window,
|
|||||||
send_icccm_message (window, display->x11_display->atom_WM_TAKE_FOCUS, timestamp);
|
send_icccm_message (window, display->x11_display->atom_WM_TAKE_FOCUS, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
MetaWindow *window;
|
||||||
|
GQueue *pending_focus_candidates;
|
||||||
|
guint32 timestamp;
|
||||||
|
guint timeout_id;
|
||||||
|
gulong unmanaged_id;
|
||||||
|
gulong focused_changed_id;
|
||||||
|
} MetaWindowX11DelayedFocusData;
|
||||||
|
|
||||||
|
static void
|
||||||
|
disconnect_pending_focus_window_signals (MetaWindow *window,
|
||||||
|
GQueue *focus_candidates)
|
||||||
|
{
|
||||||
|
g_signal_handlers_disconnect_by_func (window, g_queue_remove,
|
||||||
|
focus_candidates);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_window_x11_delayed_focus_data_free (MetaWindowX11DelayedFocusData *data)
|
||||||
|
{
|
||||||
|
g_signal_handler_disconnect (data->window, data->unmanaged_id);
|
||||||
|
g_signal_handler_disconnect (data->window->display, data->focused_changed_id);
|
||||||
|
|
||||||
|
if (data->pending_focus_candidates)
|
||||||
|
{
|
||||||
|
g_queue_foreach (data->pending_focus_candidates,
|
||||||
|
(GFunc) disconnect_pending_focus_window_signals,
|
||||||
|
data->pending_focus_candidates);
|
||||||
|
g_queue_free (data->pending_focus_candidates);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_handle_id (&data->timeout_id, g_source_remove);
|
||||||
|
g_free (data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
focus_candidates_maybe_take_and_focus_next (GQueue **focus_candidates_ptr,
|
||||||
|
guint32 timestamp)
|
||||||
|
{
|
||||||
|
MetaWindow *focus_window;
|
||||||
|
GQueue *focus_candidates;
|
||||||
|
|
||||||
|
g_assert (*focus_candidates_ptr);
|
||||||
|
|
||||||
|
if (g_queue_is_empty (*focus_candidates_ptr))
|
||||||
|
return;
|
||||||
|
|
||||||
|
focus_candidates = g_steal_pointer (focus_candidates_ptr);
|
||||||
|
focus_window = g_queue_pop_head (focus_candidates);
|
||||||
|
|
||||||
|
disconnect_pending_focus_window_signals (focus_window, focus_candidates);
|
||||||
|
meta_window_x11_maybe_focus_delayed (focus_window, focus_candidates, timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
focus_window_delayed_timeout (gpointer user_data)
|
||||||
|
{
|
||||||
|
MetaWindowX11DelayedFocusData *data = user_data;
|
||||||
|
MetaWindow *window = data->window;
|
||||||
|
guint32 timestamp = data->timestamp;
|
||||||
|
|
||||||
|
focus_candidates_maybe_take_and_focus_next (&data->pending_focus_candidates,
|
||||||
|
timestamp);
|
||||||
|
|
||||||
|
data->timeout_id = 0;
|
||||||
|
meta_window_x11_delayed_focus_data_free (data);
|
||||||
|
|
||||||
|
meta_window_focus (window, timestamp);
|
||||||
|
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_window_x11_maybe_focus_delayed (MetaWindow *window,
|
||||||
|
GQueue *other_focus_candidates,
|
||||||
|
guint32 timestamp)
|
||||||
|
{
|
||||||
|
MetaWindowX11DelayedFocusData *data;
|
||||||
|
|
||||||
|
data = g_new0 (MetaWindowX11DelayedFocusData, 1);
|
||||||
|
data->window = window;
|
||||||
|
data->timestamp = timestamp;
|
||||||
|
data->pending_focus_candidates = other_focus_candidates;
|
||||||
|
|
||||||
|
meta_topic (META_DEBUG_FOCUS,
|
||||||
|
"Requesting delayed focus to %s\n", window->desc);
|
||||||
|
|
||||||
|
data->unmanaged_id =
|
||||||
|
g_signal_connect_swapped (window, "unmanaged",
|
||||||
|
G_CALLBACK (meta_window_x11_delayed_focus_data_free),
|
||||||
|
data);
|
||||||
|
|
||||||
|
data->focused_changed_id =
|
||||||
|
g_signal_connect_swapped (window->display, "notify::focus-window",
|
||||||
|
G_CALLBACK (meta_window_x11_delayed_focus_data_free),
|
||||||
|
data);
|
||||||
|
|
||||||
|
data->timeout_id = g_timeout_add (TAKE_FOCUS_FALLBACK_DELAY_MS,
|
||||||
|
focus_window_delayed_timeout, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
maybe_focus_default_window (MetaDisplay *display,
|
||||||
|
MetaWindow *not_this_one,
|
||||||
|
guint32 timestamp)
|
||||||
|
{
|
||||||
|
MetaWorkspace *workspace;
|
||||||
|
MetaStack *stack = display->stack;
|
||||||
|
g_autoptr (GList) focusable_windows = NULL;
|
||||||
|
g_autoptr (GQueue) focus_candidates = NULL;
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
if (not_this_one && not_this_one->workspace)
|
||||||
|
workspace = not_this_one->workspace;
|
||||||
|
else
|
||||||
|
workspace = display->workspace_manager->active_workspace;
|
||||||
|
|
||||||
|
/* Go through all the focusable windows and try to focus them
|
||||||
|
* in order, waiting for a delay. The first one that replies to
|
||||||
|
* the request (in case of take focus windows) changing the display
|
||||||
|
* focused window, will stop the chained requests.
|
||||||
|
*/
|
||||||
|
focusable_windows =
|
||||||
|
meta_stack_get_default_focus_candidates (stack, workspace);
|
||||||
|
focus_candidates = g_queue_new ();
|
||||||
|
|
||||||
|
for (l = g_list_last (focusable_windows); l; l = l->prev)
|
||||||
|
{
|
||||||
|
MetaWindow *focus_window = l->data;
|
||||||
|
|
||||||
|
if (focus_window == not_this_one)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
g_queue_push_tail (focus_candidates, focus_window);
|
||||||
|
g_signal_connect_swapped (focus_window, "unmanaged",
|
||||||
|
G_CALLBACK (g_queue_remove),
|
||||||
|
focus_candidates);
|
||||||
|
|
||||||
|
if (!META_IS_WINDOW_X11 (focus_window))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (focus_window->input)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (focus_window->shaded && focus_window->frame)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
focus_candidates_maybe_take_and_focus_next (&focus_candidates, timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_window_x11_focus (MetaWindow *window,
|
meta_window_x11_focus (MetaWindow *window,
|
||||||
guint32 timestamp)
|
guint32 timestamp)
|
||||||
@@ -827,13 +986,20 @@ meta_window_x11_focus (MetaWindow *window,
|
|||||||
* Normally, we want to just leave the focus undisturbed until
|
* Normally, we want to just leave the focus undisturbed until
|
||||||
* the window responds to WM_TAKE_FOCUS, but if we're unmanaging
|
* the window responds to WM_TAKE_FOCUS, but if we're unmanaging
|
||||||
* the current focus window we *need* to move the focus away, so
|
* the current focus window we *need* to move the focus away, so
|
||||||
* we focus the no_focus_window now (and set
|
* we focus the no focus window before sending WM_TAKE_FOCUS,
|
||||||
* display->focus_window to that) before sending WM_TAKE_FOCUS.
|
* and eventually the default focus windwo excluding this one,
|
||||||
|
* if meanwhile we don't get any focus request.
|
||||||
*/
|
*/
|
||||||
if (window->display->focus_window != NULL &&
|
if (window->display->focus_window != NULL &&
|
||||||
window->display->focus_window->unmanaging)
|
window->display->focus_window->unmanaging)
|
||||||
meta_x11_display_focus_the_no_focus_window (window->display->x11_display,
|
{
|
||||||
|
MetaX11Display *x11_display = window->display->x11_display;
|
||||||
|
|
||||||
|
meta_x11_display_focus_the_no_focus_window (x11_display,
|
||||||
timestamp);
|
timestamp);
|
||||||
|
maybe_focus_default_window (window->display, window,
|
||||||
|
timestamp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
request_take_focus (window, timestamp);
|
request_take_focus (window, timestamp);
|
||||||
|
Reference in New Issue
Block a user