wmclockmon: update change-log
[dockapps.git] / wmget / dockapp / da_x.c
bloba4a693684970bbf9e20febae5f40ccf5e211b440
1 /*
2 wmget - A background download manager as a Window Maker dock app
3 Copyright (c) 2001-2003 Aaron Trickey <aaron@amtrickey.net>
5 Permission is hereby granted, free of charge, to any person
6 obtaining a copy of this software and associated documentation files
7 (the "Software"), to deal in the Software without restriction,
8 including without limitation the rights to use, copy, modify, merge,
9 publish, distribute, sublicense, and/or sell copies of the Software,
10 and to permit persons to whom the Software is furnished to do so,
11 subject to the following conditions:
13 The above copyright notice and this permission notice shall be
14 included in all copies or substantial portions of the Software.
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
20 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 ********************************************************************
25 dockapp/da_x.c - General X11 code
27 This file encapsulates all the X11 interface code, such as drawing,
28 initialization, and selection handling.
31 #include <X11/Xlib.h>
32 #include <X11/xpm.h>
33 #include <X11/extensions/shape.h>
34 #include <X11/Xatom.h>
35 #include <stdio.h>
36 #include <unistd.h>
38 #include "dockapp.h"
40 #define DOCKAPP_EXPOSE_INTERNALS
41 #include "da_mouse.h"
43 #define SELECTION_MAX 1024
45 static Display *display;
47 /* We need to update both the ``icon'' and ``main'' windows
48 * simultaneously... icon for WindowMaker and main for AfterStep...
50 static Window icon_win;
51 static Window main_win;
53 static Pixmap icon_pixmap;
55 static GC copy_gc;
56 static GC xor_gc;
59 /* request the X selection; when the server responds, we will get it in
60 * da_xfd_callback.
62 static void da_request_selection ()
64 Atom prop;
66 prop = XInternAtom (display, "XSEL_DATA", False);
67 XConvertSelection (
68 display,
69 XA_PRIMARY, /* only use the PRIMARY selection */
70 XA_STRING, /* we only accept strings (the 90% case) */
71 prop,
72 icon_win,
73 CurrentTime);
76 static dockapp_rv_t (*da_selection_cb) (void *, const char *);
77 static void *da_selection_cbdata;
79 static dockapp_rv_t da_receive_selection (XEvent *event)
81 Atom actual_type;
82 int actual_format;
83 unsigned long actual_length;
84 unsigned long remaining;
85 unsigned char *data;
86 dockapp_rv_t rv;
88 if (event->xselection.selection != XA_PRIMARY)
89 return dockapp_ok;
91 if (event->xselection.property == None) {
92 fprintf (stderr, "! selection can't become string !\n");
93 return dockapp_ok;
96 XGetWindowProperty (
97 event->xselection.display,
98 event->xselection.requestor,
99 event->xselection.property,
100 0, /* from byte zero... */
101 SELECTION_MAX, /* to this many bytes */
102 False, /* do not delete after retrieval */
103 AnyPropertyType,
104 &actual_type, /* actual type returned */
105 &actual_format, /* actual format returned */
106 &actual_length, /* in 8, 16, or 32 bit units */
107 &remaining, /* unread content (always in 8 bit units!) */
108 &data); /* property content */
110 /* We do not support non-string data or incremental transfer. */
111 if (actual_type != XA_STRING || actual_format != 8) {
112 fprintf (stderr, "! selection unavailable or not of known type !\n");
114 if (actual_length) {
115 XFree (data);
118 return dockapp_ok;
122 rv = da_selection_cb (da_selection_cbdata, (const char *)data);
124 XFree (data);
126 return rv;
130 dockapp_rv_t dockapp_request_selection_string (
131 dockapp_rv_t (*cb) (void *, const char *),
132 void *cbdata)
134 da_selection_cb = cb;
135 da_selection_cbdata = cbdata;
136 da_request_selection ();
138 return dockapp_ok;
142 static void da_redraw_icon (void)
144 XEvent event;
146 /* slurp up any queued Expose events */
147 while (XCheckTypedWindowEvent (
148 display,
149 event.xany.window,
150 Expose,
151 &event))
154 XCopyArea (
155 display,
156 icon_pixmap,
157 icon_win,
158 copy_gc,
159 0, 0, 64, 64, /* source coords */
160 0, 0); /* dest coords */
162 XCopyArea (
163 display,
164 icon_pixmap,
165 main_win,
166 copy_gc,
167 0, 0, 64, 64, /* source coords */
168 0, 0); /* dest coords */
172 /* this is the callback bound to the X server socket descriptor
174 static dockapp_rv_t da_xfd_callback (
175 void *unused_cbdata,
176 short unused_revents)
178 (void)unused_cbdata;
179 (void)unused_revents;
181 XSync (display, False);
183 while (XPending (display)) {
185 XEvent event;
187 XNextEvent (display, &event);
189 switch (event.type) {
190 case ButtonPress:
191 da_mouse_button_down (
192 event.xbutton.x,
193 event.xbutton.y,
194 event.xbutton.state);
195 break;
197 case ButtonRelease:
198 /* da_mouse_button_up() returns the callback rv of the
199 * callback which is invoked, if any
201 return da_mouse_button_up (
202 event.xbutton.x,
203 event.xbutton.y,
204 event.xbutton.state);
205 break;
207 case Expose:
208 da_redraw_icon ();
209 break;
211 case DestroyNotify:
212 XCloseDisplay (display);
213 return dockapp_exit;
215 case SelectionNotify:
216 return da_receive_selection (&event);
220 return dockapp_ok;
224 int da_x_error_handler (Display *display, XErrorEvent *xerr)
226 char msgbuf[1024];
228 XGetErrorText (display, xerr->error_code, msgbuf, sizeof msgbuf);
230 fprintf (stderr, "X11 error: %s\n", msgbuf);
232 return 0;
236 /* the following code is stolen largely from wmgeneral.c...
238 static Pixmap da_create_shaping_bitmap (char **xpm)
240 int i,j,k;
241 int width, height, numcol, depth;
242 unsigned long zero=0;
243 unsigned char bwrite;
244 int bcount;
245 unsigned long curpixel;
247 char xbm_data[64*64];
248 char *xbm = xbm_data;
250 sscanf(*xpm, "%d %d %d %d", &width, &height, &numcol, &depth);
252 for (k=0; k!=depth; k++)
254 zero <<=8;
255 zero |= xpm[1][k];
258 for (i=numcol+1; i < numcol+64+1; i++) {
259 bcount = 0;
260 bwrite = 0;
261 for (j=0; j<64*depth; j+=depth) {
262 bwrite >>= 1;
264 curpixel=0;
265 for (k=0; k!=depth; k++)
267 curpixel <<=8;
268 curpixel |= xpm[i][j+k];
271 if ( curpixel != zero ) {
272 bwrite += 128;
274 bcount++;
275 if (bcount == 8) {
276 *xbm = bwrite;
277 xbm++;
278 bcount = 0;
279 bwrite = 0;
284 return XCreateBitmapFromData (
285 display,
286 icon_win,
287 xbm_data,
288 64, 64);
292 dockapp_rv_t dockapp_init_gui (
293 char *appname,
294 char *argv[],
295 char **xpmdata)
297 int screen;
298 Window root;
299 XpmAttributes xpm_att;
300 Pixmap xpm_mask;
301 unsigned long black, white;
303 (void)argv; /* not currently parsed */
305 /* initialize x error handler */
306 XSetErrorHandler (da_x_error_handler);
308 /* get some stuff out */
309 display = XOpenDisplay (0);
311 screen = DefaultScreen (display);
313 root = RootWindow (display, screen);
315 black = BlackPixel (display, screen);
316 white = WhitePixel (display, screen);
318 /* construct the pixmap */
319 xpm_att.valuemask = XpmReturnPixels | XpmReturnExtensions;
321 XpmCreatePixmapFromData (
322 display,
323 root,
324 xpmdata,
325 &icon_pixmap,
326 &xpm_mask,
327 &xpm_att);
329 /* construct the windows */
330 main_win = XCreateSimpleWindow (
331 display,
332 root, /* parent */
333 0, 0, 64, 64, /* pos & size */
334 1, /* border width */
335 black, /* foreground */
336 white); /* background */
338 icon_win = XCreateSimpleWindow (
339 display,
340 main_win, /* parent */
341 0, 0, 64, 64, /* pos & size */
342 1, /* border width */
343 black, /* foreground */
344 white); /* background */
346 /* request all interesting X events */
347 XSelectInput (display, main_win,
348 ButtonPressMask | ExposureMask | ButtonReleaseMask |
349 PointerMotionMask | StructureNotifyMask);
351 XSelectInput (display, icon_win,
352 ButtonPressMask | ExposureMask | ButtonReleaseMask |
353 PointerMotionMask | StructureNotifyMask);
355 /* apply the shaping bitmap */
356 XShapeCombineMask (
357 display,
358 icon_win,
359 ShapeBounding,
360 0, 0,
361 da_create_shaping_bitmap (xpmdata),
362 ShapeSet);
364 XShapeCombineMask (
365 display,
366 main_win,
367 ShapeBounding,
368 0, 0,
369 da_create_shaping_bitmap (xpmdata),
370 ShapeSet);
373 /* set wm hints and title */
375 XClassHint classhint;
376 XWMHints wmhints;
378 classhint.res_name = appname;
379 classhint.res_class = appname;
380 XSetClassHint (display, main_win, &classhint);
382 wmhints.initial_state = WithdrawnState;
383 wmhints.icon_window = icon_win;
384 wmhints.window_group = main_win;
385 wmhints.flags = StateHint | IconWindowHint | WindowGroupHint;
386 XSetWMHints (display, main_win, &wmhints);
388 XStoreName (display, main_win, appname);
391 /* now we need two gc's to do drawing & copying... one which paints
392 * by overwriting pixels, and one which paints by xor'ing pixels
395 XGCValues gcv;
397 gcv.graphics_exposures = 0;
398 gcv.function = GXcopy;
400 copy_gc = XCreateGC (
401 display,
402 root,
403 GCGraphicsExposures | GCFunction,
404 &gcv);
406 gcv.function = GXxor;
408 xor_gc = XCreateGC (
409 display,
410 root,
411 GCGraphicsExposures | GCFunction,
412 &gcv);
415 /* finally, show the window */
416 XMapWindow (display, main_win);
418 /* invoke da_xfd_callback once manually to process all events which
419 * were generated by the above work... after this, it will be called
420 * by the framework whenever there is activity on the server socket
422 da_xfd_callback (0, 0);
424 /* now that we're up, add the X file descriptor to the main poll
425 * loop and bind it to our event handler
427 return dockapp_add_pollfd (
428 XConnectionNumber (display),
429 POLLIN | POLLPRI,
430 da_xfd_callback,
435 void dockapp_copy_pixmap (
436 int source_x, int source_y,
437 int target_x, int target_y,
438 int w, int h)
440 XCopyArea (
441 display,
442 icon_pixmap,
443 icon_pixmap,
444 copy_gc,
445 source_x, source_y,
446 w, h,
447 target_x, target_y);
449 da_redraw_icon ();
453 void dockapp_overlay_pixmap (
454 int source_x, int source_y,
455 int target_x, int target_y,
456 int w, int h)
458 XCopyArea (
459 display,
460 icon_pixmap,
461 icon_pixmap,
462 xor_gc,
463 source_x, source_y,
464 w, h,
465 target_x, target_y);
467 da_redraw_icon ();