2 /***********************************************************************
3 * Code is stol^H^H^H^Hbased on wmppp, wmload, and wmtme
5 * Author: Ben Cohen <buddog@aztec.asu.edu>
8 * Thomas Nemeth <tnemeth@multimania.com> -- Pushed button highlighting
9 * Craig Maloney <craig@ic.net> -- CTRL + ALT + key option
12 * This program is distributed under the GPL license.
15 * Best viewed with tab = 4 ( in vi set ts=4 )
17 ***********************************************************************/
21 #define VERSION "Ver 1.2.8 -- May 25, 1999"
24 #include <X11/Xutil.h>
26 #include <X11/extensions/shape.h>
27 #include <X11/keysym.h>
32 #include "backdrop.xpm"
33 #include "buttons.xpm"
34 #include "pushed_buttons.xpm"
44 /***********************************************************************
45 * Globals.. OK.. there's too many globals.. so sue me.
46 ***********************************************************************/
50 Window rootwin
, win
, iconwin
;
53 Pixel bg_pixel
, fg_pixel
;
55 XSizeHints xsizehints
;
57 XClassHint xclasshint
;
60 typedef struct _XpmIcon
{
63 XpmAttributes attributes
;
69 typedef struct _button_region
{
74 ButtonArea button_region
[16];
76 XpmIcon
template, visible
, buttons
, pbuttons
;
78 unsigned int control
= 0;
80 int numb_of_workspaces
= 16; /* Number of buttons to display.
81 Initially set high. Changed by
82 -n switch or button 2or3 */
84 int N
= 1; /* Button number pressed to goto WS */
85 int B
= 1; /* Button number pressed to number WS's */
90 char * app_name
= "wmcp";
94 /***********************************************************************
96 ***********************************************************************/
98 void switchToWorkspaceN( int workspace
);
99 void redraw( int xbut
, int ybut
);
101 int whichButton( int x
, int y
, int xbut
, int ybut
);
102 int flush_expose(Window w
);
110 /***********************************************************************
112 ***********************************************************************/
114 int main( int argc
, char ** argv
)
119 XTextProperty app_name_atom
;
127 int window_state
= WithdrawnState
;
129 char Geometry_str
[64] = "64x64+5+5";
130 char Display_str
[64] = "";
133 /* Parse Command Line Arguments */
135 for ( i
=1; i
<argc
; i
++ ) {
136 if ( *argv
[i
] == '-' ) {
137 switch ( *(argv
[i
]+1) ) {
142 if ( ++i
>= argc
) show_usage();
143 sscanf(argv
[i
], "%s", Geometry_str
);
144 if ( Verbose
) printf("Geometry is: %s\n", Geometry_str
);
147 if ( ++i
>= argc
) show_usage();
148 sscanf(argv
[i
], "%s", Display_str
);
149 if ( Verbose
) printf("Display is: %s\n", Display_str
);
152 if ( ++i
>= argc
) show_usage();
153 sscanf(argv
[i
], "%d", &numb_of_workspaces
);
155 printf("Numb of Workspaces: %d\n", numb_of_workspaces
);
158 if ( ++i
>= argc
) show_usage();
159 if ( *argv
[i
] == 'n' ) {
166 if ( ++i
>= argc
) show_usage();
167 switch ( *argv
[i
] ) {
169 window_state
= IconicState
;
172 window_state
= WithdrawnState
;
175 window_state
= NormalState
;
180 if ( ++i
>= argc
) show_usage();
181 sscanf(argv
[i
], "%d", &xbut
);
182 if ( xbut
< 1 || xbut
> MAX_X_BUT
) xbut
= 3;
183 if ( Verbose
) printf("Num X buttons=%d\n", xbut
);
186 if ( ++i
>= argc
) show_usage();
187 sscanf(argv
[i
], "%d", &ybut
);
188 if ( ybut
< 1 || ybut
> MAX_Y_BUT
) ybut
= 3;
189 if ( Verbose
) printf("Num Y buttons=%d\n", ybut
);
192 if ( ++i
>= argc
) show_usage();
193 sscanf(argv
[i
], "%d", &alt_key_type
);
194 if ( Verbose
) printf("Alt Key is: %d\n", alt_key_type
);
198 if ( Verbose
) printf ("Control Key Modifier added\n");
213 if ( (display
= XOpenDisplay(Display_str
)) == NULL
) {
214 fprintf(stderr
,"Fail: XOpenDisplay for %s\n", Display_str
);
219 screen
= DefaultScreen(display
);
220 rootwin
= RootWindow(display
,screen
);
221 depth
= DefaultDepth(display
, screen
);
223 bg_pixel
= WhitePixel(display
, screen
);
224 fg_pixel
= BlackPixel(display
, screen
);
228 xsizehints
.flags
= USSize
| USPosition
;
229 xsizehints
.width
= 64;
230 xsizehints
.height
= 64;
233 /* Parse Geometry string and fill in sizehints fields */
235 XWMGeometry(display
, screen
,
247 if ( (win
= XCreateSimpleWindow(
255 fg_pixel
, bg_pixel
) ) == 0 ) {
256 fprintf(stderr
,"Fail: XCreateSimpleWindow\n");
260 if ( (iconwin
= XCreateSimpleWindow(
268 fg_pixel
, bg_pixel
) ) == 0 ) {
269 fprintf(stderr
,"Fail: XCreateSimpleWindow\n");
275 /* Set up shaped windows */
276 /* Gives the appicon a border so you can grab and move it. */
278 if ( is_shaped
== YES
) {
279 if ( ( pixmask
= XCreateBitmapFromData(display
, win
,
280 mask_bits
, mask_width
, mask_height
) ) == 0 ) {
281 fprintf(stderr
,"Fail: XCreateBitmapFromData\n");
284 XShapeCombineMask(display
,win
, ShapeBounding
,0,0, pixmask
,ShapeSet
);
285 XShapeCombineMask(display
,iconwin
,ShapeBounding
,0,0, pixmask
,ShapeSet
);
291 /* Convert in pixmaps from .xpm includes. */
297 /* Interclient Communication stuff */
298 /* Appicons don't work with out this stuff */
300 xwmhints
= XAllocWMHints();
301 xwmhints
->flags
= WindowGroupHint
| IconWindowHint
| StateHint
;
302 xwmhints
->icon_window
= iconwin
;
303 xwmhints
->window_group
= win
;
304 xwmhints
->initial_state
= window_state
;
307 XSetWMHints( display
, win
, xwmhints
);
309 xclasshint
.res_name
= "wmcp";
310 xclasshint
.res_class
= "WMcp";
311 XSetClassHint( display
, win
, &xclasshint
);
313 XSetWMNormalHints( display
, win
, &xsizehints
);
319 /* Tell window manager what the title bar name is. We never see */
320 /* this anyways in the WithdrawnState */
322 if ( XStringListToTextProperty(&app_name
, 1, &app_name_atom
) == 0 ) {
323 fprintf(stderr
,"%s: Can't set up window name\n", app_name
);
326 XSetWMName( display
, win
, &app_name_atom
);
330 /* Create Graphic Context */
332 if ( (gc
= XCreateGC(
335 (GCForeground
| GCBackground
),
336 &xgcValues
)) == NULL
) {
337 fprintf(stderr
,"Fail: XCreateGC\n");
345 /* XEvent Masks. We want both window to process X events */
353 StructureNotifyMask
);
361 StructureNotifyMask
);
365 /* Store the 'state' of the application for restarting */
367 XSetCommand( display
, win
, argv
, argc
);
370 /* Window won't ever show up until it is mapped.. then drawn after a */
371 /* ConfigureNotify */
373 XMapWindow( display
, win
);
380 XNextEvent(display
, &report
);
381 switch (report
.type
) {
385 if (report
.xexpose
.count
!= 0) {
388 if ( Verbose
) fprintf(stdout
,"Event: Expose\n");
389 redraw( xbut
, ybut
);
393 case ConfigureNotify
:
394 if ( Verbose
) fprintf(stdout
,"Event: ConfigureNotify\n");
395 redraw( xbut
, ybut
);
401 printf ("numb_of_workspaces=%d\n", numb_of_workspaces
);
402 switch (report
.xbutton
.button
) {
404 N
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
, xbut
, ybut
);
405 if ( N
>= 0 && N
<= numb_of_workspaces
) {
406 switchToWorkspaceN( N
);
410 fprintf(stdout
,"Button 1:x=%d y=%d N=%d\n",
411 report
.xbutton
.x
, report
.xbutton
.y
, N
);
416 B
= whichButton(report
.xbutton
.x
, report
.xbutton
.y
, xbut
, ybut
);
417 if ( B
>= 0 && B
<= 9 ) {
418 numb_of_workspaces
= B
;
422 fprintf(stdout
,"Button 2or3:x=%d y=%d B=%d\n",
423 report
.xbutton
.x
, report
.xbutton
.y
, B
);
432 fprintf(stdout
, "Bye\n");
433 XFreeGC(display
, gc
);
434 XDestroyWindow(display
,win
);
435 XDestroyWindow(display
,iconwin
);
436 XCloseDisplay(display
);
438 fprintf(stdout
, "Bye\n");
451 /***********************************************************************
454 * Map the button region coordinates.
456 * Draw the appropriate number of buttons on the 'visible' Pixmap
457 * using data from the 'buttons' pixmap.
459 * Then, copy the 'visible' pixmap to the two windows ( the withdrawn
460 * main window and the icon window which is the main window's icon image.)
462 ***********************************************************************/
464 void redraw( int xbut
, int ybut
)
468 int dest_x
, dest_y
; /* size of a whole button */
469 int step_x
, step_y
; /* size of half a button for corner copying */
471 int offset
= 8; /* skip pixels past the window's border image */
477 xbut_size
= 48 / xbut
;
478 ybut_size
= 48 / ybut
;
482 template.pixmap
, visible
.pixmap
,
485 template.attributes
.width
,
486 template.attributes
.height
,
490 for ( j
=0; j
< ybut
; j
++ ) {
491 for ( i
=0; i
< xbut
; i
++ ) {
494 dest_x
= ( i
* xbut_size
) + offset
;
495 dest_y
= ( j
* ybut_size
) + offset
;
499 /* Define button mouse coords */
501 button_region
[n
].x
= dest_x
;
502 button_region
[n
].y
= dest_y
;
503 button_region
[n
].i
= dest_x
+ xbut_size
- 1;
504 button_region
[n
].j
= dest_y
+ ybut_size
- 1;
507 /* Copy button images for valid workspaces */
509 if ( (n
+ 1) <= numb_of_workspaces
) {
511 /* Draw normal button */
512 /* Edited by Gert Beumer */
513 if ( (n
+ 1) != N
) {
538 48 - step_x
,48 - step_y
,
552 /* Draw the numbers */
560 dest_x
+ (48 - xbut
* 5) / (2 * xbut
),
561 dest_y
+ (48 - ybut
* 5) / (2 * ybut
));
564 /* Draw pushed button */
565 /* Added by Thomas Nemeth, Edited by Gert Beumer */
566 if ( (n
+ 1) == N
) {
567 /* draw the four parts */
592 48 - step_x
,48 - step_y
,
606 /* Draw the numbers */
614 dest_x
+ (48 - xbut
* 5) / (2 * xbut
),
615 dest_y
+ (48 - ybut
* 5) / (2 * ybut
));
625 visible
.pixmap
, win
, gc
,
627 visible
.attributes
.width
,
628 visible
.attributes
.height
,
631 flush_expose( iconwin
);
633 visible
.pixmap
, iconwin
, gc
,
635 visible
.attributes
.width
,
636 visible
.attributes
.height
,
641 fprintf(stdout
,"In Redraw()\n");
648 /***********************************************************************
651 * Return the button that at the x,y coordinates. The button need not
652 * be visible ( drawn ). Return -1 if no button match.
654 ***********************************************************************/
656 int whichButton( int x
, int y
, int xbut
, int ybut
)
660 for ( index
=0; index
< xbut
*ybut
; index
++ ) {
661 if ( x
>= button_region
[index
].x
&&
662 x
<= button_region
[index
].i
&&
663 y
>= button_region
[index
].y
&&
664 y
<= button_region
[index
].j
) {
675 /***********************************************************************
676 * switchToWorkspaceN()
678 * Send the Synthetic Key Press event with the appropriate
679 * [ meta key + 1-4 key ] combo. Alt seems to usualy be Mod1Mask.
681 ***********************************************************************/
683 void switchToWorkspaceN( int workspace
) {
687 sendEvent
.xkey
.type
= KeyPress
;
688 sendEvent
.xkey
.window
= rootwin
;
689 sendEvent
.xkey
.root
= rootwin
;
690 sendEvent
.xkey
.subwindow
= 0x0;
691 switch ( alt_key_type
) {
693 sendEvent
.xkey
.state
= Mod1Mask
+control
;
696 sendEvent
.xkey
.state
= Mod2Mask
+control
;
699 sendEvent
.xkey
.state
= Mod3Mask
+control
;
702 sendEvent
.xkey
.state
= Mod4Mask
+control
;
705 sendEvent
.xkey
.keycode
= XKeysymToKeycode(display
, 0x30 + workspace
);
706 sendEvent
.xkey
.same_screen
= True
;
707 sendEvent
.xkey
.display
= display
;
708 sendEvent
.xkey
.send_event
= False
;
710 XSendEvent( display
, rootwin
, True
, KeyPressMask
, &sendEvent
);
714 /***********************************************************************
717 * Load XPM data into X Pixmaps.
719 * Pixmap template contains the untouched window backdrop image.
720 * Pixmap visible is the template pixmap with buttons drawn on it.
721 * -- what is seen by the user.
722 * Pixmap buttons holds the images for individual buttons that are
723 * later copied onto Pixmap visible.
724 ***********************************************************************/
728 template.attributes
.valuemask
|=
729 (XpmReturnPixels
| XpmReturnExtensions
);
730 visible
.attributes
.valuemask
|=
731 (XpmReturnPixels
| XpmReturnExtensions
);
732 buttons
.attributes
.valuemask
|=
733 (XpmReturnPixels
| XpmReturnExtensions
);
735 /* Template Pixmap. Never Drawn To. */
736 if ( XpmCreatePixmapFromData( display
,
741 &template.attributes
) != XpmSuccess
) {
742 fprintf(stderr
, "Can't Create 'template' Pixmap");
746 /* Visible Pixmap. Copied from template Pixmap and then drawn to. */
747 if ( XpmCreatePixmapFromData( display
,
752 &visible
.attributes
) != XpmSuccess
) {
753 fprintf(stderr
, "Can't Create 'visible' Pixmap");
757 /* Buttons Pixmap. */
758 if ( XpmCreatePixmapFromData( display
,
763 &buttons
.attributes
) != XpmSuccess
) {
764 fprintf(stderr
, "Can't Create 'buttons' Pixmap");
768 /* Pushed Buttons Pixmap. */
769 if ( XpmCreatePixmapFromData( display
,
774 &pbuttons
.attributes
) != XpmSuccess
) {
775 fprintf(stderr
, "Can't Create 'pbuttons' Pixmap");
784 /***********************************************************************
787 * Everyone else has one of these... Can't hurt to throw it in.
789 ***********************************************************************/
790 int flush_expose(Window w
) {
795 while (XCheckTypedWindowEvent(display
, w
, Expose
, &dummy
))
802 /***********************************************************************
805 ***********************************************************************/
813 This software is GPL -- do as you wish with it.\n\
816 Ben Cohen <buddog@aztec.asu.edu>\n\
819 Thomas Nemeth <tnemeth@multimania.com>\n\
820 Craig Maloney <craig@ic.net>\n\
821 Gert Beumer <Gert@scintilla.utwente.nl>\n\
825 usage: wmcp [-g geometry] [-d dpy] [-n workspaces] [-a alt key] [-v]\n\
826 [-c] [-w i/n/w] [-s y/n] [-x #] [-y #] [-h]\n\
829 -g geometry: ie: 64x64+10+10\n\
830 -d dpy: Display. ie: 127.0.0.1:0.0\n\
831 -n workspaces: How many buttons to start with.\n\
832 -a alt key: integer 1-4 defining ModXMask (default 1 Mod1Mask).\n\
833 -w i/n/w: Window State: Iconic, Normal, Withdrawn (default Withdrawn)\n\
834 -s y/n: Shaped window: yes or no (default y)\n\
835 -c Sends CTRL + ALT + Key (default only sends ALT + key)\n\
836 -v Verbose. 0=off, 1=on (default 0)\n\
837 -x Number of buttons on the x-direction (1,2,3, or 4)\n\
838 -y Number of buttons in the y-direction (1,2,3, or 4)\n\
839 -h Help. This screen.\n\
849 KeyPress event, serial 13, synthetic NO, window 0x25,
850 root 0x25, subw 0x0, time 3340683384, (37,254), root:(37,254),
851 state 0x8, keycode 10 (keysym 0x31, 1), same_screen YES,
852 XLookupString gives 1 characters: "1"
854 KeyPress event, serial 13, synthetic YES, window 0xbffff9ac,
855 root 0x40009b48, subw 0x4000a670, time 2, (26460,-1352), root:(-1146,7),
856 state 0x7de0, keycode 64 (keysym 0xffe9, Alt_L), same_screen YES,
857 XLookupString gives 0 characters: ""