This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch wl/browser-all
in repository enlightenment.
View the commit online.
commit e0b515db76e13d13267c10c4c4a1ce0a359fb729
Author: Cedric BAIL <[email protected]>
AuthorDate: Sun Aug 16 17:58:47 2026 -0600
e_comp_wl - implement wp_fractional_scale_manager_v1
Tells a surface what scale to render itself at, as a fraction over 120.
Without it a client on a non-integer display can only round - render at
2x and let the compositor shrink, costing sharpness and memory, or render
at 1x and be soft - and Firefox says so when the global is missing.
The scale is only a request; what carries it out is wp_viewporter, which
is why this protocol is meaningless without one. The client renders a
buffer of whatever pixel size the fraction implies, leaves
set_buffer_scale at 1, and uses wp_viewport.set_destination to say how
big that is in surface-local units. E already does that arithmetic, so
nothing new was needed to render a fractionally scaled client.
What E cannot yet do is want a fractional scale. Every writer of
E_Comp_Wl_Output.scale sets a whole number - the default parses
E_WL_OUTPUT_SCALE with atoi - so the preferred scale is always a multiple
of 120. That is a true answer rather than a placeholder, a client told 120
renders 1:1 and is right to, but the sharper text this protocol exists for
arrives only once E has a fractional output scale to report. That is a
change to E's coordinate model, not to this file: ec->x/y/w/h and every
zone are physical pixels, and e_comp_wl_client_scale_get returns an int
because nothing downstream of it can presently take anything else.
wlcs checks that the object can be created and that a second one on the
same surface is an error, and stops there - neither of its two tests ever
looks at a preferred_scale, so a compositor that creates the object and
then never speaks passes both. The in-tree test covers what they do not:
that the scale arrives unasked, because a client has nothing to render at
until it is told one, and that it arrives again when the surface moves to
an output with a different scale, which is why this is an event and not a
property. It is also where a genuinely fractional output scale would
first be checked.
wlcs FractionalScaleV1Test: 2 skipped -> 2 passed.
---
src/bin/e_comp_wl.h | 9 ++
src/bin/e_comp_wl_extensions.c | 140 ++++++++++++++++++
src/bin/generated/meson.build | 1 +
src/tests/wayland/globals.expected | 1 +
src/tests/wayland/meson.build | 2 +
src/tests/wayland/test_fractional_scale.c | 231 ++++++++++++++++++++++++++++++
6 files changed, 384 insertions(+)
diff --git a/src/bin/e_comp_wl.h b/src/bin/e_comp_wl.h
index 833c6f752..a4d5083c4 100644
--- a/src/bin/e_comp_wl.h
+++ b/src/bin/e_comp_wl.h
@@ -182,6 +182,10 @@ typedef struct E_Comp_Wl_Extension_Data
{
struct wl_global *global;
} wp_viewporter;
+ struct
+ {
+ struct wl_global *global;
+ } wp_fractional_scale_manager_v1;
struct
{
struct wl_global *global;
@@ -401,6 +405,11 @@ struct _E_Comp_Wl_Client_Data
* is latched from there on commit. */
struct wl_resource *viewport_resource;
E_Comp_Wl_Viewport_State viewport;
+ /* The one wp_fractional_scale_v1 this surface is allowed. Kept here rather
+ * than in a hash for the same reason the viewport is: the protocol allows
+ * exactly one per surface and has an error for the second, so the surface
+ * is where the answer to "is there already one" lives. */
+ struct wl_resource *fractional_scale_resource;
/* wl_surface.set_buffer_scale and set_buffer_transform currently in
* effect. The scale is never below 1; the transform is the value the
* client says it has ALREADY applied, so displaying the buffer means
diff --git a/src/bin/e_comp_wl_extensions.c b/src/bin/e_comp_wl_extensions.c
index 17df3e1c1..f8f687ed8 100644
--- a/src/bin/e_comp_wl_extensions.c
+++ b/src/bin/e_comp_wl_extensions.c
@@ -10,6 +10,7 @@
#include "xdg-activation-v1-server-protocol.h"
#include "viewporter-server-protocol.h"
#include "xdg-output-unstable-v1-server-protocol.h"
+#include "fractional-scale-v1-server-protocol.h"
/* mutter uses 32, seems reasonable */
#define HANDLE_LEN 32
@@ -1351,6 +1352,141 @@ static const struct wp_viewporter_interface _e_wp_viewporter_interface =
.get_viewport = _e_wp_viewporter_cb_get_viewport,
};
+/* wp_fractional_scale_manager_v1.
+ *
+ * Tells a surface what scale to render itself at, as a fraction over 120, so
+ * that 180 means 1.5. Without it a client on a non-integer display can only
+ * round: render at 2x and let the compositor shrink, which costs sharpness and
+ * memory, or render at 1x and be soft. Firefox complains when it is absent.
+ *
+ * The scale is only a request; what carries it out is wp_viewporter, which is
+ * why this protocol is meaningless without one. The client renders a buffer of
+ * whatever pixel size the fraction implies, leaves wl_surface.set_buffer_scale
+ * at 1, and uses wp_viewport.set_destination to say how big that is in
+ * surface-local units. E already does that arithmetic - the viewport half of
+ * _e_comp_wl_surface_state_size_update - so nothing new is needed to render a
+ * fractionally scaled client correctly.
+ *
+ * What E cannot yet do is *want* a fractional scale.
+ * _e_comp_wl_output_scale_default() parses E_WL_OUTPUT_SCALE with atoi, and
+ * every other writer of E_Comp_Wl_Output.scale sets a whole number, so the
+ * value computed here is always a multiple of 120. That is a true answer
+ * rather than a placeholder - a client told 120 renders 1:1 and is right to -
+ * but the sharper text this protocol exists for arrives only once E has a
+ * fractional output scale to report, and that is a change to E's coordinate
+ * model rather than to this file: ec->x/y/w/h and every zone are physical
+ * pixels, and e_comp_wl_client_scale_get returns an int because nothing
+ * downstream of it can presently take anything else. */
+
+/* The scale to ask a surface for, as the numerator over a denominator of 120. */
+static uint32_t
+_e_fractional_scale_preferred(E_Client *ec)
+{
+ int scale = 1;
+
+ if (ec) scale = e_comp_wl_client_scale_get(ec);
+ if (scale < 1) scale = 1;
+
+ return (uint32_t)scale * 120;
+}
+
+static void
+_e_fractional_scale_send(E_Client *ec)
+{
+ struct wl_resource *res;
+
+ if ((!ec) || (!ec->comp_data)) return;
+ res = ec->comp_data->fractional_scale_resource;
+ if (!res) return;
+
+ wp_fractional_scale_v1_send_preferred_scale(res,
+ _e_fractional_scale_preferred(ec));
+}
+
+static void
+_e_wp_fractional_scale_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
+{
+ wl_resource_destroy(resource);
+}
+
+static const struct wp_fractional_scale_v1_interface _e_wp_fractional_scale_interface =
+{
+ .destroy = _e_wp_fractional_scale_cb_destroy,
+};
+
+/* called by wl_resource_destroy */
+static void
+_e_wp_fractional_scale_res_destroy(struct wl_resource *resource)
+{
+ E_Client *ec = wl_resource_get_user_data(resource);
+
+ if ((!ec) || e_object_is_del(E_OBJECT(ec)) || (!ec->comp_data)) return;
+ if (ec->comp_data->fractional_scale_resource == resource)
+ ec->comp_data->fractional_scale_resource = NULL;
+}
+
+static void
+_e_wp_fractional_scale_manager_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
+{
+ wl_resource_destroy(resource);
+}
+
+static void
+_e_wp_fractional_scale_manager_cb_get_fractional_scale(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface)
+{
+ struct wl_resource *res;
+ E_Client *ec;
+
+ ec = wl_resource_get_user_data(surface);
+ if ((!ec) || e_object_is_del(E_OBJECT(ec)) || (!ec->comp_data))
+ {
+ wl_resource_post_error(resource,
+ WP_FRACTIONAL_SCALE_MANAGER_V1_ERROR_FRACTIONAL_SCALE_EXISTS,
+ "wl_surface is gone");
+ return;
+ }
+ if (ec->comp_data->fractional_scale_resource)
+ {
+ wl_resource_post_error(resource,
+ WP_FRACTIONAL_SCALE_MANAGER_V1_ERROR_FRACTIONAL_SCALE_EXISTS,
+ "wl_surface already has a wp_fractional_scale_v1");
+ return;
+ }
+
+ res = wl_resource_create(client, &wp_fractional_scale_v1_interface,
+ wl_resource_get_version(resource), id);
+ if (!res)
+ {
+ wl_client_post_no_memory(client);
+ return;
+ }
+ wl_resource_set_implementation(res, &_e_wp_fractional_scale_interface, ec,
+ _e_wp_fractional_scale_res_destroy);
+ ec->comp_data->fractional_scale_resource = res;
+
+ /* A client has nothing to render at until it has been told a scale, so say
+ * so now rather than waiting for the surface to land somewhere. */
+ _e_fractional_scale_send(ec);
+}
+
+static const struct wp_fractional_scale_manager_v1_interface _e_wp_fractional_scale_manager_v1_interface =
+{
+ .destroy = _e_wp_fractional_scale_manager_cb_destroy,
+ .get_fractional_scale = _e_wp_fractional_scale_manager_cb_get_fractional_scale,
+};
+
+/* A surface that moves to another zone may have landed on a display with a
+ * different scale, which is the whole reason preferred_scale is an event
+ * rather than a property read once at creation. */
+static Eina_Bool
+_e_fractional_scale_cb_zone_set(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+{
+ E_Event_Client *ev = event;
+
+ if ((ev) && (ev->ec)) _e_fractional_scale_send(ev->ec);
+ return ECORE_CALLBACK_RENEW;
+}
+
/* zxdg_output_manager_v1.
*
* wl_output reports a mode in physical pixels with an integer scale beside it
@@ -1458,6 +1594,7 @@ GLOBAL_BIND_CB(zwp_relative_pointer_manager_v1, zwp_relative_pointer_manager_v1_
GLOBAL_BIND_CB(zwp_pointer_constraints_v1, zwp_pointer_constraints_v1_interface)
GLOBAL_BIND_CB(xdg_activation_v1, xdg_activation_v1_interface)
GLOBAL_BIND_CB(zxdg_output_manager_v1, zxdg_output_manager_v1_interface)
+GLOBAL_BIND_CB(wp_fractional_scale_manager_v1, wp_fractional_scale_manager_v1_interface)
GLOBAL_BIND_CB(action_route, action_route_interface,
e_binding_key_list_cb = _action_route_key_list_cb;
key_bindings = eina_hash_string_superfast_new(NULL);
@@ -1559,8 +1696,11 @@ e_comp_wl_extensions_init(void)
GLOBAL_CREATE_OR_RETURN(xdg_activation_v1, xdg_activation_v1_interface, 1);
GLOBAL_CREATE_OR_RETURN(wp_viewporter, wp_viewporter_interface, 1);
GLOBAL_CREATE_OR_RETURN(zxdg_output_manager_v1, zxdg_output_manager_v1_interface, 3);
+ GLOBAL_CREATE_OR_RETURN(wp_fractional_scale_manager_v1, wp_fractional_scale_manager_v1_interface, 1);
ecore_event_handler_add(ECORE_WL2_EVENT_SYNC_DONE, _dmabuf_add, NULL);
+ ecore_event_handler_add(E_EVENT_CLIENT_ZONE_SET,
+ _e_fractional_scale_cb_zone_set, NULL);
e_client_hook_add(E_CLIENT_HOOK_MOVE_BEGIN, _e_comp_wl_extensions_client_move_begin, NULL);
e_client_hook_add(E_CLIENT_HOOK_MOVE_END, _e_comp_wl_extensions_client_move_end, NULL);
diff --git a/src/bin/generated/meson.build b/src/bin/generated/meson.build
index 473c234c8..0cbe69904 100644
--- a/src/bin/generated/meson.build
+++ b/src/bin/generated/meson.build
@@ -10,6 +10,7 @@ protos = [
'@0@/stable/viewporter/viewporter.xml'.format(dir_wayland_protocols),
'@0@/unstable/xdg-output/xdg-output-unstable-v1.xml'.format(dir_wayland_protocols),
'@0@/unstable/primary-selection/primary-selection-unstable-v1.xml'.format(dir_wayland_protocols),
+ '@0@/staging/fractional-scale/fractional-scale-v1.xml'.format(dir_wayland_protocols),
]
proto_c = []
diff --git a/src/tests/wayland/globals.expected b/src/tests/wayland/globals.expected
index 80ed8f714..40ccb62e2 100644
--- a/src/tests/wayland/globals.expected
+++ b/src/tests/wayland/globals.expected
@@ -7,6 +7,7 @@ wl_seat 8
wl_shell 1
wl_shm 1
wl_subcompositor 1
+wp_fractional_scale_manager_v1 1
wp_viewporter 1
xdg_activation_v1 1
xdg_wm_base 6
diff --git a/src/tests/wayland/meson.build b/src/tests/wayland/meson.build
index 57fb79d48..bf117ccd5 100644
--- a/src/tests/wayland/meson.build
+++ b/src/tests/wayland/meson.build
@@ -31,6 +31,7 @@ foreach p: [
'../../protocol/wl-test.xml',
'@0@/stable/xdg-shell/xdg-shell.xml'.format(dir_wayland_protocols),
'@0@/staging/xdg-activation/xdg-activation-v1.xml'.format(dir_wayland_protocols),
+ '@0@/staging/fractional-scale/fractional-scale-v1.xml'.format(dir_wayland_protocols),
]
test_proto_src += gen_scanner_client.process(p)
test_proto_src += gen_scanner_impl.process(p)
@@ -56,6 +57,7 @@ wl_protocol_tests = [
['output', 'test_output.c'],
['activation', 'test_activation.c'],
['buffer-scale', 'test_buffer_scale.c'],
+ ['fractional-scale', 'test_fractional_scale.c'],
]
foreach t: wl_protocol_tests
diff --git a/src/tests/wayland/test_fractional_scale.c b/src/tests/wayland/test_fractional_scale.c
new file mode 100644
index 000000000..bdeb0b683
--- /dev/null
+++ b/src/tests/wayland/test_fractional_scale.c
@@ -0,0 +1,231 @@
+/* Does wp_fractional_scale_v1 say what scale to render at, and say it again
+ * when the answer changes?
+ *
+ * The protocol is one event. wlcs checks that the object can be created and
+ * that a second one on the same surface is an error, and stops there - neither
+ * of its two tests ever looks at a preferred_scale. So the whole substance of
+ * the protocol is untested by the conformance suite: a compositor that creates
+ * the object and then never speaks passes both.
+ *
+ * What matters is that the scale arrives without being asked for - a client
+ * has nothing to render at until it is told - and that it arrives *again* when
+ * the surface lands on a display with a different scale, which is why this is
+ * an event and not a property read once.
+ *
+ * The scale is a fraction over 120, so 120 is 1:1 and 240 is 2x. E can only
+ * produce whole multiples of 120 today, because every writer of
+ * E_Comp_Wl_Output.scale sets a whole number; that is what is asserted here,
+ * and this test is where a genuinely fractional output scale would first be
+ * checked.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <wayland-client.h>
+#include "wl-test-client-protocol.h"
+#include "xdg-shell-client-protocol.h"
+#include "fractional-scale-v1-client-protocol.h"
+
+#define W 200
+#define H 150
+
+#define FAIL(fmt, ...) \
+ do { fprintf(stderr, "test-fractional-scale: " fmt "\n", ##__VA_ARGS__); return 1; } while (0)
+
+static struct wl_compositor *compositor;
+static struct wl_shm *shm;
+static struct xdg_wm_base *wm_base;
+static struct wl_test *tester;
+static struct wp_fractional_scale_manager_v1 *fs_manager;
+static struct wl_registry *reg;
+static struct wl_display *disp;
+static int sync_done, configured;
+
+/* Last preferred_scale seen, and how many have arrived. */
+static uint32_t preferred;
+static int preferred_n;
+
+static void
+_fs_preferred(void *d, struct wp_fractional_scale_v1 *f, uint32_t scale)
+{
+ (void)d; (void)f;
+ preferred = scale;
+ preferred_n++;
+}
+
+static const struct wp_fractional_scale_v1_listener _fs_listener =
+{
+ _fs_preferred
+};
+
+static void _wm_ping(void *d, struct xdg_wm_base *b, uint32_t serial)
+{ (void)d; xdg_wm_base_pong(b, serial); }
+static const struct xdg_wm_base_listener _wm_listener = { _wm_ping };
+
+static void _xdg_conf(void *d, struct xdg_surface *s, uint32_t serial)
+{ (void)d; xdg_surface_ack_configure(s, serial); configured = 1; }
+static const struct xdg_surface_listener _xdg_listener = { _xdg_conf };
+
+static void _top_conf(void *d, struct xdg_toplevel *t, int32_t w, int32_t h, struct wl_array *st)
+{ (void)d; (void)t; (void)w; (void)h; (void)st; }
+static void _top_close(void *d, struct xdg_toplevel *t) { (void)d; (void)t; }
+static const struct xdg_toplevel_listener _top_listener = { _top_conf, _top_close };
+
+static void _sync_done(void *d, struct wl_test *t) { (void)d; (void)t; sync_done = 1; }
+static void _client_serial(void *d, struct wl_test *t, uint32_t s) { (void)d; (void)t; (void)s; }
+static void _surface_info(void *d, struct wl_test *t, struct wl_surface *s, int32_t x, int32_t y, int32_t w, int32_t h, uint32_t vis, uint32_t foc)
+{ (void)d; (void)t; (void)s; (void)x; (void)y; (void)w; (void)h; (void)vis; (void)foc; }
+static void _surface_unknown(void *d, struct wl_test *t, struct wl_surface *s)
+{ (void)d; (void)t; (void)s; }
+static void _surface_buffer_info(void *d, struct wl_test *t, struct wl_surface *s, int32_t bs, int32_t bt, int32_t os)
+{ (void)d; (void)t; (void)s; (void)bs; (void)bt; (void)os; }
+static const struct wl_test_listener _tester_listener =
+{
+ _client_serial, _surface_info, _surface_unknown, _sync_done,
+ _surface_buffer_info
+};
+
+static void
+_global(void *data, struct wl_registry *r, uint32_t id, const char *iface, uint32_t ver)
+{
+ (void)data; (void)r; (void)ver;
+ if (!strcmp(iface, "wl_compositor"))
+ compositor = wl_registry_bind(reg, id, &wl_compositor_interface, 4);
+ else if (!strcmp(iface, "wl_shm"))
+ shm = wl_registry_bind(reg, id, &wl_shm_interface, 1);
+ else if (!strcmp(iface, "xdg_wm_base"))
+ {
+ wm_base = wl_registry_bind(reg, id, &xdg_wm_base_interface, 1);
+ xdg_wm_base_add_listener(wm_base, &_wm_listener, NULL);
+ }
+ else if (!strcmp(iface, "wp_fractional_scale_manager_v1"))
+ fs_manager = wl_registry_bind(reg, id,
+ &wp_fractional_scale_manager_v1_interface, 1);
+ else if (!strcmp(iface, "wl_test"))
+ tester = wl_registry_bind(reg, id, &wl_test_interface, 3);
+}
+
+static void _global_rm(void *d, struct wl_registry *r, uint32_t id) { (void)d; (void)r; (void)id; }
+static const struct wl_registry_listener _reg_listener = { _global, _global_rm };
+
+static int
+csync(void)
+{
+ sync_done = 0;
+ wl_test_sync(tester);
+ while (!sync_done)
+ if (wl_display_dispatch(disp) < 0) return -1;
+ return wl_display_roundtrip(disp) < 0 ? -1 : 0;
+}
+
+static struct wl_buffer *
+make_buffer(void)
+{
+ int fd, stride = W * 4, size = stride * H;
+ void *map;
+ struct wl_shm_pool *pool;
+ struct wl_buffer *buf;
+
+ fd = shm_open("/e-test-fracscale-shm", O_RDWR | O_CREAT | O_EXCL, 0600);
+ if (fd < 0) return NULL;
+ shm_unlink("/e-test-fracscale-shm");
+ if (ftruncate(fd, size) < 0) { close(fd); return NULL; }
+ map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (map == MAP_FAILED) { close(fd); return NULL; }
+ memset(map, 0xff, size);
+ pool = wl_shm_create_pool(shm, fd, size);
+ buf = wl_shm_pool_create_buffer(pool, 0, W, H, stride, WL_SHM_FORMAT_ARGB8888);
+ wl_shm_pool_destroy(pool);
+ close(fd);
+ return buf;
+}
+
+int
+main(void)
+{
+ struct wl_surface *surface;
+ struct xdg_surface *xdg_surface;
+ struct xdg_toplevel *toplevel;
+ struct wp_fractional_scale_v1 *fs;
+ struct wl_buffer *buffer;
+
+ disp = wl_display_connect(NULL);
+ if (!disp) FAIL("cannot connect to WAYLAND_DISPLAY=%s", getenv("WAYLAND_DISPLAY") ?: "(unset)");
+
+ reg = wl_display_get_registry(disp);
+ wl_registry_add_listener(reg, &_reg_listener, NULL);
+ if (wl_display_roundtrip(disp) < 0) FAIL("registry roundtrip failed");
+
+ if (!compositor || !shm || !wm_base) FAIL("missing core globals");
+ if (!tester) FAIL("no wl_test -- built without -Dtests=true?");
+ if (!fs_manager)
+ FAIL("wp_fractional_scale_manager_v1 is not advertised. Without it a "
+ "client on a non-integer display can only round its rendering up or "
+ "down, and Firefox says so");
+ wl_test_add_listener(tester, &_tester_listener, NULL);
+
+ surface = wl_compositor_create_surface(compositor);
+ xdg_surface = xdg_wm_base_get_xdg_surface(wm_base, surface);
+ xdg_surface_add_listener(xdg_surface, &_xdg_listener, NULL);
+ toplevel = xdg_surface_get_toplevel(xdg_surface);
+ xdg_toplevel_add_listener(toplevel, &_top_listener, NULL);
+ xdg_toplevel_set_title(toplevel, "fractional-scale");
+ wl_surface_commit(surface);
+ while (!configured)
+ if (wl_display_dispatch(disp) < 0) FAIL("dispatch failed awaiting configure");
+
+ buffer = make_buffer();
+ if (!buffer) FAIL("could not create an shm buffer");
+ wl_surface_attach(surface, buffer, 0, 0);
+ wl_surface_damage(surface, 0, 0, W, H);
+ wl_surface_commit(surface);
+ if (csync() < 0) FAIL("sync failed after mapping");
+
+ /* The scale must arrive unasked: a client has nothing to render at until
+ * it has been told one. */
+ preferred = 0;
+ preferred_n = 0;
+ fs = wp_fractional_scale_manager_v1_get_fractional_scale(fs_manager, surface);
+ wp_fractional_scale_v1_add_listener(fs, &_fs_listener, NULL);
+ if (csync() < 0) FAIL("sync failed after get_fractional_scale");
+
+ if (!preferred_n)
+ FAIL("no preferred_scale after get_fractional_scale. The event is the "
+ "whole protocol -- a client that is never told a scale cannot use "
+ "one, and wlcs does not check this");
+ if (preferred != 120)
+ FAIL("preferred_scale is %u on a scale 1 output, expected 120 (the "
+ "denominator is 120, so 120 means 1:1)", preferred);
+ printf("test-fractional-scale: scale 1 output reports %u\n", preferred);
+
+ /* --- a second output at another scale --------------------------------- */
+
+ wl_test_zone_add(tester, 1024, 0, 800, 600);
+ if (csync() < 0) FAIL("sync failed after zone_add");
+ wl_test_output_scale_set(tester, 1, 2);
+ if (csync() < 0) FAIL("sync failed after output_scale_set");
+
+ if (preferred != 120)
+ FAIL("scaling the *other* output changed this surface's preferred scale "
+ "to %u", preferred);
+
+ preferred_n = 0;
+ wl_test_move_surface(tester, surface, 1200, 100);
+ if (csync() < 0) FAIL("sync failed after move");
+
+ if (!preferred_n)
+ FAIL("the surface moved onto a scale 2 output and was never told. A "
+ "preferred_scale that is only ever sent once is a property, and "
+ "this protocol made it an event on purpose");
+ if (preferred != 240)
+ FAIL("on the scale 2 output preferred_scale is %u, expected 240",
+ preferred);
+ printf("test-fractional-scale: moving to a scale 2 output reports %u\n",
+ preferred);
+
+ printf("test-fractional-scale: ok\n");
+ return 0;
+}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.