From f4a9332ad149ed15353a9c482563bdd042d0b403 Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Sun, 27 Jan 2013 10:06:42 -0800 Subject: [PATCH 01/25] Handle failure to create counter in init_system_idle_counter Check for NULL pointer (which can be returned for multiple reasons) before trying to dereference it to add privates. To avoid memory leak in error path, delay malloc of privates until we're ready to add them. In case we do return NULL up through SyncInitDeviceIdleTime, handle the possibility of getting NULL passed back down to SyncRemoveDeviceIdleTime. As reported by parfait 1.1: Error: Null pointer dereference (CWE 476) Read from null pointer 'idle_time_counter' at line 2764 of xserver/Xext/sync.c in function 'init_system_idle_counter'. Function 'SyncCreateSystemCounter' may return constant 'NULL' at line 952, called at line 2756. Null pointer introduced at line 952 in function 'SyncCreateSystemCounter'. Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer --- Xext/sync.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Xext/sync.c b/Xext/sync.c index 4d11992bb..9ae5b3981 100644 --- a/Xext/sync.c +++ b/Xext/sync.c @@ -2747,7 +2747,6 @@ init_system_idle_counter(const char *name, int deviceid) { CARD64 resolution; XSyncValue idle; - IdleCounterPriv *priv = malloc(sizeof(IdleCounterPriv)); SyncCounter *idle_time_counter; IdleTimeQueryValue(NULL, &idle); @@ -2758,10 +2757,14 @@ init_system_idle_counter(const char *name, int deviceid) IdleTimeQueryValue, IdleTimeBracketValues); - priv->deviceid = deviceid; - priv->value_less = priv->value_greater = NULL; + if (idle_time_counter != NULL) { + IdleCounterPriv *priv = malloc(sizeof(IdleCounterPriv)); - idle_time_counter->pSysCounterInfo->private = priv; + priv->value_less = priv->value_greater = NULL; + priv->deviceid = deviceid; + + idle_time_counter->pSysCounterInfo->private = priv; + } return idle_time_counter; } @@ -2786,6 +2789,6 @@ void SyncRemoveDeviceIdleTime(SyncCounter *counter) /* FreeAllResources() frees all system counters before the devices are shut down, check if there are any left before freeing the device's counter */ - if (!xorg_list_is_empty(&SysCounterList)) + if (counter && !xorg_list_is_empty(&SysCounterList)) xorg_list_del(&counter->pSysCounterInfo->entry); } From 48b94651205b175760904e448f94111d1ab85e13 Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Sun, 27 Jan 2013 11:20:45 -0800 Subject: [PATCH 02/25] Stop leaking overlayWin in PanoramiXCompositeGetOverlayWindow error paths Found by parfait 1.1 code analyzer: Error: Memory leak (CWE 401) Memory leak of pointer 'overlayWin' allocated with malloc(72) at line 806 of composite/compext.c in function 'PanoramiXCompositeGetOverlayWindow'. pointer allocated at line 794 with malloc(72). leaks when rc != 0 at line 804. at line 816 of composite/compext.c in function 'PanoramiXCompositeGetOverlayWindow'. pointer allocated at line 794 with malloc(72). leaks when pOc == NULL at line 815. at line 825 of composite/compext.c in function 'PanoramiXCompositeGetOverlayWindow'. pointer allocated at line 794 with malloc(72). leaks when cs->pOverlayWin == NULL at line 822 and compCreateOverlayWindow(pScreen) == 0 at line 823. at line 834 of composite/compext.c in function 'PanoramiXCompositeGetOverlayWindow'. pointer allocated at line 794 with malloc(72). leaks when rc != 0 at line 832. Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer --- composite/compext.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/composite/compext.c b/composite/compext.c index 8641eff5e..e4821c5fc 100644 --- a/composite/compext.c +++ b/composite/compext.c @@ -803,6 +803,7 @@ PanoramiXCompositeGetOverlayWindow(ClientPtr client) RT_WINDOW, client, DixGetAttrAccess); if (rc != Success) { client->errorValue = stuff->window; + free(overlayWin); return rc; } pScreen = pWin->drawable.pScreen; @@ -812,8 +813,10 @@ PanoramiXCompositeGetOverlayWindow(ClientPtr client) * interest in the overlay window */ pOc = compCreateOverlayClient(pScreen, client); - if (pOc == NULL) + if (pOc == NULL) { + free(overlayWin); return BadAlloc; + } /* * Make sure the overlay window exists @@ -822,6 +825,7 @@ PanoramiXCompositeGetOverlayWindow(ClientPtr client) if (cs->pOverlayWin == NULL) if (!compCreateOverlayWindow(pScreen)) { FreeResource(pOc->resource, RT_NONE); + free(overlayWin); return BadAlloc; } @@ -831,6 +835,7 @@ PanoramiXCompositeGetOverlayWindow(ClientPtr client) DixGetAttrAccess); if (rc != Success) { FreeResource(pOc->resource, RT_NONE); + free(overlayWin); return rc; } } From 89badba082c81d20fe35cb064c16e131ff288ca3 Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Sun, 27 Jan 2013 12:08:47 -0800 Subject: [PATCH 03/25] Free keymap on error in Xephyr's hostx_load_keymap Found by parfait 1.1 code analyser: Memory leak of pointer 'keymap' allocated with XGetKeyboardMapping(HostX.dpy, min_keycode, ((max_keycode - min_keycode) + 1), &host_width) at line 861 of hw/kdrive/ephyr/hostx.c in function 'hostx_load_keymap'. 'keymap' allocated at line 845 with XGetKeyboardMapping(HostX.dpy, min_keycode, ((max_keycode - min_keycode) + 1), &host_width). Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer --- hw/kdrive/ephyr/hostx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c index 157ac36b2..aed0285b6 100644 --- a/hw/kdrive/ephyr/hostx.c +++ b/hw/kdrive/ephyr/hostx.c @@ -858,7 +858,7 @@ hostx_load_keymap(void) (max_keycode - min_keycode + 1) * width); if (!ephyrKeySyms.map) - return; + goto out; for (i = 0; i < (max_keycode - min_keycode + 1); i++) for (j = 0; j < width; j++) @@ -871,6 +871,7 @@ hostx_load_keymap(void) ephyrKeySyms.maxKeyCode = max_keycode; ephyrKeySyms.mapWidth = width; + out: XFree(keymap); } From c1c01e350834a23161b33bd34b2fa9c01d02a65b Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Sun, 27 Jan 2013 13:10:08 -0800 Subject: [PATCH 04/25] Make xf86ValidateModes actually copy clock range list to screen pointer Our in-house parfait 1.1 code analysis tool complained that every exit path from xf86ValidateModes() in hw/xfree86/common/xf86Mode.c leaks the storeClockRanges allocation made at line 1501 with XNFalloc. Investigating, it seems that this code to copy the clock range list to the clockRanges list in the screen pointer is just plain insane, and according to git, has been since we first imported it from XFree86. We start at line 1495 by walking the linked list from scrp->clockRanges until we find the end. But that was just a diversion, since we've found the end and immediately forgotten it, and thus at 1499 we know that storeClockRanges is NULL, but that's not a problem since we're going to immediately overwrite that value as the first thing in the loop. So we move on through this loop at 1499, which takes us through the linked list from the clockRanges variable, and for every entry in that list allocates a new structure and copies cp to it. If we've not filled in the screen's clockRanges pointer yet, we set it to the first storeClockRanges we copied from cp. Otherwise, as best I can tell, we just drop it into memory and let it leak away, as parfait warned. And then we hit the loop action, which if we haven't hit the end of the cp list, advances cp to the next item in the list, and then just for the fun of it, also sets storeClockRanges to the ->next pointer it has just copied from cp as well, even though it's going to overwrite it as the very first instruction in the loop body. v2: rewritten using nt_list_* macros from Xorg's list.h header Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer --- hw/xfree86/common/xf86Mode.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/hw/xfree86/common/xf86Mode.c b/hw/xfree86/common/xf86Mode.c index d80dec892..706ab64fc 100644 --- a/hw/xfree86/common/xf86Mode.c +++ b/hw/xfree86/common/xf86Mode.c @@ -1370,7 +1370,6 @@ xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes, int saveType; PixmapFormatRec *BankFormat; ClockRangePtr cp; - ClockRangePtr storeClockRanges; int numTimings = 0; range hsync[MAX_HSYNC]; range vrefresh[MAX_VREFRESH]; @@ -1492,16 +1491,14 @@ xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes, /* * Store the clockRanges for later use by the VidMode extension. */ - storeClockRanges = scrp->clockRanges; - while (storeClockRanges != NULL) { - storeClockRanges = storeClockRanges->next; - } - for (cp = clockRanges; cp != NULL; cp = cp->next, - storeClockRanges = storeClockRanges->next) { - storeClockRanges = xnfalloc(sizeof(ClockRange)); + nt_list_for_each_entry(cp, clockRanges, next) { + ClockRangePtr newCR = xnfalloc(sizeof(ClockRange)); + memcpy(newCR, cp, sizeof(ClockRange)); + newCR->next = NULL; if (scrp->clockRanges == NULL) - scrp->clockRanges = storeClockRanges; - memcpy(storeClockRanges, cp, sizeof(ClockRange)); + scrp->clockRanges = newCR; + else + nt_list_append(newCR, scrp->clockRanges, ClockRange, next); } /* Determine which pixmap format to pass to scanLineWidth() */ From 08f75d3a9661c6c32800e1b4f150626200b889d9 Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Sun, 27 Jan 2013 13:50:30 -0800 Subject: [PATCH 05/25] Avoid NULL pointer dereference in xf86TokenToOptinfo if token not found Reported by parfait 1.1 code analyzer: Error: Null pointer dereference (CWE 476) Read from null pointer 'p' at line 746 of hw/xfree86/common/xf86Option.c in function 'xf86TokenToOptName'. Function 'xf86TokenToOptinfo' may return constant 'NULL' at line 721, called at line 745. Null pointer introduced at line 721 in function 'xf86TokenToOptinfo'. Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer --- hw/xfree86/common/xf86Option.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/xfree86/common/xf86Option.c b/hw/xfree86/common/xf86Option.c index 40c9d15f4..607c33354 100644 --- a/hw/xfree86/common/xf86Option.c +++ b/hw/xfree86/common/xf86Option.c @@ -743,7 +743,7 @@ xf86TokenToOptName(const OptionInfoRec * table, int token) const OptionInfoRec *p; p = xf86TokenToOptinfo(table, token); - return p->name; + return p ? p->name : NULL; } Bool From 563db909bcf965b6103c1807bf9f00ede957077d Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Sun, 27 Jan 2013 13:55:50 -0800 Subject: [PATCH 06/25] Avoid memory leak on realloc failure in localRegisterFreeBoxCallback Also avoids leaving invalid pointers in structures if realloc had to move them elsewhere to make them larger. Found by parfait 1.1 code analyzer: Memory leak of pointer 'newCallbacks' allocated with realloc(((char*)offman->FreeBoxesUpdateCallback), (8 * (offman->NumCallbacks + 1))) at line 328 of hw/xfree86/common/xf86fbman.c in function 'localRegisterFreeBoxCallback'. 'newCallbacks' allocated at line 320 with realloc(((char*)offman->FreeBoxesUpdateCallback), (8 * (offman->NumCallbacks + 1))). newCallbacks leaks when newCallbacks != NULL at line 327. Memory leak of pointer 'newPrivates' allocated with realloc(((char*)offman->devPrivates), (8 * (offman->NumCallbacks + 1))) at line 328 of hw/xfree86/common/xf86fbman.c in function 'localRegisterFreeBoxCallback'. 'newPrivates' allocated at line 324 with realloc(((char*)offman->devPrivates), (8 * (offman->NumCallbacks + 1))). newPrivates leaks when newCallbacks == NULL at line 327. Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer --- hw/xfree86/common/xf86fbman.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/hw/xfree86/common/xf86fbman.c b/hw/xfree86/common/xf86fbman.c index c2e7bab9f..4da6af2b6 100644 --- a/hw/xfree86/common/xf86fbman.c +++ b/hw/xfree86/common/xf86fbman.c @@ -320,15 +320,17 @@ localRegisterFreeBoxCallback(ScreenPtr pScreen, newCallbacks = realloc(offman->FreeBoxesUpdateCallback, sizeof(FreeBoxCallbackProcPtr) * (offman->NumCallbacks + 1)); + if (!newCallbacks) + return FALSE; + else + offman->FreeBoxesUpdateCallback = newCallbacks; newPrivates = realloc(offman->devPrivates, sizeof(DevUnion) * (offman->NumCallbacks + 1)); - - if (!newCallbacks || !newPrivates) + if (!newPrivates) return FALSE; - - offman->FreeBoxesUpdateCallback = newCallbacks; - offman->devPrivates = newPrivates; + else + offman->devPrivates = newPrivates; offman->FreeBoxesUpdateCallback[offman->NumCallbacks] = FreeBoxCallback; offman->devPrivates[offman->NumCallbacks].ptr = devPriv; From b1129a1f1771c9d1653cc15aae94a614f081638a Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Sun, 27 Jan 2013 14:00:54 -0800 Subject: [PATCH 07/25] xf86XvMCScreenInit: Avoid leak if dixRegisterPrivateKey fails Found by parfait 1.1 memory analyser: Memory leak of pointer 'pAdapt' allocated with malloc((88 * num_adaptors)) at line 162 of hw/xfree86/common/xf86xvmc.c in function 'xf86XvMCScreenInit'. 'pAdapt' allocated at line 158 with malloc((88 * num_adaptors)). Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer --- hw/xfree86/common/xf86xvmc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/xfree86/common/xf86xvmc.c b/hw/xfree86/common/xf86xvmc.c index 78a32bfe1..3169c054c 100644 --- a/hw/xfree86/common/xf86xvmc.c +++ b/hw/xfree86/common/xf86xvmc.c @@ -158,8 +158,10 @@ xf86XvMCScreenInit(ScreenPtr pScreen, if (!(pAdapt = malloc(sizeof(XvMCAdaptorRec) * num_adaptors))) return FALSE; - if (!dixRegisterPrivateKey(&XF86XvMCScreenKeyRec, PRIVATE_SCREEN, 0)) + if (!dixRegisterPrivateKey(&XF86XvMCScreenKeyRec, PRIVATE_SCREEN, 0)) { + free(pAdapt); return FALSE; + } if (!(pScreenPriv = malloc(sizeof(xf86XvMCScreenRec)))) { free(pAdapt); From 73974dd7ea9ca4d4cdd5464cb813088a6ee9770b Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Sun, 27 Jan 2013 15:42:02 -0800 Subject: [PATCH 08/25] Avoid memory leak in ddc resort() if find_header() fails Call find_header first, returning on failure before calling malloc. Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer --- hw/xfree86/ddc/ddc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/hw/xfree86/ddc/ddc.c b/hw/xfree86/ddc/ddc.c index 28c969646..44c1d535c 100644 --- a/hw/xfree86/ddc/ddc.c +++ b/hw/xfree86/ddc/ddc.c @@ -91,15 +91,16 @@ resort(unsigned char *s_block) unsigned char *d_new, *d_ptr, *d_end, *s_ptr, *s_end; unsigned char tmp; + s_ptr = find_header(s_block); + if (!s_ptr) + return NULL; s_end = s_block + EDID1_LEN; + d_new = malloc(EDID1_LEN); if (!d_new) return NULL; d_end = d_new + EDID1_LEN; - s_ptr = find_header(s_block); - if (!s_ptr) - return NULL; for (d_ptr = d_new; d_ptr < d_end; d_ptr++) { tmp = *(s_ptr++); *d_ptr = tmp; From 592d35aef0a8089a344543cf5a425e0537c0431b Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 14 Feb 2013 10:02:02 +1000 Subject: [PATCH 09/25] randr: fix "set but unused" warnings rrcrtc.c: In function 'RRCrtcDetachScanoutPixmap': rrcrtc.c:366:9: warning: variable 'ret' set but not used [-Wunused-but-set-variable] rrcrtc.c: In function 'rrCheckPixmapBounding': rrcrtc.c:505:13: warning: variable 'ret' set but not used [-Wunused-but-set-variable] rrcrtc.c:445:9: warning: unused variable 'i' [-Wunused-variable] Signed-off-by: Peter Hutterer Reviewed-by: Alan Coopersmith Reviewed-by: Mark Kettenis --- randr/rrcrtc.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c index 6e2eca5ad..721b05ac3 100644 --- a/randr/rrcrtc.c +++ b/randr/rrcrtc.c @@ -363,13 +363,12 @@ void RRCrtcDetachScanoutPixmap(RRCrtcPtr crtc) { ScreenPtr master = crtc->pScreen->current_master; - int ret; PixmapPtr mscreenpix; rrScrPriv(crtc->pScreen); mscreenpix = master->GetScreenPixmap(master); - ret = pScrPriv->rrCrtcSetScanoutPixmap(crtc, NULL); + pScrPriv->rrCrtcSetScanoutPixmap(crtc, NULL); if (crtc->scanout_pixmap) { master->StopPixmapTracking(mscreenpix, crtc->scanout_pixmap); /* @@ -442,7 +441,7 @@ rrCheckPixmapBounding(ScreenPtr pScreen, RRCrtcPtr rr_crtc, int x, int y, int w, int h) { RegionRec root_pixmap_region, total_region, new_crtc_region; - int i, c; + int c; BoxRec newbox; BoxPtr newsize; ScreenPtr slave; @@ -502,10 +501,8 @@ rrCheckPixmapBounding(ScreenPtr pScreen, new_height == screen_pixmap->drawable.height) { ErrorF("adjust shatters %d %d\n", newsize->x1, newsize->x2); } else { - int ret; rrScrPriv(pScreen); - ret = pScrPriv->rrScreenSetSize(pScreen, - new_width, new_height, 0, 0); + pScrPriv->rrScreenSetSize(pScreen, new_width, new_height, 0, 0); } /* set shatters TODO */ From 858d8b19b3a5bb59e5c5f9a9e68adce2495b5e31 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 14 Feb 2013 10:04:06 +1000 Subject: [PATCH 10/25] xfree86: drop unused prevSIGIO Unused as of 5d309af2ed93e91c7d72f548a11052051efbb40f Signed-off-by: Peter Hutterer Reviewed-by: Alan Coopersmith Reviewed-by: Mark Kettenis --- hw/xfree86/common/xf86Events.c | 1 - 1 file changed, 1 deletion(-) diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c index d92174edf..055223310 100644 --- a/hw/xfree86/common/xf86Events.c +++ b/hw/xfree86/common/xf86Events.c @@ -413,7 +413,6 @@ static void xf86VTSwitch(void) { int i; - static int prevSIGIO; InputInfoPtr pInfo; IHPtr ih; From 7b79a2e4a11b5c5f0ebaa495828725e235d2b08e Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 14 Feb 2013 10:06:55 +1000 Subject: [PATCH 11/25] fb: drop two unneeded shadowing variables fbpict.c: In function 'fbGlyphs': fbpict.c:188:6: warning: declaration of 'x' shadows a previous local [-Wshadow] fbpict.c:111:9: warning: shadowed declaration is here [-Wshadow] fbpict.c:188:9: warning: declaration of 'y' shadows a previous local [-Wshadow] fbpict.c:111:12: warning: shadowed declaration is here [-Wshadow] Signed-off-by: Peter Hutterer Reviewed-by: Alan Coopersmith Reviewed-by: Soren Sandmann Reviewed-by: Mark Kettenis --- fb/fbpict.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/fb/fbpict.c b/fb/fbpict.c index 2804ff481..b50385805 100644 --- a/fb/fbpict.c +++ b/fb/fbpict.c @@ -185,19 +185,15 @@ fbGlyphs(CARD8 op, if (maskFormat) { pixman_format_code_t format; pixman_box32_t extents; - int x, y; format = maskFormat->format | (maskFormat->depth << 24); pixman_glyph_get_extents(glyphCache, n_glyphs, pglyphs, &extents); - x = extents.x1; - y = extents.y1; - pixman_composite_glyphs(op, srcImage, dstImage, format, xSrc + srcXoff + xDst, ySrc + srcYoff + yDst, - x, y, - x + dstXoff, y + dstYoff, + extents.x1, extents.y1, + extents.x1 + dstXoff, extents.y1 + dstYoff, extents.x2 - extents.x1, extents.y2 - extents.y1, glyphCache, n_glyphs, pglyphs); From 8bbea9f48f43e54c55c8b60ea36bda3134a86af2 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 14 Feb 2013 10:09:53 +1000 Subject: [PATCH 12/25] Xext: renaming shadowing variable xvdisp.c: In function 'ProcXvStopVideo': xvdisp.c:712:11: warning: declaration of 'rc' shadows a previous local [-Wshadow] xvdisp.c:705:17: warning: shadowed declaration is here [-Wshadow] Signed-off-by: Peter Hutterer Reviewed-by: Alan Coopersmith Reviewed-by: Mark Kettenis --- Xext/xvdisp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Xext/xvdisp.c b/Xext/xvdisp.c index 31b77839f..787729387 100644 --- a/Xext/xvdisp.c +++ b/Xext/xvdisp.c @@ -702,7 +702,7 @@ ProcXvUngrabPort(ClientPtr client) static int ProcXvStopVideo(ClientPtr client) { - int status, rc; + int status, ret; DrawablePtr pDraw; XvPortPtr pPort; @@ -716,9 +716,9 @@ ProcXvStopVideo(ClientPtr client) return status; } - rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixWriteAccess); - if (rc != Success) - return rc; + ret = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixWriteAccess); + if (ret != Success) + return ret; return XvdiStopVideo(client, pPort, pDraw); } From 63d00c6b146d7f5fb80f20f19066088059042a5e Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 14 Feb 2013 10:13:53 +1000 Subject: [PATCH 13/25] Xext: rename two shadowing variables panoramiX.c: In function 'PanoramiXCreateConnectionBlock': panoramiX.c:599:10: warning: declaration of 'disableBackingStore' shadows a global declaration [-Wshadow] In file included from ../include/windowstr.h:60:0, from panoramiX.c:47: ../include/opaque.h:56:52: warning: shadowed declaration is here [-Wshadow] panoramiX.c: In function 'PanoramiXConsolidate': panoramiX.c:834:19: warning: declaration of 'pScreen' shadows a previous local [-Wshadow] panoramiX.c:813:15: warning: shadowed declaration is here [-Wshadow] Signed-off-by: Peter Hutterer Reviewed-by: Alan Coopersmith Reviewed-by: Mark Kettenis --- Xext/panoramiX.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Xext/panoramiX.c b/Xext/panoramiX.c index be475f7f4..7f888e38d 100644 --- a/Xext/panoramiX.c +++ b/Xext/panoramiX.c @@ -596,7 +596,7 @@ Bool PanoramiXCreateConnectionBlock(void) { int i, j, length; - Bool disableBackingStore = FALSE; + Bool disable_backing_store = FALSE; int old_width, old_height; float width_mult, height_mult; xWindowRoot *root; @@ -622,10 +622,10 @@ PanoramiXCreateConnectionBlock(void) } if (pScreen->backingStoreSupport != screenInfo.screens[0]->backingStoreSupport) - disableBackingStore = TRUE; + disable_backing_store = TRUE; } - if (disableBackingStore) { + if (disable_backing_store) { for (i = 0; i < screenInfo.numScreens; i++) { pScreen = screenInfo.screens[i]; pScreen->backingStoreSupport = NotUseful; @@ -831,15 +831,15 @@ PanoramiXConsolidate(void) saver->type = XRT_WINDOW; FOR_NSCREENS(i) { - ScreenPtr pScreen = screenInfo.screens[i]; + ScreenPtr scr = screenInfo.screens[i]; - root->info[i].id = pScreen->root->drawable.id; + root->info[i].id = scr->root->drawable.id; root->u.win.class = InputOutput; root->u.win.root = TRUE; - saver->info[i].id = pScreen->screensaver.wid; + saver->info[i].id = scr->screensaver.wid; saver->u.win.class = InputOutput; saver->u.win.root = TRUE; - defmap->info[i].id = pScreen->defColormap; + defmap->info[i].id = scr->defColormap; } AddResource(root->info[0].id, XRT_WINDOW, root); From 6133c417595a9c8fc158b0d68fd4a7a2c58fdc47 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 14 Feb 2013 10:15:33 +1000 Subject: [PATCH 14/25] xkb: remove unused variable 'names' xkb.c: In function '_XkbSetNamesCheck': xkb.c:3987:18: warning: variable 'names' set but not used [-Wunused-but-set-variable] Signed-off-by: Peter Hutterer Reviewed-by: Alan Coopersmith Reviewed-by: Mark Kettenis --- xkb/xkb.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/xkb/xkb.c b/xkb/xkb.c index 7e51e4080..f2bcaee41 100644 --- a/xkb/xkb.c +++ b/xkb/xkb.c @@ -3984,13 +3984,11 @@ _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev, xkbSetNamesReq * stuff, CARD32 *data) { XkbDescRec *xkb; - XkbNamesRec *names; CARD32 *tmp; Atom bad; tmp = data; xkb = dev->key->xkbInfo->desc; - names = xkb->names; if (stuff->which & XkbKeyTypeNamesMask) { int i; From 82425c66e7a8c436b5be7ad44880dd4be6c1f06a Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 14 Feb 2013 10:21:47 +1000 Subject: [PATCH 15/25] xfree86: remove redundant declaration of inputInfo xf86Cursor.c:19:18: warning: redundant redeclaration of 'inputInfo' [-Wredundant-decls] In file included from xf86Cursor.c:18:0: ../../../include/inputstr.h:614:57: note: previous declaration of 'inputInfo' was here Signed-off-by: Peter Hutterer Reviewed-by: Alan Coopersmith Reviewed-by: Mark Kettenis --- hw/xfree86/ramdac/xf86Cursor.c | 1 - 1 file changed, 1 deletion(-) diff --git a/hw/xfree86/ramdac/xf86Cursor.c b/hw/xfree86/ramdac/xf86Cursor.c index 8d48a7542..d32aac1cf 100644 --- a/hw/xfree86/ramdac/xf86Cursor.c +++ b/hw/xfree86/ramdac/xf86Cursor.c @@ -16,7 +16,6 @@ * Externing inputInfo is not the nice way to do it but it works. */ #include "inputstr.h" -extern InputInfo inputInfo; DevPrivateKeyRec xf86CursorScreenKeyRec; From f9198e278becec158b570204cf9fc1de822ac76b Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 27 Feb 2012 16:43:10 +1000 Subject: [PATCH 16/25] dix: FreeAllAtoms() on reset ==5712== 6 bytes in 1 blocks are still reachable in loss record 17 of 585 ==5712== at 0x4A074CD: malloc (vg_replace_malloc.c:236) ==5712== by 0x3D1DE885B1: strndup (strndup.c:46) ==5712== by 0x41CB71: MakeAtom (atom.c:121) ==5712== by 0x55AE3E: XIGetKnownProperty (xiproperty.c:401) ==5712== by 0x4251C9: AddInputDevice (devices.c:312) ==5712== by 0x42AC0C: AllocDevicePair (devices.c:2657) ==5712== by 0x425E6E: InitCoreDevices (devices.c:677) ==5712== by 0x5ACA05: main (main.c:257) Signed-off-by: Peter Hutterer Reviewed-by: Chase Douglas --- dix/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dix/main.c b/dix/main.c index fb935c969..bea1a8d5a 100644 --- a/dix/main.c +++ b/dix/main.c @@ -357,6 +357,8 @@ main(int argc, char *argv[], char *envp[]) FreeFonts(); + FreeAllAtoms(); + FreeAuditTimer(); if (dispatchException & DE_TERMINATE) { From 3aac7a59dc6ef2d8bbf46ba5d37acdf6013e9450 Mon Sep 17 00:00:00 2001 From: Daniel Martin Date: Tue, 11 Dec 2012 17:23:55 +0100 Subject: [PATCH 17/25] ephyr: Add -resizeable option With this option passed, ephyr windows can be resized like normal windows on the fly, without the need of an explicit parent window. Signed-off-by: Daniel Martin Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- hw/kdrive/ephyr/ephyr.c | 1 + hw/kdrive/ephyr/ephyrinit.c | 6 ++++++ hw/kdrive/ephyr/hostx.c | 32 +++++++++++++++++++++----------- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c index e6520d035..f32e43285 100644 --- a/hw/kdrive/ephyr/ephyr.c +++ b/hw/kdrive/ephyr/ephyr.c @@ -56,6 +56,7 @@ typedef struct _EphyrInputPrivate { } EphyrKbdPrivate, EphyrPointerPrivate; Bool EphyrWantGrayScale = 0; +Bool EphyrWantResize = 0; Bool ephyrInitialize(KdCardInfo * card, EphyrPriv * priv) diff --git a/hw/kdrive/ephyr/ephyrinit.c b/hw/kdrive/ephyr/ephyrinit.c index 5e2eb672f..adacac949 100644 --- a/hw/kdrive/ephyr/ephyrinit.c +++ b/hw/kdrive/ephyr/ephyrinit.c @@ -31,6 +31,7 @@ extern Window EphyrPreExistingHostWin; extern Bool EphyrWantGrayScale; +extern Bool EphyrWantResize; extern Bool kdHasPointer; extern Bool kdHasKbd; @@ -116,6 +117,7 @@ ddxUseMsg(void) ErrorF("-host-cursor Re-use exisiting X host server cursor\n"); ErrorF("-fullscreen Attempt to run Xephyr fullscreen\n"); ErrorF("-grayscale Simulate 8bit grayscale\n"); + ErrorF("-resizeable Make Xephyr windows resizeable\n"); ErrorF ("-fakexa Simulate acceleration using software rendering\n"); ErrorF("-verbosity Set log verbosity level\n"); @@ -210,6 +212,10 @@ ddxProcessArgument(int argc, char **argv, int i) EphyrWantGrayScale = 1; return 1; } + else if (!strcmp(argv[i], "-resizeable")) { + EphyrWantResize = 1; + return 1; + } else if (!strcmp(argv[i], "-fakexa")) { ephyrFuncs.initAccel = ephyrDrawInit; ephyrFuncs.enableAccel = ephyrDrawEnable; diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c index aed0285b6..c8642cbe9 100644 --- a/hw/kdrive/ephyr/hostx.c +++ b/hw/kdrive/ephyr/hostx.c @@ -117,6 +117,8 @@ extern EphyrKeySyms ephyrKeySyms; extern int monitorResolution; +extern Bool EphyrWantResize; + char *ephyrResName = NULL; int ephyrResNameFromCmd = 0; char *ephyrTitle = NULL; @@ -697,7 +699,7 @@ hostx_screen_init(EphyrScreenInfo screen, XResizeWindow(HostX.dpy, host_screen->win, width, height); /* Ask the WM to keep our size static */ - if (host_screen->win_pre_existing == None) { + if (host_screen->win_pre_existing == None && !EphyrWantResize) { size_hints = XAllocSizeHints(); size_hints->max_width = size_hints->min_width = width; size_hints->max_height = size_hints->min_height = height; @@ -1012,19 +1014,27 @@ hostx_get_event(EphyrHostXEvent * ev) case ConfigureNotify: { - struct EphyrHostScreen *host_screen = - host_screen_from_window(xev.xconfigure.window); + struct EphyrHostScreen *host_screen; - if (host_screen && host_screen->win_pre_existing != None) { - ev->type = EPHYR_EV_CONFIGURE; - ev->data.configure.width = xev.xconfigure.width; - ev->data.configure.height = xev.xconfigure.height; - ev->data.configure.window = xev.xconfigure.window; - ev->data.configure.screen = host_screen->mynum; - return 1; + /* event compression as for Expose events, cause + * we don't want to resize the framebuffer for + * every single change */ + while (XCheckTypedWindowEvent(HostX.dpy, xev.xconfigure.window, + ConfigureNotify, &xev)); + host_screen = host_screen_from_window(xev.xconfigure.window); + + if (!host_screen || + (host_screen->win_pre_existing == None && !EphyrWantResize)) { + return 0; } - return 0; + ev->type = EPHYR_EV_CONFIGURE; + ev->data.configure.width = xev.xconfigure.width; + ev->data.configure.height = xev.xconfigure.height; + ev->data.configure.window = xev.xconfigure.window; + ev->data.configure.screen = host_screen->mynum; + + return 1; } default: break; From e27b2e61632b220ddc36d0d0387581a9f4774f21 Mon Sep 17 00:00:00 2001 From: Peter Harris Date: Tue, 19 Feb 2013 16:08:52 -0500 Subject: [PATCH 18/25] xkb: Set nIndicators in XkbGetIndicatorMap Xlib doesn't use this value (it computes it from the reply length instead) which is why nobody has noticed yet. But the spec http://www.x.org/releases/X11R7.7/doc/kbproto/xkbproto.html says that it should be set. Signed-off-by: Peter Harris Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- xkb/xkb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/xkb/xkb.c b/xkb/xkb.c index f2bcaee41..c78aceb78 100644 --- a/xkb/xkb.c +++ b/xkb/xkb.c @@ -3073,6 +3073,7 @@ XkbComputeGetIndicatorMapReplySize(XkbIndicatorPtr indicators, nIndicators++; } rep->length = (nIndicators * SIZEOF(xkbIndicatorMapWireDesc)) / 4; + rep->nIndicators = nIndicators; return Success; } From e21e183059df5975e7086850d1931edb2c1bbd06 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Thu, 21 Feb 2013 09:02:44 +1000 Subject: [PATCH 19/25] os: use libunwind to generate backtraces Libunwind generates backtraces much more reliably than glibc's "backtrace". Before: 0: /opt/xserver/bin/X (0x400000+0x18ce36) [0x58ce36] 1: /opt/xserver/bin/X (xorg_backtrace+0x9) [0x58d119] 2: /opt/xserver/bin/X (0x400000+0x190d69) [0x590d69] 3: /lib64/libpthread.so.0 (0x7fb904268000+0x10a90) [0x7fb904278a90] 4: /lib64/libc.so.6 (ioctl+0x7) [0x7fb902fbf987] 5: /usr/lib64/libdrm.so.2 (drmIoctl+0x28) [0x7fb90405ffa8] 6: /usr/lib64/libdrm.so.2 (drmCommandWrite+0x1b) [0x7fb90406235b] 7: /usr/lib64/libdrm_nouveau.so.2 (nouveau_bo_wait+0x89) [0x7fb902009719] 8: /opt/xserver/lib/xorg/modules/drivers/nouveau_drv.so (0x7fb90220e000+0x76f3) [0x7fb9022156f3] 9: /opt/xserver/lib/xorg/modules/libexa.so (0x7fb9019c7000+0xbae0) [0x7fb9019d2ae0] 10: /opt/xserver/bin/X (0x400000+0x17d2b3) [0x57d2b3] 11: /opt/xserver/bin/X (0x400000+0xc9930) [0x4c9930] 12: /opt/xserver/bin/X (0x400000+0x3a81a) [0x43a81a] 13: /opt/xserver/bin/X (0x400000+0x3d6a1) [0x43d6a1] 14: /opt/xserver/bin/X (0x400000+0x2c2ca) [0x42c2ca] 15: /lib64/libc.so.6 (__libc_start_main+0xf5) [0x7fb902f019b5] 16: /opt/xserver/bin/X (0x400000+0x2c60d) [0x42c60d] 17: ?? [0x0] After: 0: /opt/xserver/bin/X (OsSigHandler+0x39) [0x590d69] 1: /lib64/libpthread.so.0 (__restore_rt+0x0) [0x7fb904278a8f] 2: /lib64/libc.so.6 (ioctl+0x7) [0x7fb902fbf987] 3: /usr/lib64/libdrm.so.2 (drmIoctl+0x28) [0x7fb90405ffa8] 4: /usr/lib64/libdrm.so.2 (drmCommandWrite+0x1b) [0x7fb90406235b] 5: /usr/lib64/libdrm_nouveau.so.2 (nouveau_bo_wait+0x89) [0x7fb902009719] 6: /opt/xserver/lib/xorg/modules/drivers/nouveau_drv.so (nouveau_exa_download_from_screen+0x1a3) [0x7fb9022156f3] 7: /opt/xserver/lib/xorg/modules/libexa.so (exaGetImage+0x1f0) [0x7fb9019d2ae0] 8: /opt/xserver/bin/X (miSpriteGetImage+0x173) [0x57d2b3] 9: /opt/xserver/bin/X (compGetImage+0xb0) [0x4c9930] 10: /opt/xserver/bin/X (ProcGetImage+0x55a) [0x43a81a] 11: /opt/xserver/bin/X (Dispatch+0x341) [0x43d6a1] 12: /opt/xserver/bin/X (main+0x3ba) [0x42c2ca] 13: /lib64/libc.so.6 (__libc_start_main+0xf5) [0x7fb902f019b5] 14: /opt/xserver/bin/X (_start+0x29) [0x42c60d] 15: ? (?+0x29) [0x29] Signed-off-by: Marcin Slusarz Reviewed-by: Peter Hutterer Tested-by: Knut Petersen --- configure.ac | 9 ++++- include/dix-config.h.in | 3 ++ os/Makefile.am | 5 +++ os/backtrace.c | 75 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 91 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 53335b1d1..8b9cbc913 100644 --- a/configure.ac +++ b/configure.ac @@ -308,6 +308,13 @@ AC_CHECK_HEADER([execinfo.h],[ ])] ) +PKG_CHECK_MODULES(LIBUNWIND, libunwind, [HAVE_LIBUNWIND=yes], [HAVE_LIBUNWIND=no]) +if test "x$HAVE_LIBUNWIND" = xyes; then + AC_DEFINE(HAVE_LIBUNWIND, 1, [Have libunwind support]) +fi +AM_CONDITIONAL(HAVE_LIBUNWIND, [test "x$HAVE_LIBUNWIND" = xyes]) + + dnl --------------------------------------------------------------------------- dnl Bus options and CPU capabilities. Replaces logic in dnl hw/xfree86/os-support/bus/Makefile.am, among others. @@ -1336,7 +1343,7 @@ AC_DEFINE(BIGREQS, 1, [Support BigRequests extension]) if test "x$SPECIAL_DTRACE_OBJECTS" = "xyes" ; then DIX_LIB='$(top_builddir)/dix/dix.O' - OS_LIB='$(top_builddir)/os/os.O $(SHA1_LIBS) $(DLOPEN_LIBS)' + OS_LIB='$(top_builddir)/os/os.O $(SHA1_LIBS) $(DLOPEN_LIBS) $(LIBUNWIND_LIBS)' else DIX_LIB='$(top_builddir)/dix/libdix.la' OS_LIB='$(top_builddir)/os/libos.la' diff --git a/include/dix-config.h.in b/include/dix-config.h.in index e1cb9eb51..a643dfcc8 100644 --- a/include/dix-config.h.in +++ b/include/dix-config.h.in @@ -60,6 +60,9 @@ /* Has backtrace support */ #undef HAVE_BACKTRACE +/* Has libunwind support */ +#undef HAVE_LIBUNWIND + /* Define to 1 if you have the header file. */ #undef HAVE_BYTESWAP_H diff --git a/os/Makefile.am b/os/Makefile.am index 88914852f..364b6da2d 100644 --- a/os/Makefile.am +++ b/os/Makefile.am @@ -34,6 +34,11 @@ if XDMCP libos_la_SOURCES += $(XDMCP_SRCS) endif +if HAVE_LIBUNWIND +AM_CFLAGS += $(LIBUNWIND_CFLAGS) +libos_la_LIBADD += $(LIBUNWIND_LIBS) +endif + EXTRA_DIST = $(SECURERPC_SRCS) $(XDMCP_SRCS) if SPECIAL_DTRACE_OBJECTS diff --git a/os/backtrace.c b/os/backtrace.c index daac60cf6..426f9b15b 100644 --- a/os/backtrace.c +++ b/os/backtrace.c @@ -30,6 +30,80 @@ #include #include +#ifdef HAVE_LIBUNWIND + +#define UNW_LOCAL_ONLY +#include + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include + +void +xorg_backtrace(void) +{ + unw_cursor_t cursor; + unw_context_t context; + unw_word_t off; + unw_proc_info_t pip; + int ret, i = 0; + char procname[256]; + const char *filename; + Dl_info dlinfo; + + pip.unwind_info = NULL; + ret = unw_getcontext(&context); + if (ret) { + ErrorFSigSafe("unw_getcontext failed: %s [%d]\n", unw_strerror(ret), + ret); + return; + } + + ret = unw_init_local(&cursor, &context); + if (ret) { + ErrorFSigSafe("unw_init_local failed: %s [%d]\n", unw_strerror(ret), + ret); + return; + } + + ErrorFSigSafe("\n"); + ErrorFSigSafe("Backtrace:\n"); + ret = unw_step(&cursor); + while (ret > 0) { + ret = unw_get_proc_info(&cursor, &pip); + if (ret) { + ErrorFSigSafe("unw_get_proc_info failed: %s [%d]\n", + unw_strerror(ret), ret); + break; + } + + ret = unw_get_proc_name(&cursor, procname, 256, &off); + if (ret && ret != -UNW_ENOMEM) { + if (ret != -UNW_EUNSPEC) + ErrorFSigSafe("unw_get_proc_name failed: %s [%d]\n", + unw_strerror(ret), ret); + procname[0] = '?'; + procname[1] = 0; + } + + if (dladdr((void *)(pip.start_ip + off), &dlinfo) && dlinfo.dli_fname && + *dlinfo.dli_fname) + filename = dlinfo.dli_fname; + else + filename = "?"; + + ErrorFSigSafe("%u: %s (%s%s+0x%x) [%p]\n", i++, filename, procname, + ret == -UNW_ENOMEM ? "..." : "", (int)off, + (void *)(pip.start_ip + off)); + + ret = unw_step(&cursor); + if (ret < 0) + ErrorFSigSafe("unw_step failed: %s [%d]\n", unw_strerror(ret), ret); + } + ErrorFSigSafe("\n"); +} +#else /* HAVE_LIBUNWIND */ #ifdef HAVE_BACKTRACE #ifndef _GNU_SOURCE #define _GNU_SOURCE @@ -246,3 +320,4 @@ xorg_backtrace(void) #endif #endif +#endif From bd58ebe4cf3b0ce60f87fb26a3715f774dabd349 Mon Sep 17 00:00:00 2001 From: Daniel Martin Date: Thu, 20 Dec 2012 13:50:17 +0100 Subject: [PATCH 20/25] ephyr: Fix crash on 24bpp host framebuffer Use bytes_per_line and bits_per_pixel from the created XImage to fix https://bugzilla.redhat.com/show_bug.cgi?id=518960 Signed-off-by: Daniel Martin Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- hw/kdrive/ephyr/ephyr.c | 6 ++---- hw/kdrive/ephyr/hostx.c | 6 +++++- hw/kdrive/ephyr/hostx.h | 3 ++- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c index f32e43285..02d497073 100644 --- a/hw/kdrive/ephyr/ephyr.c +++ b/hw/kdrive/ephyr/ephyr.c @@ -238,13 +238,11 @@ ephyrMapFramebuffer(KdScreenInfo * screen) KdComputePointerMatrix(&m, ephyrRandr, screen->width, screen->height); KdSetPointerMatrix(&m); - priv->bytes_per_line = - ((screen->width * screen->fb.bitsPerPixel + 31) >> 5) << 2; - buffer_height = ephyrBufferHeight(screen); priv->base = - hostx_screen_init(screen, screen->width, screen->height, buffer_height); + hostx_screen_init(screen, screen->width, screen->height, buffer_height, + &priv->bytes_per_line, &screen->fb.bitsPerPixel); if ((scrpriv->randr & RR_Rotate_0) && !(scrpriv->randr & RR_Reflect_All)) { scrpriv->shadow = FALSE; diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c index c8642cbe9..f2b458d90 100644 --- a/hw/kdrive/ephyr/hostx.c +++ b/hw/kdrive/ephyr/hostx.c @@ -619,7 +619,8 @@ hostx_set_cmap_entry(unsigned char idx, */ void * hostx_screen_init(EphyrScreenInfo screen, - int width, int height, int buffer_height) + int width, int height, int buffer_height, + int *bytes_per_line, int *bits_per_pixel) { int bitmap_pad; Bool shm_success = False; @@ -696,6 +697,9 @@ hostx_screen_init(EphyrScreenInfo screen, malloc(host_screen->ximg->bytes_per_line * buffer_height); } + *bytes_per_line = host_screen->ximg->bytes_per_line; + *bits_per_pixel = host_screen->ximg->bits_per_pixel; + XResizeWindow(HostX.dpy, host_screen->win, width, height); /* Ask the WM to keep our size static */ diff --git a/hw/kdrive/ephyr/hostx.h b/hw/kdrive/ephyr/hostx.h index 31c4053aa..38b7b3768 100644 --- a/hw/kdrive/ephyr/hostx.h +++ b/hw/kdrive/ephyr/hostx.h @@ -193,7 +193,8 @@ hostx_set_cmap_entry(unsigned char idx, unsigned char r, unsigned char g, unsigned char b); void *hostx_screen_init(EphyrScreenInfo screen, - int width, int height, int buffer_height); + int width, int height, int buffer_height, + int *bytes_per_line, int *bits_per_pixel); void From c100211034ab69ce453a1644fb61c6808d7e3eda Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 18 Dec 2012 14:12:40 +1000 Subject: [PATCH 21/25] dix: only show the cursor if a window defines one (#58398) e02f864fdf "Suppress cursor display until the first XDefineCursor() request" disabled cursor display a priori unless -retro is given. On a plain server, caling XFixesHideCursor() and XFixesShowCursor() would show the default root cursor, despite no client actually defining a cursor. Change the logic, disable CursorVisible by default and only enable it from the window's CWCursor logic. If no window ever defines a cursor, said cursor stays invisible. X.Org Bug 58398 Signed-off-by: Peter Hutterer Tested-by: Bastien Nocera Reviewed-by: Daniel Martin --- dix/window.c | 4 ++++ include/input.h | 5 +++++ xfixes/cursor.c | 10 ++-------- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/dix/window.c b/dix/window.c index a5b28a630..a9297f3c8 100644 --- a/dix/window.c +++ b/dix/window.c @@ -1431,6 +1431,8 @@ ChangeWindowAttributes(WindowPtr pWin, Mask vmask, XID *vlist, ClientPtr client) } } + CursorVisible = TRUE; + if (pWin->realized) WindowHasNewCursor(pWin); @@ -3430,6 +3432,8 @@ ChangeWindowDeviceCursor(WindowPtr pWin, DeviceIntPtr pDev, CursorPtr pCursor) } out: + CursorVisible = TRUE; + if (pWin->realized) WindowHasNewCursor(pWin); diff --git a/include/input.h b/include/input.h index 5c65597e4..304895ffc 100644 --- a/include/input.h +++ b/include/input.h @@ -638,6 +638,11 @@ extern _X_HIDDEN void valuator_set_mode(DeviceIntPtr dev, int axis, int mode); xfixes/cursor.c uses it to determine if the cursor is enabled */ extern Bool EnableCursor; +/* Set to FALSE by default - ChangeWindowAttributes sets it to TRUE on + * CWCursor, xfixes/cursor.c uses it to determine if the cursor is enabled + */ +extern Bool CursorVisible; + extern _X_EXPORT ValuatorMask *valuator_mask_new(int num_valuators); extern _X_EXPORT void valuator_mask_free(ValuatorMask **mask); extern _X_EXPORT void valuator_mask_set_range(ValuatorMask *mask, diff --git a/xfixes/cursor.c b/xfixes/cursor.c index 568e717fa..90a026b28 100644 --- a/xfixes/cursor.c +++ b/xfixes/cursor.c @@ -129,8 +129,7 @@ typedef struct _CursorScreen { #define Unwrap(as,s,elt,backup) (((backup) = (s)->elt), (s)->elt = (as)->elt) /* The cursor doesn't show up until the first XDefineCursor() */ -static Bool CursorVisible = FALSE; - +Bool CursorVisible = FALSE; Bool EnableCursor = TRUE; static Bool @@ -142,12 +141,7 @@ CursorDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) Unwrap(cs, pScreen, DisplayCursor, backupProc); - /* - * Have to check ConnectionInfo to distinguish client requests from - * initial root window setup. Not a great way to do it, I admit. - */ - if (ConnectionInfo) - CursorVisible = EnableCursor; + CursorVisible = CursorVisible && EnableCursor; if (cs->pCursorHideCounts != NULL || !CursorVisible) { ret = (*pScreen->DisplayCursor) (pDev, pScreen, NullCursor); From 44fc062f85df7288c17d2d64b73aa4957b91fd6d Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 18 Feb 2013 14:57:58 +1000 Subject: [PATCH 22/25] os: document pnprintf as sigsafe snprintf Signed-off-by: Peter Hutterer --- os/log.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/os/log.c b/os/log.c index 95bd8cca9..dc6e2888b 100644 --- a/os/log.c +++ b/os/log.c @@ -279,6 +279,10 @@ LogSetParameter(LogParameter param, int value) } } +/** + * Signal-safe snprintf, with some limitations over snprintf. Be careful + * which directives you use. + */ static int pnprintf(char *string, size_t size, const char *f, va_list args) { From 4149ee8ec0193acbf3812c7ee2627b93b9a89997 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 15 Feb 2013 11:19:08 +1000 Subject: [PATCH 23/25] kdrive: fix "set but not used" warnings kinput.c: In function 'KdEnqueueKeyboardEvent': kinput.c:1845:16: warning: variable 'ctrl' set but not used kinput.c:1844:17: warning: variable 'keyc' set but not used kinput.c: In function 'KdEnqueuePointerEvent': kinput.c:1887:12: warning: variable 'ms' set but not used kxv.c: In function 'KdXVDisable': kxv.c:1181:19: warning: variable 'ScreenPriv' set but not used mouse.c: In function 'ps2SkipInit': mouse.c:444:9: warning: variable 'skipping' set but not used mouse.c: In function 'ps2Init': mouse.c:473:10: warning: variable 'waiting' set but not used mouse.c:472:9: warning: variable 'skipping' set but not used fbdev.c: In function 'fbdevRandRSetConfig': fbdev.c:468:19: warning: variable 'newheight' set but not used fbdev.c:468:9: warning: variable 'newwidth' set but not used Signed-off-by: Peter Hutterer Reviewed-by: Robert Morell --- hw/kdrive/fbdev/fbdev.c | 10 ---------- hw/kdrive/linux/mouse.c | 6 ------ hw/kdrive/src/kinput.c | 8 -------- hw/kdrive/src/kxv.c | 2 -- 4 files changed, 26 deletions(-) diff --git a/hw/kdrive/fbdev/fbdev.c b/hw/kdrive/fbdev/fbdev.c index fd14afa92..fb6e3a292 100644 --- a/hw/kdrive/fbdev/fbdev.c +++ b/hw/kdrive/fbdev/fbdev.c @@ -465,16 +465,6 @@ fbdevRandRSetConfig(ScreenPtr pScreen, int oldheight; int oldmmwidth; int oldmmheight; - int newwidth, newheight; - - if (screen->randr & (RR_Rotate_0 | RR_Rotate_180)) { - newwidth = pSize->width; - newheight = pSize->height; - } - else { - newwidth = pSize->height; - newheight = pSize->width; - } if (wasEnabled) KdDisableScreen(pScreen); diff --git a/hw/kdrive/linux/mouse.c b/hw/kdrive/linux/mouse.c index c87507790..f4424478a 100644 --- a/hw/kdrive/linux/mouse.c +++ b/hw/kdrive/linux/mouse.c @@ -441,10 +441,8 @@ ps2SkipInit(KdPointerInfo * pi, int ninit, Bool ret_next) { Kmouse *km = pi->driverPrivate; int c = -1; - int skipping; Bool waiting; - skipping = 0; waiting = FALSE; while (ninit || ret_next) { c = MouseReadByte(&km->iob, MOUSE_TIMEOUT); @@ -469,8 +467,6 @@ static Bool ps2Init(KdPointerInfo * pi) { Kmouse *km = pi->driverPrivate; - int skipping; - Bool waiting; int id; unsigned char *init; int ninit; @@ -483,8 +479,6 @@ ps2Init(KdPointerInfo * pi) */ if (!MouseWriteByte(km->iob.fd, PSMC_SEND_DEV_ID, 100)) return FALSE; - skipping = 0; - waiting = FALSE; id = ps2SkipInit(pi, 0, TRUE); switch (id) { case 3: diff --git a/hw/kdrive/src/kinput.c b/hw/kdrive/src/kinput.c index b1068bbee..c30f1708d 100644 --- a/hw/kdrive/src/kinput.c +++ b/hw/kdrive/src/kinput.c @@ -1821,16 +1821,11 @@ KdEnqueueKeyboardEvent(KdKeyboardInfo * ki, unsigned char scan_code, unsigned char is_up) { unsigned char key_code; - KeyClassPtr keyc = NULL; - KeybdCtrl *ctrl = NULL; int type; if (!ki || !ki->dixdev || !ki->dixdev->kbdfeed || !ki->dixdev->key) return; - keyc = ki->dixdev->key; - ctrl = &ki->dixdev->kbdfeed->ctrl; - if (scan_code >= ki->minScanCode && scan_code <= ki->maxScanCode) { key_code = scan_code + KD_MIN_KEYCODE - ki->minScanCode; @@ -1864,7 +1859,6 @@ void KdEnqueuePointerEvent(KdPointerInfo * pi, unsigned long flags, int rx, int ry, int rz) { - CARD32 ms; unsigned char buttons; int x, y, z; int (*matrix)[3] = kdPointerMatrix.matrix; @@ -1875,8 +1869,6 @@ KdEnqueuePointerEvent(KdPointerInfo * pi, unsigned long flags, int rx, int ry, if (!pi) return; - ms = GetTimeInMillis(); - /* we don't need to transform z, so we don't. */ if (flags & KD_MOUSE_DELTA) { if (pi->transformCoordinates) { diff --git a/hw/kdrive/src/kxv.c b/hw/kdrive/src/kxv.c index cf656363d..22639728d 100644 --- a/hw/kdrive/src/kxv.c +++ b/hw/kdrive/src/kxv.c @@ -1174,7 +1174,6 @@ void KdXVDisable(ScreenPtr pScreen) { XvScreenPtr pxvs; - KdXVScreenPtr ScreenPriv; XvAdaptorPtr pAdaptor; XvPortPtr pPort; XvPortRecPrivatePtr pPriv; @@ -1184,7 +1183,6 @@ KdXVDisable(ScreenPtr pScreen) return; pxvs = GET_XV_SCREEN(pScreen); - ScreenPriv = GET_KDXV_SCREEN(pScreen); for (i = 0; i < pxvs->nAdaptors; i++) { pAdaptor = &pxvs->pAdaptors[i]; From eadda231091aa6feb68207ee22f6bc3a390d4556 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 15 Feb 2013 11:19:09 +1000 Subject: [PATCH 24/25] xephyr: fix "set but not used warnings" ephyrvideo.c: In function 'ephyrPutVideo': ephyrvideo.c:1009:42: warning: variable 'drw_h' set but not used ephyrvideo.c:1009:31: warning: variable 'drw_w' set but not used ephyrvideo.c:1009:20: warning: variable 'drw_y' set but not used ephyrvideo.c:1009:9: warning: variable 'drw_x' set but not used ephyrvideo.c: In function 'ephyrGetVideo': ephyrvideo.c:1058:42: warning: variable 'drw_h' set but not used ephyrvideo.c:1058:31: warning: variable 'drw_w' set but not used ephyrvideo.c:1058:20: warning: variable 'drw_y' set but not used ephyrvideo.c:1058:9: warning: variable 'drw_x' set but not used ephyrvideo.c: In function 'ephyrPutStill': ephyrvideo.c:1107:42: warning: variable 'drw_h' set but not used ephyrvideo.c:1107:31: warning: variable 'drw_w' set but not used ephyrvideo.c:1107:20: warning: variable 'drw_y' set but not used ephyrvideo.c:1107:9: warning: variable 'drw_x' set but not used ephyrvideo.c: In function 'ephyrGetStill': ephyrvideo.c:1156:42: warning: variable 'drw_h' set but not used ephyrvideo.c:1156:31: warning: variable 'drw_w' set but not used ephyrvideo.c:1156:20: warning: variable 'drw_y' set but not used ephyrvideo.c:1156:9: warning: variable 'drw_x' set but not used Signed-off-by: Peter Hutterer Reviewed-by: Robert Morell --- hw/kdrive/ephyr/ephyrvideo.c | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/hw/kdrive/ephyr/ephyrvideo.c b/hw/kdrive/ephyr/ephyrvideo.c index 55dbd2e3a..dfc29f533 100644 --- a/hw/kdrive/ephyr/ephyrvideo.c +++ b/hw/kdrive/ephyr/ephyrvideo.c @@ -1006,7 +1006,6 @@ ephyrPutVideo(KdScreenInfo * a_info, EphyrPortPriv *port_priv = a_port_priv; BoxRec clipped_area, dst_box; int result = BadImplementation; - int drw_x = 0, drw_y = 0, drw_w = 0, drw_h = 0; EPHYR_RETURN_VAL_IF_FAIL(a_info->pScreen, BadValue); EPHYR_RETURN_VAL_IF_FAIL(a_drawable && port_priv, BadValue); @@ -1024,11 +1023,6 @@ ephyrPutVideo(KdScreenInfo * a_info, goto out; } - drw_x = clipped_area.x1; - drw_y = clipped_area.y1; - drw_w = clipped_area.x2 - clipped_area.x1; - drw_h = clipped_area.y2 - clipped_area.y1; - if (!ephyrHostXVPutVideo(a_info->pScreen->myNum, port_priv->port_number, a_vid_x, a_vid_y, a_vid_w, a_vid_h, @@ -1055,7 +1049,6 @@ ephyrGetVideo(KdScreenInfo * a_info, EphyrPortPriv *port_priv = a_port_priv; BoxRec clipped_area, dst_box; int result = BadImplementation; - int drw_x = 0, drw_y = 0, drw_w = 0, drw_h = 0; EPHYR_RETURN_VAL_IF_FAIL(a_info && a_info->pScreen, BadValue); EPHYR_RETURN_VAL_IF_FAIL(a_drawable && port_priv, BadValue); @@ -1073,11 +1066,6 @@ ephyrGetVideo(KdScreenInfo * a_info, goto out; } - drw_x = clipped_area.x1; - drw_y = clipped_area.y1; - drw_w = clipped_area.x2 - clipped_area.x1; - drw_h = clipped_area.y2 - clipped_area.y1; - if (!ephyrHostXVGetVideo(a_info->pScreen->myNum, port_priv->port_number, a_vid_x, a_vid_y, a_vid_w, a_vid_h, @@ -1104,7 +1092,6 @@ ephyrPutStill(KdScreenInfo * a_info, EphyrPortPriv *port_priv = a_port_priv; BoxRec clipped_area, dst_box; int result = BadImplementation; - int drw_x = 0, drw_y = 0, drw_w = 0, drw_h = 0; EPHYR_RETURN_VAL_IF_FAIL(a_info && a_info->pScreen, BadValue); EPHYR_RETURN_VAL_IF_FAIL(a_drawable && port_priv, BadValue); @@ -1122,11 +1109,6 @@ ephyrPutStill(KdScreenInfo * a_info, goto out; } - drw_x = clipped_area.x1; - drw_y = clipped_area.y1; - drw_w = clipped_area.x2 - clipped_area.x1; - drw_h = clipped_area.y2 - clipped_area.y1; - if (!ephyrHostXVPutStill(a_info->pScreen->myNum, port_priv->port_number, a_vid_x, a_vid_y, a_vid_w, a_vid_h, @@ -1153,7 +1135,6 @@ ephyrGetStill(KdScreenInfo * a_info, EphyrPortPriv *port_priv = a_port_priv; BoxRec clipped_area, dst_box; int result = BadImplementation; - int drw_x = 0, drw_y = 0, drw_w = 0, drw_h = 0; EPHYR_RETURN_VAL_IF_FAIL(a_info && a_info->pScreen, BadValue); EPHYR_RETURN_VAL_IF_FAIL(a_drawable && port_priv, BadValue); @@ -1171,11 +1152,6 @@ ephyrGetStill(KdScreenInfo * a_info, goto out; } - drw_x = clipped_area.x1; - drw_y = clipped_area.y1; - drw_w = clipped_area.x2 - clipped_area.x1; - drw_h = clipped_area.y2 - clipped_area.y1; - if (!ephyrHostXVGetStill(a_info->pScreen->myNum, port_priv->port_number, a_vid_x, a_vid_y, a_vid_w, a_vid_h, From 0f537da72d414ed84e3cd14e3bb7e08565136bd7 Mon Sep 17 00:00:00 2001 From: Andreas Wettstein Date: Sun, 3 Mar 2013 20:25:44 +0100 Subject: [PATCH 25/25] xkb: Fixes to LatchMods/LatchGroup The main problem this patch addresses is that if a latch is put on multi-level key with a Latch/Lock/Set, it is possible that after all keys are released, still base modifiers are set, which typically will make the keyboard unusable. To see how it happens (without the patch), assume that key AltGr sets Mod5 when pressed by itself, and latches Mod3 when pressed together with Shift. Now press Shift, then AltGr and release both keys in reverse order. Mod3 is now latched, and the LatchMods filter remains active as the second filter. Now press AltGr; Mod5 base modifier gets set, and the SetMods filter will become active as the first filter. Release AltGr: First, the SetMods filter will set clearMods to Mod5, then the LatchMods filter will overwrite clearMods with Mod3. Result: the Mod5 base modifier will remain set. This example becomes practically relevant for the revised German standard layout (DIN 2137-1:2012-06). Other changes implement the latch behaviour more accurately according to the specification. For example, releasing a modifier latching key can at the same time clear a locked modifier, promote another modifier that is latched to locked, and latch a third modifier. Overall, what the code does should be straightforward to compare what the XKB protocol specification demands, see the table in section 6.3. Finally, releasing a key no longer cancels a latch that has not become pending yet. In my opinion, the specification is not clear; it speaks of "operating" a key, which the patch effectivly interprets as "press" rather than "press or release". From my experience, using the latter interpretation makes latches on higher levels practically unusable. In the example given above, one would have to release AltGr always before Shift to get the Mod3-Latch. The practical relevance of latches on higher levels is once more given by the revised German standard layout. Signed-off-by: Andreas Wettstein Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- xkb/xkbActions.c | 151 +++++++++++++++++++++++++---------------------- 1 file changed, 81 insertions(+), 70 deletions(-) diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c index 416de925d..e32005cf6 100644 --- a/xkb/xkbActions.c +++ b/xkb/xkbActions.c @@ -222,7 +222,6 @@ _XkbFilterSetState(XkbSrvInfoPtr xkbi, #define LATCH_KEY_DOWN 1 #define LATCH_PENDING 2 -#define NO_LATCH 3 static int _XkbFilterLatchState(XkbSrvInfoPtr xkbi, @@ -230,6 +229,7 @@ _XkbFilterLatchState(XkbSrvInfoPtr xkbi, { if (filter->keycode == 0) { /* initial press */ + AccessXCancelRepeatKey(xkbi,keycode); filter->keycode = keycode; filter->active = 1; filter->filterOthers = 1; @@ -250,91 +250,102 @@ _XkbFilterLatchState(XkbSrvInfoPtr xkbi, else if (pAction && (filter->priv == LATCH_PENDING)) { if (((1 << pAction->type) & XkbSA_BreakLatch) != 0) { filter->active = 0; - if (filter->upAction.type == XkbSA_LatchMods) - xkbi->state.latched_mods &= ~filter->upAction.mods.mask; - else - xkbi->state.latched_group -= - XkbSAGroup(&filter->upAction.group); - } - else if ((pAction->type == filter->upAction.type) && - (pAction->mods.flags == filter->upAction.mods.flags) && - (pAction->mods.mask == filter->upAction.mods.mask)) { - if (filter->upAction.mods.flags & XkbSA_LatchToLock) { - XkbControlsPtr ctrls = xkbi->desc->ctrls; - - if (filter->upAction.type == XkbSA_LatchMods) - pAction->mods.type = XkbSA_LockMods; - else - pAction->group.type = XkbSA_LockGroup; - if (XkbAX_NeedFeedback(ctrls, XkbAX_StickyKeysFBMask) && - (ctrls->enabled_ctrls & XkbStickyKeysMask)) { - XkbDDXAccessXBeep(xkbi->device, _BEEP_STICKY_LOCK, - XkbStickyKeysMask); - } - } - else { - if (filter->upAction.type == XkbSA_LatchMods) - pAction->mods.type = XkbSA_SetMods; - else - pAction->group.type = XkbSA_SetGroup; - } - if (filter->upAction.type == XkbSA_LatchMods) - xkbi->state.latched_mods &= ~filter->upAction.mods.mask; - else - xkbi->state.latched_group -= - XkbSAGroup(&filter->upAction.group); - filter->active = 0; + /* If one latch is broken, all latches are broken, so it's no use + to find out which particular latch this filter tracks. */ + xkbi->state.latched_mods = 0; + xkbi->state.latched_group = 0; } } - else if (filter->keycode == keycode) { /* release */ + else if (filter->keycode == keycode && filter->priv != LATCH_PENDING){ + /* The test above for LATCH_PENDING skips subsequent releases of the + key after it has been released first time and the latch became + pending. */ XkbControlsPtr ctrls = xkbi->desc->ctrls; - int needBeep; - int beepType = _BEEP_NONE; + int needBeep = ((ctrls->enabled_ctrls & XkbStickyKeysMask) && + XkbAX_NeedFeedback(ctrls, XkbAX_StickyKeysFBMask)); - needBeep = ((ctrls->enabled_ctrls & XkbStickyKeysMask) && - XkbAX_NeedFeedback(ctrls, XkbAX_StickyKeysFBMask)); if (filter->upAction.type == XkbSA_LatchMods) { - xkbi->clearMods = filter->upAction.mods.mask; - if ((filter->upAction.mods.flags & XkbSA_ClearLocks) && - (xkbi->clearMods & xkbi->state.locked_mods) == - xkbi->clearMods) { - xkbi->state.locked_mods &= ~xkbi->clearMods; - filter->priv = NO_LATCH; - beepType = _BEEP_STICKY_UNLOCK; + unsigned char mask = filter->upAction.mods.mask; + unsigned char common; + + xkbi->clearMods = mask; + + /* ClearLocks */ + common = mask & xkbi->state.locked_mods; + if ((filter->upAction.mods.flags & XkbSA_ClearLocks) && common) { + mask &= ~common; + xkbi->state.locked_mods &= ~common; + if (needBeep) + XkbDDXAccessXBeep(xkbi->device, _BEEP_STICKY_UNLOCK, + XkbStickyKeysMask); + } + /* LatchToLock */ + common = mask & xkbi->state.latched_mods; + if ((filter->upAction.mods.flags & XkbSA_LatchToLock) && common) { + unsigned char newlocked; + + mask &= ~common; + newlocked = common & ~xkbi->state.locked_mods; + if(newlocked){ + xkbi->state.locked_mods |= newlocked; + if (needBeep) + XkbDDXAccessXBeep(xkbi->device, _BEEP_STICKY_LOCK, + XkbStickyKeysMask); + + } + xkbi->state.latched_mods &= ~common; + } + /* Latch remaining modifiers, if any. */ + if (mask) { + xkbi->state.latched_mods |= mask; + filter->priv = LATCH_PENDING; + if (needBeep) + XkbDDXAccessXBeep(xkbi->device, _BEEP_STICKY_LATCH, + XkbStickyKeysMask); } } else { xkbi->groupChange = -XkbSAGroup(&filter->upAction.group); + /* ClearLocks */ if ((filter->upAction.group.flags & XkbSA_ClearLocks) && (xkbi->state.locked_group)) { xkbi->state.locked_group = 0; - filter->priv = NO_LATCH; - beepType = _BEEP_STICKY_UNLOCK; + if (needBeep) + XkbDDXAccessXBeep(xkbi->device, _BEEP_STICKY_UNLOCK, + XkbStickyKeysMask); + } + /* LatchToLock */ + else if ((filter->upAction.group.flags & XkbSA_LatchToLock) + && (xkbi->state.latched_group)) { + xkbi->state.locked_group += XkbSAGroup(&filter->upAction.group); + xkbi->state.latched_group -= XkbSAGroup(&filter->upAction.group); + if(XkbSAGroup(&filter->upAction.group) && needBeep) + XkbDDXAccessXBeep(xkbi->device, _BEEP_STICKY_LOCK, + XkbStickyKeysMask); + } + /* Latch group */ + else if(XkbSAGroup(&filter->upAction.group)){ + xkbi->state.latched_group += XkbSAGroup(&filter->upAction.group); + filter->priv = LATCH_PENDING; + if (needBeep) + XkbDDXAccessXBeep(xkbi->device, _BEEP_STICKY_LATCH, + XkbStickyKeysMask); } } - if (filter->priv == NO_LATCH) { + + if (filter->priv != LATCH_PENDING) filter->active = 0; - } - else { - filter->priv = LATCH_PENDING; - if (filter->upAction.type == XkbSA_LatchMods) { - xkbi->state.latched_mods |= filter->upAction.mods.mask; - needBeep = xkbi->state.latched_mods ? needBeep : 0; - xkbi->state.latched_mods |= filter->upAction.mods.mask; - } - else { - xkbi->state.latched_group += - XkbSAGroup(&filter->upAction.group); - } - if (needBeep && (beepType == _BEEP_NONE)) - beepType = _BEEP_STICKY_LATCH; - } - if (needBeep && (beepType != _BEEP_NONE)) - XkbDDXAccessXBeep(xkbi->device, beepType, XkbStickyKeysMask); } - else if (filter->priv == LATCH_KEY_DOWN) { - filter->priv = NO_LATCH; - filter->filterOthers = 0; + else if (pAction && (filter->priv == LATCH_KEY_DOWN)) { + /* Latch was broken before it became pending: degrade to a + SetMods/SetGroup. */ + if (filter->upAction.type == XkbSA_LatchMods) + filter->upAction.type = XkbSA_SetMods; + else + filter->upAction.type = XkbSA_SetGroup; + filter->filter = _XkbFilterSetState; + filter->priv = 0; + return filter->filter(xkbi, filter, keycode, pAction); } return 1; }