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.

Reply via email to