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"
31 #define XA_NET_NUMBER_OF_DESKTOPS "_NET_NUMBER_OF_DESKTOPS"
32 #define XA_NET_CURRENT_DESKTOP "_NET_CURRENT_DESKTOP"
33 #define XA_NET_DESKTOP_NAMES "_NET_DESKTOP_NAMES"
35 #define WMPAGER_ENV "WMPAGER"
36 #define WMPAGER_DEFAULT_INSTALL_DIR "/usr/local/share/wmpager/"
37 #define WMPAGER_USER_DIR ".wmpager/"
43 void usage (int bVerbose
);
45 void setVerbose (int bVerbose
);
48 void initApplicationName (char* szApplicationName
);
49 char* getApplicationName ();
51 void initDisplay (char* szDisplay
);
52 void destroyDisplay ();
53 Display
* getDisplay ();
55 Pixel
getWhitePixel ();
56 Pixel
getBlackPixel ();
57 int getDefaultScreen ();
58 int getDefaultDepth ();
59 void initWindow (int nArgc
, char** szArgv
);
60 void destroyWindow ();
61 GC
getWindowGraphics ();
62 GC
getMainGraphics ();
63 void initWindowMask (char* szInstallDir
, char* szButtonTheme
);
65 void getWindowOrigin (Window w
, int* nX
, int* nY
);
69 void initButtons (int nButtons
, int nColumns
, int nRows
);
70 int getButtonCount ();
71 int getButtonRowCount ();
72 int getButtonColumnCount ();
73 int getButtonWidth ();
74 int getButtonHeight ();
75 int getButtonAt (int nLocationX
, int nLocationY
);
76 void getButtonLocation (int nButton
, int* nLocationX
, int* nLocationY
);
79 long currentTimeMillis ();
82 int getScreenCount ();
83 char* getScreenName (int nScreen
);
84 int getCurrentScreen ();
85 void setCurrentScreen (int nCurrentScreen
);
86 void gotoScreen (int nWorkspace
);
92 int main (int nArgc
, char** szArgv
) {
93 char* szDisplay
= NULL
;
95 char* szInstallDir
= NULL
;
98 int nSizeX
= -1, nSizeY
= -1;
100 initApplicationName(szArgv
[0]);
101 /* we no longer use the WMPAGER environment variable
102 * szInstallDir= (char*) getenv(WMPAGER_ENV);
103 * instead we simply use a default installation directory
105 szInstallDir
= WMPAGER_DEFAULT_INSTALL_DIR
;
108 if (strcmp("-h", szArgv
[i
]) == 0 || strcmp("--help", szArgv
[i
]) == 0) {
110 } else if (strcmp("-v", szArgv
[i
]) == 0 || strcmp("--verbose", szArgv
[i
]) == 0) {
112 } else if (strcmp("-w", szArgv
[i
]) == 0 || strcmp("--workspaces", szArgv
[i
]) == 0) {
115 sscanf(szArgv
[i
], "%d", &nWorkspaces
);
116 if (nWorkspaces
<= 0 || nWorkspaces
> 9) {
117 fprintf(stderr
, "%s: illegal number of workspaces '%s' for option '%s' (has to be 1-9)\n\n", getApplicationName(), szArgv
[i
], szArgv
[i
-1]);
121 fprintf(stderr
, "%s: workspace count expected for '%s'\n\n", getApplicationName(), szArgv
[i
-1]);
124 } else if (strcmp("-s", szArgv
[i
]) == 0 || strcmp("--size", szArgv
[i
]) == 0) {
127 sscanf(szArgv
[i
], "%dx%d", &nSizeX
, &nSizeY
);
128 if (nSizeX
<= 0 || nSizeX
> 3 || nSizeY
<= 0 || nSizeY
> 3) {
129 fprintf(stderr
, "%s: illegal size '%s' for option '%s' (has to be 1x1 .. 3x3)\n\n", getApplicationName(), szArgv
[i
], szArgv
[i
-1]);
133 fprintf(stderr
, "%s: size argument expected for '%s'\n\n", getApplicationName(), szArgv
[i
-1]);
136 } else if (strcmp("-i", szArgv
[i
]) == 0 || strcmp("--installdir", szArgv
[i
]) == 0) {
140 szInstallDir
= szArgv
[i
];
141 if (stat(szInstallDir
, &buf
) != 0) {
142 fprintf(stderr
, "%s: cannot access installation directory '%s'\n\n", getApplicationName(), szArgv
[i
]);
146 fprintf(stderr
, "%s: display argument expected for '%s'\n\n", getApplicationName(), szArgv
[i
-1]);
149 } else if (strcmp("-d", szArgv
[i
]) == 0 || strcmp("--display", szArgv
[i
]) == 0) {
152 szDisplay
= szArgv
[i
];
154 fprintf(stderr
, "%s: display argument expected for '%s'\n\n", getApplicationName(), szArgv
[i
-1]);
157 } else if (strcmp("-t", szArgv
[i
]) == 0 || strcmp("--theme", szArgv
[i
]) == 0) {
160 szTheme
= strdup(szArgv
[i
]);
162 fprintf(stderr
, "%s: theme argument expected for '%s'\n\n", getApplicationName(), szArgv
[i
-1]);
166 fprintf(stderr
, "%s: unknown option '%s'\n\n", getApplicationName(), szArgv
[i
]);
171 setVerbose(bVerbose
);
173 char* szRealDisplay
= (szDisplay
== NULL
) ? (char*) getenv("DISPLAY") : szDisplay
;
174 if (szRealDisplay
== NULL
) {
175 szRealDisplay
= "localhost:0.0";
180 "[ ] startup options:\n" \
181 "[ ] - verbose= true\n" \
182 "[ ] - display= '%s'\n" \
183 "[ ] - installdir= '%s'\n" \
184 "[ ] - theme= '%s'\n" \
185 "[ ] - workspaces= '%d'\n" \
186 "[ ] - size= '%dx%d'\n",
188 szInstallDir
== NULL
? "<undefined>" : szInstallDir
,
189 szTheme
== NULL
? "<built-in>" : szTheme
,
195 initDisplay(szDisplay
);
196 initWindow(nArgc
, szArgv
);
198 initButtons(nWorkspaces
, nSizeX
, nSizeY
);
199 initWindowMask(szInstallDir
, szTheme
);
208 static int _bVerbose
;
210 void setVerbose (int bVerbose
) {
223 "usage: %s [options]\n\n" \
224 "where options include:\n" \
225 " -h --help display usage and version information\n" \
226 " -v --verbose verbose message output\n" \
227 " -d --display <name> the display to use (defaults to the\n" \
228 " 'DISPLAY' environment variable)\n" \
229 " -s --size <w>x<h> number of buttons (default depends on the\n" \
230 " number of workspaces you have, i.e. 2x2 for 4\n" \
231 " workspaces, 2x3 for 6, maximum is 3x3)\n" \
232 " -w --workspaces <count> number of workspace buttons to display\n" \
233 " (default is the number of workspaces you have,\n" \
235 " -t --theme <theme.xpm> the button theme to use, extension\n" \
236 " '.xpm' is optional, for more information about\n" \
237 " themes see docu (default is the built-in theme)\n" \
238 " -i --installdir <dir> specifies the installation directory location,\n" \
239 " this location is automatically searched for themes\n" \
240 " (defaults to the '/usr/local/share/wmpager/'\n" \
241 " and the user specific '~/.wmpager' directory)\n"
243 void usage (int bVerbose
) {
246 fprintf(stdout
, USAGE
, getApplicationName());
249 fprintf(stderr
, USAGE
, getApplicationName());
255 fprintf(stdout
, "%s %s\n\n", APPLICATION
, VERSION
);
262 static char* _szApplicationName
;
264 char* getApplicationName () {
265 return _szApplicationName
;
268 void initApplicationName (char* szApplicationName
) {
269 if (szApplicationName
== NULL
) {
270 _szApplicationName
= APPLICATION
;
272 _szApplicationName
= strdup(szApplicationName
);
280 static Display
* _display
;
282 Display
* getDisplay () {
286 void destroyDisplay () {
287 XCloseDisplay(getDisplay());
290 void initDisplay (char* szDisplay
) {
291 if (szDisplay
== NULL
&& ((char*) getenv("DISPLAY")) == NULL
) {
295 char* szRealDisplay
= (szDisplay
== NULL
) ? (char*) getenv("DISPLAY") : szDisplay
;
296 if (szRealDisplay
== NULL
) {
297 szRealDisplay
= "localhost:0.0";
299 fprintf(stdout
, "[%8ld] initializing display '%s'\n", currentTimeMillis(), szRealDisplay
);
301 _display
= XOpenDisplay(szDisplay
);
302 if (_display
== NULL
) {
305 "%s: couldn't open display '%s'.\n",
306 getApplicationName(),
307 (szDisplay
== NULL
) ? ((char*) getenv("DISPLAY")) : szDisplay
317 static int _nDefaultScreen
, _nDefaultDepth
;
318 static Window _wRoot
, _wMain
, _wIcon
;
319 static GC _gcMain
, _gcWindow
;
320 static XpmAttributes _attrButtonTheme
;
321 static Pixmap _pButtonTheme
, _pButtonThemeMask
;
322 static XpmAttributes _attrWindow
;
323 static Pixmap _pWindow
, _pWindowMask
;
324 static Pixel _pWhite
, _pBlack
;
326 Pixel
getWhitePixel () {
330 Pixel
getBlackPixel () {
334 int getDefaultScreen () {
335 return _nDefaultScreen
;
338 int getDefaultDepth () {
339 return _nDefaultDepth
;
342 Window
getRootWindow () {
346 Window
getMainWindow () {
350 Window
getIconWindow () {
354 GC
getMainGraphics () {
358 GC
getWindowGraphics () {
362 void initWindow (int nArgc
, char** szArgv
) {
363 char* szApplicationName
= getApplicationName();
364 Display
* display
= getDisplay();
365 XSizeHints
*xsizehints
;
367 XClassHint
* xclasshint
;
368 XTextProperty xtApplication
;
371 fprintf(stdout
, "[%8ld] initializing application window\n", currentTimeMillis());
374 _nDefaultScreen
= DefaultScreen(display
);
375 _nDefaultDepth
= DefaultDepth(display
, _nDefaultScreen
);
376 _wRoot
= RootWindow(display
, _nDefaultScreen
);
378 XSelectInput(display
, _wRoot
, PropertyChangeMask
);
380 _pWhite
= WhitePixel(display
, _nDefaultScreen
);
381 _pBlack
= BlackPixel(display
, _nDefaultScreen
);
383 xsizehints
= XAllocSizeHints();
384 xsizehints
->flags
= USSize
| USPosition
;
385 xsizehints
->width
= xsizehints
->height
= 64;
387 _wMain
= XCreateSimpleWindow(display
, _wRoot
, 0, 0, 64, 64, 5, _pWhite
, _pBlack
);
389 fprintf(stderr
, "Cannot create main window.\n");
393 _wIcon
= XCreateSimpleWindow(display
, _wMain
, 0, 0, 64, 64, 5, _pWhite
, _pBlack
);
395 fprintf(stderr
, "Cannot create icon window.\n");
399 xwmhints
= XAllocWMHints();
400 xwmhints
->flags
= WindowGroupHint
| IconWindowHint
| StateHint
;
401 xwmhints
->icon_window
= _wIcon
;
402 xwmhints
->window_group
= _wMain
;
403 xwmhints
->initial_state
= WithdrawnState
;
404 XSetWMHints(display
, _wMain
, xwmhints
);
406 xclasshint
= XAllocClassHint();
407 xclasshint
->res_name
= APPLICATION
;
408 xclasshint
->res_class
= APPLICATION
;
409 XSetClassHint(display
, _wMain
, xclasshint
);
411 XSetWMNormalHints(display
, _wMain
, xsizehints
);
417 if (XStringListToTextProperty(&szApplicationName
, 1, &xtApplication
) == 0) {
418 fprintf(stderr
, "Cannot set window title.\n");
421 XSetWMName(display
, _wMain
, &xtApplication
);
422 XFree(xtApplication
.value
);
424 _gcMain
= XCreateGC(display
, _wMain
, 0L, NULL
);
425 if (_gcMain
== NULL
) {
426 fprintf(stderr
, "Cannot create graphics context.\n");
430 XSelectInput(display
, _wMain
, ExposureMask
| ButtonPressMask
| PointerMotionMask
| StructureNotifyMask
| LeaveWindowMask
);
431 XSelectInput(display
, _wIcon
, ExposureMask
| ButtonPressMask
| PointerMotionMask
| StructureNotifyMask
| LeaveWindowMask
);
433 XSetCommand(display
, _wMain
, szArgv
, nArgc
);
435 XMapWindow(display
, _wMain
);
438 void destroyWindow () {
439 XFreeGC(getDisplay(), getWindowGraphics());
440 XFreeGC(getDisplay(), getMainGraphics());
441 XDestroyWindow(getDisplay(), getMainWindow());
442 XDestroyWindow(getDisplay(), getIconWindow());
445 void initWindowMask (char* szInstallDir
, char* szButtonTheme
) {
446 Display
* display
= getDisplay();
448 Window wRoot
= getRootWindow();
449 Window wMain
= getMainWindow();
450 Window wIcon
= getIconWindow();
451 Pixmap pOpaque
, pTransparent
, pMask
;
452 char* mask
= (char*) malloc(512);
456 fprintf(stdout
, "[%8ld] initializing window mask\n", currentTimeMillis());
458 for (i
= 0; i
< 512; i
++) {
461 pTransparent
= XCreateBitmapFromData(display
, wRoot
, mask
, 64, 64);
462 if (pTransparent
== 0) {
463 fprintf(stderr
, "%s: couldn't create window mask (transparent).\n", getApplicationName());
466 pMask
= XCreateBitmapFromData(display
, wRoot
, mask
, 64, 64);
468 fprintf(stderr
, "%s: couldn't create window mask (mask buffer).\n", getApplicationName());
472 for (i
= 0; i
< 512; i
++) {
475 pOpaque
= XCreateBitmapFromData(display
, wRoot
, mask
, 64, 64);
477 fprintf(stderr
, "%s: couldn't create window mask (opaque).\n", getApplicationName());
481 gc
= XCreateGC(display
, pMask
, 0L, NULL
);
483 fprintf(stderr
, "%s: couldn't create window mask (mask graphics).\n", getApplicationName());
486 for (i
= 0; i
< getButtonCount(); i
++) {
487 int nButtonX
, nButtonY
;
488 getButtonLocation(i
, &nButtonX
, &nButtonY
);
489 XCopyArea(display
, pOpaque
, pMask
, gc
, nButtonX
, nButtonY
, getButtonWidth(), getButtonHeight(), nButtonX
, nButtonY
);
493 XFreePixmap(display
, pOpaque
);
494 XFreePixmap(display
, pTransparent
);
495 XFreeGC(display
, gc
);
497 XShapeCombineMask(display
, wMain
, ShapeBounding
, 0, 0, pMask
, ShapeSet
);
498 XShapeCombineMask(display
, wIcon
, ShapeBounding
, 0, 0, pMask
, ShapeSet
);
501 fprintf(stdout
, "[%8ld] initializing button theme '%s'\n", currentTimeMillis(),
502 szButtonTheme
== NULL
? "<built-in>" : szButtonTheme
);
505 _attrButtonTheme
.valuemask
|= (XpmReturnPixels
| XpmReturnExtensions
);
506 if (szButtonTheme
== NULL
) {
508 XpmCreatePixmapFromData(
509 display
, wRoot
, buttons_xpm
, &_pButtonTheme
, &_pButtonThemeMask
, &_attrButtonTheme
512 fprintf(stderr
, "%s: couldn't create button theme.\n", getApplicationName());
518 /* check for absolute button theme pathname */
519 if (stat(szButtonTheme
, &buf
) == -1) {
520 char* szNewTheme
= (char*) malloc(strlen(szButtonTheme
) + 5);
521 strcpy(szNewTheme
, szButtonTheme
);
522 strcat(szNewTheme
, ".xpm");
524 fprintf(stdout
, "[%8ld] theme file '%s' not found, trying '%s'\n", currentTimeMillis(), szButtonTheme
, szNewTheme
);
526 /* check for absolute button theme pathname (with .xpm added) */
527 if (stat(szNewTheme
, &buf
) == 0) {
529 szButtonTheme
= szNewTheme
;
531 fprintf(stdout
, "[%8ld] initializing button theme '%s'\n", currentTimeMillis(), szButtonTheme
);
538 if (bCheckAgain
&& szInstallDir
!= NULL
) {
539 char* szNewTheme
= (char*) malloc(strlen(szInstallDir
) + strlen(szButtonTheme
) + 6);
540 strcpy(szNewTheme
, szInstallDir
);
541 if (szNewTheme
[strlen(szNewTheme
) - 1] != '/') {
542 strcat(szNewTheme
, "/");
544 strcat(szNewTheme
, szButtonTheme
);
545 if (stat(szNewTheme
, &buf
) == 0) {
548 szButtonTheme
= szNewTheme
;
550 fprintf(stdout
, "[%8ld] initializing button theme '%s'\n", currentTimeMillis(), szButtonTheme
);
553 strcat(szNewTheme
, ".xpm");
554 if (stat(szNewTheme
, &buf
) == 0) {
557 szButtonTheme
= szNewTheme
;
559 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
) + 6);
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) {
581 szButtonTheme
= szNewTheme
;
583 fprintf(stdout
, "[%8ld] initializing button theme '%s'\n", currentTimeMillis(), szButtonTheme
);
586 strcat(szNewTheme
, ".xpm");
587 if (stat(szNewTheme
, &buf
) == 0) {
590 szButtonTheme
= szNewTheme
;
592 fprintf(stdout
, "[%8ld] initializing button theme '%s'\n", currentTimeMillis(), szButtonTheme
);
602 display
, wRoot
, szButtonTheme
, &_pButtonTheme
, &_pButtonThemeMask
, &_attrButtonTheme
605 fprintf(stderr
, "%s: couldn't read button theme '%s'.\n", getApplicationName(), szButtonTheme
);
613 fprintf(stdout
, "[%8ld] initializing screen buffer\n", currentTimeMillis());
616 _attrWindow
.valuemask
|= (XpmReturnPixels
| XpmReturnExtensions
);
618 XpmCreatePixmapFromData(
619 display
, wRoot
, screen_xpm
, &_pWindow
, &_pWindowMask
, &_attrWindow
622 fprintf(stderr
, "%s: couldn't create screen buffer.\n", getApplicationName());
626 _gcWindow
= XCreateGC(_display
, _pWindow
, 0L, NULL
);
627 if (_gcWindow
== NULL
) {
628 fprintf(stderr
, "%s: couldn't create screen buffer graphics.\n", getApplicationName());
633 void redrawWindow () {
636 int w
= getButtonWidth();
637 int h
= getButtonHeight();
638 for (i
= 0; i
< getButtonCount(); i
++) {
639 int x
, y
, xoff
, yoff
;
642 if (i
== getCurrentScreen()) {
646 getButtonLocation(i
, &x
, &y
);
647 XSetClipMask(_display
, _gcWindow
, _pWindowMask
);
648 XSetClipOrigin(_display
, _gcWindow
, 0, 0);
649 XCopyArea(_display
, _pButtonTheme
, _pWindow
, _gcWindow
, xoff
+ x
- 7, y
- 7, w
, h
, x
, y
);
650 XCopyArea(_display
, _pButtonTheme
, _pWindow
, _gcWindow
, xoff
, 0, w
, 1, x
, y
);
651 XCopyArea(_display
, _pButtonTheme
, _pWindow
, _gcWindow
, xoff
, 0, 1, h
, x
, y
);
652 XCopyArea(_display
, _pButtonTheme
, _pWindow
, _gcWindow
, xoff
+ 50, 0, 1, h
, x
+ w
- 1, y
);
653 XCopyArea(_display
, _pButtonTheme
, _pWindow
, _gcWindow
, xoff
, 50, w
, 1, x
, y
+ h
- 1);
654 XSetClipMask(_display
, _gcWindow
, _pButtonThemeMask
);
655 XSetClipOrigin(_display
, _gcWindow
, (x
+ (w
- 10) / 2) - i
* 10, -51 - yoff
+ y
+ (h
- 10) / 2);
656 XCopyArea(_display
, _pButtonTheme
, _pWindow
, _gcWindow
, i
* 10, 51 + yoff
, 10, 10, x
+ (w
- 10) / 2, y
+ (h
- 10) / 2);
658 while (XCheckTypedWindowEvent(_display
, _wMain
, Expose
, &event
));
659 XCopyArea(_display
, _pWindow
, _wMain
, _gcMain
, 0, 0, 64, 64, 0, 0);
660 while (XCheckTypedWindowEvent(_display
, _wIcon
, Expose
, &event
));
661 XCopyArea(_display
, _pWindow
, _wIcon
, _gcMain
, 0, 0, 64, 64, 0, 0);
664 void getWindowOrigin (Window w
, int* nX
, int* nY
) {
665 Window wWindow
, wParent
, wRoot
;
667 unsigned int nChildren
;
668 unsigned int ww
, wh
, wb
, wd
;
674 if (!XQueryTree(getDisplay(), wParent
, &wRoot
, &wParent
, &wChildren
, &nChildren
)) {
680 } while (wParent
!= wRoot
);
682 if (XGetGeometry(getDisplay(), wWindow
, &wRoot
, &wx
, &wy
, &ww
, &wh
, &wb
, &wd
)) {
697 Display
* display
= getDisplay();
702 fprintf(stdout
, "[%8ld] starting event loop\n", currentTimeMillis());
705 while (XPending(display
)) {
706 XNextEvent(display
, &event
);
707 switch (event
.type
) {
709 if (event
.xexpose
.count
== 0) {
713 case ConfigureNotify
:
718 int nButton
= getButtonAt(event
.xbutton
.x
, event
.xbutton
.y
);
720 fprintf(stdout
, "[%8ld] button %d pressed\n", currentTimeMillis(), nButton
);
723 setCurrentScreen(nButton
);
729 atom_name
= XGetAtomName(getDisplay(), event
.xproperty
.atom
);
730 if (atom_name
== NULL
)
732 if (strcmp(XA_NET_CURRENT_DESKTOP
, atom_name
) == 0) {
733 setCurrentScreen(-1);
735 fprintf(stdout
, "[%8ld] new current workspace (%d= %s)\n",
736 currentTimeMillis(), getCurrentScreen(), getScreenName(getCurrentScreen()));
744 fprintf(stdout
, "[%8ld] quit application\n", currentTimeMillis());
760 static int _nButtons
;
761 static int _nButtonRows
, _nButtonColumns
;
762 static int _nButtonWidth
, _nButtonHeight
;
764 int getButtonCount () {
768 int getButtonRowCount () {
772 int getButtonColumnCount () {
773 return _nButtonColumns
;
776 int getButtonWidth () {
777 return _nButtonWidth
;
780 int getButtonHeight () {
781 return _nButtonHeight
;
784 int getButtonAt (int nLocationX
, int nLocationY
) {
785 int i
, nButtonX
, nButtonY
;
786 for (i
= 0; i
< _nButtons
; i
++) {
787 getButtonLocation(i
, &nButtonX
, &nButtonY
);
789 nLocationX
>= nButtonX
&& nLocationX
< nButtonX
+ _nButtonWidth
&&
790 nLocationY
>= nButtonY
&& nLocationY
< nButtonY
+ _nButtonHeight
798 void getButtonLocation (int nButton
, int* nLocationX
, int* nLocationY
) {
799 if (nButton
< 0 || nButton
> _nButtons
) {
800 *nLocationX
= *nLocationY
= 0;
802 *nLocationX
= *nLocationY
= 7;
803 while (nButton
>= _nButtonColumns
) {
804 *nLocationY
+= _nButtonHeight
+ 3;
805 nButton
-= _nButtonColumns
;
807 while (nButton
> 0) {
808 *nLocationX
+= _nButtonWidth
+ 3;
814 void initButtons (int nButtons
, int nColumns
, int nRows
) {
815 if (nButtons
!= -1) {
818 _nButtons
= getScreenCount();
820 /* only handle nine screens at most */
824 if (nColumns
== -1 || nRows
== -1) {
827 _nButtonRows
= _nButtonColumns
= 1;
836 _nButtonColumns
= _nButtonRows
= 2;
845 _nButtonColumns
= _nButtonRows
= 3;
849 _nButtonColumns
= nColumns
;
852 if (_nButtons
> _nButtonColumns
* _nButtonRows
) {
853 _nButtons
= _nButtonColumns
* _nButtonRows
;
856 fprintf(stdout
, "[%8ld] initializing buttons\n", currentTimeMillis());
857 fprintf(stdout
, "[%8ld] - %d workspace buttons\n", currentTimeMillis(), _nButtons
);
858 fprintf(stdout
, "[%8ld] - button layout %dx%d\n", currentTimeMillis(), _nButtonColumns
, _nButtonRows
);
861 if (_nButtonColumns
== 1) {
863 } else if (_nButtonColumns
== 2) {
869 if (_nButtonRows
== 1) {
871 } else if (_nButtonRows
== 2) {
883 static struct timeval _tStart
;
887 fprintf(stdout
, "[ ] initializing time\n");
889 gettimeofday(&_tStart
, NULL
);
892 long currentTimeMillis () {
894 struct timeval tElapsed
;
896 gettimeofday(&tNow
, NULL
);
898 if (_tStart
.tv_usec
> tNow
.tv_usec
) {
899 tNow
.tv_usec
+= 1000000;
902 tElapsed
.tv_sec
= tNow
.tv_sec
- _tStart
.tv_sec
;
903 tElapsed
.tv_usec
= tNow
.tv_usec
- _tStart
.tv_usec
;
904 return (tElapsed
.tv_sec
* 1000) + (tElapsed
.tv_usec
/ 1000);
911 static Atom _xaNetNumberOfDesktops
;
912 static Atom _xaNetCurrentDesktop
;
913 static Atom _xaNetDesktopNames
;
914 static int _nScreens
;
915 static char** _szScreenNames
;
916 static int _nDesktopNames
;
917 static int _nLastScreen
;
919 int getScreenCount () {
923 char* getScreenName (int nScreen
) {
924 if (nScreen
< 0 || nScreen
>= _nDesktopNames
) {
927 return _szScreenNames
[nScreen
];
930 void gotoScreen (int nWorkspace
) {
932 event
.type
= ClientMessage
;
933 event
.xclient
.type
= ClientMessage
;
934 event
.xclient
.window
= getRootWindow();
935 event
.xclient
.message_type
= _xaNetCurrentDesktop
;
936 event
.xclient
.format
= 32;
937 event
.xclient
.data
.l
[0]= nWorkspace
;
938 event
.xclient
.data
.l
[1]= currentTimeMillis();
939 XSendEvent(getDisplay(), getRootWindow(), False
, SubstructureNotifyMask
, (XEvent
*) &event
);
942 int getCurrentScreen () {
946 void setCurrentScreen (int nCurrentScreen
) {
947 if (nCurrentScreen
== -1) {
948 long nScreen
= _nLastScreen
;
951 unsigned long nItems
, nBytesAfter
;
955 getDisplay(), getRootWindow(), _xaNetCurrentDesktop
,
956 0, 8192, False
, XA_CARDINAL
, &xaType
, &nFormat
, &nItems
, &nBytesAfter
, &data
958 if ((nFormat
== 32) && (nItems
== 1) && (nBytesAfter
== 0)) {
959 nScreen
= *(long*) data
;
962 _nLastScreen
= nScreen
;
964 _nLastScreen
= nCurrentScreen
;
968 void initScreens () {
972 unsigned long nItems
, nBytesAfter
;
976 fprintf(stdout
, "[%8ld] initializing window maker communication\n", currentTimeMillis());
978 _xaNetNumberOfDesktops
= XInternAtom(getDisplay(), XA_NET_NUMBER_OF_DESKTOPS
, False
);
979 _xaNetCurrentDesktop
= XInternAtom(getDisplay(), XA_NET_CURRENT_DESKTOP
, False
);
980 _xaNetDesktopNames
= XInternAtom(getDisplay(), XA_NET_DESKTOP_NAMES
, False
);
983 getDisplay(), getRootWindow(), _xaNetNumberOfDesktops
,
984 0, 8192, False
, XA_CARDINAL
, &xaType
, &nFormat
, &nItems
, &nBytesAfter
, &data
986 if ((nFormat
== 32) && (nItems
== 1) && (nBytesAfter
== 0)) {
987 _nScreens
= *(long*) data
;
991 XGetTextProperty(getDisplay(), getRootWindow(), &tp
, _xaNetDesktopNames
);
992 Xutf8TextPropertyToTextList(getDisplay(), &tp
, &_szScreenNames
, &_nDesktopNames
);
996 setCurrentScreen(-1);
997 if (_nLastScreen
== -1) {
1000 "%s: couldn't determine current workspace.\n" \
1001 "Make sure your WindowMaker has EWMH support enabled!\n",
1002 getApplicationName()
1004 setCurrentScreen(0);
1008 fprintf(stdout
, "[%8ld] - %d worspaces found\n", currentTimeMillis(), getScreenCount());
1009 for (i
= 0; i
< getScreenCount(); i
++) {
1010 fprintf(stdout
, "[%8ld] - workspace %d: %s\n", currentTimeMillis(), i
, getScreenName(i
));
1012 fprintf(stdout
, "[%8ld] - current workspace is %d (%s)\n", currentTimeMillis(),
1013 getCurrentScreen(), getScreenName(getCurrentScreen()));