1
0
mirror of https://github.com/gryf/wmaker.git synced 2026-07-06 18:56:36 +02:00

Compare commits

..

6 Commits

Author SHA1 Message Date
Haroldo Santos 6c107e0ce5 wmsetbg: fix "X connection broken" crash when setting background
setPixmapProperty() called XKillClient(dpy, old_pixmap) to free the
previous background pixmap stored in _XROOTPMAP_ID.  The pixmap was
created by duplicatePixmap() via a short-lived second X connection
that used XSetCloseDownMode(RetainPermanent).  After that connection
closed, the X server eventually recycled its client ID for a new
connection.  If wmsetbg's own 'dpy' connection received that recycled
ID, XKillClient() would kill wmsetbg itself, causing the fatal error:

  X connection to :0 broken (explicit kill or server shutdown).

Fix by switching from RetainPermanent to RetainTemporary in
duplicatePixmap().  With RetainTemporary, background pixmaps are kept
alive for the lifetime of the X session and freed automatically at
logout — no explicit XKillClient() is needed.

Remove the now-dead XKillClient() block from setPixmapProperty():
- dummyErrorHandler() was only used to suppress its X errors; remove.
- The mode variable toggled PropModeReplace/PropModeAppend based on
  whether an old pixmap was present; since we always want to replace,
  use PropModeReplace unconditionally.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-15 17:29:07 +01:00
Haroldo Santos 7c80e917d7 wmsetbg: fix memory leak of XGetWindowProperty data in setPixmapProperty
XGetWindowProperty() allocates a buffer and returns it via the 'data'
pointer; the caller is responsible for freeing it with XFree() when
done.  setPixmapProperty() read the old _XROOTPMAP_ID value but never
freed the returned buffer, leaking memory on every background change.

Add the missing XFree(data) call.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-15 17:29:07 +01:00
David Maciejak 90ce10998c wmaker: ignore queued motion before the screenshot anchor click
imageCaptureArea() consumed any MotionNotify still queued from the
root window before Button1 set the anchor point, with xp,yp still -1
the rectangle math anchored the XOR wireframe at (-1,-1) and drew a
box from the top-left corner to the pointer. Drop motion events
until the press has recorded an anchor.
2026-06-13 21:57:23 +01:00
David Maciejak f18de447f6 wmaker: grab the keyboard during partial screenshot selection
imageCaptureArea() already looked for XK_Escape in its event loop but
only grabbed the pointer, so the KeyPress went to the focused client
and the cancel branch was unreachable. Grab the keyboard for the
duration of the rubber-band selection, erase the XOR rectangle when
Escape aborts mid-drag, and release the keyboard on every exit path.
2026-06-13 21:57:23 +01:00
Hugo Carvalho b69c9db245 po: add European Portuguese translation, rename old pt to pt_BR
The existing pt.po was Brazilian Portuguese, so move it to pt_BR.po
unchanged and add a new European Portuguese pt.po. Register pt_BR in
EXTRA_DIST and update the maintainer table in po/README.

Imported from window-maker/wmaker pull request 68.
2026-06-13 21:55:08 +01:00
David Maciejak 3562ce9d7b wmaker: restore atom indices broken by _WINDOWMAKER_MARK_KEY insertion
The vim-like window marking change inserted "_WINDOWMAKER_MARK_KEY" at
atomNames[17] and appended wmaker.mark_key = atom[22], but did not shift
the existing atom[17..21] assignments. Since then gnustep.wm_attr,
gnustep.wm_miniaturize_window, gnustep.titlebar_state,
desktop.gtk_object_path, wm.ignore_focus_events and wmaker.mark_key have
each held the atom for the next name in the table, breaking GNUstep
window-level/titlebar/miniaturize handling, the GTK object-path skip,
WM_IGNORE_FOCUS_EVENTS and the mark feature itself.

Move the new name to the end of atomNames[] so positions 17..22 line up
with their assignments again.
2026-06-11 15:45:55 +01:00
7 changed files with 2039 additions and 328 deletions
+1 -1
View File
@@ -7,7 +7,7 @@ CLEANFILES = $(CATALOGS) $(DOMAIN).pot
# Please keep this sorted in alphabetic order!
EXTRA_DIST = be.po bg.po bs.po ca.po cs.po da.po de.po el.po es.po et.po \
fi.po fr.po fy.po gl.po hr.po hu.po hy.po it.po ja.po ko.po ms.po nl.po \
no.po pl.po pt.po ro.po ru.po sk.po sr.po sv.po tr.po uk.po zh_CN.po \
no.po pl.po pt.po pt_BR.po ro.po ru.po sk.po sr.po sv.po tr.po uk.po zh_CN.po \
zh_TW.po
POTFILES = \
+2 -1
View File
@@ -3,7 +3,8 @@ File Language Note Current Maintainer
ja.po Japanese 1 ABE Shige <sabe@ibm.net>
MANOME Tomonori <manome@itlb.te.noda.sut.ac.jp>
Takeo Hashimoto <HashimotoTakeo@mac.com>
pt.po Portuguese Eliphas Levy Theodoro <eliphas@conectiva.com.br>
pt_BR.po Brazilian Portuguese Eliphas Levy Theodoro <eliphas@conectiva.com.br>
pt.po Portuguese Hugo Carvalho <hugokarvalho@hotmail.com>
de.po German Torsten Marek <torsten.marek@vbdnet.de>
Bernd Eggert <Bernd.Eggert@t-online.de>
Matthias Warkus <mawarkus@t-online.de>
+228 -300
View File
File diff suppressed because it is too large Load Diff
+1776
View File
File diff suppressed because it is too large Load Diff
+11 -1
View File
@@ -1143,6 +1143,7 @@ static XImage *imageCaptureArea(WScreen *scr)
GrabModeAsync, None, wPreferences.cursor[WCUR_CAPTURE], CurrentTime) != Success) {
return NULL;
}
XGrabKeyboard(dpy, scr->root_win, False, GrabModeAsync, GrabModeAsync, CurrentTime);
XGrabServer(dpy);
@@ -1162,12 +1163,17 @@ static XImage *imageCaptureArea(WScreen *scr)
if (w > 0 && h > 0) {
XDrawRectangle(dpy, scr->root_win, scr->frame_gc, x, y, w, h);
XUngrabServer(dpy);
XUngrabKeyboard(dpy, CurrentTime);
XUngrabPointer(dpy, CurrentTime);
return XGetImage(dpy, scr->root_win, x, y, w, h, AllPlanes, ZPixmap);
}
}
break;
case MotionNotify:
/* drop stale root MotionNotify still queued from before
* the grab, otherwise the rectangle anchors at (-1,-1) */
if (xp < 0)
break;
XDrawRectangle(dpy, scr->root_win, scr->frame_gc, x, y, w, h);
x = event.xmotion.x_root;
if (x < xp) {
@@ -1186,8 +1192,11 @@ static XImage *imageCaptureArea(WScreen *scr)
XDrawRectangle(dpy, scr->root_win, scr->frame_gc, x, y, w, h);
break;
case KeyPress:
if (W_KeycodeToKeysym(dpy, event.xkey.keycode, 0) == XK_Escape)
if (W_KeycodeToKeysym(dpy, event.xkey.keycode, 0) == XK_Escape) {
if (w > 0 && h > 0)
XDrawRectangle(dpy, scr->root_win, scr->frame_gc, x, y, w, h);
quit = 1;
}
break;
default:
WMHandleEvent(&event);
@@ -1196,6 +1205,7 @@ static XImage *imageCaptureArea(WScreen *scr)
}
XUngrabServer(dpy);
XUngrabKeyboard(dpy, CurrentTime);
XUngrabPointer(dpy, CurrentTime);
return NULL;
}
+3 -2
View File
@@ -387,7 +387,6 @@ static char *atomNames[] = {
"_WINDOWMAKER_COMMAND",
"_WINDOWMAKER_ICON_SIZE",
"_WINDOWMAKER_ICON_TILE",
"_WINDOWMAKER_MARK_KEY",
GNUSTEP_WM_ATTR_NAME,
GNUSTEP_WM_MINIATURIZE_WINDOW,
@@ -395,7 +394,9 @@ static char *atomNames[] = {
"_GTK_APPLICATION_OBJECT_PATH",
"WM_IGNORE_FOCUS_EVENTS"
"WM_IGNORE_FOCUS_EVENTS",
"_WINDOWMAKER_MARK_KEY"
};
/*
+18 -23
View File
@@ -781,8 +781,12 @@ static Pixmap duplicatePixmap(Pixmap pixmap, int width, int height)
Display *tmpDpy;
Pixmap copyP;
/* must open a new display or the RetainPermanent will
* leave stuff allocated in RContext unallocated after exit */
/* Open a separate connection so the pixmap survives our exit.
* RetainTemporary (not RetainPermanent) is used intentionally:
* the pixmap lives until the X session ends, avoiding the need
* for XKillClient() on old pixmaps (which can crash when the
* X server reuses a client ID that now belongs to our own
* connection, causing "X connection broken"). */
tmpDpy = XOpenDisplay(display);
if (!tmpDpy) {
wwarning("could not open display to update background image information");
@@ -795,21 +799,13 @@ static Pixmap duplicatePixmap(Pixmap pixmap, int width, int height)
XCopyArea(tmpDpy, pixmap, copyP, DefaultGC(tmpDpy, scr), 0, 0, width, height, 0, 0);
XSync(tmpDpy, False);
XSetCloseDownMode(tmpDpy, RetainPermanent);
XSetCloseDownMode(tmpDpy, RetainTemporary);
XCloseDisplay(tmpDpy);
}
return copyP;
}
static int dummyErrorHandler(Display * dpy, XErrorEvent * err)
{
/* Parameter not used, but tell the compiler that it is ok */
(void) dpy;
(void) err;
return 0;
}
static void setPixmapProperty(Pixmap pixmap)
{
@@ -818,7 +814,6 @@ static void setPixmapProperty(Pixmap pixmap)
int format;
unsigned long length, after;
unsigned char *data;
int mode;
if (!prop) {
prop = XInternAtom(dpy, "_XROOTPMAP_ID", False);
@@ -826,21 +821,21 @@ static void setPixmapProperty(Pixmap pixmap)
XGrabServer(dpy);
/* Clear out the old pixmap */
/* Read and discard the old property data. We no longer call
* XKillClient() on the old pixmap: since duplicatePixmap() uses
* RetainTemporary, old pixmaps are freed automatically when the
* X session ends. Calling XKillClient() here was unsafe because
* the X server reuses client IDs; if the stored resource ID was
* reassigned to our own connection the server would kill us,
* producing "X connection to :0 broken". */
XGetWindowProperty(dpy, root, prop, 0L, 1L, False, AnyPropertyType,
&type, &format, &length, &after, &data);
if (data)
XFree(data);
if ((type == XA_PIXMAP) && (format == 32) && (length == 1)) {
XSetErrorHandler(dummyErrorHandler);
XKillClient(dpy, *((Pixmap *) data));
XSync(dpy, False);
XSetErrorHandler(NULL);
mode = PropModeReplace;
} else {
mode = PropModeAppend;
}
if (pixmap)
XChangeProperty(dpy, root, prop, XA_PIXMAP, 32, mode, (unsigned char *)&pixmap, 1);
XChangeProperty(dpy, root, prop, XA_PIXMAP, 32, PropModeReplace,
(unsigned char *)&pixmap, 1);
else
XDeleteProperty(dpy, root, prop);