static char *rcsid_wmsubs_c
= "$Header: xnwm.c,v 10.6 86/11/19 19:31:32 jg Rel $";
#define default_frame_width 5
#define default_mask MetaMask
#define default_menu_font "8x13"
#define default_size_font "8x13"
#define default_icon_font "8x13"
#define default_iconify_delta 5
/* Default button assignments; the numbers are indices into the
#define unassigned_button -1
/* Convert 0,1,2 into XRight(Middle,Left)Mask */
#define Button(i) (1 << (8 + (i)))
#include "buttons.raster"
typedef int (*ptrToFunc
) ();
int Raise(), Lower(), Move(), Resize(), IconifyOrDeIconify(),
Select(), Circulate(), Assign(), Unassigned();
char *label
[] = {"Select", "Raise", "Move", "(De)Iconify",
"Lower", "Resize", "Circulate", "Assign", ""};
ptrToFunc menuOp
[] = {Select
, Raise
, Move
, IconifyOrDeIconify
,
Lower
, Resize
, Circulate
, Assign
};
int needsWindow
[] = {TRUE
, TRUE
, TRUE
, TRUE
,
TRUE
, TRUE
, FALSE
, TRUE
};
int canDoToMenu
[] = {FALSE
, TRUE
, TRUE
, FALSE
,
TRUE
, FALSE
, TRUE
, TRUE
};
/* "item" needs an extra entry at the end */
Window item
[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
int buttonFunc
[3] = {default_right
, default_middle
, default_left
};
int itemcount
, itemWidth
, itemHeight
;
int menuWidth
, menuHeight
, menuX
, menuY
;
char code
[] = "srmilzc"; /* button assignment codes for command line */
int skinny
= FALSE
, twoRows
= FALSE
, vertical
= FALSE
;
int savex
, savey
; /* Where and what the popup menu obscures */
Pixmap menuImage
= 0; /* What the popup menu looks like */
int popupSaved
= FALSE
; /* True if a popup image is saved */
int reverse
; /* whether to reverse the normal colors */
int buttonGXfunc
; /* function to put up the button picture */
SetUpEverything(argc
, argv
);
/* If it's a ButtonReleased ignore; it's just left
over from some old click */
if (button
.type
== ButtonReleased
) continue;
InterpretLocatorW(RootWindow
, &w
, button
.location
);
/* If in background, raise menu or move back if just raised.
If using popup windows, map the popup window. Only do this
as long as the button is not bound to Select */
if (w
== 0 && NonSelect(&button
)) {
if (popup
) MapPopup(button
.location
);
if (raisedMenu
) XMoveWindow(menu
, menuX
, menuY
);
} else raisedMenu
= FALSE
;
/* If in menu, do appropriate function */
ProcessMenuFunction(&button
);
/* Otherwise do preassigned button function */
DoButtonFunc(&button
, w
);
SetUpEverything(argc
, argv
)
char *mfname
= default_menu_font
; /* font to use */
char *sfname
= default_size_font
; /* font to use */
char *ifname
= default_icon_font
; /* font to use */
char display
[256]; /* display to use */
frameWidth
= default_frame_width
;
iconifyDelta
= default_iconify_delta
;
GetDefaults(argv
[0], &mfname
, &sfname
, &ifname
, &location
);
ProcessArgs(argc
, argv
, display
, &mfname
, &sfname
, &ifname
, &location
);
SetUpFonts(mfname
, sfname
, ifname
);
GetDefaults(progname
, mfname
, sfname
, ifname
, location
)
char **mfname
, **sfname
, **ifname
, **location
;
if ((option
= XGetDefault(progname
,"MenuFont")) != NULL
) {
if ((option
= XGetDefault(progname
,"SizeFont")) != NULL
) {
if ((option
= XGetDefault(progname
,"IconFont")) != NULL
) {
if ((option
= XGetDefault(progname
,"ReverseVideo")) != NULL
) {
if (strcmp(option
, "on") == 0) reverse
= TRUE
;
if ((option
= XGetDefault(progname
,"FrameWidth")) != NULL
) {
frameWidth
= atoi(option
);
if ((option
= XGetDefault(progname
,"IconifyDelta")) != NULL
) {
iconifyDelta
= atoi(option
);
if ((option
= XGetDefault(progname
,"MenuFormat")) != NULL
) {
if (index(option
, 't') != NULL
) skinny
= TRUE
;
if (index(option
, '2') != NULL
) twoRows
= skinny
= TRUE
;
if (index(option
, 'v') != NULL
) vertical
= skinny
= TRUE
;
if ((option
= XGetDefault(progname
,"Freeze")) != NULL
) {
if (strcmp(option
, "off") == 0) freeze
= FALSE
;
if ((option
= XGetDefault(progname
,"KeyCombination")) != NULL
) {
if (index(option
, 'c') != NULL
) newmask
|= ControlMask
;
if (index(option
, 's') != NULL
) newmask
|= ShiftMask
;
if (index(option
, 'm') != NULL
) newmask
|= MetaMask
;
if (index(option
, 'l') != NULL
) newmask
|= ShiftLockMask
;
if (index(option
, 'n') != NULL
) mask
= 0;
else if (newmask
) mask
= newmask
;
if ((option
= XGetDefault(progname
,"LeftButton")) != NULL
) {
AssignButton(LeftButton
, option
[0]);
if ((option
= XGetDefault(progname
,"MiddleButton")) != NULL
) {
AssignButton(MiddleButton
, option
[0]);
if ((option
= XGetDefault(progname
,"RightButton")) != NULL
) {
AssignButton(RightButton
, option
[0]);
if ((option
= XGetDefault(progname
,"Geometry")) != NULL
) {
ProcessArgs(argc
, argv
, display
, mfname
, sfname
, ifname
, location
)
char **mfname
, **sfname
, **ifname
, **location
;
int i
, newmask
= 0, none
= FALSE
;
for (i
= 1; i
< argc
; i
++) {
if (*arg
== '\0') mask
= 0;
newmask
|= ShiftLockMask
;
vertical
= skinny
= TRUE
;
vertical
= twoRows
= FALSE
;
if (newmask
) mask
= newmask
;
frameWidth
= atoi(arg
+1);
if (frameWidth
< 0 || frameWidth
> 100) {
iconifyDelta
= atoi(arg
+1);
AssignButton(LeftButton
, arg
[2]);
AssignButton(MiddleButton
, arg
[2]);
AssignButton(RightButton
, arg
[2]);
} else if (arg
[0] == 'f' && arg
[2] == '=') {
} else strcpy(display
, arg
);
if (buttonFunc
[RightButton
] == popup_button
||
buttonFunc
[MiddleButton
] == popup_button
||
buttonFunc
[LeftButton
] == popup_button
) {
popup
= vertical
= skinny
= TRUE
;
buttonFunc
[which
] = unassigned_button
;
buttonFunc
[which
] = popup_button
;
} else buttonFunc
[which
] = ch
- code
;
puts("Usage: xnwm {-csmln} {-f} {-r} {-2vt} {@[framewidth]}");
puts(" {%[iconifyDelta]} {=[{+-}xoff[{+-}yoff]]}");
puts(" {l={srmilzcp}} {m={srmilzcp}} {r={srmilzcp}}");
puts(" {fm=menu_font} {fs=size_font} {fi=icon_font}");
puts(" {[host]:vs}"); /* whew */
if (XOpenDisplay(display
) == NULL
) {
fprintf(stderr
, "%s: Can't open display '%s'\n",
"xnwm" , XDisplayName(display
));
QueryWindow(RootWindow
, &winfo
);
screen_height
= winfo
.height
;
screen_width
= winfo
.width
;
ButtonPressed
| ButtonReleased
| UnmapWindow
| FocusChange
);
wmCursor
= XCreateCursor(nwm_width
, nwm_height
,
(caddr_t
) nwm_bits
, (caddr_t
) NULL
,
Error("Couldn't store wmCursor in StoreCursors");
static short gray_bits
[] = {
0xaaaa, 0x5555, 0xaaaa, 0x5555,
0xaaaa, 0x5555, 0xaaaa, 0x5555,
0xaaaa, 0x5555, 0xaaaa, 0x5555,
0xaaaa, 0x5555, 0xaaaa, 0x5555
buttonPixmap
[RightButton
] =
MakePixmap(button_width
, button_height
,
(caddr_t
) rbutton_bits
, bgColor
, fgColor
);
buttonPixmap
[MiddleButton
] =
MakePixmap(button_width
, button_height
,
(caddr_t
) mbutton_bits
, bgColor
, fgColor
);
buttonPixmap
[LeftButton
] =
MakePixmap(button_width
, button_height
,
(caddr_t
) lbutton_bits
, bgColor
, fgColor
);
gray
= MakePixmap(16, 16,
(caddr_t
) gray_bits
, bgColor
, fgColor
);
Pixmap
MakePixmap(width
, height
, bits
, fg
, bg
)
b
= XStoreBitmap(width
, height
, bits
);
if (b
== NULL
) Error("Couldn't store bitmap in MakePixmap");
p
= XMakePixmap (b
, fg
, bg
);
if (p
== NULL
) Error("Couldn't make pixmap in MakePixmap");
SetUpFonts(mfname
, sfname
, ifname
)
char *mfname
, *sfname
, *ifname
;
menufont
= XGetFont(mfname
);
if (menufont
== NULL
) Error("Couldn't store menu font in SetUpFont");
sizefont
= XGetFont(sfname
);
if (sizefont
== NULL
) Error("Couldn't store size font in SetUpFont");
iconfont
= XGetFont(ifname
);
if (iconfont
== NULL
) Error("Couldn't store icon font in SetUpFont");
int width
= 0, textwidth
;
while (label
[i
][0] != '\0') {
textwidth
= XQueryWidth(label
[i
], menufont
);
Error("Couldn't query string width in SetUpMenu");
if (textwidth
> width
) width
= textwidth
;
itemWidth
= 1 + 3 + width
+ 3 + button_width
+ 3 + 1;
} else itemWidth
= screen_width
/ itemcount
;
menuHeight
= itemcount
* itemHeight
;
menuWidth
= itemWidth
* ((itemcount
+1) >> 1);
menuHeight
= itemHeight
* 2;
menuWidth
= itemWidth
* itemcount
;
if (!popup
&& *location
!= '\0') {
/* Interpret the location string */
InterpLocation(location
, &x
, &y
, &xSign
, &ySign
);
if (xSign
== '+') menuX
= x
;
else menuX
= screen_width
- x
- menuWidth
;
if (ySign
== '+') menuY
= y
;
else menuY
= screen_height
- y
- menuHeight
;
menu
= XCreateWindow(RootWindow
, menuX
, menuY
, menuWidth
, menuHeight
,
if (menu
== NULL
) Error ("Couldn't open menu in SetUpMenu");
XStoreName(menu
, "xnwm menu");
XDefineCursor(menu
, wmCursor
);
if (popup
) XSelectInput(menu
, LeaveWindow
);
else XSelectInput(menu
, ExposeWindow
);
for (i
= 0; i
< itemcount
; i
++) {
if (twoRows
&& i
== (itemcount
+1) >> 1) {
item
[i
] = XCreateWindow (menu
, x
, y
, itemWidth
, itemHeight
, 1,
if (item
[i
] == NULL
) Error ("Couldn't open item in SetUpMenu");
if (vertical
) y
+= itemHeight
;
menuWidth
+= 2; /* Consider the border in from now on */
/* Don't draw anything; the expose event will cause that */
InterpLocation(location
, x
, y
, xSign
, ySign
)
while(*location
>= '0' && *location
<= '9') {
*x
= 10 * *x
+ (*location
++ - '0');
while(*location
>= '0' && *location
<= '9') {
*y
= 10 * *y
+ (*location
++ - '0');
if (*location
!= '\0') Syntax();
for (i
= 0; i
< 3; i
++) {
if (buttonFunc
[i
] != unassigned_button
) {
status
= XGrabButton(RootWindow
, wmCursor
,
ButtonPressed
|ButtonReleased
);
Error("Couldn't grab button in GrabButtons");
ProcessMenuFunction(button
)
InterpretLocatorW(menu
, &w
, button
->location
);
while (item
[i
] != NULL
&& item
[i
] != w
) i
++;
DoOperation(i
, button
->detail
);
/* First wait for the upbutton; if it doesn't occur or
occurs in a different window abort */
InterpretLocatorW(menu
, &w
, newbutton
.location
);
if (!MatchUp(newbutton
, which
) || w
!= item
[i
]) return;
/* If the function needs a window, get one */
status
= XGrabMouse(RootWindow
, wmCursor
,
ButtonPressed
| ButtonReleased
);
if (status
== NULL
) Error ("Couldn't grab mouse in DoOperation");
/* This should be the same button as was pushed to select
if (!MatchDown(newbutton
, which
)) {
InterpretLocatorW(RootWindow
, &w
, newbutton
.location
);
if (w
== 0) w
= RootWindow
;
/* Now call the appropriate function */
if (canDoToMenu
[i
] || w
!= menu
) {
(*menuOp
[i
])(which
, newbutton
.location
, w
, &winfo
);
if (needsWindow
[i
]) XUngrabMouse();
/* Returns whether or not the button is bound to Select */
int which
= button
->detail
& 0xff; /* 0, 1, or 2 */
int func
= buttonFunc
[which
];
return (func
< 0 || menuOp
[func
] != Select
);
int which
= button
->detail
& 0xff; /* 0, 1, or 2 */
register int func
= buttonFunc
[which
];
if (func
== unassigned_button
) {
/* popup_button signifies the button to map the popup window */
if (func
== popup_button
) {
MapPopup(button
->location
);
if (w
== 0) w
= RootWindow
;
status
= XGrabMouse(RootWindow
, wmCursor
,
ButtonPressed
|ButtonReleased
);
if (status
== 0) Error ("Couldn't grab mouse in DoButtonFunc");
(*menuOp
[func
])(which
, button
->location
, w
, &winfo
);
if (needsWindow
[func
]) XUngrabMouse();
/* If there's not a saved popup image, create the buttons */
if (!popupSaved
) { /* Create the items */
XDestroySubwindows(menu
); /* Get rid of old items */
for (i
= 0; i
< itemcount
; i
++) {
item
[i
] = XCreateWindow (menu
, x
, y
, itemWidth
, itemHeight
, 1,
if (item
[i
] == NULL
) Error ("Couldn't open item in MapPopup");
InterpretLocatorXY(RootWindow
, &x
, &y
, loc
);
if (lastMenuOp
== -1) y
-= menuHeight
>> 1;
else y
-= lastMenuOp
* (itemHeight
+1) + (itemHeight
>> 1);
else if (x
+ menuWidth
> screen_width
) {
x
= screen_width
- menuWidth
;
else if (y
+ menuHeight
> screen_height
) {
y
= screen_height
- menuHeight
;
saveScreen
= XPixmapSave(RootWindow
, x
, y
, menuWidth
, menuHeight
);
if (saveScreen
== 0) Error("Couldn't save screen in MapPopup");
XPixmapPut(menu
, 0, 0, 0, 0, menuWidth
-2, menuHeight
-2,
menuImage
, GXcopy
, AllPlanes
);
for (i
= 0; i
< itemcount
; i
++) DisplayButton(i
);;
menuImage
= XPixmapSave(menu
, 0, 0, menuWidth
-2, menuHeight
-2);
if (menuImage
== 0) Error("Couldn't save menu in MapPopup");
QueryMouse(RootWindow
, &x
, &y
, &w
);
if (w
!= menu
) UnmapPopup();
if (freeze
&& saveScreen
!= 0) {
XPixmapPut(RootWindow
, 0, 0, savex
, savey
, menuWidth
, menuHeight
,
saveScreen
, GXcopy
, AllPlanes
);
} else XUnmapWindow(menu
);
/* Now set things up so we don't have to map everything next time */
XDestroySubwindows(menu
); /* Get rid of old items */
for (i
= 0; i
< itemcount
; i
++) {
item
[i
] = XCreateTransparency(menu
, x
, y
,
Error("Couldn't open item in UnmapPopup");
/* Undo the popup menu caching. We can't just test popupSaved, since
it gets set in UnmapPopup and we might be called in between */
if (popupSaved
) popupSaved
= FALSE
;
if (item
[i
] == 0) return;
XPixFill(item
[i
], -1, -1, 200, 200, 0, (Bitmap
) 0,
if (item
[i
] == 0) return;
XPixSet(item
[i
], -1, -1, 200, 200, bgColor
);
XText(item
[i
], 3, 3, label
[i
], strlen(label
[i
]), menufont
,
for (j
= 0; j
< 3; j
++) {
if (buttonFunc
[j
] == i
) {
XPixmapPut (item
[buttonFunc
[j
]], 0, 0,
itemWidth
- button_width
- 3, 4,
button_width
, button_height
, buttonPixmap
[j
],
buttonGXfunc
, AllPlanes
);
IconifyOrDeIconify(which
, loc
, w
, winfo
)
if (w
== RootWindow
) return;
/* If we're trying to iconify an icon deiconify instead */
if (winfo
->type
== IsIcon
) Deiconify(which
, loc
, w
, winfo
);
else Iconify(which
, loc
, w
, winfo
);
Assign(which
, loc
, w
, winfo
)
int choice
, cleared
= FALSE
;
/* First make sure the new click was in the menu; if not
/* Now get rid of the old function assigned this button. But, don't
deassign the popup window button! */
choice
= buttonFunc
[which
];
if (choice
== popup_button
) return;
if (popup
) UnsavePopup(); /* The saved popup menu is invalid */
buttonFunc
[which
] = unassigned_button
;
/* Now find out which subwindow we were in */
InterpretLocatorW(menu
, &w
, loc
);
for (i
= 0; item
[i
] != NULL
&& item
[i
] != w
; i
++) {}
/* Can't assign Assign */
if (menuOp
[i
] == NULL
|| menuOp
[i
] == Assign
) {
if (cleared
) XUngrabButton(mask
| Button(which
));
/* Now wait for the release; if it doesn't occur abort */
if (!MatchUp(newbutton
, which
)) {
if (cleared
) XUngrabButton(mask
| Button(which
));
InterpretLocatorW(menu
, &neww
, loc
);
if (cleared
) XUngrabButton(mask
| Button(which
));
/* Now assign that function to the button */
XPixmapPut(item
[i
], 0, 0,
itemWidth
- button_width
- 3, 4,
button_width
, button_height
, buttonPixmap
[which
],
buttonGXfunc
, AllPlanes
);
if (!cleared
) { /* New assignment */
status
= XGrabButton(RootWindow
, wmCursor
,
ButtonPressed
|ButtonReleased
);
if (status
== 0) Error ("Couldn't grab button in Assign");
/* Returns whether or not this is a real event */
XButtonEvent
*be
= (XButtonEvent
*) event
;
XLeaveWindowEvent
*lwe
= (XLeaveWindowEvent
*) event
;
XExposeEvent
*ee
= (XExposeEvent
*) event
;
XUnmapEvent
*ue
= (XUnmapEvent
*) event
;
XFocusChangeEvent
*fce
= (XFocusChangeEvent
*) event
;
/* If it's in the base window, no trouble */
if (event
->window
== RootWindow
) {
if (event
->type
== FocusChange
) {
if (fce
->detail
== EnterWindow
&& fce
->subwindow
== 0) {
} else if (event
->type
== UnmapWindow
) {
FrameFocus(); /* The background has changed */
be
->detail
&= 0xff; /* mask out state of shift keys */
/* Is it the menu window? */
if (event
->window
== menu
) {
if (event
->type
== ExposeWindow
) {
if (ee
->subwindow
!= 0) RefreshMenu(ee
->subwindow
);
if (event
->type
== LeaveWindow
) {
if (lwe
->subwindow
== 0 && !doingOp
) UnmapPopup();
/* Let's see if it's in an icon */
QueryWindow(event
->window
, &winfo
);
if (winfo
.type
!= IsIcon
) return FALSE
; /* Nope -- nothing */
if (event
->type
== UnmapWindow
) return FALSE
;
status
= XFetchName(winfo
.assoc_wind
, &iconName
);
if (status
== 0) Error ("Couldn't fetch name in GetButton");
if (event
->type
== ExposeWindow
) { /* Just refresh the icon */
if (iconName
!= NULL
&& iconName
[0] != '\0') {
XText(ee
->window
, 4, 4, iconName
, strlen(iconName
), iconfont
,
} else EditIconName((XKeyPressedEvent
*)be
, iconName
);
if (iconName
) free(iconName
);
while (!GetEvent(event
)) ;
for (i
= 0; i
< itemcount
&& item
[i
] != w
; i
++) {}
if (i
>= itemcount
) return;
fprintf(stderr
, "\nxmwm: %s", string
);