1 /***********************************************************************
2 * Code is based on wmppp, wmload, wmtime, wmcp, and asbutton
3 * Author: Edward H. Flora <ehflora@ksu.edu>
6 * Christian 'Greek0' Aichinger <Greek0@gmx.net>
7 * Did some code cleanup and fixed several memory leaks.
8 * Ralf Horstmann <ralf.horstmann@gmx.de>
9 * Added ability to load pixmaps at startup,
10 * without having to re-compile
11 * Michael Cohrs <camico@users.sourceforge.net>
12 * Added Tool Tips, and updated graphics
13 * Bruno Essmann <essmann@users.sourceforge.net>)
15 * Casey Harkins <charkins@cs.wisc.edu>
16 * Bug fix reading config file path - 3/6/99
17 * Added button-presses, and other - denoted by *charkins*
18 * Ben Cohen <buddog@aztec.asu.edu>
19 * original author of wmcp (et al.)
20 * Thomas Nemeth <tnemeth@multimania.com>
22 * Michael Henderson <mghenderson@lanl.gov>
23 * Application ideas, suggestions
24 * Ryan ?? <pancake@mindspring.com>
25 * Modified wmbutton to asbutton.
26 * Note: asbutton is a seperate program, not associated
27 * with wmbutton (just as wmbutton is not associated
30 * Web Page Development
31 * The contributors listed above are not necessarily involved with the
32 * development of wmbutton. I'm listing them here partially as thanks for
33 * helping out, catching bugs in the code, etc.
34 ***********************************************************************/
44 #include "backdrop.xpm" /* background graphic */
45 #include "buttons.xpm" /* graphic of 9 buttons */
46 #include "mask.xbm" /* Border Graphic */
48 /*************** Function Prototypes ***********************************/
50 void getPixmaps(void);
51 int whichButton(int x
, int y
); // determine which button has been pressed
55 /***********************************************************************
56 * Globals.. OK.. there's too many globals.
57 * Feel free and fix it, if you'd like.
58 ***********************************************************************/
61 Window rootwin
, win
, iconwin
;
64 Pixel bg_pixel
, fg_pixel
;
66 struct Config_t Config
;
68 typedef struct _XpmIcon
{
71 XpmAttributes attributes
;
74 typedef struct _button_region
{
79 ButtonArea button_region
[9];
81 XpmIcon
template, visible
, buttons
;
84 int button_pressed
= -1; /* button to be drawn pressed *charkins*/
86 char *app_name
= "wmbutton";
88 /***********************************************************************
90 ***********************************************************************/
91 int main(int argc
, char **argv
)
95 XTextProperty app_name_atom
;
96 XSizeHints xsizehints
;
100 int N
= 1; /* Button number pressed to goto app # */
102 /* Added for Tool Tip Support */
103 long nTooltipShowDelay
= TOOLTIP_SHOW_DELAY
;
104 long nTooltipReshowDelay
= TOOLTIP_RESHOW_DELAY
;
105 long nTooltipTimer
= -1;
106 long nTooltipHideTimer
= -1;
108 int nTooltipButton
= 0, nTooltipX
= 0, nTooltipY
= 0;
110 /* Parse Command Line Arguments */
111 parseargs(argc
, argv
);
113 /* Catch fire if no configuration file exists */
114 if (!canOpenFile(Config
.configfile
)) {
115 if(!canOpenFile(CONFIGGLOBAL
)) {
116 err_mess(FAILCONF
, Config
.configfile
);
122 if ((display
= XOpenDisplay(Config
.Display_str
)) == NULL
)
123 err_mess(FAILDISP
, Config
.Display_str
);
125 screen
= DefaultScreen(display
);
126 rootwin
= RootWindow(display
, screen
);
127 depth
= DefaultDepth(display
, screen
);
129 bg_pixel
= WhitePixel(display
, screen
);
130 fg_pixel
= BlackPixel(display
, screen
);
132 xsizehints
.flags
= USSize
| USPosition
;
133 xsizehints
.width
= 64;
134 xsizehints
.height
= 64;
136 /* Parse Geometry string and fill in sizehints fields */
137 XWMGeometry(display
, screen
,
148 if ((win
= XCreateSimpleWindow(display
,
155 fg_pixel
, bg_pixel
)) == 0)
156 err_mess(FAILSWIN
, NULL
);
158 if ((iconwin
= XCreateSimpleWindow(display
,
165 fg_pixel
, bg_pixel
)) == 0)
167 err_mess(FAILICON
, NULL
);
169 /* Set up shaped windows */
170 /* Gives the appicon a border so you can grab and move it. */
171 if ((pixmask
= XCreateBitmapFromData(display
,
176 err_mess(FAILXPM
, NULL
);
178 XShapeCombineMask(display
, win
, ShapeBounding
, 0, 0, pixmask
, ShapeSet
);
179 XShapeCombineMask(display
, iconwin
, ShapeBounding
, 0, 0, pixmask
, ShapeSet
);
181 /* Convert in pixmaps from .xpm includes. */
184 /* Interclient Communication stuff */
185 /* Appicons don't work with out this stuff */
189 XSetWMNormalHints(display
, win
, &xsizehints
);
191 /* Tell window manager what the title bar name is. We never see */
192 /* this anyways in the WithdrawnState */
193 if (XStringListToTextProperty(&app_name
, 1, &app_name_atom
) == 0)
194 err_mess(FAILWNAM
, app_name
);
196 XSetWMName(display
, win
, &app_name_atom
);
198 /* Create Graphic Context */
199 if ((gc
= XCreateGC(display
, win
, (GCForeground
| GCBackground
),
200 &xgcValues
)) == NULL
)
201 err_mess(FAILGC
, NULL
);
203 /* XEvent Masks. We want both window to process X events */
204 XSelectInput(display
, win
,
207 ButtonReleaseMask
| /* added ButtonReleaseMask *charkins*/
209 StructureNotifyMask
|
212 XSelectInput(display
, iconwin
,
215 ButtonReleaseMask
| /* added ButtonReleaseMask *charkins*/
217 StructureNotifyMask
|
220 /* Store the 'state' of the application for restarting */
221 XSetCommand(display
, win
, argv
, argc
);
223 /* Window won't ever show up until it is mapped.. then drawn after a */
224 /* ConfigureNotify */
225 XMapWindow(display
, win
);
227 /* Initialize Tooltip Support */
233 while (XPending(display
) || nTooltipTimer
== -1) {
234 XNextEvent(display
, &report
);
236 switch (report
.type
) {
238 if (report
.xexpose
.count
!= 0)
242 fprintf(stdout
, "Event: Expose\n");
247 case ConfigureNotify
:
249 fprintf(stdout
, "Event: ConfigureNotify\n");
255 if (hasTooltipSupport()) {
257 nTooltipTimer
= currentTimeMillis();
258 nTooltipX
= report
.xbutton
.x
;
259 nTooltipY
= report
.xbutton
.y
;
260 nTooltipButton
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
262 int nButton
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
263 if (nButton
!= nTooltipButton
) {
266 nTooltipX
= report
.xbutton
.x
;
267 nTooltipY
= report
.xbutton
.y
;
268 nTooltipButton
= nButton
;
269 showTooltip(nTooltipButton
, nTooltipX
, nTooltipY
);
277 fprintf(stdout
, "Event: LeaveNotify\n");
281 nTooltipHideTimer
= currentTimeMillis();
286 case ButtonPress
: /* draw button pressed, don't launch *charkins*/
289 nTooltipHideTimer
= currentTimeMillis();
292 switch (report
.xbutton
.button
) {
294 N
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
295 if ((N
>= 0) && (N
<= NUMB_OF_APPS
)) {
296 button_pressed
= N
+ LMASK
;
301 fprintf(stdout
, "Button 1:x=%d y=%d N=%d\n",
302 report
.xbutton
.x
, report
.xbutton
.y
, N
+LMASK
);
306 if (!Config
.mmouse
) {
307 N
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
308 if ((N
>= 0) && (N
<= NUMB_OF_APPS
)) {
309 button_pressed
= N
+ MMASK
;
314 fprintf(stdout
, "Button 2:x=%d y=%d N=%d\n",
315 report
.xbutton
.x
, report
.xbutton
.y
, N
+MMASK
);
320 N
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
321 if ((N
>= 0) && (N
<= NUMB_OF_APPS
)) {
322 button_pressed
= N
+ RMASK
;
327 fprintf(stdout
, "Button 3:x=%d y=%d N=%d\n",
328 report
.xbutton
.x
, report
.xbutton
.y
, N
+RMASK
);
333 case ButtonRelease
: /* launch app here if still over button *charkins*/
334 switch (report
.xbutton
.button
) {
336 N
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
337 if ((N
>= 0) && (N
<= NUMB_OF_APPS
) && (N
== button_pressed
))
344 fprintf(stdout
, "Button 1:x=%d y=%d N=%d\n",
345 report
.xbutton
.x
, report
.xbutton
.y
, N
+LMASK
);
349 if (!Config
.mmouse
) {
350 N
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
351 if ((N
>= 0) && (N
<= NUMB_OF_APPS
) && (N
== button_pressed
))
358 fprintf(stdout
, "Button 2:x=%d y=%d N=%d\n",
359 report
.xbutton
.x
, report
.xbutton
.y
, N
+MMASK
);
364 N
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
365 if ((N
>= 0) && (N
<= NUMB_OF_APPS
) && (N
== button_pressed
))
372 fprintf(stdout
, "Button 3:x=%d y=%d N=%d\n",
373 report
.xbutton
.x
, report
.xbutton
.y
, N
+RMASK
);
380 fprintf(stdout
, "Bye\n");
383 XFreeGC(display
, gc
);
384 XDestroyWindow(display
, win
);
385 XDestroyWindow(display
, iconwin
);
386 XCloseDisplay(display
);
393 nNow
= currentTimeMillis();
394 if (nTooltipTimer
!= -1 &&
395 ((nNow
> nTooltipTimer
+ nTooltipShowDelay
) ||
396 (nNow
< nTooltipHideTimer
+ nTooltipReshowDelay
))) {
397 showTooltip(nTooltipButton
, nTooltipX
, nTooltipY
);
404 /***********************************************************************/
406 /***********************************************************************
409 * Map the button region coordinates.
411 * Draw the appropriate number of buttons on the 'visible' Pixmap
412 * using data from the 'buttons' pixmap.
414 * Then, copy the 'visible' pixmap to the two windows ( the withdrawn
415 * main window and the icon window which is the main window's icon image.)
416 ***********************************************************************/
418 int n
, i
, j
, dest_x
, dest_y
, space
, offset
, bsize
= 18;
421 fprintf(stdout
, "In Redraw()\n");
425 XCopyArea(display
, template.pixmap
, visible
.pixmap
, gc
, 0, 0,
426 template.attributes
.width
, template.attributes
.height
, 0, 0);
428 for (j
= 0; j
< 3; j
++) {
429 for (i
= 0; i
< 3; i
++) {
431 dest_x
= i
* (bsize
+ space
) + offset
+ space
;
432 dest_y
= j
* (bsize
+ space
) + offset
+ space
;
434 /* Define button mouse coords */
435 button_region
[n
].x
= dest_x
;
436 button_region
[n
].y
= dest_y
;
437 button_region
[n
].i
= dest_x
+ bsize
- 1;
438 button_region
[n
].j
= dest_y
+ bsize
- 1;
440 /* Copy button images for valid apps */
441 if ((n
+ 1) <= NUMB_OF_APPS
)
442 XCopyArea(display
, buttons
.pixmap
, visible
.pixmap
, gc
,
443 i
* bsize
, j
* bsize
, bsize
, bsize
, dest_x
, dest_y
);
447 if (button_pressed
> 0) { /* draw pressed button *charkins*/
448 if (button_pressed
> RMASK
)
449 button_pressed
-= RMASK
;
450 else if (button_pressed
> MMASK
)
451 button_pressed
-= MMASK
;
452 else if (button_pressed
> LMASK
)
453 button_pressed
-= LMASK
;
455 i
= (button_pressed
- 1) % 3; /* get col of button */
456 j
= (button_pressed
- 1) / 3; /* get row of button */
457 dest_x
= i
* (bsize
+ space
) + offset
+ space
;
458 dest_y
= j
* (bsize
+ space
) + offset
+ space
;
459 XSetForeground(display
, gc
, bg_pixel
);
460 XDrawLine(display
, visible
.pixmap
, gc
,
461 dest_x
+ 1, dest_y
+ bsize
- 1,
462 dest_x
+ bsize
- 1, dest_y
+ bsize
- 1);
463 XDrawLine(display
, visible
.pixmap
, gc
,
464 dest_x
+ bsize
- 1, dest_y
+ bsize
- 1,
465 dest_x
+ bsize
- 1, dest_y
+ 1);
466 XSetForeground(display
, gc
, fg_pixel
);
467 XDrawLine(display
, visible
.pixmap
, gc
,
468 dest_x
, dest_y
, dest_x
+ bsize
- 2, dest_y
);
469 XDrawLine(display
, visible
.pixmap
, gc
,
470 dest_x
, dest_y
, dest_x
, dest_y
+ bsize
- 2);
474 XCopyArea(display
, visible
.pixmap
, win
, gc
, 0, 0,
475 visible
.attributes
.width
, visible
.attributes
.height
, 0, 0);
476 flush_expose(iconwin
);
477 XCopyArea(display
, visible
.pixmap
, iconwin
, gc
, 0, 0,
478 visible
.attributes
.width
, visible
.attributes
.height
, 0, 0);
480 /***********************************************************************/
482 /***********************************************************************
485 * Return the button that at the x,y coordinates. The button need not
486 * be visible ( drawn ). Return -1 if no button match.
487 ***********************************************************************/
488 int whichButton(int x
, int y
)
492 for (index
= 0; index
< NUMB_OF_APPS
; index
++) {
493 if (x
>= button_region
[index
].x
&&
494 x
<= button_region
[index
].i
&&
495 y
>= button_region
[index
].y
&&
496 y
<= button_region
[index
].j
)
501 /***********************************************************************/
504 /***********************************************************************
507 * Load XPM data into X Pixmaps.
509 * Pixmap template contains the untouched window backdrop image.
510 * Pixmap visible is the template pixmap with buttons drawn on it.
511 * -- what is seen by the user.
512 * Pixmap buttons holds the images for individual buttons that are
513 * later copied onto Pixmap visible.
514 ***********************************************************************/
518 template.attributes
.valuemask
|= (XpmReturnPixels
| XpmReturnExtensions
);
519 visible
.attributes
.valuemask
|= (XpmReturnPixels
| XpmReturnExtensions
);
520 buttons
.attributes
.valuemask
|= (XpmReturnPixels
| XpmReturnExtensions
);
523 fprintf(stdout
, "In getPixmaps\n");
525 /* Template Pixmap. Never Drawn To. */
526 if (XpmCreatePixmapFromData(display
, rootwin
, backdrop_xpm
,
527 &template.pixmap
, &template.mask
,
528 &template.attributes
) != XpmSuccess
)
529 err_mess(FAILTMPL
, NULL
);
531 /* Visible Pixmap. Copied from template Pixmap and then drawn to. */
532 if (XpmCreatePixmapFromData(display
, rootwin
, backdrop_xpm
,
533 &visible
.pixmap
, &visible
.mask
,
534 &visible
.attributes
) != XpmSuccess
)
535 err_mess(FAILVIS
, NULL
);
538 if (access(Config
.buttonfile
, R_OK
) == 0) {
539 /* load buttons from file */
540 if (XpmReadFileToPixmap(display
, rootwin
, Config
.buttonfile
,
541 &buttons
.pixmap
, &buttons
.mask
,
542 &buttons
.attributes
) != XpmSuccess
)
543 err_mess(FAILBUT
, NULL
);
549 /* Use Builtin Button Pixmap. */
551 fprintf(stdout
, "Using builtin buttons pixmap\n");
553 if (XpmCreatePixmapFromData(display
, rootwin
, buttons_xpm
,
554 &buttons
.pixmap
, &buttons
.mask
,
555 &buttons
.attributes
) != XpmSuccess
)
556 err_mess(FAILBUT
, NULL
);
560 fprintf(stdout
, "Leaving getPixmaps\n");
563 /*********************************************************************/
569 xwmhints
= XAllocWMHints();
570 xwmhints
->flags
= WindowGroupHint
| IconWindowHint
| StateHint
;
571 xwmhints
->icon_window
= iconwin
;
572 xwmhints
->window_group
= win
;
573 xwmhints
->initial_state
= WithdrawnState
;
574 XSetWMHints(display
, win
, xwmhints
);
581 XClassHint xclasshint
;
583 xclasshint
.res_name
= "wmbutton";
584 xclasshint
.res_class
= "Wmbutton";
585 XSetClassHint(display
, win
, &xclasshint
);