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.
33 #include <X11/extensions/shape.h>
34 #include <X11/Xatom.h>
40 #define DOCKAPP_EXPOSE_INTERNALS
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
;
59 /* request the X selection; when the server responds, we will get it in
62 static void da_request_selection ()
66 prop
= XInternAtom (display
, "XSEL_DATA", False
);
69 XA_PRIMARY
, /* only use the PRIMARY selection */
70 XA_STRING
, /* we only accept strings (the 90% case) */
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
)
83 unsigned long actual_length
;
84 unsigned long remaining
;
88 if (event
->xselection
.selection
!= XA_PRIMARY
)
91 if (event
->xselection
.property
== None
) {
92 fprintf (stderr
, "! selection can't become string !\n");
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 */
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");
122 rv
= da_selection_cb (da_selection_cbdata
, (const char *)data
);
130 dockapp_rv_t
dockapp_request_selection_string (
131 dockapp_rv_t (*cb
) (void *, const char *),
134 da_selection_cb
= cb
;
135 da_selection_cbdata
= cbdata
;
136 da_request_selection ();
142 static void da_redraw_icon (void)
146 /* slurp up any queued Expose events */
147 while (XCheckTypedWindowEvent (
159 0, 0, 64, 64, /* source coords */
160 0, 0); /* dest coords */
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 (
176 short unused_revents
)
179 (void)unused_revents
;
181 XSync (display
, False
);
183 while (XPending (display
)) {
187 XNextEvent (display
, &event
);
189 switch (event
.type
) {
191 da_mouse_button_down (
194 event
.xbutton
.state
);
198 /* da_mouse_button_up() returns the callback rv of the
199 * callback which is invoked, if any
201 return da_mouse_button_up (
204 event
.xbutton
.state
);
212 XCloseDisplay (display
);
215 case SelectionNotify
:
216 return da_receive_selection (&event
);
224 int da_x_error_handler (Display
*display
, XErrorEvent
*xerr
)
228 XGetErrorText (display
, xerr
->error_code
, msgbuf
, sizeof msgbuf
);
230 fprintf (stderr
, "X11 error: %s\n", msgbuf
);
236 /* the following code is stolen largely from wmgeneral.c...
238 static Pixmap
da_create_shaping_bitmap (char **xpm
)
241 int width
, height
, numcol
, depth
;
242 unsigned long zero
=0;
243 unsigned char bwrite
;
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
++)
258 for (i
=numcol
+1; i
< numcol
+64+1; i
++) {
261 for (j
=0; j
<64*depth
; j
+=depth
) {
265 for (k
=0; k
!=depth
; k
++)
268 curpixel
|= xpm
[i
][j
+k
];
271 if ( curpixel
!= zero
) {
284 return XCreateBitmapFromData (
292 dockapp_rv_t
dockapp_init_gui (
299 XpmAttributes xpm_att
;
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 (
329 /* construct the windows */
330 main_win
= XCreateSimpleWindow (
333 0, 0, 64, 64, /* pos & size */
334 1, /* border width */
335 black
, /* foreground */
336 white
); /* background */
338 icon_win
= XCreateSimpleWindow (
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 */
361 da_create_shaping_bitmap (xpmdata
),
369 da_create_shaping_bitmap (xpmdata
),
373 /* set wm hints and title */
375 XClassHint classhint
;
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
397 gcv
.graphics_exposures
= 0;
398 gcv
.function
= GXcopy
;
400 copy_gc
= XCreateGC (
403 GCGraphicsExposures
| GCFunction
,
406 gcv
.function
= GXxor
;
411 GCGraphicsExposures
| GCFunction
,
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
),
435 void dockapp_copy_pixmap (
436 int source_x
, int source_y
,
437 int target_x
, int target_y
,
453 void dockapp_overlay_pixmap (
454 int source_x
, int source_y
,
455 int target_x
, int target_y
,