611 lines
20 KiB
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);
|
|
}
|