This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch wl/real-browser
in repository enlightenment.
View the commit online.
commit 469941fb77dee09ab9881906c4ba955948b76e4d
Author: Cedric BAIL <[email protected]>
AuthorDate: Sun Aug 16 23:06:42 2026 -0600
tests - run a real browser and drive it
Everything else in this directory tests the compositor against a client this
suite wrote, which knows the protocol because the same person wrote both. That
is the wrong shape for the question this branch exists to answer. Browsers are
the hardest clients there are: client-side decorations with shadow outside the
window, a subsurface per piece of chrome, several toplevels at once, and a
habit of destroying buffers the moment they are released. Three of the five
compositor bugs fixed on this branch so far only appear against one.
So run one and do to it what a user does - maximise, unmaximise, move, resize,
minimise, restore - and assert what the compositor believes at each step.
The assertions are relative on purpose. A browser's frame is not the zone, and
asserting exact geometry against the screen would be asserting the browser's
shadow width. What has to hold is the shape: maximising makes it bigger and
says so, unmaximising puts it back exactly, moving does not resize, minimising
takes it off the screen. Those are true of any browser, and each of them was
broken.
Three things the test deliberately does not do:
* it does not choose the window's size. Resizing a browser to a round number
first looked tidier and was a lie: E moved its own frame and reported the
new size while the browser carried on painting the old one, so the test
would have asserted against a number no client ever agreed to. It takes
the browser's own unmaximised size as the baseline instead.
* it does not drive the interactive move grab. That is asserted in
test_client_move.c, where "where was the pointer when the drag started"
has one unambiguous answer; against a browser the pointer can be over a
subsurface while the toplevel is what moves, and the test would be
measuring which surface a warp landed on.
* it does not assume how the browser opens. Firefox opens maximised and
Chromium does not.
browser-run.sh is the launcher. Private mode is used and is NOT what isolates:
Chromium's --incognito still reads the default user-data-dir and Firefox's
private window still reads the profile's prefs.js, so the disposable profile
does that work. Private mode buys no session restore and no onboarding tabs,
which is worth having when counting windows. A private D-Bus, no network, and a
pinned locale and timezone stop the browser reaching past the session - a test
that quietly depends on the internet fails on the one machine without it,
months later, for reasons nobody can reconstruct.
run-nested.sh grows E_TEST_APP for it: a command started inside the session
before the client, in its own process group because a browser is a dozen
processes and only one of them is the pid we get back. It also starts its own
Xvfb for E_TEST_BACKEND=x11 now, so that backend needs no more setup than
"buffer" does, and prints the app's log when a test fails - usually the reason.
Its own meson suite, because it is slow and depends on software this tree does
not ship. A browser that is not installed is a skip, not a failure.
Firefox and Brave pass. Chromium does not unmaximise, which is a real defect
and is next.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
---
src/tests/wayland/browser-run.sh | 123 ++++++++++++++++++++++++++++++
src/tests/wayland/e_wl_testkit.c | 35 +++++++++
src/tests/wayland/e_wl_testkit.h | 20 +++++
src/tests/wayland/meson.build | 27 +++++++
src/tests/wayland/run-nested.sh | 62 +++++++++++++++
src/tests/wayland/test_browser.c | 159 +++++++++++++++++++++++++++++++++++++++
6 files changed, 426 insertions(+)
diff --git a/src/tests/wayland/browser-run.sh b/src/tests/wayland/browser-run.sh
new file mode 100755
index 000000000..12a5dd858
--- /dev/null
+++ b/src/tests/wayland/browser-run.sh
@@ -0,0 +1,123 @@
+#!/bin/sh
+# Launch a browser hermetically, as E_TEST_APP inside run-nested.sh's session.
+#
+# browser-run.sh <firefox|chromium|brave> <url>
+# browser-run.sh --find <firefox|chromium|brave|any> -> prints the binary
+#
+# Exits 77 when the browser is not installed, which meson reports as a skip
+# rather than a failure. A machine without Chrome should not have a red suite.
+#
+# Private mode is used here and it is NOT what does the isolating, which is
+# worth being clear about because it is easy to assume otherwise. Chromium's
+# --incognito still reads the default user-data-dir; Firefox's private window
+# still reads the profile's prefs.js and its extensions. The disposable profile
+# is what keeps the developer's real configuration out of the test. Private
+# mode buys something different and also worth having: no session restore, no
+# history-driven UI, and no onboarding tabs to confuse a window count.
+#
+# Everything else here exists to stop a browser reaching past the session:
+#
+# * a private D-Bus. Browsers ask the session bus for portals, notifications
+# and the secret service. Inheriting the developer's is a leak that can put
+# a file dialog on their real desktop, and a hang when a portal never
+# answers. dbus-run-session gives them one with nothing on it, so those
+# lookups fail immediately instead of doing something surprising.
+#
+# * no network. --host-resolver-rules for Chromium, prefs for Firefox. A test
+# that quietly depends on the internet fails on the one machine that has no
+# internet, months later, for reasons nobody can reconstruct.
+#
+# * a pinned locale and timezone, so a window title is the same everywhere.
+
+set -eu
+
+BROWSER=${1:-}
+URL=""
+
+_find() {
+ case "$1" in
+ firefox) for b in firefox firefox-esr; do
+ command -v "$b" 2>/dev/null && return 0
+ done ;;
+ chromium) for b in chromium chromium-browser google-chrome google-chrome-stable; do
+ command -v "$b" 2>/dev/null && return 0
+ done ;;
+ brave) for b in brave brave-browser; do
+ command -v "$b" 2>/dev/null && return 0
+ done ;;
+ any) for w in firefox chromium brave; do
+ _find "$w" && return 0
+ done ;;
+ esac
+ return 1
+}
+
+if [ "$BROWSER" = "--find" ]; then
+ _find "${2:-any}" || exit 77
+ exit 0
+fi
+
+BIN=$(_find "$BROWSER") || {
+ echo "browser-run.sh: no $BROWSER on this machine" >&2
+ exit 77
+}
+
+# run-nested.sh hands us the session's private directory; fall back to our own
+# so this is runnable by hand against a compositor someone else started.
+RUNDIR=${E_TEST_RUNDIR:-$(mktemp -d "${TMPDIR:-/tmp}/e-browser.XXXXXX")}
+PROFILE=""
+mkdir -p "$PROFILE"
+
+COMMON="LC_ALL=C.UTF-8 TZ=UTC GDK_BACKEND=wayland XDG_SESSION_TYPE=wayland \
+XDG_CURRENT_DESKTOP=Enlightenment"
+
+case "$BROWSER" in
+firefox)
+ # user.js rather than command line: Firefox has no flags for most of this.
+ cat > "$PROFILE/user.js" <<'JS'
+user_pref("app.update.enabled", false);
+user_pref("app.update.auto", false);
+user_pref("browser.shell.checkDefaultBrowser", false);
+user_pref("browser.startup.homepage_override.mstone", "ignore");
+user_pref("datareporting.policy.dataSubmissionEnabled", false);
+user_pref("datareporting.healthreport.uploadEnabled", false);
+user_pref("toolkit.telemetry.enabled", false);
+user_pref("toolkit.telemetry.unified", false);
+user_pref("network.captive-portal-service.enabled", false);
+user_pref("network.connectivity-service.enabled", false);
+user_pref("browser.safebrowsing.malware.enabled", false);
+user_pref("browser.safebrowsing.phishing.enabled", false);
+user_pref("extensions.update.enabled", false);
+user_pref("toolkit.startup.max_resumed_crashes", -1);
+JS
+ # -no-remote is not optional. Without it, a developer with Firefox already
+ # open has the URL handed to their real browser and this one exits, so the
+ # test measures nothing while appearing to work.
+ set -- "$BIN" -profile "$PROFILE" -no-remote -private-window "$URL"
+ COMMON="$COMMON MOZ_ENABLE_WAYLAND=1 MOZ_CRASHREPORTER_DISABLE=1"
+ ;;
+chromium|brave)
+ # Quote --host-resolver-rules. Unquoted, the shell globs the * against the
+ # working directory and the browser starts with no rule at all.
+ set -- "$BIN" \
+ --user-data-dir="$PROFILE" --incognito \
+ --no-first-run --no-default-browser-check \
+ --disable-search-engine-choice-screen \
+ --password-store=basic --use-mock-keychain \
+ --disable-component-update --disable-background-networking \
+ --host-resolver-rules="MAP * ~NOTFOUND" \
+ --ozone-platform=wayland --disable-gpu \
+ "$URL"
+ ;;
+*)
+ echo "browser-run.sh: unknown browser '$BROWSER'" >&2
+ exit 2
+ ;;
+esac
+
+if command -v dbus-run-session >/dev/null 2>&1; then
+ exec env $COMMON dbus-run-session -- "$@"
+fi
+# No dbus-run-session: point them at a bus that does not exist rather than at
+# the developer's. A refused connection is immediate; an inherited one is not.
+exec env $COMMON DBUS_SESSION_BUS_ADDRESS=unix:path=/nonexistent "$@"
diff --git a/src/tests/wayland/e_wl_testkit.c b/src/tests/wayland/e_wl_testkit.c
index 888299c9c..33a6b8e2f 100644
--- a/src/tests/wayland/e_wl_testkit.c
+++ b/src/tests/wayland/e_wl_testkit.c
@@ -471,6 +471,34 @@ _now_ms(void)
return (ts.tv_sec * 1000.0) + (ts.tv_nsec / 1000000.0);
}
+Tk_Client *
+tk_wait_window(Tk *tk, const char *app_id_part, int timeout_ms)
+{
+ double deadline = _now_ms() + timeout_ms;
+
+ for (;;)
+ {
+ Tk_Client *best = NULL;
+ int i;
+
+ tk_clients(tk, NULL, 0);
+ for (i = 0; i < tk->client_count; i++)
+ {
+ Tk_Client *c = &tk->clients[i];
+
+ if (!strstr(c->app_id, app_id_part)) continue;
+ if (!(c->states & WL_TEST_CLIENT_STATE_VISIBLE)) continue;
+ if ((!best) || ((c->w * c->h) > (best->w * best->h))) best = c;
+ }
+ if (best) return best;
+ if (_now_ms() >= deadline) break;
+ tk_sync(tk);
+ }
+
+ tk_fail(tk, "waited %dms and no painted window has an app_id containing "
+ "'%s'", timeout_ms, app_id_part);
+}
+
Tk_Client *
tk_wait_state(Tk *tk, const char *app_id, unsigned int mask, unsigned int want,
int timeout_ms, const char *what)
@@ -527,3 +555,10 @@ tk_pointer_move(Tk *tk, int dx, int dy)
wl_test_pointer_move(tk->tester, dx, dy);
tk_settle(tk);
}
+
+void
+tk_pointer_button(Tk *tk, unsigned int button, int pressed)
+{
+ wl_test_pointer_button(tk->tester, button, pressed ? 1 : 0);
+ tk_settle(tk);
+}
diff --git a/src/tests/wayland/e_wl_testkit.h b/src/tests/wayland/e_wl_testkit.h
index a669f2f22..6c9a08d74 100644
--- a/src/tests/wayland/e_wl_testkit.h
+++ b/src/tests/wayland/e_wl_testkit.h
@@ -101,6 +101,19 @@ Tk_Client *tk_find(Tk *tk, const char *app_id);
/* Like tk_find, but a miss is a failure rather than a NULL to check. */
Tk_Client *tk_expect(Tk *tk, const char *app_id);
+/* Wait for a window whose app_id contains this substring to appear and be
+ * painted, and return the largest such window.
+ *
+ * Substring rather than equality, and largest rather than first, because this
+ * is for windows the test did not create. Browsers disagree about their own
+ * app_id - "firefox", "chromium", "brave-browser" - and they map more than one
+ * surface: tiny helpers, and on some toolkits a subsurface per part of the
+ * chrome. The biggest painted one is the window a person would point at.
+ *
+ * The deadline is generous by the standards of the rest of this kit because
+ * starting a browser is not a compositor operation; it is a browser starting. */
+Tk_Client *tk_wait_window(Tk *tk, const char *app_id_part, int timeout_ms);
+
/* Wait until (states & mask) == want, or fail after timeout_ms saying what was
* being waited for and dumping the window list.
*
@@ -130,4 +143,11 @@ void tk_action_end(Tk *tk, unsigned int id, const char *name, const char *params
void tk_pointer_warp(Tk *tk, int x, int y);
void tk_pointer_move(Tk *tk, int dx, int dy);
+/* Press or release a pointer button. linux/input.h codes: BTN_LEFT is 0x110.
+ * A drag a person performs starts with one of these, and it is not decoration:
+ * the press is what brings the client's idea of where the pointer is up to
+ * date, which is what the grab then measures its delta from. */
+void tk_pointer_button(Tk *tk, unsigned int button, int pressed);
+#define TK_BTN_LEFT 0x110
+
#endif
diff --git a/src/tests/wayland/meson.build b/src/tests/wayland/meson.build
index 35f338b5c..510e08810 100644
--- a/src/tests/wayland/meson.build
+++ b/src/tests/wayland/meson.build
@@ -41,6 +41,7 @@ foreach p: [
test_proto_src += gen_scanner_impl.process(p)
endforeach
+
# The golden-globals test. Cheap, and the one test every protocol branch has
# to touch: it makes E's advertised protocol surface a reviewable file.
test('wl-globals',
@@ -79,6 +80,12 @@ wl_protocol_tests = [
# library here would be ceremony around three files.
tk_src = files('e_wl_testkit.c')
+# The browser tier. Its own meson suite, because it is slow, it depends on
+# software this tree does not ship, and a browser that has changed its mind
+# about something must never be able to hold up the protocol tests. A missing
+# browser is a skip (exit 77), not a failure.
+browser_run = files('browser-run.sh')
+
foreach t: wl_protocol_tests
exe = executable('test_wl_' + t[0].underscorify(),
[t[1], tk_src, test_proto_src],
@@ -92,3 +99,23 @@ foreach t: wl_protocol_tests
should_fail: t.length() > 2 and t[2] == 'xfail',
)
endforeach
+
+test_browser = executable('test_wl_browser',
+ ['test_browser.c', tk_src, test_proto_src],
+ dependencies: [dependency('wayland-client')],
+)
+
+foreach b: ['firefox', 'chromium', 'brave']
+ test('browser-' + b,
+ find_program('run-nested.sh'),
+ args : [test_browser, b],
+ env : [
+ 'E_TEST_BIN=' + e_test_bin,
+ 'E_TEST_MODULE_SO=' + wl_test_module_so,
+ 'E_TEST_MODULE_ARCH=' + module_arch,
+ 'E_TEST_APP=@0@ @1@ about:blank'.format(browser_run[0].full_path(), b),
+ ],
+ suite : 'browser',
+ timeout: 300,
+ )
+endforeach
diff --git a/src/tests/wayland/run-nested.sh b/src/tests/wayland/run-nested.sh
index a10518000..8690973c8 100755
--- a/src/tests/wayland/run-nested.sh
+++ b/src/tests/wayland/run-nested.sh
@@ -7,6 +7,9 @@
# E_TEST_BIN path to the installed enlightenment binary (required)
# E_TEST_MODULE_SO path to the built wl_test.so (required; see below)
# E_TEST_MODULE_ARCH E's MODULE_ARCH string (required; see below)
+# E_TEST_APP command to run inside the session before the client,
+# for a test that drives a program it did not write. Its
+# pid reaches the client as E_TEST_APP_PID.
# E_TEST_BACKEND buffer (default) | x11 | wl -- see E_WL_FORCE
# E_TEST_TIMEOUT seconds to wait for E's socket (default 20)
# E_TEST_KEEP set to 1 to keep the temp dir and print E's log path
@@ -95,6 +98,10 @@ if [ ! -d "$E_PREFIX/share/enlightenment" ]; then
exit 1
fi
+# A short path, deliberately. XDG_RUNTIME_DIR holds unix sockets - ours, and
+# any the app under test makes - and sun_path is 108 bytes. A deep TMPDIR makes
+# efreetd fail to bind with a message about nothing in particular, and E's
+# watchdog then kills the session ten seconds later.
RUNDIR=$(mktemp -d "${TMPDIR:-/tmp}/e-wl-test.XXXXXX")
chmod 0700 "$RUNDIR"
@@ -120,6 +127,32 @@ MODULE_DIR="$E_HOME/e/modules/wl_test/$MODULE_ARCH"
mkdir -p "$MODULE_DIR"
ln -s "$MODULE_SO" "$MODULE_DIR/module.so"
+# The x11 backend needs an X server. Inherit one if the caller has it -- that
+# is how a developer watches a test run -- and otherwise start a private Xvfb,
+# so "meson test" needs no more setup for x11 than it does for buffer.
+X_PID=""
+if [ "$BACKEND" = "x11" ] && [ -z "${DISPLAY:-}" ]; then
+ if ! command -v Xvfb >/dev/null 2>&1; then
+ echo "run-nested.sh: E_TEST_BACKEND=x11 needs a DISPLAY or Xvfb" >&2
+ exit 1
+ fi
+ # A display number nobody else is on. :0 through :9 are real sessions.
+ X_DISPLAY=":$((70 + $$ % 20))"
+ Xvfb "$X_DISPLAY" -screen 0 "${E_TEST_SCREEN:-1280x1024x24}" \
+ >"$RUNDIR/xvfb.log" 2>&1 &
+ X_PID=$!
+ DISPLAY="$X_DISPLAY"
+ export DISPLAY
+ # Wait for it to answer rather than guessing how long it takes.
+ i=0
+ while [ $i -lt 100 ]; do
+ [ -S "/tmp/.X11-unix/X${X_DISPLAY#:}" ] && break
+ i=$((i + 1))
+ sleep 0.05
+ done
+fi
+
+APP_PID=""
E_PID=""
E_LOG="$RUNDIR/enlightenment.log"
@@ -146,6 +179,18 @@ procs_in_rundir() {
cleanup() {
status=$?
+ # The app first: it is a client of the compositor, and killing the
+ # compositor out from under it produces a lot of noise about a lost
+ # connection that is nobody's fault.
+ if [ -n "$APP_PID" ] && kill -0 "$APP_PID" 2>/dev/null; then
+ kill -TERM "-$APP_PID" 2>/dev/null || kill -TERM "$APP_PID" 2>/dev/null || :
+ i=0
+ while [ $i -lt 30 ] && kill -0 "$APP_PID" 2>/dev/null; do
+ i=$((i + 1))
+ sleep 0.1
+ done
+ kill -KILL "-$APP_PID" 2>/dev/null || kill -KILL "$APP_PID" 2>/dev/null || :
+ fi
if [ -n "$E_PID" ] && kill -0 "$E_PID" 2>/dev/null; then
kill -TERM "$E_PID" 2>/dev/null || :
# Give it a moment to go down cleanly, then insist.
@@ -167,6 +212,7 @@ cleanup() {
sleep 0.1
done
[ "$(procs_in_rundir KILL)" = "0" ] || sleep 0.5
+ [ -n "$X_PID" ] && kill "$X_PID" 2>/dev/null
if [ "${E_TEST_KEEP:-0}" = "1" ]; then
echo "run-nested.sh: kept $RUNDIR (compositor log: $E_LOG)" >&2
else
@@ -261,6 +307,18 @@ while [ $i -lt 50 ]; do
sleep 0.1
done
+# The program under test, if there is one. Started before the client so the
+# client can find its window, and in its own process group so the whole tree
+# goes down together -- a browser is a dozen processes and only one of them is
+# the pid we get back.
+if [ -n "${E_TEST_APP:-}" ]; then
+ setsid env XDG_RUNTIME_DIR="$RUNDIR" WAYLAND_DISPLAY="$SOCKET" \
+ HOME="$RUNDIR" E_TEST_RUNDIR="$RUNDIR" \
+ sh -c "$E_TEST_APP" >"$RUNDIR/app.log" 2>&1 &
+ APP_PID=$!
+ export E_TEST_APP_PID="$APP_PID"
+fi
+
set +e
XDG_RUNTIME_DIR="$RUNDIR" WAYLAND_DISPLAY="$SOCKET" "$@"
client_status=$?
@@ -268,6 +326,10 @@ set -e
if [ $client_status -ne 0 ]; then
echo "run-nested.sh: client '$1' exited $client_status" >&2
+ if [ -n "${E_TEST_APP:-}" ] && [ -s "$RUNDIR/app.log" ]; then
+ echo "--- app log (tail) ---" >&2
+ tail -40 "$RUNDIR/app.log" >&2 || :
+ fi
echo "--- compositor log ---" >&2
cat "$E_LOG" >&2 || :
fi
diff --git a/src/tests/wayland/test_browser.c b/src/tests/wayland/test_browser.c
new file mode 100644
index 000000000..c6b534507
--- /dev/null
+++ b/src/tests/wayland/test_browser.c
@@ -0,0 +1,159 @@
+/* A real browser, driven the way a person drives one.
+ *
+ * Everything else in this directory tests the compositor against a client this
+ * suite wrote, which knows the protocol because the same person wrote both.
+ * That is the wrong shape for the question this branch exists to answer, which
+ * is whether Firefox, Chrome and Brave are usable - and browsers are the
+ * hardest clients there are: client-side decorations with shadows outside the
+ * window, a subsurface per piece of chrome, several toplevels, and a habit of
+ * destroying buffers the moment they are released.
+ *
+ * So: run one, find its window, and do to it what a user does. Maximise,
+ * unmaximise, drag, resize, minimise, restore.
+ *
+ * The assertions are relative on purpose. A browser's frame is not the zone -
+ * CSD shadows sit outside the window and the numbers do not come out round -
+ * so asserting exact geometry against the screen would be asserting the
+ * browser's shadow width. What has to hold is the shape of the behaviour:
+ * maximising makes it bigger and says so, unmaximising puts it back exactly,
+ * dragging moves it without resizing it, minimising takes it off the screen.
+ * Those are the things that were broken, and they are true of any browser.
+ *
+ * argv[1] substring to match the browser's app_id (firefox, chromium, brave)
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "e_wl_testkit.h"
+
+/* Browsers are slow to start and this may be a cold profile. */
+#define APPEAR_MS 40000
+#define SETTLE_MS 10000
+
+#define MAXIMIZED (WL_TEST_CLIENT_STATE_MAXIMIZED_H | \
+ WL_TEST_CLIENT_STATE_MAXIMIZED_V)
+
+int
+main(int argc, char **argv)
+{
+ Tk *tk;
+ Tk_Client *c;
+ unsigned int id;
+ int x0, y0, w0, h0;
+ int mw, mh;
+ char app_id[256];
+ const char *want = (argc > 1) ? argv[1] : "firefox";
+
+ tk = tk_connect("test-browser");
+
+ c = tk_wait_window(tk, want, APPEAR_MS);
+ id = c->id;
+ snprintf(app_id, sizeof(app_id), "%s", c->app_id);
+ printf("test-browser: found '%s' id=%u %dx%d+%d+%d states=0x%x\n",
+ app_id, id, c->w, c->h, c->x, c->y, c->states);
+
+ if ((c->w < 200) || (c->h < 200))
+ tk_fail(tk, "the browser came up at %dx%d - a window that small is not "
+ "usable, and is what a compositor countermanding its own "
+ "configures looks like from outside", c->w, c->h);
+
+ /* Start from a known state, using the browser's own idea of one rather
+ * than a size chosen here. Firefox opens maximised and Chromium does not,
+ * so unmaximise if needed and then take whatever it settles at as the
+ * baseline. Resizing it to a round number first would be worse than
+ * useless: E would move its own frame and report the new size while the
+ * browser carried on painting the old one, and the test would be asserting
+ * against a number no client ever agreed to. */
+ if (c->states & MAXIMIZED)
+ {
+ tk_action(tk, id, "window_maximized_toggle", NULL);
+ c = tk_wait_state(tk, app_id, MAXIMIZED, 0, SETTLE_MS,
+ "the browser to start out unmaximized");
+ }
+
+ x0 = c->x; y0 = c->y; w0 = c->w; h0 = c->h;
+ printf("test-browser: baseline %dx%d+%d+%d\n", w0, h0, x0, y0);
+
+ /* ---------------------------------------------------------- maximise */
+
+ tk_action(tk, id, "window_maximized_toggle", NULL);
+ c = tk_wait_state(tk, app_id, MAXIMIZED, MAXIMIZED, SETTLE_MS,
+ "the browser to report itself maximized");
+ mw = c->w; mh = c->h;
+ if ((mw <= w0) && (mh <= h0))
+ tk_fail(tk, "maximized to %dx%d, no bigger than the %dx%d it started at",
+ mw, mh, w0, h0);
+
+ tk_action(tk, id, "window_maximized_toggle", NULL);
+ c = tk_wait_state(tk, app_id, MAXIMIZED, 0, SETTLE_MS,
+ "the browser to come back from maximized");
+ if ((c->w != w0) || (c->h != h0) || (c->x != x0) || (c->y != y0))
+ tk_fail(tk, "unmaximized to %dx%d+%d+%d, started at %dx%d+%d+%d",
+ c->w, c->h, c->x, c->y, w0, h0, x0, y0);
+
+ /* -------------------------------------------------------------- move */
+
+ /* Programmatic, not a grab. The interactive grab is asserted in
+ * test_client_move.c against a client this suite wrote, where "where was
+ * the pointer when the drag started" has one unambiguous answer. It does
+ * not here: a browser puts its chrome in subsurfaces, so the pointer can be
+ * over a child while the toplevel is the thing being dragged, and a test
+ * that drove the grab from outside would be measuring which surface the
+ * warp landed on rather than anything about moving windows.
+ *
+ * What this checks is the part that is specific to a browser and still
+ * matters: E can move one, and moving it does not resize it. A window that
+ * grows every time it is moved is unusable, and CSD insets are exactly the
+ * sort of thing that causes it. */
+ tk_action(tk, id, "window_move_by", "50 40");
+
+ c = tk_expect(tk, app_id);
+ if ((c->x != x0 + 50) || (c->y != y0 + 40))
+ tk_fail(tk, "moving by 50,40 put the browser at +%d+%d, expected +%d+%d",
+ c->x, c->y, x0 + 50, y0 + 40);
+ if ((c->w != w0) || (c->h != h0))
+ tk_fail(tk, "moving the browser resized it to %dx%d, was %dx%d",
+ c->w, c->h, w0, h0);
+
+ tk_action(tk, id, "window_move_by", "-50 -40");
+ c = tk_expect(tk, app_id);
+ if ((c->x != x0) || (c->y != y0))
+ tk_fail(tk, "moving back put the browser at +%d+%d, expected +%d+%d",
+ c->x, c->y, x0, y0);
+
+ /* ------------------------------------------------------------ resize */
+
+ tk_action(tk, id, "window_resize_by", "120 90");
+ c = tk_expect(tk, app_id);
+ if ((c->w != w0 + 120) || (c->h != h0 + 90))
+ tk_fail(tk, "resizing by 120,90 made the browser %dx%d, expected %dx%d",
+ c->w, c->h, w0 + 120, h0 + 90);
+
+ tk_action(tk, id, "window_resize_by", "-120 -90");
+ c = tk_expect(tk, app_id);
+
+ /* ----------------------------------------------------------- iconify */
+
+ tk_action(tk, id, "window_iconic_toggle", NULL);
+ c = tk_wait_state(tk, app_id,
+ WL_TEST_CLIENT_STATE_ICONIFIED | WL_TEST_CLIENT_STATE_VISIBLE,
+ WL_TEST_CLIENT_STATE_ICONIFIED, SETTLE_MS,
+ "the browser to be minimised and stop being painted");
+
+ tk_action(tk, id, "window_iconic_toggle", NULL);
+ c = tk_wait_state(tk, app_id,
+ WL_TEST_CLIENT_STATE_ICONIFIED | WL_TEST_CLIENT_STATE_VISIBLE,
+ WL_TEST_CLIENT_STATE_VISIBLE, SETTLE_MS,
+ "the browser to come back from minimised");
+
+ if ((c->w != w0) || (c->h != h0))
+ tk_fail(tk, "back from minimised at %dx%d, was %dx%d", c->w, c->h, w0, h0);
+
+ printf("test-browser: ok ('%s' maximized to %dx%d, moved, resized and "
+ "minimised, back at %dx%d+%d+%d)\n",
+ app_id, mw, mh, c->w, c->h, c->x, c->y);
+
+ tk_disconnect(tk);
+ return 0;
+}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.