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
);
115 if ((display
= XOpenDisplay(Config
.Display_str
)) == NULL
)
116 err_mess(FAILDISP
, Config
.Display_str
);
118 screen
= DefaultScreen(display
);
119 rootwin
= RootWindow(display
, screen
);
120 depth
= DefaultDepth(display
, screen
);
122 bg_pixel
= WhitePixel(display
, screen
);
123 fg_pixel
= BlackPixel(display
, screen
);
125 xsizehints
.flags
= USSize
| USPosition
;
126 xsizehints
.width
= 64;
127 xsizehints
.height
= 64;
129 /* Parse Geometry string and fill in sizehints fields */
130 XWMGeometry(display
, screen
,
141 if ((win
= XCreateSimpleWindow(display
,
148 fg_pixel
, bg_pixel
)) == 0)
149 err_mess(FAILSWIN
, NULL
);
151 if ((iconwin
= XCreateSimpleWindow(display
,
158 fg_pixel
, bg_pixel
)) == 0)
160 err_mess(FAILICON
, NULL
);
162 /* Set up shaped windows */
163 /* Gives the appicon a border so you can grab and move it. */
164 if ((pixmask
= XCreateBitmapFromData(display
,
169 err_mess(FAILXPM
, NULL
);
171 XShapeCombineMask(display
, win
, ShapeBounding
, 0, 0, pixmask
, ShapeSet
);
172 XShapeCombineMask(display
, iconwin
, ShapeBounding
, 0, 0, pixmask
, ShapeSet
);
174 /* Convert in pixmaps from .xpm includes. */
177 /* Interclient Communication stuff */
178 /* Appicons don't work with out this stuff */
182 XSetWMNormalHints(display
, win
, &xsizehints
);
184 /* Tell window manager what the title bar name is. We never see */
185 /* this anyways in the WithdrawnState */
186 if (XStringListToTextProperty(&app_name
, 1, &app_name_atom
) == 0)
187 err_mess(FAILWNAM
, app_name
);
189 XSetWMName(display
, win
, &app_name_atom
);
191 /* Create Graphic Context */
192 if ((gc
= XCreateGC(display
, win
, (GCForeground
| GCBackground
),
193 &xgcValues
)) == NULL
)
194 err_mess(FAILGC
, NULL
);
196 /* XEvent Masks. We want both window to process X events */
197 XSelectInput(display
, win
,
200 ButtonReleaseMask
| /* added ButtonReleaseMask *charkins*/
202 StructureNotifyMask
|
205 XSelectInput(display
, iconwin
,
208 ButtonReleaseMask
| /* added ButtonReleaseMask *charkins*/
210 StructureNotifyMask
|
213 /* Store the 'state' of the application for restarting */
214 XSetCommand(display
, win
, argv
, argc
);
216 /* Window won't ever show up until it is mapped.. then drawn after a */
217 /* ConfigureNotify */
218 XMapWindow(display
, win
);
220 /* Initialize Tooltip Support */
226 while (XPending(display
) || nTooltipTimer
== -1) {
227 XNextEvent(display
, &report
);
229 switch (report
.type
) {
231 if (report
.xexpose
.count
!= 0)
235 fprintf(stdout
, "Event: Expose\n");
240 case ConfigureNotify
:
242 fprintf(stdout
, "Event: ConfigureNotify\n");
248 if (hasTooltipSupport()) {
250 nTooltipTimer
= currentTimeMillis();
251 nTooltipX
= report
.xbutton
.x
;
252 nTooltipY
= report
.xbutton
.y
;
253 nTooltipButton
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
255 int nButton
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
256 if (nButton
!= nTooltipButton
) {
259 nTooltipX
= report
.xbutton
.x
;
260 nTooltipY
= report
.xbutton
.y
;
261 nTooltipButton
= nButton
;
262 showTooltip(nTooltipButton
, nTooltipX
, nTooltipY
);
270 fprintf(stdout
, "Event: LeaveNotify\n");
274 nTooltipHideTimer
= currentTimeMillis();
279 case ButtonPress
: /* draw button pressed, don't launch *charkins*/
282 nTooltipHideTimer
= currentTimeMillis();
285 switch (report
.xbutton
.button
) {
287 N
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
288 if ((N
>= 0) && (N
<= NUMB_OF_APPS
)) {
289 button_pressed
= N
+ LMASK
;
294 fprintf(stdout
, "Button 1:x=%d y=%d N=%d\n",
295 report
.xbutton
.x
, report
.xbutton
.y
, N
+LMASK
);
299 if (!Config
.mmouse
) {
300 N
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
301 if ((N
>= 0) && (N
<= NUMB_OF_APPS
)) {
302 button_pressed
= N
+ MMASK
;
307 fprintf(stdout
, "Button 2:x=%d y=%d N=%d\n",
308 report
.xbutton
.x
, report
.xbutton
.y
, N
+MMASK
);
313 N
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
314 if ((N
>= 0) && (N
<= NUMB_OF_APPS
)) {
315 button_pressed
= N
+ RMASK
;
320 fprintf(stdout
, "Button 3:x=%d y=%d N=%d\n",
321 report
.xbutton
.x
, report
.xbutton
.y
, N
+RMASK
);
326 case ButtonRelease
: /* launch app here if still over button *charkins*/
327 switch (report
.xbutton
.button
) {
329 N
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
330 if ((N
>= 0) && (N
<= NUMB_OF_APPS
) && (N
== button_pressed
))
337 fprintf(stdout
, "Button 1:x=%d y=%d N=%d\n",
338 report
.xbutton
.x
, report
.xbutton
.y
, N
+LMASK
);
342 if (!Config
.mmouse
) {
343 N
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
344 if ((N
>= 0) && (N
<= NUMB_OF_APPS
) && (N
== button_pressed
))
351 fprintf(stdout
, "Button 2:x=%d y=%d N=%d\n",
352 report
.xbutton
.x
, report
.xbutton
.y
, N
+MMASK
);
357 N
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
358 if ((N
>= 0) && (N
<= NUMB_OF_APPS
) && (N
== button_pressed
))
365 fprintf(stdout
, "Button 3:x=%d y=%d N=%d\n",
366 report
.xbutton
.x
, report
.xbutton
.y
, N
+RMASK
);
373 fprintf(stdout
, "Bye\n");
376 XFreeGC(display
, gc
);
377 XDestroyWindow(display
, win
);
378 XDestroyWindow(display
, iconwin
);
379 XCloseDisplay(display
);
386 nNow
= currentTimeMillis();
387 if (nTooltipTimer
!= -1 &&
388 ((nNow
> nTooltipTimer
+ nTooltipShowDelay
) ||
389 (nNow
< nTooltipHideTimer
+ nTooltipReshowDelay
))) {
390 showTooltip(nTooltipButton
, nTooltipX
, nTooltipY
);
397 /***********************************************************************/
399 /***********************************************************************
402 * Map the button region coordinates.
404 * Draw the appropriate number of buttons on the 'visible' Pixmap
405 * using data from the 'buttons' pixmap.
407 * Then, copy the 'visible' pixmap to the two windows ( the withdrawn
408 * main window and the icon window which is the main window's icon image.)
409 ***********************************************************************/
411 int n
, i
, j
, dest_x
, dest_y
, space
, offset
, bsize
= 18;
414 fprintf(stdout
, "In Redraw()\n");
418 XCopyArea(display
, template.pixmap
, visible
.pixmap
, gc
, 0, 0,
419 template.attributes
.width
, template.attributes
.height
, 0, 0);
421 for (j
= 0; j
< 3; j
++) {
422 for (i
= 0; i
< 3; i
++) {
424 dest_x
= i
* (bsize
+ space
) + offset
+ space
;
425 dest_y
= j
* (bsize
+ space
) + offset
+ space
;
427 /* Define button mouse coords */
428 button_region
[n
].x
= dest_x
;
429 button_region
[n
].y
= dest_y
;
430 button_region
[n
].i
= dest_x
+ bsize
- 1;
431 button_region
[n
].j
= dest_y
+ bsize
- 1;
433 /* Copy button images for valid apps */
434 if ((n
+ 1) <= NUMB_OF_APPS
)
435 XCopyArea(display
, buttons
.pixmap
, visible
.pixmap
, gc
,
436 i
* bsize
, j
* bsize
, bsize
, bsize
, dest_x
, dest_y
);
440 if (button_pressed
> 0) { /* draw pressed button *charkins*/
441 if (button_pressed
> RMASK
)
442 button_pressed
-= RMASK
;
443 else if (button_pressed
> MMASK
)
444 button_pressed
-= MMASK
;
445 else if (button_pressed
> LMASK
)
446 button_pressed
-= LMASK
;
448 i
= (button_pressed
- 1) % 3; /* get col of button */
449 j
= (button_pressed
- 1) / 3; /* get row of button */
450 dest_x
= i
* (bsize
+ space
) + offset
+ space
;
451 dest_y
= j
* (bsize
+ space
) + offset
+ space
;
452 XSetForeground(display
, gc
, bg_pixel
);
453 XDrawLine(display
, visible
.pixmap
, gc
,
454 dest_x
+ 1, dest_y
+ bsize
- 1,
455 dest_x
+ bsize
- 1, dest_y
+ bsize
- 1);
456 XDrawLine(display
, visible
.pixmap
, gc
,
457 dest_x
+ bsize
- 1, dest_y
+ bsize
- 1,
458 dest_x
+ bsize
- 1, dest_y
+ 1);
459 XSetForeground(display
, gc
, fg_pixel
);
460 XDrawLine(display
, visible
.pixmap
, gc
,
461 dest_x
, dest_y
, dest_x
+ bsize
- 2, dest_y
);
462 XDrawLine(display
, visible
.pixmap
, gc
,
463 dest_x
, dest_y
, dest_x
, dest_y
+ bsize
- 2);
467 XCopyArea(display
, visible
.pixmap
, win
, gc
, 0, 0,
468 visible
.attributes
.width
, visible
.attributes
.height
, 0, 0);
469 flush_expose(iconwin
);
470 XCopyArea(display
, visible
.pixmap
, iconwin
, gc
, 0, 0,
471 visible
.attributes
.width
, visible
.attributes
.height
, 0, 0);
473 /***********************************************************************/
475 /***********************************************************************
478 * Return the button that at the x,y coordinates. The button need not
479 * be visible ( drawn ). Return -1 if no button match.
480 ***********************************************************************/
481 int whichButton(int x
, int y
)
485 for (index
= 0; index
< NUMB_OF_APPS
; index
++) {
486 if (x
>= button_region
[index
].x
&&
487 x
<= button_region
[index
].i
&&
488 y
>= button_region
[index
].y
&&
489 y
<= button_region
[index
].j
)
494 /***********************************************************************/
497 /***********************************************************************
500 * Load XPM data into X Pixmaps.
502 * Pixmap template contains the untouched window backdrop image.
503 * Pixmap visible is the template pixmap with buttons drawn on it.
504 * -- what is seen by the user.
505 * Pixmap buttons holds the images for individual buttons that are
506 * later copied onto Pixmap visible.
507 ***********************************************************************/
511 template.attributes
.valuemask
|= (XpmReturnPixels
| XpmReturnExtensions
);
512 visible
.attributes
.valuemask
|= (XpmReturnPixels
| XpmReturnExtensions
);
513 buttons
.attributes
.valuemask
|= (XpmReturnPixels
| XpmReturnExtensions
);
516 fprintf(stdout
, "In getPixmaps\n");
518 /* Template Pixmap. Never Drawn To. */
519 if (XpmCreatePixmapFromData(display
, rootwin
, backdrop_xpm
,
520 &template.pixmap
, &template.mask
,
521 &template.attributes
) != XpmSuccess
)
522 err_mess(FAILTMPL
, NULL
);
524 /* Visible Pixmap. Copied from template Pixmap and then drawn to. */
525 if (XpmCreatePixmapFromData(display
, rootwin
, backdrop_xpm
,
526 &visible
.pixmap
, &visible
.mask
,
527 &visible
.attributes
) != XpmSuccess
)
528 err_mess(FAILVIS
, NULL
);
531 if (access(Config
.buttonfile
, R_OK
) == 0) {
532 /* load buttons from file */
533 if (XpmReadFileToPixmap(display
, rootwin
, Config
.buttonfile
,
534 &buttons
.pixmap
, &buttons
.mask
,
535 &buttons
.attributes
) != XpmSuccess
)
536 err_mess(FAILBUT
, NULL
);
542 /* Use Builtin Button Pixmap. */
544 fprintf(stdout
, "Using builtin buttons pixmap\n");
546 if (XpmCreatePixmapFromData(display
, rootwin
, buttons_xpm
,
547 &buttons
.pixmap
, &buttons
.mask
,
548 &buttons
.attributes
) != XpmSuccess
)
549 err_mess(FAILBUT
, NULL
);
553 fprintf(stdout
, "Leaving getPixmaps\n");
556 /*********************************************************************/
562 xwmhints
= XAllocWMHints();
563 xwmhints
->flags
= WindowGroupHint
| IconWindowHint
| StateHint
;
564 xwmhints
->icon_window
= iconwin
;
565 xwmhints
->window_group
= win
;
566 xwmhints
->initial_state
= WithdrawnState
;
567 XSetWMHints(display
, win
, xwmhints
);
574 XClassHint xclasshint
;
576 xclasshint
.res_name
= "wmbutton";
577 xclasshint
.res_class
= "Wmbutton";
578 XSetClassHint(display
, win
, &xclasshint
);