Compare commits
14 Commits
citadel
...
wip/3v1n0/
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9056fb00b0 | ||
![]() |
0503ecaf84 | ||
![]() |
dec20d13e1 | ||
![]() |
0242c1a527 | ||
![]() |
8652ec9ee2 | ||
![]() |
4c607164fd | ||
![]() |
08f920606e | ||
![]() |
ef3ea0a59c | ||
![]() |
a5f360cb9e | ||
![]() |
26cb0a5a75 | ||
![]() |
7c89167644 | ||
![]() |
984d27f050 | ||
![]() |
5b13372fd4 | ||
![]() |
4334534742 |
@ -2,10 +2,45 @@ image: registry.gitlab.gnome.org/gnome/mutter/master:v1
|
|||||||
|
|
||||||
stages:
|
stages:
|
||||||
- build
|
- build
|
||||||
|
- test
|
||||||
|
|
||||||
build-mutter:
|
build-mutter:
|
||||||
stage: build
|
stage: build
|
||||||
script:
|
script:
|
||||||
- meson . build -Degl_device=true -Dwayland_eglstream=true
|
- meson . build -Degl_device=true -Dwayland_eglstream=true -Dheadless_tests=enabled
|
||||||
- ninja -C build
|
- ninja -C build
|
||||||
- ninja -C build install
|
- ninja -C build install
|
||||||
|
- meson test -v -C build --suite headless
|
||||||
|
# artifacts:
|
||||||
|
# paths:
|
||||||
|
# - build
|
||||||
|
|
||||||
|
# test-cogl:
|
||||||
|
# stage: test
|
||||||
|
# dependencies:
|
||||||
|
# - build-mutter
|
||||||
|
# artifacts:
|
||||||
|
# paths:
|
||||||
|
# - build
|
||||||
|
# script:
|
||||||
|
# - meson test -v -C build --suite cogl-headless
|
||||||
|
|
||||||
|
# test-clutter:
|
||||||
|
# stage: test
|
||||||
|
# dependencies:
|
||||||
|
# - build-mutter
|
||||||
|
# artifacts:
|
||||||
|
# paths:
|
||||||
|
# - build
|
||||||
|
# script:
|
||||||
|
# - meson test -v -C build --suite clutter-headless
|
||||||
|
|
||||||
|
# test-mutter:
|
||||||
|
# stage: test
|
||||||
|
# dependencies:
|
||||||
|
# - build-mutter
|
||||||
|
# artifacts:
|
||||||
|
# paths:
|
||||||
|
# - build
|
||||||
|
# script:
|
||||||
|
# - meson test -v -C build --suite mutter-headless
|
||||||
|
@ -7,5 +7,8 @@ RUN dnf -y update && dnf -y upgrade && \
|
|||||||
# Until Fedora catches up with meson build-deps
|
# Until Fedora catches up with meson build-deps
|
||||||
dnf install -y meson xorg-x11-server-Xorg gnome-settings-daemon-devel egl-wayland-devel xorg-x11-server-Xwayland && \
|
dnf install -y meson xorg-x11-server-Xorg gnome-settings-daemon-devel egl-wayland-devel xorg-x11-server-Xwayland && \
|
||||||
|
|
||||||
|
# To enable testing headless
|
||||||
|
dnf install -y xorg-x11-server-Xvfb && \
|
||||||
|
|
||||||
dnf install -y intltool redhat-rpm-config make && \
|
dnf install -y intltool redhat-rpm-config make && \
|
||||||
dnf clean all
|
dnf clean all
|
||||||
|
@ -78,7 +78,18 @@ foreach test : clutter_conform_tests
|
|||||||
install: false,
|
install: false,
|
||||||
)
|
)
|
||||||
|
|
||||||
test('clutter/conform/@0@'.format(test), test_executable,
|
test(test, test_executable,
|
||||||
|
suite: ['clutter', 'clutter/conform'],
|
||||||
env: test_env
|
env: test_env
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if have_headless_tests
|
||||||
|
test(test, xvfb,
|
||||||
|
args: test_executable,
|
||||||
|
suite: ['clutter-headless', 'clutter-headless/conform', 'headless'],
|
||||||
|
env: test_env,
|
||||||
|
is_parallel: false,
|
||||||
|
timeout: 60,
|
||||||
|
)
|
||||||
|
endif
|
||||||
endforeach
|
endforeach
|
||||||
|
@ -95,7 +95,8 @@ cogl_conform_unit_tests = custom_target('cogl-tests-conform-unit-tests',
|
|||||||
install: false,
|
install: false,
|
||||||
)
|
)
|
||||||
|
|
||||||
test('cogl/conform', cogl_run_tests,
|
test('conform', cogl_run_tests,
|
||||||
|
suite: ['cogl'],
|
||||||
args: [
|
args: [
|
||||||
cogl_config_env,
|
cogl_config_env,
|
||||||
libmutter_cogl_test_conformance,
|
libmutter_cogl_test_conformance,
|
||||||
@ -104,3 +105,17 @@ test('cogl/conform', cogl_run_tests,
|
|||||||
is_parallel: false,
|
is_parallel: false,
|
||||||
timeout: 60,
|
timeout: 60,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if have_headless_tests
|
||||||
|
test('conform', xvfb,
|
||||||
|
suite: ['cogl-headless', 'headless'],
|
||||||
|
args: [
|
||||||
|
cogl_run_tests.path(),
|
||||||
|
cogl_config_env,
|
||||||
|
libmutter_cogl_test_conformance,
|
||||||
|
cogl_conform_unit_tests
|
||||||
|
],
|
||||||
|
is_parallel: false,
|
||||||
|
timeout: 500,
|
||||||
|
)
|
||||||
|
endif
|
||||||
|
@ -32,11 +32,22 @@ cogl_unit_unit_tests = custom_target('cogl-tests-unit-unit-tests',
|
|||||||
install: false,
|
install: false,
|
||||||
)
|
)
|
||||||
|
|
||||||
test('cogl/unit', cogl_run_tests,
|
cogl_unit_test_args = [
|
||||||
args: [
|
cogl_config_env,
|
||||||
cogl_config_env,
|
libmutter_cogl_test_unit,
|
||||||
libmutter_cogl_test_unit,
|
cogl_unit_unit_tests
|
||||||
cogl_unit_unit_tests
|
]
|
||||||
],
|
test('unit', cogl_run_tests,
|
||||||
|
suite: ['cogl'],
|
||||||
|
args: cogl_unit_test_args,
|
||||||
is_parallel: false,
|
is_parallel: false,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if have_headless_tests
|
||||||
|
test('unit', xvfb,
|
||||||
|
suite: ['cogl-headless', 'headless'],
|
||||||
|
args: [ cogl_run_tests.path() ] + cogl_unit_test_args,
|
||||||
|
is_parallel: false,
|
||||||
|
timeout: 90,
|
||||||
|
)
|
||||||
|
endif
|
||||||
|
20
meson.build
20
meson.build
@ -245,6 +245,26 @@ if have_tests
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
headless_tests_option = get_option('headless_tests')
|
||||||
|
have_headless_tests = not headless_tests_option.disabled()
|
||||||
|
if have_headless_tests
|
||||||
|
if not have_tests and not have_cogl_tests and not have_clutter_tests
|
||||||
|
have_headless_tests = false
|
||||||
|
if headless_tests_option.enabled()
|
||||||
|
error('Headless tests are enabled, but no other test suite is')
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
if have_headless_tests
|
||||||
|
xvfb = find_program('xvfb-run', required: headless_tests_option.enabled())
|
||||||
|
have_headless_tests = xvfb.found()
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
if have_headless_tests
|
||||||
|
headless_tests_suite = ['headless']
|
||||||
|
else
|
||||||
|
headless_tests_suite = []
|
||||||
|
endif
|
||||||
|
|
||||||
required_functions = [
|
required_functions = [
|
||||||
'ffs',
|
'ffs',
|
||||||
'clz',
|
'clz',
|
||||||
|
@ -123,6 +123,12 @@ option('tests',
|
|||||||
description: 'Enable mutter tests'
|
description: 'Enable mutter tests'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
option('headless_tests',
|
||||||
|
type: 'feature',
|
||||||
|
value: 'auto',
|
||||||
|
description: 'Enable mutter headless tests'
|
||||||
|
)
|
||||||
|
|
||||||
option('verbose',
|
option('verbose',
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
value: true,
|
value: true,
|
||||||
|
@ -15,6 +15,9 @@ dist_stacking_DATA = \
|
|||||||
$(srcdir)/tests/stacking/basic-x11.metatest \
|
$(srcdir)/tests/stacking/basic-x11.metatest \
|
||||||
$(srcdir)/tests/stacking/basic-wayland.metatest \
|
$(srcdir)/tests/stacking/basic-wayland.metatest \
|
||||||
$(srcdir)/tests/stacking/closed-transient.metatest \
|
$(srcdir)/tests/stacking/closed-transient.metatest \
|
||||||
|
$(srcdir)/tests/stacking/closed-transient-no-input-no-take-focus-parent.metatest \
|
||||||
|
$(srcdir)/tests/stacking/closed-transient-no-input-no-take-focus-parents.metatest \
|
||||||
|
$(srcdir)/tests/stacking/closed-transient-no-input-parent.metatest \
|
||||||
$(srcdir)/tests/stacking/minimized.metatest \
|
$(srcdir)/tests/stacking/minimized.metatest \
|
||||||
$(srcdir)/tests/stacking/mixed-windows.metatest \
|
$(srcdir)/tests/stacking/mixed-windows.metatest \
|
||||||
$(srcdir)/tests/stacking/set-parent.metatest \
|
$(srcdir)/tests/stacking/set-parent.metatest \
|
||||||
|
@ -1214,10 +1214,7 @@ get_default_focus_window (MetaStack *stack,
|
|||||||
if (window->unmaps_pending > 0)
|
if (window->unmaps_pending > 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (window->unmanaging)
|
if (!meta_window_is_focusable (window))
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!(window->input || window->take_focus))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!meta_window_should_be_showing (window))
|
if (!meta_window_should_be_showing (window))
|
||||||
|
@ -570,6 +570,7 @@ struct _MetaWindowClass
|
|||||||
ClutterInputDevice *source);
|
ClutterInputDevice *source);
|
||||||
gboolean (*shortcuts_inhibited) (MetaWindow *window,
|
gboolean (*shortcuts_inhibited) (MetaWindow *window,
|
||||||
ClutterInputDevice *source);
|
ClutterInputDevice *source);
|
||||||
|
gboolean (*is_focusable) (MetaWindow *window);
|
||||||
gboolean (*is_stackable) (MetaWindow *window);
|
gboolean (*is_stackable) (MetaWindow *window);
|
||||||
gboolean (*are_updates_frozen) (MetaWindow *window);
|
gboolean (*are_updates_frozen) (MetaWindow *window);
|
||||||
};
|
};
|
||||||
@ -664,6 +665,8 @@ void meta_window_update_unfocused_button_grabs (MetaWindow *window);
|
|||||||
void meta_window_set_focused_internal (MetaWindow *window,
|
void meta_window_set_focused_internal (MetaWindow *window,
|
||||||
gboolean focused);
|
gboolean focused);
|
||||||
|
|
||||||
|
gboolean meta_window_is_focusable (MetaWindow *window);
|
||||||
|
|
||||||
void meta_window_current_workspace_changed (MetaWindow *window);
|
void meta_window_current_workspace_changed (MetaWindow *window);
|
||||||
|
|
||||||
void meta_window_show_menu (MetaWindow *window,
|
void meta_window_show_menu (MetaWindow *window,
|
||||||
|
@ -2205,7 +2205,7 @@ window_state_on_map (MetaWindow *window,
|
|||||||
/* don't initially focus windows that are intended to not accept
|
/* don't initially focus windows that are intended to not accept
|
||||||
* focus
|
* focus
|
||||||
*/
|
*/
|
||||||
if (!(window->input || window->take_focus))
|
if (!meta_window_is_focusable (window))
|
||||||
{
|
{
|
||||||
*takes_focus = FALSE;
|
*takes_focus = FALSE;
|
||||||
return;
|
return;
|
||||||
@ -8512,6 +8512,15 @@ meta_window_shortcuts_inhibited (MetaWindow *window,
|
|||||||
return META_WINDOW_GET_CLASS (window)->shortcuts_inhibited (window, source);
|
return META_WINDOW_GET_CLASS (window)->shortcuts_inhibited (window, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
meta_window_is_focusable (MetaWindow *window)
|
||||||
|
{
|
||||||
|
if (window->unmanaging)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return META_WINDOW_GET_CLASS (window)->is_focusable (window);
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
meta_window_is_stackable (MetaWindow *window)
|
meta_window_is_stackable (MetaWindow *window)
|
||||||
{
|
{
|
||||||
|
@ -87,6 +87,12 @@ typedef struct _MetaWorkspaceLogicalMonitorData
|
|||||||
MetaRectangle logical_monitor_work_area;
|
MetaRectangle logical_monitor_work_area;
|
||||||
} MetaWorkspaceLogicalMonitorData;
|
} MetaWorkspaceLogicalMonitorData;
|
||||||
|
|
||||||
|
typedef struct _MetaWorkspaceFocusableAncestorData
|
||||||
|
{
|
||||||
|
MetaWorkspace *workspace;
|
||||||
|
MetaWindow **win;
|
||||||
|
} 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)
|
||||||
@ -1328,13 +1334,21 @@ meta_workspace_focus_default_window (MetaWorkspace *workspace,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
record_ancestor (MetaWindow *window,
|
find_focusable_ancestor (MetaWindow *window,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
MetaWindow **result = data;
|
MetaWorkspaceFocusableAncestorData *mwfa = data;
|
||||||
|
MetaWindow **result = mwfa->win;
|
||||||
|
|
||||||
*result = window;
|
if (meta_window_is_focusable (window) &&
|
||||||
return FALSE; /* quit with the first ancestor we find */
|
meta_window_located_on_workspace (window, mwfa->workspace) &&
|
||||||
|
meta_window_showing_on_its_workspace (window))
|
||||||
|
{
|
||||||
|
*result = 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 */
|
||||||
@ -1355,12 +1369,10 @@ focus_ancestor_or_top_window (MetaWorkspace *workspace,
|
|||||||
/* First, check to see if we need to focus an ancestor of a window */
|
/* First, check to see if we need to focus an ancestor of a window */
|
||||||
if (not_this_one)
|
if (not_this_one)
|
||||||
{
|
{
|
||||||
MetaWindow *ancestor;
|
MetaWindow *ancestor = NULL;
|
||||||
ancestor = NULL;
|
MetaWorkspaceFocusableAncestorData mwfa = { workspace, &ancestor };
|
||||||
meta_window_foreach_ancestor (not_this_one, record_ancestor, &ancestor);
|
meta_window_foreach_ancestor (not_this_one, find_focusable_ancestor, &mwfa);
|
||||||
if (ancestor != NULL &&
|
if (ancestor != NULL)
|
||||||
meta_window_located_on_workspace (ancestor, workspace) &&
|
|
||||||
meta_window_showing_on_its_workspace (ancestor))
|
|
||||||
{
|
{
|
||||||
meta_topic (META_DEBUG_FOCUS,
|
meta_topic (META_DEBUG_FOCUS,
|
||||||
"Focusing %s, ancestor of %s\n",
|
"Focusing %s, ancestor of %s\n",
|
||||||
|
@ -191,8 +191,7 @@ main (int argc, char *argv[])
|
|||||||
META_TYPE_BACKEND_TEST);
|
META_TYPE_BACKEND_TEST);
|
||||||
meta_wayland_override_display_name ("mutter-test-display");
|
meta_wayland_override_display_name ("mutter-test-display");
|
||||||
|
|
||||||
meta_init ();
|
test_meta_init ();
|
||||||
meta_register_with_session ();
|
|
||||||
|
|
||||||
g_idle_add (run_tests, NULL);
|
g_idle_add (run_tests, NULL);
|
||||||
|
|
||||||
|
@ -22,6 +22,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: false,
|
install: false,
|
||||||
@ -81,32 +82,73 @@ headless_start_test = executable('mutter-headless-start-test',
|
|||||||
install: false,
|
install: false,
|
||||||
)
|
)
|
||||||
|
|
||||||
stacking_tests = files([
|
stacking_tests = [
|
||||||
'stacking/basic-x11.metatest',
|
'basic-x11',
|
||||||
'stacking/basic-wayland.metatest',
|
'basic-wayland',
|
||||||
'stacking/minimized.metatest',
|
'client-side-decorated',
|
||||||
'stacking/mixed-windows.metatest',
|
'closed-transient',
|
||||||
'stacking/set-parent.metatest',
|
'closed-transient-no-input-no-take-focus-parent',
|
||||||
'stacking/override-redirect.metatest',
|
'closed-transient-no-input-no-take-focus-parents',
|
||||||
])
|
'closed-transient-no-input-parent',
|
||||||
|
'minimized',
|
||||||
|
'mixed-windows',
|
||||||
|
'set-parent',
|
||||||
|
'override-redirect',
|
||||||
|
'set-parent-exported',
|
||||||
|
]
|
||||||
|
|
||||||
test('mutter/stacking', test_runner,
|
foreach stacking_test: stacking_tests
|
||||||
env: test_env,
|
test(stacking_test, test_runner,
|
||||||
args: [
|
suite: ['mutter/stacking'],
|
||||||
stacking_tests,
|
env: test_env,
|
||||||
],
|
args: [
|
||||||
is_parallel: false,
|
files(join_paths('stacking', stacking_test + '.metatest')),
|
||||||
timeout: 60,
|
],
|
||||||
)
|
is_parallel: false,
|
||||||
|
timeout: 60,
|
||||||
|
)
|
||||||
|
if have_headless_tests
|
||||||
|
test(stacking_test, xvfb,
|
||||||
|
suite: ['mutter-headless', 'mutter-headless/stacking', 'headless'],
|
||||||
|
env: test_env,
|
||||||
|
args: [
|
||||||
|
test_runner,
|
||||||
|
files(join_paths('stacking', stacking_test + '.metatest')),
|
||||||
|
],
|
||||||
|
is_parallel: false,
|
||||||
|
timeout: 60,
|
||||||
|
)
|
||||||
|
endif
|
||||||
|
endforeach
|
||||||
|
|
||||||
test('mutter/unit', unit_tests,
|
test('normal', unit_tests,
|
||||||
|
suite: ['mutter/unit'],
|
||||||
env: test_env,
|
env: test_env,
|
||||||
is_parallel: false,
|
is_parallel: false,
|
||||||
timeout: 60,
|
timeout: 60,
|
||||||
)
|
)
|
||||||
|
|
||||||
test('mutter/unit/headless-start', headless_start_test,
|
test('headless-start', headless_start_test,
|
||||||
|
suite: ['mutter/unit'],
|
||||||
env: test_env,
|
env: test_env,
|
||||||
is_parallel: false,
|
is_parallel: false,
|
||||||
timeout: 60,
|
timeout: 60,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if have_headless_tests
|
||||||
|
test('normal', xvfb,
|
||||||
|
args: unit_tests,
|
||||||
|
suite: ['mutter-headless', 'mutter-headless/unit', 'headless'],
|
||||||
|
env: test_env,
|
||||||
|
is_parallel: false,
|
||||||
|
timeout: 60,
|
||||||
|
)
|
||||||
|
|
||||||
|
test('headless-start', xvfb,
|
||||||
|
args: headless_start_test,
|
||||||
|
suite: ['mutter-headless', 'mutter-headless/unit', 'headless'],
|
||||||
|
env: test_env,
|
||||||
|
is_parallel: false,
|
||||||
|
timeout: 60,
|
||||||
|
)
|
||||||
|
endif
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
new_client 1 x11
|
||||||
|
create 1/1
|
||||||
|
show 1/1
|
||||||
|
wait
|
||||||
|
|
||||||
|
create 1/2 csd
|
||||||
|
set_parent 1/2 1
|
||||||
|
take_focus 1/2 false
|
||||||
|
accept_focus 1/2 false
|
||||||
|
show 1/2
|
||||||
|
wait
|
||||||
|
|
||||||
|
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,32 @@
|
|||||||
|
new_client 2 x11
|
||||||
|
create 2/1
|
||||||
|
show 2/1
|
||||||
|
wait
|
||||||
|
|
||||||
|
new_client 1 x11
|
||||||
|
create 1/1
|
||||||
|
accept_focus 1/1 false
|
||||||
|
take_focus 1/1 false
|
||||||
|
show 1/1
|
||||||
|
wait
|
||||||
|
|
||||||
|
create 1/2 csd
|
||||||
|
set_parent 1/2 1
|
||||||
|
take_focus 1/2 false
|
||||||
|
accept_focus 1/2 false
|
||||||
|
show 1/2
|
||||||
|
wait
|
||||||
|
|
||||||
|
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
|
29
src/tests/stacking/closed-transient-no-input-parent.metatest
Normal file
29
src/tests/stacking/closed-transient-no-input-parent.metatest
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
new_client 2 x11
|
||||||
|
create 2/1
|
||||||
|
show 2/1
|
||||||
|
wait
|
||||||
|
|
||||||
|
new_client 1 x11
|
||||||
|
create 1/1
|
||||||
|
show 1/1
|
||||||
|
wait
|
||||||
|
|
||||||
|
create 1/2 csd
|
||||||
|
set_parent 1/2 1
|
||||||
|
accept_focus 1/2 false
|
||||||
|
show 1/2
|
||||||
|
wait
|
||||||
|
|
||||||
|
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_focused 1/1
|
||||||
|
assert_stacking 2/1 1/1 1/2
|
@ -196,6 +196,74 @@ 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean enabled = g_ascii_strcasecmp (argv[2], "true") == 0;
|
||||||
|
gtk_window_set_accept_focus (GTK_WINDOW (window), enabled);
|
||||||
|
}
|
||||||
|
else if (strcmp (argv[0], "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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_malloc0 (sizeof (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);
|
||||||
|
|
||||||
|
XFree (new_protocols);
|
||||||
|
XFree (protocols);
|
||||||
|
}
|
||||||
else if (strcmp (argv[0], "show") == 0)
|
else if (strcmp (argv[0], "show") == 0)
|
||||||
{
|
{
|
||||||
if (argc != 2)
|
if (argc != 2)
|
||||||
|
@ -237,6 +237,38 @@ 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_ascii_strcasecmp (expected_window, "null") != 0 &&
|
||||||
|
g_ascii_strcasecmp (expected_window, "none") != 0 &&
|
||||||
|
g_strcmp0 (expected_window, "0") != 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,
|
||||||
|
"stacking: 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)
|
||||||
@ -398,6 +430,44 @@ 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], "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],
|
||||||
@ -485,6 +555,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]);
|
||||||
@ -799,8 +874,7 @@ main (int argc, char **argv)
|
|||||||
meta_plugin_manager_load (test_get_plugin_name ());
|
meta_plugin_manager_load (test_get_plugin_name ());
|
||||||
meta_wayland_override_display_name ("mutter-test-display");
|
meta_wayland_override_display_name ("mutter-test-display");
|
||||||
|
|
||||||
meta_init ();
|
test_meta_init ();
|
||||||
meta_register_with_session ();
|
|
||||||
|
|
||||||
RunTestsInfo info;
|
RunTestsInfo info;
|
||||||
info.tests = (char **)tests->pdata;
|
info.tests = (char **)tests->pdata;
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "tests/test-utils.h"
|
#include "tests/test-utils.h"
|
||||||
|
|
||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
|
#include <meta/main.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "core/display-private.h"
|
#include "core/display-private.h"
|
||||||
@ -94,6 +95,21 @@ test_init (int *argc,
|
|||||||
ensure_test_client_path (*argc, *argv);
|
ensure_test_client_path (*argc, *argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_meta_init ()
|
||||||
|
{
|
||||||
|
GLogLevelFlags log_flags;
|
||||||
|
|
||||||
|
/* Accept warnings in mutter initialization, as `failed to bind` one */
|
||||||
|
log_flags = g_log_set_always_fatal (G_LOG_FATAL_MASK);
|
||||||
|
g_log_set_always_fatal (log_flags & ~G_LOG_LEVEL_WARNING);
|
||||||
|
|
||||||
|
meta_init ();
|
||||||
|
meta_register_with_session ();
|
||||||
|
|
||||||
|
g_log_set_always_fatal (log_flags);
|
||||||
|
}
|
||||||
|
|
||||||
AsyncWaiter *
|
AsyncWaiter *
|
||||||
async_waiter_new (void)
|
async_waiter_new (void)
|
||||||
{
|
{
|
||||||
|
@ -43,6 +43,8 @@ typedef struct _TestClient TestClient;
|
|||||||
void test_init (int *argc,
|
void test_init (int *argc,
|
||||||
char ***argv);
|
char ***argv);
|
||||||
|
|
||||||
|
void test_meta_init (void);
|
||||||
|
|
||||||
gboolean async_waiter_alarm_filter (AsyncWaiter *waiter,
|
gboolean async_waiter_alarm_filter (AsyncWaiter *waiter,
|
||||||
MetaX11Display *x11_display,
|
MetaX11Display *x11_display,
|
||||||
XSyncAlarmNotifyEvent *event);
|
XSyncAlarmNotifyEvent *event);
|
||||||
|
@ -265,8 +265,7 @@ main (int argc, char *argv[])
|
|||||||
META_TYPE_BACKEND_TEST);
|
META_TYPE_BACKEND_TEST);
|
||||||
meta_wayland_override_display_name ("mutter-test-display");
|
meta_wayland_override_display_name ("mutter-test-display");
|
||||||
|
|
||||||
meta_init ();
|
test_meta_init ();
|
||||||
meta_register_with_session ();
|
|
||||||
|
|
||||||
g_idle_add (run_tests, NULL);
|
g_idle_add (run_tests, NULL);
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ static void
|
|||||||
meta_window_wayland_focus (MetaWindow *window,
|
meta_window_wayland_focus (MetaWindow *window,
|
||||||
guint32 timestamp)
|
guint32 timestamp)
|
||||||
{
|
{
|
||||||
if (window->input)
|
if (meta_window_is_focusable (window))
|
||||||
meta_x11_display_set_input_focus_window (window->display->x11_display,
|
meta_x11_display_set_input_focus_window (window->display->x11_display,
|
||||||
window,
|
window,
|
||||||
FALSE,
|
FALSE,
|
||||||
@ -585,6 +585,12 @@ meta_window_wayland_shortcuts_inhibited (MetaWindow *window,
|
|||||||
return meta_wayland_compositor_is_shortcuts_inhibited (compositor, source);
|
return meta_wayland_compositor_is_shortcuts_inhibited (compositor, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
meta_window_wayland_is_focusable (MetaWindow *window)
|
||||||
|
{
|
||||||
|
return window->input;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
meta_window_wayland_is_stackable (MetaWindow *window)
|
meta_window_wayland_is_stackable (MetaWindow *window)
|
||||||
{
|
{
|
||||||
@ -618,6 +624,7 @@ meta_window_wayland_class_init (MetaWindowWaylandClass *klass)
|
|||||||
window_class->get_client_pid = meta_window_wayland_get_client_pid;
|
window_class->get_client_pid = meta_window_wayland_get_client_pid;
|
||||||
window_class->force_restore_shortcuts = meta_window_wayland_force_restore_shortcuts;
|
window_class->force_restore_shortcuts = meta_window_wayland_force_restore_shortcuts;
|
||||||
window_class->shortcuts_inhibited = meta_window_wayland_shortcuts_inhibited;
|
window_class->shortcuts_inhibited = meta_window_wayland_shortcuts_inhibited;
|
||||||
|
window_class->is_focusable = meta_window_wayland_is_focusable;
|
||||||
window_class->is_stackable = meta_window_wayland_is_stackable;
|
window_class->is_stackable = meta_window_wayland_is_stackable;
|
||||||
window_class->are_updates_frozen = meta_window_wayland_are_updates_frozen;
|
window_class->are_updates_frozen = meta_window_wayland_are_updates_frozen;
|
||||||
}
|
}
|
||||||
|
@ -752,8 +752,7 @@ meta_window_x11_focus (MetaWindow *window,
|
|||||||
* Still, we have to do this or keynav breaks for these windows.
|
* Still, we have to do this or keynav breaks for these windows.
|
||||||
*/
|
*/
|
||||||
if (window->frame &&
|
if (window->frame &&
|
||||||
(window->shaded ||
|
(window->shaded || !meta_window_is_focusable (window)))
|
||||||
!(window->input || window->take_focus)))
|
|
||||||
{
|
{
|
||||||
meta_topic (META_DEBUG_FOCUS,
|
meta_topic (META_DEBUG_FOCUS,
|
||||||
"Focusing frame of %s\n", window->desc);
|
"Focusing frame of %s\n", window->desc);
|
||||||
@ -790,13 +789,27 @@ 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 default focus window excluding this one,
|
||||||
* display->focus_window to that) before sending WM_TAKE_FOCUS.
|
* before sending WM_TAKE_FOCUS.
|
||||||
*/
|
*/
|
||||||
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,
|
{
|
||||||
timestamp);
|
MetaWindow *focus_window = window;
|
||||||
|
MetaWorkspace *workspace = window->workspace;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
focus_window = meta_stack_get_default_focus_window (workspace->display->stack,
|
||||||
|
workspace,
|
||||||
|
focus_window);
|
||||||
|
}
|
||||||
|
while (!(!focus_window || focus_window->input ||
|
||||||
|
(focus_window->frame && focus_window->shaded)));
|
||||||
|
|
||||||
|
if (focus_window)
|
||||||
|
meta_window_x11_focus (focus_window, timestamp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
request_take_focus (window, timestamp);
|
request_take_focus (window, timestamp);
|
||||||
@ -1627,6 +1640,12 @@ meta_window_x11_shortcuts_inhibited (MetaWindow *window,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
meta_window_x11_is_focusable (MetaWindow *window)
|
||||||
|
{
|
||||||
|
return window->input || window->take_focus;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
meta_window_x11_is_stackable (MetaWindow *window)
|
meta_window_x11_is_stackable (MetaWindow *window)
|
||||||
{
|
{
|
||||||
@ -1669,6 +1688,7 @@ meta_window_x11_class_init (MetaWindowX11Class *klass)
|
|||||||
window_class->get_client_pid = meta_window_x11_get_client_pid;
|
window_class->get_client_pid = meta_window_x11_get_client_pid;
|
||||||
window_class->force_restore_shortcuts = meta_window_x11_force_restore_shortcuts;
|
window_class->force_restore_shortcuts = meta_window_x11_force_restore_shortcuts;
|
||||||
window_class->shortcuts_inhibited = meta_window_x11_shortcuts_inhibited;
|
window_class->shortcuts_inhibited = meta_window_x11_shortcuts_inhibited;
|
||||||
|
window_class->is_focusable = meta_window_x11_is_focusable;
|
||||||
window_class->is_stackable = meta_window_x11_is_stackable;
|
window_class->is_stackable = meta_window_x11_is_stackable;
|
||||||
window_class->are_updates_frozen = meta_window_x11_are_updates_frozen;
|
window_class->are_updates_frozen = meta_window_x11_are_updates_frozen;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user