forked from 12to11/12to11
Improve handling buffer scale factors
* compositor.h (struct _DrawParams): New structure. (struct _RenderFuncs): Remove `apply_transform' and `reset_transform'. Make `composite' accept DrawParams. (struct _BufferFuncs): Give scale to update_buffer_for_damage. (struct _Surface): New field `factor'. (struct _RoleFuncs): New callback `parent_rescale'. * dnd.c (HandleMotion): Fix some aspects of scale handling. * egl.c (struct _EglBuffer): Remove `scale' field. (ApplyTransform): Delete function. (Composite): Pass scale specified in params as uniform to program. (ResetTransform): Delete function. (egl_render_funcs): Delete apply_transform and reset_transform. (BufferFromDmaBuf, BufferFromShm): Stop setting scale attribute. (UpdateBufferForDamage): Accept new arg `scale' and use it. * picture_renderer.c (struct _PictureBuffer): New structure. Store picture and last seen draw parameters. (ApplyTransform): Delete function. (GetScale): New function. (MaybeApplyTransform): New function. (Composite): Recompute and set pictures if draw parameters change. (ResetTransform): Delete function. (picture_render_funcs): Remove unused hooks. (BufferFromDmaBuf, FinishDmaBufRecord, BufferFromShm) (FreeShmBuffer, FreeDmabufBuffer): Replace xid with wrapper structure. * positioner.c (TryFlipX, TryFlipY, GetAdjustmentOffset) (ApplyConstraintAdjustment): * renderer.c (RenderApplyTransform, RenderComposite) (RenderResetTransform, RenderFinishRender) (RenderUpdateBufferForDamage): * seat.c (UpdateCursorOutput, ComputeHotspot, HandleRawButton) (TransformToView, DispatchEntryExit, DispatchMotion, CancelGrab) (DispatchButton, ForceEntry): * subcompositor.c (GetTxTy, ViewApplyTransform, ViewHaveTransform) (ViewComputeTransform, SubcompositorUpdate, SubcompositorExpose): * subsurface.c (MaybeUpdateOutputs, AfterParentCommit, Rescale) (Teardown, GetSubsurface, XLUpdateOutputsForChildren): Use surface-specific scale factors. * surface.c (ApplyScale): Compute a new scale factor to convert between window and surface scale. (ApplyOpaqueRegion, ApplyInputRegion, HandleScaleChanged) (ApplySurfaceDamage, InternalCommit, XLCreateSurface): Use new factors instead. * xdg_popup.c (MoveWindow): * xdg_surface.c (GetResizeDimensions, XLXdgRoleCalcNewWindowSize): * xdg_toplevel.c (NoteConfigureTime, SendStates, RecordStateSize) (HandleWindowGeometryChange, NoteWindowPreResize): Use surface-specific scale factors.
This commit is contained in:
parent
0f07b2205b
commit
7f33ba9ae3
13 changed files with 443 additions and 235 deletions
47
compositor.h
47
compositor.h
|
@ -103,6 +103,8 @@ typedef union _RenderTarget RenderTarget;
|
|||
typedef union _RenderBuffer RenderBuffer;
|
||||
typedef union _RenderFence RenderFence;
|
||||
|
||||
typedef struct _DrawParams DrawParams;
|
||||
|
||||
typedef struct _DmaBufAttributes DmaBufAttributes;
|
||||
typedef struct _SharedMemoryAttributes SharedMemoryAttributes;
|
||||
|
||||
|
@ -120,6 +122,21 @@ enum _Operation
|
|||
OperationSource,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
/* Scale has been set. */
|
||||
ScaleSet = 1,
|
||||
};
|
||||
|
||||
struct _DrawParams
|
||||
{
|
||||
/* Which fields are set. */
|
||||
int flags;
|
||||
|
||||
/* A scale factor to apply to the buffer. */
|
||||
double scale;
|
||||
};
|
||||
|
||||
struct _SharedMemoryAttributes
|
||||
{
|
||||
/* The format of the buffer. */
|
||||
|
@ -241,18 +258,12 @@ struct _RenderFuncs
|
|||
/* Clear the given rectangle. */
|
||||
void (*clear_rectangle) (RenderTarget, int, int, int, int);
|
||||
|
||||
/* Apply a projective transform to the given buffer. The first
|
||||
argument is a scale factor. */
|
||||
void (*apply_transform) (RenderBuffer, double);
|
||||
|
||||
/* Composite width, height, from the given buffer onto the given
|
||||
target, at x, y. The arguments are: buffer, target, operation,
|
||||
source_x, source_y, x, y, width, height. */
|
||||
source_x, source_y, x, y, width, height, params. params
|
||||
describes how to transform the given buffer. */
|
||||
void (*composite) (RenderBuffer, RenderTarget, Operation, int, int,
|
||||
int, int, int, int);
|
||||
|
||||
/* Reset the transform for the given buffer. */
|
||||
void (*reset_transform) (RenderBuffer);
|
||||
int, int, int, int, DrawParams *);
|
||||
|
||||
/* Finish rendering, and swap changes to display. May be NULL. */
|
||||
void (*finish_render) (RenderTarget);
|
||||
|
@ -349,8 +360,10 @@ struct _BufferFuncs
|
|||
/* Notice that the given buffer has been damaged. May be NULL. If
|
||||
the given NULL damage, assume that the entire buffer has been
|
||||
damaged. Must be called at least once before any rendering can
|
||||
be performed on the buffer. */
|
||||
void (*update_buffer_for_damage) (RenderBuffer, pixman_region32_t *);
|
||||
be performed on the buffer. 3rd arg is the scale by which to
|
||||
divide the buffer. */
|
||||
void (*update_buffer_for_damage) (RenderBuffer, pixman_region32_t *,
|
||||
float);
|
||||
|
||||
/* Return whether or not the buffer contents can be released early,
|
||||
by being copied to an offscreen buffer. */
|
||||
|
@ -376,10 +389,8 @@ extern void RenderStartRender (RenderTarget);
|
|||
extern void RenderFillBoxesWithTransparency (RenderTarget, pixman_box32_t *,
|
||||
int, int, int);
|
||||
extern void RenderClearRectangle (RenderTarget, int, int, int, int);
|
||||
extern void RenderApplyTransform (RenderBuffer, double);
|
||||
extern void RenderComposite (RenderBuffer, RenderTarget, Operation, int,
|
||||
int, int, int, int, int);
|
||||
extern void RenderResetTransform (RenderBuffer);
|
||||
int, int, int, int, int, DrawParams *);
|
||||
extern void RenderFinishRender (RenderTarget);
|
||||
extern int RenderTargetAge (RenderTarget);
|
||||
extern RenderFence RenderImportFdFence (int, Bool *);
|
||||
|
@ -398,7 +409,8 @@ extern Bool RenderValidateShmParams (uint32_t, uint32_t, uint32_t, int32_t,
|
|||
int32_t, size_t);
|
||||
extern void RenderFreeShmBuffer (RenderBuffer);
|
||||
extern void RenderFreeDmabufBuffer (RenderBuffer);
|
||||
extern void RenderUpdateBufferForDamage (RenderBuffer, pixman_region32_t *);
|
||||
extern void RenderUpdateBufferForDamage (RenderBuffer, pixman_region32_t *,
|
||||
float);
|
||||
extern Bool RenderCanReleaseNow (RenderBuffer);
|
||||
|
||||
/* Defined in run.c. */
|
||||
|
@ -832,6 +844,10 @@ struct _Surface
|
|||
|
||||
/* The associated sync acquire fd, or -1. */
|
||||
int acquire_fence;
|
||||
|
||||
/* The scale factor used to convert from surface coordinates to
|
||||
window coordinates. */
|
||||
double factor;
|
||||
};
|
||||
|
||||
struct _RoleFuncs
|
||||
|
@ -851,6 +867,7 @@ struct _RoleFuncs
|
|||
void (*post_resize) (Surface *, Role *, int, int, int, int);
|
||||
void (*move_by) (Surface *, Role *, int, int);
|
||||
void (*rescale) (Surface *, Role *);
|
||||
void (*parent_rescale) (Surface *, Role *);
|
||||
void (*note_desync_child) (Surface *, Role *);
|
||||
void (*note_child_synced) (Surface *, Role *);
|
||||
};
|
||||
|
|
17
dnd.c
17
dnd.c
|
@ -885,11 +885,24 @@ HandleMotion (Surface *toplevel, int x, int y, uint32_t action,
|
|||
/* Find the view underneath the subcompositor. */
|
||||
view = SubcompositorLookupView (subcompositor, x, y,
|
||||
&x_off, &y_off);
|
||||
|
||||
if (view)
|
||||
child = ViewGetData (view);
|
||||
else
|
||||
/* No child was found. This should be impossible in theory, but
|
||||
other clients don't respect the window shape when sending DND
|
||||
events. */
|
||||
child = NULL;
|
||||
|
||||
/* Compute the surface-relative coordinates and scale them. */
|
||||
*x_out = (x - x_off) / global_scale_factor;
|
||||
*y_out = (y - y_off) / global_scale_factor;
|
||||
|
||||
if (child)
|
||||
{
|
||||
/* x_out and y_out are only used if dnd_state.child ends up
|
||||
non-NULL. */
|
||||
*x_out = (x - x_off) / child->factor;
|
||||
*y_out = (y - y_off) / child->factor;
|
||||
}
|
||||
|
||||
if (dnd_state.child == child)
|
||||
/* If nothing changed, don't do anything. */
|
||||
|
|
45
egl.c
45
egl.c
|
@ -126,9 +126,6 @@ struct _EglBuffer
|
|||
/* The width and height of the buffer. */
|
||||
int width, height;
|
||||
|
||||
/* The projective scale factor. */
|
||||
GLfloat scale;
|
||||
|
||||
/* Various different buffers. */
|
||||
union {
|
||||
/* The type of the buffer. */
|
||||
|
@ -1128,15 +1125,6 @@ ClearRectangle (RenderTarget target, int x, int y, int width, int height)
|
|||
FillBoxesWithTransparency (target, &box, 1, 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
ApplyTransform (RenderBuffer buffer, double divisor)
|
||||
{
|
||||
EglBuffer *egl_buffer;
|
||||
|
||||
egl_buffer = buffer.pointer;
|
||||
egl_buffer->scale = 1.0f / (GLfloat) divisor;
|
||||
}
|
||||
|
||||
static CompositeProgram *
|
||||
FindProgram (EglBuffer *buffer)
|
||||
{
|
||||
|
@ -1177,7 +1165,7 @@ GetTextureTarget (EglBuffer *buffer)
|
|||
static void
|
||||
Composite (RenderBuffer buffer, RenderTarget target,
|
||||
Operation op, int src_x, int src_y, int x, int y,
|
||||
int width, int height)
|
||||
int width, int height, DrawParams *params)
|
||||
{
|
||||
GLfloat verts[8], texcoord[8];
|
||||
GLfloat x1, x2, y1, y2;
|
||||
|
@ -1185,6 +1173,7 @@ Composite (RenderBuffer buffer, RenderTarget target,
|
|||
EglBuffer *egl_buffer;
|
||||
CompositeProgram *program;
|
||||
GLenum tex_target;
|
||||
GLfloat scale;
|
||||
|
||||
egl_target = target.pointer;
|
||||
egl_buffer = buffer.pointer;
|
||||
|
@ -1244,13 +1233,18 @@ Composite (RenderBuffer buffer, RenderTarget target,
|
|||
else
|
||||
glDisable (GL_BLEND);
|
||||
|
||||
if (params->flags & ScaleSet)
|
||||
scale = params->scale;
|
||||
else
|
||||
scale = 1.0f;
|
||||
|
||||
glActiveTexture (GL_TEXTURE0);
|
||||
glBindTexture (tex_target, egl_buffer->texture);
|
||||
glTexParameteri (tex_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glUseProgram (program->program);
|
||||
|
||||
glUniform1i (program->texture, 0);
|
||||
glUniform1f (program->scale, egl_buffer->scale);
|
||||
glUniform1f (program->scale, scale);
|
||||
glUniform1i (program->invert_y, egl_buffer->flags & InvertY);
|
||||
glVertexAttribPointer (program->position, 2, GL_FLOAT,
|
||||
GL_FALSE, 0, verts);
|
||||
|
@ -1268,12 +1262,6 @@ Composite (RenderBuffer buffer, RenderTarget target,
|
|||
glBindTexture (tex_target, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
ResetTransform (RenderBuffer buffer)
|
||||
{
|
||||
/* TODO... */
|
||||
}
|
||||
|
||||
static void
|
||||
FinishRender (RenderTarget target)
|
||||
{
|
||||
|
@ -1421,9 +1409,7 @@ static RenderFuncs egl_render_funcs =
|
|||
.start_render = StartRender,
|
||||
.fill_boxes_with_transparency = FillBoxesWithTransparency,
|
||||
.clear_rectangle = ClearRectangle,
|
||||
.apply_transform = ApplyTransform,
|
||||
.composite = Composite,
|
||||
.reset_transform = ResetTransform,
|
||||
.finish_render = FinishRender,
|
||||
.target_age = TargetAge,
|
||||
.import_fd_fence = ImportFdFence,
|
||||
|
@ -1514,7 +1500,6 @@ BufferFromDmaBuf (DmaBufAttributes *attributes, Bool *error)
|
|||
buffer->texture = EGL_NO_TEXTURE;
|
||||
buffer->width = attributes->width;
|
||||
buffer->height = attributes->height;
|
||||
buffer->scale = 1.0f;
|
||||
buffer->u.type = DmaBufBuffer;
|
||||
i = 0;
|
||||
|
||||
|
@ -1664,7 +1649,6 @@ BufferFromShm (SharedMemoryAttributes *attributes, Bool *error)
|
|||
buffer->texture = EGL_NO_TEXTURE;
|
||||
buffer->width = attributes->width;
|
||||
buffer->height = attributes->height;
|
||||
buffer->scale = 1.0f;
|
||||
buffer->u.type = ShmBuffer;
|
||||
|
||||
/* Record the buffer data. */
|
||||
|
@ -2134,22 +2118,19 @@ UpdateBuffer (RenderBuffer buffer, pixman_region32_t *damage)
|
|||
}
|
||||
|
||||
static void
|
||||
UpdateBufferForDamage (RenderBuffer buffer, pixman_region32_t *damage)
|
||||
UpdateBufferForDamage (RenderBuffer buffer, pixman_region32_t *damage,
|
||||
float scale)
|
||||
{
|
||||
EglBuffer *egl_buffer;
|
||||
pixman_region32_t region;
|
||||
|
||||
egl_buffer = buffer.pointer;
|
||||
|
||||
if (egl_buffer->scale != 1.0f && damage)
|
||||
if (scale != 1.0f && damage)
|
||||
{
|
||||
/* Scale the damage, specified in scaled coordinates, down to
|
||||
texture coordinates. */
|
||||
|
||||
pixman_region32_init (®ion);
|
||||
XLScaleRegion (®ion, damage,
|
||||
1.0f / egl_buffer->scale,
|
||||
1.0f / egl_buffer->scale);
|
||||
XLScaleRegion (®ion, damage, 1.0f / scale,
|
||||
1.0f / scale);
|
||||
UpdateBuffer (buffer, ®ion);
|
||||
pixman_region32_fini (®ion);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,17 @@ along with 12to11. If not, see <https://www.gnu.org/licenses/>. */
|
|||
typedef struct _DrmFormatInfo DrmFormatInfo;
|
||||
typedef struct _DmaBufRecord DmaBufRecord;
|
||||
|
||||
typedef struct _PictureBuffer PictureBuffer;
|
||||
|
||||
struct _PictureBuffer
|
||||
{
|
||||
/* The XID of the picture. */
|
||||
Picture picture;
|
||||
|
||||
/* The last draw params associated with the picture. */
|
||||
DrawParams params;
|
||||
};
|
||||
|
||||
struct _DrmFormatInfo
|
||||
{
|
||||
/* The DRM format code. */
|
||||
|
@ -290,21 +301,6 @@ ClearRectangle (RenderTarget target, int x, int y, int width, int height)
|
|||
target.xid, &color, x, y, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
ApplyTransform (RenderBuffer buffer, double divisor)
|
||||
{
|
||||
XTransform transform;
|
||||
|
||||
memset (&transform, 0, sizeof transform);
|
||||
|
||||
transform.matrix[0][0] = XDoubleToFixed (divisor);
|
||||
transform.matrix[1][1] = XDoubleToFixed (divisor);
|
||||
transform.matrix[2][2] = XDoubleToFixed (1);
|
||||
|
||||
XRenderSetPictureTransform (compositor.display, buffer.xid,
|
||||
&transform);
|
||||
}
|
||||
|
||||
static int
|
||||
ConvertOperation (Operation op)
|
||||
{
|
||||
|
@ -320,26 +316,70 @@ ConvertOperation (Operation op)
|
|||
abort ();
|
||||
}
|
||||
|
||||
static double
|
||||
GetScale (DrawParams *params)
|
||||
{
|
||||
if (params->flags & ScaleSet)
|
||||
return params->scale;
|
||||
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
static void
|
||||
MaybeApplyTransform (PictureBuffer *buffer, DrawParams *params)
|
||||
{
|
||||
XTransform transform;
|
||||
|
||||
if (GetScale (params) == GetScale (&buffer->params))
|
||||
/* Nothing changed. */
|
||||
return;
|
||||
|
||||
/* Otherwise, compute and apply the new transform. */
|
||||
if (!params->flags)
|
||||
/* No transform of any kind is set, use the identity matrix. */
|
||||
XRenderSetPictureTransform (compositor.display,
|
||||
buffer->picture,
|
||||
&identity_transform);
|
||||
else
|
||||
{
|
||||
memset (&transform, 0, sizeof transform);
|
||||
|
||||
transform.matrix[0][0] = XDoubleToFixed (1.0 / params->scale);
|
||||
transform.matrix[1][1] = XDoubleToFixed (1.0 / params->scale);
|
||||
transform.matrix[2][2] = XDoubleToFixed (1);
|
||||
|
||||
XRenderSetPictureTransform (compositor.display,
|
||||
buffer->picture,
|
||||
&transform);
|
||||
}
|
||||
|
||||
/* Save the parameters into buffer. */
|
||||
buffer->params = *params;
|
||||
}
|
||||
|
||||
static void
|
||||
Composite (RenderBuffer buffer, RenderTarget target,
|
||||
Operation op, int src_x, int src_y, int x, int y,
|
||||
int width, int height)
|
||||
int width, int height, DrawParams *draw_params)
|
||||
{
|
||||
PictureBuffer *picture_buffer;
|
||||
|
||||
picture_buffer = buffer.pointer;
|
||||
|
||||
/* Maybe set the transform if the parameters changed. (draw_params
|
||||
specifies a transform to apply to the buffer, not to the
|
||||
target.) */
|
||||
MaybeApplyTransform (picture_buffer, draw_params);
|
||||
|
||||
/* Do the compositing. */
|
||||
XRenderComposite (compositor.display, ConvertOperation (op),
|
||||
buffer.xid, None, target.xid,
|
||||
picture_buffer->picture, None, target.xid,
|
||||
/* src-x, src-y, mask-x, mask-y. */
|
||||
src_x, src_y, 0, 0,
|
||||
/* dst-x, dst-y, width, height. */
|
||||
x, y, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
ResetTransform (RenderBuffer buffer)
|
||||
{
|
||||
XRenderSetPictureTransform (compositor.display, buffer.xid,
|
||||
&identity_transform);
|
||||
}
|
||||
|
||||
static int
|
||||
TargetAge (RenderTarget target)
|
||||
{
|
||||
|
@ -388,9 +428,7 @@ static RenderFuncs picture_render_funcs =
|
|||
.destroy_render_target = DestroyRenderTarget,
|
||||
.fill_boxes_with_transparency = FillBoxesWithTransparency,
|
||||
.clear_rectangle = ClearRectangle,
|
||||
.apply_transform = ApplyTransform,
|
||||
.composite = Composite,
|
||||
.reset_transform = ResetTransform,
|
||||
.target_age = TargetAge,
|
||||
.import_fd_fence = ImportFdFence,
|
||||
.wait_fence = WaitFence,
|
||||
|
@ -746,6 +784,7 @@ BufferFromDmaBuf (DmaBufAttributes *attributes, Bool *error)
|
|||
xcb_generic_error_t *xerror;
|
||||
XRenderPictFormat *format;
|
||||
XRenderPictureAttributes picture_attrs;
|
||||
PictureBuffer *buffer;
|
||||
|
||||
/* Find the depth and bpp corresponding to the format. */
|
||||
depth = DepthForDmabufFormat (attributes->drm_format, &bpp);
|
||||
|
@ -791,12 +830,16 @@ BufferFromDmaBuf (DmaBufAttributes *attributes, Bool *error)
|
|||
format, 0, &picture_attrs);
|
||||
XFreePixmap (compositor.display, pixmap);
|
||||
|
||||
return (RenderBuffer) picture;
|
||||
/* Create the wrapper object. */
|
||||
buffer = XLCalloc (1, sizeof *buffer);
|
||||
buffer->picture = picture;
|
||||
|
||||
return (RenderBuffer) (void *) buffer;
|
||||
|
||||
error:
|
||||
CloseFileDescriptors (attributes);
|
||||
*error = True;
|
||||
return (RenderBuffer) (XID) None;
|
||||
return (RenderBuffer) NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -832,6 +875,7 @@ FinishDmaBufRecord (DmaBufRecord *pending, Bool success)
|
|||
{
|
||||
Picture picture;
|
||||
XRenderPictureAttributes picture_attrs;
|
||||
PictureBuffer *buffer;
|
||||
|
||||
if (success)
|
||||
{
|
||||
|
@ -844,8 +888,12 @@ FinishDmaBufRecord (DmaBufRecord *pending, Bool success)
|
|||
&picture_attrs);
|
||||
XFreePixmap (compositor.display, pending->pixmap);
|
||||
|
||||
/* Create the wrapper structure. */
|
||||
buffer = XLCalloc (1, sizeof *buffer);
|
||||
buffer->picture = picture;
|
||||
|
||||
/* Call the creation success function with the new picture. */
|
||||
pending->success_func ((RenderBuffer) picture,
|
||||
pending->success_func ((RenderBuffer) (void *) buffer,
|
||||
pending->data);
|
||||
}
|
||||
else
|
||||
|
@ -989,6 +1037,7 @@ BufferFromShm (SharedMemoryAttributes *attributes, Bool *error)
|
|||
Pixmap pixmap;
|
||||
Picture picture;
|
||||
int fd, depth, format, bpp;
|
||||
PictureBuffer *buffer;
|
||||
|
||||
depth = DepthForFormat (attributes->format, &bpp);
|
||||
format = attributes->format;
|
||||
|
@ -1000,7 +1049,7 @@ BufferFromShm (SharedMemoryAttributes *attributes, Bool *error)
|
|||
if (fd < 0)
|
||||
{
|
||||
*error = True;
|
||||
return (RenderBuffer) (XID) None;
|
||||
return (RenderBuffer) NULL;
|
||||
}
|
||||
|
||||
/* Now, allocate the XIDs for the shm segment and pixmap. */
|
||||
|
@ -1021,8 +1070,12 @@ BufferFromShm (SharedMemoryAttributes *attributes, Bool *error)
|
|||
0, &picture_attrs);
|
||||
XFreePixmap (compositor.display, pixmap);
|
||||
|
||||
/* Create the wrapper object. */
|
||||
buffer = XLCalloc (1, sizeof *buffer);
|
||||
buffer->picture = picture;
|
||||
|
||||
/* Return the picture. */
|
||||
return (RenderBuffer) picture;
|
||||
return (RenderBuffer) (void *) buffer;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1086,15 +1139,27 @@ ValidateShmParams (uint32_t format, uint32_t width, uint32_t height,
|
|||
static void
|
||||
FreeShmBuffer (RenderBuffer buffer)
|
||||
{
|
||||
XRenderFreePicture (compositor.display, buffer.xid);
|
||||
PictureBuffer *picture_buffer;
|
||||
|
||||
picture_buffer = buffer.pointer;
|
||||
|
||||
XRenderFreePicture (compositor.display,
|
||||
picture_buffer->picture);
|
||||
XLFree (picture_buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
FreeDmabufBuffer (RenderBuffer buffer)
|
||||
{
|
||||
PictureBuffer *picture_buffer;
|
||||
|
||||
picture_buffer = buffer.pointer;
|
||||
|
||||
/* N.B. that the picture is the only reference to the pixmap
|
||||
here. */
|
||||
XRenderFreePicture (compositor.display, buffer.xid);
|
||||
XRenderFreePicture (compositor.display,
|
||||
picture_buffer->picture);
|
||||
XLFree (picture_buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
31
positioner.c
31
positioner.c
|
@ -60,6 +60,9 @@ struct _Positioner
|
|||
int refcount;
|
||||
};
|
||||
|
||||
/* Scale factor used during constraint adjustment calculation. */
|
||||
static double scale_adjustment_factor;
|
||||
|
||||
static void
|
||||
Destroy (struct wl_client *client, struct wl_resource *resource)
|
||||
{
|
||||
|
@ -502,7 +505,7 @@ TryFlipX (Positioner *positioner, int x, int width, int cx, int cwidth,
|
|||
CalculatePosition (&new, &new_x, NULL);
|
||||
|
||||
/* Scale that position. */
|
||||
new_x *= global_scale_factor;
|
||||
new_x *= scale_adjustment_factor;
|
||||
|
||||
/* If new_x is still constrained, use the previous position. */
|
||||
if (new_x + offset < cx
|
||||
|
@ -598,7 +601,7 @@ TryFlipY (Positioner *positioner, int y, int height, int cy, int cheight,
|
|||
CalculatePosition (&new, NULL, &new_y);
|
||||
|
||||
/* Scale that position. */
|
||||
new_y *= global_scale_factor;
|
||||
new_y *= scale_adjustment_factor;
|
||||
|
||||
/* If new_y is still constrained, use the previous position. */
|
||||
if (new_y + offset < cy
|
||||
|
@ -670,8 +673,8 @@ GetAdjustmentOffset (Role *parent, int *off_x, int *off_y)
|
|||
&parent_gy, NULL, NULL);
|
||||
XLXdgRoleCurrentRootPosition (parent, &root_x, &root_y);
|
||||
|
||||
*off_x = root_x + parent_gx * global_scale_factor;
|
||||
*off_y = root_y + parent_gy * global_scale_factor;
|
||||
*off_x = root_x + parent_gx * parent->surface->factor;
|
||||
*off_y = root_y + parent_gy * parent->surface->factor;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -681,13 +684,17 @@ ApplyConstraintAdjustment (Positioner *positioner, Role *parent, int x,
|
|||
{
|
||||
int width, height, cx, cy, cwidth, cheight, off_x, off_y;
|
||||
|
||||
width = positioner->width * global_scale_factor;
|
||||
height = positioner->height * global_scale_factor;
|
||||
width = positioner->width * scale_adjustment_factor;
|
||||
height = positioner->height * scale_adjustment_factor;
|
||||
|
||||
/* Set the factor describing how to convert surface coordinates to
|
||||
window ones. */
|
||||
scale_adjustment_factor = parent->surface->factor;
|
||||
|
||||
/* Constraint calculations are simplest if we use scaled
|
||||
coordinates, and then unscale them later. */
|
||||
x *= global_scale_factor;
|
||||
y *= global_scale_factor;
|
||||
x *= scale_adjustment_factor;
|
||||
y *= scale_adjustment_factor;
|
||||
|
||||
if (positioner->constraint_adjustment
|
||||
== XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_NONE)
|
||||
|
@ -733,10 +740,10 @@ ApplyConstraintAdjustment (Positioner *positioner, Role *parent, int x,
|
|||
off_y, &y, &height);
|
||||
|
||||
finish:
|
||||
*x_out = x / global_scale_factor;
|
||||
*y_out = y / global_scale_factor;
|
||||
*width_out = width / global_scale_factor;
|
||||
*height_out = height / global_scale_factor;
|
||||
*x_out = x / scale_adjustment_factor;
|
||||
*y_out = y / scale_adjustment_factor;
|
||||
*width_out = width / scale_adjustment_factor;
|
||||
*height_out = height / scale_adjustment_factor;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
22
renderer.c
22
renderer.c
|
@ -129,24 +129,13 @@ RenderClearRectangle (RenderTarget target, int x, int y, int width, int height)
|
|||
render_funcs.clear_rectangle (target, x, y, width, height);
|
||||
}
|
||||
|
||||
void
|
||||
RenderApplyTransform (RenderBuffer buffer, double divisor)
|
||||
{
|
||||
render_funcs.apply_transform (buffer, divisor);
|
||||
}
|
||||
|
||||
void
|
||||
RenderComposite (RenderBuffer source, RenderTarget target, Operation op,
|
||||
int src_x, int src_y, int x, int y, int width, int height)
|
||||
int src_x, int src_y, int x, int y, int width, int height,
|
||||
DrawParams *draw_params)
|
||||
{
|
||||
render_funcs.composite (source, target, op, src_x, src_y, x, y,
|
||||
width, height);
|
||||
}
|
||||
|
||||
void
|
||||
RenderResetTransform (RenderBuffer buffer)
|
||||
{
|
||||
render_funcs.reset_transform (buffer);
|
||||
width, height, draw_params);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -251,12 +240,13 @@ RenderFreeDmabufBuffer (RenderBuffer buffer)
|
|||
}
|
||||
|
||||
void
|
||||
RenderUpdateBufferForDamage (RenderBuffer buffer, pixman_region32_t *damage)
|
||||
RenderUpdateBufferForDamage (RenderBuffer buffer, pixman_region32_t *damage,
|
||||
float scale)
|
||||
{
|
||||
if (!buffer_funcs.update_buffer_for_damage)
|
||||
return;
|
||||
|
||||
buffer_funcs.update_buffer_for_damage (buffer, damage);
|
||||
buffer_funcs.update_buffer_for_damage (buffer, damage, scale);
|
||||
}
|
||||
|
||||
Bool
|
||||
|
|
52
seat.c
52
seat.c
|
@ -779,9 +779,10 @@ UpdateCursorOutput (SeatCursor *cursor, int root_x, int root_y)
|
|||
{
|
||||
int hotspot_x, hotspot_y;
|
||||
|
||||
/* Scale the hotspot coordinates up by the scale. */
|
||||
hotspot_x = cursor->hotspot_x * global_scale_factor;
|
||||
hotspot_y = cursor->hotspot_y * global_scale_factor;
|
||||
/* Scale the hotspot coordinates up by the scale factor specified in
|
||||
the surface. */
|
||||
hotspot_x = cursor->hotspot_x * cursor->role.surface->factor;
|
||||
hotspot_y = cursor->hotspot_y * cursor->role.surface->factor;
|
||||
|
||||
/* We use a rectangle 1 pixel wide and tall, originating from the
|
||||
hotspot of the pointer. */
|
||||
|
@ -991,20 +992,18 @@ ComputeHotspot (SeatCursor *cursor, int min_x, int min_y,
|
|||
int dx, dy;
|
||||
int hotspot_x, hotspot_y;
|
||||
|
||||
if (!cursor->role.surface)
|
||||
return;
|
||||
|
||||
/* Scale the hotspot coordinates up by the scale. */
|
||||
hotspot_x = cursor->hotspot_x * global_scale_factor;
|
||||
hotspot_y = cursor->hotspot_y * global_scale_factor;
|
||||
hotspot_x = cursor->hotspot_x * cursor->role.surface->factor;
|
||||
hotspot_y = cursor->hotspot_y * cursor->role.surface->factor;
|
||||
|
||||
/* Apply the surface offsets to the hotspot as well. */
|
||||
dx = dy = 0;
|
||||
|
||||
if (cursor->role.surface)
|
||||
{
|
||||
dx = (cursor->role.surface->current_state.x
|
||||
* global_scale_factor);
|
||||
* cursor->role.surface->factor);
|
||||
dy = (cursor->role.surface->current_state.y
|
||||
* global_scale_factor);
|
||||
}
|
||||
* cursor->role.surface->factor);
|
||||
|
||||
*x = min_x + hotspot_x - dx;
|
||||
*y = min_y + hotspot_y - dy;
|
||||
|
@ -2369,7 +2368,7 @@ HandleResizeComplete (Seat *seat)
|
|||
/* Forward declarations. */
|
||||
|
||||
static int GetXButton (int);
|
||||
static void TransformToView (View *, double, double, double *, double *);
|
||||
static void TransformToSurface (Surface *, double, double, double *, double *);
|
||||
static void SendButton (Seat *, Surface *, Time, uint32_t, uint32_t,
|
||||
double, double);
|
||||
|
||||
|
@ -2421,7 +2420,7 @@ HandleRawButton (XIRawEvent *event)
|
|||
{
|
||||
/* Otherwise, the pointer is on a different screen! */
|
||||
|
||||
TransformToView (seat->last_seen_surface->view,
|
||||
TransformToSurface (seat->last_seen_surface,
|
||||
win_x, win_y, &dispatch_x, &dispatch_y);
|
||||
SendButton (seat, seat->last_seen_surface, event->time,
|
||||
button, WL_POINTER_BUTTON_STATE_RELEASED,
|
||||
|
@ -3258,11 +3257,15 @@ EnteredSurface (Seat *seat, Surface *surface, Time time,
|
|||
}
|
||||
|
||||
static void
|
||||
TransformToView (View *view, double event_x, double event_y,
|
||||
TransformToSurface (Surface *surface, double event_x, double event_y,
|
||||
double *view_x_out, double *view_y_out)
|
||||
{
|
||||
int int_x, int_y, x, y;
|
||||
double view_x, view_y;
|
||||
View *view;
|
||||
|
||||
/* Use the surface's view. */
|
||||
view = surface->view;
|
||||
|
||||
/* Even though event_x and event_y are doubles, they cannot exceed
|
||||
65535.0, so this cannot overflow. */
|
||||
|
@ -3277,8 +3280,8 @@ TransformToView (View *view, double event_x, double event_y,
|
|||
|
||||
/* Finally, transform the coordinates by the global output
|
||||
scale. */
|
||||
*view_x_out = view_x / global_scale_factor;
|
||||
*view_y_out = view_y / global_scale_factor;
|
||||
*view_x_out = view_x / surface->factor;
|
||||
*view_y_out = view_y / surface->factor;
|
||||
}
|
||||
|
||||
static Bool
|
||||
|
@ -3411,9 +3414,7 @@ DispatchEntryExit (Subcompositor *subcompositor, XIEnterEvent *event)
|
|||
|
||||
after_dispatch_set:
|
||||
|
||||
TransformToView (dispatch->view, event_x,
|
||||
event_y, &x, &y);
|
||||
|
||||
TransformToSurface (dispatch, event_x, event_y, &x, &y);
|
||||
EnteredSurface (seat, dispatch, event->time, x, y, False);
|
||||
}
|
||||
|
||||
|
@ -3688,8 +3689,7 @@ DispatchMotion (Subcompositor *subcompositor, XIDeviceEvent *xev)
|
|||
/* Inside a surface; cancel external drag and drop. */
|
||||
XLDoDragLeave (seat);
|
||||
|
||||
TransformToView (dispatch->view, event_x, event_y,
|
||||
&x, &y);
|
||||
TransformToSurface (dispatch, event_x, event_y, &x, &y);
|
||||
EnteredSurface (seat, dispatch, xev->time, x, y, False);
|
||||
|
||||
if (!HandleValuatorMotion (seat, dispatch, x, y, xev))
|
||||
|
@ -3753,7 +3753,7 @@ CancelGrab (Seat *seat, Time time, Window source,
|
|||
|
||||
/* Finally, translate the coordinates to the target
|
||||
view. */
|
||||
TransformToView (seat->pointer_unlock_surface->view,
|
||||
TransformToSurface (seat->pointer_unlock_surface,
|
||||
x, y, &x, &y);
|
||||
}
|
||||
}
|
||||
|
@ -3925,8 +3925,8 @@ DispatchButton (Subcompositor *subcompositor, XIDeviceEvent *xev)
|
|||
|
||||
after_dispatch_set:
|
||||
|
||||
TransformToView (dispatch->view, xev->event_x,
|
||||
xev->event_y, &x, &y);
|
||||
TransformToSurface (dispatch, xev->event_x, xev->event_y,
|
||||
&x, &y);
|
||||
EnteredSurface (seat, dispatch, xev->time, x, y,
|
||||
False);
|
||||
|
||||
|
@ -4891,7 +4891,7 @@ ForceEntry (Seat *seat, Window source, double x, double y)
|
|||
|
||||
/* Finally, translate the coordinates to the target
|
||||
view. */
|
||||
TransformToView (surface->view, x, y, &x, &y);
|
||||
TransformToSurface (surface, x, y, &x, &y);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -1582,30 +1582,26 @@ ViewSetScale (View *view, int scale)
|
|||
}
|
||||
|
||||
static double
|
||||
GetTxTy (int scale)
|
||||
GetContentScale (int scale)
|
||||
{
|
||||
if (scale > 0)
|
||||
return scale + 1;
|
||||
return 1.0 / (scale + 1);
|
||||
|
||||
return 1.0 / (-scale + 1);
|
||||
return -scale + 1;
|
||||
}
|
||||
|
||||
static void
|
||||
ViewApplyTransform (View *view, RenderBuffer buffer)
|
||||
ViewComputeTransform (View *view, DrawParams *params)
|
||||
{
|
||||
RenderApplyTransform (buffer, GetTxTy (view->scale));
|
||||
/* First, there is no transform. */
|
||||
params->flags = 0;
|
||||
|
||||
if (view->scale)
|
||||
{
|
||||
/* There is a scale, so set it. */
|
||||
params->flags |= ScaleSet;
|
||||
params->scale = GetContentScale (view->scale);
|
||||
}
|
||||
|
||||
/* TODO: the callers of this can be optimized by setting the picture
|
||||
transform on the attached buffer if that buffer is not attached to
|
||||
any other view. */
|
||||
|
||||
static Bool
|
||||
ViewHaveTransform (View *view)
|
||||
{
|
||||
/* view->scale is the amount by which to scale _down_ the view. If
|
||||
it is 0, then no scaling will be performed. */
|
||||
return view->scale;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1763,6 +1759,7 @@ SubcompositorUpdate (Subcompositor *subcompositor)
|
|||
RenderBuffer buffer;
|
||||
int min_x, min_y;
|
||||
int age;
|
||||
DrawParams draw_params;
|
||||
|
||||
/* Just return if no target was specified. */
|
||||
if (!IsTargetAttached (subcompositor))
|
||||
|
@ -1946,7 +1943,8 @@ SubcompositorUpdate (Subcompositor *subcompositor)
|
|||
when the damage region is empty. */
|
||||
|
||||
buffer = XLRenderBufferFromBuffer (view->buffer);
|
||||
RenderUpdateBufferForDamage (buffer, &list->view->damage);
|
||||
RenderUpdateBufferForDamage (buffer, &list->view->damage,
|
||||
GetContentScale (list->view->scale));
|
||||
|
||||
if (pixman_region32_not_empty (&list->view->damage))
|
||||
{
|
||||
|
@ -2115,11 +2113,12 @@ SubcompositorUpdate (Subcompositor *subcompositor)
|
|||
|
||||
Note that if the subcompositor is not garbaged, then this
|
||||
has already been done. */
|
||||
RenderUpdateBufferForDamage (buffer, NULL);
|
||||
RenderUpdateBufferForDamage (buffer, NULL, 0.0f);
|
||||
else if (age < 0 || age > 3)
|
||||
/* The target contents are too old, but the damage can be
|
||||
trusted. */
|
||||
RenderUpdateBufferForDamage (buffer, &view->damage);
|
||||
RenderUpdateBufferForDamage (buffer, &view->damage,
|
||||
GetContentScale (list->view->scale));
|
||||
|
||||
if (!first)
|
||||
{
|
||||
|
@ -2174,8 +2173,8 @@ SubcompositorUpdate (Subcompositor *subcompositor)
|
|||
|
||||
first = view;
|
||||
|
||||
if (ViewHaveTransform (view))
|
||||
ViewApplyTransform (view, buffer);
|
||||
/* Compute the transform and put it in draw_params. */
|
||||
ViewComputeTransform (view, &draw_params);
|
||||
|
||||
if (!IsGarbaged (subcompositor) && (age >= 0 && age < 3))
|
||||
{
|
||||
|
@ -2206,8 +2205,8 @@ SubcompositorUpdate (Subcompositor *subcompositor)
|
|||
BoxStartY (temp_boxes) - min_y + ty,
|
||||
/* width. */
|
||||
BoxWidth (temp_boxes),
|
||||
/* height. */
|
||||
BoxHeight (temp_boxes));
|
||||
/* height, draw-params. */
|
||||
BoxHeight (temp_boxes), &draw_params);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2228,8 +2227,8 @@ SubcompositorUpdate (Subcompositor *subcompositor)
|
|||
view->abs_y - min_y + ty,
|
||||
/* width. */
|
||||
ViewWidth (view),
|
||||
/* height. */
|
||||
ViewHeight (view));
|
||||
/* height, draw-params. */
|
||||
ViewHeight (view), &draw_params);
|
||||
|
||||
/* Also adjust the opaque and input regions here. */
|
||||
|
||||
|
@ -2282,9 +2281,6 @@ SubcompositorUpdate (Subcompositor *subcompositor)
|
|||
}
|
||||
}
|
||||
|
||||
if (ViewHaveTransform (view))
|
||||
RenderResetTransform (buffer);
|
||||
|
||||
next_1:
|
||||
list = list->next;
|
||||
}
|
||||
|
@ -2358,6 +2354,7 @@ SubcompositorExpose (Subcompositor *subcompositor, XEvent *event)
|
|||
Operation op;
|
||||
pixman_region32_t temp;
|
||||
RenderBuffer buffer;
|
||||
DrawParams draw_params;
|
||||
|
||||
/* Graphics exposures are not yet handled. */
|
||||
if (event->type == GraphicsExpose)
|
||||
|
@ -2438,11 +2435,12 @@ SubcompositorExpose (Subcompositor *subcompositor, XEvent *event)
|
|||
buffer = XLRenderBufferFromBuffer (view->buffer);
|
||||
boxes = pixman_region32_rectangles (&temp, &nboxes);
|
||||
|
||||
/* Update the attached buffer from any damage. */
|
||||
RenderUpdateBufferForDamage (buffer, &list->view->damage);
|
||||
/* Compute the transform. */
|
||||
ViewComputeTransform (view, &draw_params);
|
||||
|
||||
if (ViewHaveTransform (view))
|
||||
ViewApplyTransform (view, buffer);
|
||||
/* Update the attached buffer from any damage. */
|
||||
RenderUpdateBufferForDamage (buffer, &list->view->damage,
|
||||
GetContentScale (list->view->scale));
|
||||
|
||||
for (i = 0; i < nboxes; ++i)
|
||||
RenderComposite (buffer, subcompositor->target, op,
|
||||
|
@ -2455,11 +2453,9 @@ SubcompositorExpose (Subcompositor *subcompositor, XEvent *event)
|
|||
/* dst-y. */
|
||||
BoxStartY (boxes[i]) - min_y + ty,
|
||||
/* width, height. */
|
||||
BoxWidth (boxes[i]), BoxHeight (boxes[i]));
|
||||
|
||||
/* Undo transforms that were applied. */
|
||||
if (ViewHaveTransform (view))
|
||||
RenderResetTransform (buffer);
|
||||
BoxWidth (boxes[i]), BoxHeight (boxes[i]),
|
||||
/* draw-params. */
|
||||
&draw_params);
|
||||
|
||||
/* Free the scratch region used to compute the intersection. */
|
||||
pixman_region32_fini (&temp);
|
||||
|
|
30
subsurface.c
30
subsurface.c
|
@ -488,9 +488,13 @@ MaybeUpdateOutputs (Subsurface *subsurface)
|
|||
/* Valid base coordinates are not yet available. */
|
||||
return;
|
||||
|
||||
if (!subsurface->parent)
|
||||
/* A valid scale factor is not available. */
|
||||
return;
|
||||
|
||||
/* Compute the positions relative to the parent. */
|
||||
x = subsurface->current_substate.x * global_scale_factor;
|
||||
y = subsurface->current_substate.y * global_scale_factor;
|
||||
x = subsurface->current_substate.x * subsurface->parent->factor;
|
||||
y = subsurface->current_substate.y * subsurface->parent->factor;
|
||||
|
||||
/* And the base X and Y. */
|
||||
base_x = subsurface->role.surface->output_x;
|
||||
|
@ -541,12 +545,12 @@ AfterParentCommit (Surface *surface, void *data)
|
|||
subsurface->current_substate.y
|
||||
= subsurface->pending_substate.y;
|
||||
|
||||
/* The X and Y coordinates here are also surface-local and must
|
||||
/* The X and Y coordinates here are also parent-local and must
|
||||
be scaled by the global scale factor. */
|
||||
|
||||
ViewMove (subsurface->role.surface->view,
|
||||
subsurface->current_substate.x * global_scale_factor,
|
||||
subsurface->current_substate.y * global_scale_factor);
|
||||
subsurface->current_substate.x * subsurface->parent->factor,
|
||||
subsurface->current_substate.y * subsurface->parent->factor);
|
||||
}
|
||||
|
||||
/* And any cached surface state too. */
|
||||
|
@ -695,8 +699,15 @@ Rescale (Surface *surface, Role *role)
|
|||
position. */
|
||||
|
||||
ViewMove (surface->view,
|
||||
subsurface->current_substate.x * global_scale_factor,
|
||||
subsurface->current_substate.y * global_scale_factor);
|
||||
subsurface->current_substate.x * subsurface->parent->factor,
|
||||
subsurface->current_substate.y * subsurface->parent->factor);
|
||||
}
|
||||
|
||||
static void
|
||||
ParentRescale (Surface *surface, Role *role)
|
||||
{
|
||||
/* This is called when the scale factor of the parent changes. */
|
||||
Rescale (surface, role);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -843,6 +854,7 @@ GetSubsurface (struct wl_client *client, struct wl_resource *resource,
|
|||
subsurface->role.funcs.early_commit = EarlyCommit;
|
||||
subsurface->role.funcs.get_window = GetWindow;
|
||||
subsurface->role.funcs.rescale = Rescale;
|
||||
subsurface->role.funcs.parent_rescale = ParentRescale;
|
||||
subsurface->role.funcs.note_child_synced = NoteChildSynced;
|
||||
subsurface->role.funcs.note_desync_child = NoteDesyncChild;
|
||||
|
||||
|
@ -937,9 +949,9 @@ XLUpdateOutputsForChildren (Surface *parent, int base_x, int base_y)
|
|||
child = item->data;
|
||||
subsurface = SubsurfaceFromRole (child->role);
|
||||
output_x = (subsurface->current_substate.x
|
||||
* global_scale_factor);
|
||||
* parent->factor);
|
||||
output_y = (subsurface->current_substate.y
|
||||
* global_scale_factor);
|
||||
* parent->factor);
|
||||
output_width = ViewWidth (child->view);
|
||||
output_height = ViewHeight (child->view);
|
||||
|
||||
|
|
107
surface.c
107
surface.c
|
@ -509,11 +509,92 @@ static void
|
|||
ApplyScale (Surface *surface)
|
||||
{
|
||||
int scale, effective;
|
||||
double b, g, e, d;
|
||||
XLList *subsurface;
|
||||
Role *role;
|
||||
|
||||
scale = surface->current_state.buffer_scale;
|
||||
effective = GetEffectiveScale (scale);
|
||||
|
||||
ViewSetScale (surface->view, effective);
|
||||
|
||||
/* Now calculate the surface factor, a factor used to scale surface
|
||||
coordinates to view (X window) coordinates.
|
||||
|
||||
The scale we want is the width of the view (area on the X screen)
|
||||
divided by the surface width, which is the width of the buffer
|
||||
after it has been shrunk B - 1 times, B being the buffer scale.
|
||||
|
||||
However, the size of the view is not available during computation.
|
||||
So, computing the scale looks something like this:
|
||||
|
||||
A = width of buffer <-------------+-- we must reduce these out
|
||||
B = buffer scale |
|
||||
C = width of view <---------------+
|
||||
L = surface width <---------------+
|
||||
G = global scale
|
||||
E = scale after accounting for difference between the global
|
||||
and buffer scales
|
||||
D = desired scale, otherwise C / surface width
|
||||
|
||||
A = 2004
|
||||
B = 3
|
||||
G = 2
|
||||
|
||||
L = A / B
|
||||
E = G - B
|
||||
|
||||
if E is not less than 0
|
||||
|
||||
E = E + 1
|
||||
|
||||
else
|
||||
|
||||
E = 1 / abs (E - 1)
|
||||
|
||||
finally
|
||||
|
||||
C = A * E
|
||||
D = C / L
|
||||
|
||||
D = (A * E) / (A / B)
|
||||
D = B * E
|
||||
|
||||
Phew. */
|
||||
|
||||
b = scale;
|
||||
g = global_scale_factor;
|
||||
e = g - b;
|
||||
|
||||
if (e >= 0.0)
|
||||
e = e + 1;
|
||||
else
|
||||
e = 1.0 / fabs (e - 1);
|
||||
|
||||
d = b * e;
|
||||
|
||||
if (surface->factor != d)
|
||||
{
|
||||
/* The scale factor changed. */
|
||||
surface->factor = d;
|
||||
|
||||
/* Notify all subsurfaces to move themselves to a more correct
|
||||
location. */
|
||||
subsurface = surface->subsurfaces;
|
||||
for (; subsurface; subsurface = subsurface->next)
|
||||
{
|
||||
/* Get the subsurface role. */
|
||||
role = subsurface->data;
|
||||
|
||||
/* Make sure it still has a surface, since it should not be
|
||||
in surface->subsurfaces otherwise. */
|
||||
XLAssert (role->surface != NULL);
|
||||
|
||||
/* Call the parent rescale hook. */
|
||||
if (role->funcs.rescale)
|
||||
role->funcs.rescale (role->surface, role);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -530,7 +611,7 @@ ApplyOpaqueRegion (Surface *surface)
|
|||
{
|
||||
pixman_region32_init (&temp);
|
||||
XLScaleRegion (&temp, &surface->current_state.opaque,
|
||||
global_scale_factor, global_scale_factor);
|
||||
surface->factor, surface->factor);
|
||||
ViewSetOpaque (surface->view, &temp);
|
||||
pixman_region32_fini (&temp);
|
||||
}
|
||||
|
@ -550,7 +631,7 @@ ApplyInputRegion (Surface *surface)
|
|||
{
|
||||
pixman_region32_init (&temp);
|
||||
XLScaleRegion (&temp, &surface->current_state.input,
|
||||
global_scale_factor, global_scale_factor);
|
||||
surface->factor, surface->factor);
|
||||
ViewSetInput (surface->view, &temp);
|
||||
pixman_region32_fini (&temp);
|
||||
}
|
||||
|
@ -566,9 +647,9 @@ HandleScaleChanged (void *data, int new_scale)
|
|||
|
||||
/* First, reapply various regions that depend on the surface
|
||||
scale. */
|
||||
ApplyScale (surface);
|
||||
ApplyInputRegion (surface);
|
||||
ApplyOpaqueRegion (surface);
|
||||
ApplyScale (surface);
|
||||
|
||||
/* Next, call any role-specific hooks. */
|
||||
if (surface->role && surface->role->funcs.rescale)
|
||||
|
@ -639,7 +720,7 @@ ApplySurfaceDamage (Surface *surface)
|
|||
{
|
||||
pixman_region32_init (&temp);
|
||||
XLScaleRegion (&temp, &surface->current_state.surface,
|
||||
global_scale_factor, global_scale_factor);
|
||||
surface->factor, surface->factor);
|
||||
ViewDamage (surface->view, &temp);
|
||||
pixman_region32_fini (&temp);
|
||||
}
|
||||
|
@ -788,6 +869,12 @@ InternalCommit (Surface *surface, State *pending)
|
|||
}
|
||||
}
|
||||
|
||||
if (pending->pending & PendingBufferScale)
|
||||
{
|
||||
surface->current_state.buffer_scale = pending->buffer_scale;
|
||||
ApplyScale (surface);
|
||||
}
|
||||
|
||||
if (pending->pending & PendingInputRegion)
|
||||
{
|
||||
pixman_region32_copy (&surface->current_state.input,
|
||||
|
@ -802,12 +889,6 @@ InternalCommit (Surface *surface, State *pending)
|
|||
ApplyOpaqueRegion (surface);
|
||||
}
|
||||
|
||||
if (pending->pending & PendingBufferScale)
|
||||
{
|
||||
surface->current_state.buffer_scale = pending->buffer_scale;
|
||||
ApplyScale (surface);
|
||||
}
|
||||
|
||||
if (pending->pending & PendingAttachments)
|
||||
{
|
||||
surface->current_state.x = pending->x;
|
||||
|
@ -1151,13 +1232,13 @@ XLCreateSurface (struct wl_client *client,
|
|||
InitState (&surface->current_state);
|
||||
InitState (&surface->cached_state);
|
||||
|
||||
/* Apply the scale to initialize the default. */
|
||||
ApplyScale (surface);
|
||||
|
||||
/* Now the default input has been initialized, so apply it to the
|
||||
view. */
|
||||
ApplyInputRegion (surface);
|
||||
|
||||
/* Likewise for the scale. */
|
||||
ApplyScale (surface);
|
||||
|
||||
/* Initially, allow surfaces to accept any kind of role. */
|
||||
surface->role_type = AnythingType;
|
||||
|
||||
|
|
27
xdg_popup.c
27
xdg_popup.c
|
@ -278,6 +278,7 @@ MoveWindow (XdgPopup *popup)
|
|||
int root_x, root_y, parent_gx, parent_gy;
|
||||
int geometry_x, geometry_y, x, y;
|
||||
Window window;
|
||||
double parent_scale, current_scale;
|
||||
|
||||
/* No parent was specified. */
|
||||
if (!popup->parent)
|
||||
|
@ -286,6 +287,14 @@ MoveWindow (XdgPopup *popup)
|
|||
if (!popup->role || !popup->parent)
|
||||
return;
|
||||
|
||||
if (!popup->role->surface || !popup->parent->surface)
|
||||
/* No surface being available means we cannot obtain the window
|
||||
scale. */
|
||||
return;
|
||||
|
||||
parent_scale = popup->parent->surface->factor;
|
||||
current_scale = popup->role->surface->factor;
|
||||
|
||||
window = XLWindowFromXdgRole (popup->role);
|
||||
|
||||
XLXdgRoleGetCurrentGeometry (popup->parent, &parent_gx,
|
||||
|
@ -295,12 +304,18 @@ MoveWindow (XdgPopup *popup)
|
|||
XLXdgRoleCurrentRootPosition (popup->parent, &root_x,
|
||||
&root_y);
|
||||
|
||||
parent_gx *= global_scale_factor;
|
||||
parent_gy *= global_scale_factor;
|
||||
geometry_x *= global_scale_factor;
|
||||
geometry_y *= global_scale_factor;
|
||||
x = popup->x * global_scale_factor;
|
||||
y = popup->y * global_scale_factor;
|
||||
/* Parent geometry is relative to the parent coordinate system. */
|
||||
parent_gx *= parent_scale;
|
||||
parent_gy *= parent_scale;
|
||||
|
||||
/* geometry_x and geometry_y are relative to the local coordinate
|
||||
system. */
|
||||
geometry_x *= current_scale;
|
||||
geometry_y *= current_scale;
|
||||
|
||||
/* X and Y are relative to the parent coordinate system. */
|
||||
x = popup->x * parent_scale;
|
||||
y = popup->y * parent_scale;
|
||||
|
||||
XMoveWindow (compositor.display, window,
|
||||
x + root_x + parent_gx - geometry_x,
|
||||
|
|
|
@ -1167,8 +1167,8 @@ GetResizeDimensions (Surface *surface, Role *role, int *x_out,
|
|||
{
|
||||
XLXdgRoleGetCurrentGeometry (role, NULL, NULL, x_out, y_out);
|
||||
|
||||
*x_out *= global_scale_factor;
|
||||
*y_out *= global_scale_factor;
|
||||
*x_out *= surface->factor;
|
||||
*y_out *= surface->factor;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1467,7 +1467,10 @@ XLXdgRoleCalcNewWindowSize (Role *role, int width, int height,
|
|||
|
||||
xdg_role = XdgRoleFromRole (role);
|
||||
|
||||
if (!xdg_role->current_state.window_geometry_width)
|
||||
if (!xdg_role->current_state.window_geometry_width
|
||||
/* If no surface exists, we might as well return immediately,
|
||||
since the scale factor will not be obtainable. */
|
||||
|| !role->surface)
|
||||
{
|
||||
*new_width = width;
|
||||
*new_height = height;
|
||||
|
@ -1480,8 +1483,8 @@ XLXdgRoleCalcNewWindowSize (Role *role, int width, int height,
|
|||
|
||||
/* Adjust the current_width and current_height by the global scale
|
||||
factor. */
|
||||
current_width = (max_x - min_x + 1) / global_scale_factor;
|
||||
current_height = (max_y - min_y + 1) / global_scale_factor;
|
||||
current_width = (max_x - min_x + 1) / role->surface->factor;
|
||||
current_height = (max_y - min_y + 1) / role->surface->factor;
|
||||
|
||||
XLXdgRoleGetCurrentGeometry (role, NULL, NULL, &geometry_width,
|
||||
&geometry_height);
|
||||
|
|
|
@ -362,9 +362,14 @@ NoteConfigureTime (Timer *timer, void *data, struct timespec time)
|
|||
{
|
||||
XdgToplevel *toplevel;
|
||||
int width, height, effective_width, effective_height;
|
||||
double factor;
|
||||
|
||||
toplevel = data;
|
||||
|
||||
/* Obtain the scale factor. toplevel->role->surface should not be
|
||||
NULL here, as the timer is cancelled upon role detachment. */
|
||||
factor = toplevel->role->surface->factor;
|
||||
|
||||
/* If only the window state changed, call SendStates. */
|
||||
if (!(toplevel->state & StatePendingConfigureSize))
|
||||
SendStates (toplevel);
|
||||
|
@ -374,8 +379,8 @@ NoteConfigureTime (Timer *timer, void *data, struct timespec time)
|
|||
if (toplevel->state & StatePendingConfigureStates)
|
||||
WriteStates (toplevel);
|
||||
|
||||
effective_width = toplevel->configure_width / global_scale_factor;
|
||||
effective_height = toplevel->configure_height / global_scale_factor;
|
||||
effective_width = toplevel->configure_width / factor;
|
||||
effective_height = toplevel->configure_height / factor;
|
||||
|
||||
/* Compute the geometry for the configure event based on the
|
||||
current size of the toplevel. */
|
||||
|
@ -477,9 +482,14 @@ static void
|
|||
SendStates (XdgToplevel *toplevel)
|
||||
{
|
||||
int width, height;
|
||||
double factor;
|
||||
|
||||
WriteStates (toplevel);
|
||||
|
||||
/* Obtain the scale factor. toplevel->role->surface should not be
|
||||
NULL here. */
|
||||
factor = toplevel->role->surface->factor;
|
||||
|
||||
/* Adjust the width and height we're sending by the window
|
||||
geometry. */
|
||||
if (toplevel->state & StateMissingState)
|
||||
|
@ -487,8 +497,8 @@ SendStates (XdgToplevel *toplevel)
|
|||
&width, &height);
|
||||
else
|
||||
XLXdgRoleCalcNewWindowSize (toplevel->role,
|
||||
toplevel->width / global_scale_factor,
|
||||
toplevel->height / global_scale_factor,
|
||||
toplevel->width / factor,
|
||||
toplevel->height / factor,
|
||||
&width, &height);
|
||||
|
||||
SendConfigure (toplevel, width, height);
|
||||
|
@ -505,6 +515,14 @@ RecordStateSize (XdgToplevel *toplevel)
|
|||
{
|
||||
Bool a, b;
|
||||
int width, height;
|
||||
double factor;
|
||||
|
||||
if (!toplevel->role->surface)
|
||||
/* We can't get the scale factor in this case. */
|
||||
return;
|
||||
|
||||
/* Obtain the scale factor. */
|
||||
factor = toplevel->role->surface->factor;
|
||||
|
||||
/* Record the last known size of a toplevel before its state is
|
||||
changed. That way, we can send xdg_toplevel::configure with the
|
||||
|
@ -521,8 +539,8 @@ RecordStateSize (XdgToplevel *toplevel)
|
|||
upon minimization. */
|
||||
XLXdgRoleGetCurrentGeometry (toplevel->role, NULL, NULL,
|
||||
&width, &height);
|
||||
width *= global_scale_factor;
|
||||
height *= global_scale_factor;
|
||||
width *= factor;
|
||||
height *= factor;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -778,10 +796,10 @@ HandleWindowGeometryChange (XdgToplevel *toplevel)
|
|||
XLXdgRoleGetCurrentGeometry (toplevel->role, &x, &y,
|
||||
&width, &height);
|
||||
|
||||
width *= global_scale_factor;
|
||||
height *= global_scale_factor;
|
||||
x *= global_scale_factor;
|
||||
y *= global_scale_factor;
|
||||
width *= toplevel->role->surface->factor;
|
||||
height *= toplevel->role->surface->factor;
|
||||
x *= toplevel->role->surface->factor;
|
||||
y *= toplevel->role->surface->factor;
|
||||
|
||||
dx = SubcompositorWidth (subcompositor) - width;
|
||||
dy = SubcompositorHeight (subcompositor) - height;
|
||||
|
@ -795,25 +813,35 @@ HandleWindowGeometryChange (XdgToplevel *toplevel)
|
|||
/* Initially, specify PSize. After the first MapNotify, also
|
||||
specify PPosition so that subsurfaces won't move the window. */
|
||||
|
||||
hints->min_width = toplevel->min_width * global_scale_factor + dx;
|
||||
hints->min_height = toplevel->min_height * global_scale_factor + dy;
|
||||
hints->min_width = (toplevel->min_width
|
||||
* toplevel->role->surface->factor
|
||||
+ dx);
|
||||
hints->min_height = (toplevel->min_height
|
||||
* toplevel->role->surface->factor
|
||||
+ dy);
|
||||
|
||||
if (toplevel->max_width)
|
||||
{
|
||||
hints->max_width = toplevel->max_width * global_scale_factor + dx;
|
||||
hints->max_height = toplevel->max_height * global_scale_factor + dy;
|
||||
hints->max_width = (toplevel->max_width
|
||||
* toplevel->role->surface->factor
|
||||
+ dx);
|
||||
hints->max_height = (toplevel->max_height
|
||||
* toplevel->role->surface->factor
|
||||
+ dy);
|
||||
hints->flags |= PMaxSize;
|
||||
}
|
||||
else
|
||||
hints->flags &= ~PMaxSize;
|
||||
|
||||
/* If a global scale factor is set, also set the resize increment to
|
||||
the scale factor. */
|
||||
/* If a scale factor is set, also set the resize increment to the
|
||||
scale factor. */
|
||||
|
||||
if (global_scale_factor != 1)
|
||||
if (toplevel->role->surface->factor != 1)
|
||||
{
|
||||
hints->width_inc = global_scale_factor;
|
||||
hints->height_inc = global_scale_factor;
|
||||
/* Take the ceiling value, there is no good way of dealing with
|
||||
cases where the scale ends up a non-integer value. */
|
||||
hints->width_inc = ceil (toplevel->role->surface->factor);
|
||||
hints->height_inc = ceil (toplevel->role->surface->factor);
|
||||
hints->flags |= PResizeInc;
|
||||
}
|
||||
else
|
||||
|
@ -1345,10 +1373,10 @@ NoteWindowPreResize (Role *role, XdgRoleImplementation *impl,
|
|||
XLXdgRoleGetCurrentGeometry (toplevel->role, &x, &y,
|
||||
&gwidth, &gheight);
|
||||
|
||||
dx = width - gwidth * global_scale_factor;
|
||||
dy = height - gheight * global_scale_factor;
|
||||
x *= global_scale_factor;
|
||||
y *= global_scale_factor;
|
||||
dx = width - gwidth * toplevel->role->surface->factor;
|
||||
dy = height - gheight * toplevel->role->surface->factor;
|
||||
x *= toplevel->role->surface->factor;
|
||||
y *= toplevel->role->surface->factor;
|
||||
|
||||
ApplyGtkFrameExtents (toplevel, x, y, dx - x, dy - y);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue