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_NET_NUMBER_OF_DESKTOPS "_NET_NUMBER_OF_DESKTOPS"
34 #define XA_NET_CURRENT_DESKTOP "_NET_CURRENT_DESKTOP"
35 #define XA_NET_DESKTOP_NAMES "_NET_DESKTOP_NAMES"
37 #define WMPAGER_ENV "WMPAGER"
38 #define WMPAGER_DEFAULT_INSTALL_DIR "/usr/local/share/wmpager/"
39 #define WMPAGER_USER_DIR ".wmpager/"
45 void usage (int bVerbose
);
47 void setVerbose (int bVerbose
);
50 void initApplicationName (char* szApplicationName
);
51 char* getApplicationName ();
53 void initDisplay (char* szDisplay
);
54 void destroyDisplay ();
55 Display
* getDisplay ();
57 Pixel
getWhitePixel ();
58 Pixel
getBlackPixel ();
59 int getDefaultScreen ();
60 int getDefaultDepth ();
61 void initWindow (int nArgc
, char** szArgv
);
62 void destroyWindow ();
63 GC
getWindowGraphics ();
64 GC
getMainGraphics ();
65 void initWindowMask (char* szInstallDir
, char* szButtonTheme
);
67 void getWindowOrigin (Window w
, int* nX
, int* nY
);
71 void initButtons (int nButtons
, int nColumns
, int nRows
);
72 int getButtonCount ();
73 int getButtonRowCount ();
74 int getButtonColumnCount ();
75 int getButtonWidth ();
76 int getButtonHeight ();
77 int getButtonAt (int nLocationX
, int nLocationY
);
78 void getButtonLocation (int nButton
, int* nLocationX
, int* nLocationY
);
81 long currentTimeMillis ();
84 int getScreenCount ();
85 char* getScreenName (int nScreen
);
86 int getCurrentScreen ();
87 void setCurrentScreen (int nCurrentScreen
);
88 void gotoScreen (int nWorkspace
);
94 int main (int nArgc
, char** szArgv
) {
95 char* szDisplay
= NULL
;
97 char* szInstallDir
= NULL
;
100 int nSizeX
= -1, nSizeY
= -1;
102 initApplicationName(szArgv
[0]);
103 /* we no longer use the WMPAGER environment variable
104 * szInstallDir= (char*) getenv(WMPAGER_ENV);
105 * instead we simply use a default installation directory
107 szInstallDir
= WMPAGER_DEFAULT_INSTALL_DIR
;
110 if (strcmp("-h", szArgv
[i
]) == 0 || strcmp("--help", szArgv
[i
]) == 0) {
112 } else if (strcmp("-v", szArgv
[i
]) == 0 || strcmp("--verbose", szArgv
[i
]) == 0) {
114 } else if (strcmp("-w", szArgv
[i
]) == 0 || strcmp("--workspaces", szArgv
[i
]) == 0) {
117 sscanf(szArgv
[i
], "%d", &nWorkspaces
);
118 if (nWorkspaces
<= 0 || nWorkspaces
> 9) {
119 fprintf(stderr
, "%s: illegal number of workspaces '%s' for option '%s' (has to be 1-9)\n\n", getApplicationName(), szArgv
[i
], szArgv
[i
-1]);
123 fprintf(stderr
, "%s: workspace count expected for '%s'\n\n", getApplicationName(), szArgv
[i
-1]);
126 } else if (strcmp("-s", szArgv
[i
]) == 0 || strcmp("--size", szArgv
[i
]) == 0) {
129 sscanf(szArgv
[i
], "%dx%d", &nSizeX
, &nSizeY
);
130 if (nSizeX
<= 0 || nSizeX
> 3 || nSizeY
<= 0 || nSizeY
> 3) {
131 fprintf(stderr
, "%s: illegal size '%s' for option '%s' (has to be 1x1 .. 3x3)\n\n", getApplicationName(), szArgv
[i
], szArgv
[i
-1]);
135 fprintf(stderr
, "%s: size argument expected for '%s'\n\n", getApplicationName(), szArgv
[i
-1]);
138 } else if (strcmp("-i", szArgv
[i
]) == 0 || strcmp("--installdir", szArgv
[i
]) == 0) {
142 szInstallDir
= szArgv
[i
];
143 if (stat(szInstallDir
, &buf
) != 0) {
144 fprintf(stderr
, "%s: cannot access installation directory '%s'\n\n", getApplicationName(), szArgv
[i
]);
148 fprintf(stderr
, "%s: display argument expected for '%s'\n\n", getApplicationName(), szArgv
[i
-1]);
151 } else if (strcmp("-d", szArgv
[i
]) == 0 || strcmp("--display", szArgv
[i
]) == 0) {
154 szDisplay
= szArgv
[i
];
156 fprintf(stderr
, "%s: display argument expected for '%s'\n\n", getApplicationName(), szArgv
[i
-1]);
159 } else if (strcmp("-t", szArgv
[i
]) == 0 || strcmp("--theme", szArgv
[i
]) == 0) {
164 fprintf(stderr
, "%s: theme argument expected for '%s'\n\n", getApplicationName(), szArgv
[i
-1]);
168 fprintf(stderr
, "%s: unknown option '%s'\n\n", getApplicationName(), szArgv
[i
]);
173 setVerbose(bVerbose
);
175 char* szRealDisplay
= (szDisplay
== NULL
) ? (char*) getenv("DISPLAY") : szDisplay
;
176 if (szRealDisplay
== NULL
) {
177 szRealDisplay
= "localhost:0.0";
182 "[ ] startup options:\n" \
183 "[ ] - verbose= true\n" \
184 "[ ] - display= '%s'\n" \
185 "[ ] - installdir= '%s'\n" \
186 "[ ] - theme= '%s'\n" \
187 "[ ] - workspaces= '%d'\n" \
188 "[ ] - size= '%dx%d'\n",
190 szInstallDir
== NULL
? "<undefined>" : szInstallDir
,
191 szTheme
== NULL
? "<built-in>" : szTheme
,
197 initDisplay(szDisplay
);
198 initWindow(nArgc
, szArgv
);
200 initButtons(nWorkspaces
, nSizeX
, nSizeY
);
201 initWindowMask(szInstallDir
, szTheme
);
210 static int _bVerbose
;
212 void setVerbose (int bVerbose
) {
225 "usage: %s [options]\n\n" \
226 "where options include:\n" \
227 " -h --help display usage and version information\n" \
228 " -v --verbose verbose message output\n" \
229 " -d --display <name> the display to use (defaults to the\n" \
230 " 'DISPLAY' environment variable)\n" \
231 " -s --size <w>x<h> number of buttons (default depends on the\n" \
232 " number of workspaces you have, i.e. 2x2 for 4\n" \
233 " workspaces, 2x3 for 6, maximum is 3x3)\n" \
234 " -w --workspaces <count> number of workspace buttons to display\n" \
235 " (default is the number of workspaces you have,\n" \
237 " -t --theme <theme.xpm> the button theme to use, extension\n" \
238 " '.xpm' is optional, for more information about\n" \
239 " themes see docu (default is the built-in theme)\n" \
240 " -i --installdir <dir> specifies the installation directory location,\n" \
241 " this location is automatically searched for themes\n" \
242 " (defaults to the '/usr/local/share/wmpager/'\n" \
243 " and the user specific '~/.wmpager' directory)\n"
245 void usage (int bVerbose
) {
248 fprintf(stdout
, USAGE
, getApplicationName());
251 fprintf(stderr
, USAGE
, getApplicationName());
257 char* szRev
= strdup(BUILD_REV
);
258 char* szDate
= strdup(BUILD_DATE
);
260 szRev
[strlen(szRev
) - 2]= '\0';
262 szDate
[strlen(szDate
) - 2]= '\0';
263 fprintf(stdout
, "%s %s (build %s, %s)\n\n", APPLICATION
, VERSION
, szRev
, szDate
);
270 static char* _szApplicationName
;
272 char* getApplicationName () {
273 return _szApplicationName
;
276 void initApplicationName (char* szApplicationName
) {
277 if (szApplicationName
== NULL
) {
278 _szApplicationName
= APPLICATION
;
280 _szApplicationName
= strdup(szApplicationName
);
288 static Display
* _display
;
290 Display
* getDisplay () {
294 void destroyDisplay () {
295 XCloseDisplay(getDisplay());
298 void initDisplay (char* szDisplay
) {
299 if (szDisplay
== NULL
&& ((char*) getenv("DISPLAY")) == NULL
) {
303 char* szRealDisplay
= (szDisplay
== NULL
) ? (char*) getenv("DISPLAY") : szDisplay
;
304 if (szRealDisplay
== NULL
) {
305 szRealDisplay
= "localhost:0.0";
307 fprintf(stdout
, "[%8ld] initializing display '%s'\n", currentTimeMillis(), szRealDisplay
);
309 _display
= XOpenDisplay(szDisplay
);
310 if (_display
== NULL
) {
313 "%s: couldn't open display '%s'.\n",
314 getApplicationName(),
315 (szDisplay
== NULL
) ? ((char*) getenv("DISPLAY")) : szDisplay
325 static int _nDefaultScreen
, _nDefaultDepth
;
326 static Window _wRoot
, _wMain
, _wIcon
;
327 static GC _gcMain
, _gcWindow
;
328 static XpmAttributes _attrButtonTheme
;
329 static Pixmap _pButtonTheme
, _pButtonThemeMask
;
330 static XpmAttributes _attrWindow
;
331 static Pixmap _pWindow
, _pWindowMask
;
332 static Pixel _pWhite
, _pBlack
;
334 Pixel
getWhitePixel () {
338 Pixel
getBlackPixel () {
342 int getDefaultScreen () {
343 return _nDefaultScreen
;
346 int getDefaultDepth () {
347 return _nDefaultDepth
;
350 Window
getRootWindow () {
354 Window
getMainWindow () {
358 Window
getIconWindow () {
362 GC
getMainGraphics () {
366 GC
getWindowGraphics () {
370 void initWindow (int nArgc
, char** szArgv
) {
371 char* szApplicationName
= getApplicationName();
372 Display
* display
= getDisplay();
373 XSizeHints
*xsizehints
;
375 XClassHint
* xclasshint
;
376 XTextProperty
* xtApplication
;
380 fprintf(stdout
, "[%8ld] initializing application window\n", currentTimeMillis());
383 _nDefaultScreen
= DefaultScreen(display
);
384 _nDefaultDepth
= DefaultDepth(display
, _nDefaultScreen
);
385 _wRoot
= RootWindow(display
, _nDefaultScreen
);
387 XSelectInput(display
, _wRoot
, PropertyChangeMask
);
389 _pWhite
= WhitePixel(display
, _nDefaultScreen
);
390 _pBlack
= BlackPixel(display
, _nDefaultScreen
);
392 xsizehints
= XAllocSizeHints();
393 xsizehints
->flags
= USSize
| USPosition
;
394 xsizehints
->width
= xsizehints
->height
= 64;
396 _wMain
= XCreateSimpleWindow(display
, _wRoot
, 0, 0, 64, 64, 5, _pWhite
, _pBlack
);
398 fprintf(stderr
, "Cannot create main window.\n");
402 _wIcon
= XCreateSimpleWindow(display
, _wMain
, 0, 0, 64, 64, 5, _pWhite
, _pBlack
);
404 fprintf(stderr
, "Cannot create icon window.\n");
408 xwmhints
= XAllocWMHints();
409 xwmhints
->flags
= WindowGroupHint
| IconWindowHint
| StateHint
;
410 xwmhints
->icon_window
= _wIcon
;
411 xwmhints
->window_group
= _wMain
;
412 xwmhints
->initial_state
= WithdrawnState
;
413 XSetWMHints(display
, _wMain
, xwmhints
);
415 xclasshint
= XAllocClassHint();
416 xclasshint
->res_name
= APPLICATION
;
417 xclasshint
->res_class
= APPLICATION
;
418 XSetClassHint(display
, _wMain
, xclasshint
);
420 XSetWMNormalHints(display
, _wMain
, xsizehints
);
422 xtApplication
= (XTextProperty
*) malloc(sizeof(XTextProperty
));
423 if (XStringListToTextProperty(&szApplicationName
, 1, xtApplication
) == 0) {
424 fprintf(stderr
, "Cannot set window title.\n");
427 XSetWMName(display
, _wMain
, xtApplication
);
429 _gcMain
= XCreateGC(display
, _wMain
, (GCForeground
| GCBackground
), &xgcMain
);
430 if (_gcMain
== NULL
) {
431 fprintf(stderr
, "Cannot create graphics context.\n");
435 XSelectInput(display
, _wMain
, ExposureMask
| ButtonPressMask
| PointerMotionMask
| StructureNotifyMask
| LeaveWindowMask
);
436 XSelectInput(display
, _wIcon
, ExposureMask
| ButtonPressMask
| PointerMotionMask
| StructureNotifyMask
| LeaveWindowMask
);
438 XSetCommand(display
, _wMain
, szArgv
, nArgc
);
440 XMapWindow(display
, _wMain
);
443 void destroyWindow () {
444 XFreeGC(getDisplay(), getWindowGraphics());
445 XFreeGC(getDisplay(), getMainGraphics());
446 XDestroyWindow(getDisplay(), getMainWindow());
447 XDestroyWindow(getDisplay(), getIconWindow());
450 void initWindowMask (char* szInstallDir
, char* szButtonTheme
) {
451 Display
* display
= getDisplay();
453 Window wRoot
= getRootWindow();
454 Window wMain
= getMainWindow();
455 Window wIcon
= getIconWindow();
456 XGCValues xgc
, xgcWindow
;
457 Pixmap pOpaque
, pTransparent
, pMask
;
458 char* mask
= (char*) malloc(512);
462 fprintf(stdout
, "[%8ld] initializing window mask\n", currentTimeMillis());
464 for (i
= 0; i
< 512; i
++) {
467 pTransparent
= XCreateBitmapFromData(display
, wRoot
, mask
, 64, 64);
468 if (pTransparent
== 0) {
469 fprintf(stderr
, "%s: couldn't create window mask (transparent).\n", getApplicationName());
472 pMask
= XCreateBitmapFromData(display
, wRoot
, mask
, 64, 64);
474 fprintf(stderr
, "%s: couldn't create window mask (mask buffer).\n", getApplicationName());
478 for (i
= 0; i
< 512; i
++) {
481 pOpaque
= XCreateBitmapFromData(display
, wRoot
, mask
, 64, 64);
483 fprintf(stderr
, "%s: couldn't create window mask (opaque).\n", getApplicationName());
487 gc
= XCreateGC(display
, pMask
, (GCForeground
| GCBackground
), &xgc
);
489 fprintf(stderr
, "%s: couldn't create window mask (mask graphics).\n", getApplicationName());
492 for (i
= 0; i
< getButtonCount(); i
++) {
493 int nButtonX
, nButtonY
;
494 getButtonLocation(i
, &nButtonX
, &nButtonY
);
495 XCopyArea(display
, pOpaque
, pMask
, gc
, nButtonX
, nButtonY
, getButtonWidth(), getButtonHeight(), nButtonX
, nButtonY
);
498 XFreePixmap(display
, pOpaque
);
499 XFreePixmap(display
, pTransparent
);
500 XFreeGC(display
, gc
);
502 XShapeCombineMask(display
, wMain
, ShapeBounding
, 0, 0, pMask
, ShapeSet
);
503 XShapeCombineMask(display
, wIcon
, ShapeBounding
, 0, 0, pMask
, ShapeSet
);
506 fprintf(stdout
, "[%8ld] initializing button theme '%s'\n", currentTimeMillis(),
507 szButtonTheme
== NULL
? "<built-in>" : szButtonTheme
);
510 _attrButtonTheme
.valuemask
|= (XpmReturnPixels
| XpmReturnExtensions
);
511 if (szButtonTheme
== NULL
) {
513 XpmCreatePixmapFromData(
514 display
, wRoot
, buttons_xpm
, &_pButtonTheme
, &_pButtonThemeMask
, &_attrButtonTheme
517 fprintf(stderr
, "%s: couldn't create button theme.\n", getApplicationName());
523 /* check for absolute button theme pathname */
524 if (stat(szButtonTheme
, &buf
) == -1) {
525 char* szNewTheme
= (char*) malloc(strlen(szButtonTheme
) + 4);
526 strcpy(szNewTheme
, szButtonTheme
);
527 strcat(szNewTheme
, ".xpm");
529 fprintf(stdout
, "[%8ld] theme file '%s' not found, trying '%s'\n", currentTimeMillis(), szButtonTheme
, szNewTheme
);
531 /* check for absolute button theme pathname (with .xpm added) */
532 if (stat(szNewTheme
, &buf
) == 0) {
533 szButtonTheme
= szNewTheme
;
535 fprintf(stdout
, "[%8ld] initializing button theme '%s'\n", currentTimeMillis(), szButtonTheme
);
542 if (bCheckAgain
&& szInstallDir
!= NULL
) {
543 char* szNewTheme
= (char*) malloc(strlen(szInstallDir
) + strlen(szButtonTheme
) + 5);
544 strcpy(szNewTheme
, szInstallDir
);
545 if (szNewTheme
[strlen(szNewTheme
) - 1] != '/') {
546 strcat(szNewTheme
, "/");
548 strcat(szNewTheme
, szButtonTheme
);
549 if (stat(szNewTheme
, &buf
) == 0) {
551 szButtonTheme
= szNewTheme
;
553 fprintf(stdout
, "[%8ld] initializing button theme '%s'\n", currentTimeMillis(), szButtonTheme
);
556 strcat(szNewTheme
, ".xpm");
557 if (stat(szNewTheme
, &buf
) == 0) {
559 szButtonTheme
= szNewTheme
;
561 fprintf(stdout
, "[%8ld] initializing button theme '%s'\n", currentTimeMillis(), szButtonTheme
);
567 /* as a goody check the ~/.wmpager directory if it exists */
568 char* szHome
= (char*) getenv("HOME");
570 /* one really shouldn't copy&paste but hey this is a q&d tool */
571 char* szNewTheme
= (char*) malloc(strlen(szHome
) + strlen(szButtonTheme
) + strlen(WMPAGER_USER_DIR
) + 5);
572 strcpy(szNewTheme
, szHome
);
573 if (szNewTheme
[strlen(szNewTheme
) - 1] != '/') {
574 strcat(szNewTheme
, "/");
576 strcat(szNewTheme
, WMPAGER_USER_DIR
);
577 strcat(szNewTheme
, szButtonTheme
);
578 if (stat(szNewTheme
, &buf
) == 0) {
580 szButtonTheme
= szNewTheme
;
582 fprintf(stdout
, "[%8ld] initializing button theme '%s'\n", currentTimeMillis(), szButtonTheme
);
585 strcat(szNewTheme
, ".xpm");
586 if (stat(szNewTheme
, &buf
) == 0) {
588 szButtonTheme
= szNewTheme
;
590 fprintf(stdout
, "[%8ld] initializing button theme '%s'\n", currentTimeMillis(), szButtonTheme
);
598 display
, wRoot
, szButtonTheme
, &_pButtonTheme
, &_pButtonThemeMask
, &_attrButtonTheme
601 fprintf(stderr
, "%s: couldn't read button theme '%s'.\n", getApplicationName(), szButtonTheme
);
607 fprintf(stdout
, "[%8ld] initializing screen buffer\n", currentTimeMillis());
610 _attrWindow
.valuemask
|= (XpmReturnPixels
| XpmReturnExtensions
);
612 XpmCreatePixmapFromData(
613 display
, wRoot
, screen_xpm
, &_pWindow
, &_pWindowMask
, &_attrWindow
616 fprintf(stderr
, "%s: couldn't create screen buffer.\n", getApplicationName());
620 _gcWindow
= XCreateGC(_display
, _pWindow
, (GCForeground
| GCBackground
), &xgcWindow
);
622 fprintf(stderr
, "%s: couldn't create screen buffer graphics.\n", getApplicationName());
627 void redrawWindow () {
630 int w
= getButtonWidth();
631 int h
= getButtonHeight();
632 for (i
= 0; i
< getButtonCount(); i
++) {
633 int x
, y
, xoff
, yoff
;
636 if (i
== getCurrentScreen()) {
640 getButtonLocation(i
, &x
, &y
);
641 XSetClipMask(_display
, _gcWindow
, _pWindowMask
);
642 XSetClipOrigin(_display
, _gcWindow
, 0, 0);
643 XCopyArea(_display
, _pButtonTheme
, _pWindow
, _gcWindow
, xoff
+ x
- 7, y
- 7, w
, h
, x
, y
);
644 XCopyArea(_display
, _pButtonTheme
, _pWindow
, _gcWindow
, xoff
, 0, w
, 1, x
, y
);
645 XCopyArea(_display
, _pButtonTheme
, _pWindow
, _gcWindow
, xoff
, 0, 1, h
, x
, y
);
646 XCopyArea(_display
, _pButtonTheme
, _pWindow
, _gcWindow
, xoff
+ 50, 0, 1, h
, x
+ w
- 1, y
);
647 XCopyArea(_display
, _pButtonTheme
, _pWindow
, _gcWindow
, xoff
, 50, w
, 1, x
, y
+ h
- 1);
648 XSetClipMask(_display
, _gcWindow
, _pButtonThemeMask
);
649 XSetClipOrigin(_display
, _gcWindow
, (x
+ (w
- 10) / 2) - i
* 10, -51 - yoff
+ y
+ (h
- 10) / 2);
650 XCopyArea(_display
, _pButtonTheme
, _pWindow
, _gcWindow
, i
* 10, 51 + yoff
, 10, 10, x
+ (w
- 10) / 2, y
+ (h
- 10) / 2);
652 while (XCheckTypedWindowEvent(_display
, _wMain
, Expose
, &event
));
653 XCopyArea(_display
, _pWindow
, _wMain
, _gcMain
, 0, 0, 64, 64, 0, 0);
654 while (XCheckTypedWindowEvent(_display
, _wIcon
, Expose
, &event
));
655 XCopyArea(_display
, _pWindow
, _wIcon
, _gcMain
, 0, 0, 64, 64, 0, 0);
658 void getWindowOrigin (Window w
, int* nX
, int* nY
) {
659 Window wWindow
, wParent
, wRoot
;
661 unsigned int nChildren
;
662 unsigned int ww
, wh
, wb
, wd
;
668 if (!XQueryTree(getDisplay(), wParent
, &wRoot
, &wParent
, &wChildren
, &nChildren
)) {
674 } while (wParent
!= wRoot
);
676 if (XGetGeometry(getDisplay(), wWindow
, &wRoot
, &wx
, &wy
, &ww
, &wh
, &wb
, &wd
)) {
691 Display
* display
= getDisplay();
695 fprintf(stdout
, "[%8ld] starting event loop\n", currentTimeMillis());
698 while (XPending(display
)) {
699 XNextEvent(display
, &event
);
700 switch (event
.type
) {
702 if (event
.xexpose
.count
== 0) {
706 case ConfigureNotify
:
711 int nButton
= getButtonAt(event
.xbutton
.x
, event
.xbutton
.y
);
713 fprintf(stdout
, "[%8ld] button %d pressed\n", currentTimeMillis(), nButton
);
716 setCurrentScreen(nButton
);
722 if (strcmp(XA_NET_CURRENT_DESKTOP
, XGetAtomName(getDisplay(), event
.xproperty
.atom
)) == 0) {
723 setCurrentScreen(-1);
725 fprintf(stdout
, "[%8ld] new current workspace (%d= %s)\n",
726 currentTimeMillis(), getCurrentScreen(), getScreenName(getCurrentScreen()));
733 fprintf(stdout
, "[%8ld] quit application\n", currentTimeMillis());
749 static int _nButtons
;
750 static int _nButtonRows
, _nButtonColumns
;
751 static int _nButtonWidth
, _nButtonHeight
;
753 int getButtonCount () {
757 int getButtonRowCount () {
761 int getButtonColumnCount () {
762 return _nButtonColumns
;
765 int getButtonWidth () {
766 return _nButtonWidth
;
769 int getButtonHeight () {
770 return _nButtonHeight
;
773 int getButtonAt (int nLocationX
, int nLocationY
) {
774 int i
, nButtonX
, nButtonY
;
775 for (i
= 0; i
< _nButtons
; i
++) {
776 getButtonLocation(i
, &nButtonX
, &nButtonY
);
778 nLocationX
>= nButtonX
&& nLocationX
< nButtonX
+ _nButtonWidth
&&
779 nLocationY
>= nButtonY
&& nLocationY
< nButtonY
+ _nButtonHeight
787 void getButtonLocation (int nButton
, int* nLocationX
, int* nLocationY
) {
788 if (nButton
< 0 || nButton
> _nButtons
) {
789 *nLocationX
= *nLocationY
= 0;
791 *nLocationX
= *nLocationY
= 7;
792 while (nButton
>= _nButtonColumns
) {
793 *nLocationY
+= _nButtonHeight
+ 3;
794 nButton
-= _nButtonColumns
;
796 while (nButton
> 0) {
797 *nLocationX
+= _nButtonWidth
+ 3;
803 void initButtons (int nButtons
, int nColumns
, int nRows
) {
804 if (nButtons
!= -1) {
807 _nButtons
= getScreenCount();
809 /* only handle nine screens at most */
813 if (nColumns
== -1 || nRows
== -1) {
816 _nButtonRows
= _nButtonColumns
= 1;
825 _nButtonColumns
= _nButtonRows
= 2;
834 _nButtonColumns
= _nButtonRows
= 3;
838 _nButtonColumns
= nColumns
;
841 if (_nButtons
> _nButtonColumns
* _nButtonRows
) {
842 _nButtons
= _nButtonColumns
* _nButtonRows
;
845 fprintf(stdout
, "[%8ld] initializing buttons\n", currentTimeMillis());
846 fprintf(stdout
, "[%8ld] - %d workspace buttons\n", currentTimeMillis(), _nButtons
);
847 fprintf(stdout
, "[%8ld] - button layout %dx%d\n", currentTimeMillis(), _nButtonColumns
, _nButtonRows
);
850 if (_nButtonColumns
== 1) {
852 } else if (_nButtonColumns
== 2) {
858 if (_nButtonRows
== 1) {
860 } else if (_nButtonRows
== 2) {
872 static struct timeval _tStart
;
876 fprintf(stdout
, "[ ] initializing time\n");
878 gettimeofday(&_tStart
, NULL
);
881 long currentTimeMillis () {
883 struct timeval tElapsed
;
885 gettimeofday(&tNow
, NULL
);
887 if (_tStart
.tv_usec
> tNow
.tv_usec
) {
888 tNow
.tv_usec
+= 1000000;
891 tElapsed
.tv_sec
= tNow
.tv_sec
- _tStart
.tv_sec
;
892 tElapsed
.tv_usec
= tNow
.tv_usec
- _tStart
.tv_usec
;
893 return (tElapsed
.tv_sec
* 1000) + (tElapsed
.tv_usec
/ 1000);
900 static Atom _xaNetNumberOfDesktops
;
901 static Atom _xaNetCurrentDesktop
;
902 static Atom _xaNetDesktopNames
;
903 static int _nScreens
;
904 static char** _szScreenNames
;
905 static int _nDesktopNames
;
906 static int _nLastScreen
;
908 int getScreenCount () {
912 char* getScreenName (int nScreen
) {
913 if (nScreen
< 0 || nScreen
>= _nDesktopNames
) {
916 return _szScreenNames
[nScreen
];
919 void gotoScreen (int nWorkspace
) {
921 event
.type
= ClientMessage
;
922 event
.xclient
.type
= ClientMessage
;
923 event
.xclient
.window
= getRootWindow();
924 event
.xclient
.message_type
= _xaNetCurrentDesktop
;
925 event
.xclient
.format
= 32;
926 event
.xclient
.data
.l
[0]= nWorkspace
;
927 event
.xclient
.data
.l
[1]= currentTimeMillis();
928 XSendEvent(getDisplay(), getRootWindow(), False
, SubstructureNotifyMask
, (XEvent
*) &event
);
931 int getCurrentScreen () {
935 void setCurrentScreen (int nCurrentScreen
) {
936 if (nCurrentScreen
== -1) {
937 long nScreen
= _nLastScreen
;
940 unsigned long nItems
, nBytesAfter
;
944 getDisplay(), getRootWindow(), _xaNetCurrentDesktop
,
945 0, 8192, False
, XA_CARDINAL
, &xaType
, &nFormat
, &nItems
, &nBytesAfter
, &data
947 if ((nFormat
== 32) && (nItems
== 1) && (nBytesAfter
== 0)) {
948 nScreen
= *(long*) data
;
950 if (xaType
!= None
) {
953 _nLastScreen
= nScreen
;
955 _nLastScreen
= nCurrentScreen
;
959 void initScreens () {
963 unsigned long nItems
, nBytesAfter
;
967 fprintf(stdout
, "[%8ld] initializing window maker communication\n", currentTimeMillis());
969 _xaNetNumberOfDesktops
= XInternAtom(getDisplay(), XA_NET_NUMBER_OF_DESKTOPS
, False
);
970 _xaNetCurrentDesktop
= XInternAtom(getDisplay(), XA_NET_CURRENT_DESKTOP
, False
);
971 _xaNetDesktopNames
= XInternAtom(getDisplay(), XA_NET_DESKTOP_NAMES
, False
);
974 getDisplay(), getRootWindow(), _xaNetNumberOfDesktops
,
975 0, 8192, False
, XA_CARDINAL
, &xaType
, &nFormat
, &nItems
, &nBytesAfter
, &data
977 if ((nFormat
== 32) && (nItems
== 1) && (nBytesAfter
== 0)) {
978 _nScreens
= *(long*) data
;
980 if (xaType
!= None
) {
984 XGetTextProperty(getDisplay(), getRootWindow(), &tp
, _xaNetDesktopNames
);
985 Xutf8TextPropertyToTextList(getDisplay(), &tp
, &_szScreenNames
, &_nDesktopNames
);
988 setCurrentScreen(-1);
989 if (_nLastScreen
== -1) {
992 "%s: couldn't determine current workspace.\n" \
993 "Make sure your WindowMaker has EWMH support enabled!\n",
1000 fprintf(stdout
, "[%8ld] - %d worspaces found\n", currentTimeMillis(), getScreenCount());
1001 for (i
= 0; i
< getScreenCount(); i
++) {
1002 fprintf(stdout
, "[%8ld] - workspace %d: %s\n", currentTimeMillis(), i
, getScreenName(i
));
1004 fprintf(stdout
, "[%8ld] - current workspace is %d (%s)\n", currentTimeMillis(),
1005 getCurrentScreen(), getScreenName(getCurrentScreen()));