diff --git a/compositor.h b/compositor.h
index 974f185..e517752 100644
--- a/compositor.h
+++ b/compositor.h
@@ -17,6 +17,8 @@ for more details.
You should have received a copy of the GNU General Public License
along with 12to11. If not, see . */
+#include
+
#include
#include
@@ -627,7 +629,6 @@ extern void *XLLookUpAssoc (XLAssocTable *, XID);
extern void XLDeleteAssoc (XLAssocTable *, XID);
extern void XLDestroyAssocTable (XLAssocTable *);
-extern void XLAssert (Bool);
extern int XLOpenShm (void);
extern void XLScaleRegion (pixman_region32_t *, pixman_region32_t *,
@@ -787,8 +788,10 @@ extern void ViewTranslate (View *, int, int, int *, int *);
extern void ViewFree (View *);
extern void ViewDamage (View *, pixman_region32_t *);
+extern void ViewDamageBuffer (View *, pixman_region32_t *);
extern void ViewSetOpaque (View *, pixman_region32_t *);
extern void ViewSetInput (View *, pixman_region32_t *);
+extern double ViewGetContentScale (View *);
extern int ViewWidth (View *);
extern int ViewHeight (View *);
extern void ViewSetScale (View *, int);
@@ -1661,3 +1664,5 @@ extern void XLRelativePointerSendRelativeMotion (struct wl_resource *,
#define IntSubtractWrapv(a, b, r) __builtin_sub_overflow (a, b, r)
#define IntMultiplyWrapv(a, b, r) __builtin_mul_overflow (a, b, r)
+/* This is a macro in order to be more static analyzer friendly. */
+#define XLAssert(cond) (!(cond) ? abort () : ((void) 0))
diff --git a/dnd.c b/dnd.c
index 1cd3d97..13cb774 100644
--- a/dnd.c
+++ b/dnd.c
@@ -1632,10 +1632,9 @@ HandleCirculateNotify (WindowCache *cache, XEvent *event)
window = XLLookUpAssoc (cache->entries, event->xcirculate.window);
- if (window)
+ if (!window)
return;
-
XLAssert (window->parent == event->xcirculate.event);
/* If the window has been recirculated to the top, relink it
@@ -1870,7 +1869,7 @@ HandleReparentNotify (WindowCache *cache, XEvent *event)
window = XLLookUpAssoc (cache->entries, event->xreparent.window);
- if (window)
+ if (!window)
return;
/* First, unlink window. */
@@ -2230,8 +2229,15 @@ ReadProtocolProperties (Window window, int *version_return,
entry = XLLookUpAssoc (drag_state.window_cache->entries, window);
if (!entry)
- /* The entry is not in the window cache... */
- return;
+ {
+ /* Return some suitable values for a window that isn't in the
+ window cache. */
+ *version_return = 0;
+ *proxy_return = None;
+
+ /* The entry is not in the window cache... */
+ return;
+ }
if (entry->flags & IsPropertyRead)
{
diff --git a/egl.c b/egl.c
index 813f920..315a767 100644
--- a/egl.c
+++ b/egl.c
@@ -466,8 +466,6 @@ HaveEglExtension1 (const char *extensions, const char *extension)
while (extensions < end)
{
- n = 0;
-
/* Skip spaces, if any. */
if (*extensions == ' ')
{
diff --git a/fns.c b/fns.c
index 79ad7fe..8ec41c8 100644
--- a/fns.c
+++ b/fns.c
@@ -337,13 +337,6 @@ XLDestroyAssocTable (XLAssocTable *table)
XLFree (table);
}
-void
-XLAssert (Bool condition)
-{
- if (!condition)
- abort ();
-}
-
void
XLScaleRegion (pixman_region32_t *dst, pixman_region32_t *src,
float scale_x, float scale_y)
diff --git a/picture_renderer.c b/picture_renderer.c
index 22a4b92..2c2df0b 100644
--- a/picture_renderer.c
+++ b/picture_renderer.c
@@ -1609,8 +1609,6 @@ GetRenderDevice (Bool *error)
int *fds, fd;
struct stat dev_stat;
- /* TODO: if this ever calls exec, set FD_CLOEXEC, and implement
- multiple providers. */
cookie = xcb_dri3_open (compositor.conn,
DefaultRootWindow (compositor.display),
None);
@@ -2022,10 +2020,17 @@ BufferFromShm (SharedMemoryAttributes *attributes, Bool *error)
Picture picture;
int fd, depth, format, bpp;
PictureBuffer *buffer;
+ XRenderPictFormat *pict_format;
depth = DepthForFormat (attributes->format, &bpp);
format = attributes->format;
+ if (!depth)
+ {
+ *error = True;
+ return (RenderBuffer) NULL;
+ }
+
/* Duplicate the fd, since XCB closes file descriptors after sending
them. */
fd = fcntl (attributes->fd, F_DUPFD_CLOEXEC, 0);
@@ -2036,6 +2041,10 @@ BufferFromShm (SharedMemoryAttributes *attributes, Bool *error)
return (RenderBuffer) NULL;
}
+ /* Obtain the picture format. */
+ pict_format = PictFormatForFormat (format);
+ XLAssert (pict_format != NULL);
+
/* Now, allocate the XIDs for the shm segment and pixmap. */
seg = xcb_generate_id (compositor.conn);
pixmap = xcb_generate_id (compositor.conn);
@@ -2050,8 +2059,7 @@ BufferFromShm (SharedMemoryAttributes *attributes, Bool *error)
/* Create the picture for the pixmap. */
picture = XRenderCreatePicture (compositor.display, pixmap,
- PictFormatForFormat (format),
- 0, &picture_attrs);
+ pict_format, 0, &picture_attrs);
/* Create the wrapper object. */
buffer = XLCalloc (1, sizeof *buffer);
@@ -2072,7 +2080,7 @@ BufferFromShm (SharedMemoryAttributes *attributes, Bool *error)
buffer->activity.buffer_last = &buffer->activity;
/* If the format is presentable, mark the buffer as presentable. */
- if (PictFormatIsPresentable (PictFormatForFormat (format)))
+ if (PictFormatIsPresentable (pict_format))
buffer->flags |= CanPresent;
/* Return the picture. */
@@ -2109,7 +2117,7 @@ ValidateShmParams (uint32_t format, uint32_t width, uint32_t height,
/* Obtain the depth and bpp. */
depth = DepthForFormat (format, &bpp);
- XLAssert (depth != -1);
+ XLAssert (depth != 0);
/* If any signed values are negative, return. */
if (offset < 0 || stride < 0)
diff --git a/pointer_constraints.c b/pointer_constraints.c
index ea20b51..5970840 100644
--- a/pointer_constraints.c
+++ b/pointer_constraints.c
@@ -1323,8 +1323,6 @@ ApplyLines (Window window, PointerConfinement *confinement,
FreeSingleBarrier);
confinement->applied_barriers = NULL;
- i = 0;
-
/* Set the pointer device. */
device_id = XLSeatGetPointerDevice (confinement->seat);
diff --git a/renderer.c b/renderer.c
index cee6ad7..682d43b 100644
--- a/renderer.c
+++ b/renderer.c
@@ -466,9 +466,10 @@ PickRenderer (void)
/* Fall back to the default renderer. */
fprintf (stderr, "Defaulting to renderer %s, as %s was not found\n",
renderers->name, selected);
- fall_back:
}
+ fall_back:
+
if (!InstallRenderer (renderers))
abort ();
}
diff --git a/seat.c b/seat.c
index 279e584..5e3c1bd 100644
--- a/seat.c
+++ b/seat.c
@@ -1038,7 +1038,12 @@ ComputeHotspot (SeatCursor *cursor, int min_x, int min_y,
int hotspot_x, hotspot_y;
if (!cursor->role.surface)
- return;
+ {
+ /* Can this really happen? */
+ *x = min_x + cursor->hotspot_x;
+ *y = min_y + cursor->hotspot_y;
+ return;
+ }
/* Scale the hotspot coordinates up by the scale. */
hotspot_x = cursor->hotspot_x * cursor->role.surface->factor;
@@ -5028,12 +5033,12 @@ XLSeatExplicitlyGrabSurface (Seat *seat, Surface *surface, uint32_t serial)
CancelGrabEarly (seat);
/* Now, grab the keyboard. Note that we just grab the keyboard so
- that keyboard focus cannot be changed; key events are still
- reported based on raw events. */
+ that keyboard focus cannot be changed, which is not very crucial,
+ so it is allowed to fail. */
- state = XIGrabDevice (compositor.display, seat->master_keyboard,
- window, time, None, XIGrabModeAsync,
- XIGrabModeAsync, True, &mask);
+ XIGrabDevice (compositor.display, seat->master_keyboard,
+ window, time, None, XIGrabModeAsync,
+ XIGrabModeAsync, True, &mask);
/* And record the grab surface, so that owner_events can be
implemented correctly. */
diff --git a/shm.c b/shm.c
index 239e531..4d74be2 100644
--- a/shm.c
+++ b/shm.c
@@ -430,7 +430,11 @@ CreatePool (struct wl_client *client, struct wl_resource *resource,
pool = XLSafeMalloc (sizeof *pool);
if (!pool)
- wl_resource_post_no_memory (resource);
+ {
+ wl_resource_post_no_memory (resource);
+ close (fd);
+ return;
+ }
memset (pool, 0, sizeof *pool);
diff --git a/subcompositor.c b/subcompositor.c
index b2771e9..52eee84 100644
--- a/subcompositor.c
+++ b/subcompositor.c
@@ -1604,6 +1604,78 @@ ViewDamage (View *view, pixman_region32_t *damage)
damage);
}
+static double
+GetContentScale (int scale)
+{
+ if (scale > 0)
+ return 1.0 / (scale + 1);
+
+ return -scale + 1;
+}
+
+void
+ViewDamageBuffer (View *view, pixman_region32_t *damage)
+{
+ pixman_region32_t temp;
+ double x_factor, y_factor;
+ double crop_width, stretch_width;
+ double crop_height, stretch_height;
+
+ if (!view->buffer)
+ return;
+
+ if (!view->scale && !IsViewported (view))
+ /* There is no scale nor viewport. Just damage the view
+ directly. */
+ ViewDamage (view, damage);
+ else
+ {
+ /* Otherwise, apply the transform to the view. */
+ pixman_region32_init (&temp);
+
+ /* First, apply the content scale. */
+ x_factor = GetContentScale (view->scale);
+ y_factor = GetContentScale (view->scale);
+
+ /* Scale the region. */
+ XLScaleRegion (&temp, damage, x_factor, y_factor);
+
+ /* Next, apply the viewport. */
+ if (IsViewported (view))
+ {
+ crop_width = view->crop_width;
+ crop_height = view->crop_height;
+ stretch_width = view->dest_width;
+ stretch_height = view->dest_height;
+
+ /* Offset the region. */
+ if (view->src_x != 1.0 || view->src_y != 1.0)
+ pixman_region32_translate (&temp, -view->src_x,
+ -view->src_y);
+
+ /* If the crop width or height were not specified, use the
+ current buffer width/height. */
+ if (crop_width == -1)
+ {
+ crop_width = (XLBufferWidth (view->buffer)
+ * GetContentScale (view->scale));
+ crop_height = (XLBufferHeight (view->buffer)
+ * GetContentScale (view->scale));
+ }
+
+ x_factor = stretch_width / crop_width;
+ y_factor = stretch_height / crop_height;
+
+ /* Scale the region again. */
+ XLScaleRegion (&temp, &temp, x_factor, y_factor);
+ }
+
+ /* Damage the view. */
+ pixman_region32_union (&view->damage, &view->damage, &temp);
+ pixman_region32_fini (&temp);
+ }
+}
+
void
ViewSetOpaque (View *view, pixman_region32_t *opaque)
{
@@ -1631,13 +1703,10 @@ ViewGetSubcompositor (View *view)
return view->subcompositor;
}
-static double
-GetContentScale (int scale)
+double
+ViewGetContentScale (View *view)
{
- if (scale > 0)
- return 1.0 / (scale + 1);
-
- return -scale + 1;
+ return GetContentScale (view->scale);
}
int
@@ -1698,7 +1767,6 @@ ViewSetScale (View *view, int scale)
ViewAfterSizeUpdate (view);
}
-
void
ViewSetViewport (View *view, double src_x, double src_y,
double crop_width, double crop_height,
@@ -2053,7 +2121,6 @@ SubcompositorUpdate (Subcompositor *subcompositor)
presented = False;
start = subcompositor->inferiors->next->view;
- original_start = subcompositor->inferiors->next->view;
age = RenderTargetAge (subcompositor->target);
/* If there is not enough prior damage available to satisfy age, set
@@ -2269,7 +2336,7 @@ SubcompositorUpdate (Subcompositor *subcompositor)
/* If the damage extends outside the area known to be
obscured by the current start, reset start back to
the original starting point. */
- if (start != original_start)
+ if (start != original_start && original_start)
{
pixman_region32_subtract (&temp, &list->view->damage,
&start_opaque);
diff --git a/surface.c b/surface.c
index aab4da1..6ec7ec5 100644
--- a/surface.c
+++ b/surface.c
@@ -644,7 +644,7 @@ static void
ApplyViewport (Surface *surface)
{
State *state;
- int dest_width, dest_height;
+ double dest_width, dest_height;
double crop_width, crop_height, src_x, src_y;
double max_width, max_height;
@@ -840,79 +840,9 @@ HandleScaleChanged (void *data, int new_scale)
static void
ApplyDamage (Surface *surface)
{
- pixman_region32_t temp;
- int scale;
- float x_factor, y_factor;
- double src_width, src_height;
- double dest_width, dest_height;
-
- scale = GetEffectiveScale (surface->current_state.buffer_scale);
-
- /* If no surface was attached, just return. */
- if (!surface->current_state.buffer)
- return;
-
- /* N.B. that this must come after the scale is applied. */
-
- if (scale || (surface->current_state.src_x != -1
- && surface->current_state.src_x != 0.0
- && surface->current_state.src_y != 0.0)
- || surface->current_state.dest_width != -1)
- {
- pixman_region32_init (&temp);
-
- if (!scale)
- x_factor = y_factor = 1.0;
- if (scale > 0)
- x_factor = y_factor = 1.0 / (scale + 1);
- else
- x_factor = y_factor = abs (scale) + 1;
-
- /* If a viewport dest size is set, add that to the scale as
- well. */
- if (surface->current_state.dest_width != -1)
- {
- if (surface->current_state.src_width != -1)
- {
- src_width = surface->current_state.src_width;
- src_height = surface->current_state.src_height;
- }
- else
- {
- src_width = XLBufferWidth (surface->current_state.buffer);
- src_height = XLBufferHeight (surface->current_state.buffer);
-
- /* Now scale these buffer dimensions down by the buffer
- scale, so they can be turned into surface
- coordinates. */
- src_width /= surface->current_state.buffer_scale;
- src_height /= surface->current_state.buffer_scale;
- }
-
- dest_width = surface->current_state.dest_width;
- dest_height = surface->current_state.dest_height;
-
- x_factor *= (float) (src_width / dest_width);
- y_factor *= (float) (src_height / dest_height);
- }
-
- if (x_factor != 1.0f || y_factor != 1.0f)
- XLScaleRegion (&temp, &surface->current_state.damage,
- x_factor, y_factor);
-
- /* If a viewport is set, translate the damage region by the
- src_x and src_y. This is lossy. */
- if (surface->current_state.src_x != -1.0)
- pixman_region32_translate (&temp,
- floor (surface->current_state.src_x),
- floor (surface->current_state.src_y));
-
- ViewDamage (surface->view, &temp);
-
- pixman_region32_fini (&temp);
- }
- else
- ViewDamage (surface->view, &surface->current_state.damage);
+ /* N.B. that this must come after the scale and viewport is
+ applied. */
+ ViewDamageBuffer (surface->view, &surface->current_state.damage);
}
static void
@@ -1809,7 +1739,7 @@ SurfaceToWindow (Surface *surface, double x, double y,
void
ScaleToWindow (Surface *surface, double width, double height,
- double *width_out, double *height_out)
+ double *width_out, double *height_out)
{
*width_out = width * surface->factor;
*height_out = height * surface->factor;
diff --git a/text_input.c b/text_input.c
index affff57..ca45df9 100644
--- a/text_input.c
+++ b/text_input.c
@@ -2781,7 +2781,11 @@ HandleNewIM (XIM xim)
while (input != &info->inputs)
{
/* Try to create the IC for this one input. */
- if (input->current_state.enabled)
+ if (input->current_state.enabled
+ /* If this is NULL, then the IC will only be created
+ upon the next commit after the focus is actually
+ transferred to the text input. */
+ && input->client_info->focus_surface)
{
CreateIC (input);
diff --git a/xdg_toplevel.c b/xdg_toplevel.c
index bd8e3df..18948f5 100644
--- a/xdg_toplevel.c
+++ b/xdg_toplevel.c
@@ -375,6 +375,8 @@ AddState (XdgToplevel *toplevel, uint32_t state)
static void
SendDecorationConfigure1 (XdgToplevel *toplevel)
{
+ XLAssert (toplevel->decoration != NULL);
+
#define ServerSide ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE
#define ClientSide ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE
@@ -676,13 +678,11 @@ HandleWmStateChange (XdgToplevel *toplevel)
&actual_format, &actual_size,
&bytes_remaining, &tmp_data);
- if (rc != Success
+ if (rc != Success || !tmp_data
|| actual_type != XA_ATOM || actual_format != 32
|| bytes_remaining)
goto empty_states;
- XLAssert (tmp_data != NULL);
-
states = (Atom *) tmp_data;
/* First, reset relevant states. */
@@ -790,13 +790,11 @@ HandleAllowedActionsChange (XdgToplevel *toplevel)
&actual_format, &actual_size,
&bytes_remaining, &tmp_data);
- if (rc != Success
+ if (rc != Success || !tmp_data
|| actual_type != XA_ATOM || actual_format != 32
|| bytes_remaining)
goto empty_states;
- XLAssert (tmp_data != NULL);
-
states = (Atom *) tmp_data;
/* First, reset the actions that we will change. */
@@ -2322,7 +2320,14 @@ HandleDecorationResourceDestroy (struct wl_resource *resource)
/* Detach the decoration from the toplevel if the latter still
exists. */
if (decoration->toplevel)
- decoration->toplevel->decoration = NULL;
+ {
+ decoration->toplevel->decoration = NULL;
+
+ /* Clear StateNeedDecorationConfigure, as not doing so may
+ result in decoration->toplevel (NULL) being dereferenced by
+ SendDecorationConfigure1. */
+ decoration->toplevel->state &= ~StateNeedDecorationConfigure;
+ }
/* Free the decoration. */
XLFree (decoration);