This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch master
in repository e16.
View the commit online.
commit 1cef4a1044086c1c559e6ab866284e5de5ae0a52
Author: Kim Woelders <[email protected]>
AuthorDate: Fri Dec 23 15:11:57 2022 +0100
cursors: Rework cursor creation
In non-ancient mode (i.e. using XRenderCreateCursor) this should be
somewhat more efficient.
---
src/cursors.c | 147 ++++++++++++++++++++++++++++++----------------------------
src/eimage.c | 42 +++++++++++++++++
src/eimage.h | 8 +++-
3 files changed, 126 insertions(+), 71 deletions(-)
diff --git a/src/cursors.c b/src/cursors.c
index 0c48bcf3..03feee6e 100644
--- a/src/cursors.c
+++ b/src/cursors.c
@@ -25,9 +25,6 @@
#include <X11/Xlib.h>
#include <X11/cursorfont.h>
-#if USE_COMPOSITE
-#include <X11/extensions/Xrender.h>
-#endif
#include "E.h"
#include "conf.h"
@@ -35,6 +32,9 @@
#include "emodule.h"
#include "list.h"
#include "xwin.h"
+#if USE_XRENDER
+#include "eimage.h"
+#endif
struct _ecursor {
dlist_t list;
@@ -49,65 +49,96 @@ struct _ecursor {
static LIST_HEAD(cursor_list);
-#if USE_COMPOSITE
-/* Assuming we have XRenderCreateCursor (render >= 0.5) */
+#if !USE_XRENDER
+
static EX_Cursor
-ECreatePixmapCursor(EX_Pixmap cpmap, EX_Pixmap cmask, unsigned int w,
- unsigned int h, int xh, int yh, unsigned int fg,
- unsigned int bg)
+_ECursorCreateFromBitmapData(int w, int h, unsigned char *cdata,
+ unsigned char *cmask, int xh, int yh,
+ unsigned int fg, unsigned int bg)
{
EX_Cursor curs;
- EX_Picture pict;
- EX_SrvRegion rgn1, rgn2;
-
- /* Looks like the pmap (not mask) bits in all theme cursors are inverted.
- * Fix by swapping fg and bg colors */
+ Pixmap pmap, mask;
+ XColor fgxc, bgxc;
- pict = EPictureCreateBuffer(VROOT, w, h, 1, NULL);
+ curs = NoXID;
+ mask = NoXID;
- /* Clear entirely (alpha = 0) */
- EPictureFillRect(pict, 0, 0, w, h, 0);
+ pmap = XCreateBitmapFromData(disp, WinGetXwin(VROOT), (char *)cdata, w, h);
+ if (!pmap)
+ goto done;
- /* Paint fg color where cmask bits are set */
- rgn1 = ERegionCreateFromBitmap(cmask);
- EPictureSetClip(pict, rgn1);
- EPictureFillRect(pict, 0, 0, w, h, fg);
+ if (cmask)
+ mask =
+ XCreateBitmapFromData(disp, WinGetXwin(VROOT), (char *)cmask, w, h);
- /* Paint bg color where cpmap bits are set */
- rgn2 = ERegionCreateFromBitmap(cpmap);
- ERegionIntersect(rgn1, rgn2);
- EPictureSetClip(pict, rgn1);
- EPictureFillRect(pict, 0, 0, w, h, bg);
+ /* Looks like the pmap (not mask) bits in all theme cursors are inverted.
+ * Fix by swapping fg and bg colors. */
+ COLOR32_TO_RGB16(bg, fgxc.red, fgxc.green, fgxc.blue);
+ COLOR32_TO_RGB16(fg, bgxc.red, bgxc.green, bgxc.blue);
+ XAllocColor(disp, WinGetCmap(VROOT), &fgxc);
+ XAllocColor(disp, WinGetCmap(VROOT), &bgxc);
- curs = XRenderCreateCursor(disp, pict, xh, yh);
+ curs = XCreatePixmapCursor(disp, pmap, mask, &fgxc, &bgxc, xh, yh);
- ERegionDestroy(rgn1);
- ERegionDestroy(rgn2);
- EPictureDestroy(pict);
+ EFreePixmap(pmap);
+ if (mask)
+ EFreePixmap(mask);
+ done:
return curs;
}
-#else
+
+#endif /* !USE_XRENDER */
+
static EX_Cursor
-ECreatePixmapCursor(EX_Pixmap cpmap, EX_Pixmap cmask,
- unsigned int w __UNUSED__, unsigned int h __UNUSED__,
- int xh, int yh, unsigned int fg, unsigned int bg)
+_ECursorCreateFromBitmaps(const char *img, unsigned int fg, unsigned int bg)
{
EX_Cursor curs;
- XColor fgxc, bgxc;
+ unsigned char *cdata, *cmask;
+ unsigned int w, h, wm, hm;
+ int xh, yh;
+ char msk[FILEPATH_LEN_MAX];
+
+ curs = NoXID;
+ w = h = 0;
+ xh = yh = 0;
+ cdata = cmask = NULL;
+
+ XReadBitmapFileData(img, &w, &h, &cdata, &xh, &yh);
+ if (!cdata)
+ goto done;
+ XQueryBestCursor(disp, WinGetXwin(VROOT), w, h, &wm, &hm);
+ if (w > wm || h > hm)
+ goto done;
+
+ Esnprintf(msk, sizeof(msk), "%s.mask", img);
+ XReadBitmapFileData(msk, &wm, &hm, &cmask, NULL, NULL);
+ if (cmask && (w != wm || h != hm))
+ {
+ /* Dimension mismatch - drop mask */
+ XFree(cmask);
+ cmask = NULL;
+ }
- /* Looks like the pmap (not mask) bits in all theme cursors are inverted.
- * Fix by swapping fg and bg colors */
- COLOR32_TO_RGB16(bg, fgxc.red, fgxc.green, fgxc.blue);
- COLOR32_TO_RGB16(fg, bgxc.red, bgxc.green, bgxc.blue);
- XAllocColor(disp, WinGetCmap(VROOT), &fgxc);
- XAllocColor(disp, WinGetCmap(VROOT), &bgxc);
+ if (xh < 0 || xh >= (int)w)
+ xh = w / 2;
+ if (yh < 0 || yh >= (int)h)
+ yh = h / 2;
- curs = XCreatePixmapCursor(disp, cpmap, cmask, &fgxc, &bgxc, xh, yh);
+#if USE_XRENDER
+ curs = EImageCursorCreateFromBitmapData(w, h, cdata, cmask, xh, yh, fg, bg);
+#else
+ curs = _ECursorCreateFromBitmapData(w, h, cdata, cmask, xh, yh, fg, bg);
+#endif
+
+ if (cmask)
+ XFree(cmask);
+ done:
+ if (cdata)
+ XFree(cdata);
return curs;
}
-#endif
static void
_ECursorCreate(const char *name, const char *image, int native_id,
@@ -155,10 +186,7 @@ _ECursorDestroy(ECursor * ec)
static ECursor *
_ECursorRealize(ECursor * ec)
{
- Pixmap pmap, mask;
- int xh, yh;
- unsigned int w, h, ww, hh;
- char *img, msk[FILEPATH_LEN_MAX];
+ char *img;
if (ec->file)
{
@@ -167,34 +195,13 @@ _ECursorRealize(ECursor * ec)
if (!img)
goto done;
- Esnprintf(msk, sizeof(msk), "%s.mask", img);
- pmap = 0;
- mask = 0;
- xh = 0;
- yh = 0;
- XReadBitmapFile(disp, WinGetXwin(VROOT), msk, &w, &h, &mask, &xh, &yh);
- XReadBitmapFile(disp, WinGetXwin(VROOT), img, &w, &h, &pmap, &xh, &yh);
- XQueryBestCursor(disp, WinGetXwin(VROOT), w, h, &ww, &hh);
- if ((w <= ww) && (h <= hh) && (pmap))
- {
- if (xh < 0 || xh >= (int)w)
- xh = (int)w / 2;
- if (yh < 0 || yh >= (int)h)
- yh = (int)h / 2;
- ec->cursor =
- ECreatePixmapCursor(pmap, mask, w, h, xh, yh, ec->fg, ec->bg);
- }
-
+ ec->cursor = _ECursorCreateFromBitmaps(img, ec->fg, ec->bg);
if (ec->cursor == NoXID)
{
- Eprintf("*** Failed to create cursor \"%s\" from %s,%s\n",
- ec->name, img, msk);
+ Eprintf("*** Failed to create cursor \"%s\" from %s,%s.mask\n",
+ ec->name, img, img);
}
- if (pmap)
- EFreePixmap(pmap);
- if (mask)
- EFreePixmap(mask);
Efree(img);
}
else
diff --git a/src/eimage.c b/src/eimage.c
index 1299a8bd..56e4eae2 100644
--- a/src/eimage.c
+++ b/src/eimage.c
@@ -757,4 +757,46 @@ EImageDefineCursor(EImage * im, int xh, int yh)
return curs;
}
+EX_Cursor
+EImageCursorCreateFromBitmapData(int w, int h, const unsigned char *cdata,
+ const unsigned char *cmask, int xh, int yh,
+ unsigned int fg, unsigned int bg)
+{
+ EX_Cursor curs;
+ uint32_t *data, pixel;
+ int i, j;
+ Imlib_Image im;
+
+ /* Looks like the pmap (not mask) bits in all theme cursors are inverted.
+ * Fix by swapping fg and bg colors. */
+
+ im = imlib_create_image(w, h);
+ imlib_context_set_image(im);
+ imlib_image_set_has_alpha(1);
+ data = ""
+
+ for (i = 0; i < h; i++)
+ {
+ for (j = 0; j < w; j++)
+ {
+ int ix = i * ((w + 7) / 8) + j / 8;
+ int bit = j % 8, bits_i, bits_m;
+ bits_i = cdata[ix];
+ bits_m = cmask ? cmask[ix] : 0;
+ if ((bits_m & (1 << bit)) == 0)
+ pixel = 0;
+ else if (bits_i & (1 << bit))
+ pixel = bg; /* fg/bg swapped */
+ else
+ pixel = fg;
+ *data++ = pixel;
+ }
+ }
+
+ curs = EImageDefineCursor(im, xh, yh);
+ imlib_free_image_and_decache();
+
+ return curs;
+}
+
#endif /* USE_XRENDER */
diff --git a/src/eimage.h b/src/eimage.h
index 53d59dd3..066413a0 100644
--- a/src/eimage.h
+++ b/src/eimage.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2021 Kim Woelders
+ * Copyright (C) 2004-2022 Kim Woelders
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
@@ -118,6 +118,12 @@ void ScaleTile(Win wsrc, EX_Drawable src, Win wdst,
int flags);
EX_Cursor EImageDefineCursor(EImage * im, int xh, int yh);
+EX_Cursor EImageCursorCreateFromBitmapData(int w, int h,
+ const unsigned char *cdata,
+ const unsigned char *cmask,
+ int xh, int yh,
+ unsigned int fg,
+ unsigned int bg);
void EDrawableDumpImage(EX_Drawable draw, const char *txt);
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.