mirror of
https://github.com/brl/mutter.git
synced 2024-11-12 17:27:03 -05:00
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
This commit is contained in:
parent
0d0cb13c8d
commit
75f81fee70
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
stage_cogl->onscreen = cogl_onscreen_new (backend->cogl_context,
|
||||
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;
|
||||
|
||||
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. */
|
||||
@ -822,6 +833,26 @@ clutter_stage_x11_can_clip_redraws (ClutterStageWindow *stage_window)
|
||||
return stage_x11->clipped_redraws_cool_off == 0;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user