[clutter/clutter-1.16] x11: Apply the window scaling factor



commit 75f81fee708f4811667191065740815b507d938e
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Wed Aug 14 11:25:01 2013 +0100

    x11: Apply the window scaling factor
    
    On high DPI density displays we create surfaces with a size scaled up by
    a certain factor. Even if the contents stay at the same relative size
    and position, we need to compensate the scaling both when changing the
    surface size, and when dealing with input.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=705915

 clutter/x11/clutter-backend-x11.c             |    2 +-
 clutter/x11/clutter-device-manager-core-x11.c |   27 ++++---
 clutter/x11/clutter-device-manager-xi2.c      |   39 ++++++-----
 clutter/x11/clutter-stage-x11.c               |   93 +++++++++++++++++++------
 clutter/x11/clutter-stage-x11.h               |    3 +
 5 files changed, 111 insertions(+), 53 deletions(-)
---
diff --git a/clutter/x11/clutter-backend-x11.c b/clutter/x11/clutter-backend-x11.c
index 5ca1a0b..9252302 100644
--- a/clutter/x11/clutter-backend-x11.c
+++ b/clutter/x11/clutter-backend-x11.c
@@ -165,7 +165,7 @@ clutter_backend_x11_xsettings_notify (const char       *name,
     {
       if (g_strcmp0 (name, CLUTTER_SETTING_X11_NAME (i)) == 0)
         {
-          GValue value = { 0, };
+          GValue value = G_VALUE_INIT;
 
           switch (setting->type)
             {
diff --git a/clutter/x11/clutter-device-manager-core-x11.c b/clutter/x11/clutter-device-manager-core-x11.c
index 6a3606d..f47e3b8 100644
--- a/clutter/x11/clutter-device-manager-core-x11.c
+++ b/clutter/x11/clutter-device-manager-core-x11.c
@@ -135,6 +135,7 @@ clutter_device_manager_x11_translate_event (ClutterEventTranslator *translator,
   ClutterTranslateReturn res;
   ClutterStage *stage;
   XEvent *xevent;
+  int window_scale;
 
   manager_x11 = CLUTTER_DEVICE_MANAGER_X11 (translator);
   backend_x11 = CLUTTER_BACKEND_X11 (clutter_get_default_backend ());
@@ -150,6 +151,8 @@ clutter_device_manager_x11_translate_event (ClutterEventTranslator *translator,
 
   stage_x11 = CLUTTER_STAGE_X11 (_clutter_stage_get_window (stage));
 
+  window_scale = stage_x11->scale_factor;
+
   event->any.stage = stage;
 
   res = CLUTTER_TRANSLATE_CONTINUE;
@@ -222,8 +225,8 @@ clutter_device_manager_x11_translate_event (ClutterEventTranslator *translator,
             event->scroll.direction = CLUTTER_SCROLL_RIGHT;
 
           event->scroll.time = xevent->xbutton.time;
-          event->scroll.x = xevent->xbutton.x;
-          event->scroll.y = xevent->xbutton.y;
+          event->scroll.x = xevent->xbutton.x / window_scale;
+          event->scroll.y = xevent->xbutton.y / window_scale;
           event->scroll.modifier_state = xevent->xbutton.state;
           event->scroll.axes = NULL;
           break;
@@ -231,8 +234,8 @@ clutter_device_manager_x11_translate_event (ClutterEventTranslator *translator,
         default:
           event->button.type = event->type = CLUTTER_BUTTON_PRESS;
           event->button.time = xevent->xbutton.time;
-          event->button.x = xevent->xbutton.x;
-          event->button.y = xevent->xbutton.y;
+          event->button.x = xevent->xbutton.x / window_scale;
+          event->button.y = xevent->xbutton.y / window_scale;
           event->button.modifier_state = xevent->xbutton.state;
           event->button.button = xevent->xbutton.button;
           event->button.axes = NULL;
@@ -265,8 +268,8 @@ clutter_device_manager_x11_translate_event (ClutterEventTranslator *translator,
 
       event->button.type = event->type = CLUTTER_BUTTON_RELEASE;
       event->button.time = xevent->xbutton.time;
-      event->button.x = xevent->xbutton.x;
-      event->button.y = xevent->xbutton.y;
+      event->button.x = xevent->xbutton.x / window_scale;
+      event->button.y = xevent->xbutton.y / window_scale;
       event->button.modifier_state = xevent->xbutton.state;
       event->button.button = xevent->xbutton.button;
       event->button.axes = NULL;
@@ -283,8 +286,8 @@ clutter_device_manager_x11_translate_event (ClutterEventTranslator *translator,
 
       event->motion.type = event->type = CLUTTER_MOTION;
       event->motion.time = xevent->xmotion.time;
-      event->motion.x = xevent->xmotion.x;
-      event->motion.y = xevent->xmotion.y;
+      event->motion.x = xevent->xmotion.x / window_scale;
+      event->motion.y = xevent->xmotion.y / window_scale;
       event->motion.modifier_state = xevent->xmotion.state;
       event->motion.axes = NULL;
       clutter_event_set_device (event, manager_x11->core_pointer);
@@ -297,8 +300,8 @@ clutter_device_manager_x11_translate_event (ClutterEventTranslator *translator,
 
       event->crossing.type = CLUTTER_ENTER;
       event->crossing.time = xevent->xcrossing.time;
-      event->crossing.x = xevent->xcrossing.x;
-      event->crossing.y = xevent->xcrossing.y;
+      event->crossing.x = xevent->xcrossing.x / window_scale;
+      event->crossing.y = xevent->xcrossing.y / window_scale;
       event->crossing.source = CLUTTER_ACTOR (stage);
       event->crossing.related = NULL;
       clutter_event_set_device (event, manager_x11->core_pointer);
@@ -323,8 +326,8 @@ clutter_device_manager_x11_translate_event (ClutterEventTranslator *translator,
 
       event->crossing.type = CLUTTER_LEAVE;
       event->crossing.time = xevent->xcrossing.time;
-      event->crossing.x = xevent->xcrossing.x;
-      event->crossing.y = xevent->xcrossing.y;
+      event->crossing.x = xevent->xcrossing.x / window_scale;
+      event->crossing.y = xevent->xcrossing.y / window_scale;
       event->crossing.source = CLUTTER_ACTOR (stage);
       event->crossing.related = NULL;
       clutter_event_set_device (event, manager_x11->core_pointer);
diff --git a/clutter/x11/clutter-device-manager-xi2.c b/clutter/x11/clutter-device-manager-xi2.c
index 1ee4fd9..8f9133f 100644
--- a/clutter/x11/clutter-device-manager-xi2.c
+++ b/clutter/x11/clutter-device-manager-xi2.c
@@ -627,11 +627,11 @@ translate_axes (ClutterInputDevice *device,
       switch (axis)
         {
         case CLUTTER_INPUT_AXIS_X:
-          retval[i] = x;
+          retval[i] = x / stage_x11->scale_factor;
           break;
 
         case CLUTTER_INPUT_AXIS_Y:
-          retval[i] = y;
+          retval[i] = y / stage_x11->scale_factor;
           break;
 
         default:
@@ -745,6 +745,7 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
   XGenericEventCookie *cookie;
   XIEvent *xi_event;
   XEvent *xevent;
+  int window_scale;
 
   backend_x11 = CLUTTER_BACKEND_X11 (clutter_get_default_backend ());
 
@@ -773,6 +774,8 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
 
   event->any.stage = stage;
 
+  window_scale = stage_x11->scale_factor;
+
   switch (xi_event->evtype)
     {
     case XI_HierarchyChanged:
@@ -927,8 +930,8 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
             event->scroll.stage = stage;
 
             event->scroll.time = xev->time;
-            event->scroll.x = xev->event_x;
-            event->scroll.y = xev->event_y;
+            event->scroll.x = xev->event_x / window_scale;
+            event->scroll.y = xev->event_y / window_scale;
            _clutter_input_device_xi2_translate_state (event,
                                                       &xev->mods,
                                                       &xev->buttons,
@@ -975,8 +978,8 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
             event->button.stage = stage;
 
             event->button.time = xev->time;
-            event->button.x = xev->event_x;
-            event->button.y = xev->event_y;
+            event->button.x = xev->event_x / window_scale;
+            event->button.y = xev->event_y / window_scale;
             event->button.button = xev->detail;
            _clutter_input_device_xi2_translate_state (event,
                                                       &xev->mods,
@@ -1058,8 +1061,8 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
 
             event->scroll.stage = stage;
             event->scroll.time = xev->time;
-            event->scroll.x = xev->event_x;
-            event->scroll.y = xev->event_y;
+            event->scroll.x = xev->event_x / window_scale;
+            event->scroll.y = xev->event_y / window_scale;
            _clutter_input_device_xi2_translate_state (event,
                                                       &xev->mods,
                                                       &xev->buttons,
@@ -1087,8 +1090,8 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
         event->motion.stage = stage;
 
         event->motion.time = xev->time;
-        event->motion.x = xev->event_x;
-        event->motion.y = xev->event_y;
+        event->motion.x = xev->event_x / window_scale;
+        event->motion.y = xev->event_y / window_scale;
        _clutter_input_device_xi2_translate_state (event,
                                                   &xev->mods,
                                                   &xev->buttons,
@@ -1139,8 +1142,8 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
 
         event->touch.stage = stage;
         event->touch.time = xev->time;
-        event->touch.x = xev->event_x;
-        event->touch.y = xev->event_y;
+        event->touch.x = xev->event_x / window_scale;
+        event->touch.y = xev->event_y / window_scale;
        _clutter_input_device_xi2_translate_state (event,
                                                   &xev->mods,
                                                   &xev->buttons,
@@ -1195,8 +1198,8 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
         event->touch.stage = stage;
         event->touch.time = xev->time;
         event->touch.sequence = GUINT_TO_POINTER (xev->detail);
-        event->touch.x = xev->event_x;
-        event->touch.y = xev->event_y;
+        event->touch.x = xev->event_x / window_scale;
+        event->touch.y = xev->event_y / window_scale;
 
         clutter_event_set_source_device (event, source_device);
 
@@ -1253,8 +1256,8 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
             event->crossing.related = NULL;
 
             event->crossing.time = xev->time;
-            event->crossing.x = xev->event_x;
-            event->crossing.y = xev->event_y;
+            event->crossing.x = xev->event_x / window_scale;
+            event->crossing.y = xev->event_y / window_scale;
 
             _clutter_input_device_set_stage (device, stage);
           }
@@ -1277,8 +1280,8 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
             event->crossing.related = NULL;
 
             event->crossing.time = xev->time;
-            event->crossing.x = xev->event_x;
-            event->crossing.y = xev->event_y;
+            event->crossing.x = xev->event_x / window_scale;
+            event->crossing.y = xev->event_y / window_scale;
 
             _clutter_input_device_set_stage (device, NULL);
           }
diff --git a/clutter/x11/clutter-stage-x11.c b/clutter/x11/clutter-stage-x11.c
index 08b8e15..9907840 100644
--- a/clutter/x11/clutter-stage-x11.c
+++ b/clutter/x11/clutter-stage-x11.c
@@ -22,6 +22,7 @@
 #include "config.h"
 
 #include <math.h>
+#include <stdlib.h>
 
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
@@ -151,10 +152,10 @@ clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11,
                                       &min_height);
 
       if (new_width <= 0)
-        new_width = min_width;
+        new_width = min_width * stage_x11->scale_factor;
 
       if (new_height <= 0)
-        new_height = min_height;
+        new_height = min_height * stage_x11->scale_factor;
 
       size_hints->flags = 0;
 
@@ -164,8 +165,8 @@ clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11,
         {
           if (resize)
             {
-              size_hints->min_width = min_width;
-              size_hints->min_height = min_height;
+              size_hints->min_width = min_width * stage_x11->scale_factor;
+              size_hints->min_height = min_height * stage_x11->scale_factor;
               size_hints->flags = PMinSize;
             }
           else
@@ -225,8 +226,8 @@ clutter_stage_x11_get_geometry (ClutterStageWindow    *stage_window,
       return;
     }
 
-  geometry->width = stage_x11->xwin_width;
-  geometry->height = stage_x11->xwin_height;
+  geometry->width = stage_x11->xwin_width / stage_x11->scale_factor;
+  geometry->height = stage_x11->xwin_height / stage_x11->scale_factor;
 }
 
 static void
@@ -244,8 +245,8 @@ clutter_stage_x11_resize (ClutterStageWindow *stage_window,
        * so we need to manually set the size and queue a relayout on the
        * stage here (as is normally done in response to ConfigureNotify).
        */
-      stage_x11->xwin_width = width;
-      stage_x11->xwin_height = height;
+      stage_x11->xwin_width = width * stage_x11->scale_factor;
+      stage_x11->xwin_height = height * stage_x11->scale_factor;
       clutter_actor_queue_relayout (CLUTTER_ACTOR (stage_cogl->wrapper));
       return;
     }
@@ -266,6 +267,9 @@ clutter_stage_x11_resize (ClutterStageWindow *stage_window,
 
   CLUTTER_NOTE (BACKEND, "New size received: (%d, %d)", width, height);
 
+  width *= stage_x11->scale_factor;
+  height *= stage_x11->scale_factor;
+
   if (stage_x11->xwin != None)
     {
       clutter_stage_x11_fix_window_size (stage_x11, width, height);
@@ -576,11 +580,18 @@ clutter_stage_x11_realize (ClutterStageWindow *stage_window)
   ClutterDeviceManager *device_manager;
   gfloat width, height;
 
-  clutter_actor_get_size (CLUTTER_ACTOR (stage_cogl->wrapper),
-                         &width, &height);
+  clutter_actor_get_size (CLUTTER_ACTOR (stage_cogl->wrapper), &width, &height);
+
+  CLUTTER_NOTE (BACKEND, "Wrapper size: %.2f x %.2f", width, height);
+
+  width = width * (float) stage_x11->scale_factor;
+  height = height * (float) stage_x11->scale_factor;
 
-  stage_cogl->onscreen = cogl_onscreen_new (backend->cogl_context,
-                                            width, height);
+  CLUTTER_NOTE (BACKEND, "Creating a new Cogl onscreen surface: %.2f x %.2f (factor: %d)",
+                width, height,
+                stage_x11->scale_factor);
+
+  stage_cogl->onscreen = cogl_onscreen_new (backend->cogl_context, width, height);
 
   /* We just created a window of the size of the actor. No need to fix
      the size of the stage, just update it. */
@@ -823,6 +834,26 @@ clutter_stage_x11_can_clip_redraws (ClutterStageWindow *stage_window)
 }
 
 static void
+clutter_stage_x11_set_scale_factor (ClutterStageWindow *stage_window,
+                                    int                 factor)
+{
+  ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
+
+  if (stage_x11->fixed_scale_factor)
+    return;
+
+  stage_x11->scale_factor = factor;
+}
+
+static int
+clutter_stage_x11_get_scale_factor (ClutterStageWindow *stage_window)
+{
+  ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
+
+  return stage_x11->scale_factor;
+}
+
+static void
 clutter_stage_x11_finalize (GObject *gobject)
 {
   ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (gobject);
@@ -855,6 +886,8 @@ clutter_stage_x11_class_init (ClutterStageX11Class *klass)
 static void
 clutter_stage_x11_init (ClutterStageX11 *stage)
 {
+  const char *scale_str;
+
   stage->xwin = None;
   stage->xwin_width = 640;
   stage->xwin_height = 480;
@@ -868,6 +901,20 @@ clutter_stage_x11_init (ClutterStageX11 *stage)
   stage->accept_focus = TRUE;
 
   stage->title = NULL;
+
+  scale_str = g_getenv ("CLUTTER_SCALE");
+  if (scale_str != NULL)
+    {
+      CLUTTER_NOTE (BACKEND, "Scale factor set using environment variable: %d ('%s')",
+                    atol (scale_str),
+                    scale_str);
+      stage->fixed_scale_factor = TRUE;
+      stage->scale_factor = atol (scale_str);
+      stage->xwin_width *= stage->scale_factor;
+      stage->xwin_height *= stage->scale_factor;
+    }
+  else
+    stage->scale_factor = 1;
 }
 
 static void
@@ -887,6 +934,8 @@ clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
   iface->realize = clutter_stage_x11_realize;
   iface->unrealize = clutter_stage_x11_unrealize;
   iface->can_clip_redraws = clutter_stage_x11_can_clip_redraws;
+  iface->set_scale_factor = clutter_stage_x11_set_scale_factor;
+  iface->get_scale_factor = clutter_stage_x11_get_scale_factor;
 }
 
 static inline void
@@ -1008,8 +1057,8 @@ clutter_stage_x11_translate_event (ClutterEventTranslator *translator,
             }
 
           clutter_actor_set_size (CLUTTER_ACTOR (stage),
-                                  xevent->xconfigure.width,
-                                  xevent->xconfigure.height);
+                                  xevent->xconfigure.width / stage_x11->scale_factor,
+                                  xevent->xconfigure.height / stage_x11->scale_factor);
 
           CLUTTER_UNSET_PRIVATE_FLAGS (stage_cogl->wrapper, CLUTTER_IN_RESIZE);
 
@@ -1181,10 +1230,10 @@ clutter_stage_x11_translate_event (ClutterEventTranslator *translator,
                       expose->width,
                       expose->height);
 
-        clip.x = expose->x;
-        clip.y = expose->y;
-        clip.width = expose->width;
-        clip.height = expose->height;
+        clip.x = expose->x / stage_x11->scale_factor;
+        clip.y = expose->y / stage_x11->scale_factor;
+        clip.width = expose->width / stage_x11->scale_factor;
+        clip.height = expose->height / stage_x11->scale_factor;
         clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &clip);
       }
       break;
@@ -1350,8 +1399,8 @@ set_foreign_window_callback (ClutterActor *actor,
   fwd->stage_x11->xwin = fwd->xwindow;
   fwd->stage_x11->is_foreign_xwin = TRUE;
 
-  fwd->stage_x11->xwin_width = fwd->geom.width;
-  fwd->stage_x11->xwin_height = fwd->geom.height;
+  fwd->stage_x11->xwin_width = fwd->geom.width * fwd->stage_x11->scale_factor;
+  fwd->stage_x11->xwin_height = fwd->geom.height * fwd->stage_x11->scale_factor;
 
   clutter_actor_set_size (actor, fwd->geom.width, fwd->geom.height);
 
@@ -1451,8 +1500,8 @@ clutter_x11_set_stage_foreign (ClutterStage *stage,
 
   fwd.geom.x = x;
   fwd.geom.y = y;
-  fwd.geom.width = width;
-  fwd.geom.height = height;
+  fwd.geom.width = width / stage_x11->scale_factor;
+  fwd.geom.height = height / stage_x11->scale_factor;
 
   actor = CLUTTER_ACTOR (stage);
 
diff --git a/clutter/x11/clutter-stage-x11.h b/clutter/x11/clutter-stage-x11.h
index 8b61056..feaacf9 100644
--- a/clutter/x11/clutter-stage-x11.h
+++ b/clutter/x11/clutter-stage-x11.h
@@ -61,6 +61,8 @@ struct _ClutterStageX11
 
   ClutterStageX11State wm_state;
 
+  int scale_factor;
+
   guint is_foreign_xwin       : 1;
   guint fullscreening         : 1;
   guint is_cursor_visible     : 1;
@@ -68,6 +70,7 @@ struct _ClutterStageX11
   guint accept_focus          : 1;
   guint fullscreen_on_realize : 1;
   guint cursor_hidden_xfixes  : 1;
+  guint fixed_scale_factor    : 1;
 };
 
 struct _ClutterStageX11Class



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]