diff --git a/12to11-test.xml b/12to11-test.xml index af8e62f..3fc6817 100644 --- a/12to11-test.xml +++ b/12to11-test.xml @@ -33,25 +33,46 @@ + + Get a test_surface object for a particular surface. If a role was already attached to this surface, or a role of a different - type was previously attached, a role_present error is issued. + type was previously attached, post a role_present error. - The window is created immediately after get_test_surface is - called. It is mapped once a commit request with a non-nil - buffer is made. + Create the window immediately after get_test_surface is + called; the window is mapped once a commit request with a + non-nil buffer is made. Once the window associated with the test_surface object is - mapped, a mapped event is sent. + mapped, send a mapped event. + + + Create a new test_scale_lock object. As long as this object + exists, set the global output scale to the scale specified in + this request (or in a subsequent test_scale_lock.set_scale + request.) + + If a test_scale_lock object already exists, generate a + scale_lock_exists error. + + If the scale is invalid (by being less than 0), post an + invalid_scale error. + + + + + The display_string event sends the name of the X display to @@ -74,8 +95,8 @@ - This request destroys the test_surface role. Subsequently, - get_test_surface can be called again with its surface. + Destroy the test_surface role. Subsequently, get_test_surface + can be called again with its surface. @@ -94,4 +115,29 @@ + + + + A scale lock resource represents the "lock" a client holds on + the global output scale. While it still exists, the scale for + every output will be whatever was specified when the lock was + created or by the last set_scale request. + + + + + Destroy the specified scale lock, restore the actual scale of + each output, and let clients call get_scale_lock again. + + + + + + Set the scale of each output to the specified scale, and + resize all surfaces accordingly. If the scale is invalid, + post an invalid_scale error. + + + + diff --git a/compositor.h b/compositor.h index f9ee30d..e43f4d1 100644 --- a/compositor.h +++ b/compositor.h @@ -1206,6 +1206,7 @@ extern void XLRemoveScaleChangeCallback (void *); extern void XLClearOutputs (Surface *); extern void XLOutputSetChangeFunction (void (*) (Time)); extern void XLGetMaxOutputBounds (int *, int *, int *, int *); +extern void XLOutputHandleScaleChange (int); /* Defined in atoms.c. */ @@ -1799,6 +1800,8 @@ extern void XLInitPointerGestures (void); /* Defined in test.c. */ +extern int locked_output_scale; + extern void XLInitTest (void); extern Bool XLHandleOneXEventForTest (XEvent *); diff --git a/output.c b/output.c index d8402fb..351f1ea 100644 --- a/output.c +++ b/output.c @@ -98,6 +98,9 @@ static ScaleChangeCallback scale_callbacks; /* The scale factor currently applied on a global basis. */ int global_scale_factor; +/* The current real scale factor. */ +static int real_scale_factor; + /* Function run upon any kind of XRandR notify event. */ static void (*change_hook) (Time); @@ -1035,6 +1038,19 @@ HandleScaleChange (int scale) RunScaleChangeCallbacks (); } +static void +HandleScaleSettingChange (int scale) +{ + real_scale_factor = scale; + + /* If the scale factor is locked, just return. */ + if (locked_output_scale) + return; + + /* Otherwise, update the scale. */ + HandleScaleChange (scale); +} + void * XLAddScaleChangeCallback (void *data, void (*func) (void *, int)) { @@ -1142,6 +1158,18 @@ XLGetMaxOutputBounds (int *x_min, int *y_min, int *x_max, *y_max = y2; } +void +XLOutputHandleScaleChange (int new_scale) +{ + /* If the value is not -1, just use the new scale. + Otherwise, use the current non-locked scale. */ + + if (new_scale != -1) + HandleScaleChange (new_scale); + else + HandleScaleChange (real_scale_factor); +} + void XLInitRROutputs (void) { @@ -1179,7 +1207,10 @@ XLInitRROutputs (void) factor was specified for debugging. */ if (!ApplyEnvironment ("GLOBAL_SCALE", &global_scale_factor)) XLListenToIntegerSetting ("Gdk/WindowScalingFactor", - HandleScaleChange); + HandleScaleSettingChange); + + /* Set the real scale factor. */ + real_scale_factor = global_scale_factor; /* Initialize the scale change callback list sentinel node. */ scale_callbacks.next = &scale_callbacks; @@ -1204,4 +1235,3 @@ XLInitRROutputs (void) all_outputs = BuildOutputTree (); MakeGlobalsForOutputTree (all_outputs); } - diff --git a/test.c b/test.c index 8e36110..ed78ad3 100644 --- a/test.c +++ b/test.c @@ -60,6 +60,11 @@ struct _TestSurface int bounds_width, bounds_height; }; +/* The locked output scale. N.B. that a test_scale_lock is not an + actual resource, and just represents the state of this + variable. */ +int locked_output_scale; + /* The test surface manager global. */ static struct wl_global *test_manager_global; @@ -348,6 +353,47 @@ HandleResourceDestroy (struct wl_resource *resource) DestroyBacking (test); } + + +static void +DestroyScaleLock (struct wl_client *client, struct wl_resource *resource) +{ + wl_resource_destroy (resource); +} + +static void +SetScale (struct wl_client *client, struct wl_resource *resource, + uint32_t scale) +{ + /* If the scale is invalid, reject it. */ + if (!scale) + { + wl_resource_post_error (resource, TEST_MANAGER_ERROR_INVALID_SCALE, + "scale of 0 specified"); + return; + } + + /* Set the scale. As there can only be one lock at any given + time, there is no need to check the resource data. */ + locked_output_scale = scale; + XLOutputHandleScaleChange (scale); +} + +static const struct test_scale_lock_interface scale_lock_impl = + { + .destroy = DestroyScaleLock, + .set_scale = SetScale, + }; + +static void +HandleScaleLockResourceDestroy (struct wl_resource *resource) +{ + /* There is no resource data associated with scale locks. Just + unlock the scale. */ + locked_output_scale = 0; + XLOutputHandleScaleChange (-1); +} + static void GetTestSurface (struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource) @@ -451,9 +497,55 @@ GetTestSurface (struct wl_client *client, struct wl_resource *resource, abort (); } +static void +GetScaleLock (struct wl_client *client, struct wl_resource *resource, + uint32_t id, uint32_t scale) +{ + struct wl_resource *lock_resource; + + if (!scale) + { + wl_resource_post_error (resource, TEST_MANAGER_ERROR_INVALID_SCALE, + "scale of 0 specified"); + return; + } + + if (locked_output_scale) + { + /* The scale is already locked, so don't create another + lock. */ + wl_resource_post_error (resource, TEST_MANAGER_ERROR_SCALE_LOCK_EXISTS, + "a scale lock already exists (another test is" + " already running?)"); + return; + } + + lock_resource = wl_resource_create (client, &test_scale_lock_interface, + wl_resource_get_version (resource), + id); + + if (!lock_resource) + { + wl_resource_post_no_memory (resource); + return; + } + + /* Now, set the locked scale. */ + locked_output_scale = scale; + + /* And update the global scale factor if need be. */ + if (scale != global_scale_factor) + XLOutputHandleScaleChange (scale); + + /* And resource implementation. */ + wl_resource_set_implementation (lock_resource, &scale_lock_impl, + NULL, HandleScaleLockResourceDestroy); +} + static const struct test_manager_interface test_manager_impl = { .get_test_surface = GetTestSurface, + .get_scale_lock = GetScaleLock, }; diff --git a/tests/Imakefile b/tests/Imakefile index 48871fd..f521a9d 100644 --- a/tests/Imakefile +++ b/tests/Imakefile @@ -2,6 +2,7 @@ 12TO11ROOT = .. DEPLIBS = $(DEPXLIB) + SYS_LIBRARIES = MathLibrary LOCAL_LIBRARIES = $(WAYLAND_CLIENT) $(XLIB) $(PNG) COMMONOBJS = test_harness.o COMMONSRCS = test_harness.c @@ -35,7 +36,9 @@ ScannerTarget(viewporter) OBJS5 = $(COMMONSRCS) viewporter_test.o SRCS6 = $(COMMONSRCS) subsurface_test.c OBJS6 = $(COMMONSRCS) subsurface_test.o - PROGRAMS = imgview simple_test damage_test transform_test viewporter_test subsurface_test + SRCS7 = $(COMMONSRCS) scale_test.c + OBJS7 = $(COMMONSRCS) scale_test.o + PROGRAMS = imgview simple_test damage_test transform_test viewporter_test subsurface_test scale_test /* Make all objects depend on HEADER. */ $(OBJS1): $(HEADER) @@ -49,7 +52,9 @@ NormalProgramTarget(damage_test,$(OBJS3),NullParameter,$(LOCAL_LIBRARIES),NullPa NormalProgramTarget(transform_test,$(OBJS4),NullParameter,$(LOCAL_LIBRARIES),NullParameter) NormalProgramTarget(viewporter_test,$(OBJS5),NullParameter,$(LOCAL_LIBRARIES),NullParameter) NormalProgramTarget(subsurface_test,$(OBJS6),NullParameter,$(LOCAL_LIBRARIES),NullParameter) +NormalProgramTarget(scale_test,$(OBJS7),NullParameter,$(LOCAL_LIBRARIES),NullParameter) DependTarget3($(SRCS1),$(SRCS2),$(SRCS3)) DependTarget3($(SRCS4),$(SRCS5),$(SRCS6)) +DependTarget3($(SRCS7),NullParameter,NullParameter) all:: $(PROGRAMS) diff --git a/tests/run_tests.sh b/tests/run_tests.sh index e93bb87..80a79a0 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -21,14 +21,11 @@ pushd "$(dirname $0)" declare -a standard_tests=( simple_test damage_test transform_test viewporter_test - subsurface_test + subsurface_test scale_test ) make -C . "${standard_tests[@]}" -# Run tandard tests, meaning those that should be run with a -# GLOBAL_SCALE of 1 and an OUTPUT_SCALE of 1. - export GLOBAL_SCALE=1 export OUTPUT_SCALE=1 exec 3< <(stdbuf -oL ../12to11 -printsocket) diff --git a/tests/svnignore.txt b/tests/svnignore.txt index a006657..e0d4c69 100644 --- a/tests/svnignore.txt +++ b/tests/svnignore.txt @@ -6,6 +6,7 @@ damage_test transform_test viewporter_test subsurface_test +scale_test imgview reject.dump Makefile diff --git a/tests/test_harness.c b/tests/test_harness.c index 5c084a7..f89ebd3 100644 --- a/tests/test_harness.c +++ b/tests/test_harness.c @@ -45,6 +45,9 @@ along with 12to11. If not, see . */ /* Whether or not to write image data instead of verifying it. */ static bool write_image_data_instead; +/* The test display. */ +static struct test_display *display; + static void handle_test_manager_display_string (void *data, struct test_manager *manager, const char *display_string) @@ -154,10 +157,29 @@ die (const char *reason) exit (1); } +/* This should be called when a test failed due to a non-IO error. It + destroys the scale lock and synchronizes with the compositor so + that by the time the next test is run, the current test's scale + lock will have been released. */ + +static void __attribute__ ((noreturn)) +exit_with_code (int code) +{ + if (display) + { + test_scale_lock_destroy (display->scale_lock); + wl_display_roundtrip (display->display); + } + + exit (code); +} + struct test_display * open_test_display (struct test_interface *interfaces, int num_interfaces) { - struct test_display *display; + if (display) + /* The display was already opened. */ + return display; display = malloc (sizeof *display); @@ -191,8 +213,17 @@ open_test_display (struct test_interface *interfaces, int num_interfaces) if (!test_manager_check (display)) goto error_3; + /* And try to set up the scale lock. */ + display->scale_lock + = test_manager_get_scale_lock (display->test_manager, 1); + + if (!display->scale_lock) + goto error_4; + return display; + error_4: + XFree (display->pixmap_formats); error_3: if (display->x_display) XCloseDisplay (display->x_display); @@ -200,6 +231,7 @@ open_test_display (struct test_interface *interfaces, int num_interfaces) wl_display_disconnect (display->display); error_1: free (display); + display = NULL; return NULL; } @@ -325,7 +357,7 @@ report_test_failure (const char *format, ...) fputs ("\n", stderr); va_end (ap); - exit (1); + exit_with_code (1); } void __attribute__ ((format (gnu_printf, 1, 2))) @@ -766,6 +798,12 @@ verify_image_data (struct test_display *display, Window window, test_log ("verified image data"); } +void +test_set_scale (struct test_display *display, int scale) +{ + test_scale_lock_set_scale (display->scale_lock, scale); +} + void test_init (void) { @@ -777,5 +815,5 @@ void __attribute__ ((noreturn)) test_complete (void) { test_log ("test ran successfully"); - exit (0); + exit_with_code (0); } diff --git a/tests/test_harness.h b/tests/test_harness.h index d95bfc8..aa54a03 100644 --- a/tests/test_harness.h +++ b/tests/test_harness.h @@ -51,6 +51,9 @@ struct test_display struct wl_shm *shm; struct test_manager *test_manager; + /* The test scale lock. */ + struct test_scale_lock *scale_lock; + /* Test interfaces. */ struct test_interface *interfaces; @@ -119,6 +122,7 @@ extern unsigned char *load_image_data (const char *, extern void verify_image_data (struct test_display *, Window, const char *); extern void test_init (void); extern void test_complete (void) __attribute__ ((noreturn)); +extern void test_set_scale (struct test_display *, int); #define ARRAYELTS(arr) (sizeof (arr) / sizeof (arr)[0])