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
;
102 int N
= 1; /* Button number pressed to goto app # */
104 /* Added for Tool Tip Support */
105 long nTooltipShowDelay
= TOOLTIP_SHOW_DELAY
;
106 long nTooltipReshowDelay
= TOOLTIP_RESHOW_DELAY
;
107 long nTooltipTimer
= -1;
108 long nTooltipHideTimer
= -1;
110 int nTooltipButton
= 0, nTooltipX
= 0, nTooltipY
= 0;
112 /* Parse Command Line Arguments */
113 parseargs(argc
, argv
);
116 if ( (display
= XOpenDisplay(Config
.Display_str
)) == NULL
)
117 err_mess(FAILDISP
, Config
.Display_str
);
119 screen
= DefaultScreen(display
);
120 rootwin
= RootWindow(display
,screen
);
121 depth
= DefaultDepth(display
, screen
);
123 bg_pixel
= WhitePixel(display
, screen
);
124 fg_pixel
= BlackPixel(display
, screen
);
126 xsizehints
.flags
= USSize
| USPosition
;
127 xsizehints
.width
= 64;
128 xsizehints
.height
= 64;
130 /* Parse Geometry string and fill in sizehints fields */
131 XWMGeometry(display
, screen
,
142 if ( (win
= XCreateSimpleWindow(display
,
149 fg_pixel
, bg_pixel
) ) == 0 )
150 err_mess(FAILSWIN
, NULL
);
153 if ( (iconwin
= XCreateSimpleWindow(display
,
160 fg_pixel
, bg_pixel
) ) == 0 )
161 err_mess(FAILICON
, NULL
);
163 /* Set up shaped windows */
164 /*Gives the appicon a border so you can grab and move it. */
166 if ( ( pixmask
= XCreateBitmapFromData(display
,
170 mask_height
) ) == 0 )
171 err_mess(FAILXPM
,NULL
);
174 XShapeCombineMask(display
, win
, ShapeBounding
, 0, 0, pixmask
, ShapeSet
);
175 XShapeCombineMask(display
, iconwin
, ShapeBounding
, 0, 0, pixmask
, ShapeSet
);
177 /* Convert in pixmaps from .xpm includes. */
180 /* Interclient Communication stuff */
181 /* Appicons don't work with out this stuff */
186 XSetWMNormalHints( display
, win
, &xsizehints
);
188 /* Tell window manager what the title bar name is. We never see */
189 /* this anyways in the WithdrawnState */
190 if ( XStringListToTextProperty(&app_name
, 1, &app_name_atom
) == 0 )
191 err_mess(FAILWNAM
,app_name
);
192 XSetWMName( display
, win
, &app_name_atom
);
194 /* Create Graphic Context */
195 if (( gc
= XCreateGC(display
, win
,(GCForeground
| GCBackground
), &xgcValues
))
197 err_mess(FAILGC
,NULL
);
199 /* XEvent Masks. We want both window to process X events */
200 XSelectInput(display
, win
,
203 ButtonReleaseMask
| /* added ButtonReleaseMask *charkins*/
205 StructureNotifyMask
|
207 XSelectInput(display
, iconwin
,
210 ButtonReleaseMask
| /* added ButtonReleaseMask *charkins*/
212 StructureNotifyMask
|
215 /* Store the 'state' of the application for restarting */
216 XSetCommand( display
, win
, argv
, argc
);
218 /* Window won't ever show up until it is mapped.. then drawn after a */
219 /* ConfigureNotify */
220 XMapWindow( display
, win
);
222 /* Initialize Tooltip Support */
224 initTooltip(!Config
.bTooltipDisable
, Config
.szTooltipFont
, Config
.bTooltipSwapColors
);
228 while (XPending(display
) || nTooltipTimer
== -1) {
229 XNextEvent(display
, &report
);
230 switch (report
.type
) {
232 if (report
.xexpose
.count
!= 0) {
235 if ( Config
.Verbose
) fprintf(stdout
,"Event: Expose\n");
239 case ConfigureNotify
:
240 if ( Config
.Verbose
) fprintf(stdout
,"Event: ConfigureNotify\n");
245 if (hasTooltipSupport()) {
247 nTooltipTimer
= currentTimeMillis();
248 nTooltipX
= report
.xbutton
.x
;
249 nTooltipY
= report
.xbutton
.y
;
250 nTooltipButton
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
252 int nButton
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
253 if (nButton
!= nTooltipButton
) {
256 nTooltipX
= report
.xbutton
.x
;
257 nTooltipY
= report
.xbutton
.y
;
258 nTooltipButton
= nButton
;
259 showTooltip(nTooltipButton
, nTooltipX
, nTooltipY
);
266 if ( Config
.Verbose
) fprintf(stdout
,"Event: LeaveNotify\n");
269 nTooltipHideTimer
= currentTimeMillis();
274 case ButtonPress
: /* draw button pressed, don't launch *charkins*/
277 nTooltipHideTimer
= currentTimeMillis();
278 } switch (report
.xbutton
.button
) {
280 N
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
281 if ( (N
>= 0) && (N
<= NUMB_OF_APPS
) ) {
282 button_pressed
= N
+ LMASK
;
286 if ( Config
.Verbose
)
287 fprintf(stdout
,"Button 1:x=%d y=%d N=%d\n",
288 report
.xbutton
.x
, report
.xbutton
.y
, N
+LMASK
);
293 N
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
294 if ( (N
>= 0) && (N
<= NUMB_OF_APPS
) ) {
295 button_pressed
= N
+ MMASK
;
299 if ( Config
.Verbose
)
300 fprintf(stdout
,"Button 2:x=%d y=%d N=%d\n",
301 report
.xbutton
.x
, report
.xbutton
.y
, N
+MMASK
);
306 N
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
307 if ( (N
>= 0) && (N
<= NUMB_OF_APPS
) ) {
308 button_pressed
= N
+ RMASK
;
312 if ( Config
.Verbose
)
313 fprintf(stdout
,"Button 3:x=%d y=%d N=%d\n",
314 report
.xbutton
.x
, report
.xbutton
.y
, N
+RMASK
);
319 case ButtonRelease
: /* launch app here if still over button *charkins*/
320 switch (report
.xbutton
.button
) {
322 N
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
323 if ( (N
>= 0) && (N
<= NUMB_OF_APPS
) && (N
== button_pressed
))
328 if ( Config
.Verbose
)
329 fprintf(stdout
,"Button 1:x=%d y=%d N=%d\n",
330 report
.xbutton
.x
, report
.xbutton
.y
, N
+LMASK
);
335 N
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
336 if ( (N
>= 0) && (N
<= NUMB_OF_APPS
) && (N
== button_pressed
))
341 if ( Config
.Verbose
)
342 fprintf(stdout
,"Button 2:x=%d y=%d N=%d\n",
343 report
.xbutton
.x
, report
.xbutton
.y
, N
+MMASK
);
348 N
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
);
349 if ( (N
>= 0) && (N
<= NUMB_OF_APPS
) && (N
== button_pressed
))
354 if ( Config
.Verbose
)
355 fprintf(stdout
,"Button 3:x=%d y=%d N=%d\n",
356 report
.xbutton
.x
, report
.xbutton
.y
, N
+RMASK
);
363 if ( Config
.Verbose
) fprintf(stdout
, "Bye\n");
366 XFreeGC(display
, gc
);
367 XDestroyWindow(display
,win
);
368 XDestroyWindow(display
,iconwin
);
369 XCloseDisplay(display
);
376 nNow
= currentTimeMillis();
377 if ( nTooltipTimer
!= -1 &&
378 ( (nNow
> nTooltipTimer
+ nTooltipShowDelay
) || (nNow
< nTooltipHideTimer
+ nTooltipReshowDelay
) ) ) {
379 showTooltip(nTooltipButton
, nTooltipX
, nTooltipY
);
386 }/***********************************************************************/
388 /***********************************************************************
391 * Map the button region coordinates.
393 * Draw the appropriate number of buttons on the 'visible' Pixmap
394 * using data from the 'buttons' pixmap.
396 * Then, copy the 'visible' pixmap to the two windows ( the withdrawn
397 * main window and the icon window which is the main window's icon image.)
398 ***********************************************************************/
407 if ( Config
.Verbose
) fprintf(stdout
,"In Redraw()\n");
410 XCopyArea(display
, template.pixmap
, visible
.pixmap
, gc
, 0, 0,
411 template.attributes
.width
, template.attributes
.height
, 0, 0 );
413 for ( j
=0; j
< 3; j
++ ) {
414 for ( i
=0; i
< 3; i
++ ) {
416 dest_x
= i
*(bsize
+ space
) + offset
+ space
;
417 dest_y
= j
*(bsize
+ space
) + offset
+ space
;
419 /* Define button mouse coords */
420 button_region
[n
].x
= dest_x
;
421 button_region
[n
].y
= dest_y
;
422 button_region
[n
].i
= dest_x
+ bsize
- 1;
423 button_region
[n
].j
= dest_y
+ bsize
- 1;
425 /* Copy button images for valid apps */
426 if ( (n
+ 1) <= NUMB_OF_APPS
) {
427 XCopyArea(display
, buttons
.pixmap
, visible
.pixmap
, gc
,
428 i
* bsize
, j
* bsize
, bsize
, bsize
, dest_x
, dest_y
);
433 if ( button_pressed
>0 ) { /* draw pressed button *charkins*/
434 if(button_pressed
>RMASK
) button_pressed
-=RMASK
;
435 else if(button_pressed
>MMASK
) button_pressed
-=MMASK
;
436 else if(button_pressed
>LMASK
) button_pressed
-=LMASK
;
437 i
= (button_pressed
-1) % 3; /* get col of button */
438 j
= (button_pressed
-1) / 3; /* get row of button */
439 dest_x
= i
* (bsize
+ space
) + offset
+ space
;
440 dest_y
= j
* (bsize
+ space
) + offset
+ space
;
441 XSetForeground(display
, gc
, bg_pixel
);
442 XDrawLine(display
, visible
.pixmap
, gc
,
443 dest_x
+1, dest_y
+bsize
-1, dest_x
+bsize
-1, dest_y
+bsize
-1);
444 XDrawLine(display
, visible
.pixmap
, gc
,
445 dest_x
+bsize
-1, dest_y
+bsize
-1, dest_x
+bsize
-1, dest_y
+1);
446 XSetForeground(display
, gc
, fg_pixel
);
447 XDrawLine(display
, visible
.pixmap
, gc
,
448 dest_x
, dest_y
, dest_x
+bsize
-2, dest_y
);
449 XDrawLine(display
, visible
.pixmap
, gc
,
450 dest_x
, dest_y
, dest_x
, dest_y
+bsize
-2);
454 XCopyArea(display
, visible
.pixmap
, win
, gc
, 0, 0,
455 visible
.attributes
.width
, visible
.attributes
.height
, 0, 0 );
456 flush_expose( iconwin
);
457 XCopyArea(display
, visible
.pixmap
, iconwin
, gc
, 0, 0,
458 visible
.attributes
.width
, visible
.attributes
.height
, 0, 0 );
460 }/***********************************************************************/
462 /***********************************************************************
465 * Return the button that at the x,y coordinates. The button need not
466 * be visible ( drawn ). Return -1 if no button match.
467 ***********************************************************************/
468 int whichButton( int x
, int y
) {
471 for ( index
=0; index
< NUMB_OF_APPS
; index
++ ) {
472 if ( x
>= button_region
[index
].x
&&
473 x
<= button_region
[index
].i
&&
474 y
>= button_region
[index
].y
&&
475 y
<= button_region
[index
].j
) {
480 }/***********************************************************************/
483 /***********************************************************************
486 * Load XPM data into X Pixmaps.
488 * Pixmap template contains the untouched window backdrop image.
489 * Pixmap visible is the template pixmap with buttons drawn on it.
490 * -- what is seen by the user.
491 * Pixmap buttons holds the images for individual buttons that are
492 * later copied onto Pixmap visible.
493 ***********************************************************************/
496 template.attributes
.valuemask
|= (XpmReturnPixels
| XpmReturnExtensions
);
497 visible
.attributes
.valuemask
|= (XpmReturnPixels
| XpmReturnExtensions
);
498 buttons
.attributes
.valuemask
|= (XpmReturnPixels
| XpmReturnExtensions
);
501 if (Config
.Verbose
) fprintf(stdout
, "In getPixmaps\n");
502 /* Template Pixmap. Never Drawn To. */
503 if ( XpmCreatePixmapFromData( display
, rootwin
, backdrop_xpm
,
504 &template.pixmap
, &template.mask
,
505 &template.attributes
) != XpmSuccess
)
506 err_mess(FAILTMPL
, NULL
);
508 /* Visible Pixmap. Copied from template Pixmap and then drawn to. */
509 if ( XpmCreatePixmapFromData( display
, rootwin
, backdrop_xpm
,
510 &visible
.pixmap
, &visible
.mask
,
511 &visible
.attributes
) != XpmSuccess
)
512 err_mess(FAILVIS
, NULL
);
515 if ( access( Config
.buttonfile
, R_OK
) == 0 ) {
516 /* load buttons from file */
517 if ( XpmReadFileToPixmap( display
, rootwin
, Config
.buttonfile
,
518 &buttons
.pixmap
, &buttons
.mask
,
519 &buttons
.attributes
) != XpmSuccess
) {
520 err_mess(FAILBUT
, NULL
);
526 /* Use Builtin Button Pixmap. */
527 if (Config
.Verbose
) fprintf(stdout
, "Using builtin buttons pixmap\n");
528 if ( XpmCreatePixmapFromData( display
, rootwin
, buttons_xpm
,
529 &buttons
.pixmap
, &buttons
.mask
,
530 &buttons
.attributes
) != XpmSuccess
)
531 err_mess(FAILBUT
, NULL
);
533 if (Config
.Verbose
) fprintf(stdout
, "Leaving getPixmaps\n");
535 }/*********************************************************************/
540 xwmhints
= XAllocWMHints();
541 xwmhints
->flags
= WindowGroupHint
| IconWindowHint
| StateHint
;
542 xwmhints
->icon_window
= iconwin
;
543 xwmhints
->window_group
= win
;
544 xwmhints
->initial_state
= WithdrawnState
;
545 XSetWMHints( display
, win
, xwmhints
);
550 void SetClassHints() {
551 XClassHint xclasshint
;
553 xclasshint
.res_name
= "wmbutton";
554 xclasshint
.res_class
= "Wmbutton";
555 XSetClassHint( display
, win
, &xclasshint
);