8 char *WMColorWellDidChangeNotification
= "WMColorWellDidChangeNotification";
11 typedef struct W_ColorWell
{
25 unsigned int active
:1;
26 unsigned int bordered
:1;
30 static char *_ColorWellActivatedNotification
= "_ColorWellActivatedNotification";
34 static void destroyColorWell(ColorWell
*cPtr
);
35 static void paintColorWell(ColorWell
*cPtr
);
37 static void handleEvents(XEvent
*event
, void *data
);
39 static void handleDragEvents(XEvent
*event
, void *data
);
41 static void handleActionEvents(XEvent
*event
, void *data
);
43 static void willResizeColorWell();
47 W_ViewDelegate _ColorWellViewDelegate
= {
57 static WMDragSourceProcs dragProcs
= {
62 #define DEFAULT_WIDTH 60
63 #define DEFAULT_HEIGHT 30
64 #define DEFAULT_BORDER_WIDTH 6
72 colorChangedObserver(void *data
, WMNotification
*notification
)
74 WMColorPanel
*panel
= (WMColorPanel
*)WMGetNotificationObject(notification
);
75 WMColorWell
*cPtr
= (WMColorWell
*)data
;
78 if (!cPtr
->flags
.active
)
81 color
= WMGetColorPanelColor(panel
);
83 WMSetColorWellColor(cPtr
, color
);
84 WMPostNotificationName(WMColorWellDidChangeNotification
, cPtr
, NULL
);
89 updateColorCallback(void *self
, void *data
)
91 WMColorPanel
*panel
= (WMColorPanel
*)self
;
92 WMColorWell
*cPtr
= (ColorWell
*)data
;
95 color
= WMGetColorPanelColor(panel
);
96 WMSetColorWellColor(cPtr
, color
);
97 WMPostNotificationName(WMColorWellDidChangeNotification
, cPtr
, NULL
);
103 activatedObserver(void *data
, WMNotification
*notification
)
106 WMColorWell *cPtr = (WMColorWell*)data;
108 if (!cPtr->flags.active || WMGetNotificationObject(notification) == cPtr)
111 W_SetViewBackgroundColor(cPtr->view, WMWidgetScreen(cPtr)->gray);
112 paintColorWell(cPtr);
114 cPtr->flags.active = 0;
121 WMCreateColorWell(WMWidget
*parent
)
125 cPtr
= wmalloc(sizeof(ColorWell
));
126 memset(cPtr
, 0, sizeof(ColorWell
));
128 cPtr
->widgetClass
= WC_ColorWell
;
130 cPtr
->view
= W_CreateView(W_VIEW(parent
));
135 cPtr
->view
->self
= cPtr
;
137 cPtr
->view
->delegate
= &_ColorWellViewDelegate
;
139 cPtr
->colorView
= W_CreateView(cPtr
->view
);
140 if (!cPtr
->colorView
) {
141 W_DestroyView(cPtr
->view
);
145 cPtr
->colorView
->self
= cPtr
;
147 WMCreateEventHandler(cPtr
->view
, ExposureMask
|StructureNotifyMask
148 |ClientMessageMask
, handleEvents
, cPtr
);
150 WMCreateEventHandler(cPtr
->colorView
, ExposureMask
, handleEvents
, cPtr
);
152 WMCreateEventHandler(cPtr
->colorView
, ButtonPressMask
|ButtonMotionMask
153 |EnterWindowMask
, handleDragEvents
, cPtr
);
155 WMCreateEventHandler(cPtr
->view
, ButtonPressMask
, handleActionEvents
,
158 cPtr
->colorView
->flags
.mapWhenRealized
= 1;
160 cPtr
->flags
.bordered
= 1;
162 W_ResizeView(cPtr
->view
, DEFAULT_WIDTH
, DEFAULT_HEIGHT
);
164 WMAddNotificationObserver(activatedObserver
, cPtr
,
165 _ColorWellActivatedNotification
, NULL
);
167 cPtr
->color
= WMBlackColor(WMWidgetScreen(cPtr
));
169 WMAddNotificationObserver(colorChangedObserver
, cPtr
,
170 WMColorPanelColorChangedNotification
, NULL
);
177 WMSetColorWellColor(WMColorWell
*cPtr
, WMColor
*color
)
180 WMReleaseColor(cPtr
->color
);
182 cPtr
->color
= WMRetainColor(color
);
184 if (cPtr
->colorView
->flags
.realized
&& cPtr
->colorView
->flags
.mapped
)
185 paintColorWell(cPtr
);
190 WMGetColorWellColor(WMColorWell
*cPtr
)
197 WSetColorWellBordered(WMColorWell
*cPtr
, Bool flag
)
199 if (cPtr
->flags
.bordered
!= flag
) {
200 cPtr
->flags
.bordered
= flag
;
201 W_ResizeView(cPtr
->view
, cPtr
->view
->size
.width
, cPtr
->view
->size
.height
);
206 #define MIN(a,b) ((a) > (b) ? (b) : (a))
209 willResizeColorWell(W_ViewDelegate
*self
, WMView
*view
,
210 unsigned int *width
, unsigned int *height
)
212 WMColorWell
*cPtr
= (WMColorWell
*)view
->self
;
215 if (cPtr
->flags
.bordered
) {
217 if (*width
< MIN_WIDTH
)
219 if (*height
< MIN_HEIGHT
)
220 *height
= MIN_HEIGHT
;
222 bw
= (int)((float)MIN(*width
, *height
)*0.24);
224 W_ResizeView(cPtr
->colorView
, *width
-2*bw
, *height
-2*bw
);
226 if (cPtr
->colorView
->pos
.x
!=bw
|| cPtr
->colorView
->pos
.y
!=bw
)
227 W_MoveView(cPtr
->colorView
, bw
, bw
);
229 W_ResizeView(cPtr
->colorView
, *width
, *height
);
231 W_MoveView(cPtr
->colorView
, 0, 0);
237 paintColorWell(ColorWell
*cPtr
)
239 W_Screen
*scr
= cPtr
->view
->screen
;
241 W_DrawRelief(scr
, cPtr
->view
->window
, 0, 0, cPtr
->view
->size
.width
,
242 cPtr
->view
->size
.height
, WRRaised
);
244 W_DrawRelief(scr
, cPtr
->colorView
->window
, 0, 0,
245 cPtr
->colorView
->size
.width
, cPtr
->colorView
->size
.height
,
249 WMPaintColorSwatch(cPtr
->color
, cPtr
->colorView
->window
,
250 2, 2, cPtr
->colorView
->size
.width
-4,
251 cPtr
->colorView
->size
.height
-4);
257 handleEvents(XEvent
*event
, void *data
)
259 ColorWell
*cPtr
= (ColorWell
*)data
;
261 CHECK_CLASS(data
, WC_ColorWell
);
264 switch (event
->type
) {
266 if (event
->xexpose
.count
!=0)
268 paintColorWell(cPtr
);
272 destroyColorWell(cPtr
);
280 makeDragPixmap(WMColorWell
*cPtr
)
282 WMScreen
*scr
= cPtr
->view
->screen
;
285 pix
= XCreatePixmap(scr
->display
, W_DRAWABLE(scr
), 16, 16, scr
->depth
);
287 XFillRectangle(scr
->display
, pix
, WMColorGC(cPtr
->color
), 0, 0, 15, 15);
289 XDrawRectangle(scr
->display
, pix
, WMColorGC(scr
->black
), 0, 0, 15, 15);
291 return WMCreatePixmapFromXPixmaps(scr
, pix
, None
, 16, 16, scr
->depth
);
296 slideView(WMView
*view
, int srcX
, int srcY
, int dstX
, int dstY
)
309 dx
= (double)(dstX
-srcX
)/20.0;
310 dy
= (double)(dstY
-srcY
)/20.0;
312 for (i
= 0; i
< 20; i
++) {
313 W_MoveView(view
, x
, y
);
314 XFlush(view
->screen
->display
);
324 findChildInWindow(Display
*dpy
, Window toplevel
, int x
, int y
)
331 if (!XQueryTree(dpy
, toplevel
, &foo
, &bar
,
332 &children
, &nchildren
) || children
== NULL
) {
336 /* first window that contains the point is the one */
337 for (i
= nchildren
-1; i
>= 0; i
--) {
338 XWindowAttributes attr
;
340 if (XGetWindowAttributes(dpy
, children
[i
], &attr
)
341 && attr
.map_state
== IsViewable
342 && x
>= attr
.x
&& y
>= attr
.y
343 && x
< attr
.x
+ attr
.width
&& y
< attr
.y
+ attr
.height
) {
346 child
= findChildInWindow(dpy
, children
[i
],
347 x
- attr
.x
, y
- attr
.y
);
364 findWindowUnderDragPointer(WMScreen
*scr
, int x
, int y
, Window iconWindow
)
371 if (!XQueryTree(scr
->display
, scr
->rootWin
, &foo
, &bar
,
372 &children
, &nchildren
) || children
== NULL
) {
376 /* try to find the window below the iconWindow by traversing
377 * the whole window list */
379 /* first find the position of the iconWindow */
380 for (i
= nchildren
-1; i
>= 0; i
--) {
381 if (children
[i
] == iconWindow
) {
391 /* first window that contains the point is the one */
392 for (; i
>= 0; i
--) {
393 XWindowAttributes attr
;
396 if (XGetWindowAttributes(scr
->display
, children
[i
], &attr
)
397 && attr
.map_state
== IsViewable
398 && x
>= attr
.x
&& y
>= attr
.y
399 && x
< attr
.x
+ attr
.width
&& y
< attr
.y
+ attr
.height
400 && (child
= findChildInWindow(scr
->display
, children
[i
],
401 x
- attr
.x
, y
- attr
.y
))) {
414 dragColor(ColorWell
*cPtr
, XEvent
*event
, WMPixmap
*image
)
417 WMScreen
*scr
= cPtr
->view
->screen
;
418 Display
*dpy
= scr
->display
;
419 XColor black
= {0, 0,0,0, DoRed
|DoGreen
|DoBlue
};
420 XColor green
= {0x0045b045, 0x4500,0xb000,0x4500, DoRed
|DoGreen
|DoBlue
};
421 XColor back
= {0, 0xffff,0xffff,0xffff, DoRed
|DoGreen
|DoBlue
};
423 WMColorWell
*activeWell
= NULL
;
425 dragView
= W_CreateTopView(scr
);
427 W_ResizeView(dragView
, 16, 16);
428 dragView
->attribFlags
|= CWOverrideRedirect
| CWSaveUnder
;
429 dragView
->attribs
.event_mask
= StructureNotifyMask
;
430 dragView
->attribs
.override_redirect
= True
;
431 dragView
->attribs
.save_under
= True
;
433 W_MoveView(dragView
, event
->xmotion
.x_root
-8, event
->xmotion
.y_root
-8);
435 W_RealizeView(dragView
);
439 XSetWindowBackgroundPixmap(dpy
, dragView
->window
, WMGetPixmapXID(image
));
440 XClearWindow(dpy
, dragView
->window
);
443 XGrabPointer(dpy
, scr
->rootWin
, True
,
444 ButtonMotionMask
|ButtonReleaseMask
,
445 GrabModeSync
, GrabModeAsync
,
446 scr
->rootWin
, scr
->defaultCursor
, CurrentTime
);
453 XAllowEvents(dpy
, SyncPointer
, CurrentTime
);
454 WMNextEvent(dpy
, &ev
);
458 if (activeWell
!= NULL
) {
459 WMSetColorWellColor(activeWell
, cPtr
->color
);
460 WMPostNotificationName(WMColorWellDidChangeNotification
,
463 slideView(dragView
, ev
.xbutton
.x_root
, ev
.xbutton
.y_root
,
464 event
->xmotion
.x_root
, event
->xmotion
.y_root
);
471 while (XCheckTypedEvent(dpy
, MotionNotify
, &ev
)) ;
473 W_MoveView(dragView
, ev
.xmotion
.x_root
-8, ev
.xmotion
.y_root
-8);
475 win
= findWindowUnderDragPointer(scr
, ev
.xmotion
.x_root
,
479 if (win
!= None
&& win
!= scr
->rootWin
) {
480 view
= W_GetViewForXWindow(dpy
, win
);
485 if (view
&& view
->self
&& W_CLASS(view
->self
) == WC_ColorWell
486 && view
->self
!= activeWell
&& view
->self
!= cPtr
) {
488 activeWell
= view
->self
;
489 XRecolorCursor(dpy
, scr
->defaultCursor
, &green
, &back
);
491 } else if (!view
|| view
->self
!= activeWell
) {
493 XRecolorCursor(dpy
, scr
->defaultCursor
, &black
, &back
);
503 XUngrabPointer(dpy
, CurrentTime
);
504 XRecolorCursor(dpy
, scr
->defaultCursor
, &black
, &back
);
506 W_DestroyView(dragView
);
511 handleDragEvents(XEvent
*event
, void *data
)
513 WMColorWell
*cPtr
= (ColorWell
*)data
;
515 switch (event
->type
) {
517 if (event
->xbutton
.button
== Button1
) {
518 cPtr
->ipoint
.x
= event
->xbutton
.x
;
519 cPtr
->ipoint
.y
= event
->xbutton
.y
;
524 if (event
->xmotion
.state
& Button1Mask
) {
525 if (abs(cPtr
->ipoint
.x
- event
->xmotion
.x
) > 4
526 || abs(cPtr
->ipoint
.y
- event
->xmotion
.y
) > 4) {
532 pixmap
= makeDragPixmap(cPtr
);
535 WMDragImageFromView(cPtr->view, pixmap, cPtr->view->pos,
539 dragColor(cPtr
, event
, pixmap
);
541 WMReleasePixmap(pixmap
);
550 handleActionEvents(XEvent
*event
, void *data
)
552 WMColorWell
*cPtr
= (ColorWell
*)data
;
553 WMScreen
*scr
= WMWidgetScreen(cPtr
);
554 WMColorPanel
*cpanel
;
556 if (cPtr
->flags
.active
)
557 W_SetViewBackgroundColor(cPtr
->view
, scr
->gray
);
559 W_SetViewBackgroundColor(cPtr
->view
, scr
->white
);
560 paintColorWell(cPtr
);
562 cPtr
->flags
.active
^= 1;
564 if (cPtr
->flags
.active
) {
565 WMPostNotificationName(_ColorWellActivatedNotification
, cPtr
, NULL
);
567 cpanel
= WMGetColorPanel(scr
);
569 WMSetColorPanelAction(cpanel
, updateColorCallback
, cPtr
);
572 WMSetColorPanelColor(cpanel
, cPtr
->color
);
573 WMShowColorPanel(cpanel
);
578 destroyColorWell(ColorWell
*cPtr
)
580 WMRemoveNotificationObserver(cPtr
);
583 WMReleaseColor(cPtr
->color
);