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])