1 /***********************************************************************
2 * Code is based on wmppp, wmload, wmtime, wmcp, and asbutton
3 * Author: Edward H. Flora <ehflora@ksu.edu>
4 * Ver 0 Rel 6.1 Jan 23, 2005
7 * Christian 'Greek0' Aichinger <Greek0@gmx.net>
8 * Did some code cleanup and fixed several memory leaks.
9 * Ralf Horstmann <ralf.horstmann@gmx.de>
10 * Added ability to load pixmaps at startup,
11 * without having to re-compile
12 * Michael Cohrs <camico@users.sourceforge.net>
13 * Added Tool Tips, and updated graphics
14 * Bruno Essmann <essmann@users.sourceforge.net>)
16 * Casey Harkins <charkins@cs.wisc.edu>
17 * Bug fix reading config file path - 3/6/99
18 * Added button-presses, and other - denoted by *charkins*
19 * Ben Cohen <buddog@aztec.asu.edu>
20 * original author of wmcp (et al.)
21 * Thomas Nemeth <tnemeth@multimania.com>
23 * Michael Henderson <mghenderson@lanl.gov>
24 * Application ideas, suggestions
25 * Ryan ?? <pancake@mindspring.com>
26 * Modified wmbutton to asbutton.
27 * Note: asbutton is a seperate program, not associated
28 * with wmbutton (just as wmbutton is not associated
31 * Web Page Development
32 * The contributors listed above are not necessarily involved with the
33 * development of wmbutton. I'm listing them here partially as thanks for
34 * helping out, catching bugs in the code, etc.
35 ***********************************************************************/
45 #include "backdrop.xpm" /* background graphic */
46 #include "buttons.xpm" /* graphic of 9 buttons */
47 #include "mask.xbm" /* Border Graphic */
49 /*************** Function Prototypes ***********************************/
51 void getPixmaps(void);
52 int whichButton(int x
, int y
); // determine which button has been pressed
56 /***********************************************************************
57 * Globals.. OK.. there's too many globals.
58 * Feel free and fix it, if you'd like.
59 ***********************************************************************/
62 Window rootwin
, win
, iconwin
;
65 Pixel bg_pixel
, fg_pixel
;
67 struct Config_t Config
;
69 typedef struct _XpmIcon
{
72 XpmAttributes attributes
;
75 typedef struct _button_region
{
80 ButtonArea button_region
[9];
82 XpmIcon
template, visible
, buttons
;
85 int button_pressed
= -1; /* button to be drawn pressed *charkins*/
87 char *app_name
= "wmbutton";
89 /***********************************************************************
91 ***********************************************************************/
92 int main(int argc
, char **argv
)
96 XTextProperty app_name_atom
;
97 XSizeHints xsizehints
;
101 int N
= 1; /* Button number pressed to goto app # */
103 /* Added for Tool Tip Support */
104 long nTooltipShowDelay
= TOOLTIP_SHOW_DELAY
;
105 long nTooltipReshowDelay
= TOOLTIP_RESHOW_DELAY
;
106 long nTooltipTimer
= -1;
107 long nTooltipHideTimer
= -1;
109 int nTooltipButton
= 0, nTooltipX
= 0, nTooltipY
= 0;
111 /* Parse Command Line Arguments */
112 parseargs(argc
, argv
);
114 /* Catch fire if no configuration file exists */
115 if (!canOpenFile(Config
.configfile
)) {
116 if(!canOpenFile(CONFIGGLOBAL
)) {
117 err_mess(FAILCONF
, Config
.configfile
);
123 if ((display
= XOpenDisplay(Config
.Display_str
)) == NULL
)
124 err_mess(FAILDISP
, Config
.Display_str
);
126 screen
= DefaultScreen(display
);
127 rootwin
= RootWindow(display
, screen
);
128 depth
= DefaultDepth(display
, screen
);
130 bg_pixel
= WhitePixel(display
, screen
);
131 fg_pixel
= BlackPixel(display
, screen
);
133 xsizehints
.flags
= USSize
| USPosition
;
134 xsizehints
.width
= 64;
135 xsizehints
.height
= 64;
137 /* Parse Geometry string and fill in sizehints fields */
138 XWMGeometry(display
, screen
,
149 if ((win
= XCreateSimpleWindow(display
,
156 fg_pixel
, bg_pixel
)) == 0)
157 err_mess(FAILSWIN
, NULL
);
159 if ((iconwin
= XCreateSimpleWindow(display
,
166 fg_pixel
, bg_pixel
)) == 0)
168 err_mess(FAILICON
, NULL
);
170 /* Set up shaped windows */
171 /* Gives the appicon a border so you can grab and move it. */
172 if ((pixmask
= XCreateBitmapFromData(display
,
177 err_mess(FAILXPM
, NULL
);
179 XShapeCombineMask(display
, win
, ShapeBounding
, 0, 0, pixmask
, ShapeSet
);
180 XShapeCombineMask(display
, iconwin
, ShapeBounding
, 0, 0, pixmask
, ShapeSet
);
182 /* Convert in pixmaps from .xpm includes. */
185 /* Interclient Communication stuff */
186 /* Appicons don't work with out this stuff */
190 XSetWMNormalHints(display
, win
, &xsizehints
);
192 /* Tell window manager what the title bar name is. We never see */
193 /* this anyways in the WithdrawnState */
194 if (XStringListToTextProperty(&app_name
, 1, &app_name_atom
) == 0)
195 err_mess(FAILWNAM
, app_name
);
197 XSetWMName(display
, win
, &app_name_atom
);
199 /* Create Graphic Context */
200 if ((gc
= XCreateGC(display
, win
, (GCForeground
| GCBackground
),
201 &xgcValues
)) == NULL
)
202 err_mess(FAILGC
, NULL
);
204 /* XEvent Masks. We want both window to process X events */
205 XSelectInput(display
, win
,
208 ButtonReleaseMask
| /* added ButtonReleaseMask *charkins*/
210 StructureNotifyMask
|
213 XSelectInput(display
, iconwin
,
216 ButtonReleaseMask
| /* added ButtonReleaseMask *charkins*/
218 StructureNotifyMask
|
221 /* Store the 'state' of the application for restarting */
222 XSetCommand(display
, win
, argv
, argc
);
224 /* Window won't ever show up until it is mapped.. then drawn after a */
225 /* ConfigureNotify */
226 XMapWindow(display
, win
);
228 /* Initialize Tooltip Support */
234 while (XPending(display
) || nTooltipTimer
== -1) {
235 XNextEvent(display
, &report
);
237 switch (report
.type
) {
239 if (report
.xexpose
.count
!= 0)
243 fprintf(stdout
, "Event: Expose\n");
248 case ConfigureNotify
:
250 fprintf(stdout
, "Event: ConfigureNotify\n");
256 if (hasTooltipSupport()) {
258 nTooltipTimer
= currentTimeMillis();
259 nTooltipX
= report
.xbutton
.x
;
260 nTooltipY
= report
.xbutton
.y
;
261 nTooltipButton
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
263 int nButton
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
264 if (nButton
!= nTooltipButton
) {
267 nTooltipX
= report
.xbutton
.x
;
268 nTooltipY
= report
.xbutton
.y
;
269 nTooltipButton
= nButton
;
270 showTooltip(nTooltipButton
, nTooltipX
, nTooltipY
);
278 fprintf(stdout
, "Event: LeaveNotify\n");
282 nTooltipHideTimer
= currentTimeMillis();
287 case ButtonPress
: /* draw button pressed, don't launch *charkins*/
290 nTooltipHideTimer
= currentTimeMillis();
293 switch (report
.xbutton
.button
) {
295 N
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
296 if ((N
>= 0) && (N
<= NUMB_OF_APPS
)) {
297 button_pressed
= N
+ LMASK
;
302 fprintf(stdout
, "Button 1:x=%d y=%d N=%d\n",
303 report
.xbutton
.x
, report
.xbutton
.y
, N
+LMASK
);
307 if (!Config
.mmouse
) {
308 N
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
309 if ((N
>= 0) && (N
<= NUMB_OF_APPS
)) {
310 button_pressed
= N
+ MMASK
;
315 fprintf(stdout
, "Button 2:x=%d y=%d N=%d\n",
316 report
.xbutton
.x
, report
.xbutton
.y
, N
+MMASK
);
321 N
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
322 if ((N
>= 0) && (N
<= NUMB_OF_APPS
)) {
323 button_pressed
= N
+ RMASK
;
328 fprintf(stdout
, "Button 3:x=%d y=%d N=%d\n",
329 report
.xbutton
.x
, report
.xbutton
.y
, N
+RMASK
);
334 case ButtonRelease
: /* launch app here if still over button *charkins*/
335 switch (report
.xbutton
.button
) {
337 N
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
338 if ((N
>= 0) && (N
<= NUMB_OF_APPS
) && (N
== button_pressed
))
345 fprintf(stdout
, "Button 1:x=%d y=%d N=%d\n",
346 report
.xbutton
.x
, report
.xbutton
.y
, N
+LMASK
);
350 if (!Config
.mmouse
) {
351 N
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
352 if ((N
>= 0) && (N
<= NUMB_OF_APPS
) && (N
== button_pressed
))
359 fprintf(stdout
, "Button 2:x=%d y=%d N=%d\n",
360 report
.xbutton
.x
, report
.xbutton
.y
, N
+MMASK
);
365 N
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
366 if ((N
>= 0) && (N
<= NUMB_OF_APPS
) && (N
== button_pressed
))
373 fprintf(stdout
, "Button 3:x=%d y=%d N=%d\n",
374 report
.xbutton
.x
, report
.xbutton
.y
, N
+RMASK
);
381 fprintf(stdout
, "Bye\n");
384 XFreeGC(display
, gc
);
385 XDestroyWindow(display
, win
);
386 XDestroyWindow(display
, iconwin
);
387 XCloseDisplay(display
);
394 nNow
= currentTimeMillis();
395 if (nTooltipTimer
!= -1 &&
396 ((nNow
> nTooltipTimer
+ nTooltipShowDelay
) ||
397 (nNow
< nTooltipHideTimer
+ nTooltipReshowDelay
))) {
398 showTooltip(nTooltipButton
, nTooltipX
, nTooltipY
);
405 /***********************************************************************/
407 /***********************************************************************
410 * Map the button region coordinates.
412 * Draw the appropriate number of buttons on the 'visible' Pixmap
413 * using data from the 'buttons' pixmap.
415 * Then, copy the 'visible' pixmap to the two windows ( the withdrawn
416 * main window and the icon window which is the main window's icon image.)
417 ***********************************************************************/
419 int n
, i
, j
, dest_x
, dest_y
, space
, offset
, bsize
= 18;
422 fprintf(stdout
, "In Redraw()\n");
426 XCopyArea(display
, template.pixmap
, visible
.pixmap
, gc
, 0, 0,
427 template.attributes
.width
, template.attributes
.height
, 0, 0);
429 for (j
= 0; j
< 3; j
++) {
430 for (i
= 0; i
< 3; i
++) {
432 dest_x
= i
* (bsize
+ space
) + offset
+ space
;
433 dest_y
= j
* (bsize
+ space
) + offset
+ space
;
435 /* Define button mouse coords */
436 button_region
[n
].x
= dest_x
;
437 button_region
[n
].y
= dest_y
;
438 button_region
[n
].i
= dest_x
+ bsize
- 1;
439 button_region
[n
].j
= dest_y
+ bsize
- 1;
441 /* Copy button images for valid apps */
442 if ((n
+ 1) <= NUMB_OF_APPS
)
443 XCopyArea(display
, buttons
.pixmap
, visible
.pixmap
, gc
,
444 i
* bsize
, j
* bsize
, bsize
, bsize
, dest_x
, dest_y
);
448 if (button_pressed
> 0) { /* draw pressed button *charkins*/
449 if (button_pressed
> RMASK
)
450 button_pressed
-= RMASK
;
451 else if (button_pressed
> MMASK
)
452 button_pressed
-= MMASK
;
453 else if (button_pressed
> LMASK
)
454 button_pressed
-= LMASK
;
456 i
= (button_pressed
- 1) % 3; /* get col of button */
457 j
= (button_pressed
- 1) / 3; /* get row of button */
458 dest_x
= i
* (bsize
+ space
) + offset
+ space
;
459 dest_y
= j
* (bsize
+ space
) + offset
+ space
;
460 XSetForeground(display
, gc
, bg_pixel
);
461 XDrawLine(display
, visible
.pixmap
, gc
,
462 dest_x
+ 1, dest_y
+ bsize
- 1,
463 dest_x
+ bsize
- 1, dest_y
+ bsize
- 1);
464 XDrawLine(display
, visible
.pixmap
, gc
,
465 dest_x
+ bsize
- 1, dest_y
+ bsize
- 1,
466 dest_x
+ bsize
- 1, dest_y
+ 1);
467 XSetForeground(display
, gc
, fg_pixel
);
468 XDrawLine(display
, visible
.pixmap
, gc
,
469 dest_x
, dest_y
, dest_x
+ bsize
- 2, dest_y
);
470 XDrawLine(display
, visible
.pixmap
, gc
,
471 dest_x
, dest_y
, dest_x
, dest_y
+ bsize
- 2);
475 XCopyArea(display
, visible
.pixmap
, win
, gc
, 0, 0,
476 visible
.attributes
.width
, visible
.attributes
.height
, 0, 0);
477 flush_expose(iconwin
);
478 XCopyArea(display
, visible
.pixmap
, iconwin
, gc
, 0, 0,
479 visible
.attributes
.width
, visible
.attributes
.height
, 0, 0);
481 /***********************************************************************/
483 /***********************************************************************
486 * Return the button that at the x,y coordinates. The button need not
487 * be visible ( drawn ). Return -1 if no button match.
488 ***********************************************************************/
489 int whichButton(int x
, int y
)
493 for (index
= 0; index
< NUMB_OF_APPS
; index
++) {
494 if (x
>= button_region
[index
].x
&&
495 x
<= button_region
[index
].i
&&
496 y
>= button_region
[index
].y
&&
497 y
<= button_region
[index
].j
)
502 /***********************************************************************/
505 /***********************************************************************
508 * Load XPM data into X Pixmaps.
510 * Pixmap template contains the untouched window backdrop image.
511 * Pixmap visible is the template pixmap with buttons drawn on it.
512 * -- what is seen by the user.
513 * Pixmap buttons holds the images for individual buttons that are
514 * later copied onto Pixmap visible.
515 ***********************************************************************/
519 template.attributes
.valuemask
|= (XpmReturnPixels
| XpmReturnExtensions
);
520 visible
.attributes
.valuemask
|= (XpmReturnPixels
| XpmReturnExtensions
);
521 buttons
.attributes
.valuemask
|= (XpmReturnPixels
| XpmReturnExtensions
);
524 fprintf(stdout
, "In getPixmaps\n");
526 /* Template Pixmap. Never Drawn To. */
527 if (XpmCreatePixmapFromData(display
, rootwin
, backdrop_xpm
,
528 &template.pixmap
, &template.mask
,
529 &template.attributes
) != XpmSuccess
)
530 err_mess(FAILTMPL
, NULL
);
532 /* Visible Pixmap. Copied from template Pixmap and then drawn to. */
533 if (XpmCreatePixmapFromData(display
, rootwin
, backdrop_xpm
,
534 &visible
.pixmap
, &visible
.mask
,
535 &visible
.attributes
) != XpmSuccess
)
536 err_mess(FAILVIS
, NULL
);
539 if (access(Config
.buttonfile
, R_OK
) == 0) {
540 /* load buttons from file */
541 if (XpmReadFileToPixmap(display
, rootwin
, Config
.buttonfile
,
542 &buttons
.pixmap
, &buttons
.mask
,
543 &buttons
.attributes
) != XpmSuccess
)
544 err_mess(FAILBUT
, NULL
);
550 /* Use Builtin Button Pixmap. */
552 fprintf(stdout
, "Using builtin buttons pixmap\n");
554 if (XpmCreatePixmapFromData(display
, rootwin
, buttons_xpm
,
555 &buttons
.pixmap
, &buttons
.mask
,
556 &buttons
.attributes
) != XpmSuccess
)
557 err_mess(FAILBUT
, NULL
);
561 fprintf(stdout
, "Leaving getPixmaps\n");
564 /*********************************************************************/
570 xwmhints
= XAllocWMHints();
571 xwmhints
->flags
= WindowGroupHint
| IconWindowHint
| StateHint
;
572 xwmhints
->icon_window
= iconwin
;
573 xwmhints
->window_group
= win
;
574 xwmhints
->initial_state
= WithdrawnState
;
575 XSetWMHints(display
, win
, xwmhints
);
582 XClassHint xclasshint
;
584 xclasshint
.res_name
= "wmbutton";
585 xclasshint
.res_class
= "Wmbutton";
586 XSetClassHint(display
, win
, &xclasshint
);