make icons use pixel32 data, and image_draw takes pixel32 data.
client.c gets pixmap icons as a backup to netwm ones, and they are converted into pixel32 data.
This commit is contained in:
parent
f41d06f583
commit
a18c1697b1
7 changed files with 255 additions and 36 deletions
|
@ -1142,6 +1142,9 @@ void client_update_wmhints(Client *self)
|
|||
it->data);
|
||||
}
|
||||
|
||||
/* the WM_HINTS can contain an icon */
|
||||
client_update_icons(self);
|
||||
|
||||
/* because the self->transient flag wont change from this call,
|
||||
we don't need to update the window's type and such, only its
|
||||
transient_for, and the transients lists of other windows in
|
||||
|
@ -1317,11 +1320,23 @@ void client_update_icons(Client *self)
|
|||
/* store the icons */
|
||||
i = 0;
|
||||
for (j = 0; j < self->nicons; ++j) {
|
||||
guint x, y, t;
|
||||
|
||||
w = self->icons[j].width = data[i++];
|
||||
h = self->icons[j].height = data[i++];
|
||||
self->icons[j].data =
|
||||
g_memdup(&data[i], w * h * sizeof(gulong));
|
||||
i += w * h;
|
||||
|
||||
self->icons[j].data = g_new(pixel32, w * h);
|
||||
for (x = 0, y = 0, t = 0; t < w * h; ++t, ++x, ++i) {
|
||||
if (x >= w) {
|
||||
x = 0;
|
||||
++y;
|
||||
}
|
||||
self->icons[j].data[t] =
|
||||
(((data[i] >> 24) & 0xff) << default_alpha_offset) +
|
||||
(((data[i] >> 16) & 0xff) << default_red_offset) +
|
||||
(((data[i] >> 8) & 0xff) << default_green_offset) +
|
||||
(((data[i] >> 0) & 0xff) << default_blue_offset);
|
||||
}
|
||||
g_assert(i <= num);
|
||||
}
|
||||
|
||||
|
@ -1331,13 +1346,34 @@ void client_update_icons(Client *self)
|
|||
if (num == 2) {
|
||||
self->nicons++;
|
||||
self->icons = g_new(Icon, self->nicons);
|
||||
/* XXX WHAT IF THIS FAILS YOU TWIT!@!*()@ */
|
||||
render_pixmap_to_rgba(data[0], data[1],
|
||||
if (!render_pixmap_to_rgba(data[0], data[1],
|
||||
&self->icons[self->nicons-1].width,
|
||||
&self->icons[self->nicons-1].height,
|
||||
&self->icons[self->nicons-1].data);
|
||||
&self->icons[self->nicons-1].data)) {
|
||||
g_free(&self->icons[self->nicons-1]);
|
||||
self->nicons--;
|
||||
}
|
||||
}
|
||||
g_free(data);
|
||||
} else {
|
||||
XWMHints *hints;
|
||||
|
||||
if ((hints = XGetWMHints(ob_display, self->window))) {
|
||||
if (hints->flags & IconPixmapHint) {
|
||||
self->nicons++;
|
||||
self->icons = g_new(Icon, self->nicons);
|
||||
if (!render_pixmap_to_rgba(hints->icon_pixmap,
|
||||
(hints->flags & IconMaskHint ?
|
||||
hints->icon_mask : None),
|
||||
&self->icons[self->nicons-1].width,
|
||||
&self->icons[self->nicons-1].height,
|
||||
&self->icons[self->nicons-1].data)){
|
||||
g_free(&self->icons[self->nicons-1]);
|
||||
self->nicons--;
|
||||
}
|
||||
}
|
||||
XFree(hints);
|
||||
}
|
||||
}
|
||||
|
||||
if (self->frame)
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include "geom.h"
|
||||
#include "stacking.h"
|
||||
#include "render/color.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
|
@ -16,7 +18,7 @@ struct Group;
|
|||
/*! Holds an icon in ARGB format */
|
||||
typedef struct Icon {
|
||||
int width, height;
|
||||
gulong *data;
|
||||
pixel32 *data;
|
||||
} Icon;
|
||||
|
||||
/*! The MWM Hints as retrieved from the window property
|
||||
|
|
135
render/color.c
135
render/color.c
|
@ -1,5 +1,6 @@
|
|||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <string.h>
|
||||
#include "render.h"
|
||||
#include "color.h"
|
||||
#include "../kernel/openbox.h"
|
||||
|
@ -82,9 +83,9 @@ void reduce_depth(pixel32 *data, XImage *im)
|
|||
r = (data[x] >> default_red_offset) & 0xFF;
|
||||
g = (data[x] >> default_green_offset) & 0xFF;
|
||||
b = (data[x] >> default_blue_offset) & 0xFF;
|
||||
p32[x] = (r << render_red_offset)
|
||||
+ (g << render_green_offset)
|
||||
+ (b << render_blue_offset);
|
||||
p32[x] = (r << render_red_shift)
|
||||
+ (g << render_green_shift)
|
||||
+ (b << render_blue_shift);
|
||||
}
|
||||
data += im->width;
|
||||
p32 += im->width;
|
||||
|
@ -125,6 +126,7 @@ void reduce_depth(pixel32 *data, XImage *im)
|
|||
g_message("your bit depth is currently unhandled\n");
|
||||
}
|
||||
}
|
||||
|
||||
XColor *pickColor(int r, int g, int b)
|
||||
{
|
||||
r = (r & 0xff) >> (8-pseudo_bpc);
|
||||
|
@ -132,3 +134,130 @@ XColor *pickColor(int r, int g, int b)
|
|||
b = (b & 0xff) >> (8-pseudo_bpc);
|
||||
return &pseudo_colors[(r << (2*pseudo_bpc)) + (g << (1*pseudo_bpc)) + b];
|
||||
}
|
||||
|
||||
static void swap_byte_order(XImage *im)
|
||||
{
|
||||
int x, y, di;
|
||||
|
||||
g_message("SWAPPING BYTE ORDER");
|
||||
|
||||
di = 0;
|
||||
for (y = 0; y < im->height; ++y) {
|
||||
for (x = 0; x < im->height; ++x) {
|
||||
char *c = &im->data[di + x * im->bits_per_pixel / 8];
|
||||
char t;
|
||||
|
||||
switch (im->bits_per_pixel) {
|
||||
case 32:
|
||||
t = c[2];
|
||||
c[2] = c[3];
|
||||
c[3] = t;
|
||||
case 16:
|
||||
t = c[0];
|
||||
c[0] = c[1];
|
||||
c[1] = t;
|
||||
case 8:
|
||||
break;
|
||||
default:
|
||||
g_message("your bit depth is currently unhandled\n");
|
||||
}
|
||||
}
|
||||
di += im->bytes_per_line;
|
||||
}
|
||||
|
||||
if (im->byte_order == LSBFirst)
|
||||
im->byte_order = MSBFirst;
|
||||
else
|
||||
im->byte_order = LSBFirst;
|
||||
}
|
||||
|
||||
void increase_depth(pixel32 *data, XImage *im)
|
||||
{
|
||||
int r, g, b;
|
||||
int x,y;
|
||||
pixel32 *p32 = (pixel32 *) im->data;
|
||||
pixel16 *p16 = (pixel16 *) im->data;
|
||||
unsigned char *p8 = (unsigned char *)im->data;
|
||||
|
||||
if (im->byte_order != render_endian)
|
||||
swap_byte_order(im);
|
||||
|
||||
switch (im->bits_per_pixel) {
|
||||
case 32:
|
||||
for (y = 0; y < im->height; y++) {
|
||||
for (x = 0; x < im->width; x++) {
|
||||
r = (p32[x] >> render_red_offset) & 0xff;
|
||||
g = (p32[x] >> render_green_offset) & 0xff;
|
||||
b = (p32[x] >> render_blue_offset) & 0xff;
|
||||
data[x] = (r << default_red_offset)
|
||||
+ (g << default_green_offset)
|
||||
+ (b << default_blue_offset)
|
||||
+ (0xff << default_alpha_offset);
|
||||
}
|
||||
data += im->width;
|
||||
p32 += im->bytes_per_line/4;
|
||||
}
|
||||
break;
|
||||
case 16:
|
||||
for (y = 0; y < im->height; y++) {
|
||||
for (x = 0; x < im->width; x++) {
|
||||
r = (p16[x] & render_red_mask) >> render_red_offset <<
|
||||
render_red_shift;
|
||||
g = (p16[x] & render_green_mask) >> render_green_offset <<
|
||||
render_green_shift;
|
||||
b = (p16[x] & render_blue_mask) >> render_blue_offset <<
|
||||
render_blue_shift;
|
||||
data[x] = (r << default_red_offset)
|
||||
+ (g << default_green_offset)
|
||||
+ (b << default_blue_offset)
|
||||
+ (0xff << default_alpha_offset);
|
||||
}
|
||||
data += im->width;
|
||||
p16 += im->bytes_per_line/2;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
g_assert(render_visual->class != TrueColor);
|
||||
for (y = 0; y < im->height; y++) {
|
||||
for (x = 0; x < im->width; x++) {
|
||||
XColor icolor;
|
||||
int ii, r, g, b;
|
||||
gulong dev, closest = 0xffffffff, close = 0;
|
||||
|
||||
icolor.pixel = p8[x];
|
||||
XQueryColor(ob_display, render_colormap, &icolor);
|
||||
|
||||
/* find the nearest color match */
|
||||
for (ii = 0; ii < pseudo_ncolors(); ii++) {
|
||||
/* find deviations */
|
||||
r = (pseudo_colors[ii].red - icolor.red) & 0xff;
|
||||
g = (pseudo_colors[ii].green - icolor.green) & 0xff;
|
||||
b = (pseudo_colors[ii].blue - icolor.blue) & 0xff;
|
||||
/* find a weighted absolute deviation */
|
||||
dev = (r * r) * (0xff - (icolor.red & 0xff)) +
|
||||
(g * g) * (0xff - (icolor.green & 0xff)) +
|
||||
(b * b) * (0xff - (icolor.blue & 0xff));
|
||||
|
||||
if (dev < closest) {
|
||||
closest = dev;
|
||||
close = ii;
|
||||
}
|
||||
}
|
||||
data[x] =
|
||||
(pseudo_colors[close].red & 0xff <<
|
||||
default_red_offset) +
|
||||
(pseudo_colors[close].green & 0xff <<
|
||||
default_green_offset) +
|
||||
(pseudo_colors[close].blue & 0xff <<
|
||||
default_blue_offset) +
|
||||
(0xff << default_alpha_offset);
|
||||
}
|
||||
data += im->width;
|
||||
p8 += im->bytes_per_line;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
g_message("your bit depth is currently unhandled\n");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,12 +25,14 @@ typedef u_int16_t pixel16;
|
|||
#define default_red_offset 0
|
||||
#define default_green_offset 8
|
||||
#define default_blue_offset 16
|
||||
#define endian MSBFirst
|
||||
#define default_alpha_offset 24
|
||||
#define render_endian MSBFirst
|
||||
#else
|
||||
#define default_alpha_offset 24
|
||||
#define default_red_offset 16
|
||||
#define default_green_offset 8
|
||||
#define default_blue_offset 0
|
||||
#define endian LSBFirst
|
||||
#define render_endian LSBFirst
|
||||
#endif /* G_BYTE_ORDER == G_BIG_ENDIAN */
|
||||
|
||||
|
||||
|
@ -48,6 +50,7 @@ color_rgb *color_parse(char *colorname);
|
|||
color_rgb *color_new(int r, int g, int b);
|
||||
void color_free(color_rgb *in);
|
||||
void reduce_depth(pixel32 *data, XImage *im);
|
||||
void increase_depth(pixel32 *data, XImage *im);
|
||||
|
||||
extern int render_red_offset;
|
||||
extern int render_green_offset;
|
||||
|
@ -57,6 +60,11 @@ extern int render_red_shift;
|
|||
extern int render_green_shift;
|
||||
extern int render_blue_shift;
|
||||
|
||||
extern int render_red_mask;
|
||||
extern int render_green_mask;
|
||||
extern int render_blue_mask;
|
||||
|
||||
extern int pseudo_bpc;
|
||||
#define pseudo_ncolors() (1 << (pseudo_bpc * 3))
|
||||
extern XColor *pseudo_colors;
|
||||
#endif /* __color_h */
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
void image_draw(pixel32 *target, TextureRGBA *rgba, Rect *position,
|
||||
Rect *surarea)
|
||||
{
|
||||
gulong *draw = rgba->data;
|
||||
pixel32 *draw = rgba->data;
|
||||
guint c, i, e, t, sfw, sfh;
|
||||
sfw = position->width;
|
||||
sfh = position->height;
|
||||
|
@ -50,10 +50,10 @@ void image_draw(pixel32 *target, TextureRGBA *rgba, Rect *position,
|
|||
for (i = 0, c = 0, t = position->x, e = sfw*sfh; i < e; ++i, ++t) {
|
||||
guchar alpha, r, g, b, bgr, bgg, bgb;
|
||||
|
||||
alpha = draw[i] >> 24;
|
||||
r = draw[i] >> 16;
|
||||
g = draw[i] >> 8;
|
||||
b = draw[i];
|
||||
alpha = draw[i] >> default_alpha_offset;
|
||||
r = draw[i] >> default_red_offset;
|
||||
g = draw[i] >> default_green_offset;
|
||||
b = draw[i] >> default_blue_offset;
|
||||
|
||||
if (c >= sfw) {
|
||||
c = 0;
|
||||
|
|
|
@ -19,6 +19,7 @@ Visual *render_visual;
|
|||
Colormap render_colormap;
|
||||
int render_red_offset = 0, render_green_offset = 0, render_blue_offset = 0;
|
||||
int render_red_shift, render_green_shift, render_blue_shift;
|
||||
int render_red_mask, render_green_mask, render_blue_mask;
|
||||
|
||||
void render_startup(void)
|
||||
{
|
||||
|
@ -87,9 +88,9 @@ void truecolor_startup(void)
|
|||
ZPixmap, 0, NULL, 1, 1, 32, 0);
|
||||
g_assert(timage != NULL);
|
||||
/* find the offsets for each color in the visual's masks */
|
||||
red_mask = timage->red_mask;
|
||||
green_mask = timage->green_mask;
|
||||
blue_mask = timage->blue_mask;
|
||||
render_red_mask = red_mask = timage->red_mask;
|
||||
render_green_mask = green_mask = timage->green_mask;
|
||||
render_blue_mask = blue_mask = timage->blue_mask;
|
||||
|
||||
render_red_offset = 0;
|
||||
render_green_offset = 0;
|
||||
|
@ -117,7 +118,7 @@ void pseudocolor_startup(void)
|
|||
/* determine the number of colors and the bits-per-color */
|
||||
pseudo_bpc = 2; /* XXX THIS SHOULD BE A USER OPTION */
|
||||
g_assert(pseudo_bpc >= 1);
|
||||
_ncolors = 1 << (pseudo_bpc * 3);
|
||||
_ncolors = pseudo_ncolors();
|
||||
|
||||
if (_ncolors > 1 << render_depth) {
|
||||
g_warning("PseudoRenderControl: Invalid colormap size. Resizing.\n");
|
||||
|
@ -166,7 +167,9 @@ void pseudocolor_startup(void)
|
|||
g = (pseudo_colors[i].green - icolors[ii].green) & 0xff;
|
||||
b = (pseudo_colors[i].blue - icolors[ii].blue) & 0xff;
|
||||
/* find a weighted absolute deviation */
|
||||
dev = (r * r) + (g * g) + (b * b);
|
||||
dev = (r * r) * (0xff - (icolors[ii].red & 0xff)) +
|
||||
(g * g) * (0xff - (icolors[ii].green & 0xff)) +
|
||||
(b * b) * (0xff - (icolors[ii].blue & 0xff));
|
||||
|
||||
if (dev < closest) {
|
||||
closest = dev;
|
||||
|
@ -400,23 +403,23 @@ void appearance_free(Appearance *a)
|
|||
|
||||
void pixel32_to_pixmap(pixel32 *in, Pixmap out, int x, int y, int w, int h)
|
||||
{
|
||||
unsigned char *scratch;
|
||||
pixel32 *scratch;
|
||||
XImage *im = NULL;
|
||||
im = XCreateImage(ob_display, render_visual, render_depth,
|
||||
ZPixmap, 0, NULL, w, h, 32, 0);
|
||||
g_assert(im != NULL);
|
||||
im->byte_order = endian;
|
||||
im->byte_order = render_endian;
|
||||
/* this malloc is a complete waste of time on normal 32bpp
|
||||
as reduce_depth just sets im->data = data and returns
|
||||
*/
|
||||
scratch = malloc(im->width * im->height * sizeof(pixel32));
|
||||
scratch = g_new(pixel32, im->width * im->height);
|
||||
im->data = (char*) scratch;
|
||||
reduce_depth(in, im);
|
||||
XPutImage(ob_display, out, DefaultGC(ob_display, ob_screen),
|
||||
im, 0, 0, x, y, w, h);
|
||||
im->data = NULL;
|
||||
XDestroyImage(im);
|
||||
free(scratch);
|
||||
g_free(scratch);
|
||||
}
|
||||
|
||||
void appearance_minsize(Appearance *l, int *w, int *h)
|
||||
|
@ -468,9 +471,50 @@ void appearance_minsize(Appearance *l, int *w, int *h)
|
|||
}
|
||||
}
|
||||
|
||||
void render_pixmap_to_rgba(Pixmap pmap, Pixmap mask,
|
||||
int *w, int *h, gulong **data)
|
||||
gboolean render_pixmap_to_rgba(Pixmap pmap, Pixmap mask,
|
||||
int *w, int *h, pixel32 **data)
|
||||
{
|
||||
*w = *h = 0;
|
||||
*data = NULL;
|
||||
Window xr;
|
||||
int xx, xy;
|
||||
guint pw, ph, mw, mh, xb, xd, i, x, y, di;
|
||||
XImage *xi, *xm = NULL;
|
||||
|
||||
if (!XGetGeometry(ob_display, pmap, &xr, &xx, &xy, &pw, &ph, &xb, &xd))
|
||||
return FALSE;
|
||||
if (mask) {
|
||||
if (!XGetGeometry(ob_display, mask, &xr, &xx, &xy, &mw, &mh, &xb, &xd))
|
||||
return FALSE;
|
||||
if (pw != mw || ph != mh || xd != 1)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
xi = XGetImage(ob_display, pmap, 0, 0, pw, ph, 0xffffffff, ZPixmap);
|
||||
if (!xi)
|
||||
return FALSE;
|
||||
|
||||
if (mask) {
|
||||
xm = XGetImage(ob_display, mask, 0, 0, mw, mh, 0xffffffff, ZPixmap);
|
||||
if (!xm)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*data = g_new(pixel32, pw * ph);
|
||||
increase_depth(*data, xi);
|
||||
|
||||
if (mask) {
|
||||
/* apply transparency from the mask */
|
||||
di = 0;
|
||||
for (i = 0, y = 0; y < ph; ++y) {
|
||||
for (x = 0; x < pw; ++x, ++i) {
|
||||
if (!((((unsigned)xm->data[di + x / 8]) >> (x % 8)) & 0x1))
|
||||
(*data)[i] &= ~(0xff << default_alpha_offset);
|
||||
}
|
||||
di += xm->bytes_per_line;
|
||||
}
|
||||
}
|
||||
|
||||
*w = pw;
|
||||
*h = ph;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -112,11 +112,11 @@ typedef struct TextureMask {
|
|||
typedef struct TextureRGBA {
|
||||
guint width;
|
||||
guint height;
|
||||
unsigned long *data;
|
||||
pixel32 *data;
|
||||
/* cached scaled so we don't have to scale often */
|
||||
guint cwidth;
|
||||
guint cheight;
|
||||
unsigned long *cache;
|
||||
pixel32 *cache;
|
||||
} TextureRGBA;
|
||||
|
||||
typedef union {
|
||||
|
@ -159,7 +159,7 @@ void pixel32_to_pixmap(pixel32 *in, Pixmap out, int x, int y, int w, int h);
|
|||
|
||||
void appearance_minsize(Appearance *l, int *w, int *h);
|
||||
|
||||
void render_pixmap_to_rgba(Pixmap pmap, Pixmap mask,
|
||||
int *w, int *h, gulong **data);
|
||||
gboolean render_pixmap_to_rgba(Pixmap pmap, Pixmap mask,
|
||||
int *w, int *h, pixel32 **data);
|
||||
|
||||
#endif /*__render_h*/
|
||||
|
|
Loading…
Reference in a new issue