windowmaker-wl/WINGs/wcolorpanel_x11.c

611 lines
20 KiB
C

/*
* ColorPanel for WINGs
*
* by ]d : Original idea and basic initial code
* Pascal Hofstee : Code for wheeldrawing and calculating
* colors from it.
* Primary coder of this Color Panel.
* Alban Hertroys : Optimizations for algorithms for color-
* wheel. Also custom ColorPalettes and
* magnifying glass. Secondary coder ;)
* Alfredo K. Kojima : For pointing out memory-allocation
* problems and similair code-issues
* Marco van Hylckama-Vlieg : For once again doing the artwork ;-)
*
*/
/* TODO:
* - Look at further optimization of colorWheel matrix calculation.
* It appears to be rather symmetric in angles of 60 degrees,
* while it is optimized in angles of 90 degrees.
* - Custom color-lists and custom colors in custom color-lists.
* - Stored colors
*/
#include "wconfig.h"
#include "WINGsP.h"
#include "wcolorpanelP.h"
#include "WINGs/WINGsX11.h"
#include <X11/Xatom.h>
#include <X11/cursorfont.h>
#ifdef USE_XSHAPE
#include <X11/extensions/shape.h>
#endif
/* Forward declaration from wcolorpanel.c */
static unsigned char getShift(unsigned char value);
static unsigned char Cursor_bits[] = {
0x00, 0x7e, 0x00, 0x00, 0xc0, 0x81, 0x03, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x08,
0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x20, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00,
0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x01, 0x42, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01,
0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01, 0x42, 0x80, 0x00,
0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x04, 0x00, 0x20,
0x00, 0x08, 0x00, 0x50, 0x00, 0x10, 0x00, 0x88, 0x00, 0x20, 0x00, 0x5c, 0x01, 0xc0, 0x81,
0x3b, 0x02, 0x00, 0x7e, 0x70, 0x05, 0x00, 0x00, 0xe0, 0x08, 0x00, 0x00, 0xc0, 0x15, 0x00,
0x00, 0x80, 0x23, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x5c,
0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x70
};
static unsigned char Cursor_shape_bits[] = {
0x00, 0x7e, 0x00, 0x00, 0xc0, 0x81, 0x03, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x08,
0x00, 0x08, 0x00, 0x10, 0x00, 0x04, 0x00, 0x20, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00,
0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x01, 0x42, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01,
0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x24, 0x80, 0x00, 0x01, 0x42, 0x80, 0x00,
0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x02, 0x00, 0x40, 0x00, 0x04, 0x00, 0x20,
0x00, 0x08, 0x00, 0x70, 0x00, 0x10, 0x00, 0xf8, 0x00, 0x20, 0x00, 0xfc, 0x01, 0xc0, 0x81,
0xfb, 0x03, 0x00, 0x7e, 0xf0, 0x07, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xc0, 0x1f, 0x00,
0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0xfc,
0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x70
};
/* Clip-mask for magnified pixels */
#define Cursor_mask_width 24
#define Cursor_mask_height 24
static unsigned char Cursor_mask_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0xc0, 0xff, 0x03, 0xe0, 0xff, 0x07,
0xf0, 0xff, 0x0f, 0xf8, 0xff, 0x1f, 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f,
0xfc, 0xff, 0x3f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f,
0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfc, 0xff, 0x3f,
0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0xf8, 0xff, 0x1f, 0xf0, 0xff, 0x0f,
0xe0, 0xff, 0x07, 0xc0, 0xff, 0x03, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00
};
typedef struct MovingView {
WMView *view; /* The view this is all about */
XImage *image; /* What's under the view */
XImage *dirtyRect; /* Storage of overlapped image area */
WMNativePixmap magPix; /* Magnified part of pixmap */
RColor color; /* Color of a pixel in the image */
int x, y; /* Position of view */
} MovingView;
/* Cursor hotspot and size constants */
#define Cursor_x_hot 11
#define Cursor_y_hot 11
#define Cursor_width 32
#define Cursor_height 32
static RColor ulongToRColor(WMScreen * scr, unsigned long value);
static WMNativeCursor magnifyGrabPointer(W_ColorPanel *panel);
static WMPoint magnifyInitialize(W_ColorPanel *panel);
static WMNativePixmap magnifyCreatePixmap(WMColorPanel * panel);
static void magnifyGetImageStored(W_ColorPanel *panel, int x1, int y1, int x2, int y2);
static XImage *magnifyGetImage(WMScreen * scr, XImage * image, int x, int y, int w, int h);
/****************** Magnifying Cursor Functions *******************/
static XImage *magnifyGetImage(WMScreen * scr, XImage * image, int x, int y, int w, int h)
{
int x0 = 0, y0 = 0, w0 = w, h0 = h;
const int displayWidth = DisplayWidth(scr->display, scr->screen),
displayHeight = DisplayHeight(scr->display, scr->screen);
if (!(image && image->data)) {
/* The image in ( (MovingView *)panel->magnifyGlass )->image does not exist yet.
* Grab one from the screen (not beyond) and use it from now on.
*/
if (!(image = XGetImage(scr->display, scr->rootWin,
x - Cursor_x_hot, y - Cursor_y_hot, w, h, AllPlanes, ZPixmap)))
wwarning(_("Color Panel: X failed request"));
return image;
}
/* Coordinate correction for back pixmap
* if magnifying glass is at screen-borders
*/
/* Figure 1: Shifting of rectangle-to-grab at top/left screen borders
* Hatched area is beyond screen border.
*
* |<-Cursor_x_hot->|
* ________________|_____
* |/ / / / / / /| | |
* | / / / / / / |(x,y) |
* |/_/_/_/_/_/_/|________|
* |<----x0----->|<--w0-->|
* 0
*/
/* Figure 2: Shifting of rectangle-to-grab at bottom/right
* screen borders
* Hatched area is beyond screen border
*
* |<-Cursor_x_hot->|
* ________________|_______________
* | | | / / / / / /|
* | (x,y)|/ / / / / / |
* |___________________|_/_/_/_/_/_/|
* |<-------w0-------->| |
* |<---------------w--|----------->|
* | |
* x0 Displaywidth-1
*/
if (x < Cursor_x_hot) { /* see fig. 1 */
x0 = Cursor_x_hot - x;
w0 = w - x0;
}
if (displayWidth - 1 < x - Cursor_x_hot + w) { /* see fig. 2 */
w0 = (displayWidth) - (x - Cursor_x_hot);
}
if (y < Cursor_y_hot) { /* see fig. 1 */
y0 = Cursor_y_hot - y;
h0 = h - y0;
}
if (displayHeight - 1 < y - Cursor_y_hot + h) { /* see fig. 2 */
h0 = (displayHeight) - (y - Cursor_y_hot);
}
/* end of coordinate correction */
/* Grab an image from the screen, clipped if necessary,
* and put it in the existing ( (MovingView *)panel->magnifyGlass )->image
* with the corresponding clipping offset.
*/
if (!XGetSubImage(scr->display, scr->rootWin,
x - Cursor_x_hot + x0, y - Cursor_y_hot + y0, w0, h0, AllPlanes, ZPixmap, image, x0, y0))
wwarning(_("Color Panel: X failed request"));
return NULL;
}
static void magnifyGetImageStored(WMColorPanel * panel, int x1, int y1, int x2, int y2)
{
/* (x1, y1) = topleft corner of existing rectangle
* (x2, y2) = topleft corner of new position
*/
W_Screen *scr = WMWidgetScreen(panel->win);
int xa = 0, ya = 0, xb = 0, yb = 0;
int width, height;
const int dx = abs(x2 - x1), dy = abs(y2 - y1);
XImage *image;
const int x_min = Cursor_x_hot,
y_min = Cursor_y_hot,
x_max = DisplayWidth(scr->display, scr->screen) - 1 -
(Cursor_mask_width - Cursor_x_hot),
y_max = DisplayHeight(scr->display, scr->screen) - 1 - (Cursor_mask_height - Cursor_y_hot);
if ((dx == 0) && (dy == 0) && ( (MovingView *)panel->magnifyGlass )->image)
return; /* No movement */
if (x1 < x2)
xa = dx;
else
xb = dx;
if (y1 < y2)
ya = dy;
else
yb = dy;
width = Cursor_mask_width - dx;
height = Cursor_mask_height - dy;
/* If the traversed distance is larger than the size of the magnifying
* glass contents, there is no need to do dirty rectangles. A whole new
* rectangle can be grabbed (unless that rectangle falls partially
* off screen).
* Destroying the image and setting it to NULL will achieve that later on.
*
* Of course, grabbing an XImage beyond the borders of the screen will
* cause trouble, this is considdered a special case. Part of the screen
* is grabbed, but there is no need for dirty rectangles.
*/
if ((width <= 0) || (height <= 0)) {
if ((x2 >= x_min) && (y2 >= y_min) && (x2 <= x_max) && (y2 <= y_max)) {
if (( (MovingView *)panel->magnifyGlass )->image)
XDestroyImage(( (MovingView *)panel->magnifyGlass )->image);
( (MovingView *)panel->magnifyGlass )->image = NULL;
}
} else {
if (( (MovingView *)panel->magnifyGlass )->image) {
/* Get dirty rectangle from ( (MovingView *)panel->magnifyGlass )->image */
( (MovingView *)panel->magnifyGlass )->dirtyRect =
XSubImage(( (MovingView *)panel->magnifyGlass )->image, xa, ya, width, height);
if (!( (MovingView *)panel->magnifyGlass )->dirtyRect) {
wwarning(_("Color Panel: X failed request"));
return; /* X returned a NULL from XSubImage */
}
}
}
/* Get image from screen */
image = magnifyGetImage(scr, ( (MovingView *)panel->magnifyGlass )->image, x2, y2, Cursor_mask_width, Cursor_mask_height);
if (image) { /* Only reassign if a *new* image was grabbed */
( (MovingView *)panel->magnifyGlass )->image = image;
return;
}
/* Copy previously stored rectangle on covered part of image */
if (( (MovingView *)panel->magnifyGlass )->image && ( (MovingView *)panel->magnifyGlass )->dirtyRect) {
int old_height;
/* "width" and "height" are used as coordinates here,
* and run from [0...width-1] and [0...height-1] respectively.
*/
width--;
height--;
old_height = height;
for (; width >= 0; width--)
for (height = old_height; height >= 0; height--)
XPutPixel(( (MovingView *)panel->magnifyGlass )->image, xb + width, yb + height,
XGetPixel(( (MovingView *)panel->magnifyGlass )->dirtyRect, width, height));
XDestroyImage(( (MovingView *)panel->magnifyGlass )->dirtyRect);
( (MovingView *)panel->magnifyGlass )->dirtyRect = NULL;
}
return;
}
static WMNativePixmap magnifyCreatePixmap(WMColorPanel * panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
int u, v;
#ifndef USE_XSHAPE
WMNativePixmap pixmap;
#endif
unsigned long color;
if (!( (MovingView *)panel->magnifyGlass )->image)
return WM_NATIVE_NONE;
if (!( (MovingView *)panel->magnifyGlass )->magPix)
return WM_NATIVE_NONE;
/*
* Copy an area of only 5x5 pixels from the center of the image.
*/
for (u = 0; u < 5; u++) {
for (v = 0; v < 5; v++) {
color = XGetPixel(( (MovingView *)panel->magnifyGlass )->image, u + 9, v + 9);
XSetForeground(scr->display, scr->copyGC, color);
if ((u == 2) && (v == 2)) /* (2,2) is center pixel (unmagn.) */
( (MovingView *)panel->magnifyGlass )->color = ulongToRColor(scr, color);
/* The center square must eventually be centered around the
* hotspot. The image needs shifting to achieve this. The amount of
* shifting is (Cursor_mask_width/2 - 2 * square_size) = 11-10 = 1
* _ _ _ _ _
* |_|_|_|_|_|
* ^------- center of center square == Cursor_x_hot
*/
XFillRectangle(scr->display, ( (MovingView *)panel->magnifyGlass )->magPix,
scr->copyGC,
u * 5 + (u == 0 ? 0 : -1), v * 5 + (v == 0 ? 0 : -1),
(u == 0 ? 4 : 5), (v == 0 ? 4 : 5));
}
}
#ifdef USE_XSHAPE
return ( (MovingView *)panel->magnifyGlass )->magPix;
#else
pixmap = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width, Cursor_mask_height, scr->depth);
if (!pixmap)
return WM_NATIVE_NONE;
XPutImage(scr->display, pixmap, scr->copyGC, ( (MovingView *)panel->magnifyGlass )->image,
0, 0, 0, 0, Cursor_mask_width, Cursor_mask_height);
/* Copy the magnified pixmap, with the clip mask, to background pixmap */
XCopyArea(scr->display, ( (MovingView *)panel->magnifyGlass )->magPix, pixmap,
scr->clipGC, 0, 0, Cursor_mask_width, Cursor_mask_height, 0, 0);
/* (2,2) puts center pixel on center of glass */
return pixmap;
#endif
}
static WMView *magnifyCreateView(W_ColorPanel *panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
WMView *magView;
magView = W_CreateTopView(scr);
if (!magView)
return NULL;
magView->self = panel->win;
magView->flags.topLevel = 1;
magView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
magView->attribs.override_redirect = True;
magView->attribs.save_under = True;
W_ResizeView(magView, Cursor_mask_width, Cursor_mask_height);
W_RealizeView(magView);
return magView;
}
static WMNativeCursor magnifyGrabPointer(W_ColorPanel *panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
WMNativePixmap magPixmap, magPixmap2;
WMNativeCursor magCursor;
XColor fgColor = { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 };
XColor bgColor = { 0, 0xbf00, 0xa000, 0x5000, DoRed | DoGreen | DoBlue, 0 };
/* WMNativeCursor creation stuff */
magPixmap = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
(char *)Cursor_bits, Cursor_width, Cursor_height, 1, 0, 1);
magPixmap2 = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
(char *)Cursor_shape_bits, Cursor_width, Cursor_height, 1, 0, 1);
magCursor = XCreatePixmapCursor(scr->display, magPixmap, magPixmap2,
&fgColor, &bgColor, Cursor_x_hot, Cursor_y_hot);
XFreePixmap(scr->display, magPixmap);
XFreePixmap(scr->display, magPixmap2);
XRecolorCursor(scr->display, magCursor, &fgColor, &bgColor);
/* Set up Pointer */
XGrabPointer(scr->display, ( (MovingView *)panel->magnifyGlass )->view->window, True,
WM_EVMASK_POINTER_MOTION | WM_EVMASK_BUTTON_PRESS,
WM_GRAB_MODE_ASYNC, WM_GRAB_MODE_ASYNC, scr->rootWin, magCursor, WM_CURRENT_TIME);
return magCursor;
}
static WMPoint magnifyInitialize(W_ColorPanel *panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
int x, y, u, v;
unsigned int mask;
WMNativePixmap pixmap, clip_mask;
WMPoint point;
WNativeWindow root_return, child_return;
clip_mask = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
(char *)Cursor_mask_bits, Cursor_mask_width, Cursor_mask_height,
1, 0, 1);
( (MovingView *)panel->magnifyGlass )->magPix = XCreatePixmap(scr->display, W_DRAWABLE(scr),
5 * 5 - 1, 5 * 5 - 1, scr->depth);
XQueryPointer(scr->display, scr->rootWin, &root_return, &child_return, &x, &y, &u, &v, &mask);
( (MovingView *)panel->magnifyGlass )->image = NULL;
/* Clipmask to make magnified view-contents circular */
#ifdef USE_XSHAPE
XShapeCombineMask(scr->display, WMViewXID(( (MovingView *)panel->magnifyGlass )->view),
ShapeBounding, 0, 0, clip_mask, ShapeSet);
#else
/* Clip circle in glass cursor */
XSetClipMask(scr->display, scr->clipGC, clip_mask);
XSetClipOrigin(scr->display, scr->clipGC, 0, 0);
#endif
XFreePixmap(scr->display, clip_mask);
/* Draw initial magnifying glass contents */
magnifyGetImageStored(panel, x, y, x, y);
pixmap = magnifyCreatePixmap(panel);
XSetWindowBackgroundPixmap(scr->display, WMViewXID(( (MovingView *)panel->magnifyGlass )->view), pixmap);
XClearWindow(scr->display, WMViewXID(( (MovingView *)panel->magnifyGlass )->view));
XFlush(scr->display);
#ifndef USE_XSHAPE
XFreePixmap(scr->display, pixmap);
#endif
point.x = x;
point.y = y;
return point;
}
void W_ColorPanelMagnify(WMWidget * w, void *data)
{
W_ColorPanel *panel = (W_ColorPanel *) (data);
W_Screen *scr = WMWidgetScreen(panel->win);
WMNativeCursor magCursor;
WMNativePixmap pixmap;
WMEvent event;
XEvent rawEvent;
WMPoint initialPosition;
/* Parameter not used, but tell the compiler that it is ok */
(void) w;
/* Destroy wheelBackImg, so it'll update properly */
if (panel->selectionBackImg) {
scr->renderBackend->pixmap_free(scr->renderBackendCtx, panel->selectionBackImg);
panel->selectionBackImg = WM_NATIVE_NONE;
}
/* Create magnifying glass */
panel->magnifyGlass = wmalloc(sizeof(MovingView));
( (MovingView *)panel->magnifyGlass )->view = magnifyCreateView(panel);
if (!( (MovingView *)panel->magnifyGlass )->view)
return;
initialPosition = magnifyInitialize(panel);
( (MovingView *)panel->magnifyGlass )->x = initialPosition.x;
( (MovingView *)panel->magnifyGlass )->y = initialPosition.y;
W_MoveView(( (MovingView *)panel->magnifyGlass )->view,
( (MovingView *)panel->magnifyGlass )->x - Cursor_x_hot, ( (MovingView *)panel->magnifyGlass )->y - Cursor_y_hot);
W_MapView(( (MovingView *)panel->magnifyGlass )->view);
magCursor = magnifyGrabPointer(panel);
while (( (MovingView *)panel->magnifyGlass )->image) {
WMNextEvent(scr, &event);
/* Pack motion events */
while (XCheckTypedEvent(scr->display, MotionNotify, &rawEvent)) {
}
switch (event.type) {
case WME_BUTTON_PRESS:
XDestroyImage(( (MovingView *)panel->magnifyGlass )->image);
( (MovingView *)panel->magnifyGlass )->image = NULL;
if (event.u.button.button == Button1) {
panel->color.rgb = ( (MovingView *)panel->magnifyGlass )->color;
panel->color.set = cpRGB;
updateSwatch(panel, panel->color);
}
switch (panel->mode) {
case WMWheelModeColorPanel:
wheelInit(panel);
wheelRender(panel);
wheelPaint(panel);
break;
case WMGrayModeColorPanel:
grayInit(panel);
break;
case WMRGBModeColorPanel:
rgbInit(panel);
break;
case WMCMYKModeColorPanel:
cmykInit(panel);
break;
case WMHSBModeColorPanel:
hsbInit(panel);
break;
default:
break;
}
panel->lastChanged = panel->mode;
WMSetButtonSelected(panel->magnifyBtn, False);
break;
case WME_MOTION:
while (XPending(scr->display)) {
XEvent ev;
XPeekEvent(scr->display, &ev);
if (ev.type == MotionNotify)
XNextEvent(scr->display, &rawEvent);
else
break;
}
/* Get a "dirty rectangle" */
magnifyGetImageStored(panel,
( (MovingView *)panel->magnifyGlass )->x, ( (MovingView *)panel->magnifyGlass )->y,
event.u.motion.x_root, event.u.motion.y_root);
/* Update coordinates */
( (MovingView *)panel->magnifyGlass )->x = event.u.motion.x_root;
( (MovingView *)panel->magnifyGlass )->y = event.u.motion.y_root;
/* Move view */
W_MoveView(( (MovingView *)panel->magnifyGlass )->view,
( (MovingView *)panel->magnifyGlass )->x - Cursor_x_hot, ( (MovingView *)panel->magnifyGlass )->y - Cursor_y_hot);
/* Put new image (with magn.) in view */
pixmap = magnifyCreatePixmap(panel);
if (pixmap != WM_NATIVE_NONE) {
/* Change the window background */
XSetWindowBackgroundPixmap(scr->display,
WMViewXID(( (MovingView *)panel->magnifyGlass )->view), pixmap);
/* Force an Expose (handled by X) */
XClearWindow(scr->display, WMViewXID(( (MovingView *)panel->magnifyGlass )->view));
/* Synchronize the event queue, so the Expose is handled NOW */
XFlush(scr->display);
#ifndef USE_XSHAPE
XFreePixmap(scr->display, pixmap);
#endif
}
break;
/* Try XQueryPointer for this !!! It returns windows that the pointer
* is over. Note: We found this solving the invisible donkey cap bug
*/
#if 0 /* As it is impossible to make this work in all cases,
* we consider it confusing. Therefore we disabled it.
*/
case WME_FOCUS_OUT: /* fall through */
case WME_FOCUS_IN:
/*
* Color Panel window (panel->win) lost or received focus.
* We need to update the pixmap in the magnifying glass.
*
* BUG Doesn't work with focus switches between two windows
* if none of them is the color panel.
*/
XUngrabPointer(scr->display, WM_CURRENT_TIME);
W_UnmapView(( (MovingView *)panel->magnifyGlass )->view);
magnifyInitialize(panel);
W_MapView(( (MovingView *)panel->magnifyGlass )->view);
XGrabPointer(scr->display, ( (MovingView *)panel->magnifyGlass )->view->window,
True, WM_EVMASK_POINTER_MOTION | WM_EVMASK_BUTTON_PRESS,
WM_GRAB_MODE_ASYNC, WM_GRAB_MODE_ASYNC, scr->rootWin, magCursor, WM_CURRENT_TIME);
break;
#endif
default:
WMHandleEvent(&event);
break;
} /* of switch */
}
XUngrabPointer(scr->display, WM_CURRENT_TIME);
XFreeCursor(scr->display, magCursor);
XFreePixmap(scr->display, ( (MovingView *)panel->magnifyGlass )->magPix);
( (MovingView *)panel->magnifyGlass )->magPix = WM_NATIVE_NONE;
W_UnmapView(( (MovingView *)panel->magnifyGlass )->view);
W_DestroyView(( (MovingView *)panel->magnifyGlass )->view);
( (MovingView *)panel->magnifyGlass )->view = NULL;
wfree(panel->magnifyGlass);
}
static RColor ulongToRColor(WMScreen * scr, unsigned long value)
{
RColor color;
XColor *xcolor = NULL;
xcolor = wmalloc(sizeof(XColor));
xcolor->pixel = value;
XQueryColor(scr->display, scr->rcontext->cmap, xcolor);
color.red = xcolor->red >> 8;
color.green = xcolor->green >> 8;
color.blue = xcolor->blue >> 8;
color.alpha = 0;
wfree(xcolor);
}