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 7b0432d1dd5b4782bcf51b72443e2556cf61d353
Author: Cedric BAIL <[email protected]>
AuthorDate: Sat Aug 15 00:53:33 2026 -0600
e_comp_wl - give wl_output.scale a meaning, and honour set_buffer_scale
E-00 clamped the advertised scale to 1 and blamed set_buffer_scale being an
empty stub. That was half the story. The other half is that the value being
advertised was e_scale, which does not mean what wl_output.scale means.
e_scale is a double that magnifies E's own widgets - it reaches
elm_config_scale_set() and edje_scale_set() and nothing else - and a user may
set it on an ordinary panel purely to make things readable. wl_output.scale
asserts something far stronger: that the display really has that many pixels
per logical unit. Tell a client that on a 1080p screen with scale.factor 2 and
it sizes itself against a 960x540 desktop and overflows the real one. On a
genuine HiDPI panel where e_scale happened to match the density it was
accidentally right, which is why it survived.
So the scale stops being inferred from a font-size preference. It is not
guessed from EDID either - physical dimensions are often wrong or missing, and
a bad guess rescales every client on the display. It defaults to 1 and is set
with E_WL_OUTPUT_SCALE, which also makes the path testable at all: without it
there is no way to exercise a scale above 1 without HiDPI hardware to hand,
and a path that cannot be tested is one that quietly stops working.
E_Zone.output is a void* that three subsystems write with three different
types, each guarding with "if nobody has yet" - e_comp_x_randr.c puts an
E_Randr2_Screen there, wl_drm its own output, and only e_comp_wl_output_init
an E_Comp_Wl_Output. Whoever initialises first wins, so it is checked by
identity against our own list before being read through rather than simply
cast. Dereferencing it blind reads a scale out of the middle of an unrelated
struct under the x11 backend - and wlcs would not catch it, because the buffer
backend it runs is one where e_comp_wl happens to win that race.
Verified by measuring the window on screen, since wlcs checks no part of this
(its entire buffer-scale coverage is that a scale event arrives at all). A
solid 200x200 buffer, four combinations, all four distinguishable by size:
output 1, buffer 1 -> 200x200
output 1, buffer 2 -> 100x100 set_buffer_scale honoured; was 200x200
output 2, buffer 2 -> 200x200 1:1, the point of the exercise
output 2, buffer 1 -> 400x400 upscaled: right size, soft
All four measured as predicted.
wlcs 1.8.1: 754 passed, 15 failed, failure set unchanged.
---
src/bin/e_comp_wl.c | 75 +++++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 61 insertions(+), 14 deletions(-)
diff --git a/src/bin/e_comp_wl.c b/src/bin/e_comp_wl.c
index c8bdabee1..2d2b74eee 100644
--- a/src/bin/e_comp_wl.c
+++ b/src/bin/e_comp_wl.c
@@ -1509,13 +1509,28 @@ _e_comp_wl_cb_mouse_move(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mou
* Taken from the output the client is on. A surface can straddle two of them;
* this follows the zone, which is the one E already considers the client to
* be on, rather than inventing a second answer to that question.
- *
- * Returns 1 for now, so every conversion below is an identity and nothing
- * changes. Turning it on is a separate commit from teaching the code to ask.
*/
E_API int
-e_comp_wl_client_scale_get(const E_Client *ec EINA_UNUSED)
+e_comp_wl_client_scale_get(const E_Client *ec)
{
+ E_Comp_Wl_Output *output;
+ Eina_List *l;
+
+ if ((!ec) || (!ec->zone) || (!ec->zone->output)) return 1;
+
+ /* E_Zone.output is a void* that three different subsystems write, each
+ * guarding with "if nobody has yet": e_comp_x_randr.c puts an
+ * E_Randr2_Screen there, wl_drm puts its own output, and only
+ * e_comp_wl_output_init puts an E_Comp_Wl_Output. Whoever runs first wins,
+ * so the pointer cannot simply be dereferenced as ours - under the x11
+ * backend it frequently is not. Confirm it is one of ours by identity
+ * before reading through it. The list has one entry per zone. */
+ EINA_LIST_FOREACH(e_comp_wl->outputs, l, output)
+ {
+ if (output != ec->zone->output) continue;
+ if (output->scale >= 1.0) return (int)(output->scale + 0.5);
+ break;
+ }
return 1;
}
@@ -3737,16 +3752,48 @@ _e_comp_wl_cb_output_unbind(struct wl_resource *resource)
output->resources = eina_list_remove(output->resources, resource);
}
-/* E-00: we advertise wl_output.scale but ignore wl_surface.set_buffer_scale -
- * _e_comp_wl_surface_cb_buffer_scale_set is an empty stub - so a client that
- * believes us attaches a 2x buffer which we then paint 1:1, and every window
- * on a HiDPI zone comes out at double size.
+/* The scale a new output starts at.
*
- * Claim scale 1 until the buffer scale is really honoured. Revert this commit
- * when E-17 lands. */
-static int32_t
-_e_comp_wl_output_scale_get(E_Comp_Wl_Output *output EINA_UNUSED)
+ * E_WL_OUTPUT_SCALE overrides it. That exists because otherwise there is no
+ * way to exercise a scale above 1 without HiDPI hardware in front of you, and
+ * a path that cannot be tested is one that quietly stops working. Read once:
+ * outputs come and go, but this is a property of the session. */
+static double
+_e_comp_wl_output_scale_default(void)
{
+ static double cached = -1.0;
+
+ if (cached < 0.0)
+ {
+ const char *s = getenv("E_WL_OUTPUT_SCALE");
+ int v = s ? atoi(s) : 0;
+
+ cached = (v > 0) ? (double)v : 1.0;
+ }
+ return cached;
+}
+
+/* The integer scale to advertise for an output.
+ *
+ * This used to be e_scale, which is what E-00 was working around, and the
+ * diagnosis in that commit was not quite right: the problem was never only
+ * that set_buffer_scale was ignored. e_scale is a double that magnifies E's
+ * own widgets - it reaches elm_config_scale_set() and edje_scale_set() and
+ * nothing else - and a user may set it on an ordinary panel purely to make
+ * things readable. wl_output.scale asserts something far stronger, that the
+ * panel really does have that many pixels per logical unit. Tell a client
+ * that on a 1080p screen with scale.factor 2 and it sizes itself against a
+ * 960x540 desktop and overflows the real one.
+ *
+ * So the scale is no longer inferred from a font-size preference. It is not
+ * guessed from EDID either: physical dimensions are frequently wrong or
+ * missing, and a wrong guess here rescales every client on the display. It is
+ * whatever it was set to, which is 1 unless somebody said otherwise. */
+static int32_t
+_e_comp_wl_output_scale_get(E_Comp_Wl_Output *output)
+{
+ if (output && (output->scale >= 1.0))
+ return (int32_t)(output->scale + 0.5);
return 1;
}
@@ -4573,7 +4620,7 @@ e_comp_wl_output_init(const char *id, const char *make, const char *model,
_e_comp_wl_cb_output_bind);
output->resources = NULL;
- output->scale = e_scale;
+ output->scale = _e_comp_wl_output_scale_default();
zone->output = output;
}
@@ -4590,7 +4637,7 @@ e_comp_wl_output_init(const char *id, const char *make, const char *model,
output->transform = transform;
if (output->scale <= 0)
- output->scale = e_scale;
+ output->scale = _e_comp_wl_output_scale_default();
/* if we have bound resources, send updates */
EINA_LIST_FOREACH(output->resources, l2, resource)
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.