tests: cover quit dialog, constraint/text-input/dialog teardown, virtual abs+mods, mgmt probe
This commit is contained in:
parent
32de4866a6
commit
ca7f1f2852
3 changed files with 285 additions and 15 deletions
4
kick.c
4
kick.c
|
|
@ -8465,6 +8465,10 @@ static void constraint_deactivate(void) {
|
|||
static void handle_constraint_destroy(struct wl_listener *listener, void *data) {
|
||||
(void)data;
|
||||
struct kick_server *s = wl_container_of(listener, s, constraint_destroy);
|
||||
kick_log(KICK_LOG_DEBUG, "[constraint] destroyed\n");
|
||||
/* Detach like constraint_deactivate does: wlroots asserts every
|
||||
listener is gone before it frees the constraint. */
|
||||
wl_list_remove(&s->constraint_destroy.link);
|
||||
s->active_constraint = NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -78,6 +78,9 @@ M = 50
|
|||
U = 22
|
||||
V = 47
|
||||
R = 19
|
||||
C = 46
|
||||
D = 32
|
||||
G = 34
|
||||
ESC = 1
|
||||
ENTER = 28
|
||||
UP = 103
|
||||
|
|
@ -943,6 +946,27 @@ def test_standalone_headless_locked_pointer_holds():
|
|||
s.close()
|
||||
|
||||
|
||||
def test_standalone_headless_locked_pointer_release():
|
||||
"""Dropping a locked constraint mid-session tears it down: the destroy
|
||||
path runs and the cursor is free to move again."""
|
||||
s = _spawn_standalone({}, "%s --constrain locked '#ff0000'" % WL)
|
||||
try:
|
||||
s.wait_app_active(0)
|
||||
s.wait_active_frame()
|
||||
assert s.proc.poll() is None
|
||||
s.warp(300, 300)
|
||||
assert _wait_log(s, r"\[constraint\] locked on surface",
|
||||
timeout=5.0), \
|
||||
"locked constraint never activated"
|
||||
s.tap(C)
|
||||
assert _wait_log(s, r"\[constraint\] destroyed", timeout=5.0), \
|
||||
"constraint destroy never ran"
|
||||
assert s.proc.poll() is None, \
|
||||
f"compositor died on constraint release; log tail:\n{s.read_log()[-400:]}"
|
||||
finally:
|
||||
s.close()
|
||||
|
||||
|
||||
def test_standalone_headless_confined_pointer_clamps():
|
||||
"""A CONFINED pointer constraint keeps the visible cursor inside the
|
||||
constraint region even when relative motion would carry it outside."""
|
||||
|
|
@ -1284,6 +1308,22 @@ def test_standalone_headless_text_input_roundtrip(tmp_path):
|
|||
s.close()
|
||||
|
||||
|
||||
def test_standalone_headless_text_input_disable():
|
||||
"""Disabling an enabled text field mid-session runs the compositor's
|
||||
disable relay without disturbing the session."""
|
||||
s = _spawn_standalone(
|
||||
{}, "%s --text-input '#ff0000'" % WL)
|
||||
try:
|
||||
s.wait_app_active(0)
|
||||
s.wait_surface_mapped(0)
|
||||
s.tap(D)
|
||||
time.sleep(1.0)
|
||||
assert s.proc.poll() is None, \
|
||||
f"compositor died on text-input disable; log tail:\n{s.read_log()[-400:]}"
|
||||
finally:
|
||||
s.close()
|
||||
|
||||
|
||||
def test_standalone_headless_text_input_focus_follows_tab(tmp_path):
|
||||
"""Cycling-free focus follow: when the focused field's tab closes, focus
|
||||
hands to the left neighbor, which is entered and gets its own IME
|
||||
|
|
@ -1470,6 +1510,28 @@ def test_standalone_headless_modal_steals_tab(tmp_path):
|
|||
s.close()
|
||||
|
||||
|
||||
def test_standalone_headless_modal_dialog_destroy_unwires():
|
||||
"""Destroying a modal dialog's object mid-session unwires it without
|
||||
disturbing the session: the compositor drops the modal wiring and the
|
||||
window carries on as a normal tab."""
|
||||
s = _spawn_standalone(
|
||||
{},
|
||||
"%s --dialog-modal --app-id dlg '#0000ff'" % WL,
|
||||
"%s '#ff0000'" % WL)
|
||||
try:
|
||||
s.wait_any_active()
|
||||
s.wait_for(r"\[dialog\] modal app=0\b")
|
||||
# The modal steal focuses its tab (possibly before startup
|
||||
# settles); the key must reach that client.
|
||||
s.wait_active(0)
|
||||
s.tap(G)
|
||||
time.sleep(1.0)
|
||||
assert s.proc.poll() is None, \
|
||||
f"compositor died on dialog destroy; log tail:\n{s.read_log()[-400:]}"
|
||||
finally:
|
||||
s.close()
|
||||
|
||||
|
||||
def test_standalone_headless_modal_tab_groups_off(tmp_path):
|
||||
"""With --tab-groups off a background modal still takes its (own) tab:
|
||||
it is glued after its parent and activated on map."""
|
||||
|
|
@ -1599,6 +1661,32 @@ def test_standalone_headless_output_mgmt_list(tmp_path):
|
|||
s.close()
|
||||
|
||||
|
||||
def test_standalone_headless_output_mgmt_test(tmp_path):
|
||||
"""Probing 640x480 through output-management succeeds without
|
||||
resizing: the client sees before/tested and the output keeps its
|
||||
size."""
|
||||
out = tmp_path / "om.out"
|
||||
s = _spawn_standalone(
|
||||
{},
|
||||
"%s --output-mgmt --output-mgmt-out '%s' --output-mgmt-size 640x480 "
|
||||
"--output-mgmt-test" % (WL, out),
|
||||
"%s '#ff0000'" % WL)
|
||||
try:
|
||||
s.wait_any_active()
|
||||
deadline = time.monotonic() + 20.0
|
||||
while time.monotonic() < deadline:
|
||||
if out.exists() and "tested" in out.read_text():
|
||||
break
|
||||
time.sleep(0.2)
|
||||
text = out.read_text() if out.exists() else ""
|
||||
assert "before " in text, f"no before line in: {text!r}"
|
||||
assert "tested" in text, f"test not acked in: {text!r}"
|
||||
assert "after " not in text, f"probe resized the output: {text!r}"
|
||||
assert s.proc.poll() is None, f"log tail:\n{s.read_log()[-400:]}"
|
||||
finally:
|
||||
s.close()
|
||||
|
||||
|
||||
def test_standalone_headless_output_mgmt_apply(tmp_path):
|
||||
"""Applying 800x600 through output-management resizes the session:
|
||||
the client sees before/applied/after and a tab commits at 800x600."""
|
||||
|
|
@ -2910,6 +2998,31 @@ def test_quit_confirm_multi_window():
|
|||
s.proc.terminate()
|
||||
|
||||
|
||||
def test_quit_confirm_dialog_renders():
|
||||
"""The confirm-quit modal actually draws: with the question pending, a
|
||||
frame dump shows the dark dialog box over the client content."""
|
||||
if not os.environ.get("WAYLAND_DISPLAY"):
|
||||
pytest.skip("needs a live host Wayland session (WAYLAND_DISPLAY)")
|
||||
s = _nested_session(f"{WL} '{RED}'", f"{WL} '{GREEN}'")
|
||||
try:
|
||||
s.wait_any_active()
|
||||
s.wait_for(r"\[claim\] app=0\b")
|
||||
s.wait_for(r"\[claim\] app=1\b")
|
||||
s.chord(CTRL | ALT, Q)
|
||||
s.wait_for(r"\[confirm\] quit: 2 windows open ")
|
||||
w, h, px = s.ppm_rgb(s.dump_host())
|
||||
assert _has_dark(w, h, px), \
|
||||
"confirm-quit dialog not visible in the composed frame"
|
||||
s.tap(N) # keep running
|
||||
s.wait_for(r"kick: quit cancelled\b")
|
||||
assert s.proc.poll() is None, \
|
||||
"compositor exited after cancelling quit"
|
||||
finally:
|
||||
s.close()
|
||||
if s.proc.poll() is None:
|
||||
s.proc.terminate()
|
||||
|
||||
|
||||
def test_quit_cancel_keeps_running():
|
||||
"""Ctrl+Alt+Q confirmation can be declined: N and Escape both dismiss it,
|
||||
the compositor keeps running, and a later quit request re-asks."""
|
||||
|
|
@ -4841,6 +4954,26 @@ def _oneshot_virtual_motion(sock, dx, dy, click=False):
|
|||
pass
|
||||
|
||||
|
||||
def _oneshot_virtual_abs(sock, x, y, click=False):
|
||||
"""Run a one-shot --virtual-abs (output-fraction warp) plus optional
|
||||
click against a live socket."""
|
||||
args = [WL, "--virtual-abs", str(x), str(y)]
|
||||
if click:
|
||||
args.append("--virtual-click")
|
||||
p = subprocess.Popen(
|
||||
args, env=dict(os.environ, WAYLAND_DISPLAY=sock),
|
||||
stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL, start_new_session=True,
|
||||
preexec_fn=_preexec_death(os.getpid()))
|
||||
try:
|
||||
p.wait(timeout=10.0)
|
||||
finally:
|
||||
try:
|
||||
p.kill()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def test_standalone_headless_virtual_pointer_motion_click(tmp_path):
|
||||
"""A virtual pointer moves the cursor and clicks: the focused window
|
||||
receives pointer motion and button events through the seat."""
|
||||
|
|
@ -4882,6 +5015,72 @@ def test_standalone_headless_virtual_pointer_motion_click(tmp_path):
|
|||
s.close()
|
||||
|
||||
|
||||
def test_standalone_headless_virtual_pointer_absolute(tmp_path):
|
||||
"""A virtual pointer warps absolutely: the focused window sees a
|
||||
pointer enter at the fraction position plus the click."""
|
||||
out = tmp_path / "pointer.out"
|
||||
s = _spawn_standalone(
|
||||
{}, "%s --app-id testwin --pointer-out '%s' '#ff0000' 320x240"
|
||||
% (WL, out))
|
||||
try:
|
||||
s.wait_any_active()
|
||||
s.wait_surface_mapped(0)
|
||||
# Centre of the output is well inside the maximized window.
|
||||
_oneshot_virtual_abs(s.socket, 0.5, 0.5, click=True)
|
||||
deadline = time.monotonic() + 10.0
|
||||
got_enter = got_button = False
|
||||
while time.monotonic() < deadline:
|
||||
if out.exists():
|
||||
text = out.read_text()
|
||||
got_enter = "enter " in text
|
||||
got_button = "button 272 " in text
|
||||
if got_enter and got_button:
|
||||
break
|
||||
time.sleep(0.1)
|
||||
assert got_enter, \
|
||||
f"window saw no pointer enter from abs warp: " \
|
||||
f"{(out.read_text() if out.exists() else '(missing)')!r}"
|
||||
assert got_button, \
|
||||
f"window saw no button press after abs warp: " \
|
||||
f"{(out.read_text() if out.exists() else '(missing)')!r}"
|
||||
assert s.proc.poll() is None, \
|
||||
f"compositor exited on virtual abs pointer; log tail:\n{s.read_log()[-400:]}"
|
||||
finally:
|
||||
s.close()
|
||||
|
||||
|
||||
def test_standalone_headless_virtual_keyboard_modifiers():
|
||||
"""Explicit virtual-keyboard modifiers reach the seat without pressing
|
||||
any key and without disturbing the session."""
|
||||
s = _spawn_standalone(
|
||||
{}, "%s --app-id win0 '#ff0000' 320x240" % WL,
|
||||
"%s --app-id win1 '#00ff00' 320x240" % WL)
|
||||
try:
|
||||
start = s.wait_any_active()
|
||||
p = subprocess.Popen(
|
||||
[WL, "--virtual-modifiers", "1"],
|
||||
env=dict(os.environ, WAYLAND_DISPLAY=s.socket),
|
||||
stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL, start_new_session=True,
|
||||
preexec_fn=_preexec_death(os.getpid()))
|
||||
try:
|
||||
p.wait(timeout=10.0)
|
||||
finally:
|
||||
try:
|
||||
p.kill()
|
||||
except Exception:
|
||||
pass
|
||||
assert p.returncode == 0, \
|
||||
f"virtual-modifiers oneshot failed: rc={p.returncode}"
|
||||
time.sleep(0.5)
|
||||
# Modifiers alone switch nothing and kill nothing.
|
||||
assert s.active() == start, "lone modifiers changed the active tab"
|
||||
assert s.proc.poll() is None, \
|
||||
f"compositor exited on virtual modifiers; log tail:\n{s.read_log()[-400:]}"
|
||||
finally:
|
||||
s.close()
|
||||
|
||||
|
||||
def test_standalone_headless_xdg_activation_globals(tmp_path):
|
||||
"""The compositor advertises xdg_activation_v1 so launchers can focus
|
||||
windows by token."""
|
||||
|
|
|
|||
|
|
@ -85,6 +85,9 @@ static struct zwp_locked_pointer_v1 *locked_ptr;
|
|||
static struct zwp_confined_pointer_v1 *confined_ptr;
|
||||
static struct wl_keyboard *keyboard;
|
||||
static struct wl_pointer *pointer;
|
||||
/* Forward declaration for the 'D' key handler below: the text-input
|
||||
object is defined with the rest of the text-input mode further down. */
|
||||
static struct zwp_text_input_v3 *ti_obj;
|
||||
/* --touch-log: append every received touch event to this file so tests can
|
||||
prove the compositor delivered touchscreen input end-to-end. */
|
||||
static FILE *touch_log;
|
||||
|
|
@ -428,6 +431,7 @@ static bool want_extra;
|
|||
extra one. --extra-delay <ms> sleeps before opening the extra window
|
||||
so boot settles first (lets a modal steal a settled tab). */
|
||||
static bool dialog_modal;
|
||||
static struct xdg_dialog_v1 *dialog_obj;
|
||||
static bool extra_modal;
|
||||
static int extra_delay_ms;
|
||||
static bool extra_done;
|
||||
|
|
@ -536,6 +540,30 @@ static void keyboard_key(void *data, struct wl_keyboard *kb, uint32_t serial,
|
|||
ex_xdg = NULL;
|
||||
ex_surface = NULL;
|
||||
}
|
||||
/* 'G' (evdev 34) destroys the xdg-dialog object, letting tests prove
|
||||
the compositor unwires a modal dialog mid-session. */
|
||||
if (key == 34 && state == WL_KEYBOARD_KEY_STATE_PRESSED && dialog_obj) {
|
||||
xdg_dialog_v1_destroy(dialog_obj);
|
||||
dialog_obj = NULL;
|
||||
}
|
||||
/* 'D' (evdev 32) disables the text-input field, letting tests prove
|
||||
the compositor relays the disable to the input method. */
|
||||
if (key == 32 && state == WL_KEYBOARD_KEY_STATE_PRESSED && ti_obj) {
|
||||
zwp_text_input_v3_disable(ti_obj);
|
||||
zwp_text_input_v3_commit(ti_obj);
|
||||
}
|
||||
/* 'C' (evdev 46) drops the pointer constraint, letting tests prove
|
||||
the compositor tears the active constraint down mid-session. */
|
||||
if (key == 46 && state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||
if (locked_ptr) {
|
||||
zwp_locked_pointer_v1_destroy(locked_ptr);
|
||||
locked_ptr = NULL;
|
||||
}
|
||||
if (confined_ptr) {
|
||||
zwp_confined_pointer_v1_destroy(confined_ptr);
|
||||
confined_ptr = NULL;
|
||||
}
|
||||
}
|
||||
if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
|
||||
maybe_set_primary(serial);
|
||||
}
|
||||
|
|
@ -1831,9 +1859,11 @@ static void gesture_bind_all(void) {
|
|||
/* --- Output management (wlr-output-management) ---
|
||||
--output-mgmt --output-mgmt-out <file> [--output-mgmt-size WxH]:
|
||||
list the head (name + current size) into <file>; with a size, apply
|
||||
it as a custom mode first and record before/after/applied. No window
|
||||
is opened. */
|
||||
it as a custom mode first and record before/after/applied.
|
||||
--output-mgmt-test probes instead of applying (records "tested").
|
||||
No window is opened. */
|
||||
static bool output_mgmt_mode;
|
||||
static bool output_mgmt_test_only;
|
||||
static const char *output_mgmt_out;static int output_mgmt_w, output_mgmt_h;
|
||||
static bool output_mgmt_want_size;
|
||||
static struct zwlr_output_head_v1 *om_head;
|
||||
|
|
@ -1883,7 +1913,9 @@ static void om_report_head(const char *tag) {
|
|||
static void om_config_succeeded(void *data,
|
||||
struct zwlr_output_configuration_v1 *cfg) {
|
||||
(void)data; (void)cfg;
|
||||
om_note("applied");
|
||||
om_note(output_mgmt_test_only ? "tested" : "applied");
|
||||
if (output_mgmt_test_only)
|
||||
exit(0);
|
||||
om_applied = true;
|
||||
}
|
||||
|
||||
|
|
@ -2032,7 +2064,10 @@ static void om_mgr_done(void *data, struct zwlr_output_manager_v1 *mgr,
|
|||
zwlr_output_configuration_v1_enable_head(cfg, om_head);
|
||||
zwlr_output_configuration_head_v1_set_custom_mode(
|
||||
chead, output_mgmt_w, output_mgmt_h, 0);
|
||||
zwlr_output_configuration_v1_apply(cfg);
|
||||
if (output_mgmt_test_only)
|
||||
zwlr_output_configuration_v1_test(cfg);
|
||||
else
|
||||
zwlr_output_configuration_v1_apply(cfg);
|
||||
wl_display_flush(display);
|
||||
return;
|
||||
}
|
||||
|
|
@ -2220,9 +2255,12 @@ static void power_run(void) {
|
|||
/* --- Virtual keyboard (zwp_virtual_keyboard_v1) ---
|
||||
--virtual-key <code:state,...>: synthesise key events through a virtual
|
||||
keyboard (no keymap sent; the compositor installs its own). E.g.
|
||||
"56:1,103:1,103:0,56:0" presses Alt+Up (tab-cycle) and releases. Exits
|
||||
after flushing. */
|
||||
"56:1,103:1,103:0,56:0" presses Alt+Up (tab-cycle) and releases.
|
||||
--virtual-modifiers <mask> sends an explicit modifier state (depressed
|
||||
mask) with no keys. Exits after flushing. */
|
||||
static const char *virtual_key_spec;
|
||||
static uint32_t virtual_mods;
|
||||
static bool virtual_mods_set;
|
||||
|
||||
static void virtual_key_run(void) {
|
||||
display = wl_display_connect(NULL);
|
||||
|
|
@ -2271,6 +2309,8 @@ static void virtual_key_run(void) {
|
|||
xkb_context_unref(xkb_ctx);
|
||||
char *spec = strdup(virtual_key_spec ? virtual_key_spec : "");
|
||||
uint32_t time = 1000;
|
||||
if (virtual_mods_set)
|
||||
zwp_virtual_keyboard_v1_modifiers(vkb, virtual_mods, 0, 0, 0);
|
||||
for (char *tok = strtok(spec, ","); tok; tok = strtok(NULL, ",")) {
|
||||
unsigned code = 0, state = 0;
|
||||
if (sscanf(tok, "%u:%u", &code, &state) == 2)
|
||||
|
|
@ -2283,9 +2323,11 @@ static void virtual_key_run(void) {
|
|||
|
||||
/* --- Virtual pointer (zwlr_virtual_pointer_v1) ---
|
||||
--virtual-motion <dx> <dy> [--virtual-click]: move the pointer relatively
|
||||
by (dx,dy); with --virtual-click also press+release left button there.
|
||||
Exits after flushing. */
|
||||
by (dx,dy); --virtual-abs <x> <y> moves absolutely to the (x,y) fraction
|
||||
of the output instead. With --virtual-click also press+release left
|
||||
button there. Exits after flushing. */
|
||||
static double virtual_dx, virtual_dy;
|
||||
static double virtual_abs_x = -1.0, virtual_abs_y = -1.0;
|
||||
static bool virtual_click;
|
||||
|
||||
static void virtual_motion_run(void) {
|
||||
|
|
@ -2304,8 +2346,14 @@ static void virtual_motion_run(void) {
|
|||
struct zwlr_virtual_pointer_v1 *vptr =
|
||||
zwlr_virtual_pointer_manager_v1_create_virtual_pointer(
|
||||
virtual_ptr_mgr, seat);
|
||||
zwlr_virtual_pointer_v1_motion(vptr, 1000,
|
||||
wl_fixed_from_double(virtual_dx), wl_fixed_from_double(virtual_dy));
|
||||
if (virtual_abs_x >= 0.0 && virtual_abs_y >= 0.0)
|
||||
zwlr_virtual_pointer_v1_motion_absolute(vptr, 1000,
|
||||
wl_fixed_from_double(virtual_abs_x * 1000.0),
|
||||
wl_fixed_from_double(virtual_abs_y * 1000.0), 1000, 1000);
|
||||
else
|
||||
zwlr_virtual_pointer_v1_motion(vptr, 1000,
|
||||
wl_fixed_from_double(virtual_dx),
|
||||
wl_fixed_from_double(virtual_dy));
|
||||
if (virtual_click) {
|
||||
/* BTN_LEFT down/up at the new position. */
|
||||
zwlr_virtual_pointer_v1_button(vptr, 1010, 272, 1);
|
||||
|
|
@ -2705,7 +2753,6 @@ static void demand_primary_once(void) {
|
|||
compositor relays field -> IME -> field end to end. */
|
||||
static bool text_input_mode;
|
||||
static const char *text_input_out;
|
||||
static struct zwp_text_input_v3 *ti_obj;
|
||||
static bool ti_enabled;
|
||||
|
||||
static void ti_note_commit(const char *kind, const char *text) {
|
||||
|
|
@ -2955,7 +3002,8 @@ static void print_usage(const char *argv0) {
|
|||
" logging it to --popup-out when given\n"
|
||||
" --output-mgmt lists the output head (name + size)\n"
|
||||
" to --output-mgmt-out, applying --output-mgmt-size\n"
|
||||
" first when given",
|
||||
" first when given (--output-mgmt-test probes it\n"
|
||||
" instead, recording \"tested\")",
|
||||
argv0, argv0);
|
||||
}
|
||||
|
||||
|
|
@ -3053,6 +3101,9 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
output_mgmt_want_size = true;
|
||||
i += 2;
|
||||
} else if (strcmp(argv[i], "--output-mgmt-test") == 0) {
|
||||
output_mgmt_test_only = true;
|
||||
i += 1;
|
||||
} else if (strcmp(argv[i], "--icon") == 0) {
|
||||
if (i + 1 >= argc) {
|
||||
fprintf(stderr, "wltest: --icon needs a color\n");
|
||||
|
|
@ -3375,6 +3426,22 @@ int main(int argc, char **argv) {
|
|||
} else if (strcmp(argv[i], "--virtual-click") == 0) {
|
||||
virtual_click = true;
|
||||
i += 1;
|
||||
} else if (strcmp(argv[i], "--virtual-abs") == 0) {
|
||||
if (i + 2 >= argc) {
|
||||
fprintf(stderr, "wltest: --virtual-abs needs x y fractions\n");
|
||||
return 1;
|
||||
}
|
||||
virtual_abs_x = atof(argv[i + 1]);
|
||||
virtual_abs_y = atof(argv[i + 2]);
|
||||
i += 3;
|
||||
} else if (strcmp(argv[i], "--virtual-modifiers") == 0) {
|
||||
if (i + 1 >= argc) {
|
||||
fprintf(stderr, "wltest: --virtual-modifiers needs a mask\n");
|
||||
return 1;
|
||||
}
|
||||
virtual_mods = (uint32_t)strtoul(argv[i + 1], NULL, 0);
|
||||
virtual_mods_set = true;
|
||||
i += 2;
|
||||
} else if (strcmp(argv[i], "--activate") == 0) {
|
||||
activate_mode = true;
|
||||
i += 1;
|
||||
|
|
@ -3487,7 +3554,7 @@ int main(int argc, char **argv) {
|
|||
return 0;
|
||||
}
|
||||
/* Virtual keyboard: synthesise keys, then exit. */
|
||||
if (virtual_key_spec) {
|
||||
if (virtual_key_spec || virtual_mods_set) {
|
||||
virtual_key_run();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -3727,9 +3794,9 @@ int main(int argc, char **argv) {
|
|||
fprintf(stderr, "wltest: dialog-modal: xdg_wm_dialog_v1 missing\n");
|
||||
return 1;
|
||||
}
|
||||
struct xdg_dialog_v1 *d =
|
||||
dialog_obj =
|
||||
xdg_wm_dialog_v1_get_xdg_dialog(dialog_mgr, toplevel);
|
||||
xdg_dialog_v1_set_modal(d);
|
||||
xdg_dialog_v1_set_modal(dialog_obj);
|
||||
}
|
||||
|
||||
/* Tearing hint for the window; fractional scale is reported back
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue