1 /* $Id: wmpager.c,v 1.4 2002/08/16 17:22:26 essmann Exp $
3 * Copyright (c) 2001 Bruno Essmann <essmann@users.sourceforge.net>
11 #include <X11/extensions/shape.h>
13 #include <sys/types.h>
20 #include "buttons.xpm"
27 #define AUTHOR "Bruno Essmann <essmann@users.sourceforge.net>"
28 #define APPLICATION "wmpager"
30 #define BUILD_REV "$Revision: 1.4 $"
31 #define BUILD_DATE "$Date: 2002/08/16 17:22:26 $"
33 #define XA_WIN_WORKSPACE "_WIN_WORKSPACE"
34 #define XA_WIN_WORKSPACE_NAMES "_WIN_WORKSPACE_NAMES"
36 #define WMPAGER_ENV "WMPAGER"
37 #define WMPAGER_DEFAULT_INSTALL_DIR "/usr/local/share/wmpager/"
38 #define WMPAGER_USER_DIR ".wmpager/"
44 void usage (int bVerbose
);
46 void setVerbose (int bVerbose
);
49 void initApplicationName (char* szApplicationName
);
50 char* getApplicationName ();
52 void initDisplay (char* szDisplay
);
53 void destroyDisplay ();
54 Display
* getDisplay ();
56 Pixel
getWhitePixel ();
57 Pixel
getBlackPixel ();
58 int getDefaultScreen ();
59 int getDefaultDepth ();
60 void initWindow (int nArgc
, char** szArgv
);
61 void destroyWindow ();
62 GC
getWindowGraphics ();
63 GC
getMainGraphics ();
64 void initWindowMask (char* szInstallDir
, char* szButtonTheme
);
66 void getWindowOrigin (Window w
, int* nX
, int* nY
);
70 void initButtons (int nButtons
, int nColumns
, int nRows
);
71 int getButtonCount ();
72 int getButtonRowCount ();
73 int getButtonColumnCount ();
74 int getButtonWidth ();
75 int getButtonHeight ();
76 int getButtonAt (int nLocationX
, int nLocationY
);
77 void getButtonLocation (int nButton
, int* nLocationX
, int* nLocationY
);
80 long currentTimeMillis ();
83 int getScreenCount ();
84 char* getScreenName (int nScreen
);
85 int getCurrentScreen ();
86 void setCurrentScreen (int nCurrentScreen
);
87 void gotoScreen (int nWorkspace
);
93 int main (int nArgc
, char** szArgv
) {
94 char* szDisplay
= NULL
;
96 char* szInstallDir
= NULL
;
99 int nSizeX
= -1, nSizeY
= -1;
101 initApplicationName(szArgv
[0]);
102 /* we no longer use the WMPAGER environment variable
103 * szInstallDir= (char*) getenv(WMPAGER_ENV);
104 * instead we simply use a default installation directory
106 szInstallDir
= WMPAGER_DEFAULT_INSTALL_DIR
;
109 if (strcmp("-h", szArgv
[i
]) == 0 || strcmp("--help", szArgv
[i
]) == 0) {
111 } else if (strcmp("-v", szArgv
[i
]) == 0 || strcmp("--verbose", szArgv
[i
]) == 0) {
113 } else if (strcmp("-w", szArgv
[i
]) == 0 || strcmp("--workspaces", szArgv
[i
]) == 0) {
116 sscanf(szArgv
[i
], "%d", &nWorkspaces
);
117 if (nWorkspaces
<= 0 || nWorkspaces
> 9) {
118 fprintf(stderr
, "%s: illegal number of workspaces '%s' for option '%s' (has to be 1-9)\n\n", getApplicationName(), szArgv
[i
], szArgv
[i
-1]);
122 fprintf(stderr
, "%s: workspace count expected for '%s'\n\n", getApplicationName(), szArgv
[i
-1]);
125 } else if (strcmp("-s", szArgv
[i
]) == 0 || strcmp("--size", szArgv
[i
]) == 0) {
128 sscanf(szArgv
[i
], "%dx%d", &nSizeX
, &nSizeY
);
129 if (nSizeX
<= 0 || nSizeX
> 3 || nSizeY
<= 0 || nSizeY
> 3) {
130 fprintf(stderr
, "%s: illegal size '%s' for option '%s' (has to be 1x1 .. 3x3)\n\n", getApplicationName(), szArgv
[i
], szArgv
[i
-1]);
134 fprintf(stderr
, "%s: size argument expected for '%s'\n\n", getApplicationName(), szArgv
[i
-1]);
137 } else if (strcmp("-i", szArgv
[i
]) == 0 || strcmp("--installdir", szArgv
[i
]) == 0) {
141 szInstallDir
= szArgv
[i
];
142 if (stat(szInstallDir
, &buf
) != 0) {
143 fprintf(stderr
, "%s: cannot access installation directory '%s'\n\n", getApplicationName(), szArgv
[i
]);
147 fprintf(stderr
, "%s: display argument expected for '%s'\n\n", getApplicationName(), szArgv
[i
-1]);
150 } else if (strcmp("-d", szArgv
[i
]) == 0 || strcmp("--display", szArgv
[i
]) == 0) {
153 szDisplay
= szArgv
[i
];
155 fprintf(stderr
, "%s: display argument expected for '%s'\n\n", getApplicationName(), szArgv
[i
-1]);
158 } else if (strcmp("-t", szArgv
[i
]) == 0 || strcmp("--theme", szArgv
[i
]) == 0) {
163 fprintf(stderr
, "%s: theme argument expected for '%s'\n\n", getApplicationName(), szArgv
[i
-1]);
167 fprintf(stderr
, "%s: unknown option '%s'\n\n", getApplicationName(), szArgv
[i
]);
172 setVerbose(bVerbose
);
174 char* szRealDisplay
= (szDisplay
== NULL
) ? (char*) getenv("DISPLAY") : szDisplay
;
175 if (szRealDisplay
== NULL
) {
176 szRealDisplay
= "localhost:0.0";
181 "[ ] startup options:\n" \
182 "[ ] - verbose= true\n" \
183 "[ ] - display= '%s'\n" \
184 "[ ] - installdir= '%s'\n" \
185 "[ ] - theme= '%s'\n" \
186 "[ ] - workspaces= '%d'\n" \
187 "[ ] - size= '%dx%d'\n",
189 szInstallDir
== NULL
? "<undefined>" : szInstallDir
,
190 szTheme
== NULL
? "<built-in>" : szTheme
,
196 initDisplay(szDisplay
);
197 initWindow(nArgc
, szArgv
);
199 initButtons(nWorkspaces
, nSizeX
, nSizeY
);
200 initWindowMask(szInstallDir
, szTheme
);
209 static int _bVerbose
;
211 void setVerbose (int bVerbose
) {
224 "usage: %s [options]\n\n" \
225 "where options include:\n" \
226 " -h --help display usage and version information\n" \
227 " -v --verbose verbose message output\n" \
228 " -d --display <name> the display to use (defaults to the\n" \
229 " 'DISPLAY' environment variable)\n" \
230 " -s --size <w>x<h> number of buttons (default depends on the\n" \
231 " number of workspaces you have, i.e. 2x2 for 4\n" \
232 " workspaces, 2x3 for 6, maximum is 3x3)\n" \
233 " -w --workspaces <count> number of workspace buttons to display\n" \
234 " (default is the number of workspaces you have,\n" \
236 " -t --theme <theme.xpm> the button theme to use, extension\n" \
237 " '.xpm' is optional, for more information about\n" \
238 " themes see docu (default is the built-in theme)\n" \
239 " -i --installdir <dir> specifies the installation directory location,\n" \
240 " this location is automatically searched for themes\n" \
241 " (defaults to the '/usr/local/share/wmpager/'\n" \
242 " and the user specific '~/.wmpager' directory)\n"
244 void usage (int bVerbose
) {
247 fprintf(stdout
, USAGE
, getApplicationName());
250 fprintf(stderr
, USAGE
, getApplicationName());
256 char* szRev
= strdup(BUILD_REV
);
257 char* szDate
= strdup(BUILD_DATE
);
259 szRev
[strlen(szRev
) - 2]= '\0';
261 szDate
[strlen(szDate
) - 2]= '\0';
262 fprintf(stdout
, "%s %s (build %s, %s)\n\n", APPLICATION
, VERSION
, szRev
, szDate
);
269 static char* _szApplicationName
;
271 char* getApplicationName () {
272 return _szApplicationName
;
275 void initApplicationName (char* szApplicationName
) {
276 if (szApplicationName
== NULL
) {
277 _szApplicationName
= APPLICATION
;
279 _szApplicationName
= strdup(szApplicationName
);
287 static Display
* _display
;
289 Display
* getDisplay () {
293 void destroyDisplay () {
294 XCloseDisplay(getDisplay());
297 void initDisplay (char* szDisplay
) {
298 if (szDisplay
== NULL
&& ((char*) getenv("DISPLAY")) == NULL
) {
302 char* szRealDisplay
= (szDisplay
== NULL
) ? (char*) getenv("DISPLAY") : szDisplay
;
303 if (szRealDisplay
== NULL
) {
304 szRealDisplay
= "localhost:0.0";
306 fprintf(stdout
, "[%8ld] initializing display '%s'\n", currentTimeMillis(), szRealDisplay
);
308 _display
= XOpenDisplay(szDisplay
);
309 if (_display
== NULL
) {
312 "%s: couldn't open display '%s'.\n",
313 getApplicationName(),
314 (szDisplay
== NULL
) ? ((char*) getenv("DISPLAY")) : szDisplay
324 static int _nDefaultScreen
, _nDefaultDepth
;
325 static Window _wRoot
, _wMain
, _wIcon
;
326 static GC _gcMain
, _gcWindow
;
327 static XpmAttributes _attrButtonTheme
;
328 static Pixmap _pButtonTheme
, _pButtonThemeMask
;
329 static XpmAttributes _attrWindow
;
330 static Pixmap _pWindow
, _pWindowMask
;
331 static Pixel _pWhite
, _pBlack
;
333 Pixel
getWhitePixel () {
337 Pixel
getBlackPixel () {
341 int getDefaultScreen () {
342 return _nDefaultScreen
;
345 int getDefaultDepth () {
346 return _nDefaultDepth
;
349 Window
getRootWindow () {
353 Window
getMainWindow () {
357 Window
getIconWindow () {
361 GC
getMainGraphics () {
365 GC
getWindowGraphics () {
369 void initWindow (int nArgc
, char** szArgv
) {
370 char* szApplicationName
= getApplicationName();
371 Display
* display
= getDisplay();
372 XSizeHints
*xsizehints
;
374 XClassHint
* xclasshint
;
375 XTextProperty
* xtApplication
;
379 fprintf(stdout
, "[%8ld] initializing application window\n", currentTimeMillis());
382 _nDefaultScreen
= DefaultScreen(display
);
383 _nDefaultDepth
= DefaultDepth(display
, _nDefaultScreen
);
384 _wRoot
= RootWindow(display
, _nDefaultScreen
);
386 XSelectInput(display
, _wRoot
, PropertyChangeMask
);
388 _pWhite
= WhitePixel(display
, _nDefaultScreen
);
389 _pBlack
= BlackPixel(display
, _nDefaultScreen
);
391 xsizehints
= XAllocSizeHints();
392 xsizehints
->flags
= USSize
| USPosition
;
393 xsizehints
->width
= xsizehints
->height
= 64;
395 _wMain
= XCreateSimpleWindow(display
, _wRoot
, 0, 0, 64, 64, 5, _pWhite
, _pBlack
);
397 fprintf(stderr
, "Cannot create main window.\n");
401 _wIcon
= XCreateSimpleWindow(display
, _wMain
, 0, 0, 64, 64, 5, _pWhite
, _pBlack
);
403 fprintf(stderr
, "Cannot create icon window.\n");
407 xwmhints
= XAllocWMHints();
408 xwmhints
->flags
= WindowGroupHint
| IconWindowHint
| StateHint
;
409 xwmhints
->icon_window
= _wIcon
;
410 xwmhints
->window_group
= _wMain
;
411 xwmhints
->initial_state
= WithdrawnState
;
412 XSetWMHints(display
, _wMain
, xwmhints
);
414 xclasshint
= XAllocClassHint();
415 xclasshint
->res_name
= APPLICATION
;
416 xclasshint
->res_class
= APPLICATION
;
417 XSetClassHint(display
, _wMain
, xclasshint
);
419 XSetWMNormalHints(display
, _wMain
, xsizehints
);
421 xtApplication
= (XTextProperty
*) malloc(sizeof(XTextProperty
));
422 if (XStringListToTextProperty(&szApplicationName
, 1, xtApplication
) == 0) {
423 fprintf(stderr
, "Cannot set window title.\n");
426 XSetWMName(display
, _wMain
, xtApplication
);
428 _gcMain
= XCreateGC(display
, _wMain
, (GCForeground
| GCBackground
), &xgcMain
);
429 if (_gcMain
== NULL
) {
430 fprintf(stderr
, "Cannot create graphics context.\n");
434 XSelectInput(display
, _wMain
, ExposureMask
| ButtonPressMask
| PointerMotionMask
| StructureNotifyMask
| LeaveWindowMask
);
435 XSelectInput(display
, _wIcon
, ExposureMask
| ButtonPressMask
| PointerMotionMask
| StructureNotifyMask
| LeaveWindowMask
);
437 XSetCommand(display
, _wMain
, szArgv
, nArgc
);
439 XMapWindow(display
, _wMain
);
442 void destroyWindow () {
443 XFreeGC(getDisplay(), getWindowGraphics());
444 XFreeGC(getDisplay(), getMainGraphics());
445 XDestroyWindow(getDisplay(), getMainWindow());
446 XDestroyWindow(getDisplay(), getIconWindow());
449 void initWindowMask (char* szInstallDir
, char* szButtonTheme
) {
450 Display
* display
= getDisplay();
452 Window wRoot
= getRootWindow();
453 Window wMain
= getMainWindow();
454 Window wIcon
= getIconWindow();
455 XGCValues xgc
, xgcWindow
;
456 Pixmap pOpaque
, pTransparent
, pMask
;
457 char* mask
= (char*) malloc(512);
461 fprintf(stdout
, "[%8ld] initializing window mask\n", currentTimeMillis());
463 for (i
= 0; i
< 512; i
++) {
466 pTransparent
= XCreateBitmapFromData(display
, wRoot
, mask
, 64, 64);
467 if (pTransparent
== 0) {
468 fprintf(stderr
, "%s: couldn't create window mask (transparent).\n", getApplicationName());
471 pMask
= XCreateBitmapFromData(display
, wRoot
, mask
, 64, 64);
473 fprintf(stderr
, "%s: couldn't create window mask (mask buffer).\n", getApplicationName());
477 for (i
= 0; i
< 512; i
++) {
480 pOpaque
= XCreateBitmapFromData(display
, wRoot
, mask
, 64, 64);
482 fprintf(stderr
, "%s: couldn't create window mask (opaque).\n", getApplicationName());
486 gc
= XCreateGC(display
, pMask
, (GCForeground
| GCBackground
), &xgc
);
488 fprintf(stderr
, "%s: couldn't create window mask (mask graphics).\n", getApplicationName());
491 for (i
= 0; i
< getButtonCount(); i
++) {
492 int nButtonX
, nButtonY
;
493 getButtonLocation(i
, &nButtonX
, &nButtonY
);
494 XCopyArea(display
, pOpaque
, pMask
, gc
, nButtonX
, nButtonY
, getButtonWidth(), getButtonHeight(), nButtonX
, nButtonY
);
497 XFreePixmap(display
, pOpaque
);
498 XFreePixmap(display
, pTransparent
);
499 XFreeGC(display
, gc
);
501 XShapeCombineMask(display
, wMain
, ShapeBounding
, 0, 0, pMask
, ShapeSet
);
502 XShapeCombineMask(display
, wIcon
, ShapeBounding
, 0, 0, pMask
, ShapeSet
);
505 fprintf(stdout
, "[%8ld] initializing button theme '%s'\n", currentTimeMillis(),
506 szButtonTheme
== NULL
? "<built-in>" : szButtonTheme
);
509 _attrButtonTheme
.valuemask
|= (XpmReturnPixels
| XpmReturnExtensions
);
510 if (szButtonTheme
== NULL
) {
512 XpmCreatePixmapFromData(
513 display
, wRoot
, buttons_xpm
, &_pButtonTheme
, &_pButtonThemeMask
, &_attrButtonTheme
516 fprintf(stderr
, "%s: couldn't create button theme.\n", getApplicationName());
522 /* check for absolute button theme pathname */
523 if (stat(szButtonTheme
, &buf
) == -1) {
524 char* szNewTheme
= (char*) malloc(strlen(szButtonTheme
) + 4);
525 strcpy(szNewTheme
, szButtonTheme
);
526 strcat(szNewTheme
, ".xpm");
528 fprintf(stdout
, "[%8ld] theme file '%s' not found, trying '%s'\n", currentTimeMillis(), szButtonTheme
, szNewTheme
);
530 /* check for absolute button theme pathname (with .xpm added) */
531 if (stat(szNewTheme
, &buf
) == 0) {
532 szButtonTheme
= szNewTheme
;
534 fprintf(stdout
, "[%8ld] initializing button theme '%s'\n", currentTimeMillis(), szButtonTheme
);
541 if (bCheckAgain
&& szInstallDir
!= NULL
) {
542 char* szNewTheme
= (char*) malloc(strlen(szInstallDir
) + strlen(szButtonTheme
) + 5);
543 strcpy(szNewTheme
, szInstallDir
);
544 if (szNewTheme
[strlen(szNewTheme
) - 1] != '/') {
545 strcat(szNewTheme
, "/");
547 strcat(szNewTheme
, szButtonTheme
);
548 if (stat(szNewTheme
, &buf
) == 0) {
550 szButtonTheme
= szNewTheme
;
552 fprintf(stdout
, "[%8ld] initializing button theme '%s'\n", currentTimeMillis(), szButtonTheme
);
555 strcat(szNewTheme
, ".xpm");
556 if (stat(szNewTheme
, &buf
) == 0) {
558 szButtonTheme
= szNewTheme
;
560 fprintf(stdout
, "[%8ld] initializing button theme '%s'\n", currentTimeMillis(), szButtonTheme
);
566 /* as a goody check the ~/.wmpager directory if it exists */
567 char* szHome
= (char*) getenv("HOME");
569 /* one really shouldn't copy&paste but hey this is a q&d tool */
570 char* szNewTheme
= (char*) malloc(strlen(szHome
) + strlen(szButtonTheme
) + strlen(WMPAGER_USER_DIR
) + 5);
571 strcpy(szNewTheme
, szHome
);
572 if (szNewTheme
[strlen(szNewTheme
) - 1] != '/') {
573 strcat(szNewTheme
, "/");
575 strcat(szNewTheme
, WMPAGER_USER_DIR
);
576 strcat(szNewTheme
, szButtonTheme
);
577 if (stat(szNewTheme
, &buf
) == 0) {
579 szButtonTheme
= szNewTheme
;
581 fprintf(stdout
, "[%8ld] initializing button theme '%s'\n", currentTimeMillis(), szButtonTheme
);
584 strcat(szNewTheme
, ".xpm");
585 if (stat(szNewTheme
, &buf
) == 0) {
587 szButtonTheme
= szNewTheme
;
589 fprintf(stdout
, "[%8ld] initializing button theme '%s'\n", currentTimeMillis(), szButtonTheme
);
597 display
, wRoot
, szButtonTheme
, &_pButtonTheme
, &_pButtonThemeMask
, &_attrButtonTheme
600 fprintf(stderr
, "%s: couldn't read button theme '%s'.\n", getApplicationName(), szButtonTheme
);
606 fprintf(stdout
, "[%8ld] initializing screen buffer\n", currentTimeMillis());
609 _attrWindow
.valuemask
|= (XpmReturnPixels
| XpmReturnExtensions
);
611 XpmCreatePixmapFromData(
612 display
, wRoot
, screen_xpm
, &_pWindow
, &_pWindowMask
, &_attrWindow
615 fprintf(stderr
, "%s: couldn't create screen buffer.\n", getApplicationName());
619 _gcWindow
= XCreateGC(_display
, _pWindow
, (GCForeground
| GCBackground
), &xgcWindow
);
621 fprintf(stderr
, "%s: couldn't create screen buffer graphics.\n", getApplicationName());
626 void redrawWindow () {
629 int w
= getButtonWidth();
630 int h
= getButtonHeight();
631 for (i
= 0; i
< getButtonCount(); i
++) {
632 int x
, y
, xoff
, yoff
;
635 if (i
== getCurrentScreen()) {
639 getButtonLocation(i
, &x
, &y
);
640 XSetClipMask(_display
, _gcWindow
, _pWindowMask
);
641 XSetClipOrigin(_display
, _gcWindow
, 0, 0);
642 XCopyArea(_display
, _pButtonTheme
, _pWindow
, _gcWindow
, xoff
+ x
- 7, y
- 7, w
, h
, x
, y
);
643 XCopyArea(_display
, _pButtonTheme
, _pWindow
, _gcWindow
, xoff
, 0, w
, 1, x
, y
);
644 XCopyArea(_display
, _pButtonTheme
, _pWindow
, _gcWindow
, xoff
, 0, 1, h
, x
, y
);
645 XCopyArea(_display
, _pButtonTheme
, _pWindow
, _gcWindow
, xoff
+ 50, 0, 1, h
, x
+ w
- 1, y
);
646 XCopyArea(_display
, _pButtonTheme
, _pWindow
, _gcWindow
, xoff
, 50, w
, 1, x
, y
+ h
- 1);
647 XSetClipMask(_display
, _gcWindow
, _pButtonThemeMask
);
648 XSetClipOrigin(_display
, _gcWindow
, (x
+ (w
- 10) / 2) - i
* 10, -51 - yoff
+ y
+ (h
- 10) / 2);
649 XCopyArea(_display
, _pButtonTheme
, _pWindow
, _gcWindow
, i
* 10, 51 + yoff
, 10, 10, x
+ (w
- 10) / 2, y
+ (h
- 10) / 2);
651 while (XCheckTypedWindowEvent(_display
, _wMain
, Expose
, &event
));
652 XCopyArea(_display
, _pWindow
, _wMain
, _gcMain
, 0, 0, 64, 64, 0, 0);
653 while (XCheckTypedWindowEvent(_display
, _wIcon
, Expose
, &event
));
654 XCopyArea(_display
, _pWindow
, _wIcon
, _gcMain
, 0, 0, 64, 64, 0, 0);
657 void getWindowOrigin (Window w
, int* nX
, int* nY
) {
658 Window wWindow
, wParent
, wRoot
;
660 unsigned int nChildren
;
661 unsigned int ww
, wh
, wb
, wd
;
667 if (!XQueryTree(getDisplay(), wParent
, &wRoot
, &wParent
, &wChildren
, &nChildren
)) {
673 } while (wParent
!= wRoot
);
675 if (XGetGeometry(getDisplay(), wWindow
, &wRoot
, &wx
, &wy
, &ww
, &wh
, &wb
, &wd
)) {
690 Display
* display
= getDisplay();
694 fprintf(stdout
, "[%8ld] starting event loop\n", currentTimeMillis());
697 while (XPending(display
)) {
698 XNextEvent(display
, &event
);
699 switch (event
.type
) {
701 if (event
.xexpose
.count
== 0) {
705 case ConfigureNotify
:
710 int nButton
= getButtonAt(event
.xbutton
.x
, event
.xbutton
.y
);
712 fprintf(stdout
, "[%8ld] button %d pressed\n", currentTimeMillis(), nButton
);
715 setCurrentScreen(nButton
);
721 if (strcmp(XA_WIN_WORKSPACE
, XGetAtomName(getDisplay(), event
.xproperty
.atom
)) == 0) {
722 setCurrentScreen(-1);
724 fprintf(stdout
, "[%8ld] new current workspace (%d= %s)\n",
725 currentTimeMillis(), getCurrentScreen(), getScreenName(getCurrentScreen()));
732 fprintf(stdout
, "[%8ld] quit application\n", currentTimeMillis());
748 static int _nButtons
;
749 static int _nButtonRows
, _nButtonColumns
;
750 static int _nButtonWidth
, _nButtonHeight
;
752 int getButtonCount () {
756 int getButtonRowCount () {
760 int getButtonColumnCount () {
761 return _nButtonColumns
;
764 int getButtonWidth () {
765 return _nButtonWidth
;
768 int getButtonHeight () {
769 return _nButtonHeight
;
772 int getButtonAt (int nLocationX
, int nLocationY
) {
773 int i
, nButtonX
, nButtonY
;
774 for (i
= 0; i
< _nButtons
; i
++) {
775 getButtonLocation(i
, &nButtonX
, &nButtonY
);
777 nLocationX
>= nButtonX
&& nLocationX
< nButtonX
+ _nButtonWidth
&&
778 nLocationY
>= nButtonY
&& nLocationY
< nButtonY
+ _nButtonHeight
786 void getButtonLocation (int nButton
, int* nLocationX
, int* nLocationY
) {
787 if (nButton
< 0 || nButton
> _nButtons
) {
788 *nLocationX
= *nLocationY
= 0;
790 *nLocationX
= *nLocationY
= 7;
791 while (nButton
>= _nButtonColumns
) {
792 *nLocationY
+= _nButtonHeight
+ 3;
793 nButton
-= _nButtonColumns
;
795 while (nButton
> 0) {
796 *nLocationX
+= _nButtonWidth
+ 3;
802 void initButtons (int nButtons
, int nColumns
, int nRows
) {
803 if (nButtons
!= -1) {
806 _nButtons
= getScreenCount();
808 /* only handle nine screens at most */
812 if (nColumns
== -1 || nRows
== -1) {
815 _nButtonRows
= _nButtonColumns
= 1;
824 _nButtonColumns
= _nButtonRows
= 2;
833 _nButtonColumns
= _nButtonRows
= 3;
837 _nButtonColumns
= nColumns
;
840 if (_nButtons
> _nButtonColumns
* _nButtonRows
) {
841 _nButtons
= _nButtonColumns
* _nButtonRows
;
844 fprintf(stdout
, "[%8ld] initializing buttons\n", currentTimeMillis());
845 fprintf(stdout
, "[%8ld] - %d workspace buttons\n", currentTimeMillis(), _nButtons
);
846 fprintf(stdout
, "[%8ld] - button layout %dx%d\n", currentTimeMillis(), _nButtonColumns
, _nButtonRows
);
849 if (_nButtonColumns
== 1) {
851 } else if (_nButtonColumns
== 2) {
857 if (_nButtonRows
== 1) {
859 } else if (_nButtonRows
== 2) {
871 static struct timeval _tStart
;
875 fprintf(stdout
, "[ ] initializing time\n");
877 gettimeofday(&_tStart
, NULL
);
880 long currentTimeMillis () {
882 struct timeval tElapsed
;
884 gettimeofday(&tNow
, NULL
);
886 if (_tStart
.tv_usec
> tNow
.tv_usec
) {
887 tNow
.tv_usec
+= 1000000;
890 tElapsed
.tv_sec
= tNow
.tv_sec
- _tStart
.tv_sec
;
891 tElapsed
.tv_usec
= tNow
.tv_usec
- _tStart
.tv_usec
;
892 return (tElapsed
.tv_sec
* 1000) + (tElapsed
.tv_usec
/ 1000);
899 static Atom _xaWinWorkspace
;
900 static Atom _xaWinWorkspaceNames
;
901 static int _nScreens
;
902 static char** _szScreenNames
;
903 static int _nLastScreen
;
905 int getScreenCount () {
909 char* getScreenName (int nScreen
) {
910 if (nScreen
< 0 || nScreen
>= _nScreens
) {
913 return _szScreenNames
[nScreen
];
916 void gotoScreen (int nWorkspace
) {
918 event
.type
= ClientMessage
;
919 event
.xclient
.type
= ClientMessage
;
920 event
.xclient
.window
= getRootWindow();
921 event
.xclient
.message_type
= _xaWinWorkspace
;
922 event
.xclient
.format
= 32;
923 event
.xclient
.data
.l
[0]= nWorkspace
;
924 event
.xclient
.data
.l
[1]= currentTimeMillis();
925 XSendEvent(getDisplay(), getRootWindow(), False
, SubstructureNotifyMask
, (XEvent
*) &event
);
928 int getCurrentScreen () {
932 void setCurrentScreen (int nCurrentScreen
) {
933 if (nCurrentScreen
== -1) {
934 long nScreen
= _nLastScreen
;
937 unsigned long nItems
, nBytesAfter
;
941 getDisplay(), getRootWindow(), _xaWinWorkspace
,
942 0, 8192, False
, XA_CARDINAL
, &xaType
, &nFormat
, &nItems
, &nBytesAfter
, &data
944 if ((nFormat
== 32) && (nItems
== 1) && (nBytesAfter
== 0)) {
945 nScreen
= *(long*) data
;
947 if (xaType
!= None
) {
950 _nLastScreen
= nScreen
;
952 _nLastScreen
= nCurrentScreen
;
956 void initScreens () {
960 fprintf(stdout
, "[%8ld] initializing window maker communication\n", currentTimeMillis());
962 _xaWinWorkspace
= XInternAtom(getDisplay(), XA_WIN_WORKSPACE
, False
);
963 _xaWinWorkspaceNames
= XInternAtom(getDisplay(), XA_WIN_WORKSPACE_NAMES
, False
);
964 XGetTextProperty(getDisplay(), getRootWindow(), &tp
, _xaWinWorkspaceNames
);
965 XTextPropertyToStringList(&tp
, &_szScreenNames
, &_nScreens
);
967 setCurrentScreen(-1);
968 if (_nLastScreen
== -1) {
971 "%s: couldn't determine current workspace.\n" \
972 "Make sure your WindowMaker has Gnome support enabled!\n",
979 fprintf(stdout
, "[%8ld] - %d worspaces found\n", currentTimeMillis(), getScreenCount());
980 for (i
= 0; i
< getScreenCount(); i
++) {
981 fprintf(stdout
, "[%8ld] - workspace %d: %s\n", currentTimeMillis(), i
, getScreenName(i
));
983 fprintf(stdout
, "[%8ld] - current workspace is %d (%s)\n", currentTimeMillis(),
984 getCurrentScreen(), getScreenName(getCurrentScreen()));