cursors: Rework cursor creation
In non-ancient mode (i.e. using XRenderCreateCursor) this should be somewhat more efficient.
This commit is contained in:
parent
8f64686175
commit
1cef4a1044
159
src/cursors.c
159
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)
|
||||
{
|
||||
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 */
|
||||
|
||||
pict = EPictureCreateBuffer(VROOT, w, h, 1, NULL);
|
||||
|
||||
/* Clear entirely (alpha = 0) */
|
||||
EPictureFillRect(pict, 0, 0, w, h, 0);
|
||||
|
||||
/* Paint fg color where cmask bits are set */
|
||||
rgn1 = ERegionCreateFromBitmap(cmask);
|
||||
EPictureSetClip(pict, rgn1);
|
||||
EPictureFillRect(pict, 0, 0, w, h, fg);
|
||||
|
||||
/* Paint bg color where cpmap bits are set */
|
||||
rgn2 = ERegionCreateFromBitmap(cpmap);
|
||||
ERegionIntersect(rgn1, rgn2);
|
||||
EPictureSetClip(pict, rgn1);
|
||||
EPictureFillRect(pict, 0, 0, w, h, bg);
|
||||
|
||||
curs = XRenderCreateCursor(disp, pict, xh, yh);
|
||||
|
||||
ERegionDestroy(rgn1);
|
||||
ERegionDestroy(rgn2);
|
||||
EPictureDestroy(pict);
|
||||
|
||||
return curs;
|
||||
}
|
||||
#else
|
||||
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)
|
||||
_ECursorCreateFromBitmapData(int w, int h, unsigned char *cdata,
|
||||
unsigned char *cmask, int xh, int yh,
|
||||
unsigned int fg, unsigned int bg)
|
||||
{
|
||||
EX_Cursor curs;
|
||||
Pixmap pmap, mask;
|
||||
XColor fgxc, bgxc;
|
||||
|
||||
curs = NoXID;
|
||||
mask = NoXID;
|
||||
|
||||
pmap = XCreateBitmapFromData(disp, WinGetXwin(VROOT), (char *)cdata, w, h);
|
||||
if (!pmap)
|
||||
goto done;
|
||||
|
||||
if (cmask)
|
||||
mask =
|
||||
XCreateBitmapFromData(disp, WinGetXwin(VROOT), (char *)cmask, w, h);
|
||||
|
||||
/* Looks like the pmap (not mask) bits in all theme cursors are inverted.
|
||||
* Fix by swapping fg and bg colors */
|
||||
* 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 = XCreatePixmapCursor(disp, cpmap, cmask, &fgxc, &bgxc, xh, yh);
|
||||
curs = XCreatePixmapCursor(disp, pmap, mask, &fgxc, &bgxc, xh, yh);
|
||||
|
||||
EFreePixmap(pmap);
|
||||
if (mask)
|
||||
EFreePixmap(mask);
|
||||
|
||||
done:
|
||||
return curs;
|
||||
}
|
||||
|
||||
#endif /* !USE_XRENDER */
|
||||
|
||||
static EX_Cursor
|
||||
_ECursorCreateFromBitmaps(const char *img, unsigned int fg, unsigned int bg)
|
||||
{
|
||||
EX_Cursor curs;
|
||||
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;
|
||||
}
|
||||
|
||||
if (xh < 0 || xh >= (int)w)
|
||||
xh = w / 2;
|
||||
if (yh < 0 || yh >= (int)h)
|
||||
yh = h / 2;
|
||||
|
||||
#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
|
||||
|
|
42
src/eimage.c
42
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 = imlib_image_get_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 */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue