- Fixed focus handling for windows that set WM_HINTS.take_focus = False.
[wmaker-crm.git] / WINGs / wcolorwell.c
blob5dcfa04f1cc70c9957659c68a4ffe15281902fd0
5 #include "WINGsP.h"
8 char *WMColorWellDidChangeNotification = "WMColorWellDidChangeNotification";
11 typedef struct W_ColorWell {
12 W_Class widgetClass;
13 WMView *view;
15 WMView *colorView;
17 WMColor *color;
19 WMAction *action;
20 void *clientData;
22 WMPoint ipoint;
24 struct {
25 unsigned int active:1;
26 unsigned int bordered:1;
27 } flags;
28 } ColorWell;
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 = {
48 NULL,
49 NULL,
50 NULL,
51 NULL,
52 willResizeColorWell
56 static unsigned draggingSourceOperation(WMView *self, Bool local);
58 static WMData* fetchDragData(WMView *self, char *type);
60 static WMDragSourceProcs _DragSourceProcs = {
61 draggingSourceOperation,
62 NULL,
63 NULL,
64 fetchDragData
68 static unsigned draggingEntered(WMView *self, WMDraggingInfo *info);
69 static unsigned draggingUpdated(WMView *self, WMDraggingInfo *info);
70 static void draggingExited(WMView *self, WMDraggingInfo *info);
71 static char *prepareForDragOperation(WMView *self, WMDraggingInfo *info);
72 static Bool performDragOperation(WMView *self, WMDraggingInfo *info,
73 WMData *data);
74 static void concludeDragOperation(WMView *self, WMDraggingInfo *info);
76 static WMDragDestinationProcs _DragDestinationProcs = {
77 draggingEntered,
78 draggingUpdated,
79 draggingExited,
80 prepareForDragOperation,
81 performDragOperation,
82 concludeDragOperation
86 #define DEFAULT_WIDTH 60
87 #define DEFAULT_HEIGHT 30
88 #define DEFAULT_BORDER_WIDTH 6
90 #define MIN_WIDTH 16
91 #define MIN_HEIGHT 8
95 static void
96 colorChangedObserver(void *data, WMNotification *notification)
98 WMColorPanel *panel = (WMColorPanel*)WMGetNotificationObject(notification);
99 WMColorWell *cPtr = (WMColorWell*)data;
100 WMColor *color;
102 if (!cPtr->flags.active)
103 return;
105 color = WMGetColorPanelColor(panel);
107 WMSetColorWellColor(cPtr, color);
108 WMPostNotificationName(WMColorWellDidChangeNotification, cPtr, NULL);
112 static void
113 updateColorCallback(void *self, void *data)
115 WMColorPanel *panel = (WMColorPanel*)self;
116 WMColorWell *cPtr = (ColorWell*)data;
117 WMColor *color;
119 color = WMGetColorPanelColor(panel);
120 WMSetColorWellColor(cPtr, color);
121 WMPostNotificationName(WMColorWellDidChangeNotification, cPtr, NULL);
126 static void
127 activatedObserver(void *data, WMNotification *notification)
130 WMColorWell *cPtr = (WMColorWell*)data;
132 if (!cPtr->flags.active || WMGetNotificationObject(notification) == cPtr)
133 return;
135 W_SetViewBackgroundColor(cPtr->view, WMWidgetScreen(cPtr)->gray);
136 paintColorWell(cPtr);
138 cPtr->flags.active = 0;
144 WMColorWell*
145 WMCreateColorWell(WMWidget *parent)
147 ColorWell *cPtr;
149 cPtr = wmalloc(sizeof(ColorWell));
150 memset(cPtr, 0, sizeof(ColorWell));
152 cPtr->widgetClass = WC_ColorWell;
154 cPtr->view = W_CreateView(W_VIEW(parent));
155 if (!cPtr->view) {
156 wfree(cPtr);
157 return NULL;
159 cPtr->view->self = cPtr;
161 cPtr->view->delegate = &_ColorWellViewDelegate;
163 cPtr->colorView = W_CreateView(cPtr->view);
164 if (!cPtr->colorView) {
165 W_DestroyView(cPtr->view);
166 wfree(cPtr);
167 return NULL;
169 cPtr->colorView->self = cPtr;
171 WMCreateEventHandler(cPtr->view, ExposureMask|StructureNotifyMask
172 |ClientMessageMask, handleEvents, cPtr);
174 WMCreateEventHandler(cPtr->colorView, ExposureMask, handleEvents, cPtr);
176 WMCreateEventHandler(cPtr->colorView, ButtonPressMask|ButtonMotionMask
177 |EnterWindowMask, handleDragEvents, cPtr);
179 WMCreateEventHandler(cPtr->view, ButtonPressMask, handleActionEvents,
180 cPtr);
182 cPtr->colorView->flags.mapWhenRealized = 1;
184 cPtr->flags.bordered = 1;
186 W_ResizeView(cPtr->view, DEFAULT_WIDTH, DEFAULT_HEIGHT);
188 WMAddNotificationObserver(activatedObserver, cPtr,
189 _ColorWellActivatedNotification, NULL);
191 cPtr->color = WMBlackColor(WMWidgetScreen(cPtr));
193 WMAddNotificationObserver(colorChangedObserver, cPtr,
194 WMColorPanelColorChangedNotification, NULL);
196 WMSetViewDragSourceProcs(cPtr->colorView, &_DragSourceProcs);
197 WMSetViewDragDestinationProcs(cPtr->colorView, &_DragDestinationProcs);
200 char *types[2] = {"application/X-color", NULL};
202 WMRegisterViewForDraggedTypes(cPtr->colorView, types);
205 return cPtr;
209 void
210 WMSetColorWellColor(WMColorWell *cPtr, WMColor *color)
212 if (cPtr->color)
213 WMReleaseColor(cPtr->color);
215 cPtr->color = WMRetainColor(color);
217 if (cPtr->colorView->flags.realized && cPtr->colorView->flags.mapped)
218 paintColorWell(cPtr);
222 WMColor*
223 WMGetColorWellColor(WMColorWell *cPtr)
225 return cPtr->color;
229 void
230 WSetColorWellBordered(WMColorWell *cPtr, Bool flag)
232 flag = ((flag==0) ? 0 : 1);
233 if (cPtr->flags.bordered != flag) {
234 cPtr->flags.bordered = flag;
235 W_ResizeView(cPtr->view, cPtr->view->size.width, cPtr->view->size.height);
240 static void
241 willResizeColorWell(W_ViewDelegate *self, WMView *view,
242 unsigned int *width, unsigned int *height)
244 WMColorWell *cPtr = (WMColorWell*)view->self;
245 int bw;
247 if (cPtr->flags.bordered) {
249 if (*width < MIN_WIDTH)
250 *width = MIN_WIDTH;
251 if (*height < MIN_HEIGHT)
252 *height = MIN_HEIGHT;
254 bw = (int)((float)WMIN(*width, *height)*0.24);
256 W_ResizeView(cPtr->colorView, *width-2*bw, *height-2*bw);
258 if (cPtr->colorView->pos.x!=bw || cPtr->colorView->pos.y!=bw)
259 W_MoveView(cPtr->colorView, bw, bw);
260 } else {
261 W_ResizeView(cPtr->colorView, *width, *height);
263 W_MoveView(cPtr->colorView, 0, 0);
268 static void
269 paintColorWell(ColorWell *cPtr)
271 W_Screen *scr = cPtr->view->screen;
273 W_DrawRelief(scr, cPtr->view->window, 0, 0, cPtr->view->size.width,
274 cPtr->view->size.height, WRRaised);
276 W_DrawRelief(scr, cPtr->colorView->window, 0, 0,
277 cPtr->colorView->size.width, cPtr->colorView->size.height,
278 WRSunken);
280 if (cPtr->color)
281 WMPaintColorSwatch(cPtr->color, cPtr->colorView->window,
282 2, 2, cPtr->colorView->size.width-4,
283 cPtr->colorView->size.height-4);
288 static void
289 handleEvents(XEvent *event, void *data)
291 ColorWell *cPtr = (ColorWell*)data;
293 CHECK_CLASS(data, WC_ColorWell);
296 switch (event->type) {
297 case Expose:
298 if (event->xexpose.count!=0)
299 break;
300 paintColorWell(cPtr);
301 break;
303 case DestroyNotify:
304 destroyColorWell(cPtr);
305 break;
311 static unsigned
312 draggingSourceOperation(WMView *self, Bool local)
314 return WDOperationCopy;
318 static WMData*
319 fetchDragData(WMView *self, char *type)
321 char *color = WMGetColorRGBDescription(((WMColorWell*)self->self)->color);
322 WMData *data;
324 data = WMCreateDataWithBytes(color, strlen(color)+1);
326 wfree(color);
328 return data;
332 static WMPixmap*
333 makeDragPixmap(WMColorWell *cPtr)
335 WMScreen *scr = cPtr->view->screen;
336 Pixmap pix;
338 pix = XCreatePixmap(scr->display, W_DRAWABLE(scr), 16, 16, scr->depth);
340 XFillRectangle(scr->display, pix, WMColorGC(cPtr->color), 0, 0, 15, 15);
342 XDrawRectangle(scr->display, pix, WMColorGC(scr->black), 0, 0, 15, 15);
344 return WMCreatePixmapFromXPixmaps(scr, pix, None, 16, 16, scr->depth);
348 static void
349 handleDragEvents(XEvent *event, void *data)
351 WMColorWell *cPtr = (ColorWell*)data;
353 switch (event->type) {
354 case ButtonPress:
355 if (event->xbutton.button == Button1) {
356 cPtr->ipoint.x = event->xbutton.x;
357 cPtr->ipoint.y = event->xbutton.y;
359 break;
361 case MotionNotify:
362 if (event->xmotion.state & Button1Mask) {
363 if (abs(cPtr->ipoint.x - event->xmotion.x) > 4
364 || abs(cPtr->ipoint.y - event->xmotion.y) > 4) {
365 WMSize offs;
366 WMPixmap *pixmap;
367 char *types[2] = {"application/X-color", NULL};
369 offs.width = 2;
370 offs.height = 2;
371 pixmap = makeDragPixmap(cPtr);
373 WMDragImageFromView(cPtr->colorView, pixmap, types,
374 wmkpoint(event->xmotion.x_root,
375 event->xmotion.y_root),
376 offs, event, True);
378 WMReleasePixmap(pixmap);
381 break;
386 static void
387 handleActionEvents(XEvent *event, void *data)
389 WMColorWell *cPtr = (ColorWell*)data;
390 WMScreen *scr = WMWidgetScreen(cPtr);
391 WMColorPanel *cpanel;
393 if (cPtr->flags.active)
394 W_SetViewBackgroundColor(cPtr->view, scr->gray);
395 else
396 W_SetViewBackgroundColor(cPtr->view, scr->white);
397 paintColorWell(cPtr);
399 cPtr->flags.active ^= 1;
401 if (cPtr->flags.active) {
402 WMPostNotificationName(_ColorWellActivatedNotification, cPtr, NULL);
404 cpanel = WMGetColorPanel(scr);
406 WMSetColorPanelAction(cpanel, updateColorCallback, cPtr);
408 if (cPtr->color)
409 WMSetColorPanelColor(cpanel, cPtr->color);
410 WMShowColorPanel(cpanel);
414 static void
415 destroyColorWell(ColorWell *cPtr)
417 WMRemoveNotificationObserver(cPtr);
419 if (cPtr->color)
420 WMReleaseColor(cPtr->color);
422 wfree(cPtr);
427 static unsigned
428 draggingEntered(WMView *self, WMDraggingInfo *info)
430 return WDOperationCopy;
434 static unsigned
435 draggingUpdated(WMView *self, WMDraggingInfo *info)
437 return WDOperationCopy;
441 static void
442 draggingExited(WMView *self, WMDraggingInfo *info)
448 static char*
449 prepareForDragOperation(WMView *self, WMDraggingInfo *info)
451 return "application/X-color";
455 static Bool
456 performDragOperation(WMView *self, WMDraggingInfo *info, WMData *data)
458 char *colorName = (char*)WMDataBytes(data);
459 WMColor *color;
461 color = WMCreateNamedColor(W_VIEW_SCREEN(self), colorName, True);
463 WMSetColorWellColor(self->self, color);
465 WMReleaseColor(color);
467 return True;
471 static void
472 concludeDragOperation(WMView *self, WMDraggingInfo *info)